1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * Copyright (C) 2014-2017 Broadcom |
4 | */ |
5 | |
6 | /* |
7 | * This file contains the Broadcom Iproc GPIO driver that supports 3 |
8 | * GPIO controllers on Iproc including the ASIU GPIO controller, the |
9 | * chipCommonG GPIO controller, and the always-on GPIO controller. Basic |
10 | * PINCONF such as bias pull up/down, and drive strength are also supported |
11 | * in this driver. |
12 | * |
13 | * It provides the functionality where pins from the GPIO can be |
14 | * individually muxed to GPIO function, if individual pad |
15 | * configuration is supported, through the interaction with respective |
16 | * SoCs IOMUX controller. |
17 | */ |
18 | |
19 | #include <linux/gpio/driver.h> |
20 | #include <linux/interrupt.h> |
21 | #include <linux/io.h> |
22 | #include <linux/ioport.h> |
23 | #include <linux/kernel.h> |
24 | #include <linux/of.h> |
25 | #include <linux/platform_device.h> |
26 | #include <linux/seq_file.h> |
27 | #include <linux/slab.h> |
28 | |
29 | #include <linux/pinctrl/consumer.h> |
30 | #include <linux/pinctrl/pinconf-generic.h> |
31 | #include <linux/pinctrl/pinconf.h> |
32 | #include <linux/pinctrl/pinctrl.h> |
33 | |
34 | #include "../pinctrl-utils.h" |
35 | |
36 | #define IPROC_GPIO_DATA_IN_OFFSET 0x00 |
37 | #define IPROC_GPIO_DATA_OUT_OFFSET 0x04 |
38 | #define IPROC_GPIO_OUT_EN_OFFSET 0x08 |
39 | #define IPROC_GPIO_INT_TYPE_OFFSET 0x0c |
40 | #define IPROC_GPIO_INT_DE_OFFSET 0x10 |
41 | #define IPROC_GPIO_INT_EDGE_OFFSET 0x14 |
42 | #define IPROC_GPIO_INT_MSK_OFFSET 0x18 |
43 | #define IPROC_GPIO_INT_STAT_OFFSET 0x1c |
44 | #define IPROC_GPIO_INT_MSTAT_OFFSET 0x20 |
45 | #define IPROC_GPIO_INT_CLR_OFFSET 0x24 |
46 | #define IPROC_GPIO_PAD_RES_OFFSET 0x34 |
47 | #define IPROC_GPIO_RES_EN_OFFSET 0x38 |
48 | |
49 | /* drive strength control for ASIU GPIO */ |
50 | #define IPROC_GPIO_ASIU_DRV0_CTRL_OFFSET 0x58 |
51 | |
52 | /* pinconf for CCM GPIO */ |
53 | #define IPROC_GPIO_PULL_DN_OFFSET 0x10 |
54 | #define IPROC_GPIO_PULL_UP_OFFSET 0x14 |
55 | |
56 | /* pinconf for CRMU(aon) GPIO and CCM GPIO*/ |
57 | #define IPROC_GPIO_DRV_CTRL_OFFSET 0x00 |
58 | |
59 | #define GPIO_BANK_SIZE 0x200 |
60 | #define NGPIOS_PER_BANK 32 |
61 | #define GPIO_BANK(pin) ((pin) / NGPIOS_PER_BANK) |
62 | |
63 | #define IPROC_GPIO_REG(pin, reg) (GPIO_BANK(pin) * GPIO_BANK_SIZE + (reg)) |
64 | #define IPROC_GPIO_SHIFT(pin) ((pin) % NGPIOS_PER_BANK) |
65 | |
66 | #define GPIO_DRV_STRENGTH_BIT_SHIFT 20 |
67 | #define GPIO_DRV_STRENGTH_BITS 3 |
68 | #define GPIO_DRV_STRENGTH_BIT_MASK ((1 << GPIO_DRV_STRENGTH_BITS) - 1) |
69 | |
70 | enum iproc_pinconf_param { |
71 | IPROC_PINCONF_DRIVE_STRENGTH = 0, |
72 | IPROC_PINCONF_BIAS_DISABLE, |
73 | IPROC_PINCONF_BIAS_PULL_UP, |
74 | IPROC_PINCONF_BIAS_PULL_DOWN, |
75 | IPROC_PINCON_MAX, |
76 | }; |
77 | |
78 | enum iproc_pinconf_ctrl_type { |
79 | IOCTRL_TYPE_AON = 1, |
80 | IOCTRL_TYPE_CDRU, |
81 | IOCTRL_TYPE_INVALID, |
82 | }; |
83 | |
84 | /* |
85 | * Iproc GPIO core |
86 | * |
87 | * @dev: pointer to device |
88 | * @base: I/O register base for Iproc GPIO controller |
89 | * @io_ctrl: I/O register base for certain type of Iproc GPIO controller that |
90 | * has the PINCONF support implemented outside of the GPIO block |
91 | * @lock: lock to protect access to I/O registers |
92 | * @gc: GPIO chip |
93 | * @num_banks: number of GPIO banks, each bank supports up to 32 GPIOs |
94 | * @pinmux_is_supported: flag to indicate this GPIO controller contains pins |
95 | * that can be individually muxed to GPIO |
96 | * @pinconf_disable: contains a list of PINCONF parameters that need to be |
97 | * disabled |
98 | * @nr_pinconf_disable: total number of PINCONF parameters that need to be |
99 | * disabled |
100 | * @pctl: pointer to pinctrl_dev |
101 | * @pctldesc: pinctrl descriptor |
102 | */ |
103 | struct iproc_gpio { |
104 | struct device *dev; |
105 | |
106 | void __iomem *base; |
107 | void __iomem *io_ctrl; |
108 | enum iproc_pinconf_ctrl_type io_ctrl_type; |
109 | |
110 | raw_spinlock_t lock; |
111 | |
112 | struct gpio_chip gc; |
113 | unsigned num_banks; |
114 | |
115 | bool pinmux_is_supported; |
116 | |
117 | enum pin_config_param *pinconf_disable; |
118 | unsigned int nr_pinconf_disable; |
119 | |
120 | struct pinctrl_dev *pctl; |
121 | struct pinctrl_desc pctldesc; |
122 | }; |
123 | |
124 | /* |
125 | * Mapping from PINCONF pins to GPIO pins is 1-to-1 |
126 | */ |
127 | static inline unsigned iproc_pin_to_gpio(unsigned pin) |
128 | { |
129 | return pin; |
130 | } |
131 | |
132 | /** |
133 | * iproc_set_bit - set or clear one bit (corresponding to the GPIO pin) in a |
134 | * Iproc GPIO register |
135 | * |
136 | * @chip: Iproc GPIO device |
137 | * @reg: register offset |
138 | * @gpio: GPIO pin |
139 | * @set: set or clear |
140 | */ |
141 | static inline void iproc_set_bit(struct iproc_gpio *chip, unsigned int reg, |
142 | unsigned gpio, bool set) |
143 | { |
144 | unsigned int offset = IPROC_GPIO_REG(gpio, reg); |
145 | unsigned int shift = IPROC_GPIO_SHIFT(gpio); |
146 | u32 val; |
147 | |
148 | val = readl(addr: chip->base + offset); |
149 | if (set) |
150 | val |= BIT(shift); |
151 | else |
152 | val &= ~BIT(shift); |
153 | writel(val, addr: chip->base + offset); |
154 | } |
155 | |
156 | static inline bool iproc_get_bit(struct iproc_gpio *chip, unsigned int reg, |
157 | unsigned gpio) |
158 | { |
159 | unsigned int offset = IPROC_GPIO_REG(gpio, reg); |
160 | unsigned int shift = IPROC_GPIO_SHIFT(gpio); |
161 | |
162 | return !!(readl(addr: chip->base + offset) & BIT(shift)); |
163 | } |
164 | |
165 | static void iproc_gpio_irq_handler(struct irq_desc *desc) |
166 | { |
167 | struct gpio_chip *gc = irq_desc_get_handler_data(desc); |
168 | struct iproc_gpio *chip = gpiochip_get_data(gc); |
169 | struct irq_chip *irq_chip = irq_desc_get_chip(desc); |
170 | int i, bit; |
171 | |
172 | chained_irq_enter(chip: irq_chip, desc); |
173 | |
174 | /* go through the entire GPIO banks and handle all interrupts */ |
175 | for (i = 0; i < chip->num_banks; i++) { |
176 | unsigned long val = readl(addr: chip->base + (i * GPIO_BANK_SIZE) + |
177 | IPROC_GPIO_INT_MSTAT_OFFSET); |
178 | |
179 | for_each_set_bit(bit, &val, NGPIOS_PER_BANK) { |
180 | unsigned pin = NGPIOS_PER_BANK * i + bit; |
181 | |
182 | /* |
183 | * Clear the interrupt before invoking the |
184 | * handler, so we do not leave any window |
185 | */ |
186 | writel(BIT(bit), addr: chip->base + (i * GPIO_BANK_SIZE) + |
187 | IPROC_GPIO_INT_CLR_OFFSET); |
188 | |
189 | generic_handle_domain_irq(domain: gc->irq.domain, hwirq: pin); |
190 | } |
191 | } |
192 | |
193 | chained_irq_exit(chip: irq_chip, desc); |
194 | } |
195 | |
196 | |
197 | static void iproc_gpio_irq_ack(struct irq_data *d) |
198 | { |
199 | struct gpio_chip *gc = irq_data_get_irq_chip_data(d); |
200 | struct iproc_gpio *chip = gpiochip_get_data(gc); |
201 | unsigned gpio = d->hwirq; |
202 | unsigned int offset = IPROC_GPIO_REG(gpio, |
203 | IPROC_GPIO_INT_CLR_OFFSET); |
204 | unsigned int shift = IPROC_GPIO_SHIFT(gpio); |
205 | u32 val = BIT(shift); |
206 | |
207 | writel(val, addr: chip->base + offset); |
208 | } |
209 | |
210 | /** |
211 | * iproc_gpio_irq_set_mask - mask/unmask a GPIO interrupt |
212 | * |
213 | * @d: IRQ chip data |
214 | * @unmask: mask/unmask GPIO interrupt |
215 | */ |
216 | static void iproc_gpio_irq_set_mask(struct irq_data *d, bool unmask) |
217 | { |
218 | struct gpio_chip *gc = irq_data_get_irq_chip_data(d); |
219 | struct iproc_gpio *chip = gpiochip_get_data(gc); |
220 | unsigned gpio = irqd_to_hwirq(d); |
221 | |
222 | iproc_set_bit(chip, IPROC_GPIO_INT_MSK_OFFSET, gpio, set: unmask); |
223 | } |
224 | |
225 | static void iproc_gpio_irq_mask(struct irq_data *d) |
226 | { |
227 | struct gpio_chip *gc = irq_data_get_irq_chip_data(d); |
228 | struct iproc_gpio *chip = gpiochip_get_data(gc); |
229 | unsigned long flags; |
230 | |
231 | raw_spin_lock_irqsave(&chip->lock, flags); |
232 | iproc_gpio_irq_set_mask(d, unmask: false); |
233 | raw_spin_unlock_irqrestore(&chip->lock, flags); |
234 | gpiochip_disable_irq(gc, offset: irqd_to_hwirq(d)); |
235 | } |
236 | |
237 | static void iproc_gpio_irq_unmask(struct irq_data *d) |
238 | { |
239 | struct gpio_chip *gc = irq_data_get_irq_chip_data(d); |
240 | struct iproc_gpio *chip = gpiochip_get_data(gc); |
241 | unsigned long flags; |
242 | |
243 | gpiochip_enable_irq(gc, offset: irqd_to_hwirq(d)); |
244 | raw_spin_lock_irqsave(&chip->lock, flags); |
245 | iproc_gpio_irq_set_mask(d, unmask: true); |
246 | raw_spin_unlock_irqrestore(&chip->lock, flags); |
247 | } |
248 | |
249 | static int iproc_gpio_irq_set_type(struct irq_data *d, unsigned int type) |
250 | { |
251 | struct gpio_chip *gc = irq_data_get_irq_chip_data(d); |
252 | struct iproc_gpio *chip = gpiochip_get_data(gc); |
253 | unsigned gpio = d->hwirq; |
254 | bool level_triggered = false; |
255 | bool dual_edge = false; |
256 | bool rising_or_high = false; |
257 | unsigned long flags; |
258 | |
259 | switch (type & IRQ_TYPE_SENSE_MASK) { |
260 | case IRQ_TYPE_EDGE_RISING: |
261 | rising_or_high = true; |
262 | break; |
263 | |
264 | case IRQ_TYPE_EDGE_FALLING: |
265 | break; |
266 | |
267 | case IRQ_TYPE_EDGE_BOTH: |
268 | dual_edge = true; |
269 | break; |
270 | |
271 | case IRQ_TYPE_LEVEL_HIGH: |
272 | level_triggered = true; |
273 | rising_or_high = true; |
274 | break; |
275 | |
276 | case IRQ_TYPE_LEVEL_LOW: |
277 | level_triggered = true; |
278 | break; |
279 | |
280 | default: |
281 | dev_err(chip->dev, "invalid GPIO IRQ type 0x%x\n" , |
282 | type); |
283 | return -EINVAL; |
284 | } |
285 | |
286 | raw_spin_lock_irqsave(&chip->lock, flags); |
287 | iproc_set_bit(chip, IPROC_GPIO_INT_TYPE_OFFSET, gpio, |
288 | set: level_triggered); |
289 | iproc_set_bit(chip, IPROC_GPIO_INT_DE_OFFSET, gpio, set: dual_edge); |
290 | iproc_set_bit(chip, IPROC_GPIO_INT_EDGE_OFFSET, gpio, |
291 | set: rising_or_high); |
292 | |
293 | if (type & IRQ_TYPE_EDGE_BOTH) |
294 | irq_set_handler_locked(data: d, handler: handle_edge_irq); |
295 | else |
296 | irq_set_handler_locked(data: d, handler: handle_level_irq); |
297 | |
298 | raw_spin_unlock_irqrestore(&chip->lock, flags); |
299 | |
300 | dev_dbg(chip->dev, |
301 | "gpio:%u level_triggered:%d dual_edge:%d rising_or_high:%d\n" , |
302 | gpio, level_triggered, dual_edge, rising_or_high); |
303 | |
304 | return 0; |
305 | } |
306 | |
307 | static void iproc_gpio_irq_print_chip(struct irq_data *d, struct seq_file *p) |
308 | { |
309 | struct gpio_chip *gc = irq_data_get_irq_chip_data(d); |
310 | struct iproc_gpio *chip = gpiochip_get_data(gc); |
311 | |
312 | seq_printf(m: p, fmt: dev_name(dev: chip->dev)); |
313 | } |
314 | |
315 | static const struct irq_chip iproc_gpio_irq_chip = { |
316 | .irq_ack = iproc_gpio_irq_ack, |
317 | .irq_mask = iproc_gpio_irq_mask, |
318 | .irq_unmask = iproc_gpio_irq_unmask, |
319 | .irq_set_type = iproc_gpio_irq_set_type, |
320 | .irq_enable = iproc_gpio_irq_unmask, |
321 | .irq_disable = iproc_gpio_irq_mask, |
322 | .irq_print_chip = iproc_gpio_irq_print_chip, |
323 | .flags = IRQCHIP_IMMUTABLE, |
324 | GPIOCHIP_IRQ_RESOURCE_HELPERS, |
325 | }; |
326 | |
327 | /* |
328 | * Request the Iproc IOMUX pinmux controller to mux individual pins to GPIO |
329 | */ |
330 | static int iproc_gpio_request(struct gpio_chip *gc, unsigned offset) |
331 | { |
332 | struct iproc_gpio *chip = gpiochip_get_data(gc); |
333 | |
334 | /* not all Iproc GPIO pins can be muxed individually */ |
335 | if (!chip->pinmux_is_supported) |
336 | return 0; |
337 | |
338 | return pinctrl_gpio_request(gc, offset); |
339 | } |
340 | |
341 | static void iproc_gpio_free(struct gpio_chip *gc, unsigned offset) |
342 | { |
343 | struct iproc_gpio *chip = gpiochip_get_data(gc); |
344 | |
345 | if (!chip->pinmux_is_supported) |
346 | return; |
347 | |
348 | pinctrl_gpio_free(gc, offset); |
349 | } |
350 | |
351 | static int iproc_gpio_direction_input(struct gpio_chip *gc, unsigned gpio) |
352 | { |
353 | struct iproc_gpio *chip = gpiochip_get_data(gc); |
354 | unsigned long flags; |
355 | |
356 | raw_spin_lock_irqsave(&chip->lock, flags); |
357 | iproc_set_bit(chip, IPROC_GPIO_OUT_EN_OFFSET, gpio, set: false); |
358 | raw_spin_unlock_irqrestore(&chip->lock, flags); |
359 | |
360 | dev_dbg(chip->dev, "gpio:%u set input\n" , gpio); |
361 | |
362 | return 0; |
363 | } |
364 | |
365 | static int iproc_gpio_direction_output(struct gpio_chip *gc, unsigned gpio, |
366 | int val) |
367 | { |
368 | struct iproc_gpio *chip = gpiochip_get_data(gc); |
369 | unsigned long flags; |
370 | |
371 | raw_spin_lock_irqsave(&chip->lock, flags); |
372 | iproc_set_bit(chip, IPROC_GPIO_OUT_EN_OFFSET, gpio, set: true); |
373 | iproc_set_bit(chip, IPROC_GPIO_DATA_OUT_OFFSET, gpio, set: !!(val)); |
374 | raw_spin_unlock_irqrestore(&chip->lock, flags); |
375 | |
376 | dev_dbg(chip->dev, "gpio:%u set output, value:%d\n" , gpio, val); |
377 | |
378 | return 0; |
379 | } |
380 | |
381 | static int iproc_gpio_get_direction(struct gpio_chip *gc, unsigned int gpio) |
382 | { |
383 | struct iproc_gpio *chip = gpiochip_get_data(gc); |
384 | unsigned int offset = IPROC_GPIO_REG(gpio, IPROC_GPIO_OUT_EN_OFFSET); |
385 | unsigned int shift = IPROC_GPIO_SHIFT(gpio); |
386 | |
387 | if (readl(addr: chip->base + offset) & BIT(shift)) |
388 | return GPIO_LINE_DIRECTION_OUT; |
389 | |
390 | return GPIO_LINE_DIRECTION_IN; |
391 | } |
392 | |
393 | static void iproc_gpio_set(struct gpio_chip *gc, unsigned gpio, int val) |
394 | { |
395 | struct iproc_gpio *chip = gpiochip_get_data(gc); |
396 | unsigned long flags; |
397 | |
398 | raw_spin_lock_irqsave(&chip->lock, flags); |
399 | iproc_set_bit(chip, IPROC_GPIO_DATA_OUT_OFFSET, gpio, set: !!(val)); |
400 | raw_spin_unlock_irqrestore(&chip->lock, flags); |
401 | |
402 | dev_dbg(chip->dev, "gpio:%u set, value:%d\n" , gpio, val); |
403 | } |
404 | |
405 | static int iproc_gpio_get(struct gpio_chip *gc, unsigned gpio) |
406 | { |
407 | struct iproc_gpio *chip = gpiochip_get_data(gc); |
408 | unsigned int offset = IPROC_GPIO_REG(gpio, |
409 | IPROC_GPIO_DATA_IN_OFFSET); |
410 | unsigned int shift = IPROC_GPIO_SHIFT(gpio); |
411 | |
412 | return !!(readl(addr: chip->base + offset) & BIT(shift)); |
413 | } |
414 | |
415 | /* |
416 | * Mapping of the iProc PINCONF parameters to the generic pin configuration |
417 | * parameters |
418 | */ |
419 | static const enum pin_config_param iproc_pinconf_disable_map[] = { |
420 | [IPROC_PINCONF_DRIVE_STRENGTH] = PIN_CONFIG_DRIVE_STRENGTH, |
421 | [IPROC_PINCONF_BIAS_DISABLE] = PIN_CONFIG_BIAS_DISABLE, |
422 | [IPROC_PINCONF_BIAS_PULL_UP] = PIN_CONFIG_BIAS_PULL_UP, |
423 | [IPROC_PINCONF_BIAS_PULL_DOWN] = PIN_CONFIG_BIAS_PULL_DOWN, |
424 | }; |
425 | |
426 | static bool iproc_pinconf_param_is_disabled(struct iproc_gpio *chip, |
427 | enum pin_config_param param) |
428 | { |
429 | unsigned int i; |
430 | |
431 | if (!chip->nr_pinconf_disable) |
432 | return false; |
433 | |
434 | for (i = 0; i < chip->nr_pinconf_disable; i++) |
435 | if (chip->pinconf_disable[i] == param) |
436 | return true; |
437 | |
438 | return false; |
439 | } |
440 | |
441 | static int iproc_pinconf_disable_map_create(struct iproc_gpio *chip, |
442 | unsigned long disable_mask) |
443 | { |
444 | unsigned int map_size = ARRAY_SIZE(iproc_pinconf_disable_map); |
445 | unsigned int bit, nbits = 0; |
446 | |
447 | /* figure out total number of PINCONF parameters to disable */ |
448 | for_each_set_bit(bit, &disable_mask, map_size) |
449 | nbits++; |
450 | |
451 | if (!nbits) |
452 | return 0; |
453 | |
454 | /* |
455 | * Allocate an array to store PINCONF parameters that need to be |
456 | * disabled |
457 | */ |
458 | chip->pinconf_disable = devm_kcalloc(dev: chip->dev, n: nbits, |
459 | size: sizeof(*chip->pinconf_disable), |
460 | GFP_KERNEL); |
461 | if (!chip->pinconf_disable) |
462 | return -ENOMEM; |
463 | |
464 | chip->nr_pinconf_disable = nbits; |
465 | |
466 | /* now store these parameters */ |
467 | nbits = 0; |
468 | for_each_set_bit(bit, &disable_mask, map_size) |
469 | chip->pinconf_disable[nbits++] = iproc_pinconf_disable_map[bit]; |
470 | |
471 | return 0; |
472 | } |
473 | |
474 | static int iproc_get_groups_count(struct pinctrl_dev *pctldev) |
475 | { |
476 | return 1; |
477 | } |
478 | |
479 | /* |
480 | * Only one group: "gpio_grp", since this local pinctrl device only performs |
481 | * GPIO specific PINCONF configurations |
482 | */ |
483 | static const char *iproc_get_group_name(struct pinctrl_dev *pctldev, |
484 | unsigned selector) |
485 | { |
486 | return "gpio_grp" ; |
487 | } |
488 | |
489 | static const struct pinctrl_ops iproc_pctrl_ops = { |
490 | .get_groups_count = iproc_get_groups_count, |
491 | .get_group_name = iproc_get_group_name, |
492 | .dt_node_to_map = pinconf_generic_dt_node_to_map_pin, |
493 | .dt_free_map = pinctrl_utils_free_map, |
494 | }; |
495 | |
496 | static int iproc_gpio_set_pull(struct iproc_gpio *chip, unsigned gpio, |
497 | bool disable, bool pull_up) |
498 | { |
499 | void __iomem *base; |
500 | unsigned long flags; |
501 | unsigned int shift; |
502 | u32 val_1, val_2; |
503 | |
504 | raw_spin_lock_irqsave(&chip->lock, flags); |
505 | if (chip->io_ctrl_type == IOCTRL_TYPE_CDRU) { |
506 | base = chip->io_ctrl; |
507 | shift = IPROC_GPIO_SHIFT(gpio); |
508 | |
509 | val_1 = readl(addr: base + IPROC_GPIO_PULL_UP_OFFSET); |
510 | val_2 = readl(addr: base + IPROC_GPIO_PULL_DN_OFFSET); |
511 | if (disable) { |
512 | /* no pull-up or pull-down */ |
513 | val_1 &= ~BIT(shift); |
514 | val_2 &= ~BIT(shift); |
515 | } else if (pull_up) { |
516 | val_1 |= BIT(shift); |
517 | val_2 &= ~BIT(shift); |
518 | } else { |
519 | val_1 &= ~BIT(shift); |
520 | val_2 |= BIT(shift); |
521 | } |
522 | writel(val: val_1, addr: base + IPROC_GPIO_PULL_UP_OFFSET); |
523 | writel(val: val_2, addr: base + IPROC_GPIO_PULL_DN_OFFSET); |
524 | } else { |
525 | if (disable) { |
526 | iproc_set_bit(chip, IPROC_GPIO_RES_EN_OFFSET, gpio, |
527 | set: false); |
528 | } else { |
529 | iproc_set_bit(chip, IPROC_GPIO_PAD_RES_OFFSET, gpio, |
530 | set: pull_up); |
531 | iproc_set_bit(chip, IPROC_GPIO_RES_EN_OFFSET, gpio, |
532 | set: true); |
533 | } |
534 | } |
535 | |
536 | raw_spin_unlock_irqrestore(&chip->lock, flags); |
537 | dev_dbg(chip->dev, "gpio:%u set pullup:%d\n" , gpio, pull_up); |
538 | |
539 | return 0; |
540 | } |
541 | |
542 | static void iproc_gpio_get_pull(struct iproc_gpio *chip, unsigned gpio, |
543 | bool *disable, bool *pull_up) |
544 | { |
545 | void __iomem *base; |
546 | unsigned long flags; |
547 | unsigned int shift; |
548 | u32 val_1, val_2; |
549 | |
550 | raw_spin_lock_irqsave(&chip->lock, flags); |
551 | if (chip->io_ctrl_type == IOCTRL_TYPE_CDRU) { |
552 | base = chip->io_ctrl; |
553 | shift = IPROC_GPIO_SHIFT(gpio); |
554 | |
555 | val_1 = readl(addr: base + IPROC_GPIO_PULL_UP_OFFSET) & BIT(shift); |
556 | val_2 = readl(addr: base + IPROC_GPIO_PULL_DN_OFFSET) & BIT(shift); |
557 | |
558 | *pull_up = val_1 ? true : false; |
559 | *disable = (val_1 | val_2) ? false : true; |
560 | |
561 | } else { |
562 | *disable = !iproc_get_bit(chip, IPROC_GPIO_RES_EN_OFFSET, gpio); |
563 | *pull_up = iproc_get_bit(chip, IPROC_GPIO_PAD_RES_OFFSET, gpio); |
564 | } |
565 | raw_spin_unlock_irqrestore(&chip->lock, flags); |
566 | } |
567 | |
568 | #define DRV_STRENGTH_OFFSET(gpio, bit, type) ((type) == IOCTRL_TYPE_AON ? \ |
569 | ((2 - (bit)) * 4 + IPROC_GPIO_DRV_CTRL_OFFSET) : \ |
570 | ((type) == IOCTRL_TYPE_CDRU) ? \ |
571 | ((bit) * 4 + IPROC_GPIO_DRV_CTRL_OFFSET) : \ |
572 | ((bit) * 4 + IPROC_GPIO_REG(gpio, IPROC_GPIO_ASIU_DRV0_CTRL_OFFSET))) |
573 | |
574 | static int iproc_gpio_set_strength(struct iproc_gpio *chip, unsigned gpio, |
575 | unsigned strength) |
576 | { |
577 | void __iomem *base; |
578 | unsigned int i, offset, shift; |
579 | u32 val; |
580 | unsigned long flags; |
581 | |
582 | /* make sure drive strength is supported */ |
583 | if (strength < 2 || strength > 16 || (strength % 2)) |
584 | return -ENOTSUPP; |
585 | |
586 | if (chip->io_ctrl) { |
587 | base = chip->io_ctrl; |
588 | } else { |
589 | base = chip->base; |
590 | } |
591 | |
592 | shift = IPROC_GPIO_SHIFT(gpio); |
593 | |
594 | dev_dbg(chip->dev, "gpio:%u set drive strength:%d mA\n" , gpio, |
595 | strength); |
596 | |
597 | raw_spin_lock_irqsave(&chip->lock, flags); |
598 | strength = (strength / 2) - 1; |
599 | for (i = 0; i < GPIO_DRV_STRENGTH_BITS; i++) { |
600 | offset = DRV_STRENGTH_OFFSET(gpio, i, chip->io_ctrl_type); |
601 | val = readl(addr: base + offset); |
602 | val &= ~BIT(shift); |
603 | val |= ((strength >> i) & 0x1) << shift; |
604 | writel(val, addr: base + offset); |
605 | } |
606 | raw_spin_unlock_irqrestore(&chip->lock, flags); |
607 | |
608 | return 0; |
609 | } |
610 | |
611 | static int iproc_gpio_get_strength(struct iproc_gpio *chip, unsigned gpio, |
612 | u16 *strength) |
613 | { |
614 | void __iomem *base; |
615 | unsigned int i, offset, shift; |
616 | u32 val; |
617 | unsigned long flags; |
618 | |
619 | if (chip->io_ctrl) { |
620 | base = chip->io_ctrl; |
621 | } else { |
622 | base = chip->base; |
623 | } |
624 | |
625 | shift = IPROC_GPIO_SHIFT(gpio); |
626 | |
627 | raw_spin_lock_irqsave(&chip->lock, flags); |
628 | *strength = 0; |
629 | for (i = 0; i < GPIO_DRV_STRENGTH_BITS; i++) { |
630 | offset = DRV_STRENGTH_OFFSET(gpio, i, chip->io_ctrl_type); |
631 | val = readl(addr: base + offset) & BIT(shift); |
632 | val >>= shift; |
633 | *strength += (val << i); |
634 | } |
635 | |
636 | /* convert to mA */ |
637 | *strength = (*strength + 1) * 2; |
638 | raw_spin_unlock_irqrestore(&chip->lock, flags); |
639 | |
640 | return 0; |
641 | } |
642 | |
643 | static int iproc_pin_config_get(struct pinctrl_dev *pctldev, unsigned pin, |
644 | unsigned long *config) |
645 | { |
646 | struct iproc_gpio *chip = pinctrl_dev_get_drvdata(pctldev); |
647 | enum pin_config_param param = pinconf_to_config_param(config: *config); |
648 | unsigned gpio = iproc_pin_to_gpio(pin); |
649 | u16 arg; |
650 | bool disable, pull_up; |
651 | int ret; |
652 | |
653 | if (iproc_pinconf_param_is_disabled(chip, param)) |
654 | return -ENOTSUPP; |
655 | |
656 | switch (param) { |
657 | case PIN_CONFIG_BIAS_DISABLE: |
658 | iproc_gpio_get_pull(chip, gpio, disable: &disable, pull_up: &pull_up); |
659 | if (disable) |
660 | return 0; |
661 | else |
662 | return -EINVAL; |
663 | |
664 | case PIN_CONFIG_BIAS_PULL_UP: |
665 | iproc_gpio_get_pull(chip, gpio, disable: &disable, pull_up: &pull_up); |
666 | if (!disable && pull_up) |
667 | return 0; |
668 | else |
669 | return -EINVAL; |
670 | |
671 | case PIN_CONFIG_BIAS_PULL_DOWN: |
672 | iproc_gpio_get_pull(chip, gpio, disable: &disable, pull_up: &pull_up); |
673 | if (!disable && !pull_up) |
674 | return 0; |
675 | else |
676 | return -EINVAL; |
677 | |
678 | case PIN_CONFIG_DRIVE_STRENGTH: |
679 | ret = iproc_gpio_get_strength(chip, gpio, strength: &arg); |
680 | if (ret) |
681 | return ret; |
682 | *config = pinconf_to_config_packed(param, argument: arg); |
683 | |
684 | return 0; |
685 | |
686 | default: |
687 | return -ENOTSUPP; |
688 | } |
689 | |
690 | return -ENOTSUPP; |
691 | } |
692 | |
693 | static int iproc_pin_config_set(struct pinctrl_dev *pctldev, unsigned pin, |
694 | unsigned long *configs, unsigned num_configs) |
695 | { |
696 | struct iproc_gpio *chip = pinctrl_dev_get_drvdata(pctldev); |
697 | enum pin_config_param param; |
698 | u32 arg; |
699 | unsigned i, gpio = iproc_pin_to_gpio(pin); |
700 | int ret = -ENOTSUPP; |
701 | |
702 | for (i = 0; i < num_configs; i++) { |
703 | param = pinconf_to_config_param(config: configs[i]); |
704 | |
705 | if (iproc_pinconf_param_is_disabled(chip, param)) |
706 | return -ENOTSUPP; |
707 | |
708 | arg = pinconf_to_config_argument(config: configs[i]); |
709 | |
710 | switch (param) { |
711 | case PIN_CONFIG_BIAS_DISABLE: |
712 | ret = iproc_gpio_set_pull(chip, gpio, disable: true, pull_up: false); |
713 | if (ret < 0) |
714 | goto out; |
715 | break; |
716 | |
717 | case PIN_CONFIG_BIAS_PULL_UP: |
718 | ret = iproc_gpio_set_pull(chip, gpio, disable: false, pull_up: true); |
719 | if (ret < 0) |
720 | goto out; |
721 | break; |
722 | |
723 | case PIN_CONFIG_BIAS_PULL_DOWN: |
724 | ret = iproc_gpio_set_pull(chip, gpio, disable: false, pull_up: false); |
725 | if (ret < 0) |
726 | goto out; |
727 | break; |
728 | |
729 | case PIN_CONFIG_DRIVE_STRENGTH: |
730 | ret = iproc_gpio_set_strength(chip, gpio, strength: arg); |
731 | if (ret < 0) |
732 | goto out; |
733 | break; |
734 | |
735 | default: |
736 | dev_err(chip->dev, "invalid configuration\n" ); |
737 | return -ENOTSUPP; |
738 | } |
739 | } /* for each config */ |
740 | |
741 | out: |
742 | return ret; |
743 | } |
744 | |
745 | static const struct pinconf_ops iproc_pconf_ops = { |
746 | .is_generic = true, |
747 | .pin_config_get = iproc_pin_config_get, |
748 | .pin_config_set = iproc_pin_config_set, |
749 | }; |
750 | |
751 | /* |
752 | * Iproc GPIO controller supports some PINCONF related configurations such as |
753 | * pull up, pull down, and drive strength, when the pin is configured to GPIO |
754 | * |
755 | * Here a local pinctrl device is created with simple 1-to-1 pin mapping to the |
756 | * local GPIO pins |
757 | */ |
758 | static int iproc_gpio_register_pinconf(struct iproc_gpio *chip) |
759 | { |
760 | struct pinctrl_desc *pctldesc = &chip->pctldesc; |
761 | struct pinctrl_pin_desc *pins; |
762 | struct gpio_chip *gc = &chip->gc; |
763 | int i; |
764 | |
765 | pins = devm_kcalloc(dev: chip->dev, n: gc->ngpio, size: sizeof(*pins), GFP_KERNEL); |
766 | if (!pins) |
767 | return -ENOMEM; |
768 | |
769 | for (i = 0; i < gc->ngpio; i++) { |
770 | pins[i].number = i; |
771 | pins[i].name = devm_kasprintf(dev: chip->dev, GFP_KERNEL, |
772 | fmt: "gpio-%d" , i); |
773 | if (!pins[i].name) |
774 | return -ENOMEM; |
775 | } |
776 | |
777 | pctldesc->name = dev_name(dev: chip->dev); |
778 | pctldesc->pctlops = &iproc_pctrl_ops; |
779 | pctldesc->pins = pins; |
780 | pctldesc->npins = gc->ngpio; |
781 | pctldesc->confops = &iproc_pconf_ops; |
782 | |
783 | chip->pctl = devm_pinctrl_register(dev: chip->dev, pctldesc, driver_data: chip); |
784 | if (IS_ERR(ptr: chip->pctl)) { |
785 | dev_err(chip->dev, "unable to register pinctrl device\n" ); |
786 | return PTR_ERR(ptr: chip->pctl); |
787 | } |
788 | |
789 | return 0; |
790 | } |
791 | |
792 | static const struct of_device_id iproc_gpio_of_match[] = { |
793 | { .compatible = "brcm,iproc-gpio" }, |
794 | { .compatible = "brcm,cygnus-ccm-gpio" }, |
795 | { .compatible = "brcm,cygnus-asiu-gpio" }, |
796 | { .compatible = "brcm,cygnus-crmu-gpio" }, |
797 | { .compatible = "brcm,iproc-nsp-gpio" }, |
798 | { .compatible = "brcm,iproc-stingray-gpio" }, |
799 | { /* sentinel */ } |
800 | }; |
801 | |
802 | static int iproc_gpio_probe(struct platform_device *pdev) |
803 | { |
804 | struct device *dev = &pdev->dev; |
805 | struct resource *res; |
806 | struct iproc_gpio *chip; |
807 | struct gpio_chip *gc; |
808 | u32 ngpios, pinconf_disable_mask = 0; |
809 | int irq, ret; |
810 | bool no_pinconf = false; |
811 | enum iproc_pinconf_ctrl_type io_ctrl_type = IOCTRL_TYPE_INVALID; |
812 | |
813 | /* NSP does not support drive strength config */ |
814 | if (of_device_is_compatible(device: dev->of_node, "brcm,iproc-nsp-gpio" )) |
815 | pinconf_disable_mask = BIT(IPROC_PINCONF_DRIVE_STRENGTH); |
816 | /* Stingray does not support pinconf in this controller */ |
817 | else if (of_device_is_compatible(device: dev->of_node, |
818 | "brcm,iproc-stingray-gpio" )) |
819 | no_pinconf = true; |
820 | |
821 | chip = devm_kzalloc(dev, size: sizeof(*chip), GFP_KERNEL); |
822 | if (!chip) |
823 | return -ENOMEM; |
824 | |
825 | chip->dev = dev; |
826 | platform_set_drvdata(pdev, data: chip); |
827 | |
828 | chip->base = devm_platform_ioremap_resource(pdev, index: 0); |
829 | if (IS_ERR(ptr: chip->base)) { |
830 | dev_err(dev, "unable to map I/O memory\n" ); |
831 | return PTR_ERR(ptr: chip->base); |
832 | } |
833 | |
834 | res = platform_get_resource(pdev, IORESOURCE_MEM, 1); |
835 | if (res) { |
836 | chip->io_ctrl = devm_ioremap_resource(dev, res); |
837 | if (IS_ERR(ptr: chip->io_ctrl)) |
838 | return PTR_ERR(ptr: chip->io_ctrl); |
839 | if (of_device_is_compatible(device: dev->of_node, |
840 | "brcm,cygnus-ccm-gpio" )) |
841 | io_ctrl_type = IOCTRL_TYPE_CDRU; |
842 | else |
843 | io_ctrl_type = IOCTRL_TYPE_AON; |
844 | } |
845 | |
846 | chip->io_ctrl_type = io_ctrl_type; |
847 | |
848 | if (of_property_read_u32(np: dev->of_node, propname: "ngpios" , out_value: &ngpios)) { |
849 | dev_err(&pdev->dev, "missing ngpios DT property\n" ); |
850 | return -ENODEV; |
851 | } |
852 | |
853 | raw_spin_lock_init(&chip->lock); |
854 | |
855 | gc = &chip->gc; |
856 | gc->base = -1; |
857 | gc->ngpio = ngpios; |
858 | chip->num_banks = (ngpios + NGPIOS_PER_BANK - 1) / NGPIOS_PER_BANK; |
859 | gc->label = dev_name(dev); |
860 | gc->parent = dev; |
861 | gc->request = iproc_gpio_request; |
862 | gc->free = iproc_gpio_free; |
863 | gc->direction_input = iproc_gpio_direction_input; |
864 | gc->direction_output = iproc_gpio_direction_output; |
865 | gc->get_direction = iproc_gpio_get_direction; |
866 | gc->set = iproc_gpio_set; |
867 | gc->get = iproc_gpio_get; |
868 | |
869 | chip->pinmux_is_supported = of_property_read_bool(np: dev->of_node, |
870 | propname: "gpio-ranges" ); |
871 | |
872 | /* optional GPIO interrupt support */ |
873 | irq = platform_get_irq_optional(pdev, 0); |
874 | if (irq > 0) { |
875 | struct gpio_irq_chip *girq; |
876 | |
877 | girq = &gc->irq; |
878 | gpio_irq_chip_set_chip(girq, chip: &iproc_gpio_irq_chip); |
879 | girq->parent_handler = iproc_gpio_irq_handler; |
880 | girq->num_parents = 1; |
881 | girq->parents = devm_kcalloc(dev, n: 1, |
882 | size: sizeof(*girq->parents), |
883 | GFP_KERNEL); |
884 | if (!girq->parents) |
885 | return -ENOMEM; |
886 | girq->parents[0] = irq; |
887 | girq->default_type = IRQ_TYPE_NONE; |
888 | girq->handler = handle_bad_irq; |
889 | } |
890 | |
891 | ret = gpiochip_add_data(gc, chip); |
892 | if (ret < 0) |
893 | return dev_err_probe(dev, err: ret, fmt: "unable to add GPIO chip\n" ); |
894 | |
895 | if (!no_pinconf) { |
896 | ret = iproc_gpio_register_pinconf(chip); |
897 | if (ret) { |
898 | dev_err(dev, "unable to register pinconf\n" ); |
899 | goto err_rm_gpiochip; |
900 | } |
901 | |
902 | if (pinconf_disable_mask) { |
903 | ret = iproc_pinconf_disable_map_create(chip, |
904 | disable_mask: pinconf_disable_mask); |
905 | if (ret) { |
906 | dev_err(dev, |
907 | "unable to create pinconf disable map\n" ); |
908 | goto err_rm_gpiochip; |
909 | } |
910 | } |
911 | } |
912 | |
913 | return 0; |
914 | |
915 | err_rm_gpiochip: |
916 | gpiochip_remove(gc); |
917 | |
918 | return ret; |
919 | } |
920 | |
921 | static struct platform_driver iproc_gpio_driver = { |
922 | .driver = { |
923 | .name = "iproc-gpio" , |
924 | .of_match_table = iproc_gpio_of_match, |
925 | }, |
926 | .probe = iproc_gpio_probe, |
927 | }; |
928 | |
929 | static int __init iproc_gpio_init(void) |
930 | { |
931 | return platform_driver_register(&iproc_gpio_driver); |
932 | } |
933 | arch_initcall_sync(iproc_gpio_init); |
934 | |