diff options
author | Lee Jones <lee.jones@linaro.org> | 2013-02-25 09:57:35 -0500 |
---|---|---|
committer | Lee Jones <lee.jones@linaro.org> | 2013-03-06 23:27:47 -0500 |
commit | 3e1a498f2728476535571d270081a17fdfceaf26 (patch) | |
tree | 98666d5be9dd27fb05d65842d5dc4f860bdf22b1 | |
parent | 4b106fb9895c7edba2acd41c152e8f6edf724651 (diff) |
mfd: ab8500-core: Add Interrupt support for ab8540
ITSource/ITLatch 7, 8, 9 and 10 don't exist on AB8540. This patch
replaces them with '-1' in the interrupt list, and handles the '-1'
in the code accordingly.
Signed-off-by: Lee Jones <lee.jones@linaro.org>
Acked-by: Samuel Ortiz <sameo@linux.intel.com>
-rw-r--r-- | drivers/mfd/ab8500-core.c | 50 | ||||
-rw-r--r-- | include/linux/mfd/abx500/ab8500.h | 1 |
2 files changed, 44 insertions, 7 deletions
diff --git a/drivers/mfd/ab8500-core.c b/drivers/mfd/ab8500-core.c index 23db4fcea496..0ba08a26cf73 100644 --- a/drivers/mfd/ab8500-core.c +++ b/drivers/mfd/ab8500-core.c | |||
@@ -103,8 +103,10 @@ | |||
103 | #define AB8500_IT_LATCHHIER1_REG 0x60 | 103 | #define AB8500_IT_LATCHHIER1_REG 0x60 |
104 | #define AB8500_IT_LATCHHIER2_REG 0x61 | 104 | #define AB8500_IT_LATCHHIER2_REG 0x61 |
105 | #define AB8500_IT_LATCHHIER3_REG 0x62 | 105 | #define AB8500_IT_LATCHHIER3_REG 0x62 |
106 | #define AB8540_IT_LATCHHIER4_REG 0x63 | ||
106 | 107 | ||
107 | #define AB8500_IT_LATCHHIER_NUM 3 | 108 | #define AB8500_IT_LATCHHIER_NUM 3 |
109 | #define AB8540_IT_LATCHHIER_NUM 4 | ||
108 | 110 | ||
109 | #define AB8500_REV_REG 0x80 | 111 | #define AB8500_REV_REG 0x80 |
110 | #define AB8500_IC_NAME_REG 0x82 | 112 | #define AB8500_IC_NAME_REG 0x82 |
@@ -143,6 +145,12 @@ static const int ab9540_irq_regoffset[AB9540_NUM_IRQ_REGS] = { | |||
143 | 0, 1, 2, 3, 4, 6, 7, 8, 9, 11, 18, 19, 20, 21, 12, 13, 24, 5, 22, 23 | 145 | 0, 1, 2, 3, 4, 6, 7, 8, 9, 11, 18, 19, 20, 21, 12, 13, 24, 5, 22, 23 |
144 | }; | 146 | }; |
145 | 147 | ||
148 | /* AB8540 support */ | ||
149 | static const int ab8540_irq_regoffset[AB8540_NUM_IRQ_REGS] = { | ||
150 | 0, 1, 2, 3, 4, -1, -1, -1, -1, 11, 18, 19, 20, 21, 12, 13, 24, 5, 22, 23, | ||
151 | 25, 26, 27, 28, 29, 30, 31, | ||
152 | }; | ||
153 | |||
146 | static const char ab8500_version_str[][7] = { | 154 | static const char ab8500_version_str[][7] = { |
147 | [AB8500_VERSION_AB8500] = "AB8500", | 155 | [AB8500_VERSION_AB8500] = "AB8500", |
148 | [AB8500_VERSION_AB8505] = "AB8505", | 156 | [AB8500_VERSION_AB8505] = "AB8505", |
@@ -360,6 +368,9 @@ static void ab8500_irq_sync_unlock(struct irq_data *data) | |||
360 | is_ab8500_1p1_or_earlier(ab8500)) | 368 | is_ab8500_1p1_or_earlier(ab8500)) |
361 | continue; | 369 | continue; |
362 | 370 | ||
371 | if (ab8500->irq_reg_offset[i] < 0) | ||
372 | continue; | ||
373 | |||
363 | ab8500->oldmask[i] = new; | 374 | ab8500->oldmask[i] = new; |
364 | 375 | ||
365 | reg = AB8500_IT_MASK1_REG + ab8500->irq_reg_offset[i]; | 376 | reg = AB8500_IT_MASK1_REG + ab8500->irq_reg_offset[i]; |
@@ -431,6 +442,18 @@ static struct irq_chip ab8500_irq_chip = { | |||
431 | .irq_set_type = ab8500_irq_set_type, | 442 | .irq_set_type = ab8500_irq_set_type, |
432 | }; | 443 | }; |
433 | 444 | ||
445 | static void update_latch_offset(u8 *offset, int i) | ||
446 | { | ||
447 | /* Fix inconsistent ITFromLatch25 bit mapping... */ | ||
448 | if (unlikely(*offset == 17)) | ||
449 | *offset = 24; | ||
450 | /* Fix inconsistent ab8540 bit mapping... */ | ||
451 | if (unlikely(*offset == 16)) | ||
452 | *offset = 25; | ||
453 | if ((i==3) && (*offset >= 24)) | ||
454 | *offset += 2; | ||
455 | } | ||
456 | |||
434 | static int ab8500_handle_hierarchical_line(struct ab8500 *ab8500, | 457 | static int ab8500_handle_hierarchical_line(struct ab8500 *ab8500, |
435 | int latch_offset, u8 latch_val) | 458 | int latch_offset, u8 latch_val) |
436 | { | 459 | { |
@@ -482,9 +505,7 @@ static int ab8500_handle_hierarchical_latch(struct ab8500 *ab8500, | |||
482 | latch_bit = __ffs(hier_val); | 505 | latch_bit = __ffs(hier_val); |
483 | latch_offset = (hier_offset << 3) + latch_bit; | 506 | latch_offset = (hier_offset << 3) + latch_bit; |
484 | 507 | ||
485 | /* Fix inconsistent ITFromLatch25 bit mapping... */ | 508 | update_latch_offset(&latch_offset, hier_offset); |
486 | if (unlikely(latch_offset == 17)) | ||
487 | latch_offset = 24; | ||
488 | 509 | ||
489 | status = get_register_interruptible(ab8500, | 510 | status = get_register_interruptible(ab8500, |
490 | AB8500_INTERRUPT, | 511 | AB8500_INTERRUPT, |
@@ -512,7 +533,7 @@ static irqreturn_t ab8500_hierarchical_irq(int irq, void *dev) | |||
512 | dev_vdbg(ab8500->dev, "interrupt\n"); | 533 | dev_vdbg(ab8500->dev, "interrupt\n"); |
513 | 534 | ||
514 | /* Hierarchical interrupt version */ | 535 | /* Hierarchical interrupt version */ |
515 | for (i = 0; i < AB8500_IT_LATCHHIER_NUM; i++) { | 536 | for (i = 0; i < (ab8500->it_latchhier_num); i++) { |
516 | int status; | 537 | int status; |
517 | u8 hier_val; | 538 | u8 hier_val; |
518 | 539 | ||
@@ -565,6 +586,9 @@ static irqreturn_t ab8500_irq(int irq, void *dev) | |||
565 | if (regoffset == 11 && is_ab8500_1p1_or_earlier(ab8500)) | 586 | if (regoffset == 11 && is_ab8500_1p1_or_earlier(ab8500)) |
566 | continue; | 587 | continue; |
567 | 588 | ||
589 | if (regoffset < 0) | ||
590 | continue; | ||
591 | |||
568 | status = get_register_interruptible(ab8500, AB8500_INTERRUPT, | 592 | status = get_register_interruptible(ab8500, AB8500_INTERRUPT, |
569 | AB8500_IT_LATCH1_REG + regoffset, &value); | 593 | AB8500_IT_LATCH1_REG + regoffset, &value); |
570 | if (status < 0 || value == 0) | 594 | if (status < 0 || value == 0) |
@@ -615,7 +639,9 @@ static int ab8500_irq_init(struct ab8500 *ab8500, struct device_node *np) | |||
615 | { | 639 | { |
616 | int num_irqs; | 640 | int num_irqs; |
617 | 641 | ||
618 | if (is_ab9540(ab8500)) | 642 | if (is_ab8540(ab8500)) |
643 | num_irqs = AB8540_NR_IRQS; | ||
644 | else if (is_ab9540(ab8500)) | ||
619 | num_irqs = AB9540_NR_IRQS; | 645 | num_irqs = AB9540_NR_IRQS; |
620 | else if (is_ab8505(ab8500)) | 646 | else if (is_ab8505(ab8500)) |
621 | num_irqs = AB8505_NR_IRQS; | 647 | num_irqs = AB8505_NR_IRQS; |
@@ -1552,13 +1578,20 @@ static int ab8500_probe(struct platform_device *pdev) | |||
1552 | ab8500->chip_id >> 4, | 1578 | ab8500->chip_id >> 4, |
1553 | ab8500->chip_id & 0x0F); | 1579 | ab8500->chip_id & 0x0F); |
1554 | 1580 | ||
1555 | /* Configure AB8500 or AB9540 IRQ */ | 1581 | /* Configure AB8540 */ |
1556 | if (is_ab9540(ab8500) || is_ab8505(ab8500)) { | 1582 | if (is_ab8540(ab8500)) { |
1583 | ab8500->mask_size = AB8540_NUM_IRQ_REGS; | ||
1584 | ab8500->irq_reg_offset = ab8540_irq_regoffset; | ||
1585 | ab8500->it_latchhier_num = AB8540_IT_LATCHHIER_NUM; | ||
1586 | }/* Configure AB8500 or AB9540 IRQ */ | ||
1587 | else if (is_ab9540(ab8500) || is_ab8505(ab8500)) { | ||
1557 | ab8500->mask_size = AB9540_NUM_IRQ_REGS; | 1588 | ab8500->mask_size = AB9540_NUM_IRQ_REGS; |
1558 | ab8500->irq_reg_offset = ab9540_irq_regoffset; | 1589 | ab8500->irq_reg_offset = ab9540_irq_regoffset; |
1590 | ab8500->it_latchhier_num = AB8500_IT_LATCHHIER_NUM; | ||
1559 | } else { | 1591 | } else { |
1560 | ab8500->mask_size = AB8500_NUM_IRQ_REGS; | 1592 | ab8500->mask_size = AB8500_NUM_IRQ_REGS; |
1561 | ab8500->irq_reg_offset = ab8500_irq_regoffset; | 1593 | ab8500->irq_reg_offset = ab8500_irq_regoffset; |
1594 | ab8500->it_latchhier_num = AB8500_IT_LATCHHIER_NUM; | ||
1562 | } | 1595 | } |
1563 | ab8500->mask = devm_kzalloc(&pdev->dev, ab8500->mask_size, GFP_KERNEL); | 1596 | ab8500->mask = devm_kzalloc(&pdev->dev, ab8500->mask_size, GFP_KERNEL); |
1564 | if (!ab8500->mask) | 1597 | if (!ab8500->mask) |
@@ -1620,6 +1653,9 @@ static int ab8500_probe(struct platform_device *pdev) | |||
1620 | is_ab8500_1p1_or_earlier(ab8500)) | 1653 | is_ab8500_1p1_or_earlier(ab8500)) |
1621 | continue; | 1654 | continue; |
1622 | 1655 | ||
1656 | if (ab8500->irq_reg_offset[i] < 0) | ||
1657 | continue; | ||
1658 | |||
1623 | get_register_interruptible(ab8500, AB8500_INTERRUPT, | 1659 | get_register_interruptible(ab8500, AB8500_INTERRUPT, |
1624 | AB8500_IT_LATCH1_REG + ab8500->irq_reg_offset[i], | 1660 | AB8500_IT_LATCH1_REG + ab8500->irq_reg_offset[i], |
1625 | &value); | 1661 | &value); |
diff --git a/include/linux/mfd/abx500/ab8500.h b/include/linux/mfd/abx500/ab8500.h index fdd8be64feeb..b5780fd40fe4 100644 --- a/include/linux/mfd/abx500/ab8500.h +++ b/include/linux/mfd/abx500/ab8500.h | |||
@@ -362,6 +362,7 @@ struct ab8500 { | |||
362 | u8 *oldmask; | 362 | u8 *oldmask; |
363 | int mask_size; | 363 | int mask_size; |
364 | const int *irq_reg_offset; | 364 | const int *irq_reg_offset; |
365 | int it_latchhier_num; | ||
365 | }; | 366 | }; |
366 | 367 | ||
367 | struct regulator_reg_init; | 368 | struct regulator_reg_init; |