xref: /openbmc/linux/drivers/mfd/ab8500-core.c (revision e2ddf46ab4ab40a657a1808cf4e358c46ae1ba68)
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;
3719c677b9bSLee Jones 
3729c677b9bSLee Jones 	/* The AB8500 GPIOs have two interrupts each (rising & falling). */
3739c677b9bSLee Jones 	if (offset >= AB8500_INT_GPIO6R && offset <= AB8500_INT_GPIO41R)
3749c677b9bSLee Jones 		ab8500->mask[index + 2] |= mask;
3759c677b9bSLee Jones 	if (offset >= AB9540_INT_GPIO50R && offset <= AB9540_INT_GPIO54R)
3769c677b9bSLee Jones 		ab8500->mask[index + 1] |= mask;
3779c677b9bSLee Jones 	if (offset == AB8540_INT_GPIO43R || offset == AB8540_INT_GPIO44R)
378*e2ddf46aSLinus Walleij 		/* Here the falling IRQ is one bit lower */
379*e2ddf46aSLinus Walleij 		ab8500->mask[index] |= (mask << 1);
38062579266SRabin Vincent }
38162579266SRabin Vincent 
3829505a0a0SMark Brown static void ab8500_irq_unmask(struct irq_data *data)
38362579266SRabin Vincent {
3849505a0a0SMark Brown 	struct ab8500 *ab8500 = irq_data_get_irq_chip_data(data);
3859c677b9bSLee Jones 	unsigned int type = irqd_get_trigger_type(data);
38606e589efSLee Jones 	int offset = data->hwirq;
38762579266SRabin Vincent 	int index = offset / 8;
38862579266SRabin Vincent 	int mask = 1 << (offset % 8);
38962579266SRabin Vincent 
3909c677b9bSLee Jones 	if (type & IRQ_TYPE_EDGE_RISING)
3919c677b9bSLee Jones 		ab8500->mask[index] &= ~mask;
3929c677b9bSLee Jones 
3939c677b9bSLee Jones 	/* The AB8500 GPIOs have two interrupts each (rising & falling). */
3949c677b9bSLee Jones 	if (type & IRQ_TYPE_EDGE_FALLING) {
3959c677b9bSLee Jones 		if (offset >= AB8500_INT_GPIO6R && offset <= AB8500_INT_GPIO41R)
3969c677b9bSLee Jones 			ab8500->mask[index + 2] &= ~mask;
3979c677b9bSLee Jones 		else if (offset >= AB9540_INT_GPIO50R && offset <= AB9540_INT_GPIO54R)
3989c677b9bSLee Jones 			ab8500->mask[index + 1] &= ~mask;
3999c677b9bSLee Jones 		else if (offset == AB8540_INT_GPIO43R || offset == AB8540_INT_GPIO44R)
400*e2ddf46aSLinus Walleij 			/* Here the falling IRQ is one bit lower */
401*e2ddf46aSLinus Walleij 			ab8500->mask[index] &= ~(mask << 1);
4029c677b9bSLee Jones 		else
4039c677b9bSLee Jones 			ab8500->mask[index] &= ~mask;
404*e2ddf46aSLinus Walleij 	} else {
4059c677b9bSLee Jones 		/* Satisfies the case where type is not set. */
40662579266SRabin Vincent 		ab8500->mask[index] &= ~mask;
40762579266SRabin Vincent 	}
408*e2ddf46aSLinus Walleij }
40962579266SRabin Vincent 
41062579266SRabin Vincent static struct irq_chip ab8500_irq_chip = {
41162579266SRabin Vincent 	.name			= "ab8500",
4129505a0a0SMark Brown 	.irq_bus_lock		= ab8500_irq_lock,
4139505a0a0SMark Brown 	.irq_bus_sync_unlock	= ab8500_irq_sync_unlock,
4149505a0a0SMark Brown 	.irq_mask		= ab8500_irq_mask,
415e6f9306eSVirupax Sadashivpetimath 	.irq_disable		= ab8500_irq_mask,
4169505a0a0SMark Brown 	.irq_unmask		= ab8500_irq_unmask,
41762579266SRabin Vincent };
41862579266SRabin Vincent 
4197ccfe9b1SMichel JAOUEN static int ab8500_handle_hierarchical_line(struct ab8500 *ab8500,
4207ccfe9b1SMichel JAOUEN 					int latch_offset, u8 latch_val)
4217ccfe9b1SMichel JAOUEN {
4227ccfe9b1SMichel JAOUEN 	int int_bit = __ffs(latch_val);
4237ccfe9b1SMichel JAOUEN 	int line, i;
4247ccfe9b1SMichel JAOUEN 
4257ccfe9b1SMichel JAOUEN 	do {
4267ccfe9b1SMichel JAOUEN 		int_bit = __ffs(latch_val);
4277ccfe9b1SMichel JAOUEN 
4287ccfe9b1SMichel JAOUEN 		for (i = 0; i < ab8500->mask_size; i++)
4297ccfe9b1SMichel JAOUEN 			if (ab8500->irq_reg_offset[i] == latch_offset)
4307ccfe9b1SMichel JAOUEN 				break;
4317ccfe9b1SMichel JAOUEN 
4327ccfe9b1SMichel JAOUEN 		if (i >= ab8500->mask_size) {
4337ccfe9b1SMichel JAOUEN 			dev_err(ab8500->dev, "Register offset 0x%2x not declared\n",
4347ccfe9b1SMichel JAOUEN 					latch_offset);
4357ccfe9b1SMichel JAOUEN 			return -ENXIO;
4367ccfe9b1SMichel JAOUEN 		}
4377ccfe9b1SMichel JAOUEN 
4387ccfe9b1SMichel JAOUEN 		line = (i << 3) + int_bit;
4397ccfe9b1SMichel JAOUEN 		latch_val &= ~(1 << int_bit);
4407ccfe9b1SMichel JAOUEN 
441*e2ddf46aSLinus Walleij 		/*
442*e2ddf46aSLinus Walleij 		 * This handles the falling edge hwirqs from the GPIO
443*e2ddf46aSLinus Walleij 		 * lines. Route them back to the line registered for the
444*e2ddf46aSLinus Walleij 		 * rising IRQ, as this is merely a flag for the same IRQ
445*e2ddf46aSLinus Walleij 		 * in linux terms.
446*e2ddf46aSLinus Walleij 		 */
447*e2ddf46aSLinus Walleij 		if (line >= AB8500_INT_GPIO6F && line <= AB8500_INT_GPIO41F)
448*e2ddf46aSLinus Walleij 			line -= 16;
449*e2ddf46aSLinus Walleij 		if (line >= AB9540_INT_GPIO50F && line <= AB9540_INT_GPIO54F)
450*e2ddf46aSLinus Walleij 			line -= 8;
451*e2ddf46aSLinus Walleij 		if (line == AB8540_INT_GPIO43F || line == AB8540_INT_GPIO44F)
452*e2ddf46aSLinus Walleij 			line += 1;
453*e2ddf46aSLinus Walleij 
4547ccfe9b1SMichel JAOUEN 		handle_nested_irq(ab8500->irq_base + line);
4557ccfe9b1SMichel JAOUEN 	} while (latch_val);
4567ccfe9b1SMichel JAOUEN 
4577ccfe9b1SMichel JAOUEN 	return 0;
4587ccfe9b1SMichel JAOUEN }
4597ccfe9b1SMichel JAOUEN 
4607ccfe9b1SMichel JAOUEN static int ab8500_handle_hierarchical_latch(struct ab8500 *ab8500,
4617ccfe9b1SMichel JAOUEN 					int hier_offset, u8 hier_val)
4627ccfe9b1SMichel JAOUEN {
4637ccfe9b1SMichel JAOUEN 	int latch_bit, status;
4647ccfe9b1SMichel JAOUEN 	u8 latch_offset, latch_val;
4657ccfe9b1SMichel JAOUEN 
4667ccfe9b1SMichel JAOUEN 	do {
4677ccfe9b1SMichel JAOUEN 		latch_bit = __ffs(hier_val);
4687ccfe9b1SMichel JAOUEN 		latch_offset = (hier_offset << 3) + latch_bit;
4697ccfe9b1SMichel JAOUEN 
4707ccfe9b1SMichel JAOUEN 		/* Fix inconsistent ITFromLatch25 bit mapping... */
4717ccfe9b1SMichel JAOUEN 		if (unlikely(latch_offset == 17))
4727ccfe9b1SMichel JAOUEN 			latch_offset = 24;
4737ccfe9b1SMichel JAOUEN 
4747ccfe9b1SMichel JAOUEN 		status = get_register_interruptible(ab8500,
4757ccfe9b1SMichel JAOUEN 				AB8500_INTERRUPT,
4767ccfe9b1SMichel JAOUEN 				AB8500_IT_LATCH1_REG + latch_offset,
4777ccfe9b1SMichel JAOUEN 				&latch_val);
4787ccfe9b1SMichel JAOUEN 		if (status < 0 || latch_val == 0)
4797ccfe9b1SMichel JAOUEN 			goto discard;
4807ccfe9b1SMichel JAOUEN 
4817ccfe9b1SMichel JAOUEN 		status = ab8500_handle_hierarchical_line(ab8500,
4827ccfe9b1SMichel JAOUEN 				latch_offset, latch_val);
4837ccfe9b1SMichel JAOUEN 		if (status < 0)
4847ccfe9b1SMichel JAOUEN 			return status;
4857ccfe9b1SMichel JAOUEN discard:
4867ccfe9b1SMichel JAOUEN 		hier_val &= ~(1 << latch_bit);
4877ccfe9b1SMichel JAOUEN 	} while (hier_val);
4887ccfe9b1SMichel JAOUEN 
4897ccfe9b1SMichel JAOUEN 	return 0;
4907ccfe9b1SMichel JAOUEN }
4917ccfe9b1SMichel JAOUEN 
4927ccfe9b1SMichel JAOUEN static irqreturn_t ab8500_hierarchical_irq(int irq, void *dev)
4937ccfe9b1SMichel JAOUEN {
4947ccfe9b1SMichel JAOUEN 	struct ab8500 *ab8500 = dev;
4957ccfe9b1SMichel JAOUEN 	u8 i;
4967ccfe9b1SMichel JAOUEN 
4977ccfe9b1SMichel JAOUEN 	dev_vdbg(ab8500->dev, "interrupt\n");
4987ccfe9b1SMichel JAOUEN 
4997ccfe9b1SMichel JAOUEN 	/*  Hierarchical interrupt version */
5007ccfe9b1SMichel JAOUEN 	for (i = 0; i < AB8500_IT_LATCHHIER_NUM; i++) {
5017ccfe9b1SMichel JAOUEN 		int status;
5027ccfe9b1SMichel JAOUEN 		u8 hier_val;
5037ccfe9b1SMichel JAOUEN 
5047ccfe9b1SMichel JAOUEN 		status = get_register_interruptible(ab8500, AB8500_INTERRUPT,
5057ccfe9b1SMichel JAOUEN 			AB8500_IT_LATCHHIER1_REG + i, &hier_val);
5067ccfe9b1SMichel JAOUEN 		if (status < 0 || hier_val == 0)
5077ccfe9b1SMichel JAOUEN 			continue;
5087ccfe9b1SMichel JAOUEN 
5097ccfe9b1SMichel JAOUEN 		status = ab8500_handle_hierarchical_latch(ab8500, i, hier_val);
5107ccfe9b1SMichel JAOUEN 		if (status < 0)
5117ccfe9b1SMichel JAOUEN 			break;
5127ccfe9b1SMichel JAOUEN 	}
5137ccfe9b1SMichel JAOUEN 	return IRQ_HANDLED;
5147ccfe9b1SMichel JAOUEN }
5157ccfe9b1SMichel JAOUEN 
51680633f05SLee Jones /**
51780633f05SLee Jones  * ab8500_irq_get_virq(): Map an interrupt on a chip to a virtual IRQ
51880633f05SLee Jones  *
51980633f05SLee Jones  * @ab8500: ab8500_irq controller to operate on.
52080633f05SLee Jones  * @irq: index of the interrupt requested in the chip IRQs
52180633f05SLee Jones  *
52280633f05SLee Jones  * Useful for drivers to request their own IRQs.
52380633f05SLee Jones  */
52480633f05SLee Jones static int ab8500_irq_get_virq(struct ab8500 *ab8500, int irq)
52580633f05SLee Jones {
52680633f05SLee Jones 	if (!ab8500)
52780633f05SLee Jones 		return -EINVAL;
52880633f05SLee Jones 
52980633f05SLee Jones 	return irq_create_mapping(ab8500->domain, irq);
53080633f05SLee Jones }
53180633f05SLee Jones 
53262579266SRabin Vincent static irqreturn_t ab8500_irq(int irq, void *dev)
53362579266SRabin Vincent {
53462579266SRabin Vincent 	struct ab8500 *ab8500 = dev;
53562579266SRabin Vincent 	int i;
53662579266SRabin Vincent 
53762579266SRabin Vincent 	dev_vdbg(ab8500->dev, "interrupt\n");
53862579266SRabin Vincent 
539112a80d2SJonas Aaberg 	atomic_inc(&ab8500->transfer_ongoing);
540112a80d2SJonas Aaberg 
5412ced445eSLinus Walleij 	for (i = 0; i < ab8500->mask_size; i++) {
5422ced445eSLinus Walleij 		int regoffset = ab8500->irq_reg_offset[i];
54362579266SRabin Vincent 		int status;
54447c16975SMattias Wallin 		u8 value;
54562579266SRabin Vincent 
5460f620837SLinus Walleij 		/*
5470f620837SLinus Walleij 		 * Interrupt register 12 doesn't exist prior to AB8500 version
5480f620837SLinus Walleij 		 * 2.0
5490f620837SLinus Walleij 		 */
5500f620837SLinus Walleij 		if (regoffset == 11 && is_ab8500_1p1_or_earlier(ab8500))
55192d50a41SMattias Wallin 			continue;
55292d50a41SMattias Wallin 
55347c16975SMattias Wallin 		status = get_register_interruptible(ab8500, AB8500_INTERRUPT,
55447c16975SMattias Wallin 			AB8500_IT_LATCH1_REG + regoffset, &value);
55547c16975SMattias Wallin 		if (status < 0 || value == 0)
55662579266SRabin Vincent 			continue;
55762579266SRabin Vincent 
55862579266SRabin Vincent 		do {
55988aec4f7SMattias Wallin 			int bit = __ffs(value);
56062579266SRabin Vincent 			int line = i * 8 + bit;
5610a37fc56SLee Jones 			int virq = ab8500_irq_get_virq(ab8500, line);
56262579266SRabin Vincent 
5630a37fc56SLee Jones 			handle_nested_irq(virq);
56447c16975SMattias Wallin 			value &= ~(1 << bit);
565112a80d2SJonas Aaberg 
56647c16975SMattias Wallin 		} while (value);
56762579266SRabin Vincent 	}
568112a80d2SJonas Aaberg 	atomic_dec(&ab8500->transfer_ongoing);
56962579266SRabin Vincent 	return IRQ_HANDLED;
57062579266SRabin Vincent }
57162579266SRabin Vincent 
57206e589efSLee Jones static int ab8500_irq_map(struct irq_domain *d, unsigned int virq,
57306e589efSLee Jones 				irq_hw_number_t hwirq)
57406e589efSLee Jones {
57506e589efSLee Jones 	struct ab8500 *ab8500 = d->host_data;
57606e589efSLee Jones 
57706e589efSLee Jones 	if (!ab8500)
57806e589efSLee Jones 		return -EINVAL;
57906e589efSLee Jones 
58006e589efSLee Jones 	irq_set_chip_data(virq, ab8500);
58106e589efSLee Jones 	irq_set_chip_and_handler(virq, &ab8500_irq_chip,
58206e589efSLee Jones 				handle_simple_irq);
58306e589efSLee Jones 	irq_set_nested_thread(virq, 1);
58406e589efSLee Jones #ifdef CONFIG_ARM
58506e589efSLee Jones 	set_irq_flags(virq, IRQF_VALID);
58606e589efSLee Jones #else
58706e589efSLee Jones 	irq_set_noprobe(virq);
58806e589efSLee Jones #endif
58962579266SRabin Vincent 
59062579266SRabin Vincent 	return 0;
59162579266SRabin Vincent }
59262579266SRabin Vincent 
59306e589efSLee Jones static struct irq_domain_ops ab8500_irq_ops = {
59406e589efSLee Jones         .map    = ab8500_irq_map,
59506e589efSLee Jones         .xlate  = irq_domain_xlate_twocell,
59606e589efSLee Jones };
59706e589efSLee Jones 
59806e589efSLee Jones static int ab8500_irq_init(struct ab8500 *ab8500, struct device_node *np)
59962579266SRabin Vincent {
6002ced445eSLinus Walleij 	int num_irqs;
60162579266SRabin Vincent 
602d6255529SLinus Walleij 	if (is_ab9540(ab8500))
603d6255529SLinus Walleij 		num_irqs = AB9540_NR_IRQS;
604a982362cSBengt Jonsson 	else if (is_ab8505(ab8500))
605a982362cSBengt Jonsson 		num_irqs = AB8505_NR_IRQS;
606d6255529SLinus Walleij 	else
6072ced445eSLinus Walleij 		num_irqs = AB8500_NR_IRQS;
6082ced445eSLinus Walleij 
609f1d11f39SLinus Walleij 	/* If ->irq_base is zero this will give a linear mapping */
610f1d11f39SLinus Walleij 	ab8500->domain = irq_domain_add_simple(NULL,
611f1d11f39SLinus Walleij 			num_irqs, ab8500->irq_base,
612f1d11f39SLinus Walleij 			&ab8500_irq_ops, ab8500);
61306e589efSLee Jones 
61406e589efSLee Jones 	if (!ab8500->domain) {
61506e589efSLee Jones 		dev_err(ab8500->dev, "Failed to create irqdomain\n");
61606e589efSLee Jones 		return -ENOSYS;
61706e589efSLee Jones 	}
61806e589efSLee Jones 
61906e589efSLee Jones 	return 0;
62062579266SRabin Vincent }
62162579266SRabin Vincent 
622112a80d2SJonas Aaberg int ab8500_suspend(struct ab8500 *ab8500)
623112a80d2SJonas Aaberg {
624112a80d2SJonas Aaberg 	if (atomic_read(&ab8500->transfer_ongoing))
625112a80d2SJonas Aaberg 		return -EINVAL;
626112a80d2SJonas Aaberg 	else
627112a80d2SJonas Aaberg 		return 0;
628112a80d2SJonas Aaberg }
629112a80d2SJonas Aaberg 
630a9e9ce4cSBill Pemberton static struct resource ab8500_gpadc_resources[] = {
63162579266SRabin Vincent 	{
63262579266SRabin Vincent 		.name	= "HW_CONV_END",
63362579266SRabin Vincent 		.start	= AB8500_INT_GP_HW_ADC_CONV_END,
63462579266SRabin Vincent 		.end	= AB8500_INT_GP_HW_ADC_CONV_END,
63562579266SRabin Vincent 		.flags	= IORESOURCE_IRQ,
63662579266SRabin Vincent 	},
63762579266SRabin Vincent 	{
63862579266SRabin Vincent 		.name	= "SW_CONV_END",
63962579266SRabin Vincent 		.start	= AB8500_INT_GP_SW_ADC_CONV_END,
64062579266SRabin Vincent 		.end	= AB8500_INT_GP_SW_ADC_CONV_END,
64162579266SRabin Vincent 		.flags	= IORESOURCE_IRQ,
64262579266SRabin Vincent 	},
64362579266SRabin Vincent };
64462579266SRabin Vincent 
645a9e9ce4cSBill Pemberton static struct resource ab8500_rtc_resources[] = {
64662579266SRabin Vincent 	{
64762579266SRabin Vincent 		.name	= "60S",
64862579266SRabin Vincent 		.start	= AB8500_INT_RTC_60S,
64962579266SRabin Vincent 		.end	= AB8500_INT_RTC_60S,
65062579266SRabin Vincent 		.flags	= IORESOURCE_IRQ,
65162579266SRabin Vincent 	},
65262579266SRabin Vincent 	{
65362579266SRabin Vincent 		.name	= "ALARM",
65462579266SRabin Vincent 		.start	= AB8500_INT_RTC_ALARM,
65562579266SRabin Vincent 		.end	= AB8500_INT_RTC_ALARM,
65662579266SRabin Vincent 		.flags	= IORESOURCE_IRQ,
65762579266SRabin Vincent 	},
65862579266SRabin Vincent };
65962579266SRabin Vincent 
660a9e9ce4cSBill Pemberton static struct resource ab8500_poweronkey_db_resources[] = {
66177686517SSundar R Iyer 	{
66277686517SSundar R Iyer 		.name	= "ONKEY_DBF",
66377686517SSundar R Iyer 		.start	= AB8500_INT_PON_KEY1DB_F,
66477686517SSundar R Iyer 		.end	= AB8500_INT_PON_KEY1DB_F,
66577686517SSundar R Iyer 		.flags	= IORESOURCE_IRQ,
66677686517SSundar R Iyer 	},
66777686517SSundar R Iyer 	{
66877686517SSundar R Iyer 		.name	= "ONKEY_DBR",
66977686517SSundar R Iyer 		.start	= AB8500_INT_PON_KEY1DB_R,
67077686517SSundar R Iyer 		.end	= AB8500_INT_PON_KEY1DB_R,
67177686517SSundar R Iyer 		.flags	= IORESOURCE_IRQ,
67277686517SSundar R Iyer 	},
67377686517SSundar R Iyer };
67477686517SSundar R Iyer 
675a9e9ce4cSBill Pemberton static struct resource ab8500_av_acc_detect_resources[] = {
676e098adedSMattias Wallin 	{
6776af75ecdSLinus Walleij 	       .name = "ACC_DETECT_1DB_F",
6786af75ecdSLinus Walleij 	       .start = AB8500_INT_ACC_DETECT_1DB_F,
6796af75ecdSLinus Walleij 	       .end = AB8500_INT_ACC_DETECT_1DB_F,
680e098adedSMattias Wallin 	       .flags = IORESOURCE_IRQ,
681e098adedSMattias Wallin 	},
682e098adedSMattias Wallin 	{
6836af75ecdSLinus Walleij 	       .name = "ACC_DETECT_1DB_R",
6846af75ecdSLinus Walleij 	       .start = AB8500_INT_ACC_DETECT_1DB_R,
6856af75ecdSLinus Walleij 	       .end = AB8500_INT_ACC_DETECT_1DB_R,
686e098adedSMattias Wallin 	       .flags = IORESOURCE_IRQ,
687e098adedSMattias Wallin 	},
688e098adedSMattias Wallin 	{
6896af75ecdSLinus Walleij 	       .name = "ACC_DETECT_21DB_F",
6906af75ecdSLinus Walleij 	       .start = AB8500_INT_ACC_DETECT_21DB_F,
6916af75ecdSLinus Walleij 	       .end = AB8500_INT_ACC_DETECT_21DB_F,
6926af75ecdSLinus Walleij 	       .flags = IORESOURCE_IRQ,
6936af75ecdSLinus Walleij 	},
6946af75ecdSLinus Walleij 	{
6956af75ecdSLinus Walleij 	       .name = "ACC_DETECT_21DB_R",
6966af75ecdSLinus Walleij 	       .start = AB8500_INT_ACC_DETECT_21DB_R,
6976af75ecdSLinus Walleij 	       .end = AB8500_INT_ACC_DETECT_21DB_R,
6986af75ecdSLinus Walleij 	       .flags = IORESOURCE_IRQ,
6996af75ecdSLinus Walleij 	},
7006af75ecdSLinus Walleij 	{
7016af75ecdSLinus Walleij 	       .name = "ACC_DETECT_22DB_F",
7026af75ecdSLinus Walleij 	       .start = AB8500_INT_ACC_DETECT_22DB_F,
7036af75ecdSLinus Walleij 	       .end = AB8500_INT_ACC_DETECT_22DB_F,
7046af75ecdSLinus Walleij 	       .flags = IORESOURCE_IRQ,
7056af75ecdSLinus Walleij 	},
7066af75ecdSLinus Walleij 	{
7076af75ecdSLinus Walleij 	       .name = "ACC_DETECT_22DB_R",
7086af75ecdSLinus Walleij 	       .start = AB8500_INT_ACC_DETECT_22DB_R,
7096af75ecdSLinus Walleij 	       .end = AB8500_INT_ACC_DETECT_22DB_R,
7106af75ecdSLinus Walleij 	       .flags = IORESOURCE_IRQ,
7116af75ecdSLinus Walleij 	},
7126af75ecdSLinus Walleij };
7136af75ecdSLinus Walleij 
714a9e9ce4cSBill Pemberton static struct resource ab8500_charger_resources[] = {
7156af75ecdSLinus Walleij 	{
716e098adedSMattias Wallin 		.name = "MAIN_CH_UNPLUG_DET",
717e098adedSMattias Wallin 		.start = AB8500_INT_MAIN_CH_UNPLUG_DET,
718e098adedSMattias Wallin 		.end = AB8500_INT_MAIN_CH_UNPLUG_DET,
719e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
720e098adedSMattias Wallin 	},
721e098adedSMattias Wallin 	{
722e098adedSMattias Wallin 		.name = "MAIN_CHARGE_PLUG_DET",
723e098adedSMattias Wallin 		.start = AB8500_INT_MAIN_CH_PLUG_DET,
724e098adedSMattias Wallin 		.end = AB8500_INT_MAIN_CH_PLUG_DET,
725e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
726e098adedSMattias Wallin 	},
727e098adedSMattias Wallin 	{
728e098adedSMattias Wallin 		.name = "VBUS_DET_R",
729e098adedSMattias Wallin 		.start = AB8500_INT_VBUS_DET_R,
730e098adedSMattias Wallin 		.end = AB8500_INT_VBUS_DET_R,
731e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
732e098adedSMattias Wallin 	},
733e098adedSMattias Wallin 	{
7346af75ecdSLinus Walleij 		.name = "VBUS_DET_F",
7356af75ecdSLinus Walleij 		.start = AB8500_INT_VBUS_DET_F,
7366af75ecdSLinus Walleij 		.end = AB8500_INT_VBUS_DET_F,
737e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
738e098adedSMattias Wallin 	},
739e098adedSMattias Wallin 	{
7406af75ecdSLinus Walleij 		.name = "USB_LINK_STATUS",
7416af75ecdSLinus Walleij 		.start = AB8500_INT_USB_LINK_STATUS,
7426af75ecdSLinus Walleij 		.end = AB8500_INT_USB_LINK_STATUS,
7436af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
7446af75ecdSLinus Walleij 	},
7456af75ecdSLinus Walleij 	{
746e098adedSMattias Wallin 		.name = "VBUS_OVV",
747e098adedSMattias Wallin 		.start = AB8500_INT_VBUS_OVV,
748e098adedSMattias Wallin 		.end = AB8500_INT_VBUS_OVV,
749e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
750e098adedSMattias Wallin 	},
751e098adedSMattias Wallin 	{
7526af75ecdSLinus Walleij 		.name = "USB_CH_TH_PROT_R",
7536af75ecdSLinus Walleij 		.start = AB8500_INT_USB_CH_TH_PROT_R,
7546af75ecdSLinus Walleij 		.end = AB8500_INT_USB_CH_TH_PROT_R,
755e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
756e098adedSMattias Wallin 	},
757e098adedSMattias Wallin 	{
7586af75ecdSLinus Walleij 		.name = "USB_CH_TH_PROT_F",
7596af75ecdSLinus Walleij 		.start = AB8500_INT_USB_CH_TH_PROT_F,
7606af75ecdSLinus Walleij 		.end = AB8500_INT_USB_CH_TH_PROT_F,
761e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
762e098adedSMattias Wallin 	},
763e098adedSMattias Wallin 	{
7646af75ecdSLinus Walleij 		.name = "MAIN_EXT_CH_NOT_OK",
7656af75ecdSLinus Walleij 		.start = AB8500_INT_MAIN_EXT_CH_NOT_OK,
7666af75ecdSLinus Walleij 		.end = AB8500_INT_MAIN_EXT_CH_NOT_OK,
7676af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
7686af75ecdSLinus Walleij 	},
7696af75ecdSLinus Walleij 	{
7706af75ecdSLinus Walleij 		.name = "MAIN_CH_TH_PROT_R",
7716af75ecdSLinus Walleij 		.start = AB8500_INT_MAIN_CH_TH_PROT_R,
7726af75ecdSLinus Walleij 		.end = AB8500_INT_MAIN_CH_TH_PROT_R,
7736af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
7746af75ecdSLinus Walleij 	},
7756af75ecdSLinus Walleij 	{
7766af75ecdSLinus Walleij 		.name = "MAIN_CH_TH_PROT_F",
7776af75ecdSLinus Walleij 		.start = AB8500_INT_MAIN_CH_TH_PROT_F,
7786af75ecdSLinus Walleij 		.end = AB8500_INT_MAIN_CH_TH_PROT_F,
7796af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
7806af75ecdSLinus Walleij 	},
7816af75ecdSLinus Walleij 	{
7826af75ecdSLinus Walleij 		.name = "USB_CHARGER_NOT_OKR",
783a982362cSBengt Jonsson 		.start = AB8500_INT_USB_CHARGER_NOT_OKR,
784a982362cSBengt Jonsson 		.end = AB8500_INT_USB_CHARGER_NOT_OKR,
7856af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
7866af75ecdSLinus Walleij 	},
7876af75ecdSLinus Walleij 	{
7886af75ecdSLinus Walleij 		.name = "CH_WD_EXP",
7896af75ecdSLinus Walleij 		.start = AB8500_INT_CH_WD_EXP,
7906af75ecdSLinus Walleij 		.end = AB8500_INT_CH_WD_EXP,
7916af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
7926af75ecdSLinus Walleij 	},
7936af75ecdSLinus Walleij };
7946af75ecdSLinus Walleij 
795a9e9ce4cSBill Pemberton static struct resource ab8500_btemp_resources[] = {
7966af75ecdSLinus Walleij 	{
7976af75ecdSLinus Walleij 		.name = "BAT_CTRL_INDB",
7986af75ecdSLinus Walleij 		.start = AB8500_INT_BAT_CTRL_INDB,
7996af75ecdSLinus Walleij 		.end = AB8500_INT_BAT_CTRL_INDB,
800e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
801e098adedSMattias Wallin 	},
802e098adedSMattias Wallin 	{
803e098adedSMattias Wallin 		.name = "BTEMP_LOW",
804e098adedSMattias Wallin 		.start = AB8500_INT_BTEMP_LOW,
805e098adedSMattias Wallin 		.end = AB8500_INT_BTEMP_LOW,
806e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
807e098adedSMattias Wallin 	},
808e098adedSMattias Wallin 	{
809e098adedSMattias Wallin 		.name = "BTEMP_HIGH",
810e098adedSMattias Wallin 		.start = AB8500_INT_BTEMP_HIGH,
811e098adedSMattias Wallin 		.end = AB8500_INT_BTEMP_HIGH,
812e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
813e098adedSMattias Wallin 	},
814e098adedSMattias Wallin 	{
8156af75ecdSLinus Walleij 		.name = "BTEMP_LOW_MEDIUM",
8166af75ecdSLinus Walleij 		.start = AB8500_INT_BTEMP_LOW_MEDIUM,
8176af75ecdSLinus Walleij 		.end = AB8500_INT_BTEMP_LOW_MEDIUM,
818e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
819e098adedSMattias Wallin 	},
820e098adedSMattias Wallin 	{
8216af75ecdSLinus Walleij 		.name = "BTEMP_MEDIUM_HIGH",
8226af75ecdSLinus Walleij 		.start = AB8500_INT_BTEMP_MEDIUM_HIGH,
8236af75ecdSLinus Walleij 		.end = AB8500_INT_BTEMP_MEDIUM_HIGH,
824e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
825e098adedSMattias Wallin 	},
826e098adedSMattias Wallin };
827e098adedSMattias Wallin 
828a9e9ce4cSBill Pemberton static struct resource ab8500_fg_resources[] = {
8296af75ecdSLinus Walleij 	{
8306af75ecdSLinus Walleij 		.name = "NCONV_ACCU",
8316af75ecdSLinus Walleij 		.start = AB8500_INT_CCN_CONV_ACC,
8326af75ecdSLinus Walleij 		.end = AB8500_INT_CCN_CONV_ACC,
8336af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
8346af75ecdSLinus Walleij 	},
8356af75ecdSLinus Walleij 	{
8366af75ecdSLinus Walleij 		.name = "BATT_OVV",
8376af75ecdSLinus Walleij 		.start = AB8500_INT_BATT_OVV,
8386af75ecdSLinus Walleij 		.end = AB8500_INT_BATT_OVV,
8396af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
8406af75ecdSLinus Walleij 	},
8416af75ecdSLinus Walleij 	{
8426af75ecdSLinus Walleij 		.name = "LOW_BAT_F",
8436af75ecdSLinus Walleij 		.start = AB8500_INT_LOW_BAT_F,
8446af75ecdSLinus Walleij 		.end = AB8500_INT_LOW_BAT_F,
8456af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
8466af75ecdSLinus Walleij 	},
8476af75ecdSLinus Walleij 	{
8486af75ecdSLinus Walleij 		.name = "LOW_BAT_R",
8496af75ecdSLinus Walleij 		.start = AB8500_INT_LOW_BAT_R,
8506af75ecdSLinus Walleij 		.end = AB8500_INT_LOW_BAT_R,
8516af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
8526af75ecdSLinus Walleij 	},
8536af75ecdSLinus Walleij 	{
8546af75ecdSLinus Walleij 		.name = "CC_INT_CALIB",
8556af75ecdSLinus Walleij 		.start = AB8500_INT_CC_INT_CALIB,
8566af75ecdSLinus Walleij 		.end = AB8500_INT_CC_INT_CALIB,
8576af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
8586af75ecdSLinus Walleij 	},
859a982362cSBengt Jonsson 	{
860a982362cSBengt Jonsson 		.name = "CCEOC",
861a982362cSBengt Jonsson 		.start = AB8500_INT_CCEOC,
862a982362cSBengt Jonsson 		.end = AB8500_INT_CCEOC,
863a982362cSBengt Jonsson 		.flags = IORESOURCE_IRQ,
864a982362cSBengt Jonsson 	},
8656af75ecdSLinus Walleij };
8666af75ecdSLinus Walleij 
867a9e9ce4cSBill Pemberton static struct resource ab8500_chargalg_resources[] = {};
8686af75ecdSLinus Walleij 
869df720647SAxel Lin #ifdef CONFIG_DEBUG_FS
870a9e9ce4cSBill Pemberton static struct resource ab8500_debug_resources[] = {
871e098adedSMattias Wallin 	{
872e098adedSMattias Wallin 		.name	= "IRQ_FIRST",
873e098adedSMattias Wallin 		.start	= AB8500_INT_MAIN_EXT_CH_NOT_OK,
874e098adedSMattias Wallin 		.end	= AB8500_INT_MAIN_EXT_CH_NOT_OK,
875e098adedSMattias Wallin 		.flags	= IORESOURCE_IRQ,
876e098adedSMattias Wallin 	},
877e098adedSMattias Wallin 	{
878e098adedSMattias Wallin 		.name	= "IRQ_LAST",
879a982362cSBengt Jonsson 		.start	= AB8500_INT_XTAL32K_KO,
880a982362cSBengt Jonsson 		.end	= AB8500_INT_XTAL32K_KO,
881e098adedSMattias Wallin 		.flags	= IORESOURCE_IRQ,
882e098adedSMattias Wallin 	},
883e098adedSMattias Wallin };
884df720647SAxel Lin #endif
885e098adedSMattias Wallin 
886a9e9ce4cSBill Pemberton static struct resource ab8500_usb_resources[] = {
887e098adedSMattias Wallin 	{
888e098adedSMattias Wallin 		.name = "ID_WAKEUP_R",
889e098adedSMattias Wallin 		.start = AB8500_INT_ID_WAKEUP_R,
890e098adedSMattias Wallin 		.end = AB8500_INT_ID_WAKEUP_R,
891e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
892e098adedSMattias Wallin 	},
893e098adedSMattias Wallin 	{
894e098adedSMattias Wallin 		.name = "ID_WAKEUP_F",
895e098adedSMattias Wallin 		.start = AB8500_INT_ID_WAKEUP_F,
896e098adedSMattias Wallin 		.end = AB8500_INT_ID_WAKEUP_F,
897e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
898e098adedSMattias Wallin 	},
899e098adedSMattias Wallin 	{
900e098adedSMattias Wallin 		.name = "VBUS_DET_F",
901e098adedSMattias Wallin 		.start = AB8500_INT_VBUS_DET_F,
902e098adedSMattias Wallin 		.end = AB8500_INT_VBUS_DET_F,
903e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
904e098adedSMattias Wallin 	},
905e098adedSMattias Wallin 	{
906e098adedSMattias Wallin 		.name = "VBUS_DET_R",
907e098adedSMattias Wallin 		.start = AB8500_INT_VBUS_DET_R,
908e098adedSMattias Wallin 		.end = AB8500_INT_VBUS_DET_R,
909e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
910e098adedSMattias Wallin 	},
91192d50a41SMattias Wallin 	{
91292d50a41SMattias Wallin 		.name = "USB_LINK_STATUS",
91392d50a41SMattias Wallin 		.start = AB8500_INT_USB_LINK_STATUS,
91492d50a41SMattias Wallin 		.end = AB8500_INT_USB_LINK_STATUS,
91592d50a41SMattias Wallin 		.flags = IORESOURCE_IRQ,
91692d50a41SMattias Wallin 	},
9176af75ecdSLinus Walleij 	{
9186af75ecdSLinus Walleij 		.name = "USB_ADP_PROBE_PLUG",
9196af75ecdSLinus Walleij 		.start = AB8500_INT_ADP_PROBE_PLUG,
9206af75ecdSLinus Walleij 		.end = AB8500_INT_ADP_PROBE_PLUG,
9216af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
9226af75ecdSLinus Walleij 	},
9236af75ecdSLinus Walleij 	{
9246af75ecdSLinus Walleij 		.name = "USB_ADP_PROBE_UNPLUG",
9256af75ecdSLinus Walleij 		.start = AB8500_INT_ADP_PROBE_UNPLUG,
9266af75ecdSLinus Walleij 		.end = AB8500_INT_ADP_PROBE_UNPLUG,
9276af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
9286af75ecdSLinus Walleij 	},
929e098adedSMattias Wallin };
930e098adedSMattias Wallin 
931a9e9ce4cSBill Pemberton static struct resource ab8505_iddet_resources[] = {
93244f72e53SVirupax Sadashivpetimath 	{
93344f72e53SVirupax Sadashivpetimath 		.name  = "KeyDeglitch",
93444f72e53SVirupax Sadashivpetimath 		.start = AB8505_INT_KEYDEGLITCH,
93544f72e53SVirupax Sadashivpetimath 		.end   = AB8505_INT_KEYDEGLITCH,
93644f72e53SVirupax Sadashivpetimath 		.flags = IORESOURCE_IRQ,
93744f72e53SVirupax Sadashivpetimath 	},
93844f72e53SVirupax Sadashivpetimath 	{
93944f72e53SVirupax Sadashivpetimath 		.name  = "KP",
94044f72e53SVirupax Sadashivpetimath 		.start = AB8505_INT_KP,
94144f72e53SVirupax Sadashivpetimath 		.end   = AB8505_INT_KP,
94244f72e53SVirupax Sadashivpetimath 		.flags = IORESOURCE_IRQ,
94344f72e53SVirupax Sadashivpetimath 	},
94444f72e53SVirupax Sadashivpetimath 	{
94544f72e53SVirupax Sadashivpetimath 		.name  = "IKP",
94644f72e53SVirupax Sadashivpetimath 		.start = AB8505_INT_IKP,
94744f72e53SVirupax Sadashivpetimath 		.end   = AB8505_INT_IKP,
94844f72e53SVirupax Sadashivpetimath 		.flags = IORESOURCE_IRQ,
94944f72e53SVirupax Sadashivpetimath 	},
95044f72e53SVirupax Sadashivpetimath 	{
95144f72e53SVirupax Sadashivpetimath 		.name  = "IKR",
95244f72e53SVirupax Sadashivpetimath 		.start = AB8505_INT_IKR,
95344f72e53SVirupax Sadashivpetimath 		.end   = AB8505_INT_IKR,
95444f72e53SVirupax Sadashivpetimath 		.flags = IORESOURCE_IRQ,
95544f72e53SVirupax Sadashivpetimath 	},
95644f72e53SVirupax Sadashivpetimath 	{
95744f72e53SVirupax Sadashivpetimath 		.name  = "KeyStuck",
95844f72e53SVirupax Sadashivpetimath 		.start = AB8505_INT_KEYSTUCK,
95944f72e53SVirupax Sadashivpetimath 		.end   = AB8505_INT_KEYSTUCK,
96044f72e53SVirupax Sadashivpetimath 		.flags = IORESOURCE_IRQ,
96144f72e53SVirupax Sadashivpetimath 	},
96244f72e53SVirupax Sadashivpetimath };
96344f72e53SVirupax Sadashivpetimath 
964a9e9ce4cSBill Pemberton static struct resource ab8500_temp_resources[] = {
965e098adedSMattias Wallin 	{
966e098adedSMattias Wallin 		.name  = "AB8500_TEMP_WARM",
967e098adedSMattias Wallin 		.start = AB8500_INT_TEMP_WARM,
968e098adedSMattias Wallin 		.end   = AB8500_INT_TEMP_WARM,
969e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
970e098adedSMattias Wallin 	},
971e098adedSMattias Wallin };
972e098adedSMattias Wallin 
973a9e9ce4cSBill Pemberton static struct mfd_cell abx500_common_devs[] = {
9745814fc35SMattias Wallin #ifdef CONFIG_DEBUG_FS
9755814fc35SMattias Wallin 	{
9765814fc35SMattias Wallin 		.name = "ab8500-debug",
977bad76991SLee Jones 		.of_compatible = "stericsson,ab8500-debug",
978e098adedSMattias Wallin 		.num_resources = ARRAY_SIZE(ab8500_debug_resources),
979e098adedSMattias Wallin 		.resources = ab8500_debug_resources,
9805814fc35SMattias Wallin 	},
9815814fc35SMattias Wallin #endif
98262579266SRabin Vincent 	{
983e098adedSMattias Wallin 		.name = "ab8500-sysctrl",
984bad76991SLee Jones 		.of_compatible = "stericsson,ab8500-sysctrl",
985e098adedSMattias Wallin 	},
986e098adedSMattias Wallin 	{
987e098adedSMattias Wallin 		.name = "ab8500-regulator",
988bad76991SLee Jones 		.of_compatible = "stericsson,ab8500-regulator",
989e098adedSMattias Wallin 	},
990e098adedSMattias Wallin 	{
991916a871cSUlf Hansson 		.name = "abx500-clk",
992916a871cSUlf Hansson 		.of_compatible = "stericsson,abx500-clk",
993916a871cSUlf Hansson 	},
994916a871cSUlf Hansson 	{
99562579266SRabin Vincent 		.name = "ab8500-gpadc",
996bad76991SLee Jones 		.of_compatible = "stericsson,ab8500-gpadc",
99762579266SRabin Vincent 		.num_resources = ARRAY_SIZE(ab8500_gpadc_resources),
99862579266SRabin Vincent 		.resources = ab8500_gpadc_resources,
99962579266SRabin Vincent 	},
100062579266SRabin Vincent 	{
100162579266SRabin Vincent 		.name = "ab8500-rtc",
1002bad76991SLee Jones 		.of_compatible = "stericsson,ab8500-rtc",
100362579266SRabin Vincent 		.num_resources = ARRAY_SIZE(ab8500_rtc_resources),
100462579266SRabin Vincent 		.resources = ab8500_rtc_resources,
100562579266SRabin Vincent 	},
1006f0f05b1cSArun Murthy 	{
10076af75ecdSLinus Walleij 		.name = "ab8500-acc-det",
1008bad76991SLee Jones 		.of_compatible = "stericsson,ab8500-acc-det",
10096af75ecdSLinus Walleij 		.num_resources = ARRAY_SIZE(ab8500_av_acc_detect_resources),
10106af75ecdSLinus Walleij 		.resources = ab8500_av_acc_detect_resources,
10116af75ecdSLinus Walleij 	},
10126af75ecdSLinus Walleij 	{
1013e098adedSMattias Wallin 		.name = "ab8500-poweron-key",
1014bad76991SLee Jones 		.of_compatible = "stericsson,ab8500-poweron-key",
1015e098adedSMattias Wallin 		.num_resources = ARRAY_SIZE(ab8500_poweronkey_db_resources),
1016e098adedSMattias Wallin 		.resources = ab8500_poweronkey_db_resources,
1017e098adedSMattias Wallin 	},
1018e098adedSMattias Wallin 	{
1019f0f05b1cSArun Murthy 		.name = "ab8500-pwm",
1020bad76991SLee Jones 		.of_compatible = "stericsson,ab8500-pwm",
1021f0f05b1cSArun Murthy 		.id = 1,
1022f0f05b1cSArun Murthy 	},
1023f0f05b1cSArun Murthy 	{
1024f0f05b1cSArun Murthy 		.name = "ab8500-pwm",
1025bad76991SLee Jones 		.of_compatible = "stericsson,ab8500-pwm",
1026f0f05b1cSArun Murthy 		.id = 2,
1027f0f05b1cSArun Murthy 	},
1028f0f05b1cSArun Murthy 	{
1029f0f05b1cSArun Murthy 		.name = "ab8500-pwm",
1030bad76991SLee Jones 		.of_compatible = "stericsson,ab8500-pwm",
1031f0f05b1cSArun Murthy 		.id = 3,
1032f0f05b1cSArun Murthy 	},
1033bad76991SLee Jones 	{
1034bad76991SLee Jones 		.name = "ab8500-leds",
1035bad76991SLee Jones 		.of_compatible = "stericsson,ab8500-leds",
1036bad76991SLee Jones 	},
103777686517SSundar R Iyer 	{
1038e098adedSMattias Wallin 		.name = "ab8500-denc",
1039bad76991SLee Jones 		.of_compatible = "stericsson,ab8500-denc",
1040e098adedSMattias Wallin 	},
1041e098adedSMattias Wallin 	{
1042e098adedSMattias Wallin 		.name = "ab8500-temp",
1043bad76991SLee Jones 		.of_compatible = "stericsson,ab8500-temp",
1044e098adedSMattias Wallin 		.num_resources = ARRAY_SIZE(ab8500_temp_resources),
1045e098adedSMattias Wallin 		.resources = ab8500_temp_resources,
104677686517SSundar R Iyer 	},
104762579266SRabin Vincent };
104862579266SRabin Vincent 
1049a9e9ce4cSBill Pemberton static struct mfd_cell ab8500_bm_devs[] = {
10506ef9418cSRickard Andersson 	{
10516ef9418cSRickard Andersson 		.name = "ab8500-charger",
10524aef72dbSRajanikanth H.V 		.of_compatible = "stericsson,ab8500-charger",
10536ef9418cSRickard Andersson 		.num_resources = ARRAY_SIZE(ab8500_charger_resources),
10546ef9418cSRickard Andersson 		.resources = ab8500_charger_resources,
10554aef72dbSRajanikanth H.V #ifndef CONFIG_OF
10564aef72dbSRajanikanth H.V 		.platform_data = &ab8500_bm_data,
10574aef72dbSRajanikanth H.V 		.pdata_size = sizeof(ab8500_bm_data),
10584aef72dbSRajanikanth H.V #endif
10596ef9418cSRickard Andersson 	},
10606ef9418cSRickard Andersson 	{
10616ef9418cSRickard Andersson 		.name = "ab8500-btemp",
1062bd9e8ab2SRajanikanth H.V 		.of_compatible = "stericsson,ab8500-btemp",
10636ef9418cSRickard Andersson 		.num_resources = ARRAY_SIZE(ab8500_btemp_resources),
10646ef9418cSRickard Andersson 		.resources = ab8500_btemp_resources,
1065bd9e8ab2SRajanikanth H.V #ifndef CONFIG_OF
1066bd9e8ab2SRajanikanth H.V 		.platform_data = &ab8500_bm_data,
1067bd9e8ab2SRajanikanth H.V 		.pdata_size = sizeof(ab8500_bm_data),
1068bd9e8ab2SRajanikanth H.V #endif
10696ef9418cSRickard Andersson 	},
10706ef9418cSRickard Andersson 	{
10716ef9418cSRickard Andersson 		.name = "ab8500-fg",
1072e0f1abebSRajanikanth H.V 		.of_compatible = "stericsson,ab8500-fg",
10736ef9418cSRickard Andersson 		.num_resources = ARRAY_SIZE(ab8500_fg_resources),
10746ef9418cSRickard Andersson 		.resources = ab8500_fg_resources,
1075e0f1abebSRajanikanth H.V #ifndef CONFIG_OF
1076e0f1abebSRajanikanth H.V 		.platform_data = &ab8500_bm_data,
1077e0f1abebSRajanikanth H.V 		.pdata_size = sizeof(ab8500_bm_data),
1078e0f1abebSRajanikanth H.V #endif
10796ef9418cSRickard Andersson 	},
10806ef9418cSRickard Andersson 	{
10816ef9418cSRickard Andersson 		.name = "ab8500-chargalg",
1082a12810abSRajanikanth H.V 		.of_compatible = "stericsson,ab8500-chargalg",
10836ef9418cSRickard Andersson 		.num_resources = ARRAY_SIZE(ab8500_chargalg_resources),
10846ef9418cSRickard Andersson 		.resources = ab8500_chargalg_resources,
1085a12810abSRajanikanth H.V #ifndef CONFIG_OF
1086a12810abSRajanikanth H.V 		.platform_data = &ab8500_bm_data,
1087a12810abSRajanikanth H.V 		.pdata_size = sizeof(ab8500_bm_data),
1088a12810abSRajanikanth H.V #endif
10896ef9418cSRickard Andersson 	},
10906ef9418cSRickard Andersson };
10916ef9418cSRickard Andersson 
1092a9e9ce4cSBill Pemberton static struct mfd_cell ab8500_devs[] = {
1093d6255529SLinus Walleij 	{
1094d6255529SLinus Walleij 		.name = "ab8500-gpio",
1095bad76991SLee Jones 		.of_compatible = "stericsson,ab8500-gpio",
1096d6255529SLinus Walleij 	},
1097d6255529SLinus Walleij 	{
1098d6255529SLinus Walleij 		.name = "ab8500-usb",
1099bad76991SLee Jones 		.of_compatible = "stericsson,ab8500-usb",
1100d6255529SLinus Walleij 		.num_resources = ARRAY_SIZE(ab8500_usb_resources),
1101d6255529SLinus Walleij 		.resources = ab8500_usb_resources,
1102d6255529SLinus Walleij 	},
110344f72e53SVirupax Sadashivpetimath 	{
110444f72e53SVirupax Sadashivpetimath 		.name = "ab8500-codec",
110581a21cddSLee Jones 		.of_compatible = "stericsson,ab8500-codec",
110644f72e53SVirupax Sadashivpetimath 	},
1107d6255529SLinus Walleij };
1108d6255529SLinus Walleij 
1109a9e9ce4cSBill Pemberton static struct mfd_cell ab9540_devs[] = {
1110d6255529SLinus Walleij 	{
1111d6255529SLinus Walleij 		.name = "ab8500-gpio",
1112d6255529SLinus Walleij 	},
1113d6255529SLinus Walleij 	{
1114d6255529SLinus Walleij 		.name = "ab9540-usb",
1115d6255529SLinus Walleij 		.num_resources = ARRAY_SIZE(ab8500_usb_resources),
1116d6255529SLinus Walleij 		.resources = ab8500_usb_resources,
1117d6255529SLinus Walleij 	},
111844f72e53SVirupax Sadashivpetimath 	{
111944f72e53SVirupax Sadashivpetimath 		.name = "ab9540-codec",
112044f72e53SVirupax Sadashivpetimath 	},
112144f72e53SVirupax Sadashivpetimath };
112244f72e53SVirupax Sadashivpetimath 
112344f72e53SVirupax Sadashivpetimath /* Device list common to ab9540 and ab8505 */
1124a9e9ce4cSBill Pemberton static struct mfd_cell ab9540_ab8505_devs[] = {
112544f72e53SVirupax Sadashivpetimath 	{
112644f72e53SVirupax Sadashivpetimath 		.name = "ab-iddet",
112744f72e53SVirupax Sadashivpetimath 		.num_resources = ARRAY_SIZE(ab8505_iddet_resources),
112844f72e53SVirupax Sadashivpetimath 		.resources = ab8505_iddet_resources,
112944f72e53SVirupax Sadashivpetimath 	},
1130d6255529SLinus Walleij };
1131d6255529SLinus Walleij 
1132cca69b67SMattias Wallin static ssize_t show_chip_id(struct device *dev,
1133cca69b67SMattias Wallin 				struct device_attribute *attr, char *buf)
1134cca69b67SMattias Wallin {
1135cca69b67SMattias Wallin 	struct ab8500 *ab8500;
1136cca69b67SMattias Wallin 
1137cca69b67SMattias Wallin 	ab8500 = dev_get_drvdata(dev);
1138cca69b67SMattias Wallin 	return sprintf(buf, "%#x\n", ab8500 ? ab8500->chip_id : -EINVAL);
1139cca69b67SMattias Wallin }
1140cca69b67SMattias Wallin 
1141e5c238c3SMattias Wallin /*
1142e5c238c3SMattias Wallin  * ab8500 has switched off due to (SWITCH_OFF_STATUS):
1143e5c238c3SMattias Wallin  * 0x01 Swoff bit programming
1144e5c238c3SMattias Wallin  * 0x02 Thermal protection activation
1145e5c238c3SMattias Wallin  * 0x04 Vbat lower then BattOk falling threshold
1146e5c238c3SMattias Wallin  * 0x08 Watchdog expired
1147e5c238c3SMattias Wallin  * 0x10 Non presence of 32kHz clock
1148e5c238c3SMattias Wallin  * 0x20 Battery level lower than power on reset threshold
1149e5c238c3SMattias Wallin  * 0x40 Power on key 1 pressed longer than 10 seconds
1150e5c238c3SMattias Wallin  * 0x80 DB8500 thermal shutdown
1151e5c238c3SMattias Wallin  */
1152e5c238c3SMattias Wallin static ssize_t show_switch_off_status(struct device *dev,
1153e5c238c3SMattias Wallin 				struct device_attribute *attr, char *buf)
1154e5c238c3SMattias Wallin {
1155e5c238c3SMattias Wallin 	int ret;
1156e5c238c3SMattias Wallin 	u8 value;
1157e5c238c3SMattias Wallin 	struct ab8500 *ab8500;
1158e5c238c3SMattias Wallin 
1159e5c238c3SMattias Wallin 	ab8500 = dev_get_drvdata(dev);
1160e5c238c3SMattias Wallin 	ret = get_register_interruptible(ab8500, AB8500_RTC,
1161e5c238c3SMattias Wallin 		AB8500_SWITCH_OFF_STATUS, &value);
1162e5c238c3SMattias Wallin 	if (ret < 0)
1163e5c238c3SMattias Wallin 		return ret;
1164e5c238c3SMattias Wallin 	return sprintf(buf, "%#x\n", value);
1165e5c238c3SMattias Wallin }
1166e5c238c3SMattias Wallin 
1167b4a31037SAndrew Lynn /*
1168b4a31037SAndrew Lynn  * ab8500 has turned on due to (TURN_ON_STATUS):
1169b4a31037SAndrew Lynn  * 0x01 PORnVbat
1170b4a31037SAndrew Lynn  * 0x02 PonKey1dbF
1171b4a31037SAndrew Lynn  * 0x04 PonKey2dbF
1172b4a31037SAndrew Lynn  * 0x08 RTCAlarm
1173b4a31037SAndrew Lynn  * 0x10 MainChDet
1174b4a31037SAndrew Lynn  * 0x20 VbusDet
1175b4a31037SAndrew Lynn  * 0x40 UsbIDDetect
1176b4a31037SAndrew Lynn  * 0x80 Reserved
1177b4a31037SAndrew Lynn  */
1178b4a31037SAndrew Lynn static ssize_t show_turn_on_status(struct device *dev,
1179b4a31037SAndrew Lynn 				struct device_attribute *attr, char *buf)
1180b4a31037SAndrew Lynn {
1181b4a31037SAndrew Lynn 	int ret;
1182b4a31037SAndrew Lynn 	u8 value;
1183b4a31037SAndrew Lynn 	struct ab8500 *ab8500;
1184b4a31037SAndrew Lynn 
1185b4a31037SAndrew Lynn 	ab8500 = dev_get_drvdata(dev);
1186b4a31037SAndrew Lynn 	ret = get_register_interruptible(ab8500, AB8500_SYS_CTRL1_BLOCK,
1187b4a31037SAndrew Lynn 		AB8500_TURN_ON_STATUS, &value);
1188b4a31037SAndrew Lynn 	if (ret < 0)
1189b4a31037SAndrew Lynn 		return ret;
1190b4a31037SAndrew Lynn 	return sprintf(buf, "%#x\n", value);
1191b4a31037SAndrew Lynn }
1192b4a31037SAndrew Lynn 
1193d6255529SLinus Walleij static ssize_t show_ab9540_dbbrstn(struct device *dev,
1194d6255529SLinus Walleij 				struct device_attribute *attr, char *buf)
1195d6255529SLinus Walleij {
1196d6255529SLinus Walleij 	struct ab8500 *ab8500;
1197d6255529SLinus Walleij 	int ret;
1198d6255529SLinus Walleij 	u8 value;
1199d6255529SLinus Walleij 
1200d6255529SLinus Walleij 	ab8500 = dev_get_drvdata(dev);
1201d6255529SLinus Walleij 
1202d6255529SLinus Walleij 	ret = get_register_interruptible(ab8500, AB8500_REGU_CTRL2,
1203d6255529SLinus Walleij 		AB9540_MODEM_CTRL2_REG, &value);
1204d6255529SLinus Walleij 	if (ret < 0)
1205d6255529SLinus Walleij 		return ret;
1206d6255529SLinus Walleij 
1207d6255529SLinus Walleij 	return sprintf(buf, "%d\n",
1208d6255529SLinus Walleij 			(value & AB9540_MODEM_CTRL2_SWDBBRSTN_BIT) ? 1 : 0);
1209d6255529SLinus Walleij }
1210d6255529SLinus Walleij 
1211d6255529SLinus Walleij static ssize_t store_ab9540_dbbrstn(struct device *dev,
1212d6255529SLinus Walleij 	struct device_attribute *attr, const char *buf, size_t count)
1213d6255529SLinus Walleij {
1214d6255529SLinus Walleij 	struct ab8500 *ab8500;
1215d6255529SLinus Walleij 	int ret = count;
1216d6255529SLinus Walleij 	int err;
1217d6255529SLinus Walleij 	u8 bitvalues;
1218d6255529SLinus Walleij 
1219d6255529SLinus Walleij 	ab8500 = dev_get_drvdata(dev);
1220d6255529SLinus Walleij 
1221d6255529SLinus Walleij 	if (count > 0) {
1222d6255529SLinus Walleij 		switch (buf[0]) {
1223d6255529SLinus Walleij 		case '0':
1224d6255529SLinus Walleij 			bitvalues = 0;
1225d6255529SLinus Walleij 			break;
1226d6255529SLinus Walleij 		case '1':
1227d6255529SLinus Walleij 			bitvalues = AB9540_MODEM_CTRL2_SWDBBRSTN_BIT;
1228d6255529SLinus Walleij 			break;
1229d6255529SLinus Walleij 		default:
1230d6255529SLinus Walleij 			goto exit;
1231d6255529SLinus Walleij 		}
1232d6255529SLinus Walleij 
1233d6255529SLinus Walleij 		err = mask_and_set_register_interruptible(ab8500,
1234d6255529SLinus Walleij 			AB8500_REGU_CTRL2, AB9540_MODEM_CTRL2_REG,
1235d6255529SLinus Walleij 			AB9540_MODEM_CTRL2_SWDBBRSTN_BIT, bitvalues);
1236d6255529SLinus Walleij 		if (err)
1237d6255529SLinus Walleij 			dev_info(ab8500->dev,
1238d6255529SLinus Walleij 				"Failed to set DBBRSTN %c, err %#x\n",
1239d6255529SLinus Walleij 				buf[0], err);
1240d6255529SLinus Walleij 	}
1241d6255529SLinus Walleij 
1242d6255529SLinus Walleij exit:
1243d6255529SLinus Walleij 	return ret;
1244d6255529SLinus Walleij }
1245d6255529SLinus Walleij 
1246cca69b67SMattias Wallin static DEVICE_ATTR(chip_id, S_IRUGO, show_chip_id, NULL);
1247e5c238c3SMattias Wallin static DEVICE_ATTR(switch_off_status, S_IRUGO, show_switch_off_status, NULL);
1248b4a31037SAndrew Lynn static DEVICE_ATTR(turn_on_status, S_IRUGO, show_turn_on_status, NULL);
1249d6255529SLinus Walleij static DEVICE_ATTR(dbbrstn, S_IRUGO | S_IWUSR,
1250d6255529SLinus Walleij 			show_ab9540_dbbrstn, store_ab9540_dbbrstn);
1251cca69b67SMattias Wallin 
1252cca69b67SMattias Wallin static struct attribute *ab8500_sysfs_entries[] = {
1253cca69b67SMattias Wallin 	&dev_attr_chip_id.attr,
1254e5c238c3SMattias Wallin 	&dev_attr_switch_off_status.attr,
1255b4a31037SAndrew Lynn 	&dev_attr_turn_on_status.attr,
1256cca69b67SMattias Wallin 	NULL,
1257cca69b67SMattias Wallin };
1258cca69b67SMattias Wallin 
1259d6255529SLinus Walleij static struct attribute *ab9540_sysfs_entries[] = {
1260d6255529SLinus Walleij 	&dev_attr_chip_id.attr,
1261d6255529SLinus Walleij 	&dev_attr_switch_off_status.attr,
1262d6255529SLinus Walleij 	&dev_attr_turn_on_status.attr,
1263d6255529SLinus Walleij 	&dev_attr_dbbrstn.attr,
1264d6255529SLinus Walleij 	NULL,
1265d6255529SLinus Walleij };
1266d6255529SLinus Walleij 
1267cca69b67SMattias Wallin static struct attribute_group ab8500_attr_group = {
1268cca69b67SMattias Wallin 	.attrs	= ab8500_sysfs_entries,
1269cca69b67SMattias Wallin };
1270cca69b67SMattias Wallin 
1271d6255529SLinus Walleij static struct attribute_group ab9540_attr_group = {
1272d6255529SLinus Walleij 	.attrs	= ab9540_sysfs_entries,
1273d6255529SLinus Walleij };
1274d6255529SLinus Walleij 
1275f791be49SBill Pemberton static int ab8500_probe(struct platform_device *pdev)
127662579266SRabin Vincent {
1277b04c530cSJonas Aaberg 	static char *switch_off_status[] = {
1278b04c530cSJonas Aaberg 		"Swoff bit programming",
1279b04c530cSJonas Aaberg 		"Thermal protection activation",
1280b04c530cSJonas Aaberg 		"Vbat lower then BattOk falling threshold",
1281b04c530cSJonas Aaberg 		"Watchdog expired",
1282b04c530cSJonas Aaberg 		"Non presence of 32kHz clock",
1283b04c530cSJonas Aaberg 		"Battery level lower than power on reset threshold",
1284b04c530cSJonas Aaberg 		"Power on key 1 pressed longer than 10 seconds",
1285b04c530cSJonas Aaberg 		"DB8500 thermal shutdown"};
1286d28f1db8SLee Jones 	struct ab8500_platform_data *plat = dev_get_platdata(&pdev->dev);
1287d28f1db8SLee Jones 	const struct platform_device_id *platid = platform_get_device_id(pdev);
12886bc4a568SLee Jones 	enum ab8500_version version = AB8500_VERSION_UNDEFINED;
12896bc4a568SLee Jones 	struct device_node *np = pdev->dev.of_node;
1290d28f1db8SLee Jones 	struct ab8500 *ab8500;
1291d28f1db8SLee Jones 	struct resource *resource;
129262579266SRabin Vincent 	int ret;
129362579266SRabin Vincent 	int i;
129447c16975SMattias Wallin 	u8 value;
129562579266SRabin Vincent 
12968c4203cbSLee Jones 	ab8500 = devm_kzalloc(&pdev->dev, sizeof *ab8500, GFP_KERNEL);
1297d28f1db8SLee Jones 	if (!ab8500)
1298d28f1db8SLee Jones 		return -ENOMEM;
1299d28f1db8SLee Jones 
130062579266SRabin Vincent 	if (plat)
130162579266SRabin Vincent 		ab8500->irq_base = plat->irq_base;
130262579266SRabin Vincent 
1303d28f1db8SLee Jones 	ab8500->dev = &pdev->dev;
1304d28f1db8SLee Jones 
1305d28f1db8SLee Jones 	resource = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
13068c4203cbSLee Jones 	if (!resource)
13078c4203cbSLee Jones 		return -ENODEV;
1308d28f1db8SLee Jones 
1309d28f1db8SLee Jones 	ab8500->irq = resource->start;
1310d28f1db8SLee Jones 
1311822672a7SLee Jones 	ab8500->read = ab8500_prcmu_read;
1312822672a7SLee Jones 	ab8500->write = ab8500_prcmu_write;
1313822672a7SLee Jones 	ab8500->write_masked = ab8500_prcmu_write_masked;
1314d28f1db8SLee Jones 
131562579266SRabin Vincent 	mutex_init(&ab8500->lock);
131662579266SRabin Vincent 	mutex_init(&ab8500->irq_lock);
1317112a80d2SJonas Aaberg 	atomic_set(&ab8500->transfer_ongoing, 0);
131862579266SRabin Vincent 
1319d28f1db8SLee Jones 	platform_set_drvdata(pdev, ab8500);
1320d28f1db8SLee Jones 
13216bc4a568SLee Jones 	if (platid)
13226bc4a568SLee Jones 		version = platid->driver_data;
13236bc4a568SLee Jones 
13240f620837SLinus Walleij 	if (version != AB8500_VERSION_UNDEFINED)
13250f620837SLinus Walleij 		ab8500->version = version;
13260f620837SLinus Walleij 	else {
13270f620837SLinus Walleij 		ret = get_register_interruptible(ab8500, AB8500_MISC,
13280f620837SLinus Walleij 			AB8500_IC_NAME_REG, &value);
13290f620837SLinus Walleij 		if (ret < 0)
13308c4203cbSLee Jones 			return ret;
13310f620837SLinus Walleij 
13320f620837SLinus Walleij 		ab8500->version = value;
13330f620837SLinus Walleij 	}
13340f620837SLinus Walleij 
133547c16975SMattias Wallin 	ret = get_register_interruptible(ab8500, AB8500_MISC,
133647c16975SMattias Wallin 		AB8500_REV_REG, &value);
133762579266SRabin Vincent 	if (ret < 0)
13388c4203cbSLee Jones 		return ret;
133962579266SRabin Vincent 
134047c16975SMattias Wallin 	ab8500->chip_id = value;
134162579266SRabin Vincent 
13420f620837SLinus Walleij 	dev_info(ab8500->dev, "detected chip, %s rev. %1x.%1x\n",
13430f620837SLinus Walleij 			ab8500_version_str[ab8500->version],
13440f620837SLinus Walleij 			ab8500->chip_id >> 4,
13450f620837SLinus Walleij 			ab8500->chip_id & 0x0F);
13460f620837SLinus Walleij 
1347d6255529SLinus Walleij 	/* Configure AB8500 or AB9540 IRQ */
1348a982362cSBengt Jonsson 	if (is_ab9540(ab8500) || is_ab8505(ab8500)) {
1349d6255529SLinus Walleij 		ab8500->mask_size = AB9540_NUM_IRQ_REGS;
1350d6255529SLinus Walleij 		ab8500->irq_reg_offset = ab9540_irq_regoffset;
1351d6255529SLinus Walleij 	} else {
13522ced445eSLinus Walleij 		ab8500->mask_size = AB8500_NUM_IRQ_REGS;
13532ced445eSLinus Walleij 		ab8500->irq_reg_offset = ab8500_irq_regoffset;
1354d6255529SLinus Walleij 	}
13558c4203cbSLee Jones 	ab8500->mask = devm_kzalloc(&pdev->dev, ab8500->mask_size, GFP_KERNEL);
13562ced445eSLinus Walleij 	if (!ab8500->mask)
13572ced445eSLinus Walleij 		return -ENOMEM;
13588c4203cbSLee Jones 	ab8500->oldmask = devm_kzalloc(&pdev->dev, ab8500->mask_size, GFP_KERNEL);
13598c4203cbSLee Jones 	if (!ab8500->oldmask)
13608c4203cbSLee Jones 		return -ENOMEM;
13618c4203cbSLee Jones 
1362e5c238c3SMattias Wallin 	/*
1363e5c238c3SMattias Wallin 	 * ab8500 has switched off due to (SWITCH_OFF_STATUS):
1364e5c238c3SMattias Wallin 	 * 0x01 Swoff bit programming
1365e5c238c3SMattias Wallin 	 * 0x02 Thermal protection activation
1366e5c238c3SMattias Wallin 	 * 0x04 Vbat lower then BattOk falling threshold
1367e5c238c3SMattias Wallin 	 * 0x08 Watchdog expired
1368e5c238c3SMattias Wallin 	 * 0x10 Non presence of 32kHz clock
1369e5c238c3SMattias Wallin 	 * 0x20 Battery level lower than power on reset threshold
1370e5c238c3SMattias Wallin 	 * 0x40 Power on key 1 pressed longer than 10 seconds
1371e5c238c3SMattias Wallin 	 * 0x80 DB8500 thermal shutdown
1372e5c238c3SMattias Wallin 	 */
1373e5c238c3SMattias Wallin 
1374e5c238c3SMattias Wallin 	ret = get_register_interruptible(ab8500, AB8500_RTC,
1375e5c238c3SMattias Wallin 		AB8500_SWITCH_OFF_STATUS, &value);
1376e5c238c3SMattias Wallin 	if (ret < 0)
1377e5c238c3SMattias Wallin 		return ret;
1378b04c530cSJonas Aaberg 	dev_info(ab8500->dev, "switch off cause(s) (%#x): ", value);
1379b04c530cSJonas Aaberg 
1380b04c530cSJonas Aaberg 	if (value) {
1381b04c530cSJonas Aaberg 		for (i = 0; i < ARRAY_SIZE(switch_off_status); i++) {
1382b04c530cSJonas Aaberg 			if (value & 1)
1383b04c530cSJonas Aaberg 				printk(KERN_CONT " \"%s\"",
1384b04c530cSJonas Aaberg 				       switch_off_status[i]);
1385b04c530cSJonas Aaberg 			value = value >> 1;
1386b04c530cSJonas Aaberg 
1387b04c530cSJonas Aaberg 		}
1388b04c530cSJonas Aaberg 		printk(KERN_CONT "\n");
1389b04c530cSJonas Aaberg 	} else {
1390b04c530cSJonas Aaberg 		printk(KERN_CONT " None\n");
1391b04c530cSJonas Aaberg 	}
1392e5c238c3SMattias Wallin 
139362579266SRabin Vincent 	if (plat && plat->init)
139462579266SRabin Vincent 		plat->init(ab8500);
139562579266SRabin Vincent 
139662579266SRabin Vincent 	/* Clear and mask all interrupts */
13972ced445eSLinus Walleij 	for (i = 0; i < ab8500->mask_size; i++) {
13980f620837SLinus Walleij 		/*
13990f620837SLinus Walleij 		 * Interrupt register 12 doesn't exist prior to AB8500 version
14000f620837SLinus Walleij 		 * 2.0
14010f620837SLinus Walleij 		 */
14020f620837SLinus Walleij 		if (ab8500->irq_reg_offset[i] == 11 &&
14030f620837SLinus Walleij 				is_ab8500_1p1_or_earlier(ab8500))
140492d50a41SMattias Wallin 			continue;
140562579266SRabin Vincent 
140647c16975SMattias Wallin 		get_register_interruptible(ab8500, AB8500_INTERRUPT,
14072ced445eSLinus Walleij 			AB8500_IT_LATCH1_REG + ab8500->irq_reg_offset[i],
140892d50a41SMattias Wallin 			&value);
140947c16975SMattias Wallin 		set_register_interruptible(ab8500, AB8500_INTERRUPT,
14102ced445eSLinus Walleij 			AB8500_IT_MASK1_REG + ab8500->irq_reg_offset[i], 0xff);
141162579266SRabin Vincent 	}
141262579266SRabin Vincent 
141347c16975SMattias Wallin 	ret = abx500_register_ops(ab8500->dev, &ab8500_ops);
141447c16975SMattias Wallin 	if (ret)
14158c4203cbSLee Jones 		return ret;
141647c16975SMattias Wallin 
14172ced445eSLinus Walleij 	for (i = 0; i < ab8500->mask_size; i++)
141862579266SRabin Vincent 		ab8500->mask[i] = ab8500->oldmask[i] = 0xff;
141962579266SRabin Vincent 
142006e589efSLee Jones 	ret = ab8500_irq_init(ab8500, np);
142162579266SRabin Vincent 	if (ret)
14228c4203cbSLee Jones 		return ret;
142362579266SRabin Vincent 
14247ccfe9b1SMichel JAOUEN 	/*  Activate this feature only in ab9540 */
14257ccfe9b1SMichel JAOUEN 	/*  till tests are done on ab8500 1p2 or later*/
142606e589efSLee Jones 	if (is_ab9540(ab8500)) {
14278c4203cbSLee Jones 		ret = devm_request_threaded_irq(&pdev->dev, ab8500->irq, NULL,
14287ccfe9b1SMichel JAOUEN 						ab8500_hierarchical_irq,
14297ccfe9b1SMichel JAOUEN 						IRQF_ONESHOT | IRQF_NO_SUSPEND,
14307ccfe9b1SMichel JAOUEN 						"ab8500", ab8500);
143106e589efSLee Jones 	}
143206e589efSLee Jones 	else {
14338c4203cbSLee Jones 		ret = devm_request_threaded_irq(&pdev->dev, ab8500->irq, NULL,
14347ccfe9b1SMichel JAOUEN 						ab8500_irq,
14354f079985SMattias Wallin 						IRQF_ONESHOT | IRQF_NO_SUSPEND,
14364f079985SMattias Wallin 						"ab8500", ab8500);
143762579266SRabin Vincent 		if (ret)
14388c4203cbSLee Jones 			return ret;
143962579266SRabin Vincent 	}
144062579266SRabin Vincent 
1441d6255529SLinus Walleij 	ret = mfd_add_devices(ab8500->dev, 0, abx500_common_devs,
1442d6255529SLinus Walleij 			ARRAY_SIZE(abx500_common_devs), NULL,
144355692af5SMark Brown 			ab8500->irq_base, ab8500->domain);
1444d6255529SLinus Walleij 	if (ret)
14458c4203cbSLee Jones 		return ret;
1446d6255529SLinus Walleij 
1447d6255529SLinus Walleij 	if (is_ab9540(ab8500))
1448d6255529SLinus Walleij 		ret = mfd_add_devices(ab8500->dev, 0, ab9540_devs,
1449d6255529SLinus Walleij 				ARRAY_SIZE(ab9540_devs), NULL,
145055692af5SMark Brown 				ab8500->irq_base, ab8500->domain);
1451d6255529SLinus Walleij 	else
1452549931f9SSundar R Iyer 		ret = mfd_add_devices(ab8500->dev, 0, ab8500_devs,
145344f72e53SVirupax Sadashivpetimath 				ARRAY_SIZE(ab8500_devs), NULL,
145455692af5SMark Brown 				ab8500->irq_base, ab8500->domain);
14556bc4a568SLee Jones 	if (ret)
14568c4203cbSLee Jones 		return ret;
145744f72e53SVirupax Sadashivpetimath 
145844f72e53SVirupax Sadashivpetimath 	if (is_ab9540(ab8500) || is_ab8505(ab8500))
145944f72e53SVirupax Sadashivpetimath 		ret = mfd_add_devices(ab8500->dev, 0, ab9540_ab8505_devs,
146044f72e53SVirupax Sadashivpetimath 				ARRAY_SIZE(ab9540_ab8505_devs), NULL,
146155692af5SMark Brown 				ab8500->irq_base, ab8500->domain);
146262579266SRabin Vincent 	if (ret)
14638c4203cbSLee Jones 		return ret;
146462579266SRabin Vincent 
14656ef9418cSRickard Andersson 	if (!no_bm) {
14666ef9418cSRickard Andersson 		/* Add battery management devices */
14676ef9418cSRickard Andersson 		ret = mfd_add_devices(ab8500->dev, 0, ab8500_bm_devs,
14686ef9418cSRickard Andersson 				      ARRAY_SIZE(ab8500_bm_devs), NULL,
146955692af5SMark Brown 				      ab8500->irq_base, ab8500->domain);
14706ef9418cSRickard Andersson 		if (ret)
14716ef9418cSRickard Andersson 			dev_err(ab8500->dev, "error adding bm devices\n");
14726ef9418cSRickard Andersson 	}
14736ef9418cSRickard Andersson 
1474d6255529SLinus Walleij 	if (is_ab9540(ab8500))
1475d6255529SLinus Walleij 		ret = sysfs_create_group(&ab8500->dev->kobj,
1476d6255529SLinus Walleij 					&ab9540_attr_group);
1477d6255529SLinus Walleij 	else
1478d6255529SLinus Walleij 		ret = sysfs_create_group(&ab8500->dev->kobj,
1479d6255529SLinus Walleij 					&ab8500_attr_group);
1480cca69b67SMattias Wallin 	if (ret)
1481cca69b67SMattias Wallin 		dev_err(ab8500->dev, "error creating sysfs entries\n");
148206e589efSLee Jones 
148362579266SRabin Vincent 	return ret;
148462579266SRabin Vincent }
148562579266SRabin Vincent 
14864740f73fSBill Pemberton static int ab8500_remove(struct platform_device *pdev)
148762579266SRabin Vincent {
1488d28f1db8SLee Jones 	struct ab8500 *ab8500 = platform_get_drvdata(pdev);
1489d28f1db8SLee Jones 
1490d6255529SLinus Walleij 	if (is_ab9540(ab8500))
1491d6255529SLinus Walleij 		sysfs_remove_group(&ab8500->dev->kobj, &ab9540_attr_group);
1492d6255529SLinus Walleij 	else
1493cca69b67SMattias Wallin 		sysfs_remove_group(&ab8500->dev->kobj, &ab8500_attr_group);
149406e589efSLee Jones 
149562579266SRabin Vincent 	mfd_remove_devices(ab8500->dev);
149662579266SRabin Vincent 
149762579266SRabin Vincent 	return 0;
149862579266SRabin Vincent }
149962579266SRabin Vincent 
1500d28f1db8SLee Jones static const struct platform_device_id ab8500_id[] = {
1501d28f1db8SLee Jones 	{ "ab8500-core", AB8500_VERSION_AB8500 },
1502d28f1db8SLee Jones 	{ "ab8505-i2c", AB8500_VERSION_AB8505 },
1503d28f1db8SLee Jones 	{ "ab9540-i2c", AB8500_VERSION_AB9540 },
1504d28f1db8SLee Jones 	{ "ab8540-i2c", AB8500_VERSION_AB8540 },
1505d28f1db8SLee Jones 	{ }
1506d28f1db8SLee Jones };
1507d28f1db8SLee Jones 
1508d28f1db8SLee Jones static struct platform_driver ab8500_core_driver = {
1509d28f1db8SLee Jones 	.driver = {
1510d28f1db8SLee Jones 		.name = "ab8500-core",
1511d28f1db8SLee Jones 		.owner = THIS_MODULE,
1512d28f1db8SLee Jones 	},
1513d28f1db8SLee Jones 	.probe	= ab8500_probe,
151484449216SBill Pemberton 	.remove	= ab8500_remove,
1515d28f1db8SLee Jones 	.id_table = ab8500_id,
1516d28f1db8SLee Jones };
1517d28f1db8SLee Jones 
1518d28f1db8SLee Jones static int __init ab8500_core_init(void)
1519d28f1db8SLee Jones {
1520d28f1db8SLee Jones 	return platform_driver_register(&ab8500_core_driver);
1521d28f1db8SLee Jones }
1522d28f1db8SLee Jones 
1523d28f1db8SLee Jones static void __exit ab8500_core_exit(void)
1524d28f1db8SLee Jones {
1525d28f1db8SLee Jones 	platform_driver_unregister(&ab8500_core_driver);
1526d28f1db8SLee Jones }
1527ba7cbc3eSLee Jones core_initcall(ab8500_core_init);
1528d28f1db8SLee Jones module_exit(ab8500_core_exit);
1529d28f1db8SLee Jones 
1530adceed62SMattias Wallin MODULE_AUTHOR("Mattias Wallin, Srinidhi Kasagar, Rabin Vincent");
153162579266SRabin Vincent MODULE_DESCRIPTION("AB8500 MFD core");
153262579266SRabin Vincent MODULE_LICENSE("GPL v2");
1533