On 01/02/2019 09:00 PM, David Wu wrote: > Use this driver to fit all Rockchip SOCs and to support > the desired pinctrl configuration via DTS. > > Signed-off-by: David Wu <david...@rock-chips.com>
Reviewed-by: Kever Yang <kever.y...@rock-chips.com> Thanks, - Kever > --- > > Changes in v2: > - Remove px30, rk2928, rk3066*. > - Split it to multiple files for the relevant per-SoC data structures. > > drivers/pinctrl/Kconfig | 91 +- > drivers/pinctrl/Makefile | 2 +- > drivers/pinctrl/rockchip/Kconfig | 17 + > drivers/pinctrl/rockchip/Makefile | 19 +- > drivers/pinctrl/rockchip/pinctrl-rk3036.c | 65 ++ > drivers/pinctrl/rockchip/pinctrl-rk3128.c | 155 ++++ > drivers/pinctrl/rockchip/pinctrl-rk3188.c | 82 ++ > drivers/pinctrl/rockchip/pinctrl-rk322x.c | 215 +++++ > drivers/pinctrl/rockchip/pinctrl-rk3288.c | 157 ++++ > drivers/pinctrl/rockchip/pinctrl-rk3328.c | 227 +++++ > drivers/pinctrl/rockchip/pinctrl-rk3368.c | 116 +++ > drivers/pinctrl/rockchip/pinctrl-rk3399.c | 193 +++++ > .../pinctrl/rockchip/pinctrl-rockchip-core.c | 788 ++++++++++++++++++ > drivers/pinctrl/rockchip/pinctrl-rockchip.h | 302 +++++++ > drivers/pinctrl/rockchip/pinctrl-rv1108.c | 203 +++++ > 15 files changed, 2532 insertions(+), 100 deletions(-) > create mode 100644 drivers/pinctrl/rockchip/Kconfig > create mode 100644 drivers/pinctrl/rockchip/pinctrl-rk3036.c > create mode 100644 drivers/pinctrl/rockchip/pinctrl-rk3128.c > create mode 100644 drivers/pinctrl/rockchip/pinctrl-rk3188.c > create mode 100644 drivers/pinctrl/rockchip/pinctrl-rk322x.c > create mode 100644 drivers/pinctrl/rockchip/pinctrl-rk3288.c > create mode 100644 drivers/pinctrl/rockchip/pinctrl-rk3328.c > create mode 100644 drivers/pinctrl/rockchip/pinctrl-rk3368.c > create mode 100644 drivers/pinctrl/rockchip/pinctrl-rk3399.c > create mode 100644 drivers/pinctrl/rockchip/pinctrl-rockchip-core.c > create mode 100644 drivers/pinctrl/rockchip/pinctrl-rockchip.h > create mode 100644 drivers/pinctrl/rockchip/pinctrl-rv1108.c > > diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig > index 7e6fad305a..d2168f7b72 100644 > --- a/drivers/pinctrl/Kconfig > +++ b/drivers/pinctrl/Kconfig > @@ -158,96 +158,6 @@ config PINCTRL_QCA953X > the GPIO definitions and pin control functions for each available > multiplex function. > > -config PINCTRL_ROCKCHIP_RK3036 > - bool "Rockchip rk3036 pin control driver" > - depends on DM > - help > - Support pin multiplexing control on Rockchip rk3036 SoCs. > - > - The driver is controlled by a device tree node which contains both > - the GPIO definitions and pin control functions for each available > - multiplex function. > - > -config PINCTRL_ROCKCHIP_RK3128 > - bool "Rockchip rk3128 pin control driver" > - depends on DM > - help > - Support pin multiplexing control on Rockchip rk3128 SoCs. > - > - The driver is controlled by a device tree node which contains both > - the GPIO definitions and pin control functions for each available > - multiplex function. > - > -config PINCTRL_ROCKCHIP_RK3188 > - bool "Rockchip rk3188 pin control driver" > - depends on DM > - help > - Support pin multiplexing control on Rockchip rk3188 SoCs. > - > - The driver is controlled by a device tree node which contains both > - the GPIO definitions and pin control functions for each available > - multiplex function. > - > -config PINCTRL_ROCKCHIP_RK322X > - bool "Rockchip rk322x pin control driver" > - depends on DM > - help > - Support pin multiplexing control on Rockchip rk322x SoCs. > - > - The driver is controlled by a device tree node which contains both > - the GPIO definitions and pin control functions for each available > - multiplex function. > - > -config PINCTRL_ROCKCHIP_RK3288 > - bool "Rockchip rk3288 pin control driver" > - depends on DM > - help > - Support pin multiplexing control on Rockchip rk3288 SoCs. > - > - The driver is controlled by a device tree node which contains both > - the GPIO definitions and pin control functions for each available > - multiplex function. > - > -config PINCTRL_ROCKCHIP_RK3328 > - bool "Rockchip rk3328 pin control driver" > - depends on DM > - help > - Support pin multiplexing control on Rockchip rk3328 SoCs. > - > - The driver is controlled by a device tree node which contains both > - the GPIO definitions and pin control functions for each available > - multiplex function. > - > -config PINCTRL_ROCKCHIP_RK3368 > - bool "Rockchip RK3368 pin control driver" > - depends on DM > - help > - Support pin multiplexing control on Rockchip rk3368 SoCs. > - > - The driver is controlled by a device tree node which contains both > - the GPIO definitions and pin control functions for each available > - multiplex function. > - > -config PINCTRL_ROCKCHIP_RK3399 > - bool "Rockchip rk3399 pin control driver" > - depends on DM > - help > - Support pin multiplexing control on Rockchip rk3399 SoCs. > - > - The driver is controlled by a device tree node which contains both > - the GPIO definitions and pin control functions for each available > - multiplex function. > - > -config PINCTRL_ROCKCHIP_RV1108 > - bool "Rockchip rv1108 pin control driver" > - depends on DM > - help > - Support pin multiplexing control on Rockchip rv1108 SoC. > - > - The driver is controlled by a device tree node which contains > - both the GPIO definitions and pin control functions for each > - available multiplex function. > - > config PINCTRL_SANDBOX > bool "Sandbox pinctrl driver" > depends on SANDBOX > @@ -304,6 +214,7 @@ source "drivers/pinctrl/meson/Kconfig" > source "drivers/pinctrl/mediatek/Kconfig" > source "drivers/pinctrl/nxp/Kconfig" > source "drivers/pinctrl/renesas/Kconfig" > +source "drivers/pinctrl/rockchip/Kconfig" > source "drivers/pinctrl/uniphier/Kconfig" > source "drivers/pinctrl/exynos/Kconfig" > source "drivers/pinctrl/mvebu/Kconfig" > diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile > index 293bad3a95..8d7738ea11 100644 > --- a/drivers/pinctrl/Makefile > +++ b/drivers/pinctrl/Makefile > @@ -6,10 +6,10 @@ obj-$(CONFIG_$(SPL_)PINCTRL_GENERIC) += > pinctrl-generic.o > obj-$(CONFIG_PINCTRL_AT91) += pinctrl-at91.o > obj-$(CONFIG_PINCTRL_AT91PIO4) += pinctrl-at91-pio4.o > obj-y += nxp/ > +obj-$(CONFIG_$(SPL_)PINCTRL_ROCKCHIP) += rockchip/ > obj-$(CONFIG_ARCH_ASPEED) += aspeed/ > obj-$(CONFIG_ARCH_ATH79) += ath79/ > obj-$(CONFIG_ARCH_RMOBILE) += renesas/ > -obj-$(CONFIG_ARCH_ROCKCHIP) += rockchip/ > obj-$(CONFIG_PINCTRL_SANDBOX) += pinctrl-sandbox.o > > obj-$(CONFIG_PINCTRL_UNIPHIER) += uniphier/ > diff --git a/drivers/pinctrl/rockchip/Kconfig > b/drivers/pinctrl/rockchip/Kconfig > new file mode 100644 > index 0000000000..dc4ba34ae5 > --- /dev/null > +++ b/drivers/pinctrl/rockchip/Kconfig > @@ -0,0 +1,17 @@ > +if ARCH_ROCKCHIP > + > +config PINCTRL_ROCKCHIP > + bool "Rockchip pin control drivers" > + depends on ARCH_ROCKCHIP && PINCTRL_GENERIC > + default y > + help > + Enable support pin control functions for Rockchip SoCs. > + > +config SPL_PINCTRL_ROCKCHIP > + bool "Support Rockchip pin controllers in SPL" > + depends on ARCH_ROCKCHIP && SPL_PINCTRL_GENERIC > + default y > + help > + This option is an SPL-variant of the PINCTRL_ROCKCHIP option. > + > +endif > diff --git a/drivers/pinctrl/rockchip/Makefile > b/drivers/pinctrl/rockchip/Makefile > index 5e3fbcb4bc..a616d8587f 100644 > --- a/drivers/pinctrl/rockchip/Makefile > +++ b/drivers/pinctrl/rockchip/Makefile > @@ -2,12 +2,13 @@ > # > # Copyright (c) 2017 Rockchip Electronics Co., Ltd > > -obj-$(CONFIG_PINCTRL_ROCKCHIP_RK3036) += pinctrl_rk3036.o > -obj-$(CONFIG_PINCTRL_ROCKCHIP_RK3128) += pinctrl_rk3128.o > -obj-$(CONFIG_PINCTRL_ROCKCHIP_RK3188) += pinctrl_rk3188.o > -obj-$(CONFIG_PINCTRL_ROCKCHIP_RK322X) += pinctrl_rk322x.o > -obj-$(CONFIG_PINCTRL_ROCKCHIP_RK3288) += pinctrl_rk3288.o > -obj-$(CONFIG_PINCTRL_ROCKCHIP_RK3328) += pinctrl_rk3328.o > -obj-$(CONFIG_PINCTRL_ROCKCHIP_RK3368) += pinctrl_rk3368.o > -obj-$(CONFIG_PINCTRL_ROCKCHIP_RK3399) += pinctrl_rk3399.o > -obj-$(CONFIG_PINCTRL_ROCKCHIP_RV1108) += pinctrl_rv1108.o > +obj-y += pinctrl-rockchip-core.o > +obj-$(CONFIG_ROCKCHIP_RK3036) += pinctrl-rk3036.o > +obj-$(CONFIG_ROCKCHIP_RK3128) += pinctrl-rk3128.o > +obj-$(CONFIG_ROCKCHIP_RK3188) += pinctrl-rk3188.o > +obj-$(CONFIG_ROCKCHIP_RK322X) += pinctrl-rk322x.o > +obj-$(CONFIG_ROCKCHIP_RK3288) += pinctrl-rk3288.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_RV1108) += pinctrl-rv1108.o > diff --git a/drivers/pinctrl/rockchip/pinctrl-rk3036.c > b/drivers/pinctrl/rockchip/pinctrl-rk3036.c > new file mode 100644 > index 0000000000..2729b03443 > --- /dev/null > +++ b/drivers/pinctrl/rockchip/pinctrl-rk3036.c > @@ -0,0 +1,65 @@ > +// SPDX-License-Identifier: GPL-2.0+ > +/* > + * (C) Copyright 2019 Rockchip Electronics Co., Ltd > + */ > + > +#include <common.h> > +#include <dm.h> > +#include <dm/pinctrl.h> > +#include <regmap.h> > +#include <syscon.h> > + > +#include "pinctrl-rockchip.h" > + > +#define RK3036_PULL_OFFSET 0x118 > +#define RK3036_PULL_PINS_PER_REG 16 > +#define RK3036_PULL_BANK_STRIDE 8 > + > +static void rk3036_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank, > + int pin_num, struct regmap **regmap, > + int *reg, u8 *bit) > +{ > + struct rockchip_pinctrl_priv *priv = bank->priv; > + > + *regmap = priv->regmap_base; > + *reg = RK3036_PULL_OFFSET; > + *reg += bank->bank_num * RK3036_PULL_BANK_STRIDE; > + *reg += (pin_num / RK3036_PULL_PINS_PER_REG) * 4; > + > + *bit = pin_num % RK3036_PULL_PINS_PER_REG; > +}; > + > +static struct rockchip_pin_bank rk3036_pin_banks[] = { > + PIN_BANK(0, 32, "gpio0"), > + PIN_BANK(1, 32, "gpio1"), > + PIN_BANK(2, 32, "gpio2"), > +}; > + > +static struct rockchip_pin_ctrl rk3036_pin_ctrl = { > + .pin_banks = rk3036_pin_banks, > + .nr_banks = ARRAY_SIZE(rk3036_pin_banks), > + .label = "RK3036-GPIO", > + .type = RK3036, > + .grf_mux_offset = 0xa8, > + .pull_calc_reg = rk3036_calc_pull_reg_and_bit, > +}; > + > +static const struct udevice_id rk3036_pinctrl_ids[] = { > + { > + .compatible = "rockchip,rk3036-pinctrl", > + .data = (ulong)&rk3036_pin_ctrl > + }, > + {} > +}; > + > +U_BOOT_DRIVER(pinctrl_rockchip) = { > + .name = "rk3036-pinctrl", > + .id = UCLASS_PINCTRL, > + .of_match = rk3036_pinctrl_ids, > + .priv_auto_alloc_size = sizeof(struct rockchip_pinctrl_priv), > + .ops = &rockchip_pinctrl_ops, > +#if !CONFIG_IS_ENABLED(OF_PLATDATA) > + .bind = dm_scan_fdt_dev, > +#endif > + .probe = rockchip_pinctrl_probe, > +}; > diff --git a/drivers/pinctrl/rockchip/pinctrl-rk3128.c > b/drivers/pinctrl/rockchip/pinctrl-rk3128.c > new file mode 100644 > index 0000000000..43a6c173a0 > --- /dev/null > +++ b/drivers/pinctrl/rockchip/pinctrl-rk3128.c > @@ -0,0 +1,155 @@ > +// SPDX-License-Identifier: GPL-2.0+ > +/* > + * (C) Copyright 2019 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_recalced_data rk3128_mux_recalced_data[] = { > + { > + .num = 2, > + .pin = 20, > + .reg = 0xe8, > + .bit = 0, > + .mask = 0x7 > + }, { > + .num = 2, > + .pin = 21, > + .reg = 0xe8, > + .bit = 4, > + .mask = 0x7 > + }, { > + .num = 2, > + .pin = 22, > + .reg = 0xe8, > + .bit = 8, > + .mask = 0x7 > + }, { > + .num = 2, > + .pin = 23, > + .reg = 0xe8, > + .bit = 12, > + .mask = 0x7 > + }, { > + .num = 2, > + .pin = 24, > + .reg = 0xd4, > + .bit = 12, > + .mask = 0x7 > + }, > +}; > + > +static struct rockchip_mux_route_data rk3128_mux_route_data[] = { > + { > + /* spi-0 */ > + .bank_num = 1, > + .pin = 10, > + .func = 1, > + .route_offset = 0x144, > + .route_val = BIT(16 + 3) | BIT(16 + 4), > + }, { > + /* spi-1 */ > + .bank_num = 1, > + .pin = 27, > + .func = 3, > + .route_offset = 0x144, > + .route_val = BIT(16 + 3) | BIT(16 + 4) | BIT(3), > + }, { > + /* spi-2 */ > + .bank_num = 0, > + .pin = 13, > + .func = 2, > + .route_offset = 0x144, > + .route_val = BIT(16 + 3) | BIT(16 + 4) | BIT(4), > + }, { > + /* i2s-0 */ > + .bank_num = 1, > + .pin = 5, > + .func = 1, > + .route_offset = 0x144, > + .route_val = BIT(16 + 5), > + }, { > + /* i2s-1 */ > + .bank_num = 0, > + .pin = 14, > + .func = 1, > + .route_offset = 0x144, > + .route_val = BIT(16 + 5) | BIT(5), > + }, { > + /* emmc-0 */ > + .bank_num = 1, > + .pin = 22, > + .func = 2, > + .route_offset = 0x144, > + .route_val = BIT(16 + 6), > + }, { > + /* emmc-1 */ > + .bank_num = 2, > + .pin = 4, > + .func = 2, > + .route_offset = 0x144, > + .route_val = BIT(16 + 6) | BIT(6), > + }, > +}; > + > +#define RK3128_PULL_OFFSET 0x118 > +#define RK3128_PULL_PINS_PER_REG 16 > +#define RK3128_PULL_BANK_STRIDE 8 > + > +static void rk3128_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank, > + int pin_num, struct regmap **regmap, > + int *reg, u8 *bit) > +{ > + struct rockchip_pinctrl_priv *priv = bank->priv; > + > + *regmap = priv->regmap_base; > + *reg = RK3128_PULL_OFFSET; > + *reg += bank->bank_num * RK3128_PULL_BANK_STRIDE; > + *reg += ((pin_num / RK3128_PULL_PINS_PER_REG) * 4); > + > + *bit = pin_num % RK3128_PULL_PINS_PER_REG; > +} > + > +static struct rockchip_pin_bank rk3128_pin_banks[] = { > + PIN_BANK(0, 32, "gpio0"), > + PIN_BANK(1, 32, "gpio1"), > + PIN_BANK(2, 32, "gpio2"), > + PIN_BANK(3, 32, "gpio3"), > +}; > + > +static struct rockchip_pin_ctrl rk3128_pin_ctrl = { > + .pin_banks = rk3128_pin_banks, > + .nr_banks = ARRAY_SIZE(rk3128_pin_banks), > + .label = "RK3128-GPIO", > + .type = RK3128, > + .grf_mux_offset = 0xa8, > + .iomux_recalced = rk3128_mux_recalced_data, > + .niomux_recalced = ARRAY_SIZE(rk3128_mux_recalced_data), > + .iomux_routes = rk3128_mux_route_data, > + .niomux_routes = ARRAY_SIZE(rk3128_mux_route_data), > + .pull_calc_reg = rk3128_calc_pull_reg_and_bit, > +}; > + > +static const struct udevice_id rk3128_pinctrl_ids[] = { > + { .compatible = "rockchip,rk3128-pinctrl", > + .data = (ulong)&rk3128_pin_ctrl }, > + { } > +}; > + > +U_BOOT_DRIVER(pinctrl_rk3128) = { > + .name = "pinctrl_rk3128", > + .id = UCLASS_PINCTRL, > + .of_match = rk3128_pinctrl_ids, > + .priv_auto_alloc_size = sizeof(struct rockchip_pinctrl_priv), > + .ops = &rockchip_pinctrl_ops, > +#if !CONFIG_IS_ENABLED(OF_PLATDATA) > + .bind = dm_scan_fdt_dev, > +#endif > + .probe = rockchip_pinctrl_probe, > +}; > diff --git a/drivers/pinctrl/rockchip/pinctrl-rk3188.c > b/drivers/pinctrl/rockchip/pinctrl-rk3188.c > new file mode 100644 > index 0000000000..5ed9aec938 > --- /dev/null > +++ b/drivers/pinctrl/rockchip/pinctrl-rk3188.c > @@ -0,0 +1,82 @@ > +// SPDX-License-Identifier: GPL-2.0+ > +/* > + * (C) Copyright 2019 Rockchip Electronics Co., Ltd > + */ > + > +#include <common.h> > +#include <dm.h> > +#include <dm/pinctrl.h> > +#include <regmap.h> > +#include <syscon.h> > + > +#include "pinctrl-rockchip.h" > + > +#define RK3188_PULL_OFFSET 0x164 > +#define RK3188_PULL_PMU_OFFSET 0x64 > + > +static void rk3188_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank, > + int pin_num, struct regmap **regmap, > + int *reg, u8 *bit) > +{ > + struct rockchip_pinctrl_priv *priv = bank->priv; > + > + /* The first 12 pins of the first bank are located elsewhere */ > + if (bank->bank_num == 0 && pin_num < 12) { > + *regmap = priv->regmap_pmu; > + *reg = RK3188_PULL_PMU_OFFSET; > + > + *reg += ((pin_num / ROCKCHIP_PULL_PINS_PER_REG) * 4); > + *bit = pin_num % ROCKCHIP_PULL_PINS_PER_REG; > + *bit *= ROCKCHIP_PULL_BITS_PER_PIN; > + } else { > + *regmap = priv->regmap_base; > + *reg = RK3188_PULL_OFFSET; > + > + /* correct the offset, as it is the 2nd pull register */ > + *reg -= 4; > + *reg += bank->bank_num * ROCKCHIP_PULL_BANK_STRIDE; > + *reg += ((pin_num / ROCKCHIP_PULL_PINS_PER_REG) * 4); > + > + /* > + * The bits in these registers have an inverse ordering > + * with the lowest pin being in bits 15:14 and the highest > + * pin in bits 1:0 > + */ > + *bit = 7 - (pin_num % ROCKCHIP_PULL_PINS_PER_REG); > + *bit *= ROCKCHIP_PULL_BITS_PER_PIN; > + } > +} > + > +static struct rockchip_pin_bank rk3188_pin_banks[] = { > + PIN_BANK_IOMUX_FLAGS(0, 32, "gpio0", IOMUX_GPIO_ONLY, 0, 0, 0), > + PIN_BANK(1, 32, "gpio1"), > + PIN_BANK(2, 32, "gpio2"), > + PIN_BANK(3, 32, "gpio3"), > +}; > + > +static struct rockchip_pin_ctrl rk3188_pin_ctrl = { > + .pin_banks = rk3188_pin_banks, > + .nr_banks = ARRAY_SIZE(rk3188_pin_banks), > + .label = "RK3188-GPIO", > + .type = RK3188, > + .grf_mux_offset = 0x60, > + .pull_calc_reg = rk3188_calc_pull_reg_and_bit, > +}; > + > +static const struct udevice_id rk3188_pinctrl_ids[] = { > + { .compatible = "rockchip,rk3188-pinctrl", > + .data = (ulong)&rk3188_pin_ctrl }, > + { } > +}; > + > +U_BOOT_DRIVER(pinctrl_rk3188) = { > + .name = "rockchip_rk3188_pinctrl", > + .id = UCLASS_PINCTRL, > + .of_match = rk3188_pinctrl_ids, > + .priv_auto_alloc_size = sizeof(struct rockchip_pinctrl_priv), > + .ops = &rockchip_pinctrl_ops, > +#if !CONFIG_IS_ENABLED(OF_PLATDATA) > + .bind = dm_scan_fdt_dev, > +#endif > + .probe = rockchip_pinctrl_probe, > +}; > diff --git a/drivers/pinctrl/rockchip/pinctrl-rk322x.c > b/drivers/pinctrl/rockchip/pinctrl-rk322x.c > new file mode 100644 > index 0000000000..d2a6cd7055 > --- /dev/null > +++ b/drivers/pinctrl/rockchip/pinctrl-rk322x.c > @@ -0,0 +1,215 @@ > +// SPDX-License-Identifier: GPL-2.0+ > +/* > + * (C) Copyright 2019 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 rk3228_mux_route_data[] = { > + { > + /* pwm0-0 */ > + .bank_num = 0, > + .pin = 26, > + .func = 1, > + .route_offset = 0x50, > + .route_val = BIT(16), > + }, { > + /* pwm0-1 */ > + .bank_num = 3, > + .pin = 21, > + .func = 1, > + .route_offset = 0x50, > + .route_val = BIT(16) | BIT(0), > + }, { > + /* pwm1-0 */ > + .bank_num = 0, > + .pin = 27, > + .func = 1, > + .route_offset = 0x50, > + .route_val = BIT(16 + 1), > + }, { > + /* pwm1-1 */ > + .bank_num = 0, > + .pin = 30, > + .func = 2, > + .route_offset = 0x50, > + .route_val = BIT(16 + 1) | BIT(1), > + }, { > + /* pwm2-0 */ > + .bank_num = 0, > + .pin = 28, > + .func = 1, > + .route_offset = 0x50, > + .route_val = BIT(16 + 2), > + }, { > + /* pwm2-1 */ > + .bank_num = 1, > + .pin = 12, > + .func = 2, > + .route_offset = 0x50, > + .route_val = BIT(16 + 2) | BIT(2), > + }, { > + /* pwm3-0 */ > + .bank_num = 3, > + .pin = 26, > + .func = 1, > + .route_offset = 0x50, > + .route_val = BIT(16 + 3), > + }, { > + /* pwm3-1 */ > + .bank_num = 1, > + .pin = 11, > + .func = 2, > + .route_offset = 0x50, > + .route_val = BIT(16 + 3) | BIT(3), > + }, { > + /* sdio-0_d0 */ > + .bank_num = 1, > + .pin = 1, > + .func = 1, > + .route_offset = 0x50, > + .route_val = BIT(16 + 4), > + }, { > + /* sdio-1_d0 */ > + .bank_num = 3, > + .pin = 2, > + .func = 1, > + .route_offset = 0x50, > + .route_val = BIT(16 + 4) | BIT(4), > + }, { > + /* spi-0_rx */ > + .bank_num = 0, > + .pin = 13, > + .func = 2, > + .route_offset = 0x50, > + .route_val = BIT(16 + 5), > + }, { > + /* spi-1_rx */ > + .bank_num = 2, > + .pin = 0, > + .func = 2, > + .route_offset = 0x50, > + .route_val = BIT(16 + 5) | BIT(5), > + }, { > + /* emmc-0_cmd */ > + .bank_num = 1, > + .pin = 22, > + .func = 2, > + .route_offset = 0x50, > + .route_val = BIT(16 + 7), > + }, { > + /* emmc-1_cmd */ > + .bank_num = 2, > + .pin = 4, > + .func = 2, > + .route_offset = 0x50, > + .route_val = BIT(16 + 7) | BIT(7), > + }, { > + /* uart2-0_rx */ > + .bank_num = 1, > + .pin = 19, > + .func = 2, > + .route_offset = 0x50, > + .route_val = BIT(16 + 8), > + }, { > + /* uart2-1_rx */ > + .bank_num = 1, > + .pin = 10, > + .func = 2, > + .route_offset = 0x50, > + .route_val = BIT(16 + 8) | BIT(8), > + }, { > + /* uart1-0_rx */ > + .bank_num = 1, > + .pin = 10, > + .func = 1, > + .route_offset = 0x50, > + .route_val = BIT(16 + 11), > + }, { > + /* uart1-1_rx */ > + .bank_num = 3, > + .pin = 13, > + .func = 1, > + .route_offset = 0x50, > + .route_val = BIT(16 + 11) | BIT(11), > + }, > +}; > + > +#define RK3228_PULL_OFFSET 0x100 > + > +static void rk3228_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank, > + int pin_num, struct regmap **regmap, > + int *reg, u8 *bit) > +{ > + struct rockchip_pinctrl_priv *priv = bank->priv; > + > + *regmap = priv->regmap_base; > + *reg = RK3228_PULL_OFFSET; > + *reg += bank->bank_num * ROCKCHIP_PULL_BANK_STRIDE; > + *reg += ((pin_num / ROCKCHIP_PULL_PINS_PER_REG) * 4); > + > + *bit = (pin_num % ROCKCHIP_PULL_PINS_PER_REG); > + *bit *= ROCKCHIP_PULL_BITS_PER_PIN; > +} > + > +#define RK3228_DRV_GRF_OFFSET 0x200 > + > +static void rk3228_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank, > + int pin_num, struct regmap **regmap, > + int *reg, u8 *bit) > +{ > + struct rockchip_pinctrl_priv *priv = bank->priv; > + > + *regmap = priv->regmap_base; > + *reg = RK3228_DRV_GRF_OFFSET; > + *reg += bank->bank_num * ROCKCHIP_DRV_BANK_STRIDE; > + *reg += ((pin_num / ROCKCHIP_DRV_PINS_PER_REG) * 4); > + > + *bit = (pin_num % ROCKCHIP_DRV_PINS_PER_REG); > + *bit *= ROCKCHIP_DRV_BITS_PER_PIN; > +} > + > +static struct rockchip_pin_bank rk3228_pin_banks[] = { > + PIN_BANK(0, 32, "gpio0"), > + PIN_BANK(1, 32, "gpio1"), > + PIN_BANK(2, 32, "gpio2"), > + PIN_BANK(3, 32, "gpio3"), > +}; > + > +static struct rockchip_pin_ctrl rk3228_pin_ctrl = { > + .pin_banks = rk3228_pin_banks, > + .nr_banks = ARRAY_SIZE(rk3228_pin_banks), > + .label = "RK3228-GPIO", > + .type = RK3288, > + .grf_mux_offset = 0x0, > + .iomux_routes = rk3228_mux_route_data, > + .niomux_routes = ARRAY_SIZE(rk3228_mux_route_data), > + .pull_calc_reg = rk3228_calc_pull_reg_and_bit, > + .drv_calc_reg = rk3228_calc_drv_reg_and_bit, > +}; > + > +static const struct udevice_id rk3228_pinctrl_ids[] = { > + { > + .compatible = "rockchip,rk3228-pinctrl", > + .data = (ulong)&rk3228_pin_ctrl > + }, > + { } > +}; > + > +U_BOOT_DRIVER(pinctrl_rk3228) = { > + .name = "rockchip_rk3228_pinctrl", > + .id = UCLASS_PINCTRL, > + .of_match = rk3228_pinctrl_ids, > + .priv_auto_alloc_size = sizeof(struct rockchip_pinctrl_priv), > + .ops = &rockchip_pinctrl_ops, > +#if !CONFIG_IS_ENABLED(OF_PLATDATA) > + .bind = dm_scan_fdt_dev, > +#endif > + .probe = rockchip_pinctrl_probe, > +}; > diff --git a/drivers/pinctrl/rockchip/pinctrl-rk3288.c > b/drivers/pinctrl/rockchip/pinctrl-rk3288.c > new file mode 100644 > index 0000000000..60585f3208 > --- /dev/null > +++ b/drivers/pinctrl/rockchip/pinctrl-rk3288.c > @@ -0,0 +1,157 @@ > +// SPDX-License-Identifier: GPL-2.0+ > +/* > + * (C) Copyright 2019 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 rk3288_mux_route_data[] = { > + { > + /* edphdmi_cecinoutt1 */ > + .bank_num = 7, > + .pin = 16, > + .func = 2, > + .route_offset = 0x264, > + .route_val = BIT(16 + 12) | BIT(12), > + }, { > + /* edphdmi_cecinout */ > + .bank_num = 7, > + .pin = 23, > + .func = 4, > + .route_offset = 0x264, > + .route_val = BIT(16 + 12), > + }, > +}; > + > +#define RK3288_PULL_OFFSET 0x140 > +#define RK3288_PULL_PMU_OFFSET 0x64 > + > +static void rk3288_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank, > + int pin_num, struct regmap **regmap, > + int *reg, u8 *bit) > +{ > + struct rockchip_pinctrl_priv *priv = bank->priv; > + > + /* The first 24 pins of the first bank are located in PMU */ > + if (bank->bank_num == 0) { > + *regmap = priv->regmap_pmu; > + *reg = RK3288_PULL_PMU_OFFSET; > + > + *reg += ((pin_num / ROCKCHIP_PULL_PINS_PER_REG) * 4); > + *bit = pin_num % ROCKCHIP_PULL_PINS_PER_REG; > + *bit *= ROCKCHIP_PULL_BITS_PER_PIN; > + } else { > + *regmap = priv->regmap_base; > + *reg = RK3288_PULL_OFFSET; > + > + /* correct the offset, as we're starting with the 2nd bank */ > + *reg -= 0x10; > + *reg += bank->bank_num * ROCKCHIP_PULL_BANK_STRIDE; > + *reg += ((pin_num / ROCKCHIP_PULL_PINS_PER_REG) * 4); > + > + *bit = (pin_num % ROCKCHIP_PULL_PINS_PER_REG); > + *bit *= ROCKCHIP_PULL_BITS_PER_PIN; > + } > +} > + > +#define RK3288_DRV_PMU_OFFSET 0x70 > +#define RK3288_DRV_GRF_OFFSET 0x1c0 > + > +static void rk3288_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank, > + int pin_num, struct regmap **regmap, > + int *reg, u8 *bit) > +{ > + struct rockchip_pinctrl_priv *priv = bank->priv; > + > + /* The first 24 pins of the first bank are located in PMU */ > + if (bank->bank_num == 0) { > + *regmap = priv->regmap_pmu; > + *reg = RK3288_DRV_PMU_OFFSET; > + > + *reg += ((pin_num / ROCKCHIP_DRV_PINS_PER_REG) * 4); > + *bit = pin_num % ROCKCHIP_DRV_PINS_PER_REG; > + *bit *= ROCKCHIP_DRV_BITS_PER_PIN; > + } else { > + *regmap = priv->regmap_base; > + *reg = RK3288_DRV_GRF_OFFSET; > + > + /* correct the offset, as we're starting with the 2nd bank */ > + *reg -= 0x10; > + *reg += bank->bank_num * ROCKCHIP_DRV_BANK_STRIDE; > + *reg += ((pin_num / ROCKCHIP_DRV_PINS_PER_REG) * 4); > + > + *bit = (pin_num % ROCKCHIP_DRV_PINS_PER_REG); > + *bit *= ROCKCHIP_DRV_BITS_PER_PIN; > + } > +} > + > +static struct rockchip_pin_bank rk3288_pin_banks[] = { > + PIN_BANK_IOMUX_FLAGS(0, 24, "gpio0", IOMUX_SOURCE_PMU, > + IOMUX_SOURCE_PMU, > + IOMUX_SOURCE_PMU, > + IOMUX_UNROUTED > + ), > + PIN_BANK_IOMUX_FLAGS(1, 32, "gpio1", IOMUX_UNROUTED, > + IOMUX_UNROUTED, > + IOMUX_UNROUTED, > + 0 > + ), > + PIN_BANK_IOMUX_FLAGS(2, 32, "gpio2", 0, 0, 0, IOMUX_UNROUTED), > + PIN_BANK_IOMUX_FLAGS(3, 32, "gpio3", 0, 0, 0, IOMUX_WIDTH_4BIT), > + PIN_BANK_IOMUX_FLAGS(4, 32, "gpio4", IOMUX_WIDTH_4BIT, > + IOMUX_WIDTH_4BIT, > + 0, > + 0 > + ), > + PIN_BANK_IOMUX_FLAGS(5, 32, "gpio5", IOMUX_UNROUTED, > + 0, > + 0, > + IOMUX_UNROUTED > + ), > + PIN_BANK_IOMUX_FLAGS(6, 32, "gpio6", 0, 0, 0, IOMUX_UNROUTED), > + PIN_BANK_IOMUX_FLAGS(7, 32, "gpio7", 0, > + 0, > + IOMUX_WIDTH_4BIT, > + IOMUX_UNROUTED > + ), > + PIN_BANK(8, 16, "gpio8"), > +}; > + > +static struct rockchip_pin_ctrl rk3288_pin_ctrl = { > + .pin_banks = rk3288_pin_banks, > + .nr_banks = ARRAY_SIZE(rk3288_pin_banks), > + .label = "RK3288-GPIO", > + .type = RK3288, > + .grf_mux_offset = 0x0, > + .pmu_mux_offset = 0x84, > + .iomux_routes = rk3288_mux_route_data, > + .niomux_routes = ARRAY_SIZE(rk3288_mux_route_data), > + .pull_calc_reg = rk3288_calc_pull_reg_and_bit, > + .drv_calc_reg = rk3288_calc_drv_reg_and_bit, > +}; > + > +static const struct udevice_id rk3288_pinctrl_ids[] = { > + { > + .compatible = "rockchip,rk3288-pinctrl", > + .data = (ulong)&rk3288_pin_ctrl > + }, > + { } > +}; > + > +U_BOOT_DRIVER(pinctrl_rk3288) = { > + .name = "rockchip_rk3288_pinctrl", > + .id = UCLASS_PINCTRL, > + .of_match = rk3288_pinctrl_ids, > + .priv_auto_alloc_size = sizeof(struct rockchip_pinctrl_priv), > + .ops = &rockchip_pinctrl_ops, > +#if !CONFIG_IS_ENABLED(OF_PLATDATA) > + .bind = dm_scan_fdt_dev, > +#endif > + .probe = rockchip_pinctrl_probe, > +}; > diff --git a/drivers/pinctrl/rockchip/pinctrl-rk3328.c > b/drivers/pinctrl/rockchip/pinctrl-rk3328.c > new file mode 100644 > index 0000000000..f1b3d10dbe > --- /dev/null > +++ b/drivers/pinctrl/rockchip/pinctrl-rk3328.c > @@ -0,0 +1,227 @@ > +// SPDX-License-Identifier: GPL-2.0+ > +/* > + * (C) Copyright 2019 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_recalced_data rk3328_mux_recalced_data[] = { > + { > + .num = 2, > + .pin = 12, > + .reg = 0x24, > + .bit = 8, > + .mask = 0x3 > + }, { > + .num = 2, > + .pin = 15, > + .reg = 0x28, > + .bit = 0, > + .mask = 0x7 > + }, { > + .num = 2, > + .pin = 23, > + .reg = 0x30, > + .bit = 14, > + .mask = 0x3 > + }, > +}; > + > +static struct rockchip_mux_route_data rk3328_mux_route_data[] = { > + { > + /* uart2dbg_rxm0 */ > + .bank_num = 1, > + .pin = 1, > + .func = 2, > + .route_offset = 0x50, > + .route_val = BIT(16) | BIT(16 + 1), > + }, { > + /* uart2dbg_rxm1 */ > + .bank_num = 2, > + .pin = 1, > + .func = 1, > + .route_offset = 0x50, > + .route_val = BIT(16) | BIT(16 + 1) | BIT(0), > + }, { > + /* gmac-m1_rxd0 */ > + .bank_num = 1, > + .pin = 11, > + .func = 2, > + .route_offset = 0x50, > + .route_val = BIT(16 + 2) | BIT(2), > + }, { > + /* gmac-m1-optimized_rxd3 */ > + .bank_num = 1, > + .pin = 14, > + .func = 2, > + .route_offset = 0x50, > + .route_val = BIT(16 + 10) | BIT(10), > + }, { > + /* pdm_sdi0m0 */ > + .bank_num = 2, > + .pin = 19, > + .func = 2, > + .route_offset = 0x50, > + .route_val = BIT(16 + 3), > + }, { > + /* pdm_sdi0m1 */ > + .bank_num = 1, > + .pin = 23, > + .func = 3, > + .route_offset = 0x50, > + .route_val = BIT(16 + 3) | BIT(3), > + }, { > + /* spi_rxdm2 */ > + .bank_num = 3, > + .pin = 2, > + .func = 4, > + .route_offset = 0x50, > + .route_val = BIT(16 + 4) | BIT(16 + 5) | BIT(5), > + }, { > + /* i2s2_sdim0 */ > + .bank_num = 1, > + .pin = 24, > + .func = 1, > + .route_offset = 0x50, > + .route_val = BIT(16 + 6), > + }, { > + /* i2s2_sdim1 */ > + .bank_num = 3, > + .pin = 2, > + .func = 6, > + .route_offset = 0x50, > + .route_val = BIT(16 + 6) | BIT(6), > + }, { > + /* card_iom1 */ > + .bank_num = 2, > + .pin = 22, > + .func = 3, > + .route_offset = 0x50, > + .route_val = BIT(16 + 7) | BIT(7), > + }, { > + /* tsp_d5m1 */ > + .bank_num = 2, > + .pin = 16, > + .func = 3, > + .route_offset = 0x50, > + .route_val = BIT(16 + 8) | BIT(8), > + }, { > + /* cif_data5m1 */ > + .bank_num = 2, > + .pin = 16, > + .func = 4, > + .route_offset = 0x50, > + .route_val = BIT(16 + 9) | BIT(9), > + }, > +}; > + > +#define RK3328_PULL_OFFSET 0x100 > + > +static void rk3328_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank, > + int pin_num, struct regmap **regmap, > + int *reg, u8 *bit) > +{ > + struct rockchip_pinctrl_priv *priv = bank->priv; > + > + *regmap = priv->regmap_base; > + *reg = RK3328_PULL_OFFSET; > + *reg += bank->bank_num * ROCKCHIP_PULL_BANK_STRIDE; > + *reg += ((pin_num / ROCKCHIP_PULL_PINS_PER_REG) * 4); > + > + *bit = (pin_num % ROCKCHIP_PULL_PINS_PER_REG); > + *bit *= ROCKCHIP_PULL_BITS_PER_PIN; > +} > + > +#define RK3328_DRV_GRF_OFFSET 0x200 > + > +static void rk3328_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank, > + int pin_num, struct regmap **regmap, > + int *reg, u8 *bit) > +{ > + struct rockchip_pinctrl_priv *priv = bank->priv; > + > + *regmap = priv->regmap_base; > + *reg = RK3328_DRV_GRF_OFFSET; > + *reg += bank->bank_num * ROCKCHIP_DRV_BANK_STRIDE; > + *reg += ((pin_num / ROCKCHIP_DRV_PINS_PER_REG) * 4); > + > + *bit = (pin_num % ROCKCHIP_DRV_PINS_PER_REG); > + *bit *= ROCKCHIP_DRV_BITS_PER_PIN; > +} > + > +#define RK3328_SCHMITT_BITS_PER_PIN 1 > +#define RK3328_SCHMITT_PINS_PER_REG 16 > +#define RK3328_SCHMITT_BANK_STRIDE 8 > +#define RK3328_SCHMITT_GRF_OFFSET 0x380 > + > +static int rk3328_calc_schmitt_reg_and_bit(struct rockchip_pin_bank *bank, > + int pin_num, > + struct regmap **regmap, > + int *reg, u8 *bit) > +{ > + struct rockchip_pinctrl_priv *priv = bank->priv; > + > + *regmap = priv->regmap_base; > + *reg = RK3328_SCHMITT_GRF_OFFSET; > + > + *reg += bank->bank_num * RK3328_SCHMITT_BANK_STRIDE; > + *reg += ((pin_num / RK3328_SCHMITT_PINS_PER_REG) * 4); > + *bit = pin_num % RK3328_SCHMITT_PINS_PER_REG; > + > + return 0; > +} > + > +static struct rockchip_pin_bank rk3328_pin_banks[] = { > + PIN_BANK_IOMUX_FLAGS(0, 32, "gpio0", 0, 0, 0, 0), > + PIN_BANK_IOMUX_FLAGS(1, 32, "gpio1", 0, 0, 0, 0), > + PIN_BANK_IOMUX_FLAGS(2, 32, "gpio2", 0, > + IOMUX_WIDTH_3BIT, > + IOMUX_WIDTH_3BIT, > + 0), > + PIN_BANK_IOMUX_FLAGS(3, 32, "gpio3", > + IOMUX_WIDTH_3BIT, > + IOMUX_WIDTH_3BIT, > + 0, > + 0), > +}; > + > +static struct rockchip_pin_ctrl rk3328_pin_ctrl = { > + .pin_banks = rk3328_pin_banks, > + .nr_banks = ARRAY_SIZE(rk3328_pin_banks), > + .label = "RK3328-GPIO", > + .type = RK3288, > + .grf_mux_offset = 0x0, > + .iomux_recalced = rk3328_mux_recalced_data, > + .niomux_recalced = ARRAY_SIZE(rk3328_mux_recalced_data), > + .iomux_routes = rk3328_mux_route_data, > + .niomux_routes = ARRAY_SIZE(rk3328_mux_route_data), > + .pull_calc_reg = rk3328_calc_pull_reg_and_bit, > + .drv_calc_reg = rk3328_calc_drv_reg_and_bit, > + .schmitt_calc_reg = rk3328_calc_schmitt_reg_and_bit, > +}; > + > +static const struct udevice_id rk3328_pinctrl_ids[] = { > + { > + .compatible = "rockchip,rk3328-pinctrl", > + .data = (ulong)&rk3328_pin_ctrl > + }, > + { } > +}; > + > +U_BOOT_DRIVER(pinctrl_rk3328) = { > + .name = "rockchip_rk3328_pinctrl", > + .id = UCLASS_PINCTRL, > + .of_match = rk3328_pinctrl_ids, > + .priv_auto_alloc_size = sizeof(struct rockchip_pinctrl_priv), > + .ops = &rockchip_pinctrl_ops, > +#if !CONFIG_IS_ENABLED(OF_PLATDATA) > + .bind = dm_scan_fdt_dev, > +#endif > + .probe = rockchip_pinctrl_probe, > +}; > diff --git a/drivers/pinctrl/rockchip/pinctrl-rk3368.c > b/drivers/pinctrl/rockchip/pinctrl-rk3368.c > new file mode 100644 > index 0000000000..f5cd6ff24e > --- /dev/null > +++ b/drivers/pinctrl/rockchip/pinctrl-rk3368.c > @@ -0,0 +1,116 @@ > +// SPDX-License-Identifier: GPL-2.0+ > +/* > + * (C) Copyright 2019 Rockchip Electronics Co., Ltd > + */ > + > +#include <common.h> > +#include <dm.h> > +#include <dm/pinctrl.h> > +#include <regmap.h> > +#include <syscon.h> > + > +#include "pinctrl-rockchip.h" > + > +#define RK3368_PULL_GRF_OFFSET 0x100 > +#define RK3368_PULL_PMU_OFFSET 0x10 > + > +static void rk3368_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank, > + int pin_num, struct regmap **regmap, > + int *reg, u8 *bit) > +{ > + struct rockchip_pinctrl_priv *priv = bank->priv; > + > + /* The first 32 pins of the first bank are located in PMU */ > + if (bank->bank_num == 0) { > + *regmap = priv->regmap_pmu; > + *reg = RK3368_PULL_PMU_OFFSET; > + > + *reg += ((pin_num / ROCKCHIP_PULL_PINS_PER_REG) * 4); > + *bit = pin_num % ROCKCHIP_PULL_PINS_PER_REG; > + *bit *= ROCKCHIP_PULL_BITS_PER_PIN; > + } else { > + *regmap = priv->regmap_base; > + *reg = RK3368_PULL_GRF_OFFSET; > + > + /* correct the offset, as we're starting with the 2nd bank */ > + *reg -= 0x10; > + *reg += bank->bank_num * ROCKCHIP_PULL_BANK_STRIDE; > + *reg += ((pin_num / ROCKCHIP_PULL_PINS_PER_REG) * 4); > + > + *bit = (pin_num % ROCKCHIP_PULL_PINS_PER_REG); > + *bit *= ROCKCHIP_PULL_BITS_PER_PIN; > + } > +} > + > +#define RK3368_DRV_PMU_OFFSET 0x20 > +#define RK3368_DRV_GRF_OFFSET 0x200 > + > +static void rk3368_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank, > + int pin_num, struct regmap **regmap, > + int *reg, u8 *bit) > +{ > + struct rockchip_pinctrl_priv *priv = bank->priv; > + > + /* The first 32 pins of the first bank are located in PMU */ > + if (bank->bank_num == 0) { > + *regmap = priv->regmap_pmu; > + *reg = RK3368_DRV_PMU_OFFSET; > + > + *reg += ((pin_num / ROCKCHIP_DRV_PINS_PER_REG) * 4); > + *bit = pin_num % ROCKCHIP_DRV_PINS_PER_REG; > + *bit *= ROCKCHIP_DRV_BITS_PER_PIN; > + } else { > + *regmap = priv->regmap_base; > + *reg = RK3368_DRV_GRF_OFFSET; > + > + /* correct the offset, as we're starting with the 2nd bank */ > + *reg -= 0x10; > + *reg += bank->bank_num * ROCKCHIP_DRV_BANK_STRIDE; > + *reg += ((pin_num / ROCKCHIP_DRV_PINS_PER_REG) * 4); > + > + *bit = (pin_num % ROCKCHIP_DRV_PINS_PER_REG); > + *bit *= ROCKCHIP_DRV_BITS_PER_PIN; > + } > +} > + > +static struct rockchip_pin_bank rk3368_pin_banks[] = { > + PIN_BANK_IOMUX_FLAGS(0, 32, "gpio0", IOMUX_SOURCE_PMU, > + IOMUX_SOURCE_PMU, > + IOMUX_SOURCE_PMU, > + IOMUX_SOURCE_PMU > + ), > + PIN_BANK(1, 32, "gpio1"), > + PIN_BANK(2, 32, "gpio2"), > + PIN_BANK(3, 32, "gpio3"), > +}; > + > +static struct rockchip_pin_ctrl rk3368_pin_ctrl = { > + .pin_banks = rk3368_pin_banks, > + .nr_banks = ARRAY_SIZE(rk3368_pin_banks), > + .label = "RK3368-GPIO", > + .type = RK3368, > + .grf_mux_offset = 0x0, > + .pmu_mux_offset = 0x0, > + .pull_calc_reg = rk3368_calc_pull_reg_and_bit, > + .drv_calc_reg = rk3368_calc_drv_reg_and_bit, > +}; > + > +static const struct udevice_id rk3368_pinctrl_ids[] = { > + { > + .compatible = "rockchip,rk3368-pinctrl", > + .data = (ulong)&rk3368_pin_ctrl > + }, > + { } > +}; > + > +U_BOOT_DRIVER(pinctrl_rk3368) = { > + .name = "rockchip_rk3368_pinctrl", > + .id = UCLASS_PINCTRL, > + .of_match = rk3368_pinctrl_ids, > + .priv_auto_alloc_size = sizeof(struct rockchip_pinctrl_priv), > + .ops = &rockchip_pinctrl_ops, > +#if !CONFIG_IS_ENABLED(OF_PLATDATA) > + .bind = dm_scan_fdt_dev, > +#endif > + .probe = rockchip_pinctrl_probe, > +}; > diff --git a/drivers/pinctrl/rockchip/pinctrl-rk3399.c > b/drivers/pinctrl/rockchip/pinctrl-rk3399.c > new file mode 100644 > index 0000000000..c5aab647a5 > --- /dev/null > +++ b/drivers/pinctrl/rockchip/pinctrl-rk3399.c > @@ -0,0 +1,193 @@ > +// SPDX-License-Identifier: GPL-2.0+ > +/* > + * (C) Copyright 2019 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 rk3399_mux_route_data[] = { > + { > + /* uart2dbga_rx */ > + .bank_num = 4, > + .pin = 8, > + .func = 2, > + .route_offset = 0xe21c, > + .route_val = BIT(16 + 10) | BIT(16 + 11), > + }, { > + /* uart2dbgb_rx */ > + .bank_num = 4, > + .pin = 16, > + .func = 2, > + .route_offset = 0xe21c, > + .route_val = BIT(16 + 10) | BIT(16 + 11) | BIT(10), > + }, { > + /* uart2dbgc_rx */ > + .bank_num = 4, > + .pin = 19, > + .func = 1, > + .route_offset = 0xe21c, > + .route_val = BIT(16 + 10) | BIT(16 + 11) | BIT(11), > + }, { > + /* pcie_clkreqn */ > + .bank_num = 2, > + .pin = 26, > + .func = 2, > + .route_offset = 0xe21c, > + .route_val = BIT(16 + 14), > + }, { > + /* pcie_clkreqnb */ > + .bank_num = 4, > + .pin = 24, > + .func = 1, > + .route_offset = 0xe21c, > + .route_val = BIT(16 + 14) | BIT(14), > + }, > +}; > + > +#define RK3399_PULL_GRF_OFFSET 0xe040 > +#define RK3399_PULL_PMU_OFFSET 0x40 > + > +static void rk3399_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank, > + int pin_num, struct regmap **regmap, > + int *reg, u8 *bit) > +{ > + struct rockchip_pinctrl_priv *priv = bank->priv; > + > + /* The bank0:16 and bank1:32 pins are located in PMU */ > + if (bank->bank_num == 0 || bank->bank_num == 1) { > + *regmap = priv->regmap_pmu; > + *reg = RK3399_PULL_PMU_OFFSET; > + > + *reg += bank->bank_num * ROCKCHIP_PULL_BANK_STRIDE; > + > + *reg += ((pin_num / ROCKCHIP_PULL_PINS_PER_REG) * 4); > + *bit = pin_num % ROCKCHIP_PULL_PINS_PER_REG; > + *bit *= ROCKCHIP_PULL_BITS_PER_PIN; > + } else { > + *regmap = priv->regmap_base; > + *reg = RK3399_PULL_GRF_OFFSET; > + > + /* correct the offset, as we're starting with the 3rd bank */ > + *reg -= 0x20; > + *reg += bank->bank_num * ROCKCHIP_PULL_BANK_STRIDE; > + *reg += ((pin_num / ROCKCHIP_PULL_PINS_PER_REG) * 4); > + > + *bit = (pin_num % ROCKCHIP_PULL_PINS_PER_REG); > + *bit *= ROCKCHIP_PULL_BITS_PER_PIN; > + } > +} > + > +static void rk3399_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank, > + int pin_num, struct regmap **regmap, > + int *reg, u8 *bit) > +{ > + struct rockchip_pinctrl_priv *priv = bank->priv; > + int drv_num = (pin_num / 8); > + > + /* The bank0:16 and bank1:32 pins are located in PMU */ > + if (bank->bank_num == 0 || bank->bank_num == 1) > + *regmap = priv->regmap_pmu; > + else > + *regmap = priv->regmap_base; > + > + *reg = bank->drv[drv_num].offset; > + if (bank->drv[drv_num].drv_type == DRV_TYPE_IO_1V8_3V0_AUTO || > + bank->drv[drv_num].drv_type == DRV_TYPE_IO_3V3_ONLY) > + *bit = (pin_num % 8) * 3; > + else > + *bit = (pin_num % 8) * 2; > +} > + > +static struct rockchip_pin_bank rk3399_pin_banks[] = { > + PIN_BANK_IOMUX_FLAGS_DRV_FLAGS_OFFSET_PULL_FLAGS(0, 32, "gpio0", > + IOMUX_SOURCE_PMU, > + IOMUX_SOURCE_PMU, > + IOMUX_SOURCE_PMU, > + IOMUX_SOURCE_PMU, > + DRV_TYPE_IO_1V8_ONLY, > + DRV_TYPE_IO_1V8_ONLY, > + DRV_TYPE_IO_DEFAULT, > + DRV_TYPE_IO_DEFAULT, > + 0x80, > + 0x88, > + -1, > + -1, > + PULL_TYPE_IO_1V8_ONLY, > + PULL_TYPE_IO_1V8_ONLY, > + PULL_TYPE_IO_DEFAULT, > + PULL_TYPE_IO_DEFAULT > + ), > + PIN_BANK_IOMUX_DRV_FLAGS_OFFSET(1, 32, "gpio1", IOMUX_SOURCE_PMU, > + IOMUX_SOURCE_PMU, > + IOMUX_SOURCE_PMU, > + IOMUX_SOURCE_PMU, > + DRV_TYPE_IO_1V8_OR_3V0, > + DRV_TYPE_IO_1V8_OR_3V0, > + DRV_TYPE_IO_1V8_OR_3V0, > + DRV_TYPE_IO_1V8_OR_3V0, > + 0xa0, > + 0xa8, > + 0xb0, > + 0xb8 > + ), > + PIN_BANK_DRV_FLAGS_PULL_FLAGS(2, 32, "gpio2", DRV_TYPE_IO_1V8_OR_3V0, > + DRV_TYPE_IO_1V8_OR_3V0, > + DRV_TYPE_IO_1V8_ONLY, > + DRV_TYPE_IO_1V8_ONLY, > + PULL_TYPE_IO_DEFAULT, > + PULL_TYPE_IO_DEFAULT, > + PULL_TYPE_IO_1V8_ONLY, > + PULL_TYPE_IO_1V8_ONLY > + ), > + PIN_BANK_DRV_FLAGS(3, 32, "gpio3", DRV_TYPE_IO_3V3_ONLY, > + DRV_TYPE_IO_3V3_ONLY, > + DRV_TYPE_IO_3V3_ONLY, > + DRV_TYPE_IO_1V8_OR_3V0 > + ), > + PIN_BANK_DRV_FLAGS(4, 32, "gpio4", DRV_TYPE_IO_1V8_OR_3V0, > + DRV_TYPE_IO_1V8_3V0_AUTO, > + DRV_TYPE_IO_1V8_OR_3V0, > + DRV_TYPE_IO_1V8_OR_3V0 > + ), > +}; > + > +static struct rockchip_pin_ctrl rk3399_pin_ctrl = { > + .pin_banks = rk3399_pin_banks, > + .nr_banks = ARRAY_SIZE(rk3399_pin_banks), > + .label = "RK3399-GPIO", > + .type = RK3399, > + .grf_mux_offset = 0xe000, > + .pmu_mux_offset = 0x0, > + .grf_drv_offset = 0xe100, > + .pmu_drv_offset = 0x80, > + .iomux_routes = rk3399_mux_route_data, > + .niomux_routes = ARRAY_SIZE(rk3399_mux_route_data), > + .pull_calc_reg = rk3399_calc_pull_reg_and_bit, > + .drv_calc_reg = rk3399_calc_drv_reg_and_bit, > +}; > + > +static const struct udevice_id rk3399_pinctrl_ids[] = { > + { > + .compatible = "rockchip,rk3399-pinctrl", > + .data = (ulong)&rk3399_pin_ctrl > + }, > + { } > +}; > + > +U_BOOT_DRIVER(pinctrl_rk3399) = { > + .name = "rockchip_rk3399_pinctrl", > + .id = UCLASS_PINCTRL, > + .of_match = rk3399_pinctrl_ids, > + .priv_auto_alloc_size = sizeof(struct rockchip_pinctrl_priv), > + .ops = &rockchip_pinctrl_ops, > +#if !CONFIG_IS_ENABLED(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 > new file mode 100644 > index 0000000000..b84b079064 > --- /dev/null > +++ b/drivers/pinctrl/rockchip/pinctrl-rockchip-core.c > @@ -0,0 +1,788 @@ > +// SPDX-License-Identifier: GPL-2.0+ > +/* > + * (C) Copyright 2019 Rockchip Electronics Co., Ltd > + */ > + > +#include <common.h> > +#include <dm.h> > +#include <dm/pinctrl.h> > +#include <regmap.h> > +#include <syscon.h> > +#include <fdtdec.h> > + > +#include "pinctrl-rockchip.h" > + > +#define MAX_ROCKCHIP_PINS_ENTRIES 30 > +#define MAX_ROCKCHIP_GPIO_PER_BANK 32 > +#define RK_FUNC_GPIO 0 > + > +static int rockchip_verify_config(struct udevice *dev, u32 bank, u32 pin) > +{ > + struct rockchip_pinctrl_priv *priv = dev_get_priv(dev); > + struct rockchip_pin_ctrl *ctrl = priv->ctrl; > + > + if (bank >= ctrl->nr_banks) { > + debug("pin conf bank %d >= nbanks %d\n", bank, ctrl->nr_banks); > + return -EINVAL; > + } > + > + if (pin >= MAX_ROCKCHIP_GPIO_PER_BANK) { > + debug("pin conf pin %d >= %d\n", pin, > + MAX_ROCKCHIP_GPIO_PER_BANK); > + return -EINVAL; > + } > + > + return 0; > +} > + > +static void rockchip_get_recalced_mux(struct rockchip_pin_bank *bank, int > pin, > + int *reg, u8 *bit, int *mask) > +{ > + struct rockchip_pinctrl_priv *priv = bank->priv; > + struct rockchip_pin_ctrl *ctrl = priv->ctrl; > + struct rockchip_mux_recalced_data *data; > + int i; > + > + for (i = 0; i < ctrl->niomux_recalced; i++) { > + data = &ctrl->iomux_recalced[i]; > + if (data->num == bank->bank_num && > + data->pin == pin) > + break; > + } > + > + if (i >= ctrl->niomux_recalced) > + return; > + > + *reg = data->reg; > + *mask = data->mask; > + *bit = data->bit; > +} > + > +static bool rockchip_get_mux_route(struct rockchip_pin_bank *bank, int pin, > + int mux, u32 *reg, u32 *value) > +{ > + struct rockchip_pinctrl_priv *priv = bank->priv; > + struct rockchip_pin_ctrl *ctrl = priv->ctrl; > + struct rockchip_mux_route_data *data; > + int i; > + > + for (i = 0; i < ctrl->niomux_routes; i++) { > + data = &ctrl->iomux_routes[i]; > + if (data->bank_num == bank->bank_num && > + data->pin == pin && data->func == mux) > + break; > + } > + > + if (i >= ctrl->niomux_routes) > + return false; > + > + *reg = data->route_offset; > + *value = data->route_val; > + > + return true; > +} > + > +static int rockchip_get_mux_data(int mux_type, int pin, u8 *bit, int *mask) > +{ > + int offset = 0; > + > + if (mux_type & IOMUX_WIDTH_4BIT) { > + if ((pin % 8) >= 4) > + offset = 0x4; > + *bit = (pin % 4) * 4; > + *mask = 0xf; > + } else if (mux_type & IOMUX_WIDTH_3BIT) { > + /* > + * pin0 ~ pin4 are at first register, and > + * pin5 ~ pin7 are at second register. > + */ > + if ((pin % 8) >= 5) > + offset = 0x4; > + *bit = (pin % 8 % 5) * 3; > + *mask = 0x7; > + } else { > + *bit = (pin % 8) * 2; > + *mask = 0x3; > + } > + > + return offset; > +} > + > +static int rockchip_get_mux(struct rockchip_pin_bank *bank, int pin) > +{ > + struct rockchip_pinctrl_priv *priv = bank->priv; > + int iomux_num = (pin / 8); > + struct regmap *regmap; > + unsigned int val; > + int reg, ret, mask, mux_type; > + u8 bit; > + > + if (iomux_num > 3) > + return -EINVAL; > + > + if (bank->iomux[iomux_num].type & IOMUX_UNROUTED) { > + debug("pin %d is unrouted\n", pin); > + return -EINVAL; > + } > + > + if (bank->iomux[iomux_num].type & IOMUX_GPIO_ONLY) > + return RK_FUNC_GPIO; > + > + regmap = (bank->iomux[iomux_num].type & IOMUX_SOURCE_PMU) > + ? priv->regmap_pmu : priv->regmap_base; > + > + /* get basic quadrupel of mux registers and the correct reg inside */ > + mux_type = bank->iomux[iomux_num].type; > + reg = bank->iomux[iomux_num].offset; > + reg += rockchip_get_mux_data(mux_type, pin, &bit, &mask); > + > + if (bank->recalced_mask & BIT(pin)) > + rockchip_get_recalced_mux(bank, pin, ®, &bit, &mask); > + > + ret = regmap_read(regmap, reg, &val); > + if (ret) > + return ret; > + > + return ((val >> bit) & mask); > +} > + > +static int rockchip_pinctrl_get_gpio_mux(struct udevice *dev, int banknum, > + int index) > +{ struct rockchip_pinctrl_priv *priv = dev_get_priv(dev); > + struct rockchip_pin_ctrl *ctrl = priv->ctrl; > + > + return rockchip_get_mux(&ctrl->pin_banks[banknum], index); > +} > + > +static int rockchip_verify_mux(struct rockchip_pin_bank *bank, > + int pin, int mux) > +{ > + int iomux_num = (pin / 8); > + > + if (iomux_num > 3) > + return -EINVAL; > + > + if (bank->iomux[iomux_num].type & IOMUX_UNROUTED) { > + debug("pin %d is unrouted\n", pin); > + return -EINVAL; > + } > + > + if (bank->iomux[iomux_num].type & IOMUX_GPIO_ONLY) { > + if (mux != IOMUX_GPIO_ONLY) { > + debug("pin %d only supports a gpio mux\n", pin); > + return -ENOTSUPP; > + } > + } > + > + return 0; > +} > + > +/* > + * Set a new mux function for a pin. > + * > + * The register is divided into the upper and lower 16 bit. When changing > + * a value, the previous register value is not read and changed. Instead > + * it seems the changed bits are marked in the upper 16 bit, while the > + * changed value gets set in the same offset in the lower 16 bit. > + * All pin settings seem to be 2 bit wide in both the upper and lower > + * parts. > + * @bank: pin bank to change > + * @pin: pin to change > + * @mux: new mux function to set > + */ > +static int rockchip_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, mux_type; > + u8 bit; > + u32 data, route_reg, route_val; > + > + ret = rockchip_verify_mux(bank, pin, mux); > + if (ret < 0) > + return ret; > + > + if (bank->iomux[iomux_num].type & IOMUX_GPIO_ONLY) > + return 0; > + > + debug("setting mux of GPIO%d-%d to %d\n", bank->bank_num, pin, mux); > + > + regmap = (bank->iomux[iomux_num].type & IOMUX_SOURCE_PMU) > + ? priv->regmap_pmu : priv->regmap_base; > + > + /* get basic quadrupel of mux registers and the correct reg inside */ > + mux_type = bank->iomux[iomux_num].type; > + reg = bank->iomux[iomux_num].offset; > + reg += rockchip_get_mux_data(mux_type, pin, &bit, &mask); > + > + if (bank->recalced_mask & BIT(pin)) > + rockchip_get_recalced_mux(bank, pin, ®, &bit, &mask); > + > + if (bank->route_mask & BIT(pin)) { > + if (rockchip_get_mux_route(bank, pin, mux, &route_reg, > + &route_val)) { > + ret = regmap_write(regmap, route_reg, route_val); > + if (ret) > + return ret; > + } > + } > + > + data = (mask << (bit + 16)); > + data |= (mux & mask) << bit; > + ret = regmap_write(regmap, reg, data); > + > + return ret; > +} > + > +static int rockchip_perpin_drv_list[DRV_TYPE_MAX][8] = { > + { 2, 4, 8, 12, -1, -1, -1, -1 }, > + { 3, 6, 9, 12, -1, -1, -1, -1 }, > + { 5, 10, 15, 20, -1, -1, -1, -1 }, > + { 4, 6, 8, 10, 12, 14, 16, 18 }, > + { 4, 7, 10, 13, 16, 19, 22, 26 } > +}; > + > +static int rockchip_set_drive_perpin(struct rockchip_pin_bank *bank, > + int pin_num, int strength) > +{ > + struct rockchip_pinctrl_priv *priv = bank->priv; > + struct rockchip_pin_ctrl *ctrl = priv->ctrl; > + struct regmap *regmap; > + int reg, ret, i; > + u32 data, rmask_bits, temp; > + u8 bit; > + int drv_type = bank->drv[pin_num / 8].drv_type; > + > + debug("setting drive of GPIO%d-%d to %d\n", bank->bank_num, > + pin_num, strength); > + > + ctrl->drv_calc_reg(bank, pin_num, ®map, ®, &bit); > + > + ret = -EINVAL; > + for (i = 0; i < ARRAY_SIZE(rockchip_perpin_drv_list[drv_type]); i++) { > + if (rockchip_perpin_drv_list[drv_type][i] == strength) { > + ret = i; > + break; > + } else if (rockchip_perpin_drv_list[drv_type][i] < 0) { > + ret = rockchip_perpin_drv_list[drv_type][i]; > + break; > + } > + } > + > + if (ret < 0) { > + debug("unsupported driver strength %d\n", strength); > + return ret; > + } > + > + switch (drv_type) { > + case DRV_TYPE_IO_1V8_3V0_AUTO: > + case DRV_TYPE_IO_3V3_ONLY: > + rmask_bits = ROCKCHIP_DRV_3BITS_PER_PIN; > + switch (bit) { > + case 0 ... 12: > + /* regular case, nothing to do */ > + break; > + case 15: > + /* > + * drive-strength offset is special, as it is spread > + * over 2 registers, the bit data[15] contains bit 0 > + * of the value while temp[1:0] contains bits 2 and 1 > + */ > + data = (ret & 0x1) << 15; > + temp = (ret >> 0x1) & 0x3; > + > + data |= BIT(31); > + ret = regmap_write(regmap, reg, data); > + if (ret) > + return ret; > + > + temp |= (0x3 << 16); > + reg += 0x4; > + ret = regmap_write(regmap, reg, temp); > + > + return ret; > + case 18 ... 21: > + /* setting fully enclosed in the second register */ > + reg += 4; > + bit -= 16; > + break; > + default: > + debug("unsupported bit: %d for pinctrl drive type: > %d\n", > + bit, drv_type); > + return -EINVAL; > + } > + break; > + case DRV_TYPE_IO_DEFAULT: > + case DRV_TYPE_IO_1V8_OR_3V0: > + case DRV_TYPE_IO_1V8_ONLY: > + rmask_bits = ROCKCHIP_DRV_BITS_PER_PIN; > + break; > + default: > + debug("unsupported pinctrl drive type: %d\n", > + drv_type); > + return -EINVAL; > + } > + > + /* enable the write to the equivalent lower bits */ > + data = ((1 << rmask_bits) - 1) << (bit + 16); > + data |= (ret << bit); > + > + ret = regmap_write(regmap, reg, data); > + return ret; > +} > + > +static int rockchip_pull_list[PULL_TYPE_MAX][4] = { > + { > + PIN_CONFIG_BIAS_DISABLE, > + PIN_CONFIG_BIAS_PULL_UP, > + PIN_CONFIG_BIAS_PULL_DOWN, > + PIN_CONFIG_BIAS_BUS_HOLD > + }, > + { > + PIN_CONFIG_BIAS_DISABLE, > + PIN_CONFIG_BIAS_PULL_DOWN, > + PIN_CONFIG_BIAS_DISABLE, > + PIN_CONFIG_BIAS_PULL_UP > + }, > +}; > + > +static int rockchip_set_pull(struct rockchip_pin_bank *bank, > + int pin_num, int pull) > +{ > + struct rockchip_pinctrl_priv *priv = bank->priv; > + struct rockchip_pin_ctrl *ctrl = priv->ctrl; > + struct regmap *regmap; > + int reg, ret, i, pull_type; > + u8 bit; > + u32 data; > + > + debug("setting pull of GPIO%d-%d to %d\n", bank->bank_num, > + pin_num, pull); > + > + ctrl->pull_calc_reg(bank, pin_num, ®map, ®, &bit); > + > + switch (ctrl->type) { > + case RK3036: > + case RK3128: > + data = BIT(bit + 16); > + if (pull == PIN_CONFIG_BIAS_DISABLE) > + data |= BIT(bit); > + ret = regmap_write(regmap, reg, data); > + break; > + case RV1108: > + case RK3188: > + case RK3288: > + case RK3368: > + case RK3399: > + pull_type = bank->pull_type[pin_num / 8]; > + ret = -EINVAL; > + for (i = 0; i < ARRAY_SIZE(rockchip_pull_list[pull_type]); > + i++) { > + if (rockchip_pull_list[pull_type][i] == pull) { > + ret = i; > + break; > + } > + } > + > + 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); > + break; > + default: > + debug("unsupported pinctrl type\n"); > + return -EINVAL; > + } > + > + return ret; > +} > + > +static int rockchip_set_schmitt(struct rockchip_pin_bank *bank, > + int pin_num, int enable) > +{ > + struct rockchip_pinctrl_priv *priv = bank->priv; > + struct rockchip_pin_ctrl *ctrl = priv->ctrl; > + struct regmap *regmap; > + int reg, ret; > + u8 bit; > + u32 data; > + > + debug("setting input schmitt of GPIO%d-%d to %d\n", bank->bank_num, > + pin_num, enable); > + > + ret = ctrl->schmitt_calc_reg(bank, pin_num, ®map, ®, &bit); > + if (ret) > + return ret; > + > + /* enable the write to the equivalent lower bits */ > + data = BIT(bit + 16) | (enable << bit); > + > + return regmap_write(regmap, reg, data); > +} > + > +/* > + * Pinconf_ops handling > + */ > +static bool rockchip_pinconf_pull_valid(struct rockchip_pin_ctrl *ctrl, > + unsigned int pull) > +{ > + switch (ctrl->type) { > + case RK3036: > + case RK3128: > + return (pull == PIN_CONFIG_BIAS_PULL_PIN_DEFAULT || > + pull == PIN_CONFIG_BIAS_DISABLE); > + case RV1108: > + case RK3188: > + case RK3288: > + case RK3368: > + case RK3399: > + return (pull != PIN_CONFIG_BIAS_PULL_PIN_DEFAULT); > + } > + > + return false; > +} > + > +/* set the pin config settings for a specified pin */ > +static int rockchip_pinconf_set(struct rockchip_pin_bank *bank, > + u32 pin, u32 param, u32 arg) > +{ > + struct rockchip_pinctrl_priv *priv = bank->priv; > + struct rockchip_pin_ctrl *ctrl = priv->ctrl; > + int rc; > + > + switch (param) { > + case PIN_CONFIG_BIAS_DISABLE: > + rc = rockchip_set_pull(bank, pin, param); > + if (rc) > + return rc; > + break; > + > + case PIN_CONFIG_BIAS_PULL_UP: > + case PIN_CONFIG_BIAS_PULL_DOWN: > + case PIN_CONFIG_BIAS_PULL_PIN_DEFAULT: > + case PIN_CONFIG_BIAS_BUS_HOLD: > + if (!rockchip_pinconf_pull_valid(ctrl, param)) > + return -ENOTSUPP; > + > + if (!arg) > + return -EINVAL; > + > + rc = rockchip_set_pull(bank, pin, param); > + if (rc) > + return rc; > + break; > + > + case PIN_CONFIG_DRIVE_STRENGTH: > + if (!ctrl->drv_calc_reg) > + return -ENOTSUPP; > + > + rc = rockchip_set_drive_perpin(bank, pin, arg); > + if (rc < 0) > + return rc; > + break; > + > + case PIN_CONFIG_INPUT_SCHMITT_ENABLE: > + if (!ctrl->schmitt_calc_reg) > + return -ENOTSUPP; > + > + rc = rockchip_set_schmitt(bank, pin, arg); > + if (rc < 0) > + return rc; > + break; > + > + default: > + break; > + } > + > + return 0; > +} > + > +static const struct pinconf_param rockchip_conf_params[] = { > + { "bias-disable", PIN_CONFIG_BIAS_DISABLE, 0 }, > + { "bias-bus-hold", PIN_CONFIG_BIAS_BUS_HOLD, 0 }, > + { "bias-pull-up", PIN_CONFIG_BIAS_PULL_UP, 1 }, > + { "bias-pull-down", PIN_CONFIG_BIAS_PULL_DOWN, 1 }, > + { "drive-strength", PIN_CONFIG_DRIVE_STRENGTH, 0 }, > + { "input-enable", PIN_CONFIG_INPUT_ENABLE, 1 }, > + { "input-disable", PIN_CONFIG_INPUT_ENABLE, 0 }, > + { "input-schmitt-disable", PIN_CONFIG_INPUT_SCHMITT_ENABLE, 0 }, > + { "input-schmitt-enable", PIN_CONFIG_INPUT_SCHMITT_ENABLE, 1 }, > +}; > + > +static int rockchip_pinconf_prop_name_to_param(const char *property, > + u32 *default_value) > +{ > + const struct pinconf_param *p, *end; > + > + p = rockchip_conf_params; > + end = p + sizeof(rockchip_conf_params) / sizeof(struct pinconf_param); > + > + /* See if this pctldev supports this parameter */ > + for (; p < end; p++) { > + if (!strcmp(property, p->property)) { > + *default_value = p->default_value; > + return p->param; > + } > + } > + > + *default_value = 0; > + return -EPERM; > +} > + > +static int rockchip_pinctrl_set_state(struct udevice *dev, > + struct udevice *config) > +{ > + struct rockchip_pinctrl_priv *priv = dev_get_priv(dev); > + struct rockchip_pin_ctrl *ctrl = priv->ctrl; > + u32 cells[MAX_ROCKCHIP_PINS_ENTRIES * 4]; > + u32 bank, pin, mux, conf, arg, default_val; > + int ret, count, i; > + const char *prop_name; > + const void *value; > + int prop_len, param; > + const u32 *data; > + ofnode node; > +#ifdef CONFIG_OF_LIVE > + const struct device_node *np; > + struct property *pp; > +#else > + int property_offset, pcfg_node; > + const void *blob = gd->fdt_blob; > +#endif > + data = dev_read_prop(config, "rockchip,pins", &count); > + if (count < 0) { > + debug("%s: bad array size %d\n", __func__, count); > + return -EINVAL; > + } > + > + count /= sizeof(u32); > + if (count > MAX_ROCKCHIP_PINS_ENTRIES * 4) { > + debug("%s: unsupported pins array count %d\n", > + __func__, count); > + return -EINVAL; > + } > + > + for (i = 0; i < count; i++) > + cells[i] = fdt32_to_cpu(data[i]); > + > + for (i = 0; i < (count >> 2); i++) { > + bank = cells[4 * i + 0]; > + pin = cells[4 * i + 1]; > + mux = cells[4 * i + 2]; > + conf = cells[4 * i + 3]; > + > + ret = rockchip_verify_config(dev, bank, pin); > + if (ret) > + return ret; > + > + ret = rockchip_set_mux(&ctrl->pin_banks[bank], pin, mux); > + if (ret) > + return ret; > + > + node = ofnode_get_by_phandle(conf); > + if (!ofnode_valid(node)) > + return -ENODEV; > +#ifdef CONFIG_OF_LIVE > + np = ofnode_to_np(node); > + for (pp = np->properties; pp; pp = pp->next) { > + prop_name = pp->name; > + prop_len = pp->length; > + value = pp->value; > +#else > + pcfg_node = ofnode_to_offset(node); > + fdt_for_each_property_offset(property_offset, blob, pcfg_node) { > + value = fdt_getprop_by_offset(blob, property_offset, > + &prop_name, &prop_len); > + if (!value) > + return -ENOENT; > +#endif > + param = rockchip_pinconf_prop_name_to_param(prop_name, > + > &default_val); > + if (param < 0) > + break; > + > + if (prop_len >= sizeof(fdt32_t)) > + arg = fdt32_to_cpu(*(fdt32_t *)value); > + else > + arg = default_val; > + > + ret = rockchip_pinconf_set(&ctrl->pin_banks[bank], pin, > + param, arg); > + if (ret) { > + debug("%s: rockchip_pinconf_set fail: %d\n", > + __func__, ret); > + return ret; > + } > + } > + } > + > + return 0; > +} > + > +const struct pinctrl_ops rockchip_pinctrl_ops = { > + .set_state = rockchip_pinctrl_set_state, > + .get_gpio_mux = rockchip_pinctrl_get_gpio_mux, > +}; > + > +/* retrieve the soc specific data */ > +static struct rockchip_pin_ctrl *rockchip_pinctrl_get_soc_data(struct > udevice *dev) > +{ > + struct rockchip_pinctrl_priv *priv = dev_get_priv(dev); > + struct rockchip_pin_ctrl *ctrl = > + (struct rockchip_pin_ctrl *)dev_get_driver_data(dev); > + struct rockchip_pin_bank *bank; > + int grf_offs, pmu_offs, drv_grf_offs, drv_pmu_offs, i, j; > + > + grf_offs = ctrl->grf_mux_offset; > + pmu_offs = ctrl->pmu_mux_offset; > + drv_pmu_offs = ctrl->pmu_drv_offset; > + drv_grf_offs = ctrl->grf_drv_offset; > + bank = ctrl->pin_banks; > + > + for (i = 0; i < ctrl->nr_banks; ++i, ++bank) { > + int bank_pins = 0; > + > + bank->priv = priv; > + bank->pin_base = ctrl->nr_pins; > + ctrl->nr_pins += bank->nr_pins; > + > + /* calculate iomux and drv offsets */ > + for (j = 0; j < 4; j++) { > + struct rockchip_iomux *iom = &bank->iomux[j]; > + struct rockchip_drv *drv = &bank->drv[j]; > + int inc; > + > + if (bank_pins >= bank->nr_pins) > + break; > + > + /* preset iomux offset value, set new start value */ > + if (iom->offset >= 0) { > + if (iom->type & IOMUX_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; > + } > + > + /* preset drv offset value, set new start value */ > + if (drv->offset >= 0) { > + if (iom->type & IOMUX_SOURCE_PMU) > + drv_pmu_offs = drv->offset; > + else > + drv_grf_offs = drv->offset; > + } else { /* set current drv offset */ > + drv->offset = (iom->type & IOMUX_SOURCE_PMU) ? > + drv_pmu_offs : drv_grf_offs; > + } > + > + debug("bank %d, iomux %d has iom_offset 0x%x drv_offset > 0x%x\n", > + i, j, iom->offset, drv->offset); > + > + /* > + * Increase offset according to iomux width. > + * 4bit iomux'es are spread over two registers. > + */ > + inc = (iom->type & (IOMUX_WIDTH_4BIT | > + IOMUX_WIDTH_3BIT)) ? 8 : 4; > + if (iom->type & IOMUX_SOURCE_PMU) > + pmu_offs += inc; > + else > + grf_offs += inc; > + > + /* > + * Increase offset according to drv width. > + * 3bit drive-strenth'es are spread over two registers. > + */ > + if ((drv->drv_type == DRV_TYPE_IO_1V8_3V0_AUTO) || > + (drv->drv_type == DRV_TYPE_IO_3V3_ONLY)) > + inc = 8; > + else > + inc = 4; > + > + if (iom->type & IOMUX_SOURCE_PMU) > + drv_pmu_offs += inc; > + else > + drv_grf_offs += inc; > + > + bank_pins += 8; > + } > + > + /* calculate the per-bank recalced_mask */ > + for (j = 0; j < ctrl->niomux_recalced; j++) { > + int pin = 0; > + > + if (ctrl->iomux_recalced[j].num == bank->bank_num) { > + pin = ctrl->iomux_recalced[j].pin; > + bank->recalced_mask |= BIT(pin); > + } > + } > + > + /* calculate the per-bank route_mask */ > + for (j = 0; j < ctrl->niomux_routes; j++) { > + int pin = 0; > + > + if (ctrl->iomux_routes[j].bank_num == bank->bank_num) { > + pin = ctrl->iomux_routes[j].pin; > + bank->route_mask |= BIT(pin); > + } > + } > + } > + > + return ctrl; > +} > + > +int rockchip_pinctrl_probe(struct udevice *dev) > +{ > + struct rockchip_pinctrl_priv *priv = dev_get_priv(dev); > + struct rockchip_pin_ctrl *ctrl; > + struct udevice *syscon; > + struct regmap *regmap; > + int ret = 0; > + > + /* get rockchip grf syscon phandle */ > + ret = uclass_get_device_by_phandle(UCLASS_SYSCON, dev, "rockchip,grf", > + &syscon); > + if (ret) { > + debug("unable to find rockchip,grf syscon device (%d)\n", ret); > + return ret; > + } > + > + /* get grf-reg base address */ > + regmap = syscon_get_regmap(syscon); > + if (!regmap) { > + debug("unable to find rockchip grf regmap\n"); > + return -ENODEV; > + } > + priv->regmap_base = regmap; > + > + /* option: get pmu-reg base address */ > + ret = uclass_get_device_by_phandle(UCLASS_SYSCON, dev, "rockchip,pmu", > + &syscon); > + if (!ret) { > + /* get pmugrf-reg base address */ > + regmap = syscon_get_regmap(syscon); > + if (!regmap) { > + debug("unable to find rockchip pmu regmap\n"); > + return -ENODEV; > + } > + priv->regmap_pmu = regmap; > + } > + > + ctrl = rockchip_pinctrl_get_soc_data(dev); > + if (!ctrl) { > + debug("driver data not available\n"); > + return -EINVAL; > + } > + > + priv->ctrl = ctrl; > + return 0; > +} > diff --git a/drivers/pinctrl/rockchip/pinctrl-rockchip.h > b/drivers/pinctrl/rockchip/pinctrl-rockchip.h > new file mode 100644 > index 0000000000..bc809630c1 > --- /dev/null > +++ b/drivers/pinctrl/rockchip/pinctrl-rockchip.h > @@ -0,0 +1,302 @@ > +/* SPDX-License-Identifier: GPL-2.0+ */ > +/* > + * (C) Copyright 2019 Rockchip Electronics Co., Ltd > + */ > + > +#ifndef __DRIVERS_PINCTRL_ROCKCHIP_H > +#define __DRIVERS_PINCTRL_ROCKCHIP_H > + > +#include <linux/types.h> > + > +enum rockchip_pinctrl_type { > + RV1108, > + RK3036, > + RK3128, > + RK3188, > + RK3288, > + RK3368, > + RK3399, > +}; > + > +/** > + * Encode variants of iomux registers into a type variable > + */ > +#define IOMUX_GPIO_ONLY BIT(0) > +#define IOMUX_WIDTH_4BIT BIT(1) > +#define IOMUX_SOURCE_PMU BIT(2) > +#define IOMUX_UNROUTED BIT(3) > +#define IOMUX_WIDTH_3BIT BIT(4) > + > +/** > + * Defined some common pins constants > + */ > +#define ROCKCHIP_PULL_BITS_PER_PIN 2 > +#define ROCKCHIP_PULL_PINS_PER_REG 8 > +#define ROCKCHIP_PULL_BANK_STRIDE 16 > +#define ROCKCHIP_DRV_BITS_PER_PIN 2 > +#define ROCKCHIP_DRV_PINS_PER_REG 8 > +#define ROCKCHIP_DRV_BANK_STRIDE 16 > +#define ROCKCHIP_DRV_3BITS_PER_PIN 3 > + > +/** > + * @type: iomux variant using IOMUX_* constants > + * @offset: if initialized to -1 it will be autocalculated, by specifying > + * an initial offset value the relevant source offset can be reset > + * to a new value for autocalculating the following iomux registers. > + */ > +struct rockchip_iomux { > + int type; > + int offset; > +}; > + > +/** > + * enum type index corresponding to rockchip_perpin_drv_list arrays index. > + */ > +enum rockchip_pin_drv_type { > + DRV_TYPE_IO_DEFAULT = 0, > + DRV_TYPE_IO_1V8_OR_3V0, > + DRV_TYPE_IO_1V8_ONLY, > + DRV_TYPE_IO_1V8_3V0_AUTO, > + DRV_TYPE_IO_3V3_ONLY, > + DRV_TYPE_MAX > +}; > + > +/** > + * enum type index corresponding to rockchip_pull_list arrays index. > + */ > +enum rockchip_pin_pull_type { > + PULL_TYPE_IO_DEFAULT = 0, > + PULL_TYPE_IO_1V8_ONLY, > + PULL_TYPE_MAX > +}; > + > +/** > + * @drv_type: drive strength variant using rockchip_perpin_drv_type > + * @offset: if initialized to -1 it will be autocalculated, by specifying > + * an initial offset value the relevant source offset can be reset > + * to a new value for autocalculating the following drive strength > + * registers. if used chips own cal_drv func instead to calculate > + * registers offset, the variant could be ignored. > + */ > +struct rockchip_drv { > + enum rockchip_pin_drv_type drv_type; > + int offset; > +}; > + > +/** > + * @priv: common pinctrl private basedata > + * @pin_base: first pin number > + * @nr_pins: number of pins in this bank > + * @name: name of the bank > + * @bank_num: number of the bank, to account for holes > + * @iomux: array describing the 4 iomux sources of the bank > + * @drv: array describing the 4 drive strength sources of the bank > + * @pull_type: array describing the 4 pull type sources of the bank > + * @recalced_mask: bits describing the mux recalced pins of per bank > + * @route_mask: bits describing the routing pins of per bank > + */ > +struct rockchip_pin_bank { > + struct rockchip_pinctrl_priv *priv; > + u32 pin_base; > + u8 nr_pins; > + char *name; > + u8 bank_num; > + struct rockchip_iomux iomux[4]; > + struct rockchip_drv drv[4]; > + enum rockchip_pin_pull_type pull_type[4]; > + u32 recalced_mask; > + u32 route_mask; > +}; > + > +#define PIN_BANK(id, pins, label) \ > + { \ > + .bank_num = id, \ > + .nr_pins = pins, \ > + .name = label, \ > + .iomux = { \ > + { .offset = -1 }, \ > + { .offset = -1 }, \ > + { .offset = -1 }, \ > + { .offset = -1 }, \ > + }, \ > + } > + > +#define PIN_BANK_IOMUX_FLAGS(id, pins, label, iom0, iom1, iom2, iom3) > \ > + { \ > + .bank_num = id, \ > + .nr_pins = pins, \ > + .name = label, \ > + .iomux = { \ > + { .type = iom0, .offset = -1 }, \ > + { .type = iom1, .offset = -1 }, \ > + { .type = iom2, .offset = -1 }, \ > + { .type = iom3, .offset = -1 }, \ > + }, \ > + } > + > +#define PIN_BANK_DRV_FLAGS(id, pins, label, type0, type1, type2, type3) \ > + { \ > + .bank_num = id, \ > + .nr_pins = pins, \ > + .name = label, \ > + .iomux = { \ > + { .offset = -1 }, \ > + { .offset = -1 }, \ > + { .offset = -1 }, \ > + { .offset = -1 }, \ > + }, \ > + .drv = { \ > + { .drv_type = type0, .offset = -1 }, \ > + { .drv_type = type1, .offset = -1 }, \ > + { .drv_type = type2, .offset = -1 }, \ > + { .drv_type = type3, .offset = -1 }, \ > + }, \ > + } > + > +#define PIN_BANK_DRV_FLAGS_PULL_FLAGS(id, pins, label, drv0, drv1, \ > + drv2, drv3, pull0, pull1, \ > + pull2, pull3) \ > + { \ > + .bank_num = id, \ > + .nr_pins = pins, \ > + .name = label, \ > + .iomux = { \ > + { .offset = -1 }, \ > + { .offset = -1 }, \ > + { .offset = -1 }, \ > + { .offset = -1 }, \ > + }, \ > + .drv = { \ > + { .drv_type = drv0, .offset = -1 }, \ > + { .drv_type = drv1, .offset = -1 }, \ > + { .drv_type = drv2, .offset = -1 }, \ > + { .drv_type = drv3, .offset = -1 }, \ > + }, \ > + .pull_type[0] = pull0, \ > + .pull_type[1] = pull1, \ > + .pull_type[2] = pull2, \ > + .pull_type[3] = pull3, \ > + } > + > +#define PIN_BANK_IOMUX_DRV_FLAGS_OFFSET(id, pins, label, iom0, iom1, \ > + iom2, iom3, drv0, drv1, drv2, \ > + drv3, offset0, offset1, \ > + offset2, offset3) \ > + { \ > + .bank_num = id, \ > + .nr_pins = pins, \ > + .name = label, \ > + .iomux = { \ > + { .type = iom0, .offset = -1 }, \ > + { .type = iom1, .offset = -1 }, \ > + { .type = iom2, .offset = -1 }, \ > + { .type = iom3, .offset = -1 }, \ > + }, \ > + .drv = { \ > + { .drv_type = drv0, .offset = offset0 }, \ > + { .drv_type = drv1, .offset = offset1 }, \ > + { .drv_type = drv2, .offset = offset2 }, \ > + { .drv_type = drv3, .offset = offset3 }, \ > + }, \ > + } > + > +#define PIN_BANK_IOMUX_FLAGS_DRV_FLAGS_OFFSET_PULL_FLAGS(id, pins, \ > + label, iom0, iom1, iom2, \ > + iom3, drv0, drv1, drv2, \ > + drv3, offset0, offset1, \ > + offset2, offset3, pull0, \ > + pull1, pull2, pull3) \ > + { \ > + .bank_num = id, \ > + .nr_pins = pins, \ > + .name = label, \ > + .iomux = { \ > + { .type = iom0, .offset = -1 }, \ > + { .type = iom1, .offset = -1 }, \ > + { .type = iom2, .offset = -1 }, \ > + { .type = iom3, .offset = -1 }, \ > + }, \ > + .drv = { \ > + { .drv_type = drv0, .offset = offset0 }, \ > + { .drv_type = drv1, .offset = offset1 }, \ > + { .drv_type = drv2, .offset = offset2 }, \ > + { .drv_type = drv3, .offset = offset3 }, \ > + }, \ > + .pull_type[0] = pull0, \ > + .pull_type[1] = pull1, \ > + .pull_type[2] = pull2, \ > + .pull_type[3] = pull3, \ > + } > + > +/** > + * struct rockchip_mux_recalced_data: recalculate a pin iomux data. > + * @num: bank number. > + * @pin: pin number. > + * @reg: register offset. > + * @bit: index at register. > + * @mask: mask bit > + */ > +struct rockchip_mux_recalced_data { > + u8 num; > + u8 pin; > + u32 reg; > + u8 bit; > + u8 mask; > +}; > + > +/** > + * struct rockchip_mux_route_data: route a pin iomux data. > + * @bank_num: bank number. > + * @pin: index at register or used to calc index. > + * @func: the min pin. > + * @route_offset: the max pin. > + * @route_val: the register offset. > + */ > +struct rockchip_mux_route_data { > + u8 bank_num; > + u8 pin; > + u8 func; > + u32 route_offset; > + u32 route_val; > +}; > + > +/** > + */ > +struct rockchip_pin_ctrl { > + struct rockchip_pin_bank *pin_banks; > + u32 nr_banks; > + u32 nr_pins; > + char *label; > + enum rockchip_pinctrl_type type; > + int grf_mux_offset; > + int pmu_mux_offset; > + int grf_drv_offset; > + int pmu_drv_offset; > + struct rockchip_mux_recalced_data *iomux_recalced; > + u32 niomux_recalced; > + struct rockchip_mux_route_data *iomux_routes; > + u32 niomux_routes; > + > + void (*pull_calc_reg)(struct rockchip_pin_bank *bank, > + int pin_num, struct regmap **regmap, > + int *reg, u8 *bit); > + void (*drv_calc_reg)(struct rockchip_pin_bank *bank, > + int pin_num, struct regmap **regmap, > + int *reg, u8 *bit); > + int (*schmitt_calc_reg)(struct rockchip_pin_bank *bank, > + int pin_num, struct regmap **regmap, > + int *reg, u8 *bit); > +}; > + > +/** > + */ > +struct rockchip_pinctrl_priv { > + struct rockchip_pin_ctrl *ctrl; > + struct regmap *regmap_base; > + struct regmap *regmap_pmu; > +}; > + > +extern const struct pinctrl_ops rockchip_pinctrl_ops; > +int rockchip_pinctrl_probe(struct udevice *dev); > + > +#endif /* __DRIVERS_PINCTRL_ROCKCHIP_H */ > diff --git a/drivers/pinctrl/rockchip/pinctrl-rv1108.c > b/drivers/pinctrl/rockchip/pinctrl-rv1108.c > new file mode 100644 > index 0000000000..f4a09a6824 > --- /dev/null > +++ b/drivers/pinctrl/rockchip/pinctrl-rv1108.c > @@ -0,0 +1,203 @@ > +// SPDX-License-Identifier: GPL-2.0+ > +/* > + * (C) Copyright 2019 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_recalced_data rv1108_mux_recalced_data[] = { > + { > + .num = 1, > + .pin = 0, > + .reg = 0x418, > + .bit = 0, > + .mask = 0x3 > + }, { > + .num = 1, > + .pin = 1, > + .reg = 0x418, > + .bit = 2, > + .mask = 0x3 > + }, { > + .num = 1, > + .pin = 2, > + .reg = 0x418, > + .bit = 4, > + .mask = 0x3 > + }, { > + .num = 1, > + .pin = 3, > + .reg = 0x418, > + .bit = 6, > + .mask = 0x3 > + }, { > + .num = 1, > + .pin = 4, > + .reg = 0x418, > + .bit = 8, > + .mask = 0x3 > + }, { > + .num = 1, > + .pin = 5, > + .reg = 0x418, > + .bit = 10, > + .mask = 0x3 > + }, { > + .num = 1, > + .pin = 6, > + .reg = 0x418, > + .bit = 12, > + .mask = 0x3 > + }, { > + .num = 1, > + .pin = 7, > + .reg = 0x418, > + .bit = 14, > + .mask = 0x3 > + }, { > + .num = 1, > + .pin = 8, > + .reg = 0x41c, > + .bit = 0, > + .mask = 0x3 > + }, { > + .num = 1, > + .pin = 9, > + .reg = 0x41c, > + .bit = 2, > + .mask = 0x3 > + }, > +}; > + > +#define RV1108_PULL_PMU_OFFSET 0x10 > +#define RV1108_PULL_OFFSET 0x110 > + > +static void rv1108_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank, > + int pin_num, struct regmap **regmap, > + int *reg, u8 *bit) > +{ > + struct rockchip_pinctrl_priv *priv = bank->priv; > + > + /* The first 24 pins of the first bank are located in PMU */ > + if (bank->bank_num == 0) { > + *regmap = priv->regmap_pmu; > + *reg = RV1108_PULL_PMU_OFFSET; > + } else { > + *reg = RV1108_PULL_OFFSET; > + *regmap = priv->regmap_base; > + /* correct the offset, as we're starting with the 2nd bank */ > + *reg -= 0x10; > + *reg += bank->bank_num * ROCKCHIP_PULL_BANK_STRIDE; > + } > + > + *reg += ((pin_num / ROCKCHIP_PULL_PINS_PER_REG) * 4); > + *bit = (pin_num % ROCKCHIP_PULL_PINS_PER_REG); > + *bit *= ROCKCHIP_PULL_BITS_PER_PIN; > +} > + > +#define RV1108_DRV_PMU_OFFSET 0x20 > +#define RV1108_DRV_GRF_OFFSET 0x210 > + > +static void rv1108_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank, > + int pin_num, struct regmap **regmap, > + int *reg, u8 *bit) > +{ > + struct rockchip_pinctrl_priv *priv = bank->priv; > + > + /* The first 24 pins of the first bank are located in PMU */ > + if (bank->bank_num == 0) { > + *regmap = priv->regmap_pmu; > + *reg = RV1108_DRV_PMU_OFFSET; > + } else { > + *regmap = priv->regmap_base; > + *reg = RV1108_DRV_GRF_OFFSET; > + > + /* correct the offset, as we're starting with the 2nd bank */ > + *reg -= 0x10; > + *reg += bank->bank_num * ROCKCHIP_DRV_BANK_STRIDE; > + } > + > + *reg += ((pin_num / ROCKCHIP_DRV_PINS_PER_REG) * 4); > + *bit = pin_num % ROCKCHIP_DRV_PINS_PER_REG; > + *bit *= ROCKCHIP_DRV_BITS_PER_PIN; > +} > + > +#define RV1108_SCHMITT_PMU_OFFSET 0x30 > +#define RV1108_SCHMITT_GRF_OFFSET 0x388 > +#define RV1108_SCHMITT_BANK_STRIDE 8 > +#define RV1108_SCHMITT_PINS_PER_GRF_REG 16 > +#define RV1108_SCHMITT_PINS_PER_PMU_REG 8 > + > +static int rv1108_calc_schmitt_reg_and_bit(struct rockchip_pin_bank *bank, > + int pin_num, > + struct regmap **regmap, > + int *reg, u8 *bit) > +{ > + struct rockchip_pinctrl_priv *priv = bank->priv; > + int pins_per_reg; > + > + if (bank->bank_num == 0) { > + *regmap = priv->regmap_pmu; > + *reg = RV1108_SCHMITT_PMU_OFFSET; > + pins_per_reg = RV1108_SCHMITT_PINS_PER_PMU_REG; > + } else { > + *regmap = priv->regmap_base; > + *reg = RV1108_SCHMITT_GRF_OFFSET; > + pins_per_reg = RV1108_SCHMITT_PINS_PER_GRF_REG; > + *reg += (bank->bank_num - 1) * RV1108_SCHMITT_BANK_STRIDE; > + } > + *reg += ((pin_num / pins_per_reg) * 4); > + *bit = pin_num % pins_per_reg; > + > + return 0; > +} > + > +static struct rockchip_pin_bank rv1108_pin_banks[] = { > + PIN_BANK_IOMUX_FLAGS(0, 32, "gpio0", IOMUX_SOURCE_PMU, > + IOMUX_SOURCE_PMU, > + IOMUX_SOURCE_PMU, > + IOMUX_SOURCE_PMU), > + PIN_BANK_IOMUX_FLAGS(1, 32, "gpio1", 0, 0, 0, 0), > + PIN_BANK_IOMUX_FLAGS(2, 32, "gpio2", 0, 0, 0, 0), > + PIN_BANK_IOMUX_FLAGS(3, 32, "gpio3", 0, 0, 0, 0), > +}; > + > +static struct rockchip_pin_ctrl rv1108_pin_ctrl = { > + .pin_banks = rv1108_pin_banks, > + .nr_banks = ARRAY_SIZE(rv1108_pin_banks), > + .label = "RV1108-GPIO", > + .type = RV1108, > + .grf_mux_offset = 0x10, > + .pmu_mux_offset = 0x0, > + .iomux_recalced = rv1108_mux_recalced_data, > + .niomux_recalced = ARRAY_SIZE(rv1108_mux_recalced_data), > + .pull_calc_reg = rv1108_calc_pull_reg_and_bit, > + .drv_calc_reg = rv1108_calc_drv_reg_and_bit, > + .schmitt_calc_reg = rv1108_calc_schmitt_reg_and_bit, > +}; > + > +static const struct udevice_id rv1108_pinctrl_ids[] = { > + { > + .compatible = "rockchip,rv1108-pinctrl", > + .data = (ulong)&rv1108_pin_ctrl > + }, > + { } > +}; > + > +U_BOOT_DRIVER(pinctrl_rv1108) = { > + .name = "pinctrl_rv1108", > + .id = UCLASS_PINCTRL, > + .of_match = rv1108_pinctrl_ids, > + .priv_auto_alloc_size = sizeof(struct rockchip_pinctrl_priv), > + .ops = &rockchip_pinctrl_ops, > +#if !CONFIG_IS_ENABLED(OF_PLATDATA) > + .bind = dm_scan_fdt_dev, > +#endif > + .probe = rockchip_pinctrl_probe, > +}; _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot