From patchwork Wed Feb 1 16:09:28 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Linus Walleij X-Patchwork-Id: 6503 Return-Path: X-Original-To: patchwork@peony.canonical.com Delivered-To: patchwork@peony.canonical.com Received: from fiordland.canonical.com (fiordland.canonical.com [91.189.94.145]) by peony.canonical.com (Postfix) with ESMTP id 052C8249CD for ; Wed, 1 Feb 2012 16:09:47 +0000 (UTC) Received: from mail-bk0-f52.google.com (mail-bk0-f52.google.com [209.85.214.52]) by fiordland.canonical.com (Postfix) with ESMTP id E9A27A1820C for ; Wed, 1 Feb 2012 16:09:46 +0000 (UTC) Received: by mail-bk0-f52.google.com with SMTP id r19so1586946bka.11 for ; Wed, 01 Feb 2012 08:09:46 -0800 (PST) Received: by 10.205.139.12 with SMTP id iu12mr12801293bkc.2.1328112586730; Wed, 01 Feb 2012 08:09:46 -0800 (PST) X-Forwarded-To: linaro-patchwork@canonical.com X-Forwarded-For: patch@linaro.org linaro-patchwork@canonical.com Delivered-To: patches@linaro.org Received: by 10.204.130.220 with SMTP id u28cs215088bks; Wed, 1 Feb 2012 08:09:46 -0800 (PST) Received: by 10.213.8.207 with SMTP id i15mr4414950ebi.143.1328112586278; Wed, 01 Feb 2012 08:09:46 -0800 (PST) Received: from eu1sys200aog104.obsmtp.com (eu1sys200aog104.obsmtp.com. [207.126.144.117]) by mx.google.com with SMTP id e47si5733833eea.50.2012.02.01.08.09.37 (version=TLSv1/SSLv3 cipher=OTHER); Wed, 01 Feb 2012 08:09:46 -0800 (PST) Received-SPF: neutral (google.com: 207.126.144.117 is neither permitted nor denied by best guess record for domain of linus.walleij@stericsson.com) client-ip=207.126.144.117; Authentication-Results: mx.google.com; spf=neutral (google.com: 207.126.144.117 is neither permitted nor denied by best guess record for domain of linus.walleij@stericsson.com) smtp.mail=linus.walleij@stericsson.com Received: from beta.dmz-ap.st.com ([138.198.100.35]) (using TLSv1) by eu1sys200aob104.postini.com ([207.126.147.11]) with SMTP ID DSNKTyljwP/iSdvjpy2i8OhLmZdZcVE/n/4D@postini.com; Wed, 01 Feb 2012 16:09:45 UTC Received: from zeta.dmz-ap.st.com (ns6.st.com [138.198.234.13]) by beta.dmz-ap.st.com (STMicroelectronics) with ESMTP id 73937C8; Wed, 1 Feb 2012 16:01:05 +0000 (GMT) Received: from relay2.stm.gmessaging.net (unknown [10.230.100.18]) by zeta.dmz-ap.st.com (STMicroelectronics) with ESMTP id 97B26B59; Wed, 1 Feb 2012 16:09:31 +0000 (GMT) Received: from exdcvycastm003.EQ1STM.local (alteon-source-exch [10.230.100.61]) (using TLSv1 with cipher RC4-MD5 (128/128 bits)) (Client CN "exdcvycastm003", Issuer "exdcvycastm003" (not verified)) by relay2.stm.gmessaging.net (Postfix) with ESMTPS id B90B6A8065; Wed, 1 Feb 2012 17:09:24 +0100 (CET) Received: from steludxu4075.lud.stericsson.com (10.230.100.153) by smtp.stericsson.com (10.230.100.1) with Microsoft SMTP Server (TLS) id 8.3.83.0; Wed, 1 Feb 2012 17:09:30 +0100 From: Linus Walleij To: Samuel Ortiz , Cc: Mark Brown , Linus Walleij , Maxime Coquelin , Alex Macro , Michel Jaouen Subject: [PATCH 3/4] mfd/ab8500: parametrize IRQ masks and registers Date: Wed, 1 Feb 2012 17:09:28 +0100 Message-ID: <1328112568-32529-1-git-send-email-linus.walleij@stericsson.com> X-Mailer: git-send-email 1.7.8 MIME-Version: 1.0 From: Linus Walleij 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. Cc: Mark Brown Signed-off-by: Maxime Coquelin Signed-off-by: Alex Macro Signed-off-by: Michel Jaouen Signed-off-by: Linus Walleij --- drivers/mfd/ab8500-core.c | 52 +++++++++++++++++++++++++++---------- include/linux/mfd/abx500/ab8500.h | 9 +++++- 2 files changed, 45 insertions(+), 16 deletions(-) diff --git a/drivers/mfd/ab8500-core.c b/drivers/mfd/ab8500-core.c index f768bb8..53a7703 100644 --- a/drivers/mfd/ab8500-core.c +++ b/drivers/mfd/ab8500-core.c @@ -97,11 +97,13 @@ /* * 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 * offset 0. */ +/* AB8500 support */ static const int ab8500_irq_regoffset[AB8500_NUM_IRQ_REGS] = { 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) struct ab8500 *ab8500 = irq_data_get_irq_chip_data(data); 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 new = ab8500->mask[i]; int reg; @@ -274,7 +276,7 @@ static void ab8500_irq_sync_unlock(struct irq_data *data) 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); } @@ -317,8 +319,8 @@ static irqreturn_t ab8500_irq(int irq, void *dev) dev_vdbg(ab8500->dev, "interrupt\n"); - for (i = 0; i < AB8500_NUM_IRQ_REGS; i++) { - int regoffset = ab8500_irq_regoffset[i]; + for (i = 0; i < ab8500->mask_size; i++) { + int regoffset = ab8500->irq_reg_offset[i]; int status; u8 value; @@ -350,8 +352,11 @@ static int ab8500_irq_init(struct ab8500 *ab8500) { int base = ab8500->irq_base; 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_and_handler(irq, &ab8500_irq_chip, handle_simple_irq); @@ -370,8 +375,11 @@ static void ab8500_irq_remove(struct ab8500 *ab8500) { int base = ab8500->irq_base; 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 set_irq_flags(irq, 0); #endif @@ -907,6 +915,16 @@ int __devinit ab8500_init(struct ab8500 *ab8500, enum ab8500_version version) ab8500->chip_id >> 4, 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): * 0x01 Swoff bit programming @@ -929,7 +947,7 @@ int __devinit ab8500_init(struct ab8500 *ab8500, enum ab8500_version version) plat->init(ab8500); /* 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 * 2.0 @@ -939,23 +957,23 @@ int __devinit ab8500_init(struct ab8500 *ab8500, enum ab8500_version version) continue; get_register_interruptible(ab8500, AB8500_INTERRUPT, - AB8500_IT_LATCH1_REG + ab8500_irq_regoffset[i], + AB8500_IT_LATCH1_REG + ab8500->irq_reg_offset[i], &value); 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); 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; if (ab8500->irq_base) { ret = ab8500_irq_init(ab8500); if (ret) - return ret; + goto out_freeoldmask; ret = request_threaded_irq(ab8500->irq, NULL, ab8500_irq, IRQF_ONESHOT | IRQF_NO_SUSPEND, @@ -982,7 +1000,11 @@ out_freeirq: out_removeirq: if (ab8500->irq_base) ab8500_irq_remove(ab8500); - } + +out_freeoldmask: + kfree(ab8500->oldmask); +out_freemask: + kfree(ab8500->mask); return ret; } @@ -994,6 +1016,8 @@ int __devexit ab8500_exit(struct ab8500 *ab8500) free_irq(ab8500->irq, ab8500); ab8500_irq_remove(ab8500); } + kfree(ab8500->oldmask); + kfree(ab8500->mask); return 0; } diff --git a/include/linux/mfd/abx500/ab8500.h b/include/linux/mfd/abx500/ab8500.h index 7989258..55eabe8 100644 --- a/include/linux/mfd/abx500/ab8500.h +++ b/include/linux/mfd/abx500/ab8500.h @@ -175,6 +175,9 @@ enum ab8500_version { * @tx_buf: tx buf for SPI * @mask: cache of 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 device *dev; @@ -192,8 +195,10 @@ struct ab8500 { unsigned long tx_buf[4]; unsigned long rx_buf[4]; - u8 mask[AB8500_NUM_IRQ_REGS]; - u8 oldmask[AB8500_NUM_IRQ_REGS]; + u8 *mask; + u8 *oldmask; + int mask_size; + const int *irq_reg_offset; }; struct regulator_reg_init;