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 106*3e1a498fSLee Jones #define AB8540_IT_LATCHHIER4_REG 0x63 1077ccfe9b1SMichel JAOUEN 1087ccfe9b1SMichel JAOUEN #define AB8500_IT_LATCHHIER_NUM 3 109*3e1a498fSLee 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 116b4a31037SAndrew Lynn 117f04a9d8aSRajkumar Kasirajan #define AB8500_CH_USBCH_STAT1_REG 0x02 118f04a9d8aSRajkumar Kasirajan #define VBUS_DET_DBNC100 0x02 119f04a9d8aSRajkumar Kasirajan #define VBUS_DET_DBNC1 0x01 120f04a9d8aSRajkumar Kasirajan 121f04a9d8aSRajkumar Kasirajan static DEFINE_SPINLOCK(on_stat_lock); 122f04a9d8aSRajkumar Kasirajan static u8 turn_on_stat_mask = 0xFF; 123f04a9d8aSRajkumar Kasirajan static u8 turn_on_stat_set; 1246ef9418cSRickard Andersson static bool no_bm; /* No battery management */ 1256ef9418cSRickard Andersson module_param(no_bm, bool, S_IRUGO); 1266ef9418cSRickard Andersson 127d6255529SLinus Walleij #define AB9540_MODEM_CTRL2_REG 0x23 128d6255529SLinus Walleij #define AB9540_MODEM_CTRL2_SWDBBRSTN_BIT BIT(2) 129d6255529SLinus Walleij 13062579266SRabin Vincent /* 13162579266SRabin Vincent * Map interrupt numbers to the LATCH and MASK register offsets, Interrupt 1322ced445eSLinus Walleij * numbers are indexed into this array with (num / 8). The interupts are 1332ced445eSLinus Walleij * defined in linux/mfd/ab8500.h 13462579266SRabin Vincent * 13562579266SRabin Vincent * This is one off from the register names, i.e. AB8500_IT_MASK1_REG is at 13662579266SRabin Vincent * offset 0. 13762579266SRabin Vincent */ 1382ced445eSLinus Walleij /* AB8500 support */ 13962579266SRabin Vincent static const int ab8500_irq_regoffset[AB8500_NUM_IRQ_REGS] = { 14092d50a41SMattias Wallin 0, 1, 2, 3, 4, 6, 7, 8, 9, 11, 18, 19, 20, 21, 14162579266SRabin Vincent }; 14262579266SRabin Vincent 143a29264b6SLee Jones /* AB9540 / AB8505 support */ 144d6255529SLinus Walleij static const int ab9540_irq_regoffset[AB9540_NUM_IRQ_REGS] = { 145a29264b6SLee Jones 0, 1, 2, 3, 4, 6, 7, 8, 9, 11, 18, 19, 20, 21, 12, 13, 24, 5, 22, 23 146d6255529SLinus Walleij }; 147d6255529SLinus Walleij 148*3e1a498fSLee Jones /* AB8540 support */ 149*3e1a498fSLee Jones static const int ab8540_irq_regoffset[AB8540_NUM_IRQ_REGS] = { 150*3e1a498fSLee Jones 0, 1, 2, 3, 4, -1, -1, -1, -1, 11, 18, 19, 20, 21, 12, 13, 24, 5, 22, 23, 151*3e1a498fSLee Jones 25, 26, 27, 28, 29, 30, 31, 152*3e1a498fSLee Jones }; 153*3e1a498fSLee Jones 1540f620837SLinus Walleij static const char ab8500_version_str[][7] = { 1550f620837SLinus Walleij [AB8500_VERSION_AB8500] = "AB8500", 1560f620837SLinus Walleij [AB8500_VERSION_AB8505] = "AB8505", 1570f620837SLinus Walleij [AB8500_VERSION_AB9540] = "AB9540", 1580f620837SLinus Walleij [AB8500_VERSION_AB8540] = "AB8540", 1590f620837SLinus Walleij }; 1600f620837SLinus Walleij 161822672a7SLee Jones static int ab8500_prcmu_write(struct ab8500 *ab8500, u16 addr, u8 data) 162d28f1db8SLee Jones { 163d28f1db8SLee Jones int ret; 164d28f1db8SLee Jones 165d28f1db8SLee Jones ret = prcmu_abb_write((u8)(addr >> 8), (u8)(addr & 0xFF), &data, 1); 166d28f1db8SLee Jones if (ret < 0) 167d28f1db8SLee Jones dev_err(ab8500->dev, "prcmu i2c error %d\n", ret); 168d28f1db8SLee Jones return ret; 169d28f1db8SLee Jones } 170d28f1db8SLee Jones 171822672a7SLee Jones static int ab8500_prcmu_write_masked(struct ab8500 *ab8500, u16 addr, u8 mask, 172d28f1db8SLee Jones u8 data) 173d28f1db8SLee Jones { 174d28f1db8SLee Jones int ret; 175d28f1db8SLee Jones 176d28f1db8SLee Jones ret = prcmu_abb_write_masked((u8)(addr >> 8), (u8)(addr & 0xFF), &data, 177d28f1db8SLee Jones &mask, 1); 178d28f1db8SLee Jones if (ret < 0) 179d28f1db8SLee Jones dev_err(ab8500->dev, "prcmu i2c error %d\n", ret); 180d28f1db8SLee Jones return ret; 181d28f1db8SLee Jones } 182d28f1db8SLee Jones 183822672a7SLee Jones static int ab8500_prcmu_read(struct ab8500 *ab8500, u16 addr) 184d28f1db8SLee Jones { 185d28f1db8SLee Jones int ret; 186d28f1db8SLee Jones u8 data; 187d28f1db8SLee Jones 188d28f1db8SLee Jones ret = prcmu_abb_read((u8)(addr >> 8), (u8)(addr & 0xFF), &data, 1); 189d28f1db8SLee Jones if (ret < 0) { 190d28f1db8SLee Jones dev_err(ab8500->dev, "prcmu i2c error %d\n", ret); 191d28f1db8SLee Jones return ret; 192d28f1db8SLee Jones } 193d28f1db8SLee Jones return (int)data; 194d28f1db8SLee Jones } 195d28f1db8SLee Jones 19647c16975SMattias Wallin static int ab8500_get_chip_id(struct device *dev) 19747c16975SMattias Wallin { 1986bce7bf1SMattias Wallin struct ab8500 *ab8500; 1996bce7bf1SMattias Wallin 2006bce7bf1SMattias Wallin if (!dev) 2016bce7bf1SMattias Wallin return -EINVAL; 2026bce7bf1SMattias Wallin ab8500 = dev_get_drvdata(dev->parent); 2036bce7bf1SMattias Wallin return ab8500 ? (int)ab8500->chip_id : -EINVAL; 20447c16975SMattias Wallin } 20547c16975SMattias Wallin 20647c16975SMattias Wallin static int set_register_interruptible(struct ab8500 *ab8500, u8 bank, 20747c16975SMattias Wallin u8 reg, u8 data) 20862579266SRabin Vincent { 20962579266SRabin Vincent int ret; 21047c16975SMattias Wallin /* 21147c16975SMattias Wallin * Put the u8 bank and u8 register together into a an u16. 21247c16975SMattias Wallin * The bank on higher 8 bits and register in lower 8 bits. 21347c16975SMattias Wallin * */ 21447c16975SMattias Wallin u16 addr = ((u16)bank) << 8 | reg; 21562579266SRabin Vincent 21662579266SRabin Vincent dev_vdbg(ab8500->dev, "wr: addr %#x <= %#x\n", addr, data); 21762579266SRabin Vincent 218392cbd1eSRabin Vincent mutex_lock(&ab8500->lock); 21947c16975SMattias Wallin 22047c16975SMattias Wallin ret = ab8500->write(ab8500, addr, data); 22147c16975SMattias Wallin if (ret < 0) 22247c16975SMattias Wallin dev_err(ab8500->dev, "failed to write reg %#x: %d\n", 22347c16975SMattias Wallin addr, ret); 22447c16975SMattias Wallin mutex_unlock(&ab8500->lock); 22547c16975SMattias Wallin 22647c16975SMattias Wallin return ret; 22747c16975SMattias Wallin } 22847c16975SMattias Wallin 22947c16975SMattias Wallin static int ab8500_set_register(struct device *dev, u8 bank, 23047c16975SMattias Wallin u8 reg, u8 value) 23147c16975SMattias Wallin { 232112a80d2SJonas Aaberg int ret; 23347c16975SMattias Wallin struct ab8500 *ab8500 = dev_get_drvdata(dev->parent); 23447c16975SMattias Wallin 235112a80d2SJonas Aaberg atomic_inc(&ab8500->transfer_ongoing); 236112a80d2SJonas Aaberg ret = set_register_interruptible(ab8500, bank, reg, value); 237112a80d2SJonas Aaberg atomic_dec(&ab8500->transfer_ongoing); 238112a80d2SJonas Aaberg return ret; 23947c16975SMattias Wallin } 24047c16975SMattias Wallin 24147c16975SMattias Wallin static int get_register_interruptible(struct ab8500 *ab8500, u8 bank, 24247c16975SMattias Wallin u8 reg, u8 *value) 24347c16975SMattias Wallin { 24447c16975SMattias Wallin int ret; 24547c16975SMattias Wallin /* put the u8 bank and u8 reg together into a an u16. 24647c16975SMattias Wallin * bank on higher 8 bits and reg in lower */ 24747c16975SMattias Wallin u16 addr = ((u16)bank) << 8 | reg; 24847c16975SMattias Wallin 249392cbd1eSRabin Vincent mutex_lock(&ab8500->lock); 25047c16975SMattias Wallin 25147c16975SMattias Wallin ret = ab8500->read(ab8500, addr); 25247c16975SMattias Wallin if (ret < 0) 25347c16975SMattias Wallin dev_err(ab8500->dev, "failed to read reg %#x: %d\n", 25447c16975SMattias Wallin addr, ret); 25547c16975SMattias Wallin else 25647c16975SMattias Wallin *value = ret; 25747c16975SMattias Wallin 25847c16975SMattias Wallin mutex_unlock(&ab8500->lock); 25947c16975SMattias Wallin dev_vdbg(ab8500->dev, "rd: addr %#x => data %#x\n", addr, ret); 26047c16975SMattias Wallin 26147c16975SMattias Wallin return ret; 26247c16975SMattias Wallin } 26347c16975SMattias Wallin 26447c16975SMattias Wallin static int ab8500_get_register(struct device *dev, u8 bank, 26547c16975SMattias Wallin u8 reg, u8 *value) 26647c16975SMattias Wallin { 267112a80d2SJonas Aaberg int ret; 26847c16975SMattias Wallin struct ab8500 *ab8500 = dev_get_drvdata(dev->parent); 26947c16975SMattias Wallin 270112a80d2SJonas Aaberg atomic_inc(&ab8500->transfer_ongoing); 271112a80d2SJonas Aaberg ret = get_register_interruptible(ab8500, bank, reg, value); 272112a80d2SJonas Aaberg atomic_dec(&ab8500->transfer_ongoing); 273112a80d2SJonas Aaberg return ret; 27447c16975SMattias Wallin } 27547c16975SMattias Wallin 27647c16975SMattias Wallin static int mask_and_set_register_interruptible(struct ab8500 *ab8500, u8 bank, 27747c16975SMattias Wallin u8 reg, u8 bitmask, u8 bitvalues) 27847c16975SMattias Wallin { 27947c16975SMattias Wallin int ret; 28047c16975SMattias Wallin /* put the u8 bank and u8 reg together into a an u16. 28147c16975SMattias Wallin * bank on higher 8 bits and reg in lower */ 28247c16975SMattias Wallin u16 addr = ((u16)bank) << 8 | reg; 28347c16975SMattias Wallin 284392cbd1eSRabin Vincent mutex_lock(&ab8500->lock); 28547c16975SMattias Wallin 286bc628fd1SMattias Nilsson if (ab8500->write_masked == NULL) { 287bc628fd1SMattias Nilsson u8 data; 288bc628fd1SMattias Nilsson 28947c16975SMattias Wallin ret = ab8500->read(ab8500, addr); 29047c16975SMattias Wallin if (ret < 0) { 29147c16975SMattias Wallin dev_err(ab8500->dev, "failed to read reg %#x: %d\n", 29247c16975SMattias Wallin addr, ret); 29347c16975SMattias Wallin goto out; 29447c16975SMattias Wallin } 29547c16975SMattias Wallin 29647c16975SMattias Wallin data = (u8)ret; 29747c16975SMattias Wallin data = (~bitmask & data) | (bitmask & bitvalues); 29847c16975SMattias Wallin 29962579266SRabin Vincent ret = ab8500->write(ab8500, addr, data); 30062579266SRabin Vincent if (ret < 0) 30162579266SRabin Vincent dev_err(ab8500->dev, "failed to write reg %#x: %d\n", 30262579266SRabin Vincent addr, ret); 30362579266SRabin Vincent 304bc628fd1SMattias Nilsson dev_vdbg(ab8500->dev, "mask: addr %#x => data %#x\n", addr, 305bc628fd1SMattias Nilsson data); 306bc628fd1SMattias Nilsson goto out; 307bc628fd1SMattias Nilsson } 308bc628fd1SMattias Nilsson ret = ab8500->write_masked(ab8500, addr, bitmask, bitvalues); 309bc628fd1SMattias Nilsson if (ret < 0) 310bc628fd1SMattias Nilsson dev_err(ab8500->dev, "failed to modify reg %#x: %d\n", addr, 311bc628fd1SMattias Nilsson ret); 31262579266SRabin Vincent out: 31362579266SRabin Vincent mutex_unlock(&ab8500->lock); 31462579266SRabin Vincent return ret; 31562579266SRabin Vincent } 31647c16975SMattias Wallin 31747c16975SMattias Wallin static int ab8500_mask_and_set_register(struct device *dev, 31847c16975SMattias Wallin u8 bank, u8 reg, u8 bitmask, u8 bitvalues) 31947c16975SMattias Wallin { 320112a80d2SJonas Aaberg int ret; 32147c16975SMattias Wallin struct ab8500 *ab8500 = dev_get_drvdata(dev->parent); 32247c16975SMattias Wallin 323112a80d2SJonas Aaberg atomic_inc(&ab8500->transfer_ongoing); 324112a80d2SJonas Aaberg ret= mask_and_set_register_interruptible(ab8500, bank, reg, 32547c16975SMattias Wallin bitmask, bitvalues); 326112a80d2SJonas Aaberg atomic_dec(&ab8500->transfer_ongoing); 327112a80d2SJonas Aaberg return ret; 32847c16975SMattias Wallin } 32947c16975SMattias Wallin 33047c16975SMattias Wallin static struct abx500_ops ab8500_ops = { 33147c16975SMattias Wallin .get_chip_id = ab8500_get_chip_id, 33247c16975SMattias Wallin .get_register = ab8500_get_register, 33347c16975SMattias Wallin .set_register = ab8500_set_register, 33447c16975SMattias Wallin .get_register_page = NULL, 33547c16975SMattias Wallin .set_register_page = NULL, 33647c16975SMattias Wallin .mask_and_set_register = ab8500_mask_and_set_register, 33747c16975SMattias Wallin .event_registers_startup_state_get = NULL, 33847c16975SMattias Wallin .startup_irq_enabled = NULL, 3391d843a6cSMian Yousaf Kaukab .dump_all_banks = ab8500_dump_all_banks, 34047c16975SMattias Wallin }; 34162579266SRabin Vincent 3429505a0a0SMark Brown static void ab8500_irq_lock(struct irq_data *data) 34362579266SRabin Vincent { 3449505a0a0SMark Brown struct ab8500 *ab8500 = irq_data_get_irq_chip_data(data); 34562579266SRabin Vincent 34662579266SRabin Vincent mutex_lock(&ab8500->irq_lock); 347112a80d2SJonas Aaberg atomic_inc(&ab8500->transfer_ongoing); 34862579266SRabin Vincent } 34962579266SRabin Vincent 3509505a0a0SMark Brown static void ab8500_irq_sync_unlock(struct irq_data *data) 35162579266SRabin Vincent { 3529505a0a0SMark Brown struct ab8500 *ab8500 = irq_data_get_irq_chip_data(data); 35362579266SRabin Vincent int i; 35462579266SRabin Vincent 3552ced445eSLinus Walleij for (i = 0; i < ab8500->mask_size; i++) { 35662579266SRabin Vincent u8 old = ab8500->oldmask[i]; 35762579266SRabin Vincent u8 new = ab8500->mask[i]; 35862579266SRabin Vincent int reg; 35962579266SRabin Vincent 36062579266SRabin Vincent if (new == old) 36162579266SRabin Vincent continue; 36262579266SRabin Vincent 3630f620837SLinus Walleij /* 3640f620837SLinus Walleij * Interrupt register 12 doesn't exist prior to AB8500 version 3650f620837SLinus Walleij * 2.0 3660f620837SLinus Walleij */ 3670f620837SLinus Walleij if (ab8500->irq_reg_offset[i] == 11 && 3680f620837SLinus Walleij is_ab8500_1p1_or_earlier(ab8500)) 36992d50a41SMattias Wallin continue; 37092d50a41SMattias Wallin 371*3e1a498fSLee Jones if (ab8500->irq_reg_offset[i] < 0) 372*3e1a498fSLee Jones continue; 373*3e1a498fSLee Jones 37462579266SRabin Vincent ab8500->oldmask[i] = new; 37562579266SRabin Vincent 3762ced445eSLinus Walleij reg = AB8500_IT_MASK1_REG + ab8500->irq_reg_offset[i]; 37747c16975SMattias Wallin set_register_interruptible(ab8500, AB8500_INTERRUPT, reg, new); 37862579266SRabin Vincent } 379112a80d2SJonas Aaberg atomic_dec(&ab8500->transfer_ongoing); 38062579266SRabin Vincent mutex_unlock(&ab8500->irq_lock); 38162579266SRabin Vincent } 38262579266SRabin Vincent 3839505a0a0SMark Brown static void ab8500_irq_mask(struct irq_data *data) 38462579266SRabin Vincent { 3859505a0a0SMark Brown struct ab8500 *ab8500 = irq_data_get_irq_chip_data(data); 38606e589efSLee Jones int offset = data->hwirq; 38762579266SRabin Vincent int index = offset / 8; 38862579266SRabin Vincent int mask = 1 << (offset % 8); 38962579266SRabin Vincent 39062579266SRabin Vincent ab8500->mask[index] |= mask; 3919c677b9bSLee Jones 3929c677b9bSLee Jones /* The AB8500 GPIOs have two interrupts each (rising & falling). */ 3939c677b9bSLee Jones if (offset >= AB8500_INT_GPIO6R && offset <= AB8500_INT_GPIO41R) 3949c677b9bSLee Jones ab8500->mask[index + 2] |= mask; 3959c677b9bSLee Jones if (offset >= AB9540_INT_GPIO50R && offset <= AB9540_INT_GPIO54R) 3969c677b9bSLee Jones ab8500->mask[index + 1] |= mask; 3979c677b9bSLee Jones if (offset == AB8540_INT_GPIO43R || offset == AB8540_INT_GPIO44R) 398e2ddf46aSLinus Walleij /* Here the falling IRQ is one bit lower */ 399e2ddf46aSLinus Walleij ab8500->mask[index] |= (mask << 1); 40062579266SRabin Vincent } 40162579266SRabin Vincent 4029505a0a0SMark Brown static void ab8500_irq_unmask(struct irq_data *data) 40362579266SRabin Vincent { 4049505a0a0SMark Brown struct ab8500 *ab8500 = irq_data_get_irq_chip_data(data); 4059c677b9bSLee Jones unsigned int type = irqd_get_trigger_type(data); 40606e589efSLee Jones int offset = data->hwirq; 40762579266SRabin Vincent int index = offset / 8; 40862579266SRabin Vincent int mask = 1 << (offset % 8); 40962579266SRabin Vincent 4109c677b9bSLee Jones if (type & IRQ_TYPE_EDGE_RISING) 41162579266SRabin Vincent ab8500->mask[index] &= ~mask; 4129c677b9bSLee Jones 4139c677b9bSLee Jones /* The AB8500 GPIOs have two interrupts each (rising & falling). */ 4149c677b9bSLee Jones if (type & IRQ_TYPE_EDGE_FALLING) { 4159c677b9bSLee Jones if (offset >= AB8500_INT_GPIO6R && offset <= AB8500_INT_GPIO41R) 4169c677b9bSLee Jones ab8500->mask[index + 2] &= ~mask; 4179c677b9bSLee Jones else if (offset >= AB9540_INT_GPIO50R && offset <= AB9540_INT_GPIO54R) 4189c677b9bSLee Jones ab8500->mask[index + 1] &= ~mask; 4199c677b9bSLee Jones else if (offset == AB8540_INT_GPIO43R || offset == AB8540_INT_GPIO44R) 420e2ddf46aSLinus Walleij /* Here the falling IRQ is one bit lower */ 421e2ddf46aSLinus Walleij ab8500->mask[index] &= ~(mask << 1); 4229c677b9bSLee Jones else 4239c677b9bSLee Jones ab8500->mask[index] &= ~mask; 424e2ddf46aSLinus Walleij } else { 4259c677b9bSLee Jones /* Satisfies the case where type is not set. */ 42662579266SRabin Vincent ab8500->mask[index] &= ~mask; 42762579266SRabin Vincent } 428e2ddf46aSLinus Walleij } 42962579266SRabin Vincent 43040f6e5a2SLee Jones static int ab8500_irq_set_type(struct irq_data *data, unsigned int type) 43140f6e5a2SLee Jones { 43240f6e5a2SLee Jones return 0; 43362579266SRabin Vincent } 43462579266SRabin Vincent 43562579266SRabin Vincent static struct irq_chip ab8500_irq_chip = { 43662579266SRabin Vincent .name = "ab8500", 4379505a0a0SMark Brown .irq_bus_lock = ab8500_irq_lock, 4389505a0a0SMark Brown .irq_bus_sync_unlock = ab8500_irq_sync_unlock, 4399505a0a0SMark Brown .irq_mask = ab8500_irq_mask, 440e6f9306eSVirupax Sadashivpetimath .irq_disable = ab8500_irq_mask, 4419505a0a0SMark Brown .irq_unmask = ab8500_irq_unmask, 44240f6e5a2SLee Jones .irq_set_type = ab8500_irq_set_type, 44362579266SRabin Vincent }; 44462579266SRabin Vincent 445*3e1a498fSLee Jones static void update_latch_offset(u8 *offset, int i) 446*3e1a498fSLee Jones { 447*3e1a498fSLee Jones /* Fix inconsistent ITFromLatch25 bit mapping... */ 448*3e1a498fSLee Jones if (unlikely(*offset == 17)) 449*3e1a498fSLee Jones *offset = 24; 450*3e1a498fSLee Jones /* Fix inconsistent ab8540 bit mapping... */ 451*3e1a498fSLee Jones if (unlikely(*offset == 16)) 452*3e1a498fSLee Jones *offset = 25; 453*3e1a498fSLee Jones if ((i==3) && (*offset >= 24)) 454*3e1a498fSLee Jones *offset += 2; 455*3e1a498fSLee Jones } 456*3e1a498fSLee Jones 4577ccfe9b1SMichel JAOUEN static int ab8500_handle_hierarchical_line(struct ab8500 *ab8500, 4587ccfe9b1SMichel JAOUEN int latch_offset, u8 latch_val) 4597ccfe9b1SMichel JAOUEN { 4607ccfe9b1SMichel JAOUEN int int_bit = __ffs(latch_val); 4617ccfe9b1SMichel JAOUEN int line, i; 4627ccfe9b1SMichel JAOUEN 4637ccfe9b1SMichel JAOUEN do { 4647ccfe9b1SMichel JAOUEN int_bit = __ffs(latch_val); 4657ccfe9b1SMichel JAOUEN 4667ccfe9b1SMichel JAOUEN for (i = 0; i < ab8500->mask_size; i++) 4677ccfe9b1SMichel JAOUEN if (ab8500->irq_reg_offset[i] == latch_offset) 4687ccfe9b1SMichel JAOUEN break; 4697ccfe9b1SMichel JAOUEN 4707ccfe9b1SMichel JAOUEN if (i >= ab8500->mask_size) { 4717ccfe9b1SMichel JAOUEN dev_err(ab8500->dev, "Register offset 0x%2x not declared\n", 4727ccfe9b1SMichel JAOUEN latch_offset); 4737ccfe9b1SMichel JAOUEN return -ENXIO; 4747ccfe9b1SMichel JAOUEN } 4757ccfe9b1SMichel JAOUEN 4767ccfe9b1SMichel JAOUEN line = (i << 3) + int_bit; 4777ccfe9b1SMichel JAOUEN latch_val &= ~(1 << int_bit); 4787ccfe9b1SMichel JAOUEN 479e2ddf46aSLinus Walleij /* 480e2ddf46aSLinus Walleij * This handles the falling edge hwirqs from the GPIO 481e2ddf46aSLinus Walleij * lines. Route them back to the line registered for the 482e2ddf46aSLinus Walleij * rising IRQ, as this is merely a flag for the same IRQ 483e2ddf46aSLinus Walleij * in linux terms. 484e2ddf46aSLinus Walleij */ 485e2ddf46aSLinus Walleij if (line >= AB8500_INT_GPIO6F && line <= AB8500_INT_GPIO41F) 486e2ddf46aSLinus Walleij line -= 16; 487e2ddf46aSLinus Walleij if (line >= AB9540_INT_GPIO50F && line <= AB9540_INT_GPIO54F) 488e2ddf46aSLinus Walleij line -= 8; 489e2ddf46aSLinus Walleij if (line == AB8540_INT_GPIO43F || line == AB8540_INT_GPIO44F) 490e2ddf46aSLinus Walleij line += 1; 491e2ddf46aSLinus Walleij 4927ccfe9b1SMichel JAOUEN handle_nested_irq(ab8500->irq_base + line); 4937ccfe9b1SMichel JAOUEN } while (latch_val); 4947ccfe9b1SMichel JAOUEN 4957ccfe9b1SMichel JAOUEN return 0; 4967ccfe9b1SMichel JAOUEN } 4977ccfe9b1SMichel JAOUEN 4987ccfe9b1SMichel JAOUEN static int ab8500_handle_hierarchical_latch(struct ab8500 *ab8500, 4997ccfe9b1SMichel JAOUEN int hier_offset, u8 hier_val) 5007ccfe9b1SMichel JAOUEN { 5017ccfe9b1SMichel JAOUEN int latch_bit, status; 5027ccfe9b1SMichel JAOUEN u8 latch_offset, latch_val; 5037ccfe9b1SMichel JAOUEN 5047ccfe9b1SMichel JAOUEN do { 5057ccfe9b1SMichel JAOUEN latch_bit = __ffs(hier_val); 5067ccfe9b1SMichel JAOUEN latch_offset = (hier_offset << 3) + latch_bit; 5077ccfe9b1SMichel JAOUEN 508*3e1a498fSLee Jones update_latch_offset(&latch_offset, hier_offset); 5097ccfe9b1SMichel JAOUEN 5107ccfe9b1SMichel JAOUEN status = get_register_interruptible(ab8500, 5117ccfe9b1SMichel JAOUEN AB8500_INTERRUPT, 5127ccfe9b1SMichel JAOUEN AB8500_IT_LATCH1_REG + latch_offset, 5137ccfe9b1SMichel JAOUEN &latch_val); 5147ccfe9b1SMichel JAOUEN if (status < 0 || latch_val == 0) 5157ccfe9b1SMichel JAOUEN goto discard; 5167ccfe9b1SMichel JAOUEN 5177ccfe9b1SMichel JAOUEN status = ab8500_handle_hierarchical_line(ab8500, 5187ccfe9b1SMichel JAOUEN latch_offset, latch_val); 5197ccfe9b1SMichel JAOUEN if (status < 0) 5207ccfe9b1SMichel JAOUEN return status; 5217ccfe9b1SMichel JAOUEN discard: 5227ccfe9b1SMichel JAOUEN hier_val &= ~(1 << latch_bit); 5237ccfe9b1SMichel JAOUEN } while (hier_val); 5247ccfe9b1SMichel JAOUEN 5257ccfe9b1SMichel JAOUEN return 0; 5267ccfe9b1SMichel JAOUEN } 5277ccfe9b1SMichel JAOUEN 5287ccfe9b1SMichel JAOUEN static irqreturn_t ab8500_hierarchical_irq(int irq, void *dev) 5297ccfe9b1SMichel JAOUEN { 5307ccfe9b1SMichel JAOUEN struct ab8500 *ab8500 = dev; 5317ccfe9b1SMichel JAOUEN u8 i; 5327ccfe9b1SMichel JAOUEN 5337ccfe9b1SMichel JAOUEN dev_vdbg(ab8500->dev, "interrupt\n"); 5347ccfe9b1SMichel JAOUEN 5357ccfe9b1SMichel JAOUEN /* Hierarchical interrupt version */ 536*3e1a498fSLee Jones for (i = 0; i < (ab8500->it_latchhier_num); i++) { 5377ccfe9b1SMichel JAOUEN int status; 5387ccfe9b1SMichel JAOUEN u8 hier_val; 5397ccfe9b1SMichel JAOUEN 5407ccfe9b1SMichel JAOUEN status = get_register_interruptible(ab8500, AB8500_INTERRUPT, 5417ccfe9b1SMichel JAOUEN AB8500_IT_LATCHHIER1_REG + i, &hier_val); 5427ccfe9b1SMichel JAOUEN if (status < 0 || hier_val == 0) 5437ccfe9b1SMichel JAOUEN continue; 5447ccfe9b1SMichel JAOUEN 5457ccfe9b1SMichel JAOUEN status = ab8500_handle_hierarchical_latch(ab8500, i, hier_val); 5467ccfe9b1SMichel JAOUEN if (status < 0) 5477ccfe9b1SMichel JAOUEN break; 5487ccfe9b1SMichel JAOUEN } 5497ccfe9b1SMichel JAOUEN return IRQ_HANDLED; 5507ccfe9b1SMichel JAOUEN } 5517ccfe9b1SMichel JAOUEN 55280633f05SLee Jones /** 55380633f05SLee Jones * ab8500_irq_get_virq(): Map an interrupt on a chip to a virtual IRQ 55480633f05SLee Jones * 55580633f05SLee Jones * @ab8500: ab8500_irq controller to operate on. 55680633f05SLee Jones * @irq: index of the interrupt requested in the chip IRQs 55780633f05SLee Jones * 55880633f05SLee Jones * Useful for drivers to request their own IRQs. 55980633f05SLee Jones */ 56080633f05SLee Jones static int ab8500_irq_get_virq(struct ab8500 *ab8500, int irq) 56180633f05SLee Jones { 56280633f05SLee Jones if (!ab8500) 56380633f05SLee Jones return -EINVAL; 56480633f05SLee Jones 56580633f05SLee Jones return irq_create_mapping(ab8500->domain, irq); 56680633f05SLee Jones } 56780633f05SLee Jones 56862579266SRabin Vincent static irqreturn_t ab8500_irq(int irq, void *dev) 56962579266SRabin Vincent { 57062579266SRabin Vincent struct ab8500 *ab8500 = dev; 57162579266SRabin Vincent int i; 57262579266SRabin Vincent 57362579266SRabin Vincent dev_vdbg(ab8500->dev, "interrupt\n"); 57462579266SRabin Vincent 575112a80d2SJonas Aaberg atomic_inc(&ab8500->transfer_ongoing); 576112a80d2SJonas Aaberg 5772ced445eSLinus Walleij for (i = 0; i < ab8500->mask_size; i++) { 5782ced445eSLinus Walleij int regoffset = ab8500->irq_reg_offset[i]; 57962579266SRabin Vincent int status; 58047c16975SMattias Wallin u8 value; 58162579266SRabin Vincent 5820f620837SLinus Walleij /* 5830f620837SLinus Walleij * Interrupt register 12 doesn't exist prior to AB8500 version 5840f620837SLinus Walleij * 2.0 5850f620837SLinus Walleij */ 5860f620837SLinus Walleij if (regoffset == 11 && is_ab8500_1p1_or_earlier(ab8500)) 58792d50a41SMattias Wallin continue; 58892d50a41SMattias Wallin 589*3e1a498fSLee Jones if (regoffset < 0) 590*3e1a498fSLee Jones continue; 591*3e1a498fSLee Jones 59247c16975SMattias Wallin status = get_register_interruptible(ab8500, AB8500_INTERRUPT, 59347c16975SMattias Wallin AB8500_IT_LATCH1_REG + regoffset, &value); 59447c16975SMattias Wallin if (status < 0 || value == 0) 59562579266SRabin Vincent continue; 59662579266SRabin Vincent 59762579266SRabin Vincent do { 59888aec4f7SMattias Wallin int bit = __ffs(value); 59962579266SRabin Vincent int line = i * 8 + bit; 6000a37fc56SLee Jones int virq = ab8500_irq_get_virq(ab8500, line); 60162579266SRabin Vincent 6020a37fc56SLee Jones handle_nested_irq(virq); 6038f0eb43bSBengt Jonsson ab8500_debug_register_interrupt(line); 60447c16975SMattias Wallin value &= ~(1 << bit); 605112a80d2SJonas Aaberg 60647c16975SMattias Wallin } while (value); 60762579266SRabin Vincent } 608112a80d2SJonas Aaberg atomic_dec(&ab8500->transfer_ongoing); 60962579266SRabin Vincent return IRQ_HANDLED; 61062579266SRabin Vincent } 61162579266SRabin Vincent 61206e589efSLee Jones static int ab8500_irq_map(struct irq_domain *d, unsigned int virq, 61306e589efSLee Jones irq_hw_number_t hwirq) 61406e589efSLee Jones { 61506e589efSLee Jones struct ab8500 *ab8500 = d->host_data; 61606e589efSLee Jones 61706e589efSLee Jones if (!ab8500) 61806e589efSLee Jones return -EINVAL; 61906e589efSLee Jones 62006e589efSLee Jones irq_set_chip_data(virq, ab8500); 62106e589efSLee Jones irq_set_chip_and_handler(virq, &ab8500_irq_chip, 62206e589efSLee Jones handle_simple_irq); 62306e589efSLee Jones irq_set_nested_thread(virq, 1); 62406e589efSLee Jones #ifdef CONFIG_ARM 62506e589efSLee Jones set_irq_flags(virq, IRQF_VALID); 62606e589efSLee Jones #else 62706e589efSLee Jones irq_set_noprobe(virq); 62806e589efSLee Jones #endif 62962579266SRabin Vincent 63062579266SRabin Vincent return 0; 63162579266SRabin Vincent } 63262579266SRabin Vincent 63306e589efSLee Jones static struct irq_domain_ops ab8500_irq_ops = { 63406e589efSLee Jones .map = ab8500_irq_map, 63506e589efSLee Jones .xlate = irq_domain_xlate_twocell, 63606e589efSLee Jones }; 63706e589efSLee Jones 63806e589efSLee Jones static int ab8500_irq_init(struct ab8500 *ab8500, struct device_node *np) 63962579266SRabin Vincent { 6402ced445eSLinus Walleij int num_irqs; 64162579266SRabin Vincent 642*3e1a498fSLee Jones if (is_ab8540(ab8500)) 643*3e1a498fSLee Jones num_irqs = AB8540_NR_IRQS; 644*3e1a498fSLee Jones else if (is_ab9540(ab8500)) 645d6255529SLinus Walleij num_irqs = AB9540_NR_IRQS; 646a982362cSBengt Jonsson else if (is_ab8505(ab8500)) 647a982362cSBengt Jonsson num_irqs = AB8505_NR_IRQS; 648d6255529SLinus Walleij else 6492ced445eSLinus Walleij num_irqs = AB8500_NR_IRQS; 6502ced445eSLinus Walleij 651f1d11f39SLinus Walleij /* If ->irq_base is zero this will give a linear mapping */ 652f1d11f39SLinus Walleij ab8500->domain = irq_domain_add_simple(NULL, 653f1d11f39SLinus Walleij num_irqs, ab8500->irq_base, 654f1d11f39SLinus Walleij &ab8500_irq_ops, ab8500); 65506e589efSLee Jones 65606e589efSLee Jones if (!ab8500->domain) { 65706e589efSLee Jones dev_err(ab8500->dev, "Failed to create irqdomain\n"); 65806e589efSLee Jones return -ENOSYS; 65906e589efSLee Jones } 66006e589efSLee Jones 66106e589efSLee Jones return 0; 66262579266SRabin Vincent } 66362579266SRabin Vincent 664112a80d2SJonas Aaberg int ab8500_suspend(struct ab8500 *ab8500) 665112a80d2SJonas Aaberg { 666112a80d2SJonas Aaberg if (atomic_read(&ab8500->transfer_ongoing)) 667112a80d2SJonas Aaberg return -EINVAL; 668112a80d2SJonas Aaberg else 669112a80d2SJonas Aaberg return 0; 670112a80d2SJonas Aaberg } 671112a80d2SJonas Aaberg 672a9e9ce4cSBill Pemberton static struct resource ab8500_gpadc_resources[] = { 67362579266SRabin Vincent { 67462579266SRabin Vincent .name = "HW_CONV_END", 67562579266SRabin Vincent .start = AB8500_INT_GP_HW_ADC_CONV_END, 67662579266SRabin Vincent .end = AB8500_INT_GP_HW_ADC_CONV_END, 67762579266SRabin Vincent .flags = IORESOURCE_IRQ, 67862579266SRabin Vincent }, 67962579266SRabin Vincent { 68062579266SRabin Vincent .name = "SW_CONV_END", 68162579266SRabin Vincent .start = AB8500_INT_GP_SW_ADC_CONV_END, 68262579266SRabin Vincent .end = AB8500_INT_GP_SW_ADC_CONV_END, 68362579266SRabin Vincent .flags = IORESOURCE_IRQ, 68462579266SRabin Vincent }, 68562579266SRabin Vincent }; 68662579266SRabin Vincent 6874b106fb9SLee Jones static struct resource ab8505_gpadc_resources[] = { 688c0eda9aeSLee Jones { 689c0eda9aeSLee Jones .name = "SW_CONV_END", 690c0eda9aeSLee Jones .start = AB8500_INT_GP_SW_ADC_CONV_END, 691c0eda9aeSLee Jones .end = AB8500_INT_GP_SW_ADC_CONV_END, 692c0eda9aeSLee Jones .flags = IORESOURCE_IRQ, 693c0eda9aeSLee Jones }, 694c0eda9aeSLee Jones }; 695c0eda9aeSLee Jones 696a9e9ce4cSBill Pemberton static struct resource ab8500_rtc_resources[] = { 69762579266SRabin Vincent { 69862579266SRabin Vincent .name = "60S", 69962579266SRabin Vincent .start = AB8500_INT_RTC_60S, 70062579266SRabin Vincent .end = AB8500_INT_RTC_60S, 70162579266SRabin Vincent .flags = IORESOURCE_IRQ, 70262579266SRabin Vincent }, 70362579266SRabin Vincent { 70462579266SRabin Vincent .name = "ALARM", 70562579266SRabin Vincent .start = AB8500_INT_RTC_ALARM, 70662579266SRabin Vincent .end = AB8500_INT_RTC_ALARM, 70762579266SRabin Vincent .flags = IORESOURCE_IRQ, 70862579266SRabin Vincent }, 70962579266SRabin Vincent }; 71062579266SRabin Vincent 711a9e9ce4cSBill Pemberton static struct resource ab8500_poweronkey_db_resources[] = { 71277686517SSundar R Iyer { 71377686517SSundar R Iyer .name = "ONKEY_DBF", 71477686517SSundar R Iyer .start = AB8500_INT_PON_KEY1DB_F, 71577686517SSundar R Iyer .end = AB8500_INT_PON_KEY1DB_F, 71677686517SSundar R Iyer .flags = IORESOURCE_IRQ, 71777686517SSundar R Iyer }, 71877686517SSundar R Iyer { 71977686517SSundar R Iyer .name = "ONKEY_DBR", 72077686517SSundar R Iyer .start = AB8500_INT_PON_KEY1DB_R, 72177686517SSundar R Iyer .end = AB8500_INT_PON_KEY1DB_R, 72277686517SSundar R Iyer .flags = IORESOURCE_IRQ, 72377686517SSundar R Iyer }, 72477686517SSundar R Iyer }; 72577686517SSundar R Iyer 726a9e9ce4cSBill Pemberton static struct resource ab8500_av_acc_detect_resources[] = { 727e098adedSMattias Wallin { 7286af75ecdSLinus Walleij .name = "ACC_DETECT_1DB_F", 7296af75ecdSLinus Walleij .start = AB8500_INT_ACC_DETECT_1DB_F, 7306af75ecdSLinus Walleij .end = AB8500_INT_ACC_DETECT_1DB_F, 731e098adedSMattias Wallin .flags = IORESOURCE_IRQ, 732e098adedSMattias Wallin }, 733e098adedSMattias Wallin { 7346af75ecdSLinus Walleij .name = "ACC_DETECT_1DB_R", 7356af75ecdSLinus Walleij .start = AB8500_INT_ACC_DETECT_1DB_R, 7366af75ecdSLinus Walleij .end = AB8500_INT_ACC_DETECT_1DB_R, 737e098adedSMattias Wallin .flags = IORESOURCE_IRQ, 738e098adedSMattias Wallin }, 739e098adedSMattias Wallin { 7406af75ecdSLinus Walleij .name = "ACC_DETECT_21DB_F", 7416af75ecdSLinus Walleij .start = AB8500_INT_ACC_DETECT_21DB_F, 7426af75ecdSLinus Walleij .end = AB8500_INT_ACC_DETECT_21DB_F, 7436af75ecdSLinus Walleij .flags = IORESOURCE_IRQ, 7446af75ecdSLinus Walleij }, 7456af75ecdSLinus Walleij { 7466af75ecdSLinus Walleij .name = "ACC_DETECT_21DB_R", 7476af75ecdSLinus Walleij .start = AB8500_INT_ACC_DETECT_21DB_R, 7486af75ecdSLinus Walleij .end = AB8500_INT_ACC_DETECT_21DB_R, 7496af75ecdSLinus Walleij .flags = IORESOURCE_IRQ, 7506af75ecdSLinus Walleij }, 7516af75ecdSLinus Walleij { 7526af75ecdSLinus Walleij .name = "ACC_DETECT_22DB_F", 7536af75ecdSLinus Walleij .start = AB8500_INT_ACC_DETECT_22DB_F, 7546af75ecdSLinus Walleij .end = AB8500_INT_ACC_DETECT_22DB_F, 7556af75ecdSLinus Walleij .flags = IORESOURCE_IRQ, 7566af75ecdSLinus Walleij }, 7576af75ecdSLinus Walleij { 7586af75ecdSLinus Walleij .name = "ACC_DETECT_22DB_R", 7596af75ecdSLinus Walleij .start = AB8500_INT_ACC_DETECT_22DB_R, 7606af75ecdSLinus Walleij .end = AB8500_INT_ACC_DETECT_22DB_R, 7616af75ecdSLinus Walleij .flags = IORESOURCE_IRQ, 7626af75ecdSLinus Walleij }, 7636af75ecdSLinus Walleij }; 7646af75ecdSLinus Walleij 765a9e9ce4cSBill Pemberton static struct resource ab8500_charger_resources[] = { 7666af75ecdSLinus Walleij { 767e098adedSMattias Wallin .name = "MAIN_CH_UNPLUG_DET", 768e098adedSMattias Wallin .start = AB8500_INT_MAIN_CH_UNPLUG_DET, 769e098adedSMattias Wallin .end = AB8500_INT_MAIN_CH_UNPLUG_DET, 770e098adedSMattias Wallin .flags = IORESOURCE_IRQ, 771e098adedSMattias Wallin }, 772e098adedSMattias Wallin { 773e098adedSMattias Wallin .name = "MAIN_CHARGE_PLUG_DET", 774e098adedSMattias Wallin .start = AB8500_INT_MAIN_CH_PLUG_DET, 775e098adedSMattias Wallin .end = AB8500_INT_MAIN_CH_PLUG_DET, 776e098adedSMattias Wallin .flags = IORESOURCE_IRQ, 777e098adedSMattias Wallin }, 778e098adedSMattias Wallin { 779e098adedSMattias Wallin .name = "VBUS_DET_R", 780e098adedSMattias Wallin .start = AB8500_INT_VBUS_DET_R, 781e098adedSMattias Wallin .end = AB8500_INT_VBUS_DET_R, 782e098adedSMattias Wallin .flags = IORESOURCE_IRQ, 783e098adedSMattias Wallin }, 784e098adedSMattias Wallin { 7856af75ecdSLinus Walleij .name = "VBUS_DET_F", 7866af75ecdSLinus Walleij .start = AB8500_INT_VBUS_DET_F, 7876af75ecdSLinus Walleij .end = AB8500_INT_VBUS_DET_F, 788e098adedSMattias Wallin .flags = IORESOURCE_IRQ, 789e098adedSMattias Wallin }, 790e098adedSMattias Wallin { 7916af75ecdSLinus Walleij .name = "USB_LINK_STATUS", 7926af75ecdSLinus Walleij .start = AB8500_INT_USB_LINK_STATUS, 7936af75ecdSLinus Walleij .end = AB8500_INT_USB_LINK_STATUS, 7946af75ecdSLinus Walleij .flags = IORESOURCE_IRQ, 7956af75ecdSLinus Walleij }, 7966af75ecdSLinus Walleij { 797e098adedSMattias Wallin .name = "VBUS_OVV", 798e098adedSMattias Wallin .start = AB8500_INT_VBUS_OVV, 799e098adedSMattias Wallin .end = AB8500_INT_VBUS_OVV, 800e098adedSMattias Wallin .flags = IORESOURCE_IRQ, 801e098adedSMattias Wallin }, 802e098adedSMattias Wallin { 8036af75ecdSLinus Walleij .name = "USB_CH_TH_PROT_R", 8046af75ecdSLinus Walleij .start = AB8500_INT_USB_CH_TH_PROT_R, 8056af75ecdSLinus Walleij .end = AB8500_INT_USB_CH_TH_PROT_R, 806e098adedSMattias Wallin .flags = IORESOURCE_IRQ, 807e098adedSMattias Wallin }, 808e098adedSMattias Wallin { 8096af75ecdSLinus Walleij .name = "USB_CH_TH_PROT_F", 8106af75ecdSLinus Walleij .start = AB8500_INT_USB_CH_TH_PROT_F, 8116af75ecdSLinus Walleij .end = AB8500_INT_USB_CH_TH_PROT_F, 812e098adedSMattias Wallin .flags = IORESOURCE_IRQ, 813e098adedSMattias Wallin }, 814e098adedSMattias Wallin { 8156af75ecdSLinus Walleij .name = "MAIN_EXT_CH_NOT_OK", 8166af75ecdSLinus Walleij .start = AB8500_INT_MAIN_EXT_CH_NOT_OK, 8176af75ecdSLinus Walleij .end = AB8500_INT_MAIN_EXT_CH_NOT_OK, 8186af75ecdSLinus Walleij .flags = IORESOURCE_IRQ, 8196af75ecdSLinus Walleij }, 8206af75ecdSLinus Walleij { 8216af75ecdSLinus Walleij .name = "MAIN_CH_TH_PROT_R", 8226af75ecdSLinus Walleij .start = AB8500_INT_MAIN_CH_TH_PROT_R, 8236af75ecdSLinus Walleij .end = AB8500_INT_MAIN_CH_TH_PROT_R, 8246af75ecdSLinus Walleij .flags = IORESOURCE_IRQ, 8256af75ecdSLinus Walleij }, 8266af75ecdSLinus Walleij { 8276af75ecdSLinus Walleij .name = "MAIN_CH_TH_PROT_F", 8286af75ecdSLinus Walleij .start = AB8500_INT_MAIN_CH_TH_PROT_F, 8296af75ecdSLinus Walleij .end = AB8500_INT_MAIN_CH_TH_PROT_F, 8306af75ecdSLinus Walleij .flags = IORESOURCE_IRQ, 8316af75ecdSLinus Walleij }, 8326af75ecdSLinus Walleij { 8336af75ecdSLinus Walleij .name = "USB_CHARGER_NOT_OKR", 834a982362cSBengt Jonsson .start = AB8500_INT_USB_CHARGER_NOT_OKR, 835a982362cSBengt Jonsson .end = AB8500_INT_USB_CHARGER_NOT_OKR, 8366af75ecdSLinus Walleij .flags = IORESOURCE_IRQ, 8376af75ecdSLinus Walleij }, 8386af75ecdSLinus Walleij { 8396af75ecdSLinus Walleij .name = "CH_WD_EXP", 8406af75ecdSLinus Walleij .start = AB8500_INT_CH_WD_EXP, 8416af75ecdSLinus Walleij .end = AB8500_INT_CH_WD_EXP, 8426af75ecdSLinus Walleij .flags = IORESOURCE_IRQ, 8436af75ecdSLinus Walleij }, 84434c11a70SPaer-Olof Haakansson { 84534c11a70SPaer-Olof Haakansson .name = "VBUS_CH_DROP_END", 84634c11a70SPaer-Olof Haakansson .start = AB8500_INT_VBUS_CH_DROP_END, 84734c11a70SPaer-Olof Haakansson .end = AB8500_INT_VBUS_CH_DROP_END, 84834c11a70SPaer-Olof Haakansson .flags = IORESOURCE_IRQ, 84934c11a70SPaer-Olof Haakansson }, 8506af75ecdSLinus Walleij }; 8516af75ecdSLinus Walleij 852a9e9ce4cSBill Pemberton static struct resource ab8500_btemp_resources[] = { 8536af75ecdSLinus Walleij { 8546af75ecdSLinus Walleij .name = "BAT_CTRL_INDB", 8556af75ecdSLinus Walleij .start = AB8500_INT_BAT_CTRL_INDB, 8566af75ecdSLinus Walleij .end = AB8500_INT_BAT_CTRL_INDB, 857e098adedSMattias Wallin .flags = IORESOURCE_IRQ, 858e098adedSMattias Wallin }, 859e098adedSMattias Wallin { 860e098adedSMattias Wallin .name = "BTEMP_LOW", 861e098adedSMattias Wallin .start = AB8500_INT_BTEMP_LOW, 862e098adedSMattias Wallin .end = AB8500_INT_BTEMP_LOW, 863e098adedSMattias Wallin .flags = IORESOURCE_IRQ, 864e098adedSMattias Wallin }, 865e098adedSMattias Wallin { 866e098adedSMattias Wallin .name = "BTEMP_HIGH", 867e098adedSMattias Wallin .start = AB8500_INT_BTEMP_HIGH, 868e098adedSMattias Wallin .end = AB8500_INT_BTEMP_HIGH, 869e098adedSMattias Wallin .flags = IORESOURCE_IRQ, 870e098adedSMattias Wallin }, 871e098adedSMattias Wallin { 8726af75ecdSLinus Walleij .name = "BTEMP_LOW_MEDIUM", 8736af75ecdSLinus Walleij .start = AB8500_INT_BTEMP_LOW_MEDIUM, 8746af75ecdSLinus Walleij .end = AB8500_INT_BTEMP_LOW_MEDIUM, 875e098adedSMattias Wallin .flags = IORESOURCE_IRQ, 876e098adedSMattias Wallin }, 877e098adedSMattias Wallin { 8786af75ecdSLinus Walleij .name = "BTEMP_MEDIUM_HIGH", 8796af75ecdSLinus Walleij .start = AB8500_INT_BTEMP_MEDIUM_HIGH, 8806af75ecdSLinus Walleij .end = AB8500_INT_BTEMP_MEDIUM_HIGH, 881e098adedSMattias Wallin .flags = IORESOURCE_IRQ, 882e098adedSMattias Wallin }, 883e098adedSMattias Wallin }; 884e098adedSMattias Wallin 885a9e9ce4cSBill Pemberton static struct resource ab8500_fg_resources[] = { 8866af75ecdSLinus Walleij { 8876af75ecdSLinus Walleij .name = "NCONV_ACCU", 8886af75ecdSLinus Walleij .start = AB8500_INT_CCN_CONV_ACC, 8896af75ecdSLinus Walleij .end = AB8500_INT_CCN_CONV_ACC, 8906af75ecdSLinus Walleij .flags = IORESOURCE_IRQ, 8916af75ecdSLinus Walleij }, 8926af75ecdSLinus Walleij { 8936af75ecdSLinus Walleij .name = "BATT_OVV", 8946af75ecdSLinus Walleij .start = AB8500_INT_BATT_OVV, 8956af75ecdSLinus Walleij .end = AB8500_INT_BATT_OVV, 8966af75ecdSLinus Walleij .flags = IORESOURCE_IRQ, 8976af75ecdSLinus Walleij }, 8986af75ecdSLinus Walleij { 8996af75ecdSLinus Walleij .name = "LOW_BAT_F", 9006af75ecdSLinus Walleij .start = AB8500_INT_LOW_BAT_F, 9016af75ecdSLinus Walleij .end = AB8500_INT_LOW_BAT_F, 9026af75ecdSLinus Walleij .flags = IORESOURCE_IRQ, 9036af75ecdSLinus Walleij }, 9046af75ecdSLinus Walleij { 9056af75ecdSLinus Walleij .name = "LOW_BAT_R", 9066af75ecdSLinus Walleij .start = AB8500_INT_LOW_BAT_R, 9076af75ecdSLinus Walleij .end = AB8500_INT_LOW_BAT_R, 9086af75ecdSLinus Walleij .flags = IORESOURCE_IRQ, 9096af75ecdSLinus Walleij }, 9106af75ecdSLinus Walleij { 9116af75ecdSLinus Walleij .name = "CC_INT_CALIB", 9126af75ecdSLinus Walleij .start = AB8500_INT_CC_INT_CALIB, 9136af75ecdSLinus Walleij .end = AB8500_INT_CC_INT_CALIB, 9146af75ecdSLinus Walleij .flags = IORESOURCE_IRQ, 9156af75ecdSLinus Walleij }, 916a982362cSBengt Jonsson { 917a982362cSBengt Jonsson .name = "CCEOC", 918a982362cSBengt Jonsson .start = AB8500_INT_CCEOC, 919a982362cSBengt Jonsson .end = AB8500_INT_CCEOC, 920a982362cSBengt Jonsson .flags = IORESOURCE_IRQ, 921a982362cSBengt Jonsson }, 9226af75ecdSLinus Walleij }; 9236af75ecdSLinus Walleij 924a9e9ce4cSBill Pemberton static struct resource ab8500_chargalg_resources[] = {}; 9256af75ecdSLinus Walleij 926df720647SAxel Lin #ifdef CONFIG_DEBUG_FS 927a9e9ce4cSBill Pemberton static struct resource ab8500_debug_resources[] = { 928e098adedSMattias Wallin { 929e098adedSMattias Wallin .name = "IRQ_FIRST", 930e098adedSMattias Wallin .start = AB8500_INT_MAIN_EXT_CH_NOT_OK, 931e098adedSMattias Wallin .end = AB8500_INT_MAIN_EXT_CH_NOT_OK, 932e098adedSMattias Wallin .flags = IORESOURCE_IRQ, 933e098adedSMattias Wallin }, 934e098adedSMattias Wallin { 935e098adedSMattias Wallin .name = "IRQ_LAST", 936a982362cSBengt Jonsson .start = AB8500_INT_XTAL32K_KO, 937a982362cSBengt Jonsson .end = AB8500_INT_XTAL32K_KO, 938e098adedSMattias Wallin .flags = IORESOURCE_IRQ, 939e098adedSMattias Wallin }, 940e098adedSMattias Wallin }; 941df720647SAxel Lin #endif 942e098adedSMattias Wallin 943a9e9ce4cSBill Pemberton static struct resource ab8500_usb_resources[] = { 944e098adedSMattias Wallin { 945e098adedSMattias Wallin .name = "ID_WAKEUP_R", 946e098adedSMattias Wallin .start = AB8500_INT_ID_WAKEUP_R, 947e098adedSMattias Wallin .end = AB8500_INT_ID_WAKEUP_R, 948e098adedSMattias Wallin .flags = IORESOURCE_IRQ, 949e098adedSMattias Wallin }, 950e098adedSMattias Wallin { 951e098adedSMattias Wallin .name = "ID_WAKEUP_F", 952e098adedSMattias Wallin .start = AB8500_INT_ID_WAKEUP_F, 953e098adedSMattias Wallin .end = AB8500_INT_ID_WAKEUP_F, 954e098adedSMattias Wallin .flags = IORESOURCE_IRQ, 955e098adedSMattias Wallin }, 956e098adedSMattias Wallin { 957e098adedSMattias Wallin .name = "VBUS_DET_F", 958e098adedSMattias Wallin .start = AB8500_INT_VBUS_DET_F, 959e098adedSMattias Wallin .end = AB8500_INT_VBUS_DET_F, 960e098adedSMattias Wallin .flags = IORESOURCE_IRQ, 961e098adedSMattias Wallin }, 962e098adedSMattias Wallin { 963e098adedSMattias Wallin .name = "VBUS_DET_R", 964e098adedSMattias Wallin .start = AB8500_INT_VBUS_DET_R, 965e098adedSMattias Wallin .end = AB8500_INT_VBUS_DET_R, 966e098adedSMattias Wallin .flags = IORESOURCE_IRQ, 967e098adedSMattias Wallin }, 96892d50a41SMattias Wallin { 96992d50a41SMattias Wallin .name = "USB_LINK_STATUS", 97092d50a41SMattias Wallin .start = AB8500_INT_USB_LINK_STATUS, 97192d50a41SMattias Wallin .end = AB8500_INT_USB_LINK_STATUS, 97292d50a41SMattias Wallin .flags = IORESOURCE_IRQ, 97392d50a41SMattias Wallin }, 9746af75ecdSLinus Walleij { 9756af75ecdSLinus Walleij .name = "USB_ADP_PROBE_PLUG", 9766af75ecdSLinus Walleij .start = AB8500_INT_ADP_PROBE_PLUG, 9776af75ecdSLinus Walleij .end = AB8500_INT_ADP_PROBE_PLUG, 9786af75ecdSLinus Walleij .flags = IORESOURCE_IRQ, 9796af75ecdSLinus Walleij }, 9806af75ecdSLinus Walleij { 9816af75ecdSLinus Walleij .name = "USB_ADP_PROBE_UNPLUG", 9826af75ecdSLinus Walleij .start = AB8500_INT_ADP_PROBE_UNPLUG, 9836af75ecdSLinus Walleij .end = AB8500_INT_ADP_PROBE_UNPLUG, 9846af75ecdSLinus Walleij .flags = IORESOURCE_IRQ, 9856af75ecdSLinus Walleij }, 986e098adedSMattias Wallin }; 987e098adedSMattias Wallin 988a9e9ce4cSBill Pemberton static struct resource ab8505_iddet_resources[] = { 98944f72e53SVirupax Sadashivpetimath { 99044f72e53SVirupax Sadashivpetimath .name = "KeyDeglitch", 99144f72e53SVirupax Sadashivpetimath .start = AB8505_INT_KEYDEGLITCH, 99244f72e53SVirupax Sadashivpetimath .end = AB8505_INT_KEYDEGLITCH, 99344f72e53SVirupax Sadashivpetimath .flags = IORESOURCE_IRQ, 99444f72e53SVirupax Sadashivpetimath }, 99544f72e53SVirupax Sadashivpetimath { 99644f72e53SVirupax Sadashivpetimath .name = "KP", 99744f72e53SVirupax Sadashivpetimath .start = AB8505_INT_KP, 99844f72e53SVirupax Sadashivpetimath .end = AB8505_INT_KP, 99944f72e53SVirupax Sadashivpetimath .flags = IORESOURCE_IRQ, 100044f72e53SVirupax Sadashivpetimath }, 100144f72e53SVirupax Sadashivpetimath { 100244f72e53SVirupax Sadashivpetimath .name = "IKP", 100344f72e53SVirupax Sadashivpetimath .start = AB8505_INT_IKP, 100444f72e53SVirupax Sadashivpetimath .end = AB8505_INT_IKP, 100544f72e53SVirupax Sadashivpetimath .flags = IORESOURCE_IRQ, 100644f72e53SVirupax Sadashivpetimath }, 100744f72e53SVirupax Sadashivpetimath { 100844f72e53SVirupax Sadashivpetimath .name = "IKR", 100944f72e53SVirupax Sadashivpetimath .start = AB8505_INT_IKR, 101044f72e53SVirupax Sadashivpetimath .end = AB8505_INT_IKR, 101144f72e53SVirupax Sadashivpetimath .flags = IORESOURCE_IRQ, 101244f72e53SVirupax Sadashivpetimath }, 101344f72e53SVirupax Sadashivpetimath { 101444f72e53SVirupax Sadashivpetimath .name = "KeyStuck", 101544f72e53SVirupax Sadashivpetimath .start = AB8505_INT_KEYSTUCK, 101644f72e53SVirupax Sadashivpetimath .end = AB8505_INT_KEYSTUCK, 101744f72e53SVirupax Sadashivpetimath .flags = IORESOURCE_IRQ, 101844f72e53SVirupax Sadashivpetimath }, 101944f72e53SVirupax Sadashivpetimath }; 102044f72e53SVirupax Sadashivpetimath 1021a9e9ce4cSBill Pemberton static struct resource ab8500_temp_resources[] = { 1022e098adedSMattias Wallin { 1023151621a7SHongbo Zhang .name = "ABX500_TEMP_WARM", 1024e098adedSMattias Wallin .start = AB8500_INT_TEMP_WARM, 1025e098adedSMattias Wallin .end = AB8500_INT_TEMP_WARM, 1026e098adedSMattias Wallin .flags = IORESOURCE_IRQ, 1027e098adedSMattias Wallin }, 1028e098adedSMattias Wallin }; 1029e098adedSMattias Wallin 1030a9e9ce4cSBill Pemberton static struct mfd_cell ab8500_bm_devs[] = { 10316ef9418cSRickard Andersson { 10326ef9418cSRickard Andersson .name = "ab8500-charger", 10334aef72dbSRajanikanth H.V .of_compatible = "stericsson,ab8500-charger", 10346ef9418cSRickard Andersson .num_resources = ARRAY_SIZE(ab8500_charger_resources), 10356ef9418cSRickard Andersson .resources = ab8500_charger_resources, 10364aef72dbSRajanikanth H.V .platform_data = &ab8500_bm_data, 10374aef72dbSRajanikanth H.V .pdata_size = sizeof(ab8500_bm_data), 10386ef9418cSRickard Andersson }, 10396ef9418cSRickard Andersson { 10406ef9418cSRickard Andersson .name = "ab8500-btemp", 1041bd9e8ab2SRajanikanth H.V .of_compatible = "stericsson,ab8500-btemp", 10426ef9418cSRickard Andersson .num_resources = ARRAY_SIZE(ab8500_btemp_resources), 10436ef9418cSRickard Andersson .resources = ab8500_btemp_resources, 1044bd9e8ab2SRajanikanth H.V .platform_data = &ab8500_bm_data, 1045bd9e8ab2SRajanikanth H.V .pdata_size = sizeof(ab8500_bm_data), 10466ef9418cSRickard Andersson }, 10476ef9418cSRickard Andersson { 10486ef9418cSRickard Andersson .name = "ab8500-fg", 1049e0f1abebSRajanikanth H.V .of_compatible = "stericsson,ab8500-fg", 10506ef9418cSRickard Andersson .num_resources = ARRAY_SIZE(ab8500_fg_resources), 10516ef9418cSRickard Andersson .resources = ab8500_fg_resources, 1052e0f1abebSRajanikanth H.V .platform_data = &ab8500_bm_data, 1053e0f1abebSRajanikanth H.V .pdata_size = sizeof(ab8500_bm_data), 10546ef9418cSRickard Andersson }, 10556ef9418cSRickard Andersson { 10566ef9418cSRickard Andersson .name = "ab8500-chargalg", 1057a12810abSRajanikanth H.V .of_compatible = "stericsson,ab8500-chargalg", 10586ef9418cSRickard Andersson .num_resources = ARRAY_SIZE(ab8500_chargalg_resources), 10596ef9418cSRickard Andersson .resources = ab8500_chargalg_resources, 1060a12810abSRajanikanth H.V .platform_data = &ab8500_bm_data, 1061a12810abSRajanikanth H.V .pdata_size = sizeof(ab8500_bm_data), 10626ef9418cSRickard Andersson }, 10636ef9418cSRickard Andersson }; 10646ef9418cSRickard Andersson 1065a9e9ce4cSBill Pemberton static struct mfd_cell ab8500_devs[] = { 10664b106fb9SLee Jones #ifdef CONFIG_DEBUG_FS 1067d6255529SLinus Walleij { 10684b106fb9SLee Jones .name = "ab8500-debug", 10694b106fb9SLee Jones .of_compatible = "stericsson,ab8500-debug", 10704b106fb9SLee Jones .num_resources = ARRAY_SIZE(ab8500_debug_resources), 10714b106fb9SLee Jones .resources = ab8500_debug_resources, 10724b106fb9SLee Jones }, 10734b106fb9SLee Jones #endif 10744b106fb9SLee Jones { 10754b106fb9SLee Jones .name = "ab8500-sysctrl", 10764b106fb9SLee Jones .of_compatible = "stericsson,ab8500-sysctrl", 10774b106fb9SLee Jones }, 10784b106fb9SLee Jones { 10794b106fb9SLee Jones .name = "ab8500-regulator", 10804b106fb9SLee Jones .of_compatible = "stericsson,ab8500-regulator", 10814b106fb9SLee Jones }, 10824b106fb9SLee Jones { 10834b106fb9SLee Jones .name = "abx500-clk", 10844b106fb9SLee Jones .of_compatible = "stericsson,abx500-clk", 10854b106fb9SLee Jones }, 10864b106fb9SLee Jones { 10874b106fb9SLee Jones .name = "ab8500-gpadc", 10884b106fb9SLee Jones .num_resources = ARRAY_SIZE(ab8500_gpadc_resources), 10894b106fb9SLee Jones .resources = ab8500_gpadc_resources, 10904b106fb9SLee Jones }, 10914b106fb9SLee Jones { 10924b106fb9SLee Jones .name = "ab8500-rtc", 10934b106fb9SLee Jones .of_compatible = "stericsson,ab8500-rtc", 10944b106fb9SLee Jones .num_resources = ARRAY_SIZE(ab8500_rtc_resources), 10954b106fb9SLee Jones .resources = ab8500_rtc_resources, 10964b106fb9SLee Jones }, 10974b106fb9SLee Jones { 10984b106fb9SLee Jones .name = "ab8500-acc-det", 10994b106fb9SLee Jones .of_compatible = "stericsson,ab8500-acc-det", 11004b106fb9SLee Jones .num_resources = ARRAY_SIZE(ab8500_av_acc_detect_resources), 11014b106fb9SLee Jones .resources = ab8500_av_acc_detect_resources, 11024b106fb9SLee Jones }, 11034b106fb9SLee Jones { 11044b106fb9SLee Jones 11054b106fb9SLee Jones .name = "ab8500-poweron-key", 11064b106fb9SLee Jones .of_compatible = "stericsson,ab8500-poweron-key", 11074b106fb9SLee Jones .num_resources = ARRAY_SIZE(ab8500_poweronkey_db_resources), 11084b106fb9SLee Jones .resources = ab8500_poweronkey_db_resources, 11094b106fb9SLee Jones }, 11104b106fb9SLee Jones { 11114b106fb9SLee Jones .name = "ab8500-pwm", 11124b106fb9SLee Jones .of_compatible = "stericsson,ab8500-pwm", 11134b106fb9SLee Jones .id = 1, 11144b106fb9SLee Jones }, 11154b106fb9SLee Jones { 11164b106fb9SLee Jones .name = "ab8500-pwm", 11174b106fb9SLee Jones .of_compatible = "stericsson,ab8500-pwm", 11184b106fb9SLee Jones .id = 2, 11194b106fb9SLee Jones }, 11204b106fb9SLee Jones { 11214b106fb9SLee Jones .name = "ab8500-pwm", 11224b106fb9SLee Jones .of_compatible = "stericsson,ab8500-pwm", 11234b106fb9SLee Jones .id = 3, 11244b106fb9SLee Jones }, 11254b106fb9SLee Jones { 11264b106fb9SLee Jones .name = "ab8500-leds", 11274b106fb9SLee Jones .of_compatible = "stericsson,ab8500-leds", 11284b106fb9SLee Jones }, 11294b106fb9SLee Jones { 11304b106fb9SLee Jones .name = "ab8500-denc", 11314b106fb9SLee Jones .of_compatible = "stericsson,ab8500-denc", 11324b106fb9SLee Jones }, 11334b106fb9SLee Jones { 11344b106fb9SLee Jones .name = "ab8500-gpio", 1135bad76991SLee Jones .of_compatible = "stericsson,ab8500-gpio", 1136d6255529SLinus Walleij }, 1137d6255529SLinus Walleij { 11384b106fb9SLee Jones .name = "abx500-temp", 11394b106fb9SLee Jones .of_compatible = "stericsson,abx500-temp", 11404b106fb9SLee Jones .num_resources = ARRAY_SIZE(ab8500_temp_resources), 11414b106fb9SLee Jones .resources = ab8500_temp_resources, 11424b106fb9SLee Jones }, 11434b106fb9SLee Jones { 1144d6255529SLinus Walleij .name = "ab8500-usb", 1145d6255529SLinus Walleij .num_resources = ARRAY_SIZE(ab8500_usb_resources), 1146d6255529SLinus Walleij .resources = ab8500_usb_resources, 1147d6255529SLinus Walleij }, 114844f72e53SVirupax Sadashivpetimath { 114944f72e53SVirupax Sadashivpetimath .name = "ab8500-codec", 11504b106fb9SLee Jones }, 11514b106fb9SLee Jones }; 11524b106fb9SLee Jones 11534b106fb9SLee Jones static struct mfd_cell ab9540_devs[] = { 11544b106fb9SLee Jones #ifdef CONFIG_DEBUG_FS 11554b106fb9SLee Jones { 11564b106fb9SLee Jones .name = "ab8500-debug", 11574b106fb9SLee Jones .num_resources = ARRAY_SIZE(ab8500_debug_resources), 11584b106fb9SLee Jones .resources = ab8500_debug_resources, 11594b106fb9SLee Jones }, 11604b106fb9SLee Jones #endif 11614b106fb9SLee Jones { 11624b106fb9SLee Jones .name = "ab8500-sysctrl", 11634b106fb9SLee Jones }, 11644b106fb9SLee Jones { 11654b106fb9SLee Jones .name = "ab8500-regulator", 116644f72e53SVirupax Sadashivpetimath }, 1167c0eda9aeSLee Jones { 1168c0eda9aeSLee Jones .name = "ab8500-gpadc", 1169c0eda9aeSLee Jones .of_compatible = "stericsson,ab8500-gpadc", 1170c0eda9aeSLee Jones .num_resources = ARRAY_SIZE(ab8500_gpadc_resources), 1171c0eda9aeSLee Jones .resources = ab8500_gpadc_resources, 1172c0eda9aeSLee Jones }, 11734b106fb9SLee Jones { 11744b106fb9SLee Jones .name = "ab8500-rtc", 11754b106fb9SLee Jones .num_resources = ARRAY_SIZE(ab8500_rtc_resources), 11764b106fb9SLee Jones .resources = ab8500_rtc_resources, 11774b106fb9SLee Jones }, 11784b106fb9SLee Jones { 11794b106fb9SLee Jones .name = "ab8500-acc-det", 11804b106fb9SLee Jones .num_resources = ARRAY_SIZE(ab8500_av_acc_detect_resources), 11814b106fb9SLee Jones .resources = ab8500_av_acc_detect_resources, 11824b106fb9SLee Jones }, 11834b106fb9SLee Jones { 11844b106fb9SLee Jones .name = "ab8500-poweron-key", 11854b106fb9SLee Jones .num_resources = ARRAY_SIZE(ab8500_poweronkey_db_resources), 11864b106fb9SLee Jones .resources = ab8500_poweronkey_db_resources, 11874b106fb9SLee Jones }, 11884b106fb9SLee Jones { 11894b106fb9SLee Jones .name = "ab8500-pwm", 11904b106fb9SLee Jones .id = 1, 11914b106fb9SLee Jones }, 11924b106fb9SLee Jones { 11934b106fb9SLee Jones .name = "ab8500-leds", 11944b106fb9SLee Jones }, 11954b106fb9SLee Jones { 11964b106fb9SLee Jones .name = "abx500-temp", 11974b106fb9SLee Jones .num_resources = ARRAY_SIZE(ab8500_temp_resources), 11984b106fb9SLee Jones .resources = ab8500_temp_resources, 11994b106fb9SLee Jones }, 1200d6255529SLinus Walleij { 1201e64d905eSLee Jones .name = "pinctrl-ab9540", 1202e64d905eSLee Jones .of_compatible = "stericsson,ab9540-gpio", 1203d6255529SLinus Walleij }, 1204d6255529SLinus Walleij { 1205d6255529SLinus Walleij .name = "ab9540-usb", 1206d6255529SLinus Walleij .num_resources = ARRAY_SIZE(ab8500_usb_resources), 1207d6255529SLinus Walleij .resources = ab8500_usb_resources, 1208d6255529SLinus Walleij }, 120944f72e53SVirupax Sadashivpetimath { 121044f72e53SVirupax Sadashivpetimath .name = "ab9540-codec", 121144f72e53SVirupax Sadashivpetimath }, 1212c0eda9aeSLee Jones { 1213c0eda9aeSLee Jones .name = "ab-iddet", 1214c0eda9aeSLee Jones .num_resources = ARRAY_SIZE(ab8505_iddet_resources), 1215c0eda9aeSLee Jones .resources = ab8505_iddet_resources, 1216c0eda9aeSLee Jones }, 121744f72e53SVirupax Sadashivpetimath }; 121844f72e53SVirupax Sadashivpetimath 1219c0eda9aeSLee Jones /* Device list for ab8505 */ 1220c0eda9aeSLee Jones static struct mfd_cell ab8505_devs[] = { 12214b106fb9SLee Jones #ifdef CONFIG_DEBUG_FS 12224b106fb9SLee Jones { 12234b106fb9SLee Jones .name = "ab8500-debug", 12244b106fb9SLee Jones .num_resources = ARRAY_SIZE(ab8500_debug_resources), 12254b106fb9SLee Jones .resources = ab8500_debug_resources, 12264b106fb9SLee Jones }, 12274b106fb9SLee Jones #endif 12284b106fb9SLee Jones { 12294b106fb9SLee Jones .name = "ab8500-sysctrl", 12304b106fb9SLee Jones }, 12314b106fb9SLee Jones { 12324b106fb9SLee Jones .name = "ab8500-regulator", 12334b106fb9SLee Jones }, 12344b106fb9SLee Jones { 12354b106fb9SLee Jones .name = "ab8500-gpadc", 12364b106fb9SLee Jones .num_resources = ARRAY_SIZE(ab8505_gpadc_resources), 12374b106fb9SLee Jones .resources = ab8505_gpadc_resources, 12384b106fb9SLee Jones }, 12394b106fb9SLee Jones { 12404b106fb9SLee Jones .name = "ab8500-rtc", 12414b106fb9SLee Jones .num_resources = ARRAY_SIZE(ab8500_rtc_resources), 12424b106fb9SLee Jones .resources = ab8500_rtc_resources, 12434b106fb9SLee Jones }, 12444b106fb9SLee Jones { 12454b106fb9SLee Jones .name = "ab8500-acc-det", 12464b106fb9SLee Jones .num_resources = ARRAY_SIZE(ab8500_av_acc_detect_resources), 12474b106fb9SLee Jones .resources = ab8500_av_acc_detect_resources, 12484b106fb9SLee Jones }, 12494b106fb9SLee Jones { 12504b106fb9SLee Jones .name = "ab8500-poweron-key", 12514b106fb9SLee Jones .num_resources = ARRAY_SIZE(ab8500_poweronkey_db_resources), 12524b106fb9SLee Jones .resources = ab8500_poweronkey_db_resources, 12534b106fb9SLee Jones }, 12544b106fb9SLee Jones { 12554b106fb9SLee Jones .name = "ab8500-pwm", 12564b106fb9SLee Jones .id = 1, 12574b106fb9SLee Jones }, 12584b106fb9SLee Jones { 12594b106fb9SLee Jones .name = "ab8500-leds", 12604b106fb9SLee Jones }, 12614b106fb9SLee Jones { 12624b106fb9SLee Jones .name = "ab8500-gpio", 12634b106fb9SLee Jones }, 12644b106fb9SLee Jones { 12654b106fb9SLee Jones .name = "ab8500-usb", 12664b106fb9SLee Jones .num_resources = ARRAY_SIZE(ab8500_usb_resources), 12674b106fb9SLee Jones .resources = ab8500_usb_resources, 12684b106fb9SLee Jones }, 12694b106fb9SLee Jones { 12704b106fb9SLee Jones .name = "ab8500-codec", 12714b106fb9SLee Jones }, 1272c0eda9aeSLee Jones { 1273c0eda9aeSLee Jones .name = "ab-iddet", 1274c0eda9aeSLee Jones .num_resources = ARRAY_SIZE(ab8505_iddet_resources), 1275c0eda9aeSLee Jones .resources = ab8505_iddet_resources, 1276c0eda9aeSLee Jones }, 1277c0eda9aeSLee Jones }; 1278c0eda9aeSLee Jones 1279c0eda9aeSLee Jones static struct mfd_cell ab8540_devs[] = { 12804b106fb9SLee Jones #ifdef CONFIG_DEBUG_FS 12814b106fb9SLee Jones { 12824b106fb9SLee Jones .name = "ab8500-debug", 12834b106fb9SLee Jones .num_resources = ARRAY_SIZE(ab8500_debug_resources), 12844b106fb9SLee Jones .resources = ab8500_debug_resources, 12854b106fb9SLee Jones }, 12864b106fb9SLee Jones #endif 12874b106fb9SLee Jones { 12884b106fb9SLee Jones .name = "ab8500-sysctrl", 12894b106fb9SLee Jones }, 12904b106fb9SLee Jones { 12914b106fb9SLee Jones .name = "ab8500-regulator", 12924b106fb9SLee Jones }, 12934b106fb9SLee Jones { 12944b106fb9SLee Jones .name = "ab8500-gpadc", 12954b106fb9SLee Jones .num_resources = ARRAY_SIZE(ab8505_gpadc_resources), 12964b106fb9SLee Jones .resources = ab8505_gpadc_resources, 12974b106fb9SLee Jones }, 12984b106fb9SLee Jones { 12994b106fb9SLee Jones .name = "ab8500-rtc", 13004b106fb9SLee Jones .num_resources = ARRAY_SIZE(ab8500_rtc_resources), 13014b106fb9SLee Jones .resources = ab8500_rtc_resources, 13024b106fb9SLee Jones }, 13034b106fb9SLee Jones { 13044b106fb9SLee Jones .name = "ab8500-acc-det", 13054b106fb9SLee Jones .num_resources = ARRAY_SIZE(ab8500_av_acc_detect_resources), 13064b106fb9SLee Jones .resources = ab8500_av_acc_detect_resources, 13074b106fb9SLee Jones }, 13084b106fb9SLee Jones { 13094b106fb9SLee Jones .name = "ab8500-poweron-key", 13104b106fb9SLee Jones .num_resources = ARRAY_SIZE(ab8500_poweronkey_db_resources), 13114b106fb9SLee Jones .resources = ab8500_poweronkey_db_resources, 13124b106fb9SLee Jones }, 13134b106fb9SLee Jones { 13144b106fb9SLee Jones .name = "ab8500-pwm", 13154b106fb9SLee Jones .id = 1, 13164b106fb9SLee Jones }, 13174b106fb9SLee Jones { 13184b106fb9SLee Jones .name = "ab8500-leds", 13194b106fb9SLee Jones }, 13204b106fb9SLee Jones { 13214b106fb9SLee Jones .name = "abx500-temp", 13224b106fb9SLee Jones .num_resources = ARRAY_SIZE(ab8500_temp_resources), 13234b106fb9SLee Jones .resources = ab8500_temp_resources, 13244b106fb9SLee Jones }, 1325c0eda9aeSLee Jones { 1326c0eda9aeSLee Jones .name = "ab8500-gpio", 1327c0eda9aeSLee Jones }, 1328c0eda9aeSLee Jones { 1329c0eda9aeSLee Jones .name = "ab8540-usb", 1330c0eda9aeSLee Jones .num_resources = ARRAY_SIZE(ab8500_usb_resources), 1331c0eda9aeSLee Jones .resources = ab8500_usb_resources, 1332c0eda9aeSLee Jones }, 1333c0eda9aeSLee Jones { 1334c0eda9aeSLee Jones .name = "ab8540-codec", 1335c0eda9aeSLee Jones }, 1336c0eda9aeSLee Jones { 133744f72e53SVirupax Sadashivpetimath .name = "ab-iddet", 133844f72e53SVirupax Sadashivpetimath .num_resources = ARRAY_SIZE(ab8505_iddet_resources), 133944f72e53SVirupax Sadashivpetimath .resources = ab8505_iddet_resources, 134044f72e53SVirupax Sadashivpetimath }, 1341d6255529SLinus Walleij }; 1342d6255529SLinus Walleij 1343cca69b67SMattias Wallin static ssize_t show_chip_id(struct device *dev, 1344cca69b67SMattias Wallin struct device_attribute *attr, char *buf) 1345cca69b67SMattias Wallin { 1346cca69b67SMattias Wallin struct ab8500 *ab8500; 1347cca69b67SMattias Wallin 1348cca69b67SMattias Wallin ab8500 = dev_get_drvdata(dev); 1349cca69b67SMattias Wallin return sprintf(buf, "%#x\n", ab8500 ? ab8500->chip_id : -EINVAL); 1350cca69b67SMattias Wallin } 1351cca69b67SMattias Wallin 1352e5c238c3SMattias Wallin /* 1353e5c238c3SMattias Wallin * ab8500 has switched off due to (SWITCH_OFF_STATUS): 1354e5c238c3SMattias Wallin * 0x01 Swoff bit programming 1355e5c238c3SMattias Wallin * 0x02 Thermal protection activation 1356e5c238c3SMattias Wallin * 0x04 Vbat lower then BattOk falling threshold 1357e5c238c3SMattias Wallin * 0x08 Watchdog expired 1358e5c238c3SMattias Wallin * 0x10 Non presence of 32kHz clock 1359e5c238c3SMattias Wallin * 0x20 Battery level lower than power on reset threshold 1360e5c238c3SMattias Wallin * 0x40 Power on key 1 pressed longer than 10 seconds 1361e5c238c3SMattias Wallin * 0x80 DB8500 thermal shutdown 1362e5c238c3SMattias Wallin */ 1363e5c238c3SMattias Wallin static ssize_t show_switch_off_status(struct device *dev, 1364e5c238c3SMattias Wallin struct device_attribute *attr, char *buf) 1365e5c238c3SMattias Wallin { 1366e5c238c3SMattias Wallin int ret; 1367e5c238c3SMattias Wallin u8 value; 1368e5c238c3SMattias Wallin struct ab8500 *ab8500; 1369e5c238c3SMattias Wallin 1370e5c238c3SMattias Wallin ab8500 = dev_get_drvdata(dev); 1371e5c238c3SMattias Wallin ret = get_register_interruptible(ab8500, AB8500_RTC, 1372e5c238c3SMattias Wallin AB8500_SWITCH_OFF_STATUS, &value); 1373e5c238c3SMattias Wallin if (ret < 0) 1374e5c238c3SMattias Wallin return ret; 1375e5c238c3SMattias Wallin return sprintf(buf, "%#x\n", value); 1376e5c238c3SMattias Wallin } 1377e5c238c3SMattias Wallin 1378f04a9d8aSRajkumar Kasirajan /* use mask and set to override the register turn_on_stat value */ 1379f04a9d8aSRajkumar Kasirajan void ab8500_override_turn_on_stat(u8 mask, u8 set) 1380f04a9d8aSRajkumar Kasirajan { 1381f04a9d8aSRajkumar Kasirajan spin_lock(&on_stat_lock); 1382f04a9d8aSRajkumar Kasirajan turn_on_stat_mask = mask; 1383f04a9d8aSRajkumar Kasirajan turn_on_stat_set = set; 1384f04a9d8aSRajkumar Kasirajan spin_unlock(&on_stat_lock); 1385f04a9d8aSRajkumar Kasirajan } 1386f04a9d8aSRajkumar Kasirajan 1387b4a31037SAndrew Lynn /* 1388b4a31037SAndrew Lynn * ab8500 has turned on due to (TURN_ON_STATUS): 1389b4a31037SAndrew Lynn * 0x01 PORnVbat 1390b4a31037SAndrew Lynn * 0x02 PonKey1dbF 1391b4a31037SAndrew Lynn * 0x04 PonKey2dbF 1392b4a31037SAndrew Lynn * 0x08 RTCAlarm 1393b4a31037SAndrew Lynn * 0x10 MainChDet 1394b4a31037SAndrew Lynn * 0x20 VbusDet 1395b4a31037SAndrew Lynn * 0x40 UsbIDDetect 1396b4a31037SAndrew Lynn * 0x80 Reserved 1397b4a31037SAndrew Lynn */ 1398b4a31037SAndrew Lynn static ssize_t show_turn_on_status(struct device *dev, 1399b4a31037SAndrew Lynn struct device_attribute *attr, char *buf) 1400b4a31037SAndrew Lynn { 1401b4a31037SAndrew Lynn int ret; 1402b4a31037SAndrew Lynn u8 value; 1403b4a31037SAndrew Lynn struct ab8500 *ab8500; 1404b4a31037SAndrew Lynn 1405b4a31037SAndrew Lynn ab8500 = dev_get_drvdata(dev); 1406b4a31037SAndrew Lynn ret = get_register_interruptible(ab8500, AB8500_SYS_CTRL1_BLOCK, 1407b4a31037SAndrew Lynn AB8500_TURN_ON_STATUS, &value); 1408b4a31037SAndrew Lynn if (ret < 0) 1409b4a31037SAndrew Lynn return ret; 1410f04a9d8aSRajkumar Kasirajan 1411f04a9d8aSRajkumar Kasirajan /* 1412f04a9d8aSRajkumar Kasirajan * In L9540, turn_on_status register is not updated correctly if 1413f04a9d8aSRajkumar Kasirajan * the device is rebooted with AC/USB charger connected. Due to 1414f04a9d8aSRajkumar Kasirajan * this, the device boots android instead of entering into charge 1415f04a9d8aSRajkumar Kasirajan * only mode. Read the AC/USB status register to detect the charger 1416f04a9d8aSRajkumar Kasirajan * presence and update the turn on status manually. 1417f04a9d8aSRajkumar Kasirajan */ 1418f04a9d8aSRajkumar Kasirajan if (is_ab9540(ab8500)) { 1419f04a9d8aSRajkumar Kasirajan spin_lock(&on_stat_lock); 1420f04a9d8aSRajkumar Kasirajan value = (value & turn_on_stat_mask) | turn_on_stat_set; 1421f04a9d8aSRajkumar Kasirajan spin_unlock(&on_stat_lock); 1422f04a9d8aSRajkumar Kasirajan } 1423f04a9d8aSRajkumar Kasirajan 1424b4a31037SAndrew Lynn return sprintf(buf, "%#x\n", value); 1425b4a31037SAndrew Lynn } 1426b4a31037SAndrew Lynn 1427d6255529SLinus Walleij static ssize_t show_ab9540_dbbrstn(struct device *dev, 1428d6255529SLinus Walleij struct device_attribute *attr, char *buf) 1429d6255529SLinus Walleij { 1430d6255529SLinus Walleij struct ab8500 *ab8500; 1431d6255529SLinus Walleij int ret; 1432d6255529SLinus Walleij u8 value; 1433d6255529SLinus Walleij 1434d6255529SLinus Walleij ab8500 = dev_get_drvdata(dev); 1435d6255529SLinus Walleij 1436d6255529SLinus Walleij ret = get_register_interruptible(ab8500, AB8500_REGU_CTRL2, 1437d6255529SLinus Walleij AB9540_MODEM_CTRL2_REG, &value); 1438d6255529SLinus Walleij if (ret < 0) 1439d6255529SLinus Walleij return ret; 1440d6255529SLinus Walleij 1441d6255529SLinus Walleij return sprintf(buf, "%d\n", 1442d6255529SLinus Walleij (value & AB9540_MODEM_CTRL2_SWDBBRSTN_BIT) ? 1 : 0); 1443d6255529SLinus Walleij } 1444d6255529SLinus Walleij 1445d6255529SLinus Walleij static ssize_t store_ab9540_dbbrstn(struct device *dev, 1446d6255529SLinus Walleij struct device_attribute *attr, const char *buf, size_t count) 1447d6255529SLinus Walleij { 1448d6255529SLinus Walleij struct ab8500 *ab8500; 1449d6255529SLinus Walleij int ret = count; 1450d6255529SLinus Walleij int err; 1451d6255529SLinus Walleij u8 bitvalues; 1452d6255529SLinus Walleij 1453d6255529SLinus Walleij ab8500 = dev_get_drvdata(dev); 1454d6255529SLinus Walleij 1455d6255529SLinus Walleij if (count > 0) { 1456d6255529SLinus Walleij switch (buf[0]) { 1457d6255529SLinus Walleij case '0': 1458d6255529SLinus Walleij bitvalues = 0; 1459d6255529SLinus Walleij break; 1460d6255529SLinus Walleij case '1': 1461d6255529SLinus Walleij bitvalues = AB9540_MODEM_CTRL2_SWDBBRSTN_BIT; 1462d6255529SLinus Walleij break; 1463d6255529SLinus Walleij default: 1464d6255529SLinus Walleij goto exit; 1465d6255529SLinus Walleij } 1466d6255529SLinus Walleij 1467d6255529SLinus Walleij err = mask_and_set_register_interruptible(ab8500, 1468d6255529SLinus Walleij AB8500_REGU_CTRL2, AB9540_MODEM_CTRL2_REG, 1469d6255529SLinus Walleij AB9540_MODEM_CTRL2_SWDBBRSTN_BIT, bitvalues); 1470d6255529SLinus Walleij if (err) 1471d6255529SLinus Walleij dev_info(ab8500->dev, 1472d6255529SLinus Walleij "Failed to set DBBRSTN %c, err %#x\n", 1473d6255529SLinus Walleij buf[0], err); 1474d6255529SLinus Walleij } 1475d6255529SLinus Walleij 1476d6255529SLinus Walleij exit: 1477d6255529SLinus Walleij return ret; 1478d6255529SLinus Walleij } 1479d6255529SLinus Walleij 1480cca69b67SMattias Wallin static DEVICE_ATTR(chip_id, S_IRUGO, show_chip_id, NULL); 1481e5c238c3SMattias Wallin static DEVICE_ATTR(switch_off_status, S_IRUGO, show_switch_off_status, NULL); 1482b4a31037SAndrew Lynn static DEVICE_ATTR(turn_on_status, S_IRUGO, show_turn_on_status, NULL); 1483d6255529SLinus Walleij static DEVICE_ATTR(dbbrstn, S_IRUGO | S_IWUSR, 1484d6255529SLinus Walleij show_ab9540_dbbrstn, store_ab9540_dbbrstn); 1485cca69b67SMattias Wallin 1486cca69b67SMattias Wallin static struct attribute *ab8500_sysfs_entries[] = { 1487cca69b67SMattias Wallin &dev_attr_chip_id.attr, 1488e5c238c3SMattias Wallin &dev_attr_switch_off_status.attr, 1489b4a31037SAndrew Lynn &dev_attr_turn_on_status.attr, 1490cca69b67SMattias Wallin NULL, 1491cca69b67SMattias Wallin }; 1492cca69b67SMattias Wallin 1493d6255529SLinus Walleij static struct attribute *ab9540_sysfs_entries[] = { 1494d6255529SLinus Walleij &dev_attr_chip_id.attr, 1495d6255529SLinus Walleij &dev_attr_switch_off_status.attr, 1496d6255529SLinus Walleij &dev_attr_turn_on_status.attr, 1497d6255529SLinus Walleij &dev_attr_dbbrstn.attr, 1498d6255529SLinus Walleij NULL, 1499d6255529SLinus Walleij }; 1500d6255529SLinus Walleij 1501cca69b67SMattias Wallin static struct attribute_group ab8500_attr_group = { 1502cca69b67SMattias Wallin .attrs = ab8500_sysfs_entries, 1503cca69b67SMattias Wallin }; 1504cca69b67SMattias Wallin 1505d6255529SLinus Walleij static struct attribute_group ab9540_attr_group = { 1506d6255529SLinus Walleij .attrs = ab9540_sysfs_entries, 1507d6255529SLinus Walleij }; 1508d6255529SLinus Walleij 1509f791be49SBill Pemberton static int ab8500_probe(struct platform_device *pdev) 151062579266SRabin Vincent { 1511b04c530cSJonas Aaberg static char *switch_off_status[] = { 1512b04c530cSJonas Aaberg "Swoff bit programming", 1513b04c530cSJonas Aaberg "Thermal protection activation", 1514b04c530cSJonas Aaberg "Vbat lower then BattOk falling threshold", 1515b04c530cSJonas Aaberg "Watchdog expired", 1516b04c530cSJonas Aaberg "Non presence of 32kHz clock", 1517b04c530cSJonas Aaberg "Battery level lower than power on reset threshold", 1518b04c530cSJonas Aaberg "Power on key 1 pressed longer than 10 seconds", 1519b04c530cSJonas Aaberg "DB8500 thermal shutdown"}; 1520d28f1db8SLee Jones struct ab8500_platform_data *plat = dev_get_platdata(&pdev->dev); 1521d28f1db8SLee Jones const struct platform_device_id *platid = platform_get_device_id(pdev); 15226bc4a568SLee Jones enum ab8500_version version = AB8500_VERSION_UNDEFINED; 15236bc4a568SLee Jones struct device_node *np = pdev->dev.of_node; 1524d28f1db8SLee Jones struct ab8500 *ab8500; 1525d28f1db8SLee Jones struct resource *resource; 152662579266SRabin Vincent int ret; 152762579266SRabin Vincent int i; 152847c16975SMattias Wallin u8 value; 152962579266SRabin Vincent 15308c4203cbSLee Jones ab8500 = devm_kzalloc(&pdev->dev, sizeof *ab8500, GFP_KERNEL); 1531d28f1db8SLee Jones if (!ab8500) 1532d28f1db8SLee Jones return -ENOMEM; 1533d28f1db8SLee Jones 153462579266SRabin Vincent if (plat) 153562579266SRabin Vincent ab8500->irq_base = plat->irq_base; 153662579266SRabin Vincent 1537d28f1db8SLee Jones ab8500->dev = &pdev->dev; 1538d28f1db8SLee Jones 1539d28f1db8SLee Jones resource = platform_get_resource(pdev, IORESOURCE_IRQ, 0); 15408c4203cbSLee Jones if (!resource) 15418c4203cbSLee Jones return -ENODEV; 1542d28f1db8SLee Jones 1543d28f1db8SLee Jones ab8500->irq = resource->start; 1544d28f1db8SLee Jones 1545822672a7SLee Jones ab8500->read = ab8500_prcmu_read; 1546822672a7SLee Jones ab8500->write = ab8500_prcmu_write; 1547822672a7SLee Jones ab8500->write_masked = ab8500_prcmu_write_masked; 1548d28f1db8SLee Jones 154962579266SRabin Vincent mutex_init(&ab8500->lock); 155062579266SRabin Vincent mutex_init(&ab8500->irq_lock); 1551112a80d2SJonas Aaberg atomic_set(&ab8500->transfer_ongoing, 0); 155262579266SRabin Vincent 1553d28f1db8SLee Jones platform_set_drvdata(pdev, ab8500); 1554d28f1db8SLee Jones 15556bc4a568SLee Jones if (platid) 15566bc4a568SLee Jones version = platid->driver_data; 15576bc4a568SLee Jones 15580f620837SLinus Walleij if (version != AB8500_VERSION_UNDEFINED) 15590f620837SLinus Walleij ab8500->version = version; 15600f620837SLinus Walleij else { 15610f620837SLinus Walleij ret = get_register_interruptible(ab8500, AB8500_MISC, 15620f620837SLinus Walleij AB8500_IC_NAME_REG, &value); 15630f620837SLinus Walleij if (ret < 0) 15648c4203cbSLee Jones return ret; 15650f620837SLinus Walleij 15660f620837SLinus Walleij ab8500->version = value; 15670f620837SLinus Walleij } 15680f620837SLinus Walleij 156947c16975SMattias Wallin ret = get_register_interruptible(ab8500, AB8500_MISC, 157047c16975SMattias Wallin AB8500_REV_REG, &value); 157162579266SRabin Vincent if (ret < 0) 15728c4203cbSLee Jones return ret; 157362579266SRabin Vincent 157447c16975SMattias Wallin ab8500->chip_id = value; 157562579266SRabin Vincent 15760f620837SLinus Walleij dev_info(ab8500->dev, "detected chip, %s rev. %1x.%1x\n", 15770f620837SLinus Walleij ab8500_version_str[ab8500->version], 15780f620837SLinus Walleij ab8500->chip_id >> 4, 15790f620837SLinus Walleij ab8500->chip_id & 0x0F); 15800f620837SLinus Walleij 1581*3e1a498fSLee Jones /* Configure AB8540 */ 1582*3e1a498fSLee Jones if (is_ab8540(ab8500)) { 1583*3e1a498fSLee Jones ab8500->mask_size = AB8540_NUM_IRQ_REGS; 1584*3e1a498fSLee Jones ab8500->irq_reg_offset = ab8540_irq_regoffset; 1585*3e1a498fSLee Jones ab8500->it_latchhier_num = AB8540_IT_LATCHHIER_NUM; 1586*3e1a498fSLee Jones }/* Configure AB8500 or AB9540 IRQ */ 1587*3e1a498fSLee Jones else if (is_ab9540(ab8500) || is_ab8505(ab8500)) { 1588d6255529SLinus Walleij ab8500->mask_size = AB9540_NUM_IRQ_REGS; 1589d6255529SLinus Walleij ab8500->irq_reg_offset = ab9540_irq_regoffset; 1590*3e1a498fSLee Jones ab8500->it_latchhier_num = AB8500_IT_LATCHHIER_NUM; 1591d6255529SLinus Walleij } else { 15922ced445eSLinus Walleij ab8500->mask_size = AB8500_NUM_IRQ_REGS; 15932ced445eSLinus Walleij ab8500->irq_reg_offset = ab8500_irq_regoffset; 1594*3e1a498fSLee Jones ab8500->it_latchhier_num = AB8500_IT_LATCHHIER_NUM; 1595d6255529SLinus Walleij } 15968c4203cbSLee Jones ab8500->mask = devm_kzalloc(&pdev->dev, ab8500->mask_size, GFP_KERNEL); 15972ced445eSLinus Walleij if (!ab8500->mask) 15982ced445eSLinus Walleij return -ENOMEM; 15998c4203cbSLee Jones ab8500->oldmask = devm_kzalloc(&pdev->dev, ab8500->mask_size, GFP_KERNEL); 16008c4203cbSLee Jones if (!ab8500->oldmask) 16018c4203cbSLee Jones return -ENOMEM; 16028c4203cbSLee Jones 1603e5c238c3SMattias Wallin /* 1604e5c238c3SMattias Wallin * ab8500 has switched off due to (SWITCH_OFF_STATUS): 1605e5c238c3SMattias Wallin * 0x01 Swoff bit programming 1606e5c238c3SMattias Wallin * 0x02 Thermal protection activation 1607e5c238c3SMattias Wallin * 0x04 Vbat lower then BattOk falling threshold 1608e5c238c3SMattias Wallin * 0x08 Watchdog expired 1609e5c238c3SMattias Wallin * 0x10 Non presence of 32kHz clock 1610e5c238c3SMattias Wallin * 0x20 Battery level lower than power on reset threshold 1611e5c238c3SMattias Wallin * 0x40 Power on key 1 pressed longer than 10 seconds 1612e5c238c3SMattias Wallin * 0x80 DB8500 thermal shutdown 1613e5c238c3SMattias Wallin */ 1614e5c238c3SMattias Wallin 1615e5c238c3SMattias Wallin ret = get_register_interruptible(ab8500, AB8500_RTC, 1616e5c238c3SMattias Wallin AB8500_SWITCH_OFF_STATUS, &value); 1617e5c238c3SMattias Wallin if (ret < 0) 1618e5c238c3SMattias Wallin return ret; 1619b04c530cSJonas Aaberg dev_info(ab8500->dev, "switch off cause(s) (%#x): ", value); 1620b04c530cSJonas Aaberg 1621b04c530cSJonas Aaberg if (value) { 1622b04c530cSJonas Aaberg for (i = 0; i < ARRAY_SIZE(switch_off_status); i++) { 1623b04c530cSJonas Aaberg if (value & 1) 1624b04c530cSJonas Aaberg printk(KERN_CONT " \"%s\"", 1625b04c530cSJonas Aaberg switch_off_status[i]); 1626b04c530cSJonas Aaberg value = value >> 1; 1627b04c530cSJonas Aaberg 1628b04c530cSJonas Aaberg } 1629b04c530cSJonas Aaberg printk(KERN_CONT "\n"); 1630b04c530cSJonas Aaberg } else { 1631b04c530cSJonas Aaberg printk(KERN_CONT " None\n"); 1632b04c530cSJonas Aaberg } 1633e5c238c3SMattias Wallin 163462579266SRabin Vincent if (plat && plat->init) 163562579266SRabin Vincent plat->init(ab8500); 1636f04a9d8aSRajkumar Kasirajan if (is_ab9540(ab8500)) { 1637f04a9d8aSRajkumar Kasirajan ret = get_register_interruptible(ab8500, AB8500_CHARGER, 1638f04a9d8aSRajkumar Kasirajan AB8500_CH_USBCH_STAT1_REG, &value); 1639f04a9d8aSRajkumar Kasirajan if (ret < 0) 1640f04a9d8aSRajkumar Kasirajan return ret; 1641f04a9d8aSRajkumar Kasirajan if ((value & VBUS_DET_DBNC1) && (value & VBUS_DET_DBNC100)) 1642f04a9d8aSRajkumar Kasirajan ab8500_override_turn_on_stat(~AB8500_POW_KEY_1_ON, 1643f04a9d8aSRajkumar Kasirajan AB8500_VBUS_DET); 1644f04a9d8aSRajkumar Kasirajan } 164562579266SRabin Vincent 164662579266SRabin Vincent /* Clear and mask all interrupts */ 16472ced445eSLinus Walleij for (i = 0; i < ab8500->mask_size; i++) { 16480f620837SLinus Walleij /* 16490f620837SLinus Walleij * Interrupt register 12 doesn't exist prior to AB8500 version 16500f620837SLinus Walleij * 2.0 16510f620837SLinus Walleij */ 16520f620837SLinus Walleij if (ab8500->irq_reg_offset[i] == 11 && 16530f620837SLinus Walleij is_ab8500_1p1_or_earlier(ab8500)) 165492d50a41SMattias Wallin continue; 165562579266SRabin Vincent 1656*3e1a498fSLee Jones if (ab8500->irq_reg_offset[i] < 0) 1657*3e1a498fSLee Jones continue; 1658*3e1a498fSLee Jones 165947c16975SMattias Wallin get_register_interruptible(ab8500, AB8500_INTERRUPT, 16602ced445eSLinus Walleij AB8500_IT_LATCH1_REG + ab8500->irq_reg_offset[i], 166192d50a41SMattias Wallin &value); 166247c16975SMattias Wallin set_register_interruptible(ab8500, AB8500_INTERRUPT, 16632ced445eSLinus Walleij AB8500_IT_MASK1_REG + ab8500->irq_reg_offset[i], 0xff); 166462579266SRabin Vincent } 166562579266SRabin Vincent 166647c16975SMattias Wallin ret = abx500_register_ops(ab8500->dev, &ab8500_ops); 166747c16975SMattias Wallin if (ret) 16688c4203cbSLee Jones return ret; 166947c16975SMattias Wallin 16702ced445eSLinus Walleij for (i = 0; i < ab8500->mask_size; i++) 167162579266SRabin Vincent ab8500->mask[i] = ab8500->oldmask[i] = 0xff; 167262579266SRabin Vincent 167306e589efSLee Jones ret = ab8500_irq_init(ab8500, np); 167462579266SRabin Vincent if (ret) 16758c4203cbSLee Jones return ret; 167662579266SRabin Vincent 16777ccfe9b1SMichel JAOUEN /* Activate this feature only in ab9540 */ 16787ccfe9b1SMichel JAOUEN /* till tests are done on ab8500 1p2 or later*/ 167906e589efSLee Jones if (is_ab9540(ab8500)) { 16808c4203cbSLee Jones ret = devm_request_threaded_irq(&pdev->dev, ab8500->irq, NULL, 16817ccfe9b1SMichel JAOUEN ab8500_hierarchical_irq, 16827ccfe9b1SMichel JAOUEN IRQF_ONESHOT | IRQF_NO_SUSPEND, 16837ccfe9b1SMichel JAOUEN "ab8500", ab8500); 168406e589efSLee Jones } 168506e589efSLee Jones else { 16868c4203cbSLee Jones ret = devm_request_threaded_irq(&pdev->dev, ab8500->irq, NULL, 16877ccfe9b1SMichel JAOUEN ab8500_irq, 16884f079985SMattias Wallin IRQF_ONESHOT | IRQF_NO_SUSPEND, 16894f079985SMattias Wallin "ab8500", ab8500); 169062579266SRabin Vincent if (ret) 16918c4203cbSLee Jones return ret; 169262579266SRabin Vincent } 169362579266SRabin Vincent 1694d6255529SLinus Walleij if (is_ab9540(ab8500)) 1695d6255529SLinus Walleij ret = mfd_add_devices(ab8500->dev, 0, ab9540_devs, 1696d6255529SLinus Walleij ARRAY_SIZE(ab9540_devs), NULL, 169755692af5SMark Brown ab8500->irq_base, ab8500->domain); 1698c0eda9aeSLee Jones else if (is_ab8540(ab8500)) 1699c0eda9aeSLee Jones ret = mfd_add_devices(ab8500->dev, 0, ab8540_devs, 1700c0eda9aeSLee Jones ARRAY_SIZE(ab8540_devs), NULL, 1701c0eda9aeSLee Jones ab8500->irq_base, ab8500->domain); 1702c0eda9aeSLee Jones else if (is_ab8505(ab8500)) 1703c0eda9aeSLee Jones ret = mfd_add_devices(ab8500->dev, 0, ab8505_devs, 1704c0eda9aeSLee Jones ARRAY_SIZE(ab8505_devs), NULL, 1705c0eda9aeSLee Jones ab8500->irq_base, ab8500->domain); 1706d6255529SLinus Walleij else 1707549931f9SSundar R Iyer ret = mfd_add_devices(ab8500->dev, 0, ab8500_devs, 170844f72e53SVirupax Sadashivpetimath ARRAY_SIZE(ab8500_devs), NULL, 170955692af5SMark Brown ab8500->irq_base, ab8500->domain); 17106bc4a568SLee Jones if (ret) 17118c4203cbSLee Jones return ret; 171244f72e53SVirupax Sadashivpetimath 17136ef9418cSRickard Andersson if (!no_bm) { 17146ef9418cSRickard Andersson /* Add battery management devices */ 17156ef9418cSRickard Andersson ret = mfd_add_devices(ab8500->dev, 0, ab8500_bm_devs, 17166ef9418cSRickard Andersson ARRAY_SIZE(ab8500_bm_devs), NULL, 171755692af5SMark Brown ab8500->irq_base, ab8500->domain); 17186ef9418cSRickard Andersson if (ret) 17196ef9418cSRickard Andersson dev_err(ab8500->dev, "error adding bm devices\n"); 17206ef9418cSRickard Andersson } 17216ef9418cSRickard Andersson 1722d6255529SLinus Walleij if (is_ab9540(ab8500)) 1723d6255529SLinus Walleij ret = sysfs_create_group(&ab8500->dev->kobj, 1724d6255529SLinus Walleij &ab9540_attr_group); 1725d6255529SLinus Walleij else 1726d6255529SLinus Walleij ret = sysfs_create_group(&ab8500->dev->kobj, 1727d6255529SLinus Walleij &ab8500_attr_group); 1728cca69b67SMattias Wallin if (ret) 1729cca69b67SMattias Wallin dev_err(ab8500->dev, "error creating sysfs entries\n"); 173006e589efSLee Jones 173162579266SRabin Vincent return ret; 173262579266SRabin Vincent } 173362579266SRabin Vincent 17344740f73fSBill Pemberton static int ab8500_remove(struct platform_device *pdev) 173562579266SRabin Vincent { 1736d28f1db8SLee Jones struct ab8500 *ab8500 = platform_get_drvdata(pdev); 1737d28f1db8SLee Jones 1738d6255529SLinus Walleij if (is_ab9540(ab8500)) 1739d6255529SLinus Walleij sysfs_remove_group(&ab8500->dev->kobj, &ab9540_attr_group); 1740d6255529SLinus Walleij else 1741cca69b67SMattias Wallin sysfs_remove_group(&ab8500->dev->kobj, &ab8500_attr_group); 174206e589efSLee Jones 174362579266SRabin Vincent mfd_remove_devices(ab8500->dev); 174462579266SRabin Vincent 174562579266SRabin Vincent return 0; 174662579266SRabin Vincent } 174762579266SRabin Vincent 1748d28f1db8SLee Jones static const struct platform_device_id ab8500_id[] = { 1749d28f1db8SLee Jones { "ab8500-core", AB8500_VERSION_AB8500 }, 1750d28f1db8SLee Jones { "ab8505-i2c", AB8500_VERSION_AB8505 }, 1751d28f1db8SLee Jones { "ab9540-i2c", AB8500_VERSION_AB9540 }, 1752d28f1db8SLee Jones { "ab8540-i2c", AB8500_VERSION_AB8540 }, 1753d28f1db8SLee Jones { } 1754d28f1db8SLee Jones }; 1755d28f1db8SLee Jones 1756d28f1db8SLee Jones static struct platform_driver ab8500_core_driver = { 1757d28f1db8SLee Jones .driver = { 1758d28f1db8SLee Jones .name = "ab8500-core", 1759d28f1db8SLee Jones .owner = THIS_MODULE, 1760d28f1db8SLee Jones }, 1761d28f1db8SLee Jones .probe = ab8500_probe, 176284449216SBill Pemberton .remove = ab8500_remove, 1763d28f1db8SLee Jones .id_table = ab8500_id, 1764d28f1db8SLee Jones }; 1765d28f1db8SLee Jones 1766d28f1db8SLee Jones static int __init ab8500_core_init(void) 1767d28f1db8SLee Jones { 1768d28f1db8SLee Jones return platform_driver_register(&ab8500_core_driver); 1769d28f1db8SLee Jones } 1770d28f1db8SLee Jones 1771d28f1db8SLee Jones static void __exit ab8500_core_exit(void) 1772d28f1db8SLee Jones { 1773d28f1db8SLee Jones platform_driver_unregister(&ab8500_core_driver); 1774d28f1db8SLee Jones } 1775ba7cbc3eSLee Jones core_initcall(ab8500_core_init); 1776d28f1db8SLee Jones module_exit(ab8500_core_exit); 1777d28f1db8SLee Jones 1778adceed62SMattias Wallin MODULE_AUTHOR("Mattias Wallin, Srinidhi Kasagar, Rabin Vincent"); 177962579266SRabin Vincent MODULE_DESCRIPTION("AB8500 MFD core"); 178062579266SRabin Vincent MODULE_LICENSE("GPL v2"); 1781