diff options
author | Zhiyong Tao <zhiyong.tao@mediatek.com> | 2018-09-08 07:07:33 -0400 |
---|---|---|
committer | Linus Walleij <linus.walleij@linaro.org> | 2018-09-18 17:53:25 -0400 |
commit | 805250982bb5c5ce4a6e52e1d87204c5feea0dd1 (patch) | |
tree | 94943bc865e0b63c1b94cd0c6aede9334d1191c9 /drivers/pinctrl/mediatek | |
parent | b7d7f9eeca551f9cf1f6418749cd609d371faf55 (diff) |
pinctrl: mediatek: add pinctrl-paris that implements the vendor dt-bindings
Add pinctrl-paris core that implements vendor dt-binding which MediaTek
tablet, box and smartphone-based SoCs such as MT81xx, MT27xx, and MT67xx
SoCs really want to depend on. The driver is just completely rewritten
according to pinctrl-mtk-common.c but uses the new logic from
pinctrl-mtk-common-v2.c to have an elegant way to support new SoCs in the
future.
Signed-off-by: Zhiyong Tao <zhiyong.tao@mediatek.com>
Signed-off-by: Sean Wang <sean.wang@mediatek.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Diffstat (limited to 'drivers/pinctrl/mediatek')
-rw-r--r-- | drivers/pinctrl/mediatek/Kconfig | 9 | ||||
-rw-r--r-- | drivers/pinctrl/mediatek/Makefile | 1 | ||||
-rw-r--r-- | drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.h | 8 | ||||
-rw-r--r-- | drivers/pinctrl/mediatek/pinctrl-paris.c | 884 | ||||
-rw-r--r-- | drivers/pinctrl/mediatek/pinctrl-paris.h | 65 |
5 files changed, 967 insertions, 0 deletions
diff --git a/drivers/pinctrl/mediatek/Kconfig b/drivers/pinctrl/mediatek/Kconfig index 6124ef053b14..4a8086e4dd39 100644 --- a/drivers/pinctrl/mediatek/Kconfig +++ b/drivers/pinctrl/mediatek/Kconfig | |||
@@ -24,6 +24,15 @@ config PINCTRL_MTK_MOORE | |||
24 | select GPIOLIB | 24 | select GPIOLIB |
25 | select OF_GPIO | 25 | select OF_GPIO |
26 | 26 | ||
27 | config PINCTRL_MTK_PARIS | ||
28 | bool "MediaTek Paris Core that implements vendor binding" | ||
29 | depends on OF | ||
30 | select PINMUX | ||
31 | select GENERIC_PINCONF | ||
32 | select GPIOLIB | ||
33 | select EINT_MTK | ||
34 | select OF_GPIO | ||
35 | |||
27 | # For ARMv7 SoCs | 36 | # For ARMv7 SoCs |
28 | config PINCTRL_MT2701 | 37 | config PINCTRL_MT2701 |
29 | bool "Mediatek MT2701 pin control" | 38 | bool "Mediatek MT2701 pin control" |
diff --git a/drivers/pinctrl/mediatek/Makefile b/drivers/pinctrl/mediatek/Makefile index 5df28e116653..8847dce84a4c 100644 --- a/drivers/pinctrl/mediatek/Makefile +++ b/drivers/pinctrl/mediatek/Makefile | |||
@@ -3,6 +3,7 @@ | |||
3 | obj-$(CONFIG_EINT_MTK) += mtk-eint.o | 3 | obj-$(CONFIG_EINT_MTK) += mtk-eint.o |
4 | obj-$(CONFIG_PINCTRL_MTK) += pinctrl-mtk-common.o | 4 | obj-$(CONFIG_PINCTRL_MTK) += pinctrl-mtk-common.o |
5 | obj-$(CONFIG_PINCTRL_MTK_MOORE) += pinctrl-moore.o pinctrl-mtk-common-v2.o | 5 | obj-$(CONFIG_PINCTRL_MTK_MOORE) += pinctrl-moore.o pinctrl-mtk-common-v2.o |
6 | obj-$(CONFIG_PINCTRL_MTK_PARIS) += pinctrl-paris.o pinctrl-mtk-common-v2.o | ||
6 | 7 | ||
7 | # SoC Drivers | 8 | # SoC Drivers |
8 | obj-$(CONFIG_PINCTRL_MT2701) += pinctrl-mt2701.o | 9 | obj-$(CONFIG_PINCTRL_MT2701) += pinctrl-mt2701.o |
diff --git a/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.h b/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.h index d5819ca98c3c..05b9b391afea 100644 --- a/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.h +++ b/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.h | |||
@@ -174,6 +174,12 @@ struct mtk_pin_desc { | |||
174 | struct mtk_func_desc *funcs; | 174 | struct mtk_func_desc *funcs; |
175 | }; | 175 | }; |
176 | 176 | ||
177 | struct mtk_pinctrl_group { | ||
178 | const char *name; | ||
179 | unsigned long config; | ||
180 | unsigned pin; | ||
181 | }; | ||
182 | |||
177 | struct mtk_pinctrl; | 183 | struct mtk_pinctrl; |
178 | 184 | ||
179 | /* struct mtk_pin_soc - the structure that holds SoC-specific data */ | 185 | /* struct mtk_pin_soc - the structure that holds SoC-specific data */ |
@@ -228,6 +234,8 @@ struct mtk_pinctrl { | |||
228 | struct gpio_chip chip; | 234 | struct gpio_chip chip; |
229 | const struct mtk_pin_soc *soc; | 235 | const struct mtk_pin_soc *soc; |
230 | struct mtk_eint *eint; | 236 | struct mtk_eint *eint; |
237 | struct mtk_pinctrl_group *groups; | ||
238 | const char **grp_names; | ||
231 | }; | 239 | }; |
232 | 240 | ||
233 | void mtk_rmw(struct mtk_pinctrl *pctl, u8 i, u32 reg, u32 mask, u32 set); | 241 | void mtk_rmw(struct mtk_pinctrl *pctl, u8 i, u32 reg, u32 mask, u32 set); |
diff --git a/drivers/pinctrl/mediatek/pinctrl-paris.c b/drivers/pinctrl/mediatek/pinctrl-paris.c new file mode 100644 index 000000000000..50d689371590 --- /dev/null +++ b/drivers/pinctrl/mediatek/pinctrl-paris.c | |||
@@ -0,0 +1,884 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
2 | /* | ||
3 | * MediaTek Pinctrl Paris Driver, which implement the vendor per-pin | ||
4 | * bindings for MediaTek SoC. | ||
5 | * | ||
6 | * Copyright (C) 2018 MediaTek Inc. | ||
7 | * Author: Sean Wang <sean.wang@mediatek.com> | ||
8 | * Zhiyong Tao <zhiyong.tao@mediatek.com> | ||
9 | * Hongzhou.Yang <hongzhou.yang@mediatek.com> | ||
10 | */ | ||
11 | |||
12 | #include <dt-bindings/pinctrl/mt65xx.h> | ||
13 | #include "pinctrl-paris.h" | ||
14 | |||
15 | #define PINCTRL_PINCTRL_DEV KBUILD_MODNAME | ||
16 | |||
17 | /* Custom pinconf parameters */ | ||
18 | #define MTK_PIN_CONFIG_TDSEL (PIN_CONFIG_END + 1) | ||
19 | #define MTK_PIN_CONFIG_RDSEL (PIN_CONFIG_END + 2) | ||
20 | #define MTK_PIN_CONFIG_PU_ADV (PIN_CONFIG_END + 3) | ||
21 | #define MTK_PIN_CONFIG_PD_ADV (PIN_CONFIG_END + 4) | ||
22 | |||
23 | static const struct pinconf_generic_params mtk_custom_bindings[] = { | ||
24 | {"mediatek,tdsel", MTK_PIN_CONFIG_TDSEL, 0}, | ||
25 | {"mediatek,rdsel", MTK_PIN_CONFIG_RDSEL, 0}, | ||
26 | {"mediatek,pull-up-adv", MTK_PIN_CONFIG_PU_ADV, 1}, | ||
27 | {"mediatek,pull-down-adv", MTK_PIN_CONFIG_PD_ADV, 1}, | ||
28 | }; | ||
29 | |||
30 | #ifdef CONFIG_DEBUG_FS | ||
31 | static const struct pin_config_item mtk_conf_items[] = { | ||
32 | PCONFDUMP(MTK_PIN_CONFIG_TDSEL, "tdsel", NULL, true), | ||
33 | PCONFDUMP(MTK_PIN_CONFIG_RDSEL, "rdsel", NULL, true), | ||
34 | PCONFDUMP(MTK_PIN_CONFIG_PU_ADV, "pu-adv", NULL, true), | ||
35 | PCONFDUMP(MTK_PIN_CONFIG_PD_ADV, "pd-adv", NULL, true), | ||
36 | }; | ||
37 | #endif | ||
38 | |||
39 | static const char * const mtk_gpio_functions[] = { | ||
40 | "func0", "func1", "func2", "func3", | ||
41 | "func4", "func5", "func6", "func7", | ||
42 | "func8", "func9", "func10", "func11", | ||
43 | "func12", "func13", "func14", "func15", | ||
44 | }; | ||
45 | |||
46 | static int mtk_pinmux_gpio_request_enable(struct pinctrl_dev *pctldev, | ||
47 | struct pinctrl_gpio_range *range, | ||
48 | unsigned int pin) | ||
49 | { | ||
50 | struct mtk_pinctrl *hw = pinctrl_dev_get_drvdata(pctldev); | ||
51 | const struct mtk_pin_desc *desc; | ||
52 | |||
53 | desc = (const struct mtk_pin_desc *)&hw->soc->pins[pin]; | ||
54 | |||
55 | return mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_MODE, | ||
56 | hw->soc->gpio_m); | ||
57 | } | ||
58 | |||
59 | static int mtk_pinmux_gpio_set_direction(struct pinctrl_dev *pctldev, | ||
60 | struct pinctrl_gpio_range *range, | ||
61 | unsigned int pin, bool input) | ||
62 | { | ||
63 | struct mtk_pinctrl *hw = pinctrl_dev_get_drvdata(pctldev); | ||
64 | const struct mtk_pin_desc *desc; | ||
65 | |||
66 | desc = (const struct mtk_pin_desc *)&hw->soc->pins[pin]; | ||
67 | |||
68 | /* hardware would take 0 as input direction */ | ||
69 | return mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_DIR, !input); | ||
70 | } | ||
71 | |||
72 | static int mtk_pinconf_get(struct pinctrl_dev *pctldev, | ||
73 | unsigned int pin, unsigned long *config) | ||
74 | { | ||
75 | struct mtk_pinctrl *hw = pinctrl_dev_get_drvdata(pctldev); | ||
76 | u32 param = pinconf_to_config_param(*config); | ||
77 | int val, val2, err, reg, ret = 1; | ||
78 | const struct mtk_pin_desc *desc; | ||
79 | |||
80 | desc = (const struct mtk_pin_desc *)&hw->soc->pins[pin]; | ||
81 | |||
82 | switch (param) { | ||
83 | case PIN_CONFIG_BIAS_DISABLE: | ||
84 | if (hw->soc->bias_disable_get) { | ||
85 | err = hw->soc->bias_disable_get(hw, desc, &ret); | ||
86 | if (err) | ||
87 | return err; | ||
88 | } else { | ||
89 | return -ENOTSUPP; | ||
90 | } | ||
91 | break; | ||
92 | case PIN_CONFIG_BIAS_PULL_UP: | ||
93 | if (hw->soc->bias_get) { | ||
94 | err = hw->soc->bias_get(hw, desc, 1, &ret); | ||
95 | if (err) | ||
96 | return err; | ||
97 | } else { | ||
98 | return -ENOTSUPP; | ||
99 | } | ||
100 | break; | ||
101 | case PIN_CONFIG_BIAS_PULL_DOWN: | ||
102 | if (hw->soc->bias_get) { | ||
103 | err = hw->soc->bias_get(hw, desc, 0, &ret); | ||
104 | if (err) | ||
105 | return err; | ||
106 | } else { | ||
107 | return -ENOTSUPP; | ||
108 | } | ||
109 | break; | ||
110 | case PIN_CONFIG_SLEW_RATE: | ||
111 | err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_SR, &val); | ||
112 | if (err) | ||
113 | return err; | ||
114 | |||
115 | if (!val) | ||
116 | return -EINVAL; | ||
117 | |||
118 | break; | ||
119 | case PIN_CONFIG_INPUT_ENABLE: | ||
120 | case PIN_CONFIG_OUTPUT_ENABLE: | ||
121 | err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_DIR, &val); | ||
122 | if (err) | ||
123 | return err; | ||
124 | |||
125 | /* HW takes input mode as zero; output mode as non-zero */ | ||
126 | if ((val && param == PIN_CONFIG_INPUT_ENABLE) || | ||
127 | (!val && param == PIN_CONFIG_OUTPUT_ENABLE)) | ||
128 | return -EINVAL; | ||
129 | |||
130 | break; | ||
131 | case PIN_CONFIG_INPUT_SCHMITT_ENABLE: | ||
132 | err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_DIR, &val); | ||
133 | if (err) | ||
134 | return err; | ||
135 | |||
136 | err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_SMT, &val2); | ||
137 | if (err) | ||
138 | return err; | ||
139 | |||
140 | if (val || !val2) | ||
141 | return -EINVAL; | ||
142 | |||
143 | break; | ||
144 | case PIN_CONFIG_DRIVE_STRENGTH: | ||
145 | if (hw->soc->drive_get) { | ||
146 | err = hw->soc->drive_get(hw, desc, &ret); | ||
147 | if (err) | ||
148 | return err; | ||
149 | } else { | ||
150 | err = -ENOTSUPP; | ||
151 | } | ||
152 | break; | ||
153 | case MTK_PIN_CONFIG_TDSEL: | ||
154 | case MTK_PIN_CONFIG_RDSEL: | ||
155 | reg = (param == MTK_PIN_CONFIG_TDSEL) ? | ||
156 | PINCTRL_PIN_REG_TDSEL : PINCTRL_PIN_REG_RDSEL; | ||
157 | |||
158 | err = mtk_hw_get_value(hw, desc, reg, &val); | ||
159 | if (err) | ||
160 | return err; | ||
161 | |||
162 | ret = val; | ||
163 | |||
164 | break; | ||
165 | case MTK_PIN_CONFIG_PU_ADV: | ||
166 | case MTK_PIN_CONFIG_PD_ADV: | ||
167 | if (hw->soc->adv_pull_get) { | ||
168 | bool pullup; | ||
169 | |||
170 | pullup = param == MTK_PIN_CONFIG_PU_ADV; | ||
171 | err = hw->soc->adv_pull_get(hw, desc, pullup, &ret); | ||
172 | if (err) | ||
173 | return err; | ||
174 | } else { | ||
175 | return -ENOTSUPP; | ||
176 | } | ||
177 | break; | ||
178 | default: | ||
179 | return -ENOTSUPP; | ||
180 | } | ||
181 | |||
182 | *config = pinconf_to_config_packed(param, ret); | ||
183 | |||
184 | return 0; | ||
185 | } | ||
186 | |||
187 | static int mtk_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin, | ||
188 | enum pin_config_param param, | ||
189 | enum pin_config_param arg) | ||
190 | { | ||
191 | struct mtk_pinctrl *hw = pinctrl_dev_get_drvdata(pctldev); | ||
192 | const struct mtk_pin_desc *desc; | ||
193 | int err = 0; | ||
194 | u32 reg; | ||
195 | |||
196 | desc = (const struct mtk_pin_desc *)&hw->soc->pins[pin]; | ||
197 | |||
198 | switch ((u32)param) { | ||
199 | case PIN_CONFIG_BIAS_DISABLE: | ||
200 | if (hw->soc->bias_disable_set) { | ||
201 | err = hw->soc->bias_disable_set(hw, desc); | ||
202 | if (err) | ||
203 | return err; | ||
204 | } else { | ||
205 | return -ENOTSUPP; | ||
206 | } | ||
207 | break; | ||
208 | case PIN_CONFIG_BIAS_PULL_UP: | ||
209 | if (hw->soc->bias_set) { | ||
210 | err = hw->soc->bias_set(hw, desc, 1); | ||
211 | if (err) | ||
212 | return err; | ||
213 | } else { | ||
214 | return -ENOTSUPP; | ||
215 | } | ||
216 | break; | ||
217 | case PIN_CONFIG_BIAS_PULL_DOWN: | ||
218 | if (hw->soc->bias_set) { | ||
219 | err = hw->soc->bias_set(hw, desc, 0); | ||
220 | if (err) | ||
221 | return err; | ||
222 | } else { | ||
223 | return -ENOTSUPP; | ||
224 | } | ||
225 | break; | ||
226 | case PIN_CONFIG_OUTPUT_ENABLE: | ||
227 | err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_SMT, | ||
228 | MTK_DISABLE); | ||
229 | if (err) | ||
230 | goto err; | ||
231 | |||
232 | err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_DIR, | ||
233 | MTK_OUTPUT); | ||
234 | if (err) | ||
235 | goto err; | ||
236 | break; | ||
237 | case PIN_CONFIG_INPUT_ENABLE: | ||
238 | if (hw->soc->ies_present) { | ||
239 | mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_IES, | ||
240 | MTK_ENABLE); | ||
241 | } | ||
242 | |||
243 | err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_DIR, | ||
244 | MTK_INPUT); | ||
245 | if (err) | ||
246 | goto err; | ||
247 | break; | ||
248 | case PIN_CONFIG_SLEW_RATE: | ||
249 | err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_SR, | ||
250 | arg); | ||
251 | if (err) | ||
252 | goto err; | ||
253 | |||
254 | break; | ||
255 | case PIN_CONFIG_OUTPUT: | ||
256 | err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_DIR, | ||
257 | MTK_OUTPUT); | ||
258 | if (err) | ||
259 | goto err; | ||
260 | |||
261 | err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_DO, | ||
262 | arg); | ||
263 | if (err) | ||
264 | goto err; | ||
265 | break; | ||
266 | case PIN_CONFIG_INPUT_SCHMITT_ENABLE: | ||
267 | /* arg = 1: Input mode & SMT enable ; | ||
268 | * arg = 0: Output mode & SMT disable | ||
269 | */ | ||
270 | arg = arg ? 2 : 1; | ||
271 | err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_DIR, | ||
272 | arg & 1); | ||
273 | if (err) | ||
274 | goto err; | ||
275 | |||
276 | err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_SMT, | ||
277 | !!(arg & 2)); | ||
278 | if (err) | ||
279 | goto err; | ||
280 | break; | ||
281 | case PIN_CONFIG_DRIVE_STRENGTH: | ||
282 | if (hw->soc->drive_set) { | ||
283 | err = hw->soc->drive_set(hw, desc, arg); | ||
284 | if (err) | ||
285 | return err; | ||
286 | } else { | ||
287 | return -ENOTSUPP; | ||
288 | } | ||
289 | break; | ||
290 | case MTK_PIN_CONFIG_TDSEL: | ||
291 | case MTK_PIN_CONFIG_RDSEL: | ||
292 | reg = (param == MTK_PIN_CONFIG_TDSEL) ? | ||
293 | PINCTRL_PIN_REG_TDSEL : PINCTRL_PIN_REG_RDSEL; | ||
294 | |||
295 | err = mtk_hw_set_value(hw, desc, reg, arg); | ||
296 | if (err) | ||
297 | goto err; | ||
298 | break; | ||
299 | case MTK_PIN_CONFIG_PU_ADV: | ||
300 | case MTK_PIN_CONFIG_PD_ADV: | ||
301 | if (hw->soc->adv_pull_set) { | ||
302 | bool pullup; | ||
303 | |||
304 | pullup = param == MTK_PIN_CONFIG_PU_ADV; | ||
305 | err = hw->soc->adv_pull_set(hw, desc, pullup, | ||
306 | arg); | ||
307 | if (err) | ||
308 | return err; | ||
309 | } else { | ||
310 | return -ENOTSUPP; | ||
311 | } | ||
312 | break; | ||
313 | default: | ||
314 | err = -ENOTSUPP; | ||
315 | } | ||
316 | |||
317 | err: | ||
318 | return err; | ||
319 | } | ||
320 | |||
321 | static struct mtk_pinctrl_group * | ||
322 | mtk_pctrl_find_group_by_pin(struct mtk_pinctrl *hw, u32 pin) | ||
323 | { | ||
324 | int i; | ||
325 | |||
326 | for (i = 0; i < hw->soc->ngrps; i++) { | ||
327 | struct mtk_pinctrl_group *grp = hw->groups + i; | ||
328 | |||
329 | if (grp->pin == pin) | ||
330 | return grp; | ||
331 | } | ||
332 | |||
333 | return NULL; | ||
334 | } | ||
335 | |||
336 | static const struct mtk_func_desc * | ||
337 | mtk_pctrl_find_function_by_pin(struct mtk_pinctrl *hw, u32 pin_num, u32 fnum) | ||
338 | { | ||
339 | const struct mtk_pin_desc *pin = hw->soc->pins + pin_num; | ||
340 | const struct mtk_func_desc *func = pin->funcs; | ||
341 | |||
342 | while (func && func->name) { | ||
343 | if (func->muxval == fnum) | ||
344 | return func; | ||
345 | func++; | ||
346 | } | ||
347 | |||
348 | return NULL; | ||
349 | } | ||
350 | |||
351 | static bool mtk_pctrl_is_function_valid(struct mtk_pinctrl *hw, u32 pin_num, | ||
352 | u32 fnum) | ||
353 | { | ||
354 | int i; | ||
355 | |||
356 | for (i = 0; i < hw->soc->npins; i++) { | ||
357 | const struct mtk_pin_desc *pin = hw->soc->pins + i; | ||
358 | |||
359 | if (pin->number == pin_num) { | ||
360 | const struct mtk_func_desc *func = pin->funcs; | ||
361 | |||
362 | while (func && func->name) { | ||
363 | if (func->muxval == fnum) | ||
364 | return true; | ||
365 | func++; | ||
366 | } | ||
367 | |||
368 | break; | ||
369 | } | ||
370 | } | ||
371 | |||
372 | return false; | ||
373 | } | ||
374 | |||
375 | static int mtk_pctrl_dt_node_to_map_func(struct mtk_pinctrl *pctl, | ||
376 | u32 pin, u32 fnum, | ||
377 | struct mtk_pinctrl_group *grp, | ||
378 | struct pinctrl_map **map, | ||
379 | unsigned *reserved_maps, | ||
380 | unsigned *num_maps) | ||
381 | { | ||
382 | bool ret; | ||
383 | |||
384 | if (*num_maps == *reserved_maps) | ||
385 | return -ENOSPC; | ||
386 | |||
387 | (*map)[*num_maps].type = PIN_MAP_TYPE_MUX_GROUP; | ||
388 | (*map)[*num_maps].data.mux.group = grp->name; | ||
389 | |||
390 | ret = mtk_pctrl_is_function_valid(pctl, pin, fnum); | ||
391 | if (!ret) { | ||
392 | dev_err(pctl->dev, "invalid function %d on pin %d .\n", | ||
393 | fnum, pin); | ||
394 | return -EINVAL; | ||
395 | } | ||
396 | |||
397 | (*map)[*num_maps].data.mux.function = mtk_gpio_functions[fnum]; | ||
398 | (*num_maps)++; | ||
399 | |||
400 | return 0; | ||
401 | } | ||
402 | |||
403 | static int mtk_pctrl_dt_subnode_to_map(struct pinctrl_dev *pctldev, | ||
404 | struct device_node *node, | ||
405 | struct pinctrl_map **map, | ||
406 | unsigned *reserved_maps, | ||
407 | unsigned *num_maps) | ||
408 | { | ||
409 | struct mtk_pinctrl *hw = pinctrl_dev_get_drvdata(pctldev); | ||
410 | int num_pins, num_funcs, maps_per_pin, i, err; | ||
411 | struct mtk_pinctrl_group *grp; | ||
412 | unsigned int num_configs; | ||
413 | bool has_config = false; | ||
414 | unsigned long *configs; | ||
415 | u32 pinfunc, pin, func; | ||
416 | struct property *pins; | ||
417 | unsigned reserve = 0; | ||
418 | |||
419 | pins = of_find_property(node, "pinmux", NULL); | ||
420 | if (!pins) { | ||
421 | dev_err(hw->dev, "missing pins property in node %s .\n", | ||
422 | node->name); | ||
423 | return -EINVAL; | ||
424 | } | ||
425 | |||
426 | err = pinconf_generic_parse_dt_config(node, pctldev, &configs, | ||
427 | &num_configs); | ||
428 | if (err) | ||
429 | return err; | ||
430 | |||
431 | if (num_configs) | ||
432 | has_config = true; | ||
433 | |||
434 | num_pins = pins->length / sizeof(u32); | ||
435 | num_funcs = num_pins; | ||
436 | maps_per_pin = 0; | ||
437 | if (num_funcs) | ||
438 | maps_per_pin++; | ||
439 | if (has_config && num_pins >= 1) | ||
440 | maps_per_pin++; | ||
441 | |||
442 | if (!num_pins || !maps_per_pin) { | ||
443 | err = -EINVAL; | ||
444 | goto exit; | ||
445 | } | ||
446 | |||
447 | reserve = num_pins * maps_per_pin; | ||
448 | |||
449 | err = pinctrl_utils_reserve_map(pctldev, map, reserved_maps, num_maps, | ||
450 | reserve); | ||
451 | if (err < 0) | ||
452 | goto exit; | ||
453 | |||
454 | for (i = 0; i < num_pins; i++) { | ||
455 | err = of_property_read_u32_index(node, "pinmux", i, &pinfunc); | ||
456 | if (err) | ||
457 | goto exit; | ||
458 | |||
459 | pin = MTK_GET_PIN_NO(pinfunc); | ||
460 | func = MTK_GET_PIN_FUNC(pinfunc); | ||
461 | |||
462 | if (pin >= hw->soc->npins || | ||
463 | func >= ARRAY_SIZE(mtk_gpio_functions)) { | ||
464 | dev_err(hw->dev, "invalid pins value.\n"); | ||
465 | err = -EINVAL; | ||
466 | goto exit; | ||
467 | } | ||
468 | |||
469 | grp = mtk_pctrl_find_group_by_pin(hw, pin); | ||
470 | if (!grp) { | ||
471 | dev_err(hw->dev, "unable to match pin %d to group\n", | ||
472 | pin); | ||
473 | err = -EINVAL; | ||
474 | goto exit; | ||
475 | } | ||
476 | |||
477 | err = mtk_pctrl_dt_node_to_map_func(hw, pin, func, grp, map, | ||
478 | reserved_maps, num_maps); | ||
479 | if (err < 0) | ||
480 | goto exit; | ||
481 | |||
482 | if (has_config) { | ||
483 | err = pinctrl_utils_add_map_configs(pctldev, map, | ||
484 | reserved_maps, | ||
485 | num_maps, | ||
486 | grp->name, | ||
487 | configs, | ||
488 | num_configs, | ||
489 | PIN_MAP_TYPE_CONFIGS_GROUP); | ||
490 | if (err < 0) | ||
491 | goto exit; | ||
492 | } | ||
493 | } | ||
494 | |||
495 | err = 0; | ||
496 | |||
497 | exit: | ||
498 | kfree(configs); | ||
499 | return err; | ||
500 | } | ||
501 | |||
502 | static int mtk_pctrl_dt_node_to_map(struct pinctrl_dev *pctldev, | ||
503 | struct device_node *np_config, | ||
504 | struct pinctrl_map **map, | ||
505 | unsigned *num_maps) | ||
506 | { | ||
507 | struct device_node *np; | ||
508 | unsigned reserved_maps; | ||
509 | int ret; | ||
510 | |||
511 | *map = NULL; | ||
512 | *num_maps = 0; | ||
513 | reserved_maps = 0; | ||
514 | |||
515 | for_each_child_of_node(np_config, np) { | ||
516 | ret = mtk_pctrl_dt_subnode_to_map(pctldev, np, map, | ||
517 | &reserved_maps, | ||
518 | num_maps); | ||
519 | if (ret < 0) { | ||
520 | pinctrl_utils_free_map(pctldev, *map, *num_maps); | ||
521 | of_node_put(np); | ||
522 | return ret; | ||
523 | } | ||
524 | } | ||
525 | |||
526 | return 0; | ||
527 | } | ||
528 | |||
529 | static int mtk_pctrl_get_groups_count(struct pinctrl_dev *pctldev) | ||
530 | { | ||
531 | struct mtk_pinctrl *hw = pinctrl_dev_get_drvdata(pctldev); | ||
532 | |||
533 | return hw->soc->ngrps; | ||
534 | } | ||
535 | |||
536 | static const char *mtk_pctrl_get_group_name(struct pinctrl_dev *pctldev, | ||
537 | unsigned group) | ||
538 | { | ||
539 | struct mtk_pinctrl *hw = pinctrl_dev_get_drvdata(pctldev); | ||
540 | |||
541 | return hw->groups[group].name; | ||
542 | } | ||
543 | |||
544 | static int mtk_pctrl_get_group_pins(struct pinctrl_dev *pctldev, | ||
545 | unsigned group, const unsigned **pins, | ||
546 | unsigned *num_pins) | ||
547 | { | ||
548 | struct mtk_pinctrl *hw = pinctrl_dev_get_drvdata(pctldev); | ||
549 | |||
550 | *pins = (unsigned *)&hw->groups[group].pin; | ||
551 | *num_pins = 1; | ||
552 | |||
553 | return 0; | ||
554 | } | ||
555 | |||
556 | static const struct pinctrl_ops mtk_pctlops = { | ||
557 | .dt_node_to_map = mtk_pctrl_dt_node_to_map, | ||
558 | .dt_free_map = pinctrl_utils_free_map, | ||
559 | .get_groups_count = mtk_pctrl_get_groups_count, | ||
560 | .get_group_name = mtk_pctrl_get_group_name, | ||
561 | .get_group_pins = mtk_pctrl_get_group_pins, | ||
562 | }; | ||
563 | |||
564 | static int mtk_pmx_get_funcs_cnt(struct pinctrl_dev *pctldev) | ||
565 | { | ||
566 | return ARRAY_SIZE(mtk_gpio_functions); | ||
567 | } | ||
568 | |||
569 | static const char *mtk_pmx_get_func_name(struct pinctrl_dev *pctldev, | ||
570 | unsigned selector) | ||
571 | { | ||
572 | return mtk_gpio_functions[selector]; | ||
573 | } | ||
574 | |||
575 | static int mtk_pmx_get_func_groups(struct pinctrl_dev *pctldev, | ||
576 | unsigned function, | ||
577 | const char * const **groups, | ||
578 | unsigned * const num_groups) | ||
579 | { | ||
580 | struct mtk_pinctrl *hw = pinctrl_dev_get_drvdata(pctldev); | ||
581 | |||
582 | *groups = hw->grp_names; | ||
583 | *num_groups = hw->soc->ngrps; | ||
584 | |||
585 | return 0; | ||
586 | } | ||
587 | |||
588 | static int mtk_pmx_set_mux(struct pinctrl_dev *pctldev, | ||
589 | unsigned function, | ||
590 | unsigned group) | ||
591 | { | ||
592 | struct mtk_pinctrl *hw = pinctrl_dev_get_drvdata(pctldev); | ||
593 | struct mtk_pinctrl_group *grp = hw->groups + group; | ||
594 | const struct mtk_func_desc *desc_func; | ||
595 | const struct mtk_pin_desc *desc; | ||
596 | bool ret; | ||
597 | |||
598 | ret = mtk_pctrl_is_function_valid(hw, grp->pin, function); | ||
599 | if (!ret) { | ||
600 | dev_err(hw->dev, "invalid function %d on group %d .\n", | ||
601 | function, group); | ||
602 | return -EINVAL; | ||
603 | } | ||
604 | |||
605 | desc_func = mtk_pctrl_find_function_by_pin(hw, grp->pin, function); | ||
606 | if (!desc_func) | ||
607 | return -EINVAL; | ||
608 | |||
609 | desc = (const struct mtk_pin_desc *)&hw->soc->pins[grp->pin]; | ||
610 | mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_MODE, desc_func->muxval); | ||
611 | |||
612 | return 0; | ||
613 | } | ||
614 | |||
615 | static const struct pinmux_ops mtk_pmxops = { | ||
616 | .get_functions_count = mtk_pmx_get_funcs_cnt, | ||
617 | .get_function_name = mtk_pmx_get_func_name, | ||
618 | .get_function_groups = mtk_pmx_get_func_groups, | ||
619 | .set_mux = mtk_pmx_set_mux, | ||
620 | .gpio_set_direction = mtk_pinmux_gpio_set_direction, | ||
621 | .gpio_request_enable = mtk_pinmux_gpio_request_enable, | ||
622 | }; | ||
623 | |||
624 | static int mtk_pconf_group_get(struct pinctrl_dev *pctldev, unsigned group, | ||
625 | unsigned long *config) | ||
626 | { | ||
627 | struct mtk_pinctrl *hw = pinctrl_dev_get_drvdata(pctldev); | ||
628 | |||
629 | *config = hw->groups[group].config; | ||
630 | |||
631 | return 0; | ||
632 | } | ||
633 | |||
634 | static int mtk_pconf_group_set(struct pinctrl_dev *pctldev, unsigned group, | ||
635 | unsigned long *configs, unsigned num_configs) | ||
636 | { | ||
637 | struct mtk_pinctrl *hw = pinctrl_dev_get_drvdata(pctldev); | ||
638 | struct mtk_pinctrl_group *grp = &hw->groups[group]; | ||
639 | int i, ret; | ||
640 | |||
641 | for (i = 0; i < num_configs; i++) { | ||
642 | ret = mtk_pinconf_set(pctldev, grp->pin, | ||
643 | pinconf_to_config_param(configs[i]), | ||
644 | pinconf_to_config_argument(configs[i])); | ||
645 | if (ret < 0) | ||
646 | return ret; | ||
647 | |||
648 | grp->config = configs[i]; | ||
649 | } | ||
650 | |||
651 | return 0; | ||
652 | } | ||
653 | |||
654 | static const struct pinconf_ops mtk_confops = { | ||
655 | .pin_config_get = mtk_pinconf_get, | ||
656 | .pin_config_group_get = mtk_pconf_group_get, | ||
657 | .pin_config_group_set = mtk_pconf_group_set, | ||
658 | }; | ||
659 | |||
660 | static struct pinctrl_desc mtk_desc = { | ||
661 | .name = PINCTRL_PINCTRL_DEV, | ||
662 | .pctlops = &mtk_pctlops, | ||
663 | .pmxops = &mtk_pmxops, | ||
664 | .confops = &mtk_confops, | ||
665 | .owner = THIS_MODULE, | ||
666 | }; | ||
667 | |||
668 | static int mtk_gpio_get_direction(struct gpio_chip *chip, unsigned int gpio) | ||
669 | { | ||
670 | struct mtk_pinctrl *hw = gpiochip_get_data(chip); | ||
671 | const struct mtk_pin_desc *desc; | ||
672 | int value, err; | ||
673 | |||
674 | desc = (const struct mtk_pin_desc *)&hw->soc->pins[gpio]; | ||
675 | |||
676 | err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_DIR, &value); | ||
677 | if (err) | ||
678 | return err; | ||
679 | |||
680 | return !value; | ||
681 | } | ||
682 | |||
683 | static int mtk_gpio_get(struct gpio_chip *chip, unsigned int gpio) | ||
684 | { | ||
685 | struct mtk_pinctrl *hw = gpiochip_get_data(chip); | ||
686 | const struct mtk_pin_desc *desc; | ||
687 | int value, err; | ||
688 | |||
689 | desc = (const struct mtk_pin_desc *)&hw->soc->pins[gpio]; | ||
690 | |||
691 | err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_DI, &value); | ||
692 | if (err) | ||
693 | return err; | ||
694 | |||
695 | return !!value; | ||
696 | } | ||
697 | |||
698 | static void mtk_gpio_set(struct gpio_chip *chip, unsigned int gpio, int value) | ||
699 | { | ||
700 | struct mtk_pinctrl *hw = gpiochip_get_data(chip); | ||
701 | const struct mtk_pin_desc *desc; | ||
702 | |||
703 | desc = (const struct mtk_pin_desc *)&hw->soc->pins[gpio]; | ||
704 | |||
705 | mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_DO, !!value); | ||
706 | } | ||
707 | |||
708 | static int mtk_gpio_direction_input(struct gpio_chip *chip, unsigned int gpio) | ||
709 | { | ||
710 | return pinctrl_gpio_direction_input(chip->base + gpio); | ||
711 | } | ||
712 | |||
713 | static int mtk_gpio_direction_output(struct gpio_chip *chip, unsigned int gpio, | ||
714 | int value) | ||
715 | { | ||
716 | mtk_gpio_set(chip, gpio, value); | ||
717 | |||
718 | return pinctrl_gpio_direction_output(chip->base + gpio); | ||
719 | } | ||
720 | |||
721 | static int mtk_gpio_set_config(struct gpio_chip *chip, unsigned int offset, | ||
722 | unsigned long config) | ||
723 | { | ||
724 | struct mtk_pinctrl *hw = gpiochip_get_data(chip); | ||
725 | const struct mtk_pin_desc *desc; | ||
726 | u32 debounce; | ||
727 | |||
728 | desc = (const struct mtk_pin_desc *)&hw->soc->pins[offset]; | ||
729 | |||
730 | if (!hw->eint || | ||
731 | pinconf_to_config_param(config) != PIN_CONFIG_INPUT_DEBOUNCE || | ||
732 | desc->eint.eint_n == EINT_NA) | ||
733 | return -ENOTSUPP; | ||
734 | |||
735 | debounce = pinconf_to_config_argument(config); | ||
736 | |||
737 | return mtk_eint_set_debounce(hw->eint, desc->eint.eint_n, debounce); | ||
738 | } | ||
739 | |||
740 | static int mtk_build_gpiochip(struct mtk_pinctrl *hw, struct device_node *np) | ||
741 | { | ||
742 | struct gpio_chip *chip = &hw->chip; | ||
743 | int ret; | ||
744 | |||
745 | chip->label = PINCTRL_PINCTRL_DEV; | ||
746 | chip->parent = hw->dev; | ||
747 | chip->request = gpiochip_generic_request; | ||
748 | chip->free = gpiochip_generic_free; | ||
749 | chip->get_direction = mtk_gpio_get_direction; | ||
750 | chip->direction_input = mtk_gpio_direction_input; | ||
751 | chip->direction_output = mtk_gpio_direction_output; | ||
752 | chip->get = mtk_gpio_get; | ||
753 | chip->set = mtk_gpio_set; | ||
754 | chip->set_config = mtk_gpio_set_config, | ||
755 | chip->base = -1; | ||
756 | chip->ngpio = hw->soc->npins; | ||
757 | chip->of_node = np; | ||
758 | chip->of_gpio_n_cells = 2; | ||
759 | |||
760 | ret = gpiochip_add_data(chip, hw); | ||
761 | if (ret < 0) | ||
762 | return ret; | ||
763 | |||
764 | return 0; | ||
765 | } | ||
766 | |||
767 | static int mtk_pctrl_build_state(struct platform_device *pdev) | ||
768 | { | ||
769 | struct mtk_pinctrl *hw = platform_get_drvdata(pdev); | ||
770 | int i; | ||
771 | |||
772 | /* Allocate groups */ | ||
773 | hw->groups = devm_kmalloc_array(&pdev->dev, hw->soc->ngrps, | ||
774 | sizeof(*hw->groups), GFP_KERNEL); | ||
775 | if (!hw->groups) | ||
776 | return -ENOMEM; | ||
777 | |||
778 | /* We assume that one pin is one group, use pin name as group name. */ | ||
779 | hw->grp_names = devm_kmalloc_array(&pdev->dev, hw->soc->ngrps, | ||
780 | sizeof(*hw->grp_names), GFP_KERNEL); | ||
781 | if (!hw->grp_names) | ||
782 | return -ENOMEM; | ||
783 | |||
784 | for (i = 0; i < hw->soc->npins; i++) { | ||
785 | const struct mtk_pin_desc *pin = hw->soc->pins + i; | ||
786 | struct mtk_pinctrl_group *group = hw->groups + i; | ||
787 | |||
788 | group->name = pin->name; | ||
789 | group->pin = pin->number; | ||
790 | |||
791 | hw->grp_names[i] = pin->name; | ||
792 | } | ||
793 | |||
794 | return 0; | ||
795 | } | ||
796 | |||
797 | int mtk_paris_pinctrl_probe(struct platform_device *pdev, | ||
798 | const struct mtk_pin_soc *soc) | ||
799 | { | ||
800 | struct pinctrl_pin_desc *pins; | ||
801 | struct mtk_pinctrl *hw; | ||
802 | struct resource *res; | ||
803 | int err, i; | ||
804 | |||
805 | hw = devm_kzalloc(&pdev->dev, sizeof(*hw), GFP_KERNEL); | ||
806 | if (!hw) | ||
807 | return -ENOMEM; | ||
808 | |||
809 | platform_set_drvdata(pdev, hw); | ||
810 | hw->soc = soc; | ||
811 | hw->dev = &pdev->dev; | ||
812 | |||
813 | if (!hw->soc->nbase_names) { | ||
814 | dev_err(&pdev->dev, | ||
815 | "SoC should be assigned at least one register base\n"); | ||
816 | return -EINVAL; | ||
817 | } | ||
818 | |||
819 | hw->base = devm_kmalloc_array(&pdev->dev, hw->soc->nbase_names, | ||
820 | sizeof(*hw->base), GFP_KERNEL); | ||
821 | if (IS_ERR(hw->base)) | ||
822 | return PTR_ERR(hw->base); | ||
823 | |||
824 | for (i = 0; i < hw->soc->nbase_names; i++) { | ||
825 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, | ||
826 | hw->soc->base_names[i]); | ||
827 | if (!res) { | ||
828 | dev_err(&pdev->dev, "missing IO resource\n"); | ||
829 | return -ENXIO; | ||
830 | } | ||
831 | |||
832 | hw->base[i] = devm_ioremap_resource(&pdev->dev, res); | ||
833 | if (IS_ERR(hw->base[i])) | ||
834 | return PTR_ERR(hw->base[i]); | ||
835 | } | ||
836 | |||
837 | hw->nbase = hw->soc->nbase_names; | ||
838 | |||
839 | err = mtk_pctrl_build_state(pdev); | ||
840 | if (err) { | ||
841 | dev_err(&pdev->dev, "build state failed: %d\n", err); | ||
842 | return -EINVAL; | ||
843 | } | ||
844 | |||
845 | /* Copy from internal struct mtk_pin_desc to register to the core */ | ||
846 | pins = devm_kmalloc_array(&pdev->dev, hw->soc->npins, sizeof(*pins), | ||
847 | GFP_KERNEL); | ||
848 | if (IS_ERR(pins)) | ||
849 | return PTR_ERR(pins); | ||
850 | |||
851 | for (i = 0; i < hw->soc->npins; i++) { | ||
852 | pins[i].number = hw->soc->pins[i].number; | ||
853 | pins[i].name = hw->soc->pins[i].name; | ||
854 | } | ||
855 | |||
856 | /* Setup pins descriptions per SoC types */ | ||
857 | mtk_desc.pins = (const struct pinctrl_pin_desc *)pins; | ||
858 | mtk_desc.npins = hw->soc->npins; | ||
859 | mtk_desc.num_custom_params = ARRAY_SIZE(mtk_custom_bindings); | ||
860 | mtk_desc.custom_params = mtk_custom_bindings; | ||
861 | #ifdef CONFIG_DEBUG_FS | ||
862 | mtk_desc.custom_conf_items = mtk_conf_items; | ||
863 | #endif | ||
864 | |||
865 | err = devm_pinctrl_register_and_init(&pdev->dev, &mtk_desc, hw, | ||
866 | &hw->pctrl); | ||
867 | if (err) | ||
868 | return err; | ||
869 | |||
870 | err = pinctrl_enable(hw->pctrl); | ||
871 | if (err) | ||
872 | return err; | ||
873 | |||
874 | /* Build gpiochip should be after pinctrl_enable is done */ | ||
875 | err = mtk_build_gpiochip(hw, pdev->dev.of_node); | ||
876 | if (err) { | ||
877 | dev_err(&pdev->dev, "Failed to add gpio_chip\n"); | ||
878 | return err; | ||
879 | } | ||
880 | |||
881 | platform_set_drvdata(pdev, hw); | ||
882 | |||
883 | return 0; | ||
884 | } | ||
diff --git a/drivers/pinctrl/mediatek/pinctrl-paris.h b/drivers/pinctrl/mediatek/pinctrl-paris.h new file mode 100644 index 000000000000..e4d204e4ce8d --- /dev/null +++ b/drivers/pinctrl/mediatek/pinctrl-paris.h | |||
@@ -0,0 +1,65 @@ | |||
1 | /* SPDX-License-Identifier: GPL-2.0 */ | ||
2 | /* | ||
3 | * Copyright (C) 2018 MediaTek Inc. | ||
4 | * | ||
5 | * Author: Sean Wang <sean.wang@mediatek.com> | ||
6 | * Zhiyong Tao <zhiyong.tao@mediatek.com> | ||
7 | * Hongzhou.Yang <hongzhou.yang@mediatek.com> | ||
8 | */ | ||
9 | #ifndef __PINCTRL_PARIS_H | ||
10 | #define __PINCTRL_PARIS_H | ||
11 | |||
12 | #include <linux/gpio.h> | ||
13 | #include <linux/gpio/driver.h> | ||
14 | #include <linux/io.h> | ||
15 | #include <linux/init.h> | ||
16 | #include <linux/of.h> | ||
17 | #include <linux/of_platform.h> | ||
18 | #include <linux/platform_device.h> | ||
19 | #include <linux/pinctrl/pinctrl.h> | ||
20 | #include <linux/pinctrl/pinmux.h> | ||
21 | #include <linux/pinctrl/pinconf.h> | ||
22 | #include <linux/pinctrl/pinconf-generic.h> | ||
23 | |||
24 | #include "../core.h" | ||
25 | #include "../pinconf.h" | ||
26 | #include "../pinctrl-utils.h" | ||
27 | #include "../pinmux.h" | ||
28 | #include "mtk-eint.h" | ||
29 | #include "pinctrl-mtk-common-v2.h" | ||
30 | |||
31 | #define MTK_RANGE(_a) { .range = (_a), .nranges = ARRAY_SIZE(_a), } | ||
32 | |||
33 | #define MTK_EINT_FUNCTION(_eintmux, _eintnum) \ | ||
34 | { \ | ||
35 | .eint_m = _eintmux, \ | ||
36 | .eint_n = _eintnum, \ | ||
37 | } | ||
38 | |||
39 | #define MTK_FUNCTION(_val, _name) \ | ||
40 | { \ | ||
41 | .muxval = _val, \ | ||
42 | .name = _name, \ | ||
43 | } | ||
44 | |||
45 | #define MTK_PIN(_number, _name, _eint, _drv_n, ...) { \ | ||
46 | .number = _number, \ | ||
47 | .name = _name, \ | ||
48 | .eint = _eint, \ | ||
49 | .drv_n = _drv_n, \ | ||
50 | .funcs = (struct mtk_func_desc[]){ \ | ||
51 | __VA_ARGS__, { } }, \ | ||
52 | } | ||
53 | |||
54 | #define PINCTRL_PIN_GROUP(name, id) \ | ||
55 | { \ | ||
56 | name, \ | ||
57 | id##_pins, \ | ||
58 | ARRAY_SIZE(id##_pins), \ | ||
59 | id##_funcs, \ | ||
60 | } | ||
61 | |||
62 | int mtk_paris_pinctrl_probe(struct platform_device *pdev, | ||
63 | const struct mtk_pin_soc *soc); | ||
64 | |||
65 | #endif /* __PINCTRL_PARIS_H */ | ||