diff options
author | Linus Walleij <linus.walleij@linaro.org> | 2014-03-25 05:42:35 -0400 |
---|---|---|
committer | Linus Walleij <linus.walleij@linaro.org> | 2014-03-26 05:31:33 -0400 |
commit | 8d5b24bd30c23930e666813ea0adc4672ea58c62 (patch) | |
tree | 1f0d7d96bd8c4a81719ca514e8c8301f7706a423 | |
parent | 1425052097b53de841e064dc190a9009480c208c (diff) |
gpio: pl061: convert driver to use gpiolib irqchip
This converts the PL061 driver to register its chained irq
handler and irqchip using the helpers in the gpiolib core.
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
-rw-r--r-- | drivers/gpio/Kconfig | 1 | ||||
-rw-r--r-- | drivers/gpio/gpio-pl061.c | 80 |
2 files changed, 19 insertions, 62 deletions
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 51c782532687..92d8e9a064b4 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig | |||
@@ -247,6 +247,7 @@ config GPIO_PL061 | |||
247 | bool "PrimeCell PL061 GPIO support" | 247 | bool "PrimeCell PL061 GPIO support" |
248 | depends on ARM_AMBA | 248 | depends on ARM_AMBA |
249 | select IRQ_DOMAIN | 249 | select IRQ_DOMAIN |
250 | select GPIOLIB_IRQCHIP | ||
250 | help | 251 | help |
251 | Say yes here to support the PrimeCell PL061 GPIO device | 252 | Say yes here to support the PrimeCell PL061 GPIO device |
252 | 253 | ||
diff --git a/drivers/gpio/gpio-pl061.c b/drivers/gpio/gpio-pl061.c index d2a0ad5fc752..b0f475243cef 100644 --- a/drivers/gpio/gpio-pl061.c +++ b/drivers/gpio/gpio-pl061.c | |||
@@ -15,7 +15,6 @@ | |||
15 | #include <linux/io.h> | 15 | #include <linux/io.h> |
16 | #include <linux/ioport.h> | 16 | #include <linux/ioport.h> |
17 | #include <linux/irq.h> | 17 | #include <linux/irq.h> |
18 | #include <linux/irqdomain.h> | ||
19 | #include <linux/irqchip/chained_irq.h> | 18 | #include <linux/irqchip/chained_irq.h> |
20 | #include <linux/bitops.h> | 19 | #include <linux/bitops.h> |
21 | #include <linux/workqueue.h> | 20 | #include <linux/workqueue.h> |
@@ -53,7 +52,6 @@ struct pl061_gpio { | |||
53 | spinlock_t lock; | 52 | spinlock_t lock; |
54 | 53 | ||
55 | void __iomem *base; | 54 | void __iomem *base; |
56 | struct irq_domain *domain; | ||
57 | struct gpio_chip gc; | 55 | struct gpio_chip gc; |
58 | 56 | ||
59 | #ifdef CONFIG_PM | 57 | #ifdef CONFIG_PM |
@@ -137,16 +135,10 @@ static void pl061_set_value(struct gpio_chip *gc, unsigned offset, int value) | |||
137 | writeb(!!value << offset, chip->base + (1 << (offset + 2))); | 135 | writeb(!!value << offset, chip->base + (1 << (offset + 2))); |
138 | } | 136 | } |
139 | 137 | ||
140 | static int pl061_to_irq(struct gpio_chip *gc, unsigned offset) | ||
141 | { | ||
142 | struct pl061_gpio *chip = container_of(gc, struct pl061_gpio, gc); | ||
143 | |||
144 | return irq_create_mapping(chip->domain, offset); | ||
145 | } | ||
146 | |||
147 | static int pl061_irq_type(struct irq_data *d, unsigned trigger) | 138 | static int pl061_irq_type(struct irq_data *d, unsigned trigger) |
148 | { | 139 | { |
149 | struct pl061_gpio *chip = irq_data_get_irq_chip_data(d); | 140 | struct gpio_chip *gc = irq_data_get_irq_chip_data(d); |
141 | struct pl061_gpio *chip = container_of(gc, struct pl061_gpio, gc); | ||
150 | int offset = irqd_to_hwirq(d); | 142 | int offset = irqd_to_hwirq(d); |
151 | unsigned long flags; | 143 | unsigned long flags; |
152 | u8 gpiois, gpioibe, gpioiev; | 144 | u8 gpiois, gpioibe, gpioiev; |
@@ -194,7 +186,8 @@ static void pl061_irq_handler(unsigned irq, struct irq_desc *desc) | |||
194 | { | 186 | { |
195 | unsigned long pending; | 187 | unsigned long pending; |
196 | int offset; | 188 | int offset; |
197 | struct pl061_gpio *chip = irq_desc_get_handler_data(desc); | 189 | struct gpio_chip *gc = irq_desc_get_handler_data(desc); |
190 | struct pl061_gpio *chip = container_of(gc, struct pl061_gpio, gc); | ||
198 | struct irq_chip *irqchip = irq_desc_get_chip(desc); | 191 | struct irq_chip *irqchip = irq_desc_get_chip(desc); |
199 | 192 | ||
200 | chained_irq_enter(irqchip, desc); | 193 | chained_irq_enter(irqchip, desc); |
@@ -203,7 +196,8 @@ static void pl061_irq_handler(unsigned irq, struct irq_desc *desc) | |||
203 | writeb(pending, chip->base + GPIOIC); | 196 | writeb(pending, chip->base + GPIOIC); |
204 | if (pending) { | 197 | if (pending) { |
205 | for_each_set_bit(offset, &pending, PL061_GPIO_NR) | 198 | for_each_set_bit(offset, &pending, PL061_GPIO_NR) |
206 | generic_handle_irq(pl061_to_irq(&chip->gc, offset)); | 199 | generic_handle_irq(irq_find_mapping(gc->irqdomain, |
200 | offset)); | ||
207 | } | 201 | } |
208 | 202 | ||
209 | chained_irq_exit(irqchip, desc); | 203 | chained_irq_exit(irqchip, desc); |
@@ -211,7 +205,8 @@ static void pl061_irq_handler(unsigned irq, struct irq_desc *desc) | |||
211 | 205 | ||
212 | static void pl061_irq_mask(struct irq_data *d) | 206 | static void pl061_irq_mask(struct irq_data *d) |
213 | { | 207 | { |
214 | struct pl061_gpio *chip = irq_data_get_irq_chip_data(d); | 208 | struct gpio_chip *gc = irq_data_get_irq_chip_data(d); |
209 | struct pl061_gpio *chip = container_of(gc, struct pl061_gpio, gc); | ||
215 | u8 mask = 1 << (irqd_to_hwirq(d) % PL061_GPIO_NR); | 210 | u8 mask = 1 << (irqd_to_hwirq(d) % PL061_GPIO_NR); |
216 | u8 gpioie; | 211 | u8 gpioie; |
217 | 212 | ||
@@ -223,7 +218,8 @@ static void pl061_irq_mask(struct irq_data *d) | |||
223 | 218 | ||
224 | static void pl061_irq_unmask(struct irq_data *d) | 219 | static void pl061_irq_unmask(struct irq_data *d) |
225 | { | 220 | { |
226 | struct pl061_gpio *chip = irq_data_get_irq_chip_data(d); | 221 | struct gpio_chip *gc = irq_data_get_irq_chip_data(d); |
222 | struct pl061_gpio *chip = container_of(gc, struct pl061_gpio, gc); | ||
227 | u8 mask = 1 << (irqd_to_hwirq(d) % PL061_GPIO_NR); | 223 | u8 mask = 1 << (irqd_to_hwirq(d) % PL061_GPIO_NR); |
228 | u8 gpioie; | 224 | u8 gpioie; |
229 | 225 | ||
@@ -233,50 +229,11 @@ static void pl061_irq_unmask(struct irq_data *d) | |||
233 | spin_unlock(&chip->lock); | 229 | spin_unlock(&chip->lock); |
234 | } | 230 | } |
235 | 231 | ||
236 | static int pl061_irq_reqres(struct irq_data *d) | ||
237 | { | ||
238 | struct pl061_gpio *chip = irq_data_get_irq_chip_data(d); | ||
239 | |||
240 | if (gpio_lock_as_irq(&chip->gc, irqd_to_hwirq(d))) { | ||
241 | dev_err(chip->gc.dev, | ||
242 | "unable to lock HW IRQ %lu for IRQ\n", | ||
243 | irqd_to_hwirq(d)); | ||
244 | return -EINVAL; | ||
245 | } | ||
246 | return 0; | ||
247 | } | ||
248 | |||
249 | static void pl061_irq_relres(struct irq_data *d) | ||
250 | { | ||
251 | struct pl061_gpio *chip = irq_data_get_irq_chip_data(d); | ||
252 | |||
253 | gpio_unlock_as_irq(&chip->gc, irqd_to_hwirq(d)); | ||
254 | } | ||
255 | |||
256 | static struct irq_chip pl061_irqchip = { | 232 | static struct irq_chip pl061_irqchip = { |
257 | .name = "pl061", | 233 | .name = "pl061", |
258 | .irq_mask = pl061_irq_mask, | 234 | .irq_mask = pl061_irq_mask, |
259 | .irq_unmask = pl061_irq_unmask, | 235 | .irq_unmask = pl061_irq_unmask, |
260 | .irq_set_type = pl061_irq_type, | 236 | .irq_set_type = pl061_irq_type, |
261 | .irq_request_resources = pl061_irq_reqres, | ||
262 | .irq_release_resources = pl061_irq_relres, | ||
263 | }; | ||
264 | |||
265 | static int pl061_irq_map(struct irq_domain *d, unsigned int irq, | ||
266 | irq_hw_number_t hwirq) | ||
267 | { | ||
268 | struct pl061_gpio *chip = d->host_data; | ||
269 | |||
270 | irq_set_chip_and_handler(irq, &pl061_irqchip, handle_simple_irq); | ||
271 | irq_set_chip_data(irq, chip); | ||
272 | irq_set_irq_type(irq, IRQ_TYPE_NONE); | ||
273 | |||
274 | return 0; | ||
275 | } | ||
276 | |||
277 | static const struct irq_domain_ops pl061_domain_ops = { | ||
278 | .map = pl061_irq_map, | ||
279 | .xlate = irq_domain_xlate_twocell, | ||
280 | }; | 237 | }; |
281 | 238 | ||
282 | static int pl061_probe(struct amba_device *adev, const struct amba_id *id) | 239 | static int pl061_probe(struct amba_device *adev, const struct amba_id *id) |
@@ -314,7 +271,6 @@ static int pl061_probe(struct amba_device *adev, const struct amba_id *id) | |||
314 | chip->gc.direction_output = pl061_direction_output; | 271 | chip->gc.direction_output = pl061_direction_output; |
315 | chip->gc.get = pl061_get_value; | 272 | chip->gc.get = pl061_get_value; |
316 | chip->gc.set = pl061_set_value; | 273 | chip->gc.set = pl061_set_value; |
317 | chip->gc.to_irq = pl061_to_irq; | ||
318 | chip->gc.ngpio = PL061_GPIO_NR; | 274 | chip->gc.ngpio = PL061_GPIO_NR; |
319 | chip->gc.label = dev_name(dev); | 275 | chip->gc.label = dev_name(dev); |
320 | chip->gc.dev = dev; | 276 | chip->gc.dev = dev; |
@@ -334,15 +290,15 @@ static int pl061_probe(struct amba_device *adev, const struct amba_id *id) | |||
334 | return -ENODEV; | 290 | return -ENODEV; |
335 | } | 291 | } |
336 | 292 | ||
337 | irq_set_chained_handler(irq, pl061_irq_handler); | 293 | ret = gpiochip_irqchip_add(&chip->gc, &pl061_irqchip, |
338 | irq_set_handler_data(irq, chip); | 294 | irq_base, handle_simple_irq, |
339 | 295 | IRQ_TYPE_NONE); | |
340 | chip->domain = irq_domain_add_simple(adev->dev.of_node, PL061_GPIO_NR, | 296 | if (ret) { |
341 | irq_base, &pl061_domain_ops, chip); | 297 | dev_info(&adev->dev, "could not add irqchip\n"); |
342 | if (!chip->domain) { | 298 | return ret; |
343 | dev_err(&adev->dev, "no irq domain\n"); | ||
344 | return -ENODEV; | ||
345 | } | 299 | } |
300 | gpiochip_set_chained_irqchip(&chip->gc, &pl061_irqchip, | ||
301 | irq, pl061_irq_handler); | ||
346 | 302 | ||
347 | for (i = 0; i < PL061_GPIO_NR; i++) { | 303 | for (i = 0; i < PL061_GPIO_NR; i++) { |
348 | if (pdata) { | 304 | if (pdata) { |