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