]>
Commit | Line | Data |
---|---|---|
08718066 GC |
1 | /* |
2 | * U-Boot Marvell 37xx SoC pinctrl driver | |
3 | * | |
4 | * Copyright (C) 2017 Stefan Roese <sr@denx.de> | |
5 | * | |
6 | * This driver is based on the Linux driver version, which is: | |
7 | * Copyright (C) 2017 Marvell | |
8 | * Gregory CLEMENT <gregory.clement@free-electrons.com> | |
9 | * | |
10 | * Additionally parts are derived from the Meson U-Boot pinctrl driver, | |
11 | * which is: | |
12 | * (C) Copyright 2016 - Beniamino Galvani <b.galvani@gmail.com> | |
13 | * Based on code from Linux kernel: | |
14 | * Copyright (C) 2016 Endless Mobile, Inc. | |
15 | * | |
16 | * SPDX-License-Identifier: GPL-2.0+ | |
17 | * https://spdx.org/licenses | |
18 | */ | |
19 | ||
20 | #include <common.h> | |
21 | #include <config.h> | |
22 | #include <dm.h> | |
d2d92bd7 GC |
23 | #include <dm/device-internal.h> |
24 | #include <dm/lists.h> | |
08718066 GC |
25 | #include <dm/pinctrl.h> |
26 | #include <dm/root.h> | |
27 | #include <errno.h> | |
28 | #include <fdtdec.h> | |
29 | #include <regmap.h> | |
d2d92bd7 | 30 | #include <asm/gpio.h> |
08718066 GC |
31 | #include <asm/system.h> |
32 | #include <asm/io.h> | |
33 | ||
34 | DECLARE_GLOBAL_DATA_PTR; | |
35 | ||
36 | #define OUTPUT_EN 0x0 | |
d2d92bd7 GC |
37 | #define INPUT_VAL 0x10 |
38 | #define OUTPUT_VAL 0x18 | |
08718066 GC |
39 | #define OUTPUT_CTL 0x20 |
40 | #define SELECTION 0x30 | |
41 | ||
42 | #define IRQ_EN 0x0 | |
43 | #define IRQ_POL 0x08 | |
44 | #define IRQ_STATUS 0x10 | |
45 | #define IRQ_WKUP 0x18 | |
46 | ||
47 | #define NB_FUNCS 2 | |
48 | #define GPIO_PER_REG 32 | |
49 | ||
50 | /** | |
51 | * struct armada_37xx_pin_group: represents group of pins of a pinmux function. | |
52 | * The pins of a pinmux groups are composed of one or two groups of contiguous | |
53 | * pins. | |
54 | * @name: Name of the pin group, used to lookup the group. | |
55 | * @start_pins: Index of the first pin of the main range of pins belonging to | |
56 | * the group | |
57 | * @npins: Number of pins included in the first range | |
58 | * @reg_mask: Bit mask matching the group in the selection register | |
59 | * @extra_pins: Index of the first pin of the optional second range of pins | |
60 | * belonging to the group | |
61 | * @npins: Number of pins included in the second optional range | |
62 | * @funcs: A list of pinmux functions that can be selected for this group. | |
63 | * @pins: List of the pins included in the group | |
64 | */ | |
65 | struct armada_37xx_pin_group { | |
66 | const char *name; | |
67 | unsigned int start_pin; | |
68 | unsigned int npins; | |
69 | u32 reg_mask; | |
70 | u32 val[NB_FUNCS]; | |
71 | unsigned int extra_pin; | |
72 | unsigned int extra_npins; | |
73 | const char *funcs[NB_FUNCS]; | |
74 | unsigned int *pins; | |
75 | }; | |
76 | ||
77 | struct armada_37xx_pin_data { | |
78 | u8 nr_pins; | |
79 | char *name; | |
80 | struct armada_37xx_pin_group *groups; | |
81 | int ngroups; | |
82 | }; | |
83 | ||
84 | struct armada_37xx_pmx_func { | |
85 | const char *name; | |
86 | const char **groups; | |
87 | unsigned int ngroups; | |
88 | }; | |
89 | ||
90 | struct armada_37xx_pinctrl { | |
91 | void __iomem *base; | |
92 | const struct armada_37xx_pin_data *data; | |
93 | struct udevice *dev; | |
94 | struct pinctrl_dev *pctl_dev; | |
95 | struct armada_37xx_pin_group *groups; | |
96 | unsigned int ngroups; | |
97 | struct armada_37xx_pmx_func *funcs; | |
98 | unsigned int nfuncs; | |
99 | }; | |
100 | ||
101 | #define PIN_GRP(_name, _start, _nr, _mask, _func1, _func2) \ | |
102 | { \ | |
103 | .name = _name, \ | |
104 | .start_pin = _start, \ | |
105 | .npins = _nr, \ | |
106 | .reg_mask = _mask, \ | |
107 | .val = {0, _mask}, \ | |
108 | .funcs = {_func1, _func2} \ | |
109 | } | |
110 | ||
111 | #define PIN_GRP_GPIO(_name, _start, _nr, _mask, _func1) \ | |
112 | { \ | |
113 | .name = _name, \ | |
114 | .start_pin = _start, \ | |
115 | .npins = _nr, \ | |
116 | .reg_mask = _mask, \ | |
117 | .val = {0, _mask}, \ | |
118 | .funcs = {_func1, "gpio"} \ | |
119 | } | |
120 | ||
121 | #define PIN_GRP_GPIO_2(_name, _start, _nr, _mask, _val1, _val2, _func1) \ | |
122 | { \ | |
123 | .name = _name, \ | |
124 | .start_pin = _start, \ | |
125 | .npins = _nr, \ | |
126 | .reg_mask = _mask, \ | |
127 | .val = {_val1, _val2}, \ | |
128 | .funcs = {_func1, "gpio"} \ | |
129 | } | |
130 | ||
131 | #define PIN_GRP_EXTRA(_name, _start, _nr, _mask, _v1, _v2, _start2, _nr2, \ | |
132 | _f1, _f2) \ | |
133 | { \ | |
134 | .name = _name, \ | |
135 | .start_pin = _start, \ | |
136 | .npins = _nr, \ | |
137 | .reg_mask = _mask, \ | |
138 | .val = {_v1, _v2}, \ | |
139 | .extra_pin = _start2, \ | |
140 | .extra_npins = _nr2, \ | |
141 | .funcs = {_f1, _f2} \ | |
142 | } | |
143 | ||
144 | static struct armada_37xx_pin_group armada_37xx_nb_groups[] = { | |
145 | PIN_GRP_GPIO("jtag", 20, 5, BIT(0), "jtag"), | |
146 | PIN_GRP_GPIO("sdio0", 8, 3, BIT(1), "sdio"), | |
147 | PIN_GRP_GPIO("emmc_nb", 27, 9, BIT(2), "emmc"), | |
148 | PIN_GRP_GPIO("pwm0", 11, 1, BIT(3), "pwm"), | |
149 | PIN_GRP_GPIO("pwm1", 12, 1, BIT(4), "pwm"), | |
150 | PIN_GRP_GPIO("pwm2", 13, 1, BIT(5), "pwm"), | |
151 | PIN_GRP_GPIO("pwm3", 14, 1, BIT(6), "pwm"), | |
152 | PIN_GRP_GPIO("pmic1", 17, 1, BIT(7), "pmic"), | |
153 | PIN_GRP_GPIO("pmic0", 16, 1, BIT(8), "pmic"), | |
154 | PIN_GRP_GPIO("i2c2", 2, 2, BIT(9), "i2c"), | |
155 | PIN_GRP_GPIO("i2c1", 0, 2, BIT(10), "i2c"), | |
156 | PIN_GRP_GPIO("spi_cs1", 17, 1, BIT(12), "spi"), | |
157 | PIN_GRP_GPIO_2("spi_cs2", 18, 1, BIT(13) | BIT(19), 0, BIT(13), "spi"), | |
158 | PIN_GRP_GPIO_2("spi_cs3", 19, 1, BIT(14) | BIT(19), 0, BIT(14), "spi"), | |
159 | PIN_GRP_GPIO("onewire", 4, 1, BIT(16), "onewire"), | |
160 | PIN_GRP_GPIO("uart1", 25, 2, BIT(17), "uart"), | |
161 | PIN_GRP_GPIO("spi_quad", 15, 2, BIT(18), "spi"), | |
b5a6c94a KM |
162 | PIN_GRP_EXTRA("uart2", 9, 2, BIT(1) | BIT(13) | BIT(14) | BIT(19), |
163 | BIT(1) | BIT(13) | BIT(14), BIT(1) | BIT(19), | |
164 | 18, 2, "gpio", "uart"), | |
08718066 GC |
165 | PIN_GRP_GPIO("led0_od", 11, 1, BIT(20), "led"), |
166 | PIN_GRP_GPIO("led1_od", 12, 1, BIT(21), "led"), | |
167 | PIN_GRP_GPIO("led2_od", 13, 1, BIT(22), "led"), | |
168 | PIN_GRP_GPIO("led3_od", 14, 1, BIT(23), "led"), | |
169 | ||
170 | }; | |
171 | ||
172 | static struct armada_37xx_pin_group armada_37xx_sb_groups[] = { | |
173 | PIN_GRP_GPIO("usb32_drvvbus0", 0, 1, BIT(0), "drvbus"), | |
174 | PIN_GRP_GPIO("usb2_drvvbus1", 1, 1, BIT(1), "drvbus"), | |
175 | PIN_GRP_GPIO("sdio_sb", 24, 5, BIT(2), "sdio"), | |
176 | PIN_GRP_EXTRA("rgmii", 6, 14, BIT(3), 0, BIT(3), 23, 1, "mii", "gpio"), | |
177 | PIN_GRP_GPIO("pcie1", 3, 2, BIT(4), "pcie"), | |
178 | PIN_GRP_GPIO("ptp", 20, 3, BIT(5), "ptp"), | |
179 | PIN_GRP("ptp_clk", 21, 1, BIT(6), "ptp", "mii"), | |
180 | PIN_GRP("ptp_trig", 22, 1, BIT(7), "ptp", "mii"), | |
181 | PIN_GRP("mii_col", 23, 1, BIT(8), "mii", "mii_err"), | |
182 | }; | |
183 | ||
184 | const struct armada_37xx_pin_data armada_37xx_pin_nb = { | |
185 | .nr_pins = 36, | |
186 | .name = "GPIO1", | |
187 | .groups = armada_37xx_nb_groups, | |
188 | .ngroups = ARRAY_SIZE(armada_37xx_nb_groups), | |
189 | }; | |
190 | ||
191 | const struct armada_37xx_pin_data armada_37xx_pin_sb = { | |
192 | .nr_pins = 29, | |
193 | .name = "GPIO2", | |
194 | .groups = armada_37xx_sb_groups, | |
195 | .ngroups = ARRAY_SIZE(armada_37xx_sb_groups), | |
196 | }; | |
197 | ||
d2d92bd7 GC |
198 | static inline void armada_37xx_update_reg(unsigned int *reg, |
199 | unsigned int offset) | |
200 | { | |
201 | /* We never have more than 2 registers */ | |
202 | if (offset >= GPIO_PER_REG) { | |
203 | offset -= GPIO_PER_REG; | |
204 | *reg += sizeof(u32); | |
205 | } | |
206 | } | |
207 | ||
08718066 GC |
208 | static int armada_37xx_get_func_reg(struct armada_37xx_pin_group *grp, |
209 | const char *func) | |
210 | { | |
211 | int f; | |
212 | ||
213 | for (f = 0; f < NB_FUNCS; f++) | |
214 | if (!strcmp(grp->funcs[f], func)) | |
215 | return f; | |
216 | ||
217 | return -ENOTSUPP; | |
218 | } | |
219 | ||
220 | static int armada_37xx_pmx_get_groups_count(struct udevice *dev) | |
221 | { | |
222 | struct armada_37xx_pinctrl *info = dev_get_priv(dev); | |
223 | ||
224 | return info->ngroups; | |
225 | } | |
226 | ||
227 | static const char *armada_37xx_pmx_dummy_name = "_dummy"; | |
228 | ||
229 | static const char *armada_37xx_pmx_get_group_name(struct udevice *dev, | |
230 | unsigned selector) | |
231 | { | |
232 | struct armada_37xx_pinctrl *info = dev_get_priv(dev); | |
233 | ||
234 | if (!info->groups[selector].name) | |
235 | return armada_37xx_pmx_dummy_name; | |
236 | ||
237 | return info->groups[selector].name; | |
238 | } | |
239 | ||
240 | static int armada_37xx_pmx_get_funcs_count(struct udevice *dev) | |
241 | { | |
242 | struct armada_37xx_pinctrl *info = dev_get_priv(dev); | |
243 | ||
244 | return info->nfuncs; | |
245 | } | |
246 | ||
247 | static const char *armada_37xx_pmx_get_func_name(struct udevice *dev, | |
248 | unsigned selector) | |
249 | { | |
250 | struct armada_37xx_pinctrl *info = dev_get_priv(dev); | |
251 | ||
252 | return info->funcs[selector].name; | |
253 | } | |
254 | ||
255 | static int armada_37xx_pmx_set_by_name(struct udevice *dev, | |
256 | const char *name, | |
257 | struct armada_37xx_pin_group *grp) | |
258 | { | |
259 | struct armada_37xx_pinctrl *info = dev_get_priv(dev); | |
260 | unsigned int reg = SELECTION; | |
261 | unsigned int mask = grp->reg_mask; | |
262 | int func, val; | |
263 | ||
264 | dev_dbg(info->dev, "enable function %s group %s\n", | |
265 | name, grp->name); | |
266 | ||
267 | func = armada_37xx_get_func_reg(grp, name); | |
268 | ||
269 | if (func < 0) | |
270 | return func; | |
271 | ||
272 | val = grp->val[func]; | |
273 | ||
274 | clrsetbits_le32(info->base + reg, mask, val); | |
275 | ||
276 | return 0; | |
277 | } | |
278 | ||
279 | static int armada_37xx_pmx_group_set(struct udevice *dev, | |
280 | unsigned group_selector, | |
281 | unsigned func_selector) | |
282 | { | |
283 | struct armada_37xx_pinctrl *info = dev_get_priv(dev); | |
284 | struct armada_37xx_pin_group *grp = &info->groups[group_selector]; | |
285 | const char *name = info->funcs[func_selector].name; | |
286 | ||
287 | return armada_37xx_pmx_set_by_name(dev, name, grp); | |
288 | } | |
289 | ||
290 | /** | |
291 | * armada_37xx_add_function() - Add a new function to the list | |
292 | * @funcs: array of function to add the new one | |
293 | * @funcsize: size of the remaining space for the function | |
294 | * @name: name of the function to add | |
295 | * | |
296 | * If it is a new function then create it by adding its name else | |
297 | * increment the number of group associated to this function. | |
298 | */ | |
299 | static int armada_37xx_add_function(struct armada_37xx_pmx_func *funcs, | |
300 | int *funcsize, const char *name) | |
301 | { | |
302 | int i = 0; | |
303 | ||
304 | if (*funcsize <= 0) | |
305 | return -EOVERFLOW; | |
306 | ||
307 | while (funcs->ngroups) { | |
308 | /* function already there */ | |
309 | if (strcmp(funcs->name, name) == 0) { | |
310 | funcs->ngroups++; | |
311 | ||
312 | return -EEXIST; | |
313 | } | |
314 | funcs++; | |
315 | i++; | |
316 | } | |
317 | ||
318 | /* append new unique function */ | |
319 | funcs->name = name; | |
320 | funcs->ngroups = 1; | |
321 | (*funcsize)--; | |
322 | ||
323 | return 0; | |
324 | } | |
325 | ||
326 | /** | |
327 | * armada_37xx_fill_group() - complete the group array | |
328 | * @info: info driver instance | |
329 | * | |
330 | * Based on the data available from the armada_37xx_pin_group array | |
331 | * completes the last member of the struct for each function: the list | |
332 | * of the groups associated to this function. | |
333 | * | |
334 | */ | |
335 | static int armada_37xx_fill_group(struct armada_37xx_pinctrl *info) | |
336 | { | |
337 | int n, num = 0, funcsize = info->data->nr_pins; | |
338 | ||
339 | for (n = 0; n < info->ngroups; n++) { | |
340 | struct armada_37xx_pin_group *grp = &info->groups[n]; | |
341 | int i, j, f; | |
342 | ||
343 | grp->pins = devm_kzalloc(info->dev, | |
344 | (grp->npins + grp->extra_npins) * | |
345 | sizeof(*grp->pins), GFP_KERNEL); | |
346 | if (!grp->pins) | |
347 | return -ENOMEM; | |
348 | ||
349 | for (i = 0; i < grp->npins; i++) | |
350 | grp->pins[i] = grp->start_pin + i; | |
351 | ||
352 | for (j = 0; j < grp->extra_npins; j++) | |
353 | grp->pins[i+j] = grp->extra_pin + j; | |
354 | ||
355 | for (f = 0; f < NB_FUNCS; f++) { | |
356 | int ret; | |
357 | /* check for unique functions and count groups */ | |
358 | ret = armada_37xx_add_function(info->funcs, &funcsize, | |
359 | grp->funcs[f]); | |
360 | if (ret == -EOVERFLOW) | |
361 | dev_err(info->dev, | |
362 | "More functions than pins(%d)\n", | |
363 | info->data->nr_pins); | |
364 | if (ret < 0) | |
365 | continue; | |
366 | num++; | |
367 | } | |
368 | } | |
369 | ||
370 | info->nfuncs = num; | |
371 | ||
372 | return 0; | |
373 | } | |
374 | ||
375 | /** | |
376 | * armada_37xx_fill_funcs() - complete the funcs array | |
377 | * @info: info driver instance | |
378 | * | |
379 | * Based on the data available from the armada_37xx_pin_group array | |
380 | * completes the last two member of the struct for each group: | |
381 | * - the list of the pins included in the group | |
382 | * - the list of pinmux functions that can be selected for this group | |
383 | * | |
384 | */ | |
385 | static int armada_37xx_fill_func(struct armada_37xx_pinctrl *info) | |
386 | { | |
387 | struct armada_37xx_pmx_func *funcs = info->funcs; | |
388 | int n; | |
389 | ||
390 | for (n = 0; n < info->nfuncs; n++) { | |
391 | const char *name = funcs[n].name; | |
392 | const char **groups; | |
393 | int g; | |
394 | ||
395 | funcs[n].groups = devm_kzalloc(info->dev, funcs[n].ngroups * | |
396 | sizeof(*(funcs[n].groups)), | |
397 | GFP_KERNEL); | |
398 | if (!funcs[n].groups) | |
399 | return -ENOMEM; | |
400 | ||
401 | groups = funcs[n].groups; | |
402 | ||
403 | for (g = 0; g < info->ngroups; g++) { | |
404 | struct armada_37xx_pin_group *gp = &info->groups[g]; | |
405 | int f; | |
406 | ||
407 | for (f = 0; f < NB_FUNCS; f++) { | |
408 | if (strcmp(gp->funcs[f], name) == 0) { | |
409 | *groups = gp->name; | |
410 | groups++; | |
411 | } | |
412 | } | |
413 | } | |
414 | } | |
415 | return 0; | |
416 | } | |
417 | ||
d2d92bd7 GC |
418 | static int armada_37xx_gpio_get(struct udevice *dev, unsigned int offset) |
419 | { | |
420 | struct armada_37xx_pinctrl *info = dev_get_priv(dev->parent); | |
421 | unsigned int reg = INPUT_VAL; | |
422 | unsigned int val, mask; | |
423 | ||
424 | armada_37xx_update_reg(®, offset); | |
425 | mask = BIT(offset); | |
426 | ||
427 | val = readl(info->base + reg); | |
428 | ||
429 | return (val & mask) != 0; | |
430 | } | |
431 | ||
432 | static int armada_37xx_gpio_set(struct udevice *dev, unsigned int offset, | |
433 | int value) | |
434 | { | |
435 | struct armada_37xx_pinctrl *info = dev_get_priv(dev->parent); | |
436 | unsigned int reg = OUTPUT_VAL; | |
437 | unsigned int mask, val; | |
438 | ||
439 | armada_37xx_update_reg(®, offset); | |
440 | mask = BIT(offset); | |
441 | val = value ? mask : 0; | |
442 | ||
443 | clrsetbits_le32(info->base + reg, mask, val); | |
444 | ||
445 | return 0; | |
446 | } | |
447 | ||
448 | static int armada_37xx_gpio_get_direction(struct udevice *dev, | |
449 | unsigned int offset) | |
450 | { | |
451 | struct armada_37xx_pinctrl *info = dev_get_priv(dev->parent); | |
452 | unsigned int reg = OUTPUT_EN; | |
453 | unsigned int val, mask; | |
454 | ||
455 | armada_37xx_update_reg(®, offset); | |
456 | mask = BIT(offset); | |
457 | val = readl(info->base + reg); | |
458 | ||
459 | if (val & mask) | |
460 | return GPIOF_OUTPUT; | |
461 | else | |
462 | return GPIOF_INPUT; | |
463 | } | |
464 | ||
465 | static int armada_37xx_gpio_direction_input(struct udevice *dev, | |
466 | unsigned int offset) | |
467 | { | |
468 | struct armada_37xx_pinctrl *info = dev_get_priv(dev->parent); | |
469 | unsigned int reg = OUTPUT_EN; | |
470 | unsigned int mask; | |
471 | ||
472 | armada_37xx_update_reg(®, offset); | |
473 | mask = BIT(offset); | |
474 | ||
475 | clrbits_le32(info->base + reg, mask); | |
476 | ||
477 | return 0; | |
478 | } | |
479 | ||
480 | static int armada_37xx_gpio_direction_output(struct udevice *dev, | |
481 | unsigned int offset, int value) | |
482 | { | |
483 | struct armada_37xx_pinctrl *info = dev_get_priv(dev->parent); | |
484 | unsigned int reg = OUTPUT_EN; | |
485 | unsigned int mask; | |
486 | ||
487 | armada_37xx_update_reg(®, offset); | |
488 | mask = BIT(offset); | |
489 | ||
490 | setbits_le32(info->base + reg, mask); | |
491 | ||
492 | /* And set the requested value */ | |
493 | return armada_37xx_gpio_set(dev, offset, value); | |
494 | } | |
495 | ||
496 | static int armada_37xx_gpio_probe(struct udevice *dev) | |
497 | { | |
498 | struct armada_37xx_pinctrl *info = dev_get_priv(dev->parent); | |
499 | struct gpio_dev_priv *uc_priv; | |
500 | ||
501 | uc_priv = dev_get_uclass_priv(dev); | |
502 | uc_priv->bank_name = info->data->name; | |
503 | uc_priv->gpio_count = info->data->nr_pins; | |
504 | ||
505 | return 0; | |
506 | } | |
507 | ||
508 | static const struct dm_gpio_ops armada_37xx_gpio_ops = { | |
509 | .set_value = armada_37xx_gpio_set, | |
510 | .get_value = armada_37xx_gpio_get, | |
511 | .get_function = armada_37xx_gpio_get_direction, | |
512 | .direction_input = armada_37xx_gpio_direction_input, | |
513 | .direction_output = armada_37xx_gpio_direction_output, | |
514 | }; | |
515 | ||
516 | static struct driver armada_37xx_gpio_driver = { | |
517 | .name = "armada-37xx-gpio", | |
518 | .id = UCLASS_GPIO, | |
519 | .probe = armada_37xx_gpio_probe, | |
520 | .ops = &armada_37xx_gpio_ops, | |
521 | }; | |
522 | ||
523 | static int armada_37xx_gpiochip_register(struct udevice *parent, | |
524 | struct armada_37xx_pinctrl *info) | |
525 | { | |
526 | const void *blob = gd->fdt_blob; | |
527 | int node = dev_of_offset(parent); | |
528 | struct uclass_driver *drv; | |
529 | struct udevice *dev; | |
530 | int ret = -ENODEV; | |
531 | int subnode; | |
532 | char *name; | |
533 | ||
534 | /* Lookup GPIO driver */ | |
535 | drv = lists_uclass_lookup(UCLASS_GPIO); | |
536 | if (!drv) { | |
537 | puts("Cannot find GPIO driver\n"); | |
538 | return -ENOENT; | |
539 | } | |
540 | ||
541 | fdt_for_each_subnode(subnode, blob, node) { | |
ae118b68 | 542 | if (fdtdec_get_bool(blob, subnode, "gpio-controller")) { |
d2d92bd7 GC |
543 | ret = 0; |
544 | break; | |
545 | } | |
546 | }; | |
547 | if (ret) | |
548 | return ret; | |
549 | ||
550 | name = calloc(1, 32); | |
551 | sprintf(name, "armada-37xx-gpio"); | |
552 | ||
553 | /* Create child device UCLASS_GPIO and bind it */ | |
554 | device_bind(parent, &armada_37xx_gpio_driver, name, NULL, subnode, | |
555 | &dev); | |
556 | dev_set_of_offset(dev, subnode); | |
557 | ||
558 | return 0; | |
559 | } | |
560 | ||
08718066 GC |
561 | const struct pinctrl_ops armada_37xx_pinctrl_ops = { |
562 | .get_groups_count = armada_37xx_pmx_get_groups_count, | |
563 | .get_group_name = armada_37xx_pmx_get_group_name, | |
564 | .get_functions_count = armada_37xx_pmx_get_funcs_count, | |
565 | .get_function_name = armada_37xx_pmx_get_func_name, | |
566 | .pinmux_group_set = armada_37xx_pmx_group_set, | |
567 | .set_state = pinctrl_generic_set_state, | |
568 | }; | |
569 | ||
570 | int armada_37xx_pinctrl_probe(struct udevice *dev) | |
571 | { | |
572 | struct armada_37xx_pinctrl *info = dev_get_priv(dev); | |
573 | const struct armada_37xx_pin_data *pin_data; | |
574 | int ret; | |
575 | ||
576 | info->data = (struct armada_37xx_pin_data *)dev_get_driver_data(dev); | |
577 | pin_data = info->data; | |
578 | ||
a821c4af | 579 | info->base = (void __iomem *)devfdt_get_addr(dev); |
08718066 | 580 | if (!info->base) { |
9b643e31 | 581 | pr_err("unable to find regmap\n"); |
08718066 GC |
582 | return -ENODEV; |
583 | } | |
584 | ||
585 | info->groups = pin_data->groups; | |
586 | info->ngroups = pin_data->ngroups; | |
587 | ||
588 | /* | |
589 | * we allocate functions for number of pins and hope there are | |
590 | * fewer unique functions than pins available | |
591 | */ | |
592 | info->funcs = devm_kzalloc(info->dev, pin_data->nr_pins * | |
593 | sizeof(struct armada_37xx_pmx_func), GFP_KERNEL); | |
594 | if (!info->funcs) | |
595 | return -ENOMEM; | |
596 | ||
597 | ||
598 | ret = armada_37xx_fill_group(info); | |
599 | if (ret) | |
600 | return ret; | |
601 | ||
602 | ret = armada_37xx_fill_func(info); | |
603 | if (ret) | |
604 | return ret; | |
605 | ||
d2d92bd7 GC |
606 | ret = armada_37xx_gpiochip_register(dev, info); |
607 | if (ret) | |
608 | return ret; | |
609 | ||
08718066 GC |
610 | return 0; |
611 | } | |
612 | ||
613 | static const struct udevice_id armada_37xx_pinctrl_of_match[] = { | |
614 | { | |
615 | .compatible = "marvell,armada3710-sb-pinctrl", | |
616 | .data = (ulong)&armada_37xx_pin_sb, | |
617 | }, | |
618 | { | |
619 | .compatible = "marvell,armada3710-nb-pinctrl", | |
620 | .data = (ulong)&armada_37xx_pin_nb, | |
621 | }, | |
622 | { /* sentinel */ } | |
623 | }; | |
624 | ||
625 | U_BOOT_DRIVER(armada_37xx_pinctrl) = { | |
626 | .name = "armada-37xx-pinctrl", | |
627 | .id = UCLASS_PINCTRL, | |
628 | .of_match = of_match_ptr(armada_37xx_pinctrl_of_match), | |
629 | .probe = armada_37xx_pinctrl_probe, | |
630 | .priv_auto_alloc_size = sizeof(struct armada_37xx_pinctrl), | |
631 | .ops = &armada_37xx_pinctrl_ops, | |
632 | }; |