xref: /OK3568_Linux_fs/kernel/drivers/pinctrl/mediatek/pinctrl-moore.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * MediaTek Pinctrl Moore Driver, which implement the generic dt-binding
4*4882a593Smuzhiyun  * pinctrl-bindings.txt for MediaTek SoC.
5*4882a593Smuzhiyun  *
6*4882a593Smuzhiyun  * Copyright (C) 2017-2018 MediaTek Inc.
7*4882a593Smuzhiyun  * Author: Sean Wang <sean.wang@mediatek.com>
8*4882a593Smuzhiyun  *
9*4882a593Smuzhiyun  */
10*4882a593Smuzhiyun 
11*4882a593Smuzhiyun #include <linux/gpio/driver.h>
12*4882a593Smuzhiyun #include "pinctrl-moore.h"
13*4882a593Smuzhiyun 
14*4882a593Smuzhiyun #define PINCTRL_PINCTRL_DEV		KBUILD_MODNAME
15*4882a593Smuzhiyun 
16*4882a593Smuzhiyun /* Custom pinconf parameters */
17*4882a593Smuzhiyun #define MTK_PIN_CONFIG_TDSEL	(PIN_CONFIG_END + 1)
18*4882a593Smuzhiyun #define MTK_PIN_CONFIG_RDSEL	(PIN_CONFIG_END + 2)
19*4882a593Smuzhiyun #define MTK_PIN_CONFIG_PU_ADV	(PIN_CONFIG_END + 3)
20*4882a593Smuzhiyun #define MTK_PIN_CONFIG_PD_ADV	(PIN_CONFIG_END + 4)
21*4882a593Smuzhiyun 
22*4882a593Smuzhiyun static const struct pinconf_generic_params mtk_custom_bindings[] = {
23*4882a593Smuzhiyun 	{"mediatek,tdsel",	MTK_PIN_CONFIG_TDSEL,		0},
24*4882a593Smuzhiyun 	{"mediatek,rdsel",	MTK_PIN_CONFIG_RDSEL,		0},
25*4882a593Smuzhiyun 	{"mediatek,pull-up-adv", MTK_PIN_CONFIG_PU_ADV,		1},
26*4882a593Smuzhiyun 	{"mediatek,pull-down-adv", MTK_PIN_CONFIG_PD_ADV,	1},
27*4882a593Smuzhiyun };
28*4882a593Smuzhiyun 
29*4882a593Smuzhiyun #ifdef CONFIG_DEBUG_FS
30*4882a593Smuzhiyun static const struct pin_config_item mtk_conf_items[] = {
31*4882a593Smuzhiyun 	PCONFDUMP(MTK_PIN_CONFIG_TDSEL, "tdsel", NULL, true),
32*4882a593Smuzhiyun 	PCONFDUMP(MTK_PIN_CONFIG_RDSEL, "rdsel", NULL, true),
33*4882a593Smuzhiyun 	PCONFDUMP(MTK_PIN_CONFIG_PU_ADV, "pu-adv", NULL, true),
34*4882a593Smuzhiyun 	PCONFDUMP(MTK_PIN_CONFIG_PD_ADV, "pd-adv", NULL, true),
35*4882a593Smuzhiyun };
36*4882a593Smuzhiyun #endif
37*4882a593Smuzhiyun 
mtk_pinmux_set_mux(struct pinctrl_dev * pctldev,unsigned int selector,unsigned int group)38*4882a593Smuzhiyun static int mtk_pinmux_set_mux(struct pinctrl_dev *pctldev,
39*4882a593Smuzhiyun 			      unsigned int selector, unsigned int group)
40*4882a593Smuzhiyun {
41*4882a593Smuzhiyun 	struct mtk_pinctrl *hw = pinctrl_dev_get_drvdata(pctldev);
42*4882a593Smuzhiyun 	struct function_desc *func;
43*4882a593Smuzhiyun 	struct group_desc *grp;
44*4882a593Smuzhiyun 	int i;
45*4882a593Smuzhiyun 
46*4882a593Smuzhiyun 	func = pinmux_generic_get_function(pctldev, selector);
47*4882a593Smuzhiyun 	if (!func)
48*4882a593Smuzhiyun 		return -EINVAL;
49*4882a593Smuzhiyun 
50*4882a593Smuzhiyun 	grp = pinctrl_generic_get_group(pctldev, group);
51*4882a593Smuzhiyun 	if (!grp)
52*4882a593Smuzhiyun 		return -EINVAL;
53*4882a593Smuzhiyun 
54*4882a593Smuzhiyun 	dev_dbg(pctldev->dev, "enable function %s group %s\n",
55*4882a593Smuzhiyun 		func->name, grp->name);
56*4882a593Smuzhiyun 
57*4882a593Smuzhiyun 	for (i = 0; i < grp->num_pins; i++) {
58*4882a593Smuzhiyun 		const struct mtk_pin_desc *desc;
59*4882a593Smuzhiyun 		int *pin_modes = grp->data;
60*4882a593Smuzhiyun 		int pin = grp->pins[i];
61*4882a593Smuzhiyun 
62*4882a593Smuzhiyun 		desc = (const struct mtk_pin_desc *)&hw->soc->pins[pin];
63*4882a593Smuzhiyun 
64*4882a593Smuzhiyun 		mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_MODE,
65*4882a593Smuzhiyun 				 pin_modes[i]);
66*4882a593Smuzhiyun 	}
67*4882a593Smuzhiyun 
68*4882a593Smuzhiyun 	return 0;
69*4882a593Smuzhiyun }
70*4882a593Smuzhiyun 
mtk_pinmux_gpio_request_enable(struct pinctrl_dev * pctldev,struct pinctrl_gpio_range * range,unsigned int pin)71*4882a593Smuzhiyun static int mtk_pinmux_gpio_request_enable(struct pinctrl_dev *pctldev,
72*4882a593Smuzhiyun 					  struct pinctrl_gpio_range *range,
73*4882a593Smuzhiyun 					  unsigned int pin)
74*4882a593Smuzhiyun {
75*4882a593Smuzhiyun 	struct mtk_pinctrl *hw = pinctrl_dev_get_drvdata(pctldev);
76*4882a593Smuzhiyun 	const struct mtk_pin_desc *desc;
77*4882a593Smuzhiyun 
78*4882a593Smuzhiyun 	desc = (const struct mtk_pin_desc *)&hw->soc->pins[pin];
79*4882a593Smuzhiyun 
80*4882a593Smuzhiyun 	return mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_MODE,
81*4882a593Smuzhiyun 				hw->soc->gpio_m);
82*4882a593Smuzhiyun }
83*4882a593Smuzhiyun 
mtk_pinmux_gpio_set_direction(struct pinctrl_dev * pctldev,struct pinctrl_gpio_range * range,unsigned int pin,bool input)84*4882a593Smuzhiyun static int mtk_pinmux_gpio_set_direction(struct pinctrl_dev *pctldev,
85*4882a593Smuzhiyun 					 struct pinctrl_gpio_range *range,
86*4882a593Smuzhiyun 					 unsigned int pin, bool input)
87*4882a593Smuzhiyun {
88*4882a593Smuzhiyun 	struct mtk_pinctrl *hw = pinctrl_dev_get_drvdata(pctldev);
89*4882a593Smuzhiyun 	const struct mtk_pin_desc *desc;
90*4882a593Smuzhiyun 
91*4882a593Smuzhiyun 	desc = (const struct mtk_pin_desc *)&hw->soc->pins[pin];
92*4882a593Smuzhiyun 
93*4882a593Smuzhiyun 	/* hardware would take 0 as input direction */
94*4882a593Smuzhiyun 	return mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_DIR, !input);
95*4882a593Smuzhiyun }
96*4882a593Smuzhiyun 
mtk_pinconf_get(struct pinctrl_dev * pctldev,unsigned int pin,unsigned long * config)97*4882a593Smuzhiyun static int mtk_pinconf_get(struct pinctrl_dev *pctldev,
98*4882a593Smuzhiyun 			   unsigned int pin, unsigned long *config)
99*4882a593Smuzhiyun {
100*4882a593Smuzhiyun 	struct mtk_pinctrl *hw = pinctrl_dev_get_drvdata(pctldev);
101*4882a593Smuzhiyun 	u32 param = pinconf_to_config_param(*config);
102*4882a593Smuzhiyun 	int val, val2, err, reg, ret = 1;
103*4882a593Smuzhiyun 	const struct mtk_pin_desc *desc;
104*4882a593Smuzhiyun 
105*4882a593Smuzhiyun 	desc = (const struct mtk_pin_desc *)&hw->soc->pins[pin];
106*4882a593Smuzhiyun 
107*4882a593Smuzhiyun 	switch (param) {
108*4882a593Smuzhiyun 	case PIN_CONFIG_BIAS_DISABLE:
109*4882a593Smuzhiyun 		if (hw->soc->bias_disable_get) {
110*4882a593Smuzhiyun 			err = hw->soc->bias_disable_get(hw, desc, &ret);
111*4882a593Smuzhiyun 			if (err)
112*4882a593Smuzhiyun 				return err;
113*4882a593Smuzhiyun 		} else {
114*4882a593Smuzhiyun 			return -ENOTSUPP;
115*4882a593Smuzhiyun 		}
116*4882a593Smuzhiyun 		break;
117*4882a593Smuzhiyun 	case PIN_CONFIG_BIAS_PULL_UP:
118*4882a593Smuzhiyun 		if (hw->soc->bias_get) {
119*4882a593Smuzhiyun 			err = hw->soc->bias_get(hw, desc, 1, &ret);
120*4882a593Smuzhiyun 			if (err)
121*4882a593Smuzhiyun 				return err;
122*4882a593Smuzhiyun 		} else {
123*4882a593Smuzhiyun 			return -ENOTSUPP;
124*4882a593Smuzhiyun 		}
125*4882a593Smuzhiyun 		break;
126*4882a593Smuzhiyun 	case PIN_CONFIG_BIAS_PULL_DOWN:
127*4882a593Smuzhiyun 		if (hw->soc->bias_get) {
128*4882a593Smuzhiyun 			err = hw->soc->bias_get(hw, desc, 0, &ret);
129*4882a593Smuzhiyun 			if (err)
130*4882a593Smuzhiyun 				return err;
131*4882a593Smuzhiyun 		} else {
132*4882a593Smuzhiyun 			return -ENOTSUPP;
133*4882a593Smuzhiyun 		}
134*4882a593Smuzhiyun 		break;
135*4882a593Smuzhiyun 	case PIN_CONFIG_SLEW_RATE:
136*4882a593Smuzhiyun 		err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_SR, &val);
137*4882a593Smuzhiyun 		if (err)
138*4882a593Smuzhiyun 			return err;
139*4882a593Smuzhiyun 
140*4882a593Smuzhiyun 		if (!val)
141*4882a593Smuzhiyun 			return -EINVAL;
142*4882a593Smuzhiyun 
143*4882a593Smuzhiyun 		break;
144*4882a593Smuzhiyun 	case PIN_CONFIG_INPUT_ENABLE:
145*4882a593Smuzhiyun 	case PIN_CONFIG_OUTPUT_ENABLE:
146*4882a593Smuzhiyun 		err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_DIR, &val);
147*4882a593Smuzhiyun 		if (err)
148*4882a593Smuzhiyun 			return err;
149*4882a593Smuzhiyun 
150*4882a593Smuzhiyun 		/* HW takes input mode as zero; output mode as non-zero */
151*4882a593Smuzhiyun 		if ((val && param == PIN_CONFIG_INPUT_ENABLE) ||
152*4882a593Smuzhiyun 		    (!val && param == PIN_CONFIG_OUTPUT_ENABLE))
153*4882a593Smuzhiyun 			return -EINVAL;
154*4882a593Smuzhiyun 
155*4882a593Smuzhiyun 		break;
156*4882a593Smuzhiyun 	case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
157*4882a593Smuzhiyun 		err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_DIR, &val);
158*4882a593Smuzhiyun 		if (err)
159*4882a593Smuzhiyun 			return err;
160*4882a593Smuzhiyun 
161*4882a593Smuzhiyun 		err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_SMT, &val2);
162*4882a593Smuzhiyun 		if (err)
163*4882a593Smuzhiyun 			return err;
164*4882a593Smuzhiyun 
165*4882a593Smuzhiyun 		if (val || !val2)
166*4882a593Smuzhiyun 			return -EINVAL;
167*4882a593Smuzhiyun 
168*4882a593Smuzhiyun 		break;
169*4882a593Smuzhiyun 	case PIN_CONFIG_DRIVE_STRENGTH:
170*4882a593Smuzhiyun 		if (hw->soc->drive_get) {
171*4882a593Smuzhiyun 			err = hw->soc->drive_get(hw, desc, &ret);
172*4882a593Smuzhiyun 			if (err)
173*4882a593Smuzhiyun 				return err;
174*4882a593Smuzhiyun 		} else {
175*4882a593Smuzhiyun 			err = -ENOTSUPP;
176*4882a593Smuzhiyun 		}
177*4882a593Smuzhiyun 		break;
178*4882a593Smuzhiyun 	case MTK_PIN_CONFIG_TDSEL:
179*4882a593Smuzhiyun 	case MTK_PIN_CONFIG_RDSEL:
180*4882a593Smuzhiyun 		reg = (param == MTK_PIN_CONFIG_TDSEL) ?
181*4882a593Smuzhiyun 		       PINCTRL_PIN_REG_TDSEL : PINCTRL_PIN_REG_RDSEL;
182*4882a593Smuzhiyun 
183*4882a593Smuzhiyun 		err = mtk_hw_get_value(hw, desc, reg, &val);
184*4882a593Smuzhiyun 		if (err)
185*4882a593Smuzhiyun 			return err;
186*4882a593Smuzhiyun 
187*4882a593Smuzhiyun 		ret = val;
188*4882a593Smuzhiyun 
189*4882a593Smuzhiyun 		break;
190*4882a593Smuzhiyun 	case MTK_PIN_CONFIG_PU_ADV:
191*4882a593Smuzhiyun 	case MTK_PIN_CONFIG_PD_ADV:
192*4882a593Smuzhiyun 		if (hw->soc->adv_pull_get) {
193*4882a593Smuzhiyun 			bool pullup;
194*4882a593Smuzhiyun 
195*4882a593Smuzhiyun 			pullup = param == MTK_PIN_CONFIG_PU_ADV;
196*4882a593Smuzhiyun 			err = hw->soc->adv_pull_get(hw, desc, pullup, &ret);
197*4882a593Smuzhiyun 			if (err)
198*4882a593Smuzhiyun 				return err;
199*4882a593Smuzhiyun 		} else {
200*4882a593Smuzhiyun 			return -ENOTSUPP;
201*4882a593Smuzhiyun 		}
202*4882a593Smuzhiyun 		break;
203*4882a593Smuzhiyun 	default:
204*4882a593Smuzhiyun 		return -ENOTSUPP;
205*4882a593Smuzhiyun 	}
206*4882a593Smuzhiyun 
207*4882a593Smuzhiyun 	*config = pinconf_to_config_packed(param, ret);
208*4882a593Smuzhiyun 
209*4882a593Smuzhiyun 	return 0;
210*4882a593Smuzhiyun }
211*4882a593Smuzhiyun 
mtk_pinconf_set(struct pinctrl_dev * pctldev,unsigned int pin,unsigned long * configs,unsigned int num_configs)212*4882a593Smuzhiyun static int mtk_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin,
213*4882a593Smuzhiyun 			   unsigned long *configs, unsigned int num_configs)
214*4882a593Smuzhiyun {
215*4882a593Smuzhiyun 	struct mtk_pinctrl *hw = pinctrl_dev_get_drvdata(pctldev);
216*4882a593Smuzhiyun 	const struct mtk_pin_desc *desc;
217*4882a593Smuzhiyun 	u32 reg, param, arg;
218*4882a593Smuzhiyun 	int cfg, err = 0;
219*4882a593Smuzhiyun 
220*4882a593Smuzhiyun 	desc = (const struct mtk_pin_desc *)&hw->soc->pins[pin];
221*4882a593Smuzhiyun 
222*4882a593Smuzhiyun 	for (cfg = 0; cfg < num_configs; cfg++) {
223*4882a593Smuzhiyun 		param = pinconf_to_config_param(configs[cfg]);
224*4882a593Smuzhiyun 		arg = pinconf_to_config_argument(configs[cfg]);
225*4882a593Smuzhiyun 
226*4882a593Smuzhiyun 		switch (param) {
227*4882a593Smuzhiyun 		case PIN_CONFIG_BIAS_DISABLE:
228*4882a593Smuzhiyun 			if (hw->soc->bias_disable_set) {
229*4882a593Smuzhiyun 				err = hw->soc->bias_disable_set(hw, desc);
230*4882a593Smuzhiyun 				if (err)
231*4882a593Smuzhiyun 					return err;
232*4882a593Smuzhiyun 			} else {
233*4882a593Smuzhiyun 				return -ENOTSUPP;
234*4882a593Smuzhiyun 			}
235*4882a593Smuzhiyun 			break;
236*4882a593Smuzhiyun 		case PIN_CONFIG_BIAS_PULL_UP:
237*4882a593Smuzhiyun 			if (hw->soc->bias_set) {
238*4882a593Smuzhiyun 				err = hw->soc->bias_set(hw, desc, 1);
239*4882a593Smuzhiyun 				if (err)
240*4882a593Smuzhiyun 					return err;
241*4882a593Smuzhiyun 			} else {
242*4882a593Smuzhiyun 				return -ENOTSUPP;
243*4882a593Smuzhiyun 			}
244*4882a593Smuzhiyun 			break;
245*4882a593Smuzhiyun 		case PIN_CONFIG_BIAS_PULL_DOWN:
246*4882a593Smuzhiyun 			if (hw->soc->bias_set) {
247*4882a593Smuzhiyun 				err = hw->soc->bias_set(hw, desc, 0);
248*4882a593Smuzhiyun 				if (err)
249*4882a593Smuzhiyun 					return err;
250*4882a593Smuzhiyun 			} else {
251*4882a593Smuzhiyun 				return -ENOTSUPP;
252*4882a593Smuzhiyun 			}
253*4882a593Smuzhiyun 			break;
254*4882a593Smuzhiyun 		case PIN_CONFIG_OUTPUT_ENABLE:
255*4882a593Smuzhiyun 			err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_SMT,
256*4882a593Smuzhiyun 					       MTK_DISABLE);
257*4882a593Smuzhiyun 			if (err)
258*4882a593Smuzhiyun 				goto err;
259*4882a593Smuzhiyun 
260*4882a593Smuzhiyun 			err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_DIR,
261*4882a593Smuzhiyun 					       MTK_OUTPUT);
262*4882a593Smuzhiyun 			if (err)
263*4882a593Smuzhiyun 				goto err;
264*4882a593Smuzhiyun 			break;
265*4882a593Smuzhiyun 		case PIN_CONFIG_INPUT_ENABLE:
266*4882a593Smuzhiyun 
267*4882a593Smuzhiyun 			if (hw->soc->ies_present) {
268*4882a593Smuzhiyun 				mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_IES,
269*4882a593Smuzhiyun 						 MTK_ENABLE);
270*4882a593Smuzhiyun 			}
271*4882a593Smuzhiyun 
272*4882a593Smuzhiyun 			err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_DIR,
273*4882a593Smuzhiyun 					       MTK_INPUT);
274*4882a593Smuzhiyun 			if (err)
275*4882a593Smuzhiyun 				goto err;
276*4882a593Smuzhiyun 			break;
277*4882a593Smuzhiyun 		case PIN_CONFIG_SLEW_RATE:
278*4882a593Smuzhiyun 			err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_SR,
279*4882a593Smuzhiyun 					       arg);
280*4882a593Smuzhiyun 			if (err)
281*4882a593Smuzhiyun 				goto err;
282*4882a593Smuzhiyun 
283*4882a593Smuzhiyun 			break;
284*4882a593Smuzhiyun 		case PIN_CONFIG_OUTPUT:
285*4882a593Smuzhiyun 			err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_DIR,
286*4882a593Smuzhiyun 					       MTK_OUTPUT);
287*4882a593Smuzhiyun 			if (err)
288*4882a593Smuzhiyun 				goto err;
289*4882a593Smuzhiyun 
290*4882a593Smuzhiyun 			err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_DO,
291*4882a593Smuzhiyun 					       arg);
292*4882a593Smuzhiyun 			if (err)
293*4882a593Smuzhiyun 				goto err;
294*4882a593Smuzhiyun 			break;
295*4882a593Smuzhiyun 		case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
296*4882a593Smuzhiyun 			/* arg = 1: Input mode & SMT enable ;
297*4882a593Smuzhiyun 			 * arg = 0: Output mode & SMT disable
298*4882a593Smuzhiyun 			 */
299*4882a593Smuzhiyun 			arg = arg ? 2 : 1;
300*4882a593Smuzhiyun 			err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_DIR,
301*4882a593Smuzhiyun 					       arg & 1);
302*4882a593Smuzhiyun 			if (err)
303*4882a593Smuzhiyun 				goto err;
304*4882a593Smuzhiyun 
305*4882a593Smuzhiyun 			err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_SMT,
306*4882a593Smuzhiyun 					       !!(arg & 2));
307*4882a593Smuzhiyun 			if (err)
308*4882a593Smuzhiyun 				goto err;
309*4882a593Smuzhiyun 			break;
310*4882a593Smuzhiyun 		case PIN_CONFIG_DRIVE_STRENGTH:
311*4882a593Smuzhiyun 			if (hw->soc->drive_set) {
312*4882a593Smuzhiyun 				err = hw->soc->drive_set(hw, desc, arg);
313*4882a593Smuzhiyun 				if (err)
314*4882a593Smuzhiyun 					return err;
315*4882a593Smuzhiyun 			} else {
316*4882a593Smuzhiyun 				err = -ENOTSUPP;
317*4882a593Smuzhiyun 			}
318*4882a593Smuzhiyun 			break;
319*4882a593Smuzhiyun 		case MTK_PIN_CONFIG_TDSEL:
320*4882a593Smuzhiyun 		case MTK_PIN_CONFIG_RDSEL:
321*4882a593Smuzhiyun 			reg = (param == MTK_PIN_CONFIG_TDSEL) ?
322*4882a593Smuzhiyun 			       PINCTRL_PIN_REG_TDSEL : PINCTRL_PIN_REG_RDSEL;
323*4882a593Smuzhiyun 
324*4882a593Smuzhiyun 			err = mtk_hw_set_value(hw, desc, reg, arg);
325*4882a593Smuzhiyun 			if (err)
326*4882a593Smuzhiyun 				goto err;
327*4882a593Smuzhiyun 			break;
328*4882a593Smuzhiyun 		case MTK_PIN_CONFIG_PU_ADV:
329*4882a593Smuzhiyun 		case MTK_PIN_CONFIG_PD_ADV:
330*4882a593Smuzhiyun 			if (hw->soc->adv_pull_set) {
331*4882a593Smuzhiyun 				bool pullup;
332*4882a593Smuzhiyun 
333*4882a593Smuzhiyun 				pullup = param == MTK_PIN_CONFIG_PU_ADV;
334*4882a593Smuzhiyun 				err = hw->soc->adv_pull_set(hw, desc, pullup,
335*4882a593Smuzhiyun 							    arg);
336*4882a593Smuzhiyun 				if (err)
337*4882a593Smuzhiyun 					return err;
338*4882a593Smuzhiyun 			} else {
339*4882a593Smuzhiyun 				return -ENOTSUPP;
340*4882a593Smuzhiyun 			}
341*4882a593Smuzhiyun 			break;
342*4882a593Smuzhiyun 		default:
343*4882a593Smuzhiyun 			err = -ENOTSUPP;
344*4882a593Smuzhiyun 		}
345*4882a593Smuzhiyun 	}
346*4882a593Smuzhiyun err:
347*4882a593Smuzhiyun 	return err;
348*4882a593Smuzhiyun }
349*4882a593Smuzhiyun 
mtk_pinconf_group_get(struct pinctrl_dev * pctldev,unsigned int group,unsigned long * config)350*4882a593Smuzhiyun static int mtk_pinconf_group_get(struct pinctrl_dev *pctldev,
351*4882a593Smuzhiyun 				 unsigned int group, unsigned long *config)
352*4882a593Smuzhiyun {
353*4882a593Smuzhiyun 	const unsigned int *pins;
354*4882a593Smuzhiyun 	unsigned int i, npins, old = 0;
355*4882a593Smuzhiyun 	int ret;
356*4882a593Smuzhiyun 
357*4882a593Smuzhiyun 	ret = pinctrl_generic_get_group_pins(pctldev, group, &pins, &npins);
358*4882a593Smuzhiyun 	if (ret)
359*4882a593Smuzhiyun 		return ret;
360*4882a593Smuzhiyun 
361*4882a593Smuzhiyun 	for (i = 0; i < npins; i++) {
362*4882a593Smuzhiyun 		if (mtk_pinconf_get(pctldev, pins[i], config))
363*4882a593Smuzhiyun 			return -ENOTSUPP;
364*4882a593Smuzhiyun 
365*4882a593Smuzhiyun 		/* configs do not match between two pins */
366*4882a593Smuzhiyun 		if (i && old != *config)
367*4882a593Smuzhiyun 			return -ENOTSUPP;
368*4882a593Smuzhiyun 
369*4882a593Smuzhiyun 		old = *config;
370*4882a593Smuzhiyun 	}
371*4882a593Smuzhiyun 
372*4882a593Smuzhiyun 	return 0;
373*4882a593Smuzhiyun }
374*4882a593Smuzhiyun 
mtk_pinconf_group_set(struct pinctrl_dev * pctldev,unsigned int group,unsigned long * configs,unsigned int num_configs)375*4882a593Smuzhiyun static int mtk_pinconf_group_set(struct pinctrl_dev *pctldev,
376*4882a593Smuzhiyun 				 unsigned int group, unsigned long *configs,
377*4882a593Smuzhiyun 				 unsigned int num_configs)
378*4882a593Smuzhiyun {
379*4882a593Smuzhiyun 	const unsigned int *pins;
380*4882a593Smuzhiyun 	unsigned int i, npins;
381*4882a593Smuzhiyun 	int ret;
382*4882a593Smuzhiyun 
383*4882a593Smuzhiyun 	ret = pinctrl_generic_get_group_pins(pctldev, group, &pins, &npins);
384*4882a593Smuzhiyun 	if (ret)
385*4882a593Smuzhiyun 		return ret;
386*4882a593Smuzhiyun 
387*4882a593Smuzhiyun 	for (i = 0; i < npins; i++) {
388*4882a593Smuzhiyun 		ret = mtk_pinconf_set(pctldev, pins[i], configs, num_configs);
389*4882a593Smuzhiyun 		if (ret)
390*4882a593Smuzhiyun 			return ret;
391*4882a593Smuzhiyun 	}
392*4882a593Smuzhiyun 
393*4882a593Smuzhiyun 	return 0;
394*4882a593Smuzhiyun }
395*4882a593Smuzhiyun 
396*4882a593Smuzhiyun static const struct pinctrl_ops mtk_pctlops = {
397*4882a593Smuzhiyun 	.get_groups_count = pinctrl_generic_get_group_count,
398*4882a593Smuzhiyun 	.get_group_name = pinctrl_generic_get_group_name,
399*4882a593Smuzhiyun 	.get_group_pins = pinctrl_generic_get_group_pins,
400*4882a593Smuzhiyun 	.dt_node_to_map = pinconf_generic_dt_node_to_map_all,
401*4882a593Smuzhiyun 	.dt_free_map = pinconf_generic_dt_free_map,
402*4882a593Smuzhiyun };
403*4882a593Smuzhiyun 
404*4882a593Smuzhiyun static const struct pinmux_ops mtk_pmxops = {
405*4882a593Smuzhiyun 	.get_functions_count = pinmux_generic_get_function_count,
406*4882a593Smuzhiyun 	.get_function_name = pinmux_generic_get_function_name,
407*4882a593Smuzhiyun 	.get_function_groups = pinmux_generic_get_function_groups,
408*4882a593Smuzhiyun 	.set_mux = mtk_pinmux_set_mux,
409*4882a593Smuzhiyun 	.gpio_request_enable = mtk_pinmux_gpio_request_enable,
410*4882a593Smuzhiyun 	.gpio_set_direction = mtk_pinmux_gpio_set_direction,
411*4882a593Smuzhiyun 	.strict = true,
412*4882a593Smuzhiyun };
413*4882a593Smuzhiyun 
414*4882a593Smuzhiyun static const struct pinconf_ops mtk_confops = {
415*4882a593Smuzhiyun 	.is_generic = true,
416*4882a593Smuzhiyun 	.pin_config_get = mtk_pinconf_get,
417*4882a593Smuzhiyun 	.pin_config_set = mtk_pinconf_set,
418*4882a593Smuzhiyun 	.pin_config_group_get = mtk_pinconf_group_get,
419*4882a593Smuzhiyun 	.pin_config_group_set = mtk_pinconf_group_set,
420*4882a593Smuzhiyun 	.pin_config_config_dbg_show = pinconf_generic_dump_config,
421*4882a593Smuzhiyun };
422*4882a593Smuzhiyun 
423*4882a593Smuzhiyun static struct pinctrl_desc mtk_desc = {
424*4882a593Smuzhiyun 	.name = PINCTRL_PINCTRL_DEV,
425*4882a593Smuzhiyun 	.pctlops = &mtk_pctlops,
426*4882a593Smuzhiyun 	.pmxops = &mtk_pmxops,
427*4882a593Smuzhiyun 	.confops = &mtk_confops,
428*4882a593Smuzhiyun 	.owner = THIS_MODULE,
429*4882a593Smuzhiyun };
430*4882a593Smuzhiyun 
mtk_gpio_get(struct gpio_chip * chip,unsigned int gpio)431*4882a593Smuzhiyun static int mtk_gpio_get(struct gpio_chip *chip, unsigned int gpio)
432*4882a593Smuzhiyun {
433*4882a593Smuzhiyun 	struct mtk_pinctrl *hw = gpiochip_get_data(chip);
434*4882a593Smuzhiyun 	const struct mtk_pin_desc *desc;
435*4882a593Smuzhiyun 	int value, err;
436*4882a593Smuzhiyun 
437*4882a593Smuzhiyun 	desc = (const struct mtk_pin_desc *)&hw->soc->pins[gpio];
438*4882a593Smuzhiyun 
439*4882a593Smuzhiyun 	err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_DI, &value);
440*4882a593Smuzhiyun 	if (err)
441*4882a593Smuzhiyun 		return err;
442*4882a593Smuzhiyun 
443*4882a593Smuzhiyun 	return !!value;
444*4882a593Smuzhiyun }
445*4882a593Smuzhiyun 
mtk_gpio_set(struct gpio_chip * chip,unsigned int gpio,int value)446*4882a593Smuzhiyun static void mtk_gpio_set(struct gpio_chip *chip, unsigned int gpio, int value)
447*4882a593Smuzhiyun {
448*4882a593Smuzhiyun 	struct mtk_pinctrl *hw = gpiochip_get_data(chip);
449*4882a593Smuzhiyun 	const struct mtk_pin_desc *desc;
450*4882a593Smuzhiyun 
451*4882a593Smuzhiyun 	desc = (const struct mtk_pin_desc *)&hw->soc->pins[gpio];
452*4882a593Smuzhiyun 
453*4882a593Smuzhiyun 	mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_DO, !!value);
454*4882a593Smuzhiyun }
455*4882a593Smuzhiyun 
mtk_gpio_direction_input(struct gpio_chip * chip,unsigned int gpio)456*4882a593Smuzhiyun static int mtk_gpio_direction_input(struct gpio_chip *chip, unsigned int gpio)
457*4882a593Smuzhiyun {
458*4882a593Smuzhiyun 	return pinctrl_gpio_direction_input(chip->base + gpio);
459*4882a593Smuzhiyun }
460*4882a593Smuzhiyun 
mtk_gpio_direction_output(struct gpio_chip * chip,unsigned int gpio,int value)461*4882a593Smuzhiyun static int mtk_gpio_direction_output(struct gpio_chip *chip, unsigned int gpio,
462*4882a593Smuzhiyun 				     int value)
463*4882a593Smuzhiyun {
464*4882a593Smuzhiyun 	mtk_gpio_set(chip, gpio, value);
465*4882a593Smuzhiyun 
466*4882a593Smuzhiyun 	return pinctrl_gpio_direction_output(chip->base + gpio);
467*4882a593Smuzhiyun }
468*4882a593Smuzhiyun 
mtk_gpio_to_irq(struct gpio_chip * chip,unsigned int offset)469*4882a593Smuzhiyun static int mtk_gpio_to_irq(struct gpio_chip *chip, unsigned int offset)
470*4882a593Smuzhiyun {
471*4882a593Smuzhiyun 	struct mtk_pinctrl *hw = gpiochip_get_data(chip);
472*4882a593Smuzhiyun 	const struct mtk_pin_desc *desc;
473*4882a593Smuzhiyun 
474*4882a593Smuzhiyun 	if (!hw->eint)
475*4882a593Smuzhiyun 		return -ENOTSUPP;
476*4882a593Smuzhiyun 
477*4882a593Smuzhiyun 	desc = (const struct mtk_pin_desc *)&hw->soc->pins[offset];
478*4882a593Smuzhiyun 
479*4882a593Smuzhiyun 	if (desc->eint.eint_n == (u16)EINT_NA)
480*4882a593Smuzhiyun 		return -ENOTSUPP;
481*4882a593Smuzhiyun 
482*4882a593Smuzhiyun 	return mtk_eint_find_irq(hw->eint, desc->eint.eint_n);
483*4882a593Smuzhiyun }
484*4882a593Smuzhiyun 
mtk_gpio_set_config(struct gpio_chip * chip,unsigned int offset,unsigned long config)485*4882a593Smuzhiyun static int mtk_gpio_set_config(struct gpio_chip *chip, unsigned int offset,
486*4882a593Smuzhiyun 			       unsigned long config)
487*4882a593Smuzhiyun {
488*4882a593Smuzhiyun 	struct mtk_pinctrl *hw = gpiochip_get_data(chip);
489*4882a593Smuzhiyun 	const struct mtk_pin_desc *desc;
490*4882a593Smuzhiyun 	u32 debounce;
491*4882a593Smuzhiyun 
492*4882a593Smuzhiyun 	desc = (const struct mtk_pin_desc *)&hw->soc->pins[offset];
493*4882a593Smuzhiyun 
494*4882a593Smuzhiyun 	if (!hw->eint ||
495*4882a593Smuzhiyun 	    pinconf_to_config_param(config) != PIN_CONFIG_INPUT_DEBOUNCE ||
496*4882a593Smuzhiyun 	    desc->eint.eint_n == (u16)EINT_NA)
497*4882a593Smuzhiyun 		return -ENOTSUPP;
498*4882a593Smuzhiyun 
499*4882a593Smuzhiyun 	debounce = pinconf_to_config_argument(config);
500*4882a593Smuzhiyun 
501*4882a593Smuzhiyun 	return mtk_eint_set_debounce(hw->eint, desc->eint.eint_n, debounce);
502*4882a593Smuzhiyun }
503*4882a593Smuzhiyun 
mtk_build_gpiochip(struct mtk_pinctrl * hw,struct device_node * np)504*4882a593Smuzhiyun static int mtk_build_gpiochip(struct mtk_pinctrl *hw, struct device_node *np)
505*4882a593Smuzhiyun {
506*4882a593Smuzhiyun 	struct gpio_chip *chip = &hw->chip;
507*4882a593Smuzhiyun 	int ret;
508*4882a593Smuzhiyun 
509*4882a593Smuzhiyun 	chip->label		= PINCTRL_PINCTRL_DEV;
510*4882a593Smuzhiyun 	chip->parent		= hw->dev;
511*4882a593Smuzhiyun 	chip->request		= gpiochip_generic_request;
512*4882a593Smuzhiyun 	chip->free		= gpiochip_generic_free;
513*4882a593Smuzhiyun 	chip->direction_input	= mtk_gpio_direction_input;
514*4882a593Smuzhiyun 	chip->direction_output	= mtk_gpio_direction_output;
515*4882a593Smuzhiyun 	chip->get		= mtk_gpio_get;
516*4882a593Smuzhiyun 	chip->set		= mtk_gpio_set;
517*4882a593Smuzhiyun 	chip->to_irq		= mtk_gpio_to_irq,
518*4882a593Smuzhiyun 	chip->set_config	= mtk_gpio_set_config,
519*4882a593Smuzhiyun 	chip->base		= -1;
520*4882a593Smuzhiyun 	chip->ngpio		= hw->soc->npins;
521*4882a593Smuzhiyun 	chip->of_node		= np;
522*4882a593Smuzhiyun 	chip->of_gpio_n_cells	= 2;
523*4882a593Smuzhiyun 
524*4882a593Smuzhiyun 	ret = gpiochip_add_data(chip, hw);
525*4882a593Smuzhiyun 	if (ret < 0)
526*4882a593Smuzhiyun 		return ret;
527*4882a593Smuzhiyun 
528*4882a593Smuzhiyun 	/* Just for backward compatible for these old pinctrl nodes without
529*4882a593Smuzhiyun 	 * "gpio-ranges" property. Otherwise, called directly from a
530*4882a593Smuzhiyun 	 * DeviceTree-supported pinctrl driver is DEPRECATED.
531*4882a593Smuzhiyun 	 * Please see Section 2.1 of
532*4882a593Smuzhiyun 	 * Documentation/devicetree/bindings/gpio/gpio.txt on how to
533*4882a593Smuzhiyun 	 * bind pinctrl and gpio drivers via the "gpio-ranges" property.
534*4882a593Smuzhiyun 	 */
535*4882a593Smuzhiyun 	if (!of_find_property(np, "gpio-ranges", NULL)) {
536*4882a593Smuzhiyun 		ret = gpiochip_add_pin_range(chip, dev_name(hw->dev), 0, 0,
537*4882a593Smuzhiyun 					     chip->ngpio);
538*4882a593Smuzhiyun 		if (ret < 0) {
539*4882a593Smuzhiyun 			gpiochip_remove(chip);
540*4882a593Smuzhiyun 			return ret;
541*4882a593Smuzhiyun 		}
542*4882a593Smuzhiyun 	}
543*4882a593Smuzhiyun 
544*4882a593Smuzhiyun 	return 0;
545*4882a593Smuzhiyun }
546*4882a593Smuzhiyun 
mtk_build_groups(struct mtk_pinctrl * hw)547*4882a593Smuzhiyun static int mtk_build_groups(struct mtk_pinctrl *hw)
548*4882a593Smuzhiyun {
549*4882a593Smuzhiyun 	int err, i;
550*4882a593Smuzhiyun 
551*4882a593Smuzhiyun 	for (i = 0; i < hw->soc->ngrps; i++) {
552*4882a593Smuzhiyun 		const struct group_desc *group = hw->soc->grps + i;
553*4882a593Smuzhiyun 
554*4882a593Smuzhiyun 		err = pinctrl_generic_add_group(hw->pctrl, group->name,
555*4882a593Smuzhiyun 						group->pins, group->num_pins,
556*4882a593Smuzhiyun 						group->data);
557*4882a593Smuzhiyun 		if (err < 0) {
558*4882a593Smuzhiyun 			dev_err(hw->dev, "Failed to register group %s\n",
559*4882a593Smuzhiyun 				group->name);
560*4882a593Smuzhiyun 			return err;
561*4882a593Smuzhiyun 		}
562*4882a593Smuzhiyun 	}
563*4882a593Smuzhiyun 
564*4882a593Smuzhiyun 	return 0;
565*4882a593Smuzhiyun }
566*4882a593Smuzhiyun 
mtk_build_functions(struct mtk_pinctrl * hw)567*4882a593Smuzhiyun static int mtk_build_functions(struct mtk_pinctrl *hw)
568*4882a593Smuzhiyun {
569*4882a593Smuzhiyun 	int i, err;
570*4882a593Smuzhiyun 
571*4882a593Smuzhiyun 	for (i = 0; i < hw->soc->nfuncs ; i++) {
572*4882a593Smuzhiyun 		const struct function_desc *func = hw->soc->funcs + i;
573*4882a593Smuzhiyun 
574*4882a593Smuzhiyun 		err = pinmux_generic_add_function(hw->pctrl, func->name,
575*4882a593Smuzhiyun 						  func->group_names,
576*4882a593Smuzhiyun 						  func->num_group_names,
577*4882a593Smuzhiyun 						  func->data);
578*4882a593Smuzhiyun 		if (err < 0) {
579*4882a593Smuzhiyun 			dev_err(hw->dev, "Failed to register function %s\n",
580*4882a593Smuzhiyun 				func->name);
581*4882a593Smuzhiyun 			return err;
582*4882a593Smuzhiyun 		}
583*4882a593Smuzhiyun 	}
584*4882a593Smuzhiyun 
585*4882a593Smuzhiyun 	return 0;
586*4882a593Smuzhiyun }
587*4882a593Smuzhiyun 
mtk_moore_pinctrl_probe(struct platform_device * pdev,const struct mtk_pin_soc * soc)588*4882a593Smuzhiyun int mtk_moore_pinctrl_probe(struct platform_device *pdev,
589*4882a593Smuzhiyun 			    const struct mtk_pin_soc *soc)
590*4882a593Smuzhiyun {
591*4882a593Smuzhiyun 	struct pinctrl_pin_desc *pins;
592*4882a593Smuzhiyun 	struct mtk_pinctrl *hw;
593*4882a593Smuzhiyun 	int err, i;
594*4882a593Smuzhiyun 
595*4882a593Smuzhiyun 	hw = devm_kzalloc(&pdev->dev, sizeof(*hw), GFP_KERNEL);
596*4882a593Smuzhiyun 	if (!hw)
597*4882a593Smuzhiyun 		return -ENOMEM;
598*4882a593Smuzhiyun 
599*4882a593Smuzhiyun 	hw->soc = soc;
600*4882a593Smuzhiyun 	hw->dev = &pdev->dev;
601*4882a593Smuzhiyun 
602*4882a593Smuzhiyun 	if (!hw->soc->nbase_names) {
603*4882a593Smuzhiyun 		dev_err(&pdev->dev,
604*4882a593Smuzhiyun 			"SoC should be assigned at least one register base\n");
605*4882a593Smuzhiyun 		return -EINVAL;
606*4882a593Smuzhiyun 	}
607*4882a593Smuzhiyun 
608*4882a593Smuzhiyun 	hw->base = devm_kmalloc_array(&pdev->dev, hw->soc->nbase_names,
609*4882a593Smuzhiyun 				      sizeof(*hw->base), GFP_KERNEL);
610*4882a593Smuzhiyun 	if (!hw->base)
611*4882a593Smuzhiyun 		return -ENOMEM;
612*4882a593Smuzhiyun 
613*4882a593Smuzhiyun 	for (i = 0; i < hw->soc->nbase_names; i++) {
614*4882a593Smuzhiyun 		hw->base[i] = devm_platform_ioremap_resource_byname(pdev,
615*4882a593Smuzhiyun 						hw->soc->base_names[i]);
616*4882a593Smuzhiyun 		if (IS_ERR(hw->base[i]))
617*4882a593Smuzhiyun 			return PTR_ERR(hw->base[i]);
618*4882a593Smuzhiyun 	}
619*4882a593Smuzhiyun 
620*4882a593Smuzhiyun 	hw->nbase = hw->soc->nbase_names;
621*4882a593Smuzhiyun 
622*4882a593Smuzhiyun 	/* Copy from internal struct mtk_pin_desc to register to the core */
623*4882a593Smuzhiyun 	pins = devm_kmalloc_array(&pdev->dev, hw->soc->npins, sizeof(*pins),
624*4882a593Smuzhiyun 				  GFP_KERNEL);
625*4882a593Smuzhiyun 	if (!pins)
626*4882a593Smuzhiyun 		return -ENOMEM;
627*4882a593Smuzhiyun 
628*4882a593Smuzhiyun 	for (i = 0; i < hw->soc->npins; i++) {
629*4882a593Smuzhiyun 		pins[i].number = hw->soc->pins[i].number;
630*4882a593Smuzhiyun 		pins[i].name = hw->soc->pins[i].name;
631*4882a593Smuzhiyun 	}
632*4882a593Smuzhiyun 
633*4882a593Smuzhiyun 	/* Setup pins descriptions per SoC types */
634*4882a593Smuzhiyun 	mtk_desc.pins = (const struct pinctrl_pin_desc *)pins;
635*4882a593Smuzhiyun 	mtk_desc.npins = hw->soc->npins;
636*4882a593Smuzhiyun 	mtk_desc.num_custom_params = ARRAY_SIZE(mtk_custom_bindings);
637*4882a593Smuzhiyun 	mtk_desc.custom_params = mtk_custom_bindings;
638*4882a593Smuzhiyun #ifdef CONFIG_DEBUG_FS
639*4882a593Smuzhiyun 	mtk_desc.custom_conf_items = mtk_conf_items;
640*4882a593Smuzhiyun #endif
641*4882a593Smuzhiyun 
642*4882a593Smuzhiyun 	err = devm_pinctrl_register_and_init(&pdev->dev, &mtk_desc, hw,
643*4882a593Smuzhiyun 					     &hw->pctrl);
644*4882a593Smuzhiyun 	if (err)
645*4882a593Smuzhiyun 		return err;
646*4882a593Smuzhiyun 
647*4882a593Smuzhiyun 	/* Setup groups descriptions per SoC types */
648*4882a593Smuzhiyun 	err = mtk_build_groups(hw);
649*4882a593Smuzhiyun 	if (err) {
650*4882a593Smuzhiyun 		dev_err(&pdev->dev, "Failed to build groups\n");
651*4882a593Smuzhiyun 		return err;
652*4882a593Smuzhiyun 	}
653*4882a593Smuzhiyun 
654*4882a593Smuzhiyun 	/* Setup functions descriptions per SoC types */
655*4882a593Smuzhiyun 	err = mtk_build_functions(hw);
656*4882a593Smuzhiyun 	if (err) {
657*4882a593Smuzhiyun 		dev_err(&pdev->dev, "Failed to build functions\n");
658*4882a593Smuzhiyun 		return err;
659*4882a593Smuzhiyun 	}
660*4882a593Smuzhiyun 
661*4882a593Smuzhiyun 	/* For able to make pinctrl_claim_hogs, we must not enable pinctrl
662*4882a593Smuzhiyun 	 * until all groups and functions are being added one.
663*4882a593Smuzhiyun 	 */
664*4882a593Smuzhiyun 	err = pinctrl_enable(hw->pctrl);
665*4882a593Smuzhiyun 	if (err)
666*4882a593Smuzhiyun 		return err;
667*4882a593Smuzhiyun 
668*4882a593Smuzhiyun 	err = mtk_build_eint(hw, pdev);
669*4882a593Smuzhiyun 	if (err)
670*4882a593Smuzhiyun 		dev_warn(&pdev->dev,
671*4882a593Smuzhiyun 			 "Failed to add EINT, but pinctrl still can work\n");
672*4882a593Smuzhiyun 
673*4882a593Smuzhiyun 	/* Build gpiochip should be after pinctrl_enable is done */
674*4882a593Smuzhiyun 	err = mtk_build_gpiochip(hw, pdev->dev.of_node);
675*4882a593Smuzhiyun 	if (err) {
676*4882a593Smuzhiyun 		dev_err(&pdev->dev, "Failed to add gpio_chip\n");
677*4882a593Smuzhiyun 		return err;
678*4882a593Smuzhiyun 	}
679*4882a593Smuzhiyun 
680*4882a593Smuzhiyun 	platform_set_drvdata(pdev, hw);
681*4882a593Smuzhiyun 
682*4882a593Smuzhiyun 	return 0;
683*4882a593Smuzhiyun }
684