xref: /OK3568_Linux_fs/u-boot/drivers/pinctrl/rockchip/pinctrl-rockchip-core.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0+
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * (C) Copyright 2019 Rockchip Electronics Co., Ltd
4*4882a593Smuzhiyun  */
5*4882a593Smuzhiyun 
6*4882a593Smuzhiyun #include <common.h>
7*4882a593Smuzhiyun #include <dm.h>
8*4882a593Smuzhiyun #include <dm/pinctrl.h>
9*4882a593Smuzhiyun #include <regmap.h>
10*4882a593Smuzhiyun #include <syscon.h>
11*4882a593Smuzhiyun #include <fdtdec.h>
12*4882a593Smuzhiyun 
13*4882a593Smuzhiyun #include "pinctrl-rockchip.h"
14*4882a593Smuzhiyun 
15*4882a593Smuzhiyun #define MAX_ROCKCHIP_PINS_ENTRIES	30
16*4882a593Smuzhiyun #define MAX_ROCKCHIP_GPIO_PER_BANK      32
17*4882a593Smuzhiyun #define RK_FUNC_GPIO                    0
18*4882a593Smuzhiyun 
rockchip_verify_config(struct udevice * dev,u32 bank,u32 pin)19*4882a593Smuzhiyun static int rockchip_verify_config(struct udevice *dev, u32 bank, u32 pin)
20*4882a593Smuzhiyun {
21*4882a593Smuzhiyun 	struct rockchip_pinctrl_priv *priv = dev_get_priv(dev);
22*4882a593Smuzhiyun 	struct rockchip_pin_ctrl *ctrl = priv->ctrl;
23*4882a593Smuzhiyun 
24*4882a593Smuzhiyun 	if (bank >= ctrl->nr_banks) {
25*4882a593Smuzhiyun 		debug("pin conf bank %d >= nbanks %d\n", bank, ctrl->nr_banks);
26*4882a593Smuzhiyun 		return -EINVAL;
27*4882a593Smuzhiyun 	}
28*4882a593Smuzhiyun 
29*4882a593Smuzhiyun 	if (pin >= MAX_ROCKCHIP_GPIO_PER_BANK) {
30*4882a593Smuzhiyun 		debug("pin conf pin %d >= %d\n", pin,
31*4882a593Smuzhiyun 		      MAX_ROCKCHIP_GPIO_PER_BANK);
32*4882a593Smuzhiyun 		return -EINVAL;
33*4882a593Smuzhiyun 	}
34*4882a593Smuzhiyun 
35*4882a593Smuzhiyun 	return 0;
36*4882a593Smuzhiyun }
37*4882a593Smuzhiyun 
rockchip_get_recalced_mux(struct rockchip_pin_bank * bank,int pin,int * reg,u8 * bit,int * mask)38*4882a593Smuzhiyun void rockchip_get_recalced_mux(struct rockchip_pin_bank *bank, int pin,
39*4882a593Smuzhiyun 			       int *reg, u8 *bit, int *mask)
40*4882a593Smuzhiyun {
41*4882a593Smuzhiyun 	struct rockchip_pinctrl_priv *priv = bank->priv;
42*4882a593Smuzhiyun 	struct rockchip_pin_ctrl *ctrl = priv->ctrl;
43*4882a593Smuzhiyun 	struct rockchip_mux_recalced_data *data;
44*4882a593Smuzhiyun 	int i;
45*4882a593Smuzhiyun 
46*4882a593Smuzhiyun 	for (i = 0; i < ctrl->niomux_recalced; i++) {
47*4882a593Smuzhiyun 		data = &ctrl->iomux_recalced[i];
48*4882a593Smuzhiyun 		if (data->num == bank->bank_num &&
49*4882a593Smuzhiyun 		    data->pin == pin)
50*4882a593Smuzhiyun 			break;
51*4882a593Smuzhiyun 	}
52*4882a593Smuzhiyun 
53*4882a593Smuzhiyun 	if (i >= ctrl->niomux_recalced)
54*4882a593Smuzhiyun 		return;
55*4882a593Smuzhiyun 
56*4882a593Smuzhiyun 	*reg = data->reg;
57*4882a593Smuzhiyun 	*mask = data->mask;
58*4882a593Smuzhiyun 	*bit = data->bit;
59*4882a593Smuzhiyun }
60*4882a593Smuzhiyun 
61*4882a593Smuzhiyun static enum rockchip_pin_route_type
rockchip_get_mux_route(struct rockchip_pin_bank * bank,int pin,int mux,u32 * reg,u32 * value)62*4882a593Smuzhiyun rockchip_get_mux_route(struct rockchip_pin_bank *bank, int pin,
63*4882a593Smuzhiyun 		       int mux, u32 *reg, u32 *value)
64*4882a593Smuzhiyun {
65*4882a593Smuzhiyun 	struct rockchip_pinctrl_priv *priv = bank->priv;
66*4882a593Smuzhiyun 	struct rockchip_pin_ctrl *ctrl = priv->ctrl;
67*4882a593Smuzhiyun 	struct rockchip_mux_route_data *data;
68*4882a593Smuzhiyun 	int i;
69*4882a593Smuzhiyun 
70*4882a593Smuzhiyun 	for (i = 0; i < ctrl->niomux_routes; i++) {
71*4882a593Smuzhiyun 		data = &ctrl->iomux_routes[i];
72*4882a593Smuzhiyun 		if (data->bank_num == bank->bank_num &&
73*4882a593Smuzhiyun 		    data->pin == pin && data->func == mux)
74*4882a593Smuzhiyun 			break;
75*4882a593Smuzhiyun 	}
76*4882a593Smuzhiyun 
77*4882a593Smuzhiyun 	if (i >= ctrl->niomux_routes)
78*4882a593Smuzhiyun 		return ROUTE_TYPE_INVALID;
79*4882a593Smuzhiyun 
80*4882a593Smuzhiyun 	*reg = data->route_offset;
81*4882a593Smuzhiyun 	*value = data->route_val;
82*4882a593Smuzhiyun 
83*4882a593Smuzhiyun 	return data->route_type;
84*4882a593Smuzhiyun }
85*4882a593Smuzhiyun 
rockchip_get_mux_data(int mux_type,int pin,u8 * bit,int * mask)86*4882a593Smuzhiyun int rockchip_get_mux_data(int mux_type, int pin, u8 *bit, int *mask)
87*4882a593Smuzhiyun {
88*4882a593Smuzhiyun 	int offset = 0;
89*4882a593Smuzhiyun 
90*4882a593Smuzhiyun 	if (mux_type & IOMUX_WIDTH_4BIT) {
91*4882a593Smuzhiyun 		if ((pin % 8) >= 4)
92*4882a593Smuzhiyun 			offset = 0x4;
93*4882a593Smuzhiyun 		*bit = (pin % 4) * 4;
94*4882a593Smuzhiyun 		*mask = 0xf;
95*4882a593Smuzhiyun 	} else if (mux_type & IOMUX_WIDTH_3BIT) {
96*4882a593Smuzhiyun 		/*
97*4882a593Smuzhiyun 		 * pin0 ~ pin4 are at first register, and
98*4882a593Smuzhiyun 		 * pin5 ~ pin7 are at second register.
99*4882a593Smuzhiyun 		 */
100*4882a593Smuzhiyun 		if ((pin % 8) >= 5)
101*4882a593Smuzhiyun 			offset = 0x4;
102*4882a593Smuzhiyun 		*bit = (pin % 8 % 5) * 3;
103*4882a593Smuzhiyun 		*mask = 0x7;
104*4882a593Smuzhiyun 	} else {
105*4882a593Smuzhiyun 		*bit = (pin % 8) * 2;
106*4882a593Smuzhiyun 		*mask = 0x3;
107*4882a593Smuzhiyun 	}
108*4882a593Smuzhiyun 
109*4882a593Smuzhiyun 	return offset;
110*4882a593Smuzhiyun }
111*4882a593Smuzhiyun 
rockchip_get_mux(struct rockchip_pin_bank * bank,int pin)112*4882a593Smuzhiyun static int rockchip_get_mux(struct rockchip_pin_bank *bank, int pin)
113*4882a593Smuzhiyun {
114*4882a593Smuzhiyun 	struct rockchip_pinctrl_priv *priv = bank->priv;
115*4882a593Smuzhiyun 	int iomux_num = (pin / 8);
116*4882a593Smuzhiyun 	struct regmap *regmap;
117*4882a593Smuzhiyun 	unsigned int val;
118*4882a593Smuzhiyun 	int reg, ret, mask, mux_type;
119*4882a593Smuzhiyun 	u8 bit;
120*4882a593Smuzhiyun 
121*4882a593Smuzhiyun 	if (iomux_num > 3)
122*4882a593Smuzhiyun 		return -EINVAL;
123*4882a593Smuzhiyun 
124*4882a593Smuzhiyun 	if (bank->iomux[iomux_num].type & IOMUX_UNROUTED) {
125*4882a593Smuzhiyun 		debug("pin %d is unrouted\n", pin);
126*4882a593Smuzhiyun 		return -ENOTSUPP;
127*4882a593Smuzhiyun 	}
128*4882a593Smuzhiyun 
129*4882a593Smuzhiyun 	if (bank->iomux[iomux_num].type & IOMUX_GPIO_ONLY)
130*4882a593Smuzhiyun 		return RK_FUNC_GPIO;
131*4882a593Smuzhiyun 
132*4882a593Smuzhiyun 	regmap = (bank->iomux[iomux_num].type & IOMUX_SOURCE_PMU)
133*4882a593Smuzhiyun 				? priv->regmap_pmu : priv->regmap_base;
134*4882a593Smuzhiyun 
135*4882a593Smuzhiyun 	/* get basic quadrupel of mux registers and the correct reg inside */
136*4882a593Smuzhiyun 	mux_type = bank->iomux[iomux_num].type;
137*4882a593Smuzhiyun 	reg = bank->iomux[iomux_num].offset;
138*4882a593Smuzhiyun 	reg += rockchip_get_mux_data(mux_type, pin, &bit, &mask);
139*4882a593Smuzhiyun 
140*4882a593Smuzhiyun 	if (bank->recalced_mask & BIT(pin))
141*4882a593Smuzhiyun 		rockchip_get_recalced_mux(bank, pin, &reg, &bit, &mask);
142*4882a593Smuzhiyun 
143*4882a593Smuzhiyun 	ret = regmap_read(regmap, reg, &val);
144*4882a593Smuzhiyun 	if (ret)
145*4882a593Smuzhiyun 		return ret;
146*4882a593Smuzhiyun 
147*4882a593Smuzhiyun 	return ((val >> bit) & mask);
148*4882a593Smuzhiyun }
149*4882a593Smuzhiyun 
rockchip_pinctrl_get_gpio_mux(struct udevice * dev,int banknum,int index)150*4882a593Smuzhiyun static int rockchip_pinctrl_get_gpio_mux(struct udevice *dev, int banknum,
151*4882a593Smuzhiyun 					 int index)
152*4882a593Smuzhiyun {	struct rockchip_pinctrl_priv *priv = dev_get_priv(dev);
153*4882a593Smuzhiyun 	struct rockchip_pin_ctrl *ctrl = priv->ctrl;
154*4882a593Smuzhiyun 
155*4882a593Smuzhiyun 	return rockchip_get_mux(&ctrl->pin_banks[banknum], index);
156*4882a593Smuzhiyun }
157*4882a593Smuzhiyun 
rockchip_verify_mux(struct rockchip_pin_bank * bank,int pin,int mux)158*4882a593Smuzhiyun static int rockchip_verify_mux(struct rockchip_pin_bank *bank,
159*4882a593Smuzhiyun 			       int pin, int mux)
160*4882a593Smuzhiyun {
161*4882a593Smuzhiyun 	int iomux_num = (pin / 8);
162*4882a593Smuzhiyun 
163*4882a593Smuzhiyun 	if (iomux_num > 3)
164*4882a593Smuzhiyun 		return -EINVAL;
165*4882a593Smuzhiyun 
166*4882a593Smuzhiyun 	if (bank->iomux[iomux_num].type & IOMUX_UNROUTED) {
167*4882a593Smuzhiyun 		debug("pin %d is unrouted\n", pin);
168*4882a593Smuzhiyun 		return -ENOTSUPP;
169*4882a593Smuzhiyun 	}
170*4882a593Smuzhiyun 
171*4882a593Smuzhiyun 	if (bank->iomux[iomux_num].type & IOMUX_GPIO_ONLY) {
172*4882a593Smuzhiyun 		if (mux != IOMUX_GPIO_ONLY) {
173*4882a593Smuzhiyun 			debug("pin %d only supports a gpio mux\n", pin);
174*4882a593Smuzhiyun 			return -ENOTSUPP;
175*4882a593Smuzhiyun 		}
176*4882a593Smuzhiyun 	}
177*4882a593Smuzhiyun 
178*4882a593Smuzhiyun 	return 0;
179*4882a593Smuzhiyun }
180*4882a593Smuzhiyun 
181*4882a593Smuzhiyun /*
182*4882a593Smuzhiyun  * Set a new mux function for a pin.
183*4882a593Smuzhiyun  *
184*4882a593Smuzhiyun  * The register is divided into the upper and lower 16 bit. When changing
185*4882a593Smuzhiyun  * a value, the previous register value is not read and changed. Instead
186*4882a593Smuzhiyun  * it seems the changed bits are marked in the upper 16 bit, while the
187*4882a593Smuzhiyun  * changed value gets set in the same offset in the lower 16 bit.
188*4882a593Smuzhiyun  * All pin settings seem to be 2 bit wide in both the upper and lower
189*4882a593Smuzhiyun  * parts.
190*4882a593Smuzhiyun  * @bank: pin bank to change
191*4882a593Smuzhiyun  * @pin: pin to change
192*4882a593Smuzhiyun  * @mux: new mux function to set
193*4882a593Smuzhiyun  */
rockchip_set_mux(struct rockchip_pin_bank * bank,int pin,int mux)194*4882a593Smuzhiyun static int rockchip_set_mux(struct rockchip_pin_bank *bank, int pin, int mux)
195*4882a593Smuzhiyun {
196*4882a593Smuzhiyun 	struct rockchip_pinctrl_priv *priv = bank->priv;
197*4882a593Smuzhiyun 	struct rockchip_pin_ctrl *ctrl = priv->ctrl;
198*4882a593Smuzhiyun 	int iomux_num = (pin / 8);
199*4882a593Smuzhiyun 	int ret;
200*4882a593Smuzhiyun 
201*4882a593Smuzhiyun 	ret = rockchip_verify_mux(bank, pin, mux);
202*4882a593Smuzhiyun 	if (ret < 0)
203*4882a593Smuzhiyun 		return ret == -ENOTSUPP ? 0 : ret;
204*4882a593Smuzhiyun 
205*4882a593Smuzhiyun 	if (bank->iomux[iomux_num].type & IOMUX_GPIO_ONLY)
206*4882a593Smuzhiyun 		return 0;
207*4882a593Smuzhiyun 
208*4882a593Smuzhiyun 	debug("setting mux of GPIO%d-%d to %d\n", bank->bank_num, pin, mux);
209*4882a593Smuzhiyun 
210*4882a593Smuzhiyun 	if (!ctrl->set_mux)
211*4882a593Smuzhiyun 		return -ENOTSUPP;
212*4882a593Smuzhiyun 
213*4882a593Smuzhiyun 	ret = ctrl->set_mux(bank, pin, mux);
214*4882a593Smuzhiyun 	if (ret)
215*4882a593Smuzhiyun 		return ret;
216*4882a593Smuzhiyun 
217*4882a593Smuzhiyun 	if (bank->route_mask & BIT(pin)) {
218*4882a593Smuzhiyun 		struct regmap *regmap;
219*4882a593Smuzhiyun 		u32 route_reg = 0, route_val = 0;
220*4882a593Smuzhiyun 
221*4882a593Smuzhiyun 		ret = rockchip_get_mux_route(bank, pin, mux,
222*4882a593Smuzhiyun 					     &route_reg, &route_val);
223*4882a593Smuzhiyun 		switch (ret) {
224*4882a593Smuzhiyun 		case ROUTE_TYPE_DEFAULT:
225*4882a593Smuzhiyun 			if (bank->iomux[iomux_num].type & IOMUX_SOURCE_PMU)
226*4882a593Smuzhiyun 				regmap = priv->regmap_pmu;
227*4882a593Smuzhiyun 			else if (bank->iomux[iomux_num].type & IOMUX_L_SOURCE_PMU)
228*4882a593Smuzhiyun 				regmap = (pin % 8 < 4) ? priv->regmap_pmu : priv->regmap_base;
229*4882a593Smuzhiyun 			else
230*4882a593Smuzhiyun 				regmap = priv->regmap_base;
231*4882a593Smuzhiyun 
232*4882a593Smuzhiyun 			regmap_write(regmap, route_reg, route_val);
233*4882a593Smuzhiyun 			break;
234*4882a593Smuzhiyun 		case ROUTE_TYPE_TOPGRF:
235*4882a593Smuzhiyun 			regmap_write(priv->regmap_base, route_reg, route_val);
236*4882a593Smuzhiyun 			break;
237*4882a593Smuzhiyun 		case ROUTE_TYPE_PMUGRF:
238*4882a593Smuzhiyun 			regmap_write(priv->regmap_pmu, route_reg, route_val);
239*4882a593Smuzhiyun 			break;
240*4882a593Smuzhiyun 		case ROUTE_TYPE_INVALID: /* Fall through */
241*4882a593Smuzhiyun 		default:
242*4882a593Smuzhiyun 			break;
243*4882a593Smuzhiyun 		}
244*4882a593Smuzhiyun 	}
245*4882a593Smuzhiyun 
246*4882a593Smuzhiyun 	return 0;
247*4882a593Smuzhiyun }
248*4882a593Smuzhiyun 
249*4882a593Smuzhiyun static int rockchip_perpin_drv_list[DRV_TYPE_MAX][8] = {
250*4882a593Smuzhiyun 	{ 2, 4, 8, 12, -1, -1, -1, -1 },
251*4882a593Smuzhiyun 	{ 3, 6, 9, 12, -1, -1, -1, -1 },
252*4882a593Smuzhiyun 	{ 5, 10, 15, 20, -1, -1, -1, -1 },
253*4882a593Smuzhiyun 	{ 4, 6, 8, 10, 12, 14, 16, 18 },
254*4882a593Smuzhiyun 	{ 4, 7, 10, 13, 16, 19, 22, 26 }
255*4882a593Smuzhiyun };
256*4882a593Smuzhiyun 
rockchip_translate_drive_value(int type,int strength)257*4882a593Smuzhiyun int rockchip_translate_drive_value(int type, int strength)
258*4882a593Smuzhiyun {
259*4882a593Smuzhiyun 	int i, ret;
260*4882a593Smuzhiyun 
261*4882a593Smuzhiyun 	ret = -EINVAL;
262*4882a593Smuzhiyun 	for (i = 0; i < ARRAY_SIZE(rockchip_perpin_drv_list[type]); i++) {
263*4882a593Smuzhiyun 		if (rockchip_perpin_drv_list[type][i] == strength) {
264*4882a593Smuzhiyun 			ret = i;
265*4882a593Smuzhiyun 			break;
266*4882a593Smuzhiyun 		} else if (rockchip_perpin_drv_list[type][i] < 0) {
267*4882a593Smuzhiyun 			ret = rockchip_perpin_drv_list[type][i];
268*4882a593Smuzhiyun 			break;
269*4882a593Smuzhiyun 		}
270*4882a593Smuzhiyun 	}
271*4882a593Smuzhiyun 
272*4882a593Smuzhiyun 	return ret;
273*4882a593Smuzhiyun }
274*4882a593Smuzhiyun 
rockchip_set_drive_perpin(struct rockchip_pin_bank * bank,int pin_num,int strength)275*4882a593Smuzhiyun static int rockchip_set_drive_perpin(struct rockchip_pin_bank *bank,
276*4882a593Smuzhiyun 				     int pin_num, int strength)
277*4882a593Smuzhiyun {
278*4882a593Smuzhiyun 	struct rockchip_pinctrl_priv *priv = bank->priv;
279*4882a593Smuzhiyun 	struct rockchip_pin_ctrl *ctrl = priv->ctrl;
280*4882a593Smuzhiyun 
281*4882a593Smuzhiyun 	debug("setting drive of GPIO%d-%d to %d\n", bank->bank_num,
282*4882a593Smuzhiyun 	      pin_num, strength);
283*4882a593Smuzhiyun 
284*4882a593Smuzhiyun 	if (!ctrl->set_drive)
285*4882a593Smuzhiyun 		return -ENOTSUPP;
286*4882a593Smuzhiyun 
287*4882a593Smuzhiyun 	return ctrl->set_drive(bank, pin_num, strength);
288*4882a593Smuzhiyun }
289*4882a593Smuzhiyun 
290*4882a593Smuzhiyun static int rockchip_pull_list[PULL_TYPE_MAX][4] = {
291*4882a593Smuzhiyun 	{
292*4882a593Smuzhiyun 		PIN_CONFIG_BIAS_DISABLE,
293*4882a593Smuzhiyun 		PIN_CONFIG_BIAS_PULL_UP,
294*4882a593Smuzhiyun 		PIN_CONFIG_BIAS_PULL_DOWN,
295*4882a593Smuzhiyun 		PIN_CONFIG_BIAS_BUS_HOLD
296*4882a593Smuzhiyun 	},
297*4882a593Smuzhiyun 	{
298*4882a593Smuzhiyun 		PIN_CONFIG_BIAS_DISABLE,
299*4882a593Smuzhiyun 		PIN_CONFIG_BIAS_PULL_DOWN,
300*4882a593Smuzhiyun 		PIN_CONFIG_BIAS_DISABLE,
301*4882a593Smuzhiyun 		PIN_CONFIG_BIAS_PULL_UP
302*4882a593Smuzhiyun 	},
303*4882a593Smuzhiyun };
304*4882a593Smuzhiyun 
rockchip_translate_pull_value(int type,int pull)305*4882a593Smuzhiyun int rockchip_translate_pull_value(int type, int pull)
306*4882a593Smuzhiyun {
307*4882a593Smuzhiyun 	int i, ret;
308*4882a593Smuzhiyun 
309*4882a593Smuzhiyun 	ret = -EINVAL;
310*4882a593Smuzhiyun 	for (i = 0; i < ARRAY_SIZE(rockchip_pull_list[type]);
311*4882a593Smuzhiyun 		i++) {
312*4882a593Smuzhiyun 		if (rockchip_pull_list[type][i] == pull) {
313*4882a593Smuzhiyun 			ret = i;
314*4882a593Smuzhiyun 			break;
315*4882a593Smuzhiyun 		}
316*4882a593Smuzhiyun 	}
317*4882a593Smuzhiyun 
318*4882a593Smuzhiyun 	return ret;
319*4882a593Smuzhiyun }
320*4882a593Smuzhiyun 
rockchip_set_pull(struct rockchip_pin_bank * bank,int pin_num,int pull)321*4882a593Smuzhiyun static int rockchip_set_pull(struct rockchip_pin_bank *bank,
322*4882a593Smuzhiyun 			     int pin_num, int pull)
323*4882a593Smuzhiyun {
324*4882a593Smuzhiyun 	struct rockchip_pinctrl_priv *priv = bank->priv;
325*4882a593Smuzhiyun 	struct rockchip_pin_ctrl *ctrl = priv->ctrl;
326*4882a593Smuzhiyun 
327*4882a593Smuzhiyun 	debug("setting pull of GPIO%d-%d to %d\n", bank->bank_num,
328*4882a593Smuzhiyun 	      pin_num, pull);
329*4882a593Smuzhiyun 
330*4882a593Smuzhiyun 	if (!ctrl->set_pull)
331*4882a593Smuzhiyun 		return -ENOTSUPP;
332*4882a593Smuzhiyun 
333*4882a593Smuzhiyun 	return ctrl->set_pull(bank, pin_num, pull);
334*4882a593Smuzhiyun }
335*4882a593Smuzhiyun 
rockchip_set_schmitt(struct rockchip_pin_bank * bank,int pin_num,int enable)336*4882a593Smuzhiyun static int rockchip_set_schmitt(struct rockchip_pin_bank *bank,
337*4882a593Smuzhiyun 				int pin_num, int enable)
338*4882a593Smuzhiyun {
339*4882a593Smuzhiyun 	struct rockchip_pinctrl_priv *priv = bank->priv;
340*4882a593Smuzhiyun 	struct rockchip_pin_ctrl *ctrl = priv->ctrl;
341*4882a593Smuzhiyun 
342*4882a593Smuzhiyun 	debug("setting input schmitt of GPIO%d-%d to %d\n", bank->bank_num,
343*4882a593Smuzhiyun 	      pin_num, enable);
344*4882a593Smuzhiyun 
345*4882a593Smuzhiyun 	if (!ctrl->set_schmitt)
346*4882a593Smuzhiyun 		return -ENOTSUPP;
347*4882a593Smuzhiyun 
348*4882a593Smuzhiyun 	return ctrl->set_schmitt(bank, pin_num, enable);
349*4882a593Smuzhiyun }
350*4882a593Smuzhiyun 
351*4882a593Smuzhiyun /* set the pin config settings for a specified pin */
rockchip_pinconf_set(struct rockchip_pin_bank * bank,u32 pin,u32 param,u32 arg)352*4882a593Smuzhiyun static int rockchip_pinconf_set(struct rockchip_pin_bank *bank,
353*4882a593Smuzhiyun 				u32 pin, u32 param, u32 arg)
354*4882a593Smuzhiyun {
355*4882a593Smuzhiyun 	int rc;
356*4882a593Smuzhiyun 
357*4882a593Smuzhiyun 	switch (param) {
358*4882a593Smuzhiyun 	case PIN_CONFIG_BIAS_DISABLE:
359*4882a593Smuzhiyun 	case PIN_CONFIG_BIAS_PULL_UP:
360*4882a593Smuzhiyun 	case PIN_CONFIG_BIAS_PULL_DOWN:
361*4882a593Smuzhiyun 	case PIN_CONFIG_BIAS_PULL_PIN_DEFAULT:
362*4882a593Smuzhiyun 	case PIN_CONFIG_BIAS_BUS_HOLD:
363*4882a593Smuzhiyun 		rc = rockchip_set_pull(bank, pin, param);
364*4882a593Smuzhiyun 		if (rc)
365*4882a593Smuzhiyun 			return rc;
366*4882a593Smuzhiyun 		break;
367*4882a593Smuzhiyun 
368*4882a593Smuzhiyun 	case PIN_CONFIG_DRIVE_STRENGTH:
369*4882a593Smuzhiyun 		rc = rockchip_set_drive_perpin(bank, pin, arg);
370*4882a593Smuzhiyun 		if (rc < 0)
371*4882a593Smuzhiyun 			return rc;
372*4882a593Smuzhiyun 		break;
373*4882a593Smuzhiyun 
374*4882a593Smuzhiyun 	case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
375*4882a593Smuzhiyun 		rc = rockchip_set_schmitt(bank, pin, arg);
376*4882a593Smuzhiyun 		if (rc < 0)
377*4882a593Smuzhiyun 			return rc;
378*4882a593Smuzhiyun 		break;
379*4882a593Smuzhiyun 
380*4882a593Smuzhiyun 	default:
381*4882a593Smuzhiyun 		break;
382*4882a593Smuzhiyun 	}
383*4882a593Smuzhiyun 
384*4882a593Smuzhiyun 	return 0;
385*4882a593Smuzhiyun }
386*4882a593Smuzhiyun 
387*4882a593Smuzhiyun static const struct pinconf_param rockchip_conf_params[] = {
388*4882a593Smuzhiyun 	{ "bias-disable", PIN_CONFIG_BIAS_DISABLE, 0 },
389*4882a593Smuzhiyun 	{ "bias-bus-hold", PIN_CONFIG_BIAS_BUS_HOLD, 0 },
390*4882a593Smuzhiyun 	{ "bias-pull-up", PIN_CONFIG_BIAS_PULL_UP, 1 },
391*4882a593Smuzhiyun 	{ "bias-pull-down", PIN_CONFIG_BIAS_PULL_DOWN, 1 },
392*4882a593Smuzhiyun 	{ "bias-pull-pin-default", PIN_CONFIG_BIAS_PULL_PIN_DEFAULT, 1 },
393*4882a593Smuzhiyun 	{ "drive-strength", PIN_CONFIG_DRIVE_STRENGTH, 0 },
394*4882a593Smuzhiyun 	{ "input-schmitt-disable", PIN_CONFIG_INPUT_SCHMITT_ENABLE, 0 },
395*4882a593Smuzhiyun 	{ "input-schmitt-enable", PIN_CONFIG_INPUT_SCHMITT_ENABLE, 1 },
396*4882a593Smuzhiyun };
397*4882a593Smuzhiyun 
rockchip_pinconf_prop_name_to_param(const char * property,u32 * default_value)398*4882a593Smuzhiyun static int rockchip_pinconf_prop_name_to_param(const char *property,
399*4882a593Smuzhiyun 					       u32 *default_value)
400*4882a593Smuzhiyun {
401*4882a593Smuzhiyun 	const struct pinconf_param *p, *end;
402*4882a593Smuzhiyun 
403*4882a593Smuzhiyun 	p = rockchip_conf_params;
404*4882a593Smuzhiyun 	end = p + sizeof(rockchip_conf_params) / sizeof(struct pinconf_param);
405*4882a593Smuzhiyun 
406*4882a593Smuzhiyun 	/* See if this pctldev supports this parameter */
407*4882a593Smuzhiyun 	for (; p < end; p++) {
408*4882a593Smuzhiyun 		if (!strcmp(property, p->property)) {
409*4882a593Smuzhiyun 			*default_value = p->default_value;
410*4882a593Smuzhiyun 			return p->param;
411*4882a593Smuzhiyun 		}
412*4882a593Smuzhiyun 	}
413*4882a593Smuzhiyun 
414*4882a593Smuzhiyun 	*default_value = 0;
415*4882a593Smuzhiyun 	return -EPERM;
416*4882a593Smuzhiyun }
417*4882a593Smuzhiyun 
rockchip_pinctrl_set_state(struct udevice * dev,struct udevice * config)418*4882a593Smuzhiyun static int rockchip_pinctrl_set_state(struct udevice *dev,
419*4882a593Smuzhiyun 				      struct udevice *config)
420*4882a593Smuzhiyun {
421*4882a593Smuzhiyun 	struct rockchip_pinctrl_priv *priv = dev_get_priv(dev);
422*4882a593Smuzhiyun 	struct rockchip_pin_ctrl *ctrl = priv->ctrl;
423*4882a593Smuzhiyun 	u32 cells[MAX_ROCKCHIP_PINS_ENTRIES * 4];
424*4882a593Smuzhiyun 	u32 bank, pin, mux, conf, arg, default_val;
425*4882a593Smuzhiyun 	int ret, count, i;
426*4882a593Smuzhiyun 	const char *prop_name;
427*4882a593Smuzhiyun 	const void *value;
428*4882a593Smuzhiyun 	int prop_len, param;
429*4882a593Smuzhiyun 	const u32 *data;
430*4882a593Smuzhiyun 	ofnode node;
431*4882a593Smuzhiyun #if CONFIG_IS_ENABLED(OF_LIVE)
432*4882a593Smuzhiyun 	const struct device_node *np;
433*4882a593Smuzhiyun 	struct property *pp;
434*4882a593Smuzhiyun #else
435*4882a593Smuzhiyun 	int property_offset, pcfg_node;
436*4882a593Smuzhiyun 	const void *blob = gd->fdt_blob;
437*4882a593Smuzhiyun #endif
438*4882a593Smuzhiyun 	data = dev_read_prop(config, "rockchip,pins", &count);
439*4882a593Smuzhiyun 	if (count < 0) {
440*4882a593Smuzhiyun 		debug("%s: bad array size %d\n", __func__, count);
441*4882a593Smuzhiyun 		return -EINVAL;
442*4882a593Smuzhiyun 	}
443*4882a593Smuzhiyun 
444*4882a593Smuzhiyun 	count /= sizeof(u32);
445*4882a593Smuzhiyun 	if (count > MAX_ROCKCHIP_PINS_ENTRIES * 4) {
446*4882a593Smuzhiyun 		debug("%s: unsupported pins array count %d\n",
447*4882a593Smuzhiyun 		      __func__, count);
448*4882a593Smuzhiyun 		return -EINVAL;
449*4882a593Smuzhiyun 	}
450*4882a593Smuzhiyun 
451*4882a593Smuzhiyun 	for (i = 0; i < count; i++)
452*4882a593Smuzhiyun 		cells[i] = fdt32_to_cpu(data[i]);
453*4882a593Smuzhiyun 
454*4882a593Smuzhiyun 	for (i = 0; i < (count >> 2); i++) {
455*4882a593Smuzhiyun 		bank = cells[4 * i + 0];
456*4882a593Smuzhiyun 		pin = cells[4 * i + 1];
457*4882a593Smuzhiyun 		mux = cells[4 * i + 2];
458*4882a593Smuzhiyun 		conf = cells[4 * i + 3];
459*4882a593Smuzhiyun 
460*4882a593Smuzhiyun 		ret = rockchip_verify_config(dev, bank, pin);
461*4882a593Smuzhiyun 		if (ret)
462*4882a593Smuzhiyun 			return ret;
463*4882a593Smuzhiyun 
464*4882a593Smuzhiyun 		ret = rockchip_set_mux(&ctrl->pin_banks[bank], pin, mux);
465*4882a593Smuzhiyun 		if (ret)
466*4882a593Smuzhiyun 			return ret;
467*4882a593Smuzhiyun 
468*4882a593Smuzhiyun 		node = ofnode_get_by_phandle(conf);
469*4882a593Smuzhiyun 		if (!ofnode_valid(node))
470*4882a593Smuzhiyun 			return -ENODEV;
471*4882a593Smuzhiyun #if CONFIG_IS_ENABLED(OF_LIVE)
472*4882a593Smuzhiyun 		np = ofnode_to_np(node);
473*4882a593Smuzhiyun 		for (pp = np->properties; pp; pp = pp->next) {
474*4882a593Smuzhiyun 			prop_name = pp->name;
475*4882a593Smuzhiyun 			prop_len = pp->length;
476*4882a593Smuzhiyun 			value = pp->value;
477*4882a593Smuzhiyun #else
478*4882a593Smuzhiyun 		pcfg_node = ofnode_to_offset(node);
479*4882a593Smuzhiyun 		fdt_for_each_property_offset(property_offset, blob, pcfg_node) {
480*4882a593Smuzhiyun 			value = fdt_getprop_by_offset(blob, property_offset,
481*4882a593Smuzhiyun 						      &prop_name, &prop_len);
482*4882a593Smuzhiyun 			if (!value)
483*4882a593Smuzhiyun 				return -ENOENT;
484*4882a593Smuzhiyun #endif
485*4882a593Smuzhiyun 			param = rockchip_pinconf_prop_name_to_param(prop_name,
486*4882a593Smuzhiyun 								    &default_val);
487*4882a593Smuzhiyun 			if (param < 0)
488*4882a593Smuzhiyun 				break;
489*4882a593Smuzhiyun 
490*4882a593Smuzhiyun 			if (prop_len >= sizeof(fdt32_t))
491*4882a593Smuzhiyun 				arg = fdt32_to_cpu(*(fdt32_t *)value);
492*4882a593Smuzhiyun 			else
493*4882a593Smuzhiyun 				arg = default_val;
494*4882a593Smuzhiyun 
495*4882a593Smuzhiyun 			ret = rockchip_pinconf_set(&ctrl->pin_banks[bank], pin,
496*4882a593Smuzhiyun 						   param, arg);
497*4882a593Smuzhiyun 			if (ret) {
498*4882a593Smuzhiyun 				debug("%s: rockchip_pinconf_set fail: %d\n",
499*4882a593Smuzhiyun 				      __func__, ret);
500*4882a593Smuzhiyun 				return ret;
501*4882a593Smuzhiyun 			}
502*4882a593Smuzhiyun 		}
503*4882a593Smuzhiyun 	}
504*4882a593Smuzhiyun 
505*4882a593Smuzhiyun 	return 0;
506*4882a593Smuzhiyun }
507*4882a593Smuzhiyun 
508*4882a593Smuzhiyun static int rockchip_pinctrl_get_pins_count(struct udevice *dev)
509*4882a593Smuzhiyun {
510*4882a593Smuzhiyun 	struct rockchip_pinctrl_priv *priv = dev_get_priv(dev);
511*4882a593Smuzhiyun 	struct rockchip_pin_ctrl *ctrl = priv->ctrl;
512*4882a593Smuzhiyun 
513*4882a593Smuzhiyun 	return ctrl->nr_pins;
514*4882a593Smuzhiyun }
515*4882a593Smuzhiyun 
516*4882a593Smuzhiyun const struct pinctrl_ops rockchip_pinctrl_ops = {
517*4882a593Smuzhiyun 	.get_pins_count			= rockchip_pinctrl_get_pins_count,
518*4882a593Smuzhiyun 	.set_state			= rockchip_pinctrl_set_state,
519*4882a593Smuzhiyun 	.get_gpio_mux			= rockchip_pinctrl_get_gpio_mux,
520*4882a593Smuzhiyun };
521*4882a593Smuzhiyun 
522*4882a593Smuzhiyun /* retrieve the soc specific data */
523*4882a593Smuzhiyun static struct rockchip_pin_ctrl *rockchip_pinctrl_get_soc_data(struct udevice *dev)
524*4882a593Smuzhiyun {
525*4882a593Smuzhiyun 	struct rockchip_pinctrl_priv *priv = dev_get_priv(dev);
526*4882a593Smuzhiyun 	struct rockchip_pin_ctrl *ctrl =
527*4882a593Smuzhiyun 			(struct rockchip_pin_ctrl *)dev_get_driver_data(dev);
528*4882a593Smuzhiyun 	struct rockchip_pin_bank *bank;
529*4882a593Smuzhiyun 	int grf_offs, pmu_offs, drv_grf_offs, drv_pmu_offs, i, j;
530*4882a593Smuzhiyun 	u32 nr_pins;
531*4882a593Smuzhiyun 
532*4882a593Smuzhiyun 	grf_offs = ctrl->grf_mux_offset;
533*4882a593Smuzhiyun 	pmu_offs = ctrl->pmu_mux_offset;
534*4882a593Smuzhiyun 	drv_pmu_offs = ctrl->pmu_drv_offset;
535*4882a593Smuzhiyun 	drv_grf_offs = ctrl->grf_drv_offset;
536*4882a593Smuzhiyun 	bank = ctrl->pin_banks;
537*4882a593Smuzhiyun 
538*4882a593Smuzhiyun 	nr_pins = 0;
539*4882a593Smuzhiyun 	for (i = 0; i < ctrl->nr_banks; ++i, ++bank) {
540*4882a593Smuzhiyun 		int bank_pins = 0;
541*4882a593Smuzhiyun 
542*4882a593Smuzhiyun 		bank->priv = priv;
543*4882a593Smuzhiyun 		bank->pin_base = nr_pins;
544*4882a593Smuzhiyun 		nr_pins += bank->nr_pins;
545*4882a593Smuzhiyun 
546*4882a593Smuzhiyun 		/* calculate iomux and drv offsets */
547*4882a593Smuzhiyun 		for (j = 0; j < 4; j++) {
548*4882a593Smuzhiyun 			struct rockchip_iomux *iom = &bank->iomux[j];
549*4882a593Smuzhiyun 			struct rockchip_drv *drv = &bank->drv[j];
550*4882a593Smuzhiyun 			int inc;
551*4882a593Smuzhiyun 
552*4882a593Smuzhiyun 			if (bank_pins >= nr_pins)
553*4882a593Smuzhiyun 				break;
554*4882a593Smuzhiyun 
555*4882a593Smuzhiyun 			/* preset iomux offset value, set new start value */
556*4882a593Smuzhiyun 			if (iom->offset >= 0) {
557*4882a593Smuzhiyun 				if ((iom->type & IOMUX_SOURCE_PMU) || (iom->type & IOMUX_L_SOURCE_PMU))
558*4882a593Smuzhiyun 					pmu_offs = iom->offset;
559*4882a593Smuzhiyun 				else
560*4882a593Smuzhiyun 					grf_offs = iom->offset;
561*4882a593Smuzhiyun 			} else { /* set current iomux offset */
562*4882a593Smuzhiyun 				iom->offset = ((iom->type & IOMUX_SOURCE_PMU) ||
563*4882a593Smuzhiyun 						(iom->type & IOMUX_L_SOURCE_PMU)) ?
564*4882a593Smuzhiyun 						pmu_offs : grf_offs;
565*4882a593Smuzhiyun 			}
566*4882a593Smuzhiyun 
567*4882a593Smuzhiyun 			/* preset drv offset value, set new start value */
568*4882a593Smuzhiyun 			if (drv->offset >= 0) {
569*4882a593Smuzhiyun 				if (iom->type & IOMUX_SOURCE_PMU)
570*4882a593Smuzhiyun 					drv_pmu_offs = drv->offset;
571*4882a593Smuzhiyun 				else
572*4882a593Smuzhiyun 					drv_grf_offs = drv->offset;
573*4882a593Smuzhiyun 			} else { /* set current drv offset */
574*4882a593Smuzhiyun 				drv->offset = (iom->type & IOMUX_SOURCE_PMU) ?
575*4882a593Smuzhiyun 						drv_pmu_offs : drv_grf_offs;
576*4882a593Smuzhiyun 			}
577*4882a593Smuzhiyun 
578*4882a593Smuzhiyun 			debug("bank %d, iomux %d has iom_offset 0x%x drv_offset 0x%x\n",
579*4882a593Smuzhiyun 			      i, j, iom->offset, drv->offset);
580*4882a593Smuzhiyun 
581*4882a593Smuzhiyun 			/*
582*4882a593Smuzhiyun 			 * Increase offset according to iomux width.
583*4882a593Smuzhiyun 			 * 4bit iomux'es are spread over two registers.
584*4882a593Smuzhiyun 			 */
585*4882a593Smuzhiyun 			inc = (iom->type & (IOMUX_WIDTH_4BIT |
586*4882a593Smuzhiyun 					    IOMUX_WIDTH_3BIT |
587*4882a593Smuzhiyun 					    IOMUX_8WIDTH_2BIT)) ? 8 : 4;
588*4882a593Smuzhiyun 			if ((iom->type & IOMUX_SOURCE_PMU) || (iom->type & IOMUX_L_SOURCE_PMU))
589*4882a593Smuzhiyun 				pmu_offs += inc;
590*4882a593Smuzhiyun 			else
591*4882a593Smuzhiyun 				grf_offs += inc;
592*4882a593Smuzhiyun 
593*4882a593Smuzhiyun 			/*
594*4882a593Smuzhiyun 			 * Increase offset according to drv width.
595*4882a593Smuzhiyun 			 * 3bit drive-strenth'es are spread over two registers.
596*4882a593Smuzhiyun 			 */
597*4882a593Smuzhiyun 			if ((drv->drv_type == DRV_TYPE_IO_1V8_3V0_AUTO) ||
598*4882a593Smuzhiyun 			    (drv->drv_type == DRV_TYPE_IO_3V3_ONLY))
599*4882a593Smuzhiyun 				inc = 8;
600*4882a593Smuzhiyun 			else
601*4882a593Smuzhiyun 				inc = 4;
602*4882a593Smuzhiyun 
603*4882a593Smuzhiyun 			if (iom->type & IOMUX_SOURCE_PMU)
604*4882a593Smuzhiyun 				drv_pmu_offs += inc;
605*4882a593Smuzhiyun 			else
606*4882a593Smuzhiyun 				drv_grf_offs += inc;
607*4882a593Smuzhiyun 
608*4882a593Smuzhiyun 			bank_pins += 8;
609*4882a593Smuzhiyun 		}
610*4882a593Smuzhiyun 
611*4882a593Smuzhiyun 		/* calculate the per-bank recalced_mask */
612*4882a593Smuzhiyun 		for (j = 0; j < ctrl->niomux_recalced; j++) {
613*4882a593Smuzhiyun 			int pin = 0;
614*4882a593Smuzhiyun 
615*4882a593Smuzhiyun 			if (ctrl->iomux_recalced[j].num == bank->bank_num) {
616*4882a593Smuzhiyun 				pin = ctrl->iomux_recalced[j].pin;
617*4882a593Smuzhiyun 				bank->recalced_mask |= BIT(pin);
618*4882a593Smuzhiyun 			}
619*4882a593Smuzhiyun 		}
620*4882a593Smuzhiyun 
621*4882a593Smuzhiyun 		/* calculate the per-bank route_mask */
622*4882a593Smuzhiyun 		for (j = 0; j < ctrl->niomux_routes; j++) {
623*4882a593Smuzhiyun 			int pin = 0;
624*4882a593Smuzhiyun 
625*4882a593Smuzhiyun 			if (ctrl->iomux_routes[j].bank_num == bank->bank_num) {
626*4882a593Smuzhiyun 				pin = ctrl->iomux_routes[j].pin;
627*4882a593Smuzhiyun 				bank->route_mask |= BIT(pin);
628*4882a593Smuzhiyun 			}
629*4882a593Smuzhiyun 		}
630*4882a593Smuzhiyun 	}
631*4882a593Smuzhiyun 
632*4882a593Smuzhiyun 	WARN_ON(nr_pins != ctrl->nr_pins);
633*4882a593Smuzhiyun 
634*4882a593Smuzhiyun 	return ctrl;
635*4882a593Smuzhiyun }
636*4882a593Smuzhiyun 
637*4882a593Smuzhiyun int rockchip_pinctrl_probe(struct udevice *dev)
638*4882a593Smuzhiyun {
639*4882a593Smuzhiyun 	struct rockchip_pinctrl_priv *priv = dev_get_priv(dev);
640*4882a593Smuzhiyun 	struct rockchip_pin_ctrl *ctrl;
641*4882a593Smuzhiyun 	struct udevice *syscon;
642*4882a593Smuzhiyun 	struct regmap *regmap;
643*4882a593Smuzhiyun 	int ret = 0;
644*4882a593Smuzhiyun 
645*4882a593Smuzhiyun 	/* get rockchip grf syscon phandle */
646*4882a593Smuzhiyun 	ret = uclass_get_device_by_phandle(UCLASS_SYSCON, dev, "rockchip,grf",
647*4882a593Smuzhiyun 					   &syscon);
648*4882a593Smuzhiyun 	if (ret) {
649*4882a593Smuzhiyun 		debug("unable to find rockchip,grf syscon device (%d)\n", ret);
650*4882a593Smuzhiyun 		return ret;
651*4882a593Smuzhiyun 	}
652*4882a593Smuzhiyun 
653*4882a593Smuzhiyun 	/* get grf-reg base address */
654*4882a593Smuzhiyun 	regmap = syscon_get_regmap(syscon);
655*4882a593Smuzhiyun 	if (!regmap) {
656*4882a593Smuzhiyun 		debug("unable to find rockchip grf regmap\n");
657*4882a593Smuzhiyun 		return -ENODEV;
658*4882a593Smuzhiyun 	}
659*4882a593Smuzhiyun 	priv->regmap_base = regmap;
660*4882a593Smuzhiyun 
661*4882a593Smuzhiyun 	/* option: get pmu-reg base address */
662*4882a593Smuzhiyun 	ret = uclass_get_device_by_phandle(UCLASS_SYSCON, dev, "rockchip,pmu",
663*4882a593Smuzhiyun 					   &syscon);
664*4882a593Smuzhiyun 	if (!ret) {
665*4882a593Smuzhiyun 		/* get pmugrf-reg base address */
666*4882a593Smuzhiyun 		regmap = syscon_get_regmap(syscon);
667*4882a593Smuzhiyun 		if (!regmap) {
668*4882a593Smuzhiyun 			debug("unable to find rockchip pmu regmap\n");
669*4882a593Smuzhiyun 			return -ENODEV;
670*4882a593Smuzhiyun 		}
671*4882a593Smuzhiyun 		priv->regmap_pmu = regmap;
672*4882a593Smuzhiyun 	}
673*4882a593Smuzhiyun 
674*4882a593Smuzhiyun 	ctrl = rockchip_pinctrl_get_soc_data(dev);
675*4882a593Smuzhiyun 	if (!ctrl) {
676*4882a593Smuzhiyun 		debug("driver data not available\n");
677*4882a593Smuzhiyun 		return -EINVAL;
678*4882a593Smuzhiyun 	}
679*4882a593Smuzhiyun 
680*4882a593Smuzhiyun 	priv->ctrl = ctrl;
681*4882a593Smuzhiyun 	return 0;
682*4882a593Smuzhiyun }
683