1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3 * (C) Copyright 2020 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 rk1808_mux_route_data[] = {
15 {
16 /* i2c2m0_sda */
17 .bank_num = 3,
18 .pin = 12,
19 .func = 2,
20 .route_offset = 0x190,
21 .route_val = BIT(16 + 3),
22 }, {
23 /* i2c2m1_sda */
24 .bank_num = 1,
25 .pin = 13,
26 .func = 2,
27 .route_offset = 0x190,
28 .route_val = BIT(16 + 3) | BIT(3),
29 }, {
30 /* uart2_rxm0 */
31 .bank_num = 4,
32 .pin = 3,
33 .func = 2,
34 .route_offset = 0x190,
35 .route_val = BIT(16 + 14) | BIT(16 + 15),
36 }, {
37 /* uart2_rxm1 */
38 .bank_num = 2,
39 .pin = 25,
40 .func = 2,
41 .route_offset = 0x190,
42 .route_val = BIT(16 + 14) | BIT(14) | BIT(16 + 15),
43 }, {
44 /* uart2_rxm2 */
45 .bank_num = 3,
46 .pin = 4,
47 .func = 2,
48 .route_offset = 0x190,
49 .route_val = BIT(16 + 14) | BIT(16 + 15) | BIT(15),
50 },
51 };
52
rk1808_set_mux(struct rockchip_pin_bank * bank,int pin,int mux)53 static int rk1808_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 debug("setting mux of GPIO%d-%d to %d\n", bank->bank_num, pin, mux);
63
64 if (bank->iomux[iomux_num].type & IOMUX_SOURCE_PMU)
65 regmap = priv->regmap_pmu;
66 else if (bank->iomux[iomux_num].type & IOMUX_L_SOURCE_PMU)
67 regmap = (pin % 8 < 4) ? priv->regmap_pmu : priv->regmap_base;
68 else
69 regmap = priv->regmap_base;
70
71 /* get basic quadrupel of mux registers and the correct reg inside */
72 mux_type = bank->iomux[iomux_num].type;
73 reg = bank->iomux[iomux_num].offset;
74 if (mux_type & IOMUX_WIDTH_4BIT) {
75 if ((pin % 8) >= 4)
76 reg += 0x4;
77 bit = (pin % 4) * 4;
78 mask = 0xf;
79 } else {
80 bit = (pin % 8) * 2;
81 mask = 0x3;
82 }
83
84 if (bank->recalced_mask & BIT(pin))
85 rockchip_get_recalced_mux(bank, pin, ®, &bit, &mask);
86
87 data = (mask << (bit + 16));
88 data |= (mux & mask) << bit;
89 ret = regmap_write(regmap, reg, data);
90
91 return ret;
92 }
93
94 #define RK1808_PULL_PMU_OFFSET 0x10
95 #define RK1808_PULL_GRF_OFFSET 0x80
96 #define RK1808_PULL_PINS_PER_REG 8
97 #define RK1808_PULL_BITS_PER_PIN 2
98 #define RK1808_PULL_BANK_STRIDE 16
99
rk1808_calc_pull_reg_and_bit(struct rockchip_pin_bank * bank,int pin_num,struct regmap ** regmap,int * reg,u8 * bit)100 static void rk1808_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank,
101 int pin_num,
102 struct regmap **regmap,
103 int *reg, u8 *bit)
104 {
105 struct rockchip_pinctrl_priv *priv = bank->priv;
106
107 if (bank->bank_num == 0) {
108 *regmap = priv->regmap_pmu;
109 *reg = RK1808_PULL_PMU_OFFSET;
110 } else {
111 *reg = RK1808_PULL_GRF_OFFSET;
112 *regmap = priv->regmap_base;
113 }
114
115 *reg += ((pin_num / RK1808_PULL_PINS_PER_REG) * 4);
116 *bit = (pin_num % RK1808_PULL_PINS_PER_REG);
117 *bit *= RK1808_PULL_BITS_PER_PIN;
118 }
119
120 #define RK1808_DRV_PMU_OFFSET 0x20
121 #define RK1808_DRV_GRF_OFFSET 0x140
122 #define RK1808_DRV_BITS_PER_PIN 2
123 #define RK1808_DRV_PINS_PER_REG 8
124 #define RK1808_DRV_BANK_STRIDE 16
125
rk1808_calc_drv_reg_and_bit(struct rockchip_pin_bank * bank,int pin_num,struct regmap ** regmap,int * reg,u8 * bit)126 static void rk1808_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank,
127 int pin_num,
128 struct regmap **regmap,
129 int *reg, u8 *bit)
130 {
131 struct rockchip_pinctrl_priv *priv = bank->priv;
132
133 if (bank->bank_num == 0) {
134 *regmap = priv->regmap_pmu;
135 *reg = RK1808_DRV_PMU_OFFSET;
136 } else {
137 *regmap = priv->regmap_base;
138 *reg = RK1808_DRV_GRF_OFFSET;
139 }
140
141 *reg += ((pin_num / RK1808_DRV_PINS_PER_REG) * 4);
142 *bit = pin_num % RK1808_DRV_PINS_PER_REG;
143 *bit *= RK1808_DRV_BITS_PER_PIN;
144 }
145
146 #define RK1808_SCHMITT_PMU_OFFSET 0x0040
147 #define RK1808_SCHMITT_GRF_OFFSET 0x0100
148 #define RK1808_SCHMITT_BANK_STRIDE 16
149 #define RK1808_SCHMITT_PINS_PER_REG 8
150
rk1808_calc_schmitt_reg_and_bit(struct rockchip_pin_bank * bank,int pin_num,struct regmap ** regmap,int * reg,u8 * bit)151 static int rk1808_calc_schmitt_reg_and_bit(struct rockchip_pin_bank *bank,
152 int pin_num,
153 struct regmap **regmap,
154 int *reg, u8 *bit)
155 {
156 struct rockchip_pinctrl_priv *priv = bank->priv;
157
158 if (bank->bank_num == 0) {
159 *regmap = priv->regmap_pmu;
160 *reg = RK1808_SCHMITT_PMU_OFFSET;
161 } else {
162 *regmap = priv->regmap_base;
163 *reg = RK1808_SCHMITT_GRF_OFFSET;
164 *reg += (bank->bank_num - 1) * RK1808_SCHMITT_BANK_STRIDE;
165 }
166 *reg += ((pin_num / RK1808_SCHMITT_PINS_PER_REG) * 4);
167 *bit = pin_num % RK1808_SCHMITT_PINS_PER_REG;
168
169 return 0;
170 }
171
rk1808_set_pull(struct rockchip_pin_bank * bank,int pin_num,int pull)172 static int rk1808_set_pull(struct rockchip_pin_bank *bank,
173 int pin_num, int pull)
174 {
175 struct regmap *regmap;
176 int reg, ret;
177 u8 bit, type;
178 u32 data;
179
180 if (pull == PIN_CONFIG_BIAS_PULL_PIN_DEFAULT)
181 return -ENOTSUPP;
182
183 rk1808_calc_pull_reg_and_bit(bank, pin_num, ®map, ®, &bit);
184 type = bank->pull_type[pin_num / 8];
185 ret = rockchip_translate_pull_value(type, pull);
186 if (ret < 0) {
187 debug("unsupported pull setting %d\n", pull);
188 return ret;
189 }
190
191 /* enable the write to the equivalent lower bits */
192 data = ((1 << ROCKCHIP_PULL_BITS_PER_PIN) - 1) << (bit + 16);
193
194 data |= (ret << bit);
195 ret = regmap_write(regmap, reg, data);
196
197 return ret;
198 }
199
rk1808_set_drive(struct rockchip_pin_bank * bank,int pin_num,int strength)200 static int rk1808_set_drive(struct rockchip_pin_bank *bank,
201 int pin_num, int strength)
202 {
203 struct regmap *regmap;
204 int reg;
205 u32 data;
206 u8 bit;
207
208 rk1808_calc_drv_reg_and_bit(bank, pin_num, ®map, ®, &bit);
209
210 /* enable the write to the equivalent lower bits */
211 data = ((1 << ROCKCHIP_DRV_BITS_PER_PIN) - 1) << (bit + 16);
212 data |= (strength << bit);
213
214 return regmap_write(regmap, reg, data);
215 }
216
rk1808_set_schmitt(struct rockchip_pin_bank * bank,int pin_num,int enable)217 static int rk1808_set_schmitt(struct rockchip_pin_bank *bank,
218 int pin_num, int enable)
219 {
220 struct regmap *regmap;
221 int reg;
222 u8 bit;
223 u32 data;
224
225 rk1808_calc_schmitt_reg_and_bit(bank, pin_num, ®map, ®, &bit);
226 /* enable the write to the equivalent lower bits */
227 data = BIT(bit + 16) | (enable << bit);
228
229 return regmap_write(regmap, reg, data);
230 }
231
232 static struct rockchip_pin_bank rk1808_pin_banks[] = {
233 PIN_BANK_IOMUX_FLAGS(0, 32, "gpio0",
234 IOMUX_SOURCE_PMU,
235 IOMUX_SOURCE_PMU,
236 IOMUX_SOURCE_PMU,
237 IOMUX_SOURCE_PMU),
238 PIN_BANK_IOMUX_FLAGS(1, 32, "gpio1",
239 IOMUX_WIDTH_4BIT,
240 IOMUX_WIDTH_4BIT,
241 IOMUX_WIDTH_4BIT,
242 IOMUX_WIDTH_4BIT),
243 PIN_BANK_IOMUX_FLAGS(2, 32, "gpio2",
244 IOMUX_WIDTH_4BIT,
245 IOMUX_WIDTH_4BIT,
246 IOMUX_WIDTH_4BIT,
247 IOMUX_WIDTH_4BIT),
248 PIN_BANK_IOMUX_FLAGS(3, 32, "gpio3",
249 IOMUX_WIDTH_4BIT,
250 IOMUX_WIDTH_4BIT,
251 IOMUX_WIDTH_4BIT,
252 IOMUX_WIDTH_4BIT),
253 PIN_BANK_IOMUX_FLAGS(4, 32, "gpio4",
254 IOMUX_WIDTH_4BIT,
255 IOMUX_WIDTH_4BIT,
256 IOMUX_WIDTH_4BIT,
257 IOMUX_WIDTH_4BIT),
258 };
259
260 static const struct rockchip_pin_ctrl rk1808_pin_ctrl = {
261 .pin_banks = rk1808_pin_banks,
262 .nr_banks = ARRAY_SIZE(rk1808_pin_banks),
263 .nr_pins = 160,
264 .iomux_routes = rk1808_mux_route_data,
265 .niomux_routes = ARRAY_SIZE(rk1808_mux_route_data),
266 .grf_mux_offset = 0x0,
267 .pmu_mux_offset = 0x0,
268 .set_mux = rk1808_set_mux,
269 .set_pull = rk1808_set_pull,
270 .set_drive = rk1808_set_drive,
271 .set_schmitt = rk1808_set_schmitt,
272 };
273
274 static const struct udevice_id rk1808_pinctrl_ids[] = {
275 {
276 .compatible = "rockchip,rk1808-pinctrl",
277 .data = (ulong)&rk1808_pin_ctrl
278 },
279 { }
280 };
281
282 U_BOOT_DRIVER(pinctrl_rk1808) = {
283 .name = "rockchip_rk1808_pinctrl",
284 .id = UCLASS_PINCTRL,
285 .of_match = rk1808_pinctrl_ids,
286 .priv_auto_alloc_size = sizeof(struct rockchip_pinctrl_priv),
287 .ops = &rockchip_pinctrl_ops,
288 #if !CONFIG_IS_ENABLED(OF_PLATDATA)
289 .bind = dm_scan_fdt_dev,
290 #endif
291 .probe = rockchip_pinctrl_probe,
292 };
293