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 114f04a9d8aSRajkumar Kasirajan #define AB8500_CH_USBCH_STAT1_REG 0x02 115f04a9d8aSRajkumar Kasirajan #define VBUS_DET_DBNC100 0x02 116f04a9d8aSRajkumar Kasirajan #define VBUS_DET_DBNC1 0x01 117f04a9d8aSRajkumar Kasirajan 118f04a9d8aSRajkumar Kasirajan static DEFINE_SPINLOCK(on_stat_lock); 119f04a9d8aSRajkumar Kasirajan static u8 turn_on_stat_mask = 0xFF; 120f04a9d8aSRajkumar Kasirajan static u8 turn_on_stat_set; 1216ef9418cSRickard Andersson static bool no_bm; /* No battery management */ 1226ef9418cSRickard Andersson module_param(no_bm, bool, S_IRUGO); 1236ef9418cSRickard Andersson 124d6255529SLinus Walleij #define AB9540_MODEM_CTRL2_REG 0x23 125d6255529SLinus Walleij #define AB9540_MODEM_CTRL2_SWDBBRSTN_BIT BIT(2) 126d6255529SLinus Walleij 12762579266SRabin Vincent /* 12862579266SRabin Vincent * Map interrupt numbers to the LATCH and MASK register offsets, Interrupt 1292ced445eSLinus Walleij * numbers are indexed into this array with (num / 8). The interupts are 1302ced445eSLinus Walleij * defined in linux/mfd/ab8500.h 13162579266SRabin Vincent * 13262579266SRabin Vincent * This is one off from the register names, i.e. AB8500_IT_MASK1_REG is at 13362579266SRabin Vincent * offset 0. 13462579266SRabin Vincent */ 1352ced445eSLinus Walleij /* AB8500 support */ 13662579266SRabin Vincent static const int ab8500_irq_regoffset[AB8500_NUM_IRQ_REGS] = { 13792d50a41SMattias Wallin 0, 1, 2, 3, 4, 6, 7, 8, 9, 11, 18, 19, 20, 21, 13862579266SRabin Vincent }; 13962579266SRabin Vincent 140d6255529SLinus Walleij /* AB9540 support */ 141d6255529SLinus Walleij static const int ab9540_irq_regoffset[AB9540_NUM_IRQ_REGS] = { 142d6255529SLinus Walleij 0, 1, 2, 3, 4, 6, 7, 8, 9, 11, 18, 19, 20, 21, 12, 13, 24, 143d6255529SLinus Walleij }; 144d6255529SLinus Walleij 1450f620837SLinus Walleij static const char ab8500_version_str[][7] = { 1460f620837SLinus Walleij [AB8500_VERSION_AB8500] = "AB8500", 1470f620837SLinus Walleij [AB8500_VERSION_AB8505] = "AB8505", 1480f620837SLinus Walleij [AB8500_VERSION_AB9540] = "AB9540", 1490f620837SLinus Walleij [AB8500_VERSION_AB8540] = "AB8540", 1500f620837SLinus Walleij }; 1510f620837SLinus Walleij 152822672a7SLee Jones static int ab8500_prcmu_write(struct ab8500 *ab8500, u16 addr, u8 data) 153d28f1db8SLee Jones { 154d28f1db8SLee Jones int ret; 155d28f1db8SLee Jones 156d28f1db8SLee Jones ret = prcmu_abb_write((u8)(addr >> 8), (u8)(addr & 0xFF), &data, 1); 157d28f1db8SLee Jones if (ret < 0) 158d28f1db8SLee Jones dev_err(ab8500->dev, "prcmu i2c error %d\n", ret); 159d28f1db8SLee Jones return ret; 160d28f1db8SLee Jones } 161d28f1db8SLee Jones 162822672a7SLee Jones static int ab8500_prcmu_write_masked(struct ab8500 *ab8500, u16 addr, u8 mask, 163d28f1db8SLee Jones u8 data) 164d28f1db8SLee Jones { 165d28f1db8SLee Jones int ret; 166d28f1db8SLee Jones 167d28f1db8SLee Jones ret = prcmu_abb_write_masked((u8)(addr >> 8), (u8)(addr & 0xFF), &data, 168d28f1db8SLee Jones &mask, 1); 169d28f1db8SLee Jones if (ret < 0) 170d28f1db8SLee Jones dev_err(ab8500->dev, "prcmu i2c error %d\n", ret); 171d28f1db8SLee Jones return ret; 172d28f1db8SLee Jones } 173d28f1db8SLee Jones 174822672a7SLee Jones static int ab8500_prcmu_read(struct ab8500 *ab8500, u16 addr) 175d28f1db8SLee Jones { 176d28f1db8SLee Jones int ret; 177d28f1db8SLee Jones u8 data; 178d28f1db8SLee Jones 179d28f1db8SLee Jones ret = prcmu_abb_read((u8)(addr >> 8), (u8)(addr & 0xFF), &data, 1); 180d28f1db8SLee Jones if (ret < 0) { 181d28f1db8SLee Jones dev_err(ab8500->dev, "prcmu i2c error %d\n", ret); 182d28f1db8SLee Jones return ret; 183d28f1db8SLee Jones } 184d28f1db8SLee Jones return (int)data; 185d28f1db8SLee Jones } 186d28f1db8SLee Jones 18747c16975SMattias Wallin static int ab8500_get_chip_id(struct device *dev) 18847c16975SMattias Wallin { 1896bce7bf1SMattias Wallin struct ab8500 *ab8500; 1906bce7bf1SMattias Wallin 1916bce7bf1SMattias Wallin if (!dev) 1926bce7bf1SMattias Wallin return -EINVAL; 1936bce7bf1SMattias Wallin ab8500 = dev_get_drvdata(dev->parent); 1946bce7bf1SMattias Wallin return ab8500 ? (int)ab8500->chip_id : -EINVAL; 19547c16975SMattias Wallin } 19647c16975SMattias Wallin 19747c16975SMattias Wallin static int set_register_interruptible(struct ab8500 *ab8500, u8 bank, 19847c16975SMattias Wallin u8 reg, u8 data) 19962579266SRabin Vincent { 20062579266SRabin Vincent int ret; 20147c16975SMattias Wallin /* 20247c16975SMattias Wallin * Put the u8 bank and u8 register together into a an u16. 20347c16975SMattias Wallin * The bank on higher 8 bits and register in lower 8 bits. 20447c16975SMattias Wallin * */ 20547c16975SMattias Wallin u16 addr = ((u16)bank) << 8 | reg; 20662579266SRabin Vincent 20762579266SRabin Vincent dev_vdbg(ab8500->dev, "wr: addr %#x <= %#x\n", addr, data); 20862579266SRabin Vincent 209392cbd1eSRabin Vincent mutex_lock(&ab8500->lock); 21047c16975SMattias Wallin 21147c16975SMattias Wallin ret = ab8500->write(ab8500, addr, data); 21247c16975SMattias Wallin if (ret < 0) 21347c16975SMattias Wallin dev_err(ab8500->dev, "failed to write reg %#x: %d\n", 21447c16975SMattias Wallin addr, ret); 21547c16975SMattias Wallin mutex_unlock(&ab8500->lock); 21647c16975SMattias Wallin 21747c16975SMattias Wallin return ret; 21847c16975SMattias Wallin } 21947c16975SMattias Wallin 22047c16975SMattias Wallin static int ab8500_set_register(struct device *dev, u8 bank, 22147c16975SMattias Wallin u8 reg, u8 value) 22247c16975SMattias Wallin { 223112a80d2SJonas Aaberg int ret; 22447c16975SMattias Wallin struct ab8500 *ab8500 = dev_get_drvdata(dev->parent); 22547c16975SMattias Wallin 226112a80d2SJonas Aaberg atomic_inc(&ab8500->transfer_ongoing); 227112a80d2SJonas Aaberg ret = set_register_interruptible(ab8500, bank, reg, value); 228112a80d2SJonas Aaberg atomic_dec(&ab8500->transfer_ongoing); 229112a80d2SJonas Aaberg return ret; 23047c16975SMattias Wallin } 23147c16975SMattias Wallin 23247c16975SMattias Wallin static int get_register_interruptible(struct ab8500 *ab8500, u8 bank, 23347c16975SMattias Wallin u8 reg, u8 *value) 23447c16975SMattias Wallin { 23547c16975SMattias Wallin int ret; 23647c16975SMattias Wallin /* put the u8 bank and u8 reg together into a an u16. 23747c16975SMattias Wallin * bank on higher 8 bits and reg in lower */ 23847c16975SMattias Wallin u16 addr = ((u16)bank) << 8 | reg; 23947c16975SMattias Wallin 240392cbd1eSRabin Vincent mutex_lock(&ab8500->lock); 24147c16975SMattias Wallin 24247c16975SMattias Wallin ret = ab8500->read(ab8500, addr); 24347c16975SMattias Wallin if (ret < 0) 24447c16975SMattias Wallin dev_err(ab8500->dev, "failed to read reg %#x: %d\n", 24547c16975SMattias Wallin addr, ret); 24647c16975SMattias Wallin else 24747c16975SMattias Wallin *value = ret; 24847c16975SMattias Wallin 24947c16975SMattias Wallin mutex_unlock(&ab8500->lock); 25047c16975SMattias Wallin dev_vdbg(ab8500->dev, "rd: addr %#x => data %#x\n", addr, ret); 25147c16975SMattias Wallin 25247c16975SMattias Wallin return ret; 25347c16975SMattias Wallin } 25447c16975SMattias Wallin 25547c16975SMattias Wallin static int ab8500_get_register(struct device *dev, u8 bank, 25647c16975SMattias Wallin u8 reg, u8 *value) 25747c16975SMattias Wallin { 258112a80d2SJonas Aaberg int ret; 25947c16975SMattias Wallin struct ab8500 *ab8500 = dev_get_drvdata(dev->parent); 26047c16975SMattias Wallin 261112a80d2SJonas Aaberg atomic_inc(&ab8500->transfer_ongoing); 262112a80d2SJonas Aaberg ret = get_register_interruptible(ab8500, bank, reg, value); 263112a80d2SJonas Aaberg atomic_dec(&ab8500->transfer_ongoing); 264112a80d2SJonas Aaberg return ret; 26547c16975SMattias Wallin } 26647c16975SMattias Wallin 26747c16975SMattias Wallin static int mask_and_set_register_interruptible(struct ab8500 *ab8500, u8 bank, 26847c16975SMattias Wallin u8 reg, u8 bitmask, u8 bitvalues) 26947c16975SMattias Wallin { 27047c16975SMattias Wallin int ret; 27147c16975SMattias Wallin /* put the u8 bank and u8 reg together into a an u16. 27247c16975SMattias Wallin * bank on higher 8 bits and reg in lower */ 27347c16975SMattias Wallin u16 addr = ((u16)bank) << 8 | reg; 27447c16975SMattias Wallin 275392cbd1eSRabin Vincent mutex_lock(&ab8500->lock); 27647c16975SMattias Wallin 277bc628fd1SMattias Nilsson if (ab8500->write_masked == NULL) { 278bc628fd1SMattias Nilsson u8 data; 279bc628fd1SMattias Nilsson 28047c16975SMattias Wallin ret = ab8500->read(ab8500, addr); 28147c16975SMattias Wallin if (ret < 0) { 28247c16975SMattias Wallin dev_err(ab8500->dev, "failed to read reg %#x: %d\n", 28347c16975SMattias Wallin addr, ret); 28447c16975SMattias Wallin goto out; 28547c16975SMattias Wallin } 28647c16975SMattias Wallin 28747c16975SMattias Wallin data = (u8)ret; 28847c16975SMattias Wallin data = (~bitmask & data) | (bitmask & bitvalues); 28947c16975SMattias Wallin 29062579266SRabin Vincent ret = ab8500->write(ab8500, addr, data); 29162579266SRabin Vincent if (ret < 0) 29262579266SRabin Vincent dev_err(ab8500->dev, "failed to write reg %#x: %d\n", 29362579266SRabin Vincent addr, ret); 29462579266SRabin Vincent 295bc628fd1SMattias Nilsson dev_vdbg(ab8500->dev, "mask: addr %#x => data %#x\n", addr, 296bc628fd1SMattias Nilsson data); 297bc628fd1SMattias Nilsson goto out; 298bc628fd1SMattias Nilsson } 299bc628fd1SMattias Nilsson ret = ab8500->write_masked(ab8500, addr, bitmask, bitvalues); 300bc628fd1SMattias Nilsson if (ret < 0) 301bc628fd1SMattias Nilsson dev_err(ab8500->dev, "failed to modify reg %#x: %d\n", addr, 302bc628fd1SMattias Nilsson ret); 30362579266SRabin Vincent out: 30462579266SRabin Vincent mutex_unlock(&ab8500->lock); 30562579266SRabin Vincent return ret; 30662579266SRabin Vincent } 30747c16975SMattias Wallin 30847c16975SMattias Wallin static int ab8500_mask_and_set_register(struct device *dev, 30947c16975SMattias Wallin u8 bank, u8 reg, u8 bitmask, u8 bitvalues) 31047c16975SMattias Wallin { 311112a80d2SJonas Aaberg int ret; 31247c16975SMattias Wallin struct ab8500 *ab8500 = dev_get_drvdata(dev->parent); 31347c16975SMattias Wallin 314112a80d2SJonas Aaberg atomic_inc(&ab8500->transfer_ongoing); 315112a80d2SJonas Aaberg ret= mask_and_set_register_interruptible(ab8500, bank, reg, 31647c16975SMattias Wallin bitmask, bitvalues); 317112a80d2SJonas Aaberg atomic_dec(&ab8500->transfer_ongoing); 318112a80d2SJonas Aaberg return ret; 31947c16975SMattias Wallin } 32047c16975SMattias Wallin 32147c16975SMattias Wallin static struct abx500_ops ab8500_ops = { 32247c16975SMattias Wallin .get_chip_id = ab8500_get_chip_id, 32347c16975SMattias Wallin .get_register = ab8500_get_register, 32447c16975SMattias Wallin .set_register = ab8500_set_register, 32547c16975SMattias Wallin .get_register_page = NULL, 32647c16975SMattias Wallin .set_register_page = NULL, 32747c16975SMattias Wallin .mask_and_set_register = ab8500_mask_and_set_register, 32847c16975SMattias Wallin .event_registers_startup_state_get = NULL, 32947c16975SMattias Wallin .startup_irq_enabled = NULL, 3301d843a6cSMian Yousaf Kaukab .dump_all_banks = ab8500_dump_all_banks, 33147c16975SMattias Wallin }; 33262579266SRabin Vincent 3339505a0a0SMark Brown static void ab8500_irq_lock(struct irq_data *data) 33462579266SRabin Vincent { 3359505a0a0SMark Brown struct ab8500 *ab8500 = irq_data_get_irq_chip_data(data); 33662579266SRabin Vincent 33762579266SRabin Vincent mutex_lock(&ab8500->irq_lock); 338112a80d2SJonas Aaberg atomic_inc(&ab8500->transfer_ongoing); 33962579266SRabin Vincent } 34062579266SRabin Vincent 3419505a0a0SMark Brown static void ab8500_irq_sync_unlock(struct irq_data *data) 34262579266SRabin Vincent { 3439505a0a0SMark Brown struct ab8500 *ab8500 = irq_data_get_irq_chip_data(data); 34462579266SRabin Vincent int i; 34562579266SRabin Vincent 3462ced445eSLinus Walleij for (i = 0; i < ab8500->mask_size; i++) { 34762579266SRabin Vincent u8 old = ab8500->oldmask[i]; 34862579266SRabin Vincent u8 new = ab8500->mask[i]; 34962579266SRabin Vincent int reg; 35062579266SRabin Vincent 35162579266SRabin Vincent if (new == old) 35262579266SRabin Vincent continue; 35362579266SRabin Vincent 3540f620837SLinus Walleij /* 3550f620837SLinus Walleij * Interrupt register 12 doesn't exist prior to AB8500 version 3560f620837SLinus Walleij * 2.0 3570f620837SLinus Walleij */ 3580f620837SLinus Walleij if (ab8500->irq_reg_offset[i] == 11 && 3590f620837SLinus Walleij is_ab8500_1p1_or_earlier(ab8500)) 36092d50a41SMattias Wallin continue; 36192d50a41SMattias Wallin 36262579266SRabin Vincent ab8500->oldmask[i] = new; 36362579266SRabin Vincent 3642ced445eSLinus Walleij reg = AB8500_IT_MASK1_REG + ab8500->irq_reg_offset[i]; 36547c16975SMattias Wallin set_register_interruptible(ab8500, AB8500_INTERRUPT, reg, new); 36662579266SRabin Vincent } 367112a80d2SJonas Aaberg atomic_dec(&ab8500->transfer_ongoing); 36862579266SRabin Vincent mutex_unlock(&ab8500->irq_lock); 36962579266SRabin Vincent } 37062579266SRabin Vincent 3719505a0a0SMark Brown static void ab8500_irq_mask(struct irq_data *data) 37262579266SRabin Vincent { 3739505a0a0SMark Brown struct ab8500 *ab8500 = irq_data_get_irq_chip_data(data); 37406e589efSLee Jones int offset = data->hwirq; 37562579266SRabin Vincent int index = offset / 8; 37662579266SRabin Vincent int mask = 1 << (offset % 8); 37762579266SRabin Vincent 37862579266SRabin Vincent ab8500->mask[index] |= mask; 3799c677b9bSLee Jones 3809c677b9bSLee Jones /* The AB8500 GPIOs have two interrupts each (rising & falling). */ 3819c677b9bSLee Jones if (offset >= AB8500_INT_GPIO6R && offset <= AB8500_INT_GPIO41R) 3829c677b9bSLee Jones ab8500->mask[index + 2] |= mask; 3839c677b9bSLee Jones if (offset >= AB9540_INT_GPIO50R && offset <= AB9540_INT_GPIO54R) 3849c677b9bSLee Jones ab8500->mask[index + 1] |= mask; 3859c677b9bSLee Jones if (offset == AB8540_INT_GPIO43R || offset == AB8540_INT_GPIO44R) 386e2ddf46aSLinus Walleij /* Here the falling IRQ is one bit lower */ 387e2ddf46aSLinus Walleij ab8500->mask[index] |= (mask << 1); 38862579266SRabin Vincent } 38962579266SRabin Vincent 3909505a0a0SMark Brown static void ab8500_irq_unmask(struct irq_data *data) 39162579266SRabin Vincent { 3929505a0a0SMark Brown struct ab8500 *ab8500 = irq_data_get_irq_chip_data(data); 3939c677b9bSLee Jones unsigned int type = irqd_get_trigger_type(data); 39406e589efSLee Jones int offset = data->hwirq; 39562579266SRabin Vincent int index = offset / 8; 39662579266SRabin Vincent int mask = 1 << (offset % 8); 39762579266SRabin Vincent 3989c677b9bSLee Jones if (type & IRQ_TYPE_EDGE_RISING) 39962579266SRabin Vincent ab8500->mask[index] &= ~mask; 4009c677b9bSLee Jones 4019c677b9bSLee Jones /* The AB8500 GPIOs have two interrupts each (rising & falling). */ 4029c677b9bSLee Jones if (type & IRQ_TYPE_EDGE_FALLING) { 4039c677b9bSLee Jones if (offset >= AB8500_INT_GPIO6R && offset <= AB8500_INT_GPIO41R) 4049c677b9bSLee Jones ab8500->mask[index + 2] &= ~mask; 4059c677b9bSLee Jones else if (offset >= AB9540_INT_GPIO50R && offset <= AB9540_INT_GPIO54R) 4069c677b9bSLee Jones ab8500->mask[index + 1] &= ~mask; 4079c677b9bSLee Jones else if (offset == AB8540_INT_GPIO43R || offset == AB8540_INT_GPIO44R) 408e2ddf46aSLinus Walleij /* Here the falling IRQ is one bit lower */ 409e2ddf46aSLinus Walleij ab8500->mask[index] &= ~(mask << 1); 4109c677b9bSLee Jones else 4119c677b9bSLee Jones ab8500->mask[index] &= ~mask; 412e2ddf46aSLinus Walleij } else { 4139c677b9bSLee Jones /* Satisfies the case where type is not set. */ 41462579266SRabin Vincent ab8500->mask[index] &= ~mask; 41562579266SRabin Vincent } 416e2ddf46aSLinus Walleij } 41762579266SRabin Vincent 41840f6e5a2SLee Jones static int ab8500_irq_set_type(struct irq_data *data, unsigned int type) 41940f6e5a2SLee Jones { 42040f6e5a2SLee Jones return 0; 42162579266SRabin Vincent } 42262579266SRabin Vincent 42362579266SRabin Vincent static struct irq_chip ab8500_irq_chip = { 42462579266SRabin Vincent .name = "ab8500", 4259505a0a0SMark Brown .irq_bus_lock = ab8500_irq_lock, 4269505a0a0SMark Brown .irq_bus_sync_unlock = ab8500_irq_sync_unlock, 4279505a0a0SMark Brown .irq_mask = ab8500_irq_mask, 428e6f9306eSVirupax Sadashivpetimath .irq_disable = ab8500_irq_mask, 4299505a0a0SMark Brown .irq_unmask = ab8500_irq_unmask, 43040f6e5a2SLee Jones .irq_set_type = ab8500_irq_set_type, 43162579266SRabin Vincent }; 43262579266SRabin Vincent 4337ccfe9b1SMichel JAOUEN static int ab8500_handle_hierarchical_line(struct ab8500 *ab8500, 4347ccfe9b1SMichel JAOUEN int latch_offset, u8 latch_val) 4357ccfe9b1SMichel JAOUEN { 4367ccfe9b1SMichel JAOUEN int int_bit = __ffs(latch_val); 4377ccfe9b1SMichel JAOUEN int line, i; 4387ccfe9b1SMichel JAOUEN 4397ccfe9b1SMichel JAOUEN do { 4407ccfe9b1SMichel JAOUEN int_bit = __ffs(latch_val); 4417ccfe9b1SMichel JAOUEN 4427ccfe9b1SMichel JAOUEN for (i = 0; i < ab8500->mask_size; i++) 4437ccfe9b1SMichel JAOUEN if (ab8500->irq_reg_offset[i] == latch_offset) 4447ccfe9b1SMichel JAOUEN break; 4457ccfe9b1SMichel JAOUEN 4467ccfe9b1SMichel JAOUEN if (i >= ab8500->mask_size) { 4477ccfe9b1SMichel JAOUEN dev_err(ab8500->dev, "Register offset 0x%2x not declared\n", 4487ccfe9b1SMichel JAOUEN latch_offset); 4497ccfe9b1SMichel JAOUEN return -ENXIO; 4507ccfe9b1SMichel JAOUEN } 4517ccfe9b1SMichel JAOUEN 4527ccfe9b1SMichel JAOUEN line = (i << 3) + int_bit; 4537ccfe9b1SMichel JAOUEN latch_val &= ~(1 << int_bit); 4547ccfe9b1SMichel JAOUEN 455e2ddf46aSLinus Walleij /* 456e2ddf46aSLinus Walleij * This handles the falling edge hwirqs from the GPIO 457e2ddf46aSLinus Walleij * lines. Route them back to the line registered for the 458e2ddf46aSLinus Walleij * rising IRQ, as this is merely a flag for the same IRQ 459e2ddf46aSLinus Walleij * in linux terms. 460e2ddf46aSLinus Walleij */ 461e2ddf46aSLinus Walleij if (line >= AB8500_INT_GPIO6F && line <= AB8500_INT_GPIO41F) 462e2ddf46aSLinus Walleij line -= 16; 463e2ddf46aSLinus Walleij if (line >= AB9540_INT_GPIO50F && line <= AB9540_INT_GPIO54F) 464e2ddf46aSLinus Walleij line -= 8; 465e2ddf46aSLinus Walleij if (line == AB8540_INT_GPIO43F || line == AB8540_INT_GPIO44F) 466e2ddf46aSLinus Walleij line += 1; 467e2ddf46aSLinus Walleij 4687ccfe9b1SMichel JAOUEN handle_nested_irq(ab8500->irq_base + line); 4697ccfe9b1SMichel JAOUEN } while (latch_val); 4707ccfe9b1SMichel JAOUEN 4717ccfe9b1SMichel JAOUEN return 0; 4727ccfe9b1SMichel JAOUEN } 4737ccfe9b1SMichel JAOUEN 4747ccfe9b1SMichel JAOUEN static int ab8500_handle_hierarchical_latch(struct ab8500 *ab8500, 4757ccfe9b1SMichel JAOUEN int hier_offset, u8 hier_val) 4767ccfe9b1SMichel JAOUEN { 4777ccfe9b1SMichel JAOUEN int latch_bit, status; 4787ccfe9b1SMichel JAOUEN u8 latch_offset, latch_val; 4797ccfe9b1SMichel JAOUEN 4807ccfe9b1SMichel JAOUEN do { 4817ccfe9b1SMichel JAOUEN latch_bit = __ffs(hier_val); 4827ccfe9b1SMichel JAOUEN latch_offset = (hier_offset << 3) + latch_bit; 4837ccfe9b1SMichel JAOUEN 4847ccfe9b1SMichel JAOUEN /* Fix inconsistent ITFromLatch25 bit mapping... */ 4857ccfe9b1SMichel JAOUEN if (unlikely(latch_offset == 17)) 4867ccfe9b1SMichel JAOUEN latch_offset = 24; 4877ccfe9b1SMichel JAOUEN 4887ccfe9b1SMichel JAOUEN status = get_register_interruptible(ab8500, 4897ccfe9b1SMichel JAOUEN AB8500_INTERRUPT, 4907ccfe9b1SMichel JAOUEN AB8500_IT_LATCH1_REG + latch_offset, 4917ccfe9b1SMichel JAOUEN &latch_val); 4927ccfe9b1SMichel JAOUEN if (status < 0 || latch_val == 0) 4937ccfe9b1SMichel JAOUEN goto discard; 4947ccfe9b1SMichel JAOUEN 4957ccfe9b1SMichel JAOUEN status = ab8500_handle_hierarchical_line(ab8500, 4967ccfe9b1SMichel JAOUEN latch_offset, latch_val); 4977ccfe9b1SMichel JAOUEN if (status < 0) 4987ccfe9b1SMichel JAOUEN return status; 4997ccfe9b1SMichel JAOUEN discard: 5007ccfe9b1SMichel JAOUEN hier_val &= ~(1 << latch_bit); 5017ccfe9b1SMichel JAOUEN } while (hier_val); 5027ccfe9b1SMichel JAOUEN 5037ccfe9b1SMichel JAOUEN return 0; 5047ccfe9b1SMichel JAOUEN } 5057ccfe9b1SMichel JAOUEN 5067ccfe9b1SMichel JAOUEN static irqreturn_t ab8500_hierarchical_irq(int irq, void *dev) 5077ccfe9b1SMichel JAOUEN { 5087ccfe9b1SMichel JAOUEN struct ab8500 *ab8500 = dev; 5097ccfe9b1SMichel JAOUEN u8 i; 5107ccfe9b1SMichel JAOUEN 5117ccfe9b1SMichel JAOUEN dev_vdbg(ab8500->dev, "interrupt\n"); 5127ccfe9b1SMichel JAOUEN 5137ccfe9b1SMichel JAOUEN /* Hierarchical interrupt version */ 5147ccfe9b1SMichel JAOUEN for (i = 0; i < AB8500_IT_LATCHHIER_NUM; i++) { 5157ccfe9b1SMichel JAOUEN int status; 5167ccfe9b1SMichel JAOUEN u8 hier_val; 5177ccfe9b1SMichel JAOUEN 5187ccfe9b1SMichel JAOUEN status = get_register_interruptible(ab8500, AB8500_INTERRUPT, 5197ccfe9b1SMichel JAOUEN AB8500_IT_LATCHHIER1_REG + i, &hier_val); 5207ccfe9b1SMichel JAOUEN if (status < 0 || hier_val == 0) 5217ccfe9b1SMichel JAOUEN continue; 5227ccfe9b1SMichel JAOUEN 5237ccfe9b1SMichel JAOUEN status = ab8500_handle_hierarchical_latch(ab8500, i, hier_val); 5247ccfe9b1SMichel JAOUEN if (status < 0) 5257ccfe9b1SMichel JAOUEN break; 5267ccfe9b1SMichel JAOUEN } 5277ccfe9b1SMichel JAOUEN return IRQ_HANDLED; 5287ccfe9b1SMichel JAOUEN } 5297ccfe9b1SMichel JAOUEN 53080633f05SLee Jones /** 53180633f05SLee Jones * ab8500_irq_get_virq(): Map an interrupt on a chip to a virtual IRQ 53280633f05SLee Jones * 53380633f05SLee Jones * @ab8500: ab8500_irq controller to operate on. 53480633f05SLee Jones * @irq: index of the interrupt requested in the chip IRQs 53580633f05SLee Jones * 53680633f05SLee Jones * Useful for drivers to request their own IRQs. 53780633f05SLee Jones */ 53880633f05SLee Jones static int ab8500_irq_get_virq(struct ab8500 *ab8500, int irq) 53980633f05SLee Jones { 54080633f05SLee Jones if (!ab8500) 54180633f05SLee Jones return -EINVAL; 54280633f05SLee Jones 54380633f05SLee Jones return irq_create_mapping(ab8500->domain, irq); 54480633f05SLee Jones } 54580633f05SLee Jones 54662579266SRabin Vincent static irqreturn_t ab8500_irq(int irq, void *dev) 54762579266SRabin Vincent { 54862579266SRabin Vincent struct ab8500 *ab8500 = dev; 54962579266SRabin Vincent int i; 55062579266SRabin Vincent 55162579266SRabin Vincent dev_vdbg(ab8500->dev, "interrupt\n"); 55262579266SRabin Vincent 553112a80d2SJonas Aaberg atomic_inc(&ab8500->transfer_ongoing); 554112a80d2SJonas Aaberg 5552ced445eSLinus Walleij for (i = 0; i < ab8500->mask_size; i++) { 5562ced445eSLinus Walleij int regoffset = ab8500->irq_reg_offset[i]; 55762579266SRabin Vincent int status; 55847c16975SMattias Wallin u8 value; 55962579266SRabin Vincent 5600f620837SLinus Walleij /* 5610f620837SLinus Walleij * Interrupt register 12 doesn't exist prior to AB8500 version 5620f620837SLinus Walleij * 2.0 5630f620837SLinus Walleij */ 5640f620837SLinus Walleij if (regoffset == 11 && is_ab8500_1p1_or_earlier(ab8500)) 56592d50a41SMattias Wallin continue; 56692d50a41SMattias Wallin 56747c16975SMattias Wallin status = get_register_interruptible(ab8500, AB8500_INTERRUPT, 56847c16975SMattias Wallin AB8500_IT_LATCH1_REG + regoffset, &value); 56947c16975SMattias Wallin if (status < 0 || value == 0) 57062579266SRabin Vincent continue; 57162579266SRabin Vincent 57262579266SRabin Vincent do { 57388aec4f7SMattias Wallin int bit = __ffs(value); 57462579266SRabin Vincent int line = i * 8 + bit; 5750a37fc56SLee Jones int virq = ab8500_irq_get_virq(ab8500, line); 57662579266SRabin Vincent 5770a37fc56SLee Jones handle_nested_irq(virq); 5788f0eb43bSBengt Jonsson ab8500_debug_register_interrupt(line); 57947c16975SMattias Wallin value &= ~(1 << bit); 580112a80d2SJonas Aaberg 58147c16975SMattias Wallin } while (value); 58262579266SRabin Vincent } 583112a80d2SJonas Aaberg atomic_dec(&ab8500->transfer_ongoing); 58462579266SRabin Vincent return IRQ_HANDLED; 58562579266SRabin Vincent } 58662579266SRabin Vincent 58706e589efSLee Jones static int ab8500_irq_map(struct irq_domain *d, unsigned int virq, 58806e589efSLee Jones irq_hw_number_t hwirq) 58906e589efSLee Jones { 59006e589efSLee Jones struct ab8500 *ab8500 = d->host_data; 59106e589efSLee Jones 59206e589efSLee Jones if (!ab8500) 59306e589efSLee Jones return -EINVAL; 59406e589efSLee Jones 59506e589efSLee Jones irq_set_chip_data(virq, ab8500); 59606e589efSLee Jones irq_set_chip_and_handler(virq, &ab8500_irq_chip, 59706e589efSLee Jones handle_simple_irq); 59806e589efSLee Jones irq_set_nested_thread(virq, 1); 59906e589efSLee Jones #ifdef CONFIG_ARM 60006e589efSLee Jones set_irq_flags(virq, IRQF_VALID); 60106e589efSLee Jones #else 60206e589efSLee Jones irq_set_noprobe(virq); 60306e589efSLee Jones #endif 60462579266SRabin Vincent 60562579266SRabin Vincent return 0; 60662579266SRabin Vincent } 60762579266SRabin Vincent 60806e589efSLee Jones static struct irq_domain_ops ab8500_irq_ops = { 60906e589efSLee Jones .map = ab8500_irq_map, 61006e589efSLee Jones .xlate = irq_domain_xlate_twocell, 61106e589efSLee Jones }; 61206e589efSLee Jones 61306e589efSLee Jones static int ab8500_irq_init(struct ab8500 *ab8500, struct device_node *np) 61462579266SRabin Vincent { 6152ced445eSLinus Walleij int num_irqs; 61662579266SRabin Vincent 617d6255529SLinus Walleij if (is_ab9540(ab8500)) 618d6255529SLinus Walleij num_irqs = AB9540_NR_IRQS; 619a982362cSBengt Jonsson else if (is_ab8505(ab8500)) 620a982362cSBengt Jonsson num_irqs = AB8505_NR_IRQS; 621d6255529SLinus Walleij else 6222ced445eSLinus Walleij num_irqs = AB8500_NR_IRQS; 6232ced445eSLinus Walleij 624f1d11f39SLinus Walleij /* If ->irq_base is zero this will give a linear mapping */ 625f1d11f39SLinus Walleij ab8500->domain = irq_domain_add_simple(NULL, 626f1d11f39SLinus Walleij num_irqs, ab8500->irq_base, 627f1d11f39SLinus Walleij &ab8500_irq_ops, ab8500); 62806e589efSLee Jones 62906e589efSLee Jones if (!ab8500->domain) { 63006e589efSLee Jones dev_err(ab8500->dev, "Failed to create irqdomain\n"); 63106e589efSLee Jones return -ENOSYS; 63206e589efSLee Jones } 63306e589efSLee Jones 63406e589efSLee Jones return 0; 63562579266SRabin Vincent } 63662579266SRabin Vincent 637112a80d2SJonas Aaberg int ab8500_suspend(struct ab8500 *ab8500) 638112a80d2SJonas Aaberg { 639112a80d2SJonas Aaberg if (atomic_read(&ab8500->transfer_ongoing)) 640112a80d2SJonas Aaberg return -EINVAL; 641112a80d2SJonas Aaberg else 642112a80d2SJonas Aaberg return 0; 643112a80d2SJonas Aaberg } 644112a80d2SJonas Aaberg 645a9e9ce4cSBill Pemberton static struct resource ab8500_gpadc_resources[] = { 64662579266SRabin Vincent { 64762579266SRabin Vincent .name = "HW_CONV_END", 64862579266SRabin Vincent .start = AB8500_INT_GP_HW_ADC_CONV_END, 64962579266SRabin Vincent .end = AB8500_INT_GP_HW_ADC_CONV_END, 65062579266SRabin Vincent .flags = IORESOURCE_IRQ, 65162579266SRabin Vincent }, 65262579266SRabin Vincent { 65362579266SRabin Vincent .name = "SW_CONV_END", 65462579266SRabin Vincent .start = AB8500_INT_GP_SW_ADC_CONV_END, 65562579266SRabin Vincent .end = AB8500_INT_GP_SW_ADC_CONV_END, 65662579266SRabin Vincent .flags = IORESOURCE_IRQ, 65762579266SRabin Vincent }, 65862579266SRabin Vincent }; 65962579266SRabin Vincent 660a9e9ce4cSBill Pemberton static struct resource ab8500_rtc_resources[] = { 66162579266SRabin Vincent { 66262579266SRabin Vincent .name = "60S", 66362579266SRabin Vincent .start = AB8500_INT_RTC_60S, 66462579266SRabin Vincent .end = AB8500_INT_RTC_60S, 66562579266SRabin Vincent .flags = IORESOURCE_IRQ, 66662579266SRabin Vincent }, 66762579266SRabin Vincent { 66862579266SRabin Vincent .name = "ALARM", 66962579266SRabin Vincent .start = AB8500_INT_RTC_ALARM, 67062579266SRabin Vincent .end = AB8500_INT_RTC_ALARM, 67162579266SRabin Vincent .flags = IORESOURCE_IRQ, 67262579266SRabin Vincent }, 67362579266SRabin Vincent }; 67462579266SRabin Vincent 675a9e9ce4cSBill Pemberton static struct resource ab8500_poweronkey_db_resources[] = { 67677686517SSundar R Iyer { 67777686517SSundar R Iyer .name = "ONKEY_DBF", 67877686517SSundar R Iyer .start = AB8500_INT_PON_KEY1DB_F, 67977686517SSundar R Iyer .end = AB8500_INT_PON_KEY1DB_F, 68077686517SSundar R Iyer .flags = IORESOURCE_IRQ, 68177686517SSundar R Iyer }, 68277686517SSundar R Iyer { 68377686517SSundar R Iyer .name = "ONKEY_DBR", 68477686517SSundar R Iyer .start = AB8500_INT_PON_KEY1DB_R, 68577686517SSundar R Iyer .end = AB8500_INT_PON_KEY1DB_R, 68677686517SSundar R Iyer .flags = IORESOURCE_IRQ, 68777686517SSundar R Iyer }, 68877686517SSundar R Iyer }; 68977686517SSundar R Iyer 690a9e9ce4cSBill Pemberton static struct resource ab8500_av_acc_detect_resources[] = { 691e098adedSMattias Wallin { 6926af75ecdSLinus Walleij .name = "ACC_DETECT_1DB_F", 6936af75ecdSLinus Walleij .start = AB8500_INT_ACC_DETECT_1DB_F, 6946af75ecdSLinus Walleij .end = AB8500_INT_ACC_DETECT_1DB_F, 695e098adedSMattias Wallin .flags = IORESOURCE_IRQ, 696e098adedSMattias Wallin }, 697e098adedSMattias Wallin { 6986af75ecdSLinus Walleij .name = "ACC_DETECT_1DB_R", 6996af75ecdSLinus Walleij .start = AB8500_INT_ACC_DETECT_1DB_R, 7006af75ecdSLinus Walleij .end = AB8500_INT_ACC_DETECT_1DB_R, 701e098adedSMattias Wallin .flags = IORESOURCE_IRQ, 702e098adedSMattias Wallin }, 703e098adedSMattias Wallin { 7046af75ecdSLinus Walleij .name = "ACC_DETECT_21DB_F", 7056af75ecdSLinus Walleij .start = AB8500_INT_ACC_DETECT_21DB_F, 7066af75ecdSLinus Walleij .end = AB8500_INT_ACC_DETECT_21DB_F, 7076af75ecdSLinus Walleij .flags = IORESOURCE_IRQ, 7086af75ecdSLinus Walleij }, 7096af75ecdSLinus Walleij { 7106af75ecdSLinus Walleij .name = "ACC_DETECT_21DB_R", 7116af75ecdSLinus Walleij .start = AB8500_INT_ACC_DETECT_21DB_R, 7126af75ecdSLinus Walleij .end = AB8500_INT_ACC_DETECT_21DB_R, 7136af75ecdSLinus Walleij .flags = IORESOURCE_IRQ, 7146af75ecdSLinus Walleij }, 7156af75ecdSLinus Walleij { 7166af75ecdSLinus Walleij .name = "ACC_DETECT_22DB_F", 7176af75ecdSLinus Walleij .start = AB8500_INT_ACC_DETECT_22DB_F, 7186af75ecdSLinus Walleij .end = AB8500_INT_ACC_DETECT_22DB_F, 7196af75ecdSLinus Walleij .flags = IORESOURCE_IRQ, 7206af75ecdSLinus Walleij }, 7216af75ecdSLinus Walleij { 7226af75ecdSLinus Walleij .name = "ACC_DETECT_22DB_R", 7236af75ecdSLinus Walleij .start = AB8500_INT_ACC_DETECT_22DB_R, 7246af75ecdSLinus Walleij .end = AB8500_INT_ACC_DETECT_22DB_R, 7256af75ecdSLinus Walleij .flags = IORESOURCE_IRQ, 7266af75ecdSLinus Walleij }, 7276af75ecdSLinus Walleij }; 7286af75ecdSLinus Walleij 729a9e9ce4cSBill Pemberton static struct resource ab8500_charger_resources[] = { 7306af75ecdSLinus Walleij { 731e098adedSMattias Wallin .name = "MAIN_CH_UNPLUG_DET", 732e098adedSMattias Wallin .start = AB8500_INT_MAIN_CH_UNPLUG_DET, 733e098adedSMattias Wallin .end = AB8500_INT_MAIN_CH_UNPLUG_DET, 734e098adedSMattias Wallin .flags = IORESOURCE_IRQ, 735e098adedSMattias Wallin }, 736e098adedSMattias Wallin { 737e098adedSMattias Wallin .name = "MAIN_CHARGE_PLUG_DET", 738e098adedSMattias Wallin .start = AB8500_INT_MAIN_CH_PLUG_DET, 739e098adedSMattias Wallin .end = AB8500_INT_MAIN_CH_PLUG_DET, 740e098adedSMattias Wallin .flags = IORESOURCE_IRQ, 741e098adedSMattias Wallin }, 742e098adedSMattias Wallin { 743e098adedSMattias Wallin .name = "VBUS_DET_R", 744e098adedSMattias Wallin .start = AB8500_INT_VBUS_DET_R, 745e098adedSMattias Wallin .end = AB8500_INT_VBUS_DET_R, 746e098adedSMattias Wallin .flags = IORESOURCE_IRQ, 747e098adedSMattias Wallin }, 748e098adedSMattias Wallin { 7496af75ecdSLinus Walleij .name = "VBUS_DET_F", 7506af75ecdSLinus Walleij .start = AB8500_INT_VBUS_DET_F, 7516af75ecdSLinus Walleij .end = AB8500_INT_VBUS_DET_F, 752e098adedSMattias Wallin .flags = IORESOURCE_IRQ, 753e098adedSMattias Wallin }, 754e098adedSMattias Wallin { 7556af75ecdSLinus Walleij .name = "USB_LINK_STATUS", 7566af75ecdSLinus Walleij .start = AB8500_INT_USB_LINK_STATUS, 7576af75ecdSLinus Walleij .end = AB8500_INT_USB_LINK_STATUS, 7586af75ecdSLinus Walleij .flags = IORESOURCE_IRQ, 7596af75ecdSLinus Walleij }, 7606af75ecdSLinus Walleij { 761e098adedSMattias Wallin .name = "VBUS_OVV", 762e098adedSMattias Wallin .start = AB8500_INT_VBUS_OVV, 763e098adedSMattias Wallin .end = AB8500_INT_VBUS_OVV, 764e098adedSMattias Wallin .flags = IORESOURCE_IRQ, 765e098adedSMattias Wallin }, 766e098adedSMattias Wallin { 7676af75ecdSLinus Walleij .name = "USB_CH_TH_PROT_R", 7686af75ecdSLinus Walleij .start = AB8500_INT_USB_CH_TH_PROT_R, 7696af75ecdSLinus Walleij .end = AB8500_INT_USB_CH_TH_PROT_R, 770e098adedSMattias Wallin .flags = IORESOURCE_IRQ, 771e098adedSMattias Wallin }, 772e098adedSMattias Wallin { 7736af75ecdSLinus Walleij .name = "USB_CH_TH_PROT_F", 7746af75ecdSLinus Walleij .start = AB8500_INT_USB_CH_TH_PROT_F, 7756af75ecdSLinus Walleij .end = AB8500_INT_USB_CH_TH_PROT_F, 776e098adedSMattias Wallin .flags = IORESOURCE_IRQ, 777e098adedSMattias Wallin }, 778e098adedSMattias Wallin { 7796af75ecdSLinus Walleij .name = "MAIN_EXT_CH_NOT_OK", 7806af75ecdSLinus Walleij .start = AB8500_INT_MAIN_EXT_CH_NOT_OK, 7816af75ecdSLinus Walleij .end = AB8500_INT_MAIN_EXT_CH_NOT_OK, 7826af75ecdSLinus Walleij .flags = IORESOURCE_IRQ, 7836af75ecdSLinus Walleij }, 7846af75ecdSLinus Walleij { 7856af75ecdSLinus Walleij .name = "MAIN_CH_TH_PROT_R", 7866af75ecdSLinus Walleij .start = AB8500_INT_MAIN_CH_TH_PROT_R, 7876af75ecdSLinus Walleij .end = AB8500_INT_MAIN_CH_TH_PROT_R, 7886af75ecdSLinus Walleij .flags = IORESOURCE_IRQ, 7896af75ecdSLinus Walleij }, 7906af75ecdSLinus Walleij { 7916af75ecdSLinus Walleij .name = "MAIN_CH_TH_PROT_F", 7926af75ecdSLinus Walleij .start = AB8500_INT_MAIN_CH_TH_PROT_F, 7936af75ecdSLinus Walleij .end = AB8500_INT_MAIN_CH_TH_PROT_F, 7946af75ecdSLinus Walleij .flags = IORESOURCE_IRQ, 7956af75ecdSLinus Walleij }, 7966af75ecdSLinus Walleij { 7976af75ecdSLinus Walleij .name = "USB_CHARGER_NOT_OKR", 798a982362cSBengt Jonsson .start = AB8500_INT_USB_CHARGER_NOT_OKR, 799a982362cSBengt Jonsson .end = AB8500_INT_USB_CHARGER_NOT_OKR, 8006af75ecdSLinus Walleij .flags = IORESOURCE_IRQ, 8016af75ecdSLinus Walleij }, 8026af75ecdSLinus Walleij { 8036af75ecdSLinus Walleij .name = "CH_WD_EXP", 8046af75ecdSLinus Walleij .start = AB8500_INT_CH_WD_EXP, 8056af75ecdSLinus Walleij .end = AB8500_INT_CH_WD_EXP, 8066af75ecdSLinus Walleij .flags = IORESOURCE_IRQ, 8076af75ecdSLinus Walleij }, 80834c11a70SPaer-Olof Haakansson { 80934c11a70SPaer-Olof Haakansson .name = "VBUS_CH_DROP_END", 81034c11a70SPaer-Olof Haakansson .start = AB8500_INT_VBUS_CH_DROP_END, 81134c11a70SPaer-Olof Haakansson .end = AB8500_INT_VBUS_CH_DROP_END, 81234c11a70SPaer-Olof Haakansson .flags = IORESOURCE_IRQ, 81334c11a70SPaer-Olof Haakansson }, 8146af75ecdSLinus Walleij }; 8156af75ecdSLinus Walleij 816a9e9ce4cSBill Pemberton static struct resource ab8500_btemp_resources[] = { 8176af75ecdSLinus Walleij { 8186af75ecdSLinus Walleij .name = "BAT_CTRL_INDB", 8196af75ecdSLinus Walleij .start = AB8500_INT_BAT_CTRL_INDB, 8206af75ecdSLinus Walleij .end = AB8500_INT_BAT_CTRL_INDB, 821e098adedSMattias Wallin .flags = IORESOURCE_IRQ, 822e098adedSMattias Wallin }, 823e098adedSMattias Wallin { 824e098adedSMattias Wallin .name = "BTEMP_LOW", 825e098adedSMattias Wallin .start = AB8500_INT_BTEMP_LOW, 826e098adedSMattias Wallin .end = AB8500_INT_BTEMP_LOW, 827e098adedSMattias Wallin .flags = IORESOURCE_IRQ, 828e098adedSMattias Wallin }, 829e098adedSMattias Wallin { 830e098adedSMattias Wallin .name = "BTEMP_HIGH", 831e098adedSMattias Wallin .start = AB8500_INT_BTEMP_HIGH, 832e098adedSMattias Wallin .end = AB8500_INT_BTEMP_HIGH, 833e098adedSMattias Wallin .flags = IORESOURCE_IRQ, 834e098adedSMattias Wallin }, 835e098adedSMattias Wallin { 8366af75ecdSLinus Walleij .name = "BTEMP_LOW_MEDIUM", 8376af75ecdSLinus Walleij .start = AB8500_INT_BTEMP_LOW_MEDIUM, 8386af75ecdSLinus Walleij .end = AB8500_INT_BTEMP_LOW_MEDIUM, 839e098adedSMattias Wallin .flags = IORESOURCE_IRQ, 840e098adedSMattias Wallin }, 841e098adedSMattias Wallin { 8426af75ecdSLinus Walleij .name = "BTEMP_MEDIUM_HIGH", 8436af75ecdSLinus Walleij .start = AB8500_INT_BTEMP_MEDIUM_HIGH, 8446af75ecdSLinus Walleij .end = AB8500_INT_BTEMP_MEDIUM_HIGH, 845e098adedSMattias Wallin .flags = IORESOURCE_IRQ, 846e098adedSMattias Wallin }, 847e098adedSMattias Wallin }; 848e098adedSMattias Wallin 849a9e9ce4cSBill Pemberton static struct resource ab8500_fg_resources[] = { 8506af75ecdSLinus Walleij { 8516af75ecdSLinus Walleij .name = "NCONV_ACCU", 8526af75ecdSLinus Walleij .start = AB8500_INT_CCN_CONV_ACC, 8536af75ecdSLinus Walleij .end = AB8500_INT_CCN_CONV_ACC, 8546af75ecdSLinus Walleij .flags = IORESOURCE_IRQ, 8556af75ecdSLinus Walleij }, 8566af75ecdSLinus Walleij { 8576af75ecdSLinus Walleij .name = "BATT_OVV", 8586af75ecdSLinus Walleij .start = AB8500_INT_BATT_OVV, 8596af75ecdSLinus Walleij .end = AB8500_INT_BATT_OVV, 8606af75ecdSLinus Walleij .flags = IORESOURCE_IRQ, 8616af75ecdSLinus Walleij }, 8626af75ecdSLinus Walleij { 8636af75ecdSLinus Walleij .name = "LOW_BAT_F", 8646af75ecdSLinus Walleij .start = AB8500_INT_LOW_BAT_F, 8656af75ecdSLinus Walleij .end = AB8500_INT_LOW_BAT_F, 8666af75ecdSLinus Walleij .flags = IORESOURCE_IRQ, 8676af75ecdSLinus Walleij }, 8686af75ecdSLinus Walleij { 8696af75ecdSLinus Walleij .name = "LOW_BAT_R", 8706af75ecdSLinus Walleij .start = AB8500_INT_LOW_BAT_R, 8716af75ecdSLinus Walleij .end = AB8500_INT_LOW_BAT_R, 8726af75ecdSLinus Walleij .flags = IORESOURCE_IRQ, 8736af75ecdSLinus Walleij }, 8746af75ecdSLinus Walleij { 8756af75ecdSLinus Walleij .name = "CC_INT_CALIB", 8766af75ecdSLinus Walleij .start = AB8500_INT_CC_INT_CALIB, 8776af75ecdSLinus Walleij .end = AB8500_INT_CC_INT_CALIB, 8786af75ecdSLinus Walleij .flags = IORESOURCE_IRQ, 8796af75ecdSLinus Walleij }, 880a982362cSBengt Jonsson { 881a982362cSBengt Jonsson .name = "CCEOC", 882a982362cSBengt Jonsson .start = AB8500_INT_CCEOC, 883a982362cSBengt Jonsson .end = AB8500_INT_CCEOC, 884a982362cSBengt Jonsson .flags = IORESOURCE_IRQ, 885a982362cSBengt Jonsson }, 8866af75ecdSLinus Walleij }; 8876af75ecdSLinus Walleij 888a9e9ce4cSBill Pemberton static struct resource ab8500_chargalg_resources[] = {}; 8896af75ecdSLinus Walleij 890df720647SAxel Lin #ifdef CONFIG_DEBUG_FS 891a9e9ce4cSBill Pemberton static struct resource ab8500_debug_resources[] = { 892e098adedSMattias Wallin { 893e098adedSMattias Wallin .name = "IRQ_FIRST", 894e098adedSMattias Wallin .start = AB8500_INT_MAIN_EXT_CH_NOT_OK, 895e098adedSMattias Wallin .end = AB8500_INT_MAIN_EXT_CH_NOT_OK, 896e098adedSMattias Wallin .flags = IORESOURCE_IRQ, 897e098adedSMattias Wallin }, 898e098adedSMattias Wallin { 899e098adedSMattias Wallin .name = "IRQ_LAST", 900a982362cSBengt Jonsson .start = AB8500_INT_XTAL32K_KO, 901a982362cSBengt Jonsson .end = AB8500_INT_XTAL32K_KO, 902e098adedSMattias Wallin .flags = IORESOURCE_IRQ, 903e098adedSMattias Wallin }, 904e098adedSMattias Wallin }; 905df720647SAxel Lin #endif 906e098adedSMattias Wallin 907a9e9ce4cSBill Pemberton static struct resource ab8500_usb_resources[] = { 908e098adedSMattias Wallin { 909e098adedSMattias Wallin .name = "ID_WAKEUP_R", 910e098adedSMattias Wallin .start = AB8500_INT_ID_WAKEUP_R, 911e098adedSMattias Wallin .end = AB8500_INT_ID_WAKEUP_R, 912e098adedSMattias Wallin .flags = IORESOURCE_IRQ, 913e098adedSMattias Wallin }, 914e098adedSMattias Wallin { 915e098adedSMattias Wallin .name = "ID_WAKEUP_F", 916e098adedSMattias Wallin .start = AB8500_INT_ID_WAKEUP_F, 917e098adedSMattias Wallin .end = AB8500_INT_ID_WAKEUP_F, 918e098adedSMattias Wallin .flags = IORESOURCE_IRQ, 919e098adedSMattias Wallin }, 920e098adedSMattias Wallin { 921e098adedSMattias Wallin .name = "VBUS_DET_F", 922e098adedSMattias Wallin .start = AB8500_INT_VBUS_DET_F, 923e098adedSMattias Wallin .end = AB8500_INT_VBUS_DET_F, 924e098adedSMattias Wallin .flags = IORESOURCE_IRQ, 925e098adedSMattias Wallin }, 926e098adedSMattias Wallin { 927e098adedSMattias Wallin .name = "VBUS_DET_R", 928e098adedSMattias Wallin .start = AB8500_INT_VBUS_DET_R, 929e098adedSMattias Wallin .end = AB8500_INT_VBUS_DET_R, 930e098adedSMattias Wallin .flags = IORESOURCE_IRQ, 931e098adedSMattias Wallin }, 93292d50a41SMattias Wallin { 93392d50a41SMattias Wallin .name = "USB_LINK_STATUS", 93492d50a41SMattias Wallin .start = AB8500_INT_USB_LINK_STATUS, 93592d50a41SMattias Wallin .end = AB8500_INT_USB_LINK_STATUS, 93692d50a41SMattias Wallin .flags = IORESOURCE_IRQ, 93792d50a41SMattias Wallin }, 9386af75ecdSLinus Walleij { 9396af75ecdSLinus Walleij .name = "USB_ADP_PROBE_PLUG", 9406af75ecdSLinus Walleij .start = AB8500_INT_ADP_PROBE_PLUG, 9416af75ecdSLinus Walleij .end = AB8500_INT_ADP_PROBE_PLUG, 9426af75ecdSLinus Walleij .flags = IORESOURCE_IRQ, 9436af75ecdSLinus Walleij }, 9446af75ecdSLinus Walleij { 9456af75ecdSLinus Walleij .name = "USB_ADP_PROBE_UNPLUG", 9466af75ecdSLinus Walleij .start = AB8500_INT_ADP_PROBE_UNPLUG, 9476af75ecdSLinus Walleij .end = AB8500_INT_ADP_PROBE_UNPLUG, 9486af75ecdSLinus Walleij .flags = IORESOURCE_IRQ, 9496af75ecdSLinus Walleij }, 950e098adedSMattias Wallin }; 951e098adedSMattias Wallin 952a9e9ce4cSBill Pemberton static struct resource ab8505_iddet_resources[] = { 95344f72e53SVirupax Sadashivpetimath { 95444f72e53SVirupax Sadashivpetimath .name = "KeyDeglitch", 95544f72e53SVirupax Sadashivpetimath .start = AB8505_INT_KEYDEGLITCH, 95644f72e53SVirupax Sadashivpetimath .end = AB8505_INT_KEYDEGLITCH, 95744f72e53SVirupax Sadashivpetimath .flags = IORESOURCE_IRQ, 95844f72e53SVirupax Sadashivpetimath }, 95944f72e53SVirupax Sadashivpetimath { 96044f72e53SVirupax Sadashivpetimath .name = "KP", 96144f72e53SVirupax Sadashivpetimath .start = AB8505_INT_KP, 96244f72e53SVirupax Sadashivpetimath .end = AB8505_INT_KP, 96344f72e53SVirupax Sadashivpetimath .flags = IORESOURCE_IRQ, 96444f72e53SVirupax Sadashivpetimath }, 96544f72e53SVirupax Sadashivpetimath { 96644f72e53SVirupax Sadashivpetimath .name = "IKP", 96744f72e53SVirupax Sadashivpetimath .start = AB8505_INT_IKP, 96844f72e53SVirupax Sadashivpetimath .end = AB8505_INT_IKP, 96944f72e53SVirupax Sadashivpetimath .flags = IORESOURCE_IRQ, 97044f72e53SVirupax Sadashivpetimath }, 97144f72e53SVirupax Sadashivpetimath { 97244f72e53SVirupax Sadashivpetimath .name = "IKR", 97344f72e53SVirupax Sadashivpetimath .start = AB8505_INT_IKR, 97444f72e53SVirupax Sadashivpetimath .end = AB8505_INT_IKR, 97544f72e53SVirupax Sadashivpetimath .flags = IORESOURCE_IRQ, 97644f72e53SVirupax Sadashivpetimath }, 97744f72e53SVirupax Sadashivpetimath { 97844f72e53SVirupax Sadashivpetimath .name = "KeyStuck", 97944f72e53SVirupax Sadashivpetimath .start = AB8505_INT_KEYSTUCK, 98044f72e53SVirupax Sadashivpetimath .end = AB8505_INT_KEYSTUCK, 98144f72e53SVirupax Sadashivpetimath .flags = IORESOURCE_IRQ, 98244f72e53SVirupax Sadashivpetimath }, 98344f72e53SVirupax Sadashivpetimath }; 98444f72e53SVirupax Sadashivpetimath 985a9e9ce4cSBill Pemberton static struct resource ab8500_temp_resources[] = { 986e098adedSMattias Wallin { 987151621a7SHongbo Zhang .name = "ABX500_TEMP_WARM", 988e098adedSMattias Wallin .start = AB8500_INT_TEMP_WARM, 989e098adedSMattias Wallin .end = AB8500_INT_TEMP_WARM, 990e098adedSMattias Wallin .flags = IORESOURCE_IRQ, 991e098adedSMattias Wallin }, 992e098adedSMattias Wallin }; 993e098adedSMattias Wallin 994a9e9ce4cSBill Pemberton static struct mfd_cell abx500_common_devs[] = { 9955814fc35SMattias Wallin #ifdef CONFIG_DEBUG_FS 9965814fc35SMattias Wallin { 9975814fc35SMattias Wallin .name = "ab8500-debug", 998bad76991SLee Jones .of_compatible = "stericsson,ab8500-debug", 999e098adedSMattias Wallin .num_resources = ARRAY_SIZE(ab8500_debug_resources), 1000e098adedSMattias Wallin .resources = ab8500_debug_resources, 10015814fc35SMattias Wallin }, 10025814fc35SMattias Wallin #endif 100362579266SRabin Vincent { 1004e098adedSMattias Wallin .name = "ab8500-sysctrl", 1005bad76991SLee Jones .of_compatible = "stericsson,ab8500-sysctrl", 1006e098adedSMattias Wallin }, 1007e098adedSMattias Wallin { 1008e098adedSMattias Wallin .name = "ab8500-regulator", 1009bad76991SLee Jones .of_compatible = "stericsson,ab8500-regulator", 1010e098adedSMattias Wallin }, 1011e098adedSMattias Wallin { 1012916a871cSUlf Hansson .name = "abx500-clk", 1013916a871cSUlf Hansson .of_compatible = "stericsson,abx500-clk", 1014916a871cSUlf Hansson }, 1015916a871cSUlf Hansson { 101662579266SRabin Vincent .name = "ab8500-gpadc", 1017bad76991SLee Jones .of_compatible = "stericsson,ab8500-gpadc", 101862579266SRabin Vincent .num_resources = ARRAY_SIZE(ab8500_gpadc_resources), 101962579266SRabin Vincent .resources = ab8500_gpadc_resources, 102062579266SRabin Vincent }, 102162579266SRabin Vincent { 102262579266SRabin Vincent .name = "ab8500-rtc", 1023bad76991SLee Jones .of_compatible = "stericsson,ab8500-rtc", 102462579266SRabin Vincent .num_resources = ARRAY_SIZE(ab8500_rtc_resources), 102562579266SRabin Vincent .resources = ab8500_rtc_resources, 102662579266SRabin Vincent }, 1027f0f05b1cSArun Murthy { 10286af75ecdSLinus Walleij .name = "ab8500-acc-det", 1029bad76991SLee Jones .of_compatible = "stericsson,ab8500-acc-det", 10306af75ecdSLinus Walleij .num_resources = ARRAY_SIZE(ab8500_av_acc_detect_resources), 10316af75ecdSLinus Walleij .resources = ab8500_av_acc_detect_resources, 10326af75ecdSLinus Walleij }, 10336af75ecdSLinus Walleij { 1034e098adedSMattias Wallin .name = "ab8500-poweron-key", 1035bad76991SLee Jones .of_compatible = "stericsson,ab8500-poweron-key", 1036e098adedSMattias Wallin .num_resources = ARRAY_SIZE(ab8500_poweronkey_db_resources), 1037e098adedSMattias Wallin .resources = ab8500_poweronkey_db_resources, 1038e098adedSMattias Wallin }, 1039e098adedSMattias Wallin { 1040f0f05b1cSArun Murthy .name = "ab8500-pwm", 1041bad76991SLee Jones .of_compatible = "stericsson,ab8500-pwm", 1042f0f05b1cSArun Murthy .id = 1, 1043f0f05b1cSArun Murthy }, 1044f0f05b1cSArun Murthy { 1045f0f05b1cSArun Murthy .name = "ab8500-pwm", 1046bad76991SLee Jones .of_compatible = "stericsson,ab8500-pwm", 1047f0f05b1cSArun Murthy .id = 2, 1048f0f05b1cSArun Murthy }, 1049f0f05b1cSArun Murthy { 1050f0f05b1cSArun Murthy .name = "ab8500-pwm", 1051bad76991SLee Jones .of_compatible = "stericsson,ab8500-pwm", 1052f0f05b1cSArun Murthy .id = 3, 1053f0f05b1cSArun Murthy }, 1054bad76991SLee Jones { 1055bad76991SLee Jones .name = "ab8500-leds", 1056bad76991SLee Jones .of_compatible = "stericsson,ab8500-leds", 1057bad76991SLee Jones }, 105877686517SSundar R Iyer { 1059e098adedSMattias Wallin .name = "ab8500-denc", 1060bad76991SLee Jones .of_compatible = "stericsson,ab8500-denc", 1061e098adedSMattias Wallin }, 1062e098adedSMattias Wallin { 1063151621a7SHongbo Zhang .name = "abx500-temp", 1064151621a7SHongbo Zhang .of_compatible = "stericsson,abx500-temp", 1065e098adedSMattias Wallin .num_resources = ARRAY_SIZE(ab8500_temp_resources), 1066e098adedSMattias Wallin .resources = ab8500_temp_resources, 106777686517SSundar R Iyer }, 106862579266SRabin Vincent }; 106962579266SRabin Vincent 1070a9e9ce4cSBill Pemberton static struct mfd_cell ab8500_bm_devs[] = { 10716ef9418cSRickard Andersson { 10726ef9418cSRickard Andersson .name = "ab8500-charger", 10734aef72dbSRajanikanth H.V .of_compatible = "stericsson,ab8500-charger", 10746ef9418cSRickard Andersson .num_resources = ARRAY_SIZE(ab8500_charger_resources), 10756ef9418cSRickard Andersson .resources = ab8500_charger_resources, 10764aef72dbSRajanikanth H.V .platform_data = &ab8500_bm_data, 10774aef72dbSRajanikanth H.V .pdata_size = sizeof(ab8500_bm_data), 10786ef9418cSRickard Andersson }, 10796ef9418cSRickard Andersson { 10806ef9418cSRickard Andersson .name = "ab8500-btemp", 1081bd9e8ab2SRajanikanth H.V .of_compatible = "stericsson,ab8500-btemp", 10826ef9418cSRickard Andersson .num_resources = ARRAY_SIZE(ab8500_btemp_resources), 10836ef9418cSRickard Andersson .resources = ab8500_btemp_resources, 1084bd9e8ab2SRajanikanth H.V .platform_data = &ab8500_bm_data, 1085bd9e8ab2SRajanikanth H.V .pdata_size = sizeof(ab8500_bm_data), 10866ef9418cSRickard Andersson }, 10876ef9418cSRickard Andersson { 10886ef9418cSRickard Andersson .name = "ab8500-fg", 1089e0f1abebSRajanikanth H.V .of_compatible = "stericsson,ab8500-fg", 10906ef9418cSRickard Andersson .num_resources = ARRAY_SIZE(ab8500_fg_resources), 10916ef9418cSRickard Andersson .resources = ab8500_fg_resources, 1092e0f1abebSRajanikanth H.V .platform_data = &ab8500_bm_data, 1093e0f1abebSRajanikanth H.V .pdata_size = sizeof(ab8500_bm_data), 10946ef9418cSRickard Andersson }, 10956ef9418cSRickard Andersson { 10966ef9418cSRickard Andersson .name = "ab8500-chargalg", 1097a12810abSRajanikanth H.V .of_compatible = "stericsson,ab8500-chargalg", 10986ef9418cSRickard Andersson .num_resources = ARRAY_SIZE(ab8500_chargalg_resources), 10996ef9418cSRickard Andersson .resources = ab8500_chargalg_resources, 1100a12810abSRajanikanth H.V .platform_data = &ab8500_bm_data, 1101a12810abSRajanikanth H.V .pdata_size = sizeof(ab8500_bm_data), 11026ef9418cSRickard Andersson }, 11036ef9418cSRickard Andersson }; 11046ef9418cSRickard Andersson 1105a9e9ce4cSBill Pemberton static struct mfd_cell ab8500_devs[] = { 1106d6255529SLinus Walleij { 11077d56a46eSLee Jones .name = "pinctrl-ab8500", 1108bad76991SLee Jones .of_compatible = "stericsson,ab8500-gpio", 1109d6255529SLinus Walleij }, 1110d6255529SLinus Walleij { 1111d6255529SLinus Walleij .name = "ab8500-usb", 1112bad76991SLee Jones .of_compatible = "stericsson,ab8500-usb", 1113d6255529SLinus Walleij .num_resources = ARRAY_SIZE(ab8500_usb_resources), 1114d6255529SLinus Walleij .resources = ab8500_usb_resources, 1115d6255529SLinus Walleij }, 111644f72e53SVirupax Sadashivpetimath { 111744f72e53SVirupax Sadashivpetimath .name = "ab8500-codec", 111881a21cddSLee Jones .of_compatible = "stericsson,ab8500-codec", 111944f72e53SVirupax Sadashivpetimath }, 1120d6255529SLinus Walleij }; 1121d6255529SLinus Walleij 1122a9e9ce4cSBill Pemberton static struct mfd_cell ab9540_devs[] = { 1123d6255529SLinus Walleij { 1124e64d905eSLee Jones .name = "pinctrl-ab9540", 1125e64d905eSLee Jones .of_compatible = "stericsson,ab9540-gpio", 1126d6255529SLinus Walleij }, 1127d6255529SLinus Walleij { 1128d6255529SLinus Walleij .name = "ab9540-usb", 1129d6255529SLinus Walleij .num_resources = ARRAY_SIZE(ab8500_usb_resources), 1130d6255529SLinus Walleij .resources = ab8500_usb_resources, 1131d6255529SLinus Walleij }, 113244f72e53SVirupax Sadashivpetimath { 113344f72e53SVirupax Sadashivpetimath .name = "ab9540-codec", 113444f72e53SVirupax Sadashivpetimath }, 113544f72e53SVirupax Sadashivpetimath }; 113644f72e53SVirupax Sadashivpetimath 113744f72e53SVirupax Sadashivpetimath /* Device list common to ab9540 and ab8505 */ 1138a9e9ce4cSBill Pemberton static struct mfd_cell ab9540_ab8505_devs[] = { 113944f72e53SVirupax Sadashivpetimath { 114044f72e53SVirupax Sadashivpetimath .name = "ab-iddet", 114144f72e53SVirupax Sadashivpetimath .num_resources = ARRAY_SIZE(ab8505_iddet_resources), 114244f72e53SVirupax Sadashivpetimath .resources = ab8505_iddet_resources, 114344f72e53SVirupax Sadashivpetimath }, 1144d6255529SLinus Walleij }; 1145d6255529SLinus Walleij 1146cca69b67SMattias Wallin static ssize_t show_chip_id(struct device *dev, 1147cca69b67SMattias Wallin struct device_attribute *attr, char *buf) 1148cca69b67SMattias Wallin { 1149cca69b67SMattias Wallin struct ab8500 *ab8500; 1150cca69b67SMattias Wallin 1151cca69b67SMattias Wallin ab8500 = dev_get_drvdata(dev); 1152cca69b67SMattias Wallin return sprintf(buf, "%#x\n", ab8500 ? ab8500->chip_id : -EINVAL); 1153cca69b67SMattias Wallin } 1154cca69b67SMattias Wallin 1155e5c238c3SMattias Wallin /* 1156e5c238c3SMattias Wallin * ab8500 has switched off due to (SWITCH_OFF_STATUS): 1157e5c238c3SMattias Wallin * 0x01 Swoff bit programming 1158e5c238c3SMattias Wallin * 0x02 Thermal protection activation 1159e5c238c3SMattias Wallin * 0x04 Vbat lower then BattOk falling threshold 1160e5c238c3SMattias Wallin * 0x08 Watchdog expired 1161e5c238c3SMattias Wallin * 0x10 Non presence of 32kHz clock 1162e5c238c3SMattias Wallin * 0x20 Battery level lower than power on reset threshold 1163e5c238c3SMattias Wallin * 0x40 Power on key 1 pressed longer than 10 seconds 1164e5c238c3SMattias Wallin * 0x80 DB8500 thermal shutdown 1165e5c238c3SMattias Wallin */ 1166e5c238c3SMattias Wallin static ssize_t show_switch_off_status(struct device *dev, 1167e5c238c3SMattias Wallin struct device_attribute *attr, char *buf) 1168e5c238c3SMattias Wallin { 1169e5c238c3SMattias Wallin int ret; 1170e5c238c3SMattias Wallin u8 value; 1171e5c238c3SMattias Wallin struct ab8500 *ab8500; 1172e5c238c3SMattias Wallin 1173e5c238c3SMattias Wallin ab8500 = dev_get_drvdata(dev); 1174e5c238c3SMattias Wallin ret = get_register_interruptible(ab8500, AB8500_RTC, 1175e5c238c3SMattias Wallin AB8500_SWITCH_OFF_STATUS, &value); 1176e5c238c3SMattias Wallin if (ret < 0) 1177e5c238c3SMattias Wallin return ret; 1178e5c238c3SMattias Wallin return sprintf(buf, "%#x\n", value); 1179e5c238c3SMattias Wallin } 1180e5c238c3SMattias Wallin 1181f04a9d8aSRajkumar Kasirajan /* use mask and set to override the register turn_on_stat value */ 1182f04a9d8aSRajkumar Kasirajan void ab8500_override_turn_on_stat(u8 mask, u8 set) 1183f04a9d8aSRajkumar Kasirajan { 1184f04a9d8aSRajkumar Kasirajan spin_lock(&on_stat_lock); 1185f04a9d8aSRajkumar Kasirajan turn_on_stat_mask = mask; 1186f04a9d8aSRajkumar Kasirajan turn_on_stat_set = set; 1187f04a9d8aSRajkumar Kasirajan spin_unlock(&on_stat_lock); 1188f04a9d8aSRajkumar Kasirajan } 1189f04a9d8aSRajkumar Kasirajan 1190b4a31037SAndrew Lynn /* 1191b4a31037SAndrew Lynn * ab8500 has turned on due to (TURN_ON_STATUS): 1192b4a31037SAndrew Lynn * 0x01 PORnVbat 1193b4a31037SAndrew Lynn * 0x02 PonKey1dbF 1194b4a31037SAndrew Lynn * 0x04 PonKey2dbF 1195b4a31037SAndrew Lynn * 0x08 RTCAlarm 1196b4a31037SAndrew Lynn * 0x10 MainChDet 1197b4a31037SAndrew Lynn * 0x20 VbusDet 1198b4a31037SAndrew Lynn * 0x40 UsbIDDetect 1199b4a31037SAndrew Lynn * 0x80 Reserved 1200b4a31037SAndrew Lynn */ 1201b4a31037SAndrew Lynn static ssize_t show_turn_on_status(struct device *dev, 1202b4a31037SAndrew Lynn struct device_attribute *attr, char *buf) 1203b4a31037SAndrew Lynn { 1204b4a31037SAndrew Lynn int ret; 1205b4a31037SAndrew Lynn u8 value; 1206b4a31037SAndrew Lynn struct ab8500 *ab8500; 1207b4a31037SAndrew Lynn 1208b4a31037SAndrew Lynn ab8500 = dev_get_drvdata(dev); 1209b4a31037SAndrew Lynn ret = get_register_interruptible(ab8500, AB8500_SYS_CTRL1_BLOCK, 1210b4a31037SAndrew Lynn AB8500_TURN_ON_STATUS, &value); 1211b4a31037SAndrew Lynn if (ret < 0) 1212b4a31037SAndrew Lynn return ret; 1213f04a9d8aSRajkumar Kasirajan 1214f04a9d8aSRajkumar Kasirajan /* 1215f04a9d8aSRajkumar Kasirajan * In L9540, turn_on_status register is not updated correctly if 1216f04a9d8aSRajkumar Kasirajan * the device is rebooted with AC/USB charger connected. Due to 1217f04a9d8aSRajkumar Kasirajan * this, the device boots android instead of entering into charge 1218f04a9d8aSRajkumar Kasirajan * only mode. Read the AC/USB status register to detect the charger 1219f04a9d8aSRajkumar Kasirajan * presence and update the turn on status manually. 1220f04a9d8aSRajkumar Kasirajan */ 1221f04a9d8aSRajkumar Kasirajan if (is_ab9540(ab8500)) { 1222f04a9d8aSRajkumar Kasirajan spin_lock(&on_stat_lock); 1223f04a9d8aSRajkumar Kasirajan value = (value & turn_on_stat_mask) | turn_on_stat_set; 1224f04a9d8aSRajkumar Kasirajan spin_unlock(&on_stat_lock); 1225f04a9d8aSRajkumar Kasirajan } 1226f04a9d8aSRajkumar Kasirajan 1227b4a31037SAndrew Lynn return sprintf(buf, "%#x\n", value); 1228b4a31037SAndrew Lynn } 1229b4a31037SAndrew Lynn 1230d6255529SLinus Walleij static ssize_t show_ab9540_dbbrstn(struct device *dev, 1231d6255529SLinus Walleij struct device_attribute *attr, char *buf) 1232d6255529SLinus Walleij { 1233d6255529SLinus Walleij struct ab8500 *ab8500; 1234d6255529SLinus Walleij int ret; 1235d6255529SLinus Walleij u8 value; 1236d6255529SLinus Walleij 1237d6255529SLinus Walleij ab8500 = dev_get_drvdata(dev); 1238d6255529SLinus Walleij 1239d6255529SLinus Walleij ret = get_register_interruptible(ab8500, AB8500_REGU_CTRL2, 1240d6255529SLinus Walleij AB9540_MODEM_CTRL2_REG, &value); 1241d6255529SLinus Walleij if (ret < 0) 1242d6255529SLinus Walleij return ret; 1243d6255529SLinus Walleij 1244d6255529SLinus Walleij return sprintf(buf, "%d\n", 1245d6255529SLinus Walleij (value & AB9540_MODEM_CTRL2_SWDBBRSTN_BIT) ? 1 : 0); 1246d6255529SLinus Walleij } 1247d6255529SLinus Walleij 1248d6255529SLinus Walleij static ssize_t store_ab9540_dbbrstn(struct device *dev, 1249d6255529SLinus Walleij struct device_attribute *attr, const char *buf, size_t count) 1250d6255529SLinus Walleij { 1251d6255529SLinus Walleij struct ab8500 *ab8500; 1252d6255529SLinus Walleij int ret = count; 1253d6255529SLinus Walleij int err; 1254d6255529SLinus Walleij u8 bitvalues; 1255d6255529SLinus Walleij 1256d6255529SLinus Walleij ab8500 = dev_get_drvdata(dev); 1257d6255529SLinus Walleij 1258d6255529SLinus Walleij if (count > 0) { 1259d6255529SLinus Walleij switch (buf[0]) { 1260d6255529SLinus Walleij case '0': 1261d6255529SLinus Walleij bitvalues = 0; 1262d6255529SLinus Walleij break; 1263d6255529SLinus Walleij case '1': 1264d6255529SLinus Walleij bitvalues = AB9540_MODEM_CTRL2_SWDBBRSTN_BIT; 1265d6255529SLinus Walleij break; 1266d6255529SLinus Walleij default: 1267d6255529SLinus Walleij goto exit; 1268d6255529SLinus Walleij } 1269d6255529SLinus Walleij 1270d6255529SLinus Walleij err = mask_and_set_register_interruptible(ab8500, 1271d6255529SLinus Walleij AB8500_REGU_CTRL2, AB9540_MODEM_CTRL2_REG, 1272d6255529SLinus Walleij AB9540_MODEM_CTRL2_SWDBBRSTN_BIT, bitvalues); 1273d6255529SLinus Walleij if (err) 1274d6255529SLinus Walleij dev_info(ab8500->dev, 1275d6255529SLinus Walleij "Failed to set DBBRSTN %c, err %#x\n", 1276d6255529SLinus Walleij buf[0], err); 1277d6255529SLinus Walleij } 1278d6255529SLinus Walleij 1279d6255529SLinus Walleij exit: 1280d6255529SLinus Walleij return ret; 1281d6255529SLinus Walleij } 1282d6255529SLinus Walleij 1283cca69b67SMattias Wallin static DEVICE_ATTR(chip_id, S_IRUGO, show_chip_id, NULL); 1284e5c238c3SMattias Wallin static DEVICE_ATTR(switch_off_status, S_IRUGO, show_switch_off_status, NULL); 1285b4a31037SAndrew Lynn static DEVICE_ATTR(turn_on_status, S_IRUGO, show_turn_on_status, NULL); 1286d6255529SLinus Walleij static DEVICE_ATTR(dbbrstn, S_IRUGO | S_IWUSR, 1287d6255529SLinus Walleij show_ab9540_dbbrstn, store_ab9540_dbbrstn); 1288cca69b67SMattias Wallin 1289cca69b67SMattias Wallin static struct attribute *ab8500_sysfs_entries[] = { 1290cca69b67SMattias Wallin &dev_attr_chip_id.attr, 1291e5c238c3SMattias Wallin &dev_attr_switch_off_status.attr, 1292b4a31037SAndrew Lynn &dev_attr_turn_on_status.attr, 1293cca69b67SMattias Wallin NULL, 1294cca69b67SMattias Wallin }; 1295cca69b67SMattias Wallin 1296d6255529SLinus Walleij static struct attribute *ab9540_sysfs_entries[] = { 1297d6255529SLinus Walleij &dev_attr_chip_id.attr, 1298d6255529SLinus Walleij &dev_attr_switch_off_status.attr, 1299d6255529SLinus Walleij &dev_attr_turn_on_status.attr, 1300d6255529SLinus Walleij &dev_attr_dbbrstn.attr, 1301d6255529SLinus Walleij NULL, 1302d6255529SLinus Walleij }; 1303d6255529SLinus Walleij 1304cca69b67SMattias Wallin static struct attribute_group ab8500_attr_group = { 1305cca69b67SMattias Wallin .attrs = ab8500_sysfs_entries, 1306cca69b67SMattias Wallin }; 1307cca69b67SMattias Wallin 1308d6255529SLinus Walleij static struct attribute_group ab9540_attr_group = { 1309d6255529SLinus Walleij .attrs = ab9540_sysfs_entries, 1310d6255529SLinus Walleij }; 1311d6255529SLinus Walleij 1312f791be49SBill Pemberton static int ab8500_probe(struct platform_device *pdev) 131362579266SRabin Vincent { 1314b04c530cSJonas Aaberg static char *switch_off_status[] = { 1315b04c530cSJonas Aaberg "Swoff bit programming", 1316b04c530cSJonas Aaberg "Thermal protection activation", 1317b04c530cSJonas Aaberg "Vbat lower then BattOk falling threshold", 1318b04c530cSJonas Aaberg "Watchdog expired", 1319b04c530cSJonas Aaberg "Non presence of 32kHz clock", 1320b04c530cSJonas Aaberg "Battery level lower than power on reset threshold", 1321b04c530cSJonas Aaberg "Power on key 1 pressed longer than 10 seconds", 1322b04c530cSJonas Aaberg "DB8500 thermal shutdown"}; 1323d28f1db8SLee Jones struct ab8500_platform_data *plat = dev_get_platdata(&pdev->dev); 1324d28f1db8SLee Jones const struct platform_device_id *platid = platform_get_device_id(pdev); 13256bc4a568SLee Jones enum ab8500_version version = AB8500_VERSION_UNDEFINED; 13266bc4a568SLee Jones struct device_node *np = pdev->dev.of_node; 1327d28f1db8SLee Jones struct ab8500 *ab8500; 1328d28f1db8SLee Jones struct resource *resource; 132962579266SRabin Vincent int ret; 133062579266SRabin Vincent int i; 133147c16975SMattias Wallin u8 value; 133262579266SRabin Vincent 13338c4203cbSLee Jones ab8500 = devm_kzalloc(&pdev->dev, sizeof *ab8500, GFP_KERNEL); 1334d28f1db8SLee Jones if (!ab8500) 1335d28f1db8SLee Jones return -ENOMEM; 1336d28f1db8SLee Jones 133762579266SRabin Vincent if (plat) 133862579266SRabin Vincent ab8500->irq_base = plat->irq_base; 133962579266SRabin Vincent 1340d28f1db8SLee Jones ab8500->dev = &pdev->dev; 1341d28f1db8SLee Jones 1342d28f1db8SLee Jones resource = platform_get_resource(pdev, IORESOURCE_IRQ, 0); 13438c4203cbSLee Jones if (!resource) 13448c4203cbSLee Jones return -ENODEV; 1345d28f1db8SLee Jones 1346d28f1db8SLee Jones ab8500->irq = resource->start; 1347d28f1db8SLee Jones 1348822672a7SLee Jones ab8500->read = ab8500_prcmu_read; 1349822672a7SLee Jones ab8500->write = ab8500_prcmu_write; 1350822672a7SLee Jones ab8500->write_masked = ab8500_prcmu_write_masked; 1351d28f1db8SLee Jones 135262579266SRabin Vincent mutex_init(&ab8500->lock); 135362579266SRabin Vincent mutex_init(&ab8500->irq_lock); 1354112a80d2SJonas Aaberg atomic_set(&ab8500->transfer_ongoing, 0); 135562579266SRabin Vincent 1356d28f1db8SLee Jones platform_set_drvdata(pdev, ab8500); 1357d28f1db8SLee Jones 13586bc4a568SLee Jones if (platid) 13596bc4a568SLee Jones version = platid->driver_data; 13606bc4a568SLee Jones 13610f620837SLinus Walleij if (version != AB8500_VERSION_UNDEFINED) 13620f620837SLinus Walleij ab8500->version = version; 13630f620837SLinus Walleij else { 13640f620837SLinus Walleij ret = get_register_interruptible(ab8500, AB8500_MISC, 13650f620837SLinus Walleij AB8500_IC_NAME_REG, &value); 13660f620837SLinus Walleij if (ret < 0) 13678c4203cbSLee Jones return ret; 13680f620837SLinus Walleij 13690f620837SLinus Walleij ab8500->version = value; 13700f620837SLinus Walleij } 13710f620837SLinus Walleij 137247c16975SMattias Wallin ret = get_register_interruptible(ab8500, AB8500_MISC, 137347c16975SMattias Wallin AB8500_REV_REG, &value); 137462579266SRabin Vincent if (ret < 0) 13758c4203cbSLee Jones return ret; 137662579266SRabin Vincent 137747c16975SMattias Wallin ab8500->chip_id = value; 137862579266SRabin Vincent 13790f620837SLinus Walleij dev_info(ab8500->dev, "detected chip, %s rev. %1x.%1x\n", 13800f620837SLinus Walleij ab8500_version_str[ab8500->version], 13810f620837SLinus Walleij ab8500->chip_id >> 4, 13820f620837SLinus Walleij ab8500->chip_id & 0x0F); 13830f620837SLinus Walleij 1384d6255529SLinus Walleij /* Configure AB8500 or AB9540 IRQ */ 1385a982362cSBengt Jonsson if (is_ab9540(ab8500) || is_ab8505(ab8500)) { 1386d6255529SLinus Walleij ab8500->mask_size = AB9540_NUM_IRQ_REGS; 1387d6255529SLinus Walleij ab8500->irq_reg_offset = ab9540_irq_regoffset; 1388d6255529SLinus Walleij } else { 13892ced445eSLinus Walleij ab8500->mask_size = AB8500_NUM_IRQ_REGS; 13902ced445eSLinus Walleij ab8500->irq_reg_offset = ab8500_irq_regoffset; 1391d6255529SLinus Walleij } 13928c4203cbSLee Jones ab8500->mask = devm_kzalloc(&pdev->dev, ab8500->mask_size, GFP_KERNEL); 13932ced445eSLinus Walleij if (!ab8500->mask) 13942ced445eSLinus Walleij return -ENOMEM; 13958c4203cbSLee Jones ab8500->oldmask = devm_kzalloc(&pdev->dev, ab8500->mask_size, GFP_KERNEL); 13968c4203cbSLee Jones if (!ab8500->oldmask) 13978c4203cbSLee Jones return -ENOMEM; 13988c4203cbSLee Jones 1399e5c238c3SMattias Wallin /* 1400e5c238c3SMattias Wallin * ab8500 has switched off due to (SWITCH_OFF_STATUS): 1401e5c238c3SMattias Wallin * 0x01 Swoff bit programming 1402e5c238c3SMattias Wallin * 0x02 Thermal protection activation 1403e5c238c3SMattias Wallin * 0x04 Vbat lower then BattOk falling threshold 1404e5c238c3SMattias Wallin * 0x08 Watchdog expired 1405e5c238c3SMattias Wallin * 0x10 Non presence of 32kHz clock 1406e5c238c3SMattias Wallin * 0x20 Battery level lower than power on reset threshold 1407e5c238c3SMattias Wallin * 0x40 Power on key 1 pressed longer than 10 seconds 1408e5c238c3SMattias Wallin * 0x80 DB8500 thermal shutdown 1409e5c238c3SMattias Wallin */ 1410e5c238c3SMattias Wallin 1411e5c238c3SMattias Wallin ret = get_register_interruptible(ab8500, AB8500_RTC, 1412e5c238c3SMattias Wallin AB8500_SWITCH_OFF_STATUS, &value); 1413e5c238c3SMattias Wallin if (ret < 0) 1414e5c238c3SMattias Wallin return ret; 1415b04c530cSJonas Aaberg dev_info(ab8500->dev, "switch off cause(s) (%#x): ", value); 1416b04c530cSJonas Aaberg 1417b04c530cSJonas Aaberg if (value) { 1418b04c530cSJonas Aaberg for (i = 0; i < ARRAY_SIZE(switch_off_status); i++) { 1419b04c530cSJonas Aaberg if (value & 1) 1420b04c530cSJonas Aaberg printk(KERN_CONT " \"%s\"", 1421b04c530cSJonas Aaberg switch_off_status[i]); 1422b04c530cSJonas Aaberg value = value >> 1; 1423b04c530cSJonas Aaberg 1424b04c530cSJonas Aaberg } 1425b04c530cSJonas Aaberg printk(KERN_CONT "\n"); 1426b04c530cSJonas Aaberg } else { 1427b04c530cSJonas Aaberg printk(KERN_CONT " None\n"); 1428b04c530cSJonas Aaberg } 1429e5c238c3SMattias Wallin 143062579266SRabin Vincent if (plat && plat->init) 143162579266SRabin Vincent plat->init(ab8500); 1432f04a9d8aSRajkumar Kasirajan if (is_ab9540(ab8500)) { 1433f04a9d8aSRajkumar Kasirajan ret = get_register_interruptible(ab8500, AB8500_CHARGER, 1434f04a9d8aSRajkumar Kasirajan AB8500_CH_USBCH_STAT1_REG, &value); 1435f04a9d8aSRajkumar Kasirajan if (ret < 0) 1436f04a9d8aSRajkumar Kasirajan return ret; 1437f04a9d8aSRajkumar Kasirajan if ((value & VBUS_DET_DBNC1) && (value & VBUS_DET_DBNC100)) 1438f04a9d8aSRajkumar Kasirajan ab8500_override_turn_on_stat(~AB8500_POW_KEY_1_ON, 1439f04a9d8aSRajkumar Kasirajan AB8500_VBUS_DET); 1440f04a9d8aSRajkumar Kasirajan } 144162579266SRabin Vincent 144262579266SRabin Vincent /* Clear and mask all interrupts */ 14432ced445eSLinus Walleij for (i = 0; i < ab8500->mask_size; i++) { 14440f620837SLinus Walleij /* 14450f620837SLinus Walleij * Interrupt register 12 doesn't exist prior to AB8500 version 14460f620837SLinus Walleij * 2.0 14470f620837SLinus Walleij */ 14480f620837SLinus Walleij if (ab8500->irq_reg_offset[i] == 11 && 14490f620837SLinus Walleij is_ab8500_1p1_or_earlier(ab8500)) 145092d50a41SMattias Wallin continue; 145162579266SRabin Vincent 145247c16975SMattias Wallin get_register_interruptible(ab8500, AB8500_INTERRUPT, 14532ced445eSLinus Walleij AB8500_IT_LATCH1_REG + ab8500->irq_reg_offset[i], 145492d50a41SMattias Wallin &value); 145547c16975SMattias Wallin set_register_interruptible(ab8500, AB8500_INTERRUPT, 14562ced445eSLinus Walleij AB8500_IT_MASK1_REG + ab8500->irq_reg_offset[i], 0xff); 145762579266SRabin Vincent } 145862579266SRabin Vincent 145947c16975SMattias Wallin ret = abx500_register_ops(ab8500->dev, &ab8500_ops); 146047c16975SMattias Wallin if (ret) 14618c4203cbSLee Jones return ret; 146247c16975SMattias Wallin 14632ced445eSLinus Walleij for (i = 0; i < ab8500->mask_size; i++) 146462579266SRabin Vincent ab8500->mask[i] = ab8500->oldmask[i] = 0xff; 146562579266SRabin Vincent 146606e589efSLee Jones ret = ab8500_irq_init(ab8500, np); 146762579266SRabin Vincent if (ret) 14688c4203cbSLee Jones return ret; 146962579266SRabin Vincent 14707ccfe9b1SMichel JAOUEN /* Activate this feature only in ab9540 */ 14717ccfe9b1SMichel JAOUEN /* till tests are done on ab8500 1p2 or later*/ 147206e589efSLee Jones if (is_ab9540(ab8500)) { 14738c4203cbSLee Jones ret = devm_request_threaded_irq(&pdev->dev, ab8500->irq, NULL, 14747ccfe9b1SMichel JAOUEN ab8500_hierarchical_irq, 14757ccfe9b1SMichel JAOUEN IRQF_ONESHOT | IRQF_NO_SUSPEND, 14767ccfe9b1SMichel JAOUEN "ab8500", ab8500); 147706e589efSLee Jones } 147806e589efSLee Jones else { 14798c4203cbSLee Jones ret = devm_request_threaded_irq(&pdev->dev, ab8500->irq, NULL, 14807ccfe9b1SMichel JAOUEN ab8500_irq, 14814f079985SMattias Wallin IRQF_ONESHOT | IRQF_NO_SUSPEND, 14824f079985SMattias Wallin "ab8500", ab8500); 148362579266SRabin Vincent if (ret) 14848c4203cbSLee Jones return ret; 148562579266SRabin Vincent } 148662579266SRabin Vincent 1487d6255529SLinus Walleij ret = mfd_add_devices(ab8500->dev, 0, abx500_common_devs, 1488d6255529SLinus Walleij ARRAY_SIZE(abx500_common_devs), NULL, 148955692af5SMark Brown ab8500->irq_base, ab8500->domain); 1490d6255529SLinus Walleij if (ret) 14918c4203cbSLee Jones return ret; 1492d6255529SLinus Walleij 1493d6255529SLinus Walleij if (is_ab9540(ab8500)) 1494d6255529SLinus Walleij ret = mfd_add_devices(ab8500->dev, 0, ab9540_devs, 1495d6255529SLinus Walleij ARRAY_SIZE(ab9540_devs), NULL, 149655692af5SMark Brown ab8500->irq_base, ab8500->domain); 1497d6255529SLinus Walleij else 1498549931f9SSundar R Iyer ret = mfd_add_devices(ab8500->dev, 0, ab8500_devs, 149944f72e53SVirupax Sadashivpetimath ARRAY_SIZE(ab8500_devs), NULL, 150055692af5SMark Brown ab8500->irq_base, ab8500->domain); 15016bc4a568SLee Jones if (ret) 15028c4203cbSLee Jones return ret; 150344f72e53SVirupax Sadashivpetimath 150444f72e53SVirupax Sadashivpetimath if (is_ab9540(ab8500) || is_ab8505(ab8500)) 150544f72e53SVirupax Sadashivpetimath ret = mfd_add_devices(ab8500->dev, 0, ab9540_ab8505_devs, 150644f72e53SVirupax Sadashivpetimath ARRAY_SIZE(ab9540_ab8505_devs), NULL, 150755692af5SMark Brown ab8500->irq_base, ab8500->domain); 150862579266SRabin Vincent if (ret) 15098c4203cbSLee Jones return ret; 151062579266SRabin Vincent 15116ef9418cSRickard Andersson if (!no_bm) { 15126ef9418cSRickard Andersson /* Add battery management devices */ 15136ef9418cSRickard Andersson ret = mfd_add_devices(ab8500->dev, 0, ab8500_bm_devs, 15146ef9418cSRickard Andersson ARRAY_SIZE(ab8500_bm_devs), NULL, 151555692af5SMark Brown ab8500->irq_base, ab8500->domain); 15166ef9418cSRickard Andersson if (ret) 15176ef9418cSRickard Andersson dev_err(ab8500->dev, "error adding bm devices\n"); 15186ef9418cSRickard Andersson } 15196ef9418cSRickard Andersson 1520d6255529SLinus Walleij if (is_ab9540(ab8500)) 1521d6255529SLinus Walleij ret = sysfs_create_group(&ab8500->dev->kobj, 1522d6255529SLinus Walleij &ab9540_attr_group); 1523d6255529SLinus Walleij else 1524d6255529SLinus Walleij ret = sysfs_create_group(&ab8500->dev->kobj, 1525d6255529SLinus Walleij &ab8500_attr_group); 1526cca69b67SMattias Wallin if (ret) 1527cca69b67SMattias Wallin dev_err(ab8500->dev, "error creating sysfs entries\n"); 152806e589efSLee Jones 152962579266SRabin Vincent return ret; 153062579266SRabin Vincent } 153162579266SRabin Vincent 15324740f73fSBill Pemberton static int ab8500_remove(struct platform_device *pdev) 153362579266SRabin Vincent { 1534d28f1db8SLee Jones struct ab8500 *ab8500 = platform_get_drvdata(pdev); 1535d28f1db8SLee Jones 1536d6255529SLinus Walleij if (is_ab9540(ab8500)) 1537d6255529SLinus Walleij sysfs_remove_group(&ab8500->dev->kobj, &ab9540_attr_group); 1538d6255529SLinus Walleij else 1539cca69b67SMattias Wallin sysfs_remove_group(&ab8500->dev->kobj, &ab8500_attr_group); 154006e589efSLee Jones 154162579266SRabin Vincent mfd_remove_devices(ab8500->dev); 154262579266SRabin Vincent 154362579266SRabin Vincent return 0; 154462579266SRabin Vincent } 154562579266SRabin Vincent 1546d28f1db8SLee Jones static const struct platform_device_id ab8500_id[] = { 1547d28f1db8SLee Jones { "ab8500-core", AB8500_VERSION_AB8500 }, 1548d28f1db8SLee Jones { "ab8505-i2c", AB8500_VERSION_AB8505 }, 1549d28f1db8SLee Jones { "ab9540-i2c", AB8500_VERSION_AB9540 }, 1550d28f1db8SLee Jones { "ab8540-i2c", AB8500_VERSION_AB8540 }, 1551d28f1db8SLee Jones { } 1552d28f1db8SLee Jones }; 1553d28f1db8SLee Jones 1554d28f1db8SLee Jones static struct platform_driver ab8500_core_driver = { 1555d28f1db8SLee Jones .driver = { 1556d28f1db8SLee Jones .name = "ab8500-core", 1557d28f1db8SLee Jones .owner = THIS_MODULE, 1558d28f1db8SLee Jones }, 1559d28f1db8SLee Jones .probe = ab8500_probe, 156084449216SBill Pemberton .remove = ab8500_remove, 1561d28f1db8SLee Jones .id_table = ab8500_id, 1562d28f1db8SLee Jones }; 1563d28f1db8SLee Jones 1564d28f1db8SLee Jones static int __init ab8500_core_init(void) 1565d28f1db8SLee Jones { 1566d28f1db8SLee Jones return platform_driver_register(&ab8500_core_driver); 1567d28f1db8SLee Jones } 1568d28f1db8SLee Jones 1569d28f1db8SLee Jones static void __exit ab8500_core_exit(void) 1570d28f1db8SLee Jones { 1571d28f1db8SLee Jones platform_driver_unregister(&ab8500_core_driver); 1572d28f1db8SLee Jones } 1573ba7cbc3eSLee Jones core_initcall(ab8500_core_init); 1574d28f1db8SLee Jones module_exit(ab8500_core_exit); 1575d28f1db8SLee Jones 1576adceed62SMattias Wallin MODULE_AUTHOR("Mattias Wallin, Srinidhi Kasagar, Rabin Vincent"); 157762579266SRabin Vincent MODULE_DESCRIPTION("AB8500 MFD core"); 157862579266SRabin Vincent MODULE_LICENSE("GPL v2"); 1579