xref: /openbmc/linux/drivers/mfd/ab8500-core.c (revision 6bc4a568414caab05424b702165a732177daccd0)
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>
1462579266SRabin Vincent #include <linux/delay.h>
1562579266SRabin Vincent #include <linux/interrupt.h>
1662579266SRabin Vincent #include <linux/module.h>
1762579266SRabin Vincent #include <linux/platform_device.h>
1862579266SRabin Vincent #include <linux/mfd/core.h>
1947c16975SMattias Wallin #include <linux/mfd/abx500.h>
20ee66e653SLinus Walleij #include <linux/mfd/abx500/ab8500.h>
21d28f1db8SLee Jones #include <linux/mfd/dbx500-prcmu.h>
22549931f9SSundar R Iyer #include <linux/regulator/ab8500.h>
23*6bc4a568SLee Jones #include <linux/of.h>
24*6bc4a568SLee Jones #include <linux/of_device.h>
2562579266SRabin Vincent 
2662579266SRabin Vincent /*
2762579266SRabin Vincent  * Interrupt register offsets
2862579266SRabin Vincent  * Bank : 0x0E
2962579266SRabin Vincent  */
3047c16975SMattias Wallin #define AB8500_IT_SOURCE1_REG		0x00
3147c16975SMattias Wallin #define AB8500_IT_SOURCE2_REG		0x01
3247c16975SMattias Wallin #define AB8500_IT_SOURCE3_REG		0x02
3347c16975SMattias Wallin #define AB8500_IT_SOURCE4_REG		0x03
3447c16975SMattias Wallin #define AB8500_IT_SOURCE5_REG		0x04
3547c16975SMattias Wallin #define AB8500_IT_SOURCE6_REG		0x05
3647c16975SMattias Wallin #define AB8500_IT_SOURCE7_REG		0x06
3747c16975SMattias Wallin #define AB8500_IT_SOURCE8_REG		0x07
38d6255529SLinus Walleij #define AB9540_IT_SOURCE13_REG		0x0C
3947c16975SMattias Wallin #define AB8500_IT_SOURCE19_REG		0x12
4047c16975SMattias Wallin #define AB8500_IT_SOURCE20_REG		0x13
4147c16975SMattias Wallin #define AB8500_IT_SOURCE21_REG		0x14
4247c16975SMattias Wallin #define AB8500_IT_SOURCE22_REG		0x15
4347c16975SMattias Wallin #define AB8500_IT_SOURCE23_REG		0x16
4447c16975SMattias Wallin #define AB8500_IT_SOURCE24_REG		0x17
4562579266SRabin Vincent 
4662579266SRabin Vincent /*
4762579266SRabin Vincent  * latch registers
4862579266SRabin Vincent  */
4947c16975SMattias Wallin #define AB8500_IT_LATCH1_REG		0x20
5047c16975SMattias Wallin #define AB8500_IT_LATCH2_REG		0x21
5147c16975SMattias Wallin #define AB8500_IT_LATCH3_REG		0x22
5247c16975SMattias Wallin #define AB8500_IT_LATCH4_REG		0x23
5347c16975SMattias Wallin #define AB8500_IT_LATCH5_REG		0x24
5447c16975SMattias Wallin #define AB8500_IT_LATCH6_REG		0x25
5547c16975SMattias Wallin #define AB8500_IT_LATCH7_REG		0x26
5647c16975SMattias Wallin #define AB8500_IT_LATCH8_REG		0x27
5747c16975SMattias Wallin #define AB8500_IT_LATCH9_REG		0x28
5847c16975SMattias Wallin #define AB8500_IT_LATCH10_REG		0x29
5992d50a41SMattias Wallin #define AB8500_IT_LATCH12_REG		0x2B
60d6255529SLinus Walleij #define AB9540_IT_LATCH13_REG		0x2C
6147c16975SMattias Wallin #define AB8500_IT_LATCH19_REG		0x32
6247c16975SMattias Wallin #define AB8500_IT_LATCH20_REG		0x33
6347c16975SMattias Wallin #define AB8500_IT_LATCH21_REG		0x34
6447c16975SMattias Wallin #define AB8500_IT_LATCH22_REG		0x35
6547c16975SMattias Wallin #define AB8500_IT_LATCH23_REG		0x36
6647c16975SMattias Wallin #define AB8500_IT_LATCH24_REG		0x37
6762579266SRabin Vincent 
6862579266SRabin Vincent /*
6962579266SRabin Vincent  * mask registers
7062579266SRabin Vincent  */
7162579266SRabin Vincent 
7247c16975SMattias Wallin #define AB8500_IT_MASK1_REG		0x40
7347c16975SMattias Wallin #define AB8500_IT_MASK2_REG		0x41
7447c16975SMattias Wallin #define AB8500_IT_MASK3_REG		0x42
7547c16975SMattias Wallin #define AB8500_IT_MASK4_REG		0x43
7647c16975SMattias Wallin #define AB8500_IT_MASK5_REG		0x44
7747c16975SMattias Wallin #define AB8500_IT_MASK6_REG		0x45
7847c16975SMattias Wallin #define AB8500_IT_MASK7_REG		0x46
7947c16975SMattias Wallin #define AB8500_IT_MASK8_REG		0x47
8047c16975SMattias Wallin #define AB8500_IT_MASK9_REG		0x48
8147c16975SMattias Wallin #define AB8500_IT_MASK10_REG		0x49
8247c16975SMattias Wallin #define AB8500_IT_MASK11_REG		0x4A
8347c16975SMattias Wallin #define AB8500_IT_MASK12_REG		0x4B
8447c16975SMattias Wallin #define AB8500_IT_MASK13_REG		0x4C
8547c16975SMattias Wallin #define AB8500_IT_MASK14_REG		0x4D
8647c16975SMattias Wallin #define AB8500_IT_MASK15_REG		0x4E
8747c16975SMattias Wallin #define AB8500_IT_MASK16_REG		0x4F
8847c16975SMattias Wallin #define AB8500_IT_MASK17_REG		0x50
8947c16975SMattias Wallin #define AB8500_IT_MASK18_REG		0x51
9047c16975SMattias Wallin #define AB8500_IT_MASK19_REG		0x52
9147c16975SMattias Wallin #define AB8500_IT_MASK20_REG		0x53
9247c16975SMattias Wallin #define AB8500_IT_MASK21_REG		0x54
9347c16975SMattias Wallin #define AB8500_IT_MASK22_REG		0x55
9447c16975SMattias Wallin #define AB8500_IT_MASK23_REG		0x56
9547c16975SMattias Wallin #define AB8500_IT_MASK24_REG		0x57
9662579266SRabin Vincent 
977ccfe9b1SMichel JAOUEN /*
987ccfe9b1SMichel JAOUEN  * latch hierarchy registers
997ccfe9b1SMichel JAOUEN  */
1007ccfe9b1SMichel JAOUEN #define AB8500_IT_LATCHHIER1_REG	0x60
1017ccfe9b1SMichel JAOUEN #define AB8500_IT_LATCHHIER2_REG	0x61
1027ccfe9b1SMichel JAOUEN #define AB8500_IT_LATCHHIER3_REG	0x62
1037ccfe9b1SMichel JAOUEN 
1047ccfe9b1SMichel JAOUEN #define AB8500_IT_LATCHHIER_NUM		3
1057ccfe9b1SMichel JAOUEN 
10647c16975SMattias Wallin #define AB8500_REV_REG			0x80
1070f620837SLinus Walleij #define AB8500_IC_NAME_REG		0x82
108e5c238c3SMattias Wallin #define AB8500_SWITCH_OFF_STATUS	0x00
10962579266SRabin Vincent 
110b4a31037SAndrew Lynn #define AB8500_TURN_ON_STATUS		0x00
111b4a31037SAndrew Lynn 
1126ef9418cSRickard Andersson static bool no_bm; /* No battery management */
1136ef9418cSRickard Andersson module_param(no_bm, bool, S_IRUGO);
1146ef9418cSRickard Andersson 
115d6255529SLinus Walleij #define AB9540_MODEM_CTRL2_REG			0x23
116d6255529SLinus Walleij #define AB9540_MODEM_CTRL2_SWDBBRSTN_BIT	BIT(2)
117d6255529SLinus Walleij 
11862579266SRabin Vincent /*
11962579266SRabin Vincent  * Map interrupt numbers to the LATCH and MASK register offsets, Interrupt
1202ced445eSLinus Walleij  * numbers are indexed into this array with (num / 8). The interupts are
1212ced445eSLinus Walleij  * defined in linux/mfd/ab8500.h
12262579266SRabin Vincent  *
12362579266SRabin Vincent  * This is one off from the register names, i.e. AB8500_IT_MASK1_REG is at
12462579266SRabin Vincent  * offset 0.
12562579266SRabin Vincent  */
1262ced445eSLinus Walleij /* AB8500 support */
12762579266SRabin Vincent static const int ab8500_irq_regoffset[AB8500_NUM_IRQ_REGS] = {
12892d50a41SMattias Wallin 	0, 1, 2, 3, 4, 6, 7, 8, 9, 11, 18, 19, 20, 21,
12962579266SRabin Vincent };
13062579266SRabin Vincent 
131d6255529SLinus Walleij /* AB9540 support */
132d6255529SLinus Walleij static const int ab9540_irq_regoffset[AB9540_NUM_IRQ_REGS] = {
133d6255529SLinus Walleij 	0, 1, 2, 3, 4, 6, 7, 8, 9, 11, 18, 19, 20, 21, 12, 13, 24,
134d6255529SLinus Walleij };
135d6255529SLinus Walleij 
1360f620837SLinus Walleij static const char ab8500_version_str[][7] = {
1370f620837SLinus Walleij 	[AB8500_VERSION_AB8500] = "AB8500",
1380f620837SLinus Walleij 	[AB8500_VERSION_AB8505] = "AB8505",
1390f620837SLinus Walleij 	[AB8500_VERSION_AB9540] = "AB9540",
1400f620837SLinus Walleij 	[AB8500_VERSION_AB8540] = "AB8540",
1410f620837SLinus Walleij };
1420f620837SLinus Walleij 
143d28f1db8SLee Jones static int ab8500_i2c_write(struct ab8500 *ab8500, u16 addr, u8 data)
144d28f1db8SLee Jones {
145d28f1db8SLee Jones 	int ret;
146d28f1db8SLee Jones 
147d28f1db8SLee Jones 	ret = prcmu_abb_write((u8)(addr >> 8), (u8)(addr & 0xFF), &data, 1);
148d28f1db8SLee Jones 	if (ret < 0)
149d28f1db8SLee Jones 		dev_err(ab8500->dev, "prcmu i2c error %d\n", ret);
150d28f1db8SLee Jones 	return ret;
151d28f1db8SLee Jones }
152d28f1db8SLee Jones 
153d28f1db8SLee Jones static int ab8500_i2c_write_masked(struct ab8500 *ab8500, u16 addr, u8 mask,
154d28f1db8SLee Jones 	u8 data)
155d28f1db8SLee Jones {
156d28f1db8SLee Jones 	int ret;
157d28f1db8SLee Jones 
158d28f1db8SLee Jones 	ret = prcmu_abb_write_masked((u8)(addr >> 8), (u8)(addr & 0xFF), &data,
159d28f1db8SLee Jones 		&mask, 1);
160d28f1db8SLee Jones 	if (ret < 0)
161d28f1db8SLee Jones 		dev_err(ab8500->dev, "prcmu i2c error %d\n", ret);
162d28f1db8SLee Jones 	return ret;
163d28f1db8SLee Jones }
164d28f1db8SLee Jones 
165d28f1db8SLee Jones static int ab8500_i2c_read(struct ab8500 *ab8500, u16 addr)
166d28f1db8SLee Jones {
167d28f1db8SLee Jones 	int ret;
168d28f1db8SLee Jones 	u8 data;
169d28f1db8SLee Jones 
170d28f1db8SLee Jones 	ret = prcmu_abb_read((u8)(addr >> 8), (u8)(addr & 0xFF), &data, 1);
171d28f1db8SLee Jones 	if (ret < 0) {
172d28f1db8SLee Jones 		dev_err(ab8500->dev, "prcmu i2c error %d\n", ret);
173d28f1db8SLee Jones 		return ret;
174d28f1db8SLee Jones 	}
175d28f1db8SLee Jones 	return (int)data;
176d28f1db8SLee Jones }
177d28f1db8SLee Jones 
17847c16975SMattias Wallin static int ab8500_get_chip_id(struct device *dev)
17947c16975SMattias Wallin {
1806bce7bf1SMattias Wallin 	struct ab8500 *ab8500;
1816bce7bf1SMattias Wallin 
1826bce7bf1SMattias Wallin 	if (!dev)
1836bce7bf1SMattias Wallin 		return -EINVAL;
1846bce7bf1SMattias Wallin 	ab8500 = dev_get_drvdata(dev->parent);
1856bce7bf1SMattias Wallin 	return ab8500 ? (int)ab8500->chip_id : -EINVAL;
18647c16975SMattias Wallin }
18747c16975SMattias Wallin 
18847c16975SMattias Wallin static int set_register_interruptible(struct ab8500 *ab8500, u8 bank,
18947c16975SMattias Wallin 	u8 reg, u8 data)
19062579266SRabin Vincent {
19162579266SRabin Vincent 	int ret;
19247c16975SMattias Wallin 	/*
19347c16975SMattias Wallin 	 * Put the u8 bank and u8 register together into a an u16.
19447c16975SMattias Wallin 	 * The bank on higher 8 bits and register in lower 8 bits.
19547c16975SMattias Wallin 	 * */
19647c16975SMattias Wallin 	u16 addr = ((u16)bank) << 8 | reg;
19762579266SRabin Vincent 
19862579266SRabin Vincent 	dev_vdbg(ab8500->dev, "wr: addr %#x <= %#x\n", addr, data);
19962579266SRabin Vincent 
200392cbd1eSRabin Vincent 	mutex_lock(&ab8500->lock);
20147c16975SMattias Wallin 
20247c16975SMattias Wallin 	ret = ab8500->write(ab8500, addr, data);
20347c16975SMattias Wallin 	if (ret < 0)
20447c16975SMattias Wallin 		dev_err(ab8500->dev, "failed to write reg %#x: %d\n",
20547c16975SMattias Wallin 			addr, ret);
20647c16975SMattias Wallin 	mutex_unlock(&ab8500->lock);
20747c16975SMattias Wallin 
20847c16975SMattias Wallin 	return ret;
20947c16975SMattias Wallin }
21047c16975SMattias Wallin 
21147c16975SMattias Wallin static int ab8500_set_register(struct device *dev, u8 bank,
21247c16975SMattias Wallin 	u8 reg, u8 value)
21347c16975SMattias Wallin {
214112a80d2SJonas Aaberg 	int ret;
21547c16975SMattias Wallin 	struct ab8500 *ab8500 = dev_get_drvdata(dev->parent);
21647c16975SMattias Wallin 
217112a80d2SJonas Aaberg 	atomic_inc(&ab8500->transfer_ongoing);
218112a80d2SJonas Aaberg 	ret = set_register_interruptible(ab8500, bank, reg, value);
219112a80d2SJonas Aaberg 	atomic_dec(&ab8500->transfer_ongoing);
220112a80d2SJonas Aaberg 	return ret;
22147c16975SMattias Wallin }
22247c16975SMattias Wallin 
22347c16975SMattias Wallin static int get_register_interruptible(struct ab8500 *ab8500, u8 bank,
22447c16975SMattias Wallin 	u8 reg, u8 *value)
22547c16975SMattias Wallin {
22647c16975SMattias Wallin 	int ret;
22747c16975SMattias Wallin 	/* put the u8 bank and u8 reg together into a an u16.
22847c16975SMattias Wallin 	 * bank on higher 8 bits and reg in lower */
22947c16975SMattias Wallin 	u16 addr = ((u16)bank) << 8 | reg;
23047c16975SMattias Wallin 
231392cbd1eSRabin Vincent 	mutex_lock(&ab8500->lock);
23247c16975SMattias Wallin 
23347c16975SMattias Wallin 	ret = ab8500->read(ab8500, addr);
23447c16975SMattias Wallin 	if (ret < 0)
23547c16975SMattias Wallin 		dev_err(ab8500->dev, "failed to read reg %#x: %d\n",
23647c16975SMattias Wallin 			addr, ret);
23747c16975SMattias Wallin 	else
23847c16975SMattias Wallin 		*value = ret;
23947c16975SMattias Wallin 
24047c16975SMattias Wallin 	mutex_unlock(&ab8500->lock);
24147c16975SMattias Wallin 	dev_vdbg(ab8500->dev, "rd: addr %#x => data %#x\n", addr, ret);
24247c16975SMattias Wallin 
24347c16975SMattias Wallin 	return ret;
24447c16975SMattias Wallin }
24547c16975SMattias Wallin 
24647c16975SMattias Wallin static int ab8500_get_register(struct device *dev, u8 bank,
24747c16975SMattias Wallin 	u8 reg, u8 *value)
24847c16975SMattias Wallin {
249112a80d2SJonas Aaberg 	int ret;
25047c16975SMattias Wallin 	struct ab8500 *ab8500 = dev_get_drvdata(dev->parent);
25147c16975SMattias Wallin 
252112a80d2SJonas Aaberg 	atomic_inc(&ab8500->transfer_ongoing);
253112a80d2SJonas Aaberg 	ret = get_register_interruptible(ab8500, bank, reg, value);
254112a80d2SJonas Aaberg 	atomic_dec(&ab8500->transfer_ongoing);
255112a80d2SJonas Aaberg 	return ret;
25647c16975SMattias Wallin }
25747c16975SMattias Wallin 
25847c16975SMattias Wallin static int mask_and_set_register_interruptible(struct ab8500 *ab8500, u8 bank,
25947c16975SMattias Wallin 	u8 reg, u8 bitmask, u8 bitvalues)
26047c16975SMattias Wallin {
26147c16975SMattias Wallin 	int ret;
26247c16975SMattias Wallin 	/* put the u8 bank and u8 reg together into a an u16.
26347c16975SMattias Wallin 	 * bank on higher 8 bits and reg in lower */
26447c16975SMattias Wallin 	u16 addr = ((u16)bank) << 8 | reg;
26547c16975SMattias Wallin 
266392cbd1eSRabin Vincent 	mutex_lock(&ab8500->lock);
26747c16975SMattias Wallin 
268bc628fd1SMattias Nilsson 	if (ab8500->write_masked == NULL) {
269bc628fd1SMattias Nilsson 		u8 data;
270bc628fd1SMattias Nilsson 
27147c16975SMattias Wallin 		ret = ab8500->read(ab8500, addr);
27247c16975SMattias Wallin 		if (ret < 0) {
27347c16975SMattias Wallin 			dev_err(ab8500->dev, "failed to read reg %#x: %d\n",
27447c16975SMattias Wallin 				addr, ret);
27547c16975SMattias Wallin 			goto out;
27647c16975SMattias Wallin 		}
27747c16975SMattias Wallin 
27847c16975SMattias Wallin 		data = (u8)ret;
27947c16975SMattias Wallin 		data = (~bitmask & data) | (bitmask & bitvalues);
28047c16975SMattias Wallin 
28162579266SRabin Vincent 		ret = ab8500->write(ab8500, addr, data);
28262579266SRabin Vincent 		if (ret < 0)
28362579266SRabin Vincent 			dev_err(ab8500->dev, "failed to write reg %#x: %d\n",
28462579266SRabin Vincent 				addr, ret);
28562579266SRabin Vincent 
286bc628fd1SMattias Nilsson 		dev_vdbg(ab8500->dev, "mask: addr %#x => data %#x\n", addr,
287bc628fd1SMattias Nilsson 			data);
288bc628fd1SMattias Nilsson 		goto out;
289bc628fd1SMattias Nilsson 	}
290bc628fd1SMattias Nilsson 	ret = ab8500->write_masked(ab8500, addr, bitmask, bitvalues);
291bc628fd1SMattias Nilsson 	if (ret < 0)
292bc628fd1SMattias Nilsson 		dev_err(ab8500->dev, "failed to modify reg %#x: %d\n", addr,
293bc628fd1SMattias Nilsson 			ret);
29462579266SRabin Vincent out:
29562579266SRabin Vincent 	mutex_unlock(&ab8500->lock);
29662579266SRabin Vincent 	return ret;
29762579266SRabin Vincent }
29847c16975SMattias Wallin 
29947c16975SMattias Wallin static int ab8500_mask_and_set_register(struct device *dev,
30047c16975SMattias Wallin 	u8 bank, u8 reg, u8 bitmask, u8 bitvalues)
30147c16975SMattias Wallin {
302112a80d2SJonas Aaberg 	int ret;
30347c16975SMattias Wallin 	struct ab8500 *ab8500 = dev_get_drvdata(dev->parent);
30447c16975SMattias Wallin 
305112a80d2SJonas Aaberg 	atomic_inc(&ab8500->transfer_ongoing);
306112a80d2SJonas Aaberg 	ret= mask_and_set_register_interruptible(ab8500, bank, reg,
30747c16975SMattias Wallin 						 bitmask, bitvalues);
308112a80d2SJonas Aaberg 	atomic_dec(&ab8500->transfer_ongoing);
309112a80d2SJonas Aaberg 	return ret;
31047c16975SMattias Wallin }
31147c16975SMattias Wallin 
31247c16975SMattias Wallin static struct abx500_ops ab8500_ops = {
31347c16975SMattias Wallin 	.get_chip_id = ab8500_get_chip_id,
31447c16975SMattias Wallin 	.get_register = ab8500_get_register,
31547c16975SMattias Wallin 	.set_register = ab8500_set_register,
31647c16975SMattias Wallin 	.get_register_page = NULL,
31747c16975SMattias Wallin 	.set_register_page = NULL,
31847c16975SMattias Wallin 	.mask_and_set_register = ab8500_mask_and_set_register,
31947c16975SMattias Wallin 	.event_registers_startup_state_get = NULL,
32047c16975SMattias Wallin 	.startup_irq_enabled = NULL,
32147c16975SMattias Wallin };
32262579266SRabin Vincent 
3239505a0a0SMark Brown static void ab8500_irq_lock(struct irq_data *data)
32462579266SRabin Vincent {
3259505a0a0SMark Brown 	struct ab8500 *ab8500 = irq_data_get_irq_chip_data(data);
32662579266SRabin Vincent 
32762579266SRabin Vincent 	mutex_lock(&ab8500->irq_lock);
328112a80d2SJonas Aaberg 	atomic_inc(&ab8500->transfer_ongoing);
32962579266SRabin Vincent }
33062579266SRabin Vincent 
3319505a0a0SMark Brown static void ab8500_irq_sync_unlock(struct irq_data *data)
33262579266SRabin Vincent {
3339505a0a0SMark Brown 	struct ab8500 *ab8500 = irq_data_get_irq_chip_data(data);
33462579266SRabin Vincent 	int i;
33562579266SRabin Vincent 
3362ced445eSLinus Walleij 	for (i = 0; i < ab8500->mask_size; i++) {
33762579266SRabin Vincent 		u8 old = ab8500->oldmask[i];
33862579266SRabin Vincent 		u8 new = ab8500->mask[i];
33962579266SRabin Vincent 		int reg;
34062579266SRabin Vincent 
34162579266SRabin Vincent 		if (new == old)
34262579266SRabin Vincent 			continue;
34362579266SRabin Vincent 
3440f620837SLinus Walleij 		/*
3450f620837SLinus Walleij 		 * Interrupt register 12 doesn't exist prior to AB8500 version
3460f620837SLinus Walleij 		 * 2.0
3470f620837SLinus Walleij 		 */
3480f620837SLinus Walleij 		if (ab8500->irq_reg_offset[i] == 11 &&
3490f620837SLinus Walleij 			is_ab8500_1p1_or_earlier(ab8500))
35092d50a41SMattias Wallin 			continue;
35192d50a41SMattias Wallin 
35262579266SRabin Vincent 		ab8500->oldmask[i] = new;
35362579266SRabin Vincent 
3542ced445eSLinus Walleij 		reg = AB8500_IT_MASK1_REG + ab8500->irq_reg_offset[i];
35547c16975SMattias Wallin 		set_register_interruptible(ab8500, AB8500_INTERRUPT, reg, new);
35662579266SRabin Vincent 	}
357112a80d2SJonas Aaberg 	atomic_dec(&ab8500->transfer_ongoing);
35862579266SRabin Vincent 	mutex_unlock(&ab8500->irq_lock);
35962579266SRabin Vincent }
36062579266SRabin Vincent 
3619505a0a0SMark Brown static void ab8500_irq_mask(struct irq_data *data)
36262579266SRabin Vincent {
3639505a0a0SMark Brown 	struct ab8500 *ab8500 = irq_data_get_irq_chip_data(data);
3649505a0a0SMark Brown 	int offset = data->irq - ab8500->irq_base;
36562579266SRabin Vincent 	int index = offset / 8;
36662579266SRabin Vincent 	int mask = 1 << (offset % 8);
36762579266SRabin Vincent 
36862579266SRabin Vincent 	ab8500->mask[index] |= mask;
36962579266SRabin Vincent }
37062579266SRabin Vincent 
3719505a0a0SMark Brown static void ab8500_irq_unmask(struct irq_data *data)
37262579266SRabin Vincent {
3739505a0a0SMark Brown 	struct ab8500 *ab8500 = irq_data_get_irq_chip_data(data);
3749505a0a0SMark Brown 	int offset = data->irq - ab8500->irq_base;
37562579266SRabin Vincent 	int index = offset / 8;
37662579266SRabin Vincent 	int mask = 1 << (offset % 8);
37762579266SRabin Vincent 
37862579266SRabin Vincent 	ab8500->mask[index] &= ~mask;
37962579266SRabin Vincent }
38062579266SRabin Vincent 
38162579266SRabin Vincent static struct irq_chip ab8500_irq_chip = {
38262579266SRabin Vincent 	.name			= "ab8500",
3839505a0a0SMark Brown 	.irq_bus_lock		= ab8500_irq_lock,
3849505a0a0SMark Brown 	.irq_bus_sync_unlock	= ab8500_irq_sync_unlock,
3859505a0a0SMark Brown 	.irq_mask		= ab8500_irq_mask,
386e6f9306eSVirupax Sadashivpetimath 	.irq_disable		= ab8500_irq_mask,
3879505a0a0SMark Brown 	.irq_unmask		= ab8500_irq_unmask,
38862579266SRabin Vincent };
38962579266SRabin Vincent 
3907ccfe9b1SMichel JAOUEN static int ab8500_handle_hierarchical_line(struct ab8500 *ab8500,
3917ccfe9b1SMichel JAOUEN 					int latch_offset, u8 latch_val)
3927ccfe9b1SMichel JAOUEN {
3937ccfe9b1SMichel JAOUEN 	int int_bit = __ffs(latch_val);
3947ccfe9b1SMichel JAOUEN 	int line, i;
3957ccfe9b1SMichel JAOUEN 
3967ccfe9b1SMichel JAOUEN 	do {
3977ccfe9b1SMichel JAOUEN 		int_bit = __ffs(latch_val);
3987ccfe9b1SMichel JAOUEN 
3997ccfe9b1SMichel JAOUEN 		for (i = 0; i < ab8500->mask_size; i++)
4007ccfe9b1SMichel JAOUEN 			if (ab8500->irq_reg_offset[i] == latch_offset)
4017ccfe9b1SMichel JAOUEN 				break;
4027ccfe9b1SMichel JAOUEN 
4037ccfe9b1SMichel JAOUEN 		if (i >= ab8500->mask_size) {
4047ccfe9b1SMichel JAOUEN 			dev_err(ab8500->dev, "Register offset 0x%2x not declared\n",
4057ccfe9b1SMichel JAOUEN 					latch_offset);
4067ccfe9b1SMichel JAOUEN 			return -ENXIO;
4077ccfe9b1SMichel JAOUEN 		}
4087ccfe9b1SMichel JAOUEN 
4097ccfe9b1SMichel JAOUEN 		line = (i << 3) + int_bit;
4107ccfe9b1SMichel JAOUEN 		latch_val &= ~(1 << int_bit);
4117ccfe9b1SMichel JAOUEN 
4127ccfe9b1SMichel JAOUEN 		handle_nested_irq(ab8500->irq_base + line);
4137ccfe9b1SMichel JAOUEN 	} while (latch_val);
4147ccfe9b1SMichel JAOUEN 
4157ccfe9b1SMichel JAOUEN 	return 0;
4167ccfe9b1SMichel JAOUEN }
4177ccfe9b1SMichel JAOUEN 
4187ccfe9b1SMichel JAOUEN static int ab8500_handle_hierarchical_latch(struct ab8500 *ab8500,
4197ccfe9b1SMichel JAOUEN 					int hier_offset, u8 hier_val)
4207ccfe9b1SMichel JAOUEN {
4217ccfe9b1SMichel JAOUEN 	int latch_bit, status;
4227ccfe9b1SMichel JAOUEN 	u8 latch_offset, latch_val;
4237ccfe9b1SMichel JAOUEN 
4247ccfe9b1SMichel JAOUEN 	do {
4257ccfe9b1SMichel JAOUEN 		latch_bit = __ffs(hier_val);
4267ccfe9b1SMichel JAOUEN 		latch_offset = (hier_offset << 3) + latch_bit;
4277ccfe9b1SMichel JAOUEN 
4287ccfe9b1SMichel JAOUEN 		/* Fix inconsistent ITFromLatch25 bit mapping... */
4297ccfe9b1SMichel JAOUEN 		if (unlikely(latch_offset == 17))
4307ccfe9b1SMichel JAOUEN 			latch_offset = 24;
4317ccfe9b1SMichel JAOUEN 
4327ccfe9b1SMichel JAOUEN 		status = get_register_interruptible(ab8500,
4337ccfe9b1SMichel JAOUEN 				AB8500_INTERRUPT,
4347ccfe9b1SMichel JAOUEN 				AB8500_IT_LATCH1_REG + latch_offset,
4357ccfe9b1SMichel JAOUEN 				&latch_val);
4367ccfe9b1SMichel JAOUEN 		if (status < 0 || latch_val == 0)
4377ccfe9b1SMichel JAOUEN 			goto discard;
4387ccfe9b1SMichel JAOUEN 
4397ccfe9b1SMichel JAOUEN 		status = ab8500_handle_hierarchical_line(ab8500,
4407ccfe9b1SMichel JAOUEN 				latch_offset, latch_val);
4417ccfe9b1SMichel JAOUEN 		if (status < 0)
4427ccfe9b1SMichel JAOUEN 			return status;
4437ccfe9b1SMichel JAOUEN discard:
4447ccfe9b1SMichel JAOUEN 		hier_val &= ~(1 << latch_bit);
4457ccfe9b1SMichel JAOUEN 	} while (hier_val);
4467ccfe9b1SMichel JAOUEN 
4477ccfe9b1SMichel JAOUEN 	return 0;
4487ccfe9b1SMichel JAOUEN }
4497ccfe9b1SMichel JAOUEN 
4507ccfe9b1SMichel JAOUEN static irqreturn_t ab8500_hierarchical_irq(int irq, void *dev)
4517ccfe9b1SMichel JAOUEN {
4527ccfe9b1SMichel JAOUEN 	struct ab8500 *ab8500 = dev;
4537ccfe9b1SMichel JAOUEN 	u8 i;
4547ccfe9b1SMichel JAOUEN 
4557ccfe9b1SMichel JAOUEN 	dev_vdbg(ab8500->dev, "interrupt\n");
4567ccfe9b1SMichel JAOUEN 
4577ccfe9b1SMichel JAOUEN 	/*  Hierarchical interrupt version */
4587ccfe9b1SMichel JAOUEN 	for (i = 0; i < AB8500_IT_LATCHHIER_NUM; i++) {
4597ccfe9b1SMichel JAOUEN 		int status;
4607ccfe9b1SMichel JAOUEN 		u8 hier_val;
4617ccfe9b1SMichel JAOUEN 
4627ccfe9b1SMichel JAOUEN 		status = get_register_interruptible(ab8500, AB8500_INTERRUPT,
4637ccfe9b1SMichel JAOUEN 			AB8500_IT_LATCHHIER1_REG + i, &hier_val);
4647ccfe9b1SMichel JAOUEN 		if (status < 0 || hier_val == 0)
4657ccfe9b1SMichel JAOUEN 			continue;
4667ccfe9b1SMichel JAOUEN 
4677ccfe9b1SMichel JAOUEN 		status = ab8500_handle_hierarchical_latch(ab8500, i, hier_val);
4687ccfe9b1SMichel JAOUEN 		if (status < 0)
4697ccfe9b1SMichel JAOUEN 			break;
4707ccfe9b1SMichel JAOUEN 	}
4717ccfe9b1SMichel JAOUEN 	return IRQ_HANDLED;
4727ccfe9b1SMichel JAOUEN }
4737ccfe9b1SMichel JAOUEN 
47462579266SRabin Vincent static irqreturn_t ab8500_irq(int irq, void *dev)
47562579266SRabin Vincent {
47662579266SRabin Vincent 	struct ab8500 *ab8500 = dev;
47762579266SRabin Vincent 	int i;
47862579266SRabin Vincent 
47962579266SRabin Vincent 	dev_vdbg(ab8500->dev, "interrupt\n");
48062579266SRabin Vincent 
481112a80d2SJonas Aaberg 	atomic_inc(&ab8500->transfer_ongoing);
482112a80d2SJonas Aaberg 
4832ced445eSLinus Walleij 	for (i = 0; i < ab8500->mask_size; i++) {
4842ced445eSLinus Walleij 		int regoffset = ab8500->irq_reg_offset[i];
48562579266SRabin Vincent 		int status;
48647c16975SMattias Wallin 		u8 value;
48762579266SRabin Vincent 
4880f620837SLinus Walleij 		/*
4890f620837SLinus Walleij 		 * Interrupt register 12 doesn't exist prior to AB8500 version
4900f620837SLinus Walleij 		 * 2.0
4910f620837SLinus Walleij 		 */
4920f620837SLinus Walleij 		if (regoffset == 11 && is_ab8500_1p1_or_earlier(ab8500))
49392d50a41SMattias Wallin 			continue;
49492d50a41SMattias Wallin 
49547c16975SMattias Wallin 		status = get_register_interruptible(ab8500, AB8500_INTERRUPT,
49647c16975SMattias Wallin 			AB8500_IT_LATCH1_REG + regoffset, &value);
49747c16975SMattias Wallin 		if (status < 0 || value == 0)
49862579266SRabin Vincent 			continue;
49962579266SRabin Vincent 
50062579266SRabin Vincent 		do {
50188aec4f7SMattias Wallin 			int bit = __ffs(value);
50262579266SRabin Vincent 			int line = i * 8 + bit;
50362579266SRabin Vincent 
50462579266SRabin Vincent 			handle_nested_irq(ab8500->irq_base + line);
50547c16975SMattias Wallin 			value &= ~(1 << bit);
506112a80d2SJonas Aaberg 
50747c16975SMattias Wallin 		} while (value);
50862579266SRabin Vincent 	}
509112a80d2SJonas Aaberg 	atomic_dec(&ab8500->transfer_ongoing);
51062579266SRabin Vincent 	return IRQ_HANDLED;
51162579266SRabin Vincent }
51262579266SRabin Vincent 
51362579266SRabin Vincent static int ab8500_irq_init(struct ab8500 *ab8500)
51462579266SRabin Vincent {
51562579266SRabin Vincent 	int base = ab8500->irq_base;
51662579266SRabin Vincent 	int irq;
5172ced445eSLinus Walleij 	int num_irqs;
51862579266SRabin Vincent 
519d6255529SLinus Walleij 	if (is_ab9540(ab8500))
520d6255529SLinus Walleij 		num_irqs = AB9540_NR_IRQS;
521a982362cSBengt Jonsson 	else if (is_ab8505(ab8500))
522a982362cSBengt Jonsson 		num_irqs = AB8505_NR_IRQS;
523d6255529SLinus Walleij 	else
5242ced445eSLinus Walleij 		num_irqs = AB8500_NR_IRQS;
5252ced445eSLinus Walleij 
5262ced445eSLinus Walleij 	for (irq = base; irq < base + num_irqs; irq++) {
527d5bb1221SThomas Gleixner 		irq_set_chip_data(irq, ab8500);
528d5bb1221SThomas Gleixner 		irq_set_chip_and_handler(irq, &ab8500_irq_chip,
52962579266SRabin Vincent 					 handle_simple_irq);
530d5bb1221SThomas Gleixner 		irq_set_nested_thread(irq, 1);
53162579266SRabin Vincent #ifdef CONFIG_ARM
53262579266SRabin Vincent 		set_irq_flags(irq, IRQF_VALID);
53362579266SRabin Vincent #else
534d5bb1221SThomas Gleixner 		irq_set_noprobe(irq);
53562579266SRabin Vincent #endif
53662579266SRabin Vincent 	}
53762579266SRabin Vincent 
53862579266SRabin Vincent 	return 0;
53962579266SRabin Vincent }
54062579266SRabin Vincent 
54162579266SRabin Vincent static void ab8500_irq_remove(struct ab8500 *ab8500)
54262579266SRabin Vincent {
54362579266SRabin Vincent 	int base = ab8500->irq_base;
54462579266SRabin Vincent 	int irq;
5452ced445eSLinus Walleij 	int num_irqs;
54662579266SRabin Vincent 
547d6255529SLinus Walleij 	if (is_ab9540(ab8500))
548d6255529SLinus Walleij 		num_irqs = AB9540_NR_IRQS;
549a982362cSBengt Jonsson 	else if (is_ab8505(ab8500))
550a982362cSBengt Jonsson 		num_irqs = AB8505_NR_IRQS;
551d6255529SLinus Walleij 	else
5522ced445eSLinus Walleij 		num_irqs = AB8500_NR_IRQS;
5532ced445eSLinus Walleij 
5542ced445eSLinus Walleij 	for (irq = base; irq < base + num_irqs; irq++) {
55562579266SRabin Vincent #ifdef CONFIG_ARM
55662579266SRabin Vincent 		set_irq_flags(irq, 0);
55762579266SRabin Vincent #endif
558d5bb1221SThomas Gleixner 		irq_set_chip_and_handler(irq, NULL, NULL);
559d5bb1221SThomas Gleixner 		irq_set_chip_data(irq, NULL);
56062579266SRabin Vincent 	}
56162579266SRabin Vincent }
56262579266SRabin Vincent 
563112a80d2SJonas Aaberg int ab8500_suspend(struct ab8500 *ab8500)
564112a80d2SJonas Aaberg {
565112a80d2SJonas Aaberg 	if (atomic_read(&ab8500->transfer_ongoing))
566112a80d2SJonas Aaberg 		return -EINVAL;
567112a80d2SJonas Aaberg 	else
568112a80d2SJonas Aaberg 		return 0;
569112a80d2SJonas Aaberg }
570112a80d2SJonas Aaberg 
571d6255529SLinus Walleij /* AB8500 GPIO Resources */
5725cef8df5SRobert Rosengren static struct resource __devinitdata ab8500_gpio_resources[] = {
5730cb3fcd7SBibek Basu 	{
5740cb3fcd7SBibek Basu 		.name	= "GPIO_INT6",
5750cb3fcd7SBibek Basu 		.start	= AB8500_INT_GPIO6R,
5760cb3fcd7SBibek Basu 		.end	= AB8500_INT_GPIO41F,
5770cb3fcd7SBibek Basu 		.flags	= IORESOURCE_IRQ,
5780cb3fcd7SBibek Basu 	}
5790cb3fcd7SBibek Basu };
5800cb3fcd7SBibek Basu 
581d6255529SLinus Walleij /* AB9540 GPIO Resources */
582d6255529SLinus Walleij static struct resource __devinitdata ab9540_gpio_resources[] = {
583d6255529SLinus Walleij 	{
584d6255529SLinus Walleij 		.name	= "GPIO_INT6",
585d6255529SLinus Walleij 		.start	= AB8500_INT_GPIO6R,
586d6255529SLinus Walleij 		.end	= AB8500_INT_GPIO41F,
587d6255529SLinus Walleij 		.flags	= IORESOURCE_IRQ,
588d6255529SLinus Walleij 	},
589d6255529SLinus Walleij 	{
590d6255529SLinus Walleij 		.name	= "GPIO_INT14",
591d6255529SLinus Walleij 		.start	= AB9540_INT_GPIO50R,
592d6255529SLinus Walleij 		.end	= AB9540_INT_GPIO54R,
593d6255529SLinus Walleij 		.flags	= IORESOURCE_IRQ,
594d6255529SLinus Walleij 	},
595d6255529SLinus Walleij 	{
596d6255529SLinus Walleij 		.name	= "GPIO_INT15",
597d6255529SLinus Walleij 		.start	= AB9540_INT_GPIO50F,
598d6255529SLinus Walleij 		.end	= AB9540_INT_GPIO54F,
599d6255529SLinus Walleij 		.flags	= IORESOURCE_IRQ,
600d6255529SLinus Walleij 	}
601d6255529SLinus Walleij };
602d6255529SLinus Walleij 
6035cef8df5SRobert Rosengren static struct resource __devinitdata ab8500_gpadc_resources[] = {
60462579266SRabin Vincent 	{
60562579266SRabin Vincent 		.name	= "HW_CONV_END",
60662579266SRabin Vincent 		.start	= AB8500_INT_GP_HW_ADC_CONV_END,
60762579266SRabin Vincent 		.end	= AB8500_INT_GP_HW_ADC_CONV_END,
60862579266SRabin Vincent 		.flags	= IORESOURCE_IRQ,
60962579266SRabin Vincent 	},
61062579266SRabin Vincent 	{
61162579266SRabin Vincent 		.name	= "SW_CONV_END",
61262579266SRabin Vincent 		.start	= AB8500_INT_GP_SW_ADC_CONV_END,
61362579266SRabin Vincent 		.end	= AB8500_INT_GP_SW_ADC_CONV_END,
61462579266SRabin Vincent 		.flags	= IORESOURCE_IRQ,
61562579266SRabin Vincent 	},
61662579266SRabin Vincent };
61762579266SRabin Vincent 
6185cef8df5SRobert Rosengren static struct resource __devinitdata ab8500_rtc_resources[] = {
61962579266SRabin Vincent 	{
62062579266SRabin Vincent 		.name	= "60S",
62162579266SRabin Vincent 		.start	= AB8500_INT_RTC_60S,
62262579266SRabin Vincent 		.end	= AB8500_INT_RTC_60S,
62362579266SRabin Vincent 		.flags	= IORESOURCE_IRQ,
62462579266SRabin Vincent 	},
62562579266SRabin Vincent 	{
62662579266SRabin Vincent 		.name	= "ALARM",
62762579266SRabin Vincent 		.start	= AB8500_INT_RTC_ALARM,
62862579266SRabin Vincent 		.end	= AB8500_INT_RTC_ALARM,
62962579266SRabin Vincent 		.flags	= IORESOURCE_IRQ,
63062579266SRabin Vincent 	},
63162579266SRabin Vincent };
63262579266SRabin Vincent 
6335cef8df5SRobert Rosengren static struct resource __devinitdata ab8500_poweronkey_db_resources[] = {
63477686517SSundar R Iyer 	{
63577686517SSundar R Iyer 		.name	= "ONKEY_DBF",
63677686517SSundar R Iyer 		.start	= AB8500_INT_PON_KEY1DB_F,
63777686517SSundar R Iyer 		.end	= AB8500_INT_PON_KEY1DB_F,
63877686517SSundar R Iyer 		.flags	= IORESOURCE_IRQ,
63977686517SSundar R Iyer 	},
64077686517SSundar R Iyer 	{
64177686517SSundar R Iyer 		.name	= "ONKEY_DBR",
64277686517SSundar R Iyer 		.start	= AB8500_INT_PON_KEY1DB_R,
64377686517SSundar R Iyer 		.end	= AB8500_INT_PON_KEY1DB_R,
64477686517SSundar R Iyer 		.flags	= IORESOURCE_IRQ,
64577686517SSundar R Iyer 	},
64677686517SSundar R Iyer };
64777686517SSundar R Iyer 
6486af75ecdSLinus Walleij static struct resource __devinitdata ab8500_av_acc_detect_resources[] = {
649e098adedSMattias Wallin 	{
6506af75ecdSLinus Walleij 	       .name = "ACC_DETECT_1DB_F",
6516af75ecdSLinus Walleij 	       .start = AB8500_INT_ACC_DETECT_1DB_F,
6526af75ecdSLinus Walleij 	       .end = AB8500_INT_ACC_DETECT_1DB_F,
653e098adedSMattias Wallin 	       .flags = IORESOURCE_IRQ,
654e098adedSMattias Wallin 	},
655e098adedSMattias Wallin 	{
6566af75ecdSLinus Walleij 	       .name = "ACC_DETECT_1DB_R",
6576af75ecdSLinus Walleij 	       .start = AB8500_INT_ACC_DETECT_1DB_R,
6586af75ecdSLinus Walleij 	       .end = AB8500_INT_ACC_DETECT_1DB_R,
659e098adedSMattias Wallin 	       .flags = IORESOURCE_IRQ,
660e098adedSMattias Wallin 	},
661e098adedSMattias Wallin 	{
6626af75ecdSLinus Walleij 	       .name = "ACC_DETECT_21DB_F",
6636af75ecdSLinus Walleij 	       .start = AB8500_INT_ACC_DETECT_21DB_F,
6646af75ecdSLinus Walleij 	       .end = AB8500_INT_ACC_DETECT_21DB_F,
6656af75ecdSLinus Walleij 	       .flags = IORESOURCE_IRQ,
6666af75ecdSLinus Walleij 	},
6676af75ecdSLinus Walleij 	{
6686af75ecdSLinus Walleij 	       .name = "ACC_DETECT_21DB_R",
6696af75ecdSLinus Walleij 	       .start = AB8500_INT_ACC_DETECT_21DB_R,
6706af75ecdSLinus Walleij 	       .end = AB8500_INT_ACC_DETECT_21DB_R,
6716af75ecdSLinus Walleij 	       .flags = IORESOURCE_IRQ,
6726af75ecdSLinus Walleij 	},
6736af75ecdSLinus Walleij 	{
6746af75ecdSLinus Walleij 	       .name = "ACC_DETECT_22DB_F",
6756af75ecdSLinus Walleij 	       .start = AB8500_INT_ACC_DETECT_22DB_F,
6766af75ecdSLinus Walleij 	       .end = AB8500_INT_ACC_DETECT_22DB_F,
6776af75ecdSLinus Walleij 	       .flags = IORESOURCE_IRQ,
6786af75ecdSLinus Walleij 	},
6796af75ecdSLinus Walleij 	{
6806af75ecdSLinus Walleij 	       .name = "ACC_DETECT_22DB_R",
6816af75ecdSLinus Walleij 	       .start = AB8500_INT_ACC_DETECT_22DB_R,
6826af75ecdSLinus Walleij 	       .end = AB8500_INT_ACC_DETECT_22DB_R,
6836af75ecdSLinus Walleij 	       .flags = IORESOURCE_IRQ,
6846af75ecdSLinus Walleij 	},
6856af75ecdSLinus Walleij };
6866af75ecdSLinus Walleij 
6876af75ecdSLinus Walleij static struct resource __devinitdata ab8500_charger_resources[] = {
6886af75ecdSLinus Walleij 	{
689e098adedSMattias Wallin 		.name = "MAIN_CH_UNPLUG_DET",
690e098adedSMattias Wallin 		.start = AB8500_INT_MAIN_CH_UNPLUG_DET,
691e098adedSMattias Wallin 		.end = AB8500_INT_MAIN_CH_UNPLUG_DET,
692e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
693e098adedSMattias Wallin 	},
694e098adedSMattias Wallin 	{
695e098adedSMattias Wallin 		.name = "MAIN_CHARGE_PLUG_DET",
696e098adedSMattias Wallin 		.start = AB8500_INT_MAIN_CH_PLUG_DET,
697e098adedSMattias Wallin 		.end = AB8500_INT_MAIN_CH_PLUG_DET,
698e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
699e098adedSMattias Wallin 	},
700e098adedSMattias Wallin 	{
701e098adedSMattias Wallin 		.name = "VBUS_DET_R",
702e098adedSMattias Wallin 		.start = AB8500_INT_VBUS_DET_R,
703e098adedSMattias Wallin 		.end = AB8500_INT_VBUS_DET_R,
704e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
705e098adedSMattias Wallin 	},
706e098adedSMattias Wallin 	{
7076af75ecdSLinus Walleij 		.name = "VBUS_DET_F",
7086af75ecdSLinus Walleij 		.start = AB8500_INT_VBUS_DET_F,
7096af75ecdSLinus Walleij 		.end = AB8500_INT_VBUS_DET_F,
710e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
711e098adedSMattias Wallin 	},
712e098adedSMattias Wallin 	{
7136af75ecdSLinus Walleij 		.name = "USB_LINK_STATUS",
7146af75ecdSLinus Walleij 		.start = AB8500_INT_USB_LINK_STATUS,
7156af75ecdSLinus Walleij 		.end = AB8500_INT_USB_LINK_STATUS,
7166af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
7176af75ecdSLinus Walleij 	},
7186af75ecdSLinus Walleij 	{
719e098adedSMattias Wallin 		.name = "VBUS_OVV",
720e098adedSMattias Wallin 		.start = AB8500_INT_VBUS_OVV,
721e098adedSMattias Wallin 		.end = AB8500_INT_VBUS_OVV,
722e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
723e098adedSMattias Wallin 	},
724e098adedSMattias Wallin 	{
7256af75ecdSLinus Walleij 		.name = "USB_CH_TH_PROT_R",
7266af75ecdSLinus Walleij 		.start = AB8500_INT_USB_CH_TH_PROT_R,
7276af75ecdSLinus Walleij 		.end = AB8500_INT_USB_CH_TH_PROT_R,
728e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
729e098adedSMattias Wallin 	},
730e098adedSMattias Wallin 	{
7316af75ecdSLinus Walleij 		.name = "USB_CH_TH_PROT_F",
7326af75ecdSLinus Walleij 		.start = AB8500_INT_USB_CH_TH_PROT_F,
7336af75ecdSLinus Walleij 		.end = AB8500_INT_USB_CH_TH_PROT_F,
734e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
735e098adedSMattias Wallin 	},
736e098adedSMattias Wallin 	{
7376af75ecdSLinus Walleij 		.name = "MAIN_EXT_CH_NOT_OK",
7386af75ecdSLinus Walleij 		.start = AB8500_INT_MAIN_EXT_CH_NOT_OK,
7396af75ecdSLinus Walleij 		.end = AB8500_INT_MAIN_EXT_CH_NOT_OK,
7406af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
7416af75ecdSLinus Walleij 	},
7426af75ecdSLinus Walleij 	{
7436af75ecdSLinus Walleij 		.name = "MAIN_CH_TH_PROT_R",
7446af75ecdSLinus Walleij 		.start = AB8500_INT_MAIN_CH_TH_PROT_R,
7456af75ecdSLinus Walleij 		.end = AB8500_INT_MAIN_CH_TH_PROT_R,
7466af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
7476af75ecdSLinus Walleij 	},
7486af75ecdSLinus Walleij 	{
7496af75ecdSLinus Walleij 		.name = "MAIN_CH_TH_PROT_F",
7506af75ecdSLinus Walleij 		.start = AB8500_INT_MAIN_CH_TH_PROT_F,
7516af75ecdSLinus Walleij 		.end = AB8500_INT_MAIN_CH_TH_PROT_F,
7526af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
7536af75ecdSLinus Walleij 	},
7546af75ecdSLinus Walleij 	{
7556af75ecdSLinus Walleij 		.name = "USB_CHARGER_NOT_OKR",
756a982362cSBengt Jonsson 		.start = AB8500_INT_USB_CHARGER_NOT_OKR,
757a982362cSBengt Jonsson 		.end = AB8500_INT_USB_CHARGER_NOT_OKR,
7586af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
7596af75ecdSLinus Walleij 	},
7606af75ecdSLinus Walleij 	{
7616af75ecdSLinus Walleij 		.name = "CH_WD_EXP",
7626af75ecdSLinus Walleij 		.start = AB8500_INT_CH_WD_EXP,
7636af75ecdSLinus Walleij 		.end = AB8500_INT_CH_WD_EXP,
7646af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
7656af75ecdSLinus Walleij 	},
7666af75ecdSLinus Walleij };
7676af75ecdSLinus Walleij 
7686af75ecdSLinus Walleij static struct resource __devinitdata ab8500_btemp_resources[] = {
7696af75ecdSLinus Walleij 	{
7706af75ecdSLinus Walleij 		.name = "BAT_CTRL_INDB",
7716af75ecdSLinus Walleij 		.start = AB8500_INT_BAT_CTRL_INDB,
7726af75ecdSLinus Walleij 		.end = AB8500_INT_BAT_CTRL_INDB,
773e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
774e098adedSMattias Wallin 	},
775e098adedSMattias Wallin 	{
776e098adedSMattias Wallin 		.name = "BTEMP_LOW",
777e098adedSMattias Wallin 		.start = AB8500_INT_BTEMP_LOW,
778e098adedSMattias Wallin 		.end = AB8500_INT_BTEMP_LOW,
779e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
780e098adedSMattias Wallin 	},
781e098adedSMattias Wallin 	{
782e098adedSMattias Wallin 		.name = "BTEMP_HIGH",
783e098adedSMattias Wallin 		.start = AB8500_INT_BTEMP_HIGH,
784e098adedSMattias Wallin 		.end = AB8500_INT_BTEMP_HIGH,
785e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
786e098adedSMattias Wallin 	},
787e098adedSMattias Wallin 	{
7886af75ecdSLinus Walleij 		.name = "BTEMP_LOW_MEDIUM",
7896af75ecdSLinus Walleij 		.start = AB8500_INT_BTEMP_LOW_MEDIUM,
7906af75ecdSLinus Walleij 		.end = AB8500_INT_BTEMP_LOW_MEDIUM,
791e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
792e098adedSMattias Wallin 	},
793e098adedSMattias Wallin 	{
7946af75ecdSLinus Walleij 		.name = "BTEMP_MEDIUM_HIGH",
7956af75ecdSLinus Walleij 		.start = AB8500_INT_BTEMP_MEDIUM_HIGH,
7966af75ecdSLinus Walleij 		.end = AB8500_INT_BTEMP_MEDIUM_HIGH,
797e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
798e098adedSMattias Wallin 	},
799e098adedSMattias Wallin };
800e098adedSMattias Wallin 
8016af75ecdSLinus Walleij static struct resource __devinitdata ab8500_fg_resources[] = {
8026af75ecdSLinus Walleij 	{
8036af75ecdSLinus Walleij 		.name = "NCONV_ACCU",
8046af75ecdSLinus Walleij 		.start = AB8500_INT_CCN_CONV_ACC,
8056af75ecdSLinus Walleij 		.end = AB8500_INT_CCN_CONV_ACC,
8066af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
8076af75ecdSLinus Walleij 	},
8086af75ecdSLinus Walleij 	{
8096af75ecdSLinus Walleij 		.name = "BATT_OVV",
8106af75ecdSLinus Walleij 		.start = AB8500_INT_BATT_OVV,
8116af75ecdSLinus Walleij 		.end = AB8500_INT_BATT_OVV,
8126af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
8136af75ecdSLinus Walleij 	},
8146af75ecdSLinus Walleij 	{
8156af75ecdSLinus Walleij 		.name = "LOW_BAT_F",
8166af75ecdSLinus Walleij 		.start = AB8500_INT_LOW_BAT_F,
8176af75ecdSLinus Walleij 		.end = AB8500_INT_LOW_BAT_F,
8186af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
8196af75ecdSLinus Walleij 	},
8206af75ecdSLinus Walleij 	{
8216af75ecdSLinus Walleij 		.name = "LOW_BAT_R",
8226af75ecdSLinus Walleij 		.start = AB8500_INT_LOW_BAT_R,
8236af75ecdSLinus Walleij 		.end = AB8500_INT_LOW_BAT_R,
8246af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
8256af75ecdSLinus Walleij 	},
8266af75ecdSLinus Walleij 	{
8276af75ecdSLinus Walleij 		.name = "CC_INT_CALIB",
8286af75ecdSLinus Walleij 		.start = AB8500_INT_CC_INT_CALIB,
8296af75ecdSLinus Walleij 		.end = AB8500_INT_CC_INT_CALIB,
8306af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
8316af75ecdSLinus Walleij 	},
832a982362cSBengt Jonsson 	{
833a982362cSBengt Jonsson 		.name = "CCEOC",
834a982362cSBengt Jonsson 		.start = AB8500_INT_CCEOC,
835a982362cSBengt Jonsson 		.end = AB8500_INT_CCEOC,
836a982362cSBengt Jonsson 		.flags = IORESOURCE_IRQ,
837a982362cSBengt Jonsson 	},
8386af75ecdSLinus Walleij };
8396af75ecdSLinus Walleij 
8406af75ecdSLinus Walleij static struct resource __devinitdata ab8500_chargalg_resources[] = {};
8416af75ecdSLinus Walleij 
842df720647SAxel Lin #ifdef CONFIG_DEBUG_FS
8435cef8df5SRobert Rosengren static struct resource __devinitdata ab8500_debug_resources[] = {
844e098adedSMattias Wallin 	{
845e098adedSMattias Wallin 		.name	= "IRQ_FIRST",
846e098adedSMattias Wallin 		.start	= AB8500_INT_MAIN_EXT_CH_NOT_OK,
847e098adedSMattias Wallin 		.end	= AB8500_INT_MAIN_EXT_CH_NOT_OK,
848e098adedSMattias Wallin 		.flags	= IORESOURCE_IRQ,
849e098adedSMattias Wallin 	},
850e098adedSMattias Wallin 	{
851e098adedSMattias Wallin 		.name	= "IRQ_LAST",
852a982362cSBengt Jonsson 		.start	= AB8500_INT_XTAL32K_KO,
853a982362cSBengt Jonsson 		.end	= AB8500_INT_XTAL32K_KO,
854e098adedSMattias Wallin 		.flags	= IORESOURCE_IRQ,
855e098adedSMattias Wallin 	},
856e098adedSMattias Wallin };
857df720647SAxel Lin #endif
858e098adedSMattias Wallin 
8595cef8df5SRobert Rosengren static struct resource __devinitdata ab8500_usb_resources[] = {
860e098adedSMattias Wallin 	{
861e098adedSMattias Wallin 		.name = "ID_WAKEUP_R",
862e098adedSMattias Wallin 		.start = AB8500_INT_ID_WAKEUP_R,
863e098adedSMattias Wallin 		.end = AB8500_INT_ID_WAKEUP_R,
864e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
865e098adedSMattias Wallin 	},
866e098adedSMattias Wallin 	{
867e098adedSMattias Wallin 		.name = "ID_WAKEUP_F",
868e098adedSMattias Wallin 		.start = AB8500_INT_ID_WAKEUP_F,
869e098adedSMattias Wallin 		.end = AB8500_INT_ID_WAKEUP_F,
870e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
871e098adedSMattias Wallin 	},
872e098adedSMattias Wallin 	{
873e098adedSMattias Wallin 		.name = "VBUS_DET_F",
874e098adedSMattias Wallin 		.start = AB8500_INT_VBUS_DET_F,
875e098adedSMattias Wallin 		.end = AB8500_INT_VBUS_DET_F,
876e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
877e098adedSMattias Wallin 	},
878e098adedSMattias Wallin 	{
879e098adedSMattias Wallin 		.name = "VBUS_DET_R",
880e098adedSMattias Wallin 		.start = AB8500_INT_VBUS_DET_R,
881e098adedSMattias Wallin 		.end = AB8500_INT_VBUS_DET_R,
882e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
883e098adedSMattias Wallin 	},
88492d50a41SMattias Wallin 	{
88592d50a41SMattias Wallin 		.name = "USB_LINK_STATUS",
88692d50a41SMattias Wallin 		.start = AB8500_INT_USB_LINK_STATUS,
88792d50a41SMattias Wallin 		.end = AB8500_INT_USB_LINK_STATUS,
88892d50a41SMattias Wallin 		.flags = IORESOURCE_IRQ,
88992d50a41SMattias Wallin 	},
8906af75ecdSLinus Walleij 	{
8916af75ecdSLinus Walleij 		.name = "USB_ADP_PROBE_PLUG",
8926af75ecdSLinus Walleij 		.start = AB8500_INT_ADP_PROBE_PLUG,
8936af75ecdSLinus Walleij 		.end = AB8500_INT_ADP_PROBE_PLUG,
8946af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
8956af75ecdSLinus Walleij 	},
8966af75ecdSLinus Walleij 	{
8976af75ecdSLinus Walleij 		.name = "USB_ADP_PROBE_UNPLUG",
8986af75ecdSLinus Walleij 		.start = AB8500_INT_ADP_PROBE_UNPLUG,
8996af75ecdSLinus Walleij 		.end = AB8500_INT_ADP_PROBE_UNPLUG,
9006af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
9016af75ecdSLinus Walleij 	},
902e098adedSMattias Wallin };
903e098adedSMattias Wallin 
90444f72e53SVirupax Sadashivpetimath static struct resource __devinitdata ab8505_iddet_resources[] = {
90544f72e53SVirupax Sadashivpetimath 	{
90644f72e53SVirupax Sadashivpetimath 		.name  = "KeyDeglitch",
90744f72e53SVirupax Sadashivpetimath 		.start = AB8505_INT_KEYDEGLITCH,
90844f72e53SVirupax Sadashivpetimath 		.end   = AB8505_INT_KEYDEGLITCH,
90944f72e53SVirupax Sadashivpetimath 		.flags = IORESOURCE_IRQ,
91044f72e53SVirupax Sadashivpetimath 	},
91144f72e53SVirupax Sadashivpetimath 	{
91244f72e53SVirupax Sadashivpetimath 		.name  = "KP",
91344f72e53SVirupax Sadashivpetimath 		.start = AB8505_INT_KP,
91444f72e53SVirupax Sadashivpetimath 		.end   = AB8505_INT_KP,
91544f72e53SVirupax Sadashivpetimath 		.flags = IORESOURCE_IRQ,
91644f72e53SVirupax Sadashivpetimath 	},
91744f72e53SVirupax Sadashivpetimath 	{
91844f72e53SVirupax Sadashivpetimath 		.name  = "IKP",
91944f72e53SVirupax Sadashivpetimath 		.start = AB8505_INT_IKP,
92044f72e53SVirupax Sadashivpetimath 		.end   = AB8505_INT_IKP,
92144f72e53SVirupax Sadashivpetimath 		.flags = IORESOURCE_IRQ,
92244f72e53SVirupax Sadashivpetimath 	},
92344f72e53SVirupax Sadashivpetimath 	{
92444f72e53SVirupax Sadashivpetimath 		.name  = "IKR",
92544f72e53SVirupax Sadashivpetimath 		.start = AB8505_INT_IKR,
92644f72e53SVirupax Sadashivpetimath 		.end   = AB8505_INT_IKR,
92744f72e53SVirupax Sadashivpetimath 		.flags = IORESOURCE_IRQ,
92844f72e53SVirupax Sadashivpetimath 	},
92944f72e53SVirupax Sadashivpetimath 	{
93044f72e53SVirupax Sadashivpetimath 		.name  = "KeyStuck",
93144f72e53SVirupax Sadashivpetimath 		.start = AB8505_INT_KEYSTUCK,
93244f72e53SVirupax Sadashivpetimath 		.end   = AB8505_INT_KEYSTUCK,
93344f72e53SVirupax Sadashivpetimath 		.flags = IORESOURCE_IRQ,
93444f72e53SVirupax Sadashivpetimath 	},
93544f72e53SVirupax Sadashivpetimath };
93644f72e53SVirupax Sadashivpetimath 
9375cef8df5SRobert Rosengren static struct resource __devinitdata ab8500_temp_resources[] = {
938e098adedSMattias Wallin 	{
939e098adedSMattias Wallin 		.name  = "AB8500_TEMP_WARM",
940e098adedSMattias Wallin 		.start = AB8500_INT_TEMP_WARM,
941e098adedSMattias Wallin 		.end   = AB8500_INT_TEMP_WARM,
942e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
943e098adedSMattias Wallin 	},
944e098adedSMattias Wallin };
945e098adedSMattias Wallin 
946d6255529SLinus Walleij static struct mfd_cell __devinitdata abx500_common_devs[] = {
9475814fc35SMattias Wallin #ifdef CONFIG_DEBUG_FS
9485814fc35SMattias Wallin 	{
9495814fc35SMattias Wallin 		.name = "ab8500-debug",
950e098adedSMattias Wallin 		.num_resources = ARRAY_SIZE(ab8500_debug_resources),
951e098adedSMattias Wallin 		.resources = ab8500_debug_resources,
9525814fc35SMattias Wallin 	},
9535814fc35SMattias Wallin #endif
95462579266SRabin Vincent 	{
955e098adedSMattias Wallin 		.name = "ab8500-sysctrl",
956e098adedSMattias Wallin 	},
957e098adedSMattias Wallin 	{
958e098adedSMattias Wallin 		.name = "ab8500-regulator",
959e098adedSMattias Wallin 	},
960e098adedSMattias Wallin 	{
96162579266SRabin Vincent 		.name = "ab8500-gpadc",
96262579266SRabin Vincent 		.num_resources = ARRAY_SIZE(ab8500_gpadc_resources),
96362579266SRabin Vincent 		.resources = ab8500_gpadc_resources,
96462579266SRabin Vincent 	},
96562579266SRabin Vincent 	{
96662579266SRabin Vincent 		.name = "ab8500-rtc",
96762579266SRabin Vincent 		.num_resources = ARRAY_SIZE(ab8500_rtc_resources),
96862579266SRabin Vincent 		.resources = ab8500_rtc_resources,
96962579266SRabin Vincent 	},
970f0f05b1cSArun Murthy 	{
9716af75ecdSLinus Walleij 		.name = "ab8500-acc-det",
9726af75ecdSLinus Walleij 		.num_resources = ARRAY_SIZE(ab8500_av_acc_detect_resources),
9736af75ecdSLinus Walleij 		.resources = ab8500_av_acc_detect_resources,
9746af75ecdSLinus Walleij 	},
9756af75ecdSLinus Walleij 	{
976e098adedSMattias Wallin 		.name = "ab8500-poweron-key",
977e098adedSMattias Wallin 		.num_resources = ARRAY_SIZE(ab8500_poweronkey_db_resources),
978e098adedSMattias Wallin 		.resources = ab8500_poweronkey_db_resources,
979e098adedSMattias Wallin 	},
980e098adedSMattias Wallin 	{
981f0f05b1cSArun Murthy 		.name = "ab8500-pwm",
982f0f05b1cSArun Murthy 		.id = 1,
983f0f05b1cSArun Murthy 	},
984f0f05b1cSArun Murthy 	{
985f0f05b1cSArun Murthy 		.name = "ab8500-pwm",
986f0f05b1cSArun Murthy 		.id = 2,
987f0f05b1cSArun Murthy 	},
988f0f05b1cSArun Murthy 	{
989f0f05b1cSArun Murthy 		.name = "ab8500-pwm",
990f0f05b1cSArun Murthy 		.id = 3,
991f0f05b1cSArun Murthy 	},
992e098adedSMattias Wallin 	{ .name = "ab8500-leds", },
99377686517SSundar R Iyer 	{
994e098adedSMattias Wallin 		.name = "ab8500-denc",
995e098adedSMattias Wallin 	},
996e098adedSMattias Wallin 	{
997e098adedSMattias Wallin 		.name = "ab8500-temp",
998e098adedSMattias Wallin 		.num_resources = ARRAY_SIZE(ab8500_temp_resources),
999e098adedSMattias Wallin 		.resources = ab8500_temp_resources,
100077686517SSundar R Iyer 	},
100162579266SRabin Vincent };
100262579266SRabin Vincent 
10036ef9418cSRickard Andersson static struct mfd_cell __devinitdata ab8500_bm_devs[] = {
10046ef9418cSRickard Andersson 	{
10056ef9418cSRickard Andersson 		.name = "ab8500-charger",
10066ef9418cSRickard Andersson 		.num_resources = ARRAY_SIZE(ab8500_charger_resources),
10076ef9418cSRickard Andersson 		.resources = ab8500_charger_resources,
10086ef9418cSRickard Andersson 	},
10096ef9418cSRickard Andersson 	{
10106ef9418cSRickard Andersson 		.name = "ab8500-btemp",
10116ef9418cSRickard Andersson 		.num_resources = ARRAY_SIZE(ab8500_btemp_resources),
10126ef9418cSRickard Andersson 		.resources = ab8500_btemp_resources,
10136ef9418cSRickard Andersson 	},
10146ef9418cSRickard Andersson 	{
10156ef9418cSRickard Andersson 		.name = "ab8500-fg",
10166ef9418cSRickard Andersson 		.num_resources = ARRAY_SIZE(ab8500_fg_resources),
10176ef9418cSRickard Andersson 		.resources = ab8500_fg_resources,
10186ef9418cSRickard Andersson 	},
10196ef9418cSRickard Andersson 	{
10206ef9418cSRickard Andersson 		.name = "ab8500-chargalg",
10216ef9418cSRickard Andersson 		.num_resources = ARRAY_SIZE(ab8500_chargalg_resources),
10226ef9418cSRickard Andersson 		.resources = ab8500_chargalg_resources,
10236ef9418cSRickard Andersson 	},
10246ef9418cSRickard Andersson };
10256ef9418cSRickard Andersson 
1026d6255529SLinus Walleij static struct mfd_cell __devinitdata ab8500_devs[] = {
1027d6255529SLinus Walleij 	{
1028d6255529SLinus Walleij 		.name = "ab8500-gpio",
1029d6255529SLinus Walleij 		.num_resources = ARRAY_SIZE(ab8500_gpio_resources),
1030d6255529SLinus Walleij 		.resources = ab8500_gpio_resources,
1031d6255529SLinus Walleij 	},
1032d6255529SLinus Walleij 	{
1033d6255529SLinus Walleij 		.name = "ab8500-usb",
1034d6255529SLinus Walleij 		.num_resources = ARRAY_SIZE(ab8500_usb_resources),
1035d6255529SLinus Walleij 		.resources = ab8500_usb_resources,
1036d6255529SLinus Walleij 	},
103744f72e53SVirupax Sadashivpetimath 	{
103844f72e53SVirupax Sadashivpetimath 		.name = "ab8500-codec",
103944f72e53SVirupax Sadashivpetimath 	},
1040d6255529SLinus Walleij };
1041d6255529SLinus Walleij 
1042d6255529SLinus Walleij static struct mfd_cell __devinitdata ab9540_devs[] = {
1043d6255529SLinus Walleij 	{
1044d6255529SLinus Walleij 		.name = "ab8500-gpio",
1045d6255529SLinus Walleij 		.num_resources = ARRAY_SIZE(ab9540_gpio_resources),
1046d6255529SLinus Walleij 		.resources = ab9540_gpio_resources,
1047d6255529SLinus Walleij 	},
1048d6255529SLinus Walleij 	{
1049d6255529SLinus Walleij 		.name = "ab9540-usb",
1050d6255529SLinus Walleij 		.num_resources = ARRAY_SIZE(ab8500_usb_resources),
1051d6255529SLinus Walleij 		.resources = ab8500_usb_resources,
1052d6255529SLinus Walleij 	},
105344f72e53SVirupax Sadashivpetimath 	{
105444f72e53SVirupax Sadashivpetimath 		.name = "ab9540-codec",
105544f72e53SVirupax Sadashivpetimath 	},
105644f72e53SVirupax Sadashivpetimath };
105744f72e53SVirupax Sadashivpetimath 
105844f72e53SVirupax Sadashivpetimath /* Device list common to ab9540 and ab8505 */
105944f72e53SVirupax Sadashivpetimath static struct mfd_cell __devinitdata ab9540_ab8505_devs[] = {
106044f72e53SVirupax Sadashivpetimath 	{
106144f72e53SVirupax Sadashivpetimath 		.name = "ab-iddet",
106244f72e53SVirupax Sadashivpetimath 		.num_resources = ARRAY_SIZE(ab8505_iddet_resources),
106344f72e53SVirupax Sadashivpetimath 		.resources = ab8505_iddet_resources,
106444f72e53SVirupax Sadashivpetimath 	},
1065d6255529SLinus Walleij };
1066d6255529SLinus Walleij 
1067cca69b67SMattias Wallin static ssize_t show_chip_id(struct device *dev,
1068cca69b67SMattias Wallin 				struct device_attribute *attr, char *buf)
1069cca69b67SMattias Wallin {
1070cca69b67SMattias Wallin 	struct ab8500 *ab8500;
1071cca69b67SMattias Wallin 
1072cca69b67SMattias Wallin 	ab8500 = dev_get_drvdata(dev);
1073cca69b67SMattias Wallin 	return sprintf(buf, "%#x\n", ab8500 ? ab8500->chip_id : -EINVAL);
1074cca69b67SMattias Wallin }
1075cca69b67SMattias Wallin 
1076e5c238c3SMattias Wallin /*
1077e5c238c3SMattias Wallin  * ab8500 has switched off due to (SWITCH_OFF_STATUS):
1078e5c238c3SMattias Wallin  * 0x01 Swoff bit programming
1079e5c238c3SMattias Wallin  * 0x02 Thermal protection activation
1080e5c238c3SMattias Wallin  * 0x04 Vbat lower then BattOk falling threshold
1081e5c238c3SMattias Wallin  * 0x08 Watchdog expired
1082e5c238c3SMattias Wallin  * 0x10 Non presence of 32kHz clock
1083e5c238c3SMattias Wallin  * 0x20 Battery level lower than power on reset threshold
1084e5c238c3SMattias Wallin  * 0x40 Power on key 1 pressed longer than 10 seconds
1085e5c238c3SMattias Wallin  * 0x80 DB8500 thermal shutdown
1086e5c238c3SMattias Wallin  */
1087e5c238c3SMattias Wallin static ssize_t show_switch_off_status(struct device *dev,
1088e5c238c3SMattias Wallin 				struct device_attribute *attr, char *buf)
1089e5c238c3SMattias Wallin {
1090e5c238c3SMattias Wallin 	int ret;
1091e5c238c3SMattias Wallin 	u8 value;
1092e5c238c3SMattias Wallin 	struct ab8500 *ab8500;
1093e5c238c3SMattias Wallin 
1094e5c238c3SMattias Wallin 	ab8500 = dev_get_drvdata(dev);
1095e5c238c3SMattias Wallin 	ret = get_register_interruptible(ab8500, AB8500_RTC,
1096e5c238c3SMattias Wallin 		AB8500_SWITCH_OFF_STATUS, &value);
1097e5c238c3SMattias Wallin 	if (ret < 0)
1098e5c238c3SMattias Wallin 		return ret;
1099e5c238c3SMattias Wallin 	return sprintf(buf, "%#x\n", value);
1100e5c238c3SMattias Wallin }
1101e5c238c3SMattias Wallin 
1102b4a31037SAndrew Lynn /*
1103b4a31037SAndrew Lynn  * ab8500 has turned on due to (TURN_ON_STATUS):
1104b4a31037SAndrew Lynn  * 0x01 PORnVbat
1105b4a31037SAndrew Lynn  * 0x02 PonKey1dbF
1106b4a31037SAndrew Lynn  * 0x04 PonKey2dbF
1107b4a31037SAndrew Lynn  * 0x08 RTCAlarm
1108b4a31037SAndrew Lynn  * 0x10 MainChDet
1109b4a31037SAndrew Lynn  * 0x20 VbusDet
1110b4a31037SAndrew Lynn  * 0x40 UsbIDDetect
1111b4a31037SAndrew Lynn  * 0x80 Reserved
1112b4a31037SAndrew Lynn  */
1113b4a31037SAndrew Lynn static ssize_t show_turn_on_status(struct device *dev,
1114b4a31037SAndrew Lynn 				struct device_attribute *attr, char *buf)
1115b4a31037SAndrew Lynn {
1116b4a31037SAndrew Lynn 	int ret;
1117b4a31037SAndrew Lynn 	u8 value;
1118b4a31037SAndrew Lynn 	struct ab8500 *ab8500;
1119b4a31037SAndrew Lynn 
1120b4a31037SAndrew Lynn 	ab8500 = dev_get_drvdata(dev);
1121b4a31037SAndrew Lynn 	ret = get_register_interruptible(ab8500, AB8500_SYS_CTRL1_BLOCK,
1122b4a31037SAndrew Lynn 		AB8500_TURN_ON_STATUS, &value);
1123b4a31037SAndrew Lynn 	if (ret < 0)
1124b4a31037SAndrew Lynn 		return ret;
1125b4a31037SAndrew Lynn 	return sprintf(buf, "%#x\n", value);
1126b4a31037SAndrew Lynn }
1127b4a31037SAndrew Lynn 
1128d6255529SLinus Walleij static ssize_t show_ab9540_dbbrstn(struct device *dev,
1129d6255529SLinus Walleij 				struct device_attribute *attr, char *buf)
1130d6255529SLinus Walleij {
1131d6255529SLinus Walleij 	struct ab8500 *ab8500;
1132d6255529SLinus Walleij 	int ret;
1133d6255529SLinus Walleij 	u8 value;
1134d6255529SLinus Walleij 
1135d6255529SLinus Walleij 	ab8500 = dev_get_drvdata(dev);
1136d6255529SLinus Walleij 
1137d6255529SLinus Walleij 	ret = get_register_interruptible(ab8500, AB8500_REGU_CTRL2,
1138d6255529SLinus Walleij 		AB9540_MODEM_CTRL2_REG, &value);
1139d6255529SLinus Walleij 	if (ret < 0)
1140d6255529SLinus Walleij 		return ret;
1141d6255529SLinus Walleij 
1142d6255529SLinus Walleij 	return sprintf(buf, "%d\n",
1143d6255529SLinus Walleij 			(value & AB9540_MODEM_CTRL2_SWDBBRSTN_BIT) ? 1 : 0);
1144d6255529SLinus Walleij }
1145d6255529SLinus Walleij 
1146d6255529SLinus Walleij static ssize_t store_ab9540_dbbrstn(struct device *dev,
1147d6255529SLinus Walleij 	struct device_attribute *attr, const char *buf, size_t count)
1148d6255529SLinus Walleij {
1149d6255529SLinus Walleij 	struct ab8500 *ab8500;
1150d6255529SLinus Walleij 	int ret = count;
1151d6255529SLinus Walleij 	int err;
1152d6255529SLinus Walleij 	u8 bitvalues;
1153d6255529SLinus Walleij 
1154d6255529SLinus Walleij 	ab8500 = dev_get_drvdata(dev);
1155d6255529SLinus Walleij 
1156d6255529SLinus Walleij 	if (count > 0) {
1157d6255529SLinus Walleij 		switch (buf[0]) {
1158d6255529SLinus Walleij 		case '0':
1159d6255529SLinus Walleij 			bitvalues = 0;
1160d6255529SLinus Walleij 			break;
1161d6255529SLinus Walleij 		case '1':
1162d6255529SLinus Walleij 			bitvalues = AB9540_MODEM_CTRL2_SWDBBRSTN_BIT;
1163d6255529SLinus Walleij 			break;
1164d6255529SLinus Walleij 		default:
1165d6255529SLinus Walleij 			goto exit;
1166d6255529SLinus Walleij 		}
1167d6255529SLinus Walleij 
1168d6255529SLinus Walleij 		err = mask_and_set_register_interruptible(ab8500,
1169d6255529SLinus Walleij 			AB8500_REGU_CTRL2, AB9540_MODEM_CTRL2_REG,
1170d6255529SLinus Walleij 			AB9540_MODEM_CTRL2_SWDBBRSTN_BIT, bitvalues);
1171d6255529SLinus Walleij 		if (err)
1172d6255529SLinus Walleij 			dev_info(ab8500->dev,
1173d6255529SLinus Walleij 				"Failed to set DBBRSTN %c, err %#x\n",
1174d6255529SLinus Walleij 				buf[0], err);
1175d6255529SLinus Walleij 	}
1176d6255529SLinus Walleij 
1177d6255529SLinus Walleij exit:
1178d6255529SLinus Walleij 	return ret;
1179d6255529SLinus Walleij }
1180d6255529SLinus Walleij 
1181cca69b67SMattias Wallin static DEVICE_ATTR(chip_id, S_IRUGO, show_chip_id, NULL);
1182e5c238c3SMattias Wallin static DEVICE_ATTR(switch_off_status, S_IRUGO, show_switch_off_status, NULL);
1183b4a31037SAndrew Lynn static DEVICE_ATTR(turn_on_status, S_IRUGO, show_turn_on_status, NULL);
1184d6255529SLinus Walleij static DEVICE_ATTR(dbbrstn, S_IRUGO | S_IWUSR,
1185d6255529SLinus Walleij 			show_ab9540_dbbrstn, store_ab9540_dbbrstn);
1186cca69b67SMattias Wallin 
1187cca69b67SMattias Wallin static struct attribute *ab8500_sysfs_entries[] = {
1188cca69b67SMattias Wallin 	&dev_attr_chip_id.attr,
1189e5c238c3SMattias Wallin 	&dev_attr_switch_off_status.attr,
1190b4a31037SAndrew Lynn 	&dev_attr_turn_on_status.attr,
1191cca69b67SMattias Wallin 	NULL,
1192cca69b67SMattias Wallin };
1193cca69b67SMattias Wallin 
1194d6255529SLinus Walleij static struct attribute *ab9540_sysfs_entries[] = {
1195d6255529SLinus Walleij 	&dev_attr_chip_id.attr,
1196d6255529SLinus Walleij 	&dev_attr_switch_off_status.attr,
1197d6255529SLinus Walleij 	&dev_attr_turn_on_status.attr,
1198d6255529SLinus Walleij 	&dev_attr_dbbrstn.attr,
1199d6255529SLinus Walleij 	NULL,
1200d6255529SLinus Walleij };
1201d6255529SLinus Walleij 
1202cca69b67SMattias Wallin static struct attribute_group ab8500_attr_group = {
1203cca69b67SMattias Wallin 	.attrs	= ab8500_sysfs_entries,
1204cca69b67SMattias Wallin };
1205cca69b67SMattias Wallin 
1206d6255529SLinus Walleij static struct attribute_group ab9540_attr_group = {
1207d6255529SLinus Walleij 	.attrs	= ab9540_sysfs_entries,
1208d6255529SLinus Walleij };
1209d6255529SLinus Walleij 
1210*6bc4a568SLee Jones static const struct of_device_id ab8500_match[] = {
1211*6bc4a568SLee Jones 	{
1212*6bc4a568SLee Jones 		.compatible = "stericsson,ab8500",
1213*6bc4a568SLee Jones 		.data = (void *)AB8500_VERSION_AB8500,
1214*6bc4a568SLee Jones 	},
1215*6bc4a568SLee Jones 	{},
1216*6bc4a568SLee Jones };
1217*6bc4a568SLee Jones 
1218d28f1db8SLee Jones static int __devinit ab8500_probe(struct platform_device *pdev)
121962579266SRabin Vincent {
1220d28f1db8SLee Jones 	struct ab8500_platform_data *plat = dev_get_platdata(&pdev->dev);
1221d28f1db8SLee Jones 	const struct platform_device_id *platid = platform_get_device_id(pdev);
1222*6bc4a568SLee Jones 	enum ab8500_version version = AB8500_VERSION_UNDEFINED;
1223*6bc4a568SLee Jones 	struct device_node *np = pdev->dev.of_node;
1224d28f1db8SLee Jones 	struct ab8500 *ab8500;
1225d28f1db8SLee Jones 	struct resource *resource;
122662579266SRabin Vincent 	int ret;
122762579266SRabin Vincent 	int i;
122847c16975SMattias Wallin 	u8 value;
122962579266SRabin Vincent 
1230d28f1db8SLee Jones 	ab8500 = kzalloc(sizeof *ab8500, GFP_KERNEL);
1231d28f1db8SLee Jones 	if (!ab8500)
1232d28f1db8SLee Jones 		return -ENOMEM;
1233d28f1db8SLee Jones 
123462579266SRabin Vincent 	if (plat)
123562579266SRabin Vincent 		ab8500->irq_base = plat->irq_base;
1236*6bc4a568SLee Jones 	else if (np)
1237*6bc4a568SLee Jones 		ret = of_property_read_u32(np, "stericsson,irq-base", &ab8500->irq_base);
1238*6bc4a568SLee Jones 
1239*6bc4a568SLee Jones 	if (!ab8500->irq_base) {
1240*6bc4a568SLee Jones 		dev_info(&pdev->dev, "couldn't find irq-base\n");
1241*6bc4a568SLee Jones 		ret = -EINVAL;
1242*6bc4a568SLee Jones 		goto out_free_ab8500;
1243*6bc4a568SLee Jones 	}
124462579266SRabin Vincent 
1245d28f1db8SLee Jones 	ab8500->dev = &pdev->dev;
1246d28f1db8SLee Jones 
1247d28f1db8SLee Jones 	resource = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
1248d28f1db8SLee Jones 	if (!resource) {
1249d28f1db8SLee Jones 		ret = -ENODEV;
1250d28f1db8SLee Jones 		goto out_free_ab8500;
1251d28f1db8SLee Jones 	}
1252d28f1db8SLee Jones 
1253d28f1db8SLee Jones 	ab8500->irq = resource->start;
1254d28f1db8SLee Jones 
1255d28f1db8SLee Jones 	ab8500->read = ab8500_i2c_read;
1256d28f1db8SLee Jones 	ab8500->write = ab8500_i2c_write;
1257d28f1db8SLee Jones 	ab8500->write_masked = ab8500_i2c_write_masked;
1258d28f1db8SLee Jones 
125962579266SRabin Vincent 	mutex_init(&ab8500->lock);
126062579266SRabin Vincent 	mutex_init(&ab8500->irq_lock);
1261112a80d2SJonas Aaberg 	atomic_set(&ab8500->transfer_ongoing, 0);
126262579266SRabin Vincent 
1263d28f1db8SLee Jones 	platform_set_drvdata(pdev, ab8500);
1264d28f1db8SLee Jones 
1265*6bc4a568SLee Jones 	if (platid)
1266*6bc4a568SLee Jones 		version = platid->driver_data;
1267*6bc4a568SLee Jones 	else if (np)
1268*6bc4a568SLee Jones 		version = (unsigned int)
1269*6bc4a568SLee Jones 			of_match_device(ab8500_match, &pdev->dev)->data;
1270*6bc4a568SLee Jones 
12710f620837SLinus Walleij 	if (version != AB8500_VERSION_UNDEFINED)
12720f620837SLinus Walleij 		ab8500->version = version;
12730f620837SLinus Walleij 	else {
12740f620837SLinus Walleij 		ret = get_register_interruptible(ab8500, AB8500_MISC,
12750f620837SLinus Walleij 			AB8500_IC_NAME_REG, &value);
12760f620837SLinus Walleij 		if (ret < 0)
1277d28f1db8SLee Jones 			goto out_free_ab8500;
12780f620837SLinus Walleij 
12790f620837SLinus Walleij 		ab8500->version = value;
12800f620837SLinus Walleij 	}
12810f620837SLinus Walleij 
128247c16975SMattias Wallin 	ret = get_register_interruptible(ab8500, AB8500_MISC,
128347c16975SMattias Wallin 		AB8500_REV_REG, &value);
128462579266SRabin Vincent 	if (ret < 0)
1285d28f1db8SLee Jones 		goto out_free_ab8500;
128662579266SRabin Vincent 
128747c16975SMattias Wallin 	ab8500->chip_id = value;
128862579266SRabin Vincent 
12890f620837SLinus Walleij 	dev_info(ab8500->dev, "detected chip, %s rev. %1x.%1x\n",
12900f620837SLinus Walleij 			ab8500_version_str[ab8500->version],
12910f620837SLinus Walleij 			ab8500->chip_id >> 4,
12920f620837SLinus Walleij 			ab8500->chip_id & 0x0F);
12930f620837SLinus Walleij 
1294d6255529SLinus Walleij 	/* Configure AB8500 or AB9540 IRQ */
1295a982362cSBengt Jonsson 	if (is_ab9540(ab8500) || is_ab8505(ab8500)) {
1296d6255529SLinus Walleij 		ab8500->mask_size = AB9540_NUM_IRQ_REGS;
1297d6255529SLinus Walleij 		ab8500->irq_reg_offset = ab9540_irq_regoffset;
1298d6255529SLinus Walleij 	} else {
12992ced445eSLinus Walleij 		ab8500->mask_size = AB8500_NUM_IRQ_REGS;
13002ced445eSLinus Walleij 		ab8500->irq_reg_offset = ab8500_irq_regoffset;
1301d6255529SLinus Walleij 	}
13022ced445eSLinus Walleij 	ab8500->mask = kzalloc(ab8500->mask_size, GFP_KERNEL);
13032ced445eSLinus Walleij 	if (!ab8500->mask)
13042ced445eSLinus Walleij 		return -ENOMEM;
13052ced445eSLinus Walleij 	ab8500->oldmask = kzalloc(ab8500->mask_size, GFP_KERNEL);
13062ced445eSLinus Walleij 	if (!ab8500->oldmask) {
13072ced445eSLinus Walleij 		ret = -ENOMEM;
13082ced445eSLinus Walleij 		goto out_freemask;
13092ced445eSLinus Walleij 	}
1310e5c238c3SMattias Wallin 	/*
1311e5c238c3SMattias Wallin 	 * ab8500 has switched off due to (SWITCH_OFF_STATUS):
1312e5c238c3SMattias Wallin 	 * 0x01 Swoff bit programming
1313e5c238c3SMattias Wallin 	 * 0x02 Thermal protection activation
1314e5c238c3SMattias Wallin 	 * 0x04 Vbat lower then BattOk falling threshold
1315e5c238c3SMattias Wallin 	 * 0x08 Watchdog expired
1316e5c238c3SMattias Wallin 	 * 0x10 Non presence of 32kHz clock
1317e5c238c3SMattias Wallin 	 * 0x20 Battery level lower than power on reset threshold
1318e5c238c3SMattias Wallin 	 * 0x40 Power on key 1 pressed longer than 10 seconds
1319e5c238c3SMattias Wallin 	 * 0x80 DB8500 thermal shutdown
1320e5c238c3SMattias Wallin 	 */
1321e5c238c3SMattias Wallin 
1322e5c238c3SMattias Wallin 	ret = get_register_interruptible(ab8500, AB8500_RTC,
1323e5c238c3SMattias Wallin 		AB8500_SWITCH_OFF_STATUS, &value);
1324e5c238c3SMattias Wallin 	if (ret < 0)
1325e5c238c3SMattias Wallin 		return ret;
1326e5c238c3SMattias Wallin 	dev_info(ab8500->dev, "switch off status: %#x", value);
1327e5c238c3SMattias Wallin 
132862579266SRabin Vincent 	if (plat && plat->init)
132962579266SRabin Vincent 		plat->init(ab8500);
133062579266SRabin Vincent 
133162579266SRabin Vincent 	/* Clear and mask all interrupts */
13322ced445eSLinus Walleij 	for (i = 0; i < ab8500->mask_size; i++) {
13330f620837SLinus Walleij 		/*
13340f620837SLinus Walleij 		 * Interrupt register 12 doesn't exist prior to AB8500 version
13350f620837SLinus Walleij 		 * 2.0
13360f620837SLinus Walleij 		 */
13370f620837SLinus Walleij 		if (ab8500->irq_reg_offset[i] == 11 &&
13380f620837SLinus Walleij 				is_ab8500_1p1_or_earlier(ab8500))
133992d50a41SMattias Wallin 			continue;
134062579266SRabin Vincent 
134147c16975SMattias Wallin 		get_register_interruptible(ab8500, AB8500_INTERRUPT,
13422ced445eSLinus Walleij 			AB8500_IT_LATCH1_REG + ab8500->irq_reg_offset[i],
134392d50a41SMattias Wallin 			&value);
134447c16975SMattias Wallin 		set_register_interruptible(ab8500, AB8500_INTERRUPT,
13452ced445eSLinus Walleij 			AB8500_IT_MASK1_REG + ab8500->irq_reg_offset[i], 0xff);
134662579266SRabin Vincent 	}
134762579266SRabin Vincent 
134847c16975SMattias Wallin 	ret = abx500_register_ops(ab8500->dev, &ab8500_ops);
134947c16975SMattias Wallin 	if (ret)
13502ced445eSLinus Walleij 		goto out_freeoldmask;
135147c16975SMattias Wallin 
13522ced445eSLinus Walleij 	for (i = 0; i < ab8500->mask_size; i++)
135362579266SRabin Vincent 		ab8500->mask[i] = ab8500->oldmask[i] = 0xff;
135462579266SRabin Vincent 
135562579266SRabin Vincent 	if (ab8500->irq_base) {
135662579266SRabin Vincent 		ret = ab8500_irq_init(ab8500);
135762579266SRabin Vincent 		if (ret)
13582ced445eSLinus Walleij 			goto out_freeoldmask;
135962579266SRabin Vincent 
13607ccfe9b1SMichel JAOUEN 		/*  Activate this feature only in ab9540 */
13617ccfe9b1SMichel JAOUEN 		/*  till tests are done on ab8500 1p2 or later*/
13627ccfe9b1SMichel JAOUEN 		if (is_ab9540(ab8500))
13637ccfe9b1SMichel JAOUEN 			ret = request_threaded_irq(ab8500->irq, NULL,
13647ccfe9b1SMichel JAOUEN 					ab8500_hierarchical_irq,
13657ccfe9b1SMichel JAOUEN 					IRQF_ONESHOT | IRQF_NO_SUSPEND,
13667ccfe9b1SMichel JAOUEN 					"ab8500", ab8500);
13677ccfe9b1SMichel JAOUEN 		else
13687ccfe9b1SMichel JAOUEN 			ret = request_threaded_irq(ab8500->irq, NULL,
13697ccfe9b1SMichel JAOUEN 					ab8500_irq,
13704f079985SMattias Wallin 					IRQF_ONESHOT | IRQF_NO_SUSPEND,
13714f079985SMattias Wallin 					"ab8500", ab8500);
137262579266SRabin Vincent 		if (ret)
137362579266SRabin Vincent 			goto out_removeirq;
137462579266SRabin Vincent 	}
137562579266SRabin Vincent 
1376*6bc4a568SLee Jones 	if (!np) {
1377d6255529SLinus Walleij 		ret = mfd_add_devices(ab8500->dev, 0, abx500_common_devs,
1378d6255529SLinus Walleij 				ARRAY_SIZE(abx500_common_devs), NULL,
1379d6255529SLinus Walleij 				ab8500->irq_base);
1380d6255529SLinus Walleij 
1381d6255529SLinus Walleij 		if (ret)
1382d6255529SLinus Walleij 			goto out_freeirq;
1383d6255529SLinus Walleij 
1384d6255529SLinus Walleij 		if (is_ab9540(ab8500))
1385d6255529SLinus Walleij 			ret = mfd_add_devices(ab8500->dev, 0, ab9540_devs,
1386d6255529SLinus Walleij 					ARRAY_SIZE(ab9540_devs), NULL,
1387d6255529SLinus Walleij 					ab8500->irq_base);
1388d6255529SLinus Walleij 		else
1389549931f9SSundar R Iyer 			ret = mfd_add_devices(ab8500->dev, 0, ab8500_devs,
139044f72e53SVirupax Sadashivpetimath 					ARRAY_SIZE(ab8500_devs), NULL,
139162579266SRabin Vincent 					ab8500->irq_base);
1392*6bc4a568SLee Jones 		if (ret)
1393*6bc4a568SLee Jones 			goto out_freeirq;
139444f72e53SVirupax Sadashivpetimath 
139544f72e53SVirupax Sadashivpetimath 		if (is_ab9540(ab8500) || is_ab8505(ab8500))
139644f72e53SVirupax Sadashivpetimath 			ret = mfd_add_devices(ab8500->dev, 0, ab9540_ab8505_devs,
139744f72e53SVirupax Sadashivpetimath 					ARRAY_SIZE(ab9540_ab8505_devs), NULL,
139844f72e53SVirupax Sadashivpetimath 					ab8500->irq_base);
139962579266SRabin Vincent 		if (ret)
140062579266SRabin Vincent 			goto out_freeirq;
1401*6bc4a568SLee Jones 	}
140262579266SRabin Vincent 
14036ef9418cSRickard Andersson 	if (!no_bm) {
14046ef9418cSRickard Andersson 		/* Add battery management devices */
14056ef9418cSRickard Andersson 		ret = mfd_add_devices(ab8500->dev, 0, ab8500_bm_devs,
14066ef9418cSRickard Andersson 				      ARRAY_SIZE(ab8500_bm_devs), NULL,
14076ef9418cSRickard Andersson 				      ab8500->irq_base);
14086ef9418cSRickard Andersson 		if (ret)
14096ef9418cSRickard Andersson 			dev_err(ab8500->dev, "error adding bm devices\n");
14106ef9418cSRickard Andersson 	}
14116ef9418cSRickard Andersson 
1412d6255529SLinus Walleij 	if (is_ab9540(ab8500))
1413d6255529SLinus Walleij 		ret = sysfs_create_group(&ab8500->dev->kobj,
1414d6255529SLinus Walleij 					&ab9540_attr_group);
1415d6255529SLinus Walleij 	else
1416d6255529SLinus Walleij 		ret = sysfs_create_group(&ab8500->dev->kobj,
1417d6255529SLinus Walleij 					&ab8500_attr_group);
1418cca69b67SMattias Wallin 	if (ret)
1419cca69b67SMattias Wallin 		dev_err(ab8500->dev, "error creating sysfs entries\n");
1420d6255529SLinus Walleij 	else
142162579266SRabin Vincent 		return ret;
142262579266SRabin Vincent 
142362579266SRabin Vincent out_freeirq:
14246d95b7fdSLinus Walleij 	if (ab8500->irq_base)
142562579266SRabin Vincent 		free_irq(ab8500->irq, ab8500);
142662579266SRabin Vincent out_removeirq:
14276d95b7fdSLinus Walleij 	if (ab8500->irq_base)
142862579266SRabin Vincent 		ab8500_irq_remove(ab8500);
14292ced445eSLinus Walleij out_freeoldmask:
14302ced445eSLinus Walleij 	kfree(ab8500->oldmask);
14312ced445eSLinus Walleij out_freemask:
14322ced445eSLinus Walleij 	kfree(ab8500->mask);
1433d28f1db8SLee Jones out_free_ab8500:
1434d28f1db8SLee Jones 	kfree(ab8500);
14356d95b7fdSLinus Walleij 
143662579266SRabin Vincent 	return ret;
143762579266SRabin Vincent }
143862579266SRabin Vincent 
1439d28f1db8SLee Jones static int __devexit ab8500_remove(struct platform_device *pdev)
144062579266SRabin Vincent {
1441d28f1db8SLee Jones 	struct ab8500 *ab8500 = platform_get_drvdata(pdev);
1442d28f1db8SLee Jones 
1443d6255529SLinus Walleij 	if (is_ab9540(ab8500))
1444d6255529SLinus Walleij 		sysfs_remove_group(&ab8500->dev->kobj, &ab9540_attr_group);
1445d6255529SLinus Walleij 	else
1446cca69b67SMattias Wallin 		sysfs_remove_group(&ab8500->dev->kobj, &ab8500_attr_group);
144762579266SRabin Vincent 	mfd_remove_devices(ab8500->dev);
144862579266SRabin Vincent 	if (ab8500->irq_base) {
144962579266SRabin Vincent 		free_irq(ab8500->irq, ab8500);
145062579266SRabin Vincent 		ab8500_irq_remove(ab8500);
145162579266SRabin Vincent 	}
14522ced445eSLinus Walleij 	kfree(ab8500->oldmask);
14532ced445eSLinus Walleij 	kfree(ab8500->mask);
1454d28f1db8SLee Jones 	kfree(ab8500);
145562579266SRabin Vincent 
145662579266SRabin Vincent 	return 0;
145762579266SRabin Vincent }
145862579266SRabin Vincent 
1459d28f1db8SLee Jones static const struct platform_device_id ab8500_id[] = {
1460d28f1db8SLee Jones 	{ "ab8500-core", AB8500_VERSION_AB8500 },
1461d28f1db8SLee Jones 	{ "ab8505-i2c", AB8500_VERSION_AB8505 },
1462d28f1db8SLee Jones 	{ "ab9540-i2c", AB8500_VERSION_AB9540 },
1463d28f1db8SLee Jones 	{ "ab8540-i2c", AB8500_VERSION_AB8540 },
1464d28f1db8SLee Jones 	{ }
1465d28f1db8SLee Jones };
1466d28f1db8SLee Jones 
1467d28f1db8SLee Jones static struct platform_driver ab8500_core_driver = {
1468d28f1db8SLee Jones 	.driver = {
1469d28f1db8SLee Jones 		.name = "ab8500-core",
1470d28f1db8SLee Jones 		.owner = THIS_MODULE,
1471*6bc4a568SLee Jones 		.of_match_table = ab8500_match,
1472d28f1db8SLee Jones 	},
1473d28f1db8SLee Jones 	.probe	= ab8500_probe,
1474d28f1db8SLee Jones 	.remove	= __devexit_p(ab8500_remove),
1475d28f1db8SLee Jones 	.id_table = ab8500_id,
1476d28f1db8SLee Jones };
1477d28f1db8SLee Jones 
1478d28f1db8SLee Jones static int __init ab8500_core_init(void)
1479d28f1db8SLee Jones {
1480d28f1db8SLee Jones 	return platform_driver_register(&ab8500_core_driver);
1481d28f1db8SLee Jones }
1482d28f1db8SLee Jones 
1483d28f1db8SLee Jones static void __exit ab8500_core_exit(void)
1484d28f1db8SLee Jones {
1485d28f1db8SLee Jones 	platform_driver_unregister(&ab8500_core_driver);
1486d28f1db8SLee Jones }
1487d28f1db8SLee Jones arch_initcall(ab8500_core_init);
1488d28f1db8SLee Jones module_exit(ab8500_core_exit);
1489d28f1db8SLee Jones 
1490adceed62SMattias Wallin MODULE_AUTHOR("Mattias Wallin, Srinidhi Kasagar, Rabin Vincent");
149162579266SRabin Vincent MODULE_DESCRIPTION("AB8500 MFD core");
149262579266SRabin Vincent MODULE_LICENSE("GPL v2");
1493