134812fe1SMasahiro Yamada // SPDX-License-Identifier: GPL-2.0+
234812fe1SMasahiro Yamada //
334812fe1SMasahiro Yamada // Copyright (C) 2015-2017 Socionext Inc.
434812fe1SMasahiro Yamada // Author: Masahiro Yamada <yamada.masahiro@socionext.com>
56e908892SMasahiro Yamada
69697509eSMasahiro Yamada #include <linux/list.h>
76e908892SMasahiro Yamada #include <linux/mfd/syscon.h>
83e030b0bSMasahiro Yamada #include <linux/of.h>
96e908892SMasahiro Yamada #include <linux/platform_device.h>
106e908892SMasahiro Yamada #include <linux/regmap.h>
11*24b4d76aSAndy Shevchenko #include <linux/seq_file.h>
12*24b4d76aSAndy Shevchenko
13*24b4d76aSAndy Shevchenko #include <linux/pinctrl/pinconf-generic.h>
14*24b4d76aSAndy Shevchenko #include <linux/pinctrl/pinconf.h>
15*24b4d76aSAndy Shevchenko #include <linux/pinctrl/pinctrl.h>
16*24b4d76aSAndy Shevchenko #include <linux/pinctrl/pinmux.h>
176e908892SMasahiro Yamada
186e908892SMasahiro Yamada #include "../core.h"
196e908892SMasahiro Yamada #include "../pinctrl-utils.h"
206e908892SMasahiro Yamada #include "pinctrl-uniphier.h"
216e908892SMasahiro Yamada
228ef364b3SMasahiro Yamada #define UNIPHIER_PINCTRL_PINMUX_BASE 0x1000
238ef364b3SMasahiro Yamada #define UNIPHIER_PINCTRL_LOAD_PINMUX 0x1700
248ef364b3SMasahiro Yamada #define UNIPHIER_PINCTRL_DRVCTRL_BASE 0x1800
258ef364b3SMasahiro Yamada #define UNIPHIER_PINCTRL_DRV2CTRL_BASE 0x1900
268ef364b3SMasahiro Yamada #define UNIPHIER_PINCTRL_DRV3CTRL_BASE 0x1980
278ef364b3SMasahiro Yamada #define UNIPHIER_PINCTRL_PUPDCTRL_BASE 0x1a00
28e3829d15SMasahiro Yamada #define UNIPHIER_PINCTRL_IECTRL_BASE 0x1d00
298ef364b3SMasahiro Yamada
309697509eSMasahiro Yamada struct uniphier_pinctrl_reg_region {
319697509eSMasahiro Yamada struct list_head node;
329697509eSMasahiro Yamada unsigned int base;
339697509eSMasahiro Yamada unsigned int nregs;
34aa0ed0d0SGustavo A. R. Silva u32 vals[];
359697509eSMasahiro Yamada };
369697509eSMasahiro Yamada
376e908892SMasahiro Yamada struct uniphier_pinctrl_priv {
38fc78a566SMasahiro Yamada struct pinctrl_desc pctldesc;
396e908892SMasahiro Yamada struct pinctrl_dev *pctldev;
406e908892SMasahiro Yamada struct regmap *regmap;
418b78de95SMasahiro Yamada const struct uniphier_pinctrl_socdata *socdata;
429697509eSMasahiro Yamada struct list_head reg_regions;
436e908892SMasahiro Yamada };
446e908892SMasahiro Yamada
uniphier_pctl_get_groups_count(struct pinctrl_dev * pctldev)456e908892SMasahiro Yamada static int uniphier_pctl_get_groups_count(struct pinctrl_dev *pctldev)
466e908892SMasahiro Yamada {
476e908892SMasahiro Yamada struct uniphier_pinctrl_priv *priv = pinctrl_dev_get_drvdata(pctldev);
486e908892SMasahiro Yamada
496e908892SMasahiro Yamada return priv->socdata->groups_count;
506e908892SMasahiro Yamada }
516e908892SMasahiro Yamada
uniphier_pctl_get_group_name(struct pinctrl_dev * pctldev,unsigned selector)526e908892SMasahiro Yamada static const char *uniphier_pctl_get_group_name(struct pinctrl_dev *pctldev,
536e908892SMasahiro Yamada unsigned selector)
546e908892SMasahiro Yamada {
556e908892SMasahiro Yamada struct uniphier_pinctrl_priv *priv = pinctrl_dev_get_drvdata(pctldev);
566e908892SMasahiro Yamada
576e908892SMasahiro Yamada return priv->socdata->groups[selector].name;
586e908892SMasahiro Yamada }
596e908892SMasahiro Yamada
uniphier_pctl_get_group_pins(struct pinctrl_dev * pctldev,unsigned selector,const unsigned ** pins,unsigned * num_pins)606e908892SMasahiro Yamada static int uniphier_pctl_get_group_pins(struct pinctrl_dev *pctldev,
616e908892SMasahiro Yamada unsigned selector,
626e908892SMasahiro Yamada const unsigned **pins,
636e908892SMasahiro Yamada unsigned *num_pins)
646e908892SMasahiro Yamada {
656e908892SMasahiro Yamada struct uniphier_pinctrl_priv *priv = pinctrl_dev_get_drvdata(pctldev);
666e908892SMasahiro Yamada
676e908892SMasahiro Yamada *pins = priv->socdata->groups[selector].pins;
686e908892SMasahiro Yamada *num_pins = priv->socdata->groups[selector].num_pins;
696e908892SMasahiro Yamada
706e908892SMasahiro Yamada return 0;
716e908892SMasahiro Yamada }
726e908892SMasahiro Yamada
736e908892SMasahiro Yamada #ifdef CONFIG_DEBUG_FS
uniphier_pctl_pin_dbg_show(struct pinctrl_dev * pctldev,struct seq_file * s,unsigned offset)746e908892SMasahiro Yamada static void uniphier_pctl_pin_dbg_show(struct pinctrl_dev *pctldev,
756e908892SMasahiro Yamada struct seq_file *s, unsigned offset)
766e908892SMasahiro Yamada {
7794bf176bSMasahiro Yamada const struct pin_desc *desc = pin_desc_get(pctldev, offset);
789eaa98a6SMasahiro Yamada const char *pull_dir, *drv_type;
796e908892SMasahiro Yamada
8094bf176bSMasahiro Yamada switch (uniphier_pin_get_pull_dir(desc->drv_data)) {
816e908892SMasahiro Yamada case UNIPHIER_PIN_PULL_UP:
826e908892SMasahiro Yamada pull_dir = "UP";
836e908892SMasahiro Yamada break;
846e908892SMasahiro Yamada case UNIPHIER_PIN_PULL_DOWN:
856e908892SMasahiro Yamada pull_dir = "DOWN";
866e908892SMasahiro Yamada break;
8710ef8277SMasahiro Yamada case UNIPHIER_PIN_PULL_UP_FIXED:
8810ef8277SMasahiro Yamada pull_dir = "UP(FIXED)";
8910ef8277SMasahiro Yamada break;
9010ef8277SMasahiro Yamada case UNIPHIER_PIN_PULL_DOWN_FIXED:
9110ef8277SMasahiro Yamada pull_dir = "DOWN(FIXED)";
9210ef8277SMasahiro Yamada break;
936e908892SMasahiro Yamada case UNIPHIER_PIN_PULL_NONE:
946e908892SMasahiro Yamada pull_dir = "NONE";
956e908892SMasahiro Yamada break;
966e908892SMasahiro Yamada default:
976e908892SMasahiro Yamada BUG();
986e908892SMasahiro Yamada }
996e908892SMasahiro Yamada
10094bf176bSMasahiro Yamada switch (uniphier_pin_get_drv_type(desc->drv_data)) {
1019eaa98a6SMasahiro Yamada case UNIPHIER_PIN_DRV_1BIT:
1029eaa98a6SMasahiro Yamada drv_type = "4/8(mA)";
1036e908892SMasahiro Yamada break;
1049eaa98a6SMasahiro Yamada case UNIPHIER_PIN_DRV_2BIT:
1059eaa98a6SMasahiro Yamada drv_type = "8/12/16/20(mA)";
1066e908892SMasahiro Yamada break;
10772e5706aSMasahiro Yamada case UNIPHIER_PIN_DRV_3BIT:
10872e5706aSMasahiro Yamada drv_type = "4/5/7/9/11/12/14/16(mA)";
10972e5706aSMasahiro Yamada break;
1109eaa98a6SMasahiro Yamada case UNIPHIER_PIN_DRV_FIXED4:
1119eaa98a6SMasahiro Yamada drv_type = "4(mA)";
1126e908892SMasahiro Yamada break;
1139eaa98a6SMasahiro Yamada case UNIPHIER_PIN_DRV_FIXED5:
1149eaa98a6SMasahiro Yamada drv_type = "5(mA)";
1156e908892SMasahiro Yamada break;
1169eaa98a6SMasahiro Yamada case UNIPHIER_PIN_DRV_FIXED8:
1179eaa98a6SMasahiro Yamada drv_type = "8(mA)";
1186e908892SMasahiro Yamada break;
1196e908892SMasahiro Yamada case UNIPHIER_PIN_DRV_NONE:
1209eaa98a6SMasahiro Yamada drv_type = "NONE";
1216e908892SMasahiro Yamada break;
1226e908892SMasahiro Yamada default:
1236e908892SMasahiro Yamada BUG();
1246e908892SMasahiro Yamada }
1256e908892SMasahiro Yamada
1269eaa98a6SMasahiro Yamada seq_printf(s, " PULL_DIR=%s DRV_TYPE=%s", pull_dir, drv_type);
1276e908892SMasahiro Yamada }
1286e908892SMasahiro Yamada #endif
1296e908892SMasahiro Yamada
1306e908892SMasahiro Yamada static const struct pinctrl_ops uniphier_pctlops = {
1316e908892SMasahiro Yamada .get_groups_count = uniphier_pctl_get_groups_count,
1326e908892SMasahiro Yamada .get_group_name = uniphier_pctl_get_group_name,
1336e908892SMasahiro Yamada .get_group_pins = uniphier_pctl_get_group_pins,
1346e908892SMasahiro Yamada #ifdef CONFIG_DEBUG_FS
1356e908892SMasahiro Yamada .pin_dbg_show = uniphier_pctl_pin_dbg_show,
1366e908892SMasahiro Yamada #endif
1376e908892SMasahiro Yamada .dt_node_to_map = pinconf_generic_dt_node_to_map_all,
138d32f7fd3SIrina Tirdea .dt_free_map = pinctrl_utils_free_map,
1396e908892SMasahiro Yamada };
1406e908892SMasahiro Yamada
141fb36a7b0SMasahiro Yamada static const unsigned int uniphier_conf_drv_strengths_1bit[] = {4, 8};
142fb36a7b0SMasahiro Yamada static const unsigned int uniphier_conf_drv_strengths_2bit[] = {8, 12, 16, 20};
143fb36a7b0SMasahiro Yamada static const unsigned int uniphier_conf_drv_strengths_3bit[] = {4, 5, 7, 9, 11,
144fb36a7b0SMasahiro Yamada 12, 14, 16};
145fb36a7b0SMasahiro Yamada static const unsigned int uniphier_conf_drv_strengths_fixed4[] = {4};
146fb36a7b0SMasahiro Yamada static const unsigned int uniphier_conf_drv_strengths_fixed5[] = {5};
147fb36a7b0SMasahiro Yamada static const unsigned int uniphier_conf_drv_strengths_fixed8[] = {8};
148fb36a7b0SMasahiro Yamada
uniphier_conf_get_drvctrl_data(struct pinctrl_dev * pctldev,unsigned int pin,unsigned int * reg,unsigned int * shift,unsigned int * mask,const unsigned int ** strengths)149fb36a7b0SMasahiro Yamada static int uniphier_conf_get_drvctrl_data(struct pinctrl_dev *pctldev,
150fb36a7b0SMasahiro Yamada unsigned int pin, unsigned int *reg,
151fb36a7b0SMasahiro Yamada unsigned int *shift,
152fb36a7b0SMasahiro Yamada unsigned int *mask,
153fb36a7b0SMasahiro Yamada const unsigned int **strengths)
154fb36a7b0SMasahiro Yamada {
155fb36a7b0SMasahiro Yamada const struct pin_desc *desc = pin_desc_get(pctldev, pin);
156fb36a7b0SMasahiro Yamada enum uniphier_pin_drv_type type =
157fb36a7b0SMasahiro Yamada uniphier_pin_get_drv_type(desc->drv_data);
158fb36a7b0SMasahiro Yamada unsigned int base = 0;
159fb36a7b0SMasahiro Yamada unsigned int stride = 0;
160fb36a7b0SMasahiro Yamada unsigned int width = 0;
161fb36a7b0SMasahiro Yamada unsigned int drvctrl;
162fb36a7b0SMasahiro Yamada
163fb36a7b0SMasahiro Yamada switch (type) {
164fb36a7b0SMasahiro Yamada case UNIPHIER_PIN_DRV_1BIT:
165fb36a7b0SMasahiro Yamada *strengths = uniphier_conf_drv_strengths_1bit;
166fb36a7b0SMasahiro Yamada base = UNIPHIER_PINCTRL_DRVCTRL_BASE;
167fb36a7b0SMasahiro Yamada stride = 1;
168fb36a7b0SMasahiro Yamada width = 1;
169fb36a7b0SMasahiro Yamada break;
170fb36a7b0SMasahiro Yamada case UNIPHIER_PIN_DRV_2BIT:
171fb36a7b0SMasahiro Yamada *strengths = uniphier_conf_drv_strengths_2bit;
172fb36a7b0SMasahiro Yamada base = UNIPHIER_PINCTRL_DRV2CTRL_BASE;
173fb36a7b0SMasahiro Yamada stride = 2;
174fb36a7b0SMasahiro Yamada width = 2;
175fb36a7b0SMasahiro Yamada break;
176fb36a7b0SMasahiro Yamada case UNIPHIER_PIN_DRV_3BIT:
177fb36a7b0SMasahiro Yamada *strengths = uniphier_conf_drv_strengths_3bit;
178fb36a7b0SMasahiro Yamada base = UNIPHIER_PINCTRL_DRV3CTRL_BASE;
179fb36a7b0SMasahiro Yamada stride = 4;
180fb36a7b0SMasahiro Yamada width = 3;
181fb36a7b0SMasahiro Yamada break;
182fb36a7b0SMasahiro Yamada case UNIPHIER_PIN_DRV_FIXED4:
183fb36a7b0SMasahiro Yamada *strengths = uniphier_conf_drv_strengths_fixed4;
184fb36a7b0SMasahiro Yamada break;
185fb36a7b0SMasahiro Yamada case UNIPHIER_PIN_DRV_FIXED5:
186fb36a7b0SMasahiro Yamada *strengths = uniphier_conf_drv_strengths_fixed5;
187fb36a7b0SMasahiro Yamada break;
188fb36a7b0SMasahiro Yamada case UNIPHIER_PIN_DRV_FIXED8:
189fb36a7b0SMasahiro Yamada *strengths = uniphier_conf_drv_strengths_fixed8;
190fb36a7b0SMasahiro Yamada break;
191fb36a7b0SMasahiro Yamada default:
192fb36a7b0SMasahiro Yamada /* drive strength control is not supported for this pin */
193fb36a7b0SMasahiro Yamada return -EINVAL;
194fb36a7b0SMasahiro Yamada }
195fb36a7b0SMasahiro Yamada
196fb36a7b0SMasahiro Yamada drvctrl = uniphier_pin_get_drvctrl(desc->drv_data);
197fb36a7b0SMasahiro Yamada drvctrl *= stride;
198fb36a7b0SMasahiro Yamada
199fb36a7b0SMasahiro Yamada *reg = base + drvctrl / 32 * 4;
200fb36a7b0SMasahiro Yamada *shift = drvctrl % 32;
201fb36a7b0SMasahiro Yamada *mask = (1U << width) - 1;
202fb36a7b0SMasahiro Yamada
203fb36a7b0SMasahiro Yamada return 0;
204fb36a7b0SMasahiro Yamada }
205fb36a7b0SMasahiro Yamada
uniphier_conf_pin_bias_get(struct pinctrl_dev * pctldev,unsigned int pin,enum pin_config_param param)2066e908892SMasahiro Yamada static int uniphier_conf_pin_bias_get(struct pinctrl_dev *pctldev,
2074e767983SMasahiro Yamada unsigned int pin,
2086e908892SMasahiro Yamada enum pin_config_param param)
2096e908892SMasahiro Yamada {
2106e908892SMasahiro Yamada struct uniphier_pinctrl_priv *priv = pinctrl_dev_get_drvdata(pctldev);
2114e767983SMasahiro Yamada const struct pin_desc *desc = pin_desc_get(pctldev, pin);
2126e908892SMasahiro Yamada enum uniphier_pin_pull_dir pull_dir =
21394bf176bSMasahiro Yamada uniphier_pin_get_pull_dir(desc->drv_data);
2146e908892SMasahiro Yamada unsigned int pupdctrl, reg, shift, val;
2156e908892SMasahiro Yamada unsigned int expected = 1;
2166e908892SMasahiro Yamada int ret;
2176e908892SMasahiro Yamada
2186e908892SMasahiro Yamada switch (param) {
2196e908892SMasahiro Yamada case PIN_CONFIG_BIAS_DISABLE:
2206e908892SMasahiro Yamada if (pull_dir == UNIPHIER_PIN_PULL_NONE)
2216e908892SMasahiro Yamada return 0;
2226e908892SMasahiro Yamada if (pull_dir == UNIPHIER_PIN_PULL_UP_FIXED ||
2236e908892SMasahiro Yamada pull_dir == UNIPHIER_PIN_PULL_DOWN_FIXED)
2246e908892SMasahiro Yamada return -EINVAL;
2256e908892SMasahiro Yamada expected = 0;
2266e908892SMasahiro Yamada break;
2276e908892SMasahiro Yamada case PIN_CONFIG_BIAS_PULL_UP:
2286e908892SMasahiro Yamada if (pull_dir == UNIPHIER_PIN_PULL_UP_FIXED)
2296e908892SMasahiro Yamada return 0;
2306e908892SMasahiro Yamada if (pull_dir != UNIPHIER_PIN_PULL_UP)
2316e908892SMasahiro Yamada return -EINVAL;
2326e908892SMasahiro Yamada break;
2336e908892SMasahiro Yamada case PIN_CONFIG_BIAS_PULL_DOWN:
2346e908892SMasahiro Yamada if (pull_dir == UNIPHIER_PIN_PULL_DOWN_FIXED)
2356e908892SMasahiro Yamada return 0;
2366e908892SMasahiro Yamada if (pull_dir != UNIPHIER_PIN_PULL_DOWN)
2376e908892SMasahiro Yamada return -EINVAL;
2386e908892SMasahiro Yamada break;
2396e908892SMasahiro Yamada default:
2406e908892SMasahiro Yamada BUG();
2416e908892SMasahiro Yamada }
2426e908892SMasahiro Yamada
24394bf176bSMasahiro Yamada pupdctrl = uniphier_pin_get_pupdctrl(desc->drv_data);
2446e908892SMasahiro Yamada
2456e908892SMasahiro Yamada reg = UNIPHIER_PINCTRL_PUPDCTRL_BASE + pupdctrl / 32 * 4;
2466e908892SMasahiro Yamada shift = pupdctrl % 32;
2476e908892SMasahiro Yamada
2488ef364b3SMasahiro Yamada ret = regmap_read(priv->regmap, reg, &val);
2496e908892SMasahiro Yamada if (ret)
2506e908892SMasahiro Yamada return ret;
2516e908892SMasahiro Yamada
2526e908892SMasahiro Yamada val = (val >> shift) & 1;
2536e908892SMasahiro Yamada
2546e908892SMasahiro Yamada return (val == expected) ? 0 : -EINVAL;
2556e908892SMasahiro Yamada }
2566e908892SMasahiro Yamada
uniphier_conf_pin_drive_get(struct pinctrl_dev * pctldev,unsigned int pin,u32 * strength)2576e908892SMasahiro Yamada static int uniphier_conf_pin_drive_get(struct pinctrl_dev *pctldev,
25837f92c18SMasahiro Yamada unsigned int pin, u32 *strength)
2596e908892SMasahiro Yamada {
2606e908892SMasahiro Yamada struct uniphier_pinctrl_priv *priv = pinctrl_dev_get_drvdata(pctldev);
261fb36a7b0SMasahiro Yamada unsigned int reg, shift, mask, val;
262fb36a7b0SMasahiro Yamada const unsigned int *strengths;
2636e908892SMasahiro Yamada int ret;
2646e908892SMasahiro Yamada
265fb36a7b0SMasahiro Yamada ret = uniphier_conf_get_drvctrl_data(pctldev, pin, ®, &shift,
266fb36a7b0SMasahiro Yamada &mask, &strengths);
2676e908892SMasahiro Yamada if (ret)
2686e908892SMasahiro Yamada return ret;
2696e908892SMasahiro Yamada
270fb36a7b0SMasahiro Yamada if (mask) {
271fb36a7b0SMasahiro Yamada ret = regmap_read(priv->regmap, reg, &val);
272fb36a7b0SMasahiro Yamada if (ret)
273fb36a7b0SMasahiro Yamada return ret;
274fb36a7b0SMasahiro Yamada } else {
275fb36a7b0SMasahiro Yamada val = 0;
276fb36a7b0SMasahiro Yamada }
277fb36a7b0SMasahiro Yamada
278fb36a7b0SMasahiro Yamada *strength = strengths[(val >> shift) & mask];
2796e908892SMasahiro Yamada
2806e908892SMasahiro Yamada return 0;
2816e908892SMasahiro Yamada }
2826e908892SMasahiro Yamada
uniphier_conf_pin_input_enable_get(struct pinctrl_dev * pctldev,unsigned int pin)2836e908892SMasahiro Yamada static int uniphier_conf_pin_input_enable_get(struct pinctrl_dev *pctldev,
2844e767983SMasahiro Yamada unsigned int pin)
2856e908892SMasahiro Yamada {
2866e908892SMasahiro Yamada struct uniphier_pinctrl_priv *priv = pinctrl_dev_get_drvdata(pctldev);
2874e767983SMasahiro Yamada const struct pin_desc *desc = pin_desc_get(pctldev, pin);
28894bf176bSMasahiro Yamada unsigned int iectrl = uniphier_pin_get_iectrl(desc->drv_data);
289e3829d15SMasahiro Yamada unsigned int reg, mask, val;
2906e908892SMasahiro Yamada int ret;
2916e908892SMasahiro Yamada
2926e908892SMasahiro Yamada if (iectrl == UNIPHIER_PIN_IECTRL_NONE)
2936e908892SMasahiro Yamada /* This pin is always input-enabled. */
2946e908892SMasahiro Yamada return 0;
2956e908892SMasahiro Yamada
2964e767983SMasahiro Yamada if (priv->socdata->caps & UNIPHIER_PINCTRL_CAPS_PERPIN_IECTRL)
2974e767983SMasahiro Yamada iectrl = pin;
2984e767983SMasahiro Yamada
299e3829d15SMasahiro Yamada reg = UNIPHIER_PINCTRL_IECTRL_BASE + iectrl / 32 * 4;
300e3829d15SMasahiro Yamada mask = BIT(iectrl % 32);
301e3829d15SMasahiro Yamada
302e3829d15SMasahiro Yamada ret = regmap_read(priv->regmap, reg, &val);
3036e908892SMasahiro Yamada if (ret)
3046e908892SMasahiro Yamada return ret;
3056e908892SMasahiro Yamada
306e3829d15SMasahiro Yamada return val & mask ? 0 : -EINVAL;
3076e908892SMasahiro Yamada }
3086e908892SMasahiro Yamada
uniphier_conf_pin_config_get(struct pinctrl_dev * pctldev,unsigned pin,unsigned long * configs)3096e908892SMasahiro Yamada static int uniphier_conf_pin_config_get(struct pinctrl_dev *pctldev,
3106e908892SMasahiro Yamada unsigned pin,
3116e908892SMasahiro Yamada unsigned long *configs)
3126e908892SMasahiro Yamada {
3136e908892SMasahiro Yamada enum pin_config_param param = pinconf_to_config_param(*configs);
3146e908892SMasahiro Yamada bool has_arg = false;
31537f92c18SMasahiro Yamada u32 arg;
3166e908892SMasahiro Yamada int ret;
3176e908892SMasahiro Yamada
3186e908892SMasahiro Yamada switch (param) {
3196e908892SMasahiro Yamada case PIN_CONFIG_BIAS_DISABLE:
3206e908892SMasahiro Yamada case PIN_CONFIG_BIAS_PULL_UP:
3216e908892SMasahiro Yamada case PIN_CONFIG_BIAS_PULL_DOWN:
3224e767983SMasahiro Yamada ret = uniphier_conf_pin_bias_get(pctldev, pin, param);
3236e908892SMasahiro Yamada break;
3246e908892SMasahiro Yamada case PIN_CONFIG_DRIVE_STRENGTH:
3254e767983SMasahiro Yamada ret = uniphier_conf_pin_drive_get(pctldev, pin, &arg);
3266e908892SMasahiro Yamada has_arg = true;
3276e908892SMasahiro Yamada break;
3286e908892SMasahiro Yamada case PIN_CONFIG_INPUT_ENABLE:
3294e767983SMasahiro Yamada ret = uniphier_conf_pin_input_enable_get(pctldev, pin);
3306e908892SMasahiro Yamada break;
3316e908892SMasahiro Yamada default:
3326e908892SMasahiro Yamada /* unsupported parameter */
3336e908892SMasahiro Yamada ret = -EINVAL;
3346e908892SMasahiro Yamada break;
3356e908892SMasahiro Yamada }
3366e908892SMasahiro Yamada
3376e908892SMasahiro Yamada if (ret == 0 && has_arg)
3386e908892SMasahiro Yamada *configs = pinconf_to_config_packed(param, arg);
3396e908892SMasahiro Yamada
3406e908892SMasahiro Yamada return ret;
3416e908892SMasahiro Yamada }
3426e908892SMasahiro Yamada
uniphier_conf_pin_bias_set(struct pinctrl_dev * pctldev,unsigned int pin,enum pin_config_param param,u32 arg)3436e908892SMasahiro Yamada static int uniphier_conf_pin_bias_set(struct pinctrl_dev *pctldev,
3444e767983SMasahiro Yamada unsigned int pin,
34558957d2eSMika Westerberg enum pin_config_param param, u32 arg)
3466e908892SMasahiro Yamada {
3476e908892SMasahiro Yamada struct uniphier_pinctrl_priv *priv = pinctrl_dev_get_drvdata(pctldev);
3484e767983SMasahiro Yamada const struct pin_desc *desc = pin_desc_get(pctldev, pin);
3496e908892SMasahiro Yamada enum uniphier_pin_pull_dir pull_dir =
35094bf176bSMasahiro Yamada uniphier_pin_get_pull_dir(desc->drv_data);
3516e908892SMasahiro Yamada unsigned int pupdctrl, reg, shift;
3526e908892SMasahiro Yamada unsigned int val = 1;
3536e908892SMasahiro Yamada
3546e908892SMasahiro Yamada switch (param) {
3556e908892SMasahiro Yamada case PIN_CONFIG_BIAS_DISABLE:
3566e908892SMasahiro Yamada if (pull_dir == UNIPHIER_PIN_PULL_NONE)
3576e908892SMasahiro Yamada return 0;
3586e908892SMasahiro Yamada if (pull_dir == UNIPHIER_PIN_PULL_UP_FIXED ||
3596e908892SMasahiro Yamada pull_dir == UNIPHIER_PIN_PULL_DOWN_FIXED) {
3606e908892SMasahiro Yamada dev_err(pctldev->dev,
36194bf176bSMasahiro Yamada "can not disable pull register for pin %s\n",
36294bf176bSMasahiro Yamada desc->name);
3636e908892SMasahiro Yamada return -EINVAL;
3646e908892SMasahiro Yamada }
3656e908892SMasahiro Yamada val = 0;
3666e908892SMasahiro Yamada break;
3676e908892SMasahiro Yamada case PIN_CONFIG_BIAS_PULL_UP:
3686e908892SMasahiro Yamada if (pull_dir == UNIPHIER_PIN_PULL_UP_FIXED && arg != 0)
3696e908892SMasahiro Yamada return 0;
3706e908892SMasahiro Yamada if (pull_dir != UNIPHIER_PIN_PULL_UP) {
3716e908892SMasahiro Yamada dev_err(pctldev->dev,
37294bf176bSMasahiro Yamada "pull-up is unsupported for pin %s\n",
37394bf176bSMasahiro Yamada desc->name);
3746e908892SMasahiro Yamada return -EINVAL;
3756e908892SMasahiro Yamada }
3766e908892SMasahiro Yamada if (arg == 0) {
3776e908892SMasahiro Yamada dev_err(pctldev->dev, "pull-up can not be total\n");
3786e908892SMasahiro Yamada return -EINVAL;
3796e908892SMasahiro Yamada }
3806e908892SMasahiro Yamada break;
3816e908892SMasahiro Yamada case PIN_CONFIG_BIAS_PULL_DOWN:
3826e908892SMasahiro Yamada if (pull_dir == UNIPHIER_PIN_PULL_DOWN_FIXED && arg != 0)
3836e908892SMasahiro Yamada return 0;
3846e908892SMasahiro Yamada if (pull_dir != UNIPHIER_PIN_PULL_DOWN) {
3856e908892SMasahiro Yamada dev_err(pctldev->dev,
38694bf176bSMasahiro Yamada "pull-down is unsupported for pin %s\n",
38794bf176bSMasahiro Yamada desc->name);
3886e908892SMasahiro Yamada return -EINVAL;
3896e908892SMasahiro Yamada }
3906e908892SMasahiro Yamada if (arg == 0) {
3916e908892SMasahiro Yamada dev_err(pctldev->dev, "pull-down can not be total\n");
3926e908892SMasahiro Yamada return -EINVAL;
3936e908892SMasahiro Yamada }
3946e908892SMasahiro Yamada break;
3956e908892SMasahiro Yamada case PIN_CONFIG_BIAS_PULL_PIN_DEFAULT:
3966e908892SMasahiro Yamada if (pull_dir == UNIPHIER_PIN_PULL_NONE) {
3976e908892SMasahiro Yamada dev_err(pctldev->dev,
39894bf176bSMasahiro Yamada "pull-up/down is unsupported for pin %s\n",
39994bf176bSMasahiro Yamada desc->name);
4006e908892SMasahiro Yamada return -EINVAL;
4016e908892SMasahiro Yamada }
4026e908892SMasahiro Yamada
4036e908892SMasahiro Yamada if (arg == 0)
4046e908892SMasahiro Yamada return 0; /* configuration ingored */
4056e908892SMasahiro Yamada break;
4066e908892SMasahiro Yamada default:
4076e908892SMasahiro Yamada BUG();
4086e908892SMasahiro Yamada }
4096e908892SMasahiro Yamada
41094bf176bSMasahiro Yamada pupdctrl = uniphier_pin_get_pupdctrl(desc->drv_data);
4116e908892SMasahiro Yamada
4126e908892SMasahiro Yamada reg = UNIPHIER_PINCTRL_PUPDCTRL_BASE + pupdctrl / 32 * 4;
4136e908892SMasahiro Yamada shift = pupdctrl % 32;
4146e908892SMasahiro Yamada
4158ef364b3SMasahiro Yamada return regmap_update_bits(priv->regmap, reg, 1 << shift, val << shift);
4166e908892SMasahiro Yamada }
4176e908892SMasahiro Yamada
uniphier_conf_pin_drive_set(struct pinctrl_dev * pctldev,unsigned int pin,u32 strength)4186e908892SMasahiro Yamada static int uniphier_conf_pin_drive_set(struct pinctrl_dev *pctldev,
41937f92c18SMasahiro Yamada unsigned int pin, u32 strength)
4206e908892SMasahiro Yamada {
4216e908892SMasahiro Yamada struct uniphier_pinctrl_priv *priv = pinctrl_dev_get_drvdata(pctldev);
4224e767983SMasahiro Yamada const struct pin_desc *desc = pin_desc_get(pctldev, pin);
423fb36a7b0SMasahiro Yamada unsigned int reg, shift, mask, val;
424fb36a7b0SMasahiro Yamada const unsigned int *strengths;
425fb36a7b0SMasahiro Yamada int ret;
4266e908892SMasahiro Yamada
427fb36a7b0SMasahiro Yamada ret = uniphier_conf_get_drvctrl_data(pctldev, pin, ®, &shift,
428fb36a7b0SMasahiro Yamada &mask, &strengths);
429fb36a7b0SMasahiro Yamada if (ret) {
430fb36a7b0SMasahiro Yamada dev_err(pctldev->dev, "cannot set drive strength for pin %s\n",
43194bf176bSMasahiro Yamada desc->name);
432fb36a7b0SMasahiro Yamada return ret;
4336e908892SMasahiro Yamada }
4346e908892SMasahiro Yamada
435fb36a7b0SMasahiro Yamada for (val = 0; val <= mask; val++) {
436fb36a7b0SMasahiro Yamada if (strengths[val] > strength)
4376e908892SMasahiro Yamada break;
4386e908892SMasahiro Yamada }
4396e908892SMasahiro Yamada
4406e908892SMasahiro Yamada if (val == 0) {
4416e908892SMasahiro Yamada dev_err(pctldev->dev,
44294bf176bSMasahiro Yamada "unsupported drive strength %u mA for pin %s\n",
44394bf176bSMasahiro Yamada strength, desc->name);
4446e908892SMasahiro Yamada return -EINVAL;
4456e908892SMasahiro Yamada }
4466e908892SMasahiro Yamada
447fb36a7b0SMasahiro Yamada if (!mask)
448fb36a7b0SMasahiro Yamada return 0;
449fb36a7b0SMasahiro Yamada
4506e908892SMasahiro Yamada val--;
4516e908892SMasahiro Yamada
4528ef364b3SMasahiro Yamada return regmap_update_bits(priv->regmap, reg,
4536e908892SMasahiro Yamada mask << shift, val << shift);
4546e908892SMasahiro Yamada }
4556e908892SMasahiro Yamada
uniphier_conf_pin_input_enable(struct pinctrl_dev * pctldev,unsigned int pin,u32 enable)4566e908892SMasahiro Yamada static int uniphier_conf_pin_input_enable(struct pinctrl_dev *pctldev,
45737f92c18SMasahiro Yamada unsigned int pin, u32 enable)
4586e908892SMasahiro Yamada {
4596e908892SMasahiro Yamada struct uniphier_pinctrl_priv *priv = pinctrl_dev_get_drvdata(pctldev);
4604e767983SMasahiro Yamada const struct pin_desc *desc = pin_desc_get(pctldev, pin);
46194bf176bSMasahiro Yamada unsigned int iectrl = uniphier_pin_get_iectrl(desc->drv_data);
462aa543888SMasahiro Yamada unsigned int reg, mask;
4636e908892SMasahiro Yamada
4646e908892SMasahiro Yamada /*
465aa543888SMasahiro Yamada * Multiple pins share one input enable, per-pin disabling is
466aa543888SMasahiro Yamada * impossible.
4676e908892SMasahiro Yamada */
468aa543888SMasahiro Yamada if (!(priv->socdata->caps & UNIPHIER_PINCTRL_CAPS_PERPIN_IECTRL) &&
469aa543888SMasahiro Yamada !enable)
4706e908892SMasahiro Yamada return -EINVAL;
4716e908892SMasahiro Yamada
472aa543888SMasahiro Yamada /* UNIPHIER_PIN_IECTRL_NONE means the pin is always input-enabled */
4736e908892SMasahiro Yamada if (iectrl == UNIPHIER_PIN_IECTRL_NONE)
474aa543888SMasahiro Yamada return enable ? 0 : -EINVAL;
4756e908892SMasahiro Yamada
4764e767983SMasahiro Yamada if (priv->socdata->caps & UNIPHIER_PINCTRL_CAPS_PERPIN_IECTRL)
4774e767983SMasahiro Yamada iectrl = pin;
4784e767983SMasahiro Yamada
479e3829d15SMasahiro Yamada reg = UNIPHIER_PINCTRL_IECTRL_BASE + iectrl / 32 * 4;
480aa543888SMasahiro Yamada mask = BIT(iectrl % 32);
481aa543888SMasahiro Yamada
482aa543888SMasahiro Yamada return regmap_update_bits(priv->regmap, reg, mask, enable ? mask : 0);
4836e908892SMasahiro Yamada }
4846e908892SMasahiro Yamada
uniphier_conf_pin_config_set(struct pinctrl_dev * pctldev,unsigned pin,unsigned long * configs,unsigned num_configs)4856e908892SMasahiro Yamada static int uniphier_conf_pin_config_set(struct pinctrl_dev *pctldev,
4866e908892SMasahiro Yamada unsigned pin,
4876e908892SMasahiro Yamada unsigned long *configs,
4886e908892SMasahiro Yamada unsigned num_configs)
4896e908892SMasahiro Yamada {
4906e908892SMasahiro Yamada int i, ret;
4916e908892SMasahiro Yamada
4926e908892SMasahiro Yamada for (i = 0; i < num_configs; i++) {
4936e908892SMasahiro Yamada enum pin_config_param param =
4946e908892SMasahiro Yamada pinconf_to_config_param(configs[i]);
49558957d2eSMika Westerberg u32 arg = pinconf_to_config_argument(configs[i]);
4966e908892SMasahiro Yamada
4976e908892SMasahiro Yamada switch (param) {
4986e908892SMasahiro Yamada case PIN_CONFIG_BIAS_DISABLE:
4996e908892SMasahiro Yamada case PIN_CONFIG_BIAS_PULL_UP:
5006e908892SMasahiro Yamada case PIN_CONFIG_BIAS_PULL_DOWN:
5016e908892SMasahiro Yamada case PIN_CONFIG_BIAS_PULL_PIN_DEFAULT:
5024e767983SMasahiro Yamada ret = uniphier_conf_pin_bias_set(pctldev, pin,
5036e908892SMasahiro Yamada param, arg);
5046e908892SMasahiro Yamada break;
5056e908892SMasahiro Yamada case PIN_CONFIG_DRIVE_STRENGTH:
5064e767983SMasahiro Yamada ret = uniphier_conf_pin_drive_set(pctldev, pin, arg);
5076e908892SMasahiro Yamada break;
5086e908892SMasahiro Yamada case PIN_CONFIG_INPUT_ENABLE:
5094e767983SMasahiro Yamada ret = uniphier_conf_pin_input_enable(pctldev, pin, arg);
5106e908892SMasahiro Yamada break;
5116e908892SMasahiro Yamada default:
5126e908892SMasahiro Yamada dev_err(pctldev->dev,
5136e908892SMasahiro Yamada "unsupported configuration parameter %u\n",
5146e908892SMasahiro Yamada param);
5156e908892SMasahiro Yamada return -EINVAL;
5166e908892SMasahiro Yamada }
5176e908892SMasahiro Yamada
5186e908892SMasahiro Yamada if (ret)
5196e908892SMasahiro Yamada return ret;
5206e908892SMasahiro Yamada }
5216e908892SMasahiro Yamada
5226e908892SMasahiro Yamada return 0;
5236e908892SMasahiro Yamada }
5246e908892SMasahiro Yamada
uniphier_conf_pin_config_group_set(struct pinctrl_dev * pctldev,unsigned selector,unsigned long * configs,unsigned num_configs)5256e908892SMasahiro Yamada static int uniphier_conf_pin_config_group_set(struct pinctrl_dev *pctldev,
5266e908892SMasahiro Yamada unsigned selector,
5276e908892SMasahiro Yamada unsigned long *configs,
5286e908892SMasahiro Yamada unsigned num_configs)
5296e908892SMasahiro Yamada {
5306e908892SMasahiro Yamada struct uniphier_pinctrl_priv *priv = pinctrl_dev_get_drvdata(pctldev);
5316e908892SMasahiro Yamada const unsigned *pins = priv->socdata->groups[selector].pins;
5326e908892SMasahiro Yamada unsigned num_pins = priv->socdata->groups[selector].num_pins;
5336e908892SMasahiro Yamada int i, ret;
5346e908892SMasahiro Yamada
5356e908892SMasahiro Yamada for (i = 0; i < num_pins; i++) {
5366e908892SMasahiro Yamada ret = uniphier_conf_pin_config_set(pctldev, pins[i],
5376e908892SMasahiro Yamada configs, num_configs);
5386e908892SMasahiro Yamada if (ret)
5396e908892SMasahiro Yamada return ret;
5406e908892SMasahiro Yamada }
5416e908892SMasahiro Yamada
5426e908892SMasahiro Yamada return 0;
5436e908892SMasahiro Yamada }
5446e908892SMasahiro Yamada
5456e908892SMasahiro Yamada static const struct pinconf_ops uniphier_confops = {
5466e908892SMasahiro Yamada .is_generic = true,
5476e908892SMasahiro Yamada .pin_config_get = uniphier_conf_pin_config_get,
5486e908892SMasahiro Yamada .pin_config_set = uniphier_conf_pin_config_set,
5496e908892SMasahiro Yamada .pin_config_group_set = uniphier_conf_pin_config_group_set,
5506e908892SMasahiro Yamada };
5516e908892SMasahiro Yamada
uniphier_pmx_get_functions_count(struct pinctrl_dev * pctldev)5526e908892SMasahiro Yamada static int uniphier_pmx_get_functions_count(struct pinctrl_dev *pctldev)
5536e908892SMasahiro Yamada {
5546e908892SMasahiro Yamada struct uniphier_pinctrl_priv *priv = pinctrl_dev_get_drvdata(pctldev);
5556e908892SMasahiro Yamada
5566e908892SMasahiro Yamada return priv->socdata->functions_count;
5576e908892SMasahiro Yamada }
5586e908892SMasahiro Yamada
uniphier_pmx_get_function_name(struct pinctrl_dev * pctldev,unsigned selector)5596e908892SMasahiro Yamada static const char *uniphier_pmx_get_function_name(struct pinctrl_dev *pctldev,
5606e908892SMasahiro Yamada unsigned selector)
5616e908892SMasahiro Yamada {
5626e908892SMasahiro Yamada struct uniphier_pinctrl_priv *priv = pinctrl_dev_get_drvdata(pctldev);
5636e908892SMasahiro Yamada
5646e908892SMasahiro Yamada return priv->socdata->functions[selector].name;
5656e908892SMasahiro Yamada }
5666e908892SMasahiro Yamada
uniphier_pmx_get_function_groups(struct pinctrl_dev * pctldev,unsigned selector,const char * const ** groups,unsigned * num_groups)5676e908892SMasahiro Yamada static int uniphier_pmx_get_function_groups(struct pinctrl_dev *pctldev,
5686e908892SMasahiro Yamada unsigned selector,
5696e908892SMasahiro Yamada const char * const **groups,
5706e908892SMasahiro Yamada unsigned *num_groups)
5716e908892SMasahiro Yamada {
5726e908892SMasahiro Yamada struct uniphier_pinctrl_priv *priv = pinctrl_dev_get_drvdata(pctldev);
5736e908892SMasahiro Yamada
5746e908892SMasahiro Yamada *groups = priv->socdata->functions[selector].groups;
5756e908892SMasahiro Yamada *num_groups = priv->socdata->functions[selector].num_groups;
5766e908892SMasahiro Yamada
5776e908892SMasahiro Yamada return 0;
5786e908892SMasahiro Yamada }
5796e908892SMasahiro Yamada
uniphier_pmx_set_one_mux(struct pinctrl_dev * pctldev,unsigned pin,int muxval)5806e908892SMasahiro Yamada static int uniphier_pmx_set_one_mux(struct pinctrl_dev *pctldev, unsigned pin,
58139ec9aceSMasahiro Yamada int muxval)
5826e908892SMasahiro Yamada {
5836e908892SMasahiro Yamada struct uniphier_pinctrl_priv *priv = pinctrl_dev_get_drvdata(pctldev);
584c2ebf475SMasahiro Yamada unsigned int mux_bits, reg_stride, reg, reg_end, shift, mask;
585c2ebf475SMasahiro Yamada bool load_pinctrl;
5866e908892SMasahiro Yamada int ret;
5876e908892SMasahiro Yamada
588bac7f4c1SMasahiro Yamada /* some pins need input-enabling */
5894e767983SMasahiro Yamada ret = uniphier_conf_pin_input_enable(pctldev, pin, 1);
590bac7f4c1SMasahiro Yamada if (ret)
591bac7f4c1SMasahiro Yamada return ret;
592bac7f4c1SMasahiro Yamada
59339ec9aceSMasahiro Yamada if (muxval < 0)
59439ec9aceSMasahiro Yamada return 0; /* dedicated pin; nothing to do for pin-mux */
59539ec9aceSMasahiro Yamada
596c2ebf475SMasahiro Yamada if (priv->socdata->caps & UNIPHIER_PINCTRL_CAPS_DBGMUX_SEPARATE) {
597c2ebf475SMasahiro Yamada /*
598c2ebf475SMasahiro Yamada * Mode reg_offset bit_position
599c2ebf475SMasahiro Yamada * Normal 4 * n shift+3:shift
600c2ebf475SMasahiro Yamada * Debug 4 * n shift+7:shift+4
601c2ebf475SMasahiro Yamada */
602c2ebf475SMasahiro Yamada mux_bits = 4;
603c2ebf475SMasahiro Yamada reg_stride = 8;
604c2ebf475SMasahiro Yamada load_pinctrl = true;
605c2ebf475SMasahiro Yamada } else {
606c2ebf475SMasahiro Yamada /*
607c2ebf475SMasahiro Yamada * Mode reg_offset bit_position
608c2ebf475SMasahiro Yamada * Normal 8 * n shift+3:shift
609c2ebf475SMasahiro Yamada * Debug 8 * n + 4 shift+3:shift
610c2ebf475SMasahiro Yamada */
611c2ebf475SMasahiro Yamada mux_bits = 8;
612c2ebf475SMasahiro Yamada reg_stride = 4;
613c2ebf475SMasahiro Yamada load_pinctrl = false;
614c2ebf475SMasahiro Yamada }
615c2ebf475SMasahiro Yamada
6166e908892SMasahiro Yamada reg = UNIPHIER_PINCTRL_PINMUX_BASE + pin * mux_bits / 32 * reg_stride;
6176e908892SMasahiro Yamada reg_end = reg + reg_stride;
6186e908892SMasahiro Yamada shift = pin * mux_bits % 32;
6196e908892SMasahiro Yamada mask = (1U << mux_bits) - 1;
6206e908892SMasahiro Yamada
6216e908892SMasahiro Yamada /*
6226e908892SMasahiro Yamada * If reg_stride is greater than 4, the MSB of each pinsel shall be
6236e908892SMasahiro Yamada * stored in the offset+4.
6246e908892SMasahiro Yamada */
6256e908892SMasahiro Yamada for (; reg < reg_end; reg += 4) {
6268ef364b3SMasahiro Yamada ret = regmap_update_bits(priv->regmap, reg,
6276e908892SMasahiro Yamada mask << shift, muxval << shift);
6286e908892SMasahiro Yamada if (ret)
6296e908892SMasahiro Yamada return ret;
6306e908892SMasahiro Yamada muxval >>= mux_bits;
6316e908892SMasahiro Yamada }
6326e908892SMasahiro Yamada
633c2ebf475SMasahiro Yamada if (load_pinctrl) {
6346e908892SMasahiro Yamada ret = regmap_write(priv->regmap,
6358ef364b3SMasahiro Yamada UNIPHIER_PINCTRL_LOAD_PINMUX, 1);
6366e908892SMasahiro Yamada if (ret)
6376e908892SMasahiro Yamada return ret;
6386e908892SMasahiro Yamada }
6396e908892SMasahiro Yamada
640bac7f4c1SMasahiro Yamada return 0;
6416e908892SMasahiro Yamada }
6426e908892SMasahiro Yamada
uniphier_pmx_set_mux(struct pinctrl_dev * pctldev,unsigned func_selector,unsigned group_selector)6436e908892SMasahiro Yamada static int uniphier_pmx_set_mux(struct pinctrl_dev *pctldev,
6446e908892SMasahiro Yamada unsigned func_selector,
6456e908892SMasahiro Yamada unsigned group_selector)
6466e908892SMasahiro Yamada {
6476e908892SMasahiro Yamada struct uniphier_pinctrl_priv *priv = pinctrl_dev_get_drvdata(pctldev);
6486e908892SMasahiro Yamada const struct uniphier_pinctrl_group *grp =
6496e908892SMasahiro Yamada &priv->socdata->groups[group_selector];
6506e908892SMasahiro Yamada int i;
6516e908892SMasahiro Yamada int ret;
6526e908892SMasahiro Yamada
6536e908892SMasahiro Yamada for (i = 0; i < grp->num_pins; i++) {
6546e908892SMasahiro Yamada ret = uniphier_pmx_set_one_mux(pctldev, grp->pins[i],
6556e908892SMasahiro Yamada grp->muxvals[i]);
6566e908892SMasahiro Yamada if (ret)
6576e908892SMasahiro Yamada return ret;
6586e908892SMasahiro Yamada }
6596e908892SMasahiro Yamada
6606e908892SMasahiro Yamada return 0;
6616e908892SMasahiro Yamada }
6626e908892SMasahiro Yamada
uniphier_pmx_gpio_request_enable(struct pinctrl_dev * pctldev,struct pinctrl_gpio_range * range,unsigned offset)6636e908892SMasahiro Yamada static int uniphier_pmx_gpio_request_enable(struct pinctrl_dev *pctldev,
6646e908892SMasahiro Yamada struct pinctrl_gpio_range *range,
6656e908892SMasahiro Yamada unsigned offset)
6666e908892SMasahiro Yamada {
6676e908892SMasahiro Yamada struct uniphier_pinctrl_priv *priv = pinctrl_dev_get_drvdata(pctldev);
6687f6ee0a5SMasahiro Yamada unsigned int gpio_offset;
6697f6ee0a5SMasahiro Yamada int muxval, i;
6706e908892SMasahiro Yamada
6717f6ee0a5SMasahiro Yamada if (range->pins) {
6727f6ee0a5SMasahiro Yamada for (i = 0; i < range->npins; i++)
6737f6ee0a5SMasahiro Yamada if (range->pins[i] == offset)
6747f6ee0a5SMasahiro Yamada break;
6756e908892SMasahiro Yamada
6767f6ee0a5SMasahiro Yamada if (WARN_ON(i == range->npins))
6776e908892SMasahiro Yamada return -EINVAL;
6786e908892SMasahiro Yamada
6797f6ee0a5SMasahiro Yamada gpio_offset = i;
6807f6ee0a5SMasahiro Yamada } else {
6817f6ee0a5SMasahiro Yamada gpio_offset = offset - range->pin_base;
6827f6ee0a5SMasahiro Yamada }
6837f6ee0a5SMasahiro Yamada
6847f6ee0a5SMasahiro Yamada gpio_offset += range->id;
6857f6ee0a5SMasahiro Yamada
6867f6ee0a5SMasahiro Yamada muxval = priv->socdata->get_gpio_muxval(offset, gpio_offset);
6877f6ee0a5SMasahiro Yamada
6887f6ee0a5SMasahiro Yamada return uniphier_pmx_set_one_mux(pctldev, offset, muxval);
6896e908892SMasahiro Yamada }
6906e908892SMasahiro Yamada
6916e908892SMasahiro Yamada static const struct pinmux_ops uniphier_pmxops = {
6926e908892SMasahiro Yamada .get_functions_count = uniphier_pmx_get_functions_count,
6936e908892SMasahiro Yamada .get_function_name = uniphier_pmx_get_function_name,
6946e908892SMasahiro Yamada .get_function_groups = uniphier_pmx_get_function_groups,
6956e908892SMasahiro Yamada .set_mux = uniphier_pmx_set_mux,
6966e908892SMasahiro Yamada .gpio_request_enable = uniphier_pmx_gpio_request_enable,
6976e908892SMasahiro Yamada .strict = true,
6986e908892SMasahiro Yamada };
6996e908892SMasahiro Yamada
7009697509eSMasahiro Yamada #ifdef CONFIG_PM_SLEEP
uniphier_pinctrl_suspend(struct device * dev)7019697509eSMasahiro Yamada static int uniphier_pinctrl_suspend(struct device *dev)
7029697509eSMasahiro Yamada {
7039697509eSMasahiro Yamada struct uniphier_pinctrl_priv *priv = dev_get_drvdata(dev);
7049697509eSMasahiro Yamada struct uniphier_pinctrl_reg_region *r;
7059697509eSMasahiro Yamada int ret;
7069697509eSMasahiro Yamada
7079697509eSMasahiro Yamada list_for_each_entry(r, &priv->reg_regions, node) {
7089697509eSMasahiro Yamada ret = regmap_bulk_read(priv->regmap, r->base, r->vals,
7099697509eSMasahiro Yamada r->nregs);
7109697509eSMasahiro Yamada if (ret)
7119697509eSMasahiro Yamada return ret;
7129697509eSMasahiro Yamada }
7139697509eSMasahiro Yamada
7149697509eSMasahiro Yamada return 0;
7159697509eSMasahiro Yamada }
7169697509eSMasahiro Yamada
uniphier_pinctrl_resume(struct device * dev)7179697509eSMasahiro Yamada static int uniphier_pinctrl_resume(struct device *dev)
7189697509eSMasahiro Yamada {
7199697509eSMasahiro Yamada struct uniphier_pinctrl_priv *priv = dev_get_drvdata(dev);
7209697509eSMasahiro Yamada struct uniphier_pinctrl_reg_region *r;
7219697509eSMasahiro Yamada int ret;
7229697509eSMasahiro Yamada
7239697509eSMasahiro Yamada list_for_each_entry(r, &priv->reg_regions, node) {
7249697509eSMasahiro Yamada ret = regmap_bulk_write(priv->regmap, r->base, r->vals,
7259697509eSMasahiro Yamada r->nregs);
7269697509eSMasahiro Yamada if (ret)
7279697509eSMasahiro Yamada return ret;
7289697509eSMasahiro Yamada }
7299697509eSMasahiro Yamada
7309697509eSMasahiro Yamada if (priv->socdata->caps & UNIPHIER_PINCTRL_CAPS_DBGMUX_SEPARATE) {
7319697509eSMasahiro Yamada ret = regmap_write(priv->regmap,
7329697509eSMasahiro Yamada UNIPHIER_PINCTRL_LOAD_PINMUX, 1);
7339697509eSMasahiro Yamada if (ret)
7349697509eSMasahiro Yamada return ret;
7359697509eSMasahiro Yamada }
7369697509eSMasahiro Yamada
7379697509eSMasahiro Yamada return 0;
7389697509eSMasahiro Yamada }
7399697509eSMasahiro Yamada
uniphier_pinctrl_add_reg_region(struct device * dev,struct uniphier_pinctrl_priv * priv,unsigned int base,unsigned int count,unsigned int width)7409697509eSMasahiro Yamada static int uniphier_pinctrl_add_reg_region(struct device *dev,
7419697509eSMasahiro Yamada struct uniphier_pinctrl_priv *priv,
7429697509eSMasahiro Yamada unsigned int base,
7439697509eSMasahiro Yamada unsigned int count,
7449697509eSMasahiro Yamada unsigned int width)
7459697509eSMasahiro Yamada {
7469697509eSMasahiro Yamada struct uniphier_pinctrl_reg_region *region;
7479697509eSMasahiro Yamada unsigned int nregs;
7489697509eSMasahiro Yamada
7499697509eSMasahiro Yamada if (!count)
7509697509eSMasahiro Yamada return 0;
7519697509eSMasahiro Yamada
7529697509eSMasahiro Yamada nregs = DIV_ROUND_UP(count * width, 32);
7539697509eSMasahiro Yamada
7540ed2dd03SKees Cook region = devm_kzalloc(dev, struct_size(region, vals, nregs),
7559697509eSMasahiro Yamada GFP_KERNEL);
7569697509eSMasahiro Yamada if (!region)
7579697509eSMasahiro Yamada return -ENOMEM;
7589697509eSMasahiro Yamada
7599697509eSMasahiro Yamada region->base = base;
7609697509eSMasahiro Yamada region->nregs = nregs;
7619697509eSMasahiro Yamada
7629697509eSMasahiro Yamada list_add_tail(®ion->node, &priv->reg_regions);
7639697509eSMasahiro Yamada
7649697509eSMasahiro Yamada return 0;
7659697509eSMasahiro Yamada }
7669697509eSMasahiro Yamada #endif
7679697509eSMasahiro Yamada
uniphier_pinctrl_pm_init(struct device * dev,struct uniphier_pinctrl_priv * priv)7689697509eSMasahiro Yamada static int uniphier_pinctrl_pm_init(struct device *dev,
7699697509eSMasahiro Yamada struct uniphier_pinctrl_priv *priv)
7709697509eSMasahiro Yamada {
7719697509eSMasahiro Yamada #ifdef CONFIG_PM_SLEEP
7729697509eSMasahiro Yamada const struct uniphier_pinctrl_socdata *socdata = priv->socdata;
7739697509eSMasahiro Yamada unsigned int num_drvctrl = 0;
7749697509eSMasahiro Yamada unsigned int num_drv2ctrl = 0;
7759697509eSMasahiro Yamada unsigned int num_drv3ctrl = 0;
7769697509eSMasahiro Yamada unsigned int num_pupdctrl = 0;
7779697509eSMasahiro Yamada unsigned int num_iectrl = 0;
7789697509eSMasahiro Yamada unsigned int iectrl, drvctrl, pupdctrl;
7799697509eSMasahiro Yamada enum uniphier_pin_drv_type drv_type;
7809697509eSMasahiro Yamada enum uniphier_pin_pull_dir pull_dir;
7819697509eSMasahiro Yamada int i, ret;
7829697509eSMasahiro Yamada
7839697509eSMasahiro Yamada for (i = 0; i < socdata->npins; i++) {
7849697509eSMasahiro Yamada void *drv_data = socdata->pins[i].drv_data;
7859697509eSMasahiro Yamada
7869697509eSMasahiro Yamada drvctrl = uniphier_pin_get_drvctrl(drv_data);
7879697509eSMasahiro Yamada drv_type = uniphier_pin_get_drv_type(drv_data);
7889697509eSMasahiro Yamada pupdctrl = uniphier_pin_get_pupdctrl(drv_data);
7899697509eSMasahiro Yamada pull_dir = uniphier_pin_get_pull_dir(drv_data);
7909697509eSMasahiro Yamada iectrl = uniphier_pin_get_iectrl(drv_data);
7919697509eSMasahiro Yamada
7929697509eSMasahiro Yamada switch (drv_type) {
7939697509eSMasahiro Yamada case UNIPHIER_PIN_DRV_1BIT:
7949697509eSMasahiro Yamada num_drvctrl = max(num_drvctrl, drvctrl + 1);
7959697509eSMasahiro Yamada break;
7969697509eSMasahiro Yamada case UNIPHIER_PIN_DRV_2BIT:
7979697509eSMasahiro Yamada num_drv2ctrl = max(num_drv2ctrl, drvctrl + 1);
7989697509eSMasahiro Yamada break;
7999697509eSMasahiro Yamada case UNIPHIER_PIN_DRV_3BIT:
8009697509eSMasahiro Yamada num_drv3ctrl = max(num_drv3ctrl, drvctrl + 1);
8019697509eSMasahiro Yamada break;
8029697509eSMasahiro Yamada default:
8039697509eSMasahiro Yamada break;
8049697509eSMasahiro Yamada }
8059697509eSMasahiro Yamada
8069697509eSMasahiro Yamada if (pull_dir == UNIPHIER_PIN_PULL_UP ||
8079697509eSMasahiro Yamada pull_dir == UNIPHIER_PIN_PULL_DOWN)
8089697509eSMasahiro Yamada num_pupdctrl = max(num_pupdctrl, pupdctrl + 1);
8099697509eSMasahiro Yamada
8109697509eSMasahiro Yamada if (iectrl != UNIPHIER_PIN_IECTRL_NONE) {
8119697509eSMasahiro Yamada if (socdata->caps & UNIPHIER_PINCTRL_CAPS_PERPIN_IECTRL)
8129697509eSMasahiro Yamada iectrl = i;
8139697509eSMasahiro Yamada num_iectrl = max(num_iectrl, iectrl + 1);
8149697509eSMasahiro Yamada }
8159697509eSMasahiro Yamada }
8169697509eSMasahiro Yamada
8179697509eSMasahiro Yamada INIT_LIST_HEAD(&priv->reg_regions);
8189697509eSMasahiro Yamada
8199697509eSMasahiro Yamada ret = uniphier_pinctrl_add_reg_region(dev, priv,
8209697509eSMasahiro Yamada UNIPHIER_PINCTRL_PINMUX_BASE,
8219697509eSMasahiro Yamada socdata->npins, 8);
8229697509eSMasahiro Yamada if (ret)
8239697509eSMasahiro Yamada return ret;
8249697509eSMasahiro Yamada
8259697509eSMasahiro Yamada ret = uniphier_pinctrl_add_reg_region(dev, priv,
8269697509eSMasahiro Yamada UNIPHIER_PINCTRL_DRVCTRL_BASE,
8279697509eSMasahiro Yamada num_drvctrl, 1);
8289697509eSMasahiro Yamada if (ret)
8299697509eSMasahiro Yamada return ret;
8309697509eSMasahiro Yamada
8319697509eSMasahiro Yamada ret = uniphier_pinctrl_add_reg_region(dev, priv,
8329697509eSMasahiro Yamada UNIPHIER_PINCTRL_DRV2CTRL_BASE,
8339697509eSMasahiro Yamada num_drv2ctrl, 2);
8349697509eSMasahiro Yamada if (ret)
8359697509eSMasahiro Yamada return ret;
8369697509eSMasahiro Yamada
8379697509eSMasahiro Yamada ret = uniphier_pinctrl_add_reg_region(dev, priv,
8389697509eSMasahiro Yamada UNIPHIER_PINCTRL_DRV3CTRL_BASE,
8399697509eSMasahiro Yamada num_drv3ctrl, 3);
8409697509eSMasahiro Yamada if (ret)
8419697509eSMasahiro Yamada return ret;
8429697509eSMasahiro Yamada
8439697509eSMasahiro Yamada ret = uniphier_pinctrl_add_reg_region(dev, priv,
8449697509eSMasahiro Yamada UNIPHIER_PINCTRL_PUPDCTRL_BASE,
8459697509eSMasahiro Yamada num_pupdctrl, 1);
8469697509eSMasahiro Yamada if (ret)
8479697509eSMasahiro Yamada return ret;
8489697509eSMasahiro Yamada
8499697509eSMasahiro Yamada ret = uniphier_pinctrl_add_reg_region(dev, priv,
8509697509eSMasahiro Yamada UNIPHIER_PINCTRL_IECTRL_BASE,
8519697509eSMasahiro Yamada num_iectrl, 1);
8529697509eSMasahiro Yamada if (ret)
8539697509eSMasahiro Yamada return ret;
8549697509eSMasahiro Yamada #endif
8559697509eSMasahiro Yamada return 0;
8569697509eSMasahiro Yamada }
8579697509eSMasahiro Yamada
8589697509eSMasahiro Yamada const struct dev_pm_ops uniphier_pinctrl_pm_ops = {
8599697509eSMasahiro Yamada SET_LATE_SYSTEM_SLEEP_PM_OPS(uniphier_pinctrl_suspend,
8609697509eSMasahiro Yamada uniphier_pinctrl_resume)
8619697509eSMasahiro Yamada };
8629697509eSMasahiro Yamada
uniphier_pinctrl_probe(struct platform_device * pdev,const struct uniphier_pinctrl_socdata * socdata)8636e908892SMasahiro Yamada int uniphier_pinctrl_probe(struct platform_device *pdev,
8648b78de95SMasahiro Yamada const struct uniphier_pinctrl_socdata *socdata)
8656e908892SMasahiro Yamada {
8666e908892SMasahiro Yamada struct device *dev = &pdev->dev;
8676e908892SMasahiro Yamada struct uniphier_pinctrl_priv *priv;
8683e030b0bSMasahiro Yamada struct device_node *parent;
8699697509eSMasahiro Yamada int ret;
8706e908892SMasahiro Yamada
8716e908892SMasahiro Yamada if (!socdata ||
872fc78a566SMasahiro Yamada !socdata->pins || !socdata->npins ||
873c2ebf475SMasahiro Yamada !socdata->groups || !socdata->groups_count ||
874c2ebf475SMasahiro Yamada !socdata->functions || !socdata->functions_count) {
8756e908892SMasahiro Yamada dev_err(dev, "pinctrl socdata lacks necessary members\n");
8766e908892SMasahiro Yamada return -EINVAL;
8776e908892SMasahiro Yamada }
8786e908892SMasahiro Yamada
8796e908892SMasahiro Yamada priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
8806e908892SMasahiro Yamada if (!priv)
8816e908892SMasahiro Yamada return -ENOMEM;
8826e908892SMasahiro Yamada
8833e030b0bSMasahiro Yamada parent = of_get_parent(dev->of_node);
8843e030b0bSMasahiro Yamada priv->regmap = syscon_node_to_regmap(parent);
8853e030b0bSMasahiro Yamada of_node_put(parent);
8863e030b0bSMasahiro Yamada
8876e908892SMasahiro Yamada if (IS_ERR(priv->regmap)) {
8886e908892SMasahiro Yamada dev_err(dev, "failed to get regmap\n");
8896e908892SMasahiro Yamada return PTR_ERR(priv->regmap);
8906e908892SMasahiro Yamada }
8916e908892SMasahiro Yamada
8926e908892SMasahiro Yamada priv->socdata = socdata;
893fc78a566SMasahiro Yamada priv->pctldesc.name = dev->driver->name;
894fc78a566SMasahiro Yamada priv->pctldesc.pins = socdata->pins;
895fc78a566SMasahiro Yamada priv->pctldesc.npins = socdata->npins;
896fc78a566SMasahiro Yamada priv->pctldesc.pctlops = &uniphier_pctlops;
897fc78a566SMasahiro Yamada priv->pctldesc.pmxops = &uniphier_pmxops;
898fc78a566SMasahiro Yamada priv->pctldesc.confops = &uniphier_confops;
899fc78a566SMasahiro Yamada priv->pctldesc.owner = dev->driver->owner;
9006e908892SMasahiro Yamada
9019697509eSMasahiro Yamada ret = uniphier_pinctrl_pm_init(dev, priv);
9029697509eSMasahiro Yamada if (ret)
9039697509eSMasahiro Yamada return ret;
9049697509eSMasahiro Yamada
905fc78a566SMasahiro Yamada priv->pctldev = devm_pinctrl_register(dev, &priv->pctldesc, priv);
9066e908892SMasahiro Yamada if (IS_ERR(priv->pctldev)) {
9076e908892SMasahiro Yamada dev_err(dev, "failed to register UniPhier pinctrl driver\n");
9086e908892SMasahiro Yamada return PTR_ERR(priv->pctldev);
9096e908892SMasahiro Yamada }
9106e908892SMasahiro Yamada
9116e908892SMasahiro Yamada platform_set_drvdata(pdev, priv);
9126e908892SMasahiro Yamada
9136e908892SMasahiro Yamada return 0;
9146e908892SMasahiro Yamada }
915