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 98a29264b6SLee 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 1063e1a498fSLee Jones #define AB8540_IT_LATCHHIER4_REG 0x63 1077ccfe9b1SMichel JAOUEN 1087ccfe9b1SMichel JAOUEN #define AB8500_IT_LATCHHIER_NUM 3 1093e1a498fSLee Jones #define AB8540_IT_LATCHHIER_NUM 4 1107ccfe9b1SMichel JAOUEN 11147c16975SMattias Wallin #define AB8500_REV_REG 0x80 1120f620837SLinus Walleij #define AB8500_IC_NAME_REG 0x82 113e5c238c3SMattias Wallin #define AB8500_SWITCH_OFF_STATUS 0x00 11462579266SRabin Vincent 115b4a31037SAndrew Lynn #define AB8500_TURN_ON_STATUS 0x00 11693ff722eSLee Jones #define AB8505_TURN_ON_STATUS_2 0x04 117b4a31037SAndrew Lynn 118f04a9d8aSRajkumar Kasirajan #define AB8500_CH_USBCH_STAT1_REG 0x02 119f04a9d8aSRajkumar Kasirajan #define VBUS_DET_DBNC100 0x02 120f04a9d8aSRajkumar Kasirajan #define VBUS_DET_DBNC1 0x01 121f04a9d8aSRajkumar Kasirajan 122f04a9d8aSRajkumar Kasirajan static DEFINE_SPINLOCK(on_stat_lock); 123f04a9d8aSRajkumar Kasirajan static u8 turn_on_stat_mask = 0xFF; 124f04a9d8aSRajkumar Kasirajan static u8 turn_on_stat_set; 1256ef9418cSRickard Andersson static bool no_bm; /* No battery management */ 1266ef9418cSRickard Andersson module_param(no_bm, bool, S_IRUGO); 1276ef9418cSRickard Andersson 128d6255529SLinus Walleij #define AB9540_MODEM_CTRL2_REG 0x23 129d6255529SLinus Walleij #define AB9540_MODEM_CTRL2_SWDBBRSTN_BIT BIT(2) 130d6255529SLinus Walleij 13162579266SRabin Vincent /* 13262579266SRabin Vincent * Map interrupt numbers to the LATCH and MASK register offsets, Interrupt 1332ced445eSLinus Walleij * numbers are indexed into this array with (num / 8). The interupts are 1342ced445eSLinus Walleij * defined in linux/mfd/ab8500.h 13562579266SRabin Vincent * 13662579266SRabin Vincent * This is one off from the register names, i.e. AB8500_IT_MASK1_REG is at 13762579266SRabin Vincent * offset 0. 13862579266SRabin Vincent */ 1392ced445eSLinus Walleij /* AB8500 support */ 14062579266SRabin Vincent static const int ab8500_irq_regoffset[AB8500_NUM_IRQ_REGS] = { 14192d50a41SMattias Wallin 0, 1, 2, 3, 4, 6, 7, 8, 9, 11, 18, 19, 20, 21, 14262579266SRabin Vincent }; 14362579266SRabin Vincent 144a29264b6SLee Jones /* AB9540 / AB8505 support */ 145d6255529SLinus Walleij static const int ab9540_irq_regoffset[AB9540_NUM_IRQ_REGS] = { 146a29264b6SLee Jones 0, 1, 2, 3, 4, 6, 7, 8, 9, 11, 18, 19, 20, 21, 12, 13, 24, 5, 22, 23 147d6255529SLinus Walleij }; 148d6255529SLinus Walleij 1493e1a498fSLee Jones /* AB8540 support */ 1503e1a498fSLee Jones static const int ab8540_irq_regoffset[AB8540_NUM_IRQ_REGS] = { 1513e1a498fSLee Jones 0, 1, 2, 3, 4, -1, -1, -1, -1, 11, 18, 19, 20, 21, 12, 13, 24, 5, 22, 23, 1523e1a498fSLee Jones 25, 26, 27, 28, 29, 30, 31, 1533e1a498fSLee Jones }; 1543e1a498fSLee Jones 1550f620837SLinus Walleij static const char ab8500_version_str[][7] = { 1560f620837SLinus Walleij [AB8500_VERSION_AB8500] = "AB8500", 1570f620837SLinus Walleij [AB8500_VERSION_AB8505] = "AB8505", 1580f620837SLinus Walleij [AB8500_VERSION_AB9540] = "AB9540", 1590f620837SLinus Walleij [AB8500_VERSION_AB8540] = "AB8540", 1600f620837SLinus Walleij }; 1610f620837SLinus Walleij 162822672a7SLee Jones static int ab8500_prcmu_write(struct ab8500 *ab8500, u16 addr, u8 data) 163d28f1db8SLee Jones { 164d28f1db8SLee Jones int ret; 165d28f1db8SLee Jones 166d28f1db8SLee Jones ret = prcmu_abb_write((u8)(addr >> 8), (u8)(addr & 0xFF), &data, 1); 167d28f1db8SLee Jones if (ret < 0) 168d28f1db8SLee Jones dev_err(ab8500->dev, "prcmu i2c error %d\n", ret); 169d28f1db8SLee Jones return ret; 170d28f1db8SLee Jones } 171d28f1db8SLee Jones 172822672a7SLee Jones static int ab8500_prcmu_write_masked(struct ab8500 *ab8500, u16 addr, u8 mask, 173d28f1db8SLee Jones u8 data) 174d28f1db8SLee Jones { 175d28f1db8SLee Jones int ret; 176d28f1db8SLee Jones 177d28f1db8SLee Jones ret = prcmu_abb_write_masked((u8)(addr >> 8), (u8)(addr & 0xFF), &data, 178d28f1db8SLee Jones &mask, 1); 179d28f1db8SLee Jones if (ret < 0) 180d28f1db8SLee Jones dev_err(ab8500->dev, "prcmu i2c error %d\n", ret); 181d28f1db8SLee Jones return ret; 182d28f1db8SLee Jones } 183d28f1db8SLee Jones 184822672a7SLee Jones static int ab8500_prcmu_read(struct ab8500 *ab8500, u16 addr) 185d28f1db8SLee Jones { 186d28f1db8SLee Jones int ret; 187d28f1db8SLee Jones u8 data; 188d28f1db8SLee Jones 189d28f1db8SLee Jones ret = prcmu_abb_read((u8)(addr >> 8), (u8)(addr & 0xFF), &data, 1); 190d28f1db8SLee Jones if (ret < 0) { 191d28f1db8SLee Jones dev_err(ab8500->dev, "prcmu i2c error %d\n", ret); 192d28f1db8SLee Jones return ret; 193d28f1db8SLee Jones } 194d28f1db8SLee Jones return (int)data; 195d28f1db8SLee Jones } 196d28f1db8SLee Jones 19747c16975SMattias Wallin static int ab8500_get_chip_id(struct device *dev) 19847c16975SMattias Wallin { 1996bce7bf1SMattias Wallin struct ab8500 *ab8500; 2006bce7bf1SMattias Wallin 2016bce7bf1SMattias Wallin if (!dev) 2026bce7bf1SMattias Wallin return -EINVAL; 2036bce7bf1SMattias Wallin ab8500 = dev_get_drvdata(dev->parent); 2046bce7bf1SMattias Wallin return ab8500 ? (int)ab8500->chip_id : -EINVAL; 20547c16975SMattias Wallin } 20647c16975SMattias Wallin 20747c16975SMattias Wallin static int set_register_interruptible(struct ab8500 *ab8500, u8 bank, 20847c16975SMattias Wallin u8 reg, u8 data) 20962579266SRabin Vincent { 21062579266SRabin Vincent int ret; 21147c16975SMattias Wallin /* 21247c16975SMattias Wallin * Put the u8 bank and u8 register together into a an u16. 21347c16975SMattias Wallin * The bank on higher 8 bits and register in lower 8 bits. 21447c16975SMattias Wallin * */ 21547c16975SMattias Wallin u16 addr = ((u16)bank) << 8 | reg; 21662579266SRabin Vincent 21762579266SRabin Vincent dev_vdbg(ab8500->dev, "wr: addr %#x <= %#x\n", addr, data); 21862579266SRabin Vincent 219392cbd1eSRabin Vincent mutex_lock(&ab8500->lock); 22047c16975SMattias Wallin 22147c16975SMattias Wallin ret = ab8500->write(ab8500, addr, data); 22247c16975SMattias Wallin if (ret < 0) 22347c16975SMattias Wallin dev_err(ab8500->dev, "failed to write reg %#x: %d\n", 22447c16975SMattias Wallin addr, ret); 22547c16975SMattias Wallin mutex_unlock(&ab8500->lock); 22647c16975SMattias Wallin 22747c16975SMattias Wallin return ret; 22847c16975SMattias Wallin } 22947c16975SMattias Wallin 23047c16975SMattias Wallin static int ab8500_set_register(struct device *dev, u8 bank, 23147c16975SMattias Wallin u8 reg, u8 value) 23247c16975SMattias Wallin { 233112a80d2SJonas Aaberg int ret; 23447c16975SMattias Wallin struct ab8500 *ab8500 = dev_get_drvdata(dev->parent); 23547c16975SMattias Wallin 236112a80d2SJonas Aaberg atomic_inc(&ab8500->transfer_ongoing); 237112a80d2SJonas Aaberg ret = set_register_interruptible(ab8500, bank, reg, value); 238112a80d2SJonas Aaberg atomic_dec(&ab8500->transfer_ongoing); 239112a80d2SJonas Aaberg return ret; 24047c16975SMattias Wallin } 24147c16975SMattias Wallin 24247c16975SMattias Wallin static int get_register_interruptible(struct ab8500 *ab8500, u8 bank, 24347c16975SMattias Wallin u8 reg, u8 *value) 24447c16975SMattias Wallin { 24547c16975SMattias Wallin int ret; 24647c16975SMattias Wallin /* put the u8 bank and u8 reg together into a an u16. 24747c16975SMattias Wallin * bank on higher 8 bits and reg in lower */ 24847c16975SMattias Wallin u16 addr = ((u16)bank) << 8 | reg; 24947c16975SMattias Wallin 250392cbd1eSRabin Vincent mutex_lock(&ab8500->lock); 25147c16975SMattias Wallin 25247c16975SMattias Wallin ret = ab8500->read(ab8500, addr); 25347c16975SMattias Wallin if (ret < 0) 25447c16975SMattias Wallin dev_err(ab8500->dev, "failed to read reg %#x: %d\n", 25547c16975SMattias Wallin addr, ret); 25647c16975SMattias Wallin else 25747c16975SMattias Wallin *value = ret; 25847c16975SMattias Wallin 25947c16975SMattias Wallin mutex_unlock(&ab8500->lock); 26047c16975SMattias Wallin dev_vdbg(ab8500->dev, "rd: addr %#x => data %#x\n", addr, ret); 26147c16975SMattias Wallin 26247c16975SMattias Wallin return ret; 26347c16975SMattias Wallin } 26447c16975SMattias Wallin 26547c16975SMattias Wallin static int ab8500_get_register(struct device *dev, u8 bank, 26647c16975SMattias Wallin u8 reg, u8 *value) 26747c16975SMattias Wallin { 268112a80d2SJonas Aaberg int ret; 26947c16975SMattias Wallin struct ab8500 *ab8500 = dev_get_drvdata(dev->parent); 27047c16975SMattias Wallin 271112a80d2SJonas Aaberg atomic_inc(&ab8500->transfer_ongoing); 272112a80d2SJonas Aaberg ret = get_register_interruptible(ab8500, bank, reg, value); 273112a80d2SJonas Aaberg atomic_dec(&ab8500->transfer_ongoing); 274112a80d2SJonas Aaberg return ret; 27547c16975SMattias Wallin } 27647c16975SMattias Wallin 27747c16975SMattias Wallin static int mask_and_set_register_interruptible(struct ab8500 *ab8500, u8 bank, 27847c16975SMattias Wallin u8 reg, u8 bitmask, u8 bitvalues) 27947c16975SMattias Wallin { 28047c16975SMattias Wallin int ret; 28147c16975SMattias Wallin /* put the u8 bank and u8 reg together into a an u16. 28247c16975SMattias Wallin * bank on higher 8 bits and reg in lower */ 28347c16975SMattias Wallin u16 addr = ((u16)bank) << 8 | reg; 28447c16975SMattias Wallin 285392cbd1eSRabin Vincent mutex_lock(&ab8500->lock); 28647c16975SMattias Wallin 287bc628fd1SMattias Nilsson if (ab8500->write_masked == NULL) { 288bc628fd1SMattias Nilsson u8 data; 289bc628fd1SMattias Nilsson 29047c16975SMattias Wallin ret = ab8500->read(ab8500, addr); 29147c16975SMattias Wallin if (ret < 0) { 29247c16975SMattias Wallin dev_err(ab8500->dev, "failed to read reg %#x: %d\n", 29347c16975SMattias Wallin addr, ret); 29447c16975SMattias Wallin goto out; 29547c16975SMattias Wallin } 29647c16975SMattias Wallin 29747c16975SMattias Wallin data = (u8)ret; 29847c16975SMattias Wallin data = (~bitmask & data) | (bitmask & bitvalues); 29947c16975SMattias Wallin 30062579266SRabin Vincent ret = ab8500->write(ab8500, addr, data); 30162579266SRabin Vincent if (ret < 0) 30262579266SRabin Vincent dev_err(ab8500->dev, "failed to write reg %#x: %d\n", 30362579266SRabin Vincent addr, ret); 30462579266SRabin Vincent 305bc628fd1SMattias Nilsson dev_vdbg(ab8500->dev, "mask: addr %#x => data %#x\n", addr, 306bc628fd1SMattias Nilsson data); 307bc628fd1SMattias Nilsson goto out; 308bc628fd1SMattias Nilsson } 309bc628fd1SMattias Nilsson ret = ab8500->write_masked(ab8500, addr, bitmask, bitvalues); 310bc628fd1SMattias Nilsson if (ret < 0) 311bc628fd1SMattias Nilsson dev_err(ab8500->dev, "failed to modify reg %#x: %d\n", addr, 312bc628fd1SMattias Nilsson ret); 31362579266SRabin Vincent out: 31462579266SRabin Vincent mutex_unlock(&ab8500->lock); 31562579266SRabin Vincent return ret; 31662579266SRabin Vincent } 31747c16975SMattias Wallin 31847c16975SMattias Wallin static int ab8500_mask_and_set_register(struct device *dev, 31947c16975SMattias Wallin u8 bank, u8 reg, u8 bitmask, u8 bitvalues) 32047c16975SMattias Wallin { 321112a80d2SJonas Aaberg int ret; 32247c16975SMattias Wallin struct ab8500 *ab8500 = dev_get_drvdata(dev->parent); 32347c16975SMattias Wallin 324112a80d2SJonas Aaberg atomic_inc(&ab8500->transfer_ongoing); 325112a80d2SJonas Aaberg ret= mask_and_set_register_interruptible(ab8500, bank, reg, 32647c16975SMattias Wallin bitmask, bitvalues); 327112a80d2SJonas Aaberg atomic_dec(&ab8500->transfer_ongoing); 328112a80d2SJonas Aaberg return ret; 32947c16975SMattias Wallin } 33047c16975SMattias Wallin 33147c16975SMattias Wallin static struct abx500_ops ab8500_ops = { 33247c16975SMattias Wallin .get_chip_id = ab8500_get_chip_id, 33347c16975SMattias Wallin .get_register = ab8500_get_register, 33447c16975SMattias Wallin .set_register = ab8500_set_register, 33547c16975SMattias Wallin .get_register_page = NULL, 33647c16975SMattias Wallin .set_register_page = NULL, 33747c16975SMattias Wallin .mask_and_set_register = ab8500_mask_and_set_register, 33847c16975SMattias Wallin .event_registers_startup_state_get = NULL, 33947c16975SMattias Wallin .startup_irq_enabled = NULL, 3401d843a6cSMian Yousaf Kaukab .dump_all_banks = ab8500_dump_all_banks, 34147c16975SMattias Wallin }; 34262579266SRabin Vincent 3439505a0a0SMark Brown static void ab8500_irq_lock(struct irq_data *data) 34462579266SRabin Vincent { 3459505a0a0SMark Brown struct ab8500 *ab8500 = irq_data_get_irq_chip_data(data); 34662579266SRabin Vincent 34762579266SRabin Vincent mutex_lock(&ab8500->irq_lock); 348112a80d2SJonas Aaberg atomic_inc(&ab8500->transfer_ongoing); 34962579266SRabin Vincent } 35062579266SRabin Vincent 3519505a0a0SMark Brown static void ab8500_irq_sync_unlock(struct irq_data *data) 35262579266SRabin Vincent { 3539505a0a0SMark Brown struct ab8500 *ab8500 = irq_data_get_irq_chip_data(data); 35462579266SRabin Vincent int i; 35562579266SRabin Vincent 3562ced445eSLinus Walleij for (i = 0; i < ab8500->mask_size; i++) { 35762579266SRabin Vincent u8 old = ab8500->oldmask[i]; 35862579266SRabin Vincent u8 new = ab8500->mask[i]; 35962579266SRabin Vincent int reg; 36062579266SRabin Vincent 36162579266SRabin Vincent if (new == old) 36262579266SRabin Vincent continue; 36362579266SRabin Vincent 3640f620837SLinus Walleij /* 3650f620837SLinus Walleij * Interrupt register 12 doesn't exist prior to AB8500 version 3660f620837SLinus Walleij * 2.0 3670f620837SLinus Walleij */ 3680f620837SLinus Walleij if (ab8500->irq_reg_offset[i] == 11 && 3690f620837SLinus Walleij is_ab8500_1p1_or_earlier(ab8500)) 37092d50a41SMattias Wallin continue; 37192d50a41SMattias Wallin 3723e1a498fSLee Jones if (ab8500->irq_reg_offset[i] < 0) 3733e1a498fSLee Jones continue; 3743e1a498fSLee Jones 37562579266SRabin Vincent ab8500->oldmask[i] = new; 37662579266SRabin Vincent 3772ced445eSLinus Walleij reg = AB8500_IT_MASK1_REG + ab8500->irq_reg_offset[i]; 37847c16975SMattias Wallin set_register_interruptible(ab8500, AB8500_INTERRUPT, reg, new); 37962579266SRabin Vincent } 380112a80d2SJonas Aaberg atomic_dec(&ab8500->transfer_ongoing); 38162579266SRabin Vincent mutex_unlock(&ab8500->irq_lock); 38262579266SRabin Vincent } 38362579266SRabin Vincent 3849505a0a0SMark Brown static void ab8500_irq_mask(struct irq_data *data) 38562579266SRabin Vincent { 3869505a0a0SMark Brown struct ab8500 *ab8500 = irq_data_get_irq_chip_data(data); 38706e589efSLee Jones int offset = data->hwirq; 38862579266SRabin Vincent int index = offset / 8; 38962579266SRabin Vincent int mask = 1 << (offset % 8); 39062579266SRabin Vincent 39162579266SRabin Vincent ab8500->mask[index] |= mask; 3929c677b9bSLee Jones 3939c677b9bSLee Jones /* The AB8500 GPIOs have two interrupts each (rising & falling). */ 3949c677b9bSLee Jones if (offset >= AB8500_INT_GPIO6R && offset <= AB8500_INT_GPIO41R) 3959c677b9bSLee Jones ab8500->mask[index + 2] |= mask; 3969c677b9bSLee Jones if (offset >= AB9540_INT_GPIO50R && offset <= AB9540_INT_GPIO54R) 3979c677b9bSLee Jones ab8500->mask[index + 1] |= mask; 3989c677b9bSLee Jones if (offset == AB8540_INT_GPIO43R || offset == AB8540_INT_GPIO44R) 399e2ddf46aSLinus Walleij /* Here the falling IRQ is one bit lower */ 400e2ddf46aSLinus Walleij ab8500->mask[index] |= (mask << 1); 40162579266SRabin Vincent } 40262579266SRabin Vincent 4039505a0a0SMark Brown static void ab8500_irq_unmask(struct irq_data *data) 40462579266SRabin Vincent { 4059505a0a0SMark Brown struct ab8500 *ab8500 = irq_data_get_irq_chip_data(data); 4069c677b9bSLee Jones unsigned int type = irqd_get_trigger_type(data); 40706e589efSLee Jones int offset = data->hwirq; 40862579266SRabin Vincent int index = offset / 8; 40962579266SRabin Vincent int mask = 1 << (offset % 8); 41062579266SRabin Vincent 4119c677b9bSLee Jones if (type & IRQ_TYPE_EDGE_RISING) 41262579266SRabin Vincent ab8500->mask[index] &= ~mask; 4139c677b9bSLee Jones 4149c677b9bSLee Jones /* The AB8500 GPIOs have two interrupts each (rising & falling). */ 4159c677b9bSLee Jones if (type & IRQ_TYPE_EDGE_FALLING) { 4169c677b9bSLee Jones if (offset >= AB8500_INT_GPIO6R && offset <= AB8500_INT_GPIO41R) 4179c677b9bSLee Jones ab8500->mask[index + 2] &= ~mask; 4189c677b9bSLee Jones else if (offset >= AB9540_INT_GPIO50R && offset <= AB9540_INT_GPIO54R) 4199c677b9bSLee Jones ab8500->mask[index + 1] &= ~mask; 4209c677b9bSLee Jones else if (offset == AB8540_INT_GPIO43R || offset == AB8540_INT_GPIO44R) 421e2ddf46aSLinus Walleij /* Here the falling IRQ is one bit lower */ 422e2ddf46aSLinus Walleij ab8500->mask[index] &= ~(mask << 1); 4239c677b9bSLee Jones else 4249c677b9bSLee Jones ab8500->mask[index] &= ~mask; 425e2ddf46aSLinus Walleij } else { 4269c677b9bSLee Jones /* Satisfies the case where type is not set. */ 42762579266SRabin Vincent ab8500->mask[index] &= ~mask; 42862579266SRabin Vincent } 429e2ddf46aSLinus Walleij } 43062579266SRabin Vincent 43140f6e5a2SLee Jones static int ab8500_irq_set_type(struct irq_data *data, unsigned int type) 43240f6e5a2SLee Jones { 43340f6e5a2SLee Jones return 0; 43462579266SRabin Vincent } 43562579266SRabin Vincent 43662579266SRabin Vincent static struct irq_chip ab8500_irq_chip = { 43762579266SRabin Vincent .name = "ab8500", 4389505a0a0SMark Brown .irq_bus_lock = ab8500_irq_lock, 4399505a0a0SMark Brown .irq_bus_sync_unlock = ab8500_irq_sync_unlock, 4409505a0a0SMark Brown .irq_mask = ab8500_irq_mask, 441e6f9306eSVirupax Sadashivpetimath .irq_disable = ab8500_irq_mask, 4429505a0a0SMark Brown .irq_unmask = ab8500_irq_unmask, 44340f6e5a2SLee Jones .irq_set_type = ab8500_irq_set_type, 44462579266SRabin Vincent }; 44562579266SRabin Vincent 4463e1a498fSLee Jones static void update_latch_offset(u8 *offset, int i) 4473e1a498fSLee Jones { 4483e1a498fSLee Jones /* Fix inconsistent ITFromLatch25 bit mapping... */ 4493e1a498fSLee Jones if (unlikely(*offset == 17)) 4503e1a498fSLee Jones *offset = 24; 4513e1a498fSLee Jones /* Fix inconsistent ab8540 bit mapping... */ 4523e1a498fSLee Jones if (unlikely(*offset == 16)) 4533e1a498fSLee Jones *offset = 25; 4543e1a498fSLee Jones if ((i==3) && (*offset >= 24)) 4553e1a498fSLee Jones *offset += 2; 4563e1a498fSLee Jones } 4573e1a498fSLee Jones 4587ccfe9b1SMichel JAOUEN static int ab8500_handle_hierarchical_line(struct ab8500 *ab8500, 4597ccfe9b1SMichel JAOUEN int latch_offset, u8 latch_val) 4607ccfe9b1SMichel JAOUEN { 4617a93fb37SFabio Baltieri int int_bit, line, i; 4627ccfe9b1SMichel JAOUEN 4637ccfe9b1SMichel JAOUEN for (i = 0; i < ab8500->mask_size; i++) 4647ccfe9b1SMichel JAOUEN if (ab8500->irq_reg_offset[i] == latch_offset) 4657ccfe9b1SMichel JAOUEN break; 4667ccfe9b1SMichel JAOUEN 4677ccfe9b1SMichel JAOUEN if (i >= ab8500->mask_size) { 4687ccfe9b1SMichel JAOUEN dev_err(ab8500->dev, "Register offset 0x%2x not declared\n", 4697ccfe9b1SMichel JAOUEN latch_offset); 4707ccfe9b1SMichel JAOUEN return -ENXIO; 4717ccfe9b1SMichel JAOUEN } 4727ccfe9b1SMichel JAOUEN 4737a93fb37SFabio Baltieri /* ignore masked out interrupts */ 4747a93fb37SFabio Baltieri latch_val &= ~ab8500->mask[i]; 4757a93fb37SFabio Baltieri 4767a93fb37SFabio Baltieri while (latch_val) { 4777a93fb37SFabio Baltieri int_bit = __ffs(latch_val); 4787ccfe9b1SMichel JAOUEN line = (i << 3) + int_bit; 4797ccfe9b1SMichel JAOUEN latch_val &= ~(1 << int_bit); 4807ccfe9b1SMichel JAOUEN 481e2ddf46aSLinus Walleij /* 482e2ddf46aSLinus Walleij * This handles the falling edge hwirqs from the GPIO 483e2ddf46aSLinus Walleij * lines. Route them back to the line registered for the 484e2ddf46aSLinus Walleij * rising IRQ, as this is merely a flag for the same IRQ 485e2ddf46aSLinus Walleij * in linux terms. 486e2ddf46aSLinus Walleij */ 487e2ddf46aSLinus Walleij if (line >= AB8500_INT_GPIO6F && line <= AB8500_INT_GPIO41F) 488e2ddf46aSLinus Walleij line -= 16; 489e2ddf46aSLinus Walleij if (line >= AB9540_INT_GPIO50F && line <= AB9540_INT_GPIO54F) 490e2ddf46aSLinus Walleij line -= 8; 491e2ddf46aSLinus Walleij if (line == AB8540_INT_GPIO43F || line == AB8540_INT_GPIO44F) 492e2ddf46aSLinus Walleij line += 1; 493e2ddf46aSLinus Walleij 4947ccfe9b1SMichel JAOUEN handle_nested_irq(ab8500->irq_base + line); 4957a93fb37SFabio Baltieri } 4967ccfe9b1SMichel JAOUEN 4977ccfe9b1SMichel JAOUEN return 0; 4987ccfe9b1SMichel JAOUEN } 4997ccfe9b1SMichel JAOUEN 5007ccfe9b1SMichel JAOUEN static int ab8500_handle_hierarchical_latch(struct ab8500 *ab8500, 5017ccfe9b1SMichel JAOUEN int hier_offset, u8 hier_val) 5027ccfe9b1SMichel JAOUEN { 5037ccfe9b1SMichel JAOUEN int latch_bit, status; 5047ccfe9b1SMichel JAOUEN u8 latch_offset, latch_val; 5057ccfe9b1SMichel JAOUEN 5067ccfe9b1SMichel JAOUEN do { 5077ccfe9b1SMichel JAOUEN latch_bit = __ffs(hier_val); 5087ccfe9b1SMichel JAOUEN latch_offset = (hier_offset << 3) + latch_bit; 5097ccfe9b1SMichel JAOUEN 5103e1a498fSLee Jones update_latch_offset(&latch_offset, hier_offset); 5117ccfe9b1SMichel JAOUEN 5127ccfe9b1SMichel JAOUEN status = get_register_interruptible(ab8500, 5137ccfe9b1SMichel JAOUEN AB8500_INTERRUPT, 5147ccfe9b1SMichel JAOUEN AB8500_IT_LATCH1_REG + latch_offset, 5157ccfe9b1SMichel JAOUEN &latch_val); 5167ccfe9b1SMichel JAOUEN if (status < 0 || latch_val == 0) 5177ccfe9b1SMichel JAOUEN goto discard; 5187ccfe9b1SMichel JAOUEN 5197ccfe9b1SMichel JAOUEN status = ab8500_handle_hierarchical_line(ab8500, 5207ccfe9b1SMichel JAOUEN latch_offset, latch_val); 5217ccfe9b1SMichel JAOUEN if (status < 0) 5227ccfe9b1SMichel JAOUEN return status; 5237ccfe9b1SMichel JAOUEN discard: 5247ccfe9b1SMichel JAOUEN hier_val &= ~(1 << latch_bit); 5257ccfe9b1SMichel JAOUEN } while (hier_val); 5267ccfe9b1SMichel JAOUEN 5277ccfe9b1SMichel JAOUEN return 0; 5287ccfe9b1SMichel JAOUEN } 5297ccfe9b1SMichel JAOUEN 5307ccfe9b1SMichel JAOUEN static irqreturn_t ab8500_hierarchical_irq(int irq, void *dev) 5317ccfe9b1SMichel JAOUEN { 5327ccfe9b1SMichel JAOUEN struct ab8500 *ab8500 = dev; 5337ccfe9b1SMichel JAOUEN u8 i; 5347ccfe9b1SMichel JAOUEN 5357ccfe9b1SMichel JAOUEN dev_vdbg(ab8500->dev, "interrupt\n"); 5367ccfe9b1SMichel JAOUEN 5377ccfe9b1SMichel JAOUEN /* Hierarchical interrupt version */ 5383e1a498fSLee Jones for (i = 0; i < (ab8500->it_latchhier_num); i++) { 5397ccfe9b1SMichel JAOUEN int status; 5407ccfe9b1SMichel JAOUEN u8 hier_val; 5417ccfe9b1SMichel JAOUEN 5427ccfe9b1SMichel JAOUEN status = get_register_interruptible(ab8500, AB8500_INTERRUPT, 5437ccfe9b1SMichel JAOUEN AB8500_IT_LATCHHIER1_REG + i, &hier_val); 5447ccfe9b1SMichel JAOUEN if (status < 0 || hier_val == 0) 5457ccfe9b1SMichel JAOUEN continue; 5467ccfe9b1SMichel JAOUEN 5477ccfe9b1SMichel JAOUEN status = ab8500_handle_hierarchical_latch(ab8500, i, hier_val); 5487ccfe9b1SMichel JAOUEN if (status < 0) 5497ccfe9b1SMichel JAOUEN break; 5507ccfe9b1SMichel JAOUEN } 5517ccfe9b1SMichel JAOUEN return IRQ_HANDLED; 5527ccfe9b1SMichel JAOUEN } 5537ccfe9b1SMichel JAOUEN 55406e589efSLee Jones static int ab8500_irq_map(struct irq_domain *d, unsigned int virq, 55506e589efSLee Jones irq_hw_number_t hwirq) 55606e589efSLee Jones { 55706e589efSLee Jones struct ab8500 *ab8500 = d->host_data; 55806e589efSLee Jones 55906e589efSLee Jones if (!ab8500) 56006e589efSLee Jones return -EINVAL; 56106e589efSLee Jones 56206e589efSLee Jones irq_set_chip_data(virq, ab8500); 56306e589efSLee Jones irq_set_chip_and_handler(virq, &ab8500_irq_chip, 56406e589efSLee Jones handle_simple_irq); 56506e589efSLee Jones irq_set_nested_thread(virq, 1); 56606e589efSLee Jones #ifdef CONFIG_ARM 56706e589efSLee Jones set_irq_flags(virq, IRQF_VALID); 56806e589efSLee Jones #else 56906e589efSLee Jones irq_set_noprobe(virq); 57006e589efSLee Jones #endif 57162579266SRabin Vincent 57262579266SRabin Vincent return 0; 57362579266SRabin Vincent } 57462579266SRabin Vincent 57506e589efSLee Jones static struct irq_domain_ops ab8500_irq_ops = { 57606e589efSLee Jones .map = ab8500_irq_map, 57706e589efSLee Jones .xlate = irq_domain_xlate_twocell, 57806e589efSLee Jones }; 57906e589efSLee Jones 58006e589efSLee Jones static int ab8500_irq_init(struct ab8500 *ab8500, struct device_node *np) 58162579266SRabin Vincent { 5822ced445eSLinus Walleij int num_irqs; 58362579266SRabin Vincent 5843e1a498fSLee Jones if (is_ab8540(ab8500)) 5853e1a498fSLee Jones num_irqs = AB8540_NR_IRQS; 5863e1a498fSLee Jones else if (is_ab9540(ab8500)) 587d6255529SLinus Walleij num_irqs = AB9540_NR_IRQS; 588a982362cSBengt Jonsson else if (is_ab8505(ab8500)) 589a982362cSBengt Jonsson num_irqs = AB8505_NR_IRQS; 590d6255529SLinus Walleij else 5912ced445eSLinus Walleij num_irqs = AB8500_NR_IRQS; 5922ced445eSLinus Walleij 593f1d11f39SLinus Walleij /* If ->irq_base is zero this will give a linear mapping */ 594f1d11f39SLinus Walleij ab8500->domain = irq_domain_add_simple(NULL, 595f1d11f39SLinus Walleij num_irqs, ab8500->irq_base, 596f1d11f39SLinus Walleij &ab8500_irq_ops, ab8500); 59706e589efSLee Jones 59806e589efSLee Jones if (!ab8500->domain) { 59906e589efSLee Jones dev_err(ab8500->dev, "Failed to create irqdomain\n"); 60006e589efSLee Jones return -ENOSYS; 60106e589efSLee Jones } 60206e589efSLee Jones 60306e589efSLee Jones return 0; 60462579266SRabin Vincent } 60562579266SRabin Vincent 606112a80d2SJonas Aaberg int ab8500_suspend(struct ab8500 *ab8500) 607112a80d2SJonas Aaberg { 608112a80d2SJonas Aaberg if (atomic_read(&ab8500->transfer_ongoing)) 609112a80d2SJonas Aaberg return -EINVAL; 610112a80d2SJonas Aaberg else 611112a80d2SJonas Aaberg return 0; 612112a80d2SJonas Aaberg } 613112a80d2SJonas Aaberg 614a9e9ce4cSBill Pemberton static struct resource ab8500_gpadc_resources[] = { 61562579266SRabin Vincent { 61662579266SRabin Vincent .name = "HW_CONV_END", 61762579266SRabin Vincent .start = AB8500_INT_GP_HW_ADC_CONV_END, 61862579266SRabin Vincent .end = AB8500_INT_GP_HW_ADC_CONV_END, 61962579266SRabin Vincent .flags = IORESOURCE_IRQ, 62062579266SRabin Vincent }, 62162579266SRabin Vincent { 62262579266SRabin Vincent .name = "SW_CONV_END", 62362579266SRabin Vincent .start = AB8500_INT_GP_SW_ADC_CONV_END, 62462579266SRabin Vincent .end = AB8500_INT_GP_SW_ADC_CONV_END, 62562579266SRabin Vincent .flags = IORESOURCE_IRQ, 62662579266SRabin Vincent }, 62762579266SRabin Vincent }; 62862579266SRabin Vincent 6294b106fb9SLee Jones static struct resource ab8505_gpadc_resources[] = { 630c0eda9aeSLee Jones { 631c0eda9aeSLee Jones .name = "SW_CONV_END", 632c0eda9aeSLee Jones .start = AB8500_INT_GP_SW_ADC_CONV_END, 633c0eda9aeSLee Jones .end = AB8500_INT_GP_SW_ADC_CONV_END, 634c0eda9aeSLee Jones .flags = IORESOURCE_IRQ, 635c0eda9aeSLee Jones }, 636c0eda9aeSLee Jones }; 637c0eda9aeSLee Jones 638a9e9ce4cSBill Pemberton static struct resource ab8500_rtc_resources[] = { 63962579266SRabin Vincent { 64062579266SRabin Vincent .name = "60S", 64162579266SRabin Vincent .start = AB8500_INT_RTC_60S, 64262579266SRabin Vincent .end = AB8500_INT_RTC_60S, 64362579266SRabin Vincent .flags = IORESOURCE_IRQ, 64462579266SRabin Vincent }, 64562579266SRabin Vincent { 64662579266SRabin Vincent .name = "ALARM", 64762579266SRabin Vincent .start = AB8500_INT_RTC_ALARM, 64862579266SRabin Vincent .end = AB8500_INT_RTC_ALARM, 64962579266SRabin Vincent .flags = IORESOURCE_IRQ, 65062579266SRabin Vincent }, 65162579266SRabin Vincent }; 65262579266SRabin Vincent 653a9e9ce4cSBill Pemberton static struct resource ab8500_poweronkey_db_resources[] = { 65477686517SSundar R Iyer { 65577686517SSundar R Iyer .name = "ONKEY_DBF", 65677686517SSundar R Iyer .start = AB8500_INT_PON_KEY1DB_F, 65777686517SSundar R Iyer .end = AB8500_INT_PON_KEY1DB_F, 65877686517SSundar R Iyer .flags = IORESOURCE_IRQ, 65977686517SSundar R Iyer }, 66077686517SSundar R Iyer { 66177686517SSundar R Iyer .name = "ONKEY_DBR", 66277686517SSundar R Iyer .start = AB8500_INT_PON_KEY1DB_R, 66377686517SSundar R Iyer .end = AB8500_INT_PON_KEY1DB_R, 66477686517SSundar R Iyer .flags = IORESOURCE_IRQ, 66577686517SSundar R Iyer }, 66677686517SSundar R Iyer }; 66777686517SSundar R Iyer 668a9e9ce4cSBill Pemberton static struct resource ab8500_av_acc_detect_resources[] = { 669e098adedSMattias Wallin { 6706af75ecdSLinus Walleij .name = "ACC_DETECT_1DB_F", 6716af75ecdSLinus Walleij .start = AB8500_INT_ACC_DETECT_1DB_F, 6726af75ecdSLinus Walleij .end = AB8500_INT_ACC_DETECT_1DB_F, 673e098adedSMattias Wallin .flags = IORESOURCE_IRQ, 674e098adedSMattias Wallin }, 675e098adedSMattias Wallin { 6766af75ecdSLinus Walleij .name = "ACC_DETECT_1DB_R", 6776af75ecdSLinus Walleij .start = AB8500_INT_ACC_DETECT_1DB_R, 6786af75ecdSLinus Walleij .end = AB8500_INT_ACC_DETECT_1DB_R, 679e098adedSMattias Wallin .flags = IORESOURCE_IRQ, 680e098adedSMattias Wallin }, 681e098adedSMattias Wallin { 6826af75ecdSLinus Walleij .name = "ACC_DETECT_21DB_F", 6836af75ecdSLinus Walleij .start = AB8500_INT_ACC_DETECT_21DB_F, 6846af75ecdSLinus Walleij .end = AB8500_INT_ACC_DETECT_21DB_F, 6856af75ecdSLinus Walleij .flags = IORESOURCE_IRQ, 6866af75ecdSLinus Walleij }, 6876af75ecdSLinus Walleij { 6886af75ecdSLinus Walleij .name = "ACC_DETECT_21DB_R", 6896af75ecdSLinus Walleij .start = AB8500_INT_ACC_DETECT_21DB_R, 6906af75ecdSLinus Walleij .end = AB8500_INT_ACC_DETECT_21DB_R, 6916af75ecdSLinus Walleij .flags = IORESOURCE_IRQ, 6926af75ecdSLinus Walleij }, 6936af75ecdSLinus Walleij { 6946af75ecdSLinus Walleij .name = "ACC_DETECT_22DB_F", 6956af75ecdSLinus Walleij .start = AB8500_INT_ACC_DETECT_22DB_F, 6966af75ecdSLinus Walleij .end = AB8500_INT_ACC_DETECT_22DB_F, 6976af75ecdSLinus Walleij .flags = IORESOURCE_IRQ, 6986af75ecdSLinus Walleij }, 6996af75ecdSLinus Walleij { 7006af75ecdSLinus Walleij .name = "ACC_DETECT_22DB_R", 7016af75ecdSLinus Walleij .start = AB8500_INT_ACC_DETECT_22DB_R, 7026af75ecdSLinus Walleij .end = AB8500_INT_ACC_DETECT_22DB_R, 7036af75ecdSLinus Walleij .flags = IORESOURCE_IRQ, 7046af75ecdSLinus Walleij }, 7056af75ecdSLinus Walleij }; 7066af75ecdSLinus Walleij 707a9e9ce4cSBill Pemberton static struct resource ab8500_charger_resources[] = { 7086af75ecdSLinus Walleij { 709e098adedSMattias Wallin .name = "MAIN_CH_UNPLUG_DET", 710e098adedSMattias Wallin .start = AB8500_INT_MAIN_CH_UNPLUG_DET, 711e098adedSMattias Wallin .end = AB8500_INT_MAIN_CH_UNPLUG_DET, 712e098adedSMattias Wallin .flags = IORESOURCE_IRQ, 713e098adedSMattias Wallin }, 714e098adedSMattias Wallin { 715e098adedSMattias Wallin .name = "MAIN_CHARGE_PLUG_DET", 716e098adedSMattias Wallin .start = AB8500_INT_MAIN_CH_PLUG_DET, 717e098adedSMattias Wallin .end = AB8500_INT_MAIN_CH_PLUG_DET, 718e098adedSMattias Wallin .flags = IORESOURCE_IRQ, 719e098adedSMattias Wallin }, 720e098adedSMattias Wallin { 721e098adedSMattias Wallin .name = "VBUS_DET_R", 722e098adedSMattias Wallin .start = AB8500_INT_VBUS_DET_R, 723e098adedSMattias Wallin .end = AB8500_INT_VBUS_DET_R, 724e098adedSMattias Wallin .flags = IORESOURCE_IRQ, 725e098adedSMattias Wallin }, 726e098adedSMattias Wallin { 7276af75ecdSLinus Walleij .name = "VBUS_DET_F", 7286af75ecdSLinus Walleij .start = AB8500_INT_VBUS_DET_F, 7296af75ecdSLinus Walleij .end = AB8500_INT_VBUS_DET_F, 730e098adedSMattias Wallin .flags = IORESOURCE_IRQ, 731e098adedSMattias Wallin }, 732e098adedSMattias Wallin { 7336af75ecdSLinus Walleij .name = "USB_LINK_STATUS", 7346af75ecdSLinus Walleij .start = AB8500_INT_USB_LINK_STATUS, 7356af75ecdSLinus Walleij .end = AB8500_INT_USB_LINK_STATUS, 7366af75ecdSLinus Walleij .flags = IORESOURCE_IRQ, 7376af75ecdSLinus Walleij }, 7386af75ecdSLinus Walleij { 739e098adedSMattias Wallin .name = "VBUS_OVV", 740e098adedSMattias Wallin .start = AB8500_INT_VBUS_OVV, 741e098adedSMattias Wallin .end = AB8500_INT_VBUS_OVV, 742e098adedSMattias Wallin .flags = IORESOURCE_IRQ, 743e098adedSMattias Wallin }, 744e098adedSMattias Wallin { 7456af75ecdSLinus Walleij .name = "USB_CH_TH_PROT_R", 7466af75ecdSLinus Walleij .start = AB8500_INT_USB_CH_TH_PROT_R, 7476af75ecdSLinus Walleij .end = AB8500_INT_USB_CH_TH_PROT_R, 748e098adedSMattias Wallin .flags = IORESOURCE_IRQ, 749e098adedSMattias Wallin }, 750e098adedSMattias Wallin { 7516af75ecdSLinus Walleij .name = "USB_CH_TH_PROT_F", 7526af75ecdSLinus Walleij .start = AB8500_INT_USB_CH_TH_PROT_F, 7536af75ecdSLinus Walleij .end = AB8500_INT_USB_CH_TH_PROT_F, 754e098adedSMattias Wallin .flags = IORESOURCE_IRQ, 755e098adedSMattias Wallin }, 756e098adedSMattias Wallin { 7576af75ecdSLinus Walleij .name = "MAIN_EXT_CH_NOT_OK", 7586af75ecdSLinus Walleij .start = AB8500_INT_MAIN_EXT_CH_NOT_OK, 7596af75ecdSLinus Walleij .end = AB8500_INT_MAIN_EXT_CH_NOT_OK, 7606af75ecdSLinus Walleij .flags = IORESOURCE_IRQ, 7616af75ecdSLinus Walleij }, 7626af75ecdSLinus Walleij { 7636af75ecdSLinus Walleij .name = "MAIN_CH_TH_PROT_R", 7646af75ecdSLinus Walleij .start = AB8500_INT_MAIN_CH_TH_PROT_R, 7656af75ecdSLinus Walleij .end = AB8500_INT_MAIN_CH_TH_PROT_R, 7666af75ecdSLinus Walleij .flags = IORESOURCE_IRQ, 7676af75ecdSLinus Walleij }, 7686af75ecdSLinus Walleij { 7696af75ecdSLinus Walleij .name = "MAIN_CH_TH_PROT_F", 7706af75ecdSLinus Walleij .start = AB8500_INT_MAIN_CH_TH_PROT_F, 7716af75ecdSLinus Walleij .end = AB8500_INT_MAIN_CH_TH_PROT_F, 7726af75ecdSLinus Walleij .flags = IORESOURCE_IRQ, 7736af75ecdSLinus Walleij }, 7746af75ecdSLinus Walleij { 7756af75ecdSLinus Walleij .name = "USB_CHARGER_NOT_OKR", 776a982362cSBengt Jonsson .start = AB8500_INT_USB_CHARGER_NOT_OKR, 777a982362cSBengt Jonsson .end = AB8500_INT_USB_CHARGER_NOT_OKR, 7786af75ecdSLinus Walleij .flags = IORESOURCE_IRQ, 7796af75ecdSLinus Walleij }, 7806af75ecdSLinus Walleij { 7816af75ecdSLinus Walleij .name = "CH_WD_EXP", 7826af75ecdSLinus Walleij .start = AB8500_INT_CH_WD_EXP, 7836af75ecdSLinus Walleij .end = AB8500_INT_CH_WD_EXP, 7846af75ecdSLinus Walleij .flags = IORESOURCE_IRQ, 7856af75ecdSLinus Walleij }, 78634c11a70SPaer-Olof Haakansson { 78734c11a70SPaer-Olof Haakansson .name = "VBUS_CH_DROP_END", 78834c11a70SPaer-Olof Haakansson .start = AB8500_INT_VBUS_CH_DROP_END, 78934c11a70SPaer-Olof Haakansson .end = AB8500_INT_VBUS_CH_DROP_END, 79034c11a70SPaer-Olof Haakansson .flags = IORESOURCE_IRQ, 79134c11a70SPaer-Olof Haakansson }, 7926af75ecdSLinus Walleij }; 7936af75ecdSLinus Walleij 794a9e9ce4cSBill Pemberton static struct resource ab8500_btemp_resources[] = { 7956af75ecdSLinus Walleij { 7966af75ecdSLinus Walleij .name = "BAT_CTRL_INDB", 7976af75ecdSLinus Walleij .start = AB8500_INT_BAT_CTRL_INDB, 7986af75ecdSLinus Walleij .end = AB8500_INT_BAT_CTRL_INDB, 799e098adedSMattias Wallin .flags = IORESOURCE_IRQ, 800e098adedSMattias Wallin }, 801e098adedSMattias Wallin { 802e098adedSMattias Wallin .name = "BTEMP_LOW", 803e098adedSMattias Wallin .start = AB8500_INT_BTEMP_LOW, 804e098adedSMattias Wallin .end = AB8500_INT_BTEMP_LOW, 805e098adedSMattias Wallin .flags = IORESOURCE_IRQ, 806e098adedSMattias Wallin }, 807e098adedSMattias Wallin { 808e098adedSMattias Wallin .name = "BTEMP_HIGH", 809e098adedSMattias Wallin .start = AB8500_INT_BTEMP_HIGH, 810e098adedSMattias Wallin .end = AB8500_INT_BTEMP_HIGH, 811e098adedSMattias Wallin .flags = IORESOURCE_IRQ, 812e098adedSMattias Wallin }, 813e098adedSMattias Wallin { 8146af75ecdSLinus Walleij .name = "BTEMP_LOW_MEDIUM", 8156af75ecdSLinus Walleij .start = AB8500_INT_BTEMP_LOW_MEDIUM, 8166af75ecdSLinus Walleij .end = AB8500_INT_BTEMP_LOW_MEDIUM, 817e098adedSMattias Wallin .flags = IORESOURCE_IRQ, 818e098adedSMattias Wallin }, 819e098adedSMattias Wallin { 8206af75ecdSLinus Walleij .name = "BTEMP_MEDIUM_HIGH", 8216af75ecdSLinus Walleij .start = AB8500_INT_BTEMP_MEDIUM_HIGH, 8226af75ecdSLinus Walleij .end = AB8500_INT_BTEMP_MEDIUM_HIGH, 823e098adedSMattias Wallin .flags = IORESOURCE_IRQ, 824e098adedSMattias Wallin }, 825e098adedSMattias Wallin }; 826e098adedSMattias Wallin 827a9e9ce4cSBill Pemberton static struct resource ab8500_fg_resources[] = { 8286af75ecdSLinus Walleij { 8296af75ecdSLinus Walleij .name = "NCONV_ACCU", 8306af75ecdSLinus Walleij .start = AB8500_INT_CCN_CONV_ACC, 8316af75ecdSLinus Walleij .end = AB8500_INT_CCN_CONV_ACC, 8326af75ecdSLinus Walleij .flags = IORESOURCE_IRQ, 8336af75ecdSLinus Walleij }, 8346af75ecdSLinus Walleij { 8356af75ecdSLinus Walleij .name = "BATT_OVV", 8366af75ecdSLinus Walleij .start = AB8500_INT_BATT_OVV, 8376af75ecdSLinus Walleij .end = AB8500_INT_BATT_OVV, 8386af75ecdSLinus Walleij .flags = IORESOURCE_IRQ, 8396af75ecdSLinus Walleij }, 8406af75ecdSLinus Walleij { 8416af75ecdSLinus Walleij .name = "LOW_BAT_F", 8426af75ecdSLinus Walleij .start = AB8500_INT_LOW_BAT_F, 8436af75ecdSLinus Walleij .end = AB8500_INT_LOW_BAT_F, 8446af75ecdSLinus Walleij .flags = IORESOURCE_IRQ, 8456af75ecdSLinus Walleij }, 8466af75ecdSLinus Walleij { 8476af75ecdSLinus Walleij .name = "LOW_BAT_R", 8486af75ecdSLinus Walleij .start = AB8500_INT_LOW_BAT_R, 8496af75ecdSLinus Walleij .end = AB8500_INT_LOW_BAT_R, 8506af75ecdSLinus Walleij .flags = IORESOURCE_IRQ, 8516af75ecdSLinus Walleij }, 8526af75ecdSLinus Walleij { 8536af75ecdSLinus Walleij .name = "CC_INT_CALIB", 8546af75ecdSLinus Walleij .start = AB8500_INT_CC_INT_CALIB, 8556af75ecdSLinus Walleij .end = AB8500_INT_CC_INT_CALIB, 8566af75ecdSLinus Walleij .flags = IORESOURCE_IRQ, 8576af75ecdSLinus Walleij }, 858a982362cSBengt Jonsson { 859a982362cSBengt Jonsson .name = "CCEOC", 860a982362cSBengt Jonsson .start = AB8500_INT_CCEOC, 861a982362cSBengt Jonsson .end = AB8500_INT_CCEOC, 862a982362cSBengt Jonsson .flags = IORESOURCE_IRQ, 863a982362cSBengt Jonsson }, 8646af75ecdSLinus Walleij }; 8656af75ecdSLinus Walleij 866a9e9ce4cSBill Pemberton static struct resource ab8500_chargalg_resources[] = {}; 8676af75ecdSLinus Walleij 868df720647SAxel Lin #ifdef CONFIG_DEBUG_FS 869a9e9ce4cSBill Pemberton static struct resource ab8500_debug_resources[] = { 870e098adedSMattias Wallin { 8716999181eSLinus Walleij .name = "IRQ_AB8500", 8726999181eSLinus Walleij /* 8736999181eSLinus Walleij * Number will be filled in. NOTE: this is deliberately 8746999181eSLinus Walleij * not flagged as an IRQ in ordet to avoid remapping using 8756999181eSLinus Walleij * the irqdomain in the MFD core, so that this IRQ passes 8766999181eSLinus Walleij * unremapped to the debug code. 8776999181eSLinus Walleij */ 8786999181eSLinus Walleij }, 8796999181eSLinus Walleij { 880e098adedSMattias Wallin .name = "IRQ_FIRST", 881e098adedSMattias Wallin .start = AB8500_INT_MAIN_EXT_CH_NOT_OK, 882e098adedSMattias Wallin .end = AB8500_INT_MAIN_EXT_CH_NOT_OK, 883e098adedSMattias Wallin .flags = IORESOURCE_IRQ, 884e098adedSMattias Wallin }, 885e098adedSMattias Wallin { 886e098adedSMattias Wallin .name = "IRQ_LAST", 887a982362cSBengt Jonsson .start = AB8500_INT_XTAL32K_KO, 888a982362cSBengt Jonsson .end = AB8500_INT_XTAL32K_KO, 889e098adedSMattias Wallin .flags = IORESOURCE_IRQ, 890e098adedSMattias Wallin }, 891e098adedSMattias Wallin }; 892df720647SAxel Lin #endif 893e098adedSMattias Wallin 894a9e9ce4cSBill Pemberton static struct resource ab8500_usb_resources[] = { 895e098adedSMattias Wallin { 896e098adedSMattias Wallin .name = "ID_WAKEUP_R", 897e098adedSMattias Wallin .start = AB8500_INT_ID_WAKEUP_R, 898e098adedSMattias Wallin .end = AB8500_INT_ID_WAKEUP_R, 899e098adedSMattias Wallin .flags = IORESOURCE_IRQ, 900e098adedSMattias Wallin }, 901e098adedSMattias Wallin { 902e098adedSMattias Wallin .name = "ID_WAKEUP_F", 903e098adedSMattias Wallin .start = AB8500_INT_ID_WAKEUP_F, 904e098adedSMattias Wallin .end = AB8500_INT_ID_WAKEUP_F, 905e098adedSMattias Wallin .flags = IORESOURCE_IRQ, 906e098adedSMattias Wallin }, 907e098adedSMattias Wallin { 908e098adedSMattias Wallin .name = "VBUS_DET_F", 909e098adedSMattias Wallin .start = AB8500_INT_VBUS_DET_F, 910e098adedSMattias Wallin .end = AB8500_INT_VBUS_DET_F, 911e098adedSMattias Wallin .flags = IORESOURCE_IRQ, 912e098adedSMattias Wallin }, 913e098adedSMattias Wallin { 914e098adedSMattias Wallin .name = "VBUS_DET_R", 915e098adedSMattias Wallin .start = AB8500_INT_VBUS_DET_R, 916e098adedSMattias Wallin .end = AB8500_INT_VBUS_DET_R, 917e098adedSMattias Wallin .flags = IORESOURCE_IRQ, 918e098adedSMattias Wallin }, 91992d50a41SMattias Wallin { 92092d50a41SMattias Wallin .name = "USB_LINK_STATUS", 92192d50a41SMattias Wallin .start = AB8500_INT_USB_LINK_STATUS, 92292d50a41SMattias Wallin .end = AB8500_INT_USB_LINK_STATUS, 92392d50a41SMattias Wallin .flags = IORESOURCE_IRQ, 92492d50a41SMattias Wallin }, 9256af75ecdSLinus Walleij { 9266af75ecdSLinus Walleij .name = "USB_ADP_PROBE_PLUG", 9276af75ecdSLinus Walleij .start = AB8500_INT_ADP_PROBE_PLUG, 9286af75ecdSLinus Walleij .end = AB8500_INT_ADP_PROBE_PLUG, 9296af75ecdSLinus Walleij .flags = IORESOURCE_IRQ, 9306af75ecdSLinus Walleij }, 9316af75ecdSLinus Walleij { 9326af75ecdSLinus Walleij .name = "USB_ADP_PROBE_UNPLUG", 9336af75ecdSLinus Walleij .start = AB8500_INT_ADP_PROBE_UNPLUG, 9346af75ecdSLinus Walleij .end = AB8500_INT_ADP_PROBE_UNPLUG, 9356af75ecdSLinus Walleij .flags = IORESOURCE_IRQ, 9366af75ecdSLinus Walleij }, 937e098adedSMattias Wallin }; 938e098adedSMattias Wallin 939a9e9ce4cSBill Pemberton static struct resource ab8505_iddet_resources[] = { 94044f72e53SVirupax Sadashivpetimath { 94144f72e53SVirupax Sadashivpetimath .name = "KeyDeglitch", 94244f72e53SVirupax Sadashivpetimath .start = AB8505_INT_KEYDEGLITCH, 94344f72e53SVirupax Sadashivpetimath .end = AB8505_INT_KEYDEGLITCH, 94444f72e53SVirupax Sadashivpetimath .flags = IORESOURCE_IRQ, 94544f72e53SVirupax Sadashivpetimath }, 94644f72e53SVirupax Sadashivpetimath { 94744f72e53SVirupax Sadashivpetimath .name = "KP", 94844f72e53SVirupax Sadashivpetimath .start = AB8505_INT_KP, 94944f72e53SVirupax Sadashivpetimath .end = AB8505_INT_KP, 95044f72e53SVirupax Sadashivpetimath .flags = IORESOURCE_IRQ, 95144f72e53SVirupax Sadashivpetimath }, 95244f72e53SVirupax Sadashivpetimath { 95344f72e53SVirupax Sadashivpetimath .name = "IKP", 95444f72e53SVirupax Sadashivpetimath .start = AB8505_INT_IKP, 95544f72e53SVirupax Sadashivpetimath .end = AB8505_INT_IKP, 95644f72e53SVirupax Sadashivpetimath .flags = IORESOURCE_IRQ, 95744f72e53SVirupax Sadashivpetimath }, 95844f72e53SVirupax Sadashivpetimath { 95944f72e53SVirupax Sadashivpetimath .name = "IKR", 96044f72e53SVirupax Sadashivpetimath .start = AB8505_INT_IKR, 96144f72e53SVirupax Sadashivpetimath .end = AB8505_INT_IKR, 96244f72e53SVirupax Sadashivpetimath .flags = IORESOURCE_IRQ, 96344f72e53SVirupax Sadashivpetimath }, 96444f72e53SVirupax Sadashivpetimath { 96544f72e53SVirupax Sadashivpetimath .name = "KeyStuck", 96644f72e53SVirupax Sadashivpetimath .start = AB8505_INT_KEYSTUCK, 96744f72e53SVirupax Sadashivpetimath .end = AB8505_INT_KEYSTUCK, 96844f72e53SVirupax Sadashivpetimath .flags = IORESOURCE_IRQ, 96944f72e53SVirupax Sadashivpetimath }, 970492390c8SLee Jones { 971492390c8SLee Jones .name = "VBUS_DET_R", 972492390c8SLee Jones .start = AB8500_INT_VBUS_DET_R, 973492390c8SLee Jones .end = AB8500_INT_VBUS_DET_R, 974492390c8SLee Jones .flags = IORESOURCE_IRQ, 975492390c8SLee Jones }, 976492390c8SLee Jones { 977492390c8SLee Jones .name = "VBUS_DET_F", 978492390c8SLee Jones .start = AB8500_INT_VBUS_DET_F, 979492390c8SLee Jones .end = AB8500_INT_VBUS_DET_F, 980492390c8SLee Jones .flags = IORESOURCE_IRQ, 981492390c8SLee Jones }, 982492390c8SLee Jones { 983492390c8SLee Jones .name = "ID_DET_PLUGR", 984492390c8SLee Jones .start = AB8500_INT_ID_DET_PLUGR, 985492390c8SLee Jones .end = AB8500_INT_ID_DET_PLUGR, 986492390c8SLee Jones .flags = IORESOURCE_IRQ, 987492390c8SLee Jones }, 988492390c8SLee Jones { 989492390c8SLee Jones .name = "ID_DET_PLUGF", 990492390c8SLee Jones .start = AB8500_INT_ID_DET_PLUGF, 991492390c8SLee Jones .end = AB8500_INT_ID_DET_PLUGF, 992492390c8SLee Jones .flags = IORESOURCE_IRQ, 993492390c8SLee Jones }, 99444f72e53SVirupax Sadashivpetimath }; 99544f72e53SVirupax Sadashivpetimath 996a9e9ce4cSBill Pemberton static struct resource ab8500_temp_resources[] = { 997e098adedSMattias Wallin { 998151621a7SHongbo Zhang .name = "ABX500_TEMP_WARM", 999e098adedSMattias Wallin .start = AB8500_INT_TEMP_WARM, 1000e098adedSMattias Wallin .end = AB8500_INT_TEMP_WARM, 1001e098adedSMattias Wallin .flags = IORESOURCE_IRQ, 1002e098adedSMattias Wallin }, 1003e098adedSMattias Wallin }; 1004e098adedSMattias Wallin 1005a9e9ce4cSBill Pemberton static struct mfd_cell ab8500_bm_devs[] = { 10066ef9418cSRickard Andersson { 10076ef9418cSRickard Andersson .name = "ab8500-charger", 10084aef72dbSRajanikanth H.V .of_compatible = "stericsson,ab8500-charger", 10096ef9418cSRickard Andersson .num_resources = ARRAY_SIZE(ab8500_charger_resources), 10106ef9418cSRickard Andersson .resources = ab8500_charger_resources, 10114aef72dbSRajanikanth H.V .platform_data = &ab8500_bm_data, 10124aef72dbSRajanikanth H.V .pdata_size = sizeof(ab8500_bm_data), 10136ef9418cSRickard Andersson }, 10146ef9418cSRickard Andersson { 10156ef9418cSRickard Andersson .name = "ab8500-btemp", 1016bd9e8ab2SRajanikanth H.V .of_compatible = "stericsson,ab8500-btemp", 10176ef9418cSRickard Andersson .num_resources = ARRAY_SIZE(ab8500_btemp_resources), 10186ef9418cSRickard Andersson .resources = ab8500_btemp_resources, 1019bd9e8ab2SRajanikanth H.V .platform_data = &ab8500_bm_data, 1020bd9e8ab2SRajanikanth H.V .pdata_size = sizeof(ab8500_bm_data), 10216ef9418cSRickard Andersson }, 10226ef9418cSRickard Andersson { 10236ef9418cSRickard Andersson .name = "ab8500-fg", 1024e0f1abebSRajanikanth H.V .of_compatible = "stericsson,ab8500-fg", 10256ef9418cSRickard Andersson .num_resources = ARRAY_SIZE(ab8500_fg_resources), 10266ef9418cSRickard Andersson .resources = ab8500_fg_resources, 1027e0f1abebSRajanikanth H.V .platform_data = &ab8500_bm_data, 1028e0f1abebSRajanikanth H.V .pdata_size = sizeof(ab8500_bm_data), 10296ef9418cSRickard Andersson }, 10306ef9418cSRickard Andersson { 10316ef9418cSRickard Andersson .name = "ab8500-chargalg", 1032a12810abSRajanikanth H.V .of_compatible = "stericsson,ab8500-chargalg", 10336ef9418cSRickard Andersson .num_resources = ARRAY_SIZE(ab8500_chargalg_resources), 10346ef9418cSRickard Andersson .resources = ab8500_chargalg_resources, 1035a12810abSRajanikanth H.V .platform_data = &ab8500_bm_data, 1036a12810abSRajanikanth H.V .pdata_size = sizeof(ab8500_bm_data), 10376ef9418cSRickard Andersson }, 10386ef9418cSRickard Andersson }; 10396ef9418cSRickard Andersson 1040a9e9ce4cSBill Pemberton static struct mfd_cell ab8500_devs[] = { 10414b106fb9SLee Jones #ifdef CONFIG_DEBUG_FS 1042d6255529SLinus Walleij { 10434b106fb9SLee Jones .name = "ab8500-debug", 10444b106fb9SLee Jones .of_compatible = "stericsson,ab8500-debug", 10454b106fb9SLee Jones .num_resources = ARRAY_SIZE(ab8500_debug_resources), 10464b106fb9SLee Jones .resources = ab8500_debug_resources, 10474b106fb9SLee Jones }, 10484b106fb9SLee Jones #endif 10494b106fb9SLee Jones { 10504b106fb9SLee Jones .name = "ab8500-sysctrl", 10514b106fb9SLee Jones .of_compatible = "stericsson,ab8500-sysctrl", 10524b106fb9SLee Jones }, 10534b106fb9SLee Jones { 10544b106fb9SLee Jones .name = "ab8500-regulator", 10554b106fb9SLee Jones .of_compatible = "stericsson,ab8500-regulator", 10564b106fb9SLee Jones }, 10574b106fb9SLee Jones { 10584b106fb9SLee Jones .name = "abx500-clk", 10594b106fb9SLee Jones .of_compatible = "stericsson,abx500-clk", 10604b106fb9SLee Jones }, 10614b106fb9SLee Jones { 10624b106fb9SLee Jones .name = "ab8500-gpadc", 10634b106fb9SLee Jones .num_resources = ARRAY_SIZE(ab8500_gpadc_resources), 10644b106fb9SLee Jones .resources = ab8500_gpadc_resources, 10654b106fb9SLee Jones }, 10664b106fb9SLee Jones { 10674b106fb9SLee Jones .name = "ab8500-rtc", 10684b106fb9SLee Jones .of_compatible = "stericsson,ab8500-rtc", 10694b106fb9SLee Jones .num_resources = ARRAY_SIZE(ab8500_rtc_resources), 10704b106fb9SLee Jones .resources = ab8500_rtc_resources, 10714b106fb9SLee Jones }, 10724b106fb9SLee Jones { 10734b106fb9SLee Jones .name = "ab8500-acc-det", 10744b106fb9SLee Jones .of_compatible = "stericsson,ab8500-acc-det", 10754b106fb9SLee Jones .num_resources = ARRAY_SIZE(ab8500_av_acc_detect_resources), 10764b106fb9SLee Jones .resources = ab8500_av_acc_detect_resources, 10774b106fb9SLee Jones }, 10784b106fb9SLee Jones { 10794b106fb9SLee Jones 10804b106fb9SLee Jones .name = "ab8500-poweron-key", 10814b106fb9SLee Jones .of_compatible = "stericsson,ab8500-poweron-key", 10824b106fb9SLee Jones .num_resources = ARRAY_SIZE(ab8500_poweronkey_db_resources), 10834b106fb9SLee Jones .resources = ab8500_poweronkey_db_resources, 10844b106fb9SLee Jones }, 10854b106fb9SLee Jones { 10864b106fb9SLee Jones .name = "ab8500-pwm", 10874b106fb9SLee Jones .of_compatible = "stericsson,ab8500-pwm", 10884b106fb9SLee Jones .id = 1, 10894b106fb9SLee Jones }, 10904b106fb9SLee Jones { 10914b106fb9SLee Jones .name = "ab8500-pwm", 10924b106fb9SLee Jones .of_compatible = "stericsson,ab8500-pwm", 10934b106fb9SLee Jones .id = 2, 10944b106fb9SLee Jones }, 10954b106fb9SLee Jones { 10964b106fb9SLee Jones .name = "ab8500-pwm", 10974b106fb9SLee Jones .of_compatible = "stericsson,ab8500-pwm", 10984b106fb9SLee Jones .id = 3, 10994b106fb9SLee Jones }, 11004b106fb9SLee Jones { 11014b106fb9SLee Jones .name = "ab8500-leds", 11024b106fb9SLee Jones .of_compatible = "stericsson,ab8500-leds", 11034b106fb9SLee Jones }, 11044b106fb9SLee Jones { 11054b106fb9SLee Jones .name = "ab8500-denc", 11064b106fb9SLee Jones .of_compatible = "stericsson,ab8500-denc", 11074b106fb9SLee Jones }, 11084b106fb9SLee Jones { 1109*eb696c31SLee Jones .name = "pinctrl-ab8500", 1110bad76991SLee Jones .of_compatible = "stericsson,ab8500-gpio", 1111d6255529SLinus Walleij }, 1112d6255529SLinus Walleij { 11134b106fb9SLee Jones .name = "abx500-temp", 11144b106fb9SLee Jones .of_compatible = "stericsson,abx500-temp", 11154b106fb9SLee Jones .num_resources = ARRAY_SIZE(ab8500_temp_resources), 11164b106fb9SLee Jones .resources = ab8500_temp_resources, 11174b106fb9SLee Jones }, 11184b106fb9SLee Jones { 1119d6255529SLinus Walleij .name = "ab8500-usb", 1120f201f730SFabio Baltieri .of_compatible = "stericsson,ab8500-usb", 1121d6255529SLinus Walleij .num_resources = ARRAY_SIZE(ab8500_usb_resources), 1122d6255529SLinus Walleij .resources = ab8500_usb_resources, 1123d6255529SLinus Walleij }, 112444f72e53SVirupax Sadashivpetimath { 112544f72e53SVirupax Sadashivpetimath .name = "ab8500-codec", 11264b106fb9SLee Jones }, 11274b106fb9SLee Jones }; 11284b106fb9SLee Jones 11294b106fb9SLee Jones static struct mfd_cell ab9540_devs[] = { 11304b106fb9SLee Jones #ifdef CONFIG_DEBUG_FS 11314b106fb9SLee Jones { 11324b106fb9SLee Jones .name = "ab8500-debug", 11334b106fb9SLee Jones .num_resources = ARRAY_SIZE(ab8500_debug_resources), 11344b106fb9SLee Jones .resources = ab8500_debug_resources, 11354b106fb9SLee Jones }, 11364b106fb9SLee Jones #endif 11374b106fb9SLee Jones { 11384b106fb9SLee Jones .name = "ab8500-sysctrl", 11394b106fb9SLee Jones }, 11404b106fb9SLee Jones { 11414b106fb9SLee Jones .name = "ab8500-regulator", 114244f72e53SVirupax Sadashivpetimath }, 1143c0eda9aeSLee Jones { 11449ee17676SUlf Hansson .name = "abx500-clk", 11459ee17676SUlf Hansson .of_compatible = "stericsson,abx500-clk", 11469ee17676SUlf Hansson }, 11479ee17676SUlf Hansson { 1148c0eda9aeSLee Jones .name = "ab8500-gpadc", 1149c0eda9aeSLee Jones .of_compatible = "stericsson,ab8500-gpadc", 1150c0eda9aeSLee Jones .num_resources = ARRAY_SIZE(ab8500_gpadc_resources), 1151c0eda9aeSLee Jones .resources = ab8500_gpadc_resources, 1152c0eda9aeSLee Jones }, 11534b106fb9SLee Jones { 11544b106fb9SLee Jones .name = "ab8500-rtc", 11554b106fb9SLee Jones .num_resources = ARRAY_SIZE(ab8500_rtc_resources), 11564b106fb9SLee Jones .resources = ab8500_rtc_resources, 11574b106fb9SLee Jones }, 11584b106fb9SLee Jones { 11594b106fb9SLee Jones .name = "ab8500-acc-det", 11604b106fb9SLee Jones .num_resources = ARRAY_SIZE(ab8500_av_acc_detect_resources), 11614b106fb9SLee Jones .resources = ab8500_av_acc_detect_resources, 11624b106fb9SLee Jones }, 11634b106fb9SLee Jones { 11644b106fb9SLee Jones .name = "ab8500-poweron-key", 11654b106fb9SLee Jones .num_resources = ARRAY_SIZE(ab8500_poweronkey_db_resources), 11664b106fb9SLee Jones .resources = ab8500_poweronkey_db_resources, 11674b106fb9SLee Jones }, 11684b106fb9SLee Jones { 11694b106fb9SLee Jones .name = "ab8500-pwm", 11704b106fb9SLee Jones .id = 1, 11714b106fb9SLee Jones }, 11724b106fb9SLee Jones { 11734b106fb9SLee Jones .name = "ab8500-leds", 11744b106fb9SLee Jones }, 11754b106fb9SLee Jones { 11764b106fb9SLee Jones .name = "abx500-temp", 11774b106fb9SLee Jones .num_resources = ARRAY_SIZE(ab8500_temp_resources), 11784b106fb9SLee Jones .resources = ab8500_temp_resources, 11794b106fb9SLee Jones }, 1180d6255529SLinus Walleij { 1181e64d905eSLee Jones .name = "pinctrl-ab9540", 1182e64d905eSLee Jones .of_compatible = "stericsson,ab9540-gpio", 1183d6255529SLinus Walleij }, 1184d6255529SLinus Walleij { 1185d6255529SLinus Walleij .name = "ab9540-usb", 1186d6255529SLinus Walleij .num_resources = ARRAY_SIZE(ab8500_usb_resources), 1187d6255529SLinus Walleij .resources = ab8500_usb_resources, 1188d6255529SLinus Walleij }, 118944f72e53SVirupax Sadashivpetimath { 119044f72e53SVirupax Sadashivpetimath .name = "ab9540-codec", 119144f72e53SVirupax Sadashivpetimath }, 1192c0eda9aeSLee Jones { 1193c0eda9aeSLee Jones .name = "ab-iddet", 1194c0eda9aeSLee Jones .num_resources = ARRAY_SIZE(ab8505_iddet_resources), 1195c0eda9aeSLee Jones .resources = ab8505_iddet_resources, 1196c0eda9aeSLee Jones }, 119744f72e53SVirupax Sadashivpetimath }; 119844f72e53SVirupax Sadashivpetimath 1199c0eda9aeSLee Jones /* Device list for ab8505 */ 1200c0eda9aeSLee Jones static struct mfd_cell ab8505_devs[] = { 12014b106fb9SLee Jones #ifdef CONFIG_DEBUG_FS 12024b106fb9SLee Jones { 12034b106fb9SLee Jones .name = "ab8500-debug", 12044b106fb9SLee Jones .num_resources = ARRAY_SIZE(ab8500_debug_resources), 12054b106fb9SLee Jones .resources = ab8500_debug_resources, 12064b106fb9SLee Jones }, 12074b106fb9SLee Jones #endif 12084b106fb9SLee Jones { 12094b106fb9SLee Jones .name = "ab8500-sysctrl", 12104b106fb9SLee Jones }, 12114b106fb9SLee Jones { 12124b106fb9SLee Jones .name = "ab8500-regulator", 12134b106fb9SLee Jones }, 12144b106fb9SLee Jones { 12159ee17676SUlf Hansson .name = "abx500-clk", 12169ee17676SUlf Hansson .of_compatible = "stericsson,abx500-clk", 12179ee17676SUlf Hansson }, 12189ee17676SUlf Hansson { 12194b106fb9SLee Jones .name = "ab8500-gpadc", 12204b106fb9SLee Jones .num_resources = ARRAY_SIZE(ab8505_gpadc_resources), 12214b106fb9SLee Jones .resources = ab8505_gpadc_resources, 12224b106fb9SLee Jones }, 12234b106fb9SLee Jones { 12244b106fb9SLee Jones .name = "ab8500-rtc", 12254b106fb9SLee Jones .num_resources = ARRAY_SIZE(ab8500_rtc_resources), 12264b106fb9SLee Jones .resources = ab8500_rtc_resources, 12274b106fb9SLee Jones }, 12284b106fb9SLee Jones { 12294b106fb9SLee Jones .name = "ab8500-acc-det", 12304b106fb9SLee Jones .num_resources = ARRAY_SIZE(ab8500_av_acc_detect_resources), 12314b106fb9SLee Jones .resources = ab8500_av_acc_detect_resources, 12324b106fb9SLee Jones }, 12334b106fb9SLee Jones { 12344b106fb9SLee Jones .name = "ab8500-poweron-key", 12354b106fb9SLee Jones .num_resources = ARRAY_SIZE(ab8500_poweronkey_db_resources), 12364b106fb9SLee Jones .resources = ab8500_poweronkey_db_resources, 12374b106fb9SLee Jones }, 12384b106fb9SLee Jones { 12394b106fb9SLee Jones .name = "ab8500-pwm", 12404b106fb9SLee Jones .id = 1, 12414b106fb9SLee Jones }, 12424b106fb9SLee Jones { 12434b106fb9SLee Jones .name = "ab8500-leds", 12444b106fb9SLee Jones }, 12454b106fb9SLee Jones { 1246*eb696c31SLee Jones .name = "pinctrl-ab8505", 12474b106fb9SLee Jones }, 12484b106fb9SLee Jones { 12494b106fb9SLee Jones .name = "ab8500-usb", 12504b106fb9SLee Jones .num_resources = ARRAY_SIZE(ab8500_usb_resources), 12514b106fb9SLee Jones .resources = ab8500_usb_resources, 12524b106fb9SLee Jones }, 12534b106fb9SLee Jones { 12544b106fb9SLee Jones .name = "ab8500-codec", 12554b106fb9SLee Jones }, 1256c0eda9aeSLee Jones { 1257c0eda9aeSLee Jones .name = "ab-iddet", 1258c0eda9aeSLee Jones .num_resources = ARRAY_SIZE(ab8505_iddet_resources), 1259c0eda9aeSLee Jones .resources = ab8505_iddet_resources, 1260c0eda9aeSLee Jones }, 1261c0eda9aeSLee Jones }; 1262c0eda9aeSLee Jones 1263c0eda9aeSLee Jones static struct mfd_cell ab8540_devs[] = { 12644b106fb9SLee Jones #ifdef CONFIG_DEBUG_FS 12654b106fb9SLee Jones { 12664b106fb9SLee Jones .name = "ab8500-debug", 12674b106fb9SLee Jones .num_resources = ARRAY_SIZE(ab8500_debug_resources), 12684b106fb9SLee Jones .resources = ab8500_debug_resources, 12694b106fb9SLee Jones }, 12704b106fb9SLee Jones #endif 12714b106fb9SLee Jones { 12724b106fb9SLee Jones .name = "ab8500-sysctrl", 12734b106fb9SLee Jones }, 12744b106fb9SLee Jones { 12754b106fb9SLee Jones .name = "ab8500-regulator", 12764b106fb9SLee Jones }, 12774b106fb9SLee Jones { 12789ee17676SUlf Hansson .name = "abx500-clk", 12799ee17676SUlf Hansson .of_compatible = "stericsson,abx500-clk", 12809ee17676SUlf Hansson }, 12819ee17676SUlf Hansson { 12824b106fb9SLee Jones .name = "ab8500-gpadc", 12834b106fb9SLee Jones .num_resources = ARRAY_SIZE(ab8505_gpadc_resources), 12844b106fb9SLee Jones .resources = ab8505_gpadc_resources, 12854b106fb9SLee Jones }, 12864b106fb9SLee Jones { 12874b106fb9SLee Jones .name = "ab8500-rtc", 12884b106fb9SLee Jones .num_resources = ARRAY_SIZE(ab8500_rtc_resources), 12894b106fb9SLee Jones .resources = ab8500_rtc_resources, 12904b106fb9SLee Jones }, 12914b106fb9SLee Jones { 12924b106fb9SLee Jones .name = "ab8500-acc-det", 12934b106fb9SLee Jones .num_resources = ARRAY_SIZE(ab8500_av_acc_detect_resources), 12944b106fb9SLee Jones .resources = ab8500_av_acc_detect_resources, 12954b106fb9SLee Jones }, 12964b106fb9SLee Jones { 12974b106fb9SLee Jones .name = "ab8500-poweron-key", 12984b106fb9SLee Jones .num_resources = ARRAY_SIZE(ab8500_poweronkey_db_resources), 12994b106fb9SLee Jones .resources = ab8500_poweronkey_db_resources, 13004b106fb9SLee Jones }, 13014b106fb9SLee Jones { 13024b106fb9SLee Jones .name = "ab8500-pwm", 13034b106fb9SLee Jones .id = 1, 13044b106fb9SLee Jones }, 13054b106fb9SLee Jones { 13064b106fb9SLee Jones .name = "ab8500-leds", 13074b106fb9SLee Jones }, 13084b106fb9SLee Jones { 13094b106fb9SLee Jones .name = "abx500-temp", 13104b106fb9SLee Jones .num_resources = ARRAY_SIZE(ab8500_temp_resources), 13114b106fb9SLee Jones .resources = ab8500_temp_resources, 13124b106fb9SLee Jones }, 1313c0eda9aeSLee Jones { 1314*eb696c31SLee Jones .name = "pinctrl-ab8540", 1315c0eda9aeSLee Jones }, 1316c0eda9aeSLee Jones { 1317c0eda9aeSLee Jones .name = "ab8540-usb", 1318c0eda9aeSLee Jones .num_resources = ARRAY_SIZE(ab8500_usb_resources), 1319c0eda9aeSLee Jones .resources = ab8500_usb_resources, 1320c0eda9aeSLee Jones }, 1321c0eda9aeSLee Jones { 1322c0eda9aeSLee Jones .name = "ab8540-codec", 1323c0eda9aeSLee Jones }, 1324c0eda9aeSLee Jones { 132544f72e53SVirupax Sadashivpetimath .name = "ab-iddet", 132644f72e53SVirupax Sadashivpetimath .num_resources = ARRAY_SIZE(ab8505_iddet_resources), 132744f72e53SVirupax Sadashivpetimath .resources = ab8505_iddet_resources, 132844f72e53SVirupax Sadashivpetimath }, 1329d6255529SLinus Walleij }; 1330d6255529SLinus Walleij 1331cca69b67SMattias Wallin static ssize_t show_chip_id(struct device *dev, 1332cca69b67SMattias Wallin struct device_attribute *attr, char *buf) 1333cca69b67SMattias Wallin { 1334cca69b67SMattias Wallin struct ab8500 *ab8500; 1335cca69b67SMattias Wallin 1336cca69b67SMattias Wallin ab8500 = dev_get_drvdata(dev); 1337e436ddffSLee Jones 1338cca69b67SMattias Wallin return sprintf(buf, "%#x\n", ab8500 ? ab8500->chip_id : -EINVAL); 1339cca69b67SMattias Wallin } 1340cca69b67SMattias Wallin 1341e5c238c3SMattias Wallin /* 1342e5c238c3SMattias Wallin * ab8500 has switched off due to (SWITCH_OFF_STATUS): 1343e5c238c3SMattias Wallin * 0x01 Swoff bit programming 1344e5c238c3SMattias Wallin * 0x02 Thermal protection activation 1345e5c238c3SMattias Wallin * 0x04 Vbat lower then BattOk falling threshold 1346e5c238c3SMattias Wallin * 0x08 Watchdog expired 1347e5c238c3SMattias Wallin * 0x10 Non presence of 32kHz clock 1348e5c238c3SMattias Wallin * 0x20 Battery level lower than power on reset threshold 1349e5c238c3SMattias Wallin * 0x40 Power on key 1 pressed longer than 10 seconds 1350e5c238c3SMattias Wallin * 0x80 DB8500 thermal shutdown 1351e5c238c3SMattias Wallin */ 1352e5c238c3SMattias Wallin static ssize_t show_switch_off_status(struct device *dev, 1353e5c238c3SMattias Wallin struct device_attribute *attr, char *buf) 1354e5c238c3SMattias Wallin { 1355e5c238c3SMattias Wallin int ret; 1356e5c238c3SMattias Wallin u8 value; 1357e5c238c3SMattias Wallin struct ab8500 *ab8500; 1358e5c238c3SMattias Wallin 1359e5c238c3SMattias Wallin ab8500 = dev_get_drvdata(dev); 1360e5c238c3SMattias Wallin ret = get_register_interruptible(ab8500, AB8500_RTC, 1361e5c238c3SMattias Wallin AB8500_SWITCH_OFF_STATUS, &value); 1362e5c238c3SMattias Wallin if (ret < 0) 1363e5c238c3SMattias Wallin return ret; 1364e5c238c3SMattias Wallin return sprintf(buf, "%#x\n", value); 1365e5c238c3SMattias Wallin } 1366e5c238c3SMattias Wallin 1367f04a9d8aSRajkumar Kasirajan /* use mask and set to override the register turn_on_stat value */ 1368f04a9d8aSRajkumar Kasirajan void ab8500_override_turn_on_stat(u8 mask, u8 set) 1369f04a9d8aSRajkumar Kasirajan { 1370f04a9d8aSRajkumar Kasirajan spin_lock(&on_stat_lock); 1371f04a9d8aSRajkumar Kasirajan turn_on_stat_mask = mask; 1372f04a9d8aSRajkumar Kasirajan turn_on_stat_set = set; 1373f04a9d8aSRajkumar Kasirajan spin_unlock(&on_stat_lock); 1374f04a9d8aSRajkumar Kasirajan } 1375f04a9d8aSRajkumar Kasirajan 1376b4a31037SAndrew Lynn /* 1377b4a31037SAndrew Lynn * ab8500 has turned on due to (TURN_ON_STATUS): 1378b4a31037SAndrew Lynn * 0x01 PORnVbat 1379b4a31037SAndrew Lynn * 0x02 PonKey1dbF 1380b4a31037SAndrew Lynn * 0x04 PonKey2dbF 1381b4a31037SAndrew Lynn * 0x08 RTCAlarm 1382b4a31037SAndrew Lynn * 0x10 MainChDet 1383b4a31037SAndrew Lynn * 0x20 VbusDet 1384b4a31037SAndrew Lynn * 0x40 UsbIDDetect 1385b4a31037SAndrew Lynn * 0x80 Reserved 1386b4a31037SAndrew Lynn */ 1387b4a31037SAndrew Lynn static ssize_t show_turn_on_status(struct device *dev, 1388b4a31037SAndrew Lynn struct device_attribute *attr, char *buf) 1389b4a31037SAndrew Lynn { 1390b4a31037SAndrew Lynn int ret; 1391b4a31037SAndrew Lynn u8 value; 1392b4a31037SAndrew Lynn struct ab8500 *ab8500; 1393b4a31037SAndrew Lynn 1394b4a31037SAndrew Lynn ab8500 = dev_get_drvdata(dev); 1395b4a31037SAndrew Lynn ret = get_register_interruptible(ab8500, AB8500_SYS_CTRL1_BLOCK, 1396b4a31037SAndrew Lynn AB8500_TURN_ON_STATUS, &value); 1397b4a31037SAndrew Lynn if (ret < 0) 1398b4a31037SAndrew Lynn return ret; 1399f04a9d8aSRajkumar Kasirajan 1400f04a9d8aSRajkumar Kasirajan /* 1401f04a9d8aSRajkumar Kasirajan * In L9540, turn_on_status register is not updated correctly if 1402f04a9d8aSRajkumar Kasirajan * the device is rebooted with AC/USB charger connected. Due to 1403f04a9d8aSRajkumar Kasirajan * this, the device boots android instead of entering into charge 1404f04a9d8aSRajkumar Kasirajan * only mode. Read the AC/USB status register to detect the charger 1405f04a9d8aSRajkumar Kasirajan * presence and update the turn on status manually. 1406f04a9d8aSRajkumar Kasirajan */ 1407f04a9d8aSRajkumar Kasirajan if (is_ab9540(ab8500)) { 1408f04a9d8aSRajkumar Kasirajan spin_lock(&on_stat_lock); 1409f04a9d8aSRajkumar Kasirajan value = (value & turn_on_stat_mask) | turn_on_stat_set; 1410f04a9d8aSRajkumar Kasirajan spin_unlock(&on_stat_lock); 1411f04a9d8aSRajkumar Kasirajan } 1412f04a9d8aSRajkumar Kasirajan 1413b4a31037SAndrew Lynn return sprintf(buf, "%#x\n", value); 1414b4a31037SAndrew Lynn } 1415b4a31037SAndrew Lynn 141693ff722eSLee Jones static ssize_t show_turn_on_status_2(struct device *dev, 141793ff722eSLee Jones struct device_attribute *attr, char *buf) 141893ff722eSLee Jones { 141993ff722eSLee Jones int ret; 142093ff722eSLee Jones u8 value; 142193ff722eSLee Jones struct ab8500 *ab8500; 142293ff722eSLee Jones 142393ff722eSLee Jones ab8500 = dev_get_drvdata(dev); 142493ff722eSLee Jones ret = get_register_interruptible(ab8500, AB8500_SYS_CTRL1_BLOCK, 142593ff722eSLee Jones AB8505_TURN_ON_STATUS_2, &value); 142693ff722eSLee Jones if (ret < 0) 142793ff722eSLee Jones return ret; 142893ff722eSLee Jones return sprintf(buf, "%#x\n", (value & 0x1)); 142993ff722eSLee Jones } 143093ff722eSLee Jones 1431d6255529SLinus Walleij static ssize_t show_ab9540_dbbrstn(struct device *dev, 1432d6255529SLinus Walleij struct device_attribute *attr, char *buf) 1433d6255529SLinus Walleij { 1434d6255529SLinus Walleij struct ab8500 *ab8500; 1435d6255529SLinus Walleij int ret; 1436d6255529SLinus Walleij u8 value; 1437d6255529SLinus Walleij 1438d6255529SLinus Walleij ab8500 = dev_get_drvdata(dev); 1439d6255529SLinus Walleij 1440d6255529SLinus Walleij ret = get_register_interruptible(ab8500, AB8500_REGU_CTRL2, 1441d6255529SLinus Walleij AB9540_MODEM_CTRL2_REG, &value); 1442d6255529SLinus Walleij if (ret < 0) 1443d6255529SLinus Walleij return ret; 1444d6255529SLinus Walleij 1445d6255529SLinus Walleij return sprintf(buf, "%d\n", 1446d6255529SLinus Walleij (value & AB9540_MODEM_CTRL2_SWDBBRSTN_BIT) ? 1 : 0); 1447d6255529SLinus Walleij } 1448d6255529SLinus Walleij 1449d6255529SLinus Walleij static ssize_t store_ab9540_dbbrstn(struct device *dev, 1450d6255529SLinus Walleij struct device_attribute *attr, const char *buf, size_t count) 1451d6255529SLinus Walleij { 1452d6255529SLinus Walleij struct ab8500 *ab8500; 1453d6255529SLinus Walleij int ret = count; 1454d6255529SLinus Walleij int err; 1455d6255529SLinus Walleij u8 bitvalues; 1456d6255529SLinus Walleij 1457d6255529SLinus Walleij ab8500 = dev_get_drvdata(dev); 1458d6255529SLinus Walleij 1459d6255529SLinus Walleij if (count > 0) { 1460d6255529SLinus Walleij switch (buf[0]) { 1461d6255529SLinus Walleij case '0': 1462d6255529SLinus Walleij bitvalues = 0; 1463d6255529SLinus Walleij break; 1464d6255529SLinus Walleij case '1': 1465d6255529SLinus Walleij bitvalues = AB9540_MODEM_CTRL2_SWDBBRSTN_BIT; 1466d6255529SLinus Walleij break; 1467d6255529SLinus Walleij default: 1468d6255529SLinus Walleij goto exit; 1469d6255529SLinus Walleij } 1470d6255529SLinus Walleij 1471d6255529SLinus Walleij err = mask_and_set_register_interruptible(ab8500, 1472d6255529SLinus Walleij AB8500_REGU_CTRL2, AB9540_MODEM_CTRL2_REG, 1473d6255529SLinus Walleij AB9540_MODEM_CTRL2_SWDBBRSTN_BIT, bitvalues); 1474d6255529SLinus Walleij if (err) 1475d6255529SLinus Walleij dev_info(ab8500->dev, 1476d6255529SLinus Walleij "Failed to set DBBRSTN %c, err %#x\n", 1477d6255529SLinus Walleij buf[0], err); 1478d6255529SLinus Walleij } 1479d6255529SLinus Walleij 1480d6255529SLinus Walleij exit: 1481d6255529SLinus Walleij return ret; 1482d6255529SLinus Walleij } 1483d6255529SLinus Walleij 1484cca69b67SMattias Wallin static DEVICE_ATTR(chip_id, S_IRUGO, show_chip_id, NULL); 1485e5c238c3SMattias Wallin static DEVICE_ATTR(switch_off_status, S_IRUGO, show_switch_off_status, NULL); 1486b4a31037SAndrew Lynn static DEVICE_ATTR(turn_on_status, S_IRUGO, show_turn_on_status, NULL); 148793ff722eSLee Jones static DEVICE_ATTR(turn_on_status_2, S_IRUGO, show_turn_on_status_2, NULL); 1488d6255529SLinus Walleij static DEVICE_ATTR(dbbrstn, S_IRUGO | S_IWUSR, 1489d6255529SLinus Walleij show_ab9540_dbbrstn, store_ab9540_dbbrstn); 1490cca69b67SMattias Wallin 1491cca69b67SMattias Wallin static struct attribute *ab8500_sysfs_entries[] = { 1492cca69b67SMattias Wallin &dev_attr_chip_id.attr, 1493e5c238c3SMattias Wallin &dev_attr_switch_off_status.attr, 1494b4a31037SAndrew Lynn &dev_attr_turn_on_status.attr, 1495cca69b67SMattias Wallin NULL, 1496cca69b67SMattias Wallin }; 1497cca69b67SMattias Wallin 149893ff722eSLee Jones static struct attribute *ab8505_sysfs_entries[] = { 149993ff722eSLee Jones &dev_attr_turn_on_status_2.attr, 150093ff722eSLee Jones NULL, 150193ff722eSLee Jones }; 150293ff722eSLee Jones 1503d6255529SLinus Walleij static struct attribute *ab9540_sysfs_entries[] = { 1504d6255529SLinus Walleij &dev_attr_chip_id.attr, 1505d6255529SLinus Walleij &dev_attr_switch_off_status.attr, 1506d6255529SLinus Walleij &dev_attr_turn_on_status.attr, 1507d6255529SLinus Walleij &dev_attr_dbbrstn.attr, 1508d6255529SLinus Walleij NULL, 1509d6255529SLinus Walleij }; 1510d6255529SLinus Walleij 1511cca69b67SMattias Wallin static struct attribute_group ab8500_attr_group = { 1512cca69b67SMattias Wallin .attrs = ab8500_sysfs_entries, 1513cca69b67SMattias Wallin }; 1514cca69b67SMattias Wallin 151593ff722eSLee Jones static struct attribute_group ab8505_attr_group = { 151693ff722eSLee Jones .attrs = ab8505_sysfs_entries, 151793ff722eSLee Jones }; 151893ff722eSLee Jones 1519d6255529SLinus Walleij static struct attribute_group ab9540_attr_group = { 1520d6255529SLinus Walleij .attrs = ab9540_sysfs_entries, 1521d6255529SLinus Walleij }; 1522d6255529SLinus Walleij 1523f791be49SBill Pemberton static int ab8500_probe(struct platform_device *pdev) 152462579266SRabin Vincent { 1525b04c530cSJonas Aaberg static char *switch_off_status[] = { 1526b04c530cSJonas Aaberg "Swoff bit programming", 1527b04c530cSJonas Aaberg "Thermal protection activation", 1528b04c530cSJonas Aaberg "Vbat lower then BattOk falling threshold", 1529b04c530cSJonas Aaberg "Watchdog expired", 1530b04c530cSJonas Aaberg "Non presence of 32kHz clock", 1531b04c530cSJonas Aaberg "Battery level lower than power on reset threshold", 1532b04c530cSJonas Aaberg "Power on key 1 pressed longer than 10 seconds", 1533b04c530cSJonas Aaberg "DB8500 thermal shutdown"}; 1534abee26cdSMattias Wallin static char *turn_on_status[] = { 1535abee26cdSMattias Wallin "Battery rising (Vbat)", 1536abee26cdSMattias Wallin "Power On Key 1 dbF", 1537abee26cdSMattias Wallin "Power On Key 2 dbF", 1538abee26cdSMattias Wallin "RTC Alarm", 1539abee26cdSMattias Wallin "Main Charger Detect", 1540abee26cdSMattias Wallin "Vbus Detect (USB)", 1541abee26cdSMattias Wallin "USB ID Detect", 1542abee26cdSMattias Wallin "UART Factory Mode Detect"}; 1543d28f1db8SLee Jones struct ab8500_platform_data *plat = dev_get_platdata(&pdev->dev); 1544d28f1db8SLee Jones const struct platform_device_id *platid = platform_get_device_id(pdev); 15456bc4a568SLee Jones enum ab8500_version version = AB8500_VERSION_UNDEFINED; 15466bc4a568SLee Jones struct device_node *np = pdev->dev.of_node; 1547d28f1db8SLee Jones struct ab8500 *ab8500; 1548d28f1db8SLee Jones struct resource *resource; 154962579266SRabin Vincent int ret; 155062579266SRabin Vincent int i; 155147c16975SMattias Wallin u8 value; 155262579266SRabin Vincent 15538c4203cbSLee Jones ab8500 = devm_kzalloc(&pdev->dev, sizeof *ab8500, GFP_KERNEL); 1554d28f1db8SLee Jones if (!ab8500) 1555d28f1db8SLee Jones return -ENOMEM; 1556d28f1db8SLee Jones 155762579266SRabin Vincent if (plat) 155862579266SRabin Vincent ab8500->irq_base = plat->irq_base; 155962579266SRabin Vincent 1560d28f1db8SLee Jones ab8500->dev = &pdev->dev; 1561d28f1db8SLee Jones 1562d28f1db8SLee Jones resource = platform_get_resource(pdev, IORESOURCE_IRQ, 0); 15638c4203cbSLee Jones if (!resource) 15648c4203cbSLee Jones return -ENODEV; 1565d28f1db8SLee Jones 1566d28f1db8SLee Jones ab8500->irq = resource->start; 1567d28f1db8SLee Jones 1568822672a7SLee Jones ab8500->read = ab8500_prcmu_read; 1569822672a7SLee Jones ab8500->write = ab8500_prcmu_write; 1570822672a7SLee Jones ab8500->write_masked = ab8500_prcmu_write_masked; 1571d28f1db8SLee Jones 157262579266SRabin Vincent mutex_init(&ab8500->lock); 157362579266SRabin Vincent mutex_init(&ab8500->irq_lock); 1574112a80d2SJonas Aaberg atomic_set(&ab8500->transfer_ongoing, 0); 157562579266SRabin Vincent 1576d28f1db8SLee Jones platform_set_drvdata(pdev, ab8500); 1577d28f1db8SLee Jones 15786bc4a568SLee Jones if (platid) 15796bc4a568SLee Jones version = platid->driver_data; 15806bc4a568SLee Jones 15810f620837SLinus Walleij if (version != AB8500_VERSION_UNDEFINED) 15820f620837SLinus Walleij ab8500->version = version; 15830f620837SLinus Walleij else { 15840f620837SLinus Walleij ret = get_register_interruptible(ab8500, AB8500_MISC, 15850f620837SLinus Walleij AB8500_IC_NAME_REG, &value); 15860f620837SLinus Walleij if (ret < 0) 15878c4203cbSLee Jones return ret; 15880f620837SLinus Walleij 15890f620837SLinus Walleij ab8500->version = value; 15900f620837SLinus Walleij } 15910f620837SLinus Walleij 159247c16975SMattias Wallin ret = get_register_interruptible(ab8500, AB8500_MISC, 159347c16975SMattias Wallin AB8500_REV_REG, &value); 159462579266SRabin Vincent if (ret < 0) 15958c4203cbSLee Jones return ret; 159662579266SRabin Vincent 159747c16975SMattias Wallin ab8500->chip_id = value; 159862579266SRabin Vincent 15990f620837SLinus Walleij dev_info(ab8500->dev, "detected chip, %s rev. %1x.%1x\n", 16000f620837SLinus Walleij ab8500_version_str[ab8500->version], 16010f620837SLinus Walleij ab8500->chip_id >> 4, 16020f620837SLinus Walleij ab8500->chip_id & 0x0F); 16030f620837SLinus Walleij 16043e1a498fSLee Jones /* Configure AB8540 */ 16053e1a498fSLee Jones if (is_ab8540(ab8500)) { 16063e1a498fSLee Jones ab8500->mask_size = AB8540_NUM_IRQ_REGS; 16073e1a498fSLee Jones ab8500->irq_reg_offset = ab8540_irq_regoffset; 16083e1a498fSLee Jones ab8500->it_latchhier_num = AB8540_IT_LATCHHIER_NUM; 16093e1a498fSLee Jones }/* Configure AB8500 or AB9540 IRQ */ 16103e1a498fSLee Jones else if (is_ab9540(ab8500) || is_ab8505(ab8500)) { 1611d6255529SLinus Walleij ab8500->mask_size = AB9540_NUM_IRQ_REGS; 1612d6255529SLinus Walleij ab8500->irq_reg_offset = ab9540_irq_regoffset; 16133e1a498fSLee Jones ab8500->it_latchhier_num = AB8500_IT_LATCHHIER_NUM; 1614d6255529SLinus Walleij } else { 16152ced445eSLinus Walleij ab8500->mask_size = AB8500_NUM_IRQ_REGS; 16162ced445eSLinus Walleij ab8500->irq_reg_offset = ab8500_irq_regoffset; 16173e1a498fSLee Jones ab8500->it_latchhier_num = AB8500_IT_LATCHHIER_NUM; 1618d6255529SLinus Walleij } 16198c4203cbSLee Jones ab8500->mask = devm_kzalloc(&pdev->dev, ab8500->mask_size, GFP_KERNEL); 16202ced445eSLinus Walleij if (!ab8500->mask) 16212ced445eSLinus Walleij return -ENOMEM; 16228c4203cbSLee Jones ab8500->oldmask = devm_kzalloc(&pdev->dev, ab8500->mask_size, GFP_KERNEL); 16238c4203cbSLee Jones if (!ab8500->oldmask) 16248c4203cbSLee Jones return -ENOMEM; 16258c4203cbSLee Jones 1626e5c238c3SMattias Wallin /* 1627e5c238c3SMattias Wallin * ab8500 has switched off due to (SWITCH_OFF_STATUS): 1628e5c238c3SMattias Wallin * 0x01 Swoff bit programming 1629e5c238c3SMattias Wallin * 0x02 Thermal protection activation 1630e5c238c3SMattias Wallin * 0x04 Vbat lower then BattOk falling threshold 1631e5c238c3SMattias Wallin * 0x08 Watchdog expired 1632e5c238c3SMattias Wallin * 0x10 Non presence of 32kHz clock 1633e5c238c3SMattias Wallin * 0x20 Battery level lower than power on reset threshold 1634e5c238c3SMattias Wallin * 0x40 Power on key 1 pressed longer than 10 seconds 1635e5c238c3SMattias Wallin * 0x80 DB8500 thermal shutdown 1636e5c238c3SMattias Wallin */ 1637e5c238c3SMattias Wallin 1638e5c238c3SMattias Wallin ret = get_register_interruptible(ab8500, AB8500_RTC, 1639e5c238c3SMattias Wallin AB8500_SWITCH_OFF_STATUS, &value); 1640e5c238c3SMattias Wallin if (ret < 0) 1641e5c238c3SMattias Wallin return ret; 1642b04c530cSJonas Aaberg dev_info(ab8500->dev, "switch off cause(s) (%#x): ", value); 1643b04c530cSJonas Aaberg 1644b04c530cSJonas Aaberg if (value) { 1645b04c530cSJonas Aaberg for (i = 0; i < ARRAY_SIZE(switch_off_status); i++) { 1646b04c530cSJonas Aaberg if (value & 1) 1647b04c530cSJonas Aaberg printk(KERN_CONT " \"%s\"", 1648b04c530cSJonas Aaberg switch_off_status[i]); 1649b04c530cSJonas Aaberg value = value >> 1; 1650b04c530cSJonas Aaberg 1651b04c530cSJonas Aaberg } 1652b04c530cSJonas Aaberg printk(KERN_CONT "\n"); 1653b04c530cSJonas Aaberg } else { 1654b04c530cSJonas Aaberg printk(KERN_CONT " None\n"); 1655b04c530cSJonas Aaberg } 1656abee26cdSMattias Wallin ret = get_register_interruptible(ab8500, AB8500_SYS_CTRL1_BLOCK, 1657abee26cdSMattias Wallin AB8500_TURN_ON_STATUS, &value); 1658abee26cdSMattias Wallin if (ret < 0) 1659abee26cdSMattias Wallin return ret; 1660abee26cdSMattias Wallin dev_info(ab8500->dev, "turn on reason(s) (%#x): ", value); 1661abee26cdSMattias Wallin 1662abee26cdSMattias Wallin if (value) { 1663abee26cdSMattias Wallin for (i = 0; i < ARRAY_SIZE(turn_on_status); i++) { 1664abee26cdSMattias Wallin if (value & 1) 1665abee26cdSMattias Wallin printk("\"%s\" ", turn_on_status[i]); 1666abee26cdSMattias Wallin value = value >> 1; 1667abee26cdSMattias Wallin } 1668abee26cdSMattias Wallin printk("\n"); 1669abee26cdSMattias Wallin } else { 1670abee26cdSMattias Wallin printk("None\n"); 1671abee26cdSMattias Wallin } 1672e5c238c3SMattias Wallin 167362579266SRabin Vincent if (plat && plat->init) 167462579266SRabin Vincent plat->init(ab8500); 1675abee26cdSMattias Wallin 1676f04a9d8aSRajkumar Kasirajan if (is_ab9540(ab8500)) { 1677f04a9d8aSRajkumar Kasirajan ret = get_register_interruptible(ab8500, AB8500_CHARGER, 1678f04a9d8aSRajkumar Kasirajan AB8500_CH_USBCH_STAT1_REG, &value); 1679f04a9d8aSRajkumar Kasirajan if (ret < 0) 1680f04a9d8aSRajkumar Kasirajan return ret; 1681f04a9d8aSRajkumar Kasirajan if ((value & VBUS_DET_DBNC1) && (value & VBUS_DET_DBNC100)) 1682f04a9d8aSRajkumar Kasirajan ab8500_override_turn_on_stat(~AB8500_POW_KEY_1_ON, 1683f04a9d8aSRajkumar Kasirajan AB8500_VBUS_DET); 1684f04a9d8aSRajkumar Kasirajan } 168562579266SRabin Vincent 168662579266SRabin Vincent /* Clear and mask all interrupts */ 16872ced445eSLinus Walleij for (i = 0; i < ab8500->mask_size; i++) { 16880f620837SLinus Walleij /* 16890f620837SLinus Walleij * Interrupt register 12 doesn't exist prior to AB8500 version 16900f620837SLinus Walleij * 2.0 16910f620837SLinus Walleij */ 16920f620837SLinus Walleij if (ab8500->irq_reg_offset[i] == 11 && 16930f620837SLinus Walleij is_ab8500_1p1_or_earlier(ab8500)) 169492d50a41SMattias Wallin continue; 169562579266SRabin Vincent 16963e1a498fSLee Jones if (ab8500->irq_reg_offset[i] < 0) 16973e1a498fSLee Jones continue; 16983e1a498fSLee Jones 169947c16975SMattias Wallin get_register_interruptible(ab8500, AB8500_INTERRUPT, 17002ced445eSLinus Walleij AB8500_IT_LATCH1_REG + ab8500->irq_reg_offset[i], 170192d50a41SMattias Wallin &value); 170247c16975SMattias Wallin set_register_interruptible(ab8500, AB8500_INTERRUPT, 17032ced445eSLinus Walleij AB8500_IT_MASK1_REG + ab8500->irq_reg_offset[i], 0xff); 170462579266SRabin Vincent } 170562579266SRabin Vincent 170647c16975SMattias Wallin ret = abx500_register_ops(ab8500->dev, &ab8500_ops); 170747c16975SMattias Wallin if (ret) 17088c4203cbSLee Jones return ret; 170947c16975SMattias Wallin 17102ced445eSLinus Walleij for (i = 0; i < ab8500->mask_size; i++) 171162579266SRabin Vincent ab8500->mask[i] = ab8500->oldmask[i] = 0xff; 171262579266SRabin Vincent 171306e589efSLee Jones ret = ab8500_irq_init(ab8500, np); 171462579266SRabin Vincent if (ret) 17158c4203cbSLee Jones return ret; 171662579266SRabin Vincent 17178c4203cbSLee Jones ret = devm_request_threaded_irq(&pdev->dev, ab8500->irq, NULL, 17187ccfe9b1SMichel JAOUEN ab8500_hierarchical_irq, 17197ccfe9b1SMichel JAOUEN IRQF_ONESHOT | IRQF_NO_SUSPEND, 17207ccfe9b1SMichel JAOUEN "ab8500", ab8500); 172162579266SRabin Vincent if (ret) 17228c4203cbSLee Jones return ret; 172362579266SRabin Vincent 17246999181eSLinus Walleij #if CONFIG_DEBUG_FS 17256999181eSLinus Walleij /* Pass to debugfs */ 17266999181eSLinus Walleij ab8500_debug_resources[0].start = ab8500->irq; 17276999181eSLinus Walleij ab8500_debug_resources[0].end = ab8500->irq; 17286999181eSLinus Walleij #endif 17296999181eSLinus Walleij 1730d6255529SLinus Walleij if (is_ab9540(ab8500)) 1731d6255529SLinus Walleij ret = mfd_add_devices(ab8500->dev, 0, ab9540_devs, 1732d6255529SLinus Walleij ARRAY_SIZE(ab9540_devs), NULL, 173355692af5SMark Brown ab8500->irq_base, ab8500->domain); 1734c0eda9aeSLee Jones else if (is_ab8540(ab8500)) 1735c0eda9aeSLee Jones ret = mfd_add_devices(ab8500->dev, 0, ab8540_devs, 1736c0eda9aeSLee Jones ARRAY_SIZE(ab8540_devs), NULL, 1737c0eda9aeSLee Jones ab8500->irq_base, ab8500->domain); 1738c0eda9aeSLee Jones else if (is_ab8505(ab8500)) 1739c0eda9aeSLee Jones ret = mfd_add_devices(ab8500->dev, 0, ab8505_devs, 1740c0eda9aeSLee Jones ARRAY_SIZE(ab8505_devs), NULL, 1741c0eda9aeSLee Jones ab8500->irq_base, ab8500->domain); 1742d6255529SLinus Walleij else 1743549931f9SSundar R Iyer ret = mfd_add_devices(ab8500->dev, 0, ab8500_devs, 174444f72e53SVirupax Sadashivpetimath ARRAY_SIZE(ab8500_devs), NULL, 174555692af5SMark Brown ab8500->irq_base, ab8500->domain); 17466bc4a568SLee Jones if (ret) 17478c4203cbSLee Jones return ret; 174844f72e53SVirupax Sadashivpetimath 17496ef9418cSRickard Andersson if (!no_bm) { 17506ef9418cSRickard Andersson /* Add battery management devices */ 17516ef9418cSRickard Andersson ret = mfd_add_devices(ab8500->dev, 0, ab8500_bm_devs, 17526ef9418cSRickard Andersson ARRAY_SIZE(ab8500_bm_devs), NULL, 175355692af5SMark Brown ab8500->irq_base, ab8500->domain); 17546ef9418cSRickard Andersson if (ret) 17556ef9418cSRickard Andersson dev_err(ab8500->dev, "error adding bm devices\n"); 17566ef9418cSRickard Andersson } 17576ef9418cSRickard Andersson 1758e436ddffSLee Jones if (((is_ab8505(ab8500) || is_ab9540(ab8500)) && 1759e436ddffSLee Jones ab8500->chip_id >= AB8500_CUT2P0) || is_ab8540(ab8500)) 1760d6255529SLinus Walleij ret = sysfs_create_group(&ab8500->dev->kobj, 1761d6255529SLinus Walleij &ab9540_attr_group); 1762d6255529SLinus Walleij else 1763d6255529SLinus Walleij ret = sysfs_create_group(&ab8500->dev->kobj, 1764d6255529SLinus Walleij &ab8500_attr_group); 176593ff722eSLee Jones 176693ff722eSLee Jones if ((is_ab8505(ab8500) || is_ab9540(ab8500)) && 176793ff722eSLee Jones ab8500->chip_id >= AB8500_CUT2P0) 176893ff722eSLee Jones ret = sysfs_create_group(&ab8500->dev->kobj, 176993ff722eSLee Jones &ab8505_attr_group); 177093ff722eSLee Jones 1771cca69b67SMattias Wallin if (ret) 1772cca69b67SMattias Wallin dev_err(ab8500->dev, "error creating sysfs entries\n"); 177306e589efSLee Jones 177462579266SRabin Vincent return ret; 177562579266SRabin Vincent } 177662579266SRabin Vincent 17774740f73fSBill Pemberton static int ab8500_remove(struct platform_device *pdev) 177862579266SRabin Vincent { 1779d28f1db8SLee Jones struct ab8500 *ab8500 = platform_get_drvdata(pdev); 1780d28f1db8SLee Jones 1781e436ddffSLee Jones if (((is_ab8505(ab8500) || is_ab9540(ab8500)) && 1782e436ddffSLee Jones ab8500->chip_id >= AB8500_CUT2P0) || is_ab8540(ab8500)) 1783d6255529SLinus Walleij sysfs_remove_group(&ab8500->dev->kobj, &ab9540_attr_group); 1784d6255529SLinus Walleij else 1785cca69b67SMattias Wallin sysfs_remove_group(&ab8500->dev->kobj, &ab8500_attr_group); 178606e589efSLee Jones 178793ff722eSLee Jones if ((is_ab8505(ab8500) || is_ab9540(ab8500)) && 178893ff722eSLee Jones ab8500->chip_id >= AB8500_CUT2P0) 178993ff722eSLee Jones sysfs_remove_group(&ab8500->dev->kobj, &ab8505_attr_group); 179093ff722eSLee Jones 179162579266SRabin Vincent mfd_remove_devices(ab8500->dev); 179262579266SRabin Vincent 179362579266SRabin Vincent return 0; 179462579266SRabin Vincent } 179562579266SRabin Vincent 1796d28f1db8SLee Jones static const struct platform_device_id ab8500_id[] = { 1797d28f1db8SLee Jones { "ab8500-core", AB8500_VERSION_AB8500 }, 1798d28f1db8SLee Jones { "ab8505-i2c", AB8500_VERSION_AB8505 }, 1799d28f1db8SLee Jones { "ab9540-i2c", AB8500_VERSION_AB9540 }, 1800d28f1db8SLee Jones { "ab8540-i2c", AB8500_VERSION_AB8540 }, 1801d28f1db8SLee Jones { } 1802d28f1db8SLee Jones }; 1803d28f1db8SLee Jones 1804d28f1db8SLee Jones static struct platform_driver ab8500_core_driver = { 1805d28f1db8SLee Jones .driver = { 1806d28f1db8SLee Jones .name = "ab8500-core", 1807d28f1db8SLee Jones .owner = THIS_MODULE, 1808d28f1db8SLee Jones }, 1809d28f1db8SLee Jones .probe = ab8500_probe, 181084449216SBill Pemberton .remove = ab8500_remove, 1811d28f1db8SLee Jones .id_table = ab8500_id, 1812d28f1db8SLee Jones }; 1813d28f1db8SLee Jones 1814d28f1db8SLee Jones static int __init ab8500_core_init(void) 1815d28f1db8SLee Jones { 1816d28f1db8SLee Jones return platform_driver_register(&ab8500_core_driver); 1817d28f1db8SLee Jones } 1818d28f1db8SLee Jones 1819d28f1db8SLee Jones static void __exit ab8500_core_exit(void) 1820d28f1db8SLee Jones { 1821d28f1db8SLee Jones platform_driver_unregister(&ab8500_core_driver); 1822d28f1db8SLee Jones } 1823ba7cbc3eSLee Jones core_initcall(ab8500_core_init); 1824d28f1db8SLee Jones module_exit(ab8500_core_exit); 1825d28f1db8SLee Jones 1826adceed62SMattias Wallin MODULE_AUTHOR("Mattias Wallin, Srinidhi Kasagar, Rabin Vincent"); 182762579266SRabin Vincent MODULE_DESCRIPTION("AB8500 MFD core"); 182862579266SRabin Vincent MODULE_LICENSE("GPL v2"); 1829