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_route_data rk3399_mux_route_data[] = { 15 { 16 /* uart2dbga_rx */ 17 .bank_num = 4, 18 .pin = 8, 19 .func = 2, 20 .route_offset = 0xe21c, 21 .route_val = BIT(16 + 10) | BIT(16 + 11), 22 }, { 23 /* uart2dbgb_rx */ 24 .bank_num = 4, 25 .pin = 16, 26 .func = 2, 27 .route_offset = 0xe21c, 28 .route_val = BIT(16 + 10) | BIT(16 + 11) | BIT(10), 29 }, { 30 /* uart2dbgc_rx */ 31 .bank_num = 4, 32 .pin = 19, 33 .func = 1, 34 .route_offset = 0xe21c, 35 .route_val = BIT(16 + 10) | BIT(16 + 11) | BIT(11), 36 }, { 37 /* pcie_clkreqn */ 38 .bank_num = 2, 39 .pin = 26, 40 .func = 2, 41 .route_offset = 0xe21c, 42 .route_val = BIT(16 + 14), 43 }, { 44 /* pcie_clkreqnb */ 45 .bank_num = 4, 46 .pin = 24, 47 .func = 1, 48 .route_offset = 0xe21c, 49 .route_val = BIT(16 + 14) | BIT(14), 50 }, 51 }; 52 53 static int rk3399_set_mux(struct rockchip_pin_bank *bank, int pin, int mux) 54 { 55 struct rockchip_pinctrl_priv *priv = bank->priv; 56 int iomux_num = (pin / 8); 57 struct regmap *regmap; 58 int reg, ret, mask, mux_type; 59 u8 bit; 60 u32 data, route_reg, route_val; 61 62 regmap = (bank->iomux[iomux_num].type & IOMUX_SOURCE_PMU) 63 ? priv->regmap_pmu : priv->regmap_base; 64 65 /* get basic quadrupel of mux registers and the correct reg inside */ 66 mux_type = bank->iomux[iomux_num].type; 67 reg = bank->iomux[iomux_num].offset; 68 reg += rockchip_get_mux_data(mux_type, pin, &bit, &mask); 69 70 if (bank->route_mask & BIT(pin)) { 71 if (rockchip_get_mux_route(bank, pin, mux, &route_reg, 72 &route_val)) { 73 ret = regmap_write(regmap, route_reg, route_val); 74 if (ret) 75 return ret; 76 } 77 } 78 79 data = (mask << (bit + 16)); 80 data |= (mux & mask) << bit; 81 ret = regmap_write(regmap, reg, data); 82 83 return ret; 84 } 85 86 #define RK3399_PULL_GRF_OFFSET 0xe040 87 #define RK3399_PULL_PMU_OFFSET 0x40 88 89 static void rk3399_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank, 90 int pin_num, struct regmap **regmap, 91 int *reg, u8 *bit) 92 { 93 struct rockchip_pinctrl_priv *priv = bank->priv; 94 95 /* The bank0:16 and bank1:32 pins are located in PMU */ 96 if (bank->bank_num == 0 || bank->bank_num == 1) { 97 *regmap = priv->regmap_pmu; 98 *reg = RK3399_PULL_PMU_OFFSET; 99 100 *reg += bank->bank_num * ROCKCHIP_PULL_BANK_STRIDE; 101 } else { 102 *regmap = priv->regmap_base; 103 *reg = RK3399_PULL_GRF_OFFSET; 104 105 /* correct the offset, as we're starting with the 3rd bank */ 106 *reg -= 0x20; 107 *reg += bank->bank_num * ROCKCHIP_PULL_BANK_STRIDE; 108 } 109 110 *reg += ((pin_num / ROCKCHIP_PULL_PINS_PER_REG) * 4); 111 112 *bit = (pin_num % ROCKCHIP_PULL_PINS_PER_REG); 113 *bit *= ROCKCHIP_PULL_BITS_PER_PIN; 114 } 115 116 static int rk3399_set_pull(struct rockchip_pin_bank *bank, 117 int pin_num, int pull) 118 { 119 struct regmap *regmap; 120 int reg, ret; 121 u8 bit, type; 122 u32 data; 123 124 if (pull == PIN_CONFIG_BIAS_PULL_PIN_DEFAULT) 125 return -ENOTSUPP; 126 127 rk3399_calc_pull_reg_and_bit(bank, pin_num, ®map, ®, &bit); 128 type = bank->pull_type[pin_num / 8]; 129 ret = rockchip_translate_pull_value(type, pull); 130 if (ret < 0) { 131 debug("unsupported pull setting %d\n", pull); 132 return ret; 133 } 134 135 /* enable the write to the equivalent lower bits */ 136 data = ((1 << ROCKCHIP_PULL_BITS_PER_PIN) - 1) << (bit + 16); 137 data |= (ret << bit); 138 ret = regmap_write(regmap, reg, data); 139 140 return ret; 141 } 142 143 static void rk3399_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank, 144 int pin_num, struct regmap **regmap, 145 int *reg, u8 *bit) 146 { 147 struct rockchip_pinctrl_priv *priv = bank->priv; 148 int drv_num = (pin_num / 8); 149 150 /* The bank0:16 and bank1:32 pins are located in PMU */ 151 if (bank->bank_num == 0 || bank->bank_num == 1) 152 *regmap = priv->regmap_pmu; 153 else 154 *regmap = priv->regmap_base; 155 156 *reg = bank->drv[drv_num].offset; 157 if (bank->drv[drv_num].drv_type == DRV_TYPE_IO_1V8_3V0_AUTO || 158 bank->drv[drv_num].drv_type == DRV_TYPE_IO_3V3_ONLY) 159 *bit = (pin_num % 8) * 3; 160 else 161 *bit = (pin_num % 8) * 2; 162 } 163 164 static int rk3399_set_drive(struct rockchip_pin_bank *bank, 165 int pin_num, int strength) 166 { 167 struct regmap *regmap; 168 int reg, ret; 169 u32 data, rmask_bits, temp; 170 u8 bit; 171 int drv_type = bank->drv[pin_num / 8].drv_type; 172 173 rk3399_calc_drv_reg_and_bit(bank, pin_num, ®map, ®, &bit); 174 ret = rockchip_translate_drive_value(drv_type, strength); 175 if (ret < 0) { 176 debug("unsupported driver strength %d\n", strength); 177 return ret; 178 } 179 180 switch (drv_type) { 181 case DRV_TYPE_IO_1V8_3V0_AUTO: 182 case DRV_TYPE_IO_3V3_ONLY: 183 rmask_bits = ROCKCHIP_DRV_3BITS_PER_PIN; 184 switch (bit) { 185 case 0 ... 12: 186 /* regular case, nothing to do */ 187 break; 188 case 15: 189 /* 190 * drive-strength offset is special, as it is spread 191 * over 2 registers, the bit data[15] contains bit 0 192 * of the value while temp[1:0] contains bits 2 and 1 193 */ 194 data = (ret & 0x1) << 15; 195 temp = (ret >> 0x1) & 0x3; 196 197 data |= BIT(31); 198 ret = regmap_write(regmap, reg, data); 199 if (ret) 200 return ret; 201 202 temp |= (0x3 << 16); 203 reg += 0x4; 204 ret = regmap_write(regmap, reg, temp); 205 206 return ret; 207 case 18 ... 21: 208 /* setting fully enclosed in the second register */ 209 reg += 4; 210 bit -= 16; 211 break; 212 default: 213 debug("unsupported bit: %d for pinctrl drive type: %d\n", 214 bit, drv_type); 215 return -EINVAL; 216 } 217 break; 218 case DRV_TYPE_IO_DEFAULT: 219 case DRV_TYPE_IO_1V8_OR_3V0: 220 case DRV_TYPE_IO_1V8_ONLY: 221 rmask_bits = ROCKCHIP_DRV_BITS_PER_PIN; 222 break; 223 default: 224 debug("unsupported pinctrl drive type: %d\n", 225 drv_type); 226 return -EINVAL; 227 } 228 229 /* enable the write to the equivalent lower bits */ 230 data = ((1 << rmask_bits) - 1) << (bit + 16); 231 data |= (ret << bit); 232 ret = regmap_write(regmap, reg, data); 233 234 return ret; 235 } 236 237 static struct rockchip_pin_bank rk3399_pin_banks[] = { 238 PIN_BANK_IOMUX_FLAGS_DRV_FLAGS_OFFSET_PULL_FLAGS(0, 32, "gpio0", 239 IOMUX_SOURCE_PMU, 240 IOMUX_SOURCE_PMU, 241 IOMUX_SOURCE_PMU, 242 IOMUX_SOURCE_PMU, 243 DRV_TYPE_IO_1V8_ONLY, 244 DRV_TYPE_IO_1V8_ONLY, 245 DRV_TYPE_IO_DEFAULT, 246 DRV_TYPE_IO_DEFAULT, 247 0x80, 248 0x88, 249 -1, 250 -1, 251 PULL_TYPE_IO_1V8_ONLY, 252 PULL_TYPE_IO_1V8_ONLY, 253 PULL_TYPE_IO_DEFAULT, 254 PULL_TYPE_IO_DEFAULT 255 ), 256 PIN_BANK_IOMUX_DRV_FLAGS_OFFSET(1, 32, "gpio1", IOMUX_SOURCE_PMU, 257 IOMUX_SOURCE_PMU, 258 IOMUX_SOURCE_PMU, 259 IOMUX_SOURCE_PMU, 260 DRV_TYPE_IO_1V8_OR_3V0, 261 DRV_TYPE_IO_1V8_OR_3V0, 262 DRV_TYPE_IO_1V8_OR_3V0, 263 DRV_TYPE_IO_1V8_OR_3V0, 264 0xa0, 265 0xa8, 266 0xb0, 267 0xb8 268 ), 269 PIN_BANK_DRV_FLAGS_PULL_FLAGS(2, 32, "gpio2", DRV_TYPE_IO_1V8_OR_3V0, 270 DRV_TYPE_IO_1V8_OR_3V0, 271 DRV_TYPE_IO_1V8_ONLY, 272 DRV_TYPE_IO_1V8_ONLY, 273 PULL_TYPE_IO_DEFAULT, 274 PULL_TYPE_IO_DEFAULT, 275 PULL_TYPE_IO_1V8_ONLY, 276 PULL_TYPE_IO_1V8_ONLY 277 ), 278 PIN_BANK_DRV_FLAGS(3, 32, "gpio3", DRV_TYPE_IO_3V3_ONLY, 279 DRV_TYPE_IO_3V3_ONLY, 280 DRV_TYPE_IO_3V3_ONLY, 281 DRV_TYPE_IO_1V8_OR_3V0 282 ), 283 PIN_BANK_DRV_FLAGS(4, 32, "gpio4", DRV_TYPE_IO_1V8_OR_3V0, 284 DRV_TYPE_IO_1V8_3V0_AUTO, 285 DRV_TYPE_IO_1V8_OR_3V0, 286 DRV_TYPE_IO_1V8_OR_3V0 287 ), 288 }; 289 290 static struct rockchip_pin_ctrl rk3399_pin_ctrl = { 291 .pin_banks = rk3399_pin_banks, 292 .nr_banks = ARRAY_SIZE(rk3399_pin_banks), 293 .grf_mux_offset = 0xe000, 294 .pmu_mux_offset = 0x0, 295 .grf_drv_offset = 0xe100, 296 .pmu_drv_offset = 0x80, 297 .iomux_routes = rk3399_mux_route_data, 298 .niomux_routes = ARRAY_SIZE(rk3399_mux_route_data), 299 .set_mux = rk3399_set_mux, 300 .set_pull = rk3399_set_pull, 301 .set_drive = rk3399_set_drive, 302 }; 303 304 static const struct udevice_id rk3399_pinctrl_ids[] = { 305 { 306 .compatible = "rockchip,rk3399-pinctrl", 307 .data = (ulong)&rk3399_pin_ctrl 308 }, 309 { } 310 }; 311 312 U_BOOT_DRIVER(pinctrl_rk3399) = { 313 .name = "rockchip_rk3399_pinctrl", 314 .id = UCLASS_PINCTRL, 315 .of_match = rk3399_pinctrl_ids, 316 .priv_auto_alloc_size = sizeof(struct rockchip_pinctrl_priv), 317 .ops = &rockchip_pinctrl_ops, 318 #if !CONFIG_IS_ENABLED(OF_PLATDATA) 319 .bind = dm_scan_fdt_dev, 320 #endif 321 .probe = rockchip_pinctrl_probe, 322 }; 323