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/bcma/bcma.h>
16 #include "bcma_private.h"
18 #define BCMA_GPIO_MAX_PINS 32
20 static int bcma_gpio_get_value(struct gpio_chip
*chip
, unsigned gpio
)
22 struct bcma_drv_cc
*cc
= gpiochip_get_data(chip
);
24 return !!bcma_chipco_gpio_in(cc
, 1 << gpio
);
27 static void bcma_gpio_set_value(struct gpio_chip
*chip
, unsigned gpio
,
30 struct bcma_drv_cc
*cc
= gpiochip_get_data(chip
);
32 bcma_chipco_gpio_out(cc
, 1 << gpio
, value
? 1 << gpio
: 0);
35 static int bcma_gpio_direction_input(struct gpio_chip
*chip
, unsigned gpio
)
37 struct bcma_drv_cc
*cc
= gpiochip_get_data(chip
);
39 bcma_chipco_gpio_outen(cc
, 1 << gpio
, 0);
43 static int bcma_gpio_direction_output(struct gpio_chip
*chip
, unsigned gpio
,
46 struct bcma_drv_cc
*cc
= gpiochip_get_data(chip
);
48 bcma_chipco_gpio_outen(cc
, 1 << gpio
, 1 << gpio
);
49 bcma_chipco_gpio_out(cc
, 1 << gpio
, value
? 1 << gpio
: 0);
53 static int bcma_gpio_request(struct gpio_chip
*chip
, unsigned gpio
)
55 struct bcma_drv_cc
*cc
= gpiochip_get_data(chip
);
57 bcma_chipco_gpio_control(cc
, 1 << gpio
, 0);
59 bcma_chipco_gpio_pulldown(cc
, 1 << gpio
, 0);
61 bcma_chipco_gpio_pullup(cc
, 1 << gpio
, 1 << gpio
);
66 static void bcma_gpio_free(struct gpio_chip
*chip
, unsigned gpio
)
68 struct bcma_drv_cc
*cc
= gpiochip_get_data(chip
);
71 bcma_chipco_gpio_pullup(cc
, 1 << gpio
, 0);
74 #if IS_BUILTIN(CONFIG_BCM47XX) || IS_BUILTIN(CONFIG_ARCH_BCM_5301X)
76 static void bcma_gpio_irq_unmask(struct irq_data
*d
)
78 struct gpio_chip
*gc
= irq_data_get_irq_chip_data(d
);
79 struct bcma_drv_cc
*cc
= gpiochip_get_data(gc
);
80 int gpio
= irqd_to_hwirq(d
);
81 u32 val
= bcma_chipco_gpio_in(cc
, BIT(gpio
));
83 bcma_chipco_gpio_polarity(cc
, BIT(gpio
), val
);
84 bcma_chipco_gpio_intmask(cc
, BIT(gpio
), BIT(gpio
));
87 static void bcma_gpio_irq_mask(struct irq_data
*d
)
89 struct gpio_chip
*gc
= irq_data_get_irq_chip_data(d
);
90 struct bcma_drv_cc
*cc
= gpiochip_get_data(gc
);
91 int gpio
= irqd_to_hwirq(d
);
93 bcma_chipco_gpio_intmask(cc
, BIT(gpio
), 0);
96 static struct irq_chip bcma_gpio_irq_chip
= {
98 .irq_mask
= bcma_gpio_irq_mask
,
99 .irq_unmask
= bcma_gpio_irq_unmask
,
102 static irqreturn_t
bcma_gpio_irq_handler(int irq
, void *dev_id
)
104 struct bcma_drv_cc
*cc
= dev_id
;
105 struct gpio_chip
*gc
= &cc
->gpio
;
106 u32 val
= bcma_cc_read32(cc
, BCMA_CC_GPIOIN
);
107 u32 mask
= bcma_cc_read32(cc
, BCMA_CC_GPIOIRQ
);
108 u32 pol
= bcma_cc_read32(cc
, BCMA_CC_GPIOPOL
);
109 unsigned long irqs
= (val
^ pol
) & mask
;
115 for_each_set_bit(gpio
, &irqs
, gc
->ngpio
)
116 generic_handle_irq(irq_find_mapping(gc
->irq
.domain
, gpio
));
117 bcma_chipco_gpio_polarity(cc
, irqs
, val
& irqs
);
122 static int bcma_gpio_irq_init(struct bcma_drv_cc
*cc
)
124 struct gpio_chip
*chip
= &cc
->gpio
;
127 if (cc
->core
->bus
->hosttype
!= BCMA_HOSTTYPE_SOC
)
130 hwirq
= bcma_core_irq(cc
->core
, 0);
131 err
= request_irq(hwirq
, bcma_gpio_irq_handler
, IRQF_SHARED
, "gpio",
136 bcma_chipco_gpio_intmask(cc
, ~0, 0);
137 bcma_cc_set32(cc
, BCMA_CC_IRQMASK
, BCMA_CC_IRQ_GPIO
);
139 err
= gpiochip_irqchip_add(chip
,
152 static void bcma_gpio_irq_exit(struct bcma_drv_cc
*cc
)
154 if (cc
->core
->bus
->hosttype
!= BCMA_HOSTTYPE_SOC
)
157 bcma_cc_mask32(cc
, BCMA_CC_IRQMASK
, ~BCMA_CC_IRQ_GPIO
);
158 free_irq(bcma_core_irq(cc
->core
, 0), cc
);
161 static int bcma_gpio_irq_init(struct bcma_drv_cc
*cc
)
166 static void bcma_gpio_irq_exit(struct bcma_drv_cc
*cc
)
171 int bcma_gpio_init(struct bcma_drv_cc
*cc
)
173 struct bcma_bus
*bus
= cc
->core
->bus
;
174 struct gpio_chip
*chip
= &cc
->gpio
;
177 chip
->label
= "bcma_gpio";
178 chip
->owner
= THIS_MODULE
;
179 chip
->request
= bcma_gpio_request
;
180 chip
->free
= bcma_gpio_free
;
181 chip
->get
= bcma_gpio_get_value
;
182 chip
->set
= bcma_gpio_set_value
;
183 chip
->direction_input
= bcma_gpio_direction_input
;
184 chip
->direction_output
= bcma_gpio_direction_output
;
185 chip
->owner
= THIS_MODULE
;
186 chip
->parent
= bcma_bus_get_host_dev(bus
);
187 #if IS_BUILTIN(CONFIG_OF)
188 chip
->of_node
= cc
->core
->dev
.of_node
;
190 switch (bus
->chipinfo
.id
) {
191 case BCMA_CHIP_ID_BCM4707
:
192 case BCMA_CHIP_ID_BCM5357
:
193 case BCMA_CHIP_ID_BCM53572
:
194 case BCMA_CHIP_ID_BCM53573
:
195 case BCMA_CHIP_ID_BCM47094
:
203 * Register SoC GPIO devices with absolute GPIO pin base.
204 * On MIPS, we don't have Device Tree and we can't use relative (per chip)
206 * On some ARM devices, user space may want to access some system GPIO
207 * pins directly, which is easier to do with a predictable GPIO base.
209 if (IS_BUILTIN(CONFIG_BCM47XX
) ||
210 cc
->core
->bus
->hosttype
== BCMA_HOSTTYPE_SOC
)
211 chip
->base
= bus
->num
* BCMA_GPIO_MAX_PINS
;
215 err
= gpiochip_add_data(chip
, cc
);
219 err
= bcma_gpio_irq_init(cc
);
221 gpiochip_remove(chip
);
228 int bcma_gpio_unregister(struct bcma_drv_cc
*cc
)
230 bcma_gpio_irq_exit(cc
);
231 gpiochip_remove(&cc
->gpio
);