xref: /openbmc/linux/drivers/mfd/ab8500-core.c (revision 9c677b9b74d4314ed7f222bf802d6d1e7585eb65)
162579266SRabin Vincent /*
262579266SRabin Vincent  * Copyright (C) ST-Ericsson SA 2010
362579266SRabin Vincent  *
462579266SRabin Vincent  * License Terms: GNU General Public License v2
562579266SRabin Vincent  * Author: Srinidhi Kasagar <srinidhi.kasagar@stericsson.com>
662579266SRabin Vincent  * Author: Rabin Vincent <rabin.vincent@stericsson.com>
7adceed62SMattias Wallin  * Author: Mattias Wallin <mattias.wallin@stericsson.com>
862579266SRabin Vincent  */
962579266SRabin Vincent 
1062579266SRabin Vincent #include <linux/kernel.h>
1162579266SRabin Vincent #include <linux/slab.h>
1262579266SRabin Vincent #include <linux/init.h>
1362579266SRabin Vincent #include <linux/irq.h>
1406e589efSLee Jones #include <linux/irqdomain.h>
1562579266SRabin Vincent #include <linux/delay.h>
1662579266SRabin Vincent #include <linux/interrupt.h>
1762579266SRabin Vincent #include <linux/module.h>
1862579266SRabin Vincent #include <linux/platform_device.h>
1962579266SRabin Vincent #include <linux/mfd/core.h>
2047c16975SMattias Wallin #include <linux/mfd/abx500.h>
21ee66e653SLinus Walleij #include <linux/mfd/abx500/ab8500.h>
2200441b5eSLee Jones #include <linux/mfd/abx500/ab8500-bm.h>
23d28f1db8SLee Jones #include <linux/mfd/dbx500-prcmu.h>
24549931f9SSundar R Iyer #include <linux/regulator/ab8500.h>
256bc4a568SLee Jones #include <linux/of.h>
266bc4a568SLee Jones #include <linux/of_device.h>
2762579266SRabin Vincent 
2862579266SRabin Vincent /*
2962579266SRabin Vincent  * Interrupt register offsets
3062579266SRabin Vincent  * Bank : 0x0E
3162579266SRabin Vincent  */
3247c16975SMattias Wallin #define AB8500_IT_SOURCE1_REG		0x00
3347c16975SMattias Wallin #define AB8500_IT_SOURCE2_REG		0x01
3447c16975SMattias Wallin #define AB8500_IT_SOURCE3_REG		0x02
3547c16975SMattias Wallin #define AB8500_IT_SOURCE4_REG		0x03
3647c16975SMattias Wallin #define AB8500_IT_SOURCE5_REG		0x04
3747c16975SMattias Wallin #define AB8500_IT_SOURCE6_REG		0x05
3847c16975SMattias Wallin #define AB8500_IT_SOURCE7_REG		0x06
3947c16975SMattias Wallin #define AB8500_IT_SOURCE8_REG		0x07
40d6255529SLinus Walleij #define AB9540_IT_SOURCE13_REG		0x0C
4147c16975SMattias Wallin #define AB8500_IT_SOURCE19_REG		0x12
4247c16975SMattias Wallin #define AB8500_IT_SOURCE20_REG		0x13
4347c16975SMattias Wallin #define AB8500_IT_SOURCE21_REG		0x14
4447c16975SMattias Wallin #define AB8500_IT_SOURCE22_REG		0x15
4547c16975SMattias Wallin #define AB8500_IT_SOURCE23_REG		0x16
4647c16975SMattias Wallin #define AB8500_IT_SOURCE24_REG		0x17
4762579266SRabin Vincent 
4862579266SRabin Vincent /*
4962579266SRabin Vincent  * latch registers
5062579266SRabin Vincent  */
5147c16975SMattias Wallin #define AB8500_IT_LATCH1_REG		0x20
5247c16975SMattias Wallin #define AB8500_IT_LATCH2_REG		0x21
5347c16975SMattias Wallin #define AB8500_IT_LATCH3_REG		0x22
5447c16975SMattias Wallin #define AB8500_IT_LATCH4_REG		0x23
5547c16975SMattias Wallin #define AB8500_IT_LATCH5_REG		0x24
5647c16975SMattias Wallin #define AB8500_IT_LATCH6_REG		0x25
5747c16975SMattias Wallin #define AB8500_IT_LATCH7_REG		0x26
5847c16975SMattias Wallin #define AB8500_IT_LATCH8_REG		0x27
5947c16975SMattias Wallin #define AB8500_IT_LATCH9_REG		0x28
6047c16975SMattias Wallin #define AB8500_IT_LATCH10_REG		0x29
6192d50a41SMattias Wallin #define AB8500_IT_LATCH12_REG		0x2B
62d6255529SLinus Walleij #define AB9540_IT_LATCH13_REG		0x2C
6347c16975SMattias Wallin #define AB8500_IT_LATCH19_REG		0x32
6447c16975SMattias Wallin #define AB8500_IT_LATCH20_REG		0x33
6547c16975SMattias Wallin #define AB8500_IT_LATCH21_REG		0x34
6647c16975SMattias Wallin #define AB8500_IT_LATCH22_REG		0x35
6747c16975SMattias Wallin #define AB8500_IT_LATCH23_REG		0x36
6847c16975SMattias Wallin #define AB8500_IT_LATCH24_REG		0x37
6962579266SRabin Vincent 
7062579266SRabin Vincent /*
7162579266SRabin Vincent  * mask registers
7262579266SRabin Vincent  */
7362579266SRabin Vincent 
7447c16975SMattias Wallin #define AB8500_IT_MASK1_REG		0x40
7547c16975SMattias Wallin #define AB8500_IT_MASK2_REG		0x41
7647c16975SMattias Wallin #define AB8500_IT_MASK3_REG		0x42
7747c16975SMattias Wallin #define AB8500_IT_MASK4_REG		0x43
7847c16975SMattias Wallin #define AB8500_IT_MASK5_REG		0x44
7947c16975SMattias Wallin #define AB8500_IT_MASK6_REG		0x45
8047c16975SMattias Wallin #define AB8500_IT_MASK7_REG		0x46
8147c16975SMattias Wallin #define AB8500_IT_MASK8_REG		0x47
8247c16975SMattias Wallin #define AB8500_IT_MASK9_REG		0x48
8347c16975SMattias Wallin #define AB8500_IT_MASK10_REG		0x49
8447c16975SMattias Wallin #define AB8500_IT_MASK11_REG		0x4A
8547c16975SMattias Wallin #define AB8500_IT_MASK12_REG		0x4B
8647c16975SMattias Wallin #define AB8500_IT_MASK13_REG		0x4C
8747c16975SMattias Wallin #define AB8500_IT_MASK14_REG		0x4D
8847c16975SMattias Wallin #define AB8500_IT_MASK15_REG		0x4E
8947c16975SMattias Wallin #define AB8500_IT_MASK16_REG		0x4F
9047c16975SMattias Wallin #define AB8500_IT_MASK17_REG		0x50
9147c16975SMattias Wallin #define AB8500_IT_MASK18_REG		0x51
9247c16975SMattias Wallin #define AB8500_IT_MASK19_REG		0x52
9347c16975SMattias Wallin #define AB8500_IT_MASK20_REG		0x53
9447c16975SMattias Wallin #define AB8500_IT_MASK21_REG		0x54
9547c16975SMattias Wallin #define AB8500_IT_MASK22_REG		0x55
9647c16975SMattias Wallin #define AB8500_IT_MASK23_REG		0x56
9747c16975SMattias Wallin #define AB8500_IT_MASK24_REG		0x57
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;
371*9c677b9bSLee Jones 
372*9c677b9bSLee Jones 	/* The AB8500 GPIOs have two interrupts each (rising & falling). */
373*9c677b9bSLee Jones 	if (offset >= AB8500_INT_GPIO6R && offset <= AB8500_INT_GPIO41R)
374*9c677b9bSLee Jones 		ab8500->mask[index + 2] |= mask;
375*9c677b9bSLee Jones 	if (offset >= AB9540_INT_GPIO50R && offset <= AB9540_INT_GPIO54R)
376*9c677b9bSLee Jones 		ab8500->mask[index + 1] |= mask;
377*9c677b9bSLee Jones 	if (offset == AB8540_INT_GPIO43R || offset == AB8540_INT_GPIO44R)
378*9c677b9bSLee Jones 		ab8500->mask[index] |= (mask >> 1);
37962579266SRabin Vincent }
38062579266SRabin Vincent 
3819505a0a0SMark Brown static void ab8500_irq_unmask(struct irq_data *data)
38262579266SRabin Vincent {
3839505a0a0SMark Brown 	struct ab8500 *ab8500 = irq_data_get_irq_chip_data(data);
384*9c677b9bSLee Jones 	unsigned int type = irqd_get_trigger_type(data);
38506e589efSLee Jones 	int offset = data->hwirq;
38662579266SRabin Vincent 	int index = offset / 8;
38762579266SRabin Vincent 	int mask = 1 << (offset % 8);
38862579266SRabin Vincent 
389*9c677b9bSLee Jones 	if (type & IRQ_TYPE_EDGE_RISING)
390*9c677b9bSLee Jones 		ab8500->mask[index] &= ~mask;
391*9c677b9bSLee Jones 
392*9c677b9bSLee Jones 	/* The AB8500 GPIOs have two interrupts each (rising & falling). */
393*9c677b9bSLee Jones 	if (type & IRQ_TYPE_EDGE_FALLING) {
394*9c677b9bSLee Jones 		if (offset >= AB8500_INT_GPIO6R && offset <= AB8500_INT_GPIO41R)
395*9c677b9bSLee Jones 			ab8500->mask[index + 2] &= ~mask;
396*9c677b9bSLee Jones 		else if (offset >= AB9540_INT_GPIO50R && offset <= AB9540_INT_GPIO54R)
397*9c677b9bSLee Jones 			ab8500->mask[index + 1] &= ~mask;
398*9c677b9bSLee Jones 		else if (offset == AB8540_INT_GPIO43R || offset == AB8540_INT_GPIO44R)
399*9c677b9bSLee Jones 			ab8500->mask[index] &= ~(mask >> 1);
400*9c677b9bSLee Jones 		else
401*9c677b9bSLee Jones 			ab8500->mask[index] &= ~mask;
402*9c677b9bSLee Jones 	} else
403*9c677b9bSLee Jones 		/* Satisfies the case where type is not set. */
40462579266SRabin Vincent 		ab8500->mask[index] &= ~mask;
40562579266SRabin Vincent }
40662579266SRabin Vincent 
40762579266SRabin Vincent static struct irq_chip ab8500_irq_chip = {
40862579266SRabin Vincent 	.name			= "ab8500",
4099505a0a0SMark Brown 	.irq_bus_lock		= ab8500_irq_lock,
4109505a0a0SMark Brown 	.irq_bus_sync_unlock	= ab8500_irq_sync_unlock,
4119505a0a0SMark Brown 	.irq_mask		= ab8500_irq_mask,
412e6f9306eSVirupax Sadashivpetimath 	.irq_disable		= ab8500_irq_mask,
4139505a0a0SMark Brown 	.irq_unmask		= ab8500_irq_unmask,
41462579266SRabin Vincent };
41562579266SRabin Vincent 
4167ccfe9b1SMichel JAOUEN static int ab8500_handle_hierarchical_line(struct ab8500 *ab8500,
4177ccfe9b1SMichel JAOUEN 					int latch_offset, u8 latch_val)
4187ccfe9b1SMichel JAOUEN {
4197ccfe9b1SMichel JAOUEN 	int int_bit = __ffs(latch_val);
4207ccfe9b1SMichel JAOUEN 	int line, i;
4217ccfe9b1SMichel JAOUEN 
4227ccfe9b1SMichel JAOUEN 	do {
4237ccfe9b1SMichel JAOUEN 		int_bit = __ffs(latch_val);
4247ccfe9b1SMichel JAOUEN 
4257ccfe9b1SMichel JAOUEN 		for (i = 0; i < ab8500->mask_size; i++)
4267ccfe9b1SMichel JAOUEN 			if (ab8500->irq_reg_offset[i] == latch_offset)
4277ccfe9b1SMichel JAOUEN 				break;
4287ccfe9b1SMichel JAOUEN 
4297ccfe9b1SMichel JAOUEN 		if (i >= ab8500->mask_size) {
4307ccfe9b1SMichel JAOUEN 			dev_err(ab8500->dev, "Register offset 0x%2x not declared\n",
4317ccfe9b1SMichel JAOUEN 					latch_offset);
4327ccfe9b1SMichel JAOUEN 			return -ENXIO;
4337ccfe9b1SMichel JAOUEN 		}
4347ccfe9b1SMichel JAOUEN 
4357ccfe9b1SMichel JAOUEN 		line = (i << 3) + int_bit;
4367ccfe9b1SMichel JAOUEN 		latch_val &= ~(1 << int_bit);
4377ccfe9b1SMichel JAOUEN 
4387ccfe9b1SMichel JAOUEN 		handle_nested_irq(ab8500->irq_base + line);
4397ccfe9b1SMichel JAOUEN 	} while (latch_val);
4407ccfe9b1SMichel JAOUEN 
4417ccfe9b1SMichel JAOUEN 	return 0;
4427ccfe9b1SMichel JAOUEN }
4437ccfe9b1SMichel JAOUEN 
4447ccfe9b1SMichel JAOUEN static int ab8500_handle_hierarchical_latch(struct ab8500 *ab8500,
4457ccfe9b1SMichel JAOUEN 					int hier_offset, u8 hier_val)
4467ccfe9b1SMichel JAOUEN {
4477ccfe9b1SMichel JAOUEN 	int latch_bit, status;
4487ccfe9b1SMichel JAOUEN 	u8 latch_offset, latch_val;
4497ccfe9b1SMichel JAOUEN 
4507ccfe9b1SMichel JAOUEN 	do {
4517ccfe9b1SMichel JAOUEN 		latch_bit = __ffs(hier_val);
4527ccfe9b1SMichel JAOUEN 		latch_offset = (hier_offset << 3) + latch_bit;
4537ccfe9b1SMichel JAOUEN 
4547ccfe9b1SMichel JAOUEN 		/* Fix inconsistent ITFromLatch25 bit mapping... */
4557ccfe9b1SMichel JAOUEN 		if (unlikely(latch_offset == 17))
4567ccfe9b1SMichel JAOUEN 			latch_offset = 24;
4577ccfe9b1SMichel JAOUEN 
4587ccfe9b1SMichel JAOUEN 		status = get_register_interruptible(ab8500,
4597ccfe9b1SMichel JAOUEN 				AB8500_INTERRUPT,
4607ccfe9b1SMichel JAOUEN 				AB8500_IT_LATCH1_REG + latch_offset,
4617ccfe9b1SMichel JAOUEN 				&latch_val);
4627ccfe9b1SMichel JAOUEN 		if (status < 0 || latch_val == 0)
4637ccfe9b1SMichel JAOUEN 			goto discard;
4647ccfe9b1SMichel JAOUEN 
4657ccfe9b1SMichel JAOUEN 		status = ab8500_handle_hierarchical_line(ab8500,
4667ccfe9b1SMichel JAOUEN 				latch_offset, latch_val);
4677ccfe9b1SMichel JAOUEN 		if (status < 0)
4687ccfe9b1SMichel JAOUEN 			return status;
4697ccfe9b1SMichel JAOUEN discard:
4707ccfe9b1SMichel JAOUEN 		hier_val &= ~(1 << latch_bit);
4717ccfe9b1SMichel JAOUEN 	} while (hier_val);
4727ccfe9b1SMichel JAOUEN 
4737ccfe9b1SMichel JAOUEN 	return 0;
4747ccfe9b1SMichel JAOUEN }
4757ccfe9b1SMichel JAOUEN 
4767ccfe9b1SMichel JAOUEN static irqreturn_t ab8500_hierarchical_irq(int irq, void *dev)
4777ccfe9b1SMichel JAOUEN {
4787ccfe9b1SMichel JAOUEN 	struct ab8500 *ab8500 = dev;
4797ccfe9b1SMichel JAOUEN 	u8 i;
4807ccfe9b1SMichel JAOUEN 
4817ccfe9b1SMichel JAOUEN 	dev_vdbg(ab8500->dev, "interrupt\n");
4827ccfe9b1SMichel JAOUEN 
4837ccfe9b1SMichel JAOUEN 	/*  Hierarchical interrupt version */
4847ccfe9b1SMichel JAOUEN 	for (i = 0; i < AB8500_IT_LATCHHIER_NUM; i++) {
4857ccfe9b1SMichel JAOUEN 		int status;
4867ccfe9b1SMichel JAOUEN 		u8 hier_val;
4877ccfe9b1SMichel JAOUEN 
4887ccfe9b1SMichel JAOUEN 		status = get_register_interruptible(ab8500, AB8500_INTERRUPT,
4897ccfe9b1SMichel JAOUEN 			AB8500_IT_LATCHHIER1_REG + i, &hier_val);
4907ccfe9b1SMichel JAOUEN 		if (status < 0 || hier_val == 0)
4917ccfe9b1SMichel JAOUEN 			continue;
4927ccfe9b1SMichel JAOUEN 
4937ccfe9b1SMichel JAOUEN 		status = ab8500_handle_hierarchical_latch(ab8500, i, hier_val);
4947ccfe9b1SMichel JAOUEN 		if (status < 0)
4957ccfe9b1SMichel JAOUEN 			break;
4967ccfe9b1SMichel JAOUEN 	}
4977ccfe9b1SMichel JAOUEN 	return IRQ_HANDLED;
4987ccfe9b1SMichel JAOUEN }
4997ccfe9b1SMichel JAOUEN 
50080633f05SLee Jones /**
50180633f05SLee Jones  * ab8500_irq_get_virq(): Map an interrupt on a chip to a virtual IRQ
50280633f05SLee Jones  *
50380633f05SLee Jones  * @ab8500: ab8500_irq controller to operate on.
50480633f05SLee Jones  * @irq: index of the interrupt requested in the chip IRQs
50580633f05SLee Jones  *
50680633f05SLee Jones  * Useful for drivers to request their own IRQs.
50780633f05SLee Jones  */
50880633f05SLee Jones static int ab8500_irq_get_virq(struct ab8500 *ab8500, int irq)
50980633f05SLee Jones {
51080633f05SLee Jones 	if (!ab8500)
51180633f05SLee Jones 		return -EINVAL;
51280633f05SLee Jones 
51380633f05SLee Jones 	return irq_create_mapping(ab8500->domain, irq);
51480633f05SLee Jones }
51580633f05SLee Jones 
51662579266SRabin Vincent static irqreturn_t ab8500_irq(int irq, void *dev)
51762579266SRabin Vincent {
51862579266SRabin Vincent 	struct ab8500 *ab8500 = dev;
51962579266SRabin Vincent 	int i;
52062579266SRabin Vincent 
52162579266SRabin Vincent 	dev_vdbg(ab8500->dev, "interrupt\n");
52262579266SRabin Vincent 
523112a80d2SJonas Aaberg 	atomic_inc(&ab8500->transfer_ongoing);
524112a80d2SJonas Aaberg 
5252ced445eSLinus Walleij 	for (i = 0; i < ab8500->mask_size; i++) {
5262ced445eSLinus Walleij 		int regoffset = ab8500->irq_reg_offset[i];
52762579266SRabin Vincent 		int status;
52847c16975SMattias Wallin 		u8 value;
52962579266SRabin Vincent 
5300f620837SLinus Walleij 		/*
5310f620837SLinus Walleij 		 * Interrupt register 12 doesn't exist prior to AB8500 version
5320f620837SLinus Walleij 		 * 2.0
5330f620837SLinus Walleij 		 */
5340f620837SLinus Walleij 		if (regoffset == 11 && is_ab8500_1p1_or_earlier(ab8500))
53592d50a41SMattias Wallin 			continue;
53692d50a41SMattias Wallin 
53747c16975SMattias Wallin 		status = get_register_interruptible(ab8500, AB8500_INTERRUPT,
53847c16975SMattias Wallin 			AB8500_IT_LATCH1_REG + regoffset, &value);
53947c16975SMattias Wallin 		if (status < 0 || value == 0)
54062579266SRabin Vincent 			continue;
54162579266SRabin Vincent 
54262579266SRabin Vincent 		do {
54388aec4f7SMattias Wallin 			int bit = __ffs(value);
54462579266SRabin Vincent 			int line = i * 8 + bit;
5450a37fc56SLee Jones 			int virq = ab8500_irq_get_virq(ab8500, line);
54662579266SRabin Vincent 
5470a37fc56SLee Jones 			handle_nested_irq(virq);
54847c16975SMattias Wallin 			value &= ~(1 << bit);
549112a80d2SJonas Aaberg 
55047c16975SMattias Wallin 		} while (value);
55162579266SRabin Vincent 	}
552112a80d2SJonas Aaberg 	atomic_dec(&ab8500->transfer_ongoing);
55362579266SRabin Vincent 	return IRQ_HANDLED;
55462579266SRabin Vincent }
55562579266SRabin Vincent 
55606e589efSLee Jones static int ab8500_irq_map(struct irq_domain *d, unsigned int virq,
55706e589efSLee Jones 				irq_hw_number_t hwirq)
55806e589efSLee Jones {
55906e589efSLee Jones 	struct ab8500 *ab8500 = d->host_data;
56006e589efSLee Jones 
56106e589efSLee Jones 	if (!ab8500)
56206e589efSLee Jones 		return -EINVAL;
56306e589efSLee Jones 
56406e589efSLee Jones 	irq_set_chip_data(virq, ab8500);
56506e589efSLee Jones 	irq_set_chip_and_handler(virq, &ab8500_irq_chip,
56606e589efSLee Jones 				handle_simple_irq);
56706e589efSLee Jones 	irq_set_nested_thread(virq, 1);
56806e589efSLee Jones #ifdef CONFIG_ARM
56906e589efSLee Jones 	set_irq_flags(virq, IRQF_VALID);
57006e589efSLee Jones #else
57106e589efSLee Jones 	irq_set_noprobe(virq);
57206e589efSLee Jones #endif
57362579266SRabin Vincent 
57462579266SRabin Vincent 	return 0;
57562579266SRabin Vincent }
57662579266SRabin Vincent 
57706e589efSLee Jones static struct irq_domain_ops ab8500_irq_ops = {
57806e589efSLee Jones         .map    = ab8500_irq_map,
57906e589efSLee Jones         .xlate  = irq_domain_xlate_twocell,
58006e589efSLee Jones };
58106e589efSLee Jones 
58206e589efSLee Jones static int ab8500_irq_init(struct ab8500 *ab8500, struct device_node *np)
58362579266SRabin Vincent {
5842ced445eSLinus Walleij 	int num_irqs;
58562579266SRabin Vincent 
586d6255529SLinus Walleij 	if (is_ab9540(ab8500))
587d6255529SLinus Walleij 		num_irqs = AB9540_NR_IRQS;
588a982362cSBengt Jonsson 	else if (is_ab8505(ab8500))
589a982362cSBengt Jonsson 		num_irqs = AB8505_NR_IRQS;
590d6255529SLinus Walleij 	else
5912ced445eSLinus Walleij 		num_irqs = AB8500_NR_IRQS;
5922ced445eSLinus Walleij 
593f1d11f39SLinus Walleij 	/* If ->irq_base is zero this will give a linear mapping */
594f1d11f39SLinus Walleij 	ab8500->domain = irq_domain_add_simple(NULL,
595f1d11f39SLinus Walleij 			num_irqs, ab8500->irq_base,
596f1d11f39SLinus Walleij 			&ab8500_irq_ops, ab8500);
59706e589efSLee Jones 
59806e589efSLee Jones 	if (!ab8500->domain) {
59906e589efSLee Jones 		dev_err(ab8500->dev, "Failed to create irqdomain\n");
60006e589efSLee Jones 		return -ENOSYS;
60106e589efSLee Jones 	}
60206e589efSLee Jones 
60306e589efSLee Jones 	return 0;
60462579266SRabin Vincent }
60562579266SRabin Vincent 
606112a80d2SJonas Aaberg int ab8500_suspend(struct ab8500 *ab8500)
607112a80d2SJonas Aaberg {
608112a80d2SJonas Aaberg 	if (atomic_read(&ab8500->transfer_ongoing))
609112a80d2SJonas Aaberg 		return -EINVAL;
610112a80d2SJonas Aaberg 	else
611112a80d2SJonas Aaberg 		return 0;
612112a80d2SJonas Aaberg }
613112a80d2SJonas Aaberg 
614a9e9ce4cSBill Pemberton static struct resource ab8500_gpadc_resources[] = {
61562579266SRabin Vincent 	{
61662579266SRabin Vincent 		.name	= "HW_CONV_END",
61762579266SRabin Vincent 		.start	= AB8500_INT_GP_HW_ADC_CONV_END,
61862579266SRabin Vincent 		.end	= AB8500_INT_GP_HW_ADC_CONV_END,
61962579266SRabin Vincent 		.flags	= IORESOURCE_IRQ,
62062579266SRabin Vincent 	},
62162579266SRabin Vincent 	{
62262579266SRabin Vincent 		.name	= "SW_CONV_END",
62362579266SRabin Vincent 		.start	= AB8500_INT_GP_SW_ADC_CONV_END,
62462579266SRabin Vincent 		.end	= AB8500_INT_GP_SW_ADC_CONV_END,
62562579266SRabin Vincent 		.flags	= IORESOURCE_IRQ,
62662579266SRabin Vincent 	},
62762579266SRabin Vincent };
62862579266SRabin Vincent 
629a9e9ce4cSBill Pemberton static struct resource ab8500_rtc_resources[] = {
63062579266SRabin Vincent 	{
63162579266SRabin Vincent 		.name	= "60S",
63262579266SRabin Vincent 		.start	= AB8500_INT_RTC_60S,
63362579266SRabin Vincent 		.end	= AB8500_INT_RTC_60S,
63462579266SRabin Vincent 		.flags	= IORESOURCE_IRQ,
63562579266SRabin Vincent 	},
63662579266SRabin Vincent 	{
63762579266SRabin Vincent 		.name	= "ALARM",
63862579266SRabin Vincent 		.start	= AB8500_INT_RTC_ALARM,
63962579266SRabin Vincent 		.end	= AB8500_INT_RTC_ALARM,
64062579266SRabin Vincent 		.flags	= IORESOURCE_IRQ,
64162579266SRabin Vincent 	},
64262579266SRabin Vincent };
64362579266SRabin Vincent 
644a9e9ce4cSBill Pemberton static struct resource ab8500_poweronkey_db_resources[] = {
64577686517SSundar R Iyer 	{
64677686517SSundar R Iyer 		.name	= "ONKEY_DBF",
64777686517SSundar R Iyer 		.start	= AB8500_INT_PON_KEY1DB_F,
64877686517SSundar R Iyer 		.end	= AB8500_INT_PON_KEY1DB_F,
64977686517SSundar R Iyer 		.flags	= IORESOURCE_IRQ,
65077686517SSundar R Iyer 	},
65177686517SSundar R Iyer 	{
65277686517SSundar R Iyer 		.name	= "ONKEY_DBR",
65377686517SSundar R Iyer 		.start	= AB8500_INT_PON_KEY1DB_R,
65477686517SSundar R Iyer 		.end	= AB8500_INT_PON_KEY1DB_R,
65577686517SSundar R Iyer 		.flags	= IORESOURCE_IRQ,
65677686517SSundar R Iyer 	},
65777686517SSundar R Iyer };
65877686517SSundar R Iyer 
659a9e9ce4cSBill Pemberton static struct resource ab8500_av_acc_detect_resources[] = {
660e098adedSMattias Wallin 	{
6616af75ecdSLinus Walleij 	       .name = "ACC_DETECT_1DB_F",
6626af75ecdSLinus Walleij 	       .start = AB8500_INT_ACC_DETECT_1DB_F,
6636af75ecdSLinus Walleij 	       .end = AB8500_INT_ACC_DETECT_1DB_F,
664e098adedSMattias Wallin 	       .flags = IORESOURCE_IRQ,
665e098adedSMattias Wallin 	},
666e098adedSMattias Wallin 	{
6676af75ecdSLinus Walleij 	       .name = "ACC_DETECT_1DB_R",
6686af75ecdSLinus Walleij 	       .start = AB8500_INT_ACC_DETECT_1DB_R,
6696af75ecdSLinus Walleij 	       .end = AB8500_INT_ACC_DETECT_1DB_R,
670e098adedSMattias Wallin 	       .flags = IORESOURCE_IRQ,
671e098adedSMattias Wallin 	},
672e098adedSMattias Wallin 	{
6736af75ecdSLinus Walleij 	       .name = "ACC_DETECT_21DB_F",
6746af75ecdSLinus Walleij 	       .start = AB8500_INT_ACC_DETECT_21DB_F,
6756af75ecdSLinus Walleij 	       .end = AB8500_INT_ACC_DETECT_21DB_F,
6766af75ecdSLinus Walleij 	       .flags = IORESOURCE_IRQ,
6776af75ecdSLinus Walleij 	},
6786af75ecdSLinus Walleij 	{
6796af75ecdSLinus Walleij 	       .name = "ACC_DETECT_21DB_R",
6806af75ecdSLinus Walleij 	       .start = AB8500_INT_ACC_DETECT_21DB_R,
6816af75ecdSLinus Walleij 	       .end = AB8500_INT_ACC_DETECT_21DB_R,
6826af75ecdSLinus Walleij 	       .flags = IORESOURCE_IRQ,
6836af75ecdSLinus Walleij 	},
6846af75ecdSLinus Walleij 	{
6856af75ecdSLinus Walleij 	       .name = "ACC_DETECT_22DB_F",
6866af75ecdSLinus Walleij 	       .start = AB8500_INT_ACC_DETECT_22DB_F,
6876af75ecdSLinus Walleij 	       .end = AB8500_INT_ACC_DETECT_22DB_F,
6886af75ecdSLinus Walleij 	       .flags = IORESOURCE_IRQ,
6896af75ecdSLinus Walleij 	},
6906af75ecdSLinus Walleij 	{
6916af75ecdSLinus Walleij 	       .name = "ACC_DETECT_22DB_R",
6926af75ecdSLinus Walleij 	       .start = AB8500_INT_ACC_DETECT_22DB_R,
6936af75ecdSLinus Walleij 	       .end = AB8500_INT_ACC_DETECT_22DB_R,
6946af75ecdSLinus Walleij 	       .flags = IORESOURCE_IRQ,
6956af75ecdSLinus Walleij 	},
6966af75ecdSLinus Walleij };
6976af75ecdSLinus Walleij 
698a9e9ce4cSBill Pemberton static struct resource ab8500_charger_resources[] = {
6996af75ecdSLinus Walleij 	{
700e098adedSMattias Wallin 		.name = "MAIN_CH_UNPLUG_DET",
701e098adedSMattias Wallin 		.start = AB8500_INT_MAIN_CH_UNPLUG_DET,
702e098adedSMattias Wallin 		.end = AB8500_INT_MAIN_CH_UNPLUG_DET,
703e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
704e098adedSMattias Wallin 	},
705e098adedSMattias Wallin 	{
706e098adedSMattias Wallin 		.name = "MAIN_CHARGE_PLUG_DET",
707e098adedSMattias Wallin 		.start = AB8500_INT_MAIN_CH_PLUG_DET,
708e098adedSMattias Wallin 		.end = AB8500_INT_MAIN_CH_PLUG_DET,
709e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
710e098adedSMattias Wallin 	},
711e098adedSMattias Wallin 	{
712e098adedSMattias Wallin 		.name = "VBUS_DET_R",
713e098adedSMattias Wallin 		.start = AB8500_INT_VBUS_DET_R,
714e098adedSMattias Wallin 		.end = AB8500_INT_VBUS_DET_R,
715e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
716e098adedSMattias Wallin 	},
717e098adedSMattias Wallin 	{
7186af75ecdSLinus Walleij 		.name = "VBUS_DET_F",
7196af75ecdSLinus Walleij 		.start = AB8500_INT_VBUS_DET_F,
7206af75ecdSLinus Walleij 		.end = AB8500_INT_VBUS_DET_F,
721e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
722e098adedSMattias Wallin 	},
723e098adedSMattias Wallin 	{
7246af75ecdSLinus Walleij 		.name = "USB_LINK_STATUS",
7256af75ecdSLinus Walleij 		.start = AB8500_INT_USB_LINK_STATUS,
7266af75ecdSLinus Walleij 		.end = AB8500_INT_USB_LINK_STATUS,
7276af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
7286af75ecdSLinus Walleij 	},
7296af75ecdSLinus Walleij 	{
730e098adedSMattias Wallin 		.name = "VBUS_OVV",
731e098adedSMattias Wallin 		.start = AB8500_INT_VBUS_OVV,
732e098adedSMattias Wallin 		.end = AB8500_INT_VBUS_OVV,
733e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
734e098adedSMattias Wallin 	},
735e098adedSMattias Wallin 	{
7366af75ecdSLinus Walleij 		.name = "USB_CH_TH_PROT_R",
7376af75ecdSLinus Walleij 		.start = AB8500_INT_USB_CH_TH_PROT_R,
7386af75ecdSLinus Walleij 		.end = AB8500_INT_USB_CH_TH_PROT_R,
739e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
740e098adedSMattias Wallin 	},
741e098adedSMattias Wallin 	{
7426af75ecdSLinus Walleij 		.name = "USB_CH_TH_PROT_F",
7436af75ecdSLinus Walleij 		.start = AB8500_INT_USB_CH_TH_PROT_F,
7446af75ecdSLinus Walleij 		.end = AB8500_INT_USB_CH_TH_PROT_F,
745e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
746e098adedSMattias Wallin 	},
747e098adedSMattias Wallin 	{
7486af75ecdSLinus Walleij 		.name = "MAIN_EXT_CH_NOT_OK",
7496af75ecdSLinus Walleij 		.start = AB8500_INT_MAIN_EXT_CH_NOT_OK,
7506af75ecdSLinus Walleij 		.end = AB8500_INT_MAIN_EXT_CH_NOT_OK,
7516af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
7526af75ecdSLinus Walleij 	},
7536af75ecdSLinus Walleij 	{
7546af75ecdSLinus Walleij 		.name = "MAIN_CH_TH_PROT_R",
7556af75ecdSLinus Walleij 		.start = AB8500_INT_MAIN_CH_TH_PROT_R,
7566af75ecdSLinus Walleij 		.end = AB8500_INT_MAIN_CH_TH_PROT_R,
7576af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
7586af75ecdSLinus Walleij 	},
7596af75ecdSLinus Walleij 	{
7606af75ecdSLinus Walleij 		.name = "MAIN_CH_TH_PROT_F",
7616af75ecdSLinus Walleij 		.start = AB8500_INT_MAIN_CH_TH_PROT_F,
7626af75ecdSLinus Walleij 		.end = AB8500_INT_MAIN_CH_TH_PROT_F,
7636af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
7646af75ecdSLinus Walleij 	},
7656af75ecdSLinus Walleij 	{
7666af75ecdSLinus Walleij 		.name = "USB_CHARGER_NOT_OKR",
767a982362cSBengt Jonsson 		.start = AB8500_INT_USB_CHARGER_NOT_OKR,
768a982362cSBengt Jonsson 		.end = AB8500_INT_USB_CHARGER_NOT_OKR,
7696af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
7706af75ecdSLinus Walleij 	},
7716af75ecdSLinus Walleij 	{
7726af75ecdSLinus Walleij 		.name = "CH_WD_EXP",
7736af75ecdSLinus Walleij 		.start = AB8500_INT_CH_WD_EXP,
7746af75ecdSLinus Walleij 		.end = AB8500_INT_CH_WD_EXP,
7756af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
7766af75ecdSLinus Walleij 	},
7776af75ecdSLinus Walleij };
7786af75ecdSLinus Walleij 
779a9e9ce4cSBill Pemberton static struct resource ab8500_btemp_resources[] = {
7806af75ecdSLinus Walleij 	{
7816af75ecdSLinus Walleij 		.name = "BAT_CTRL_INDB",
7826af75ecdSLinus Walleij 		.start = AB8500_INT_BAT_CTRL_INDB,
7836af75ecdSLinus Walleij 		.end = AB8500_INT_BAT_CTRL_INDB,
784e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
785e098adedSMattias Wallin 	},
786e098adedSMattias Wallin 	{
787e098adedSMattias Wallin 		.name = "BTEMP_LOW",
788e098adedSMattias Wallin 		.start = AB8500_INT_BTEMP_LOW,
789e098adedSMattias Wallin 		.end = AB8500_INT_BTEMP_LOW,
790e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
791e098adedSMattias Wallin 	},
792e098adedSMattias Wallin 	{
793e098adedSMattias Wallin 		.name = "BTEMP_HIGH",
794e098adedSMattias Wallin 		.start = AB8500_INT_BTEMP_HIGH,
795e098adedSMattias Wallin 		.end = AB8500_INT_BTEMP_HIGH,
796e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
797e098adedSMattias Wallin 	},
798e098adedSMattias Wallin 	{
7996af75ecdSLinus Walleij 		.name = "BTEMP_LOW_MEDIUM",
8006af75ecdSLinus Walleij 		.start = AB8500_INT_BTEMP_LOW_MEDIUM,
8016af75ecdSLinus Walleij 		.end = AB8500_INT_BTEMP_LOW_MEDIUM,
802e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
803e098adedSMattias Wallin 	},
804e098adedSMattias Wallin 	{
8056af75ecdSLinus Walleij 		.name = "BTEMP_MEDIUM_HIGH",
8066af75ecdSLinus Walleij 		.start = AB8500_INT_BTEMP_MEDIUM_HIGH,
8076af75ecdSLinus Walleij 		.end = AB8500_INT_BTEMP_MEDIUM_HIGH,
808e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
809e098adedSMattias Wallin 	},
810e098adedSMattias Wallin };
811e098adedSMattias Wallin 
812a9e9ce4cSBill Pemberton static struct resource ab8500_fg_resources[] = {
8136af75ecdSLinus Walleij 	{
8146af75ecdSLinus Walleij 		.name = "NCONV_ACCU",
8156af75ecdSLinus Walleij 		.start = AB8500_INT_CCN_CONV_ACC,
8166af75ecdSLinus Walleij 		.end = AB8500_INT_CCN_CONV_ACC,
8176af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
8186af75ecdSLinus Walleij 	},
8196af75ecdSLinus Walleij 	{
8206af75ecdSLinus Walleij 		.name = "BATT_OVV",
8216af75ecdSLinus Walleij 		.start = AB8500_INT_BATT_OVV,
8226af75ecdSLinus Walleij 		.end = AB8500_INT_BATT_OVV,
8236af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
8246af75ecdSLinus Walleij 	},
8256af75ecdSLinus Walleij 	{
8266af75ecdSLinus Walleij 		.name = "LOW_BAT_F",
8276af75ecdSLinus Walleij 		.start = AB8500_INT_LOW_BAT_F,
8286af75ecdSLinus Walleij 		.end = AB8500_INT_LOW_BAT_F,
8296af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
8306af75ecdSLinus Walleij 	},
8316af75ecdSLinus Walleij 	{
8326af75ecdSLinus Walleij 		.name = "LOW_BAT_R",
8336af75ecdSLinus Walleij 		.start = AB8500_INT_LOW_BAT_R,
8346af75ecdSLinus Walleij 		.end = AB8500_INT_LOW_BAT_R,
8356af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
8366af75ecdSLinus Walleij 	},
8376af75ecdSLinus Walleij 	{
8386af75ecdSLinus Walleij 		.name = "CC_INT_CALIB",
8396af75ecdSLinus Walleij 		.start = AB8500_INT_CC_INT_CALIB,
8406af75ecdSLinus Walleij 		.end = AB8500_INT_CC_INT_CALIB,
8416af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
8426af75ecdSLinus Walleij 	},
843a982362cSBengt Jonsson 	{
844a982362cSBengt Jonsson 		.name = "CCEOC",
845a982362cSBengt Jonsson 		.start = AB8500_INT_CCEOC,
846a982362cSBengt Jonsson 		.end = AB8500_INT_CCEOC,
847a982362cSBengt Jonsson 		.flags = IORESOURCE_IRQ,
848a982362cSBengt Jonsson 	},
8496af75ecdSLinus Walleij };
8506af75ecdSLinus Walleij 
851a9e9ce4cSBill Pemberton static struct resource ab8500_chargalg_resources[] = {};
8526af75ecdSLinus Walleij 
853df720647SAxel Lin #ifdef CONFIG_DEBUG_FS
854a9e9ce4cSBill Pemberton static struct resource ab8500_debug_resources[] = {
855e098adedSMattias Wallin 	{
856e098adedSMattias Wallin 		.name	= "IRQ_FIRST",
857e098adedSMattias Wallin 		.start	= AB8500_INT_MAIN_EXT_CH_NOT_OK,
858e098adedSMattias Wallin 		.end	= AB8500_INT_MAIN_EXT_CH_NOT_OK,
859e098adedSMattias Wallin 		.flags	= IORESOURCE_IRQ,
860e098adedSMattias Wallin 	},
861e098adedSMattias Wallin 	{
862e098adedSMattias Wallin 		.name	= "IRQ_LAST",
863a982362cSBengt Jonsson 		.start	= AB8500_INT_XTAL32K_KO,
864a982362cSBengt Jonsson 		.end	= AB8500_INT_XTAL32K_KO,
865e098adedSMattias Wallin 		.flags	= IORESOURCE_IRQ,
866e098adedSMattias Wallin 	},
867e098adedSMattias Wallin };
868df720647SAxel Lin #endif
869e098adedSMattias Wallin 
870a9e9ce4cSBill Pemberton static struct resource ab8500_usb_resources[] = {
871e098adedSMattias Wallin 	{
872e098adedSMattias Wallin 		.name = "ID_WAKEUP_R",
873e098adedSMattias Wallin 		.start = AB8500_INT_ID_WAKEUP_R,
874e098adedSMattias Wallin 		.end = AB8500_INT_ID_WAKEUP_R,
875e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
876e098adedSMattias Wallin 	},
877e098adedSMattias Wallin 	{
878e098adedSMattias Wallin 		.name = "ID_WAKEUP_F",
879e098adedSMattias Wallin 		.start = AB8500_INT_ID_WAKEUP_F,
880e098adedSMattias Wallin 		.end = AB8500_INT_ID_WAKEUP_F,
881e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
882e098adedSMattias Wallin 	},
883e098adedSMattias Wallin 	{
884e098adedSMattias Wallin 		.name = "VBUS_DET_F",
885e098adedSMattias Wallin 		.start = AB8500_INT_VBUS_DET_F,
886e098adedSMattias Wallin 		.end = AB8500_INT_VBUS_DET_F,
887e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
888e098adedSMattias Wallin 	},
889e098adedSMattias Wallin 	{
890e098adedSMattias Wallin 		.name = "VBUS_DET_R",
891e098adedSMattias Wallin 		.start = AB8500_INT_VBUS_DET_R,
892e098adedSMattias Wallin 		.end = AB8500_INT_VBUS_DET_R,
893e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
894e098adedSMattias Wallin 	},
89592d50a41SMattias Wallin 	{
89692d50a41SMattias Wallin 		.name = "USB_LINK_STATUS",
89792d50a41SMattias Wallin 		.start = AB8500_INT_USB_LINK_STATUS,
89892d50a41SMattias Wallin 		.end = AB8500_INT_USB_LINK_STATUS,
89992d50a41SMattias Wallin 		.flags = IORESOURCE_IRQ,
90092d50a41SMattias Wallin 	},
9016af75ecdSLinus Walleij 	{
9026af75ecdSLinus Walleij 		.name = "USB_ADP_PROBE_PLUG",
9036af75ecdSLinus Walleij 		.start = AB8500_INT_ADP_PROBE_PLUG,
9046af75ecdSLinus Walleij 		.end = AB8500_INT_ADP_PROBE_PLUG,
9056af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
9066af75ecdSLinus Walleij 	},
9076af75ecdSLinus Walleij 	{
9086af75ecdSLinus Walleij 		.name = "USB_ADP_PROBE_UNPLUG",
9096af75ecdSLinus Walleij 		.start = AB8500_INT_ADP_PROBE_UNPLUG,
9106af75ecdSLinus Walleij 		.end = AB8500_INT_ADP_PROBE_UNPLUG,
9116af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
9126af75ecdSLinus Walleij 	},
913e098adedSMattias Wallin };
914e098adedSMattias Wallin 
915a9e9ce4cSBill Pemberton static struct resource ab8505_iddet_resources[] = {
91644f72e53SVirupax Sadashivpetimath 	{
91744f72e53SVirupax Sadashivpetimath 		.name  = "KeyDeglitch",
91844f72e53SVirupax Sadashivpetimath 		.start = AB8505_INT_KEYDEGLITCH,
91944f72e53SVirupax Sadashivpetimath 		.end   = AB8505_INT_KEYDEGLITCH,
92044f72e53SVirupax Sadashivpetimath 		.flags = IORESOURCE_IRQ,
92144f72e53SVirupax Sadashivpetimath 	},
92244f72e53SVirupax Sadashivpetimath 	{
92344f72e53SVirupax Sadashivpetimath 		.name  = "KP",
92444f72e53SVirupax Sadashivpetimath 		.start = AB8505_INT_KP,
92544f72e53SVirupax Sadashivpetimath 		.end   = AB8505_INT_KP,
92644f72e53SVirupax Sadashivpetimath 		.flags = IORESOURCE_IRQ,
92744f72e53SVirupax Sadashivpetimath 	},
92844f72e53SVirupax Sadashivpetimath 	{
92944f72e53SVirupax Sadashivpetimath 		.name  = "IKP",
93044f72e53SVirupax Sadashivpetimath 		.start = AB8505_INT_IKP,
93144f72e53SVirupax Sadashivpetimath 		.end   = AB8505_INT_IKP,
93244f72e53SVirupax Sadashivpetimath 		.flags = IORESOURCE_IRQ,
93344f72e53SVirupax Sadashivpetimath 	},
93444f72e53SVirupax Sadashivpetimath 	{
93544f72e53SVirupax Sadashivpetimath 		.name  = "IKR",
93644f72e53SVirupax Sadashivpetimath 		.start = AB8505_INT_IKR,
93744f72e53SVirupax Sadashivpetimath 		.end   = AB8505_INT_IKR,
93844f72e53SVirupax Sadashivpetimath 		.flags = IORESOURCE_IRQ,
93944f72e53SVirupax Sadashivpetimath 	},
94044f72e53SVirupax Sadashivpetimath 	{
94144f72e53SVirupax Sadashivpetimath 		.name  = "KeyStuck",
94244f72e53SVirupax Sadashivpetimath 		.start = AB8505_INT_KEYSTUCK,
94344f72e53SVirupax Sadashivpetimath 		.end   = AB8505_INT_KEYSTUCK,
94444f72e53SVirupax Sadashivpetimath 		.flags = IORESOURCE_IRQ,
94544f72e53SVirupax Sadashivpetimath 	},
94644f72e53SVirupax Sadashivpetimath };
94744f72e53SVirupax Sadashivpetimath 
948a9e9ce4cSBill Pemberton static struct resource ab8500_temp_resources[] = {
949e098adedSMattias Wallin 	{
950e098adedSMattias Wallin 		.name  = "AB8500_TEMP_WARM",
951e098adedSMattias Wallin 		.start = AB8500_INT_TEMP_WARM,
952e098adedSMattias Wallin 		.end   = AB8500_INT_TEMP_WARM,
953e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
954e098adedSMattias Wallin 	},
955e098adedSMattias Wallin };
956e098adedSMattias Wallin 
957a9e9ce4cSBill Pemberton static struct mfd_cell abx500_common_devs[] = {
9585814fc35SMattias Wallin #ifdef CONFIG_DEBUG_FS
9595814fc35SMattias Wallin 	{
9605814fc35SMattias Wallin 		.name = "ab8500-debug",
961bad76991SLee Jones 		.of_compatible = "stericsson,ab8500-debug",
962e098adedSMattias Wallin 		.num_resources = ARRAY_SIZE(ab8500_debug_resources),
963e098adedSMattias Wallin 		.resources = ab8500_debug_resources,
9645814fc35SMattias Wallin 	},
9655814fc35SMattias Wallin #endif
96662579266SRabin Vincent 	{
967e098adedSMattias Wallin 		.name = "ab8500-sysctrl",
968bad76991SLee Jones 		.of_compatible = "stericsson,ab8500-sysctrl",
969e098adedSMattias Wallin 	},
970e098adedSMattias Wallin 	{
971e098adedSMattias Wallin 		.name = "ab8500-regulator",
972bad76991SLee Jones 		.of_compatible = "stericsson,ab8500-regulator",
973e098adedSMattias Wallin 	},
974e098adedSMattias Wallin 	{
975916a871cSUlf Hansson 		.name = "abx500-clk",
976916a871cSUlf Hansson 		.of_compatible = "stericsson,abx500-clk",
977916a871cSUlf Hansson 	},
978916a871cSUlf Hansson 	{
97962579266SRabin Vincent 		.name = "ab8500-gpadc",
980bad76991SLee Jones 		.of_compatible = "stericsson,ab8500-gpadc",
98162579266SRabin Vincent 		.num_resources = ARRAY_SIZE(ab8500_gpadc_resources),
98262579266SRabin Vincent 		.resources = ab8500_gpadc_resources,
98362579266SRabin Vincent 	},
98462579266SRabin Vincent 	{
98562579266SRabin Vincent 		.name = "ab8500-rtc",
986bad76991SLee Jones 		.of_compatible = "stericsson,ab8500-rtc",
98762579266SRabin Vincent 		.num_resources = ARRAY_SIZE(ab8500_rtc_resources),
98862579266SRabin Vincent 		.resources = ab8500_rtc_resources,
98962579266SRabin Vincent 	},
990f0f05b1cSArun Murthy 	{
9916af75ecdSLinus Walleij 		.name = "ab8500-acc-det",
992bad76991SLee Jones 		.of_compatible = "stericsson,ab8500-acc-det",
9936af75ecdSLinus Walleij 		.num_resources = ARRAY_SIZE(ab8500_av_acc_detect_resources),
9946af75ecdSLinus Walleij 		.resources = ab8500_av_acc_detect_resources,
9956af75ecdSLinus Walleij 	},
9966af75ecdSLinus Walleij 	{
997e098adedSMattias Wallin 		.name = "ab8500-poweron-key",
998bad76991SLee Jones 		.of_compatible = "stericsson,ab8500-poweron-key",
999e098adedSMattias Wallin 		.num_resources = ARRAY_SIZE(ab8500_poweronkey_db_resources),
1000e098adedSMattias Wallin 		.resources = ab8500_poweronkey_db_resources,
1001e098adedSMattias Wallin 	},
1002e098adedSMattias Wallin 	{
1003f0f05b1cSArun Murthy 		.name = "ab8500-pwm",
1004bad76991SLee Jones 		.of_compatible = "stericsson,ab8500-pwm",
1005f0f05b1cSArun Murthy 		.id = 1,
1006f0f05b1cSArun Murthy 	},
1007f0f05b1cSArun Murthy 	{
1008f0f05b1cSArun Murthy 		.name = "ab8500-pwm",
1009bad76991SLee Jones 		.of_compatible = "stericsson,ab8500-pwm",
1010f0f05b1cSArun Murthy 		.id = 2,
1011f0f05b1cSArun Murthy 	},
1012f0f05b1cSArun Murthy 	{
1013f0f05b1cSArun Murthy 		.name = "ab8500-pwm",
1014bad76991SLee Jones 		.of_compatible = "stericsson,ab8500-pwm",
1015f0f05b1cSArun Murthy 		.id = 3,
1016f0f05b1cSArun Murthy 	},
1017bad76991SLee Jones 	{
1018bad76991SLee Jones 		.name = "ab8500-leds",
1019bad76991SLee Jones 		.of_compatible = "stericsson,ab8500-leds",
1020bad76991SLee Jones 	},
102177686517SSundar R Iyer 	{
1022e098adedSMattias Wallin 		.name = "ab8500-denc",
1023bad76991SLee Jones 		.of_compatible = "stericsson,ab8500-denc",
1024e098adedSMattias Wallin 	},
1025e098adedSMattias Wallin 	{
1026e098adedSMattias Wallin 		.name = "ab8500-temp",
1027bad76991SLee Jones 		.of_compatible = "stericsson,ab8500-temp",
1028e098adedSMattias Wallin 		.num_resources = ARRAY_SIZE(ab8500_temp_resources),
1029e098adedSMattias Wallin 		.resources = ab8500_temp_resources,
103077686517SSundar R Iyer 	},
103162579266SRabin Vincent };
103262579266SRabin Vincent 
1033a9e9ce4cSBill Pemberton static struct mfd_cell ab8500_bm_devs[] = {
10346ef9418cSRickard Andersson 	{
10356ef9418cSRickard Andersson 		.name = "ab8500-charger",
10364aef72dbSRajanikanth H.V 		.of_compatible = "stericsson,ab8500-charger",
10376ef9418cSRickard Andersson 		.num_resources = ARRAY_SIZE(ab8500_charger_resources),
10386ef9418cSRickard Andersson 		.resources = ab8500_charger_resources,
10394aef72dbSRajanikanth H.V #ifndef CONFIG_OF
10404aef72dbSRajanikanth H.V 		.platform_data = &ab8500_bm_data,
10414aef72dbSRajanikanth H.V 		.pdata_size = sizeof(ab8500_bm_data),
10424aef72dbSRajanikanth H.V #endif
10436ef9418cSRickard Andersson 	},
10446ef9418cSRickard Andersson 	{
10456ef9418cSRickard Andersson 		.name = "ab8500-btemp",
1046bd9e8ab2SRajanikanth H.V 		.of_compatible = "stericsson,ab8500-btemp",
10476ef9418cSRickard Andersson 		.num_resources = ARRAY_SIZE(ab8500_btemp_resources),
10486ef9418cSRickard Andersson 		.resources = ab8500_btemp_resources,
1049bd9e8ab2SRajanikanth H.V #ifndef CONFIG_OF
1050bd9e8ab2SRajanikanth H.V 		.platform_data = &ab8500_bm_data,
1051bd9e8ab2SRajanikanth H.V 		.pdata_size = sizeof(ab8500_bm_data),
1052bd9e8ab2SRajanikanth H.V #endif
10536ef9418cSRickard Andersson 	},
10546ef9418cSRickard Andersson 	{
10556ef9418cSRickard Andersson 		.name = "ab8500-fg",
1056e0f1abebSRajanikanth H.V 		.of_compatible = "stericsson,ab8500-fg",
10576ef9418cSRickard Andersson 		.num_resources = ARRAY_SIZE(ab8500_fg_resources),
10586ef9418cSRickard Andersson 		.resources = ab8500_fg_resources,
1059e0f1abebSRajanikanth H.V #ifndef CONFIG_OF
1060e0f1abebSRajanikanth H.V 		.platform_data = &ab8500_bm_data,
1061e0f1abebSRajanikanth H.V 		.pdata_size = sizeof(ab8500_bm_data),
1062e0f1abebSRajanikanth H.V #endif
10636ef9418cSRickard Andersson 	},
10646ef9418cSRickard Andersson 	{
10656ef9418cSRickard Andersson 		.name = "ab8500-chargalg",
1066a12810abSRajanikanth H.V 		.of_compatible = "stericsson,ab8500-chargalg",
10676ef9418cSRickard Andersson 		.num_resources = ARRAY_SIZE(ab8500_chargalg_resources),
10686ef9418cSRickard Andersson 		.resources = ab8500_chargalg_resources,
1069a12810abSRajanikanth H.V #ifndef CONFIG_OF
1070a12810abSRajanikanth H.V 		.platform_data = &ab8500_bm_data,
1071a12810abSRajanikanth H.V 		.pdata_size = sizeof(ab8500_bm_data),
1072a12810abSRajanikanth H.V #endif
10736ef9418cSRickard Andersson 	},
10746ef9418cSRickard Andersson };
10756ef9418cSRickard Andersson 
1076a9e9ce4cSBill Pemberton static struct mfd_cell ab8500_devs[] = {
1077d6255529SLinus Walleij 	{
1078d6255529SLinus Walleij 		.name = "ab8500-gpio",
1079bad76991SLee Jones 		.of_compatible = "stericsson,ab8500-gpio",
1080d6255529SLinus Walleij 	},
1081d6255529SLinus Walleij 	{
1082d6255529SLinus Walleij 		.name = "ab8500-usb",
1083bad76991SLee Jones 		.of_compatible = "stericsson,ab8500-usb",
1084d6255529SLinus Walleij 		.num_resources = ARRAY_SIZE(ab8500_usb_resources),
1085d6255529SLinus Walleij 		.resources = ab8500_usb_resources,
1086d6255529SLinus Walleij 	},
108744f72e53SVirupax Sadashivpetimath 	{
108844f72e53SVirupax Sadashivpetimath 		.name = "ab8500-codec",
108981a21cddSLee Jones 		.of_compatible = "stericsson,ab8500-codec",
109044f72e53SVirupax Sadashivpetimath 	},
1091d6255529SLinus Walleij };
1092d6255529SLinus Walleij 
1093a9e9ce4cSBill Pemberton static struct mfd_cell ab9540_devs[] = {
1094d6255529SLinus Walleij 	{
1095d6255529SLinus Walleij 		.name = "ab8500-gpio",
1096d6255529SLinus Walleij 	},
1097d6255529SLinus Walleij 	{
1098d6255529SLinus Walleij 		.name = "ab9540-usb",
1099d6255529SLinus Walleij 		.num_resources = ARRAY_SIZE(ab8500_usb_resources),
1100d6255529SLinus Walleij 		.resources = ab8500_usb_resources,
1101d6255529SLinus Walleij 	},
110244f72e53SVirupax Sadashivpetimath 	{
110344f72e53SVirupax Sadashivpetimath 		.name = "ab9540-codec",
110444f72e53SVirupax Sadashivpetimath 	},
110544f72e53SVirupax Sadashivpetimath };
110644f72e53SVirupax Sadashivpetimath 
110744f72e53SVirupax Sadashivpetimath /* Device list common to ab9540 and ab8505 */
1108a9e9ce4cSBill Pemberton static struct mfd_cell ab9540_ab8505_devs[] = {
110944f72e53SVirupax Sadashivpetimath 	{
111044f72e53SVirupax Sadashivpetimath 		.name = "ab-iddet",
111144f72e53SVirupax Sadashivpetimath 		.num_resources = ARRAY_SIZE(ab8505_iddet_resources),
111244f72e53SVirupax Sadashivpetimath 		.resources = ab8505_iddet_resources,
111344f72e53SVirupax Sadashivpetimath 	},
1114d6255529SLinus Walleij };
1115d6255529SLinus Walleij 
1116cca69b67SMattias Wallin static ssize_t show_chip_id(struct device *dev,
1117cca69b67SMattias Wallin 				struct device_attribute *attr, char *buf)
1118cca69b67SMattias Wallin {
1119cca69b67SMattias Wallin 	struct ab8500 *ab8500;
1120cca69b67SMattias Wallin 
1121cca69b67SMattias Wallin 	ab8500 = dev_get_drvdata(dev);
1122cca69b67SMattias Wallin 	return sprintf(buf, "%#x\n", ab8500 ? ab8500->chip_id : -EINVAL);
1123cca69b67SMattias Wallin }
1124cca69b67SMattias Wallin 
1125e5c238c3SMattias Wallin /*
1126e5c238c3SMattias Wallin  * ab8500 has switched off due to (SWITCH_OFF_STATUS):
1127e5c238c3SMattias Wallin  * 0x01 Swoff bit programming
1128e5c238c3SMattias Wallin  * 0x02 Thermal protection activation
1129e5c238c3SMattias Wallin  * 0x04 Vbat lower then BattOk falling threshold
1130e5c238c3SMattias Wallin  * 0x08 Watchdog expired
1131e5c238c3SMattias Wallin  * 0x10 Non presence of 32kHz clock
1132e5c238c3SMattias Wallin  * 0x20 Battery level lower than power on reset threshold
1133e5c238c3SMattias Wallin  * 0x40 Power on key 1 pressed longer than 10 seconds
1134e5c238c3SMattias Wallin  * 0x80 DB8500 thermal shutdown
1135e5c238c3SMattias Wallin  */
1136e5c238c3SMattias Wallin static ssize_t show_switch_off_status(struct device *dev,
1137e5c238c3SMattias Wallin 				struct device_attribute *attr, char *buf)
1138e5c238c3SMattias Wallin {
1139e5c238c3SMattias Wallin 	int ret;
1140e5c238c3SMattias Wallin 	u8 value;
1141e5c238c3SMattias Wallin 	struct ab8500 *ab8500;
1142e5c238c3SMattias Wallin 
1143e5c238c3SMattias Wallin 	ab8500 = dev_get_drvdata(dev);
1144e5c238c3SMattias Wallin 	ret = get_register_interruptible(ab8500, AB8500_RTC,
1145e5c238c3SMattias Wallin 		AB8500_SWITCH_OFF_STATUS, &value);
1146e5c238c3SMattias Wallin 	if (ret < 0)
1147e5c238c3SMattias Wallin 		return ret;
1148e5c238c3SMattias Wallin 	return sprintf(buf, "%#x\n", value);
1149e5c238c3SMattias Wallin }
1150e5c238c3SMattias Wallin 
1151b4a31037SAndrew Lynn /*
1152b4a31037SAndrew Lynn  * ab8500 has turned on due to (TURN_ON_STATUS):
1153b4a31037SAndrew Lynn  * 0x01 PORnVbat
1154b4a31037SAndrew Lynn  * 0x02 PonKey1dbF
1155b4a31037SAndrew Lynn  * 0x04 PonKey2dbF
1156b4a31037SAndrew Lynn  * 0x08 RTCAlarm
1157b4a31037SAndrew Lynn  * 0x10 MainChDet
1158b4a31037SAndrew Lynn  * 0x20 VbusDet
1159b4a31037SAndrew Lynn  * 0x40 UsbIDDetect
1160b4a31037SAndrew Lynn  * 0x80 Reserved
1161b4a31037SAndrew Lynn  */
1162b4a31037SAndrew Lynn static ssize_t show_turn_on_status(struct device *dev,
1163b4a31037SAndrew Lynn 				struct device_attribute *attr, char *buf)
1164b4a31037SAndrew Lynn {
1165b4a31037SAndrew Lynn 	int ret;
1166b4a31037SAndrew Lynn 	u8 value;
1167b4a31037SAndrew Lynn 	struct ab8500 *ab8500;
1168b4a31037SAndrew Lynn 
1169b4a31037SAndrew Lynn 	ab8500 = dev_get_drvdata(dev);
1170b4a31037SAndrew Lynn 	ret = get_register_interruptible(ab8500, AB8500_SYS_CTRL1_BLOCK,
1171b4a31037SAndrew Lynn 		AB8500_TURN_ON_STATUS, &value);
1172b4a31037SAndrew Lynn 	if (ret < 0)
1173b4a31037SAndrew Lynn 		return ret;
1174b4a31037SAndrew Lynn 	return sprintf(buf, "%#x\n", value);
1175b4a31037SAndrew Lynn }
1176b4a31037SAndrew Lynn 
1177d6255529SLinus Walleij static ssize_t show_ab9540_dbbrstn(struct device *dev,
1178d6255529SLinus Walleij 				struct device_attribute *attr, char *buf)
1179d6255529SLinus Walleij {
1180d6255529SLinus Walleij 	struct ab8500 *ab8500;
1181d6255529SLinus Walleij 	int ret;
1182d6255529SLinus Walleij 	u8 value;
1183d6255529SLinus Walleij 
1184d6255529SLinus Walleij 	ab8500 = dev_get_drvdata(dev);
1185d6255529SLinus Walleij 
1186d6255529SLinus Walleij 	ret = get_register_interruptible(ab8500, AB8500_REGU_CTRL2,
1187d6255529SLinus Walleij 		AB9540_MODEM_CTRL2_REG, &value);
1188d6255529SLinus Walleij 	if (ret < 0)
1189d6255529SLinus Walleij 		return ret;
1190d6255529SLinus Walleij 
1191d6255529SLinus Walleij 	return sprintf(buf, "%d\n",
1192d6255529SLinus Walleij 			(value & AB9540_MODEM_CTRL2_SWDBBRSTN_BIT) ? 1 : 0);
1193d6255529SLinus Walleij }
1194d6255529SLinus Walleij 
1195d6255529SLinus Walleij static ssize_t store_ab9540_dbbrstn(struct device *dev,
1196d6255529SLinus Walleij 	struct device_attribute *attr, const char *buf, size_t count)
1197d6255529SLinus Walleij {
1198d6255529SLinus Walleij 	struct ab8500 *ab8500;
1199d6255529SLinus Walleij 	int ret = count;
1200d6255529SLinus Walleij 	int err;
1201d6255529SLinus Walleij 	u8 bitvalues;
1202d6255529SLinus Walleij 
1203d6255529SLinus Walleij 	ab8500 = dev_get_drvdata(dev);
1204d6255529SLinus Walleij 
1205d6255529SLinus Walleij 	if (count > 0) {
1206d6255529SLinus Walleij 		switch (buf[0]) {
1207d6255529SLinus Walleij 		case '0':
1208d6255529SLinus Walleij 			bitvalues = 0;
1209d6255529SLinus Walleij 			break;
1210d6255529SLinus Walleij 		case '1':
1211d6255529SLinus Walleij 			bitvalues = AB9540_MODEM_CTRL2_SWDBBRSTN_BIT;
1212d6255529SLinus Walleij 			break;
1213d6255529SLinus Walleij 		default:
1214d6255529SLinus Walleij 			goto exit;
1215d6255529SLinus Walleij 		}
1216d6255529SLinus Walleij 
1217d6255529SLinus Walleij 		err = mask_and_set_register_interruptible(ab8500,
1218d6255529SLinus Walleij 			AB8500_REGU_CTRL2, AB9540_MODEM_CTRL2_REG,
1219d6255529SLinus Walleij 			AB9540_MODEM_CTRL2_SWDBBRSTN_BIT, bitvalues);
1220d6255529SLinus Walleij 		if (err)
1221d6255529SLinus Walleij 			dev_info(ab8500->dev,
1222d6255529SLinus Walleij 				"Failed to set DBBRSTN %c, err %#x\n",
1223d6255529SLinus Walleij 				buf[0], err);
1224d6255529SLinus Walleij 	}
1225d6255529SLinus Walleij 
1226d6255529SLinus Walleij exit:
1227d6255529SLinus Walleij 	return ret;
1228d6255529SLinus Walleij }
1229d6255529SLinus Walleij 
1230cca69b67SMattias Wallin static DEVICE_ATTR(chip_id, S_IRUGO, show_chip_id, NULL);
1231e5c238c3SMattias Wallin static DEVICE_ATTR(switch_off_status, S_IRUGO, show_switch_off_status, NULL);
1232b4a31037SAndrew Lynn static DEVICE_ATTR(turn_on_status, S_IRUGO, show_turn_on_status, NULL);
1233d6255529SLinus Walleij static DEVICE_ATTR(dbbrstn, S_IRUGO | S_IWUSR,
1234d6255529SLinus Walleij 			show_ab9540_dbbrstn, store_ab9540_dbbrstn);
1235cca69b67SMattias Wallin 
1236cca69b67SMattias Wallin static struct attribute *ab8500_sysfs_entries[] = {
1237cca69b67SMattias Wallin 	&dev_attr_chip_id.attr,
1238e5c238c3SMattias Wallin 	&dev_attr_switch_off_status.attr,
1239b4a31037SAndrew Lynn 	&dev_attr_turn_on_status.attr,
1240cca69b67SMattias Wallin 	NULL,
1241cca69b67SMattias Wallin };
1242cca69b67SMattias Wallin 
1243d6255529SLinus Walleij static struct attribute *ab9540_sysfs_entries[] = {
1244d6255529SLinus Walleij 	&dev_attr_chip_id.attr,
1245d6255529SLinus Walleij 	&dev_attr_switch_off_status.attr,
1246d6255529SLinus Walleij 	&dev_attr_turn_on_status.attr,
1247d6255529SLinus Walleij 	&dev_attr_dbbrstn.attr,
1248d6255529SLinus Walleij 	NULL,
1249d6255529SLinus Walleij };
1250d6255529SLinus Walleij 
1251cca69b67SMattias Wallin static struct attribute_group ab8500_attr_group = {
1252cca69b67SMattias Wallin 	.attrs	= ab8500_sysfs_entries,
1253cca69b67SMattias Wallin };
1254cca69b67SMattias Wallin 
1255d6255529SLinus Walleij static struct attribute_group ab9540_attr_group = {
1256d6255529SLinus Walleij 	.attrs	= ab9540_sysfs_entries,
1257d6255529SLinus Walleij };
1258d6255529SLinus Walleij 
1259f791be49SBill Pemberton static int ab8500_probe(struct platform_device *pdev)
126062579266SRabin Vincent {
1261b04c530cSJonas Aaberg 	static char *switch_off_status[] = {
1262b04c530cSJonas Aaberg 		"Swoff bit programming",
1263b04c530cSJonas Aaberg 		"Thermal protection activation",
1264b04c530cSJonas Aaberg 		"Vbat lower then BattOk falling threshold",
1265b04c530cSJonas Aaberg 		"Watchdog expired",
1266b04c530cSJonas Aaberg 		"Non presence of 32kHz clock",
1267b04c530cSJonas Aaberg 		"Battery level lower than power on reset threshold",
1268b04c530cSJonas Aaberg 		"Power on key 1 pressed longer than 10 seconds",
1269b04c530cSJonas Aaberg 		"DB8500 thermal shutdown"};
1270d28f1db8SLee Jones 	struct ab8500_platform_data *plat = dev_get_platdata(&pdev->dev);
1271d28f1db8SLee Jones 	const struct platform_device_id *platid = platform_get_device_id(pdev);
12726bc4a568SLee Jones 	enum ab8500_version version = AB8500_VERSION_UNDEFINED;
12736bc4a568SLee Jones 	struct device_node *np = pdev->dev.of_node;
1274d28f1db8SLee Jones 	struct ab8500 *ab8500;
1275d28f1db8SLee Jones 	struct resource *resource;
127662579266SRabin Vincent 	int ret;
127762579266SRabin Vincent 	int i;
127847c16975SMattias Wallin 	u8 value;
127962579266SRabin Vincent 
12808c4203cbSLee Jones 	ab8500 = devm_kzalloc(&pdev->dev, sizeof *ab8500, GFP_KERNEL);
1281d28f1db8SLee Jones 	if (!ab8500)
1282d28f1db8SLee Jones 		return -ENOMEM;
1283d28f1db8SLee Jones 
128462579266SRabin Vincent 	if (plat)
128562579266SRabin Vincent 		ab8500->irq_base = plat->irq_base;
128662579266SRabin Vincent 
1287d28f1db8SLee Jones 	ab8500->dev = &pdev->dev;
1288d28f1db8SLee Jones 
1289d28f1db8SLee Jones 	resource = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
12908c4203cbSLee Jones 	if (!resource)
12918c4203cbSLee Jones 		return -ENODEV;
1292d28f1db8SLee Jones 
1293d28f1db8SLee Jones 	ab8500->irq = resource->start;
1294d28f1db8SLee Jones 
1295822672a7SLee Jones 	ab8500->read = ab8500_prcmu_read;
1296822672a7SLee Jones 	ab8500->write = ab8500_prcmu_write;
1297822672a7SLee Jones 	ab8500->write_masked = ab8500_prcmu_write_masked;
1298d28f1db8SLee Jones 
129962579266SRabin Vincent 	mutex_init(&ab8500->lock);
130062579266SRabin Vincent 	mutex_init(&ab8500->irq_lock);
1301112a80d2SJonas Aaberg 	atomic_set(&ab8500->transfer_ongoing, 0);
130262579266SRabin Vincent 
1303d28f1db8SLee Jones 	platform_set_drvdata(pdev, ab8500);
1304d28f1db8SLee Jones 
13056bc4a568SLee Jones 	if (platid)
13066bc4a568SLee Jones 		version = platid->driver_data;
13076bc4a568SLee Jones 
13080f620837SLinus Walleij 	if (version != AB8500_VERSION_UNDEFINED)
13090f620837SLinus Walleij 		ab8500->version = version;
13100f620837SLinus Walleij 	else {
13110f620837SLinus Walleij 		ret = get_register_interruptible(ab8500, AB8500_MISC,
13120f620837SLinus Walleij 			AB8500_IC_NAME_REG, &value);
13130f620837SLinus Walleij 		if (ret < 0)
13148c4203cbSLee Jones 			return ret;
13150f620837SLinus Walleij 
13160f620837SLinus Walleij 		ab8500->version = value;
13170f620837SLinus Walleij 	}
13180f620837SLinus Walleij 
131947c16975SMattias Wallin 	ret = get_register_interruptible(ab8500, AB8500_MISC,
132047c16975SMattias Wallin 		AB8500_REV_REG, &value);
132162579266SRabin Vincent 	if (ret < 0)
13228c4203cbSLee Jones 		return ret;
132362579266SRabin Vincent 
132447c16975SMattias Wallin 	ab8500->chip_id = value;
132562579266SRabin Vincent 
13260f620837SLinus Walleij 	dev_info(ab8500->dev, "detected chip, %s rev. %1x.%1x\n",
13270f620837SLinus Walleij 			ab8500_version_str[ab8500->version],
13280f620837SLinus Walleij 			ab8500->chip_id >> 4,
13290f620837SLinus Walleij 			ab8500->chip_id & 0x0F);
13300f620837SLinus Walleij 
1331d6255529SLinus Walleij 	/* Configure AB8500 or AB9540 IRQ */
1332a982362cSBengt Jonsson 	if (is_ab9540(ab8500) || is_ab8505(ab8500)) {
1333d6255529SLinus Walleij 		ab8500->mask_size = AB9540_NUM_IRQ_REGS;
1334d6255529SLinus Walleij 		ab8500->irq_reg_offset = ab9540_irq_regoffset;
1335d6255529SLinus Walleij 	} else {
13362ced445eSLinus Walleij 		ab8500->mask_size = AB8500_NUM_IRQ_REGS;
13372ced445eSLinus Walleij 		ab8500->irq_reg_offset = ab8500_irq_regoffset;
1338d6255529SLinus Walleij 	}
13398c4203cbSLee Jones 	ab8500->mask = devm_kzalloc(&pdev->dev, ab8500->mask_size, GFP_KERNEL);
13402ced445eSLinus Walleij 	if (!ab8500->mask)
13412ced445eSLinus Walleij 		return -ENOMEM;
13428c4203cbSLee Jones 	ab8500->oldmask = devm_kzalloc(&pdev->dev, ab8500->mask_size, GFP_KERNEL);
13438c4203cbSLee Jones 	if (!ab8500->oldmask)
13448c4203cbSLee Jones 		return -ENOMEM;
13458c4203cbSLee Jones 
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)
13998c4203cbSLee Jones 		return ret;
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)
14068c4203cbSLee Jones 		return ret;
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)) {
14118c4203cbSLee Jones 		ret = devm_request_threaded_irq(&pdev->dev, ab8500->irq, NULL,
14127ccfe9b1SMichel JAOUEN 						ab8500_hierarchical_irq,
14137ccfe9b1SMichel JAOUEN 						IRQF_ONESHOT | IRQF_NO_SUSPEND,
14147ccfe9b1SMichel JAOUEN 						"ab8500", ab8500);
141506e589efSLee Jones 	}
141606e589efSLee Jones 	else {
14178c4203cbSLee Jones 		ret = devm_request_threaded_irq(&pdev->dev, ab8500->irq, NULL,
14187ccfe9b1SMichel JAOUEN 						ab8500_irq,
14194f079985SMattias Wallin 						IRQF_ONESHOT | IRQF_NO_SUSPEND,
14204f079985SMattias Wallin 						"ab8500", ab8500);
142162579266SRabin Vincent 		if (ret)
14228c4203cbSLee Jones 			return ret;
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)
14298c4203cbSLee Jones 		return ret;
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)
14408c4203cbSLee Jones 		return ret;
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)
14478c4203cbSLee Jones 		return ret;
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 
14704740f73fSBill Pemberton static int ab8500_remove(struct platform_device *pdev)
147162579266SRabin Vincent {
1472d28f1db8SLee Jones 	struct ab8500 *ab8500 = platform_get_drvdata(pdev);
1473d28f1db8SLee Jones 
1474d6255529SLinus Walleij 	if (is_ab9540(ab8500))
1475d6255529SLinus Walleij 		sysfs_remove_group(&ab8500->dev->kobj, &ab9540_attr_group);
1476d6255529SLinus Walleij 	else
1477cca69b67SMattias Wallin 		sysfs_remove_group(&ab8500->dev->kobj, &ab8500_attr_group);
147806e589efSLee Jones 
147962579266SRabin Vincent 	mfd_remove_devices(ab8500->dev);
148062579266SRabin Vincent 
148162579266SRabin Vincent 	return 0;
148262579266SRabin Vincent }
148362579266SRabin Vincent 
1484d28f1db8SLee Jones static const struct platform_device_id ab8500_id[] = {
1485d28f1db8SLee Jones 	{ "ab8500-core", AB8500_VERSION_AB8500 },
1486d28f1db8SLee Jones 	{ "ab8505-i2c", AB8500_VERSION_AB8505 },
1487d28f1db8SLee Jones 	{ "ab9540-i2c", AB8500_VERSION_AB9540 },
1488d28f1db8SLee Jones 	{ "ab8540-i2c", AB8500_VERSION_AB8540 },
1489d28f1db8SLee Jones 	{ }
1490d28f1db8SLee Jones };
1491d28f1db8SLee Jones 
1492d28f1db8SLee Jones static struct platform_driver ab8500_core_driver = {
1493d28f1db8SLee Jones 	.driver = {
1494d28f1db8SLee Jones 		.name = "ab8500-core",
1495d28f1db8SLee Jones 		.owner = THIS_MODULE,
1496d28f1db8SLee Jones 	},
1497d28f1db8SLee Jones 	.probe	= ab8500_probe,
149884449216SBill Pemberton 	.remove	= ab8500_remove,
1499d28f1db8SLee Jones 	.id_table = ab8500_id,
1500d28f1db8SLee Jones };
1501d28f1db8SLee Jones 
1502d28f1db8SLee Jones static int __init ab8500_core_init(void)
1503d28f1db8SLee Jones {
1504d28f1db8SLee Jones 	return platform_driver_register(&ab8500_core_driver);
1505d28f1db8SLee Jones }
1506d28f1db8SLee Jones 
1507d28f1db8SLee Jones static void __exit ab8500_core_exit(void)
1508d28f1db8SLee Jones {
1509d28f1db8SLee Jones 	platform_driver_unregister(&ab8500_core_driver);
1510d28f1db8SLee Jones }
1511ba7cbc3eSLee Jones core_initcall(ab8500_core_init);
1512d28f1db8SLee Jones module_exit(ab8500_core_exit);
1513d28f1db8SLee Jones 
1514adceed62SMattias Wallin MODULE_AUTHOR("Mattias Wallin, Srinidhi Kasagar, Rabin Vincent");
151562579266SRabin Vincent MODULE_DESCRIPTION("AB8500 MFD core");
151662579266SRabin Vincent MODULE_LICENSE("GPL v2");
1517