1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * (C) Copyright 2022 Rockchip Electronics Co., Ltd 4 */ 5 6 #include <common.h> 7 #include <dm.h> 8 #include <dm/pinctrl.h> 9 #include <regmap.h> 10 #include <syscon.h> 11 12 #include "pinctrl-rockchip.h" 13 14 static int rv1106_set_mux(struct rockchip_pin_bank *bank, int pin, int mux) 15 { 16 struct rockchip_pinctrl_priv *priv = bank->priv; 17 int iomux_num = (pin / 8); 18 struct regmap *regmap; 19 int reg, ret, mask; 20 u8 bit; 21 u32 data; 22 23 debug("setting mux of GPIO%d-%d to %d\n", bank->bank_num, pin, mux); 24 25 if (bank->iomux[iomux_num].type & IOMUX_SOURCE_PMU) 26 regmap = priv->regmap_pmu; 27 else 28 regmap = priv->regmap_base; 29 30 reg = bank->iomux[iomux_num].offset; 31 if ((pin % 8) >= 4) 32 reg += 0x4; 33 bit = (pin % 4) * 4; 34 mask = 0xf; 35 36 data = (mask << (bit + 16)); 37 data |= (mux & mask) << bit; 38 39 debug("iomux write reg = %x data = %x\n", reg, data); 40 41 ret = regmap_write(regmap, reg, data); 42 43 return ret; 44 } 45 46 #define RV1106_DRV_BITS_PER_PIN 8 47 #define RV1106_DRV_PINS_PER_REG 2 48 #define RV1106_DRV_GPIO0_OFFSET 0x10 49 #define RV1106_DRV_GPIO1_OFFSET 0x80 50 #define RV1106_DRV_GPIO2_OFFSET 0x100C0 51 #define RV1106_DRV_GPIO3_OFFSET 0x20100 52 #define RV1106_DRV_GPIO4_OFFSET 0x30020 53 54 static void rv1106_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank, 55 int pin_num, struct regmap **regmap, 56 int *reg, u8 *bit) 57 { 58 struct rockchip_pinctrl_priv *priv = bank->priv; 59 60 /* GPIO0_IOC is located in PMU */ 61 switch (bank->bank_num) { 62 case 0: 63 *regmap = priv->regmap_pmu; 64 *reg = RV1106_DRV_GPIO0_OFFSET; 65 break; 66 67 case 1: 68 *regmap = priv->regmap_base; 69 *reg = RV1106_DRV_GPIO1_OFFSET; 70 break; 71 72 case 2: 73 *regmap = priv->regmap_base; 74 *reg = RV1106_DRV_GPIO2_OFFSET; 75 break; 76 77 case 3: 78 *regmap = priv->regmap_base; 79 *reg = RV1106_DRV_GPIO3_OFFSET; 80 break; 81 82 case 4: 83 *regmap = priv->regmap_base; 84 *reg = RV1106_DRV_GPIO4_OFFSET; 85 break; 86 87 default: 88 *regmap = priv->regmap_base; 89 *reg = 0; 90 dev_err(priv->dev, "unsupported bank_num %d\n", bank->bank_num); 91 break; 92 } 93 94 *reg += ((pin_num / RV1106_DRV_PINS_PER_REG) * 4); 95 *bit = pin_num % RV1106_DRV_PINS_PER_REG; 96 *bit *= RV1106_DRV_BITS_PER_PIN; 97 } 98 99 static int rv1106_set_drive(struct rockchip_pin_bank *bank, 100 int pin_num, int strength) 101 { 102 struct regmap *regmap; 103 int reg, ret; 104 u32 data; 105 u8 bit; 106 int drv = (1 << (strength + 1)) - 1; 107 108 rv1106_calc_drv_reg_and_bit(bank, pin_num, ®map, ®, &bit); 109 110 /* enable the write to the equivalent lower bits */ 111 data = ((1 << RV1106_DRV_BITS_PER_PIN) - 1) << (bit + 16); 112 data |= (drv << bit); 113 ret = regmap_write(regmap, reg, data); 114 115 return ret; 116 } 117 118 #define RV1106_PULL_BITS_PER_PIN 2 119 #define RV1106_PULL_PINS_PER_REG 8 120 #define RV1106_PULL_GPIO0_OFFSET 0x38 121 #define RV1106_PULL_GPIO1_OFFSET 0x1C0 122 #define RV1106_PULL_GPIO2_OFFSET 0x101D0 123 #define RV1106_PULL_GPIO3_OFFSET 0x201E0 124 #define RV1106_PULL_GPIO4_OFFSET 0x30070 125 126 static void rv1106_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank, 127 int pin_num, struct regmap **regmap, 128 int *reg, u8 *bit) 129 { 130 struct rockchip_pinctrl_priv *priv = bank->priv; 131 132 /* GPIO0_IOC is located in PMU */ 133 switch (bank->bank_num) { 134 case 0: 135 *regmap = priv->regmap_pmu; 136 *reg = RV1106_PULL_GPIO0_OFFSET; 137 break; 138 139 case 1: 140 *regmap = priv->regmap_base; 141 *reg = RV1106_PULL_GPIO1_OFFSET; 142 break; 143 144 case 2: 145 *regmap = priv->regmap_base; 146 *reg = RV1106_PULL_GPIO2_OFFSET; 147 break; 148 149 case 3: 150 *regmap = priv->regmap_base; 151 *reg = RV1106_PULL_GPIO3_OFFSET; 152 break; 153 154 case 4: 155 *regmap = priv->regmap_base; 156 *reg = RV1106_PULL_GPIO4_OFFSET; 157 break; 158 159 default: 160 *regmap = priv->regmap_base; 161 *reg = 0; 162 dev_err(priv->dev, "unsupported bank_num %d\n", bank->bank_num); 163 break; 164 } 165 166 *reg += ((pin_num / RV1106_PULL_PINS_PER_REG) * 4); 167 *bit = pin_num % RV1106_PULL_PINS_PER_REG; 168 *bit *= RV1106_PULL_BITS_PER_PIN; 169 } 170 171 static int rv1106_set_pull(struct rockchip_pin_bank *bank, 172 int pin_num, int pull) 173 { 174 struct regmap *regmap; 175 int reg, ret; 176 u8 bit, type; 177 u32 data; 178 179 if (pull == PIN_CONFIG_BIAS_PULL_PIN_DEFAULT) 180 return -ENOTSUPP; 181 182 rv1106_calc_pull_reg_and_bit(bank, pin_num, ®map, ®, &bit); 183 type = bank->pull_type[pin_num / 8]; 184 ret = rockchip_translate_pull_value(type, pull); 185 if (ret < 0) { 186 debug("unsupported pull setting %d\n", pull); 187 return ret; 188 } 189 190 /* enable the write to the equivalent lower bits */ 191 data = ((1 << RV1106_PULL_BITS_PER_PIN) - 1) << (bit + 16); 192 193 data |= (ret << bit); 194 ret = regmap_write(regmap, reg, data); 195 196 return ret; 197 } 198 199 #define RV1106_SMT_BITS_PER_PIN 1 200 #define RV1106_SMT_PINS_PER_REG 8 201 #define RV1106_SMT_GPIO0_OFFSET 0x40 202 #define RV1106_SMT_GPIO1_OFFSET 0x280 203 #define RV1106_SMT_GPIO2_OFFSET 0x10290 204 #define RV1106_SMT_GPIO3_OFFSET 0x202A0 205 #define RV1106_SMT_GPIO4_OFFSET 0x300A0 206 207 static int rv1106_calc_schmitt_reg_and_bit(struct rockchip_pin_bank *bank, 208 int pin_num, 209 struct regmap **regmap, 210 int *reg, u8 *bit) 211 { 212 struct rockchip_pinctrl_priv *priv = bank->priv; 213 214 /* GPIO0_IOC is located in PMU */ 215 switch (bank->bank_num) { 216 case 0: 217 *regmap = priv->regmap_pmu; 218 *reg = RV1106_SMT_GPIO0_OFFSET; 219 break; 220 221 case 1: 222 *regmap = priv->regmap_base; 223 *reg = RV1106_SMT_GPIO1_OFFSET; 224 break; 225 226 case 2: 227 *regmap = priv->regmap_base; 228 *reg = RV1106_SMT_GPIO2_OFFSET; 229 break; 230 231 case 3: 232 *regmap = priv->regmap_base; 233 *reg = RV1106_SMT_GPIO3_OFFSET; 234 break; 235 236 case 4: 237 *regmap = priv->regmap_base; 238 *reg = RV1106_SMT_GPIO4_OFFSET; 239 break; 240 241 default: 242 *regmap = priv->regmap_base; 243 *reg = 0; 244 dev_err(priv->dev, "unsupported bank_num %d\n", bank->bank_num); 245 break; 246 } 247 248 *reg += ((pin_num / RV1106_SMT_PINS_PER_REG) * 4); 249 *bit = pin_num % RV1106_SMT_PINS_PER_REG; 250 *bit *= RV1106_SMT_BITS_PER_PIN; 251 252 return 0; 253 } 254 255 static int rv1106_set_schmitt(struct rockchip_pin_bank *bank, 256 int pin_num, int enable) 257 { 258 struct regmap *regmap; 259 int reg, ret; 260 u32 data; 261 u8 bit; 262 263 rv1106_calc_schmitt_reg_and_bit(bank, pin_num, ®map, ®, &bit); 264 265 /* enable the write to the equivalent lower bits */ 266 data = ((1 << RV1106_SMT_BITS_PER_PIN) - 1) << (bit + 16); 267 data |= (enable << bit); 268 ret = regmap_write(regmap, reg, data); 269 270 return ret; 271 } 272 273 static struct rockchip_pin_bank rv1106_pin_banks[] = { 274 PIN_BANK_IOMUX_FLAGS(0, 32, "gpio0", 275 IOMUX_WIDTH_4BIT | IOMUX_SOURCE_PMU, 276 IOMUX_WIDTH_4BIT | IOMUX_SOURCE_PMU, 277 IOMUX_WIDTH_4BIT | IOMUX_SOURCE_PMU, 278 IOMUX_WIDTH_4BIT | IOMUX_SOURCE_PMU), 279 PIN_BANK_IOMUX_FLAGS_OFFSET(1, 32, "gpio1", 280 IOMUX_WIDTH_4BIT, 281 IOMUX_WIDTH_4BIT, 282 IOMUX_WIDTH_4BIT, 283 IOMUX_WIDTH_4BIT, 284 0, 0x08, 0x10, 0x18), 285 PIN_BANK_IOMUX_FLAGS_OFFSET(2, 32, "gpio2", 286 IOMUX_WIDTH_4BIT, 287 IOMUX_WIDTH_4BIT, 288 IOMUX_WIDTH_4BIT, 289 IOMUX_WIDTH_4BIT, 290 0x10020, 0x10028, 0, 0), 291 PIN_BANK_IOMUX_FLAGS_OFFSET(3, 32, "gpio3", 292 IOMUX_WIDTH_4BIT, 293 IOMUX_WIDTH_4BIT, 294 IOMUX_WIDTH_4BIT, 295 IOMUX_WIDTH_4BIT, 296 0x20040, 0x20048, 0x20050, 0x20058), 297 PIN_BANK_IOMUX_FLAGS_OFFSET(4, 24, "gpio4", 298 IOMUX_WIDTH_4BIT, 299 IOMUX_WIDTH_4BIT, 300 IOMUX_WIDTH_4BIT, 301 0, 302 0x30000, 0x30008, 0x30010, 0), 303 }; 304 305 static const struct rockchip_pin_ctrl rv1106_pin_ctrl = { 306 .pin_banks = rv1106_pin_banks, 307 .nr_banks = ARRAY_SIZE(rv1106_pin_banks), 308 .nr_pins = 152, 309 .grf_mux_offset = 0x0, 310 .pmu_mux_offset = 0x0, 311 .set_mux = rv1106_set_mux, 312 .set_pull = rv1106_set_pull, 313 .set_drive = rv1106_set_drive, 314 .set_schmitt = rv1106_set_schmitt, 315 }; 316 317 static const struct udevice_id rv1106_pinctrl_ids[] = { 318 { 319 .compatible = "rockchip,rv1106-pinctrl", 320 .data = (ulong)&rv1106_pin_ctrl 321 }, 322 { } 323 }; 324 325 U_BOOT_DRIVER(pinctrl_rv1106) = { 326 .name = "rockchip_rv1106_pinctrl", 327 .id = UCLASS_PINCTRL, 328 .of_match = rv1106_pinctrl_ids, 329 .priv_auto_alloc_size = sizeof(struct rockchip_pinctrl_priv), 330 .ops = &rockchip_pinctrl_ops, 331 #if !CONFIG_IS_ENABLED(OF_PLATDATA) 332 .bind = dm_scan_fdt_dev, 333 #endif 334 .probe = rockchip_pinctrl_probe, 335 }; 336