xref: /openbmc/linux/drivers/mfd/ab8500-core.c (revision 93ff722e88530b9719cbf53be4f3197722461394)
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
116*93ff722eSLee 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] = {
1513e1a498fSLee Jones 	0, 1, 2, 3, 4, -1, -1, -1, -1, 11, 18, 19, 20, 21, 12, 13, 24, 5, 22, 23,
1523e1a498fSLee Jones 	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;
4189c677b9bSLee Jones 		else if (offset >= AB9540_INT_GPIO50R && offset <= AB9540_INT_GPIO54R)
4199c677b9bSLee Jones 			ab8500->mask[index + 1] &= ~mask;
4209c677b9bSLee Jones 		else if (offset == AB8540_INT_GPIO43R || offset == AB8540_INT_GPIO44R)
421e2ddf46aSLinus Walleij 			/* Here the falling IRQ is one bit lower */
422e2ddf46aSLinus Walleij 			ab8500->mask[index] &= ~(mask << 1);
4239c677b9bSLee Jones 		else
4249c677b9bSLee Jones 			ab8500->mask[index] &= ~mask;
425e2ddf46aSLinus Walleij 	} else {
4269c677b9bSLee Jones 		/* Satisfies the case where type is not set. */
42762579266SRabin Vincent 		ab8500->mask[index] &= ~mask;
42862579266SRabin Vincent 	}
429e2ddf46aSLinus Walleij }
43062579266SRabin Vincent 
43140f6e5a2SLee Jones static int ab8500_irq_set_type(struct irq_data *data, unsigned int type)
43240f6e5a2SLee Jones {
43340f6e5a2SLee Jones 	return 0;
43462579266SRabin Vincent }
43562579266SRabin Vincent 
43662579266SRabin Vincent static struct irq_chip ab8500_irq_chip = {
43762579266SRabin Vincent 	.name			= "ab8500",
4389505a0a0SMark Brown 	.irq_bus_lock		= ab8500_irq_lock,
4399505a0a0SMark Brown 	.irq_bus_sync_unlock	= ab8500_irq_sync_unlock,
4409505a0a0SMark Brown 	.irq_mask		= ab8500_irq_mask,
441e6f9306eSVirupax Sadashivpetimath 	.irq_disable		= ab8500_irq_mask,
4429505a0a0SMark Brown 	.irq_unmask		= ab8500_irq_unmask,
44340f6e5a2SLee Jones 	.irq_set_type		= ab8500_irq_set_type,
44462579266SRabin Vincent };
44562579266SRabin Vincent 
4463e1a498fSLee Jones static void update_latch_offset(u8 *offset, int i)
4473e1a498fSLee Jones {
4483e1a498fSLee Jones 	/* Fix inconsistent ITFromLatch25 bit mapping... */
4493e1a498fSLee Jones 	if (unlikely(*offset == 17))
4503e1a498fSLee Jones 			*offset = 24;
4513e1a498fSLee Jones 	/* Fix inconsistent ab8540 bit mapping... */
4523e1a498fSLee Jones 	if (unlikely(*offset == 16))
4533e1a498fSLee Jones 			*offset = 25;
4543e1a498fSLee Jones 	if ((i==3) && (*offset >= 24))
4553e1a498fSLee Jones 			*offset += 2;
4563e1a498fSLee Jones }
4573e1a498fSLee Jones 
4587ccfe9b1SMichel JAOUEN static int ab8500_handle_hierarchical_line(struct ab8500 *ab8500,
4597ccfe9b1SMichel JAOUEN 					int latch_offset, u8 latch_val)
4607ccfe9b1SMichel JAOUEN {
4617ccfe9b1SMichel JAOUEN 	int int_bit = __ffs(latch_val);
4627ccfe9b1SMichel JAOUEN 	int line, i;
4637ccfe9b1SMichel JAOUEN 
4647ccfe9b1SMichel JAOUEN 	do {
4657ccfe9b1SMichel JAOUEN 		int_bit = __ffs(latch_val);
4667ccfe9b1SMichel JAOUEN 
4677ccfe9b1SMichel JAOUEN 		for (i = 0; i < ab8500->mask_size; i++)
4687ccfe9b1SMichel JAOUEN 			if (ab8500->irq_reg_offset[i] == latch_offset)
4697ccfe9b1SMichel JAOUEN 				break;
4707ccfe9b1SMichel JAOUEN 
4717ccfe9b1SMichel JAOUEN 		if (i >= ab8500->mask_size) {
4727ccfe9b1SMichel JAOUEN 			dev_err(ab8500->dev, "Register offset 0x%2x not declared\n",
4737ccfe9b1SMichel JAOUEN 					latch_offset);
4747ccfe9b1SMichel JAOUEN 			return -ENXIO;
4757ccfe9b1SMichel JAOUEN 		}
4767ccfe9b1SMichel JAOUEN 
4777ccfe9b1SMichel JAOUEN 		line = (i << 3) + int_bit;
4787ccfe9b1SMichel JAOUEN 		latch_val &= ~(1 << int_bit);
4797ccfe9b1SMichel JAOUEN 
480e2ddf46aSLinus Walleij 		/*
481e2ddf46aSLinus Walleij 		 * This handles the falling edge hwirqs from the GPIO
482e2ddf46aSLinus Walleij 		 * lines. Route them back to the line registered for the
483e2ddf46aSLinus Walleij 		 * rising IRQ, as this is merely a flag for the same IRQ
484e2ddf46aSLinus Walleij 		 * in linux terms.
485e2ddf46aSLinus Walleij 		 */
486e2ddf46aSLinus Walleij 		if (line >= AB8500_INT_GPIO6F && line <= AB8500_INT_GPIO41F)
487e2ddf46aSLinus Walleij 			line -= 16;
488e2ddf46aSLinus Walleij 		if (line >= AB9540_INT_GPIO50F && line <= AB9540_INT_GPIO54F)
489e2ddf46aSLinus Walleij 			line -= 8;
490e2ddf46aSLinus Walleij 		if (line == AB8540_INT_GPIO43F || line == AB8540_INT_GPIO44F)
491e2ddf46aSLinus Walleij 			line += 1;
492e2ddf46aSLinus Walleij 
4937ccfe9b1SMichel JAOUEN 		handle_nested_irq(ab8500->irq_base + line);
4947ccfe9b1SMichel JAOUEN 	} while (latch_val);
4957ccfe9b1SMichel JAOUEN 
4967ccfe9b1SMichel JAOUEN 	return 0;
4977ccfe9b1SMichel JAOUEN }
4987ccfe9b1SMichel JAOUEN 
4997ccfe9b1SMichel JAOUEN static int ab8500_handle_hierarchical_latch(struct ab8500 *ab8500,
5007ccfe9b1SMichel JAOUEN 					int hier_offset, u8 hier_val)
5017ccfe9b1SMichel JAOUEN {
5027ccfe9b1SMichel JAOUEN 	int latch_bit, status;
5037ccfe9b1SMichel JAOUEN 	u8 latch_offset, latch_val;
5047ccfe9b1SMichel JAOUEN 
5057ccfe9b1SMichel JAOUEN 	do {
5067ccfe9b1SMichel JAOUEN 		latch_bit = __ffs(hier_val);
5077ccfe9b1SMichel JAOUEN 		latch_offset = (hier_offset << 3) + latch_bit;
5087ccfe9b1SMichel JAOUEN 
5093e1a498fSLee Jones 		update_latch_offset(&latch_offset, hier_offset);
5107ccfe9b1SMichel JAOUEN 
5117ccfe9b1SMichel JAOUEN 		status = get_register_interruptible(ab8500,
5127ccfe9b1SMichel JAOUEN 				AB8500_INTERRUPT,
5137ccfe9b1SMichel JAOUEN 				AB8500_IT_LATCH1_REG + latch_offset,
5147ccfe9b1SMichel JAOUEN 				&latch_val);
5157ccfe9b1SMichel JAOUEN 		if (status < 0 || latch_val == 0)
5167ccfe9b1SMichel JAOUEN 			goto discard;
5177ccfe9b1SMichel JAOUEN 
5187ccfe9b1SMichel JAOUEN 		status = ab8500_handle_hierarchical_line(ab8500,
5197ccfe9b1SMichel JAOUEN 				latch_offset, latch_val);
5207ccfe9b1SMichel JAOUEN 		if (status < 0)
5217ccfe9b1SMichel JAOUEN 			return status;
5227ccfe9b1SMichel JAOUEN discard:
5237ccfe9b1SMichel JAOUEN 		hier_val &= ~(1 << latch_bit);
5247ccfe9b1SMichel JAOUEN 	} while (hier_val);
5257ccfe9b1SMichel JAOUEN 
5267ccfe9b1SMichel JAOUEN 	return 0;
5277ccfe9b1SMichel JAOUEN }
5287ccfe9b1SMichel JAOUEN 
5297ccfe9b1SMichel JAOUEN static irqreturn_t ab8500_hierarchical_irq(int irq, void *dev)
5307ccfe9b1SMichel JAOUEN {
5317ccfe9b1SMichel JAOUEN 	struct ab8500 *ab8500 = dev;
5327ccfe9b1SMichel JAOUEN 	u8 i;
5337ccfe9b1SMichel JAOUEN 
5347ccfe9b1SMichel JAOUEN 	dev_vdbg(ab8500->dev, "interrupt\n");
5357ccfe9b1SMichel JAOUEN 
5367ccfe9b1SMichel JAOUEN 	/*  Hierarchical interrupt version */
5373e1a498fSLee Jones 	for (i = 0; i < (ab8500->it_latchhier_num); i++) {
5387ccfe9b1SMichel JAOUEN 		int status;
5397ccfe9b1SMichel JAOUEN 		u8 hier_val;
5407ccfe9b1SMichel JAOUEN 
5417ccfe9b1SMichel JAOUEN 		status = get_register_interruptible(ab8500, AB8500_INTERRUPT,
5427ccfe9b1SMichel JAOUEN 			AB8500_IT_LATCHHIER1_REG + i, &hier_val);
5437ccfe9b1SMichel JAOUEN 		if (status < 0 || hier_val == 0)
5447ccfe9b1SMichel JAOUEN 			continue;
5457ccfe9b1SMichel JAOUEN 
5467ccfe9b1SMichel JAOUEN 		status = ab8500_handle_hierarchical_latch(ab8500, i, hier_val);
5477ccfe9b1SMichel JAOUEN 		if (status < 0)
5487ccfe9b1SMichel JAOUEN 			break;
5497ccfe9b1SMichel JAOUEN 	}
5507ccfe9b1SMichel JAOUEN 	return IRQ_HANDLED;
5517ccfe9b1SMichel JAOUEN }
5527ccfe9b1SMichel JAOUEN 
55306e589efSLee Jones static int ab8500_irq_map(struct irq_domain *d, unsigned int virq,
55406e589efSLee Jones 				irq_hw_number_t hwirq)
55506e589efSLee Jones {
55606e589efSLee Jones 	struct ab8500 *ab8500 = d->host_data;
55706e589efSLee Jones 
55806e589efSLee Jones 	if (!ab8500)
55906e589efSLee Jones 		return -EINVAL;
56006e589efSLee Jones 
56106e589efSLee Jones 	irq_set_chip_data(virq, ab8500);
56206e589efSLee Jones 	irq_set_chip_and_handler(virq, &ab8500_irq_chip,
56306e589efSLee Jones 				handle_simple_irq);
56406e589efSLee Jones 	irq_set_nested_thread(virq, 1);
56506e589efSLee Jones #ifdef CONFIG_ARM
56606e589efSLee Jones 	set_irq_flags(virq, IRQF_VALID);
56706e589efSLee Jones #else
56806e589efSLee Jones 	irq_set_noprobe(virq);
56906e589efSLee Jones #endif
57062579266SRabin Vincent 
57162579266SRabin Vincent 	return 0;
57262579266SRabin Vincent }
57362579266SRabin Vincent 
57406e589efSLee Jones static struct irq_domain_ops ab8500_irq_ops = {
57506e589efSLee Jones         .map    = ab8500_irq_map,
57606e589efSLee Jones         .xlate  = irq_domain_xlate_twocell,
57706e589efSLee Jones };
57806e589efSLee Jones 
57906e589efSLee Jones static int ab8500_irq_init(struct ab8500 *ab8500, struct device_node *np)
58062579266SRabin Vincent {
5812ced445eSLinus Walleij 	int num_irqs;
58262579266SRabin Vincent 
5833e1a498fSLee Jones 	if (is_ab8540(ab8500))
5843e1a498fSLee Jones 		num_irqs = AB8540_NR_IRQS;
5853e1a498fSLee Jones 	else if (is_ab9540(ab8500))
586d6255529SLinus Walleij 		num_irqs = AB9540_NR_IRQS;
587a982362cSBengt Jonsson 	else if (is_ab8505(ab8500))
588a982362cSBengt Jonsson 		num_irqs = AB8505_NR_IRQS;
589d6255529SLinus Walleij 	else
5902ced445eSLinus Walleij 		num_irqs = AB8500_NR_IRQS;
5912ced445eSLinus Walleij 
592f1d11f39SLinus Walleij 	/* If ->irq_base is zero this will give a linear mapping */
593f1d11f39SLinus Walleij 	ab8500->domain = irq_domain_add_simple(NULL,
594f1d11f39SLinus Walleij 			num_irqs, ab8500->irq_base,
595f1d11f39SLinus Walleij 			&ab8500_irq_ops, ab8500);
59606e589efSLee Jones 
59706e589efSLee Jones 	if (!ab8500->domain) {
59806e589efSLee Jones 		dev_err(ab8500->dev, "Failed to create irqdomain\n");
59906e589efSLee Jones 		return -ENOSYS;
60006e589efSLee Jones 	}
60106e589efSLee Jones 
60206e589efSLee Jones 	return 0;
60362579266SRabin Vincent }
60462579266SRabin Vincent 
605112a80d2SJonas Aaberg int ab8500_suspend(struct ab8500 *ab8500)
606112a80d2SJonas Aaberg {
607112a80d2SJonas Aaberg 	if (atomic_read(&ab8500->transfer_ongoing))
608112a80d2SJonas Aaberg 		return -EINVAL;
609112a80d2SJonas Aaberg 	else
610112a80d2SJonas Aaberg 		return 0;
611112a80d2SJonas Aaberg }
612112a80d2SJonas Aaberg 
613a9e9ce4cSBill Pemberton static struct resource ab8500_gpadc_resources[] = {
61462579266SRabin Vincent 	{
61562579266SRabin Vincent 		.name	= "HW_CONV_END",
61662579266SRabin Vincent 		.start	= AB8500_INT_GP_HW_ADC_CONV_END,
61762579266SRabin Vincent 		.end	= AB8500_INT_GP_HW_ADC_CONV_END,
61862579266SRabin Vincent 		.flags	= IORESOURCE_IRQ,
61962579266SRabin Vincent 	},
62062579266SRabin Vincent 	{
62162579266SRabin Vincent 		.name	= "SW_CONV_END",
62262579266SRabin Vincent 		.start	= AB8500_INT_GP_SW_ADC_CONV_END,
62362579266SRabin Vincent 		.end	= AB8500_INT_GP_SW_ADC_CONV_END,
62462579266SRabin Vincent 		.flags	= IORESOURCE_IRQ,
62562579266SRabin Vincent 	},
62662579266SRabin Vincent };
62762579266SRabin Vincent 
6284b106fb9SLee Jones static struct resource ab8505_gpadc_resources[] = {
629c0eda9aeSLee Jones 	{
630c0eda9aeSLee Jones 		.name	= "SW_CONV_END",
631c0eda9aeSLee Jones 		.start	= AB8500_INT_GP_SW_ADC_CONV_END,
632c0eda9aeSLee Jones 		.end	= AB8500_INT_GP_SW_ADC_CONV_END,
633c0eda9aeSLee Jones 		.flags	= IORESOURCE_IRQ,
634c0eda9aeSLee Jones 	},
635c0eda9aeSLee Jones };
636c0eda9aeSLee Jones 
637a9e9ce4cSBill Pemberton static struct resource ab8500_rtc_resources[] = {
63862579266SRabin Vincent 	{
63962579266SRabin Vincent 		.name	= "60S",
64062579266SRabin Vincent 		.start	= AB8500_INT_RTC_60S,
64162579266SRabin Vincent 		.end	= AB8500_INT_RTC_60S,
64262579266SRabin Vincent 		.flags	= IORESOURCE_IRQ,
64362579266SRabin Vincent 	},
64462579266SRabin Vincent 	{
64562579266SRabin Vincent 		.name	= "ALARM",
64662579266SRabin Vincent 		.start	= AB8500_INT_RTC_ALARM,
64762579266SRabin Vincent 		.end	= AB8500_INT_RTC_ALARM,
64862579266SRabin Vincent 		.flags	= IORESOURCE_IRQ,
64962579266SRabin Vincent 	},
65062579266SRabin Vincent };
65162579266SRabin Vincent 
652a9e9ce4cSBill Pemberton static struct resource ab8500_poweronkey_db_resources[] = {
65377686517SSundar R Iyer 	{
65477686517SSundar R Iyer 		.name	= "ONKEY_DBF",
65577686517SSundar R Iyer 		.start	= AB8500_INT_PON_KEY1DB_F,
65677686517SSundar R Iyer 		.end	= AB8500_INT_PON_KEY1DB_F,
65777686517SSundar R Iyer 		.flags	= IORESOURCE_IRQ,
65877686517SSundar R Iyer 	},
65977686517SSundar R Iyer 	{
66077686517SSundar R Iyer 		.name	= "ONKEY_DBR",
66177686517SSundar R Iyer 		.start	= AB8500_INT_PON_KEY1DB_R,
66277686517SSundar R Iyer 		.end	= AB8500_INT_PON_KEY1DB_R,
66377686517SSundar R Iyer 		.flags	= IORESOURCE_IRQ,
66477686517SSundar R Iyer 	},
66577686517SSundar R Iyer };
66677686517SSundar R Iyer 
667a9e9ce4cSBill Pemberton static struct resource ab8500_av_acc_detect_resources[] = {
668e098adedSMattias Wallin 	{
6696af75ecdSLinus Walleij 	       .name = "ACC_DETECT_1DB_F",
6706af75ecdSLinus Walleij 	       .start = AB8500_INT_ACC_DETECT_1DB_F,
6716af75ecdSLinus Walleij 	       .end = AB8500_INT_ACC_DETECT_1DB_F,
672e098adedSMattias Wallin 	       .flags = IORESOURCE_IRQ,
673e098adedSMattias Wallin 	},
674e098adedSMattias Wallin 	{
6756af75ecdSLinus Walleij 	       .name = "ACC_DETECT_1DB_R",
6766af75ecdSLinus Walleij 	       .start = AB8500_INT_ACC_DETECT_1DB_R,
6776af75ecdSLinus Walleij 	       .end = AB8500_INT_ACC_DETECT_1DB_R,
678e098adedSMattias Wallin 	       .flags = IORESOURCE_IRQ,
679e098adedSMattias Wallin 	},
680e098adedSMattias Wallin 	{
6816af75ecdSLinus Walleij 	       .name = "ACC_DETECT_21DB_F",
6826af75ecdSLinus Walleij 	       .start = AB8500_INT_ACC_DETECT_21DB_F,
6836af75ecdSLinus Walleij 	       .end = AB8500_INT_ACC_DETECT_21DB_F,
6846af75ecdSLinus Walleij 	       .flags = IORESOURCE_IRQ,
6856af75ecdSLinus Walleij 	},
6866af75ecdSLinus Walleij 	{
6876af75ecdSLinus Walleij 	       .name = "ACC_DETECT_21DB_R",
6886af75ecdSLinus Walleij 	       .start = AB8500_INT_ACC_DETECT_21DB_R,
6896af75ecdSLinus Walleij 	       .end = AB8500_INT_ACC_DETECT_21DB_R,
6906af75ecdSLinus Walleij 	       .flags = IORESOURCE_IRQ,
6916af75ecdSLinus Walleij 	},
6926af75ecdSLinus Walleij 	{
6936af75ecdSLinus Walleij 	       .name = "ACC_DETECT_22DB_F",
6946af75ecdSLinus Walleij 	       .start = AB8500_INT_ACC_DETECT_22DB_F,
6956af75ecdSLinus Walleij 	       .end = AB8500_INT_ACC_DETECT_22DB_F,
6966af75ecdSLinus Walleij 	       .flags = IORESOURCE_IRQ,
6976af75ecdSLinus Walleij 	},
6986af75ecdSLinus Walleij 	{
6996af75ecdSLinus Walleij 	       .name = "ACC_DETECT_22DB_R",
7006af75ecdSLinus Walleij 	       .start = AB8500_INT_ACC_DETECT_22DB_R,
7016af75ecdSLinus Walleij 	       .end = AB8500_INT_ACC_DETECT_22DB_R,
7026af75ecdSLinus Walleij 	       .flags = IORESOURCE_IRQ,
7036af75ecdSLinus Walleij 	},
7046af75ecdSLinus Walleij };
7056af75ecdSLinus Walleij 
706a9e9ce4cSBill Pemberton static struct resource ab8500_charger_resources[] = {
7076af75ecdSLinus Walleij 	{
708e098adedSMattias Wallin 		.name = "MAIN_CH_UNPLUG_DET",
709e098adedSMattias Wallin 		.start = AB8500_INT_MAIN_CH_UNPLUG_DET,
710e098adedSMattias Wallin 		.end = AB8500_INT_MAIN_CH_UNPLUG_DET,
711e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
712e098adedSMattias Wallin 	},
713e098adedSMattias Wallin 	{
714e098adedSMattias Wallin 		.name = "MAIN_CHARGE_PLUG_DET",
715e098adedSMattias Wallin 		.start = AB8500_INT_MAIN_CH_PLUG_DET,
716e098adedSMattias Wallin 		.end = AB8500_INT_MAIN_CH_PLUG_DET,
717e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
718e098adedSMattias Wallin 	},
719e098adedSMattias Wallin 	{
720e098adedSMattias Wallin 		.name = "VBUS_DET_R",
721e098adedSMattias Wallin 		.start = AB8500_INT_VBUS_DET_R,
722e098adedSMattias Wallin 		.end = AB8500_INT_VBUS_DET_R,
723e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
724e098adedSMattias Wallin 	},
725e098adedSMattias Wallin 	{
7266af75ecdSLinus Walleij 		.name = "VBUS_DET_F",
7276af75ecdSLinus Walleij 		.start = AB8500_INT_VBUS_DET_F,
7286af75ecdSLinus Walleij 		.end = AB8500_INT_VBUS_DET_F,
729e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
730e098adedSMattias Wallin 	},
731e098adedSMattias Wallin 	{
7326af75ecdSLinus Walleij 		.name = "USB_LINK_STATUS",
7336af75ecdSLinus Walleij 		.start = AB8500_INT_USB_LINK_STATUS,
7346af75ecdSLinus Walleij 		.end = AB8500_INT_USB_LINK_STATUS,
7356af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
7366af75ecdSLinus Walleij 	},
7376af75ecdSLinus Walleij 	{
738e098adedSMattias Wallin 		.name = "VBUS_OVV",
739e098adedSMattias Wallin 		.start = AB8500_INT_VBUS_OVV,
740e098adedSMattias Wallin 		.end = AB8500_INT_VBUS_OVV,
741e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
742e098adedSMattias Wallin 	},
743e098adedSMattias Wallin 	{
7446af75ecdSLinus Walleij 		.name = "USB_CH_TH_PROT_R",
7456af75ecdSLinus Walleij 		.start = AB8500_INT_USB_CH_TH_PROT_R,
7466af75ecdSLinus Walleij 		.end = AB8500_INT_USB_CH_TH_PROT_R,
747e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
748e098adedSMattias Wallin 	},
749e098adedSMattias Wallin 	{
7506af75ecdSLinus Walleij 		.name = "USB_CH_TH_PROT_F",
7516af75ecdSLinus Walleij 		.start = AB8500_INT_USB_CH_TH_PROT_F,
7526af75ecdSLinus Walleij 		.end = AB8500_INT_USB_CH_TH_PROT_F,
753e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
754e098adedSMattias Wallin 	},
755e098adedSMattias Wallin 	{
7566af75ecdSLinus Walleij 		.name = "MAIN_EXT_CH_NOT_OK",
7576af75ecdSLinus Walleij 		.start = AB8500_INT_MAIN_EXT_CH_NOT_OK,
7586af75ecdSLinus Walleij 		.end = AB8500_INT_MAIN_EXT_CH_NOT_OK,
7596af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
7606af75ecdSLinus Walleij 	},
7616af75ecdSLinus Walleij 	{
7626af75ecdSLinus Walleij 		.name = "MAIN_CH_TH_PROT_R",
7636af75ecdSLinus Walleij 		.start = AB8500_INT_MAIN_CH_TH_PROT_R,
7646af75ecdSLinus Walleij 		.end = AB8500_INT_MAIN_CH_TH_PROT_R,
7656af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
7666af75ecdSLinus Walleij 	},
7676af75ecdSLinus Walleij 	{
7686af75ecdSLinus Walleij 		.name = "MAIN_CH_TH_PROT_F",
7696af75ecdSLinus Walleij 		.start = AB8500_INT_MAIN_CH_TH_PROT_F,
7706af75ecdSLinus Walleij 		.end = AB8500_INT_MAIN_CH_TH_PROT_F,
7716af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
7726af75ecdSLinus Walleij 	},
7736af75ecdSLinus Walleij 	{
7746af75ecdSLinus Walleij 		.name = "USB_CHARGER_NOT_OKR",
775a982362cSBengt Jonsson 		.start = AB8500_INT_USB_CHARGER_NOT_OKR,
776a982362cSBengt Jonsson 		.end = AB8500_INT_USB_CHARGER_NOT_OKR,
7776af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
7786af75ecdSLinus Walleij 	},
7796af75ecdSLinus Walleij 	{
7806af75ecdSLinus Walleij 		.name = "CH_WD_EXP",
7816af75ecdSLinus Walleij 		.start = AB8500_INT_CH_WD_EXP,
7826af75ecdSLinus Walleij 		.end = AB8500_INT_CH_WD_EXP,
7836af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
7846af75ecdSLinus Walleij 	},
78534c11a70SPaer-Olof Haakansson 	{
78634c11a70SPaer-Olof Haakansson 		.name = "VBUS_CH_DROP_END",
78734c11a70SPaer-Olof Haakansson 		.start = AB8500_INT_VBUS_CH_DROP_END,
78834c11a70SPaer-Olof Haakansson 		.end = AB8500_INT_VBUS_CH_DROP_END,
78934c11a70SPaer-Olof Haakansson 		.flags = IORESOURCE_IRQ,
79034c11a70SPaer-Olof Haakansson 	},
7916af75ecdSLinus Walleij };
7926af75ecdSLinus Walleij 
793a9e9ce4cSBill Pemberton static struct resource ab8500_btemp_resources[] = {
7946af75ecdSLinus Walleij 	{
7956af75ecdSLinus Walleij 		.name = "BAT_CTRL_INDB",
7966af75ecdSLinus Walleij 		.start = AB8500_INT_BAT_CTRL_INDB,
7976af75ecdSLinus Walleij 		.end = AB8500_INT_BAT_CTRL_INDB,
798e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
799e098adedSMattias Wallin 	},
800e098adedSMattias Wallin 	{
801e098adedSMattias Wallin 		.name = "BTEMP_LOW",
802e098adedSMattias Wallin 		.start = AB8500_INT_BTEMP_LOW,
803e098adedSMattias Wallin 		.end = AB8500_INT_BTEMP_LOW,
804e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
805e098adedSMattias Wallin 	},
806e098adedSMattias Wallin 	{
807e098adedSMattias Wallin 		.name = "BTEMP_HIGH",
808e098adedSMattias Wallin 		.start = AB8500_INT_BTEMP_HIGH,
809e098adedSMattias Wallin 		.end = AB8500_INT_BTEMP_HIGH,
810e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
811e098adedSMattias Wallin 	},
812e098adedSMattias Wallin 	{
8136af75ecdSLinus Walleij 		.name = "BTEMP_LOW_MEDIUM",
8146af75ecdSLinus Walleij 		.start = AB8500_INT_BTEMP_LOW_MEDIUM,
8156af75ecdSLinus Walleij 		.end = AB8500_INT_BTEMP_LOW_MEDIUM,
816e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
817e098adedSMattias Wallin 	},
818e098adedSMattias Wallin 	{
8196af75ecdSLinus Walleij 		.name = "BTEMP_MEDIUM_HIGH",
8206af75ecdSLinus Walleij 		.start = AB8500_INT_BTEMP_MEDIUM_HIGH,
8216af75ecdSLinus Walleij 		.end = AB8500_INT_BTEMP_MEDIUM_HIGH,
822e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
823e098adedSMattias Wallin 	},
824e098adedSMattias Wallin };
825e098adedSMattias Wallin 
826a9e9ce4cSBill Pemberton static struct resource ab8500_fg_resources[] = {
8276af75ecdSLinus Walleij 	{
8286af75ecdSLinus Walleij 		.name = "NCONV_ACCU",
8296af75ecdSLinus Walleij 		.start = AB8500_INT_CCN_CONV_ACC,
8306af75ecdSLinus Walleij 		.end = AB8500_INT_CCN_CONV_ACC,
8316af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
8326af75ecdSLinus Walleij 	},
8336af75ecdSLinus Walleij 	{
8346af75ecdSLinus Walleij 		.name = "BATT_OVV",
8356af75ecdSLinus Walleij 		.start = AB8500_INT_BATT_OVV,
8366af75ecdSLinus Walleij 		.end = AB8500_INT_BATT_OVV,
8376af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
8386af75ecdSLinus Walleij 	},
8396af75ecdSLinus Walleij 	{
8406af75ecdSLinus Walleij 		.name = "LOW_BAT_F",
8416af75ecdSLinus Walleij 		.start = AB8500_INT_LOW_BAT_F,
8426af75ecdSLinus Walleij 		.end = AB8500_INT_LOW_BAT_F,
8436af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
8446af75ecdSLinus Walleij 	},
8456af75ecdSLinus Walleij 	{
8466af75ecdSLinus Walleij 		.name = "LOW_BAT_R",
8476af75ecdSLinus Walleij 		.start = AB8500_INT_LOW_BAT_R,
8486af75ecdSLinus Walleij 		.end = AB8500_INT_LOW_BAT_R,
8496af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
8506af75ecdSLinus Walleij 	},
8516af75ecdSLinus Walleij 	{
8526af75ecdSLinus Walleij 		.name = "CC_INT_CALIB",
8536af75ecdSLinus Walleij 		.start = AB8500_INT_CC_INT_CALIB,
8546af75ecdSLinus Walleij 		.end = AB8500_INT_CC_INT_CALIB,
8556af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
8566af75ecdSLinus Walleij 	},
857a982362cSBengt Jonsson 	{
858a982362cSBengt Jonsson 		.name = "CCEOC",
859a982362cSBengt Jonsson 		.start = AB8500_INT_CCEOC,
860a982362cSBengt Jonsson 		.end = AB8500_INT_CCEOC,
861a982362cSBengt Jonsson 		.flags = IORESOURCE_IRQ,
862a982362cSBengt Jonsson 	},
8636af75ecdSLinus Walleij };
8646af75ecdSLinus Walleij 
865a9e9ce4cSBill Pemberton static struct resource ab8500_chargalg_resources[] = {};
8666af75ecdSLinus Walleij 
867df720647SAxel Lin #ifdef CONFIG_DEBUG_FS
868a9e9ce4cSBill Pemberton static struct resource ab8500_debug_resources[] = {
869e098adedSMattias Wallin 	{
870e098adedSMattias Wallin 		.name	= "IRQ_FIRST",
871e098adedSMattias Wallin 		.start	= AB8500_INT_MAIN_EXT_CH_NOT_OK,
872e098adedSMattias Wallin 		.end	= AB8500_INT_MAIN_EXT_CH_NOT_OK,
873e098adedSMattias Wallin 		.flags	= IORESOURCE_IRQ,
874e098adedSMattias Wallin 	},
875e098adedSMattias Wallin 	{
876e098adedSMattias Wallin 		.name	= "IRQ_LAST",
877a982362cSBengt Jonsson 		.start	= AB8500_INT_XTAL32K_KO,
878a982362cSBengt Jonsson 		.end	= AB8500_INT_XTAL32K_KO,
879e098adedSMattias Wallin 		.flags	= IORESOURCE_IRQ,
880e098adedSMattias Wallin 	},
881e098adedSMattias Wallin };
882df720647SAxel Lin #endif
883e098adedSMattias Wallin 
884a9e9ce4cSBill Pemberton static struct resource ab8500_usb_resources[] = {
885e098adedSMattias Wallin 	{
886e098adedSMattias Wallin 		.name = "ID_WAKEUP_R",
887e098adedSMattias Wallin 		.start = AB8500_INT_ID_WAKEUP_R,
888e098adedSMattias Wallin 		.end = AB8500_INT_ID_WAKEUP_R,
889e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
890e098adedSMattias Wallin 	},
891e098adedSMattias Wallin 	{
892e098adedSMattias Wallin 		.name = "ID_WAKEUP_F",
893e098adedSMattias Wallin 		.start = AB8500_INT_ID_WAKEUP_F,
894e098adedSMattias Wallin 		.end = AB8500_INT_ID_WAKEUP_F,
895e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
896e098adedSMattias Wallin 	},
897e098adedSMattias Wallin 	{
898e098adedSMattias Wallin 		.name = "VBUS_DET_F",
899e098adedSMattias Wallin 		.start = AB8500_INT_VBUS_DET_F,
900e098adedSMattias Wallin 		.end = AB8500_INT_VBUS_DET_F,
901e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
902e098adedSMattias Wallin 	},
903e098adedSMattias Wallin 	{
904e098adedSMattias Wallin 		.name = "VBUS_DET_R",
905e098adedSMattias Wallin 		.start = AB8500_INT_VBUS_DET_R,
906e098adedSMattias Wallin 		.end = AB8500_INT_VBUS_DET_R,
907e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
908e098adedSMattias Wallin 	},
90992d50a41SMattias Wallin 	{
91092d50a41SMattias Wallin 		.name = "USB_LINK_STATUS",
91192d50a41SMattias Wallin 		.start = AB8500_INT_USB_LINK_STATUS,
91292d50a41SMattias Wallin 		.end = AB8500_INT_USB_LINK_STATUS,
91392d50a41SMattias Wallin 		.flags = IORESOURCE_IRQ,
91492d50a41SMattias Wallin 	},
9156af75ecdSLinus Walleij 	{
9166af75ecdSLinus Walleij 		.name = "USB_ADP_PROBE_PLUG",
9176af75ecdSLinus Walleij 		.start = AB8500_INT_ADP_PROBE_PLUG,
9186af75ecdSLinus Walleij 		.end = AB8500_INT_ADP_PROBE_PLUG,
9196af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
9206af75ecdSLinus Walleij 	},
9216af75ecdSLinus Walleij 	{
9226af75ecdSLinus Walleij 		.name = "USB_ADP_PROBE_UNPLUG",
9236af75ecdSLinus Walleij 		.start = AB8500_INT_ADP_PROBE_UNPLUG,
9246af75ecdSLinus Walleij 		.end = AB8500_INT_ADP_PROBE_UNPLUG,
9256af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
9266af75ecdSLinus Walleij 	},
927e098adedSMattias Wallin };
928e098adedSMattias Wallin 
929a9e9ce4cSBill Pemberton static struct resource ab8505_iddet_resources[] = {
93044f72e53SVirupax Sadashivpetimath 	{
93144f72e53SVirupax Sadashivpetimath 		.name  = "KeyDeglitch",
93244f72e53SVirupax Sadashivpetimath 		.start = AB8505_INT_KEYDEGLITCH,
93344f72e53SVirupax Sadashivpetimath 		.end   = AB8505_INT_KEYDEGLITCH,
93444f72e53SVirupax Sadashivpetimath 		.flags = IORESOURCE_IRQ,
93544f72e53SVirupax Sadashivpetimath 	},
93644f72e53SVirupax Sadashivpetimath 	{
93744f72e53SVirupax Sadashivpetimath 		.name  = "KP",
93844f72e53SVirupax Sadashivpetimath 		.start = AB8505_INT_KP,
93944f72e53SVirupax Sadashivpetimath 		.end   = AB8505_INT_KP,
94044f72e53SVirupax Sadashivpetimath 		.flags = IORESOURCE_IRQ,
94144f72e53SVirupax Sadashivpetimath 	},
94244f72e53SVirupax Sadashivpetimath 	{
94344f72e53SVirupax Sadashivpetimath 		.name  = "IKP",
94444f72e53SVirupax Sadashivpetimath 		.start = AB8505_INT_IKP,
94544f72e53SVirupax Sadashivpetimath 		.end   = AB8505_INT_IKP,
94644f72e53SVirupax Sadashivpetimath 		.flags = IORESOURCE_IRQ,
94744f72e53SVirupax Sadashivpetimath 	},
94844f72e53SVirupax Sadashivpetimath 	{
94944f72e53SVirupax Sadashivpetimath 		.name  = "IKR",
95044f72e53SVirupax Sadashivpetimath 		.start = AB8505_INT_IKR,
95144f72e53SVirupax Sadashivpetimath 		.end   = AB8505_INT_IKR,
95244f72e53SVirupax Sadashivpetimath 		.flags = IORESOURCE_IRQ,
95344f72e53SVirupax Sadashivpetimath 	},
95444f72e53SVirupax Sadashivpetimath 	{
95544f72e53SVirupax Sadashivpetimath 		.name  = "KeyStuck",
95644f72e53SVirupax Sadashivpetimath 		.start = AB8505_INT_KEYSTUCK,
95744f72e53SVirupax Sadashivpetimath 		.end   = AB8505_INT_KEYSTUCK,
95844f72e53SVirupax Sadashivpetimath 		.flags = IORESOURCE_IRQ,
95944f72e53SVirupax Sadashivpetimath 	},
960492390c8SLee Jones 	{
961492390c8SLee Jones 		.name = "VBUS_DET_R",
962492390c8SLee Jones 		.start = AB8500_INT_VBUS_DET_R,
963492390c8SLee Jones 		.end = AB8500_INT_VBUS_DET_R,
964492390c8SLee Jones 		.flags = IORESOURCE_IRQ,
965492390c8SLee Jones 	},
966492390c8SLee Jones 	{
967492390c8SLee Jones 		.name = "VBUS_DET_F",
968492390c8SLee Jones 		.start = AB8500_INT_VBUS_DET_F,
969492390c8SLee Jones 		.end = AB8500_INT_VBUS_DET_F,
970492390c8SLee Jones 		.flags = IORESOURCE_IRQ,
971492390c8SLee Jones 	},
972492390c8SLee Jones 	{
973492390c8SLee Jones 		.name = "ID_DET_PLUGR",
974492390c8SLee Jones 		.start = AB8500_INT_ID_DET_PLUGR,
975492390c8SLee Jones 		.end = AB8500_INT_ID_DET_PLUGR,
976492390c8SLee Jones 		.flags = IORESOURCE_IRQ,
977492390c8SLee Jones 	},
978492390c8SLee Jones 	{
979492390c8SLee Jones 		.name = "ID_DET_PLUGF",
980492390c8SLee Jones 		.start = AB8500_INT_ID_DET_PLUGF,
981492390c8SLee Jones 		.end = AB8500_INT_ID_DET_PLUGF,
982492390c8SLee Jones 		.flags = IORESOURCE_IRQ,
983492390c8SLee Jones 	},
98444f72e53SVirupax Sadashivpetimath };
98544f72e53SVirupax Sadashivpetimath 
986a9e9ce4cSBill Pemberton static struct resource ab8500_temp_resources[] = {
987e098adedSMattias Wallin 	{
988151621a7SHongbo Zhang 		.name  = "ABX500_TEMP_WARM",
989e098adedSMattias Wallin 		.start = AB8500_INT_TEMP_WARM,
990e098adedSMattias Wallin 		.end   = AB8500_INT_TEMP_WARM,
991e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
992e098adedSMattias Wallin 	},
993e098adedSMattias Wallin };
994e098adedSMattias Wallin 
995a9e9ce4cSBill Pemberton static struct mfd_cell ab8500_bm_devs[] = {
9966ef9418cSRickard Andersson 	{
9976ef9418cSRickard Andersson 		.name = "ab8500-charger",
9984aef72dbSRajanikanth H.V 		.of_compatible = "stericsson,ab8500-charger",
9996ef9418cSRickard Andersson 		.num_resources = ARRAY_SIZE(ab8500_charger_resources),
10006ef9418cSRickard Andersson 		.resources = ab8500_charger_resources,
10014aef72dbSRajanikanth H.V 		.platform_data = &ab8500_bm_data,
10024aef72dbSRajanikanth H.V 		.pdata_size = sizeof(ab8500_bm_data),
10036ef9418cSRickard Andersson 	},
10046ef9418cSRickard Andersson 	{
10056ef9418cSRickard Andersson 		.name = "ab8500-btemp",
1006bd9e8ab2SRajanikanth H.V 		.of_compatible = "stericsson,ab8500-btemp",
10076ef9418cSRickard Andersson 		.num_resources = ARRAY_SIZE(ab8500_btemp_resources),
10086ef9418cSRickard Andersson 		.resources = ab8500_btemp_resources,
1009bd9e8ab2SRajanikanth H.V 		.platform_data = &ab8500_bm_data,
1010bd9e8ab2SRajanikanth H.V 		.pdata_size = sizeof(ab8500_bm_data),
10116ef9418cSRickard Andersson 	},
10126ef9418cSRickard Andersson 	{
10136ef9418cSRickard Andersson 		.name = "ab8500-fg",
1014e0f1abebSRajanikanth H.V 		.of_compatible = "stericsson,ab8500-fg",
10156ef9418cSRickard Andersson 		.num_resources = ARRAY_SIZE(ab8500_fg_resources),
10166ef9418cSRickard Andersson 		.resources = ab8500_fg_resources,
1017e0f1abebSRajanikanth H.V 		.platform_data = &ab8500_bm_data,
1018e0f1abebSRajanikanth H.V 		.pdata_size = sizeof(ab8500_bm_data),
10196ef9418cSRickard Andersson 	},
10206ef9418cSRickard Andersson 	{
10216ef9418cSRickard Andersson 		.name = "ab8500-chargalg",
1022a12810abSRajanikanth H.V 		.of_compatible = "stericsson,ab8500-chargalg",
10236ef9418cSRickard Andersson 		.num_resources = ARRAY_SIZE(ab8500_chargalg_resources),
10246ef9418cSRickard Andersson 		.resources = ab8500_chargalg_resources,
1025a12810abSRajanikanth H.V 		.platform_data = &ab8500_bm_data,
1026a12810abSRajanikanth H.V 		.pdata_size = sizeof(ab8500_bm_data),
10276ef9418cSRickard Andersson 	},
10286ef9418cSRickard Andersson };
10296ef9418cSRickard Andersson 
1030a9e9ce4cSBill Pemberton static struct mfd_cell ab8500_devs[] = {
10314b106fb9SLee Jones #ifdef CONFIG_DEBUG_FS
1032d6255529SLinus Walleij 	{
10334b106fb9SLee Jones 		.name = "ab8500-debug",
10344b106fb9SLee Jones 		.of_compatible = "stericsson,ab8500-debug",
10354b106fb9SLee Jones 		.num_resources = ARRAY_SIZE(ab8500_debug_resources),
10364b106fb9SLee Jones 		.resources = ab8500_debug_resources,
10374b106fb9SLee Jones 	},
10384b106fb9SLee Jones #endif
10394b106fb9SLee Jones 	{
10404b106fb9SLee Jones 		.name = "ab8500-sysctrl",
10414b106fb9SLee Jones 		.of_compatible = "stericsson,ab8500-sysctrl",
10424b106fb9SLee Jones 	},
10434b106fb9SLee Jones 	{
10444b106fb9SLee Jones 		.name = "ab8500-regulator",
10454b106fb9SLee Jones 		.of_compatible = "stericsson,ab8500-regulator",
10464b106fb9SLee Jones 	},
10474b106fb9SLee Jones 	{
10484b106fb9SLee Jones 		.name = "abx500-clk",
10494b106fb9SLee Jones 		.of_compatible = "stericsson,abx500-clk",
10504b106fb9SLee Jones 	},
10514b106fb9SLee Jones 	{
10524b106fb9SLee Jones 		.name = "ab8500-gpadc",
10534b106fb9SLee Jones 		.num_resources = ARRAY_SIZE(ab8500_gpadc_resources),
10544b106fb9SLee Jones 		.resources = ab8500_gpadc_resources,
10554b106fb9SLee Jones 	},
10564b106fb9SLee Jones 	{
10574b106fb9SLee Jones 		.name = "ab8500-rtc",
10584b106fb9SLee Jones 		.of_compatible = "stericsson,ab8500-rtc",
10594b106fb9SLee Jones 		.num_resources = ARRAY_SIZE(ab8500_rtc_resources),
10604b106fb9SLee Jones 		.resources = ab8500_rtc_resources,
10614b106fb9SLee Jones 	},
10624b106fb9SLee Jones 	{
10634b106fb9SLee Jones 		.name = "ab8500-acc-det",
10644b106fb9SLee Jones 		.of_compatible = "stericsson,ab8500-acc-det",
10654b106fb9SLee Jones 		.num_resources = ARRAY_SIZE(ab8500_av_acc_detect_resources),
10664b106fb9SLee Jones 		.resources = ab8500_av_acc_detect_resources,
10674b106fb9SLee Jones 	},
10684b106fb9SLee Jones 	{
10694b106fb9SLee Jones 
10704b106fb9SLee Jones 		.name = "ab8500-poweron-key",
10714b106fb9SLee Jones 		.of_compatible = "stericsson,ab8500-poweron-key",
10724b106fb9SLee Jones 		.num_resources = ARRAY_SIZE(ab8500_poweronkey_db_resources),
10734b106fb9SLee Jones 		.resources = ab8500_poweronkey_db_resources,
10744b106fb9SLee Jones 	},
10754b106fb9SLee Jones 	{
10764b106fb9SLee Jones 		.name = "ab8500-pwm",
10774b106fb9SLee Jones 		.of_compatible = "stericsson,ab8500-pwm",
10784b106fb9SLee Jones 		.id = 1,
10794b106fb9SLee Jones 	},
10804b106fb9SLee Jones 	{
10814b106fb9SLee Jones 		.name = "ab8500-pwm",
10824b106fb9SLee Jones 		.of_compatible = "stericsson,ab8500-pwm",
10834b106fb9SLee Jones 		.id = 2,
10844b106fb9SLee Jones 	},
10854b106fb9SLee Jones 	{
10864b106fb9SLee Jones 		.name = "ab8500-pwm",
10874b106fb9SLee Jones 		.of_compatible = "stericsson,ab8500-pwm",
10884b106fb9SLee Jones 		.id = 3,
10894b106fb9SLee Jones 	},
10904b106fb9SLee Jones 	{
10914b106fb9SLee Jones 		.name = "ab8500-leds",
10924b106fb9SLee Jones 		.of_compatible = "stericsson,ab8500-leds",
10934b106fb9SLee Jones 	},
10944b106fb9SLee Jones 	{
10954b106fb9SLee Jones 		.name = "ab8500-denc",
10964b106fb9SLee Jones 		.of_compatible = "stericsson,ab8500-denc",
10974b106fb9SLee Jones 	},
10984b106fb9SLee Jones 	{
10994b106fb9SLee Jones 		.name = "ab8500-gpio",
1100bad76991SLee Jones 		.of_compatible = "stericsson,ab8500-gpio",
1101d6255529SLinus Walleij 	},
1102d6255529SLinus Walleij 	{
11034b106fb9SLee Jones 		.name = "abx500-temp",
11044b106fb9SLee Jones 		.of_compatible = "stericsson,abx500-temp",
11054b106fb9SLee Jones 		.num_resources = ARRAY_SIZE(ab8500_temp_resources),
11064b106fb9SLee Jones 		.resources = ab8500_temp_resources,
11074b106fb9SLee Jones 	},
11084b106fb9SLee Jones 	{
1109d6255529SLinus Walleij 		.name = "ab8500-usb",
1110d6255529SLinus Walleij 		.num_resources = ARRAY_SIZE(ab8500_usb_resources),
1111d6255529SLinus Walleij 		.resources = ab8500_usb_resources,
1112d6255529SLinus Walleij 	},
111344f72e53SVirupax Sadashivpetimath 	{
111444f72e53SVirupax Sadashivpetimath 		.name = "ab8500-codec",
11154b106fb9SLee Jones 	},
11164b106fb9SLee Jones };
11174b106fb9SLee Jones 
11184b106fb9SLee Jones static struct mfd_cell ab9540_devs[] = {
11194b106fb9SLee Jones #ifdef CONFIG_DEBUG_FS
11204b106fb9SLee Jones 	{
11214b106fb9SLee Jones 		.name = "ab8500-debug",
11224b106fb9SLee Jones 		.num_resources = ARRAY_SIZE(ab8500_debug_resources),
11234b106fb9SLee Jones 		.resources = ab8500_debug_resources,
11244b106fb9SLee Jones 	},
11254b106fb9SLee Jones #endif
11264b106fb9SLee Jones 	{
11274b106fb9SLee Jones 		.name = "ab8500-sysctrl",
11284b106fb9SLee Jones 	},
11294b106fb9SLee Jones 	{
11304b106fb9SLee Jones 		.name = "ab8500-regulator",
113144f72e53SVirupax Sadashivpetimath 	},
1132c0eda9aeSLee Jones 	{
11339ee17676SUlf Hansson 		.name = "abx500-clk",
11349ee17676SUlf Hansson 		.of_compatible = "stericsson,abx500-clk",
11359ee17676SUlf Hansson 	},
11369ee17676SUlf Hansson 	{
1137c0eda9aeSLee Jones 		.name = "ab8500-gpadc",
1138c0eda9aeSLee Jones 		.of_compatible = "stericsson,ab8500-gpadc",
1139c0eda9aeSLee Jones 		.num_resources = ARRAY_SIZE(ab8500_gpadc_resources),
1140c0eda9aeSLee Jones 		.resources = ab8500_gpadc_resources,
1141c0eda9aeSLee Jones 	},
11424b106fb9SLee Jones 	{
11434b106fb9SLee Jones 		.name = "ab8500-rtc",
11444b106fb9SLee Jones 		.num_resources = ARRAY_SIZE(ab8500_rtc_resources),
11454b106fb9SLee Jones 		.resources = ab8500_rtc_resources,
11464b106fb9SLee Jones 	},
11474b106fb9SLee Jones 	{
11484b106fb9SLee Jones 		.name = "ab8500-acc-det",
11494b106fb9SLee Jones 		.num_resources = ARRAY_SIZE(ab8500_av_acc_detect_resources),
11504b106fb9SLee Jones 		.resources = ab8500_av_acc_detect_resources,
11514b106fb9SLee Jones 	},
11524b106fb9SLee Jones 	{
11534b106fb9SLee Jones 		.name = "ab8500-poweron-key",
11544b106fb9SLee Jones 		.num_resources = ARRAY_SIZE(ab8500_poweronkey_db_resources),
11554b106fb9SLee Jones 		.resources = ab8500_poweronkey_db_resources,
11564b106fb9SLee Jones 	},
11574b106fb9SLee Jones 	{
11584b106fb9SLee Jones 		.name = "ab8500-pwm",
11594b106fb9SLee Jones 		.id = 1,
11604b106fb9SLee Jones 	},
11614b106fb9SLee Jones 	{
11624b106fb9SLee Jones 		.name = "ab8500-leds",
11634b106fb9SLee Jones 	},
11644b106fb9SLee Jones 	{
11654b106fb9SLee Jones 		.name = "abx500-temp",
11664b106fb9SLee Jones 		.num_resources = ARRAY_SIZE(ab8500_temp_resources),
11674b106fb9SLee Jones 		.resources = ab8500_temp_resources,
11684b106fb9SLee Jones 	},
1169d6255529SLinus Walleij 	{
1170e64d905eSLee Jones 		.name = "pinctrl-ab9540",
1171e64d905eSLee Jones 		.of_compatible = "stericsson,ab9540-gpio",
1172d6255529SLinus Walleij 	},
1173d6255529SLinus Walleij 	{
1174d6255529SLinus Walleij 		.name = "ab9540-usb",
1175d6255529SLinus Walleij 		.num_resources = ARRAY_SIZE(ab8500_usb_resources),
1176d6255529SLinus Walleij 		.resources = ab8500_usb_resources,
1177d6255529SLinus Walleij 	},
117844f72e53SVirupax Sadashivpetimath 	{
117944f72e53SVirupax Sadashivpetimath 		.name = "ab9540-codec",
118044f72e53SVirupax Sadashivpetimath 	},
1181c0eda9aeSLee Jones 	{
1182c0eda9aeSLee Jones 		.name = "ab-iddet",
1183c0eda9aeSLee Jones 		.num_resources = ARRAY_SIZE(ab8505_iddet_resources),
1184c0eda9aeSLee Jones 		.resources = ab8505_iddet_resources,
1185c0eda9aeSLee Jones 	},
118644f72e53SVirupax Sadashivpetimath };
118744f72e53SVirupax Sadashivpetimath 
1188c0eda9aeSLee Jones /* Device list for ab8505  */
1189c0eda9aeSLee Jones static struct mfd_cell ab8505_devs[] = {
11904b106fb9SLee Jones #ifdef CONFIG_DEBUG_FS
11914b106fb9SLee Jones 	{
11924b106fb9SLee Jones 		.name = "ab8500-debug",
11934b106fb9SLee Jones 		.num_resources = ARRAY_SIZE(ab8500_debug_resources),
11944b106fb9SLee Jones 		.resources = ab8500_debug_resources,
11954b106fb9SLee Jones 	},
11964b106fb9SLee Jones #endif
11974b106fb9SLee Jones 	{
11984b106fb9SLee Jones 		.name = "ab8500-sysctrl",
11994b106fb9SLee Jones 	},
12004b106fb9SLee Jones 	{
12014b106fb9SLee Jones 		.name = "ab8500-regulator",
12024b106fb9SLee Jones 	},
12034b106fb9SLee Jones 	{
12049ee17676SUlf Hansson 		.name = "abx500-clk",
12059ee17676SUlf Hansson 		.of_compatible = "stericsson,abx500-clk",
12069ee17676SUlf Hansson 	},
12079ee17676SUlf Hansson 	{
12084b106fb9SLee Jones 		.name = "ab8500-gpadc",
12094b106fb9SLee Jones 		.num_resources = ARRAY_SIZE(ab8505_gpadc_resources),
12104b106fb9SLee Jones 		.resources = ab8505_gpadc_resources,
12114b106fb9SLee Jones 	},
12124b106fb9SLee Jones 	{
12134b106fb9SLee Jones 		.name = "ab8500-rtc",
12144b106fb9SLee Jones 		.num_resources = ARRAY_SIZE(ab8500_rtc_resources),
12154b106fb9SLee Jones 		.resources = ab8500_rtc_resources,
12164b106fb9SLee Jones 	},
12174b106fb9SLee Jones 	{
12184b106fb9SLee Jones 		.name = "ab8500-acc-det",
12194b106fb9SLee Jones 		.num_resources = ARRAY_SIZE(ab8500_av_acc_detect_resources),
12204b106fb9SLee Jones 		.resources = ab8500_av_acc_detect_resources,
12214b106fb9SLee Jones 	},
12224b106fb9SLee Jones 	{
12234b106fb9SLee Jones 		.name = "ab8500-poweron-key",
12244b106fb9SLee Jones 		.num_resources = ARRAY_SIZE(ab8500_poweronkey_db_resources),
12254b106fb9SLee Jones 		.resources = ab8500_poweronkey_db_resources,
12264b106fb9SLee Jones 	},
12274b106fb9SLee Jones 	{
12284b106fb9SLee Jones 		.name = "ab8500-pwm",
12294b106fb9SLee Jones 		.id = 1,
12304b106fb9SLee Jones 	},
12314b106fb9SLee Jones 	{
12324b106fb9SLee Jones 		.name = "ab8500-leds",
12334b106fb9SLee Jones 	},
12344b106fb9SLee Jones 	{
12354b106fb9SLee Jones 		.name = "ab8500-gpio",
12364b106fb9SLee Jones 	},
12374b106fb9SLee Jones 	{
12384b106fb9SLee Jones 		.name = "ab8500-usb",
12394b106fb9SLee Jones 		.num_resources = ARRAY_SIZE(ab8500_usb_resources),
12404b106fb9SLee Jones 		.resources = ab8500_usb_resources,
12414b106fb9SLee Jones 	},
12424b106fb9SLee Jones 	{
12434b106fb9SLee Jones 		.name = "ab8500-codec",
12444b106fb9SLee Jones 	},
1245c0eda9aeSLee Jones 	{
1246c0eda9aeSLee Jones 		.name = "ab-iddet",
1247c0eda9aeSLee Jones 		.num_resources = ARRAY_SIZE(ab8505_iddet_resources),
1248c0eda9aeSLee Jones 		.resources = ab8505_iddet_resources,
1249c0eda9aeSLee Jones 	},
1250c0eda9aeSLee Jones };
1251c0eda9aeSLee Jones 
1252c0eda9aeSLee Jones static struct mfd_cell ab8540_devs[] = {
12534b106fb9SLee Jones #ifdef CONFIG_DEBUG_FS
12544b106fb9SLee Jones 	{
12554b106fb9SLee Jones 		.name = "ab8500-debug",
12564b106fb9SLee Jones 		.num_resources = ARRAY_SIZE(ab8500_debug_resources),
12574b106fb9SLee Jones 		.resources = ab8500_debug_resources,
12584b106fb9SLee Jones 	},
12594b106fb9SLee Jones #endif
12604b106fb9SLee Jones 	{
12614b106fb9SLee Jones 		.name = "ab8500-sysctrl",
12624b106fb9SLee Jones 	},
12634b106fb9SLee Jones 	{
12644b106fb9SLee Jones 		.name = "ab8500-regulator",
12654b106fb9SLee Jones 	},
12664b106fb9SLee Jones 	{
12679ee17676SUlf Hansson 		.name = "abx500-clk",
12689ee17676SUlf Hansson 		.of_compatible = "stericsson,abx500-clk",
12699ee17676SUlf Hansson 	},
12709ee17676SUlf Hansson 	{
12714b106fb9SLee Jones 		.name = "ab8500-gpadc",
12724b106fb9SLee Jones 		.num_resources = ARRAY_SIZE(ab8505_gpadc_resources),
12734b106fb9SLee Jones 		.resources = ab8505_gpadc_resources,
12744b106fb9SLee Jones 	},
12754b106fb9SLee Jones 	{
12764b106fb9SLee Jones 		.name = "ab8500-rtc",
12774b106fb9SLee Jones 		.num_resources = ARRAY_SIZE(ab8500_rtc_resources),
12784b106fb9SLee Jones 		.resources = ab8500_rtc_resources,
12794b106fb9SLee Jones 	},
12804b106fb9SLee Jones 	{
12814b106fb9SLee Jones 		.name = "ab8500-acc-det",
12824b106fb9SLee Jones 		.num_resources = ARRAY_SIZE(ab8500_av_acc_detect_resources),
12834b106fb9SLee Jones 		.resources = ab8500_av_acc_detect_resources,
12844b106fb9SLee Jones 	},
12854b106fb9SLee Jones 	{
12864b106fb9SLee Jones 		.name = "ab8500-poweron-key",
12874b106fb9SLee Jones 		.num_resources = ARRAY_SIZE(ab8500_poweronkey_db_resources),
12884b106fb9SLee Jones 		.resources = ab8500_poweronkey_db_resources,
12894b106fb9SLee Jones 	},
12904b106fb9SLee Jones 	{
12914b106fb9SLee Jones 		.name = "ab8500-pwm",
12924b106fb9SLee Jones 		.id = 1,
12934b106fb9SLee Jones 	},
12944b106fb9SLee Jones 	{
12954b106fb9SLee Jones 		.name = "ab8500-leds",
12964b106fb9SLee Jones 	},
12974b106fb9SLee Jones 	{
12984b106fb9SLee Jones 		.name = "abx500-temp",
12994b106fb9SLee Jones 		.num_resources = ARRAY_SIZE(ab8500_temp_resources),
13004b106fb9SLee Jones 		.resources = ab8500_temp_resources,
13014b106fb9SLee Jones 	},
1302c0eda9aeSLee Jones 	{
1303c0eda9aeSLee Jones 		.name = "ab8500-gpio",
1304c0eda9aeSLee Jones 	},
1305c0eda9aeSLee Jones 	{
1306c0eda9aeSLee Jones 		.name = "ab8540-usb",
1307c0eda9aeSLee Jones 		.num_resources = ARRAY_SIZE(ab8500_usb_resources),
1308c0eda9aeSLee Jones 		.resources = ab8500_usb_resources,
1309c0eda9aeSLee Jones 	},
1310c0eda9aeSLee Jones 	{
1311c0eda9aeSLee Jones 		.name = "ab8540-codec",
1312c0eda9aeSLee Jones 	},
1313c0eda9aeSLee Jones 	{
131444f72e53SVirupax Sadashivpetimath 		.name = "ab-iddet",
131544f72e53SVirupax Sadashivpetimath 		.num_resources = ARRAY_SIZE(ab8505_iddet_resources),
131644f72e53SVirupax Sadashivpetimath 		.resources = ab8505_iddet_resources,
131744f72e53SVirupax Sadashivpetimath 	},
1318d6255529SLinus Walleij };
1319d6255529SLinus Walleij 
1320cca69b67SMattias Wallin static ssize_t show_chip_id(struct device *dev,
1321cca69b67SMattias Wallin 				struct device_attribute *attr, char *buf)
1322cca69b67SMattias Wallin {
1323cca69b67SMattias Wallin 	struct ab8500 *ab8500;
1324cca69b67SMattias Wallin 
1325cca69b67SMattias Wallin 	ab8500 = dev_get_drvdata(dev);
1326e436ddffSLee Jones 
1327cca69b67SMattias Wallin 	return sprintf(buf, "%#x\n", ab8500 ? ab8500->chip_id : -EINVAL);
1328cca69b67SMattias Wallin }
1329cca69b67SMattias Wallin 
1330e5c238c3SMattias Wallin /*
1331e5c238c3SMattias Wallin  * ab8500 has switched off due to (SWITCH_OFF_STATUS):
1332e5c238c3SMattias Wallin  * 0x01 Swoff bit programming
1333e5c238c3SMattias Wallin  * 0x02 Thermal protection activation
1334e5c238c3SMattias Wallin  * 0x04 Vbat lower then BattOk falling threshold
1335e5c238c3SMattias Wallin  * 0x08 Watchdog expired
1336e5c238c3SMattias Wallin  * 0x10 Non presence of 32kHz clock
1337e5c238c3SMattias Wallin  * 0x20 Battery level lower than power on reset threshold
1338e5c238c3SMattias Wallin  * 0x40 Power on key 1 pressed longer than 10 seconds
1339e5c238c3SMattias Wallin  * 0x80 DB8500 thermal shutdown
1340e5c238c3SMattias Wallin  */
1341e5c238c3SMattias Wallin static ssize_t show_switch_off_status(struct device *dev,
1342e5c238c3SMattias Wallin 				struct device_attribute *attr, char *buf)
1343e5c238c3SMattias Wallin {
1344e5c238c3SMattias Wallin 	int ret;
1345e5c238c3SMattias Wallin 	u8 value;
1346e5c238c3SMattias Wallin 	struct ab8500 *ab8500;
1347e5c238c3SMattias Wallin 
1348e5c238c3SMattias Wallin 	ab8500 = dev_get_drvdata(dev);
1349e5c238c3SMattias Wallin 	ret = get_register_interruptible(ab8500, AB8500_RTC,
1350e5c238c3SMattias Wallin 		AB8500_SWITCH_OFF_STATUS, &value);
1351e5c238c3SMattias Wallin 	if (ret < 0)
1352e5c238c3SMattias Wallin 		return ret;
1353e5c238c3SMattias Wallin 	return sprintf(buf, "%#x\n", value);
1354e5c238c3SMattias Wallin }
1355e5c238c3SMattias Wallin 
1356f04a9d8aSRajkumar Kasirajan /* use mask and set to override the register turn_on_stat value */
1357f04a9d8aSRajkumar Kasirajan void ab8500_override_turn_on_stat(u8 mask, u8 set)
1358f04a9d8aSRajkumar Kasirajan {
1359f04a9d8aSRajkumar Kasirajan 	spin_lock(&on_stat_lock);
1360f04a9d8aSRajkumar Kasirajan 	turn_on_stat_mask = mask;
1361f04a9d8aSRajkumar Kasirajan 	turn_on_stat_set = set;
1362f04a9d8aSRajkumar Kasirajan 	spin_unlock(&on_stat_lock);
1363f04a9d8aSRajkumar Kasirajan }
1364f04a9d8aSRajkumar Kasirajan 
1365b4a31037SAndrew Lynn /*
1366b4a31037SAndrew Lynn  * ab8500 has turned on due to (TURN_ON_STATUS):
1367b4a31037SAndrew Lynn  * 0x01 PORnVbat
1368b4a31037SAndrew Lynn  * 0x02 PonKey1dbF
1369b4a31037SAndrew Lynn  * 0x04 PonKey2dbF
1370b4a31037SAndrew Lynn  * 0x08 RTCAlarm
1371b4a31037SAndrew Lynn  * 0x10 MainChDet
1372b4a31037SAndrew Lynn  * 0x20 VbusDet
1373b4a31037SAndrew Lynn  * 0x40 UsbIDDetect
1374b4a31037SAndrew Lynn  * 0x80 Reserved
1375b4a31037SAndrew Lynn  */
1376b4a31037SAndrew Lynn static ssize_t show_turn_on_status(struct device *dev,
1377b4a31037SAndrew Lynn 				struct device_attribute *attr, char *buf)
1378b4a31037SAndrew Lynn {
1379b4a31037SAndrew Lynn 	int ret;
1380b4a31037SAndrew Lynn 	u8 value;
1381b4a31037SAndrew Lynn 	struct ab8500 *ab8500;
1382b4a31037SAndrew Lynn 
1383b4a31037SAndrew Lynn 	ab8500 = dev_get_drvdata(dev);
1384b4a31037SAndrew Lynn 	ret = get_register_interruptible(ab8500, AB8500_SYS_CTRL1_BLOCK,
1385b4a31037SAndrew Lynn 		AB8500_TURN_ON_STATUS, &value);
1386b4a31037SAndrew Lynn 	if (ret < 0)
1387b4a31037SAndrew Lynn 		return ret;
1388f04a9d8aSRajkumar Kasirajan 
1389f04a9d8aSRajkumar Kasirajan 	/*
1390f04a9d8aSRajkumar Kasirajan 	 * In L9540, turn_on_status register is not updated correctly if
1391f04a9d8aSRajkumar Kasirajan 	 * the device is rebooted with AC/USB charger connected. Due to
1392f04a9d8aSRajkumar Kasirajan 	 * this, the device boots android instead of entering into charge
1393f04a9d8aSRajkumar Kasirajan 	 * only mode. Read the AC/USB status register to detect the charger
1394f04a9d8aSRajkumar Kasirajan 	 * presence and update the turn on status manually.
1395f04a9d8aSRajkumar Kasirajan 	 */
1396f04a9d8aSRajkumar Kasirajan 	if (is_ab9540(ab8500)) {
1397f04a9d8aSRajkumar Kasirajan 		spin_lock(&on_stat_lock);
1398f04a9d8aSRajkumar Kasirajan 		value = (value & turn_on_stat_mask) | turn_on_stat_set;
1399f04a9d8aSRajkumar Kasirajan 		spin_unlock(&on_stat_lock);
1400f04a9d8aSRajkumar Kasirajan 	}
1401f04a9d8aSRajkumar Kasirajan 
1402b4a31037SAndrew Lynn 	return sprintf(buf, "%#x\n", value);
1403b4a31037SAndrew Lynn }
1404b4a31037SAndrew Lynn 
1405*93ff722eSLee Jones static ssize_t show_turn_on_status_2(struct device *dev,
1406*93ff722eSLee Jones 				struct device_attribute *attr, char *buf)
1407*93ff722eSLee Jones {
1408*93ff722eSLee Jones 	int ret;
1409*93ff722eSLee Jones 	u8 value;
1410*93ff722eSLee Jones 	struct ab8500 *ab8500;
1411*93ff722eSLee Jones 
1412*93ff722eSLee Jones 	ab8500 = dev_get_drvdata(dev);
1413*93ff722eSLee Jones 	ret = get_register_interruptible(ab8500, AB8500_SYS_CTRL1_BLOCK,
1414*93ff722eSLee Jones 		AB8505_TURN_ON_STATUS_2, &value);
1415*93ff722eSLee Jones 	if (ret < 0)
1416*93ff722eSLee Jones 		return ret;
1417*93ff722eSLee Jones 	return sprintf(buf, "%#x\n", (value & 0x1));
1418*93ff722eSLee Jones }
1419*93ff722eSLee Jones 
1420d6255529SLinus Walleij static ssize_t show_ab9540_dbbrstn(struct device *dev,
1421d6255529SLinus Walleij 				struct device_attribute *attr, char *buf)
1422d6255529SLinus Walleij {
1423d6255529SLinus Walleij 	struct ab8500 *ab8500;
1424d6255529SLinus Walleij 	int ret;
1425d6255529SLinus Walleij 	u8 value;
1426d6255529SLinus Walleij 
1427d6255529SLinus Walleij 	ab8500 = dev_get_drvdata(dev);
1428d6255529SLinus Walleij 
1429d6255529SLinus Walleij 	ret = get_register_interruptible(ab8500, AB8500_REGU_CTRL2,
1430d6255529SLinus Walleij 		AB9540_MODEM_CTRL2_REG, &value);
1431d6255529SLinus Walleij 	if (ret < 0)
1432d6255529SLinus Walleij 		return ret;
1433d6255529SLinus Walleij 
1434d6255529SLinus Walleij 	return sprintf(buf, "%d\n",
1435d6255529SLinus Walleij 			(value & AB9540_MODEM_CTRL2_SWDBBRSTN_BIT) ? 1 : 0);
1436d6255529SLinus Walleij }
1437d6255529SLinus Walleij 
1438d6255529SLinus Walleij static ssize_t store_ab9540_dbbrstn(struct device *dev,
1439d6255529SLinus Walleij 	struct device_attribute *attr, const char *buf, size_t count)
1440d6255529SLinus Walleij {
1441d6255529SLinus Walleij 	struct ab8500 *ab8500;
1442d6255529SLinus Walleij 	int ret = count;
1443d6255529SLinus Walleij 	int err;
1444d6255529SLinus Walleij 	u8 bitvalues;
1445d6255529SLinus Walleij 
1446d6255529SLinus Walleij 	ab8500 = dev_get_drvdata(dev);
1447d6255529SLinus Walleij 
1448d6255529SLinus Walleij 	if (count > 0) {
1449d6255529SLinus Walleij 		switch (buf[0]) {
1450d6255529SLinus Walleij 		case '0':
1451d6255529SLinus Walleij 			bitvalues = 0;
1452d6255529SLinus Walleij 			break;
1453d6255529SLinus Walleij 		case '1':
1454d6255529SLinus Walleij 			bitvalues = AB9540_MODEM_CTRL2_SWDBBRSTN_BIT;
1455d6255529SLinus Walleij 			break;
1456d6255529SLinus Walleij 		default:
1457d6255529SLinus Walleij 			goto exit;
1458d6255529SLinus Walleij 		}
1459d6255529SLinus Walleij 
1460d6255529SLinus Walleij 		err = mask_and_set_register_interruptible(ab8500,
1461d6255529SLinus Walleij 			AB8500_REGU_CTRL2, AB9540_MODEM_CTRL2_REG,
1462d6255529SLinus Walleij 			AB9540_MODEM_CTRL2_SWDBBRSTN_BIT, bitvalues);
1463d6255529SLinus Walleij 		if (err)
1464d6255529SLinus Walleij 			dev_info(ab8500->dev,
1465d6255529SLinus Walleij 				"Failed to set DBBRSTN %c, err %#x\n",
1466d6255529SLinus Walleij 				buf[0], err);
1467d6255529SLinus Walleij 	}
1468d6255529SLinus Walleij 
1469d6255529SLinus Walleij exit:
1470d6255529SLinus Walleij 	return ret;
1471d6255529SLinus Walleij }
1472d6255529SLinus Walleij 
1473cca69b67SMattias Wallin static DEVICE_ATTR(chip_id, S_IRUGO, show_chip_id, NULL);
1474e5c238c3SMattias Wallin static DEVICE_ATTR(switch_off_status, S_IRUGO, show_switch_off_status, NULL);
1475b4a31037SAndrew Lynn static DEVICE_ATTR(turn_on_status, S_IRUGO, show_turn_on_status, NULL);
1476*93ff722eSLee Jones static DEVICE_ATTR(turn_on_status_2, S_IRUGO, show_turn_on_status_2, NULL);
1477d6255529SLinus Walleij static DEVICE_ATTR(dbbrstn, S_IRUGO | S_IWUSR,
1478d6255529SLinus Walleij 			show_ab9540_dbbrstn, store_ab9540_dbbrstn);
1479cca69b67SMattias Wallin 
1480cca69b67SMattias Wallin static struct attribute *ab8500_sysfs_entries[] = {
1481cca69b67SMattias Wallin 	&dev_attr_chip_id.attr,
1482e5c238c3SMattias Wallin 	&dev_attr_switch_off_status.attr,
1483b4a31037SAndrew Lynn 	&dev_attr_turn_on_status.attr,
1484cca69b67SMattias Wallin 	NULL,
1485cca69b67SMattias Wallin };
1486cca69b67SMattias Wallin 
1487*93ff722eSLee Jones static struct attribute *ab8505_sysfs_entries[] = {
1488*93ff722eSLee Jones 	&dev_attr_turn_on_status_2.attr,
1489*93ff722eSLee Jones 	NULL,
1490*93ff722eSLee Jones };
1491*93ff722eSLee Jones 
1492d6255529SLinus Walleij static struct attribute *ab9540_sysfs_entries[] = {
1493d6255529SLinus Walleij 	&dev_attr_chip_id.attr,
1494d6255529SLinus Walleij 	&dev_attr_switch_off_status.attr,
1495d6255529SLinus Walleij 	&dev_attr_turn_on_status.attr,
1496d6255529SLinus Walleij 	&dev_attr_dbbrstn.attr,
1497d6255529SLinus Walleij 	NULL,
1498d6255529SLinus Walleij };
1499d6255529SLinus Walleij 
1500cca69b67SMattias Wallin static struct attribute_group ab8500_attr_group = {
1501cca69b67SMattias Wallin 	.attrs	= ab8500_sysfs_entries,
1502cca69b67SMattias Wallin };
1503cca69b67SMattias Wallin 
1504*93ff722eSLee Jones static struct attribute_group ab8505_attr_group = {
1505*93ff722eSLee Jones 	.attrs	= ab8505_sysfs_entries,
1506*93ff722eSLee Jones };
1507*93ff722eSLee Jones 
1508d6255529SLinus Walleij static struct attribute_group ab9540_attr_group = {
1509d6255529SLinus Walleij 	.attrs	= ab9540_sysfs_entries,
1510d6255529SLinus Walleij };
1511d6255529SLinus Walleij 
1512f791be49SBill Pemberton static int ab8500_probe(struct platform_device *pdev)
151362579266SRabin Vincent {
1514b04c530cSJonas Aaberg 	static char *switch_off_status[] = {
1515b04c530cSJonas Aaberg 		"Swoff bit programming",
1516b04c530cSJonas Aaberg 		"Thermal protection activation",
1517b04c530cSJonas Aaberg 		"Vbat lower then BattOk falling threshold",
1518b04c530cSJonas Aaberg 		"Watchdog expired",
1519b04c530cSJonas Aaberg 		"Non presence of 32kHz clock",
1520b04c530cSJonas Aaberg 		"Battery level lower than power on reset threshold",
1521b04c530cSJonas Aaberg 		"Power on key 1 pressed longer than 10 seconds",
1522b04c530cSJonas Aaberg 		"DB8500 thermal shutdown"};
1523abee26cdSMattias Wallin 	static char *turn_on_status[] = {
1524abee26cdSMattias Wallin 		"Battery rising (Vbat)",
1525abee26cdSMattias Wallin 		"Power On Key 1 dbF",
1526abee26cdSMattias Wallin 		"Power On Key 2 dbF",
1527abee26cdSMattias Wallin 		"RTC Alarm",
1528abee26cdSMattias Wallin 		"Main Charger Detect",
1529abee26cdSMattias Wallin 		"Vbus Detect (USB)",
1530abee26cdSMattias Wallin 		"USB ID Detect",
1531abee26cdSMattias Wallin 		"UART Factory Mode Detect"};
1532d28f1db8SLee Jones 	struct ab8500_platform_data *plat = dev_get_platdata(&pdev->dev);
1533d28f1db8SLee Jones 	const struct platform_device_id *platid = platform_get_device_id(pdev);
15346bc4a568SLee Jones 	enum ab8500_version version = AB8500_VERSION_UNDEFINED;
15356bc4a568SLee Jones 	struct device_node *np = pdev->dev.of_node;
1536d28f1db8SLee Jones 	struct ab8500 *ab8500;
1537d28f1db8SLee Jones 	struct resource *resource;
153862579266SRabin Vincent 	int ret;
153962579266SRabin Vincent 	int i;
154047c16975SMattias Wallin 	u8 value;
154162579266SRabin Vincent 
15428c4203cbSLee Jones 	ab8500 = devm_kzalloc(&pdev->dev, sizeof *ab8500, GFP_KERNEL);
1543d28f1db8SLee Jones 	if (!ab8500)
1544d28f1db8SLee Jones 		return -ENOMEM;
1545d28f1db8SLee Jones 
154662579266SRabin Vincent 	if (plat)
154762579266SRabin Vincent 		ab8500->irq_base = plat->irq_base;
154862579266SRabin Vincent 
1549d28f1db8SLee Jones 	ab8500->dev = &pdev->dev;
1550d28f1db8SLee Jones 
1551d28f1db8SLee Jones 	resource = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
15528c4203cbSLee Jones 	if (!resource)
15538c4203cbSLee Jones 		return -ENODEV;
1554d28f1db8SLee Jones 
1555d28f1db8SLee Jones 	ab8500->irq = resource->start;
1556d28f1db8SLee Jones 
1557822672a7SLee Jones 	ab8500->read = ab8500_prcmu_read;
1558822672a7SLee Jones 	ab8500->write = ab8500_prcmu_write;
1559822672a7SLee Jones 	ab8500->write_masked = ab8500_prcmu_write_masked;
1560d28f1db8SLee Jones 
156162579266SRabin Vincent 	mutex_init(&ab8500->lock);
156262579266SRabin Vincent 	mutex_init(&ab8500->irq_lock);
1563112a80d2SJonas Aaberg 	atomic_set(&ab8500->transfer_ongoing, 0);
156462579266SRabin Vincent 
1565d28f1db8SLee Jones 	platform_set_drvdata(pdev, ab8500);
1566d28f1db8SLee Jones 
15676bc4a568SLee Jones 	if (platid)
15686bc4a568SLee Jones 		version = platid->driver_data;
15696bc4a568SLee Jones 
15700f620837SLinus Walleij 	if (version != AB8500_VERSION_UNDEFINED)
15710f620837SLinus Walleij 		ab8500->version = version;
15720f620837SLinus Walleij 	else {
15730f620837SLinus Walleij 		ret = get_register_interruptible(ab8500, AB8500_MISC,
15740f620837SLinus Walleij 			AB8500_IC_NAME_REG, &value);
15750f620837SLinus Walleij 		if (ret < 0)
15768c4203cbSLee Jones 			return ret;
15770f620837SLinus Walleij 
15780f620837SLinus Walleij 		ab8500->version = value;
15790f620837SLinus Walleij 	}
15800f620837SLinus Walleij 
158147c16975SMattias Wallin 	ret = get_register_interruptible(ab8500, AB8500_MISC,
158247c16975SMattias Wallin 		AB8500_REV_REG, &value);
158362579266SRabin Vincent 	if (ret < 0)
15848c4203cbSLee Jones 		return ret;
158562579266SRabin Vincent 
158647c16975SMattias Wallin 	ab8500->chip_id = value;
158762579266SRabin Vincent 
15880f620837SLinus Walleij 	dev_info(ab8500->dev, "detected chip, %s rev. %1x.%1x\n",
15890f620837SLinus Walleij 			ab8500_version_str[ab8500->version],
15900f620837SLinus Walleij 			ab8500->chip_id >> 4,
15910f620837SLinus Walleij 			ab8500->chip_id & 0x0F);
15920f620837SLinus Walleij 
15933e1a498fSLee Jones 	/* Configure AB8540 */
15943e1a498fSLee Jones 	if (is_ab8540(ab8500)) {
15953e1a498fSLee Jones 		ab8500->mask_size = AB8540_NUM_IRQ_REGS;
15963e1a498fSLee Jones 		ab8500->irq_reg_offset = ab8540_irq_regoffset;
15973e1a498fSLee Jones 		ab8500->it_latchhier_num = AB8540_IT_LATCHHIER_NUM;
15983e1a498fSLee Jones 	}/* Configure AB8500 or AB9540 IRQ */
15993e1a498fSLee Jones 	else if (is_ab9540(ab8500) || is_ab8505(ab8500)) {
1600d6255529SLinus Walleij 		ab8500->mask_size = AB9540_NUM_IRQ_REGS;
1601d6255529SLinus Walleij 		ab8500->irq_reg_offset = ab9540_irq_regoffset;
16023e1a498fSLee Jones 		ab8500->it_latchhier_num = AB8500_IT_LATCHHIER_NUM;
1603d6255529SLinus Walleij 	} else {
16042ced445eSLinus Walleij 		ab8500->mask_size = AB8500_NUM_IRQ_REGS;
16052ced445eSLinus Walleij 		ab8500->irq_reg_offset = ab8500_irq_regoffset;
16063e1a498fSLee Jones 		ab8500->it_latchhier_num = AB8500_IT_LATCHHIER_NUM;
1607d6255529SLinus Walleij 	}
16088c4203cbSLee Jones 	ab8500->mask = devm_kzalloc(&pdev->dev, ab8500->mask_size, GFP_KERNEL);
16092ced445eSLinus Walleij 	if (!ab8500->mask)
16102ced445eSLinus Walleij 		return -ENOMEM;
16118c4203cbSLee Jones 	ab8500->oldmask = devm_kzalloc(&pdev->dev, ab8500->mask_size, GFP_KERNEL);
16128c4203cbSLee Jones 	if (!ab8500->oldmask)
16138c4203cbSLee Jones 		return -ENOMEM;
16148c4203cbSLee Jones 
1615e5c238c3SMattias Wallin 	/*
1616e5c238c3SMattias Wallin 	 * ab8500 has switched off due to (SWITCH_OFF_STATUS):
1617e5c238c3SMattias Wallin 	 * 0x01 Swoff bit programming
1618e5c238c3SMattias Wallin 	 * 0x02 Thermal protection activation
1619e5c238c3SMattias Wallin 	 * 0x04 Vbat lower then BattOk falling threshold
1620e5c238c3SMattias Wallin 	 * 0x08 Watchdog expired
1621e5c238c3SMattias Wallin 	 * 0x10 Non presence of 32kHz clock
1622e5c238c3SMattias Wallin 	 * 0x20 Battery level lower than power on reset threshold
1623e5c238c3SMattias Wallin 	 * 0x40 Power on key 1 pressed longer than 10 seconds
1624e5c238c3SMattias Wallin 	 * 0x80 DB8500 thermal shutdown
1625e5c238c3SMattias Wallin 	 */
1626e5c238c3SMattias Wallin 
1627e5c238c3SMattias Wallin 	ret = get_register_interruptible(ab8500, AB8500_RTC,
1628e5c238c3SMattias Wallin 		AB8500_SWITCH_OFF_STATUS, &value);
1629e5c238c3SMattias Wallin 	if (ret < 0)
1630e5c238c3SMattias Wallin 		return ret;
1631b04c530cSJonas Aaberg 	dev_info(ab8500->dev, "switch off cause(s) (%#x): ", value);
1632b04c530cSJonas Aaberg 
1633b04c530cSJonas Aaberg 	if (value) {
1634b04c530cSJonas Aaberg 		for (i = 0; i < ARRAY_SIZE(switch_off_status); i++) {
1635b04c530cSJonas Aaberg 			if (value & 1)
1636b04c530cSJonas Aaberg 				printk(KERN_CONT " \"%s\"",
1637b04c530cSJonas Aaberg 				       switch_off_status[i]);
1638b04c530cSJonas Aaberg 			value = value >> 1;
1639b04c530cSJonas Aaberg 
1640b04c530cSJonas Aaberg 		}
1641b04c530cSJonas Aaberg 		printk(KERN_CONT "\n");
1642b04c530cSJonas Aaberg 	} else {
1643b04c530cSJonas Aaberg 		printk(KERN_CONT " None\n");
1644b04c530cSJonas Aaberg 	}
1645abee26cdSMattias Wallin 	ret = get_register_interruptible(ab8500, AB8500_SYS_CTRL1_BLOCK,
1646abee26cdSMattias Wallin 		AB8500_TURN_ON_STATUS, &value);
1647abee26cdSMattias Wallin 	if (ret < 0)
1648abee26cdSMattias Wallin 		return ret;
1649abee26cdSMattias Wallin 	dev_info(ab8500->dev, "turn on reason(s) (%#x): ", value);
1650abee26cdSMattias Wallin 
1651abee26cdSMattias Wallin 	if (value) {
1652abee26cdSMattias Wallin 		for (i = 0; i < ARRAY_SIZE(turn_on_status); i++) {
1653abee26cdSMattias Wallin 			if (value & 1)
1654abee26cdSMattias Wallin 				printk("\"%s\" ", turn_on_status[i]);
1655abee26cdSMattias Wallin 			value = value >> 1;
1656abee26cdSMattias Wallin 		}
1657abee26cdSMattias Wallin 		printk("\n");
1658abee26cdSMattias Wallin 	} else {
1659abee26cdSMattias Wallin 		printk("None\n");
1660abee26cdSMattias Wallin 	}
1661e5c238c3SMattias Wallin 
166262579266SRabin Vincent 	if (plat && plat->init)
166362579266SRabin Vincent 		plat->init(ab8500);
1664abee26cdSMattias Wallin 
1665f04a9d8aSRajkumar Kasirajan 	if (is_ab9540(ab8500)) {
1666f04a9d8aSRajkumar Kasirajan 		ret = get_register_interruptible(ab8500, AB8500_CHARGER,
1667f04a9d8aSRajkumar Kasirajan 			AB8500_CH_USBCH_STAT1_REG, &value);
1668f04a9d8aSRajkumar Kasirajan 		if (ret < 0)
1669f04a9d8aSRajkumar Kasirajan 			return ret;
1670f04a9d8aSRajkumar Kasirajan 		if ((value & VBUS_DET_DBNC1) && (value & VBUS_DET_DBNC100))
1671f04a9d8aSRajkumar Kasirajan 			ab8500_override_turn_on_stat(~AB8500_POW_KEY_1_ON,
1672f04a9d8aSRajkumar Kasirajan 						     AB8500_VBUS_DET);
1673f04a9d8aSRajkumar Kasirajan 	}
167462579266SRabin Vincent 
167562579266SRabin Vincent 	/* Clear and mask all interrupts */
16762ced445eSLinus Walleij 	for (i = 0; i < ab8500->mask_size; i++) {
16770f620837SLinus Walleij 		/*
16780f620837SLinus Walleij 		 * Interrupt register 12 doesn't exist prior to AB8500 version
16790f620837SLinus Walleij 		 * 2.0
16800f620837SLinus Walleij 		 */
16810f620837SLinus Walleij 		if (ab8500->irq_reg_offset[i] == 11 &&
16820f620837SLinus Walleij 				is_ab8500_1p1_or_earlier(ab8500))
168392d50a41SMattias Wallin 			continue;
168462579266SRabin Vincent 
16853e1a498fSLee Jones 		if (ab8500->irq_reg_offset[i] < 0)
16863e1a498fSLee Jones 			continue;
16873e1a498fSLee Jones 
168847c16975SMattias Wallin 		get_register_interruptible(ab8500, AB8500_INTERRUPT,
16892ced445eSLinus Walleij 			AB8500_IT_LATCH1_REG + ab8500->irq_reg_offset[i],
169092d50a41SMattias Wallin 			&value);
169147c16975SMattias Wallin 		set_register_interruptible(ab8500, AB8500_INTERRUPT,
16922ced445eSLinus Walleij 			AB8500_IT_MASK1_REG + ab8500->irq_reg_offset[i], 0xff);
169362579266SRabin Vincent 	}
169462579266SRabin Vincent 
169547c16975SMattias Wallin 	ret = abx500_register_ops(ab8500->dev, &ab8500_ops);
169647c16975SMattias Wallin 	if (ret)
16978c4203cbSLee Jones 		return ret;
169847c16975SMattias Wallin 
16992ced445eSLinus Walleij 	for (i = 0; i < ab8500->mask_size; i++)
170062579266SRabin Vincent 		ab8500->mask[i] = ab8500->oldmask[i] = 0xff;
170162579266SRabin Vincent 
170206e589efSLee Jones 	ret = ab8500_irq_init(ab8500, np);
170362579266SRabin Vincent 	if (ret)
17048c4203cbSLee Jones 		return ret;
170562579266SRabin Vincent 
17068c4203cbSLee Jones 	ret = devm_request_threaded_irq(&pdev->dev, ab8500->irq, NULL,
17077ccfe9b1SMichel JAOUEN 			ab8500_hierarchical_irq,
17087ccfe9b1SMichel JAOUEN 			IRQF_ONESHOT | IRQF_NO_SUSPEND,
17097ccfe9b1SMichel JAOUEN 			"ab8500", ab8500);
171062579266SRabin Vincent 	if (ret)
17118c4203cbSLee Jones 		return ret;
171262579266SRabin Vincent 
1713d6255529SLinus Walleij 	if (is_ab9540(ab8500))
1714d6255529SLinus Walleij 		ret = mfd_add_devices(ab8500->dev, 0, ab9540_devs,
1715d6255529SLinus Walleij 				ARRAY_SIZE(ab9540_devs), NULL,
171655692af5SMark Brown 				ab8500->irq_base, ab8500->domain);
1717c0eda9aeSLee Jones 	else if (is_ab8540(ab8500))
1718c0eda9aeSLee Jones 		ret = mfd_add_devices(ab8500->dev, 0, ab8540_devs,
1719c0eda9aeSLee Jones 			      ARRAY_SIZE(ab8540_devs), NULL,
1720c0eda9aeSLee Jones 			      ab8500->irq_base, ab8500->domain);
1721c0eda9aeSLee Jones 	else if (is_ab8505(ab8500))
1722c0eda9aeSLee Jones 		ret = mfd_add_devices(ab8500->dev, 0, ab8505_devs,
1723c0eda9aeSLee Jones 			      ARRAY_SIZE(ab8505_devs), NULL,
1724c0eda9aeSLee Jones 			      ab8500->irq_base, ab8500->domain);
1725d6255529SLinus Walleij 	else
1726549931f9SSundar R Iyer 		ret = mfd_add_devices(ab8500->dev, 0, ab8500_devs,
172744f72e53SVirupax Sadashivpetimath 				ARRAY_SIZE(ab8500_devs), NULL,
172855692af5SMark Brown 				ab8500->irq_base, ab8500->domain);
17296bc4a568SLee Jones 	if (ret)
17308c4203cbSLee Jones 		return ret;
173144f72e53SVirupax Sadashivpetimath 
17326ef9418cSRickard Andersson 	if (!no_bm) {
17336ef9418cSRickard Andersson 		/* Add battery management devices */
17346ef9418cSRickard Andersson 		ret = mfd_add_devices(ab8500->dev, 0, ab8500_bm_devs,
17356ef9418cSRickard Andersson 				      ARRAY_SIZE(ab8500_bm_devs), NULL,
173655692af5SMark Brown 				      ab8500->irq_base, ab8500->domain);
17376ef9418cSRickard Andersson 		if (ret)
17386ef9418cSRickard Andersson 			dev_err(ab8500->dev, "error adding bm devices\n");
17396ef9418cSRickard Andersson 	}
17406ef9418cSRickard Andersson 
1741e436ddffSLee Jones 	if (((is_ab8505(ab8500) || is_ab9540(ab8500)) &&
1742e436ddffSLee Jones 			ab8500->chip_id >= AB8500_CUT2P0) || is_ab8540(ab8500))
1743d6255529SLinus Walleij 		ret = sysfs_create_group(&ab8500->dev->kobj,
1744d6255529SLinus Walleij 					&ab9540_attr_group);
1745d6255529SLinus Walleij 	else
1746d6255529SLinus Walleij 		ret = sysfs_create_group(&ab8500->dev->kobj,
1747d6255529SLinus Walleij 					&ab8500_attr_group);
1748*93ff722eSLee Jones 
1749*93ff722eSLee Jones 	if ((is_ab8505(ab8500) || is_ab9540(ab8500)) &&
1750*93ff722eSLee Jones 			ab8500->chip_id >= AB8500_CUT2P0)
1751*93ff722eSLee Jones 		ret = sysfs_create_group(&ab8500->dev->kobj,
1752*93ff722eSLee Jones 					 &ab8505_attr_group);
1753*93ff722eSLee Jones 
1754cca69b67SMattias Wallin 	if (ret)
1755cca69b67SMattias Wallin 		dev_err(ab8500->dev, "error creating sysfs entries\n");
175606e589efSLee Jones 
175762579266SRabin Vincent 	return ret;
175862579266SRabin Vincent }
175962579266SRabin Vincent 
17604740f73fSBill Pemberton static int ab8500_remove(struct platform_device *pdev)
176162579266SRabin Vincent {
1762d28f1db8SLee Jones 	struct ab8500 *ab8500 = platform_get_drvdata(pdev);
1763d28f1db8SLee Jones 
1764e436ddffSLee Jones 	if (((is_ab8505(ab8500) || is_ab9540(ab8500)) &&
1765e436ddffSLee Jones 			ab8500->chip_id >= AB8500_CUT2P0) || is_ab8540(ab8500))
1766d6255529SLinus Walleij 		sysfs_remove_group(&ab8500->dev->kobj, &ab9540_attr_group);
1767d6255529SLinus Walleij 	else
1768cca69b67SMattias Wallin 		sysfs_remove_group(&ab8500->dev->kobj, &ab8500_attr_group);
176906e589efSLee Jones 
1770*93ff722eSLee Jones 	if ((is_ab8505(ab8500) || is_ab9540(ab8500)) &&
1771*93ff722eSLee Jones 			ab8500->chip_id >= AB8500_CUT2P0)
1772*93ff722eSLee Jones 		sysfs_remove_group(&ab8500->dev->kobj, &ab8505_attr_group);
1773*93ff722eSLee Jones 
177462579266SRabin Vincent 	mfd_remove_devices(ab8500->dev);
177562579266SRabin Vincent 
177662579266SRabin Vincent 	return 0;
177762579266SRabin Vincent }
177862579266SRabin Vincent 
1779d28f1db8SLee Jones static const struct platform_device_id ab8500_id[] = {
1780d28f1db8SLee Jones 	{ "ab8500-core", AB8500_VERSION_AB8500 },
1781d28f1db8SLee Jones 	{ "ab8505-i2c", AB8500_VERSION_AB8505 },
1782d28f1db8SLee Jones 	{ "ab9540-i2c", AB8500_VERSION_AB9540 },
1783d28f1db8SLee Jones 	{ "ab8540-i2c", AB8500_VERSION_AB8540 },
1784d28f1db8SLee Jones 	{ }
1785d28f1db8SLee Jones };
1786d28f1db8SLee Jones 
1787d28f1db8SLee Jones static struct platform_driver ab8500_core_driver = {
1788d28f1db8SLee Jones 	.driver = {
1789d28f1db8SLee Jones 		.name = "ab8500-core",
1790d28f1db8SLee Jones 		.owner = THIS_MODULE,
1791d28f1db8SLee Jones 	},
1792d28f1db8SLee Jones 	.probe	= ab8500_probe,
179384449216SBill Pemberton 	.remove	= ab8500_remove,
1794d28f1db8SLee Jones 	.id_table = ab8500_id,
1795d28f1db8SLee Jones };
1796d28f1db8SLee Jones 
1797d28f1db8SLee Jones static int __init ab8500_core_init(void)
1798d28f1db8SLee Jones {
1799d28f1db8SLee Jones 	return platform_driver_register(&ab8500_core_driver);
1800d28f1db8SLee Jones }
1801d28f1db8SLee Jones 
1802d28f1db8SLee Jones static void __exit ab8500_core_exit(void)
1803d28f1db8SLee Jones {
1804d28f1db8SLee Jones 	platform_driver_unregister(&ab8500_core_driver);
1805d28f1db8SLee Jones }
1806ba7cbc3eSLee Jones core_initcall(ab8500_core_init);
1807d28f1db8SLee Jones module_exit(ab8500_core_exit);
1808d28f1db8SLee Jones 
1809adceed62SMattias Wallin MODULE_AUTHOR("Mattias Wallin, Srinidhi Kasagar, Rabin Vincent");
181062579266SRabin Vincent MODULE_DESCRIPTION("AB8500 MFD core");
181162579266SRabin Vincent MODULE_LICENSE("GPL v2");
1812