xref: /openbmc/linux/drivers/mfd/ab8500-core.c (revision a29264b68a93556a09005b9f18cbd3f61f6fd355)
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
98*a29264b6SLee 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
1067ccfe9b1SMichel JAOUEN 
1077ccfe9b1SMichel JAOUEN #define AB8500_IT_LATCHHIER_NUM		3
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
114b4a31037SAndrew Lynn 
115f04a9d8aSRajkumar Kasirajan #define AB8500_CH_USBCH_STAT1_REG	0x02
116f04a9d8aSRajkumar Kasirajan #define VBUS_DET_DBNC100		0x02
117f04a9d8aSRajkumar Kasirajan #define VBUS_DET_DBNC1			0x01
118f04a9d8aSRajkumar Kasirajan 
119f04a9d8aSRajkumar Kasirajan static DEFINE_SPINLOCK(on_stat_lock);
120f04a9d8aSRajkumar Kasirajan static u8 turn_on_stat_mask = 0xFF;
121f04a9d8aSRajkumar Kasirajan static u8 turn_on_stat_set;
1226ef9418cSRickard Andersson static bool no_bm; /* No battery management */
1236ef9418cSRickard Andersson module_param(no_bm, bool, S_IRUGO);
1246ef9418cSRickard Andersson 
125d6255529SLinus Walleij #define AB9540_MODEM_CTRL2_REG			0x23
126d6255529SLinus Walleij #define AB9540_MODEM_CTRL2_SWDBBRSTN_BIT	BIT(2)
127d6255529SLinus Walleij 
12862579266SRabin Vincent /*
12962579266SRabin Vincent  * Map interrupt numbers to the LATCH and MASK register offsets, Interrupt
1302ced445eSLinus Walleij  * numbers are indexed into this array with (num / 8). The interupts are
1312ced445eSLinus Walleij  * defined in linux/mfd/ab8500.h
13262579266SRabin Vincent  *
13362579266SRabin Vincent  * This is one off from the register names, i.e. AB8500_IT_MASK1_REG is at
13462579266SRabin Vincent  * offset 0.
13562579266SRabin Vincent  */
1362ced445eSLinus Walleij /* AB8500 support */
13762579266SRabin Vincent static const int ab8500_irq_regoffset[AB8500_NUM_IRQ_REGS] = {
13892d50a41SMattias Wallin 	0, 1, 2, 3, 4, 6, 7, 8, 9, 11, 18, 19, 20, 21,
13962579266SRabin Vincent };
14062579266SRabin Vincent 
141*a29264b6SLee Jones /* AB9540 / AB8505 support */
142d6255529SLinus Walleij static const int ab9540_irq_regoffset[AB9540_NUM_IRQ_REGS] = {
143*a29264b6SLee Jones 	0, 1, 2, 3, 4, 6, 7, 8, 9, 11, 18, 19, 20, 21, 12, 13, 24, 5, 22, 23
144d6255529SLinus Walleij };
145d6255529SLinus Walleij 
1460f620837SLinus Walleij static const char ab8500_version_str[][7] = {
1470f620837SLinus Walleij 	[AB8500_VERSION_AB8500] = "AB8500",
1480f620837SLinus Walleij 	[AB8500_VERSION_AB8505] = "AB8505",
1490f620837SLinus Walleij 	[AB8500_VERSION_AB9540] = "AB9540",
1500f620837SLinus Walleij 	[AB8500_VERSION_AB8540] = "AB8540",
1510f620837SLinus Walleij };
1520f620837SLinus Walleij 
153822672a7SLee Jones static int ab8500_prcmu_write(struct ab8500 *ab8500, u16 addr, u8 data)
154d28f1db8SLee Jones {
155d28f1db8SLee Jones 	int ret;
156d28f1db8SLee Jones 
157d28f1db8SLee Jones 	ret = prcmu_abb_write((u8)(addr >> 8), (u8)(addr & 0xFF), &data, 1);
158d28f1db8SLee Jones 	if (ret < 0)
159d28f1db8SLee Jones 		dev_err(ab8500->dev, "prcmu i2c error %d\n", ret);
160d28f1db8SLee Jones 	return ret;
161d28f1db8SLee Jones }
162d28f1db8SLee Jones 
163822672a7SLee Jones static int ab8500_prcmu_write_masked(struct ab8500 *ab8500, u16 addr, u8 mask,
164d28f1db8SLee Jones 	u8 data)
165d28f1db8SLee Jones {
166d28f1db8SLee Jones 	int ret;
167d28f1db8SLee Jones 
168d28f1db8SLee Jones 	ret = prcmu_abb_write_masked((u8)(addr >> 8), (u8)(addr & 0xFF), &data,
169d28f1db8SLee Jones 		&mask, 1);
170d28f1db8SLee Jones 	if (ret < 0)
171d28f1db8SLee Jones 		dev_err(ab8500->dev, "prcmu i2c error %d\n", ret);
172d28f1db8SLee Jones 	return ret;
173d28f1db8SLee Jones }
174d28f1db8SLee Jones 
175822672a7SLee Jones static int ab8500_prcmu_read(struct ab8500 *ab8500, u16 addr)
176d28f1db8SLee Jones {
177d28f1db8SLee Jones 	int ret;
178d28f1db8SLee Jones 	u8 data;
179d28f1db8SLee Jones 
180d28f1db8SLee Jones 	ret = prcmu_abb_read((u8)(addr >> 8), (u8)(addr & 0xFF), &data, 1);
181d28f1db8SLee Jones 	if (ret < 0) {
182d28f1db8SLee Jones 		dev_err(ab8500->dev, "prcmu i2c error %d\n", ret);
183d28f1db8SLee Jones 		return ret;
184d28f1db8SLee Jones 	}
185d28f1db8SLee Jones 	return (int)data;
186d28f1db8SLee Jones }
187d28f1db8SLee Jones 
18847c16975SMattias Wallin static int ab8500_get_chip_id(struct device *dev)
18947c16975SMattias Wallin {
1906bce7bf1SMattias Wallin 	struct ab8500 *ab8500;
1916bce7bf1SMattias Wallin 
1926bce7bf1SMattias Wallin 	if (!dev)
1936bce7bf1SMattias Wallin 		return -EINVAL;
1946bce7bf1SMattias Wallin 	ab8500 = dev_get_drvdata(dev->parent);
1956bce7bf1SMattias Wallin 	return ab8500 ? (int)ab8500->chip_id : -EINVAL;
19647c16975SMattias Wallin }
19747c16975SMattias Wallin 
19847c16975SMattias Wallin static int set_register_interruptible(struct ab8500 *ab8500, u8 bank,
19947c16975SMattias Wallin 	u8 reg, u8 data)
20062579266SRabin Vincent {
20162579266SRabin Vincent 	int ret;
20247c16975SMattias Wallin 	/*
20347c16975SMattias Wallin 	 * Put the u8 bank and u8 register together into a an u16.
20447c16975SMattias Wallin 	 * The bank on higher 8 bits and register in lower 8 bits.
20547c16975SMattias Wallin 	 * */
20647c16975SMattias Wallin 	u16 addr = ((u16)bank) << 8 | reg;
20762579266SRabin Vincent 
20862579266SRabin Vincent 	dev_vdbg(ab8500->dev, "wr: addr %#x <= %#x\n", addr, data);
20962579266SRabin Vincent 
210392cbd1eSRabin Vincent 	mutex_lock(&ab8500->lock);
21147c16975SMattias Wallin 
21247c16975SMattias Wallin 	ret = ab8500->write(ab8500, addr, data);
21347c16975SMattias Wallin 	if (ret < 0)
21447c16975SMattias Wallin 		dev_err(ab8500->dev, "failed to write reg %#x: %d\n",
21547c16975SMattias Wallin 			addr, ret);
21647c16975SMattias Wallin 	mutex_unlock(&ab8500->lock);
21747c16975SMattias Wallin 
21847c16975SMattias Wallin 	return ret;
21947c16975SMattias Wallin }
22047c16975SMattias Wallin 
22147c16975SMattias Wallin static int ab8500_set_register(struct device *dev, u8 bank,
22247c16975SMattias Wallin 	u8 reg, u8 value)
22347c16975SMattias Wallin {
224112a80d2SJonas Aaberg 	int ret;
22547c16975SMattias Wallin 	struct ab8500 *ab8500 = dev_get_drvdata(dev->parent);
22647c16975SMattias Wallin 
227112a80d2SJonas Aaberg 	atomic_inc(&ab8500->transfer_ongoing);
228112a80d2SJonas Aaberg 	ret = set_register_interruptible(ab8500, bank, reg, value);
229112a80d2SJonas Aaberg 	atomic_dec(&ab8500->transfer_ongoing);
230112a80d2SJonas Aaberg 	return ret;
23147c16975SMattias Wallin }
23247c16975SMattias Wallin 
23347c16975SMattias Wallin static int get_register_interruptible(struct ab8500 *ab8500, u8 bank,
23447c16975SMattias Wallin 	u8 reg, u8 *value)
23547c16975SMattias Wallin {
23647c16975SMattias Wallin 	int ret;
23747c16975SMattias Wallin 	/* put the u8 bank and u8 reg together into a an u16.
23847c16975SMattias Wallin 	 * bank on higher 8 bits and reg in lower */
23947c16975SMattias Wallin 	u16 addr = ((u16)bank) << 8 | reg;
24047c16975SMattias Wallin 
241392cbd1eSRabin Vincent 	mutex_lock(&ab8500->lock);
24247c16975SMattias Wallin 
24347c16975SMattias Wallin 	ret = ab8500->read(ab8500, addr);
24447c16975SMattias Wallin 	if (ret < 0)
24547c16975SMattias Wallin 		dev_err(ab8500->dev, "failed to read reg %#x: %d\n",
24647c16975SMattias Wallin 			addr, ret);
24747c16975SMattias Wallin 	else
24847c16975SMattias Wallin 		*value = ret;
24947c16975SMattias Wallin 
25047c16975SMattias Wallin 	mutex_unlock(&ab8500->lock);
25147c16975SMattias Wallin 	dev_vdbg(ab8500->dev, "rd: addr %#x => data %#x\n", addr, ret);
25247c16975SMattias Wallin 
25347c16975SMattias Wallin 	return ret;
25447c16975SMattias Wallin }
25547c16975SMattias Wallin 
25647c16975SMattias Wallin static int ab8500_get_register(struct device *dev, u8 bank,
25747c16975SMattias Wallin 	u8 reg, u8 *value)
25847c16975SMattias Wallin {
259112a80d2SJonas Aaberg 	int ret;
26047c16975SMattias Wallin 	struct ab8500 *ab8500 = dev_get_drvdata(dev->parent);
26147c16975SMattias Wallin 
262112a80d2SJonas Aaberg 	atomic_inc(&ab8500->transfer_ongoing);
263112a80d2SJonas Aaberg 	ret = get_register_interruptible(ab8500, bank, reg, value);
264112a80d2SJonas Aaberg 	atomic_dec(&ab8500->transfer_ongoing);
265112a80d2SJonas Aaberg 	return ret;
26647c16975SMattias Wallin }
26747c16975SMattias Wallin 
26847c16975SMattias Wallin static int mask_and_set_register_interruptible(struct ab8500 *ab8500, u8 bank,
26947c16975SMattias Wallin 	u8 reg, u8 bitmask, u8 bitvalues)
27047c16975SMattias Wallin {
27147c16975SMattias Wallin 	int ret;
27247c16975SMattias Wallin 	/* put the u8 bank and u8 reg together into a an u16.
27347c16975SMattias Wallin 	 * bank on higher 8 bits and reg in lower */
27447c16975SMattias Wallin 	u16 addr = ((u16)bank) << 8 | reg;
27547c16975SMattias Wallin 
276392cbd1eSRabin Vincent 	mutex_lock(&ab8500->lock);
27747c16975SMattias Wallin 
278bc628fd1SMattias Nilsson 	if (ab8500->write_masked == NULL) {
279bc628fd1SMattias Nilsson 		u8 data;
280bc628fd1SMattias Nilsson 
28147c16975SMattias Wallin 		ret = ab8500->read(ab8500, addr);
28247c16975SMattias Wallin 		if (ret < 0) {
28347c16975SMattias Wallin 			dev_err(ab8500->dev, "failed to read reg %#x: %d\n",
28447c16975SMattias Wallin 				addr, ret);
28547c16975SMattias Wallin 			goto out;
28647c16975SMattias Wallin 		}
28747c16975SMattias Wallin 
28847c16975SMattias Wallin 		data = (u8)ret;
28947c16975SMattias Wallin 		data = (~bitmask & data) | (bitmask & bitvalues);
29047c16975SMattias Wallin 
29162579266SRabin Vincent 		ret = ab8500->write(ab8500, addr, data);
29262579266SRabin Vincent 		if (ret < 0)
29362579266SRabin Vincent 			dev_err(ab8500->dev, "failed to write reg %#x: %d\n",
29462579266SRabin Vincent 				addr, ret);
29562579266SRabin Vincent 
296bc628fd1SMattias Nilsson 		dev_vdbg(ab8500->dev, "mask: addr %#x => data %#x\n", addr,
297bc628fd1SMattias Nilsson 			data);
298bc628fd1SMattias Nilsson 		goto out;
299bc628fd1SMattias Nilsson 	}
300bc628fd1SMattias Nilsson 	ret = ab8500->write_masked(ab8500, addr, bitmask, bitvalues);
301bc628fd1SMattias Nilsson 	if (ret < 0)
302bc628fd1SMattias Nilsson 		dev_err(ab8500->dev, "failed to modify reg %#x: %d\n", addr,
303bc628fd1SMattias Nilsson 			ret);
30462579266SRabin Vincent out:
30562579266SRabin Vincent 	mutex_unlock(&ab8500->lock);
30662579266SRabin Vincent 	return ret;
30762579266SRabin Vincent }
30847c16975SMattias Wallin 
30947c16975SMattias Wallin static int ab8500_mask_and_set_register(struct device *dev,
31047c16975SMattias Wallin 	u8 bank, u8 reg, u8 bitmask, u8 bitvalues)
31147c16975SMattias Wallin {
312112a80d2SJonas Aaberg 	int ret;
31347c16975SMattias Wallin 	struct ab8500 *ab8500 = dev_get_drvdata(dev->parent);
31447c16975SMattias Wallin 
315112a80d2SJonas Aaberg 	atomic_inc(&ab8500->transfer_ongoing);
316112a80d2SJonas Aaberg 	ret= mask_and_set_register_interruptible(ab8500, bank, reg,
31747c16975SMattias Wallin 						 bitmask, bitvalues);
318112a80d2SJonas Aaberg 	atomic_dec(&ab8500->transfer_ongoing);
319112a80d2SJonas Aaberg 	return ret;
32047c16975SMattias Wallin }
32147c16975SMattias Wallin 
32247c16975SMattias Wallin static struct abx500_ops ab8500_ops = {
32347c16975SMattias Wallin 	.get_chip_id = ab8500_get_chip_id,
32447c16975SMattias Wallin 	.get_register = ab8500_get_register,
32547c16975SMattias Wallin 	.set_register = ab8500_set_register,
32647c16975SMattias Wallin 	.get_register_page = NULL,
32747c16975SMattias Wallin 	.set_register_page = NULL,
32847c16975SMattias Wallin 	.mask_and_set_register = ab8500_mask_and_set_register,
32947c16975SMattias Wallin 	.event_registers_startup_state_get = NULL,
33047c16975SMattias Wallin 	.startup_irq_enabled = NULL,
3311d843a6cSMian Yousaf Kaukab 	.dump_all_banks = ab8500_dump_all_banks,
33247c16975SMattias Wallin };
33362579266SRabin Vincent 
3349505a0a0SMark Brown static void ab8500_irq_lock(struct irq_data *data)
33562579266SRabin Vincent {
3369505a0a0SMark Brown 	struct ab8500 *ab8500 = irq_data_get_irq_chip_data(data);
33762579266SRabin Vincent 
33862579266SRabin Vincent 	mutex_lock(&ab8500->irq_lock);
339112a80d2SJonas Aaberg 	atomic_inc(&ab8500->transfer_ongoing);
34062579266SRabin Vincent }
34162579266SRabin Vincent 
3429505a0a0SMark Brown static void ab8500_irq_sync_unlock(struct irq_data *data)
34362579266SRabin Vincent {
3449505a0a0SMark Brown 	struct ab8500 *ab8500 = irq_data_get_irq_chip_data(data);
34562579266SRabin Vincent 	int i;
34662579266SRabin Vincent 
3472ced445eSLinus Walleij 	for (i = 0; i < ab8500->mask_size; i++) {
34862579266SRabin Vincent 		u8 old = ab8500->oldmask[i];
34962579266SRabin Vincent 		u8 new = ab8500->mask[i];
35062579266SRabin Vincent 		int reg;
35162579266SRabin Vincent 
35262579266SRabin Vincent 		if (new == old)
35362579266SRabin Vincent 			continue;
35462579266SRabin Vincent 
3550f620837SLinus Walleij 		/*
3560f620837SLinus Walleij 		 * Interrupt register 12 doesn't exist prior to AB8500 version
3570f620837SLinus Walleij 		 * 2.0
3580f620837SLinus Walleij 		 */
3590f620837SLinus Walleij 		if (ab8500->irq_reg_offset[i] == 11 &&
3600f620837SLinus Walleij 			is_ab8500_1p1_or_earlier(ab8500))
36192d50a41SMattias Wallin 			continue;
36292d50a41SMattias Wallin 
36362579266SRabin Vincent 		ab8500->oldmask[i] = new;
36462579266SRabin Vincent 
3652ced445eSLinus Walleij 		reg = AB8500_IT_MASK1_REG + ab8500->irq_reg_offset[i];
36647c16975SMattias Wallin 		set_register_interruptible(ab8500, AB8500_INTERRUPT, reg, new);
36762579266SRabin Vincent 	}
368112a80d2SJonas Aaberg 	atomic_dec(&ab8500->transfer_ongoing);
36962579266SRabin Vincent 	mutex_unlock(&ab8500->irq_lock);
37062579266SRabin Vincent }
37162579266SRabin Vincent 
3729505a0a0SMark Brown static void ab8500_irq_mask(struct irq_data *data)
37362579266SRabin Vincent {
3749505a0a0SMark Brown 	struct ab8500 *ab8500 = irq_data_get_irq_chip_data(data);
37506e589efSLee Jones 	int offset = data->hwirq;
37662579266SRabin Vincent 	int index = offset / 8;
37762579266SRabin Vincent 	int mask = 1 << (offset % 8);
37862579266SRabin Vincent 
37962579266SRabin Vincent 	ab8500->mask[index] |= mask;
3809c677b9bSLee Jones 
3819c677b9bSLee Jones 	/* The AB8500 GPIOs have two interrupts each (rising & falling). */
3829c677b9bSLee Jones 	if (offset >= AB8500_INT_GPIO6R && offset <= AB8500_INT_GPIO41R)
3839c677b9bSLee Jones 		ab8500->mask[index + 2] |= mask;
3849c677b9bSLee Jones 	if (offset >= AB9540_INT_GPIO50R && offset <= AB9540_INT_GPIO54R)
3859c677b9bSLee Jones 		ab8500->mask[index + 1] |= mask;
3869c677b9bSLee Jones 	if (offset == AB8540_INT_GPIO43R || offset == AB8540_INT_GPIO44R)
387e2ddf46aSLinus Walleij 		/* Here the falling IRQ is one bit lower */
388e2ddf46aSLinus Walleij 		ab8500->mask[index] |= (mask << 1);
38962579266SRabin Vincent }
39062579266SRabin Vincent 
3919505a0a0SMark Brown static void ab8500_irq_unmask(struct irq_data *data)
39262579266SRabin Vincent {
3939505a0a0SMark Brown 	struct ab8500 *ab8500 = irq_data_get_irq_chip_data(data);
3949c677b9bSLee Jones 	unsigned int type = irqd_get_trigger_type(data);
39506e589efSLee Jones 	int offset = data->hwirq;
39662579266SRabin Vincent 	int index = offset / 8;
39762579266SRabin Vincent 	int mask = 1 << (offset % 8);
39862579266SRabin Vincent 
3999c677b9bSLee Jones 	if (type & IRQ_TYPE_EDGE_RISING)
40062579266SRabin Vincent 		ab8500->mask[index] &= ~mask;
4019c677b9bSLee Jones 
4029c677b9bSLee Jones 	/* The AB8500 GPIOs have two interrupts each (rising & falling). */
4039c677b9bSLee Jones 	if (type & IRQ_TYPE_EDGE_FALLING) {
4049c677b9bSLee Jones 		if (offset >= AB8500_INT_GPIO6R && offset <= AB8500_INT_GPIO41R)
4059c677b9bSLee Jones 			ab8500->mask[index + 2] &= ~mask;
4069c677b9bSLee Jones 		else if (offset >= AB9540_INT_GPIO50R && offset <= AB9540_INT_GPIO54R)
4079c677b9bSLee Jones 			ab8500->mask[index + 1] &= ~mask;
4089c677b9bSLee Jones 		else if (offset == AB8540_INT_GPIO43R || offset == AB8540_INT_GPIO44R)
409e2ddf46aSLinus Walleij 			/* Here the falling IRQ is one bit lower */
410e2ddf46aSLinus Walleij 			ab8500->mask[index] &= ~(mask << 1);
4119c677b9bSLee Jones 		else
4129c677b9bSLee Jones 			ab8500->mask[index] &= ~mask;
413e2ddf46aSLinus Walleij 	} else {
4149c677b9bSLee Jones 		/* Satisfies the case where type is not set. */
41562579266SRabin Vincent 		ab8500->mask[index] &= ~mask;
41662579266SRabin Vincent 	}
417e2ddf46aSLinus Walleij }
41862579266SRabin Vincent 
41940f6e5a2SLee Jones static int ab8500_irq_set_type(struct irq_data *data, unsigned int type)
42040f6e5a2SLee Jones {
42140f6e5a2SLee Jones 	return 0;
42262579266SRabin Vincent }
42362579266SRabin Vincent 
42462579266SRabin Vincent static struct irq_chip ab8500_irq_chip = {
42562579266SRabin Vincent 	.name			= "ab8500",
4269505a0a0SMark Brown 	.irq_bus_lock		= ab8500_irq_lock,
4279505a0a0SMark Brown 	.irq_bus_sync_unlock	= ab8500_irq_sync_unlock,
4289505a0a0SMark Brown 	.irq_mask		= ab8500_irq_mask,
429e6f9306eSVirupax Sadashivpetimath 	.irq_disable		= ab8500_irq_mask,
4309505a0a0SMark Brown 	.irq_unmask		= ab8500_irq_unmask,
43140f6e5a2SLee Jones 	.irq_set_type		= ab8500_irq_set_type,
43262579266SRabin Vincent };
43362579266SRabin Vincent 
4347ccfe9b1SMichel JAOUEN static int ab8500_handle_hierarchical_line(struct ab8500 *ab8500,
4357ccfe9b1SMichel JAOUEN 					int latch_offset, u8 latch_val)
4367ccfe9b1SMichel JAOUEN {
4377ccfe9b1SMichel JAOUEN 	int int_bit = __ffs(latch_val);
4387ccfe9b1SMichel JAOUEN 	int line, i;
4397ccfe9b1SMichel JAOUEN 
4407ccfe9b1SMichel JAOUEN 	do {
4417ccfe9b1SMichel JAOUEN 		int_bit = __ffs(latch_val);
4427ccfe9b1SMichel JAOUEN 
4437ccfe9b1SMichel JAOUEN 		for (i = 0; i < ab8500->mask_size; i++)
4447ccfe9b1SMichel JAOUEN 			if (ab8500->irq_reg_offset[i] == latch_offset)
4457ccfe9b1SMichel JAOUEN 				break;
4467ccfe9b1SMichel JAOUEN 
4477ccfe9b1SMichel JAOUEN 		if (i >= ab8500->mask_size) {
4487ccfe9b1SMichel JAOUEN 			dev_err(ab8500->dev, "Register offset 0x%2x not declared\n",
4497ccfe9b1SMichel JAOUEN 					latch_offset);
4507ccfe9b1SMichel JAOUEN 			return -ENXIO;
4517ccfe9b1SMichel JAOUEN 		}
4527ccfe9b1SMichel JAOUEN 
4537ccfe9b1SMichel JAOUEN 		line = (i << 3) + int_bit;
4547ccfe9b1SMichel JAOUEN 		latch_val &= ~(1 << int_bit);
4557ccfe9b1SMichel JAOUEN 
456e2ddf46aSLinus Walleij 		/*
457e2ddf46aSLinus Walleij 		 * This handles the falling edge hwirqs from the GPIO
458e2ddf46aSLinus Walleij 		 * lines. Route them back to the line registered for the
459e2ddf46aSLinus Walleij 		 * rising IRQ, as this is merely a flag for the same IRQ
460e2ddf46aSLinus Walleij 		 * in linux terms.
461e2ddf46aSLinus Walleij 		 */
462e2ddf46aSLinus Walleij 		if (line >= AB8500_INT_GPIO6F && line <= AB8500_INT_GPIO41F)
463e2ddf46aSLinus Walleij 			line -= 16;
464e2ddf46aSLinus Walleij 		if (line >= AB9540_INT_GPIO50F && line <= AB9540_INT_GPIO54F)
465e2ddf46aSLinus Walleij 			line -= 8;
466e2ddf46aSLinus Walleij 		if (line == AB8540_INT_GPIO43F || line == AB8540_INT_GPIO44F)
467e2ddf46aSLinus Walleij 			line += 1;
468e2ddf46aSLinus Walleij 
4697ccfe9b1SMichel JAOUEN 		handle_nested_irq(ab8500->irq_base + line);
4707ccfe9b1SMichel JAOUEN 	} while (latch_val);
4717ccfe9b1SMichel JAOUEN 
4727ccfe9b1SMichel JAOUEN 	return 0;
4737ccfe9b1SMichel JAOUEN }
4747ccfe9b1SMichel JAOUEN 
4757ccfe9b1SMichel JAOUEN static int ab8500_handle_hierarchical_latch(struct ab8500 *ab8500,
4767ccfe9b1SMichel JAOUEN 					int hier_offset, u8 hier_val)
4777ccfe9b1SMichel JAOUEN {
4787ccfe9b1SMichel JAOUEN 	int latch_bit, status;
4797ccfe9b1SMichel JAOUEN 	u8 latch_offset, latch_val;
4807ccfe9b1SMichel JAOUEN 
4817ccfe9b1SMichel JAOUEN 	do {
4827ccfe9b1SMichel JAOUEN 		latch_bit = __ffs(hier_val);
4837ccfe9b1SMichel JAOUEN 		latch_offset = (hier_offset << 3) + latch_bit;
4847ccfe9b1SMichel JAOUEN 
4857ccfe9b1SMichel JAOUEN 		/* Fix inconsistent ITFromLatch25 bit mapping... */
4867ccfe9b1SMichel JAOUEN 		if (unlikely(latch_offset == 17))
4877ccfe9b1SMichel JAOUEN 			latch_offset = 24;
4887ccfe9b1SMichel JAOUEN 
4897ccfe9b1SMichel JAOUEN 		status = get_register_interruptible(ab8500,
4907ccfe9b1SMichel JAOUEN 				AB8500_INTERRUPT,
4917ccfe9b1SMichel JAOUEN 				AB8500_IT_LATCH1_REG + latch_offset,
4927ccfe9b1SMichel JAOUEN 				&latch_val);
4937ccfe9b1SMichel JAOUEN 		if (status < 0 || latch_val == 0)
4947ccfe9b1SMichel JAOUEN 			goto discard;
4957ccfe9b1SMichel JAOUEN 
4967ccfe9b1SMichel JAOUEN 		status = ab8500_handle_hierarchical_line(ab8500,
4977ccfe9b1SMichel JAOUEN 				latch_offset, latch_val);
4987ccfe9b1SMichel JAOUEN 		if (status < 0)
4997ccfe9b1SMichel JAOUEN 			return status;
5007ccfe9b1SMichel JAOUEN discard:
5017ccfe9b1SMichel JAOUEN 		hier_val &= ~(1 << latch_bit);
5027ccfe9b1SMichel JAOUEN 	} while (hier_val);
5037ccfe9b1SMichel JAOUEN 
5047ccfe9b1SMichel JAOUEN 	return 0;
5057ccfe9b1SMichel JAOUEN }
5067ccfe9b1SMichel JAOUEN 
5077ccfe9b1SMichel JAOUEN static irqreturn_t ab8500_hierarchical_irq(int irq, void *dev)
5087ccfe9b1SMichel JAOUEN {
5097ccfe9b1SMichel JAOUEN 	struct ab8500 *ab8500 = dev;
5107ccfe9b1SMichel JAOUEN 	u8 i;
5117ccfe9b1SMichel JAOUEN 
5127ccfe9b1SMichel JAOUEN 	dev_vdbg(ab8500->dev, "interrupt\n");
5137ccfe9b1SMichel JAOUEN 
5147ccfe9b1SMichel JAOUEN 	/*  Hierarchical interrupt version */
5157ccfe9b1SMichel JAOUEN 	for (i = 0; i < AB8500_IT_LATCHHIER_NUM; i++) {
5167ccfe9b1SMichel JAOUEN 		int status;
5177ccfe9b1SMichel JAOUEN 		u8 hier_val;
5187ccfe9b1SMichel JAOUEN 
5197ccfe9b1SMichel JAOUEN 		status = get_register_interruptible(ab8500, AB8500_INTERRUPT,
5207ccfe9b1SMichel JAOUEN 			AB8500_IT_LATCHHIER1_REG + i, &hier_val);
5217ccfe9b1SMichel JAOUEN 		if (status < 0 || hier_val == 0)
5227ccfe9b1SMichel JAOUEN 			continue;
5237ccfe9b1SMichel JAOUEN 
5247ccfe9b1SMichel JAOUEN 		status = ab8500_handle_hierarchical_latch(ab8500, i, hier_val);
5257ccfe9b1SMichel JAOUEN 		if (status < 0)
5267ccfe9b1SMichel JAOUEN 			break;
5277ccfe9b1SMichel JAOUEN 	}
5287ccfe9b1SMichel JAOUEN 	return IRQ_HANDLED;
5297ccfe9b1SMichel JAOUEN }
5307ccfe9b1SMichel JAOUEN 
53180633f05SLee Jones /**
53280633f05SLee Jones  * ab8500_irq_get_virq(): Map an interrupt on a chip to a virtual IRQ
53380633f05SLee Jones  *
53480633f05SLee Jones  * @ab8500: ab8500_irq controller to operate on.
53580633f05SLee Jones  * @irq: index of the interrupt requested in the chip IRQs
53680633f05SLee Jones  *
53780633f05SLee Jones  * Useful for drivers to request their own IRQs.
53880633f05SLee Jones  */
53980633f05SLee Jones static int ab8500_irq_get_virq(struct ab8500 *ab8500, int irq)
54080633f05SLee Jones {
54180633f05SLee Jones 	if (!ab8500)
54280633f05SLee Jones 		return -EINVAL;
54380633f05SLee Jones 
54480633f05SLee Jones 	return irq_create_mapping(ab8500->domain, irq);
54580633f05SLee Jones }
54680633f05SLee Jones 
54762579266SRabin Vincent static irqreturn_t ab8500_irq(int irq, void *dev)
54862579266SRabin Vincent {
54962579266SRabin Vincent 	struct ab8500 *ab8500 = dev;
55062579266SRabin Vincent 	int i;
55162579266SRabin Vincent 
55262579266SRabin Vincent 	dev_vdbg(ab8500->dev, "interrupt\n");
55362579266SRabin Vincent 
554112a80d2SJonas Aaberg 	atomic_inc(&ab8500->transfer_ongoing);
555112a80d2SJonas Aaberg 
5562ced445eSLinus Walleij 	for (i = 0; i < ab8500->mask_size; i++) {
5572ced445eSLinus Walleij 		int regoffset = ab8500->irq_reg_offset[i];
55862579266SRabin Vincent 		int status;
55947c16975SMattias Wallin 		u8 value;
56062579266SRabin Vincent 
5610f620837SLinus Walleij 		/*
5620f620837SLinus Walleij 		 * Interrupt register 12 doesn't exist prior to AB8500 version
5630f620837SLinus Walleij 		 * 2.0
5640f620837SLinus Walleij 		 */
5650f620837SLinus Walleij 		if (regoffset == 11 && is_ab8500_1p1_or_earlier(ab8500))
56692d50a41SMattias Wallin 			continue;
56792d50a41SMattias Wallin 
56847c16975SMattias Wallin 		status = get_register_interruptible(ab8500, AB8500_INTERRUPT,
56947c16975SMattias Wallin 			AB8500_IT_LATCH1_REG + regoffset, &value);
57047c16975SMattias Wallin 		if (status < 0 || value == 0)
57162579266SRabin Vincent 			continue;
57262579266SRabin Vincent 
57362579266SRabin Vincent 		do {
57488aec4f7SMattias Wallin 			int bit = __ffs(value);
57562579266SRabin Vincent 			int line = i * 8 + bit;
5760a37fc56SLee Jones 			int virq = ab8500_irq_get_virq(ab8500, line);
57762579266SRabin Vincent 
5780a37fc56SLee Jones 			handle_nested_irq(virq);
5798f0eb43bSBengt Jonsson 			ab8500_debug_register_interrupt(line);
58047c16975SMattias Wallin 			value &= ~(1 << bit);
581112a80d2SJonas Aaberg 
58247c16975SMattias Wallin 		} while (value);
58362579266SRabin Vincent 	}
584112a80d2SJonas Aaberg 	atomic_dec(&ab8500->transfer_ongoing);
58562579266SRabin Vincent 	return IRQ_HANDLED;
58662579266SRabin Vincent }
58762579266SRabin Vincent 
58806e589efSLee Jones static int ab8500_irq_map(struct irq_domain *d, unsigned int virq,
58906e589efSLee Jones 				irq_hw_number_t hwirq)
59006e589efSLee Jones {
59106e589efSLee Jones 	struct ab8500 *ab8500 = d->host_data;
59206e589efSLee Jones 
59306e589efSLee Jones 	if (!ab8500)
59406e589efSLee Jones 		return -EINVAL;
59506e589efSLee Jones 
59606e589efSLee Jones 	irq_set_chip_data(virq, ab8500);
59706e589efSLee Jones 	irq_set_chip_and_handler(virq, &ab8500_irq_chip,
59806e589efSLee Jones 				handle_simple_irq);
59906e589efSLee Jones 	irq_set_nested_thread(virq, 1);
60006e589efSLee Jones #ifdef CONFIG_ARM
60106e589efSLee Jones 	set_irq_flags(virq, IRQF_VALID);
60206e589efSLee Jones #else
60306e589efSLee Jones 	irq_set_noprobe(virq);
60406e589efSLee Jones #endif
60562579266SRabin Vincent 
60662579266SRabin Vincent 	return 0;
60762579266SRabin Vincent }
60862579266SRabin Vincent 
60906e589efSLee Jones static struct irq_domain_ops ab8500_irq_ops = {
61006e589efSLee Jones         .map    = ab8500_irq_map,
61106e589efSLee Jones         .xlate  = irq_domain_xlate_twocell,
61206e589efSLee Jones };
61306e589efSLee Jones 
61406e589efSLee Jones static int ab8500_irq_init(struct ab8500 *ab8500, struct device_node *np)
61562579266SRabin Vincent {
6162ced445eSLinus Walleij 	int num_irqs;
61762579266SRabin Vincent 
618d6255529SLinus Walleij 	if (is_ab9540(ab8500))
619d6255529SLinus Walleij 		num_irqs = AB9540_NR_IRQS;
620a982362cSBengt Jonsson 	else if (is_ab8505(ab8500))
621a982362cSBengt Jonsson 		num_irqs = AB8505_NR_IRQS;
622d6255529SLinus Walleij 	else
6232ced445eSLinus Walleij 		num_irqs = AB8500_NR_IRQS;
6242ced445eSLinus Walleij 
625f1d11f39SLinus Walleij 	/* If ->irq_base is zero this will give a linear mapping */
626f1d11f39SLinus Walleij 	ab8500->domain = irq_domain_add_simple(NULL,
627f1d11f39SLinus Walleij 			num_irqs, ab8500->irq_base,
628f1d11f39SLinus Walleij 			&ab8500_irq_ops, ab8500);
62906e589efSLee Jones 
63006e589efSLee Jones 	if (!ab8500->domain) {
63106e589efSLee Jones 		dev_err(ab8500->dev, "Failed to create irqdomain\n");
63206e589efSLee Jones 		return -ENOSYS;
63306e589efSLee Jones 	}
63406e589efSLee Jones 
63506e589efSLee Jones 	return 0;
63662579266SRabin Vincent }
63762579266SRabin Vincent 
638112a80d2SJonas Aaberg int ab8500_suspend(struct ab8500 *ab8500)
639112a80d2SJonas Aaberg {
640112a80d2SJonas Aaberg 	if (atomic_read(&ab8500->transfer_ongoing))
641112a80d2SJonas Aaberg 		return -EINVAL;
642112a80d2SJonas Aaberg 	else
643112a80d2SJonas Aaberg 		return 0;
644112a80d2SJonas Aaberg }
645112a80d2SJonas Aaberg 
646a9e9ce4cSBill Pemberton static struct resource ab8500_gpadc_resources[] = {
64762579266SRabin Vincent 	{
64862579266SRabin Vincent 		.name	= "HW_CONV_END",
64962579266SRabin Vincent 		.start	= AB8500_INT_GP_HW_ADC_CONV_END,
65062579266SRabin Vincent 		.end	= AB8500_INT_GP_HW_ADC_CONV_END,
65162579266SRabin Vincent 		.flags	= IORESOURCE_IRQ,
65262579266SRabin Vincent 	},
65362579266SRabin Vincent 	{
65462579266SRabin Vincent 		.name	= "SW_CONV_END",
65562579266SRabin Vincent 		.start	= AB8500_INT_GP_SW_ADC_CONV_END,
65662579266SRabin Vincent 		.end	= AB8500_INT_GP_SW_ADC_CONV_END,
65762579266SRabin Vincent 		.flags	= IORESOURCE_IRQ,
65862579266SRabin Vincent 	},
65962579266SRabin Vincent };
66062579266SRabin Vincent 
661a9e9ce4cSBill Pemberton static struct resource ab8500_rtc_resources[] = {
66262579266SRabin Vincent 	{
66362579266SRabin Vincent 		.name	= "60S",
66462579266SRabin Vincent 		.start	= AB8500_INT_RTC_60S,
66562579266SRabin Vincent 		.end	= AB8500_INT_RTC_60S,
66662579266SRabin Vincent 		.flags	= IORESOURCE_IRQ,
66762579266SRabin Vincent 	},
66862579266SRabin Vincent 	{
66962579266SRabin Vincent 		.name	= "ALARM",
67062579266SRabin Vincent 		.start	= AB8500_INT_RTC_ALARM,
67162579266SRabin Vincent 		.end	= AB8500_INT_RTC_ALARM,
67262579266SRabin Vincent 		.flags	= IORESOURCE_IRQ,
67362579266SRabin Vincent 	},
67462579266SRabin Vincent };
67562579266SRabin Vincent 
676a9e9ce4cSBill Pemberton static struct resource ab8500_poweronkey_db_resources[] = {
67777686517SSundar R Iyer 	{
67877686517SSundar R Iyer 		.name	= "ONKEY_DBF",
67977686517SSundar R Iyer 		.start	= AB8500_INT_PON_KEY1DB_F,
68077686517SSundar R Iyer 		.end	= AB8500_INT_PON_KEY1DB_F,
68177686517SSundar R Iyer 		.flags	= IORESOURCE_IRQ,
68277686517SSundar R Iyer 	},
68377686517SSundar R Iyer 	{
68477686517SSundar R Iyer 		.name	= "ONKEY_DBR",
68577686517SSundar R Iyer 		.start	= AB8500_INT_PON_KEY1DB_R,
68677686517SSundar R Iyer 		.end	= AB8500_INT_PON_KEY1DB_R,
68777686517SSundar R Iyer 		.flags	= IORESOURCE_IRQ,
68877686517SSundar R Iyer 	},
68977686517SSundar R Iyer };
69077686517SSundar R Iyer 
691a9e9ce4cSBill Pemberton static struct resource ab8500_av_acc_detect_resources[] = {
692e098adedSMattias Wallin 	{
6936af75ecdSLinus Walleij 	       .name = "ACC_DETECT_1DB_F",
6946af75ecdSLinus Walleij 	       .start = AB8500_INT_ACC_DETECT_1DB_F,
6956af75ecdSLinus Walleij 	       .end = AB8500_INT_ACC_DETECT_1DB_F,
696e098adedSMattias Wallin 	       .flags = IORESOURCE_IRQ,
697e098adedSMattias Wallin 	},
698e098adedSMattias Wallin 	{
6996af75ecdSLinus Walleij 	       .name = "ACC_DETECT_1DB_R",
7006af75ecdSLinus Walleij 	       .start = AB8500_INT_ACC_DETECT_1DB_R,
7016af75ecdSLinus Walleij 	       .end = AB8500_INT_ACC_DETECT_1DB_R,
702e098adedSMattias Wallin 	       .flags = IORESOURCE_IRQ,
703e098adedSMattias Wallin 	},
704e098adedSMattias Wallin 	{
7056af75ecdSLinus Walleij 	       .name = "ACC_DETECT_21DB_F",
7066af75ecdSLinus Walleij 	       .start = AB8500_INT_ACC_DETECT_21DB_F,
7076af75ecdSLinus Walleij 	       .end = AB8500_INT_ACC_DETECT_21DB_F,
7086af75ecdSLinus Walleij 	       .flags = IORESOURCE_IRQ,
7096af75ecdSLinus Walleij 	},
7106af75ecdSLinus Walleij 	{
7116af75ecdSLinus Walleij 	       .name = "ACC_DETECT_21DB_R",
7126af75ecdSLinus Walleij 	       .start = AB8500_INT_ACC_DETECT_21DB_R,
7136af75ecdSLinus Walleij 	       .end = AB8500_INT_ACC_DETECT_21DB_R,
7146af75ecdSLinus Walleij 	       .flags = IORESOURCE_IRQ,
7156af75ecdSLinus Walleij 	},
7166af75ecdSLinus Walleij 	{
7176af75ecdSLinus Walleij 	       .name = "ACC_DETECT_22DB_F",
7186af75ecdSLinus Walleij 	       .start = AB8500_INT_ACC_DETECT_22DB_F,
7196af75ecdSLinus Walleij 	       .end = AB8500_INT_ACC_DETECT_22DB_F,
7206af75ecdSLinus Walleij 	       .flags = IORESOURCE_IRQ,
7216af75ecdSLinus Walleij 	},
7226af75ecdSLinus Walleij 	{
7236af75ecdSLinus Walleij 	       .name = "ACC_DETECT_22DB_R",
7246af75ecdSLinus Walleij 	       .start = AB8500_INT_ACC_DETECT_22DB_R,
7256af75ecdSLinus Walleij 	       .end = AB8500_INT_ACC_DETECT_22DB_R,
7266af75ecdSLinus Walleij 	       .flags = IORESOURCE_IRQ,
7276af75ecdSLinus Walleij 	},
7286af75ecdSLinus Walleij };
7296af75ecdSLinus Walleij 
730a9e9ce4cSBill Pemberton static struct resource ab8500_charger_resources[] = {
7316af75ecdSLinus Walleij 	{
732e098adedSMattias Wallin 		.name = "MAIN_CH_UNPLUG_DET",
733e098adedSMattias Wallin 		.start = AB8500_INT_MAIN_CH_UNPLUG_DET,
734e098adedSMattias Wallin 		.end = AB8500_INT_MAIN_CH_UNPLUG_DET,
735e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
736e098adedSMattias Wallin 	},
737e098adedSMattias Wallin 	{
738e098adedSMattias Wallin 		.name = "MAIN_CHARGE_PLUG_DET",
739e098adedSMattias Wallin 		.start = AB8500_INT_MAIN_CH_PLUG_DET,
740e098adedSMattias Wallin 		.end = AB8500_INT_MAIN_CH_PLUG_DET,
741e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
742e098adedSMattias Wallin 	},
743e098adedSMattias Wallin 	{
744e098adedSMattias Wallin 		.name = "VBUS_DET_R",
745e098adedSMattias Wallin 		.start = AB8500_INT_VBUS_DET_R,
746e098adedSMattias Wallin 		.end = AB8500_INT_VBUS_DET_R,
747e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
748e098adedSMattias Wallin 	},
749e098adedSMattias Wallin 	{
7506af75ecdSLinus Walleij 		.name = "VBUS_DET_F",
7516af75ecdSLinus Walleij 		.start = AB8500_INT_VBUS_DET_F,
7526af75ecdSLinus Walleij 		.end = AB8500_INT_VBUS_DET_F,
753e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
754e098adedSMattias Wallin 	},
755e098adedSMattias Wallin 	{
7566af75ecdSLinus Walleij 		.name = "USB_LINK_STATUS",
7576af75ecdSLinus Walleij 		.start = AB8500_INT_USB_LINK_STATUS,
7586af75ecdSLinus Walleij 		.end = AB8500_INT_USB_LINK_STATUS,
7596af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
7606af75ecdSLinus Walleij 	},
7616af75ecdSLinus Walleij 	{
762e098adedSMattias Wallin 		.name = "VBUS_OVV",
763e098adedSMattias Wallin 		.start = AB8500_INT_VBUS_OVV,
764e098adedSMattias Wallin 		.end = AB8500_INT_VBUS_OVV,
765e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
766e098adedSMattias Wallin 	},
767e098adedSMattias Wallin 	{
7686af75ecdSLinus Walleij 		.name = "USB_CH_TH_PROT_R",
7696af75ecdSLinus Walleij 		.start = AB8500_INT_USB_CH_TH_PROT_R,
7706af75ecdSLinus Walleij 		.end = AB8500_INT_USB_CH_TH_PROT_R,
771e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
772e098adedSMattias Wallin 	},
773e098adedSMattias Wallin 	{
7746af75ecdSLinus Walleij 		.name = "USB_CH_TH_PROT_F",
7756af75ecdSLinus Walleij 		.start = AB8500_INT_USB_CH_TH_PROT_F,
7766af75ecdSLinus Walleij 		.end = AB8500_INT_USB_CH_TH_PROT_F,
777e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
778e098adedSMattias Wallin 	},
779e098adedSMattias Wallin 	{
7806af75ecdSLinus Walleij 		.name = "MAIN_EXT_CH_NOT_OK",
7816af75ecdSLinus Walleij 		.start = AB8500_INT_MAIN_EXT_CH_NOT_OK,
7826af75ecdSLinus Walleij 		.end = AB8500_INT_MAIN_EXT_CH_NOT_OK,
7836af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
7846af75ecdSLinus Walleij 	},
7856af75ecdSLinus Walleij 	{
7866af75ecdSLinus Walleij 		.name = "MAIN_CH_TH_PROT_R",
7876af75ecdSLinus Walleij 		.start = AB8500_INT_MAIN_CH_TH_PROT_R,
7886af75ecdSLinus Walleij 		.end = AB8500_INT_MAIN_CH_TH_PROT_R,
7896af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
7906af75ecdSLinus Walleij 	},
7916af75ecdSLinus Walleij 	{
7926af75ecdSLinus Walleij 		.name = "MAIN_CH_TH_PROT_F",
7936af75ecdSLinus Walleij 		.start = AB8500_INT_MAIN_CH_TH_PROT_F,
7946af75ecdSLinus Walleij 		.end = AB8500_INT_MAIN_CH_TH_PROT_F,
7956af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
7966af75ecdSLinus Walleij 	},
7976af75ecdSLinus Walleij 	{
7986af75ecdSLinus Walleij 		.name = "USB_CHARGER_NOT_OKR",
799a982362cSBengt Jonsson 		.start = AB8500_INT_USB_CHARGER_NOT_OKR,
800a982362cSBengt Jonsson 		.end = AB8500_INT_USB_CHARGER_NOT_OKR,
8016af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
8026af75ecdSLinus Walleij 	},
8036af75ecdSLinus Walleij 	{
8046af75ecdSLinus Walleij 		.name = "CH_WD_EXP",
8056af75ecdSLinus Walleij 		.start = AB8500_INT_CH_WD_EXP,
8066af75ecdSLinus Walleij 		.end = AB8500_INT_CH_WD_EXP,
8076af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
8086af75ecdSLinus Walleij 	},
80934c11a70SPaer-Olof Haakansson 	{
81034c11a70SPaer-Olof Haakansson 		.name = "VBUS_CH_DROP_END",
81134c11a70SPaer-Olof Haakansson 		.start = AB8500_INT_VBUS_CH_DROP_END,
81234c11a70SPaer-Olof Haakansson 		.end = AB8500_INT_VBUS_CH_DROP_END,
81334c11a70SPaer-Olof Haakansson 		.flags = IORESOURCE_IRQ,
81434c11a70SPaer-Olof Haakansson 	},
8156af75ecdSLinus Walleij };
8166af75ecdSLinus Walleij 
817a9e9ce4cSBill Pemberton static struct resource ab8500_btemp_resources[] = {
8186af75ecdSLinus Walleij 	{
8196af75ecdSLinus Walleij 		.name = "BAT_CTRL_INDB",
8206af75ecdSLinus Walleij 		.start = AB8500_INT_BAT_CTRL_INDB,
8216af75ecdSLinus Walleij 		.end = AB8500_INT_BAT_CTRL_INDB,
822e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
823e098adedSMattias Wallin 	},
824e098adedSMattias Wallin 	{
825e098adedSMattias Wallin 		.name = "BTEMP_LOW",
826e098adedSMattias Wallin 		.start = AB8500_INT_BTEMP_LOW,
827e098adedSMattias Wallin 		.end = AB8500_INT_BTEMP_LOW,
828e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
829e098adedSMattias Wallin 	},
830e098adedSMattias Wallin 	{
831e098adedSMattias Wallin 		.name = "BTEMP_HIGH",
832e098adedSMattias Wallin 		.start = AB8500_INT_BTEMP_HIGH,
833e098adedSMattias Wallin 		.end = AB8500_INT_BTEMP_HIGH,
834e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
835e098adedSMattias Wallin 	},
836e098adedSMattias Wallin 	{
8376af75ecdSLinus Walleij 		.name = "BTEMP_LOW_MEDIUM",
8386af75ecdSLinus Walleij 		.start = AB8500_INT_BTEMP_LOW_MEDIUM,
8396af75ecdSLinus Walleij 		.end = AB8500_INT_BTEMP_LOW_MEDIUM,
840e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
841e098adedSMattias Wallin 	},
842e098adedSMattias Wallin 	{
8436af75ecdSLinus Walleij 		.name = "BTEMP_MEDIUM_HIGH",
8446af75ecdSLinus Walleij 		.start = AB8500_INT_BTEMP_MEDIUM_HIGH,
8456af75ecdSLinus Walleij 		.end = AB8500_INT_BTEMP_MEDIUM_HIGH,
846e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
847e098adedSMattias Wallin 	},
848e098adedSMattias Wallin };
849e098adedSMattias Wallin 
850a9e9ce4cSBill Pemberton static struct resource ab8500_fg_resources[] = {
8516af75ecdSLinus Walleij 	{
8526af75ecdSLinus Walleij 		.name = "NCONV_ACCU",
8536af75ecdSLinus Walleij 		.start = AB8500_INT_CCN_CONV_ACC,
8546af75ecdSLinus Walleij 		.end = AB8500_INT_CCN_CONV_ACC,
8556af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
8566af75ecdSLinus Walleij 	},
8576af75ecdSLinus Walleij 	{
8586af75ecdSLinus Walleij 		.name = "BATT_OVV",
8596af75ecdSLinus Walleij 		.start = AB8500_INT_BATT_OVV,
8606af75ecdSLinus Walleij 		.end = AB8500_INT_BATT_OVV,
8616af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
8626af75ecdSLinus Walleij 	},
8636af75ecdSLinus Walleij 	{
8646af75ecdSLinus Walleij 		.name = "LOW_BAT_F",
8656af75ecdSLinus Walleij 		.start = AB8500_INT_LOW_BAT_F,
8666af75ecdSLinus Walleij 		.end = AB8500_INT_LOW_BAT_F,
8676af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
8686af75ecdSLinus Walleij 	},
8696af75ecdSLinus Walleij 	{
8706af75ecdSLinus Walleij 		.name = "LOW_BAT_R",
8716af75ecdSLinus Walleij 		.start = AB8500_INT_LOW_BAT_R,
8726af75ecdSLinus Walleij 		.end = AB8500_INT_LOW_BAT_R,
8736af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
8746af75ecdSLinus Walleij 	},
8756af75ecdSLinus Walleij 	{
8766af75ecdSLinus Walleij 		.name = "CC_INT_CALIB",
8776af75ecdSLinus Walleij 		.start = AB8500_INT_CC_INT_CALIB,
8786af75ecdSLinus Walleij 		.end = AB8500_INT_CC_INT_CALIB,
8796af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
8806af75ecdSLinus Walleij 	},
881a982362cSBengt Jonsson 	{
882a982362cSBengt Jonsson 		.name = "CCEOC",
883a982362cSBengt Jonsson 		.start = AB8500_INT_CCEOC,
884a982362cSBengt Jonsson 		.end = AB8500_INT_CCEOC,
885a982362cSBengt Jonsson 		.flags = IORESOURCE_IRQ,
886a982362cSBengt Jonsson 	},
8876af75ecdSLinus Walleij };
8886af75ecdSLinus Walleij 
889a9e9ce4cSBill Pemberton static struct resource ab8500_chargalg_resources[] = {};
8906af75ecdSLinus Walleij 
891df720647SAxel Lin #ifdef CONFIG_DEBUG_FS
892a9e9ce4cSBill Pemberton static struct resource ab8500_debug_resources[] = {
893e098adedSMattias Wallin 	{
894e098adedSMattias Wallin 		.name	= "IRQ_FIRST",
895e098adedSMattias Wallin 		.start	= AB8500_INT_MAIN_EXT_CH_NOT_OK,
896e098adedSMattias Wallin 		.end	= AB8500_INT_MAIN_EXT_CH_NOT_OK,
897e098adedSMattias Wallin 		.flags	= IORESOURCE_IRQ,
898e098adedSMattias Wallin 	},
899e098adedSMattias Wallin 	{
900e098adedSMattias Wallin 		.name	= "IRQ_LAST",
901a982362cSBengt Jonsson 		.start	= AB8500_INT_XTAL32K_KO,
902a982362cSBengt Jonsson 		.end	= AB8500_INT_XTAL32K_KO,
903e098adedSMattias Wallin 		.flags	= IORESOURCE_IRQ,
904e098adedSMattias Wallin 	},
905e098adedSMattias Wallin };
906df720647SAxel Lin #endif
907e098adedSMattias Wallin 
908a9e9ce4cSBill Pemberton static struct resource ab8500_usb_resources[] = {
909e098adedSMattias Wallin 	{
910e098adedSMattias Wallin 		.name = "ID_WAKEUP_R",
911e098adedSMattias Wallin 		.start = AB8500_INT_ID_WAKEUP_R,
912e098adedSMattias Wallin 		.end = AB8500_INT_ID_WAKEUP_R,
913e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
914e098adedSMattias Wallin 	},
915e098adedSMattias Wallin 	{
916e098adedSMattias Wallin 		.name = "ID_WAKEUP_F",
917e098adedSMattias Wallin 		.start = AB8500_INT_ID_WAKEUP_F,
918e098adedSMattias Wallin 		.end = AB8500_INT_ID_WAKEUP_F,
919e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
920e098adedSMattias Wallin 	},
921e098adedSMattias Wallin 	{
922e098adedSMattias Wallin 		.name = "VBUS_DET_F",
923e098adedSMattias Wallin 		.start = AB8500_INT_VBUS_DET_F,
924e098adedSMattias Wallin 		.end = AB8500_INT_VBUS_DET_F,
925e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
926e098adedSMattias Wallin 	},
927e098adedSMattias Wallin 	{
928e098adedSMattias Wallin 		.name = "VBUS_DET_R",
929e098adedSMattias Wallin 		.start = AB8500_INT_VBUS_DET_R,
930e098adedSMattias Wallin 		.end = AB8500_INT_VBUS_DET_R,
931e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
932e098adedSMattias Wallin 	},
93392d50a41SMattias Wallin 	{
93492d50a41SMattias Wallin 		.name = "USB_LINK_STATUS",
93592d50a41SMattias Wallin 		.start = AB8500_INT_USB_LINK_STATUS,
93692d50a41SMattias Wallin 		.end = AB8500_INT_USB_LINK_STATUS,
93792d50a41SMattias Wallin 		.flags = IORESOURCE_IRQ,
93892d50a41SMattias Wallin 	},
9396af75ecdSLinus Walleij 	{
9406af75ecdSLinus Walleij 		.name = "USB_ADP_PROBE_PLUG",
9416af75ecdSLinus Walleij 		.start = AB8500_INT_ADP_PROBE_PLUG,
9426af75ecdSLinus Walleij 		.end = AB8500_INT_ADP_PROBE_PLUG,
9436af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
9446af75ecdSLinus Walleij 	},
9456af75ecdSLinus Walleij 	{
9466af75ecdSLinus Walleij 		.name = "USB_ADP_PROBE_UNPLUG",
9476af75ecdSLinus Walleij 		.start = AB8500_INT_ADP_PROBE_UNPLUG,
9486af75ecdSLinus Walleij 		.end = AB8500_INT_ADP_PROBE_UNPLUG,
9496af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
9506af75ecdSLinus Walleij 	},
951e098adedSMattias Wallin };
952e098adedSMattias Wallin 
953a9e9ce4cSBill Pemberton static struct resource ab8505_iddet_resources[] = {
95444f72e53SVirupax Sadashivpetimath 	{
95544f72e53SVirupax Sadashivpetimath 		.name  = "KeyDeglitch",
95644f72e53SVirupax Sadashivpetimath 		.start = AB8505_INT_KEYDEGLITCH,
95744f72e53SVirupax Sadashivpetimath 		.end   = AB8505_INT_KEYDEGLITCH,
95844f72e53SVirupax Sadashivpetimath 		.flags = IORESOURCE_IRQ,
95944f72e53SVirupax Sadashivpetimath 	},
96044f72e53SVirupax Sadashivpetimath 	{
96144f72e53SVirupax Sadashivpetimath 		.name  = "KP",
96244f72e53SVirupax Sadashivpetimath 		.start = AB8505_INT_KP,
96344f72e53SVirupax Sadashivpetimath 		.end   = AB8505_INT_KP,
96444f72e53SVirupax Sadashivpetimath 		.flags = IORESOURCE_IRQ,
96544f72e53SVirupax Sadashivpetimath 	},
96644f72e53SVirupax Sadashivpetimath 	{
96744f72e53SVirupax Sadashivpetimath 		.name  = "IKP",
96844f72e53SVirupax Sadashivpetimath 		.start = AB8505_INT_IKP,
96944f72e53SVirupax Sadashivpetimath 		.end   = AB8505_INT_IKP,
97044f72e53SVirupax Sadashivpetimath 		.flags = IORESOURCE_IRQ,
97144f72e53SVirupax Sadashivpetimath 	},
97244f72e53SVirupax Sadashivpetimath 	{
97344f72e53SVirupax Sadashivpetimath 		.name  = "IKR",
97444f72e53SVirupax Sadashivpetimath 		.start = AB8505_INT_IKR,
97544f72e53SVirupax Sadashivpetimath 		.end   = AB8505_INT_IKR,
97644f72e53SVirupax Sadashivpetimath 		.flags = IORESOURCE_IRQ,
97744f72e53SVirupax Sadashivpetimath 	},
97844f72e53SVirupax Sadashivpetimath 	{
97944f72e53SVirupax Sadashivpetimath 		.name  = "KeyStuck",
98044f72e53SVirupax Sadashivpetimath 		.start = AB8505_INT_KEYSTUCK,
98144f72e53SVirupax Sadashivpetimath 		.end   = AB8505_INT_KEYSTUCK,
98244f72e53SVirupax Sadashivpetimath 		.flags = IORESOURCE_IRQ,
98344f72e53SVirupax Sadashivpetimath 	},
98444f72e53SVirupax Sadashivpetimath };
98544f72e53SVirupax Sadashivpetimath 
986a9e9ce4cSBill Pemberton static struct resource ab8500_temp_resources[] = {
987e098adedSMattias Wallin 	{
988151621a7SHongbo Zhang 		.name  = "ABX500_TEMP_WARM",
989e098adedSMattias Wallin 		.start = AB8500_INT_TEMP_WARM,
990e098adedSMattias Wallin 		.end   = AB8500_INT_TEMP_WARM,
991e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
992e098adedSMattias Wallin 	},
993e098adedSMattias Wallin };
994e098adedSMattias Wallin 
995a9e9ce4cSBill Pemberton static struct mfd_cell abx500_common_devs[] = {
9965814fc35SMattias Wallin #ifdef CONFIG_DEBUG_FS
9975814fc35SMattias Wallin 	{
9985814fc35SMattias Wallin 		.name = "ab8500-debug",
999bad76991SLee Jones 		.of_compatible = "stericsson,ab8500-debug",
1000e098adedSMattias Wallin 		.num_resources = ARRAY_SIZE(ab8500_debug_resources),
1001e098adedSMattias Wallin 		.resources = ab8500_debug_resources,
10025814fc35SMattias Wallin 	},
10035814fc35SMattias Wallin #endif
100462579266SRabin Vincent 	{
1005e098adedSMattias Wallin 		.name = "ab8500-sysctrl",
1006bad76991SLee Jones 		.of_compatible = "stericsson,ab8500-sysctrl",
1007e098adedSMattias Wallin 	},
1008e098adedSMattias Wallin 	{
1009e098adedSMattias Wallin 		.name = "ab8500-regulator",
1010bad76991SLee Jones 		.of_compatible = "stericsson,ab8500-regulator",
1011e098adedSMattias Wallin 	},
1012e098adedSMattias Wallin 	{
1013916a871cSUlf Hansson 		.name = "abx500-clk",
1014916a871cSUlf Hansson 		.of_compatible = "stericsson,abx500-clk",
1015916a871cSUlf Hansson 	},
1016916a871cSUlf Hansson 	{
101762579266SRabin Vincent 		.name = "ab8500-gpadc",
1018bad76991SLee Jones 		.of_compatible = "stericsson,ab8500-gpadc",
101962579266SRabin Vincent 		.num_resources = ARRAY_SIZE(ab8500_gpadc_resources),
102062579266SRabin Vincent 		.resources = ab8500_gpadc_resources,
102162579266SRabin Vincent 	},
102262579266SRabin Vincent 	{
102362579266SRabin Vincent 		.name = "ab8500-rtc",
1024bad76991SLee Jones 		.of_compatible = "stericsson,ab8500-rtc",
102562579266SRabin Vincent 		.num_resources = ARRAY_SIZE(ab8500_rtc_resources),
102662579266SRabin Vincent 		.resources = ab8500_rtc_resources,
102762579266SRabin Vincent 	},
1028f0f05b1cSArun Murthy 	{
10296af75ecdSLinus Walleij 		.name = "ab8500-acc-det",
1030bad76991SLee Jones 		.of_compatible = "stericsson,ab8500-acc-det",
10316af75ecdSLinus Walleij 		.num_resources = ARRAY_SIZE(ab8500_av_acc_detect_resources),
10326af75ecdSLinus Walleij 		.resources = ab8500_av_acc_detect_resources,
10336af75ecdSLinus Walleij 	},
10346af75ecdSLinus Walleij 	{
1035e098adedSMattias Wallin 		.name = "ab8500-poweron-key",
1036bad76991SLee Jones 		.of_compatible = "stericsson,ab8500-poweron-key",
1037e098adedSMattias Wallin 		.num_resources = ARRAY_SIZE(ab8500_poweronkey_db_resources),
1038e098adedSMattias Wallin 		.resources = ab8500_poweronkey_db_resources,
1039e098adedSMattias Wallin 	},
1040e098adedSMattias Wallin 	{
1041f0f05b1cSArun Murthy 		.name = "ab8500-pwm",
1042bad76991SLee Jones 		.of_compatible = "stericsson,ab8500-pwm",
1043f0f05b1cSArun Murthy 		.id = 1,
1044f0f05b1cSArun Murthy 	},
1045f0f05b1cSArun Murthy 	{
1046f0f05b1cSArun Murthy 		.name = "ab8500-pwm",
1047bad76991SLee Jones 		.of_compatible = "stericsson,ab8500-pwm",
1048f0f05b1cSArun Murthy 		.id = 2,
1049f0f05b1cSArun Murthy 	},
1050f0f05b1cSArun Murthy 	{
1051f0f05b1cSArun Murthy 		.name = "ab8500-pwm",
1052bad76991SLee Jones 		.of_compatible = "stericsson,ab8500-pwm",
1053f0f05b1cSArun Murthy 		.id = 3,
1054f0f05b1cSArun Murthy 	},
1055bad76991SLee Jones 	{
1056bad76991SLee Jones 		.name = "ab8500-leds",
1057bad76991SLee Jones 		.of_compatible = "stericsson,ab8500-leds",
1058bad76991SLee Jones 	},
105977686517SSundar R Iyer 	{
1060e098adedSMattias Wallin 		.name = "ab8500-denc",
1061bad76991SLee Jones 		.of_compatible = "stericsson,ab8500-denc",
1062e098adedSMattias Wallin 	},
1063e098adedSMattias Wallin 	{
1064151621a7SHongbo Zhang 		.name = "abx500-temp",
1065151621a7SHongbo Zhang 		.of_compatible = "stericsson,abx500-temp",
1066e098adedSMattias Wallin 		.num_resources = ARRAY_SIZE(ab8500_temp_resources),
1067e098adedSMattias Wallin 		.resources = ab8500_temp_resources,
106877686517SSundar R Iyer 	},
106962579266SRabin Vincent };
107062579266SRabin Vincent 
1071a9e9ce4cSBill Pemberton static struct mfd_cell ab8500_bm_devs[] = {
10726ef9418cSRickard Andersson 	{
10736ef9418cSRickard Andersson 		.name = "ab8500-charger",
10744aef72dbSRajanikanth H.V 		.of_compatible = "stericsson,ab8500-charger",
10756ef9418cSRickard Andersson 		.num_resources = ARRAY_SIZE(ab8500_charger_resources),
10766ef9418cSRickard Andersson 		.resources = ab8500_charger_resources,
10774aef72dbSRajanikanth H.V 		.platform_data = &ab8500_bm_data,
10784aef72dbSRajanikanth H.V 		.pdata_size = sizeof(ab8500_bm_data),
10796ef9418cSRickard Andersson 	},
10806ef9418cSRickard Andersson 	{
10816ef9418cSRickard Andersson 		.name = "ab8500-btemp",
1082bd9e8ab2SRajanikanth H.V 		.of_compatible = "stericsson,ab8500-btemp",
10836ef9418cSRickard Andersson 		.num_resources = ARRAY_SIZE(ab8500_btemp_resources),
10846ef9418cSRickard Andersson 		.resources = ab8500_btemp_resources,
1085bd9e8ab2SRajanikanth H.V 		.platform_data = &ab8500_bm_data,
1086bd9e8ab2SRajanikanth H.V 		.pdata_size = sizeof(ab8500_bm_data),
10876ef9418cSRickard Andersson 	},
10886ef9418cSRickard Andersson 	{
10896ef9418cSRickard Andersson 		.name = "ab8500-fg",
1090e0f1abebSRajanikanth H.V 		.of_compatible = "stericsson,ab8500-fg",
10916ef9418cSRickard Andersson 		.num_resources = ARRAY_SIZE(ab8500_fg_resources),
10926ef9418cSRickard Andersson 		.resources = ab8500_fg_resources,
1093e0f1abebSRajanikanth H.V 		.platform_data = &ab8500_bm_data,
1094e0f1abebSRajanikanth H.V 		.pdata_size = sizeof(ab8500_bm_data),
10956ef9418cSRickard Andersson 	},
10966ef9418cSRickard Andersson 	{
10976ef9418cSRickard Andersson 		.name = "ab8500-chargalg",
1098a12810abSRajanikanth H.V 		.of_compatible = "stericsson,ab8500-chargalg",
10996ef9418cSRickard Andersson 		.num_resources = ARRAY_SIZE(ab8500_chargalg_resources),
11006ef9418cSRickard Andersson 		.resources = ab8500_chargalg_resources,
1101a12810abSRajanikanth H.V 		.platform_data = &ab8500_bm_data,
1102a12810abSRajanikanth H.V 		.pdata_size = sizeof(ab8500_bm_data),
11036ef9418cSRickard Andersson 	},
11046ef9418cSRickard Andersson };
11056ef9418cSRickard Andersson 
1106a9e9ce4cSBill Pemberton static struct mfd_cell ab8500_devs[] = {
1107d6255529SLinus Walleij 	{
11087d56a46eSLee Jones 		.name = "pinctrl-ab8500",
1109bad76991SLee Jones 		.of_compatible = "stericsson,ab8500-gpio",
1110d6255529SLinus Walleij 	},
1111d6255529SLinus Walleij 	{
1112d6255529SLinus Walleij 		.name = "ab8500-usb",
1113bad76991SLee Jones 		.of_compatible = "stericsson,ab8500-usb",
1114d6255529SLinus Walleij 		.num_resources = ARRAY_SIZE(ab8500_usb_resources),
1115d6255529SLinus Walleij 		.resources = ab8500_usb_resources,
1116d6255529SLinus Walleij 	},
111744f72e53SVirupax Sadashivpetimath 	{
111844f72e53SVirupax Sadashivpetimath 		.name = "ab8500-codec",
111981a21cddSLee Jones 		.of_compatible = "stericsson,ab8500-codec",
112044f72e53SVirupax Sadashivpetimath 	},
1121d6255529SLinus Walleij };
1122d6255529SLinus Walleij 
1123a9e9ce4cSBill Pemberton static struct mfd_cell ab9540_devs[] = {
1124d6255529SLinus Walleij 	{
1125e64d905eSLee Jones 		.name = "pinctrl-ab9540",
1126e64d905eSLee Jones 		.of_compatible = "stericsson,ab9540-gpio",
1127d6255529SLinus Walleij 	},
1128d6255529SLinus Walleij 	{
1129d6255529SLinus Walleij 		.name = "ab9540-usb",
1130d6255529SLinus Walleij 		.num_resources = ARRAY_SIZE(ab8500_usb_resources),
1131d6255529SLinus Walleij 		.resources = ab8500_usb_resources,
1132d6255529SLinus Walleij 	},
113344f72e53SVirupax Sadashivpetimath 	{
113444f72e53SVirupax Sadashivpetimath 		.name = "ab9540-codec",
113544f72e53SVirupax Sadashivpetimath 	},
113644f72e53SVirupax Sadashivpetimath };
113744f72e53SVirupax Sadashivpetimath 
113844f72e53SVirupax Sadashivpetimath /* Device list common to ab9540 and ab8505 */
1139a9e9ce4cSBill Pemberton static struct mfd_cell ab9540_ab8505_devs[] = {
114044f72e53SVirupax Sadashivpetimath 	{
114144f72e53SVirupax Sadashivpetimath 		.name = "ab-iddet",
114244f72e53SVirupax Sadashivpetimath 		.num_resources = ARRAY_SIZE(ab8505_iddet_resources),
114344f72e53SVirupax Sadashivpetimath 		.resources = ab8505_iddet_resources,
114444f72e53SVirupax Sadashivpetimath 	},
1145d6255529SLinus Walleij };
1146d6255529SLinus Walleij 
1147cca69b67SMattias Wallin static ssize_t show_chip_id(struct device *dev,
1148cca69b67SMattias Wallin 				struct device_attribute *attr, char *buf)
1149cca69b67SMattias Wallin {
1150cca69b67SMattias Wallin 	struct ab8500 *ab8500;
1151cca69b67SMattias Wallin 
1152cca69b67SMattias Wallin 	ab8500 = dev_get_drvdata(dev);
1153cca69b67SMattias Wallin 	return sprintf(buf, "%#x\n", ab8500 ? ab8500->chip_id : -EINVAL);
1154cca69b67SMattias Wallin }
1155cca69b67SMattias Wallin 
1156e5c238c3SMattias Wallin /*
1157e5c238c3SMattias Wallin  * ab8500 has switched off due to (SWITCH_OFF_STATUS):
1158e5c238c3SMattias Wallin  * 0x01 Swoff bit programming
1159e5c238c3SMattias Wallin  * 0x02 Thermal protection activation
1160e5c238c3SMattias Wallin  * 0x04 Vbat lower then BattOk falling threshold
1161e5c238c3SMattias Wallin  * 0x08 Watchdog expired
1162e5c238c3SMattias Wallin  * 0x10 Non presence of 32kHz clock
1163e5c238c3SMattias Wallin  * 0x20 Battery level lower than power on reset threshold
1164e5c238c3SMattias Wallin  * 0x40 Power on key 1 pressed longer than 10 seconds
1165e5c238c3SMattias Wallin  * 0x80 DB8500 thermal shutdown
1166e5c238c3SMattias Wallin  */
1167e5c238c3SMattias Wallin static ssize_t show_switch_off_status(struct device *dev,
1168e5c238c3SMattias Wallin 				struct device_attribute *attr, char *buf)
1169e5c238c3SMattias Wallin {
1170e5c238c3SMattias Wallin 	int ret;
1171e5c238c3SMattias Wallin 	u8 value;
1172e5c238c3SMattias Wallin 	struct ab8500 *ab8500;
1173e5c238c3SMattias Wallin 
1174e5c238c3SMattias Wallin 	ab8500 = dev_get_drvdata(dev);
1175e5c238c3SMattias Wallin 	ret = get_register_interruptible(ab8500, AB8500_RTC,
1176e5c238c3SMattias Wallin 		AB8500_SWITCH_OFF_STATUS, &value);
1177e5c238c3SMattias Wallin 	if (ret < 0)
1178e5c238c3SMattias Wallin 		return ret;
1179e5c238c3SMattias Wallin 	return sprintf(buf, "%#x\n", value);
1180e5c238c3SMattias Wallin }
1181e5c238c3SMattias Wallin 
1182f04a9d8aSRajkumar Kasirajan /* use mask and set to override the register turn_on_stat value */
1183f04a9d8aSRajkumar Kasirajan void ab8500_override_turn_on_stat(u8 mask, u8 set)
1184f04a9d8aSRajkumar Kasirajan {
1185f04a9d8aSRajkumar Kasirajan 	spin_lock(&on_stat_lock);
1186f04a9d8aSRajkumar Kasirajan 	turn_on_stat_mask = mask;
1187f04a9d8aSRajkumar Kasirajan 	turn_on_stat_set = set;
1188f04a9d8aSRajkumar Kasirajan 	spin_unlock(&on_stat_lock);
1189f04a9d8aSRajkumar Kasirajan }
1190f04a9d8aSRajkumar Kasirajan 
1191b4a31037SAndrew Lynn /*
1192b4a31037SAndrew Lynn  * ab8500 has turned on due to (TURN_ON_STATUS):
1193b4a31037SAndrew Lynn  * 0x01 PORnVbat
1194b4a31037SAndrew Lynn  * 0x02 PonKey1dbF
1195b4a31037SAndrew Lynn  * 0x04 PonKey2dbF
1196b4a31037SAndrew Lynn  * 0x08 RTCAlarm
1197b4a31037SAndrew Lynn  * 0x10 MainChDet
1198b4a31037SAndrew Lynn  * 0x20 VbusDet
1199b4a31037SAndrew Lynn  * 0x40 UsbIDDetect
1200b4a31037SAndrew Lynn  * 0x80 Reserved
1201b4a31037SAndrew Lynn  */
1202b4a31037SAndrew Lynn static ssize_t show_turn_on_status(struct device *dev,
1203b4a31037SAndrew Lynn 				struct device_attribute *attr, char *buf)
1204b4a31037SAndrew Lynn {
1205b4a31037SAndrew Lynn 	int ret;
1206b4a31037SAndrew Lynn 	u8 value;
1207b4a31037SAndrew Lynn 	struct ab8500 *ab8500;
1208b4a31037SAndrew Lynn 
1209b4a31037SAndrew Lynn 	ab8500 = dev_get_drvdata(dev);
1210b4a31037SAndrew Lynn 	ret = get_register_interruptible(ab8500, AB8500_SYS_CTRL1_BLOCK,
1211b4a31037SAndrew Lynn 		AB8500_TURN_ON_STATUS, &value);
1212b4a31037SAndrew Lynn 	if (ret < 0)
1213b4a31037SAndrew Lynn 		return ret;
1214f04a9d8aSRajkumar Kasirajan 
1215f04a9d8aSRajkumar Kasirajan 	/*
1216f04a9d8aSRajkumar Kasirajan 	 * In L9540, turn_on_status register is not updated correctly if
1217f04a9d8aSRajkumar Kasirajan 	 * the device is rebooted with AC/USB charger connected. Due to
1218f04a9d8aSRajkumar Kasirajan 	 * this, the device boots android instead of entering into charge
1219f04a9d8aSRajkumar Kasirajan 	 * only mode. Read the AC/USB status register to detect the charger
1220f04a9d8aSRajkumar Kasirajan 	 * presence and update the turn on status manually.
1221f04a9d8aSRajkumar Kasirajan 	 */
1222f04a9d8aSRajkumar Kasirajan 	if (is_ab9540(ab8500)) {
1223f04a9d8aSRajkumar Kasirajan 		spin_lock(&on_stat_lock);
1224f04a9d8aSRajkumar Kasirajan 		value = (value & turn_on_stat_mask) | turn_on_stat_set;
1225f04a9d8aSRajkumar Kasirajan 		spin_unlock(&on_stat_lock);
1226f04a9d8aSRajkumar Kasirajan 	}
1227f04a9d8aSRajkumar Kasirajan 
1228b4a31037SAndrew Lynn 	return sprintf(buf, "%#x\n", value);
1229b4a31037SAndrew Lynn }
1230b4a31037SAndrew Lynn 
1231d6255529SLinus Walleij static ssize_t show_ab9540_dbbrstn(struct device *dev,
1232d6255529SLinus Walleij 				struct device_attribute *attr, char *buf)
1233d6255529SLinus Walleij {
1234d6255529SLinus Walleij 	struct ab8500 *ab8500;
1235d6255529SLinus Walleij 	int ret;
1236d6255529SLinus Walleij 	u8 value;
1237d6255529SLinus Walleij 
1238d6255529SLinus Walleij 	ab8500 = dev_get_drvdata(dev);
1239d6255529SLinus Walleij 
1240d6255529SLinus Walleij 	ret = get_register_interruptible(ab8500, AB8500_REGU_CTRL2,
1241d6255529SLinus Walleij 		AB9540_MODEM_CTRL2_REG, &value);
1242d6255529SLinus Walleij 	if (ret < 0)
1243d6255529SLinus Walleij 		return ret;
1244d6255529SLinus Walleij 
1245d6255529SLinus Walleij 	return sprintf(buf, "%d\n",
1246d6255529SLinus Walleij 			(value & AB9540_MODEM_CTRL2_SWDBBRSTN_BIT) ? 1 : 0);
1247d6255529SLinus Walleij }
1248d6255529SLinus Walleij 
1249d6255529SLinus Walleij static ssize_t store_ab9540_dbbrstn(struct device *dev,
1250d6255529SLinus Walleij 	struct device_attribute *attr, const char *buf, size_t count)
1251d6255529SLinus Walleij {
1252d6255529SLinus Walleij 	struct ab8500 *ab8500;
1253d6255529SLinus Walleij 	int ret = count;
1254d6255529SLinus Walleij 	int err;
1255d6255529SLinus Walleij 	u8 bitvalues;
1256d6255529SLinus Walleij 
1257d6255529SLinus Walleij 	ab8500 = dev_get_drvdata(dev);
1258d6255529SLinus Walleij 
1259d6255529SLinus Walleij 	if (count > 0) {
1260d6255529SLinus Walleij 		switch (buf[0]) {
1261d6255529SLinus Walleij 		case '0':
1262d6255529SLinus Walleij 			bitvalues = 0;
1263d6255529SLinus Walleij 			break;
1264d6255529SLinus Walleij 		case '1':
1265d6255529SLinus Walleij 			bitvalues = AB9540_MODEM_CTRL2_SWDBBRSTN_BIT;
1266d6255529SLinus Walleij 			break;
1267d6255529SLinus Walleij 		default:
1268d6255529SLinus Walleij 			goto exit;
1269d6255529SLinus Walleij 		}
1270d6255529SLinus Walleij 
1271d6255529SLinus Walleij 		err = mask_and_set_register_interruptible(ab8500,
1272d6255529SLinus Walleij 			AB8500_REGU_CTRL2, AB9540_MODEM_CTRL2_REG,
1273d6255529SLinus Walleij 			AB9540_MODEM_CTRL2_SWDBBRSTN_BIT, bitvalues);
1274d6255529SLinus Walleij 		if (err)
1275d6255529SLinus Walleij 			dev_info(ab8500->dev,
1276d6255529SLinus Walleij 				"Failed to set DBBRSTN %c, err %#x\n",
1277d6255529SLinus Walleij 				buf[0], err);
1278d6255529SLinus Walleij 	}
1279d6255529SLinus Walleij 
1280d6255529SLinus Walleij exit:
1281d6255529SLinus Walleij 	return ret;
1282d6255529SLinus Walleij }
1283d6255529SLinus Walleij 
1284cca69b67SMattias Wallin static DEVICE_ATTR(chip_id, S_IRUGO, show_chip_id, NULL);
1285e5c238c3SMattias Wallin static DEVICE_ATTR(switch_off_status, S_IRUGO, show_switch_off_status, NULL);
1286b4a31037SAndrew Lynn static DEVICE_ATTR(turn_on_status, S_IRUGO, show_turn_on_status, NULL);
1287d6255529SLinus Walleij static DEVICE_ATTR(dbbrstn, S_IRUGO | S_IWUSR,
1288d6255529SLinus Walleij 			show_ab9540_dbbrstn, store_ab9540_dbbrstn);
1289cca69b67SMattias Wallin 
1290cca69b67SMattias Wallin static struct attribute *ab8500_sysfs_entries[] = {
1291cca69b67SMattias Wallin 	&dev_attr_chip_id.attr,
1292e5c238c3SMattias Wallin 	&dev_attr_switch_off_status.attr,
1293b4a31037SAndrew Lynn 	&dev_attr_turn_on_status.attr,
1294cca69b67SMattias Wallin 	NULL,
1295cca69b67SMattias Wallin };
1296cca69b67SMattias Wallin 
1297d6255529SLinus Walleij static struct attribute *ab9540_sysfs_entries[] = {
1298d6255529SLinus Walleij 	&dev_attr_chip_id.attr,
1299d6255529SLinus Walleij 	&dev_attr_switch_off_status.attr,
1300d6255529SLinus Walleij 	&dev_attr_turn_on_status.attr,
1301d6255529SLinus Walleij 	&dev_attr_dbbrstn.attr,
1302d6255529SLinus Walleij 	NULL,
1303d6255529SLinus Walleij };
1304d6255529SLinus Walleij 
1305cca69b67SMattias Wallin static struct attribute_group ab8500_attr_group = {
1306cca69b67SMattias Wallin 	.attrs	= ab8500_sysfs_entries,
1307cca69b67SMattias Wallin };
1308cca69b67SMattias Wallin 
1309d6255529SLinus Walleij static struct attribute_group ab9540_attr_group = {
1310d6255529SLinus Walleij 	.attrs	= ab9540_sysfs_entries,
1311d6255529SLinus Walleij };
1312d6255529SLinus Walleij 
1313f791be49SBill Pemberton static int ab8500_probe(struct platform_device *pdev)
131462579266SRabin Vincent {
1315b04c530cSJonas Aaberg 	static char *switch_off_status[] = {
1316b04c530cSJonas Aaberg 		"Swoff bit programming",
1317b04c530cSJonas Aaberg 		"Thermal protection activation",
1318b04c530cSJonas Aaberg 		"Vbat lower then BattOk falling threshold",
1319b04c530cSJonas Aaberg 		"Watchdog expired",
1320b04c530cSJonas Aaberg 		"Non presence of 32kHz clock",
1321b04c530cSJonas Aaberg 		"Battery level lower than power on reset threshold",
1322b04c530cSJonas Aaberg 		"Power on key 1 pressed longer than 10 seconds",
1323b04c530cSJonas Aaberg 		"DB8500 thermal shutdown"};
1324d28f1db8SLee Jones 	struct ab8500_platform_data *plat = dev_get_platdata(&pdev->dev);
1325d28f1db8SLee Jones 	const struct platform_device_id *platid = platform_get_device_id(pdev);
13266bc4a568SLee Jones 	enum ab8500_version version = AB8500_VERSION_UNDEFINED;
13276bc4a568SLee Jones 	struct device_node *np = pdev->dev.of_node;
1328d28f1db8SLee Jones 	struct ab8500 *ab8500;
1329d28f1db8SLee Jones 	struct resource *resource;
133062579266SRabin Vincent 	int ret;
133162579266SRabin Vincent 	int i;
133247c16975SMattias Wallin 	u8 value;
133362579266SRabin Vincent 
13348c4203cbSLee Jones 	ab8500 = devm_kzalloc(&pdev->dev, sizeof *ab8500, GFP_KERNEL);
1335d28f1db8SLee Jones 	if (!ab8500)
1336d28f1db8SLee Jones 		return -ENOMEM;
1337d28f1db8SLee Jones 
133862579266SRabin Vincent 	if (plat)
133962579266SRabin Vincent 		ab8500->irq_base = plat->irq_base;
134062579266SRabin Vincent 
1341d28f1db8SLee Jones 	ab8500->dev = &pdev->dev;
1342d28f1db8SLee Jones 
1343d28f1db8SLee Jones 	resource = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
13448c4203cbSLee Jones 	if (!resource)
13458c4203cbSLee Jones 		return -ENODEV;
1346d28f1db8SLee Jones 
1347d28f1db8SLee Jones 	ab8500->irq = resource->start;
1348d28f1db8SLee Jones 
1349822672a7SLee Jones 	ab8500->read = ab8500_prcmu_read;
1350822672a7SLee Jones 	ab8500->write = ab8500_prcmu_write;
1351822672a7SLee Jones 	ab8500->write_masked = ab8500_prcmu_write_masked;
1352d28f1db8SLee Jones 
135362579266SRabin Vincent 	mutex_init(&ab8500->lock);
135462579266SRabin Vincent 	mutex_init(&ab8500->irq_lock);
1355112a80d2SJonas Aaberg 	atomic_set(&ab8500->transfer_ongoing, 0);
135662579266SRabin Vincent 
1357d28f1db8SLee Jones 	platform_set_drvdata(pdev, ab8500);
1358d28f1db8SLee Jones 
13596bc4a568SLee Jones 	if (platid)
13606bc4a568SLee Jones 		version = platid->driver_data;
13616bc4a568SLee Jones 
13620f620837SLinus Walleij 	if (version != AB8500_VERSION_UNDEFINED)
13630f620837SLinus Walleij 		ab8500->version = version;
13640f620837SLinus Walleij 	else {
13650f620837SLinus Walleij 		ret = get_register_interruptible(ab8500, AB8500_MISC,
13660f620837SLinus Walleij 			AB8500_IC_NAME_REG, &value);
13670f620837SLinus Walleij 		if (ret < 0)
13688c4203cbSLee Jones 			return ret;
13690f620837SLinus Walleij 
13700f620837SLinus Walleij 		ab8500->version = value;
13710f620837SLinus Walleij 	}
13720f620837SLinus Walleij 
137347c16975SMattias Wallin 	ret = get_register_interruptible(ab8500, AB8500_MISC,
137447c16975SMattias Wallin 		AB8500_REV_REG, &value);
137562579266SRabin Vincent 	if (ret < 0)
13768c4203cbSLee Jones 		return ret;
137762579266SRabin Vincent 
137847c16975SMattias Wallin 	ab8500->chip_id = value;
137962579266SRabin Vincent 
13800f620837SLinus Walleij 	dev_info(ab8500->dev, "detected chip, %s rev. %1x.%1x\n",
13810f620837SLinus Walleij 			ab8500_version_str[ab8500->version],
13820f620837SLinus Walleij 			ab8500->chip_id >> 4,
13830f620837SLinus Walleij 			ab8500->chip_id & 0x0F);
13840f620837SLinus Walleij 
1385d6255529SLinus Walleij 	/* Configure AB8500 or AB9540 IRQ */
1386a982362cSBengt Jonsson 	if (is_ab9540(ab8500) || is_ab8505(ab8500)) {
1387d6255529SLinus Walleij 		ab8500->mask_size = AB9540_NUM_IRQ_REGS;
1388d6255529SLinus Walleij 		ab8500->irq_reg_offset = ab9540_irq_regoffset;
1389d6255529SLinus Walleij 	} else {
13902ced445eSLinus Walleij 		ab8500->mask_size = AB8500_NUM_IRQ_REGS;
13912ced445eSLinus Walleij 		ab8500->irq_reg_offset = ab8500_irq_regoffset;
1392d6255529SLinus Walleij 	}
13938c4203cbSLee Jones 	ab8500->mask = devm_kzalloc(&pdev->dev, ab8500->mask_size, GFP_KERNEL);
13942ced445eSLinus Walleij 	if (!ab8500->mask)
13952ced445eSLinus Walleij 		return -ENOMEM;
13968c4203cbSLee Jones 	ab8500->oldmask = devm_kzalloc(&pdev->dev, ab8500->mask_size, GFP_KERNEL);
13978c4203cbSLee Jones 	if (!ab8500->oldmask)
13988c4203cbSLee Jones 		return -ENOMEM;
13998c4203cbSLee Jones 
1400e5c238c3SMattias Wallin 	/*
1401e5c238c3SMattias Wallin 	 * ab8500 has switched off due to (SWITCH_OFF_STATUS):
1402e5c238c3SMattias Wallin 	 * 0x01 Swoff bit programming
1403e5c238c3SMattias Wallin 	 * 0x02 Thermal protection activation
1404e5c238c3SMattias Wallin 	 * 0x04 Vbat lower then BattOk falling threshold
1405e5c238c3SMattias Wallin 	 * 0x08 Watchdog expired
1406e5c238c3SMattias Wallin 	 * 0x10 Non presence of 32kHz clock
1407e5c238c3SMattias Wallin 	 * 0x20 Battery level lower than power on reset threshold
1408e5c238c3SMattias Wallin 	 * 0x40 Power on key 1 pressed longer than 10 seconds
1409e5c238c3SMattias Wallin 	 * 0x80 DB8500 thermal shutdown
1410e5c238c3SMattias Wallin 	 */
1411e5c238c3SMattias Wallin 
1412e5c238c3SMattias Wallin 	ret = get_register_interruptible(ab8500, AB8500_RTC,
1413e5c238c3SMattias Wallin 		AB8500_SWITCH_OFF_STATUS, &value);
1414e5c238c3SMattias Wallin 	if (ret < 0)
1415e5c238c3SMattias Wallin 		return ret;
1416b04c530cSJonas Aaberg 	dev_info(ab8500->dev, "switch off cause(s) (%#x): ", value);
1417b04c530cSJonas Aaberg 
1418b04c530cSJonas Aaberg 	if (value) {
1419b04c530cSJonas Aaberg 		for (i = 0; i < ARRAY_SIZE(switch_off_status); i++) {
1420b04c530cSJonas Aaberg 			if (value & 1)
1421b04c530cSJonas Aaberg 				printk(KERN_CONT " \"%s\"",
1422b04c530cSJonas Aaberg 				       switch_off_status[i]);
1423b04c530cSJonas Aaberg 			value = value >> 1;
1424b04c530cSJonas Aaberg 
1425b04c530cSJonas Aaberg 		}
1426b04c530cSJonas Aaberg 		printk(KERN_CONT "\n");
1427b04c530cSJonas Aaberg 	} else {
1428b04c530cSJonas Aaberg 		printk(KERN_CONT " None\n");
1429b04c530cSJonas Aaberg 	}
1430e5c238c3SMattias Wallin 
143162579266SRabin Vincent 	if (plat && plat->init)
143262579266SRabin Vincent 		plat->init(ab8500);
1433f04a9d8aSRajkumar Kasirajan 	if (is_ab9540(ab8500)) {
1434f04a9d8aSRajkumar Kasirajan 		ret = get_register_interruptible(ab8500, AB8500_CHARGER,
1435f04a9d8aSRajkumar Kasirajan 			AB8500_CH_USBCH_STAT1_REG, &value);
1436f04a9d8aSRajkumar Kasirajan 		if (ret < 0)
1437f04a9d8aSRajkumar Kasirajan 			return ret;
1438f04a9d8aSRajkumar Kasirajan 		if ((value & VBUS_DET_DBNC1) && (value & VBUS_DET_DBNC100))
1439f04a9d8aSRajkumar Kasirajan 			ab8500_override_turn_on_stat(~AB8500_POW_KEY_1_ON,
1440f04a9d8aSRajkumar Kasirajan 						     AB8500_VBUS_DET);
1441f04a9d8aSRajkumar Kasirajan 	}
144262579266SRabin Vincent 
144362579266SRabin Vincent 	/* Clear and mask all interrupts */
14442ced445eSLinus Walleij 	for (i = 0; i < ab8500->mask_size; i++) {
14450f620837SLinus Walleij 		/*
14460f620837SLinus Walleij 		 * Interrupt register 12 doesn't exist prior to AB8500 version
14470f620837SLinus Walleij 		 * 2.0
14480f620837SLinus Walleij 		 */
14490f620837SLinus Walleij 		if (ab8500->irq_reg_offset[i] == 11 &&
14500f620837SLinus Walleij 				is_ab8500_1p1_or_earlier(ab8500))
145192d50a41SMattias Wallin 			continue;
145262579266SRabin Vincent 
145347c16975SMattias Wallin 		get_register_interruptible(ab8500, AB8500_INTERRUPT,
14542ced445eSLinus Walleij 			AB8500_IT_LATCH1_REG + ab8500->irq_reg_offset[i],
145592d50a41SMattias Wallin 			&value);
145647c16975SMattias Wallin 		set_register_interruptible(ab8500, AB8500_INTERRUPT,
14572ced445eSLinus Walleij 			AB8500_IT_MASK1_REG + ab8500->irq_reg_offset[i], 0xff);
145862579266SRabin Vincent 	}
145962579266SRabin Vincent 
146047c16975SMattias Wallin 	ret = abx500_register_ops(ab8500->dev, &ab8500_ops);
146147c16975SMattias Wallin 	if (ret)
14628c4203cbSLee Jones 		return ret;
146347c16975SMattias Wallin 
14642ced445eSLinus Walleij 	for (i = 0; i < ab8500->mask_size; i++)
146562579266SRabin Vincent 		ab8500->mask[i] = ab8500->oldmask[i] = 0xff;
146662579266SRabin Vincent 
146706e589efSLee Jones 	ret = ab8500_irq_init(ab8500, np);
146862579266SRabin Vincent 	if (ret)
14698c4203cbSLee Jones 		return ret;
147062579266SRabin Vincent 
14717ccfe9b1SMichel JAOUEN 	/*  Activate this feature only in ab9540 */
14727ccfe9b1SMichel JAOUEN 	/*  till tests are done on ab8500 1p2 or later*/
147306e589efSLee Jones 	if (is_ab9540(ab8500)) {
14748c4203cbSLee Jones 		ret = devm_request_threaded_irq(&pdev->dev, ab8500->irq, NULL,
14757ccfe9b1SMichel JAOUEN 						ab8500_hierarchical_irq,
14767ccfe9b1SMichel JAOUEN 						IRQF_ONESHOT | IRQF_NO_SUSPEND,
14777ccfe9b1SMichel JAOUEN 						"ab8500", ab8500);
147806e589efSLee Jones 	}
147906e589efSLee Jones 	else {
14808c4203cbSLee Jones 		ret = devm_request_threaded_irq(&pdev->dev, ab8500->irq, NULL,
14817ccfe9b1SMichel JAOUEN 						ab8500_irq,
14824f079985SMattias Wallin 						IRQF_ONESHOT | IRQF_NO_SUSPEND,
14834f079985SMattias Wallin 						"ab8500", ab8500);
148462579266SRabin Vincent 		if (ret)
14858c4203cbSLee Jones 			return ret;
148662579266SRabin Vincent 	}
148762579266SRabin Vincent 
1488d6255529SLinus Walleij 	ret = mfd_add_devices(ab8500->dev, 0, abx500_common_devs,
1489d6255529SLinus Walleij 			ARRAY_SIZE(abx500_common_devs), NULL,
149055692af5SMark Brown 			ab8500->irq_base, ab8500->domain);
1491d6255529SLinus Walleij 	if (ret)
14928c4203cbSLee Jones 		return ret;
1493d6255529SLinus Walleij 
1494d6255529SLinus Walleij 	if (is_ab9540(ab8500))
1495d6255529SLinus Walleij 		ret = mfd_add_devices(ab8500->dev, 0, ab9540_devs,
1496d6255529SLinus Walleij 				ARRAY_SIZE(ab9540_devs), NULL,
149755692af5SMark Brown 				ab8500->irq_base, ab8500->domain);
1498d6255529SLinus Walleij 	else
1499549931f9SSundar R Iyer 		ret = mfd_add_devices(ab8500->dev, 0, ab8500_devs,
150044f72e53SVirupax Sadashivpetimath 				ARRAY_SIZE(ab8500_devs), NULL,
150155692af5SMark Brown 				ab8500->irq_base, ab8500->domain);
15026bc4a568SLee Jones 	if (ret)
15038c4203cbSLee Jones 		return ret;
150444f72e53SVirupax Sadashivpetimath 
150544f72e53SVirupax Sadashivpetimath 	if (is_ab9540(ab8500) || is_ab8505(ab8500))
150644f72e53SVirupax Sadashivpetimath 		ret = mfd_add_devices(ab8500->dev, 0, ab9540_ab8505_devs,
150744f72e53SVirupax Sadashivpetimath 				ARRAY_SIZE(ab9540_ab8505_devs), NULL,
150855692af5SMark Brown 				ab8500->irq_base, ab8500->domain);
150962579266SRabin Vincent 	if (ret)
15108c4203cbSLee Jones 		return ret;
151162579266SRabin Vincent 
15126ef9418cSRickard Andersson 	if (!no_bm) {
15136ef9418cSRickard Andersson 		/* Add battery management devices */
15146ef9418cSRickard Andersson 		ret = mfd_add_devices(ab8500->dev, 0, ab8500_bm_devs,
15156ef9418cSRickard Andersson 				      ARRAY_SIZE(ab8500_bm_devs), NULL,
151655692af5SMark Brown 				      ab8500->irq_base, ab8500->domain);
15176ef9418cSRickard Andersson 		if (ret)
15186ef9418cSRickard Andersson 			dev_err(ab8500->dev, "error adding bm devices\n");
15196ef9418cSRickard Andersson 	}
15206ef9418cSRickard Andersson 
1521d6255529SLinus Walleij 	if (is_ab9540(ab8500))
1522d6255529SLinus Walleij 		ret = sysfs_create_group(&ab8500->dev->kobj,
1523d6255529SLinus Walleij 					&ab9540_attr_group);
1524d6255529SLinus Walleij 	else
1525d6255529SLinus Walleij 		ret = sysfs_create_group(&ab8500->dev->kobj,
1526d6255529SLinus Walleij 					&ab8500_attr_group);
1527cca69b67SMattias Wallin 	if (ret)
1528cca69b67SMattias Wallin 		dev_err(ab8500->dev, "error creating sysfs entries\n");
152906e589efSLee Jones 
153062579266SRabin Vincent 	return ret;
153162579266SRabin Vincent }
153262579266SRabin Vincent 
15334740f73fSBill Pemberton static int ab8500_remove(struct platform_device *pdev)
153462579266SRabin Vincent {
1535d28f1db8SLee Jones 	struct ab8500 *ab8500 = platform_get_drvdata(pdev);
1536d28f1db8SLee Jones 
1537d6255529SLinus Walleij 	if (is_ab9540(ab8500))
1538d6255529SLinus Walleij 		sysfs_remove_group(&ab8500->dev->kobj, &ab9540_attr_group);
1539d6255529SLinus Walleij 	else
1540cca69b67SMattias Wallin 		sysfs_remove_group(&ab8500->dev->kobj, &ab8500_attr_group);
154106e589efSLee Jones 
154262579266SRabin Vincent 	mfd_remove_devices(ab8500->dev);
154362579266SRabin Vincent 
154462579266SRabin Vincent 	return 0;
154562579266SRabin Vincent }
154662579266SRabin Vincent 
1547d28f1db8SLee Jones static const struct platform_device_id ab8500_id[] = {
1548d28f1db8SLee Jones 	{ "ab8500-core", AB8500_VERSION_AB8500 },
1549d28f1db8SLee Jones 	{ "ab8505-i2c", AB8500_VERSION_AB8505 },
1550d28f1db8SLee Jones 	{ "ab9540-i2c", AB8500_VERSION_AB9540 },
1551d28f1db8SLee Jones 	{ "ab8540-i2c", AB8500_VERSION_AB8540 },
1552d28f1db8SLee Jones 	{ }
1553d28f1db8SLee Jones };
1554d28f1db8SLee Jones 
1555d28f1db8SLee Jones static struct platform_driver ab8500_core_driver = {
1556d28f1db8SLee Jones 	.driver = {
1557d28f1db8SLee Jones 		.name = "ab8500-core",
1558d28f1db8SLee Jones 		.owner = THIS_MODULE,
1559d28f1db8SLee Jones 	},
1560d28f1db8SLee Jones 	.probe	= ab8500_probe,
156184449216SBill Pemberton 	.remove	= ab8500_remove,
1562d28f1db8SLee Jones 	.id_table = ab8500_id,
1563d28f1db8SLee Jones };
1564d28f1db8SLee Jones 
1565d28f1db8SLee Jones static int __init ab8500_core_init(void)
1566d28f1db8SLee Jones {
1567d28f1db8SLee Jones 	return platform_driver_register(&ab8500_core_driver);
1568d28f1db8SLee Jones }
1569d28f1db8SLee Jones 
1570d28f1db8SLee Jones static void __exit ab8500_core_exit(void)
1571d28f1db8SLee Jones {
1572d28f1db8SLee Jones 	platform_driver_unregister(&ab8500_core_driver);
1573d28f1db8SLee Jones }
1574ba7cbc3eSLee Jones core_initcall(ab8500_core_init);
1575d28f1db8SLee Jones module_exit(ab8500_core_exit);
1576d28f1db8SLee Jones 
1577adceed62SMattias Wallin MODULE_AUTHOR("Mattias Wallin, Srinidhi Kasagar, Rabin Vincent");
157862579266SRabin Vincent MODULE_DESCRIPTION("AB8500 MFD core");
157962579266SRabin Vincent MODULE_LICENSE("GPL v2");
1580