// SPDX-License-Identifier: GPL-2.0+ /* * (C) Copyright 2021 Rockchip Electronics Co., Ltd */ #include #include #include #include #include #include "pinctrl-rockchip.h" 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) { u32 reg0 = 0; reg0 = reg + 0x4000 - 0xC; /* PMU2_IOC_BASE */ data = (mask << (bit + 16)); data |= (mux & mask) << bit; ret = regmap_write(regmap, reg0, data); reg0 = reg + 0x8000; /* BUS_IOC_BASE */ data = (mask << (bit + 16)); regmap = priv->regmap_base; regmap_write(regmap, reg0, 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_DRV_PMU_OFFSET 0x70 #define rk3588_DRV_GRF_OFFSET 0x200 #define rk3588_DRV_BITS_PER_PIN 8 #define rk3588_DRV_PINS_PER_REG 2 #define rk3588_DRV_BANK_STRIDE 0x40 #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 }, }; 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_A4, 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_A4, 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; } BUG_ON(i == 0); } *regmap = info->regmap_base; *reg += ((pin - rk3588_p_regs[i][0]) / RK3588_PULL_PINS_PER_REG) * 4; *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; } BUG_ON(i == 0); } *regmap = info->regmap_base; *reg += ((pin - rk3588_ds_regs[i][0]) / RK3588_DRV_PINS_PER_REG) * 4; *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; } BUG_ON(i == 0); } *regmap = info->regmap_base; *reg += ((pin - rk3588_smt_regs[i][0]) / RK3588_SMT_PINS_PER_REG) * 4; *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; u32 data; u8 bit; rk3588_calc_pull_reg_and_bit(bank, pin_num, ®map, ®, &bit); /* enable the write to the equivalent lower bits */ data = ((1 << ROCKCHIP_PULL_BITS_PER_PIN) - 1) << (bit + 16); data |= (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_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, };