xref: /openbmc/linux/drivers/pinctrl/uniphier/pinctrl-uniphier-core.c (revision 7ae9fb1b7ecbb5d85d07857943f677fd1a559b18)
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, &reg, &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, &reg, &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(&region->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