xref: /openbmc/linux/drivers/mfd/ab8500-core.c (revision 7ccf40b1a1aa060cc0c95bf00cf66f9e88636404)
162579266SRabin Vincent /*
262579266SRabin Vincent  * Copyright (C) ST-Ericsson SA 2010
362579266SRabin Vincent  *
462579266SRabin Vincent  * License Terms: GNU General Public License v2
562579266SRabin Vincent  * Author: Srinidhi Kasagar <srinidhi.kasagar@stericsson.com>
662579266SRabin Vincent  * Author: Rabin Vincent <rabin.vincent@stericsson.com>
7adceed62SMattias Wallin  * Author: Mattias Wallin <mattias.wallin@stericsson.com>
862579266SRabin Vincent  */
962579266SRabin Vincent 
1062579266SRabin Vincent #include <linux/kernel.h>
1162579266SRabin Vincent #include <linux/slab.h>
1262579266SRabin Vincent #include <linux/init.h>
1362579266SRabin Vincent #include <linux/irq.h>
1406e589efSLee Jones #include <linux/irqdomain.h>
1562579266SRabin Vincent #include <linux/delay.h>
1662579266SRabin Vincent #include <linux/interrupt.h>
1762579266SRabin Vincent #include <linux/module.h>
1862579266SRabin Vincent #include <linux/platform_device.h>
1962579266SRabin Vincent #include <linux/mfd/core.h>
2047c16975SMattias Wallin #include <linux/mfd/abx500.h>
21ee66e653SLinus Walleij #include <linux/mfd/abx500/ab8500.h>
2200441b5eSLee Jones #include <linux/mfd/abx500/ab8500-bm.h>
23d28f1db8SLee Jones #include <linux/mfd/dbx500-prcmu.h>
24549931f9SSundar R Iyer #include <linux/regulator/ab8500.h>
256bc4a568SLee Jones #include <linux/of.h>
266bc4a568SLee Jones #include <linux/of_device.h>
2762579266SRabin Vincent 
2862579266SRabin Vincent /*
2962579266SRabin Vincent  * Interrupt register offsets
3062579266SRabin Vincent  * Bank : 0x0E
3162579266SRabin Vincent  */
3247c16975SMattias Wallin #define AB8500_IT_SOURCE1_REG		0x00
3347c16975SMattias Wallin #define AB8500_IT_SOURCE2_REG		0x01
3447c16975SMattias Wallin #define AB8500_IT_SOURCE3_REG		0x02
3547c16975SMattias Wallin #define AB8500_IT_SOURCE4_REG		0x03
3647c16975SMattias Wallin #define AB8500_IT_SOURCE5_REG		0x04
3747c16975SMattias Wallin #define AB8500_IT_SOURCE6_REG		0x05
3847c16975SMattias Wallin #define AB8500_IT_SOURCE7_REG		0x06
3947c16975SMattias Wallin #define AB8500_IT_SOURCE8_REG		0x07
40d6255529SLinus Walleij #define AB9540_IT_SOURCE13_REG		0x0C
4147c16975SMattias Wallin #define AB8500_IT_SOURCE19_REG		0x12
4247c16975SMattias Wallin #define AB8500_IT_SOURCE20_REG		0x13
4347c16975SMattias Wallin #define AB8500_IT_SOURCE21_REG		0x14
4447c16975SMattias Wallin #define AB8500_IT_SOURCE22_REG		0x15
4547c16975SMattias Wallin #define AB8500_IT_SOURCE23_REG		0x16
4647c16975SMattias Wallin #define AB8500_IT_SOURCE24_REG		0x17
4762579266SRabin Vincent 
4862579266SRabin Vincent /*
4962579266SRabin Vincent  * latch registers
5062579266SRabin Vincent  */
5147c16975SMattias Wallin #define AB8500_IT_LATCH1_REG		0x20
5247c16975SMattias Wallin #define AB8500_IT_LATCH2_REG		0x21
5347c16975SMattias Wallin #define AB8500_IT_LATCH3_REG		0x22
5447c16975SMattias Wallin #define AB8500_IT_LATCH4_REG		0x23
5547c16975SMattias Wallin #define AB8500_IT_LATCH5_REG		0x24
5647c16975SMattias Wallin #define AB8500_IT_LATCH6_REG		0x25
5747c16975SMattias Wallin #define AB8500_IT_LATCH7_REG		0x26
5847c16975SMattias Wallin #define AB8500_IT_LATCH8_REG		0x27
5947c16975SMattias Wallin #define AB8500_IT_LATCH9_REG		0x28
6047c16975SMattias Wallin #define AB8500_IT_LATCH10_REG		0x29
6192d50a41SMattias Wallin #define AB8500_IT_LATCH12_REG		0x2B
62d6255529SLinus Walleij #define AB9540_IT_LATCH13_REG		0x2C
6347c16975SMattias Wallin #define AB8500_IT_LATCH19_REG		0x32
6447c16975SMattias Wallin #define AB8500_IT_LATCH20_REG		0x33
6547c16975SMattias Wallin #define AB8500_IT_LATCH21_REG		0x34
6647c16975SMattias Wallin #define AB8500_IT_LATCH22_REG		0x35
6747c16975SMattias Wallin #define AB8500_IT_LATCH23_REG		0x36
6847c16975SMattias Wallin #define AB8500_IT_LATCH24_REG		0x37
6962579266SRabin Vincent 
7062579266SRabin Vincent /*
7162579266SRabin Vincent  * mask registers
7262579266SRabin Vincent  */
7362579266SRabin Vincent 
7447c16975SMattias Wallin #define AB8500_IT_MASK1_REG		0x40
7547c16975SMattias Wallin #define AB8500_IT_MASK2_REG		0x41
7647c16975SMattias Wallin #define AB8500_IT_MASK3_REG		0x42
7747c16975SMattias Wallin #define AB8500_IT_MASK4_REG		0x43
7847c16975SMattias Wallin #define AB8500_IT_MASK5_REG		0x44
7947c16975SMattias Wallin #define AB8500_IT_MASK6_REG		0x45
8047c16975SMattias Wallin #define AB8500_IT_MASK7_REG		0x46
8147c16975SMattias Wallin #define AB8500_IT_MASK8_REG		0x47
8247c16975SMattias Wallin #define AB8500_IT_MASK9_REG		0x48
8347c16975SMattias Wallin #define AB8500_IT_MASK10_REG		0x49
8447c16975SMattias Wallin #define AB8500_IT_MASK11_REG		0x4A
8547c16975SMattias Wallin #define AB8500_IT_MASK12_REG		0x4B
8647c16975SMattias Wallin #define AB8500_IT_MASK13_REG		0x4C
8747c16975SMattias Wallin #define AB8500_IT_MASK14_REG		0x4D
8847c16975SMattias Wallin #define AB8500_IT_MASK15_REG		0x4E
8947c16975SMattias Wallin #define AB8500_IT_MASK16_REG		0x4F
9047c16975SMattias Wallin #define AB8500_IT_MASK17_REG		0x50
9147c16975SMattias Wallin #define AB8500_IT_MASK18_REG		0x51
9247c16975SMattias Wallin #define AB8500_IT_MASK19_REG		0x52
9347c16975SMattias Wallin #define AB8500_IT_MASK20_REG		0x53
9447c16975SMattias Wallin #define AB8500_IT_MASK21_REG		0x54
9547c16975SMattias Wallin #define AB8500_IT_MASK22_REG		0x55
9647c16975SMattias Wallin #define AB8500_IT_MASK23_REG		0x56
9747c16975SMattias Wallin #define AB8500_IT_MASK24_REG		0x57
98a29264b6SLee Jones #define AB8500_IT_MASK25_REG		0x58
9962579266SRabin Vincent 
1007ccfe9b1SMichel JAOUEN /*
1017ccfe9b1SMichel JAOUEN  * latch hierarchy registers
1027ccfe9b1SMichel JAOUEN  */
1037ccfe9b1SMichel JAOUEN #define AB8500_IT_LATCHHIER1_REG	0x60
1047ccfe9b1SMichel JAOUEN #define AB8500_IT_LATCHHIER2_REG	0x61
1057ccfe9b1SMichel JAOUEN #define AB8500_IT_LATCHHIER3_REG	0x62
1063e1a498fSLee Jones #define AB8540_IT_LATCHHIER4_REG	0x63
1077ccfe9b1SMichel JAOUEN 
1087ccfe9b1SMichel JAOUEN #define AB8500_IT_LATCHHIER_NUM		3
1093e1a498fSLee Jones #define AB8540_IT_LATCHHIER_NUM		4
1107ccfe9b1SMichel JAOUEN 
11147c16975SMattias Wallin #define AB8500_REV_REG			0x80
1120f620837SLinus Walleij #define AB8500_IC_NAME_REG		0x82
113e5c238c3SMattias Wallin #define AB8500_SWITCH_OFF_STATUS	0x00
11462579266SRabin Vincent 
115b4a31037SAndrew Lynn #define AB8500_TURN_ON_STATUS		0x00
11693ff722eSLee Jones #define AB8505_TURN_ON_STATUS_2	0x04
117b4a31037SAndrew Lynn 
118f04a9d8aSRajkumar Kasirajan #define AB8500_CH_USBCH_STAT1_REG	0x02
119f04a9d8aSRajkumar Kasirajan #define VBUS_DET_DBNC100		0x02
120f04a9d8aSRajkumar Kasirajan #define VBUS_DET_DBNC1			0x01
121f04a9d8aSRajkumar Kasirajan 
122f04a9d8aSRajkumar Kasirajan static DEFINE_SPINLOCK(on_stat_lock);
123f04a9d8aSRajkumar Kasirajan static u8 turn_on_stat_mask = 0xFF;
124f04a9d8aSRajkumar Kasirajan static u8 turn_on_stat_set;
1256ef9418cSRickard Andersson static bool no_bm; /* No battery management */
1266ef9418cSRickard Andersson module_param(no_bm, bool, S_IRUGO);
1276ef9418cSRickard Andersson 
128d6255529SLinus Walleij #define AB9540_MODEM_CTRL2_REG			0x23
129d6255529SLinus Walleij #define AB9540_MODEM_CTRL2_SWDBBRSTN_BIT	BIT(2)
130d6255529SLinus Walleij 
13162579266SRabin Vincent /*
13262579266SRabin Vincent  * Map interrupt numbers to the LATCH and MASK register offsets, Interrupt
1332ced445eSLinus Walleij  * numbers are indexed into this array with (num / 8). The interupts are
1342ced445eSLinus Walleij  * defined in linux/mfd/ab8500.h
13562579266SRabin Vincent  *
13662579266SRabin Vincent  * This is one off from the register names, i.e. AB8500_IT_MASK1_REG is at
13762579266SRabin Vincent  * offset 0.
13862579266SRabin Vincent  */
1392ced445eSLinus Walleij /* AB8500 support */
14062579266SRabin Vincent static const int ab8500_irq_regoffset[AB8500_NUM_IRQ_REGS] = {
14192d50a41SMattias Wallin 	0, 1, 2, 3, 4, 6, 7, 8, 9, 11, 18, 19, 20, 21,
14262579266SRabin Vincent };
14362579266SRabin Vincent 
144a29264b6SLee Jones /* AB9540 / AB8505 support */
145d6255529SLinus Walleij static const int ab9540_irq_regoffset[AB9540_NUM_IRQ_REGS] = {
146a29264b6SLee Jones 	0, 1, 2, 3, 4, 6, 7, 8, 9, 11, 18, 19, 20, 21, 12, 13, 24, 5, 22, 23
147d6255529SLinus Walleij };
148d6255529SLinus Walleij 
1493e1a498fSLee Jones /* AB8540 support */
1503e1a498fSLee Jones static const int ab8540_irq_regoffset[AB8540_NUM_IRQ_REGS] = {
151*7ccf40b1SLee Jones 	0, 1, 2, 3, 4, -1, -1, -1, -1, 11, 18, 19, 20, 21, 12, 13, 24, 5, 22,
152*7ccf40b1SLee Jones 	23, 25, 26, 27, 28, 29, 30, 31,
1533e1a498fSLee Jones };
1543e1a498fSLee Jones 
1550f620837SLinus Walleij static const char ab8500_version_str[][7] = {
1560f620837SLinus Walleij 	[AB8500_VERSION_AB8500] = "AB8500",
1570f620837SLinus Walleij 	[AB8500_VERSION_AB8505] = "AB8505",
1580f620837SLinus Walleij 	[AB8500_VERSION_AB9540] = "AB9540",
1590f620837SLinus Walleij 	[AB8500_VERSION_AB8540] = "AB8540",
1600f620837SLinus Walleij };
1610f620837SLinus Walleij 
162822672a7SLee Jones static int ab8500_prcmu_write(struct ab8500 *ab8500, u16 addr, u8 data)
163d28f1db8SLee Jones {
164d28f1db8SLee Jones 	int ret;
165d28f1db8SLee Jones 
166d28f1db8SLee Jones 	ret = prcmu_abb_write((u8)(addr >> 8), (u8)(addr & 0xFF), &data, 1);
167d28f1db8SLee Jones 	if (ret < 0)
168d28f1db8SLee Jones 		dev_err(ab8500->dev, "prcmu i2c error %d\n", ret);
169d28f1db8SLee Jones 	return ret;
170d28f1db8SLee Jones }
171d28f1db8SLee Jones 
172822672a7SLee Jones static int ab8500_prcmu_write_masked(struct ab8500 *ab8500, u16 addr, u8 mask,
173d28f1db8SLee Jones 	u8 data)
174d28f1db8SLee Jones {
175d28f1db8SLee Jones 	int ret;
176d28f1db8SLee Jones 
177d28f1db8SLee Jones 	ret = prcmu_abb_write_masked((u8)(addr >> 8), (u8)(addr & 0xFF), &data,
178d28f1db8SLee Jones 		&mask, 1);
179d28f1db8SLee Jones 	if (ret < 0)
180d28f1db8SLee Jones 		dev_err(ab8500->dev, "prcmu i2c error %d\n", ret);
181d28f1db8SLee Jones 	return ret;
182d28f1db8SLee Jones }
183d28f1db8SLee Jones 
184822672a7SLee Jones static int ab8500_prcmu_read(struct ab8500 *ab8500, u16 addr)
185d28f1db8SLee Jones {
186d28f1db8SLee Jones 	int ret;
187d28f1db8SLee Jones 	u8 data;
188d28f1db8SLee Jones 
189d28f1db8SLee Jones 	ret = prcmu_abb_read((u8)(addr >> 8), (u8)(addr & 0xFF), &data, 1);
190d28f1db8SLee Jones 	if (ret < 0) {
191d28f1db8SLee Jones 		dev_err(ab8500->dev, "prcmu i2c error %d\n", ret);
192d28f1db8SLee Jones 		return ret;
193d28f1db8SLee Jones 	}
194d28f1db8SLee Jones 	return (int)data;
195d28f1db8SLee Jones }
196d28f1db8SLee Jones 
19747c16975SMattias Wallin static int ab8500_get_chip_id(struct device *dev)
19847c16975SMattias Wallin {
1996bce7bf1SMattias Wallin 	struct ab8500 *ab8500;
2006bce7bf1SMattias Wallin 
2016bce7bf1SMattias Wallin 	if (!dev)
2026bce7bf1SMattias Wallin 		return -EINVAL;
2036bce7bf1SMattias Wallin 	ab8500 = dev_get_drvdata(dev->parent);
2046bce7bf1SMattias Wallin 	return ab8500 ? (int)ab8500->chip_id : -EINVAL;
20547c16975SMattias Wallin }
20647c16975SMattias Wallin 
20747c16975SMattias Wallin static int set_register_interruptible(struct ab8500 *ab8500, u8 bank,
20847c16975SMattias Wallin 	u8 reg, u8 data)
20962579266SRabin Vincent {
21062579266SRabin Vincent 	int ret;
21147c16975SMattias Wallin 	/*
21247c16975SMattias Wallin 	 * Put the u8 bank and u8 register together into a an u16.
21347c16975SMattias Wallin 	 * The bank on higher 8 bits and register in lower 8 bits.
21447c16975SMattias Wallin 	 * */
21547c16975SMattias Wallin 	u16 addr = ((u16)bank) << 8 | reg;
21662579266SRabin Vincent 
21762579266SRabin Vincent 	dev_vdbg(ab8500->dev, "wr: addr %#x <= %#x\n", addr, data);
21862579266SRabin Vincent 
219392cbd1eSRabin Vincent 	mutex_lock(&ab8500->lock);
22047c16975SMattias Wallin 
22147c16975SMattias Wallin 	ret = ab8500->write(ab8500, addr, data);
22247c16975SMattias Wallin 	if (ret < 0)
22347c16975SMattias Wallin 		dev_err(ab8500->dev, "failed to write reg %#x: %d\n",
22447c16975SMattias Wallin 			addr, ret);
22547c16975SMattias Wallin 	mutex_unlock(&ab8500->lock);
22647c16975SMattias Wallin 
22747c16975SMattias Wallin 	return ret;
22847c16975SMattias Wallin }
22947c16975SMattias Wallin 
23047c16975SMattias Wallin static int ab8500_set_register(struct device *dev, u8 bank,
23147c16975SMattias Wallin 	u8 reg, u8 value)
23247c16975SMattias Wallin {
233112a80d2SJonas Aaberg 	int ret;
23447c16975SMattias Wallin 	struct ab8500 *ab8500 = dev_get_drvdata(dev->parent);
23547c16975SMattias Wallin 
236112a80d2SJonas Aaberg 	atomic_inc(&ab8500->transfer_ongoing);
237112a80d2SJonas Aaberg 	ret = set_register_interruptible(ab8500, bank, reg, value);
238112a80d2SJonas Aaberg 	atomic_dec(&ab8500->transfer_ongoing);
239112a80d2SJonas Aaberg 	return ret;
24047c16975SMattias Wallin }
24147c16975SMattias Wallin 
24247c16975SMattias Wallin static int get_register_interruptible(struct ab8500 *ab8500, u8 bank,
24347c16975SMattias Wallin 	u8 reg, u8 *value)
24447c16975SMattias Wallin {
24547c16975SMattias Wallin 	int ret;
24647c16975SMattias Wallin 	/* put the u8 bank and u8 reg together into a an u16.
24747c16975SMattias Wallin 	 * bank on higher 8 bits and reg in lower */
24847c16975SMattias Wallin 	u16 addr = ((u16)bank) << 8 | reg;
24947c16975SMattias Wallin 
250392cbd1eSRabin Vincent 	mutex_lock(&ab8500->lock);
25147c16975SMattias Wallin 
25247c16975SMattias Wallin 	ret = ab8500->read(ab8500, addr);
25347c16975SMattias Wallin 	if (ret < 0)
25447c16975SMattias Wallin 		dev_err(ab8500->dev, "failed to read reg %#x: %d\n",
25547c16975SMattias Wallin 			addr, ret);
25647c16975SMattias Wallin 	else
25747c16975SMattias Wallin 		*value = ret;
25847c16975SMattias Wallin 
25947c16975SMattias Wallin 	mutex_unlock(&ab8500->lock);
26047c16975SMattias Wallin 	dev_vdbg(ab8500->dev, "rd: addr %#x => data %#x\n", addr, ret);
26147c16975SMattias Wallin 
26247c16975SMattias Wallin 	return ret;
26347c16975SMattias Wallin }
26447c16975SMattias Wallin 
26547c16975SMattias Wallin static int ab8500_get_register(struct device *dev, u8 bank,
26647c16975SMattias Wallin 	u8 reg, u8 *value)
26747c16975SMattias Wallin {
268112a80d2SJonas Aaberg 	int ret;
26947c16975SMattias Wallin 	struct ab8500 *ab8500 = dev_get_drvdata(dev->parent);
27047c16975SMattias Wallin 
271112a80d2SJonas Aaberg 	atomic_inc(&ab8500->transfer_ongoing);
272112a80d2SJonas Aaberg 	ret = get_register_interruptible(ab8500, bank, reg, value);
273112a80d2SJonas Aaberg 	atomic_dec(&ab8500->transfer_ongoing);
274112a80d2SJonas Aaberg 	return ret;
27547c16975SMattias Wallin }
27647c16975SMattias Wallin 
27747c16975SMattias Wallin static int mask_and_set_register_interruptible(struct ab8500 *ab8500, u8 bank,
27847c16975SMattias Wallin 	u8 reg, u8 bitmask, u8 bitvalues)
27947c16975SMattias Wallin {
28047c16975SMattias Wallin 	int ret;
28147c16975SMattias Wallin 	/* put the u8 bank and u8 reg together into a an u16.
28247c16975SMattias Wallin 	 * bank on higher 8 bits and reg in lower */
28347c16975SMattias Wallin 	u16 addr = ((u16)bank) << 8 | reg;
28447c16975SMattias Wallin 
285392cbd1eSRabin Vincent 	mutex_lock(&ab8500->lock);
28647c16975SMattias Wallin 
287bc628fd1SMattias Nilsson 	if (ab8500->write_masked == NULL) {
288bc628fd1SMattias Nilsson 		u8 data;
289bc628fd1SMattias Nilsson 
29047c16975SMattias Wallin 		ret = ab8500->read(ab8500, addr);
29147c16975SMattias Wallin 		if (ret < 0) {
29247c16975SMattias Wallin 			dev_err(ab8500->dev, "failed to read reg %#x: %d\n",
29347c16975SMattias Wallin 				addr, ret);
29447c16975SMattias Wallin 			goto out;
29547c16975SMattias Wallin 		}
29647c16975SMattias Wallin 
29747c16975SMattias Wallin 		data = (u8)ret;
29847c16975SMattias Wallin 		data = (~bitmask & data) | (bitmask & bitvalues);
29947c16975SMattias Wallin 
30062579266SRabin Vincent 		ret = ab8500->write(ab8500, addr, data);
30162579266SRabin Vincent 		if (ret < 0)
30262579266SRabin Vincent 			dev_err(ab8500->dev, "failed to write reg %#x: %d\n",
30362579266SRabin Vincent 				addr, ret);
30462579266SRabin Vincent 
305bc628fd1SMattias Nilsson 		dev_vdbg(ab8500->dev, "mask: addr %#x => data %#x\n", addr,
306bc628fd1SMattias Nilsson 			data);
307bc628fd1SMattias Nilsson 		goto out;
308bc628fd1SMattias Nilsson 	}
309bc628fd1SMattias Nilsson 	ret = ab8500->write_masked(ab8500, addr, bitmask, bitvalues);
310bc628fd1SMattias Nilsson 	if (ret < 0)
311bc628fd1SMattias Nilsson 		dev_err(ab8500->dev, "failed to modify reg %#x: %d\n", addr,
312bc628fd1SMattias Nilsson 			ret);
31362579266SRabin Vincent out:
31462579266SRabin Vincent 	mutex_unlock(&ab8500->lock);
31562579266SRabin Vincent 	return ret;
31662579266SRabin Vincent }
31747c16975SMattias Wallin 
31847c16975SMattias Wallin static int ab8500_mask_and_set_register(struct device *dev,
31947c16975SMattias Wallin 	u8 bank, u8 reg, u8 bitmask, u8 bitvalues)
32047c16975SMattias Wallin {
321112a80d2SJonas Aaberg 	int ret;
32247c16975SMattias Wallin 	struct ab8500 *ab8500 = dev_get_drvdata(dev->parent);
32347c16975SMattias Wallin 
324112a80d2SJonas Aaberg 	atomic_inc(&ab8500->transfer_ongoing);
325112a80d2SJonas Aaberg 	ret = mask_and_set_register_interruptible(ab8500, bank, reg,
32647c16975SMattias Wallin 						 bitmask, bitvalues);
327112a80d2SJonas Aaberg 	atomic_dec(&ab8500->transfer_ongoing);
328112a80d2SJonas Aaberg 	return ret;
32947c16975SMattias Wallin }
33047c16975SMattias Wallin 
33147c16975SMattias Wallin static struct abx500_ops ab8500_ops = {
33247c16975SMattias Wallin 	.get_chip_id = ab8500_get_chip_id,
33347c16975SMattias Wallin 	.get_register = ab8500_get_register,
33447c16975SMattias Wallin 	.set_register = ab8500_set_register,
33547c16975SMattias Wallin 	.get_register_page = NULL,
33647c16975SMattias Wallin 	.set_register_page = NULL,
33747c16975SMattias Wallin 	.mask_and_set_register = ab8500_mask_and_set_register,
33847c16975SMattias Wallin 	.event_registers_startup_state_get = NULL,
33947c16975SMattias Wallin 	.startup_irq_enabled = NULL,
3401d843a6cSMian Yousaf Kaukab 	.dump_all_banks = ab8500_dump_all_banks,
34147c16975SMattias Wallin };
34262579266SRabin Vincent 
3439505a0a0SMark Brown static void ab8500_irq_lock(struct irq_data *data)
34462579266SRabin Vincent {
3459505a0a0SMark Brown 	struct ab8500 *ab8500 = irq_data_get_irq_chip_data(data);
34662579266SRabin Vincent 
34762579266SRabin Vincent 	mutex_lock(&ab8500->irq_lock);
348112a80d2SJonas Aaberg 	atomic_inc(&ab8500->transfer_ongoing);
34962579266SRabin Vincent }
35062579266SRabin Vincent 
3519505a0a0SMark Brown static void ab8500_irq_sync_unlock(struct irq_data *data)
35262579266SRabin Vincent {
3539505a0a0SMark Brown 	struct ab8500 *ab8500 = irq_data_get_irq_chip_data(data);
35462579266SRabin Vincent 	int i;
35562579266SRabin Vincent 
3562ced445eSLinus Walleij 	for (i = 0; i < ab8500->mask_size; i++) {
35762579266SRabin Vincent 		u8 old = ab8500->oldmask[i];
35862579266SRabin Vincent 		u8 new = ab8500->mask[i];
35962579266SRabin Vincent 		int reg;
36062579266SRabin Vincent 
36162579266SRabin Vincent 		if (new == old)
36262579266SRabin Vincent 			continue;
36362579266SRabin Vincent 
3640f620837SLinus Walleij 		/*
3650f620837SLinus Walleij 		 * Interrupt register 12 doesn't exist prior to AB8500 version
3660f620837SLinus Walleij 		 * 2.0
3670f620837SLinus Walleij 		 */
3680f620837SLinus Walleij 		if (ab8500->irq_reg_offset[i] == 11 &&
3690f620837SLinus Walleij 			is_ab8500_1p1_or_earlier(ab8500))
37092d50a41SMattias Wallin 			continue;
37192d50a41SMattias Wallin 
3723e1a498fSLee Jones 		if (ab8500->irq_reg_offset[i] < 0)
3733e1a498fSLee Jones 			continue;
3743e1a498fSLee Jones 
37562579266SRabin Vincent 		ab8500->oldmask[i] = new;
37662579266SRabin Vincent 
3772ced445eSLinus Walleij 		reg = AB8500_IT_MASK1_REG + ab8500->irq_reg_offset[i];
37847c16975SMattias Wallin 		set_register_interruptible(ab8500, AB8500_INTERRUPT, reg, new);
37962579266SRabin Vincent 	}
380112a80d2SJonas Aaberg 	atomic_dec(&ab8500->transfer_ongoing);
38162579266SRabin Vincent 	mutex_unlock(&ab8500->irq_lock);
38262579266SRabin Vincent }
38362579266SRabin Vincent 
3849505a0a0SMark Brown static void ab8500_irq_mask(struct irq_data *data)
38562579266SRabin Vincent {
3869505a0a0SMark Brown 	struct ab8500 *ab8500 = irq_data_get_irq_chip_data(data);
38706e589efSLee Jones 	int offset = data->hwirq;
38862579266SRabin Vincent 	int index = offset / 8;
38962579266SRabin Vincent 	int mask = 1 << (offset % 8);
39062579266SRabin Vincent 
39162579266SRabin Vincent 	ab8500->mask[index] |= mask;
3929c677b9bSLee Jones 
3939c677b9bSLee Jones 	/* The AB8500 GPIOs have two interrupts each (rising & falling). */
3949c677b9bSLee Jones 	if (offset >= AB8500_INT_GPIO6R && offset <= AB8500_INT_GPIO41R)
3959c677b9bSLee Jones 		ab8500->mask[index + 2] |= mask;
3969c677b9bSLee Jones 	if (offset >= AB9540_INT_GPIO50R && offset <= AB9540_INT_GPIO54R)
3979c677b9bSLee Jones 		ab8500->mask[index + 1] |= mask;
3989c677b9bSLee Jones 	if (offset == AB8540_INT_GPIO43R || offset == AB8540_INT_GPIO44R)
399e2ddf46aSLinus Walleij 		/* Here the falling IRQ is one bit lower */
400e2ddf46aSLinus Walleij 		ab8500->mask[index] |= (mask << 1);
40162579266SRabin Vincent }
40262579266SRabin Vincent 
4039505a0a0SMark Brown static void ab8500_irq_unmask(struct irq_data *data)
40462579266SRabin Vincent {
4059505a0a0SMark Brown 	struct ab8500 *ab8500 = irq_data_get_irq_chip_data(data);
4069c677b9bSLee Jones 	unsigned int type = irqd_get_trigger_type(data);
40706e589efSLee Jones 	int offset = data->hwirq;
40862579266SRabin Vincent 	int index = offset / 8;
40962579266SRabin Vincent 	int mask = 1 << (offset % 8);
41062579266SRabin Vincent 
4119c677b9bSLee Jones 	if (type & IRQ_TYPE_EDGE_RISING)
41262579266SRabin Vincent 		ab8500->mask[index] &= ~mask;
4139c677b9bSLee Jones 
4149c677b9bSLee Jones 	/* The AB8500 GPIOs have two interrupts each (rising & falling). */
4159c677b9bSLee Jones 	if (type & IRQ_TYPE_EDGE_FALLING) {
4169c677b9bSLee Jones 		if (offset >= AB8500_INT_GPIO6R && offset <= AB8500_INT_GPIO41R)
4179c677b9bSLee Jones 			ab8500->mask[index + 2] &= ~mask;
418*7ccf40b1SLee Jones 		else if (offset >= AB9540_INT_GPIO50R &&
419*7ccf40b1SLee Jones 			 offset <= AB9540_INT_GPIO54R)
4209c677b9bSLee Jones 			ab8500->mask[index + 1] &= ~mask;
421*7ccf40b1SLee Jones 		else if (offset == AB8540_INT_GPIO43R ||
422*7ccf40b1SLee Jones 			 offset == AB8540_INT_GPIO44R)
423e2ddf46aSLinus Walleij 			/* Here the falling IRQ is one bit lower */
424e2ddf46aSLinus Walleij 			ab8500->mask[index] &= ~(mask << 1);
4259c677b9bSLee Jones 		else
4269c677b9bSLee Jones 			ab8500->mask[index] &= ~mask;
427e2ddf46aSLinus Walleij 	} else {
4289c677b9bSLee Jones 		/* Satisfies the case where type is not set. */
42962579266SRabin Vincent 		ab8500->mask[index] &= ~mask;
43062579266SRabin Vincent 	}
431e2ddf46aSLinus Walleij }
43262579266SRabin Vincent 
43340f6e5a2SLee Jones static int ab8500_irq_set_type(struct irq_data *data, unsigned int type)
43440f6e5a2SLee Jones {
43540f6e5a2SLee Jones 	return 0;
43662579266SRabin Vincent }
43762579266SRabin Vincent 
43862579266SRabin Vincent static struct irq_chip ab8500_irq_chip = {
43962579266SRabin Vincent 	.name			= "ab8500",
4409505a0a0SMark Brown 	.irq_bus_lock		= ab8500_irq_lock,
4419505a0a0SMark Brown 	.irq_bus_sync_unlock	= ab8500_irq_sync_unlock,
4429505a0a0SMark Brown 	.irq_mask		= ab8500_irq_mask,
443e6f9306eSVirupax Sadashivpetimath 	.irq_disable		= ab8500_irq_mask,
4449505a0a0SMark Brown 	.irq_unmask		= ab8500_irq_unmask,
44540f6e5a2SLee Jones 	.irq_set_type		= ab8500_irq_set_type,
44662579266SRabin Vincent };
44762579266SRabin Vincent 
4483e1a498fSLee Jones static void update_latch_offset(u8 *offset, int i)
4493e1a498fSLee Jones {
4503e1a498fSLee Jones 	/* Fix inconsistent ITFromLatch25 bit mapping... */
4513e1a498fSLee Jones 	if (unlikely(*offset == 17))
4523e1a498fSLee Jones 			*offset = 24;
4533e1a498fSLee Jones 	/* Fix inconsistent ab8540 bit mapping... */
4543e1a498fSLee Jones 	if (unlikely(*offset == 16))
4553e1a498fSLee Jones 			*offset = 25;
4563e1a498fSLee Jones 	if ((i == 3) && (*offset >= 24))
4573e1a498fSLee Jones 			*offset += 2;
4583e1a498fSLee Jones }
4593e1a498fSLee Jones 
4607ccfe9b1SMichel JAOUEN static int ab8500_handle_hierarchical_line(struct ab8500 *ab8500,
4617ccfe9b1SMichel JAOUEN 					int latch_offset, u8 latch_val)
4627ccfe9b1SMichel JAOUEN {
4637a93fb37SFabio Baltieri 	int int_bit, line, i;
4647ccfe9b1SMichel JAOUEN 
4657ccfe9b1SMichel JAOUEN 	for (i = 0; i < ab8500->mask_size; i++)
4667ccfe9b1SMichel JAOUEN 		if (ab8500->irq_reg_offset[i] == latch_offset)
4677ccfe9b1SMichel JAOUEN 			break;
4687ccfe9b1SMichel JAOUEN 
4697ccfe9b1SMichel JAOUEN 	if (i >= ab8500->mask_size) {
4707ccfe9b1SMichel JAOUEN 		dev_err(ab8500->dev, "Register offset 0x%2x not declared\n",
4717ccfe9b1SMichel JAOUEN 				latch_offset);
4727ccfe9b1SMichel JAOUEN 		return -ENXIO;
4737ccfe9b1SMichel JAOUEN 	}
4747ccfe9b1SMichel JAOUEN 
4757a93fb37SFabio Baltieri 	/* ignore masked out interrupts */
4767a93fb37SFabio Baltieri 	latch_val &= ~ab8500->mask[i];
4777a93fb37SFabio Baltieri 
4787a93fb37SFabio Baltieri 	while (latch_val) {
4797a93fb37SFabio Baltieri 		int_bit = __ffs(latch_val);
4807ccfe9b1SMichel JAOUEN 		line = (i << 3) + int_bit;
4817ccfe9b1SMichel JAOUEN 		latch_val &= ~(1 << int_bit);
4827ccfe9b1SMichel JAOUEN 
483e2ddf46aSLinus Walleij 		/*
484e2ddf46aSLinus Walleij 		 * This handles the falling edge hwirqs from the GPIO
485e2ddf46aSLinus Walleij 		 * lines. Route them back to the line registered for the
486e2ddf46aSLinus Walleij 		 * rising IRQ, as this is merely a flag for the same IRQ
487e2ddf46aSLinus Walleij 		 * in linux terms.
488e2ddf46aSLinus Walleij 		 */
489e2ddf46aSLinus Walleij 		if (line >= AB8500_INT_GPIO6F && line <= AB8500_INT_GPIO41F)
490e2ddf46aSLinus Walleij 			line -= 16;
491e2ddf46aSLinus Walleij 		if (line >= AB9540_INT_GPIO50F && line <= AB9540_INT_GPIO54F)
492e2ddf46aSLinus Walleij 			line -= 8;
493e2ddf46aSLinus Walleij 		if (line == AB8540_INT_GPIO43F || line == AB8540_INT_GPIO44F)
494e2ddf46aSLinus Walleij 			line += 1;
495e2ddf46aSLinus Walleij 
496ed83d301SLinus Walleij 		handle_nested_irq(irq_create_mapping(ab8500->domain, line));
4977a93fb37SFabio Baltieri 	}
4987ccfe9b1SMichel JAOUEN 
4997ccfe9b1SMichel JAOUEN 	return 0;
5007ccfe9b1SMichel JAOUEN }
5017ccfe9b1SMichel JAOUEN 
5027ccfe9b1SMichel JAOUEN static int ab8500_handle_hierarchical_latch(struct ab8500 *ab8500,
5037ccfe9b1SMichel JAOUEN 					int hier_offset, u8 hier_val)
5047ccfe9b1SMichel JAOUEN {
5057ccfe9b1SMichel JAOUEN 	int latch_bit, status;
5067ccfe9b1SMichel JAOUEN 	u8 latch_offset, latch_val;
5077ccfe9b1SMichel JAOUEN 
5087ccfe9b1SMichel JAOUEN 	do {
5097ccfe9b1SMichel JAOUEN 		latch_bit = __ffs(hier_val);
5107ccfe9b1SMichel JAOUEN 		latch_offset = (hier_offset << 3) + latch_bit;
5117ccfe9b1SMichel JAOUEN 
5123e1a498fSLee Jones 		update_latch_offset(&latch_offset, hier_offset);
5137ccfe9b1SMichel JAOUEN 
5147ccfe9b1SMichel JAOUEN 		status = get_register_interruptible(ab8500,
5157ccfe9b1SMichel JAOUEN 				AB8500_INTERRUPT,
5167ccfe9b1SMichel JAOUEN 				AB8500_IT_LATCH1_REG + latch_offset,
5177ccfe9b1SMichel JAOUEN 				&latch_val);
5187ccfe9b1SMichel JAOUEN 		if (status < 0 || latch_val == 0)
5197ccfe9b1SMichel JAOUEN 			goto discard;
5207ccfe9b1SMichel JAOUEN 
5217ccfe9b1SMichel JAOUEN 		status = ab8500_handle_hierarchical_line(ab8500,
5227ccfe9b1SMichel JAOUEN 				latch_offset, latch_val);
5237ccfe9b1SMichel JAOUEN 		if (status < 0)
5247ccfe9b1SMichel JAOUEN 			return status;
5257ccfe9b1SMichel JAOUEN discard:
5267ccfe9b1SMichel JAOUEN 		hier_val &= ~(1 << latch_bit);
5277ccfe9b1SMichel JAOUEN 	} while (hier_val);
5287ccfe9b1SMichel JAOUEN 
5297ccfe9b1SMichel JAOUEN 	return 0;
5307ccfe9b1SMichel JAOUEN }
5317ccfe9b1SMichel JAOUEN 
5327ccfe9b1SMichel JAOUEN static irqreturn_t ab8500_hierarchical_irq(int irq, void *dev)
5337ccfe9b1SMichel JAOUEN {
5347ccfe9b1SMichel JAOUEN 	struct ab8500 *ab8500 = dev;
5357ccfe9b1SMichel JAOUEN 	u8 i;
5367ccfe9b1SMichel JAOUEN 
5377ccfe9b1SMichel JAOUEN 	dev_vdbg(ab8500->dev, "interrupt\n");
5387ccfe9b1SMichel JAOUEN 
5397ccfe9b1SMichel JAOUEN 	/*  Hierarchical interrupt version */
5403e1a498fSLee Jones 	for (i = 0; i < (ab8500->it_latchhier_num); i++) {
5417ccfe9b1SMichel JAOUEN 		int status;
5427ccfe9b1SMichel JAOUEN 		u8 hier_val;
5437ccfe9b1SMichel JAOUEN 
5447ccfe9b1SMichel JAOUEN 		status = get_register_interruptible(ab8500, AB8500_INTERRUPT,
5457ccfe9b1SMichel JAOUEN 			AB8500_IT_LATCHHIER1_REG + i, &hier_val);
5467ccfe9b1SMichel JAOUEN 		if (status < 0 || hier_val == 0)
5477ccfe9b1SMichel JAOUEN 			continue;
5487ccfe9b1SMichel JAOUEN 
5497ccfe9b1SMichel JAOUEN 		status = ab8500_handle_hierarchical_latch(ab8500, i, hier_val);
5507ccfe9b1SMichel JAOUEN 		if (status < 0)
5517ccfe9b1SMichel JAOUEN 			break;
5527ccfe9b1SMichel JAOUEN 	}
5537ccfe9b1SMichel JAOUEN 	return IRQ_HANDLED;
5547ccfe9b1SMichel JAOUEN }
5557ccfe9b1SMichel JAOUEN 
55606e589efSLee Jones static int ab8500_irq_map(struct irq_domain *d, unsigned int virq,
55706e589efSLee Jones 				irq_hw_number_t hwirq)
55806e589efSLee Jones {
55906e589efSLee Jones 	struct ab8500 *ab8500 = d->host_data;
56006e589efSLee Jones 
56106e589efSLee Jones 	if (!ab8500)
56206e589efSLee Jones 		return -EINVAL;
56306e589efSLee Jones 
56406e589efSLee Jones 	irq_set_chip_data(virq, ab8500);
56506e589efSLee Jones 	irq_set_chip_and_handler(virq, &ab8500_irq_chip,
56606e589efSLee Jones 				handle_simple_irq);
56706e589efSLee Jones 	irq_set_nested_thread(virq, 1);
56806e589efSLee Jones #ifdef CONFIG_ARM
56906e589efSLee Jones 	set_irq_flags(virq, IRQF_VALID);
57006e589efSLee Jones #else
57106e589efSLee Jones 	irq_set_noprobe(virq);
57206e589efSLee Jones #endif
57362579266SRabin Vincent 
57462579266SRabin Vincent 	return 0;
57562579266SRabin Vincent }
57662579266SRabin Vincent 
57706e589efSLee Jones static struct irq_domain_ops ab8500_irq_ops = {
57806e589efSLee Jones 	.map    = ab8500_irq_map,
57906e589efSLee Jones 	.xlate  = irq_domain_xlate_twocell,
58006e589efSLee Jones };
58106e589efSLee Jones 
58206e589efSLee Jones static int ab8500_irq_init(struct ab8500 *ab8500, struct device_node *np)
58362579266SRabin Vincent {
5842ced445eSLinus Walleij 	int num_irqs;
58562579266SRabin Vincent 
5863e1a498fSLee Jones 	if (is_ab8540(ab8500))
5873e1a498fSLee Jones 		num_irqs = AB8540_NR_IRQS;
5883e1a498fSLee Jones 	else if (is_ab9540(ab8500))
589d6255529SLinus Walleij 		num_irqs = AB9540_NR_IRQS;
590a982362cSBengt Jonsson 	else if (is_ab8505(ab8500))
591a982362cSBengt Jonsson 		num_irqs = AB8505_NR_IRQS;
592d6255529SLinus Walleij 	else
5932ced445eSLinus Walleij 		num_irqs = AB8500_NR_IRQS;
5942ced445eSLinus Walleij 
595f1d11f39SLinus Walleij 	/* If ->irq_base is zero this will give a linear mapping */
5967602e05dSGrygorii Strashko 	ab8500->domain = irq_domain_add_simple(ab8500->dev->of_node,
597f864c46aSLinus Walleij 			num_irqs, 0,
598f1d11f39SLinus Walleij 			&ab8500_irq_ops, ab8500);
59906e589efSLee Jones 
60006e589efSLee Jones 	if (!ab8500->domain) {
60106e589efSLee Jones 		dev_err(ab8500->dev, "Failed to create irqdomain\n");
60206e589efSLee Jones 		return -ENOSYS;
60306e589efSLee Jones 	}
60406e589efSLee Jones 
60506e589efSLee Jones 	return 0;
60662579266SRabin Vincent }
60762579266SRabin Vincent 
608112a80d2SJonas Aaberg int ab8500_suspend(struct ab8500 *ab8500)
609112a80d2SJonas Aaberg {
610112a80d2SJonas Aaberg 	if (atomic_read(&ab8500->transfer_ongoing))
611112a80d2SJonas Aaberg 		return -EINVAL;
612f3556302SLee Jones 
613112a80d2SJonas Aaberg 	return 0;
614112a80d2SJonas Aaberg }
615112a80d2SJonas Aaberg 
616a9e9ce4cSBill Pemberton static struct resource ab8500_gpadc_resources[] = {
61762579266SRabin Vincent 	{
61862579266SRabin Vincent 		.name	= "HW_CONV_END",
61962579266SRabin Vincent 		.start	= AB8500_INT_GP_HW_ADC_CONV_END,
62062579266SRabin Vincent 		.end	= AB8500_INT_GP_HW_ADC_CONV_END,
62162579266SRabin Vincent 		.flags	= IORESOURCE_IRQ,
62262579266SRabin Vincent 	},
62362579266SRabin Vincent 	{
62462579266SRabin Vincent 		.name	= "SW_CONV_END",
62562579266SRabin Vincent 		.start	= AB8500_INT_GP_SW_ADC_CONV_END,
62662579266SRabin Vincent 		.end	= AB8500_INT_GP_SW_ADC_CONV_END,
62762579266SRabin Vincent 		.flags	= IORESOURCE_IRQ,
62862579266SRabin Vincent 	},
62962579266SRabin Vincent };
63062579266SRabin Vincent 
6314b106fb9SLee Jones static struct resource ab8505_gpadc_resources[] = {
632c0eda9aeSLee Jones 	{
633c0eda9aeSLee Jones 		.name	= "SW_CONV_END",
634c0eda9aeSLee Jones 		.start	= AB8500_INT_GP_SW_ADC_CONV_END,
635c0eda9aeSLee Jones 		.end	= AB8500_INT_GP_SW_ADC_CONV_END,
636c0eda9aeSLee Jones 		.flags	= IORESOURCE_IRQ,
637c0eda9aeSLee Jones 	},
638c0eda9aeSLee Jones };
639c0eda9aeSLee Jones 
640a9e9ce4cSBill Pemberton static struct resource ab8500_rtc_resources[] = {
64162579266SRabin Vincent 	{
64262579266SRabin Vincent 		.name	= "60S",
64362579266SRabin Vincent 		.start	= AB8500_INT_RTC_60S,
64462579266SRabin Vincent 		.end	= AB8500_INT_RTC_60S,
64562579266SRabin Vincent 		.flags	= IORESOURCE_IRQ,
64662579266SRabin Vincent 	},
64762579266SRabin Vincent 	{
64862579266SRabin Vincent 		.name	= "ALARM",
64962579266SRabin Vincent 		.start	= AB8500_INT_RTC_ALARM,
65062579266SRabin Vincent 		.end	= AB8500_INT_RTC_ALARM,
65162579266SRabin Vincent 		.flags	= IORESOURCE_IRQ,
65262579266SRabin Vincent 	},
65362579266SRabin Vincent };
65462579266SRabin Vincent 
6559c717cf3SAlexandre Torgue static struct resource ab8540_rtc_resources[] = {
6569c717cf3SAlexandre Torgue 	{
6579c717cf3SAlexandre Torgue 		.name	= "1S",
6589c717cf3SAlexandre Torgue 		.start	= AB8540_INT_RTC_1S,
6599c717cf3SAlexandre Torgue 		.end	= AB8540_INT_RTC_1S,
6609c717cf3SAlexandre Torgue 		.flags	= IORESOURCE_IRQ,
6619c717cf3SAlexandre Torgue 	},
6629c717cf3SAlexandre Torgue 	{
6639c717cf3SAlexandre Torgue 		.name	= "ALARM",
6649c717cf3SAlexandre Torgue 		.start	= AB8500_INT_RTC_ALARM,
6659c717cf3SAlexandre Torgue 		.end	= AB8500_INT_RTC_ALARM,
6669c717cf3SAlexandre Torgue 		.flags	= IORESOURCE_IRQ,
6679c717cf3SAlexandre Torgue 	},
6689c717cf3SAlexandre Torgue };
6699c717cf3SAlexandre Torgue 
670a9e9ce4cSBill Pemberton static struct resource ab8500_poweronkey_db_resources[] = {
67177686517SSundar R Iyer 	{
67277686517SSundar R Iyer 		.name	= "ONKEY_DBF",
67377686517SSundar R Iyer 		.start	= AB8500_INT_PON_KEY1DB_F,
67477686517SSundar R Iyer 		.end	= AB8500_INT_PON_KEY1DB_F,
67577686517SSundar R Iyer 		.flags	= IORESOURCE_IRQ,
67677686517SSundar R Iyer 	},
67777686517SSundar R Iyer 	{
67877686517SSundar R Iyer 		.name	= "ONKEY_DBR",
67977686517SSundar R Iyer 		.start	= AB8500_INT_PON_KEY1DB_R,
68077686517SSundar R Iyer 		.end	= AB8500_INT_PON_KEY1DB_R,
68177686517SSundar R Iyer 		.flags	= IORESOURCE_IRQ,
68277686517SSundar R Iyer 	},
68377686517SSundar R Iyer };
68477686517SSundar R Iyer 
685a9e9ce4cSBill Pemberton static struct resource ab8500_av_acc_detect_resources[] = {
686e098adedSMattias Wallin 	{
6876af75ecdSLinus Walleij 	       .name = "ACC_DETECT_1DB_F",
6886af75ecdSLinus Walleij 	       .start = AB8500_INT_ACC_DETECT_1DB_F,
6896af75ecdSLinus Walleij 	       .end = AB8500_INT_ACC_DETECT_1DB_F,
690e098adedSMattias Wallin 	       .flags = IORESOURCE_IRQ,
691e098adedSMattias Wallin 	},
692e098adedSMattias Wallin 	{
6936af75ecdSLinus Walleij 	       .name = "ACC_DETECT_1DB_R",
6946af75ecdSLinus Walleij 	       .start = AB8500_INT_ACC_DETECT_1DB_R,
6956af75ecdSLinus Walleij 	       .end = AB8500_INT_ACC_DETECT_1DB_R,
696e098adedSMattias Wallin 	       .flags = IORESOURCE_IRQ,
697e098adedSMattias Wallin 	},
698e098adedSMattias Wallin 	{
6996af75ecdSLinus Walleij 	       .name = "ACC_DETECT_21DB_F",
7006af75ecdSLinus Walleij 	       .start = AB8500_INT_ACC_DETECT_21DB_F,
7016af75ecdSLinus Walleij 	       .end = AB8500_INT_ACC_DETECT_21DB_F,
7026af75ecdSLinus Walleij 	       .flags = IORESOURCE_IRQ,
7036af75ecdSLinus Walleij 	},
7046af75ecdSLinus Walleij 	{
7056af75ecdSLinus Walleij 	       .name = "ACC_DETECT_21DB_R",
7066af75ecdSLinus Walleij 	       .start = AB8500_INT_ACC_DETECT_21DB_R,
7076af75ecdSLinus Walleij 	       .end = AB8500_INT_ACC_DETECT_21DB_R,
7086af75ecdSLinus Walleij 	       .flags = IORESOURCE_IRQ,
7096af75ecdSLinus Walleij 	},
7106af75ecdSLinus Walleij 	{
7116af75ecdSLinus Walleij 	       .name = "ACC_DETECT_22DB_F",
7126af75ecdSLinus Walleij 	       .start = AB8500_INT_ACC_DETECT_22DB_F,
7136af75ecdSLinus Walleij 	       .end = AB8500_INT_ACC_DETECT_22DB_F,
7146af75ecdSLinus Walleij 	       .flags = IORESOURCE_IRQ,
7156af75ecdSLinus Walleij 	},
7166af75ecdSLinus Walleij 	{
7176af75ecdSLinus Walleij 	       .name = "ACC_DETECT_22DB_R",
7186af75ecdSLinus Walleij 	       .start = AB8500_INT_ACC_DETECT_22DB_R,
7196af75ecdSLinus Walleij 	       .end = AB8500_INT_ACC_DETECT_22DB_R,
7206af75ecdSLinus Walleij 	       .flags = IORESOURCE_IRQ,
7216af75ecdSLinus Walleij 	},
7226af75ecdSLinus Walleij };
7236af75ecdSLinus Walleij 
724a9e9ce4cSBill Pemberton static struct resource ab8500_charger_resources[] = {
7256af75ecdSLinus Walleij 	{
726e098adedSMattias Wallin 		.name = "MAIN_CH_UNPLUG_DET",
727e098adedSMattias Wallin 		.start = AB8500_INT_MAIN_CH_UNPLUG_DET,
728e098adedSMattias Wallin 		.end = AB8500_INT_MAIN_CH_UNPLUG_DET,
729e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
730e098adedSMattias Wallin 	},
731e098adedSMattias Wallin 	{
732e098adedSMattias Wallin 		.name = "MAIN_CHARGE_PLUG_DET",
733e098adedSMattias Wallin 		.start = AB8500_INT_MAIN_CH_PLUG_DET,
734e098adedSMattias Wallin 		.end = AB8500_INT_MAIN_CH_PLUG_DET,
735e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
736e098adedSMattias Wallin 	},
737e098adedSMattias Wallin 	{
738e098adedSMattias Wallin 		.name = "VBUS_DET_R",
739e098adedSMattias Wallin 		.start = AB8500_INT_VBUS_DET_R,
740e098adedSMattias Wallin 		.end = AB8500_INT_VBUS_DET_R,
741e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
742e098adedSMattias Wallin 	},
743e098adedSMattias Wallin 	{
7446af75ecdSLinus Walleij 		.name = "VBUS_DET_F",
7456af75ecdSLinus Walleij 		.start = AB8500_INT_VBUS_DET_F,
7466af75ecdSLinus Walleij 		.end = AB8500_INT_VBUS_DET_F,
747e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
748e098adedSMattias Wallin 	},
749e098adedSMattias Wallin 	{
7506af75ecdSLinus Walleij 		.name = "USB_LINK_STATUS",
7516af75ecdSLinus Walleij 		.start = AB8500_INT_USB_LINK_STATUS,
7526af75ecdSLinus Walleij 		.end = AB8500_INT_USB_LINK_STATUS,
7536af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
7546af75ecdSLinus Walleij 	},
7556af75ecdSLinus Walleij 	{
756e098adedSMattias Wallin 		.name = "VBUS_OVV",
757e098adedSMattias Wallin 		.start = AB8500_INT_VBUS_OVV,
758e098adedSMattias Wallin 		.end = AB8500_INT_VBUS_OVV,
759e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
760e098adedSMattias Wallin 	},
761e098adedSMattias Wallin 	{
7626af75ecdSLinus Walleij 		.name = "USB_CH_TH_PROT_R",
7636af75ecdSLinus Walleij 		.start = AB8500_INT_USB_CH_TH_PROT_R,
7646af75ecdSLinus Walleij 		.end = AB8500_INT_USB_CH_TH_PROT_R,
765e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
766e098adedSMattias Wallin 	},
767e098adedSMattias Wallin 	{
7686af75ecdSLinus Walleij 		.name = "USB_CH_TH_PROT_F",
7696af75ecdSLinus Walleij 		.start = AB8500_INT_USB_CH_TH_PROT_F,
7706af75ecdSLinus Walleij 		.end = AB8500_INT_USB_CH_TH_PROT_F,
771e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
772e098adedSMattias Wallin 	},
773e098adedSMattias Wallin 	{
7746af75ecdSLinus Walleij 		.name = "MAIN_EXT_CH_NOT_OK",
7756af75ecdSLinus Walleij 		.start = AB8500_INT_MAIN_EXT_CH_NOT_OK,
7766af75ecdSLinus Walleij 		.end = AB8500_INT_MAIN_EXT_CH_NOT_OK,
7776af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
7786af75ecdSLinus Walleij 	},
7796af75ecdSLinus Walleij 	{
7806af75ecdSLinus Walleij 		.name = "MAIN_CH_TH_PROT_R",
7816af75ecdSLinus Walleij 		.start = AB8500_INT_MAIN_CH_TH_PROT_R,
7826af75ecdSLinus Walleij 		.end = AB8500_INT_MAIN_CH_TH_PROT_R,
7836af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
7846af75ecdSLinus Walleij 	},
7856af75ecdSLinus Walleij 	{
7866af75ecdSLinus Walleij 		.name = "MAIN_CH_TH_PROT_F",
7876af75ecdSLinus Walleij 		.start = AB8500_INT_MAIN_CH_TH_PROT_F,
7886af75ecdSLinus Walleij 		.end = AB8500_INT_MAIN_CH_TH_PROT_F,
7896af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
7906af75ecdSLinus Walleij 	},
7916af75ecdSLinus Walleij 	{
7926af75ecdSLinus Walleij 		.name = "USB_CHARGER_NOT_OKR",
793a982362cSBengt Jonsson 		.start = AB8500_INT_USB_CHARGER_NOT_OKR,
794a982362cSBengt Jonsson 		.end = AB8500_INT_USB_CHARGER_NOT_OKR,
7956af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
7966af75ecdSLinus Walleij 	},
7976af75ecdSLinus Walleij 	{
7986af75ecdSLinus Walleij 		.name = "CH_WD_EXP",
7996af75ecdSLinus Walleij 		.start = AB8500_INT_CH_WD_EXP,
8006af75ecdSLinus Walleij 		.end = AB8500_INT_CH_WD_EXP,
8016af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
8026af75ecdSLinus Walleij 	},
80334c11a70SPaer-Olof Haakansson 	{
80434c11a70SPaer-Olof Haakansson 		.name = "VBUS_CH_DROP_END",
80534c11a70SPaer-Olof Haakansson 		.start = AB8500_INT_VBUS_CH_DROP_END,
80634c11a70SPaer-Olof Haakansson 		.end = AB8500_INT_VBUS_CH_DROP_END,
80734c11a70SPaer-Olof Haakansson 		.flags = IORESOURCE_IRQ,
80834c11a70SPaer-Olof Haakansson 	},
8096af75ecdSLinus Walleij };
8106af75ecdSLinus Walleij 
811a9e9ce4cSBill Pemberton static struct resource ab8500_btemp_resources[] = {
8126af75ecdSLinus Walleij 	{
8136af75ecdSLinus Walleij 		.name = "BAT_CTRL_INDB",
8146af75ecdSLinus Walleij 		.start = AB8500_INT_BAT_CTRL_INDB,
8156af75ecdSLinus Walleij 		.end = AB8500_INT_BAT_CTRL_INDB,
816e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
817e098adedSMattias Wallin 	},
818e098adedSMattias Wallin 	{
819e098adedSMattias Wallin 		.name = "BTEMP_LOW",
820e098adedSMattias Wallin 		.start = AB8500_INT_BTEMP_LOW,
821e098adedSMattias Wallin 		.end = AB8500_INT_BTEMP_LOW,
822e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
823e098adedSMattias Wallin 	},
824e098adedSMattias Wallin 	{
825e098adedSMattias Wallin 		.name = "BTEMP_HIGH",
826e098adedSMattias Wallin 		.start = AB8500_INT_BTEMP_HIGH,
827e098adedSMattias Wallin 		.end = AB8500_INT_BTEMP_HIGH,
828e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
829e098adedSMattias Wallin 	},
830e098adedSMattias Wallin 	{
8316af75ecdSLinus Walleij 		.name = "BTEMP_LOW_MEDIUM",
8326af75ecdSLinus Walleij 		.start = AB8500_INT_BTEMP_LOW_MEDIUM,
8336af75ecdSLinus Walleij 		.end = AB8500_INT_BTEMP_LOW_MEDIUM,
834e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
835e098adedSMattias Wallin 	},
836e098adedSMattias Wallin 	{
8376af75ecdSLinus Walleij 		.name = "BTEMP_MEDIUM_HIGH",
8386af75ecdSLinus Walleij 		.start = AB8500_INT_BTEMP_MEDIUM_HIGH,
8396af75ecdSLinus Walleij 		.end = AB8500_INT_BTEMP_MEDIUM_HIGH,
840e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
841e098adedSMattias Wallin 	},
842e098adedSMattias Wallin };
843e098adedSMattias Wallin 
844a9e9ce4cSBill Pemberton static struct resource ab8500_fg_resources[] = {
8456af75ecdSLinus Walleij 	{
8466af75ecdSLinus Walleij 		.name = "NCONV_ACCU",
8476af75ecdSLinus Walleij 		.start = AB8500_INT_CCN_CONV_ACC,
8486af75ecdSLinus Walleij 		.end = AB8500_INT_CCN_CONV_ACC,
8496af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
8506af75ecdSLinus Walleij 	},
8516af75ecdSLinus Walleij 	{
8526af75ecdSLinus Walleij 		.name = "BATT_OVV",
8536af75ecdSLinus Walleij 		.start = AB8500_INT_BATT_OVV,
8546af75ecdSLinus Walleij 		.end = AB8500_INT_BATT_OVV,
8556af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
8566af75ecdSLinus Walleij 	},
8576af75ecdSLinus Walleij 	{
8586af75ecdSLinus Walleij 		.name = "LOW_BAT_F",
8596af75ecdSLinus Walleij 		.start = AB8500_INT_LOW_BAT_F,
8606af75ecdSLinus Walleij 		.end = AB8500_INT_LOW_BAT_F,
8616af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
8626af75ecdSLinus Walleij 	},
8636af75ecdSLinus Walleij 	{
8646af75ecdSLinus Walleij 		.name = "LOW_BAT_R",
8656af75ecdSLinus Walleij 		.start = AB8500_INT_LOW_BAT_R,
8666af75ecdSLinus Walleij 		.end = AB8500_INT_LOW_BAT_R,
8676af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
8686af75ecdSLinus Walleij 	},
8696af75ecdSLinus Walleij 	{
8706af75ecdSLinus Walleij 		.name = "CC_INT_CALIB",
8716af75ecdSLinus Walleij 		.start = AB8500_INT_CC_INT_CALIB,
8726af75ecdSLinus Walleij 		.end = AB8500_INT_CC_INT_CALIB,
8736af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
8746af75ecdSLinus Walleij 	},
875a982362cSBengt Jonsson 	{
876a982362cSBengt Jonsson 		.name = "CCEOC",
877a982362cSBengt Jonsson 		.start = AB8500_INT_CCEOC,
878a982362cSBengt Jonsson 		.end = AB8500_INT_CCEOC,
879a982362cSBengt Jonsson 		.flags = IORESOURCE_IRQ,
880a982362cSBengt Jonsson 	},
8816af75ecdSLinus Walleij };
8826af75ecdSLinus Walleij 
883a9e9ce4cSBill Pemberton static struct resource ab8500_chargalg_resources[] = {};
8846af75ecdSLinus Walleij 
885df720647SAxel Lin #ifdef CONFIG_DEBUG_FS
886a9e9ce4cSBill Pemberton static struct resource ab8500_debug_resources[] = {
887e098adedSMattias Wallin 	{
8886999181eSLinus Walleij 		.name	= "IRQ_AB8500",
8896999181eSLinus Walleij 		/*
8906999181eSLinus Walleij 		 * Number will be filled in. NOTE: this is deliberately
8916999181eSLinus Walleij 		 * not flagged as an IRQ in ordet to avoid remapping using
8926999181eSLinus Walleij 		 * the irqdomain in the MFD core, so that this IRQ passes
8936999181eSLinus Walleij 		 * unremapped to the debug code.
8946999181eSLinus Walleij 		 */
8956999181eSLinus Walleij 	},
8966999181eSLinus Walleij 	{
897e098adedSMattias Wallin 		.name	= "IRQ_FIRST",
898e098adedSMattias Wallin 		.start	= AB8500_INT_MAIN_EXT_CH_NOT_OK,
899e098adedSMattias Wallin 		.end	= AB8500_INT_MAIN_EXT_CH_NOT_OK,
900e098adedSMattias Wallin 		.flags	= IORESOURCE_IRQ,
901e098adedSMattias Wallin 	},
902e098adedSMattias Wallin 	{
903e098adedSMattias Wallin 		.name	= "IRQ_LAST",
904a982362cSBengt Jonsson 		.start	= AB8500_INT_XTAL32K_KO,
905a982362cSBengt Jonsson 		.end	= AB8500_INT_XTAL32K_KO,
906e098adedSMattias Wallin 		.flags	= IORESOURCE_IRQ,
907e098adedSMattias Wallin 	},
908e098adedSMattias Wallin };
909df720647SAxel Lin #endif
910e098adedSMattias Wallin 
911a9e9ce4cSBill Pemberton static struct resource ab8500_usb_resources[] = {
912e098adedSMattias Wallin 	{
913e098adedSMattias Wallin 		.name = "ID_WAKEUP_R",
914e098adedSMattias Wallin 		.start = AB8500_INT_ID_WAKEUP_R,
915e098adedSMattias Wallin 		.end = AB8500_INT_ID_WAKEUP_R,
916e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
917e098adedSMattias Wallin 	},
918e098adedSMattias Wallin 	{
919e098adedSMattias Wallin 		.name = "ID_WAKEUP_F",
920e098adedSMattias Wallin 		.start = AB8500_INT_ID_WAKEUP_F,
921e098adedSMattias Wallin 		.end = AB8500_INT_ID_WAKEUP_F,
922e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
923e098adedSMattias Wallin 	},
924e098adedSMattias Wallin 	{
925e098adedSMattias Wallin 		.name = "VBUS_DET_F",
926e098adedSMattias Wallin 		.start = AB8500_INT_VBUS_DET_F,
927e098adedSMattias Wallin 		.end = AB8500_INT_VBUS_DET_F,
928e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
929e098adedSMattias Wallin 	},
930e098adedSMattias Wallin 	{
931e098adedSMattias Wallin 		.name = "VBUS_DET_R",
932e098adedSMattias Wallin 		.start = AB8500_INT_VBUS_DET_R,
933e098adedSMattias Wallin 		.end = AB8500_INT_VBUS_DET_R,
934e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
935e098adedSMattias Wallin 	},
93692d50a41SMattias Wallin 	{
93792d50a41SMattias Wallin 		.name = "USB_LINK_STATUS",
93892d50a41SMattias Wallin 		.start = AB8500_INT_USB_LINK_STATUS,
93992d50a41SMattias Wallin 		.end = AB8500_INT_USB_LINK_STATUS,
94092d50a41SMattias Wallin 		.flags = IORESOURCE_IRQ,
94192d50a41SMattias Wallin 	},
9426af75ecdSLinus Walleij 	{
9436af75ecdSLinus Walleij 		.name = "USB_ADP_PROBE_PLUG",
9446af75ecdSLinus Walleij 		.start = AB8500_INT_ADP_PROBE_PLUG,
9456af75ecdSLinus Walleij 		.end = AB8500_INT_ADP_PROBE_PLUG,
9466af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
9476af75ecdSLinus Walleij 	},
9486af75ecdSLinus Walleij 	{
9496af75ecdSLinus Walleij 		.name = "USB_ADP_PROBE_UNPLUG",
9506af75ecdSLinus Walleij 		.start = AB8500_INT_ADP_PROBE_UNPLUG,
9516af75ecdSLinus Walleij 		.end = AB8500_INT_ADP_PROBE_UNPLUG,
9526af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
9536af75ecdSLinus Walleij 	},
954e098adedSMattias Wallin };
955e098adedSMattias Wallin 
956a9e9ce4cSBill Pemberton static struct resource ab8505_iddet_resources[] = {
95744f72e53SVirupax Sadashivpetimath 	{
95844f72e53SVirupax Sadashivpetimath 		.name  = "KeyDeglitch",
95944f72e53SVirupax Sadashivpetimath 		.start = AB8505_INT_KEYDEGLITCH,
96044f72e53SVirupax Sadashivpetimath 		.end   = AB8505_INT_KEYDEGLITCH,
96144f72e53SVirupax Sadashivpetimath 		.flags = IORESOURCE_IRQ,
96244f72e53SVirupax Sadashivpetimath 	},
96344f72e53SVirupax Sadashivpetimath 	{
96444f72e53SVirupax Sadashivpetimath 		.name  = "KP",
96544f72e53SVirupax Sadashivpetimath 		.start = AB8505_INT_KP,
96644f72e53SVirupax Sadashivpetimath 		.end   = AB8505_INT_KP,
96744f72e53SVirupax Sadashivpetimath 		.flags = IORESOURCE_IRQ,
96844f72e53SVirupax Sadashivpetimath 	},
96944f72e53SVirupax Sadashivpetimath 	{
97044f72e53SVirupax Sadashivpetimath 		.name  = "IKP",
97144f72e53SVirupax Sadashivpetimath 		.start = AB8505_INT_IKP,
97244f72e53SVirupax Sadashivpetimath 		.end   = AB8505_INT_IKP,
97344f72e53SVirupax Sadashivpetimath 		.flags = IORESOURCE_IRQ,
97444f72e53SVirupax Sadashivpetimath 	},
97544f72e53SVirupax Sadashivpetimath 	{
97644f72e53SVirupax Sadashivpetimath 		.name  = "IKR",
97744f72e53SVirupax Sadashivpetimath 		.start = AB8505_INT_IKR,
97844f72e53SVirupax Sadashivpetimath 		.end   = AB8505_INT_IKR,
97944f72e53SVirupax Sadashivpetimath 		.flags = IORESOURCE_IRQ,
98044f72e53SVirupax Sadashivpetimath 	},
98144f72e53SVirupax Sadashivpetimath 	{
98244f72e53SVirupax Sadashivpetimath 		.name  = "KeyStuck",
98344f72e53SVirupax Sadashivpetimath 		.start = AB8505_INT_KEYSTUCK,
98444f72e53SVirupax Sadashivpetimath 		.end   = AB8505_INT_KEYSTUCK,
98544f72e53SVirupax Sadashivpetimath 		.flags = IORESOURCE_IRQ,
98644f72e53SVirupax Sadashivpetimath 	},
987492390c8SLee Jones 	{
988492390c8SLee Jones 		.name = "VBUS_DET_R",
989492390c8SLee Jones 		.start = AB8500_INT_VBUS_DET_R,
990492390c8SLee Jones 		.end = AB8500_INT_VBUS_DET_R,
991492390c8SLee Jones 		.flags = IORESOURCE_IRQ,
992492390c8SLee Jones 	},
993492390c8SLee Jones 	{
994492390c8SLee Jones 		.name = "VBUS_DET_F",
995492390c8SLee Jones 		.start = AB8500_INT_VBUS_DET_F,
996492390c8SLee Jones 		.end = AB8500_INT_VBUS_DET_F,
997492390c8SLee Jones 		.flags = IORESOURCE_IRQ,
998492390c8SLee Jones 	},
999492390c8SLee Jones 	{
1000492390c8SLee Jones 		.name = "ID_DET_PLUGR",
1001492390c8SLee Jones 		.start = AB8500_INT_ID_DET_PLUGR,
1002492390c8SLee Jones 		.end = AB8500_INT_ID_DET_PLUGR,
1003492390c8SLee Jones 		.flags = IORESOURCE_IRQ,
1004492390c8SLee Jones 	},
1005492390c8SLee Jones 	{
1006492390c8SLee Jones 		.name = "ID_DET_PLUGF",
1007492390c8SLee Jones 		.start = AB8500_INT_ID_DET_PLUGF,
1008492390c8SLee Jones 		.end = AB8500_INT_ID_DET_PLUGF,
1009492390c8SLee Jones 		.flags = IORESOURCE_IRQ,
1010492390c8SLee Jones 	},
101144f72e53SVirupax Sadashivpetimath };
101244f72e53SVirupax Sadashivpetimath 
1013a9e9ce4cSBill Pemberton static struct resource ab8500_temp_resources[] = {
1014e098adedSMattias Wallin 	{
1015151621a7SHongbo Zhang 		.name  = "ABX500_TEMP_WARM",
1016e098adedSMattias Wallin 		.start = AB8500_INT_TEMP_WARM,
1017e098adedSMattias Wallin 		.end   = AB8500_INT_TEMP_WARM,
1018e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
1019e098adedSMattias Wallin 	},
1020e098adedSMattias Wallin };
1021e098adedSMattias Wallin 
10225ac98553SGeert Uytterhoeven static const struct mfd_cell ab8500_bm_devs[] = {
10236ef9418cSRickard Andersson 	{
10246ef9418cSRickard Andersson 		.name = "ab8500-charger",
10254aef72dbSRajanikanth H.V 		.of_compatible = "stericsson,ab8500-charger",
10266ef9418cSRickard Andersson 		.num_resources = ARRAY_SIZE(ab8500_charger_resources),
10276ef9418cSRickard Andersson 		.resources = ab8500_charger_resources,
10284aef72dbSRajanikanth H.V 		.platform_data = &ab8500_bm_data,
10294aef72dbSRajanikanth H.V 		.pdata_size = sizeof(ab8500_bm_data),
10306ef9418cSRickard Andersson 	},
10316ef9418cSRickard Andersson 	{
10326ef9418cSRickard Andersson 		.name = "ab8500-btemp",
1033bd9e8ab2SRajanikanth H.V 		.of_compatible = "stericsson,ab8500-btemp",
10346ef9418cSRickard Andersson 		.num_resources = ARRAY_SIZE(ab8500_btemp_resources),
10356ef9418cSRickard Andersson 		.resources = ab8500_btemp_resources,
1036bd9e8ab2SRajanikanth H.V 		.platform_data = &ab8500_bm_data,
1037bd9e8ab2SRajanikanth H.V 		.pdata_size = sizeof(ab8500_bm_data),
10386ef9418cSRickard Andersson 	},
10396ef9418cSRickard Andersson 	{
10406ef9418cSRickard Andersson 		.name = "ab8500-fg",
1041e0f1abebSRajanikanth H.V 		.of_compatible = "stericsson,ab8500-fg",
10426ef9418cSRickard Andersson 		.num_resources = ARRAY_SIZE(ab8500_fg_resources),
10436ef9418cSRickard Andersson 		.resources = ab8500_fg_resources,
1044e0f1abebSRajanikanth H.V 		.platform_data = &ab8500_bm_data,
1045e0f1abebSRajanikanth H.V 		.pdata_size = sizeof(ab8500_bm_data),
10466ef9418cSRickard Andersson 	},
10476ef9418cSRickard Andersson 	{
10486ef9418cSRickard Andersson 		.name = "ab8500-chargalg",
1049a12810abSRajanikanth H.V 		.of_compatible = "stericsson,ab8500-chargalg",
10506ef9418cSRickard Andersson 		.num_resources = ARRAY_SIZE(ab8500_chargalg_resources),
10516ef9418cSRickard Andersson 		.resources = ab8500_chargalg_resources,
1052a12810abSRajanikanth H.V 		.platform_data = &ab8500_bm_data,
1053a12810abSRajanikanth H.V 		.pdata_size = sizeof(ab8500_bm_data),
10546ef9418cSRickard Andersson 	},
10556ef9418cSRickard Andersson };
10566ef9418cSRickard Andersson 
10575ac98553SGeert Uytterhoeven static const struct mfd_cell ab8500_devs[] = {
10584b106fb9SLee Jones #ifdef CONFIG_DEBUG_FS
1059d6255529SLinus Walleij 	{
10604b106fb9SLee Jones 		.name = "ab8500-debug",
10614b106fb9SLee Jones 		.of_compatible = "stericsson,ab8500-debug",
10624b106fb9SLee Jones 		.num_resources = ARRAY_SIZE(ab8500_debug_resources),
10634b106fb9SLee Jones 		.resources = ab8500_debug_resources,
10644b106fb9SLee Jones 	},
10654b106fb9SLee Jones #endif
10664b106fb9SLee Jones 	{
10674b106fb9SLee Jones 		.name = "ab8500-sysctrl",
10684b106fb9SLee Jones 		.of_compatible = "stericsson,ab8500-sysctrl",
10694b106fb9SLee Jones 	},
10704b106fb9SLee Jones 	{
107153f325beSLee Jones 		.name = "ab8500-ext-regulator",
107253f325beSLee Jones 		.of_compatible = "stericsson,ab8500-ext-regulator",
107353f325beSLee Jones 	},
107453f325beSLee Jones 	{
10754b106fb9SLee Jones 		.name = "ab8500-regulator",
10764b106fb9SLee Jones 		.of_compatible = "stericsson,ab8500-regulator",
10774b106fb9SLee Jones 	},
10784b106fb9SLee Jones 	{
10794b106fb9SLee Jones 		.name = "abx500-clk",
10804b106fb9SLee Jones 		.of_compatible = "stericsson,abx500-clk",
10814b106fb9SLee Jones 	},
10824b106fb9SLee Jones 	{
10834b106fb9SLee Jones 		.name = "ab8500-gpadc",
1084955de2eaSLee Jones 		.of_compatible = "stericsson,ab8500-gpadc",
10854b106fb9SLee Jones 		.num_resources = ARRAY_SIZE(ab8500_gpadc_resources),
10864b106fb9SLee Jones 		.resources = ab8500_gpadc_resources,
10874b106fb9SLee Jones 	},
10884b106fb9SLee Jones 	{
10894b106fb9SLee Jones 		.name = "ab8500-rtc",
10904b106fb9SLee Jones 		.of_compatible = "stericsson,ab8500-rtc",
10914b106fb9SLee Jones 		.num_resources = ARRAY_SIZE(ab8500_rtc_resources),
10924b106fb9SLee Jones 		.resources = ab8500_rtc_resources,
10934b106fb9SLee Jones 	},
10944b106fb9SLee Jones 	{
10954b106fb9SLee Jones 		.name = "ab8500-acc-det",
10964b106fb9SLee Jones 		.of_compatible = "stericsson,ab8500-acc-det",
10974b106fb9SLee Jones 		.num_resources = ARRAY_SIZE(ab8500_av_acc_detect_resources),
10984b106fb9SLee Jones 		.resources = ab8500_av_acc_detect_resources,
10994b106fb9SLee Jones 	},
11004b106fb9SLee Jones 	{
11014b106fb9SLee Jones 
11024b106fb9SLee Jones 		.name = "ab8500-poweron-key",
11034b106fb9SLee Jones 		.of_compatible = "stericsson,ab8500-poweron-key",
11044b106fb9SLee Jones 		.num_resources = ARRAY_SIZE(ab8500_poweronkey_db_resources),
11054b106fb9SLee Jones 		.resources = ab8500_poweronkey_db_resources,
11064b106fb9SLee Jones 	},
11074b106fb9SLee Jones 	{
11084b106fb9SLee Jones 		.name = "ab8500-pwm",
11094b106fb9SLee Jones 		.of_compatible = "stericsson,ab8500-pwm",
11104b106fb9SLee Jones 		.id = 1,
11114b106fb9SLee Jones 	},
11124b106fb9SLee Jones 	{
11134b106fb9SLee Jones 		.name = "ab8500-pwm",
11144b106fb9SLee Jones 		.of_compatible = "stericsson,ab8500-pwm",
11154b106fb9SLee Jones 		.id = 2,
11164b106fb9SLee Jones 	},
11174b106fb9SLee Jones 	{
11184b106fb9SLee Jones 		.name = "ab8500-pwm",
11194b106fb9SLee Jones 		.of_compatible = "stericsson,ab8500-pwm",
11204b106fb9SLee Jones 		.id = 3,
11214b106fb9SLee Jones 	},
11224b106fb9SLee Jones 	{
11234b106fb9SLee Jones 		.name = "ab8500-denc",
11244b106fb9SLee Jones 		.of_compatible = "stericsson,ab8500-denc",
11254b106fb9SLee Jones 	},
11264b106fb9SLee Jones 	{
1127eb696c31SLee Jones 		.name = "pinctrl-ab8500",
1128bad76991SLee Jones 		.of_compatible = "stericsson,ab8500-gpio",
1129d6255529SLinus Walleij 	},
1130d6255529SLinus Walleij 	{
11314b106fb9SLee Jones 		.name = "abx500-temp",
11324b106fb9SLee Jones 		.of_compatible = "stericsson,abx500-temp",
11334b106fb9SLee Jones 		.num_resources = ARRAY_SIZE(ab8500_temp_resources),
11344b106fb9SLee Jones 		.resources = ab8500_temp_resources,
11354b106fb9SLee Jones 	},
11364b106fb9SLee Jones 	{
1137d6255529SLinus Walleij 		.name = "ab8500-usb",
1138f201f730SFabio Baltieri 		.of_compatible = "stericsson,ab8500-usb",
1139d6255529SLinus Walleij 		.num_resources = ARRAY_SIZE(ab8500_usb_resources),
1140d6255529SLinus Walleij 		.resources = ab8500_usb_resources,
1141d6255529SLinus Walleij 	},
114244f72e53SVirupax Sadashivpetimath 	{
114344f72e53SVirupax Sadashivpetimath 		.name = "ab8500-codec",
1144fccf14adSFabio Baltieri 		.of_compatible = "stericsson,ab8500-codec",
11454b106fb9SLee Jones 	},
11464b106fb9SLee Jones };
11474b106fb9SLee Jones 
11485ac98553SGeert Uytterhoeven static const struct mfd_cell ab9540_devs[] = {
11494b106fb9SLee Jones #ifdef CONFIG_DEBUG_FS
11504b106fb9SLee Jones 	{
11514b106fb9SLee Jones 		.name = "ab8500-debug",
11524b106fb9SLee Jones 		.num_resources = ARRAY_SIZE(ab8500_debug_resources),
11534b106fb9SLee Jones 		.resources = ab8500_debug_resources,
11544b106fb9SLee Jones 	},
11554b106fb9SLee Jones #endif
11564b106fb9SLee Jones 	{
11574b106fb9SLee Jones 		.name = "ab8500-sysctrl",
11584b106fb9SLee Jones 	},
11594b106fb9SLee Jones 	{
116053f325beSLee Jones 		.name = "ab8500-ext-regulator",
116153f325beSLee Jones 	},
116253f325beSLee Jones 	{
11634b106fb9SLee Jones 		.name = "ab8500-regulator",
116444f72e53SVirupax Sadashivpetimath 	},
1165c0eda9aeSLee Jones 	{
11669ee17676SUlf Hansson 		.name = "abx500-clk",
11679ee17676SUlf Hansson 		.of_compatible = "stericsson,abx500-clk",
11689ee17676SUlf Hansson 	},
11699ee17676SUlf Hansson 	{
1170c0eda9aeSLee Jones 		.name = "ab8500-gpadc",
1171c0eda9aeSLee Jones 		.of_compatible = "stericsson,ab8500-gpadc",
1172c0eda9aeSLee Jones 		.num_resources = ARRAY_SIZE(ab8500_gpadc_resources),
1173c0eda9aeSLee Jones 		.resources = ab8500_gpadc_resources,
1174c0eda9aeSLee Jones 	},
11754b106fb9SLee Jones 	{
11764b106fb9SLee Jones 		.name = "ab8500-rtc",
11774b106fb9SLee Jones 		.num_resources = ARRAY_SIZE(ab8500_rtc_resources),
11784b106fb9SLee Jones 		.resources = ab8500_rtc_resources,
11794b106fb9SLee Jones 	},
11804b106fb9SLee Jones 	{
11814b106fb9SLee Jones 		.name = "ab8500-acc-det",
11824b106fb9SLee Jones 		.num_resources = ARRAY_SIZE(ab8500_av_acc_detect_resources),
11834b106fb9SLee Jones 		.resources = ab8500_av_acc_detect_resources,
11844b106fb9SLee Jones 	},
11854b106fb9SLee Jones 	{
11864b106fb9SLee Jones 		.name = "ab8500-poweron-key",
11874b106fb9SLee Jones 		.num_resources = ARRAY_SIZE(ab8500_poweronkey_db_resources),
11884b106fb9SLee Jones 		.resources = ab8500_poweronkey_db_resources,
11894b106fb9SLee Jones 	},
11904b106fb9SLee Jones 	{
11914b106fb9SLee Jones 		.name = "ab8500-pwm",
11924b106fb9SLee Jones 		.id = 1,
11934b106fb9SLee Jones 	},
11944b106fb9SLee Jones 	{
11954b106fb9SLee Jones 		.name = "abx500-temp",
11964b106fb9SLee Jones 		.num_resources = ARRAY_SIZE(ab8500_temp_resources),
11974b106fb9SLee Jones 		.resources = ab8500_temp_resources,
11984b106fb9SLee Jones 	},
1199d6255529SLinus Walleij 	{
1200e64d905eSLee Jones 		.name = "pinctrl-ab9540",
1201e64d905eSLee Jones 		.of_compatible = "stericsson,ab9540-gpio",
1202d6255529SLinus Walleij 	},
1203d6255529SLinus Walleij 	{
1204d6255529SLinus Walleij 		.name = "ab9540-usb",
1205d6255529SLinus Walleij 		.num_resources = ARRAY_SIZE(ab8500_usb_resources),
1206d6255529SLinus Walleij 		.resources = ab8500_usb_resources,
1207d6255529SLinus Walleij 	},
120844f72e53SVirupax Sadashivpetimath 	{
120944f72e53SVirupax Sadashivpetimath 		.name = "ab9540-codec",
121044f72e53SVirupax Sadashivpetimath 	},
1211c0eda9aeSLee Jones 	{
1212c0eda9aeSLee Jones 		.name = "ab-iddet",
1213c0eda9aeSLee Jones 		.num_resources = ARRAY_SIZE(ab8505_iddet_resources),
1214c0eda9aeSLee Jones 		.resources = ab8505_iddet_resources,
1215c0eda9aeSLee Jones 	},
121644f72e53SVirupax Sadashivpetimath };
121744f72e53SVirupax Sadashivpetimath 
1218c0eda9aeSLee Jones /* Device list for ab8505  */
12195ac98553SGeert Uytterhoeven static const struct mfd_cell ab8505_devs[] = {
12204b106fb9SLee Jones #ifdef CONFIG_DEBUG_FS
12214b106fb9SLee Jones 	{
12224b106fb9SLee Jones 		.name = "ab8500-debug",
12234b106fb9SLee Jones 		.num_resources = ARRAY_SIZE(ab8500_debug_resources),
12244b106fb9SLee Jones 		.resources = ab8500_debug_resources,
12254b106fb9SLee Jones 	},
12264b106fb9SLee Jones #endif
12274b106fb9SLee Jones 	{
12284b106fb9SLee Jones 		.name = "ab8500-sysctrl",
12294b106fb9SLee Jones 	},
12304b106fb9SLee Jones 	{
12314b106fb9SLee Jones 		.name = "ab8500-regulator",
12324b106fb9SLee Jones 	},
12334b106fb9SLee Jones 	{
12349ee17676SUlf Hansson 		.name = "abx500-clk",
12359ee17676SUlf Hansson 		.of_compatible = "stericsson,abx500-clk",
12369ee17676SUlf Hansson 	},
12379ee17676SUlf Hansson 	{
12384b106fb9SLee Jones 		.name = "ab8500-gpadc",
1239955de2eaSLee Jones 		.of_compatible = "stericsson,ab8500-gpadc",
12404b106fb9SLee Jones 		.num_resources = ARRAY_SIZE(ab8505_gpadc_resources),
12414b106fb9SLee Jones 		.resources = ab8505_gpadc_resources,
12424b106fb9SLee Jones 	},
12434b106fb9SLee Jones 	{
12444b106fb9SLee Jones 		.name = "ab8500-rtc",
12454b106fb9SLee Jones 		.num_resources = ARRAY_SIZE(ab8500_rtc_resources),
12464b106fb9SLee Jones 		.resources = ab8500_rtc_resources,
12474b106fb9SLee Jones 	},
12484b106fb9SLee Jones 	{
12494b106fb9SLee Jones 		.name = "ab8500-acc-det",
12504b106fb9SLee Jones 		.num_resources = ARRAY_SIZE(ab8500_av_acc_detect_resources),
12514b106fb9SLee Jones 		.resources = ab8500_av_acc_detect_resources,
12524b106fb9SLee Jones 	},
12534b106fb9SLee Jones 	{
12544b106fb9SLee Jones 		.name = "ab8500-poweron-key",
12554b106fb9SLee Jones 		.num_resources = ARRAY_SIZE(ab8500_poweronkey_db_resources),
12564b106fb9SLee Jones 		.resources = ab8500_poweronkey_db_resources,
12574b106fb9SLee Jones 	},
12584b106fb9SLee Jones 	{
12594b106fb9SLee Jones 		.name = "ab8500-pwm",
12604b106fb9SLee Jones 		.id = 1,
12614b106fb9SLee Jones 	},
12624b106fb9SLee Jones 	{
1263eb696c31SLee Jones 		.name = "pinctrl-ab8505",
12644b106fb9SLee Jones 	},
12654b106fb9SLee Jones 	{
12664b106fb9SLee Jones 		.name = "ab8500-usb",
12674b106fb9SLee Jones 		.num_resources = ARRAY_SIZE(ab8500_usb_resources),
12684b106fb9SLee Jones 		.resources = ab8500_usb_resources,
12694b106fb9SLee Jones 	},
12704b106fb9SLee Jones 	{
12714b106fb9SLee Jones 		.name = "ab8500-codec",
12724b106fb9SLee Jones 	},
1273c0eda9aeSLee Jones 	{
1274c0eda9aeSLee Jones 		.name = "ab-iddet",
1275c0eda9aeSLee Jones 		.num_resources = ARRAY_SIZE(ab8505_iddet_resources),
1276c0eda9aeSLee Jones 		.resources = ab8505_iddet_resources,
1277c0eda9aeSLee Jones 	},
1278c0eda9aeSLee Jones };
1279c0eda9aeSLee Jones 
12805ac98553SGeert Uytterhoeven static const struct mfd_cell ab8540_devs[] = {
12814b106fb9SLee Jones #ifdef CONFIG_DEBUG_FS
12824b106fb9SLee Jones 	{
12834b106fb9SLee Jones 		.name = "ab8500-debug",
12844b106fb9SLee Jones 		.num_resources = ARRAY_SIZE(ab8500_debug_resources),
12854b106fb9SLee Jones 		.resources = ab8500_debug_resources,
12864b106fb9SLee Jones 	},
12874b106fb9SLee Jones #endif
12884b106fb9SLee Jones 	{
12894b106fb9SLee Jones 		.name = "ab8500-sysctrl",
12904b106fb9SLee Jones 	},
12914b106fb9SLee Jones 	{
129253f325beSLee Jones 		.name = "ab8500-ext-regulator",
129353f325beSLee Jones 	},
129453f325beSLee Jones 	{
12954b106fb9SLee Jones 		.name = "ab8500-regulator",
12964b106fb9SLee Jones 	},
12974b106fb9SLee Jones 	{
12989ee17676SUlf Hansson 		.name = "abx500-clk",
12999ee17676SUlf Hansson 		.of_compatible = "stericsson,abx500-clk",
13009ee17676SUlf Hansson 	},
13019ee17676SUlf Hansson 	{
13024b106fb9SLee Jones 		.name = "ab8500-gpadc",
1303955de2eaSLee Jones 		.of_compatible = "stericsson,ab8500-gpadc",
13044b106fb9SLee Jones 		.num_resources = ARRAY_SIZE(ab8505_gpadc_resources),
13054b106fb9SLee Jones 		.resources = ab8505_gpadc_resources,
13064b106fb9SLee Jones 	},
13074b106fb9SLee Jones 	{
13084b106fb9SLee Jones 		.name = "ab8500-acc-det",
13094b106fb9SLee Jones 		.num_resources = ARRAY_SIZE(ab8500_av_acc_detect_resources),
13104b106fb9SLee Jones 		.resources = ab8500_av_acc_detect_resources,
13114b106fb9SLee Jones 	},
13124b106fb9SLee Jones 	{
13134b106fb9SLee Jones 		.name = "ab8500-poweron-key",
13144b106fb9SLee Jones 		.num_resources = ARRAY_SIZE(ab8500_poweronkey_db_resources),
13154b106fb9SLee Jones 		.resources = ab8500_poweronkey_db_resources,
13164b106fb9SLee Jones 	},
13174b106fb9SLee Jones 	{
13184b106fb9SLee Jones 		.name = "ab8500-pwm",
13194b106fb9SLee Jones 		.id = 1,
13204b106fb9SLee Jones 	},
13214b106fb9SLee Jones 	{
13224b106fb9SLee Jones 		.name = "abx500-temp",
13234b106fb9SLee Jones 		.num_resources = ARRAY_SIZE(ab8500_temp_resources),
13244b106fb9SLee Jones 		.resources = ab8500_temp_resources,
13254b106fb9SLee Jones 	},
1326c0eda9aeSLee Jones 	{
1327eb696c31SLee Jones 		.name = "pinctrl-ab8540",
1328c0eda9aeSLee Jones 	},
1329c0eda9aeSLee Jones 	{
1330c0eda9aeSLee Jones 		.name = "ab8540-usb",
1331c0eda9aeSLee Jones 		.num_resources = ARRAY_SIZE(ab8500_usb_resources),
1332c0eda9aeSLee Jones 		.resources = ab8500_usb_resources,
1333c0eda9aeSLee Jones 	},
1334c0eda9aeSLee Jones 	{
1335c0eda9aeSLee Jones 		.name = "ab8540-codec",
1336c0eda9aeSLee Jones 	},
1337c0eda9aeSLee Jones 	{
133844f72e53SVirupax Sadashivpetimath 		.name = "ab-iddet",
133944f72e53SVirupax Sadashivpetimath 		.num_resources = ARRAY_SIZE(ab8505_iddet_resources),
134044f72e53SVirupax Sadashivpetimath 		.resources = ab8505_iddet_resources,
134144f72e53SVirupax Sadashivpetimath 	},
1342d6255529SLinus Walleij };
1343d6255529SLinus Walleij 
13445ac98553SGeert Uytterhoeven static const struct mfd_cell ab8540_cut1_devs[] = {
13459c717cf3SAlexandre Torgue 	{
13469c717cf3SAlexandre Torgue 		.name = "ab8500-rtc",
13479c717cf3SAlexandre Torgue 		.of_compatible = "stericsson,ab8500-rtc",
13489c717cf3SAlexandre Torgue 		.num_resources = ARRAY_SIZE(ab8500_rtc_resources),
13499c717cf3SAlexandre Torgue 		.resources = ab8500_rtc_resources,
13509c717cf3SAlexandre Torgue 	},
13519c717cf3SAlexandre Torgue };
13529c717cf3SAlexandre Torgue 
13535ac98553SGeert Uytterhoeven static const struct mfd_cell ab8540_cut2_devs[] = {
13549c717cf3SAlexandre Torgue 	{
13559c717cf3SAlexandre Torgue 		.name = "ab8540-rtc",
13569c717cf3SAlexandre Torgue 		.of_compatible = "stericsson,ab8540-rtc",
13579c717cf3SAlexandre Torgue 		.num_resources = ARRAY_SIZE(ab8540_rtc_resources),
13589c717cf3SAlexandre Torgue 		.resources = ab8540_rtc_resources,
13599c717cf3SAlexandre Torgue 	},
13609c717cf3SAlexandre Torgue };
13619c717cf3SAlexandre Torgue 
1362cca69b67SMattias Wallin static ssize_t show_chip_id(struct device *dev,
1363cca69b67SMattias Wallin 				struct device_attribute *attr, char *buf)
1364cca69b67SMattias Wallin {
1365cca69b67SMattias Wallin 	struct ab8500 *ab8500;
1366cca69b67SMattias Wallin 
1367cca69b67SMattias Wallin 	ab8500 = dev_get_drvdata(dev);
1368e436ddffSLee Jones 
1369cca69b67SMattias Wallin 	return sprintf(buf, "%#x\n", ab8500 ? ab8500->chip_id : -EINVAL);
1370cca69b67SMattias Wallin }
1371cca69b67SMattias Wallin 
1372e5c238c3SMattias Wallin /*
1373e5c238c3SMattias Wallin  * ab8500 has switched off due to (SWITCH_OFF_STATUS):
1374e5c238c3SMattias Wallin  * 0x01 Swoff bit programming
1375e5c238c3SMattias Wallin  * 0x02 Thermal protection activation
1376e5c238c3SMattias Wallin  * 0x04 Vbat lower then BattOk falling threshold
1377e5c238c3SMattias Wallin  * 0x08 Watchdog expired
1378e5c238c3SMattias Wallin  * 0x10 Non presence of 32kHz clock
1379e5c238c3SMattias Wallin  * 0x20 Battery level lower than power on reset threshold
1380e5c238c3SMattias Wallin  * 0x40 Power on key 1 pressed longer than 10 seconds
1381e5c238c3SMattias Wallin  * 0x80 DB8500 thermal shutdown
1382e5c238c3SMattias Wallin  */
1383e5c238c3SMattias Wallin static ssize_t show_switch_off_status(struct device *dev,
1384e5c238c3SMattias Wallin 				struct device_attribute *attr, char *buf)
1385e5c238c3SMattias Wallin {
1386e5c238c3SMattias Wallin 	int ret;
1387e5c238c3SMattias Wallin 	u8 value;
1388e5c238c3SMattias Wallin 	struct ab8500 *ab8500;
1389e5c238c3SMattias Wallin 
1390e5c238c3SMattias Wallin 	ab8500 = dev_get_drvdata(dev);
1391e5c238c3SMattias Wallin 	ret = get_register_interruptible(ab8500, AB8500_RTC,
1392e5c238c3SMattias Wallin 		AB8500_SWITCH_OFF_STATUS, &value);
1393e5c238c3SMattias Wallin 	if (ret < 0)
1394e5c238c3SMattias Wallin 		return ret;
1395e5c238c3SMattias Wallin 	return sprintf(buf, "%#x\n", value);
1396e5c238c3SMattias Wallin }
1397e5c238c3SMattias Wallin 
1398f04a9d8aSRajkumar Kasirajan /* use mask and set to override the register turn_on_stat value */
1399f04a9d8aSRajkumar Kasirajan void ab8500_override_turn_on_stat(u8 mask, u8 set)
1400f04a9d8aSRajkumar Kasirajan {
1401f04a9d8aSRajkumar Kasirajan 	spin_lock(&on_stat_lock);
1402f04a9d8aSRajkumar Kasirajan 	turn_on_stat_mask = mask;
1403f04a9d8aSRajkumar Kasirajan 	turn_on_stat_set = set;
1404f04a9d8aSRajkumar Kasirajan 	spin_unlock(&on_stat_lock);
1405f04a9d8aSRajkumar Kasirajan }
1406f04a9d8aSRajkumar Kasirajan 
1407b4a31037SAndrew Lynn /*
1408b4a31037SAndrew Lynn  * ab8500 has turned on due to (TURN_ON_STATUS):
1409b4a31037SAndrew Lynn  * 0x01 PORnVbat
1410b4a31037SAndrew Lynn  * 0x02 PonKey1dbF
1411b4a31037SAndrew Lynn  * 0x04 PonKey2dbF
1412b4a31037SAndrew Lynn  * 0x08 RTCAlarm
1413b4a31037SAndrew Lynn  * 0x10 MainChDet
1414b4a31037SAndrew Lynn  * 0x20 VbusDet
1415b4a31037SAndrew Lynn  * 0x40 UsbIDDetect
1416b4a31037SAndrew Lynn  * 0x80 Reserved
1417b4a31037SAndrew Lynn  */
1418b4a31037SAndrew Lynn static ssize_t show_turn_on_status(struct device *dev,
1419b4a31037SAndrew Lynn 				struct device_attribute *attr, char *buf)
1420b4a31037SAndrew Lynn {
1421b4a31037SAndrew Lynn 	int ret;
1422b4a31037SAndrew Lynn 	u8 value;
1423b4a31037SAndrew Lynn 	struct ab8500 *ab8500;
1424b4a31037SAndrew Lynn 
1425b4a31037SAndrew Lynn 	ab8500 = dev_get_drvdata(dev);
1426b4a31037SAndrew Lynn 	ret = get_register_interruptible(ab8500, AB8500_SYS_CTRL1_BLOCK,
1427b4a31037SAndrew Lynn 		AB8500_TURN_ON_STATUS, &value);
1428b4a31037SAndrew Lynn 	if (ret < 0)
1429b4a31037SAndrew Lynn 		return ret;
1430f04a9d8aSRajkumar Kasirajan 
1431f04a9d8aSRajkumar Kasirajan 	/*
1432f04a9d8aSRajkumar Kasirajan 	 * In L9540, turn_on_status register is not updated correctly if
1433f04a9d8aSRajkumar Kasirajan 	 * the device is rebooted with AC/USB charger connected. Due to
1434f04a9d8aSRajkumar Kasirajan 	 * this, the device boots android instead of entering into charge
1435f04a9d8aSRajkumar Kasirajan 	 * only mode. Read the AC/USB status register to detect the charger
1436f04a9d8aSRajkumar Kasirajan 	 * presence and update the turn on status manually.
1437f04a9d8aSRajkumar Kasirajan 	 */
1438f04a9d8aSRajkumar Kasirajan 	if (is_ab9540(ab8500)) {
1439f04a9d8aSRajkumar Kasirajan 		spin_lock(&on_stat_lock);
1440f04a9d8aSRajkumar Kasirajan 		value = (value & turn_on_stat_mask) | turn_on_stat_set;
1441f04a9d8aSRajkumar Kasirajan 		spin_unlock(&on_stat_lock);
1442f04a9d8aSRajkumar Kasirajan 	}
1443f04a9d8aSRajkumar Kasirajan 
1444b4a31037SAndrew Lynn 	return sprintf(buf, "%#x\n", value);
1445b4a31037SAndrew Lynn }
1446b4a31037SAndrew Lynn 
144793ff722eSLee Jones static ssize_t show_turn_on_status_2(struct device *dev,
144893ff722eSLee Jones 				struct device_attribute *attr, char *buf)
144993ff722eSLee Jones {
145093ff722eSLee Jones 	int ret;
145193ff722eSLee Jones 	u8 value;
145293ff722eSLee Jones 	struct ab8500 *ab8500;
145393ff722eSLee Jones 
145493ff722eSLee Jones 	ab8500 = dev_get_drvdata(dev);
145593ff722eSLee Jones 	ret = get_register_interruptible(ab8500, AB8500_SYS_CTRL1_BLOCK,
145693ff722eSLee Jones 		AB8505_TURN_ON_STATUS_2, &value);
145793ff722eSLee Jones 	if (ret < 0)
145893ff722eSLee Jones 		return ret;
145993ff722eSLee Jones 	return sprintf(buf, "%#x\n", (value & 0x1));
146093ff722eSLee Jones }
146193ff722eSLee Jones 
1462d6255529SLinus Walleij static ssize_t show_ab9540_dbbrstn(struct device *dev,
1463d6255529SLinus Walleij 				struct device_attribute *attr, char *buf)
1464d6255529SLinus Walleij {
1465d6255529SLinus Walleij 	struct ab8500 *ab8500;
1466d6255529SLinus Walleij 	int ret;
1467d6255529SLinus Walleij 	u8 value;
1468d6255529SLinus Walleij 
1469d6255529SLinus Walleij 	ab8500 = dev_get_drvdata(dev);
1470d6255529SLinus Walleij 
1471d6255529SLinus Walleij 	ret = get_register_interruptible(ab8500, AB8500_REGU_CTRL2,
1472d6255529SLinus Walleij 		AB9540_MODEM_CTRL2_REG, &value);
1473d6255529SLinus Walleij 	if (ret < 0)
1474d6255529SLinus Walleij 		return ret;
1475d6255529SLinus Walleij 
1476d6255529SLinus Walleij 	return sprintf(buf, "%d\n",
1477d6255529SLinus Walleij 			(value & AB9540_MODEM_CTRL2_SWDBBRSTN_BIT) ? 1 : 0);
1478d6255529SLinus Walleij }
1479d6255529SLinus Walleij 
1480d6255529SLinus Walleij static ssize_t store_ab9540_dbbrstn(struct device *dev,
1481d6255529SLinus Walleij 	struct device_attribute *attr, const char *buf, size_t count)
1482d6255529SLinus Walleij {
1483d6255529SLinus Walleij 	struct ab8500 *ab8500;
1484d6255529SLinus Walleij 	int ret = count;
1485d6255529SLinus Walleij 	int err;
1486d6255529SLinus Walleij 	u8 bitvalues;
1487d6255529SLinus Walleij 
1488d6255529SLinus Walleij 	ab8500 = dev_get_drvdata(dev);
1489d6255529SLinus Walleij 
1490d6255529SLinus Walleij 	if (count > 0) {
1491d6255529SLinus Walleij 		switch (buf[0]) {
1492d6255529SLinus Walleij 		case '0':
1493d6255529SLinus Walleij 			bitvalues = 0;
1494d6255529SLinus Walleij 			break;
1495d6255529SLinus Walleij 		case '1':
1496d6255529SLinus Walleij 			bitvalues = AB9540_MODEM_CTRL2_SWDBBRSTN_BIT;
1497d6255529SLinus Walleij 			break;
1498d6255529SLinus Walleij 		default:
1499d6255529SLinus Walleij 			goto exit;
1500d6255529SLinus Walleij 		}
1501d6255529SLinus Walleij 
1502d6255529SLinus Walleij 		err = mask_and_set_register_interruptible(ab8500,
1503d6255529SLinus Walleij 			AB8500_REGU_CTRL2, AB9540_MODEM_CTRL2_REG,
1504d6255529SLinus Walleij 			AB9540_MODEM_CTRL2_SWDBBRSTN_BIT, bitvalues);
1505d6255529SLinus Walleij 		if (err)
1506d6255529SLinus Walleij 			dev_info(ab8500->dev,
1507d6255529SLinus Walleij 				"Failed to set DBBRSTN %c, err %#x\n",
1508d6255529SLinus Walleij 				buf[0], err);
1509d6255529SLinus Walleij 	}
1510d6255529SLinus Walleij 
1511d6255529SLinus Walleij exit:
1512d6255529SLinus Walleij 	return ret;
1513d6255529SLinus Walleij }
1514d6255529SLinus Walleij 
1515cca69b67SMattias Wallin static DEVICE_ATTR(chip_id, S_IRUGO, show_chip_id, NULL);
1516e5c238c3SMattias Wallin static DEVICE_ATTR(switch_off_status, S_IRUGO, show_switch_off_status, NULL);
1517b4a31037SAndrew Lynn static DEVICE_ATTR(turn_on_status, S_IRUGO, show_turn_on_status, NULL);
151893ff722eSLee Jones static DEVICE_ATTR(turn_on_status_2, S_IRUGO, show_turn_on_status_2, NULL);
1519d6255529SLinus Walleij static DEVICE_ATTR(dbbrstn, S_IRUGO | S_IWUSR,
1520d6255529SLinus Walleij 			show_ab9540_dbbrstn, store_ab9540_dbbrstn);
1521cca69b67SMattias Wallin 
1522cca69b67SMattias Wallin static struct attribute *ab8500_sysfs_entries[] = {
1523cca69b67SMattias Wallin 	&dev_attr_chip_id.attr,
1524e5c238c3SMattias Wallin 	&dev_attr_switch_off_status.attr,
1525b4a31037SAndrew Lynn 	&dev_attr_turn_on_status.attr,
1526cca69b67SMattias Wallin 	NULL,
1527cca69b67SMattias Wallin };
1528cca69b67SMattias Wallin 
152993ff722eSLee Jones static struct attribute *ab8505_sysfs_entries[] = {
153093ff722eSLee Jones 	&dev_attr_turn_on_status_2.attr,
153193ff722eSLee Jones 	NULL,
153293ff722eSLee Jones };
153393ff722eSLee Jones 
1534d6255529SLinus Walleij static struct attribute *ab9540_sysfs_entries[] = {
1535d6255529SLinus Walleij 	&dev_attr_chip_id.attr,
1536d6255529SLinus Walleij 	&dev_attr_switch_off_status.attr,
1537d6255529SLinus Walleij 	&dev_attr_turn_on_status.attr,
1538d6255529SLinus Walleij 	&dev_attr_dbbrstn.attr,
1539d6255529SLinus Walleij 	NULL,
1540d6255529SLinus Walleij };
1541d6255529SLinus Walleij 
1542cca69b67SMattias Wallin static struct attribute_group ab8500_attr_group = {
1543cca69b67SMattias Wallin 	.attrs	= ab8500_sysfs_entries,
1544cca69b67SMattias Wallin };
1545cca69b67SMattias Wallin 
154693ff722eSLee Jones static struct attribute_group ab8505_attr_group = {
154793ff722eSLee Jones 	.attrs	= ab8505_sysfs_entries,
154893ff722eSLee Jones };
154993ff722eSLee Jones 
1550d6255529SLinus Walleij static struct attribute_group ab9540_attr_group = {
1551d6255529SLinus Walleij 	.attrs	= ab9540_sysfs_entries,
1552d6255529SLinus Walleij };
1553d6255529SLinus Walleij 
1554f791be49SBill Pemberton static int ab8500_probe(struct platform_device *pdev)
155562579266SRabin Vincent {
1556*7ccf40b1SLee Jones 	static const char *switch_off_status[] = {
1557b04c530cSJonas Aaberg 		"Swoff bit programming",
1558b04c530cSJonas Aaberg 		"Thermal protection activation",
1559b04c530cSJonas Aaberg 		"Vbat lower then BattOk falling threshold",
1560b04c530cSJonas Aaberg 		"Watchdog expired",
1561b04c530cSJonas Aaberg 		"Non presence of 32kHz clock",
1562b04c530cSJonas Aaberg 		"Battery level lower than power on reset threshold",
1563b04c530cSJonas Aaberg 		"Power on key 1 pressed longer than 10 seconds",
1564b04c530cSJonas Aaberg 		"DB8500 thermal shutdown"};
1565*7ccf40b1SLee Jones 	static const char *turn_on_status[] = {
1566abee26cdSMattias Wallin 		"Battery rising (Vbat)",
1567abee26cdSMattias Wallin 		"Power On Key 1 dbF",
1568abee26cdSMattias Wallin 		"Power On Key 2 dbF",
1569abee26cdSMattias Wallin 		"RTC Alarm",
1570abee26cdSMattias Wallin 		"Main Charger Detect",
1571abee26cdSMattias Wallin 		"Vbus Detect (USB)",
1572abee26cdSMattias Wallin 		"USB ID Detect",
1573abee26cdSMattias Wallin 		"UART Factory Mode Detect"};
1574d28f1db8SLee Jones 	struct ab8500_platform_data *plat = dev_get_platdata(&pdev->dev);
1575d28f1db8SLee Jones 	const struct platform_device_id *platid = platform_get_device_id(pdev);
15766bc4a568SLee Jones 	enum ab8500_version version = AB8500_VERSION_UNDEFINED;
15776bc4a568SLee Jones 	struct device_node *np = pdev->dev.of_node;
1578d28f1db8SLee Jones 	struct ab8500 *ab8500;
1579d28f1db8SLee Jones 	struct resource *resource;
158062579266SRabin Vincent 	int ret;
158162579266SRabin Vincent 	int i;
158247c16975SMattias Wallin 	u8 value;
158362579266SRabin Vincent 
1584*7ccf40b1SLee Jones 	ab8500 = devm_kzalloc(&pdev->dev, sizeof(*ab8500), GFP_KERNEL);
1585d28f1db8SLee Jones 	if (!ab8500)
1586d28f1db8SLee Jones 		return -ENOMEM;
1587d28f1db8SLee Jones 
1588d28f1db8SLee Jones 	ab8500->dev = &pdev->dev;
1589d28f1db8SLee Jones 
1590d28f1db8SLee Jones 	resource = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
1591f864c46aSLinus Walleij 	if (!resource) {
1592f864c46aSLinus Walleij 		dev_err(&pdev->dev, "no IRQ resource\n");
15938c4203cbSLee Jones 		return -ENODEV;
1594f864c46aSLinus Walleij 	}
1595d28f1db8SLee Jones 
1596d28f1db8SLee Jones 	ab8500->irq = resource->start;
1597d28f1db8SLee Jones 
1598822672a7SLee Jones 	ab8500->read = ab8500_prcmu_read;
1599822672a7SLee Jones 	ab8500->write = ab8500_prcmu_write;
1600822672a7SLee Jones 	ab8500->write_masked = ab8500_prcmu_write_masked;
1601d28f1db8SLee Jones 
160262579266SRabin Vincent 	mutex_init(&ab8500->lock);
160362579266SRabin Vincent 	mutex_init(&ab8500->irq_lock);
1604112a80d2SJonas Aaberg 	atomic_set(&ab8500->transfer_ongoing, 0);
160562579266SRabin Vincent 
1606d28f1db8SLee Jones 	platform_set_drvdata(pdev, ab8500);
1607d28f1db8SLee Jones 
16086bc4a568SLee Jones 	if (platid)
16096bc4a568SLee Jones 		version = platid->driver_data;
16106bc4a568SLee Jones 
16110f620837SLinus Walleij 	if (version != AB8500_VERSION_UNDEFINED)
16120f620837SLinus Walleij 		ab8500->version = version;
16130f620837SLinus Walleij 	else {
16140f620837SLinus Walleij 		ret = get_register_interruptible(ab8500, AB8500_MISC,
16150f620837SLinus Walleij 			AB8500_IC_NAME_REG, &value);
1616f864c46aSLinus Walleij 		if (ret < 0) {
1617f864c46aSLinus Walleij 			dev_err(&pdev->dev, "could not probe HW\n");
16188c4203cbSLee Jones 			return ret;
1619f864c46aSLinus Walleij 		}
16200f620837SLinus Walleij 
16210f620837SLinus Walleij 		ab8500->version = value;
16220f620837SLinus Walleij 	}
16230f620837SLinus Walleij 
162447c16975SMattias Wallin 	ret = get_register_interruptible(ab8500, AB8500_MISC,
162547c16975SMattias Wallin 		AB8500_REV_REG, &value);
162662579266SRabin Vincent 	if (ret < 0)
16278c4203cbSLee Jones 		return ret;
162862579266SRabin Vincent 
162947c16975SMattias Wallin 	ab8500->chip_id = value;
163062579266SRabin Vincent 
16310f620837SLinus Walleij 	dev_info(ab8500->dev, "detected chip, %s rev. %1x.%1x\n",
16320f620837SLinus Walleij 			ab8500_version_str[ab8500->version],
16330f620837SLinus Walleij 			ab8500->chip_id >> 4,
16340f620837SLinus Walleij 			ab8500->chip_id & 0x0F);
16350f620837SLinus Walleij 
16363e1a498fSLee Jones 	/* Configure AB8540 */
16373e1a498fSLee Jones 	if (is_ab8540(ab8500)) {
16383e1a498fSLee Jones 		ab8500->mask_size = AB8540_NUM_IRQ_REGS;
16393e1a498fSLee Jones 		ab8500->irq_reg_offset = ab8540_irq_regoffset;
16403e1a498fSLee Jones 		ab8500->it_latchhier_num = AB8540_IT_LATCHHIER_NUM;
16413e1a498fSLee Jones 	} /* Configure AB8500 or AB9540 IRQ */
16423e1a498fSLee Jones 	else if (is_ab9540(ab8500) || is_ab8505(ab8500)) {
1643d6255529SLinus Walleij 		ab8500->mask_size = AB9540_NUM_IRQ_REGS;
1644d6255529SLinus Walleij 		ab8500->irq_reg_offset = ab9540_irq_regoffset;
16453e1a498fSLee Jones 		ab8500->it_latchhier_num = AB8500_IT_LATCHHIER_NUM;
1646d6255529SLinus Walleij 	} else {
16472ced445eSLinus Walleij 		ab8500->mask_size = AB8500_NUM_IRQ_REGS;
16482ced445eSLinus Walleij 		ab8500->irq_reg_offset = ab8500_irq_regoffset;
16493e1a498fSLee Jones 		ab8500->it_latchhier_num = AB8500_IT_LATCHHIER_NUM;
1650d6255529SLinus Walleij 	}
1651*7ccf40b1SLee Jones 	ab8500->mask = devm_kzalloc(&pdev->dev, ab8500->mask_size,
1652*7ccf40b1SLee Jones 				    GFP_KERNEL);
16532ced445eSLinus Walleij 	if (!ab8500->mask)
16542ced445eSLinus Walleij 		return -ENOMEM;
1655*7ccf40b1SLee Jones 	ab8500->oldmask = devm_kzalloc(&pdev->dev, ab8500->mask_size,
1656*7ccf40b1SLee Jones 				       GFP_KERNEL);
16578c4203cbSLee Jones 	if (!ab8500->oldmask)
16588c4203cbSLee Jones 		return -ENOMEM;
16598c4203cbSLee Jones 
1660e5c238c3SMattias Wallin 	/*
1661e5c238c3SMattias Wallin 	 * ab8500 has switched off due to (SWITCH_OFF_STATUS):
1662e5c238c3SMattias Wallin 	 * 0x01 Swoff bit programming
1663e5c238c3SMattias Wallin 	 * 0x02 Thermal protection activation
1664e5c238c3SMattias Wallin 	 * 0x04 Vbat lower then BattOk falling threshold
1665e5c238c3SMattias Wallin 	 * 0x08 Watchdog expired
1666e5c238c3SMattias Wallin 	 * 0x10 Non presence of 32kHz clock
1667e5c238c3SMattias Wallin 	 * 0x20 Battery level lower than power on reset threshold
1668e5c238c3SMattias Wallin 	 * 0x40 Power on key 1 pressed longer than 10 seconds
1669e5c238c3SMattias Wallin 	 * 0x80 DB8500 thermal shutdown
1670e5c238c3SMattias Wallin 	 */
1671e5c238c3SMattias Wallin 
1672e5c238c3SMattias Wallin 	ret = get_register_interruptible(ab8500, AB8500_RTC,
1673e5c238c3SMattias Wallin 		AB8500_SWITCH_OFF_STATUS, &value);
1674e5c238c3SMattias Wallin 	if (ret < 0)
1675e5c238c3SMattias Wallin 		return ret;
1676b04c530cSJonas Aaberg 	dev_info(ab8500->dev, "switch off cause(s) (%#x): ", value);
1677b04c530cSJonas Aaberg 
1678b04c530cSJonas Aaberg 	if (value) {
1679b04c530cSJonas Aaberg 		for (i = 0; i < ARRAY_SIZE(switch_off_status); i++) {
1680b04c530cSJonas Aaberg 			if (value & 1)
1681*7ccf40b1SLee Jones 				pr_cont(" \"%s\"", switch_off_status[i]);
1682b04c530cSJonas Aaberg 			value = value >> 1;
1683b04c530cSJonas Aaberg 
1684b04c530cSJonas Aaberg 		}
1685*7ccf40b1SLee Jones 		pr_cont("\n");
1686b04c530cSJonas Aaberg 	} else {
1687*7ccf40b1SLee Jones 		pr_cont(" None\n");
1688b04c530cSJonas Aaberg 	}
1689abee26cdSMattias Wallin 	ret = get_register_interruptible(ab8500, AB8500_SYS_CTRL1_BLOCK,
1690abee26cdSMattias Wallin 		AB8500_TURN_ON_STATUS, &value);
1691abee26cdSMattias Wallin 	if (ret < 0)
1692abee26cdSMattias Wallin 		return ret;
1693abee26cdSMattias Wallin 	dev_info(ab8500->dev, "turn on reason(s) (%#x): ", value);
1694abee26cdSMattias Wallin 
1695abee26cdSMattias Wallin 	if (value) {
1696abee26cdSMattias Wallin 		for (i = 0; i < ARRAY_SIZE(turn_on_status); i++) {
1697abee26cdSMattias Wallin 			if (value & 1)
1698*7ccf40b1SLee Jones 				pr_cont("\"%s\" ", turn_on_status[i]);
1699abee26cdSMattias Wallin 			value = value >> 1;
1700abee26cdSMattias Wallin 		}
1701*7ccf40b1SLee Jones 		pr_cont("\n");
1702abee26cdSMattias Wallin 	} else {
1703*7ccf40b1SLee Jones 		pr_cont("None\n");
1704abee26cdSMattias Wallin 	}
1705e5c238c3SMattias Wallin 
170662579266SRabin Vincent 	if (plat && plat->init)
170762579266SRabin Vincent 		plat->init(ab8500);
1708abee26cdSMattias Wallin 
1709f04a9d8aSRajkumar Kasirajan 	if (is_ab9540(ab8500)) {
1710f04a9d8aSRajkumar Kasirajan 		ret = get_register_interruptible(ab8500, AB8500_CHARGER,
1711f04a9d8aSRajkumar Kasirajan 			AB8500_CH_USBCH_STAT1_REG, &value);
1712f04a9d8aSRajkumar Kasirajan 		if (ret < 0)
1713f04a9d8aSRajkumar Kasirajan 			return ret;
1714f04a9d8aSRajkumar Kasirajan 		if ((value & VBUS_DET_DBNC1) && (value & VBUS_DET_DBNC100))
1715f04a9d8aSRajkumar Kasirajan 			ab8500_override_turn_on_stat(~AB8500_POW_KEY_1_ON,
1716f04a9d8aSRajkumar Kasirajan 						     AB8500_VBUS_DET);
1717f04a9d8aSRajkumar Kasirajan 	}
171862579266SRabin Vincent 
171962579266SRabin Vincent 	/* Clear and mask all interrupts */
17202ced445eSLinus Walleij 	for (i = 0; i < ab8500->mask_size; i++) {
17210f620837SLinus Walleij 		/*
17220f620837SLinus Walleij 		 * Interrupt register 12 doesn't exist prior to AB8500 version
17230f620837SLinus Walleij 		 * 2.0
17240f620837SLinus Walleij 		 */
17250f620837SLinus Walleij 		if (ab8500->irq_reg_offset[i] == 11 &&
17260f620837SLinus Walleij 				is_ab8500_1p1_or_earlier(ab8500))
172792d50a41SMattias Wallin 			continue;
172862579266SRabin Vincent 
17293e1a498fSLee Jones 		if (ab8500->irq_reg_offset[i] < 0)
17303e1a498fSLee Jones 			continue;
17313e1a498fSLee Jones 
173247c16975SMattias Wallin 		get_register_interruptible(ab8500, AB8500_INTERRUPT,
17332ced445eSLinus Walleij 			AB8500_IT_LATCH1_REG + ab8500->irq_reg_offset[i],
173492d50a41SMattias Wallin 			&value);
173547c16975SMattias Wallin 		set_register_interruptible(ab8500, AB8500_INTERRUPT,
17362ced445eSLinus Walleij 			AB8500_IT_MASK1_REG + ab8500->irq_reg_offset[i], 0xff);
173762579266SRabin Vincent 	}
173862579266SRabin Vincent 
173947c16975SMattias Wallin 	ret = abx500_register_ops(ab8500->dev, &ab8500_ops);
174047c16975SMattias Wallin 	if (ret)
17418c4203cbSLee Jones 		return ret;
174247c16975SMattias Wallin 
17432ced445eSLinus Walleij 	for (i = 0; i < ab8500->mask_size; i++)
174462579266SRabin Vincent 		ab8500->mask[i] = ab8500->oldmask[i] = 0xff;
174562579266SRabin Vincent 
174606e589efSLee Jones 	ret = ab8500_irq_init(ab8500, np);
174762579266SRabin Vincent 	if (ret)
17488c4203cbSLee Jones 		return ret;
174962579266SRabin Vincent 
17508c4203cbSLee Jones 	ret = devm_request_threaded_irq(&pdev->dev, ab8500->irq, NULL,
17517ccfe9b1SMichel JAOUEN 			ab8500_hierarchical_irq,
17527ccfe9b1SMichel JAOUEN 			IRQF_ONESHOT | IRQF_NO_SUSPEND,
17537ccfe9b1SMichel JAOUEN 			"ab8500", ab8500);
175462579266SRabin Vincent 	if (ret)
17558c4203cbSLee Jones 		return ret;
175662579266SRabin Vincent 
17576999181eSLinus Walleij #if CONFIG_DEBUG_FS
17586999181eSLinus Walleij 	/* Pass to debugfs */
17596999181eSLinus Walleij 	ab8500_debug_resources[0].start = ab8500->irq;
17606999181eSLinus Walleij 	ab8500_debug_resources[0].end = ab8500->irq;
17616999181eSLinus Walleij #endif
17626999181eSLinus Walleij 
1763d6255529SLinus Walleij 	if (is_ab9540(ab8500))
1764d6255529SLinus Walleij 		ret = mfd_add_devices(ab8500->dev, 0, ab9540_devs,
1765d6255529SLinus Walleij 				ARRAY_SIZE(ab9540_devs), NULL,
1766f864c46aSLinus Walleij 				0, ab8500->domain);
17679c717cf3SAlexandre Torgue 	else if (is_ab8540(ab8500)) {
1768c0eda9aeSLee Jones 		ret = mfd_add_devices(ab8500->dev, 0, ab8540_devs,
1769c0eda9aeSLee Jones 			      ARRAY_SIZE(ab8540_devs), NULL,
1770f864c46aSLinus Walleij 			      0, ab8500->domain);
17719c717cf3SAlexandre Torgue 		if (ret)
17729c717cf3SAlexandre Torgue 			return ret;
17739c717cf3SAlexandre Torgue 
17749c717cf3SAlexandre Torgue 		if (is_ab8540_1p2_or_earlier(ab8500))
17759c717cf3SAlexandre Torgue 			ret = mfd_add_devices(ab8500->dev, 0, ab8540_cut1_devs,
17769c717cf3SAlexandre Torgue 			      ARRAY_SIZE(ab8540_cut1_devs), NULL,
1777f864c46aSLinus Walleij 			      0, ab8500->domain);
17789c717cf3SAlexandre Torgue 		else /* ab8540 >= cut2 */
17799c717cf3SAlexandre Torgue 			ret = mfd_add_devices(ab8500->dev, 0, ab8540_cut2_devs,
17809c717cf3SAlexandre Torgue 			      ARRAY_SIZE(ab8540_cut2_devs), NULL,
1781f864c46aSLinus Walleij 			      0, ab8500->domain);
17829c717cf3SAlexandre Torgue 	} else if (is_ab8505(ab8500))
1783c0eda9aeSLee Jones 		ret = mfd_add_devices(ab8500->dev, 0, ab8505_devs,
1784c0eda9aeSLee Jones 			      ARRAY_SIZE(ab8505_devs), NULL,
1785f864c46aSLinus Walleij 			      0, ab8500->domain);
1786d6255529SLinus Walleij 	else
1787549931f9SSundar R Iyer 		ret = mfd_add_devices(ab8500->dev, 0, ab8500_devs,
178844f72e53SVirupax Sadashivpetimath 				ARRAY_SIZE(ab8500_devs), NULL,
1789f864c46aSLinus Walleij 				0, ab8500->domain);
17906bc4a568SLee Jones 	if (ret)
17918c4203cbSLee Jones 		return ret;
179244f72e53SVirupax Sadashivpetimath 
17936ef9418cSRickard Andersson 	if (!no_bm) {
17946ef9418cSRickard Andersson 		/* Add battery management devices */
17956ef9418cSRickard Andersson 		ret = mfd_add_devices(ab8500->dev, 0, ab8500_bm_devs,
17966ef9418cSRickard Andersson 				      ARRAY_SIZE(ab8500_bm_devs), NULL,
1797f864c46aSLinus Walleij 				      0, ab8500->domain);
17986ef9418cSRickard Andersson 		if (ret)
17996ef9418cSRickard Andersson 			dev_err(ab8500->dev, "error adding bm devices\n");
18006ef9418cSRickard Andersson 	}
18016ef9418cSRickard Andersson 
1802e436ddffSLee Jones 	if (((is_ab8505(ab8500) || is_ab9540(ab8500)) &&
1803e436ddffSLee Jones 			ab8500->chip_id >= AB8500_CUT2P0) || is_ab8540(ab8500))
1804d6255529SLinus Walleij 		ret = sysfs_create_group(&ab8500->dev->kobj,
1805d6255529SLinus Walleij 					&ab9540_attr_group);
1806d6255529SLinus Walleij 	else
1807d6255529SLinus Walleij 		ret = sysfs_create_group(&ab8500->dev->kobj,
1808d6255529SLinus Walleij 					&ab8500_attr_group);
180993ff722eSLee Jones 
181093ff722eSLee Jones 	if ((is_ab8505(ab8500) || is_ab9540(ab8500)) &&
181193ff722eSLee Jones 			ab8500->chip_id >= AB8500_CUT2P0)
181293ff722eSLee Jones 		ret = sysfs_create_group(&ab8500->dev->kobj,
181393ff722eSLee Jones 					 &ab8505_attr_group);
181493ff722eSLee Jones 
1815cca69b67SMattias Wallin 	if (ret)
1816cca69b67SMattias Wallin 		dev_err(ab8500->dev, "error creating sysfs entries\n");
181706e589efSLee Jones 
181862579266SRabin Vincent 	return ret;
181962579266SRabin Vincent }
182062579266SRabin Vincent 
18214740f73fSBill Pemberton static int ab8500_remove(struct platform_device *pdev)
182262579266SRabin Vincent {
1823d28f1db8SLee Jones 	struct ab8500 *ab8500 = platform_get_drvdata(pdev);
1824d28f1db8SLee Jones 
1825e436ddffSLee Jones 	if (((is_ab8505(ab8500) || is_ab9540(ab8500)) &&
1826e436ddffSLee Jones 			ab8500->chip_id >= AB8500_CUT2P0) || is_ab8540(ab8500))
1827d6255529SLinus Walleij 		sysfs_remove_group(&ab8500->dev->kobj, &ab9540_attr_group);
1828d6255529SLinus Walleij 	else
1829cca69b67SMattias Wallin 		sysfs_remove_group(&ab8500->dev->kobj, &ab8500_attr_group);
183006e589efSLee Jones 
183193ff722eSLee Jones 	if ((is_ab8505(ab8500) || is_ab9540(ab8500)) &&
183293ff722eSLee Jones 			ab8500->chip_id >= AB8500_CUT2P0)
183393ff722eSLee Jones 		sysfs_remove_group(&ab8500->dev->kobj, &ab8505_attr_group);
183493ff722eSLee Jones 
183562579266SRabin Vincent 	mfd_remove_devices(ab8500->dev);
183662579266SRabin Vincent 
183762579266SRabin Vincent 	return 0;
183862579266SRabin Vincent }
183962579266SRabin Vincent 
1840d28f1db8SLee Jones static const struct platform_device_id ab8500_id[] = {
1841d28f1db8SLee Jones 	{ "ab8500-core", AB8500_VERSION_AB8500 },
1842d28f1db8SLee Jones 	{ "ab8505-i2c", AB8500_VERSION_AB8505 },
1843d28f1db8SLee Jones 	{ "ab9540-i2c", AB8500_VERSION_AB9540 },
1844d28f1db8SLee Jones 	{ "ab8540-i2c", AB8500_VERSION_AB8540 },
1845d28f1db8SLee Jones 	{ }
1846d28f1db8SLee Jones };
1847d28f1db8SLee Jones 
1848d28f1db8SLee Jones static struct platform_driver ab8500_core_driver = {
1849d28f1db8SLee Jones 	.driver = {
1850d28f1db8SLee Jones 		.name = "ab8500-core",
1851d28f1db8SLee Jones 		.owner = THIS_MODULE,
1852d28f1db8SLee Jones 	},
1853d28f1db8SLee Jones 	.probe	= ab8500_probe,
185484449216SBill Pemberton 	.remove	= ab8500_remove,
1855d28f1db8SLee Jones 	.id_table = ab8500_id,
1856d28f1db8SLee Jones };
1857d28f1db8SLee Jones 
1858d28f1db8SLee Jones static int __init ab8500_core_init(void)
1859d28f1db8SLee Jones {
1860d28f1db8SLee Jones 	return platform_driver_register(&ab8500_core_driver);
1861d28f1db8SLee Jones }
1862d28f1db8SLee Jones 
1863d28f1db8SLee Jones static void __exit ab8500_core_exit(void)
1864d28f1db8SLee Jones {
1865d28f1db8SLee Jones 	platform_driver_unregister(&ab8500_core_driver);
1866d28f1db8SLee Jones }
1867ba7cbc3eSLee Jones core_initcall(ab8500_core_init);
1868d28f1db8SLee Jones module_exit(ab8500_core_exit);
1869d28f1db8SLee Jones 
1870adceed62SMattias Wallin MODULE_AUTHOR("Mattias Wallin, Srinidhi Kasagar, Rabin Vincent");
187162579266SRabin Vincent MODULE_DESCRIPTION("AB8500 MFD core");
187262579266SRabin Vincent MODULE_LICENSE("GPL v2");
1873