aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLee Jones <lee.jones@linaro.org>2013-02-25 09:57:35 -0500
committerLee Jones <lee.jones@linaro.org>2013-03-06 23:27:47 -0500
commit3e1a498f2728476535571d270081a17fdfceaf26 (patch)
tree98666d5be9dd27fb05d65842d5dc4f860bdf22b1
parent4b106fb9895c7edba2acd41c152e8f6edf724651 (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.c50
-rw-r--r--include/linux/mfd/abx500/ab8500.h1
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 */
149static 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
146static const char ab8500_version_str[][7] = { 154static 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
445static 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
434static int ab8500_handle_hierarchical_line(struct ab8500 *ab8500, 457static 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
367struct regulator_reg_init; 368struct regulator_reg_init;