diff options
Diffstat (limited to 'drivers/pinctrl')
-rw-r--r-- | drivers/pinctrl/intel/pinctrl-baytrail.c | 100 |
1 files changed, 56 insertions, 44 deletions
diff --git a/drivers/pinctrl/intel/pinctrl-baytrail.c b/drivers/pinctrl/intel/pinctrl-baytrail.c index d264b099182d..2318057a309b 100644 --- a/drivers/pinctrl/intel/pinctrl-baytrail.c +++ b/drivers/pinctrl/intel/pinctrl-baytrail.c | |||
@@ -252,23 +252,13 @@ static int byt_irq_type(struct irq_data *d, unsigned type) | |||
252 | value &= ~(BYT_DIRECT_IRQ_EN | BYT_TRIG_POS | BYT_TRIG_NEG | | 252 | value &= ~(BYT_DIRECT_IRQ_EN | BYT_TRIG_POS | BYT_TRIG_NEG | |
253 | BYT_TRIG_LVL); | 253 | BYT_TRIG_LVL); |
254 | 254 | ||
255 | switch (type) { | ||
256 | case IRQ_TYPE_LEVEL_HIGH: | ||
257 | value |= BYT_TRIG_LVL; | ||
258 | case IRQ_TYPE_EDGE_RISING: | ||
259 | value |= BYT_TRIG_POS; | ||
260 | break; | ||
261 | case IRQ_TYPE_LEVEL_LOW: | ||
262 | value |= BYT_TRIG_LVL; | ||
263 | case IRQ_TYPE_EDGE_FALLING: | ||
264 | value |= BYT_TRIG_NEG; | ||
265 | break; | ||
266 | case IRQ_TYPE_EDGE_BOTH: | ||
267 | value |= (BYT_TRIG_NEG | BYT_TRIG_POS); | ||
268 | break; | ||
269 | } | ||
270 | writel(value, reg); | 255 | writel(value, reg); |
271 | 256 | ||
257 | if (type & IRQ_TYPE_EDGE_BOTH) | ||
258 | __irq_set_handler_locked(d->irq, handle_edge_irq); | ||
259 | else if (type & IRQ_TYPE_LEVEL_MASK) | ||
260 | __irq_set_handler_locked(d->irq, handle_level_irq); | ||
261 | |||
272 | spin_unlock_irqrestore(&vg->lock, flags); | 262 | spin_unlock_irqrestore(&vg->lock, flags); |
273 | 263 | ||
274 | return 0; | 264 | return 0; |
@@ -426,58 +416,80 @@ static void byt_gpio_irq_handler(unsigned irq, struct irq_desc *desc) | |||
426 | struct irq_data *data = irq_desc_get_irq_data(desc); | 416 | struct irq_data *data = irq_desc_get_irq_data(desc); |
427 | struct byt_gpio *vg = to_byt_gpio(irq_desc_get_handler_data(desc)); | 417 | struct byt_gpio *vg = to_byt_gpio(irq_desc_get_handler_data(desc)); |
428 | struct irq_chip *chip = irq_data_get_irq_chip(data); | 418 | struct irq_chip *chip = irq_data_get_irq_chip(data); |
429 | u32 base, pin, mask; | 419 | u32 base, pin; |
430 | void __iomem *reg; | 420 | void __iomem *reg; |
431 | u32 pending; | 421 | unsigned long pending; |
432 | unsigned virq; | 422 | unsigned virq; |
433 | int looplimit = 0; | ||
434 | 423 | ||
435 | /* check from GPIO controller which pin triggered the interrupt */ | 424 | /* check from GPIO controller which pin triggered the interrupt */ |
436 | for (base = 0; base < vg->chip.ngpio; base += 32) { | 425 | for (base = 0; base < vg->chip.ngpio; base += 32) { |
437 | |||
438 | reg = byt_gpio_reg(&vg->chip, base, BYT_INT_STAT_REG); | 426 | reg = byt_gpio_reg(&vg->chip, base, BYT_INT_STAT_REG); |
439 | 427 | pending = readl(reg); | |
440 | while ((pending = readl(reg))) { | 428 | for_each_set_bit(pin, &pending, 32) { |
441 | pin = __ffs(pending); | ||
442 | mask = BIT(pin); | ||
443 | /* Clear before handling so we can't lose an edge */ | ||
444 | writel(mask, reg); | ||
445 | |||
446 | virq = irq_find_mapping(vg->chip.irqdomain, base + pin); | 429 | virq = irq_find_mapping(vg->chip.irqdomain, base + pin); |
447 | generic_handle_irq(virq); | 430 | generic_handle_irq(virq); |
448 | |||
449 | /* In case bios or user sets triggering incorretly a pin | ||
450 | * might remain in "interrupt triggered" state. | ||
451 | */ | ||
452 | if (looplimit++ > 32) { | ||
453 | dev_err(&vg->pdev->dev, | ||
454 | "Gpio %d interrupt flood, disabling\n", | ||
455 | base + pin); | ||
456 | |||
457 | reg = byt_gpio_reg(&vg->chip, base + pin, | ||
458 | BYT_CONF0_REG); | ||
459 | mask = readl(reg); | ||
460 | mask &= ~(BYT_TRIG_NEG | BYT_TRIG_POS | | ||
461 | BYT_TRIG_LVL); | ||
462 | writel(mask, reg); | ||
463 | mask = readl(reg); /* flush */ | ||
464 | break; | ||
465 | } | ||
466 | } | 431 | } |
467 | } | 432 | } |
468 | chip->irq_eoi(data); | 433 | chip->irq_eoi(data); |
469 | } | 434 | } |
470 | 435 | ||
436 | static void byt_irq_ack(struct irq_data *d) | ||
437 | { | ||
438 | struct gpio_chip *gc = irq_data_get_irq_chip_data(d); | ||
439 | struct byt_gpio *vg = to_byt_gpio(gc); | ||
440 | unsigned offset = irqd_to_hwirq(d); | ||
441 | void __iomem *reg; | ||
442 | |||
443 | reg = byt_gpio_reg(&vg->chip, offset, BYT_INT_STAT_REG); | ||
444 | writel(BIT(offset % 32), reg); | ||
445 | } | ||
446 | |||
471 | static void byt_irq_unmask(struct irq_data *d) | 447 | static void byt_irq_unmask(struct irq_data *d) |
472 | { | 448 | { |
449 | struct gpio_chip *gc = irq_data_get_irq_chip_data(d); | ||
450 | struct byt_gpio *vg = to_byt_gpio(gc); | ||
451 | unsigned offset = irqd_to_hwirq(d); | ||
452 | unsigned long flags; | ||
453 | void __iomem *reg; | ||
454 | u32 value; | ||
455 | |||
456 | spin_lock_irqsave(&vg->lock, flags); | ||
457 | |||
458 | reg = byt_gpio_reg(&vg->chip, offset, BYT_CONF0_REG); | ||
459 | value = readl(reg); | ||
460 | |||
461 | switch (irqd_get_trigger_type(d)) { | ||
462 | case IRQ_TYPE_LEVEL_HIGH: | ||
463 | value |= BYT_TRIG_LVL; | ||
464 | case IRQ_TYPE_EDGE_RISING: | ||
465 | value |= BYT_TRIG_POS; | ||
466 | break; | ||
467 | case IRQ_TYPE_LEVEL_LOW: | ||
468 | value |= BYT_TRIG_LVL; | ||
469 | case IRQ_TYPE_EDGE_FALLING: | ||
470 | value |= BYT_TRIG_NEG; | ||
471 | break; | ||
472 | case IRQ_TYPE_EDGE_BOTH: | ||
473 | value |= (BYT_TRIG_NEG | BYT_TRIG_POS); | ||
474 | break; | ||
475 | } | ||
476 | |||
477 | writel(value, reg); | ||
478 | |||
479 | spin_unlock_irqrestore(&vg->lock, flags); | ||
473 | } | 480 | } |
474 | 481 | ||
475 | static void byt_irq_mask(struct irq_data *d) | 482 | static void byt_irq_mask(struct irq_data *d) |
476 | { | 483 | { |
484 | struct gpio_chip *gc = irq_data_get_irq_chip_data(d); | ||
485 | struct byt_gpio *vg = to_byt_gpio(gc); | ||
486 | |||
487 | byt_gpio_clear_triggering(vg, irqd_to_hwirq(d)); | ||
477 | } | 488 | } |
478 | 489 | ||
479 | static struct irq_chip byt_irqchip = { | 490 | static struct irq_chip byt_irqchip = { |
480 | .name = "BYT-GPIO", | 491 | .name = "BYT-GPIO", |
492 | .irq_ack = byt_irq_ack, | ||
481 | .irq_mask = byt_irq_mask, | 493 | .irq_mask = byt_irq_mask, |
482 | .irq_unmask = byt_irq_unmask, | 494 | .irq_unmask = byt_irq_unmask, |
483 | .irq_set_type = byt_irq_type, | 495 | .irq_set_type = byt_irq_type, |