aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/pinctrl/bcm/Kconfig22
-rw-r--r--drivers/pinctrl/bcm/Makefile1
-rw-r--r--drivers/pinctrl/bcm/pinctrl-cygnus-gpio.c907
3 files changed, 930 insertions, 0 deletions
diff --git a/drivers/pinctrl/bcm/Kconfig b/drivers/pinctrl/bcm/Kconfig
index eb1320152a87..cd11d4d9ad58 100644
--- a/drivers/pinctrl/bcm/Kconfig
+++ b/drivers/pinctrl/bcm/Kconfig
@@ -20,6 +20,28 @@ config PINCTRL_BCM2835
20 select PINMUX 20 select PINMUX
21 select PINCONF 21 select PINCONF
22 22
23config PINCTRL_CYGNUS_GPIO
24 bool "Broadcom Cygnus GPIO (with PINCONF) driver"
25 depends on OF_GPIO && ARCH_BCM_CYGNUS
26 select GPIOLIB_IRQCHIP
27 select PINCONF
28 select GENERIC_PINCONF
29 default ARCH_BCM_CYGNUS
30 help
31 Say yes here to enable the Broadcom Cygnus GPIO driver.
32
33 The Broadcom Cygnus SoC has 3 GPIO controllers including the ASIU
34 GPIO controller (ASIU), the chipCommonG GPIO controller (CCM), and
35 the always-ON GPIO controller (CRMU/AON). All 3 GPIO controllers are
36 supported by this driver.
37
38 All 3 Cygnus GPIO controllers support basic PINCONF functions such
39 as bias pull up, pull down, and drive strength configurations, when
40 these pins are muxed to GPIO.
41
42 Pins from the ASIU GPIO can be individually muxed to GPIO function,
43 through interaction with the Cygnus IOMUX controller.
44
23config PINCTRL_CYGNUS_MUX 45config PINCTRL_CYGNUS_MUX
24 bool "Broadcom Cygnus IOMUX driver" 46 bool "Broadcom Cygnus IOMUX driver"
25 depends on (ARCH_BCM_CYGNUS || COMPILE_TEST) 47 depends on (ARCH_BCM_CYGNUS || COMPILE_TEST)
diff --git a/drivers/pinctrl/bcm/Makefile b/drivers/pinctrl/bcm/Makefile
index bb6beb66d962..2b2f70ee804c 100644
--- a/drivers/pinctrl/bcm/Makefile
+++ b/drivers/pinctrl/bcm/Makefile
@@ -2,4 +2,5 @@
2 2
3obj-$(CONFIG_PINCTRL_BCM281XX) += pinctrl-bcm281xx.o 3obj-$(CONFIG_PINCTRL_BCM281XX) += pinctrl-bcm281xx.o
4obj-$(CONFIG_PINCTRL_BCM2835) += pinctrl-bcm2835.o 4obj-$(CONFIG_PINCTRL_BCM2835) += pinctrl-bcm2835.o
5obj-$(CONFIG_PINCTRL_CYGNUS_GPIO) += pinctrl-cygnus-gpio.o
5obj-$(CONFIG_PINCTRL_CYGNUS_MUX) += pinctrl-cygnus-mux.o 6obj-$(CONFIG_PINCTRL_CYGNUS_MUX) += pinctrl-cygnus-mux.o
diff --git a/drivers/pinctrl/bcm/pinctrl-cygnus-gpio.c b/drivers/pinctrl/bcm/pinctrl-cygnus-gpio.c
new file mode 100644
index 000000000000..4ad5c1a996e3
--- /dev/null
+++ b/drivers/pinctrl/bcm/pinctrl-cygnus-gpio.c
@@ -0,0 +1,907 @@
1/*
2 * Copyright (C) 2014-2015 Broadcom Corporation
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation version 2.
7 *
8 * This program is distributed "as is" WITHOUT ANY WARRANTY of any
9 * kind, whether express or implied; without even the implied warranty
10 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * This file contains the Broadcom Cygnus GPIO driver that supports 3
14 * GPIO controllers on Cygnus including the ASIU GPIO controller, the
15 * chipCommonG GPIO controller, and the always-on GPIO controller. Basic
16 * PINCONF such as bias pull up/down, and drive strength are also supported
17 * in this driver.
18 *
19 * Pins from the ASIU GPIO can be individually muxed to GPIO function,
20 * through the interaction with the Cygnus IOMUX controller
21 */
22
23#include <linux/kernel.h>
24#include <linux/slab.h>
25#include <linux/interrupt.h>
26#include <linux/io.h>
27#include <linux/gpio.h>
28#include <linux/ioport.h>
29#include <linux/of_device.h>
30#include <linux/of_irq.h>
31#include <linux/pinctrl/pinctrl.h>
32#include <linux/pinctrl/pinmux.h>
33#include <linux/pinctrl/pinconf.h>
34#include <linux/pinctrl/pinconf-generic.h>
35
36#include "../pinctrl-utils.h"
37
38#define CYGNUS_GPIO_DATA_IN_OFFSET 0x00
39#define CYGNUS_GPIO_DATA_OUT_OFFSET 0x04
40#define CYGNUS_GPIO_OUT_EN_OFFSET 0x08
41#define CYGNUS_GPIO_IN_TYPE_OFFSET 0x0c
42#define CYGNUS_GPIO_INT_DE_OFFSET 0x10
43#define CYGNUS_GPIO_INT_EDGE_OFFSET 0x14
44#define CYGNUS_GPIO_INT_MSK_OFFSET 0x18
45#define CYGNUS_GPIO_INT_STAT_OFFSET 0x1c
46#define CYGNUS_GPIO_INT_MSTAT_OFFSET 0x20
47#define CYGNUS_GPIO_INT_CLR_OFFSET 0x24
48#define CYGNUS_GPIO_PAD_RES_OFFSET 0x34
49#define CYGNUS_GPIO_RES_EN_OFFSET 0x38
50
51/* drive strength control for ASIU GPIO */
52#define CYGNUS_GPIO_ASIU_DRV0_CTRL_OFFSET 0x58
53
54/* drive strength control for CCM/CRMU (AON) GPIO */
55#define CYGNUS_GPIO_DRV0_CTRL_OFFSET 0x00
56
57#define GPIO_BANK_SIZE 0x200
58#define NGPIOS_PER_BANK 32
59#define GPIO_BANK(pin) ((pin) / NGPIOS_PER_BANK)
60
61#define CYGNUS_GPIO_REG(pin, reg) (GPIO_BANK(pin) * GPIO_BANK_SIZE + (reg))
62#define CYGNUS_GPIO_SHIFT(pin) ((pin) % NGPIOS_PER_BANK)
63
64#define GPIO_DRV_STRENGTH_BIT_SHIFT 20
65#define GPIO_DRV_STRENGTH_BITS 3
66#define GPIO_DRV_STRENGTH_BIT_MASK ((1 << GPIO_DRV_STRENGTH_BITS) - 1)
67
68/*
69 * Cygnus GPIO core
70 *
71 * @dev: pointer to device
72 * @base: I/O register base for Cygnus GPIO controller
73 * @io_ctrl: I/O register base for certain type of Cygnus GPIO controller that
74 * has the PINCONF support implemented outside of the GPIO block
75 * @lock: lock to protect access to I/O registers
76 * @gc: GPIO chip
77 * @num_banks: number of GPIO banks, each bank supports up to 32 GPIOs
78 * @pinmux_is_supported: flag to indicate this GPIO controller contains pins
79 * that can be individually muxed to GPIO
80 * @pctl: pointer to pinctrl_dev
81 * @pctldesc: pinctrl descriptor
82 */
83struct cygnus_gpio {
84 struct device *dev;
85
86 void __iomem *base;
87 void __iomem *io_ctrl;
88
89 spinlock_t lock;
90
91 struct gpio_chip gc;
92 unsigned num_banks;
93
94 bool pinmux_is_supported;
95
96 struct pinctrl_dev *pctl;
97 struct pinctrl_desc pctldesc;
98};
99
100static inline struct cygnus_gpio *to_cygnus_gpio(struct gpio_chip *gc)
101{
102 return container_of(gc, struct cygnus_gpio, gc);
103}
104
105/*
106 * Mapping from PINCONF pins to GPIO pins is 1-to-1
107 */
108static inline unsigned cygnus_pin_to_gpio(unsigned pin)
109{
110 return pin;
111}
112
113/**
114 * cygnus_set_bit - set or clear one bit (corresponding to the GPIO pin) in a
115 * Cygnus GPIO register
116 *
117 * @cygnus_gpio: Cygnus GPIO device
118 * @reg: register offset
119 * @gpio: GPIO pin
120 * @set: set or clear
121 */
122static inline void cygnus_set_bit(struct cygnus_gpio *chip, unsigned int reg,
123 unsigned gpio, bool set)
124{
125 unsigned int offset = CYGNUS_GPIO_REG(gpio, reg);
126 unsigned int shift = CYGNUS_GPIO_SHIFT(gpio);
127 u32 val;
128
129 val = readl(chip->base + offset);
130 if (set)
131 val |= BIT(shift);
132 else
133 val &= ~BIT(shift);
134 writel(val, chip->base + offset);
135}
136
137static inline bool cygnus_get_bit(struct cygnus_gpio *chip, unsigned int reg,
138 unsigned gpio)
139{
140 unsigned int offset = CYGNUS_GPIO_REG(gpio, reg);
141 unsigned int shift = CYGNUS_GPIO_SHIFT(gpio);
142
143 return !!(readl(chip->base + offset) & BIT(shift));
144}
145
146static void cygnus_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
147{
148 struct gpio_chip *gc = irq_desc_get_handler_data(desc);
149 struct cygnus_gpio *chip = to_cygnus_gpio(gc);
150 struct irq_chip *irq_chip = irq_desc_get_chip(desc);
151 int i, bit;
152
153 chained_irq_enter(irq_chip, desc);
154
155 /* go through the entire GPIO banks and handle all interrupts */
156 for (i = 0; i < chip->num_banks; i++) {
157 unsigned long val = readl(chip->base + (i * GPIO_BANK_SIZE) +
158 CYGNUS_GPIO_INT_MSTAT_OFFSET);
159
160 for_each_set_bit(bit, &val, NGPIOS_PER_BANK) {
161 unsigned pin = NGPIOS_PER_BANK * i + bit;
162 int child_irq = irq_find_mapping(gc->irqdomain, pin);
163
164 /*
165 * Clear the interrupt before invoking the
166 * handler, so we do not leave any window
167 */
168 writel(BIT(bit), chip->base + (i * GPIO_BANK_SIZE) +
169 CYGNUS_GPIO_INT_CLR_OFFSET);
170
171 generic_handle_irq(child_irq);
172 }
173 }
174
175 chained_irq_exit(irq_chip, desc);
176}
177
178
179static void cygnus_gpio_irq_ack(struct irq_data *d)
180{
181 struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
182 struct cygnus_gpio *chip = to_cygnus_gpio(gc);
183 unsigned gpio = d->hwirq;
184 unsigned int offset = CYGNUS_GPIO_REG(gpio,
185 CYGNUS_GPIO_INT_CLR_OFFSET);
186 unsigned int shift = CYGNUS_GPIO_SHIFT(gpio);
187 u32 val = BIT(shift);
188
189 writel(val, chip->base + offset);
190}
191
192/**
193 * cygnus_gpio_irq_set_mask - mask/unmask a GPIO interrupt
194 *
195 * @d: IRQ chip data
196 * @unmask: mask/unmask GPIO interrupt
197 */
198static void cygnus_gpio_irq_set_mask(struct irq_data *d, bool unmask)
199{
200 struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
201 struct cygnus_gpio *chip = to_cygnus_gpio(gc);
202 unsigned gpio = d->hwirq;
203
204 cygnus_set_bit(chip, CYGNUS_GPIO_INT_MSK_OFFSET, gpio, unmask);
205}
206
207static void cygnus_gpio_irq_mask(struct irq_data *d)
208{
209 struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
210 struct cygnus_gpio *chip = to_cygnus_gpio(gc);
211 unsigned long flags;
212
213 spin_lock_irqsave(&chip->lock, flags);
214 cygnus_gpio_irq_set_mask(d, false);
215 spin_unlock_irqrestore(&chip->lock, flags);
216}
217
218static void cygnus_gpio_irq_unmask(struct irq_data *d)
219{
220 struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
221 struct cygnus_gpio *chip = to_cygnus_gpio(gc);
222 unsigned long flags;
223
224 spin_lock_irqsave(&chip->lock, flags);
225 cygnus_gpio_irq_set_mask(d, true);
226 spin_unlock_irqrestore(&chip->lock, flags);
227}
228
229static int cygnus_gpio_irq_set_type(struct irq_data *d, unsigned int type)
230{
231 struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
232 struct cygnus_gpio *chip = to_cygnus_gpio(gc);
233 unsigned gpio = d->hwirq;
234 bool level_triggered = false;
235 bool dual_edge = false;
236 bool rising_or_high = false;
237 unsigned long flags;
238
239 switch (type & IRQ_TYPE_SENSE_MASK) {
240 case IRQ_TYPE_EDGE_RISING:
241 rising_or_high = true;
242 break;
243
244 case IRQ_TYPE_EDGE_FALLING:
245 break;
246
247 case IRQ_TYPE_EDGE_BOTH:
248 dual_edge = true;
249 break;
250
251 case IRQ_TYPE_LEVEL_HIGH:
252 level_triggered = true;
253 rising_or_high = true;
254 break;
255
256 case IRQ_TYPE_LEVEL_LOW:
257 level_triggered = true;
258 break;
259
260 default:
261 dev_err(chip->dev, "invalid GPIO IRQ type 0x%x\n",
262 type);
263 return -EINVAL;
264 }
265
266 spin_lock_irqsave(&chip->lock, flags);
267 cygnus_set_bit(chip, CYGNUS_GPIO_IN_TYPE_OFFSET, gpio,
268 level_triggered);
269 cygnus_set_bit(chip, CYGNUS_GPIO_INT_DE_OFFSET, gpio, dual_edge);
270 cygnus_set_bit(chip, CYGNUS_GPIO_INT_EDGE_OFFSET, gpio,
271 rising_or_high);
272 spin_unlock_irqrestore(&chip->lock, flags);
273
274 dev_dbg(chip->dev,
275 "gpio:%u level_triggered:%d dual_edge:%d rising_or_high:%d\n",
276 gpio, level_triggered, dual_edge, rising_or_high);
277
278 return 0;
279}
280
281static struct irq_chip cygnus_gpio_irq_chip = {
282 .name = "bcm-cygnus-gpio",
283 .irq_ack = cygnus_gpio_irq_ack,
284 .irq_mask = cygnus_gpio_irq_mask,
285 .irq_unmask = cygnus_gpio_irq_unmask,
286 .irq_set_type = cygnus_gpio_irq_set_type,
287};
288
289/*
290 * Request the Cygnus IOMUX pinmux controller to mux individual pins to GPIO
291 */
292static int cygnus_gpio_request(struct gpio_chip *gc, unsigned offset)
293{
294 struct cygnus_gpio *chip = to_cygnus_gpio(gc);
295 unsigned gpio = gc->base + offset;
296
297 /* not all Cygnus GPIO pins can be muxed individually */
298 if (!chip->pinmux_is_supported)
299 return 0;
300
301 return pinctrl_request_gpio(gpio);
302}
303
304static void cygnus_gpio_free(struct gpio_chip *gc, unsigned offset)
305{
306 struct cygnus_gpio *chip = to_cygnus_gpio(gc);
307 unsigned gpio = gc->base + offset;
308
309 if (!chip->pinmux_is_supported)
310 return;
311
312 pinctrl_free_gpio(gpio);
313}
314
315static int cygnus_gpio_direction_input(struct gpio_chip *gc, unsigned gpio)
316{
317 struct cygnus_gpio *chip = to_cygnus_gpio(gc);
318 unsigned long flags;
319
320 spin_lock_irqsave(&chip->lock, flags);
321 cygnus_set_bit(chip, CYGNUS_GPIO_OUT_EN_OFFSET, gpio, false);
322 spin_unlock_irqrestore(&chip->lock, flags);
323
324 dev_dbg(chip->dev, "gpio:%u set input\n", gpio);
325
326 return 0;
327}
328
329static int cygnus_gpio_direction_output(struct gpio_chip *gc, unsigned gpio,
330 int val)
331{
332 struct cygnus_gpio *chip = to_cygnus_gpio(gc);
333 unsigned long flags;
334
335 spin_lock_irqsave(&chip->lock, flags);
336 cygnus_set_bit(chip, CYGNUS_GPIO_OUT_EN_OFFSET, gpio, true);
337 cygnus_set_bit(chip, CYGNUS_GPIO_DATA_OUT_OFFSET, gpio, !!(val));
338 spin_unlock_irqrestore(&chip->lock, flags);
339
340 dev_dbg(chip->dev, "gpio:%u set output, value:%d\n", gpio, val);
341
342 return 0;
343}
344
345static void cygnus_gpio_set(struct gpio_chip *gc, unsigned gpio, int val)
346{
347 struct cygnus_gpio *chip = to_cygnus_gpio(gc);
348 unsigned long flags;
349
350 spin_lock_irqsave(&chip->lock, flags);
351 cygnus_set_bit(chip, CYGNUS_GPIO_DATA_OUT_OFFSET, gpio, !!(val));
352 spin_unlock_irqrestore(&chip->lock, flags);
353
354 dev_dbg(chip->dev, "gpio:%u set, value:%d\n", gpio, val);
355}
356
357static int cygnus_gpio_get(struct gpio_chip *gc, unsigned gpio)
358{
359 struct cygnus_gpio *chip = to_cygnus_gpio(gc);
360 unsigned int offset = CYGNUS_GPIO_REG(gpio,
361 CYGNUS_GPIO_DATA_IN_OFFSET);
362 unsigned int shift = CYGNUS_GPIO_SHIFT(gpio);
363
364 return !!(readl(chip->base + offset) & BIT(shift));
365}
366
367static int cygnus_get_groups_count(struct pinctrl_dev *pctldev)
368{
369 return 1;
370}
371
372/*
373 * Only one group: "gpio_grp", since this local pinctrl device only performs
374 * GPIO specific PINCONF configurations
375 */
376static const char *cygnus_get_group_name(struct pinctrl_dev *pctldev,
377 unsigned selector)
378{
379 return "gpio_grp";
380}
381
382static const struct pinctrl_ops cygnus_pctrl_ops = {
383 .get_groups_count = cygnus_get_groups_count,
384 .get_group_name = cygnus_get_group_name,
385 .dt_node_to_map = pinconf_generic_dt_node_to_map_pin,
386 .dt_free_map = pinctrl_utils_dt_free_map,
387};
388
389static int cygnus_gpio_set_pull(struct cygnus_gpio *chip, unsigned gpio,
390 bool disable, bool pull_up)
391{
392 unsigned long flags;
393
394 spin_lock_irqsave(&chip->lock, flags);
395
396 if (disable) {
397 cygnus_set_bit(chip, CYGNUS_GPIO_RES_EN_OFFSET, gpio, false);
398 } else {
399 cygnus_set_bit(chip, CYGNUS_GPIO_PAD_RES_OFFSET, gpio,
400 pull_up);
401 cygnus_set_bit(chip, CYGNUS_GPIO_RES_EN_OFFSET, gpio, true);
402 }
403
404 spin_unlock_irqrestore(&chip->lock, flags);
405
406 dev_dbg(chip->dev, "gpio:%u set pullup:%d\n", gpio, pull_up);
407
408 return 0;
409}
410
411static void cygnus_gpio_get_pull(struct cygnus_gpio *chip, unsigned gpio,
412 bool *disable, bool *pull_up)
413{
414 unsigned long flags;
415
416 spin_lock_irqsave(&chip->lock, flags);
417 *disable = !cygnus_get_bit(chip, CYGNUS_GPIO_RES_EN_OFFSET, gpio);
418 *pull_up = cygnus_get_bit(chip, CYGNUS_GPIO_PAD_RES_OFFSET, gpio);
419 spin_unlock_irqrestore(&chip->lock, flags);
420}
421
422static int cygnus_gpio_set_strength(struct cygnus_gpio *chip, unsigned gpio,
423 unsigned strength)
424{
425 void __iomem *base;
426 unsigned int i, offset, shift;
427 u32 val;
428 unsigned long flags;
429
430 /* make sure drive strength is supported */
431 if (strength < 2 || strength > 16 || (strength % 2))
432 return -ENOTSUPP;
433
434 if (chip->io_ctrl) {
435 base = chip->io_ctrl;
436 offset = CYGNUS_GPIO_DRV0_CTRL_OFFSET;
437 } else {
438 base = chip->base;
439 offset = CYGNUS_GPIO_REG(gpio,
440 CYGNUS_GPIO_ASIU_DRV0_CTRL_OFFSET);
441 }
442
443 shift = CYGNUS_GPIO_SHIFT(gpio);
444
445 dev_dbg(chip->dev, "gpio:%u set drive strength:%d mA\n", gpio,
446 strength);
447
448 spin_lock_irqsave(&chip->lock, flags);
449 strength = (strength / 2) - 1;
450 for (i = 0; i < GPIO_DRV_STRENGTH_BITS; i++) {
451 val = readl(base + offset);
452 val &= ~BIT(shift);
453 val |= ((strength >> i) & 0x1) << shift;
454 writel(val, base + offset);
455 offset += 4;
456 }
457 spin_unlock_irqrestore(&chip->lock, flags);
458
459 return 0;
460}
461
462static int cygnus_gpio_get_strength(struct cygnus_gpio *chip, unsigned gpio,
463 u16 *strength)
464{
465 void __iomem *base;
466 unsigned int i, offset, shift;
467 u32 val;
468 unsigned long flags;
469
470 if (chip->io_ctrl) {
471 base = chip->io_ctrl;
472 offset = CYGNUS_GPIO_DRV0_CTRL_OFFSET;
473 } else {
474 base = chip->base;
475 offset = CYGNUS_GPIO_REG(gpio,
476 CYGNUS_GPIO_ASIU_DRV0_CTRL_OFFSET);
477 }
478
479 shift = CYGNUS_GPIO_SHIFT(gpio);
480
481 spin_lock_irqsave(&chip->lock, flags);
482 *strength = 0;
483 for (i = 0; i < GPIO_DRV_STRENGTH_BITS; i++) {
484 val = readl(base + offset) & BIT(shift);
485 val >>= shift;
486 *strength += (val << i);
487 offset += 4;
488 }
489
490 /* convert to mA */
491 *strength = (*strength + 1) * 2;
492 spin_unlock_irqrestore(&chip->lock, flags);
493
494 return 0;
495}
496
497static int cygnus_pin_config_get(struct pinctrl_dev *pctldev, unsigned pin,
498 unsigned long *config)
499{
500 struct cygnus_gpio *chip = pinctrl_dev_get_drvdata(pctldev);
501 enum pin_config_param param = pinconf_to_config_param(*config);
502 unsigned gpio = cygnus_pin_to_gpio(pin);
503 u16 arg;
504 bool disable, pull_up;
505 int ret;
506
507 switch (param) {
508 case PIN_CONFIG_BIAS_DISABLE:
509 cygnus_gpio_get_pull(chip, gpio, &disable, &pull_up);
510 if (disable)
511 return 0;
512 else
513 return -EINVAL;
514
515 case PIN_CONFIG_BIAS_PULL_UP:
516 cygnus_gpio_get_pull(chip, gpio, &disable, &pull_up);
517 if (!disable && pull_up)
518 return 0;
519 else
520 return -EINVAL;
521
522 case PIN_CONFIG_BIAS_PULL_DOWN:
523 cygnus_gpio_get_pull(chip, gpio, &disable, &pull_up);
524 if (!disable && !pull_up)
525 return 0;
526 else
527 return -EINVAL;
528
529 case PIN_CONFIG_DRIVE_STRENGTH:
530 ret = cygnus_gpio_get_strength(chip, gpio, &arg);
531 if (ret)
532 return ret;
533 else
534 *config = pinconf_to_config_packed(param, arg);
535
536 return 0;
537
538 default:
539 return -ENOTSUPP;
540 }
541
542 return -ENOTSUPP;
543}
544
545static int cygnus_pin_config_set(struct pinctrl_dev *pctldev, unsigned pin,
546 unsigned long *configs, unsigned num_configs)
547{
548 struct cygnus_gpio *chip = pinctrl_dev_get_drvdata(pctldev);
549 enum pin_config_param param;
550 u16 arg;
551 unsigned i, gpio = cygnus_pin_to_gpio(pin);
552 int ret = -ENOTSUPP;
553
554 for (i = 0; i < num_configs; i++) {
555 param = pinconf_to_config_param(configs[i]);
556 arg = pinconf_to_config_argument(configs[i]);
557
558 switch (param) {
559 case PIN_CONFIG_BIAS_DISABLE:
560 ret = cygnus_gpio_set_pull(chip, gpio, true, false);
561 if (ret < 0)
562 goto out;
563 break;
564
565 case PIN_CONFIG_BIAS_PULL_UP:
566 ret = cygnus_gpio_set_pull(chip, gpio, false, true);
567 if (ret < 0)
568 goto out;
569 break;
570
571 case PIN_CONFIG_BIAS_PULL_DOWN:
572 ret = cygnus_gpio_set_pull(chip, gpio, false, false);
573 if (ret < 0)
574 goto out;
575 break;
576
577 case PIN_CONFIG_DRIVE_STRENGTH:
578 ret = cygnus_gpio_set_strength(chip, gpio, arg);
579 if (ret < 0)
580 goto out;
581 break;
582
583 default:
584 dev_err(chip->dev, "invalid configuration\n");
585 return -ENOTSUPP;
586 }
587 } /* for each config */
588
589out:
590 return ret;
591}
592
593static const struct pinconf_ops cygnus_pconf_ops = {
594 .is_generic = true,
595 .pin_config_get = cygnus_pin_config_get,
596 .pin_config_set = cygnus_pin_config_set,
597};
598
599/*
600 * Map a GPIO in the local gpio_chip pin space to a pin in the Cygnus IOMUX
601 * pinctrl pin space
602 */
603struct cygnus_gpio_pin_range {
604 unsigned offset;
605 unsigned pin_base;
606 unsigned num_pins;
607};
608
609#define CYGNUS_PINRANGE(o, p, n) { .offset = o, .pin_base = p, .num_pins = n }
610
611/*
612 * Pin mapping table for mapping local GPIO pins to Cygnus IOMUX pinctrl pins
613 */
614static const struct cygnus_gpio_pin_range cygnus_gpio_pintable[] = {
615 CYGNUS_PINRANGE(0, 42, 1),
616 CYGNUS_PINRANGE(1, 44, 3),
617 CYGNUS_PINRANGE(4, 48, 1),
618 CYGNUS_PINRANGE(5, 50, 3),
619 CYGNUS_PINRANGE(8, 126, 1),
620 CYGNUS_PINRANGE(9, 155, 1),
621 CYGNUS_PINRANGE(10, 152, 1),
622 CYGNUS_PINRANGE(11, 154, 1),
623 CYGNUS_PINRANGE(12, 153, 1),
624 CYGNUS_PINRANGE(13, 127, 3),
625 CYGNUS_PINRANGE(16, 140, 1),
626 CYGNUS_PINRANGE(17, 145, 7),
627 CYGNUS_PINRANGE(24, 130, 10),
628 CYGNUS_PINRANGE(34, 141, 4),
629 CYGNUS_PINRANGE(38, 54, 1),
630 CYGNUS_PINRANGE(39, 56, 3),
631 CYGNUS_PINRANGE(42, 60, 3),
632 CYGNUS_PINRANGE(45, 64, 3),
633 CYGNUS_PINRANGE(48, 68, 2),
634 CYGNUS_PINRANGE(50, 84, 6),
635 CYGNUS_PINRANGE(56, 94, 6),
636 CYGNUS_PINRANGE(62, 72, 1),
637 CYGNUS_PINRANGE(63, 70, 1),
638 CYGNUS_PINRANGE(64, 80, 1),
639 CYGNUS_PINRANGE(65, 74, 3),
640 CYGNUS_PINRANGE(68, 78, 1),
641 CYGNUS_PINRANGE(69, 82, 1),
642 CYGNUS_PINRANGE(70, 156, 17),
643 CYGNUS_PINRANGE(87, 104, 12),
644 CYGNUS_PINRANGE(99, 102, 2),
645 CYGNUS_PINRANGE(101, 90, 4),
646 CYGNUS_PINRANGE(105, 116, 10),
647 CYGNUS_PINRANGE(123, 11, 1),
648 CYGNUS_PINRANGE(124, 38, 4),
649 CYGNUS_PINRANGE(128, 43, 1),
650 CYGNUS_PINRANGE(129, 47, 1),
651 CYGNUS_PINRANGE(130, 49, 1),
652 CYGNUS_PINRANGE(131, 53, 1),
653 CYGNUS_PINRANGE(132, 55, 1),
654 CYGNUS_PINRANGE(133, 59, 1),
655 CYGNUS_PINRANGE(134, 63, 1),
656 CYGNUS_PINRANGE(135, 67, 1),
657 CYGNUS_PINRANGE(136, 71, 1),
658 CYGNUS_PINRANGE(137, 73, 1),
659 CYGNUS_PINRANGE(138, 77, 1),
660 CYGNUS_PINRANGE(139, 79, 1),
661 CYGNUS_PINRANGE(140, 81, 1),
662 CYGNUS_PINRANGE(141, 83, 1),
663 CYGNUS_PINRANGE(142, 10, 1)
664};
665
666/*
667 * The Cygnus IOMUX controller mainly supports group based mux configuration,
668 * but certain pins can be muxed to GPIO individually. Only the ASIU GPIO
669 * controller can support this, so it's an optional configuration
670 *
671 * Return -ENODEV means no support and that's fine
672 */
673static int cygnus_gpio_pinmux_add_range(struct cygnus_gpio *chip)
674{
675 struct device_node *node = chip->dev->of_node;
676 struct device_node *pinmux_node;
677 struct platform_device *pinmux_pdev;
678 struct gpio_chip *gc = &chip->gc;
679 int i, ret = 0;
680
681 /* parse DT to find the phandle to the pinmux controller */
682 pinmux_node = of_parse_phandle(node, "pinmux", 0);
683 if (!pinmux_node)
684 return -ENODEV;
685
686 pinmux_pdev = of_find_device_by_node(pinmux_node);
687 /* no longer need the pinmux node */
688 of_node_put(pinmux_node);
689 if (!pinmux_pdev) {
690 dev_err(chip->dev, "failed to get pinmux device\n");
691 return -EINVAL;
692 }
693
694 /* now need to create the mapping between local GPIO and PINMUX pins */
695 for (i = 0; i < ARRAY_SIZE(cygnus_gpio_pintable); i++) {
696 ret = gpiochip_add_pin_range(gc, dev_name(&pinmux_pdev->dev),
697 cygnus_gpio_pintable[i].offset,
698 cygnus_gpio_pintable[i].pin_base,
699 cygnus_gpio_pintable[i].num_pins);
700 if (ret) {
701 dev_err(chip->dev, "unable to add GPIO pin range\n");
702 goto err_put_device;
703 }
704 }
705
706 chip->pinmux_is_supported = true;
707
708 /* no need for pinmux_pdev device reference anymore */
709 put_device(&pinmux_pdev->dev);
710 return 0;
711
712err_put_device:
713 put_device(&pinmux_pdev->dev);
714 gpiochip_remove_pin_ranges(gc);
715 return ret;
716}
717
718/*
719 * Cygnus GPIO controller supports some PINCONF related configurations such as
720 * pull up, pull down, and drive strength, when the pin is configured to GPIO
721 *
722 * Here a local pinctrl device is created with simple 1-to-1 pin mapping to the
723 * local GPIO pins
724 */
725static int cygnus_gpio_register_pinconf(struct cygnus_gpio *chip)
726{
727 struct pinctrl_desc *pctldesc = &chip->pctldesc;
728 struct pinctrl_pin_desc *pins;
729 struct gpio_chip *gc = &chip->gc;
730 int i;
731
732 pins = devm_kcalloc(chip->dev, gc->ngpio, sizeof(*pins), GFP_KERNEL);
733 if (!pins)
734 return -ENOMEM;
735
736 for (i = 0; i < gc->ngpio; i++) {
737 pins[i].number = i;
738 pins[i].name = devm_kasprintf(chip->dev, GFP_KERNEL,
739 "gpio-%d", i);
740 if (!pins[i].name)
741 return -ENOMEM;
742 }
743
744 pctldesc->name = dev_name(chip->dev);
745 pctldesc->pctlops = &cygnus_pctrl_ops;
746 pctldesc->pins = pins;
747 pctldesc->npins = gc->ngpio;
748 pctldesc->confops = &cygnus_pconf_ops;
749
750 chip->pctl = pinctrl_register(pctldesc, chip->dev, chip);
751 if (!chip->pctl) {
752 dev_err(chip->dev, "unable to register pinctrl device\n");
753 return -EINVAL;
754 }
755
756 return 0;
757}
758
759static void cygnus_gpio_unregister_pinconf(struct cygnus_gpio *chip)
760{
761 if (chip->pctl)
762 pinctrl_unregister(chip->pctl);
763}
764
765struct cygnus_gpio_data {
766 unsigned num_gpios;
767};
768
769static const struct cygnus_gpio_data cygnus_cmm_gpio_data = {
770 .num_gpios = 24,
771};
772
773static const struct cygnus_gpio_data cygnus_asiu_gpio_data = {
774 .num_gpios = 146,
775};
776
777static const struct cygnus_gpio_data cygnus_crmu_gpio_data = {
778 .num_gpios = 6,
779};
780
781static const struct of_device_id cygnus_gpio_of_match[] = {
782 {
783 .compatible = "brcm,cygnus-ccm-gpio",
784 .data = &cygnus_cmm_gpio_data,
785 },
786 {
787 .compatible = "brcm,cygnus-asiu-gpio",
788 .data = &cygnus_asiu_gpio_data,
789 },
790 {
791 .compatible = "brcm,cygnus-crmu-gpio",
792 .data = &cygnus_crmu_gpio_data,
793 }
794};
795
796static int cygnus_gpio_probe(struct platform_device *pdev)
797{
798 struct device *dev = &pdev->dev;
799 struct resource *res;
800 struct cygnus_gpio *chip;
801 struct gpio_chip *gc;
802 u32 ngpios;
803 int irq, ret;
804 const struct of_device_id *match;
805 const struct cygnus_gpio_data *gpio_data;
806
807 match = of_match_device(cygnus_gpio_of_match, dev);
808 if (!match)
809 return -ENODEV;
810 gpio_data = match->data;
811 ngpios = gpio_data->num_gpios;
812
813 chip = devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL);
814 if (!chip)
815 return -ENOMEM;
816
817 chip->dev = dev;
818 platform_set_drvdata(pdev, chip);
819
820 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
821 chip->base = devm_ioremap_resource(dev, res);
822 if (IS_ERR(chip->base)) {
823 dev_err(dev, "unable to map I/O memory\n");
824 return PTR_ERR(chip->base);
825 }
826
827 res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
828 if (res) {
829 chip->io_ctrl = devm_ioremap_resource(dev, res);
830 if (IS_ERR(chip->io_ctrl)) {
831 dev_err(dev, "unable to map I/O memory\n");
832 return PTR_ERR(chip->io_ctrl);
833 }
834 }
835
836 spin_lock_init(&chip->lock);
837
838 gc = &chip->gc;
839 gc->base = -1;
840 gc->ngpio = ngpios;
841 chip->num_banks = (ngpios + NGPIOS_PER_BANK - 1) / NGPIOS_PER_BANK;
842 gc->label = dev_name(dev);
843 gc->dev = dev;
844 gc->of_node = dev->of_node;
845 gc->request = cygnus_gpio_request;
846 gc->free = cygnus_gpio_free;
847 gc->direction_input = cygnus_gpio_direction_input;
848 gc->direction_output = cygnus_gpio_direction_output;
849 gc->set = cygnus_gpio_set;
850 gc->get = cygnus_gpio_get;
851
852 ret = gpiochip_add(gc);
853 if (ret < 0) {
854 dev_err(dev, "unable to add GPIO chip\n");
855 return ret;
856 }
857
858 ret = cygnus_gpio_pinmux_add_range(chip);
859 if (ret && ret != -ENODEV) {
860 dev_err(dev, "unable to add GPIO pin range\n");
861 goto err_rm_gpiochip;
862 }
863
864 ret = cygnus_gpio_register_pinconf(chip);
865 if (ret) {
866 dev_err(dev, "unable to register pinconf\n");
867 goto err_rm_gpiochip;
868 }
869
870 /* optional GPIO interrupt support */
871 irq = platform_get_irq(pdev, 0);
872 if (irq) {
873 ret = gpiochip_irqchip_add(gc, &cygnus_gpio_irq_chip, 0,
874 handle_simple_irq, IRQ_TYPE_NONE);
875 if (ret) {
876 dev_err(dev, "no GPIO irqchip\n");
877 goto err_unregister_pinconf;
878 }
879
880 gpiochip_set_chained_irqchip(gc, &cygnus_gpio_irq_chip, irq,
881 cygnus_gpio_irq_handler);
882 }
883
884 return 0;
885
886err_unregister_pinconf:
887 cygnus_gpio_unregister_pinconf(chip);
888
889err_rm_gpiochip:
890 gpiochip_remove(gc);
891
892 return ret;
893}
894
895static struct platform_driver cygnus_gpio_driver = {
896 .driver = {
897 .name = "cygnus-gpio",
898 .of_match_table = cygnus_gpio_of_match,
899 },
900 .probe = cygnus_gpio_probe,
901};
902
903static int __init cygnus_gpio_init(void)
904{
905 return platform_driver_probe(&cygnus_gpio_driver, cygnus_gpio_probe);
906}
907arch_initcall_sync(cygnus_gpio_init);