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, ®map, ®, &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, ®map, ®, &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, ®map, ®, &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