1190207Srpaulo// SPDX-License-Identifier: GPL-2.0+
2127668Sbms/*
3127668Sbms * (C) Copyright 2019 Rockchip Electronics Co., Ltd
4127668Sbms */
5127668Sbms
6127668Sbms#include <common.h>
7127668Sbms#include <dm.h>
8127668Sbms#include <log.h>
9127668Sbms#include <dm/pinctrl.h>
10127668Sbms#include <regmap.h>
11127668Sbms#include <syscon.h>
12127668Sbms#include <linux/bitops.h>
13127668Sbms
14127668Sbms#include "pinctrl-rockchip.h"
15127668Sbms
16127668Sbmsstatic struct rockchip_mux_recalced_data rv1108_mux_recalced_data[] = {
17190207Srpaulo	{
18190207Srpaulo		.num = 1,
19190207Srpaulo		.pin = 0,
20190207Srpaulo		.reg = 0x418,
21190207Srpaulo		.bit = 0,
22190207Srpaulo		.mask = 0x3
23190207Srpaulo	}, {
24190207Srpaulo		.num = 1,
25190207Srpaulo		.pin = 1,
26214478Srpaulo		.reg = 0x418,
27214478Srpaulo		.bit = 2,
28214478Srpaulo		.mask = 0x3
29214478Srpaulo	}, {
30214478Srpaulo		.num = 1,
31214478Srpaulo		.pin = 2,
32214478Srpaulo		.reg = 0x418,
33214478Srpaulo		.bit = 4,
34214478Srpaulo		.mask = 0x3
35	}, {
36		.num = 1,
37		.pin = 3,
38		.reg = 0x418,
39		.bit = 6,
40		.mask = 0x3
41	}, {
42		.num = 1,
43		.pin = 4,
44		.reg = 0x418,
45		.bit = 8,
46		.mask = 0x3
47	}, {
48		.num = 1,
49		.pin = 5,
50		.reg = 0x418,
51		.bit = 10,
52		.mask = 0x3
53	}, {
54		.num = 1,
55		.pin = 6,
56		.reg = 0x418,
57		.bit = 12,
58		.mask = 0x3
59	}, {
60		.num = 1,
61		.pin = 7,
62		.reg = 0x418,
63		.bit = 14,
64		.mask = 0x3
65	}, {
66		.num = 1,
67		.pin = 8,
68		.reg = 0x41c,
69		.bit = 0,
70		.mask = 0x3
71	}, {
72		.num = 1,
73		.pin = 9,
74		.reg = 0x41c,
75		.bit = 2,
76		.mask = 0x3
77	},
78};
79
80static int rv1108_set_mux(struct rockchip_pin_bank *bank, int pin, int mux)
81{
82	struct rockchip_pinctrl_priv *priv = bank->priv;
83	int iomux_num = (pin / 8);
84	struct regmap *regmap;
85	int reg, ret, mask, mux_type;
86	u8 bit;
87	u32 data;
88
89	regmap = (bank->iomux[iomux_num].type & IOMUX_SOURCE_PMU)
90				? priv->regmap_pmu : priv->regmap_base;
91
92	/* get basic quadrupel of mux registers and the correct reg inside */
93	mux_type = bank->iomux[iomux_num].type;
94	reg = bank->iomux[iomux_num].offset;
95	reg += rockchip_get_mux_data(mux_type, pin, &bit, &mask);
96
97	if (bank->recalced_mask & BIT(pin))
98		rockchip_get_recalced_mux(bank, pin, &reg, &bit, &mask);
99
100	data = (mask << (bit + 16));
101	data |= (mux & mask) << bit;
102	ret = regmap_write(regmap, reg, data);
103
104	return ret;
105}
106
107#define RV1108_PULL_PMU_OFFSET		0x10
108#define RV1108_PULL_OFFSET		0x110
109
110static void rv1108_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank,
111					 int pin_num, struct regmap **regmap,
112					 int *reg, u8 *bit)
113{
114	struct rockchip_pinctrl_priv *priv = bank->priv;
115
116	/* The first 24 pins of the first bank are located in PMU */
117	if (bank->bank_num == 0) {
118		*regmap = priv->regmap_pmu;
119		*reg = RV1108_PULL_PMU_OFFSET;
120	} else {
121		*reg = RV1108_PULL_OFFSET;
122		*regmap = priv->regmap_base;
123		/* correct the offset, as we're starting with the 2nd bank */
124		*reg -= 0x10;
125		*reg += bank->bank_num * ROCKCHIP_PULL_BANK_STRIDE;
126	}
127
128	*reg += ((pin_num / ROCKCHIP_PULL_PINS_PER_REG) * 4);
129	*bit = (pin_num % ROCKCHIP_PULL_PINS_PER_REG);
130	*bit *= ROCKCHIP_PULL_BITS_PER_PIN;
131}
132
133static int rv1108_set_pull(struct rockchip_pin_bank *bank,
134			   int pin_num, int pull)
135{
136	struct regmap *regmap;
137	int reg, ret;
138	u8 bit, type;
139	u32 data;
140
141	if (pull == PIN_CONFIG_BIAS_PULL_PIN_DEFAULT)
142		return -ENOTSUPP;
143
144	rv1108_calc_pull_reg_and_bit(bank, pin_num, &regmap, &reg, &bit);
145	type = bank->pull_type[pin_num / 8];
146	ret = rockchip_translate_pull_value(type, pull);
147	if (ret < 0) {
148		debug("unsupported pull setting %d\n", pull);
149		return ret;
150	}
151
152	/* enable the write to the equivalent lower bits */
153	data = ((1 << ROCKCHIP_PULL_BITS_PER_PIN) - 1) << (bit + 16);
154
155	data |= (ret << bit);
156	ret = regmap_write(regmap, reg, data);
157
158	return ret;
159}
160
161#define RV1108_DRV_PMU_OFFSET		0x20
162#define RV1108_DRV_GRF_OFFSET		0x210
163
164static void rv1108_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank,
165					int pin_num, struct regmap **regmap,
166					int *reg, u8 *bit)
167{
168	struct rockchip_pinctrl_priv *priv = bank->priv;
169
170	/* The first 24 pins of the first bank are located in PMU */
171	if (bank->bank_num == 0) {
172		*regmap = priv->regmap_pmu;
173		*reg = RV1108_DRV_PMU_OFFSET;
174	} else {
175		*regmap = priv->regmap_base;
176		*reg = RV1108_DRV_GRF_OFFSET;
177
178		/* correct the offset, as we're starting with the 2nd bank */
179		*reg -= 0x10;
180		*reg += bank->bank_num * ROCKCHIP_DRV_BANK_STRIDE;
181	}
182
183	*reg += ((pin_num / ROCKCHIP_DRV_PINS_PER_REG) * 4);
184	*bit = pin_num % ROCKCHIP_DRV_PINS_PER_REG;
185	*bit *= ROCKCHIP_DRV_BITS_PER_PIN;
186}
187
188static int rv1108_set_drive(struct rockchip_pin_bank *bank,
189			    int pin_num, int strength)
190{
191	struct regmap *regmap;
192	int reg, ret;
193	u32 data;
194	u8 bit;
195	int type = bank->drv[pin_num / 8].drv_type;
196
197	rv1108_calc_drv_reg_and_bit(bank, pin_num, &regmap, &reg, &bit);
198	ret = rockchip_translate_drive_value(type, strength);
199	if (ret < 0) {
200		debug("unsupported driver strength %d\n", strength);
201		return ret;
202	}
203
204	/* enable the write to the equivalent lower bits */
205	data = ((1 << ROCKCHIP_DRV_BITS_PER_PIN) - 1) << (bit + 16);
206
207	data |= (ret << bit);
208	ret = regmap_write(regmap, reg, data);
209	return ret;
210}
211
212#define RV1108_SCHMITT_PMU_OFFSET		0x30
213#define RV1108_SCHMITT_GRF_OFFSET		0x388
214#define RV1108_SCHMITT_BANK_STRIDE		8
215#define RV1108_SCHMITT_PINS_PER_GRF_REG		16
216#define RV1108_SCHMITT_PINS_PER_PMU_REG		8
217
218static int rv1108_calc_schmitt_reg_and_bit(struct rockchip_pin_bank *bank,
219					   int pin_num,
220					   struct regmap **regmap,
221					   int *reg, u8 *bit)
222{
223	struct rockchip_pinctrl_priv *priv = bank->priv;
224	int pins_per_reg;
225
226	if (bank->bank_num == 0) {
227		*regmap = priv->regmap_pmu;
228		*reg = RV1108_SCHMITT_PMU_OFFSET;
229		pins_per_reg = RV1108_SCHMITT_PINS_PER_PMU_REG;
230	} else {
231		*regmap = priv->regmap_base;
232		*reg = RV1108_SCHMITT_GRF_OFFSET;
233		pins_per_reg = RV1108_SCHMITT_PINS_PER_GRF_REG;
234		*reg += (bank->bank_num  - 1) * RV1108_SCHMITT_BANK_STRIDE;
235	}
236	*reg += ((pin_num / pins_per_reg) * 4);
237	*bit = pin_num % pins_per_reg;
238
239	return 0;
240}
241
242static int rv1108_set_schmitt(struct rockchip_pin_bank *bank,
243			      int pin_num, int enable)
244{
245	struct regmap *regmap;
246	int reg;
247	u8 bit;
248	u32 data;
249
250	rv1108_calc_schmitt_reg_and_bit(bank, pin_num, &regmap, &reg, &bit);
251	/* enable the write to the equivalent lower bits */
252	data = BIT(bit + 16) | (enable << bit);
253
254	return regmap_write(regmap, reg, data);
255}
256
257static struct rockchip_pin_bank rv1108_pin_banks[] = {
258	PIN_BANK_IOMUX_FLAGS(0, 32, "gpio0", IOMUX_SOURCE_PMU,
259					     IOMUX_SOURCE_PMU,
260					     IOMUX_SOURCE_PMU,
261					     IOMUX_SOURCE_PMU),
262	PIN_BANK_IOMUX_FLAGS(1, 32, "gpio1", 0, 0, 0, 0),
263	PIN_BANK_IOMUX_FLAGS(2, 32, "gpio2", 0, 0, 0, 0),
264	PIN_BANK_IOMUX_FLAGS(3, 32, "gpio3", 0, 0, 0, 0),
265};
266
267static struct rockchip_pin_ctrl rv1108_pin_ctrl = {
268	.pin_banks		= rv1108_pin_banks,
269	.nr_banks		= ARRAY_SIZE(rv1108_pin_banks),
270	.grf_mux_offset		= 0x10,
271	.pmu_mux_offset		= 0x0,
272	.iomux_recalced		= rv1108_mux_recalced_data,
273	.niomux_recalced	= ARRAY_SIZE(rv1108_mux_recalced_data),
274	.set_mux		= rv1108_set_mux,
275	.set_pull		= rv1108_set_pull,
276	.set_drive		= rv1108_set_drive,
277	.set_schmitt		= rv1108_set_schmitt,
278};
279
280static const struct udevice_id rv1108_pinctrl_ids[] = {
281	{
282		.compatible = "rockchip,rv1108-pinctrl",
283		.data = (ulong)&rv1108_pin_ctrl
284	},
285	{ }
286};
287
288U_BOOT_DRIVER(pinctrl_rv1108) = {
289	.name           = "pinctrl_rv1108",
290	.id             = UCLASS_PINCTRL,
291	.of_match       = rv1108_pinctrl_ids,
292	.priv_auto	= sizeof(struct rockchip_pinctrl_priv),
293	.ops            = &rockchip_pinctrl_ops,
294#if CONFIG_IS_ENABLED(OF_REAL)
295	.bind		= dm_scan_fdt_dev,
296#endif
297	.probe          = rockchip_pinctrl_probe,
298};
299