1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * Copyright (C) 2018 MediaTek Inc.
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * Author: Sean Wang <sean.wang@mediatek.com>
6*4882a593Smuzhiyun *
7*4882a593Smuzhiyun */
8*4882a593Smuzhiyun
9*4882a593Smuzhiyun #include <dt-bindings/pinctrl/mt65xx.h>
10*4882a593Smuzhiyun #include <linux/device.h>
11*4882a593Smuzhiyun #include <linux/err.h>
12*4882a593Smuzhiyun #include <linux/gpio/driver.h>
13*4882a593Smuzhiyun #include <linux/platform_device.h>
14*4882a593Smuzhiyun #include <linux/io.h>
15*4882a593Smuzhiyun #include <linux/module.h>
16*4882a593Smuzhiyun #include <linux/of_irq.h>
17*4882a593Smuzhiyun
18*4882a593Smuzhiyun #include "mtk-eint.h"
19*4882a593Smuzhiyun #include "pinctrl-mtk-common-v2.h"
20*4882a593Smuzhiyun
21*4882a593Smuzhiyun /**
22*4882a593Smuzhiyun * struct mtk_drive_desc - the structure that holds the information
23*4882a593Smuzhiyun * of the driving current
24*4882a593Smuzhiyun * @min: the minimum current of this group
25*4882a593Smuzhiyun * @max: the maximum current of this group
26*4882a593Smuzhiyun * @step: the step current of this group
27*4882a593Smuzhiyun * @scal: the weight factor
28*4882a593Smuzhiyun *
29*4882a593Smuzhiyun * formula: output = ((input) / step - 1) * scal
30*4882a593Smuzhiyun */
31*4882a593Smuzhiyun struct mtk_drive_desc {
32*4882a593Smuzhiyun u8 min;
33*4882a593Smuzhiyun u8 max;
34*4882a593Smuzhiyun u8 step;
35*4882a593Smuzhiyun u8 scal;
36*4882a593Smuzhiyun };
37*4882a593Smuzhiyun
38*4882a593Smuzhiyun /* The groups of drive strength */
39*4882a593Smuzhiyun static const struct mtk_drive_desc mtk_drive[] = {
40*4882a593Smuzhiyun [DRV_GRP0] = { 4, 16, 4, 1 },
41*4882a593Smuzhiyun [DRV_GRP1] = { 4, 16, 4, 2 },
42*4882a593Smuzhiyun [DRV_GRP2] = { 2, 8, 2, 1 },
43*4882a593Smuzhiyun [DRV_GRP3] = { 2, 8, 2, 2 },
44*4882a593Smuzhiyun [DRV_GRP4] = { 2, 16, 2, 1 },
45*4882a593Smuzhiyun };
46*4882a593Smuzhiyun
mtk_w32(struct mtk_pinctrl * pctl,u8 i,u32 reg,u32 val)47*4882a593Smuzhiyun static void mtk_w32(struct mtk_pinctrl *pctl, u8 i, u32 reg, u32 val)
48*4882a593Smuzhiyun {
49*4882a593Smuzhiyun writel_relaxed(val, pctl->base[i] + reg);
50*4882a593Smuzhiyun }
51*4882a593Smuzhiyun
mtk_r32(struct mtk_pinctrl * pctl,u8 i,u32 reg)52*4882a593Smuzhiyun static u32 mtk_r32(struct mtk_pinctrl *pctl, u8 i, u32 reg)
53*4882a593Smuzhiyun {
54*4882a593Smuzhiyun return readl_relaxed(pctl->base[i] + reg);
55*4882a593Smuzhiyun }
56*4882a593Smuzhiyun
mtk_rmw(struct mtk_pinctrl * pctl,u8 i,u32 reg,u32 mask,u32 set)57*4882a593Smuzhiyun void mtk_rmw(struct mtk_pinctrl *pctl, u8 i, u32 reg, u32 mask, u32 set)
58*4882a593Smuzhiyun {
59*4882a593Smuzhiyun u32 val;
60*4882a593Smuzhiyun
61*4882a593Smuzhiyun val = mtk_r32(pctl, i, reg);
62*4882a593Smuzhiyun val &= ~mask;
63*4882a593Smuzhiyun val |= set;
64*4882a593Smuzhiyun mtk_w32(pctl, i, reg, val);
65*4882a593Smuzhiyun }
66*4882a593Smuzhiyun
mtk_hw_pin_field_lookup(struct mtk_pinctrl * hw,const struct mtk_pin_desc * desc,int field,struct mtk_pin_field * pfd)67*4882a593Smuzhiyun static int mtk_hw_pin_field_lookup(struct mtk_pinctrl *hw,
68*4882a593Smuzhiyun const struct mtk_pin_desc *desc,
69*4882a593Smuzhiyun int field, struct mtk_pin_field *pfd)
70*4882a593Smuzhiyun {
71*4882a593Smuzhiyun const struct mtk_pin_field_calc *c;
72*4882a593Smuzhiyun const struct mtk_pin_reg_calc *rc;
73*4882a593Smuzhiyun int start = 0, end, check;
74*4882a593Smuzhiyun bool found = false;
75*4882a593Smuzhiyun u32 bits;
76*4882a593Smuzhiyun
77*4882a593Smuzhiyun if (hw->soc->reg_cal && hw->soc->reg_cal[field].range) {
78*4882a593Smuzhiyun rc = &hw->soc->reg_cal[field];
79*4882a593Smuzhiyun } else {
80*4882a593Smuzhiyun dev_dbg(hw->dev,
81*4882a593Smuzhiyun "Not support field %d for this soc\n", field);
82*4882a593Smuzhiyun return -ENOTSUPP;
83*4882a593Smuzhiyun }
84*4882a593Smuzhiyun
85*4882a593Smuzhiyun end = rc->nranges - 1;
86*4882a593Smuzhiyun
87*4882a593Smuzhiyun while (start <= end) {
88*4882a593Smuzhiyun check = (start + end) >> 1;
89*4882a593Smuzhiyun if (desc->number >= rc->range[check].s_pin
90*4882a593Smuzhiyun && desc->number <= rc->range[check].e_pin) {
91*4882a593Smuzhiyun found = true;
92*4882a593Smuzhiyun break;
93*4882a593Smuzhiyun } else if (start == end)
94*4882a593Smuzhiyun break;
95*4882a593Smuzhiyun else if (desc->number < rc->range[check].s_pin)
96*4882a593Smuzhiyun end = check - 1;
97*4882a593Smuzhiyun else
98*4882a593Smuzhiyun start = check + 1;
99*4882a593Smuzhiyun }
100*4882a593Smuzhiyun
101*4882a593Smuzhiyun if (!found) {
102*4882a593Smuzhiyun dev_dbg(hw->dev, "Not support field %d for pin = %d (%s)\n",
103*4882a593Smuzhiyun field, desc->number, desc->name);
104*4882a593Smuzhiyun return -ENOTSUPP;
105*4882a593Smuzhiyun }
106*4882a593Smuzhiyun
107*4882a593Smuzhiyun c = rc->range + check;
108*4882a593Smuzhiyun
109*4882a593Smuzhiyun if (c->i_base > hw->nbase - 1) {
110*4882a593Smuzhiyun dev_err(hw->dev,
111*4882a593Smuzhiyun "Invalid base for field %d for pin = %d (%s)\n",
112*4882a593Smuzhiyun field, desc->number, desc->name);
113*4882a593Smuzhiyun return -EINVAL;
114*4882a593Smuzhiyun }
115*4882a593Smuzhiyun
116*4882a593Smuzhiyun /* Calculated bits as the overall offset the pin is located at,
117*4882a593Smuzhiyun * if c->fixed is held, that determines the all the pins in the
118*4882a593Smuzhiyun * range use the same field with the s_pin.
119*4882a593Smuzhiyun */
120*4882a593Smuzhiyun bits = c->fixed ? c->s_bit : c->s_bit +
121*4882a593Smuzhiyun (desc->number - c->s_pin) * (c->x_bits);
122*4882a593Smuzhiyun
123*4882a593Smuzhiyun /* Fill pfd from bits. For example 32-bit register applied is assumed
124*4882a593Smuzhiyun * when c->sz_reg is equal to 32.
125*4882a593Smuzhiyun */
126*4882a593Smuzhiyun pfd->index = c->i_base;
127*4882a593Smuzhiyun pfd->offset = c->s_addr + c->x_addrs * (bits / c->sz_reg);
128*4882a593Smuzhiyun pfd->bitpos = bits % c->sz_reg;
129*4882a593Smuzhiyun pfd->mask = (1 << c->x_bits) - 1;
130*4882a593Smuzhiyun
131*4882a593Smuzhiyun /* pfd->next is used for indicating that bit wrapping-around happens
132*4882a593Smuzhiyun * which requires the manipulation for bit 0 starting in the next
133*4882a593Smuzhiyun * register to form the complete field read/write.
134*4882a593Smuzhiyun */
135*4882a593Smuzhiyun pfd->next = pfd->bitpos + c->x_bits > c->sz_reg ? c->x_addrs : 0;
136*4882a593Smuzhiyun
137*4882a593Smuzhiyun return 0;
138*4882a593Smuzhiyun }
139*4882a593Smuzhiyun
mtk_hw_pin_field_get(struct mtk_pinctrl * hw,const struct mtk_pin_desc * desc,int field,struct mtk_pin_field * pfd)140*4882a593Smuzhiyun static int mtk_hw_pin_field_get(struct mtk_pinctrl *hw,
141*4882a593Smuzhiyun const struct mtk_pin_desc *desc,
142*4882a593Smuzhiyun int field, struct mtk_pin_field *pfd)
143*4882a593Smuzhiyun {
144*4882a593Smuzhiyun if (field < 0 || field >= PINCTRL_PIN_REG_MAX) {
145*4882a593Smuzhiyun dev_err(hw->dev, "Invalid Field %d\n", field);
146*4882a593Smuzhiyun return -EINVAL;
147*4882a593Smuzhiyun }
148*4882a593Smuzhiyun
149*4882a593Smuzhiyun return mtk_hw_pin_field_lookup(hw, desc, field, pfd);
150*4882a593Smuzhiyun }
151*4882a593Smuzhiyun
mtk_hw_bits_part(struct mtk_pin_field * pf,int * h,int * l)152*4882a593Smuzhiyun static void mtk_hw_bits_part(struct mtk_pin_field *pf, int *h, int *l)
153*4882a593Smuzhiyun {
154*4882a593Smuzhiyun *l = 32 - pf->bitpos;
155*4882a593Smuzhiyun *h = get_count_order(pf->mask) - *l;
156*4882a593Smuzhiyun }
157*4882a593Smuzhiyun
mtk_hw_write_cross_field(struct mtk_pinctrl * hw,struct mtk_pin_field * pf,int value)158*4882a593Smuzhiyun static void mtk_hw_write_cross_field(struct mtk_pinctrl *hw,
159*4882a593Smuzhiyun struct mtk_pin_field *pf, int value)
160*4882a593Smuzhiyun {
161*4882a593Smuzhiyun int nbits_l, nbits_h;
162*4882a593Smuzhiyun
163*4882a593Smuzhiyun mtk_hw_bits_part(pf, &nbits_h, &nbits_l);
164*4882a593Smuzhiyun
165*4882a593Smuzhiyun mtk_rmw(hw, pf->index, pf->offset, pf->mask << pf->bitpos,
166*4882a593Smuzhiyun (value & pf->mask) << pf->bitpos);
167*4882a593Smuzhiyun
168*4882a593Smuzhiyun mtk_rmw(hw, pf->index, pf->offset + pf->next, BIT(nbits_h) - 1,
169*4882a593Smuzhiyun (value & pf->mask) >> nbits_l);
170*4882a593Smuzhiyun }
171*4882a593Smuzhiyun
mtk_hw_read_cross_field(struct mtk_pinctrl * hw,struct mtk_pin_field * pf,int * value)172*4882a593Smuzhiyun static void mtk_hw_read_cross_field(struct mtk_pinctrl *hw,
173*4882a593Smuzhiyun struct mtk_pin_field *pf, int *value)
174*4882a593Smuzhiyun {
175*4882a593Smuzhiyun int nbits_l, nbits_h, h, l;
176*4882a593Smuzhiyun
177*4882a593Smuzhiyun mtk_hw_bits_part(pf, &nbits_h, &nbits_l);
178*4882a593Smuzhiyun
179*4882a593Smuzhiyun l = (mtk_r32(hw, pf->index, pf->offset)
180*4882a593Smuzhiyun >> pf->bitpos) & (BIT(nbits_l) - 1);
181*4882a593Smuzhiyun h = (mtk_r32(hw, pf->index, pf->offset + pf->next))
182*4882a593Smuzhiyun & (BIT(nbits_h) - 1);
183*4882a593Smuzhiyun
184*4882a593Smuzhiyun *value = (h << nbits_l) | l;
185*4882a593Smuzhiyun }
186*4882a593Smuzhiyun
mtk_hw_set_value(struct mtk_pinctrl * hw,const struct mtk_pin_desc * desc,int field,int value)187*4882a593Smuzhiyun int mtk_hw_set_value(struct mtk_pinctrl *hw, const struct mtk_pin_desc *desc,
188*4882a593Smuzhiyun int field, int value)
189*4882a593Smuzhiyun {
190*4882a593Smuzhiyun struct mtk_pin_field pf;
191*4882a593Smuzhiyun int err;
192*4882a593Smuzhiyun
193*4882a593Smuzhiyun err = mtk_hw_pin_field_get(hw, desc, field, &pf);
194*4882a593Smuzhiyun if (err)
195*4882a593Smuzhiyun return err;
196*4882a593Smuzhiyun
197*4882a593Smuzhiyun if (value < 0 || value > pf.mask)
198*4882a593Smuzhiyun return -EINVAL;
199*4882a593Smuzhiyun
200*4882a593Smuzhiyun if (!pf.next)
201*4882a593Smuzhiyun mtk_rmw(hw, pf.index, pf.offset, pf.mask << pf.bitpos,
202*4882a593Smuzhiyun (value & pf.mask) << pf.bitpos);
203*4882a593Smuzhiyun else
204*4882a593Smuzhiyun mtk_hw_write_cross_field(hw, &pf, value);
205*4882a593Smuzhiyun
206*4882a593Smuzhiyun return 0;
207*4882a593Smuzhiyun }
208*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(mtk_hw_set_value);
209*4882a593Smuzhiyun
mtk_hw_get_value(struct mtk_pinctrl * hw,const struct mtk_pin_desc * desc,int field,int * value)210*4882a593Smuzhiyun int mtk_hw_get_value(struct mtk_pinctrl *hw, const struct mtk_pin_desc *desc,
211*4882a593Smuzhiyun int field, int *value)
212*4882a593Smuzhiyun {
213*4882a593Smuzhiyun struct mtk_pin_field pf;
214*4882a593Smuzhiyun int err;
215*4882a593Smuzhiyun
216*4882a593Smuzhiyun err = mtk_hw_pin_field_get(hw, desc, field, &pf);
217*4882a593Smuzhiyun if (err)
218*4882a593Smuzhiyun return err;
219*4882a593Smuzhiyun
220*4882a593Smuzhiyun if (!pf.next)
221*4882a593Smuzhiyun *value = (mtk_r32(hw, pf.index, pf.offset)
222*4882a593Smuzhiyun >> pf.bitpos) & pf.mask;
223*4882a593Smuzhiyun else
224*4882a593Smuzhiyun mtk_hw_read_cross_field(hw, &pf, value);
225*4882a593Smuzhiyun
226*4882a593Smuzhiyun return 0;
227*4882a593Smuzhiyun }
228*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(mtk_hw_get_value);
229*4882a593Smuzhiyun
mtk_xt_find_eint_num(struct mtk_pinctrl * hw,unsigned long eint_n)230*4882a593Smuzhiyun static int mtk_xt_find_eint_num(struct mtk_pinctrl *hw, unsigned long eint_n)
231*4882a593Smuzhiyun {
232*4882a593Smuzhiyun const struct mtk_pin_desc *desc;
233*4882a593Smuzhiyun int i = 0;
234*4882a593Smuzhiyun
235*4882a593Smuzhiyun desc = (const struct mtk_pin_desc *)hw->soc->pins;
236*4882a593Smuzhiyun
237*4882a593Smuzhiyun while (i < hw->soc->npins) {
238*4882a593Smuzhiyun if (desc[i].eint.eint_n == eint_n)
239*4882a593Smuzhiyun return desc[i].number;
240*4882a593Smuzhiyun i++;
241*4882a593Smuzhiyun }
242*4882a593Smuzhiyun
243*4882a593Smuzhiyun return EINT_NA;
244*4882a593Smuzhiyun }
245*4882a593Smuzhiyun
246*4882a593Smuzhiyun /*
247*4882a593Smuzhiyun * Virtual GPIO only used inside SOC and not being exported to outside SOC.
248*4882a593Smuzhiyun * Some modules use virtual GPIO as eint (e.g. pmif or usb).
249*4882a593Smuzhiyun * In MTK platform, external interrupt (EINT) and GPIO is 1-1 mapping
250*4882a593Smuzhiyun * and we can set GPIO as eint.
251*4882a593Smuzhiyun * But some modules use specific eint which doesn't have real GPIO pin.
252*4882a593Smuzhiyun * So we use virtual GPIO to map it.
253*4882a593Smuzhiyun */
254*4882a593Smuzhiyun
mtk_is_virt_gpio(struct mtk_pinctrl * hw,unsigned int gpio_n)255*4882a593Smuzhiyun bool mtk_is_virt_gpio(struct mtk_pinctrl *hw, unsigned int gpio_n)
256*4882a593Smuzhiyun {
257*4882a593Smuzhiyun const struct mtk_pin_desc *desc;
258*4882a593Smuzhiyun bool virt_gpio = false;
259*4882a593Smuzhiyun
260*4882a593Smuzhiyun desc = (const struct mtk_pin_desc *)&hw->soc->pins[gpio_n];
261*4882a593Smuzhiyun
262*4882a593Smuzhiyun /* if the GPIO is not supported for eint mode */
263*4882a593Smuzhiyun if (desc->eint.eint_m == NO_EINT_SUPPORT)
264*4882a593Smuzhiyun return virt_gpio;
265*4882a593Smuzhiyun
266*4882a593Smuzhiyun if (desc->funcs && !desc->funcs[desc->eint.eint_m].name)
267*4882a593Smuzhiyun virt_gpio = true;
268*4882a593Smuzhiyun
269*4882a593Smuzhiyun return virt_gpio;
270*4882a593Smuzhiyun }
271*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(mtk_is_virt_gpio);
272*4882a593Smuzhiyun
mtk_xt_get_gpio_n(void * data,unsigned long eint_n,unsigned int * gpio_n,struct gpio_chip ** gpio_chip)273*4882a593Smuzhiyun static int mtk_xt_get_gpio_n(void *data, unsigned long eint_n,
274*4882a593Smuzhiyun unsigned int *gpio_n,
275*4882a593Smuzhiyun struct gpio_chip **gpio_chip)
276*4882a593Smuzhiyun {
277*4882a593Smuzhiyun struct mtk_pinctrl *hw = (struct mtk_pinctrl *)data;
278*4882a593Smuzhiyun const struct mtk_pin_desc *desc;
279*4882a593Smuzhiyun
280*4882a593Smuzhiyun desc = (const struct mtk_pin_desc *)hw->soc->pins;
281*4882a593Smuzhiyun *gpio_chip = &hw->chip;
282*4882a593Smuzhiyun
283*4882a593Smuzhiyun /*
284*4882a593Smuzhiyun * Be greedy to guess first gpio_n is equal to eint_n.
285*4882a593Smuzhiyun * Only eint virtual eint number is greater than gpio number.
286*4882a593Smuzhiyun */
287*4882a593Smuzhiyun if (hw->soc->npins > eint_n &&
288*4882a593Smuzhiyun desc[eint_n].eint.eint_n == eint_n)
289*4882a593Smuzhiyun *gpio_n = eint_n;
290*4882a593Smuzhiyun else
291*4882a593Smuzhiyun *gpio_n = mtk_xt_find_eint_num(hw, eint_n);
292*4882a593Smuzhiyun
293*4882a593Smuzhiyun return *gpio_n == EINT_NA ? -EINVAL : 0;
294*4882a593Smuzhiyun }
295*4882a593Smuzhiyun
mtk_xt_get_gpio_state(void * data,unsigned long eint_n)296*4882a593Smuzhiyun static int mtk_xt_get_gpio_state(void *data, unsigned long eint_n)
297*4882a593Smuzhiyun {
298*4882a593Smuzhiyun struct mtk_pinctrl *hw = (struct mtk_pinctrl *)data;
299*4882a593Smuzhiyun const struct mtk_pin_desc *desc;
300*4882a593Smuzhiyun struct gpio_chip *gpio_chip;
301*4882a593Smuzhiyun unsigned int gpio_n;
302*4882a593Smuzhiyun int value, err;
303*4882a593Smuzhiyun
304*4882a593Smuzhiyun err = mtk_xt_get_gpio_n(hw, eint_n, &gpio_n, &gpio_chip);
305*4882a593Smuzhiyun if (err)
306*4882a593Smuzhiyun return err;
307*4882a593Smuzhiyun
308*4882a593Smuzhiyun desc = (const struct mtk_pin_desc *)&hw->soc->pins[gpio_n];
309*4882a593Smuzhiyun
310*4882a593Smuzhiyun err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_DI, &value);
311*4882a593Smuzhiyun if (err)
312*4882a593Smuzhiyun return err;
313*4882a593Smuzhiyun
314*4882a593Smuzhiyun return !!value;
315*4882a593Smuzhiyun }
316*4882a593Smuzhiyun
mtk_xt_set_gpio_as_eint(void * data,unsigned long eint_n)317*4882a593Smuzhiyun static int mtk_xt_set_gpio_as_eint(void *data, unsigned long eint_n)
318*4882a593Smuzhiyun {
319*4882a593Smuzhiyun struct mtk_pinctrl *hw = (struct mtk_pinctrl *)data;
320*4882a593Smuzhiyun const struct mtk_pin_desc *desc;
321*4882a593Smuzhiyun struct gpio_chip *gpio_chip;
322*4882a593Smuzhiyun unsigned int gpio_n;
323*4882a593Smuzhiyun int err;
324*4882a593Smuzhiyun
325*4882a593Smuzhiyun err = mtk_xt_get_gpio_n(hw, eint_n, &gpio_n, &gpio_chip);
326*4882a593Smuzhiyun if (err)
327*4882a593Smuzhiyun return err;
328*4882a593Smuzhiyun
329*4882a593Smuzhiyun if (mtk_is_virt_gpio(hw, gpio_n))
330*4882a593Smuzhiyun return 0;
331*4882a593Smuzhiyun
332*4882a593Smuzhiyun desc = (const struct mtk_pin_desc *)&hw->soc->pins[gpio_n];
333*4882a593Smuzhiyun
334*4882a593Smuzhiyun err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_MODE,
335*4882a593Smuzhiyun desc->eint.eint_m);
336*4882a593Smuzhiyun if (err)
337*4882a593Smuzhiyun return err;
338*4882a593Smuzhiyun
339*4882a593Smuzhiyun err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_DIR, MTK_INPUT);
340*4882a593Smuzhiyun if (err)
341*4882a593Smuzhiyun return err;
342*4882a593Smuzhiyun
343*4882a593Smuzhiyun err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_SMT, MTK_ENABLE);
344*4882a593Smuzhiyun /* SMT is supposed to be supported by every real GPIO and doesn't
345*4882a593Smuzhiyun * support virtual GPIOs, so the extra condition err != -ENOTSUPP
346*4882a593Smuzhiyun * is just for adding EINT support to these virtual GPIOs. It should
347*4882a593Smuzhiyun * add an extra flag in the pin descriptor when more pins with
348*4882a593Smuzhiyun * distinctive characteristic come out.
349*4882a593Smuzhiyun */
350*4882a593Smuzhiyun if (err && err != -ENOTSUPP)
351*4882a593Smuzhiyun return err;
352*4882a593Smuzhiyun
353*4882a593Smuzhiyun return 0;
354*4882a593Smuzhiyun }
355*4882a593Smuzhiyun
356*4882a593Smuzhiyun static const struct mtk_eint_xt mtk_eint_xt = {
357*4882a593Smuzhiyun .get_gpio_n = mtk_xt_get_gpio_n,
358*4882a593Smuzhiyun .get_gpio_state = mtk_xt_get_gpio_state,
359*4882a593Smuzhiyun .set_gpio_as_eint = mtk_xt_set_gpio_as_eint,
360*4882a593Smuzhiyun };
361*4882a593Smuzhiyun
mtk_build_eint(struct mtk_pinctrl * hw,struct platform_device * pdev)362*4882a593Smuzhiyun int mtk_build_eint(struct mtk_pinctrl *hw, struct platform_device *pdev)
363*4882a593Smuzhiyun {
364*4882a593Smuzhiyun struct device_node *np = pdev->dev.of_node;
365*4882a593Smuzhiyun int ret;
366*4882a593Smuzhiyun
367*4882a593Smuzhiyun if (!IS_ENABLED(CONFIG_EINT_MTK))
368*4882a593Smuzhiyun return 0;
369*4882a593Smuzhiyun
370*4882a593Smuzhiyun if (!of_property_read_bool(np, "interrupt-controller"))
371*4882a593Smuzhiyun return -ENODEV;
372*4882a593Smuzhiyun
373*4882a593Smuzhiyun hw->eint = devm_kzalloc(hw->dev, sizeof(*hw->eint), GFP_KERNEL);
374*4882a593Smuzhiyun if (!hw->eint)
375*4882a593Smuzhiyun return -ENOMEM;
376*4882a593Smuzhiyun
377*4882a593Smuzhiyun hw->eint->base = devm_platform_ioremap_resource_byname(pdev, "eint");
378*4882a593Smuzhiyun if (IS_ERR(hw->eint->base)) {
379*4882a593Smuzhiyun ret = PTR_ERR(hw->eint->base);
380*4882a593Smuzhiyun goto err_free_eint;
381*4882a593Smuzhiyun }
382*4882a593Smuzhiyun
383*4882a593Smuzhiyun hw->eint->irq = irq_of_parse_and_map(np, 0);
384*4882a593Smuzhiyun if (!hw->eint->irq) {
385*4882a593Smuzhiyun ret = -EINVAL;
386*4882a593Smuzhiyun goto err_free_eint;
387*4882a593Smuzhiyun }
388*4882a593Smuzhiyun
389*4882a593Smuzhiyun if (!hw->soc->eint_hw) {
390*4882a593Smuzhiyun ret = -ENODEV;
391*4882a593Smuzhiyun goto err_free_eint;
392*4882a593Smuzhiyun }
393*4882a593Smuzhiyun
394*4882a593Smuzhiyun hw->eint->dev = &pdev->dev;
395*4882a593Smuzhiyun hw->eint->hw = hw->soc->eint_hw;
396*4882a593Smuzhiyun hw->eint->pctl = hw;
397*4882a593Smuzhiyun hw->eint->gpio_xlate = &mtk_eint_xt;
398*4882a593Smuzhiyun
399*4882a593Smuzhiyun return mtk_eint_do_init(hw->eint);
400*4882a593Smuzhiyun
401*4882a593Smuzhiyun err_free_eint:
402*4882a593Smuzhiyun devm_kfree(hw->dev, hw->eint);
403*4882a593Smuzhiyun hw->eint = NULL;
404*4882a593Smuzhiyun return ret;
405*4882a593Smuzhiyun }
406*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(mtk_build_eint);
407*4882a593Smuzhiyun
408*4882a593Smuzhiyun /* Revision 0 */
mtk_pinconf_bias_disable_set(struct mtk_pinctrl * hw,const struct mtk_pin_desc * desc)409*4882a593Smuzhiyun int mtk_pinconf_bias_disable_set(struct mtk_pinctrl *hw,
410*4882a593Smuzhiyun const struct mtk_pin_desc *desc)
411*4882a593Smuzhiyun {
412*4882a593Smuzhiyun int err;
413*4882a593Smuzhiyun
414*4882a593Smuzhiyun err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_PU,
415*4882a593Smuzhiyun MTK_DISABLE);
416*4882a593Smuzhiyun if (err)
417*4882a593Smuzhiyun return err;
418*4882a593Smuzhiyun
419*4882a593Smuzhiyun err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_PD,
420*4882a593Smuzhiyun MTK_DISABLE);
421*4882a593Smuzhiyun if (err)
422*4882a593Smuzhiyun return err;
423*4882a593Smuzhiyun
424*4882a593Smuzhiyun return 0;
425*4882a593Smuzhiyun }
426*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(mtk_pinconf_bias_disable_set);
427*4882a593Smuzhiyun
mtk_pinconf_bias_disable_get(struct mtk_pinctrl * hw,const struct mtk_pin_desc * desc,int * res)428*4882a593Smuzhiyun int mtk_pinconf_bias_disable_get(struct mtk_pinctrl *hw,
429*4882a593Smuzhiyun const struct mtk_pin_desc *desc, int *res)
430*4882a593Smuzhiyun {
431*4882a593Smuzhiyun int v, v2;
432*4882a593Smuzhiyun int err;
433*4882a593Smuzhiyun
434*4882a593Smuzhiyun err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_PU, &v);
435*4882a593Smuzhiyun if (err)
436*4882a593Smuzhiyun return err;
437*4882a593Smuzhiyun
438*4882a593Smuzhiyun err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_PD, &v2);
439*4882a593Smuzhiyun if (err)
440*4882a593Smuzhiyun return err;
441*4882a593Smuzhiyun
442*4882a593Smuzhiyun if (v == MTK_ENABLE || v2 == MTK_ENABLE)
443*4882a593Smuzhiyun return -EINVAL;
444*4882a593Smuzhiyun
445*4882a593Smuzhiyun *res = 1;
446*4882a593Smuzhiyun
447*4882a593Smuzhiyun return 0;
448*4882a593Smuzhiyun }
449*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(mtk_pinconf_bias_disable_get);
450*4882a593Smuzhiyun
mtk_pinconf_bias_set(struct mtk_pinctrl * hw,const struct mtk_pin_desc * desc,bool pullup)451*4882a593Smuzhiyun int mtk_pinconf_bias_set(struct mtk_pinctrl *hw,
452*4882a593Smuzhiyun const struct mtk_pin_desc *desc, bool pullup)
453*4882a593Smuzhiyun {
454*4882a593Smuzhiyun int err, arg;
455*4882a593Smuzhiyun
456*4882a593Smuzhiyun arg = pullup ? 1 : 2;
457*4882a593Smuzhiyun
458*4882a593Smuzhiyun err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_PU, arg & 1);
459*4882a593Smuzhiyun if (err)
460*4882a593Smuzhiyun return err;
461*4882a593Smuzhiyun
462*4882a593Smuzhiyun err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_PD,
463*4882a593Smuzhiyun !!(arg & 2));
464*4882a593Smuzhiyun if (err)
465*4882a593Smuzhiyun return err;
466*4882a593Smuzhiyun
467*4882a593Smuzhiyun return 0;
468*4882a593Smuzhiyun }
469*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(mtk_pinconf_bias_set);
470*4882a593Smuzhiyun
mtk_pinconf_bias_get(struct mtk_pinctrl * hw,const struct mtk_pin_desc * desc,bool pullup,int * res)471*4882a593Smuzhiyun int mtk_pinconf_bias_get(struct mtk_pinctrl *hw,
472*4882a593Smuzhiyun const struct mtk_pin_desc *desc, bool pullup, int *res)
473*4882a593Smuzhiyun {
474*4882a593Smuzhiyun int reg, err, v;
475*4882a593Smuzhiyun
476*4882a593Smuzhiyun reg = pullup ? PINCTRL_PIN_REG_PU : PINCTRL_PIN_REG_PD;
477*4882a593Smuzhiyun
478*4882a593Smuzhiyun err = mtk_hw_get_value(hw, desc, reg, &v);
479*4882a593Smuzhiyun if (err)
480*4882a593Smuzhiyun return err;
481*4882a593Smuzhiyun
482*4882a593Smuzhiyun if (!v)
483*4882a593Smuzhiyun return -EINVAL;
484*4882a593Smuzhiyun
485*4882a593Smuzhiyun *res = 1;
486*4882a593Smuzhiyun
487*4882a593Smuzhiyun return 0;
488*4882a593Smuzhiyun }
489*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(mtk_pinconf_bias_get);
490*4882a593Smuzhiyun
491*4882a593Smuzhiyun /* Revision 1 */
mtk_pinconf_bias_disable_set_rev1(struct mtk_pinctrl * hw,const struct mtk_pin_desc * desc)492*4882a593Smuzhiyun int mtk_pinconf_bias_disable_set_rev1(struct mtk_pinctrl *hw,
493*4882a593Smuzhiyun const struct mtk_pin_desc *desc)
494*4882a593Smuzhiyun {
495*4882a593Smuzhiyun int err;
496*4882a593Smuzhiyun
497*4882a593Smuzhiyun err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_PULLEN,
498*4882a593Smuzhiyun MTK_DISABLE);
499*4882a593Smuzhiyun if (err)
500*4882a593Smuzhiyun return err;
501*4882a593Smuzhiyun
502*4882a593Smuzhiyun return 0;
503*4882a593Smuzhiyun }
504*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(mtk_pinconf_bias_disable_set_rev1);
505*4882a593Smuzhiyun
mtk_pinconf_bias_disable_get_rev1(struct mtk_pinctrl * hw,const struct mtk_pin_desc * desc,int * res)506*4882a593Smuzhiyun int mtk_pinconf_bias_disable_get_rev1(struct mtk_pinctrl *hw,
507*4882a593Smuzhiyun const struct mtk_pin_desc *desc, int *res)
508*4882a593Smuzhiyun {
509*4882a593Smuzhiyun int v, err;
510*4882a593Smuzhiyun
511*4882a593Smuzhiyun err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_PULLEN, &v);
512*4882a593Smuzhiyun if (err)
513*4882a593Smuzhiyun return err;
514*4882a593Smuzhiyun
515*4882a593Smuzhiyun if (v == MTK_ENABLE)
516*4882a593Smuzhiyun return -EINVAL;
517*4882a593Smuzhiyun
518*4882a593Smuzhiyun *res = 1;
519*4882a593Smuzhiyun
520*4882a593Smuzhiyun return 0;
521*4882a593Smuzhiyun }
522*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(mtk_pinconf_bias_disable_get_rev1);
523*4882a593Smuzhiyun
mtk_pinconf_bias_set_rev1(struct mtk_pinctrl * hw,const struct mtk_pin_desc * desc,bool pullup)524*4882a593Smuzhiyun int mtk_pinconf_bias_set_rev1(struct mtk_pinctrl *hw,
525*4882a593Smuzhiyun const struct mtk_pin_desc *desc, bool pullup)
526*4882a593Smuzhiyun {
527*4882a593Smuzhiyun int err, arg;
528*4882a593Smuzhiyun
529*4882a593Smuzhiyun arg = pullup ? MTK_PULLUP : MTK_PULLDOWN;
530*4882a593Smuzhiyun
531*4882a593Smuzhiyun err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_PULLEN,
532*4882a593Smuzhiyun MTK_ENABLE);
533*4882a593Smuzhiyun if (err)
534*4882a593Smuzhiyun return err;
535*4882a593Smuzhiyun
536*4882a593Smuzhiyun err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_PULLSEL, arg);
537*4882a593Smuzhiyun if (err)
538*4882a593Smuzhiyun return err;
539*4882a593Smuzhiyun
540*4882a593Smuzhiyun return 0;
541*4882a593Smuzhiyun }
542*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(mtk_pinconf_bias_set_rev1);
543*4882a593Smuzhiyun
mtk_pinconf_bias_get_rev1(struct mtk_pinctrl * hw,const struct mtk_pin_desc * desc,bool pullup,int * res)544*4882a593Smuzhiyun int mtk_pinconf_bias_get_rev1(struct mtk_pinctrl *hw,
545*4882a593Smuzhiyun const struct mtk_pin_desc *desc, bool pullup,
546*4882a593Smuzhiyun int *res)
547*4882a593Smuzhiyun {
548*4882a593Smuzhiyun int err, v;
549*4882a593Smuzhiyun
550*4882a593Smuzhiyun err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_PULLEN, &v);
551*4882a593Smuzhiyun if (err)
552*4882a593Smuzhiyun return err;
553*4882a593Smuzhiyun
554*4882a593Smuzhiyun if (v == MTK_DISABLE)
555*4882a593Smuzhiyun return -EINVAL;
556*4882a593Smuzhiyun
557*4882a593Smuzhiyun err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_PULLSEL, &v);
558*4882a593Smuzhiyun if (err)
559*4882a593Smuzhiyun return err;
560*4882a593Smuzhiyun
561*4882a593Smuzhiyun if (pullup ^ (v == MTK_PULLUP))
562*4882a593Smuzhiyun return -EINVAL;
563*4882a593Smuzhiyun
564*4882a593Smuzhiyun *res = 1;
565*4882a593Smuzhiyun
566*4882a593Smuzhiyun return 0;
567*4882a593Smuzhiyun }
568*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(mtk_pinconf_bias_get_rev1);
569*4882a593Smuzhiyun
570*4882a593Smuzhiyun /* Combo for the following pull register type:
571*4882a593Smuzhiyun * 1. PU + PD
572*4882a593Smuzhiyun * 2. PULLSEL + PULLEN
573*4882a593Smuzhiyun * 3. PUPD + R0 + R1
574*4882a593Smuzhiyun */
mtk_pinconf_bias_set_pu_pd(struct mtk_pinctrl * hw,const struct mtk_pin_desc * desc,u32 pullup,u32 arg)575*4882a593Smuzhiyun static int mtk_pinconf_bias_set_pu_pd(struct mtk_pinctrl *hw,
576*4882a593Smuzhiyun const struct mtk_pin_desc *desc,
577*4882a593Smuzhiyun u32 pullup, u32 arg)
578*4882a593Smuzhiyun {
579*4882a593Smuzhiyun int err, pu, pd;
580*4882a593Smuzhiyun
581*4882a593Smuzhiyun if (arg == MTK_DISABLE) {
582*4882a593Smuzhiyun pu = 0;
583*4882a593Smuzhiyun pd = 0;
584*4882a593Smuzhiyun } else if ((arg == MTK_ENABLE) && pullup) {
585*4882a593Smuzhiyun pu = 1;
586*4882a593Smuzhiyun pd = 0;
587*4882a593Smuzhiyun } else if ((arg == MTK_ENABLE) && !pullup) {
588*4882a593Smuzhiyun pu = 0;
589*4882a593Smuzhiyun pd = 1;
590*4882a593Smuzhiyun } else {
591*4882a593Smuzhiyun err = -EINVAL;
592*4882a593Smuzhiyun goto out;
593*4882a593Smuzhiyun }
594*4882a593Smuzhiyun
595*4882a593Smuzhiyun err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_PU, pu);
596*4882a593Smuzhiyun if (err)
597*4882a593Smuzhiyun goto out;
598*4882a593Smuzhiyun
599*4882a593Smuzhiyun err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_PD, pd);
600*4882a593Smuzhiyun
601*4882a593Smuzhiyun out:
602*4882a593Smuzhiyun return err;
603*4882a593Smuzhiyun }
604*4882a593Smuzhiyun
mtk_pinconf_bias_set_pullsel_pullen(struct mtk_pinctrl * hw,const struct mtk_pin_desc * desc,u32 pullup,u32 arg)605*4882a593Smuzhiyun static int mtk_pinconf_bias_set_pullsel_pullen(struct mtk_pinctrl *hw,
606*4882a593Smuzhiyun const struct mtk_pin_desc *desc,
607*4882a593Smuzhiyun u32 pullup, u32 arg)
608*4882a593Smuzhiyun {
609*4882a593Smuzhiyun int err, enable;
610*4882a593Smuzhiyun
611*4882a593Smuzhiyun if (arg == MTK_DISABLE)
612*4882a593Smuzhiyun enable = 0;
613*4882a593Smuzhiyun else if (arg == MTK_ENABLE)
614*4882a593Smuzhiyun enable = 1;
615*4882a593Smuzhiyun else {
616*4882a593Smuzhiyun err = -EINVAL;
617*4882a593Smuzhiyun goto out;
618*4882a593Smuzhiyun }
619*4882a593Smuzhiyun
620*4882a593Smuzhiyun err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_PULLEN, enable);
621*4882a593Smuzhiyun if (err)
622*4882a593Smuzhiyun goto out;
623*4882a593Smuzhiyun
624*4882a593Smuzhiyun err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_PULLSEL, pullup);
625*4882a593Smuzhiyun
626*4882a593Smuzhiyun out:
627*4882a593Smuzhiyun return err;
628*4882a593Smuzhiyun }
629*4882a593Smuzhiyun
mtk_pinconf_bias_set_pupd_r1_r0(struct mtk_pinctrl * hw,const struct mtk_pin_desc * desc,u32 pullup,u32 arg)630*4882a593Smuzhiyun static int mtk_pinconf_bias_set_pupd_r1_r0(struct mtk_pinctrl *hw,
631*4882a593Smuzhiyun const struct mtk_pin_desc *desc,
632*4882a593Smuzhiyun u32 pullup, u32 arg)
633*4882a593Smuzhiyun {
634*4882a593Smuzhiyun int err, r0, r1;
635*4882a593Smuzhiyun
636*4882a593Smuzhiyun if ((arg == MTK_DISABLE) || (arg == MTK_PUPD_SET_R1R0_00)) {
637*4882a593Smuzhiyun pullup = 0;
638*4882a593Smuzhiyun r0 = 0;
639*4882a593Smuzhiyun r1 = 0;
640*4882a593Smuzhiyun } else if (arg == MTK_PUPD_SET_R1R0_01) {
641*4882a593Smuzhiyun r0 = 1;
642*4882a593Smuzhiyun r1 = 0;
643*4882a593Smuzhiyun } else if (arg == MTK_PUPD_SET_R1R0_10) {
644*4882a593Smuzhiyun r0 = 0;
645*4882a593Smuzhiyun r1 = 1;
646*4882a593Smuzhiyun } else if (arg == MTK_PUPD_SET_R1R0_11) {
647*4882a593Smuzhiyun r0 = 1;
648*4882a593Smuzhiyun r1 = 1;
649*4882a593Smuzhiyun } else {
650*4882a593Smuzhiyun err = -EINVAL;
651*4882a593Smuzhiyun goto out;
652*4882a593Smuzhiyun }
653*4882a593Smuzhiyun
654*4882a593Smuzhiyun /* MTK HW PUPD bit: 1 for pull-down, 0 for pull-up */
655*4882a593Smuzhiyun err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_PUPD, !pullup);
656*4882a593Smuzhiyun if (err)
657*4882a593Smuzhiyun goto out;
658*4882a593Smuzhiyun
659*4882a593Smuzhiyun err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_R0, r0);
660*4882a593Smuzhiyun if (err)
661*4882a593Smuzhiyun goto out;
662*4882a593Smuzhiyun
663*4882a593Smuzhiyun err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_R1, r1);
664*4882a593Smuzhiyun
665*4882a593Smuzhiyun out:
666*4882a593Smuzhiyun return err;
667*4882a593Smuzhiyun }
668*4882a593Smuzhiyun
mtk_pinconf_bias_get_pu_pd(struct mtk_pinctrl * hw,const struct mtk_pin_desc * desc,u32 * pullup,u32 * enable)669*4882a593Smuzhiyun static int mtk_pinconf_bias_get_pu_pd(struct mtk_pinctrl *hw,
670*4882a593Smuzhiyun const struct mtk_pin_desc *desc,
671*4882a593Smuzhiyun u32 *pullup, u32 *enable)
672*4882a593Smuzhiyun {
673*4882a593Smuzhiyun int err, pu, pd;
674*4882a593Smuzhiyun
675*4882a593Smuzhiyun err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_PU, &pu);
676*4882a593Smuzhiyun if (err)
677*4882a593Smuzhiyun goto out;
678*4882a593Smuzhiyun
679*4882a593Smuzhiyun err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_PD, &pd);
680*4882a593Smuzhiyun if (err)
681*4882a593Smuzhiyun goto out;
682*4882a593Smuzhiyun
683*4882a593Smuzhiyun if (pu == 0 && pd == 0) {
684*4882a593Smuzhiyun *pullup = 0;
685*4882a593Smuzhiyun *enable = MTK_DISABLE;
686*4882a593Smuzhiyun } else if (pu == 1 && pd == 0) {
687*4882a593Smuzhiyun *pullup = 1;
688*4882a593Smuzhiyun *enable = MTK_ENABLE;
689*4882a593Smuzhiyun } else if (pu == 0 && pd == 1) {
690*4882a593Smuzhiyun *pullup = 0;
691*4882a593Smuzhiyun *enable = MTK_ENABLE;
692*4882a593Smuzhiyun } else
693*4882a593Smuzhiyun err = -EINVAL;
694*4882a593Smuzhiyun
695*4882a593Smuzhiyun out:
696*4882a593Smuzhiyun return err;
697*4882a593Smuzhiyun }
698*4882a593Smuzhiyun
mtk_pinconf_bias_get_pullsel_pullen(struct mtk_pinctrl * hw,const struct mtk_pin_desc * desc,u32 * pullup,u32 * enable)699*4882a593Smuzhiyun static int mtk_pinconf_bias_get_pullsel_pullen(struct mtk_pinctrl *hw,
700*4882a593Smuzhiyun const struct mtk_pin_desc *desc,
701*4882a593Smuzhiyun u32 *pullup, u32 *enable)
702*4882a593Smuzhiyun {
703*4882a593Smuzhiyun int err;
704*4882a593Smuzhiyun
705*4882a593Smuzhiyun err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_PULLSEL, pullup);
706*4882a593Smuzhiyun if (err)
707*4882a593Smuzhiyun goto out;
708*4882a593Smuzhiyun
709*4882a593Smuzhiyun err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_PULLEN, enable);
710*4882a593Smuzhiyun
711*4882a593Smuzhiyun out:
712*4882a593Smuzhiyun return err;
713*4882a593Smuzhiyun }
714*4882a593Smuzhiyun
mtk_pinconf_bias_get_pupd_r1_r0(struct mtk_pinctrl * hw,const struct mtk_pin_desc * desc,u32 * pullup,u32 * enable)715*4882a593Smuzhiyun static int mtk_pinconf_bias_get_pupd_r1_r0(struct mtk_pinctrl *hw,
716*4882a593Smuzhiyun const struct mtk_pin_desc *desc,
717*4882a593Smuzhiyun u32 *pullup, u32 *enable)
718*4882a593Smuzhiyun {
719*4882a593Smuzhiyun int err, r0, r1;
720*4882a593Smuzhiyun
721*4882a593Smuzhiyun err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_PUPD, pullup);
722*4882a593Smuzhiyun if (err)
723*4882a593Smuzhiyun goto out;
724*4882a593Smuzhiyun /* MTK HW PUPD bit: 1 for pull-down, 0 for pull-up */
725*4882a593Smuzhiyun *pullup = !(*pullup);
726*4882a593Smuzhiyun
727*4882a593Smuzhiyun err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_R0, &r0);
728*4882a593Smuzhiyun if (err)
729*4882a593Smuzhiyun goto out;
730*4882a593Smuzhiyun
731*4882a593Smuzhiyun err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_R1, &r1);
732*4882a593Smuzhiyun if (err)
733*4882a593Smuzhiyun goto out;
734*4882a593Smuzhiyun
735*4882a593Smuzhiyun if ((r1 == 0) && (r0 == 0))
736*4882a593Smuzhiyun *enable = MTK_PUPD_SET_R1R0_00;
737*4882a593Smuzhiyun else if ((r1 == 0) && (r0 == 1))
738*4882a593Smuzhiyun *enable = MTK_PUPD_SET_R1R0_01;
739*4882a593Smuzhiyun else if ((r1 == 1) && (r0 == 0))
740*4882a593Smuzhiyun *enable = MTK_PUPD_SET_R1R0_10;
741*4882a593Smuzhiyun else if ((r1 == 1) && (r0 == 1))
742*4882a593Smuzhiyun *enable = MTK_PUPD_SET_R1R0_11;
743*4882a593Smuzhiyun else
744*4882a593Smuzhiyun err = -EINVAL;
745*4882a593Smuzhiyun
746*4882a593Smuzhiyun out:
747*4882a593Smuzhiyun return err;
748*4882a593Smuzhiyun }
749*4882a593Smuzhiyun
mtk_pinconf_bias_set_combo(struct mtk_pinctrl * hw,const struct mtk_pin_desc * desc,u32 pullup,u32 arg)750*4882a593Smuzhiyun int mtk_pinconf_bias_set_combo(struct mtk_pinctrl *hw,
751*4882a593Smuzhiyun const struct mtk_pin_desc *desc,
752*4882a593Smuzhiyun u32 pullup, u32 arg)
753*4882a593Smuzhiyun {
754*4882a593Smuzhiyun int err;
755*4882a593Smuzhiyun
756*4882a593Smuzhiyun err = mtk_pinconf_bias_set_pu_pd(hw, desc, pullup, arg);
757*4882a593Smuzhiyun if (!err)
758*4882a593Smuzhiyun goto out;
759*4882a593Smuzhiyun
760*4882a593Smuzhiyun err = mtk_pinconf_bias_set_pullsel_pullen(hw, desc, pullup, arg);
761*4882a593Smuzhiyun if (!err)
762*4882a593Smuzhiyun goto out;
763*4882a593Smuzhiyun
764*4882a593Smuzhiyun err = mtk_pinconf_bias_set_pupd_r1_r0(hw, desc, pullup, arg);
765*4882a593Smuzhiyun
766*4882a593Smuzhiyun out:
767*4882a593Smuzhiyun return err;
768*4882a593Smuzhiyun }
769*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(mtk_pinconf_bias_set_combo);
770*4882a593Smuzhiyun
mtk_pinconf_bias_get_combo(struct mtk_pinctrl * hw,const struct mtk_pin_desc * desc,u32 * pullup,u32 * enable)771*4882a593Smuzhiyun int mtk_pinconf_bias_get_combo(struct mtk_pinctrl *hw,
772*4882a593Smuzhiyun const struct mtk_pin_desc *desc,
773*4882a593Smuzhiyun u32 *pullup, u32 *enable)
774*4882a593Smuzhiyun {
775*4882a593Smuzhiyun int err;
776*4882a593Smuzhiyun
777*4882a593Smuzhiyun err = mtk_pinconf_bias_get_pu_pd(hw, desc, pullup, enable);
778*4882a593Smuzhiyun if (!err)
779*4882a593Smuzhiyun goto out;
780*4882a593Smuzhiyun
781*4882a593Smuzhiyun err = mtk_pinconf_bias_get_pullsel_pullen(hw, desc, pullup, enable);
782*4882a593Smuzhiyun if (!err)
783*4882a593Smuzhiyun goto out;
784*4882a593Smuzhiyun
785*4882a593Smuzhiyun err = mtk_pinconf_bias_get_pupd_r1_r0(hw, desc, pullup, enable);
786*4882a593Smuzhiyun
787*4882a593Smuzhiyun out:
788*4882a593Smuzhiyun return err;
789*4882a593Smuzhiyun }
790*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(mtk_pinconf_bias_get_combo);
791*4882a593Smuzhiyun
792*4882a593Smuzhiyun /* Revision 0 */
mtk_pinconf_drive_set(struct mtk_pinctrl * hw,const struct mtk_pin_desc * desc,u32 arg)793*4882a593Smuzhiyun int mtk_pinconf_drive_set(struct mtk_pinctrl *hw,
794*4882a593Smuzhiyun const struct mtk_pin_desc *desc, u32 arg)
795*4882a593Smuzhiyun {
796*4882a593Smuzhiyun const struct mtk_drive_desc *tb;
797*4882a593Smuzhiyun int err = -ENOTSUPP;
798*4882a593Smuzhiyun
799*4882a593Smuzhiyun tb = &mtk_drive[desc->drv_n];
800*4882a593Smuzhiyun /* 4mA when (e8, e4) = (0, 0)
801*4882a593Smuzhiyun * 8mA when (e8, e4) = (0, 1)
802*4882a593Smuzhiyun * 12mA when (e8, e4) = (1, 0)
803*4882a593Smuzhiyun * 16mA when (e8, e4) = (1, 1)
804*4882a593Smuzhiyun */
805*4882a593Smuzhiyun if ((arg >= tb->min && arg <= tb->max) && !(arg % tb->step)) {
806*4882a593Smuzhiyun arg = (arg / tb->step - 1) * tb->scal;
807*4882a593Smuzhiyun err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_E4,
808*4882a593Smuzhiyun arg & 0x1);
809*4882a593Smuzhiyun if (err)
810*4882a593Smuzhiyun return err;
811*4882a593Smuzhiyun
812*4882a593Smuzhiyun err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_E8,
813*4882a593Smuzhiyun (arg & 0x2) >> 1);
814*4882a593Smuzhiyun if (err)
815*4882a593Smuzhiyun return err;
816*4882a593Smuzhiyun }
817*4882a593Smuzhiyun
818*4882a593Smuzhiyun return err;
819*4882a593Smuzhiyun }
820*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(mtk_pinconf_drive_set);
821*4882a593Smuzhiyun
mtk_pinconf_drive_get(struct mtk_pinctrl * hw,const struct mtk_pin_desc * desc,int * val)822*4882a593Smuzhiyun int mtk_pinconf_drive_get(struct mtk_pinctrl *hw,
823*4882a593Smuzhiyun const struct mtk_pin_desc *desc, int *val)
824*4882a593Smuzhiyun {
825*4882a593Smuzhiyun const struct mtk_drive_desc *tb;
826*4882a593Smuzhiyun int err, val1, val2;
827*4882a593Smuzhiyun
828*4882a593Smuzhiyun tb = &mtk_drive[desc->drv_n];
829*4882a593Smuzhiyun
830*4882a593Smuzhiyun err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_E4, &val1);
831*4882a593Smuzhiyun if (err)
832*4882a593Smuzhiyun return err;
833*4882a593Smuzhiyun
834*4882a593Smuzhiyun err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_E8, &val2);
835*4882a593Smuzhiyun if (err)
836*4882a593Smuzhiyun return err;
837*4882a593Smuzhiyun
838*4882a593Smuzhiyun /* 4mA when (e8, e4) = (0, 0); 8mA when (e8, e4) = (0, 1)
839*4882a593Smuzhiyun * 12mA when (e8, e4) = (1, 0); 16mA when (e8, e4) = (1, 1)
840*4882a593Smuzhiyun */
841*4882a593Smuzhiyun *val = (((val2 << 1) + val1) / tb->scal + 1) * tb->step;
842*4882a593Smuzhiyun
843*4882a593Smuzhiyun return 0;
844*4882a593Smuzhiyun }
845*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(mtk_pinconf_drive_get);
846*4882a593Smuzhiyun
847*4882a593Smuzhiyun /* Revision 1 */
mtk_pinconf_drive_set_rev1(struct mtk_pinctrl * hw,const struct mtk_pin_desc * desc,u32 arg)848*4882a593Smuzhiyun int mtk_pinconf_drive_set_rev1(struct mtk_pinctrl *hw,
849*4882a593Smuzhiyun const struct mtk_pin_desc *desc, u32 arg)
850*4882a593Smuzhiyun {
851*4882a593Smuzhiyun const struct mtk_drive_desc *tb;
852*4882a593Smuzhiyun int err = -ENOTSUPP;
853*4882a593Smuzhiyun
854*4882a593Smuzhiyun tb = &mtk_drive[desc->drv_n];
855*4882a593Smuzhiyun
856*4882a593Smuzhiyun if ((arg >= tb->min && arg <= tb->max) && !(arg % tb->step)) {
857*4882a593Smuzhiyun arg = (arg / tb->step - 1) * tb->scal;
858*4882a593Smuzhiyun
859*4882a593Smuzhiyun err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_DRV,
860*4882a593Smuzhiyun arg);
861*4882a593Smuzhiyun if (err)
862*4882a593Smuzhiyun return err;
863*4882a593Smuzhiyun }
864*4882a593Smuzhiyun
865*4882a593Smuzhiyun return err;
866*4882a593Smuzhiyun }
867*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(mtk_pinconf_drive_set_rev1);
868*4882a593Smuzhiyun
mtk_pinconf_drive_get_rev1(struct mtk_pinctrl * hw,const struct mtk_pin_desc * desc,int * val)869*4882a593Smuzhiyun int mtk_pinconf_drive_get_rev1(struct mtk_pinctrl *hw,
870*4882a593Smuzhiyun const struct mtk_pin_desc *desc, int *val)
871*4882a593Smuzhiyun {
872*4882a593Smuzhiyun const struct mtk_drive_desc *tb;
873*4882a593Smuzhiyun int err, val1;
874*4882a593Smuzhiyun
875*4882a593Smuzhiyun tb = &mtk_drive[desc->drv_n];
876*4882a593Smuzhiyun
877*4882a593Smuzhiyun err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_DRV, &val1);
878*4882a593Smuzhiyun if (err)
879*4882a593Smuzhiyun return err;
880*4882a593Smuzhiyun
881*4882a593Smuzhiyun *val = ((val1 & 0x7) / tb->scal + 1) * tb->step;
882*4882a593Smuzhiyun
883*4882a593Smuzhiyun return 0;
884*4882a593Smuzhiyun }
885*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(mtk_pinconf_drive_get_rev1);
886*4882a593Smuzhiyun
mtk_pinconf_drive_set_raw(struct mtk_pinctrl * hw,const struct mtk_pin_desc * desc,u32 arg)887*4882a593Smuzhiyun int mtk_pinconf_drive_set_raw(struct mtk_pinctrl *hw,
888*4882a593Smuzhiyun const struct mtk_pin_desc *desc, u32 arg)
889*4882a593Smuzhiyun {
890*4882a593Smuzhiyun return mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_DRV, arg);
891*4882a593Smuzhiyun }
892*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(mtk_pinconf_drive_set_raw);
893*4882a593Smuzhiyun
mtk_pinconf_drive_get_raw(struct mtk_pinctrl * hw,const struct mtk_pin_desc * desc,int * val)894*4882a593Smuzhiyun int mtk_pinconf_drive_get_raw(struct mtk_pinctrl *hw,
895*4882a593Smuzhiyun const struct mtk_pin_desc *desc, int *val)
896*4882a593Smuzhiyun {
897*4882a593Smuzhiyun return mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_DRV, val);
898*4882a593Smuzhiyun }
899*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(mtk_pinconf_drive_get_raw);
900*4882a593Smuzhiyun
mtk_pinconf_adv_pull_set(struct mtk_pinctrl * hw,const struct mtk_pin_desc * desc,bool pullup,u32 arg)901*4882a593Smuzhiyun int mtk_pinconf_adv_pull_set(struct mtk_pinctrl *hw,
902*4882a593Smuzhiyun const struct mtk_pin_desc *desc, bool pullup,
903*4882a593Smuzhiyun u32 arg)
904*4882a593Smuzhiyun {
905*4882a593Smuzhiyun int err;
906*4882a593Smuzhiyun
907*4882a593Smuzhiyun /* 10K off & 50K (75K) off, when (R0, R1) = (0, 0);
908*4882a593Smuzhiyun * 10K off & 50K (75K) on, when (R0, R1) = (0, 1);
909*4882a593Smuzhiyun * 10K on & 50K (75K) off, when (R0, R1) = (1, 0);
910*4882a593Smuzhiyun * 10K on & 50K (75K) on, when (R0, R1) = (1, 1)
911*4882a593Smuzhiyun */
912*4882a593Smuzhiyun err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_R0, arg & 1);
913*4882a593Smuzhiyun if (err)
914*4882a593Smuzhiyun return 0;
915*4882a593Smuzhiyun
916*4882a593Smuzhiyun err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_R1,
917*4882a593Smuzhiyun !!(arg & 2));
918*4882a593Smuzhiyun if (err)
919*4882a593Smuzhiyun return 0;
920*4882a593Smuzhiyun
921*4882a593Smuzhiyun arg = pullup ? 0 : 1;
922*4882a593Smuzhiyun
923*4882a593Smuzhiyun err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_PUPD, arg);
924*4882a593Smuzhiyun
925*4882a593Smuzhiyun /* If PUPD register is not supported for that pin, let's fallback to
926*4882a593Smuzhiyun * general bias control.
927*4882a593Smuzhiyun */
928*4882a593Smuzhiyun if (err == -ENOTSUPP) {
929*4882a593Smuzhiyun if (hw->soc->bias_set) {
930*4882a593Smuzhiyun err = hw->soc->bias_set(hw, desc, pullup);
931*4882a593Smuzhiyun if (err)
932*4882a593Smuzhiyun return err;
933*4882a593Smuzhiyun } else {
934*4882a593Smuzhiyun err = mtk_pinconf_bias_set_rev1(hw, desc, pullup);
935*4882a593Smuzhiyun if (err)
936*4882a593Smuzhiyun err = mtk_pinconf_bias_set(hw, desc, pullup);
937*4882a593Smuzhiyun }
938*4882a593Smuzhiyun }
939*4882a593Smuzhiyun
940*4882a593Smuzhiyun return err;
941*4882a593Smuzhiyun }
942*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(mtk_pinconf_adv_pull_set);
943*4882a593Smuzhiyun
mtk_pinconf_adv_pull_get(struct mtk_pinctrl * hw,const struct mtk_pin_desc * desc,bool pullup,u32 * val)944*4882a593Smuzhiyun int mtk_pinconf_adv_pull_get(struct mtk_pinctrl *hw,
945*4882a593Smuzhiyun const struct mtk_pin_desc *desc, bool pullup,
946*4882a593Smuzhiyun u32 *val)
947*4882a593Smuzhiyun {
948*4882a593Smuzhiyun u32 t, t2;
949*4882a593Smuzhiyun int err;
950*4882a593Smuzhiyun
951*4882a593Smuzhiyun err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_PUPD, &t);
952*4882a593Smuzhiyun
953*4882a593Smuzhiyun /* If PUPD register is not supported for that pin, let's fallback to
954*4882a593Smuzhiyun * general bias control.
955*4882a593Smuzhiyun */
956*4882a593Smuzhiyun if (err == -ENOTSUPP) {
957*4882a593Smuzhiyun if (hw->soc->bias_get) {
958*4882a593Smuzhiyun err = hw->soc->bias_get(hw, desc, pullup, val);
959*4882a593Smuzhiyun if (err)
960*4882a593Smuzhiyun return err;
961*4882a593Smuzhiyun } else {
962*4882a593Smuzhiyun return -ENOTSUPP;
963*4882a593Smuzhiyun }
964*4882a593Smuzhiyun } else {
965*4882a593Smuzhiyun /* t == 0 supposes PULLUP for the customized PULL setup */
966*4882a593Smuzhiyun if (err)
967*4882a593Smuzhiyun return err;
968*4882a593Smuzhiyun
969*4882a593Smuzhiyun if (pullup ^ !t)
970*4882a593Smuzhiyun return -EINVAL;
971*4882a593Smuzhiyun }
972*4882a593Smuzhiyun
973*4882a593Smuzhiyun err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_R0, &t);
974*4882a593Smuzhiyun if (err)
975*4882a593Smuzhiyun return err;
976*4882a593Smuzhiyun
977*4882a593Smuzhiyun err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_R1, &t2);
978*4882a593Smuzhiyun if (err)
979*4882a593Smuzhiyun return err;
980*4882a593Smuzhiyun
981*4882a593Smuzhiyun *val = (t | t2 << 1) & 0x7;
982*4882a593Smuzhiyun
983*4882a593Smuzhiyun return 0;
984*4882a593Smuzhiyun }
985*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(mtk_pinconf_adv_pull_get);
986*4882a593Smuzhiyun
mtk_pinconf_adv_drive_set(struct mtk_pinctrl * hw,const struct mtk_pin_desc * desc,u32 arg)987*4882a593Smuzhiyun int mtk_pinconf_adv_drive_set(struct mtk_pinctrl *hw,
988*4882a593Smuzhiyun const struct mtk_pin_desc *desc, u32 arg)
989*4882a593Smuzhiyun {
990*4882a593Smuzhiyun int err;
991*4882a593Smuzhiyun int en = arg & 1;
992*4882a593Smuzhiyun int e0 = !!(arg & 2);
993*4882a593Smuzhiyun int e1 = !!(arg & 4);
994*4882a593Smuzhiyun
995*4882a593Smuzhiyun err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_DRV_EN, en);
996*4882a593Smuzhiyun if (err)
997*4882a593Smuzhiyun return err;
998*4882a593Smuzhiyun
999*4882a593Smuzhiyun if (!en)
1000*4882a593Smuzhiyun return err;
1001*4882a593Smuzhiyun
1002*4882a593Smuzhiyun err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_DRV_E0, e0);
1003*4882a593Smuzhiyun if (err)
1004*4882a593Smuzhiyun return err;
1005*4882a593Smuzhiyun
1006*4882a593Smuzhiyun err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_DRV_E1, e1);
1007*4882a593Smuzhiyun if (err)
1008*4882a593Smuzhiyun return err;
1009*4882a593Smuzhiyun
1010*4882a593Smuzhiyun return err;
1011*4882a593Smuzhiyun }
1012*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(mtk_pinconf_adv_drive_set);
1013*4882a593Smuzhiyun
mtk_pinconf_adv_drive_get(struct mtk_pinctrl * hw,const struct mtk_pin_desc * desc,u32 * val)1014*4882a593Smuzhiyun int mtk_pinconf_adv_drive_get(struct mtk_pinctrl *hw,
1015*4882a593Smuzhiyun const struct mtk_pin_desc *desc, u32 *val)
1016*4882a593Smuzhiyun {
1017*4882a593Smuzhiyun u32 en, e0, e1;
1018*4882a593Smuzhiyun int err;
1019*4882a593Smuzhiyun
1020*4882a593Smuzhiyun err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_DRV_EN, &en);
1021*4882a593Smuzhiyun if (err)
1022*4882a593Smuzhiyun return err;
1023*4882a593Smuzhiyun
1024*4882a593Smuzhiyun err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_DRV_E0, &e0);
1025*4882a593Smuzhiyun if (err)
1026*4882a593Smuzhiyun return err;
1027*4882a593Smuzhiyun
1028*4882a593Smuzhiyun err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_DRV_E1, &e1);
1029*4882a593Smuzhiyun if (err)
1030*4882a593Smuzhiyun return err;
1031*4882a593Smuzhiyun
1032*4882a593Smuzhiyun *val = (en | e0 << 1 | e1 << 2) & 0x7;
1033*4882a593Smuzhiyun
1034*4882a593Smuzhiyun return 0;
1035*4882a593Smuzhiyun }
1036*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(mtk_pinconf_adv_drive_get);
1037*4882a593Smuzhiyun
1038*4882a593Smuzhiyun MODULE_LICENSE("GPL v2");
1039*4882a593Smuzhiyun MODULE_AUTHOR("Sean Wang <sean.wang@mediatek.com>");
1040*4882a593Smuzhiyun MODULE_DESCRIPTION("Pin configuration library module for mediatek SoCs");
1041