diff --git a/arch/arm/include/asm/arch-rockchip/gpio.h b/arch/arm/include/asm/arch-rockchip/gpio.h index 1aaec5faec..15f5de321b 100644 --- a/arch/arm/include/asm/arch-rockchip/gpio.h +++ b/arch/arm/include/asm/arch-rockchip/gpio.h @@ -6,6 +6,7 @@ #ifndef _ASM_ARCH_GPIO_H #define _ASM_ARCH_GPIO_H +#if !defined(CONFIG_ROCKCHIP_RK3568) struct rockchip_gpio_regs { u32 swport_dr; u32 swport_ddr; @@ -22,7 +23,44 @@ struct rockchip_gpio_regs { u32 reserved1[(0x60 - 0x54) / 4]; u32 ls_sync; }; + check_member(rockchip_gpio_regs, ls_sync, 0x60); +#else +struct rockchip_gpio_regs { + u32 swport_dr_l; /* ADDRESS OFFSET: 0x0000 */ + u32 swport_dr_h; /* ADDRESS OFFSET: 0x0004 */ + u32 swport_ddr_l; /* ADDRESS OFFSET: 0x0008 */ + u32 swport_ddr_h; /* ADDRESS OFFSET: 0x000c */ + u32 int_en_l; /* ADDRESS OFFSET: 0x0010 */ + u32 int_en_h; /* ADDRESS OFFSET: 0x0014 */ + u32 int_mask_l; /* ADDRESS OFFSET: 0x0018 */ + u32 int_mask_h; /* ADDRESS OFFSET: 0x001c */ + u32 int_type_l; /* ADDRESS OFFSET: 0x0020 */ + u32 int_type_h; /* ADDRESS OFFSET: 0x0024 */ + u32 int_polarity_l; /* ADDRESS OFFSET: 0x0028 */ + u32 int_polarity_h; /* ADDRESS OFFSET: 0x002c */ + u32 int_bothedge_l; /* ADDRESS OFFSET: 0x0030 */ + u32 int_bothedge_h; /* ADDRESS OFFSET: 0x0034 */ + u32 debounce_l; /* ADDRESS OFFSET: 0x0038 */ + u32 debounce_h; /* ADDRESS OFFSET: 0x003c */ + u32 dbclk_div_en_l; /* ADDRESS OFFSET: 0x0040 */ + u32 dbclk_div_en_h; /* ADDRESS OFFSET: 0x0044 */ + u32 dbclk_div_con; /* ADDRESS OFFSET: 0x0048 */ + u32 reserved004c; /* ADDRESS OFFSET: 0x004c */ + u32 int_status; /* ADDRESS OFFSET: 0x0050 */ + u32 reserved0054; /* ADDRESS OFFSET: 0x0054 */ + u32 int_rawstatus; /* ADDRESS OFFSET: 0x0058 */ + u32 reserved005c; /* ADDRESS OFFSET: 0x005c */ + u32 port_eoi_l; /* ADDRESS OFFSET: 0x0060 */ + u32 port_eoi_h; /* ADDRESS OFFSET: 0x0064 */ + u32 reserved0068[2]; /* ADDRESS OFFSET: 0x0068 */ + u32 ext_port; /* ADDRESS OFFSET: 0x0070 */ + u32 reserved0074; /* ADDRESS OFFSET: 0x0074 */ + u32 ver_id; /* ADDRESS OFFSET: 0x0078 */ +}; + +check_member(rockchip_gpio_regs, ver_id, 0x0078); +#endif enum gpio_pu_pd { GPIO_PULL_NORMAL = 0, diff --git a/drivers/gpio/rk_gpio.c b/drivers/gpio/rk_gpio.c index f7ad4d68b4..458482cd2e 100644 --- a/drivers/gpio/rk_gpio.c +++ b/drivers/gpio/rk_gpio.c @@ -2,12 +2,15 @@ /* * (C) Copyright 2015 Google, Inc * - * (C) Copyright 2008-2014 Rockchip Electronics + * (C) Copyright 2008-2023 Rockchip Electronics * Peter, Software Engineering, . + * Jianqun Xu, Software Engineering, . */ #include #include +#include +#include #include #include #include @@ -23,6 +26,35 @@ enum { #define OFFSET_TO_BIT(bit) (1UL << (bit)) +/* + * Newer Rockchip devices have additional registers that must be + * accounted for. + */ +#if defined(CONFIG_ROCKCHIP_RK3568) +#define GPIO_VER 2 +#define REG_L(R) (R##_l) +#define REG_H(R) (R##_h) +#define READ_REG(REG) ((readl(REG_L(REG)) & 0xFFFF) | \ + ((readl(REG_H(REG)) & 0xFFFF) << 16)) +#define WRITE_REG(REG, VAL) \ +{\ + writel(((VAL) & 0xFFFF) | 0xFFFF0000, REG_L(REG)); \ + writel((((VAL) & 0xFFFF0000) >> 16) | 0xFFFF0000, REG_H(REG));\ +} +#define CLRBITS_LE32(REG, MASK) WRITE_REG(REG, READ_REG(REG) & ~(MASK)) +#define SETBITS_LE32(REG, MASK) WRITE_REG(REG, READ_REG(REG) | (MASK)) +#define CLRSETBITS_LE32(REG, MASK, VAL) WRITE_REG(REG, \ + (READ_REG(REG) & ~(MASK)) | (VAL)) + +#else +#define GPIO_VER 1 +#define READ_REG(REG) readl(REG) +#define WRITE_REG(REG, VAL) writel(VAL, REG) +#define CLRBITS_LE32(REG, MASK) clrbits_le32(REG, MASK) +#define SETBITS_LE32(REG, MASK) setbits_le32(REG, MASK) +#define CLRSETBITS_LE32(REG, MASK, VAL) clrsetbits_le32(REG, MASK, VAL) +#endif + struct rockchip_gpio_priv { struct rockchip_gpio_regs *regs; struct udevice *pinctrl; @@ -35,7 +67,7 @@ static int rockchip_gpio_direction_input(struct udevice *dev, unsigned offset) struct rockchip_gpio_priv *priv = dev_get_priv(dev); struct rockchip_gpio_regs *regs = priv->regs; - clrbits_le32(®s->swport_ddr, OFFSET_TO_BIT(offset)); + CLRBITS_LE32(®s->swport_ddr, OFFSET_TO_BIT(offset)); return 0; } @@ -47,8 +79,8 @@ static int rockchip_gpio_direction_output(struct udevice *dev, unsigned offset, struct rockchip_gpio_regs *regs = priv->regs; int mask = OFFSET_TO_BIT(offset); - clrsetbits_le32(®s->swport_dr, mask, value ? mask : 0); - setbits_le32(®s->swport_ddr, mask); + CLRSETBITS_LE32(®s->swport_dr, mask, value ? mask : 0); + SETBITS_LE32(®s->swport_ddr, mask); return 0; } @@ -68,7 +100,7 @@ static int rockchip_gpio_set_value(struct udevice *dev, unsigned offset, struct rockchip_gpio_regs *regs = priv->regs; int mask = OFFSET_TO_BIT(offset); - clrsetbits_le32(®s->swport_dr, mask, value ? mask : 0); + CLRSETBITS_LE32(®s->swport_dr, mask, value ? mask : 0); return 0; } @@ -86,14 +118,14 @@ static int rockchip_gpio_get_function(struct udevice *dev, unsigned offset) ret = pinctrl_get_gpio_mux(priv->pinctrl, priv->bank, offset); if (ret) return ret; - is_output = readl(®s->swport_ddr) & OFFSET_TO_BIT(offset); + is_output = READ_REG(®s->swport_ddr) & OFFSET_TO_BIT(offset); return is_output ? GPIOF_OUTPUT : GPIOF_INPUT; #endif } /* Simple SPL interface to GPIOs */ -#ifdef CONFIG_SPL_BUILD +#if defined(CONFIG_SPL_BUILD) && (GPIO_VER == 1) enum { PULL_NONE_1V8 = 0, @@ -143,7 +175,7 @@ static int rockchip_gpio_probe(struct udevice *dev) struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev); struct rockchip_gpio_priv *priv = dev_get_priv(dev); struct ofnode_phandle_args args; - char *end; + char *end = NULL; int ret; priv->regs = dev_read_addr_ptr(dev);