xref: /openbmc/linux/drivers/mfd/ab8500-core.c (revision e0f1abeb)
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>
22d28f1db8SLee Jones #include <linux/mfd/dbx500-prcmu.h>
23549931f9SSundar R Iyer #include <linux/regulator/ab8500.h>
246bc4a568SLee Jones #include <linux/of.h>
256bc4a568SLee Jones #include <linux/of_device.h>
2662579266SRabin Vincent 
2762579266SRabin Vincent /*
2862579266SRabin Vincent  * Interrupt register offsets
2962579266SRabin Vincent  * Bank : 0x0E
3062579266SRabin Vincent  */
3147c16975SMattias Wallin #define AB8500_IT_SOURCE1_REG		0x00
3247c16975SMattias Wallin #define AB8500_IT_SOURCE2_REG		0x01
3347c16975SMattias Wallin #define AB8500_IT_SOURCE3_REG		0x02
3447c16975SMattias Wallin #define AB8500_IT_SOURCE4_REG		0x03
3547c16975SMattias Wallin #define AB8500_IT_SOURCE5_REG		0x04
3647c16975SMattias Wallin #define AB8500_IT_SOURCE6_REG		0x05
3747c16975SMattias Wallin #define AB8500_IT_SOURCE7_REG		0x06
3847c16975SMattias Wallin #define AB8500_IT_SOURCE8_REG		0x07
39d6255529SLinus Walleij #define AB9540_IT_SOURCE13_REG		0x0C
4047c16975SMattias Wallin #define AB8500_IT_SOURCE19_REG		0x12
4147c16975SMattias Wallin #define AB8500_IT_SOURCE20_REG		0x13
4247c16975SMattias Wallin #define AB8500_IT_SOURCE21_REG		0x14
4347c16975SMattias Wallin #define AB8500_IT_SOURCE22_REG		0x15
4447c16975SMattias Wallin #define AB8500_IT_SOURCE23_REG		0x16
4547c16975SMattias Wallin #define AB8500_IT_SOURCE24_REG		0x17
4662579266SRabin Vincent 
4762579266SRabin Vincent /*
4862579266SRabin Vincent  * latch registers
4962579266SRabin Vincent  */
5047c16975SMattias Wallin #define AB8500_IT_LATCH1_REG		0x20
5147c16975SMattias Wallin #define AB8500_IT_LATCH2_REG		0x21
5247c16975SMattias Wallin #define AB8500_IT_LATCH3_REG		0x22
5347c16975SMattias Wallin #define AB8500_IT_LATCH4_REG		0x23
5447c16975SMattias Wallin #define AB8500_IT_LATCH5_REG		0x24
5547c16975SMattias Wallin #define AB8500_IT_LATCH6_REG		0x25
5647c16975SMattias Wallin #define AB8500_IT_LATCH7_REG		0x26
5747c16975SMattias Wallin #define AB8500_IT_LATCH8_REG		0x27
5847c16975SMattias Wallin #define AB8500_IT_LATCH9_REG		0x28
5947c16975SMattias Wallin #define AB8500_IT_LATCH10_REG		0x29
6092d50a41SMattias Wallin #define AB8500_IT_LATCH12_REG		0x2B
61d6255529SLinus Walleij #define AB9540_IT_LATCH13_REG		0x2C
6247c16975SMattias Wallin #define AB8500_IT_LATCH19_REG		0x32
6347c16975SMattias Wallin #define AB8500_IT_LATCH20_REG		0x33
6447c16975SMattias Wallin #define AB8500_IT_LATCH21_REG		0x34
6547c16975SMattias Wallin #define AB8500_IT_LATCH22_REG		0x35
6647c16975SMattias Wallin #define AB8500_IT_LATCH23_REG		0x36
6747c16975SMattias Wallin #define AB8500_IT_LATCH24_REG		0x37
6862579266SRabin Vincent 
6962579266SRabin Vincent /*
7062579266SRabin Vincent  * mask registers
7162579266SRabin Vincent  */
7262579266SRabin Vincent 
7347c16975SMattias Wallin #define AB8500_IT_MASK1_REG		0x40
7447c16975SMattias Wallin #define AB8500_IT_MASK2_REG		0x41
7547c16975SMattias Wallin #define AB8500_IT_MASK3_REG		0x42
7647c16975SMattias Wallin #define AB8500_IT_MASK4_REG		0x43
7747c16975SMattias Wallin #define AB8500_IT_MASK5_REG		0x44
7847c16975SMattias Wallin #define AB8500_IT_MASK6_REG		0x45
7947c16975SMattias Wallin #define AB8500_IT_MASK7_REG		0x46
8047c16975SMattias Wallin #define AB8500_IT_MASK8_REG		0x47
8147c16975SMattias Wallin #define AB8500_IT_MASK9_REG		0x48
8247c16975SMattias Wallin #define AB8500_IT_MASK10_REG		0x49
8347c16975SMattias Wallin #define AB8500_IT_MASK11_REG		0x4A
8447c16975SMattias Wallin #define AB8500_IT_MASK12_REG		0x4B
8547c16975SMattias Wallin #define AB8500_IT_MASK13_REG		0x4C
8647c16975SMattias Wallin #define AB8500_IT_MASK14_REG		0x4D
8747c16975SMattias Wallin #define AB8500_IT_MASK15_REG		0x4E
8847c16975SMattias Wallin #define AB8500_IT_MASK16_REG		0x4F
8947c16975SMattias Wallin #define AB8500_IT_MASK17_REG		0x50
9047c16975SMattias Wallin #define AB8500_IT_MASK18_REG		0x51
9147c16975SMattias Wallin #define AB8500_IT_MASK19_REG		0x52
9247c16975SMattias Wallin #define AB8500_IT_MASK20_REG		0x53
9347c16975SMattias Wallin #define AB8500_IT_MASK21_REG		0x54
9447c16975SMattias Wallin #define AB8500_IT_MASK22_REG		0x55
9547c16975SMattias Wallin #define AB8500_IT_MASK23_REG		0x56
9647c16975SMattias Wallin #define AB8500_IT_MASK24_REG		0x57
9762579266SRabin Vincent 
987ccfe9b1SMichel JAOUEN /*
997ccfe9b1SMichel JAOUEN  * latch hierarchy registers
1007ccfe9b1SMichel JAOUEN  */
1017ccfe9b1SMichel JAOUEN #define AB8500_IT_LATCHHIER1_REG	0x60
1027ccfe9b1SMichel JAOUEN #define AB8500_IT_LATCHHIER2_REG	0x61
1037ccfe9b1SMichel JAOUEN #define AB8500_IT_LATCHHIER3_REG	0x62
1047ccfe9b1SMichel JAOUEN 
1057ccfe9b1SMichel JAOUEN #define AB8500_IT_LATCHHIER_NUM		3
1067ccfe9b1SMichel JAOUEN 
10747c16975SMattias Wallin #define AB8500_REV_REG			0x80
1080f620837SLinus Walleij #define AB8500_IC_NAME_REG		0x82
109e5c238c3SMattias Wallin #define AB8500_SWITCH_OFF_STATUS	0x00
11062579266SRabin Vincent 
111b4a31037SAndrew Lynn #define AB8500_TURN_ON_STATUS		0x00
112b4a31037SAndrew Lynn 
1136ef9418cSRickard Andersson static bool no_bm; /* No battery management */
1146ef9418cSRickard Andersson module_param(no_bm, bool, S_IRUGO);
1156ef9418cSRickard Andersson 
116d6255529SLinus Walleij #define AB9540_MODEM_CTRL2_REG			0x23
117d6255529SLinus Walleij #define AB9540_MODEM_CTRL2_SWDBBRSTN_BIT	BIT(2)
118d6255529SLinus Walleij 
11962579266SRabin Vincent /*
12062579266SRabin Vincent  * Map interrupt numbers to the LATCH and MASK register offsets, Interrupt
1212ced445eSLinus Walleij  * numbers are indexed into this array with (num / 8). The interupts are
1222ced445eSLinus Walleij  * defined in linux/mfd/ab8500.h
12362579266SRabin Vincent  *
12462579266SRabin Vincent  * This is one off from the register names, i.e. AB8500_IT_MASK1_REG is at
12562579266SRabin Vincent  * offset 0.
12662579266SRabin Vincent  */
1272ced445eSLinus Walleij /* AB8500 support */
12862579266SRabin Vincent static const int ab8500_irq_regoffset[AB8500_NUM_IRQ_REGS] = {
12992d50a41SMattias Wallin 	0, 1, 2, 3, 4, 6, 7, 8, 9, 11, 18, 19, 20, 21,
13062579266SRabin Vincent };
13162579266SRabin Vincent 
132d6255529SLinus Walleij /* AB9540 support */
133d6255529SLinus Walleij static const int ab9540_irq_regoffset[AB9540_NUM_IRQ_REGS] = {
134d6255529SLinus Walleij 	0, 1, 2, 3, 4, 6, 7, 8, 9, 11, 18, 19, 20, 21, 12, 13, 24,
135d6255529SLinus Walleij };
136d6255529SLinus Walleij 
1370f620837SLinus Walleij static const char ab8500_version_str[][7] = {
1380f620837SLinus Walleij 	[AB8500_VERSION_AB8500] = "AB8500",
1390f620837SLinus Walleij 	[AB8500_VERSION_AB8505] = "AB8505",
1400f620837SLinus Walleij 	[AB8500_VERSION_AB9540] = "AB9540",
1410f620837SLinus Walleij 	[AB8500_VERSION_AB8540] = "AB8540",
1420f620837SLinus Walleij };
1430f620837SLinus Walleij 
144822672a7SLee Jones static int ab8500_prcmu_write(struct ab8500 *ab8500, u16 addr, u8 data)
145d28f1db8SLee Jones {
146d28f1db8SLee Jones 	int ret;
147d28f1db8SLee Jones 
148d28f1db8SLee Jones 	ret = prcmu_abb_write((u8)(addr >> 8), (u8)(addr & 0xFF), &data, 1);
149d28f1db8SLee Jones 	if (ret < 0)
150d28f1db8SLee Jones 		dev_err(ab8500->dev, "prcmu i2c error %d\n", ret);
151d28f1db8SLee Jones 	return ret;
152d28f1db8SLee Jones }
153d28f1db8SLee Jones 
154822672a7SLee Jones static int ab8500_prcmu_write_masked(struct ab8500 *ab8500, u16 addr, u8 mask,
155d28f1db8SLee Jones 	u8 data)
156d28f1db8SLee Jones {
157d28f1db8SLee Jones 	int ret;
158d28f1db8SLee Jones 
159d28f1db8SLee Jones 	ret = prcmu_abb_write_masked((u8)(addr >> 8), (u8)(addr & 0xFF), &data,
160d28f1db8SLee Jones 		&mask, 1);
161d28f1db8SLee Jones 	if (ret < 0)
162d28f1db8SLee Jones 		dev_err(ab8500->dev, "prcmu i2c error %d\n", ret);
163d28f1db8SLee Jones 	return ret;
164d28f1db8SLee Jones }
165d28f1db8SLee Jones 
166822672a7SLee Jones static int ab8500_prcmu_read(struct ab8500 *ab8500, u16 addr)
167d28f1db8SLee Jones {
168d28f1db8SLee Jones 	int ret;
169d28f1db8SLee Jones 	u8 data;
170d28f1db8SLee Jones 
171d28f1db8SLee Jones 	ret = prcmu_abb_read((u8)(addr >> 8), (u8)(addr & 0xFF), &data, 1);
172d28f1db8SLee Jones 	if (ret < 0) {
173d28f1db8SLee Jones 		dev_err(ab8500->dev, "prcmu i2c error %d\n", ret);
174d28f1db8SLee Jones 		return ret;
175d28f1db8SLee Jones 	}
176d28f1db8SLee Jones 	return (int)data;
177d28f1db8SLee Jones }
178d28f1db8SLee Jones 
17947c16975SMattias Wallin static int ab8500_get_chip_id(struct device *dev)
18047c16975SMattias Wallin {
1816bce7bf1SMattias Wallin 	struct ab8500 *ab8500;
1826bce7bf1SMattias Wallin 
1836bce7bf1SMattias Wallin 	if (!dev)
1846bce7bf1SMattias Wallin 		return -EINVAL;
1856bce7bf1SMattias Wallin 	ab8500 = dev_get_drvdata(dev->parent);
1866bce7bf1SMattias Wallin 	return ab8500 ? (int)ab8500->chip_id : -EINVAL;
18747c16975SMattias Wallin }
18847c16975SMattias Wallin 
18947c16975SMattias Wallin static int set_register_interruptible(struct ab8500 *ab8500, u8 bank,
19047c16975SMattias Wallin 	u8 reg, u8 data)
19162579266SRabin Vincent {
19262579266SRabin Vincent 	int ret;
19347c16975SMattias Wallin 	/*
19447c16975SMattias Wallin 	 * Put the u8 bank and u8 register together into a an u16.
19547c16975SMattias Wallin 	 * The bank on higher 8 bits and register in lower 8 bits.
19647c16975SMattias Wallin 	 * */
19747c16975SMattias Wallin 	u16 addr = ((u16)bank) << 8 | reg;
19862579266SRabin Vincent 
19962579266SRabin Vincent 	dev_vdbg(ab8500->dev, "wr: addr %#x <= %#x\n", addr, data);
20062579266SRabin Vincent 
201392cbd1eSRabin Vincent 	mutex_lock(&ab8500->lock);
20247c16975SMattias Wallin 
20347c16975SMattias Wallin 	ret = ab8500->write(ab8500, addr, data);
20447c16975SMattias Wallin 	if (ret < 0)
20547c16975SMattias Wallin 		dev_err(ab8500->dev, "failed to write reg %#x: %d\n",
20647c16975SMattias Wallin 			addr, ret);
20747c16975SMattias Wallin 	mutex_unlock(&ab8500->lock);
20847c16975SMattias Wallin 
20947c16975SMattias Wallin 	return ret;
21047c16975SMattias Wallin }
21147c16975SMattias Wallin 
21247c16975SMattias Wallin static int ab8500_set_register(struct device *dev, u8 bank,
21347c16975SMattias Wallin 	u8 reg, u8 value)
21447c16975SMattias Wallin {
215112a80d2SJonas Aaberg 	int ret;
21647c16975SMattias Wallin 	struct ab8500 *ab8500 = dev_get_drvdata(dev->parent);
21747c16975SMattias Wallin 
218112a80d2SJonas Aaberg 	atomic_inc(&ab8500->transfer_ongoing);
219112a80d2SJonas Aaberg 	ret = set_register_interruptible(ab8500, bank, reg, value);
220112a80d2SJonas Aaberg 	atomic_dec(&ab8500->transfer_ongoing);
221112a80d2SJonas Aaberg 	return ret;
22247c16975SMattias Wallin }
22347c16975SMattias Wallin 
22447c16975SMattias Wallin static int get_register_interruptible(struct ab8500 *ab8500, u8 bank,
22547c16975SMattias Wallin 	u8 reg, u8 *value)
22647c16975SMattias Wallin {
22747c16975SMattias Wallin 	int ret;
22847c16975SMattias Wallin 	/* put the u8 bank and u8 reg together into a an u16.
22947c16975SMattias Wallin 	 * bank on higher 8 bits and reg in lower */
23047c16975SMattias Wallin 	u16 addr = ((u16)bank) << 8 | reg;
23147c16975SMattias Wallin 
232392cbd1eSRabin Vincent 	mutex_lock(&ab8500->lock);
23347c16975SMattias Wallin 
23447c16975SMattias Wallin 	ret = ab8500->read(ab8500, addr);
23547c16975SMattias Wallin 	if (ret < 0)
23647c16975SMattias Wallin 		dev_err(ab8500->dev, "failed to read reg %#x: %d\n",
23747c16975SMattias Wallin 			addr, ret);
23847c16975SMattias Wallin 	else
23947c16975SMattias Wallin 		*value = ret;
24047c16975SMattias Wallin 
24147c16975SMattias Wallin 	mutex_unlock(&ab8500->lock);
24247c16975SMattias Wallin 	dev_vdbg(ab8500->dev, "rd: addr %#x => data %#x\n", addr, ret);
24347c16975SMattias Wallin 
24447c16975SMattias Wallin 	return ret;
24547c16975SMattias Wallin }
24647c16975SMattias Wallin 
24747c16975SMattias Wallin static int ab8500_get_register(struct device *dev, u8 bank,
24847c16975SMattias Wallin 	u8 reg, u8 *value)
24947c16975SMattias Wallin {
250112a80d2SJonas Aaberg 	int ret;
25147c16975SMattias Wallin 	struct ab8500 *ab8500 = dev_get_drvdata(dev->parent);
25247c16975SMattias Wallin 
253112a80d2SJonas Aaberg 	atomic_inc(&ab8500->transfer_ongoing);
254112a80d2SJonas Aaberg 	ret = get_register_interruptible(ab8500, bank, reg, value);
255112a80d2SJonas Aaberg 	atomic_dec(&ab8500->transfer_ongoing);
256112a80d2SJonas Aaberg 	return ret;
25747c16975SMattias Wallin }
25847c16975SMattias Wallin 
25947c16975SMattias Wallin static int mask_and_set_register_interruptible(struct ab8500 *ab8500, u8 bank,
26047c16975SMattias Wallin 	u8 reg, u8 bitmask, u8 bitvalues)
26147c16975SMattias Wallin {
26247c16975SMattias Wallin 	int ret;
26347c16975SMattias Wallin 	/* put the u8 bank and u8 reg together into a an u16.
26447c16975SMattias Wallin 	 * bank on higher 8 bits and reg in lower */
26547c16975SMattias Wallin 	u16 addr = ((u16)bank) << 8 | reg;
26647c16975SMattias Wallin 
267392cbd1eSRabin Vincent 	mutex_lock(&ab8500->lock);
26847c16975SMattias Wallin 
269bc628fd1SMattias Nilsson 	if (ab8500->write_masked == NULL) {
270bc628fd1SMattias Nilsson 		u8 data;
271bc628fd1SMattias Nilsson 
27247c16975SMattias Wallin 		ret = ab8500->read(ab8500, addr);
27347c16975SMattias Wallin 		if (ret < 0) {
27447c16975SMattias Wallin 			dev_err(ab8500->dev, "failed to read reg %#x: %d\n",
27547c16975SMattias Wallin 				addr, ret);
27647c16975SMattias Wallin 			goto out;
27747c16975SMattias Wallin 		}
27847c16975SMattias Wallin 
27947c16975SMattias Wallin 		data = (u8)ret;
28047c16975SMattias Wallin 		data = (~bitmask & data) | (bitmask & bitvalues);
28147c16975SMattias Wallin 
28262579266SRabin Vincent 		ret = ab8500->write(ab8500, addr, data);
28362579266SRabin Vincent 		if (ret < 0)
28462579266SRabin Vincent 			dev_err(ab8500->dev, "failed to write reg %#x: %d\n",
28562579266SRabin Vincent 				addr, ret);
28662579266SRabin Vincent 
287bc628fd1SMattias Nilsson 		dev_vdbg(ab8500->dev, "mask: addr %#x => data %#x\n", addr,
288bc628fd1SMattias Nilsson 			data);
289bc628fd1SMattias Nilsson 		goto out;
290bc628fd1SMattias Nilsson 	}
291bc628fd1SMattias Nilsson 	ret = ab8500->write_masked(ab8500, addr, bitmask, bitvalues);
292bc628fd1SMattias Nilsson 	if (ret < 0)
293bc628fd1SMattias Nilsson 		dev_err(ab8500->dev, "failed to modify reg %#x: %d\n", addr,
294bc628fd1SMattias Nilsson 			ret);
29562579266SRabin Vincent out:
29662579266SRabin Vincent 	mutex_unlock(&ab8500->lock);
29762579266SRabin Vincent 	return ret;
29862579266SRabin Vincent }
29947c16975SMattias Wallin 
30047c16975SMattias Wallin static int ab8500_mask_and_set_register(struct device *dev,
30147c16975SMattias Wallin 	u8 bank, u8 reg, u8 bitmask, u8 bitvalues)
30247c16975SMattias Wallin {
303112a80d2SJonas Aaberg 	int ret;
30447c16975SMattias Wallin 	struct ab8500 *ab8500 = dev_get_drvdata(dev->parent);
30547c16975SMattias Wallin 
306112a80d2SJonas Aaberg 	atomic_inc(&ab8500->transfer_ongoing);
307112a80d2SJonas Aaberg 	ret= mask_and_set_register_interruptible(ab8500, bank, reg,
30847c16975SMattias Wallin 						 bitmask, bitvalues);
309112a80d2SJonas Aaberg 	atomic_dec(&ab8500->transfer_ongoing);
310112a80d2SJonas Aaberg 	return ret;
31147c16975SMattias Wallin }
31247c16975SMattias Wallin 
31347c16975SMattias Wallin static struct abx500_ops ab8500_ops = {
31447c16975SMattias Wallin 	.get_chip_id = ab8500_get_chip_id,
31547c16975SMattias Wallin 	.get_register = ab8500_get_register,
31647c16975SMattias Wallin 	.set_register = ab8500_set_register,
31747c16975SMattias Wallin 	.get_register_page = NULL,
31847c16975SMattias Wallin 	.set_register_page = NULL,
31947c16975SMattias Wallin 	.mask_and_set_register = ab8500_mask_and_set_register,
32047c16975SMattias Wallin 	.event_registers_startup_state_get = NULL,
32147c16975SMattias Wallin 	.startup_irq_enabled = NULL,
32247c16975SMattias Wallin };
32362579266SRabin Vincent 
3249505a0a0SMark Brown static void ab8500_irq_lock(struct irq_data *data)
32562579266SRabin Vincent {
3269505a0a0SMark Brown 	struct ab8500 *ab8500 = irq_data_get_irq_chip_data(data);
32762579266SRabin Vincent 
32862579266SRabin Vincent 	mutex_lock(&ab8500->irq_lock);
329112a80d2SJonas Aaberg 	atomic_inc(&ab8500->transfer_ongoing);
33062579266SRabin Vincent }
33162579266SRabin Vincent 
3329505a0a0SMark Brown static void ab8500_irq_sync_unlock(struct irq_data *data)
33362579266SRabin Vincent {
3349505a0a0SMark Brown 	struct ab8500 *ab8500 = irq_data_get_irq_chip_data(data);
33562579266SRabin Vincent 	int i;
33662579266SRabin Vincent 
3372ced445eSLinus Walleij 	for (i = 0; i < ab8500->mask_size; i++) {
33862579266SRabin Vincent 		u8 old = ab8500->oldmask[i];
33962579266SRabin Vincent 		u8 new = ab8500->mask[i];
34062579266SRabin Vincent 		int reg;
34162579266SRabin Vincent 
34262579266SRabin Vincent 		if (new == old)
34362579266SRabin Vincent 			continue;
34462579266SRabin Vincent 
3450f620837SLinus Walleij 		/*
3460f620837SLinus Walleij 		 * Interrupt register 12 doesn't exist prior to AB8500 version
3470f620837SLinus Walleij 		 * 2.0
3480f620837SLinus Walleij 		 */
3490f620837SLinus Walleij 		if (ab8500->irq_reg_offset[i] == 11 &&
3500f620837SLinus Walleij 			is_ab8500_1p1_or_earlier(ab8500))
35192d50a41SMattias Wallin 			continue;
35292d50a41SMattias Wallin 
35362579266SRabin Vincent 		ab8500->oldmask[i] = new;
35462579266SRabin Vincent 
3552ced445eSLinus Walleij 		reg = AB8500_IT_MASK1_REG + ab8500->irq_reg_offset[i];
35647c16975SMattias Wallin 		set_register_interruptible(ab8500, AB8500_INTERRUPT, reg, new);
35762579266SRabin Vincent 	}
358112a80d2SJonas Aaberg 	atomic_dec(&ab8500->transfer_ongoing);
35962579266SRabin Vincent 	mutex_unlock(&ab8500->irq_lock);
36062579266SRabin Vincent }
36162579266SRabin Vincent 
3629505a0a0SMark Brown static void ab8500_irq_mask(struct irq_data *data)
36362579266SRabin Vincent {
3649505a0a0SMark Brown 	struct ab8500 *ab8500 = irq_data_get_irq_chip_data(data);
36506e589efSLee Jones 	int offset = data->hwirq;
36662579266SRabin Vincent 	int index = offset / 8;
36762579266SRabin Vincent 	int mask = 1 << (offset % 8);
36862579266SRabin Vincent 
36962579266SRabin Vincent 	ab8500->mask[index] |= mask;
37062579266SRabin Vincent }
37162579266SRabin Vincent 
3729505a0a0SMark Brown static void ab8500_irq_unmask(struct irq_data *data)
37362579266SRabin Vincent {
3749505a0a0SMark Brown 	struct ab8500 *ab8500 = irq_data_get_irq_chip_data(data);
37506e589efSLee Jones 	int offset = data->hwirq;
37662579266SRabin Vincent 	int index = offset / 8;
37762579266SRabin Vincent 	int mask = 1 << (offset % 8);
37862579266SRabin Vincent 
37962579266SRabin Vincent 	ab8500->mask[index] &= ~mask;
38062579266SRabin Vincent }
38162579266SRabin Vincent 
38262579266SRabin Vincent static struct irq_chip ab8500_irq_chip = {
38362579266SRabin Vincent 	.name			= "ab8500",
3849505a0a0SMark Brown 	.irq_bus_lock		= ab8500_irq_lock,
3859505a0a0SMark Brown 	.irq_bus_sync_unlock	= ab8500_irq_sync_unlock,
3869505a0a0SMark Brown 	.irq_mask		= ab8500_irq_mask,
387e6f9306eSVirupax Sadashivpetimath 	.irq_disable		= ab8500_irq_mask,
3889505a0a0SMark Brown 	.irq_unmask		= ab8500_irq_unmask,
38962579266SRabin Vincent };
39062579266SRabin Vincent 
3917ccfe9b1SMichel JAOUEN static int ab8500_handle_hierarchical_line(struct ab8500 *ab8500,
3927ccfe9b1SMichel JAOUEN 					int latch_offset, u8 latch_val)
3937ccfe9b1SMichel JAOUEN {
3947ccfe9b1SMichel JAOUEN 	int int_bit = __ffs(latch_val);
3957ccfe9b1SMichel JAOUEN 	int line, i;
3967ccfe9b1SMichel JAOUEN 
3977ccfe9b1SMichel JAOUEN 	do {
3987ccfe9b1SMichel JAOUEN 		int_bit = __ffs(latch_val);
3997ccfe9b1SMichel JAOUEN 
4007ccfe9b1SMichel JAOUEN 		for (i = 0; i < ab8500->mask_size; i++)
4017ccfe9b1SMichel JAOUEN 			if (ab8500->irq_reg_offset[i] == latch_offset)
4027ccfe9b1SMichel JAOUEN 				break;
4037ccfe9b1SMichel JAOUEN 
4047ccfe9b1SMichel JAOUEN 		if (i >= ab8500->mask_size) {
4057ccfe9b1SMichel JAOUEN 			dev_err(ab8500->dev, "Register offset 0x%2x not declared\n",
4067ccfe9b1SMichel JAOUEN 					latch_offset);
4077ccfe9b1SMichel JAOUEN 			return -ENXIO;
4087ccfe9b1SMichel JAOUEN 		}
4097ccfe9b1SMichel JAOUEN 
4107ccfe9b1SMichel JAOUEN 		line = (i << 3) + int_bit;
4117ccfe9b1SMichel JAOUEN 		latch_val &= ~(1 << int_bit);
4127ccfe9b1SMichel JAOUEN 
4137ccfe9b1SMichel JAOUEN 		handle_nested_irq(ab8500->irq_base + line);
4147ccfe9b1SMichel JAOUEN 	} while (latch_val);
4157ccfe9b1SMichel JAOUEN 
4167ccfe9b1SMichel JAOUEN 	return 0;
4177ccfe9b1SMichel JAOUEN }
4187ccfe9b1SMichel JAOUEN 
4197ccfe9b1SMichel JAOUEN static int ab8500_handle_hierarchical_latch(struct ab8500 *ab8500,
4207ccfe9b1SMichel JAOUEN 					int hier_offset, u8 hier_val)
4217ccfe9b1SMichel JAOUEN {
4227ccfe9b1SMichel JAOUEN 	int latch_bit, status;
4237ccfe9b1SMichel JAOUEN 	u8 latch_offset, latch_val;
4247ccfe9b1SMichel JAOUEN 
4257ccfe9b1SMichel JAOUEN 	do {
4267ccfe9b1SMichel JAOUEN 		latch_bit = __ffs(hier_val);
4277ccfe9b1SMichel JAOUEN 		latch_offset = (hier_offset << 3) + latch_bit;
4287ccfe9b1SMichel JAOUEN 
4297ccfe9b1SMichel JAOUEN 		/* Fix inconsistent ITFromLatch25 bit mapping... */
4307ccfe9b1SMichel JAOUEN 		if (unlikely(latch_offset == 17))
4317ccfe9b1SMichel JAOUEN 			latch_offset = 24;
4327ccfe9b1SMichel JAOUEN 
4337ccfe9b1SMichel JAOUEN 		status = get_register_interruptible(ab8500,
4347ccfe9b1SMichel JAOUEN 				AB8500_INTERRUPT,
4357ccfe9b1SMichel JAOUEN 				AB8500_IT_LATCH1_REG + latch_offset,
4367ccfe9b1SMichel JAOUEN 				&latch_val);
4377ccfe9b1SMichel JAOUEN 		if (status < 0 || latch_val == 0)
4387ccfe9b1SMichel JAOUEN 			goto discard;
4397ccfe9b1SMichel JAOUEN 
4407ccfe9b1SMichel JAOUEN 		status = ab8500_handle_hierarchical_line(ab8500,
4417ccfe9b1SMichel JAOUEN 				latch_offset, latch_val);
4427ccfe9b1SMichel JAOUEN 		if (status < 0)
4437ccfe9b1SMichel JAOUEN 			return status;
4447ccfe9b1SMichel JAOUEN discard:
4457ccfe9b1SMichel JAOUEN 		hier_val &= ~(1 << latch_bit);
4467ccfe9b1SMichel JAOUEN 	} while (hier_val);
4477ccfe9b1SMichel JAOUEN 
4487ccfe9b1SMichel JAOUEN 	return 0;
4497ccfe9b1SMichel JAOUEN }
4507ccfe9b1SMichel JAOUEN 
4517ccfe9b1SMichel JAOUEN static irqreturn_t ab8500_hierarchical_irq(int irq, void *dev)
4527ccfe9b1SMichel JAOUEN {
4537ccfe9b1SMichel JAOUEN 	struct ab8500 *ab8500 = dev;
4547ccfe9b1SMichel JAOUEN 	u8 i;
4557ccfe9b1SMichel JAOUEN 
4567ccfe9b1SMichel JAOUEN 	dev_vdbg(ab8500->dev, "interrupt\n");
4577ccfe9b1SMichel JAOUEN 
4587ccfe9b1SMichel JAOUEN 	/*  Hierarchical interrupt version */
4597ccfe9b1SMichel JAOUEN 	for (i = 0; i < AB8500_IT_LATCHHIER_NUM; i++) {
4607ccfe9b1SMichel JAOUEN 		int status;
4617ccfe9b1SMichel JAOUEN 		u8 hier_val;
4627ccfe9b1SMichel JAOUEN 
4637ccfe9b1SMichel JAOUEN 		status = get_register_interruptible(ab8500, AB8500_INTERRUPT,
4647ccfe9b1SMichel JAOUEN 			AB8500_IT_LATCHHIER1_REG + i, &hier_val);
4657ccfe9b1SMichel JAOUEN 		if (status < 0 || hier_val == 0)
4667ccfe9b1SMichel JAOUEN 			continue;
4677ccfe9b1SMichel JAOUEN 
4687ccfe9b1SMichel JAOUEN 		status = ab8500_handle_hierarchical_latch(ab8500, i, hier_val);
4697ccfe9b1SMichel JAOUEN 		if (status < 0)
4707ccfe9b1SMichel JAOUEN 			break;
4717ccfe9b1SMichel JAOUEN 	}
4727ccfe9b1SMichel JAOUEN 	return IRQ_HANDLED;
4737ccfe9b1SMichel JAOUEN }
4747ccfe9b1SMichel JAOUEN 
47580633f05SLee Jones /**
47680633f05SLee Jones  * ab8500_irq_get_virq(): Map an interrupt on a chip to a virtual IRQ
47780633f05SLee Jones  *
47880633f05SLee Jones  * @ab8500: ab8500_irq controller to operate on.
47980633f05SLee Jones  * @irq: index of the interrupt requested in the chip IRQs
48080633f05SLee Jones  *
48180633f05SLee Jones  * Useful for drivers to request their own IRQs.
48280633f05SLee Jones  */
48380633f05SLee Jones static int ab8500_irq_get_virq(struct ab8500 *ab8500, int irq)
48480633f05SLee Jones {
48580633f05SLee Jones 	if (!ab8500)
48680633f05SLee Jones 		return -EINVAL;
48780633f05SLee Jones 
48880633f05SLee Jones 	return irq_create_mapping(ab8500->domain, irq);
48980633f05SLee Jones }
49080633f05SLee Jones 
49162579266SRabin Vincent static irqreturn_t ab8500_irq(int irq, void *dev)
49262579266SRabin Vincent {
49362579266SRabin Vincent 	struct ab8500 *ab8500 = dev;
49462579266SRabin Vincent 	int i;
49562579266SRabin Vincent 
49662579266SRabin Vincent 	dev_vdbg(ab8500->dev, "interrupt\n");
49762579266SRabin Vincent 
498112a80d2SJonas Aaberg 	atomic_inc(&ab8500->transfer_ongoing);
499112a80d2SJonas Aaberg 
5002ced445eSLinus Walleij 	for (i = 0; i < ab8500->mask_size; i++) {
5012ced445eSLinus Walleij 		int regoffset = ab8500->irq_reg_offset[i];
50262579266SRabin Vincent 		int status;
50347c16975SMattias Wallin 		u8 value;
50462579266SRabin Vincent 
5050f620837SLinus Walleij 		/*
5060f620837SLinus Walleij 		 * Interrupt register 12 doesn't exist prior to AB8500 version
5070f620837SLinus Walleij 		 * 2.0
5080f620837SLinus Walleij 		 */
5090f620837SLinus Walleij 		if (regoffset == 11 && is_ab8500_1p1_or_earlier(ab8500))
51092d50a41SMattias Wallin 			continue;
51192d50a41SMattias Wallin 
51247c16975SMattias Wallin 		status = get_register_interruptible(ab8500, AB8500_INTERRUPT,
51347c16975SMattias Wallin 			AB8500_IT_LATCH1_REG + regoffset, &value);
51447c16975SMattias Wallin 		if (status < 0 || value == 0)
51562579266SRabin Vincent 			continue;
51662579266SRabin Vincent 
51762579266SRabin Vincent 		do {
51888aec4f7SMattias Wallin 			int bit = __ffs(value);
51962579266SRabin Vincent 			int line = i * 8 + bit;
5200a37fc56SLee Jones 			int virq = ab8500_irq_get_virq(ab8500, line);
52162579266SRabin Vincent 
5220a37fc56SLee Jones 			handle_nested_irq(virq);
52347c16975SMattias Wallin 			value &= ~(1 << bit);
524112a80d2SJonas Aaberg 
52547c16975SMattias Wallin 		} while (value);
52662579266SRabin Vincent 	}
527112a80d2SJonas Aaberg 	atomic_dec(&ab8500->transfer_ongoing);
52862579266SRabin Vincent 	return IRQ_HANDLED;
52962579266SRabin Vincent }
53062579266SRabin Vincent 
53106e589efSLee Jones static int ab8500_irq_map(struct irq_domain *d, unsigned int virq,
53206e589efSLee Jones 				irq_hw_number_t hwirq)
53306e589efSLee Jones {
53406e589efSLee Jones 	struct ab8500 *ab8500 = d->host_data;
53506e589efSLee Jones 
53606e589efSLee Jones 	if (!ab8500)
53706e589efSLee Jones 		return -EINVAL;
53806e589efSLee Jones 
53906e589efSLee Jones 	irq_set_chip_data(virq, ab8500);
54006e589efSLee Jones 	irq_set_chip_and_handler(virq, &ab8500_irq_chip,
54106e589efSLee Jones 				handle_simple_irq);
54206e589efSLee Jones 	irq_set_nested_thread(virq, 1);
54306e589efSLee Jones #ifdef CONFIG_ARM
54406e589efSLee Jones 	set_irq_flags(virq, IRQF_VALID);
54506e589efSLee Jones #else
54606e589efSLee Jones 	irq_set_noprobe(virq);
54706e589efSLee Jones #endif
54862579266SRabin Vincent 
54962579266SRabin Vincent 	return 0;
55062579266SRabin Vincent }
55162579266SRabin Vincent 
55206e589efSLee Jones static struct irq_domain_ops ab8500_irq_ops = {
55306e589efSLee Jones         .map    = ab8500_irq_map,
55406e589efSLee Jones         .xlate  = irq_domain_xlate_twocell,
55506e589efSLee Jones };
55606e589efSLee Jones 
55706e589efSLee Jones static int ab8500_irq_init(struct ab8500 *ab8500, struct device_node *np)
55862579266SRabin Vincent {
5592ced445eSLinus Walleij 	int num_irqs;
56062579266SRabin Vincent 
561d6255529SLinus Walleij 	if (is_ab9540(ab8500))
562d6255529SLinus Walleij 		num_irqs = AB9540_NR_IRQS;
563a982362cSBengt Jonsson 	else if (is_ab8505(ab8500))
564a982362cSBengt Jonsson 		num_irqs = AB8505_NR_IRQS;
565d6255529SLinus Walleij 	else
5662ced445eSLinus Walleij 		num_irqs = AB8500_NR_IRQS;
5672ced445eSLinus Walleij 
56806e589efSLee Jones 	if (ab8500->irq_base) {
56906e589efSLee Jones 		ab8500->domain = irq_domain_add_legacy(
57006e589efSLee Jones 			NULL, num_irqs, ab8500->irq_base,
57106e589efSLee Jones 			0, &ab8500_irq_ops, ab8500);
57262579266SRabin Vincent 	}
57306e589efSLee Jones 	else {
57406e589efSLee Jones 		ab8500->domain = irq_domain_add_linear(
57506e589efSLee Jones 			np, num_irqs, &ab8500_irq_ops, ab8500);
57606e589efSLee Jones 	}
57706e589efSLee Jones 
57806e589efSLee Jones 	if (!ab8500->domain) {
57906e589efSLee Jones 		dev_err(ab8500->dev, "Failed to create irqdomain\n");
58006e589efSLee Jones 		return -ENOSYS;
58106e589efSLee Jones 	}
58206e589efSLee Jones 
58306e589efSLee Jones 	return 0;
58462579266SRabin Vincent }
58562579266SRabin Vincent 
586112a80d2SJonas Aaberg int ab8500_suspend(struct ab8500 *ab8500)
587112a80d2SJonas Aaberg {
588112a80d2SJonas Aaberg 	if (atomic_read(&ab8500->transfer_ongoing))
589112a80d2SJonas Aaberg 		return -EINVAL;
590112a80d2SJonas Aaberg 	else
591112a80d2SJonas Aaberg 		return 0;
592112a80d2SJonas Aaberg }
593112a80d2SJonas Aaberg 
594d6255529SLinus Walleij /* AB8500 GPIO Resources */
5955cef8df5SRobert Rosengren static struct resource __devinitdata ab8500_gpio_resources[] = {
5960cb3fcd7SBibek Basu 	{
5970cb3fcd7SBibek Basu 		.name	= "GPIO_INT6",
5980cb3fcd7SBibek Basu 		.start	= AB8500_INT_GPIO6R,
5990cb3fcd7SBibek Basu 		.end	= AB8500_INT_GPIO41F,
6000cb3fcd7SBibek Basu 		.flags	= IORESOURCE_IRQ,
6010cb3fcd7SBibek Basu 	}
6020cb3fcd7SBibek Basu };
6030cb3fcd7SBibek Basu 
604d6255529SLinus Walleij /* AB9540 GPIO Resources */
605d6255529SLinus Walleij static struct resource __devinitdata ab9540_gpio_resources[] = {
606d6255529SLinus Walleij 	{
607d6255529SLinus Walleij 		.name	= "GPIO_INT6",
608d6255529SLinus Walleij 		.start	= AB8500_INT_GPIO6R,
609d6255529SLinus Walleij 		.end	= AB8500_INT_GPIO41F,
610d6255529SLinus Walleij 		.flags	= IORESOURCE_IRQ,
611d6255529SLinus Walleij 	},
612d6255529SLinus Walleij 	{
613d6255529SLinus Walleij 		.name	= "GPIO_INT14",
614d6255529SLinus Walleij 		.start	= AB9540_INT_GPIO50R,
615d6255529SLinus Walleij 		.end	= AB9540_INT_GPIO54R,
616d6255529SLinus Walleij 		.flags	= IORESOURCE_IRQ,
617d6255529SLinus Walleij 	},
618d6255529SLinus Walleij 	{
619d6255529SLinus Walleij 		.name	= "GPIO_INT15",
620d6255529SLinus Walleij 		.start	= AB9540_INT_GPIO50F,
621d6255529SLinus Walleij 		.end	= AB9540_INT_GPIO54F,
622d6255529SLinus Walleij 		.flags	= IORESOURCE_IRQ,
623d6255529SLinus Walleij 	}
624d6255529SLinus Walleij };
625d6255529SLinus Walleij 
6265cef8df5SRobert Rosengren static struct resource __devinitdata ab8500_gpadc_resources[] = {
62762579266SRabin Vincent 	{
62862579266SRabin Vincent 		.name	= "HW_CONV_END",
62962579266SRabin Vincent 		.start	= AB8500_INT_GP_HW_ADC_CONV_END,
63062579266SRabin Vincent 		.end	= AB8500_INT_GP_HW_ADC_CONV_END,
63162579266SRabin Vincent 		.flags	= IORESOURCE_IRQ,
63262579266SRabin Vincent 	},
63362579266SRabin Vincent 	{
63462579266SRabin Vincent 		.name	= "SW_CONV_END",
63562579266SRabin Vincent 		.start	= AB8500_INT_GP_SW_ADC_CONV_END,
63662579266SRabin Vincent 		.end	= AB8500_INT_GP_SW_ADC_CONV_END,
63762579266SRabin Vincent 		.flags	= IORESOURCE_IRQ,
63862579266SRabin Vincent 	},
63962579266SRabin Vincent };
64062579266SRabin Vincent 
6415cef8df5SRobert Rosengren static struct resource __devinitdata ab8500_rtc_resources[] = {
64262579266SRabin Vincent 	{
64362579266SRabin Vincent 		.name	= "60S",
64462579266SRabin Vincent 		.start	= AB8500_INT_RTC_60S,
64562579266SRabin Vincent 		.end	= AB8500_INT_RTC_60S,
64662579266SRabin Vincent 		.flags	= IORESOURCE_IRQ,
64762579266SRabin Vincent 	},
64862579266SRabin Vincent 	{
64962579266SRabin Vincent 		.name	= "ALARM",
65062579266SRabin Vincent 		.start	= AB8500_INT_RTC_ALARM,
65162579266SRabin Vincent 		.end	= AB8500_INT_RTC_ALARM,
65262579266SRabin Vincent 		.flags	= IORESOURCE_IRQ,
65362579266SRabin Vincent 	},
65462579266SRabin Vincent };
65562579266SRabin Vincent 
6565cef8df5SRobert Rosengren static struct resource __devinitdata ab8500_poweronkey_db_resources[] = {
65777686517SSundar R Iyer 	{
65877686517SSundar R Iyer 		.name	= "ONKEY_DBF",
65977686517SSundar R Iyer 		.start	= AB8500_INT_PON_KEY1DB_F,
66077686517SSundar R Iyer 		.end	= AB8500_INT_PON_KEY1DB_F,
66177686517SSundar R Iyer 		.flags	= IORESOURCE_IRQ,
66277686517SSundar R Iyer 	},
66377686517SSundar R Iyer 	{
66477686517SSundar R Iyer 		.name	= "ONKEY_DBR",
66577686517SSundar R Iyer 		.start	= AB8500_INT_PON_KEY1DB_R,
66677686517SSundar R Iyer 		.end	= AB8500_INT_PON_KEY1DB_R,
66777686517SSundar R Iyer 		.flags	= IORESOURCE_IRQ,
66877686517SSundar R Iyer 	},
66977686517SSundar R Iyer };
67077686517SSundar R Iyer 
6716af75ecdSLinus Walleij static struct resource __devinitdata ab8500_av_acc_detect_resources[] = {
672e098adedSMattias Wallin 	{
6736af75ecdSLinus Walleij 	       .name = "ACC_DETECT_1DB_F",
6746af75ecdSLinus Walleij 	       .start = AB8500_INT_ACC_DETECT_1DB_F,
6756af75ecdSLinus Walleij 	       .end = AB8500_INT_ACC_DETECT_1DB_F,
676e098adedSMattias Wallin 	       .flags = IORESOURCE_IRQ,
677e098adedSMattias Wallin 	},
678e098adedSMattias Wallin 	{
6796af75ecdSLinus Walleij 	       .name = "ACC_DETECT_1DB_R",
6806af75ecdSLinus Walleij 	       .start = AB8500_INT_ACC_DETECT_1DB_R,
6816af75ecdSLinus Walleij 	       .end = AB8500_INT_ACC_DETECT_1DB_R,
682e098adedSMattias Wallin 	       .flags = IORESOURCE_IRQ,
683e098adedSMattias Wallin 	},
684e098adedSMattias Wallin 	{
6856af75ecdSLinus Walleij 	       .name = "ACC_DETECT_21DB_F",
6866af75ecdSLinus Walleij 	       .start = AB8500_INT_ACC_DETECT_21DB_F,
6876af75ecdSLinus Walleij 	       .end = AB8500_INT_ACC_DETECT_21DB_F,
6886af75ecdSLinus Walleij 	       .flags = IORESOURCE_IRQ,
6896af75ecdSLinus Walleij 	},
6906af75ecdSLinus Walleij 	{
6916af75ecdSLinus Walleij 	       .name = "ACC_DETECT_21DB_R",
6926af75ecdSLinus Walleij 	       .start = AB8500_INT_ACC_DETECT_21DB_R,
6936af75ecdSLinus Walleij 	       .end = AB8500_INT_ACC_DETECT_21DB_R,
6946af75ecdSLinus Walleij 	       .flags = IORESOURCE_IRQ,
6956af75ecdSLinus Walleij 	},
6966af75ecdSLinus Walleij 	{
6976af75ecdSLinus Walleij 	       .name = "ACC_DETECT_22DB_F",
6986af75ecdSLinus Walleij 	       .start = AB8500_INT_ACC_DETECT_22DB_F,
6996af75ecdSLinus Walleij 	       .end = AB8500_INT_ACC_DETECT_22DB_F,
7006af75ecdSLinus Walleij 	       .flags = IORESOURCE_IRQ,
7016af75ecdSLinus Walleij 	},
7026af75ecdSLinus Walleij 	{
7036af75ecdSLinus Walleij 	       .name = "ACC_DETECT_22DB_R",
7046af75ecdSLinus Walleij 	       .start = AB8500_INT_ACC_DETECT_22DB_R,
7056af75ecdSLinus Walleij 	       .end = AB8500_INT_ACC_DETECT_22DB_R,
7066af75ecdSLinus Walleij 	       .flags = IORESOURCE_IRQ,
7076af75ecdSLinus Walleij 	},
7086af75ecdSLinus Walleij };
7096af75ecdSLinus Walleij 
7106af75ecdSLinus Walleij static struct resource __devinitdata ab8500_charger_resources[] = {
7116af75ecdSLinus Walleij 	{
712e098adedSMattias Wallin 		.name = "MAIN_CH_UNPLUG_DET",
713e098adedSMattias Wallin 		.start = AB8500_INT_MAIN_CH_UNPLUG_DET,
714e098adedSMattias Wallin 		.end = AB8500_INT_MAIN_CH_UNPLUG_DET,
715e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
716e098adedSMattias Wallin 	},
717e098adedSMattias Wallin 	{
718e098adedSMattias Wallin 		.name = "MAIN_CHARGE_PLUG_DET",
719e098adedSMattias Wallin 		.start = AB8500_INT_MAIN_CH_PLUG_DET,
720e098adedSMattias Wallin 		.end = AB8500_INT_MAIN_CH_PLUG_DET,
721e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
722e098adedSMattias Wallin 	},
723e098adedSMattias Wallin 	{
724e098adedSMattias Wallin 		.name = "VBUS_DET_R",
725e098adedSMattias Wallin 		.start = AB8500_INT_VBUS_DET_R,
726e098adedSMattias Wallin 		.end = AB8500_INT_VBUS_DET_R,
727e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
728e098adedSMattias Wallin 	},
729e098adedSMattias Wallin 	{
7306af75ecdSLinus Walleij 		.name = "VBUS_DET_F",
7316af75ecdSLinus Walleij 		.start = AB8500_INT_VBUS_DET_F,
7326af75ecdSLinus Walleij 		.end = AB8500_INT_VBUS_DET_F,
733e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
734e098adedSMattias Wallin 	},
735e098adedSMattias Wallin 	{
7366af75ecdSLinus Walleij 		.name = "USB_LINK_STATUS",
7376af75ecdSLinus Walleij 		.start = AB8500_INT_USB_LINK_STATUS,
7386af75ecdSLinus Walleij 		.end = AB8500_INT_USB_LINK_STATUS,
7396af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
7406af75ecdSLinus Walleij 	},
7416af75ecdSLinus Walleij 	{
742e098adedSMattias Wallin 		.name = "VBUS_OVV",
743e098adedSMattias Wallin 		.start = AB8500_INT_VBUS_OVV,
744e098adedSMattias Wallin 		.end = AB8500_INT_VBUS_OVV,
745e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
746e098adedSMattias Wallin 	},
747e098adedSMattias Wallin 	{
7486af75ecdSLinus Walleij 		.name = "USB_CH_TH_PROT_R",
7496af75ecdSLinus Walleij 		.start = AB8500_INT_USB_CH_TH_PROT_R,
7506af75ecdSLinus Walleij 		.end = AB8500_INT_USB_CH_TH_PROT_R,
751e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
752e098adedSMattias Wallin 	},
753e098adedSMattias Wallin 	{
7546af75ecdSLinus Walleij 		.name = "USB_CH_TH_PROT_F",
7556af75ecdSLinus Walleij 		.start = AB8500_INT_USB_CH_TH_PROT_F,
7566af75ecdSLinus Walleij 		.end = AB8500_INT_USB_CH_TH_PROT_F,
757e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
758e098adedSMattias Wallin 	},
759e098adedSMattias Wallin 	{
7606af75ecdSLinus Walleij 		.name = "MAIN_EXT_CH_NOT_OK",
7616af75ecdSLinus Walleij 		.start = AB8500_INT_MAIN_EXT_CH_NOT_OK,
7626af75ecdSLinus Walleij 		.end = AB8500_INT_MAIN_EXT_CH_NOT_OK,
7636af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
7646af75ecdSLinus Walleij 	},
7656af75ecdSLinus Walleij 	{
7666af75ecdSLinus Walleij 		.name = "MAIN_CH_TH_PROT_R",
7676af75ecdSLinus Walleij 		.start = AB8500_INT_MAIN_CH_TH_PROT_R,
7686af75ecdSLinus Walleij 		.end = AB8500_INT_MAIN_CH_TH_PROT_R,
7696af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
7706af75ecdSLinus Walleij 	},
7716af75ecdSLinus Walleij 	{
7726af75ecdSLinus Walleij 		.name = "MAIN_CH_TH_PROT_F",
7736af75ecdSLinus Walleij 		.start = AB8500_INT_MAIN_CH_TH_PROT_F,
7746af75ecdSLinus Walleij 		.end = AB8500_INT_MAIN_CH_TH_PROT_F,
7756af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
7766af75ecdSLinus Walleij 	},
7776af75ecdSLinus Walleij 	{
7786af75ecdSLinus Walleij 		.name = "USB_CHARGER_NOT_OKR",
779a982362cSBengt Jonsson 		.start = AB8500_INT_USB_CHARGER_NOT_OKR,
780a982362cSBengt Jonsson 		.end = AB8500_INT_USB_CHARGER_NOT_OKR,
7816af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
7826af75ecdSLinus Walleij 	},
7836af75ecdSLinus Walleij 	{
7846af75ecdSLinus Walleij 		.name = "CH_WD_EXP",
7856af75ecdSLinus Walleij 		.start = AB8500_INT_CH_WD_EXP,
7866af75ecdSLinus Walleij 		.end = AB8500_INT_CH_WD_EXP,
7876af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
7886af75ecdSLinus Walleij 	},
7896af75ecdSLinus Walleij };
7906af75ecdSLinus Walleij 
7916af75ecdSLinus Walleij static struct resource __devinitdata ab8500_btemp_resources[] = {
7926af75ecdSLinus Walleij 	{
7936af75ecdSLinus Walleij 		.name = "BAT_CTRL_INDB",
7946af75ecdSLinus Walleij 		.start = AB8500_INT_BAT_CTRL_INDB,
7956af75ecdSLinus Walleij 		.end = AB8500_INT_BAT_CTRL_INDB,
796e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
797e098adedSMattias Wallin 	},
798e098adedSMattias Wallin 	{
799e098adedSMattias Wallin 		.name = "BTEMP_LOW",
800e098adedSMattias Wallin 		.start = AB8500_INT_BTEMP_LOW,
801e098adedSMattias Wallin 		.end = AB8500_INT_BTEMP_LOW,
802e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
803e098adedSMattias Wallin 	},
804e098adedSMattias Wallin 	{
805e098adedSMattias Wallin 		.name = "BTEMP_HIGH",
806e098adedSMattias Wallin 		.start = AB8500_INT_BTEMP_HIGH,
807e098adedSMattias Wallin 		.end = AB8500_INT_BTEMP_HIGH,
808e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
809e098adedSMattias Wallin 	},
810e098adedSMattias Wallin 	{
8116af75ecdSLinus Walleij 		.name = "BTEMP_LOW_MEDIUM",
8126af75ecdSLinus Walleij 		.start = AB8500_INT_BTEMP_LOW_MEDIUM,
8136af75ecdSLinus Walleij 		.end = AB8500_INT_BTEMP_LOW_MEDIUM,
814e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
815e098adedSMattias Wallin 	},
816e098adedSMattias Wallin 	{
8176af75ecdSLinus Walleij 		.name = "BTEMP_MEDIUM_HIGH",
8186af75ecdSLinus Walleij 		.start = AB8500_INT_BTEMP_MEDIUM_HIGH,
8196af75ecdSLinus Walleij 		.end = AB8500_INT_BTEMP_MEDIUM_HIGH,
820e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
821e098adedSMattias Wallin 	},
822e098adedSMattias Wallin };
823e098adedSMattias Wallin 
8246af75ecdSLinus Walleij static struct resource __devinitdata ab8500_fg_resources[] = {
8256af75ecdSLinus Walleij 	{
8266af75ecdSLinus Walleij 		.name = "NCONV_ACCU",
8276af75ecdSLinus Walleij 		.start = AB8500_INT_CCN_CONV_ACC,
8286af75ecdSLinus Walleij 		.end = AB8500_INT_CCN_CONV_ACC,
8296af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
8306af75ecdSLinus Walleij 	},
8316af75ecdSLinus Walleij 	{
8326af75ecdSLinus Walleij 		.name = "BATT_OVV",
8336af75ecdSLinus Walleij 		.start = AB8500_INT_BATT_OVV,
8346af75ecdSLinus Walleij 		.end = AB8500_INT_BATT_OVV,
8356af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
8366af75ecdSLinus Walleij 	},
8376af75ecdSLinus Walleij 	{
8386af75ecdSLinus Walleij 		.name = "LOW_BAT_F",
8396af75ecdSLinus Walleij 		.start = AB8500_INT_LOW_BAT_F,
8406af75ecdSLinus Walleij 		.end = AB8500_INT_LOW_BAT_F,
8416af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
8426af75ecdSLinus Walleij 	},
8436af75ecdSLinus Walleij 	{
8446af75ecdSLinus Walleij 		.name = "LOW_BAT_R",
8456af75ecdSLinus Walleij 		.start = AB8500_INT_LOW_BAT_R,
8466af75ecdSLinus Walleij 		.end = AB8500_INT_LOW_BAT_R,
8476af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
8486af75ecdSLinus Walleij 	},
8496af75ecdSLinus Walleij 	{
8506af75ecdSLinus Walleij 		.name = "CC_INT_CALIB",
8516af75ecdSLinus Walleij 		.start = AB8500_INT_CC_INT_CALIB,
8526af75ecdSLinus Walleij 		.end = AB8500_INT_CC_INT_CALIB,
8536af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
8546af75ecdSLinus Walleij 	},
855a982362cSBengt Jonsson 	{
856a982362cSBengt Jonsson 		.name = "CCEOC",
857a982362cSBengt Jonsson 		.start = AB8500_INT_CCEOC,
858a982362cSBengt Jonsson 		.end = AB8500_INT_CCEOC,
859a982362cSBengt Jonsson 		.flags = IORESOURCE_IRQ,
860a982362cSBengt Jonsson 	},
8616af75ecdSLinus Walleij };
8626af75ecdSLinus Walleij 
8636af75ecdSLinus Walleij static struct resource __devinitdata ab8500_chargalg_resources[] = {};
8646af75ecdSLinus Walleij 
865df720647SAxel Lin #ifdef CONFIG_DEBUG_FS
8665cef8df5SRobert Rosengren static struct resource __devinitdata ab8500_debug_resources[] = {
867e098adedSMattias Wallin 	{
868e098adedSMattias Wallin 		.name	= "IRQ_FIRST",
869e098adedSMattias Wallin 		.start	= AB8500_INT_MAIN_EXT_CH_NOT_OK,
870e098adedSMattias Wallin 		.end	= AB8500_INT_MAIN_EXT_CH_NOT_OK,
871e098adedSMattias Wallin 		.flags	= IORESOURCE_IRQ,
872e098adedSMattias Wallin 	},
873e098adedSMattias Wallin 	{
874e098adedSMattias Wallin 		.name	= "IRQ_LAST",
875a982362cSBengt Jonsson 		.start	= AB8500_INT_XTAL32K_KO,
876a982362cSBengt Jonsson 		.end	= AB8500_INT_XTAL32K_KO,
877e098adedSMattias Wallin 		.flags	= IORESOURCE_IRQ,
878e098adedSMattias Wallin 	},
879e098adedSMattias Wallin };
880df720647SAxel Lin #endif
881e098adedSMattias Wallin 
8825cef8df5SRobert Rosengren static struct resource __devinitdata ab8500_usb_resources[] = {
883e098adedSMattias Wallin 	{
884e098adedSMattias Wallin 		.name = "ID_WAKEUP_R",
885e098adedSMattias Wallin 		.start = AB8500_INT_ID_WAKEUP_R,
886e098adedSMattias Wallin 		.end = AB8500_INT_ID_WAKEUP_R,
887e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
888e098adedSMattias Wallin 	},
889e098adedSMattias Wallin 	{
890e098adedSMattias Wallin 		.name = "ID_WAKEUP_F",
891e098adedSMattias Wallin 		.start = AB8500_INT_ID_WAKEUP_F,
892e098adedSMattias Wallin 		.end = AB8500_INT_ID_WAKEUP_F,
893e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
894e098adedSMattias Wallin 	},
895e098adedSMattias Wallin 	{
896e098adedSMattias Wallin 		.name = "VBUS_DET_F",
897e098adedSMattias Wallin 		.start = AB8500_INT_VBUS_DET_F,
898e098adedSMattias Wallin 		.end = AB8500_INT_VBUS_DET_F,
899e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
900e098adedSMattias Wallin 	},
901e098adedSMattias Wallin 	{
902e098adedSMattias Wallin 		.name = "VBUS_DET_R",
903e098adedSMattias Wallin 		.start = AB8500_INT_VBUS_DET_R,
904e098adedSMattias Wallin 		.end = AB8500_INT_VBUS_DET_R,
905e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
906e098adedSMattias Wallin 	},
90792d50a41SMattias Wallin 	{
90892d50a41SMattias Wallin 		.name = "USB_LINK_STATUS",
90992d50a41SMattias Wallin 		.start = AB8500_INT_USB_LINK_STATUS,
91092d50a41SMattias Wallin 		.end = AB8500_INT_USB_LINK_STATUS,
91192d50a41SMattias Wallin 		.flags = IORESOURCE_IRQ,
91292d50a41SMattias Wallin 	},
9136af75ecdSLinus Walleij 	{
9146af75ecdSLinus Walleij 		.name = "USB_ADP_PROBE_PLUG",
9156af75ecdSLinus Walleij 		.start = AB8500_INT_ADP_PROBE_PLUG,
9166af75ecdSLinus Walleij 		.end = AB8500_INT_ADP_PROBE_PLUG,
9176af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
9186af75ecdSLinus Walleij 	},
9196af75ecdSLinus Walleij 	{
9206af75ecdSLinus Walleij 		.name = "USB_ADP_PROBE_UNPLUG",
9216af75ecdSLinus Walleij 		.start = AB8500_INT_ADP_PROBE_UNPLUG,
9226af75ecdSLinus Walleij 		.end = AB8500_INT_ADP_PROBE_UNPLUG,
9236af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
9246af75ecdSLinus Walleij 	},
925e098adedSMattias Wallin };
926e098adedSMattias Wallin 
92744f72e53SVirupax Sadashivpetimath static struct resource __devinitdata ab8505_iddet_resources[] = {
92844f72e53SVirupax Sadashivpetimath 	{
92944f72e53SVirupax Sadashivpetimath 		.name  = "KeyDeglitch",
93044f72e53SVirupax Sadashivpetimath 		.start = AB8505_INT_KEYDEGLITCH,
93144f72e53SVirupax Sadashivpetimath 		.end   = AB8505_INT_KEYDEGLITCH,
93244f72e53SVirupax Sadashivpetimath 		.flags = IORESOURCE_IRQ,
93344f72e53SVirupax Sadashivpetimath 	},
93444f72e53SVirupax Sadashivpetimath 	{
93544f72e53SVirupax Sadashivpetimath 		.name  = "KP",
93644f72e53SVirupax Sadashivpetimath 		.start = AB8505_INT_KP,
93744f72e53SVirupax Sadashivpetimath 		.end   = AB8505_INT_KP,
93844f72e53SVirupax Sadashivpetimath 		.flags = IORESOURCE_IRQ,
93944f72e53SVirupax Sadashivpetimath 	},
94044f72e53SVirupax Sadashivpetimath 	{
94144f72e53SVirupax Sadashivpetimath 		.name  = "IKP",
94244f72e53SVirupax Sadashivpetimath 		.start = AB8505_INT_IKP,
94344f72e53SVirupax Sadashivpetimath 		.end   = AB8505_INT_IKP,
94444f72e53SVirupax Sadashivpetimath 		.flags = IORESOURCE_IRQ,
94544f72e53SVirupax Sadashivpetimath 	},
94644f72e53SVirupax Sadashivpetimath 	{
94744f72e53SVirupax Sadashivpetimath 		.name  = "IKR",
94844f72e53SVirupax Sadashivpetimath 		.start = AB8505_INT_IKR,
94944f72e53SVirupax Sadashivpetimath 		.end   = AB8505_INT_IKR,
95044f72e53SVirupax Sadashivpetimath 		.flags = IORESOURCE_IRQ,
95144f72e53SVirupax Sadashivpetimath 	},
95244f72e53SVirupax Sadashivpetimath 	{
95344f72e53SVirupax Sadashivpetimath 		.name  = "KeyStuck",
95444f72e53SVirupax Sadashivpetimath 		.start = AB8505_INT_KEYSTUCK,
95544f72e53SVirupax Sadashivpetimath 		.end   = AB8505_INT_KEYSTUCK,
95644f72e53SVirupax Sadashivpetimath 		.flags = IORESOURCE_IRQ,
95744f72e53SVirupax Sadashivpetimath 	},
95844f72e53SVirupax Sadashivpetimath };
95944f72e53SVirupax Sadashivpetimath 
9605cef8df5SRobert Rosengren static struct resource __devinitdata ab8500_temp_resources[] = {
961e098adedSMattias Wallin 	{
962e098adedSMattias Wallin 		.name  = "AB8500_TEMP_WARM",
963e098adedSMattias Wallin 		.start = AB8500_INT_TEMP_WARM,
964e098adedSMattias Wallin 		.end   = AB8500_INT_TEMP_WARM,
965e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
966e098adedSMattias Wallin 	},
967e098adedSMattias Wallin };
968e098adedSMattias Wallin 
969d6255529SLinus Walleij static struct mfd_cell __devinitdata abx500_common_devs[] = {
9705814fc35SMattias Wallin #ifdef CONFIG_DEBUG_FS
9715814fc35SMattias Wallin 	{
9725814fc35SMattias Wallin 		.name = "ab8500-debug",
973bad76991SLee Jones 		.of_compatible = "stericsson,ab8500-debug",
974e098adedSMattias Wallin 		.num_resources = ARRAY_SIZE(ab8500_debug_resources),
975e098adedSMattias Wallin 		.resources = ab8500_debug_resources,
9765814fc35SMattias Wallin 	},
9775814fc35SMattias Wallin #endif
97862579266SRabin Vincent 	{
979e098adedSMattias Wallin 		.name = "ab8500-sysctrl",
980bad76991SLee Jones 		.of_compatible = "stericsson,ab8500-sysctrl",
981e098adedSMattias Wallin 	},
982e098adedSMattias Wallin 	{
983e098adedSMattias Wallin 		.name = "ab8500-regulator",
984bad76991SLee Jones 		.of_compatible = "stericsson,ab8500-regulator",
985e098adedSMattias Wallin 	},
986e098adedSMattias Wallin 	{
98762579266SRabin Vincent 		.name = "ab8500-gpadc",
988bad76991SLee Jones 		.of_compatible = "stericsson,ab8500-gpadc",
98962579266SRabin Vincent 		.num_resources = ARRAY_SIZE(ab8500_gpadc_resources),
99062579266SRabin Vincent 		.resources = ab8500_gpadc_resources,
99162579266SRabin Vincent 	},
99262579266SRabin Vincent 	{
99362579266SRabin Vincent 		.name = "ab8500-rtc",
994bad76991SLee Jones 		.of_compatible = "stericsson,ab8500-rtc",
99562579266SRabin Vincent 		.num_resources = ARRAY_SIZE(ab8500_rtc_resources),
99662579266SRabin Vincent 		.resources = ab8500_rtc_resources,
99762579266SRabin Vincent 	},
998f0f05b1cSArun Murthy 	{
9996af75ecdSLinus Walleij 		.name = "ab8500-acc-det",
1000bad76991SLee Jones 		.of_compatible = "stericsson,ab8500-acc-det",
10016af75ecdSLinus Walleij 		.num_resources = ARRAY_SIZE(ab8500_av_acc_detect_resources),
10026af75ecdSLinus Walleij 		.resources = ab8500_av_acc_detect_resources,
10036af75ecdSLinus Walleij 	},
10046af75ecdSLinus Walleij 	{
1005e098adedSMattias Wallin 		.name = "ab8500-poweron-key",
1006bad76991SLee Jones 		.of_compatible = "stericsson,ab8500-poweron-key",
1007e098adedSMattias Wallin 		.num_resources = ARRAY_SIZE(ab8500_poweronkey_db_resources),
1008e098adedSMattias Wallin 		.resources = ab8500_poweronkey_db_resources,
1009e098adedSMattias Wallin 	},
1010e098adedSMattias Wallin 	{
1011f0f05b1cSArun Murthy 		.name = "ab8500-pwm",
1012bad76991SLee Jones 		.of_compatible = "stericsson,ab8500-pwm",
1013f0f05b1cSArun Murthy 		.id = 1,
1014f0f05b1cSArun Murthy 	},
1015f0f05b1cSArun Murthy 	{
1016f0f05b1cSArun Murthy 		.name = "ab8500-pwm",
1017bad76991SLee Jones 		.of_compatible = "stericsson,ab8500-pwm",
1018f0f05b1cSArun Murthy 		.id = 2,
1019f0f05b1cSArun Murthy 	},
1020f0f05b1cSArun Murthy 	{
1021f0f05b1cSArun Murthy 		.name = "ab8500-pwm",
1022bad76991SLee Jones 		.of_compatible = "stericsson,ab8500-pwm",
1023f0f05b1cSArun Murthy 		.id = 3,
1024f0f05b1cSArun Murthy 	},
1025bad76991SLee Jones 	{
1026bad76991SLee Jones 		.name = "ab8500-leds",
1027bad76991SLee Jones 		.of_compatible = "stericsson,ab8500-leds",
1028bad76991SLee Jones 	},
102977686517SSundar R Iyer 	{
1030e098adedSMattias Wallin 		.name = "ab8500-denc",
1031bad76991SLee Jones 		.of_compatible = "stericsson,ab8500-denc",
1032e098adedSMattias Wallin 	},
1033e098adedSMattias Wallin 	{
1034e098adedSMattias Wallin 		.name = "ab8500-temp",
1035bad76991SLee Jones 		.of_compatible = "stericsson,ab8500-temp",
1036e098adedSMattias Wallin 		.num_resources = ARRAY_SIZE(ab8500_temp_resources),
1037e098adedSMattias Wallin 		.resources = ab8500_temp_resources,
103877686517SSundar R Iyer 	},
103962579266SRabin Vincent };
104062579266SRabin Vincent 
10416ef9418cSRickard Andersson static struct mfd_cell __devinitdata ab8500_bm_devs[] = {
10426ef9418cSRickard Andersson 	{
10436ef9418cSRickard Andersson 		.name = "ab8500-charger",
10446ef9418cSRickard Andersson 		.num_resources = ARRAY_SIZE(ab8500_charger_resources),
10456ef9418cSRickard Andersson 		.resources = ab8500_charger_resources,
10466ef9418cSRickard Andersson 	},
10476ef9418cSRickard Andersson 	{
10486ef9418cSRickard Andersson 		.name = "ab8500-btemp",
10496ef9418cSRickard Andersson 		.num_resources = ARRAY_SIZE(ab8500_btemp_resources),
10506ef9418cSRickard Andersson 		.resources = ab8500_btemp_resources,
10516ef9418cSRickard Andersson 	},
10526ef9418cSRickard Andersson 	{
10536ef9418cSRickard Andersson 		.name = "ab8500-fg",
1054e0f1abebSRajanikanth H.V 		.of_compatible = "stericsson,ab8500-fg",
10556ef9418cSRickard Andersson 		.num_resources = ARRAY_SIZE(ab8500_fg_resources),
10566ef9418cSRickard Andersson 		.resources = ab8500_fg_resources,
1057e0f1abebSRajanikanth H.V #ifndef CONFIG_OF
1058e0f1abebSRajanikanth H.V 		.platform_data = &ab8500_bm_data,
1059e0f1abebSRajanikanth H.V 		.pdata_size = sizeof(ab8500_bm_data),
1060e0f1abebSRajanikanth H.V #endif
10616ef9418cSRickard Andersson 	},
10626ef9418cSRickard Andersson 	{
10636ef9418cSRickard Andersson 		.name = "ab8500-chargalg",
10646ef9418cSRickard Andersson 		.num_resources = ARRAY_SIZE(ab8500_chargalg_resources),
10656ef9418cSRickard Andersson 		.resources = ab8500_chargalg_resources,
10666ef9418cSRickard Andersson 	},
10676ef9418cSRickard Andersson };
10686ef9418cSRickard Andersson 
1069d6255529SLinus Walleij static struct mfd_cell __devinitdata ab8500_devs[] = {
1070d6255529SLinus Walleij 	{
1071d6255529SLinus Walleij 		.name = "ab8500-gpio",
1072bad76991SLee Jones 		.of_compatible = "stericsson,ab8500-gpio",
1073d6255529SLinus Walleij 		.num_resources = ARRAY_SIZE(ab8500_gpio_resources),
1074d6255529SLinus Walleij 		.resources = ab8500_gpio_resources,
1075d6255529SLinus Walleij 	},
1076d6255529SLinus Walleij 	{
1077d6255529SLinus Walleij 		.name = "ab8500-usb",
1078bad76991SLee Jones 		.of_compatible = "stericsson,ab8500-usb",
1079d6255529SLinus Walleij 		.num_resources = ARRAY_SIZE(ab8500_usb_resources),
1080d6255529SLinus Walleij 		.resources = ab8500_usb_resources,
1081d6255529SLinus Walleij 	},
108244f72e53SVirupax Sadashivpetimath 	{
108344f72e53SVirupax Sadashivpetimath 		.name = "ab8500-codec",
108481a21cddSLee Jones 		.of_compatible = "stericsson,ab8500-codec",
108544f72e53SVirupax Sadashivpetimath 	},
1086d6255529SLinus Walleij };
1087d6255529SLinus Walleij 
1088d6255529SLinus Walleij static struct mfd_cell __devinitdata ab9540_devs[] = {
1089d6255529SLinus Walleij 	{
1090d6255529SLinus Walleij 		.name = "ab8500-gpio",
1091d6255529SLinus Walleij 		.num_resources = ARRAY_SIZE(ab9540_gpio_resources),
1092d6255529SLinus Walleij 		.resources = ab9540_gpio_resources,
1093d6255529SLinus Walleij 	},
1094d6255529SLinus Walleij 	{
1095d6255529SLinus Walleij 		.name = "ab9540-usb",
1096d6255529SLinus Walleij 		.num_resources = ARRAY_SIZE(ab8500_usb_resources),
1097d6255529SLinus Walleij 		.resources = ab8500_usb_resources,
1098d6255529SLinus Walleij 	},
109944f72e53SVirupax Sadashivpetimath 	{
110044f72e53SVirupax Sadashivpetimath 		.name = "ab9540-codec",
110144f72e53SVirupax Sadashivpetimath 	},
110244f72e53SVirupax Sadashivpetimath };
110344f72e53SVirupax Sadashivpetimath 
110444f72e53SVirupax Sadashivpetimath /* Device list common to ab9540 and ab8505 */
110544f72e53SVirupax Sadashivpetimath static struct mfd_cell __devinitdata ab9540_ab8505_devs[] = {
110644f72e53SVirupax Sadashivpetimath 	{
110744f72e53SVirupax Sadashivpetimath 		.name = "ab-iddet",
110844f72e53SVirupax Sadashivpetimath 		.num_resources = ARRAY_SIZE(ab8505_iddet_resources),
110944f72e53SVirupax Sadashivpetimath 		.resources = ab8505_iddet_resources,
111044f72e53SVirupax Sadashivpetimath 	},
1111d6255529SLinus Walleij };
1112d6255529SLinus Walleij 
1113cca69b67SMattias Wallin static ssize_t show_chip_id(struct device *dev,
1114cca69b67SMattias Wallin 				struct device_attribute *attr, char *buf)
1115cca69b67SMattias Wallin {
1116cca69b67SMattias Wallin 	struct ab8500 *ab8500;
1117cca69b67SMattias Wallin 
1118cca69b67SMattias Wallin 	ab8500 = dev_get_drvdata(dev);
1119cca69b67SMattias Wallin 	return sprintf(buf, "%#x\n", ab8500 ? ab8500->chip_id : -EINVAL);
1120cca69b67SMattias Wallin }
1121cca69b67SMattias Wallin 
1122e5c238c3SMattias Wallin /*
1123e5c238c3SMattias Wallin  * ab8500 has switched off due to (SWITCH_OFF_STATUS):
1124e5c238c3SMattias Wallin  * 0x01 Swoff bit programming
1125e5c238c3SMattias Wallin  * 0x02 Thermal protection activation
1126e5c238c3SMattias Wallin  * 0x04 Vbat lower then BattOk falling threshold
1127e5c238c3SMattias Wallin  * 0x08 Watchdog expired
1128e5c238c3SMattias Wallin  * 0x10 Non presence of 32kHz clock
1129e5c238c3SMattias Wallin  * 0x20 Battery level lower than power on reset threshold
1130e5c238c3SMattias Wallin  * 0x40 Power on key 1 pressed longer than 10 seconds
1131e5c238c3SMattias Wallin  * 0x80 DB8500 thermal shutdown
1132e5c238c3SMattias Wallin  */
1133e5c238c3SMattias Wallin static ssize_t show_switch_off_status(struct device *dev,
1134e5c238c3SMattias Wallin 				struct device_attribute *attr, char *buf)
1135e5c238c3SMattias Wallin {
1136e5c238c3SMattias Wallin 	int ret;
1137e5c238c3SMattias Wallin 	u8 value;
1138e5c238c3SMattias Wallin 	struct ab8500 *ab8500;
1139e5c238c3SMattias Wallin 
1140e5c238c3SMattias Wallin 	ab8500 = dev_get_drvdata(dev);
1141e5c238c3SMattias Wallin 	ret = get_register_interruptible(ab8500, AB8500_RTC,
1142e5c238c3SMattias Wallin 		AB8500_SWITCH_OFF_STATUS, &value);
1143e5c238c3SMattias Wallin 	if (ret < 0)
1144e5c238c3SMattias Wallin 		return ret;
1145e5c238c3SMattias Wallin 	return sprintf(buf, "%#x\n", value);
1146e5c238c3SMattias Wallin }
1147e5c238c3SMattias Wallin 
1148b4a31037SAndrew Lynn /*
1149b4a31037SAndrew Lynn  * ab8500 has turned on due to (TURN_ON_STATUS):
1150b4a31037SAndrew Lynn  * 0x01 PORnVbat
1151b4a31037SAndrew Lynn  * 0x02 PonKey1dbF
1152b4a31037SAndrew Lynn  * 0x04 PonKey2dbF
1153b4a31037SAndrew Lynn  * 0x08 RTCAlarm
1154b4a31037SAndrew Lynn  * 0x10 MainChDet
1155b4a31037SAndrew Lynn  * 0x20 VbusDet
1156b4a31037SAndrew Lynn  * 0x40 UsbIDDetect
1157b4a31037SAndrew Lynn  * 0x80 Reserved
1158b4a31037SAndrew Lynn  */
1159b4a31037SAndrew Lynn static ssize_t show_turn_on_status(struct device *dev,
1160b4a31037SAndrew Lynn 				struct device_attribute *attr, char *buf)
1161b4a31037SAndrew Lynn {
1162b4a31037SAndrew Lynn 	int ret;
1163b4a31037SAndrew Lynn 	u8 value;
1164b4a31037SAndrew Lynn 	struct ab8500 *ab8500;
1165b4a31037SAndrew Lynn 
1166b4a31037SAndrew Lynn 	ab8500 = dev_get_drvdata(dev);
1167b4a31037SAndrew Lynn 	ret = get_register_interruptible(ab8500, AB8500_SYS_CTRL1_BLOCK,
1168b4a31037SAndrew Lynn 		AB8500_TURN_ON_STATUS, &value);
1169b4a31037SAndrew Lynn 	if (ret < 0)
1170b4a31037SAndrew Lynn 		return ret;
1171b4a31037SAndrew Lynn 	return sprintf(buf, "%#x\n", value);
1172b4a31037SAndrew Lynn }
1173b4a31037SAndrew Lynn 
1174d6255529SLinus Walleij static ssize_t show_ab9540_dbbrstn(struct device *dev,
1175d6255529SLinus Walleij 				struct device_attribute *attr, char *buf)
1176d6255529SLinus Walleij {
1177d6255529SLinus Walleij 	struct ab8500 *ab8500;
1178d6255529SLinus Walleij 	int ret;
1179d6255529SLinus Walleij 	u8 value;
1180d6255529SLinus Walleij 
1181d6255529SLinus Walleij 	ab8500 = dev_get_drvdata(dev);
1182d6255529SLinus Walleij 
1183d6255529SLinus Walleij 	ret = get_register_interruptible(ab8500, AB8500_REGU_CTRL2,
1184d6255529SLinus Walleij 		AB9540_MODEM_CTRL2_REG, &value);
1185d6255529SLinus Walleij 	if (ret < 0)
1186d6255529SLinus Walleij 		return ret;
1187d6255529SLinus Walleij 
1188d6255529SLinus Walleij 	return sprintf(buf, "%d\n",
1189d6255529SLinus Walleij 			(value & AB9540_MODEM_CTRL2_SWDBBRSTN_BIT) ? 1 : 0);
1190d6255529SLinus Walleij }
1191d6255529SLinus Walleij 
1192d6255529SLinus Walleij static ssize_t store_ab9540_dbbrstn(struct device *dev,
1193d6255529SLinus Walleij 	struct device_attribute *attr, const char *buf, size_t count)
1194d6255529SLinus Walleij {
1195d6255529SLinus Walleij 	struct ab8500 *ab8500;
1196d6255529SLinus Walleij 	int ret = count;
1197d6255529SLinus Walleij 	int err;
1198d6255529SLinus Walleij 	u8 bitvalues;
1199d6255529SLinus Walleij 
1200d6255529SLinus Walleij 	ab8500 = dev_get_drvdata(dev);
1201d6255529SLinus Walleij 
1202d6255529SLinus Walleij 	if (count > 0) {
1203d6255529SLinus Walleij 		switch (buf[0]) {
1204d6255529SLinus Walleij 		case '0':
1205d6255529SLinus Walleij 			bitvalues = 0;
1206d6255529SLinus Walleij 			break;
1207d6255529SLinus Walleij 		case '1':
1208d6255529SLinus Walleij 			bitvalues = AB9540_MODEM_CTRL2_SWDBBRSTN_BIT;
1209d6255529SLinus Walleij 			break;
1210d6255529SLinus Walleij 		default:
1211d6255529SLinus Walleij 			goto exit;
1212d6255529SLinus Walleij 		}
1213d6255529SLinus Walleij 
1214d6255529SLinus Walleij 		err = mask_and_set_register_interruptible(ab8500,
1215d6255529SLinus Walleij 			AB8500_REGU_CTRL2, AB9540_MODEM_CTRL2_REG,
1216d6255529SLinus Walleij 			AB9540_MODEM_CTRL2_SWDBBRSTN_BIT, bitvalues);
1217d6255529SLinus Walleij 		if (err)
1218d6255529SLinus Walleij 			dev_info(ab8500->dev,
1219d6255529SLinus Walleij 				"Failed to set DBBRSTN %c, err %#x\n",
1220d6255529SLinus Walleij 				buf[0], err);
1221d6255529SLinus Walleij 	}
1222d6255529SLinus Walleij 
1223d6255529SLinus Walleij exit:
1224d6255529SLinus Walleij 	return ret;
1225d6255529SLinus Walleij }
1226d6255529SLinus Walleij 
1227cca69b67SMattias Wallin static DEVICE_ATTR(chip_id, S_IRUGO, show_chip_id, NULL);
1228e5c238c3SMattias Wallin static DEVICE_ATTR(switch_off_status, S_IRUGO, show_switch_off_status, NULL);
1229b4a31037SAndrew Lynn static DEVICE_ATTR(turn_on_status, S_IRUGO, show_turn_on_status, NULL);
1230d6255529SLinus Walleij static DEVICE_ATTR(dbbrstn, S_IRUGO | S_IWUSR,
1231d6255529SLinus Walleij 			show_ab9540_dbbrstn, store_ab9540_dbbrstn);
1232cca69b67SMattias Wallin 
1233cca69b67SMattias Wallin static struct attribute *ab8500_sysfs_entries[] = {
1234cca69b67SMattias Wallin 	&dev_attr_chip_id.attr,
1235e5c238c3SMattias Wallin 	&dev_attr_switch_off_status.attr,
1236b4a31037SAndrew Lynn 	&dev_attr_turn_on_status.attr,
1237cca69b67SMattias Wallin 	NULL,
1238cca69b67SMattias Wallin };
1239cca69b67SMattias Wallin 
1240d6255529SLinus Walleij static struct attribute *ab9540_sysfs_entries[] = {
1241d6255529SLinus Walleij 	&dev_attr_chip_id.attr,
1242d6255529SLinus Walleij 	&dev_attr_switch_off_status.attr,
1243d6255529SLinus Walleij 	&dev_attr_turn_on_status.attr,
1244d6255529SLinus Walleij 	&dev_attr_dbbrstn.attr,
1245d6255529SLinus Walleij 	NULL,
1246d6255529SLinus Walleij };
1247d6255529SLinus Walleij 
1248cca69b67SMattias Wallin static struct attribute_group ab8500_attr_group = {
1249cca69b67SMattias Wallin 	.attrs	= ab8500_sysfs_entries,
1250cca69b67SMattias Wallin };
1251cca69b67SMattias Wallin 
1252d6255529SLinus Walleij static struct attribute_group ab9540_attr_group = {
1253d6255529SLinus Walleij 	.attrs	= ab9540_sysfs_entries,
1254d6255529SLinus Walleij };
1255d6255529SLinus Walleij 
1256d28f1db8SLee Jones static int __devinit ab8500_probe(struct platform_device *pdev)
125762579266SRabin Vincent {
1258b04c530cSJonas Aaberg 	static char *switch_off_status[] = {
1259b04c530cSJonas Aaberg 		"Swoff bit programming",
1260b04c530cSJonas Aaberg 		"Thermal protection activation",
1261b04c530cSJonas Aaberg 		"Vbat lower then BattOk falling threshold",
1262b04c530cSJonas Aaberg 		"Watchdog expired",
1263b04c530cSJonas Aaberg 		"Non presence of 32kHz clock",
1264b04c530cSJonas Aaberg 		"Battery level lower than power on reset threshold",
1265b04c530cSJonas Aaberg 		"Power on key 1 pressed longer than 10 seconds",
1266b04c530cSJonas Aaberg 		"DB8500 thermal shutdown"};
1267d28f1db8SLee Jones 	struct ab8500_platform_data *plat = dev_get_platdata(&pdev->dev);
1268d28f1db8SLee Jones 	const struct platform_device_id *platid = platform_get_device_id(pdev);
12696bc4a568SLee Jones 	enum ab8500_version version = AB8500_VERSION_UNDEFINED;
12706bc4a568SLee Jones 	struct device_node *np = pdev->dev.of_node;
1271d28f1db8SLee Jones 	struct ab8500 *ab8500;
1272d28f1db8SLee Jones 	struct resource *resource;
127362579266SRabin Vincent 	int ret;
127462579266SRabin Vincent 	int i;
127547c16975SMattias Wallin 	u8 value;
127662579266SRabin Vincent 
1277d28f1db8SLee Jones 	ab8500 = kzalloc(sizeof *ab8500, GFP_KERNEL);
1278d28f1db8SLee Jones 	if (!ab8500)
1279d28f1db8SLee Jones 		return -ENOMEM;
1280d28f1db8SLee Jones 
128162579266SRabin Vincent 	if (plat)
128262579266SRabin Vincent 		ab8500->irq_base = plat->irq_base;
128362579266SRabin Vincent 
1284d28f1db8SLee Jones 	ab8500->dev = &pdev->dev;
1285d28f1db8SLee Jones 
1286d28f1db8SLee Jones 	resource = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
1287d28f1db8SLee Jones 	if (!resource) {
1288d28f1db8SLee Jones 		ret = -ENODEV;
1289d28f1db8SLee Jones 		goto out_free_ab8500;
1290d28f1db8SLee Jones 	}
1291d28f1db8SLee Jones 
1292d28f1db8SLee Jones 	ab8500->irq = resource->start;
1293d28f1db8SLee Jones 
1294822672a7SLee Jones 	ab8500->read = ab8500_prcmu_read;
1295822672a7SLee Jones 	ab8500->write = ab8500_prcmu_write;
1296822672a7SLee Jones 	ab8500->write_masked = ab8500_prcmu_write_masked;
1297d28f1db8SLee Jones 
129862579266SRabin Vincent 	mutex_init(&ab8500->lock);
129962579266SRabin Vincent 	mutex_init(&ab8500->irq_lock);
1300112a80d2SJonas Aaberg 	atomic_set(&ab8500->transfer_ongoing, 0);
130162579266SRabin Vincent 
1302d28f1db8SLee Jones 	platform_set_drvdata(pdev, ab8500);
1303d28f1db8SLee Jones 
13046bc4a568SLee Jones 	if (platid)
13056bc4a568SLee Jones 		version = platid->driver_data;
13066bc4a568SLee Jones 
13070f620837SLinus Walleij 	if (version != AB8500_VERSION_UNDEFINED)
13080f620837SLinus Walleij 		ab8500->version = version;
13090f620837SLinus Walleij 	else {
13100f620837SLinus Walleij 		ret = get_register_interruptible(ab8500, AB8500_MISC,
13110f620837SLinus Walleij 			AB8500_IC_NAME_REG, &value);
13120f620837SLinus Walleij 		if (ret < 0)
1313d28f1db8SLee Jones 			goto out_free_ab8500;
13140f620837SLinus Walleij 
13150f620837SLinus Walleij 		ab8500->version = value;
13160f620837SLinus Walleij 	}
13170f620837SLinus Walleij 
131847c16975SMattias Wallin 	ret = get_register_interruptible(ab8500, AB8500_MISC,
131947c16975SMattias Wallin 		AB8500_REV_REG, &value);
132062579266SRabin Vincent 	if (ret < 0)
1321d28f1db8SLee Jones 		goto out_free_ab8500;
132262579266SRabin Vincent 
132347c16975SMattias Wallin 	ab8500->chip_id = value;
132462579266SRabin Vincent 
13250f620837SLinus Walleij 	dev_info(ab8500->dev, "detected chip, %s rev. %1x.%1x\n",
13260f620837SLinus Walleij 			ab8500_version_str[ab8500->version],
13270f620837SLinus Walleij 			ab8500->chip_id >> 4,
13280f620837SLinus Walleij 			ab8500->chip_id & 0x0F);
13290f620837SLinus Walleij 
1330d6255529SLinus Walleij 	/* Configure AB8500 or AB9540 IRQ */
1331a982362cSBengt Jonsson 	if (is_ab9540(ab8500) || is_ab8505(ab8500)) {
1332d6255529SLinus Walleij 		ab8500->mask_size = AB9540_NUM_IRQ_REGS;
1333d6255529SLinus Walleij 		ab8500->irq_reg_offset = ab9540_irq_regoffset;
1334d6255529SLinus Walleij 	} else {
13352ced445eSLinus Walleij 		ab8500->mask_size = AB8500_NUM_IRQ_REGS;
13362ced445eSLinus Walleij 		ab8500->irq_reg_offset = ab8500_irq_regoffset;
1337d6255529SLinus Walleij 	}
13382ced445eSLinus Walleij 	ab8500->mask = kzalloc(ab8500->mask_size, GFP_KERNEL);
13392ced445eSLinus Walleij 	if (!ab8500->mask)
13402ced445eSLinus Walleij 		return -ENOMEM;
13412ced445eSLinus Walleij 	ab8500->oldmask = kzalloc(ab8500->mask_size, GFP_KERNEL);
13422ced445eSLinus Walleij 	if (!ab8500->oldmask) {
13432ced445eSLinus Walleij 		ret = -ENOMEM;
13442ced445eSLinus Walleij 		goto out_freemask;
13452ced445eSLinus Walleij 	}
1346e5c238c3SMattias Wallin 	/*
1347e5c238c3SMattias Wallin 	 * ab8500 has switched off due to (SWITCH_OFF_STATUS):
1348e5c238c3SMattias Wallin 	 * 0x01 Swoff bit programming
1349e5c238c3SMattias Wallin 	 * 0x02 Thermal protection activation
1350e5c238c3SMattias Wallin 	 * 0x04 Vbat lower then BattOk falling threshold
1351e5c238c3SMattias Wallin 	 * 0x08 Watchdog expired
1352e5c238c3SMattias Wallin 	 * 0x10 Non presence of 32kHz clock
1353e5c238c3SMattias Wallin 	 * 0x20 Battery level lower than power on reset threshold
1354e5c238c3SMattias Wallin 	 * 0x40 Power on key 1 pressed longer than 10 seconds
1355e5c238c3SMattias Wallin 	 * 0x80 DB8500 thermal shutdown
1356e5c238c3SMattias Wallin 	 */
1357e5c238c3SMattias Wallin 
1358e5c238c3SMattias Wallin 	ret = get_register_interruptible(ab8500, AB8500_RTC,
1359e5c238c3SMattias Wallin 		AB8500_SWITCH_OFF_STATUS, &value);
1360e5c238c3SMattias Wallin 	if (ret < 0)
1361e5c238c3SMattias Wallin 		return ret;
1362b04c530cSJonas Aaberg 	dev_info(ab8500->dev, "switch off cause(s) (%#x): ", value);
1363b04c530cSJonas Aaberg 
1364b04c530cSJonas Aaberg 	if (value) {
1365b04c530cSJonas Aaberg 		for (i = 0; i < ARRAY_SIZE(switch_off_status); i++) {
1366b04c530cSJonas Aaberg 			if (value & 1)
1367b04c530cSJonas Aaberg 				printk(KERN_CONT " \"%s\"",
1368b04c530cSJonas Aaberg 				       switch_off_status[i]);
1369b04c530cSJonas Aaberg 			value = value >> 1;
1370b04c530cSJonas Aaberg 
1371b04c530cSJonas Aaberg 		}
1372b04c530cSJonas Aaberg 		printk(KERN_CONT "\n");
1373b04c530cSJonas Aaberg 	} else {
1374b04c530cSJonas Aaberg 		printk(KERN_CONT " None\n");
1375b04c530cSJonas Aaberg 	}
1376e5c238c3SMattias Wallin 
137762579266SRabin Vincent 	if (plat && plat->init)
137862579266SRabin Vincent 		plat->init(ab8500);
137962579266SRabin Vincent 
138062579266SRabin Vincent 	/* Clear and mask all interrupts */
13812ced445eSLinus Walleij 	for (i = 0; i < ab8500->mask_size; i++) {
13820f620837SLinus Walleij 		/*
13830f620837SLinus Walleij 		 * Interrupt register 12 doesn't exist prior to AB8500 version
13840f620837SLinus Walleij 		 * 2.0
13850f620837SLinus Walleij 		 */
13860f620837SLinus Walleij 		if (ab8500->irq_reg_offset[i] == 11 &&
13870f620837SLinus Walleij 				is_ab8500_1p1_or_earlier(ab8500))
138892d50a41SMattias Wallin 			continue;
138962579266SRabin Vincent 
139047c16975SMattias Wallin 		get_register_interruptible(ab8500, AB8500_INTERRUPT,
13912ced445eSLinus Walleij 			AB8500_IT_LATCH1_REG + ab8500->irq_reg_offset[i],
139292d50a41SMattias Wallin 			&value);
139347c16975SMattias Wallin 		set_register_interruptible(ab8500, AB8500_INTERRUPT,
13942ced445eSLinus Walleij 			AB8500_IT_MASK1_REG + ab8500->irq_reg_offset[i], 0xff);
139562579266SRabin Vincent 	}
139662579266SRabin Vincent 
139747c16975SMattias Wallin 	ret = abx500_register_ops(ab8500->dev, &ab8500_ops);
139847c16975SMattias Wallin 	if (ret)
13992ced445eSLinus Walleij 		goto out_freeoldmask;
140047c16975SMattias Wallin 
14012ced445eSLinus Walleij 	for (i = 0; i < ab8500->mask_size; i++)
140262579266SRabin Vincent 		ab8500->mask[i] = ab8500->oldmask[i] = 0xff;
140362579266SRabin Vincent 
140406e589efSLee Jones 	ret = ab8500_irq_init(ab8500, np);
140562579266SRabin Vincent 	if (ret)
14062ced445eSLinus Walleij 		goto out_freeoldmask;
140762579266SRabin Vincent 
14087ccfe9b1SMichel JAOUEN 	/*  Activate this feature only in ab9540 */
14097ccfe9b1SMichel JAOUEN 	/*  till tests are done on ab8500 1p2 or later*/
141006e589efSLee Jones 	if (is_ab9540(ab8500)) {
14117ccfe9b1SMichel JAOUEN 		ret = request_threaded_irq(ab8500->irq, NULL,
14127ccfe9b1SMichel JAOUEN 					ab8500_hierarchical_irq,
14137ccfe9b1SMichel JAOUEN 					IRQF_ONESHOT | IRQF_NO_SUSPEND,
14147ccfe9b1SMichel JAOUEN 					"ab8500", ab8500);
141506e589efSLee Jones 	}
141606e589efSLee Jones 	else {
14177ccfe9b1SMichel JAOUEN 		ret = request_threaded_irq(ab8500->irq, NULL,
14187ccfe9b1SMichel JAOUEN 					ab8500_irq,
14194f079985SMattias Wallin 					IRQF_ONESHOT | IRQF_NO_SUSPEND,
14204f079985SMattias Wallin 					"ab8500", ab8500);
142162579266SRabin Vincent 		if (ret)
142206e589efSLee Jones 			goto out_freeoldmask;
142362579266SRabin Vincent 	}
142462579266SRabin Vincent 
1425d6255529SLinus Walleij 	ret = mfd_add_devices(ab8500->dev, 0, abx500_common_devs,
1426d6255529SLinus Walleij 			ARRAY_SIZE(abx500_common_devs), NULL,
142755692af5SMark Brown 			ab8500->irq_base, ab8500->domain);
1428d6255529SLinus Walleij 	if (ret)
1429d6255529SLinus Walleij 		goto out_freeirq;
1430d6255529SLinus Walleij 
1431d6255529SLinus Walleij 	if (is_ab9540(ab8500))
1432d6255529SLinus Walleij 		ret = mfd_add_devices(ab8500->dev, 0, ab9540_devs,
1433d6255529SLinus Walleij 				ARRAY_SIZE(ab9540_devs), NULL,
143455692af5SMark Brown 				ab8500->irq_base, ab8500->domain);
1435d6255529SLinus Walleij 	else
1436549931f9SSundar R Iyer 		ret = mfd_add_devices(ab8500->dev, 0, ab8500_devs,
143744f72e53SVirupax Sadashivpetimath 				ARRAY_SIZE(ab8500_devs), NULL,
143855692af5SMark Brown 				ab8500->irq_base, ab8500->domain);
14396bc4a568SLee Jones 	if (ret)
14406bc4a568SLee Jones 		goto out_freeirq;
144144f72e53SVirupax Sadashivpetimath 
144244f72e53SVirupax Sadashivpetimath 	if (is_ab9540(ab8500) || is_ab8505(ab8500))
144344f72e53SVirupax Sadashivpetimath 		ret = mfd_add_devices(ab8500->dev, 0, ab9540_ab8505_devs,
144444f72e53SVirupax Sadashivpetimath 				ARRAY_SIZE(ab9540_ab8505_devs), NULL,
144555692af5SMark Brown 				ab8500->irq_base, ab8500->domain);
144662579266SRabin Vincent 	if (ret)
144762579266SRabin Vincent 		goto out_freeirq;
144862579266SRabin Vincent 
14496ef9418cSRickard Andersson 	if (!no_bm) {
14506ef9418cSRickard Andersson 		/* Add battery management devices */
14516ef9418cSRickard Andersson 		ret = mfd_add_devices(ab8500->dev, 0, ab8500_bm_devs,
14526ef9418cSRickard Andersson 				      ARRAY_SIZE(ab8500_bm_devs), NULL,
145355692af5SMark Brown 				      ab8500->irq_base, ab8500->domain);
14546ef9418cSRickard Andersson 		if (ret)
14556ef9418cSRickard Andersson 			dev_err(ab8500->dev, "error adding bm devices\n");
14566ef9418cSRickard Andersson 	}
14576ef9418cSRickard Andersson 
1458d6255529SLinus Walleij 	if (is_ab9540(ab8500))
1459d6255529SLinus Walleij 		ret = sysfs_create_group(&ab8500->dev->kobj,
1460d6255529SLinus Walleij 					&ab9540_attr_group);
1461d6255529SLinus Walleij 	else
1462d6255529SLinus Walleij 		ret = sysfs_create_group(&ab8500->dev->kobj,
1463d6255529SLinus Walleij 					&ab8500_attr_group);
1464cca69b67SMattias Wallin 	if (ret)
1465cca69b67SMattias Wallin 		dev_err(ab8500->dev, "error creating sysfs entries\n");
146606e589efSLee Jones 
146762579266SRabin Vincent 	return ret;
146862579266SRabin Vincent 
146962579266SRabin Vincent out_freeirq:
147062579266SRabin Vincent 	free_irq(ab8500->irq, ab8500);
14712ced445eSLinus Walleij out_freeoldmask:
14722ced445eSLinus Walleij 	kfree(ab8500->oldmask);
14732ced445eSLinus Walleij out_freemask:
14742ced445eSLinus Walleij 	kfree(ab8500->mask);
1475d28f1db8SLee Jones out_free_ab8500:
1476d28f1db8SLee Jones 	kfree(ab8500);
14776d95b7fdSLinus Walleij 
147862579266SRabin Vincent 	return ret;
147962579266SRabin Vincent }
148062579266SRabin Vincent 
1481d28f1db8SLee Jones static int __devexit ab8500_remove(struct platform_device *pdev)
148262579266SRabin Vincent {
1483d28f1db8SLee Jones 	struct ab8500 *ab8500 = platform_get_drvdata(pdev);
1484d28f1db8SLee Jones 
1485d6255529SLinus Walleij 	if (is_ab9540(ab8500))
1486d6255529SLinus Walleij 		sysfs_remove_group(&ab8500->dev->kobj, &ab9540_attr_group);
1487d6255529SLinus Walleij 	else
1488cca69b67SMattias Wallin 		sysfs_remove_group(&ab8500->dev->kobj, &ab8500_attr_group);
148906e589efSLee Jones 
149062579266SRabin Vincent 	mfd_remove_devices(ab8500->dev);
149162579266SRabin Vincent 	free_irq(ab8500->irq, ab8500);
149206e589efSLee Jones 
14932ced445eSLinus Walleij 	kfree(ab8500->oldmask);
14942ced445eSLinus Walleij 	kfree(ab8500->mask);
1495d28f1db8SLee Jones 	kfree(ab8500);
149662579266SRabin Vincent 
149762579266SRabin Vincent 	return 0;
149862579266SRabin Vincent }
149962579266SRabin Vincent 
1500d28f1db8SLee Jones static const struct platform_device_id ab8500_id[] = {
1501d28f1db8SLee Jones 	{ "ab8500-core", AB8500_VERSION_AB8500 },
1502d28f1db8SLee Jones 	{ "ab8505-i2c", AB8500_VERSION_AB8505 },
1503d28f1db8SLee Jones 	{ "ab9540-i2c", AB8500_VERSION_AB9540 },
1504d28f1db8SLee Jones 	{ "ab8540-i2c", AB8500_VERSION_AB8540 },
1505d28f1db8SLee Jones 	{ }
1506d28f1db8SLee Jones };
1507d28f1db8SLee Jones 
1508d28f1db8SLee Jones static struct platform_driver ab8500_core_driver = {
1509d28f1db8SLee Jones 	.driver = {
1510d28f1db8SLee Jones 		.name = "ab8500-core",
1511d28f1db8SLee Jones 		.owner = THIS_MODULE,
1512d28f1db8SLee Jones 	},
1513d28f1db8SLee Jones 	.probe	= ab8500_probe,
1514d28f1db8SLee Jones 	.remove	= __devexit_p(ab8500_remove),
1515d28f1db8SLee Jones 	.id_table = ab8500_id,
1516d28f1db8SLee Jones };
1517d28f1db8SLee Jones 
1518d28f1db8SLee Jones static int __init ab8500_core_init(void)
1519d28f1db8SLee Jones {
1520d28f1db8SLee Jones 	return platform_driver_register(&ab8500_core_driver);
1521d28f1db8SLee Jones }
1522d28f1db8SLee Jones 
1523d28f1db8SLee Jones static void __exit ab8500_core_exit(void)
1524d28f1db8SLee Jones {
1525d28f1db8SLee Jones 	platform_driver_unregister(&ab8500_core_driver);
1526d28f1db8SLee Jones }
1527ba7cbc3eSLee Jones core_initcall(ab8500_core_init);
1528d28f1db8SLee Jones module_exit(ab8500_core_exit);
1529d28f1db8SLee Jones 
1530adceed62SMattias Wallin MODULE_AUTHOR("Mattias Wallin, Srinidhi Kasagar, Rabin Vincent");
153162579266SRabin Vincent MODULE_DESCRIPTION("AB8500 MFD core");
153262579266SRabin Vincent MODULE_LICENSE("GPL v2");
1533