xref: /openbmc/linux/drivers/mfd/ab8500-core.c (revision 3e1a498f2728476535571d270081a17fdfceaf26)
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
106*3e1a498fSLee Jones #define AB8540_IT_LATCHHIER4_REG	0x63
1077ccfe9b1SMichel JAOUEN 
1087ccfe9b1SMichel JAOUEN #define AB8500_IT_LATCHHIER_NUM		3
109*3e1a498fSLee Jones #define AB8540_IT_LATCHHIER_NUM		4
1107ccfe9b1SMichel JAOUEN 
11147c16975SMattias Wallin #define AB8500_REV_REG			0x80
1120f620837SLinus Walleij #define AB8500_IC_NAME_REG		0x82
113e5c238c3SMattias Wallin #define AB8500_SWITCH_OFF_STATUS	0x00
11462579266SRabin Vincent 
115b4a31037SAndrew Lynn #define AB8500_TURN_ON_STATUS		0x00
116b4a31037SAndrew Lynn 
117f04a9d8aSRajkumar Kasirajan #define AB8500_CH_USBCH_STAT1_REG	0x02
118f04a9d8aSRajkumar Kasirajan #define VBUS_DET_DBNC100		0x02
119f04a9d8aSRajkumar Kasirajan #define VBUS_DET_DBNC1			0x01
120f04a9d8aSRajkumar Kasirajan 
121f04a9d8aSRajkumar Kasirajan static DEFINE_SPINLOCK(on_stat_lock);
122f04a9d8aSRajkumar Kasirajan static u8 turn_on_stat_mask = 0xFF;
123f04a9d8aSRajkumar Kasirajan static u8 turn_on_stat_set;
1246ef9418cSRickard Andersson static bool no_bm; /* No battery management */
1256ef9418cSRickard Andersson module_param(no_bm, bool, S_IRUGO);
1266ef9418cSRickard Andersson 
127d6255529SLinus Walleij #define AB9540_MODEM_CTRL2_REG			0x23
128d6255529SLinus Walleij #define AB9540_MODEM_CTRL2_SWDBBRSTN_BIT	BIT(2)
129d6255529SLinus Walleij 
13062579266SRabin Vincent /*
13162579266SRabin Vincent  * Map interrupt numbers to the LATCH and MASK register offsets, Interrupt
1322ced445eSLinus Walleij  * numbers are indexed into this array with (num / 8). The interupts are
1332ced445eSLinus Walleij  * defined in linux/mfd/ab8500.h
13462579266SRabin Vincent  *
13562579266SRabin Vincent  * This is one off from the register names, i.e. AB8500_IT_MASK1_REG is at
13662579266SRabin Vincent  * offset 0.
13762579266SRabin Vincent  */
1382ced445eSLinus Walleij /* AB8500 support */
13962579266SRabin Vincent static const int ab8500_irq_regoffset[AB8500_NUM_IRQ_REGS] = {
14092d50a41SMattias Wallin 	0, 1, 2, 3, 4, 6, 7, 8, 9, 11, 18, 19, 20, 21,
14162579266SRabin Vincent };
14262579266SRabin Vincent 
143a29264b6SLee Jones /* AB9540 / AB8505 support */
144d6255529SLinus Walleij static const int ab9540_irq_regoffset[AB9540_NUM_IRQ_REGS] = {
145a29264b6SLee Jones 	0, 1, 2, 3, 4, 6, 7, 8, 9, 11, 18, 19, 20, 21, 12, 13, 24, 5, 22, 23
146d6255529SLinus Walleij };
147d6255529SLinus Walleij 
148*3e1a498fSLee Jones /* AB8540 support */
149*3e1a498fSLee Jones static const int ab8540_irq_regoffset[AB8540_NUM_IRQ_REGS] = {
150*3e1a498fSLee Jones 	0, 1, 2, 3, 4, -1, -1, -1, -1, 11, 18, 19, 20, 21, 12, 13, 24, 5, 22, 23,
151*3e1a498fSLee Jones 	25, 26, 27, 28, 29, 30, 31,
152*3e1a498fSLee Jones };
153*3e1a498fSLee Jones 
1540f620837SLinus Walleij static const char ab8500_version_str[][7] = {
1550f620837SLinus Walleij 	[AB8500_VERSION_AB8500] = "AB8500",
1560f620837SLinus Walleij 	[AB8500_VERSION_AB8505] = "AB8505",
1570f620837SLinus Walleij 	[AB8500_VERSION_AB9540] = "AB9540",
1580f620837SLinus Walleij 	[AB8500_VERSION_AB8540] = "AB8540",
1590f620837SLinus Walleij };
1600f620837SLinus Walleij 
161822672a7SLee Jones static int ab8500_prcmu_write(struct ab8500 *ab8500, u16 addr, u8 data)
162d28f1db8SLee Jones {
163d28f1db8SLee Jones 	int ret;
164d28f1db8SLee Jones 
165d28f1db8SLee Jones 	ret = prcmu_abb_write((u8)(addr >> 8), (u8)(addr & 0xFF), &data, 1);
166d28f1db8SLee Jones 	if (ret < 0)
167d28f1db8SLee Jones 		dev_err(ab8500->dev, "prcmu i2c error %d\n", ret);
168d28f1db8SLee Jones 	return ret;
169d28f1db8SLee Jones }
170d28f1db8SLee Jones 
171822672a7SLee Jones static int ab8500_prcmu_write_masked(struct ab8500 *ab8500, u16 addr, u8 mask,
172d28f1db8SLee Jones 	u8 data)
173d28f1db8SLee Jones {
174d28f1db8SLee Jones 	int ret;
175d28f1db8SLee Jones 
176d28f1db8SLee Jones 	ret = prcmu_abb_write_masked((u8)(addr >> 8), (u8)(addr & 0xFF), &data,
177d28f1db8SLee Jones 		&mask, 1);
178d28f1db8SLee Jones 	if (ret < 0)
179d28f1db8SLee Jones 		dev_err(ab8500->dev, "prcmu i2c error %d\n", ret);
180d28f1db8SLee Jones 	return ret;
181d28f1db8SLee Jones }
182d28f1db8SLee Jones 
183822672a7SLee Jones static int ab8500_prcmu_read(struct ab8500 *ab8500, u16 addr)
184d28f1db8SLee Jones {
185d28f1db8SLee Jones 	int ret;
186d28f1db8SLee Jones 	u8 data;
187d28f1db8SLee Jones 
188d28f1db8SLee Jones 	ret = prcmu_abb_read((u8)(addr >> 8), (u8)(addr & 0xFF), &data, 1);
189d28f1db8SLee Jones 	if (ret < 0) {
190d28f1db8SLee Jones 		dev_err(ab8500->dev, "prcmu i2c error %d\n", ret);
191d28f1db8SLee Jones 		return ret;
192d28f1db8SLee Jones 	}
193d28f1db8SLee Jones 	return (int)data;
194d28f1db8SLee Jones }
195d28f1db8SLee Jones 
19647c16975SMattias Wallin static int ab8500_get_chip_id(struct device *dev)
19747c16975SMattias Wallin {
1986bce7bf1SMattias Wallin 	struct ab8500 *ab8500;
1996bce7bf1SMattias Wallin 
2006bce7bf1SMattias Wallin 	if (!dev)
2016bce7bf1SMattias Wallin 		return -EINVAL;
2026bce7bf1SMattias Wallin 	ab8500 = dev_get_drvdata(dev->parent);
2036bce7bf1SMattias Wallin 	return ab8500 ? (int)ab8500->chip_id : -EINVAL;
20447c16975SMattias Wallin }
20547c16975SMattias Wallin 
20647c16975SMattias Wallin static int set_register_interruptible(struct ab8500 *ab8500, u8 bank,
20747c16975SMattias Wallin 	u8 reg, u8 data)
20862579266SRabin Vincent {
20962579266SRabin Vincent 	int ret;
21047c16975SMattias Wallin 	/*
21147c16975SMattias Wallin 	 * Put the u8 bank and u8 register together into a an u16.
21247c16975SMattias Wallin 	 * The bank on higher 8 bits and register in lower 8 bits.
21347c16975SMattias Wallin 	 * */
21447c16975SMattias Wallin 	u16 addr = ((u16)bank) << 8 | reg;
21562579266SRabin Vincent 
21662579266SRabin Vincent 	dev_vdbg(ab8500->dev, "wr: addr %#x <= %#x\n", addr, data);
21762579266SRabin Vincent 
218392cbd1eSRabin Vincent 	mutex_lock(&ab8500->lock);
21947c16975SMattias Wallin 
22047c16975SMattias Wallin 	ret = ab8500->write(ab8500, addr, data);
22147c16975SMattias Wallin 	if (ret < 0)
22247c16975SMattias Wallin 		dev_err(ab8500->dev, "failed to write reg %#x: %d\n",
22347c16975SMattias Wallin 			addr, ret);
22447c16975SMattias Wallin 	mutex_unlock(&ab8500->lock);
22547c16975SMattias Wallin 
22647c16975SMattias Wallin 	return ret;
22747c16975SMattias Wallin }
22847c16975SMattias Wallin 
22947c16975SMattias Wallin static int ab8500_set_register(struct device *dev, u8 bank,
23047c16975SMattias Wallin 	u8 reg, u8 value)
23147c16975SMattias Wallin {
232112a80d2SJonas Aaberg 	int ret;
23347c16975SMattias Wallin 	struct ab8500 *ab8500 = dev_get_drvdata(dev->parent);
23447c16975SMattias Wallin 
235112a80d2SJonas Aaberg 	atomic_inc(&ab8500->transfer_ongoing);
236112a80d2SJonas Aaberg 	ret = set_register_interruptible(ab8500, bank, reg, value);
237112a80d2SJonas Aaberg 	atomic_dec(&ab8500->transfer_ongoing);
238112a80d2SJonas Aaberg 	return ret;
23947c16975SMattias Wallin }
24047c16975SMattias Wallin 
24147c16975SMattias Wallin static int get_register_interruptible(struct ab8500 *ab8500, u8 bank,
24247c16975SMattias Wallin 	u8 reg, u8 *value)
24347c16975SMattias Wallin {
24447c16975SMattias Wallin 	int ret;
24547c16975SMattias Wallin 	/* put the u8 bank and u8 reg together into a an u16.
24647c16975SMattias Wallin 	 * bank on higher 8 bits and reg in lower */
24747c16975SMattias Wallin 	u16 addr = ((u16)bank) << 8 | reg;
24847c16975SMattias Wallin 
249392cbd1eSRabin Vincent 	mutex_lock(&ab8500->lock);
25047c16975SMattias Wallin 
25147c16975SMattias Wallin 	ret = ab8500->read(ab8500, addr);
25247c16975SMattias Wallin 	if (ret < 0)
25347c16975SMattias Wallin 		dev_err(ab8500->dev, "failed to read reg %#x: %d\n",
25447c16975SMattias Wallin 			addr, ret);
25547c16975SMattias Wallin 	else
25647c16975SMattias Wallin 		*value = ret;
25747c16975SMattias Wallin 
25847c16975SMattias Wallin 	mutex_unlock(&ab8500->lock);
25947c16975SMattias Wallin 	dev_vdbg(ab8500->dev, "rd: addr %#x => data %#x\n", addr, ret);
26047c16975SMattias Wallin 
26147c16975SMattias Wallin 	return ret;
26247c16975SMattias Wallin }
26347c16975SMattias Wallin 
26447c16975SMattias Wallin static int ab8500_get_register(struct device *dev, u8 bank,
26547c16975SMattias Wallin 	u8 reg, u8 *value)
26647c16975SMattias Wallin {
267112a80d2SJonas Aaberg 	int ret;
26847c16975SMattias Wallin 	struct ab8500 *ab8500 = dev_get_drvdata(dev->parent);
26947c16975SMattias Wallin 
270112a80d2SJonas Aaberg 	atomic_inc(&ab8500->transfer_ongoing);
271112a80d2SJonas Aaberg 	ret = get_register_interruptible(ab8500, bank, reg, value);
272112a80d2SJonas Aaberg 	atomic_dec(&ab8500->transfer_ongoing);
273112a80d2SJonas Aaberg 	return ret;
27447c16975SMattias Wallin }
27547c16975SMattias Wallin 
27647c16975SMattias Wallin static int mask_and_set_register_interruptible(struct ab8500 *ab8500, u8 bank,
27747c16975SMattias Wallin 	u8 reg, u8 bitmask, u8 bitvalues)
27847c16975SMattias Wallin {
27947c16975SMattias Wallin 	int ret;
28047c16975SMattias Wallin 	/* put the u8 bank and u8 reg together into a an u16.
28147c16975SMattias Wallin 	 * bank on higher 8 bits and reg in lower */
28247c16975SMattias Wallin 	u16 addr = ((u16)bank) << 8 | reg;
28347c16975SMattias Wallin 
284392cbd1eSRabin Vincent 	mutex_lock(&ab8500->lock);
28547c16975SMattias Wallin 
286bc628fd1SMattias Nilsson 	if (ab8500->write_masked == NULL) {
287bc628fd1SMattias Nilsson 		u8 data;
288bc628fd1SMattias Nilsson 
28947c16975SMattias Wallin 		ret = ab8500->read(ab8500, addr);
29047c16975SMattias Wallin 		if (ret < 0) {
29147c16975SMattias Wallin 			dev_err(ab8500->dev, "failed to read reg %#x: %d\n",
29247c16975SMattias Wallin 				addr, ret);
29347c16975SMattias Wallin 			goto out;
29447c16975SMattias Wallin 		}
29547c16975SMattias Wallin 
29647c16975SMattias Wallin 		data = (u8)ret;
29747c16975SMattias Wallin 		data = (~bitmask & data) | (bitmask & bitvalues);
29847c16975SMattias Wallin 
29962579266SRabin Vincent 		ret = ab8500->write(ab8500, addr, data);
30062579266SRabin Vincent 		if (ret < 0)
30162579266SRabin Vincent 			dev_err(ab8500->dev, "failed to write reg %#x: %d\n",
30262579266SRabin Vincent 				addr, ret);
30362579266SRabin Vincent 
304bc628fd1SMattias Nilsson 		dev_vdbg(ab8500->dev, "mask: addr %#x => data %#x\n", addr,
305bc628fd1SMattias Nilsson 			data);
306bc628fd1SMattias Nilsson 		goto out;
307bc628fd1SMattias Nilsson 	}
308bc628fd1SMattias Nilsson 	ret = ab8500->write_masked(ab8500, addr, bitmask, bitvalues);
309bc628fd1SMattias Nilsson 	if (ret < 0)
310bc628fd1SMattias Nilsson 		dev_err(ab8500->dev, "failed to modify reg %#x: %d\n", addr,
311bc628fd1SMattias Nilsson 			ret);
31262579266SRabin Vincent out:
31362579266SRabin Vincent 	mutex_unlock(&ab8500->lock);
31462579266SRabin Vincent 	return ret;
31562579266SRabin Vincent }
31647c16975SMattias Wallin 
31747c16975SMattias Wallin static int ab8500_mask_and_set_register(struct device *dev,
31847c16975SMattias Wallin 	u8 bank, u8 reg, u8 bitmask, u8 bitvalues)
31947c16975SMattias Wallin {
320112a80d2SJonas Aaberg 	int ret;
32147c16975SMattias Wallin 	struct ab8500 *ab8500 = dev_get_drvdata(dev->parent);
32247c16975SMattias Wallin 
323112a80d2SJonas Aaberg 	atomic_inc(&ab8500->transfer_ongoing);
324112a80d2SJonas Aaberg 	ret= mask_and_set_register_interruptible(ab8500, bank, reg,
32547c16975SMattias Wallin 						 bitmask, bitvalues);
326112a80d2SJonas Aaberg 	atomic_dec(&ab8500->transfer_ongoing);
327112a80d2SJonas Aaberg 	return ret;
32847c16975SMattias Wallin }
32947c16975SMattias Wallin 
33047c16975SMattias Wallin static struct abx500_ops ab8500_ops = {
33147c16975SMattias Wallin 	.get_chip_id = ab8500_get_chip_id,
33247c16975SMattias Wallin 	.get_register = ab8500_get_register,
33347c16975SMattias Wallin 	.set_register = ab8500_set_register,
33447c16975SMattias Wallin 	.get_register_page = NULL,
33547c16975SMattias Wallin 	.set_register_page = NULL,
33647c16975SMattias Wallin 	.mask_and_set_register = ab8500_mask_and_set_register,
33747c16975SMattias Wallin 	.event_registers_startup_state_get = NULL,
33847c16975SMattias Wallin 	.startup_irq_enabled = NULL,
3391d843a6cSMian Yousaf Kaukab 	.dump_all_banks = ab8500_dump_all_banks,
34047c16975SMattias Wallin };
34162579266SRabin Vincent 
3429505a0a0SMark Brown static void ab8500_irq_lock(struct irq_data *data)
34362579266SRabin Vincent {
3449505a0a0SMark Brown 	struct ab8500 *ab8500 = irq_data_get_irq_chip_data(data);
34562579266SRabin Vincent 
34662579266SRabin Vincent 	mutex_lock(&ab8500->irq_lock);
347112a80d2SJonas Aaberg 	atomic_inc(&ab8500->transfer_ongoing);
34862579266SRabin Vincent }
34962579266SRabin Vincent 
3509505a0a0SMark Brown static void ab8500_irq_sync_unlock(struct irq_data *data)
35162579266SRabin Vincent {
3529505a0a0SMark Brown 	struct ab8500 *ab8500 = irq_data_get_irq_chip_data(data);
35362579266SRabin Vincent 	int i;
35462579266SRabin Vincent 
3552ced445eSLinus Walleij 	for (i = 0; i < ab8500->mask_size; i++) {
35662579266SRabin Vincent 		u8 old = ab8500->oldmask[i];
35762579266SRabin Vincent 		u8 new = ab8500->mask[i];
35862579266SRabin Vincent 		int reg;
35962579266SRabin Vincent 
36062579266SRabin Vincent 		if (new == old)
36162579266SRabin Vincent 			continue;
36262579266SRabin Vincent 
3630f620837SLinus Walleij 		/*
3640f620837SLinus Walleij 		 * Interrupt register 12 doesn't exist prior to AB8500 version
3650f620837SLinus Walleij 		 * 2.0
3660f620837SLinus Walleij 		 */
3670f620837SLinus Walleij 		if (ab8500->irq_reg_offset[i] == 11 &&
3680f620837SLinus Walleij 			is_ab8500_1p1_or_earlier(ab8500))
36992d50a41SMattias Wallin 			continue;
37092d50a41SMattias Wallin 
371*3e1a498fSLee Jones 		if (ab8500->irq_reg_offset[i] < 0)
372*3e1a498fSLee Jones 			continue;
373*3e1a498fSLee Jones 
37462579266SRabin Vincent 		ab8500->oldmask[i] = new;
37562579266SRabin Vincent 
3762ced445eSLinus Walleij 		reg = AB8500_IT_MASK1_REG + ab8500->irq_reg_offset[i];
37747c16975SMattias Wallin 		set_register_interruptible(ab8500, AB8500_INTERRUPT, reg, new);
37862579266SRabin Vincent 	}
379112a80d2SJonas Aaberg 	atomic_dec(&ab8500->transfer_ongoing);
38062579266SRabin Vincent 	mutex_unlock(&ab8500->irq_lock);
38162579266SRabin Vincent }
38262579266SRabin Vincent 
3839505a0a0SMark Brown static void ab8500_irq_mask(struct irq_data *data)
38462579266SRabin Vincent {
3859505a0a0SMark Brown 	struct ab8500 *ab8500 = irq_data_get_irq_chip_data(data);
38606e589efSLee Jones 	int offset = data->hwirq;
38762579266SRabin Vincent 	int index = offset / 8;
38862579266SRabin Vincent 	int mask = 1 << (offset % 8);
38962579266SRabin Vincent 
39062579266SRabin Vincent 	ab8500->mask[index] |= mask;
3919c677b9bSLee Jones 
3929c677b9bSLee Jones 	/* The AB8500 GPIOs have two interrupts each (rising & falling). */
3939c677b9bSLee Jones 	if (offset >= AB8500_INT_GPIO6R && offset <= AB8500_INT_GPIO41R)
3949c677b9bSLee Jones 		ab8500->mask[index + 2] |= mask;
3959c677b9bSLee Jones 	if (offset >= AB9540_INT_GPIO50R && offset <= AB9540_INT_GPIO54R)
3969c677b9bSLee Jones 		ab8500->mask[index + 1] |= mask;
3979c677b9bSLee Jones 	if (offset == AB8540_INT_GPIO43R || offset == AB8540_INT_GPIO44R)
398e2ddf46aSLinus Walleij 		/* Here the falling IRQ is one bit lower */
399e2ddf46aSLinus Walleij 		ab8500->mask[index] |= (mask << 1);
40062579266SRabin Vincent }
40162579266SRabin Vincent 
4029505a0a0SMark Brown static void ab8500_irq_unmask(struct irq_data *data)
40362579266SRabin Vincent {
4049505a0a0SMark Brown 	struct ab8500 *ab8500 = irq_data_get_irq_chip_data(data);
4059c677b9bSLee Jones 	unsigned int type = irqd_get_trigger_type(data);
40606e589efSLee Jones 	int offset = data->hwirq;
40762579266SRabin Vincent 	int index = offset / 8;
40862579266SRabin Vincent 	int mask = 1 << (offset % 8);
40962579266SRabin Vincent 
4109c677b9bSLee Jones 	if (type & IRQ_TYPE_EDGE_RISING)
41162579266SRabin Vincent 		ab8500->mask[index] &= ~mask;
4129c677b9bSLee Jones 
4139c677b9bSLee Jones 	/* The AB8500 GPIOs have two interrupts each (rising & falling). */
4149c677b9bSLee Jones 	if (type & IRQ_TYPE_EDGE_FALLING) {
4159c677b9bSLee Jones 		if (offset >= AB8500_INT_GPIO6R && offset <= AB8500_INT_GPIO41R)
4169c677b9bSLee Jones 			ab8500->mask[index + 2] &= ~mask;
4179c677b9bSLee Jones 		else if (offset >= AB9540_INT_GPIO50R && offset <= AB9540_INT_GPIO54R)
4189c677b9bSLee Jones 			ab8500->mask[index + 1] &= ~mask;
4199c677b9bSLee Jones 		else if (offset == AB8540_INT_GPIO43R || offset == AB8540_INT_GPIO44R)
420e2ddf46aSLinus Walleij 			/* Here the falling IRQ is one bit lower */
421e2ddf46aSLinus Walleij 			ab8500->mask[index] &= ~(mask << 1);
4229c677b9bSLee Jones 		else
4239c677b9bSLee Jones 			ab8500->mask[index] &= ~mask;
424e2ddf46aSLinus Walleij 	} else {
4259c677b9bSLee Jones 		/* Satisfies the case where type is not set. */
42662579266SRabin Vincent 		ab8500->mask[index] &= ~mask;
42762579266SRabin Vincent 	}
428e2ddf46aSLinus Walleij }
42962579266SRabin Vincent 
43040f6e5a2SLee Jones static int ab8500_irq_set_type(struct irq_data *data, unsigned int type)
43140f6e5a2SLee Jones {
43240f6e5a2SLee Jones 	return 0;
43362579266SRabin Vincent }
43462579266SRabin Vincent 
43562579266SRabin Vincent static struct irq_chip ab8500_irq_chip = {
43662579266SRabin Vincent 	.name			= "ab8500",
4379505a0a0SMark Brown 	.irq_bus_lock		= ab8500_irq_lock,
4389505a0a0SMark Brown 	.irq_bus_sync_unlock	= ab8500_irq_sync_unlock,
4399505a0a0SMark Brown 	.irq_mask		= ab8500_irq_mask,
440e6f9306eSVirupax Sadashivpetimath 	.irq_disable		= ab8500_irq_mask,
4419505a0a0SMark Brown 	.irq_unmask		= ab8500_irq_unmask,
44240f6e5a2SLee Jones 	.irq_set_type		= ab8500_irq_set_type,
44362579266SRabin Vincent };
44462579266SRabin Vincent 
445*3e1a498fSLee Jones static void update_latch_offset(u8 *offset, int i)
446*3e1a498fSLee Jones {
447*3e1a498fSLee Jones 	/* Fix inconsistent ITFromLatch25 bit mapping... */
448*3e1a498fSLee Jones 	if (unlikely(*offset == 17))
449*3e1a498fSLee Jones 			*offset = 24;
450*3e1a498fSLee Jones 	/* Fix inconsistent ab8540 bit mapping... */
451*3e1a498fSLee Jones 	if (unlikely(*offset == 16))
452*3e1a498fSLee Jones 			*offset = 25;
453*3e1a498fSLee Jones 	if ((i==3) && (*offset >= 24))
454*3e1a498fSLee Jones 			*offset += 2;
455*3e1a498fSLee Jones }
456*3e1a498fSLee Jones 
4577ccfe9b1SMichel JAOUEN static int ab8500_handle_hierarchical_line(struct ab8500 *ab8500,
4587ccfe9b1SMichel JAOUEN 					int latch_offset, u8 latch_val)
4597ccfe9b1SMichel JAOUEN {
4607ccfe9b1SMichel JAOUEN 	int int_bit = __ffs(latch_val);
4617ccfe9b1SMichel JAOUEN 	int line, i;
4627ccfe9b1SMichel JAOUEN 
4637ccfe9b1SMichel JAOUEN 	do {
4647ccfe9b1SMichel JAOUEN 		int_bit = __ffs(latch_val);
4657ccfe9b1SMichel JAOUEN 
4667ccfe9b1SMichel JAOUEN 		for (i = 0; i < ab8500->mask_size; i++)
4677ccfe9b1SMichel JAOUEN 			if (ab8500->irq_reg_offset[i] == latch_offset)
4687ccfe9b1SMichel JAOUEN 				break;
4697ccfe9b1SMichel JAOUEN 
4707ccfe9b1SMichel JAOUEN 		if (i >= ab8500->mask_size) {
4717ccfe9b1SMichel JAOUEN 			dev_err(ab8500->dev, "Register offset 0x%2x not declared\n",
4727ccfe9b1SMichel JAOUEN 					latch_offset);
4737ccfe9b1SMichel JAOUEN 			return -ENXIO;
4747ccfe9b1SMichel JAOUEN 		}
4757ccfe9b1SMichel JAOUEN 
4767ccfe9b1SMichel JAOUEN 		line = (i << 3) + int_bit;
4777ccfe9b1SMichel JAOUEN 		latch_val &= ~(1 << int_bit);
4787ccfe9b1SMichel JAOUEN 
479e2ddf46aSLinus Walleij 		/*
480e2ddf46aSLinus Walleij 		 * This handles the falling edge hwirqs from the GPIO
481e2ddf46aSLinus Walleij 		 * lines. Route them back to the line registered for the
482e2ddf46aSLinus Walleij 		 * rising IRQ, as this is merely a flag for the same IRQ
483e2ddf46aSLinus Walleij 		 * in linux terms.
484e2ddf46aSLinus Walleij 		 */
485e2ddf46aSLinus Walleij 		if (line >= AB8500_INT_GPIO6F && line <= AB8500_INT_GPIO41F)
486e2ddf46aSLinus Walleij 			line -= 16;
487e2ddf46aSLinus Walleij 		if (line >= AB9540_INT_GPIO50F && line <= AB9540_INT_GPIO54F)
488e2ddf46aSLinus Walleij 			line -= 8;
489e2ddf46aSLinus Walleij 		if (line == AB8540_INT_GPIO43F || line == AB8540_INT_GPIO44F)
490e2ddf46aSLinus Walleij 			line += 1;
491e2ddf46aSLinus Walleij 
4927ccfe9b1SMichel JAOUEN 		handle_nested_irq(ab8500->irq_base + line);
4937ccfe9b1SMichel JAOUEN 	} while (latch_val);
4947ccfe9b1SMichel JAOUEN 
4957ccfe9b1SMichel JAOUEN 	return 0;
4967ccfe9b1SMichel JAOUEN }
4977ccfe9b1SMichel JAOUEN 
4987ccfe9b1SMichel JAOUEN static int ab8500_handle_hierarchical_latch(struct ab8500 *ab8500,
4997ccfe9b1SMichel JAOUEN 					int hier_offset, u8 hier_val)
5007ccfe9b1SMichel JAOUEN {
5017ccfe9b1SMichel JAOUEN 	int latch_bit, status;
5027ccfe9b1SMichel JAOUEN 	u8 latch_offset, latch_val;
5037ccfe9b1SMichel JAOUEN 
5047ccfe9b1SMichel JAOUEN 	do {
5057ccfe9b1SMichel JAOUEN 		latch_bit = __ffs(hier_val);
5067ccfe9b1SMichel JAOUEN 		latch_offset = (hier_offset << 3) + latch_bit;
5077ccfe9b1SMichel JAOUEN 
508*3e1a498fSLee Jones 		update_latch_offset(&latch_offset, hier_offset);
5097ccfe9b1SMichel JAOUEN 
5107ccfe9b1SMichel JAOUEN 		status = get_register_interruptible(ab8500,
5117ccfe9b1SMichel JAOUEN 				AB8500_INTERRUPT,
5127ccfe9b1SMichel JAOUEN 				AB8500_IT_LATCH1_REG + latch_offset,
5137ccfe9b1SMichel JAOUEN 				&latch_val);
5147ccfe9b1SMichel JAOUEN 		if (status < 0 || latch_val == 0)
5157ccfe9b1SMichel JAOUEN 			goto discard;
5167ccfe9b1SMichel JAOUEN 
5177ccfe9b1SMichel JAOUEN 		status = ab8500_handle_hierarchical_line(ab8500,
5187ccfe9b1SMichel JAOUEN 				latch_offset, latch_val);
5197ccfe9b1SMichel JAOUEN 		if (status < 0)
5207ccfe9b1SMichel JAOUEN 			return status;
5217ccfe9b1SMichel JAOUEN discard:
5227ccfe9b1SMichel JAOUEN 		hier_val &= ~(1 << latch_bit);
5237ccfe9b1SMichel JAOUEN 	} while (hier_val);
5247ccfe9b1SMichel JAOUEN 
5257ccfe9b1SMichel JAOUEN 	return 0;
5267ccfe9b1SMichel JAOUEN }
5277ccfe9b1SMichel JAOUEN 
5287ccfe9b1SMichel JAOUEN static irqreturn_t ab8500_hierarchical_irq(int irq, void *dev)
5297ccfe9b1SMichel JAOUEN {
5307ccfe9b1SMichel JAOUEN 	struct ab8500 *ab8500 = dev;
5317ccfe9b1SMichel JAOUEN 	u8 i;
5327ccfe9b1SMichel JAOUEN 
5337ccfe9b1SMichel JAOUEN 	dev_vdbg(ab8500->dev, "interrupt\n");
5347ccfe9b1SMichel JAOUEN 
5357ccfe9b1SMichel JAOUEN 	/*  Hierarchical interrupt version */
536*3e1a498fSLee Jones 	for (i = 0; i < (ab8500->it_latchhier_num); i++) {
5377ccfe9b1SMichel JAOUEN 		int status;
5387ccfe9b1SMichel JAOUEN 		u8 hier_val;
5397ccfe9b1SMichel JAOUEN 
5407ccfe9b1SMichel JAOUEN 		status = get_register_interruptible(ab8500, AB8500_INTERRUPT,
5417ccfe9b1SMichel JAOUEN 			AB8500_IT_LATCHHIER1_REG + i, &hier_val);
5427ccfe9b1SMichel JAOUEN 		if (status < 0 || hier_val == 0)
5437ccfe9b1SMichel JAOUEN 			continue;
5447ccfe9b1SMichel JAOUEN 
5457ccfe9b1SMichel JAOUEN 		status = ab8500_handle_hierarchical_latch(ab8500, i, hier_val);
5467ccfe9b1SMichel JAOUEN 		if (status < 0)
5477ccfe9b1SMichel JAOUEN 			break;
5487ccfe9b1SMichel JAOUEN 	}
5497ccfe9b1SMichel JAOUEN 	return IRQ_HANDLED;
5507ccfe9b1SMichel JAOUEN }
5517ccfe9b1SMichel JAOUEN 
55280633f05SLee Jones /**
55380633f05SLee Jones  * ab8500_irq_get_virq(): Map an interrupt on a chip to a virtual IRQ
55480633f05SLee Jones  *
55580633f05SLee Jones  * @ab8500: ab8500_irq controller to operate on.
55680633f05SLee Jones  * @irq: index of the interrupt requested in the chip IRQs
55780633f05SLee Jones  *
55880633f05SLee Jones  * Useful for drivers to request their own IRQs.
55980633f05SLee Jones  */
56080633f05SLee Jones static int ab8500_irq_get_virq(struct ab8500 *ab8500, int irq)
56180633f05SLee Jones {
56280633f05SLee Jones 	if (!ab8500)
56380633f05SLee Jones 		return -EINVAL;
56480633f05SLee Jones 
56580633f05SLee Jones 	return irq_create_mapping(ab8500->domain, irq);
56680633f05SLee Jones }
56780633f05SLee Jones 
56862579266SRabin Vincent static irqreturn_t ab8500_irq(int irq, void *dev)
56962579266SRabin Vincent {
57062579266SRabin Vincent 	struct ab8500 *ab8500 = dev;
57162579266SRabin Vincent 	int i;
57262579266SRabin Vincent 
57362579266SRabin Vincent 	dev_vdbg(ab8500->dev, "interrupt\n");
57462579266SRabin Vincent 
575112a80d2SJonas Aaberg 	atomic_inc(&ab8500->transfer_ongoing);
576112a80d2SJonas Aaberg 
5772ced445eSLinus Walleij 	for (i = 0; i < ab8500->mask_size; i++) {
5782ced445eSLinus Walleij 		int regoffset = ab8500->irq_reg_offset[i];
57962579266SRabin Vincent 		int status;
58047c16975SMattias Wallin 		u8 value;
58162579266SRabin Vincent 
5820f620837SLinus Walleij 		/*
5830f620837SLinus Walleij 		 * Interrupt register 12 doesn't exist prior to AB8500 version
5840f620837SLinus Walleij 		 * 2.0
5850f620837SLinus Walleij 		 */
5860f620837SLinus Walleij 		if (regoffset == 11 && is_ab8500_1p1_or_earlier(ab8500))
58792d50a41SMattias Wallin 			continue;
58892d50a41SMattias Wallin 
589*3e1a498fSLee Jones 		if (regoffset < 0)
590*3e1a498fSLee Jones 			continue;
591*3e1a498fSLee Jones 
59247c16975SMattias Wallin 		status = get_register_interruptible(ab8500, AB8500_INTERRUPT,
59347c16975SMattias Wallin 			AB8500_IT_LATCH1_REG + regoffset, &value);
59447c16975SMattias Wallin 		if (status < 0 || value == 0)
59562579266SRabin Vincent 			continue;
59662579266SRabin Vincent 
59762579266SRabin Vincent 		do {
59888aec4f7SMattias Wallin 			int bit = __ffs(value);
59962579266SRabin Vincent 			int line = i * 8 + bit;
6000a37fc56SLee Jones 			int virq = ab8500_irq_get_virq(ab8500, line);
60162579266SRabin Vincent 
6020a37fc56SLee Jones 			handle_nested_irq(virq);
6038f0eb43bSBengt Jonsson 			ab8500_debug_register_interrupt(line);
60447c16975SMattias Wallin 			value &= ~(1 << bit);
605112a80d2SJonas Aaberg 
60647c16975SMattias Wallin 		} while (value);
60762579266SRabin Vincent 	}
608112a80d2SJonas Aaberg 	atomic_dec(&ab8500->transfer_ongoing);
60962579266SRabin Vincent 	return IRQ_HANDLED;
61062579266SRabin Vincent }
61162579266SRabin Vincent 
61206e589efSLee Jones static int ab8500_irq_map(struct irq_domain *d, unsigned int virq,
61306e589efSLee Jones 				irq_hw_number_t hwirq)
61406e589efSLee Jones {
61506e589efSLee Jones 	struct ab8500 *ab8500 = d->host_data;
61606e589efSLee Jones 
61706e589efSLee Jones 	if (!ab8500)
61806e589efSLee Jones 		return -EINVAL;
61906e589efSLee Jones 
62006e589efSLee Jones 	irq_set_chip_data(virq, ab8500);
62106e589efSLee Jones 	irq_set_chip_and_handler(virq, &ab8500_irq_chip,
62206e589efSLee Jones 				handle_simple_irq);
62306e589efSLee Jones 	irq_set_nested_thread(virq, 1);
62406e589efSLee Jones #ifdef CONFIG_ARM
62506e589efSLee Jones 	set_irq_flags(virq, IRQF_VALID);
62606e589efSLee Jones #else
62706e589efSLee Jones 	irq_set_noprobe(virq);
62806e589efSLee Jones #endif
62962579266SRabin Vincent 
63062579266SRabin Vincent 	return 0;
63162579266SRabin Vincent }
63262579266SRabin Vincent 
63306e589efSLee Jones static struct irq_domain_ops ab8500_irq_ops = {
63406e589efSLee Jones         .map    = ab8500_irq_map,
63506e589efSLee Jones         .xlate  = irq_domain_xlate_twocell,
63606e589efSLee Jones };
63706e589efSLee Jones 
63806e589efSLee Jones static int ab8500_irq_init(struct ab8500 *ab8500, struct device_node *np)
63962579266SRabin Vincent {
6402ced445eSLinus Walleij 	int num_irqs;
64162579266SRabin Vincent 
642*3e1a498fSLee Jones 	if (is_ab8540(ab8500))
643*3e1a498fSLee Jones 		num_irqs = AB8540_NR_IRQS;
644*3e1a498fSLee Jones 	else if (is_ab9540(ab8500))
645d6255529SLinus Walleij 		num_irqs = AB9540_NR_IRQS;
646a982362cSBengt Jonsson 	else if (is_ab8505(ab8500))
647a982362cSBengt Jonsson 		num_irqs = AB8505_NR_IRQS;
648d6255529SLinus Walleij 	else
6492ced445eSLinus Walleij 		num_irqs = AB8500_NR_IRQS;
6502ced445eSLinus Walleij 
651f1d11f39SLinus Walleij 	/* If ->irq_base is zero this will give a linear mapping */
652f1d11f39SLinus Walleij 	ab8500->domain = irq_domain_add_simple(NULL,
653f1d11f39SLinus Walleij 			num_irqs, ab8500->irq_base,
654f1d11f39SLinus Walleij 			&ab8500_irq_ops, ab8500);
65506e589efSLee Jones 
65606e589efSLee Jones 	if (!ab8500->domain) {
65706e589efSLee Jones 		dev_err(ab8500->dev, "Failed to create irqdomain\n");
65806e589efSLee Jones 		return -ENOSYS;
65906e589efSLee Jones 	}
66006e589efSLee Jones 
66106e589efSLee Jones 	return 0;
66262579266SRabin Vincent }
66362579266SRabin Vincent 
664112a80d2SJonas Aaberg int ab8500_suspend(struct ab8500 *ab8500)
665112a80d2SJonas Aaberg {
666112a80d2SJonas Aaberg 	if (atomic_read(&ab8500->transfer_ongoing))
667112a80d2SJonas Aaberg 		return -EINVAL;
668112a80d2SJonas Aaberg 	else
669112a80d2SJonas Aaberg 		return 0;
670112a80d2SJonas Aaberg }
671112a80d2SJonas Aaberg 
672a9e9ce4cSBill Pemberton static struct resource ab8500_gpadc_resources[] = {
67362579266SRabin Vincent 	{
67462579266SRabin Vincent 		.name	= "HW_CONV_END",
67562579266SRabin Vincent 		.start	= AB8500_INT_GP_HW_ADC_CONV_END,
67662579266SRabin Vincent 		.end	= AB8500_INT_GP_HW_ADC_CONV_END,
67762579266SRabin Vincent 		.flags	= IORESOURCE_IRQ,
67862579266SRabin Vincent 	},
67962579266SRabin Vincent 	{
68062579266SRabin Vincent 		.name	= "SW_CONV_END",
68162579266SRabin Vincent 		.start	= AB8500_INT_GP_SW_ADC_CONV_END,
68262579266SRabin Vincent 		.end	= AB8500_INT_GP_SW_ADC_CONV_END,
68362579266SRabin Vincent 		.flags	= IORESOURCE_IRQ,
68462579266SRabin Vincent 	},
68562579266SRabin Vincent };
68662579266SRabin Vincent 
6874b106fb9SLee Jones static struct resource ab8505_gpadc_resources[] = {
688c0eda9aeSLee Jones 	{
689c0eda9aeSLee Jones 		.name	= "SW_CONV_END",
690c0eda9aeSLee Jones 		.start	= AB8500_INT_GP_SW_ADC_CONV_END,
691c0eda9aeSLee Jones 		.end	= AB8500_INT_GP_SW_ADC_CONV_END,
692c0eda9aeSLee Jones 		.flags	= IORESOURCE_IRQ,
693c0eda9aeSLee Jones 	},
694c0eda9aeSLee Jones };
695c0eda9aeSLee Jones 
696a9e9ce4cSBill Pemberton static struct resource ab8500_rtc_resources[] = {
69762579266SRabin Vincent 	{
69862579266SRabin Vincent 		.name	= "60S",
69962579266SRabin Vincent 		.start	= AB8500_INT_RTC_60S,
70062579266SRabin Vincent 		.end	= AB8500_INT_RTC_60S,
70162579266SRabin Vincent 		.flags	= IORESOURCE_IRQ,
70262579266SRabin Vincent 	},
70362579266SRabin Vincent 	{
70462579266SRabin Vincent 		.name	= "ALARM",
70562579266SRabin Vincent 		.start	= AB8500_INT_RTC_ALARM,
70662579266SRabin Vincent 		.end	= AB8500_INT_RTC_ALARM,
70762579266SRabin Vincent 		.flags	= IORESOURCE_IRQ,
70862579266SRabin Vincent 	},
70962579266SRabin Vincent };
71062579266SRabin Vincent 
711a9e9ce4cSBill Pemberton static struct resource ab8500_poweronkey_db_resources[] = {
71277686517SSundar R Iyer 	{
71377686517SSundar R Iyer 		.name	= "ONKEY_DBF",
71477686517SSundar R Iyer 		.start	= AB8500_INT_PON_KEY1DB_F,
71577686517SSundar R Iyer 		.end	= AB8500_INT_PON_KEY1DB_F,
71677686517SSundar R Iyer 		.flags	= IORESOURCE_IRQ,
71777686517SSundar R Iyer 	},
71877686517SSundar R Iyer 	{
71977686517SSundar R Iyer 		.name	= "ONKEY_DBR",
72077686517SSundar R Iyer 		.start	= AB8500_INT_PON_KEY1DB_R,
72177686517SSundar R Iyer 		.end	= AB8500_INT_PON_KEY1DB_R,
72277686517SSundar R Iyer 		.flags	= IORESOURCE_IRQ,
72377686517SSundar R Iyer 	},
72477686517SSundar R Iyer };
72577686517SSundar R Iyer 
726a9e9ce4cSBill Pemberton static struct resource ab8500_av_acc_detect_resources[] = {
727e098adedSMattias Wallin 	{
7286af75ecdSLinus Walleij 	       .name = "ACC_DETECT_1DB_F",
7296af75ecdSLinus Walleij 	       .start = AB8500_INT_ACC_DETECT_1DB_F,
7306af75ecdSLinus Walleij 	       .end = AB8500_INT_ACC_DETECT_1DB_F,
731e098adedSMattias Wallin 	       .flags = IORESOURCE_IRQ,
732e098adedSMattias Wallin 	},
733e098adedSMattias Wallin 	{
7346af75ecdSLinus Walleij 	       .name = "ACC_DETECT_1DB_R",
7356af75ecdSLinus Walleij 	       .start = AB8500_INT_ACC_DETECT_1DB_R,
7366af75ecdSLinus Walleij 	       .end = AB8500_INT_ACC_DETECT_1DB_R,
737e098adedSMattias Wallin 	       .flags = IORESOURCE_IRQ,
738e098adedSMattias Wallin 	},
739e098adedSMattias Wallin 	{
7406af75ecdSLinus Walleij 	       .name = "ACC_DETECT_21DB_F",
7416af75ecdSLinus Walleij 	       .start = AB8500_INT_ACC_DETECT_21DB_F,
7426af75ecdSLinus Walleij 	       .end = AB8500_INT_ACC_DETECT_21DB_F,
7436af75ecdSLinus Walleij 	       .flags = IORESOURCE_IRQ,
7446af75ecdSLinus Walleij 	},
7456af75ecdSLinus Walleij 	{
7466af75ecdSLinus Walleij 	       .name = "ACC_DETECT_21DB_R",
7476af75ecdSLinus Walleij 	       .start = AB8500_INT_ACC_DETECT_21DB_R,
7486af75ecdSLinus Walleij 	       .end = AB8500_INT_ACC_DETECT_21DB_R,
7496af75ecdSLinus Walleij 	       .flags = IORESOURCE_IRQ,
7506af75ecdSLinus Walleij 	},
7516af75ecdSLinus Walleij 	{
7526af75ecdSLinus Walleij 	       .name = "ACC_DETECT_22DB_F",
7536af75ecdSLinus Walleij 	       .start = AB8500_INT_ACC_DETECT_22DB_F,
7546af75ecdSLinus Walleij 	       .end = AB8500_INT_ACC_DETECT_22DB_F,
7556af75ecdSLinus Walleij 	       .flags = IORESOURCE_IRQ,
7566af75ecdSLinus Walleij 	},
7576af75ecdSLinus Walleij 	{
7586af75ecdSLinus Walleij 	       .name = "ACC_DETECT_22DB_R",
7596af75ecdSLinus Walleij 	       .start = AB8500_INT_ACC_DETECT_22DB_R,
7606af75ecdSLinus Walleij 	       .end = AB8500_INT_ACC_DETECT_22DB_R,
7616af75ecdSLinus Walleij 	       .flags = IORESOURCE_IRQ,
7626af75ecdSLinus Walleij 	},
7636af75ecdSLinus Walleij };
7646af75ecdSLinus Walleij 
765a9e9ce4cSBill Pemberton static struct resource ab8500_charger_resources[] = {
7666af75ecdSLinus Walleij 	{
767e098adedSMattias Wallin 		.name = "MAIN_CH_UNPLUG_DET",
768e098adedSMattias Wallin 		.start = AB8500_INT_MAIN_CH_UNPLUG_DET,
769e098adedSMattias Wallin 		.end = AB8500_INT_MAIN_CH_UNPLUG_DET,
770e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
771e098adedSMattias Wallin 	},
772e098adedSMattias Wallin 	{
773e098adedSMattias Wallin 		.name = "MAIN_CHARGE_PLUG_DET",
774e098adedSMattias Wallin 		.start = AB8500_INT_MAIN_CH_PLUG_DET,
775e098adedSMattias Wallin 		.end = AB8500_INT_MAIN_CH_PLUG_DET,
776e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
777e098adedSMattias Wallin 	},
778e098adedSMattias Wallin 	{
779e098adedSMattias Wallin 		.name = "VBUS_DET_R",
780e098adedSMattias Wallin 		.start = AB8500_INT_VBUS_DET_R,
781e098adedSMattias Wallin 		.end = AB8500_INT_VBUS_DET_R,
782e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
783e098adedSMattias Wallin 	},
784e098adedSMattias Wallin 	{
7856af75ecdSLinus Walleij 		.name = "VBUS_DET_F",
7866af75ecdSLinus Walleij 		.start = AB8500_INT_VBUS_DET_F,
7876af75ecdSLinus Walleij 		.end = AB8500_INT_VBUS_DET_F,
788e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
789e098adedSMattias Wallin 	},
790e098adedSMattias Wallin 	{
7916af75ecdSLinus Walleij 		.name = "USB_LINK_STATUS",
7926af75ecdSLinus Walleij 		.start = AB8500_INT_USB_LINK_STATUS,
7936af75ecdSLinus Walleij 		.end = AB8500_INT_USB_LINK_STATUS,
7946af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
7956af75ecdSLinus Walleij 	},
7966af75ecdSLinus Walleij 	{
797e098adedSMattias Wallin 		.name = "VBUS_OVV",
798e098adedSMattias Wallin 		.start = AB8500_INT_VBUS_OVV,
799e098adedSMattias Wallin 		.end = AB8500_INT_VBUS_OVV,
800e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
801e098adedSMattias Wallin 	},
802e098adedSMattias Wallin 	{
8036af75ecdSLinus Walleij 		.name = "USB_CH_TH_PROT_R",
8046af75ecdSLinus Walleij 		.start = AB8500_INT_USB_CH_TH_PROT_R,
8056af75ecdSLinus Walleij 		.end = AB8500_INT_USB_CH_TH_PROT_R,
806e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
807e098adedSMattias Wallin 	},
808e098adedSMattias Wallin 	{
8096af75ecdSLinus Walleij 		.name = "USB_CH_TH_PROT_F",
8106af75ecdSLinus Walleij 		.start = AB8500_INT_USB_CH_TH_PROT_F,
8116af75ecdSLinus Walleij 		.end = AB8500_INT_USB_CH_TH_PROT_F,
812e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
813e098adedSMattias Wallin 	},
814e098adedSMattias Wallin 	{
8156af75ecdSLinus Walleij 		.name = "MAIN_EXT_CH_NOT_OK",
8166af75ecdSLinus Walleij 		.start = AB8500_INT_MAIN_EXT_CH_NOT_OK,
8176af75ecdSLinus Walleij 		.end = AB8500_INT_MAIN_EXT_CH_NOT_OK,
8186af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
8196af75ecdSLinus Walleij 	},
8206af75ecdSLinus Walleij 	{
8216af75ecdSLinus Walleij 		.name = "MAIN_CH_TH_PROT_R",
8226af75ecdSLinus Walleij 		.start = AB8500_INT_MAIN_CH_TH_PROT_R,
8236af75ecdSLinus Walleij 		.end = AB8500_INT_MAIN_CH_TH_PROT_R,
8246af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
8256af75ecdSLinus Walleij 	},
8266af75ecdSLinus Walleij 	{
8276af75ecdSLinus Walleij 		.name = "MAIN_CH_TH_PROT_F",
8286af75ecdSLinus Walleij 		.start = AB8500_INT_MAIN_CH_TH_PROT_F,
8296af75ecdSLinus Walleij 		.end = AB8500_INT_MAIN_CH_TH_PROT_F,
8306af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
8316af75ecdSLinus Walleij 	},
8326af75ecdSLinus Walleij 	{
8336af75ecdSLinus Walleij 		.name = "USB_CHARGER_NOT_OKR",
834a982362cSBengt Jonsson 		.start = AB8500_INT_USB_CHARGER_NOT_OKR,
835a982362cSBengt Jonsson 		.end = AB8500_INT_USB_CHARGER_NOT_OKR,
8366af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
8376af75ecdSLinus Walleij 	},
8386af75ecdSLinus Walleij 	{
8396af75ecdSLinus Walleij 		.name = "CH_WD_EXP",
8406af75ecdSLinus Walleij 		.start = AB8500_INT_CH_WD_EXP,
8416af75ecdSLinus Walleij 		.end = AB8500_INT_CH_WD_EXP,
8426af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
8436af75ecdSLinus Walleij 	},
84434c11a70SPaer-Olof Haakansson 	{
84534c11a70SPaer-Olof Haakansson 		.name = "VBUS_CH_DROP_END",
84634c11a70SPaer-Olof Haakansson 		.start = AB8500_INT_VBUS_CH_DROP_END,
84734c11a70SPaer-Olof Haakansson 		.end = AB8500_INT_VBUS_CH_DROP_END,
84834c11a70SPaer-Olof Haakansson 		.flags = IORESOURCE_IRQ,
84934c11a70SPaer-Olof Haakansson 	},
8506af75ecdSLinus Walleij };
8516af75ecdSLinus Walleij 
852a9e9ce4cSBill Pemberton static struct resource ab8500_btemp_resources[] = {
8536af75ecdSLinus Walleij 	{
8546af75ecdSLinus Walleij 		.name = "BAT_CTRL_INDB",
8556af75ecdSLinus Walleij 		.start = AB8500_INT_BAT_CTRL_INDB,
8566af75ecdSLinus Walleij 		.end = AB8500_INT_BAT_CTRL_INDB,
857e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
858e098adedSMattias Wallin 	},
859e098adedSMattias Wallin 	{
860e098adedSMattias Wallin 		.name = "BTEMP_LOW",
861e098adedSMattias Wallin 		.start = AB8500_INT_BTEMP_LOW,
862e098adedSMattias Wallin 		.end = AB8500_INT_BTEMP_LOW,
863e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
864e098adedSMattias Wallin 	},
865e098adedSMattias Wallin 	{
866e098adedSMattias Wallin 		.name = "BTEMP_HIGH",
867e098adedSMattias Wallin 		.start = AB8500_INT_BTEMP_HIGH,
868e098adedSMattias Wallin 		.end = AB8500_INT_BTEMP_HIGH,
869e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
870e098adedSMattias Wallin 	},
871e098adedSMattias Wallin 	{
8726af75ecdSLinus Walleij 		.name = "BTEMP_LOW_MEDIUM",
8736af75ecdSLinus Walleij 		.start = AB8500_INT_BTEMP_LOW_MEDIUM,
8746af75ecdSLinus Walleij 		.end = AB8500_INT_BTEMP_LOW_MEDIUM,
875e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
876e098adedSMattias Wallin 	},
877e098adedSMattias Wallin 	{
8786af75ecdSLinus Walleij 		.name = "BTEMP_MEDIUM_HIGH",
8796af75ecdSLinus Walleij 		.start = AB8500_INT_BTEMP_MEDIUM_HIGH,
8806af75ecdSLinus Walleij 		.end = AB8500_INT_BTEMP_MEDIUM_HIGH,
881e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
882e098adedSMattias Wallin 	},
883e098adedSMattias Wallin };
884e098adedSMattias Wallin 
885a9e9ce4cSBill Pemberton static struct resource ab8500_fg_resources[] = {
8866af75ecdSLinus Walleij 	{
8876af75ecdSLinus Walleij 		.name = "NCONV_ACCU",
8886af75ecdSLinus Walleij 		.start = AB8500_INT_CCN_CONV_ACC,
8896af75ecdSLinus Walleij 		.end = AB8500_INT_CCN_CONV_ACC,
8906af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
8916af75ecdSLinus Walleij 	},
8926af75ecdSLinus Walleij 	{
8936af75ecdSLinus Walleij 		.name = "BATT_OVV",
8946af75ecdSLinus Walleij 		.start = AB8500_INT_BATT_OVV,
8956af75ecdSLinus Walleij 		.end = AB8500_INT_BATT_OVV,
8966af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
8976af75ecdSLinus Walleij 	},
8986af75ecdSLinus Walleij 	{
8996af75ecdSLinus Walleij 		.name = "LOW_BAT_F",
9006af75ecdSLinus Walleij 		.start = AB8500_INT_LOW_BAT_F,
9016af75ecdSLinus Walleij 		.end = AB8500_INT_LOW_BAT_F,
9026af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
9036af75ecdSLinus Walleij 	},
9046af75ecdSLinus Walleij 	{
9056af75ecdSLinus Walleij 		.name = "LOW_BAT_R",
9066af75ecdSLinus Walleij 		.start = AB8500_INT_LOW_BAT_R,
9076af75ecdSLinus Walleij 		.end = AB8500_INT_LOW_BAT_R,
9086af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
9096af75ecdSLinus Walleij 	},
9106af75ecdSLinus Walleij 	{
9116af75ecdSLinus Walleij 		.name = "CC_INT_CALIB",
9126af75ecdSLinus Walleij 		.start = AB8500_INT_CC_INT_CALIB,
9136af75ecdSLinus Walleij 		.end = AB8500_INT_CC_INT_CALIB,
9146af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
9156af75ecdSLinus Walleij 	},
916a982362cSBengt Jonsson 	{
917a982362cSBengt Jonsson 		.name = "CCEOC",
918a982362cSBengt Jonsson 		.start = AB8500_INT_CCEOC,
919a982362cSBengt Jonsson 		.end = AB8500_INT_CCEOC,
920a982362cSBengt Jonsson 		.flags = IORESOURCE_IRQ,
921a982362cSBengt Jonsson 	},
9226af75ecdSLinus Walleij };
9236af75ecdSLinus Walleij 
924a9e9ce4cSBill Pemberton static struct resource ab8500_chargalg_resources[] = {};
9256af75ecdSLinus Walleij 
926df720647SAxel Lin #ifdef CONFIG_DEBUG_FS
927a9e9ce4cSBill Pemberton static struct resource ab8500_debug_resources[] = {
928e098adedSMattias Wallin 	{
929e098adedSMattias Wallin 		.name	= "IRQ_FIRST",
930e098adedSMattias Wallin 		.start	= AB8500_INT_MAIN_EXT_CH_NOT_OK,
931e098adedSMattias Wallin 		.end	= AB8500_INT_MAIN_EXT_CH_NOT_OK,
932e098adedSMattias Wallin 		.flags	= IORESOURCE_IRQ,
933e098adedSMattias Wallin 	},
934e098adedSMattias Wallin 	{
935e098adedSMattias Wallin 		.name	= "IRQ_LAST",
936a982362cSBengt Jonsson 		.start	= AB8500_INT_XTAL32K_KO,
937a982362cSBengt Jonsson 		.end	= AB8500_INT_XTAL32K_KO,
938e098adedSMattias Wallin 		.flags	= IORESOURCE_IRQ,
939e098adedSMattias Wallin 	},
940e098adedSMattias Wallin };
941df720647SAxel Lin #endif
942e098adedSMattias Wallin 
943a9e9ce4cSBill Pemberton static struct resource ab8500_usb_resources[] = {
944e098adedSMattias Wallin 	{
945e098adedSMattias Wallin 		.name = "ID_WAKEUP_R",
946e098adedSMattias Wallin 		.start = AB8500_INT_ID_WAKEUP_R,
947e098adedSMattias Wallin 		.end = AB8500_INT_ID_WAKEUP_R,
948e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
949e098adedSMattias Wallin 	},
950e098adedSMattias Wallin 	{
951e098adedSMattias Wallin 		.name = "ID_WAKEUP_F",
952e098adedSMattias Wallin 		.start = AB8500_INT_ID_WAKEUP_F,
953e098adedSMattias Wallin 		.end = AB8500_INT_ID_WAKEUP_F,
954e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
955e098adedSMattias Wallin 	},
956e098adedSMattias Wallin 	{
957e098adedSMattias Wallin 		.name = "VBUS_DET_F",
958e098adedSMattias Wallin 		.start = AB8500_INT_VBUS_DET_F,
959e098adedSMattias Wallin 		.end = AB8500_INT_VBUS_DET_F,
960e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
961e098adedSMattias Wallin 	},
962e098adedSMattias Wallin 	{
963e098adedSMattias Wallin 		.name = "VBUS_DET_R",
964e098adedSMattias Wallin 		.start = AB8500_INT_VBUS_DET_R,
965e098adedSMattias Wallin 		.end = AB8500_INT_VBUS_DET_R,
966e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
967e098adedSMattias Wallin 	},
96892d50a41SMattias Wallin 	{
96992d50a41SMattias Wallin 		.name = "USB_LINK_STATUS",
97092d50a41SMattias Wallin 		.start = AB8500_INT_USB_LINK_STATUS,
97192d50a41SMattias Wallin 		.end = AB8500_INT_USB_LINK_STATUS,
97292d50a41SMattias Wallin 		.flags = IORESOURCE_IRQ,
97392d50a41SMattias Wallin 	},
9746af75ecdSLinus Walleij 	{
9756af75ecdSLinus Walleij 		.name = "USB_ADP_PROBE_PLUG",
9766af75ecdSLinus Walleij 		.start = AB8500_INT_ADP_PROBE_PLUG,
9776af75ecdSLinus Walleij 		.end = AB8500_INT_ADP_PROBE_PLUG,
9786af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
9796af75ecdSLinus Walleij 	},
9806af75ecdSLinus Walleij 	{
9816af75ecdSLinus Walleij 		.name = "USB_ADP_PROBE_UNPLUG",
9826af75ecdSLinus Walleij 		.start = AB8500_INT_ADP_PROBE_UNPLUG,
9836af75ecdSLinus Walleij 		.end = AB8500_INT_ADP_PROBE_UNPLUG,
9846af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
9856af75ecdSLinus Walleij 	},
986e098adedSMattias Wallin };
987e098adedSMattias Wallin 
988a9e9ce4cSBill Pemberton static struct resource ab8505_iddet_resources[] = {
98944f72e53SVirupax Sadashivpetimath 	{
99044f72e53SVirupax Sadashivpetimath 		.name  = "KeyDeglitch",
99144f72e53SVirupax Sadashivpetimath 		.start = AB8505_INT_KEYDEGLITCH,
99244f72e53SVirupax Sadashivpetimath 		.end   = AB8505_INT_KEYDEGLITCH,
99344f72e53SVirupax Sadashivpetimath 		.flags = IORESOURCE_IRQ,
99444f72e53SVirupax Sadashivpetimath 	},
99544f72e53SVirupax Sadashivpetimath 	{
99644f72e53SVirupax Sadashivpetimath 		.name  = "KP",
99744f72e53SVirupax Sadashivpetimath 		.start = AB8505_INT_KP,
99844f72e53SVirupax Sadashivpetimath 		.end   = AB8505_INT_KP,
99944f72e53SVirupax Sadashivpetimath 		.flags = IORESOURCE_IRQ,
100044f72e53SVirupax Sadashivpetimath 	},
100144f72e53SVirupax Sadashivpetimath 	{
100244f72e53SVirupax Sadashivpetimath 		.name  = "IKP",
100344f72e53SVirupax Sadashivpetimath 		.start = AB8505_INT_IKP,
100444f72e53SVirupax Sadashivpetimath 		.end   = AB8505_INT_IKP,
100544f72e53SVirupax Sadashivpetimath 		.flags = IORESOURCE_IRQ,
100644f72e53SVirupax Sadashivpetimath 	},
100744f72e53SVirupax Sadashivpetimath 	{
100844f72e53SVirupax Sadashivpetimath 		.name  = "IKR",
100944f72e53SVirupax Sadashivpetimath 		.start = AB8505_INT_IKR,
101044f72e53SVirupax Sadashivpetimath 		.end   = AB8505_INT_IKR,
101144f72e53SVirupax Sadashivpetimath 		.flags = IORESOURCE_IRQ,
101244f72e53SVirupax Sadashivpetimath 	},
101344f72e53SVirupax Sadashivpetimath 	{
101444f72e53SVirupax Sadashivpetimath 		.name  = "KeyStuck",
101544f72e53SVirupax Sadashivpetimath 		.start = AB8505_INT_KEYSTUCK,
101644f72e53SVirupax Sadashivpetimath 		.end   = AB8505_INT_KEYSTUCK,
101744f72e53SVirupax Sadashivpetimath 		.flags = IORESOURCE_IRQ,
101844f72e53SVirupax Sadashivpetimath 	},
101944f72e53SVirupax Sadashivpetimath };
102044f72e53SVirupax Sadashivpetimath 
1021a9e9ce4cSBill Pemberton static struct resource ab8500_temp_resources[] = {
1022e098adedSMattias Wallin 	{
1023151621a7SHongbo Zhang 		.name  = "ABX500_TEMP_WARM",
1024e098adedSMattias Wallin 		.start = AB8500_INT_TEMP_WARM,
1025e098adedSMattias Wallin 		.end   = AB8500_INT_TEMP_WARM,
1026e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
1027e098adedSMattias Wallin 	},
1028e098adedSMattias Wallin };
1029e098adedSMattias Wallin 
1030a9e9ce4cSBill Pemberton static struct mfd_cell ab8500_bm_devs[] = {
10316ef9418cSRickard Andersson 	{
10326ef9418cSRickard Andersson 		.name = "ab8500-charger",
10334aef72dbSRajanikanth H.V 		.of_compatible = "stericsson,ab8500-charger",
10346ef9418cSRickard Andersson 		.num_resources = ARRAY_SIZE(ab8500_charger_resources),
10356ef9418cSRickard Andersson 		.resources = ab8500_charger_resources,
10364aef72dbSRajanikanth H.V 		.platform_data = &ab8500_bm_data,
10374aef72dbSRajanikanth H.V 		.pdata_size = sizeof(ab8500_bm_data),
10386ef9418cSRickard Andersson 	},
10396ef9418cSRickard Andersson 	{
10406ef9418cSRickard Andersson 		.name = "ab8500-btemp",
1041bd9e8ab2SRajanikanth H.V 		.of_compatible = "stericsson,ab8500-btemp",
10426ef9418cSRickard Andersson 		.num_resources = ARRAY_SIZE(ab8500_btemp_resources),
10436ef9418cSRickard Andersson 		.resources = ab8500_btemp_resources,
1044bd9e8ab2SRajanikanth H.V 		.platform_data = &ab8500_bm_data,
1045bd9e8ab2SRajanikanth H.V 		.pdata_size = sizeof(ab8500_bm_data),
10466ef9418cSRickard Andersson 	},
10476ef9418cSRickard Andersson 	{
10486ef9418cSRickard Andersson 		.name = "ab8500-fg",
1049e0f1abebSRajanikanth H.V 		.of_compatible = "stericsson,ab8500-fg",
10506ef9418cSRickard Andersson 		.num_resources = ARRAY_SIZE(ab8500_fg_resources),
10516ef9418cSRickard Andersson 		.resources = ab8500_fg_resources,
1052e0f1abebSRajanikanth H.V 		.platform_data = &ab8500_bm_data,
1053e0f1abebSRajanikanth H.V 		.pdata_size = sizeof(ab8500_bm_data),
10546ef9418cSRickard Andersson 	},
10556ef9418cSRickard Andersson 	{
10566ef9418cSRickard Andersson 		.name = "ab8500-chargalg",
1057a12810abSRajanikanth H.V 		.of_compatible = "stericsson,ab8500-chargalg",
10586ef9418cSRickard Andersson 		.num_resources = ARRAY_SIZE(ab8500_chargalg_resources),
10596ef9418cSRickard Andersson 		.resources = ab8500_chargalg_resources,
1060a12810abSRajanikanth H.V 		.platform_data = &ab8500_bm_data,
1061a12810abSRajanikanth H.V 		.pdata_size = sizeof(ab8500_bm_data),
10626ef9418cSRickard Andersson 	},
10636ef9418cSRickard Andersson };
10646ef9418cSRickard Andersson 
1065a9e9ce4cSBill Pemberton static struct mfd_cell ab8500_devs[] = {
10664b106fb9SLee Jones #ifdef CONFIG_DEBUG_FS
1067d6255529SLinus Walleij 	{
10684b106fb9SLee Jones 		.name = "ab8500-debug",
10694b106fb9SLee Jones 		.of_compatible = "stericsson,ab8500-debug",
10704b106fb9SLee Jones 		.num_resources = ARRAY_SIZE(ab8500_debug_resources),
10714b106fb9SLee Jones 		.resources = ab8500_debug_resources,
10724b106fb9SLee Jones 	},
10734b106fb9SLee Jones #endif
10744b106fb9SLee Jones 	{
10754b106fb9SLee Jones 		.name = "ab8500-sysctrl",
10764b106fb9SLee Jones 		.of_compatible = "stericsson,ab8500-sysctrl",
10774b106fb9SLee Jones 	},
10784b106fb9SLee Jones 	{
10794b106fb9SLee Jones 		.name = "ab8500-regulator",
10804b106fb9SLee Jones 		.of_compatible = "stericsson,ab8500-regulator",
10814b106fb9SLee Jones 	},
10824b106fb9SLee Jones 	{
10834b106fb9SLee Jones 		.name = "abx500-clk",
10844b106fb9SLee Jones 		.of_compatible = "stericsson,abx500-clk",
10854b106fb9SLee Jones 	},
10864b106fb9SLee Jones 	{
10874b106fb9SLee Jones 		.name = "ab8500-gpadc",
10884b106fb9SLee Jones 		.num_resources = ARRAY_SIZE(ab8500_gpadc_resources),
10894b106fb9SLee Jones 		.resources = ab8500_gpadc_resources,
10904b106fb9SLee Jones 	},
10914b106fb9SLee Jones 	{
10924b106fb9SLee Jones 		.name = "ab8500-rtc",
10934b106fb9SLee Jones 		.of_compatible = "stericsson,ab8500-rtc",
10944b106fb9SLee Jones 		.num_resources = ARRAY_SIZE(ab8500_rtc_resources),
10954b106fb9SLee Jones 		.resources = ab8500_rtc_resources,
10964b106fb9SLee Jones 	},
10974b106fb9SLee Jones 	{
10984b106fb9SLee Jones 		.name = "ab8500-acc-det",
10994b106fb9SLee Jones 		.of_compatible = "stericsson,ab8500-acc-det",
11004b106fb9SLee Jones 		.num_resources = ARRAY_SIZE(ab8500_av_acc_detect_resources),
11014b106fb9SLee Jones 		.resources = ab8500_av_acc_detect_resources,
11024b106fb9SLee Jones 	},
11034b106fb9SLee Jones 	{
11044b106fb9SLee Jones 
11054b106fb9SLee Jones 		.name = "ab8500-poweron-key",
11064b106fb9SLee Jones 		.of_compatible = "stericsson,ab8500-poweron-key",
11074b106fb9SLee Jones 		.num_resources = ARRAY_SIZE(ab8500_poweronkey_db_resources),
11084b106fb9SLee Jones 		.resources = ab8500_poweronkey_db_resources,
11094b106fb9SLee Jones 	},
11104b106fb9SLee Jones 	{
11114b106fb9SLee Jones 		.name = "ab8500-pwm",
11124b106fb9SLee Jones 		.of_compatible = "stericsson,ab8500-pwm",
11134b106fb9SLee Jones 		.id = 1,
11144b106fb9SLee Jones 	},
11154b106fb9SLee Jones 	{
11164b106fb9SLee Jones 		.name = "ab8500-pwm",
11174b106fb9SLee Jones 		.of_compatible = "stericsson,ab8500-pwm",
11184b106fb9SLee Jones 		.id = 2,
11194b106fb9SLee Jones 	},
11204b106fb9SLee Jones 	{
11214b106fb9SLee Jones 		.name = "ab8500-pwm",
11224b106fb9SLee Jones 		.of_compatible = "stericsson,ab8500-pwm",
11234b106fb9SLee Jones 		.id = 3,
11244b106fb9SLee Jones 	},
11254b106fb9SLee Jones 	{
11264b106fb9SLee Jones 		.name = "ab8500-leds",
11274b106fb9SLee Jones 		.of_compatible = "stericsson,ab8500-leds",
11284b106fb9SLee Jones 	},
11294b106fb9SLee Jones 	{
11304b106fb9SLee Jones 		.name = "ab8500-denc",
11314b106fb9SLee Jones 		.of_compatible = "stericsson,ab8500-denc",
11324b106fb9SLee Jones 	},
11334b106fb9SLee Jones 	{
11344b106fb9SLee Jones 		.name = "ab8500-gpio",
1135bad76991SLee Jones 		.of_compatible = "stericsson,ab8500-gpio",
1136d6255529SLinus Walleij 	},
1137d6255529SLinus Walleij 	{
11384b106fb9SLee Jones 		.name = "abx500-temp",
11394b106fb9SLee Jones 		.of_compatible = "stericsson,abx500-temp",
11404b106fb9SLee Jones 		.num_resources = ARRAY_SIZE(ab8500_temp_resources),
11414b106fb9SLee Jones 		.resources = ab8500_temp_resources,
11424b106fb9SLee Jones 	},
11434b106fb9SLee Jones 	{
1144d6255529SLinus Walleij 		.name = "ab8500-usb",
1145d6255529SLinus Walleij 		.num_resources = ARRAY_SIZE(ab8500_usb_resources),
1146d6255529SLinus Walleij 		.resources = ab8500_usb_resources,
1147d6255529SLinus Walleij 	},
114844f72e53SVirupax Sadashivpetimath 	{
114944f72e53SVirupax Sadashivpetimath 		.name = "ab8500-codec",
11504b106fb9SLee Jones 	},
11514b106fb9SLee Jones };
11524b106fb9SLee Jones 
11534b106fb9SLee Jones static struct mfd_cell ab9540_devs[] = {
11544b106fb9SLee Jones #ifdef CONFIG_DEBUG_FS
11554b106fb9SLee Jones 	{
11564b106fb9SLee Jones 		.name = "ab8500-debug",
11574b106fb9SLee Jones 		.num_resources = ARRAY_SIZE(ab8500_debug_resources),
11584b106fb9SLee Jones 		.resources = ab8500_debug_resources,
11594b106fb9SLee Jones 	},
11604b106fb9SLee Jones #endif
11614b106fb9SLee Jones 	{
11624b106fb9SLee Jones 		.name = "ab8500-sysctrl",
11634b106fb9SLee Jones 	},
11644b106fb9SLee Jones 	{
11654b106fb9SLee Jones 		.name = "ab8500-regulator",
116644f72e53SVirupax Sadashivpetimath 	},
1167c0eda9aeSLee Jones 	{
1168c0eda9aeSLee Jones 		.name = "ab8500-gpadc",
1169c0eda9aeSLee Jones 		.of_compatible = "stericsson,ab8500-gpadc",
1170c0eda9aeSLee Jones 		.num_resources = ARRAY_SIZE(ab8500_gpadc_resources),
1171c0eda9aeSLee Jones 		.resources = ab8500_gpadc_resources,
1172c0eda9aeSLee Jones 	},
11734b106fb9SLee Jones 	{
11744b106fb9SLee Jones 		.name = "ab8500-rtc",
11754b106fb9SLee Jones 		.num_resources = ARRAY_SIZE(ab8500_rtc_resources),
11764b106fb9SLee Jones 		.resources = ab8500_rtc_resources,
11774b106fb9SLee Jones 	},
11784b106fb9SLee Jones 	{
11794b106fb9SLee Jones 		.name = "ab8500-acc-det",
11804b106fb9SLee Jones 		.num_resources = ARRAY_SIZE(ab8500_av_acc_detect_resources),
11814b106fb9SLee Jones 		.resources = ab8500_av_acc_detect_resources,
11824b106fb9SLee Jones 	},
11834b106fb9SLee Jones 	{
11844b106fb9SLee Jones 		.name = "ab8500-poweron-key",
11854b106fb9SLee Jones 		.num_resources = ARRAY_SIZE(ab8500_poweronkey_db_resources),
11864b106fb9SLee Jones 		.resources = ab8500_poweronkey_db_resources,
11874b106fb9SLee Jones 	},
11884b106fb9SLee Jones 	{
11894b106fb9SLee Jones 		.name = "ab8500-pwm",
11904b106fb9SLee Jones 		.id = 1,
11914b106fb9SLee Jones 	},
11924b106fb9SLee Jones 	{
11934b106fb9SLee Jones 		.name = "ab8500-leds",
11944b106fb9SLee Jones 	},
11954b106fb9SLee Jones 	{
11964b106fb9SLee Jones 		.name = "abx500-temp",
11974b106fb9SLee Jones 		.num_resources = ARRAY_SIZE(ab8500_temp_resources),
11984b106fb9SLee Jones 		.resources = ab8500_temp_resources,
11994b106fb9SLee Jones 	},
1200d6255529SLinus Walleij 	{
1201e64d905eSLee Jones 		.name = "pinctrl-ab9540",
1202e64d905eSLee Jones 		.of_compatible = "stericsson,ab9540-gpio",
1203d6255529SLinus Walleij 	},
1204d6255529SLinus Walleij 	{
1205d6255529SLinus Walleij 		.name = "ab9540-usb",
1206d6255529SLinus Walleij 		.num_resources = ARRAY_SIZE(ab8500_usb_resources),
1207d6255529SLinus Walleij 		.resources = ab8500_usb_resources,
1208d6255529SLinus Walleij 	},
120944f72e53SVirupax Sadashivpetimath 	{
121044f72e53SVirupax Sadashivpetimath 		.name = "ab9540-codec",
121144f72e53SVirupax Sadashivpetimath 	},
1212c0eda9aeSLee Jones 	{
1213c0eda9aeSLee Jones 		.name = "ab-iddet",
1214c0eda9aeSLee Jones 		.num_resources = ARRAY_SIZE(ab8505_iddet_resources),
1215c0eda9aeSLee Jones 		.resources = ab8505_iddet_resources,
1216c0eda9aeSLee Jones 	},
121744f72e53SVirupax Sadashivpetimath };
121844f72e53SVirupax Sadashivpetimath 
1219c0eda9aeSLee Jones /* Device list for ab8505  */
1220c0eda9aeSLee Jones static struct mfd_cell ab8505_devs[] = {
12214b106fb9SLee Jones #ifdef CONFIG_DEBUG_FS
12224b106fb9SLee Jones 	{
12234b106fb9SLee Jones 		.name = "ab8500-debug",
12244b106fb9SLee Jones 		.num_resources = ARRAY_SIZE(ab8500_debug_resources),
12254b106fb9SLee Jones 		.resources = ab8500_debug_resources,
12264b106fb9SLee Jones 	},
12274b106fb9SLee Jones #endif
12284b106fb9SLee Jones 	{
12294b106fb9SLee Jones 		.name = "ab8500-sysctrl",
12304b106fb9SLee Jones 	},
12314b106fb9SLee Jones 	{
12324b106fb9SLee Jones 		.name = "ab8500-regulator",
12334b106fb9SLee Jones 	},
12344b106fb9SLee Jones 	{
12354b106fb9SLee Jones 		.name = "ab8500-gpadc",
12364b106fb9SLee Jones 		.num_resources = ARRAY_SIZE(ab8505_gpadc_resources),
12374b106fb9SLee Jones 		.resources = ab8505_gpadc_resources,
12384b106fb9SLee Jones 	},
12394b106fb9SLee Jones 	{
12404b106fb9SLee Jones 		.name = "ab8500-rtc",
12414b106fb9SLee Jones 		.num_resources = ARRAY_SIZE(ab8500_rtc_resources),
12424b106fb9SLee Jones 		.resources = ab8500_rtc_resources,
12434b106fb9SLee Jones 	},
12444b106fb9SLee Jones 	{
12454b106fb9SLee Jones 		.name = "ab8500-acc-det",
12464b106fb9SLee Jones 		.num_resources = ARRAY_SIZE(ab8500_av_acc_detect_resources),
12474b106fb9SLee Jones 		.resources = ab8500_av_acc_detect_resources,
12484b106fb9SLee Jones 	},
12494b106fb9SLee Jones 	{
12504b106fb9SLee Jones 		.name = "ab8500-poweron-key",
12514b106fb9SLee Jones 		.num_resources = ARRAY_SIZE(ab8500_poweronkey_db_resources),
12524b106fb9SLee Jones 		.resources = ab8500_poweronkey_db_resources,
12534b106fb9SLee Jones 	},
12544b106fb9SLee Jones 	{
12554b106fb9SLee Jones 		.name = "ab8500-pwm",
12564b106fb9SLee Jones 		.id = 1,
12574b106fb9SLee Jones 	},
12584b106fb9SLee Jones 	{
12594b106fb9SLee Jones 		.name = "ab8500-leds",
12604b106fb9SLee Jones 	},
12614b106fb9SLee Jones 	{
12624b106fb9SLee Jones 		.name = "ab8500-gpio",
12634b106fb9SLee Jones 	},
12644b106fb9SLee Jones 	{
12654b106fb9SLee Jones 		.name = "ab8500-usb",
12664b106fb9SLee Jones 		.num_resources = ARRAY_SIZE(ab8500_usb_resources),
12674b106fb9SLee Jones 		.resources = ab8500_usb_resources,
12684b106fb9SLee Jones 	},
12694b106fb9SLee Jones 	{
12704b106fb9SLee Jones 		.name = "ab8500-codec",
12714b106fb9SLee Jones 	},
1272c0eda9aeSLee Jones 	{
1273c0eda9aeSLee Jones 		.name = "ab-iddet",
1274c0eda9aeSLee Jones 		.num_resources = ARRAY_SIZE(ab8505_iddet_resources),
1275c0eda9aeSLee Jones 		.resources = ab8505_iddet_resources,
1276c0eda9aeSLee Jones 	},
1277c0eda9aeSLee Jones };
1278c0eda9aeSLee Jones 
1279c0eda9aeSLee Jones static struct mfd_cell ab8540_devs[] = {
12804b106fb9SLee Jones #ifdef CONFIG_DEBUG_FS
12814b106fb9SLee Jones 	{
12824b106fb9SLee Jones 		.name = "ab8500-debug",
12834b106fb9SLee Jones 		.num_resources = ARRAY_SIZE(ab8500_debug_resources),
12844b106fb9SLee Jones 		.resources = ab8500_debug_resources,
12854b106fb9SLee Jones 	},
12864b106fb9SLee Jones #endif
12874b106fb9SLee Jones 	{
12884b106fb9SLee Jones 		.name = "ab8500-sysctrl",
12894b106fb9SLee Jones 	},
12904b106fb9SLee Jones 	{
12914b106fb9SLee Jones 		.name = "ab8500-regulator",
12924b106fb9SLee Jones 	},
12934b106fb9SLee Jones 	{
12944b106fb9SLee Jones 		.name = "ab8500-gpadc",
12954b106fb9SLee Jones 		.num_resources = ARRAY_SIZE(ab8505_gpadc_resources),
12964b106fb9SLee Jones 		.resources = ab8505_gpadc_resources,
12974b106fb9SLee Jones 	},
12984b106fb9SLee Jones 	{
12994b106fb9SLee Jones 		.name = "ab8500-rtc",
13004b106fb9SLee Jones 		.num_resources = ARRAY_SIZE(ab8500_rtc_resources),
13014b106fb9SLee Jones 		.resources = ab8500_rtc_resources,
13024b106fb9SLee Jones 	},
13034b106fb9SLee Jones 	{
13044b106fb9SLee Jones 		.name = "ab8500-acc-det",
13054b106fb9SLee Jones 		.num_resources = ARRAY_SIZE(ab8500_av_acc_detect_resources),
13064b106fb9SLee Jones 		.resources = ab8500_av_acc_detect_resources,
13074b106fb9SLee Jones 	},
13084b106fb9SLee Jones 	{
13094b106fb9SLee Jones 		.name = "ab8500-poweron-key",
13104b106fb9SLee Jones 		.num_resources = ARRAY_SIZE(ab8500_poweronkey_db_resources),
13114b106fb9SLee Jones 		.resources = ab8500_poweronkey_db_resources,
13124b106fb9SLee Jones 	},
13134b106fb9SLee Jones 	{
13144b106fb9SLee Jones 		.name = "ab8500-pwm",
13154b106fb9SLee Jones 		.id = 1,
13164b106fb9SLee Jones 	},
13174b106fb9SLee Jones 	{
13184b106fb9SLee Jones 		.name = "ab8500-leds",
13194b106fb9SLee Jones 	},
13204b106fb9SLee Jones 	{
13214b106fb9SLee Jones 		.name = "abx500-temp",
13224b106fb9SLee Jones 		.num_resources = ARRAY_SIZE(ab8500_temp_resources),
13234b106fb9SLee Jones 		.resources = ab8500_temp_resources,
13244b106fb9SLee Jones 	},
1325c0eda9aeSLee Jones 	{
1326c0eda9aeSLee Jones 		.name = "ab8500-gpio",
1327c0eda9aeSLee Jones 	},
1328c0eda9aeSLee Jones 	{
1329c0eda9aeSLee Jones 		.name = "ab8540-usb",
1330c0eda9aeSLee Jones 		.num_resources = ARRAY_SIZE(ab8500_usb_resources),
1331c0eda9aeSLee Jones 		.resources = ab8500_usb_resources,
1332c0eda9aeSLee Jones 	},
1333c0eda9aeSLee Jones 	{
1334c0eda9aeSLee Jones 		.name = "ab8540-codec",
1335c0eda9aeSLee Jones 	},
1336c0eda9aeSLee Jones 	{
133744f72e53SVirupax Sadashivpetimath 		.name = "ab-iddet",
133844f72e53SVirupax Sadashivpetimath 		.num_resources = ARRAY_SIZE(ab8505_iddet_resources),
133944f72e53SVirupax Sadashivpetimath 		.resources = ab8505_iddet_resources,
134044f72e53SVirupax Sadashivpetimath 	},
1341d6255529SLinus Walleij };
1342d6255529SLinus Walleij 
1343cca69b67SMattias Wallin static ssize_t show_chip_id(struct device *dev,
1344cca69b67SMattias Wallin 				struct device_attribute *attr, char *buf)
1345cca69b67SMattias Wallin {
1346cca69b67SMattias Wallin 	struct ab8500 *ab8500;
1347cca69b67SMattias Wallin 
1348cca69b67SMattias Wallin 	ab8500 = dev_get_drvdata(dev);
1349cca69b67SMattias Wallin 	return sprintf(buf, "%#x\n", ab8500 ? ab8500->chip_id : -EINVAL);
1350cca69b67SMattias Wallin }
1351cca69b67SMattias Wallin 
1352e5c238c3SMattias Wallin /*
1353e5c238c3SMattias Wallin  * ab8500 has switched off due to (SWITCH_OFF_STATUS):
1354e5c238c3SMattias Wallin  * 0x01 Swoff bit programming
1355e5c238c3SMattias Wallin  * 0x02 Thermal protection activation
1356e5c238c3SMattias Wallin  * 0x04 Vbat lower then BattOk falling threshold
1357e5c238c3SMattias Wallin  * 0x08 Watchdog expired
1358e5c238c3SMattias Wallin  * 0x10 Non presence of 32kHz clock
1359e5c238c3SMattias Wallin  * 0x20 Battery level lower than power on reset threshold
1360e5c238c3SMattias Wallin  * 0x40 Power on key 1 pressed longer than 10 seconds
1361e5c238c3SMattias Wallin  * 0x80 DB8500 thermal shutdown
1362e5c238c3SMattias Wallin  */
1363e5c238c3SMattias Wallin static ssize_t show_switch_off_status(struct device *dev,
1364e5c238c3SMattias Wallin 				struct device_attribute *attr, char *buf)
1365e5c238c3SMattias Wallin {
1366e5c238c3SMattias Wallin 	int ret;
1367e5c238c3SMattias Wallin 	u8 value;
1368e5c238c3SMattias Wallin 	struct ab8500 *ab8500;
1369e5c238c3SMattias Wallin 
1370e5c238c3SMattias Wallin 	ab8500 = dev_get_drvdata(dev);
1371e5c238c3SMattias Wallin 	ret = get_register_interruptible(ab8500, AB8500_RTC,
1372e5c238c3SMattias Wallin 		AB8500_SWITCH_OFF_STATUS, &value);
1373e5c238c3SMattias Wallin 	if (ret < 0)
1374e5c238c3SMattias Wallin 		return ret;
1375e5c238c3SMattias Wallin 	return sprintf(buf, "%#x\n", value);
1376e5c238c3SMattias Wallin }
1377e5c238c3SMattias Wallin 
1378f04a9d8aSRajkumar Kasirajan /* use mask and set to override the register turn_on_stat value */
1379f04a9d8aSRajkumar Kasirajan void ab8500_override_turn_on_stat(u8 mask, u8 set)
1380f04a9d8aSRajkumar Kasirajan {
1381f04a9d8aSRajkumar Kasirajan 	spin_lock(&on_stat_lock);
1382f04a9d8aSRajkumar Kasirajan 	turn_on_stat_mask = mask;
1383f04a9d8aSRajkumar Kasirajan 	turn_on_stat_set = set;
1384f04a9d8aSRajkumar Kasirajan 	spin_unlock(&on_stat_lock);
1385f04a9d8aSRajkumar Kasirajan }
1386f04a9d8aSRajkumar Kasirajan 
1387b4a31037SAndrew Lynn /*
1388b4a31037SAndrew Lynn  * ab8500 has turned on due to (TURN_ON_STATUS):
1389b4a31037SAndrew Lynn  * 0x01 PORnVbat
1390b4a31037SAndrew Lynn  * 0x02 PonKey1dbF
1391b4a31037SAndrew Lynn  * 0x04 PonKey2dbF
1392b4a31037SAndrew Lynn  * 0x08 RTCAlarm
1393b4a31037SAndrew Lynn  * 0x10 MainChDet
1394b4a31037SAndrew Lynn  * 0x20 VbusDet
1395b4a31037SAndrew Lynn  * 0x40 UsbIDDetect
1396b4a31037SAndrew Lynn  * 0x80 Reserved
1397b4a31037SAndrew Lynn  */
1398b4a31037SAndrew Lynn static ssize_t show_turn_on_status(struct device *dev,
1399b4a31037SAndrew Lynn 				struct device_attribute *attr, char *buf)
1400b4a31037SAndrew Lynn {
1401b4a31037SAndrew Lynn 	int ret;
1402b4a31037SAndrew Lynn 	u8 value;
1403b4a31037SAndrew Lynn 	struct ab8500 *ab8500;
1404b4a31037SAndrew Lynn 
1405b4a31037SAndrew Lynn 	ab8500 = dev_get_drvdata(dev);
1406b4a31037SAndrew Lynn 	ret = get_register_interruptible(ab8500, AB8500_SYS_CTRL1_BLOCK,
1407b4a31037SAndrew Lynn 		AB8500_TURN_ON_STATUS, &value);
1408b4a31037SAndrew Lynn 	if (ret < 0)
1409b4a31037SAndrew Lynn 		return ret;
1410f04a9d8aSRajkumar Kasirajan 
1411f04a9d8aSRajkumar Kasirajan 	/*
1412f04a9d8aSRajkumar Kasirajan 	 * In L9540, turn_on_status register is not updated correctly if
1413f04a9d8aSRajkumar Kasirajan 	 * the device is rebooted with AC/USB charger connected. Due to
1414f04a9d8aSRajkumar Kasirajan 	 * this, the device boots android instead of entering into charge
1415f04a9d8aSRajkumar Kasirajan 	 * only mode. Read the AC/USB status register to detect the charger
1416f04a9d8aSRajkumar Kasirajan 	 * presence and update the turn on status manually.
1417f04a9d8aSRajkumar Kasirajan 	 */
1418f04a9d8aSRajkumar Kasirajan 	if (is_ab9540(ab8500)) {
1419f04a9d8aSRajkumar Kasirajan 		spin_lock(&on_stat_lock);
1420f04a9d8aSRajkumar Kasirajan 		value = (value & turn_on_stat_mask) | turn_on_stat_set;
1421f04a9d8aSRajkumar Kasirajan 		spin_unlock(&on_stat_lock);
1422f04a9d8aSRajkumar Kasirajan 	}
1423f04a9d8aSRajkumar Kasirajan 
1424b4a31037SAndrew Lynn 	return sprintf(buf, "%#x\n", value);
1425b4a31037SAndrew Lynn }
1426b4a31037SAndrew Lynn 
1427d6255529SLinus Walleij static ssize_t show_ab9540_dbbrstn(struct device *dev,
1428d6255529SLinus Walleij 				struct device_attribute *attr, char *buf)
1429d6255529SLinus Walleij {
1430d6255529SLinus Walleij 	struct ab8500 *ab8500;
1431d6255529SLinus Walleij 	int ret;
1432d6255529SLinus Walleij 	u8 value;
1433d6255529SLinus Walleij 
1434d6255529SLinus Walleij 	ab8500 = dev_get_drvdata(dev);
1435d6255529SLinus Walleij 
1436d6255529SLinus Walleij 	ret = get_register_interruptible(ab8500, AB8500_REGU_CTRL2,
1437d6255529SLinus Walleij 		AB9540_MODEM_CTRL2_REG, &value);
1438d6255529SLinus Walleij 	if (ret < 0)
1439d6255529SLinus Walleij 		return ret;
1440d6255529SLinus Walleij 
1441d6255529SLinus Walleij 	return sprintf(buf, "%d\n",
1442d6255529SLinus Walleij 			(value & AB9540_MODEM_CTRL2_SWDBBRSTN_BIT) ? 1 : 0);
1443d6255529SLinus Walleij }
1444d6255529SLinus Walleij 
1445d6255529SLinus Walleij static ssize_t store_ab9540_dbbrstn(struct device *dev,
1446d6255529SLinus Walleij 	struct device_attribute *attr, const char *buf, size_t count)
1447d6255529SLinus Walleij {
1448d6255529SLinus Walleij 	struct ab8500 *ab8500;
1449d6255529SLinus Walleij 	int ret = count;
1450d6255529SLinus Walleij 	int err;
1451d6255529SLinus Walleij 	u8 bitvalues;
1452d6255529SLinus Walleij 
1453d6255529SLinus Walleij 	ab8500 = dev_get_drvdata(dev);
1454d6255529SLinus Walleij 
1455d6255529SLinus Walleij 	if (count > 0) {
1456d6255529SLinus Walleij 		switch (buf[0]) {
1457d6255529SLinus Walleij 		case '0':
1458d6255529SLinus Walleij 			bitvalues = 0;
1459d6255529SLinus Walleij 			break;
1460d6255529SLinus Walleij 		case '1':
1461d6255529SLinus Walleij 			bitvalues = AB9540_MODEM_CTRL2_SWDBBRSTN_BIT;
1462d6255529SLinus Walleij 			break;
1463d6255529SLinus Walleij 		default:
1464d6255529SLinus Walleij 			goto exit;
1465d6255529SLinus Walleij 		}
1466d6255529SLinus Walleij 
1467d6255529SLinus Walleij 		err = mask_and_set_register_interruptible(ab8500,
1468d6255529SLinus Walleij 			AB8500_REGU_CTRL2, AB9540_MODEM_CTRL2_REG,
1469d6255529SLinus Walleij 			AB9540_MODEM_CTRL2_SWDBBRSTN_BIT, bitvalues);
1470d6255529SLinus Walleij 		if (err)
1471d6255529SLinus Walleij 			dev_info(ab8500->dev,
1472d6255529SLinus Walleij 				"Failed to set DBBRSTN %c, err %#x\n",
1473d6255529SLinus Walleij 				buf[0], err);
1474d6255529SLinus Walleij 	}
1475d6255529SLinus Walleij 
1476d6255529SLinus Walleij exit:
1477d6255529SLinus Walleij 	return ret;
1478d6255529SLinus Walleij }
1479d6255529SLinus Walleij 
1480cca69b67SMattias Wallin static DEVICE_ATTR(chip_id, S_IRUGO, show_chip_id, NULL);
1481e5c238c3SMattias Wallin static DEVICE_ATTR(switch_off_status, S_IRUGO, show_switch_off_status, NULL);
1482b4a31037SAndrew Lynn static DEVICE_ATTR(turn_on_status, S_IRUGO, show_turn_on_status, NULL);
1483d6255529SLinus Walleij static DEVICE_ATTR(dbbrstn, S_IRUGO | S_IWUSR,
1484d6255529SLinus Walleij 			show_ab9540_dbbrstn, store_ab9540_dbbrstn);
1485cca69b67SMattias Wallin 
1486cca69b67SMattias Wallin static struct attribute *ab8500_sysfs_entries[] = {
1487cca69b67SMattias Wallin 	&dev_attr_chip_id.attr,
1488e5c238c3SMattias Wallin 	&dev_attr_switch_off_status.attr,
1489b4a31037SAndrew Lynn 	&dev_attr_turn_on_status.attr,
1490cca69b67SMattias Wallin 	NULL,
1491cca69b67SMattias Wallin };
1492cca69b67SMattias Wallin 
1493d6255529SLinus Walleij static struct attribute *ab9540_sysfs_entries[] = {
1494d6255529SLinus Walleij 	&dev_attr_chip_id.attr,
1495d6255529SLinus Walleij 	&dev_attr_switch_off_status.attr,
1496d6255529SLinus Walleij 	&dev_attr_turn_on_status.attr,
1497d6255529SLinus Walleij 	&dev_attr_dbbrstn.attr,
1498d6255529SLinus Walleij 	NULL,
1499d6255529SLinus Walleij };
1500d6255529SLinus Walleij 
1501cca69b67SMattias Wallin static struct attribute_group ab8500_attr_group = {
1502cca69b67SMattias Wallin 	.attrs	= ab8500_sysfs_entries,
1503cca69b67SMattias Wallin };
1504cca69b67SMattias Wallin 
1505d6255529SLinus Walleij static struct attribute_group ab9540_attr_group = {
1506d6255529SLinus Walleij 	.attrs	= ab9540_sysfs_entries,
1507d6255529SLinus Walleij };
1508d6255529SLinus Walleij 
1509f791be49SBill Pemberton static int ab8500_probe(struct platform_device *pdev)
151062579266SRabin Vincent {
1511b04c530cSJonas Aaberg 	static char *switch_off_status[] = {
1512b04c530cSJonas Aaberg 		"Swoff bit programming",
1513b04c530cSJonas Aaberg 		"Thermal protection activation",
1514b04c530cSJonas Aaberg 		"Vbat lower then BattOk falling threshold",
1515b04c530cSJonas Aaberg 		"Watchdog expired",
1516b04c530cSJonas Aaberg 		"Non presence of 32kHz clock",
1517b04c530cSJonas Aaberg 		"Battery level lower than power on reset threshold",
1518b04c530cSJonas Aaberg 		"Power on key 1 pressed longer than 10 seconds",
1519b04c530cSJonas Aaberg 		"DB8500 thermal shutdown"};
1520d28f1db8SLee Jones 	struct ab8500_platform_data *plat = dev_get_platdata(&pdev->dev);
1521d28f1db8SLee Jones 	const struct platform_device_id *platid = platform_get_device_id(pdev);
15226bc4a568SLee Jones 	enum ab8500_version version = AB8500_VERSION_UNDEFINED;
15236bc4a568SLee Jones 	struct device_node *np = pdev->dev.of_node;
1524d28f1db8SLee Jones 	struct ab8500 *ab8500;
1525d28f1db8SLee Jones 	struct resource *resource;
152662579266SRabin Vincent 	int ret;
152762579266SRabin Vincent 	int i;
152847c16975SMattias Wallin 	u8 value;
152962579266SRabin Vincent 
15308c4203cbSLee Jones 	ab8500 = devm_kzalloc(&pdev->dev, sizeof *ab8500, GFP_KERNEL);
1531d28f1db8SLee Jones 	if (!ab8500)
1532d28f1db8SLee Jones 		return -ENOMEM;
1533d28f1db8SLee Jones 
153462579266SRabin Vincent 	if (plat)
153562579266SRabin Vincent 		ab8500->irq_base = plat->irq_base;
153662579266SRabin Vincent 
1537d28f1db8SLee Jones 	ab8500->dev = &pdev->dev;
1538d28f1db8SLee Jones 
1539d28f1db8SLee Jones 	resource = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
15408c4203cbSLee Jones 	if (!resource)
15418c4203cbSLee Jones 		return -ENODEV;
1542d28f1db8SLee Jones 
1543d28f1db8SLee Jones 	ab8500->irq = resource->start;
1544d28f1db8SLee Jones 
1545822672a7SLee Jones 	ab8500->read = ab8500_prcmu_read;
1546822672a7SLee Jones 	ab8500->write = ab8500_prcmu_write;
1547822672a7SLee Jones 	ab8500->write_masked = ab8500_prcmu_write_masked;
1548d28f1db8SLee Jones 
154962579266SRabin Vincent 	mutex_init(&ab8500->lock);
155062579266SRabin Vincent 	mutex_init(&ab8500->irq_lock);
1551112a80d2SJonas Aaberg 	atomic_set(&ab8500->transfer_ongoing, 0);
155262579266SRabin Vincent 
1553d28f1db8SLee Jones 	platform_set_drvdata(pdev, ab8500);
1554d28f1db8SLee Jones 
15556bc4a568SLee Jones 	if (platid)
15566bc4a568SLee Jones 		version = platid->driver_data;
15576bc4a568SLee Jones 
15580f620837SLinus Walleij 	if (version != AB8500_VERSION_UNDEFINED)
15590f620837SLinus Walleij 		ab8500->version = version;
15600f620837SLinus Walleij 	else {
15610f620837SLinus Walleij 		ret = get_register_interruptible(ab8500, AB8500_MISC,
15620f620837SLinus Walleij 			AB8500_IC_NAME_REG, &value);
15630f620837SLinus Walleij 		if (ret < 0)
15648c4203cbSLee Jones 			return ret;
15650f620837SLinus Walleij 
15660f620837SLinus Walleij 		ab8500->version = value;
15670f620837SLinus Walleij 	}
15680f620837SLinus Walleij 
156947c16975SMattias Wallin 	ret = get_register_interruptible(ab8500, AB8500_MISC,
157047c16975SMattias Wallin 		AB8500_REV_REG, &value);
157162579266SRabin Vincent 	if (ret < 0)
15728c4203cbSLee Jones 		return ret;
157362579266SRabin Vincent 
157447c16975SMattias Wallin 	ab8500->chip_id = value;
157562579266SRabin Vincent 
15760f620837SLinus Walleij 	dev_info(ab8500->dev, "detected chip, %s rev. %1x.%1x\n",
15770f620837SLinus Walleij 			ab8500_version_str[ab8500->version],
15780f620837SLinus Walleij 			ab8500->chip_id >> 4,
15790f620837SLinus Walleij 			ab8500->chip_id & 0x0F);
15800f620837SLinus Walleij 
1581*3e1a498fSLee Jones 	/* Configure AB8540 */
1582*3e1a498fSLee Jones 	if (is_ab8540(ab8500)) {
1583*3e1a498fSLee Jones 		ab8500->mask_size = AB8540_NUM_IRQ_REGS;
1584*3e1a498fSLee Jones 		ab8500->irq_reg_offset = ab8540_irq_regoffset;
1585*3e1a498fSLee Jones 		ab8500->it_latchhier_num = AB8540_IT_LATCHHIER_NUM;
1586*3e1a498fSLee Jones 	}/* Configure AB8500 or AB9540 IRQ */
1587*3e1a498fSLee Jones 	else if (is_ab9540(ab8500) || is_ab8505(ab8500)) {
1588d6255529SLinus Walleij 		ab8500->mask_size = AB9540_NUM_IRQ_REGS;
1589d6255529SLinus Walleij 		ab8500->irq_reg_offset = ab9540_irq_regoffset;
1590*3e1a498fSLee Jones 		ab8500->it_latchhier_num = AB8500_IT_LATCHHIER_NUM;
1591d6255529SLinus Walleij 	} else {
15922ced445eSLinus Walleij 		ab8500->mask_size = AB8500_NUM_IRQ_REGS;
15932ced445eSLinus Walleij 		ab8500->irq_reg_offset = ab8500_irq_regoffset;
1594*3e1a498fSLee Jones 		ab8500->it_latchhier_num = AB8500_IT_LATCHHIER_NUM;
1595d6255529SLinus Walleij 	}
15968c4203cbSLee Jones 	ab8500->mask = devm_kzalloc(&pdev->dev, ab8500->mask_size, GFP_KERNEL);
15972ced445eSLinus Walleij 	if (!ab8500->mask)
15982ced445eSLinus Walleij 		return -ENOMEM;
15998c4203cbSLee Jones 	ab8500->oldmask = devm_kzalloc(&pdev->dev, ab8500->mask_size, GFP_KERNEL);
16008c4203cbSLee Jones 	if (!ab8500->oldmask)
16018c4203cbSLee Jones 		return -ENOMEM;
16028c4203cbSLee Jones 
1603e5c238c3SMattias Wallin 	/*
1604e5c238c3SMattias Wallin 	 * ab8500 has switched off due to (SWITCH_OFF_STATUS):
1605e5c238c3SMattias Wallin 	 * 0x01 Swoff bit programming
1606e5c238c3SMattias Wallin 	 * 0x02 Thermal protection activation
1607e5c238c3SMattias Wallin 	 * 0x04 Vbat lower then BattOk falling threshold
1608e5c238c3SMattias Wallin 	 * 0x08 Watchdog expired
1609e5c238c3SMattias Wallin 	 * 0x10 Non presence of 32kHz clock
1610e5c238c3SMattias Wallin 	 * 0x20 Battery level lower than power on reset threshold
1611e5c238c3SMattias Wallin 	 * 0x40 Power on key 1 pressed longer than 10 seconds
1612e5c238c3SMattias Wallin 	 * 0x80 DB8500 thermal shutdown
1613e5c238c3SMattias Wallin 	 */
1614e5c238c3SMattias Wallin 
1615e5c238c3SMattias Wallin 	ret = get_register_interruptible(ab8500, AB8500_RTC,
1616e5c238c3SMattias Wallin 		AB8500_SWITCH_OFF_STATUS, &value);
1617e5c238c3SMattias Wallin 	if (ret < 0)
1618e5c238c3SMattias Wallin 		return ret;
1619b04c530cSJonas Aaberg 	dev_info(ab8500->dev, "switch off cause(s) (%#x): ", value);
1620b04c530cSJonas Aaberg 
1621b04c530cSJonas Aaberg 	if (value) {
1622b04c530cSJonas Aaberg 		for (i = 0; i < ARRAY_SIZE(switch_off_status); i++) {
1623b04c530cSJonas Aaberg 			if (value & 1)
1624b04c530cSJonas Aaberg 				printk(KERN_CONT " \"%s\"",
1625b04c530cSJonas Aaberg 				       switch_off_status[i]);
1626b04c530cSJonas Aaberg 			value = value >> 1;
1627b04c530cSJonas Aaberg 
1628b04c530cSJonas Aaberg 		}
1629b04c530cSJonas Aaberg 		printk(KERN_CONT "\n");
1630b04c530cSJonas Aaberg 	} else {
1631b04c530cSJonas Aaberg 		printk(KERN_CONT " None\n");
1632b04c530cSJonas Aaberg 	}
1633e5c238c3SMattias Wallin 
163462579266SRabin Vincent 	if (plat && plat->init)
163562579266SRabin Vincent 		plat->init(ab8500);
1636f04a9d8aSRajkumar Kasirajan 	if (is_ab9540(ab8500)) {
1637f04a9d8aSRajkumar Kasirajan 		ret = get_register_interruptible(ab8500, AB8500_CHARGER,
1638f04a9d8aSRajkumar Kasirajan 			AB8500_CH_USBCH_STAT1_REG, &value);
1639f04a9d8aSRajkumar Kasirajan 		if (ret < 0)
1640f04a9d8aSRajkumar Kasirajan 			return ret;
1641f04a9d8aSRajkumar Kasirajan 		if ((value & VBUS_DET_DBNC1) && (value & VBUS_DET_DBNC100))
1642f04a9d8aSRajkumar Kasirajan 			ab8500_override_turn_on_stat(~AB8500_POW_KEY_1_ON,
1643f04a9d8aSRajkumar Kasirajan 						     AB8500_VBUS_DET);
1644f04a9d8aSRajkumar Kasirajan 	}
164562579266SRabin Vincent 
164662579266SRabin Vincent 	/* Clear and mask all interrupts */
16472ced445eSLinus Walleij 	for (i = 0; i < ab8500->mask_size; i++) {
16480f620837SLinus Walleij 		/*
16490f620837SLinus Walleij 		 * Interrupt register 12 doesn't exist prior to AB8500 version
16500f620837SLinus Walleij 		 * 2.0
16510f620837SLinus Walleij 		 */
16520f620837SLinus Walleij 		if (ab8500->irq_reg_offset[i] == 11 &&
16530f620837SLinus Walleij 				is_ab8500_1p1_or_earlier(ab8500))
165492d50a41SMattias Wallin 			continue;
165562579266SRabin Vincent 
1656*3e1a498fSLee Jones 		if (ab8500->irq_reg_offset[i] < 0)
1657*3e1a498fSLee Jones 			continue;
1658*3e1a498fSLee Jones 
165947c16975SMattias Wallin 		get_register_interruptible(ab8500, AB8500_INTERRUPT,
16602ced445eSLinus Walleij 			AB8500_IT_LATCH1_REG + ab8500->irq_reg_offset[i],
166192d50a41SMattias Wallin 			&value);
166247c16975SMattias Wallin 		set_register_interruptible(ab8500, AB8500_INTERRUPT,
16632ced445eSLinus Walleij 			AB8500_IT_MASK1_REG + ab8500->irq_reg_offset[i], 0xff);
166462579266SRabin Vincent 	}
166562579266SRabin Vincent 
166647c16975SMattias Wallin 	ret = abx500_register_ops(ab8500->dev, &ab8500_ops);
166747c16975SMattias Wallin 	if (ret)
16688c4203cbSLee Jones 		return ret;
166947c16975SMattias Wallin 
16702ced445eSLinus Walleij 	for (i = 0; i < ab8500->mask_size; i++)
167162579266SRabin Vincent 		ab8500->mask[i] = ab8500->oldmask[i] = 0xff;
167262579266SRabin Vincent 
167306e589efSLee Jones 	ret = ab8500_irq_init(ab8500, np);
167462579266SRabin Vincent 	if (ret)
16758c4203cbSLee Jones 		return ret;
167662579266SRabin Vincent 
16777ccfe9b1SMichel JAOUEN 	/*  Activate this feature only in ab9540 */
16787ccfe9b1SMichel JAOUEN 	/*  till tests are done on ab8500 1p2 or later*/
167906e589efSLee Jones 	if (is_ab9540(ab8500)) {
16808c4203cbSLee Jones 		ret = devm_request_threaded_irq(&pdev->dev, ab8500->irq, NULL,
16817ccfe9b1SMichel JAOUEN 						ab8500_hierarchical_irq,
16827ccfe9b1SMichel JAOUEN 						IRQF_ONESHOT | IRQF_NO_SUSPEND,
16837ccfe9b1SMichel JAOUEN 						"ab8500", ab8500);
168406e589efSLee Jones 	}
168506e589efSLee Jones 	else {
16868c4203cbSLee Jones 		ret = devm_request_threaded_irq(&pdev->dev, ab8500->irq, NULL,
16877ccfe9b1SMichel JAOUEN 						ab8500_irq,
16884f079985SMattias Wallin 						IRQF_ONESHOT | IRQF_NO_SUSPEND,
16894f079985SMattias Wallin 						"ab8500", ab8500);
169062579266SRabin Vincent 		if (ret)
16918c4203cbSLee Jones 			return ret;
169262579266SRabin Vincent 	}
169362579266SRabin Vincent 
1694d6255529SLinus Walleij 	if (is_ab9540(ab8500))
1695d6255529SLinus Walleij 		ret = mfd_add_devices(ab8500->dev, 0, ab9540_devs,
1696d6255529SLinus Walleij 				ARRAY_SIZE(ab9540_devs), NULL,
169755692af5SMark Brown 				ab8500->irq_base, ab8500->domain);
1698c0eda9aeSLee Jones 	else if (is_ab8540(ab8500))
1699c0eda9aeSLee Jones 		ret = mfd_add_devices(ab8500->dev, 0, ab8540_devs,
1700c0eda9aeSLee Jones 			      ARRAY_SIZE(ab8540_devs), NULL,
1701c0eda9aeSLee Jones 			      ab8500->irq_base, ab8500->domain);
1702c0eda9aeSLee Jones 	else if (is_ab8505(ab8500))
1703c0eda9aeSLee Jones 		ret = mfd_add_devices(ab8500->dev, 0, ab8505_devs,
1704c0eda9aeSLee Jones 			      ARRAY_SIZE(ab8505_devs), NULL,
1705c0eda9aeSLee Jones 			      ab8500->irq_base, ab8500->domain);
1706d6255529SLinus Walleij 	else
1707549931f9SSundar R Iyer 		ret = mfd_add_devices(ab8500->dev, 0, ab8500_devs,
170844f72e53SVirupax Sadashivpetimath 				ARRAY_SIZE(ab8500_devs), NULL,
170955692af5SMark Brown 				ab8500->irq_base, ab8500->domain);
17106bc4a568SLee Jones 	if (ret)
17118c4203cbSLee Jones 		return ret;
171244f72e53SVirupax Sadashivpetimath 
17136ef9418cSRickard Andersson 	if (!no_bm) {
17146ef9418cSRickard Andersson 		/* Add battery management devices */
17156ef9418cSRickard Andersson 		ret = mfd_add_devices(ab8500->dev, 0, ab8500_bm_devs,
17166ef9418cSRickard Andersson 				      ARRAY_SIZE(ab8500_bm_devs), NULL,
171755692af5SMark Brown 				      ab8500->irq_base, ab8500->domain);
17186ef9418cSRickard Andersson 		if (ret)
17196ef9418cSRickard Andersson 			dev_err(ab8500->dev, "error adding bm devices\n");
17206ef9418cSRickard Andersson 	}
17216ef9418cSRickard Andersson 
1722d6255529SLinus Walleij 	if (is_ab9540(ab8500))
1723d6255529SLinus Walleij 		ret = sysfs_create_group(&ab8500->dev->kobj,
1724d6255529SLinus Walleij 					&ab9540_attr_group);
1725d6255529SLinus Walleij 	else
1726d6255529SLinus Walleij 		ret = sysfs_create_group(&ab8500->dev->kobj,
1727d6255529SLinus Walleij 					&ab8500_attr_group);
1728cca69b67SMattias Wallin 	if (ret)
1729cca69b67SMattias Wallin 		dev_err(ab8500->dev, "error creating sysfs entries\n");
173006e589efSLee Jones 
173162579266SRabin Vincent 	return ret;
173262579266SRabin Vincent }
173362579266SRabin Vincent 
17344740f73fSBill Pemberton static int ab8500_remove(struct platform_device *pdev)
173562579266SRabin Vincent {
1736d28f1db8SLee Jones 	struct ab8500 *ab8500 = platform_get_drvdata(pdev);
1737d28f1db8SLee Jones 
1738d6255529SLinus Walleij 	if (is_ab9540(ab8500))
1739d6255529SLinus Walleij 		sysfs_remove_group(&ab8500->dev->kobj, &ab9540_attr_group);
1740d6255529SLinus Walleij 	else
1741cca69b67SMattias Wallin 		sysfs_remove_group(&ab8500->dev->kobj, &ab8500_attr_group);
174206e589efSLee Jones 
174362579266SRabin Vincent 	mfd_remove_devices(ab8500->dev);
174462579266SRabin Vincent 
174562579266SRabin Vincent 	return 0;
174662579266SRabin Vincent }
174762579266SRabin Vincent 
1748d28f1db8SLee Jones static const struct platform_device_id ab8500_id[] = {
1749d28f1db8SLee Jones 	{ "ab8500-core", AB8500_VERSION_AB8500 },
1750d28f1db8SLee Jones 	{ "ab8505-i2c", AB8500_VERSION_AB8505 },
1751d28f1db8SLee Jones 	{ "ab9540-i2c", AB8500_VERSION_AB9540 },
1752d28f1db8SLee Jones 	{ "ab8540-i2c", AB8500_VERSION_AB8540 },
1753d28f1db8SLee Jones 	{ }
1754d28f1db8SLee Jones };
1755d28f1db8SLee Jones 
1756d28f1db8SLee Jones static struct platform_driver ab8500_core_driver = {
1757d28f1db8SLee Jones 	.driver = {
1758d28f1db8SLee Jones 		.name = "ab8500-core",
1759d28f1db8SLee Jones 		.owner = THIS_MODULE,
1760d28f1db8SLee Jones 	},
1761d28f1db8SLee Jones 	.probe	= ab8500_probe,
176284449216SBill Pemberton 	.remove	= ab8500_remove,
1763d28f1db8SLee Jones 	.id_table = ab8500_id,
1764d28f1db8SLee Jones };
1765d28f1db8SLee Jones 
1766d28f1db8SLee Jones static int __init ab8500_core_init(void)
1767d28f1db8SLee Jones {
1768d28f1db8SLee Jones 	return platform_driver_register(&ab8500_core_driver);
1769d28f1db8SLee Jones }
1770d28f1db8SLee Jones 
1771d28f1db8SLee Jones static void __exit ab8500_core_exit(void)
1772d28f1db8SLee Jones {
1773d28f1db8SLee Jones 	platform_driver_unregister(&ab8500_core_driver);
1774d28f1db8SLee Jones }
1775ba7cbc3eSLee Jones core_initcall(ab8500_core_init);
1776d28f1db8SLee Jones module_exit(ab8500_core_exit);
1777d28f1db8SLee Jones 
1778adceed62SMattias Wallin MODULE_AUTHOR("Mattias Wallin, Srinidhi Kasagar, Rabin Vincent");
177962579266SRabin Vincent MODULE_DESCRIPTION("AB8500 MFD core");
178062579266SRabin Vincent MODULE_LICENSE("GPL v2");
1781