xref: /openbmc/linux/drivers/mfd/ab8500-core.c (revision a982362c1723464fec0414f6460684844f2638f3)
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>
21549931f9SSundar R Iyer #include <linux/regulator/ab8500.h>
2262579266SRabin Vincent 
2362579266SRabin Vincent /*
2462579266SRabin Vincent  * Interrupt register offsets
2562579266SRabin Vincent  * Bank : 0x0E
2662579266SRabin Vincent  */
2747c16975SMattias Wallin #define AB8500_IT_SOURCE1_REG		0x00
2847c16975SMattias Wallin #define AB8500_IT_SOURCE2_REG		0x01
2947c16975SMattias Wallin #define AB8500_IT_SOURCE3_REG		0x02
3047c16975SMattias Wallin #define AB8500_IT_SOURCE4_REG		0x03
3147c16975SMattias Wallin #define AB8500_IT_SOURCE5_REG		0x04
3247c16975SMattias Wallin #define AB8500_IT_SOURCE6_REG		0x05
3347c16975SMattias Wallin #define AB8500_IT_SOURCE7_REG		0x06
3447c16975SMattias Wallin #define AB8500_IT_SOURCE8_REG		0x07
35d6255529SLinus Walleij #define AB9540_IT_SOURCE13_REG		0x0C
3647c16975SMattias Wallin #define AB8500_IT_SOURCE19_REG		0x12
3747c16975SMattias Wallin #define AB8500_IT_SOURCE20_REG		0x13
3847c16975SMattias Wallin #define AB8500_IT_SOURCE21_REG		0x14
3947c16975SMattias Wallin #define AB8500_IT_SOURCE22_REG		0x15
4047c16975SMattias Wallin #define AB8500_IT_SOURCE23_REG		0x16
4147c16975SMattias Wallin #define AB8500_IT_SOURCE24_REG		0x17
4262579266SRabin Vincent 
4362579266SRabin Vincent /*
4462579266SRabin Vincent  * latch registers
4562579266SRabin Vincent  */
4647c16975SMattias Wallin #define AB8500_IT_LATCH1_REG		0x20
4747c16975SMattias Wallin #define AB8500_IT_LATCH2_REG		0x21
4847c16975SMattias Wallin #define AB8500_IT_LATCH3_REG		0x22
4947c16975SMattias Wallin #define AB8500_IT_LATCH4_REG		0x23
5047c16975SMattias Wallin #define AB8500_IT_LATCH5_REG		0x24
5147c16975SMattias Wallin #define AB8500_IT_LATCH6_REG		0x25
5247c16975SMattias Wallin #define AB8500_IT_LATCH7_REG		0x26
5347c16975SMattias Wallin #define AB8500_IT_LATCH8_REG		0x27
5447c16975SMattias Wallin #define AB8500_IT_LATCH9_REG		0x28
5547c16975SMattias Wallin #define AB8500_IT_LATCH10_REG		0x29
5692d50a41SMattias Wallin #define AB8500_IT_LATCH12_REG		0x2B
57d6255529SLinus Walleij #define AB9540_IT_LATCH13_REG		0x2C
5847c16975SMattias Wallin #define AB8500_IT_LATCH19_REG		0x32
5947c16975SMattias Wallin #define AB8500_IT_LATCH20_REG		0x33
6047c16975SMattias Wallin #define AB8500_IT_LATCH21_REG		0x34
6147c16975SMattias Wallin #define AB8500_IT_LATCH22_REG		0x35
6247c16975SMattias Wallin #define AB8500_IT_LATCH23_REG		0x36
6347c16975SMattias Wallin #define AB8500_IT_LATCH24_REG		0x37
6462579266SRabin Vincent 
6562579266SRabin Vincent /*
6662579266SRabin Vincent  * mask registers
6762579266SRabin Vincent  */
6862579266SRabin Vincent 
6947c16975SMattias Wallin #define AB8500_IT_MASK1_REG		0x40
7047c16975SMattias Wallin #define AB8500_IT_MASK2_REG		0x41
7147c16975SMattias Wallin #define AB8500_IT_MASK3_REG		0x42
7247c16975SMattias Wallin #define AB8500_IT_MASK4_REG		0x43
7347c16975SMattias Wallin #define AB8500_IT_MASK5_REG		0x44
7447c16975SMattias Wallin #define AB8500_IT_MASK6_REG		0x45
7547c16975SMattias Wallin #define AB8500_IT_MASK7_REG		0x46
7647c16975SMattias Wallin #define AB8500_IT_MASK8_REG		0x47
7747c16975SMattias Wallin #define AB8500_IT_MASK9_REG		0x48
7847c16975SMattias Wallin #define AB8500_IT_MASK10_REG		0x49
7947c16975SMattias Wallin #define AB8500_IT_MASK11_REG		0x4A
8047c16975SMattias Wallin #define AB8500_IT_MASK12_REG		0x4B
8147c16975SMattias Wallin #define AB8500_IT_MASK13_REG		0x4C
8247c16975SMattias Wallin #define AB8500_IT_MASK14_REG		0x4D
8347c16975SMattias Wallin #define AB8500_IT_MASK15_REG		0x4E
8447c16975SMattias Wallin #define AB8500_IT_MASK16_REG		0x4F
8547c16975SMattias Wallin #define AB8500_IT_MASK17_REG		0x50
8647c16975SMattias Wallin #define AB8500_IT_MASK18_REG		0x51
8747c16975SMattias Wallin #define AB8500_IT_MASK19_REG		0x52
8847c16975SMattias Wallin #define AB8500_IT_MASK20_REG		0x53
8947c16975SMattias Wallin #define AB8500_IT_MASK21_REG		0x54
9047c16975SMattias Wallin #define AB8500_IT_MASK22_REG		0x55
9147c16975SMattias Wallin #define AB8500_IT_MASK23_REG		0x56
9247c16975SMattias Wallin #define AB8500_IT_MASK24_REG		0x57
9362579266SRabin Vincent 
9447c16975SMattias Wallin #define AB8500_REV_REG			0x80
950f620837SLinus Walleij #define AB8500_IC_NAME_REG		0x82
96e5c238c3SMattias Wallin #define AB8500_SWITCH_OFF_STATUS	0x00
9762579266SRabin Vincent 
98b4a31037SAndrew Lynn #define AB8500_TURN_ON_STATUS		0x00
99b4a31037SAndrew Lynn 
100d6255529SLinus Walleij #define AB9540_MODEM_CTRL2_REG			0x23
101d6255529SLinus Walleij #define AB9540_MODEM_CTRL2_SWDBBRSTN_BIT	BIT(2)
102d6255529SLinus Walleij 
10362579266SRabin Vincent /*
10462579266SRabin Vincent  * Map interrupt numbers to the LATCH and MASK register offsets, Interrupt
1052ced445eSLinus Walleij  * numbers are indexed into this array with (num / 8). The interupts are
1062ced445eSLinus Walleij  * defined in linux/mfd/ab8500.h
10762579266SRabin Vincent  *
10862579266SRabin Vincent  * This is one off from the register names, i.e. AB8500_IT_MASK1_REG is at
10962579266SRabin Vincent  * offset 0.
11062579266SRabin Vincent  */
1112ced445eSLinus Walleij /* AB8500 support */
11262579266SRabin Vincent static const int ab8500_irq_regoffset[AB8500_NUM_IRQ_REGS] = {
11392d50a41SMattias Wallin 	0, 1, 2, 3, 4, 6, 7, 8, 9, 11, 18, 19, 20, 21,
11462579266SRabin Vincent };
11562579266SRabin Vincent 
116d6255529SLinus Walleij /* AB9540 support */
117d6255529SLinus Walleij static const int ab9540_irq_regoffset[AB9540_NUM_IRQ_REGS] = {
118d6255529SLinus Walleij 	0, 1, 2, 3, 4, 6, 7, 8, 9, 11, 18, 19, 20, 21, 12, 13, 24,
119d6255529SLinus Walleij };
120d6255529SLinus Walleij 
1210f620837SLinus Walleij static const char ab8500_version_str[][7] = {
1220f620837SLinus Walleij 	[AB8500_VERSION_AB8500] = "AB8500",
1230f620837SLinus Walleij 	[AB8500_VERSION_AB8505] = "AB8505",
1240f620837SLinus Walleij 	[AB8500_VERSION_AB9540] = "AB9540",
1250f620837SLinus Walleij 	[AB8500_VERSION_AB8540] = "AB8540",
1260f620837SLinus Walleij };
1270f620837SLinus Walleij 
12847c16975SMattias Wallin static int ab8500_get_chip_id(struct device *dev)
12947c16975SMattias Wallin {
1306bce7bf1SMattias Wallin 	struct ab8500 *ab8500;
1316bce7bf1SMattias Wallin 
1326bce7bf1SMattias Wallin 	if (!dev)
1336bce7bf1SMattias Wallin 		return -EINVAL;
1346bce7bf1SMattias Wallin 	ab8500 = dev_get_drvdata(dev->parent);
1356bce7bf1SMattias Wallin 	return ab8500 ? (int)ab8500->chip_id : -EINVAL;
13647c16975SMattias Wallin }
13747c16975SMattias Wallin 
13847c16975SMattias Wallin static int set_register_interruptible(struct ab8500 *ab8500, u8 bank,
13947c16975SMattias Wallin 	u8 reg, u8 data)
14062579266SRabin Vincent {
14162579266SRabin Vincent 	int ret;
14247c16975SMattias Wallin 	/*
14347c16975SMattias Wallin 	 * Put the u8 bank and u8 register together into a an u16.
14447c16975SMattias Wallin 	 * The bank on higher 8 bits and register in lower 8 bits.
14547c16975SMattias Wallin 	 * */
14647c16975SMattias Wallin 	u16 addr = ((u16)bank) << 8 | reg;
14762579266SRabin Vincent 
14862579266SRabin Vincent 	dev_vdbg(ab8500->dev, "wr: addr %#x <= %#x\n", addr, data);
14962579266SRabin Vincent 
150392cbd1eSRabin Vincent 	mutex_lock(&ab8500->lock);
15147c16975SMattias Wallin 
15247c16975SMattias Wallin 	ret = ab8500->write(ab8500, addr, data);
15347c16975SMattias Wallin 	if (ret < 0)
15447c16975SMattias Wallin 		dev_err(ab8500->dev, "failed to write reg %#x: %d\n",
15547c16975SMattias Wallin 			addr, ret);
15647c16975SMattias Wallin 	mutex_unlock(&ab8500->lock);
15747c16975SMattias Wallin 
15847c16975SMattias Wallin 	return ret;
15947c16975SMattias Wallin }
16047c16975SMattias Wallin 
16147c16975SMattias Wallin static int ab8500_set_register(struct device *dev, u8 bank,
16247c16975SMattias Wallin 	u8 reg, u8 value)
16347c16975SMattias Wallin {
16447c16975SMattias Wallin 	struct ab8500 *ab8500 = dev_get_drvdata(dev->parent);
16547c16975SMattias Wallin 
16647c16975SMattias Wallin 	return set_register_interruptible(ab8500, bank, reg, value);
16747c16975SMattias Wallin }
16847c16975SMattias Wallin 
16947c16975SMattias Wallin static int get_register_interruptible(struct ab8500 *ab8500, u8 bank,
17047c16975SMattias Wallin 	u8 reg, u8 *value)
17147c16975SMattias Wallin {
17247c16975SMattias Wallin 	int ret;
17347c16975SMattias Wallin 	/* put the u8 bank and u8 reg together into a an u16.
17447c16975SMattias Wallin 	 * bank on higher 8 bits and reg in lower */
17547c16975SMattias Wallin 	u16 addr = ((u16)bank) << 8 | reg;
17647c16975SMattias Wallin 
177392cbd1eSRabin Vincent 	mutex_lock(&ab8500->lock);
17847c16975SMattias Wallin 
17947c16975SMattias Wallin 	ret = ab8500->read(ab8500, addr);
18047c16975SMattias Wallin 	if (ret < 0)
18147c16975SMattias Wallin 		dev_err(ab8500->dev, "failed to read reg %#x: %d\n",
18247c16975SMattias Wallin 			addr, ret);
18347c16975SMattias Wallin 	else
18447c16975SMattias Wallin 		*value = ret;
18547c16975SMattias Wallin 
18647c16975SMattias Wallin 	mutex_unlock(&ab8500->lock);
18747c16975SMattias Wallin 	dev_vdbg(ab8500->dev, "rd: addr %#x => data %#x\n", addr, ret);
18847c16975SMattias Wallin 
18947c16975SMattias Wallin 	return ret;
19047c16975SMattias Wallin }
19147c16975SMattias Wallin 
19247c16975SMattias Wallin static int ab8500_get_register(struct device *dev, u8 bank,
19347c16975SMattias Wallin 	u8 reg, u8 *value)
19447c16975SMattias Wallin {
19547c16975SMattias Wallin 	struct ab8500 *ab8500 = dev_get_drvdata(dev->parent);
19647c16975SMattias Wallin 
19747c16975SMattias Wallin 	return get_register_interruptible(ab8500, bank, reg, value);
19847c16975SMattias Wallin }
19947c16975SMattias Wallin 
20047c16975SMattias Wallin static int mask_and_set_register_interruptible(struct ab8500 *ab8500, u8 bank,
20147c16975SMattias Wallin 	u8 reg, u8 bitmask, u8 bitvalues)
20247c16975SMattias Wallin {
20347c16975SMattias Wallin 	int ret;
20447c16975SMattias Wallin 	u8 data;
20547c16975SMattias Wallin 	/* put the u8 bank and u8 reg together into a an u16.
20647c16975SMattias Wallin 	 * bank on higher 8 bits and reg in lower */
20747c16975SMattias Wallin 	u16 addr = ((u16)bank) << 8 | reg;
20847c16975SMattias Wallin 
209392cbd1eSRabin Vincent 	mutex_lock(&ab8500->lock);
21047c16975SMattias Wallin 
21147c16975SMattias Wallin 	ret = ab8500->read(ab8500, addr);
21247c16975SMattias Wallin 	if (ret < 0) {
21347c16975SMattias Wallin 		dev_err(ab8500->dev, "failed to read reg %#x: %d\n",
21447c16975SMattias Wallin 			addr, ret);
21547c16975SMattias Wallin 		goto out;
21647c16975SMattias Wallin 	}
21747c16975SMattias Wallin 
21847c16975SMattias Wallin 	data = (u8)ret;
21947c16975SMattias Wallin 	data = (~bitmask & data) | (bitmask & bitvalues);
22047c16975SMattias Wallin 
22162579266SRabin Vincent 	ret = ab8500->write(ab8500, addr, data);
22262579266SRabin Vincent 	if (ret < 0)
22362579266SRabin Vincent 		dev_err(ab8500->dev, "failed to write reg %#x: %d\n",
22462579266SRabin Vincent 			addr, ret);
22562579266SRabin Vincent 
22647c16975SMattias Wallin 	dev_vdbg(ab8500->dev, "mask: addr %#x => data %#x\n", addr, data);
22762579266SRabin Vincent out:
22862579266SRabin Vincent 	mutex_unlock(&ab8500->lock);
22962579266SRabin Vincent 	return ret;
23062579266SRabin Vincent }
23147c16975SMattias Wallin 
23247c16975SMattias Wallin static int ab8500_mask_and_set_register(struct device *dev,
23347c16975SMattias Wallin 	u8 bank, u8 reg, u8 bitmask, u8 bitvalues)
23447c16975SMattias Wallin {
23547c16975SMattias Wallin 	struct ab8500 *ab8500 = dev_get_drvdata(dev->parent);
23647c16975SMattias Wallin 
23747c16975SMattias Wallin 	return mask_and_set_register_interruptible(ab8500, bank, reg,
23847c16975SMattias Wallin 		bitmask, bitvalues);
23947c16975SMattias Wallin 
24047c16975SMattias Wallin }
24147c16975SMattias Wallin 
24247c16975SMattias Wallin static struct abx500_ops ab8500_ops = {
24347c16975SMattias Wallin 	.get_chip_id = ab8500_get_chip_id,
24447c16975SMattias Wallin 	.get_register = ab8500_get_register,
24547c16975SMattias Wallin 	.set_register = ab8500_set_register,
24647c16975SMattias Wallin 	.get_register_page = NULL,
24747c16975SMattias Wallin 	.set_register_page = NULL,
24847c16975SMattias Wallin 	.mask_and_set_register = ab8500_mask_and_set_register,
24947c16975SMattias Wallin 	.event_registers_startup_state_get = NULL,
25047c16975SMattias Wallin 	.startup_irq_enabled = NULL,
25147c16975SMattias Wallin };
25262579266SRabin Vincent 
2539505a0a0SMark Brown static void ab8500_irq_lock(struct irq_data *data)
25462579266SRabin Vincent {
2559505a0a0SMark Brown 	struct ab8500 *ab8500 = irq_data_get_irq_chip_data(data);
25662579266SRabin Vincent 
25762579266SRabin Vincent 	mutex_lock(&ab8500->irq_lock);
25862579266SRabin Vincent }
25962579266SRabin Vincent 
2609505a0a0SMark Brown static void ab8500_irq_sync_unlock(struct irq_data *data)
26162579266SRabin Vincent {
2629505a0a0SMark Brown 	struct ab8500 *ab8500 = irq_data_get_irq_chip_data(data);
26362579266SRabin Vincent 	int i;
26462579266SRabin Vincent 
2652ced445eSLinus Walleij 	for (i = 0; i < ab8500->mask_size; i++) {
26662579266SRabin Vincent 		u8 old = ab8500->oldmask[i];
26762579266SRabin Vincent 		u8 new = ab8500->mask[i];
26862579266SRabin Vincent 		int reg;
26962579266SRabin Vincent 
27062579266SRabin Vincent 		if (new == old)
27162579266SRabin Vincent 			continue;
27262579266SRabin Vincent 
2730f620837SLinus Walleij 		/*
2740f620837SLinus Walleij 		 * Interrupt register 12 doesn't exist prior to AB8500 version
2750f620837SLinus Walleij 		 * 2.0
2760f620837SLinus Walleij 		 */
2770f620837SLinus Walleij 		if (ab8500->irq_reg_offset[i] == 11 &&
2780f620837SLinus Walleij 			is_ab8500_1p1_or_earlier(ab8500))
27992d50a41SMattias Wallin 			continue;
28092d50a41SMattias Wallin 
28162579266SRabin Vincent 		ab8500->oldmask[i] = new;
28262579266SRabin Vincent 
2832ced445eSLinus Walleij 		reg = AB8500_IT_MASK1_REG + ab8500->irq_reg_offset[i];
28447c16975SMattias Wallin 		set_register_interruptible(ab8500, AB8500_INTERRUPT, reg, new);
28562579266SRabin Vincent 	}
28662579266SRabin Vincent 
28762579266SRabin Vincent 	mutex_unlock(&ab8500->irq_lock);
28862579266SRabin Vincent }
28962579266SRabin Vincent 
2909505a0a0SMark Brown static void ab8500_irq_mask(struct irq_data *data)
29162579266SRabin Vincent {
2929505a0a0SMark Brown 	struct ab8500 *ab8500 = irq_data_get_irq_chip_data(data);
2939505a0a0SMark Brown 	int offset = data->irq - ab8500->irq_base;
29462579266SRabin Vincent 	int index = offset / 8;
29562579266SRabin Vincent 	int mask = 1 << (offset % 8);
29662579266SRabin Vincent 
29762579266SRabin Vincent 	ab8500->mask[index] |= mask;
29862579266SRabin Vincent }
29962579266SRabin Vincent 
3009505a0a0SMark Brown static void ab8500_irq_unmask(struct irq_data *data)
30162579266SRabin Vincent {
3029505a0a0SMark Brown 	struct ab8500 *ab8500 = irq_data_get_irq_chip_data(data);
3039505a0a0SMark Brown 	int offset = data->irq - ab8500->irq_base;
30462579266SRabin Vincent 	int index = offset / 8;
30562579266SRabin Vincent 	int mask = 1 << (offset % 8);
30662579266SRabin Vincent 
30762579266SRabin Vincent 	ab8500->mask[index] &= ~mask;
30862579266SRabin Vincent }
30962579266SRabin Vincent 
31062579266SRabin Vincent static struct irq_chip ab8500_irq_chip = {
31162579266SRabin Vincent 	.name			= "ab8500",
3129505a0a0SMark Brown 	.irq_bus_lock		= ab8500_irq_lock,
3139505a0a0SMark Brown 	.irq_bus_sync_unlock	= ab8500_irq_sync_unlock,
3149505a0a0SMark Brown 	.irq_mask		= ab8500_irq_mask,
315e6f9306eSVirupax Sadashivpetimath 	.irq_disable		= ab8500_irq_mask,
3169505a0a0SMark Brown 	.irq_unmask		= ab8500_irq_unmask,
31762579266SRabin Vincent };
31862579266SRabin Vincent 
31962579266SRabin Vincent static irqreturn_t ab8500_irq(int irq, void *dev)
32062579266SRabin Vincent {
32162579266SRabin Vincent 	struct ab8500 *ab8500 = dev;
32262579266SRabin Vincent 	int i;
32362579266SRabin Vincent 
32462579266SRabin Vincent 	dev_vdbg(ab8500->dev, "interrupt\n");
32562579266SRabin Vincent 
3262ced445eSLinus Walleij 	for (i = 0; i < ab8500->mask_size; i++) {
3272ced445eSLinus Walleij 		int regoffset = ab8500->irq_reg_offset[i];
32862579266SRabin Vincent 		int status;
32947c16975SMattias Wallin 		u8 value;
33062579266SRabin Vincent 
3310f620837SLinus Walleij 		/*
3320f620837SLinus Walleij 		 * Interrupt register 12 doesn't exist prior to AB8500 version
3330f620837SLinus Walleij 		 * 2.0
3340f620837SLinus Walleij 		 */
3350f620837SLinus Walleij 		if (regoffset == 11 && is_ab8500_1p1_or_earlier(ab8500))
33692d50a41SMattias Wallin 			continue;
33792d50a41SMattias Wallin 
33847c16975SMattias Wallin 		status = get_register_interruptible(ab8500, AB8500_INTERRUPT,
33947c16975SMattias Wallin 			AB8500_IT_LATCH1_REG + regoffset, &value);
34047c16975SMattias Wallin 		if (status < 0 || value == 0)
34162579266SRabin Vincent 			continue;
34262579266SRabin Vincent 
34362579266SRabin Vincent 		do {
34488aec4f7SMattias Wallin 			int bit = __ffs(value);
34562579266SRabin Vincent 			int line = i * 8 + bit;
34662579266SRabin Vincent 
34762579266SRabin Vincent 			handle_nested_irq(ab8500->irq_base + line);
34847c16975SMattias Wallin 			value &= ~(1 << bit);
34947c16975SMattias Wallin 		} while (value);
35062579266SRabin Vincent 	}
35162579266SRabin Vincent 
35262579266SRabin Vincent 	return IRQ_HANDLED;
35362579266SRabin Vincent }
35462579266SRabin Vincent 
35562579266SRabin Vincent static int ab8500_irq_init(struct ab8500 *ab8500)
35662579266SRabin Vincent {
35762579266SRabin Vincent 	int base = ab8500->irq_base;
35862579266SRabin Vincent 	int irq;
3592ced445eSLinus Walleij 	int num_irqs;
36062579266SRabin Vincent 
361d6255529SLinus Walleij 	if (is_ab9540(ab8500))
362d6255529SLinus Walleij 		num_irqs = AB9540_NR_IRQS;
363*a982362cSBengt Jonsson 	else if (is_ab8505(ab8500))
364*a982362cSBengt Jonsson 		num_irqs = AB8505_NR_IRQS;
365d6255529SLinus Walleij 	else
3662ced445eSLinus Walleij 		num_irqs = AB8500_NR_IRQS;
3672ced445eSLinus Walleij 
3682ced445eSLinus Walleij 	for (irq = base; irq < base + num_irqs; irq++) {
369d5bb1221SThomas Gleixner 		irq_set_chip_data(irq, ab8500);
370d5bb1221SThomas Gleixner 		irq_set_chip_and_handler(irq, &ab8500_irq_chip,
37162579266SRabin Vincent 					 handle_simple_irq);
372d5bb1221SThomas Gleixner 		irq_set_nested_thread(irq, 1);
37362579266SRabin Vincent #ifdef CONFIG_ARM
37462579266SRabin Vincent 		set_irq_flags(irq, IRQF_VALID);
37562579266SRabin Vincent #else
376d5bb1221SThomas Gleixner 		irq_set_noprobe(irq);
37762579266SRabin Vincent #endif
37862579266SRabin Vincent 	}
37962579266SRabin Vincent 
38062579266SRabin Vincent 	return 0;
38162579266SRabin Vincent }
38262579266SRabin Vincent 
38362579266SRabin Vincent static void ab8500_irq_remove(struct ab8500 *ab8500)
38462579266SRabin Vincent {
38562579266SRabin Vincent 	int base = ab8500->irq_base;
38662579266SRabin Vincent 	int irq;
3872ced445eSLinus Walleij 	int num_irqs;
38862579266SRabin Vincent 
389d6255529SLinus Walleij 	if (is_ab9540(ab8500))
390d6255529SLinus Walleij 		num_irqs = AB9540_NR_IRQS;
391*a982362cSBengt Jonsson 	else if (is_ab8505(ab8500))
392*a982362cSBengt Jonsson 		num_irqs = AB8505_NR_IRQS;
393d6255529SLinus Walleij 	else
3942ced445eSLinus Walleij 		num_irqs = AB8500_NR_IRQS;
3952ced445eSLinus Walleij 
3962ced445eSLinus Walleij 	for (irq = base; irq < base + num_irqs; irq++) {
39762579266SRabin Vincent #ifdef CONFIG_ARM
39862579266SRabin Vincent 		set_irq_flags(irq, 0);
39962579266SRabin Vincent #endif
400d5bb1221SThomas Gleixner 		irq_set_chip_and_handler(irq, NULL, NULL);
401d5bb1221SThomas Gleixner 		irq_set_chip_data(irq, NULL);
40262579266SRabin Vincent 	}
40362579266SRabin Vincent }
40462579266SRabin Vincent 
405d6255529SLinus Walleij /* AB8500 GPIO Resources */
4065cef8df5SRobert Rosengren static struct resource __devinitdata ab8500_gpio_resources[] = {
4070cb3fcd7SBibek Basu 	{
4080cb3fcd7SBibek Basu 		.name	= "GPIO_INT6",
4090cb3fcd7SBibek Basu 		.start	= AB8500_INT_GPIO6R,
4100cb3fcd7SBibek Basu 		.end	= AB8500_INT_GPIO41F,
4110cb3fcd7SBibek Basu 		.flags	= IORESOURCE_IRQ,
4120cb3fcd7SBibek Basu 	}
4130cb3fcd7SBibek Basu };
4140cb3fcd7SBibek Basu 
415d6255529SLinus Walleij /* AB9540 GPIO Resources */
416d6255529SLinus Walleij static struct resource __devinitdata ab9540_gpio_resources[] = {
417d6255529SLinus Walleij 	{
418d6255529SLinus Walleij 		.name	= "GPIO_INT6",
419d6255529SLinus Walleij 		.start	= AB8500_INT_GPIO6R,
420d6255529SLinus Walleij 		.end	= AB8500_INT_GPIO41F,
421d6255529SLinus Walleij 		.flags	= IORESOURCE_IRQ,
422d6255529SLinus Walleij 	},
423d6255529SLinus Walleij 	{
424d6255529SLinus Walleij 		.name	= "GPIO_INT14",
425d6255529SLinus Walleij 		.start	= AB9540_INT_GPIO50R,
426d6255529SLinus Walleij 		.end	= AB9540_INT_GPIO54R,
427d6255529SLinus Walleij 		.flags	= IORESOURCE_IRQ,
428d6255529SLinus Walleij 	},
429d6255529SLinus Walleij 	{
430d6255529SLinus Walleij 		.name	= "GPIO_INT15",
431d6255529SLinus Walleij 		.start	= AB9540_INT_GPIO50F,
432d6255529SLinus Walleij 		.end	= AB9540_INT_GPIO54F,
433d6255529SLinus Walleij 		.flags	= IORESOURCE_IRQ,
434d6255529SLinus Walleij 	}
435d6255529SLinus Walleij };
436d6255529SLinus Walleij 
4375cef8df5SRobert Rosengren static struct resource __devinitdata ab8500_gpadc_resources[] = {
43862579266SRabin Vincent 	{
43962579266SRabin Vincent 		.name	= "HW_CONV_END",
44062579266SRabin Vincent 		.start	= AB8500_INT_GP_HW_ADC_CONV_END,
44162579266SRabin Vincent 		.end	= AB8500_INT_GP_HW_ADC_CONV_END,
44262579266SRabin Vincent 		.flags	= IORESOURCE_IRQ,
44362579266SRabin Vincent 	},
44462579266SRabin Vincent 	{
44562579266SRabin Vincent 		.name	= "SW_CONV_END",
44662579266SRabin Vincent 		.start	= AB8500_INT_GP_SW_ADC_CONV_END,
44762579266SRabin Vincent 		.end	= AB8500_INT_GP_SW_ADC_CONV_END,
44862579266SRabin Vincent 		.flags	= IORESOURCE_IRQ,
44962579266SRabin Vincent 	},
45062579266SRabin Vincent };
45162579266SRabin Vincent 
4525cef8df5SRobert Rosengren static struct resource __devinitdata ab8500_rtc_resources[] = {
45362579266SRabin Vincent 	{
45462579266SRabin Vincent 		.name	= "60S",
45562579266SRabin Vincent 		.start	= AB8500_INT_RTC_60S,
45662579266SRabin Vincent 		.end	= AB8500_INT_RTC_60S,
45762579266SRabin Vincent 		.flags	= IORESOURCE_IRQ,
45862579266SRabin Vincent 	},
45962579266SRabin Vincent 	{
46062579266SRabin Vincent 		.name	= "ALARM",
46162579266SRabin Vincent 		.start	= AB8500_INT_RTC_ALARM,
46262579266SRabin Vincent 		.end	= AB8500_INT_RTC_ALARM,
46362579266SRabin Vincent 		.flags	= IORESOURCE_IRQ,
46462579266SRabin Vincent 	},
46562579266SRabin Vincent };
46662579266SRabin Vincent 
4675cef8df5SRobert Rosengren static struct resource __devinitdata ab8500_poweronkey_db_resources[] = {
46877686517SSundar R Iyer 	{
46977686517SSundar R Iyer 		.name	= "ONKEY_DBF",
47077686517SSundar R Iyer 		.start	= AB8500_INT_PON_KEY1DB_F,
47177686517SSundar R Iyer 		.end	= AB8500_INT_PON_KEY1DB_F,
47277686517SSundar R Iyer 		.flags	= IORESOURCE_IRQ,
47377686517SSundar R Iyer 	},
47477686517SSundar R Iyer 	{
47577686517SSundar R Iyer 		.name	= "ONKEY_DBR",
47677686517SSundar R Iyer 		.start	= AB8500_INT_PON_KEY1DB_R,
47777686517SSundar R Iyer 		.end	= AB8500_INT_PON_KEY1DB_R,
47877686517SSundar R Iyer 		.flags	= IORESOURCE_IRQ,
47977686517SSundar R Iyer 	},
48077686517SSundar R Iyer };
48177686517SSundar R Iyer 
4826af75ecdSLinus Walleij static struct resource __devinitdata ab8500_av_acc_detect_resources[] = {
483e098adedSMattias Wallin 	{
4846af75ecdSLinus Walleij 	       .name = "ACC_DETECT_1DB_F",
4856af75ecdSLinus Walleij 	       .start = AB8500_INT_ACC_DETECT_1DB_F,
4866af75ecdSLinus Walleij 	       .end = AB8500_INT_ACC_DETECT_1DB_F,
487e098adedSMattias Wallin 	       .flags = IORESOURCE_IRQ,
488e098adedSMattias Wallin 	},
489e098adedSMattias Wallin 	{
4906af75ecdSLinus Walleij 	       .name = "ACC_DETECT_1DB_R",
4916af75ecdSLinus Walleij 	       .start = AB8500_INT_ACC_DETECT_1DB_R,
4926af75ecdSLinus Walleij 	       .end = AB8500_INT_ACC_DETECT_1DB_R,
493e098adedSMattias Wallin 	       .flags = IORESOURCE_IRQ,
494e098adedSMattias Wallin 	},
495e098adedSMattias Wallin 	{
4966af75ecdSLinus Walleij 	       .name = "ACC_DETECT_21DB_F",
4976af75ecdSLinus Walleij 	       .start = AB8500_INT_ACC_DETECT_21DB_F,
4986af75ecdSLinus Walleij 	       .end = AB8500_INT_ACC_DETECT_21DB_F,
4996af75ecdSLinus Walleij 	       .flags = IORESOURCE_IRQ,
5006af75ecdSLinus Walleij 	},
5016af75ecdSLinus Walleij 	{
5026af75ecdSLinus Walleij 	       .name = "ACC_DETECT_21DB_R",
5036af75ecdSLinus Walleij 	       .start = AB8500_INT_ACC_DETECT_21DB_R,
5046af75ecdSLinus Walleij 	       .end = AB8500_INT_ACC_DETECT_21DB_R,
5056af75ecdSLinus Walleij 	       .flags = IORESOURCE_IRQ,
5066af75ecdSLinus Walleij 	},
5076af75ecdSLinus Walleij 	{
5086af75ecdSLinus Walleij 	       .name = "ACC_DETECT_22DB_F",
5096af75ecdSLinus Walleij 	       .start = AB8500_INT_ACC_DETECT_22DB_F,
5106af75ecdSLinus Walleij 	       .end = AB8500_INT_ACC_DETECT_22DB_F,
5116af75ecdSLinus Walleij 	       .flags = IORESOURCE_IRQ,
5126af75ecdSLinus Walleij 	},
5136af75ecdSLinus Walleij 	{
5146af75ecdSLinus Walleij 	       .name = "ACC_DETECT_22DB_R",
5156af75ecdSLinus Walleij 	       .start = AB8500_INT_ACC_DETECT_22DB_R,
5166af75ecdSLinus Walleij 	       .end = AB8500_INT_ACC_DETECT_22DB_R,
5176af75ecdSLinus Walleij 	       .flags = IORESOURCE_IRQ,
5186af75ecdSLinus Walleij 	},
5196af75ecdSLinus Walleij };
5206af75ecdSLinus Walleij 
5216af75ecdSLinus Walleij static struct resource __devinitdata ab8500_charger_resources[] = {
5226af75ecdSLinus Walleij 	{
523e098adedSMattias Wallin 		.name = "MAIN_CH_UNPLUG_DET",
524e098adedSMattias Wallin 		.start = AB8500_INT_MAIN_CH_UNPLUG_DET,
525e098adedSMattias Wallin 		.end = AB8500_INT_MAIN_CH_UNPLUG_DET,
526e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
527e098adedSMattias Wallin 	},
528e098adedSMattias Wallin 	{
529e098adedSMattias Wallin 		.name = "MAIN_CHARGE_PLUG_DET",
530e098adedSMattias Wallin 		.start = AB8500_INT_MAIN_CH_PLUG_DET,
531e098adedSMattias Wallin 		.end = AB8500_INT_MAIN_CH_PLUG_DET,
532e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
533e098adedSMattias Wallin 	},
534e098adedSMattias Wallin 	{
535e098adedSMattias Wallin 		.name = "VBUS_DET_R",
536e098adedSMattias Wallin 		.start = AB8500_INT_VBUS_DET_R,
537e098adedSMattias Wallin 		.end = AB8500_INT_VBUS_DET_R,
538e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
539e098adedSMattias Wallin 	},
540e098adedSMattias Wallin 	{
5416af75ecdSLinus Walleij 		.name = "VBUS_DET_F",
5426af75ecdSLinus Walleij 		.start = AB8500_INT_VBUS_DET_F,
5436af75ecdSLinus Walleij 		.end = AB8500_INT_VBUS_DET_F,
544e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
545e098adedSMattias Wallin 	},
546e098adedSMattias Wallin 	{
5476af75ecdSLinus Walleij 		.name = "USB_LINK_STATUS",
5486af75ecdSLinus Walleij 		.start = AB8500_INT_USB_LINK_STATUS,
5496af75ecdSLinus Walleij 		.end = AB8500_INT_USB_LINK_STATUS,
5506af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
5516af75ecdSLinus Walleij 	},
5526af75ecdSLinus Walleij 	{
553e098adedSMattias Wallin 		.name = "VBUS_OVV",
554e098adedSMattias Wallin 		.start = AB8500_INT_VBUS_OVV,
555e098adedSMattias Wallin 		.end = AB8500_INT_VBUS_OVV,
556e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
557e098adedSMattias Wallin 	},
558e098adedSMattias Wallin 	{
5596af75ecdSLinus Walleij 		.name = "USB_CH_TH_PROT_R",
5606af75ecdSLinus Walleij 		.start = AB8500_INT_USB_CH_TH_PROT_R,
5616af75ecdSLinus Walleij 		.end = AB8500_INT_USB_CH_TH_PROT_R,
562e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
563e098adedSMattias Wallin 	},
564e098adedSMattias Wallin 	{
5656af75ecdSLinus Walleij 		.name = "USB_CH_TH_PROT_F",
5666af75ecdSLinus Walleij 		.start = AB8500_INT_USB_CH_TH_PROT_F,
5676af75ecdSLinus Walleij 		.end = AB8500_INT_USB_CH_TH_PROT_F,
568e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
569e098adedSMattias Wallin 	},
570e098adedSMattias Wallin 	{
5716af75ecdSLinus Walleij 		.name = "MAIN_EXT_CH_NOT_OK",
5726af75ecdSLinus Walleij 		.start = AB8500_INT_MAIN_EXT_CH_NOT_OK,
5736af75ecdSLinus Walleij 		.end = AB8500_INT_MAIN_EXT_CH_NOT_OK,
5746af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
5756af75ecdSLinus Walleij 	},
5766af75ecdSLinus Walleij 	{
5776af75ecdSLinus Walleij 		.name = "MAIN_CH_TH_PROT_R",
5786af75ecdSLinus Walleij 		.start = AB8500_INT_MAIN_CH_TH_PROT_R,
5796af75ecdSLinus Walleij 		.end = AB8500_INT_MAIN_CH_TH_PROT_R,
5806af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
5816af75ecdSLinus Walleij 	},
5826af75ecdSLinus Walleij 	{
5836af75ecdSLinus Walleij 		.name = "MAIN_CH_TH_PROT_F",
5846af75ecdSLinus Walleij 		.start = AB8500_INT_MAIN_CH_TH_PROT_F,
5856af75ecdSLinus Walleij 		.end = AB8500_INT_MAIN_CH_TH_PROT_F,
5866af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
5876af75ecdSLinus Walleij 	},
5886af75ecdSLinus Walleij 	{
5896af75ecdSLinus Walleij 		.name = "USB_CHARGER_NOT_OKR",
590*a982362cSBengt Jonsson 		.start = AB8500_INT_USB_CHARGER_NOT_OKR,
591*a982362cSBengt Jonsson 		.end = AB8500_INT_USB_CHARGER_NOT_OKR,
5926af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
5936af75ecdSLinus Walleij 	},
5946af75ecdSLinus Walleij 	{
5956af75ecdSLinus Walleij 		.name = "CH_WD_EXP",
5966af75ecdSLinus Walleij 		.start = AB8500_INT_CH_WD_EXP,
5976af75ecdSLinus Walleij 		.end = AB8500_INT_CH_WD_EXP,
5986af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
5996af75ecdSLinus Walleij 	},
6006af75ecdSLinus Walleij };
6016af75ecdSLinus Walleij 
6026af75ecdSLinus Walleij static struct resource __devinitdata ab8500_btemp_resources[] = {
6036af75ecdSLinus Walleij 	{
6046af75ecdSLinus Walleij 		.name = "BAT_CTRL_INDB",
6056af75ecdSLinus Walleij 		.start = AB8500_INT_BAT_CTRL_INDB,
6066af75ecdSLinus Walleij 		.end = AB8500_INT_BAT_CTRL_INDB,
607e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
608e098adedSMattias Wallin 	},
609e098adedSMattias Wallin 	{
610e098adedSMattias Wallin 		.name = "BTEMP_LOW",
611e098adedSMattias Wallin 		.start = AB8500_INT_BTEMP_LOW,
612e098adedSMattias Wallin 		.end = AB8500_INT_BTEMP_LOW,
613e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
614e098adedSMattias Wallin 	},
615e098adedSMattias Wallin 	{
616e098adedSMattias Wallin 		.name = "BTEMP_HIGH",
617e098adedSMattias Wallin 		.start = AB8500_INT_BTEMP_HIGH,
618e098adedSMattias Wallin 		.end = AB8500_INT_BTEMP_HIGH,
619e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
620e098adedSMattias Wallin 	},
621e098adedSMattias Wallin 	{
6226af75ecdSLinus Walleij 		.name = "BTEMP_LOW_MEDIUM",
6236af75ecdSLinus Walleij 		.start = AB8500_INT_BTEMP_LOW_MEDIUM,
6246af75ecdSLinus Walleij 		.end = AB8500_INT_BTEMP_LOW_MEDIUM,
625e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
626e098adedSMattias Wallin 	},
627e098adedSMattias Wallin 	{
6286af75ecdSLinus Walleij 		.name = "BTEMP_MEDIUM_HIGH",
6296af75ecdSLinus Walleij 		.start = AB8500_INT_BTEMP_MEDIUM_HIGH,
6306af75ecdSLinus Walleij 		.end = AB8500_INT_BTEMP_MEDIUM_HIGH,
631e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
632e098adedSMattias Wallin 	},
633e098adedSMattias Wallin };
634e098adedSMattias Wallin 
6356af75ecdSLinus Walleij static struct resource __devinitdata ab8500_fg_resources[] = {
6366af75ecdSLinus Walleij 	{
6376af75ecdSLinus Walleij 		.name = "NCONV_ACCU",
6386af75ecdSLinus Walleij 		.start = AB8500_INT_CCN_CONV_ACC,
6396af75ecdSLinus Walleij 		.end = AB8500_INT_CCN_CONV_ACC,
6406af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
6416af75ecdSLinus Walleij 	},
6426af75ecdSLinus Walleij 	{
6436af75ecdSLinus Walleij 		.name = "BATT_OVV",
6446af75ecdSLinus Walleij 		.start = AB8500_INT_BATT_OVV,
6456af75ecdSLinus Walleij 		.end = AB8500_INT_BATT_OVV,
6466af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
6476af75ecdSLinus Walleij 	},
6486af75ecdSLinus Walleij 	{
6496af75ecdSLinus Walleij 		.name = "LOW_BAT_F",
6506af75ecdSLinus Walleij 		.start = AB8500_INT_LOW_BAT_F,
6516af75ecdSLinus Walleij 		.end = AB8500_INT_LOW_BAT_F,
6526af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
6536af75ecdSLinus Walleij 	},
6546af75ecdSLinus Walleij 	{
6556af75ecdSLinus Walleij 		.name = "LOW_BAT_R",
6566af75ecdSLinus Walleij 		.start = AB8500_INT_LOW_BAT_R,
6576af75ecdSLinus Walleij 		.end = AB8500_INT_LOW_BAT_R,
6586af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
6596af75ecdSLinus Walleij 	},
6606af75ecdSLinus Walleij 	{
6616af75ecdSLinus Walleij 		.name = "CC_INT_CALIB",
6626af75ecdSLinus Walleij 		.start = AB8500_INT_CC_INT_CALIB,
6636af75ecdSLinus Walleij 		.end = AB8500_INT_CC_INT_CALIB,
6646af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
6656af75ecdSLinus Walleij 	},
666*a982362cSBengt Jonsson 	{
667*a982362cSBengt Jonsson 		.name = "CCEOC",
668*a982362cSBengt Jonsson 		.start = AB8500_INT_CCEOC,
669*a982362cSBengt Jonsson 		.end = AB8500_INT_CCEOC,
670*a982362cSBengt Jonsson 		.flags = IORESOURCE_IRQ,
671*a982362cSBengt Jonsson 	},
6726af75ecdSLinus Walleij };
6736af75ecdSLinus Walleij 
6746af75ecdSLinus Walleij static struct resource __devinitdata ab8500_chargalg_resources[] = {};
6756af75ecdSLinus Walleij 
676df720647SAxel Lin #ifdef CONFIG_DEBUG_FS
6775cef8df5SRobert Rosengren static struct resource __devinitdata ab8500_debug_resources[] = {
678e098adedSMattias Wallin 	{
679e098adedSMattias Wallin 		.name	= "IRQ_FIRST",
680e098adedSMattias Wallin 		.start	= AB8500_INT_MAIN_EXT_CH_NOT_OK,
681e098adedSMattias Wallin 		.end	= AB8500_INT_MAIN_EXT_CH_NOT_OK,
682e098adedSMattias Wallin 		.flags	= IORESOURCE_IRQ,
683e098adedSMattias Wallin 	},
684e098adedSMattias Wallin 	{
685e098adedSMattias Wallin 		.name	= "IRQ_LAST",
686*a982362cSBengt Jonsson 		.start	= AB8500_INT_XTAL32K_KO,
687*a982362cSBengt Jonsson 		.end	= AB8500_INT_XTAL32K_KO,
688e098adedSMattias Wallin 		.flags	= IORESOURCE_IRQ,
689e098adedSMattias Wallin 	},
690e098adedSMattias Wallin };
691df720647SAxel Lin #endif
692e098adedSMattias Wallin 
6935cef8df5SRobert Rosengren static struct resource __devinitdata ab8500_usb_resources[] = {
694e098adedSMattias Wallin 	{
695e098adedSMattias Wallin 		.name = "ID_WAKEUP_R",
696e098adedSMattias Wallin 		.start = AB8500_INT_ID_WAKEUP_R,
697e098adedSMattias Wallin 		.end = AB8500_INT_ID_WAKEUP_R,
698e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
699e098adedSMattias Wallin 	},
700e098adedSMattias Wallin 	{
701e098adedSMattias Wallin 		.name = "ID_WAKEUP_F",
702e098adedSMattias Wallin 		.start = AB8500_INT_ID_WAKEUP_F,
703e098adedSMattias Wallin 		.end = AB8500_INT_ID_WAKEUP_F,
704e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
705e098adedSMattias Wallin 	},
706e098adedSMattias Wallin 	{
707e098adedSMattias Wallin 		.name = "VBUS_DET_F",
708e098adedSMattias Wallin 		.start = AB8500_INT_VBUS_DET_F,
709e098adedSMattias Wallin 		.end = AB8500_INT_VBUS_DET_F,
710e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
711e098adedSMattias Wallin 	},
712e098adedSMattias Wallin 	{
713e098adedSMattias Wallin 		.name = "VBUS_DET_R",
714e098adedSMattias Wallin 		.start = AB8500_INT_VBUS_DET_R,
715e098adedSMattias Wallin 		.end = AB8500_INT_VBUS_DET_R,
716e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
717e098adedSMattias Wallin 	},
71892d50a41SMattias Wallin 	{
71992d50a41SMattias Wallin 		.name = "USB_LINK_STATUS",
72092d50a41SMattias Wallin 		.start = AB8500_INT_USB_LINK_STATUS,
72192d50a41SMattias Wallin 		.end = AB8500_INT_USB_LINK_STATUS,
72292d50a41SMattias Wallin 		.flags = IORESOURCE_IRQ,
72392d50a41SMattias Wallin 	},
7246af75ecdSLinus Walleij 	{
7256af75ecdSLinus Walleij 		.name = "USB_ADP_PROBE_PLUG",
7266af75ecdSLinus Walleij 		.start = AB8500_INT_ADP_PROBE_PLUG,
7276af75ecdSLinus Walleij 		.end = AB8500_INT_ADP_PROBE_PLUG,
7286af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
7296af75ecdSLinus Walleij 	},
7306af75ecdSLinus Walleij 	{
7316af75ecdSLinus Walleij 		.name = "USB_ADP_PROBE_UNPLUG",
7326af75ecdSLinus Walleij 		.start = AB8500_INT_ADP_PROBE_UNPLUG,
7336af75ecdSLinus Walleij 		.end = AB8500_INT_ADP_PROBE_UNPLUG,
7346af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
7356af75ecdSLinus Walleij 	},
736e098adedSMattias Wallin };
737e098adedSMattias Wallin 
7385cef8df5SRobert Rosengren static struct resource __devinitdata ab8500_temp_resources[] = {
739e098adedSMattias Wallin 	{
740e098adedSMattias Wallin 		.name  = "AB8500_TEMP_WARM",
741e098adedSMattias Wallin 		.start = AB8500_INT_TEMP_WARM,
742e098adedSMattias Wallin 		.end   = AB8500_INT_TEMP_WARM,
743e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
744e098adedSMattias Wallin 	},
745e098adedSMattias Wallin };
746e098adedSMattias Wallin 
747d6255529SLinus Walleij static struct mfd_cell __devinitdata abx500_common_devs[] = {
7485814fc35SMattias Wallin #ifdef CONFIG_DEBUG_FS
7495814fc35SMattias Wallin 	{
7505814fc35SMattias Wallin 		.name = "ab8500-debug",
751e098adedSMattias Wallin 		.num_resources = ARRAY_SIZE(ab8500_debug_resources),
752e098adedSMattias Wallin 		.resources = ab8500_debug_resources,
7535814fc35SMattias Wallin 	},
7545814fc35SMattias Wallin #endif
75562579266SRabin Vincent 	{
756e098adedSMattias Wallin 		.name = "ab8500-sysctrl",
757e098adedSMattias Wallin 	},
758e098adedSMattias Wallin 	{
759e098adedSMattias Wallin 		.name = "ab8500-regulator",
760e098adedSMattias Wallin 	},
761e098adedSMattias Wallin 	{
76262579266SRabin Vincent 		.name = "ab8500-gpadc",
76362579266SRabin Vincent 		.num_resources = ARRAY_SIZE(ab8500_gpadc_resources),
76462579266SRabin Vincent 		.resources = ab8500_gpadc_resources,
76562579266SRabin Vincent 	},
76662579266SRabin Vincent 	{
76762579266SRabin Vincent 		.name = "ab8500-rtc",
76862579266SRabin Vincent 		.num_resources = ARRAY_SIZE(ab8500_rtc_resources),
76962579266SRabin Vincent 		.resources = ab8500_rtc_resources,
77062579266SRabin Vincent 	},
771f0f05b1cSArun Murthy 	{
7726af75ecdSLinus Walleij 		.name = "ab8500-charger",
7736af75ecdSLinus Walleij 		.num_resources = ARRAY_SIZE(ab8500_charger_resources),
7746af75ecdSLinus Walleij 		.resources = ab8500_charger_resources,
775e098adedSMattias Wallin 	},
7766af75ecdSLinus Walleij 	{
7776af75ecdSLinus Walleij 		.name = "ab8500-btemp",
7786af75ecdSLinus Walleij 		.num_resources = ARRAY_SIZE(ab8500_btemp_resources),
7796af75ecdSLinus Walleij 		.resources = ab8500_btemp_resources,
7806af75ecdSLinus Walleij 	},
7816af75ecdSLinus Walleij 	{
7826af75ecdSLinus Walleij 		.name = "ab8500-fg",
7836af75ecdSLinus Walleij 		.num_resources = ARRAY_SIZE(ab8500_fg_resources),
7846af75ecdSLinus Walleij 		.resources = ab8500_fg_resources,
7856af75ecdSLinus Walleij 	},
7866af75ecdSLinus Walleij 	{
7876af75ecdSLinus Walleij 		.name = "ab8500-chargalg",
7886af75ecdSLinus Walleij 		.num_resources = ARRAY_SIZE(ab8500_chargalg_resources),
7896af75ecdSLinus Walleij 		.resources = ab8500_chargalg_resources,
7906af75ecdSLinus Walleij 	},
7916af75ecdSLinus Walleij 	{
7926af75ecdSLinus Walleij 		.name = "ab8500-acc-det",
7936af75ecdSLinus Walleij 		.num_resources = ARRAY_SIZE(ab8500_av_acc_detect_resources),
7946af75ecdSLinus Walleij 		.resources = ab8500_av_acc_detect_resources,
7956af75ecdSLinus Walleij 	},
7966af75ecdSLinus Walleij 	{
7976af75ecdSLinus Walleij 		.name = "ab8500-codec",
7986af75ecdSLinus Walleij 	},
799d6255529SLinus Walleij 
800e098adedSMattias Wallin 	{
801e098adedSMattias Wallin 		.name = "ab8500-poweron-key",
802e098adedSMattias Wallin 		.num_resources = ARRAY_SIZE(ab8500_poweronkey_db_resources),
803e098adedSMattias Wallin 		.resources = ab8500_poweronkey_db_resources,
804e098adedSMattias Wallin 	},
805e098adedSMattias Wallin 	{
806f0f05b1cSArun Murthy 		.name = "ab8500-pwm",
807f0f05b1cSArun Murthy 		.id = 1,
808f0f05b1cSArun Murthy 	},
809f0f05b1cSArun Murthy 	{
810f0f05b1cSArun Murthy 		.name = "ab8500-pwm",
811f0f05b1cSArun Murthy 		.id = 2,
812f0f05b1cSArun Murthy 	},
813f0f05b1cSArun Murthy 	{
814f0f05b1cSArun Murthy 		.name = "ab8500-pwm",
815f0f05b1cSArun Murthy 		.id = 3,
816f0f05b1cSArun Murthy 	},
817e098adedSMattias Wallin 	{ .name = "ab8500-leds", },
81877686517SSundar R Iyer 	{
819e098adedSMattias Wallin 		.name = "ab8500-denc",
820e098adedSMattias Wallin 	},
821e098adedSMattias Wallin 	{
822e098adedSMattias Wallin 		.name = "ab8500-temp",
823e098adedSMattias Wallin 		.num_resources = ARRAY_SIZE(ab8500_temp_resources),
824e098adedSMattias Wallin 		.resources = ab8500_temp_resources,
82577686517SSundar R Iyer 	},
82662579266SRabin Vincent };
82762579266SRabin Vincent 
828d6255529SLinus Walleij static struct mfd_cell __devinitdata ab8500_devs[] = {
829d6255529SLinus Walleij 	{
830d6255529SLinus Walleij 		.name = "ab8500-gpio",
831d6255529SLinus Walleij 		.num_resources = ARRAY_SIZE(ab8500_gpio_resources),
832d6255529SLinus Walleij 		.resources = ab8500_gpio_resources,
833d6255529SLinus Walleij 	},
834d6255529SLinus Walleij 	{
835d6255529SLinus Walleij 		.name = "ab8500-usb",
836d6255529SLinus Walleij 		.num_resources = ARRAY_SIZE(ab8500_usb_resources),
837d6255529SLinus Walleij 		.resources = ab8500_usb_resources,
838d6255529SLinus Walleij 	},
839d6255529SLinus Walleij };
840d6255529SLinus Walleij 
841d6255529SLinus Walleij static struct mfd_cell __devinitdata ab9540_devs[] = {
842d6255529SLinus Walleij 	{
843d6255529SLinus Walleij 		.name = "ab8500-gpio",
844d6255529SLinus Walleij 		.num_resources = ARRAY_SIZE(ab9540_gpio_resources),
845d6255529SLinus Walleij 		.resources = ab9540_gpio_resources,
846d6255529SLinus Walleij 	},
847d6255529SLinus Walleij 	{
848d6255529SLinus Walleij 		.name = "ab9540-usb",
849d6255529SLinus Walleij 		.num_resources = ARRAY_SIZE(ab8500_usb_resources),
850d6255529SLinus Walleij 		.resources = ab8500_usb_resources,
851d6255529SLinus Walleij 	},
852d6255529SLinus Walleij };
853d6255529SLinus Walleij 
854cca69b67SMattias Wallin static ssize_t show_chip_id(struct device *dev,
855cca69b67SMattias Wallin 				struct device_attribute *attr, char *buf)
856cca69b67SMattias Wallin {
857cca69b67SMattias Wallin 	struct ab8500 *ab8500;
858cca69b67SMattias Wallin 
859cca69b67SMattias Wallin 	ab8500 = dev_get_drvdata(dev);
860cca69b67SMattias Wallin 	return sprintf(buf, "%#x\n", ab8500 ? ab8500->chip_id : -EINVAL);
861cca69b67SMattias Wallin }
862cca69b67SMattias Wallin 
863e5c238c3SMattias Wallin /*
864e5c238c3SMattias Wallin  * ab8500 has switched off due to (SWITCH_OFF_STATUS):
865e5c238c3SMattias Wallin  * 0x01 Swoff bit programming
866e5c238c3SMattias Wallin  * 0x02 Thermal protection activation
867e5c238c3SMattias Wallin  * 0x04 Vbat lower then BattOk falling threshold
868e5c238c3SMattias Wallin  * 0x08 Watchdog expired
869e5c238c3SMattias Wallin  * 0x10 Non presence of 32kHz clock
870e5c238c3SMattias Wallin  * 0x20 Battery level lower than power on reset threshold
871e5c238c3SMattias Wallin  * 0x40 Power on key 1 pressed longer than 10 seconds
872e5c238c3SMattias Wallin  * 0x80 DB8500 thermal shutdown
873e5c238c3SMattias Wallin  */
874e5c238c3SMattias Wallin static ssize_t show_switch_off_status(struct device *dev,
875e5c238c3SMattias Wallin 				struct device_attribute *attr, char *buf)
876e5c238c3SMattias Wallin {
877e5c238c3SMattias Wallin 	int ret;
878e5c238c3SMattias Wallin 	u8 value;
879e5c238c3SMattias Wallin 	struct ab8500 *ab8500;
880e5c238c3SMattias Wallin 
881e5c238c3SMattias Wallin 	ab8500 = dev_get_drvdata(dev);
882e5c238c3SMattias Wallin 	ret = get_register_interruptible(ab8500, AB8500_RTC,
883e5c238c3SMattias Wallin 		AB8500_SWITCH_OFF_STATUS, &value);
884e5c238c3SMattias Wallin 	if (ret < 0)
885e5c238c3SMattias Wallin 		return ret;
886e5c238c3SMattias Wallin 	return sprintf(buf, "%#x\n", value);
887e5c238c3SMattias Wallin }
888e5c238c3SMattias Wallin 
889b4a31037SAndrew Lynn /*
890b4a31037SAndrew Lynn  * ab8500 has turned on due to (TURN_ON_STATUS):
891b4a31037SAndrew Lynn  * 0x01 PORnVbat
892b4a31037SAndrew Lynn  * 0x02 PonKey1dbF
893b4a31037SAndrew Lynn  * 0x04 PonKey2dbF
894b4a31037SAndrew Lynn  * 0x08 RTCAlarm
895b4a31037SAndrew Lynn  * 0x10 MainChDet
896b4a31037SAndrew Lynn  * 0x20 VbusDet
897b4a31037SAndrew Lynn  * 0x40 UsbIDDetect
898b4a31037SAndrew Lynn  * 0x80 Reserved
899b4a31037SAndrew Lynn  */
900b4a31037SAndrew Lynn static ssize_t show_turn_on_status(struct device *dev,
901b4a31037SAndrew Lynn 				struct device_attribute *attr, char *buf)
902b4a31037SAndrew Lynn {
903b4a31037SAndrew Lynn 	int ret;
904b4a31037SAndrew Lynn 	u8 value;
905b4a31037SAndrew Lynn 	struct ab8500 *ab8500;
906b4a31037SAndrew Lynn 
907b4a31037SAndrew Lynn 	ab8500 = dev_get_drvdata(dev);
908b4a31037SAndrew Lynn 	ret = get_register_interruptible(ab8500, AB8500_SYS_CTRL1_BLOCK,
909b4a31037SAndrew Lynn 		AB8500_TURN_ON_STATUS, &value);
910b4a31037SAndrew Lynn 	if (ret < 0)
911b4a31037SAndrew Lynn 		return ret;
912b4a31037SAndrew Lynn 	return sprintf(buf, "%#x\n", value);
913b4a31037SAndrew Lynn }
914b4a31037SAndrew Lynn 
915d6255529SLinus Walleij static ssize_t show_ab9540_dbbrstn(struct device *dev,
916d6255529SLinus Walleij 				struct device_attribute *attr, char *buf)
917d6255529SLinus Walleij {
918d6255529SLinus Walleij 	struct ab8500 *ab8500;
919d6255529SLinus Walleij 	int ret;
920d6255529SLinus Walleij 	u8 value;
921d6255529SLinus Walleij 
922d6255529SLinus Walleij 	ab8500 = dev_get_drvdata(dev);
923d6255529SLinus Walleij 
924d6255529SLinus Walleij 	ret = get_register_interruptible(ab8500, AB8500_REGU_CTRL2,
925d6255529SLinus Walleij 		AB9540_MODEM_CTRL2_REG, &value);
926d6255529SLinus Walleij 	if (ret < 0)
927d6255529SLinus Walleij 		return ret;
928d6255529SLinus Walleij 
929d6255529SLinus Walleij 	return sprintf(buf, "%d\n",
930d6255529SLinus Walleij 			(value & AB9540_MODEM_CTRL2_SWDBBRSTN_BIT) ? 1 : 0);
931d6255529SLinus Walleij }
932d6255529SLinus Walleij 
933d6255529SLinus Walleij static ssize_t store_ab9540_dbbrstn(struct device *dev,
934d6255529SLinus Walleij 	struct device_attribute *attr, const char *buf, size_t count)
935d6255529SLinus Walleij {
936d6255529SLinus Walleij 	struct ab8500 *ab8500;
937d6255529SLinus Walleij 	int ret = count;
938d6255529SLinus Walleij 	int err;
939d6255529SLinus Walleij 	u8 bitvalues;
940d6255529SLinus Walleij 
941d6255529SLinus Walleij 	ab8500 = dev_get_drvdata(dev);
942d6255529SLinus Walleij 
943d6255529SLinus Walleij 	if (count > 0) {
944d6255529SLinus Walleij 		switch (buf[0]) {
945d6255529SLinus Walleij 		case '0':
946d6255529SLinus Walleij 			bitvalues = 0;
947d6255529SLinus Walleij 			break;
948d6255529SLinus Walleij 		case '1':
949d6255529SLinus Walleij 			bitvalues = AB9540_MODEM_CTRL2_SWDBBRSTN_BIT;
950d6255529SLinus Walleij 			break;
951d6255529SLinus Walleij 		default:
952d6255529SLinus Walleij 			goto exit;
953d6255529SLinus Walleij 		}
954d6255529SLinus Walleij 
955d6255529SLinus Walleij 		err = mask_and_set_register_interruptible(ab8500,
956d6255529SLinus Walleij 			AB8500_REGU_CTRL2, AB9540_MODEM_CTRL2_REG,
957d6255529SLinus Walleij 			AB9540_MODEM_CTRL2_SWDBBRSTN_BIT, bitvalues);
958d6255529SLinus Walleij 		if (err)
959d6255529SLinus Walleij 			dev_info(ab8500->dev,
960d6255529SLinus Walleij 				"Failed to set DBBRSTN %c, err %#x\n",
961d6255529SLinus Walleij 				buf[0], err);
962d6255529SLinus Walleij 	}
963d6255529SLinus Walleij 
964d6255529SLinus Walleij exit:
965d6255529SLinus Walleij 	return ret;
966d6255529SLinus Walleij }
967d6255529SLinus Walleij 
968cca69b67SMattias Wallin static DEVICE_ATTR(chip_id, S_IRUGO, show_chip_id, NULL);
969e5c238c3SMattias Wallin static DEVICE_ATTR(switch_off_status, S_IRUGO, show_switch_off_status, NULL);
970b4a31037SAndrew Lynn static DEVICE_ATTR(turn_on_status, S_IRUGO, show_turn_on_status, NULL);
971d6255529SLinus Walleij static DEVICE_ATTR(dbbrstn, S_IRUGO | S_IWUSR,
972d6255529SLinus Walleij 			show_ab9540_dbbrstn, store_ab9540_dbbrstn);
973cca69b67SMattias Wallin 
974cca69b67SMattias Wallin static struct attribute *ab8500_sysfs_entries[] = {
975cca69b67SMattias Wallin 	&dev_attr_chip_id.attr,
976e5c238c3SMattias Wallin 	&dev_attr_switch_off_status.attr,
977b4a31037SAndrew Lynn 	&dev_attr_turn_on_status.attr,
978cca69b67SMattias Wallin 	NULL,
979cca69b67SMattias Wallin };
980cca69b67SMattias Wallin 
981d6255529SLinus Walleij static struct attribute *ab9540_sysfs_entries[] = {
982d6255529SLinus Walleij 	&dev_attr_chip_id.attr,
983d6255529SLinus Walleij 	&dev_attr_switch_off_status.attr,
984d6255529SLinus Walleij 	&dev_attr_turn_on_status.attr,
985d6255529SLinus Walleij 	&dev_attr_dbbrstn.attr,
986d6255529SLinus Walleij 	NULL,
987d6255529SLinus Walleij };
988d6255529SLinus Walleij 
989cca69b67SMattias Wallin static struct attribute_group ab8500_attr_group = {
990cca69b67SMattias Wallin 	.attrs	= ab8500_sysfs_entries,
991cca69b67SMattias Wallin };
992cca69b67SMattias Wallin 
993d6255529SLinus Walleij static struct attribute_group ab9540_attr_group = {
994d6255529SLinus Walleij 	.attrs	= ab9540_sysfs_entries,
995d6255529SLinus Walleij };
996d6255529SLinus Walleij 
9970f620837SLinus Walleij int __devinit ab8500_init(struct ab8500 *ab8500, enum ab8500_version version)
99862579266SRabin Vincent {
99962579266SRabin Vincent 	struct ab8500_platform_data *plat = dev_get_platdata(ab8500->dev);
100062579266SRabin Vincent 	int ret;
100162579266SRabin Vincent 	int i;
100247c16975SMattias Wallin 	u8 value;
100362579266SRabin Vincent 
100462579266SRabin Vincent 	if (plat)
100562579266SRabin Vincent 		ab8500->irq_base = plat->irq_base;
100662579266SRabin Vincent 
100762579266SRabin Vincent 	mutex_init(&ab8500->lock);
100862579266SRabin Vincent 	mutex_init(&ab8500->irq_lock);
100962579266SRabin Vincent 
10100f620837SLinus Walleij 	if (version != AB8500_VERSION_UNDEFINED)
10110f620837SLinus Walleij 		ab8500->version = version;
10120f620837SLinus Walleij 	else {
10130f620837SLinus Walleij 		ret = get_register_interruptible(ab8500, AB8500_MISC,
10140f620837SLinus Walleij 			AB8500_IC_NAME_REG, &value);
10150f620837SLinus Walleij 		if (ret < 0)
10160f620837SLinus Walleij 			return ret;
10170f620837SLinus Walleij 
10180f620837SLinus Walleij 		ab8500->version = value;
10190f620837SLinus Walleij 	}
10200f620837SLinus Walleij 
102147c16975SMattias Wallin 	ret = get_register_interruptible(ab8500, AB8500_MISC,
102247c16975SMattias Wallin 		AB8500_REV_REG, &value);
102362579266SRabin Vincent 	if (ret < 0)
102462579266SRabin Vincent 		return ret;
102562579266SRabin Vincent 
102647c16975SMattias Wallin 	ab8500->chip_id = value;
102762579266SRabin Vincent 
10280f620837SLinus Walleij 	dev_info(ab8500->dev, "detected chip, %s rev. %1x.%1x\n",
10290f620837SLinus Walleij 			ab8500_version_str[ab8500->version],
10300f620837SLinus Walleij 			ab8500->chip_id >> 4,
10310f620837SLinus Walleij 			ab8500->chip_id & 0x0F);
10320f620837SLinus Walleij 
1033d6255529SLinus Walleij 	/* Configure AB8500 or AB9540 IRQ */
1034*a982362cSBengt Jonsson 	if (is_ab9540(ab8500) || is_ab8505(ab8500)) {
1035d6255529SLinus Walleij 		ab8500->mask_size = AB9540_NUM_IRQ_REGS;
1036d6255529SLinus Walleij 		ab8500->irq_reg_offset = ab9540_irq_regoffset;
1037d6255529SLinus Walleij 	} else {
10382ced445eSLinus Walleij 		ab8500->mask_size = AB8500_NUM_IRQ_REGS;
10392ced445eSLinus Walleij 		ab8500->irq_reg_offset = ab8500_irq_regoffset;
1040d6255529SLinus Walleij 	}
10412ced445eSLinus Walleij 	ab8500->mask = kzalloc(ab8500->mask_size, GFP_KERNEL);
10422ced445eSLinus Walleij 	if (!ab8500->mask)
10432ced445eSLinus Walleij 		return -ENOMEM;
10442ced445eSLinus Walleij 	ab8500->oldmask = kzalloc(ab8500->mask_size, GFP_KERNEL);
10452ced445eSLinus Walleij 	if (!ab8500->oldmask) {
10462ced445eSLinus Walleij 		ret = -ENOMEM;
10472ced445eSLinus Walleij 		goto out_freemask;
10482ced445eSLinus Walleij 	}
1049e5c238c3SMattias Wallin 	/*
1050e5c238c3SMattias Wallin 	 * ab8500 has switched off due to (SWITCH_OFF_STATUS):
1051e5c238c3SMattias Wallin 	 * 0x01 Swoff bit programming
1052e5c238c3SMattias Wallin 	 * 0x02 Thermal protection activation
1053e5c238c3SMattias Wallin 	 * 0x04 Vbat lower then BattOk falling threshold
1054e5c238c3SMattias Wallin 	 * 0x08 Watchdog expired
1055e5c238c3SMattias Wallin 	 * 0x10 Non presence of 32kHz clock
1056e5c238c3SMattias Wallin 	 * 0x20 Battery level lower than power on reset threshold
1057e5c238c3SMattias Wallin 	 * 0x40 Power on key 1 pressed longer than 10 seconds
1058e5c238c3SMattias Wallin 	 * 0x80 DB8500 thermal shutdown
1059e5c238c3SMattias Wallin 	 */
1060e5c238c3SMattias Wallin 
1061e5c238c3SMattias Wallin 	ret = get_register_interruptible(ab8500, AB8500_RTC,
1062e5c238c3SMattias Wallin 		AB8500_SWITCH_OFF_STATUS, &value);
1063e5c238c3SMattias Wallin 	if (ret < 0)
1064e5c238c3SMattias Wallin 		return ret;
1065e5c238c3SMattias Wallin 	dev_info(ab8500->dev, "switch off status: %#x", value);
1066e5c238c3SMattias Wallin 
106762579266SRabin Vincent 	if (plat && plat->init)
106862579266SRabin Vincent 		plat->init(ab8500);
106962579266SRabin Vincent 
107062579266SRabin Vincent 	/* Clear and mask all interrupts */
10712ced445eSLinus Walleij 	for (i = 0; i < ab8500->mask_size; i++) {
10720f620837SLinus Walleij 		/*
10730f620837SLinus Walleij 		 * Interrupt register 12 doesn't exist prior to AB8500 version
10740f620837SLinus Walleij 		 * 2.0
10750f620837SLinus Walleij 		 */
10760f620837SLinus Walleij 		if (ab8500->irq_reg_offset[i] == 11 &&
10770f620837SLinus Walleij 				is_ab8500_1p1_or_earlier(ab8500))
107892d50a41SMattias Wallin 			continue;
107962579266SRabin Vincent 
108047c16975SMattias Wallin 		get_register_interruptible(ab8500, AB8500_INTERRUPT,
10812ced445eSLinus Walleij 			AB8500_IT_LATCH1_REG + ab8500->irq_reg_offset[i],
108292d50a41SMattias Wallin 			&value);
108347c16975SMattias Wallin 		set_register_interruptible(ab8500, AB8500_INTERRUPT,
10842ced445eSLinus Walleij 			AB8500_IT_MASK1_REG + ab8500->irq_reg_offset[i], 0xff);
108562579266SRabin Vincent 	}
108662579266SRabin Vincent 
108747c16975SMattias Wallin 	ret = abx500_register_ops(ab8500->dev, &ab8500_ops);
108847c16975SMattias Wallin 	if (ret)
10892ced445eSLinus Walleij 		goto out_freeoldmask;
109047c16975SMattias Wallin 
10912ced445eSLinus Walleij 	for (i = 0; i < ab8500->mask_size; i++)
109262579266SRabin Vincent 		ab8500->mask[i] = ab8500->oldmask[i] = 0xff;
109362579266SRabin Vincent 
109462579266SRabin Vincent 	if (ab8500->irq_base) {
109562579266SRabin Vincent 		ret = ab8500_irq_init(ab8500);
109662579266SRabin Vincent 		if (ret)
10972ced445eSLinus Walleij 			goto out_freeoldmask;
109862579266SRabin Vincent 
109962579266SRabin Vincent 		ret = request_threaded_irq(ab8500->irq, NULL, ab8500_irq,
11004f079985SMattias Wallin 					   IRQF_ONESHOT | IRQF_NO_SUSPEND,
11014f079985SMattias Wallin 					   "ab8500", ab8500);
110262579266SRabin Vincent 		if (ret)
110362579266SRabin Vincent 			goto out_removeirq;
110462579266SRabin Vincent 	}
110562579266SRabin Vincent 
1106d6255529SLinus Walleij 	ret = mfd_add_devices(ab8500->dev, 0, abx500_common_devs,
1107d6255529SLinus Walleij 			      ARRAY_SIZE(abx500_common_devs), NULL,
1108d6255529SLinus Walleij 			      ab8500->irq_base);
1109d6255529SLinus Walleij 
1110d6255529SLinus Walleij 	if (ret)
1111d6255529SLinus Walleij 		goto out_freeirq;
1112d6255529SLinus Walleij 
1113d6255529SLinus Walleij 	if (is_ab9540(ab8500))
1114d6255529SLinus Walleij 		ret = mfd_add_devices(ab8500->dev, 0, ab9540_devs,
1115d6255529SLinus Walleij 			      ARRAY_SIZE(ab9540_devs), NULL,
1116d6255529SLinus Walleij 			      ab8500->irq_base);
1117d6255529SLinus Walleij 	else
1118549931f9SSundar R Iyer 		ret = mfd_add_devices(ab8500->dev, 0, ab8500_devs,
1119d6255529SLinus Walleij 			      ARRAY_SIZE(ab9540_devs), NULL,
112062579266SRabin Vincent 			      ab8500->irq_base);
112162579266SRabin Vincent 	if (ret)
112262579266SRabin Vincent 		goto out_freeirq;
112362579266SRabin Vincent 
1124d6255529SLinus Walleij 	if (is_ab9540(ab8500))
1125d6255529SLinus Walleij 		ret = sysfs_create_group(&ab8500->dev->kobj,
1126d6255529SLinus Walleij 					&ab9540_attr_group);
1127d6255529SLinus Walleij 	else
1128d6255529SLinus Walleij 		ret = sysfs_create_group(&ab8500->dev->kobj,
1129d6255529SLinus Walleij 					&ab8500_attr_group);
1130cca69b67SMattias Wallin 	if (ret)
1131cca69b67SMattias Wallin 		dev_err(ab8500->dev, "error creating sysfs entries\n");
1132d6255529SLinus Walleij 	else
113362579266SRabin Vincent 		return ret;
113462579266SRabin Vincent 
113562579266SRabin Vincent out_freeirq:
11366d95b7fdSLinus Walleij 	if (ab8500->irq_base)
113762579266SRabin Vincent 		free_irq(ab8500->irq, ab8500);
113862579266SRabin Vincent out_removeirq:
11396d95b7fdSLinus Walleij 	if (ab8500->irq_base)
114062579266SRabin Vincent 		ab8500_irq_remove(ab8500);
11412ced445eSLinus Walleij out_freeoldmask:
11422ced445eSLinus Walleij 	kfree(ab8500->oldmask);
11432ced445eSLinus Walleij out_freemask:
11442ced445eSLinus Walleij 	kfree(ab8500->mask);
11456d95b7fdSLinus Walleij 
114662579266SRabin Vincent 	return ret;
114762579266SRabin Vincent }
114862579266SRabin Vincent 
114962579266SRabin Vincent int __devexit ab8500_exit(struct ab8500 *ab8500)
115062579266SRabin Vincent {
1151d6255529SLinus Walleij 	if (is_ab9540(ab8500))
1152d6255529SLinus Walleij 		sysfs_remove_group(&ab8500->dev->kobj, &ab9540_attr_group);
1153d6255529SLinus Walleij 	else
1154cca69b67SMattias Wallin 		sysfs_remove_group(&ab8500->dev->kobj, &ab8500_attr_group);
115562579266SRabin Vincent 	mfd_remove_devices(ab8500->dev);
115662579266SRabin Vincent 	if (ab8500->irq_base) {
115762579266SRabin Vincent 		free_irq(ab8500->irq, ab8500);
115862579266SRabin Vincent 		ab8500_irq_remove(ab8500);
115962579266SRabin Vincent 	}
11602ced445eSLinus Walleij 	kfree(ab8500->oldmask);
11612ced445eSLinus Walleij 	kfree(ab8500->mask);
116262579266SRabin Vincent 
116362579266SRabin Vincent 	return 0;
116462579266SRabin Vincent }
116562579266SRabin Vincent 
1166adceed62SMattias Wallin MODULE_AUTHOR("Mattias Wallin, Srinidhi Kasagar, Rabin Vincent");
116762579266SRabin Vincent MODULE_DESCRIPTION("AB8500 MFD core");
116862579266SRabin Vincent MODULE_LICENSE("GPL v2");
1169