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", ®))
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