// SPDX-License-Identifier: GPL-2.0+ /* * (C) Copyright 2021 Rockchip Electronics Co., Ltd */ #include #include #include #include #include "pinctrl-rockchip.h" #include static int rk3588_set_mux(struct rockchip_pin_bank *bank, int pin, int mux) { struct rockchip_pinctrl_priv *priv = bank->priv; struct regmap *regmap; int iomux_num = (pin / 8); int reg, ret, mask; u8 bit; u32 data; debug("setting mux of GPIO%d-%d to %d\n", bank->bank_num, pin, mux); regmap = priv->regmap_base; reg = bank->iomux[iomux_num].offset; if ((pin % 8) >= 4) reg += 0x4; bit = (pin % 4) * 4; mask = 0xf; if (bank->bank_num == 0) { if (pin >= RK_PB4 && pin <= RK_PD7) { if (mux < 8) { reg += 0x4000 - 0xC; /* PMU2_IOC_BASE */ data = (mask << (bit + 16)); data |= (mux & mask) << bit; ret = regmap_write(regmap, reg, data); } else { u32 reg0 = 0; reg0 = reg + 0x4000 - 0xC; /* PMU2_IOC_BASE */ data = (mask << (bit + 16)); data |= 8 << bit; ret = regmap_write(regmap, reg0, data); reg0 = reg + 0x8000; /* BUS_IOC_BASE */ data = (mask << (bit + 16)); data |= mux << bit; regmap = priv->regmap_base; regmap_write(regmap, reg0, data); } } else { data = (mask << (bit + 16)); data |= (mux & mask) << bit; ret = regmap_write(regmap, reg, data); } return ret; } else if (bank->bank_num > 0) { reg += 0x8000; /* BUS_IOC_BASE */ } data = (mask << (bit + 16)); data |= (mux & mask) << bit; return regmap_write(regmap, reg, data); } #define RK3588_PMU1_IOC_REG (0x0000) #define RK3588_PMU2_IOC_REG (0x4000) #define RK3588_BUS_IOC_REG (0x8000) #define RK3588_VCCIO1_4_IOC_REG (0x9000) #define RK3588_VCCIO3_5_IOC_REG (0xA000) #define RK3588_VCCIO2_IOC_REG (0xB000) #define RK3588_VCCIO6_IOC_REG (0xC000) #define RK3588_EMMC_IOC_REG (0xD000) static const u32 rk3588_ds_regs[][2] = { {RK_GPIO0_A0, RK3588_PMU1_IOC_REG + 0x0010}, {RK_GPIO0_A4, RK3588_PMU1_IOC_REG + 0x0014}, {RK_GPIO0_B0, RK3588_PMU1_IOC_REG + 0x0018}, {RK_GPIO0_B4, RK3588_PMU2_IOC_REG + 0x0014}, {RK_GPIO0_C0, RK3588_PMU2_IOC_REG + 0x0018}, {RK_GPIO0_C4, RK3588_PMU2_IOC_REG + 0x001C}, {RK_GPIO0_D0, RK3588_PMU2_IOC_REG + 0x0020}, {RK_GPIO0_D4, RK3588_PMU2_IOC_REG + 0x0024}, {RK_GPIO1_A0, RK3588_VCCIO1_4_IOC_REG + 0x0020}, {RK_GPIO1_A4, RK3588_VCCIO1_4_IOC_REG + 0x0024}, {RK_GPIO1_B0, RK3588_VCCIO1_4_IOC_REG + 0x0028}, {RK_GPIO1_B4, RK3588_VCCIO1_4_IOC_REG + 0x002C}, {RK_GPIO1_C0, RK3588_VCCIO1_4_IOC_REG + 0x0030}, {RK_GPIO1_C4, RK3588_VCCIO1_4_IOC_REG + 0x0034}, {RK_GPIO1_D0, RK3588_VCCIO1_4_IOC_REG + 0x0038}, {RK_GPIO1_D4, RK3588_VCCIO1_4_IOC_REG + 0x003C}, {RK_GPIO2_A0, RK3588_EMMC_IOC_REG + 0x0040}, {RK_GPIO2_A4, RK3588_VCCIO3_5_IOC_REG + 0x0044}, {RK_GPIO2_B0, RK3588_VCCIO3_5_IOC_REG + 0x0048}, {RK_GPIO2_B4, RK3588_VCCIO3_5_IOC_REG + 0x004C}, {RK_GPIO2_C0, RK3588_VCCIO3_5_IOC_REG + 0x0050}, {RK_GPIO2_C4, RK3588_VCCIO3_5_IOC_REG + 0x0054}, {RK_GPIO2_D0, RK3588_EMMC_IOC_REG + 0x0058}, {RK_GPIO2_D4, RK3588_EMMC_IOC_REG + 0x005C}, {RK_GPIO3_A0, RK3588_VCCIO3_5_IOC_REG + 0x0060}, {RK_GPIO3_A4, RK3588_VCCIO3_5_IOC_REG + 0x0064}, {RK_GPIO3_B0, RK3588_VCCIO3_5_IOC_REG + 0x0068}, {RK_GPIO3_B4, RK3588_VCCIO3_5_IOC_REG + 0x006C}, {RK_GPIO3_C0, RK3588_VCCIO3_5_IOC_REG + 0x0070}, {RK_GPIO3_C4, RK3588_VCCIO3_5_IOC_REG + 0x0074}, {RK_GPIO3_D0, RK3588_VCCIO3_5_IOC_REG + 0x0078}, {RK_GPIO3_D4, RK3588_VCCIO3_5_IOC_REG + 0x007C}, {RK_GPIO4_A0, RK3588_VCCIO6_IOC_REG + 0x0080}, {RK_GPIO4_A4, RK3588_VCCIO6_IOC_REG + 0x0084}, {RK_GPIO4_B0, RK3588_VCCIO6_IOC_REG + 0x0088}, {RK_GPIO4_B4, RK3588_VCCIO6_IOC_REG + 0x008C}, {RK_GPIO4_C0, RK3588_VCCIO6_IOC_REG + 0x0090}, {RK_GPIO4_C2, RK3588_VCCIO3_5_IOC_REG + 0x0090}, {RK_GPIO4_C4, RK3588_VCCIO3_5_IOC_REG + 0x0094}, {RK_GPIO4_D0, RK3588_VCCIO2_IOC_REG + 0x0098}, {RK_GPIO4_D4, RK3588_VCCIO2_IOC_REG + 0x009C}, }; static const u32 rk3588_p_regs[][2] = { {RK_GPIO0_A0, RK3588_PMU1_IOC_REG + 0x0020}, {RK_GPIO0_B0, RK3588_PMU1_IOC_REG + 0x0024}, {RK_GPIO0_B5, RK3588_PMU2_IOC_REG + 0x0028}, {RK_GPIO0_C0, RK3588_PMU2_IOC_REG + 0x002C}, {RK_GPIO0_D0, RK3588_PMU2_IOC_REG + 0x0030}, {RK_GPIO1_A0, RK3588_VCCIO1_4_IOC_REG + 0x0110}, {RK_GPIO1_B0, RK3588_VCCIO1_4_IOC_REG + 0x0114}, {RK_GPIO1_C0, RK3588_VCCIO1_4_IOC_REG + 0x0118}, {RK_GPIO1_D0, RK3588_VCCIO1_4_IOC_REG + 0x011C}, {RK_GPIO2_A0, RK3588_EMMC_IOC_REG + 0x0120}, {RK_GPIO2_A6, RK3588_VCCIO3_5_IOC_REG + 0x0120}, {RK_GPIO2_B0, RK3588_VCCIO3_5_IOC_REG + 0x0124}, {RK_GPIO2_C0, RK3588_VCCIO3_5_IOC_REG + 0x0128}, {RK_GPIO2_D0, RK3588_EMMC_IOC_REG + 0x012C}, {RK_GPIO3_A0, RK3588_VCCIO3_5_IOC_REG + 0x0130}, {RK_GPIO3_B0, RK3588_VCCIO3_5_IOC_REG + 0x0134}, {RK_GPIO3_C0, RK3588_VCCIO3_5_IOC_REG + 0x0138}, {RK_GPIO3_D0, RK3588_VCCIO3_5_IOC_REG + 0x013C}, {RK_GPIO4_A0, RK3588_VCCIO6_IOC_REG + 0x0140}, {RK_GPIO4_B0, RK3588_VCCIO6_IOC_REG + 0x0144}, {RK_GPIO4_C0, RK3588_VCCIO6_IOC_REG + 0x0148}, {RK_GPIO4_C2, RK3588_VCCIO3_5_IOC_REG + 0x0148}, {RK_GPIO4_D0, RK3588_VCCIO2_IOC_REG + 0x014C}, }; static const u32 rk3588_smt_regs[][2] = { {RK_GPIO0_A0, RK3588_PMU1_IOC_REG + 0x0030}, {RK_GPIO0_B0, RK3588_PMU1_IOC_REG + 0x0034}, {RK_GPIO0_B5, RK3588_PMU2_IOC_REG + 0x0040}, {RK_GPIO0_C0, RK3588_PMU2_IOC_REG + 0x0044}, {RK_GPIO0_D0, RK3588_PMU2_IOC_REG + 0x0048}, {RK_GPIO1_A0, RK3588_VCCIO1_4_IOC_REG + 0x0210}, {RK_GPIO1_B0, RK3588_VCCIO1_4_IOC_REG + 0x0214}, {RK_GPIO1_C0, RK3588_VCCIO1_4_IOC_REG + 0x0218}, {RK_GPIO1_D0, RK3588_VCCIO1_4_IOC_REG + 0x021C}, {RK_GPIO2_A0, RK3588_EMMC_IOC_REG + 0x0220}, {RK_GPIO2_A6, RK3588_VCCIO3_5_IOC_REG + 0x0220}, {RK_GPIO2_B0, RK3588_VCCIO3_5_IOC_REG + 0x0224}, {RK_GPIO2_C0, RK3588_VCCIO3_5_IOC_REG + 0x0228}, {RK_GPIO2_D0, RK3588_EMMC_IOC_REG + 0x022C}, {RK_GPIO3_A0, RK3588_VCCIO3_5_IOC_REG + 0x0230}, {RK_GPIO3_B0, RK3588_VCCIO3_5_IOC_REG + 0x0234}, {RK_GPIO3_C0, RK3588_VCCIO3_5_IOC_REG + 0x0238}, {RK_GPIO3_D0, RK3588_VCCIO3_5_IOC_REG + 0x023C}, {RK_GPIO4_A0, RK3588_VCCIO6_IOC_REG + 0x0240}, {RK_GPIO4_B0, RK3588_VCCIO6_IOC_REG + 0x0244}, {RK_GPIO4_C0, RK3588_VCCIO6_IOC_REG + 0x0248}, {RK_GPIO4_C2, RK3588_VCCIO3_5_IOC_REG + 0x0248}, {RK_GPIO4_D0, RK3588_VCCIO2_IOC_REG + 0x024C}, }; #define RK3588_PULL_BITS_PER_PIN 2 #define RK3588_PULL_PINS_PER_REG 8 static void rk3588_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; u8 bank_num = bank->bank_num; u32 pin = bank_num * 32 + pin_num; int i; for (i = ARRAY_SIZE(rk3588_p_regs) - 1; i >= 0; i--) { if (pin >= rk3588_p_regs[i][0]) { *reg = rk3588_p_regs[i][1]; break; } } assert(i >= 0); *regmap = info->regmap_base; *bit = pin_num % RK3588_PULL_PINS_PER_REG; *bit *= RK3588_PULL_BITS_PER_PIN; } #define RK3588_DRV_BITS_PER_PIN 4 #define RK3588_DRV_PINS_PER_REG 4 static void rk3588_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; u8 bank_num = bank->bank_num; u32 pin = bank_num * 32 + pin_num; int i; for (i = ARRAY_SIZE(rk3588_ds_regs) - 1; i >= 0; i--) { if (pin >= rk3588_ds_regs[i][0]) { *reg = rk3588_ds_regs[i][1]; break; } } assert(i >= 0); *regmap = info->regmap_base; *bit = pin_num % RK3588_DRV_PINS_PER_REG; *bit *= RK3588_DRV_BITS_PER_PIN; } #define RK3588_SMT_BITS_PER_PIN 1 #define RK3588_SMT_PINS_PER_REG 8 static int rk3588_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; u8 bank_num = bank->bank_num; u32 pin = bank_num * 32 + pin_num; int i; for (i = ARRAY_SIZE(rk3588_smt_regs) - 1; i >= 0; i--) { if (pin >= rk3588_smt_regs[i][0]) { *reg = rk3588_smt_regs[i][1]; break; } } assert(i >= 0); *regmap = info->regmap_base; *bit = pin_num % RK3588_SMT_PINS_PER_REG; *bit *= RK3588_SMT_BITS_PER_PIN; return 0; } static int rk3588_set_pull(struct rockchip_pin_bank *bank, int pin_num, int pull) { struct regmap *regmap; int reg, translated_pull; u8 bit, type; u32 data; rk3588_calc_pull_reg_and_bit(bank, pin_num, ®map, ®, &bit); type = bank->pull_type[pin_num / 8]; translated_pull = rockchip_translate_pull_value(type, pull); if (translated_pull < 0) { debug("unsupported pull setting %d\n", pull); return -EINVAL; } /* enable the write to the equivalent lower bits */ data = ((1 << ROCKCHIP_PULL_BITS_PER_PIN) - 1) << (bit + 16); data |= (translated_pull << bit); return regmap_write(regmap, reg, data); } static int rk3588_set_drive(struct rockchip_pin_bank *bank, int pin_num, int strength) { struct regmap *regmap; int reg; u32 data; u8 bit; rk3588_calc_drv_reg_and_bit(bank, pin_num, ®map, ®, &bit); /* enable the write to the equivalent lower bits */ data = ((1 << RK3588_DRV_BITS_PER_PIN) - 1) << (bit + 16); data |= (strength << bit); return regmap_write(regmap, reg, data); } static int rk3588_set_schmitt(struct rockchip_pin_bank *bank, int pin_num, int enable) { struct regmap *regmap; int reg; u32 data; u8 bit; rk3588_calc_schmitt_reg_and_bit(bank, pin_num, ®map, ®, &bit); /* enable the write to the equivalent lower bits */ data = ((1 << RK3588_SMT_BITS_PER_PIN) - 1) << (bit + 16); data |= (enable << bit); return regmap_write(regmap, reg, data); } static struct rockchip_pin_bank rk3588_pin_banks[] = { RK3588_PIN_BANK_FLAGS(0, 32, "gpio0", IOMUX_WIDTH_4BIT, PULL_TYPE_IO_1V8_ONLY), RK3588_PIN_BANK_FLAGS(1, 32, "gpio1", IOMUX_WIDTH_4BIT, PULL_TYPE_IO_1V8_ONLY), RK3588_PIN_BANK_FLAGS(2, 32, "gpio2", IOMUX_WIDTH_4BIT, PULL_TYPE_IO_1V8_ONLY), RK3588_PIN_BANK_FLAGS(3, 32, "gpio3", IOMUX_WIDTH_4BIT, PULL_TYPE_IO_1V8_ONLY), RK3588_PIN_BANK_FLAGS(4, 32, "gpio4", IOMUX_WIDTH_4BIT, PULL_TYPE_IO_1V8_ONLY), }; static const struct rockchip_pin_ctrl rk3588_pin_ctrl = { .pin_banks = rk3588_pin_banks, .nr_banks = ARRAY_SIZE(rk3588_pin_banks), .nr_pins = 160, .set_mux = rk3588_set_mux, .set_pull = rk3588_set_pull, .set_drive = rk3588_set_drive, .set_schmitt = rk3588_set_schmitt, }; static const struct udevice_id rk3588_pinctrl_ids[] = { { .compatible = "rockchip,rk3588-pinctrl", .data = (ulong)&rk3588_pin_ctrl }, { } }; U_BOOT_DRIVER(pinctrl_rk3588) = { .name = "rockchip_rk3588_pinctrl", .id = UCLASS_PINCTRL, .of_match = rk3588_pinctrl_ids, .priv_auto = sizeof(struct rockchip_pinctrl_priv), .ops = &rockchip_pinctrl_ops, #if CONFIG_IS_ENABLED(OF_REAL) .bind = dm_scan_fdt_dev, #endif .probe = rockchip_pinctrl_probe, };