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