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/pinconf.h>
33#include <linux/pinctrl/pinconf-generic.h>
34
35#include "../pinctrl-utils.h"
36
37#define CYGNUS_GPIO_DATA_IN_OFFSET   0x00
38#define CYGNUS_GPIO_DATA_OUT_OFFSET  0x04
39#define CYGNUS_GPIO_OUT_EN_OFFSET    0x08
40#define CYGNUS_GPIO_INT_TYPE_OFFSET  0x0c
41#define CYGNUS_GPIO_INT_DE_OFFSET    0x10
42#define CYGNUS_GPIO_INT_EDGE_OFFSET  0x14
43#define CYGNUS_GPIO_INT_MSK_OFFSET   0x18
44#define CYGNUS_GPIO_INT_STAT_OFFSET  0x1c
45#define CYGNUS_GPIO_INT_MSTAT_OFFSET 0x20
46#define CYGNUS_GPIO_INT_CLR_OFFSET   0x24
47#define CYGNUS_GPIO_PAD_RES_OFFSET   0x34
48#define CYGNUS_GPIO_RES_EN_OFFSET    0x38
49
50/* drive strength control for ASIU GPIO */
51#define CYGNUS_GPIO_ASIU_DRV0_CTRL_OFFSET 0x58
52
53/* drive strength control for CCM/CRMU (AON) GPIO */
54#define CYGNUS_GPIO_DRV0_CTRL_OFFSET  0x00
55
56#define GPIO_BANK_SIZE 0x200
57#define NGPIOS_PER_BANK 32
58#define GPIO_BANK(pin) ((pin) / NGPIOS_PER_BANK)
59
60#define CYGNUS_GPIO_REG(pin, reg) (GPIO_BANK(pin) * GPIO_BANK_SIZE + (reg))
61#define CYGNUS_GPIO_SHIFT(pin) ((pin) % NGPIOS_PER_BANK)
62
63#define GPIO_DRV_STRENGTH_BIT_SHIFT  20
64#define GPIO_DRV_STRENGTH_BITS       3
65#define GPIO_DRV_STRENGTH_BIT_MASK   ((1 << GPIO_DRV_STRENGTH_BITS) - 1)
66
67/*
68 * Cygnus GPIO core
69 *
70 * @dev: pointer to device
71 * @base: I/O register base for Cygnus GPIO controller
72 * @io_ctrl: I/O register base for certain type of Cygnus GPIO controller that
73 * has the PINCONF support implemented outside of the GPIO block
74 * @lock: lock to protect access to I/O registers
75 * @gc: GPIO chip
76 * @num_banks: number of GPIO banks, each bank supports up to 32 GPIOs
77 * @pinmux_is_supported: flag to indicate this GPIO controller contains pins
78 * that can be individually muxed to GPIO
79 * @pctl: pointer to pinctrl_dev
80 * @pctldesc: pinctrl descriptor
81 */
82struct cygnus_gpio {
83	struct device *dev;
84
85	void __iomem *base;
86	void __iomem *io_ctrl;
87
88	spinlock_t lock;
89
90	struct gpio_chip gc;
91	unsigned num_banks;
92
93	bool pinmux_is_supported;
94
95	struct pinctrl_dev *pctl;
96	struct pinctrl_desc pctldesc;
97};
98
99static inline struct cygnus_gpio *to_cygnus_gpio(struct gpio_chip *gc)
100{
101	return container_of(gc, struct cygnus_gpio, gc);
102}
103
104/*
105 * Mapping from PINCONF pins to GPIO pins is 1-to-1
106 */
107static inline unsigned cygnus_pin_to_gpio(unsigned pin)
108{
109	return pin;
110}
111
112/**
113 *  cygnus_set_bit - set or clear one bit (corresponding to the GPIO pin) in a
114 *  Cygnus GPIO register
115 *
116 *  @cygnus_gpio: Cygnus GPIO device
117 *  @reg: register offset
118 *  @gpio: GPIO pin
119 *  @set: set or clear
120 */
121static inline void cygnus_set_bit(struct cygnus_gpio *chip, unsigned int reg,
122				  unsigned gpio, bool set)
123{
124	unsigned int offset = CYGNUS_GPIO_REG(gpio, reg);
125	unsigned int shift = CYGNUS_GPIO_SHIFT(gpio);
126	u32 val;
127
128	val = readl(chip->base + offset);
129	if (set)
130		val |= BIT(shift);
131	else
132		val &= ~BIT(shift);
133	writel(val, chip->base + offset);
134}
135
136static inline bool cygnus_get_bit(struct cygnus_gpio *chip, unsigned int reg,
137				  unsigned gpio)
138{
139	unsigned int offset = CYGNUS_GPIO_REG(gpio, reg);
140	unsigned int shift = CYGNUS_GPIO_SHIFT(gpio);
141
142	return !!(readl(chip->base + offset) & BIT(shift));
143}
144
145static void cygnus_gpio_irq_handler(struct irq_desc *desc)
146{
147	struct gpio_chip *gc = irq_desc_get_handler_data(desc);
148	struct cygnus_gpio *chip = to_cygnus_gpio(gc);
149	struct irq_chip *irq_chip = irq_desc_get_chip(desc);
150	int i, bit;
151
152	chained_irq_enter(irq_chip, desc);
153
154	/* go through the entire GPIO banks and handle all interrupts */
155	for (i = 0; i < chip->num_banks; i++) {
156		unsigned long val = readl(chip->base + (i * GPIO_BANK_SIZE) +
157					  CYGNUS_GPIO_INT_MSTAT_OFFSET);
158
159		for_each_set_bit(bit, &val, NGPIOS_PER_BANK) {
160			unsigned pin = NGPIOS_PER_BANK * i + bit;
161			int child_irq = irq_find_mapping(gc->irqdomain, pin);
162
163			/*
164			 * Clear the interrupt before invoking the
165			 * handler, so we do not leave any window
166			 */
167			writel(BIT(bit), chip->base + (i * GPIO_BANK_SIZE) +
168			       CYGNUS_GPIO_INT_CLR_OFFSET);
169
170			generic_handle_irq(child_irq);
171		}
172	}
173
174	chained_irq_exit(irq_chip, desc);
175}
176
177
178static void cygnus_gpio_irq_ack(struct irq_data *d)
179{
180	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
181	struct cygnus_gpio *chip = to_cygnus_gpio(gc);
182	unsigned gpio = d->hwirq;
183	unsigned int offset = CYGNUS_GPIO_REG(gpio,
184			CYGNUS_GPIO_INT_CLR_OFFSET);
185	unsigned int shift = CYGNUS_GPIO_SHIFT(gpio);
186	u32 val = BIT(shift);
187
188	writel(val, chip->base + offset);
189}
190
191/**
192 *  cygnus_gpio_irq_set_mask - mask/unmask a GPIO interrupt
193 *
194 *  @d: IRQ chip data
195 *  @unmask: mask/unmask GPIO interrupt
196 */
197static void cygnus_gpio_irq_set_mask(struct irq_data *d, bool unmask)
198{
199	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
200	struct cygnus_gpio *chip = to_cygnus_gpio(gc);
201	unsigned gpio = d->hwirq;
202
203	cygnus_set_bit(chip, CYGNUS_GPIO_INT_MSK_OFFSET, gpio, unmask);
204}
205
206static void cygnus_gpio_irq_mask(struct irq_data *d)
207{
208	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
209	struct cygnus_gpio *chip = to_cygnus_gpio(gc);
210	unsigned long flags;
211
212	spin_lock_irqsave(&chip->lock, flags);
213	cygnus_gpio_irq_set_mask(d, false);
214	spin_unlock_irqrestore(&chip->lock, flags);
215}
216
217static void cygnus_gpio_irq_unmask(struct irq_data *d)
218{
219	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
220	struct cygnus_gpio *chip = to_cygnus_gpio(gc);
221	unsigned long flags;
222
223	spin_lock_irqsave(&chip->lock, flags);
224	cygnus_gpio_irq_set_mask(d, true);
225	spin_unlock_irqrestore(&chip->lock, flags);
226}
227
228static int cygnus_gpio_irq_set_type(struct irq_data *d, unsigned int type)
229{
230	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
231	struct cygnus_gpio *chip = to_cygnus_gpio(gc);
232	unsigned gpio = d->hwirq;
233	bool level_triggered = false;
234	bool dual_edge = false;
235	bool rising_or_high = false;
236	unsigned long flags;
237
238	switch (type & IRQ_TYPE_SENSE_MASK) {
239	case IRQ_TYPE_EDGE_RISING:
240		rising_or_high = true;
241		break;
242
243	case IRQ_TYPE_EDGE_FALLING:
244		break;
245
246	case IRQ_TYPE_EDGE_BOTH:
247		dual_edge = true;
248		break;
249
250	case IRQ_TYPE_LEVEL_HIGH:
251		level_triggered = true;
252		rising_or_high = true;
253		break;
254
255	case IRQ_TYPE_LEVEL_LOW:
256		level_triggered = true;
257		break;
258
259	default:
260		dev_err(chip->dev, "invalid GPIO IRQ type 0x%x\n",
261			type);
262		return -EINVAL;
263	}
264
265	spin_lock_irqsave(&chip->lock, flags);
266	cygnus_set_bit(chip, CYGNUS_GPIO_INT_TYPE_OFFSET, gpio,
267		       level_triggered);
268	cygnus_set_bit(chip, CYGNUS_GPIO_INT_DE_OFFSET, gpio, dual_edge);
269	cygnus_set_bit(chip, CYGNUS_GPIO_INT_EDGE_OFFSET, gpio,
270		       rising_or_high);
271	spin_unlock_irqrestore(&chip->lock, flags);
272
273	dev_dbg(chip->dev,
274		"gpio:%u level_triggered:%d dual_edge:%d rising_or_high:%d\n",
275		gpio, level_triggered, dual_edge, rising_or_high);
276
277	return 0;
278}
279
280static struct irq_chip cygnus_gpio_irq_chip = {
281	.name = "bcm-cygnus-gpio",
282	.irq_ack = cygnus_gpio_irq_ack,
283	.irq_mask = cygnus_gpio_irq_mask,
284	.irq_unmask = cygnus_gpio_irq_unmask,
285	.irq_set_type = cygnus_gpio_irq_set_type,
286};
287
288/*
289 * Request the Cygnus IOMUX pinmux controller to mux individual pins to GPIO
290 */
291static int cygnus_gpio_request(struct gpio_chip *gc, unsigned offset)
292{
293	struct cygnus_gpio *chip = to_cygnus_gpio(gc);
294	unsigned gpio = gc->base + offset;
295
296	/* not all Cygnus GPIO pins can be muxed individually */
297	if (!chip->pinmux_is_supported)
298		return 0;
299
300	return pinctrl_request_gpio(gpio);
301}
302
303static void cygnus_gpio_free(struct gpio_chip *gc, unsigned offset)
304{
305	struct cygnus_gpio *chip = to_cygnus_gpio(gc);
306	unsigned gpio = gc->base + offset;
307
308	if (!chip->pinmux_is_supported)
309		return;
310
311	pinctrl_free_gpio(gpio);
312}
313
314static int cygnus_gpio_direction_input(struct gpio_chip *gc, unsigned gpio)
315{
316	struct cygnus_gpio *chip = to_cygnus_gpio(gc);
317	unsigned long flags;
318
319	spin_lock_irqsave(&chip->lock, flags);
320	cygnus_set_bit(chip, CYGNUS_GPIO_OUT_EN_OFFSET, gpio, false);
321	spin_unlock_irqrestore(&chip->lock, flags);
322
323	dev_dbg(chip->dev, "gpio:%u set input\n", gpio);
324
325	return 0;
326}
327
328static int cygnus_gpio_direction_output(struct gpio_chip *gc, unsigned gpio,
329					int val)
330{
331	struct cygnus_gpio *chip = to_cygnus_gpio(gc);
332	unsigned long flags;
333
334	spin_lock_irqsave(&chip->lock, flags);
335	cygnus_set_bit(chip, CYGNUS_GPIO_OUT_EN_OFFSET, gpio, true);
336	cygnus_set_bit(chip, CYGNUS_GPIO_DATA_OUT_OFFSET, gpio, !!(val));
337	spin_unlock_irqrestore(&chip->lock, flags);
338
339	dev_dbg(chip->dev, "gpio:%u set output, value:%d\n", gpio, val);
340
341	return 0;
342}
343
344static void cygnus_gpio_set(struct gpio_chip *gc, unsigned gpio, int val)
345{
346	struct cygnus_gpio *chip = to_cygnus_gpio(gc);
347	unsigned long flags;
348
349	spin_lock_irqsave(&chip->lock, flags);
350	cygnus_set_bit(chip, CYGNUS_GPIO_DATA_OUT_OFFSET, gpio, !!(val));
351	spin_unlock_irqrestore(&chip->lock, flags);
352
353	dev_dbg(chip->dev, "gpio:%u set, value:%d\n", gpio, val);
354}
355
356static int cygnus_gpio_get(struct gpio_chip *gc, unsigned gpio)
357{
358	struct cygnus_gpio *chip = to_cygnus_gpio(gc);
359	unsigned int offset = CYGNUS_GPIO_REG(gpio,
360					      CYGNUS_GPIO_DATA_IN_OFFSET);
361	unsigned int shift = CYGNUS_GPIO_SHIFT(gpio);
362
363	return !!(readl(chip->base + offset) & BIT(shift));
364}
365
366static int cygnus_get_groups_count(struct pinctrl_dev *pctldev)
367{
368	return 1;
369}
370
371/*
372 * Only one group: "gpio_grp", since this local pinctrl device only performs
373 * GPIO specific PINCONF configurations
374 */
375static const char *cygnus_get_group_name(struct pinctrl_dev *pctldev,
376					 unsigned selector)
377{
378	return "gpio_grp";
379}
380
381static const struct pinctrl_ops cygnus_pctrl_ops = {
382	.get_groups_count = cygnus_get_groups_count,
383	.get_group_name = cygnus_get_group_name,
384	.dt_node_to_map = pinconf_generic_dt_node_to_map_pin,
385	.dt_free_map = pinctrl_utils_dt_free_map,
386};
387
388static int cygnus_gpio_set_pull(struct cygnus_gpio *chip, unsigned gpio,
389				bool disable, bool pull_up)
390{
391	unsigned long flags;
392
393	spin_lock_irqsave(&chip->lock, flags);
394
395	if (disable) {
396		cygnus_set_bit(chip, CYGNUS_GPIO_RES_EN_OFFSET, gpio, false);
397	} else {
398		cygnus_set_bit(chip, CYGNUS_GPIO_PAD_RES_OFFSET, gpio,
399			       pull_up);
400		cygnus_set_bit(chip, CYGNUS_GPIO_RES_EN_OFFSET, gpio, true);
401	}
402
403	spin_unlock_irqrestore(&chip->lock, flags);
404
405	dev_dbg(chip->dev, "gpio:%u set pullup:%d\n", gpio, pull_up);
406
407	return 0;
408}
409
410static void cygnus_gpio_get_pull(struct cygnus_gpio *chip, unsigned gpio,
411				 bool *disable, bool *pull_up)
412{
413	unsigned long flags;
414
415	spin_lock_irqsave(&chip->lock, flags);
416	*disable = !cygnus_get_bit(chip, CYGNUS_GPIO_RES_EN_OFFSET, gpio);
417	*pull_up = cygnus_get_bit(chip, CYGNUS_GPIO_PAD_RES_OFFSET, gpio);
418	spin_unlock_irqrestore(&chip->lock, flags);
419}
420
421static int cygnus_gpio_set_strength(struct cygnus_gpio *chip, unsigned gpio,
422				    unsigned strength)
423{
424	void __iomem *base;
425	unsigned int i, offset, shift;
426	u32 val;
427	unsigned long flags;
428
429	/* make sure drive strength is supported */
430	if (strength < 2 ||  strength > 16 || (strength % 2))
431		return -ENOTSUPP;
432
433	if (chip->io_ctrl) {
434		base = chip->io_ctrl;
435		offset = CYGNUS_GPIO_DRV0_CTRL_OFFSET;
436	} else {
437		base = chip->base;
438		offset = CYGNUS_GPIO_REG(gpio,
439					 CYGNUS_GPIO_ASIU_DRV0_CTRL_OFFSET);
440	}
441
442	shift = CYGNUS_GPIO_SHIFT(gpio);
443
444	dev_dbg(chip->dev, "gpio:%u set drive strength:%d mA\n", gpio,
445		strength);
446
447	spin_lock_irqsave(&chip->lock, flags);
448	strength = (strength / 2) - 1;
449	for (i = 0; i < GPIO_DRV_STRENGTH_BITS; i++) {
450		val = readl(base + offset);
451		val &= ~BIT(shift);
452		val |= ((strength >> i) & 0x1) << shift;
453		writel(val, base + offset);
454		offset += 4;
455	}
456	spin_unlock_irqrestore(&chip->lock, flags);
457
458	return 0;
459}
460
461static int cygnus_gpio_get_strength(struct cygnus_gpio *chip, unsigned gpio,
462				    u16 *strength)
463{
464	void __iomem *base;
465	unsigned int i, offset, shift;
466	u32 val;
467	unsigned long flags;
468
469	if (chip->io_ctrl) {
470		base = chip->io_ctrl;
471		offset = CYGNUS_GPIO_DRV0_CTRL_OFFSET;
472	} else {
473		base = chip->base;
474		offset = CYGNUS_GPIO_REG(gpio,
475					 CYGNUS_GPIO_ASIU_DRV0_CTRL_OFFSET);
476	}
477
478	shift = CYGNUS_GPIO_SHIFT(gpio);
479
480	spin_lock_irqsave(&chip->lock, flags);
481	*strength = 0;
482	for (i = 0; i < GPIO_DRV_STRENGTH_BITS; i++) {
483		val = readl(base + offset) & BIT(shift);
484		val >>= shift;
485		*strength += (val << i);
486		offset += 4;
487	}
488
489	/* convert to mA */
490	*strength = (*strength + 1) * 2;
491	spin_unlock_irqrestore(&chip->lock, flags);
492
493	return 0;
494}
495
496static int cygnus_pin_config_get(struct pinctrl_dev *pctldev, unsigned pin,
497				 unsigned long *config)
498{
499	struct cygnus_gpio *chip = pinctrl_dev_get_drvdata(pctldev);
500	enum pin_config_param param = pinconf_to_config_param(*config);
501	unsigned gpio = cygnus_pin_to_gpio(pin);
502	u16 arg;
503	bool disable, pull_up;
504	int ret;
505
506	switch (param) {
507	case PIN_CONFIG_BIAS_DISABLE:
508		cygnus_gpio_get_pull(chip, gpio, &disable, &pull_up);
509		if (disable)
510			return 0;
511		else
512			return -EINVAL;
513
514	case PIN_CONFIG_BIAS_PULL_UP:
515		cygnus_gpio_get_pull(chip, gpio, &disable, &pull_up);
516		if (!disable && pull_up)
517			return 0;
518		else
519			return -EINVAL;
520
521	case PIN_CONFIG_BIAS_PULL_DOWN:
522		cygnus_gpio_get_pull(chip, gpio, &disable, &pull_up);
523		if (!disable && !pull_up)
524			return 0;
525		else
526			return -EINVAL;
527
528	case PIN_CONFIG_DRIVE_STRENGTH:
529		ret = cygnus_gpio_get_strength(chip, gpio, &arg);
530		if (ret)
531			return ret;
532		else
533			*config = pinconf_to_config_packed(param, arg);
534
535		return 0;
536
537	default:
538		return -ENOTSUPP;
539	}
540
541	return -ENOTSUPP;
542}
543
544static int cygnus_pin_config_set(struct pinctrl_dev *pctldev, unsigned pin,
545				 unsigned long *configs, unsigned num_configs)
546{
547	struct cygnus_gpio *chip = pinctrl_dev_get_drvdata(pctldev);
548	enum pin_config_param param;
549	u16 arg;
550	unsigned i, gpio = cygnus_pin_to_gpio(pin);
551	int ret = -ENOTSUPP;
552
553	for (i = 0; i < num_configs; i++) {
554		param = pinconf_to_config_param(configs[i]);
555		arg = pinconf_to_config_argument(configs[i]);
556
557		switch (param) {
558		case PIN_CONFIG_BIAS_DISABLE:
559			ret = cygnus_gpio_set_pull(chip, gpio, true, false);
560			if (ret < 0)
561				goto out;
562			break;
563
564		case PIN_CONFIG_BIAS_PULL_UP:
565			ret = cygnus_gpio_set_pull(chip, gpio, false, true);
566			if (ret < 0)
567				goto out;
568			break;
569
570		case PIN_CONFIG_BIAS_PULL_DOWN:
571			ret = cygnus_gpio_set_pull(chip, gpio, false, false);
572			if (ret < 0)
573				goto out;
574			break;
575
576		case PIN_CONFIG_DRIVE_STRENGTH:
577			ret = cygnus_gpio_set_strength(chip, gpio, arg);
578			if (ret < 0)
579				goto out;
580			break;
581
582		default:
583			dev_err(chip->dev, "invalid configuration\n");
584			return -ENOTSUPP;
585		}
586	} /* for each config */
587
588out:
589	return ret;
590}
591
592static const struct pinconf_ops cygnus_pconf_ops = {
593	.is_generic = true,
594	.pin_config_get = cygnus_pin_config_get,
595	.pin_config_set = cygnus_pin_config_set,
596};
597
598/*
599 * Cygnus GPIO controller supports some PINCONF related configurations such as
600 * pull up, pull down, and drive strength, when the pin is configured to GPIO
601 *
602 * Here a local pinctrl device is created with simple 1-to-1 pin mapping to the
603 * local GPIO pins
604 */
605static int cygnus_gpio_register_pinconf(struct cygnus_gpio *chip)
606{
607	struct pinctrl_desc *pctldesc = &chip->pctldesc;
608	struct pinctrl_pin_desc *pins;
609	struct gpio_chip *gc = &chip->gc;
610	int i;
611
612	pins = devm_kcalloc(chip->dev, gc->ngpio, sizeof(*pins), GFP_KERNEL);
613	if (!pins)
614		return -ENOMEM;
615
616	for (i = 0; i < gc->ngpio; i++) {
617		pins[i].number = i;
618		pins[i].name = devm_kasprintf(chip->dev, GFP_KERNEL,
619					      "gpio-%d", i);
620		if (!pins[i].name)
621			return -ENOMEM;
622	}
623
624	pctldesc->name = dev_name(chip->dev);
625	pctldesc->pctlops = &cygnus_pctrl_ops;
626	pctldesc->pins = pins;
627	pctldesc->npins = gc->ngpio;
628	pctldesc->confops = &cygnus_pconf_ops;
629
630	chip->pctl = pinctrl_register(pctldesc, chip->dev, chip);
631	if (IS_ERR(chip->pctl)) {
632		dev_err(chip->dev, "unable to register pinctrl device\n");
633		return PTR_ERR(chip->pctl);
634	}
635
636	return 0;
637}
638
639static void cygnus_gpio_unregister_pinconf(struct cygnus_gpio *chip)
640{
641	if (chip->pctl)
642		pinctrl_unregister(chip->pctl);
643}
644
645struct cygnus_gpio_data {
646	unsigned num_gpios;
647};
648
649static const struct cygnus_gpio_data cygnus_cmm_gpio_data = {
650	.num_gpios = 24,
651};
652
653static const struct cygnus_gpio_data cygnus_asiu_gpio_data = {
654	.num_gpios = 146,
655};
656
657static const struct cygnus_gpio_data cygnus_crmu_gpio_data = {
658	.num_gpios = 6,
659};
660
661static const struct of_device_id cygnus_gpio_of_match[] = {
662	{
663		.compatible = "brcm,cygnus-ccm-gpio",
664		.data = &cygnus_cmm_gpio_data,
665	},
666	{
667		.compatible = "brcm,cygnus-asiu-gpio",
668		.data = &cygnus_asiu_gpio_data,
669	},
670	{
671		.compatible = "brcm,cygnus-crmu-gpio",
672		.data = &cygnus_crmu_gpio_data,
673	}
674};
675
676static int cygnus_gpio_probe(struct platform_device *pdev)
677{
678	struct device *dev = &pdev->dev;
679	struct resource *res;
680	struct cygnus_gpio *chip;
681	struct gpio_chip *gc;
682	u32 ngpios;
683	int irq, ret;
684	const struct of_device_id *match;
685	const struct cygnus_gpio_data *gpio_data;
686
687	match = of_match_device(cygnus_gpio_of_match, dev);
688	if (!match)
689		return -ENODEV;
690	gpio_data = match->data;
691	ngpios = gpio_data->num_gpios;
692
693	chip = devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL);
694	if (!chip)
695		return -ENOMEM;
696
697	chip->dev = dev;
698	platform_set_drvdata(pdev, chip);
699
700	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
701	chip->base = devm_ioremap_resource(dev, res);
702	if (IS_ERR(chip->base)) {
703		dev_err(dev, "unable to map I/O memory\n");
704		return PTR_ERR(chip->base);
705	}
706
707	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
708	if (res) {
709		chip->io_ctrl = devm_ioremap_resource(dev, res);
710		if (IS_ERR(chip->io_ctrl)) {
711			dev_err(dev, "unable to map I/O memory\n");
712			return PTR_ERR(chip->io_ctrl);
713		}
714	}
715
716	spin_lock_init(&chip->lock);
717
718	gc = &chip->gc;
719	gc->base = -1;
720	gc->ngpio = ngpios;
721	chip->num_banks = (ngpios + NGPIOS_PER_BANK - 1) / NGPIOS_PER_BANK;
722	gc->label = dev_name(dev);
723	gc->dev = dev;
724	gc->of_node = dev->of_node;
725	gc->request = cygnus_gpio_request;
726	gc->free = cygnus_gpio_free;
727	gc->direction_input = cygnus_gpio_direction_input;
728	gc->direction_output = cygnus_gpio_direction_output;
729	gc->set = cygnus_gpio_set;
730	gc->get = cygnus_gpio_get;
731
732	chip->pinmux_is_supported = of_property_read_bool(dev->of_node,
733							"gpio-ranges");
734
735	ret = gpiochip_add(gc);
736	if (ret < 0) {
737		dev_err(dev, "unable to add GPIO chip\n");
738		return ret;
739	}
740
741	ret = cygnus_gpio_register_pinconf(chip);
742	if (ret) {
743		dev_err(dev, "unable to register pinconf\n");
744		goto err_rm_gpiochip;
745	}
746
747	/* optional GPIO interrupt support */
748	irq = platform_get_irq(pdev, 0);
749	if (irq) {
750		ret = gpiochip_irqchip_add(gc, &cygnus_gpio_irq_chip, 0,
751					   handle_simple_irq, IRQ_TYPE_NONE);
752		if (ret) {
753			dev_err(dev, "no GPIO irqchip\n");
754			goto err_unregister_pinconf;
755		}
756
757		gpiochip_set_chained_irqchip(gc, &cygnus_gpio_irq_chip, irq,
758					     cygnus_gpio_irq_handler);
759	}
760
761	return 0;
762
763err_unregister_pinconf:
764	cygnus_gpio_unregister_pinconf(chip);
765
766err_rm_gpiochip:
767	gpiochip_remove(gc);
768
769	return ret;
770}
771
772static struct platform_driver cygnus_gpio_driver = {
773	.driver = {
774		.name = "cygnus-gpio",
775		.of_match_table = cygnus_gpio_of_match,
776	},
777	.probe = cygnus_gpio_probe,
778};
779
780static int __init cygnus_gpio_init(void)
781{
782	return platform_driver_probe(&cygnus_gpio_driver, cygnus_gpio_probe);
783}
784arch_initcall_sync(cygnus_gpio_init);
785