blob: d4e02c5d74a894e61411820d49cb425d72afd81b [file] [log] [blame]
Zhiyong Tao80525092018-09-08 19:07:33 +08001// 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
Linus Walleij22d7fe42018-09-18 15:03:13 -070012#include <linux/gpio/driver.h>
Light Hsieh8174a852020-04-08 04:08:16 +080013#include <linux/module.h>
Zhiyong Tao80525092018-09-08 19:07:33 +080014#include <dt-bindings/pinctrl/mt65xx.h>
15#include "pinctrl-paris.h"
16
17#define PINCTRL_PINCTRL_DEV KBUILD_MODNAME
18
19/* Custom pinconf parameters */
20#define MTK_PIN_CONFIG_TDSEL (PIN_CONFIG_END + 1)
21#define MTK_PIN_CONFIG_RDSEL (PIN_CONFIG_END + 2)
22#define MTK_PIN_CONFIG_PU_ADV (PIN_CONFIG_END + 3)
23#define MTK_PIN_CONFIG_PD_ADV (PIN_CONFIG_END + 4)
Zhiyong Tao5e73de32019-04-01 11:35:35 +080024#define MTK_PIN_CONFIG_DRV_ADV (PIN_CONFIG_END + 5)
Zhiyong Tao80525092018-09-08 19:07:33 +080025
26static const struct pinconf_generic_params mtk_custom_bindings[] = {
27 {"mediatek,tdsel", MTK_PIN_CONFIG_TDSEL, 0},
28 {"mediatek,rdsel", MTK_PIN_CONFIG_RDSEL, 0},
29 {"mediatek,pull-up-adv", MTK_PIN_CONFIG_PU_ADV, 1},
30 {"mediatek,pull-down-adv", MTK_PIN_CONFIG_PD_ADV, 1},
Zhiyong Tao5e73de32019-04-01 11:35:35 +080031 {"mediatek,drive-strength-adv", MTK_PIN_CONFIG_DRV_ADV, 2},
Zhiyong Tao80525092018-09-08 19:07:33 +080032};
33
34#ifdef CONFIG_DEBUG_FS
35static const struct pin_config_item mtk_conf_items[] = {
36 PCONFDUMP(MTK_PIN_CONFIG_TDSEL, "tdsel", NULL, true),
37 PCONFDUMP(MTK_PIN_CONFIG_RDSEL, "rdsel", NULL, true),
38 PCONFDUMP(MTK_PIN_CONFIG_PU_ADV, "pu-adv", NULL, true),
39 PCONFDUMP(MTK_PIN_CONFIG_PD_ADV, "pd-adv", NULL, true),
Zhiyong Tao5e73de32019-04-01 11:35:35 +080040 PCONFDUMP(MTK_PIN_CONFIG_DRV_ADV, "drive-strength-adv", NULL, true),
Zhiyong Tao80525092018-09-08 19:07:33 +080041};
42#endif
43
44static const char * const mtk_gpio_functions[] = {
45 "func0", "func1", "func2", "func3",
46 "func4", "func5", "func6", "func7",
47 "func8", "func9", "func10", "func11",
48 "func12", "func13", "func14", "func15",
49};
50
51static int mtk_pinmux_gpio_request_enable(struct pinctrl_dev *pctldev,
52 struct pinctrl_gpio_range *range,
53 unsigned int pin)
54{
55 struct mtk_pinctrl *hw = pinctrl_dev_get_drvdata(pctldev);
56 const struct mtk_pin_desc *desc;
57
58 desc = (const struct mtk_pin_desc *)&hw->soc->pins[pin];
59
60 return mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_MODE,
61 hw->soc->gpio_m);
62}
63
64static int mtk_pinmux_gpio_set_direction(struct pinctrl_dev *pctldev,
65 struct pinctrl_gpio_range *range,
66 unsigned int pin, bool input)
67{
68 struct mtk_pinctrl *hw = pinctrl_dev_get_drvdata(pctldev);
69 const struct mtk_pin_desc *desc;
70
71 desc = (const struct mtk_pin_desc *)&hw->soc->pins[pin];
72
73 /* hardware would take 0 as input direction */
74 return mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_DIR, !input);
75}
76
77static int mtk_pinconf_get(struct pinctrl_dev *pctldev,
78 unsigned int pin, unsigned long *config)
79{
80 struct mtk_pinctrl *hw = pinctrl_dev_get_drvdata(pctldev);
81 u32 param = pinconf_to_config_param(*config);
Light Hsiehcafe19d2020-01-22 14:53:13 +080082 int pullup, err, reg, ret = 1;
Zhiyong Tao80525092018-09-08 19:07:33 +080083 const struct mtk_pin_desc *desc;
84
Light Hsieh3599cc522020-01-22 14:53:11 +080085 if (pin >= hw->soc->npins) {
86 err = -EINVAL;
87 goto out;
88 }
Zhiyong Tao80525092018-09-08 19:07:33 +080089 desc = (const struct mtk_pin_desc *)&hw->soc->pins[pin];
90
91 switch (param) {
92 case PIN_CONFIG_BIAS_DISABLE:
Zhiyong Tao80525092018-09-08 19:07:33 +080093 case PIN_CONFIG_BIAS_PULL_UP:
Zhiyong Tao80525092018-09-08 19:07:33 +080094 case PIN_CONFIG_BIAS_PULL_DOWN:
Light Hsiehcafe19d2020-01-22 14:53:13 +080095 if (hw->soc->bias_get_combo) {
96 err = hw->soc->bias_get_combo(hw, desc, &pullup, &ret);
97 if (err)
98 goto out;
99 if (param == PIN_CONFIG_BIAS_DISABLE) {
100 if (ret == MTK_PUPD_SET_R1R0_00)
101 ret = MTK_DISABLE;
102 } else if (param == PIN_CONFIG_BIAS_PULL_UP) {
103 /* When desire to get pull-up value, return
104 * error if current setting is pull-down
105 */
106 if (!pullup)
107 err = -EINVAL;
108 } else if (param == PIN_CONFIG_BIAS_PULL_DOWN) {
109 /* When desire to get pull-down value, return
110 * error if current setting is pull-up
111 */
112 if (pullup)
113 err = -EINVAL;
114 }
115 } else {
Light Hsieh3599cc522020-01-22 14:53:11 +0800116 err = -ENOTSUPP;
Light Hsiehcafe19d2020-01-22 14:53:13 +0800117 }
Zhiyong Tao80525092018-09-08 19:07:33 +0800118 break;
119 case PIN_CONFIG_SLEW_RATE:
Light Hsieh1bea6af2020-01-22 14:53:12 +0800120 err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_SR, &ret);
Zhiyong Tao80525092018-09-08 19:07:33 +0800121 break;
122 case PIN_CONFIG_INPUT_ENABLE:
123 case PIN_CONFIG_OUTPUT_ENABLE:
Light Hsieh1bea6af2020-01-22 14:53:12 +0800124 err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_DIR, &ret);
Zhiyong Tao80525092018-09-08 19:07:33 +0800125 if (err)
Light Hsieh3599cc522020-01-22 14:53:11 +0800126 goto out;
127 /* CONFIG Current direction return value
128 * ------------- ----------------- ----------------------
129 * OUTPUT_ENABLE output 1 (= HW value)
130 * input 0 (= HW value)
131 * INPUT_ENABLE output 0 (= reverse HW value)
132 * input 1 (= reverse HW value)
133 */
134 if (param == PIN_CONFIG_INPUT_ENABLE)
Light Hsieh1bea6af2020-01-22 14:53:12 +0800135 ret = !ret;
Zhiyong Tao80525092018-09-08 19:07:33 +0800136
137 break;
138 case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
Light Hsieh1bea6af2020-01-22 14:53:12 +0800139 err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_DIR, &ret);
Zhiyong Tao80525092018-09-08 19:07:33 +0800140 if (err)
Light Hsieh1bea6af2020-01-22 14:53:12 +0800141 goto out;
142 /* return error when in output mode
143 * because schmitt trigger only work in input mode
144 */
145 if (ret) {
146 err = -EINVAL;
147 goto out;
148 }
Zhiyong Tao80525092018-09-08 19:07:33 +0800149
Light Hsieh1bea6af2020-01-22 14:53:12 +0800150 err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_SMT, &ret);
Zhiyong Tao80525092018-09-08 19:07:33 +0800151
152 break;
153 case PIN_CONFIG_DRIVE_STRENGTH:
Light Hsieh3599cc522020-01-22 14:53:11 +0800154 if (hw->soc->drive_get)
Zhiyong Tao80525092018-09-08 19:07:33 +0800155 err = hw->soc->drive_get(hw, desc, &ret);
Light Hsieh3599cc522020-01-22 14:53:11 +0800156 else
Zhiyong Tao80525092018-09-08 19:07:33 +0800157 err = -ENOTSUPP;
Zhiyong Tao80525092018-09-08 19:07:33 +0800158 break;
159 case MTK_PIN_CONFIG_TDSEL:
160 case MTK_PIN_CONFIG_RDSEL:
161 reg = (param == MTK_PIN_CONFIG_TDSEL) ?
162 PINCTRL_PIN_REG_TDSEL : PINCTRL_PIN_REG_RDSEL;
Light Hsieh1bea6af2020-01-22 14:53:12 +0800163 err = mtk_hw_get_value(hw, desc, reg, &ret);
Zhiyong Tao80525092018-09-08 19:07:33 +0800164 break;
165 case MTK_PIN_CONFIG_PU_ADV:
166 case MTK_PIN_CONFIG_PD_ADV:
167 if (hw->soc->adv_pull_get) {
Zhiyong Tao80525092018-09-08 19:07:33 +0800168 pullup = param == MTK_PIN_CONFIG_PU_ADV;
169 err = hw->soc->adv_pull_get(hw, desc, pullup, &ret);
Light Hsieh3599cc522020-01-22 14:53:11 +0800170 } else
171 err = -ENOTSUPP;
Zhiyong Tao80525092018-09-08 19:07:33 +0800172 break;
Zhiyong Tao5e73de32019-04-01 11:35:35 +0800173 case MTK_PIN_CONFIG_DRV_ADV:
Light Hsieh3599cc522020-01-22 14:53:11 +0800174 if (hw->soc->adv_drive_get)
Zhiyong Tao5e73de32019-04-01 11:35:35 +0800175 err = hw->soc->adv_drive_get(hw, desc, &ret);
Light Hsieh3599cc522020-01-22 14:53:11 +0800176 else
177 err = -ENOTSUPP;
Zhiyong Tao5e73de32019-04-01 11:35:35 +0800178 break;
Zhiyong Tao80525092018-09-08 19:07:33 +0800179 default:
Light Hsieh3599cc522020-01-22 14:53:11 +0800180 err = -ENOTSUPP;
Zhiyong Tao80525092018-09-08 19:07:33 +0800181 }
182
Light Hsieh3599cc522020-01-22 14:53:11 +0800183out:
184 if (!err)
185 *config = pinconf_to_config_packed(param, ret);
Zhiyong Tao80525092018-09-08 19:07:33 +0800186
Light Hsieh3599cc522020-01-22 14:53:11 +0800187 return err;
Zhiyong Tao80525092018-09-08 19:07:33 +0800188}
189
190static int mtk_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin,
191 enum pin_config_param param,
192 enum pin_config_param arg)
193{
194 struct mtk_pinctrl *hw = pinctrl_dev_get_drvdata(pctldev);
195 const struct mtk_pin_desc *desc;
196 int err = 0;
197 u32 reg;
198
Light Hsieh3de7dee2020-01-22 14:53:09 +0800199 if (pin >= hw->soc->npins) {
200 err = -EINVAL;
201 goto err;
202 }
Zhiyong Tao80525092018-09-08 19:07:33 +0800203 desc = (const struct mtk_pin_desc *)&hw->soc->pins[pin];
204
205 switch ((u32)param) {
206 case PIN_CONFIG_BIAS_DISABLE:
Light Hsiehcafe19d2020-01-22 14:53:13 +0800207 if (hw->soc->bias_set_combo)
208 err = hw->soc->bias_set_combo(hw, desc, 0, MTK_DISABLE);
Light Hsieh3599cc522020-01-22 14:53:11 +0800209 else
210 err = -ENOTSUPP;
Zhiyong Tao80525092018-09-08 19:07:33 +0800211 break;
212 case PIN_CONFIG_BIAS_PULL_UP:
Light Hsiehcafe19d2020-01-22 14:53:13 +0800213 if (hw->soc->bias_set_combo)
214 err = hw->soc->bias_set_combo(hw, desc, 1, arg);
Light Hsieh3599cc522020-01-22 14:53:11 +0800215 else
216 err = -ENOTSUPP;
Zhiyong Tao80525092018-09-08 19:07:33 +0800217 break;
218 case PIN_CONFIG_BIAS_PULL_DOWN:
Light Hsiehcafe19d2020-01-22 14:53:13 +0800219 if (hw->soc->bias_set_combo)
220 err = hw->soc->bias_set_combo(hw, desc, 0, arg);
Light Hsieh3599cc522020-01-22 14:53:11 +0800221 else
222 err = -ENOTSUPP;
Zhiyong Tao80525092018-09-08 19:07:33 +0800223 break;
224 case PIN_CONFIG_OUTPUT_ENABLE:
225 err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_SMT,
226 MTK_DISABLE);
Light Hsieh3599cc522020-01-22 14:53:11 +0800227 /* Keep set direction to consider the case that a GPIO pin
228 * does not have SMT control
229 */
230 if (err != -ENOTSUPP)
Zhiyong Tao80525092018-09-08 19:07:33 +0800231 goto err;
232
233 err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_DIR,
234 MTK_OUTPUT);
Zhiyong Tao80525092018-09-08 19:07:33 +0800235 break;
236 case PIN_CONFIG_INPUT_ENABLE:
Light Hsieh3599cc522020-01-22 14:53:11 +0800237 /* regard all non-zero value as enable */
238 err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_IES, !!arg);
239 if (err)
240 goto err;
Zhiyong Tao80525092018-09-08 19:07:33 +0800241
242 err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_DIR,
243 MTK_INPUT);
Zhiyong Tao80525092018-09-08 19:07:33 +0800244 break;
245 case PIN_CONFIG_SLEW_RATE:
Light Hsieh3599cc522020-01-22 14:53:11 +0800246 /* regard all non-zero value as enable */
247 err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_SR, !!arg);
Zhiyong Tao80525092018-09-08 19:07:33 +0800248 break;
249 case PIN_CONFIG_OUTPUT:
Zhiyong Tao517c3f52020-11-20 17:30:58 +0800250 err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_DO,
251 arg);
Zhiyong Tao80525092018-09-08 19:07:33 +0800252 if (err)
253 goto err;
254
Zhiyong Tao517c3f52020-11-20 17:30:58 +0800255 err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_DIR,
256 MTK_OUTPUT);
Zhiyong Tao80525092018-09-08 19:07:33 +0800257 break;
Light Hsieh3599cc522020-01-22 14:53:11 +0800258 case PIN_CONFIG_INPUT_SCHMITT:
Zhiyong Tao80525092018-09-08 19:07:33 +0800259 case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
260 /* arg = 1: Input mode & SMT enable ;
261 * arg = 0: Output mode & SMT disable
262 */
Light Hsieh3599cc522020-01-22 14:53:11 +0800263 err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_DIR, !arg);
Zhiyong Tao80525092018-09-08 19:07:33 +0800264 if (err)
265 goto err;
266
Light Hsieh3599cc522020-01-22 14:53:11 +0800267 err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_SMT, !!arg);
Zhiyong Tao80525092018-09-08 19:07:33 +0800268 break;
269 case PIN_CONFIG_DRIVE_STRENGTH:
Light Hsieh3599cc522020-01-22 14:53:11 +0800270 if (hw->soc->drive_set)
Zhiyong Tao80525092018-09-08 19:07:33 +0800271 err = hw->soc->drive_set(hw, desc, arg);
Light Hsieh3599cc522020-01-22 14:53:11 +0800272 else
273 err = -ENOTSUPP;
Zhiyong Tao80525092018-09-08 19:07:33 +0800274 break;
275 case MTK_PIN_CONFIG_TDSEL:
276 case MTK_PIN_CONFIG_RDSEL:
277 reg = (param == MTK_PIN_CONFIG_TDSEL) ?
278 PINCTRL_PIN_REG_TDSEL : PINCTRL_PIN_REG_RDSEL;
Zhiyong Tao80525092018-09-08 19:07:33 +0800279 err = mtk_hw_set_value(hw, desc, reg, arg);
Zhiyong Tao80525092018-09-08 19:07:33 +0800280 break;
281 case MTK_PIN_CONFIG_PU_ADV:
282 case MTK_PIN_CONFIG_PD_ADV:
283 if (hw->soc->adv_pull_set) {
284 bool pullup;
285
286 pullup = param == MTK_PIN_CONFIG_PU_ADV;
287 err = hw->soc->adv_pull_set(hw, desc, pullup,
288 arg);
Light Hsieh3599cc522020-01-22 14:53:11 +0800289 } else
290 err = -ENOTSUPP;
Zhiyong Tao80525092018-09-08 19:07:33 +0800291 break;
Zhiyong Tao5e73de32019-04-01 11:35:35 +0800292 case MTK_PIN_CONFIG_DRV_ADV:
Light Hsieh3599cc522020-01-22 14:53:11 +0800293 if (hw->soc->adv_drive_set)
Zhiyong Tao5e73de32019-04-01 11:35:35 +0800294 err = hw->soc->adv_drive_set(hw, desc, arg);
Light Hsieh3599cc522020-01-22 14:53:11 +0800295 else
296 err = -ENOTSUPP;
Zhiyong Tao5e73de32019-04-01 11:35:35 +0800297 break;
Zhiyong Tao80525092018-09-08 19:07:33 +0800298 default:
299 err = -ENOTSUPP;
300 }
301
302err:
303 return err;
304}
305
306static struct mtk_pinctrl_group *
307mtk_pctrl_find_group_by_pin(struct mtk_pinctrl *hw, u32 pin)
308{
309 int i;
310
311 for (i = 0; i < hw->soc->ngrps; i++) {
312 struct mtk_pinctrl_group *grp = hw->groups + i;
313
314 if (grp->pin == pin)
315 return grp;
316 }
317
318 return NULL;
319}
320
321static const struct mtk_func_desc *
322mtk_pctrl_find_function_by_pin(struct mtk_pinctrl *hw, u32 pin_num, u32 fnum)
323{
324 const struct mtk_pin_desc *pin = hw->soc->pins + pin_num;
325 const struct mtk_func_desc *func = pin->funcs;
326
327 while (func && func->name) {
328 if (func->muxval == fnum)
329 return func;
330 func++;
331 }
332
333 return NULL;
334}
335
336static bool mtk_pctrl_is_function_valid(struct mtk_pinctrl *hw, u32 pin_num,
337 u32 fnum)
338{
339 int i;
340
341 for (i = 0; i < hw->soc->npins; i++) {
342 const struct mtk_pin_desc *pin = hw->soc->pins + i;
343
344 if (pin->number == pin_num) {
345 const struct mtk_func_desc *func = pin->funcs;
346
347 while (func && func->name) {
348 if (func->muxval == fnum)
349 return true;
350 func++;
351 }
352
353 break;
354 }
355 }
356
357 return false;
358}
359
360static int mtk_pctrl_dt_node_to_map_func(struct mtk_pinctrl *pctl,
361 u32 pin, u32 fnum,
362 struct mtk_pinctrl_group *grp,
363 struct pinctrl_map **map,
364 unsigned *reserved_maps,
365 unsigned *num_maps)
366{
367 bool ret;
368
369 if (*num_maps == *reserved_maps)
370 return -ENOSPC;
371
372 (*map)[*num_maps].type = PIN_MAP_TYPE_MUX_GROUP;
373 (*map)[*num_maps].data.mux.group = grp->name;
374
375 ret = mtk_pctrl_is_function_valid(pctl, pin, fnum);
376 if (!ret) {
377 dev_err(pctl->dev, "invalid function %d on pin %d .\n",
378 fnum, pin);
379 return -EINVAL;
380 }
381
382 (*map)[*num_maps].data.mux.function = mtk_gpio_functions[fnum];
383 (*num_maps)++;
384
385 return 0;
386}
387
388static int mtk_pctrl_dt_subnode_to_map(struct pinctrl_dev *pctldev,
389 struct device_node *node,
390 struct pinctrl_map **map,
391 unsigned *reserved_maps,
392 unsigned *num_maps)
393{
394 struct mtk_pinctrl *hw = pinctrl_dev_get_drvdata(pctldev);
395 int num_pins, num_funcs, maps_per_pin, i, err;
396 struct mtk_pinctrl_group *grp;
397 unsigned int num_configs;
398 bool has_config = false;
399 unsigned long *configs;
400 u32 pinfunc, pin, func;
401 struct property *pins;
402 unsigned reserve = 0;
403
404 pins = of_find_property(node, "pinmux", NULL);
405 if (!pins) {
Rob Herring9ede2a72018-11-16 16:05:40 -0600406 dev_err(hw->dev, "missing pins property in node %pOFn .\n",
407 node);
Zhiyong Tao80525092018-09-08 19:07:33 +0800408 return -EINVAL;
409 }
410
411 err = pinconf_generic_parse_dt_config(node, pctldev, &configs,
412 &num_configs);
413 if (err)
414 return err;
415
416 if (num_configs)
417 has_config = true;
418
419 num_pins = pins->length / sizeof(u32);
420 num_funcs = num_pins;
421 maps_per_pin = 0;
422 if (num_funcs)
423 maps_per_pin++;
424 if (has_config && num_pins >= 1)
425 maps_per_pin++;
426
427 if (!num_pins || !maps_per_pin) {
428 err = -EINVAL;
429 goto exit;
430 }
431
432 reserve = num_pins * maps_per_pin;
433
434 err = pinctrl_utils_reserve_map(pctldev, map, reserved_maps, num_maps,
435 reserve);
436 if (err < 0)
437 goto exit;
438
439 for (i = 0; i < num_pins; i++) {
440 err = of_property_read_u32_index(node, "pinmux", i, &pinfunc);
441 if (err)
442 goto exit;
443
444 pin = MTK_GET_PIN_NO(pinfunc);
445 func = MTK_GET_PIN_FUNC(pinfunc);
446
447 if (pin >= hw->soc->npins ||
448 func >= ARRAY_SIZE(mtk_gpio_functions)) {
449 dev_err(hw->dev, "invalid pins value.\n");
450 err = -EINVAL;
451 goto exit;
452 }
453
454 grp = mtk_pctrl_find_group_by_pin(hw, pin);
455 if (!grp) {
456 dev_err(hw->dev, "unable to match pin %d to group\n",
457 pin);
458 err = -EINVAL;
459 goto exit;
460 }
461
462 err = mtk_pctrl_dt_node_to_map_func(hw, pin, func, grp, map,
463 reserved_maps, num_maps);
464 if (err < 0)
465 goto exit;
466
467 if (has_config) {
468 err = pinctrl_utils_add_map_configs(pctldev, map,
469 reserved_maps,
470 num_maps,
471 grp->name,
472 configs,
473 num_configs,
474 PIN_MAP_TYPE_CONFIGS_GROUP);
475 if (err < 0)
476 goto exit;
477 }
478 }
479
480 err = 0;
481
482exit:
483 kfree(configs);
484 return err;
485}
486
487static int mtk_pctrl_dt_node_to_map(struct pinctrl_dev *pctldev,
488 struct device_node *np_config,
489 struct pinctrl_map **map,
490 unsigned *num_maps)
491{
492 struct device_node *np;
493 unsigned reserved_maps;
494 int ret;
495
496 *map = NULL;
497 *num_maps = 0;
498 reserved_maps = 0;
499
500 for_each_child_of_node(np_config, np) {
501 ret = mtk_pctrl_dt_subnode_to_map(pctldev, np, map,
502 &reserved_maps,
503 num_maps);
504 if (ret < 0) {
505 pinctrl_utils_free_map(pctldev, *map, *num_maps);
506 of_node_put(np);
507 return ret;
508 }
509 }
510
511 return 0;
512}
513
514static int mtk_pctrl_get_groups_count(struct pinctrl_dev *pctldev)
515{
516 struct mtk_pinctrl *hw = pinctrl_dev_get_drvdata(pctldev);
517
518 return hw->soc->ngrps;
519}
520
521static const char *mtk_pctrl_get_group_name(struct pinctrl_dev *pctldev,
522 unsigned group)
523{
524 struct mtk_pinctrl *hw = pinctrl_dev_get_drvdata(pctldev);
525
526 return hw->groups[group].name;
527}
528
529static int mtk_pctrl_get_group_pins(struct pinctrl_dev *pctldev,
530 unsigned group, const unsigned **pins,
531 unsigned *num_pins)
532{
533 struct mtk_pinctrl *hw = pinctrl_dev_get_drvdata(pctldev);
534
535 *pins = (unsigned *)&hw->groups[group].pin;
536 *num_pins = 1;
537
538 return 0;
539}
540
Light Hsieh184d8e12020-01-22 14:53:14 +0800541static int mtk_hw_get_value_wrap(struct mtk_pinctrl *hw, unsigned int gpio, int field)
542{
543 const struct mtk_pin_desc *desc;
544 int value, err;
545
Dan Carpenter3385ab72020-02-18 08:52:47 +0300546 if (gpio >= hw->soc->npins)
Light Hsieh184d8e12020-01-22 14:53:14 +0800547 return -EINVAL;
548
549 desc = (const struct mtk_pin_desc *)&hw->soc->pins[gpio];
550
551 err = mtk_hw_get_value(hw, desc, field, &value);
552 if (err)
553 return err;
554
555 return value;
556}
557
558#define mtk_pctrl_get_pinmux(hw, gpio) \
559 mtk_hw_get_value_wrap(hw, gpio, PINCTRL_PIN_REG_MODE)
560
561#define mtk_pctrl_get_direction(hw, gpio) \
562 mtk_hw_get_value_wrap(hw, gpio, PINCTRL_PIN_REG_DIR)
563
564#define mtk_pctrl_get_out(hw, gpio) \
565 mtk_hw_get_value_wrap(hw, gpio, PINCTRL_PIN_REG_DO)
566
567#define mtk_pctrl_get_in(hw, gpio) \
568 mtk_hw_get_value_wrap(hw, gpio, PINCTRL_PIN_REG_DI)
569
570#define mtk_pctrl_get_smt(hw, gpio) \
571 mtk_hw_get_value_wrap(hw, gpio, PINCTRL_PIN_REG_SMT)
572
573#define mtk_pctrl_get_ies(hw, gpio) \
574 mtk_hw_get_value_wrap(hw, gpio, PINCTRL_PIN_REG_IES)
575
576#define mtk_pctrl_get_driving(hw, gpio) \
577 mtk_hw_get_value_wrap(hw, gpio, PINCTRL_PIN_REG_DRV)
578
579ssize_t mtk_pctrl_show_one_pin(struct mtk_pinctrl *hw,
Zhiyong Tao25a74c02021-09-24 16:06:30 +0800580 unsigned int gpio, char *buf, unsigned int buf_len)
Light Hsieh184d8e12020-01-22 14:53:14 +0800581{
Zhiyong Taofb34a9a2021-09-24 16:06:31 +0800582 int pinmux, pullup, pullen, len = 0, r1 = -1, r0 = -1, rsel = -1;
Light Hsieh184d8e12020-01-22 14:53:14 +0800583 const struct mtk_pin_desc *desc;
Zhiyong Taofb34a9a2021-09-24 16:06:31 +0800584 u32 try_all_type;
Light Hsieh184d8e12020-01-22 14:53:14 +0800585
Dan Carpenter3385ab72020-02-18 08:52:47 +0300586 if (gpio >= hw->soc->npins)
Light Hsieh184d8e12020-01-22 14:53:14 +0800587 return -EINVAL;
588
589 desc = (const struct mtk_pin_desc *)&hw->soc->pins[gpio];
590 pinmux = mtk_pctrl_get_pinmux(hw, gpio);
591 if (pinmux >= hw->soc->nfuncs)
592 pinmux -= hw->soc->nfuncs;
593
594 mtk_pinconf_bias_get_combo(hw, desc, &pullup, &pullen);
Zhiyong Taofb34a9a2021-09-24 16:06:31 +0800595
596 if (hw->soc->pull_type)
597 try_all_type = hw->soc->pull_type[desc->number];
598
599 if (hw->rsel_si_unit && (try_all_type & MTK_PULL_RSEL_TYPE)) {
600 rsel = pullen;
Light Hsieh184d8e12020-01-22 14:53:14 +0800601 pullen = 1;
Zhiyong Taofb34a9a2021-09-24 16:06:31 +0800602 } else {
603 /* Case for: R1R0 */
604 if (pullen == MTK_PUPD_SET_R1R0_00) {
605 pullen = 0;
606 r1 = 0;
607 r0 = 0;
608 } else if (pullen == MTK_PUPD_SET_R1R0_01) {
609 pullen = 1;
610 r1 = 0;
611 r0 = 1;
612 } else if (pullen == MTK_PUPD_SET_R1R0_10) {
613 pullen = 1;
614 r1 = 1;
615 r0 = 0;
616 } else if (pullen == MTK_PUPD_SET_R1R0_11) {
617 pullen = 1;
618 r1 = 1;
619 r0 = 1;
620 }
621
622 /* Case for: RSEL */
623 if (pullen >= MTK_PULL_SET_RSEL_000 &&
624 pullen <= MTK_PULL_SET_RSEL_111) {
625 rsel = pullen - MTK_PULL_SET_RSEL_000;
626 pullen = 1;
627 }
Light Hsieh184d8e12020-01-22 14:53:14 +0800628 }
Zhiyong Tao25a74c02021-09-24 16:06:30 +0800629 len += scnprintf(buf + len, buf_len - len,
Light Hsieh184d8e12020-01-22 14:53:14 +0800630 "%03d: %1d%1d%1d%1d%02d%1d%1d%1d%1d",
631 gpio,
632 pinmux,
633 mtk_pctrl_get_direction(hw, gpio),
634 mtk_pctrl_get_out(hw, gpio),
635 mtk_pctrl_get_in(hw, gpio),
636 mtk_pctrl_get_driving(hw, gpio),
637 mtk_pctrl_get_smt(hw, gpio),
638 mtk_pctrl_get_ies(hw, gpio),
639 pullen,
640 pullup);
641
642 if (r1 != -1) {
Zhiyong Tao25a74c02021-09-24 16:06:30 +0800643 len += scnprintf(buf + len, buf_len - len, " (%1d %1d)\n",
Light Hsieh184d8e12020-01-22 14:53:14 +0800644 r1, r0);
Zhiyong Taofb34a9a2021-09-24 16:06:31 +0800645 } else if (rsel != -1) {
646 len += scnprintf(buf + len, buf_len - len, " (%1d)\n", rsel);
Light Hsieh184d8e12020-01-22 14:53:14 +0800647 } else {
Zhiyong Tao25a74c02021-09-24 16:06:30 +0800648 len += scnprintf(buf + len, buf_len - len, "\n");
Light Hsieh184d8e12020-01-22 14:53:14 +0800649 }
650
651 return len;
652}
Light Hsieh8174a852020-04-08 04:08:16 +0800653EXPORT_SYMBOL_GPL(mtk_pctrl_show_one_pin);
Light Hsieh184d8e12020-01-22 14:53:14 +0800654
655#define PIN_DBG_BUF_SZ 96
656static void mtk_pctrl_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s,
657 unsigned int gpio)
658{
659 struct mtk_pinctrl *hw = pinctrl_dev_get_drvdata(pctldev);
660 char buf[PIN_DBG_BUF_SZ];
661
662 (void)mtk_pctrl_show_one_pin(hw, gpio, buf, PIN_DBG_BUF_SZ);
663
664 seq_printf(s, "%s", buf);
665}
666
Zhiyong Tao80525092018-09-08 19:07:33 +0800667static const struct pinctrl_ops mtk_pctlops = {
668 .dt_node_to_map = mtk_pctrl_dt_node_to_map,
669 .dt_free_map = pinctrl_utils_free_map,
670 .get_groups_count = mtk_pctrl_get_groups_count,
671 .get_group_name = mtk_pctrl_get_group_name,
672 .get_group_pins = mtk_pctrl_get_group_pins,
Light Hsieh184d8e12020-01-22 14:53:14 +0800673 .pin_dbg_show = mtk_pctrl_dbg_show,
Zhiyong Tao80525092018-09-08 19:07:33 +0800674};
675
676static int mtk_pmx_get_funcs_cnt(struct pinctrl_dev *pctldev)
677{
678 return ARRAY_SIZE(mtk_gpio_functions);
679}
680
681static const char *mtk_pmx_get_func_name(struct pinctrl_dev *pctldev,
682 unsigned selector)
683{
684 return mtk_gpio_functions[selector];
685}
686
687static int mtk_pmx_get_func_groups(struct pinctrl_dev *pctldev,
688 unsigned function,
689 const char * const **groups,
690 unsigned * const num_groups)
691{
692 struct mtk_pinctrl *hw = pinctrl_dev_get_drvdata(pctldev);
693
694 *groups = hw->grp_names;
695 *num_groups = hw->soc->ngrps;
696
697 return 0;
698}
699
700static int mtk_pmx_set_mux(struct pinctrl_dev *pctldev,
701 unsigned function,
702 unsigned group)
703{
704 struct mtk_pinctrl *hw = pinctrl_dev_get_drvdata(pctldev);
705 struct mtk_pinctrl_group *grp = hw->groups + group;
706 const struct mtk_func_desc *desc_func;
707 const struct mtk_pin_desc *desc;
708 bool ret;
709
710 ret = mtk_pctrl_is_function_valid(hw, grp->pin, function);
711 if (!ret) {
712 dev_err(hw->dev, "invalid function %d on group %d .\n",
713 function, group);
714 return -EINVAL;
715 }
716
717 desc_func = mtk_pctrl_find_function_by_pin(hw, grp->pin, function);
718 if (!desc_func)
719 return -EINVAL;
720
721 desc = (const struct mtk_pin_desc *)&hw->soc->pins[grp->pin];
722 mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_MODE, desc_func->muxval);
723
724 return 0;
725}
726
727static const struct pinmux_ops mtk_pmxops = {
728 .get_functions_count = mtk_pmx_get_funcs_cnt,
729 .get_function_name = mtk_pmx_get_func_name,
730 .get_function_groups = mtk_pmx_get_func_groups,
731 .set_mux = mtk_pmx_set_mux,
732 .gpio_set_direction = mtk_pinmux_gpio_set_direction,
733 .gpio_request_enable = mtk_pinmux_gpio_request_enable,
734};
735
736static int mtk_pconf_group_get(struct pinctrl_dev *pctldev, unsigned group,
737 unsigned long *config)
738{
739 struct mtk_pinctrl *hw = pinctrl_dev_get_drvdata(pctldev);
740
741 *config = hw->groups[group].config;
742
743 return 0;
744}
745
746static int mtk_pconf_group_set(struct pinctrl_dev *pctldev, unsigned group,
747 unsigned long *configs, unsigned num_configs)
748{
749 struct mtk_pinctrl *hw = pinctrl_dev_get_drvdata(pctldev);
750 struct mtk_pinctrl_group *grp = &hw->groups[group];
751 int i, ret;
752
753 for (i = 0; i < num_configs; i++) {
754 ret = mtk_pinconf_set(pctldev, grp->pin,
755 pinconf_to_config_param(configs[i]),
756 pinconf_to_config_argument(configs[i]));
757 if (ret < 0)
758 return ret;
759
760 grp->config = configs[i];
761 }
762
763 return 0;
764}
765
766static const struct pinconf_ops mtk_confops = {
767 .pin_config_get = mtk_pinconf_get,
768 .pin_config_group_get = mtk_pconf_group_get,
769 .pin_config_group_set = mtk_pconf_group_set,
Light Hsieh184d8e12020-01-22 14:53:14 +0800770 .is_generic = true,
Zhiyong Tao80525092018-09-08 19:07:33 +0800771};
772
773static struct pinctrl_desc mtk_desc = {
774 .name = PINCTRL_PINCTRL_DEV,
775 .pctlops = &mtk_pctlops,
776 .pmxops = &mtk_pmxops,
777 .confops = &mtk_confops,
778 .owner = THIS_MODULE,
779};
780
781static int mtk_gpio_get_direction(struct gpio_chip *chip, unsigned int gpio)
782{
783 struct mtk_pinctrl *hw = gpiochip_get_data(chip);
784 const struct mtk_pin_desc *desc;
785 int value, err;
786
Dan Carpenter3385ab72020-02-18 08:52:47 +0300787 if (gpio >= hw->soc->npins)
Light Hsieh3de7dee2020-01-22 14:53:09 +0800788 return -EINVAL;
789
Hanks Chenedd54642020-07-23 19:19:53 +0800790 /*
791 * "Virtual" GPIOs are always and only used for interrupts
792 * Since they are only used for interrupts, they are always inputs
793 */
794 if (mtk_is_virt_gpio(hw, gpio))
795 return 1;
796
Zhiyong Tao80525092018-09-08 19:07:33 +0800797 desc = (const struct mtk_pin_desc *)&hw->soc->pins[gpio];
798
799 err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_DIR, &value);
800 if (err)
801 return err;
802
Matti Vaittinen3c827872020-02-14 15:57:12 +0200803 if (value)
804 return GPIO_LINE_DIRECTION_OUT;
805
806 return GPIO_LINE_DIRECTION_IN;
Zhiyong Tao80525092018-09-08 19:07:33 +0800807}
808
809static int mtk_gpio_get(struct gpio_chip *chip, unsigned int gpio)
810{
811 struct mtk_pinctrl *hw = gpiochip_get_data(chip);
812 const struct mtk_pin_desc *desc;
813 int value, err;
814
Dan Carpenter3385ab72020-02-18 08:52:47 +0300815 if (gpio >= hw->soc->npins)
Light Hsieh3de7dee2020-01-22 14:53:09 +0800816 return -EINVAL;
817
Zhiyong Tao80525092018-09-08 19:07:33 +0800818 desc = (const struct mtk_pin_desc *)&hw->soc->pins[gpio];
819
820 err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_DI, &value);
821 if (err)
822 return err;
823
824 return !!value;
825}
826
827static void mtk_gpio_set(struct gpio_chip *chip, unsigned int gpio, int value)
828{
829 struct mtk_pinctrl *hw = gpiochip_get_data(chip);
830 const struct mtk_pin_desc *desc;
831
Dan Carpenter3385ab72020-02-18 08:52:47 +0300832 if (gpio >= hw->soc->npins)
Light Hsieh3de7dee2020-01-22 14:53:09 +0800833 return;
834
Zhiyong Tao80525092018-09-08 19:07:33 +0800835 desc = (const struct mtk_pin_desc *)&hw->soc->pins[gpio];
836
837 mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_DO, !!value);
838}
839
840static int mtk_gpio_direction_input(struct gpio_chip *chip, unsigned int gpio)
841{
Light Hsieh3de7dee2020-01-22 14:53:09 +0800842 struct mtk_pinctrl *hw = gpiochip_get_data(chip);
843
Dan Carpenter3385ab72020-02-18 08:52:47 +0300844 if (gpio >= hw->soc->npins)
Light Hsieh3de7dee2020-01-22 14:53:09 +0800845 return -EINVAL;
846
Zhiyong Tao80525092018-09-08 19:07:33 +0800847 return pinctrl_gpio_direction_input(chip->base + gpio);
848}
849
850static int mtk_gpio_direction_output(struct gpio_chip *chip, unsigned int gpio,
851 int value)
852{
Light Hsieh3de7dee2020-01-22 14:53:09 +0800853 struct mtk_pinctrl *hw = gpiochip_get_data(chip);
854
Dan Carpenter3385ab72020-02-18 08:52:47 +0300855 if (gpio >= hw->soc->npins)
Light Hsieh3de7dee2020-01-22 14:53:09 +0800856 return -EINVAL;
857
Zhiyong Tao80525092018-09-08 19:07:33 +0800858 mtk_gpio_set(chip, gpio, value);
859
860 return pinctrl_gpio_direction_output(chip->base + gpio);
861}
862
Sean Wang65618592018-09-08 19:07:38 +0800863static int mtk_gpio_to_irq(struct gpio_chip *chip, unsigned int offset)
864{
865 struct mtk_pinctrl *hw = gpiochip_get_data(chip);
866 const struct mtk_pin_desc *desc;
867
868 if (!hw->eint)
869 return -ENOTSUPP;
870
871 desc = (const struct mtk_pin_desc *)&hw->soc->pins[offset];
872
873 if (desc->eint.eint_n == EINT_NA)
874 return -ENOTSUPP;
875
876 return mtk_eint_find_irq(hw->eint, desc->eint.eint_n);
877}
878
Zhiyong Tao80525092018-09-08 19:07:33 +0800879static int mtk_gpio_set_config(struct gpio_chip *chip, unsigned int offset,
880 unsigned long config)
881{
882 struct mtk_pinctrl *hw = gpiochip_get_data(chip);
883 const struct mtk_pin_desc *desc;
884 u32 debounce;
885
886 desc = (const struct mtk_pin_desc *)&hw->soc->pins[offset];
887
888 if (!hw->eint ||
889 pinconf_to_config_param(config) != PIN_CONFIG_INPUT_DEBOUNCE ||
890 desc->eint.eint_n == EINT_NA)
891 return -ENOTSUPP;
892
893 debounce = pinconf_to_config_argument(config);
894
895 return mtk_eint_set_debounce(hw->eint, desc->eint.eint_n, debounce);
896}
897
898static int mtk_build_gpiochip(struct mtk_pinctrl *hw, struct device_node *np)
899{
900 struct gpio_chip *chip = &hw->chip;
901 int ret;
902
903 chip->label = PINCTRL_PINCTRL_DEV;
904 chip->parent = hw->dev;
905 chip->request = gpiochip_generic_request;
906 chip->free = gpiochip_generic_free;
907 chip->get_direction = mtk_gpio_get_direction;
908 chip->direction_input = mtk_gpio_direction_input;
909 chip->direction_output = mtk_gpio_direction_output;
910 chip->get = mtk_gpio_get;
911 chip->set = mtk_gpio_set;
Zheng Yongjun8ad57492020-12-11 16:47:17 +0800912 chip->to_irq = mtk_gpio_to_irq;
913 chip->set_config = mtk_gpio_set_config;
Zhiyong Tao80525092018-09-08 19:07:33 +0800914 chip->base = -1;
915 chip->ngpio = hw->soc->npins;
916 chip->of_node = np;
917 chip->of_gpio_n_cells = 2;
918
919 ret = gpiochip_add_data(chip, hw);
920 if (ret < 0)
921 return ret;
922
923 return 0;
924}
925
926static int mtk_pctrl_build_state(struct platform_device *pdev)
927{
928 struct mtk_pinctrl *hw = platform_get_drvdata(pdev);
929 int i;
930
931 /* Allocate groups */
932 hw->groups = devm_kmalloc_array(&pdev->dev, hw->soc->ngrps,
933 sizeof(*hw->groups), GFP_KERNEL);
934 if (!hw->groups)
935 return -ENOMEM;
936
937 /* We assume that one pin is one group, use pin name as group name. */
938 hw->grp_names = devm_kmalloc_array(&pdev->dev, hw->soc->ngrps,
939 sizeof(*hw->grp_names), GFP_KERNEL);
940 if (!hw->grp_names)
941 return -ENOMEM;
942
943 for (i = 0; i < hw->soc->npins; i++) {
944 const struct mtk_pin_desc *pin = hw->soc->pins + i;
945 struct mtk_pinctrl_group *group = hw->groups + i;
946
947 group->name = pin->name;
948 group->pin = pin->number;
949
950 hw->grp_names[i] = pin->name;
951 }
952
953 return 0;
954}
955
956int mtk_paris_pinctrl_probe(struct platform_device *pdev,
957 const struct mtk_pin_soc *soc)
958{
959 struct pinctrl_pin_desc *pins;
960 struct mtk_pinctrl *hw;
Zhiyong Tao80525092018-09-08 19:07:33 +0800961 int err, i;
962
963 hw = devm_kzalloc(&pdev->dev, sizeof(*hw), GFP_KERNEL);
964 if (!hw)
965 return -ENOMEM;
966
967 platform_set_drvdata(pdev, hw);
968 hw->soc = soc;
969 hw->dev = &pdev->dev;
970
971 if (!hw->soc->nbase_names) {
972 dev_err(&pdev->dev,
973 "SoC should be assigned at least one register base\n");
974 return -EINVAL;
975 }
976
977 hw->base = devm_kmalloc_array(&pdev->dev, hw->soc->nbase_names,
978 sizeof(*hw->base), GFP_KERNEL);
Wei Yongjun184744e2018-09-20 06:21:28 +0000979 if (!hw->base)
980 return -ENOMEM;
Zhiyong Tao80525092018-09-08 19:07:33 +0800981
982 for (i = 0; i < hw->soc->nbase_names; i++) {
Wang Xiaojun48548c72020-09-17 14:41:51 +0800983 hw->base[i] = devm_platform_ioremap_resource_byname(pdev,
984 hw->soc->base_names[i]);
Zhiyong Tao80525092018-09-08 19:07:33 +0800985 if (IS_ERR(hw->base[i]))
986 return PTR_ERR(hw->base[i]);
987 }
988
989 hw->nbase = hw->soc->nbase_names;
990
Zhiyong Taofb34a9a2021-09-24 16:06:31 +0800991 if (of_find_property(hw->dev->of_node,
992 "mediatek,rsel_resistance_in_si_unit", NULL))
993 hw->rsel_si_unit = true;
994 else
995 hw->rsel_si_unit = false;
996
Tzung-Bi Shih56ab29e2021-04-19 17:34:49 +0800997 spin_lock_init(&hw->lock);
Zhiyong Tao42a46432021-03-21 11:31:50 +0800998
Zhiyong Tao80525092018-09-08 19:07:33 +0800999 err = mtk_pctrl_build_state(pdev);
1000 if (err) {
1001 dev_err(&pdev->dev, "build state failed: %d\n", err);
1002 return -EINVAL;
1003 }
1004
1005 /* Copy from internal struct mtk_pin_desc to register to the core */
1006 pins = devm_kmalloc_array(&pdev->dev, hw->soc->npins, sizeof(*pins),
1007 GFP_KERNEL);
Wei Yongjun184744e2018-09-20 06:21:28 +00001008 if (!pins)
1009 return -ENOMEM;
Zhiyong Tao80525092018-09-08 19:07:33 +08001010
1011 for (i = 0; i < hw->soc->npins; i++) {
1012 pins[i].number = hw->soc->pins[i].number;
1013 pins[i].name = hw->soc->pins[i].name;
1014 }
1015
1016 /* Setup pins descriptions per SoC types */
1017 mtk_desc.pins = (const struct pinctrl_pin_desc *)pins;
1018 mtk_desc.npins = hw->soc->npins;
1019 mtk_desc.num_custom_params = ARRAY_SIZE(mtk_custom_bindings);
1020 mtk_desc.custom_params = mtk_custom_bindings;
1021#ifdef CONFIG_DEBUG_FS
1022 mtk_desc.custom_conf_items = mtk_conf_items;
1023#endif
1024
1025 err = devm_pinctrl_register_and_init(&pdev->dev, &mtk_desc, hw,
1026 &hw->pctrl);
1027 if (err)
1028 return err;
1029
1030 err = pinctrl_enable(hw->pctrl);
1031 if (err)
1032 return err;
1033
Sean Wang65618592018-09-08 19:07:38 +08001034 err = mtk_build_eint(hw, pdev);
1035 if (err)
1036 dev_warn(&pdev->dev,
1037 "Failed to add EINT, but pinctrl still can work\n");
1038
Zhiyong Tao80525092018-09-08 19:07:33 +08001039 /* Build gpiochip should be after pinctrl_enable is done */
1040 err = mtk_build_gpiochip(hw, pdev->dev.of_node);
1041 if (err) {
1042 dev_err(&pdev->dev, "Failed to add gpio_chip\n");
1043 return err;
1044 }
1045
1046 platform_set_drvdata(pdev, hw);
1047
1048 return 0;
1049}
Light Hsieh8174a852020-04-08 04:08:16 +08001050EXPORT_SYMBOL_GPL(mtk_paris_pinctrl_probe);
Nicolas Boichat5c090442019-05-08 15:33:30 +08001051
1052static int mtk_paris_pinctrl_suspend(struct device *device)
1053{
1054 struct mtk_pinctrl *pctl = dev_get_drvdata(device);
1055
1056 return mtk_eint_do_suspend(pctl->eint);
1057}
1058
1059static int mtk_paris_pinctrl_resume(struct device *device)
1060{
1061 struct mtk_pinctrl *pctl = dev_get_drvdata(device);
1062
1063 return mtk_eint_do_resume(pctl->eint);
1064}
1065
1066const struct dev_pm_ops mtk_paris_pinctrl_pm_ops = {
1067 .suspend_noirq = mtk_paris_pinctrl_suspend,
1068 .resume_noirq = mtk_paris_pinctrl_resume,
1069};
Light Hsieh8174a852020-04-08 04:08:16 +08001070
1071MODULE_LICENSE("GPL v2");
1072MODULE_DESCRIPTION("MediaTek Pinctrl Common Driver V2 Paris");