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