gpio/rockchip: rk_gpio support v2 gpio controller

The v2 gpio controller add write enable bit for some register,
such as data register, data direction register and so on.

This patch support v2 gpio controller by redefine the read and
write operation functions.

Change-Id: I2adbcca06a37c48e6f494b89833cd034ba0dae29
Signed-off-by: Jianqun Xu <jay.xu@rock-chips.com>
This commit is contained in:
Jianqun Xu 2020-05-27 11:36:26 +08:00 committed by Jianhong Chen
parent 7d13e745d6
commit d1aef94b5a
3 changed files with 81 additions and 6 deletions

View File

@ -7,6 +7,7 @@
#ifndef _ASM_ARCH_GPIO_H
#define _ASM_ARCH_GPIO_H
#ifndef CONFIG_ROCKCHIP_GPIO_V2
struct rockchip_gpio_regs {
u32 swport_dr;
u32 swport_ddr;
@ -24,5 +25,40 @@ struct rockchip_gpio_regs {
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
#endif

View File

@ -144,6 +144,19 @@ config ROCKCHIP_GPIO
The GPIOs for a device are defined in the device tree with one node
for each bank.
config ROCKCHIP_GPIO_V2
bool "Rockchip GPIO driver version 2.0"
depends on ROCKCHIP_GPIO
default n
help
Support GPIO access on Rockchip SoCs. The GPIOs are arranged into
a number of banks (different for each SoC type) each with 32 GPIOs.
The GPIOs for a device are defined in the device tree with one node
for each bank.
Support version 2.0 GPIO controller, which support write enable bits
for some registers, such as dr, ddr.
config SANDBOX_GPIO
bool "Enable sandbox GPIO driver"
depends on SANDBOX && DM && DM_GPIO

View File

@ -1,8 +1,9 @@
/*
* (C) Copyright 2015 Google, Inc
*
* (C) Copyright 2008-2014 Rockchip Electronics
* (C) Copyright 2008-2020 Rockchip Electronics
* Peter, Software Engineering, <superpeter.cai@gmail.com>.
* Jianqun Xu, Software Engineering, <jay.xu@rock-chips.com>.
*
* SPDX-License-Identifier: GPL-2.0+
*/
@ -23,6 +24,30 @@ enum {
#define OFFSET_TO_BIT(bit) (1UL << (bit))
#ifdef CONFIG_ROCKCHIP_GPIO_V2
#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 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 +60,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(&regs->swport_ddr, OFFSET_TO_BIT(offset));
CLRBITS_LE32(&regs->swport_ddr, OFFSET_TO_BIT(offset));
return 0;
}
@ -47,8 +72,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(&regs->swport_dr, mask, value ? mask : 0);
setbits_le32(&regs->swport_ddr, mask);
CLRSETBITS_LE32(&regs->swport_dr, mask, value ? mask : 0);
SETBITS_LE32(&regs->swport_ddr, mask);
return 0;
}
@ -68,7 +93,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(&regs->swport_dr, mask, value ? mask : 0);
CLRSETBITS_LE32(&regs->swport_dr, mask, value ? mask : 0);
return 0;
}
@ -90,7 +115,8 @@ static int rockchip_gpio_get_function(struct udevice *dev, unsigned offset)
/* If it's not 0, then it is not a GPIO */
if (ret)
return GPIOF_FUNC;
is_output = readl(&regs->swport_ddr) & OFFSET_TO_BIT(offset);
is_output = READ_REG(&regs->swport_ddr) & OFFSET_TO_BIT(offset);
return is_output ? GPIOF_OUTPUT : GPIOF_INPUT;
#endif