diff options
author | Linus Walleij <linus.walleij@linaro.org> | 2014-05-29 10:55:55 -0400 |
---|---|---|
committer | Linus Walleij <linus.walleij@linaro.org> | 2014-06-19 03:31:16 -0400 |
commit | 3f7dbfd8eea9a2989485886029b1bd2a6b441f3e (patch) | |
tree | 8c19f6747c0299edc94622e023cf8a855d9933aa /drivers/gpio | |
parent | fe44e70db0544e24cd1d00fc594b6e5b0afd333b (diff) |
gpio: intel-mid: switch to using gpiolib irqchip helpers
This switches the Intel MID GPIO driver over to using the gpiolib
irqchip helpers in the gpiolib core.
Cc: xinhui.pan <xinhuiX.pan@intel.com>
Acked-by: David Cohen <david.a.cohen@linux.intel.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Diffstat (limited to 'drivers/gpio')
-rw-r--r-- | drivers/gpio/gpio-intel-mid.c | 86 |
1 files changed, 25 insertions, 61 deletions
diff --git a/drivers/gpio/gpio-intel-mid.c b/drivers/gpio/gpio-intel-mid.c index 118a6bf455d9..aa28c65eb6b4 100644 --- a/drivers/gpio/gpio-intel-mid.c +++ b/drivers/gpio/gpio-intel-mid.c | |||
@@ -28,12 +28,10 @@ | |||
28 | #include <linux/stddef.h> | 28 | #include <linux/stddef.h> |
29 | #include <linux/interrupt.h> | 29 | #include <linux/interrupt.h> |
30 | #include <linux/init.h> | 30 | #include <linux/init.h> |
31 | #include <linux/irq.h> | ||
32 | #include <linux/io.h> | 31 | #include <linux/io.h> |
33 | #include <linux/gpio.h> | 32 | #include <linux/gpio/driver.h> |
34 | #include <linux/slab.h> | 33 | #include <linux/slab.h> |
35 | #include <linux/pm_runtime.h> | 34 | #include <linux/pm_runtime.h> |
36 | #include <linux/irqdomain.h> | ||
37 | 35 | ||
38 | #define INTEL_MID_IRQ_TYPE_EDGE (1 << 0) | 36 | #define INTEL_MID_IRQ_TYPE_EDGE (1 << 0) |
39 | #define INTEL_MID_IRQ_TYPE_LEVEL (1 << 1) | 37 | #define INTEL_MID_IRQ_TYPE_LEVEL (1 << 1) |
@@ -78,10 +76,12 @@ struct intel_mid_gpio { | |||
78 | void __iomem *reg_base; | 76 | void __iomem *reg_base; |
79 | spinlock_t lock; | 77 | spinlock_t lock; |
80 | struct pci_dev *pdev; | 78 | struct pci_dev *pdev; |
81 | struct irq_domain *domain; | ||
82 | }; | 79 | }; |
83 | 80 | ||
84 | #define to_intel_gpio_priv(chip) container_of(chip, struct intel_mid_gpio, chip) | 81 | static inline struct intel_mid_gpio *to_intel_gpio_priv(struct gpio_chip *gc) |
82 | { | ||
83 | return container_of(gc, struct intel_mid_gpio, chip); | ||
84 | } | ||
85 | 85 | ||
86 | static void __iomem *gpio_reg(struct gpio_chip *chip, unsigned offset, | 86 | static void __iomem *gpio_reg(struct gpio_chip *chip, unsigned offset, |
87 | enum GPIO_REG reg_type) | 87 | enum GPIO_REG reg_type) |
@@ -182,15 +182,10 @@ static int intel_gpio_direction_output(struct gpio_chip *chip, | |||
182 | return 0; | 182 | return 0; |
183 | } | 183 | } |
184 | 184 | ||
185 | static int intel_gpio_to_irq(struct gpio_chip *chip, unsigned offset) | ||
186 | { | ||
187 | struct intel_mid_gpio *priv = to_intel_gpio_priv(chip); | ||
188 | return irq_create_mapping(priv->domain, offset); | ||
189 | } | ||
190 | |||
191 | static int intel_mid_irq_type(struct irq_data *d, unsigned type) | 185 | static int intel_mid_irq_type(struct irq_data *d, unsigned type) |
192 | { | 186 | { |
193 | struct intel_mid_gpio *priv = irq_data_get_irq_chip_data(d); | 187 | struct gpio_chip *gc = irq_data_get_irq_chip_data(d); |
188 | struct intel_mid_gpio *priv = to_intel_gpio_priv(gc); | ||
194 | u32 gpio = irqd_to_hwirq(d); | 189 | u32 gpio = irqd_to_hwirq(d); |
195 | unsigned long flags; | 190 | unsigned long flags; |
196 | u32 value; | 191 | u32 value; |
@@ -231,33 +226,11 @@ static void intel_mid_irq_mask(struct irq_data *d) | |||
231 | { | 226 | { |
232 | } | 227 | } |
233 | 228 | ||
234 | static int intel_mid_irq_reqres(struct irq_data *d) | ||
235 | { | ||
236 | struct intel_mid_gpio *priv = irq_data_get_irq_chip_data(d); | ||
237 | |||
238 | if (gpio_lock_as_irq(&priv->chip, irqd_to_hwirq(d))) { | ||
239 | dev_err(priv->chip.dev, | ||
240 | "unable to lock HW IRQ %lu for IRQ\n", | ||
241 | irqd_to_hwirq(d)); | ||
242 | return -EINVAL; | ||
243 | } | ||
244 | return 0; | ||
245 | } | ||
246 | |||
247 | static void intel_mid_irq_relres(struct irq_data *d) | ||
248 | { | ||
249 | struct intel_mid_gpio *priv = irq_data_get_irq_chip_data(d); | ||
250 | |||
251 | gpio_unlock_as_irq(&priv->chip, irqd_to_hwirq(d)); | ||
252 | } | ||
253 | |||
254 | static struct irq_chip intel_mid_irqchip = { | 229 | static struct irq_chip intel_mid_irqchip = { |
255 | .name = "INTEL_MID-GPIO", | 230 | .name = "INTEL_MID-GPIO", |
256 | .irq_mask = intel_mid_irq_mask, | 231 | .irq_mask = intel_mid_irq_mask, |
257 | .irq_unmask = intel_mid_irq_unmask, | 232 | .irq_unmask = intel_mid_irq_unmask, |
258 | .irq_set_type = intel_mid_irq_type, | 233 | .irq_set_type = intel_mid_irq_type, |
259 | .irq_request_resources = intel_mid_irq_reqres, | ||
260 | .irq_release_resources = intel_mid_irq_relres, | ||
261 | }; | 234 | }; |
262 | 235 | ||
263 | static const struct intel_mid_gpio_ddata gpio_lincroft = { | 236 | static const struct intel_mid_gpio_ddata gpio_lincroft = { |
@@ -330,8 +303,9 @@ MODULE_DEVICE_TABLE(pci, intel_gpio_ids); | |||
330 | 303 | ||
331 | static void intel_mid_irq_handler(unsigned irq, struct irq_desc *desc) | 304 | static void intel_mid_irq_handler(unsigned irq, struct irq_desc *desc) |
332 | { | 305 | { |
306 | struct gpio_chip *gc = irq_desc_get_handler_data(desc); | ||
307 | struct intel_mid_gpio *priv = to_intel_gpio_priv(gc); | ||
333 | struct irq_data *data = irq_desc_get_irq_data(desc); | 308 | struct irq_data *data = irq_desc_get_irq_data(desc); |
334 | struct intel_mid_gpio *priv = irq_data_get_irq_handler_data(data); | ||
335 | struct irq_chip *chip = irq_data_get_irq_chip(data); | 309 | struct irq_chip *chip = irq_data_get_irq_chip(data); |
336 | u32 base, gpio, mask; | 310 | u32 base, gpio, mask; |
337 | unsigned long pending; | 311 | unsigned long pending; |
@@ -345,7 +319,7 @@ static void intel_mid_irq_handler(unsigned irq, struct irq_desc *desc) | |||
345 | mask = BIT(gpio); | 319 | mask = BIT(gpio); |
346 | /* Clear before handling so we can't lose an edge */ | 320 | /* Clear before handling so we can't lose an edge */ |
347 | writel(mask, gedr); | 321 | writel(mask, gedr); |
348 | generic_handle_irq(irq_find_mapping(priv->domain, | 322 | generic_handle_irq(irq_find_mapping(gc->irqdomain, |
349 | base + gpio)); | 323 | base + gpio)); |
350 | } | 324 | } |
351 | } | 325 | } |
@@ -371,23 +345,6 @@ static void intel_mid_irq_init_hw(struct intel_mid_gpio *priv) | |||
371 | } | 345 | } |
372 | } | 346 | } |
373 | 347 | ||
374 | static int intel_gpio_irq_map(struct irq_domain *d, unsigned int irq, | ||
375 | irq_hw_number_t hwirq) | ||
376 | { | ||
377 | struct intel_mid_gpio *priv = d->host_data; | ||
378 | |||
379 | irq_set_chip_and_handler(irq, &intel_mid_irqchip, handle_simple_irq); | ||
380 | irq_set_chip_data(irq, priv); | ||
381 | irq_set_irq_type(irq, IRQ_TYPE_NONE); | ||
382 | |||
383 | return 0; | ||
384 | } | ||
385 | |||
386 | static const struct irq_domain_ops intel_gpio_irq_ops = { | ||
387 | .map = intel_gpio_irq_map, | ||
388 | .xlate = irq_domain_xlate_twocell, | ||
389 | }; | ||
390 | |||
391 | static int intel_gpio_runtime_idle(struct device *dev) | 348 | static int intel_gpio_runtime_idle(struct device *dev) |
392 | { | 349 | { |
393 | int err = pm_schedule_suspend(dev, 500); | 350 | int err = pm_schedule_suspend(dev, 500); |
@@ -441,7 +398,6 @@ static int intel_gpio_probe(struct pci_dev *pdev, | |||
441 | priv->chip.direction_output = intel_gpio_direction_output; | 398 | priv->chip.direction_output = intel_gpio_direction_output; |
442 | priv->chip.get = intel_gpio_get; | 399 | priv->chip.get = intel_gpio_get; |
443 | priv->chip.set = intel_gpio_set; | 400 | priv->chip.set = intel_gpio_set; |
444 | priv->chip.to_irq = intel_gpio_to_irq; | ||
445 | priv->chip.base = gpio_base; | 401 | priv->chip.base = gpio_base; |
446 | priv->chip.ngpio = ddata->ngpio; | 402 | priv->chip.ngpio = ddata->ngpio; |
447 | priv->chip.can_sleep = false; | 403 | priv->chip.can_sleep = false; |
@@ -449,11 +405,6 @@ static int intel_gpio_probe(struct pci_dev *pdev, | |||
449 | 405 | ||
450 | spin_lock_init(&priv->lock); | 406 | spin_lock_init(&priv->lock); |
451 | 407 | ||
452 | priv->domain = irq_domain_add_simple(pdev->dev.of_node, ddata->ngpio, | ||
453 | irq_base, &intel_gpio_irq_ops, priv); | ||
454 | if (!priv->domain) | ||
455 | return -ENOMEM; | ||
456 | |||
457 | pci_set_drvdata(pdev, priv); | 408 | pci_set_drvdata(pdev, priv); |
458 | retval = gpiochip_add(&priv->chip); | 409 | retval = gpiochip_add(&priv->chip); |
459 | if (retval) { | 410 | if (retval) { |
@@ -461,10 +412,23 @@ static int intel_gpio_probe(struct pci_dev *pdev, | |||
461 | return retval; | 412 | return retval; |
462 | } | 413 | } |
463 | 414 | ||
415 | retval = gpiochip_irqchip_add(&priv->chip, | ||
416 | &intel_mid_irqchip, | ||
417 | irq_base, | ||
418 | handle_simple_irq, | ||
419 | IRQ_TYPE_NONE); | ||
420 | if (retval) { | ||
421 | dev_err(&pdev->dev, | ||
422 | "could not connect irqchip to gpiochip\n"); | ||
423 | return retval; | ||
424 | } | ||
425 | |||
464 | intel_mid_irq_init_hw(priv); | 426 | intel_mid_irq_init_hw(priv); |
465 | 427 | ||
466 | irq_set_handler_data(pdev->irq, priv); | 428 | gpiochip_set_chained_irqchip(&priv->chip, |
467 | irq_set_chained_handler(pdev->irq, intel_mid_irq_handler); | 429 | &intel_mid_irqchip, |
430 | pdev->irq, | ||
431 | intel_mid_irq_handler); | ||
468 | 432 | ||
469 | pm_runtime_put_noidle(&pdev->dev); | 433 | pm_runtime_put_noidle(&pdev->dev); |
470 | pm_runtime_allow(&pdev->dev); | 434 | pm_runtime_allow(&pdev->dev); |