diff options
author | Mika Westerberg <mika.westerberg@linux.intel.com> | 2014-07-25 02:54:46 -0400 |
---|---|---|
committer | Linus Walleij <linus.walleij@linaro.org> | 2014-07-28 06:23:56 -0400 |
commit | 7f87210eff7a26a0215b493e9dd7322b16d8dc72 (patch) | |
tree | 1bdf99aaab68b8cc1088cb33040fead683cbac7c | |
parent | 0a6d315827eedc733d404ecff3cd4cc0e6437865 (diff) |
gpio: lynxpoint: Convert to use gpiolib irqchip
Instead of open-coding irqchip handling in the driver we can take advantage
of the new irqchip helpers provided by the gpiolib core.
While doing this we also make sure that we call gpiochip_irqchip_add()
after the gpiochip itself is registered as required.
Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
-rw-r--r-- | drivers/gpio/Kconfig | 2 | ||||
-rw-r--r-- | drivers/gpio/gpio-lynxpoint.c | 93 |
2 files changed, 26 insertions, 69 deletions
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 345da63fb0ad..255e8f00910f 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig | |||
@@ -430,7 +430,7 @@ config GPIO_GE_FPGA | |||
430 | config GPIO_LYNXPOINT | 430 | config GPIO_LYNXPOINT |
431 | tristate "Intel Lynxpoint GPIO support" | 431 | tristate "Intel Lynxpoint GPIO support" |
432 | depends on ACPI && X86 | 432 | depends on ACPI && X86 |
433 | select IRQ_DOMAIN | 433 | select GPIOLIB_IRQCHIP |
434 | help | 434 | help |
435 | driver for GPIO functionality on Intel Lynxpoint PCH chipset | 435 | driver for GPIO functionality on Intel Lynxpoint PCH chipset |
436 | Requires ACPI device enumeration code to set up a platform device. | 436 | Requires ACPI device enumeration code to set up a platform device. |
diff --git a/drivers/gpio/gpio-lynxpoint.c b/drivers/gpio/gpio-lynxpoint.c index 7c141dd850a1..ff9eb911b5e4 100644 --- a/drivers/gpio/gpio-lynxpoint.c +++ b/drivers/gpio/gpio-lynxpoint.c | |||
@@ -25,9 +25,7 @@ | |||
25 | #include <linux/types.h> | 25 | #include <linux/types.h> |
26 | #include <linux/bitops.h> | 26 | #include <linux/bitops.h> |
27 | #include <linux/interrupt.h> | 27 | #include <linux/interrupt.h> |
28 | #include <linux/irq.h> | ||
29 | #include <linux/gpio.h> | 28 | #include <linux/gpio.h> |
30 | #include <linux/irqdomain.h> | ||
31 | #include <linux/slab.h> | 29 | #include <linux/slab.h> |
32 | #include <linux/acpi.h> | 30 | #include <linux/acpi.h> |
33 | #include <linux/platform_device.h> | 31 | #include <linux/platform_device.h> |
@@ -62,7 +60,6 @@ | |||
62 | 60 | ||
63 | struct lp_gpio { | 61 | struct lp_gpio { |
64 | struct gpio_chip chip; | 62 | struct gpio_chip chip; |
65 | struct irq_domain *domain; | ||
66 | struct platform_device *pdev; | 63 | struct platform_device *pdev; |
67 | spinlock_t lock; | 64 | spinlock_t lock; |
68 | unsigned long reg_base; | 65 | unsigned long reg_base; |
@@ -151,7 +148,8 @@ static void lp_gpio_free(struct gpio_chip *chip, unsigned offset) | |||
151 | 148 | ||
152 | static int lp_irq_type(struct irq_data *d, unsigned type) | 149 | static int lp_irq_type(struct irq_data *d, unsigned type) |
153 | { | 150 | { |
154 | struct lp_gpio *lg = irq_data_get_irq_chip_data(d); | 151 | struct gpio_chip *gc = irq_data_get_irq_chip_data(d); |
152 | struct lp_gpio *lg = container_of(gc, struct lp_gpio, chip); | ||
155 | u32 hwirq = irqd_to_hwirq(d); | 153 | u32 hwirq = irqd_to_hwirq(d); |
156 | unsigned long flags; | 154 | unsigned long flags; |
157 | u32 value; | 155 | u32 value; |
@@ -236,16 +234,11 @@ static int lp_gpio_direction_output(struct gpio_chip *chip, | |||
236 | return 0; | 234 | return 0; |
237 | } | 235 | } |
238 | 236 | ||
239 | static int lp_gpio_to_irq(struct gpio_chip *chip, unsigned offset) | ||
240 | { | ||
241 | struct lp_gpio *lg = container_of(chip, struct lp_gpio, chip); | ||
242 | return irq_create_mapping(lg->domain, offset); | ||
243 | } | ||
244 | |||
245 | static void lp_gpio_irq_handler(unsigned hwirq, struct irq_desc *desc) | 237 | static void lp_gpio_irq_handler(unsigned hwirq, struct irq_desc *desc) |
246 | { | 238 | { |
247 | struct irq_data *data = irq_desc_get_irq_data(desc); | 239 | struct irq_data *data = irq_desc_get_irq_data(desc); |
248 | struct lp_gpio *lg = irq_data_get_irq_handler_data(data); | 240 | struct gpio_chip *gc = irq_desc_get_handler_data(desc); |
241 | struct lp_gpio *lg = container_of(gc, struct lp_gpio, chip); | ||
249 | struct irq_chip *chip = irq_data_get_irq_chip(data); | 242 | struct irq_chip *chip = irq_data_get_irq_chip(data); |
250 | u32 base, pin, mask; | 243 | u32 base, pin, mask; |
251 | unsigned long reg, ena, pending; | 244 | unsigned long reg, ena, pending; |
@@ -262,7 +255,7 @@ static void lp_gpio_irq_handler(unsigned hwirq, struct irq_desc *desc) | |||
262 | mask = BIT(pin); | 255 | mask = BIT(pin); |
263 | /* Clear before handling so we don't lose an edge */ | 256 | /* Clear before handling so we don't lose an edge */ |
264 | outl(mask, reg); | 257 | outl(mask, reg); |
265 | irq = irq_find_mapping(lg->domain, base + pin); | 258 | irq = irq_find_mapping(lg->chip.irqdomain, base + pin); |
266 | generic_handle_irq(irq); | 259 | generic_handle_irq(irq); |
267 | } | 260 | } |
268 | } | 261 | } |
@@ -279,7 +272,8 @@ static void lp_irq_mask(struct irq_data *d) | |||
279 | 272 | ||
280 | static void lp_irq_enable(struct irq_data *d) | 273 | static void lp_irq_enable(struct irq_data *d) |
281 | { | 274 | { |
282 | struct lp_gpio *lg = irq_data_get_irq_chip_data(d); | 275 | struct gpio_chip *gc = irq_data_get_irq_chip_data(d); |
276 | struct lp_gpio *lg = container_of(gc, struct lp_gpio, chip); | ||
283 | u32 hwirq = irqd_to_hwirq(d); | 277 | u32 hwirq = irqd_to_hwirq(d); |
284 | unsigned long reg = lp_gpio_reg(&lg->chip, hwirq, LP_INT_ENABLE); | 278 | unsigned long reg = lp_gpio_reg(&lg->chip, hwirq, LP_INT_ENABLE); |
285 | unsigned long flags; | 279 | unsigned long flags; |
@@ -291,7 +285,8 @@ static void lp_irq_enable(struct irq_data *d) | |||
291 | 285 | ||
292 | static void lp_irq_disable(struct irq_data *d) | 286 | static void lp_irq_disable(struct irq_data *d) |
293 | { | 287 | { |
294 | struct lp_gpio *lg = irq_data_get_irq_chip_data(d); | 288 | struct gpio_chip *gc = irq_data_get_irq_chip_data(d); |
289 | struct lp_gpio *lg = container_of(gc, struct lp_gpio, chip); | ||
295 | u32 hwirq = irqd_to_hwirq(d); | 290 | u32 hwirq = irqd_to_hwirq(d); |
296 | unsigned long reg = lp_gpio_reg(&lg->chip, hwirq, LP_INT_ENABLE); | 291 | unsigned long reg = lp_gpio_reg(&lg->chip, hwirq, LP_INT_ENABLE); |
297 | unsigned long flags; | 292 | unsigned long flags; |
@@ -301,26 +296,6 @@ static void lp_irq_disable(struct irq_data *d) | |||
301 | spin_unlock_irqrestore(&lg->lock, flags); | 296 | spin_unlock_irqrestore(&lg->lock, flags); |
302 | } | 297 | } |
303 | 298 | ||
304 | static int lp_irq_reqres(struct irq_data *d) | ||
305 | { | ||
306 | struct lp_gpio *lg = irq_data_get_irq_chip_data(d); | ||
307 | |||
308 | if (gpio_lock_as_irq(&lg->chip, irqd_to_hwirq(d))) { | ||
309 | dev_err(lg->chip.dev, | ||
310 | "unable to lock HW IRQ %lu for IRQ\n", | ||
311 | irqd_to_hwirq(d)); | ||
312 | return -EINVAL; | ||
313 | } | ||
314 | return 0; | ||
315 | } | ||
316 | |||
317 | static void lp_irq_relres(struct irq_data *d) | ||
318 | { | ||
319 | struct lp_gpio *lg = irq_data_get_irq_chip_data(d); | ||
320 | |||
321 | gpio_unlock_as_irq(&lg->chip, irqd_to_hwirq(d)); | ||
322 | } | ||
323 | |||
324 | static struct irq_chip lp_irqchip = { | 299 | static struct irq_chip lp_irqchip = { |
325 | .name = "LP-GPIO", | 300 | .name = "LP-GPIO", |
326 | .irq_mask = lp_irq_mask, | 301 | .irq_mask = lp_irq_mask, |
@@ -328,8 +303,6 @@ static struct irq_chip lp_irqchip = { | |||
328 | .irq_enable = lp_irq_enable, | 303 | .irq_enable = lp_irq_enable, |
329 | .irq_disable = lp_irq_disable, | 304 | .irq_disable = lp_irq_disable, |
330 | .irq_set_type = lp_irq_type, | 305 | .irq_set_type = lp_irq_type, |
331 | .irq_request_resources = lp_irq_reqres, | ||
332 | .irq_release_resources = lp_irq_relres, | ||
333 | .flags = IRQCHIP_SKIP_SET_WAKE, | 306 | .flags = IRQCHIP_SKIP_SET_WAKE, |
334 | }; | 307 | }; |
335 | 308 | ||
@@ -348,22 +321,6 @@ static void lp_gpio_irq_init_hw(struct lp_gpio *lg) | |||
348 | } | 321 | } |
349 | } | 322 | } |
350 | 323 | ||
351 | static int lp_gpio_irq_map(struct irq_domain *d, unsigned int irq, | ||
352 | irq_hw_number_t hwirq) | ||
353 | { | ||
354 | struct lp_gpio *lg = d->host_data; | ||
355 | |||
356 | irq_set_chip_and_handler(irq, &lp_irqchip, handle_simple_irq); | ||
357 | irq_set_chip_data(irq, lg); | ||
358 | irq_set_irq_type(irq, IRQ_TYPE_NONE); | ||
359 | |||
360 | return 0; | ||
361 | } | ||
362 | |||
363 | static const struct irq_domain_ops lp_gpio_irq_ops = { | ||
364 | .map = lp_gpio_irq_map, | ||
365 | }; | ||
366 | |||
367 | static int lp_gpio_probe(struct platform_device *pdev) | 324 | static int lp_gpio_probe(struct platform_device *pdev) |
368 | { | 325 | { |
369 | struct lp_gpio *lg; | 326 | struct lp_gpio *lg; |
@@ -371,7 +328,6 @@ static int lp_gpio_probe(struct platform_device *pdev) | |||
371 | struct resource *io_rc, *irq_rc; | 328 | struct resource *io_rc, *irq_rc; |
372 | struct device *dev = &pdev->dev; | 329 | struct device *dev = &pdev->dev; |
373 | unsigned long reg_len; | 330 | unsigned long reg_len; |
374 | unsigned hwirq; | ||
375 | int ret = -ENODEV; | 331 | int ret = -ENODEV; |
376 | 332 | ||
377 | lg = devm_kzalloc(dev, sizeof(struct lp_gpio), GFP_KERNEL); | 333 | lg = devm_kzalloc(dev, sizeof(struct lp_gpio), GFP_KERNEL); |
@@ -414,27 +370,28 @@ static int lp_gpio_probe(struct platform_device *pdev) | |||
414 | gc->can_sleep = false; | 370 | gc->can_sleep = false; |
415 | gc->dev = dev; | 371 | gc->dev = dev; |
416 | 372 | ||
373 | ret = gpiochip_add(gc); | ||
374 | if (ret) { | ||
375 | dev_err(dev, "failed adding lp-gpio chip\n"); | ||
376 | return ret; | ||
377 | } | ||
378 | |||
417 | /* set up interrupts */ | 379 | /* set up interrupts */ |
418 | if (irq_rc && irq_rc->start) { | 380 | if (irq_rc && irq_rc->start) { |
419 | hwirq = irq_rc->start; | ||
420 | gc->to_irq = lp_gpio_to_irq; | ||
421 | |||
422 | lg->domain = irq_domain_add_linear(NULL, LP_NUM_GPIO, | ||
423 | &lp_gpio_irq_ops, lg); | ||
424 | if (!lg->domain) | ||
425 | return -ENXIO; | ||
426 | |||
427 | lp_gpio_irq_init_hw(lg); | 381 | lp_gpio_irq_init_hw(lg); |
382 | ret = gpiochip_irqchip_add(gc, &lp_irqchip, 0, | ||
383 | handle_simple_irq, IRQ_TYPE_NONE); | ||
384 | if (ret) { | ||
385 | dev_err(dev, "failed to add irqchip\n"); | ||
386 | gpiochip_remove(gc); | ||
387 | return ret; | ||
388 | } | ||
428 | 389 | ||
429 | irq_set_handler_data(hwirq, lg); | 390 | gpiochip_set_chained_irqchip(gc, &lp_irqchip, |
430 | irq_set_chained_handler(hwirq, lp_gpio_irq_handler); | 391 | (unsigned)irq_rc->start, |
392 | lp_gpio_irq_handler); | ||
431 | } | 393 | } |
432 | 394 | ||
433 | ret = gpiochip_add(gc); | ||
434 | if (ret) { | ||
435 | dev_err(dev, "failed adding lp-gpio chip\n"); | ||
436 | return ret; | ||
437 | } | ||
438 | pm_runtime_enable(dev); | 395 | pm_runtime_enable(dev); |
439 | 396 | ||
440 | return 0; | 397 | return 0; |