diff mbox series

[V2,7/9] gpio/rockchip: rk_gpio support v2 gpio controller

Message ID 20230213222742.135093-8-macroalpha82@gmail.com
State Changes Requested
Delegated to: Kever Yang
Headers show
Series Rockchip: Improve Support for RK3566 Devices | expand

Commit Message

Chris Morgan Feb. 13, 2023, 10:27 p.m. UTC
From: Chris Morgan <macromorgan@hotmail.com>

Add support for the newer GPIO controller used by the rk356x series,
as well as the pinctrl device for the rk356x series. The GPIOv2
controller has a write enable bit for some registers which differs
from the older versions of the GPIO controller.

Signed-off-by: Peter Geis <pgwipeout@gmail.com>
Signed-off-by: Chris Morgan <macromorgan@hotmail.com>
---
 arch/arm/include/asm/arch-rockchip/gpio.h     |  38 ++
 drivers/gpio/rk_gpio.c                        |  49 +-
 drivers/pinctrl/rockchip/Makefile             |   1 +
 drivers/pinctrl/rockchip/pinctrl-rk3568.c     | 453 ++++++++++++++++++
 .../pinctrl/rockchip/pinctrl-rockchip-core.c  |  12 +-
 5 files changed, 540 insertions(+), 13 deletions(-)
 create mode 100644 drivers/pinctrl/rockchip/pinctrl-rk3568.c

Comments

FUKAUMI Naoki Feb. 16, 2023, 11:19 a.m. UTC | #1
hi,

On 2/14/23 07:27, Chris Morgan wrote:
> From: Chris Morgan <macromorgan@hotmail.com>
> 
> Add support for the newer GPIO controller used by the rk356x series,
> as well as the pinctrl device for the rk356x series. The GPIOv2
> controller has a write enable bit for some registers which differs
> from the older versions of the GPIO controller.
> 
> Signed-off-by: Peter Geis <pgwipeout@gmail.com>
> Signed-off-by: Chris Morgan <macromorgan@hotmail.com>
> ---
>   arch/arm/include/asm/arch-rockchip/gpio.h     |  38 ++
>   drivers/gpio/rk_gpio.c                        |  49 +-
>   drivers/pinctrl/rockchip/Makefile             |   1 +
>   drivers/pinctrl/rockchip/pinctrl-rk3568.c     | 453 ++++++++++++++++++
>   .../pinctrl/rockchip/pinctrl-rockchip-core.c  |  12 +-
>   5 files changed, 540 insertions(+), 13 deletions(-)
>   create mode 100644 drivers/pinctrl/rockchip/pinctrl-rk3568.c
> 
> 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 98a79b5f4d..e2653be058 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, <superpeter.cai@gmail.com>.
> + * Jianqun Xu, Software Engineering, <jay.xu@rock-chips.com>.
>    */
>   
>   #include <common.h>
>   #include <dm.h>
> +#include <dm/of_access.h>
> +#include <dm/device_compat.h>
>   #include <syscon.h>
>   #include <linux/errno.h>
>   #include <asm/gpio.h>
> @@ -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 +68,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 +80,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 +101,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;
>   }
> @@ -86,14 +119,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(&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
>   }
>   
>   /* Simple SPL interface to GPIOs */
> -#ifdef CONFIG_SPL_BUILD
> +#if defined(CONFIG_SPL_BUILD) && (GPIO_VER == 1)
>   
>   enum {
>   	PULL_NONE_1V8 = 0,
> @@ -143,7 +176,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);
> diff --git a/drivers/pinctrl/rockchip/Makefile b/drivers/pinctrl/rockchip/Makefile
> index 9884355473..90461ae881 100644
> --- a/drivers/pinctrl/rockchip/Makefile
> +++ b/drivers/pinctrl/rockchip/Makefile
> @@ -14,5 +14,6 @@ obj-$(CONFIG_ROCKCHIP_RK3308) += pinctrl-rk3308.o
>   obj-$(CONFIG_ROCKCHIP_RK3328) += pinctrl-rk3328.o
>   obj-$(CONFIG_ROCKCHIP_RK3368) += pinctrl-rk3368.o
>   obj-$(CONFIG_ROCKCHIP_RK3399) += pinctrl-rk3399.o
> +obj-$(CONFIG_ROCKCHIP_RK3568) += pinctrl-rk3568.o
>   obj-$(CONFIG_ROCKCHIP_RV1108) += pinctrl-rv1108.o
>   obj-$(CONFIG_ROCKCHIP_RV1126) += pinctrl-rv1126.o
> diff --git a/drivers/pinctrl/rockchip/pinctrl-rk3568.c b/drivers/pinctrl/rockchip/pinctrl-rk3568.c
> new file mode 100644
> index 0000000000..dce1c1e7ee
> --- /dev/null
> +++ b/drivers/pinctrl/rockchip/pinctrl-rk3568.c
> @@ -0,0 +1,453 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * (C) Copyright 2020 Rockchip Electronics Co., Ltd
> + */
> +
> +#include <common.h>
> +#include <dm.h>
> +#include <dm/pinctrl.h>
> +#include <regmap.h>
> +#include <syscon.h>

+#include <dt-bindings/pinctrl/rockchip.h>

--
FUKAUMI Naoki

> +
> +#include "pinctrl-rockchip.h"
> +
> +static struct rockchip_mux_route_data rk3568_mux_route_data[] = {
> +	/* CAN0 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO0, RK_PB3, RK_FUNC_2, 0x0300, RK_GENMASK_VAL(0, 0, 0)),
> +	/* CAN0 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO2, RK_PA1, RK_FUNC_4, 0x0300, RK_GENMASK_VAL(0, 0, 1)),
> +	/* CAN1 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO1, RK_PA1, RK_FUNC_3, 0x0300, RK_GENMASK_VAL(2, 2, 0)),
> +	/* CAN1 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO4, RK_PC3, RK_FUNC_3, 0x0300, RK_GENMASK_VAL(2, 2, 1)),
> +	/* CAN2 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO4, RK_PB5, RK_FUNC_3, 0x0300, RK_GENMASK_VAL(4, 4, 0)),
> +	/* CAN2 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO2, RK_PB2, RK_FUNC_4, 0x0300, RK_GENMASK_VAL(4, 4, 1)),
> +	/* EDPDP_HPDIN IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO4, RK_PC4, RK_FUNC_1, 0x0300, RK_GENMASK_VAL(6, 6, 0)),
> +	/* EDPDP_HPDIN IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO0, RK_PC2, RK_FUNC_2, 0x0300, RK_GENMASK_VAL(6, 6, 1)),
> +	/* GMAC1 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO3, RK_PB1, RK_FUNC_3, 0x0300, RK_GENMASK_VAL(8, 8, 0)),
> +	/* GMAC1 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO4, RK_PA7, RK_FUNC_3, 0x0300, RK_GENMASK_VAL(8, 8, 1)),
> +	/* HDMITX IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO4, RK_PD1, RK_FUNC_1, 0x0300, RK_GENMASK_VAL(10, 10, 0)),
> +	/* HDMITX IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO0, RK_PC7, RK_FUNC_1, 0x0300, RK_GENMASK_VAL(10, 10, 1)),
> +	/* I2C2 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO0, RK_PB6, RK_FUNC_1, 0x0300, RK_GENMASK_VAL(14, 14, 0)),
> +	/* I2C2 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO4, RK_PB4, RK_FUNC_1, 0x0300, RK_GENMASK_VAL(14, 14, 1)),
> +	/* I2C3 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO1, RK_PA0, RK_FUNC_1, 0x0304, RK_GENMASK_VAL(0, 0, 0)),
> +	/* I2C3 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO3, RK_PB6, RK_FUNC_4, 0x0304, RK_GENMASK_VAL(0, 0, 1)),
> +	/* I2C4 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO4, RK_PB2, RK_FUNC_1, 0x0304, RK_GENMASK_VAL(2, 2, 0)),
> +	/* I2C4 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO2, RK_PB1, RK_FUNC_2, 0x0304, RK_GENMASK_VAL(2, 2, 1)),
> +	/* I2C5 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO3, RK_PB4, RK_FUNC_4, 0x0304, RK_GENMASK_VAL(4, 4, 0)),
> +	/* I2C5 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO4, RK_PD0, RK_FUNC_2, 0x0304, RK_GENMASK_VAL(4, 4, 1)),
> +	/* PWM4 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0304, RK_GENMASK_VAL(6, 6, 0)),
> +	/* PWM4 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0304, RK_GENMASK_VAL(6, 6, 1)),
> +	/* PWM5 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0304, RK_GENMASK_VAL(8, 8, 0)),
> +	/* PWM5 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0304, RK_GENMASK_VAL(8, 8, 1)),
> +	/* PWM6 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0304, RK_GENMASK_VAL(10, 10, 0)),
> +	/* PWM6 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0304, RK_GENMASK_VAL(10, 10, 1)),
> +	/* PWM7 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0304, RK_GENMASK_VAL(12, 12, 0)),
> +	/* PWM7 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0304, RK_GENMASK_VAL(12, 12, 1)),
> +	/* PWM8 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0304, RK_GENMASK_VAL(14, 14, 0)),
> +	/* PWM8 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0304, RK_GENMASK_VAL(14, 14, 1)),
> +	/* PWM9 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(0, 0, 0)),
> +	/* PWM9 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(0, 0, 1)),
> +	/* PWM10 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(2, 2, 0)),
> +	/* PWM10 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(2, 2, 1)),
> +	/* PWM11 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(4, 4, 0)),
> +	/* PWM11 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(4, 4, 1)),
> +	/* PWM12 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(6, 6, 0)),
> +	/* PWM12 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(6, 6, 1)),
> +	/* PWM13 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(8, 8, 0)),
> +	/* PWM13 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(8, 8, 1)),
> +	/* PWM14 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(10, 10, 0)),
> +	/* PWM14 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(10, 10, 1)),
> +	/* PWM15 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(12, 12, 0)),
> +	/* PWM15 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(12, 12, 1)),
> +	/* SDMMC2 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_3, 0x0308, RK_GENMASK_VAL(14, 14, 0)),
> +	/* SDMMC2 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO3, RK_PA5, RK_FUNC_5, 0x0308, RK_GENMASK_VAL(14, 14, 1)),
> +	/* SPI0 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO0, RK_PB5, RK_FUNC_2, 0x030c, RK_GENMASK_VAL(0, 0, 0)),
> +	/* SPI0 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO2, RK_PD3, RK_FUNC_3, 0x030c, RK_GENMASK_VAL(0, 0, 1)),
> +	/* SPI1 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO2, RK_PB5, RK_FUNC_3, 0x030c, RK_GENMASK_VAL(2, 2, 0)),
> +	/* SPI1 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO3, RK_PC3, RK_FUNC_3, 0x030c, RK_GENMASK_VAL(2, 2, 1)),
> +	/* SPI2 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO2, RK_PC1, RK_FUNC_4, 0x030c, RK_GENMASK_VAL(4, 4, 0)),
> +	/* SPI2 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO3, RK_PA0, RK_FUNC_3, 0x030c, RK_GENMASK_VAL(4, 4, 1)),
> +	/* SPI3 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO4, RK_PB3, RK_FUNC_4, 0x030c, RK_GENMASK_VAL(6, 6, 0)),
> +	/* SPI3 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO4, RK_PC2, RK_FUNC_2, 0x030c, RK_GENMASK_VAL(6, 6, 1)),
> +	/* UART1 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO2, RK_PB4, RK_FUNC_2, 0x030c, RK_GENMASK_VAL(8, 8, 0)),
> +	/* UART1 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO0, RK_PD1, RK_FUNC_1, 0x030c, RK_GENMASK_VAL(8, 8, 1)),
> +	/* UART2 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO0, RK_PD1, RK_FUNC_1, 0x030c, RK_GENMASK_VAL(10, 10, 0)),
> +	/* UART2 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO1, RK_PD5, RK_FUNC_2, 0x030c, RK_GENMASK_VAL(10, 10, 1)),
> +	/* UART3 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO1, RK_PA1, RK_FUNC_2, 0x030c, RK_GENMASK_VAL(12, 12, 0)),
> +	/* UART3 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO3, RK_PB7, RK_FUNC_4, 0x030c, RK_GENMASK_VAL(12, 12, 1)),
> +	/* UART4 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO1, RK_PA6, RK_FUNC_2, 0x030c, RK_GENMASK_VAL(14, 14, 0)),
> +	/* UART4 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO3, RK_PB2, RK_FUNC_4, 0x030c, RK_GENMASK_VAL(14, 14, 1)),
> +	/* UART5 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO2, RK_PA2, RK_FUNC_3, 0x0310, RK_GENMASK_VAL(0, 0, 0)),
> +	/* UART5 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO3, RK_PC2, RK_FUNC_4, 0x0310, RK_GENMASK_VAL(0, 0, 1)),
> +	/* UART6 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO2, RK_PA4, RK_FUNC_3, 0x0310, RK_GENMASK_VAL(2, 2, 0)),
> +	/* UART6 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO1, RK_PD5, RK_FUNC_3, 0x0310, RK_GENMASK_VAL(2, 2, 1)),
> +	/* UART7 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO2, RK_PA6, RK_FUNC_3, 0x0310, RK_GENMASK_VAL(5, 4, 0)),
> +	/* UART7 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO3, RK_PC4, RK_FUNC_4, 0x0310, RK_GENMASK_VAL(5, 4, 1)),
> +	/* UART7 IO mux selection M2 */
> +	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0310, RK_GENMASK_VAL(5, 4, 2)),
> +	/* UART8 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO2, RK_PC5, RK_FUNC_3, 0x0310, RK_GENMASK_VAL(6, 6, 0)),
> +	/* UART8 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO2, RK_PD7, RK_FUNC_4, 0x0310, RK_GENMASK_VAL(6, 6, 1)),
> +	/* UART9 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO2, RK_PB0, RK_FUNC_3, 0x0310, RK_GENMASK_VAL(9, 8, 0)),
> +	/* UART9 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO4, RK_PC5, RK_FUNC_4, 0x0310, RK_GENMASK_VAL(9, 8, 1)),
> +	/* UART9 IO mux selection M2 */
> +	MR_TOPGRF(RK_GPIO4, RK_PA4, RK_FUNC_4, 0x0310, RK_GENMASK_VAL(9, 8, 2)),
> +	/* I2S1 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO1, RK_PA2, RK_FUNC_1, 0x0310, RK_GENMASK_VAL(11, 10, 0)),
> +	/* I2S1 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO3, RK_PC6, RK_FUNC_4, 0x0310, RK_GENMASK_VAL(11, 10, 1)),
> +	/* I2S1 IO mux selection M2 */
> +	MR_TOPGRF(RK_GPIO2, RK_PD0, RK_FUNC_5, 0x0310, RK_GENMASK_VAL(11, 10, 2)),
> +	/* I2S2 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO2, RK_PC1, RK_FUNC_1, 0x0310, RK_GENMASK_VAL(12, 12, 0)),
> +	/* I2S2 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO4, RK_PB6, RK_FUNC_5, 0x0310, RK_GENMASK_VAL(12, 12, 1)),
> +	/* I2S3 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO3, RK_PA2, RK_FUNC_4, 0x0310, RK_GENMASK_VAL(14, 14, 0)),
> +	/* I2S3 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO4, RK_PC2, RK_FUNC_5, 0x0310, RK_GENMASK_VAL(14, 14, 1)),
> +	/* PDM IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO1, RK_PA6, RK_FUNC_3, 0x0314, RK_GENMASK_VAL(0, 0, 0)),
> +	/* PDM IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO3, RK_PD6, RK_FUNC_5, 0x0314, RK_GENMASK_VAL(0, 0, 1)),
> +	/* PCIE20 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO0, RK_PA5, RK_FUNC_3, 0x0314, RK_GENMASK_VAL(3, 2, 0)),
> +	/* PCIE20 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO2, RK_PD0, RK_FUNC_4, 0x0314, RK_GENMASK_VAL(3, 2, 1)),
> +	/* PCIE20 IO mux selection M2 */
> +	MR_TOPGRF(RK_GPIO1, RK_PB0, RK_FUNC_4, 0x0314, RK_GENMASK_VAL(3, 2, 2)),
> +	/* PCIE30X1 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO0, RK_PA4, RK_FUNC_3, 0x0314, RK_GENMASK_VAL(5, 4, 0)),
> +	/* PCIE30X1 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO2, RK_PD2, RK_FUNC_4, 0x0314, RK_GENMASK_VAL(5, 4, 1)),
> +	/* PCIE30X1 IO mux selection M2 */
> +	MR_TOPGRF(RK_GPIO1, RK_PA5, RK_FUNC_4, 0x0314, RK_GENMASK_VAL(5, 4, 2)),
> +	/* PCIE30X2 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO0, RK_PA6, RK_FUNC_2, 0x0314, RK_GENMASK_VAL(7, 6, 0)),
> +	/* PCIE30X2 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO2, RK_PD4, RK_FUNC_4, 0x0314, RK_GENMASK_VAL(7, 6, 1)),
> +	/* PCIE30X2 IO mux selection M2 */
> +	MR_TOPGRF(RK_GPIO4, RK_PC2, RK_FUNC_4, 0x0314, RK_GENMASK_VAL(7, 6, 2)),
> +};
> +
> +static int rk3568_set_mux(struct rockchip_pin_bank *bank, int pin, int mux)
> +{
> +	struct rockchip_pinctrl_priv *priv = bank->priv;
> +	int iomux_num = (pin / 8);
> +	struct regmap *regmap;
> +	int reg, ret, mask;
> +	u8 bit;
> +	u32 data;
> +
> +	debug("setting mux of GPIO%d-%d to %d\n", bank->bank_num, pin, mux);
> +
> +	if (bank->iomux[iomux_num].type & IOMUX_SOURCE_PMU)
> +		regmap = priv->regmap_pmu;
> +	else
> +		regmap = priv->regmap_base;
> +
> +	reg = bank->iomux[iomux_num].offset;
> +	if ((pin % 8) >= 4)
> +		reg += 0x4;
> +	bit = (pin % 4) * 4;
> +	mask = 0xf;
> +
> +	data = (mask << (bit + 16));
> +	data |= (mux & mask) << bit;
> +	ret = regmap_write(regmap, reg, data);
> +
> +	return ret;
> +}
> +
> +#define RK3568_PULL_PMU_OFFSET		0x20
> +#define RK3568_PULL_GRF_OFFSET		0x80
> +#define RK3568_PULL_BITS_PER_PIN	2
> +#define RK3568_PULL_PINS_PER_REG	8
> +#define RK3568_PULL_BANK_STRIDE		0x10
> +
> +static void rk3568_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank,
> +					 int pin_num, struct regmap **regmap,
> +					 int *reg, u8 *bit)
> +{
> +	struct rockchip_pinctrl_priv *info = bank->priv;
> +
> +	if (bank->bank_num == 0) {
> +		*regmap = info->regmap_pmu;
> +		*reg = RK3568_PULL_PMU_OFFSET;
> +		*reg += bank->bank_num * RK3568_PULL_BANK_STRIDE;
> +	} else {
> +		*regmap = info->regmap_base;
> +		*reg = RK3568_PULL_GRF_OFFSET;
> +		*reg += (bank->bank_num - 1) * RK3568_PULL_BANK_STRIDE;
> +	}
> +
> +	*reg += ((pin_num / RK3568_PULL_PINS_PER_REG) * 4);
> +	*bit = (pin_num % RK3568_PULL_PINS_PER_REG);
> +	*bit *= RK3568_PULL_BITS_PER_PIN;
> +}
> +
> +#define RK3568_DRV_PMU_OFFSET		0x70
> +#define RK3568_DRV_GRF_OFFSET		0x200
> +#define RK3568_DRV_BITS_PER_PIN		8
> +#define RK3568_DRV_PINS_PER_REG		2
> +#define RK3568_DRV_BANK_STRIDE		0x40
> +
> +static void rk3568_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank,
> +					int pin_num, struct regmap **regmap,
> +					int *reg, u8 *bit)
> +{
> +	struct rockchip_pinctrl_priv *info = bank->priv;
> +
> +	/* The first 32 pins of the first bank are located in PMU */
> +	if (bank->bank_num == 0) {
> +		*regmap = info->regmap_pmu;
> +		*reg = RK3568_DRV_PMU_OFFSET;
> +	} else {
> +		*regmap = info->regmap_base;
> +		*reg = RK3568_DRV_GRF_OFFSET;
> +		*reg += (bank->bank_num - 1) * RK3568_DRV_BANK_STRIDE;
> +	}
> +
> +	*reg += ((pin_num / RK3568_DRV_PINS_PER_REG) * 4);
> +	*bit = (pin_num % RK3568_DRV_PINS_PER_REG);
> +	*bit *= RK3568_DRV_BITS_PER_PIN;
> +}
> +
> +#define RK3568_SCHMITT_BITS_PER_PIN		2
> +#define RK3568_SCHMITT_PINS_PER_REG		8
> +#define RK3568_SCHMITT_BANK_STRIDE		0x10
> +#define RK3568_SCHMITT_GRF_OFFSET		0xc0
> +#define RK3568_SCHMITT_PMUGRF_OFFSET		0x30
> +
> +static int rk3568_calc_schmitt_reg_and_bit(struct rockchip_pin_bank *bank,
> +					   int pin_num, struct regmap **regmap,
> +					   int *reg, u8 *bit)
> +{
> +	struct rockchip_pinctrl_priv *info = bank->priv;
> +
> +	if (bank->bank_num == 0) {
> +		*regmap = info->regmap_pmu;
> +		*reg = RK3568_SCHMITT_PMUGRF_OFFSET;
> +	} else {
> +		*regmap = info->regmap_base;
> +		*reg = RK3568_SCHMITT_GRF_OFFSET;
> +		*reg += (bank->bank_num - 1) * RK3568_SCHMITT_BANK_STRIDE;
> +	}
> +
> +	*reg += ((pin_num / RK3568_SCHMITT_PINS_PER_REG) * 4);
> +	*bit = pin_num % RK3568_SCHMITT_PINS_PER_REG;
> +	*bit *= RK3568_SCHMITT_BITS_PER_PIN;
> +
> +	return 0;
> +}
> +
> +static int rk3568_set_pull(struct rockchip_pin_bank *bank,
> +			   int pin_num, int pull)
> +{
> +	struct regmap *regmap;
> +	int reg, ret;
> +	u8 bit, type;
> +	u32 data;
> +
> +	if (pull == PIN_CONFIG_BIAS_PULL_PIN_DEFAULT)
> +		return -EOPNOTSUPP;
> +
> +	rk3568_calc_pull_reg_and_bit(bank, pin_num, &regmap, &reg, &bit);
> +	type = bank->pull_type[pin_num / 8];
> +	ret = rockchip_translate_pull_value(type, pull);
> +	if (ret < 0) {
> +		debug("unsupported pull setting %d\n", pull);
> +		return ret;
> +	}
> +
> +	/* enable the write to the equivalent lower bits */
> +	data = ((1 << ROCKCHIP_PULL_BITS_PER_PIN) - 1) << (bit + 16);
> +
> +	data |= (ret << bit);
> +	ret = regmap_write(regmap, reg, data);
> +
> +	return ret;
> +}
> +
> +static int rk3568_set_drive(struct rockchip_pin_bank *bank,
> +			    int pin_num, int strength)
> +{
> +	struct regmap *regmap;
> +	int reg;
> +	u32 data;
> +	u8 bit;
> +	int drv = (1 << (strength + 1)) - 1;
> +	int ret = 0;
> +
> +	rk3568_calc_drv_reg_and_bit(bank, pin_num, &regmap, &reg, &bit);
> +
> +	/* enable the write to the equivalent lower bits */
> +	data = ((1 << RK3568_DRV_BITS_PER_PIN) - 1) << (bit + 16);
> +	data |= (drv << bit);
> +
> +	ret = regmap_write(regmap, reg, data);
> +	if (ret)
> +		return ret;
> +
> +	if (bank->bank_num == 1 && pin_num == 21)
> +		reg = 0x0840;
> +	else if (bank->bank_num == 2 && pin_num == 2)
> +		reg = 0x0844;
> +	else if (bank->bank_num == 2 && pin_num == 8)
> +		reg = 0x0848;
> +	else if (bank->bank_num == 3 && pin_num == 0)
> +		reg = 0x084c;
> +	else if (bank->bank_num == 3 && pin_num == 6)
> +		reg = 0x0850;
> +	else if (bank->bank_num == 4 && pin_num == 0)
> +		reg = 0x0854;
> +	else
> +		return 0;
> +
> +	data = ((1 << RK3568_DRV_BITS_PER_PIN) - 1) << 16;
> +	data |= drv;
> +
> +	return regmap_write(regmap, reg, data);
> +}
> +
> +static int rk3568_set_schmitt(struct rockchip_pin_bank *bank,
> +			      int pin_num, int enable)
> +{
> +	struct regmap *regmap;
> +	int reg;
> +	u32 data;
> +	u8 bit;
> +
> +	rk3568_calc_schmitt_reg_and_bit(bank, pin_num, &regmap, &reg, &bit);
> +
> +	/* enable the write to the equivalent lower bits */
> +	data = ((1 << RK3568_SCHMITT_BITS_PER_PIN) - 1) << (bit + 16);
> +	data |= (enable << bit);
> +
> +	return regmap_write(regmap, reg, data);
> +}
> +
> +static struct rockchip_pin_bank rk3568_pin_banks[] = {
> +	PIN_BANK_IOMUX_FLAGS(0, 32, "gpio0", IOMUX_SOURCE_PMU | IOMUX_WIDTH_4BIT,
> +			     IOMUX_SOURCE_PMU | IOMUX_WIDTH_4BIT,
> +			     IOMUX_SOURCE_PMU | IOMUX_WIDTH_4BIT,
> +			     IOMUX_SOURCE_PMU | IOMUX_WIDTH_4BIT),
> +	PIN_BANK_IOMUX_FLAGS(1, 32, "gpio1", IOMUX_WIDTH_4BIT,
> +			     IOMUX_WIDTH_4BIT,
> +			     IOMUX_WIDTH_4BIT,
> +			     IOMUX_WIDTH_4BIT),
> +	PIN_BANK_IOMUX_FLAGS(2, 32, "gpio2", IOMUX_WIDTH_4BIT,
> +			     IOMUX_WIDTH_4BIT,
> +			     IOMUX_WIDTH_4BIT,
> +			     IOMUX_WIDTH_4BIT),
> +	PIN_BANK_IOMUX_FLAGS(3, 32, "gpio3", IOMUX_WIDTH_4BIT,
> +			     IOMUX_WIDTH_4BIT,
> +			     IOMUX_WIDTH_4BIT,
> +			     IOMUX_WIDTH_4BIT),
> +	PIN_BANK_IOMUX_FLAGS(4, 32, "gpio4", IOMUX_WIDTH_4BIT,
> +			     IOMUX_WIDTH_4BIT,
> +			     IOMUX_WIDTH_4BIT,
> +			     IOMUX_WIDTH_4BIT),
> +};
> +
> +static const struct rockchip_pin_ctrl rk3568_pin_ctrl = {
> +	.pin_banks		= rk3568_pin_banks,
> +	.nr_banks		= ARRAY_SIZE(rk3568_pin_banks),
> +	.nr_pins		= 160,
> +	.grf_mux_offset		= 0x0,
> +	.pmu_mux_offset		= 0x0,
> +	.iomux_routes		= rk3568_mux_route_data,
> +	.niomux_routes		= ARRAY_SIZE(rk3568_mux_route_data),
> +	.set_mux		= rk3568_set_mux,
> +	.set_pull		= rk3568_set_pull,
> +	.set_drive		= rk3568_set_drive,
> +	.set_schmitt		= rk3568_set_schmitt,
> +};
> +
> +static const struct udevice_id rk3568_pinctrl_ids[] = {
> +	{
> +		.compatible = "rockchip,rk3568-pinctrl",
> +		.data = (ulong)&rk3568_pin_ctrl
> +	},
> +	{ }
> +};
> +
> +U_BOOT_DRIVER(pinctrl_rk3568) = {
> +	.name		= "rockchip_rk3568_pinctrl",
> +	.id		= UCLASS_PINCTRL,
> +	.of_match	= rk3568_pinctrl_ids,
> +	.priv_auto = sizeof(struct rockchip_pinctrl_priv),
> +	.ops		= &rockchip_pinctrl_ops,
> +#if !IS_ENABLED(CONFIG_OF_PLATDATA)
> +	.bind		= dm_scan_fdt_dev,
> +#endif
> +	.probe		= rockchip_pinctrl_probe,
> +};
> diff --git a/drivers/pinctrl/rockchip/pinctrl-rockchip-core.c b/drivers/pinctrl/rockchip/pinctrl-rockchip-core.c
> index d9d61fdb72..1481c1e51c 100644
> --- a/drivers/pinctrl/rockchip/pinctrl-rockchip-core.c
> +++ b/drivers/pinctrl/rockchip/pinctrl-rockchip-core.c
> @@ -433,7 +433,7 @@ static int rockchip_pinctrl_set_state(struct udevice *dev,
>   	int prop_len, param;
>   	const u32 *data;
>   	ofnode node;
> -#ifdef CONFIG_OF_LIVE
> +#if CONFIG_IS_ENABLED(OF_LIVE)
>   	const struct device_node *np;
>   	struct property *pp;
>   #else
> @@ -473,7 +473,7 @@ static int rockchip_pinctrl_set_state(struct udevice *dev,
>   		node = ofnode_get_by_phandle(conf);
>   		if (!ofnode_valid(node))
>   			return -ENODEV;
> -#ifdef CONFIG_OF_LIVE
> +#if CONFIG_IS_ENABLED(OF_LIVE)
>   		np = ofnode_to_np(node);
>   		for (pp = np->properties; pp; pp = pp->next) {
>   			prop_name = pp->name;
> @@ -548,13 +548,15 @@ static struct rockchip_pin_ctrl *rockchip_pinctrl_get_soc_data(struct udevice *d
>   
>   			/* preset iomux offset value, set new start value */
>   			if (iom->offset >= 0) {
> -				if (iom->type & IOMUX_SOURCE_PMU)
> +				if ((iom->type & IOMUX_SOURCE_PMU) || \
> +				    (iom->type & IOMUX_L_SOURCE_PMU))
>   					pmu_offs = iom->offset;
>   				else
>   					grf_offs = iom->offset;
>   			} else { /* set current iomux offset */
> -				iom->offset = (iom->type & IOMUX_SOURCE_PMU) ?
> -							pmu_offs : grf_offs;
> +				iom->offset = ((iom->type & IOMUX_SOURCE_PMU) ||
> +						(iom->type & IOMUX_L_SOURCE_PMU)) ?
> +						pmu_offs : grf_offs;
>   			}
>   
>   			/* preset drv offset value, set new start value */
Kever Yang Feb. 22, 2023, 7:49 a.m. UTC | #2
On 2023/2/14 06:27, Chris Morgan wrote:
> From: Chris Morgan <macromorgan@hotmail.com>
>
> Add support for the newer GPIO controller used by the rk356x series,
> as well as the pinctrl device for the rk356x series. The GPIOv2
> controller has a write enable bit for some registers which differs
> from the older versions of the GPIO controller.
>
> Signed-off-by: Peter Geis <pgwipeout@gmail.com>
> Signed-off-by: Chris Morgan <macromorgan@hotmail.com>

With FUKAUMI Naoki's comment apply:

Reviewed-by: Kever Yang <kever.yang@rock-chips.com>

Thanks,
- Kever

> ---
>   arch/arm/include/asm/arch-rockchip/gpio.h     |  38 ++
>   drivers/gpio/rk_gpio.c                        |  49 +-
>   drivers/pinctrl/rockchip/Makefile             |   1 +
>   drivers/pinctrl/rockchip/pinctrl-rk3568.c     | 453 ++++++++++++++++++
>   .../pinctrl/rockchip/pinctrl-rockchip-core.c  |  12 +-
>   5 files changed, 540 insertions(+), 13 deletions(-)
>   create mode 100644 drivers/pinctrl/rockchip/pinctrl-rk3568.c
>
> 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 98a79b5f4d..e2653be058 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, <superpeter.cai@gmail.com>.
> + * Jianqun Xu, Software Engineering, <jay.xu@rock-chips.com>.
>    */
>   
>   #include <common.h>
>   #include <dm.h>
> +#include <dm/of_access.h>
> +#include <dm/device_compat.h>
>   #include <syscon.h>
>   #include <linux/errno.h>
>   #include <asm/gpio.h>
> @@ -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 +68,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 +80,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 +101,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;
>   }
> @@ -86,14 +119,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(&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
>   }
>   
>   /* Simple SPL interface to GPIOs */
> -#ifdef CONFIG_SPL_BUILD
> +#if defined(CONFIG_SPL_BUILD) && (GPIO_VER == 1)
>   
>   enum {
>   	PULL_NONE_1V8 = 0,
> @@ -143,7 +176,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);
> diff --git a/drivers/pinctrl/rockchip/Makefile b/drivers/pinctrl/rockchip/Makefile
> index 9884355473..90461ae881 100644
> --- a/drivers/pinctrl/rockchip/Makefile
> +++ b/drivers/pinctrl/rockchip/Makefile
> @@ -14,5 +14,6 @@ obj-$(CONFIG_ROCKCHIP_RK3308) += pinctrl-rk3308.o
>   obj-$(CONFIG_ROCKCHIP_RK3328) += pinctrl-rk3328.o
>   obj-$(CONFIG_ROCKCHIP_RK3368) += pinctrl-rk3368.o
>   obj-$(CONFIG_ROCKCHIP_RK3399) += pinctrl-rk3399.o
> +obj-$(CONFIG_ROCKCHIP_RK3568) += pinctrl-rk3568.o
>   obj-$(CONFIG_ROCKCHIP_RV1108) += pinctrl-rv1108.o
>   obj-$(CONFIG_ROCKCHIP_RV1126) += pinctrl-rv1126.o
> diff --git a/drivers/pinctrl/rockchip/pinctrl-rk3568.c b/drivers/pinctrl/rockchip/pinctrl-rk3568.c
> new file mode 100644
> index 0000000000..dce1c1e7ee
> --- /dev/null
> +++ b/drivers/pinctrl/rockchip/pinctrl-rk3568.c
> @@ -0,0 +1,453 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * (C) Copyright 2020 Rockchip Electronics Co., Ltd
> + */
> +
> +#include <common.h>
> +#include <dm.h>
> +#include <dm/pinctrl.h>
> +#include <regmap.h>
> +#include <syscon.h>
> +
> +#include "pinctrl-rockchip.h"
> +
> +static struct rockchip_mux_route_data rk3568_mux_route_data[] = {
> +	/* CAN0 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO0, RK_PB3, RK_FUNC_2, 0x0300, RK_GENMASK_VAL(0, 0, 0)),
> +	/* CAN0 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO2, RK_PA1, RK_FUNC_4, 0x0300, RK_GENMASK_VAL(0, 0, 1)),
> +	/* CAN1 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO1, RK_PA1, RK_FUNC_3, 0x0300, RK_GENMASK_VAL(2, 2, 0)),
> +	/* CAN1 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO4, RK_PC3, RK_FUNC_3, 0x0300, RK_GENMASK_VAL(2, 2, 1)),
> +	/* CAN2 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO4, RK_PB5, RK_FUNC_3, 0x0300, RK_GENMASK_VAL(4, 4, 0)),
> +	/* CAN2 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO2, RK_PB2, RK_FUNC_4, 0x0300, RK_GENMASK_VAL(4, 4, 1)),
> +	/* EDPDP_HPDIN IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO4, RK_PC4, RK_FUNC_1, 0x0300, RK_GENMASK_VAL(6, 6, 0)),
> +	/* EDPDP_HPDIN IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO0, RK_PC2, RK_FUNC_2, 0x0300, RK_GENMASK_VAL(6, 6, 1)),
> +	/* GMAC1 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO3, RK_PB1, RK_FUNC_3, 0x0300, RK_GENMASK_VAL(8, 8, 0)),
> +	/* GMAC1 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO4, RK_PA7, RK_FUNC_3, 0x0300, RK_GENMASK_VAL(8, 8, 1)),
> +	/* HDMITX IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO4, RK_PD1, RK_FUNC_1, 0x0300, RK_GENMASK_VAL(10, 10, 0)),
> +	/* HDMITX IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO0, RK_PC7, RK_FUNC_1, 0x0300, RK_GENMASK_VAL(10, 10, 1)),
> +	/* I2C2 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO0, RK_PB6, RK_FUNC_1, 0x0300, RK_GENMASK_VAL(14, 14, 0)),
> +	/* I2C2 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO4, RK_PB4, RK_FUNC_1, 0x0300, RK_GENMASK_VAL(14, 14, 1)),
> +	/* I2C3 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO1, RK_PA0, RK_FUNC_1, 0x0304, RK_GENMASK_VAL(0, 0, 0)),
> +	/* I2C3 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO3, RK_PB6, RK_FUNC_4, 0x0304, RK_GENMASK_VAL(0, 0, 1)),
> +	/* I2C4 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO4, RK_PB2, RK_FUNC_1, 0x0304, RK_GENMASK_VAL(2, 2, 0)),
> +	/* I2C4 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO2, RK_PB1, RK_FUNC_2, 0x0304, RK_GENMASK_VAL(2, 2, 1)),
> +	/* I2C5 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO3, RK_PB4, RK_FUNC_4, 0x0304, RK_GENMASK_VAL(4, 4, 0)),
> +	/* I2C5 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO4, RK_PD0, RK_FUNC_2, 0x0304, RK_GENMASK_VAL(4, 4, 1)),
> +	/* PWM4 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0304, RK_GENMASK_VAL(6, 6, 0)),
> +	/* PWM4 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0304, RK_GENMASK_VAL(6, 6, 1)),
> +	/* PWM5 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0304, RK_GENMASK_VAL(8, 8, 0)),
> +	/* PWM5 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0304, RK_GENMASK_VAL(8, 8, 1)),
> +	/* PWM6 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0304, RK_GENMASK_VAL(10, 10, 0)),
> +	/* PWM6 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0304, RK_GENMASK_VAL(10, 10, 1)),
> +	/* PWM7 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0304, RK_GENMASK_VAL(12, 12, 0)),
> +	/* PWM7 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0304, RK_GENMASK_VAL(12, 12, 1)),
> +	/* PWM8 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0304, RK_GENMASK_VAL(14, 14, 0)),
> +	/* PWM8 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0304, RK_GENMASK_VAL(14, 14, 1)),
> +	/* PWM9 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(0, 0, 0)),
> +	/* PWM9 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(0, 0, 1)),
> +	/* PWM10 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(2, 2, 0)),
> +	/* PWM10 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(2, 2, 1)),
> +	/* PWM11 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(4, 4, 0)),
> +	/* PWM11 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(4, 4, 1)),
> +	/* PWM12 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(6, 6, 0)),
> +	/* PWM12 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(6, 6, 1)),
> +	/* PWM13 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(8, 8, 0)),
> +	/* PWM13 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(8, 8, 1)),
> +	/* PWM14 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(10, 10, 0)),
> +	/* PWM14 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(10, 10, 1)),
> +	/* PWM15 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(12, 12, 0)),
> +	/* PWM15 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(12, 12, 1)),
> +	/* SDMMC2 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_3, 0x0308, RK_GENMASK_VAL(14, 14, 0)),
> +	/* SDMMC2 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO3, RK_PA5, RK_FUNC_5, 0x0308, RK_GENMASK_VAL(14, 14, 1)),
> +	/* SPI0 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO0, RK_PB5, RK_FUNC_2, 0x030c, RK_GENMASK_VAL(0, 0, 0)),
> +	/* SPI0 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO2, RK_PD3, RK_FUNC_3, 0x030c, RK_GENMASK_VAL(0, 0, 1)),
> +	/* SPI1 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO2, RK_PB5, RK_FUNC_3, 0x030c, RK_GENMASK_VAL(2, 2, 0)),
> +	/* SPI1 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO3, RK_PC3, RK_FUNC_3, 0x030c, RK_GENMASK_VAL(2, 2, 1)),
> +	/* SPI2 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO2, RK_PC1, RK_FUNC_4, 0x030c, RK_GENMASK_VAL(4, 4, 0)),
> +	/* SPI2 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO3, RK_PA0, RK_FUNC_3, 0x030c, RK_GENMASK_VAL(4, 4, 1)),
> +	/* SPI3 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO4, RK_PB3, RK_FUNC_4, 0x030c, RK_GENMASK_VAL(6, 6, 0)),
> +	/* SPI3 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO4, RK_PC2, RK_FUNC_2, 0x030c, RK_GENMASK_VAL(6, 6, 1)),
> +	/* UART1 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO2, RK_PB4, RK_FUNC_2, 0x030c, RK_GENMASK_VAL(8, 8, 0)),
> +	/* UART1 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO0, RK_PD1, RK_FUNC_1, 0x030c, RK_GENMASK_VAL(8, 8, 1)),
> +	/* UART2 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO0, RK_PD1, RK_FUNC_1, 0x030c, RK_GENMASK_VAL(10, 10, 0)),
> +	/* UART2 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO1, RK_PD5, RK_FUNC_2, 0x030c, RK_GENMASK_VAL(10, 10, 1)),
> +	/* UART3 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO1, RK_PA1, RK_FUNC_2, 0x030c, RK_GENMASK_VAL(12, 12, 0)),
> +	/* UART3 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO3, RK_PB7, RK_FUNC_4, 0x030c, RK_GENMASK_VAL(12, 12, 1)),
> +	/* UART4 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO1, RK_PA6, RK_FUNC_2, 0x030c, RK_GENMASK_VAL(14, 14, 0)),
> +	/* UART4 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO3, RK_PB2, RK_FUNC_4, 0x030c, RK_GENMASK_VAL(14, 14, 1)),
> +	/* UART5 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO2, RK_PA2, RK_FUNC_3, 0x0310, RK_GENMASK_VAL(0, 0, 0)),
> +	/* UART5 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO3, RK_PC2, RK_FUNC_4, 0x0310, RK_GENMASK_VAL(0, 0, 1)),
> +	/* UART6 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO2, RK_PA4, RK_FUNC_3, 0x0310, RK_GENMASK_VAL(2, 2, 0)),
> +	/* UART6 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO1, RK_PD5, RK_FUNC_3, 0x0310, RK_GENMASK_VAL(2, 2, 1)),
> +	/* UART7 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO2, RK_PA6, RK_FUNC_3, 0x0310, RK_GENMASK_VAL(5, 4, 0)),
> +	/* UART7 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO3, RK_PC4, RK_FUNC_4, 0x0310, RK_GENMASK_VAL(5, 4, 1)),
> +	/* UART7 IO mux selection M2 */
> +	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0310, RK_GENMASK_VAL(5, 4, 2)),
> +	/* UART8 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO2, RK_PC5, RK_FUNC_3, 0x0310, RK_GENMASK_VAL(6, 6, 0)),
> +	/* UART8 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO2, RK_PD7, RK_FUNC_4, 0x0310, RK_GENMASK_VAL(6, 6, 1)),
> +	/* UART9 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO2, RK_PB0, RK_FUNC_3, 0x0310, RK_GENMASK_VAL(9, 8, 0)),
> +	/* UART9 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO4, RK_PC5, RK_FUNC_4, 0x0310, RK_GENMASK_VAL(9, 8, 1)),
> +	/* UART9 IO mux selection M2 */
> +	MR_TOPGRF(RK_GPIO4, RK_PA4, RK_FUNC_4, 0x0310, RK_GENMASK_VAL(9, 8, 2)),
> +	/* I2S1 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO1, RK_PA2, RK_FUNC_1, 0x0310, RK_GENMASK_VAL(11, 10, 0)),
> +	/* I2S1 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO3, RK_PC6, RK_FUNC_4, 0x0310, RK_GENMASK_VAL(11, 10, 1)),
> +	/* I2S1 IO mux selection M2 */
> +	MR_TOPGRF(RK_GPIO2, RK_PD0, RK_FUNC_5, 0x0310, RK_GENMASK_VAL(11, 10, 2)),
> +	/* I2S2 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO2, RK_PC1, RK_FUNC_1, 0x0310, RK_GENMASK_VAL(12, 12, 0)),
> +	/* I2S2 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO4, RK_PB6, RK_FUNC_5, 0x0310, RK_GENMASK_VAL(12, 12, 1)),
> +	/* I2S3 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO3, RK_PA2, RK_FUNC_4, 0x0310, RK_GENMASK_VAL(14, 14, 0)),
> +	/* I2S3 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO4, RK_PC2, RK_FUNC_5, 0x0310, RK_GENMASK_VAL(14, 14, 1)),
> +	/* PDM IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO1, RK_PA6, RK_FUNC_3, 0x0314, RK_GENMASK_VAL(0, 0, 0)),
> +	/* PDM IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO3, RK_PD6, RK_FUNC_5, 0x0314, RK_GENMASK_VAL(0, 0, 1)),
> +	/* PCIE20 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO0, RK_PA5, RK_FUNC_3, 0x0314, RK_GENMASK_VAL(3, 2, 0)),
> +	/* PCIE20 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO2, RK_PD0, RK_FUNC_4, 0x0314, RK_GENMASK_VAL(3, 2, 1)),
> +	/* PCIE20 IO mux selection M2 */
> +	MR_TOPGRF(RK_GPIO1, RK_PB0, RK_FUNC_4, 0x0314, RK_GENMASK_VAL(3, 2, 2)),
> +	/* PCIE30X1 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO0, RK_PA4, RK_FUNC_3, 0x0314, RK_GENMASK_VAL(5, 4, 0)),
> +	/* PCIE30X1 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO2, RK_PD2, RK_FUNC_4, 0x0314, RK_GENMASK_VAL(5, 4, 1)),
> +	/* PCIE30X1 IO mux selection M2 */
> +	MR_TOPGRF(RK_GPIO1, RK_PA5, RK_FUNC_4, 0x0314, RK_GENMASK_VAL(5, 4, 2)),
> +	/* PCIE30X2 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO0, RK_PA6, RK_FUNC_2, 0x0314, RK_GENMASK_VAL(7, 6, 0)),
> +	/* PCIE30X2 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO2, RK_PD4, RK_FUNC_4, 0x0314, RK_GENMASK_VAL(7, 6, 1)),
> +	/* PCIE30X2 IO mux selection M2 */
> +	MR_TOPGRF(RK_GPIO4, RK_PC2, RK_FUNC_4, 0x0314, RK_GENMASK_VAL(7, 6, 2)),
> +};
> +
> +static int rk3568_set_mux(struct rockchip_pin_bank *bank, int pin, int mux)
> +{
> +	struct rockchip_pinctrl_priv *priv = bank->priv;
> +	int iomux_num = (pin / 8);
> +	struct regmap *regmap;
> +	int reg, ret, mask;
> +	u8 bit;
> +	u32 data;
> +
> +	debug("setting mux of GPIO%d-%d to %d\n", bank->bank_num, pin, mux);
> +
> +	if (bank->iomux[iomux_num].type & IOMUX_SOURCE_PMU)
> +		regmap = priv->regmap_pmu;
> +	else
> +		regmap = priv->regmap_base;
> +
> +	reg = bank->iomux[iomux_num].offset;
> +	if ((pin % 8) >= 4)
> +		reg += 0x4;
> +	bit = (pin % 4) * 4;
> +	mask = 0xf;
> +
> +	data = (mask << (bit + 16));
> +	data |= (mux & mask) << bit;
> +	ret = regmap_write(regmap, reg, data);
> +
> +	return ret;
> +}
> +
> +#define RK3568_PULL_PMU_OFFSET		0x20
> +#define RK3568_PULL_GRF_OFFSET		0x80
> +#define RK3568_PULL_BITS_PER_PIN	2
> +#define RK3568_PULL_PINS_PER_REG	8
> +#define RK3568_PULL_BANK_STRIDE		0x10
> +
> +static void rk3568_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank,
> +					 int pin_num, struct regmap **regmap,
> +					 int *reg, u8 *bit)
> +{
> +	struct rockchip_pinctrl_priv *info = bank->priv;
> +
> +	if (bank->bank_num == 0) {
> +		*regmap = info->regmap_pmu;
> +		*reg = RK3568_PULL_PMU_OFFSET;
> +		*reg += bank->bank_num * RK3568_PULL_BANK_STRIDE;
> +	} else {
> +		*regmap = info->regmap_base;
> +		*reg = RK3568_PULL_GRF_OFFSET;
> +		*reg += (bank->bank_num - 1) * RK3568_PULL_BANK_STRIDE;
> +	}
> +
> +	*reg += ((pin_num / RK3568_PULL_PINS_PER_REG) * 4);
> +	*bit = (pin_num % RK3568_PULL_PINS_PER_REG);
> +	*bit *= RK3568_PULL_BITS_PER_PIN;
> +}
> +
> +#define RK3568_DRV_PMU_OFFSET		0x70
> +#define RK3568_DRV_GRF_OFFSET		0x200
> +#define RK3568_DRV_BITS_PER_PIN		8
> +#define RK3568_DRV_PINS_PER_REG		2
> +#define RK3568_DRV_BANK_STRIDE		0x40
> +
> +static void rk3568_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank,
> +					int pin_num, struct regmap **regmap,
> +					int *reg, u8 *bit)
> +{
> +	struct rockchip_pinctrl_priv *info = bank->priv;
> +
> +	/* The first 32 pins of the first bank are located in PMU */
> +	if (bank->bank_num == 0) {
> +		*regmap = info->regmap_pmu;
> +		*reg = RK3568_DRV_PMU_OFFSET;
> +	} else {
> +		*regmap = info->regmap_base;
> +		*reg = RK3568_DRV_GRF_OFFSET;
> +		*reg += (bank->bank_num - 1) * RK3568_DRV_BANK_STRIDE;
> +	}
> +
> +	*reg += ((pin_num / RK3568_DRV_PINS_PER_REG) * 4);
> +	*bit = (pin_num % RK3568_DRV_PINS_PER_REG);
> +	*bit *= RK3568_DRV_BITS_PER_PIN;
> +}
> +
> +#define RK3568_SCHMITT_BITS_PER_PIN		2
> +#define RK3568_SCHMITT_PINS_PER_REG		8
> +#define RK3568_SCHMITT_BANK_STRIDE		0x10
> +#define RK3568_SCHMITT_GRF_OFFSET		0xc0
> +#define RK3568_SCHMITT_PMUGRF_OFFSET		0x30
> +
> +static int rk3568_calc_schmitt_reg_and_bit(struct rockchip_pin_bank *bank,
> +					   int pin_num, struct regmap **regmap,
> +					   int *reg, u8 *bit)
> +{
> +	struct rockchip_pinctrl_priv *info = bank->priv;
> +
> +	if (bank->bank_num == 0) {
> +		*regmap = info->regmap_pmu;
> +		*reg = RK3568_SCHMITT_PMUGRF_OFFSET;
> +	} else {
> +		*regmap = info->regmap_base;
> +		*reg = RK3568_SCHMITT_GRF_OFFSET;
> +		*reg += (bank->bank_num - 1) * RK3568_SCHMITT_BANK_STRIDE;
> +	}
> +
> +	*reg += ((pin_num / RK3568_SCHMITT_PINS_PER_REG) * 4);
> +	*bit = pin_num % RK3568_SCHMITT_PINS_PER_REG;
> +	*bit *= RK3568_SCHMITT_BITS_PER_PIN;
> +
> +	return 0;
> +}
> +
> +static int rk3568_set_pull(struct rockchip_pin_bank *bank,
> +			   int pin_num, int pull)
> +{
> +	struct regmap *regmap;
> +	int reg, ret;
> +	u8 bit, type;
> +	u32 data;
> +
> +	if (pull == PIN_CONFIG_BIAS_PULL_PIN_DEFAULT)
> +		return -EOPNOTSUPP;
> +
> +	rk3568_calc_pull_reg_and_bit(bank, pin_num, &regmap, &reg, &bit);
> +	type = bank->pull_type[pin_num / 8];
> +	ret = rockchip_translate_pull_value(type, pull);
> +	if (ret < 0) {
> +		debug("unsupported pull setting %d\n", pull);
> +		return ret;
> +	}
> +
> +	/* enable the write to the equivalent lower bits */
> +	data = ((1 << ROCKCHIP_PULL_BITS_PER_PIN) - 1) << (bit + 16);
> +
> +	data |= (ret << bit);
> +	ret = regmap_write(regmap, reg, data);
> +
> +	return ret;
> +}
> +
> +static int rk3568_set_drive(struct rockchip_pin_bank *bank,
> +			    int pin_num, int strength)
> +{
> +	struct regmap *regmap;
> +	int reg;
> +	u32 data;
> +	u8 bit;
> +	int drv = (1 << (strength + 1)) - 1;
> +	int ret = 0;
> +
> +	rk3568_calc_drv_reg_and_bit(bank, pin_num, &regmap, &reg, &bit);
> +
> +	/* enable the write to the equivalent lower bits */
> +	data = ((1 << RK3568_DRV_BITS_PER_PIN) - 1) << (bit + 16);
> +	data |= (drv << bit);
> +
> +	ret = regmap_write(regmap, reg, data);
> +	if (ret)
> +		return ret;
> +
> +	if (bank->bank_num == 1 && pin_num == 21)
> +		reg = 0x0840;
> +	else if (bank->bank_num == 2 && pin_num == 2)
> +		reg = 0x0844;
> +	else if (bank->bank_num == 2 && pin_num == 8)
> +		reg = 0x0848;
> +	else if (bank->bank_num == 3 && pin_num == 0)
> +		reg = 0x084c;
> +	else if (bank->bank_num == 3 && pin_num == 6)
> +		reg = 0x0850;
> +	else if (bank->bank_num == 4 && pin_num == 0)
> +		reg = 0x0854;
> +	else
> +		return 0;
> +
> +	data = ((1 << RK3568_DRV_BITS_PER_PIN) - 1) << 16;
> +	data |= drv;
> +
> +	return regmap_write(regmap, reg, data);
> +}
> +
> +static int rk3568_set_schmitt(struct rockchip_pin_bank *bank,
> +			      int pin_num, int enable)
> +{
> +	struct regmap *regmap;
> +	int reg;
> +	u32 data;
> +	u8 bit;
> +
> +	rk3568_calc_schmitt_reg_and_bit(bank, pin_num, &regmap, &reg, &bit);
> +
> +	/* enable the write to the equivalent lower bits */
> +	data = ((1 << RK3568_SCHMITT_BITS_PER_PIN) - 1) << (bit + 16);
> +	data |= (enable << bit);
> +
> +	return regmap_write(regmap, reg, data);
> +}
> +
> +static struct rockchip_pin_bank rk3568_pin_banks[] = {
> +	PIN_BANK_IOMUX_FLAGS(0, 32, "gpio0", IOMUX_SOURCE_PMU | IOMUX_WIDTH_4BIT,
> +			     IOMUX_SOURCE_PMU | IOMUX_WIDTH_4BIT,
> +			     IOMUX_SOURCE_PMU | IOMUX_WIDTH_4BIT,
> +			     IOMUX_SOURCE_PMU | IOMUX_WIDTH_4BIT),
> +	PIN_BANK_IOMUX_FLAGS(1, 32, "gpio1", IOMUX_WIDTH_4BIT,
> +			     IOMUX_WIDTH_4BIT,
> +			     IOMUX_WIDTH_4BIT,
> +			     IOMUX_WIDTH_4BIT),
> +	PIN_BANK_IOMUX_FLAGS(2, 32, "gpio2", IOMUX_WIDTH_4BIT,
> +			     IOMUX_WIDTH_4BIT,
> +			     IOMUX_WIDTH_4BIT,
> +			     IOMUX_WIDTH_4BIT),
> +	PIN_BANK_IOMUX_FLAGS(3, 32, "gpio3", IOMUX_WIDTH_4BIT,
> +			     IOMUX_WIDTH_4BIT,
> +			     IOMUX_WIDTH_4BIT,
> +			     IOMUX_WIDTH_4BIT),
> +	PIN_BANK_IOMUX_FLAGS(4, 32, "gpio4", IOMUX_WIDTH_4BIT,
> +			     IOMUX_WIDTH_4BIT,
> +			     IOMUX_WIDTH_4BIT,
> +			     IOMUX_WIDTH_4BIT),
> +};
> +
> +static const struct rockchip_pin_ctrl rk3568_pin_ctrl = {
> +	.pin_banks		= rk3568_pin_banks,
> +	.nr_banks		= ARRAY_SIZE(rk3568_pin_banks),
> +	.nr_pins		= 160,
> +	.grf_mux_offset		= 0x0,
> +	.pmu_mux_offset		= 0x0,
> +	.iomux_routes		= rk3568_mux_route_data,
> +	.niomux_routes		= ARRAY_SIZE(rk3568_mux_route_data),
> +	.set_mux		= rk3568_set_mux,
> +	.set_pull		= rk3568_set_pull,
> +	.set_drive		= rk3568_set_drive,
> +	.set_schmitt		= rk3568_set_schmitt,
> +};
> +
> +static const struct udevice_id rk3568_pinctrl_ids[] = {
> +	{
> +		.compatible = "rockchip,rk3568-pinctrl",
> +		.data = (ulong)&rk3568_pin_ctrl
> +	},
> +	{ }
> +};
> +
> +U_BOOT_DRIVER(pinctrl_rk3568) = {
> +	.name		= "rockchip_rk3568_pinctrl",
> +	.id		= UCLASS_PINCTRL,
> +	.of_match	= rk3568_pinctrl_ids,
> +	.priv_auto = sizeof(struct rockchip_pinctrl_priv),
> +	.ops		= &rockchip_pinctrl_ops,
> +#if !IS_ENABLED(CONFIG_OF_PLATDATA)
> +	.bind		= dm_scan_fdt_dev,
> +#endif
> +	.probe		= rockchip_pinctrl_probe,
> +};
> diff --git a/drivers/pinctrl/rockchip/pinctrl-rockchip-core.c b/drivers/pinctrl/rockchip/pinctrl-rockchip-core.c
> index d9d61fdb72..1481c1e51c 100644
> --- a/drivers/pinctrl/rockchip/pinctrl-rockchip-core.c
> +++ b/drivers/pinctrl/rockchip/pinctrl-rockchip-core.c
> @@ -433,7 +433,7 @@ static int rockchip_pinctrl_set_state(struct udevice *dev,
>   	int prop_len, param;
>   	const u32 *data;
>   	ofnode node;
> -#ifdef CONFIG_OF_LIVE
> +#if CONFIG_IS_ENABLED(OF_LIVE)
>   	const struct device_node *np;
>   	struct property *pp;
>   #else
> @@ -473,7 +473,7 @@ static int rockchip_pinctrl_set_state(struct udevice *dev,
>   		node = ofnode_get_by_phandle(conf);
>   		if (!ofnode_valid(node))
>   			return -ENODEV;
> -#ifdef CONFIG_OF_LIVE
> +#if CONFIG_IS_ENABLED(OF_LIVE)
>   		np = ofnode_to_np(node);
>   		for (pp = np->properties; pp; pp = pp->next) {
>   			prop_name = pp->name;
> @@ -548,13 +548,15 @@ static struct rockchip_pin_ctrl *rockchip_pinctrl_get_soc_data(struct udevice *d
>   
>   			/* preset iomux offset value, set new start value */
>   			if (iom->offset >= 0) {
> -				if (iom->type & IOMUX_SOURCE_PMU)
> +				if ((iom->type & IOMUX_SOURCE_PMU) || \
> +				    (iom->type & IOMUX_L_SOURCE_PMU))
>   					pmu_offs = iom->offset;
>   				else
>   					grf_offs = iom->offset;
>   			} else { /* set current iomux offset */
> -				iom->offset = (iom->type & IOMUX_SOURCE_PMU) ?
> -							pmu_offs : grf_offs;
> +				iom->offset = ((iom->type & IOMUX_SOURCE_PMU) ||
> +						(iom->type & IOMUX_L_SOURCE_PMU)) ?
> +						pmu_offs : grf_offs;
>   			}
>   
>   			/* preset drv offset value, set new start value */
Kever Yang Feb. 22, 2023, 8:28 a.m. UTC | #3
Hi Chris,

     For this patch, I have pick below patch instead:

https://patchwork.ozlabs.org/project/uboot/patch/20230217115845.75303-11-jagan@amarulasolutions.com/

     For those change other than pinctrl-rk3568.c, please send a new 
patch is still available.


Thanks,

- Kever

On 2023/2/14 06:27, Chris Morgan wrote:
> From: Chris Morgan <macromorgan@hotmail.com>
>
> Add support for the newer GPIO controller used by the rk356x series,
> as well as the pinctrl device for the rk356x series. The GPIOv2
> controller has a write enable bit for some registers which differs
> from the older versions of the GPIO controller.
>
> Signed-off-by: Peter Geis <pgwipeout@gmail.com>
> Signed-off-by: Chris Morgan <macromorgan@hotmail.com>
> ---
>   arch/arm/include/asm/arch-rockchip/gpio.h     |  38 ++
>   drivers/gpio/rk_gpio.c                        |  49 +-
>   drivers/pinctrl/rockchip/Makefile             |   1 +
>   drivers/pinctrl/rockchip/pinctrl-rk3568.c     | 453 ++++++++++++++++++
>   .../pinctrl/rockchip/pinctrl-rockchip-core.c  |  12 +-
>   5 files changed, 540 insertions(+), 13 deletions(-)
>   create mode 100644 drivers/pinctrl/rockchip/pinctrl-rk3568.c
>
> 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 98a79b5f4d..e2653be058 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, <superpeter.cai@gmail.com>.
> + * Jianqun Xu, Software Engineering, <jay.xu@rock-chips.com>.
>    */
>   
>   #include <common.h>
>   #include <dm.h>
> +#include <dm/of_access.h>
> +#include <dm/device_compat.h>
>   #include <syscon.h>
>   #include <linux/errno.h>
>   #include <asm/gpio.h>
> @@ -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 +68,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 +80,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 +101,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;
>   }
> @@ -86,14 +119,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(&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
>   }
>   
>   /* Simple SPL interface to GPIOs */
> -#ifdef CONFIG_SPL_BUILD
> +#if defined(CONFIG_SPL_BUILD) && (GPIO_VER == 1)
>   
>   enum {
>   	PULL_NONE_1V8 = 0,
> @@ -143,7 +176,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);
> diff --git a/drivers/pinctrl/rockchip/Makefile b/drivers/pinctrl/rockchip/Makefile
> index 9884355473..90461ae881 100644
> --- a/drivers/pinctrl/rockchip/Makefile
> +++ b/drivers/pinctrl/rockchip/Makefile
> @@ -14,5 +14,6 @@ obj-$(CONFIG_ROCKCHIP_RK3308) += pinctrl-rk3308.o
>   obj-$(CONFIG_ROCKCHIP_RK3328) += pinctrl-rk3328.o
>   obj-$(CONFIG_ROCKCHIP_RK3368) += pinctrl-rk3368.o
>   obj-$(CONFIG_ROCKCHIP_RK3399) += pinctrl-rk3399.o
> +obj-$(CONFIG_ROCKCHIP_RK3568) += pinctrl-rk3568.o
>   obj-$(CONFIG_ROCKCHIP_RV1108) += pinctrl-rv1108.o
>   obj-$(CONFIG_ROCKCHIP_RV1126) += pinctrl-rv1126.o
> diff --git a/drivers/pinctrl/rockchip/pinctrl-rk3568.c b/drivers/pinctrl/rockchip/pinctrl-rk3568.c
> new file mode 100644
> index 0000000000..dce1c1e7ee
> --- /dev/null
> +++ b/drivers/pinctrl/rockchip/pinctrl-rk3568.c
> @@ -0,0 +1,453 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * (C) Copyright 2020 Rockchip Electronics Co., Ltd
> + */
> +
> +#include <common.h>
> +#include <dm.h>
> +#include <dm/pinctrl.h>
> +#include <regmap.h>
> +#include <syscon.h>
> +
> +#include "pinctrl-rockchip.h"
> +
> +static struct rockchip_mux_route_data rk3568_mux_route_data[] = {
> +	/* CAN0 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO0, RK_PB3, RK_FUNC_2, 0x0300, RK_GENMASK_VAL(0, 0, 0)),
> +	/* CAN0 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO2, RK_PA1, RK_FUNC_4, 0x0300, RK_GENMASK_VAL(0, 0, 1)),
> +	/* CAN1 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO1, RK_PA1, RK_FUNC_3, 0x0300, RK_GENMASK_VAL(2, 2, 0)),
> +	/* CAN1 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO4, RK_PC3, RK_FUNC_3, 0x0300, RK_GENMASK_VAL(2, 2, 1)),
> +	/* CAN2 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO4, RK_PB5, RK_FUNC_3, 0x0300, RK_GENMASK_VAL(4, 4, 0)),
> +	/* CAN2 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO2, RK_PB2, RK_FUNC_4, 0x0300, RK_GENMASK_VAL(4, 4, 1)),
> +	/* EDPDP_HPDIN IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO4, RK_PC4, RK_FUNC_1, 0x0300, RK_GENMASK_VAL(6, 6, 0)),
> +	/* EDPDP_HPDIN IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO0, RK_PC2, RK_FUNC_2, 0x0300, RK_GENMASK_VAL(6, 6, 1)),
> +	/* GMAC1 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO3, RK_PB1, RK_FUNC_3, 0x0300, RK_GENMASK_VAL(8, 8, 0)),
> +	/* GMAC1 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO4, RK_PA7, RK_FUNC_3, 0x0300, RK_GENMASK_VAL(8, 8, 1)),
> +	/* HDMITX IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO4, RK_PD1, RK_FUNC_1, 0x0300, RK_GENMASK_VAL(10, 10, 0)),
> +	/* HDMITX IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO0, RK_PC7, RK_FUNC_1, 0x0300, RK_GENMASK_VAL(10, 10, 1)),
> +	/* I2C2 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO0, RK_PB6, RK_FUNC_1, 0x0300, RK_GENMASK_VAL(14, 14, 0)),
> +	/* I2C2 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO4, RK_PB4, RK_FUNC_1, 0x0300, RK_GENMASK_VAL(14, 14, 1)),
> +	/* I2C3 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO1, RK_PA0, RK_FUNC_1, 0x0304, RK_GENMASK_VAL(0, 0, 0)),
> +	/* I2C3 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO3, RK_PB6, RK_FUNC_4, 0x0304, RK_GENMASK_VAL(0, 0, 1)),
> +	/* I2C4 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO4, RK_PB2, RK_FUNC_1, 0x0304, RK_GENMASK_VAL(2, 2, 0)),
> +	/* I2C4 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO2, RK_PB1, RK_FUNC_2, 0x0304, RK_GENMASK_VAL(2, 2, 1)),
> +	/* I2C5 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO3, RK_PB4, RK_FUNC_4, 0x0304, RK_GENMASK_VAL(4, 4, 0)),
> +	/* I2C5 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO4, RK_PD0, RK_FUNC_2, 0x0304, RK_GENMASK_VAL(4, 4, 1)),
> +	/* PWM4 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0304, RK_GENMASK_VAL(6, 6, 0)),
> +	/* PWM4 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0304, RK_GENMASK_VAL(6, 6, 1)),
> +	/* PWM5 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0304, RK_GENMASK_VAL(8, 8, 0)),
> +	/* PWM5 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0304, RK_GENMASK_VAL(8, 8, 1)),
> +	/* PWM6 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0304, RK_GENMASK_VAL(10, 10, 0)),
> +	/* PWM6 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0304, RK_GENMASK_VAL(10, 10, 1)),
> +	/* PWM7 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0304, RK_GENMASK_VAL(12, 12, 0)),
> +	/* PWM7 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0304, RK_GENMASK_VAL(12, 12, 1)),
> +	/* PWM8 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0304, RK_GENMASK_VAL(14, 14, 0)),
> +	/* PWM8 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0304, RK_GENMASK_VAL(14, 14, 1)),
> +	/* PWM9 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(0, 0, 0)),
> +	/* PWM9 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(0, 0, 1)),
> +	/* PWM10 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(2, 2, 0)),
> +	/* PWM10 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(2, 2, 1)),
> +	/* PWM11 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(4, 4, 0)),
> +	/* PWM11 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(4, 4, 1)),
> +	/* PWM12 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(6, 6, 0)),
> +	/* PWM12 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(6, 6, 1)),
> +	/* PWM13 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(8, 8, 0)),
> +	/* PWM13 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(8, 8, 1)),
> +	/* PWM14 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(10, 10, 0)),
> +	/* PWM14 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(10, 10, 1)),
> +	/* PWM15 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(12, 12, 0)),
> +	/* PWM15 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(12, 12, 1)),
> +	/* SDMMC2 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_3, 0x0308, RK_GENMASK_VAL(14, 14, 0)),
> +	/* SDMMC2 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO3, RK_PA5, RK_FUNC_5, 0x0308, RK_GENMASK_VAL(14, 14, 1)),
> +	/* SPI0 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO0, RK_PB5, RK_FUNC_2, 0x030c, RK_GENMASK_VAL(0, 0, 0)),
> +	/* SPI0 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO2, RK_PD3, RK_FUNC_3, 0x030c, RK_GENMASK_VAL(0, 0, 1)),
> +	/* SPI1 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO2, RK_PB5, RK_FUNC_3, 0x030c, RK_GENMASK_VAL(2, 2, 0)),
> +	/* SPI1 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO3, RK_PC3, RK_FUNC_3, 0x030c, RK_GENMASK_VAL(2, 2, 1)),
> +	/* SPI2 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO2, RK_PC1, RK_FUNC_4, 0x030c, RK_GENMASK_VAL(4, 4, 0)),
> +	/* SPI2 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO3, RK_PA0, RK_FUNC_3, 0x030c, RK_GENMASK_VAL(4, 4, 1)),
> +	/* SPI3 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO4, RK_PB3, RK_FUNC_4, 0x030c, RK_GENMASK_VAL(6, 6, 0)),
> +	/* SPI3 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO4, RK_PC2, RK_FUNC_2, 0x030c, RK_GENMASK_VAL(6, 6, 1)),
> +	/* UART1 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO2, RK_PB4, RK_FUNC_2, 0x030c, RK_GENMASK_VAL(8, 8, 0)),
> +	/* UART1 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO0, RK_PD1, RK_FUNC_1, 0x030c, RK_GENMASK_VAL(8, 8, 1)),
> +	/* UART2 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO0, RK_PD1, RK_FUNC_1, 0x030c, RK_GENMASK_VAL(10, 10, 0)),
> +	/* UART2 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO1, RK_PD5, RK_FUNC_2, 0x030c, RK_GENMASK_VAL(10, 10, 1)),
> +	/* UART3 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO1, RK_PA1, RK_FUNC_2, 0x030c, RK_GENMASK_VAL(12, 12, 0)),
> +	/* UART3 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO3, RK_PB7, RK_FUNC_4, 0x030c, RK_GENMASK_VAL(12, 12, 1)),
> +	/* UART4 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO1, RK_PA6, RK_FUNC_2, 0x030c, RK_GENMASK_VAL(14, 14, 0)),
> +	/* UART4 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO3, RK_PB2, RK_FUNC_4, 0x030c, RK_GENMASK_VAL(14, 14, 1)),
> +	/* UART5 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO2, RK_PA2, RK_FUNC_3, 0x0310, RK_GENMASK_VAL(0, 0, 0)),
> +	/* UART5 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO3, RK_PC2, RK_FUNC_4, 0x0310, RK_GENMASK_VAL(0, 0, 1)),
> +	/* UART6 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO2, RK_PA4, RK_FUNC_3, 0x0310, RK_GENMASK_VAL(2, 2, 0)),
> +	/* UART6 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO1, RK_PD5, RK_FUNC_3, 0x0310, RK_GENMASK_VAL(2, 2, 1)),
> +	/* UART7 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO2, RK_PA6, RK_FUNC_3, 0x0310, RK_GENMASK_VAL(5, 4, 0)),
> +	/* UART7 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO3, RK_PC4, RK_FUNC_4, 0x0310, RK_GENMASK_VAL(5, 4, 1)),
> +	/* UART7 IO mux selection M2 */
> +	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0310, RK_GENMASK_VAL(5, 4, 2)),
> +	/* UART8 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO2, RK_PC5, RK_FUNC_3, 0x0310, RK_GENMASK_VAL(6, 6, 0)),
> +	/* UART8 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO2, RK_PD7, RK_FUNC_4, 0x0310, RK_GENMASK_VAL(6, 6, 1)),
> +	/* UART9 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO2, RK_PB0, RK_FUNC_3, 0x0310, RK_GENMASK_VAL(9, 8, 0)),
> +	/* UART9 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO4, RK_PC5, RK_FUNC_4, 0x0310, RK_GENMASK_VAL(9, 8, 1)),
> +	/* UART9 IO mux selection M2 */
> +	MR_TOPGRF(RK_GPIO4, RK_PA4, RK_FUNC_4, 0x0310, RK_GENMASK_VAL(9, 8, 2)),
> +	/* I2S1 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO1, RK_PA2, RK_FUNC_1, 0x0310, RK_GENMASK_VAL(11, 10, 0)),
> +	/* I2S1 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO3, RK_PC6, RK_FUNC_4, 0x0310, RK_GENMASK_VAL(11, 10, 1)),
> +	/* I2S1 IO mux selection M2 */
> +	MR_TOPGRF(RK_GPIO2, RK_PD0, RK_FUNC_5, 0x0310, RK_GENMASK_VAL(11, 10, 2)),
> +	/* I2S2 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO2, RK_PC1, RK_FUNC_1, 0x0310, RK_GENMASK_VAL(12, 12, 0)),
> +	/* I2S2 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO4, RK_PB6, RK_FUNC_5, 0x0310, RK_GENMASK_VAL(12, 12, 1)),
> +	/* I2S3 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO3, RK_PA2, RK_FUNC_4, 0x0310, RK_GENMASK_VAL(14, 14, 0)),
> +	/* I2S3 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO4, RK_PC2, RK_FUNC_5, 0x0310, RK_GENMASK_VAL(14, 14, 1)),
> +	/* PDM IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO1, RK_PA6, RK_FUNC_3, 0x0314, RK_GENMASK_VAL(0, 0, 0)),
> +	/* PDM IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO3, RK_PD6, RK_FUNC_5, 0x0314, RK_GENMASK_VAL(0, 0, 1)),
> +	/* PCIE20 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO0, RK_PA5, RK_FUNC_3, 0x0314, RK_GENMASK_VAL(3, 2, 0)),
> +	/* PCIE20 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO2, RK_PD0, RK_FUNC_4, 0x0314, RK_GENMASK_VAL(3, 2, 1)),
> +	/* PCIE20 IO mux selection M2 */
> +	MR_TOPGRF(RK_GPIO1, RK_PB0, RK_FUNC_4, 0x0314, RK_GENMASK_VAL(3, 2, 2)),
> +	/* PCIE30X1 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO0, RK_PA4, RK_FUNC_3, 0x0314, RK_GENMASK_VAL(5, 4, 0)),
> +	/* PCIE30X1 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO2, RK_PD2, RK_FUNC_4, 0x0314, RK_GENMASK_VAL(5, 4, 1)),
> +	/* PCIE30X1 IO mux selection M2 */
> +	MR_TOPGRF(RK_GPIO1, RK_PA5, RK_FUNC_4, 0x0314, RK_GENMASK_VAL(5, 4, 2)),
> +	/* PCIE30X2 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO0, RK_PA6, RK_FUNC_2, 0x0314, RK_GENMASK_VAL(7, 6, 0)),
> +	/* PCIE30X2 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO2, RK_PD4, RK_FUNC_4, 0x0314, RK_GENMASK_VAL(7, 6, 1)),
> +	/* PCIE30X2 IO mux selection M2 */
> +	MR_TOPGRF(RK_GPIO4, RK_PC2, RK_FUNC_4, 0x0314, RK_GENMASK_VAL(7, 6, 2)),
> +};
> +
> +static int rk3568_set_mux(struct rockchip_pin_bank *bank, int pin, int mux)
> +{
> +	struct rockchip_pinctrl_priv *priv = bank->priv;
> +	int iomux_num = (pin / 8);
> +	struct regmap *regmap;
> +	int reg, ret, mask;
> +	u8 bit;
> +	u32 data;
> +
> +	debug("setting mux of GPIO%d-%d to %d\n", bank->bank_num, pin, mux);
> +
> +	if (bank->iomux[iomux_num].type & IOMUX_SOURCE_PMU)
> +		regmap = priv->regmap_pmu;
> +	else
> +		regmap = priv->regmap_base;
> +
> +	reg = bank->iomux[iomux_num].offset;
> +	if ((pin % 8) >= 4)
> +		reg += 0x4;
> +	bit = (pin % 4) * 4;
> +	mask = 0xf;
> +
> +	data = (mask << (bit + 16));
> +	data |= (mux & mask) << bit;
> +	ret = regmap_write(regmap, reg, data);
> +
> +	return ret;
> +}
> +
> +#define RK3568_PULL_PMU_OFFSET		0x20
> +#define RK3568_PULL_GRF_OFFSET		0x80
> +#define RK3568_PULL_BITS_PER_PIN	2
> +#define RK3568_PULL_PINS_PER_REG	8
> +#define RK3568_PULL_BANK_STRIDE		0x10
> +
> +static void rk3568_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank,
> +					 int pin_num, struct regmap **regmap,
> +					 int *reg, u8 *bit)
> +{
> +	struct rockchip_pinctrl_priv *info = bank->priv;
> +
> +	if (bank->bank_num == 0) {
> +		*regmap = info->regmap_pmu;
> +		*reg = RK3568_PULL_PMU_OFFSET;
> +		*reg += bank->bank_num * RK3568_PULL_BANK_STRIDE;
> +	} else {
> +		*regmap = info->regmap_base;
> +		*reg = RK3568_PULL_GRF_OFFSET;
> +		*reg += (bank->bank_num - 1) * RK3568_PULL_BANK_STRIDE;
> +	}
> +
> +	*reg += ((pin_num / RK3568_PULL_PINS_PER_REG) * 4);
> +	*bit = (pin_num % RK3568_PULL_PINS_PER_REG);
> +	*bit *= RK3568_PULL_BITS_PER_PIN;
> +}
> +
> +#define RK3568_DRV_PMU_OFFSET		0x70
> +#define RK3568_DRV_GRF_OFFSET		0x200
> +#define RK3568_DRV_BITS_PER_PIN		8
> +#define RK3568_DRV_PINS_PER_REG		2
> +#define RK3568_DRV_BANK_STRIDE		0x40
> +
> +static void rk3568_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank,
> +					int pin_num, struct regmap **regmap,
> +					int *reg, u8 *bit)
> +{
> +	struct rockchip_pinctrl_priv *info = bank->priv;
> +
> +	/* The first 32 pins of the first bank are located in PMU */
> +	if (bank->bank_num == 0) {
> +		*regmap = info->regmap_pmu;
> +		*reg = RK3568_DRV_PMU_OFFSET;
> +	} else {
> +		*regmap = info->regmap_base;
> +		*reg = RK3568_DRV_GRF_OFFSET;
> +		*reg += (bank->bank_num - 1) * RK3568_DRV_BANK_STRIDE;
> +	}
> +
> +	*reg += ((pin_num / RK3568_DRV_PINS_PER_REG) * 4);
> +	*bit = (pin_num % RK3568_DRV_PINS_PER_REG);
> +	*bit *= RK3568_DRV_BITS_PER_PIN;
> +}
> +
> +#define RK3568_SCHMITT_BITS_PER_PIN		2
> +#define RK3568_SCHMITT_PINS_PER_REG		8
> +#define RK3568_SCHMITT_BANK_STRIDE		0x10
> +#define RK3568_SCHMITT_GRF_OFFSET		0xc0
> +#define RK3568_SCHMITT_PMUGRF_OFFSET		0x30
> +
> +static int rk3568_calc_schmitt_reg_and_bit(struct rockchip_pin_bank *bank,
> +					   int pin_num, struct regmap **regmap,
> +					   int *reg, u8 *bit)
> +{
> +	struct rockchip_pinctrl_priv *info = bank->priv;
> +
> +	if (bank->bank_num == 0) {
> +		*regmap = info->regmap_pmu;
> +		*reg = RK3568_SCHMITT_PMUGRF_OFFSET;
> +	} else {
> +		*regmap = info->regmap_base;
> +		*reg = RK3568_SCHMITT_GRF_OFFSET;
> +		*reg += (bank->bank_num - 1) * RK3568_SCHMITT_BANK_STRIDE;
> +	}
> +
> +	*reg += ((pin_num / RK3568_SCHMITT_PINS_PER_REG) * 4);
> +	*bit = pin_num % RK3568_SCHMITT_PINS_PER_REG;
> +	*bit *= RK3568_SCHMITT_BITS_PER_PIN;
> +
> +	return 0;
> +}
> +
> +static int rk3568_set_pull(struct rockchip_pin_bank *bank,
> +			   int pin_num, int pull)
> +{
> +	struct regmap *regmap;
> +	int reg, ret;
> +	u8 bit, type;
> +	u32 data;
> +
> +	if (pull == PIN_CONFIG_BIAS_PULL_PIN_DEFAULT)
> +		return -EOPNOTSUPP;
> +
> +	rk3568_calc_pull_reg_and_bit(bank, pin_num, &regmap, &reg, &bit);
> +	type = bank->pull_type[pin_num / 8];
> +	ret = rockchip_translate_pull_value(type, pull);
> +	if (ret < 0) {
> +		debug("unsupported pull setting %d\n", pull);
> +		return ret;
> +	}
> +
> +	/* enable the write to the equivalent lower bits */
> +	data = ((1 << ROCKCHIP_PULL_BITS_PER_PIN) - 1) << (bit + 16);
> +
> +	data |= (ret << bit);
> +	ret = regmap_write(regmap, reg, data);
> +
> +	return ret;
> +}
> +
> +static int rk3568_set_drive(struct rockchip_pin_bank *bank,
> +			    int pin_num, int strength)
> +{
> +	struct regmap *regmap;
> +	int reg;
> +	u32 data;
> +	u8 bit;
> +	int drv = (1 << (strength + 1)) - 1;
> +	int ret = 0;
> +
> +	rk3568_calc_drv_reg_and_bit(bank, pin_num, &regmap, &reg, &bit);
> +
> +	/* enable the write to the equivalent lower bits */
> +	data = ((1 << RK3568_DRV_BITS_PER_PIN) - 1) << (bit + 16);
> +	data |= (drv << bit);
> +
> +	ret = regmap_write(regmap, reg, data);
> +	if (ret)
> +		return ret;
> +
> +	if (bank->bank_num == 1 && pin_num == 21)
> +		reg = 0x0840;
> +	else if (bank->bank_num == 2 && pin_num == 2)
> +		reg = 0x0844;
> +	else if (bank->bank_num == 2 && pin_num == 8)
> +		reg = 0x0848;
> +	else if (bank->bank_num == 3 && pin_num == 0)
> +		reg = 0x084c;
> +	else if (bank->bank_num == 3 && pin_num == 6)
> +		reg = 0x0850;
> +	else if (bank->bank_num == 4 && pin_num == 0)
> +		reg = 0x0854;
> +	else
> +		return 0;
> +
> +	data = ((1 << RK3568_DRV_BITS_PER_PIN) - 1) << 16;
> +	data |= drv;
> +
> +	return regmap_write(regmap, reg, data);
> +}
> +
> +static int rk3568_set_schmitt(struct rockchip_pin_bank *bank,
> +			      int pin_num, int enable)
> +{
> +	struct regmap *regmap;
> +	int reg;
> +	u32 data;
> +	u8 bit;
> +
> +	rk3568_calc_schmitt_reg_and_bit(bank, pin_num, &regmap, &reg, &bit);
> +
> +	/* enable the write to the equivalent lower bits */
> +	data = ((1 << RK3568_SCHMITT_BITS_PER_PIN) - 1) << (bit + 16);
> +	data |= (enable << bit);
> +
> +	return regmap_write(regmap, reg, data);
> +}
> +
> +static struct rockchip_pin_bank rk3568_pin_banks[] = {
> +	PIN_BANK_IOMUX_FLAGS(0, 32, "gpio0", IOMUX_SOURCE_PMU | IOMUX_WIDTH_4BIT,
> +			     IOMUX_SOURCE_PMU | IOMUX_WIDTH_4BIT,
> +			     IOMUX_SOURCE_PMU | IOMUX_WIDTH_4BIT,
> +			     IOMUX_SOURCE_PMU | IOMUX_WIDTH_4BIT),
> +	PIN_BANK_IOMUX_FLAGS(1, 32, "gpio1", IOMUX_WIDTH_4BIT,
> +			     IOMUX_WIDTH_4BIT,
> +			     IOMUX_WIDTH_4BIT,
> +			     IOMUX_WIDTH_4BIT),
> +	PIN_BANK_IOMUX_FLAGS(2, 32, "gpio2", IOMUX_WIDTH_4BIT,
> +			     IOMUX_WIDTH_4BIT,
> +			     IOMUX_WIDTH_4BIT,
> +			     IOMUX_WIDTH_4BIT),
> +	PIN_BANK_IOMUX_FLAGS(3, 32, "gpio3", IOMUX_WIDTH_4BIT,
> +			     IOMUX_WIDTH_4BIT,
> +			     IOMUX_WIDTH_4BIT,
> +			     IOMUX_WIDTH_4BIT),
> +	PIN_BANK_IOMUX_FLAGS(4, 32, "gpio4", IOMUX_WIDTH_4BIT,
> +			     IOMUX_WIDTH_4BIT,
> +			     IOMUX_WIDTH_4BIT,
> +			     IOMUX_WIDTH_4BIT),
> +};
> +
> +static const struct rockchip_pin_ctrl rk3568_pin_ctrl = {
> +	.pin_banks		= rk3568_pin_banks,
> +	.nr_banks		= ARRAY_SIZE(rk3568_pin_banks),
> +	.nr_pins		= 160,
> +	.grf_mux_offset		= 0x0,
> +	.pmu_mux_offset		= 0x0,
> +	.iomux_routes		= rk3568_mux_route_data,
> +	.niomux_routes		= ARRAY_SIZE(rk3568_mux_route_data),
> +	.set_mux		= rk3568_set_mux,
> +	.set_pull		= rk3568_set_pull,
> +	.set_drive		= rk3568_set_drive,
> +	.set_schmitt		= rk3568_set_schmitt,
> +};
> +
> +static const struct udevice_id rk3568_pinctrl_ids[] = {
> +	{
> +		.compatible = "rockchip,rk3568-pinctrl",
> +		.data = (ulong)&rk3568_pin_ctrl
> +	},
> +	{ }
> +};
> +
> +U_BOOT_DRIVER(pinctrl_rk3568) = {
> +	.name		= "rockchip_rk3568_pinctrl",
> +	.id		= UCLASS_PINCTRL,
> +	.of_match	= rk3568_pinctrl_ids,
> +	.priv_auto = sizeof(struct rockchip_pinctrl_priv),
> +	.ops		= &rockchip_pinctrl_ops,
> +#if !IS_ENABLED(CONFIG_OF_PLATDATA)
> +	.bind		= dm_scan_fdt_dev,
> +#endif
> +	.probe		= rockchip_pinctrl_probe,
> +};
> diff --git a/drivers/pinctrl/rockchip/pinctrl-rockchip-core.c b/drivers/pinctrl/rockchip/pinctrl-rockchip-core.c
> index d9d61fdb72..1481c1e51c 100644
> --- a/drivers/pinctrl/rockchip/pinctrl-rockchip-core.c
> +++ b/drivers/pinctrl/rockchip/pinctrl-rockchip-core.c
> @@ -433,7 +433,7 @@ static int rockchip_pinctrl_set_state(struct udevice *dev,
>   	int prop_len, param;
>   	const u32 *data;
>   	ofnode node;
> -#ifdef CONFIG_OF_LIVE
> +#if CONFIG_IS_ENABLED(OF_LIVE)
>   	const struct device_node *np;
>   	struct property *pp;
>   #else
> @@ -473,7 +473,7 @@ static int rockchip_pinctrl_set_state(struct udevice *dev,
>   		node = ofnode_get_by_phandle(conf);
>   		if (!ofnode_valid(node))
>   			return -ENODEV;
> -#ifdef CONFIG_OF_LIVE
> +#if CONFIG_IS_ENABLED(OF_LIVE)
>   		np = ofnode_to_np(node);
>   		for (pp = np->properties; pp; pp = pp->next) {
>   			prop_name = pp->name;
> @@ -548,13 +548,15 @@ static struct rockchip_pin_ctrl *rockchip_pinctrl_get_soc_data(struct udevice *d
>   
>   			/* preset iomux offset value, set new start value */
>   			if (iom->offset >= 0) {
> -				if (iom->type & IOMUX_SOURCE_PMU)
> +				if ((iom->type & IOMUX_SOURCE_PMU) || \
> +				    (iom->type & IOMUX_L_SOURCE_PMU))
>   					pmu_offs = iom->offset;
>   				else
>   					grf_offs = iom->offset;
>   			} else { /* set current iomux offset */
> -				iom->offset = (iom->type & IOMUX_SOURCE_PMU) ?
> -							pmu_offs : grf_offs;
> +				iom->offset = ((iom->type & IOMUX_SOURCE_PMU) ||
> +						(iom->type & IOMUX_L_SOURCE_PMU)) ?
> +						pmu_offs : grf_offs;
>   			}
>   
>   			/* preset drv offset value, set new start value */
Vasily Khoruzhick Feb. 23, 2023, 10:14 p.m. UTC | #4
On Mon, Feb 13, 2023 at 2:30 PM Chris Morgan <macroalpha82@gmail.com> wrote:
>
> From: Chris Morgan <macromorgan@hotmail.com>
>
> Add support for the newer GPIO controller used by the rk356x series,
> as well as the pinctrl device for the rk356x series. The GPIOv2
> controller has a write enable bit for some registers which differs
> from the older versions of the GPIO controller.
>
> Signed-off-by: Peter Geis <pgwipeout@gmail.com>
> Signed-off-by: Chris Morgan <macromorgan@hotmail.com>

With pinctrl part from
https://patchwork.ozlabs.org/project/uboot/patch/20230217115845.75303-11-jagan@amarulasolutions.com/

Tested-by: Vasily Khoruzhick <anarsoul@gmail.com>

> ---
>  arch/arm/include/asm/arch-rockchip/gpio.h     |  38 ++
>  drivers/gpio/rk_gpio.c                        |  49 +-
>  drivers/pinctrl/rockchip/Makefile             |   1 +
>  drivers/pinctrl/rockchip/pinctrl-rk3568.c     | 453 ++++++++++++++++++
>  .../pinctrl/rockchip/pinctrl-rockchip-core.c  |  12 +-
>  5 files changed, 540 insertions(+), 13 deletions(-)
>  create mode 100644 drivers/pinctrl/rockchip/pinctrl-rk3568.c
>
> 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 98a79b5f4d..e2653be058 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, <superpeter.cai@gmail.com>.
> + * Jianqun Xu, Software Engineering, <jay.xu@rock-chips.com>.
>   */
>
>  #include <common.h>
>  #include <dm.h>
> +#include <dm/of_access.h>
> +#include <dm/device_compat.h>
>  #include <syscon.h>
>  #include <linux/errno.h>
>  #include <asm/gpio.h>
> @@ -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 +68,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 +80,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 +101,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;
>  }
> @@ -86,14 +119,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(&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
>  }
>
>  /* Simple SPL interface to GPIOs */
> -#ifdef CONFIG_SPL_BUILD
> +#if defined(CONFIG_SPL_BUILD) && (GPIO_VER == 1)
>
>  enum {
>         PULL_NONE_1V8 = 0,
> @@ -143,7 +176,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);
> diff --git a/drivers/pinctrl/rockchip/Makefile b/drivers/pinctrl/rockchip/Makefile
> index 9884355473..90461ae881 100644
> --- a/drivers/pinctrl/rockchip/Makefile
> +++ b/drivers/pinctrl/rockchip/Makefile
> @@ -14,5 +14,6 @@ obj-$(CONFIG_ROCKCHIP_RK3308) += pinctrl-rk3308.o
>  obj-$(CONFIG_ROCKCHIP_RK3328) += pinctrl-rk3328.o
>  obj-$(CONFIG_ROCKCHIP_RK3368) += pinctrl-rk3368.o
>  obj-$(CONFIG_ROCKCHIP_RK3399) += pinctrl-rk3399.o
> +obj-$(CONFIG_ROCKCHIP_RK3568) += pinctrl-rk3568.o
>  obj-$(CONFIG_ROCKCHIP_RV1108) += pinctrl-rv1108.o
>  obj-$(CONFIG_ROCKCHIP_RV1126) += pinctrl-rv1126.o
> diff --git a/drivers/pinctrl/rockchip/pinctrl-rk3568.c b/drivers/pinctrl/rockchip/pinctrl-rk3568.c
> new file mode 100644
> index 0000000000..dce1c1e7ee
> --- /dev/null
> +++ b/drivers/pinctrl/rockchip/pinctrl-rk3568.c
> @@ -0,0 +1,453 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * (C) Copyright 2020 Rockchip Electronics Co., Ltd
> + */
> +
> +#include <common.h>
> +#include <dm.h>
> +#include <dm/pinctrl.h>
> +#include <regmap.h>
> +#include <syscon.h>
> +
> +#include "pinctrl-rockchip.h"
> +
> +static struct rockchip_mux_route_data rk3568_mux_route_data[] = {
> +       /* CAN0 IO mux selection M0 */
> +       MR_TOPGRF(RK_GPIO0, RK_PB3, RK_FUNC_2, 0x0300, RK_GENMASK_VAL(0, 0, 0)),
> +       /* CAN0 IO mux selection M1 */
> +       MR_TOPGRF(RK_GPIO2, RK_PA1, RK_FUNC_4, 0x0300, RK_GENMASK_VAL(0, 0, 1)),
> +       /* CAN1 IO mux selection M0 */
> +       MR_TOPGRF(RK_GPIO1, RK_PA1, RK_FUNC_3, 0x0300, RK_GENMASK_VAL(2, 2, 0)),
> +       /* CAN1 IO mux selection M1 */
> +       MR_TOPGRF(RK_GPIO4, RK_PC3, RK_FUNC_3, 0x0300, RK_GENMASK_VAL(2, 2, 1)),
> +       /* CAN2 IO mux selection M0 */
> +       MR_TOPGRF(RK_GPIO4, RK_PB5, RK_FUNC_3, 0x0300, RK_GENMASK_VAL(4, 4, 0)),
> +       /* CAN2 IO mux selection M1 */
> +       MR_TOPGRF(RK_GPIO2, RK_PB2, RK_FUNC_4, 0x0300, RK_GENMASK_VAL(4, 4, 1)),
> +       /* EDPDP_HPDIN IO mux selection M0 */
> +       MR_TOPGRF(RK_GPIO4, RK_PC4, RK_FUNC_1, 0x0300, RK_GENMASK_VAL(6, 6, 0)),
> +       /* EDPDP_HPDIN IO mux selection M1 */
> +       MR_TOPGRF(RK_GPIO0, RK_PC2, RK_FUNC_2, 0x0300, RK_GENMASK_VAL(6, 6, 1)),
> +       /* GMAC1 IO mux selection M0 */
> +       MR_TOPGRF(RK_GPIO3, RK_PB1, RK_FUNC_3, 0x0300, RK_GENMASK_VAL(8, 8, 0)),
> +       /* GMAC1 IO mux selection M1 */
> +       MR_TOPGRF(RK_GPIO4, RK_PA7, RK_FUNC_3, 0x0300, RK_GENMASK_VAL(8, 8, 1)),
> +       /* HDMITX IO mux selection M0 */
> +       MR_TOPGRF(RK_GPIO4, RK_PD1, RK_FUNC_1, 0x0300, RK_GENMASK_VAL(10, 10, 0)),
> +       /* HDMITX IO mux selection M1 */
> +       MR_TOPGRF(RK_GPIO0, RK_PC7, RK_FUNC_1, 0x0300, RK_GENMASK_VAL(10, 10, 1)),
> +       /* I2C2 IO mux selection M0 */
> +       MR_TOPGRF(RK_GPIO0, RK_PB6, RK_FUNC_1, 0x0300, RK_GENMASK_VAL(14, 14, 0)),
> +       /* I2C2 IO mux selection M1 */
> +       MR_TOPGRF(RK_GPIO4, RK_PB4, RK_FUNC_1, 0x0300, RK_GENMASK_VAL(14, 14, 1)),
> +       /* I2C3 IO mux selection M0 */
> +       MR_TOPGRF(RK_GPIO1, RK_PA0, RK_FUNC_1, 0x0304, RK_GENMASK_VAL(0, 0, 0)),
> +       /* I2C3 IO mux selection M1 */
> +       MR_TOPGRF(RK_GPIO3, RK_PB6, RK_FUNC_4, 0x0304, RK_GENMASK_VAL(0, 0, 1)),
> +       /* I2C4 IO mux selection M0 */
> +       MR_TOPGRF(RK_GPIO4, RK_PB2, RK_FUNC_1, 0x0304, RK_GENMASK_VAL(2, 2, 0)),
> +       /* I2C4 IO mux selection M1 */
> +       MR_TOPGRF(RK_GPIO2, RK_PB1, RK_FUNC_2, 0x0304, RK_GENMASK_VAL(2, 2, 1)),
> +       /* I2C5 IO mux selection M0 */
> +       MR_TOPGRF(RK_GPIO3, RK_PB4, RK_FUNC_4, 0x0304, RK_GENMASK_VAL(4, 4, 0)),
> +       /* I2C5 IO mux selection M1 */
> +       MR_TOPGRF(RK_GPIO4, RK_PD0, RK_FUNC_2, 0x0304, RK_GENMASK_VAL(4, 4, 1)),
> +       /* PWM4 IO mux selection M0 */
> +       MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0304, RK_GENMASK_VAL(6, 6, 0)),
> +       /* PWM4 IO mux selection M1 */
> +       MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0304, RK_GENMASK_VAL(6, 6, 1)),
> +       /* PWM5 IO mux selection M0 */
> +       MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0304, RK_GENMASK_VAL(8, 8, 0)),
> +       /* PWM5 IO mux selection M1 */
> +       MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0304, RK_GENMASK_VAL(8, 8, 1)),
> +       /* PWM6 IO mux selection M0 */
> +       MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0304, RK_GENMASK_VAL(10, 10, 0)),
> +       /* PWM6 IO mux selection M1 */
> +       MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0304, RK_GENMASK_VAL(10, 10, 1)),
> +       /* PWM7 IO mux selection M0 */
> +       MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0304, RK_GENMASK_VAL(12, 12, 0)),
> +       /* PWM7 IO mux selection M1 */
> +       MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0304, RK_GENMASK_VAL(12, 12, 1)),
> +       /* PWM8 IO mux selection M0 */
> +       MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0304, RK_GENMASK_VAL(14, 14, 0)),
> +       /* PWM8 IO mux selection M1 */
> +       MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0304, RK_GENMASK_VAL(14, 14, 1)),
> +       /* PWM9 IO mux selection M0 */
> +       MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(0, 0, 0)),
> +       /* PWM9 IO mux selection M1 */
> +       MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(0, 0, 1)),
> +       /* PWM10 IO mux selection M0 */
> +       MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(2, 2, 0)),
> +       /* PWM10 IO mux selection M1 */
> +       MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(2, 2, 1)),
> +       /* PWM11 IO mux selection M0 */
> +       MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(4, 4, 0)),
> +       /* PWM11 IO mux selection M1 */
> +       MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(4, 4, 1)),
> +       /* PWM12 IO mux selection M0 */
> +       MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(6, 6, 0)),
> +       /* PWM12 IO mux selection M1 */
> +       MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(6, 6, 1)),
> +       /* PWM13 IO mux selection M0 */
> +       MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(8, 8, 0)),
> +       /* PWM13 IO mux selection M1 */
> +       MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(8, 8, 1)),
> +       /* PWM14 IO mux selection M0 */
> +       MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(10, 10, 0)),
> +       /* PWM14 IO mux selection M1 */
> +       MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(10, 10, 1)),
> +       /* PWM15 IO mux selection M0 */
> +       MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(12, 12, 0)),
> +       /* PWM15 IO mux selection M1 */
> +       MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(12, 12, 1)),
> +       /* SDMMC2 IO mux selection M0 */
> +       MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_3, 0x0308, RK_GENMASK_VAL(14, 14, 0)),
> +       /* SDMMC2 IO mux selection M1 */
> +       MR_TOPGRF(RK_GPIO3, RK_PA5, RK_FUNC_5, 0x0308, RK_GENMASK_VAL(14, 14, 1)),
> +       /* SPI0 IO mux selection M0 */
> +       MR_TOPGRF(RK_GPIO0, RK_PB5, RK_FUNC_2, 0x030c, RK_GENMASK_VAL(0, 0, 0)),
> +       /* SPI0 IO mux selection M1 */
> +       MR_TOPGRF(RK_GPIO2, RK_PD3, RK_FUNC_3, 0x030c, RK_GENMASK_VAL(0, 0, 1)),
> +       /* SPI1 IO mux selection M0 */
> +       MR_TOPGRF(RK_GPIO2, RK_PB5, RK_FUNC_3, 0x030c, RK_GENMASK_VAL(2, 2, 0)),
> +       /* SPI1 IO mux selection M1 */
> +       MR_TOPGRF(RK_GPIO3, RK_PC3, RK_FUNC_3, 0x030c, RK_GENMASK_VAL(2, 2, 1)),
> +       /* SPI2 IO mux selection M0 */
> +       MR_TOPGRF(RK_GPIO2, RK_PC1, RK_FUNC_4, 0x030c, RK_GENMASK_VAL(4, 4, 0)),
> +       /* SPI2 IO mux selection M1 */
> +       MR_TOPGRF(RK_GPIO3, RK_PA0, RK_FUNC_3, 0x030c, RK_GENMASK_VAL(4, 4, 1)),
> +       /* SPI3 IO mux selection M0 */
> +       MR_TOPGRF(RK_GPIO4, RK_PB3, RK_FUNC_4, 0x030c, RK_GENMASK_VAL(6, 6, 0)),
> +       /* SPI3 IO mux selection M1 */
> +       MR_TOPGRF(RK_GPIO4, RK_PC2, RK_FUNC_2, 0x030c, RK_GENMASK_VAL(6, 6, 1)),
> +       /* UART1 IO mux selection M0 */
> +       MR_TOPGRF(RK_GPIO2, RK_PB4, RK_FUNC_2, 0x030c, RK_GENMASK_VAL(8, 8, 0)),
> +       /* UART1 IO mux selection M1 */
> +       MR_TOPGRF(RK_GPIO0, RK_PD1, RK_FUNC_1, 0x030c, RK_GENMASK_VAL(8, 8, 1)),
> +       /* UART2 IO mux selection M0 */
> +       MR_TOPGRF(RK_GPIO0, RK_PD1, RK_FUNC_1, 0x030c, RK_GENMASK_VAL(10, 10, 0)),
> +       /* UART2 IO mux selection M1 */
> +       MR_TOPGRF(RK_GPIO1, RK_PD5, RK_FUNC_2, 0x030c, RK_GENMASK_VAL(10, 10, 1)),
> +       /* UART3 IO mux selection M0 */
> +       MR_TOPGRF(RK_GPIO1, RK_PA1, RK_FUNC_2, 0x030c, RK_GENMASK_VAL(12, 12, 0)),
> +       /* UART3 IO mux selection M1 */
> +       MR_TOPGRF(RK_GPIO3, RK_PB7, RK_FUNC_4, 0x030c, RK_GENMASK_VAL(12, 12, 1)),
> +       /* UART4 IO mux selection M0 */
> +       MR_TOPGRF(RK_GPIO1, RK_PA6, RK_FUNC_2, 0x030c, RK_GENMASK_VAL(14, 14, 0)),
> +       /* UART4 IO mux selection M1 */
> +       MR_TOPGRF(RK_GPIO3, RK_PB2, RK_FUNC_4, 0x030c, RK_GENMASK_VAL(14, 14, 1)),
> +       /* UART5 IO mux selection M0 */
> +       MR_TOPGRF(RK_GPIO2, RK_PA2, RK_FUNC_3, 0x0310, RK_GENMASK_VAL(0, 0, 0)),
> +       /* UART5 IO mux selection M1 */
> +       MR_TOPGRF(RK_GPIO3, RK_PC2, RK_FUNC_4, 0x0310, RK_GENMASK_VAL(0, 0, 1)),
> +       /* UART6 IO mux selection M0 */
> +       MR_TOPGRF(RK_GPIO2, RK_PA4, RK_FUNC_3, 0x0310, RK_GENMASK_VAL(2, 2, 0)),
> +       /* UART6 IO mux selection M1 */
> +       MR_TOPGRF(RK_GPIO1, RK_PD5, RK_FUNC_3, 0x0310, RK_GENMASK_VAL(2, 2, 1)),
> +       /* UART7 IO mux selection M0 */
> +       MR_TOPGRF(RK_GPIO2, RK_PA6, RK_FUNC_3, 0x0310, RK_GENMASK_VAL(5, 4, 0)),
> +       /* UART7 IO mux selection M1 */
> +       MR_TOPGRF(RK_GPIO3, RK_PC4, RK_FUNC_4, 0x0310, RK_GENMASK_VAL(5, 4, 1)),
> +       /* UART7 IO mux selection M2 */
> +       MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0310, RK_GENMASK_VAL(5, 4, 2)),
> +       /* UART8 IO mux selection M0 */
> +       MR_TOPGRF(RK_GPIO2, RK_PC5, RK_FUNC_3, 0x0310, RK_GENMASK_VAL(6, 6, 0)),
> +       /* UART8 IO mux selection M1 */
> +       MR_TOPGRF(RK_GPIO2, RK_PD7, RK_FUNC_4, 0x0310, RK_GENMASK_VAL(6, 6, 1)),
> +       /* UART9 IO mux selection M0 */
> +       MR_TOPGRF(RK_GPIO2, RK_PB0, RK_FUNC_3, 0x0310, RK_GENMASK_VAL(9, 8, 0)),
> +       /* UART9 IO mux selection M1 */
> +       MR_TOPGRF(RK_GPIO4, RK_PC5, RK_FUNC_4, 0x0310, RK_GENMASK_VAL(9, 8, 1)),
> +       /* UART9 IO mux selection M2 */
> +       MR_TOPGRF(RK_GPIO4, RK_PA4, RK_FUNC_4, 0x0310, RK_GENMASK_VAL(9, 8, 2)),
> +       /* I2S1 IO mux selection M0 */
> +       MR_TOPGRF(RK_GPIO1, RK_PA2, RK_FUNC_1, 0x0310, RK_GENMASK_VAL(11, 10, 0)),
> +       /* I2S1 IO mux selection M1 */
> +       MR_TOPGRF(RK_GPIO3, RK_PC6, RK_FUNC_4, 0x0310, RK_GENMASK_VAL(11, 10, 1)),
> +       /* I2S1 IO mux selection M2 */
> +       MR_TOPGRF(RK_GPIO2, RK_PD0, RK_FUNC_5, 0x0310, RK_GENMASK_VAL(11, 10, 2)),
> +       /* I2S2 IO mux selection M0 */
> +       MR_TOPGRF(RK_GPIO2, RK_PC1, RK_FUNC_1, 0x0310, RK_GENMASK_VAL(12, 12, 0)),
> +       /* I2S2 IO mux selection M1 */
> +       MR_TOPGRF(RK_GPIO4, RK_PB6, RK_FUNC_5, 0x0310, RK_GENMASK_VAL(12, 12, 1)),
> +       /* I2S3 IO mux selection M0 */
> +       MR_TOPGRF(RK_GPIO3, RK_PA2, RK_FUNC_4, 0x0310, RK_GENMASK_VAL(14, 14, 0)),
> +       /* I2S3 IO mux selection M1 */
> +       MR_TOPGRF(RK_GPIO4, RK_PC2, RK_FUNC_5, 0x0310, RK_GENMASK_VAL(14, 14, 1)),
> +       /* PDM IO mux selection M0 */
> +       MR_TOPGRF(RK_GPIO1, RK_PA6, RK_FUNC_3, 0x0314, RK_GENMASK_VAL(0, 0, 0)),
> +       /* PDM IO mux selection M1 */
> +       MR_TOPGRF(RK_GPIO3, RK_PD6, RK_FUNC_5, 0x0314, RK_GENMASK_VAL(0, 0, 1)),
> +       /* PCIE20 IO mux selection M0 */
> +       MR_TOPGRF(RK_GPIO0, RK_PA5, RK_FUNC_3, 0x0314, RK_GENMASK_VAL(3, 2, 0)),
> +       /* PCIE20 IO mux selection M1 */
> +       MR_TOPGRF(RK_GPIO2, RK_PD0, RK_FUNC_4, 0x0314, RK_GENMASK_VAL(3, 2, 1)),
> +       /* PCIE20 IO mux selection M2 */
> +       MR_TOPGRF(RK_GPIO1, RK_PB0, RK_FUNC_4, 0x0314, RK_GENMASK_VAL(3, 2, 2)),
> +       /* PCIE30X1 IO mux selection M0 */
> +       MR_TOPGRF(RK_GPIO0, RK_PA4, RK_FUNC_3, 0x0314, RK_GENMASK_VAL(5, 4, 0)),
> +       /* PCIE30X1 IO mux selection M1 */
> +       MR_TOPGRF(RK_GPIO2, RK_PD2, RK_FUNC_4, 0x0314, RK_GENMASK_VAL(5, 4, 1)),
> +       /* PCIE30X1 IO mux selection M2 */
> +       MR_TOPGRF(RK_GPIO1, RK_PA5, RK_FUNC_4, 0x0314, RK_GENMASK_VAL(5, 4, 2)),
> +       /* PCIE30X2 IO mux selection M0 */
> +       MR_TOPGRF(RK_GPIO0, RK_PA6, RK_FUNC_2, 0x0314, RK_GENMASK_VAL(7, 6, 0)),
> +       /* PCIE30X2 IO mux selection M1 */
> +       MR_TOPGRF(RK_GPIO2, RK_PD4, RK_FUNC_4, 0x0314, RK_GENMASK_VAL(7, 6, 1)),
> +       /* PCIE30X2 IO mux selection M2 */
> +       MR_TOPGRF(RK_GPIO4, RK_PC2, RK_FUNC_4, 0x0314, RK_GENMASK_VAL(7, 6, 2)),
> +};
> +
> +static int rk3568_set_mux(struct rockchip_pin_bank *bank, int pin, int mux)
> +{
> +       struct rockchip_pinctrl_priv *priv = bank->priv;
> +       int iomux_num = (pin / 8);
> +       struct regmap *regmap;
> +       int reg, ret, mask;
> +       u8 bit;
> +       u32 data;
> +
> +       debug("setting mux of GPIO%d-%d to %d\n", bank->bank_num, pin, mux);
> +
> +       if (bank->iomux[iomux_num].type & IOMUX_SOURCE_PMU)
> +               regmap = priv->regmap_pmu;
> +       else
> +               regmap = priv->regmap_base;
> +
> +       reg = bank->iomux[iomux_num].offset;
> +       if ((pin % 8) >= 4)
> +               reg += 0x4;
> +       bit = (pin % 4) * 4;
> +       mask = 0xf;
> +
> +       data = (mask << (bit + 16));
> +       data |= (mux & mask) << bit;
> +       ret = regmap_write(regmap, reg, data);
> +
> +       return ret;
> +}
> +
> +#define RK3568_PULL_PMU_OFFSET         0x20
> +#define RK3568_PULL_GRF_OFFSET         0x80
> +#define RK3568_PULL_BITS_PER_PIN       2
> +#define RK3568_PULL_PINS_PER_REG       8
> +#define RK3568_PULL_BANK_STRIDE                0x10
> +
> +static void rk3568_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank,
> +                                        int pin_num, struct regmap **regmap,
> +                                        int *reg, u8 *bit)
> +{
> +       struct rockchip_pinctrl_priv *info = bank->priv;
> +
> +       if (bank->bank_num == 0) {
> +               *regmap = info->regmap_pmu;
> +               *reg = RK3568_PULL_PMU_OFFSET;
> +               *reg += bank->bank_num * RK3568_PULL_BANK_STRIDE;
> +       } else {
> +               *regmap = info->regmap_base;
> +               *reg = RK3568_PULL_GRF_OFFSET;
> +               *reg += (bank->bank_num - 1) * RK3568_PULL_BANK_STRIDE;
> +       }
> +
> +       *reg += ((pin_num / RK3568_PULL_PINS_PER_REG) * 4);
> +       *bit = (pin_num % RK3568_PULL_PINS_PER_REG);
> +       *bit *= RK3568_PULL_BITS_PER_PIN;
> +}
> +
> +#define RK3568_DRV_PMU_OFFSET          0x70
> +#define RK3568_DRV_GRF_OFFSET          0x200
> +#define RK3568_DRV_BITS_PER_PIN                8
> +#define RK3568_DRV_PINS_PER_REG                2
> +#define RK3568_DRV_BANK_STRIDE         0x40
> +
> +static void rk3568_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank,
> +                                       int pin_num, struct regmap **regmap,
> +                                       int *reg, u8 *bit)
> +{
> +       struct rockchip_pinctrl_priv *info = bank->priv;
> +
> +       /* The first 32 pins of the first bank are located in PMU */
> +       if (bank->bank_num == 0) {
> +               *regmap = info->regmap_pmu;
> +               *reg = RK3568_DRV_PMU_OFFSET;
> +       } else {
> +               *regmap = info->regmap_base;
> +               *reg = RK3568_DRV_GRF_OFFSET;
> +               *reg += (bank->bank_num - 1) * RK3568_DRV_BANK_STRIDE;
> +       }
> +
> +       *reg += ((pin_num / RK3568_DRV_PINS_PER_REG) * 4);
> +       *bit = (pin_num % RK3568_DRV_PINS_PER_REG);
> +       *bit *= RK3568_DRV_BITS_PER_PIN;
> +}
> +
> +#define RK3568_SCHMITT_BITS_PER_PIN            2
> +#define RK3568_SCHMITT_PINS_PER_REG            8
> +#define RK3568_SCHMITT_BANK_STRIDE             0x10
> +#define RK3568_SCHMITT_GRF_OFFSET              0xc0
> +#define RK3568_SCHMITT_PMUGRF_OFFSET           0x30
> +
> +static int rk3568_calc_schmitt_reg_and_bit(struct rockchip_pin_bank *bank,
> +                                          int pin_num, struct regmap **regmap,
> +                                          int *reg, u8 *bit)
> +{
> +       struct rockchip_pinctrl_priv *info = bank->priv;
> +
> +       if (bank->bank_num == 0) {
> +               *regmap = info->regmap_pmu;
> +               *reg = RK3568_SCHMITT_PMUGRF_OFFSET;
> +       } else {
> +               *regmap = info->regmap_base;
> +               *reg = RK3568_SCHMITT_GRF_OFFSET;
> +               *reg += (bank->bank_num - 1) * RK3568_SCHMITT_BANK_STRIDE;
> +       }
> +
> +       *reg += ((pin_num / RK3568_SCHMITT_PINS_PER_REG) * 4);
> +       *bit = pin_num % RK3568_SCHMITT_PINS_PER_REG;
> +       *bit *= RK3568_SCHMITT_BITS_PER_PIN;
> +
> +       return 0;
> +}
> +
> +static int rk3568_set_pull(struct rockchip_pin_bank *bank,
> +                          int pin_num, int pull)
> +{
> +       struct regmap *regmap;
> +       int reg, ret;
> +       u8 bit, type;
> +       u32 data;
> +
> +       if (pull == PIN_CONFIG_BIAS_PULL_PIN_DEFAULT)
> +               return -EOPNOTSUPP;
> +
> +       rk3568_calc_pull_reg_and_bit(bank, pin_num, &regmap, &reg, &bit);
> +       type = bank->pull_type[pin_num / 8];
> +       ret = rockchip_translate_pull_value(type, pull);
> +       if (ret < 0) {
> +               debug("unsupported pull setting %d\n", pull);
> +               return ret;
> +       }
> +
> +       /* enable the write to the equivalent lower bits */
> +       data = ((1 << ROCKCHIP_PULL_BITS_PER_PIN) - 1) << (bit + 16);
> +
> +       data |= (ret << bit);
> +       ret = regmap_write(regmap, reg, data);
> +
> +       return ret;
> +}
> +
> +static int rk3568_set_drive(struct rockchip_pin_bank *bank,
> +                           int pin_num, int strength)
> +{
> +       struct regmap *regmap;
> +       int reg;
> +       u32 data;
> +       u8 bit;
> +       int drv = (1 << (strength + 1)) - 1;
> +       int ret = 0;
> +
> +       rk3568_calc_drv_reg_and_bit(bank, pin_num, &regmap, &reg, &bit);
> +
> +       /* enable the write to the equivalent lower bits */
> +       data = ((1 << RK3568_DRV_BITS_PER_PIN) - 1) << (bit + 16);
> +       data |= (drv << bit);
> +
> +       ret = regmap_write(regmap, reg, data);
> +       if (ret)
> +               return ret;
> +
> +       if (bank->bank_num == 1 && pin_num == 21)
> +               reg = 0x0840;
> +       else if (bank->bank_num == 2 && pin_num == 2)
> +               reg = 0x0844;
> +       else if (bank->bank_num == 2 && pin_num == 8)
> +               reg = 0x0848;
> +       else if (bank->bank_num == 3 && pin_num == 0)
> +               reg = 0x084c;
> +       else if (bank->bank_num == 3 && pin_num == 6)
> +               reg = 0x0850;
> +       else if (bank->bank_num == 4 && pin_num == 0)
> +               reg = 0x0854;
> +       else
> +               return 0;
> +
> +       data = ((1 << RK3568_DRV_BITS_PER_PIN) - 1) << 16;
> +       data |= drv;
> +
> +       return regmap_write(regmap, reg, data);
> +}
> +
> +static int rk3568_set_schmitt(struct rockchip_pin_bank *bank,
> +                             int pin_num, int enable)
> +{
> +       struct regmap *regmap;
> +       int reg;
> +       u32 data;
> +       u8 bit;
> +
> +       rk3568_calc_schmitt_reg_and_bit(bank, pin_num, &regmap, &reg, &bit);
> +
> +       /* enable the write to the equivalent lower bits */
> +       data = ((1 << RK3568_SCHMITT_BITS_PER_PIN) - 1) << (bit + 16);
> +       data |= (enable << bit);
> +
> +       return regmap_write(regmap, reg, data);
> +}
> +
> +static struct rockchip_pin_bank rk3568_pin_banks[] = {
> +       PIN_BANK_IOMUX_FLAGS(0, 32, "gpio0", IOMUX_SOURCE_PMU | IOMUX_WIDTH_4BIT,
> +                            IOMUX_SOURCE_PMU | IOMUX_WIDTH_4BIT,
> +                            IOMUX_SOURCE_PMU | IOMUX_WIDTH_4BIT,
> +                            IOMUX_SOURCE_PMU | IOMUX_WIDTH_4BIT),
> +       PIN_BANK_IOMUX_FLAGS(1, 32, "gpio1", IOMUX_WIDTH_4BIT,
> +                            IOMUX_WIDTH_4BIT,
> +                            IOMUX_WIDTH_4BIT,
> +                            IOMUX_WIDTH_4BIT),
> +       PIN_BANK_IOMUX_FLAGS(2, 32, "gpio2", IOMUX_WIDTH_4BIT,
> +                            IOMUX_WIDTH_4BIT,
> +                            IOMUX_WIDTH_4BIT,
> +                            IOMUX_WIDTH_4BIT),
> +       PIN_BANK_IOMUX_FLAGS(3, 32, "gpio3", IOMUX_WIDTH_4BIT,
> +                            IOMUX_WIDTH_4BIT,
> +                            IOMUX_WIDTH_4BIT,
> +                            IOMUX_WIDTH_4BIT),
> +       PIN_BANK_IOMUX_FLAGS(4, 32, "gpio4", IOMUX_WIDTH_4BIT,
> +                            IOMUX_WIDTH_4BIT,
> +                            IOMUX_WIDTH_4BIT,
> +                            IOMUX_WIDTH_4BIT),
> +};
> +
> +static const struct rockchip_pin_ctrl rk3568_pin_ctrl = {
> +       .pin_banks              = rk3568_pin_banks,
> +       .nr_banks               = ARRAY_SIZE(rk3568_pin_banks),
> +       .nr_pins                = 160,
> +       .grf_mux_offset         = 0x0,
> +       .pmu_mux_offset         = 0x0,
> +       .iomux_routes           = rk3568_mux_route_data,
> +       .niomux_routes          = ARRAY_SIZE(rk3568_mux_route_data),
> +       .set_mux                = rk3568_set_mux,
> +       .set_pull               = rk3568_set_pull,
> +       .set_drive              = rk3568_set_drive,
> +       .set_schmitt            = rk3568_set_schmitt,
> +};
> +
> +static const struct udevice_id rk3568_pinctrl_ids[] = {
> +       {
> +               .compatible = "rockchip,rk3568-pinctrl",
> +               .data = (ulong)&rk3568_pin_ctrl
> +       },
> +       { }
> +};
> +
> +U_BOOT_DRIVER(pinctrl_rk3568) = {
> +       .name           = "rockchip_rk3568_pinctrl",
> +       .id             = UCLASS_PINCTRL,
> +       .of_match       = rk3568_pinctrl_ids,
> +       .priv_auto = sizeof(struct rockchip_pinctrl_priv),
> +       .ops            = &rockchip_pinctrl_ops,
> +#if !IS_ENABLED(CONFIG_OF_PLATDATA)
> +       .bind           = dm_scan_fdt_dev,
> +#endif
> +       .probe          = rockchip_pinctrl_probe,
> +};
> diff --git a/drivers/pinctrl/rockchip/pinctrl-rockchip-core.c b/drivers/pinctrl/rockchip/pinctrl-rockchip-core.c
> index d9d61fdb72..1481c1e51c 100644
> --- a/drivers/pinctrl/rockchip/pinctrl-rockchip-core.c
> +++ b/drivers/pinctrl/rockchip/pinctrl-rockchip-core.c
> @@ -433,7 +433,7 @@ static int rockchip_pinctrl_set_state(struct udevice *dev,
>         int prop_len, param;
>         const u32 *data;
>         ofnode node;
> -#ifdef CONFIG_OF_LIVE
> +#if CONFIG_IS_ENABLED(OF_LIVE)
>         const struct device_node *np;
>         struct property *pp;
>  #else
> @@ -473,7 +473,7 @@ static int rockchip_pinctrl_set_state(struct udevice *dev,
>                 node = ofnode_get_by_phandle(conf);
>                 if (!ofnode_valid(node))
>                         return -ENODEV;
> -#ifdef CONFIG_OF_LIVE
> +#if CONFIG_IS_ENABLED(OF_LIVE)
>                 np = ofnode_to_np(node);
>                 for (pp = np->properties; pp; pp = pp->next) {
>                         prop_name = pp->name;
> @@ -548,13 +548,15 @@ static struct rockchip_pin_ctrl *rockchip_pinctrl_get_soc_data(struct udevice *d
>
>                         /* preset iomux offset value, set new start value */
>                         if (iom->offset >= 0) {
> -                               if (iom->type & IOMUX_SOURCE_PMU)
> +                               if ((iom->type & IOMUX_SOURCE_PMU) || \
> +                                   (iom->type & IOMUX_L_SOURCE_PMU))
>                                         pmu_offs = iom->offset;
>                                 else
>                                         grf_offs = iom->offset;
>                         } else { /* set current iomux offset */
> -                               iom->offset = (iom->type & IOMUX_SOURCE_PMU) ?
> -                                                       pmu_offs : grf_offs;
> +                               iom->offset = ((iom->type & IOMUX_SOURCE_PMU) ||
> +                                               (iom->type & IOMUX_L_SOURCE_PMU)) ?
> +                                               pmu_offs : grf_offs;
>                         }
>
>                         /* preset drv offset value, set new start value */
> --
> 2.34.1
>
Eugen Hristev March 1, 2023, 8:25 a.m. UTC | #5
On 2/14/23 00:27, Chris Morgan wrote:
> From: Chris Morgan <macromorgan@hotmail.com>
> 
> Add support for the newer GPIO controller used by the rk356x series,
> as well as the pinctrl device for the rk356x series. The GPIOv2
> controller has a write enable bit for some registers which differs
> from the older versions of the GPIO controller.
> 
> Signed-off-by: Peter Geis <pgwipeout@gmail.com>
> Signed-off-by: Chris Morgan <macromorgan@hotmail.com>

Hi Chris,

In the file below you have added

 > + * Jianqun Xu, Software Engineering, <jay.xu@rock-chips.com>.

as copyright owner, maybe add him as co-author of this patch ? Or what 
was his contribution ?


> ---
>   arch/arm/include/asm/arch-rockchip/gpio.h     |  38 ++
>   drivers/gpio/rk_gpio.c                        |  49 +-
>   drivers/pinctrl/rockchip/Makefile             |   1 +
>   drivers/pinctrl/rockchip/pinctrl-rk3568.c     | 453 ++++++++++++++++++
>   .../pinctrl/rockchip/pinctrl-rockchip-core.c  |  12 +-
>   5 files changed, 540 insertions(+), 13 deletions(-)
>   create mode 100644 drivers/pinctrl/rockchip/pinctrl-rk3568.c
> 
> 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)

Can't we figure out from the compatible which struct layout to use ?
Using conditionally compile code makes things difficult to read after 
some time.


>   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 98a79b5f4d..e2653be058 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, <superpeter.cai@gmail.com>.
> + * Jianqun Xu, Software Engineering, <jay.xu@rock-chips.com>.
>    */
>   
>   #include <common.h>
>   #include <dm.h>
> +#include <dm/of_access.h>
> +#include <dm/device_compat.h>
>   #include <syscon.h>
>   #include <linux/errno.h>
>   #include <asm/gpio.h>
> @@ -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

Why don't you use the gpio versioning from here:

https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/gpio/gpio-rockchip.c#n30

I think it's best to reuse the definitions from Linux kernel, as it's 
already implemented there.


> +#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

ditto

> +#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 +68,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 +80,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 +101,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;
>   }
> @@ -86,14 +119,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(&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
>   }
>   
>   /* Simple SPL interface to GPIOs */
> -#ifdef CONFIG_SPL_BUILD
> +#if defined(CONFIG_SPL_BUILD) && (GPIO_VER == 1)
>   
>   enum {
>   	PULL_NONE_1V8 = 0,
> @@ -143,7 +176,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);
> diff --git a/drivers/pinctrl/rockchip/Makefile b/drivers/pinctrl/rockchip/Makefile
> index 9884355473..90461ae881 100644
> --- a/drivers/pinctrl/rockchip/Makefile
> +++ b/drivers/pinctrl/rockchip/Makefile
> @@ -14,5 +14,6 @@ obj-$(CONFIG_ROCKCHIP_RK3308) += pinctrl-rk3308.o
>   obj-$(CONFIG_ROCKCHIP_RK3328) += pinctrl-rk3328.o
>   obj-$(CONFIG_ROCKCHIP_RK3368) += pinctrl-rk3368.o
>   obj-$(CONFIG_ROCKCHIP_RK3399) += pinctrl-rk3399.o
> +obj-$(CONFIG_ROCKCHIP_RK3568) += pinctrl-rk3568.o
>   obj-$(CONFIG_ROCKCHIP_RV1108) += pinctrl-rv1108.o
>   obj-$(CONFIG_ROCKCHIP_RV1126) += pinctrl-rv1126.o
> diff --git a/drivers/pinctrl/rockchip/pinctrl-rk3568.c b/drivers/pinctrl/rockchip/pinctrl-rk3568.c
> new file mode 100644
> index 0000000000..dce1c1e7ee
> --- /dev/null
> +++ b/drivers/pinctrl/rockchip/pinctrl-rk3568.c
> @@ -0,0 +1,453 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * (C) Copyright 2020 Rockchip Electronics Co., Ltd
> + */
> +
> +#include <common.h>
> +#include <dm.h>
> +#include <dm/pinctrl.h>
> +#include <regmap.h>
> +#include <syscon.h>
> +
> +#include "pinctrl-rockchip.h"
> +
> +static struct rockchip_mux_route_data rk3568_mux_route_data[] = {
> +	/* CAN0 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO0, RK_PB3, RK_FUNC_2, 0x0300, RK_GENMASK_VAL(0, 0, 0)),
> +	/* CAN0 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO2, RK_PA1, RK_FUNC_4, 0x0300, RK_GENMASK_VAL(0, 0, 1)),
> +	/* CAN1 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO1, RK_PA1, RK_FUNC_3, 0x0300, RK_GENMASK_VAL(2, 2, 0)),
> +	/* CAN1 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO4, RK_PC3, RK_FUNC_3, 0x0300, RK_GENMASK_VAL(2, 2, 1)),
> +	/* CAN2 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO4, RK_PB5, RK_FUNC_3, 0x0300, RK_GENMASK_VAL(4, 4, 0)),
> +	/* CAN2 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO2, RK_PB2, RK_FUNC_4, 0x0300, RK_GENMASK_VAL(4, 4, 1)),
> +	/* EDPDP_HPDIN IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO4, RK_PC4, RK_FUNC_1, 0x0300, RK_GENMASK_VAL(6, 6, 0)),
> +	/* EDPDP_HPDIN IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO0, RK_PC2, RK_FUNC_2, 0x0300, RK_GENMASK_VAL(6, 6, 1)),
> +	/* GMAC1 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO3, RK_PB1, RK_FUNC_3, 0x0300, RK_GENMASK_VAL(8, 8, 0)),
> +	/* GMAC1 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO4, RK_PA7, RK_FUNC_3, 0x0300, RK_GENMASK_VAL(8, 8, 1)),
> +	/* HDMITX IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO4, RK_PD1, RK_FUNC_1, 0x0300, RK_GENMASK_VAL(10, 10, 0)),
> +	/* HDMITX IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO0, RK_PC7, RK_FUNC_1, 0x0300, RK_GENMASK_VAL(10, 10, 1)),
> +	/* I2C2 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO0, RK_PB6, RK_FUNC_1, 0x0300, RK_GENMASK_VAL(14, 14, 0)),
> +	/* I2C2 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO4, RK_PB4, RK_FUNC_1, 0x0300, RK_GENMASK_VAL(14, 14, 1)),
> +	/* I2C3 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO1, RK_PA0, RK_FUNC_1, 0x0304, RK_GENMASK_VAL(0, 0, 0)),
> +	/* I2C3 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO3, RK_PB6, RK_FUNC_4, 0x0304, RK_GENMASK_VAL(0, 0, 1)),
> +	/* I2C4 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO4, RK_PB2, RK_FUNC_1, 0x0304, RK_GENMASK_VAL(2, 2, 0)),
> +	/* I2C4 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO2, RK_PB1, RK_FUNC_2, 0x0304, RK_GENMASK_VAL(2, 2, 1)),
> +	/* I2C5 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO3, RK_PB4, RK_FUNC_4, 0x0304, RK_GENMASK_VAL(4, 4, 0)),
> +	/* I2C5 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO4, RK_PD0, RK_FUNC_2, 0x0304, RK_GENMASK_VAL(4, 4, 1)),
> +	/* PWM4 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0304, RK_GENMASK_VAL(6, 6, 0)),
> +	/* PWM4 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0304, RK_GENMASK_VAL(6, 6, 1)),
> +	/* PWM5 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0304, RK_GENMASK_VAL(8, 8, 0)),
> +	/* PWM5 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0304, RK_GENMASK_VAL(8, 8, 1)),
> +	/* PWM6 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0304, RK_GENMASK_VAL(10, 10, 0)),
> +	/* PWM6 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0304, RK_GENMASK_VAL(10, 10, 1)),
> +	/* PWM7 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0304, RK_GENMASK_VAL(12, 12, 0)),
> +	/* PWM7 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0304, RK_GENMASK_VAL(12, 12, 1)),
> +	/* PWM8 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0304, RK_GENMASK_VAL(14, 14, 0)),
> +	/* PWM8 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0304, RK_GENMASK_VAL(14, 14, 1)),
> +	/* PWM9 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(0, 0, 0)),
> +	/* PWM9 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(0, 0, 1)),
> +	/* PWM10 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(2, 2, 0)),
> +	/* PWM10 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(2, 2, 1)),
> +	/* PWM11 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(4, 4, 0)),
> +	/* PWM11 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(4, 4, 1)),
> +	/* PWM12 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(6, 6, 0)),
> +	/* PWM12 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(6, 6, 1)),
> +	/* PWM13 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(8, 8, 0)),
> +	/* PWM13 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(8, 8, 1)),
> +	/* PWM14 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(10, 10, 0)),
> +	/* PWM14 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(10, 10, 1)),
> +	/* PWM15 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(12, 12, 0)),
> +	/* PWM15 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(12, 12, 1)),
> +	/* SDMMC2 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_3, 0x0308, RK_GENMASK_VAL(14, 14, 0)),
> +	/* SDMMC2 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO3, RK_PA5, RK_FUNC_5, 0x0308, RK_GENMASK_VAL(14, 14, 1)),
> +	/* SPI0 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO0, RK_PB5, RK_FUNC_2, 0x030c, RK_GENMASK_VAL(0, 0, 0)),
> +	/* SPI0 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO2, RK_PD3, RK_FUNC_3, 0x030c, RK_GENMASK_VAL(0, 0, 1)),
> +	/* SPI1 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO2, RK_PB5, RK_FUNC_3, 0x030c, RK_GENMASK_VAL(2, 2, 0)),
> +	/* SPI1 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO3, RK_PC3, RK_FUNC_3, 0x030c, RK_GENMASK_VAL(2, 2, 1)),
> +	/* SPI2 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO2, RK_PC1, RK_FUNC_4, 0x030c, RK_GENMASK_VAL(4, 4, 0)),
> +	/* SPI2 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO3, RK_PA0, RK_FUNC_3, 0x030c, RK_GENMASK_VAL(4, 4, 1)),
> +	/* SPI3 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO4, RK_PB3, RK_FUNC_4, 0x030c, RK_GENMASK_VAL(6, 6, 0)),
> +	/* SPI3 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO4, RK_PC2, RK_FUNC_2, 0x030c, RK_GENMASK_VAL(6, 6, 1)),
> +	/* UART1 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO2, RK_PB4, RK_FUNC_2, 0x030c, RK_GENMASK_VAL(8, 8, 0)),
> +	/* UART1 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO0, RK_PD1, RK_FUNC_1, 0x030c, RK_GENMASK_VAL(8, 8, 1)),
> +	/* UART2 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO0, RK_PD1, RK_FUNC_1, 0x030c, RK_GENMASK_VAL(10, 10, 0)),
> +	/* UART2 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO1, RK_PD5, RK_FUNC_2, 0x030c, RK_GENMASK_VAL(10, 10, 1)),
> +	/* UART3 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO1, RK_PA1, RK_FUNC_2, 0x030c, RK_GENMASK_VAL(12, 12, 0)),
> +	/* UART3 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO3, RK_PB7, RK_FUNC_4, 0x030c, RK_GENMASK_VAL(12, 12, 1)),
> +	/* UART4 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO1, RK_PA6, RK_FUNC_2, 0x030c, RK_GENMASK_VAL(14, 14, 0)),
> +	/* UART4 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO3, RK_PB2, RK_FUNC_4, 0x030c, RK_GENMASK_VAL(14, 14, 1)),
> +	/* UART5 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO2, RK_PA2, RK_FUNC_3, 0x0310, RK_GENMASK_VAL(0, 0, 0)),
> +	/* UART5 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO3, RK_PC2, RK_FUNC_4, 0x0310, RK_GENMASK_VAL(0, 0, 1)),
> +	/* UART6 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO2, RK_PA4, RK_FUNC_3, 0x0310, RK_GENMASK_VAL(2, 2, 0)),
> +	/* UART6 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO1, RK_PD5, RK_FUNC_3, 0x0310, RK_GENMASK_VAL(2, 2, 1)),
> +	/* UART7 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO2, RK_PA6, RK_FUNC_3, 0x0310, RK_GENMASK_VAL(5, 4, 0)),
> +	/* UART7 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO3, RK_PC4, RK_FUNC_4, 0x0310, RK_GENMASK_VAL(5, 4, 1)),
> +	/* UART7 IO mux selection M2 */
> +	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0310, RK_GENMASK_VAL(5, 4, 2)),
> +	/* UART8 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO2, RK_PC5, RK_FUNC_3, 0x0310, RK_GENMASK_VAL(6, 6, 0)),
> +	/* UART8 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO2, RK_PD7, RK_FUNC_4, 0x0310, RK_GENMASK_VAL(6, 6, 1)),
> +	/* UART9 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO2, RK_PB0, RK_FUNC_3, 0x0310, RK_GENMASK_VAL(9, 8, 0)),
> +	/* UART9 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO4, RK_PC5, RK_FUNC_4, 0x0310, RK_GENMASK_VAL(9, 8, 1)),
> +	/* UART9 IO mux selection M2 */
> +	MR_TOPGRF(RK_GPIO4, RK_PA4, RK_FUNC_4, 0x0310, RK_GENMASK_VAL(9, 8, 2)),
> +	/* I2S1 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO1, RK_PA2, RK_FUNC_1, 0x0310, RK_GENMASK_VAL(11, 10, 0)),
> +	/* I2S1 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO3, RK_PC6, RK_FUNC_4, 0x0310, RK_GENMASK_VAL(11, 10, 1)),
> +	/* I2S1 IO mux selection M2 */
> +	MR_TOPGRF(RK_GPIO2, RK_PD0, RK_FUNC_5, 0x0310, RK_GENMASK_VAL(11, 10, 2)),
> +	/* I2S2 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO2, RK_PC1, RK_FUNC_1, 0x0310, RK_GENMASK_VAL(12, 12, 0)),
> +	/* I2S2 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO4, RK_PB6, RK_FUNC_5, 0x0310, RK_GENMASK_VAL(12, 12, 1)),
> +	/* I2S3 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO3, RK_PA2, RK_FUNC_4, 0x0310, RK_GENMASK_VAL(14, 14, 0)),
> +	/* I2S3 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO4, RK_PC2, RK_FUNC_5, 0x0310, RK_GENMASK_VAL(14, 14, 1)),
> +	/* PDM IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO1, RK_PA6, RK_FUNC_3, 0x0314, RK_GENMASK_VAL(0, 0, 0)),
> +	/* PDM IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO3, RK_PD6, RK_FUNC_5, 0x0314, RK_GENMASK_VAL(0, 0, 1)),
> +	/* PCIE20 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO0, RK_PA5, RK_FUNC_3, 0x0314, RK_GENMASK_VAL(3, 2, 0)),
> +	/* PCIE20 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO2, RK_PD0, RK_FUNC_4, 0x0314, RK_GENMASK_VAL(3, 2, 1)),
> +	/* PCIE20 IO mux selection M2 */
> +	MR_TOPGRF(RK_GPIO1, RK_PB0, RK_FUNC_4, 0x0314, RK_GENMASK_VAL(3, 2, 2)),
> +	/* PCIE30X1 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO0, RK_PA4, RK_FUNC_3, 0x0314, RK_GENMASK_VAL(5, 4, 0)),
> +	/* PCIE30X1 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO2, RK_PD2, RK_FUNC_4, 0x0314, RK_GENMASK_VAL(5, 4, 1)),
> +	/* PCIE30X1 IO mux selection M2 */
> +	MR_TOPGRF(RK_GPIO1, RK_PA5, RK_FUNC_4, 0x0314, RK_GENMASK_VAL(5, 4, 2)),
> +	/* PCIE30X2 IO mux selection M0 */
> +	MR_TOPGRF(RK_GPIO0, RK_PA6, RK_FUNC_2, 0x0314, RK_GENMASK_VAL(7, 6, 0)),
> +	/* PCIE30X2 IO mux selection M1 */
> +	MR_TOPGRF(RK_GPIO2, RK_PD4, RK_FUNC_4, 0x0314, RK_GENMASK_VAL(7, 6, 1)),
> +	/* PCIE30X2 IO mux selection M2 */
> +	MR_TOPGRF(RK_GPIO4, RK_PC2, RK_FUNC_4, 0x0314, RK_GENMASK_VAL(7, 6, 2)),
> +};
> +
> +static int rk3568_set_mux(struct rockchip_pin_bank *bank, int pin, int mux)
> +{
> +	struct rockchip_pinctrl_priv *priv = bank->priv;
> +	int iomux_num = (pin / 8);
> +	struct regmap *regmap;
> +	int reg, ret, mask;
> +	u8 bit;
> +	u32 data;
> +
> +	debug("setting mux of GPIO%d-%d to %d\n", bank->bank_num, pin, mux);
> +
> +	if (bank->iomux[iomux_num].type & IOMUX_SOURCE_PMU)
> +		regmap = priv->regmap_pmu;
> +	else
> +		regmap = priv->regmap_base;
> +
> +	reg = bank->iomux[iomux_num].offset;
> +	if ((pin % 8) >= 4)
> +		reg += 0x4;
> +	bit = (pin % 4) * 4;
> +	mask = 0xf;
> +
> +	data = (mask << (bit + 16));
> +	data |= (mux & mask) << bit;
> +	ret = regmap_write(regmap, reg, data);
> +
> +	return ret;
> +}
> +
> +#define RK3568_PULL_PMU_OFFSET		0x20
> +#define RK3568_PULL_GRF_OFFSET		0x80
> +#define RK3568_PULL_BITS_PER_PIN	2
> +#define RK3568_PULL_PINS_PER_REG	8
> +#define RK3568_PULL_BANK_STRIDE		0x10
> +
> +static void rk3568_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank,
> +					 int pin_num, struct regmap **regmap,
> +					 int *reg, u8 *bit)
> +{
> +	struct rockchip_pinctrl_priv *info = bank->priv;
> +
> +	if (bank->bank_num == 0) {
> +		*regmap = info->regmap_pmu;
> +		*reg = RK3568_PULL_PMU_OFFSET;
> +		*reg += bank->bank_num * RK3568_PULL_BANK_STRIDE;
> +	} else {
> +		*regmap = info->regmap_base;
> +		*reg = RK3568_PULL_GRF_OFFSET;
> +		*reg += (bank->bank_num - 1) * RK3568_PULL_BANK_STRIDE;
> +	}
> +
> +	*reg += ((pin_num / RK3568_PULL_PINS_PER_REG) * 4);
> +	*bit = (pin_num % RK3568_PULL_PINS_PER_REG);
> +	*bit *= RK3568_PULL_BITS_PER_PIN;
> +}
> +
> +#define RK3568_DRV_PMU_OFFSET		0x70
> +#define RK3568_DRV_GRF_OFFSET		0x200
> +#define RK3568_DRV_BITS_PER_PIN		8
> +#define RK3568_DRV_PINS_PER_REG		2
> +#define RK3568_DRV_BANK_STRIDE		0x40
> +
> +static void rk3568_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank,
> +					int pin_num, struct regmap **regmap,
> +					int *reg, u8 *bit)
> +{
> +	struct rockchip_pinctrl_priv *info = bank->priv;
> +
> +	/* The first 32 pins of the first bank are located in PMU */
> +	if (bank->bank_num == 0) {
> +		*regmap = info->regmap_pmu;
> +		*reg = RK3568_DRV_PMU_OFFSET;
> +	} else {
> +		*regmap = info->regmap_base;
> +		*reg = RK3568_DRV_GRF_OFFSET;
> +		*reg += (bank->bank_num - 1) * RK3568_DRV_BANK_STRIDE;
> +	}
> +
> +	*reg += ((pin_num / RK3568_DRV_PINS_PER_REG) * 4);
> +	*bit = (pin_num % RK3568_DRV_PINS_PER_REG);
> +	*bit *= RK3568_DRV_BITS_PER_PIN;
> +}
> +
> +#define RK3568_SCHMITT_BITS_PER_PIN		2
> +#define RK3568_SCHMITT_PINS_PER_REG		8
> +#define RK3568_SCHMITT_BANK_STRIDE		0x10
> +#define RK3568_SCHMITT_GRF_OFFSET		0xc0
> +#define RK3568_SCHMITT_PMUGRF_OFFSET		0x30
> +
> +static int rk3568_calc_schmitt_reg_and_bit(struct rockchip_pin_bank *bank,
> +					   int pin_num, struct regmap **regmap,
> +					   int *reg, u8 *bit)
> +{
> +	struct rockchip_pinctrl_priv *info = bank->priv;
> +
> +	if (bank->bank_num == 0) {
> +		*regmap = info->regmap_pmu;
> +		*reg = RK3568_SCHMITT_PMUGRF_OFFSET;
> +	} else {
> +		*regmap = info->regmap_base;
> +		*reg = RK3568_SCHMITT_GRF_OFFSET;
> +		*reg += (bank->bank_num - 1) * RK3568_SCHMITT_BANK_STRIDE;
> +	}
> +
> +	*reg += ((pin_num / RK3568_SCHMITT_PINS_PER_REG) * 4);
> +	*bit = pin_num % RK3568_SCHMITT_PINS_PER_REG;
> +	*bit *= RK3568_SCHMITT_BITS_PER_PIN;
> +
> +	return 0;
> +}
> +
> +static int rk3568_set_pull(struct rockchip_pin_bank *bank,
> +			   int pin_num, int pull)
> +{
> +	struct regmap *regmap;
> +	int reg, ret;
> +	u8 bit, type;
> +	u32 data;
> +
> +	if (pull == PIN_CONFIG_BIAS_PULL_PIN_DEFAULT)
> +		return -EOPNOTSUPP;
> +
> +	rk3568_calc_pull_reg_and_bit(bank, pin_num, &regmap, &reg, &bit);
> +	type = bank->pull_type[pin_num / 8];
> +	ret = rockchip_translate_pull_value(type, pull);
> +	if (ret < 0) {
> +		debug("unsupported pull setting %d\n", pull);
> +		return ret;
> +	}
> +
> +	/* enable the write to the equivalent lower bits */
> +	data = ((1 << ROCKCHIP_PULL_BITS_PER_PIN) - 1) << (bit + 16);
> +
> +	data |= (ret << bit);
> +	ret = regmap_write(regmap, reg, data);
> +
> +	return ret;
> +}
> +
> +static int rk3568_set_drive(struct rockchip_pin_bank *bank,
> +			    int pin_num, int strength)
> +{
> +	struct regmap *regmap;
> +	int reg;
> +	u32 data;
> +	u8 bit;
> +	int drv = (1 << (strength + 1)) - 1;
> +	int ret = 0;
> +
> +	rk3568_calc_drv_reg_and_bit(bank, pin_num, &regmap, &reg, &bit);
> +
> +	/* enable the write to the equivalent lower bits */
> +	data = ((1 << RK3568_DRV_BITS_PER_PIN) - 1) << (bit + 16);
> +	data |= (drv << bit);
> +
> +	ret = regmap_write(regmap, reg, data);
> +	if (ret)
> +		return ret;
> +
> +	if (bank->bank_num == 1 && pin_num == 21)
> +		reg = 0x0840;
> +	else if (bank->bank_num == 2 && pin_num == 2)
> +		reg = 0x0844;
> +	else if (bank->bank_num == 2 && pin_num == 8)
> +		reg = 0x0848;
> +	else if (bank->bank_num == 3 && pin_num == 0)
> +		reg = 0x084c;
> +	else if (bank->bank_num == 3 && pin_num == 6)
> +		reg = 0x0850;
> +	else if (bank->bank_num == 4 && pin_num == 0)
> +		reg = 0x0854;
> +	else
> +		return 0;
> +
> +	data = ((1 << RK3568_DRV_BITS_PER_PIN) - 1) << 16;
> +	data |= drv;
> +
> +	return regmap_write(regmap, reg, data);
> +}
> +
> +static int rk3568_set_schmitt(struct rockchip_pin_bank *bank,
> +			      int pin_num, int enable)
> +{
> +	struct regmap *regmap;
> +	int reg;
> +	u32 data;
> +	u8 bit;
> +
> +	rk3568_calc_schmitt_reg_and_bit(bank, pin_num, &regmap, &reg, &bit);
> +
> +	/* enable the write to the equivalent lower bits */
> +	data = ((1 << RK3568_SCHMITT_BITS_PER_PIN) - 1) << (bit + 16);
> +	data |= (enable << bit);
> +
> +	return regmap_write(regmap, reg, data);
> +}
> +
> +static struct rockchip_pin_bank rk3568_pin_banks[] = {
> +	PIN_BANK_IOMUX_FLAGS(0, 32, "gpio0", IOMUX_SOURCE_PMU | IOMUX_WIDTH_4BIT,
> +			     IOMUX_SOURCE_PMU | IOMUX_WIDTH_4BIT,
> +			     IOMUX_SOURCE_PMU | IOMUX_WIDTH_4BIT,
> +			     IOMUX_SOURCE_PMU | IOMUX_WIDTH_4BIT),
> +	PIN_BANK_IOMUX_FLAGS(1, 32, "gpio1", IOMUX_WIDTH_4BIT,
> +			     IOMUX_WIDTH_4BIT,
> +			     IOMUX_WIDTH_4BIT,
> +			     IOMUX_WIDTH_4BIT),
> +	PIN_BANK_IOMUX_FLAGS(2, 32, "gpio2", IOMUX_WIDTH_4BIT,
> +			     IOMUX_WIDTH_4BIT,
> +			     IOMUX_WIDTH_4BIT,
> +			     IOMUX_WIDTH_4BIT),
> +	PIN_BANK_IOMUX_FLAGS(3, 32, "gpio3", IOMUX_WIDTH_4BIT,
> +			     IOMUX_WIDTH_4BIT,
> +			     IOMUX_WIDTH_4BIT,
> +			     IOMUX_WIDTH_4BIT),
> +	PIN_BANK_IOMUX_FLAGS(4, 32, "gpio4", IOMUX_WIDTH_4BIT,
> +			     IOMUX_WIDTH_4BIT,
> +			     IOMUX_WIDTH_4BIT,
> +			     IOMUX_WIDTH_4BIT),
> +};
> +
> +static const struct rockchip_pin_ctrl rk3568_pin_ctrl = {
> +	.pin_banks		= rk3568_pin_banks,
> +	.nr_banks		= ARRAY_SIZE(rk3568_pin_banks),
> +	.nr_pins		= 160,
> +	.grf_mux_offset		= 0x0,
> +	.pmu_mux_offset		= 0x0,
> +	.iomux_routes		= rk3568_mux_route_data,
> +	.niomux_routes		= ARRAY_SIZE(rk3568_mux_route_data),
> +	.set_mux		= rk3568_set_mux,
> +	.set_pull		= rk3568_set_pull,
> +	.set_drive		= rk3568_set_drive,
> +	.set_schmitt		= rk3568_set_schmitt,
> +};
> +
> +static const struct udevice_id rk3568_pinctrl_ids[] = {
> +	{
> +		.compatible = "rockchip,rk3568-pinctrl",
> +		.data = (ulong)&rk3568_pin_ctrl
> +	},
> +	{ }
> +};
> +
> +U_BOOT_DRIVER(pinctrl_rk3568) = {
> +	.name		= "rockchip_rk3568_pinctrl",
> +	.id		= UCLASS_PINCTRL,
> +	.of_match	= rk3568_pinctrl_ids,
> +	.priv_auto = sizeof(struct rockchip_pinctrl_priv),
> +	.ops		= &rockchip_pinctrl_ops,
> +#if !IS_ENABLED(CONFIG_OF_PLATDATA)

you should use here #if IS_ENABLED(CONFIG_OF_REAL)

> +	.bind		= dm_scan_fdt_dev,
> +#endif
> +	.probe		= rockchip_pinctrl_probe,
> +};
> diff --git a/drivers/pinctrl/rockchip/pinctrl-rockchip-core.c b/drivers/pinctrl/rockchip/pinctrl-rockchip-core.c
> index d9d61fdb72..1481c1e51c 100644
> --- a/drivers/pinctrl/rockchip/pinctrl-rockchip-core.c
> +++ b/drivers/pinctrl/rockchip/pinctrl-rockchip-core.c
> @@ -433,7 +433,7 @@ static int rockchip_pinctrl_set_state(struct udevice *dev,
>   	int prop_len, param;
>   	const u32 *data;
>   	ofnode node;
> -#ifdef CONFIG_OF_LIVE
> +#if CONFIG_IS_ENABLED(OF_LIVE)
>   	const struct device_node *np;
>   	struct property *pp;
>   #else
> @@ -473,7 +473,7 @@ static int rockchip_pinctrl_set_state(struct udevice *dev,
>   		node = ofnode_get_by_phandle(conf);
>   		if (!ofnode_valid(node))
>   			return -ENODEV;
> -#ifdef CONFIG_OF_LIVE
> +#if CONFIG_IS_ENABLED(OF_LIVE)
>   		np = ofnode_to_np(node);
>   		for (pp = np->properties; pp; pp = pp->next) {
>   			prop_name = pp->name;
> @@ -548,13 +548,15 @@ static struct rockchip_pin_ctrl *rockchip_pinctrl_get_soc_data(struct udevice *d
>   
>   			/* preset iomux offset value, set new start value */
>   			if (iom->offset >= 0) {
> -				if (iom->type & IOMUX_SOURCE_PMU)
> +				if ((iom->type & IOMUX_SOURCE_PMU) || \
> +				    (iom->type & IOMUX_L_SOURCE_PMU))
>   					pmu_offs = iom->offset;
>   				else
>   					grf_offs = iom->offset;
>   			} else { /* set current iomux offset */
> -				iom->offset = (iom->type & IOMUX_SOURCE_PMU) ?
> -							pmu_offs : grf_offs;
> +				iom->offset = ((iom->type & IOMUX_SOURCE_PMU) ||
> +						(iom->type & IOMUX_L_SOURCE_PMU)) ?
> +						pmu_offs : grf_offs;
>   			}
>   
>   			/* preset drv offset value, set new start value */
Simon Glass March 1, 2023, 3:02 p.m. UTC | #6
Hi,

On Wed, 1 Mar 2023 at 01:25, Eugen Hristev <eugen.hristev@collabora.com> wrote:
>
> On 2/14/23 00:27, Chris Morgan wrote:
> > From: Chris Morgan <macromorgan@hotmail.com>
> >
> > Add support for the newer GPIO controller used by the rk356x series,
> > as well as the pinctrl device for the rk356x series. The GPIOv2
> > controller has a write enable bit for some registers which differs
> > from the older versions of the GPIO controller.
> >
> > Signed-off-by: Peter Geis <pgwipeout@gmail.com>
> > Signed-off-by: Chris Morgan <macromorgan@hotmail.com>
>
> Hi Chris,
>
> In the file below you have added
>
>  > + * Jianqun Xu, Software Engineering, <jay.xu@rock-chips.com>.
>
> as copyright owner, maybe add him as co-author of this patch ? Or what
> was his contribution ?
>
>
> > ---
> >   arch/arm/include/asm/arch-rockchip/gpio.h     |  38 ++
> >   drivers/gpio/rk_gpio.c                        |  49 +-
> >   drivers/pinctrl/rockchip/Makefile             |   1 +
> >   drivers/pinctrl/rockchip/pinctrl-rk3568.c     | 453 ++++++++++++++++++
> >   .../pinctrl/rockchip/pinctrl-rockchip-core.c  |  12 +-
> >   5 files changed, 540 insertions(+), 13 deletions(-)
> >   create mode 100644 drivers/pinctrl/rockchip/pinctrl-rk3568.c
> >
> > 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)
>
> Can't we figure out from the compatible which struct layout to use ?
> Using conditionally compile code makes things difficult to read after
> some time.

Yes, we must not add arch-specific CONFIG things to drivers. Handle it
at runtime instead, i.e. the driver should handle both.

Regards,
SImon
diff mbox series

Patch

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 98a79b5f4d..e2653be058 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, <superpeter.cai@gmail.com>.
+ * Jianqun Xu, Software Engineering, <jay.xu@rock-chips.com>.
  */
 
 #include <common.h>
 #include <dm.h>
+#include <dm/of_access.h>
+#include <dm/device_compat.h>
 #include <syscon.h>
 #include <linux/errno.h>
 #include <asm/gpio.h>
@@ -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 +68,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 +80,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 +101,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;
 }
@@ -86,14 +119,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(&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
 }
 
 /* Simple SPL interface to GPIOs */
-#ifdef CONFIG_SPL_BUILD
+#if defined(CONFIG_SPL_BUILD) && (GPIO_VER == 1)
 
 enum {
 	PULL_NONE_1V8 = 0,
@@ -143,7 +176,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);
diff --git a/drivers/pinctrl/rockchip/Makefile b/drivers/pinctrl/rockchip/Makefile
index 9884355473..90461ae881 100644
--- a/drivers/pinctrl/rockchip/Makefile
+++ b/drivers/pinctrl/rockchip/Makefile
@@ -14,5 +14,6 @@  obj-$(CONFIG_ROCKCHIP_RK3308) += pinctrl-rk3308.o
 obj-$(CONFIG_ROCKCHIP_RK3328) += pinctrl-rk3328.o
 obj-$(CONFIG_ROCKCHIP_RK3368) += pinctrl-rk3368.o
 obj-$(CONFIG_ROCKCHIP_RK3399) += pinctrl-rk3399.o
+obj-$(CONFIG_ROCKCHIP_RK3568) += pinctrl-rk3568.o
 obj-$(CONFIG_ROCKCHIP_RV1108) += pinctrl-rv1108.o
 obj-$(CONFIG_ROCKCHIP_RV1126) += pinctrl-rv1126.o
diff --git a/drivers/pinctrl/rockchip/pinctrl-rk3568.c b/drivers/pinctrl/rockchip/pinctrl-rk3568.c
new file mode 100644
index 0000000000..dce1c1e7ee
--- /dev/null
+++ b/drivers/pinctrl/rockchip/pinctrl-rk3568.c
@@ -0,0 +1,453 @@ 
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2020 Rockchip Electronics Co., Ltd
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <dm/pinctrl.h>
+#include <regmap.h>
+#include <syscon.h>
+
+#include "pinctrl-rockchip.h"
+
+static struct rockchip_mux_route_data rk3568_mux_route_data[] = {
+	/* CAN0 IO mux selection M0 */
+	MR_TOPGRF(RK_GPIO0, RK_PB3, RK_FUNC_2, 0x0300, RK_GENMASK_VAL(0, 0, 0)),
+	/* CAN0 IO mux selection M1 */
+	MR_TOPGRF(RK_GPIO2, RK_PA1, RK_FUNC_4, 0x0300, RK_GENMASK_VAL(0, 0, 1)),
+	/* CAN1 IO mux selection M0 */
+	MR_TOPGRF(RK_GPIO1, RK_PA1, RK_FUNC_3, 0x0300, RK_GENMASK_VAL(2, 2, 0)),
+	/* CAN1 IO mux selection M1 */
+	MR_TOPGRF(RK_GPIO4, RK_PC3, RK_FUNC_3, 0x0300, RK_GENMASK_VAL(2, 2, 1)),
+	/* CAN2 IO mux selection M0 */
+	MR_TOPGRF(RK_GPIO4, RK_PB5, RK_FUNC_3, 0x0300, RK_GENMASK_VAL(4, 4, 0)),
+	/* CAN2 IO mux selection M1 */
+	MR_TOPGRF(RK_GPIO2, RK_PB2, RK_FUNC_4, 0x0300, RK_GENMASK_VAL(4, 4, 1)),
+	/* EDPDP_HPDIN IO mux selection M0 */
+	MR_TOPGRF(RK_GPIO4, RK_PC4, RK_FUNC_1, 0x0300, RK_GENMASK_VAL(6, 6, 0)),
+	/* EDPDP_HPDIN IO mux selection M1 */
+	MR_TOPGRF(RK_GPIO0, RK_PC2, RK_FUNC_2, 0x0300, RK_GENMASK_VAL(6, 6, 1)),
+	/* GMAC1 IO mux selection M0 */
+	MR_TOPGRF(RK_GPIO3, RK_PB1, RK_FUNC_3, 0x0300, RK_GENMASK_VAL(8, 8, 0)),
+	/* GMAC1 IO mux selection M1 */
+	MR_TOPGRF(RK_GPIO4, RK_PA7, RK_FUNC_3, 0x0300, RK_GENMASK_VAL(8, 8, 1)),
+	/* HDMITX IO mux selection M0 */
+	MR_TOPGRF(RK_GPIO4, RK_PD1, RK_FUNC_1, 0x0300, RK_GENMASK_VAL(10, 10, 0)),
+	/* HDMITX IO mux selection M1 */
+	MR_TOPGRF(RK_GPIO0, RK_PC7, RK_FUNC_1, 0x0300, RK_GENMASK_VAL(10, 10, 1)),
+	/* I2C2 IO mux selection M0 */
+	MR_TOPGRF(RK_GPIO0, RK_PB6, RK_FUNC_1, 0x0300, RK_GENMASK_VAL(14, 14, 0)),
+	/* I2C2 IO mux selection M1 */
+	MR_TOPGRF(RK_GPIO4, RK_PB4, RK_FUNC_1, 0x0300, RK_GENMASK_VAL(14, 14, 1)),
+	/* I2C3 IO mux selection M0 */
+	MR_TOPGRF(RK_GPIO1, RK_PA0, RK_FUNC_1, 0x0304, RK_GENMASK_VAL(0, 0, 0)),
+	/* I2C3 IO mux selection M1 */
+	MR_TOPGRF(RK_GPIO3, RK_PB6, RK_FUNC_4, 0x0304, RK_GENMASK_VAL(0, 0, 1)),
+	/* I2C4 IO mux selection M0 */
+	MR_TOPGRF(RK_GPIO4, RK_PB2, RK_FUNC_1, 0x0304, RK_GENMASK_VAL(2, 2, 0)),
+	/* I2C4 IO mux selection M1 */
+	MR_TOPGRF(RK_GPIO2, RK_PB1, RK_FUNC_2, 0x0304, RK_GENMASK_VAL(2, 2, 1)),
+	/* I2C5 IO mux selection M0 */
+	MR_TOPGRF(RK_GPIO3, RK_PB4, RK_FUNC_4, 0x0304, RK_GENMASK_VAL(4, 4, 0)),
+	/* I2C5 IO mux selection M1 */
+	MR_TOPGRF(RK_GPIO4, RK_PD0, RK_FUNC_2, 0x0304, RK_GENMASK_VAL(4, 4, 1)),
+	/* PWM4 IO mux selection M0 */
+	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0304, RK_GENMASK_VAL(6, 6, 0)),
+	/* PWM4 IO mux selection M1 */
+	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0304, RK_GENMASK_VAL(6, 6, 1)),
+	/* PWM5 IO mux selection M0 */
+	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0304, RK_GENMASK_VAL(8, 8, 0)),
+	/* PWM5 IO mux selection M1 */
+	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0304, RK_GENMASK_VAL(8, 8, 1)),
+	/* PWM6 IO mux selection M0 */
+	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0304, RK_GENMASK_VAL(10, 10, 0)),
+	/* PWM6 IO mux selection M1 */
+	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0304, RK_GENMASK_VAL(10, 10, 1)),
+	/* PWM7 IO mux selection M0 */
+	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0304, RK_GENMASK_VAL(12, 12, 0)),
+	/* PWM7 IO mux selection M1 */
+	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0304, RK_GENMASK_VAL(12, 12, 1)),
+	/* PWM8 IO mux selection M0 */
+	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0304, RK_GENMASK_VAL(14, 14, 0)),
+	/* PWM8 IO mux selection M1 */
+	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0304, RK_GENMASK_VAL(14, 14, 1)),
+	/* PWM9 IO mux selection M0 */
+	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(0, 0, 0)),
+	/* PWM9 IO mux selection M1 */
+	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(0, 0, 1)),
+	/* PWM10 IO mux selection M0 */
+	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(2, 2, 0)),
+	/* PWM10 IO mux selection M1 */
+	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(2, 2, 1)),
+	/* PWM11 IO mux selection M0 */
+	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(4, 4, 0)),
+	/* PWM11 IO mux selection M1 */
+	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(4, 4, 1)),
+	/* PWM12 IO mux selection M0 */
+	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(6, 6, 0)),
+	/* PWM12 IO mux selection M1 */
+	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(6, 6, 1)),
+	/* PWM13 IO mux selection M0 */
+	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(8, 8, 0)),
+	/* PWM13 IO mux selection M1 */
+	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(8, 8, 1)),
+	/* PWM14 IO mux selection M0 */
+	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(10, 10, 0)),
+	/* PWM14 IO mux selection M1 */
+	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(10, 10, 1)),
+	/* PWM15 IO mux selection M0 */
+	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(12, 12, 0)),
+	/* PWM15 IO mux selection M1 */
+	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(12, 12, 1)),
+	/* SDMMC2 IO mux selection M0 */
+	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_3, 0x0308, RK_GENMASK_VAL(14, 14, 0)),
+	/* SDMMC2 IO mux selection M1 */
+	MR_TOPGRF(RK_GPIO3, RK_PA5, RK_FUNC_5, 0x0308, RK_GENMASK_VAL(14, 14, 1)),
+	/* SPI0 IO mux selection M0 */
+	MR_TOPGRF(RK_GPIO0, RK_PB5, RK_FUNC_2, 0x030c, RK_GENMASK_VAL(0, 0, 0)),
+	/* SPI0 IO mux selection M1 */
+	MR_TOPGRF(RK_GPIO2, RK_PD3, RK_FUNC_3, 0x030c, RK_GENMASK_VAL(0, 0, 1)),
+	/* SPI1 IO mux selection M0 */
+	MR_TOPGRF(RK_GPIO2, RK_PB5, RK_FUNC_3, 0x030c, RK_GENMASK_VAL(2, 2, 0)),
+	/* SPI1 IO mux selection M1 */
+	MR_TOPGRF(RK_GPIO3, RK_PC3, RK_FUNC_3, 0x030c, RK_GENMASK_VAL(2, 2, 1)),
+	/* SPI2 IO mux selection M0 */
+	MR_TOPGRF(RK_GPIO2, RK_PC1, RK_FUNC_4, 0x030c, RK_GENMASK_VAL(4, 4, 0)),
+	/* SPI2 IO mux selection M1 */
+	MR_TOPGRF(RK_GPIO3, RK_PA0, RK_FUNC_3, 0x030c, RK_GENMASK_VAL(4, 4, 1)),
+	/* SPI3 IO mux selection M0 */
+	MR_TOPGRF(RK_GPIO4, RK_PB3, RK_FUNC_4, 0x030c, RK_GENMASK_VAL(6, 6, 0)),
+	/* SPI3 IO mux selection M1 */
+	MR_TOPGRF(RK_GPIO4, RK_PC2, RK_FUNC_2, 0x030c, RK_GENMASK_VAL(6, 6, 1)),
+	/* UART1 IO mux selection M0 */
+	MR_TOPGRF(RK_GPIO2, RK_PB4, RK_FUNC_2, 0x030c, RK_GENMASK_VAL(8, 8, 0)),
+	/* UART1 IO mux selection M1 */
+	MR_TOPGRF(RK_GPIO0, RK_PD1, RK_FUNC_1, 0x030c, RK_GENMASK_VAL(8, 8, 1)),
+	/* UART2 IO mux selection M0 */
+	MR_TOPGRF(RK_GPIO0, RK_PD1, RK_FUNC_1, 0x030c, RK_GENMASK_VAL(10, 10, 0)),
+	/* UART2 IO mux selection M1 */
+	MR_TOPGRF(RK_GPIO1, RK_PD5, RK_FUNC_2, 0x030c, RK_GENMASK_VAL(10, 10, 1)),
+	/* UART3 IO mux selection M0 */
+	MR_TOPGRF(RK_GPIO1, RK_PA1, RK_FUNC_2, 0x030c, RK_GENMASK_VAL(12, 12, 0)),
+	/* UART3 IO mux selection M1 */
+	MR_TOPGRF(RK_GPIO3, RK_PB7, RK_FUNC_4, 0x030c, RK_GENMASK_VAL(12, 12, 1)),
+	/* UART4 IO mux selection M0 */
+	MR_TOPGRF(RK_GPIO1, RK_PA6, RK_FUNC_2, 0x030c, RK_GENMASK_VAL(14, 14, 0)),
+	/* UART4 IO mux selection M1 */
+	MR_TOPGRF(RK_GPIO3, RK_PB2, RK_FUNC_4, 0x030c, RK_GENMASK_VAL(14, 14, 1)),
+	/* UART5 IO mux selection M0 */
+	MR_TOPGRF(RK_GPIO2, RK_PA2, RK_FUNC_3, 0x0310, RK_GENMASK_VAL(0, 0, 0)),
+	/* UART5 IO mux selection M1 */
+	MR_TOPGRF(RK_GPIO3, RK_PC2, RK_FUNC_4, 0x0310, RK_GENMASK_VAL(0, 0, 1)),
+	/* UART6 IO mux selection M0 */
+	MR_TOPGRF(RK_GPIO2, RK_PA4, RK_FUNC_3, 0x0310, RK_GENMASK_VAL(2, 2, 0)),
+	/* UART6 IO mux selection M1 */
+	MR_TOPGRF(RK_GPIO1, RK_PD5, RK_FUNC_3, 0x0310, RK_GENMASK_VAL(2, 2, 1)),
+	/* UART7 IO mux selection M0 */
+	MR_TOPGRF(RK_GPIO2, RK_PA6, RK_FUNC_3, 0x0310, RK_GENMASK_VAL(5, 4, 0)),
+	/* UART7 IO mux selection M1 */
+	MR_TOPGRF(RK_GPIO3, RK_PC4, RK_FUNC_4, 0x0310, RK_GENMASK_VAL(5, 4, 1)),
+	/* UART7 IO mux selection M2 */
+	MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0310, RK_GENMASK_VAL(5, 4, 2)),
+	/* UART8 IO mux selection M0 */
+	MR_TOPGRF(RK_GPIO2, RK_PC5, RK_FUNC_3, 0x0310, RK_GENMASK_VAL(6, 6, 0)),
+	/* UART8 IO mux selection M1 */
+	MR_TOPGRF(RK_GPIO2, RK_PD7, RK_FUNC_4, 0x0310, RK_GENMASK_VAL(6, 6, 1)),
+	/* UART9 IO mux selection M0 */
+	MR_TOPGRF(RK_GPIO2, RK_PB0, RK_FUNC_3, 0x0310, RK_GENMASK_VAL(9, 8, 0)),
+	/* UART9 IO mux selection M1 */
+	MR_TOPGRF(RK_GPIO4, RK_PC5, RK_FUNC_4, 0x0310, RK_GENMASK_VAL(9, 8, 1)),
+	/* UART9 IO mux selection M2 */
+	MR_TOPGRF(RK_GPIO4, RK_PA4, RK_FUNC_4, 0x0310, RK_GENMASK_VAL(9, 8, 2)),
+	/* I2S1 IO mux selection M0 */
+	MR_TOPGRF(RK_GPIO1, RK_PA2, RK_FUNC_1, 0x0310, RK_GENMASK_VAL(11, 10, 0)),
+	/* I2S1 IO mux selection M1 */
+	MR_TOPGRF(RK_GPIO3, RK_PC6, RK_FUNC_4, 0x0310, RK_GENMASK_VAL(11, 10, 1)),
+	/* I2S1 IO mux selection M2 */
+	MR_TOPGRF(RK_GPIO2, RK_PD0, RK_FUNC_5, 0x0310, RK_GENMASK_VAL(11, 10, 2)),
+	/* I2S2 IO mux selection M0 */
+	MR_TOPGRF(RK_GPIO2, RK_PC1, RK_FUNC_1, 0x0310, RK_GENMASK_VAL(12, 12, 0)),
+	/* I2S2 IO mux selection M1 */
+	MR_TOPGRF(RK_GPIO4, RK_PB6, RK_FUNC_5, 0x0310, RK_GENMASK_VAL(12, 12, 1)),
+	/* I2S3 IO mux selection M0 */
+	MR_TOPGRF(RK_GPIO3, RK_PA2, RK_FUNC_4, 0x0310, RK_GENMASK_VAL(14, 14, 0)),
+	/* I2S3 IO mux selection M1 */
+	MR_TOPGRF(RK_GPIO4, RK_PC2, RK_FUNC_5, 0x0310, RK_GENMASK_VAL(14, 14, 1)),
+	/* PDM IO mux selection M0 */
+	MR_TOPGRF(RK_GPIO1, RK_PA6, RK_FUNC_3, 0x0314, RK_GENMASK_VAL(0, 0, 0)),
+	/* PDM IO mux selection M1 */
+	MR_TOPGRF(RK_GPIO3, RK_PD6, RK_FUNC_5, 0x0314, RK_GENMASK_VAL(0, 0, 1)),
+	/* PCIE20 IO mux selection M0 */
+	MR_TOPGRF(RK_GPIO0, RK_PA5, RK_FUNC_3, 0x0314, RK_GENMASK_VAL(3, 2, 0)),
+	/* PCIE20 IO mux selection M1 */
+	MR_TOPGRF(RK_GPIO2, RK_PD0, RK_FUNC_4, 0x0314, RK_GENMASK_VAL(3, 2, 1)),
+	/* PCIE20 IO mux selection M2 */
+	MR_TOPGRF(RK_GPIO1, RK_PB0, RK_FUNC_4, 0x0314, RK_GENMASK_VAL(3, 2, 2)),
+	/* PCIE30X1 IO mux selection M0 */
+	MR_TOPGRF(RK_GPIO0, RK_PA4, RK_FUNC_3, 0x0314, RK_GENMASK_VAL(5, 4, 0)),
+	/* PCIE30X1 IO mux selection M1 */
+	MR_TOPGRF(RK_GPIO2, RK_PD2, RK_FUNC_4, 0x0314, RK_GENMASK_VAL(5, 4, 1)),
+	/* PCIE30X1 IO mux selection M2 */
+	MR_TOPGRF(RK_GPIO1, RK_PA5, RK_FUNC_4, 0x0314, RK_GENMASK_VAL(5, 4, 2)),
+	/* PCIE30X2 IO mux selection M0 */
+	MR_TOPGRF(RK_GPIO0, RK_PA6, RK_FUNC_2, 0x0314, RK_GENMASK_VAL(7, 6, 0)),
+	/* PCIE30X2 IO mux selection M1 */
+	MR_TOPGRF(RK_GPIO2, RK_PD4, RK_FUNC_4, 0x0314, RK_GENMASK_VAL(7, 6, 1)),
+	/* PCIE30X2 IO mux selection M2 */
+	MR_TOPGRF(RK_GPIO4, RK_PC2, RK_FUNC_4, 0x0314, RK_GENMASK_VAL(7, 6, 2)),
+};
+
+static int rk3568_set_mux(struct rockchip_pin_bank *bank, int pin, int mux)
+{
+	struct rockchip_pinctrl_priv *priv = bank->priv;
+	int iomux_num = (pin / 8);
+	struct regmap *regmap;
+	int reg, ret, mask;
+	u8 bit;
+	u32 data;
+
+	debug("setting mux of GPIO%d-%d to %d\n", bank->bank_num, pin, mux);
+
+	if (bank->iomux[iomux_num].type & IOMUX_SOURCE_PMU)
+		regmap = priv->regmap_pmu;
+	else
+		regmap = priv->regmap_base;
+
+	reg = bank->iomux[iomux_num].offset;
+	if ((pin % 8) >= 4)
+		reg += 0x4;
+	bit = (pin % 4) * 4;
+	mask = 0xf;
+
+	data = (mask << (bit + 16));
+	data |= (mux & mask) << bit;
+	ret = regmap_write(regmap, reg, data);
+
+	return ret;
+}
+
+#define RK3568_PULL_PMU_OFFSET		0x20
+#define RK3568_PULL_GRF_OFFSET		0x80
+#define RK3568_PULL_BITS_PER_PIN	2
+#define RK3568_PULL_PINS_PER_REG	8
+#define RK3568_PULL_BANK_STRIDE		0x10
+
+static void rk3568_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank,
+					 int pin_num, struct regmap **regmap,
+					 int *reg, u8 *bit)
+{
+	struct rockchip_pinctrl_priv *info = bank->priv;
+
+	if (bank->bank_num == 0) {
+		*regmap = info->regmap_pmu;
+		*reg = RK3568_PULL_PMU_OFFSET;
+		*reg += bank->bank_num * RK3568_PULL_BANK_STRIDE;
+	} else {
+		*regmap = info->regmap_base;
+		*reg = RK3568_PULL_GRF_OFFSET;
+		*reg += (bank->bank_num - 1) * RK3568_PULL_BANK_STRIDE;
+	}
+
+	*reg += ((pin_num / RK3568_PULL_PINS_PER_REG) * 4);
+	*bit = (pin_num % RK3568_PULL_PINS_PER_REG);
+	*bit *= RK3568_PULL_BITS_PER_PIN;
+}
+
+#define RK3568_DRV_PMU_OFFSET		0x70
+#define RK3568_DRV_GRF_OFFSET		0x200
+#define RK3568_DRV_BITS_PER_PIN		8
+#define RK3568_DRV_PINS_PER_REG		2
+#define RK3568_DRV_BANK_STRIDE		0x40
+
+static void rk3568_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank,
+					int pin_num, struct regmap **regmap,
+					int *reg, u8 *bit)
+{
+	struct rockchip_pinctrl_priv *info = bank->priv;
+
+	/* The first 32 pins of the first bank are located in PMU */
+	if (bank->bank_num == 0) {
+		*regmap = info->regmap_pmu;
+		*reg = RK3568_DRV_PMU_OFFSET;
+	} else {
+		*regmap = info->regmap_base;
+		*reg = RK3568_DRV_GRF_OFFSET;
+		*reg += (bank->bank_num - 1) * RK3568_DRV_BANK_STRIDE;
+	}
+
+	*reg += ((pin_num / RK3568_DRV_PINS_PER_REG) * 4);
+	*bit = (pin_num % RK3568_DRV_PINS_PER_REG);
+	*bit *= RK3568_DRV_BITS_PER_PIN;
+}
+
+#define RK3568_SCHMITT_BITS_PER_PIN		2
+#define RK3568_SCHMITT_PINS_PER_REG		8
+#define RK3568_SCHMITT_BANK_STRIDE		0x10
+#define RK3568_SCHMITT_GRF_OFFSET		0xc0
+#define RK3568_SCHMITT_PMUGRF_OFFSET		0x30
+
+static int rk3568_calc_schmitt_reg_and_bit(struct rockchip_pin_bank *bank,
+					   int pin_num, struct regmap **regmap,
+					   int *reg, u8 *bit)
+{
+	struct rockchip_pinctrl_priv *info = bank->priv;
+
+	if (bank->bank_num == 0) {
+		*regmap = info->regmap_pmu;
+		*reg = RK3568_SCHMITT_PMUGRF_OFFSET;
+	} else {
+		*regmap = info->regmap_base;
+		*reg = RK3568_SCHMITT_GRF_OFFSET;
+		*reg += (bank->bank_num - 1) * RK3568_SCHMITT_BANK_STRIDE;
+	}
+
+	*reg += ((pin_num / RK3568_SCHMITT_PINS_PER_REG) * 4);
+	*bit = pin_num % RK3568_SCHMITT_PINS_PER_REG;
+	*bit *= RK3568_SCHMITT_BITS_PER_PIN;
+
+	return 0;
+}
+
+static int rk3568_set_pull(struct rockchip_pin_bank *bank,
+			   int pin_num, int pull)
+{
+	struct regmap *regmap;
+	int reg, ret;
+	u8 bit, type;
+	u32 data;
+
+	if (pull == PIN_CONFIG_BIAS_PULL_PIN_DEFAULT)
+		return -EOPNOTSUPP;
+
+	rk3568_calc_pull_reg_and_bit(bank, pin_num, &regmap, &reg, &bit);
+	type = bank->pull_type[pin_num / 8];
+	ret = rockchip_translate_pull_value(type, pull);
+	if (ret < 0) {
+		debug("unsupported pull setting %d\n", pull);
+		return ret;
+	}
+
+	/* enable the write to the equivalent lower bits */
+	data = ((1 << ROCKCHIP_PULL_BITS_PER_PIN) - 1) << (bit + 16);
+
+	data |= (ret << bit);
+	ret = regmap_write(regmap, reg, data);
+
+	return ret;
+}
+
+static int rk3568_set_drive(struct rockchip_pin_bank *bank,
+			    int pin_num, int strength)
+{
+	struct regmap *regmap;
+	int reg;
+	u32 data;
+	u8 bit;
+	int drv = (1 << (strength + 1)) - 1;
+	int ret = 0;
+
+	rk3568_calc_drv_reg_and_bit(bank, pin_num, &regmap, &reg, &bit);
+
+	/* enable the write to the equivalent lower bits */
+	data = ((1 << RK3568_DRV_BITS_PER_PIN) - 1) << (bit + 16);
+	data |= (drv << bit);
+
+	ret = regmap_write(regmap, reg, data);
+	if (ret)
+		return ret;
+
+	if (bank->bank_num == 1 && pin_num == 21)
+		reg = 0x0840;
+	else if (bank->bank_num == 2 && pin_num == 2)
+		reg = 0x0844;
+	else if (bank->bank_num == 2 && pin_num == 8)
+		reg = 0x0848;
+	else if (bank->bank_num == 3 && pin_num == 0)
+		reg = 0x084c;
+	else if (bank->bank_num == 3 && pin_num == 6)
+		reg = 0x0850;
+	else if (bank->bank_num == 4 && pin_num == 0)
+		reg = 0x0854;
+	else
+		return 0;
+
+	data = ((1 << RK3568_DRV_BITS_PER_PIN) - 1) << 16;
+	data |= drv;
+
+	return regmap_write(regmap, reg, data);
+}
+
+static int rk3568_set_schmitt(struct rockchip_pin_bank *bank,
+			      int pin_num, int enable)
+{
+	struct regmap *regmap;
+	int reg;
+	u32 data;
+	u8 bit;
+
+	rk3568_calc_schmitt_reg_and_bit(bank, pin_num, &regmap, &reg, &bit);
+
+	/* enable the write to the equivalent lower bits */
+	data = ((1 << RK3568_SCHMITT_BITS_PER_PIN) - 1) << (bit + 16);
+	data |= (enable << bit);
+
+	return regmap_write(regmap, reg, data);
+}
+
+static struct rockchip_pin_bank rk3568_pin_banks[] = {
+	PIN_BANK_IOMUX_FLAGS(0, 32, "gpio0", IOMUX_SOURCE_PMU | IOMUX_WIDTH_4BIT,
+			     IOMUX_SOURCE_PMU | IOMUX_WIDTH_4BIT,
+			     IOMUX_SOURCE_PMU | IOMUX_WIDTH_4BIT,
+			     IOMUX_SOURCE_PMU | IOMUX_WIDTH_4BIT),
+	PIN_BANK_IOMUX_FLAGS(1, 32, "gpio1", IOMUX_WIDTH_4BIT,
+			     IOMUX_WIDTH_4BIT,
+			     IOMUX_WIDTH_4BIT,
+			     IOMUX_WIDTH_4BIT),
+	PIN_BANK_IOMUX_FLAGS(2, 32, "gpio2", IOMUX_WIDTH_4BIT,
+			     IOMUX_WIDTH_4BIT,
+			     IOMUX_WIDTH_4BIT,
+			     IOMUX_WIDTH_4BIT),
+	PIN_BANK_IOMUX_FLAGS(3, 32, "gpio3", IOMUX_WIDTH_4BIT,
+			     IOMUX_WIDTH_4BIT,
+			     IOMUX_WIDTH_4BIT,
+			     IOMUX_WIDTH_4BIT),
+	PIN_BANK_IOMUX_FLAGS(4, 32, "gpio4", IOMUX_WIDTH_4BIT,
+			     IOMUX_WIDTH_4BIT,
+			     IOMUX_WIDTH_4BIT,
+			     IOMUX_WIDTH_4BIT),
+};
+
+static const struct rockchip_pin_ctrl rk3568_pin_ctrl = {
+	.pin_banks		= rk3568_pin_banks,
+	.nr_banks		= ARRAY_SIZE(rk3568_pin_banks),
+	.nr_pins		= 160,
+	.grf_mux_offset		= 0x0,
+	.pmu_mux_offset		= 0x0,
+	.iomux_routes		= rk3568_mux_route_data,
+	.niomux_routes		= ARRAY_SIZE(rk3568_mux_route_data),
+	.set_mux		= rk3568_set_mux,
+	.set_pull		= rk3568_set_pull,
+	.set_drive		= rk3568_set_drive,
+	.set_schmitt		= rk3568_set_schmitt,
+};
+
+static const struct udevice_id rk3568_pinctrl_ids[] = {
+	{
+		.compatible = "rockchip,rk3568-pinctrl",
+		.data = (ulong)&rk3568_pin_ctrl
+	},
+	{ }
+};
+
+U_BOOT_DRIVER(pinctrl_rk3568) = {
+	.name		= "rockchip_rk3568_pinctrl",
+	.id		= UCLASS_PINCTRL,
+	.of_match	= rk3568_pinctrl_ids,
+	.priv_auto = sizeof(struct rockchip_pinctrl_priv),
+	.ops		= &rockchip_pinctrl_ops,
+#if !IS_ENABLED(CONFIG_OF_PLATDATA)
+	.bind		= dm_scan_fdt_dev,
+#endif
+	.probe		= rockchip_pinctrl_probe,
+};
diff --git a/drivers/pinctrl/rockchip/pinctrl-rockchip-core.c b/drivers/pinctrl/rockchip/pinctrl-rockchip-core.c
index d9d61fdb72..1481c1e51c 100644
--- a/drivers/pinctrl/rockchip/pinctrl-rockchip-core.c
+++ b/drivers/pinctrl/rockchip/pinctrl-rockchip-core.c
@@ -433,7 +433,7 @@  static int rockchip_pinctrl_set_state(struct udevice *dev,
 	int prop_len, param;
 	const u32 *data;
 	ofnode node;
-#ifdef CONFIG_OF_LIVE
+#if CONFIG_IS_ENABLED(OF_LIVE)
 	const struct device_node *np;
 	struct property *pp;
 #else
@@ -473,7 +473,7 @@  static int rockchip_pinctrl_set_state(struct udevice *dev,
 		node = ofnode_get_by_phandle(conf);
 		if (!ofnode_valid(node))
 			return -ENODEV;
-#ifdef CONFIG_OF_LIVE
+#if CONFIG_IS_ENABLED(OF_LIVE)
 		np = ofnode_to_np(node);
 		for (pp = np->properties; pp; pp = pp->next) {
 			prop_name = pp->name;
@@ -548,13 +548,15 @@  static struct rockchip_pin_ctrl *rockchip_pinctrl_get_soc_data(struct udevice *d
 
 			/* preset iomux offset value, set new start value */
 			if (iom->offset >= 0) {
-				if (iom->type & IOMUX_SOURCE_PMU)
+				if ((iom->type & IOMUX_SOURCE_PMU) || \
+				    (iom->type & IOMUX_L_SOURCE_PMU))
 					pmu_offs = iom->offset;
 				else
 					grf_offs = iom->offset;
 			} else { /* set current iomux offset */
-				iom->offset = (iom->type & IOMUX_SOURCE_PMU) ?
-							pmu_offs : grf_offs;
+				iom->offset = ((iom->type & IOMUX_SOURCE_PMU) ||
+						(iom->type & IOMUX_L_SOURCE_PMU)) ?
+						pmu_offs : grf_offs;
 			}
 
 			/* preset drv offset value, set new start value */