xref: /rk3399_rockchip-uboot/drivers/pinctrl/rockchip/pinctrl-rv1106.c (revision 72d1fc89f31fb0f5e785875f7d725c6933af5ac3)
1ddc84990SSteven Liu // SPDX-License-Identifier: GPL-2.0+
2ddc84990SSteven Liu /*
3ddc84990SSteven Liu  * (C) Copyright 2022 Rockchip Electronics Co., Ltd
4ddc84990SSteven Liu  */
5ddc84990SSteven Liu 
6ddc84990SSteven Liu #include <common.h>
7ddc84990SSteven Liu #include <dm.h>
8ddc84990SSteven Liu #include <dm/pinctrl.h>
9ddc84990SSteven Liu #include <regmap.h>
10ddc84990SSteven Liu #include <syscon.h>
11ddc84990SSteven Liu 
12ddc84990SSteven Liu #include "pinctrl-rockchip.h"
13ddc84990SSteven Liu 
rv1106_set_mux(struct rockchip_pin_bank * bank,int pin,int mux)14ddc84990SSteven Liu static int rv1106_set_mux(struct rockchip_pin_bank *bank, int pin, int mux)
15ddc84990SSteven Liu {
16ddc84990SSteven Liu 	struct rockchip_pinctrl_priv *priv = bank->priv;
17ddc84990SSteven Liu 	int iomux_num = (pin / 8);
18ddc84990SSteven Liu 	struct regmap *regmap;
19ddc84990SSteven Liu 	int reg, ret, mask;
20ddc84990SSteven Liu 	u8 bit;
21ddc84990SSteven Liu 	u32 data;
22ddc84990SSteven Liu 
23ddc84990SSteven Liu 	debug("setting mux of GPIO%d-%d to %d\n", bank->bank_num, pin, mux);
24ddc84990SSteven Liu 
25ddc84990SSteven Liu 	if (bank->iomux[iomux_num].type & IOMUX_SOURCE_PMU)
26ddc84990SSteven Liu 		regmap = priv->regmap_pmu;
27ddc84990SSteven Liu 	else
28ddc84990SSteven Liu 		regmap = priv->regmap_base;
29ddc84990SSteven Liu 
30ddc84990SSteven Liu 	reg = bank->iomux[iomux_num].offset;
31ddc84990SSteven Liu 	if ((pin % 8) >= 4)
32ddc84990SSteven Liu 		reg += 0x4;
33ddc84990SSteven Liu 	bit = (pin % 4) * 4;
34ddc84990SSteven Liu 	mask = 0xf;
35ddc84990SSteven Liu 
36ddc84990SSteven Liu 	data = (mask << (bit + 16));
37ddc84990SSteven Liu 	data |= (mux & mask) << bit;
38ddc84990SSteven Liu 
39ddc84990SSteven Liu 	debug("iomux write reg = %x data = %x\n", reg, data);
40ddc84990SSteven Liu 
41ddc84990SSteven Liu 	ret = regmap_write(regmap, reg, data);
42ddc84990SSteven Liu 
43ddc84990SSteven Liu 	return ret;
44ddc84990SSteven Liu }
45ddc84990SSteven Liu 
46ddc84990SSteven Liu #define RV1106_DRV_BITS_PER_PIN		8
47ddc84990SSteven Liu #define RV1106_DRV_PINS_PER_REG		2
48ddc84990SSteven Liu #define RV1106_DRV_GPIO0_OFFSET		0x10
49ddc84990SSteven Liu #define RV1106_DRV_GPIO1_OFFSET		0x80
50ddc84990SSteven Liu #define RV1106_DRV_GPIO2_OFFSET		0x100C0
51ddc84990SSteven Liu #define RV1106_DRV_GPIO3_OFFSET		0x20100
52ddc84990SSteven Liu #define RV1106_DRV_GPIO4_OFFSET		0x30020
53ddc84990SSteven Liu 
rv1106_calc_drv_reg_and_bit(struct rockchip_pin_bank * bank,int pin_num,struct regmap ** regmap,int * reg,u8 * bit)54ddc84990SSteven Liu static void rv1106_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank,
55ddc84990SSteven Liu 					int pin_num, struct regmap **regmap,
56ddc84990SSteven Liu 					int *reg, u8 *bit)
57ddc84990SSteven Liu {
58ddc84990SSteven Liu 	struct rockchip_pinctrl_priv *priv = bank->priv;
59ddc84990SSteven Liu 
60ddc84990SSteven Liu 	/* GPIO0_IOC is located in PMU */
61ddc84990SSteven Liu 	switch (bank->bank_num) {
62ddc84990SSteven Liu 	case 0:
63ddc84990SSteven Liu 		*regmap = priv->regmap_pmu;
64ddc84990SSteven Liu 		*reg = RV1106_DRV_GPIO0_OFFSET;
65ddc84990SSteven Liu 		break;
66ddc84990SSteven Liu 
67ddc84990SSteven Liu 	case 1:
68ddc84990SSteven Liu 		*regmap = priv->regmap_base;
69ddc84990SSteven Liu 		*reg = RV1106_DRV_GPIO1_OFFSET;
70ddc84990SSteven Liu 		break;
71ddc84990SSteven Liu 
72ddc84990SSteven Liu 	case 2:
73ddc84990SSteven Liu 		*regmap = priv->regmap_base;
74ddc84990SSteven Liu 		*reg = RV1106_DRV_GPIO2_OFFSET;
75ddc84990SSteven Liu 		break;
76ddc84990SSteven Liu 
77ddc84990SSteven Liu 	case 3:
78ddc84990SSteven Liu 		*regmap = priv->regmap_base;
79ddc84990SSteven Liu 		*reg = RV1106_DRV_GPIO3_OFFSET;
80ddc84990SSteven Liu 		break;
81ddc84990SSteven Liu 
82ddc84990SSteven Liu 	case 4:
83ddc84990SSteven Liu 		*regmap = priv->regmap_base;
84ddc84990SSteven Liu 		*reg = RV1106_DRV_GPIO4_OFFSET;
85ddc84990SSteven Liu 		break;
86ddc84990SSteven Liu 
87ddc84990SSteven Liu 	default:
88ddc84990SSteven Liu 		*regmap = priv->regmap_base;
89ddc84990SSteven Liu 		*reg = 0;
90ddc84990SSteven Liu 		dev_err(priv->dev, "unsupported bank_num %d\n", bank->bank_num);
91ddc84990SSteven Liu 		break;
92ddc84990SSteven Liu 	}
93ddc84990SSteven Liu 
94ddc84990SSteven Liu 	*reg += ((pin_num / RV1106_DRV_PINS_PER_REG) * 4);
95ddc84990SSteven Liu 	*bit = pin_num % RV1106_DRV_PINS_PER_REG;
96ddc84990SSteven Liu 	*bit *= RV1106_DRV_BITS_PER_PIN;
97ddc84990SSteven Liu }
98ddc84990SSteven Liu 
rv1106_set_drive(struct rockchip_pin_bank * bank,int pin_num,int strength)99ddc84990SSteven Liu static int rv1106_set_drive(struct rockchip_pin_bank *bank,
100ddc84990SSteven Liu 			    int pin_num, int strength)
101ddc84990SSteven Liu {
102ddc84990SSteven Liu 	struct regmap *regmap;
103ddc84990SSteven Liu 	int reg, ret;
104ddc84990SSteven Liu 	u32 data;
105ddc84990SSteven Liu 	u8 bit;
106ddc84990SSteven Liu 	int drv = (1 << (strength + 1)) - 1;
107ddc84990SSteven Liu 
108ddc84990SSteven Liu 	rv1106_calc_drv_reg_and_bit(bank, pin_num, &regmap, &reg, &bit);
109ddc84990SSteven Liu 
110ddc84990SSteven Liu 	/* enable the write to the equivalent lower bits */
111ddc84990SSteven Liu 	data = ((1 << RV1106_DRV_BITS_PER_PIN) - 1) << (bit + 16);
112ddc84990SSteven Liu 	data |= (drv << bit);
113ddc84990SSteven Liu 	ret = regmap_write(regmap, reg, data);
114ddc84990SSteven Liu 
115ddc84990SSteven Liu 	return ret;
116ddc84990SSteven Liu }
117ddc84990SSteven Liu 
118ddc84990SSteven Liu #define RV1106_PULL_BITS_PER_PIN		2
119ddc84990SSteven Liu #define RV1106_PULL_PINS_PER_REG		8
120ddc84990SSteven Liu #define RV1106_PULL_GPIO0_OFFSET		0x38
121ddc84990SSteven Liu #define RV1106_PULL_GPIO1_OFFSET		0x1C0
122ddc84990SSteven Liu #define RV1106_PULL_GPIO2_OFFSET		0x101D0
123ddc84990SSteven Liu #define RV1106_PULL_GPIO3_OFFSET		0x201E0
124ddc84990SSteven Liu #define RV1106_PULL_GPIO4_OFFSET		0x30070
125ddc84990SSteven Liu 
rv1106_calc_pull_reg_and_bit(struct rockchip_pin_bank * bank,int pin_num,struct regmap ** regmap,int * reg,u8 * bit)126ddc84990SSteven Liu static void rv1106_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank,
127ddc84990SSteven Liu 					 int pin_num, struct regmap **regmap,
128ddc84990SSteven Liu 					 int *reg, u8 *bit)
129ddc84990SSteven Liu {
130ddc84990SSteven Liu 	struct rockchip_pinctrl_priv *priv = bank->priv;
131ddc84990SSteven Liu 
132ddc84990SSteven Liu 	/* GPIO0_IOC is located in PMU */
133ddc84990SSteven Liu 	switch (bank->bank_num) {
134ddc84990SSteven Liu 	case 0:
135ddc84990SSteven Liu 		*regmap = priv->regmap_pmu;
136ddc84990SSteven Liu 		*reg = RV1106_PULL_GPIO0_OFFSET;
137ddc84990SSteven Liu 		break;
138ddc84990SSteven Liu 
139ddc84990SSteven Liu 	case 1:
140ddc84990SSteven Liu 		*regmap = priv->regmap_base;
141ddc84990SSteven Liu 		*reg = RV1106_PULL_GPIO1_OFFSET;
142ddc84990SSteven Liu 		break;
143ddc84990SSteven Liu 
144ddc84990SSteven Liu 	case 2:
145ddc84990SSteven Liu 		*regmap = priv->regmap_base;
146ddc84990SSteven Liu 		*reg = RV1106_PULL_GPIO2_OFFSET;
147ddc84990SSteven Liu 		break;
148ddc84990SSteven Liu 
149ddc84990SSteven Liu 	case 3:
150ddc84990SSteven Liu 		*regmap = priv->regmap_base;
151ddc84990SSteven Liu 		*reg = RV1106_PULL_GPIO3_OFFSET;
152ddc84990SSteven Liu 		break;
153ddc84990SSteven Liu 
154ddc84990SSteven Liu 	case 4:
155ddc84990SSteven Liu 		*regmap = priv->regmap_base;
156ddc84990SSteven Liu 		*reg = RV1106_PULL_GPIO4_OFFSET;
157ddc84990SSteven Liu 		break;
158ddc84990SSteven Liu 
159ddc84990SSteven Liu 	default:
160ddc84990SSteven Liu 		*regmap = priv->regmap_base;
161ddc84990SSteven Liu 		*reg = 0;
162ddc84990SSteven Liu 		dev_err(priv->dev, "unsupported bank_num %d\n", bank->bank_num);
163ddc84990SSteven Liu 		break;
164ddc84990SSteven Liu 	}
165ddc84990SSteven Liu 
166ddc84990SSteven Liu 	*reg += ((pin_num / RV1106_PULL_PINS_PER_REG) * 4);
167ddc84990SSteven Liu 	*bit = pin_num % RV1106_PULL_PINS_PER_REG;
168ddc84990SSteven Liu 	*bit *= RV1106_PULL_BITS_PER_PIN;
169ddc84990SSteven Liu }
170ddc84990SSteven Liu 
rv1106_set_pull(struct rockchip_pin_bank * bank,int pin_num,int pull)171ddc84990SSteven Liu static int rv1106_set_pull(struct rockchip_pin_bank *bank,
172ddc84990SSteven Liu 			   int pin_num, int pull)
173ddc84990SSteven Liu {
174ddc84990SSteven Liu 	struct regmap *regmap;
175ddc84990SSteven Liu 	int reg, ret;
176ddc84990SSteven Liu 	u8 bit, type;
177ddc84990SSteven Liu 	u32 data;
178ddc84990SSteven Liu 
179ddc84990SSteven Liu 	if (pull == PIN_CONFIG_BIAS_PULL_PIN_DEFAULT)
180ddc84990SSteven Liu 		return -ENOTSUPP;
181ddc84990SSteven Liu 
182ddc84990SSteven Liu 	rv1106_calc_pull_reg_and_bit(bank, pin_num, &regmap, &reg, &bit);
183ddc84990SSteven Liu 	type = bank->pull_type[pin_num / 8];
184ddc84990SSteven Liu 	ret = rockchip_translate_pull_value(type, pull);
185ddc84990SSteven Liu 	if (ret < 0) {
186ddc84990SSteven Liu 		debug("unsupported pull setting %d\n", pull);
187ddc84990SSteven Liu 		return ret;
188ddc84990SSteven Liu 	}
189ddc84990SSteven Liu 
190ddc84990SSteven Liu 	/* enable the write to the equivalent lower bits */
191ddc84990SSteven Liu 	data = ((1 << RV1106_PULL_BITS_PER_PIN) - 1) << (bit + 16);
192ddc84990SSteven Liu 
193ddc84990SSteven Liu 	data |= (ret << bit);
194ddc84990SSteven Liu 	ret = regmap_write(regmap, reg, data);
195ddc84990SSteven Liu 
196ddc84990SSteven Liu 	return ret;
197ddc84990SSteven Liu }
198ddc84990SSteven Liu 
199ddc84990SSteven Liu #define RV1106_SMT_BITS_PER_PIN		1
200ddc84990SSteven Liu #define RV1106_SMT_PINS_PER_REG		8
201ddc84990SSteven Liu #define RV1106_SMT_GPIO0_OFFSET		0x40
202ddc84990SSteven Liu #define RV1106_SMT_GPIO1_OFFSET		0x280
203ddc84990SSteven Liu #define RV1106_SMT_GPIO2_OFFSET		0x10290
204ddc84990SSteven Liu #define RV1106_SMT_GPIO3_OFFSET		0x202A0
205ddc84990SSteven Liu #define RV1106_SMT_GPIO4_OFFSET		0x300A0
206ddc84990SSteven Liu 
rv1106_calc_schmitt_reg_and_bit(struct rockchip_pin_bank * bank,int pin_num,struct regmap ** regmap,int * reg,u8 * bit)207ddc84990SSteven Liu static int rv1106_calc_schmitt_reg_and_bit(struct rockchip_pin_bank *bank,
208ddc84990SSteven Liu 					   int pin_num,
209ddc84990SSteven Liu 					   struct regmap **regmap,
210ddc84990SSteven Liu 					   int *reg, u8 *bit)
211ddc84990SSteven Liu {
212ddc84990SSteven Liu 	struct rockchip_pinctrl_priv *priv = bank->priv;
213ddc84990SSteven Liu 
214ddc84990SSteven Liu 	/* GPIO0_IOC is located in PMU */
215ddc84990SSteven Liu 	switch (bank->bank_num) {
216ddc84990SSteven Liu 	case 0:
217ddc84990SSteven Liu 		*regmap = priv->regmap_pmu;
218ddc84990SSteven Liu 		*reg = RV1106_SMT_GPIO0_OFFSET;
219ddc84990SSteven Liu 		break;
220ddc84990SSteven Liu 
221ddc84990SSteven Liu 	case 1:
222ddc84990SSteven Liu 		*regmap = priv->regmap_base;
223ddc84990SSteven Liu 		*reg = RV1106_SMT_GPIO1_OFFSET;
224ddc84990SSteven Liu 		break;
225ddc84990SSteven Liu 
226ddc84990SSteven Liu 	case 2:
227ddc84990SSteven Liu 		*regmap = priv->regmap_base;
228ddc84990SSteven Liu 		*reg = RV1106_SMT_GPIO2_OFFSET;
229ddc84990SSteven Liu 		break;
230ddc84990SSteven Liu 
231ddc84990SSteven Liu 	case 3:
232ddc84990SSteven Liu 		*regmap = priv->regmap_base;
233ddc84990SSteven Liu 		*reg = RV1106_SMT_GPIO3_OFFSET;
234ddc84990SSteven Liu 		break;
235ddc84990SSteven Liu 
236ddc84990SSteven Liu 	case 4:
237ddc84990SSteven Liu 		*regmap = priv->regmap_base;
238ddc84990SSteven Liu 		*reg = RV1106_SMT_GPIO4_OFFSET;
239ddc84990SSteven Liu 		break;
240ddc84990SSteven Liu 
241ddc84990SSteven Liu 	default:
242ddc84990SSteven Liu 		*regmap = priv->regmap_base;
243ddc84990SSteven Liu 		*reg = 0;
244ddc84990SSteven Liu 		dev_err(priv->dev, "unsupported bank_num %d\n", bank->bank_num);
245ddc84990SSteven Liu 		break;
246ddc84990SSteven Liu 	}
247ddc84990SSteven Liu 
248ddc84990SSteven Liu 	*reg += ((pin_num / RV1106_SMT_PINS_PER_REG) * 4);
249ddc84990SSteven Liu 	*bit = pin_num % RV1106_SMT_PINS_PER_REG;
250ddc84990SSteven Liu 	*bit *= RV1106_SMT_BITS_PER_PIN;
251ddc84990SSteven Liu 
252ddc84990SSteven Liu 	return 0;
253ddc84990SSteven Liu }
254ddc84990SSteven Liu 
rv1106_set_schmitt(struct rockchip_pin_bank * bank,int pin_num,int enable)255ddc84990SSteven Liu static int rv1106_set_schmitt(struct rockchip_pin_bank *bank,
256ddc84990SSteven Liu 			      int pin_num, int enable)
257ddc84990SSteven Liu {
258ddc84990SSteven Liu 	struct regmap *regmap;
259ddc84990SSteven Liu 	int reg, ret;
260ddc84990SSteven Liu 	u32 data;
261ddc84990SSteven Liu 	u8 bit;
262ddc84990SSteven Liu 
263ddc84990SSteven Liu 	rv1106_calc_schmitt_reg_and_bit(bank, pin_num, &regmap, &reg, &bit);
264ddc84990SSteven Liu 
265ddc84990SSteven Liu 	/* enable the write to the equivalent lower bits */
266ddc84990SSteven Liu 	data = ((1 << RV1106_SMT_BITS_PER_PIN) - 1) << (bit + 16);
267ddc84990SSteven Liu 	data |= (enable << bit);
268ddc84990SSteven Liu 	ret = regmap_write(regmap, reg, data);
269ddc84990SSteven Liu 
270ddc84990SSteven Liu 	return ret;
271ddc84990SSteven Liu }
272ddc84990SSteven Liu 
273ddc84990SSteven Liu static struct rockchip_pin_bank rv1106_pin_banks[] = {
274*72d1fc89SSteven Liu 	PIN_BANK_IOMUX_FLAGS(0, 32, "gpio0",
275*72d1fc89SSteven Liu 			     IOMUX_WIDTH_4BIT | IOMUX_SOURCE_PMU,
276*72d1fc89SSteven Liu 			     IOMUX_WIDTH_4BIT | IOMUX_SOURCE_PMU,
277*72d1fc89SSteven Liu 			     IOMUX_WIDTH_4BIT | IOMUX_SOURCE_PMU,
278*72d1fc89SSteven Liu 			     IOMUX_WIDTH_4BIT | IOMUX_SOURCE_PMU),
279*72d1fc89SSteven Liu 	PIN_BANK_IOMUX_FLAGS_OFFSET(1, 32, "gpio1",
280*72d1fc89SSteven Liu 				    IOMUX_WIDTH_4BIT,
281ddc84990SSteven Liu 				    IOMUX_WIDTH_4BIT,
282ddc84990SSteven Liu 				    IOMUX_WIDTH_4BIT,
283ddc84990SSteven Liu 				    IOMUX_WIDTH_4BIT,
284ddc84990SSteven Liu 				    0, 0x08, 0x10, 0x18),
285*72d1fc89SSteven Liu 	PIN_BANK_IOMUX_FLAGS_OFFSET(2, 32, "gpio2",
286ddc84990SSteven Liu 				    IOMUX_WIDTH_4BIT,
287*72d1fc89SSteven Liu 				    IOMUX_WIDTH_4BIT,
288*72d1fc89SSteven Liu 				    IOMUX_WIDTH_4BIT,
289*72d1fc89SSteven Liu 				    IOMUX_WIDTH_4BIT,
290ddc84990SSteven Liu 				    0x10020, 0x10028, 0, 0),
291*72d1fc89SSteven Liu 	PIN_BANK_IOMUX_FLAGS_OFFSET(3, 32, "gpio3",
292*72d1fc89SSteven Liu 				    IOMUX_WIDTH_4BIT,
293ddc84990SSteven Liu 				    IOMUX_WIDTH_4BIT,
294ddc84990SSteven Liu 				    IOMUX_WIDTH_4BIT,
295ddc84990SSteven Liu 				    IOMUX_WIDTH_4BIT,
296ddc84990SSteven Liu 				    0x20040, 0x20048, 0x20050, 0x20058),
297*72d1fc89SSteven Liu 	PIN_BANK_IOMUX_FLAGS_OFFSET(4, 24, "gpio4",
298*72d1fc89SSteven Liu 				    IOMUX_WIDTH_4BIT,
299ddc84990SSteven Liu 				    IOMUX_WIDTH_4BIT,
300ddc84990SSteven Liu 				    IOMUX_WIDTH_4BIT,
301ddc84990SSteven Liu 				    0,
302ddc84990SSteven Liu 				    0x30000, 0x30008, 0x30010, 0),
303ddc84990SSteven Liu };
304ddc84990SSteven Liu 
305ddc84990SSteven Liu static const struct rockchip_pin_ctrl rv1106_pin_ctrl = {
306ddc84990SSteven Liu 	.pin_banks		= rv1106_pin_banks,
307ddc84990SSteven Liu 	.nr_banks		= ARRAY_SIZE(rv1106_pin_banks),
308*72d1fc89SSteven Liu 	.nr_pins		= 152,
309ddc84990SSteven Liu 	.grf_mux_offset		= 0x0,
310ddc84990SSteven Liu 	.pmu_mux_offset		= 0x0,
311ddc84990SSteven Liu 	.set_mux		= rv1106_set_mux,
312ddc84990SSteven Liu 	.set_pull		= rv1106_set_pull,
313ddc84990SSteven Liu 	.set_drive		= rv1106_set_drive,
314ddc84990SSteven Liu 	.set_schmitt		= rv1106_set_schmitt,
315ddc84990SSteven Liu };
316ddc84990SSteven Liu 
317ddc84990SSteven Liu static const struct udevice_id rv1106_pinctrl_ids[] = {
318ddc84990SSteven Liu 	{
319ddc84990SSteven Liu 		.compatible = "rockchip,rv1106-pinctrl",
320ddc84990SSteven Liu 		.data = (ulong)&rv1106_pin_ctrl
321ddc84990SSteven Liu 	},
322ddc84990SSteven Liu 	{ }
323ddc84990SSteven Liu };
324ddc84990SSteven Liu 
325ddc84990SSteven Liu U_BOOT_DRIVER(pinctrl_rv1106) = {
326ddc84990SSteven Liu 	.name		= "rockchip_rv1106_pinctrl",
327ddc84990SSteven Liu 	.id		= UCLASS_PINCTRL,
328ddc84990SSteven Liu 	.of_match	= rv1106_pinctrl_ids,
329ddc84990SSteven Liu 	.priv_auto_alloc_size = sizeof(struct rockchip_pinctrl_priv),
330ddc84990SSteven Liu 	.ops		= &rockchip_pinctrl_ops,
331ddc84990SSteven Liu #if !CONFIG_IS_ENABLED(OF_PLATDATA)
332ddc84990SSteven Liu 	.bind		= dm_scan_fdt_dev,
333ddc84990SSteven Liu #endif
334ddc84990SSteven Liu 	.probe		= rockchip_pinctrl_probe,
335ddc84990SSteven Liu };
336