162579266SRabin Vincent /* 262579266SRabin Vincent * Copyright (C) ST-Ericsson SA 2010 362579266SRabin Vincent * 462579266SRabin Vincent * License Terms: GNU General Public License v2 562579266SRabin Vincent * Author: Srinidhi Kasagar <srinidhi.kasagar@stericsson.com> 662579266SRabin Vincent * Author: Rabin Vincent <rabin.vincent@stericsson.com> 7adceed62SMattias Wallin * Author: Mattias Wallin <mattias.wallin@stericsson.com> 862579266SRabin Vincent */ 962579266SRabin Vincent 1062579266SRabin Vincent #include <linux/kernel.h> 1162579266SRabin Vincent #include <linux/slab.h> 1262579266SRabin Vincent #include <linux/init.h> 1362579266SRabin Vincent #include <linux/irq.h> 1406e589efSLee Jones #include <linux/irqdomain.h> 1562579266SRabin Vincent #include <linux/delay.h> 1662579266SRabin Vincent #include <linux/interrupt.h> 1762579266SRabin Vincent #include <linux/module.h> 1862579266SRabin Vincent #include <linux/platform_device.h> 1962579266SRabin Vincent #include <linux/mfd/core.h> 2047c16975SMattias Wallin #include <linux/mfd/abx500.h> 21ee66e653SLinus Walleij #include <linux/mfd/abx500/ab8500.h> 2200441b5eSLee Jones #include <linux/mfd/abx500/ab8500-bm.h> 23d28f1db8SLee Jones #include <linux/mfd/dbx500-prcmu.h> 24549931f9SSundar R Iyer #include <linux/regulator/ab8500.h> 256bc4a568SLee Jones #include <linux/of.h> 266bc4a568SLee Jones #include <linux/of_device.h> 2762579266SRabin Vincent 2862579266SRabin Vincent /* 2962579266SRabin Vincent * Interrupt register offsets 3062579266SRabin Vincent * Bank : 0x0E 3162579266SRabin Vincent */ 3247c16975SMattias Wallin #define AB8500_IT_SOURCE1_REG 0x00 3347c16975SMattias Wallin #define AB8500_IT_SOURCE2_REG 0x01 3447c16975SMattias Wallin #define AB8500_IT_SOURCE3_REG 0x02 3547c16975SMattias Wallin #define AB8500_IT_SOURCE4_REG 0x03 3647c16975SMattias Wallin #define AB8500_IT_SOURCE5_REG 0x04 3747c16975SMattias Wallin #define AB8500_IT_SOURCE6_REG 0x05 3847c16975SMattias Wallin #define AB8500_IT_SOURCE7_REG 0x06 3947c16975SMattias Wallin #define AB8500_IT_SOURCE8_REG 0x07 40d6255529SLinus Walleij #define AB9540_IT_SOURCE13_REG 0x0C 4147c16975SMattias Wallin #define AB8500_IT_SOURCE19_REG 0x12 4247c16975SMattias Wallin #define AB8500_IT_SOURCE20_REG 0x13 4347c16975SMattias Wallin #define AB8500_IT_SOURCE21_REG 0x14 4447c16975SMattias Wallin #define AB8500_IT_SOURCE22_REG 0x15 4547c16975SMattias Wallin #define AB8500_IT_SOURCE23_REG 0x16 4647c16975SMattias Wallin #define AB8500_IT_SOURCE24_REG 0x17 4762579266SRabin Vincent 4862579266SRabin Vincent /* 4962579266SRabin Vincent * latch registers 5062579266SRabin Vincent */ 5147c16975SMattias Wallin #define AB8500_IT_LATCH1_REG 0x20 5247c16975SMattias Wallin #define AB8500_IT_LATCH2_REG 0x21 5347c16975SMattias Wallin #define AB8500_IT_LATCH3_REG 0x22 5447c16975SMattias Wallin #define AB8500_IT_LATCH4_REG 0x23 5547c16975SMattias Wallin #define AB8500_IT_LATCH5_REG 0x24 5647c16975SMattias Wallin #define AB8500_IT_LATCH6_REG 0x25 5747c16975SMattias Wallin #define AB8500_IT_LATCH7_REG 0x26 5847c16975SMattias Wallin #define AB8500_IT_LATCH8_REG 0x27 5947c16975SMattias Wallin #define AB8500_IT_LATCH9_REG 0x28 6047c16975SMattias Wallin #define AB8500_IT_LATCH10_REG 0x29 6192d50a41SMattias Wallin #define AB8500_IT_LATCH12_REG 0x2B 62d6255529SLinus Walleij #define AB9540_IT_LATCH13_REG 0x2C 6347c16975SMattias Wallin #define AB8500_IT_LATCH19_REG 0x32 6447c16975SMattias Wallin #define AB8500_IT_LATCH20_REG 0x33 6547c16975SMattias Wallin #define AB8500_IT_LATCH21_REG 0x34 6647c16975SMattias Wallin #define AB8500_IT_LATCH22_REG 0x35 6747c16975SMattias Wallin #define AB8500_IT_LATCH23_REG 0x36 6847c16975SMattias Wallin #define AB8500_IT_LATCH24_REG 0x37 6962579266SRabin Vincent 7062579266SRabin Vincent /* 7162579266SRabin Vincent * mask registers 7262579266SRabin Vincent */ 7362579266SRabin Vincent 7447c16975SMattias Wallin #define AB8500_IT_MASK1_REG 0x40 7547c16975SMattias Wallin #define AB8500_IT_MASK2_REG 0x41 7647c16975SMattias Wallin #define AB8500_IT_MASK3_REG 0x42 7747c16975SMattias Wallin #define AB8500_IT_MASK4_REG 0x43 7847c16975SMattias Wallin #define AB8500_IT_MASK5_REG 0x44 7947c16975SMattias Wallin #define AB8500_IT_MASK6_REG 0x45 8047c16975SMattias Wallin #define AB8500_IT_MASK7_REG 0x46 8147c16975SMattias Wallin #define AB8500_IT_MASK8_REG 0x47 8247c16975SMattias Wallin #define AB8500_IT_MASK9_REG 0x48 8347c16975SMattias Wallin #define AB8500_IT_MASK10_REG 0x49 8447c16975SMattias Wallin #define AB8500_IT_MASK11_REG 0x4A 8547c16975SMattias Wallin #define AB8500_IT_MASK12_REG 0x4B 8647c16975SMattias Wallin #define AB8500_IT_MASK13_REG 0x4C 8747c16975SMattias Wallin #define AB8500_IT_MASK14_REG 0x4D 8847c16975SMattias Wallin #define AB8500_IT_MASK15_REG 0x4E 8947c16975SMattias Wallin #define AB8500_IT_MASK16_REG 0x4F 9047c16975SMattias Wallin #define AB8500_IT_MASK17_REG 0x50 9147c16975SMattias Wallin #define AB8500_IT_MASK18_REG 0x51 9247c16975SMattias Wallin #define AB8500_IT_MASK19_REG 0x52 9347c16975SMattias Wallin #define AB8500_IT_MASK20_REG 0x53 9447c16975SMattias Wallin #define AB8500_IT_MASK21_REG 0x54 9547c16975SMattias Wallin #define AB8500_IT_MASK22_REG 0x55 9647c16975SMattias Wallin #define AB8500_IT_MASK23_REG 0x56 9747c16975SMattias Wallin #define AB8500_IT_MASK24_REG 0x57 9862579266SRabin Vincent 997ccfe9b1SMichel JAOUEN /* 1007ccfe9b1SMichel JAOUEN * latch hierarchy registers 1017ccfe9b1SMichel JAOUEN */ 1027ccfe9b1SMichel JAOUEN #define AB8500_IT_LATCHHIER1_REG 0x60 1037ccfe9b1SMichel JAOUEN #define AB8500_IT_LATCHHIER2_REG 0x61 1047ccfe9b1SMichel JAOUEN #define AB8500_IT_LATCHHIER3_REG 0x62 1057ccfe9b1SMichel JAOUEN 1067ccfe9b1SMichel JAOUEN #define AB8500_IT_LATCHHIER_NUM 3 1077ccfe9b1SMichel JAOUEN 10847c16975SMattias Wallin #define AB8500_REV_REG 0x80 1090f620837SLinus Walleij #define AB8500_IC_NAME_REG 0x82 110e5c238c3SMattias Wallin #define AB8500_SWITCH_OFF_STATUS 0x00 11162579266SRabin Vincent 112b4a31037SAndrew Lynn #define AB8500_TURN_ON_STATUS 0x00 113b4a31037SAndrew Lynn 1146ef9418cSRickard Andersson static bool no_bm; /* No battery management */ 1156ef9418cSRickard Andersson module_param(no_bm, bool, S_IRUGO); 1166ef9418cSRickard Andersson 117d6255529SLinus Walleij #define AB9540_MODEM_CTRL2_REG 0x23 118d6255529SLinus Walleij #define AB9540_MODEM_CTRL2_SWDBBRSTN_BIT BIT(2) 119d6255529SLinus Walleij 12062579266SRabin Vincent /* 12162579266SRabin Vincent * Map interrupt numbers to the LATCH and MASK register offsets, Interrupt 1222ced445eSLinus Walleij * numbers are indexed into this array with (num / 8). The interupts are 1232ced445eSLinus Walleij * defined in linux/mfd/ab8500.h 12462579266SRabin Vincent * 12562579266SRabin Vincent * This is one off from the register names, i.e. AB8500_IT_MASK1_REG is at 12662579266SRabin Vincent * offset 0. 12762579266SRabin Vincent */ 1282ced445eSLinus Walleij /* AB8500 support */ 12962579266SRabin Vincent static const int ab8500_irq_regoffset[AB8500_NUM_IRQ_REGS] = { 13092d50a41SMattias Wallin 0, 1, 2, 3, 4, 6, 7, 8, 9, 11, 18, 19, 20, 21, 13162579266SRabin Vincent }; 13262579266SRabin Vincent 133d6255529SLinus Walleij /* AB9540 support */ 134d6255529SLinus Walleij static const int ab9540_irq_regoffset[AB9540_NUM_IRQ_REGS] = { 135d6255529SLinus Walleij 0, 1, 2, 3, 4, 6, 7, 8, 9, 11, 18, 19, 20, 21, 12, 13, 24, 136d6255529SLinus Walleij }; 137d6255529SLinus Walleij 1380f620837SLinus Walleij static const char ab8500_version_str[][7] = { 1390f620837SLinus Walleij [AB8500_VERSION_AB8500] = "AB8500", 1400f620837SLinus Walleij [AB8500_VERSION_AB8505] = "AB8505", 1410f620837SLinus Walleij [AB8500_VERSION_AB9540] = "AB9540", 1420f620837SLinus Walleij [AB8500_VERSION_AB8540] = "AB8540", 1430f620837SLinus Walleij }; 1440f620837SLinus Walleij 145822672a7SLee Jones static int ab8500_prcmu_write(struct ab8500 *ab8500, u16 addr, u8 data) 146d28f1db8SLee Jones { 147d28f1db8SLee Jones int ret; 148d28f1db8SLee Jones 149d28f1db8SLee Jones ret = prcmu_abb_write((u8)(addr >> 8), (u8)(addr & 0xFF), &data, 1); 150d28f1db8SLee Jones if (ret < 0) 151d28f1db8SLee Jones dev_err(ab8500->dev, "prcmu i2c error %d\n", ret); 152d28f1db8SLee Jones return ret; 153d28f1db8SLee Jones } 154d28f1db8SLee Jones 155822672a7SLee Jones static int ab8500_prcmu_write_masked(struct ab8500 *ab8500, u16 addr, u8 mask, 156d28f1db8SLee Jones u8 data) 157d28f1db8SLee Jones { 158d28f1db8SLee Jones int ret; 159d28f1db8SLee Jones 160d28f1db8SLee Jones ret = prcmu_abb_write_masked((u8)(addr >> 8), (u8)(addr & 0xFF), &data, 161d28f1db8SLee Jones &mask, 1); 162d28f1db8SLee Jones if (ret < 0) 163d28f1db8SLee Jones dev_err(ab8500->dev, "prcmu i2c error %d\n", ret); 164d28f1db8SLee Jones return ret; 165d28f1db8SLee Jones } 166d28f1db8SLee Jones 167822672a7SLee Jones static int ab8500_prcmu_read(struct ab8500 *ab8500, u16 addr) 168d28f1db8SLee Jones { 169d28f1db8SLee Jones int ret; 170d28f1db8SLee Jones u8 data; 171d28f1db8SLee Jones 172d28f1db8SLee Jones ret = prcmu_abb_read((u8)(addr >> 8), (u8)(addr & 0xFF), &data, 1); 173d28f1db8SLee Jones if (ret < 0) { 174d28f1db8SLee Jones dev_err(ab8500->dev, "prcmu i2c error %d\n", ret); 175d28f1db8SLee Jones return ret; 176d28f1db8SLee Jones } 177d28f1db8SLee Jones return (int)data; 178d28f1db8SLee Jones } 179d28f1db8SLee Jones 18047c16975SMattias Wallin static int ab8500_get_chip_id(struct device *dev) 18147c16975SMattias Wallin { 1826bce7bf1SMattias Wallin struct ab8500 *ab8500; 1836bce7bf1SMattias Wallin 1846bce7bf1SMattias Wallin if (!dev) 1856bce7bf1SMattias Wallin return -EINVAL; 1866bce7bf1SMattias Wallin ab8500 = dev_get_drvdata(dev->parent); 1876bce7bf1SMattias Wallin return ab8500 ? (int)ab8500->chip_id : -EINVAL; 18847c16975SMattias Wallin } 18947c16975SMattias Wallin 19047c16975SMattias Wallin static int set_register_interruptible(struct ab8500 *ab8500, u8 bank, 19147c16975SMattias Wallin u8 reg, u8 data) 19262579266SRabin Vincent { 19362579266SRabin Vincent int ret; 19447c16975SMattias Wallin /* 19547c16975SMattias Wallin * Put the u8 bank and u8 register together into a an u16. 19647c16975SMattias Wallin * The bank on higher 8 bits and register in lower 8 bits. 19747c16975SMattias Wallin * */ 19847c16975SMattias Wallin u16 addr = ((u16)bank) << 8 | reg; 19962579266SRabin Vincent 20062579266SRabin Vincent dev_vdbg(ab8500->dev, "wr: addr %#x <= %#x\n", addr, data); 20162579266SRabin Vincent 202392cbd1eSRabin Vincent mutex_lock(&ab8500->lock); 20347c16975SMattias Wallin 20447c16975SMattias Wallin ret = ab8500->write(ab8500, addr, data); 20547c16975SMattias Wallin if (ret < 0) 20647c16975SMattias Wallin dev_err(ab8500->dev, "failed to write reg %#x: %d\n", 20747c16975SMattias Wallin addr, ret); 20847c16975SMattias Wallin mutex_unlock(&ab8500->lock); 20947c16975SMattias Wallin 21047c16975SMattias Wallin return ret; 21147c16975SMattias Wallin } 21247c16975SMattias Wallin 21347c16975SMattias Wallin static int ab8500_set_register(struct device *dev, u8 bank, 21447c16975SMattias Wallin u8 reg, u8 value) 21547c16975SMattias Wallin { 216112a80d2SJonas Aaberg int ret; 21747c16975SMattias Wallin struct ab8500 *ab8500 = dev_get_drvdata(dev->parent); 21847c16975SMattias Wallin 219112a80d2SJonas Aaberg atomic_inc(&ab8500->transfer_ongoing); 220112a80d2SJonas Aaberg ret = set_register_interruptible(ab8500, bank, reg, value); 221112a80d2SJonas Aaberg atomic_dec(&ab8500->transfer_ongoing); 222112a80d2SJonas Aaberg return ret; 22347c16975SMattias Wallin } 22447c16975SMattias Wallin 22547c16975SMattias Wallin static int get_register_interruptible(struct ab8500 *ab8500, u8 bank, 22647c16975SMattias Wallin u8 reg, u8 *value) 22747c16975SMattias Wallin { 22847c16975SMattias Wallin int ret; 22947c16975SMattias Wallin /* put the u8 bank and u8 reg together into a an u16. 23047c16975SMattias Wallin * bank on higher 8 bits and reg in lower */ 23147c16975SMattias Wallin u16 addr = ((u16)bank) << 8 | reg; 23247c16975SMattias Wallin 233392cbd1eSRabin Vincent mutex_lock(&ab8500->lock); 23447c16975SMattias Wallin 23547c16975SMattias Wallin ret = ab8500->read(ab8500, addr); 23647c16975SMattias Wallin if (ret < 0) 23747c16975SMattias Wallin dev_err(ab8500->dev, "failed to read reg %#x: %d\n", 23847c16975SMattias Wallin addr, ret); 23947c16975SMattias Wallin else 24047c16975SMattias Wallin *value = ret; 24147c16975SMattias Wallin 24247c16975SMattias Wallin mutex_unlock(&ab8500->lock); 24347c16975SMattias Wallin dev_vdbg(ab8500->dev, "rd: addr %#x => data %#x\n", addr, ret); 24447c16975SMattias Wallin 24547c16975SMattias Wallin return ret; 24647c16975SMattias Wallin } 24747c16975SMattias Wallin 24847c16975SMattias Wallin static int ab8500_get_register(struct device *dev, u8 bank, 24947c16975SMattias Wallin u8 reg, u8 *value) 25047c16975SMattias Wallin { 251112a80d2SJonas Aaberg int ret; 25247c16975SMattias Wallin struct ab8500 *ab8500 = dev_get_drvdata(dev->parent); 25347c16975SMattias Wallin 254112a80d2SJonas Aaberg atomic_inc(&ab8500->transfer_ongoing); 255112a80d2SJonas Aaberg ret = get_register_interruptible(ab8500, bank, reg, value); 256112a80d2SJonas Aaberg atomic_dec(&ab8500->transfer_ongoing); 257112a80d2SJonas Aaberg return ret; 25847c16975SMattias Wallin } 25947c16975SMattias Wallin 26047c16975SMattias Wallin static int mask_and_set_register_interruptible(struct ab8500 *ab8500, u8 bank, 26147c16975SMattias Wallin u8 reg, u8 bitmask, u8 bitvalues) 26247c16975SMattias Wallin { 26347c16975SMattias Wallin int ret; 26447c16975SMattias Wallin /* put the u8 bank and u8 reg together into a an u16. 26547c16975SMattias Wallin * bank on higher 8 bits and reg in lower */ 26647c16975SMattias Wallin u16 addr = ((u16)bank) << 8 | reg; 26747c16975SMattias Wallin 268392cbd1eSRabin Vincent mutex_lock(&ab8500->lock); 26947c16975SMattias Wallin 270bc628fd1SMattias Nilsson if (ab8500->write_masked == NULL) { 271bc628fd1SMattias Nilsson u8 data; 272bc628fd1SMattias Nilsson 27347c16975SMattias Wallin ret = ab8500->read(ab8500, addr); 27447c16975SMattias Wallin if (ret < 0) { 27547c16975SMattias Wallin dev_err(ab8500->dev, "failed to read reg %#x: %d\n", 27647c16975SMattias Wallin addr, ret); 27747c16975SMattias Wallin goto out; 27847c16975SMattias Wallin } 27947c16975SMattias Wallin 28047c16975SMattias Wallin data = (u8)ret; 28147c16975SMattias Wallin data = (~bitmask & data) | (bitmask & bitvalues); 28247c16975SMattias Wallin 28362579266SRabin Vincent ret = ab8500->write(ab8500, addr, data); 28462579266SRabin Vincent if (ret < 0) 28562579266SRabin Vincent dev_err(ab8500->dev, "failed to write reg %#x: %d\n", 28662579266SRabin Vincent addr, ret); 28762579266SRabin Vincent 288bc628fd1SMattias Nilsson dev_vdbg(ab8500->dev, "mask: addr %#x => data %#x\n", addr, 289bc628fd1SMattias Nilsson data); 290bc628fd1SMattias Nilsson goto out; 291bc628fd1SMattias Nilsson } 292bc628fd1SMattias Nilsson ret = ab8500->write_masked(ab8500, addr, bitmask, bitvalues); 293bc628fd1SMattias Nilsson if (ret < 0) 294bc628fd1SMattias Nilsson dev_err(ab8500->dev, "failed to modify reg %#x: %d\n", addr, 295bc628fd1SMattias Nilsson ret); 29662579266SRabin Vincent out: 29762579266SRabin Vincent mutex_unlock(&ab8500->lock); 29862579266SRabin Vincent return ret; 29962579266SRabin Vincent } 30047c16975SMattias Wallin 30147c16975SMattias Wallin static int ab8500_mask_and_set_register(struct device *dev, 30247c16975SMattias Wallin u8 bank, u8 reg, u8 bitmask, u8 bitvalues) 30347c16975SMattias Wallin { 304112a80d2SJonas Aaberg int ret; 30547c16975SMattias Wallin struct ab8500 *ab8500 = dev_get_drvdata(dev->parent); 30647c16975SMattias Wallin 307112a80d2SJonas Aaberg atomic_inc(&ab8500->transfer_ongoing); 308112a80d2SJonas Aaberg ret= mask_and_set_register_interruptible(ab8500, bank, reg, 30947c16975SMattias Wallin bitmask, bitvalues); 310112a80d2SJonas Aaberg atomic_dec(&ab8500->transfer_ongoing); 311112a80d2SJonas Aaberg return ret; 31247c16975SMattias Wallin } 31347c16975SMattias Wallin 31447c16975SMattias Wallin static struct abx500_ops ab8500_ops = { 31547c16975SMattias Wallin .get_chip_id = ab8500_get_chip_id, 31647c16975SMattias Wallin .get_register = ab8500_get_register, 31747c16975SMattias Wallin .set_register = ab8500_set_register, 31847c16975SMattias Wallin .get_register_page = NULL, 31947c16975SMattias Wallin .set_register_page = NULL, 32047c16975SMattias Wallin .mask_and_set_register = ab8500_mask_and_set_register, 32147c16975SMattias Wallin .event_registers_startup_state_get = NULL, 32247c16975SMattias Wallin .startup_irq_enabled = NULL, 32347c16975SMattias Wallin }; 32462579266SRabin Vincent 3259505a0a0SMark Brown static void ab8500_irq_lock(struct irq_data *data) 32662579266SRabin Vincent { 3279505a0a0SMark Brown struct ab8500 *ab8500 = irq_data_get_irq_chip_data(data); 32862579266SRabin Vincent 32962579266SRabin Vincent mutex_lock(&ab8500->irq_lock); 330112a80d2SJonas Aaberg atomic_inc(&ab8500->transfer_ongoing); 33162579266SRabin Vincent } 33262579266SRabin Vincent 3339505a0a0SMark Brown static void ab8500_irq_sync_unlock(struct irq_data *data) 33462579266SRabin Vincent { 3359505a0a0SMark Brown struct ab8500 *ab8500 = irq_data_get_irq_chip_data(data); 33662579266SRabin Vincent int i; 33762579266SRabin Vincent 3382ced445eSLinus Walleij for (i = 0; i < ab8500->mask_size; i++) { 33962579266SRabin Vincent u8 old = ab8500->oldmask[i]; 34062579266SRabin Vincent u8 new = ab8500->mask[i]; 34162579266SRabin Vincent int reg; 34262579266SRabin Vincent 34362579266SRabin Vincent if (new == old) 34462579266SRabin Vincent continue; 34562579266SRabin Vincent 3460f620837SLinus Walleij /* 3470f620837SLinus Walleij * Interrupt register 12 doesn't exist prior to AB8500 version 3480f620837SLinus Walleij * 2.0 3490f620837SLinus Walleij */ 3500f620837SLinus Walleij if (ab8500->irq_reg_offset[i] == 11 && 3510f620837SLinus Walleij is_ab8500_1p1_or_earlier(ab8500)) 35292d50a41SMattias Wallin continue; 35392d50a41SMattias Wallin 35462579266SRabin Vincent ab8500->oldmask[i] = new; 35562579266SRabin Vincent 3562ced445eSLinus Walleij reg = AB8500_IT_MASK1_REG + ab8500->irq_reg_offset[i]; 35747c16975SMattias Wallin set_register_interruptible(ab8500, AB8500_INTERRUPT, reg, new); 35862579266SRabin Vincent } 359112a80d2SJonas Aaberg atomic_dec(&ab8500->transfer_ongoing); 36062579266SRabin Vincent mutex_unlock(&ab8500->irq_lock); 36162579266SRabin Vincent } 36262579266SRabin Vincent 3639505a0a0SMark Brown static void ab8500_irq_mask(struct irq_data *data) 36462579266SRabin Vincent { 3659505a0a0SMark Brown struct ab8500 *ab8500 = irq_data_get_irq_chip_data(data); 36606e589efSLee Jones int offset = data->hwirq; 36762579266SRabin Vincent int index = offset / 8; 36862579266SRabin Vincent int mask = 1 << (offset % 8); 36962579266SRabin Vincent 37062579266SRabin Vincent ab8500->mask[index] |= mask; 3719c677b9bSLee Jones 3729c677b9bSLee Jones /* The AB8500 GPIOs have two interrupts each (rising & falling). */ 3739c677b9bSLee Jones if (offset >= AB8500_INT_GPIO6R && offset <= AB8500_INT_GPIO41R) 3749c677b9bSLee Jones ab8500->mask[index + 2] |= mask; 3759c677b9bSLee Jones if (offset >= AB9540_INT_GPIO50R && offset <= AB9540_INT_GPIO54R) 3769c677b9bSLee Jones ab8500->mask[index + 1] |= mask; 3779c677b9bSLee Jones if (offset == AB8540_INT_GPIO43R || offset == AB8540_INT_GPIO44R) 378e2ddf46aSLinus Walleij /* Here the falling IRQ is one bit lower */ 379e2ddf46aSLinus Walleij ab8500->mask[index] |= (mask << 1); 38062579266SRabin Vincent } 38162579266SRabin Vincent 3829505a0a0SMark Brown static void ab8500_irq_unmask(struct irq_data *data) 38362579266SRabin Vincent { 3849505a0a0SMark Brown struct ab8500 *ab8500 = irq_data_get_irq_chip_data(data); 3859c677b9bSLee Jones unsigned int type = irqd_get_trigger_type(data); 38606e589efSLee Jones int offset = data->hwirq; 38762579266SRabin Vincent int index = offset / 8; 38862579266SRabin Vincent int mask = 1 << (offset % 8); 38962579266SRabin Vincent 3909c677b9bSLee Jones if (type & IRQ_TYPE_EDGE_RISING) 3919c677b9bSLee Jones ab8500->mask[index] &= ~mask; 3929c677b9bSLee Jones 3939c677b9bSLee Jones /* The AB8500 GPIOs have two interrupts each (rising & falling). */ 3949c677b9bSLee Jones if (type & IRQ_TYPE_EDGE_FALLING) { 3959c677b9bSLee Jones if (offset >= AB8500_INT_GPIO6R && offset <= AB8500_INT_GPIO41R) 3969c677b9bSLee Jones ab8500->mask[index + 2] &= ~mask; 3979c677b9bSLee Jones else if (offset >= AB9540_INT_GPIO50R && offset <= AB9540_INT_GPIO54R) 3989c677b9bSLee Jones ab8500->mask[index + 1] &= ~mask; 3999c677b9bSLee Jones else if (offset == AB8540_INT_GPIO43R || offset == AB8540_INT_GPIO44R) 400e2ddf46aSLinus Walleij /* Here the falling IRQ is one bit lower */ 401e2ddf46aSLinus Walleij ab8500->mask[index] &= ~(mask << 1); 4029c677b9bSLee Jones else 4039c677b9bSLee Jones ab8500->mask[index] &= ~mask; 404e2ddf46aSLinus Walleij } else { 4059c677b9bSLee Jones /* Satisfies the case where type is not set. */ 40662579266SRabin Vincent ab8500->mask[index] &= ~mask; 40762579266SRabin Vincent } 408e2ddf46aSLinus Walleij } 40962579266SRabin Vincent 41040f6e5a2SLee Jones static int ab8500_irq_set_type(struct irq_data *data, unsigned int type) 41140f6e5a2SLee Jones { 41240f6e5a2SLee Jones return 0; 41340f6e5a2SLee Jones } 41440f6e5a2SLee Jones 41562579266SRabin Vincent static struct irq_chip ab8500_irq_chip = { 41662579266SRabin Vincent .name = "ab8500", 4179505a0a0SMark Brown .irq_bus_lock = ab8500_irq_lock, 4189505a0a0SMark Brown .irq_bus_sync_unlock = ab8500_irq_sync_unlock, 4199505a0a0SMark Brown .irq_mask = ab8500_irq_mask, 420e6f9306eSVirupax Sadashivpetimath .irq_disable = ab8500_irq_mask, 4219505a0a0SMark Brown .irq_unmask = ab8500_irq_unmask, 42240f6e5a2SLee Jones .irq_set_type = ab8500_irq_set_type, 42362579266SRabin Vincent }; 42462579266SRabin Vincent 4257ccfe9b1SMichel JAOUEN static int ab8500_handle_hierarchical_line(struct ab8500 *ab8500, 4267ccfe9b1SMichel JAOUEN int latch_offset, u8 latch_val) 4277ccfe9b1SMichel JAOUEN { 4287ccfe9b1SMichel JAOUEN int int_bit = __ffs(latch_val); 4297ccfe9b1SMichel JAOUEN int line, i; 4307ccfe9b1SMichel JAOUEN 4317ccfe9b1SMichel JAOUEN do { 4327ccfe9b1SMichel JAOUEN int_bit = __ffs(latch_val); 4337ccfe9b1SMichel JAOUEN 4347ccfe9b1SMichel JAOUEN for (i = 0; i < ab8500->mask_size; i++) 4357ccfe9b1SMichel JAOUEN if (ab8500->irq_reg_offset[i] == latch_offset) 4367ccfe9b1SMichel JAOUEN break; 4377ccfe9b1SMichel JAOUEN 4387ccfe9b1SMichel JAOUEN if (i >= ab8500->mask_size) { 4397ccfe9b1SMichel JAOUEN dev_err(ab8500->dev, "Register offset 0x%2x not declared\n", 4407ccfe9b1SMichel JAOUEN latch_offset); 4417ccfe9b1SMichel JAOUEN return -ENXIO; 4427ccfe9b1SMichel JAOUEN } 4437ccfe9b1SMichel JAOUEN 4447ccfe9b1SMichel JAOUEN line = (i << 3) + int_bit; 4457ccfe9b1SMichel JAOUEN latch_val &= ~(1 << int_bit); 4467ccfe9b1SMichel JAOUEN 447e2ddf46aSLinus Walleij /* 448e2ddf46aSLinus Walleij * This handles the falling edge hwirqs from the GPIO 449e2ddf46aSLinus Walleij * lines. Route them back to the line registered for the 450e2ddf46aSLinus Walleij * rising IRQ, as this is merely a flag for the same IRQ 451e2ddf46aSLinus Walleij * in linux terms. 452e2ddf46aSLinus Walleij */ 453e2ddf46aSLinus Walleij if (line >= AB8500_INT_GPIO6F && line <= AB8500_INT_GPIO41F) 454e2ddf46aSLinus Walleij line -= 16; 455e2ddf46aSLinus Walleij if (line >= AB9540_INT_GPIO50F && line <= AB9540_INT_GPIO54F) 456e2ddf46aSLinus Walleij line -= 8; 457e2ddf46aSLinus Walleij if (line == AB8540_INT_GPIO43F || line == AB8540_INT_GPIO44F) 458e2ddf46aSLinus Walleij line += 1; 459e2ddf46aSLinus Walleij 4607ccfe9b1SMichel JAOUEN handle_nested_irq(ab8500->irq_base + line); 4617ccfe9b1SMichel JAOUEN } while (latch_val); 4627ccfe9b1SMichel JAOUEN 4637ccfe9b1SMichel JAOUEN return 0; 4647ccfe9b1SMichel JAOUEN } 4657ccfe9b1SMichel JAOUEN 4667ccfe9b1SMichel JAOUEN static int ab8500_handle_hierarchical_latch(struct ab8500 *ab8500, 4677ccfe9b1SMichel JAOUEN int hier_offset, u8 hier_val) 4687ccfe9b1SMichel JAOUEN { 4697ccfe9b1SMichel JAOUEN int latch_bit, status; 4707ccfe9b1SMichel JAOUEN u8 latch_offset, latch_val; 4717ccfe9b1SMichel JAOUEN 4727ccfe9b1SMichel JAOUEN do { 4737ccfe9b1SMichel JAOUEN latch_bit = __ffs(hier_val); 4747ccfe9b1SMichel JAOUEN latch_offset = (hier_offset << 3) + latch_bit; 4757ccfe9b1SMichel JAOUEN 4767ccfe9b1SMichel JAOUEN /* Fix inconsistent ITFromLatch25 bit mapping... */ 4777ccfe9b1SMichel JAOUEN if (unlikely(latch_offset == 17)) 4787ccfe9b1SMichel JAOUEN latch_offset = 24; 4797ccfe9b1SMichel JAOUEN 4807ccfe9b1SMichel JAOUEN status = get_register_interruptible(ab8500, 4817ccfe9b1SMichel JAOUEN AB8500_INTERRUPT, 4827ccfe9b1SMichel JAOUEN AB8500_IT_LATCH1_REG + latch_offset, 4837ccfe9b1SMichel JAOUEN &latch_val); 4847ccfe9b1SMichel JAOUEN if (status < 0 || latch_val == 0) 4857ccfe9b1SMichel JAOUEN goto discard; 4867ccfe9b1SMichel JAOUEN 4877ccfe9b1SMichel JAOUEN status = ab8500_handle_hierarchical_line(ab8500, 4887ccfe9b1SMichel JAOUEN latch_offset, latch_val); 4897ccfe9b1SMichel JAOUEN if (status < 0) 4907ccfe9b1SMichel JAOUEN return status; 4917ccfe9b1SMichel JAOUEN discard: 4927ccfe9b1SMichel JAOUEN hier_val &= ~(1 << latch_bit); 4937ccfe9b1SMichel JAOUEN } while (hier_val); 4947ccfe9b1SMichel JAOUEN 4957ccfe9b1SMichel JAOUEN return 0; 4967ccfe9b1SMichel JAOUEN } 4977ccfe9b1SMichel JAOUEN 4987ccfe9b1SMichel JAOUEN static irqreturn_t ab8500_hierarchical_irq(int irq, void *dev) 4997ccfe9b1SMichel JAOUEN { 5007ccfe9b1SMichel JAOUEN struct ab8500 *ab8500 = dev; 5017ccfe9b1SMichel JAOUEN u8 i; 5027ccfe9b1SMichel JAOUEN 5037ccfe9b1SMichel JAOUEN dev_vdbg(ab8500->dev, "interrupt\n"); 5047ccfe9b1SMichel JAOUEN 5057ccfe9b1SMichel JAOUEN /* Hierarchical interrupt version */ 5067ccfe9b1SMichel JAOUEN for (i = 0; i < AB8500_IT_LATCHHIER_NUM; i++) { 5077ccfe9b1SMichel JAOUEN int status; 5087ccfe9b1SMichel JAOUEN u8 hier_val; 5097ccfe9b1SMichel JAOUEN 5107ccfe9b1SMichel JAOUEN status = get_register_interruptible(ab8500, AB8500_INTERRUPT, 5117ccfe9b1SMichel JAOUEN AB8500_IT_LATCHHIER1_REG + i, &hier_val); 5127ccfe9b1SMichel JAOUEN if (status < 0 || hier_val == 0) 5137ccfe9b1SMichel JAOUEN continue; 5147ccfe9b1SMichel JAOUEN 5157ccfe9b1SMichel JAOUEN status = ab8500_handle_hierarchical_latch(ab8500, i, hier_val); 5167ccfe9b1SMichel JAOUEN if (status < 0) 5177ccfe9b1SMichel JAOUEN break; 5187ccfe9b1SMichel JAOUEN } 5197ccfe9b1SMichel JAOUEN return IRQ_HANDLED; 5207ccfe9b1SMichel JAOUEN } 5217ccfe9b1SMichel JAOUEN 52280633f05SLee Jones /** 52380633f05SLee Jones * ab8500_irq_get_virq(): Map an interrupt on a chip to a virtual IRQ 52480633f05SLee Jones * 52580633f05SLee Jones * @ab8500: ab8500_irq controller to operate on. 52680633f05SLee Jones * @irq: index of the interrupt requested in the chip IRQs 52780633f05SLee Jones * 52880633f05SLee Jones * Useful for drivers to request their own IRQs. 52980633f05SLee Jones */ 53080633f05SLee Jones static int ab8500_irq_get_virq(struct ab8500 *ab8500, int irq) 53180633f05SLee Jones { 53280633f05SLee Jones if (!ab8500) 53380633f05SLee Jones return -EINVAL; 53480633f05SLee Jones 53580633f05SLee Jones return irq_create_mapping(ab8500->domain, irq); 53680633f05SLee Jones } 53780633f05SLee Jones 53862579266SRabin Vincent static irqreturn_t ab8500_irq(int irq, void *dev) 53962579266SRabin Vincent { 54062579266SRabin Vincent struct ab8500 *ab8500 = dev; 54162579266SRabin Vincent int i; 54262579266SRabin Vincent 54362579266SRabin Vincent dev_vdbg(ab8500->dev, "interrupt\n"); 54462579266SRabin Vincent 545112a80d2SJonas Aaberg atomic_inc(&ab8500->transfer_ongoing); 546112a80d2SJonas Aaberg 5472ced445eSLinus Walleij for (i = 0; i < ab8500->mask_size; i++) { 5482ced445eSLinus Walleij int regoffset = ab8500->irq_reg_offset[i]; 54962579266SRabin Vincent int status; 55047c16975SMattias Wallin u8 value; 55162579266SRabin Vincent 5520f620837SLinus Walleij /* 5530f620837SLinus Walleij * Interrupt register 12 doesn't exist prior to AB8500 version 5540f620837SLinus Walleij * 2.0 5550f620837SLinus Walleij */ 5560f620837SLinus Walleij if (regoffset == 11 && is_ab8500_1p1_or_earlier(ab8500)) 55792d50a41SMattias Wallin continue; 55892d50a41SMattias Wallin 55947c16975SMattias Wallin status = get_register_interruptible(ab8500, AB8500_INTERRUPT, 56047c16975SMattias Wallin AB8500_IT_LATCH1_REG + regoffset, &value); 56147c16975SMattias Wallin if (status < 0 || value == 0) 56262579266SRabin Vincent continue; 56362579266SRabin Vincent 56462579266SRabin Vincent do { 56588aec4f7SMattias Wallin int bit = __ffs(value); 56662579266SRabin Vincent int line = i * 8 + bit; 5670a37fc56SLee Jones int virq = ab8500_irq_get_virq(ab8500, line); 56862579266SRabin Vincent 5690a37fc56SLee Jones handle_nested_irq(virq); 57047c16975SMattias Wallin value &= ~(1 << bit); 571112a80d2SJonas Aaberg 57247c16975SMattias Wallin } while (value); 57362579266SRabin Vincent } 574112a80d2SJonas Aaberg atomic_dec(&ab8500->transfer_ongoing); 57562579266SRabin Vincent return IRQ_HANDLED; 57662579266SRabin Vincent } 57762579266SRabin Vincent 57806e589efSLee Jones static int ab8500_irq_map(struct irq_domain *d, unsigned int virq, 57906e589efSLee Jones irq_hw_number_t hwirq) 58006e589efSLee Jones { 58106e589efSLee Jones struct ab8500 *ab8500 = d->host_data; 58206e589efSLee Jones 58306e589efSLee Jones if (!ab8500) 58406e589efSLee Jones return -EINVAL; 58506e589efSLee Jones 58606e589efSLee Jones irq_set_chip_data(virq, ab8500); 58706e589efSLee Jones irq_set_chip_and_handler(virq, &ab8500_irq_chip, 58806e589efSLee Jones handle_simple_irq); 58906e589efSLee Jones irq_set_nested_thread(virq, 1); 59006e589efSLee Jones #ifdef CONFIG_ARM 59106e589efSLee Jones set_irq_flags(virq, IRQF_VALID); 59206e589efSLee Jones #else 59306e589efSLee Jones irq_set_noprobe(virq); 59406e589efSLee Jones #endif 59562579266SRabin Vincent 59662579266SRabin Vincent return 0; 59762579266SRabin Vincent } 59862579266SRabin Vincent 59906e589efSLee Jones static struct irq_domain_ops ab8500_irq_ops = { 60006e589efSLee Jones .map = ab8500_irq_map, 60106e589efSLee Jones .xlate = irq_domain_xlate_twocell, 60206e589efSLee Jones }; 60306e589efSLee Jones 60406e589efSLee Jones static int ab8500_irq_init(struct ab8500 *ab8500, struct device_node *np) 60562579266SRabin Vincent { 6062ced445eSLinus Walleij int num_irqs; 60762579266SRabin Vincent 608d6255529SLinus Walleij if (is_ab9540(ab8500)) 609d6255529SLinus Walleij num_irqs = AB9540_NR_IRQS; 610a982362cSBengt Jonsson else if (is_ab8505(ab8500)) 611a982362cSBengt Jonsson num_irqs = AB8505_NR_IRQS; 612d6255529SLinus Walleij else 6132ced445eSLinus Walleij num_irqs = AB8500_NR_IRQS; 6142ced445eSLinus Walleij 615f1d11f39SLinus Walleij /* If ->irq_base is zero this will give a linear mapping */ 616f1d11f39SLinus Walleij ab8500->domain = irq_domain_add_simple(NULL, 617f1d11f39SLinus Walleij num_irqs, ab8500->irq_base, 618f1d11f39SLinus Walleij &ab8500_irq_ops, ab8500); 61906e589efSLee Jones 62006e589efSLee Jones if (!ab8500->domain) { 62106e589efSLee Jones dev_err(ab8500->dev, "Failed to create irqdomain\n"); 62206e589efSLee Jones return -ENOSYS; 62306e589efSLee Jones } 62406e589efSLee Jones 62506e589efSLee Jones return 0; 62662579266SRabin Vincent } 62762579266SRabin Vincent 628112a80d2SJonas Aaberg int ab8500_suspend(struct ab8500 *ab8500) 629112a80d2SJonas Aaberg { 630112a80d2SJonas Aaberg if (atomic_read(&ab8500->transfer_ongoing)) 631112a80d2SJonas Aaberg return -EINVAL; 632112a80d2SJonas Aaberg else 633112a80d2SJonas Aaberg return 0; 634112a80d2SJonas Aaberg } 635112a80d2SJonas Aaberg 636a9e9ce4cSBill Pemberton static struct resource ab8500_gpadc_resources[] = { 63762579266SRabin Vincent { 63862579266SRabin Vincent .name = "HW_CONV_END", 63962579266SRabin Vincent .start = AB8500_INT_GP_HW_ADC_CONV_END, 64062579266SRabin Vincent .end = AB8500_INT_GP_HW_ADC_CONV_END, 64162579266SRabin Vincent .flags = IORESOURCE_IRQ, 64262579266SRabin Vincent }, 64362579266SRabin Vincent { 64462579266SRabin Vincent .name = "SW_CONV_END", 64562579266SRabin Vincent .start = AB8500_INT_GP_SW_ADC_CONV_END, 64662579266SRabin Vincent .end = AB8500_INT_GP_SW_ADC_CONV_END, 64762579266SRabin Vincent .flags = IORESOURCE_IRQ, 64862579266SRabin Vincent }, 64962579266SRabin Vincent }; 65062579266SRabin Vincent 651a9e9ce4cSBill Pemberton static struct resource ab8500_rtc_resources[] = { 65262579266SRabin Vincent { 65362579266SRabin Vincent .name = "60S", 65462579266SRabin Vincent .start = AB8500_INT_RTC_60S, 65562579266SRabin Vincent .end = AB8500_INT_RTC_60S, 65662579266SRabin Vincent .flags = IORESOURCE_IRQ, 65762579266SRabin Vincent }, 65862579266SRabin Vincent { 65962579266SRabin Vincent .name = "ALARM", 66062579266SRabin Vincent .start = AB8500_INT_RTC_ALARM, 66162579266SRabin Vincent .end = AB8500_INT_RTC_ALARM, 66262579266SRabin Vincent .flags = IORESOURCE_IRQ, 66362579266SRabin Vincent }, 66462579266SRabin Vincent }; 66562579266SRabin Vincent 666a9e9ce4cSBill Pemberton static struct resource ab8500_poweronkey_db_resources[] = { 66777686517SSundar R Iyer { 66877686517SSundar R Iyer .name = "ONKEY_DBF", 66977686517SSundar R Iyer .start = AB8500_INT_PON_KEY1DB_F, 67077686517SSundar R Iyer .end = AB8500_INT_PON_KEY1DB_F, 67177686517SSundar R Iyer .flags = IORESOURCE_IRQ, 67277686517SSundar R Iyer }, 67377686517SSundar R Iyer { 67477686517SSundar R Iyer .name = "ONKEY_DBR", 67577686517SSundar R Iyer .start = AB8500_INT_PON_KEY1DB_R, 67677686517SSundar R Iyer .end = AB8500_INT_PON_KEY1DB_R, 67777686517SSundar R Iyer .flags = IORESOURCE_IRQ, 67877686517SSundar R Iyer }, 67977686517SSundar R Iyer }; 68077686517SSundar R Iyer 681a9e9ce4cSBill Pemberton static struct resource ab8500_av_acc_detect_resources[] = { 682e098adedSMattias Wallin { 6836af75ecdSLinus Walleij .name = "ACC_DETECT_1DB_F", 6846af75ecdSLinus Walleij .start = AB8500_INT_ACC_DETECT_1DB_F, 6856af75ecdSLinus Walleij .end = AB8500_INT_ACC_DETECT_1DB_F, 686e098adedSMattias Wallin .flags = IORESOURCE_IRQ, 687e098adedSMattias Wallin }, 688e098adedSMattias Wallin { 6896af75ecdSLinus Walleij .name = "ACC_DETECT_1DB_R", 6906af75ecdSLinus Walleij .start = AB8500_INT_ACC_DETECT_1DB_R, 6916af75ecdSLinus Walleij .end = AB8500_INT_ACC_DETECT_1DB_R, 692e098adedSMattias Wallin .flags = IORESOURCE_IRQ, 693e098adedSMattias Wallin }, 694e098adedSMattias Wallin { 6956af75ecdSLinus Walleij .name = "ACC_DETECT_21DB_F", 6966af75ecdSLinus Walleij .start = AB8500_INT_ACC_DETECT_21DB_F, 6976af75ecdSLinus Walleij .end = AB8500_INT_ACC_DETECT_21DB_F, 6986af75ecdSLinus Walleij .flags = IORESOURCE_IRQ, 6996af75ecdSLinus Walleij }, 7006af75ecdSLinus Walleij { 7016af75ecdSLinus Walleij .name = "ACC_DETECT_21DB_R", 7026af75ecdSLinus Walleij .start = AB8500_INT_ACC_DETECT_21DB_R, 7036af75ecdSLinus Walleij .end = AB8500_INT_ACC_DETECT_21DB_R, 7046af75ecdSLinus Walleij .flags = IORESOURCE_IRQ, 7056af75ecdSLinus Walleij }, 7066af75ecdSLinus Walleij { 7076af75ecdSLinus Walleij .name = "ACC_DETECT_22DB_F", 7086af75ecdSLinus Walleij .start = AB8500_INT_ACC_DETECT_22DB_F, 7096af75ecdSLinus Walleij .end = AB8500_INT_ACC_DETECT_22DB_F, 7106af75ecdSLinus Walleij .flags = IORESOURCE_IRQ, 7116af75ecdSLinus Walleij }, 7126af75ecdSLinus Walleij { 7136af75ecdSLinus Walleij .name = "ACC_DETECT_22DB_R", 7146af75ecdSLinus Walleij .start = AB8500_INT_ACC_DETECT_22DB_R, 7156af75ecdSLinus Walleij .end = AB8500_INT_ACC_DETECT_22DB_R, 7166af75ecdSLinus Walleij .flags = IORESOURCE_IRQ, 7176af75ecdSLinus Walleij }, 7186af75ecdSLinus Walleij }; 7196af75ecdSLinus Walleij 720a9e9ce4cSBill Pemberton static struct resource ab8500_charger_resources[] = { 7216af75ecdSLinus Walleij { 722e098adedSMattias Wallin .name = "MAIN_CH_UNPLUG_DET", 723e098adedSMattias Wallin .start = AB8500_INT_MAIN_CH_UNPLUG_DET, 724e098adedSMattias Wallin .end = AB8500_INT_MAIN_CH_UNPLUG_DET, 725e098adedSMattias Wallin .flags = IORESOURCE_IRQ, 726e098adedSMattias Wallin }, 727e098adedSMattias Wallin { 728e098adedSMattias Wallin .name = "MAIN_CHARGE_PLUG_DET", 729e098adedSMattias Wallin .start = AB8500_INT_MAIN_CH_PLUG_DET, 730e098adedSMattias Wallin .end = AB8500_INT_MAIN_CH_PLUG_DET, 731e098adedSMattias Wallin .flags = IORESOURCE_IRQ, 732e098adedSMattias Wallin }, 733e098adedSMattias Wallin { 734e098adedSMattias Wallin .name = "VBUS_DET_R", 735e098adedSMattias Wallin .start = AB8500_INT_VBUS_DET_R, 736e098adedSMattias Wallin .end = AB8500_INT_VBUS_DET_R, 737e098adedSMattias Wallin .flags = IORESOURCE_IRQ, 738e098adedSMattias Wallin }, 739e098adedSMattias Wallin { 7406af75ecdSLinus Walleij .name = "VBUS_DET_F", 7416af75ecdSLinus Walleij .start = AB8500_INT_VBUS_DET_F, 7426af75ecdSLinus Walleij .end = AB8500_INT_VBUS_DET_F, 743e098adedSMattias Wallin .flags = IORESOURCE_IRQ, 744e098adedSMattias Wallin }, 745e098adedSMattias Wallin { 7466af75ecdSLinus Walleij .name = "USB_LINK_STATUS", 7476af75ecdSLinus Walleij .start = AB8500_INT_USB_LINK_STATUS, 7486af75ecdSLinus Walleij .end = AB8500_INT_USB_LINK_STATUS, 7496af75ecdSLinus Walleij .flags = IORESOURCE_IRQ, 7506af75ecdSLinus Walleij }, 7516af75ecdSLinus Walleij { 752e098adedSMattias Wallin .name = "VBUS_OVV", 753e098adedSMattias Wallin .start = AB8500_INT_VBUS_OVV, 754e098adedSMattias Wallin .end = AB8500_INT_VBUS_OVV, 755e098adedSMattias Wallin .flags = IORESOURCE_IRQ, 756e098adedSMattias Wallin }, 757e098adedSMattias Wallin { 7586af75ecdSLinus Walleij .name = "USB_CH_TH_PROT_R", 7596af75ecdSLinus Walleij .start = AB8500_INT_USB_CH_TH_PROT_R, 7606af75ecdSLinus Walleij .end = AB8500_INT_USB_CH_TH_PROT_R, 761e098adedSMattias Wallin .flags = IORESOURCE_IRQ, 762e098adedSMattias Wallin }, 763e098adedSMattias Wallin { 7646af75ecdSLinus Walleij .name = "USB_CH_TH_PROT_F", 7656af75ecdSLinus Walleij .start = AB8500_INT_USB_CH_TH_PROT_F, 7666af75ecdSLinus Walleij .end = AB8500_INT_USB_CH_TH_PROT_F, 767e098adedSMattias Wallin .flags = IORESOURCE_IRQ, 768e098adedSMattias Wallin }, 769e098adedSMattias Wallin { 7706af75ecdSLinus Walleij .name = "MAIN_EXT_CH_NOT_OK", 7716af75ecdSLinus Walleij .start = AB8500_INT_MAIN_EXT_CH_NOT_OK, 7726af75ecdSLinus Walleij .end = AB8500_INT_MAIN_EXT_CH_NOT_OK, 7736af75ecdSLinus Walleij .flags = IORESOURCE_IRQ, 7746af75ecdSLinus Walleij }, 7756af75ecdSLinus Walleij { 7766af75ecdSLinus Walleij .name = "MAIN_CH_TH_PROT_R", 7776af75ecdSLinus Walleij .start = AB8500_INT_MAIN_CH_TH_PROT_R, 7786af75ecdSLinus Walleij .end = AB8500_INT_MAIN_CH_TH_PROT_R, 7796af75ecdSLinus Walleij .flags = IORESOURCE_IRQ, 7806af75ecdSLinus Walleij }, 7816af75ecdSLinus Walleij { 7826af75ecdSLinus Walleij .name = "MAIN_CH_TH_PROT_F", 7836af75ecdSLinus Walleij .start = AB8500_INT_MAIN_CH_TH_PROT_F, 7846af75ecdSLinus Walleij .end = AB8500_INT_MAIN_CH_TH_PROT_F, 7856af75ecdSLinus Walleij .flags = IORESOURCE_IRQ, 7866af75ecdSLinus Walleij }, 7876af75ecdSLinus Walleij { 7886af75ecdSLinus Walleij .name = "USB_CHARGER_NOT_OKR", 789a982362cSBengt Jonsson .start = AB8500_INT_USB_CHARGER_NOT_OKR, 790a982362cSBengt Jonsson .end = AB8500_INT_USB_CHARGER_NOT_OKR, 7916af75ecdSLinus Walleij .flags = IORESOURCE_IRQ, 7926af75ecdSLinus Walleij }, 7936af75ecdSLinus Walleij { 7946af75ecdSLinus Walleij .name = "CH_WD_EXP", 7956af75ecdSLinus Walleij .start = AB8500_INT_CH_WD_EXP, 7966af75ecdSLinus Walleij .end = AB8500_INT_CH_WD_EXP, 7976af75ecdSLinus Walleij .flags = IORESOURCE_IRQ, 7986af75ecdSLinus Walleij }, 7996af75ecdSLinus Walleij }; 8006af75ecdSLinus Walleij 801a9e9ce4cSBill Pemberton static struct resource ab8500_btemp_resources[] = { 8026af75ecdSLinus Walleij { 8036af75ecdSLinus Walleij .name = "BAT_CTRL_INDB", 8046af75ecdSLinus Walleij .start = AB8500_INT_BAT_CTRL_INDB, 8056af75ecdSLinus Walleij .end = AB8500_INT_BAT_CTRL_INDB, 806e098adedSMattias Wallin .flags = IORESOURCE_IRQ, 807e098adedSMattias Wallin }, 808e098adedSMattias Wallin { 809e098adedSMattias Wallin .name = "BTEMP_LOW", 810e098adedSMattias Wallin .start = AB8500_INT_BTEMP_LOW, 811e098adedSMattias Wallin .end = AB8500_INT_BTEMP_LOW, 812e098adedSMattias Wallin .flags = IORESOURCE_IRQ, 813e098adedSMattias Wallin }, 814e098adedSMattias Wallin { 815e098adedSMattias Wallin .name = "BTEMP_HIGH", 816e098adedSMattias Wallin .start = AB8500_INT_BTEMP_HIGH, 817e098adedSMattias Wallin .end = AB8500_INT_BTEMP_HIGH, 818e098adedSMattias Wallin .flags = IORESOURCE_IRQ, 819e098adedSMattias Wallin }, 820e098adedSMattias Wallin { 8216af75ecdSLinus Walleij .name = "BTEMP_LOW_MEDIUM", 8226af75ecdSLinus Walleij .start = AB8500_INT_BTEMP_LOW_MEDIUM, 8236af75ecdSLinus Walleij .end = AB8500_INT_BTEMP_LOW_MEDIUM, 824e098adedSMattias Wallin .flags = IORESOURCE_IRQ, 825e098adedSMattias Wallin }, 826e098adedSMattias Wallin { 8276af75ecdSLinus Walleij .name = "BTEMP_MEDIUM_HIGH", 8286af75ecdSLinus Walleij .start = AB8500_INT_BTEMP_MEDIUM_HIGH, 8296af75ecdSLinus Walleij .end = AB8500_INT_BTEMP_MEDIUM_HIGH, 830e098adedSMattias Wallin .flags = IORESOURCE_IRQ, 831e098adedSMattias Wallin }, 832e098adedSMattias Wallin }; 833e098adedSMattias Wallin 834a9e9ce4cSBill Pemberton static struct resource ab8500_fg_resources[] = { 8356af75ecdSLinus Walleij { 8366af75ecdSLinus Walleij .name = "NCONV_ACCU", 8376af75ecdSLinus Walleij .start = AB8500_INT_CCN_CONV_ACC, 8386af75ecdSLinus Walleij .end = AB8500_INT_CCN_CONV_ACC, 8396af75ecdSLinus Walleij .flags = IORESOURCE_IRQ, 8406af75ecdSLinus Walleij }, 8416af75ecdSLinus Walleij { 8426af75ecdSLinus Walleij .name = "BATT_OVV", 8436af75ecdSLinus Walleij .start = AB8500_INT_BATT_OVV, 8446af75ecdSLinus Walleij .end = AB8500_INT_BATT_OVV, 8456af75ecdSLinus Walleij .flags = IORESOURCE_IRQ, 8466af75ecdSLinus Walleij }, 8476af75ecdSLinus Walleij { 8486af75ecdSLinus Walleij .name = "LOW_BAT_F", 8496af75ecdSLinus Walleij .start = AB8500_INT_LOW_BAT_F, 8506af75ecdSLinus Walleij .end = AB8500_INT_LOW_BAT_F, 8516af75ecdSLinus Walleij .flags = IORESOURCE_IRQ, 8526af75ecdSLinus Walleij }, 8536af75ecdSLinus Walleij { 8546af75ecdSLinus Walleij .name = "LOW_BAT_R", 8556af75ecdSLinus Walleij .start = AB8500_INT_LOW_BAT_R, 8566af75ecdSLinus Walleij .end = AB8500_INT_LOW_BAT_R, 8576af75ecdSLinus Walleij .flags = IORESOURCE_IRQ, 8586af75ecdSLinus Walleij }, 8596af75ecdSLinus Walleij { 8606af75ecdSLinus Walleij .name = "CC_INT_CALIB", 8616af75ecdSLinus Walleij .start = AB8500_INT_CC_INT_CALIB, 8626af75ecdSLinus Walleij .end = AB8500_INT_CC_INT_CALIB, 8636af75ecdSLinus Walleij .flags = IORESOURCE_IRQ, 8646af75ecdSLinus Walleij }, 865a982362cSBengt Jonsson { 866a982362cSBengt Jonsson .name = "CCEOC", 867a982362cSBengt Jonsson .start = AB8500_INT_CCEOC, 868a982362cSBengt Jonsson .end = AB8500_INT_CCEOC, 869a982362cSBengt Jonsson .flags = IORESOURCE_IRQ, 870a982362cSBengt Jonsson }, 8716af75ecdSLinus Walleij }; 8726af75ecdSLinus Walleij 873a9e9ce4cSBill Pemberton static struct resource ab8500_chargalg_resources[] = {}; 8746af75ecdSLinus Walleij 875df720647SAxel Lin #ifdef CONFIG_DEBUG_FS 876a9e9ce4cSBill Pemberton static struct resource ab8500_debug_resources[] = { 877e098adedSMattias Wallin { 878e098adedSMattias Wallin .name = "IRQ_FIRST", 879e098adedSMattias Wallin .start = AB8500_INT_MAIN_EXT_CH_NOT_OK, 880e098adedSMattias Wallin .end = AB8500_INT_MAIN_EXT_CH_NOT_OK, 881e098adedSMattias Wallin .flags = IORESOURCE_IRQ, 882e098adedSMattias Wallin }, 883e098adedSMattias Wallin { 884e098adedSMattias Wallin .name = "IRQ_LAST", 885a982362cSBengt Jonsson .start = AB8500_INT_XTAL32K_KO, 886a982362cSBengt Jonsson .end = AB8500_INT_XTAL32K_KO, 887e098adedSMattias Wallin .flags = IORESOURCE_IRQ, 888e098adedSMattias Wallin }, 889e098adedSMattias Wallin }; 890df720647SAxel Lin #endif 891e098adedSMattias Wallin 892a9e9ce4cSBill Pemberton static struct resource ab8500_usb_resources[] = { 893e098adedSMattias Wallin { 894e098adedSMattias Wallin .name = "ID_WAKEUP_R", 895e098adedSMattias Wallin .start = AB8500_INT_ID_WAKEUP_R, 896e098adedSMattias Wallin .end = AB8500_INT_ID_WAKEUP_R, 897e098adedSMattias Wallin .flags = IORESOURCE_IRQ, 898e098adedSMattias Wallin }, 899e098adedSMattias Wallin { 900e098adedSMattias Wallin .name = "ID_WAKEUP_F", 901e098adedSMattias Wallin .start = AB8500_INT_ID_WAKEUP_F, 902e098adedSMattias Wallin .end = AB8500_INT_ID_WAKEUP_F, 903e098adedSMattias Wallin .flags = IORESOURCE_IRQ, 904e098adedSMattias Wallin }, 905e098adedSMattias Wallin { 906e098adedSMattias Wallin .name = "VBUS_DET_F", 907e098adedSMattias Wallin .start = AB8500_INT_VBUS_DET_F, 908e098adedSMattias Wallin .end = AB8500_INT_VBUS_DET_F, 909e098adedSMattias Wallin .flags = IORESOURCE_IRQ, 910e098adedSMattias Wallin }, 911e098adedSMattias Wallin { 912e098adedSMattias Wallin .name = "VBUS_DET_R", 913e098adedSMattias Wallin .start = AB8500_INT_VBUS_DET_R, 914e098adedSMattias Wallin .end = AB8500_INT_VBUS_DET_R, 915e098adedSMattias Wallin .flags = IORESOURCE_IRQ, 916e098adedSMattias Wallin }, 91792d50a41SMattias Wallin { 91892d50a41SMattias Wallin .name = "USB_LINK_STATUS", 91992d50a41SMattias Wallin .start = AB8500_INT_USB_LINK_STATUS, 92092d50a41SMattias Wallin .end = AB8500_INT_USB_LINK_STATUS, 92192d50a41SMattias Wallin .flags = IORESOURCE_IRQ, 92292d50a41SMattias Wallin }, 9236af75ecdSLinus Walleij { 9246af75ecdSLinus Walleij .name = "USB_ADP_PROBE_PLUG", 9256af75ecdSLinus Walleij .start = AB8500_INT_ADP_PROBE_PLUG, 9266af75ecdSLinus Walleij .end = AB8500_INT_ADP_PROBE_PLUG, 9276af75ecdSLinus Walleij .flags = IORESOURCE_IRQ, 9286af75ecdSLinus Walleij }, 9296af75ecdSLinus Walleij { 9306af75ecdSLinus Walleij .name = "USB_ADP_PROBE_UNPLUG", 9316af75ecdSLinus Walleij .start = AB8500_INT_ADP_PROBE_UNPLUG, 9326af75ecdSLinus Walleij .end = AB8500_INT_ADP_PROBE_UNPLUG, 9336af75ecdSLinus Walleij .flags = IORESOURCE_IRQ, 9346af75ecdSLinus Walleij }, 935e098adedSMattias Wallin }; 936e098adedSMattias Wallin 937a9e9ce4cSBill Pemberton static struct resource ab8505_iddet_resources[] = { 93844f72e53SVirupax Sadashivpetimath { 93944f72e53SVirupax Sadashivpetimath .name = "KeyDeglitch", 94044f72e53SVirupax Sadashivpetimath .start = AB8505_INT_KEYDEGLITCH, 94144f72e53SVirupax Sadashivpetimath .end = AB8505_INT_KEYDEGLITCH, 94244f72e53SVirupax Sadashivpetimath .flags = IORESOURCE_IRQ, 94344f72e53SVirupax Sadashivpetimath }, 94444f72e53SVirupax Sadashivpetimath { 94544f72e53SVirupax Sadashivpetimath .name = "KP", 94644f72e53SVirupax Sadashivpetimath .start = AB8505_INT_KP, 94744f72e53SVirupax Sadashivpetimath .end = AB8505_INT_KP, 94844f72e53SVirupax Sadashivpetimath .flags = IORESOURCE_IRQ, 94944f72e53SVirupax Sadashivpetimath }, 95044f72e53SVirupax Sadashivpetimath { 95144f72e53SVirupax Sadashivpetimath .name = "IKP", 95244f72e53SVirupax Sadashivpetimath .start = AB8505_INT_IKP, 95344f72e53SVirupax Sadashivpetimath .end = AB8505_INT_IKP, 95444f72e53SVirupax Sadashivpetimath .flags = IORESOURCE_IRQ, 95544f72e53SVirupax Sadashivpetimath }, 95644f72e53SVirupax Sadashivpetimath { 95744f72e53SVirupax Sadashivpetimath .name = "IKR", 95844f72e53SVirupax Sadashivpetimath .start = AB8505_INT_IKR, 95944f72e53SVirupax Sadashivpetimath .end = AB8505_INT_IKR, 96044f72e53SVirupax Sadashivpetimath .flags = IORESOURCE_IRQ, 96144f72e53SVirupax Sadashivpetimath }, 96244f72e53SVirupax Sadashivpetimath { 96344f72e53SVirupax Sadashivpetimath .name = "KeyStuck", 96444f72e53SVirupax Sadashivpetimath .start = AB8505_INT_KEYSTUCK, 96544f72e53SVirupax Sadashivpetimath .end = AB8505_INT_KEYSTUCK, 96644f72e53SVirupax Sadashivpetimath .flags = IORESOURCE_IRQ, 96744f72e53SVirupax Sadashivpetimath }, 96844f72e53SVirupax Sadashivpetimath }; 96944f72e53SVirupax Sadashivpetimath 970a9e9ce4cSBill Pemberton static struct resource ab8500_temp_resources[] = { 971e098adedSMattias Wallin { 972e098adedSMattias Wallin .name = "AB8500_TEMP_WARM", 973e098adedSMattias Wallin .start = AB8500_INT_TEMP_WARM, 974e098adedSMattias Wallin .end = AB8500_INT_TEMP_WARM, 975e098adedSMattias Wallin .flags = IORESOURCE_IRQ, 976e098adedSMattias Wallin }, 977e098adedSMattias Wallin }; 978e098adedSMattias Wallin 979a9e9ce4cSBill Pemberton static struct mfd_cell abx500_common_devs[] = { 9805814fc35SMattias Wallin #ifdef CONFIG_DEBUG_FS 9815814fc35SMattias Wallin { 9825814fc35SMattias Wallin .name = "ab8500-debug", 983bad76991SLee Jones .of_compatible = "stericsson,ab8500-debug", 984e098adedSMattias Wallin .num_resources = ARRAY_SIZE(ab8500_debug_resources), 985e098adedSMattias Wallin .resources = ab8500_debug_resources, 9865814fc35SMattias Wallin }, 9875814fc35SMattias Wallin #endif 98862579266SRabin Vincent { 989e098adedSMattias Wallin .name = "ab8500-sysctrl", 990bad76991SLee Jones .of_compatible = "stericsson,ab8500-sysctrl", 991e098adedSMattias Wallin }, 992e098adedSMattias Wallin { 993e098adedSMattias Wallin .name = "ab8500-regulator", 994bad76991SLee Jones .of_compatible = "stericsson,ab8500-regulator", 995e098adedSMattias Wallin }, 996e098adedSMattias Wallin { 997916a871cSUlf Hansson .name = "abx500-clk", 998916a871cSUlf Hansson .of_compatible = "stericsson,abx500-clk", 999916a871cSUlf Hansson }, 1000916a871cSUlf Hansson { 100162579266SRabin Vincent .name = "ab8500-gpadc", 1002bad76991SLee Jones .of_compatible = "stericsson,ab8500-gpadc", 100362579266SRabin Vincent .num_resources = ARRAY_SIZE(ab8500_gpadc_resources), 100462579266SRabin Vincent .resources = ab8500_gpadc_resources, 100562579266SRabin Vincent }, 100662579266SRabin Vincent { 100762579266SRabin Vincent .name = "ab8500-rtc", 1008bad76991SLee Jones .of_compatible = "stericsson,ab8500-rtc", 100962579266SRabin Vincent .num_resources = ARRAY_SIZE(ab8500_rtc_resources), 101062579266SRabin Vincent .resources = ab8500_rtc_resources, 101162579266SRabin Vincent }, 1012f0f05b1cSArun Murthy { 10136af75ecdSLinus Walleij .name = "ab8500-acc-det", 1014bad76991SLee Jones .of_compatible = "stericsson,ab8500-acc-det", 10156af75ecdSLinus Walleij .num_resources = ARRAY_SIZE(ab8500_av_acc_detect_resources), 10166af75ecdSLinus Walleij .resources = ab8500_av_acc_detect_resources, 10176af75ecdSLinus Walleij }, 10186af75ecdSLinus Walleij { 1019e098adedSMattias Wallin .name = "ab8500-poweron-key", 1020bad76991SLee Jones .of_compatible = "stericsson,ab8500-poweron-key", 1021e098adedSMattias Wallin .num_resources = ARRAY_SIZE(ab8500_poweronkey_db_resources), 1022e098adedSMattias Wallin .resources = ab8500_poweronkey_db_resources, 1023e098adedSMattias Wallin }, 1024e098adedSMattias Wallin { 1025f0f05b1cSArun Murthy .name = "ab8500-pwm", 1026bad76991SLee Jones .of_compatible = "stericsson,ab8500-pwm", 1027f0f05b1cSArun Murthy .id = 1, 1028f0f05b1cSArun Murthy }, 1029f0f05b1cSArun Murthy { 1030f0f05b1cSArun Murthy .name = "ab8500-pwm", 1031bad76991SLee Jones .of_compatible = "stericsson,ab8500-pwm", 1032f0f05b1cSArun Murthy .id = 2, 1033f0f05b1cSArun Murthy }, 1034f0f05b1cSArun Murthy { 1035f0f05b1cSArun Murthy .name = "ab8500-pwm", 1036bad76991SLee Jones .of_compatible = "stericsson,ab8500-pwm", 1037f0f05b1cSArun Murthy .id = 3, 1038f0f05b1cSArun Murthy }, 1039bad76991SLee Jones { 1040bad76991SLee Jones .name = "ab8500-leds", 1041bad76991SLee Jones .of_compatible = "stericsson,ab8500-leds", 1042bad76991SLee Jones }, 104377686517SSundar R Iyer { 1044e098adedSMattias Wallin .name = "ab8500-denc", 1045bad76991SLee Jones .of_compatible = "stericsson,ab8500-denc", 1046e098adedSMattias Wallin }, 1047e098adedSMattias Wallin { 1048e098adedSMattias Wallin .name = "ab8500-temp", 1049bad76991SLee Jones .of_compatible = "stericsson,ab8500-temp", 1050e098adedSMattias Wallin .num_resources = ARRAY_SIZE(ab8500_temp_resources), 1051e098adedSMattias Wallin .resources = ab8500_temp_resources, 105277686517SSundar R Iyer }, 105362579266SRabin Vincent }; 105462579266SRabin Vincent 1055a9e9ce4cSBill Pemberton static struct mfd_cell ab8500_bm_devs[] = { 10566ef9418cSRickard Andersson { 10576ef9418cSRickard Andersson .name = "ab8500-charger", 10584aef72dbSRajanikanth H.V .of_compatible = "stericsson,ab8500-charger", 10596ef9418cSRickard Andersson .num_resources = ARRAY_SIZE(ab8500_charger_resources), 10606ef9418cSRickard Andersson .resources = ab8500_charger_resources, 10614aef72dbSRajanikanth H.V #ifndef CONFIG_OF 10624aef72dbSRajanikanth H.V .platform_data = &ab8500_bm_data, 10634aef72dbSRajanikanth H.V .pdata_size = sizeof(ab8500_bm_data), 10644aef72dbSRajanikanth H.V #endif 10656ef9418cSRickard Andersson }, 10666ef9418cSRickard Andersson { 10676ef9418cSRickard Andersson .name = "ab8500-btemp", 1068bd9e8ab2SRajanikanth H.V .of_compatible = "stericsson,ab8500-btemp", 10696ef9418cSRickard Andersson .num_resources = ARRAY_SIZE(ab8500_btemp_resources), 10706ef9418cSRickard Andersson .resources = ab8500_btemp_resources, 1071bd9e8ab2SRajanikanth H.V #ifndef CONFIG_OF 1072bd9e8ab2SRajanikanth H.V .platform_data = &ab8500_bm_data, 1073bd9e8ab2SRajanikanth H.V .pdata_size = sizeof(ab8500_bm_data), 1074bd9e8ab2SRajanikanth H.V #endif 10756ef9418cSRickard Andersson }, 10766ef9418cSRickard Andersson { 10776ef9418cSRickard Andersson .name = "ab8500-fg", 1078e0f1abebSRajanikanth H.V .of_compatible = "stericsson,ab8500-fg", 10796ef9418cSRickard Andersson .num_resources = ARRAY_SIZE(ab8500_fg_resources), 10806ef9418cSRickard Andersson .resources = ab8500_fg_resources, 1081e0f1abebSRajanikanth H.V #ifndef CONFIG_OF 1082e0f1abebSRajanikanth H.V .platform_data = &ab8500_bm_data, 1083e0f1abebSRajanikanth H.V .pdata_size = sizeof(ab8500_bm_data), 1084e0f1abebSRajanikanth H.V #endif 10856ef9418cSRickard Andersson }, 10866ef9418cSRickard Andersson { 10876ef9418cSRickard Andersson .name = "ab8500-chargalg", 1088a12810abSRajanikanth H.V .of_compatible = "stericsson,ab8500-chargalg", 10896ef9418cSRickard Andersson .num_resources = ARRAY_SIZE(ab8500_chargalg_resources), 10906ef9418cSRickard Andersson .resources = ab8500_chargalg_resources, 1091a12810abSRajanikanth H.V #ifndef CONFIG_OF 1092a12810abSRajanikanth H.V .platform_data = &ab8500_bm_data, 1093a12810abSRajanikanth H.V .pdata_size = sizeof(ab8500_bm_data), 1094a12810abSRajanikanth H.V #endif 10956ef9418cSRickard Andersson }, 10966ef9418cSRickard Andersson }; 10976ef9418cSRickard Andersson 1098a9e9ce4cSBill Pemberton static struct mfd_cell ab8500_devs[] = { 1099d6255529SLinus Walleij { 11007d56a46eSLee Jones .name = "pinctrl-ab8500", 1101bad76991SLee Jones .of_compatible = "stericsson,ab8500-gpio", 1102d6255529SLinus Walleij }, 1103d6255529SLinus Walleij { 1104d6255529SLinus Walleij .name = "ab8500-usb", 1105bad76991SLee Jones .of_compatible = "stericsson,ab8500-usb", 1106d6255529SLinus Walleij .num_resources = ARRAY_SIZE(ab8500_usb_resources), 1107d6255529SLinus Walleij .resources = ab8500_usb_resources, 1108d6255529SLinus Walleij }, 110944f72e53SVirupax Sadashivpetimath { 111044f72e53SVirupax Sadashivpetimath .name = "ab8500-codec", 111181a21cddSLee Jones .of_compatible = "stericsson,ab8500-codec", 111244f72e53SVirupax Sadashivpetimath }, 1113d6255529SLinus Walleij }; 1114d6255529SLinus Walleij 1115a9e9ce4cSBill Pemberton static struct mfd_cell ab9540_devs[] = { 1116d6255529SLinus Walleij { 1117*e64d905eSLee Jones .name = "pinctrl-ab9540", 1118*e64d905eSLee Jones .of_compatible = "stericsson,ab9540-gpio", 1119d6255529SLinus Walleij }, 1120d6255529SLinus Walleij { 1121d6255529SLinus Walleij .name = "ab9540-usb", 1122d6255529SLinus Walleij .num_resources = ARRAY_SIZE(ab8500_usb_resources), 1123d6255529SLinus Walleij .resources = ab8500_usb_resources, 1124d6255529SLinus Walleij }, 112544f72e53SVirupax Sadashivpetimath { 112644f72e53SVirupax Sadashivpetimath .name = "ab9540-codec", 112744f72e53SVirupax Sadashivpetimath }, 112844f72e53SVirupax Sadashivpetimath }; 112944f72e53SVirupax Sadashivpetimath 113044f72e53SVirupax Sadashivpetimath /* Device list common to ab9540 and ab8505 */ 1131a9e9ce4cSBill Pemberton static struct mfd_cell ab9540_ab8505_devs[] = { 113244f72e53SVirupax Sadashivpetimath { 113344f72e53SVirupax Sadashivpetimath .name = "ab-iddet", 113444f72e53SVirupax Sadashivpetimath .num_resources = ARRAY_SIZE(ab8505_iddet_resources), 113544f72e53SVirupax Sadashivpetimath .resources = ab8505_iddet_resources, 113644f72e53SVirupax Sadashivpetimath }, 1137d6255529SLinus Walleij }; 1138d6255529SLinus Walleij 1139cca69b67SMattias Wallin static ssize_t show_chip_id(struct device *dev, 1140cca69b67SMattias Wallin struct device_attribute *attr, char *buf) 1141cca69b67SMattias Wallin { 1142cca69b67SMattias Wallin struct ab8500 *ab8500; 1143cca69b67SMattias Wallin 1144cca69b67SMattias Wallin ab8500 = dev_get_drvdata(dev); 1145cca69b67SMattias Wallin return sprintf(buf, "%#x\n", ab8500 ? ab8500->chip_id : -EINVAL); 1146cca69b67SMattias Wallin } 1147cca69b67SMattias Wallin 1148e5c238c3SMattias Wallin /* 1149e5c238c3SMattias Wallin * ab8500 has switched off due to (SWITCH_OFF_STATUS): 1150e5c238c3SMattias Wallin * 0x01 Swoff bit programming 1151e5c238c3SMattias Wallin * 0x02 Thermal protection activation 1152e5c238c3SMattias Wallin * 0x04 Vbat lower then BattOk falling threshold 1153e5c238c3SMattias Wallin * 0x08 Watchdog expired 1154e5c238c3SMattias Wallin * 0x10 Non presence of 32kHz clock 1155e5c238c3SMattias Wallin * 0x20 Battery level lower than power on reset threshold 1156e5c238c3SMattias Wallin * 0x40 Power on key 1 pressed longer than 10 seconds 1157e5c238c3SMattias Wallin * 0x80 DB8500 thermal shutdown 1158e5c238c3SMattias Wallin */ 1159e5c238c3SMattias Wallin static ssize_t show_switch_off_status(struct device *dev, 1160e5c238c3SMattias Wallin struct device_attribute *attr, char *buf) 1161e5c238c3SMattias Wallin { 1162e5c238c3SMattias Wallin int ret; 1163e5c238c3SMattias Wallin u8 value; 1164e5c238c3SMattias Wallin struct ab8500 *ab8500; 1165e5c238c3SMattias Wallin 1166e5c238c3SMattias Wallin ab8500 = dev_get_drvdata(dev); 1167e5c238c3SMattias Wallin ret = get_register_interruptible(ab8500, AB8500_RTC, 1168e5c238c3SMattias Wallin AB8500_SWITCH_OFF_STATUS, &value); 1169e5c238c3SMattias Wallin if (ret < 0) 1170e5c238c3SMattias Wallin return ret; 1171e5c238c3SMattias Wallin return sprintf(buf, "%#x\n", value); 1172e5c238c3SMattias Wallin } 1173e5c238c3SMattias Wallin 1174b4a31037SAndrew Lynn /* 1175b4a31037SAndrew Lynn * ab8500 has turned on due to (TURN_ON_STATUS): 1176b4a31037SAndrew Lynn * 0x01 PORnVbat 1177b4a31037SAndrew Lynn * 0x02 PonKey1dbF 1178b4a31037SAndrew Lynn * 0x04 PonKey2dbF 1179b4a31037SAndrew Lynn * 0x08 RTCAlarm 1180b4a31037SAndrew Lynn * 0x10 MainChDet 1181b4a31037SAndrew Lynn * 0x20 VbusDet 1182b4a31037SAndrew Lynn * 0x40 UsbIDDetect 1183b4a31037SAndrew Lynn * 0x80 Reserved 1184b4a31037SAndrew Lynn */ 1185b4a31037SAndrew Lynn static ssize_t show_turn_on_status(struct device *dev, 1186b4a31037SAndrew Lynn struct device_attribute *attr, char *buf) 1187b4a31037SAndrew Lynn { 1188b4a31037SAndrew Lynn int ret; 1189b4a31037SAndrew Lynn u8 value; 1190b4a31037SAndrew Lynn struct ab8500 *ab8500; 1191b4a31037SAndrew Lynn 1192b4a31037SAndrew Lynn ab8500 = dev_get_drvdata(dev); 1193b4a31037SAndrew Lynn ret = get_register_interruptible(ab8500, AB8500_SYS_CTRL1_BLOCK, 1194b4a31037SAndrew Lynn AB8500_TURN_ON_STATUS, &value); 1195b4a31037SAndrew Lynn if (ret < 0) 1196b4a31037SAndrew Lynn return ret; 1197b4a31037SAndrew Lynn return sprintf(buf, "%#x\n", value); 1198b4a31037SAndrew Lynn } 1199b4a31037SAndrew Lynn 1200d6255529SLinus Walleij static ssize_t show_ab9540_dbbrstn(struct device *dev, 1201d6255529SLinus Walleij struct device_attribute *attr, char *buf) 1202d6255529SLinus Walleij { 1203d6255529SLinus Walleij struct ab8500 *ab8500; 1204d6255529SLinus Walleij int ret; 1205d6255529SLinus Walleij u8 value; 1206d6255529SLinus Walleij 1207d6255529SLinus Walleij ab8500 = dev_get_drvdata(dev); 1208d6255529SLinus Walleij 1209d6255529SLinus Walleij ret = get_register_interruptible(ab8500, AB8500_REGU_CTRL2, 1210d6255529SLinus Walleij AB9540_MODEM_CTRL2_REG, &value); 1211d6255529SLinus Walleij if (ret < 0) 1212d6255529SLinus Walleij return ret; 1213d6255529SLinus Walleij 1214d6255529SLinus Walleij return sprintf(buf, "%d\n", 1215d6255529SLinus Walleij (value & AB9540_MODEM_CTRL2_SWDBBRSTN_BIT) ? 1 : 0); 1216d6255529SLinus Walleij } 1217d6255529SLinus Walleij 1218d6255529SLinus Walleij static ssize_t store_ab9540_dbbrstn(struct device *dev, 1219d6255529SLinus Walleij struct device_attribute *attr, const char *buf, size_t count) 1220d6255529SLinus Walleij { 1221d6255529SLinus Walleij struct ab8500 *ab8500; 1222d6255529SLinus Walleij int ret = count; 1223d6255529SLinus Walleij int err; 1224d6255529SLinus Walleij u8 bitvalues; 1225d6255529SLinus Walleij 1226d6255529SLinus Walleij ab8500 = dev_get_drvdata(dev); 1227d6255529SLinus Walleij 1228d6255529SLinus Walleij if (count > 0) { 1229d6255529SLinus Walleij switch (buf[0]) { 1230d6255529SLinus Walleij case '0': 1231d6255529SLinus Walleij bitvalues = 0; 1232d6255529SLinus Walleij break; 1233d6255529SLinus Walleij case '1': 1234d6255529SLinus Walleij bitvalues = AB9540_MODEM_CTRL2_SWDBBRSTN_BIT; 1235d6255529SLinus Walleij break; 1236d6255529SLinus Walleij default: 1237d6255529SLinus Walleij goto exit; 1238d6255529SLinus Walleij } 1239d6255529SLinus Walleij 1240d6255529SLinus Walleij err = mask_and_set_register_interruptible(ab8500, 1241d6255529SLinus Walleij AB8500_REGU_CTRL2, AB9540_MODEM_CTRL2_REG, 1242d6255529SLinus Walleij AB9540_MODEM_CTRL2_SWDBBRSTN_BIT, bitvalues); 1243d6255529SLinus Walleij if (err) 1244d6255529SLinus Walleij dev_info(ab8500->dev, 1245d6255529SLinus Walleij "Failed to set DBBRSTN %c, err %#x\n", 1246d6255529SLinus Walleij buf[0], err); 1247d6255529SLinus Walleij } 1248d6255529SLinus Walleij 1249d6255529SLinus Walleij exit: 1250d6255529SLinus Walleij return ret; 1251d6255529SLinus Walleij } 1252d6255529SLinus Walleij 1253cca69b67SMattias Wallin static DEVICE_ATTR(chip_id, S_IRUGO, show_chip_id, NULL); 1254e5c238c3SMattias Wallin static DEVICE_ATTR(switch_off_status, S_IRUGO, show_switch_off_status, NULL); 1255b4a31037SAndrew Lynn static DEVICE_ATTR(turn_on_status, S_IRUGO, show_turn_on_status, NULL); 1256d6255529SLinus Walleij static DEVICE_ATTR(dbbrstn, S_IRUGO | S_IWUSR, 1257d6255529SLinus Walleij show_ab9540_dbbrstn, store_ab9540_dbbrstn); 1258cca69b67SMattias Wallin 1259cca69b67SMattias Wallin static struct attribute *ab8500_sysfs_entries[] = { 1260cca69b67SMattias Wallin &dev_attr_chip_id.attr, 1261e5c238c3SMattias Wallin &dev_attr_switch_off_status.attr, 1262b4a31037SAndrew Lynn &dev_attr_turn_on_status.attr, 1263cca69b67SMattias Wallin NULL, 1264cca69b67SMattias Wallin }; 1265cca69b67SMattias Wallin 1266d6255529SLinus Walleij static struct attribute *ab9540_sysfs_entries[] = { 1267d6255529SLinus Walleij &dev_attr_chip_id.attr, 1268d6255529SLinus Walleij &dev_attr_switch_off_status.attr, 1269d6255529SLinus Walleij &dev_attr_turn_on_status.attr, 1270d6255529SLinus Walleij &dev_attr_dbbrstn.attr, 1271d6255529SLinus Walleij NULL, 1272d6255529SLinus Walleij }; 1273d6255529SLinus Walleij 1274cca69b67SMattias Wallin static struct attribute_group ab8500_attr_group = { 1275cca69b67SMattias Wallin .attrs = ab8500_sysfs_entries, 1276cca69b67SMattias Wallin }; 1277cca69b67SMattias Wallin 1278d6255529SLinus Walleij static struct attribute_group ab9540_attr_group = { 1279d6255529SLinus Walleij .attrs = ab9540_sysfs_entries, 1280d6255529SLinus Walleij }; 1281d6255529SLinus Walleij 1282f791be49SBill Pemberton static int ab8500_probe(struct platform_device *pdev) 128362579266SRabin Vincent { 1284b04c530cSJonas Aaberg static char *switch_off_status[] = { 1285b04c530cSJonas Aaberg "Swoff bit programming", 1286b04c530cSJonas Aaberg "Thermal protection activation", 1287b04c530cSJonas Aaberg "Vbat lower then BattOk falling threshold", 1288b04c530cSJonas Aaberg "Watchdog expired", 1289b04c530cSJonas Aaberg "Non presence of 32kHz clock", 1290b04c530cSJonas Aaberg "Battery level lower than power on reset threshold", 1291b04c530cSJonas Aaberg "Power on key 1 pressed longer than 10 seconds", 1292b04c530cSJonas Aaberg "DB8500 thermal shutdown"}; 1293d28f1db8SLee Jones struct ab8500_platform_data *plat = dev_get_platdata(&pdev->dev); 1294d28f1db8SLee Jones const struct platform_device_id *platid = platform_get_device_id(pdev); 12956bc4a568SLee Jones enum ab8500_version version = AB8500_VERSION_UNDEFINED; 12966bc4a568SLee Jones struct device_node *np = pdev->dev.of_node; 1297d28f1db8SLee Jones struct ab8500 *ab8500; 1298d28f1db8SLee Jones struct resource *resource; 129962579266SRabin Vincent int ret; 130062579266SRabin Vincent int i; 130147c16975SMattias Wallin u8 value; 130262579266SRabin Vincent 13038c4203cbSLee Jones ab8500 = devm_kzalloc(&pdev->dev, sizeof *ab8500, GFP_KERNEL); 1304d28f1db8SLee Jones if (!ab8500) 1305d28f1db8SLee Jones return -ENOMEM; 1306d28f1db8SLee Jones 130762579266SRabin Vincent if (plat) 130862579266SRabin Vincent ab8500->irq_base = plat->irq_base; 130962579266SRabin Vincent 1310d28f1db8SLee Jones ab8500->dev = &pdev->dev; 1311d28f1db8SLee Jones 1312d28f1db8SLee Jones resource = platform_get_resource(pdev, IORESOURCE_IRQ, 0); 13138c4203cbSLee Jones if (!resource) 13148c4203cbSLee Jones return -ENODEV; 1315d28f1db8SLee Jones 1316d28f1db8SLee Jones ab8500->irq = resource->start; 1317d28f1db8SLee Jones 1318822672a7SLee Jones ab8500->read = ab8500_prcmu_read; 1319822672a7SLee Jones ab8500->write = ab8500_prcmu_write; 1320822672a7SLee Jones ab8500->write_masked = ab8500_prcmu_write_masked; 1321d28f1db8SLee Jones 132262579266SRabin Vincent mutex_init(&ab8500->lock); 132362579266SRabin Vincent mutex_init(&ab8500->irq_lock); 1324112a80d2SJonas Aaberg atomic_set(&ab8500->transfer_ongoing, 0); 132562579266SRabin Vincent 1326d28f1db8SLee Jones platform_set_drvdata(pdev, ab8500); 1327d28f1db8SLee Jones 13286bc4a568SLee Jones if (platid) 13296bc4a568SLee Jones version = platid->driver_data; 13306bc4a568SLee Jones 13310f620837SLinus Walleij if (version != AB8500_VERSION_UNDEFINED) 13320f620837SLinus Walleij ab8500->version = version; 13330f620837SLinus Walleij else { 13340f620837SLinus Walleij ret = get_register_interruptible(ab8500, AB8500_MISC, 13350f620837SLinus Walleij AB8500_IC_NAME_REG, &value); 13360f620837SLinus Walleij if (ret < 0) 13378c4203cbSLee Jones return ret; 13380f620837SLinus Walleij 13390f620837SLinus Walleij ab8500->version = value; 13400f620837SLinus Walleij } 13410f620837SLinus Walleij 134247c16975SMattias Wallin ret = get_register_interruptible(ab8500, AB8500_MISC, 134347c16975SMattias Wallin AB8500_REV_REG, &value); 134462579266SRabin Vincent if (ret < 0) 13458c4203cbSLee Jones return ret; 134662579266SRabin Vincent 134747c16975SMattias Wallin ab8500->chip_id = value; 134862579266SRabin Vincent 13490f620837SLinus Walleij dev_info(ab8500->dev, "detected chip, %s rev. %1x.%1x\n", 13500f620837SLinus Walleij ab8500_version_str[ab8500->version], 13510f620837SLinus Walleij ab8500->chip_id >> 4, 13520f620837SLinus Walleij ab8500->chip_id & 0x0F); 13530f620837SLinus Walleij 1354d6255529SLinus Walleij /* Configure AB8500 or AB9540 IRQ */ 1355a982362cSBengt Jonsson if (is_ab9540(ab8500) || is_ab8505(ab8500)) { 1356d6255529SLinus Walleij ab8500->mask_size = AB9540_NUM_IRQ_REGS; 1357d6255529SLinus Walleij ab8500->irq_reg_offset = ab9540_irq_regoffset; 1358d6255529SLinus Walleij } else { 13592ced445eSLinus Walleij ab8500->mask_size = AB8500_NUM_IRQ_REGS; 13602ced445eSLinus Walleij ab8500->irq_reg_offset = ab8500_irq_regoffset; 1361d6255529SLinus Walleij } 13628c4203cbSLee Jones ab8500->mask = devm_kzalloc(&pdev->dev, ab8500->mask_size, GFP_KERNEL); 13632ced445eSLinus Walleij if (!ab8500->mask) 13642ced445eSLinus Walleij return -ENOMEM; 13658c4203cbSLee Jones ab8500->oldmask = devm_kzalloc(&pdev->dev, ab8500->mask_size, GFP_KERNEL); 13668c4203cbSLee Jones if (!ab8500->oldmask) 13678c4203cbSLee Jones return -ENOMEM; 13688c4203cbSLee Jones 1369e5c238c3SMattias Wallin /* 1370e5c238c3SMattias Wallin * ab8500 has switched off due to (SWITCH_OFF_STATUS): 1371e5c238c3SMattias Wallin * 0x01 Swoff bit programming 1372e5c238c3SMattias Wallin * 0x02 Thermal protection activation 1373e5c238c3SMattias Wallin * 0x04 Vbat lower then BattOk falling threshold 1374e5c238c3SMattias Wallin * 0x08 Watchdog expired 1375e5c238c3SMattias Wallin * 0x10 Non presence of 32kHz clock 1376e5c238c3SMattias Wallin * 0x20 Battery level lower than power on reset threshold 1377e5c238c3SMattias Wallin * 0x40 Power on key 1 pressed longer than 10 seconds 1378e5c238c3SMattias Wallin * 0x80 DB8500 thermal shutdown 1379e5c238c3SMattias Wallin */ 1380e5c238c3SMattias Wallin 1381e5c238c3SMattias Wallin ret = get_register_interruptible(ab8500, AB8500_RTC, 1382e5c238c3SMattias Wallin AB8500_SWITCH_OFF_STATUS, &value); 1383e5c238c3SMattias Wallin if (ret < 0) 1384e5c238c3SMattias Wallin return ret; 1385b04c530cSJonas Aaberg dev_info(ab8500->dev, "switch off cause(s) (%#x): ", value); 1386b04c530cSJonas Aaberg 1387b04c530cSJonas Aaberg if (value) { 1388b04c530cSJonas Aaberg for (i = 0; i < ARRAY_SIZE(switch_off_status); i++) { 1389b04c530cSJonas Aaberg if (value & 1) 1390b04c530cSJonas Aaberg printk(KERN_CONT " \"%s\"", 1391b04c530cSJonas Aaberg switch_off_status[i]); 1392b04c530cSJonas Aaberg value = value >> 1; 1393b04c530cSJonas Aaberg 1394b04c530cSJonas Aaberg } 1395b04c530cSJonas Aaberg printk(KERN_CONT "\n"); 1396b04c530cSJonas Aaberg } else { 1397b04c530cSJonas Aaberg printk(KERN_CONT " None\n"); 1398b04c530cSJonas Aaberg } 1399e5c238c3SMattias Wallin 140062579266SRabin Vincent if (plat && plat->init) 140162579266SRabin Vincent plat->init(ab8500); 140262579266SRabin Vincent 140362579266SRabin Vincent /* Clear and mask all interrupts */ 14042ced445eSLinus Walleij for (i = 0; i < ab8500->mask_size; i++) { 14050f620837SLinus Walleij /* 14060f620837SLinus Walleij * Interrupt register 12 doesn't exist prior to AB8500 version 14070f620837SLinus Walleij * 2.0 14080f620837SLinus Walleij */ 14090f620837SLinus Walleij if (ab8500->irq_reg_offset[i] == 11 && 14100f620837SLinus Walleij is_ab8500_1p1_or_earlier(ab8500)) 141192d50a41SMattias Wallin continue; 141262579266SRabin Vincent 141347c16975SMattias Wallin get_register_interruptible(ab8500, AB8500_INTERRUPT, 14142ced445eSLinus Walleij AB8500_IT_LATCH1_REG + ab8500->irq_reg_offset[i], 141592d50a41SMattias Wallin &value); 141647c16975SMattias Wallin set_register_interruptible(ab8500, AB8500_INTERRUPT, 14172ced445eSLinus Walleij AB8500_IT_MASK1_REG + ab8500->irq_reg_offset[i], 0xff); 141862579266SRabin Vincent } 141962579266SRabin Vincent 142047c16975SMattias Wallin ret = abx500_register_ops(ab8500->dev, &ab8500_ops); 142147c16975SMattias Wallin if (ret) 14228c4203cbSLee Jones return ret; 142347c16975SMattias Wallin 14242ced445eSLinus Walleij for (i = 0; i < ab8500->mask_size; i++) 142562579266SRabin Vincent ab8500->mask[i] = ab8500->oldmask[i] = 0xff; 142662579266SRabin Vincent 142706e589efSLee Jones ret = ab8500_irq_init(ab8500, np); 142862579266SRabin Vincent if (ret) 14298c4203cbSLee Jones return ret; 143062579266SRabin Vincent 14317ccfe9b1SMichel JAOUEN /* Activate this feature only in ab9540 */ 14327ccfe9b1SMichel JAOUEN /* till tests are done on ab8500 1p2 or later*/ 143306e589efSLee Jones if (is_ab9540(ab8500)) { 14348c4203cbSLee Jones ret = devm_request_threaded_irq(&pdev->dev, ab8500->irq, NULL, 14357ccfe9b1SMichel JAOUEN ab8500_hierarchical_irq, 14367ccfe9b1SMichel JAOUEN IRQF_ONESHOT | IRQF_NO_SUSPEND, 14377ccfe9b1SMichel JAOUEN "ab8500", ab8500); 143806e589efSLee Jones } 143906e589efSLee Jones else { 14408c4203cbSLee Jones ret = devm_request_threaded_irq(&pdev->dev, ab8500->irq, NULL, 14417ccfe9b1SMichel JAOUEN ab8500_irq, 14424f079985SMattias Wallin IRQF_ONESHOT | IRQF_NO_SUSPEND, 14434f079985SMattias Wallin "ab8500", ab8500); 144462579266SRabin Vincent if (ret) 14458c4203cbSLee Jones return ret; 144662579266SRabin Vincent } 144762579266SRabin Vincent 1448d6255529SLinus Walleij ret = mfd_add_devices(ab8500->dev, 0, abx500_common_devs, 1449d6255529SLinus Walleij ARRAY_SIZE(abx500_common_devs), NULL, 145055692af5SMark Brown ab8500->irq_base, ab8500->domain); 1451d6255529SLinus Walleij if (ret) 14528c4203cbSLee Jones return ret; 1453d6255529SLinus Walleij 1454d6255529SLinus Walleij if (is_ab9540(ab8500)) 1455d6255529SLinus Walleij ret = mfd_add_devices(ab8500->dev, 0, ab9540_devs, 1456d6255529SLinus Walleij ARRAY_SIZE(ab9540_devs), NULL, 145755692af5SMark Brown ab8500->irq_base, ab8500->domain); 1458d6255529SLinus Walleij else 1459549931f9SSundar R Iyer ret = mfd_add_devices(ab8500->dev, 0, ab8500_devs, 146044f72e53SVirupax Sadashivpetimath ARRAY_SIZE(ab8500_devs), NULL, 146155692af5SMark Brown ab8500->irq_base, ab8500->domain); 14626bc4a568SLee Jones if (ret) 14638c4203cbSLee Jones return ret; 146444f72e53SVirupax Sadashivpetimath 146544f72e53SVirupax Sadashivpetimath if (is_ab9540(ab8500) || is_ab8505(ab8500)) 146644f72e53SVirupax Sadashivpetimath ret = mfd_add_devices(ab8500->dev, 0, ab9540_ab8505_devs, 146744f72e53SVirupax Sadashivpetimath ARRAY_SIZE(ab9540_ab8505_devs), NULL, 146855692af5SMark Brown ab8500->irq_base, ab8500->domain); 146962579266SRabin Vincent if (ret) 14708c4203cbSLee Jones return ret; 147162579266SRabin Vincent 14726ef9418cSRickard Andersson if (!no_bm) { 14736ef9418cSRickard Andersson /* Add battery management devices */ 14746ef9418cSRickard Andersson ret = mfd_add_devices(ab8500->dev, 0, ab8500_bm_devs, 14756ef9418cSRickard Andersson ARRAY_SIZE(ab8500_bm_devs), NULL, 147655692af5SMark Brown ab8500->irq_base, ab8500->domain); 14776ef9418cSRickard Andersson if (ret) 14786ef9418cSRickard Andersson dev_err(ab8500->dev, "error adding bm devices\n"); 14796ef9418cSRickard Andersson } 14806ef9418cSRickard Andersson 1481d6255529SLinus Walleij if (is_ab9540(ab8500)) 1482d6255529SLinus Walleij ret = sysfs_create_group(&ab8500->dev->kobj, 1483d6255529SLinus Walleij &ab9540_attr_group); 1484d6255529SLinus Walleij else 1485d6255529SLinus Walleij ret = sysfs_create_group(&ab8500->dev->kobj, 1486d6255529SLinus Walleij &ab8500_attr_group); 1487cca69b67SMattias Wallin if (ret) 1488cca69b67SMattias Wallin dev_err(ab8500->dev, "error creating sysfs entries\n"); 148906e589efSLee Jones 149062579266SRabin Vincent return ret; 149162579266SRabin Vincent } 149262579266SRabin Vincent 14934740f73fSBill Pemberton static int ab8500_remove(struct platform_device *pdev) 149462579266SRabin Vincent { 1495d28f1db8SLee Jones struct ab8500 *ab8500 = platform_get_drvdata(pdev); 1496d28f1db8SLee Jones 1497d6255529SLinus Walleij if (is_ab9540(ab8500)) 1498d6255529SLinus Walleij sysfs_remove_group(&ab8500->dev->kobj, &ab9540_attr_group); 1499d6255529SLinus Walleij else 1500cca69b67SMattias Wallin sysfs_remove_group(&ab8500->dev->kobj, &ab8500_attr_group); 150106e589efSLee Jones 150262579266SRabin Vincent mfd_remove_devices(ab8500->dev); 150362579266SRabin Vincent 150462579266SRabin Vincent return 0; 150562579266SRabin Vincent } 150662579266SRabin Vincent 1507d28f1db8SLee Jones static const struct platform_device_id ab8500_id[] = { 1508d28f1db8SLee Jones { "ab8500-core", AB8500_VERSION_AB8500 }, 1509d28f1db8SLee Jones { "ab8505-i2c", AB8500_VERSION_AB8505 }, 1510d28f1db8SLee Jones { "ab9540-i2c", AB8500_VERSION_AB9540 }, 1511d28f1db8SLee Jones { "ab8540-i2c", AB8500_VERSION_AB8540 }, 1512d28f1db8SLee Jones { } 1513d28f1db8SLee Jones }; 1514d28f1db8SLee Jones 1515d28f1db8SLee Jones static struct platform_driver ab8500_core_driver = { 1516d28f1db8SLee Jones .driver = { 1517d28f1db8SLee Jones .name = "ab8500-core", 1518d28f1db8SLee Jones .owner = THIS_MODULE, 1519d28f1db8SLee Jones }, 1520d28f1db8SLee Jones .probe = ab8500_probe, 152184449216SBill Pemberton .remove = ab8500_remove, 1522d28f1db8SLee Jones .id_table = ab8500_id, 1523d28f1db8SLee Jones }; 1524d28f1db8SLee Jones 1525d28f1db8SLee Jones static int __init ab8500_core_init(void) 1526d28f1db8SLee Jones { 1527d28f1db8SLee Jones return platform_driver_register(&ab8500_core_driver); 1528d28f1db8SLee Jones } 1529d28f1db8SLee Jones 1530d28f1db8SLee Jones static void __exit ab8500_core_exit(void) 1531d28f1db8SLee Jones { 1532d28f1db8SLee Jones platform_driver_unregister(&ab8500_core_driver); 1533d28f1db8SLee Jones } 1534ba7cbc3eSLee Jones core_initcall(ab8500_core_init); 1535d28f1db8SLee Jones module_exit(ab8500_core_exit); 1536d28f1db8SLee Jones 1537adceed62SMattias Wallin MODULE_AUTHOR("Mattias Wallin, Srinidhi Kasagar, Rabin Vincent"); 153862579266SRabin Vincent MODULE_DESCRIPTION("AB8500 MFD core"); 153962579266SRabin Vincent MODULE_LICENSE("GPL v2"); 1540