10376148fSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only 262579266SRabin Vincent /* 362579266SRabin Vincent * Copyright (C) ST-Ericsson SA 2010 462579266SRabin Vincent * 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> 1731cbae22SPaul Gortmaker #include <linux/moduleparam.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> 22d28f1db8SLee Jones #include <linux/mfd/dbx500-prcmu.h> 236bc4a568SLee Jones #include <linux/of.h> 246bc4a568SLee Jones #include <linux/of_device.h> 2562579266SRabin Vincent 2662579266SRabin Vincent /* 2762579266SRabin Vincent * Interrupt register offsets 2862579266SRabin Vincent * Bank : 0x0E 2962579266SRabin Vincent */ 3047c16975SMattias Wallin #define AB8500_IT_SOURCE1_REG 0x00 3147c16975SMattias Wallin #define AB8500_IT_SOURCE2_REG 0x01 3247c16975SMattias Wallin #define AB8500_IT_SOURCE3_REG 0x02 3347c16975SMattias Wallin #define AB8500_IT_SOURCE4_REG 0x03 3447c16975SMattias Wallin #define AB8500_IT_SOURCE5_REG 0x04 3547c16975SMattias Wallin #define AB8500_IT_SOURCE6_REG 0x05 3647c16975SMattias Wallin #define AB8500_IT_SOURCE7_REG 0x06 3747c16975SMattias Wallin #define AB8500_IT_SOURCE8_REG 0x07 38d6255529SLinus Walleij #define AB9540_IT_SOURCE13_REG 0x0C 3947c16975SMattias Wallin #define AB8500_IT_SOURCE19_REG 0x12 4047c16975SMattias Wallin #define AB8500_IT_SOURCE20_REG 0x13 4147c16975SMattias Wallin #define AB8500_IT_SOURCE21_REG 0x14 4247c16975SMattias Wallin #define AB8500_IT_SOURCE22_REG 0x15 4347c16975SMattias Wallin #define AB8500_IT_SOURCE23_REG 0x16 4447c16975SMattias Wallin #define AB8500_IT_SOURCE24_REG 0x17 4562579266SRabin Vincent 4662579266SRabin Vincent /* 4762579266SRabin Vincent * latch registers 4862579266SRabin Vincent */ 4947c16975SMattias Wallin #define AB8500_IT_LATCH1_REG 0x20 5047c16975SMattias Wallin #define AB8500_IT_LATCH2_REG 0x21 5147c16975SMattias Wallin #define AB8500_IT_LATCH3_REG 0x22 5247c16975SMattias Wallin #define AB8500_IT_LATCH4_REG 0x23 5347c16975SMattias Wallin #define AB8500_IT_LATCH5_REG 0x24 5447c16975SMattias Wallin #define AB8500_IT_LATCH6_REG 0x25 5547c16975SMattias Wallin #define AB8500_IT_LATCH7_REG 0x26 5647c16975SMattias Wallin #define AB8500_IT_LATCH8_REG 0x27 5747c16975SMattias Wallin #define AB8500_IT_LATCH9_REG 0x28 5847c16975SMattias Wallin #define AB8500_IT_LATCH10_REG 0x29 5992d50a41SMattias Wallin #define AB8500_IT_LATCH12_REG 0x2B 60d6255529SLinus Walleij #define AB9540_IT_LATCH13_REG 0x2C 6147c16975SMattias Wallin #define AB8500_IT_LATCH19_REG 0x32 6247c16975SMattias Wallin #define AB8500_IT_LATCH20_REG 0x33 6347c16975SMattias Wallin #define AB8500_IT_LATCH21_REG 0x34 6447c16975SMattias Wallin #define AB8500_IT_LATCH22_REG 0x35 6547c16975SMattias Wallin #define AB8500_IT_LATCH23_REG 0x36 6647c16975SMattias Wallin #define AB8500_IT_LATCH24_REG 0x37 6762579266SRabin Vincent 6862579266SRabin Vincent /* 6962579266SRabin Vincent * mask registers 7062579266SRabin Vincent */ 7162579266SRabin Vincent 7247c16975SMattias Wallin #define AB8500_IT_MASK1_REG 0x40 7347c16975SMattias Wallin #define AB8500_IT_MASK2_REG 0x41 7447c16975SMattias Wallin #define AB8500_IT_MASK3_REG 0x42 7547c16975SMattias Wallin #define AB8500_IT_MASK4_REG 0x43 7647c16975SMattias Wallin #define AB8500_IT_MASK5_REG 0x44 7747c16975SMattias Wallin #define AB8500_IT_MASK6_REG 0x45 7847c16975SMattias Wallin #define AB8500_IT_MASK7_REG 0x46 7947c16975SMattias Wallin #define AB8500_IT_MASK8_REG 0x47 8047c16975SMattias Wallin #define AB8500_IT_MASK9_REG 0x48 8147c16975SMattias Wallin #define AB8500_IT_MASK10_REG 0x49 8247c16975SMattias Wallin #define AB8500_IT_MASK11_REG 0x4A 8347c16975SMattias Wallin #define AB8500_IT_MASK12_REG 0x4B 8447c16975SMattias Wallin #define AB8500_IT_MASK13_REG 0x4C 8547c16975SMattias Wallin #define AB8500_IT_MASK14_REG 0x4D 8647c16975SMattias Wallin #define AB8500_IT_MASK15_REG 0x4E 8747c16975SMattias Wallin #define AB8500_IT_MASK16_REG 0x4F 8847c16975SMattias Wallin #define AB8500_IT_MASK17_REG 0x50 8947c16975SMattias Wallin #define AB8500_IT_MASK18_REG 0x51 9047c16975SMattias Wallin #define AB8500_IT_MASK19_REG 0x52 9147c16975SMattias Wallin #define AB8500_IT_MASK20_REG 0x53 9247c16975SMattias Wallin #define AB8500_IT_MASK21_REG 0x54 9347c16975SMattias Wallin #define AB8500_IT_MASK22_REG 0x55 9447c16975SMattias Wallin #define AB8500_IT_MASK23_REG 0x56 9547c16975SMattias Wallin #define AB8500_IT_MASK24_REG 0x57 96a29264b6SLee Jones #define AB8500_IT_MASK25_REG 0x58 9762579266SRabin Vincent 987ccfe9b1SMichel JAOUEN /* 997ccfe9b1SMichel JAOUEN * latch hierarchy registers 1007ccfe9b1SMichel JAOUEN */ 1017ccfe9b1SMichel JAOUEN #define AB8500_IT_LATCHHIER1_REG 0x60 1027ccfe9b1SMichel JAOUEN #define AB8500_IT_LATCHHIER2_REG 0x61 1037ccfe9b1SMichel JAOUEN #define AB8500_IT_LATCHHIER3_REG 0x62 1043e1a498fSLee Jones #define AB8540_IT_LATCHHIER4_REG 0x63 1057ccfe9b1SMichel JAOUEN 1067ccfe9b1SMichel JAOUEN #define AB8500_IT_LATCHHIER_NUM 3 1073e1a498fSLee Jones #define AB8540_IT_LATCHHIER_NUM 4 1087ccfe9b1SMichel JAOUEN 10947c16975SMattias Wallin #define AB8500_REV_REG 0x80 1100f620837SLinus Walleij #define AB8500_IC_NAME_REG 0x82 111e5c238c3SMattias Wallin #define AB8500_SWITCH_OFF_STATUS 0x00 11262579266SRabin Vincent 113b4a31037SAndrew Lynn #define AB8500_TURN_ON_STATUS 0x00 11493ff722eSLee Jones #define AB8505_TURN_ON_STATUS_2 0x04 115b4a31037SAndrew Lynn 116f04a9d8aSRajkumar Kasirajan #define AB8500_CH_USBCH_STAT1_REG 0x02 117f04a9d8aSRajkumar Kasirajan #define VBUS_DET_DBNC100 0x02 118f04a9d8aSRajkumar Kasirajan #define VBUS_DET_DBNC1 0x01 119f04a9d8aSRajkumar Kasirajan 120f04a9d8aSRajkumar Kasirajan static DEFINE_SPINLOCK(on_stat_lock); 121f04a9d8aSRajkumar Kasirajan static u8 turn_on_stat_mask = 0xFF; 122f04a9d8aSRajkumar Kasirajan static u8 turn_on_stat_set; 1236ef9418cSRickard Andersson 124d6255529SLinus Walleij #define AB9540_MODEM_CTRL2_REG 0x23 125d6255529SLinus Walleij #define AB9540_MODEM_CTRL2_SWDBBRSTN_BIT BIT(2) 126d6255529SLinus Walleij 12762579266SRabin Vincent /* 12862579266SRabin Vincent * Map interrupt numbers to the LATCH and MASK register offsets, Interrupt 1292ced445eSLinus Walleij * numbers are indexed into this array with (num / 8). The interupts are 1302ced445eSLinus Walleij * defined in linux/mfd/ab8500.h 13162579266SRabin Vincent * 13262579266SRabin Vincent * This is one off from the register names, i.e. AB8500_IT_MASK1_REG is at 13362579266SRabin Vincent * offset 0. 13462579266SRabin Vincent */ 1352ced445eSLinus Walleij /* AB8500 support */ 13662579266SRabin Vincent static const int ab8500_irq_regoffset[AB8500_NUM_IRQ_REGS] = { 13792d50a41SMattias Wallin 0, 1, 2, 3, 4, 6, 7, 8, 9, 11, 18, 19, 20, 21, 13862579266SRabin Vincent }; 13962579266SRabin Vincent 140a29264b6SLee Jones /* AB9540 / AB8505 support */ 141d6255529SLinus Walleij static const int ab9540_irq_regoffset[AB9540_NUM_IRQ_REGS] = { 142a29264b6SLee Jones 0, 1, 2, 3, 4, 6, 7, 8, 9, 11, 18, 19, 20, 21, 12, 13, 24, 5, 22, 23 143d6255529SLinus Walleij }; 144d6255529SLinus Walleij 1453e1a498fSLee Jones /* AB8540 support */ 1463e1a498fSLee Jones static const int ab8540_irq_regoffset[AB8540_NUM_IRQ_REGS] = { 1477ccf40b1SLee Jones 0, 1, 2, 3, 4, -1, -1, -1, -1, 11, 18, 19, 20, 21, 12, 13, 24, 5, 22, 1487ccf40b1SLee Jones 23, 25, 26, 27, 28, 29, 30, 31, 1493e1a498fSLee Jones }; 1503e1a498fSLee Jones 1510f620837SLinus Walleij static const char ab8500_version_str[][7] = { 1520f620837SLinus Walleij [AB8500_VERSION_AB8500] = "AB8500", 1530f620837SLinus Walleij [AB8500_VERSION_AB8505] = "AB8505", 1540f620837SLinus Walleij [AB8500_VERSION_AB9540] = "AB9540", 1550f620837SLinus Walleij [AB8500_VERSION_AB8540] = "AB8540", 1560f620837SLinus Walleij }; 1570f620837SLinus Walleij 158822672a7SLee Jones static int ab8500_prcmu_write(struct ab8500 *ab8500, u16 addr, u8 data) 159d28f1db8SLee Jones { 160d28f1db8SLee Jones int ret; 161d28f1db8SLee Jones 162d28f1db8SLee Jones ret = prcmu_abb_write((u8)(addr >> 8), (u8)(addr & 0xFF), &data, 1); 163d28f1db8SLee Jones if (ret < 0) 164d28f1db8SLee Jones dev_err(ab8500->dev, "prcmu i2c error %d\n", ret); 165d28f1db8SLee Jones return ret; 166d28f1db8SLee Jones } 167d28f1db8SLee Jones 168822672a7SLee Jones static int ab8500_prcmu_write_masked(struct ab8500 *ab8500, u16 addr, u8 mask, 169d28f1db8SLee Jones u8 data) 170d28f1db8SLee Jones { 171d28f1db8SLee Jones int ret; 172d28f1db8SLee Jones 173d28f1db8SLee Jones ret = prcmu_abb_write_masked((u8)(addr >> 8), (u8)(addr & 0xFF), &data, 174d28f1db8SLee Jones &mask, 1); 175d28f1db8SLee Jones if (ret < 0) 176d28f1db8SLee Jones dev_err(ab8500->dev, "prcmu i2c error %d\n", ret); 177d28f1db8SLee Jones return ret; 178d28f1db8SLee Jones } 179d28f1db8SLee Jones 180822672a7SLee Jones static int ab8500_prcmu_read(struct ab8500 *ab8500, u16 addr) 181d28f1db8SLee Jones { 182d28f1db8SLee Jones int ret; 183d28f1db8SLee Jones u8 data; 184d28f1db8SLee Jones 185d28f1db8SLee Jones ret = prcmu_abb_read((u8)(addr >> 8), (u8)(addr & 0xFF), &data, 1); 186d28f1db8SLee Jones if (ret < 0) { 187d28f1db8SLee Jones dev_err(ab8500->dev, "prcmu i2c error %d\n", ret); 188d28f1db8SLee Jones return ret; 189d28f1db8SLee Jones } 190d28f1db8SLee Jones return (int)data; 191d28f1db8SLee Jones } 192d28f1db8SLee Jones 19347c16975SMattias Wallin static int ab8500_get_chip_id(struct device *dev) 19447c16975SMattias Wallin { 1956bce7bf1SMattias Wallin struct ab8500 *ab8500; 1966bce7bf1SMattias Wallin 1976bce7bf1SMattias Wallin if (!dev) 1986bce7bf1SMattias Wallin return -EINVAL; 1996bce7bf1SMattias Wallin ab8500 = dev_get_drvdata(dev->parent); 2006bce7bf1SMattias Wallin return ab8500 ? (int)ab8500->chip_id : -EINVAL; 20147c16975SMattias Wallin } 20247c16975SMattias Wallin 20347c16975SMattias Wallin static int set_register_interruptible(struct ab8500 *ab8500, u8 bank, 20447c16975SMattias Wallin u8 reg, u8 data) 20562579266SRabin Vincent { 20662579266SRabin Vincent int ret; 20747c16975SMattias Wallin /* 20847c16975SMattias Wallin * Put the u8 bank and u8 register together into a an u16. 20947c16975SMattias Wallin * The bank on higher 8 bits and register in lower 8 bits. 210500e69a1SLee Jones */ 21147c16975SMattias Wallin u16 addr = ((u16)bank) << 8 | reg; 21262579266SRabin Vincent 21362579266SRabin Vincent dev_vdbg(ab8500->dev, "wr: addr %#x <= %#x\n", addr, data); 21462579266SRabin Vincent 215392cbd1eSRabin Vincent mutex_lock(&ab8500->lock); 21647c16975SMattias Wallin 21747c16975SMattias Wallin ret = ab8500->write(ab8500, addr, data); 21847c16975SMattias Wallin if (ret < 0) 21947c16975SMattias Wallin dev_err(ab8500->dev, "failed to write reg %#x: %d\n", 22047c16975SMattias Wallin addr, ret); 22147c16975SMattias Wallin mutex_unlock(&ab8500->lock); 22247c16975SMattias Wallin 22347c16975SMattias Wallin return ret; 22447c16975SMattias Wallin } 22547c16975SMattias Wallin 22647c16975SMattias Wallin static int ab8500_set_register(struct device *dev, u8 bank, 22747c16975SMattias Wallin u8 reg, u8 value) 22847c16975SMattias Wallin { 229112a80d2SJonas Aaberg int ret; 23047c16975SMattias Wallin struct ab8500 *ab8500 = dev_get_drvdata(dev->parent); 23147c16975SMattias Wallin 232112a80d2SJonas Aaberg atomic_inc(&ab8500->transfer_ongoing); 233112a80d2SJonas Aaberg ret = set_register_interruptible(ab8500, bank, reg, value); 234112a80d2SJonas Aaberg atomic_dec(&ab8500->transfer_ongoing); 235112a80d2SJonas Aaberg return ret; 23647c16975SMattias Wallin } 23747c16975SMattias Wallin 23847c16975SMattias Wallin static int get_register_interruptible(struct ab8500 *ab8500, u8 bank, 23947c16975SMattias Wallin u8 reg, u8 *value) 24047c16975SMattias Wallin { 24147c16975SMattias Wallin int ret; 24247c16975SMattias Wallin u16 addr = ((u16)bank) << 8 | reg; 24347c16975SMattias Wallin 244392cbd1eSRabin Vincent mutex_lock(&ab8500->lock); 24547c16975SMattias Wallin 24647c16975SMattias Wallin ret = ab8500->read(ab8500, addr); 24747c16975SMattias Wallin if (ret < 0) 24847c16975SMattias Wallin dev_err(ab8500->dev, "failed to read reg %#x: %d\n", 24947c16975SMattias Wallin addr, ret); 25047c16975SMattias Wallin else 25147c16975SMattias Wallin *value = ret; 25247c16975SMattias Wallin 25347c16975SMattias Wallin mutex_unlock(&ab8500->lock); 25447c16975SMattias Wallin dev_vdbg(ab8500->dev, "rd: addr %#x => data %#x\n", addr, ret); 25547c16975SMattias Wallin 25610628e3eSDan Carpenter return (ret < 0) ? ret : 0; 25747c16975SMattias Wallin } 25847c16975SMattias Wallin 25947c16975SMattias Wallin static int ab8500_get_register(struct device *dev, u8 bank, 26047c16975SMattias Wallin u8 reg, u8 *value) 26147c16975SMattias Wallin { 262112a80d2SJonas Aaberg int ret; 26347c16975SMattias Wallin struct ab8500 *ab8500 = dev_get_drvdata(dev->parent); 26447c16975SMattias Wallin 265112a80d2SJonas Aaberg atomic_inc(&ab8500->transfer_ongoing); 266112a80d2SJonas Aaberg ret = get_register_interruptible(ab8500, bank, reg, value); 267112a80d2SJonas Aaberg atomic_dec(&ab8500->transfer_ongoing); 268112a80d2SJonas Aaberg return ret; 26947c16975SMattias Wallin } 27047c16975SMattias Wallin 27147c16975SMattias Wallin static int mask_and_set_register_interruptible(struct ab8500 *ab8500, u8 bank, 27247c16975SMattias Wallin u8 reg, u8 bitmask, u8 bitvalues) 27347c16975SMattias Wallin { 27447c16975SMattias Wallin int ret; 27547c16975SMattias Wallin u16 addr = ((u16)bank) << 8 | reg; 27647c16975SMattias Wallin 277392cbd1eSRabin Vincent mutex_lock(&ab8500->lock); 27847c16975SMattias Wallin 279bc628fd1SMattias Nilsson if (ab8500->write_masked == NULL) { 280bc628fd1SMattias Nilsson u8 data; 281bc628fd1SMattias Nilsson 28247c16975SMattias Wallin ret = ab8500->read(ab8500, addr); 28347c16975SMattias Wallin if (ret < 0) { 28447c16975SMattias Wallin dev_err(ab8500->dev, "failed to read reg %#x: %d\n", 28547c16975SMattias Wallin addr, ret); 28647c16975SMattias Wallin goto out; 28747c16975SMattias Wallin } 28847c16975SMattias Wallin 28947c16975SMattias Wallin data = (u8)ret; 29047c16975SMattias Wallin data = (~bitmask & data) | (bitmask & bitvalues); 29147c16975SMattias Wallin 29262579266SRabin Vincent ret = ab8500->write(ab8500, addr, data); 29362579266SRabin Vincent if (ret < 0) 29462579266SRabin Vincent dev_err(ab8500->dev, "failed to write reg %#x: %d\n", 29562579266SRabin Vincent addr, ret); 29662579266SRabin Vincent 297bc628fd1SMattias Nilsson dev_vdbg(ab8500->dev, "mask: addr %#x => data %#x\n", addr, 298bc628fd1SMattias Nilsson data); 299bc628fd1SMattias Nilsson goto out; 300bc628fd1SMattias Nilsson } 301bc628fd1SMattias Nilsson ret = ab8500->write_masked(ab8500, addr, bitmask, bitvalues); 302bc628fd1SMattias Nilsson if (ret < 0) 303bc628fd1SMattias Nilsson dev_err(ab8500->dev, "failed to modify reg %#x: %d\n", addr, 304bc628fd1SMattias Nilsson ret); 30562579266SRabin Vincent out: 30662579266SRabin Vincent mutex_unlock(&ab8500->lock); 30762579266SRabin Vincent return ret; 30862579266SRabin Vincent } 30947c16975SMattias Wallin 31047c16975SMattias Wallin static int ab8500_mask_and_set_register(struct device *dev, 31147c16975SMattias Wallin u8 bank, u8 reg, u8 bitmask, u8 bitvalues) 31247c16975SMattias Wallin { 313112a80d2SJonas Aaberg int ret; 31447c16975SMattias Wallin struct ab8500 *ab8500 = dev_get_drvdata(dev->parent); 31547c16975SMattias Wallin 316112a80d2SJonas Aaberg atomic_inc(&ab8500->transfer_ongoing); 317112a80d2SJonas Aaberg ret = mask_and_set_register_interruptible(ab8500, bank, reg, 31847c16975SMattias Wallin bitmask, bitvalues); 319112a80d2SJonas Aaberg atomic_dec(&ab8500->transfer_ongoing); 320112a80d2SJonas Aaberg return ret; 32147c16975SMattias Wallin } 32247c16975SMattias Wallin 32347c16975SMattias Wallin static struct abx500_ops ab8500_ops = { 32447c16975SMattias Wallin .get_chip_id = ab8500_get_chip_id, 32547c16975SMattias Wallin .get_register = ab8500_get_register, 32647c16975SMattias Wallin .set_register = ab8500_set_register, 32747c16975SMattias Wallin .get_register_page = NULL, 32847c16975SMattias Wallin .set_register_page = NULL, 32947c16975SMattias Wallin .mask_and_set_register = ab8500_mask_and_set_register, 33047c16975SMattias Wallin .event_registers_startup_state_get = NULL, 33147c16975SMattias Wallin .startup_irq_enabled = NULL, 3321d843a6cSMian Yousaf Kaukab .dump_all_banks = ab8500_dump_all_banks, 33347c16975SMattias Wallin }; 33462579266SRabin Vincent 3359505a0a0SMark Brown static void ab8500_irq_lock(struct irq_data *data) 33662579266SRabin Vincent { 3379505a0a0SMark Brown struct ab8500 *ab8500 = irq_data_get_irq_chip_data(data); 33862579266SRabin Vincent 33962579266SRabin Vincent mutex_lock(&ab8500->irq_lock); 340112a80d2SJonas Aaberg atomic_inc(&ab8500->transfer_ongoing); 34162579266SRabin Vincent } 34262579266SRabin Vincent 3439505a0a0SMark Brown static void ab8500_irq_sync_unlock(struct irq_data *data) 34462579266SRabin Vincent { 3459505a0a0SMark Brown struct ab8500 *ab8500 = irq_data_get_irq_chip_data(data); 34662579266SRabin Vincent int i; 34762579266SRabin Vincent 3482ced445eSLinus Walleij for (i = 0; i < ab8500->mask_size; i++) { 34962579266SRabin Vincent u8 old = ab8500->oldmask[i]; 35062579266SRabin Vincent u8 new = ab8500->mask[i]; 35162579266SRabin Vincent int reg; 35262579266SRabin Vincent 35362579266SRabin Vincent if (new == old) 35462579266SRabin Vincent continue; 35562579266SRabin Vincent 3560f620837SLinus Walleij /* 3570f620837SLinus Walleij * Interrupt register 12 doesn't exist prior to AB8500 version 3580f620837SLinus Walleij * 2.0 3590f620837SLinus Walleij */ 3600f620837SLinus Walleij if (ab8500->irq_reg_offset[i] == 11 && 3610f620837SLinus Walleij is_ab8500_1p1_or_earlier(ab8500)) 36292d50a41SMattias Wallin continue; 36392d50a41SMattias Wallin 3643e1a498fSLee Jones if (ab8500->irq_reg_offset[i] < 0) 3653e1a498fSLee Jones continue; 3663e1a498fSLee Jones 36762579266SRabin Vincent ab8500->oldmask[i] = new; 36862579266SRabin Vincent 3692ced445eSLinus Walleij reg = AB8500_IT_MASK1_REG + ab8500->irq_reg_offset[i]; 37047c16975SMattias Wallin set_register_interruptible(ab8500, AB8500_INTERRUPT, reg, new); 37162579266SRabin Vincent } 372112a80d2SJonas Aaberg atomic_dec(&ab8500->transfer_ongoing); 37362579266SRabin Vincent mutex_unlock(&ab8500->irq_lock); 37462579266SRabin Vincent } 37562579266SRabin Vincent 3769505a0a0SMark Brown static void ab8500_irq_mask(struct irq_data *data) 37762579266SRabin Vincent { 3789505a0a0SMark Brown struct ab8500 *ab8500 = irq_data_get_irq_chip_data(data); 37906e589efSLee Jones int offset = data->hwirq; 38062579266SRabin Vincent int index = offset / 8; 38162579266SRabin Vincent int mask = 1 << (offset % 8); 38262579266SRabin Vincent 38362579266SRabin Vincent ab8500->mask[index] |= mask; 3849c677b9bSLee Jones 3859c677b9bSLee Jones /* The AB8500 GPIOs have two interrupts each (rising & falling). */ 3869c677b9bSLee Jones if (offset >= AB8500_INT_GPIO6R && offset <= AB8500_INT_GPIO41R) 3879c677b9bSLee Jones ab8500->mask[index + 2] |= mask; 3889c677b9bSLee Jones if (offset >= AB9540_INT_GPIO50R && offset <= AB9540_INT_GPIO54R) 3899c677b9bSLee Jones ab8500->mask[index + 1] |= mask; 3909c677b9bSLee Jones if (offset == AB8540_INT_GPIO43R || offset == AB8540_INT_GPIO44R) 391e2ddf46aSLinus Walleij /* Here the falling IRQ is one bit lower */ 392e2ddf46aSLinus Walleij ab8500->mask[index] |= (mask << 1); 39362579266SRabin Vincent } 39462579266SRabin Vincent 3959505a0a0SMark Brown static void ab8500_irq_unmask(struct irq_data *data) 39662579266SRabin Vincent { 3979505a0a0SMark Brown struct ab8500 *ab8500 = irq_data_get_irq_chip_data(data); 3989c677b9bSLee Jones unsigned int type = irqd_get_trigger_type(data); 39906e589efSLee Jones int offset = data->hwirq; 40062579266SRabin Vincent int index = offset / 8; 40162579266SRabin Vincent int mask = 1 << (offset % 8); 40262579266SRabin Vincent 4039c677b9bSLee Jones if (type & IRQ_TYPE_EDGE_RISING) 40462579266SRabin Vincent ab8500->mask[index] &= ~mask; 4059c677b9bSLee Jones 4069c677b9bSLee Jones /* The AB8500 GPIOs have two interrupts each (rising & falling). */ 4079c677b9bSLee Jones if (type & IRQ_TYPE_EDGE_FALLING) { 4089c677b9bSLee Jones if (offset >= AB8500_INT_GPIO6R && offset <= AB8500_INT_GPIO41R) 4099c677b9bSLee Jones ab8500->mask[index + 2] &= ~mask; 4107ccf40b1SLee Jones else if (offset >= AB9540_INT_GPIO50R && 4117ccf40b1SLee Jones offset <= AB9540_INT_GPIO54R) 4129c677b9bSLee Jones ab8500->mask[index + 1] &= ~mask; 4137ccf40b1SLee Jones else if (offset == AB8540_INT_GPIO43R || 4147ccf40b1SLee Jones offset == AB8540_INT_GPIO44R) 415e2ddf46aSLinus Walleij /* Here the falling IRQ is one bit lower */ 416e2ddf46aSLinus Walleij ab8500->mask[index] &= ~(mask << 1); 4179c677b9bSLee Jones else 4189c677b9bSLee Jones ab8500->mask[index] &= ~mask; 419e2ddf46aSLinus Walleij } else { 4209c677b9bSLee Jones /* Satisfies the case where type is not set. */ 42162579266SRabin Vincent ab8500->mask[index] &= ~mask; 42262579266SRabin Vincent } 423e2ddf46aSLinus Walleij } 42462579266SRabin Vincent 42540f6e5a2SLee Jones static int ab8500_irq_set_type(struct irq_data *data, unsigned int type) 42640f6e5a2SLee Jones { 42740f6e5a2SLee Jones return 0; 42862579266SRabin Vincent } 42962579266SRabin Vincent 43062579266SRabin Vincent static struct irq_chip ab8500_irq_chip = { 43162579266SRabin Vincent .name = "ab8500", 4329505a0a0SMark Brown .irq_bus_lock = ab8500_irq_lock, 4339505a0a0SMark Brown .irq_bus_sync_unlock = ab8500_irq_sync_unlock, 4349505a0a0SMark Brown .irq_mask = ab8500_irq_mask, 435e6f9306eSVirupax Sadashivpetimath .irq_disable = ab8500_irq_mask, 4369505a0a0SMark Brown .irq_unmask = ab8500_irq_unmask, 43740f6e5a2SLee Jones .irq_set_type = ab8500_irq_set_type, 43862579266SRabin Vincent }; 43962579266SRabin Vincent 4403e1a498fSLee Jones static void update_latch_offset(u8 *offset, int i) 4413e1a498fSLee Jones { 4423e1a498fSLee Jones /* Fix inconsistent ITFromLatch25 bit mapping... */ 4433e1a498fSLee Jones if (unlikely(*offset == 17)) 4443e1a498fSLee Jones *offset = 24; 4453e1a498fSLee Jones /* Fix inconsistent ab8540 bit mapping... */ 4463e1a498fSLee Jones if (unlikely(*offset == 16)) 4473e1a498fSLee Jones *offset = 25; 4483e1a498fSLee Jones if ((i == 3) && (*offset >= 24)) 4493e1a498fSLee Jones *offset += 2; 4503e1a498fSLee Jones } 4513e1a498fSLee Jones 4527ccfe9b1SMichel JAOUEN static int ab8500_handle_hierarchical_line(struct ab8500 *ab8500, 4537ccfe9b1SMichel JAOUEN int latch_offset, u8 latch_val) 4547ccfe9b1SMichel JAOUEN { 4557a93fb37SFabio Baltieri int int_bit, line, i; 4567ccfe9b1SMichel JAOUEN 4577ccfe9b1SMichel JAOUEN for (i = 0; i < ab8500->mask_size; i++) 4587ccfe9b1SMichel JAOUEN if (ab8500->irq_reg_offset[i] == latch_offset) 4597ccfe9b1SMichel JAOUEN break; 4607ccfe9b1SMichel JAOUEN 4617ccfe9b1SMichel JAOUEN if (i >= ab8500->mask_size) { 4627ccfe9b1SMichel JAOUEN dev_err(ab8500->dev, "Register offset 0x%2x not declared\n", 4637ccfe9b1SMichel JAOUEN latch_offset); 4647ccfe9b1SMichel JAOUEN return -ENXIO; 4657ccfe9b1SMichel JAOUEN } 4667ccfe9b1SMichel JAOUEN 4677a93fb37SFabio Baltieri /* ignore masked out interrupts */ 4687a93fb37SFabio Baltieri latch_val &= ~ab8500->mask[i]; 4697a93fb37SFabio Baltieri 4707a93fb37SFabio Baltieri while (latch_val) { 4717a93fb37SFabio Baltieri int_bit = __ffs(latch_val); 4727ccfe9b1SMichel JAOUEN line = (i << 3) + int_bit; 4737ccfe9b1SMichel JAOUEN latch_val &= ~(1 << int_bit); 4747ccfe9b1SMichel JAOUEN 475e2ddf46aSLinus Walleij /* 476e2ddf46aSLinus Walleij * This handles the falling edge hwirqs from the GPIO 477e2ddf46aSLinus Walleij * lines. Route them back to the line registered for the 478e2ddf46aSLinus Walleij * rising IRQ, as this is merely a flag for the same IRQ 479e2ddf46aSLinus Walleij * in linux terms. 480e2ddf46aSLinus Walleij */ 481e2ddf46aSLinus Walleij if (line >= AB8500_INT_GPIO6F && line <= AB8500_INT_GPIO41F) 482e2ddf46aSLinus Walleij line -= 16; 483e2ddf46aSLinus Walleij if (line >= AB9540_INT_GPIO50F && line <= AB9540_INT_GPIO54F) 484e2ddf46aSLinus Walleij line -= 8; 485e2ddf46aSLinus Walleij if (line == AB8540_INT_GPIO43F || line == AB8540_INT_GPIO44F) 486e2ddf46aSLinus Walleij line += 1; 487e2ddf46aSLinus Walleij 4889ff80e2dSMarc Zyngier handle_nested_irq(irq_find_mapping(ab8500->domain, line)); 4897a93fb37SFabio Baltieri } 4907ccfe9b1SMichel JAOUEN 4917ccfe9b1SMichel JAOUEN return 0; 4927ccfe9b1SMichel JAOUEN } 4937ccfe9b1SMichel JAOUEN 4947ccfe9b1SMichel JAOUEN static int ab8500_handle_hierarchical_latch(struct ab8500 *ab8500, 4957ccfe9b1SMichel JAOUEN int hier_offset, u8 hier_val) 4967ccfe9b1SMichel JAOUEN { 4977ccfe9b1SMichel JAOUEN int latch_bit, status; 4987ccfe9b1SMichel JAOUEN u8 latch_offset, latch_val; 4997ccfe9b1SMichel JAOUEN 5007ccfe9b1SMichel JAOUEN do { 5017ccfe9b1SMichel JAOUEN latch_bit = __ffs(hier_val); 5027ccfe9b1SMichel JAOUEN latch_offset = (hier_offset << 3) + latch_bit; 5037ccfe9b1SMichel JAOUEN 5043e1a498fSLee Jones update_latch_offset(&latch_offset, hier_offset); 5057ccfe9b1SMichel JAOUEN 5067ccfe9b1SMichel JAOUEN status = get_register_interruptible(ab8500, 5077ccfe9b1SMichel JAOUEN AB8500_INTERRUPT, 5087ccfe9b1SMichel JAOUEN AB8500_IT_LATCH1_REG + latch_offset, 5097ccfe9b1SMichel JAOUEN &latch_val); 5107ccfe9b1SMichel JAOUEN if (status < 0 || latch_val == 0) 5117ccfe9b1SMichel JAOUEN goto discard; 5127ccfe9b1SMichel JAOUEN 5137ccfe9b1SMichel JAOUEN status = ab8500_handle_hierarchical_line(ab8500, 5147ccfe9b1SMichel JAOUEN latch_offset, latch_val); 5157ccfe9b1SMichel JAOUEN if (status < 0) 5167ccfe9b1SMichel JAOUEN return status; 5177ccfe9b1SMichel JAOUEN discard: 5187ccfe9b1SMichel JAOUEN hier_val &= ~(1 << latch_bit); 5197ccfe9b1SMichel JAOUEN } while (hier_val); 5207ccfe9b1SMichel JAOUEN 5217ccfe9b1SMichel JAOUEN return 0; 5227ccfe9b1SMichel JAOUEN } 5237ccfe9b1SMichel JAOUEN 5247ccfe9b1SMichel JAOUEN static irqreturn_t ab8500_hierarchical_irq(int irq, void *dev) 5257ccfe9b1SMichel JAOUEN { 5267ccfe9b1SMichel JAOUEN struct ab8500 *ab8500 = dev; 5277ccfe9b1SMichel JAOUEN u8 i; 5287ccfe9b1SMichel JAOUEN 5297ccfe9b1SMichel JAOUEN dev_vdbg(ab8500->dev, "interrupt\n"); 5307ccfe9b1SMichel JAOUEN 5317ccfe9b1SMichel JAOUEN /* Hierarchical interrupt version */ 5323e1a498fSLee Jones for (i = 0; i < (ab8500->it_latchhier_num); i++) { 5337ccfe9b1SMichel JAOUEN int status; 5347ccfe9b1SMichel JAOUEN u8 hier_val; 5357ccfe9b1SMichel JAOUEN 5367ccfe9b1SMichel JAOUEN status = get_register_interruptible(ab8500, AB8500_INTERRUPT, 5377ccfe9b1SMichel JAOUEN AB8500_IT_LATCHHIER1_REG + i, &hier_val); 5387ccfe9b1SMichel JAOUEN if (status < 0 || hier_val == 0) 5397ccfe9b1SMichel JAOUEN continue; 5407ccfe9b1SMichel JAOUEN 5417ccfe9b1SMichel JAOUEN status = ab8500_handle_hierarchical_latch(ab8500, i, hier_val); 5427ccfe9b1SMichel JAOUEN if (status < 0) 5437ccfe9b1SMichel JAOUEN break; 5447ccfe9b1SMichel JAOUEN } 5457ccfe9b1SMichel JAOUEN return IRQ_HANDLED; 5467ccfe9b1SMichel JAOUEN } 5477ccfe9b1SMichel JAOUEN 54806e589efSLee Jones static int ab8500_irq_map(struct irq_domain *d, unsigned int virq, 54906e589efSLee Jones irq_hw_number_t hwirq) 55006e589efSLee Jones { 55106e589efSLee Jones struct ab8500 *ab8500 = d->host_data; 55206e589efSLee Jones 55306e589efSLee Jones if (!ab8500) 55406e589efSLee Jones return -EINVAL; 55506e589efSLee Jones 55606e589efSLee Jones irq_set_chip_data(virq, ab8500); 55706e589efSLee Jones irq_set_chip_and_handler(virq, &ab8500_irq_chip, 55806e589efSLee Jones handle_simple_irq); 55906e589efSLee Jones irq_set_nested_thread(virq, 1); 56006e589efSLee Jones irq_set_noprobe(virq); 56162579266SRabin Vincent 56262579266SRabin Vincent return 0; 56362579266SRabin Vincent } 56462579266SRabin Vincent 5657ce7b26fSKrzysztof Kozlowski static const struct irq_domain_ops ab8500_irq_ops = { 56606e589efSLee Jones .map = ab8500_irq_map, 56706e589efSLee Jones .xlate = irq_domain_xlate_twocell, 56806e589efSLee Jones }; 56906e589efSLee Jones 57006e589efSLee Jones static int ab8500_irq_init(struct ab8500 *ab8500, struct device_node *np) 57162579266SRabin Vincent { 5722ced445eSLinus Walleij int num_irqs; 57362579266SRabin Vincent 5743e1a498fSLee Jones if (is_ab8540(ab8500)) 5753e1a498fSLee Jones num_irqs = AB8540_NR_IRQS; 5763e1a498fSLee Jones else if (is_ab9540(ab8500)) 577d6255529SLinus Walleij num_irqs = AB9540_NR_IRQS; 578a982362cSBengt Jonsson else if (is_ab8505(ab8500)) 579a982362cSBengt Jonsson num_irqs = AB8505_NR_IRQS; 580d6255529SLinus Walleij else 5812ced445eSLinus Walleij num_irqs = AB8500_NR_IRQS; 5822ced445eSLinus Walleij 583f1d11f39SLinus Walleij /* If ->irq_base is zero this will give a linear mapping */ 5847602e05dSGrygorii Strashko ab8500->domain = irq_domain_add_simple(ab8500->dev->of_node, 585f864c46aSLinus Walleij num_irqs, 0, 586f1d11f39SLinus Walleij &ab8500_irq_ops, ab8500); 58706e589efSLee Jones 58806e589efSLee Jones if (!ab8500->domain) { 58906e589efSLee Jones dev_err(ab8500->dev, "Failed to create irqdomain\n"); 590500e69a1SLee Jones return -ENODEV; 59106e589efSLee Jones } 59206e589efSLee Jones 59306e589efSLee Jones return 0; 59462579266SRabin Vincent } 59562579266SRabin Vincent 596112a80d2SJonas Aaberg int ab8500_suspend(struct ab8500 *ab8500) 597112a80d2SJonas Aaberg { 598112a80d2SJonas Aaberg if (atomic_read(&ab8500->transfer_ongoing)) 599112a80d2SJonas Aaberg return -EINVAL; 600f3556302SLee Jones 601112a80d2SJonas Aaberg return 0; 602112a80d2SJonas Aaberg } 603112a80d2SJonas Aaberg 6045ac98553SGeert Uytterhoeven static const struct mfd_cell ab8500_bm_devs[] = { 605417c0fc2SLinus Walleij MFD_CELL_OF("ab8500-charger", NULL, NULL, 0, 0, 606417c0fc2SLinus Walleij "stericsson,ab8500-charger"), 607417c0fc2SLinus Walleij MFD_CELL_OF("ab8500-btemp", NULL, NULL, 0, 0, 608417c0fc2SLinus Walleij "stericsson,ab8500-btemp"), 609417c0fc2SLinus Walleij MFD_CELL_OF("ab8500-fg", NULL, NULL, 0, 0, 610417c0fc2SLinus Walleij "stericsson,ab8500-fg"), 611417c0fc2SLinus Walleij MFD_CELL_OF("ab8500-chargalg", NULL, NULL, 0, 0, 612417c0fc2SLinus Walleij "stericsson,ab8500-chargalg"), 6136ef9418cSRickard Andersson }; 6146ef9418cSRickard Andersson 6155ac98553SGeert Uytterhoeven static const struct mfd_cell ab8500_devs[] = { 616db783e76SLee Jones MFD_CELL_OF("ab8500-sysctrl", 617f4d41ad8SLee Jones NULL, NULL, 0, 0, "stericsson,ab8500-sysctrl"), 618db783e76SLee Jones MFD_CELL_OF("ab8500-ext-regulator", 619f4d41ad8SLee Jones NULL, NULL, 0, 0, "stericsson,ab8500-ext-regulator"), 620db783e76SLee Jones MFD_CELL_OF("ab8500-regulator", 621f4d41ad8SLee Jones NULL, NULL, 0, 0, "stericsson,ab8500-regulator"), 622db783e76SLee Jones MFD_CELL_OF("ab8500-clk", 623702204c2SLinus Walleij NULL, NULL, 0, 0, "stericsson,ab8500-clk"), 624db783e76SLee Jones MFD_CELL_OF("ab8500-gpadc", 625f4d41ad8SLee Jones NULL, NULL, 0, 0, "stericsson,ab8500-gpadc"), 626db783e76SLee Jones MFD_CELL_OF("ab8500-rtc", 627f4d41ad8SLee Jones NULL, NULL, 0, 0, "stericsson,ab8500-rtc"), 628db783e76SLee Jones MFD_CELL_OF("ab8500-acc-det", 629f4d41ad8SLee Jones NULL, NULL, 0, 0, "stericsson,ab8500-acc-det"), 630db783e76SLee Jones MFD_CELL_OF("ab8500-poweron-key", 631f4d41ad8SLee Jones NULL, NULL, 0, 0, "stericsson,ab8500-poweron-key"), 632db783e76SLee Jones MFD_CELL_OF("ab8500-pwm", 633f4d41ad8SLee Jones NULL, NULL, 0, 1, "stericsson,ab8500-pwm"), 634db783e76SLee Jones MFD_CELL_OF("ab8500-pwm", 635f4d41ad8SLee Jones NULL, NULL, 0, 2, "stericsson,ab8500-pwm"), 636db783e76SLee Jones MFD_CELL_OF("ab8500-pwm", 637f4d41ad8SLee Jones NULL, NULL, 0, 3, "stericsson,ab8500-pwm"), 638db783e76SLee Jones MFD_CELL_OF("ab8500-denc", 639f4d41ad8SLee Jones NULL, NULL, 0, 0, "stericsson,ab8500-denc"), 640db783e76SLee Jones MFD_CELL_OF("pinctrl-ab8500", 641f4d41ad8SLee Jones NULL, NULL, 0, 0, "stericsson,ab8500-gpio"), 642db783e76SLee Jones MFD_CELL_OF("abx500-temp", 643f4d41ad8SLee Jones NULL, NULL, 0, 0, "stericsson,abx500-temp"), 644db783e76SLee Jones MFD_CELL_OF("ab8500-usb", 645f4d41ad8SLee Jones NULL, NULL, 0, 0, "stericsson,ab8500-usb"), 646db783e76SLee Jones MFD_CELL_OF("ab8500-codec", 647f4d41ad8SLee Jones NULL, NULL, 0, 0, "stericsson,ab8500-codec"), 6484b106fb9SLee Jones }; 6494b106fb9SLee Jones 6505ac98553SGeert Uytterhoeven static const struct mfd_cell ab9540_devs[] = { 6514b106fb9SLee Jones { 6524b106fb9SLee Jones .name = "ab8500-sysctrl", 6534b106fb9SLee Jones }, 6544b106fb9SLee Jones { 65553f325beSLee Jones .name = "ab8500-ext-regulator", 65653f325beSLee Jones }, 65753f325beSLee Jones { 6584b106fb9SLee Jones .name = "ab8500-regulator", 65944f72e53SVirupax Sadashivpetimath }, 660c0eda9aeSLee Jones { 6619ee17676SUlf Hansson .name = "abx500-clk", 6629ee17676SUlf Hansson .of_compatible = "stericsson,abx500-clk", 6639ee17676SUlf Hansson }, 6649ee17676SUlf Hansson { 665c0eda9aeSLee Jones .name = "ab8500-gpadc", 666c0eda9aeSLee Jones .of_compatible = "stericsson,ab8500-gpadc", 667c0eda9aeSLee Jones }, 6684b106fb9SLee Jones { 6694b106fb9SLee Jones .name = "ab8500-rtc", 6704b106fb9SLee Jones }, 6714b106fb9SLee Jones { 6724b106fb9SLee Jones .name = "ab8500-acc-det", 6734b106fb9SLee Jones }, 6744b106fb9SLee Jones { 6754b106fb9SLee Jones .name = "ab8500-poweron-key", 6764b106fb9SLee Jones }, 6774b106fb9SLee Jones { 6784b106fb9SLee Jones .name = "ab8500-pwm", 6794b106fb9SLee Jones .id = 1, 6804b106fb9SLee Jones }, 6814b106fb9SLee Jones { 6824b106fb9SLee Jones .name = "abx500-temp", 6834b106fb9SLee Jones }, 684d6255529SLinus Walleij { 685e64d905eSLee Jones .name = "pinctrl-ab9540", 686e64d905eSLee Jones .of_compatible = "stericsson,ab9540-gpio", 687d6255529SLinus Walleij }, 688d6255529SLinus Walleij { 689d6255529SLinus Walleij .name = "ab9540-usb", 690d6255529SLinus Walleij }, 69144f72e53SVirupax Sadashivpetimath { 69244f72e53SVirupax Sadashivpetimath .name = "ab9540-codec", 69344f72e53SVirupax Sadashivpetimath }, 694c0eda9aeSLee Jones { 695c0eda9aeSLee Jones .name = "ab-iddet", 696c0eda9aeSLee Jones }, 69744f72e53SVirupax Sadashivpetimath }; 69844f72e53SVirupax Sadashivpetimath 699c0eda9aeSLee Jones /* Device list for ab8505 */ 7005ac98553SGeert Uytterhoeven static const struct mfd_cell ab8505_devs[] = { 7014b106fb9SLee Jones { 7024b106fb9SLee Jones .name = "ab8500-sysctrl", 7031c0769d2SStephan Gerhold .of_compatible = "stericsson,ab8500-sysctrl", 7044b106fb9SLee Jones }, 7054b106fb9SLee Jones { 7064b106fb9SLee Jones .name = "ab8500-regulator", 7071c0769d2SStephan Gerhold .of_compatible = "stericsson,ab8505-regulator", 7084b106fb9SLee Jones }, 7094b106fb9SLee Jones { 7109ee17676SUlf Hansson .name = "abx500-clk", 7111c0769d2SStephan Gerhold .of_compatible = "stericsson,ab8500-clk", 7129ee17676SUlf Hansson }, 7139ee17676SUlf Hansson { 7144b106fb9SLee Jones .name = "ab8500-gpadc", 715955de2eaSLee Jones .of_compatible = "stericsson,ab8500-gpadc", 7164b106fb9SLee Jones }, 7174b106fb9SLee Jones { 7184b106fb9SLee Jones .name = "ab8500-rtc", 7191c0769d2SStephan Gerhold .of_compatible = "stericsson,ab8500-rtc", 7204b106fb9SLee Jones }, 7214b106fb9SLee Jones { 7224b106fb9SLee Jones .name = "ab8500-acc-det", 7231c0769d2SStephan Gerhold .of_compatible = "stericsson,ab8500-acc-det", 7244b106fb9SLee Jones }, 7254b106fb9SLee Jones { 7264b106fb9SLee Jones .name = "ab8500-poweron-key", 7271c0769d2SStephan Gerhold .of_compatible = "stericsson,ab8500-poweron-key", 7284b106fb9SLee Jones }, 7294b106fb9SLee Jones { 7304b106fb9SLee Jones .name = "ab8500-pwm", 7311c0769d2SStephan Gerhold .of_compatible = "stericsson,ab8500-pwm", 7324b106fb9SLee Jones .id = 1, 7334b106fb9SLee Jones }, 7344b106fb9SLee Jones { 735eb696c31SLee Jones .name = "pinctrl-ab8505", 7361c0769d2SStephan Gerhold .of_compatible = "stericsson,ab8505-gpio", 7374b106fb9SLee Jones }, 7384b106fb9SLee Jones { 7394b106fb9SLee Jones .name = "ab8500-usb", 7401c0769d2SStephan Gerhold .of_compatible = "stericsson,ab8500-usb", 7414b106fb9SLee Jones }, 7424b106fb9SLee Jones { 7434b106fb9SLee Jones .name = "ab8500-codec", 7441c0769d2SStephan Gerhold .of_compatible = "stericsson,ab8500-codec", 7454b106fb9SLee Jones }, 746c0eda9aeSLee Jones { 747c0eda9aeSLee Jones .name = "ab-iddet", 748c0eda9aeSLee Jones }, 749c0eda9aeSLee Jones }; 750c0eda9aeSLee Jones 7515ac98553SGeert Uytterhoeven static const struct mfd_cell ab8540_devs[] = { 7524b106fb9SLee Jones { 7534b106fb9SLee Jones .name = "ab8500-sysctrl", 7544b106fb9SLee Jones }, 7554b106fb9SLee Jones { 75653f325beSLee Jones .name = "ab8500-ext-regulator", 75753f325beSLee Jones }, 75853f325beSLee Jones { 7594b106fb9SLee Jones .name = "ab8500-regulator", 7604b106fb9SLee Jones }, 7614b106fb9SLee Jones { 7629ee17676SUlf Hansson .name = "abx500-clk", 7639ee17676SUlf Hansson .of_compatible = "stericsson,abx500-clk", 7649ee17676SUlf Hansson }, 7659ee17676SUlf Hansson { 7664b106fb9SLee Jones .name = "ab8500-gpadc", 767955de2eaSLee Jones .of_compatible = "stericsson,ab8500-gpadc", 7684b106fb9SLee Jones }, 7694b106fb9SLee Jones { 7704b106fb9SLee Jones .name = "ab8500-acc-det", 7714b106fb9SLee Jones }, 7724b106fb9SLee Jones { 7734b106fb9SLee Jones .name = "ab8500-poweron-key", 7744b106fb9SLee Jones }, 7754b106fb9SLee Jones { 7764b106fb9SLee Jones .name = "ab8500-pwm", 7774b106fb9SLee Jones .id = 1, 7784b106fb9SLee Jones }, 7794b106fb9SLee Jones { 7804b106fb9SLee Jones .name = "abx500-temp", 7814b106fb9SLee Jones }, 782c0eda9aeSLee Jones { 783eb696c31SLee Jones .name = "pinctrl-ab8540", 784c0eda9aeSLee Jones }, 785c0eda9aeSLee Jones { 786c0eda9aeSLee Jones .name = "ab8540-usb", 787c0eda9aeSLee Jones }, 788c0eda9aeSLee Jones { 789c0eda9aeSLee Jones .name = "ab8540-codec", 790c0eda9aeSLee Jones }, 791c0eda9aeSLee Jones { 79244f72e53SVirupax Sadashivpetimath .name = "ab-iddet", 79344f72e53SVirupax Sadashivpetimath }, 794d6255529SLinus Walleij }; 795d6255529SLinus Walleij 7965ac98553SGeert Uytterhoeven static const struct mfd_cell ab8540_cut1_devs[] = { 7979c717cf3SAlexandre Torgue { 7989c717cf3SAlexandre Torgue .name = "ab8500-rtc", 7999c717cf3SAlexandre Torgue .of_compatible = "stericsson,ab8500-rtc", 8009c717cf3SAlexandre Torgue }, 8019c717cf3SAlexandre Torgue }; 8029c717cf3SAlexandre Torgue 8035ac98553SGeert Uytterhoeven static const struct mfd_cell ab8540_cut2_devs[] = { 8049c717cf3SAlexandre Torgue { 8059c717cf3SAlexandre Torgue .name = "ab8540-rtc", 8069c717cf3SAlexandre Torgue .of_compatible = "stericsson,ab8540-rtc", 8079c717cf3SAlexandre Torgue }, 8089c717cf3SAlexandre Torgue }; 8099c717cf3SAlexandre Torgue 810afb349c0SZhen Lei static ssize_t chip_id_show(struct device *dev, 811cca69b67SMattias Wallin struct device_attribute *attr, char *buf) 812cca69b67SMattias Wallin { 813cca69b67SMattias Wallin struct ab8500 *ab8500; 814cca69b67SMattias Wallin 815cca69b67SMattias Wallin ab8500 = dev_get_drvdata(dev); 816e436ddffSLee Jones 817cca69b67SMattias Wallin return sprintf(buf, "%#x\n", ab8500 ? ab8500->chip_id : -EINVAL); 818cca69b67SMattias Wallin } 819cca69b67SMattias Wallin 820e5c238c3SMattias Wallin /* 821e5c238c3SMattias Wallin * ab8500 has switched off due to (SWITCH_OFF_STATUS): 822e5c238c3SMattias Wallin * 0x01 Swoff bit programming 823e5c238c3SMattias Wallin * 0x02 Thermal protection activation 824e5c238c3SMattias Wallin * 0x04 Vbat lower then BattOk falling threshold 825e5c238c3SMattias Wallin * 0x08 Watchdog expired 826e5c238c3SMattias Wallin * 0x10 Non presence of 32kHz clock 827e5c238c3SMattias Wallin * 0x20 Battery level lower than power on reset threshold 828e5c238c3SMattias Wallin * 0x40 Power on key 1 pressed longer than 10 seconds 829e5c238c3SMattias Wallin * 0x80 DB8500 thermal shutdown 830e5c238c3SMattias Wallin */ 831afb349c0SZhen Lei static ssize_t switch_off_status_show(struct device *dev, 832e5c238c3SMattias Wallin struct device_attribute *attr, char *buf) 833e5c238c3SMattias Wallin { 834e5c238c3SMattias Wallin int ret; 835e5c238c3SMattias Wallin u8 value; 836e5c238c3SMattias Wallin struct ab8500 *ab8500; 837e5c238c3SMattias Wallin 838e5c238c3SMattias Wallin ab8500 = dev_get_drvdata(dev); 839e5c238c3SMattias Wallin ret = get_register_interruptible(ab8500, AB8500_RTC, 840e5c238c3SMattias Wallin AB8500_SWITCH_OFF_STATUS, &value); 841e5c238c3SMattias Wallin if (ret < 0) 842e5c238c3SMattias Wallin return ret; 843e5c238c3SMattias Wallin return sprintf(buf, "%#x\n", value); 844e5c238c3SMattias Wallin } 845e5c238c3SMattias Wallin 846f04a9d8aSRajkumar Kasirajan /* use mask and set to override the register turn_on_stat value */ 847f04a9d8aSRajkumar Kasirajan void ab8500_override_turn_on_stat(u8 mask, u8 set) 848f04a9d8aSRajkumar Kasirajan { 849f04a9d8aSRajkumar Kasirajan spin_lock(&on_stat_lock); 850f04a9d8aSRajkumar Kasirajan turn_on_stat_mask = mask; 851f04a9d8aSRajkumar Kasirajan turn_on_stat_set = set; 852f04a9d8aSRajkumar Kasirajan spin_unlock(&on_stat_lock); 853f04a9d8aSRajkumar Kasirajan } 854f04a9d8aSRajkumar Kasirajan 855b4a31037SAndrew Lynn /* 856b4a31037SAndrew Lynn * ab8500 has turned on due to (TURN_ON_STATUS): 857b4a31037SAndrew Lynn * 0x01 PORnVbat 858b4a31037SAndrew Lynn * 0x02 PonKey1dbF 859b4a31037SAndrew Lynn * 0x04 PonKey2dbF 860b4a31037SAndrew Lynn * 0x08 RTCAlarm 861b4a31037SAndrew Lynn * 0x10 MainChDet 862b4a31037SAndrew Lynn * 0x20 VbusDet 863b4a31037SAndrew Lynn * 0x40 UsbIDDetect 864b4a31037SAndrew Lynn * 0x80 Reserved 865b4a31037SAndrew Lynn */ 866afb349c0SZhen Lei static ssize_t turn_on_status_show(struct device *dev, 867b4a31037SAndrew Lynn struct device_attribute *attr, char *buf) 868b4a31037SAndrew Lynn { 869b4a31037SAndrew Lynn int ret; 870b4a31037SAndrew Lynn u8 value; 871b4a31037SAndrew Lynn struct ab8500 *ab8500; 872b4a31037SAndrew Lynn 873b4a31037SAndrew Lynn ab8500 = dev_get_drvdata(dev); 874b4a31037SAndrew Lynn ret = get_register_interruptible(ab8500, AB8500_SYS_CTRL1_BLOCK, 875b4a31037SAndrew Lynn AB8500_TURN_ON_STATUS, &value); 876b4a31037SAndrew Lynn if (ret < 0) 877b4a31037SAndrew Lynn return ret; 878f04a9d8aSRajkumar Kasirajan 879f04a9d8aSRajkumar Kasirajan /* 880f04a9d8aSRajkumar Kasirajan * In L9540, turn_on_status register is not updated correctly if 881f04a9d8aSRajkumar Kasirajan * the device is rebooted with AC/USB charger connected. Due to 882f04a9d8aSRajkumar Kasirajan * this, the device boots android instead of entering into charge 883f04a9d8aSRajkumar Kasirajan * only mode. Read the AC/USB status register to detect the charger 884f04a9d8aSRajkumar Kasirajan * presence and update the turn on status manually. 885f04a9d8aSRajkumar Kasirajan */ 886f04a9d8aSRajkumar Kasirajan if (is_ab9540(ab8500)) { 887f04a9d8aSRajkumar Kasirajan spin_lock(&on_stat_lock); 888f04a9d8aSRajkumar Kasirajan value = (value & turn_on_stat_mask) | turn_on_stat_set; 889f04a9d8aSRajkumar Kasirajan spin_unlock(&on_stat_lock); 890f04a9d8aSRajkumar Kasirajan } 891f04a9d8aSRajkumar Kasirajan 892b4a31037SAndrew Lynn return sprintf(buf, "%#x\n", value); 893b4a31037SAndrew Lynn } 894b4a31037SAndrew Lynn 895afb349c0SZhen Lei static ssize_t turn_on_status_2_show(struct device *dev, 89693ff722eSLee Jones struct device_attribute *attr, char *buf) 89793ff722eSLee Jones { 89893ff722eSLee Jones int ret; 89993ff722eSLee Jones u8 value; 90093ff722eSLee Jones struct ab8500 *ab8500; 90193ff722eSLee Jones 90293ff722eSLee Jones ab8500 = dev_get_drvdata(dev); 90393ff722eSLee Jones ret = get_register_interruptible(ab8500, AB8500_SYS_CTRL1_BLOCK, 90493ff722eSLee Jones AB8505_TURN_ON_STATUS_2, &value); 90593ff722eSLee Jones if (ret < 0) 90693ff722eSLee Jones return ret; 90793ff722eSLee Jones return sprintf(buf, "%#x\n", (value & 0x1)); 90893ff722eSLee Jones } 90993ff722eSLee Jones 910afb349c0SZhen Lei static ssize_t dbbrstn_show(struct device *dev, 911d6255529SLinus Walleij struct device_attribute *attr, char *buf) 912d6255529SLinus Walleij { 913d6255529SLinus Walleij struct ab8500 *ab8500; 914d6255529SLinus Walleij int ret; 915d6255529SLinus Walleij u8 value; 916d6255529SLinus Walleij 917d6255529SLinus Walleij ab8500 = dev_get_drvdata(dev); 918d6255529SLinus Walleij 919d6255529SLinus Walleij ret = get_register_interruptible(ab8500, AB8500_REGU_CTRL2, 920d6255529SLinus Walleij AB9540_MODEM_CTRL2_REG, &value); 921d6255529SLinus Walleij if (ret < 0) 922d6255529SLinus Walleij return ret; 923d6255529SLinus Walleij 924d6255529SLinus Walleij return sprintf(buf, "%d\n", 925d6255529SLinus Walleij (value & AB9540_MODEM_CTRL2_SWDBBRSTN_BIT) ? 1 : 0); 926d6255529SLinus Walleij } 927d6255529SLinus Walleij 928afb349c0SZhen Lei static ssize_t dbbrstn_store(struct device *dev, 929d6255529SLinus Walleij struct device_attribute *attr, const char *buf, size_t count) 930d6255529SLinus Walleij { 931d6255529SLinus Walleij struct ab8500 *ab8500; 932d6255529SLinus Walleij int ret = count; 933d6255529SLinus Walleij int err; 934d6255529SLinus Walleij u8 bitvalues; 935d6255529SLinus Walleij 936d6255529SLinus Walleij ab8500 = dev_get_drvdata(dev); 937d6255529SLinus Walleij 938d6255529SLinus Walleij if (count > 0) { 939d6255529SLinus Walleij switch (buf[0]) { 940d6255529SLinus Walleij case '0': 941d6255529SLinus Walleij bitvalues = 0; 942d6255529SLinus Walleij break; 943d6255529SLinus Walleij case '1': 944d6255529SLinus Walleij bitvalues = AB9540_MODEM_CTRL2_SWDBBRSTN_BIT; 945d6255529SLinus Walleij break; 946d6255529SLinus Walleij default: 947d6255529SLinus Walleij goto exit; 948d6255529SLinus Walleij } 949d6255529SLinus Walleij 950d6255529SLinus Walleij err = mask_and_set_register_interruptible(ab8500, 951d6255529SLinus Walleij AB8500_REGU_CTRL2, AB9540_MODEM_CTRL2_REG, 952d6255529SLinus Walleij AB9540_MODEM_CTRL2_SWDBBRSTN_BIT, bitvalues); 953d6255529SLinus Walleij if (err) 954d6255529SLinus Walleij dev_info(ab8500->dev, 955d6255529SLinus Walleij "Failed to set DBBRSTN %c, err %#x\n", 956d6255529SLinus Walleij buf[0], err); 957d6255529SLinus Walleij } 958d6255529SLinus Walleij 959d6255529SLinus Walleij exit: 960d6255529SLinus Walleij return ret; 961d6255529SLinus Walleij } 962d6255529SLinus Walleij 963afb349c0SZhen Lei static DEVICE_ATTR_RO(chip_id); 964afb349c0SZhen Lei static DEVICE_ATTR_RO(switch_off_status); 965afb349c0SZhen Lei static DEVICE_ATTR_RO(turn_on_status); 966afb349c0SZhen Lei static DEVICE_ATTR_RO(turn_on_status_2); 967afb349c0SZhen Lei static DEVICE_ATTR_RW(dbbrstn); 968cca69b67SMattias Wallin 969cca69b67SMattias Wallin static struct attribute *ab8500_sysfs_entries[] = { 970cca69b67SMattias Wallin &dev_attr_chip_id.attr, 971e5c238c3SMattias Wallin &dev_attr_switch_off_status.attr, 972b4a31037SAndrew Lynn &dev_attr_turn_on_status.attr, 973cca69b67SMattias Wallin NULL, 974cca69b67SMattias Wallin }; 975cca69b67SMattias Wallin 97693ff722eSLee Jones static struct attribute *ab8505_sysfs_entries[] = { 97793ff722eSLee Jones &dev_attr_turn_on_status_2.attr, 97893ff722eSLee Jones NULL, 97993ff722eSLee Jones }; 98093ff722eSLee Jones 981d6255529SLinus Walleij static struct attribute *ab9540_sysfs_entries[] = { 982d6255529SLinus Walleij &dev_attr_chip_id.attr, 983d6255529SLinus Walleij &dev_attr_switch_off_status.attr, 984d6255529SLinus Walleij &dev_attr_turn_on_status.attr, 985d6255529SLinus Walleij &dev_attr_dbbrstn.attr, 986d6255529SLinus Walleij NULL, 987d6255529SLinus Walleij }; 988d6255529SLinus Walleij 98952557dc6SArvind Yadav static const struct attribute_group ab8500_attr_group = { 990cca69b67SMattias Wallin .attrs = ab8500_sysfs_entries, 991cca69b67SMattias Wallin }; 992cca69b67SMattias Wallin 99352557dc6SArvind Yadav static const struct attribute_group ab8505_attr_group = { 99493ff722eSLee Jones .attrs = ab8505_sysfs_entries, 99593ff722eSLee Jones }; 99693ff722eSLee Jones 99752557dc6SArvind Yadav static const struct attribute_group ab9540_attr_group = { 998d6255529SLinus Walleij .attrs = ab9540_sysfs_entries, 999d6255529SLinus Walleij }; 1000d6255529SLinus Walleij 1001f791be49SBill Pemberton static int ab8500_probe(struct platform_device *pdev) 100262579266SRabin Vincent { 1003500e69a1SLee Jones static const char * const switch_off_status[] = { 1004b04c530cSJonas Aaberg "Swoff bit programming", 1005b04c530cSJonas Aaberg "Thermal protection activation", 1006b04c530cSJonas Aaberg "Vbat lower then BattOk falling threshold", 1007b04c530cSJonas Aaberg "Watchdog expired", 1008b04c530cSJonas Aaberg "Non presence of 32kHz clock", 1009b04c530cSJonas Aaberg "Battery level lower than power on reset threshold", 1010b04c530cSJonas Aaberg "Power on key 1 pressed longer than 10 seconds", 1011b04c530cSJonas Aaberg "DB8500 thermal shutdown"}; 1012500e69a1SLee Jones static const char * const turn_on_status[] = { 1013abee26cdSMattias Wallin "Battery rising (Vbat)", 1014abee26cdSMattias Wallin "Power On Key 1 dbF", 1015abee26cdSMattias Wallin "Power On Key 2 dbF", 1016abee26cdSMattias Wallin "RTC Alarm", 1017abee26cdSMattias Wallin "Main Charger Detect", 1018abee26cdSMattias Wallin "Vbus Detect (USB)", 1019abee26cdSMattias Wallin "USB ID Detect", 1020abee26cdSMattias Wallin "UART Factory Mode Detect"}; 1021d28f1db8SLee Jones const struct platform_device_id *platid = platform_get_device_id(pdev); 10226bc4a568SLee Jones enum ab8500_version version = AB8500_VERSION_UNDEFINED; 10236bc4a568SLee Jones struct device_node *np = pdev->dev.of_node; 1024d28f1db8SLee Jones struct ab8500 *ab8500; 102562579266SRabin Vincent int ret; 102662579266SRabin Vincent int i; 1027*fc832ac9SMinghao Chi (CGEL ZTE) int irq; 102847c16975SMattias Wallin u8 value; 102962579266SRabin Vincent 10307ccf40b1SLee Jones ab8500 = devm_kzalloc(&pdev->dev, sizeof(*ab8500), GFP_KERNEL); 1031d28f1db8SLee Jones if (!ab8500) 1032d28f1db8SLee Jones return -ENOMEM; 1033d28f1db8SLee Jones 1034d28f1db8SLee Jones ab8500->dev = &pdev->dev; 1035d28f1db8SLee Jones 1036*fc832ac9SMinghao Chi (CGEL ZTE) irq = platform_get_irq(pdev, 0); 1037*fc832ac9SMinghao Chi (CGEL ZTE) if (irq < 0) 1038*fc832ac9SMinghao Chi (CGEL ZTE) return irq; 1039d28f1db8SLee Jones 1040*fc832ac9SMinghao Chi (CGEL ZTE) ab8500->irq = irq; 1041d28f1db8SLee Jones 1042822672a7SLee Jones ab8500->read = ab8500_prcmu_read; 1043822672a7SLee Jones ab8500->write = ab8500_prcmu_write; 1044822672a7SLee Jones ab8500->write_masked = ab8500_prcmu_write_masked; 1045d28f1db8SLee Jones 104662579266SRabin Vincent mutex_init(&ab8500->lock); 104762579266SRabin Vincent mutex_init(&ab8500->irq_lock); 1048112a80d2SJonas Aaberg atomic_set(&ab8500->transfer_ongoing, 0); 104962579266SRabin Vincent 1050d28f1db8SLee Jones platform_set_drvdata(pdev, ab8500); 1051d28f1db8SLee Jones 10526bc4a568SLee Jones if (platid) 10536bc4a568SLee Jones version = platid->driver_data; 10546bc4a568SLee Jones 10550f620837SLinus Walleij if (version != AB8500_VERSION_UNDEFINED) 10560f620837SLinus Walleij ab8500->version = version; 10570f620837SLinus Walleij else { 10580f620837SLinus Walleij ret = get_register_interruptible(ab8500, AB8500_MISC, 10590f620837SLinus Walleij AB8500_IC_NAME_REG, &value); 1060f864c46aSLinus Walleij if (ret < 0) { 1061f864c46aSLinus Walleij dev_err(&pdev->dev, "could not probe HW\n"); 10628c4203cbSLee Jones return ret; 1063f864c46aSLinus Walleij } 10640f620837SLinus Walleij 10650f620837SLinus Walleij ab8500->version = value; 10660f620837SLinus Walleij } 10670f620837SLinus Walleij 106847c16975SMattias Wallin ret = get_register_interruptible(ab8500, AB8500_MISC, 106947c16975SMattias Wallin AB8500_REV_REG, &value); 107062579266SRabin Vincent if (ret < 0) 10718c4203cbSLee Jones return ret; 107262579266SRabin Vincent 107347c16975SMattias Wallin ab8500->chip_id = value; 107462579266SRabin Vincent 10750f620837SLinus Walleij dev_info(ab8500->dev, "detected chip, %s rev. %1x.%1x\n", 10760f620837SLinus Walleij ab8500_version_str[ab8500->version], 10770f620837SLinus Walleij ab8500->chip_id >> 4, 10780f620837SLinus Walleij ab8500->chip_id & 0x0F); 10790f620837SLinus Walleij 10803e1a498fSLee Jones /* Configure AB8540 */ 10813e1a498fSLee Jones if (is_ab8540(ab8500)) { 10823e1a498fSLee Jones ab8500->mask_size = AB8540_NUM_IRQ_REGS; 10833e1a498fSLee Jones ab8500->irq_reg_offset = ab8540_irq_regoffset; 10843e1a498fSLee Jones ab8500->it_latchhier_num = AB8540_IT_LATCHHIER_NUM; 10853e1a498fSLee Jones } /* Configure AB8500 or AB9540 IRQ */ 10863e1a498fSLee Jones else if (is_ab9540(ab8500) || is_ab8505(ab8500)) { 1087d6255529SLinus Walleij ab8500->mask_size = AB9540_NUM_IRQ_REGS; 1088d6255529SLinus Walleij ab8500->irq_reg_offset = ab9540_irq_regoffset; 10893e1a498fSLee Jones ab8500->it_latchhier_num = AB8500_IT_LATCHHIER_NUM; 1090d6255529SLinus Walleij } else { 10912ced445eSLinus Walleij ab8500->mask_size = AB8500_NUM_IRQ_REGS; 10922ced445eSLinus Walleij ab8500->irq_reg_offset = ab8500_irq_regoffset; 10933e1a498fSLee Jones ab8500->it_latchhier_num = AB8500_IT_LATCHHIER_NUM; 1094d6255529SLinus Walleij } 10957ccf40b1SLee Jones ab8500->mask = devm_kzalloc(&pdev->dev, ab8500->mask_size, 10967ccf40b1SLee Jones GFP_KERNEL); 10972ced445eSLinus Walleij if (!ab8500->mask) 10982ced445eSLinus Walleij return -ENOMEM; 10997ccf40b1SLee Jones ab8500->oldmask = devm_kzalloc(&pdev->dev, ab8500->mask_size, 11007ccf40b1SLee Jones GFP_KERNEL); 11018c4203cbSLee Jones if (!ab8500->oldmask) 11028c4203cbSLee Jones return -ENOMEM; 11038c4203cbSLee Jones 1104e5c238c3SMattias Wallin /* 1105e5c238c3SMattias Wallin * ab8500 has switched off due to (SWITCH_OFF_STATUS): 1106e5c238c3SMattias Wallin * 0x01 Swoff bit programming 1107e5c238c3SMattias Wallin * 0x02 Thermal protection activation 1108e5c238c3SMattias Wallin * 0x04 Vbat lower then BattOk falling threshold 1109e5c238c3SMattias Wallin * 0x08 Watchdog expired 1110e5c238c3SMattias Wallin * 0x10 Non presence of 32kHz clock 1111e5c238c3SMattias Wallin * 0x20 Battery level lower than power on reset threshold 1112e5c238c3SMattias Wallin * 0x40 Power on key 1 pressed longer than 10 seconds 1113e5c238c3SMattias Wallin * 0x80 DB8500 thermal shutdown 1114e5c238c3SMattias Wallin */ 1115e5c238c3SMattias Wallin 1116e5c238c3SMattias Wallin ret = get_register_interruptible(ab8500, AB8500_RTC, 1117e5c238c3SMattias Wallin AB8500_SWITCH_OFF_STATUS, &value); 1118e5c238c3SMattias Wallin if (ret < 0) 1119e5c238c3SMattias Wallin return ret; 1120b04c530cSJonas Aaberg dev_info(ab8500->dev, "switch off cause(s) (%#x): ", value); 1121b04c530cSJonas Aaberg 1122b04c530cSJonas Aaberg if (value) { 1123b04c530cSJonas Aaberg for (i = 0; i < ARRAY_SIZE(switch_off_status); i++) { 1124b04c530cSJonas Aaberg if (value & 1) 11257ccf40b1SLee Jones pr_cont(" \"%s\"", switch_off_status[i]); 1126b04c530cSJonas Aaberg value = value >> 1; 1127b04c530cSJonas Aaberg 1128b04c530cSJonas Aaberg } 11297ccf40b1SLee Jones pr_cont("\n"); 1130b04c530cSJonas Aaberg } else { 11317ccf40b1SLee Jones pr_cont(" None\n"); 1132b04c530cSJonas Aaberg } 1133abee26cdSMattias Wallin ret = get_register_interruptible(ab8500, AB8500_SYS_CTRL1_BLOCK, 1134abee26cdSMattias Wallin AB8500_TURN_ON_STATUS, &value); 1135abee26cdSMattias Wallin if (ret < 0) 1136abee26cdSMattias Wallin return ret; 1137abee26cdSMattias Wallin dev_info(ab8500->dev, "turn on reason(s) (%#x): ", value); 1138abee26cdSMattias Wallin 1139abee26cdSMattias Wallin if (value) { 1140abee26cdSMattias Wallin for (i = 0; i < ARRAY_SIZE(turn_on_status); i++) { 1141abee26cdSMattias Wallin if (value & 1) 11427ccf40b1SLee Jones pr_cont("\"%s\" ", turn_on_status[i]); 1143abee26cdSMattias Wallin value = value >> 1; 1144abee26cdSMattias Wallin } 11457ccf40b1SLee Jones pr_cont("\n"); 1146abee26cdSMattias Wallin } else { 11477ccf40b1SLee Jones pr_cont("None\n"); 1148abee26cdSMattias Wallin } 1149e5c238c3SMattias Wallin 1150f04a9d8aSRajkumar Kasirajan if (is_ab9540(ab8500)) { 1151f04a9d8aSRajkumar Kasirajan ret = get_register_interruptible(ab8500, AB8500_CHARGER, 1152f04a9d8aSRajkumar Kasirajan AB8500_CH_USBCH_STAT1_REG, &value); 1153f04a9d8aSRajkumar Kasirajan if (ret < 0) 1154f04a9d8aSRajkumar Kasirajan return ret; 1155f04a9d8aSRajkumar Kasirajan if ((value & VBUS_DET_DBNC1) && (value & VBUS_DET_DBNC100)) 1156f04a9d8aSRajkumar Kasirajan ab8500_override_turn_on_stat(~AB8500_POW_KEY_1_ON, 1157f04a9d8aSRajkumar Kasirajan AB8500_VBUS_DET); 1158f04a9d8aSRajkumar Kasirajan } 115962579266SRabin Vincent 116062579266SRabin Vincent /* Clear and mask all interrupts */ 11612ced445eSLinus Walleij for (i = 0; i < ab8500->mask_size; i++) { 11620f620837SLinus Walleij /* 11630f620837SLinus Walleij * Interrupt register 12 doesn't exist prior to AB8500 version 11640f620837SLinus Walleij * 2.0 11650f620837SLinus Walleij */ 11660f620837SLinus Walleij if (ab8500->irq_reg_offset[i] == 11 && 11670f620837SLinus Walleij is_ab8500_1p1_or_earlier(ab8500)) 116892d50a41SMattias Wallin continue; 116962579266SRabin Vincent 11703e1a498fSLee Jones if (ab8500->irq_reg_offset[i] < 0) 11713e1a498fSLee Jones continue; 11723e1a498fSLee Jones 117347c16975SMattias Wallin get_register_interruptible(ab8500, AB8500_INTERRUPT, 11742ced445eSLinus Walleij AB8500_IT_LATCH1_REG + ab8500->irq_reg_offset[i], 117592d50a41SMattias Wallin &value); 117647c16975SMattias Wallin set_register_interruptible(ab8500, AB8500_INTERRUPT, 11772ced445eSLinus Walleij AB8500_IT_MASK1_REG + ab8500->irq_reg_offset[i], 0xff); 117862579266SRabin Vincent } 117962579266SRabin Vincent 118047c16975SMattias Wallin ret = abx500_register_ops(ab8500->dev, &ab8500_ops); 118147c16975SMattias Wallin if (ret) 11828c4203cbSLee Jones return ret; 118347c16975SMattias Wallin 11842ced445eSLinus Walleij for (i = 0; i < ab8500->mask_size; i++) 118562579266SRabin Vincent ab8500->mask[i] = ab8500->oldmask[i] = 0xff; 118662579266SRabin Vincent 118706e589efSLee Jones ret = ab8500_irq_init(ab8500, np); 118862579266SRabin Vincent if (ret) 11898c4203cbSLee Jones return ret; 119062579266SRabin Vincent 11918c4203cbSLee Jones ret = devm_request_threaded_irq(&pdev->dev, ab8500->irq, NULL, 11927ccfe9b1SMichel JAOUEN ab8500_hierarchical_irq, 11937ccfe9b1SMichel JAOUEN IRQF_ONESHOT | IRQF_NO_SUSPEND, 11947ccfe9b1SMichel JAOUEN "ab8500", ab8500); 119562579266SRabin Vincent if (ret) 11968c4203cbSLee Jones return ret; 119762579266SRabin Vincent 1198d6255529SLinus Walleij if (is_ab9540(ab8500)) 1199d6255529SLinus Walleij ret = mfd_add_devices(ab8500->dev, 0, ab9540_devs, 1200d6255529SLinus Walleij ARRAY_SIZE(ab9540_devs), NULL, 1201f864c46aSLinus Walleij 0, ab8500->domain); 12029c717cf3SAlexandre Torgue else if (is_ab8540(ab8500)) { 1203c0eda9aeSLee Jones ret = mfd_add_devices(ab8500->dev, 0, ab8540_devs, 1204c0eda9aeSLee Jones ARRAY_SIZE(ab8540_devs), NULL, 1205f864c46aSLinus Walleij 0, ab8500->domain); 12069c717cf3SAlexandre Torgue if (ret) 12079c717cf3SAlexandre Torgue return ret; 12089c717cf3SAlexandre Torgue 12099c717cf3SAlexandre Torgue if (is_ab8540_1p2_or_earlier(ab8500)) 12109c717cf3SAlexandre Torgue ret = mfd_add_devices(ab8500->dev, 0, ab8540_cut1_devs, 12119c717cf3SAlexandre Torgue ARRAY_SIZE(ab8540_cut1_devs), NULL, 1212f864c46aSLinus Walleij 0, ab8500->domain); 12139c717cf3SAlexandre Torgue else /* ab8540 >= cut2 */ 12149c717cf3SAlexandre Torgue ret = mfd_add_devices(ab8500->dev, 0, ab8540_cut2_devs, 12159c717cf3SAlexandre Torgue ARRAY_SIZE(ab8540_cut2_devs), NULL, 1216f864c46aSLinus Walleij 0, ab8500->domain); 12179c717cf3SAlexandre Torgue } else if (is_ab8505(ab8500)) 1218c0eda9aeSLee Jones ret = mfd_add_devices(ab8500->dev, 0, ab8505_devs, 1219c0eda9aeSLee Jones ARRAY_SIZE(ab8505_devs), NULL, 1220f864c46aSLinus Walleij 0, ab8500->domain); 1221d6255529SLinus Walleij else 1222549931f9SSundar R Iyer ret = mfd_add_devices(ab8500->dev, 0, ab8500_devs, 122344f72e53SVirupax Sadashivpetimath ARRAY_SIZE(ab8500_devs), NULL, 1224f864c46aSLinus Walleij 0, ab8500->domain); 12256bc4a568SLee Jones if (ret) 12268c4203cbSLee Jones return ret; 122744f72e53SVirupax Sadashivpetimath 12286ef9418cSRickard Andersson /* Add battery management devices */ 12296ef9418cSRickard Andersson ret = mfd_add_devices(ab8500->dev, 0, ab8500_bm_devs, 12306ef9418cSRickard Andersson ARRAY_SIZE(ab8500_bm_devs), NULL, 1231f864c46aSLinus Walleij 0, ab8500->domain); 12326ef9418cSRickard Andersson if (ret) 12336ef9418cSRickard Andersson dev_err(ab8500->dev, "error adding bm devices\n"); 12346ef9418cSRickard Andersson 1235e436ddffSLee Jones if (((is_ab8505(ab8500) || is_ab9540(ab8500)) && 1236e436ddffSLee Jones ab8500->chip_id >= AB8500_CUT2P0) || is_ab8540(ab8500)) 1237d6255529SLinus Walleij ret = sysfs_create_group(&ab8500->dev->kobj, 1238d6255529SLinus Walleij &ab9540_attr_group); 1239d6255529SLinus Walleij else 1240d6255529SLinus Walleij ret = sysfs_create_group(&ab8500->dev->kobj, 1241d6255529SLinus Walleij &ab8500_attr_group); 124293ff722eSLee Jones 124393ff722eSLee Jones if ((is_ab8505(ab8500) || is_ab9540(ab8500)) && 124493ff722eSLee Jones ab8500->chip_id >= AB8500_CUT2P0) 124593ff722eSLee Jones ret = sysfs_create_group(&ab8500->dev->kobj, 124693ff722eSLee Jones &ab8505_attr_group); 124793ff722eSLee Jones 1248cca69b67SMattias Wallin if (ret) 1249cca69b67SMattias Wallin dev_err(ab8500->dev, "error creating sysfs entries\n"); 125006e589efSLee Jones 125162579266SRabin Vincent return ret; 125262579266SRabin Vincent } 125362579266SRabin Vincent 1254d28f1db8SLee Jones static const struct platform_device_id ab8500_id[] = { 1255d28f1db8SLee Jones { "ab8500-core", AB8500_VERSION_AB8500 }, 12561c0769d2SStephan Gerhold { "ab8505-core", AB8500_VERSION_AB8505 }, 1257d28f1db8SLee Jones { "ab9540-i2c", AB8500_VERSION_AB9540 }, 1258d28f1db8SLee Jones { "ab8540-i2c", AB8500_VERSION_AB8540 }, 1259d28f1db8SLee Jones { } 1260d28f1db8SLee Jones }; 1261d28f1db8SLee Jones 1262d28f1db8SLee Jones static struct platform_driver ab8500_core_driver = { 1263d28f1db8SLee Jones .driver = { 1264d28f1db8SLee Jones .name = "ab8500-core", 126531cbae22SPaul Gortmaker .suppress_bind_attrs = true, 1266d28f1db8SLee Jones }, 1267d28f1db8SLee Jones .probe = ab8500_probe, 1268d28f1db8SLee Jones .id_table = ab8500_id, 1269d28f1db8SLee Jones }; 1270d28f1db8SLee Jones 1271d28f1db8SLee Jones static int __init ab8500_core_init(void) 1272d28f1db8SLee Jones { 1273d28f1db8SLee Jones return platform_driver_register(&ab8500_core_driver); 1274d28f1db8SLee Jones } 1275ba7cbc3eSLee Jones core_initcall(ab8500_core_init); 1276