1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* Copyright (C) 2015 Broadcom Corporation |
3 | * |
4 | * This file contains the Northstar plus (NSP) IOMUX driver that supports |
5 | * group based PINMUX configuration. The Northstar plus IOMUX controller |
6 | * allows pins to be individually muxed to GPIO function. The NAND and MMC is |
7 | * a group based selection. The gpio_a 8 - 11 are muxed with gpio_b and pwm. |
8 | * To select PWM, one need to enable the corresponding gpio_b as well. |
9 | * |
10 | * gpio_a (8 - 11) |
11 | * +---------- |
12 | * | |
13 | * gpio_a (8-11) | gpio_b (0 - 3) |
14 | * ------------------------+-------+---------- |
15 | * | |
16 | * | pwm (0 - 3) |
17 | * +---------- |
18 | */ |
19 | |
20 | #include <linux/err.h> |
21 | #include <linux/io.h> |
22 | #include <linux/of.h> |
23 | #include <linux/platform_device.h> |
24 | #include <linux/seq_file.h> |
25 | #include <linux/slab.h> |
26 | |
27 | #include <linux/pinctrl/pinconf-generic.h> |
28 | #include <linux/pinctrl/pinconf.h> |
29 | #include <linux/pinctrl/pinctrl.h> |
30 | #include <linux/pinctrl/pinmux.h> |
31 | |
32 | #include "../core.h" |
33 | #include "../pinctrl-utils.h" |
34 | |
35 | #define NSP_MUX_BASE0 0x00 |
36 | #define NSP_MUX_BASE1 0x01 |
37 | #define NSP_MUX_BASE2 0x02 |
38 | /* |
39 | * nsp IOMUX register description |
40 | * |
41 | * @base: base 0 or base 1 |
42 | * @shift: bit shift for mux configuration of a group |
43 | * @mask: bit mask of the function |
44 | * @alt: alternate function to set to |
45 | */ |
46 | struct nsp_mux { |
47 | unsigned int base; |
48 | unsigned int shift; |
49 | unsigned int mask; |
50 | unsigned int alt; |
51 | }; |
52 | |
53 | /* |
54 | * Keep track of nsp IOMUX configuration and prevent double configuration |
55 | * |
56 | * @nsp_mux: nsp IOMUX register description |
57 | * @is_configured: flag to indicate whether a mux setting has already been |
58 | * configured |
59 | */ |
60 | struct nsp_mux_log { |
61 | struct nsp_mux mux; |
62 | bool is_configured; |
63 | }; |
64 | |
65 | /* |
66 | * Group based IOMUX configuration |
67 | * |
68 | * @name: name of the group |
69 | * @pins: array of pins used by this group |
70 | * @num_pins: total number of pins used by this group |
71 | * @mux: nsp group based IOMUX configuration |
72 | */ |
73 | struct nsp_pin_group { |
74 | const char *name; |
75 | const unsigned int *pins; |
76 | const unsigned int num_pins; |
77 | const struct nsp_mux mux; |
78 | }; |
79 | |
80 | /* |
81 | * nsp mux function and supported pin groups |
82 | * |
83 | * @name: name of the function |
84 | * @groups: array of groups that can be supported by this function |
85 | * @num_groups: total number of groups that can be supported by this function |
86 | */ |
87 | struct nsp_pin_function { |
88 | const char *name; |
89 | const char * const *groups; |
90 | const unsigned int num_groups; |
91 | }; |
92 | |
93 | /* |
94 | * nsp IOMUX pinctrl core |
95 | * |
96 | * @pctl: pointer to pinctrl_dev |
97 | * @dev: pointer to device |
98 | * @base0: first mux register |
99 | * @base1: second mux register |
100 | * @base2: third mux register |
101 | * @groups: pointer to array of groups |
102 | * @num_groups: total number of groups |
103 | * @functions: pointer to array of functions |
104 | * @num_functions: total number of functions |
105 | * @mux_log: pointer to the array of mux logs |
106 | * @lock: lock to protect register access |
107 | */ |
108 | struct nsp_pinctrl { |
109 | struct pinctrl_dev *pctl; |
110 | struct device *dev; |
111 | void __iomem *base0; |
112 | void __iomem *base1; |
113 | void __iomem *base2; |
114 | const struct nsp_pin_group *groups; |
115 | unsigned int num_groups; |
116 | const struct nsp_pin_function *functions; |
117 | unsigned int num_functions; |
118 | struct nsp_mux_log *mux_log; |
119 | spinlock_t lock; |
120 | }; |
121 | |
122 | /* |
123 | * Description of a pin in nsp |
124 | * |
125 | * @pin: pin number |
126 | * @name: pin name |
127 | * @gpio_select: reg data to select GPIO |
128 | */ |
129 | struct nsp_pin { |
130 | unsigned int pin; |
131 | char *name; |
132 | unsigned int gpio_select; |
133 | }; |
134 | |
135 | #define NSP_PIN_DESC(p, n, g) \ |
136 | { \ |
137 | .pin = p, \ |
138 | .name = n, \ |
139 | .gpio_select = g, \ |
140 | } |
141 | |
142 | /* |
143 | * List of muxable pins in nsp |
144 | */ |
145 | static struct nsp_pin nsp_pins[] = { |
146 | NSP_PIN_DESC(0, "spi_clk" , 1), |
147 | NSP_PIN_DESC(1, "spi_ss" , 1), |
148 | NSP_PIN_DESC(2, "spi_mosi" , 1), |
149 | NSP_PIN_DESC(3, "spi_miso" , 1), |
150 | NSP_PIN_DESC(4, "scl" , 1), |
151 | NSP_PIN_DESC(5, "sda" , 1), |
152 | NSP_PIN_DESC(6, "mdc" , 1), |
153 | NSP_PIN_DESC(7, "mdio" , 1), |
154 | NSP_PIN_DESC(8, "pwm0" , 1), |
155 | NSP_PIN_DESC(9, "pwm1" , 1), |
156 | NSP_PIN_DESC(10, "pwm2" , 1), |
157 | NSP_PIN_DESC(11, "pwm3" , 1), |
158 | NSP_PIN_DESC(12, "uart1_rx" , 1), |
159 | NSP_PIN_DESC(13, "uart1_tx" , 1), |
160 | NSP_PIN_DESC(14, "uart1_cts" , 1), |
161 | NSP_PIN_DESC(15, "uart1_rts" , 1), |
162 | NSP_PIN_DESC(16, "uart2_rx" , 1), |
163 | NSP_PIN_DESC(17, "uart2_tx" , 1), |
164 | NSP_PIN_DESC(18, "synce" , 0), |
165 | NSP_PIN_DESC(19, "sata0_led" , 0), |
166 | NSP_PIN_DESC(20, "sata1_led" , 0), |
167 | NSP_PIN_DESC(21, "xtal_out" , 1), |
168 | NSP_PIN_DESC(22, "sdio_pwr" , 1), |
169 | NSP_PIN_DESC(23, "sdio_en_1p8v" , 1), |
170 | NSP_PIN_DESC(24, "gpio_24" , 1), |
171 | NSP_PIN_DESC(25, "gpio_25" , 1), |
172 | NSP_PIN_DESC(26, "p5_led0" , 0), |
173 | NSP_PIN_DESC(27, "p5_led1" , 0), |
174 | NSP_PIN_DESC(28, "gpio_28" , 1), |
175 | NSP_PIN_DESC(29, "gpio_29" , 1), |
176 | NSP_PIN_DESC(30, "gpio_30" , 1), |
177 | NSP_PIN_DESC(31, "gpio_31" , 1), |
178 | NSP_PIN_DESC(32, "nand_ale" , 0), |
179 | NSP_PIN_DESC(33, "nand_ce0" , 0), |
180 | NSP_PIN_DESC(34, "nand_r/b" , 0), |
181 | NSP_PIN_DESC(35, "nand_dq0" , 0), |
182 | NSP_PIN_DESC(36, "nand_dq1" , 0), |
183 | NSP_PIN_DESC(37, "nand_dq2" , 0), |
184 | NSP_PIN_DESC(38, "nand_dq3" , 0), |
185 | NSP_PIN_DESC(39, "nand_dq4" , 0), |
186 | NSP_PIN_DESC(40, "nand_dq5" , 0), |
187 | NSP_PIN_DESC(41, "nand_dq6" , 0), |
188 | NSP_PIN_DESC(42, "nand_dq7" , 0), |
189 | }; |
190 | |
191 | /* |
192 | * List of groups of pins |
193 | */ |
194 | |
195 | static const unsigned int spi_pins[] = {0, 1, 2, 3}; |
196 | static const unsigned int i2c_pins[] = {4, 5}; |
197 | static const unsigned int mdio_pins[] = {6, 7}; |
198 | static const unsigned int pwm0_pins[] = {8}; |
199 | static const unsigned int gpio_b_0_pins[] = {8}; |
200 | static const unsigned int pwm1_pins[] = {9}; |
201 | static const unsigned int gpio_b_1_pins[] = {9}; |
202 | static const unsigned int pwm2_pins[] = {10}; |
203 | static const unsigned int gpio_b_2_pins[] = {10}; |
204 | static const unsigned int pwm3_pins[] = {11}; |
205 | static const unsigned int gpio_b_3_pins[] = {11}; |
206 | static const unsigned int uart1_pins[] = {12, 13, 14, 15}; |
207 | static const unsigned int uart2_pins[] = {16, 17}; |
208 | static const unsigned int synce_pins[] = {18}; |
209 | static const unsigned int sata0_led_pins[] = {19}; |
210 | static const unsigned int sata1_led_pins[] = {20}; |
211 | static const unsigned int xtal_out_pins[] = {21}; |
212 | static const unsigned int sdio_pwr_pins[] = {22}; |
213 | static const unsigned int sdio_1p8v_pins[] = {23}; |
214 | static const unsigned int switch_p05_led0_pins[] = {26}; |
215 | static const unsigned int switch_p05_led1_pins[] = {27}; |
216 | static const unsigned int nand_pins[] = {32, 33, 34, 35, 36, 37, 38, 39, |
217 | 40, 41, 42}; |
218 | static const unsigned int emmc_pins[] = {32, 33, 34, 35, 36, 37, 38, 39, |
219 | 40, 41, 42}; |
220 | |
221 | #define NSP_PIN_GROUP(group_name, ba, sh, ma, al) \ |
222 | { \ |
223 | .name = __stringify(group_name) "_grp", \ |
224 | .pins = group_name ## _pins, \ |
225 | .num_pins = ARRAY_SIZE(group_name ## _pins), \ |
226 | .mux = { \ |
227 | .base = ba, \ |
228 | .shift = sh, \ |
229 | .mask = ma, \ |
230 | .alt = al, \ |
231 | } \ |
232 | } |
233 | |
234 | /* |
235 | * List of nsp pin groups |
236 | */ |
237 | static const struct nsp_pin_group nsp_pin_groups[] = { |
238 | NSP_PIN_GROUP(spi, NSP_MUX_BASE0, 0, 0x0f, 0x00), |
239 | NSP_PIN_GROUP(i2c, NSP_MUX_BASE0, 3, 0x03, 0x00), |
240 | NSP_PIN_GROUP(mdio, NSP_MUX_BASE0, 5, 0x03, 0x00), |
241 | NSP_PIN_GROUP(gpio_b_0, NSP_MUX_BASE0, 7, 0x01, 0x00), |
242 | NSP_PIN_GROUP(pwm0, NSP_MUX_BASE1, 0, 0x01, 0x01), |
243 | NSP_PIN_GROUP(gpio_b_1, NSP_MUX_BASE0, 8, 0x01, 0x00), |
244 | NSP_PIN_GROUP(pwm1, NSP_MUX_BASE1, 1, 0x01, 0x01), |
245 | NSP_PIN_GROUP(gpio_b_2, NSP_MUX_BASE0, 9, 0x01, 0x00), |
246 | NSP_PIN_GROUP(pwm2, NSP_MUX_BASE1, 2, 0x01, 0x01), |
247 | NSP_PIN_GROUP(gpio_b_3, NSP_MUX_BASE0, 10, 0x01, 0x00), |
248 | NSP_PIN_GROUP(pwm3, NSP_MUX_BASE1, 3, 0x01, 0x01), |
249 | NSP_PIN_GROUP(uart1, NSP_MUX_BASE0, 11, 0x0f, 0x00), |
250 | NSP_PIN_GROUP(uart2, NSP_MUX_BASE0, 15, 0x03, 0x00), |
251 | NSP_PIN_GROUP(synce, NSP_MUX_BASE0, 17, 0x01, 0x01), |
252 | NSP_PIN_GROUP(sata0_led, NSP_MUX_BASE0, 18, 0x01, 0x01), |
253 | NSP_PIN_GROUP(sata1_led, NSP_MUX_BASE0, 19, 0x01, 0x01), |
254 | NSP_PIN_GROUP(xtal_out, NSP_MUX_BASE0, 20, 0x01, 0x00), |
255 | NSP_PIN_GROUP(sdio_pwr, NSP_MUX_BASE0, 21, 0x01, 0x00), |
256 | NSP_PIN_GROUP(sdio_1p8v, NSP_MUX_BASE0, 22, 0x01, 0x00), |
257 | NSP_PIN_GROUP(switch_p05_led0, NSP_MUX_BASE0, 26, 0x01, 0x01), |
258 | NSP_PIN_GROUP(switch_p05_led1, NSP_MUX_BASE0, 27, 0x01, 0x01), |
259 | NSP_PIN_GROUP(nand, NSP_MUX_BASE2, 0, 0x01, 0x00), |
260 | NSP_PIN_GROUP(emmc, NSP_MUX_BASE2, 0, 0x01, 0x01) |
261 | }; |
262 | |
263 | /* |
264 | * List of groups supported by functions |
265 | */ |
266 | |
267 | static const char * const spi_grps[] = {"spi_grp" }; |
268 | static const char * const i2c_grps[] = {"i2c_grp" }; |
269 | static const char * const mdio_grps[] = {"mdio_grp" }; |
270 | static const char * const pwm_grps[] = {"pwm0_grp" , "pwm1_grp" , "pwm2_grp" |
271 | , "pwm3_grp" }; |
272 | static const char * const gpio_b_grps[] = {"gpio_b_0_grp" , "gpio_b_1_grp" , |
273 | "gpio_b_2_grp" , "gpio_b_3_grp" }; |
274 | static const char * const uart1_grps[] = {"uart1_grp" }; |
275 | static const char * const uart2_grps[] = {"uart2_grp" }; |
276 | static const char * const synce_grps[] = {"synce_grp" }; |
277 | static const char * const sata_led_grps[] = {"sata0_led_grp" , "sata1_led_grp" }; |
278 | static const char * const xtal_out_grps[] = {"xtal_out_grp" }; |
279 | static const char * const sdio_grps[] = {"sdio_pwr_grp" , "sdio_1p8v_grp" }; |
280 | static const char * const switch_led_grps[] = {"switch_p05_led0_grp" , |
281 | "switch_p05_led1_grp" }; |
282 | static const char * const nand_grps[] = {"nand_grp" }; |
283 | static const char * const emmc_grps[] = {"emmc_grp" }; |
284 | |
285 | #define NSP_PIN_FUNCTION(func) \ |
286 | { \ |
287 | .name = #func, \ |
288 | .groups = func ## _grps, \ |
289 | .num_groups = ARRAY_SIZE(func ## _grps), \ |
290 | } |
291 | |
292 | /* |
293 | * List of supported functions in nsp |
294 | */ |
295 | static const struct nsp_pin_function nsp_pin_functions[] = { |
296 | NSP_PIN_FUNCTION(spi), |
297 | NSP_PIN_FUNCTION(i2c), |
298 | NSP_PIN_FUNCTION(mdio), |
299 | NSP_PIN_FUNCTION(pwm), |
300 | NSP_PIN_FUNCTION(gpio_b), |
301 | NSP_PIN_FUNCTION(uart1), |
302 | NSP_PIN_FUNCTION(uart2), |
303 | NSP_PIN_FUNCTION(synce), |
304 | NSP_PIN_FUNCTION(sata_led), |
305 | NSP_PIN_FUNCTION(xtal_out), |
306 | NSP_PIN_FUNCTION(sdio), |
307 | NSP_PIN_FUNCTION(switch_led), |
308 | NSP_PIN_FUNCTION(nand), |
309 | NSP_PIN_FUNCTION(emmc) |
310 | }; |
311 | |
312 | static int nsp_get_groups_count(struct pinctrl_dev *pctrl_dev) |
313 | { |
314 | struct nsp_pinctrl *pinctrl = pinctrl_dev_get_drvdata(pctldev: pctrl_dev); |
315 | |
316 | return pinctrl->num_groups; |
317 | } |
318 | |
319 | static const char *nsp_get_group_name(struct pinctrl_dev *pctrl_dev, |
320 | unsigned int selector) |
321 | { |
322 | struct nsp_pinctrl *pinctrl = pinctrl_dev_get_drvdata(pctldev: pctrl_dev); |
323 | |
324 | return pinctrl->groups[selector].name; |
325 | } |
326 | |
327 | static int nsp_get_group_pins(struct pinctrl_dev *pctrl_dev, |
328 | unsigned int selector, const unsigned int **pins, |
329 | unsigned int *num_pins) |
330 | { |
331 | struct nsp_pinctrl *pinctrl = pinctrl_dev_get_drvdata(pctldev: pctrl_dev); |
332 | |
333 | *pins = pinctrl->groups[selector].pins; |
334 | *num_pins = pinctrl->groups[selector].num_pins; |
335 | |
336 | return 0; |
337 | } |
338 | |
339 | static void nsp_pin_dbg_show(struct pinctrl_dev *pctrl_dev, |
340 | struct seq_file *s, unsigned int offset) |
341 | { |
342 | seq_printf(m: s, fmt: " %s" , dev_name(dev: pctrl_dev->dev)); |
343 | } |
344 | |
345 | static const struct pinctrl_ops nsp_pinctrl_ops = { |
346 | .get_groups_count = nsp_get_groups_count, |
347 | .get_group_name = nsp_get_group_name, |
348 | .get_group_pins = nsp_get_group_pins, |
349 | .pin_dbg_show = nsp_pin_dbg_show, |
350 | .dt_node_to_map = pinconf_generic_dt_node_to_map_group, |
351 | .dt_free_map = pinctrl_utils_free_map, |
352 | }; |
353 | |
354 | static int nsp_get_functions_count(struct pinctrl_dev *pctrl_dev) |
355 | { |
356 | struct nsp_pinctrl *pinctrl = pinctrl_dev_get_drvdata(pctldev: pctrl_dev); |
357 | |
358 | return pinctrl->num_functions; |
359 | } |
360 | |
361 | static const char *nsp_get_function_name(struct pinctrl_dev *pctrl_dev, |
362 | unsigned int selector) |
363 | { |
364 | struct nsp_pinctrl *pinctrl = pinctrl_dev_get_drvdata(pctldev: pctrl_dev); |
365 | |
366 | return pinctrl->functions[selector].name; |
367 | } |
368 | |
369 | static int nsp_get_function_groups(struct pinctrl_dev *pctrl_dev, |
370 | unsigned int selector, |
371 | const char * const **groups, |
372 | unsigned * const num_groups) |
373 | { |
374 | struct nsp_pinctrl *pinctrl = pinctrl_dev_get_drvdata(pctldev: pctrl_dev); |
375 | |
376 | *groups = pinctrl->functions[selector].groups; |
377 | *num_groups = pinctrl->functions[selector].num_groups; |
378 | |
379 | return 0; |
380 | } |
381 | |
382 | static int nsp_pinmux_set(struct nsp_pinctrl *pinctrl, |
383 | const struct nsp_pin_function *func, |
384 | const struct nsp_pin_group *grp, |
385 | struct nsp_mux_log *mux_log) |
386 | { |
387 | const struct nsp_mux *mux = &grp->mux; |
388 | int i; |
389 | u32 val, mask; |
390 | unsigned long flags; |
391 | void __iomem *base_address; |
392 | |
393 | for (i = 0; i < pinctrl->num_groups; i++) { |
394 | if ((mux->shift != mux_log[i].mux.shift) || |
395 | (mux->base != mux_log[i].mux.base)) |
396 | continue; |
397 | |
398 | /* if this is a new configuration, just do it! */ |
399 | if (!mux_log[i].is_configured) |
400 | break; |
401 | |
402 | /* |
403 | * IOMUX has been configured previously and one is trying to |
404 | * configure it to a different function |
405 | */ |
406 | if (mux_log[i].mux.alt != mux->alt) { |
407 | dev_err(pinctrl->dev, |
408 | "double configuration error detected!\n" ); |
409 | dev_err(pinctrl->dev, "func:%s grp:%s\n" , |
410 | func->name, grp->name); |
411 | return -EINVAL; |
412 | } |
413 | |
414 | return 0; |
415 | } |
416 | if (i == pinctrl->num_groups) |
417 | return -EINVAL; |
418 | |
419 | mask = mux->mask; |
420 | mux_log[i].mux.alt = mux->alt; |
421 | mux_log[i].is_configured = true; |
422 | |
423 | switch (mux->base) { |
424 | case NSP_MUX_BASE0: |
425 | base_address = pinctrl->base0; |
426 | break; |
427 | |
428 | case NSP_MUX_BASE1: |
429 | base_address = pinctrl->base1; |
430 | break; |
431 | |
432 | case NSP_MUX_BASE2: |
433 | base_address = pinctrl->base2; |
434 | break; |
435 | |
436 | default: |
437 | return -EINVAL; |
438 | } |
439 | |
440 | spin_lock_irqsave(&pinctrl->lock, flags); |
441 | val = readl(addr: base_address); |
442 | val &= ~(mask << grp->mux.shift); |
443 | val |= grp->mux.alt << grp->mux.shift; |
444 | writel(val, addr: base_address); |
445 | spin_unlock_irqrestore(lock: &pinctrl->lock, flags); |
446 | |
447 | return 0; |
448 | } |
449 | |
450 | static int nsp_pinmux_enable(struct pinctrl_dev *pctrl_dev, |
451 | unsigned int func_select, unsigned int grp_select) |
452 | { |
453 | struct nsp_pinctrl *pinctrl = pinctrl_dev_get_drvdata(pctldev: pctrl_dev); |
454 | const struct nsp_pin_function *func; |
455 | const struct nsp_pin_group *grp; |
456 | |
457 | if (grp_select >= pinctrl->num_groups || |
458 | func_select >= pinctrl->num_functions) |
459 | return -EINVAL; |
460 | |
461 | func = &pinctrl->functions[func_select]; |
462 | grp = &pinctrl->groups[grp_select]; |
463 | |
464 | dev_dbg(pctrl_dev->dev, "func:%u name:%s grp:%u name:%s\n" , |
465 | func_select, func->name, grp_select, grp->name); |
466 | |
467 | dev_dbg(pctrl_dev->dev, "shift:%u alt:%u\n" , grp->mux.shift, |
468 | grp->mux.alt); |
469 | |
470 | return nsp_pinmux_set(pinctrl, func, grp, mux_log: pinctrl->mux_log); |
471 | } |
472 | |
473 | |
474 | static int nsp_gpio_request_enable(struct pinctrl_dev *pctrl_dev, |
475 | struct pinctrl_gpio_range *range, |
476 | unsigned int pin) |
477 | { |
478 | struct nsp_pinctrl *pinctrl = pinctrl_dev_get_drvdata(pctldev: pctrl_dev); |
479 | u32 *gpio_select = pctrl_dev->desc->pins[pin].drv_data; |
480 | u32 val; |
481 | unsigned long flags; |
482 | |
483 | spin_lock_irqsave(&pinctrl->lock, flags); |
484 | val = readl(addr: pinctrl->base0); |
485 | if ((val & BIT(pin)) != (*gpio_select << pin)) { |
486 | val &= ~BIT(pin); |
487 | val |= *gpio_select << pin; |
488 | writel(val, addr: pinctrl->base0); |
489 | } |
490 | spin_unlock_irqrestore(lock: &pinctrl->lock, flags); |
491 | |
492 | return 0; |
493 | } |
494 | |
495 | static void nsp_gpio_disable_free(struct pinctrl_dev *pctrl_dev, |
496 | struct pinctrl_gpio_range *range, |
497 | unsigned int pin) |
498 | { |
499 | struct nsp_pinctrl *pinctrl = pinctrl_dev_get_drvdata(pctldev: pctrl_dev); |
500 | u32 *gpio_select = pctrl_dev->desc->pins[pin].drv_data; |
501 | u32 val; |
502 | unsigned long flags; |
503 | |
504 | spin_lock_irqsave(&pinctrl->lock, flags); |
505 | val = readl(addr: pinctrl->base0); |
506 | if ((val & (1 << pin)) == (*gpio_select << pin)) { |
507 | val &= ~(1 << pin); |
508 | if (!(*gpio_select)) |
509 | val |= (1 << pin); |
510 | writel(val, addr: pinctrl->base0); |
511 | } |
512 | spin_unlock_irqrestore(lock: &pinctrl->lock, flags); |
513 | } |
514 | |
515 | static const struct pinmux_ops nsp_pinmux_ops = { |
516 | .get_functions_count = nsp_get_functions_count, |
517 | .get_function_name = nsp_get_function_name, |
518 | .get_function_groups = nsp_get_function_groups, |
519 | .set_mux = nsp_pinmux_enable, |
520 | .gpio_request_enable = nsp_gpio_request_enable, |
521 | .gpio_disable_free = nsp_gpio_disable_free, |
522 | }; |
523 | |
524 | static struct pinctrl_desc nsp_pinctrl_desc = { |
525 | .name = "nsp-pinmux" , |
526 | .pctlops = &nsp_pinctrl_ops, |
527 | .pmxops = &nsp_pinmux_ops, |
528 | }; |
529 | |
530 | static int nsp_mux_log_init(struct nsp_pinctrl *pinctrl) |
531 | { |
532 | struct nsp_mux_log *log; |
533 | unsigned int i; |
534 | u32 no_of_groups = ARRAY_SIZE(nsp_pin_groups); |
535 | |
536 | pinctrl->mux_log = devm_kcalloc(dev: pinctrl->dev, n: no_of_groups, |
537 | size: sizeof(struct nsp_mux_log), |
538 | GFP_KERNEL); |
539 | if (!pinctrl->mux_log) |
540 | return -ENOMEM; |
541 | |
542 | for (i = 0; i < no_of_groups; i++) { |
543 | log = &pinctrl->mux_log[i]; |
544 | log->mux.base = nsp_pin_groups[i].mux.base; |
545 | log->mux.shift = nsp_pin_groups[i].mux.shift; |
546 | log->mux.alt = 0; |
547 | log->is_configured = false; |
548 | } |
549 | |
550 | return 0; |
551 | } |
552 | |
553 | static int nsp_pinmux_probe(struct platform_device *pdev) |
554 | { |
555 | struct nsp_pinctrl *pinctrl; |
556 | struct resource *res; |
557 | int i, ret; |
558 | struct pinctrl_pin_desc *pins; |
559 | unsigned int num_pins = ARRAY_SIZE(nsp_pins); |
560 | |
561 | pinctrl = devm_kzalloc(dev: &pdev->dev, size: sizeof(*pinctrl), GFP_KERNEL); |
562 | if (!pinctrl) |
563 | return -ENOMEM; |
564 | pinctrl->dev = &pdev->dev; |
565 | platform_set_drvdata(pdev, data: pinctrl); |
566 | spin_lock_init(&pinctrl->lock); |
567 | |
568 | pinctrl->base0 = devm_platform_ioremap_resource(pdev, index: 0); |
569 | if (IS_ERR(ptr: pinctrl->base0)) |
570 | return PTR_ERR(ptr: pinctrl->base0); |
571 | |
572 | res = platform_get_resource(pdev, IORESOURCE_MEM, 1); |
573 | if (!res) |
574 | return -EINVAL; |
575 | pinctrl->base1 = devm_ioremap(dev: &pdev->dev, offset: res->start, |
576 | size: resource_size(res)); |
577 | if (!pinctrl->base1) { |
578 | dev_err(&pdev->dev, "unable to map I/O space\n" ); |
579 | return -ENOMEM; |
580 | } |
581 | |
582 | pinctrl->base2 = devm_platform_ioremap_resource(pdev, index: 2); |
583 | if (IS_ERR(ptr: pinctrl->base2)) |
584 | return PTR_ERR(ptr: pinctrl->base2); |
585 | |
586 | ret = nsp_mux_log_init(pinctrl); |
587 | if (ret) { |
588 | dev_err(&pdev->dev, "unable to initialize IOMUX log\n" ); |
589 | return ret; |
590 | } |
591 | |
592 | pins = devm_kcalloc(dev: &pdev->dev, n: num_pins, size: sizeof(*pins), GFP_KERNEL); |
593 | if (!pins) |
594 | return -ENOMEM; |
595 | |
596 | for (i = 0; i < num_pins; i++) { |
597 | pins[i].number = nsp_pins[i].pin; |
598 | pins[i].name = nsp_pins[i].name; |
599 | pins[i].drv_data = &nsp_pins[i].gpio_select; |
600 | } |
601 | |
602 | pinctrl->groups = nsp_pin_groups; |
603 | pinctrl->num_groups = ARRAY_SIZE(nsp_pin_groups); |
604 | pinctrl->functions = nsp_pin_functions; |
605 | pinctrl->num_functions = ARRAY_SIZE(nsp_pin_functions); |
606 | nsp_pinctrl_desc.pins = pins; |
607 | nsp_pinctrl_desc.npins = num_pins; |
608 | |
609 | pinctrl->pctl = devm_pinctrl_register(dev: &pdev->dev, pctldesc: &nsp_pinctrl_desc, |
610 | driver_data: pinctrl); |
611 | if (IS_ERR(ptr: pinctrl->pctl)) { |
612 | dev_err(&pdev->dev, "unable to register nsp IOMUX pinctrl\n" ); |
613 | return PTR_ERR(ptr: pinctrl->pctl); |
614 | } |
615 | |
616 | return 0; |
617 | } |
618 | |
619 | static const struct of_device_id nsp_pinmux_of_match[] = { |
620 | { .compatible = "brcm,nsp-pinmux" }, |
621 | { } |
622 | }; |
623 | |
624 | static struct platform_driver nsp_pinmux_driver = { |
625 | .driver = { |
626 | .name = "nsp-pinmux" , |
627 | .of_match_table = nsp_pinmux_of_match, |
628 | }, |
629 | .probe = nsp_pinmux_probe, |
630 | }; |
631 | |
632 | static int __init nsp_pinmux_init(void) |
633 | { |
634 | return platform_driver_register(&nsp_pinmux_driver); |
635 | } |
636 | arch_initcall(nsp_pinmux_init); |
637 | |