1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * (C) Copyright 2019 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 struct rockchip_mux_recalced_data rk3328_mux_recalced_data[] = { 15 { 16 .num = 2, 17 .pin = 12, 18 .reg = 0x24, 19 .bit = 8, 20 .mask = 0x3 21 }, { 22 .num = 2, 23 .pin = 15, 24 .reg = 0x28, 25 .bit = 0, 26 .mask = 0x7 27 }, { 28 .num = 2, 29 .pin = 23, 30 .reg = 0x30, 31 .bit = 14, 32 .mask = 0x3 33 }, 34 }; 35 36 static struct rockchip_mux_route_data rk3328_mux_route_data[] = { 37 { 38 /* uart2dbg_rxm0 */ 39 .bank_num = 1, 40 .pin = 1, 41 .func = 2, 42 .route_offset = 0x50, 43 .route_val = BIT(16) | BIT(16 + 1), 44 }, { 45 /* uart2dbg_rxm1 */ 46 .bank_num = 2, 47 .pin = 1, 48 .func = 1, 49 .route_offset = 0x50, 50 .route_val = BIT(16) | BIT(16 + 1) | BIT(0), 51 }, { 52 /* gmac-m1_rxd0 */ 53 .bank_num = 1, 54 .pin = 11, 55 .func = 2, 56 .route_offset = 0x50, 57 .route_val = BIT(16 + 2) | BIT(2), 58 }, { 59 /* gmac-m1-optimized_rxd3 */ 60 .bank_num = 1, 61 .pin = 14, 62 .func = 2, 63 .route_offset = 0x50, 64 .route_val = BIT(16 + 10) | BIT(10), 65 }, { 66 /* pdm_sdi0m0 */ 67 .bank_num = 2, 68 .pin = 19, 69 .func = 2, 70 .route_offset = 0x50, 71 .route_val = BIT(16 + 3), 72 }, { 73 /* pdm_sdi0m1 */ 74 .bank_num = 1, 75 .pin = 23, 76 .func = 3, 77 .route_offset = 0x50, 78 .route_val = BIT(16 + 3) | BIT(3), 79 }, { 80 /* spi_rxdm2 */ 81 .bank_num = 3, 82 .pin = 2, 83 .func = 4, 84 .route_offset = 0x50, 85 .route_val = BIT(16 + 4) | BIT(16 + 5) | BIT(5), 86 }, { 87 /* i2s2_sdim0 */ 88 .bank_num = 1, 89 .pin = 24, 90 .func = 1, 91 .route_offset = 0x50, 92 .route_val = BIT(16 + 6), 93 }, { 94 /* i2s2_sdim1 */ 95 .bank_num = 3, 96 .pin = 2, 97 .func = 6, 98 .route_offset = 0x50, 99 .route_val = BIT(16 + 6) | BIT(6), 100 }, { 101 /* card_iom1 */ 102 .bank_num = 2, 103 .pin = 22, 104 .func = 3, 105 .route_offset = 0x50, 106 .route_val = BIT(16 + 7) | BIT(7), 107 }, { 108 /* tsp_d5m1 */ 109 .bank_num = 2, 110 .pin = 16, 111 .func = 3, 112 .route_offset = 0x50, 113 .route_val = BIT(16 + 8) | BIT(8), 114 }, { 115 /* cif_data5m1 */ 116 .bank_num = 2, 117 .pin = 16, 118 .func = 4, 119 .route_offset = 0x50, 120 .route_val = BIT(16 + 9) | BIT(9), 121 }, 122 }; 123 124 static int rk3328_set_mux(struct rockchip_pin_bank *bank, int pin, int mux) 125 { 126 struct rockchip_pinctrl_priv *priv = bank->priv; 127 int iomux_num = (pin / 8); 128 struct regmap *regmap; 129 int reg, ret, mask, mux_type; 130 u8 bit; 131 u32 data, route_reg, route_val; 132 133 regmap = (bank->iomux[iomux_num].type & IOMUX_SOURCE_PMU) 134 ? priv->regmap_pmu : priv->regmap_base; 135 136 /* get basic quadrupel of mux registers and the correct reg inside */ 137 mux_type = bank->iomux[iomux_num].type; 138 reg = bank->iomux[iomux_num].offset; 139 reg += rockchip_get_mux_data(mux_type, pin, &bit, &mask); 140 141 if (bank->recalced_mask & BIT(pin)) 142 rockchip_get_recalced_mux(bank, pin, ®, &bit, &mask); 143 144 if (bank->route_mask & BIT(pin)) { 145 if (rockchip_get_mux_route(bank, pin, mux, &route_reg, 146 &route_val)) { 147 ret = regmap_write(regmap, route_reg, route_val); 148 if (ret) 149 return ret; 150 } 151 } 152 153 data = (mask << (bit + 16)); 154 data |= (mux & mask) << bit; 155 ret = regmap_write(regmap, reg, data); 156 157 return ret; 158 } 159 160 #define RK3328_PULL_OFFSET 0x100 161 162 static void rk3328_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank, 163 int pin_num, struct regmap **regmap, 164 int *reg, u8 *bit) 165 { 166 struct rockchip_pinctrl_priv *priv = bank->priv; 167 168 *regmap = priv->regmap_base; 169 *reg = RK3328_PULL_OFFSET; 170 *reg += bank->bank_num * ROCKCHIP_PULL_BANK_STRIDE; 171 *reg += ((pin_num / ROCKCHIP_PULL_PINS_PER_REG) * 4); 172 173 *bit = (pin_num % ROCKCHIP_PULL_PINS_PER_REG); 174 *bit *= ROCKCHIP_PULL_BITS_PER_PIN; 175 } 176 177 static int rk3328_set_pull(struct rockchip_pin_bank *bank, 178 int pin_num, int pull) 179 { 180 struct regmap *regmap; 181 int reg, ret; 182 u8 bit, type; 183 u32 data; 184 185 if (pull == PIN_CONFIG_BIAS_PULL_PIN_DEFAULT) 186 return -ENOTSUPP; 187 188 rk3328_calc_pull_reg_and_bit(bank, pin_num, ®map, ®, &bit); 189 type = bank->pull_type[pin_num / 8]; 190 ret = rockchip_translate_pull_value(type, pull); 191 if (ret < 0) { 192 debug("unsupported pull setting %d\n", pull); 193 return ret; 194 } 195 196 /* enable the write to the equivalent lower bits */ 197 data = ((1 << ROCKCHIP_PULL_BITS_PER_PIN) - 1) << (bit + 16); 198 data |= (ret << bit); 199 ret = regmap_write(regmap, reg, data); 200 201 return ret; 202 } 203 204 #define RK3328_DRV_GRF_OFFSET 0x200 205 206 static void rk3328_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank, 207 int pin_num, struct regmap **regmap, 208 int *reg, u8 *bit) 209 { 210 struct rockchip_pinctrl_priv *priv = bank->priv; 211 212 *regmap = priv->regmap_base; 213 *reg = RK3328_DRV_GRF_OFFSET; 214 *reg += bank->bank_num * ROCKCHIP_DRV_BANK_STRIDE; 215 *reg += ((pin_num / ROCKCHIP_DRV_PINS_PER_REG) * 4); 216 217 *bit = (pin_num % ROCKCHIP_DRV_PINS_PER_REG); 218 *bit *= ROCKCHIP_DRV_BITS_PER_PIN; 219 } 220 221 static int rk3328_set_drive(struct rockchip_pin_bank *bank, 222 int pin_num, int strength) 223 { 224 struct regmap *regmap; 225 int reg, ret; 226 u32 data; 227 u8 bit; 228 int type = bank->drv[pin_num / 8].drv_type; 229 230 rk3328_calc_drv_reg_and_bit(bank, pin_num, ®map, ®, &bit); 231 ret = rockchip_translate_drive_value(type, strength); 232 if (ret < 0) { 233 debug("unsupported driver strength %d\n", strength); 234 return ret; 235 } 236 237 /* enable the write to the equivalent lower bits */ 238 data = ((1 << ROCKCHIP_DRV_BITS_PER_PIN) - 1) << (bit + 16); 239 data |= (ret << bit); 240 ret = regmap_write(regmap, reg, data); 241 242 return ret; 243 } 244 245 #define RK3328_SCHMITT_BITS_PER_PIN 1 246 #define RK3328_SCHMITT_PINS_PER_REG 16 247 #define RK3328_SCHMITT_BANK_STRIDE 8 248 #define RK3328_SCHMITT_GRF_OFFSET 0x380 249 250 static int rk3328_calc_schmitt_reg_and_bit(struct rockchip_pin_bank *bank, 251 int pin_num, 252 struct regmap **regmap, 253 int *reg, u8 *bit) 254 { 255 struct rockchip_pinctrl_priv *priv = bank->priv; 256 257 *regmap = priv->regmap_base; 258 *reg = RK3328_SCHMITT_GRF_OFFSET; 259 260 *reg += bank->bank_num * RK3328_SCHMITT_BANK_STRIDE; 261 *reg += ((pin_num / RK3328_SCHMITT_PINS_PER_REG) * 4); 262 *bit = pin_num % RK3328_SCHMITT_PINS_PER_REG; 263 264 return 0; 265 } 266 267 static int rk3328_set_schmitt(struct rockchip_pin_bank *bank, 268 int pin_num, int enable) 269 { 270 struct regmap *regmap; 271 int reg; 272 u8 bit; 273 u32 data; 274 275 rk3328_calc_schmitt_reg_and_bit(bank, pin_num, ®map, ®, &bit); 276 /* enable the write to the equivalent lower bits */ 277 data = BIT(bit + 16) | (enable << bit); 278 279 return regmap_write(regmap, reg, data); 280 } 281 282 static struct rockchip_pin_bank rk3328_pin_banks[] = { 283 PIN_BANK_IOMUX_FLAGS(0, 32, "gpio0", 0, 0, 0, 0), 284 PIN_BANK_IOMUX_FLAGS(1, 32, "gpio1", 0, 0, 0, 0), 285 PIN_BANK_IOMUX_FLAGS(2, 32, "gpio2", 0, 286 IOMUX_WIDTH_3BIT, 287 IOMUX_WIDTH_3BIT, 288 0), 289 PIN_BANK_IOMUX_FLAGS(3, 32, "gpio3", 290 IOMUX_WIDTH_3BIT, 291 IOMUX_WIDTH_3BIT, 292 0, 293 0), 294 }; 295 296 static struct rockchip_pin_ctrl rk3328_pin_ctrl = { 297 .pin_banks = rk3328_pin_banks, 298 .nr_banks = ARRAY_SIZE(rk3328_pin_banks), 299 .grf_mux_offset = 0x0, 300 .iomux_recalced = rk3328_mux_recalced_data, 301 .niomux_recalced = ARRAY_SIZE(rk3328_mux_recalced_data), 302 .iomux_routes = rk3328_mux_route_data, 303 .niomux_routes = ARRAY_SIZE(rk3328_mux_route_data), 304 .set_mux = rk3328_set_mux, 305 .set_pull = rk3328_set_pull, 306 .set_drive = rk3328_set_drive, 307 .set_schmitt = rk3328_set_schmitt, 308 }; 309 310 static const struct udevice_id rk3328_pinctrl_ids[] = { 311 { 312 .compatible = "rockchip,rk3328-pinctrl", 313 .data = (ulong)&rk3328_pin_ctrl 314 }, 315 { } 316 }; 317 318 U_BOOT_DRIVER(pinctrl_rk3328) = { 319 .name = "rockchip_rk3328_pinctrl", 320 .id = UCLASS_PINCTRL, 321 .of_match = rk3328_pinctrl_ids, 322 .priv_auto_alloc_size = sizeof(struct rockchip_pinctrl_priv), 323 .ops = &rockchip_pinctrl_ops, 324 #if !CONFIG_IS_ENABLED(OF_PLATDATA) 325 .bind = dm_scan_fdt_dev, 326 #endif 327 .probe = rockchip_pinctrl_probe, 328 }; 329