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