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 98*a29264b6SLee Jones #define AB8500_IT_MASK25_REG 0x58 9962579266SRabin Vincent 1007ccfe9b1SMichel JAOUEN /* 1017ccfe9b1SMichel JAOUEN * latch hierarchy registers 1027ccfe9b1SMichel JAOUEN */ 1037ccfe9b1SMichel JAOUEN #define AB8500_IT_LATCHHIER1_REG 0x60 1047ccfe9b1SMichel JAOUEN #define AB8500_IT_LATCHHIER2_REG 0x61 1057ccfe9b1SMichel JAOUEN #define AB8500_IT_LATCHHIER3_REG 0x62 1067ccfe9b1SMichel JAOUEN 1077ccfe9b1SMichel JAOUEN #define AB8500_IT_LATCHHIER_NUM 3 1087ccfe9b1SMichel JAOUEN 10947c16975SMattias Wallin #define AB8500_REV_REG 0x80 1100f620837SLinus Walleij #define AB8500_IC_NAME_REG 0x82 111e5c238c3SMattias Wallin #define AB8500_SWITCH_OFF_STATUS 0x00 11262579266SRabin Vincent 113b4a31037SAndrew Lynn #define AB8500_TURN_ON_STATUS 0x00 114b4a31037SAndrew Lynn 115f04a9d8aSRajkumar Kasirajan #define AB8500_CH_USBCH_STAT1_REG 0x02 116f04a9d8aSRajkumar Kasirajan #define VBUS_DET_DBNC100 0x02 117f04a9d8aSRajkumar Kasirajan #define VBUS_DET_DBNC1 0x01 118f04a9d8aSRajkumar Kasirajan 119f04a9d8aSRajkumar Kasirajan static DEFINE_SPINLOCK(on_stat_lock); 120f04a9d8aSRajkumar Kasirajan static u8 turn_on_stat_mask = 0xFF; 121f04a9d8aSRajkumar Kasirajan static u8 turn_on_stat_set; 1226ef9418cSRickard Andersson static bool no_bm; /* No battery management */ 1236ef9418cSRickard Andersson module_param(no_bm, bool, S_IRUGO); 1246ef9418cSRickard Andersson 125d6255529SLinus Walleij #define AB9540_MODEM_CTRL2_REG 0x23 126d6255529SLinus Walleij #define AB9540_MODEM_CTRL2_SWDBBRSTN_BIT BIT(2) 127d6255529SLinus Walleij 12862579266SRabin Vincent /* 12962579266SRabin Vincent * Map interrupt numbers to the LATCH and MASK register offsets, Interrupt 1302ced445eSLinus Walleij * numbers are indexed into this array with (num / 8). The interupts are 1312ced445eSLinus Walleij * defined in linux/mfd/ab8500.h 13262579266SRabin Vincent * 13362579266SRabin Vincent * This is one off from the register names, i.e. AB8500_IT_MASK1_REG is at 13462579266SRabin Vincent * offset 0. 13562579266SRabin Vincent */ 1362ced445eSLinus Walleij /* AB8500 support */ 13762579266SRabin Vincent static const int ab8500_irq_regoffset[AB8500_NUM_IRQ_REGS] = { 13892d50a41SMattias Wallin 0, 1, 2, 3, 4, 6, 7, 8, 9, 11, 18, 19, 20, 21, 13962579266SRabin Vincent }; 14062579266SRabin Vincent 141*a29264b6SLee Jones /* AB9540 / AB8505 support */ 142d6255529SLinus Walleij static const int ab9540_irq_regoffset[AB9540_NUM_IRQ_REGS] = { 143*a29264b6SLee Jones 0, 1, 2, 3, 4, 6, 7, 8, 9, 11, 18, 19, 20, 21, 12, 13, 24, 5, 22, 23 144d6255529SLinus Walleij }; 145d6255529SLinus Walleij 1460f620837SLinus Walleij static const char ab8500_version_str[][7] = { 1470f620837SLinus Walleij [AB8500_VERSION_AB8500] = "AB8500", 1480f620837SLinus Walleij [AB8500_VERSION_AB8505] = "AB8505", 1490f620837SLinus Walleij [AB8500_VERSION_AB9540] = "AB9540", 1500f620837SLinus Walleij [AB8500_VERSION_AB8540] = "AB8540", 1510f620837SLinus Walleij }; 1520f620837SLinus Walleij 153822672a7SLee Jones static int ab8500_prcmu_write(struct ab8500 *ab8500, u16 addr, u8 data) 154d28f1db8SLee Jones { 155d28f1db8SLee Jones int ret; 156d28f1db8SLee Jones 157d28f1db8SLee Jones ret = prcmu_abb_write((u8)(addr >> 8), (u8)(addr & 0xFF), &data, 1); 158d28f1db8SLee Jones if (ret < 0) 159d28f1db8SLee Jones dev_err(ab8500->dev, "prcmu i2c error %d\n", ret); 160d28f1db8SLee Jones return ret; 161d28f1db8SLee Jones } 162d28f1db8SLee Jones 163822672a7SLee Jones static int ab8500_prcmu_write_masked(struct ab8500 *ab8500, u16 addr, u8 mask, 164d28f1db8SLee Jones u8 data) 165d28f1db8SLee Jones { 166d28f1db8SLee Jones int ret; 167d28f1db8SLee Jones 168d28f1db8SLee Jones ret = prcmu_abb_write_masked((u8)(addr >> 8), (u8)(addr & 0xFF), &data, 169d28f1db8SLee Jones &mask, 1); 170d28f1db8SLee Jones if (ret < 0) 171d28f1db8SLee Jones dev_err(ab8500->dev, "prcmu i2c error %d\n", ret); 172d28f1db8SLee Jones return ret; 173d28f1db8SLee Jones } 174d28f1db8SLee Jones 175822672a7SLee Jones static int ab8500_prcmu_read(struct ab8500 *ab8500, u16 addr) 176d28f1db8SLee Jones { 177d28f1db8SLee Jones int ret; 178d28f1db8SLee Jones u8 data; 179d28f1db8SLee Jones 180d28f1db8SLee Jones ret = prcmu_abb_read((u8)(addr >> 8), (u8)(addr & 0xFF), &data, 1); 181d28f1db8SLee Jones if (ret < 0) { 182d28f1db8SLee Jones dev_err(ab8500->dev, "prcmu i2c error %d\n", ret); 183d28f1db8SLee Jones return ret; 184d28f1db8SLee Jones } 185d28f1db8SLee Jones return (int)data; 186d28f1db8SLee Jones } 187d28f1db8SLee Jones 18847c16975SMattias Wallin static int ab8500_get_chip_id(struct device *dev) 18947c16975SMattias Wallin { 1906bce7bf1SMattias Wallin struct ab8500 *ab8500; 1916bce7bf1SMattias Wallin 1926bce7bf1SMattias Wallin if (!dev) 1936bce7bf1SMattias Wallin return -EINVAL; 1946bce7bf1SMattias Wallin ab8500 = dev_get_drvdata(dev->parent); 1956bce7bf1SMattias Wallin return ab8500 ? (int)ab8500->chip_id : -EINVAL; 19647c16975SMattias Wallin } 19747c16975SMattias Wallin 19847c16975SMattias Wallin static int set_register_interruptible(struct ab8500 *ab8500, u8 bank, 19947c16975SMattias Wallin u8 reg, u8 data) 20062579266SRabin Vincent { 20162579266SRabin Vincent int ret; 20247c16975SMattias Wallin /* 20347c16975SMattias Wallin * Put the u8 bank and u8 register together into a an u16. 20447c16975SMattias Wallin * The bank on higher 8 bits and register in lower 8 bits. 20547c16975SMattias Wallin * */ 20647c16975SMattias Wallin u16 addr = ((u16)bank) << 8 | reg; 20762579266SRabin Vincent 20862579266SRabin Vincent dev_vdbg(ab8500->dev, "wr: addr %#x <= %#x\n", addr, data); 20962579266SRabin Vincent 210392cbd1eSRabin Vincent mutex_lock(&ab8500->lock); 21147c16975SMattias Wallin 21247c16975SMattias Wallin ret = ab8500->write(ab8500, addr, data); 21347c16975SMattias Wallin if (ret < 0) 21447c16975SMattias Wallin dev_err(ab8500->dev, "failed to write reg %#x: %d\n", 21547c16975SMattias Wallin addr, ret); 21647c16975SMattias Wallin mutex_unlock(&ab8500->lock); 21747c16975SMattias Wallin 21847c16975SMattias Wallin return ret; 21947c16975SMattias Wallin } 22047c16975SMattias Wallin 22147c16975SMattias Wallin static int ab8500_set_register(struct device *dev, u8 bank, 22247c16975SMattias Wallin u8 reg, u8 value) 22347c16975SMattias Wallin { 224112a80d2SJonas Aaberg int ret; 22547c16975SMattias Wallin struct ab8500 *ab8500 = dev_get_drvdata(dev->parent); 22647c16975SMattias Wallin 227112a80d2SJonas Aaberg atomic_inc(&ab8500->transfer_ongoing); 228112a80d2SJonas Aaberg ret = set_register_interruptible(ab8500, bank, reg, value); 229112a80d2SJonas Aaberg atomic_dec(&ab8500->transfer_ongoing); 230112a80d2SJonas Aaberg return ret; 23147c16975SMattias Wallin } 23247c16975SMattias Wallin 23347c16975SMattias Wallin static int get_register_interruptible(struct ab8500 *ab8500, u8 bank, 23447c16975SMattias Wallin u8 reg, u8 *value) 23547c16975SMattias Wallin { 23647c16975SMattias Wallin int ret; 23747c16975SMattias Wallin /* put the u8 bank and u8 reg together into a an u16. 23847c16975SMattias Wallin * bank on higher 8 bits and reg in lower */ 23947c16975SMattias Wallin u16 addr = ((u16)bank) << 8 | reg; 24047c16975SMattias Wallin 241392cbd1eSRabin Vincent mutex_lock(&ab8500->lock); 24247c16975SMattias Wallin 24347c16975SMattias Wallin ret = ab8500->read(ab8500, addr); 24447c16975SMattias Wallin if (ret < 0) 24547c16975SMattias Wallin dev_err(ab8500->dev, "failed to read reg %#x: %d\n", 24647c16975SMattias Wallin addr, ret); 24747c16975SMattias Wallin else 24847c16975SMattias Wallin *value = ret; 24947c16975SMattias Wallin 25047c16975SMattias Wallin mutex_unlock(&ab8500->lock); 25147c16975SMattias Wallin dev_vdbg(ab8500->dev, "rd: addr %#x => data %#x\n", addr, ret); 25247c16975SMattias Wallin 25347c16975SMattias Wallin return ret; 25447c16975SMattias Wallin } 25547c16975SMattias Wallin 25647c16975SMattias Wallin static int ab8500_get_register(struct device *dev, u8 bank, 25747c16975SMattias Wallin u8 reg, u8 *value) 25847c16975SMattias Wallin { 259112a80d2SJonas Aaberg int ret; 26047c16975SMattias Wallin struct ab8500 *ab8500 = dev_get_drvdata(dev->parent); 26147c16975SMattias Wallin 262112a80d2SJonas Aaberg atomic_inc(&ab8500->transfer_ongoing); 263112a80d2SJonas Aaberg ret = get_register_interruptible(ab8500, bank, reg, value); 264112a80d2SJonas Aaberg atomic_dec(&ab8500->transfer_ongoing); 265112a80d2SJonas Aaberg return ret; 26647c16975SMattias Wallin } 26747c16975SMattias Wallin 26847c16975SMattias Wallin static int mask_and_set_register_interruptible(struct ab8500 *ab8500, u8 bank, 26947c16975SMattias Wallin u8 reg, u8 bitmask, u8 bitvalues) 27047c16975SMattias Wallin { 27147c16975SMattias Wallin int ret; 27247c16975SMattias Wallin /* put the u8 bank and u8 reg together into a an u16. 27347c16975SMattias Wallin * bank on higher 8 bits and reg in lower */ 27447c16975SMattias Wallin u16 addr = ((u16)bank) << 8 | reg; 27547c16975SMattias Wallin 276392cbd1eSRabin Vincent mutex_lock(&ab8500->lock); 27747c16975SMattias Wallin 278bc628fd1SMattias Nilsson if (ab8500->write_masked == NULL) { 279bc628fd1SMattias Nilsson u8 data; 280bc628fd1SMattias Nilsson 28147c16975SMattias Wallin ret = ab8500->read(ab8500, addr); 28247c16975SMattias Wallin if (ret < 0) { 28347c16975SMattias Wallin dev_err(ab8500->dev, "failed to read reg %#x: %d\n", 28447c16975SMattias Wallin addr, ret); 28547c16975SMattias Wallin goto out; 28647c16975SMattias Wallin } 28747c16975SMattias Wallin 28847c16975SMattias Wallin data = (u8)ret; 28947c16975SMattias Wallin data = (~bitmask & data) | (bitmask & bitvalues); 29047c16975SMattias Wallin 29162579266SRabin Vincent ret = ab8500->write(ab8500, addr, data); 29262579266SRabin Vincent if (ret < 0) 29362579266SRabin Vincent dev_err(ab8500->dev, "failed to write reg %#x: %d\n", 29462579266SRabin Vincent addr, ret); 29562579266SRabin Vincent 296bc628fd1SMattias Nilsson dev_vdbg(ab8500->dev, "mask: addr %#x => data %#x\n", addr, 297bc628fd1SMattias Nilsson data); 298bc628fd1SMattias Nilsson goto out; 299bc628fd1SMattias Nilsson } 300bc628fd1SMattias Nilsson ret = ab8500->write_masked(ab8500, addr, bitmask, bitvalues); 301bc628fd1SMattias Nilsson if (ret < 0) 302bc628fd1SMattias Nilsson dev_err(ab8500->dev, "failed to modify reg %#x: %d\n", addr, 303bc628fd1SMattias Nilsson ret); 30462579266SRabin Vincent out: 30562579266SRabin Vincent mutex_unlock(&ab8500->lock); 30662579266SRabin Vincent return ret; 30762579266SRabin Vincent } 30847c16975SMattias Wallin 30947c16975SMattias Wallin static int ab8500_mask_and_set_register(struct device *dev, 31047c16975SMattias Wallin u8 bank, u8 reg, u8 bitmask, u8 bitvalues) 31147c16975SMattias Wallin { 312112a80d2SJonas Aaberg int ret; 31347c16975SMattias Wallin struct ab8500 *ab8500 = dev_get_drvdata(dev->parent); 31447c16975SMattias Wallin 315112a80d2SJonas Aaberg atomic_inc(&ab8500->transfer_ongoing); 316112a80d2SJonas Aaberg ret= mask_and_set_register_interruptible(ab8500, bank, reg, 31747c16975SMattias Wallin bitmask, bitvalues); 318112a80d2SJonas Aaberg atomic_dec(&ab8500->transfer_ongoing); 319112a80d2SJonas Aaberg return ret; 32047c16975SMattias Wallin } 32147c16975SMattias Wallin 32247c16975SMattias Wallin static struct abx500_ops ab8500_ops = { 32347c16975SMattias Wallin .get_chip_id = ab8500_get_chip_id, 32447c16975SMattias Wallin .get_register = ab8500_get_register, 32547c16975SMattias Wallin .set_register = ab8500_set_register, 32647c16975SMattias Wallin .get_register_page = NULL, 32747c16975SMattias Wallin .set_register_page = NULL, 32847c16975SMattias Wallin .mask_and_set_register = ab8500_mask_and_set_register, 32947c16975SMattias Wallin .event_registers_startup_state_get = NULL, 33047c16975SMattias Wallin .startup_irq_enabled = NULL, 3311d843a6cSMian Yousaf Kaukab .dump_all_banks = ab8500_dump_all_banks, 33247c16975SMattias Wallin }; 33362579266SRabin Vincent 3349505a0a0SMark Brown static void ab8500_irq_lock(struct irq_data *data) 33562579266SRabin Vincent { 3369505a0a0SMark Brown struct ab8500 *ab8500 = irq_data_get_irq_chip_data(data); 33762579266SRabin Vincent 33862579266SRabin Vincent mutex_lock(&ab8500->irq_lock); 339112a80d2SJonas Aaberg atomic_inc(&ab8500->transfer_ongoing); 34062579266SRabin Vincent } 34162579266SRabin Vincent 3429505a0a0SMark Brown static void ab8500_irq_sync_unlock(struct irq_data *data) 34362579266SRabin Vincent { 3449505a0a0SMark Brown struct ab8500 *ab8500 = irq_data_get_irq_chip_data(data); 34562579266SRabin Vincent int i; 34662579266SRabin Vincent 3472ced445eSLinus Walleij for (i = 0; i < ab8500->mask_size; i++) { 34862579266SRabin Vincent u8 old = ab8500->oldmask[i]; 34962579266SRabin Vincent u8 new = ab8500->mask[i]; 35062579266SRabin Vincent int reg; 35162579266SRabin Vincent 35262579266SRabin Vincent if (new == old) 35362579266SRabin Vincent continue; 35462579266SRabin Vincent 3550f620837SLinus Walleij /* 3560f620837SLinus Walleij * Interrupt register 12 doesn't exist prior to AB8500 version 3570f620837SLinus Walleij * 2.0 3580f620837SLinus Walleij */ 3590f620837SLinus Walleij if (ab8500->irq_reg_offset[i] == 11 && 3600f620837SLinus Walleij is_ab8500_1p1_or_earlier(ab8500)) 36192d50a41SMattias Wallin continue; 36292d50a41SMattias Wallin 36362579266SRabin Vincent ab8500->oldmask[i] = new; 36462579266SRabin Vincent 3652ced445eSLinus Walleij reg = AB8500_IT_MASK1_REG + ab8500->irq_reg_offset[i]; 36647c16975SMattias Wallin set_register_interruptible(ab8500, AB8500_INTERRUPT, reg, new); 36762579266SRabin Vincent } 368112a80d2SJonas Aaberg atomic_dec(&ab8500->transfer_ongoing); 36962579266SRabin Vincent mutex_unlock(&ab8500->irq_lock); 37062579266SRabin Vincent } 37162579266SRabin Vincent 3729505a0a0SMark Brown static void ab8500_irq_mask(struct irq_data *data) 37362579266SRabin Vincent { 3749505a0a0SMark Brown struct ab8500 *ab8500 = irq_data_get_irq_chip_data(data); 37506e589efSLee Jones int offset = data->hwirq; 37662579266SRabin Vincent int index = offset / 8; 37762579266SRabin Vincent int mask = 1 << (offset % 8); 37862579266SRabin Vincent 37962579266SRabin Vincent ab8500->mask[index] |= mask; 3809c677b9bSLee Jones 3819c677b9bSLee Jones /* The AB8500 GPIOs have two interrupts each (rising & falling). */ 3829c677b9bSLee Jones if (offset >= AB8500_INT_GPIO6R && offset <= AB8500_INT_GPIO41R) 3839c677b9bSLee Jones ab8500->mask[index + 2] |= mask; 3849c677b9bSLee Jones if (offset >= AB9540_INT_GPIO50R && offset <= AB9540_INT_GPIO54R) 3859c677b9bSLee Jones ab8500->mask[index + 1] |= mask; 3869c677b9bSLee Jones if (offset == AB8540_INT_GPIO43R || offset == AB8540_INT_GPIO44R) 387e2ddf46aSLinus Walleij /* Here the falling IRQ is one bit lower */ 388e2ddf46aSLinus Walleij ab8500->mask[index] |= (mask << 1); 38962579266SRabin Vincent } 39062579266SRabin Vincent 3919505a0a0SMark Brown static void ab8500_irq_unmask(struct irq_data *data) 39262579266SRabin Vincent { 3939505a0a0SMark Brown struct ab8500 *ab8500 = irq_data_get_irq_chip_data(data); 3949c677b9bSLee Jones unsigned int type = irqd_get_trigger_type(data); 39506e589efSLee Jones int offset = data->hwirq; 39662579266SRabin Vincent int index = offset / 8; 39762579266SRabin Vincent int mask = 1 << (offset % 8); 39862579266SRabin Vincent 3999c677b9bSLee Jones if (type & IRQ_TYPE_EDGE_RISING) 40062579266SRabin Vincent ab8500->mask[index] &= ~mask; 4019c677b9bSLee Jones 4029c677b9bSLee Jones /* The AB8500 GPIOs have two interrupts each (rising & falling). */ 4039c677b9bSLee Jones if (type & IRQ_TYPE_EDGE_FALLING) { 4049c677b9bSLee Jones if (offset >= AB8500_INT_GPIO6R && offset <= AB8500_INT_GPIO41R) 4059c677b9bSLee Jones ab8500->mask[index + 2] &= ~mask; 4069c677b9bSLee Jones else if (offset >= AB9540_INT_GPIO50R && offset <= AB9540_INT_GPIO54R) 4079c677b9bSLee Jones ab8500->mask[index + 1] &= ~mask; 4089c677b9bSLee Jones else if (offset == AB8540_INT_GPIO43R || offset == AB8540_INT_GPIO44R) 409e2ddf46aSLinus Walleij /* Here the falling IRQ is one bit lower */ 410e2ddf46aSLinus Walleij ab8500->mask[index] &= ~(mask << 1); 4119c677b9bSLee Jones else 4129c677b9bSLee Jones ab8500->mask[index] &= ~mask; 413e2ddf46aSLinus Walleij } else { 4149c677b9bSLee Jones /* Satisfies the case where type is not set. */ 41562579266SRabin Vincent ab8500->mask[index] &= ~mask; 41662579266SRabin Vincent } 417e2ddf46aSLinus Walleij } 41862579266SRabin Vincent 41940f6e5a2SLee Jones static int ab8500_irq_set_type(struct irq_data *data, unsigned int type) 42040f6e5a2SLee Jones { 42140f6e5a2SLee Jones return 0; 42262579266SRabin Vincent } 42362579266SRabin Vincent 42462579266SRabin Vincent static struct irq_chip ab8500_irq_chip = { 42562579266SRabin Vincent .name = "ab8500", 4269505a0a0SMark Brown .irq_bus_lock = ab8500_irq_lock, 4279505a0a0SMark Brown .irq_bus_sync_unlock = ab8500_irq_sync_unlock, 4289505a0a0SMark Brown .irq_mask = ab8500_irq_mask, 429e6f9306eSVirupax Sadashivpetimath .irq_disable = ab8500_irq_mask, 4309505a0a0SMark Brown .irq_unmask = ab8500_irq_unmask, 43140f6e5a2SLee Jones .irq_set_type = ab8500_irq_set_type, 43262579266SRabin Vincent }; 43362579266SRabin Vincent 4347ccfe9b1SMichel JAOUEN static int ab8500_handle_hierarchical_line(struct ab8500 *ab8500, 4357ccfe9b1SMichel JAOUEN int latch_offset, u8 latch_val) 4367ccfe9b1SMichel JAOUEN { 4377ccfe9b1SMichel JAOUEN int int_bit = __ffs(latch_val); 4387ccfe9b1SMichel JAOUEN int line, i; 4397ccfe9b1SMichel JAOUEN 4407ccfe9b1SMichel JAOUEN do { 4417ccfe9b1SMichel JAOUEN int_bit = __ffs(latch_val); 4427ccfe9b1SMichel JAOUEN 4437ccfe9b1SMichel JAOUEN for (i = 0; i < ab8500->mask_size; i++) 4447ccfe9b1SMichel JAOUEN if (ab8500->irq_reg_offset[i] == latch_offset) 4457ccfe9b1SMichel JAOUEN break; 4467ccfe9b1SMichel JAOUEN 4477ccfe9b1SMichel JAOUEN if (i >= ab8500->mask_size) { 4487ccfe9b1SMichel JAOUEN dev_err(ab8500->dev, "Register offset 0x%2x not declared\n", 4497ccfe9b1SMichel JAOUEN latch_offset); 4507ccfe9b1SMichel JAOUEN return -ENXIO; 4517ccfe9b1SMichel JAOUEN } 4527ccfe9b1SMichel JAOUEN 4537ccfe9b1SMichel JAOUEN line = (i << 3) + int_bit; 4547ccfe9b1SMichel JAOUEN latch_val &= ~(1 << int_bit); 4557ccfe9b1SMichel JAOUEN 456e2ddf46aSLinus Walleij /* 457e2ddf46aSLinus Walleij * This handles the falling edge hwirqs from the GPIO 458e2ddf46aSLinus Walleij * lines. Route them back to the line registered for the 459e2ddf46aSLinus Walleij * rising IRQ, as this is merely a flag for the same IRQ 460e2ddf46aSLinus Walleij * in linux terms. 461e2ddf46aSLinus Walleij */ 462e2ddf46aSLinus Walleij if (line >= AB8500_INT_GPIO6F && line <= AB8500_INT_GPIO41F) 463e2ddf46aSLinus Walleij line -= 16; 464e2ddf46aSLinus Walleij if (line >= AB9540_INT_GPIO50F && line <= AB9540_INT_GPIO54F) 465e2ddf46aSLinus Walleij line -= 8; 466e2ddf46aSLinus Walleij if (line == AB8540_INT_GPIO43F || line == AB8540_INT_GPIO44F) 467e2ddf46aSLinus Walleij line += 1; 468e2ddf46aSLinus Walleij 4697ccfe9b1SMichel JAOUEN handle_nested_irq(ab8500->irq_base + line); 4707ccfe9b1SMichel JAOUEN } while (latch_val); 4717ccfe9b1SMichel JAOUEN 4727ccfe9b1SMichel JAOUEN return 0; 4737ccfe9b1SMichel JAOUEN } 4747ccfe9b1SMichel JAOUEN 4757ccfe9b1SMichel JAOUEN static int ab8500_handle_hierarchical_latch(struct ab8500 *ab8500, 4767ccfe9b1SMichel JAOUEN int hier_offset, u8 hier_val) 4777ccfe9b1SMichel JAOUEN { 4787ccfe9b1SMichel JAOUEN int latch_bit, status; 4797ccfe9b1SMichel JAOUEN u8 latch_offset, latch_val; 4807ccfe9b1SMichel JAOUEN 4817ccfe9b1SMichel JAOUEN do { 4827ccfe9b1SMichel JAOUEN latch_bit = __ffs(hier_val); 4837ccfe9b1SMichel JAOUEN latch_offset = (hier_offset << 3) + latch_bit; 4847ccfe9b1SMichel JAOUEN 4857ccfe9b1SMichel JAOUEN /* Fix inconsistent ITFromLatch25 bit mapping... */ 4867ccfe9b1SMichel JAOUEN if (unlikely(latch_offset == 17)) 4877ccfe9b1SMichel JAOUEN latch_offset = 24; 4887ccfe9b1SMichel JAOUEN 4897ccfe9b1SMichel JAOUEN status = get_register_interruptible(ab8500, 4907ccfe9b1SMichel JAOUEN AB8500_INTERRUPT, 4917ccfe9b1SMichel JAOUEN AB8500_IT_LATCH1_REG + latch_offset, 4927ccfe9b1SMichel JAOUEN &latch_val); 4937ccfe9b1SMichel JAOUEN if (status < 0 || latch_val == 0) 4947ccfe9b1SMichel JAOUEN goto discard; 4957ccfe9b1SMichel JAOUEN 4967ccfe9b1SMichel JAOUEN status = ab8500_handle_hierarchical_line(ab8500, 4977ccfe9b1SMichel JAOUEN latch_offset, latch_val); 4987ccfe9b1SMichel JAOUEN if (status < 0) 4997ccfe9b1SMichel JAOUEN return status; 5007ccfe9b1SMichel JAOUEN discard: 5017ccfe9b1SMichel JAOUEN hier_val &= ~(1 << latch_bit); 5027ccfe9b1SMichel JAOUEN } while (hier_val); 5037ccfe9b1SMichel JAOUEN 5047ccfe9b1SMichel JAOUEN return 0; 5057ccfe9b1SMichel JAOUEN } 5067ccfe9b1SMichel JAOUEN 5077ccfe9b1SMichel JAOUEN static irqreturn_t ab8500_hierarchical_irq(int irq, void *dev) 5087ccfe9b1SMichel JAOUEN { 5097ccfe9b1SMichel JAOUEN struct ab8500 *ab8500 = dev; 5107ccfe9b1SMichel JAOUEN u8 i; 5117ccfe9b1SMichel JAOUEN 5127ccfe9b1SMichel JAOUEN dev_vdbg(ab8500->dev, "interrupt\n"); 5137ccfe9b1SMichel JAOUEN 5147ccfe9b1SMichel JAOUEN /* Hierarchical interrupt version */ 5157ccfe9b1SMichel JAOUEN for (i = 0; i < AB8500_IT_LATCHHIER_NUM; i++) { 5167ccfe9b1SMichel JAOUEN int status; 5177ccfe9b1SMichel JAOUEN u8 hier_val; 5187ccfe9b1SMichel JAOUEN 5197ccfe9b1SMichel JAOUEN status = get_register_interruptible(ab8500, AB8500_INTERRUPT, 5207ccfe9b1SMichel JAOUEN AB8500_IT_LATCHHIER1_REG + i, &hier_val); 5217ccfe9b1SMichel JAOUEN if (status < 0 || hier_val == 0) 5227ccfe9b1SMichel JAOUEN continue; 5237ccfe9b1SMichel JAOUEN 5247ccfe9b1SMichel JAOUEN status = ab8500_handle_hierarchical_latch(ab8500, i, hier_val); 5257ccfe9b1SMichel JAOUEN if (status < 0) 5267ccfe9b1SMichel JAOUEN break; 5277ccfe9b1SMichel JAOUEN } 5287ccfe9b1SMichel JAOUEN return IRQ_HANDLED; 5297ccfe9b1SMichel JAOUEN } 5307ccfe9b1SMichel JAOUEN 53180633f05SLee Jones /** 53280633f05SLee Jones * ab8500_irq_get_virq(): Map an interrupt on a chip to a virtual IRQ 53380633f05SLee Jones * 53480633f05SLee Jones * @ab8500: ab8500_irq controller to operate on. 53580633f05SLee Jones * @irq: index of the interrupt requested in the chip IRQs 53680633f05SLee Jones * 53780633f05SLee Jones * Useful for drivers to request their own IRQs. 53880633f05SLee Jones */ 53980633f05SLee Jones static int ab8500_irq_get_virq(struct ab8500 *ab8500, int irq) 54080633f05SLee Jones { 54180633f05SLee Jones if (!ab8500) 54280633f05SLee Jones return -EINVAL; 54380633f05SLee Jones 54480633f05SLee Jones return irq_create_mapping(ab8500->domain, irq); 54580633f05SLee Jones } 54680633f05SLee Jones 54762579266SRabin Vincent static irqreturn_t ab8500_irq(int irq, void *dev) 54862579266SRabin Vincent { 54962579266SRabin Vincent struct ab8500 *ab8500 = dev; 55062579266SRabin Vincent int i; 55162579266SRabin Vincent 55262579266SRabin Vincent dev_vdbg(ab8500->dev, "interrupt\n"); 55362579266SRabin Vincent 554112a80d2SJonas Aaberg atomic_inc(&ab8500->transfer_ongoing); 555112a80d2SJonas Aaberg 5562ced445eSLinus Walleij for (i = 0; i < ab8500->mask_size; i++) { 5572ced445eSLinus Walleij int regoffset = ab8500->irq_reg_offset[i]; 55862579266SRabin Vincent int status; 55947c16975SMattias Wallin u8 value; 56062579266SRabin Vincent 5610f620837SLinus Walleij /* 5620f620837SLinus Walleij * Interrupt register 12 doesn't exist prior to AB8500 version 5630f620837SLinus Walleij * 2.0 5640f620837SLinus Walleij */ 5650f620837SLinus Walleij if (regoffset == 11 && is_ab8500_1p1_or_earlier(ab8500)) 56692d50a41SMattias Wallin continue; 56792d50a41SMattias Wallin 56847c16975SMattias Wallin status = get_register_interruptible(ab8500, AB8500_INTERRUPT, 56947c16975SMattias Wallin AB8500_IT_LATCH1_REG + regoffset, &value); 57047c16975SMattias Wallin if (status < 0 || value == 0) 57162579266SRabin Vincent continue; 57262579266SRabin Vincent 57362579266SRabin Vincent do { 57488aec4f7SMattias Wallin int bit = __ffs(value); 57562579266SRabin Vincent int line = i * 8 + bit; 5760a37fc56SLee Jones int virq = ab8500_irq_get_virq(ab8500, line); 57762579266SRabin Vincent 5780a37fc56SLee Jones handle_nested_irq(virq); 5798f0eb43bSBengt Jonsson ab8500_debug_register_interrupt(line); 58047c16975SMattias Wallin value &= ~(1 << bit); 581112a80d2SJonas Aaberg 58247c16975SMattias Wallin } while (value); 58362579266SRabin Vincent } 584112a80d2SJonas Aaberg atomic_dec(&ab8500->transfer_ongoing); 58562579266SRabin Vincent return IRQ_HANDLED; 58662579266SRabin Vincent } 58762579266SRabin Vincent 58806e589efSLee Jones static int ab8500_irq_map(struct irq_domain *d, unsigned int virq, 58906e589efSLee Jones irq_hw_number_t hwirq) 59006e589efSLee Jones { 59106e589efSLee Jones struct ab8500 *ab8500 = d->host_data; 59206e589efSLee Jones 59306e589efSLee Jones if (!ab8500) 59406e589efSLee Jones return -EINVAL; 59506e589efSLee Jones 59606e589efSLee Jones irq_set_chip_data(virq, ab8500); 59706e589efSLee Jones irq_set_chip_and_handler(virq, &ab8500_irq_chip, 59806e589efSLee Jones handle_simple_irq); 59906e589efSLee Jones irq_set_nested_thread(virq, 1); 60006e589efSLee Jones #ifdef CONFIG_ARM 60106e589efSLee Jones set_irq_flags(virq, IRQF_VALID); 60206e589efSLee Jones #else 60306e589efSLee Jones irq_set_noprobe(virq); 60406e589efSLee Jones #endif 60562579266SRabin Vincent 60662579266SRabin Vincent return 0; 60762579266SRabin Vincent } 60862579266SRabin Vincent 60906e589efSLee Jones static struct irq_domain_ops ab8500_irq_ops = { 61006e589efSLee Jones .map = ab8500_irq_map, 61106e589efSLee Jones .xlate = irq_domain_xlate_twocell, 61206e589efSLee Jones }; 61306e589efSLee Jones 61406e589efSLee Jones static int ab8500_irq_init(struct ab8500 *ab8500, struct device_node *np) 61562579266SRabin Vincent { 6162ced445eSLinus Walleij int num_irqs; 61762579266SRabin Vincent 618d6255529SLinus Walleij if (is_ab9540(ab8500)) 619d6255529SLinus Walleij num_irqs = AB9540_NR_IRQS; 620a982362cSBengt Jonsson else if (is_ab8505(ab8500)) 621a982362cSBengt Jonsson num_irqs = AB8505_NR_IRQS; 622d6255529SLinus Walleij else 6232ced445eSLinus Walleij num_irqs = AB8500_NR_IRQS; 6242ced445eSLinus Walleij 625f1d11f39SLinus Walleij /* If ->irq_base is zero this will give a linear mapping */ 626f1d11f39SLinus Walleij ab8500->domain = irq_domain_add_simple(NULL, 627f1d11f39SLinus Walleij num_irqs, ab8500->irq_base, 628f1d11f39SLinus Walleij &ab8500_irq_ops, ab8500); 62906e589efSLee Jones 63006e589efSLee Jones if (!ab8500->domain) { 63106e589efSLee Jones dev_err(ab8500->dev, "Failed to create irqdomain\n"); 63206e589efSLee Jones return -ENOSYS; 63306e589efSLee Jones } 63406e589efSLee Jones 63506e589efSLee Jones return 0; 63662579266SRabin Vincent } 63762579266SRabin Vincent 638112a80d2SJonas Aaberg int ab8500_suspend(struct ab8500 *ab8500) 639112a80d2SJonas Aaberg { 640112a80d2SJonas Aaberg if (atomic_read(&ab8500->transfer_ongoing)) 641112a80d2SJonas Aaberg return -EINVAL; 642112a80d2SJonas Aaberg else 643112a80d2SJonas Aaberg return 0; 644112a80d2SJonas Aaberg } 645112a80d2SJonas Aaberg 646a9e9ce4cSBill Pemberton static struct resource ab8500_gpadc_resources[] = { 64762579266SRabin Vincent { 64862579266SRabin Vincent .name = "HW_CONV_END", 64962579266SRabin Vincent .start = AB8500_INT_GP_HW_ADC_CONV_END, 65062579266SRabin Vincent .end = AB8500_INT_GP_HW_ADC_CONV_END, 65162579266SRabin Vincent .flags = IORESOURCE_IRQ, 65262579266SRabin Vincent }, 65362579266SRabin Vincent { 65462579266SRabin Vincent .name = "SW_CONV_END", 65562579266SRabin Vincent .start = AB8500_INT_GP_SW_ADC_CONV_END, 65662579266SRabin Vincent .end = AB8500_INT_GP_SW_ADC_CONV_END, 65762579266SRabin Vincent .flags = IORESOURCE_IRQ, 65862579266SRabin Vincent }, 65962579266SRabin Vincent }; 66062579266SRabin Vincent 661a9e9ce4cSBill Pemberton static struct resource ab8500_rtc_resources[] = { 66262579266SRabin Vincent { 66362579266SRabin Vincent .name = "60S", 66462579266SRabin Vincent .start = AB8500_INT_RTC_60S, 66562579266SRabin Vincent .end = AB8500_INT_RTC_60S, 66662579266SRabin Vincent .flags = IORESOURCE_IRQ, 66762579266SRabin Vincent }, 66862579266SRabin Vincent { 66962579266SRabin Vincent .name = "ALARM", 67062579266SRabin Vincent .start = AB8500_INT_RTC_ALARM, 67162579266SRabin Vincent .end = AB8500_INT_RTC_ALARM, 67262579266SRabin Vincent .flags = IORESOURCE_IRQ, 67362579266SRabin Vincent }, 67462579266SRabin Vincent }; 67562579266SRabin Vincent 676a9e9ce4cSBill Pemberton static struct resource ab8500_poweronkey_db_resources[] = { 67777686517SSundar R Iyer { 67877686517SSundar R Iyer .name = "ONKEY_DBF", 67977686517SSundar R Iyer .start = AB8500_INT_PON_KEY1DB_F, 68077686517SSundar R Iyer .end = AB8500_INT_PON_KEY1DB_F, 68177686517SSundar R Iyer .flags = IORESOURCE_IRQ, 68277686517SSundar R Iyer }, 68377686517SSundar R Iyer { 68477686517SSundar R Iyer .name = "ONKEY_DBR", 68577686517SSundar R Iyer .start = AB8500_INT_PON_KEY1DB_R, 68677686517SSundar R Iyer .end = AB8500_INT_PON_KEY1DB_R, 68777686517SSundar R Iyer .flags = IORESOURCE_IRQ, 68877686517SSundar R Iyer }, 68977686517SSundar R Iyer }; 69077686517SSundar R Iyer 691a9e9ce4cSBill Pemberton static struct resource ab8500_av_acc_detect_resources[] = { 692e098adedSMattias Wallin { 6936af75ecdSLinus Walleij .name = "ACC_DETECT_1DB_F", 6946af75ecdSLinus Walleij .start = AB8500_INT_ACC_DETECT_1DB_F, 6956af75ecdSLinus Walleij .end = AB8500_INT_ACC_DETECT_1DB_F, 696e098adedSMattias Wallin .flags = IORESOURCE_IRQ, 697e098adedSMattias Wallin }, 698e098adedSMattias Wallin { 6996af75ecdSLinus Walleij .name = "ACC_DETECT_1DB_R", 7006af75ecdSLinus Walleij .start = AB8500_INT_ACC_DETECT_1DB_R, 7016af75ecdSLinus Walleij .end = AB8500_INT_ACC_DETECT_1DB_R, 702e098adedSMattias Wallin .flags = IORESOURCE_IRQ, 703e098adedSMattias Wallin }, 704e098adedSMattias Wallin { 7056af75ecdSLinus Walleij .name = "ACC_DETECT_21DB_F", 7066af75ecdSLinus Walleij .start = AB8500_INT_ACC_DETECT_21DB_F, 7076af75ecdSLinus Walleij .end = AB8500_INT_ACC_DETECT_21DB_F, 7086af75ecdSLinus Walleij .flags = IORESOURCE_IRQ, 7096af75ecdSLinus Walleij }, 7106af75ecdSLinus Walleij { 7116af75ecdSLinus Walleij .name = "ACC_DETECT_21DB_R", 7126af75ecdSLinus Walleij .start = AB8500_INT_ACC_DETECT_21DB_R, 7136af75ecdSLinus Walleij .end = AB8500_INT_ACC_DETECT_21DB_R, 7146af75ecdSLinus Walleij .flags = IORESOURCE_IRQ, 7156af75ecdSLinus Walleij }, 7166af75ecdSLinus Walleij { 7176af75ecdSLinus Walleij .name = "ACC_DETECT_22DB_F", 7186af75ecdSLinus Walleij .start = AB8500_INT_ACC_DETECT_22DB_F, 7196af75ecdSLinus Walleij .end = AB8500_INT_ACC_DETECT_22DB_F, 7206af75ecdSLinus Walleij .flags = IORESOURCE_IRQ, 7216af75ecdSLinus Walleij }, 7226af75ecdSLinus Walleij { 7236af75ecdSLinus Walleij .name = "ACC_DETECT_22DB_R", 7246af75ecdSLinus Walleij .start = AB8500_INT_ACC_DETECT_22DB_R, 7256af75ecdSLinus Walleij .end = AB8500_INT_ACC_DETECT_22DB_R, 7266af75ecdSLinus Walleij .flags = IORESOURCE_IRQ, 7276af75ecdSLinus Walleij }, 7286af75ecdSLinus Walleij }; 7296af75ecdSLinus Walleij 730a9e9ce4cSBill Pemberton static struct resource ab8500_charger_resources[] = { 7316af75ecdSLinus Walleij { 732e098adedSMattias Wallin .name = "MAIN_CH_UNPLUG_DET", 733e098adedSMattias Wallin .start = AB8500_INT_MAIN_CH_UNPLUG_DET, 734e098adedSMattias Wallin .end = AB8500_INT_MAIN_CH_UNPLUG_DET, 735e098adedSMattias Wallin .flags = IORESOURCE_IRQ, 736e098adedSMattias Wallin }, 737e098adedSMattias Wallin { 738e098adedSMattias Wallin .name = "MAIN_CHARGE_PLUG_DET", 739e098adedSMattias Wallin .start = AB8500_INT_MAIN_CH_PLUG_DET, 740e098adedSMattias Wallin .end = AB8500_INT_MAIN_CH_PLUG_DET, 741e098adedSMattias Wallin .flags = IORESOURCE_IRQ, 742e098adedSMattias Wallin }, 743e098adedSMattias Wallin { 744e098adedSMattias Wallin .name = "VBUS_DET_R", 745e098adedSMattias Wallin .start = AB8500_INT_VBUS_DET_R, 746e098adedSMattias Wallin .end = AB8500_INT_VBUS_DET_R, 747e098adedSMattias Wallin .flags = IORESOURCE_IRQ, 748e098adedSMattias Wallin }, 749e098adedSMattias Wallin { 7506af75ecdSLinus Walleij .name = "VBUS_DET_F", 7516af75ecdSLinus Walleij .start = AB8500_INT_VBUS_DET_F, 7526af75ecdSLinus Walleij .end = AB8500_INT_VBUS_DET_F, 753e098adedSMattias Wallin .flags = IORESOURCE_IRQ, 754e098adedSMattias Wallin }, 755e098adedSMattias Wallin { 7566af75ecdSLinus Walleij .name = "USB_LINK_STATUS", 7576af75ecdSLinus Walleij .start = AB8500_INT_USB_LINK_STATUS, 7586af75ecdSLinus Walleij .end = AB8500_INT_USB_LINK_STATUS, 7596af75ecdSLinus Walleij .flags = IORESOURCE_IRQ, 7606af75ecdSLinus Walleij }, 7616af75ecdSLinus Walleij { 762e098adedSMattias Wallin .name = "VBUS_OVV", 763e098adedSMattias Wallin .start = AB8500_INT_VBUS_OVV, 764e098adedSMattias Wallin .end = AB8500_INT_VBUS_OVV, 765e098adedSMattias Wallin .flags = IORESOURCE_IRQ, 766e098adedSMattias Wallin }, 767e098adedSMattias Wallin { 7686af75ecdSLinus Walleij .name = "USB_CH_TH_PROT_R", 7696af75ecdSLinus Walleij .start = AB8500_INT_USB_CH_TH_PROT_R, 7706af75ecdSLinus Walleij .end = AB8500_INT_USB_CH_TH_PROT_R, 771e098adedSMattias Wallin .flags = IORESOURCE_IRQ, 772e098adedSMattias Wallin }, 773e098adedSMattias Wallin { 7746af75ecdSLinus Walleij .name = "USB_CH_TH_PROT_F", 7756af75ecdSLinus Walleij .start = AB8500_INT_USB_CH_TH_PROT_F, 7766af75ecdSLinus Walleij .end = AB8500_INT_USB_CH_TH_PROT_F, 777e098adedSMattias Wallin .flags = IORESOURCE_IRQ, 778e098adedSMattias Wallin }, 779e098adedSMattias Wallin { 7806af75ecdSLinus Walleij .name = "MAIN_EXT_CH_NOT_OK", 7816af75ecdSLinus Walleij .start = AB8500_INT_MAIN_EXT_CH_NOT_OK, 7826af75ecdSLinus Walleij .end = AB8500_INT_MAIN_EXT_CH_NOT_OK, 7836af75ecdSLinus Walleij .flags = IORESOURCE_IRQ, 7846af75ecdSLinus Walleij }, 7856af75ecdSLinus Walleij { 7866af75ecdSLinus Walleij .name = "MAIN_CH_TH_PROT_R", 7876af75ecdSLinus Walleij .start = AB8500_INT_MAIN_CH_TH_PROT_R, 7886af75ecdSLinus Walleij .end = AB8500_INT_MAIN_CH_TH_PROT_R, 7896af75ecdSLinus Walleij .flags = IORESOURCE_IRQ, 7906af75ecdSLinus Walleij }, 7916af75ecdSLinus Walleij { 7926af75ecdSLinus Walleij .name = "MAIN_CH_TH_PROT_F", 7936af75ecdSLinus Walleij .start = AB8500_INT_MAIN_CH_TH_PROT_F, 7946af75ecdSLinus Walleij .end = AB8500_INT_MAIN_CH_TH_PROT_F, 7956af75ecdSLinus Walleij .flags = IORESOURCE_IRQ, 7966af75ecdSLinus Walleij }, 7976af75ecdSLinus Walleij { 7986af75ecdSLinus Walleij .name = "USB_CHARGER_NOT_OKR", 799a982362cSBengt Jonsson .start = AB8500_INT_USB_CHARGER_NOT_OKR, 800a982362cSBengt Jonsson .end = AB8500_INT_USB_CHARGER_NOT_OKR, 8016af75ecdSLinus Walleij .flags = IORESOURCE_IRQ, 8026af75ecdSLinus Walleij }, 8036af75ecdSLinus Walleij { 8046af75ecdSLinus Walleij .name = "CH_WD_EXP", 8056af75ecdSLinus Walleij .start = AB8500_INT_CH_WD_EXP, 8066af75ecdSLinus Walleij .end = AB8500_INT_CH_WD_EXP, 8076af75ecdSLinus Walleij .flags = IORESOURCE_IRQ, 8086af75ecdSLinus Walleij }, 80934c11a70SPaer-Olof Haakansson { 81034c11a70SPaer-Olof Haakansson .name = "VBUS_CH_DROP_END", 81134c11a70SPaer-Olof Haakansson .start = AB8500_INT_VBUS_CH_DROP_END, 81234c11a70SPaer-Olof Haakansson .end = AB8500_INT_VBUS_CH_DROP_END, 81334c11a70SPaer-Olof Haakansson .flags = IORESOURCE_IRQ, 81434c11a70SPaer-Olof Haakansson }, 8156af75ecdSLinus Walleij }; 8166af75ecdSLinus Walleij 817a9e9ce4cSBill Pemberton static struct resource ab8500_btemp_resources[] = { 8186af75ecdSLinus Walleij { 8196af75ecdSLinus Walleij .name = "BAT_CTRL_INDB", 8206af75ecdSLinus Walleij .start = AB8500_INT_BAT_CTRL_INDB, 8216af75ecdSLinus Walleij .end = AB8500_INT_BAT_CTRL_INDB, 822e098adedSMattias Wallin .flags = IORESOURCE_IRQ, 823e098adedSMattias Wallin }, 824e098adedSMattias Wallin { 825e098adedSMattias Wallin .name = "BTEMP_LOW", 826e098adedSMattias Wallin .start = AB8500_INT_BTEMP_LOW, 827e098adedSMattias Wallin .end = AB8500_INT_BTEMP_LOW, 828e098adedSMattias Wallin .flags = IORESOURCE_IRQ, 829e098adedSMattias Wallin }, 830e098adedSMattias Wallin { 831e098adedSMattias Wallin .name = "BTEMP_HIGH", 832e098adedSMattias Wallin .start = AB8500_INT_BTEMP_HIGH, 833e098adedSMattias Wallin .end = AB8500_INT_BTEMP_HIGH, 834e098adedSMattias Wallin .flags = IORESOURCE_IRQ, 835e098adedSMattias Wallin }, 836e098adedSMattias Wallin { 8376af75ecdSLinus Walleij .name = "BTEMP_LOW_MEDIUM", 8386af75ecdSLinus Walleij .start = AB8500_INT_BTEMP_LOW_MEDIUM, 8396af75ecdSLinus Walleij .end = AB8500_INT_BTEMP_LOW_MEDIUM, 840e098adedSMattias Wallin .flags = IORESOURCE_IRQ, 841e098adedSMattias Wallin }, 842e098adedSMattias Wallin { 8436af75ecdSLinus Walleij .name = "BTEMP_MEDIUM_HIGH", 8446af75ecdSLinus Walleij .start = AB8500_INT_BTEMP_MEDIUM_HIGH, 8456af75ecdSLinus Walleij .end = AB8500_INT_BTEMP_MEDIUM_HIGH, 846e098adedSMattias Wallin .flags = IORESOURCE_IRQ, 847e098adedSMattias Wallin }, 848e098adedSMattias Wallin }; 849e098adedSMattias Wallin 850a9e9ce4cSBill Pemberton static struct resource ab8500_fg_resources[] = { 8516af75ecdSLinus Walleij { 8526af75ecdSLinus Walleij .name = "NCONV_ACCU", 8536af75ecdSLinus Walleij .start = AB8500_INT_CCN_CONV_ACC, 8546af75ecdSLinus Walleij .end = AB8500_INT_CCN_CONV_ACC, 8556af75ecdSLinus Walleij .flags = IORESOURCE_IRQ, 8566af75ecdSLinus Walleij }, 8576af75ecdSLinus Walleij { 8586af75ecdSLinus Walleij .name = "BATT_OVV", 8596af75ecdSLinus Walleij .start = AB8500_INT_BATT_OVV, 8606af75ecdSLinus Walleij .end = AB8500_INT_BATT_OVV, 8616af75ecdSLinus Walleij .flags = IORESOURCE_IRQ, 8626af75ecdSLinus Walleij }, 8636af75ecdSLinus Walleij { 8646af75ecdSLinus Walleij .name = "LOW_BAT_F", 8656af75ecdSLinus Walleij .start = AB8500_INT_LOW_BAT_F, 8666af75ecdSLinus Walleij .end = AB8500_INT_LOW_BAT_F, 8676af75ecdSLinus Walleij .flags = IORESOURCE_IRQ, 8686af75ecdSLinus Walleij }, 8696af75ecdSLinus Walleij { 8706af75ecdSLinus Walleij .name = "LOW_BAT_R", 8716af75ecdSLinus Walleij .start = AB8500_INT_LOW_BAT_R, 8726af75ecdSLinus Walleij .end = AB8500_INT_LOW_BAT_R, 8736af75ecdSLinus Walleij .flags = IORESOURCE_IRQ, 8746af75ecdSLinus Walleij }, 8756af75ecdSLinus Walleij { 8766af75ecdSLinus Walleij .name = "CC_INT_CALIB", 8776af75ecdSLinus Walleij .start = AB8500_INT_CC_INT_CALIB, 8786af75ecdSLinus Walleij .end = AB8500_INT_CC_INT_CALIB, 8796af75ecdSLinus Walleij .flags = IORESOURCE_IRQ, 8806af75ecdSLinus Walleij }, 881a982362cSBengt Jonsson { 882a982362cSBengt Jonsson .name = "CCEOC", 883a982362cSBengt Jonsson .start = AB8500_INT_CCEOC, 884a982362cSBengt Jonsson .end = AB8500_INT_CCEOC, 885a982362cSBengt Jonsson .flags = IORESOURCE_IRQ, 886a982362cSBengt Jonsson }, 8876af75ecdSLinus Walleij }; 8886af75ecdSLinus Walleij 889a9e9ce4cSBill Pemberton static struct resource ab8500_chargalg_resources[] = {}; 8906af75ecdSLinus Walleij 891df720647SAxel Lin #ifdef CONFIG_DEBUG_FS 892a9e9ce4cSBill Pemberton static struct resource ab8500_debug_resources[] = { 893e098adedSMattias Wallin { 894e098adedSMattias Wallin .name = "IRQ_FIRST", 895e098adedSMattias Wallin .start = AB8500_INT_MAIN_EXT_CH_NOT_OK, 896e098adedSMattias Wallin .end = AB8500_INT_MAIN_EXT_CH_NOT_OK, 897e098adedSMattias Wallin .flags = IORESOURCE_IRQ, 898e098adedSMattias Wallin }, 899e098adedSMattias Wallin { 900e098adedSMattias Wallin .name = "IRQ_LAST", 901a982362cSBengt Jonsson .start = AB8500_INT_XTAL32K_KO, 902a982362cSBengt Jonsson .end = AB8500_INT_XTAL32K_KO, 903e098adedSMattias Wallin .flags = IORESOURCE_IRQ, 904e098adedSMattias Wallin }, 905e098adedSMattias Wallin }; 906df720647SAxel Lin #endif 907e098adedSMattias Wallin 908a9e9ce4cSBill Pemberton static struct resource ab8500_usb_resources[] = { 909e098adedSMattias Wallin { 910e098adedSMattias Wallin .name = "ID_WAKEUP_R", 911e098adedSMattias Wallin .start = AB8500_INT_ID_WAKEUP_R, 912e098adedSMattias Wallin .end = AB8500_INT_ID_WAKEUP_R, 913e098adedSMattias Wallin .flags = IORESOURCE_IRQ, 914e098adedSMattias Wallin }, 915e098adedSMattias Wallin { 916e098adedSMattias Wallin .name = "ID_WAKEUP_F", 917e098adedSMattias Wallin .start = AB8500_INT_ID_WAKEUP_F, 918e098adedSMattias Wallin .end = AB8500_INT_ID_WAKEUP_F, 919e098adedSMattias Wallin .flags = IORESOURCE_IRQ, 920e098adedSMattias Wallin }, 921e098adedSMattias Wallin { 922e098adedSMattias Wallin .name = "VBUS_DET_F", 923e098adedSMattias Wallin .start = AB8500_INT_VBUS_DET_F, 924e098adedSMattias Wallin .end = AB8500_INT_VBUS_DET_F, 925e098adedSMattias Wallin .flags = IORESOURCE_IRQ, 926e098adedSMattias Wallin }, 927e098adedSMattias Wallin { 928e098adedSMattias Wallin .name = "VBUS_DET_R", 929e098adedSMattias Wallin .start = AB8500_INT_VBUS_DET_R, 930e098adedSMattias Wallin .end = AB8500_INT_VBUS_DET_R, 931e098adedSMattias Wallin .flags = IORESOURCE_IRQ, 932e098adedSMattias Wallin }, 93392d50a41SMattias Wallin { 93492d50a41SMattias Wallin .name = "USB_LINK_STATUS", 93592d50a41SMattias Wallin .start = AB8500_INT_USB_LINK_STATUS, 93692d50a41SMattias Wallin .end = AB8500_INT_USB_LINK_STATUS, 93792d50a41SMattias Wallin .flags = IORESOURCE_IRQ, 93892d50a41SMattias Wallin }, 9396af75ecdSLinus Walleij { 9406af75ecdSLinus Walleij .name = "USB_ADP_PROBE_PLUG", 9416af75ecdSLinus Walleij .start = AB8500_INT_ADP_PROBE_PLUG, 9426af75ecdSLinus Walleij .end = AB8500_INT_ADP_PROBE_PLUG, 9436af75ecdSLinus Walleij .flags = IORESOURCE_IRQ, 9446af75ecdSLinus Walleij }, 9456af75ecdSLinus Walleij { 9466af75ecdSLinus Walleij .name = "USB_ADP_PROBE_UNPLUG", 9476af75ecdSLinus Walleij .start = AB8500_INT_ADP_PROBE_UNPLUG, 9486af75ecdSLinus Walleij .end = AB8500_INT_ADP_PROBE_UNPLUG, 9496af75ecdSLinus Walleij .flags = IORESOURCE_IRQ, 9506af75ecdSLinus Walleij }, 951e098adedSMattias Wallin }; 952e098adedSMattias Wallin 953a9e9ce4cSBill Pemberton static struct resource ab8505_iddet_resources[] = { 95444f72e53SVirupax Sadashivpetimath { 95544f72e53SVirupax Sadashivpetimath .name = "KeyDeglitch", 95644f72e53SVirupax Sadashivpetimath .start = AB8505_INT_KEYDEGLITCH, 95744f72e53SVirupax Sadashivpetimath .end = AB8505_INT_KEYDEGLITCH, 95844f72e53SVirupax Sadashivpetimath .flags = IORESOURCE_IRQ, 95944f72e53SVirupax Sadashivpetimath }, 96044f72e53SVirupax Sadashivpetimath { 96144f72e53SVirupax Sadashivpetimath .name = "KP", 96244f72e53SVirupax Sadashivpetimath .start = AB8505_INT_KP, 96344f72e53SVirupax Sadashivpetimath .end = AB8505_INT_KP, 96444f72e53SVirupax Sadashivpetimath .flags = IORESOURCE_IRQ, 96544f72e53SVirupax Sadashivpetimath }, 96644f72e53SVirupax Sadashivpetimath { 96744f72e53SVirupax Sadashivpetimath .name = "IKP", 96844f72e53SVirupax Sadashivpetimath .start = AB8505_INT_IKP, 96944f72e53SVirupax Sadashivpetimath .end = AB8505_INT_IKP, 97044f72e53SVirupax Sadashivpetimath .flags = IORESOURCE_IRQ, 97144f72e53SVirupax Sadashivpetimath }, 97244f72e53SVirupax Sadashivpetimath { 97344f72e53SVirupax Sadashivpetimath .name = "IKR", 97444f72e53SVirupax Sadashivpetimath .start = AB8505_INT_IKR, 97544f72e53SVirupax Sadashivpetimath .end = AB8505_INT_IKR, 97644f72e53SVirupax Sadashivpetimath .flags = IORESOURCE_IRQ, 97744f72e53SVirupax Sadashivpetimath }, 97844f72e53SVirupax Sadashivpetimath { 97944f72e53SVirupax Sadashivpetimath .name = "KeyStuck", 98044f72e53SVirupax Sadashivpetimath .start = AB8505_INT_KEYSTUCK, 98144f72e53SVirupax Sadashivpetimath .end = AB8505_INT_KEYSTUCK, 98244f72e53SVirupax Sadashivpetimath .flags = IORESOURCE_IRQ, 98344f72e53SVirupax Sadashivpetimath }, 98444f72e53SVirupax Sadashivpetimath }; 98544f72e53SVirupax Sadashivpetimath 986a9e9ce4cSBill Pemberton static struct resource ab8500_temp_resources[] = { 987e098adedSMattias Wallin { 988151621a7SHongbo Zhang .name = "ABX500_TEMP_WARM", 989e098adedSMattias Wallin .start = AB8500_INT_TEMP_WARM, 990e098adedSMattias Wallin .end = AB8500_INT_TEMP_WARM, 991e098adedSMattias Wallin .flags = IORESOURCE_IRQ, 992e098adedSMattias Wallin }, 993e098adedSMattias Wallin }; 994e098adedSMattias Wallin 995a9e9ce4cSBill Pemberton static struct mfd_cell abx500_common_devs[] = { 9965814fc35SMattias Wallin #ifdef CONFIG_DEBUG_FS 9975814fc35SMattias Wallin { 9985814fc35SMattias Wallin .name = "ab8500-debug", 999bad76991SLee Jones .of_compatible = "stericsson,ab8500-debug", 1000e098adedSMattias Wallin .num_resources = ARRAY_SIZE(ab8500_debug_resources), 1001e098adedSMattias Wallin .resources = ab8500_debug_resources, 10025814fc35SMattias Wallin }, 10035814fc35SMattias Wallin #endif 100462579266SRabin Vincent { 1005e098adedSMattias Wallin .name = "ab8500-sysctrl", 1006bad76991SLee Jones .of_compatible = "stericsson,ab8500-sysctrl", 1007e098adedSMattias Wallin }, 1008e098adedSMattias Wallin { 1009e098adedSMattias Wallin .name = "ab8500-regulator", 1010bad76991SLee Jones .of_compatible = "stericsson,ab8500-regulator", 1011e098adedSMattias Wallin }, 1012e098adedSMattias Wallin { 1013916a871cSUlf Hansson .name = "abx500-clk", 1014916a871cSUlf Hansson .of_compatible = "stericsson,abx500-clk", 1015916a871cSUlf Hansson }, 1016916a871cSUlf Hansson { 101762579266SRabin Vincent .name = "ab8500-gpadc", 1018bad76991SLee Jones .of_compatible = "stericsson,ab8500-gpadc", 101962579266SRabin Vincent .num_resources = ARRAY_SIZE(ab8500_gpadc_resources), 102062579266SRabin Vincent .resources = ab8500_gpadc_resources, 102162579266SRabin Vincent }, 102262579266SRabin Vincent { 102362579266SRabin Vincent .name = "ab8500-rtc", 1024bad76991SLee Jones .of_compatible = "stericsson,ab8500-rtc", 102562579266SRabin Vincent .num_resources = ARRAY_SIZE(ab8500_rtc_resources), 102662579266SRabin Vincent .resources = ab8500_rtc_resources, 102762579266SRabin Vincent }, 1028f0f05b1cSArun Murthy { 10296af75ecdSLinus Walleij .name = "ab8500-acc-det", 1030bad76991SLee Jones .of_compatible = "stericsson,ab8500-acc-det", 10316af75ecdSLinus Walleij .num_resources = ARRAY_SIZE(ab8500_av_acc_detect_resources), 10326af75ecdSLinus Walleij .resources = ab8500_av_acc_detect_resources, 10336af75ecdSLinus Walleij }, 10346af75ecdSLinus Walleij { 1035e098adedSMattias Wallin .name = "ab8500-poweron-key", 1036bad76991SLee Jones .of_compatible = "stericsson,ab8500-poweron-key", 1037e098adedSMattias Wallin .num_resources = ARRAY_SIZE(ab8500_poweronkey_db_resources), 1038e098adedSMattias Wallin .resources = ab8500_poweronkey_db_resources, 1039e098adedSMattias Wallin }, 1040e098adedSMattias Wallin { 1041f0f05b1cSArun Murthy .name = "ab8500-pwm", 1042bad76991SLee Jones .of_compatible = "stericsson,ab8500-pwm", 1043f0f05b1cSArun Murthy .id = 1, 1044f0f05b1cSArun Murthy }, 1045f0f05b1cSArun Murthy { 1046f0f05b1cSArun Murthy .name = "ab8500-pwm", 1047bad76991SLee Jones .of_compatible = "stericsson,ab8500-pwm", 1048f0f05b1cSArun Murthy .id = 2, 1049f0f05b1cSArun Murthy }, 1050f0f05b1cSArun Murthy { 1051f0f05b1cSArun Murthy .name = "ab8500-pwm", 1052bad76991SLee Jones .of_compatible = "stericsson,ab8500-pwm", 1053f0f05b1cSArun Murthy .id = 3, 1054f0f05b1cSArun Murthy }, 1055bad76991SLee Jones { 1056bad76991SLee Jones .name = "ab8500-leds", 1057bad76991SLee Jones .of_compatible = "stericsson,ab8500-leds", 1058bad76991SLee Jones }, 105977686517SSundar R Iyer { 1060e098adedSMattias Wallin .name = "ab8500-denc", 1061bad76991SLee Jones .of_compatible = "stericsson,ab8500-denc", 1062e098adedSMattias Wallin }, 1063e098adedSMattias Wallin { 1064151621a7SHongbo Zhang .name = "abx500-temp", 1065151621a7SHongbo Zhang .of_compatible = "stericsson,abx500-temp", 1066e098adedSMattias Wallin .num_resources = ARRAY_SIZE(ab8500_temp_resources), 1067e098adedSMattias Wallin .resources = ab8500_temp_resources, 106877686517SSundar R Iyer }, 106962579266SRabin Vincent }; 107062579266SRabin Vincent 1071a9e9ce4cSBill Pemberton static struct mfd_cell ab8500_bm_devs[] = { 10726ef9418cSRickard Andersson { 10736ef9418cSRickard Andersson .name = "ab8500-charger", 10744aef72dbSRajanikanth H.V .of_compatible = "stericsson,ab8500-charger", 10756ef9418cSRickard Andersson .num_resources = ARRAY_SIZE(ab8500_charger_resources), 10766ef9418cSRickard Andersson .resources = ab8500_charger_resources, 10774aef72dbSRajanikanth H.V .platform_data = &ab8500_bm_data, 10784aef72dbSRajanikanth H.V .pdata_size = sizeof(ab8500_bm_data), 10796ef9418cSRickard Andersson }, 10806ef9418cSRickard Andersson { 10816ef9418cSRickard Andersson .name = "ab8500-btemp", 1082bd9e8ab2SRajanikanth H.V .of_compatible = "stericsson,ab8500-btemp", 10836ef9418cSRickard Andersson .num_resources = ARRAY_SIZE(ab8500_btemp_resources), 10846ef9418cSRickard Andersson .resources = ab8500_btemp_resources, 1085bd9e8ab2SRajanikanth H.V .platform_data = &ab8500_bm_data, 1086bd9e8ab2SRajanikanth H.V .pdata_size = sizeof(ab8500_bm_data), 10876ef9418cSRickard Andersson }, 10886ef9418cSRickard Andersson { 10896ef9418cSRickard Andersson .name = "ab8500-fg", 1090e0f1abebSRajanikanth H.V .of_compatible = "stericsson,ab8500-fg", 10916ef9418cSRickard Andersson .num_resources = ARRAY_SIZE(ab8500_fg_resources), 10926ef9418cSRickard Andersson .resources = ab8500_fg_resources, 1093e0f1abebSRajanikanth H.V .platform_data = &ab8500_bm_data, 1094e0f1abebSRajanikanth H.V .pdata_size = sizeof(ab8500_bm_data), 10956ef9418cSRickard Andersson }, 10966ef9418cSRickard Andersson { 10976ef9418cSRickard Andersson .name = "ab8500-chargalg", 1098a12810abSRajanikanth H.V .of_compatible = "stericsson,ab8500-chargalg", 10996ef9418cSRickard Andersson .num_resources = ARRAY_SIZE(ab8500_chargalg_resources), 11006ef9418cSRickard Andersson .resources = ab8500_chargalg_resources, 1101a12810abSRajanikanth H.V .platform_data = &ab8500_bm_data, 1102a12810abSRajanikanth H.V .pdata_size = sizeof(ab8500_bm_data), 11036ef9418cSRickard Andersson }, 11046ef9418cSRickard Andersson }; 11056ef9418cSRickard Andersson 1106a9e9ce4cSBill Pemberton static struct mfd_cell ab8500_devs[] = { 1107d6255529SLinus Walleij { 11087d56a46eSLee Jones .name = "pinctrl-ab8500", 1109bad76991SLee Jones .of_compatible = "stericsson,ab8500-gpio", 1110d6255529SLinus Walleij }, 1111d6255529SLinus Walleij { 1112d6255529SLinus Walleij .name = "ab8500-usb", 1113bad76991SLee Jones .of_compatible = "stericsson,ab8500-usb", 1114d6255529SLinus Walleij .num_resources = ARRAY_SIZE(ab8500_usb_resources), 1115d6255529SLinus Walleij .resources = ab8500_usb_resources, 1116d6255529SLinus Walleij }, 111744f72e53SVirupax Sadashivpetimath { 111844f72e53SVirupax Sadashivpetimath .name = "ab8500-codec", 111981a21cddSLee Jones .of_compatible = "stericsson,ab8500-codec", 112044f72e53SVirupax Sadashivpetimath }, 1121d6255529SLinus Walleij }; 1122d6255529SLinus Walleij 1123a9e9ce4cSBill Pemberton static struct mfd_cell ab9540_devs[] = { 1124d6255529SLinus Walleij { 1125e64d905eSLee Jones .name = "pinctrl-ab9540", 1126e64d905eSLee Jones .of_compatible = "stericsson,ab9540-gpio", 1127d6255529SLinus Walleij }, 1128d6255529SLinus Walleij { 1129d6255529SLinus Walleij .name = "ab9540-usb", 1130d6255529SLinus Walleij .num_resources = ARRAY_SIZE(ab8500_usb_resources), 1131d6255529SLinus Walleij .resources = ab8500_usb_resources, 1132d6255529SLinus Walleij }, 113344f72e53SVirupax Sadashivpetimath { 113444f72e53SVirupax Sadashivpetimath .name = "ab9540-codec", 113544f72e53SVirupax Sadashivpetimath }, 113644f72e53SVirupax Sadashivpetimath }; 113744f72e53SVirupax Sadashivpetimath 113844f72e53SVirupax Sadashivpetimath /* Device list common to ab9540 and ab8505 */ 1139a9e9ce4cSBill Pemberton static struct mfd_cell ab9540_ab8505_devs[] = { 114044f72e53SVirupax Sadashivpetimath { 114144f72e53SVirupax Sadashivpetimath .name = "ab-iddet", 114244f72e53SVirupax Sadashivpetimath .num_resources = ARRAY_SIZE(ab8505_iddet_resources), 114344f72e53SVirupax Sadashivpetimath .resources = ab8505_iddet_resources, 114444f72e53SVirupax Sadashivpetimath }, 1145d6255529SLinus Walleij }; 1146d6255529SLinus Walleij 1147cca69b67SMattias Wallin static ssize_t show_chip_id(struct device *dev, 1148cca69b67SMattias Wallin struct device_attribute *attr, char *buf) 1149cca69b67SMattias Wallin { 1150cca69b67SMattias Wallin struct ab8500 *ab8500; 1151cca69b67SMattias Wallin 1152cca69b67SMattias Wallin ab8500 = dev_get_drvdata(dev); 1153cca69b67SMattias Wallin return sprintf(buf, "%#x\n", ab8500 ? ab8500->chip_id : -EINVAL); 1154cca69b67SMattias Wallin } 1155cca69b67SMattias Wallin 1156e5c238c3SMattias Wallin /* 1157e5c238c3SMattias Wallin * ab8500 has switched off due to (SWITCH_OFF_STATUS): 1158e5c238c3SMattias Wallin * 0x01 Swoff bit programming 1159e5c238c3SMattias Wallin * 0x02 Thermal protection activation 1160e5c238c3SMattias Wallin * 0x04 Vbat lower then BattOk falling threshold 1161e5c238c3SMattias Wallin * 0x08 Watchdog expired 1162e5c238c3SMattias Wallin * 0x10 Non presence of 32kHz clock 1163e5c238c3SMattias Wallin * 0x20 Battery level lower than power on reset threshold 1164e5c238c3SMattias Wallin * 0x40 Power on key 1 pressed longer than 10 seconds 1165e5c238c3SMattias Wallin * 0x80 DB8500 thermal shutdown 1166e5c238c3SMattias Wallin */ 1167e5c238c3SMattias Wallin static ssize_t show_switch_off_status(struct device *dev, 1168e5c238c3SMattias Wallin struct device_attribute *attr, char *buf) 1169e5c238c3SMattias Wallin { 1170e5c238c3SMattias Wallin int ret; 1171e5c238c3SMattias Wallin u8 value; 1172e5c238c3SMattias Wallin struct ab8500 *ab8500; 1173e5c238c3SMattias Wallin 1174e5c238c3SMattias Wallin ab8500 = dev_get_drvdata(dev); 1175e5c238c3SMattias Wallin ret = get_register_interruptible(ab8500, AB8500_RTC, 1176e5c238c3SMattias Wallin AB8500_SWITCH_OFF_STATUS, &value); 1177e5c238c3SMattias Wallin if (ret < 0) 1178e5c238c3SMattias Wallin return ret; 1179e5c238c3SMattias Wallin return sprintf(buf, "%#x\n", value); 1180e5c238c3SMattias Wallin } 1181e5c238c3SMattias Wallin 1182f04a9d8aSRajkumar Kasirajan /* use mask and set to override the register turn_on_stat value */ 1183f04a9d8aSRajkumar Kasirajan void ab8500_override_turn_on_stat(u8 mask, u8 set) 1184f04a9d8aSRajkumar Kasirajan { 1185f04a9d8aSRajkumar Kasirajan spin_lock(&on_stat_lock); 1186f04a9d8aSRajkumar Kasirajan turn_on_stat_mask = mask; 1187f04a9d8aSRajkumar Kasirajan turn_on_stat_set = set; 1188f04a9d8aSRajkumar Kasirajan spin_unlock(&on_stat_lock); 1189f04a9d8aSRajkumar Kasirajan } 1190f04a9d8aSRajkumar Kasirajan 1191b4a31037SAndrew Lynn /* 1192b4a31037SAndrew Lynn * ab8500 has turned on due to (TURN_ON_STATUS): 1193b4a31037SAndrew Lynn * 0x01 PORnVbat 1194b4a31037SAndrew Lynn * 0x02 PonKey1dbF 1195b4a31037SAndrew Lynn * 0x04 PonKey2dbF 1196b4a31037SAndrew Lynn * 0x08 RTCAlarm 1197b4a31037SAndrew Lynn * 0x10 MainChDet 1198b4a31037SAndrew Lynn * 0x20 VbusDet 1199b4a31037SAndrew Lynn * 0x40 UsbIDDetect 1200b4a31037SAndrew Lynn * 0x80 Reserved 1201b4a31037SAndrew Lynn */ 1202b4a31037SAndrew Lynn static ssize_t show_turn_on_status(struct device *dev, 1203b4a31037SAndrew Lynn struct device_attribute *attr, char *buf) 1204b4a31037SAndrew Lynn { 1205b4a31037SAndrew Lynn int ret; 1206b4a31037SAndrew Lynn u8 value; 1207b4a31037SAndrew Lynn struct ab8500 *ab8500; 1208b4a31037SAndrew Lynn 1209b4a31037SAndrew Lynn ab8500 = dev_get_drvdata(dev); 1210b4a31037SAndrew Lynn ret = get_register_interruptible(ab8500, AB8500_SYS_CTRL1_BLOCK, 1211b4a31037SAndrew Lynn AB8500_TURN_ON_STATUS, &value); 1212b4a31037SAndrew Lynn if (ret < 0) 1213b4a31037SAndrew Lynn return ret; 1214f04a9d8aSRajkumar Kasirajan 1215f04a9d8aSRajkumar Kasirajan /* 1216f04a9d8aSRajkumar Kasirajan * In L9540, turn_on_status register is not updated correctly if 1217f04a9d8aSRajkumar Kasirajan * the device is rebooted with AC/USB charger connected. Due to 1218f04a9d8aSRajkumar Kasirajan * this, the device boots android instead of entering into charge 1219f04a9d8aSRajkumar Kasirajan * only mode. Read the AC/USB status register to detect the charger 1220f04a9d8aSRajkumar Kasirajan * presence and update the turn on status manually. 1221f04a9d8aSRajkumar Kasirajan */ 1222f04a9d8aSRajkumar Kasirajan if (is_ab9540(ab8500)) { 1223f04a9d8aSRajkumar Kasirajan spin_lock(&on_stat_lock); 1224f04a9d8aSRajkumar Kasirajan value = (value & turn_on_stat_mask) | turn_on_stat_set; 1225f04a9d8aSRajkumar Kasirajan spin_unlock(&on_stat_lock); 1226f04a9d8aSRajkumar Kasirajan } 1227f04a9d8aSRajkumar Kasirajan 1228b4a31037SAndrew Lynn return sprintf(buf, "%#x\n", value); 1229b4a31037SAndrew Lynn } 1230b4a31037SAndrew Lynn 1231d6255529SLinus Walleij static ssize_t show_ab9540_dbbrstn(struct device *dev, 1232d6255529SLinus Walleij struct device_attribute *attr, char *buf) 1233d6255529SLinus Walleij { 1234d6255529SLinus Walleij struct ab8500 *ab8500; 1235d6255529SLinus Walleij int ret; 1236d6255529SLinus Walleij u8 value; 1237d6255529SLinus Walleij 1238d6255529SLinus Walleij ab8500 = dev_get_drvdata(dev); 1239d6255529SLinus Walleij 1240d6255529SLinus Walleij ret = get_register_interruptible(ab8500, AB8500_REGU_CTRL2, 1241d6255529SLinus Walleij AB9540_MODEM_CTRL2_REG, &value); 1242d6255529SLinus Walleij if (ret < 0) 1243d6255529SLinus Walleij return ret; 1244d6255529SLinus Walleij 1245d6255529SLinus Walleij return sprintf(buf, "%d\n", 1246d6255529SLinus Walleij (value & AB9540_MODEM_CTRL2_SWDBBRSTN_BIT) ? 1 : 0); 1247d6255529SLinus Walleij } 1248d6255529SLinus Walleij 1249d6255529SLinus Walleij static ssize_t store_ab9540_dbbrstn(struct device *dev, 1250d6255529SLinus Walleij struct device_attribute *attr, const char *buf, size_t count) 1251d6255529SLinus Walleij { 1252d6255529SLinus Walleij struct ab8500 *ab8500; 1253d6255529SLinus Walleij int ret = count; 1254d6255529SLinus Walleij int err; 1255d6255529SLinus Walleij u8 bitvalues; 1256d6255529SLinus Walleij 1257d6255529SLinus Walleij ab8500 = dev_get_drvdata(dev); 1258d6255529SLinus Walleij 1259d6255529SLinus Walleij if (count > 0) { 1260d6255529SLinus Walleij switch (buf[0]) { 1261d6255529SLinus Walleij case '0': 1262d6255529SLinus Walleij bitvalues = 0; 1263d6255529SLinus Walleij break; 1264d6255529SLinus Walleij case '1': 1265d6255529SLinus Walleij bitvalues = AB9540_MODEM_CTRL2_SWDBBRSTN_BIT; 1266d6255529SLinus Walleij break; 1267d6255529SLinus Walleij default: 1268d6255529SLinus Walleij goto exit; 1269d6255529SLinus Walleij } 1270d6255529SLinus Walleij 1271d6255529SLinus Walleij err = mask_and_set_register_interruptible(ab8500, 1272d6255529SLinus Walleij AB8500_REGU_CTRL2, AB9540_MODEM_CTRL2_REG, 1273d6255529SLinus Walleij AB9540_MODEM_CTRL2_SWDBBRSTN_BIT, bitvalues); 1274d6255529SLinus Walleij if (err) 1275d6255529SLinus Walleij dev_info(ab8500->dev, 1276d6255529SLinus Walleij "Failed to set DBBRSTN %c, err %#x\n", 1277d6255529SLinus Walleij buf[0], err); 1278d6255529SLinus Walleij } 1279d6255529SLinus Walleij 1280d6255529SLinus Walleij exit: 1281d6255529SLinus Walleij return ret; 1282d6255529SLinus Walleij } 1283d6255529SLinus Walleij 1284cca69b67SMattias Wallin static DEVICE_ATTR(chip_id, S_IRUGO, show_chip_id, NULL); 1285e5c238c3SMattias Wallin static DEVICE_ATTR(switch_off_status, S_IRUGO, show_switch_off_status, NULL); 1286b4a31037SAndrew Lynn static DEVICE_ATTR(turn_on_status, S_IRUGO, show_turn_on_status, NULL); 1287d6255529SLinus Walleij static DEVICE_ATTR(dbbrstn, S_IRUGO | S_IWUSR, 1288d6255529SLinus Walleij show_ab9540_dbbrstn, store_ab9540_dbbrstn); 1289cca69b67SMattias Wallin 1290cca69b67SMattias Wallin static struct attribute *ab8500_sysfs_entries[] = { 1291cca69b67SMattias Wallin &dev_attr_chip_id.attr, 1292e5c238c3SMattias Wallin &dev_attr_switch_off_status.attr, 1293b4a31037SAndrew Lynn &dev_attr_turn_on_status.attr, 1294cca69b67SMattias Wallin NULL, 1295cca69b67SMattias Wallin }; 1296cca69b67SMattias Wallin 1297d6255529SLinus Walleij static struct attribute *ab9540_sysfs_entries[] = { 1298d6255529SLinus Walleij &dev_attr_chip_id.attr, 1299d6255529SLinus Walleij &dev_attr_switch_off_status.attr, 1300d6255529SLinus Walleij &dev_attr_turn_on_status.attr, 1301d6255529SLinus Walleij &dev_attr_dbbrstn.attr, 1302d6255529SLinus Walleij NULL, 1303d6255529SLinus Walleij }; 1304d6255529SLinus Walleij 1305cca69b67SMattias Wallin static struct attribute_group ab8500_attr_group = { 1306cca69b67SMattias Wallin .attrs = ab8500_sysfs_entries, 1307cca69b67SMattias Wallin }; 1308cca69b67SMattias Wallin 1309d6255529SLinus Walleij static struct attribute_group ab9540_attr_group = { 1310d6255529SLinus Walleij .attrs = ab9540_sysfs_entries, 1311d6255529SLinus Walleij }; 1312d6255529SLinus Walleij 1313f791be49SBill Pemberton static int ab8500_probe(struct platform_device *pdev) 131462579266SRabin Vincent { 1315b04c530cSJonas Aaberg static char *switch_off_status[] = { 1316b04c530cSJonas Aaberg "Swoff bit programming", 1317b04c530cSJonas Aaberg "Thermal protection activation", 1318b04c530cSJonas Aaberg "Vbat lower then BattOk falling threshold", 1319b04c530cSJonas Aaberg "Watchdog expired", 1320b04c530cSJonas Aaberg "Non presence of 32kHz clock", 1321b04c530cSJonas Aaberg "Battery level lower than power on reset threshold", 1322b04c530cSJonas Aaberg "Power on key 1 pressed longer than 10 seconds", 1323b04c530cSJonas Aaberg "DB8500 thermal shutdown"}; 1324d28f1db8SLee Jones struct ab8500_platform_data *plat = dev_get_platdata(&pdev->dev); 1325d28f1db8SLee Jones const struct platform_device_id *platid = platform_get_device_id(pdev); 13266bc4a568SLee Jones enum ab8500_version version = AB8500_VERSION_UNDEFINED; 13276bc4a568SLee Jones struct device_node *np = pdev->dev.of_node; 1328d28f1db8SLee Jones struct ab8500 *ab8500; 1329d28f1db8SLee Jones struct resource *resource; 133062579266SRabin Vincent int ret; 133162579266SRabin Vincent int i; 133247c16975SMattias Wallin u8 value; 133362579266SRabin Vincent 13348c4203cbSLee Jones ab8500 = devm_kzalloc(&pdev->dev, sizeof *ab8500, GFP_KERNEL); 1335d28f1db8SLee Jones if (!ab8500) 1336d28f1db8SLee Jones return -ENOMEM; 1337d28f1db8SLee Jones 133862579266SRabin Vincent if (plat) 133962579266SRabin Vincent ab8500->irq_base = plat->irq_base; 134062579266SRabin Vincent 1341d28f1db8SLee Jones ab8500->dev = &pdev->dev; 1342d28f1db8SLee Jones 1343d28f1db8SLee Jones resource = platform_get_resource(pdev, IORESOURCE_IRQ, 0); 13448c4203cbSLee Jones if (!resource) 13458c4203cbSLee Jones return -ENODEV; 1346d28f1db8SLee Jones 1347d28f1db8SLee Jones ab8500->irq = resource->start; 1348d28f1db8SLee Jones 1349822672a7SLee Jones ab8500->read = ab8500_prcmu_read; 1350822672a7SLee Jones ab8500->write = ab8500_prcmu_write; 1351822672a7SLee Jones ab8500->write_masked = ab8500_prcmu_write_masked; 1352d28f1db8SLee Jones 135362579266SRabin Vincent mutex_init(&ab8500->lock); 135462579266SRabin Vincent mutex_init(&ab8500->irq_lock); 1355112a80d2SJonas Aaberg atomic_set(&ab8500->transfer_ongoing, 0); 135662579266SRabin Vincent 1357d28f1db8SLee Jones platform_set_drvdata(pdev, ab8500); 1358d28f1db8SLee Jones 13596bc4a568SLee Jones if (platid) 13606bc4a568SLee Jones version = platid->driver_data; 13616bc4a568SLee Jones 13620f620837SLinus Walleij if (version != AB8500_VERSION_UNDEFINED) 13630f620837SLinus Walleij ab8500->version = version; 13640f620837SLinus Walleij else { 13650f620837SLinus Walleij ret = get_register_interruptible(ab8500, AB8500_MISC, 13660f620837SLinus Walleij AB8500_IC_NAME_REG, &value); 13670f620837SLinus Walleij if (ret < 0) 13688c4203cbSLee Jones return ret; 13690f620837SLinus Walleij 13700f620837SLinus Walleij ab8500->version = value; 13710f620837SLinus Walleij } 13720f620837SLinus Walleij 137347c16975SMattias Wallin ret = get_register_interruptible(ab8500, AB8500_MISC, 137447c16975SMattias Wallin AB8500_REV_REG, &value); 137562579266SRabin Vincent if (ret < 0) 13768c4203cbSLee Jones return ret; 137762579266SRabin Vincent 137847c16975SMattias Wallin ab8500->chip_id = value; 137962579266SRabin Vincent 13800f620837SLinus Walleij dev_info(ab8500->dev, "detected chip, %s rev. %1x.%1x\n", 13810f620837SLinus Walleij ab8500_version_str[ab8500->version], 13820f620837SLinus Walleij ab8500->chip_id >> 4, 13830f620837SLinus Walleij ab8500->chip_id & 0x0F); 13840f620837SLinus Walleij 1385d6255529SLinus Walleij /* Configure AB8500 or AB9540 IRQ */ 1386a982362cSBengt Jonsson if (is_ab9540(ab8500) || is_ab8505(ab8500)) { 1387d6255529SLinus Walleij ab8500->mask_size = AB9540_NUM_IRQ_REGS; 1388d6255529SLinus Walleij ab8500->irq_reg_offset = ab9540_irq_regoffset; 1389d6255529SLinus Walleij } else { 13902ced445eSLinus Walleij ab8500->mask_size = AB8500_NUM_IRQ_REGS; 13912ced445eSLinus Walleij ab8500->irq_reg_offset = ab8500_irq_regoffset; 1392d6255529SLinus Walleij } 13938c4203cbSLee Jones ab8500->mask = devm_kzalloc(&pdev->dev, ab8500->mask_size, GFP_KERNEL); 13942ced445eSLinus Walleij if (!ab8500->mask) 13952ced445eSLinus Walleij return -ENOMEM; 13968c4203cbSLee Jones ab8500->oldmask = devm_kzalloc(&pdev->dev, ab8500->mask_size, GFP_KERNEL); 13978c4203cbSLee Jones if (!ab8500->oldmask) 13988c4203cbSLee Jones return -ENOMEM; 13998c4203cbSLee Jones 1400e5c238c3SMattias Wallin /* 1401e5c238c3SMattias Wallin * ab8500 has switched off due to (SWITCH_OFF_STATUS): 1402e5c238c3SMattias Wallin * 0x01 Swoff bit programming 1403e5c238c3SMattias Wallin * 0x02 Thermal protection activation 1404e5c238c3SMattias Wallin * 0x04 Vbat lower then BattOk falling threshold 1405e5c238c3SMattias Wallin * 0x08 Watchdog expired 1406e5c238c3SMattias Wallin * 0x10 Non presence of 32kHz clock 1407e5c238c3SMattias Wallin * 0x20 Battery level lower than power on reset threshold 1408e5c238c3SMattias Wallin * 0x40 Power on key 1 pressed longer than 10 seconds 1409e5c238c3SMattias Wallin * 0x80 DB8500 thermal shutdown 1410e5c238c3SMattias Wallin */ 1411e5c238c3SMattias Wallin 1412e5c238c3SMattias Wallin ret = get_register_interruptible(ab8500, AB8500_RTC, 1413e5c238c3SMattias Wallin AB8500_SWITCH_OFF_STATUS, &value); 1414e5c238c3SMattias Wallin if (ret < 0) 1415e5c238c3SMattias Wallin return ret; 1416b04c530cSJonas Aaberg dev_info(ab8500->dev, "switch off cause(s) (%#x): ", value); 1417b04c530cSJonas Aaberg 1418b04c530cSJonas Aaberg if (value) { 1419b04c530cSJonas Aaberg for (i = 0; i < ARRAY_SIZE(switch_off_status); i++) { 1420b04c530cSJonas Aaberg if (value & 1) 1421b04c530cSJonas Aaberg printk(KERN_CONT " \"%s\"", 1422b04c530cSJonas Aaberg switch_off_status[i]); 1423b04c530cSJonas Aaberg value = value >> 1; 1424b04c530cSJonas Aaberg 1425b04c530cSJonas Aaberg } 1426b04c530cSJonas Aaberg printk(KERN_CONT "\n"); 1427b04c530cSJonas Aaberg } else { 1428b04c530cSJonas Aaberg printk(KERN_CONT " None\n"); 1429b04c530cSJonas Aaberg } 1430e5c238c3SMattias Wallin 143162579266SRabin Vincent if (plat && plat->init) 143262579266SRabin Vincent plat->init(ab8500); 1433f04a9d8aSRajkumar Kasirajan if (is_ab9540(ab8500)) { 1434f04a9d8aSRajkumar Kasirajan ret = get_register_interruptible(ab8500, AB8500_CHARGER, 1435f04a9d8aSRajkumar Kasirajan AB8500_CH_USBCH_STAT1_REG, &value); 1436f04a9d8aSRajkumar Kasirajan if (ret < 0) 1437f04a9d8aSRajkumar Kasirajan return ret; 1438f04a9d8aSRajkumar Kasirajan if ((value & VBUS_DET_DBNC1) && (value & VBUS_DET_DBNC100)) 1439f04a9d8aSRajkumar Kasirajan ab8500_override_turn_on_stat(~AB8500_POW_KEY_1_ON, 1440f04a9d8aSRajkumar Kasirajan AB8500_VBUS_DET); 1441f04a9d8aSRajkumar Kasirajan } 144262579266SRabin Vincent 144362579266SRabin Vincent /* Clear and mask all interrupts */ 14442ced445eSLinus Walleij for (i = 0; i < ab8500->mask_size; i++) { 14450f620837SLinus Walleij /* 14460f620837SLinus Walleij * Interrupt register 12 doesn't exist prior to AB8500 version 14470f620837SLinus Walleij * 2.0 14480f620837SLinus Walleij */ 14490f620837SLinus Walleij if (ab8500->irq_reg_offset[i] == 11 && 14500f620837SLinus Walleij is_ab8500_1p1_or_earlier(ab8500)) 145192d50a41SMattias Wallin continue; 145262579266SRabin Vincent 145347c16975SMattias Wallin get_register_interruptible(ab8500, AB8500_INTERRUPT, 14542ced445eSLinus Walleij AB8500_IT_LATCH1_REG + ab8500->irq_reg_offset[i], 145592d50a41SMattias Wallin &value); 145647c16975SMattias Wallin set_register_interruptible(ab8500, AB8500_INTERRUPT, 14572ced445eSLinus Walleij AB8500_IT_MASK1_REG + ab8500->irq_reg_offset[i], 0xff); 145862579266SRabin Vincent } 145962579266SRabin Vincent 146047c16975SMattias Wallin ret = abx500_register_ops(ab8500->dev, &ab8500_ops); 146147c16975SMattias Wallin if (ret) 14628c4203cbSLee Jones return ret; 146347c16975SMattias Wallin 14642ced445eSLinus Walleij for (i = 0; i < ab8500->mask_size; i++) 146562579266SRabin Vincent ab8500->mask[i] = ab8500->oldmask[i] = 0xff; 146662579266SRabin Vincent 146706e589efSLee Jones ret = ab8500_irq_init(ab8500, np); 146862579266SRabin Vincent if (ret) 14698c4203cbSLee Jones return ret; 147062579266SRabin Vincent 14717ccfe9b1SMichel JAOUEN /* Activate this feature only in ab9540 */ 14727ccfe9b1SMichel JAOUEN /* till tests are done on ab8500 1p2 or later*/ 147306e589efSLee Jones if (is_ab9540(ab8500)) { 14748c4203cbSLee Jones ret = devm_request_threaded_irq(&pdev->dev, ab8500->irq, NULL, 14757ccfe9b1SMichel JAOUEN ab8500_hierarchical_irq, 14767ccfe9b1SMichel JAOUEN IRQF_ONESHOT | IRQF_NO_SUSPEND, 14777ccfe9b1SMichel JAOUEN "ab8500", ab8500); 147806e589efSLee Jones } 147906e589efSLee Jones else { 14808c4203cbSLee Jones ret = devm_request_threaded_irq(&pdev->dev, ab8500->irq, NULL, 14817ccfe9b1SMichel JAOUEN ab8500_irq, 14824f079985SMattias Wallin IRQF_ONESHOT | IRQF_NO_SUSPEND, 14834f079985SMattias Wallin "ab8500", ab8500); 148462579266SRabin Vincent if (ret) 14858c4203cbSLee Jones return ret; 148662579266SRabin Vincent } 148762579266SRabin Vincent 1488d6255529SLinus Walleij ret = mfd_add_devices(ab8500->dev, 0, abx500_common_devs, 1489d6255529SLinus Walleij ARRAY_SIZE(abx500_common_devs), NULL, 149055692af5SMark Brown ab8500->irq_base, ab8500->domain); 1491d6255529SLinus Walleij if (ret) 14928c4203cbSLee Jones return ret; 1493d6255529SLinus Walleij 1494d6255529SLinus Walleij if (is_ab9540(ab8500)) 1495d6255529SLinus Walleij ret = mfd_add_devices(ab8500->dev, 0, ab9540_devs, 1496d6255529SLinus Walleij ARRAY_SIZE(ab9540_devs), NULL, 149755692af5SMark Brown ab8500->irq_base, ab8500->domain); 1498d6255529SLinus Walleij else 1499549931f9SSundar R Iyer ret = mfd_add_devices(ab8500->dev, 0, ab8500_devs, 150044f72e53SVirupax Sadashivpetimath ARRAY_SIZE(ab8500_devs), NULL, 150155692af5SMark Brown ab8500->irq_base, ab8500->domain); 15026bc4a568SLee Jones if (ret) 15038c4203cbSLee Jones return ret; 150444f72e53SVirupax Sadashivpetimath 150544f72e53SVirupax Sadashivpetimath if (is_ab9540(ab8500) || is_ab8505(ab8500)) 150644f72e53SVirupax Sadashivpetimath ret = mfd_add_devices(ab8500->dev, 0, ab9540_ab8505_devs, 150744f72e53SVirupax Sadashivpetimath ARRAY_SIZE(ab9540_ab8505_devs), NULL, 150855692af5SMark Brown ab8500->irq_base, ab8500->domain); 150962579266SRabin Vincent if (ret) 15108c4203cbSLee Jones return ret; 151162579266SRabin Vincent 15126ef9418cSRickard Andersson if (!no_bm) { 15136ef9418cSRickard Andersson /* Add battery management devices */ 15146ef9418cSRickard Andersson ret = mfd_add_devices(ab8500->dev, 0, ab8500_bm_devs, 15156ef9418cSRickard Andersson ARRAY_SIZE(ab8500_bm_devs), NULL, 151655692af5SMark Brown ab8500->irq_base, ab8500->domain); 15176ef9418cSRickard Andersson if (ret) 15186ef9418cSRickard Andersson dev_err(ab8500->dev, "error adding bm devices\n"); 15196ef9418cSRickard Andersson } 15206ef9418cSRickard Andersson 1521d6255529SLinus Walleij if (is_ab9540(ab8500)) 1522d6255529SLinus Walleij ret = sysfs_create_group(&ab8500->dev->kobj, 1523d6255529SLinus Walleij &ab9540_attr_group); 1524d6255529SLinus Walleij else 1525d6255529SLinus Walleij ret = sysfs_create_group(&ab8500->dev->kobj, 1526d6255529SLinus Walleij &ab8500_attr_group); 1527cca69b67SMattias Wallin if (ret) 1528cca69b67SMattias Wallin dev_err(ab8500->dev, "error creating sysfs entries\n"); 152906e589efSLee Jones 153062579266SRabin Vincent return ret; 153162579266SRabin Vincent } 153262579266SRabin Vincent 15334740f73fSBill Pemberton static int ab8500_remove(struct platform_device *pdev) 153462579266SRabin Vincent { 1535d28f1db8SLee Jones struct ab8500 *ab8500 = platform_get_drvdata(pdev); 1536d28f1db8SLee Jones 1537d6255529SLinus Walleij if (is_ab9540(ab8500)) 1538d6255529SLinus Walleij sysfs_remove_group(&ab8500->dev->kobj, &ab9540_attr_group); 1539d6255529SLinus Walleij else 1540cca69b67SMattias Wallin sysfs_remove_group(&ab8500->dev->kobj, &ab8500_attr_group); 154106e589efSLee Jones 154262579266SRabin Vincent mfd_remove_devices(ab8500->dev); 154362579266SRabin Vincent 154462579266SRabin Vincent return 0; 154562579266SRabin Vincent } 154662579266SRabin Vincent 1547d28f1db8SLee Jones static const struct platform_device_id ab8500_id[] = { 1548d28f1db8SLee Jones { "ab8500-core", AB8500_VERSION_AB8500 }, 1549d28f1db8SLee Jones { "ab8505-i2c", AB8500_VERSION_AB8505 }, 1550d28f1db8SLee Jones { "ab9540-i2c", AB8500_VERSION_AB9540 }, 1551d28f1db8SLee Jones { "ab8540-i2c", AB8500_VERSION_AB8540 }, 1552d28f1db8SLee Jones { } 1553d28f1db8SLee Jones }; 1554d28f1db8SLee Jones 1555d28f1db8SLee Jones static struct platform_driver ab8500_core_driver = { 1556d28f1db8SLee Jones .driver = { 1557d28f1db8SLee Jones .name = "ab8500-core", 1558d28f1db8SLee Jones .owner = THIS_MODULE, 1559d28f1db8SLee Jones }, 1560d28f1db8SLee Jones .probe = ab8500_probe, 156184449216SBill Pemberton .remove = ab8500_remove, 1562d28f1db8SLee Jones .id_table = ab8500_id, 1563d28f1db8SLee Jones }; 1564d28f1db8SLee Jones 1565d28f1db8SLee Jones static int __init ab8500_core_init(void) 1566d28f1db8SLee Jones { 1567d28f1db8SLee Jones return platform_driver_register(&ab8500_core_driver); 1568d28f1db8SLee Jones } 1569d28f1db8SLee Jones 1570d28f1db8SLee Jones static void __exit ab8500_core_exit(void) 1571d28f1db8SLee Jones { 1572d28f1db8SLee Jones platform_driver_unregister(&ab8500_core_driver); 1573d28f1db8SLee Jones } 1574ba7cbc3eSLee Jones core_initcall(ab8500_core_init); 1575d28f1db8SLee Jones module_exit(ab8500_core_exit); 1576d28f1db8SLee Jones 1577adceed62SMattias Wallin MODULE_AUTHOR("Mattias Wallin, Srinidhi Kasagar, Rabin Vincent"); 157862579266SRabin Vincent MODULE_DESCRIPTION("AB8500 MFD core"); 157962579266SRabin Vincent MODULE_LICENSE("GPL v2"); 1580