xref: /openbmc/linux/drivers/mfd/ab8500-core.c (revision 00441b5e6b98ad6a50b5cb7f88d473e3ea1e0d75)
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>
22*00441b5eSLee 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
9862579266SRabin Vincent 
997ccfe9b1SMichel JAOUEN /*
1007ccfe9b1SMichel JAOUEN  * latch hierarchy registers
1017ccfe9b1SMichel JAOUEN  */
1027ccfe9b1SMichel JAOUEN #define AB8500_IT_LATCHHIER1_REG	0x60
1037ccfe9b1SMichel JAOUEN #define AB8500_IT_LATCHHIER2_REG	0x61
1047ccfe9b1SMichel JAOUEN #define AB8500_IT_LATCHHIER3_REG	0x62
1057ccfe9b1SMichel JAOUEN 
1067ccfe9b1SMichel JAOUEN #define AB8500_IT_LATCHHIER_NUM		3
1077ccfe9b1SMichel JAOUEN 
10847c16975SMattias Wallin #define AB8500_REV_REG			0x80
1090f620837SLinus Walleij #define AB8500_IC_NAME_REG		0x82
110e5c238c3SMattias Wallin #define AB8500_SWITCH_OFF_STATUS	0x00
11162579266SRabin Vincent 
112b4a31037SAndrew Lynn #define AB8500_TURN_ON_STATUS		0x00
113b4a31037SAndrew Lynn 
1146ef9418cSRickard Andersson static bool no_bm; /* No battery management */
1156ef9418cSRickard Andersson module_param(no_bm, bool, S_IRUGO);
1166ef9418cSRickard Andersson 
117d6255529SLinus Walleij #define AB9540_MODEM_CTRL2_REG			0x23
118d6255529SLinus Walleij #define AB9540_MODEM_CTRL2_SWDBBRSTN_BIT	BIT(2)
119d6255529SLinus Walleij 
12062579266SRabin Vincent /*
12162579266SRabin Vincent  * Map interrupt numbers to the LATCH and MASK register offsets, Interrupt
1222ced445eSLinus Walleij  * numbers are indexed into this array with (num / 8). The interupts are
1232ced445eSLinus Walleij  * defined in linux/mfd/ab8500.h
12462579266SRabin Vincent  *
12562579266SRabin Vincent  * This is one off from the register names, i.e. AB8500_IT_MASK1_REG is at
12662579266SRabin Vincent  * offset 0.
12762579266SRabin Vincent  */
1282ced445eSLinus Walleij /* AB8500 support */
12962579266SRabin Vincent static const int ab8500_irq_regoffset[AB8500_NUM_IRQ_REGS] = {
13092d50a41SMattias Wallin 	0, 1, 2, 3, 4, 6, 7, 8, 9, 11, 18, 19, 20, 21,
13162579266SRabin Vincent };
13262579266SRabin Vincent 
133d6255529SLinus Walleij /* AB9540 support */
134d6255529SLinus Walleij static const int ab9540_irq_regoffset[AB9540_NUM_IRQ_REGS] = {
135d6255529SLinus Walleij 	0, 1, 2, 3, 4, 6, 7, 8, 9, 11, 18, 19, 20, 21, 12, 13, 24,
136d6255529SLinus Walleij };
137d6255529SLinus Walleij 
1380f620837SLinus Walleij static const char ab8500_version_str[][7] = {
1390f620837SLinus Walleij 	[AB8500_VERSION_AB8500] = "AB8500",
1400f620837SLinus Walleij 	[AB8500_VERSION_AB8505] = "AB8505",
1410f620837SLinus Walleij 	[AB8500_VERSION_AB9540] = "AB9540",
1420f620837SLinus Walleij 	[AB8500_VERSION_AB8540] = "AB8540",
1430f620837SLinus Walleij };
1440f620837SLinus Walleij 
145822672a7SLee Jones static int ab8500_prcmu_write(struct ab8500 *ab8500, u16 addr, u8 data)
146d28f1db8SLee Jones {
147d28f1db8SLee Jones 	int ret;
148d28f1db8SLee Jones 
149d28f1db8SLee Jones 	ret = prcmu_abb_write((u8)(addr >> 8), (u8)(addr & 0xFF), &data, 1);
150d28f1db8SLee Jones 	if (ret < 0)
151d28f1db8SLee Jones 		dev_err(ab8500->dev, "prcmu i2c error %d\n", ret);
152d28f1db8SLee Jones 	return ret;
153d28f1db8SLee Jones }
154d28f1db8SLee Jones 
155822672a7SLee Jones static int ab8500_prcmu_write_masked(struct ab8500 *ab8500, u16 addr, u8 mask,
156d28f1db8SLee Jones 	u8 data)
157d28f1db8SLee Jones {
158d28f1db8SLee Jones 	int ret;
159d28f1db8SLee Jones 
160d28f1db8SLee Jones 	ret = prcmu_abb_write_masked((u8)(addr >> 8), (u8)(addr & 0xFF), &data,
161d28f1db8SLee Jones 		&mask, 1);
162d28f1db8SLee Jones 	if (ret < 0)
163d28f1db8SLee Jones 		dev_err(ab8500->dev, "prcmu i2c error %d\n", ret);
164d28f1db8SLee Jones 	return ret;
165d28f1db8SLee Jones }
166d28f1db8SLee Jones 
167822672a7SLee Jones static int ab8500_prcmu_read(struct ab8500 *ab8500, u16 addr)
168d28f1db8SLee Jones {
169d28f1db8SLee Jones 	int ret;
170d28f1db8SLee Jones 	u8 data;
171d28f1db8SLee Jones 
172d28f1db8SLee Jones 	ret = prcmu_abb_read((u8)(addr >> 8), (u8)(addr & 0xFF), &data, 1);
173d28f1db8SLee Jones 	if (ret < 0) {
174d28f1db8SLee Jones 		dev_err(ab8500->dev, "prcmu i2c error %d\n", ret);
175d28f1db8SLee Jones 		return ret;
176d28f1db8SLee Jones 	}
177d28f1db8SLee Jones 	return (int)data;
178d28f1db8SLee Jones }
179d28f1db8SLee Jones 
18047c16975SMattias Wallin static int ab8500_get_chip_id(struct device *dev)
18147c16975SMattias Wallin {
1826bce7bf1SMattias Wallin 	struct ab8500 *ab8500;
1836bce7bf1SMattias Wallin 
1846bce7bf1SMattias Wallin 	if (!dev)
1856bce7bf1SMattias Wallin 		return -EINVAL;
1866bce7bf1SMattias Wallin 	ab8500 = dev_get_drvdata(dev->parent);
1876bce7bf1SMattias Wallin 	return ab8500 ? (int)ab8500->chip_id : -EINVAL;
18847c16975SMattias Wallin }
18947c16975SMattias Wallin 
19047c16975SMattias Wallin static int set_register_interruptible(struct ab8500 *ab8500, u8 bank,
19147c16975SMattias Wallin 	u8 reg, u8 data)
19262579266SRabin Vincent {
19362579266SRabin Vincent 	int ret;
19447c16975SMattias Wallin 	/*
19547c16975SMattias Wallin 	 * Put the u8 bank and u8 register together into a an u16.
19647c16975SMattias Wallin 	 * The bank on higher 8 bits and register in lower 8 bits.
19747c16975SMattias Wallin 	 * */
19847c16975SMattias Wallin 	u16 addr = ((u16)bank) << 8 | reg;
19962579266SRabin Vincent 
20062579266SRabin Vincent 	dev_vdbg(ab8500->dev, "wr: addr %#x <= %#x\n", addr, data);
20162579266SRabin Vincent 
202392cbd1eSRabin Vincent 	mutex_lock(&ab8500->lock);
20347c16975SMattias Wallin 
20447c16975SMattias Wallin 	ret = ab8500->write(ab8500, addr, data);
20547c16975SMattias Wallin 	if (ret < 0)
20647c16975SMattias Wallin 		dev_err(ab8500->dev, "failed to write reg %#x: %d\n",
20747c16975SMattias Wallin 			addr, ret);
20847c16975SMattias Wallin 	mutex_unlock(&ab8500->lock);
20947c16975SMattias Wallin 
21047c16975SMattias Wallin 	return ret;
21147c16975SMattias Wallin }
21247c16975SMattias Wallin 
21347c16975SMattias Wallin static int ab8500_set_register(struct device *dev, u8 bank,
21447c16975SMattias Wallin 	u8 reg, u8 value)
21547c16975SMattias Wallin {
216112a80d2SJonas Aaberg 	int ret;
21747c16975SMattias Wallin 	struct ab8500 *ab8500 = dev_get_drvdata(dev->parent);
21847c16975SMattias Wallin 
219112a80d2SJonas Aaberg 	atomic_inc(&ab8500->transfer_ongoing);
220112a80d2SJonas Aaberg 	ret = set_register_interruptible(ab8500, bank, reg, value);
221112a80d2SJonas Aaberg 	atomic_dec(&ab8500->transfer_ongoing);
222112a80d2SJonas Aaberg 	return ret;
22347c16975SMattias Wallin }
22447c16975SMattias Wallin 
22547c16975SMattias Wallin static int get_register_interruptible(struct ab8500 *ab8500, u8 bank,
22647c16975SMattias Wallin 	u8 reg, u8 *value)
22747c16975SMattias Wallin {
22847c16975SMattias Wallin 	int ret;
22947c16975SMattias Wallin 	/* put the u8 bank and u8 reg together into a an u16.
23047c16975SMattias Wallin 	 * bank on higher 8 bits and reg in lower */
23147c16975SMattias Wallin 	u16 addr = ((u16)bank) << 8 | reg;
23247c16975SMattias Wallin 
233392cbd1eSRabin Vincent 	mutex_lock(&ab8500->lock);
23447c16975SMattias Wallin 
23547c16975SMattias Wallin 	ret = ab8500->read(ab8500, addr);
23647c16975SMattias Wallin 	if (ret < 0)
23747c16975SMattias Wallin 		dev_err(ab8500->dev, "failed to read reg %#x: %d\n",
23847c16975SMattias Wallin 			addr, ret);
23947c16975SMattias Wallin 	else
24047c16975SMattias Wallin 		*value = ret;
24147c16975SMattias Wallin 
24247c16975SMattias Wallin 	mutex_unlock(&ab8500->lock);
24347c16975SMattias Wallin 	dev_vdbg(ab8500->dev, "rd: addr %#x => data %#x\n", addr, ret);
24447c16975SMattias Wallin 
24547c16975SMattias Wallin 	return ret;
24647c16975SMattias Wallin }
24747c16975SMattias Wallin 
24847c16975SMattias Wallin static int ab8500_get_register(struct device *dev, u8 bank,
24947c16975SMattias Wallin 	u8 reg, u8 *value)
25047c16975SMattias Wallin {
251112a80d2SJonas Aaberg 	int ret;
25247c16975SMattias Wallin 	struct ab8500 *ab8500 = dev_get_drvdata(dev->parent);
25347c16975SMattias Wallin 
254112a80d2SJonas Aaberg 	atomic_inc(&ab8500->transfer_ongoing);
255112a80d2SJonas Aaberg 	ret = get_register_interruptible(ab8500, bank, reg, value);
256112a80d2SJonas Aaberg 	atomic_dec(&ab8500->transfer_ongoing);
257112a80d2SJonas Aaberg 	return ret;
25847c16975SMattias Wallin }
25947c16975SMattias Wallin 
26047c16975SMattias Wallin static int mask_and_set_register_interruptible(struct ab8500 *ab8500, u8 bank,
26147c16975SMattias Wallin 	u8 reg, u8 bitmask, u8 bitvalues)
26247c16975SMattias Wallin {
26347c16975SMattias Wallin 	int ret;
26447c16975SMattias Wallin 	/* put the u8 bank and u8 reg together into a an u16.
26547c16975SMattias Wallin 	 * bank on higher 8 bits and reg in lower */
26647c16975SMattias Wallin 	u16 addr = ((u16)bank) << 8 | reg;
26747c16975SMattias Wallin 
268392cbd1eSRabin Vincent 	mutex_lock(&ab8500->lock);
26947c16975SMattias Wallin 
270bc628fd1SMattias Nilsson 	if (ab8500->write_masked == NULL) {
271bc628fd1SMattias Nilsson 		u8 data;
272bc628fd1SMattias Nilsson 
27347c16975SMattias Wallin 		ret = ab8500->read(ab8500, addr);
27447c16975SMattias Wallin 		if (ret < 0) {
27547c16975SMattias Wallin 			dev_err(ab8500->dev, "failed to read reg %#x: %d\n",
27647c16975SMattias Wallin 				addr, ret);
27747c16975SMattias Wallin 			goto out;
27847c16975SMattias Wallin 		}
27947c16975SMattias Wallin 
28047c16975SMattias Wallin 		data = (u8)ret;
28147c16975SMattias Wallin 		data = (~bitmask & data) | (bitmask & bitvalues);
28247c16975SMattias Wallin 
28362579266SRabin Vincent 		ret = ab8500->write(ab8500, addr, data);
28462579266SRabin Vincent 		if (ret < 0)
28562579266SRabin Vincent 			dev_err(ab8500->dev, "failed to write reg %#x: %d\n",
28662579266SRabin Vincent 				addr, ret);
28762579266SRabin Vincent 
288bc628fd1SMattias Nilsson 		dev_vdbg(ab8500->dev, "mask: addr %#x => data %#x\n", addr,
289bc628fd1SMattias Nilsson 			data);
290bc628fd1SMattias Nilsson 		goto out;
291bc628fd1SMattias Nilsson 	}
292bc628fd1SMattias Nilsson 	ret = ab8500->write_masked(ab8500, addr, bitmask, bitvalues);
293bc628fd1SMattias Nilsson 	if (ret < 0)
294bc628fd1SMattias Nilsson 		dev_err(ab8500->dev, "failed to modify reg %#x: %d\n", addr,
295bc628fd1SMattias Nilsson 			ret);
29662579266SRabin Vincent out:
29762579266SRabin Vincent 	mutex_unlock(&ab8500->lock);
29862579266SRabin Vincent 	return ret;
29962579266SRabin Vincent }
30047c16975SMattias Wallin 
30147c16975SMattias Wallin static int ab8500_mask_and_set_register(struct device *dev,
30247c16975SMattias Wallin 	u8 bank, u8 reg, u8 bitmask, u8 bitvalues)
30347c16975SMattias Wallin {
304112a80d2SJonas Aaberg 	int ret;
30547c16975SMattias Wallin 	struct ab8500 *ab8500 = dev_get_drvdata(dev->parent);
30647c16975SMattias Wallin 
307112a80d2SJonas Aaberg 	atomic_inc(&ab8500->transfer_ongoing);
308112a80d2SJonas Aaberg 	ret= mask_and_set_register_interruptible(ab8500, bank, reg,
30947c16975SMattias Wallin 						 bitmask, bitvalues);
310112a80d2SJonas Aaberg 	atomic_dec(&ab8500->transfer_ongoing);
311112a80d2SJonas Aaberg 	return ret;
31247c16975SMattias Wallin }
31347c16975SMattias Wallin 
31447c16975SMattias Wallin static struct abx500_ops ab8500_ops = {
31547c16975SMattias Wallin 	.get_chip_id = ab8500_get_chip_id,
31647c16975SMattias Wallin 	.get_register = ab8500_get_register,
31747c16975SMattias Wallin 	.set_register = ab8500_set_register,
31847c16975SMattias Wallin 	.get_register_page = NULL,
31947c16975SMattias Wallin 	.set_register_page = NULL,
32047c16975SMattias Wallin 	.mask_and_set_register = ab8500_mask_and_set_register,
32147c16975SMattias Wallin 	.event_registers_startup_state_get = NULL,
32247c16975SMattias Wallin 	.startup_irq_enabled = NULL,
32347c16975SMattias Wallin };
32462579266SRabin Vincent 
3259505a0a0SMark Brown static void ab8500_irq_lock(struct irq_data *data)
32662579266SRabin Vincent {
3279505a0a0SMark Brown 	struct ab8500 *ab8500 = irq_data_get_irq_chip_data(data);
32862579266SRabin Vincent 
32962579266SRabin Vincent 	mutex_lock(&ab8500->irq_lock);
330112a80d2SJonas Aaberg 	atomic_inc(&ab8500->transfer_ongoing);
33162579266SRabin Vincent }
33262579266SRabin Vincent 
3339505a0a0SMark Brown static void ab8500_irq_sync_unlock(struct irq_data *data)
33462579266SRabin Vincent {
3359505a0a0SMark Brown 	struct ab8500 *ab8500 = irq_data_get_irq_chip_data(data);
33662579266SRabin Vincent 	int i;
33762579266SRabin Vincent 
3382ced445eSLinus Walleij 	for (i = 0; i < ab8500->mask_size; i++) {
33962579266SRabin Vincent 		u8 old = ab8500->oldmask[i];
34062579266SRabin Vincent 		u8 new = ab8500->mask[i];
34162579266SRabin Vincent 		int reg;
34262579266SRabin Vincent 
34362579266SRabin Vincent 		if (new == old)
34462579266SRabin Vincent 			continue;
34562579266SRabin Vincent 
3460f620837SLinus Walleij 		/*
3470f620837SLinus Walleij 		 * Interrupt register 12 doesn't exist prior to AB8500 version
3480f620837SLinus Walleij 		 * 2.0
3490f620837SLinus Walleij 		 */
3500f620837SLinus Walleij 		if (ab8500->irq_reg_offset[i] == 11 &&
3510f620837SLinus Walleij 			is_ab8500_1p1_or_earlier(ab8500))
35292d50a41SMattias Wallin 			continue;
35392d50a41SMattias Wallin 
35462579266SRabin Vincent 		ab8500->oldmask[i] = new;
35562579266SRabin Vincent 
3562ced445eSLinus Walleij 		reg = AB8500_IT_MASK1_REG + ab8500->irq_reg_offset[i];
35747c16975SMattias Wallin 		set_register_interruptible(ab8500, AB8500_INTERRUPT, reg, new);
35862579266SRabin Vincent 	}
359112a80d2SJonas Aaberg 	atomic_dec(&ab8500->transfer_ongoing);
36062579266SRabin Vincent 	mutex_unlock(&ab8500->irq_lock);
36162579266SRabin Vincent }
36262579266SRabin Vincent 
3639505a0a0SMark Brown static void ab8500_irq_mask(struct irq_data *data)
36462579266SRabin Vincent {
3659505a0a0SMark Brown 	struct ab8500 *ab8500 = irq_data_get_irq_chip_data(data);
36606e589efSLee Jones 	int offset = data->hwirq;
36762579266SRabin Vincent 	int index = offset / 8;
36862579266SRabin Vincent 	int mask = 1 << (offset % 8);
36962579266SRabin Vincent 
37062579266SRabin Vincent 	ab8500->mask[index] |= mask;
37162579266SRabin Vincent }
37262579266SRabin Vincent 
3739505a0a0SMark Brown static void ab8500_irq_unmask(struct irq_data *data)
37462579266SRabin Vincent {
3759505a0a0SMark Brown 	struct ab8500 *ab8500 = irq_data_get_irq_chip_data(data);
37606e589efSLee Jones 	int offset = data->hwirq;
37762579266SRabin Vincent 	int index = offset / 8;
37862579266SRabin Vincent 	int mask = 1 << (offset % 8);
37962579266SRabin Vincent 
38062579266SRabin Vincent 	ab8500->mask[index] &= ~mask;
38162579266SRabin Vincent }
38262579266SRabin Vincent 
38362579266SRabin Vincent static struct irq_chip ab8500_irq_chip = {
38462579266SRabin Vincent 	.name			= "ab8500",
3859505a0a0SMark Brown 	.irq_bus_lock		= ab8500_irq_lock,
3869505a0a0SMark Brown 	.irq_bus_sync_unlock	= ab8500_irq_sync_unlock,
3879505a0a0SMark Brown 	.irq_mask		= ab8500_irq_mask,
388e6f9306eSVirupax Sadashivpetimath 	.irq_disable		= ab8500_irq_mask,
3899505a0a0SMark Brown 	.irq_unmask		= ab8500_irq_unmask,
39062579266SRabin Vincent };
39162579266SRabin Vincent 
3927ccfe9b1SMichel JAOUEN static int ab8500_handle_hierarchical_line(struct ab8500 *ab8500,
3937ccfe9b1SMichel JAOUEN 					int latch_offset, u8 latch_val)
3947ccfe9b1SMichel JAOUEN {
3957ccfe9b1SMichel JAOUEN 	int int_bit = __ffs(latch_val);
3967ccfe9b1SMichel JAOUEN 	int line, i;
3977ccfe9b1SMichel JAOUEN 
3987ccfe9b1SMichel JAOUEN 	do {
3997ccfe9b1SMichel JAOUEN 		int_bit = __ffs(latch_val);
4007ccfe9b1SMichel JAOUEN 
4017ccfe9b1SMichel JAOUEN 		for (i = 0; i < ab8500->mask_size; i++)
4027ccfe9b1SMichel JAOUEN 			if (ab8500->irq_reg_offset[i] == latch_offset)
4037ccfe9b1SMichel JAOUEN 				break;
4047ccfe9b1SMichel JAOUEN 
4057ccfe9b1SMichel JAOUEN 		if (i >= ab8500->mask_size) {
4067ccfe9b1SMichel JAOUEN 			dev_err(ab8500->dev, "Register offset 0x%2x not declared\n",
4077ccfe9b1SMichel JAOUEN 					latch_offset);
4087ccfe9b1SMichel JAOUEN 			return -ENXIO;
4097ccfe9b1SMichel JAOUEN 		}
4107ccfe9b1SMichel JAOUEN 
4117ccfe9b1SMichel JAOUEN 		line = (i << 3) + int_bit;
4127ccfe9b1SMichel JAOUEN 		latch_val &= ~(1 << int_bit);
4137ccfe9b1SMichel JAOUEN 
4147ccfe9b1SMichel JAOUEN 		handle_nested_irq(ab8500->irq_base + line);
4157ccfe9b1SMichel JAOUEN 	} while (latch_val);
4167ccfe9b1SMichel JAOUEN 
4177ccfe9b1SMichel JAOUEN 	return 0;
4187ccfe9b1SMichel JAOUEN }
4197ccfe9b1SMichel JAOUEN 
4207ccfe9b1SMichel JAOUEN static int ab8500_handle_hierarchical_latch(struct ab8500 *ab8500,
4217ccfe9b1SMichel JAOUEN 					int hier_offset, u8 hier_val)
4227ccfe9b1SMichel JAOUEN {
4237ccfe9b1SMichel JAOUEN 	int latch_bit, status;
4247ccfe9b1SMichel JAOUEN 	u8 latch_offset, latch_val;
4257ccfe9b1SMichel JAOUEN 
4267ccfe9b1SMichel JAOUEN 	do {
4277ccfe9b1SMichel JAOUEN 		latch_bit = __ffs(hier_val);
4287ccfe9b1SMichel JAOUEN 		latch_offset = (hier_offset << 3) + latch_bit;
4297ccfe9b1SMichel JAOUEN 
4307ccfe9b1SMichel JAOUEN 		/* Fix inconsistent ITFromLatch25 bit mapping... */
4317ccfe9b1SMichel JAOUEN 		if (unlikely(latch_offset == 17))
4327ccfe9b1SMichel JAOUEN 			latch_offset = 24;
4337ccfe9b1SMichel JAOUEN 
4347ccfe9b1SMichel JAOUEN 		status = get_register_interruptible(ab8500,
4357ccfe9b1SMichel JAOUEN 				AB8500_INTERRUPT,
4367ccfe9b1SMichel JAOUEN 				AB8500_IT_LATCH1_REG + latch_offset,
4377ccfe9b1SMichel JAOUEN 				&latch_val);
4387ccfe9b1SMichel JAOUEN 		if (status < 0 || latch_val == 0)
4397ccfe9b1SMichel JAOUEN 			goto discard;
4407ccfe9b1SMichel JAOUEN 
4417ccfe9b1SMichel JAOUEN 		status = ab8500_handle_hierarchical_line(ab8500,
4427ccfe9b1SMichel JAOUEN 				latch_offset, latch_val);
4437ccfe9b1SMichel JAOUEN 		if (status < 0)
4447ccfe9b1SMichel JAOUEN 			return status;
4457ccfe9b1SMichel JAOUEN discard:
4467ccfe9b1SMichel JAOUEN 		hier_val &= ~(1 << latch_bit);
4477ccfe9b1SMichel JAOUEN 	} while (hier_val);
4487ccfe9b1SMichel JAOUEN 
4497ccfe9b1SMichel JAOUEN 	return 0;
4507ccfe9b1SMichel JAOUEN }
4517ccfe9b1SMichel JAOUEN 
4527ccfe9b1SMichel JAOUEN static irqreturn_t ab8500_hierarchical_irq(int irq, void *dev)
4537ccfe9b1SMichel JAOUEN {
4547ccfe9b1SMichel JAOUEN 	struct ab8500 *ab8500 = dev;
4557ccfe9b1SMichel JAOUEN 	u8 i;
4567ccfe9b1SMichel JAOUEN 
4577ccfe9b1SMichel JAOUEN 	dev_vdbg(ab8500->dev, "interrupt\n");
4587ccfe9b1SMichel JAOUEN 
4597ccfe9b1SMichel JAOUEN 	/*  Hierarchical interrupt version */
4607ccfe9b1SMichel JAOUEN 	for (i = 0; i < AB8500_IT_LATCHHIER_NUM; i++) {
4617ccfe9b1SMichel JAOUEN 		int status;
4627ccfe9b1SMichel JAOUEN 		u8 hier_val;
4637ccfe9b1SMichel JAOUEN 
4647ccfe9b1SMichel JAOUEN 		status = get_register_interruptible(ab8500, AB8500_INTERRUPT,
4657ccfe9b1SMichel JAOUEN 			AB8500_IT_LATCHHIER1_REG + i, &hier_val);
4667ccfe9b1SMichel JAOUEN 		if (status < 0 || hier_val == 0)
4677ccfe9b1SMichel JAOUEN 			continue;
4687ccfe9b1SMichel JAOUEN 
4697ccfe9b1SMichel JAOUEN 		status = ab8500_handle_hierarchical_latch(ab8500, i, hier_val);
4707ccfe9b1SMichel JAOUEN 		if (status < 0)
4717ccfe9b1SMichel JAOUEN 			break;
4727ccfe9b1SMichel JAOUEN 	}
4737ccfe9b1SMichel JAOUEN 	return IRQ_HANDLED;
4747ccfe9b1SMichel JAOUEN }
4757ccfe9b1SMichel JAOUEN 
47680633f05SLee Jones /**
47780633f05SLee Jones  * ab8500_irq_get_virq(): Map an interrupt on a chip to a virtual IRQ
47880633f05SLee Jones  *
47980633f05SLee Jones  * @ab8500: ab8500_irq controller to operate on.
48080633f05SLee Jones  * @irq: index of the interrupt requested in the chip IRQs
48180633f05SLee Jones  *
48280633f05SLee Jones  * Useful for drivers to request their own IRQs.
48380633f05SLee Jones  */
48480633f05SLee Jones static int ab8500_irq_get_virq(struct ab8500 *ab8500, int irq)
48580633f05SLee Jones {
48680633f05SLee Jones 	if (!ab8500)
48780633f05SLee Jones 		return -EINVAL;
48880633f05SLee Jones 
48980633f05SLee Jones 	return irq_create_mapping(ab8500->domain, irq);
49080633f05SLee Jones }
49180633f05SLee Jones 
49262579266SRabin Vincent static irqreturn_t ab8500_irq(int irq, void *dev)
49362579266SRabin Vincent {
49462579266SRabin Vincent 	struct ab8500 *ab8500 = dev;
49562579266SRabin Vincent 	int i;
49662579266SRabin Vincent 
49762579266SRabin Vincent 	dev_vdbg(ab8500->dev, "interrupt\n");
49862579266SRabin Vincent 
499112a80d2SJonas Aaberg 	atomic_inc(&ab8500->transfer_ongoing);
500112a80d2SJonas Aaberg 
5012ced445eSLinus Walleij 	for (i = 0; i < ab8500->mask_size; i++) {
5022ced445eSLinus Walleij 		int regoffset = ab8500->irq_reg_offset[i];
50362579266SRabin Vincent 		int status;
50447c16975SMattias Wallin 		u8 value;
50562579266SRabin Vincent 
5060f620837SLinus Walleij 		/*
5070f620837SLinus Walleij 		 * Interrupt register 12 doesn't exist prior to AB8500 version
5080f620837SLinus Walleij 		 * 2.0
5090f620837SLinus Walleij 		 */
5100f620837SLinus Walleij 		if (regoffset == 11 && is_ab8500_1p1_or_earlier(ab8500))
51192d50a41SMattias Wallin 			continue;
51292d50a41SMattias Wallin 
51347c16975SMattias Wallin 		status = get_register_interruptible(ab8500, AB8500_INTERRUPT,
51447c16975SMattias Wallin 			AB8500_IT_LATCH1_REG + regoffset, &value);
51547c16975SMattias Wallin 		if (status < 0 || value == 0)
51662579266SRabin Vincent 			continue;
51762579266SRabin Vincent 
51862579266SRabin Vincent 		do {
51988aec4f7SMattias Wallin 			int bit = __ffs(value);
52062579266SRabin Vincent 			int line = i * 8 + bit;
5210a37fc56SLee Jones 			int virq = ab8500_irq_get_virq(ab8500, line);
52262579266SRabin Vincent 
5230a37fc56SLee Jones 			handle_nested_irq(virq);
52447c16975SMattias Wallin 			value &= ~(1 << bit);
525112a80d2SJonas Aaberg 
52647c16975SMattias Wallin 		} while (value);
52762579266SRabin Vincent 	}
528112a80d2SJonas Aaberg 	atomic_dec(&ab8500->transfer_ongoing);
52962579266SRabin Vincent 	return IRQ_HANDLED;
53062579266SRabin Vincent }
53162579266SRabin Vincent 
53206e589efSLee Jones static int ab8500_irq_map(struct irq_domain *d, unsigned int virq,
53306e589efSLee Jones 				irq_hw_number_t hwirq)
53406e589efSLee Jones {
53506e589efSLee Jones 	struct ab8500 *ab8500 = d->host_data;
53606e589efSLee Jones 
53706e589efSLee Jones 	if (!ab8500)
53806e589efSLee Jones 		return -EINVAL;
53906e589efSLee Jones 
54006e589efSLee Jones 	irq_set_chip_data(virq, ab8500);
54106e589efSLee Jones 	irq_set_chip_and_handler(virq, &ab8500_irq_chip,
54206e589efSLee Jones 				handle_simple_irq);
54306e589efSLee Jones 	irq_set_nested_thread(virq, 1);
54406e589efSLee Jones #ifdef CONFIG_ARM
54506e589efSLee Jones 	set_irq_flags(virq, IRQF_VALID);
54606e589efSLee Jones #else
54706e589efSLee Jones 	irq_set_noprobe(virq);
54806e589efSLee Jones #endif
54962579266SRabin Vincent 
55062579266SRabin Vincent 	return 0;
55162579266SRabin Vincent }
55262579266SRabin Vincent 
55306e589efSLee Jones static struct irq_domain_ops ab8500_irq_ops = {
55406e589efSLee Jones         .map    = ab8500_irq_map,
55506e589efSLee Jones         .xlate  = irq_domain_xlate_twocell,
55606e589efSLee Jones };
55706e589efSLee Jones 
55806e589efSLee Jones static int ab8500_irq_init(struct ab8500 *ab8500, struct device_node *np)
55962579266SRabin Vincent {
5602ced445eSLinus Walleij 	int num_irqs;
56162579266SRabin Vincent 
562d6255529SLinus Walleij 	if (is_ab9540(ab8500))
563d6255529SLinus Walleij 		num_irqs = AB9540_NR_IRQS;
564a982362cSBengt Jonsson 	else if (is_ab8505(ab8500))
565a982362cSBengt Jonsson 		num_irqs = AB8505_NR_IRQS;
566d6255529SLinus Walleij 	else
5672ced445eSLinus Walleij 		num_irqs = AB8500_NR_IRQS;
5682ced445eSLinus Walleij 
569f1d11f39SLinus Walleij 	/* If ->irq_base is zero this will give a linear mapping */
570f1d11f39SLinus Walleij 	ab8500->domain = irq_domain_add_simple(NULL,
571f1d11f39SLinus Walleij 			num_irqs, ab8500->irq_base,
572f1d11f39SLinus Walleij 			&ab8500_irq_ops, ab8500);
57306e589efSLee Jones 
57406e589efSLee Jones 	if (!ab8500->domain) {
57506e589efSLee Jones 		dev_err(ab8500->dev, "Failed to create irqdomain\n");
57606e589efSLee Jones 		return -ENOSYS;
57706e589efSLee Jones 	}
57806e589efSLee Jones 
57906e589efSLee Jones 	return 0;
58062579266SRabin Vincent }
58162579266SRabin Vincent 
582112a80d2SJonas Aaberg int ab8500_suspend(struct ab8500 *ab8500)
583112a80d2SJonas Aaberg {
584112a80d2SJonas Aaberg 	if (atomic_read(&ab8500->transfer_ongoing))
585112a80d2SJonas Aaberg 		return -EINVAL;
586112a80d2SJonas Aaberg 	else
587112a80d2SJonas Aaberg 		return 0;
588112a80d2SJonas Aaberg }
589112a80d2SJonas Aaberg 
590a9e9ce4cSBill Pemberton static struct resource ab8500_gpadc_resources[] = {
59162579266SRabin Vincent 	{
59262579266SRabin Vincent 		.name	= "HW_CONV_END",
59362579266SRabin Vincent 		.start	= AB8500_INT_GP_HW_ADC_CONV_END,
59462579266SRabin Vincent 		.end	= AB8500_INT_GP_HW_ADC_CONV_END,
59562579266SRabin Vincent 		.flags	= IORESOURCE_IRQ,
59662579266SRabin Vincent 	},
59762579266SRabin Vincent 	{
59862579266SRabin Vincent 		.name	= "SW_CONV_END",
59962579266SRabin Vincent 		.start	= AB8500_INT_GP_SW_ADC_CONV_END,
60062579266SRabin Vincent 		.end	= AB8500_INT_GP_SW_ADC_CONV_END,
60162579266SRabin Vincent 		.flags	= IORESOURCE_IRQ,
60262579266SRabin Vincent 	},
60362579266SRabin Vincent };
60462579266SRabin Vincent 
605a9e9ce4cSBill Pemberton static struct resource ab8500_rtc_resources[] = {
60662579266SRabin Vincent 	{
60762579266SRabin Vincent 		.name	= "60S",
60862579266SRabin Vincent 		.start	= AB8500_INT_RTC_60S,
60962579266SRabin Vincent 		.end	= AB8500_INT_RTC_60S,
61062579266SRabin Vincent 		.flags	= IORESOURCE_IRQ,
61162579266SRabin Vincent 	},
61262579266SRabin Vincent 	{
61362579266SRabin Vincent 		.name	= "ALARM",
61462579266SRabin Vincent 		.start	= AB8500_INT_RTC_ALARM,
61562579266SRabin Vincent 		.end	= AB8500_INT_RTC_ALARM,
61662579266SRabin Vincent 		.flags	= IORESOURCE_IRQ,
61762579266SRabin Vincent 	},
61862579266SRabin Vincent };
61962579266SRabin Vincent 
620a9e9ce4cSBill Pemberton static struct resource ab8500_poweronkey_db_resources[] = {
62177686517SSundar R Iyer 	{
62277686517SSundar R Iyer 		.name	= "ONKEY_DBF",
62377686517SSundar R Iyer 		.start	= AB8500_INT_PON_KEY1DB_F,
62477686517SSundar R Iyer 		.end	= AB8500_INT_PON_KEY1DB_F,
62577686517SSundar R Iyer 		.flags	= IORESOURCE_IRQ,
62677686517SSundar R Iyer 	},
62777686517SSundar R Iyer 	{
62877686517SSundar R Iyer 		.name	= "ONKEY_DBR",
62977686517SSundar R Iyer 		.start	= AB8500_INT_PON_KEY1DB_R,
63077686517SSundar R Iyer 		.end	= AB8500_INT_PON_KEY1DB_R,
63177686517SSundar R Iyer 		.flags	= IORESOURCE_IRQ,
63277686517SSundar R Iyer 	},
63377686517SSundar R Iyer };
63477686517SSundar R Iyer 
635a9e9ce4cSBill Pemberton static struct resource ab8500_av_acc_detect_resources[] = {
636e098adedSMattias Wallin 	{
6376af75ecdSLinus Walleij 	       .name = "ACC_DETECT_1DB_F",
6386af75ecdSLinus Walleij 	       .start = AB8500_INT_ACC_DETECT_1DB_F,
6396af75ecdSLinus Walleij 	       .end = AB8500_INT_ACC_DETECT_1DB_F,
640e098adedSMattias Wallin 	       .flags = IORESOURCE_IRQ,
641e098adedSMattias Wallin 	},
642e098adedSMattias Wallin 	{
6436af75ecdSLinus Walleij 	       .name = "ACC_DETECT_1DB_R",
6446af75ecdSLinus Walleij 	       .start = AB8500_INT_ACC_DETECT_1DB_R,
6456af75ecdSLinus Walleij 	       .end = AB8500_INT_ACC_DETECT_1DB_R,
646e098adedSMattias Wallin 	       .flags = IORESOURCE_IRQ,
647e098adedSMattias Wallin 	},
648e098adedSMattias Wallin 	{
6496af75ecdSLinus Walleij 	       .name = "ACC_DETECT_21DB_F",
6506af75ecdSLinus Walleij 	       .start = AB8500_INT_ACC_DETECT_21DB_F,
6516af75ecdSLinus Walleij 	       .end = AB8500_INT_ACC_DETECT_21DB_F,
6526af75ecdSLinus Walleij 	       .flags = IORESOURCE_IRQ,
6536af75ecdSLinus Walleij 	},
6546af75ecdSLinus Walleij 	{
6556af75ecdSLinus Walleij 	       .name = "ACC_DETECT_21DB_R",
6566af75ecdSLinus Walleij 	       .start = AB8500_INT_ACC_DETECT_21DB_R,
6576af75ecdSLinus Walleij 	       .end = AB8500_INT_ACC_DETECT_21DB_R,
6586af75ecdSLinus Walleij 	       .flags = IORESOURCE_IRQ,
6596af75ecdSLinus Walleij 	},
6606af75ecdSLinus Walleij 	{
6616af75ecdSLinus Walleij 	       .name = "ACC_DETECT_22DB_F",
6626af75ecdSLinus Walleij 	       .start = AB8500_INT_ACC_DETECT_22DB_F,
6636af75ecdSLinus Walleij 	       .end = AB8500_INT_ACC_DETECT_22DB_F,
6646af75ecdSLinus Walleij 	       .flags = IORESOURCE_IRQ,
6656af75ecdSLinus Walleij 	},
6666af75ecdSLinus Walleij 	{
6676af75ecdSLinus Walleij 	       .name = "ACC_DETECT_22DB_R",
6686af75ecdSLinus Walleij 	       .start = AB8500_INT_ACC_DETECT_22DB_R,
6696af75ecdSLinus Walleij 	       .end = AB8500_INT_ACC_DETECT_22DB_R,
6706af75ecdSLinus Walleij 	       .flags = IORESOURCE_IRQ,
6716af75ecdSLinus Walleij 	},
6726af75ecdSLinus Walleij };
6736af75ecdSLinus Walleij 
674a9e9ce4cSBill Pemberton static struct resource ab8500_charger_resources[] = {
6756af75ecdSLinus Walleij 	{
676e098adedSMattias Wallin 		.name = "MAIN_CH_UNPLUG_DET",
677e098adedSMattias Wallin 		.start = AB8500_INT_MAIN_CH_UNPLUG_DET,
678e098adedSMattias Wallin 		.end = AB8500_INT_MAIN_CH_UNPLUG_DET,
679e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
680e098adedSMattias Wallin 	},
681e098adedSMattias Wallin 	{
682e098adedSMattias Wallin 		.name = "MAIN_CHARGE_PLUG_DET",
683e098adedSMattias Wallin 		.start = AB8500_INT_MAIN_CH_PLUG_DET,
684e098adedSMattias Wallin 		.end = AB8500_INT_MAIN_CH_PLUG_DET,
685e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
686e098adedSMattias Wallin 	},
687e098adedSMattias Wallin 	{
688e098adedSMattias Wallin 		.name = "VBUS_DET_R",
689e098adedSMattias Wallin 		.start = AB8500_INT_VBUS_DET_R,
690e098adedSMattias Wallin 		.end = AB8500_INT_VBUS_DET_R,
691e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
692e098adedSMattias Wallin 	},
693e098adedSMattias Wallin 	{
6946af75ecdSLinus Walleij 		.name = "VBUS_DET_F",
6956af75ecdSLinus Walleij 		.start = AB8500_INT_VBUS_DET_F,
6966af75ecdSLinus Walleij 		.end = AB8500_INT_VBUS_DET_F,
697e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
698e098adedSMattias Wallin 	},
699e098adedSMattias Wallin 	{
7006af75ecdSLinus Walleij 		.name = "USB_LINK_STATUS",
7016af75ecdSLinus Walleij 		.start = AB8500_INT_USB_LINK_STATUS,
7026af75ecdSLinus Walleij 		.end = AB8500_INT_USB_LINK_STATUS,
7036af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
7046af75ecdSLinus Walleij 	},
7056af75ecdSLinus Walleij 	{
706e098adedSMattias Wallin 		.name = "VBUS_OVV",
707e098adedSMattias Wallin 		.start = AB8500_INT_VBUS_OVV,
708e098adedSMattias Wallin 		.end = AB8500_INT_VBUS_OVV,
709e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
710e098adedSMattias Wallin 	},
711e098adedSMattias Wallin 	{
7126af75ecdSLinus Walleij 		.name = "USB_CH_TH_PROT_R",
7136af75ecdSLinus Walleij 		.start = AB8500_INT_USB_CH_TH_PROT_R,
7146af75ecdSLinus Walleij 		.end = AB8500_INT_USB_CH_TH_PROT_R,
715e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
716e098adedSMattias Wallin 	},
717e098adedSMattias Wallin 	{
7186af75ecdSLinus Walleij 		.name = "USB_CH_TH_PROT_F",
7196af75ecdSLinus Walleij 		.start = AB8500_INT_USB_CH_TH_PROT_F,
7206af75ecdSLinus Walleij 		.end = AB8500_INT_USB_CH_TH_PROT_F,
721e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
722e098adedSMattias Wallin 	},
723e098adedSMattias Wallin 	{
7246af75ecdSLinus Walleij 		.name = "MAIN_EXT_CH_NOT_OK",
7256af75ecdSLinus Walleij 		.start = AB8500_INT_MAIN_EXT_CH_NOT_OK,
7266af75ecdSLinus Walleij 		.end = AB8500_INT_MAIN_EXT_CH_NOT_OK,
7276af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
7286af75ecdSLinus Walleij 	},
7296af75ecdSLinus Walleij 	{
7306af75ecdSLinus Walleij 		.name = "MAIN_CH_TH_PROT_R",
7316af75ecdSLinus Walleij 		.start = AB8500_INT_MAIN_CH_TH_PROT_R,
7326af75ecdSLinus Walleij 		.end = AB8500_INT_MAIN_CH_TH_PROT_R,
7336af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
7346af75ecdSLinus Walleij 	},
7356af75ecdSLinus Walleij 	{
7366af75ecdSLinus Walleij 		.name = "MAIN_CH_TH_PROT_F",
7376af75ecdSLinus Walleij 		.start = AB8500_INT_MAIN_CH_TH_PROT_F,
7386af75ecdSLinus Walleij 		.end = AB8500_INT_MAIN_CH_TH_PROT_F,
7396af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
7406af75ecdSLinus Walleij 	},
7416af75ecdSLinus Walleij 	{
7426af75ecdSLinus Walleij 		.name = "USB_CHARGER_NOT_OKR",
743a982362cSBengt Jonsson 		.start = AB8500_INT_USB_CHARGER_NOT_OKR,
744a982362cSBengt Jonsson 		.end = AB8500_INT_USB_CHARGER_NOT_OKR,
7456af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
7466af75ecdSLinus Walleij 	},
7476af75ecdSLinus Walleij 	{
7486af75ecdSLinus Walleij 		.name = "CH_WD_EXP",
7496af75ecdSLinus Walleij 		.start = AB8500_INT_CH_WD_EXP,
7506af75ecdSLinus Walleij 		.end = AB8500_INT_CH_WD_EXP,
7516af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
7526af75ecdSLinus Walleij 	},
7536af75ecdSLinus Walleij };
7546af75ecdSLinus Walleij 
755a9e9ce4cSBill Pemberton static struct resource ab8500_btemp_resources[] = {
7566af75ecdSLinus Walleij 	{
7576af75ecdSLinus Walleij 		.name = "BAT_CTRL_INDB",
7586af75ecdSLinus Walleij 		.start = AB8500_INT_BAT_CTRL_INDB,
7596af75ecdSLinus Walleij 		.end = AB8500_INT_BAT_CTRL_INDB,
760e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
761e098adedSMattias Wallin 	},
762e098adedSMattias Wallin 	{
763e098adedSMattias Wallin 		.name = "BTEMP_LOW",
764e098adedSMattias Wallin 		.start = AB8500_INT_BTEMP_LOW,
765e098adedSMattias Wallin 		.end = AB8500_INT_BTEMP_LOW,
766e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
767e098adedSMattias Wallin 	},
768e098adedSMattias Wallin 	{
769e098adedSMattias Wallin 		.name = "BTEMP_HIGH",
770e098adedSMattias Wallin 		.start = AB8500_INT_BTEMP_HIGH,
771e098adedSMattias Wallin 		.end = AB8500_INT_BTEMP_HIGH,
772e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
773e098adedSMattias Wallin 	},
774e098adedSMattias Wallin 	{
7756af75ecdSLinus Walleij 		.name = "BTEMP_LOW_MEDIUM",
7766af75ecdSLinus Walleij 		.start = AB8500_INT_BTEMP_LOW_MEDIUM,
7776af75ecdSLinus Walleij 		.end = AB8500_INT_BTEMP_LOW_MEDIUM,
778e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
779e098adedSMattias Wallin 	},
780e098adedSMattias Wallin 	{
7816af75ecdSLinus Walleij 		.name = "BTEMP_MEDIUM_HIGH",
7826af75ecdSLinus Walleij 		.start = AB8500_INT_BTEMP_MEDIUM_HIGH,
7836af75ecdSLinus Walleij 		.end = AB8500_INT_BTEMP_MEDIUM_HIGH,
784e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
785e098adedSMattias Wallin 	},
786e098adedSMattias Wallin };
787e098adedSMattias Wallin 
788a9e9ce4cSBill Pemberton static struct resource ab8500_fg_resources[] = {
7896af75ecdSLinus Walleij 	{
7906af75ecdSLinus Walleij 		.name = "NCONV_ACCU",
7916af75ecdSLinus Walleij 		.start = AB8500_INT_CCN_CONV_ACC,
7926af75ecdSLinus Walleij 		.end = AB8500_INT_CCN_CONV_ACC,
7936af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
7946af75ecdSLinus Walleij 	},
7956af75ecdSLinus Walleij 	{
7966af75ecdSLinus Walleij 		.name = "BATT_OVV",
7976af75ecdSLinus Walleij 		.start = AB8500_INT_BATT_OVV,
7986af75ecdSLinus Walleij 		.end = AB8500_INT_BATT_OVV,
7996af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
8006af75ecdSLinus Walleij 	},
8016af75ecdSLinus Walleij 	{
8026af75ecdSLinus Walleij 		.name = "LOW_BAT_F",
8036af75ecdSLinus Walleij 		.start = AB8500_INT_LOW_BAT_F,
8046af75ecdSLinus Walleij 		.end = AB8500_INT_LOW_BAT_F,
8056af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
8066af75ecdSLinus Walleij 	},
8076af75ecdSLinus Walleij 	{
8086af75ecdSLinus Walleij 		.name = "LOW_BAT_R",
8096af75ecdSLinus Walleij 		.start = AB8500_INT_LOW_BAT_R,
8106af75ecdSLinus Walleij 		.end = AB8500_INT_LOW_BAT_R,
8116af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
8126af75ecdSLinus Walleij 	},
8136af75ecdSLinus Walleij 	{
8146af75ecdSLinus Walleij 		.name = "CC_INT_CALIB",
8156af75ecdSLinus Walleij 		.start = AB8500_INT_CC_INT_CALIB,
8166af75ecdSLinus Walleij 		.end = AB8500_INT_CC_INT_CALIB,
8176af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
8186af75ecdSLinus Walleij 	},
819a982362cSBengt Jonsson 	{
820a982362cSBengt Jonsson 		.name = "CCEOC",
821a982362cSBengt Jonsson 		.start = AB8500_INT_CCEOC,
822a982362cSBengt Jonsson 		.end = AB8500_INT_CCEOC,
823a982362cSBengt Jonsson 		.flags = IORESOURCE_IRQ,
824a982362cSBengt Jonsson 	},
8256af75ecdSLinus Walleij };
8266af75ecdSLinus Walleij 
827a9e9ce4cSBill Pemberton static struct resource ab8500_chargalg_resources[] = {};
8286af75ecdSLinus Walleij 
829df720647SAxel Lin #ifdef CONFIG_DEBUG_FS
830a9e9ce4cSBill Pemberton static struct resource ab8500_debug_resources[] = {
831e098adedSMattias Wallin 	{
832e098adedSMattias Wallin 		.name	= "IRQ_FIRST",
833e098adedSMattias Wallin 		.start	= AB8500_INT_MAIN_EXT_CH_NOT_OK,
834e098adedSMattias Wallin 		.end	= AB8500_INT_MAIN_EXT_CH_NOT_OK,
835e098adedSMattias Wallin 		.flags	= IORESOURCE_IRQ,
836e098adedSMattias Wallin 	},
837e098adedSMattias Wallin 	{
838e098adedSMattias Wallin 		.name	= "IRQ_LAST",
839a982362cSBengt Jonsson 		.start	= AB8500_INT_XTAL32K_KO,
840a982362cSBengt Jonsson 		.end	= AB8500_INT_XTAL32K_KO,
841e098adedSMattias Wallin 		.flags	= IORESOURCE_IRQ,
842e098adedSMattias Wallin 	},
843e098adedSMattias Wallin };
844df720647SAxel Lin #endif
845e098adedSMattias Wallin 
846a9e9ce4cSBill Pemberton static struct resource ab8500_usb_resources[] = {
847e098adedSMattias Wallin 	{
848e098adedSMattias Wallin 		.name = "ID_WAKEUP_R",
849e098adedSMattias Wallin 		.start = AB8500_INT_ID_WAKEUP_R,
850e098adedSMattias Wallin 		.end = AB8500_INT_ID_WAKEUP_R,
851e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
852e098adedSMattias Wallin 	},
853e098adedSMattias Wallin 	{
854e098adedSMattias Wallin 		.name = "ID_WAKEUP_F",
855e098adedSMattias Wallin 		.start = AB8500_INT_ID_WAKEUP_F,
856e098adedSMattias Wallin 		.end = AB8500_INT_ID_WAKEUP_F,
857e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
858e098adedSMattias Wallin 	},
859e098adedSMattias Wallin 	{
860e098adedSMattias Wallin 		.name = "VBUS_DET_F",
861e098adedSMattias Wallin 		.start = AB8500_INT_VBUS_DET_F,
862e098adedSMattias Wallin 		.end = AB8500_INT_VBUS_DET_F,
863e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
864e098adedSMattias Wallin 	},
865e098adedSMattias Wallin 	{
866e098adedSMattias Wallin 		.name = "VBUS_DET_R",
867e098adedSMattias Wallin 		.start = AB8500_INT_VBUS_DET_R,
868e098adedSMattias Wallin 		.end = AB8500_INT_VBUS_DET_R,
869e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
870e098adedSMattias Wallin 	},
87192d50a41SMattias Wallin 	{
87292d50a41SMattias Wallin 		.name = "USB_LINK_STATUS",
87392d50a41SMattias Wallin 		.start = AB8500_INT_USB_LINK_STATUS,
87492d50a41SMattias Wallin 		.end = AB8500_INT_USB_LINK_STATUS,
87592d50a41SMattias Wallin 		.flags = IORESOURCE_IRQ,
87692d50a41SMattias Wallin 	},
8776af75ecdSLinus Walleij 	{
8786af75ecdSLinus Walleij 		.name = "USB_ADP_PROBE_PLUG",
8796af75ecdSLinus Walleij 		.start = AB8500_INT_ADP_PROBE_PLUG,
8806af75ecdSLinus Walleij 		.end = AB8500_INT_ADP_PROBE_PLUG,
8816af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
8826af75ecdSLinus Walleij 	},
8836af75ecdSLinus Walleij 	{
8846af75ecdSLinus Walleij 		.name = "USB_ADP_PROBE_UNPLUG",
8856af75ecdSLinus Walleij 		.start = AB8500_INT_ADP_PROBE_UNPLUG,
8866af75ecdSLinus Walleij 		.end = AB8500_INT_ADP_PROBE_UNPLUG,
8876af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
8886af75ecdSLinus Walleij 	},
889e098adedSMattias Wallin };
890e098adedSMattias Wallin 
891a9e9ce4cSBill Pemberton static struct resource ab8505_iddet_resources[] = {
89244f72e53SVirupax Sadashivpetimath 	{
89344f72e53SVirupax Sadashivpetimath 		.name  = "KeyDeglitch",
89444f72e53SVirupax Sadashivpetimath 		.start = AB8505_INT_KEYDEGLITCH,
89544f72e53SVirupax Sadashivpetimath 		.end   = AB8505_INT_KEYDEGLITCH,
89644f72e53SVirupax Sadashivpetimath 		.flags = IORESOURCE_IRQ,
89744f72e53SVirupax Sadashivpetimath 	},
89844f72e53SVirupax Sadashivpetimath 	{
89944f72e53SVirupax Sadashivpetimath 		.name  = "KP",
90044f72e53SVirupax Sadashivpetimath 		.start = AB8505_INT_KP,
90144f72e53SVirupax Sadashivpetimath 		.end   = AB8505_INT_KP,
90244f72e53SVirupax Sadashivpetimath 		.flags = IORESOURCE_IRQ,
90344f72e53SVirupax Sadashivpetimath 	},
90444f72e53SVirupax Sadashivpetimath 	{
90544f72e53SVirupax Sadashivpetimath 		.name  = "IKP",
90644f72e53SVirupax Sadashivpetimath 		.start = AB8505_INT_IKP,
90744f72e53SVirupax Sadashivpetimath 		.end   = AB8505_INT_IKP,
90844f72e53SVirupax Sadashivpetimath 		.flags = IORESOURCE_IRQ,
90944f72e53SVirupax Sadashivpetimath 	},
91044f72e53SVirupax Sadashivpetimath 	{
91144f72e53SVirupax Sadashivpetimath 		.name  = "IKR",
91244f72e53SVirupax Sadashivpetimath 		.start = AB8505_INT_IKR,
91344f72e53SVirupax Sadashivpetimath 		.end   = AB8505_INT_IKR,
91444f72e53SVirupax Sadashivpetimath 		.flags = IORESOURCE_IRQ,
91544f72e53SVirupax Sadashivpetimath 	},
91644f72e53SVirupax Sadashivpetimath 	{
91744f72e53SVirupax Sadashivpetimath 		.name  = "KeyStuck",
91844f72e53SVirupax Sadashivpetimath 		.start = AB8505_INT_KEYSTUCK,
91944f72e53SVirupax Sadashivpetimath 		.end   = AB8505_INT_KEYSTUCK,
92044f72e53SVirupax Sadashivpetimath 		.flags = IORESOURCE_IRQ,
92144f72e53SVirupax Sadashivpetimath 	},
92244f72e53SVirupax Sadashivpetimath };
92344f72e53SVirupax Sadashivpetimath 
924a9e9ce4cSBill Pemberton static struct resource ab8500_temp_resources[] = {
925e098adedSMattias Wallin 	{
926e098adedSMattias Wallin 		.name  = "AB8500_TEMP_WARM",
927e098adedSMattias Wallin 		.start = AB8500_INT_TEMP_WARM,
928e098adedSMattias Wallin 		.end   = AB8500_INT_TEMP_WARM,
929e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
930e098adedSMattias Wallin 	},
931e098adedSMattias Wallin };
932e098adedSMattias Wallin 
933a9e9ce4cSBill Pemberton static struct mfd_cell abx500_common_devs[] = {
9345814fc35SMattias Wallin #ifdef CONFIG_DEBUG_FS
9355814fc35SMattias Wallin 	{
9365814fc35SMattias Wallin 		.name = "ab8500-debug",
937bad76991SLee Jones 		.of_compatible = "stericsson,ab8500-debug",
938e098adedSMattias Wallin 		.num_resources = ARRAY_SIZE(ab8500_debug_resources),
939e098adedSMattias Wallin 		.resources = ab8500_debug_resources,
9405814fc35SMattias Wallin 	},
9415814fc35SMattias Wallin #endif
94262579266SRabin Vincent 	{
943e098adedSMattias Wallin 		.name = "ab8500-sysctrl",
944bad76991SLee Jones 		.of_compatible = "stericsson,ab8500-sysctrl",
945e098adedSMattias Wallin 	},
946e098adedSMattias Wallin 	{
947e098adedSMattias Wallin 		.name = "ab8500-regulator",
948bad76991SLee Jones 		.of_compatible = "stericsson,ab8500-regulator",
949e098adedSMattias Wallin 	},
950e098adedSMattias Wallin 	{
951916a871cSUlf Hansson 		.name = "abx500-clk",
952916a871cSUlf Hansson 		.of_compatible = "stericsson,abx500-clk",
953916a871cSUlf Hansson 	},
954916a871cSUlf Hansson 	{
95562579266SRabin Vincent 		.name = "ab8500-gpadc",
956bad76991SLee Jones 		.of_compatible = "stericsson,ab8500-gpadc",
95762579266SRabin Vincent 		.num_resources = ARRAY_SIZE(ab8500_gpadc_resources),
95862579266SRabin Vincent 		.resources = ab8500_gpadc_resources,
95962579266SRabin Vincent 	},
96062579266SRabin Vincent 	{
96162579266SRabin Vincent 		.name = "ab8500-rtc",
962bad76991SLee Jones 		.of_compatible = "stericsson,ab8500-rtc",
96362579266SRabin Vincent 		.num_resources = ARRAY_SIZE(ab8500_rtc_resources),
96462579266SRabin Vincent 		.resources = ab8500_rtc_resources,
96562579266SRabin Vincent 	},
966f0f05b1cSArun Murthy 	{
9676af75ecdSLinus Walleij 		.name = "ab8500-acc-det",
968bad76991SLee Jones 		.of_compatible = "stericsson,ab8500-acc-det",
9696af75ecdSLinus Walleij 		.num_resources = ARRAY_SIZE(ab8500_av_acc_detect_resources),
9706af75ecdSLinus Walleij 		.resources = ab8500_av_acc_detect_resources,
9716af75ecdSLinus Walleij 	},
9726af75ecdSLinus Walleij 	{
973e098adedSMattias Wallin 		.name = "ab8500-poweron-key",
974bad76991SLee Jones 		.of_compatible = "stericsson,ab8500-poweron-key",
975e098adedSMattias Wallin 		.num_resources = ARRAY_SIZE(ab8500_poweronkey_db_resources),
976e098adedSMattias Wallin 		.resources = ab8500_poweronkey_db_resources,
977e098adedSMattias Wallin 	},
978e098adedSMattias Wallin 	{
979f0f05b1cSArun Murthy 		.name = "ab8500-pwm",
980bad76991SLee Jones 		.of_compatible = "stericsson,ab8500-pwm",
981f0f05b1cSArun Murthy 		.id = 1,
982f0f05b1cSArun Murthy 	},
983f0f05b1cSArun Murthy 	{
984f0f05b1cSArun Murthy 		.name = "ab8500-pwm",
985bad76991SLee Jones 		.of_compatible = "stericsson,ab8500-pwm",
986f0f05b1cSArun Murthy 		.id = 2,
987f0f05b1cSArun Murthy 	},
988f0f05b1cSArun Murthy 	{
989f0f05b1cSArun Murthy 		.name = "ab8500-pwm",
990bad76991SLee Jones 		.of_compatible = "stericsson,ab8500-pwm",
991f0f05b1cSArun Murthy 		.id = 3,
992f0f05b1cSArun Murthy 	},
993bad76991SLee Jones 	{
994bad76991SLee Jones 		.name = "ab8500-leds",
995bad76991SLee Jones 		.of_compatible = "stericsson,ab8500-leds",
996bad76991SLee Jones 	},
99777686517SSundar R Iyer 	{
998e098adedSMattias Wallin 		.name = "ab8500-denc",
999bad76991SLee Jones 		.of_compatible = "stericsson,ab8500-denc",
1000e098adedSMattias Wallin 	},
1001e098adedSMattias Wallin 	{
1002e098adedSMattias Wallin 		.name = "ab8500-temp",
1003bad76991SLee Jones 		.of_compatible = "stericsson,ab8500-temp",
1004e098adedSMattias Wallin 		.num_resources = ARRAY_SIZE(ab8500_temp_resources),
1005e098adedSMattias Wallin 		.resources = ab8500_temp_resources,
100677686517SSundar R Iyer 	},
100762579266SRabin Vincent };
100862579266SRabin Vincent 
1009a9e9ce4cSBill Pemberton static struct mfd_cell ab8500_bm_devs[] = {
10106ef9418cSRickard Andersson 	{
10116ef9418cSRickard Andersson 		.name = "ab8500-charger",
10124aef72dbSRajanikanth H.V 		.of_compatible = "stericsson,ab8500-charger",
10136ef9418cSRickard Andersson 		.num_resources = ARRAY_SIZE(ab8500_charger_resources),
10146ef9418cSRickard Andersson 		.resources = ab8500_charger_resources,
10154aef72dbSRajanikanth H.V #ifndef CONFIG_OF
10164aef72dbSRajanikanth H.V 		.platform_data = &ab8500_bm_data,
10174aef72dbSRajanikanth H.V 		.pdata_size = sizeof(ab8500_bm_data),
10184aef72dbSRajanikanth H.V #endif
10196ef9418cSRickard Andersson 	},
10206ef9418cSRickard Andersson 	{
10216ef9418cSRickard Andersson 		.name = "ab8500-btemp",
1022bd9e8ab2SRajanikanth H.V 		.of_compatible = "stericsson,ab8500-btemp",
10236ef9418cSRickard Andersson 		.num_resources = ARRAY_SIZE(ab8500_btemp_resources),
10246ef9418cSRickard Andersson 		.resources = ab8500_btemp_resources,
1025bd9e8ab2SRajanikanth H.V #ifndef CONFIG_OF
1026bd9e8ab2SRajanikanth H.V 		.platform_data = &ab8500_bm_data,
1027bd9e8ab2SRajanikanth H.V 		.pdata_size = sizeof(ab8500_bm_data),
1028bd9e8ab2SRajanikanth H.V #endif
10296ef9418cSRickard Andersson 	},
10306ef9418cSRickard Andersson 	{
10316ef9418cSRickard Andersson 		.name = "ab8500-fg",
1032e0f1abebSRajanikanth H.V 		.of_compatible = "stericsson,ab8500-fg",
10336ef9418cSRickard Andersson 		.num_resources = ARRAY_SIZE(ab8500_fg_resources),
10346ef9418cSRickard Andersson 		.resources = ab8500_fg_resources,
1035e0f1abebSRajanikanth H.V #ifndef CONFIG_OF
1036e0f1abebSRajanikanth H.V 		.platform_data = &ab8500_bm_data,
1037e0f1abebSRajanikanth H.V 		.pdata_size = sizeof(ab8500_bm_data),
1038e0f1abebSRajanikanth H.V #endif
10396ef9418cSRickard Andersson 	},
10406ef9418cSRickard Andersson 	{
10416ef9418cSRickard Andersson 		.name = "ab8500-chargalg",
1042a12810abSRajanikanth H.V 		.of_compatible = "stericsson,ab8500-chargalg",
10436ef9418cSRickard Andersson 		.num_resources = ARRAY_SIZE(ab8500_chargalg_resources),
10446ef9418cSRickard Andersson 		.resources = ab8500_chargalg_resources,
1045a12810abSRajanikanth H.V #ifndef CONFIG_OF
1046a12810abSRajanikanth H.V 		.platform_data = &ab8500_bm_data,
1047a12810abSRajanikanth H.V 		.pdata_size = sizeof(ab8500_bm_data),
1048a12810abSRajanikanth H.V #endif
10496ef9418cSRickard Andersson 	},
10506ef9418cSRickard Andersson };
10516ef9418cSRickard Andersson 
1052a9e9ce4cSBill Pemberton static struct mfd_cell ab8500_devs[] = {
1053d6255529SLinus Walleij 	{
1054d6255529SLinus Walleij 		.name = "ab8500-gpio",
1055bad76991SLee Jones 		.of_compatible = "stericsson,ab8500-gpio",
1056d6255529SLinus Walleij 	},
1057d6255529SLinus Walleij 	{
1058d6255529SLinus Walleij 		.name = "ab8500-usb",
1059bad76991SLee Jones 		.of_compatible = "stericsson,ab8500-usb",
1060d6255529SLinus Walleij 		.num_resources = ARRAY_SIZE(ab8500_usb_resources),
1061d6255529SLinus Walleij 		.resources = ab8500_usb_resources,
1062d6255529SLinus Walleij 	},
106344f72e53SVirupax Sadashivpetimath 	{
106444f72e53SVirupax Sadashivpetimath 		.name = "ab8500-codec",
106581a21cddSLee Jones 		.of_compatible = "stericsson,ab8500-codec",
106644f72e53SVirupax Sadashivpetimath 	},
1067d6255529SLinus Walleij };
1068d6255529SLinus Walleij 
1069a9e9ce4cSBill Pemberton static struct mfd_cell ab9540_devs[] = {
1070d6255529SLinus Walleij 	{
1071d6255529SLinus Walleij 		.name = "ab8500-gpio",
1072d6255529SLinus Walleij 	},
1073d6255529SLinus Walleij 	{
1074d6255529SLinus Walleij 		.name = "ab9540-usb",
1075d6255529SLinus Walleij 		.num_resources = ARRAY_SIZE(ab8500_usb_resources),
1076d6255529SLinus Walleij 		.resources = ab8500_usb_resources,
1077d6255529SLinus Walleij 	},
107844f72e53SVirupax Sadashivpetimath 	{
107944f72e53SVirupax Sadashivpetimath 		.name = "ab9540-codec",
108044f72e53SVirupax Sadashivpetimath 	},
108144f72e53SVirupax Sadashivpetimath };
108244f72e53SVirupax Sadashivpetimath 
108344f72e53SVirupax Sadashivpetimath /* Device list common to ab9540 and ab8505 */
1084a9e9ce4cSBill Pemberton static struct mfd_cell ab9540_ab8505_devs[] = {
108544f72e53SVirupax Sadashivpetimath 	{
108644f72e53SVirupax Sadashivpetimath 		.name = "ab-iddet",
108744f72e53SVirupax Sadashivpetimath 		.num_resources = ARRAY_SIZE(ab8505_iddet_resources),
108844f72e53SVirupax Sadashivpetimath 		.resources = ab8505_iddet_resources,
108944f72e53SVirupax Sadashivpetimath 	},
1090d6255529SLinus Walleij };
1091d6255529SLinus Walleij 
1092cca69b67SMattias Wallin static ssize_t show_chip_id(struct device *dev,
1093cca69b67SMattias Wallin 				struct device_attribute *attr, char *buf)
1094cca69b67SMattias Wallin {
1095cca69b67SMattias Wallin 	struct ab8500 *ab8500;
1096cca69b67SMattias Wallin 
1097cca69b67SMattias Wallin 	ab8500 = dev_get_drvdata(dev);
1098cca69b67SMattias Wallin 	return sprintf(buf, "%#x\n", ab8500 ? ab8500->chip_id : -EINVAL);
1099cca69b67SMattias Wallin }
1100cca69b67SMattias Wallin 
1101e5c238c3SMattias Wallin /*
1102e5c238c3SMattias Wallin  * ab8500 has switched off due to (SWITCH_OFF_STATUS):
1103e5c238c3SMattias Wallin  * 0x01 Swoff bit programming
1104e5c238c3SMattias Wallin  * 0x02 Thermal protection activation
1105e5c238c3SMattias Wallin  * 0x04 Vbat lower then BattOk falling threshold
1106e5c238c3SMattias Wallin  * 0x08 Watchdog expired
1107e5c238c3SMattias Wallin  * 0x10 Non presence of 32kHz clock
1108e5c238c3SMattias Wallin  * 0x20 Battery level lower than power on reset threshold
1109e5c238c3SMattias Wallin  * 0x40 Power on key 1 pressed longer than 10 seconds
1110e5c238c3SMattias Wallin  * 0x80 DB8500 thermal shutdown
1111e5c238c3SMattias Wallin  */
1112e5c238c3SMattias Wallin static ssize_t show_switch_off_status(struct device *dev,
1113e5c238c3SMattias Wallin 				struct device_attribute *attr, char *buf)
1114e5c238c3SMattias Wallin {
1115e5c238c3SMattias Wallin 	int ret;
1116e5c238c3SMattias Wallin 	u8 value;
1117e5c238c3SMattias Wallin 	struct ab8500 *ab8500;
1118e5c238c3SMattias Wallin 
1119e5c238c3SMattias Wallin 	ab8500 = dev_get_drvdata(dev);
1120e5c238c3SMattias Wallin 	ret = get_register_interruptible(ab8500, AB8500_RTC,
1121e5c238c3SMattias Wallin 		AB8500_SWITCH_OFF_STATUS, &value);
1122e5c238c3SMattias Wallin 	if (ret < 0)
1123e5c238c3SMattias Wallin 		return ret;
1124e5c238c3SMattias Wallin 	return sprintf(buf, "%#x\n", value);
1125e5c238c3SMattias Wallin }
1126e5c238c3SMattias Wallin 
1127b4a31037SAndrew Lynn /*
1128b4a31037SAndrew Lynn  * ab8500 has turned on due to (TURN_ON_STATUS):
1129b4a31037SAndrew Lynn  * 0x01 PORnVbat
1130b4a31037SAndrew Lynn  * 0x02 PonKey1dbF
1131b4a31037SAndrew Lynn  * 0x04 PonKey2dbF
1132b4a31037SAndrew Lynn  * 0x08 RTCAlarm
1133b4a31037SAndrew Lynn  * 0x10 MainChDet
1134b4a31037SAndrew Lynn  * 0x20 VbusDet
1135b4a31037SAndrew Lynn  * 0x40 UsbIDDetect
1136b4a31037SAndrew Lynn  * 0x80 Reserved
1137b4a31037SAndrew Lynn  */
1138b4a31037SAndrew Lynn static ssize_t show_turn_on_status(struct device *dev,
1139b4a31037SAndrew Lynn 				struct device_attribute *attr, char *buf)
1140b4a31037SAndrew Lynn {
1141b4a31037SAndrew Lynn 	int ret;
1142b4a31037SAndrew Lynn 	u8 value;
1143b4a31037SAndrew Lynn 	struct ab8500 *ab8500;
1144b4a31037SAndrew Lynn 
1145b4a31037SAndrew Lynn 	ab8500 = dev_get_drvdata(dev);
1146b4a31037SAndrew Lynn 	ret = get_register_interruptible(ab8500, AB8500_SYS_CTRL1_BLOCK,
1147b4a31037SAndrew Lynn 		AB8500_TURN_ON_STATUS, &value);
1148b4a31037SAndrew Lynn 	if (ret < 0)
1149b4a31037SAndrew Lynn 		return ret;
1150b4a31037SAndrew Lynn 	return sprintf(buf, "%#x\n", value);
1151b4a31037SAndrew Lynn }
1152b4a31037SAndrew Lynn 
1153d6255529SLinus Walleij static ssize_t show_ab9540_dbbrstn(struct device *dev,
1154d6255529SLinus Walleij 				struct device_attribute *attr, char *buf)
1155d6255529SLinus Walleij {
1156d6255529SLinus Walleij 	struct ab8500 *ab8500;
1157d6255529SLinus Walleij 	int ret;
1158d6255529SLinus Walleij 	u8 value;
1159d6255529SLinus Walleij 
1160d6255529SLinus Walleij 	ab8500 = dev_get_drvdata(dev);
1161d6255529SLinus Walleij 
1162d6255529SLinus Walleij 	ret = get_register_interruptible(ab8500, AB8500_REGU_CTRL2,
1163d6255529SLinus Walleij 		AB9540_MODEM_CTRL2_REG, &value);
1164d6255529SLinus Walleij 	if (ret < 0)
1165d6255529SLinus Walleij 		return ret;
1166d6255529SLinus Walleij 
1167d6255529SLinus Walleij 	return sprintf(buf, "%d\n",
1168d6255529SLinus Walleij 			(value & AB9540_MODEM_CTRL2_SWDBBRSTN_BIT) ? 1 : 0);
1169d6255529SLinus Walleij }
1170d6255529SLinus Walleij 
1171d6255529SLinus Walleij static ssize_t store_ab9540_dbbrstn(struct device *dev,
1172d6255529SLinus Walleij 	struct device_attribute *attr, const char *buf, size_t count)
1173d6255529SLinus Walleij {
1174d6255529SLinus Walleij 	struct ab8500 *ab8500;
1175d6255529SLinus Walleij 	int ret = count;
1176d6255529SLinus Walleij 	int err;
1177d6255529SLinus Walleij 	u8 bitvalues;
1178d6255529SLinus Walleij 
1179d6255529SLinus Walleij 	ab8500 = dev_get_drvdata(dev);
1180d6255529SLinus Walleij 
1181d6255529SLinus Walleij 	if (count > 0) {
1182d6255529SLinus Walleij 		switch (buf[0]) {
1183d6255529SLinus Walleij 		case '0':
1184d6255529SLinus Walleij 			bitvalues = 0;
1185d6255529SLinus Walleij 			break;
1186d6255529SLinus Walleij 		case '1':
1187d6255529SLinus Walleij 			bitvalues = AB9540_MODEM_CTRL2_SWDBBRSTN_BIT;
1188d6255529SLinus Walleij 			break;
1189d6255529SLinus Walleij 		default:
1190d6255529SLinus Walleij 			goto exit;
1191d6255529SLinus Walleij 		}
1192d6255529SLinus Walleij 
1193d6255529SLinus Walleij 		err = mask_and_set_register_interruptible(ab8500,
1194d6255529SLinus Walleij 			AB8500_REGU_CTRL2, AB9540_MODEM_CTRL2_REG,
1195d6255529SLinus Walleij 			AB9540_MODEM_CTRL2_SWDBBRSTN_BIT, bitvalues);
1196d6255529SLinus Walleij 		if (err)
1197d6255529SLinus Walleij 			dev_info(ab8500->dev,
1198d6255529SLinus Walleij 				"Failed to set DBBRSTN %c, err %#x\n",
1199d6255529SLinus Walleij 				buf[0], err);
1200d6255529SLinus Walleij 	}
1201d6255529SLinus Walleij 
1202d6255529SLinus Walleij exit:
1203d6255529SLinus Walleij 	return ret;
1204d6255529SLinus Walleij }
1205d6255529SLinus Walleij 
1206cca69b67SMattias Wallin static DEVICE_ATTR(chip_id, S_IRUGO, show_chip_id, NULL);
1207e5c238c3SMattias Wallin static DEVICE_ATTR(switch_off_status, S_IRUGO, show_switch_off_status, NULL);
1208b4a31037SAndrew Lynn static DEVICE_ATTR(turn_on_status, S_IRUGO, show_turn_on_status, NULL);
1209d6255529SLinus Walleij static DEVICE_ATTR(dbbrstn, S_IRUGO | S_IWUSR,
1210d6255529SLinus Walleij 			show_ab9540_dbbrstn, store_ab9540_dbbrstn);
1211cca69b67SMattias Wallin 
1212cca69b67SMattias Wallin static struct attribute *ab8500_sysfs_entries[] = {
1213cca69b67SMattias Wallin 	&dev_attr_chip_id.attr,
1214e5c238c3SMattias Wallin 	&dev_attr_switch_off_status.attr,
1215b4a31037SAndrew Lynn 	&dev_attr_turn_on_status.attr,
1216cca69b67SMattias Wallin 	NULL,
1217cca69b67SMattias Wallin };
1218cca69b67SMattias Wallin 
1219d6255529SLinus Walleij static struct attribute *ab9540_sysfs_entries[] = {
1220d6255529SLinus Walleij 	&dev_attr_chip_id.attr,
1221d6255529SLinus Walleij 	&dev_attr_switch_off_status.attr,
1222d6255529SLinus Walleij 	&dev_attr_turn_on_status.attr,
1223d6255529SLinus Walleij 	&dev_attr_dbbrstn.attr,
1224d6255529SLinus Walleij 	NULL,
1225d6255529SLinus Walleij };
1226d6255529SLinus Walleij 
1227cca69b67SMattias Wallin static struct attribute_group ab8500_attr_group = {
1228cca69b67SMattias Wallin 	.attrs	= ab8500_sysfs_entries,
1229cca69b67SMattias Wallin };
1230cca69b67SMattias Wallin 
1231d6255529SLinus Walleij static struct attribute_group ab9540_attr_group = {
1232d6255529SLinus Walleij 	.attrs	= ab9540_sysfs_entries,
1233d6255529SLinus Walleij };
1234d6255529SLinus Walleij 
1235f791be49SBill Pemberton static int ab8500_probe(struct platform_device *pdev)
123662579266SRabin Vincent {
1237b04c530cSJonas Aaberg 	static char *switch_off_status[] = {
1238b04c530cSJonas Aaberg 		"Swoff bit programming",
1239b04c530cSJonas Aaberg 		"Thermal protection activation",
1240b04c530cSJonas Aaberg 		"Vbat lower then BattOk falling threshold",
1241b04c530cSJonas Aaberg 		"Watchdog expired",
1242b04c530cSJonas Aaberg 		"Non presence of 32kHz clock",
1243b04c530cSJonas Aaberg 		"Battery level lower than power on reset threshold",
1244b04c530cSJonas Aaberg 		"Power on key 1 pressed longer than 10 seconds",
1245b04c530cSJonas Aaberg 		"DB8500 thermal shutdown"};
1246d28f1db8SLee Jones 	struct ab8500_platform_data *plat = dev_get_platdata(&pdev->dev);
1247d28f1db8SLee Jones 	const struct platform_device_id *platid = platform_get_device_id(pdev);
12486bc4a568SLee Jones 	enum ab8500_version version = AB8500_VERSION_UNDEFINED;
12496bc4a568SLee Jones 	struct device_node *np = pdev->dev.of_node;
1250d28f1db8SLee Jones 	struct ab8500 *ab8500;
1251d28f1db8SLee Jones 	struct resource *resource;
125262579266SRabin Vincent 	int ret;
125362579266SRabin Vincent 	int i;
125447c16975SMattias Wallin 	u8 value;
125562579266SRabin Vincent 
12568c4203cbSLee Jones 	ab8500 = devm_kzalloc(&pdev->dev, sizeof *ab8500, GFP_KERNEL);
1257d28f1db8SLee Jones 	if (!ab8500)
1258d28f1db8SLee Jones 		return -ENOMEM;
1259d28f1db8SLee Jones 
126062579266SRabin Vincent 	if (plat)
126162579266SRabin Vincent 		ab8500->irq_base = plat->irq_base;
126262579266SRabin Vincent 
1263d28f1db8SLee Jones 	ab8500->dev = &pdev->dev;
1264d28f1db8SLee Jones 
1265d28f1db8SLee Jones 	resource = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
12668c4203cbSLee Jones 	if (!resource)
12678c4203cbSLee Jones 		return -ENODEV;
1268d28f1db8SLee Jones 
1269d28f1db8SLee Jones 	ab8500->irq = resource->start;
1270d28f1db8SLee Jones 
1271822672a7SLee Jones 	ab8500->read = ab8500_prcmu_read;
1272822672a7SLee Jones 	ab8500->write = ab8500_prcmu_write;
1273822672a7SLee Jones 	ab8500->write_masked = ab8500_prcmu_write_masked;
1274d28f1db8SLee Jones 
127562579266SRabin Vincent 	mutex_init(&ab8500->lock);
127662579266SRabin Vincent 	mutex_init(&ab8500->irq_lock);
1277112a80d2SJonas Aaberg 	atomic_set(&ab8500->transfer_ongoing, 0);
127862579266SRabin Vincent 
1279d28f1db8SLee Jones 	platform_set_drvdata(pdev, ab8500);
1280d28f1db8SLee Jones 
12816bc4a568SLee Jones 	if (platid)
12826bc4a568SLee Jones 		version = platid->driver_data;
12836bc4a568SLee Jones 
12840f620837SLinus Walleij 	if (version != AB8500_VERSION_UNDEFINED)
12850f620837SLinus Walleij 		ab8500->version = version;
12860f620837SLinus Walleij 	else {
12870f620837SLinus Walleij 		ret = get_register_interruptible(ab8500, AB8500_MISC,
12880f620837SLinus Walleij 			AB8500_IC_NAME_REG, &value);
12890f620837SLinus Walleij 		if (ret < 0)
12908c4203cbSLee Jones 			return ret;
12910f620837SLinus Walleij 
12920f620837SLinus Walleij 		ab8500->version = value;
12930f620837SLinus Walleij 	}
12940f620837SLinus Walleij 
129547c16975SMattias Wallin 	ret = get_register_interruptible(ab8500, AB8500_MISC,
129647c16975SMattias Wallin 		AB8500_REV_REG, &value);
129762579266SRabin Vincent 	if (ret < 0)
12988c4203cbSLee Jones 		return ret;
129962579266SRabin Vincent 
130047c16975SMattias Wallin 	ab8500->chip_id = value;
130162579266SRabin Vincent 
13020f620837SLinus Walleij 	dev_info(ab8500->dev, "detected chip, %s rev. %1x.%1x\n",
13030f620837SLinus Walleij 			ab8500_version_str[ab8500->version],
13040f620837SLinus Walleij 			ab8500->chip_id >> 4,
13050f620837SLinus Walleij 			ab8500->chip_id & 0x0F);
13060f620837SLinus Walleij 
1307d6255529SLinus Walleij 	/* Configure AB8500 or AB9540 IRQ */
1308a982362cSBengt Jonsson 	if (is_ab9540(ab8500) || is_ab8505(ab8500)) {
1309d6255529SLinus Walleij 		ab8500->mask_size = AB9540_NUM_IRQ_REGS;
1310d6255529SLinus Walleij 		ab8500->irq_reg_offset = ab9540_irq_regoffset;
1311d6255529SLinus Walleij 	} else {
13122ced445eSLinus Walleij 		ab8500->mask_size = AB8500_NUM_IRQ_REGS;
13132ced445eSLinus Walleij 		ab8500->irq_reg_offset = ab8500_irq_regoffset;
1314d6255529SLinus Walleij 	}
13158c4203cbSLee Jones 	ab8500->mask = devm_kzalloc(&pdev->dev, ab8500->mask_size, GFP_KERNEL);
13162ced445eSLinus Walleij 	if (!ab8500->mask)
13172ced445eSLinus Walleij 		return -ENOMEM;
13188c4203cbSLee Jones 	ab8500->oldmask = devm_kzalloc(&pdev->dev, ab8500->mask_size, GFP_KERNEL);
13198c4203cbSLee Jones 	if (!ab8500->oldmask)
13208c4203cbSLee Jones 		return -ENOMEM;
13218c4203cbSLee Jones 
1322e5c238c3SMattias Wallin 	/*
1323e5c238c3SMattias Wallin 	 * ab8500 has switched off due to (SWITCH_OFF_STATUS):
1324e5c238c3SMattias Wallin 	 * 0x01 Swoff bit programming
1325e5c238c3SMattias Wallin 	 * 0x02 Thermal protection activation
1326e5c238c3SMattias Wallin 	 * 0x04 Vbat lower then BattOk falling threshold
1327e5c238c3SMattias Wallin 	 * 0x08 Watchdog expired
1328e5c238c3SMattias Wallin 	 * 0x10 Non presence of 32kHz clock
1329e5c238c3SMattias Wallin 	 * 0x20 Battery level lower than power on reset threshold
1330e5c238c3SMattias Wallin 	 * 0x40 Power on key 1 pressed longer than 10 seconds
1331e5c238c3SMattias Wallin 	 * 0x80 DB8500 thermal shutdown
1332e5c238c3SMattias Wallin 	 */
1333e5c238c3SMattias Wallin 
1334e5c238c3SMattias Wallin 	ret = get_register_interruptible(ab8500, AB8500_RTC,
1335e5c238c3SMattias Wallin 		AB8500_SWITCH_OFF_STATUS, &value);
1336e5c238c3SMattias Wallin 	if (ret < 0)
1337e5c238c3SMattias Wallin 		return ret;
1338b04c530cSJonas Aaberg 	dev_info(ab8500->dev, "switch off cause(s) (%#x): ", value);
1339b04c530cSJonas Aaberg 
1340b04c530cSJonas Aaberg 	if (value) {
1341b04c530cSJonas Aaberg 		for (i = 0; i < ARRAY_SIZE(switch_off_status); i++) {
1342b04c530cSJonas Aaberg 			if (value & 1)
1343b04c530cSJonas Aaberg 				printk(KERN_CONT " \"%s\"",
1344b04c530cSJonas Aaberg 				       switch_off_status[i]);
1345b04c530cSJonas Aaberg 			value = value >> 1;
1346b04c530cSJonas Aaberg 
1347b04c530cSJonas Aaberg 		}
1348b04c530cSJonas Aaberg 		printk(KERN_CONT "\n");
1349b04c530cSJonas Aaberg 	} else {
1350b04c530cSJonas Aaberg 		printk(KERN_CONT " None\n");
1351b04c530cSJonas Aaberg 	}
1352e5c238c3SMattias Wallin 
135362579266SRabin Vincent 	if (plat && plat->init)
135462579266SRabin Vincent 		plat->init(ab8500);
135562579266SRabin Vincent 
135662579266SRabin Vincent 	/* Clear and mask all interrupts */
13572ced445eSLinus Walleij 	for (i = 0; i < ab8500->mask_size; i++) {
13580f620837SLinus Walleij 		/*
13590f620837SLinus Walleij 		 * Interrupt register 12 doesn't exist prior to AB8500 version
13600f620837SLinus Walleij 		 * 2.0
13610f620837SLinus Walleij 		 */
13620f620837SLinus Walleij 		if (ab8500->irq_reg_offset[i] == 11 &&
13630f620837SLinus Walleij 				is_ab8500_1p1_or_earlier(ab8500))
136492d50a41SMattias Wallin 			continue;
136562579266SRabin Vincent 
136647c16975SMattias Wallin 		get_register_interruptible(ab8500, AB8500_INTERRUPT,
13672ced445eSLinus Walleij 			AB8500_IT_LATCH1_REG + ab8500->irq_reg_offset[i],
136892d50a41SMattias Wallin 			&value);
136947c16975SMattias Wallin 		set_register_interruptible(ab8500, AB8500_INTERRUPT,
13702ced445eSLinus Walleij 			AB8500_IT_MASK1_REG + ab8500->irq_reg_offset[i], 0xff);
137162579266SRabin Vincent 	}
137262579266SRabin Vincent 
137347c16975SMattias Wallin 	ret = abx500_register_ops(ab8500->dev, &ab8500_ops);
137447c16975SMattias Wallin 	if (ret)
13758c4203cbSLee Jones 		return ret;
137647c16975SMattias Wallin 
13772ced445eSLinus Walleij 	for (i = 0; i < ab8500->mask_size; i++)
137862579266SRabin Vincent 		ab8500->mask[i] = ab8500->oldmask[i] = 0xff;
137962579266SRabin Vincent 
138006e589efSLee Jones 	ret = ab8500_irq_init(ab8500, np);
138162579266SRabin Vincent 	if (ret)
13828c4203cbSLee Jones 		return ret;
138362579266SRabin Vincent 
13847ccfe9b1SMichel JAOUEN 	/*  Activate this feature only in ab9540 */
13857ccfe9b1SMichel JAOUEN 	/*  till tests are done on ab8500 1p2 or later*/
138606e589efSLee Jones 	if (is_ab9540(ab8500)) {
13878c4203cbSLee Jones 		ret = devm_request_threaded_irq(&pdev->dev, ab8500->irq, NULL,
13887ccfe9b1SMichel JAOUEN 						ab8500_hierarchical_irq,
13897ccfe9b1SMichel JAOUEN 						IRQF_ONESHOT | IRQF_NO_SUSPEND,
13907ccfe9b1SMichel JAOUEN 						"ab8500", ab8500);
139106e589efSLee Jones 	}
139206e589efSLee Jones 	else {
13938c4203cbSLee Jones 		ret = devm_request_threaded_irq(&pdev->dev, ab8500->irq, NULL,
13947ccfe9b1SMichel JAOUEN 						ab8500_irq,
13954f079985SMattias Wallin 						IRQF_ONESHOT | IRQF_NO_SUSPEND,
13964f079985SMattias Wallin 						"ab8500", ab8500);
139762579266SRabin Vincent 		if (ret)
13988c4203cbSLee Jones 			return ret;
139962579266SRabin Vincent 	}
140062579266SRabin Vincent 
1401d6255529SLinus Walleij 	ret = mfd_add_devices(ab8500->dev, 0, abx500_common_devs,
1402d6255529SLinus Walleij 			ARRAY_SIZE(abx500_common_devs), NULL,
140355692af5SMark Brown 			ab8500->irq_base, ab8500->domain);
1404d6255529SLinus Walleij 	if (ret)
14058c4203cbSLee Jones 		return ret;
1406d6255529SLinus Walleij 
1407d6255529SLinus Walleij 	if (is_ab9540(ab8500))
1408d6255529SLinus Walleij 		ret = mfd_add_devices(ab8500->dev, 0, ab9540_devs,
1409d6255529SLinus Walleij 				ARRAY_SIZE(ab9540_devs), NULL,
141055692af5SMark Brown 				ab8500->irq_base, ab8500->domain);
1411d6255529SLinus Walleij 	else
1412549931f9SSundar R Iyer 		ret = mfd_add_devices(ab8500->dev, 0, ab8500_devs,
141344f72e53SVirupax Sadashivpetimath 				ARRAY_SIZE(ab8500_devs), NULL,
141455692af5SMark Brown 				ab8500->irq_base, ab8500->domain);
14156bc4a568SLee Jones 	if (ret)
14168c4203cbSLee Jones 		return ret;
141744f72e53SVirupax Sadashivpetimath 
141844f72e53SVirupax Sadashivpetimath 	if (is_ab9540(ab8500) || is_ab8505(ab8500))
141944f72e53SVirupax Sadashivpetimath 		ret = mfd_add_devices(ab8500->dev, 0, ab9540_ab8505_devs,
142044f72e53SVirupax Sadashivpetimath 				ARRAY_SIZE(ab9540_ab8505_devs), NULL,
142155692af5SMark Brown 				ab8500->irq_base, ab8500->domain);
142262579266SRabin Vincent 	if (ret)
14238c4203cbSLee Jones 		return ret;
142462579266SRabin Vincent 
14256ef9418cSRickard Andersson 	if (!no_bm) {
14266ef9418cSRickard Andersson 		/* Add battery management devices */
14276ef9418cSRickard Andersson 		ret = mfd_add_devices(ab8500->dev, 0, ab8500_bm_devs,
14286ef9418cSRickard Andersson 				      ARRAY_SIZE(ab8500_bm_devs), NULL,
142955692af5SMark Brown 				      ab8500->irq_base, ab8500->domain);
14306ef9418cSRickard Andersson 		if (ret)
14316ef9418cSRickard Andersson 			dev_err(ab8500->dev, "error adding bm devices\n");
14326ef9418cSRickard Andersson 	}
14336ef9418cSRickard Andersson 
1434d6255529SLinus Walleij 	if (is_ab9540(ab8500))
1435d6255529SLinus Walleij 		ret = sysfs_create_group(&ab8500->dev->kobj,
1436d6255529SLinus Walleij 					&ab9540_attr_group);
1437d6255529SLinus Walleij 	else
1438d6255529SLinus Walleij 		ret = sysfs_create_group(&ab8500->dev->kobj,
1439d6255529SLinus Walleij 					&ab8500_attr_group);
1440cca69b67SMattias Wallin 	if (ret)
1441cca69b67SMattias Wallin 		dev_err(ab8500->dev, "error creating sysfs entries\n");
144206e589efSLee Jones 
144362579266SRabin Vincent 	return ret;
144462579266SRabin Vincent }
144562579266SRabin Vincent 
14464740f73fSBill Pemberton static int ab8500_remove(struct platform_device *pdev)
144762579266SRabin Vincent {
1448d28f1db8SLee Jones 	struct ab8500 *ab8500 = platform_get_drvdata(pdev);
1449d28f1db8SLee Jones 
1450d6255529SLinus Walleij 	if (is_ab9540(ab8500))
1451d6255529SLinus Walleij 		sysfs_remove_group(&ab8500->dev->kobj, &ab9540_attr_group);
1452d6255529SLinus Walleij 	else
1453cca69b67SMattias Wallin 		sysfs_remove_group(&ab8500->dev->kobj, &ab8500_attr_group);
145406e589efSLee Jones 
145562579266SRabin Vincent 	mfd_remove_devices(ab8500->dev);
145662579266SRabin Vincent 
145762579266SRabin Vincent 	return 0;
145862579266SRabin Vincent }
145962579266SRabin Vincent 
1460d28f1db8SLee Jones static const struct platform_device_id ab8500_id[] = {
1461d28f1db8SLee Jones 	{ "ab8500-core", AB8500_VERSION_AB8500 },
1462d28f1db8SLee Jones 	{ "ab8505-i2c", AB8500_VERSION_AB8505 },
1463d28f1db8SLee Jones 	{ "ab9540-i2c", AB8500_VERSION_AB9540 },
1464d28f1db8SLee Jones 	{ "ab8540-i2c", AB8500_VERSION_AB8540 },
1465d28f1db8SLee Jones 	{ }
1466d28f1db8SLee Jones };
1467d28f1db8SLee Jones 
1468d28f1db8SLee Jones static struct platform_driver ab8500_core_driver = {
1469d28f1db8SLee Jones 	.driver = {
1470d28f1db8SLee Jones 		.name = "ab8500-core",
1471d28f1db8SLee Jones 		.owner = THIS_MODULE,
1472d28f1db8SLee Jones 	},
1473d28f1db8SLee Jones 	.probe	= ab8500_probe,
147484449216SBill Pemberton 	.remove	= ab8500_remove,
1475d28f1db8SLee Jones 	.id_table = ab8500_id,
1476d28f1db8SLee Jones };
1477d28f1db8SLee Jones 
1478d28f1db8SLee Jones static int __init ab8500_core_init(void)
1479d28f1db8SLee Jones {
1480d28f1db8SLee Jones 	return platform_driver_register(&ab8500_core_driver);
1481d28f1db8SLee Jones }
1482d28f1db8SLee Jones 
1483d28f1db8SLee Jones static void __exit ab8500_core_exit(void)
1484d28f1db8SLee Jones {
1485d28f1db8SLee Jones 	platform_driver_unregister(&ab8500_core_driver);
1486d28f1db8SLee Jones }
1487ba7cbc3eSLee Jones core_initcall(ab8500_core_init);
1488d28f1db8SLee Jones module_exit(ab8500_core_exit);
1489d28f1db8SLee Jones 
1490adceed62SMattias Wallin MODULE_AUTHOR("Mattias Wallin, Srinidhi Kasagar, Rabin Vincent");
149162579266SRabin Vincent MODULE_DESCRIPTION("AB8500 MFD core");
149262579266SRabin Vincent MODULE_LICENSE("GPL v2");
1493