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 
16 static struct rockchip_mux_recalced_data rk3308_mux_recalced_data[] = {
17 	{
18 		.num = 1,
19 		.pin = 14,
20 		.reg = 0x28,
21 		.bit = 12,
22 		.mask = 0xf
23 	}, {
24 		.num = 1,
25 		.pin = 15,
26 		.reg = 0x2c,
27 		.bit = 0,
28 		.mask = 0x3
29 	}, {
30 		.num = 1,
31 		.pin = 18,
32 		.reg = 0x30,
33 		.bit = 4,
34 		.mask = 0xf
35 	}, {
36 		.num = 1,
37 		.pin = 19,
38 		.reg = 0x30,
39 		.bit = 8,
40 		.mask = 0xf
41 	}, {
42 		.num = 1,
43 		.pin = 20,
44 		.reg = 0x30,
45 		.bit = 12,
46 		.mask = 0xf
47 	}, {
48 		.num = 1,
49 		.pin = 21,
50 		.reg = 0x34,
51 		.bit = 0,
52 		.mask = 0xf
53 	}, {
54 		.num = 1,
55 		.pin = 22,
56 		.reg = 0x34,
57 		.bit = 4,
58 		.mask = 0xf
59 	}, {
60 		.num = 1,
61 		.pin = 23,
62 		.reg = 0x34,
63 		.bit = 8,
64 		.mask = 0xf
65 	}, {
66 		.num = 3,
67 		.pin = 12,
68 		.reg = 0x68,
69 		.bit = 8,
70 		.mask = 0xf
71 	}, {
72 		.num = 3,
73 		.pin = 13,
74 		.reg = 0x68,
75 		.bit = 12,
76 		.mask = 0xf
77 	}, {
78 		.num = 2,
79 		.pin = 2,
80 		.reg = 0x608,
81 		.bit = 0,
82 		.mask = 0x7
83 	}, {
84 		.num = 2,
85 		.pin = 3,
86 		.reg = 0x608,
87 		.bit = 4,
88 		.mask = 0x7
89 	}, {
90 		.num = 2,
91 		.pin = 16,
92 		.reg = 0x610,
93 		.bit = 8,
94 		.mask = 0x7
95 	}, {
96 		.num = 3,
97 		.pin = 10,
98 		.reg = 0x610,
99 		.bit = 0,
100 		.mask = 0x7
101 	}, {
102 		.num = 3,
103 		.pin = 11,
104 		.reg = 0x610,
105 		.bit = 4,
106 		.mask = 0x7
107 	},
108 };
109 
110 static struct rockchip_mux_route_data rk3308_mux_route_data[] = {
111 	{
112 		/* rtc_clk */
113 		.bank_num = 0,
114 		.pin = 19,
115 		.func = 1,
116 		.route_offset = 0x314,
117 		.route_val = BIT(16 + 0) | BIT(0),
118 	}, {
119 		/* uart2_rxm0 */
120 		.bank_num = 1,
121 		.pin = 22,
122 		.func = 2,
123 		.route_offset = 0x314,
124 		.route_val = BIT(16 + 2) | BIT(16 + 3),
125 	}, {
126 		/* uart2_rxm1 */
127 		.bank_num = 4,
128 		.pin = 26,
129 		.func = 2,
130 		.route_offset = 0x314,
131 		.route_val = BIT(16 + 2) | BIT(16 + 3) | BIT(2),
132 	}, {
133 		/* i2c3_sdam0 */
134 		.bank_num = 0,
135 		.pin = 15,
136 		.func = 2,
137 		.route_offset = 0x608,
138 		.route_val = BIT(16 + 8) | BIT(16 + 9),
139 	}, {
140 		/* i2c3_sdam1 */
141 		.bank_num = 3,
142 		.pin = 12,
143 		.func = 2,
144 		.route_offset = 0x608,
145 		.route_val = BIT(16 + 8) | BIT(16 + 9) | BIT(8),
146 	}, {
147 		/* i2c3_sdam2 */
148 		.bank_num = 2,
149 		.pin = 0,
150 		.func = 3,
151 		.route_offset = 0x608,
152 		.route_val = BIT(16 + 8) | BIT(16 + 9) | BIT(9),
153 	}, {
154 		/* i2s-8ch-1-sclktxm0 */
155 		.bank_num = 1,
156 		.pin = 3,
157 		.func = 2,
158 		.route_offset = 0x308,
159 		.route_val = BIT(16 + 3),
160 	}, {
161 		/* i2s-8ch-1-sclkrxm0 */
162 		.bank_num = 1,
163 		.pin = 4,
164 		.func = 2,
165 		.route_offset = 0x308,
166 		.route_val = BIT(16 + 3),
167 	}, {
168 		/* i2s-8ch-1-sclktxm1 */
169 		.bank_num = 1,
170 		.pin = 13,
171 		.func = 2,
172 		.route_offset = 0x308,
173 		.route_val = BIT(16 + 3) | BIT(3),
174 	}, {
175 		/* i2s-8ch-1-sclkrxm1 */
176 		.bank_num = 1,
177 		.pin = 14,
178 		.func = 2,
179 		.route_offset = 0x308,
180 		.route_val = BIT(16 + 3) | BIT(3),
181 	}, {
182 		/* pdm-clkm0 */
183 		.bank_num = 1,
184 		.pin = 4,
185 		.func = 3,
186 		.route_offset = 0x308,
187 		.route_val =  BIT(16 + 12) | BIT(16 + 13),
188 	}, {
189 		/* pdm-clkm1 */
190 		.bank_num = 1,
191 		.pin = 14,
192 		.func = 4,
193 		.route_offset = 0x308,
194 		.route_val = BIT(16 + 12) | BIT(16 + 13) | BIT(12),
195 	}, {
196 		/* pdm-clkm2 */
197 		.bank_num = 2,
198 		.pin = 6,
199 		.func = 2,
200 		.route_offset = 0x308,
201 		.route_val = BIT(16 + 12) | BIT(16 + 13) | BIT(13),
202 	}, {
203 		/* pdm-clkm-m2 */
204 		.bank_num = 2,
205 		.pin = 4,
206 		.func = 3,
207 		.route_offset = 0x600,
208 		.route_val = BIT(16 + 2) | BIT(2),
209 	}, {
210 		/* spi1_miso */
211 		.bank_num = 3,
212 		.pin = 10,
213 		.func = 3,
214 		.route_offset = 0x314,
215 		.route_val = BIT(16 + 9),
216 	}, {
217 		/* spi1_miso_m1 */
218 		.bank_num = 2,
219 		.pin = 4,
220 		.func = 2,
221 		.route_offset = 0x314,
222 		.route_val = BIT(16 + 9) | BIT(9),
223 	}, {
224 		/* mac_rxd0_m0 */
225 		.bank_num = 1,
226 		.pin = 20,
227 		.func = 3,
228 		.route_offset = 0x314,
229 		.route_val = BIT(16 + 14),
230 	}, {
231 		/* mac_rxd0_m1 */
232 		.bank_num = 4,
233 		.pin = 2,
234 		.func = 2,
235 		.route_offset = 0x314,
236 		.route_val = BIT(16 + 14) | BIT(14),
237 	}, {
238 		/* uart3_rx */
239 		.bank_num = 3,
240 		.pin = 12,
241 		.func = 4,
242 		.route_offset = 0x314,
243 		.route_val = BIT(16 + 15),
244 	}, {
245 		/* uart3_rx_m1 */
246 		.bank_num = 0,
247 		.pin = 17,
248 		.func = 3,
249 		.route_offset = 0x314,
250 		.route_val = BIT(16 + 15) | BIT(15),
251 	},
252 };
253 
rk3308_set_mux(struct rockchip_pin_bank * bank,int pin,int mux)254 static int rk3308_set_mux(struct rockchip_pin_bank *bank, int pin, int mux)
255 {
256 	struct rockchip_pinctrl_priv *priv = bank->priv;
257 	int iomux_num = (pin / 8);
258 	struct regmap *regmap;
259 	int reg, ret, mask, mux_type;
260 	u8 bit;
261 	u32 data, route_reg, route_val;
262 
263 	regmap = (bank->iomux[iomux_num].type & IOMUX_SOURCE_PMU)
264 				? priv->regmap_pmu : priv->regmap_base;
265 
266 	/* get basic quadrupel of mux registers and the correct reg inside */
267 	mux_type = bank->iomux[iomux_num].type;
268 	reg = bank->iomux[iomux_num].offset;
269 	reg += rockchip_get_mux_data(mux_type, pin, &bit, &mask);
270 
271 	if (bank->recalced_mask & BIT(pin))
272 		rockchip_get_recalced_mux(bank, pin, &reg, &bit, &mask);
273 
274 	if (bank->route_mask & BIT(pin)) {
275 		if (rockchip_get_mux_route(bank, pin, mux, &route_reg,
276 					   &route_val)) {
277 			ret = regmap_write(regmap, route_reg, route_val);
278 			if (ret)
279 				return ret;
280 		}
281 	}
282 
283 	data = (mask << (bit + 16));
284 	data |= (mux & mask) << bit;
285 	ret = regmap_write(regmap, reg, data);
286 
287 	return ret;
288 }
289 
290 #define RK3308_PULL_OFFSET		0xa0
291 
rk3308_calc_pull_reg_and_bit(struct rockchip_pin_bank * bank,int pin_num,struct regmap ** regmap,int * reg,u8 * bit)292 static void rk3308_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank,
293 					 int pin_num, struct regmap **regmap,
294 					 int *reg, u8 *bit)
295 {
296 	struct rockchip_pinctrl_priv *priv = bank->priv;
297 
298 	*regmap = priv->regmap_base;
299 	*reg = RK3308_PULL_OFFSET;
300 	*reg += bank->bank_num * ROCKCHIP_PULL_BANK_STRIDE;
301 	*reg += ((pin_num / ROCKCHIP_PULL_PINS_PER_REG) * 4);
302 
303 	*bit = (pin_num % ROCKCHIP_PULL_PINS_PER_REG);
304 	*bit *= ROCKCHIP_PULL_BITS_PER_PIN;
305 }
306 
rk3308_set_pull(struct rockchip_pin_bank * bank,int pin_num,int pull)307 static int rk3308_set_pull(struct rockchip_pin_bank *bank,
308 			   int pin_num, int pull)
309 {
310 	struct regmap *regmap;
311 	int reg, ret;
312 	u8 bit, type;
313 	u32 data;
314 
315 	if (pull == PIN_CONFIG_BIAS_PULL_PIN_DEFAULT)
316 		return -ENOTSUPP;
317 
318 	rk3308_calc_pull_reg_and_bit(bank, pin_num, &regmap, &reg, &bit);
319 	type = bank->pull_type[pin_num / 8];
320 	ret = rockchip_translate_pull_value(type, pull);
321 	if (ret < 0) {
322 		debug("unsupported pull setting %d\n", pull);
323 		return ret;
324 	}
325 
326 	/* enable the write to the equivalent lower bits */
327 	data = ((1 << ROCKCHIP_PULL_BITS_PER_PIN) - 1) << (bit + 16);
328 	data |= (ret << bit);
329 
330 	ret = regmap_write(regmap, reg, data);
331 
332 	return ret;
333 }
334 
335 #define RK3308_DRV_GRF_OFFSET		0x100
336 
rk3308_calc_drv_reg_and_bit(struct rockchip_pin_bank * bank,int pin_num,struct regmap ** regmap,int * reg,u8 * bit)337 static void rk3308_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank,
338 					int pin_num, struct regmap **regmap,
339 					int *reg, u8 *bit)
340 {
341 	struct rockchip_pinctrl_priv *priv = bank->priv;
342 
343 	*regmap = priv->regmap_base;
344 	*reg = RK3308_DRV_GRF_OFFSET;
345 	*reg += bank->bank_num * ROCKCHIP_DRV_BANK_STRIDE;
346 	*reg += ((pin_num / ROCKCHIP_DRV_PINS_PER_REG) * 4);
347 
348 	*bit = (pin_num % ROCKCHIP_DRV_PINS_PER_REG);
349 	*bit *= ROCKCHIP_DRV_BITS_PER_PIN;
350 }
351 
rk3308_set_drive(struct rockchip_pin_bank * bank,int pin_num,int strength)352 static int rk3308_set_drive(struct rockchip_pin_bank *bank,
353 			    int pin_num, int strength)
354 {
355 	struct regmap *regmap;
356 	int reg, ret;
357 	u32 data;
358 	u8 bit;
359 	int type = bank->drv[pin_num / 8].drv_type;
360 
361 	rk3308_calc_drv_reg_and_bit(bank, pin_num, &regmap, &reg, &bit);
362 	ret = rockchip_translate_drive_value(type, strength);
363 	if (ret < 0) {
364 		debug("unsupported driver strength %d\n", strength);
365 		return ret;
366 	}
367 
368 	/* enable the write to the equivalent lower bits */
369 	data = ((1 << ROCKCHIP_DRV_BITS_PER_PIN) - 1) << (bit + 16);
370 	data |= (ret << bit);
371 	ret = regmap_write(regmap, reg, data);
372 	return ret;
373 }
374 
375 #define RK3308_SCHMITT_PINS_PER_REG	8
376 #define RK3308_SCHMITT_BANK_STRIDE	16
377 #define RK3308_SCHMITT_GRF_OFFSET	0x1a0
378 
rk3308_calc_schmitt_reg_and_bit(struct rockchip_pin_bank * bank,int pin_num,struct regmap ** regmap,int * reg,u8 * bit)379 static int rk3308_calc_schmitt_reg_and_bit(struct rockchip_pin_bank *bank,
380 					   int pin_num,
381 					   struct regmap **regmap,
382 					   int *reg, u8 *bit)
383 {
384 	struct rockchip_pinctrl_priv *priv = bank->priv;
385 
386 	*regmap = priv->regmap_base;
387 	*reg = RK3308_SCHMITT_GRF_OFFSET;
388 
389 	*reg += bank->bank_num * RK3308_SCHMITT_BANK_STRIDE;
390 	*reg += ((pin_num / RK3308_SCHMITT_PINS_PER_REG) * 4);
391 	*bit = pin_num % RK3308_SCHMITT_PINS_PER_REG;
392 
393 	return 0;
394 }
395 
rk3308_set_schmitt(struct rockchip_pin_bank * bank,int pin_num,int enable)396 static int rk3308_set_schmitt(struct rockchip_pin_bank *bank,
397 			      int pin_num, int enable)
398 {
399 	struct regmap *regmap;
400 	int reg;
401 	u8 bit;
402 	u32 data;
403 
404 	rk3308_calc_schmitt_reg_and_bit(bank, pin_num, &regmap, &reg, &bit);
405 	/* enable the write to the equivalent lower bits */
406 	data = BIT(bit + 16) | (enable << bit);
407 
408 	return regmap_write(regmap, reg, data);
409 }
410 
411 static struct rockchip_pin_bank rk3308_pin_banks[] = {
412 	PIN_BANK_IOMUX_FLAGS(0, 32, "gpio0", IOMUX_8WIDTH_2BIT,
413 					     IOMUX_8WIDTH_2BIT,
414 					     IOMUX_8WIDTH_2BIT,
415 					     IOMUX_8WIDTH_2BIT),
416 	PIN_BANK_IOMUX_FLAGS(1, 32, "gpio1", IOMUX_8WIDTH_2BIT,
417 					     IOMUX_8WIDTH_2BIT,
418 					     IOMUX_8WIDTH_2BIT,
419 					     IOMUX_8WIDTH_2BIT),
420 	PIN_BANK_IOMUX_FLAGS(2, 32, "gpio2", IOMUX_8WIDTH_2BIT,
421 					     IOMUX_8WIDTH_2BIT,
422 					     IOMUX_8WIDTH_2BIT,
423 					     IOMUX_8WIDTH_2BIT),
424 	PIN_BANK_IOMUX_FLAGS(3, 32, "gpio3", IOMUX_8WIDTH_2BIT,
425 					     IOMUX_8WIDTH_2BIT,
426 					     IOMUX_8WIDTH_2BIT,
427 					     IOMUX_8WIDTH_2BIT),
428 	PIN_BANK_IOMUX_FLAGS(4, 32, "gpio4", IOMUX_8WIDTH_2BIT,
429 					     IOMUX_8WIDTH_2BIT,
430 					     IOMUX_8WIDTH_2BIT,
431 					     IOMUX_8WIDTH_2BIT),
432 };
433 
434 static struct rockchip_pin_ctrl rk3308_pin_ctrl = {
435 	.pin_banks		= rk3308_pin_banks,
436 	.nr_banks		= ARRAY_SIZE(rk3308_pin_banks),
437 	.grf_mux_offset		= 0x0,
438 	.iomux_recalced		= rk3308_mux_recalced_data,
439 	.niomux_recalced	= ARRAY_SIZE(rk3308_mux_recalced_data),
440 	.iomux_routes		= rk3308_mux_route_data,
441 	.niomux_routes		= ARRAY_SIZE(rk3308_mux_route_data),
442 	.set_mux		= rk3308_set_mux,
443 	.set_drive		= rk3308_set_drive,
444 	.set_pull		= rk3308_set_pull,
445 	.set_schmitt		= rk3308_set_schmitt,
446 };
447 
448 static const struct udevice_id rk3308_pinctrl_ids[] = {
449 	{
450 		.compatible = "rockchip,rk3308-pinctrl",
451 		.data = (ulong)&rk3308_pin_ctrl
452 	},
453 	{ }
454 };
455 
456 U_BOOT_DRIVER(pinctrl_rk3308) = {
457 	.name		= "rockchip_rk3308_pinctrl",
458 	.id		= UCLASS_PINCTRL,
459 	.of_match	= rk3308_pinctrl_ids,
460 	.priv_auto	= sizeof(struct rockchip_pinctrl_priv),
461 	.ops		= &rockchip_pinctrl_ops,
462 #if !CONFIG_IS_ENABLED(OF_PLATDATA)
463 	.bind		= dm_scan_fdt_dev,
464 #endif
465 	.probe		= rockchip_pinctrl_probe,
466 };
467