xref: /OK3568_Linux_fs/kernel/drivers/pinctrl/freescale/pinctrl-mxs.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0+
2*4882a593Smuzhiyun //
3*4882a593Smuzhiyun // Copyright 2012 Freescale Semiconductor, Inc.
4*4882a593Smuzhiyun 
5*4882a593Smuzhiyun #include <linux/err.h>
6*4882a593Smuzhiyun #include <linux/init.h>
7*4882a593Smuzhiyun #include <linux/io.h>
8*4882a593Smuzhiyun #include <linux/of.h>
9*4882a593Smuzhiyun #include <linux/of_address.h>
10*4882a593Smuzhiyun #include <linux/pinctrl/machine.h>
11*4882a593Smuzhiyun #include <linux/pinctrl/pinconf.h>
12*4882a593Smuzhiyun #include <linux/pinctrl/pinctrl.h>
13*4882a593Smuzhiyun #include <linux/pinctrl/pinmux.h>
14*4882a593Smuzhiyun #include <linux/platform_device.h>
15*4882a593Smuzhiyun #include <linux/slab.h>
16*4882a593Smuzhiyun #include "../core.h"
17*4882a593Smuzhiyun #include "pinctrl-mxs.h"
18*4882a593Smuzhiyun 
19*4882a593Smuzhiyun #define SUFFIX_LEN	4
20*4882a593Smuzhiyun 
21*4882a593Smuzhiyun struct mxs_pinctrl_data {
22*4882a593Smuzhiyun 	struct device *dev;
23*4882a593Smuzhiyun 	struct pinctrl_dev *pctl;
24*4882a593Smuzhiyun 	void __iomem *base;
25*4882a593Smuzhiyun 	struct mxs_pinctrl_soc_data *soc;
26*4882a593Smuzhiyun };
27*4882a593Smuzhiyun 
mxs_get_groups_count(struct pinctrl_dev * pctldev)28*4882a593Smuzhiyun static int mxs_get_groups_count(struct pinctrl_dev *pctldev)
29*4882a593Smuzhiyun {
30*4882a593Smuzhiyun 	struct mxs_pinctrl_data *d = pinctrl_dev_get_drvdata(pctldev);
31*4882a593Smuzhiyun 
32*4882a593Smuzhiyun 	return d->soc->ngroups;
33*4882a593Smuzhiyun }
34*4882a593Smuzhiyun 
mxs_get_group_name(struct pinctrl_dev * pctldev,unsigned group)35*4882a593Smuzhiyun static const char *mxs_get_group_name(struct pinctrl_dev *pctldev,
36*4882a593Smuzhiyun 				      unsigned group)
37*4882a593Smuzhiyun {
38*4882a593Smuzhiyun 	struct mxs_pinctrl_data *d = pinctrl_dev_get_drvdata(pctldev);
39*4882a593Smuzhiyun 
40*4882a593Smuzhiyun 	return d->soc->groups[group].name;
41*4882a593Smuzhiyun }
42*4882a593Smuzhiyun 
mxs_get_group_pins(struct pinctrl_dev * pctldev,unsigned group,const unsigned ** pins,unsigned * num_pins)43*4882a593Smuzhiyun static int mxs_get_group_pins(struct pinctrl_dev *pctldev, unsigned group,
44*4882a593Smuzhiyun 			      const unsigned **pins, unsigned *num_pins)
45*4882a593Smuzhiyun {
46*4882a593Smuzhiyun 	struct mxs_pinctrl_data *d = pinctrl_dev_get_drvdata(pctldev);
47*4882a593Smuzhiyun 
48*4882a593Smuzhiyun 	*pins = d->soc->groups[group].pins;
49*4882a593Smuzhiyun 	*num_pins = d->soc->groups[group].npins;
50*4882a593Smuzhiyun 
51*4882a593Smuzhiyun 	return 0;
52*4882a593Smuzhiyun }
53*4882a593Smuzhiyun 
mxs_pin_dbg_show(struct pinctrl_dev * pctldev,struct seq_file * s,unsigned offset)54*4882a593Smuzhiyun static void mxs_pin_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s,
55*4882a593Smuzhiyun 			     unsigned offset)
56*4882a593Smuzhiyun {
57*4882a593Smuzhiyun 	seq_printf(s, " %s", dev_name(pctldev->dev));
58*4882a593Smuzhiyun }
59*4882a593Smuzhiyun 
mxs_dt_node_to_map(struct pinctrl_dev * pctldev,struct device_node * np,struct pinctrl_map ** map,unsigned * num_maps)60*4882a593Smuzhiyun static int mxs_dt_node_to_map(struct pinctrl_dev *pctldev,
61*4882a593Smuzhiyun 			      struct device_node *np,
62*4882a593Smuzhiyun 			      struct pinctrl_map **map, unsigned *num_maps)
63*4882a593Smuzhiyun {
64*4882a593Smuzhiyun 	struct pinctrl_map *new_map;
65*4882a593Smuzhiyun 	char *group = NULL;
66*4882a593Smuzhiyun 	unsigned new_num = 1;
67*4882a593Smuzhiyun 	unsigned long config = 0;
68*4882a593Smuzhiyun 	unsigned long *pconfig;
69*4882a593Smuzhiyun 	int length = strlen(np->name) + SUFFIX_LEN;
70*4882a593Smuzhiyun 	bool purecfg = false;
71*4882a593Smuzhiyun 	u32 val, reg;
72*4882a593Smuzhiyun 	int ret, i = 0;
73*4882a593Smuzhiyun 
74*4882a593Smuzhiyun 	/* Check for pin config node which has no 'reg' property */
75*4882a593Smuzhiyun 	if (of_property_read_u32(np, "reg", &reg))
76*4882a593Smuzhiyun 		purecfg = true;
77*4882a593Smuzhiyun 
78*4882a593Smuzhiyun 	ret = of_property_read_u32(np, "fsl,drive-strength", &val);
79*4882a593Smuzhiyun 	if (!ret)
80*4882a593Smuzhiyun 		config = val | MA_PRESENT;
81*4882a593Smuzhiyun 	ret = of_property_read_u32(np, "fsl,voltage", &val);
82*4882a593Smuzhiyun 	if (!ret)
83*4882a593Smuzhiyun 		config |= val << VOL_SHIFT | VOL_PRESENT;
84*4882a593Smuzhiyun 	ret = of_property_read_u32(np, "fsl,pull-up", &val);
85*4882a593Smuzhiyun 	if (!ret)
86*4882a593Smuzhiyun 		config |= val << PULL_SHIFT | PULL_PRESENT;
87*4882a593Smuzhiyun 
88*4882a593Smuzhiyun 	/* Check for group node which has both mux and config settings */
89*4882a593Smuzhiyun 	if (!purecfg && config)
90*4882a593Smuzhiyun 		new_num = 2;
91*4882a593Smuzhiyun 
92*4882a593Smuzhiyun 	new_map = kcalloc(new_num, sizeof(*new_map), GFP_KERNEL);
93*4882a593Smuzhiyun 	if (!new_map)
94*4882a593Smuzhiyun 		return -ENOMEM;
95*4882a593Smuzhiyun 
96*4882a593Smuzhiyun 	if (!purecfg) {
97*4882a593Smuzhiyun 		new_map[i].type = PIN_MAP_TYPE_MUX_GROUP;
98*4882a593Smuzhiyun 		new_map[i].data.mux.function = np->name;
99*4882a593Smuzhiyun 
100*4882a593Smuzhiyun 		/* Compose group name */
101*4882a593Smuzhiyun 		group = kzalloc(length, GFP_KERNEL);
102*4882a593Smuzhiyun 		if (!group) {
103*4882a593Smuzhiyun 			ret = -ENOMEM;
104*4882a593Smuzhiyun 			goto free;
105*4882a593Smuzhiyun 		}
106*4882a593Smuzhiyun 		snprintf(group, length, "%s.%d", np->name, reg);
107*4882a593Smuzhiyun 		new_map[i].data.mux.group = group;
108*4882a593Smuzhiyun 		i++;
109*4882a593Smuzhiyun 	}
110*4882a593Smuzhiyun 
111*4882a593Smuzhiyun 	if (config) {
112*4882a593Smuzhiyun 		pconfig = kmemdup(&config, sizeof(config), GFP_KERNEL);
113*4882a593Smuzhiyun 		if (!pconfig) {
114*4882a593Smuzhiyun 			ret = -ENOMEM;
115*4882a593Smuzhiyun 			goto free_group;
116*4882a593Smuzhiyun 		}
117*4882a593Smuzhiyun 
118*4882a593Smuzhiyun 		new_map[i].type = PIN_MAP_TYPE_CONFIGS_GROUP;
119*4882a593Smuzhiyun 		new_map[i].data.configs.group_or_pin = purecfg ? np->name :
120*4882a593Smuzhiyun 								 group;
121*4882a593Smuzhiyun 		new_map[i].data.configs.configs = pconfig;
122*4882a593Smuzhiyun 		new_map[i].data.configs.num_configs = 1;
123*4882a593Smuzhiyun 	}
124*4882a593Smuzhiyun 
125*4882a593Smuzhiyun 	*map = new_map;
126*4882a593Smuzhiyun 	*num_maps = new_num;
127*4882a593Smuzhiyun 
128*4882a593Smuzhiyun 	return 0;
129*4882a593Smuzhiyun 
130*4882a593Smuzhiyun free_group:
131*4882a593Smuzhiyun 	if (!purecfg)
132*4882a593Smuzhiyun 		kfree(group);
133*4882a593Smuzhiyun free:
134*4882a593Smuzhiyun 	kfree(new_map);
135*4882a593Smuzhiyun 	return ret;
136*4882a593Smuzhiyun }
137*4882a593Smuzhiyun 
mxs_dt_free_map(struct pinctrl_dev * pctldev,struct pinctrl_map * map,unsigned num_maps)138*4882a593Smuzhiyun static void mxs_dt_free_map(struct pinctrl_dev *pctldev,
139*4882a593Smuzhiyun 			    struct pinctrl_map *map, unsigned num_maps)
140*4882a593Smuzhiyun {
141*4882a593Smuzhiyun 	u32 i;
142*4882a593Smuzhiyun 
143*4882a593Smuzhiyun 	for (i = 0; i < num_maps; i++) {
144*4882a593Smuzhiyun 		if (map[i].type == PIN_MAP_TYPE_MUX_GROUP)
145*4882a593Smuzhiyun 			kfree(map[i].data.mux.group);
146*4882a593Smuzhiyun 		if (map[i].type == PIN_MAP_TYPE_CONFIGS_GROUP)
147*4882a593Smuzhiyun 			kfree(map[i].data.configs.configs);
148*4882a593Smuzhiyun 	}
149*4882a593Smuzhiyun 
150*4882a593Smuzhiyun 	kfree(map);
151*4882a593Smuzhiyun }
152*4882a593Smuzhiyun 
153*4882a593Smuzhiyun static const struct pinctrl_ops mxs_pinctrl_ops = {
154*4882a593Smuzhiyun 	.get_groups_count = mxs_get_groups_count,
155*4882a593Smuzhiyun 	.get_group_name = mxs_get_group_name,
156*4882a593Smuzhiyun 	.get_group_pins = mxs_get_group_pins,
157*4882a593Smuzhiyun 	.pin_dbg_show = mxs_pin_dbg_show,
158*4882a593Smuzhiyun 	.dt_node_to_map = mxs_dt_node_to_map,
159*4882a593Smuzhiyun 	.dt_free_map = mxs_dt_free_map,
160*4882a593Smuzhiyun };
161*4882a593Smuzhiyun 
mxs_pinctrl_get_funcs_count(struct pinctrl_dev * pctldev)162*4882a593Smuzhiyun static int mxs_pinctrl_get_funcs_count(struct pinctrl_dev *pctldev)
163*4882a593Smuzhiyun {
164*4882a593Smuzhiyun 	struct mxs_pinctrl_data *d = pinctrl_dev_get_drvdata(pctldev);
165*4882a593Smuzhiyun 
166*4882a593Smuzhiyun 	return d->soc->nfunctions;
167*4882a593Smuzhiyun }
168*4882a593Smuzhiyun 
mxs_pinctrl_get_func_name(struct pinctrl_dev * pctldev,unsigned function)169*4882a593Smuzhiyun static const char *mxs_pinctrl_get_func_name(struct pinctrl_dev *pctldev,
170*4882a593Smuzhiyun 					     unsigned function)
171*4882a593Smuzhiyun {
172*4882a593Smuzhiyun 	struct mxs_pinctrl_data *d = pinctrl_dev_get_drvdata(pctldev);
173*4882a593Smuzhiyun 
174*4882a593Smuzhiyun 	return d->soc->functions[function].name;
175*4882a593Smuzhiyun }
176*4882a593Smuzhiyun 
mxs_pinctrl_get_func_groups(struct pinctrl_dev * pctldev,unsigned group,const char * const ** groups,unsigned * const num_groups)177*4882a593Smuzhiyun static int mxs_pinctrl_get_func_groups(struct pinctrl_dev *pctldev,
178*4882a593Smuzhiyun 				       unsigned group,
179*4882a593Smuzhiyun 				       const char * const **groups,
180*4882a593Smuzhiyun 				       unsigned * const num_groups)
181*4882a593Smuzhiyun {
182*4882a593Smuzhiyun 	struct mxs_pinctrl_data *d = pinctrl_dev_get_drvdata(pctldev);
183*4882a593Smuzhiyun 
184*4882a593Smuzhiyun 	*groups = d->soc->functions[group].groups;
185*4882a593Smuzhiyun 	*num_groups = d->soc->functions[group].ngroups;
186*4882a593Smuzhiyun 
187*4882a593Smuzhiyun 	return 0;
188*4882a593Smuzhiyun }
189*4882a593Smuzhiyun 
mxs_pinctrl_rmwl(u32 value,u32 mask,u8 shift,void __iomem * reg)190*4882a593Smuzhiyun static void mxs_pinctrl_rmwl(u32 value, u32 mask, u8 shift, void __iomem *reg)
191*4882a593Smuzhiyun {
192*4882a593Smuzhiyun 	u32 tmp;
193*4882a593Smuzhiyun 
194*4882a593Smuzhiyun 	tmp = readl(reg);
195*4882a593Smuzhiyun 	tmp &= ~(mask << shift);
196*4882a593Smuzhiyun 	tmp |= value << shift;
197*4882a593Smuzhiyun 	writel(tmp, reg);
198*4882a593Smuzhiyun }
199*4882a593Smuzhiyun 
mxs_pinctrl_set_mux(struct pinctrl_dev * pctldev,unsigned selector,unsigned group)200*4882a593Smuzhiyun static int mxs_pinctrl_set_mux(struct pinctrl_dev *pctldev, unsigned selector,
201*4882a593Smuzhiyun 			       unsigned group)
202*4882a593Smuzhiyun {
203*4882a593Smuzhiyun 	struct mxs_pinctrl_data *d = pinctrl_dev_get_drvdata(pctldev);
204*4882a593Smuzhiyun 	struct mxs_group *g = &d->soc->groups[group];
205*4882a593Smuzhiyun 	void __iomem *reg;
206*4882a593Smuzhiyun 	u8 bank, shift;
207*4882a593Smuzhiyun 	u16 pin;
208*4882a593Smuzhiyun 	u32 i;
209*4882a593Smuzhiyun 
210*4882a593Smuzhiyun 	for (i = 0; i < g->npins; i++) {
211*4882a593Smuzhiyun 		bank = PINID_TO_BANK(g->pins[i]);
212*4882a593Smuzhiyun 		pin = PINID_TO_PIN(g->pins[i]);
213*4882a593Smuzhiyun 		reg = d->base + d->soc->regs->muxsel;
214*4882a593Smuzhiyun 		reg += bank * 0x20 + pin / 16 * 0x10;
215*4882a593Smuzhiyun 		shift = pin % 16 * 2;
216*4882a593Smuzhiyun 
217*4882a593Smuzhiyun 		mxs_pinctrl_rmwl(g->muxsel[i], 0x3, shift, reg);
218*4882a593Smuzhiyun 	}
219*4882a593Smuzhiyun 
220*4882a593Smuzhiyun 	return 0;
221*4882a593Smuzhiyun }
222*4882a593Smuzhiyun 
223*4882a593Smuzhiyun static const struct pinmux_ops mxs_pinmux_ops = {
224*4882a593Smuzhiyun 	.get_functions_count = mxs_pinctrl_get_funcs_count,
225*4882a593Smuzhiyun 	.get_function_name = mxs_pinctrl_get_func_name,
226*4882a593Smuzhiyun 	.get_function_groups = mxs_pinctrl_get_func_groups,
227*4882a593Smuzhiyun 	.set_mux = mxs_pinctrl_set_mux,
228*4882a593Smuzhiyun };
229*4882a593Smuzhiyun 
mxs_pinconf_get(struct pinctrl_dev * pctldev,unsigned pin,unsigned long * config)230*4882a593Smuzhiyun static int mxs_pinconf_get(struct pinctrl_dev *pctldev,
231*4882a593Smuzhiyun 			   unsigned pin, unsigned long *config)
232*4882a593Smuzhiyun {
233*4882a593Smuzhiyun 	return -ENOTSUPP;
234*4882a593Smuzhiyun }
235*4882a593Smuzhiyun 
mxs_pinconf_set(struct pinctrl_dev * pctldev,unsigned pin,unsigned long * configs,unsigned num_configs)236*4882a593Smuzhiyun static int mxs_pinconf_set(struct pinctrl_dev *pctldev,
237*4882a593Smuzhiyun 			   unsigned pin, unsigned long *configs,
238*4882a593Smuzhiyun 			   unsigned num_configs)
239*4882a593Smuzhiyun {
240*4882a593Smuzhiyun 	return -ENOTSUPP;
241*4882a593Smuzhiyun }
242*4882a593Smuzhiyun 
mxs_pinconf_group_get(struct pinctrl_dev * pctldev,unsigned group,unsigned long * config)243*4882a593Smuzhiyun static int mxs_pinconf_group_get(struct pinctrl_dev *pctldev,
244*4882a593Smuzhiyun 				 unsigned group, unsigned long *config)
245*4882a593Smuzhiyun {
246*4882a593Smuzhiyun 	struct mxs_pinctrl_data *d = pinctrl_dev_get_drvdata(pctldev);
247*4882a593Smuzhiyun 
248*4882a593Smuzhiyun 	*config = d->soc->groups[group].config;
249*4882a593Smuzhiyun 
250*4882a593Smuzhiyun 	return 0;
251*4882a593Smuzhiyun }
252*4882a593Smuzhiyun 
mxs_pinconf_group_set(struct pinctrl_dev * pctldev,unsigned group,unsigned long * configs,unsigned num_configs)253*4882a593Smuzhiyun static int mxs_pinconf_group_set(struct pinctrl_dev *pctldev,
254*4882a593Smuzhiyun 				 unsigned group, unsigned long *configs,
255*4882a593Smuzhiyun 				 unsigned num_configs)
256*4882a593Smuzhiyun {
257*4882a593Smuzhiyun 	struct mxs_pinctrl_data *d = pinctrl_dev_get_drvdata(pctldev);
258*4882a593Smuzhiyun 	struct mxs_group *g = &d->soc->groups[group];
259*4882a593Smuzhiyun 	void __iomem *reg;
260*4882a593Smuzhiyun 	u8 ma, vol, pull, bank, shift;
261*4882a593Smuzhiyun 	u16 pin;
262*4882a593Smuzhiyun 	u32 i;
263*4882a593Smuzhiyun 	int n;
264*4882a593Smuzhiyun 	unsigned long config;
265*4882a593Smuzhiyun 
266*4882a593Smuzhiyun 	for (n = 0; n < num_configs; n++) {
267*4882a593Smuzhiyun 		config = configs[n];
268*4882a593Smuzhiyun 
269*4882a593Smuzhiyun 		ma = CONFIG_TO_MA(config);
270*4882a593Smuzhiyun 		vol = CONFIG_TO_VOL(config);
271*4882a593Smuzhiyun 		pull = CONFIG_TO_PULL(config);
272*4882a593Smuzhiyun 
273*4882a593Smuzhiyun 		for (i = 0; i < g->npins; i++) {
274*4882a593Smuzhiyun 			bank = PINID_TO_BANK(g->pins[i]);
275*4882a593Smuzhiyun 			pin = PINID_TO_PIN(g->pins[i]);
276*4882a593Smuzhiyun 
277*4882a593Smuzhiyun 			/* drive */
278*4882a593Smuzhiyun 			reg = d->base + d->soc->regs->drive;
279*4882a593Smuzhiyun 			reg += bank * 0x40 + pin / 8 * 0x10;
280*4882a593Smuzhiyun 
281*4882a593Smuzhiyun 			/* mA */
282*4882a593Smuzhiyun 			if (config & MA_PRESENT) {
283*4882a593Smuzhiyun 				shift = pin % 8 * 4;
284*4882a593Smuzhiyun 				mxs_pinctrl_rmwl(ma, 0x3, shift, reg);
285*4882a593Smuzhiyun 			}
286*4882a593Smuzhiyun 
287*4882a593Smuzhiyun 			/* vol */
288*4882a593Smuzhiyun 			if (config & VOL_PRESENT) {
289*4882a593Smuzhiyun 				shift = pin % 8 * 4 + 2;
290*4882a593Smuzhiyun 				if (vol)
291*4882a593Smuzhiyun 					writel(1 << shift, reg + SET);
292*4882a593Smuzhiyun 				else
293*4882a593Smuzhiyun 					writel(1 << shift, reg + CLR);
294*4882a593Smuzhiyun 			}
295*4882a593Smuzhiyun 
296*4882a593Smuzhiyun 			/* pull */
297*4882a593Smuzhiyun 			if (config & PULL_PRESENT) {
298*4882a593Smuzhiyun 				reg = d->base + d->soc->regs->pull;
299*4882a593Smuzhiyun 				reg += bank * 0x10;
300*4882a593Smuzhiyun 				shift = pin;
301*4882a593Smuzhiyun 				if (pull)
302*4882a593Smuzhiyun 					writel(1 << shift, reg + SET);
303*4882a593Smuzhiyun 				else
304*4882a593Smuzhiyun 					writel(1 << shift, reg + CLR);
305*4882a593Smuzhiyun 			}
306*4882a593Smuzhiyun 		}
307*4882a593Smuzhiyun 
308*4882a593Smuzhiyun 		/* cache the config value for mxs_pinconf_group_get() */
309*4882a593Smuzhiyun 		g->config = config;
310*4882a593Smuzhiyun 
311*4882a593Smuzhiyun 	} /* for each config */
312*4882a593Smuzhiyun 
313*4882a593Smuzhiyun 	return 0;
314*4882a593Smuzhiyun }
315*4882a593Smuzhiyun 
mxs_pinconf_dbg_show(struct pinctrl_dev * pctldev,struct seq_file * s,unsigned pin)316*4882a593Smuzhiyun static void mxs_pinconf_dbg_show(struct pinctrl_dev *pctldev,
317*4882a593Smuzhiyun 				 struct seq_file *s, unsigned pin)
318*4882a593Smuzhiyun {
319*4882a593Smuzhiyun 	/* Not support */
320*4882a593Smuzhiyun }
321*4882a593Smuzhiyun 
mxs_pinconf_group_dbg_show(struct pinctrl_dev * pctldev,struct seq_file * s,unsigned group)322*4882a593Smuzhiyun static void mxs_pinconf_group_dbg_show(struct pinctrl_dev *pctldev,
323*4882a593Smuzhiyun 				       struct seq_file *s, unsigned group)
324*4882a593Smuzhiyun {
325*4882a593Smuzhiyun 	unsigned long config;
326*4882a593Smuzhiyun 
327*4882a593Smuzhiyun 	if (!mxs_pinconf_group_get(pctldev, group, &config))
328*4882a593Smuzhiyun 		seq_printf(s, "0x%lx", config);
329*4882a593Smuzhiyun }
330*4882a593Smuzhiyun 
331*4882a593Smuzhiyun static const struct pinconf_ops mxs_pinconf_ops = {
332*4882a593Smuzhiyun 	.pin_config_get = mxs_pinconf_get,
333*4882a593Smuzhiyun 	.pin_config_set = mxs_pinconf_set,
334*4882a593Smuzhiyun 	.pin_config_group_get = mxs_pinconf_group_get,
335*4882a593Smuzhiyun 	.pin_config_group_set = mxs_pinconf_group_set,
336*4882a593Smuzhiyun 	.pin_config_dbg_show = mxs_pinconf_dbg_show,
337*4882a593Smuzhiyun 	.pin_config_group_dbg_show = mxs_pinconf_group_dbg_show,
338*4882a593Smuzhiyun };
339*4882a593Smuzhiyun 
340*4882a593Smuzhiyun static struct pinctrl_desc mxs_pinctrl_desc = {
341*4882a593Smuzhiyun 	.pctlops = &mxs_pinctrl_ops,
342*4882a593Smuzhiyun 	.pmxops = &mxs_pinmux_ops,
343*4882a593Smuzhiyun 	.confops = &mxs_pinconf_ops,
344*4882a593Smuzhiyun 	.owner = THIS_MODULE,
345*4882a593Smuzhiyun };
346*4882a593Smuzhiyun 
mxs_pinctrl_parse_group(struct platform_device * pdev,struct device_node * np,int idx,const char ** out_name)347*4882a593Smuzhiyun static int mxs_pinctrl_parse_group(struct platform_device *pdev,
348*4882a593Smuzhiyun 				   struct device_node *np, int idx,
349*4882a593Smuzhiyun 				   const char **out_name)
350*4882a593Smuzhiyun {
351*4882a593Smuzhiyun 	struct mxs_pinctrl_data *d = platform_get_drvdata(pdev);
352*4882a593Smuzhiyun 	struct mxs_group *g = &d->soc->groups[idx];
353*4882a593Smuzhiyun 	struct property *prop;
354*4882a593Smuzhiyun 	const char *propname = "fsl,pinmux-ids";
355*4882a593Smuzhiyun 	char *group;
356*4882a593Smuzhiyun 	int length = strlen(np->name) + SUFFIX_LEN;
357*4882a593Smuzhiyun 	u32 val, i;
358*4882a593Smuzhiyun 
359*4882a593Smuzhiyun 	group = devm_kzalloc(&pdev->dev, length, GFP_KERNEL);
360*4882a593Smuzhiyun 	if (!group)
361*4882a593Smuzhiyun 		return -ENOMEM;
362*4882a593Smuzhiyun 	if (of_property_read_u32(np, "reg", &val))
363*4882a593Smuzhiyun 		snprintf(group, length, "%s", np->name);
364*4882a593Smuzhiyun 	else
365*4882a593Smuzhiyun 		snprintf(group, length, "%s.%d", np->name, val);
366*4882a593Smuzhiyun 	g->name = group;
367*4882a593Smuzhiyun 
368*4882a593Smuzhiyun 	prop = of_find_property(np, propname, &length);
369*4882a593Smuzhiyun 	if (!prop)
370*4882a593Smuzhiyun 		return -EINVAL;
371*4882a593Smuzhiyun 	g->npins = length / sizeof(u32);
372*4882a593Smuzhiyun 
373*4882a593Smuzhiyun 	g->pins = devm_kcalloc(&pdev->dev, g->npins, sizeof(*g->pins),
374*4882a593Smuzhiyun 			       GFP_KERNEL);
375*4882a593Smuzhiyun 	if (!g->pins)
376*4882a593Smuzhiyun 		return -ENOMEM;
377*4882a593Smuzhiyun 
378*4882a593Smuzhiyun 	g->muxsel = devm_kcalloc(&pdev->dev, g->npins, sizeof(*g->muxsel),
379*4882a593Smuzhiyun 				 GFP_KERNEL);
380*4882a593Smuzhiyun 	if (!g->muxsel)
381*4882a593Smuzhiyun 		return -ENOMEM;
382*4882a593Smuzhiyun 
383*4882a593Smuzhiyun 	of_property_read_u32_array(np, propname, g->pins, g->npins);
384*4882a593Smuzhiyun 	for (i = 0; i < g->npins; i++) {
385*4882a593Smuzhiyun 		g->muxsel[i] = MUXID_TO_MUXSEL(g->pins[i]);
386*4882a593Smuzhiyun 		g->pins[i] = MUXID_TO_PINID(g->pins[i]);
387*4882a593Smuzhiyun 	}
388*4882a593Smuzhiyun 
389*4882a593Smuzhiyun 	if (out_name)
390*4882a593Smuzhiyun 		*out_name = g->name;
391*4882a593Smuzhiyun 
392*4882a593Smuzhiyun 	return 0;
393*4882a593Smuzhiyun }
394*4882a593Smuzhiyun 
mxs_pinctrl_probe_dt(struct platform_device * pdev,struct mxs_pinctrl_data * d)395*4882a593Smuzhiyun static int mxs_pinctrl_probe_dt(struct platform_device *pdev,
396*4882a593Smuzhiyun 				struct mxs_pinctrl_data *d)
397*4882a593Smuzhiyun {
398*4882a593Smuzhiyun 	struct mxs_pinctrl_soc_data *soc = d->soc;
399*4882a593Smuzhiyun 	struct device_node *np = pdev->dev.of_node;
400*4882a593Smuzhiyun 	struct device_node *child;
401*4882a593Smuzhiyun 	struct mxs_function *f;
402*4882a593Smuzhiyun 	const char *gpio_compat = "fsl,mxs-gpio";
403*4882a593Smuzhiyun 	const char *fn, *fnull = "";
404*4882a593Smuzhiyun 	int i = 0, idxf = 0, idxg = 0;
405*4882a593Smuzhiyun 	int ret;
406*4882a593Smuzhiyun 	u32 val;
407*4882a593Smuzhiyun 
408*4882a593Smuzhiyun 	child = of_get_next_child(np, NULL);
409*4882a593Smuzhiyun 	if (!child) {
410*4882a593Smuzhiyun 		dev_err(&pdev->dev, "no group is defined\n");
411*4882a593Smuzhiyun 		return -ENOENT;
412*4882a593Smuzhiyun 	}
413*4882a593Smuzhiyun 
414*4882a593Smuzhiyun 	/* Count total functions and groups */
415*4882a593Smuzhiyun 	fn = fnull;
416*4882a593Smuzhiyun 	for_each_child_of_node(np, child) {
417*4882a593Smuzhiyun 		if (of_device_is_compatible(child, gpio_compat))
418*4882a593Smuzhiyun 			continue;
419*4882a593Smuzhiyun 		soc->ngroups++;
420*4882a593Smuzhiyun 		/* Skip pure pinconf node */
421*4882a593Smuzhiyun 		if (of_property_read_u32(child, "reg", &val))
422*4882a593Smuzhiyun 			continue;
423*4882a593Smuzhiyun 		if (strcmp(fn, child->name)) {
424*4882a593Smuzhiyun 			fn = child->name;
425*4882a593Smuzhiyun 			soc->nfunctions++;
426*4882a593Smuzhiyun 		}
427*4882a593Smuzhiyun 	}
428*4882a593Smuzhiyun 
429*4882a593Smuzhiyun 	soc->functions = devm_kcalloc(&pdev->dev,
430*4882a593Smuzhiyun 				      soc->nfunctions,
431*4882a593Smuzhiyun 				      sizeof(*soc->functions),
432*4882a593Smuzhiyun 				      GFP_KERNEL);
433*4882a593Smuzhiyun 	if (!soc->functions)
434*4882a593Smuzhiyun 		return -ENOMEM;
435*4882a593Smuzhiyun 
436*4882a593Smuzhiyun 	soc->groups = devm_kcalloc(&pdev->dev,
437*4882a593Smuzhiyun 				   soc->ngroups, sizeof(*soc->groups),
438*4882a593Smuzhiyun 				   GFP_KERNEL);
439*4882a593Smuzhiyun 	if (!soc->groups)
440*4882a593Smuzhiyun 		return -ENOMEM;
441*4882a593Smuzhiyun 
442*4882a593Smuzhiyun 	/* Count groups for each function */
443*4882a593Smuzhiyun 	fn = fnull;
444*4882a593Smuzhiyun 	f = &soc->functions[idxf];
445*4882a593Smuzhiyun 	for_each_child_of_node(np, child) {
446*4882a593Smuzhiyun 		if (of_device_is_compatible(child, gpio_compat))
447*4882a593Smuzhiyun 			continue;
448*4882a593Smuzhiyun 		if (of_property_read_u32(child, "reg", &val))
449*4882a593Smuzhiyun 			continue;
450*4882a593Smuzhiyun 		if (strcmp(fn, child->name)) {
451*4882a593Smuzhiyun 			struct device_node *child2;
452*4882a593Smuzhiyun 
453*4882a593Smuzhiyun 			/*
454*4882a593Smuzhiyun 			 * This reference is dropped by
455*4882a593Smuzhiyun 			 * of_get_next_child(np, * child)
456*4882a593Smuzhiyun 			 */
457*4882a593Smuzhiyun 			of_node_get(child);
458*4882a593Smuzhiyun 
459*4882a593Smuzhiyun 			/*
460*4882a593Smuzhiyun 			 * The logic parsing the functions from dt currently
461*4882a593Smuzhiyun 			 * doesn't handle if functions with the same name are
462*4882a593Smuzhiyun 			 * not grouped together. Only the first contiguous
463*4882a593Smuzhiyun 			 * cluster is usable for each function name. This is a
464*4882a593Smuzhiyun 			 * bug that is not trivial to fix, but at least warn
465*4882a593Smuzhiyun 			 * about it.
466*4882a593Smuzhiyun 			 */
467*4882a593Smuzhiyun 			for (child2 = of_get_next_child(np, child);
468*4882a593Smuzhiyun 			     child2 != NULL;
469*4882a593Smuzhiyun 			     child2 = of_get_next_child(np, child2)) {
470*4882a593Smuzhiyun 				if (!strcmp(child2->name, fn))
471*4882a593Smuzhiyun 					dev_warn(&pdev->dev,
472*4882a593Smuzhiyun 						 "function nodes must be grouped by name (failed for: %s)",
473*4882a593Smuzhiyun 						 fn);
474*4882a593Smuzhiyun 			}
475*4882a593Smuzhiyun 
476*4882a593Smuzhiyun 			f = &soc->functions[idxf++];
477*4882a593Smuzhiyun 			f->name = fn = child->name;
478*4882a593Smuzhiyun 		}
479*4882a593Smuzhiyun 		f->ngroups++;
480*4882a593Smuzhiyun 	}
481*4882a593Smuzhiyun 
482*4882a593Smuzhiyun 	/* Get groups for each function */
483*4882a593Smuzhiyun 	idxf = 0;
484*4882a593Smuzhiyun 	fn = fnull;
485*4882a593Smuzhiyun 	for_each_child_of_node(np, child) {
486*4882a593Smuzhiyun 		if (of_device_is_compatible(child, gpio_compat))
487*4882a593Smuzhiyun 			continue;
488*4882a593Smuzhiyun 		if (of_property_read_u32(child, "reg", &val)) {
489*4882a593Smuzhiyun 			ret = mxs_pinctrl_parse_group(pdev, child,
490*4882a593Smuzhiyun 						      idxg++, NULL);
491*4882a593Smuzhiyun 			if (ret) {
492*4882a593Smuzhiyun 				of_node_put(child);
493*4882a593Smuzhiyun 				return ret;
494*4882a593Smuzhiyun 			}
495*4882a593Smuzhiyun 			continue;
496*4882a593Smuzhiyun 		}
497*4882a593Smuzhiyun 
498*4882a593Smuzhiyun 		if (strcmp(fn, child->name)) {
499*4882a593Smuzhiyun 			f = &soc->functions[idxf++];
500*4882a593Smuzhiyun 			f->groups = devm_kcalloc(&pdev->dev,
501*4882a593Smuzhiyun 						 f->ngroups,
502*4882a593Smuzhiyun 						 sizeof(*f->groups),
503*4882a593Smuzhiyun 						 GFP_KERNEL);
504*4882a593Smuzhiyun 			if (!f->groups) {
505*4882a593Smuzhiyun 				of_node_put(child);
506*4882a593Smuzhiyun 				return -ENOMEM;
507*4882a593Smuzhiyun 			}
508*4882a593Smuzhiyun 			fn = child->name;
509*4882a593Smuzhiyun 			i = 0;
510*4882a593Smuzhiyun 		}
511*4882a593Smuzhiyun 		ret = mxs_pinctrl_parse_group(pdev, child, idxg++,
512*4882a593Smuzhiyun 					      &f->groups[i++]);
513*4882a593Smuzhiyun 		if (ret) {
514*4882a593Smuzhiyun 			of_node_put(child);
515*4882a593Smuzhiyun 			return ret;
516*4882a593Smuzhiyun 		}
517*4882a593Smuzhiyun 	}
518*4882a593Smuzhiyun 
519*4882a593Smuzhiyun 	return 0;
520*4882a593Smuzhiyun }
521*4882a593Smuzhiyun 
mxs_pinctrl_probe(struct platform_device * pdev,struct mxs_pinctrl_soc_data * soc)522*4882a593Smuzhiyun int mxs_pinctrl_probe(struct platform_device *pdev,
523*4882a593Smuzhiyun 		      struct mxs_pinctrl_soc_data *soc)
524*4882a593Smuzhiyun {
525*4882a593Smuzhiyun 	struct device_node *np = pdev->dev.of_node;
526*4882a593Smuzhiyun 	struct mxs_pinctrl_data *d;
527*4882a593Smuzhiyun 	int ret;
528*4882a593Smuzhiyun 
529*4882a593Smuzhiyun 	d = devm_kzalloc(&pdev->dev, sizeof(*d), GFP_KERNEL);
530*4882a593Smuzhiyun 	if (!d)
531*4882a593Smuzhiyun 		return -ENOMEM;
532*4882a593Smuzhiyun 
533*4882a593Smuzhiyun 	d->dev = &pdev->dev;
534*4882a593Smuzhiyun 	d->soc = soc;
535*4882a593Smuzhiyun 
536*4882a593Smuzhiyun 	d->base = of_iomap(np, 0);
537*4882a593Smuzhiyun 	if (!d->base)
538*4882a593Smuzhiyun 		return -EADDRNOTAVAIL;
539*4882a593Smuzhiyun 
540*4882a593Smuzhiyun 	mxs_pinctrl_desc.pins = d->soc->pins;
541*4882a593Smuzhiyun 	mxs_pinctrl_desc.npins = d->soc->npins;
542*4882a593Smuzhiyun 	mxs_pinctrl_desc.name = dev_name(&pdev->dev);
543*4882a593Smuzhiyun 
544*4882a593Smuzhiyun 	platform_set_drvdata(pdev, d);
545*4882a593Smuzhiyun 
546*4882a593Smuzhiyun 	ret = mxs_pinctrl_probe_dt(pdev, d);
547*4882a593Smuzhiyun 	if (ret) {
548*4882a593Smuzhiyun 		dev_err(&pdev->dev, "dt probe failed: %d\n", ret);
549*4882a593Smuzhiyun 		goto err;
550*4882a593Smuzhiyun 	}
551*4882a593Smuzhiyun 
552*4882a593Smuzhiyun 	d->pctl = pinctrl_register(&mxs_pinctrl_desc, &pdev->dev, d);
553*4882a593Smuzhiyun 	if (IS_ERR(d->pctl)) {
554*4882a593Smuzhiyun 		dev_err(&pdev->dev, "Couldn't register MXS pinctrl driver\n");
555*4882a593Smuzhiyun 		ret = PTR_ERR(d->pctl);
556*4882a593Smuzhiyun 		goto err;
557*4882a593Smuzhiyun 	}
558*4882a593Smuzhiyun 
559*4882a593Smuzhiyun 	return 0;
560*4882a593Smuzhiyun 
561*4882a593Smuzhiyun err:
562*4882a593Smuzhiyun 	iounmap(d->base);
563*4882a593Smuzhiyun 	return ret;
564*4882a593Smuzhiyun }
565