]>
Commit | Line | Data |
---|---|---|
83d290c5 | 1 | // SPDX-License-Identifier: GPL-2.0+ |
44d5c371 FB |
2 | /* |
3 | * Copyright (C) EETS GmbH, 2017, Felix Brack <[email protected]> | |
76d470de | 4 | * Copyright (C) 2021 Dario Binacchi <[email protected]> |
44d5c371 FB |
5 | */ |
6 | ||
7f18fb8a | 7 | #include <mapmem.h> |
9d922450 | 8 | #include <dm.h> |
336d4615 | 9 | #include <dm/device_compat.h> |
76d470de | 10 | #include <dm/devres.h> |
62f86c6a | 11 | #include <dm/of_access.h> |
44d5c371 | 12 | #include <dm/pinctrl.h> |
b08c8c48 | 13 | #include <linux/libfdt.h> |
76d470de | 14 | #include <linux/list.h> |
44d5c371 | 15 | #include <asm/io.h> |
76d470de | 16 | #include <sort.h> |
44d5c371 | 17 | |
4ace4fa6 DB |
18 | /** |
19 | * struct single_pdata - platform data | |
20 | * @base: first configuration register | |
21 | * @offset: index of last configuration register | |
22 | * @mask: configuration-value mask bits | |
23 | * @width: configuration register bit width | |
24 | * @bits_per_mux: true if one register controls more than one pin | |
25 | */ | |
44d5c371 | 26 | struct single_pdata { |
7f18fb8a | 27 | void *base; |
4ace4fa6 DB |
28 | int offset; |
29 | u32 mask; | |
971c64a4 | 30 | u32 width; |
1041eae4 | 31 | u32 args_count; |
159a887e | 32 | bool bits_per_mux; |
44d5c371 FB |
33 | }; |
34 | ||
76d470de DB |
35 | /** |
36 | * struct single_func - pinctrl function | |
37 | * @node: list node | |
38 | * @name: pinctrl function name | |
39 | * @npins: number of entries in pins array | |
40 | * @pins: pins array | |
41 | */ | |
42 | struct single_func { | |
43 | struct list_head node; | |
44 | const char *name; | |
45 | unsigned int npins; | |
46 | unsigned int *pins; | |
47 | }; | |
48 | ||
62f86c6a BG |
49 | /** |
50 | * struct single_gpiofunc_range - pin ranges with same mux value of gpio fun | |
51 | * @offset: offset base of pins | |
52 | * @npins: number pins with the same mux value of gpio function | |
53 | * @gpiofunc: mux value of gpio function | |
54 | * @node: list node | |
55 | */ | |
56 | struct single_gpiofunc_range { | |
57 | u32 offset; | |
58 | u32 npins; | |
59 | u32 gpiofunc; | |
60 | struct list_head node; | |
61 | }; | |
62 | ||
1dd7ae20 DB |
63 | /** |
64 | * struct single_priv - private data | |
65 | * @bits_per_pin: number of bits per pin | |
66 | * @npins: number of selectable pins | |
0b121629 | 67 | * @pin_name: temporary buffer to store the pin name |
62f86c6a BG |
68 | * @functions: list pin functions |
69 | * @gpiofuncs: list gpio functions | |
1dd7ae20 DB |
70 | */ |
71 | struct single_priv { | |
5532262d DB |
72 | #if (IS_ENABLED(CONFIG_SANDBOX)) |
73 | u32 *sandbox_regs; | |
74 | #endif | |
1dd7ae20 DB |
75 | unsigned int bits_per_pin; |
76 | unsigned int npins; | |
0b121629 | 77 | char pin_name[PINNAME_SIZE]; |
76d470de | 78 | struct list_head functions; |
62f86c6a | 79 | struct list_head gpiofuncs; |
1dd7ae20 DB |
80 | }; |
81 | ||
4ace4fa6 DB |
82 | /** |
83 | * struct single_fdt_bits_cfg - pin configuration | |
84 | * | |
85 | * This structure is used for the pin configuration parameters in case | |
86 | * the register controls more than one pin. | |
87 | * | |
88 | * @reg: configuration register offset | |
89 | * @val: configuration register value | |
90 | * @mask: configuration register mask | |
91 | */ | |
159a887e | 92 | struct single_fdt_bits_cfg { |
4ace4fa6 DB |
93 | fdt32_t reg; |
94 | fdt32_t val; | |
95 | fdt32_t mask; | |
159a887e AF |
96 | }; |
97 | ||
5532262d DB |
98 | #if (!IS_ENABLED(CONFIG_SANDBOX)) |
99 | ||
7f18fb8a | 100 | static unsigned int single_read(struct udevice *dev, void *reg) |
180531fc DB |
101 | { |
102 | struct single_pdata *pdata = dev_get_plat(dev); | |
103 | ||
104 | switch (pdata->width) { | |
105 | case 8: | |
106 | return readb(reg); | |
107 | case 16: | |
108 | return readw(reg); | |
109 | default: /* 32 bits */ | |
110 | return readl(reg); | |
111 | } | |
112 | ||
113 | return readb(reg); | |
114 | } | |
115 | ||
7f18fb8a | 116 | static void single_write(struct udevice *dev, unsigned int val, void *reg) |
180531fc DB |
117 | { |
118 | struct single_pdata *pdata = dev_get_plat(dev); | |
119 | ||
120 | switch (pdata->width) { | |
121 | case 8: | |
122 | writeb(val, reg); | |
123 | break; | |
124 | case 16: | |
125 | writew(val, reg); | |
126 | break; | |
127 | default: /* 32 bits */ | |
128 | writel(val, reg); | |
129 | } | |
130 | } | |
131 | ||
5532262d DB |
132 | #else /* CONFIG_SANDBOX */ |
133 | ||
7f18fb8a | 134 | static unsigned int single_read(struct udevice *dev, void *reg) |
5532262d DB |
135 | { |
136 | struct single_priv *priv = dev_get_priv(dev); | |
137 | ||
7f18fb8a | 138 | return priv->sandbox_regs[map_to_sysmem(reg)]; |
5532262d DB |
139 | } |
140 | ||
7f18fb8a | 141 | static void single_write(struct udevice *dev, unsigned int val, void *reg) |
5532262d DB |
142 | { |
143 | struct single_priv *priv = dev_get_priv(dev); | |
144 | ||
7f18fb8a | 145 | priv->sandbox_regs[map_to_sysmem(reg)] = val; |
5532262d DB |
146 | } |
147 | ||
148 | #endif /* CONFIG_SANDBOX */ | |
149 | ||
76d470de DB |
150 | /** |
151 | * single_get_pin_by_offset() - get a pin based on the register offset | |
152 | * @dev: single driver instance | |
153 | * @offset: register offset from the base | |
154 | */ | |
155 | static int single_get_pin_by_offset(struct udevice *dev, unsigned int offset) | |
156 | { | |
157 | struct single_pdata *pdata = dev_get_plat(dev); | |
158 | struct single_priv *priv = dev_get_priv(dev); | |
159 | ||
160 | if (offset > pdata->offset) { | |
161 | dev_err(dev, "mux offset out of range: 0x%x (0x%x)\n", | |
162 | offset, pdata->offset); | |
163 | return -EINVAL; | |
164 | } | |
165 | ||
166 | if (pdata->bits_per_mux) | |
167 | return (offset * BITS_PER_BYTE) / priv->bits_per_pin; | |
168 | ||
169 | return offset / (pdata->width / BITS_PER_BYTE); | |
170 | } | |
171 | ||
172 | static int single_get_offset_by_pin(struct udevice *dev, unsigned int pin) | |
173 | { | |
174 | struct single_pdata *pdata = dev_get_plat(dev); | |
175 | struct single_priv *priv = dev_get_priv(dev); | |
176 | unsigned int mux_bytes; | |
177 | ||
178 | if (pin >= priv->npins) | |
179 | return -EINVAL; | |
180 | ||
181 | mux_bytes = pdata->width / BITS_PER_BYTE; | |
182 | if (pdata->bits_per_mux) { | |
183 | int byte_num; | |
184 | ||
185 | byte_num = (priv->bits_per_pin * pin) / BITS_PER_BYTE; | |
186 | return (byte_num / mux_bytes) * mux_bytes; | |
187 | } | |
188 | ||
189 | return pin * mux_bytes; | |
190 | } | |
191 | ||
192 | static const char *single_get_pin_function(struct udevice *dev, | |
193 | unsigned int pin) | |
194 | { | |
195 | struct single_priv *priv = dev_get_priv(dev); | |
196 | struct single_func *func; | |
197 | int i; | |
198 | ||
199 | list_for_each_entry(func, &priv->functions, node) { | |
200 | for (i = 0; i < func->npins; i++) { | |
201 | if (pin == func->pins[i]) | |
202 | return func->name; | |
203 | ||
204 | if (pin < func->pins[i]) | |
205 | break; | |
206 | } | |
207 | } | |
208 | ||
209 | return NULL; | |
210 | } | |
211 | ||
212 | static int single_get_pin_muxing(struct udevice *dev, unsigned int pin, | |
213 | char *buf, int size) | |
214 | { | |
215 | struct single_pdata *pdata = dev_get_plat(dev); | |
216 | struct single_priv *priv = dev_get_priv(dev); | |
7f18fb8a MS |
217 | phys_addr_t phys_reg; |
218 | void *reg; | |
76d470de DB |
219 | const char *fname; |
220 | unsigned int val; | |
221 | int offset, pin_shift = 0; | |
222 | ||
223 | offset = single_get_offset_by_pin(dev, pin); | |
224 | if (offset < 0) | |
225 | return offset; | |
226 | ||
227 | reg = pdata->base + offset; | |
228 | val = single_read(dev, reg); | |
229 | ||
7f18fb8a MS |
230 | phys_reg = map_to_sysmem(reg); |
231 | ||
76d470de DB |
232 | if (pdata->bits_per_mux) |
233 | pin_shift = pin % (pdata->width / priv->bits_per_pin) * | |
234 | priv->bits_per_pin; | |
235 | ||
236 | val &= (pdata->mask << pin_shift); | |
237 | fname = single_get_pin_function(dev, pin); | |
7f18fb8a | 238 | snprintf(buf, size, "%pa 0x%08x %s", &phys_reg, val, |
76d470de DB |
239 | fname ? fname : "UNCLAIMED"); |
240 | return 0; | |
241 | } | |
242 | ||
fd921d20 BG |
243 | static int single_request(struct udevice *dev, int pin, int flags) |
244 | { | |
245 | struct single_priv *priv = dev_get_priv(dev); | |
246 | struct single_pdata *pdata = dev_get_plat(dev); | |
247 | struct single_gpiofunc_range *frange = NULL; | |
248 | struct list_head *pos, *tmp; | |
7f18fb8a | 249 | void *reg; |
fd921d20 BG |
250 | int mux_bytes = 0; |
251 | u32 data; | |
252 | ||
253 | /* If function mask is null, needn't enable it. */ | |
254 | if (!pdata->mask) | |
255 | return -ENOTSUPP; | |
256 | ||
257 | list_for_each_safe(pos, tmp, &priv->gpiofuncs) { | |
258 | frange = list_entry(pos, struct single_gpiofunc_range, node); | |
259 | if ((pin >= frange->offset + frange->npins) || | |
260 | pin < frange->offset) | |
261 | continue; | |
262 | ||
263 | mux_bytes = pdata->width / BITS_PER_BYTE; | |
264 | reg = pdata->base + pin * mux_bytes; | |
265 | ||
266 | data = single_read(dev, reg); | |
267 | data &= ~pdata->mask; | |
268 | data |= frange->gpiofunc; | |
269 | single_write(dev, data, reg); | |
270 | break; | |
271 | } | |
272 | ||
273 | return 0; | |
274 | } | |
275 | ||
76d470de DB |
276 | static struct single_func *single_allocate_function(struct udevice *dev, |
277 | unsigned int group_pins) | |
278 | { | |
279 | struct single_func *func; | |
280 | ||
281 | func = devm_kmalloc(dev, sizeof(*func), GFP_KERNEL); | |
282 | if (!func) | |
283 | return ERR_PTR(-ENOMEM); | |
284 | ||
285 | func->pins = devm_kmalloc(dev, sizeof(unsigned int) * group_pins, | |
286 | GFP_KERNEL); | |
287 | if (!func->pins) | |
288 | return ERR_PTR(-ENOMEM); | |
289 | ||
290 | return func; | |
291 | } | |
292 | ||
293 | static int single_pin_compare(const void *s1, const void *s2) | |
294 | { | |
295 | int pin1 = *(const unsigned int *)s1; | |
296 | int pin2 = *(const unsigned int *)s2; | |
297 | ||
298 | return pin1 - pin2; | |
299 | } | |
300 | ||
44d5c371 FB |
301 | /** |
302 | * single_configure_pins() - Configure pins based on FDT data | |
303 | * | |
304 | * @dev: Pointer to single pin configuration device which is the parent of | |
305 | * the pins node holding the pin configuration data. | |
306 | * @pins: Pointer to the first element of an array of register/value pairs | |
1041eae4 AB |
307 | * of type 'u32'. Each such pair describes the pin to be configured |
308 | * and the value to be used for configuration. | |
309 | * The value can either be a simple value if #pinctrl-cells = 1 | |
310 | * or a configuration value and a pin mux mode value if it is 2 | |
44d5c371 FB |
311 | * This pointer points to a 'pinctrl-single,pins' property in the |
312 | * device-tree. | |
313 | * @size: Size of the 'pins' array in bytes. | |
1041eae4 AB |
314 | * The number of cells in the array therefore equals to |
315 | * 'size / sizeof(u32)'. | |
76d470de | 316 | * @fname: Function name. |
44d5c371 FB |
317 | */ |
318 | static int single_configure_pins(struct udevice *dev, | |
1041eae4 | 319 | const u32 *pins, |
76d470de | 320 | int size, const char *fname) |
44d5c371 | 321 | { |
0fd3d911 | 322 | struct single_pdata *pdata = dev_get_plat(dev); |
76d470de | 323 | struct single_priv *priv = dev_get_priv(dev); |
1041eae4 AB |
324 | int stride = pdata->args_count + 1; |
325 | int n, pin, count = size / sizeof(u32); | |
76d470de | 326 | struct single_func *func; |
7f18fb8a | 327 | void *reg; |
1041eae4 | 328 | u32 offset, val, mux; |
44d5c371 | 329 | |
d85b93e8 DB |
330 | /* If function mask is null, needn't enable it. */ |
331 | if (!pdata->mask) | |
332 | return 0; | |
333 | ||
76d470de DB |
334 | func = single_allocate_function(dev, count); |
335 | if (IS_ERR(func)) | |
336 | return PTR_ERR(func); | |
337 | ||
338 | func->name = fname; | |
339 | func->npins = 0; | |
1041eae4 AB |
340 | for (n = 0; n < count; n += stride) { |
341 | offset = fdt32_to_cpu(pins[n]); | |
230bc623 | 342 | if (offset > pdata->offset) { |
76d470de | 343 | dev_err(dev, " invalid register offset 0x%x\n", |
9b884e79 | 344 | offset); |
44d5c371 FB |
345 | continue; |
346 | } | |
9b884e79 | 347 | |
1041eae4 AB |
348 | /* if the pinctrl-cells is 2 then the second cell contains the mux */ |
349 | if (stride == 3) | |
350 | mux = fdt32_to_cpu(pins[n + 2]); | |
351 | else | |
352 | mux = 0; | |
353 | ||
9b884e79 | 354 | reg = pdata->base + offset; |
1041eae4 | 355 | val = (fdt32_to_cpu(pins[n + 1]) | mux) & pdata->mask; |
76d470de DB |
356 | pin = single_get_pin_by_offset(dev, offset); |
357 | if (pin < 0) { | |
358 | dev_err(dev, " failed to get pin by offset %x\n", | |
359 | offset); | |
360 | continue; | |
361 | } | |
362 | ||
180531fc DB |
363 | single_write(dev, (single_read(dev, reg) & ~pdata->mask) | val, |
364 | reg); | |
fcf6a2b3 | 365 | dev_dbg(dev, " reg/val %pa/0x%08x\n", ®, val); |
76d470de DB |
366 | func->pins[func->npins] = pin; |
367 | func->npins++; | |
44d5c371 | 368 | } |
76d470de DB |
369 | |
370 | qsort(func->pins, func->npins, sizeof(func->pins[0]), | |
371 | single_pin_compare); | |
372 | list_add(&func->node, &priv->functions); | |
44d5c371 FB |
373 | return 0; |
374 | } | |
375 | ||
159a887e AF |
376 | static int single_configure_bits(struct udevice *dev, |
377 | const struct single_fdt_bits_cfg *pins, | |
76d470de | 378 | int size, const char *fname) |
159a887e | 379 | { |
0fd3d911 | 380 | struct single_pdata *pdata = dev_get_plat(dev); |
76d470de DB |
381 | struct single_priv *priv = dev_get_priv(dev); |
382 | int n, pin, count = size / sizeof(struct single_fdt_bits_cfg); | |
383 | int npins_in_reg, pin_num_from_lsb; | |
384 | struct single_func *func; | |
7f18fb8a | 385 | void *reg; |
76d470de DB |
386 | u32 offset, val, mask, bit_pos, val_pos, mask_pos, submask; |
387 | ||
69414d86 DB |
388 | /* If function mask is null, needn't enable it. */ |
389 | if (!pdata->mask) | |
390 | return 0; | |
391 | ||
76d470de DB |
392 | npins_in_reg = pdata->width / priv->bits_per_pin; |
393 | func = single_allocate_function(dev, count * npins_in_reg); | |
394 | if (IS_ERR(func)) | |
395 | return PTR_ERR(func); | |
159a887e | 396 | |
76d470de DB |
397 | func->name = fname; |
398 | func->npins = 0; | |
159a887e | 399 | for (n = 0; n < count; n++, pins++) { |
9b884e79 | 400 | offset = fdt32_to_cpu(pins->reg); |
230bc623 | 401 | if (offset > pdata->offset) { |
9b884e79 DB |
402 | dev_dbg(dev, " invalid register offset 0x%x\n", |
403 | offset); | |
159a887e AF |
404 | continue; |
405 | } | |
9b884e79 DB |
406 | |
407 | reg = pdata->base + offset; | |
159a887e | 408 | |
76d470de DB |
409 | pin = single_get_pin_by_offset(dev, offset); |
410 | if (pin < 0) { | |
411 | dev_err(dev, " failed to get pin by offset 0x%pa\n", | |
412 | ®); | |
413 | continue; | |
414 | } | |
415 | ||
159a887e AF |
416 | mask = fdt32_to_cpu(pins->mask); |
417 | val = fdt32_to_cpu(pins->val) & mask; | |
180531fc | 418 | single_write(dev, (single_read(dev, reg) & ~mask) | val, reg); |
fcf6a2b3 | 419 | dev_dbg(dev, " reg/val %pa/0x%08x\n", ®, val); |
76d470de DB |
420 | |
421 | while (mask) { | |
422 | bit_pos = __ffs(mask); | |
423 | pin_num_from_lsb = bit_pos / priv->bits_per_pin; | |
424 | mask_pos = pdata->mask << bit_pos; | |
425 | val_pos = val & mask_pos; | |
426 | submask = mask & mask_pos; | |
427 | ||
428 | if ((mask & mask_pos) == 0) { | |
429 | dev_err(dev, "Invalid mask at 0x%x\n", offset); | |
430 | break; | |
431 | } | |
432 | ||
433 | mask &= ~mask_pos; | |
434 | ||
435 | if (submask != mask_pos) { | |
436 | dev_warn(dev, | |
437 | "Invalid submask 0x%x at 0x%x\n", | |
438 | submask, offset); | |
439 | continue; | |
440 | } | |
441 | ||
442 | func->pins[func->npins] = pin + pin_num_from_lsb; | |
443 | func->npins++; | |
444 | } | |
159a887e | 445 | } |
76d470de DB |
446 | |
447 | qsort(func->pins, func->npins, sizeof(func->pins[0]), | |
448 | single_pin_compare); | |
449 | list_add(&func->node, &priv->functions); | |
159a887e AF |
450 | return 0; |
451 | } | |
44d5c371 FB |
452 | static int single_set_state(struct udevice *dev, |
453 | struct udevice *config) | |
454 | { | |
1041eae4 | 455 | const u32 *prop; |
159a887e | 456 | const struct single_fdt_bits_cfg *prop_bits; |
44d5c371 FB |
457 | int len; |
458 | ||
dbfd9e0e | 459 | prop = dev_read_prop(config, "pinctrl-single,pins", &len); |
159a887e | 460 | |
44d5c371 FB |
461 | if (prop) { |
462 | dev_dbg(dev, "configuring pins for %s\n", config->name); | |
1041eae4 | 463 | if (len % sizeof(u32)) { |
44d5c371 FB |
464 | dev_dbg(dev, " invalid pin configuration in fdt\n"); |
465 | return -FDT_ERR_BADSTRUCTURE; | |
466 | } | |
76d470de | 467 | single_configure_pins(dev, prop, len, config->name); |
159a887e | 468 | return 0; |
44d5c371 FB |
469 | } |
470 | ||
159a887e | 471 | /* pinctrl-single,pins not found so check for pinctrl-single,bits */ |
dbfd9e0e | 472 | prop_bits = dev_read_prop(config, "pinctrl-single,bits", &len); |
159a887e AF |
473 | if (prop_bits) { |
474 | dev_dbg(dev, "configuring pins for %s\n", config->name); | |
475 | if (len % sizeof(struct single_fdt_bits_cfg)) { | |
476 | dev_dbg(dev, " invalid bits configuration in fdt\n"); | |
477 | return -FDT_ERR_BADSTRUCTURE; | |
478 | } | |
76d470de | 479 | single_configure_bits(dev, prop_bits, len, config->name); |
159a887e AF |
480 | return 0; |
481 | } | |
482 | ||
483 | /* Neither 'pinctrl-single,pins' nor 'pinctrl-single,bits' were found */ | |
44d5c371 FB |
484 | return len; |
485 | } | |
486 | ||
0b121629 DB |
487 | static const char *single_get_pin_name(struct udevice *dev, |
488 | unsigned int selector) | |
489 | { | |
490 | struct single_priv *priv = dev_get_priv(dev); | |
491 | ||
492 | if (selector >= priv->npins) | |
493 | snprintf(priv->pin_name, PINNAME_SIZE, "Error"); | |
494 | else | |
495 | snprintf(priv->pin_name, PINNAME_SIZE, "PIN%u", selector); | |
496 | ||
497 | return priv->pin_name; | |
498 | } | |
499 | ||
1dd7ae20 DB |
500 | static int single_get_pins_count(struct udevice *dev) |
501 | { | |
502 | struct single_priv *priv = dev_get_priv(dev); | |
503 | ||
504 | return priv->npins; | |
505 | } | |
506 | ||
62f86c6a BG |
507 | static int single_add_gpio_func(struct udevice *dev) |
508 | { | |
509 | struct single_priv *priv = dev_get_priv(dev); | |
510 | const char *propname = "pinctrl-single,gpio-range"; | |
511 | const char *cellname = "#pinctrl-single,gpio-range-cells"; | |
512 | struct single_gpiofunc_range *range; | |
513 | struct ofnode_phandle_args gpiospec; | |
514 | int ret, i; | |
515 | ||
516 | for (i = 0; ; i++) { | |
517 | ret = ofnode_parse_phandle_with_args(dev_ofnode(dev), propname, | |
518 | cellname, 0, i, &gpiospec); | |
519 | /* Do not treat it as error. Only treat it as end condition. */ | |
520 | if (ret) { | |
521 | ret = 0; | |
522 | break; | |
523 | } | |
524 | range = devm_kzalloc(dev, sizeof(*range), GFP_KERNEL); | |
525 | if (!range) { | |
526 | ret = -ENOMEM; | |
527 | break; | |
528 | } | |
529 | range->offset = gpiospec.args[0]; | |
530 | range->npins = gpiospec.args[1]; | |
531 | range->gpiofunc = gpiospec.args[2]; | |
532 | list_add_tail(&range->node, &priv->gpiofuncs); | |
533 | } | |
534 | return ret; | |
535 | } | |
536 | ||
1dd7ae20 DB |
537 | static int single_probe(struct udevice *dev) |
538 | { | |
539 | struct single_pdata *pdata = dev_get_plat(dev); | |
540 | struct single_priv *priv = dev_get_priv(dev); | |
541 | u32 size; | |
542 | ||
76d470de | 543 | INIT_LIST_HEAD(&priv->functions); |
62f86c6a | 544 | INIT_LIST_HEAD(&priv->gpiofuncs); |
76d470de | 545 | |
1dd7ae20 | 546 | size = pdata->offset + pdata->width / BITS_PER_BYTE; |
ef746bfd | 547 | #if (IS_ENABLED(CONFIG_SANDBOX)) |
5532262d DB |
548 | priv->sandbox_regs = |
549 | devm_kzalloc(dev, size * sizeof(*priv->sandbox_regs), | |
550 | GFP_KERNEL); | |
551 | if (!priv->sandbox_regs) | |
552 | return -ENOMEM; | |
553 | #endif | |
554 | ||
4d159b6f | 555 | /* looks like a possible divide by 0, but data->width avoids this */ |
1dd7ae20 DB |
556 | priv->npins = size / (pdata->width / BITS_PER_BYTE); |
557 | if (pdata->bits_per_mux) { | |
69414d86 DB |
558 | if (!pdata->mask) { |
559 | dev_err(dev, "function mask needs to be non-zero\n"); | |
560 | return -EINVAL; | |
561 | } | |
562 | ||
1dd7ae20 DB |
563 | priv->bits_per_pin = fls(pdata->mask); |
564 | priv->npins *= (pdata->width / priv->bits_per_pin); | |
565 | } | |
566 | ||
62f86c6a BG |
567 | if (single_add_gpio_func(dev)) |
568 | dev_dbg(dev, "gpio functions are not added\n"); | |
569 | ||
1dd7ae20 DB |
570 | dev_dbg(dev, "%d pins\n", priv->npins); |
571 | return 0; | |
572 | } | |
573 | ||
d1998a9f | 574 | static int single_of_to_plat(struct udevice *dev) |
44d5c371 | 575 | { |
7f18fb8a | 576 | void *addr; |
9fd8a430 | 577 | fdt_size_t size; |
0fd3d911 | 578 | struct single_pdata *pdata = dev_get_plat(dev); |
971c64a4 | 579 | int ret; |
44d5c371 | 580 | |
971c64a4 DB |
581 | ret = dev_read_u32(dev, "pinctrl-single,register-width", &pdata->width); |
582 | if (ret) { | |
583 | dev_err(dev, "missing register width\n"); | |
584 | return ret; | |
585 | } | |
44d5c371 | 586 | |
180531fc DB |
587 | switch (pdata->width) { |
588 | case 8: | |
589 | case 16: | |
590 | case 32: | |
591 | break; | |
592 | default: | |
593 | dev_err(dev, "wrong register width\n"); | |
594 | return -EINVAL; | |
595 | } | |
596 | ||
7f18fb8a MS |
597 | addr = dev_read_addr_size_index_ptr(dev, 0, &size); |
598 | if (!addr) { | |
1e787904 | 599 | dev_err(dev, "failed to get base register address\n"); |
9fd8a430 DB |
600 | return -EINVAL; |
601 | } | |
602 | ||
603 | pdata->offset = size - pdata->width / BITS_PER_BYTE; | |
44d5c371 FB |
604 | pdata->base = addr; |
605 | ||
d85b93e8 DB |
606 | ret = dev_read_u32(dev, "pinctrl-single,function-mask", &pdata->mask); |
607 | if (ret) { | |
608 | pdata->mask = 0; | |
609 | dev_warn(dev, "missing function register mask\n"); | |
610 | } | |
611 | ||
719cab6d | 612 | pdata->bits_per_mux = dev_read_bool(dev, "pinctrl-single,bit-per-mux"); |
159a887e | 613 | |
1041eae4 AB |
614 | /* If no pinctrl-cells is present, default to old style of 2 cells with |
615 | * bits per mux and 1 cell otherwise. | |
616 | */ | |
617 | ret = dev_read_u32(dev, "#pinctrl-cells", &pdata->args_count); | |
618 | if (ret) | |
619 | pdata->args_count = pdata->bits_per_mux ? 2 : 1; | |
620 | ||
44d5c371 FB |
621 | return 0; |
622 | } | |
623 | ||
624 | const struct pinctrl_ops single_pinctrl_ops = { | |
1dd7ae20 | 625 | .get_pins_count = single_get_pins_count, |
0b121629 | 626 | .get_pin_name = single_get_pin_name, |
44d5c371 | 627 | .set_state = single_set_state, |
76d470de | 628 | .get_pin_muxing = single_get_pin_muxing, |
fd921d20 | 629 | .request = single_request, |
44d5c371 FB |
630 | }; |
631 | ||
632 | static const struct udevice_id single_pinctrl_match[] = { | |
633 | { .compatible = "pinctrl-single" }, | |
634 | { /* sentinel */ } | |
635 | }; | |
636 | ||
637 | U_BOOT_DRIVER(single_pinctrl) = { | |
638 | .name = "single-pinctrl", | |
639 | .id = UCLASS_PINCTRL, | |
640 | .of_match = single_pinctrl_match, | |
641 | .ops = &single_pinctrl_ops, | |
caa4daa2 | 642 | .plat_auto = sizeof(struct single_pdata), |
1dd7ae20 | 643 | .priv_auto = sizeof(struct single_priv), |
d1998a9f | 644 | .of_to_plat = single_of_to_plat, |
1dd7ae20 | 645 | .probe = single_probe, |
44d5c371 | 646 | }; |