xref: /linux/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.c (revision 6e737a4e921ea99125955d0d8821d8da129b03bd)
1a1a503a8SSean Wang // SPDX-License-Identifier: GPL-2.0
2a1a503a8SSean Wang /*
3a1a503a8SSean Wang  * Copyright (C) 2018 MediaTek Inc.
4a1a503a8SSean Wang  *
5a1a503a8SSean Wang  * Author: Sean Wang <sean.wang@mediatek.com>
6a1a503a8SSean Wang  *
7a1a503a8SSean Wang  */
8a1a503a8SSean Wang 
9a1a503a8SSean Wang #include <linux/device.h>
10a1a503a8SSean Wang #include <linux/err.h>
1122d7fe49SLinus Walleij #include <linux/gpio/driver.h>
1289132dd8SSean Wang #include <linux/platform_device.h>
13a1a503a8SSean Wang #include <linux/io.h>
1489132dd8SSean Wang #include <linux/of_irq.h>
15a1a503a8SSean Wang 
1689132dd8SSean Wang #include "mtk-eint.h"
17a1a503a8SSean Wang #include "pinctrl-mtk-common-v2.h"
18a1a503a8SSean Wang 
19c2832197SSean Wang /**
20c2832197SSean Wang  * struct mtk_drive_desc - the structure that holds the information
21c2832197SSean Wang  *			    of the driving current
22c2832197SSean Wang  * @min:	the minimum current of this group
23c2832197SSean Wang  * @max:	the maximum current of this group
24c2832197SSean Wang  * @step:	the step current of this group
25c2832197SSean Wang  * @scal:	the weight factor
26c2832197SSean Wang  *
27c2832197SSean Wang  * formula: output = ((input) / step - 1) * scal
28c2832197SSean Wang  */
29c2832197SSean Wang struct mtk_drive_desc {
30c2832197SSean Wang 	u8 min;
31c2832197SSean Wang 	u8 max;
32c2832197SSean Wang 	u8 step;
33c2832197SSean Wang 	u8 scal;
34c2832197SSean Wang };
35c2832197SSean Wang 
36c2832197SSean Wang /* The groups of drive strength */
3707c6b037SWei Yongjun static const struct mtk_drive_desc mtk_drive[] = {
38c2832197SSean Wang 	[DRV_GRP0] = { 4, 16, 4, 1 },
39c2832197SSean Wang 	[DRV_GRP1] = { 4, 16, 4, 2 },
40c2832197SSean Wang 	[DRV_GRP2] = { 2, 8, 2, 1 },
41c2832197SSean Wang 	[DRV_GRP3] = { 2, 8, 2, 2 },
42c2832197SSean Wang 	[DRV_GRP4] = { 2, 16, 2, 1 },
43c2832197SSean Wang };
44c2832197SSean Wang 
452bc47dfeSSean Wang static void mtk_w32(struct mtk_pinctrl *pctl, u8 i, u32 reg, u32 val)
46a1a503a8SSean Wang {
472bc47dfeSSean Wang 	writel_relaxed(val, pctl->base[i] + reg);
48a1a503a8SSean Wang }
49a1a503a8SSean Wang 
502bc47dfeSSean Wang static u32 mtk_r32(struct mtk_pinctrl *pctl, u8 i, u32 reg)
51a1a503a8SSean Wang {
522bc47dfeSSean Wang 	return readl_relaxed(pctl->base[i] + reg);
53a1a503a8SSean Wang }
54a1a503a8SSean Wang 
552bc47dfeSSean Wang void mtk_rmw(struct mtk_pinctrl *pctl, u8 i, u32 reg, u32 mask, u32 set)
56a1a503a8SSean Wang {
57a1a503a8SSean Wang 	u32 val;
58a1a503a8SSean Wang 
592bc47dfeSSean Wang 	val = mtk_r32(pctl, i, reg);
60a1a503a8SSean Wang 	val &= ~mask;
61a1a503a8SSean Wang 	val |= set;
622bc47dfeSSean Wang 	mtk_w32(pctl, i, reg, val);
63a1a503a8SSean Wang }
64a1a503a8SSean Wang 
65ea051eb3SSean Wang static int mtk_hw_pin_field_lookup(struct mtk_pinctrl *hw,
66ea051eb3SSean Wang 				   const struct mtk_pin_desc *desc,
679d9b171cSSean Wang 				   int field, struct mtk_pin_field *pfd)
68a1a503a8SSean Wang {
69a1a503a8SSean Wang 	const struct mtk_pin_field_calc *c, *e;
709d9b171cSSean Wang 	const struct mtk_pin_reg_calc *rc;
71a1a503a8SSean Wang 	u32 bits;
72a1a503a8SSean Wang 
739d9b171cSSean Wang 	if (hw->soc->reg_cal && hw->soc->reg_cal[field].range) {
749d9b171cSSean Wang 		rc = &hw->soc->reg_cal[field];
759d9b171cSSean Wang 	} else {
769d9b171cSSean Wang 		dev_dbg(hw->dev,
779d9b171cSSean Wang 			"Not support field %d for pin %d (%s)\n",
789d9b171cSSean Wang 			field, desc->number, desc->name);
799d9b171cSSean Wang 		return -ENOTSUPP;
809d9b171cSSean Wang 	}
819d9b171cSSean Wang 
82a1a503a8SSean Wang 	c = rc->range;
83a1a503a8SSean Wang 	e = c + rc->nranges;
84a1a503a8SSean Wang 
85a1a503a8SSean Wang 	while (c < e) {
86ea051eb3SSean Wang 		if (desc->number >= c->s_pin && desc->number <= c->e_pin)
87a1a503a8SSean Wang 			break;
88a1a503a8SSean Wang 		c++;
89a1a503a8SSean Wang 	}
90a1a503a8SSean Wang 
91a1a503a8SSean Wang 	if (c >= e) {
929d9b171cSSean Wang 		dev_dbg(hw->dev, "Not support field %d for pin = %d (%s)\n",
939d9b171cSSean Wang 			field, desc->number, desc->name);
949d9b171cSSean Wang 		return -ENOTSUPP;
95a1a503a8SSean Wang 	}
96a1a503a8SSean Wang 
972bc47dfeSSean Wang 	if (c->i_base > hw->nbase - 1) {
989d9b171cSSean Wang 		dev_err(hw->dev,
999d9b171cSSean Wang 			"Invalid base for field %d for pin = %d (%s)\n",
1009d9b171cSSean Wang 			field, desc->number, desc->name);
1012bc47dfeSSean Wang 		return -EINVAL;
1022bc47dfeSSean Wang 	}
1032bc47dfeSSean Wang 
104b906faf7SSean Wang 	/* Calculated bits as the overall offset the pin is located at,
105b906faf7SSean Wang 	 * if c->fixed is held, that determines the all the pins in the
106b906faf7SSean Wang 	 * range use the same field with the s_pin.
107b906faf7SSean Wang 	 */
108ea051eb3SSean Wang 	bits = c->fixed ? c->s_bit : c->s_bit +
109ea051eb3SSean Wang 	       (desc->number - c->s_pin) * (c->x_bits);
110a1a503a8SSean Wang 
111b906faf7SSean Wang 	/* Fill pfd from bits. For example 32-bit register applied is assumed
112b906faf7SSean Wang 	 * when c->sz_reg is equal to 32.
113b906faf7SSean Wang 	 */
1142bc47dfeSSean Wang 	pfd->index = c->i_base;
115b906faf7SSean Wang 	pfd->offset = c->s_addr + c->x_addrs * (bits / c->sz_reg);
116b906faf7SSean Wang 	pfd->bitpos = bits % c->sz_reg;
117a1a503a8SSean Wang 	pfd->mask = (1 << c->x_bits) - 1;
118a1a503a8SSean Wang 
119a1a503a8SSean Wang 	/* pfd->next is used for indicating that bit wrapping-around happens
120a1a503a8SSean Wang 	 * which requires the manipulation for bit 0 starting in the next
121a1a503a8SSean Wang 	 * register to form the complete field read/write.
122a1a503a8SSean Wang 	 */
123b906faf7SSean Wang 	pfd->next = pfd->bitpos + c->x_bits > c->sz_reg ? c->x_addrs : 0;
124a1a503a8SSean Wang 
125a1a503a8SSean Wang 	return 0;
126a1a503a8SSean Wang }
127a1a503a8SSean Wang 
128ea051eb3SSean Wang static int mtk_hw_pin_field_get(struct mtk_pinctrl *hw,
129ea051eb3SSean Wang 				const struct mtk_pin_desc *desc,
130a1a503a8SSean Wang 				int field, struct mtk_pin_field *pfd)
131a1a503a8SSean Wang {
132a1a503a8SSean Wang 	if (field < 0 || field >= PINCTRL_PIN_REG_MAX) {
133a1a503a8SSean Wang 		dev_err(hw->dev, "Invalid Field %d\n", field);
134a1a503a8SSean Wang 		return -EINVAL;
135a1a503a8SSean Wang 	}
136a1a503a8SSean Wang 
1379d9b171cSSean Wang 	return mtk_hw_pin_field_lookup(hw, desc, field, pfd);
138a1a503a8SSean Wang }
139a1a503a8SSean Wang 
140a1a503a8SSean Wang static void mtk_hw_bits_part(struct mtk_pin_field *pf, int *h, int *l)
141a1a503a8SSean Wang {
142a1a503a8SSean Wang 	*l = 32 - pf->bitpos;
143a1a503a8SSean Wang 	*h = get_count_order(pf->mask) - *l;
144a1a503a8SSean Wang }
145a1a503a8SSean Wang 
146a1a503a8SSean Wang static void mtk_hw_write_cross_field(struct mtk_pinctrl *hw,
147a1a503a8SSean Wang 				     struct mtk_pin_field *pf, int value)
148a1a503a8SSean Wang {
149a1a503a8SSean Wang 	int nbits_l, nbits_h;
150a1a503a8SSean Wang 
151a1a503a8SSean Wang 	mtk_hw_bits_part(pf, &nbits_h, &nbits_l);
152a1a503a8SSean Wang 
1532bc47dfeSSean Wang 	mtk_rmw(hw, pf->index, pf->offset, pf->mask << pf->bitpos,
154a1a503a8SSean Wang 		(value & pf->mask) << pf->bitpos);
155a1a503a8SSean Wang 
1562bc47dfeSSean Wang 	mtk_rmw(hw, pf->index, pf->offset + pf->next, BIT(nbits_h) - 1,
157a1a503a8SSean Wang 		(value & pf->mask) >> nbits_l);
158a1a503a8SSean Wang }
159a1a503a8SSean Wang 
160a1a503a8SSean Wang static void mtk_hw_read_cross_field(struct mtk_pinctrl *hw,
161a1a503a8SSean Wang 				    struct mtk_pin_field *pf, int *value)
162a1a503a8SSean Wang {
163a1a503a8SSean Wang 	int nbits_l, nbits_h, h, l;
164a1a503a8SSean Wang 
165a1a503a8SSean Wang 	mtk_hw_bits_part(pf, &nbits_h, &nbits_l);
166a1a503a8SSean Wang 
1672bc47dfeSSean Wang 	l  = (mtk_r32(hw, pf->index, pf->offset)
1682bc47dfeSSean Wang 	      >> pf->bitpos) & (BIT(nbits_l) - 1);
1692bc47dfeSSean Wang 	h  = (mtk_r32(hw, pf->index, pf->offset + pf->next))
1702bc47dfeSSean Wang 	      & (BIT(nbits_h) - 1);
171a1a503a8SSean Wang 
172a1a503a8SSean Wang 	*value = (h << nbits_l) | l;
173a1a503a8SSean Wang }
174a1a503a8SSean Wang 
175ea051eb3SSean Wang int mtk_hw_set_value(struct mtk_pinctrl *hw, const struct mtk_pin_desc *desc,
176ea051eb3SSean Wang 		     int field, int value)
177a1a503a8SSean Wang {
178a1a503a8SSean Wang 	struct mtk_pin_field pf;
179a1a503a8SSean Wang 	int err;
180a1a503a8SSean Wang 
181ea051eb3SSean Wang 	err = mtk_hw_pin_field_get(hw, desc, field, &pf);
182a1a503a8SSean Wang 	if (err)
183a1a503a8SSean Wang 		return err;
184a1a503a8SSean Wang 
185a1a503a8SSean Wang 	if (!pf.next)
1862bc47dfeSSean Wang 		mtk_rmw(hw, pf.index, pf.offset, pf.mask << pf.bitpos,
187a1a503a8SSean Wang 			(value & pf.mask) << pf.bitpos);
188a1a503a8SSean Wang 	else
189a1a503a8SSean Wang 		mtk_hw_write_cross_field(hw, &pf, value);
190a1a503a8SSean Wang 
191a1a503a8SSean Wang 	return 0;
192a1a503a8SSean Wang }
193a1a503a8SSean Wang 
194ea051eb3SSean Wang int mtk_hw_get_value(struct mtk_pinctrl *hw, const struct mtk_pin_desc *desc,
195ea051eb3SSean Wang 		     int field, int *value)
196a1a503a8SSean Wang {
197a1a503a8SSean Wang 	struct mtk_pin_field pf;
198a1a503a8SSean Wang 	int err;
199a1a503a8SSean Wang 
200ea051eb3SSean Wang 	err = mtk_hw_pin_field_get(hw, desc, field, &pf);
201a1a503a8SSean Wang 	if (err)
202a1a503a8SSean Wang 		return err;
203a1a503a8SSean Wang 
204a1a503a8SSean Wang 	if (!pf.next)
2052bc47dfeSSean Wang 		*value = (mtk_r32(hw, pf.index, pf.offset)
2062bc47dfeSSean Wang 			  >> pf.bitpos) & pf.mask;
207a1a503a8SSean Wang 	else
208a1a503a8SSean Wang 		mtk_hw_read_cross_field(hw, &pf, value);
209a1a503a8SSean Wang 
210a1a503a8SSean Wang 	return 0;
211a1a503a8SSean Wang }
212c2832197SSean Wang 
21389132dd8SSean Wang static int mtk_xt_find_eint_num(struct mtk_pinctrl *hw, unsigned long eint_n)
21489132dd8SSean Wang {
21589132dd8SSean Wang 	const struct mtk_pin_desc *desc;
21689132dd8SSean Wang 	int i = 0;
21789132dd8SSean Wang 
21889132dd8SSean Wang 	desc = (const struct mtk_pin_desc *)hw->soc->pins;
21989132dd8SSean Wang 
22089132dd8SSean Wang 	while (i < hw->soc->npins) {
22189132dd8SSean Wang 		if (desc[i].eint.eint_n == eint_n)
22289132dd8SSean Wang 			return desc[i].number;
22389132dd8SSean Wang 		i++;
22489132dd8SSean Wang 	}
22589132dd8SSean Wang 
22689132dd8SSean Wang 	return EINT_NA;
22789132dd8SSean Wang }
22889132dd8SSean Wang 
22989132dd8SSean Wang static int mtk_xt_get_gpio_n(void *data, unsigned long eint_n,
23089132dd8SSean Wang 			     unsigned int *gpio_n,
23189132dd8SSean Wang 			     struct gpio_chip **gpio_chip)
23289132dd8SSean Wang {
23389132dd8SSean Wang 	struct mtk_pinctrl *hw = (struct mtk_pinctrl *)data;
23489132dd8SSean Wang 	const struct mtk_pin_desc *desc;
23589132dd8SSean Wang 
23689132dd8SSean Wang 	desc = (const struct mtk_pin_desc *)hw->soc->pins;
23789132dd8SSean Wang 	*gpio_chip = &hw->chip;
23889132dd8SSean Wang 
23989132dd8SSean Wang 	/* Be greedy to guess first gpio_n is equal to eint_n */
24089132dd8SSean Wang 	if (desc[eint_n].eint.eint_n == eint_n)
24189132dd8SSean Wang 		*gpio_n = eint_n;
24289132dd8SSean Wang 	else
24389132dd8SSean Wang 		*gpio_n = mtk_xt_find_eint_num(hw, eint_n);
24489132dd8SSean Wang 
24589132dd8SSean Wang 	return *gpio_n == EINT_NA ? -EINVAL : 0;
24689132dd8SSean Wang }
24789132dd8SSean Wang 
24889132dd8SSean Wang static int mtk_xt_get_gpio_state(void *data, unsigned long eint_n)
24989132dd8SSean Wang {
25089132dd8SSean Wang 	struct mtk_pinctrl *hw = (struct mtk_pinctrl *)data;
25189132dd8SSean Wang 	const struct mtk_pin_desc *desc;
25289132dd8SSean Wang 	struct gpio_chip *gpio_chip;
25389132dd8SSean Wang 	unsigned int gpio_n;
25489132dd8SSean Wang 	int value, err;
25589132dd8SSean Wang 
25689132dd8SSean Wang 	err = mtk_xt_get_gpio_n(hw, eint_n, &gpio_n, &gpio_chip);
25789132dd8SSean Wang 	if (err)
25889132dd8SSean Wang 		return err;
25989132dd8SSean Wang 
26089132dd8SSean Wang 	desc = (const struct mtk_pin_desc *)&hw->soc->pins[gpio_n];
26189132dd8SSean Wang 
26289132dd8SSean Wang 	err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_DI, &value);
26389132dd8SSean Wang 	if (err)
26489132dd8SSean Wang 		return err;
26589132dd8SSean Wang 
26689132dd8SSean Wang 	return !!value;
26789132dd8SSean Wang }
26889132dd8SSean Wang 
26989132dd8SSean Wang static int mtk_xt_set_gpio_as_eint(void *data, unsigned long eint_n)
27089132dd8SSean Wang {
27189132dd8SSean Wang 	struct mtk_pinctrl *hw = (struct mtk_pinctrl *)data;
27289132dd8SSean Wang 	const struct mtk_pin_desc *desc;
27389132dd8SSean Wang 	struct gpio_chip *gpio_chip;
27489132dd8SSean Wang 	unsigned int gpio_n;
27589132dd8SSean Wang 	int err;
27689132dd8SSean Wang 
27789132dd8SSean Wang 	err = mtk_xt_get_gpio_n(hw, eint_n, &gpio_n, &gpio_chip);
27889132dd8SSean Wang 	if (err)
27989132dd8SSean Wang 		return err;
28089132dd8SSean Wang 
28189132dd8SSean Wang 	desc = (const struct mtk_pin_desc *)&hw->soc->pins[gpio_n];
28289132dd8SSean Wang 
28389132dd8SSean Wang 	err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_MODE,
28489132dd8SSean Wang 			       desc->eint.eint_m);
28589132dd8SSean Wang 	if (err)
28689132dd8SSean Wang 		return err;
28789132dd8SSean Wang 
28889132dd8SSean Wang 	err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_DIR, MTK_INPUT);
28989132dd8SSean Wang 	if (err)
29089132dd8SSean Wang 		return err;
29189132dd8SSean Wang 
29289132dd8SSean Wang 	err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_SMT, MTK_ENABLE);
293*6e737a4eSchuanjia.liu 	/* SMT is supposed to be supported by every real GPIO and doesn't
294*6e737a4eSchuanjia.liu 	 * support virtual GPIOs, so the extra condition err != -ENOTSUPP
295*6e737a4eSchuanjia.liu 	 * is just for adding EINT support to these virtual GPIOs. It should
296*6e737a4eSchuanjia.liu 	 * add an extra flag in the pin descriptor when more pins with
297*6e737a4eSchuanjia.liu 	 * distinctive characteristic come out.
298*6e737a4eSchuanjia.liu 	 */
299*6e737a4eSchuanjia.liu 	if (err && err != -ENOTSUPP)
30089132dd8SSean Wang 		return err;
30189132dd8SSean Wang 
30289132dd8SSean Wang 	return 0;
30389132dd8SSean Wang }
30489132dd8SSean Wang 
30589132dd8SSean Wang static const struct mtk_eint_xt mtk_eint_xt = {
30689132dd8SSean Wang 	.get_gpio_n = mtk_xt_get_gpio_n,
30789132dd8SSean Wang 	.get_gpio_state = mtk_xt_get_gpio_state,
30889132dd8SSean Wang 	.set_gpio_as_eint = mtk_xt_set_gpio_as_eint,
30989132dd8SSean Wang };
31089132dd8SSean Wang 
31189132dd8SSean Wang int mtk_build_eint(struct mtk_pinctrl *hw, struct platform_device *pdev)
31289132dd8SSean Wang {
31389132dd8SSean Wang 	struct device_node *np = pdev->dev.of_node;
31489132dd8SSean Wang 	struct resource *res;
31589132dd8SSean Wang 
31689132dd8SSean Wang 	if (!IS_ENABLED(CONFIG_EINT_MTK))
31789132dd8SSean Wang 		return 0;
31889132dd8SSean Wang 
31989132dd8SSean Wang 	if (!of_property_read_bool(np, "interrupt-controller"))
32089132dd8SSean Wang 		return -ENODEV;
32189132dd8SSean Wang 
32289132dd8SSean Wang 	hw->eint = devm_kzalloc(hw->dev, sizeof(*hw->eint), GFP_KERNEL);
32389132dd8SSean Wang 	if (!hw->eint)
32489132dd8SSean Wang 		return -ENOMEM;
32589132dd8SSean Wang 
32689132dd8SSean Wang 	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "eint");
32789132dd8SSean Wang 	if (!res) {
32889132dd8SSean Wang 		dev_err(&pdev->dev, "Unable to get eint resource\n");
32989132dd8SSean Wang 		return -ENODEV;
33089132dd8SSean Wang 	}
33189132dd8SSean Wang 
33289132dd8SSean Wang 	hw->eint->base = devm_ioremap_resource(&pdev->dev, res);
33389132dd8SSean Wang 	if (IS_ERR(hw->eint->base))
33489132dd8SSean Wang 		return PTR_ERR(hw->eint->base);
33589132dd8SSean Wang 
33689132dd8SSean Wang 	hw->eint->irq = irq_of_parse_and_map(np, 0);
33789132dd8SSean Wang 	if (!hw->eint->irq)
33889132dd8SSean Wang 		return -EINVAL;
33989132dd8SSean Wang 
34089132dd8SSean Wang 	if (!hw->soc->eint_hw)
34189132dd8SSean Wang 		return -ENODEV;
34289132dd8SSean Wang 
34389132dd8SSean Wang 	hw->eint->dev = &pdev->dev;
34489132dd8SSean Wang 	hw->eint->hw = hw->soc->eint_hw;
34589132dd8SSean Wang 	hw->eint->pctl = hw;
34689132dd8SSean Wang 	hw->eint->gpio_xlate = &mtk_eint_xt;
34789132dd8SSean Wang 
34889132dd8SSean Wang 	return mtk_eint_do_init(hw->eint);
34989132dd8SSean Wang }
35089132dd8SSean Wang 
3519afc305bSSean Wang /* Revision 0 */
35285430152SSean Wang int mtk_pinconf_bias_disable_set(struct mtk_pinctrl *hw,
35385430152SSean Wang 				 const struct mtk_pin_desc *desc)
35485430152SSean Wang {
35585430152SSean Wang 	int err;
35685430152SSean Wang 
357ea051eb3SSean Wang 	err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_PU,
35885430152SSean Wang 			       MTK_DISABLE);
35985430152SSean Wang 	if (err)
36085430152SSean Wang 		return err;
36185430152SSean Wang 
362ea051eb3SSean Wang 	err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_PD,
36385430152SSean Wang 			       MTK_DISABLE);
36485430152SSean Wang 	if (err)
36585430152SSean Wang 		return err;
36685430152SSean Wang 
36785430152SSean Wang 	return 0;
36885430152SSean Wang }
36985430152SSean Wang 
37085430152SSean Wang int mtk_pinconf_bias_disable_get(struct mtk_pinctrl *hw,
37185430152SSean Wang 				 const struct mtk_pin_desc *desc, int *res)
37285430152SSean Wang {
37385430152SSean Wang 	int v, v2;
37485430152SSean Wang 	int err;
37585430152SSean Wang 
376ea051eb3SSean Wang 	err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_PU, &v);
37785430152SSean Wang 	if (err)
37885430152SSean Wang 		return err;
37985430152SSean Wang 
380ea051eb3SSean Wang 	err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_PD, &v2);
38185430152SSean Wang 	if (err)
38285430152SSean Wang 		return err;
38385430152SSean Wang 
38485430152SSean Wang 	if (v == MTK_ENABLE || v2 == MTK_ENABLE)
38585430152SSean Wang 		return -EINVAL;
38685430152SSean Wang 
38785430152SSean Wang 	*res = 1;
38885430152SSean Wang 
38985430152SSean Wang 	return 0;
39085430152SSean Wang }
39185430152SSean Wang 
39285430152SSean Wang int mtk_pinconf_bias_set(struct mtk_pinctrl *hw,
39385430152SSean Wang 			 const struct mtk_pin_desc *desc, bool pullup)
39485430152SSean Wang {
39585430152SSean Wang 	int err, arg;
39685430152SSean Wang 
39785430152SSean Wang 	arg = pullup ? 1 : 2;
39885430152SSean Wang 
399ea051eb3SSean Wang 	err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_PU, arg & 1);
40085430152SSean Wang 	if (err)
40185430152SSean Wang 		return err;
40285430152SSean Wang 
403ea051eb3SSean Wang 	err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_PD,
40485430152SSean Wang 			       !!(arg & 2));
40585430152SSean Wang 	if (err)
40685430152SSean Wang 		return err;
40785430152SSean Wang 
40885430152SSean Wang 	return 0;
40985430152SSean Wang }
41085430152SSean Wang 
41185430152SSean Wang int mtk_pinconf_bias_get(struct mtk_pinctrl *hw,
41285430152SSean Wang 			 const struct mtk_pin_desc *desc, bool pullup, int *res)
41385430152SSean Wang {
41485430152SSean Wang 	int reg, err, v;
41585430152SSean Wang 
41685430152SSean Wang 	reg = pullup ? PINCTRL_PIN_REG_PU : PINCTRL_PIN_REG_PD;
41785430152SSean Wang 
418ea051eb3SSean Wang 	err = mtk_hw_get_value(hw, desc, reg, &v);
41985430152SSean Wang 	if (err)
42085430152SSean Wang 		return err;
42185430152SSean Wang 
42285430152SSean Wang 	if (!v)
42385430152SSean Wang 		return -EINVAL;
42485430152SSean Wang 
42585430152SSean Wang 	*res = 1;
42685430152SSean Wang 
42785430152SSean Wang 	return 0;
42885430152SSean Wang }
42985430152SSean Wang 
4309afc305bSSean Wang /* Revision 1 */
4319afc305bSSean Wang int mtk_pinconf_bias_disable_set_rev1(struct mtk_pinctrl *hw,
4329afc305bSSean Wang 				      const struct mtk_pin_desc *desc)
4339afc305bSSean Wang {
4349afc305bSSean Wang 	int err;
4359afc305bSSean Wang 
436ea051eb3SSean Wang 	err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_PULLEN,
4379afc305bSSean Wang 			       MTK_DISABLE);
4389afc305bSSean Wang 	if (err)
4399afc305bSSean Wang 		return err;
4409afc305bSSean Wang 
4419afc305bSSean Wang 	return 0;
4429afc305bSSean Wang }
4439afc305bSSean Wang 
4449afc305bSSean Wang int mtk_pinconf_bias_disable_get_rev1(struct mtk_pinctrl *hw,
4459afc305bSSean Wang 				      const struct mtk_pin_desc *desc, int *res)
4469afc305bSSean Wang {
4479afc305bSSean Wang 	int v, err;
4489afc305bSSean Wang 
449ea051eb3SSean Wang 	err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_PULLEN, &v);
4509afc305bSSean Wang 	if (err)
4519afc305bSSean Wang 		return err;
4529afc305bSSean Wang 
4539afc305bSSean Wang 	if (v == MTK_ENABLE)
4549afc305bSSean Wang 		return -EINVAL;
4559afc305bSSean Wang 
4569afc305bSSean Wang 	*res = 1;
4579afc305bSSean Wang 
4589afc305bSSean Wang 	return 0;
4599afc305bSSean Wang }
4609afc305bSSean Wang 
4619afc305bSSean Wang int mtk_pinconf_bias_set_rev1(struct mtk_pinctrl *hw,
4629afc305bSSean Wang 			      const struct mtk_pin_desc *desc, bool pullup)
4639afc305bSSean Wang {
4649afc305bSSean Wang 	int err, arg;
4659afc305bSSean Wang 
4669afc305bSSean Wang 	arg = pullup ? MTK_PULLUP : MTK_PULLDOWN;
4679afc305bSSean Wang 
468ea051eb3SSean Wang 	err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_PULLEN,
4699afc305bSSean Wang 			       MTK_ENABLE);
4709afc305bSSean Wang 	if (err)
4719afc305bSSean Wang 		return err;
4729afc305bSSean Wang 
473ea051eb3SSean Wang 	err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_PULLSEL, arg);
4749afc305bSSean Wang 	if (err)
4759afc305bSSean Wang 		return err;
4769afc305bSSean Wang 
4779afc305bSSean Wang 	return 0;
4789afc305bSSean Wang }
4799afc305bSSean Wang 
4809afc305bSSean Wang int mtk_pinconf_bias_get_rev1(struct mtk_pinctrl *hw,
4819afc305bSSean Wang 			      const struct mtk_pin_desc *desc, bool pullup,
4829afc305bSSean Wang 			      int *res)
4839afc305bSSean Wang {
4849afc305bSSean Wang 	int err, v;
4859afc305bSSean Wang 
486ea051eb3SSean Wang 	err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_PULLEN, &v);
4879afc305bSSean Wang 	if (err)
4889afc305bSSean Wang 		return err;
4899afc305bSSean Wang 
4909afc305bSSean Wang 	if (v == MTK_DISABLE)
4919afc305bSSean Wang 		return -EINVAL;
4929afc305bSSean Wang 
493ea051eb3SSean Wang 	err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_PULLSEL, &v);
4949afc305bSSean Wang 	if (err)
4959afc305bSSean Wang 		return err;
4969afc305bSSean Wang 
4979afc305bSSean Wang 	if (pullup ^ (v == MTK_PULLUP))
4989afc305bSSean Wang 		return -EINVAL;
4999afc305bSSean Wang 
5009afc305bSSean Wang 	*res = 1;
5019afc305bSSean Wang 
5029afc305bSSean Wang 	return 0;
5039afc305bSSean Wang }
5049afc305bSSean Wang 
505c2832197SSean Wang /* Revision 0 */
506c2832197SSean Wang int mtk_pinconf_drive_set(struct mtk_pinctrl *hw,
507c2832197SSean Wang 			  const struct mtk_pin_desc *desc, u32 arg)
508c2832197SSean Wang {
509c2832197SSean Wang 	const struct mtk_drive_desc *tb;
510c2832197SSean Wang 	int err = -ENOTSUPP;
511c2832197SSean Wang 
512c2832197SSean Wang 	tb = &mtk_drive[desc->drv_n];
513c2832197SSean Wang 	/* 4mA when (e8, e4) = (0, 0)
514c2832197SSean Wang 	 * 8mA when (e8, e4) = (0, 1)
515c2832197SSean Wang 	 * 12mA when (e8, e4) = (1, 0)
516c2832197SSean Wang 	 * 16mA when (e8, e4) = (1, 1)
517c2832197SSean Wang 	 */
518c2832197SSean Wang 	if ((arg >= tb->min && arg <= tb->max) && !(arg % tb->step)) {
519c2832197SSean Wang 		arg = (arg / tb->step - 1) * tb->scal;
520ea051eb3SSean Wang 		err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_E4,
521c2832197SSean Wang 				       arg & 0x1);
522c2832197SSean Wang 		if (err)
523c2832197SSean Wang 			return err;
524c2832197SSean Wang 
525ea051eb3SSean Wang 		err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_E8,
526c2832197SSean Wang 				       (arg & 0x2) >> 1);
527c2832197SSean Wang 		if (err)
528c2832197SSean Wang 			return err;
529c2832197SSean Wang 	}
530c2832197SSean Wang 
531c2832197SSean Wang 	return err;
532c2832197SSean Wang }
533c2832197SSean Wang 
534c2832197SSean Wang int mtk_pinconf_drive_get(struct mtk_pinctrl *hw,
535c2832197SSean Wang 			  const struct mtk_pin_desc *desc, int *val)
536c2832197SSean Wang {
537c2832197SSean Wang 	const struct mtk_drive_desc *tb;
538c2832197SSean Wang 	int err, val1, val2;
539c2832197SSean Wang 
540c2832197SSean Wang 	tb = &mtk_drive[desc->drv_n];
541c2832197SSean Wang 
542ea051eb3SSean Wang 	err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_E4, &val1);
543c2832197SSean Wang 	if (err)
544c2832197SSean Wang 		return err;
545c2832197SSean Wang 
546ea051eb3SSean Wang 	err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_E8, &val2);
547c2832197SSean Wang 	if (err)
548c2832197SSean Wang 		return err;
549c2832197SSean Wang 
550c2832197SSean Wang 	/* 4mA when (e8, e4) = (0, 0); 8mA when (e8, e4) = (0, 1)
551c2832197SSean Wang 	 * 12mA when (e8, e4) = (1, 0); 16mA when (e8, e4) = (1, 1)
552c2832197SSean Wang 	 */
553c2832197SSean Wang 	*val = (((val2 << 1) + val1) / tb->scal + 1) * tb->step;
554c2832197SSean Wang 
555c2832197SSean Wang 	return 0;
556c2832197SSean Wang }
5573ad38a14SSean Wang 
5583ad38a14SSean Wang /* Revision 1 */
5593ad38a14SSean Wang int mtk_pinconf_drive_set_rev1(struct mtk_pinctrl *hw,
5603ad38a14SSean Wang 			       const struct mtk_pin_desc *desc, u32 arg)
5613ad38a14SSean Wang {
5623ad38a14SSean Wang 	const struct mtk_drive_desc *tb;
5633ad38a14SSean Wang 	int err = -ENOTSUPP;
5643ad38a14SSean Wang 
5653ad38a14SSean Wang 	tb = &mtk_drive[desc->drv_n];
5663ad38a14SSean Wang 
5673ad38a14SSean Wang 	if ((arg >= tb->min && arg <= tb->max) && !(arg % tb->step)) {
5683ad38a14SSean Wang 		arg = (arg / tb->step - 1) * tb->scal;
5693ad38a14SSean Wang 
570ea051eb3SSean Wang 		err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_DRV,
5713ad38a14SSean Wang 				       arg);
5723ad38a14SSean Wang 		if (err)
5733ad38a14SSean Wang 			return err;
5743ad38a14SSean Wang 	}
5753ad38a14SSean Wang 
5763ad38a14SSean Wang 	return err;
5773ad38a14SSean Wang }
5783ad38a14SSean Wang 
5793ad38a14SSean Wang int mtk_pinconf_drive_get_rev1(struct mtk_pinctrl *hw,
5803ad38a14SSean Wang 			       const struct mtk_pin_desc *desc, int *val)
5813ad38a14SSean Wang {
5823ad38a14SSean Wang 	const struct mtk_drive_desc *tb;
5833ad38a14SSean Wang 	int err, val1;
5843ad38a14SSean Wang 
5853ad38a14SSean Wang 	tb = &mtk_drive[desc->drv_n];
5863ad38a14SSean Wang 
587ea051eb3SSean Wang 	err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_DRV, &val1);
5883ad38a14SSean Wang 	if (err)
5893ad38a14SSean Wang 		return err;
5903ad38a14SSean Wang 
5913ad38a14SSean Wang 	*val = ((val1 & 0x7) / tb->scal + 1) * tb->step;
5923ad38a14SSean Wang 
5933ad38a14SSean Wang 	return 0;
5943ad38a14SSean Wang }
5950d7ca772SSean Wang 
5960d7ca772SSean Wang int mtk_pinconf_adv_pull_set(struct mtk_pinctrl *hw,
5970d7ca772SSean Wang 			     const struct mtk_pin_desc *desc, bool pullup,
5980d7ca772SSean Wang 			     u32 arg)
5990d7ca772SSean Wang {
6000d7ca772SSean Wang 	int err;
6010d7ca772SSean Wang 
6020d7ca772SSean Wang 	/* 10K off & 50K (75K) off, when (R0, R1) = (0, 0);
6030d7ca772SSean Wang 	 * 10K off & 50K (75K) on, when (R0, R1) = (0, 1);
6040d7ca772SSean Wang 	 * 10K on & 50K (75K) off, when (R0, R1) = (1, 0);
6050d7ca772SSean Wang 	 * 10K on & 50K (75K) on, when (R0, R1) = (1, 1)
6060d7ca772SSean Wang 	 */
607ea051eb3SSean Wang 	err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_R0, arg & 1);
6080d7ca772SSean Wang 	if (err)
6090d7ca772SSean Wang 		return 0;
6100d7ca772SSean Wang 
611ea051eb3SSean Wang 	err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_R1,
6120d7ca772SSean Wang 			       !!(arg & 2));
6130d7ca772SSean Wang 	if (err)
6140d7ca772SSean Wang 		return 0;
6150d7ca772SSean Wang 
6160d7ca772SSean Wang 	arg = pullup ? 0 : 1;
6170d7ca772SSean Wang 
618ea051eb3SSean Wang 	err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_PUPD, arg);
6190d7ca772SSean Wang 
62079348f6fSSean Wang 	/* If PUPD register is not supported for that pin, let's fallback to
62179348f6fSSean Wang 	 * general bias control.
62279348f6fSSean Wang 	 */
62379348f6fSSean Wang 	if (err == -ENOTSUPP) {
62479348f6fSSean Wang 		if (hw->soc->bias_set) {
62579348f6fSSean Wang 			err = hw->soc->bias_set(hw, desc, pullup);
62679348f6fSSean Wang 			if (err)
62779348f6fSSean Wang 				return err;
62879348f6fSSean Wang 		} else {
62979348f6fSSean Wang 			return -ENOTSUPP;
63079348f6fSSean Wang 		}
63179348f6fSSean Wang 	}
63279348f6fSSean Wang 
6330d7ca772SSean Wang 	return err;
6340d7ca772SSean Wang }
6350d7ca772SSean Wang 
6360d7ca772SSean Wang int mtk_pinconf_adv_pull_get(struct mtk_pinctrl *hw,
6370d7ca772SSean Wang 			     const struct mtk_pin_desc *desc, bool pullup,
6380d7ca772SSean Wang 			     u32 *val)
6390d7ca772SSean Wang {
6400d7ca772SSean Wang 	u32 t, t2;
6410d7ca772SSean Wang 	int err;
6420d7ca772SSean Wang 
643ea051eb3SSean Wang 	err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_PUPD, &t);
64479348f6fSSean Wang 
64579348f6fSSean Wang 	/* If PUPD register is not supported for that pin, let's fallback to
64679348f6fSSean Wang 	 * general bias control.
64779348f6fSSean Wang 	 */
64879348f6fSSean Wang 	if (err == -ENOTSUPP) {
64979348f6fSSean Wang 		if (hw->soc->bias_get) {
65079348f6fSSean Wang 			err = hw->soc->bias_get(hw, desc, pullup, val);
65179348f6fSSean Wang 			if (err)
65279348f6fSSean Wang 				return err;
65379348f6fSSean Wang 		} else {
65479348f6fSSean Wang 			return -ENOTSUPP;
65579348f6fSSean Wang 		}
65679348f6fSSean Wang 	} else {
65779348f6fSSean Wang 		/* t == 0 supposes PULLUP for the customized PULL setup */
6580d7ca772SSean Wang 		if (err)
6590d7ca772SSean Wang 			return err;
6600d7ca772SSean Wang 
6610d7ca772SSean Wang 		if (pullup ^ !t)
6620d7ca772SSean Wang 			return -EINVAL;
66379348f6fSSean Wang 	}
6640d7ca772SSean Wang 
665ea051eb3SSean Wang 	err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_R0, &t);
6660d7ca772SSean Wang 	if (err)
6670d7ca772SSean Wang 		return err;
6680d7ca772SSean Wang 
669ea051eb3SSean Wang 	err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_R1, &t2);
6700d7ca772SSean Wang 	if (err)
6710d7ca772SSean Wang 		return err;
6720d7ca772SSean Wang 
6730d7ca772SSean Wang 	*val = (t | t2 << 1) & 0x7;
6740d7ca772SSean Wang 
6750d7ca772SSean Wang 	return 0;
6760d7ca772SSean Wang }
677