]>
Commit | Line | Data |
---|---|---|
83d290c5 | 1 | // SPDX-License-Identifier: GPL-2.0+ |
08718066 GC |
2 | /* |
3 | * U-Boot Marvell 37xx SoC pinctrl driver | |
4 | * | |
5 | * Copyright (C) 2017 Stefan Roese <sr@denx.de> | |
6 | * | |
7 | * This driver is based on the Linux driver version, which is: | |
8 | * Copyright (C) 2017 Marvell | |
9 | * Gregory CLEMENT <gregory.clement@free-electrons.com> | |
10 | * | |
11 | * Additionally parts are derived from the Meson U-Boot pinctrl driver, | |
12 | * which is: | |
13 | * (C) Copyright 2016 - Beniamino Galvani <b.galvani@gmail.com> | |
14 | * Based on code from Linux kernel: | |
15 | * Copyright (C) 2016 Endless Mobile, Inc. | |
08718066 GC |
16 | * https://spdx.org/licenses |
17 | */ | |
18 | ||
d678a59d | 19 | #include <common.h> |
08718066 GC |
20 | #include <config.h> |
21 | #include <dm.h> | |
336d4615 | 22 | #include <malloc.h> |
401d1c4f | 23 | #include <asm/global_data.h> |
d2d92bd7 | 24 | #include <dm/device-internal.h> |
336d4615 | 25 | #include <dm/device_compat.h> |
61b29b82 | 26 | #include <dm/devres.h> |
d2d92bd7 | 27 | #include <dm/lists.h> |
08718066 GC |
28 | #include <dm/pinctrl.h> |
29 | #include <dm/root.h> | |
30 | #include <errno.h> | |
31 | #include <fdtdec.h> | |
32 | #include <regmap.h> | |
d2d92bd7 | 33 | #include <asm/gpio.h> |
08718066 GC |
34 | #include <asm/system.h> |
35 | #include <asm/io.h> | |
cd93d625 | 36 | #include <linux/bitops.h> |
4d72caa5 | 37 | #include <linux/libfdt.h> |
1e94b46f | 38 | #include <linux/printk.h> |
08718066 GC |
39 | |
40 | DECLARE_GLOBAL_DATA_PTR; | |
41 | ||
42 | #define OUTPUT_EN 0x0 | |
d2d92bd7 GC |
43 | #define INPUT_VAL 0x10 |
44 | #define OUTPUT_VAL 0x18 | |
08718066 GC |
45 | #define OUTPUT_CTL 0x20 |
46 | #define SELECTION 0x30 | |
47 | ||
48 | #define IRQ_EN 0x0 | |
49 | #define IRQ_POL 0x08 | |
50 | #define IRQ_STATUS 0x10 | |
51 | #define IRQ_WKUP 0x18 | |
52 | ||
23626cac | 53 | #define NB_FUNCS 3 |
08718066 GC |
54 | #define GPIO_PER_REG 32 |
55 | ||
56 | /** | |
57 | * struct armada_37xx_pin_group: represents group of pins of a pinmux function. | |
58 | * The pins of a pinmux groups are composed of one or two groups of contiguous | |
59 | * pins. | |
60 | * @name: Name of the pin group, used to lookup the group. | |
61 | * @start_pins: Index of the first pin of the main range of pins belonging to | |
62 | * the group | |
63 | * @npins: Number of pins included in the first range | |
64 | * @reg_mask: Bit mask matching the group in the selection register | |
65 | * @extra_pins: Index of the first pin of the optional second range of pins | |
66 | * belonging to the group | |
67 | * @npins: Number of pins included in the second optional range | |
68 | * @funcs: A list of pinmux functions that can be selected for this group. | |
08718066 GC |
69 | */ |
70 | struct armada_37xx_pin_group { | |
71 | const char *name; | |
72 | unsigned int start_pin; | |
73 | unsigned int npins; | |
74 | u32 reg_mask; | |
75 | u32 val[NB_FUNCS]; | |
76 | unsigned int extra_pin; | |
77 | unsigned int extra_npins; | |
78 | const char *funcs[NB_FUNCS]; | |
08718066 GC |
79 | }; |
80 | ||
81 | struct armada_37xx_pin_data { | |
82 | u8 nr_pins; | |
83 | char *name; | |
84 | struct armada_37xx_pin_group *groups; | |
85 | int ngroups; | |
86 | }; | |
87 | ||
88 | struct armada_37xx_pmx_func { | |
89 | const char *name; | |
90 | const char **groups; | |
91 | unsigned int ngroups; | |
92 | }; | |
93 | ||
94 | struct armada_37xx_pinctrl { | |
95 | void __iomem *base; | |
96 | const struct armada_37xx_pin_data *data; | |
97 | struct udevice *dev; | |
98 | struct pinctrl_dev *pctl_dev; | |
08718066 GC |
99 | struct armada_37xx_pmx_func *funcs; |
100 | unsigned int nfuncs; | |
101 | }; | |
102 | ||
3d98071d T |
103 | #define PIN_GRP_GPIO_0(_name, _start, _nr) \ |
104 | { \ | |
105 | .name = _name, \ | |
106 | .start_pin = _start, \ | |
107 | .npins = _nr, \ | |
108 | .reg_mask = 0, \ | |
109 | .val = {0}, \ | |
110 | .funcs = {"gpio"} \ | |
111 | } | |
112 | ||
08718066 GC |
113 | #define PIN_GRP_GPIO(_name, _start, _nr, _mask, _func1) \ |
114 | { \ | |
115 | .name = _name, \ | |
116 | .start_pin = _start, \ | |
117 | .npins = _nr, \ | |
118 | .reg_mask = _mask, \ | |
119 | .val = {0, _mask}, \ | |
120 | .funcs = {_func1, "gpio"} \ | |
121 | } | |
122 | ||
123 | #define PIN_GRP_GPIO_2(_name, _start, _nr, _mask, _val1, _val2, _func1) \ | |
124 | { \ | |
125 | .name = _name, \ | |
126 | .start_pin = _start, \ | |
127 | .npins = _nr, \ | |
128 | .reg_mask = _mask, \ | |
129 | .val = {_val1, _val2}, \ | |
130 | .funcs = {_func1, "gpio"} \ | |
131 | } | |
132 | ||
23626cac KM |
133 | #define PIN_GRP_GPIO_3(_name, _start, _nr, _mask, _v1, _v2, _v3, _f1, _f2) \ |
134 | { \ | |
135 | .name = _name, \ | |
136 | .start_pin = _start, \ | |
137 | .npins = _nr, \ | |
138 | .reg_mask = _mask, \ | |
139 | .val = {_v1, _v2, _v3}, \ | |
140 | .funcs = {_f1, _f2, "gpio"} \ | |
141 | } | |
142 | ||
08718066 GC |
143 | #define PIN_GRP_EXTRA(_name, _start, _nr, _mask, _v1, _v2, _start2, _nr2, \ |
144 | _f1, _f2) \ | |
145 | { \ | |
146 | .name = _name, \ | |
147 | .start_pin = _start, \ | |
148 | .npins = _nr, \ | |
149 | .reg_mask = _mask, \ | |
150 | .val = {_v1, _v2}, \ | |
151 | .extra_pin = _start2, \ | |
152 | .extra_npins = _nr2, \ | |
153 | .funcs = {_f1, _f2} \ | |
154 | } | |
155 | ||
156 | static struct armada_37xx_pin_group armada_37xx_nb_groups[] = { | |
157 | PIN_GRP_GPIO("jtag", 20, 5, BIT(0), "jtag"), | |
158 | PIN_GRP_GPIO("sdio0", 8, 3, BIT(1), "sdio"), | |
159 | PIN_GRP_GPIO("emmc_nb", 27, 9, BIT(2), "emmc"), | |
5534fb4f MB |
160 | PIN_GRP_GPIO_3("pwm0", 11, 1, BIT(3) | BIT(20), 0, BIT(20), BIT(3), |
161 | "pwm", "led"), | |
87724d5c | 162 | PIN_GRP_GPIO_3("pwm1", 12, 1, BIT(4) | BIT(21), 0, BIT(21), BIT(4), |
5534fb4f | 163 | "pwm", "led"), |
87724d5c | 164 | PIN_GRP_GPIO_3("pwm2", 13, 1, BIT(5) | BIT(22), 0, BIT(22), BIT(5), |
5534fb4f | 165 | "pwm", "led"), |
87724d5c | 166 | PIN_GRP_GPIO_3("pwm3", 14, 1, BIT(6) | BIT(23), 0, BIT(23), BIT(6), |
5534fb4f | 167 | "pwm", "led"), |
dc36235a KM |
168 | PIN_GRP_GPIO("pmic1", 7, 1, BIT(7), "pmic"), |
169 | PIN_GRP_GPIO("pmic0", 6, 1, BIT(8), "pmic"), | |
3d98071d | 170 | PIN_GRP_GPIO_0("gpio1_5", 5, 1), |
08718066 GC |
171 | PIN_GRP_GPIO("i2c2", 2, 2, BIT(9), "i2c"), |
172 | PIN_GRP_GPIO("i2c1", 0, 2, BIT(10), "i2c"), | |
173 | PIN_GRP_GPIO("spi_cs1", 17, 1, BIT(12), "spi"), | |
174 | PIN_GRP_GPIO_2("spi_cs2", 18, 1, BIT(13) | BIT(19), 0, BIT(13), "spi"), | |
175 | PIN_GRP_GPIO_2("spi_cs3", 19, 1, BIT(14) | BIT(19), 0, BIT(14), "spi"), | |
176 | PIN_GRP_GPIO("onewire", 4, 1, BIT(16), "onewire"), | |
177 | PIN_GRP_GPIO("uart1", 25, 2, BIT(17), "uart"), | |
178 | PIN_GRP_GPIO("spi_quad", 15, 2, BIT(18), "spi"), | |
b5a6c94a KM |
179 | PIN_GRP_EXTRA("uart2", 9, 2, BIT(1) | BIT(13) | BIT(14) | BIT(19), |
180 | BIT(1) | BIT(13) | BIT(14), BIT(1) | BIT(19), | |
181 | 18, 2, "gpio", "uart"), | |
08718066 GC |
182 | }; |
183 | ||
184 | static struct armada_37xx_pin_group armada_37xx_sb_groups[] = { | |
185 | PIN_GRP_GPIO("usb32_drvvbus0", 0, 1, BIT(0), "drvbus"), | |
186 | PIN_GRP_GPIO("usb2_drvvbus1", 1, 1, BIT(1), "drvbus"), | |
3d98071d | 187 | PIN_GRP_GPIO_0("gpio2_2", 2, 1), |
dc36235a KM |
188 | PIN_GRP_GPIO("sdio_sb", 24, 6, BIT(2), "sdio"), |
189 | PIN_GRP_GPIO("rgmii", 6, 12, BIT(3), "mii"), | |
190 | PIN_GRP_GPIO("smi", 18, 2, BIT(4), "smi"), | |
3d98071d T |
191 | PIN_GRP_GPIO("pcie1", 3, 1, BIT(5), "pcie"), /* this actually controls "pcie1_reset" */ |
192 | PIN_GRP_GPIO("pcie1_clkreq", 4, 1, BIT(9), "pcie"), | |
193 | PIN_GRP_GPIO("pcie1_wakeup", 5, 1, BIT(10), "pcie"), | |
7a1c0711 T |
194 | PIN_GRP_GPIO("ptp", 20, 1, BIT(11), "ptp"), |
195 | PIN_GRP_GPIO_3("ptp_clk", 21, 1, BIT(6) | BIT(12), 0, BIT(6), BIT(12), | |
196 | "ptp", "mii"), | |
197 | PIN_GRP_GPIO_3("ptp_trig", 22, 1, BIT(7) | BIT(13), 0, BIT(7), BIT(13), | |
198 | "ptp", "mii"), | |
23626cac KM |
199 | PIN_GRP_GPIO_3("mii_col", 23, 1, BIT(8) | BIT(14), 0, BIT(8), BIT(14), |
200 | "mii", "mii_err"), | |
08718066 GC |
201 | }; |
202 | ||
ffab0495 | 203 | static const struct armada_37xx_pin_data armada_37xx_pin_nb = { |
08718066 GC |
204 | .nr_pins = 36, |
205 | .name = "GPIO1", | |
206 | .groups = armada_37xx_nb_groups, | |
207 | .ngroups = ARRAY_SIZE(armada_37xx_nb_groups), | |
208 | }; | |
209 | ||
ffab0495 | 210 | static const struct armada_37xx_pin_data armada_37xx_pin_sb = { |
44ac747b | 211 | .nr_pins = 30, |
08718066 GC |
212 | .name = "GPIO2", |
213 | .groups = armada_37xx_sb_groups, | |
214 | .ngroups = ARRAY_SIZE(armada_37xx_sb_groups), | |
215 | }; | |
216 | ||
d2d92bd7 | 217 | static inline void armada_37xx_update_reg(unsigned int *reg, |
0237448a | 218 | unsigned int *offset) |
d2d92bd7 GC |
219 | { |
220 | /* We never have more than 2 registers */ | |
0237448a KM |
221 | if (*offset >= GPIO_PER_REG) { |
222 | *offset -= GPIO_PER_REG; | |
d2d92bd7 GC |
223 | *reg += sizeof(u32); |
224 | } | |
225 | } | |
226 | ||
08718066 GC |
227 | static int armada_37xx_get_func_reg(struct armada_37xx_pin_group *grp, |
228 | const char *func) | |
229 | { | |
230 | int f; | |
231 | ||
23626cac | 232 | for (f = 0; (f < NB_FUNCS) && grp->funcs[f]; f++) |
08718066 GC |
233 | if (!strcmp(grp->funcs[f], func)) |
234 | return f; | |
235 | ||
236 | return -ENOTSUPP; | |
237 | } | |
238 | ||
239 | static int armada_37xx_pmx_get_groups_count(struct udevice *dev) | |
240 | { | |
241 | struct armada_37xx_pinctrl *info = dev_get_priv(dev); | |
242 | ||
33893e52 | 243 | return info->data->ngroups; |
08718066 GC |
244 | } |
245 | ||
246 | static const char *armada_37xx_pmx_dummy_name = "_dummy"; | |
247 | ||
248 | static const char *armada_37xx_pmx_get_group_name(struct udevice *dev, | |
249 | unsigned selector) | |
250 | { | |
251 | struct armada_37xx_pinctrl *info = dev_get_priv(dev); | |
252 | ||
33893e52 | 253 | if (!info->data->groups[selector].name) |
08718066 GC |
254 | return armada_37xx_pmx_dummy_name; |
255 | ||
33893e52 | 256 | return info->data->groups[selector].name; |
08718066 GC |
257 | } |
258 | ||
259 | static int armada_37xx_pmx_get_funcs_count(struct udevice *dev) | |
260 | { | |
261 | struct armada_37xx_pinctrl *info = dev_get_priv(dev); | |
262 | ||
263 | return info->nfuncs; | |
264 | } | |
265 | ||
266 | static const char *armada_37xx_pmx_get_func_name(struct udevice *dev, | |
267 | unsigned selector) | |
268 | { | |
269 | struct armada_37xx_pinctrl *info = dev_get_priv(dev); | |
270 | ||
271 | return info->funcs[selector].name; | |
272 | } | |
273 | ||
274 | static int armada_37xx_pmx_set_by_name(struct udevice *dev, | |
275 | const char *name, | |
140ebcdb T |
276 | struct armada_37xx_pin_group *grp, |
277 | bool warn_on_change) | |
08718066 GC |
278 | { |
279 | struct armada_37xx_pinctrl *info = dev_get_priv(dev); | |
280 | unsigned int reg = SELECTION; | |
281 | unsigned int mask = grp->reg_mask; | |
140ebcdb | 282 | int func, val, old_func; |
08718066 GC |
283 | |
284 | dev_dbg(info->dev, "enable function %s group %s\n", | |
285 | name, grp->name); | |
286 | ||
287 | func = armada_37xx_get_func_reg(grp, name); | |
288 | ||
289 | if (func < 0) | |
290 | return func; | |
291 | ||
292 | val = grp->val[func]; | |
293 | ||
140ebcdb T |
294 | if (warn_on_change && val != (readl(info->base + reg) & mask)) { |
295 | for (old_func = 0; (old_func < NB_FUNCS) && grp->funcs[old_func]; old_func++) { | |
296 | if (grp->val[old_func] == val) | |
297 | break; | |
298 | } | |
299 | dev_warn(info->dev, "Warning: Changing MPPs %u-%u function from %s to %s...\n", | |
300 | grp->start_pin, grp->start_pin + grp->npins - 1, | |
301 | ((old_func < NB_FUNCS && grp->funcs[old_func]) ? | |
302 | grp->funcs[old_func] : "unknown"), | |
303 | name); | |
304 | } | |
305 | ||
08718066 GC |
306 | clrsetbits_le32(info->base + reg, mask, val); |
307 | ||
308 | return 0; | |
309 | } | |
310 | ||
311 | static int armada_37xx_pmx_group_set(struct udevice *dev, | |
312 | unsigned group_selector, | |
313 | unsigned func_selector) | |
314 | { | |
315 | struct armada_37xx_pinctrl *info = dev_get_priv(dev); | |
33893e52 | 316 | struct armada_37xx_pin_group *grp = &info->data->groups[group_selector]; |
08718066 GC |
317 | const char *name = info->funcs[func_selector].name; |
318 | ||
140ebcdb T |
319 | return armada_37xx_pmx_set_by_name(dev, name, grp, false); |
320 | } | |
321 | ||
322 | static int armada_37xx_pmx_gpio_request_enable(struct udevice *dev, unsigned int selector) | |
323 | { | |
324 | struct armada_37xx_pinctrl *info = dev_get_priv(dev); | |
325 | int ret = -ENOTSUPP; | |
326 | int n; | |
327 | ||
328 | /* Find all groups where is requested selector pin and set each group to gpio function */ | |
329 | for (n = 0; n < info->data->ngroups; n++) { | |
330 | struct armada_37xx_pin_group *grp = &info->data->groups[n]; | |
331 | ||
332 | if ((selector >= grp->start_pin && selector < grp->start_pin + grp->npins) || | |
333 | (selector >= grp->extra_pin && selector < grp->extra_pin + grp->extra_npins)) { | |
334 | ret = armada_37xx_pmx_set_by_name(dev, "gpio", grp, true); | |
335 | if (ret) | |
336 | return ret; | |
337 | } | |
338 | } | |
339 | ||
340 | return ret; | |
341 | } | |
342 | ||
343 | static int armada_37xx_pmx_gpio_disable_free(struct udevice *dev, unsigned int selector) | |
344 | { | |
345 | /* nothing to do */ | |
346 | return 0; | |
08718066 GC |
347 | } |
348 | ||
e34d8afd T |
349 | static int armada_37xx_pmx_get_pins_count(struct udevice *dev) |
350 | { | |
351 | struct armada_37xx_pinctrl *info = dev_get_priv(dev); | |
352 | ||
353 | return info->data->nr_pins; | |
354 | } | |
355 | ||
356 | static const char *armada_37xx_pmx_get_pin_name(struct udevice *dev, unsigned int selector) | |
357 | { | |
358 | struct armada_37xx_pinctrl *info = dev_get_priv(dev); | |
359 | static char buf[sizeof("MPPx_XX")]; | |
360 | ||
361 | sprintf(buf, "MPP%c_%u", info->data->name[4], selector); | |
362 | return buf; | |
363 | } | |
364 | ||
365 | static int armada_37xx_pmx_get_pin_muxing(struct udevice *dev, unsigned int selector, | |
366 | char *buf, int size) | |
367 | { | |
368 | struct armada_37xx_pinctrl *info = dev_get_priv(dev); | |
369 | int n; | |
370 | ||
371 | /* | |
372 | * First check if selected pin is in some extra pin group. | |
373 | * Function in extra pin group is active only when it is not gpio. | |
374 | */ | |
375 | for (n = 0; n < info->data->ngroups; n++) { | |
376 | struct armada_37xx_pin_group *grp = &info->data->groups[n]; | |
377 | ||
378 | if (selector >= grp->extra_pin && selector < grp->extra_pin + grp->extra_npins) { | |
379 | unsigned int reg = SELECTION; | |
380 | unsigned int mask = grp->reg_mask; | |
381 | int f, val; | |
382 | ||
383 | val = (readl(info->base + reg) & mask); | |
384 | ||
385 | for (f = 0; f < NB_FUNCS && grp->funcs[f]; f++) { | |
386 | if (grp->val[f] == val) { | |
387 | if (strcmp(grp->funcs[f], "gpio") != 0) { | |
388 | strlcpy(buf, grp->funcs[f], size); | |
389 | return 0; | |
390 | } | |
391 | break; | |
392 | } | |
393 | } | |
394 | } | |
395 | } | |
396 | ||
397 | /* If pin is not active in some extra pin group then check regular groups. */ | |
398 | for (n = 0; n < info->data->ngroups; n++) { | |
399 | struct armada_37xx_pin_group *grp = &info->data->groups[n]; | |
400 | ||
401 | if (selector >= grp->start_pin && selector < grp->start_pin + grp->npins) { | |
402 | unsigned int reg = SELECTION; | |
403 | unsigned int mask = grp->reg_mask; | |
404 | int f, val; | |
405 | ||
406 | val = (readl(info->base + reg) & mask); | |
407 | ||
408 | for (f = 0; f < NB_FUNCS && grp->funcs[f]; f++) { | |
409 | if (grp->val[f] == val) { | |
01909064 T |
410 | /* |
411 | * In more cases group name consist of | |
412 | * function name followed by function | |
413 | * number. So if function name is just | |
414 | * prefix of group name, show group name. | |
415 | */ | |
416 | if (strncmp(grp->name, grp->funcs[f], | |
417 | strlen(grp->funcs[f])) == 0) | |
418 | strlcpy(buf, grp->name, size); | |
419 | else | |
420 | strlcpy(buf, grp->funcs[f], size); | |
e34d8afd T |
421 | return 0; |
422 | } | |
423 | } | |
424 | ||
425 | strlcpy(buf, "unknown", size); | |
426 | return 0; | |
427 | } | |
428 | } | |
429 | ||
430 | strlcpy(buf, "unknown", size); | |
431 | return 0; | |
432 | } | |
433 | ||
08718066 GC |
434 | /** |
435 | * armada_37xx_add_function() - Add a new function to the list | |
436 | * @funcs: array of function to add the new one | |
437 | * @funcsize: size of the remaining space for the function | |
438 | * @name: name of the function to add | |
439 | * | |
440 | * If it is a new function then create it by adding its name else | |
441 | * increment the number of group associated to this function. | |
442 | */ | |
443 | static int armada_37xx_add_function(struct armada_37xx_pmx_func *funcs, | |
444 | int *funcsize, const char *name) | |
445 | { | |
446 | int i = 0; | |
447 | ||
448 | if (*funcsize <= 0) | |
449 | return -EOVERFLOW; | |
450 | ||
451 | while (funcs->ngroups) { | |
452 | /* function already there */ | |
453 | if (strcmp(funcs->name, name) == 0) { | |
454 | funcs->ngroups++; | |
455 | ||
456 | return -EEXIST; | |
457 | } | |
458 | funcs++; | |
459 | i++; | |
460 | } | |
461 | ||
462 | /* append new unique function */ | |
463 | funcs->name = name; | |
464 | funcs->ngroups = 1; | |
465 | (*funcsize)--; | |
466 | ||
467 | return 0; | |
468 | } | |
469 | ||
470 | /** | |
471 | * armada_37xx_fill_group() - complete the group array | |
472 | * @info: info driver instance | |
473 | * | |
474 | * Based on the data available from the armada_37xx_pin_group array | |
475 | * completes the last member of the struct for each function: the list | |
476 | * of the groups associated to this function. | |
477 | * | |
478 | */ | |
479 | static int armada_37xx_fill_group(struct armada_37xx_pinctrl *info) | |
480 | { | |
481 | int n, num = 0, funcsize = info->data->nr_pins; | |
482 | ||
33893e52 T |
483 | for (n = 0; n < info->data->ngroups; n++) { |
484 | struct armada_37xx_pin_group *grp = &info->data->groups[n]; | |
bd913a72 | 485 | int f; |
08718066 | 486 | |
23626cac | 487 | for (f = 0; (f < NB_FUNCS) && grp->funcs[f]; f++) { |
08718066 GC |
488 | int ret; |
489 | /* check for unique functions and count groups */ | |
490 | ret = armada_37xx_add_function(info->funcs, &funcsize, | |
491 | grp->funcs[f]); | |
492 | if (ret == -EOVERFLOW) | |
493 | dev_err(info->dev, | |
494 | "More functions than pins(%d)\n", | |
495 | info->data->nr_pins); | |
496 | if (ret < 0) | |
497 | continue; | |
498 | num++; | |
499 | } | |
500 | } | |
501 | ||
502 | info->nfuncs = num; | |
503 | ||
504 | return 0; | |
505 | } | |
506 | ||
507 | /** | |
508 | * armada_37xx_fill_funcs() - complete the funcs array | |
509 | * @info: info driver instance | |
510 | * | |
511 | * Based on the data available from the armada_37xx_pin_group array | |
512 | * completes the last two member of the struct for each group: | |
513 | * - the list of the pins included in the group | |
514 | * - the list of pinmux functions that can be selected for this group | |
515 | * | |
516 | */ | |
517 | static int armada_37xx_fill_func(struct armada_37xx_pinctrl *info) | |
518 | { | |
519 | struct armada_37xx_pmx_func *funcs = info->funcs; | |
520 | int n; | |
521 | ||
522 | for (n = 0; n < info->nfuncs; n++) { | |
523 | const char *name = funcs[n].name; | |
524 | const char **groups; | |
525 | int g; | |
526 | ||
527 | funcs[n].groups = devm_kzalloc(info->dev, funcs[n].ngroups * | |
528 | sizeof(*(funcs[n].groups)), | |
529 | GFP_KERNEL); | |
530 | if (!funcs[n].groups) | |
531 | return -ENOMEM; | |
532 | ||
533 | groups = funcs[n].groups; | |
534 | ||
33893e52 T |
535 | for (g = 0; g < info->data->ngroups; g++) { |
536 | struct armada_37xx_pin_group *gp = &info->data->groups[g]; | |
08718066 GC |
537 | int f; |
538 | ||
23626cac | 539 | for (f = 0; (f < NB_FUNCS) && gp->funcs[f]; f++) { |
08718066 GC |
540 | if (strcmp(gp->funcs[f], name) == 0) { |
541 | *groups = gp->name; | |
542 | groups++; | |
543 | } | |
544 | } | |
545 | } | |
546 | } | |
547 | return 0; | |
548 | } | |
549 | ||
d2d92bd7 GC |
550 | static int armada_37xx_gpio_get(struct udevice *dev, unsigned int offset) |
551 | { | |
552 | struct armada_37xx_pinctrl *info = dev_get_priv(dev->parent); | |
553 | unsigned int reg = INPUT_VAL; | |
554 | unsigned int val, mask; | |
555 | ||
0237448a | 556 | armada_37xx_update_reg(®, &offset); |
d2d92bd7 GC |
557 | mask = BIT(offset); |
558 | ||
559 | val = readl(info->base + reg); | |
560 | ||
561 | return (val & mask) != 0; | |
562 | } | |
563 | ||
564 | static int armada_37xx_gpio_set(struct udevice *dev, unsigned int offset, | |
565 | int value) | |
566 | { | |
567 | struct armada_37xx_pinctrl *info = dev_get_priv(dev->parent); | |
568 | unsigned int reg = OUTPUT_VAL; | |
569 | unsigned int mask, val; | |
570 | ||
0237448a | 571 | armada_37xx_update_reg(®, &offset); |
d2d92bd7 GC |
572 | mask = BIT(offset); |
573 | val = value ? mask : 0; | |
574 | ||
575 | clrsetbits_le32(info->base + reg, mask, val); | |
576 | ||
577 | return 0; | |
578 | } | |
579 | ||
580 | static int armada_37xx_gpio_get_direction(struct udevice *dev, | |
581 | unsigned int offset) | |
582 | { | |
583 | struct armada_37xx_pinctrl *info = dev_get_priv(dev->parent); | |
584 | unsigned int reg = OUTPUT_EN; | |
585 | unsigned int val, mask; | |
586 | ||
0237448a | 587 | armada_37xx_update_reg(®, &offset); |
d2d92bd7 GC |
588 | mask = BIT(offset); |
589 | val = readl(info->base + reg); | |
590 | ||
591 | if (val & mask) | |
592 | return GPIOF_OUTPUT; | |
593 | else | |
594 | return GPIOF_INPUT; | |
595 | } | |
596 | ||
597 | static int armada_37xx_gpio_direction_input(struct udevice *dev, | |
598 | unsigned int offset) | |
599 | { | |
600 | struct armada_37xx_pinctrl *info = dev_get_priv(dev->parent); | |
601 | unsigned int reg = OUTPUT_EN; | |
602 | unsigned int mask; | |
603 | ||
0237448a | 604 | armada_37xx_update_reg(®, &offset); |
d2d92bd7 GC |
605 | mask = BIT(offset); |
606 | ||
607 | clrbits_le32(info->base + reg, mask); | |
608 | ||
609 | return 0; | |
610 | } | |
611 | ||
612 | static int armada_37xx_gpio_direction_output(struct udevice *dev, | |
613 | unsigned int offset, int value) | |
614 | { | |
615 | struct armada_37xx_pinctrl *info = dev_get_priv(dev->parent); | |
616 | unsigned int reg = OUTPUT_EN; | |
617 | unsigned int mask; | |
618 | ||
0237448a | 619 | armada_37xx_update_reg(®, &offset); |
d2d92bd7 GC |
620 | mask = BIT(offset); |
621 | ||
622 | setbits_le32(info->base + reg, mask); | |
623 | ||
624 | /* And set the requested value */ | |
625 | return armada_37xx_gpio_set(dev, offset, value); | |
626 | } | |
627 | ||
628 | static int armada_37xx_gpio_probe(struct udevice *dev) | |
629 | { | |
630 | struct armada_37xx_pinctrl *info = dev_get_priv(dev->parent); | |
631 | struct gpio_dev_priv *uc_priv; | |
632 | ||
633 | uc_priv = dev_get_uclass_priv(dev); | |
634 | uc_priv->bank_name = info->data->name; | |
635 | uc_priv->gpio_count = info->data->nr_pins; | |
636 | ||
637 | return 0; | |
638 | } | |
639 | ||
640 | static const struct dm_gpio_ops armada_37xx_gpio_ops = { | |
140ebcdb T |
641 | .request = pinctrl_gpio_request, |
642 | .rfree = pinctrl_gpio_free, | |
d2d92bd7 GC |
643 | .set_value = armada_37xx_gpio_set, |
644 | .get_value = armada_37xx_gpio_get, | |
645 | .get_function = armada_37xx_gpio_get_direction, | |
646 | .direction_input = armada_37xx_gpio_direction_input, | |
647 | .direction_output = armada_37xx_gpio_direction_output, | |
648 | }; | |
649 | ||
650 | static struct driver armada_37xx_gpio_driver = { | |
651 | .name = "armada-37xx-gpio", | |
652 | .id = UCLASS_GPIO, | |
653 | .probe = armada_37xx_gpio_probe, | |
654 | .ops = &armada_37xx_gpio_ops, | |
655 | }; | |
656 | ||
657 | static int armada_37xx_gpiochip_register(struct udevice *parent, | |
658 | struct armada_37xx_pinctrl *info) | |
659 | { | |
660 | const void *blob = gd->fdt_blob; | |
661 | int node = dev_of_offset(parent); | |
662 | struct uclass_driver *drv; | |
663 | struct udevice *dev; | |
664 | int ret = -ENODEV; | |
665 | int subnode; | |
666 | char *name; | |
667 | ||
a2703ce1 | 668 | /* FIXME: Should not need to lookup GPIO uclass */ |
d2d92bd7 GC |
669 | drv = lists_uclass_lookup(UCLASS_GPIO); |
670 | if (!drv) { | |
671 | puts("Cannot find GPIO driver\n"); | |
672 | return -ENOENT; | |
673 | } | |
674 | ||
a2703ce1 | 675 | /* FIXME: Use livtree and check the result of device_bind() below */ |
d2d92bd7 | 676 | fdt_for_each_subnode(subnode, blob, node) { |
ae118b68 | 677 | if (fdtdec_get_bool(blob, subnode, "gpio-controller")) { |
d2d92bd7 GC |
678 | ret = 0; |
679 | break; | |
680 | } | |
681 | }; | |
682 | if (ret) | |
683 | return ret; | |
684 | ||
685 | name = calloc(1, 32); | |
686 | sprintf(name, "armada-37xx-gpio"); | |
687 | ||
688 | /* Create child device UCLASS_GPIO and bind it */ | |
a2703ce1 SG |
689 | device_bind(parent, &armada_37xx_gpio_driver, name, NULL, |
690 | offset_to_ofnode(subnode), &dev); | |
d2d92bd7 GC |
691 | |
692 | return 0; | |
693 | } | |
694 | ||
ffab0495 | 695 | static const struct pinctrl_ops armada_37xx_pinctrl_ops = { |
e34d8afd T |
696 | .get_pins_count = armada_37xx_pmx_get_pins_count, |
697 | .get_pin_name = armada_37xx_pmx_get_pin_name, | |
698 | .get_pin_muxing = armada_37xx_pmx_get_pin_muxing, | |
08718066 GC |
699 | .get_groups_count = armada_37xx_pmx_get_groups_count, |
700 | .get_group_name = armada_37xx_pmx_get_group_name, | |
701 | .get_functions_count = armada_37xx_pmx_get_funcs_count, | |
702 | .get_function_name = armada_37xx_pmx_get_func_name, | |
703 | .pinmux_group_set = armada_37xx_pmx_group_set, | |
140ebcdb T |
704 | .gpio_request_enable = armada_37xx_pmx_gpio_request_enable, |
705 | .gpio_disable_free = armada_37xx_pmx_gpio_disable_free, | |
08718066 GC |
706 | .set_state = pinctrl_generic_set_state, |
707 | }; | |
708 | ||
ffab0495 | 709 | static int armada_37xx_pinctrl_probe(struct udevice *dev) |
08718066 GC |
710 | { |
711 | struct armada_37xx_pinctrl *info = dev_get_priv(dev); | |
712 | const struct armada_37xx_pin_data *pin_data; | |
713 | int ret; | |
714 | ||
715 | info->data = (struct armada_37xx_pin_data *)dev_get_driver_data(dev); | |
716 | pin_data = info->data; | |
717 | ||
8613c8d8 | 718 | info->base = dev_read_addr_ptr(dev); |
08718066 | 719 | if (!info->base) { |
9b643e31 | 720 | pr_err("unable to find regmap\n"); |
08718066 GC |
721 | return -ENODEV; |
722 | } | |
723 | ||
08718066 GC |
724 | /* |
725 | * we allocate functions for number of pins and hope there are | |
726 | * fewer unique functions than pins available | |
727 | */ | |
728 | info->funcs = devm_kzalloc(info->dev, pin_data->nr_pins * | |
729 | sizeof(struct armada_37xx_pmx_func), GFP_KERNEL); | |
730 | if (!info->funcs) | |
731 | return -ENOMEM; | |
732 | ||
733 | ||
734 | ret = armada_37xx_fill_group(info); | |
735 | if (ret) | |
736 | return ret; | |
737 | ||
738 | ret = armada_37xx_fill_func(info); | |
739 | if (ret) | |
740 | return ret; | |
741 | ||
d2d92bd7 GC |
742 | ret = armada_37xx_gpiochip_register(dev, info); |
743 | if (ret) | |
744 | return ret; | |
745 | ||
08718066 GC |
746 | return 0; |
747 | } | |
748 | ||
1de76a45 RM |
749 | static int armada_37xx_pinctrl_bind(struct udevice *dev) |
750 | { | |
751 | /* | |
752 | * Make sure that the pinctrl driver gets probed after binding | |
753 | * as on A37XX the pinctrl driver is the one that is also | |
754 | * registering the GPIO one during probe, so if its not probed | |
755 | * GPIO-s are not registered as well. | |
756 | */ | |
757 | dev_or_flags(dev, DM_FLAG_PROBE_AFTER_BIND); | |
758 | ||
759 | return 0; | |
760 | } | |
761 | ||
08718066 GC |
762 | static const struct udevice_id armada_37xx_pinctrl_of_match[] = { |
763 | { | |
764 | .compatible = "marvell,armada3710-sb-pinctrl", | |
765 | .data = (ulong)&armada_37xx_pin_sb, | |
766 | }, | |
767 | { | |
768 | .compatible = "marvell,armada3710-nb-pinctrl", | |
769 | .data = (ulong)&armada_37xx_pin_nb, | |
770 | }, | |
771 | { /* sentinel */ } | |
772 | }; | |
773 | ||
774 | U_BOOT_DRIVER(armada_37xx_pinctrl) = { | |
775 | .name = "armada-37xx-pinctrl", | |
776 | .id = UCLASS_PINCTRL, | |
777 | .of_match = of_match_ptr(armada_37xx_pinctrl_of_match), | |
778 | .probe = armada_37xx_pinctrl_probe, | |
1de76a45 | 779 | .bind = armada_37xx_pinctrl_bind, |
41575d8e | 780 | .priv_auto = sizeof(struct armada_37xx_pinctrl), |
08718066 GC |
781 | .ops = &armada_37xx_pinctrl_ops, |
782 | }; |