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 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 1483e1a498fSLee Jones /* AB8540 support */ 1493e1a498fSLee Jones static const int ab8540_irq_regoffset[AB8540_NUM_IRQ_REGS] = { 1503e1a498fSLee Jones 0, 1, 2, 3, 4, -1, -1, -1, -1, 11, 18, 19, 20, 21, 12, 13, 24, 5, 22, 23, 1513e1a498fSLee Jones 25, 26, 27, 28, 29, 30, 31, 1523e1a498fSLee Jones }; 1533e1a498fSLee 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 3713e1a498fSLee Jones if (ab8500->irq_reg_offset[i] < 0) 3723e1a498fSLee Jones continue; 3733e1a498fSLee 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 4453e1a498fSLee Jones static void update_latch_offset(u8 *offset, int i) 4463e1a498fSLee Jones { 4473e1a498fSLee Jones /* Fix inconsistent ITFromLatch25 bit mapping... */ 4483e1a498fSLee Jones if (unlikely(*offset == 17)) 4493e1a498fSLee Jones *offset = 24; 4503e1a498fSLee Jones /* Fix inconsistent ab8540 bit mapping... */ 4513e1a498fSLee Jones if (unlikely(*offset == 16)) 4523e1a498fSLee Jones *offset = 25; 4533e1a498fSLee Jones if ((i==3) && (*offset >= 24)) 4543e1a498fSLee Jones *offset += 2; 4553e1a498fSLee Jones } 4563e1a498fSLee 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 5083e1a498fSLee 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 */ 5363e1a498fSLee 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 5893e1a498fSLee Jones if (regoffset < 0) 5903e1a498fSLee Jones continue; 5913e1a498fSLee 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 6423e1a498fSLee Jones if (is_ab8540(ab8500)) 6433e1a498fSLee Jones num_irqs = AB8540_NR_IRQS; 6443e1a498fSLee 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 }, 1019492390c8SLee Jones { 1020492390c8SLee Jones .name = "VBUS_DET_R", 1021492390c8SLee Jones .start = AB8500_INT_VBUS_DET_R, 1022492390c8SLee Jones .end = AB8500_INT_VBUS_DET_R, 1023492390c8SLee Jones .flags = IORESOURCE_IRQ, 1024492390c8SLee Jones }, 1025492390c8SLee Jones { 1026492390c8SLee Jones .name = "VBUS_DET_F", 1027492390c8SLee Jones .start = AB8500_INT_VBUS_DET_F, 1028492390c8SLee Jones .end = AB8500_INT_VBUS_DET_F, 1029492390c8SLee Jones .flags = IORESOURCE_IRQ, 1030492390c8SLee Jones }, 1031492390c8SLee Jones { 1032492390c8SLee Jones .name = "ID_DET_PLUGR", 1033492390c8SLee Jones .start = AB8500_INT_ID_DET_PLUGR, 1034492390c8SLee Jones .end = AB8500_INT_ID_DET_PLUGR, 1035492390c8SLee Jones .flags = IORESOURCE_IRQ, 1036492390c8SLee Jones }, 1037492390c8SLee Jones { 1038492390c8SLee Jones .name = "ID_DET_PLUGF", 1039492390c8SLee Jones .start = AB8500_INT_ID_DET_PLUGF, 1040492390c8SLee Jones .end = AB8500_INT_ID_DET_PLUGF, 1041492390c8SLee Jones .flags = IORESOURCE_IRQ, 1042492390c8SLee Jones }, 104344f72e53SVirupax Sadashivpetimath }; 104444f72e53SVirupax Sadashivpetimath 1045a9e9ce4cSBill Pemberton static struct resource ab8500_temp_resources[] = { 1046e098adedSMattias Wallin { 1047151621a7SHongbo Zhang .name = "ABX500_TEMP_WARM", 1048e098adedSMattias Wallin .start = AB8500_INT_TEMP_WARM, 1049e098adedSMattias Wallin .end = AB8500_INT_TEMP_WARM, 1050e098adedSMattias Wallin .flags = IORESOURCE_IRQ, 1051e098adedSMattias Wallin }, 1052e098adedSMattias Wallin }; 1053e098adedSMattias Wallin 1054a9e9ce4cSBill Pemberton static struct mfd_cell ab8500_bm_devs[] = { 10556ef9418cSRickard Andersson { 10566ef9418cSRickard Andersson .name = "ab8500-charger", 10574aef72dbSRajanikanth H.V .of_compatible = "stericsson,ab8500-charger", 10586ef9418cSRickard Andersson .num_resources = ARRAY_SIZE(ab8500_charger_resources), 10596ef9418cSRickard Andersson .resources = ab8500_charger_resources, 10604aef72dbSRajanikanth H.V .platform_data = &ab8500_bm_data, 10614aef72dbSRajanikanth H.V .pdata_size = sizeof(ab8500_bm_data), 10626ef9418cSRickard Andersson }, 10636ef9418cSRickard Andersson { 10646ef9418cSRickard Andersson .name = "ab8500-btemp", 1065bd9e8ab2SRajanikanth H.V .of_compatible = "stericsson,ab8500-btemp", 10666ef9418cSRickard Andersson .num_resources = ARRAY_SIZE(ab8500_btemp_resources), 10676ef9418cSRickard Andersson .resources = ab8500_btemp_resources, 1068bd9e8ab2SRajanikanth H.V .platform_data = &ab8500_bm_data, 1069bd9e8ab2SRajanikanth H.V .pdata_size = sizeof(ab8500_bm_data), 10706ef9418cSRickard Andersson }, 10716ef9418cSRickard Andersson { 10726ef9418cSRickard Andersson .name = "ab8500-fg", 1073e0f1abebSRajanikanth H.V .of_compatible = "stericsson,ab8500-fg", 10746ef9418cSRickard Andersson .num_resources = ARRAY_SIZE(ab8500_fg_resources), 10756ef9418cSRickard Andersson .resources = ab8500_fg_resources, 1076e0f1abebSRajanikanth H.V .platform_data = &ab8500_bm_data, 1077e0f1abebSRajanikanth H.V .pdata_size = sizeof(ab8500_bm_data), 10786ef9418cSRickard Andersson }, 10796ef9418cSRickard Andersson { 10806ef9418cSRickard Andersson .name = "ab8500-chargalg", 1081a12810abSRajanikanth H.V .of_compatible = "stericsson,ab8500-chargalg", 10826ef9418cSRickard Andersson .num_resources = ARRAY_SIZE(ab8500_chargalg_resources), 10836ef9418cSRickard Andersson .resources = ab8500_chargalg_resources, 1084a12810abSRajanikanth H.V .platform_data = &ab8500_bm_data, 1085a12810abSRajanikanth H.V .pdata_size = sizeof(ab8500_bm_data), 10866ef9418cSRickard Andersson }, 10876ef9418cSRickard Andersson }; 10886ef9418cSRickard Andersson 1089a9e9ce4cSBill Pemberton static struct mfd_cell ab8500_devs[] = { 10904b106fb9SLee Jones #ifdef CONFIG_DEBUG_FS 1091d6255529SLinus Walleij { 10924b106fb9SLee Jones .name = "ab8500-debug", 10934b106fb9SLee Jones .of_compatible = "stericsson,ab8500-debug", 10944b106fb9SLee Jones .num_resources = ARRAY_SIZE(ab8500_debug_resources), 10954b106fb9SLee Jones .resources = ab8500_debug_resources, 10964b106fb9SLee Jones }, 10974b106fb9SLee Jones #endif 10984b106fb9SLee Jones { 10994b106fb9SLee Jones .name = "ab8500-sysctrl", 11004b106fb9SLee Jones .of_compatible = "stericsson,ab8500-sysctrl", 11014b106fb9SLee Jones }, 11024b106fb9SLee Jones { 11034b106fb9SLee Jones .name = "ab8500-regulator", 11044b106fb9SLee Jones .of_compatible = "stericsson,ab8500-regulator", 11054b106fb9SLee Jones }, 11064b106fb9SLee Jones { 11074b106fb9SLee Jones .name = "abx500-clk", 11084b106fb9SLee Jones .of_compatible = "stericsson,abx500-clk", 11094b106fb9SLee Jones }, 11104b106fb9SLee Jones { 11114b106fb9SLee Jones .name = "ab8500-gpadc", 11124b106fb9SLee Jones .num_resources = ARRAY_SIZE(ab8500_gpadc_resources), 11134b106fb9SLee Jones .resources = ab8500_gpadc_resources, 11144b106fb9SLee Jones }, 11154b106fb9SLee Jones { 11164b106fb9SLee Jones .name = "ab8500-rtc", 11174b106fb9SLee Jones .of_compatible = "stericsson,ab8500-rtc", 11184b106fb9SLee Jones .num_resources = ARRAY_SIZE(ab8500_rtc_resources), 11194b106fb9SLee Jones .resources = ab8500_rtc_resources, 11204b106fb9SLee Jones }, 11214b106fb9SLee Jones { 11224b106fb9SLee Jones .name = "ab8500-acc-det", 11234b106fb9SLee Jones .of_compatible = "stericsson,ab8500-acc-det", 11244b106fb9SLee Jones .num_resources = ARRAY_SIZE(ab8500_av_acc_detect_resources), 11254b106fb9SLee Jones .resources = ab8500_av_acc_detect_resources, 11264b106fb9SLee Jones }, 11274b106fb9SLee Jones { 11284b106fb9SLee Jones 11294b106fb9SLee Jones .name = "ab8500-poweron-key", 11304b106fb9SLee Jones .of_compatible = "stericsson,ab8500-poweron-key", 11314b106fb9SLee Jones .num_resources = ARRAY_SIZE(ab8500_poweronkey_db_resources), 11324b106fb9SLee Jones .resources = ab8500_poweronkey_db_resources, 11334b106fb9SLee Jones }, 11344b106fb9SLee Jones { 11354b106fb9SLee Jones .name = "ab8500-pwm", 11364b106fb9SLee Jones .of_compatible = "stericsson,ab8500-pwm", 11374b106fb9SLee Jones .id = 1, 11384b106fb9SLee Jones }, 11394b106fb9SLee Jones { 11404b106fb9SLee Jones .name = "ab8500-pwm", 11414b106fb9SLee Jones .of_compatible = "stericsson,ab8500-pwm", 11424b106fb9SLee Jones .id = 2, 11434b106fb9SLee Jones }, 11444b106fb9SLee Jones { 11454b106fb9SLee Jones .name = "ab8500-pwm", 11464b106fb9SLee Jones .of_compatible = "stericsson,ab8500-pwm", 11474b106fb9SLee Jones .id = 3, 11484b106fb9SLee Jones }, 11494b106fb9SLee Jones { 11504b106fb9SLee Jones .name = "ab8500-leds", 11514b106fb9SLee Jones .of_compatible = "stericsson,ab8500-leds", 11524b106fb9SLee Jones }, 11534b106fb9SLee Jones { 11544b106fb9SLee Jones .name = "ab8500-denc", 11554b106fb9SLee Jones .of_compatible = "stericsson,ab8500-denc", 11564b106fb9SLee Jones }, 11574b106fb9SLee Jones { 11584b106fb9SLee Jones .name = "ab8500-gpio", 1159bad76991SLee Jones .of_compatible = "stericsson,ab8500-gpio", 1160d6255529SLinus Walleij }, 1161d6255529SLinus Walleij { 11624b106fb9SLee Jones .name = "abx500-temp", 11634b106fb9SLee Jones .of_compatible = "stericsson,abx500-temp", 11644b106fb9SLee Jones .num_resources = ARRAY_SIZE(ab8500_temp_resources), 11654b106fb9SLee Jones .resources = ab8500_temp_resources, 11664b106fb9SLee Jones }, 11674b106fb9SLee Jones { 1168d6255529SLinus Walleij .name = "ab8500-usb", 1169d6255529SLinus Walleij .num_resources = ARRAY_SIZE(ab8500_usb_resources), 1170d6255529SLinus Walleij .resources = ab8500_usb_resources, 1171d6255529SLinus Walleij }, 117244f72e53SVirupax Sadashivpetimath { 117344f72e53SVirupax Sadashivpetimath .name = "ab8500-codec", 11744b106fb9SLee Jones }, 11754b106fb9SLee Jones }; 11764b106fb9SLee Jones 11774b106fb9SLee Jones static struct mfd_cell ab9540_devs[] = { 11784b106fb9SLee Jones #ifdef CONFIG_DEBUG_FS 11794b106fb9SLee Jones { 11804b106fb9SLee Jones .name = "ab8500-debug", 11814b106fb9SLee Jones .num_resources = ARRAY_SIZE(ab8500_debug_resources), 11824b106fb9SLee Jones .resources = ab8500_debug_resources, 11834b106fb9SLee Jones }, 11844b106fb9SLee Jones #endif 11854b106fb9SLee Jones { 11864b106fb9SLee Jones .name = "ab8500-sysctrl", 11874b106fb9SLee Jones }, 11884b106fb9SLee Jones { 11894b106fb9SLee Jones .name = "ab8500-regulator", 119044f72e53SVirupax Sadashivpetimath }, 1191c0eda9aeSLee Jones { 1192c0eda9aeSLee Jones .name = "ab8500-gpadc", 1193c0eda9aeSLee Jones .of_compatible = "stericsson,ab8500-gpadc", 1194c0eda9aeSLee Jones .num_resources = ARRAY_SIZE(ab8500_gpadc_resources), 1195c0eda9aeSLee Jones .resources = ab8500_gpadc_resources, 1196c0eda9aeSLee Jones }, 11974b106fb9SLee Jones { 11984b106fb9SLee Jones .name = "ab8500-rtc", 11994b106fb9SLee Jones .num_resources = ARRAY_SIZE(ab8500_rtc_resources), 12004b106fb9SLee Jones .resources = ab8500_rtc_resources, 12014b106fb9SLee Jones }, 12024b106fb9SLee Jones { 12034b106fb9SLee Jones .name = "ab8500-acc-det", 12044b106fb9SLee Jones .num_resources = ARRAY_SIZE(ab8500_av_acc_detect_resources), 12054b106fb9SLee Jones .resources = ab8500_av_acc_detect_resources, 12064b106fb9SLee Jones }, 12074b106fb9SLee Jones { 12084b106fb9SLee Jones .name = "ab8500-poweron-key", 12094b106fb9SLee Jones .num_resources = ARRAY_SIZE(ab8500_poweronkey_db_resources), 12104b106fb9SLee Jones .resources = ab8500_poweronkey_db_resources, 12114b106fb9SLee Jones }, 12124b106fb9SLee Jones { 12134b106fb9SLee Jones .name = "ab8500-pwm", 12144b106fb9SLee Jones .id = 1, 12154b106fb9SLee Jones }, 12164b106fb9SLee Jones { 12174b106fb9SLee Jones .name = "ab8500-leds", 12184b106fb9SLee Jones }, 12194b106fb9SLee Jones { 12204b106fb9SLee Jones .name = "abx500-temp", 12214b106fb9SLee Jones .num_resources = ARRAY_SIZE(ab8500_temp_resources), 12224b106fb9SLee Jones .resources = ab8500_temp_resources, 12234b106fb9SLee Jones }, 1224d6255529SLinus Walleij { 1225e64d905eSLee Jones .name = "pinctrl-ab9540", 1226e64d905eSLee Jones .of_compatible = "stericsson,ab9540-gpio", 1227d6255529SLinus Walleij }, 1228d6255529SLinus Walleij { 1229d6255529SLinus Walleij .name = "ab9540-usb", 1230d6255529SLinus Walleij .num_resources = ARRAY_SIZE(ab8500_usb_resources), 1231d6255529SLinus Walleij .resources = ab8500_usb_resources, 1232d6255529SLinus Walleij }, 123344f72e53SVirupax Sadashivpetimath { 123444f72e53SVirupax Sadashivpetimath .name = "ab9540-codec", 123544f72e53SVirupax Sadashivpetimath }, 1236c0eda9aeSLee Jones { 1237c0eda9aeSLee Jones .name = "ab-iddet", 1238c0eda9aeSLee Jones .num_resources = ARRAY_SIZE(ab8505_iddet_resources), 1239c0eda9aeSLee Jones .resources = ab8505_iddet_resources, 1240c0eda9aeSLee Jones }, 124144f72e53SVirupax Sadashivpetimath }; 124244f72e53SVirupax Sadashivpetimath 1243c0eda9aeSLee Jones /* Device list for ab8505 */ 1244c0eda9aeSLee Jones static struct mfd_cell ab8505_devs[] = { 12454b106fb9SLee Jones #ifdef CONFIG_DEBUG_FS 12464b106fb9SLee Jones { 12474b106fb9SLee Jones .name = "ab8500-debug", 12484b106fb9SLee Jones .num_resources = ARRAY_SIZE(ab8500_debug_resources), 12494b106fb9SLee Jones .resources = ab8500_debug_resources, 12504b106fb9SLee Jones }, 12514b106fb9SLee Jones #endif 12524b106fb9SLee Jones { 12534b106fb9SLee Jones .name = "ab8500-sysctrl", 12544b106fb9SLee Jones }, 12554b106fb9SLee Jones { 12564b106fb9SLee Jones .name = "ab8500-regulator", 12574b106fb9SLee Jones }, 12584b106fb9SLee Jones { 12594b106fb9SLee Jones .name = "ab8500-gpadc", 12604b106fb9SLee Jones .num_resources = ARRAY_SIZE(ab8505_gpadc_resources), 12614b106fb9SLee Jones .resources = ab8505_gpadc_resources, 12624b106fb9SLee Jones }, 12634b106fb9SLee Jones { 12644b106fb9SLee Jones .name = "ab8500-rtc", 12654b106fb9SLee Jones .num_resources = ARRAY_SIZE(ab8500_rtc_resources), 12664b106fb9SLee Jones .resources = ab8500_rtc_resources, 12674b106fb9SLee Jones }, 12684b106fb9SLee Jones { 12694b106fb9SLee Jones .name = "ab8500-acc-det", 12704b106fb9SLee Jones .num_resources = ARRAY_SIZE(ab8500_av_acc_detect_resources), 12714b106fb9SLee Jones .resources = ab8500_av_acc_detect_resources, 12724b106fb9SLee Jones }, 12734b106fb9SLee Jones { 12744b106fb9SLee Jones .name = "ab8500-poweron-key", 12754b106fb9SLee Jones .num_resources = ARRAY_SIZE(ab8500_poweronkey_db_resources), 12764b106fb9SLee Jones .resources = ab8500_poweronkey_db_resources, 12774b106fb9SLee Jones }, 12784b106fb9SLee Jones { 12794b106fb9SLee Jones .name = "ab8500-pwm", 12804b106fb9SLee Jones .id = 1, 12814b106fb9SLee Jones }, 12824b106fb9SLee Jones { 12834b106fb9SLee Jones .name = "ab8500-leds", 12844b106fb9SLee Jones }, 12854b106fb9SLee Jones { 12864b106fb9SLee Jones .name = "ab8500-gpio", 12874b106fb9SLee Jones }, 12884b106fb9SLee Jones { 12894b106fb9SLee Jones .name = "ab8500-usb", 12904b106fb9SLee Jones .num_resources = ARRAY_SIZE(ab8500_usb_resources), 12914b106fb9SLee Jones .resources = ab8500_usb_resources, 12924b106fb9SLee Jones }, 12934b106fb9SLee Jones { 12944b106fb9SLee Jones .name = "ab8500-codec", 12954b106fb9SLee Jones }, 1296c0eda9aeSLee Jones { 1297c0eda9aeSLee Jones .name = "ab-iddet", 1298c0eda9aeSLee Jones .num_resources = ARRAY_SIZE(ab8505_iddet_resources), 1299c0eda9aeSLee Jones .resources = ab8505_iddet_resources, 1300c0eda9aeSLee Jones }, 1301c0eda9aeSLee Jones }; 1302c0eda9aeSLee Jones 1303c0eda9aeSLee Jones static struct mfd_cell ab8540_devs[] = { 13044b106fb9SLee Jones #ifdef CONFIG_DEBUG_FS 13054b106fb9SLee Jones { 13064b106fb9SLee Jones .name = "ab8500-debug", 13074b106fb9SLee Jones .num_resources = ARRAY_SIZE(ab8500_debug_resources), 13084b106fb9SLee Jones .resources = ab8500_debug_resources, 13094b106fb9SLee Jones }, 13104b106fb9SLee Jones #endif 13114b106fb9SLee Jones { 13124b106fb9SLee Jones .name = "ab8500-sysctrl", 13134b106fb9SLee Jones }, 13144b106fb9SLee Jones { 13154b106fb9SLee Jones .name = "ab8500-regulator", 13164b106fb9SLee Jones }, 13174b106fb9SLee Jones { 13184b106fb9SLee Jones .name = "ab8500-gpadc", 13194b106fb9SLee Jones .num_resources = ARRAY_SIZE(ab8505_gpadc_resources), 13204b106fb9SLee Jones .resources = ab8505_gpadc_resources, 13214b106fb9SLee Jones }, 13224b106fb9SLee Jones { 13234b106fb9SLee Jones .name = "ab8500-rtc", 13244b106fb9SLee Jones .num_resources = ARRAY_SIZE(ab8500_rtc_resources), 13254b106fb9SLee Jones .resources = ab8500_rtc_resources, 13264b106fb9SLee Jones }, 13274b106fb9SLee Jones { 13284b106fb9SLee Jones .name = "ab8500-acc-det", 13294b106fb9SLee Jones .num_resources = ARRAY_SIZE(ab8500_av_acc_detect_resources), 13304b106fb9SLee Jones .resources = ab8500_av_acc_detect_resources, 13314b106fb9SLee Jones }, 13324b106fb9SLee Jones { 13334b106fb9SLee Jones .name = "ab8500-poweron-key", 13344b106fb9SLee Jones .num_resources = ARRAY_SIZE(ab8500_poweronkey_db_resources), 13354b106fb9SLee Jones .resources = ab8500_poweronkey_db_resources, 13364b106fb9SLee Jones }, 13374b106fb9SLee Jones { 13384b106fb9SLee Jones .name = "ab8500-pwm", 13394b106fb9SLee Jones .id = 1, 13404b106fb9SLee Jones }, 13414b106fb9SLee Jones { 13424b106fb9SLee Jones .name = "ab8500-leds", 13434b106fb9SLee Jones }, 13444b106fb9SLee Jones { 13454b106fb9SLee Jones .name = "abx500-temp", 13464b106fb9SLee Jones .num_resources = ARRAY_SIZE(ab8500_temp_resources), 13474b106fb9SLee Jones .resources = ab8500_temp_resources, 13484b106fb9SLee Jones }, 1349c0eda9aeSLee Jones { 1350c0eda9aeSLee Jones .name = "ab8500-gpio", 1351c0eda9aeSLee Jones }, 1352c0eda9aeSLee Jones { 1353c0eda9aeSLee Jones .name = "ab8540-usb", 1354c0eda9aeSLee Jones .num_resources = ARRAY_SIZE(ab8500_usb_resources), 1355c0eda9aeSLee Jones .resources = ab8500_usb_resources, 1356c0eda9aeSLee Jones }, 1357c0eda9aeSLee Jones { 1358c0eda9aeSLee Jones .name = "ab8540-codec", 1359c0eda9aeSLee Jones }, 1360c0eda9aeSLee Jones { 136144f72e53SVirupax Sadashivpetimath .name = "ab-iddet", 136244f72e53SVirupax Sadashivpetimath .num_resources = ARRAY_SIZE(ab8505_iddet_resources), 136344f72e53SVirupax Sadashivpetimath .resources = ab8505_iddet_resources, 136444f72e53SVirupax Sadashivpetimath }, 1365d6255529SLinus Walleij }; 1366d6255529SLinus Walleij 1367cca69b67SMattias Wallin static ssize_t show_chip_id(struct device *dev, 1368cca69b67SMattias Wallin struct device_attribute *attr, char *buf) 1369cca69b67SMattias Wallin { 1370cca69b67SMattias Wallin struct ab8500 *ab8500; 1371cca69b67SMattias Wallin 1372cca69b67SMattias Wallin ab8500 = dev_get_drvdata(dev); 1373e436ddffSLee Jones 1374cca69b67SMattias Wallin return sprintf(buf, "%#x\n", ab8500 ? ab8500->chip_id : -EINVAL); 1375cca69b67SMattias Wallin } 1376cca69b67SMattias Wallin 1377e5c238c3SMattias Wallin /* 1378e5c238c3SMattias Wallin * ab8500 has switched off due to (SWITCH_OFF_STATUS): 1379e5c238c3SMattias Wallin * 0x01 Swoff bit programming 1380e5c238c3SMattias Wallin * 0x02 Thermal protection activation 1381e5c238c3SMattias Wallin * 0x04 Vbat lower then BattOk falling threshold 1382e5c238c3SMattias Wallin * 0x08 Watchdog expired 1383e5c238c3SMattias Wallin * 0x10 Non presence of 32kHz clock 1384e5c238c3SMattias Wallin * 0x20 Battery level lower than power on reset threshold 1385e5c238c3SMattias Wallin * 0x40 Power on key 1 pressed longer than 10 seconds 1386e5c238c3SMattias Wallin * 0x80 DB8500 thermal shutdown 1387e5c238c3SMattias Wallin */ 1388e5c238c3SMattias Wallin static ssize_t show_switch_off_status(struct device *dev, 1389e5c238c3SMattias Wallin struct device_attribute *attr, char *buf) 1390e5c238c3SMattias Wallin { 1391e5c238c3SMattias Wallin int ret; 1392e5c238c3SMattias Wallin u8 value; 1393e5c238c3SMattias Wallin struct ab8500 *ab8500; 1394e5c238c3SMattias Wallin 1395e5c238c3SMattias Wallin ab8500 = dev_get_drvdata(dev); 1396e5c238c3SMattias Wallin ret = get_register_interruptible(ab8500, AB8500_RTC, 1397e5c238c3SMattias Wallin AB8500_SWITCH_OFF_STATUS, &value); 1398e5c238c3SMattias Wallin if (ret < 0) 1399e5c238c3SMattias Wallin return ret; 1400e5c238c3SMattias Wallin return sprintf(buf, "%#x\n", value); 1401e5c238c3SMattias Wallin } 1402e5c238c3SMattias Wallin 1403f04a9d8aSRajkumar Kasirajan /* use mask and set to override the register turn_on_stat value */ 1404f04a9d8aSRajkumar Kasirajan void ab8500_override_turn_on_stat(u8 mask, u8 set) 1405f04a9d8aSRajkumar Kasirajan { 1406f04a9d8aSRajkumar Kasirajan spin_lock(&on_stat_lock); 1407f04a9d8aSRajkumar Kasirajan turn_on_stat_mask = mask; 1408f04a9d8aSRajkumar Kasirajan turn_on_stat_set = set; 1409f04a9d8aSRajkumar Kasirajan spin_unlock(&on_stat_lock); 1410f04a9d8aSRajkumar Kasirajan } 1411f04a9d8aSRajkumar Kasirajan 1412b4a31037SAndrew Lynn /* 1413b4a31037SAndrew Lynn * ab8500 has turned on due to (TURN_ON_STATUS): 1414b4a31037SAndrew Lynn * 0x01 PORnVbat 1415b4a31037SAndrew Lynn * 0x02 PonKey1dbF 1416b4a31037SAndrew Lynn * 0x04 PonKey2dbF 1417b4a31037SAndrew Lynn * 0x08 RTCAlarm 1418b4a31037SAndrew Lynn * 0x10 MainChDet 1419b4a31037SAndrew Lynn * 0x20 VbusDet 1420b4a31037SAndrew Lynn * 0x40 UsbIDDetect 1421b4a31037SAndrew Lynn * 0x80 Reserved 1422b4a31037SAndrew Lynn */ 1423b4a31037SAndrew Lynn static ssize_t show_turn_on_status(struct device *dev, 1424b4a31037SAndrew Lynn struct device_attribute *attr, char *buf) 1425b4a31037SAndrew Lynn { 1426b4a31037SAndrew Lynn int ret; 1427b4a31037SAndrew Lynn u8 value; 1428b4a31037SAndrew Lynn struct ab8500 *ab8500; 1429b4a31037SAndrew Lynn 1430b4a31037SAndrew Lynn ab8500 = dev_get_drvdata(dev); 1431b4a31037SAndrew Lynn ret = get_register_interruptible(ab8500, AB8500_SYS_CTRL1_BLOCK, 1432b4a31037SAndrew Lynn AB8500_TURN_ON_STATUS, &value); 1433b4a31037SAndrew Lynn if (ret < 0) 1434b4a31037SAndrew Lynn return ret; 1435f04a9d8aSRajkumar Kasirajan 1436f04a9d8aSRajkumar Kasirajan /* 1437f04a9d8aSRajkumar Kasirajan * In L9540, turn_on_status register is not updated correctly if 1438f04a9d8aSRajkumar Kasirajan * the device is rebooted with AC/USB charger connected. Due to 1439f04a9d8aSRajkumar Kasirajan * this, the device boots android instead of entering into charge 1440f04a9d8aSRajkumar Kasirajan * only mode. Read the AC/USB status register to detect the charger 1441f04a9d8aSRajkumar Kasirajan * presence and update the turn on status manually. 1442f04a9d8aSRajkumar Kasirajan */ 1443f04a9d8aSRajkumar Kasirajan if (is_ab9540(ab8500)) { 1444f04a9d8aSRajkumar Kasirajan spin_lock(&on_stat_lock); 1445f04a9d8aSRajkumar Kasirajan value = (value & turn_on_stat_mask) | turn_on_stat_set; 1446f04a9d8aSRajkumar Kasirajan spin_unlock(&on_stat_lock); 1447f04a9d8aSRajkumar Kasirajan } 1448f04a9d8aSRajkumar Kasirajan 1449b4a31037SAndrew Lynn return sprintf(buf, "%#x\n", value); 1450b4a31037SAndrew Lynn } 1451b4a31037SAndrew Lynn 1452d6255529SLinus Walleij static ssize_t show_ab9540_dbbrstn(struct device *dev, 1453d6255529SLinus Walleij struct device_attribute *attr, char *buf) 1454d6255529SLinus Walleij { 1455d6255529SLinus Walleij struct ab8500 *ab8500; 1456d6255529SLinus Walleij int ret; 1457d6255529SLinus Walleij u8 value; 1458d6255529SLinus Walleij 1459d6255529SLinus Walleij ab8500 = dev_get_drvdata(dev); 1460d6255529SLinus Walleij 1461d6255529SLinus Walleij ret = get_register_interruptible(ab8500, AB8500_REGU_CTRL2, 1462d6255529SLinus Walleij AB9540_MODEM_CTRL2_REG, &value); 1463d6255529SLinus Walleij if (ret < 0) 1464d6255529SLinus Walleij return ret; 1465d6255529SLinus Walleij 1466d6255529SLinus Walleij return sprintf(buf, "%d\n", 1467d6255529SLinus Walleij (value & AB9540_MODEM_CTRL2_SWDBBRSTN_BIT) ? 1 : 0); 1468d6255529SLinus Walleij } 1469d6255529SLinus Walleij 1470d6255529SLinus Walleij static ssize_t store_ab9540_dbbrstn(struct device *dev, 1471d6255529SLinus Walleij struct device_attribute *attr, const char *buf, size_t count) 1472d6255529SLinus Walleij { 1473d6255529SLinus Walleij struct ab8500 *ab8500; 1474d6255529SLinus Walleij int ret = count; 1475d6255529SLinus Walleij int err; 1476d6255529SLinus Walleij u8 bitvalues; 1477d6255529SLinus Walleij 1478d6255529SLinus Walleij ab8500 = dev_get_drvdata(dev); 1479d6255529SLinus Walleij 1480d6255529SLinus Walleij if (count > 0) { 1481d6255529SLinus Walleij switch (buf[0]) { 1482d6255529SLinus Walleij case '0': 1483d6255529SLinus Walleij bitvalues = 0; 1484d6255529SLinus Walleij break; 1485d6255529SLinus Walleij case '1': 1486d6255529SLinus Walleij bitvalues = AB9540_MODEM_CTRL2_SWDBBRSTN_BIT; 1487d6255529SLinus Walleij break; 1488d6255529SLinus Walleij default: 1489d6255529SLinus Walleij goto exit; 1490d6255529SLinus Walleij } 1491d6255529SLinus Walleij 1492d6255529SLinus Walleij err = mask_and_set_register_interruptible(ab8500, 1493d6255529SLinus Walleij AB8500_REGU_CTRL2, AB9540_MODEM_CTRL2_REG, 1494d6255529SLinus Walleij AB9540_MODEM_CTRL2_SWDBBRSTN_BIT, bitvalues); 1495d6255529SLinus Walleij if (err) 1496d6255529SLinus Walleij dev_info(ab8500->dev, 1497d6255529SLinus Walleij "Failed to set DBBRSTN %c, err %#x\n", 1498d6255529SLinus Walleij buf[0], err); 1499d6255529SLinus Walleij } 1500d6255529SLinus Walleij 1501d6255529SLinus Walleij exit: 1502d6255529SLinus Walleij return ret; 1503d6255529SLinus Walleij } 1504d6255529SLinus Walleij 1505cca69b67SMattias Wallin static DEVICE_ATTR(chip_id, S_IRUGO, show_chip_id, NULL); 1506e5c238c3SMattias Wallin static DEVICE_ATTR(switch_off_status, S_IRUGO, show_switch_off_status, NULL); 1507b4a31037SAndrew Lynn static DEVICE_ATTR(turn_on_status, S_IRUGO, show_turn_on_status, NULL); 1508d6255529SLinus Walleij static DEVICE_ATTR(dbbrstn, S_IRUGO | S_IWUSR, 1509d6255529SLinus Walleij show_ab9540_dbbrstn, store_ab9540_dbbrstn); 1510cca69b67SMattias Wallin 1511cca69b67SMattias Wallin static struct attribute *ab8500_sysfs_entries[] = { 1512cca69b67SMattias Wallin &dev_attr_chip_id.attr, 1513e5c238c3SMattias Wallin &dev_attr_switch_off_status.attr, 1514b4a31037SAndrew Lynn &dev_attr_turn_on_status.attr, 1515cca69b67SMattias Wallin NULL, 1516cca69b67SMattias Wallin }; 1517cca69b67SMattias Wallin 1518d6255529SLinus Walleij static struct attribute *ab9540_sysfs_entries[] = { 1519d6255529SLinus Walleij &dev_attr_chip_id.attr, 1520d6255529SLinus Walleij &dev_attr_switch_off_status.attr, 1521d6255529SLinus Walleij &dev_attr_turn_on_status.attr, 1522d6255529SLinus Walleij &dev_attr_dbbrstn.attr, 1523d6255529SLinus Walleij NULL, 1524d6255529SLinus Walleij }; 1525d6255529SLinus Walleij 1526cca69b67SMattias Wallin static struct attribute_group ab8500_attr_group = { 1527cca69b67SMattias Wallin .attrs = ab8500_sysfs_entries, 1528cca69b67SMattias Wallin }; 1529cca69b67SMattias Wallin 1530d6255529SLinus Walleij static struct attribute_group ab9540_attr_group = { 1531d6255529SLinus Walleij .attrs = ab9540_sysfs_entries, 1532d6255529SLinus Walleij }; 1533d6255529SLinus Walleij 1534f791be49SBill Pemberton static int ab8500_probe(struct platform_device *pdev) 153562579266SRabin Vincent { 1536b04c530cSJonas Aaberg static char *switch_off_status[] = { 1537b04c530cSJonas Aaberg "Swoff bit programming", 1538b04c530cSJonas Aaberg "Thermal protection activation", 1539b04c530cSJonas Aaberg "Vbat lower then BattOk falling threshold", 1540b04c530cSJonas Aaberg "Watchdog expired", 1541b04c530cSJonas Aaberg "Non presence of 32kHz clock", 1542b04c530cSJonas Aaberg "Battery level lower than power on reset threshold", 1543b04c530cSJonas Aaberg "Power on key 1 pressed longer than 10 seconds", 1544b04c530cSJonas Aaberg "DB8500 thermal shutdown"}; 1545*abee26cdSMattias Wallin static char *turn_on_status[] = { 1546*abee26cdSMattias Wallin "Battery rising (Vbat)", 1547*abee26cdSMattias Wallin "Power On Key 1 dbF", 1548*abee26cdSMattias Wallin "Power On Key 2 dbF", 1549*abee26cdSMattias Wallin "RTC Alarm", 1550*abee26cdSMattias Wallin "Main Charger Detect", 1551*abee26cdSMattias Wallin "Vbus Detect (USB)", 1552*abee26cdSMattias Wallin "USB ID Detect", 1553*abee26cdSMattias Wallin "UART Factory Mode Detect"}; 1554d28f1db8SLee Jones struct ab8500_platform_data *plat = dev_get_platdata(&pdev->dev); 1555d28f1db8SLee Jones const struct platform_device_id *platid = platform_get_device_id(pdev); 15566bc4a568SLee Jones enum ab8500_version version = AB8500_VERSION_UNDEFINED; 15576bc4a568SLee Jones struct device_node *np = pdev->dev.of_node; 1558d28f1db8SLee Jones struct ab8500 *ab8500; 1559d28f1db8SLee Jones struct resource *resource; 156062579266SRabin Vincent int ret; 156162579266SRabin Vincent int i; 156247c16975SMattias Wallin u8 value; 156362579266SRabin Vincent 15648c4203cbSLee Jones ab8500 = devm_kzalloc(&pdev->dev, sizeof *ab8500, GFP_KERNEL); 1565d28f1db8SLee Jones if (!ab8500) 1566d28f1db8SLee Jones return -ENOMEM; 1567d28f1db8SLee Jones 156862579266SRabin Vincent if (plat) 156962579266SRabin Vincent ab8500->irq_base = plat->irq_base; 157062579266SRabin Vincent 1571d28f1db8SLee Jones ab8500->dev = &pdev->dev; 1572d28f1db8SLee Jones 1573d28f1db8SLee Jones resource = platform_get_resource(pdev, IORESOURCE_IRQ, 0); 15748c4203cbSLee Jones if (!resource) 15758c4203cbSLee Jones return -ENODEV; 1576d28f1db8SLee Jones 1577d28f1db8SLee Jones ab8500->irq = resource->start; 1578d28f1db8SLee Jones 1579822672a7SLee Jones ab8500->read = ab8500_prcmu_read; 1580822672a7SLee Jones ab8500->write = ab8500_prcmu_write; 1581822672a7SLee Jones ab8500->write_masked = ab8500_prcmu_write_masked; 1582d28f1db8SLee Jones 158362579266SRabin Vincent mutex_init(&ab8500->lock); 158462579266SRabin Vincent mutex_init(&ab8500->irq_lock); 1585112a80d2SJonas Aaberg atomic_set(&ab8500->transfer_ongoing, 0); 158662579266SRabin Vincent 1587d28f1db8SLee Jones platform_set_drvdata(pdev, ab8500); 1588d28f1db8SLee Jones 15896bc4a568SLee Jones if (platid) 15906bc4a568SLee Jones version = platid->driver_data; 15916bc4a568SLee Jones 15920f620837SLinus Walleij if (version != AB8500_VERSION_UNDEFINED) 15930f620837SLinus Walleij ab8500->version = version; 15940f620837SLinus Walleij else { 15950f620837SLinus Walleij ret = get_register_interruptible(ab8500, AB8500_MISC, 15960f620837SLinus Walleij AB8500_IC_NAME_REG, &value); 15970f620837SLinus Walleij if (ret < 0) 15988c4203cbSLee Jones return ret; 15990f620837SLinus Walleij 16000f620837SLinus Walleij ab8500->version = value; 16010f620837SLinus Walleij } 16020f620837SLinus Walleij 160347c16975SMattias Wallin ret = get_register_interruptible(ab8500, AB8500_MISC, 160447c16975SMattias Wallin AB8500_REV_REG, &value); 160562579266SRabin Vincent if (ret < 0) 16068c4203cbSLee Jones return ret; 160762579266SRabin Vincent 160847c16975SMattias Wallin ab8500->chip_id = value; 160962579266SRabin Vincent 16100f620837SLinus Walleij dev_info(ab8500->dev, "detected chip, %s rev. %1x.%1x\n", 16110f620837SLinus Walleij ab8500_version_str[ab8500->version], 16120f620837SLinus Walleij ab8500->chip_id >> 4, 16130f620837SLinus Walleij ab8500->chip_id & 0x0F); 16140f620837SLinus Walleij 16153e1a498fSLee Jones /* Configure AB8540 */ 16163e1a498fSLee Jones if (is_ab8540(ab8500)) { 16173e1a498fSLee Jones ab8500->mask_size = AB8540_NUM_IRQ_REGS; 16183e1a498fSLee Jones ab8500->irq_reg_offset = ab8540_irq_regoffset; 16193e1a498fSLee Jones ab8500->it_latchhier_num = AB8540_IT_LATCHHIER_NUM; 16203e1a498fSLee Jones }/* Configure AB8500 or AB9540 IRQ */ 16213e1a498fSLee Jones else if (is_ab9540(ab8500) || is_ab8505(ab8500)) { 1622d6255529SLinus Walleij ab8500->mask_size = AB9540_NUM_IRQ_REGS; 1623d6255529SLinus Walleij ab8500->irq_reg_offset = ab9540_irq_regoffset; 16243e1a498fSLee Jones ab8500->it_latchhier_num = AB8500_IT_LATCHHIER_NUM; 1625d6255529SLinus Walleij } else { 16262ced445eSLinus Walleij ab8500->mask_size = AB8500_NUM_IRQ_REGS; 16272ced445eSLinus Walleij ab8500->irq_reg_offset = ab8500_irq_regoffset; 16283e1a498fSLee Jones ab8500->it_latchhier_num = AB8500_IT_LATCHHIER_NUM; 1629d6255529SLinus Walleij } 16308c4203cbSLee Jones ab8500->mask = devm_kzalloc(&pdev->dev, ab8500->mask_size, GFP_KERNEL); 16312ced445eSLinus Walleij if (!ab8500->mask) 16322ced445eSLinus Walleij return -ENOMEM; 16338c4203cbSLee Jones ab8500->oldmask = devm_kzalloc(&pdev->dev, ab8500->mask_size, GFP_KERNEL); 16348c4203cbSLee Jones if (!ab8500->oldmask) 16358c4203cbSLee Jones return -ENOMEM; 16368c4203cbSLee Jones 1637e5c238c3SMattias Wallin /* 1638e5c238c3SMattias Wallin * ab8500 has switched off due to (SWITCH_OFF_STATUS): 1639e5c238c3SMattias Wallin * 0x01 Swoff bit programming 1640e5c238c3SMattias Wallin * 0x02 Thermal protection activation 1641e5c238c3SMattias Wallin * 0x04 Vbat lower then BattOk falling threshold 1642e5c238c3SMattias Wallin * 0x08 Watchdog expired 1643e5c238c3SMattias Wallin * 0x10 Non presence of 32kHz clock 1644e5c238c3SMattias Wallin * 0x20 Battery level lower than power on reset threshold 1645e5c238c3SMattias Wallin * 0x40 Power on key 1 pressed longer than 10 seconds 1646e5c238c3SMattias Wallin * 0x80 DB8500 thermal shutdown 1647e5c238c3SMattias Wallin */ 1648e5c238c3SMattias Wallin 1649e5c238c3SMattias Wallin ret = get_register_interruptible(ab8500, AB8500_RTC, 1650e5c238c3SMattias Wallin AB8500_SWITCH_OFF_STATUS, &value); 1651e5c238c3SMattias Wallin if (ret < 0) 1652e5c238c3SMattias Wallin return ret; 1653b04c530cSJonas Aaberg dev_info(ab8500->dev, "switch off cause(s) (%#x): ", value); 1654b04c530cSJonas Aaberg 1655b04c530cSJonas Aaberg if (value) { 1656b04c530cSJonas Aaberg for (i = 0; i < ARRAY_SIZE(switch_off_status); i++) { 1657b04c530cSJonas Aaberg if (value & 1) 1658b04c530cSJonas Aaberg printk(KERN_CONT " \"%s\"", 1659b04c530cSJonas Aaberg switch_off_status[i]); 1660b04c530cSJonas Aaberg value = value >> 1; 1661b04c530cSJonas Aaberg 1662b04c530cSJonas Aaberg } 1663b04c530cSJonas Aaberg printk(KERN_CONT "\n"); 1664b04c530cSJonas Aaberg } else { 1665b04c530cSJonas Aaberg printk(KERN_CONT " None\n"); 1666b04c530cSJonas Aaberg } 1667*abee26cdSMattias Wallin ret = get_register_interruptible(ab8500, AB8500_SYS_CTRL1_BLOCK, 1668*abee26cdSMattias Wallin AB8500_TURN_ON_STATUS, &value); 1669*abee26cdSMattias Wallin if (ret < 0) 1670*abee26cdSMattias Wallin return ret; 1671*abee26cdSMattias Wallin dev_info(ab8500->dev, "turn on reason(s) (%#x): ", value); 1672*abee26cdSMattias Wallin 1673*abee26cdSMattias Wallin if (value) { 1674*abee26cdSMattias Wallin for (i = 0; i < ARRAY_SIZE(turn_on_status); i++) { 1675*abee26cdSMattias Wallin if (value & 1) 1676*abee26cdSMattias Wallin printk("\"%s\" ", turn_on_status[i]); 1677*abee26cdSMattias Wallin value = value >> 1; 1678*abee26cdSMattias Wallin } 1679*abee26cdSMattias Wallin printk("\n"); 1680*abee26cdSMattias Wallin } else { 1681*abee26cdSMattias Wallin printk("None\n"); 1682*abee26cdSMattias Wallin } 1683e5c238c3SMattias Wallin 168462579266SRabin Vincent if (plat && plat->init) 168562579266SRabin Vincent plat->init(ab8500); 1686*abee26cdSMattias Wallin 1687f04a9d8aSRajkumar Kasirajan if (is_ab9540(ab8500)) { 1688f04a9d8aSRajkumar Kasirajan ret = get_register_interruptible(ab8500, AB8500_CHARGER, 1689f04a9d8aSRajkumar Kasirajan AB8500_CH_USBCH_STAT1_REG, &value); 1690f04a9d8aSRajkumar Kasirajan if (ret < 0) 1691f04a9d8aSRajkumar Kasirajan return ret; 1692f04a9d8aSRajkumar Kasirajan if ((value & VBUS_DET_DBNC1) && (value & VBUS_DET_DBNC100)) 1693f04a9d8aSRajkumar Kasirajan ab8500_override_turn_on_stat(~AB8500_POW_KEY_1_ON, 1694f04a9d8aSRajkumar Kasirajan AB8500_VBUS_DET); 1695f04a9d8aSRajkumar Kasirajan } 169662579266SRabin Vincent 169762579266SRabin Vincent /* Clear and mask all interrupts */ 16982ced445eSLinus Walleij for (i = 0; i < ab8500->mask_size; i++) { 16990f620837SLinus Walleij /* 17000f620837SLinus Walleij * Interrupt register 12 doesn't exist prior to AB8500 version 17010f620837SLinus Walleij * 2.0 17020f620837SLinus Walleij */ 17030f620837SLinus Walleij if (ab8500->irq_reg_offset[i] == 11 && 17040f620837SLinus Walleij is_ab8500_1p1_or_earlier(ab8500)) 170592d50a41SMattias Wallin continue; 170662579266SRabin Vincent 17073e1a498fSLee Jones if (ab8500->irq_reg_offset[i] < 0) 17083e1a498fSLee Jones continue; 17093e1a498fSLee Jones 171047c16975SMattias Wallin get_register_interruptible(ab8500, AB8500_INTERRUPT, 17112ced445eSLinus Walleij AB8500_IT_LATCH1_REG + ab8500->irq_reg_offset[i], 171292d50a41SMattias Wallin &value); 171347c16975SMattias Wallin set_register_interruptible(ab8500, AB8500_INTERRUPT, 17142ced445eSLinus Walleij AB8500_IT_MASK1_REG + ab8500->irq_reg_offset[i], 0xff); 171562579266SRabin Vincent } 171662579266SRabin Vincent 171747c16975SMattias Wallin ret = abx500_register_ops(ab8500->dev, &ab8500_ops); 171847c16975SMattias Wallin if (ret) 17198c4203cbSLee Jones return ret; 172047c16975SMattias Wallin 17212ced445eSLinus Walleij for (i = 0; i < ab8500->mask_size; i++) 172262579266SRabin Vincent ab8500->mask[i] = ab8500->oldmask[i] = 0xff; 172362579266SRabin Vincent 172406e589efSLee Jones ret = ab8500_irq_init(ab8500, np); 172562579266SRabin Vincent if (ret) 17268c4203cbSLee Jones return ret; 172762579266SRabin Vincent 17287ccfe9b1SMichel JAOUEN /* Activate this feature only in ab9540 */ 17297ccfe9b1SMichel JAOUEN /* till tests are done on ab8500 1p2 or later*/ 1730e436ddffSLee Jones if (is_ab9540(ab8500) || is_ab8540(ab8500)) 17318c4203cbSLee Jones ret = devm_request_threaded_irq(&pdev->dev, ab8500->irq, NULL, 17327ccfe9b1SMichel JAOUEN ab8500_hierarchical_irq, 17337ccfe9b1SMichel JAOUEN IRQF_ONESHOT | IRQF_NO_SUSPEND, 17347ccfe9b1SMichel JAOUEN "ab8500", ab8500); 173506e589efSLee Jones } 173606e589efSLee Jones else { 17378c4203cbSLee Jones ret = devm_request_threaded_irq(&pdev->dev, ab8500->irq, NULL, 17387ccfe9b1SMichel JAOUEN ab8500_irq, 17394f079985SMattias Wallin IRQF_ONESHOT | IRQF_NO_SUSPEND, 17404f079985SMattias Wallin "ab8500", ab8500); 174162579266SRabin Vincent if (ret) 17428c4203cbSLee Jones return ret; 174362579266SRabin Vincent } 174462579266SRabin Vincent 1745d6255529SLinus Walleij if (is_ab9540(ab8500)) 1746d6255529SLinus Walleij ret = mfd_add_devices(ab8500->dev, 0, ab9540_devs, 1747d6255529SLinus Walleij ARRAY_SIZE(ab9540_devs), NULL, 174855692af5SMark Brown ab8500->irq_base, ab8500->domain); 1749c0eda9aeSLee Jones else if (is_ab8540(ab8500)) 1750c0eda9aeSLee Jones ret = mfd_add_devices(ab8500->dev, 0, ab8540_devs, 1751c0eda9aeSLee Jones ARRAY_SIZE(ab8540_devs), NULL, 1752c0eda9aeSLee Jones ab8500->irq_base, ab8500->domain); 1753c0eda9aeSLee Jones else if (is_ab8505(ab8500)) 1754c0eda9aeSLee Jones ret = mfd_add_devices(ab8500->dev, 0, ab8505_devs, 1755c0eda9aeSLee Jones ARRAY_SIZE(ab8505_devs), NULL, 1756c0eda9aeSLee Jones ab8500->irq_base, ab8500->domain); 1757d6255529SLinus Walleij else 1758549931f9SSundar R Iyer ret = mfd_add_devices(ab8500->dev, 0, ab8500_devs, 175944f72e53SVirupax Sadashivpetimath ARRAY_SIZE(ab8500_devs), NULL, 176055692af5SMark Brown ab8500->irq_base, ab8500->domain); 17616bc4a568SLee Jones if (ret) 17628c4203cbSLee Jones return ret; 176344f72e53SVirupax Sadashivpetimath 17646ef9418cSRickard Andersson if (!no_bm) { 17656ef9418cSRickard Andersson /* Add battery management devices */ 17666ef9418cSRickard Andersson ret = mfd_add_devices(ab8500->dev, 0, ab8500_bm_devs, 17676ef9418cSRickard Andersson ARRAY_SIZE(ab8500_bm_devs), NULL, 176855692af5SMark Brown ab8500->irq_base, ab8500->domain); 17696ef9418cSRickard Andersson if (ret) 17706ef9418cSRickard Andersson dev_err(ab8500->dev, "error adding bm devices\n"); 17716ef9418cSRickard Andersson } 17726ef9418cSRickard Andersson 1773e436ddffSLee Jones if (((is_ab8505(ab8500) || is_ab9540(ab8500)) && 1774e436ddffSLee Jones ab8500->chip_id >= AB8500_CUT2P0) || is_ab8540(ab8500)) 1775d6255529SLinus Walleij ret = sysfs_create_group(&ab8500->dev->kobj, 1776d6255529SLinus Walleij &ab9540_attr_group); 1777d6255529SLinus Walleij else 1778d6255529SLinus Walleij ret = sysfs_create_group(&ab8500->dev->kobj, 1779d6255529SLinus Walleij &ab8500_attr_group); 1780cca69b67SMattias Wallin if (ret) 1781cca69b67SMattias Wallin dev_err(ab8500->dev, "error creating sysfs entries\n"); 178206e589efSLee Jones 178362579266SRabin Vincent return ret; 178462579266SRabin Vincent } 178562579266SRabin Vincent 17864740f73fSBill Pemberton static int ab8500_remove(struct platform_device *pdev) 178762579266SRabin Vincent { 1788d28f1db8SLee Jones struct ab8500 *ab8500 = platform_get_drvdata(pdev); 1789d28f1db8SLee Jones 1790e436ddffSLee Jones if (((is_ab8505(ab8500) || is_ab9540(ab8500)) && 1791e436ddffSLee Jones ab8500->chip_id >= AB8500_CUT2P0) || is_ab8540(ab8500)) 1792d6255529SLinus Walleij sysfs_remove_group(&ab8500->dev->kobj, &ab9540_attr_group); 1793d6255529SLinus Walleij else 1794cca69b67SMattias Wallin sysfs_remove_group(&ab8500->dev->kobj, &ab8500_attr_group); 179506e589efSLee Jones 179662579266SRabin Vincent mfd_remove_devices(ab8500->dev); 179762579266SRabin Vincent 179862579266SRabin Vincent return 0; 179962579266SRabin Vincent } 180062579266SRabin Vincent 1801d28f1db8SLee Jones static const struct platform_device_id ab8500_id[] = { 1802d28f1db8SLee Jones { "ab8500-core", AB8500_VERSION_AB8500 }, 1803d28f1db8SLee Jones { "ab8505-i2c", AB8500_VERSION_AB8505 }, 1804d28f1db8SLee Jones { "ab9540-i2c", AB8500_VERSION_AB9540 }, 1805d28f1db8SLee Jones { "ab8540-i2c", AB8500_VERSION_AB8540 }, 1806d28f1db8SLee Jones { } 1807d28f1db8SLee Jones }; 1808d28f1db8SLee Jones 1809d28f1db8SLee Jones static struct platform_driver ab8500_core_driver = { 1810d28f1db8SLee Jones .driver = { 1811d28f1db8SLee Jones .name = "ab8500-core", 1812d28f1db8SLee Jones .owner = THIS_MODULE, 1813d28f1db8SLee Jones }, 1814d28f1db8SLee Jones .probe = ab8500_probe, 181584449216SBill Pemberton .remove = ab8500_remove, 1816d28f1db8SLee Jones .id_table = ab8500_id, 1817d28f1db8SLee Jones }; 1818d28f1db8SLee Jones 1819d28f1db8SLee Jones static int __init ab8500_core_init(void) 1820d28f1db8SLee Jones { 1821d28f1db8SLee Jones return platform_driver_register(&ab8500_core_driver); 1822d28f1db8SLee Jones } 1823d28f1db8SLee Jones 1824d28f1db8SLee Jones static void __exit ab8500_core_exit(void) 1825d28f1db8SLee Jones { 1826d28f1db8SLee Jones platform_driver_unregister(&ab8500_core_driver); 1827d28f1db8SLee Jones } 1828ba7cbc3eSLee Jones core_initcall(ab8500_core_init); 1829d28f1db8SLee Jones module_exit(ab8500_core_exit); 1830d28f1db8SLee Jones 1831adceed62SMattias Wallin MODULE_AUTHOR("Mattias Wallin, Srinidhi Kasagar, Rabin Vincent"); 183262579266SRabin Vincent MODULE_DESCRIPTION("AB8500 MFD core"); 183362579266SRabin Vincent MODULE_LICENSE("GPL v2"); 1834