1*01aa9d1dSRyder Lee // SPDX-License-Identifier: GPL-2.0
2*01aa9d1dSRyder Lee /*
3*01aa9d1dSRyder Lee  * Copyright (C) 2018 MediaTek Inc.
4*01aa9d1dSRyder Lee  * Author: Ryder Lee <ryder.lee@mediatek.com>
5*01aa9d1dSRyder Lee  */
6*01aa9d1dSRyder Lee 
7*01aa9d1dSRyder Lee #include <common.h>
8*01aa9d1dSRyder Lee #include <dm.h>
9*01aa9d1dSRyder Lee #include <dm/device-internal.h>
10*01aa9d1dSRyder Lee #include <dm/lists.h>
11*01aa9d1dSRyder Lee #include <dm/pinctrl.h>
12*01aa9d1dSRyder Lee #include <asm/io.h>
13*01aa9d1dSRyder Lee #include <asm-generic/gpio.h>
14*01aa9d1dSRyder Lee 
15*01aa9d1dSRyder Lee #include "pinctrl-mtk-common.h"
16*01aa9d1dSRyder Lee 
17*01aa9d1dSRyder Lee /**
18*01aa9d1dSRyder Lee  * struct mtk_drive_desc - the structure that holds the information
19*01aa9d1dSRyder Lee  *			    of the driving current
20*01aa9d1dSRyder Lee  * @min:	the minimum current of this group
21*01aa9d1dSRyder Lee  * @max:	the maximum current of this group
22*01aa9d1dSRyder Lee  * @step:	the step current of this group
23*01aa9d1dSRyder Lee  * @scal:	the weight factor
24*01aa9d1dSRyder Lee  *
25*01aa9d1dSRyder Lee  * formula: output = ((input) / step - 1) * scal
26*01aa9d1dSRyder Lee  */
27*01aa9d1dSRyder Lee struct mtk_drive_desc {
28*01aa9d1dSRyder Lee 	u8 min;
29*01aa9d1dSRyder Lee 	u8 max;
30*01aa9d1dSRyder Lee 	u8 step;
31*01aa9d1dSRyder Lee 	u8 scal;
32*01aa9d1dSRyder Lee };
33*01aa9d1dSRyder Lee 
34*01aa9d1dSRyder Lee /* The groups of drive strength */
35*01aa9d1dSRyder Lee static const struct mtk_drive_desc mtk_drive[] = {
36*01aa9d1dSRyder Lee 	[DRV_GRP0] = { 4, 16, 4, 1 },
37*01aa9d1dSRyder Lee 	[DRV_GRP1] = { 4, 16, 4, 2 },
38*01aa9d1dSRyder Lee 	[DRV_GRP2] = { 2, 8, 2, 1 },
39*01aa9d1dSRyder Lee 	[DRV_GRP3] = { 2, 8, 2, 2 },
40*01aa9d1dSRyder Lee 	[DRV_GRP4] = { 2, 16, 2, 1 },
41*01aa9d1dSRyder Lee };
42*01aa9d1dSRyder Lee 
43*01aa9d1dSRyder Lee static const char *mtk_pinctrl_dummy_name = "_dummy";
44*01aa9d1dSRyder Lee 
mtk_w32(struct udevice * dev,u32 reg,u32 val)45*01aa9d1dSRyder Lee static void mtk_w32(struct udevice *dev, u32 reg, u32 val)
46*01aa9d1dSRyder Lee {
47*01aa9d1dSRyder Lee 	struct mtk_pinctrl_priv *priv = dev_get_priv(dev);
48*01aa9d1dSRyder Lee 
49*01aa9d1dSRyder Lee 	__raw_writel(val, priv->base + reg);
50*01aa9d1dSRyder Lee }
51*01aa9d1dSRyder Lee 
mtk_r32(struct udevice * dev,u32 reg)52*01aa9d1dSRyder Lee static u32 mtk_r32(struct udevice *dev, u32 reg)
53*01aa9d1dSRyder Lee {
54*01aa9d1dSRyder Lee 	struct mtk_pinctrl_priv *priv = dev_get_priv(dev);
55*01aa9d1dSRyder Lee 
56*01aa9d1dSRyder Lee 	return __raw_readl(priv->base + reg);
57*01aa9d1dSRyder Lee }
58*01aa9d1dSRyder Lee 
get_count_order(unsigned int count)59*01aa9d1dSRyder Lee static inline int get_count_order(unsigned int count)
60*01aa9d1dSRyder Lee {
61*01aa9d1dSRyder Lee 	int order;
62*01aa9d1dSRyder Lee 
63*01aa9d1dSRyder Lee 	order = fls(count) - 1;
64*01aa9d1dSRyder Lee 	if (count & (count - 1))
65*01aa9d1dSRyder Lee 		order++;
66*01aa9d1dSRyder Lee 	return order;
67*01aa9d1dSRyder Lee }
68*01aa9d1dSRyder Lee 
mtk_rmw(struct udevice * dev,u32 reg,u32 mask,u32 set)69*01aa9d1dSRyder Lee void mtk_rmw(struct udevice *dev, u32 reg, u32 mask, u32 set)
70*01aa9d1dSRyder Lee {
71*01aa9d1dSRyder Lee 	u32 val;
72*01aa9d1dSRyder Lee 
73*01aa9d1dSRyder Lee 	val = mtk_r32(dev, reg);
74*01aa9d1dSRyder Lee 	val &= ~mask;
75*01aa9d1dSRyder Lee 	val |= set;
76*01aa9d1dSRyder Lee 	mtk_w32(dev, reg, val);
77*01aa9d1dSRyder Lee }
78*01aa9d1dSRyder Lee 
mtk_hw_pin_field_lookup(struct udevice * dev,int pin,const struct mtk_pin_reg_calc * rc,struct mtk_pin_field * pfd)79*01aa9d1dSRyder Lee static int mtk_hw_pin_field_lookup(struct udevice *dev, int pin,
80*01aa9d1dSRyder Lee 				   const struct mtk_pin_reg_calc *rc,
81*01aa9d1dSRyder Lee 				   struct mtk_pin_field *pfd)
82*01aa9d1dSRyder Lee {
83*01aa9d1dSRyder Lee 	const struct mtk_pin_field_calc *c, *e;
84*01aa9d1dSRyder Lee 	u32 bits;
85*01aa9d1dSRyder Lee 
86*01aa9d1dSRyder Lee 	c = rc->range;
87*01aa9d1dSRyder Lee 	e = c + rc->nranges;
88*01aa9d1dSRyder Lee 
89*01aa9d1dSRyder Lee 	while (c < e) {
90*01aa9d1dSRyder Lee 		if (pin >= c->s_pin && pin <= c->e_pin)
91*01aa9d1dSRyder Lee 			break;
92*01aa9d1dSRyder Lee 		c++;
93*01aa9d1dSRyder Lee 	}
94*01aa9d1dSRyder Lee 
95*01aa9d1dSRyder Lee 	if (c >= e)
96*01aa9d1dSRyder Lee 		return -EINVAL;
97*01aa9d1dSRyder Lee 
98*01aa9d1dSRyder Lee 	/* Calculated bits as the overall offset the pin is located at,
99*01aa9d1dSRyder Lee 	 * if c->fixed is held, that determines the all the pins in the
100*01aa9d1dSRyder Lee 	 * range use the same field with the s_pin.
101*01aa9d1dSRyder Lee 	 */
102*01aa9d1dSRyder Lee 	bits = c->fixed ? c->s_bit : c->s_bit + (pin - c->s_pin) * (c->x_bits);
103*01aa9d1dSRyder Lee 
104*01aa9d1dSRyder Lee 	/* Fill pfd from bits. For example 32-bit register applied is assumed
105*01aa9d1dSRyder Lee 	 * when c->sz_reg is equal to 32.
106*01aa9d1dSRyder Lee 	 */
107*01aa9d1dSRyder Lee 	pfd->offset = c->s_addr + c->x_addrs * (bits / c->sz_reg);
108*01aa9d1dSRyder Lee 	pfd->bitpos = bits % c->sz_reg;
109*01aa9d1dSRyder Lee 	pfd->mask = (1 << c->x_bits) - 1;
110*01aa9d1dSRyder Lee 
111*01aa9d1dSRyder Lee 	/* pfd->next is used for indicating that bit wrapping-around happens
112*01aa9d1dSRyder Lee 	 * which requires the manipulation for bit 0 starting in the next
113*01aa9d1dSRyder Lee 	 * register to form the complete field read/write.
114*01aa9d1dSRyder Lee 	 */
115*01aa9d1dSRyder Lee 	pfd->next = pfd->bitpos + c->x_bits > c->sz_reg ? c->x_addrs : 0;
116*01aa9d1dSRyder Lee 
117*01aa9d1dSRyder Lee 	return 0;
118*01aa9d1dSRyder Lee }
119*01aa9d1dSRyder Lee 
mtk_hw_pin_field_get(struct udevice * dev,int pin,int field,struct mtk_pin_field * pfd)120*01aa9d1dSRyder Lee static int mtk_hw_pin_field_get(struct udevice *dev, int pin,
121*01aa9d1dSRyder Lee 				int field, struct mtk_pin_field *pfd)
122*01aa9d1dSRyder Lee {
123*01aa9d1dSRyder Lee 	struct mtk_pinctrl_priv *priv = dev_get_priv(dev);
124*01aa9d1dSRyder Lee 	const struct mtk_pin_reg_calc *rc;
125*01aa9d1dSRyder Lee 
126*01aa9d1dSRyder Lee 	if (field < 0 || field >= PINCTRL_PIN_REG_MAX)
127*01aa9d1dSRyder Lee 		return -EINVAL;
128*01aa9d1dSRyder Lee 
129*01aa9d1dSRyder Lee 	if (priv->soc->reg_cal && priv->soc->reg_cal[field].range)
130*01aa9d1dSRyder Lee 		rc = &priv->soc->reg_cal[field];
131*01aa9d1dSRyder Lee 	else
132*01aa9d1dSRyder Lee 		return -EINVAL;
133*01aa9d1dSRyder Lee 
134*01aa9d1dSRyder Lee 	return mtk_hw_pin_field_lookup(dev, pin, rc, pfd);
135*01aa9d1dSRyder Lee }
136*01aa9d1dSRyder Lee 
mtk_hw_bits_part(struct mtk_pin_field * pf,int * h,int * l)137*01aa9d1dSRyder Lee static void mtk_hw_bits_part(struct mtk_pin_field *pf, int *h, int *l)
138*01aa9d1dSRyder Lee {
139*01aa9d1dSRyder Lee 	*l = 32 - pf->bitpos;
140*01aa9d1dSRyder Lee 	*h = get_count_order(pf->mask) - *l;
141*01aa9d1dSRyder Lee }
142*01aa9d1dSRyder Lee 
mtk_hw_write_cross_field(struct udevice * dev,struct mtk_pin_field * pf,int value)143*01aa9d1dSRyder Lee static void mtk_hw_write_cross_field(struct udevice *dev,
144*01aa9d1dSRyder Lee 				     struct mtk_pin_field *pf, int value)
145*01aa9d1dSRyder Lee {
146*01aa9d1dSRyder Lee 	int nbits_l, nbits_h;
147*01aa9d1dSRyder Lee 
148*01aa9d1dSRyder Lee 	mtk_hw_bits_part(pf, &nbits_h, &nbits_l);
149*01aa9d1dSRyder Lee 
150*01aa9d1dSRyder Lee 	mtk_rmw(dev, pf->offset, pf->mask << pf->bitpos,
151*01aa9d1dSRyder Lee 		(value & pf->mask) << pf->bitpos);
152*01aa9d1dSRyder Lee 
153*01aa9d1dSRyder Lee 	mtk_rmw(dev, pf->offset + pf->next, BIT(nbits_h) - 1,
154*01aa9d1dSRyder Lee 		(value & pf->mask) >> nbits_l);
155*01aa9d1dSRyder Lee }
156*01aa9d1dSRyder Lee 
mtk_hw_read_cross_field(struct udevice * dev,struct mtk_pin_field * pf,int * value)157*01aa9d1dSRyder Lee static void mtk_hw_read_cross_field(struct udevice *dev,
158*01aa9d1dSRyder Lee 				    struct mtk_pin_field *pf, int *value)
159*01aa9d1dSRyder Lee {
160*01aa9d1dSRyder Lee 	int nbits_l, nbits_h, h, l;
161*01aa9d1dSRyder Lee 
162*01aa9d1dSRyder Lee 	mtk_hw_bits_part(pf, &nbits_h, &nbits_l);
163*01aa9d1dSRyder Lee 
164*01aa9d1dSRyder Lee 	l  = (mtk_r32(dev, pf->offset) >> pf->bitpos) & (BIT(nbits_l) - 1);
165*01aa9d1dSRyder Lee 	h  = (mtk_r32(dev, pf->offset + pf->next)) & (BIT(nbits_h) - 1);
166*01aa9d1dSRyder Lee 
167*01aa9d1dSRyder Lee 	*value = (h << nbits_l) | l;
168*01aa9d1dSRyder Lee }
169*01aa9d1dSRyder Lee 
mtk_hw_set_value(struct udevice * dev,int pin,int field,int value)170*01aa9d1dSRyder Lee static int mtk_hw_set_value(struct udevice *dev, int pin, int field,
171*01aa9d1dSRyder Lee 			    int value)
172*01aa9d1dSRyder Lee {
173*01aa9d1dSRyder Lee 	struct mtk_pin_field pf;
174*01aa9d1dSRyder Lee 	int err;
175*01aa9d1dSRyder Lee 
176*01aa9d1dSRyder Lee 	err = mtk_hw_pin_field_get(dev, pin, field, &pf);
177*01aa9d1dSRyder Lee 	if (err)
178*01aa9d1dSRyder Lee 		return err;
179*01aa9d1dSRyder Lee 
180*01aa9d1dSRyder Lee 	if (!pf.next)
181*01aa9d1dSRyder Lee 		mtk_rmw(dev, pf.offset, pf.mask << pf.bitpos,
182*01aa9d1dSRyder Lee 			(value & pf.mask) << pf.bitpos);
183*01aa9d1dSRyder Lee 	else
184*01aa9d1dSRyder Lee 		mtk_hw_write_cross_field(dev, &pf, value);
185*01aa9d1dSRyder Lee 
186*01aa9d1dSRyder Lee 	return 0;
187*01aa9d1dSRyder Lee }
188*01aa9d1dSRyder Lee 
mtk_hw_get_value(struct udevice * dev,int pin,int field,int * value)189*01aa9d1dSRyder Lee static int mtk_hw_get_value(struct udevice *dev, int pin, int field,
190*01aa9d1dSRyder Lee 			    int *value)
191*01aa9d1dSRyder Lee {
192*01aa9d1dSRyder Lee 	struct mtk_pin_field pf;
193*01aa9d1dSRyder Lee 	int err;
194*01aa9d1dSRyder Lee 
195*01aa9d1dSRyder Lee 	err = mtk_hw_pin_field_get(dev, pin, field, &pf);
196*01aa9d1dSRyder Lee 	if (err)
197*01aa9d1dSRyder Lee 		return err;
198*01aa9d1dSRyder Lee 
199*01aa9d1dSRyder Lee 	if (!pf.next)
200*01aa9d1dSRyder Lee 		*value = (mtk_r32(dev, pf.offset) >> pf.bitpos) & pf.mask;
201*01aa9d1dSRyder Lee 	else
202*01aa9d1dSRyder Lee 		mtk_hw_read_cross_field(dev, &pf, value);
203*01aa9d1dSRyder Lee 
204*01aa9d1dSRyder Lee 	return 0;
205*01aa9d1dSRyder Lee }
206*01aa9d1dSRyder Lee 
mtk_get_groups_count(struct udevice * dev)207*01aa9d1dSRyder Lee static int mtk_get_groups_count(struct udevice *dev)
208*01aa9d1dSRyder Lee {
209*01aa9d1dSRyder Lee 	struct mtk_pinctrl_priv *priv = dev_get_priv(dev);
210*01aa9d1dSRyder Lee 
211*01aa9d1dSRyder Lee 	return priv->soc->ngrps;
212*01aa9d1dSRyder Lee }
213*01aa9d1dSRyder Lee 
mtk_get_pin_name(struct udevice * dev,unsigned int selector)214*01aa9d1dSRyder Lee static const char *mtk_get_pin_name(struct udevice *dev,
215*01aa9d1dSRyder Lee 				    unsigned int selector)
216*01aa9d1dSRyder Lee {
217*01aa9d1dSRyder Lee 	struct mtk_pinctrl_priv *priv = dev_get_priv(dev);
218*01aa9d1dSRyder Lee 
219*01aa9d1dSRyder Lee 	if (!priv->soc->grps[selector].name)
220*01aa9d1dSRyder Lee 		return mtk_pinctrl_dummy_name;
221*01aa9d1dSRyder Lee 
222*01aa9d1dSRyder Lee 	return priv->soc->pins[selector].name;
223*01aa9d1dSRyder Lee }
224*01aa9d1dSRyder Lee 
mtk_get_pins_count(struct udevice * dev)225*01aa9d1dSRyder Lee static int mtk_get_pins_count(struct udevice *dev)
226*01aa9d1dSRyder Lee {
227*01aa9d1dSRyder Lee 	struct mtk_pinctrl_priv *priv = dev_get_priv(dev);
228*01aa9d1dSRyder Lee 
229*01aa9d1dSRyder Lee 	return priv->soc->npins;
230*01aa9d1dSRyder Lee }
231*01aa9d1dSRyder Lee 
mtk_get_group_name(struct udevice * dev,unsigned int selector)232*01aa9d1dSRyder Lee static const char *mtk_get_group_name(struct udevice *dev,
233*01aa9d1dSRyder Lee 				      unsigned int selector)
234*01aa9d1dSRyder Lee {
235*01aa9d1dSRyder Lee 	struct mtk_pinctrl_priv *priv = dev_get_priv(dev);
236*01aa9d1dSRyder Lee 
237*01aa9d1dSRyder Lee 	if (!priv->soc->grps[selector].name)
238*01aa9d1dSRyder Lee 		return mtk_pinctrl_dummy_name;
239*01aa9d1dSRyder Lee 
240*01aa9d1dSRyder Lee 	return priv->soc->grps[selector].name;
241*01aa9d1dSRyder Lee }
242*01aa9d1dSRyder Lee 
mtk_get_functions_count(struct udevice * dev)243*01aa9d1dSRyder Lee static int mtk_get_functions_count(struct udevice *dev)
244*01aa9d1dSRyder Lee {
245*01aa9d1dSRyder Lee 	struct mtk_pinctrl_priv *priv = dev_get_priv(dev);
246*01aa9d1dSRyder Lee 
247*01aa9d1dSRyder Lee 	return priv->soc->nfuncs;
248*01aa9d1dSRyder Lee }
249*01aa9d1dSRyder Lee 
mtk_get_function_name(struct udevice * dev,unsigned int selector)250*01aa9d1dSRyder Lee static const char *mtk_get_function_name(struct udevice *dev,
251*01aa9d1dSRyder Lee 					 unsigned int selector)
252*01aa9d1dSRyder Lee {
253*01aa9d1dSRyder Lee 	struct mtk_pinctrl_priv *priv = dev_get_priv(dev);
254*01aa9d1dSRyder Lee 
255*01aa9d1dSRyder Lee 	if (!priv->soc->funcs[selector].name)
256*01aa9d1dSRyder Lee 		return mtk_pinctrl_dummy_name;
257*01aa9d1dSRyder Lee 
258*01aa9d1dSRyder Lee 	return priv->soc->funcs[selector].name;
259*01aa9d1dSRyder Lee }
260*01aa9d1dSRyder Lee 
mtk_pinmux_group_set(struct udevice * dev,unsigned int group_selector,unsigned int func_selector)261*01aa9d1dSRyder Lee static int mtk_pinmux_group_set(struct udevice *dev,
262*01aa9d1dSRyder Lee 				unsigned int group_selector,
263*01aa9d1dSRyder Lee 				unsigned int func_selector)
264*01aa9d1dSRyder Lee {
265*01aa9d1dSRyder Lee 	struct mtk_pinctrl_priv *priv = dev_get_priv(dev);
266*01aa9d1dSRyder Lee 	const struct mtk_group_desc *grp =
267*01aa9d1dSRyder Lee 			&priv->soc->grps[group_selector];
268*01aa9d1dSRyder Lee 	int i;
269*01aa9d1dSRyder Lee 
270*01aa9d1dSRyder Lee 	for (i = 0; i < grp->num_pins; i++) {
271*01aa9d1dSRyder Lee 		int *pin_modes = grp->data;
272*01aa9d1dSRyder Lee 
273*01aa9d1dSRyder Lee 		mtk_hw_set_value(dev, grp->pins[i], PINCTRL_PIN_REG_MODE,
274*01aa9d1dSRyder Lee 				 pin_modes[i]);
275*01aa9d1dSRyder Lee 	}
276*01aa9d1dSRyder Lee 
277*01aa9d1dSRyder Lee 	return 0;
278*01aa9d1dSRyder Lee }
279*01aa9d1dSRyder Lee 
280*01aa9d1dSRyder Lee #if CONFIG_IS_ENABLED(PINCONF)
281*01aa9d1dSRyder Lee static const struct pinconf_param mtk_conf_params[] = {
282*01aa9d1dSRyder Lee 	{ "bias-disable", PIN_CONFIG_BIAS_DISABLE, 0 },
283*01aa9d1dSRyder Lee 	{ "bias-pull-up", PIN_CONFIG_BIAS_PULL_UP, 1 },
284*01aa9d1dSRyder Lee 	{ "bias-pull-down", PIN_CONFIG_BIAS_PULL_DOWN, 1 },
285*01aa9d1dSRyder Lee 	{ "input-schmitt-enable", PIN_CONFIG_INPUT_SCHMITT_ENABLE, 1 },
286*01aa9d1dSRyder Lee 	{ "input-schmitt-disable", PIN_CONFIG_INPUT_SCHMITT_ENABLE, 0 },
287*01aa9d1dSRyder Lee 	{ "input-enable", PIN_CONFIG_INPUT_ENABLE, 1 },
288*01aa9d1dSRyder Lee 	{ "input-disable", PIN_CONFIG_INPUT_ENABLE, 0 },
289*01aa9d1dSRyder Lee 	{ "output-enable", PIN_CONFIG_OUTPUT_ENABLE, 1 },
290*01aa9d1dSRyder Lee 	{ "output-high", PIN_CONFIG_OUTPUT, 1, },
291*01aa9d1dSRyder Lee 	{ "output-low", PIN_CONFIG_OUTPUT, 0, },
292*01aa9d1dSRyder Lee 	{ "drive-strength", PIN_CONFIG_DRIVE_STRENGTH, 0 },
293*01aa9d1dSRyder Lee };
294*01aa9d1dSRyder Lee 
mtk_pinconf_drive_set(struct udevice * dev,u32 pin,u32 arg)295*01aa9d1dSRyder Lee int mtk_pinconf_drive_set(struct udevice *dev, u32 pin, u32 arg)
296*01aa9d1dSRyder Lee {
297*01aa9d1dSRyder Lee 	struct mtk_pinctrl_priv *priv = dev_get_priv(dev);
298*01aa9d1dSRyder Lee 	const struct mtk_pin_desc *desc = &priv->soc->pins[pin];
299*01aa9d1dSRyder Lee 	const struct mtk_drive_desc *tb;
300*01aa9d1dSRyder Lee 	int err = -ENOTSUPP;
301*01aa9d1dSRyder Lee 
302*01aa9d1dSRyder Lee 	tb = &mtk_drive[desc->drv_n];
303*01aa9d1dSRyder Lee 	/* 4mA when (e8, e4) = (0, 0)
304*01aa9d1dSRyder Lee 	 * 8mA when (e8, e4) = (0, 1)
305*01aa9d1dSRyder Lee 	 * 12mA when (e8, e4) = (1, 0)
306*01aa9d1dSRyder Lee 	 * 16mA when (e8, e4) = (1, 1)
307*01aa9d1dSRyder Lee 	 */
308*01aa9d1dSRyder Lee 	if ((arg >= tb->min && arg <= tb->max) && !(arg % tb->step)) {
309*01aa9d1dSRyder Lee 		arg = (arg / tb->step - 1) * tb->scal;
310*01aa9d1dSRyder Lee 
311*01aa9d1dSRyder Lee 		err = mtk_hw_set_value(dev, pin, PINCTRL_PIN_REG_DRV, arg);
312*01aa9d1dSRyder Lee 		if (err)
313*01aa9d1dSRyder Lee 			return err;
314*01aa9d1dSRyder Lee 	}
315*01aa9d1dSRyder Lee 
316*01aa9d1dSRyder Lee 	return 0;
317*01aa9d1dSRyder Lee }
318*01aa9d1dSRyder Lee 
mtk_pinconf_set(struct udevice * dev,unsigned int pin,unsigned int param,unsigned int arg)319*01aa9d1dSRyder Lee static int mtk_pinconf_set(struct udevice *dev, unsigned int pin,
320*01aa9d1dSRyder Lee 			   unsigned int param, unsigned int arg)
321*01aa9d1dSRyder Lee {
322*01aa9d1dSRyder Lee 	int err = 0;
323*01aa9d1dSRyder Lee 
324*01aa9d1dSRyder Lee 	switch (param) {
325*01aa9d1dSRyder Lee 	case PIN_CONFIG_BIAS_DISABLE:
326*01aa9d1dSRyder Lee 	case PIN_CONFIG_BIAS_PULL_UP:
327*01aa9d1dSRyder Lee 	case PIN_CONFIG_BIAS_PULL_DOWN:
328*01aa9d1dSRyder Lee 		arg = (param == PIN_CONFIG_BIAS_DISABLE) ? 0 :
329*01aa9d1dSRyder Lee 			(param == PIN_CONFIG_BIAS_PULL_UP) ? 3 : 2;
330*01aa9d1dSRyder Lee 
331*01aa9d1dSRyder Lee 		err = mtk_hw_set_value(dev, pin, PINCTRL_PIN_REG_PULLSEL,
332*01aa9d1dSRyder Lee 				       arg & 1);
333*01aa9d1dSRyder Lee 		if (err)
334*01aa9d1dSRyder Lee 			goto err;
335*01aa9d1dSRyder Lee 
336*01aa9d1dSRyder Lee 		err = mtk_hw_set_value(dev, pin, PINCTRL_PIN_REG_PULLEN,
337*01aa9d1dSRyder Lee 				       !!(arg & 2));
338*01aa9d1dSRyder Lee 		if (err)
339*01aa9d1dSRyder Lee 			goto err;
340*01aa9d1dSRyder Lee 		break;
341*01aa9d1dSRyder Lee 	case PIN_CONFIG_OUTPUT_ENABLE:
342*01aa9d1dSRyder Lee 		err = mtk_hw_set_value(dev, pin, PINCTRL_PIN_REG_SMT, 0);
343*01aa9d1dSRyder Lee 		if (err)
344*01aa9d1dSRyder Lee 			goto err;
345*01aa9d1dSRyder Lee 		err = mtk_hw_set_value(dev, pin, PINCTRL_PIN_REG_DIR, 1);
346*01aa9d1dSRyder Lee 		if (err)
347*01aa9d1dSRyder Lee 			goto err;
348*01aa9d1dSRyder Lee 		break;
349*01aa9d1dSRyder Lee 	case PIN_CONFIG_INPUT_ENABLE:
350*01aa9d1dSRyder Lee 		err = mtk_hw_set_value(dev, pin, PINCTRL_PIN_REG_IES, 1);
351*01aa9d1dSRyder Lee 		if (err)
352*01aa9d1dSRyder Lee 			goto err;
353*01aa9d1dSRyder Lee 		err = mtk_hw_set_value(dev, pin, PINCTRL_PIN_REG_DIR, 0);
354*01aa9d1dSRyder Lee 		if (err)
355*01aa9d1dSRyder Lee 			goto err;
356*01aa9d1dSRyder Lee 		break;
357*01aa9d1dSRyder Lee 	case PIN_CONFIG_OUTPUT:
358*01aa9d1dSRyder Lee 		err = mtk_hw_set_value(dev, pin, PINCTRL_PIN_REG_DIR, 1);
359*01aa9d1dSRyder Lee 		if (err)
360*01aa9d1dSRyder Lee 			goto err;
361*01aa9d1dSRyder Lee 
362*01aa9d1dSRyder Lee 		err = mtk_hw_set_value(dev, pin, PINCTRL_PIN_REG_DO, arg);
363*01aa9d1dSRyder Lee 		if (err)
364*01aa9d1dSRyder Lee 			goto err;
365*01aa9d1dSRyder Lee 		break;
366*01aa9d1dSRyder Lee 	case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
367*01aa9d1dSRyder Lee 		/* arg = 1: Input mode & SMT enable ;
368*01aa9d1dSRyder Lee 		 * arg = 0: Output mode & SMT disable
369*01aa9d1dSRyder Lee 		 */
370*01aa9d1dSRyder Lee 		arg = arg ? 2 : 1;
371*01aa9d1dSRyder Lee 		err = mtk_hw_set_value(dev, pin, PINCTRL_PIN_REG_DIR,
372*01aa9d1dSRyder Lee 				       arg & 1);
373*01aa9d1dSRyder Lee 		if (err)
374*01aa9d1dSRyder Lee 			goto err;
375*01aa9d1dSRyder Lee 
376*01aa9d1dSRyder Lee 		err = mtk_hw_set_value(dev, pin, PINCTRL_PIN_REG_SMT,
377*01aa9d1dSRyder Lee 				       !!(arg & 2));
378*01aa9d1dSRyder Lee 		if (err)
379*01aa9d1dSRyder Lee 			goto err;
380*01aa9d1dSRyder Lee 		break;
381*01aa9d1dSRyder Lee 	case PIN_CONFIG_DRIVE_STRENGTH:
382*01aa9d1dSRyder Lee 		err = mtk_pinconf_drive_set(dev, pin, arg);
383*01aa9d1dSRyder Lee 		if (err)
384*01aa9d1dSRyder Lee 			goto err;
385*01aa9d1dSRyder Lee 		break;
386*01aa9d1dSRyder Lee 
387*01aa9d1dSRyder Lee 	default:
388*01aa9d1dSRyder Lee 		err = -ENOTSUPP;
389*01aa9d1dSRyder Lee 	}
390*01aa9d1dSRyder Lee 
391*01aa9d1dSRyder Lee err:
392*01aa9d1dSRyder Lee 
393*01aa9d1dSRyder Lee 	return err;
394*01aa9d1dSRyder Lee }
395*01aa9d1dSRyder Lee 
mtk_pinconf_group_set(struct udevice * dev,unsigned int group_selector,unsigned int param,unsigned int arg)396*01aa9d1dSRyder Lee static int mtk_pinconf_group_set(struct udevice *dev,
397*01aa9d1dSRyder Lee 				 unsigned int group_selector,
398*01aa9d1dSRyder Lee 				 unsigned int param, unsigned int arg)
399*01aa9d1dSRyder Lee {
400*01aa9d1dSRyder Lee 	struct mtk_pinctrl_priv *priv = dev_get_priv(dev);
401*01aa9d1dSRyder Lee 	const struct mtk_group_desc *grp =
402*01aa9d1dSRyder Lee 			&priv->soc->grps[group_selector];
403*01aa9d1dSRyder Lee 	int i, ret;
404*01aa9d1dSRyder Lee 
405*01aa9d1dSRyder Lee 	for (i = 0; i < grp->num_pins; i++) {
406*01aa9d1dSRyder Lee 		ret = mtk_pinconf_set(dev, grp->pins[i], param, arg);
407*01aa9d1dSRyder Lee 		if (ret)
408*01aa9d1dSRyder Lee 			return ret;
409*01aa9d1dSRyder Lee 	}
410*01aa9d1dSRyder Lee 
411*01aa9d1dSRyder Lee 	return 0;
412*01aa9d1dSRyder Lee }
413*01aa9d1dSRyder Lee #endif
414*01aa9d1dSRyder Lee 
415*01aa9d1dSRyder Lee const struct pinctrl_ops mtk_pinctrl_ops = {
416*01aa9d1dSRyder Lee 	.get_pins_count = mtk_get_pins_count,
417*01aa9d1dSRyder Lee 	.get_pin_name = mtk_get_pin_name,
418*01aa9d1dSRyder Lee 	.get_groups_count = mtk_get_groups_count,
419*01aa9d1dSRyder Lee 	.get_group_name = mtk_get_group_name,
420*01aa9d1dSRyder Lee 	.get_functions_count = mtk_get_functions_count,
421*01aa9d1dSRyder Lee 	.get_function_name = mtk_get_function_name,
422*01aa9d1dSRyder Lee 	.pinmux_group_set = mtk_pinmux_group_set,
423*01aa9d1dSRyder Lee #if CONFIG_IS_ENABLED(PINCONF)
424*01aa9d1dSRyder Lee 	.pinconf_num_params = ARRAY_SIZE(mtk_conf_params),
425*01aa9d1dSRyder Lee 	.pinconf_params = mtk_conf_params,
426*01aa9d1dSRyder Lee 	.pinconf_set = mtk_pinconf_set,
427*01aa9d1dSRyder Lee 	.pinconf_group_set = mtk_pinconf_group_set,
428*01aa9d1dSRyder Lee #endif
429*01aa9d1dSRyder Lee 	.set_state = pinctrl_generic_set_state,
430*01aa9d1dSRyder Lee };
431*01aa9d1dSRyder Lee 
mtk_gpio_get(struct udevice * dev,unsigned int off)432*01aa9d1dSRyder Lee static int mtk_gpio_get(struct udevice *dev, unsigned int off)
433*01aa9d1dSRyder Lee {
434*01aa9d1dSRyder Lee 	int val, err;
435*01aa9d1dSRyder Lee 
436*01aa9d1dSRyder Lee 	err = mtk_hw_get_value(dev->parent, off, PINCTRL_PIN_REG_DI, &val);
437*01aa9d1dSRyder Lee 	if (err)
438*01aa9d1dSRyder Lee 		return err;
439*01aa9d1dSRyder Lee 
440*01aa9d1dSRyder Lee 	return !!val;
441*01aa9d1dSRyder Lee }
442*01aa9d1dSRyder Lee 
mtk_gpio_set(struct udevice * dev,unsigned int off,int val)443*01aa9d1dSRyder Lee static int mtk_gpio_set(struct udevice *dev, unsigned int off, int val)
444*01aa9d1dSRyder Lee {
445*01aa9d1dSRyder Lee 	return mtk_hw_set_value(dev->parent, off, PINCTRL_PIN_REG_DO, !!val);
446*01aa9d1dSRyder Lee }
447*01aa9d1dSRyder Lee 
mtk_gpio_get_direction(struct udevice * dev,unsigned int off)448*01aa9d1dSRyder Lee static int mtk_gpio_get_direction(struct udevice *dev, unsigned int off)
449*01aa9d1dSRyder Lee {
450*01aa9d1dSRyder Lee 	int val, err;
451*01aa9d1dSRyder Lee 
452*01aa9d1dSRyder Lee 	err = mtk_hw_get_value(dev->parent, off, PINCTRL_PIN_REG_DIR, &val);
453*01aa9d1dSRyder Lee 	if (err)
454*01aa9d1dSRyder Lee 		return err;
455*01aa9d1dSRyder Lee 
456*01aa9d1dSRyder Lee 	return val ? GPIOF_OUTPUT : GPIOF_INPUT;
457*01aa9d1dSRyder Lee }
458*01aa9d1dSRyder Lee 
mtk_gpio_direction_input(struct udevice * dev,unsigned int off)459*01aa9d1dSRyder Lee static int mtk_gpio_direction_input(struct udevice *dev, unsigned int off)
460*01aa9d1dSRyder Lee {
461*01aa9d1dSRyder Lee 	return mtk_hw_set_value(dev->parent, off, PINCTRL_PIN_REG_DIR, 0);
462*01aa9d1dSRyder Lee }
463*01aa9d1dSRyder Lee 
mtk_gpio_direction_output(struct udevice * dev,unsigned int off,int val)464*01aa9d1dSRyder Lee static int mtk_gpio_direction_output(struct udevice *dev,
465*01aa9d1dSRyder Lee 				     unsigned int off, int val)
466*01aa9d1dSRyder Lee {
467*01aa9d1dSRyder Lee 	mtk_gpio_set(dev, off, val);
468*01aa9d1dSRyder Lee 
469*01aa9d1dSRyder Lee 	/* And set the requested value */
470*01aa9d1dSRyder Lee 	return mtk_hw_set_value(dev->parent, off, PINCTRL_PIN_REG_DIR, 1);
471*01aa9d1dSRyder Lee }
472*01aa9d1dSRyder Lee 
mtk_gpio_request(struct udevice * dev,unsigned int off,const char * label)473*01aa9d1dSRyder Lee static int mtk_gpio_request(struct udevice *dev, unsigned int off,
474*01aa9d1dSRyder Lee 			    const char *label)
475*01aa9d1dSRyder Lee {
476*01aa9d1dSRyder Lee 	return mtk_hw_set_value(dev->parent, off, PINCTRL_PIN_REG_MODE, 0);
477*01aa9d1dSRyder Lee }
478*01aa9d1dSRyder Lee 
mtk_gpio_probe(struct udevice * dev)479*01aa9d1dSRyder Lee static int mtk_gpio_probe(struct udevice *dev)
480*01aa9d1dSRyder Lee {
481*01aa9d1dSRyder Lee 	struct mtk_pinctrl_priv *priv = dev_get_priv(dev->parent);
482*01aa9d1dSRyder Lee 	struct gpio_dev_priv *uc_priv;
483*01aa9d1dSRyder Lee 
484*01aa9d1dSRyder Lee 	uc_priv = dev_get_uclass_priv(dev);
485*01aa9d1dSRyder Lee 	uc_priv->bank_name = priv->soc->name;
486*01aa9d1dSRyder Lee 	uc_priv->gpio_count = priv->soc->npins;
487*01aa9d1dSRyder Lee 
488*01aa9d1dSRyder Lee 	return 0;
489*01aa9d1dSRyder Lee }
490*01aa9d1dSRyder Lee 
491*01aa9d1dSRyder Lee static const struct dm_gpio_ops mtk_gpio_ops = {
492*01aa9d1dSRyder Lee 	.request = mtk_gpio_request,
493*01aa9d1dSRyder Lee 	.set_value = mtk_gpio_set,
494*01aa9d1dSRyder Lee 	.get_value = mtk_gpio_get,
495*01aa9d1dSRyder Lee 	.get_function = mtk_gpio_get_direction,
496*01aa9d1dSRyder Lee 	.direction_input = mtk_gpio_direction_input,
497*01aa9d1dSRyder Lee 	.direction_output = mtk_gpio_direction_output,
498*01aa9d1dSRyder Lee };
499*01aa9d1dSRyder Lee 
500*01aa9d1dSRyder Lee static struct driver mtk_gpio_driver = {
501*01aa9d1dSRyder Lee 	.name = "mediatek_gpio",
502*01aa9d1dSRyder Lee 	.id	= UCLASS_GPIO,
503*01aa9d1dSRyder Lee 	.probe = mtk_gpio_probe,
504*01aa9d1dSRyder Lee 	.ops = &mtk_gpio_ops,
505*01aa9d1dSRyder Lee };
506*01aa9d1dSRyder Lee 
mtk_gpiochip_register(struct udevice * parent)507*01aa9d1dSRyder Lee static int mtk_gpiochip_register(struct udevice *parent)
508*01aa9d1dSRyder Lee {
509*01aa9d1dSRyder Lee 	struct uclass_driver *drv;
510*01aa9d1dSRyder Lee 	struct udevice *dev;
511*01aa9d1dSRyder Lee 	int ret;
512*01aa9d1dSRyder Lee 	ofnode node;
513*01aa9d1dSRyder Lee 
514*01aa9d1dSRyder Lee 	drv = lists_uclass_lookup(UCLASS_GPIO);
515*01aa9d1dSRyder Lee 	if (!drv)
516*01aa9d1dSRyder Lee 		return -ENOENT;
517*01aa9d1dSRyder Lee 
518*01aa9d1dSRyder Lee 	dev_for_each_subnode(node, parent)
519*01aa9d1dSRyder Lee 		if (ofnode_read_bool(node, "gpio-controller")) {
520*01aa9d1dSRyder Lee 			ret = 0;
521*01aa9d1dSRyder Lee 			break;
522*01aa9d1dSRyder Lee 		}
523*01aa9d1dSRyder Lee 
524*01aa9d1dSRyder Lee 	if (ret)
525*01aa9d1dSRyder Lee 		return ret;
526*01aa9d1dSRyder Lee 
527*01aa9d1dSRyder Lee 	ret = device_bind_with_driver_data(parent, &mtk_gpio_driver,
528*01aa9d1dSRyder Lee 					   "mediatek_gpio", 0, node,
529*01aa9d1dSRyder Lee 					   &dev);
530*01aa9d1dSRyder Lee 	if (ret)
531*01aa9d1dSRyder Lee 		return ret;
532*01aa9d1dSRyder Lee 
533*01aa9d1dSRyder Lee 	return 0;
534*01aa9d1dSRyder Lee }
535*01aa9d1dSRyder Lee 
mtk_pinctrl_common_probe(struct udevice * dev,struct mtk_pinctrl_soc * soc)536*01aa9d1dSRyder Lee int mtk_pinctrl_common_probe(struct udevice *dev,
537*01aa9d1dSRyder Lee 			     struct mtk_pinctrl_soc *soc)
538*01aa9d1dSRyder Lee {
539*01aa9d1dSRyder Lee 	struct mtk_pinctrl_priv *priv = dev_get_priv(dev);
540*01aa9d1dSRyder Lee 	int ret;
541*01aa9d1dSRyder Lee 
542*01aa9d1dSRyder Lee 	priv->base = dev_read_addr_ptr(dev);
543*01aa9d1dSRyder Lee 	if (priv->base == (void *)FDT_ADDR_T_NONE)
544*01aa9d1dSRyder Lee 		return -EINVAL;
545*01aa9d1dSRyder Lee 
546*01aa9d1dSRyder Lee 	priv->soc = soc;
547*01aa9d1dSRyder Lee 
548*01aa9d1dSRyder Lee 	ret = mtk_gpiochip_register(dev);
549*01aa9d1dSRyder Lee 	if (ret)
550*01aa9d1dSRyder Lee 		return ret;
551*01aa9d1dSRyder Lee 
552*01aa9d1dSRyder Lee 	return 0;
553*01aa9d1dSRyder Lee }
554