Commit 2ced445e authored by Linus Walleij's avatar Linus Walleij Committed by Samuel Ortiz

mfd: Parametrize ab8500 IRQ masks and registers

This makes the AB8500 state struct contain the IRQ mask and
register offsets previously hard-coded so as to make room for
more AB8500 variants.
Reviewed-by: default avatarMark Brown <broonie@opensource.wolfsonmicro.com>
Signed-off-by: default avatarMaxime Coquelin <maxime.coquelin@stericsson.com>
Signed-off-by: default avatarAlex Macro <alex.macro@stericsson.com>
Signed-off-by: default avatarMichel Jaouen <michel.jaouen@stericsson.com>
Signed-off-by: default avatarLinus Walleij <linus.walleij@linaro.org>
Signed-off-by: default avatarSamuel Ortiz <sameo@linux.intel.com>
parent 0f620837
...@@ -97,11 +97,13 @@ ...@@ -97,11 +97,13 @@
/* /*
* Map interrupt numbers to the LATCH and MASK register offsets, Interrupt * Map interrupt numbers to the LATCH and MASK register offsets, Interrupt
* numbers are indexed into this array with (num / 8). * numbers are indexed into this array with (num / 8). The interupts are
* defined in linux/mfd/ab8500.h
* *
* This is one off from the register names, i.e. AB8500_IT_MASK1_REG is at * This is one off from the register names, i.e. AB8500_IT_MASK1_REG is at
* offset 0. * offset 0.
*/ */
/* AB8500 support */
static const int ab8500_irq_regoffset[AB8500_NUM_IRQ_REGS] = { static const int ab8500_irq_regoffset[AB8500_NUM_IRQ_REGS] = {
0, 1, 2, 3, 4, 6, 7, 8, 9, 11, 18, 19, 20, 21, 0, 1, 2, 3, 4, 6, 7, 8, 9, 11, 18, 19, 20, 21,
}; };
...@@ -256,7 +258,7 @@ static void ab8500_irq_sync_unlock(struct irq_data *data) ...@@ -256,7 +258,7 @@ static void ab8500_irq_sync_unlock(struct irq_data *data)
struct ab8500 *ab8500 = irq_data_get_irq_chip_data(data); struct ab8500 *ab8500 = irq_data_get_irq_chip_data(data);
int i; int i;
for (i = 0; i < AB8500_NUM_IRQ_REGS; i++) { for (i = 0; i < ab8500->mask_size; i++) {
u8 old = ab8500->oldmask[i]; u8 old = ab8500->oldmask[i];
u8 new = ab8500->mask[i]; u8 new = ab8500->mask[i];
int reg; int reg;
...@@ -274,7 +276,7 @@ static void ab8500_irq_sync_unlock(struct irq_data *data) ...@@ -274,7 +276,7 @@ static void ab8500_irq_sync_unlock(struct irq_data *data)
ab8500->oldmask[i] = new; ab8500->oldmask[i] = new;
reg = AB8500_IT_MASK1_REG + ab8500_irq_regoffset[i]; reg = AB8500_IT_MASK1_REG + ab8500->irq_reg_offset[i];
set_register_interruptible(ab8500, AB8500_INTERRUPT, reg, new); set_register_interruptible(ab8500, AB8500_INTERRUPT, reg, new);
} }
...@@ -317,8 +319,8 @@ static irqreturn_t ab8500_irq(int irq, void *dev) ...@@ -317,8 +319,8 @@ static irqreturn_t ab8500_irq(int irq, void *dev)
dev_vdbg(ab8500->dev, "interrupt\n"); dev_vdbg(ab8500->dev, "interrupt\n");
for (i = 0; i < AB8500_NUM_IRQ_REGS; i++) { for (i = 0; i < ab8500->mask_size; i++) {
int regoffset = ab8500_irq_regoffset[i]; int regoffset = ab8500->irq_reg_offset[i];
int status; int status;
u8 value; u8 value;
...@@ -350,8 +352,11 @@ static int ab8500_irq_init(struct ab8500 *ab8500) ...@@ -350,8 +352,11 @@ static int ab8500_irq_init(struct ab8500 *ab8500)
{ {
int base = ab8500->irq_base; int base = ab8500->irq_base;
int irq; int irq;
int num_irqs;
for (irq = base; irq < base + AB8500_NR_IRQS; irq++) { num_irqs = AB8500_NR_IRQS;
for (irq = base; irq < base + num_irqs; irq++) {
irq_set_chip_data(irq, ab8500); irq_set_chip_data(irq, ab8500);
irq_set_chip_and_handler(irq, &ab8500_irq_chip, irq_set_chip_and_handler(irq, &ab8500_irq_chip,
handle_simple_irq); handle_simple_irq);
...@@ -370,8 +375,11 @@ static void ab8500_irq_remove(struct ab8500 *ab8500) ...@@ -370,8 +375,11 @@ static void ab8500_irq_remove(struct ab8500 *ab8500)
{ {
int base = ab8500->irq_base; int base = ab8500->irq_base;
int irq; int irq;
int num_irqs;
num_irqs = AB8500_NR_IRQS;
for (irq = base; irq < base + AB8500_NR_IRQS; irq++) { for (irq = base; irq < base + num_irqs; irq++) {
#ifdef CONFIG_ARM #ifdef CONFIG_ARM
set_irq_flags(irq, 0); set_irq_flags(irq, 0);
#endif #endif
...@@ -907,6 +915,16 @@ int __devinit ab8500_init(struct ab8500 *ab8500, enum ab8500_version version) ...@@ -907,6 +915,16 @@ int __devinit ab8500_init(struct ab8500 *ab8500, enum ab8500_version version)
ab8500->chip_id >> 4, ab8500->chip_id >> 4,
ab8500->chip_id & 0x0F); ab8500->chip_id & 0x0F);
ab8500->mask_size = AB8500_NUM_IRQ_REGS;
ab8500->irq_reg_offset = ab8500_irq_regoffset;
ab8500->mask = kzalloc(ab8500->mask_size, GFP_KERNEL);
if (!ab8500->mask)
return -ENOMEM;
ab8500->oldmask = kzalloc(ab8500->mask_size, GFP_KERNEL);
if (!ab8500->oldmask) {
ret = -ENOMEM;
goto out_freemask;
}
/* /*
* ab8500 has switched off due to (SWITCH_OFF_STATUS): * ab8500 has switched off due to (SWITCH_OFF_STATUS):
* 0x01 Swoff bit programming * 0x01 Swoff bit programming
...@@ -929,7 +947,7 @@ int __devinit ab8500_init(struct ab8500 *ab8500, enum ab8500_version version) ...@@ -929,7 +947,7 @@ int __devinit ab8500_init(struct ab8500 *ab8500, enum ab8500_version version)
plat->init(ab8500); plat->init(ab8500);
/* Clear and mask all interrupts */ /* Clear and mask all interrupts */
for (i = 0; i < AB8500_NUM_IRQ_REGS; i++) { for (i = 0; i < ab8500->mask_size; i++) {
/* /*
* Interrupt register 12 doesn't exist prior to AB8500 version * Interrupt register 12 doesn't exist prior to AB8500 version
* 2.0 * 2.0
...@@ -939,23 +957,23 @@ int __devinit ab8500_init(struct ab8500 *ab8500, enum ab8500_version version) ...@@ -939,23 +957,23 @@ int __devinit ab8500_init(struct ab8500 *ab8500, enum ab8500_version version)
continue; continue;
get_register_interruptible(ab8500, AB8500_INTERRUPT, get_register_interruptible(ab8500, AB8500_INTERRUPT,
AB8500_IT_LATCH1_REG + ab8500_irq_regoffset[i], AB8500_IT_LATCH1_REG + ab8500->irq_reg_offset[i],
&value); &value);
set_register_interruptible(ab8500, AB8500_INTERRUPT, set_register_interruptible(ab8500, AB8500_INTERRUPT,
AB8500_IT_MASK1_REG + ab8500_irq_regoffset[i], 0xff); AB8500_IT_MASK1_REG + ab8500->irq_reg_offset[i], 0xff);
} }
ret = abx500_register_ops(ab8500->dev, &ab8500_ops); ret = abx500_register_ops(ab8500->dev, &ab8500_ops);
if (ret) if (ret)
return ret; goto out_freeoldmask;
for (i = 0; i < AB8500_NUM_IRQ_REGS; i++) for (i = 0; i < ab8500->mask_size; i++)
ab8500->mask[i] = ab8500->oldmask[i] = 0xff; ab8500->mask[i] = ab8500->oldmask[i] = 0xff;
if (ab8500->irq_base) { if (ab8500->irq_base) {
ret = ab8500_irq_init(ab8500); ret = ab8500_irq_init(ab8500);
if (ret) if (ret)
return ret; goto out_freeoldmask;
ret = request_threaded_irq(ab8500->irq, NULL, ab8500_irq, ret = request_threaded_irq(ab8500->irq, NULL, ab8500_irq,
IRQF_ONESHOT | IRQF_NO_SUSPEND, IRQF_ONESHOT | IRQF_NO_SUSPEND,
...@@ -982,6 +1000,10 @@ int __devinit ab8500_init(struct ab8500 *ab8500, enum ab8500_version version) ...@@ -982,6 +1000,10 @@ int __devinit ab8500_init(struct ab8500 *ab8500, enum ab8500_version version)
out_removeirq: out_removeirq:
if (ab8500->irq_base) if (ab8500->irq_base)
ab8500_irq_remove(ab8500); ab8500_irq_remove(ab8500);
out_freeoldmask:
kfree(ab8500->oldmask);
out_freemask:
kfree(ab8500->mask);
return ret; return ret;
} }
...@@ -994,6 +1016,8 @@ int __devexit ab8500_exit(struct ab8500 *ab8500) ...@@ -994,6 +1016,8 @@ int __devexit ab8500_exit(struct ab8500 *ab8500)
free_irq(ab8500->irq, ab8500); free_irq(ab8500->irq, ab8500);
ab8500_irq_remove(ab8500); ab8500_irq_remove(ab8500);
} }
kfree(ab8500->oldmask);
kfree(ab8500->mask);
return 0; return 0;
} }
......
...@@ -175,6 +175,9 @@ enum ab8500_version { ...@@ -175,6 +175,9 @@ enum ab8500_version {
* @tx_buf: tx buf for SPI * @tx_buf: tx buf for SPI
* @mask: cache of IRQ regs for bus lock * @mask: cache of IRQ regs for bus lock
* @oldmask: cache of previous IRQ regs for bus lock * @oldmask: cache of previous IRQ regs for bus lock
* @mask_size: Actual number of valid entries in mask[], oldmask[] and
* irq_reg_offset
* @irq_reg_offset: Array of offsets into IRQ registers
*/ */
struct ab8500 { struct ab8500 {
struct device *dev; struct device *dev;
...@@ -192,8 +195,10 @@ struct ab8500 { ...@@ -192,8 +195,10 @@ struct ab8500 {
unsigned long tx_buf[4]; unsigned long tx_buf[4];
unsigned long rx_buf[4]; unsigned long rx_buf[4];
u8 mask[AB8500_NUM_IRQ_REGS]; u8 *mask;
u8 oldmask[AB8500_NUM_IRQ_REGS]; u8 *oldmask;
int mask_size;
const int *irq_reg_offset;
}; };
struct regulator_reg_init; struct regulator_reg_init;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment