2 * Broadcom specific AMBA
5 * Copyright 2011, Broadcom Corporation
6 * Copyright 2012, Hauke Mehrtens <hauke@hauke-m.de>
8 * Licensed under the GNU/GPL. See COPYING for details.
11 #include <linux/gpio/driver.h>
12 #include <linux/interrupt.h>
13 #include <linux/export.h>
14 #include <linux/property.h>
16 #include <linux/bcma/bcma.h>
18 #include "bcma_private.h"
20 #define BCMA_GPIO_MAX_PINS 32
22 static int bcma_gpio_get_value(struct gpio_chip
*chip
, unsigned gpio
)
24 struct bcma_drv_cc
*cc
= gpiochip_get_data(chip
);
26 return !!bcma_chipco_gpio_in(cc
, 1 << gpio
);
29 static void bcma_gpio_set_value(struct gpio_chip
*chip
, unsigned gpio
,
32 struct bcma_drv_cc
*cc
= gpiochip_get_data(chip
);
34 bcma_chipco_gpio_out(cc
, 1 << gpio
, value
? 1 << gpio
: 0);
37 static int bcma_gpio_direction_input(struct gpio_chip
*chip
, unsigned gpio
)
39 struct bcma_drv_cc
*cc
= gpiochip_get_data(chip
);
41 bcma_chipco_gpio_outen(cc
, 1 << gpio
, 0);
45 static int bcma_gpio_direction_output(struct gpio_chip
*chip
, unsigned gpio
,
48 struct bcma_drv_cc
*cc
= gpiochip_get_data(chip
);
50 bcma_chipco_gpio_outen(cc
, 1 << gpio
, 1 << gpio
);
51 bcma_chipco_gpio_out(cc
, 1 << gpio
, value
? 1 << gpio
: 0);
55 static int bcma_gpio_request(struct gpio_chip
*chip
, unsigned gpio
)
57 struct bcma_drv_cc
*cc
= gpiochip_get_data(chip
);
59 bcma_chipco_gpio_control(cc
, 1 << gpio
, 0);
61 bcma_chipco_gpio_pulldown(cc
, 1 << gpio
, 0);
63 bcma_chipco_gpio_pullup(cc
, 1 << gpio
, 1 << gpio
);
68 static void bcma_gpio_free(struct gpio_chip
*chip
, unsigned gpio
)
70 struct bcma_drv_cc
*cc
= gpiochip_get_data(chip
);
73 bcma_chipco_gpio_pullup(cc
, 1 << gpio
, 0);
76 #if IS_BUILTIN(CONFIG_BCM47XX) || IS_BUILTIN(CONFIG_ARCH_BCM_5301X)
78 static void bcma_gpio_irq_unmask(struct irq_data
*d
)
80 struct gpio_chip
*gc
= irq_data_get_irq_chip_data(d
);
81 struct bcma_drv_cc
*cc
= gpiochip_get_data(gc
);
82 int gpio
= irqd_to_hwirq(d
);
83 u32 val
= bcma_chipco_gpio_in(cc
, BIT(gpio
));
85 gpiochip_enable_irq(gc
, gpio
);
86 bcma_chipco_gpio_polarity(cc
, BIT(gpio
), val
);
87 bcma_chipco_gpio_intmask(cc
, BIT(gpio
), BIT(gpio
));
90 static void bcma_gpio_irq_mask(struct irq_data
*d
)
92 struct gpio_chip
*gc
= irq_data_get_irq_chip_data(d
);
93 struct bcma_drv_cc
*cc
= gpiochip_get_data(gc
);
94 int gpio
= irqd_to_hwirq(d
);
96 bcma_chipco_gpio_intmask(cc
, BIT(gpio
), 0);
97 gpiochip_disable_irq(gc
, gpio
);
100 static const struct irq_chip bcma_gpio_irq_chip
= {
102 .irq_mask
= bcma_gpio_irq_mask
,
103 .irq_unmask
= bcma_gpio_irq_unmask
,
104 .flags
= IRQCHIP_IMMUTABLE
,
105 GPIOCHIP_IRQ_RESOURCE_HELPERS
,
108 static irqreturn_t
bcma_gpio_irq_handler(int irq
, void *dev_id
)
110 struct bcma_drv_cc
*cc
= dev_id
;
111 struct gpio_chip
*gc
= &cc
->gpio
;
112 u32 val
= bcma_cc_read32(cc
, BCMA_CC_GPIOIN
);
113 u32 mask
= bcma_cc_read32(cc
, BCMA_CC_GPIOIRQ
);
114 u32 pol
= bcma_cc_read32(cc
, BCMA_CC_GPIOPOL
);
115 unsigned long irqs
= (val
^ pol
) & mask
;
121 for_each_set_bit(gpio
, &irqs
, gc
->ngpio
)
122 generic_handle_domain_irq_safe(gc
->irq
.domain
, gpio
);
123 bcma_chipco_gpio_polarity(cc
, irqs
, val
& irqs
);
128 static int bcma_gpio_irq_init(struct bcma_drv_cc
*cc
)
130 struct gpio_chip
*chip
= &cc
->gpio
;
131 struct gpio_irq_chip
*girq
= &chip
->irq
;
134 if (cc
->core
->bus
->hosttype
!= BCMA_HOSTTYPE_SOC
)
137 hwirq
= bcma_core_irq(cc
->core
, 0);
138 err
= request_irq(hwirq
, bcma_gpio_irq_handler
, IRQF_SHARED
, "gpio",
143 bcma_chipco_gpio_intmask(cc
, ~0, 0);
144 bcma_cc_set32(cc
, BCMA_CC_IRQMASK
, BCMA_CC_IRQ_GPIO
);
146 gpio_irq_chip_set_chip(girq
, &bcma_gpio_irq_chip
);
147 /* This will let us handle the parent IRQ in the driver */
148 girq
->parent_handler
= NULL
;
149 girq
->num_parents
= 0;
150 girq
->parents
= NULL
;
151 girq
->default_type
= IRQ_TYPE_NONE
;
152 girq
->handler
= handle_simple_irq
;
157 static void bcma_gpio_irq_exit(struct bcma_drv_cc
*cc
)
159 if (cc
->core
->bus
->hosttype
!= BCMA_HOSTTYPE_SOC
)
162 bcma_cc_mask32(cc
, BCMA_CC_IRQMASK
, ~BCMA_CC_IRQ_GPIO
);
163 free_irq(bcma_core_irq(cc
->core
, 0), cc
);
166 static int bcma_gpio_irq_init(struct bcma_drv_cc
*cc
)
171 static void bcma_gpio_irq_exit(struct bcma_drv_cc
*cc
)
176 int bcma_gpio_init(struct bcma_drv_cc
*cc
)
178 struct bcma_bus
*bus
= cc
->core
->bus
;
179 struct gpio_chip
*chip
= &cc
->gpio
;
182 chip
->label
= "bcma_gpio";
183 chip
->owner
= THIS_MODULE
;
184 chip
->request
= bcma_gpio_request
;
185 chip
->free
= bcma_gpio_free
;
186 chip
->get
= bcma_gpio_get_value
;
187 chip
->set
= bcma_gpio_set_value
;
188 chip
->direction_input
= bcma_gpio_direction_input
;
189 chip
->direction_output
= bcma_gpio_direction_output
;
190 chip
->parent
= bus
->dev
;
191 chip
->fwnode
= dev_fwnode(&cc
->core
->dev
);
193 switch (bus
->chipinfo
.id
) {
194 case BCMA_CHIP_ID_BCM4707
:
195 case BCMA_CHIP_ID_BCM5357
:
196 case BCMA_CHIP_ID_BCM53572
:
197 case BCMA_CHIP_ID_BCM53573
:
198 case BCMA_CHIP_ID_BCM47094
:
206 * Register SoC GPIO devices with absolute GPIO pin base.
207 * On MIPS, we don't have Device Tree and we can't use relative (per chip)
209 * On some ARM devices, user space may want to access some system GPIO
210 * pins directly, which is easier to do with a predictable GPIO base.
212 if (IS_BUILTIN(CONFIG_BCM47XX
) ||
213 cc
->core
->bus
->hosttype
== BCMA_HOSTTYPE_SOC
)
214 chip
->base
= bus
->num
* BCMA_GPIO_MAX_PINS
;
218 err
= bcma_gpio_irq_init(cc
);
222 err
= gpiochip_add_data(chip
, cc
);
224 bcma_gpio_irq_exit(cc
);
231 int bcma_gpio_unregister(struct bcma_drv_cc
*cc
)
233 bcma_gpio_irq_exit(cc
);
234 gpiochip_remove(&cc
->gpio
);