xref: /openbmc/linux/drivers/mfd/ab8500-core.c (revision 2ced445e2ddf65f484a489161accddf475676965)
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
3547c16975SMattias Wallin #define AB8500_IT_SOURCE19_REG		0x12
3647c16975SMattias Wallin #define AB8500_IT_SOURCE20_REG		0x13
3747c16975SMattias Wallin #define AB8500_IT_SOURCE21_REG		0x14
3847c16975SMattias Wallin #define AB8500_IT_SOURCE22_REG		0x15
3947c16975SMattias Wallin #define AB8500_IT_SOURCE23_REG		0x16
4047c16975SMattias Wallin #define AB8500_IT_SOURCE24_REG		0x17
4162579266SRabin Vincent 
4262579266SRabin Vincent /*
4362579266SRabin Vincent  * latch registers
4462579266SRabin Vincent  */
4547c16975SMattias Wallin #define AB8500_IT_LATCH1_REG		0x20
4647c16975SMattias Wallin #define AB8500_IT_LATCH2_REG		0x21
4747c16975SMattias Wallin #define AB8500_IT_LATCH3_REG		0x22
4847c16975SMattias Wallin #define AB8500_IT_LATCH4_REG		0x23
4947c16975SMattias Wallin #define AB8500_IT_LATCH5_REG		0x24
5047c16975SMattias Wallin #define AB8500_IT_LATCH6_REG		0x25
5147c16975SMattias Wallin #define AB8500_IT_LATCH7_REG		0x26
5247c16975SMattias Wallin #define AB8500_IT_LATCH8_REG		0x27
5347c16975SMattias Wallin #define AB8500_IT_LATCH9_REG		0x28
5447c16975SMattias Wallin #define AB8500_IT_LATCH10_REG		0x29
5592d50a41SMattias Wallin #define AB8500_IT_LATCH12_REG		0x2B
5647c16975SMattias Wallin #define AB8500_IT_LATCH19_REG		0x32
5747c16975SMattias Wallin #define AB8500_IT_LATCH20_REG		0x33
5847c16975SMattias Wallin #define AB8500_IT_LATCH21_REG		0x34
5947c16975SMattias Wallin #define AB8500_IT_LATCH22_REG		0x35
6047c16975SMattias Wallin #define AB8500_IT_LATCH23_REG		0x36
6147c16975SMattias Wallin #define AB8500_IT_LATCH24_REG		0x37
6262579266SRabin Vincent 
6362579266SRabin Vincent /*
6462579266SRabin Vincent  * mask registers
6562579266SRabin Vincent  */
6662579266SRabin Vincent 
6747c16975SMattias Wallin #define AB8500_IT_MASK1_REG		0x40
6847c16975SMattias Wallin #define AB8500_IT_MASK2_REG		0x41
6947c16975SMattias Wallin #define AB8500_IT_MASK3_REG		0x42
7047c16975SMattias Wallin #define AB8500_IT_MASK4_REG		0x43
7147c16975SMattias Wallin #define AB8500_IT_MASK5_REG		0x44
7247c16975SMattias Wallin #define AB8500_IT_MASK6_REG		0x45
7347c16975SMattias Wallin #define AB8500_IT_MASK7_REG		0x46
7447c16975SMattias Wallin #define AB8500_IT_MASK8_REG		0x47
7547c16975SMattias Wallin #define AB8500_IT_MASK9_REG		0x48
7647c16975SMattias Wallin #define AB8500_IT_MASK10_REG		0x49
7747c16975SMattias Wallin #define AB8500_IT_MASK11_REG		0x4A
7847c16975SMattias Wallin #define AB8500_IT_MASK12_REG		0x4B
7947c16975SMattias Wallin #define AB8500_IT_MASK13_REG		0x4C
8047c16975SMattias Wallin #define AB8500_IT_MASK14_REG		0x4D
8147c16975SMattias Wallin #define AB8500_IT_MASK15_REG		0x4E
8247c16975SMattias Wallin #define AB8500_IT_MASK16_REG		0x4F
8347c16975SMattias Wallin #define AB8500_IT_MASK17_REG		0x50
8447c16975SMattias Wallin #define AB8500_IT_MASK18_REG		0x51
8547c16975SMattias Wallin #define AB8500_IT_MASK19_REG		0x52
8647c16975SMattias Wallin #define AB8500_IT_MASK20_REG		0x53
8747c16975SMattias Wallin #define AB8500_IT_MASK21_REG		0x54
8847c16975SMattias Wallin #define AB8500_IT_MASK22_REG		0x55
8947c16975SMattias Wallin #define AB8500_IT_MASK23_REG		0x56
9047c16975SMattias Wallin #define AB8500_IT_MASK24_REG		0x57
9162579266SRabin Vincent 
9247c16975SMattias Wallin #define AB8500_REV_REG			0x80
930f620837SLinus Walleij #define AB8500_IC_NAME_REG		0x82
94e5c238c3SMattias Wallin #define AB8500_SWITCH_OFF_STATUS	0x00
9562579266SRabin Vincent 
96b4a31037SAndrew Lynn #define AB8500_TURN_ON_STATUS		0x00
97b4a31037SAndrew Lynn 
9862579266SRabin Vincent /*
9962579266SRabin Vincent  * Map interrupt numbers to the LATCH and MASK register offsets, Interrupt
100*2ced445eSLinus Walleij  * numbers are indexed into this array with (num / 8). The interupts are
101*2ced445eSLinus Walleij  * defined in linux/mfd/ab8500.h
10262579266SRabin Vincent  *
10362579266SRabin Vincent  * This is one off from the register names, i.e. AB8500_IT_MASK1_REG is at
10462579266SRabin Vincent  * offset 0.
10562579266SRabin Vincent  */
106*2ced445eSLinus Walleij /* AB8500 support */
10762579266SRabin Vincent static const int ab8500_irq_regoffset[AB8500_NUM_IRQ_REGS] = {
10892d50a41SMattias Wallin 	0, 1, 2, 3, 4, 6, 7, 8, 9, 11, 18, 19, 20, 21,
10962579266SRabin Vincent };
11062579266SRabin Vincent 
1110f620837SLinus Walleij static const char ab8500_version_str[][7] = {
1120f620837SLinus Walleij 	[AB8500_VERSION_AB8500] = "AB8500",
1130f620837SLinus Walleij 	[AB8500_VERSION_AB8505] = "AB8505",
1140f620837SLinus Walleij 	[AB8500_VERSION_AB9540] = "AB9540",
1150f620837SLinus Walleij 	[AB8500_VERSION_AB8540] = "AB8540",
1160f620837SLinus Walleij };
1170f620837SLinus Walleij 
11847c16975SMattias Wallin static int ab8500_get_chip_id(struct device *dev)
11947c16975SMattias Wallin {
1206bce7bf1SMattias Wallin 	struct ab8500 *ab8500;
1216bce7bf1SMattias Wallin 
1226bce7bf1SMattias Wallin 	if (!dev)
1236bce7bf1SMattias Wallin 		return -EINVAL;
1246bce7bf1SMattias Wallin 	ab8500 = dev_get_drvdata(dev->parent);
1256bce7bf1SMattias Wallin 	return ab8500 ? (int)ab8500->chip_id : -EINVAL;
12647c16975SMattias Wallin }
12747c16975SMattias Wallin 
12847c16975SMattias Wallin static int set_register_interruptible(struct ab8500 *ab8500, u8 bank,
12947c16975SMattias Wallin 	u8 reg, u8 data)
13062579266SRabin Vincent {
13162579266SRabin Vincent 	int ret;
13247c16975SMattias Wallin 	/*
13347c16975SMattias Wallin 	 * Put the u8 bank and u8 register together into a an u16.
13447c16975SMattias Wallin 	 * The bank on higher 8 bits and register in lower 8 bits.
13547c16975SMattias Wallin 	 * */
13647c16975SMattias Wallin 	u16 addr = ((u16)bank) << 8 | reg;
13762579266SRabin Vincent 
13862579266SRabin Vincent 	dev_vdbg(ab8500->dev, "wr: addr %#x <= %#x\n", addr, data);
13962579266SRabin Vincent 
14047c16975SMattias Wallin 	ret = mutex_lock_interruptible(&ab8500->lock);
14147c16975SMattias Wallin 	if (ret)
14247c16975SMattias Wallin 		return ret;
14347c16975SMattias Wallin 
14447c16975SMattias Wallin 	ret = ab8500->write(ab8500, addr, data);
14547c16975SMattias Wallin 	if (ret < 0)
14647c16975SMattias Wallin 		dev_err(ab8500->dev, "failed to write reg %#x: %d\n",
14747c16975SMattias Wallin 			addr, ret);
14847c16975SMattias Wallin 	mutex_unlock(&ab8500->lock);
14947c16975SMattias Wallin 
15047c16975SMattias Wallin 	return ret;
15147c16975SMattias Wallin }
15247c16975SMattias Wallin 
15347c16975SMattias Wallin static int ab8500_set_register(struct device *dev, u8 bank,
15447c16975SMattias Wallin 	u8 reg, u8 value)
15547c16975SMattias Wallin {
15647c16975SMattias Wallin 	struct ab8500 *ab8500 = dev_get_drvdata(dev->parent);
15747c16975SMattias Wallin 
15847c16975SMattias Wallin 	return set_register_interruptible(ab8500, bank, reg, value);
15947c16975SMattias Wallin }
16047c16975SMattias Wallin 
16147c16975SMattias Wallin static int get_register_interruptible(struct ab8500 *ab8500, u8 bank,
16247c16975SMattias Wallin 	u8 reg, u8 *value)
16347c16975SMattias Wallin {
16447c16975SMattias Wallin 	int ret;
16547c16975SMattias Wallin 	/* put the u8 bank and u8 reg together into a an u16.
16647c16975SMattias Wallin 	 * bank on higher 8 bits and reg in lower */
16747c16975SMattias Wallin 	u16 addr = ((u16)bank) << 8 | reg;
16847c16975SMattias Wallin 
16947c16975SMattias Wallin 	ret = mutex_lock_interruptible(&ab8500->lock);
17047c16975SMattias Wallin 	if (ret)
17147c16975SMattias Wallin 		return ret;
17247c16975SMattias Wallin 
17347c16975SMattias Wallin 	ret = ab8500->read(ab8500, addr);
17447c16975SMattias Wallin 	if (ret < 0)
17547c16975SMattias Wallin 		dev_err(ab8500->dev, "failed to read reg %#x: %d\n",
17647c16975SMattias Wallin 			addr, ret);
17747c16975SMattias Wallin 	else
17847c16975SMattias Wallin 		*value = ret;
17947c16975SMattias Wallin 
18047c16975SMattias Wallin 	mutex_unlock(&ab8500->lock);
18147c16975SMattias Wallin 	dev_vdbg(ab8500->dev, "rd: addr %#x => data %#x\n", addr, ret);
18247c16975SMattias Wallin 
18347c16975SMattias Wallin 	return ret;
18447c16975SMattias Wallin }
18547c16975SMattias Wallin 
18647c16975SMattias Wallin static int ab8500_get_register(struct device *dev, u8 bank,
18747c16975SMattias Wallin 	u8 reg, u8 *value)
18847c16975SMattias Wallin {
18947c16975SMattias Wallin 	struct ab8500 *ab8500 = dev_get_drvdata(dev->parent);
19047c16975SMattias Wallin 
19147c16975SMattias Wallin 	return get_register_interruptible(ab8500, bank, reg, value);
19247c16975SMattias Wallin }
19347c16975SMattias Wallin 
19447c16975SMattias Wallin static int mask_and_set_register_interruptible(struct ab8500 *ab8500, u8 bank,
19547c16975SMattias Wallin 	u8 reg, u8 bitmask, u8 bitvalues)
19647c16975SMattias Wallin {
19747c16975SMattias Wallin 	int ret;
19847c16975SMattias Wallin 	u8 data;
19947c16975SMattias Wallin 	/* put the u8 bank and u8 reg together into a an u16.
20047c16975SMattias Wallin 	 * bank on higher 8 bits and reg in lower */
20147c16975SMattias Wallin 	u16 addr = ((u16)bank) << 8 | reg;
20247c16975SMattias Wallin 
20347c16975SMattias Wallin 	ret = mutex_lock_interruptible(&ab8500->lock);
20447c16975SMattias Wallin 	if (ret)
20547c16975SMattias Wallin 		return ret;
20647c16975SMattias Wallin 
20747c16975SMattias Wallin 	ret = ab8500->read(ab8500, addr);
20847c16975SMattias Wallin 	if (ret < 0) {
20947c16975SMattias Wallin 		dev_err(ab8500->dev, "failed to read reg %#x: %d\n",
21047c16975SMattias Wallin 			addr, ret);
21147c16975SMattias Wallin 		goto out;
21247c16975SMattias Wallin 	}
21347c16975SMattias Wallin 
21447c16975SMattias Wallin 	data = (u8)ret;
21547c16975SMattias Wallin 	data = (~bitmask & data) | (bitmask & bitvalues);
21647c16975SMattias Wallin 
21762579266SRabin Vincent 	ret = ab8500->write(ab8500, addr, data);
21862579266SRabin Vincent 	if (ret < 0)
21962579266SRabin Vincent 		dev_err(ab8500->dev, "failed to write reg %#x: %d\n",
22062579266SRabin Vincent 			addr, ret);
22162579266SRabin Vincent 
22247c16975SMattias Wallin 	dev_vdbg(ab8500->dev, "mask: addr %#x => data %#x\n", addr, data);
22362579266SRabin Vincent out:
22462579266SRabin Vincent 	mutex_unlock(&ab8500->lock);
22562579266SRabin Vincent 	return ret;
22662579266SRabin Vincent }
22747c16975SMattias Wallin 
22847c16975SMattias Wallin static int ab8500_mask_and_set_register(struct device *dev,
22947c16975SMattias Wallin 	u8 bank, u8 reg, u8 bitmask, u8 bitvalues)
23047c16975SMattias Wallin {
23147c16975SMattias Wallin 	struct ab8500 *ab8500 = dev_get_drvdata(dev->parent);
23247c16975SMattias Wallin 
23347c16975SMattias Wallin 	return mask_and_set_register_interruptible(ab8500, bank, reg,
23447c16975SMattias Wallin 		bitmask, bitvalues);
23547c16975SMattias Wallin 
23647c16975SMattias Wallin }
23747c16975SMattias Wallin 
23847c16975SMattias Wallin static struct abx500_ops ab8500_ops = {
23947c16975SMattias Wallin 	.get_chip_id = ab8500_get_chip_id,
24047c16975SMattias Wallin 	.get_register = ab8500_get_register,
24147c16975SMattias Wallin 	.set_register = ab8500_set_register,
24247c16975SMattias Wallin 	.get_register_page = NULL,
24347c16975SMattias Wallin 	.set_register_page = NULL,
24447c16975SMattias Wallin 	.mask_and_set_register = ab8500_mask_and_set_register,
24547c16975SMattias Wallin 	.event_registers_startup_state_get = NULL,
24647c16975SMattias Wallin 	.startup_irq_enabled = NULL,
24747c16975SMattias Wallin };
24862579266SRabin Vincent 
2499505a0a0SMark Brown static void ab8500_irq_lock(struct irq_data *data)
25062579266SRabin Vincent {
2519505a0a0SMark Brown 	struct ab8500 *ab8500 = irq_data_get_irq_chip_data(data);
25262579266SRabin Vincent 
25362579266SRabin Vincent 	mutex_lock(&ab8500->irq_lock);
25462579266SRabin Vincent }
25562579266SRabin Vincent 
2569505a0a0SMark Brown static void ab8500_irq_sync_unlock(struct irq_data *data)
25762579266SRabin Vincent {
2589505a0a0SMark Brown 	struct ab8500 *ab8500 = irq_data_get_irq_chip_data(data);
25962579266SRabin Vincent 	int i;
26062579266SRabin Vincent 
261*2ced445eSLinus Walleij 	for (i = 0; i < ab8500->mask_size; i++) {
26262579266SRabin Vincent 		u8 old = ab8500->oldmask[i];
26362579266SRabin Vincent 		u8 new = ab8500->mask[i];
26462579266SRabin Vincent 		int reg;
26562579266SRabin Vincent 
26662579266SRabin Vincent 		if (new == old)
26762579266SRabin Vincent 			continue;
26862579266SRabin Vincent 
2690f620837SLinus Walleij 		/*
2700f620837SLinus Walleij 		 * Interrupt register 12 doesn't exist prior to AB8500 version
2710f620837SLinus Walleij 		 * 2.0
2720f620837SLinus Walleij 		 */
2730f620837SLinus Walleij 		if (ab8500->irq_reg_offset[i] == 11 &&
2740f620837SLinus Walleij 			is_ab8500_1p1_or_earlier(ab8500))
27592d50a41SMattias Wallin 			continue;
27692d50a41SMattias Wallin 
27762579266SRabin Vincent 		ab8500->oldmask[i] = new;
27862579266SRabin Vincent 
279*2ced445eSLinus Walleij 		reg = AB8500_IT_MASK1_REG + ab8500->irq_reg_offset[i];
28047c16975SMattias Wallin 		set_register_interruptible(ab8500, AB8500_INTERRUPT, reg, new);
28162579266SRabin Vincent 	}
28262579266SRabin Vincent 
28362579266SRabin Vincent 	mutex_unlock(&ab8500->irq_lock);
28462579266SRabin Vincent }
28562579266SRabin Vincent 
2869505a0a0SMark Brown static void ab8500_irq_mask(struct irq_data *data)
28762579266SRabin Vincent {
2889505a0a0SMark Brown 	struct ab8500 *ab8500 = irq_data_get_irq_chip_data(data);
2899505a0a0SMark Brown 	int offset = data->irq - ab8500->irq_base;
29062579266SRabin Vincent 	int index = offset / 8;
29162579266SRabin Vincent 	int mask = 1 << (offset % 8);
29262579266SRabin Vincent 
29362579266SRabin Vincent 	ab8500->mask[index] |= mask;
29462579266SRabin Vincent }
29562579266SRabin Vincent 
2969505a0a0SMark Brown static void ab8500_irq_unmask(struct irq_data *data)
29762579266SRabin Vincent {
2989505a0a0SMark Brown 	struct ab8500 *ab8500 = irq_data_get_irq_chip_data(data);
2999505a0a0SMark Brown 	int offset = data->irq - ab8500->irq_base;
30062579266SRabin Vincent 	int index = offset / 8;
30162579266SRabin Vincent 	int mask = 1 << (offset % 8);
30262579266SRabin Vincent 
30362579266SRabin Vincent 	ab8500->mask[index] &= ~mask;
30462579266SRabin Vincent }
30562579266SRabin Vincent 
30662579266SRabin Vincent static struct irq_chip ab8500_irq_chip = {
30762579266SRabin Vincent 	.name			= "ab8500",
3089505a0a0SMark Brown 	.irq_bus_lock		= ab8500_irq_lock,
3099505a0a0SMark Brown 	.irq_bus_sync_unlock	= ab8500_irq_sync_unlock,
3109505a0a0SMark Brown 	.irq_mask		= ab8500_irq_mask,
311e6f9306eSVirupax Sadashivpetimath 	.irq_disable		= ab8500_irq_mask,
3129505a0a0SMark Brown 	.irq_unmask		= ab8500_irq_unmask,
31362579266SRabin Vincent };
31462579266SRabin Vincent 
31562579266SRabin Vincent static irqreturn_t ab8500_irq(int irq, void *dev)
31662579266SRabin Vincent {
31762579266SRabin Vincent 	struct ab8500 *ab8500 = dev;
31862579266SRabin Vincent 	int i;
31962579266SRabin Vincent 
32062579266SRabin Vincent 	dev_vdbg(ab8500->dev, "interrupt\n");
32162579266SRabin Vincent 
322*2ced445eSLinus Walleij 	for (i = 0; i < ab8500->mask_size; i++) {
323*2ced445eSLinus Walleij 		int regoffset = ab8500->irq_reg_offset[i];
32462579266SRabin Vincent 		int status;
32547c16975SMattias Wallin 		u8 value;
32662579266SRabin Vincent 
3270f620837SLinus Walleij 		/*
3280f620837SLinus Walleij 		 * Interrupt register 12 doesn't exist prior to AB8500 version
3290f620837SLinus Walleij 		 * 2.0
3300f620837SLinus Walleij 		 */
3310f620837SLinus Walleij 		if (regoffset == 11 && is_ab8500_1p1_or_earlier(ab8500))
33292d50a41SMattias Wallin 			continue;
33392d50a41SMattias Wallin 
33447c16975SMattias Wallin 		status = get_register_interruptible(ab8500, AB8500_INTERRUPT,
33547c16975SMattias Wallin 			AB8500_IT_LATCH1_REG + regoffset, &value);
33647c16975SMattias Wallin 		if (status < 0 || value == 0)
33762579266SRabin Vincent 			continue;
33862579266SRabin Vincent 
33962579266SRabin Vincent 		do {
34088aec4f7SMattias Wallin 			int bit = __ffs(value);
34162579266SRabin Vincent 			int line = i * 8 + bit;
34262579266SRabin Vincent 
34362579266SRabin Vincent 			handle_nested_irq(ab8500->irq_base + line);
34447c16975SMattias Wallin 			value &= ~(1 << bit);
34547c16975SMattias Wallin 		} while (value);
34662579266SRabin Vincent 	}
34762579266SRabin Vincent 
34862579266SRabin Vincent 	return IRQ_HANDLED;
34962579266SRabin Vincent }
35062579266SRabin Vincent 
35162579266SRabin Vincent static int ab8500_irq_init(struct ab8500 *ab8500)
35262579266SRabin Vincent {
35362579266SRabin Vincent 	int base = ab8500->irq_base;
35462579266SRabin Vincent 	int irq;
355*2ced445eSLinus Walleij 	int num_irqs;
35662579266SRabin Vincent 
357*2ced445eSLinus Walleij 	num_irqs = AB8500_NR_IRQS;
358*2ced445eSLinus Walleij 
359*2ced445eSLinus Walleij 	for (irq = base; irq < base + num_irqs; irq++) {
360d5bb1221SThomas Gleixner 		irq_set_chip_data(irq, ab8500);
361d5bb1221SThomas Gleixner 		irq_set_chip_and_handler(irq, &ab8500_irq_chip,
36262579266SRabin Vincent 					 handle_simple_irq);
363d5bb1221SThomas Gleixner 		irq_set_nested_thread(irq, 1);
36462579266SRabin Vincent #ifdef CONFIG_ARM
36562579266SRabin Vincent 		set_irq_flags(irq, IRQF_VALID);
36662579266SRabin Vincent #else
367d5bb1221SThomas Gleixner 		irq_set_noprobe(irq);
36862579266SRabin Vincent #endif
36962579266SRabin Vincent 	}
37062579266SRabin Vincent 
37162579266SRabin Vincent 	return 0;
37262579266SRabin Vincent }
37362579266SRabin Vincent 
37462579266SRabin Vincent static void ab8500_irq_remove(struct ab8500 *ab8500)
37562579266SRabin Vincent {
37662579266SRabin Vincent 	int base = ab8500->irq_base;
37762579266SRabin Vincent 	int irq;
378*2ced445eSLinus Walleij 	int num_irqs;
37962579266SRabin Vincent 
380*2ced445eSLinus Walleij 	num_irqs = AB8500_NR_IRQS;
381*2ced445eSLinus Walleij 
382*2ced445eSLinus Walleij 	for (irq = base; irq < base + num_irqs; irq++) {
38362579266SRabin Vincent #ifdef CONFIG_ARM
38462579266SRabin Vincent 		set_irq_flags(irq, 0);
38562579266SRabin Vincent #endif
386d5bb1221SThomas Gleixner 		irq_set_chip_and_handler(irq, NULL, NULL);
387d5bb1221SThomas Gleixner 		irq_set_chip_data(irq, NULL);
38862579266SRabin Vincent 	}
38962579266SRabin Vincent }
39062579266SRabin Vincent 
3915cef8df5SRobert Rosengren static struct resource __devinitdata ab8500_gpio_resources[] = {
3920cb3fcd7SBibek Basu 	{
3930cb3fcd7SBibek Basu 		.name	= "GPIO_INT6",
3940cb3fcd7SBibek Basu 		.start	= AB8500_INT_GPIO6R,
3950cb3fcd7SBibek Basu 		.end	= AB8500_INT_GPIO41F,
3960cb3fcd7SBibek Basu 		.flags	= IORESOURCE_IRQ,
3970cb3fcd7SBibek Basu 	}
3980cb3fcd7SBibek Basu };
3990cb3fcd7SBibek Basu 
4005cef8df5SRobert Rosengren static struct resource __devinitdata ab8500_gpadc_resources[] = {
40162579266SRabin Vincent 	{
40262579266SRabin Vincent 		.name	= "HW_CONV_END",
40362579266SRabin Vincent 		.start	= AB8500_INT_GP_HW_ADC_CONV_END,
40462579266SRabin Vincent 		.end	= AB8500_INT_GP_HW_ADC_CONV_END,
40562579266SRabin Vincent 		.flags	= IORESOURCE_IRQ,
40662579266SRabin Vincent 	},
40762579266SRabin Vincent 	{
40862579266SRabin Vincent 		.name	= "SW_CONV_END",
40962579266SRabin Vincent 		.start	= AB8500_INT_GP_SW_ADC_CONV_END,
41062579266SRabin Vincent 		.end	= AB8500_INT_GP_SW_ADC_CONV_END,
41162579266SRabin Vincent 		.flags	= IORESOURCE_IRQ,
41262579266SRabin Vincent 	},
41362579266SRabin Vincent };
41462579266SRabin Vincent 
4155cef8df5SRobert Rosengren static struct resource __devinitdata ab8500_rtc_resources[] = {
41662579266SRabin Vincent 	{
41762579266SRabin Vincent 		.name	= "60S",
41862579266SRabin Vincent 		.start	= AB8500_INT_RTC_60S,
41962579266SRabin Vincent 		.end	= AB8500_INT_RTC_60S,
42062579266SRabin Vincent 		.flags	= IORESOURCE_IRQ,
42162579266SRabin Vincent 	},
42262579266SRabin Vincent 	{
42362579266SRabin Vincent 		.name	= "ALARM",
42462579266SRabin Vincent 		.start	= AB8500_INT_RTC_ALARM,
42562579266SRabin Vincent 		.end	= AB8500_INT_RTC_ALARM,
42662579266SRabin Vincent 		.flags	= IORESOURCE_IRQ,
42762579266SRabin Vincent 	},
42862579266SRabin Vincent };
42962579266SRabin Vincent 
4305cef8df5SRobert Rosengren static struct resource __devinitdata ab8500_poweronkey_db_resources[] = {
43177686517SSundar R Iyer 	{
43277686517SSundar R Iyer 		.name	= "ONKEY_DBF",
43377686517SSundar R Iyer 		.start	= AB8500_INT_PON_KEY1DB_F,
43477686517SSundar R Iyer 		.end	= AB8500_INT_PON_KEY1DB_F,
43577686517SSundar R Iyer 		.flags	= IORESOURCE_IRQ,
43677686517SSundar R Iyer 	},
43777686517SSundar R Iyer 	{
43877686517SSundar R Iyer 		.name	= "ONKEY_DBR",
43977686517SSundar R Iyer 		.start	= AB8500_INT_PON_KEY1DB_R,
44077686517SSundar R Iyer 		.end	= AB8500_INT_PON_KEY1DB_R,
44177686517SSundar R Iyer 		.flags	= IORESOURCE_IRQ,
44277686517SSundar R Iyer 	},
44377686517SSundar R Iyer };
44477686517SSundar R Iyer 
4456af75ecdSLinus Walleij static struct resource __devinitdata ab8500_av_acc_detect_resources[] = {
446e098adedSMattias Wallin 	{
4476af75ecdSLinus Walleij 	       .name = "ACC_DETECT_1DB_F",
4486af75ecdSLinus Walleij 	       .start = AB8500_INT_ACC_DETECT_1DB_F,
4496af75ecdSLinus Walleij 	       .end = AB8500_INT_ACC_DETECT_1DB_F,
450e098adedSMattias Wallin 	       .flags = IORESOURCE_IRQ,
451e098adedSMattias Wallin 	},
452e098adedSMattias Wallin 	{
4536af75ecdSLinus Walleij 	       .name = "ACC_DETECT_1DB_R",
4546af75ecdSLinus Walleij 	       .start = AB8500_INT_ACC_DETECT_1DB_R,
4556af75ecdSLinus Walleij 	       .end = AB8500_INT_ACC_DETECT_1DB_R,
456e098adedSMattias Wallin 	       .flags = IORESOURCE_IRQ,
457e098adedSMattias Wallin 	},
458e098adedSMattias Wallin 	{
4596af75ecdSLinus Walleij 	       .name = "ACC_DETECT_21DB_F",
4606af75ecdSLinus Walleij 	       .start = AB8500_INT_ACC_DETECT_21DB_F,
4616af75ecdSLinus Walleij 	       .end = AB8500_INT_ACC_DETECT_21DB_F,
4626af75ecdSLinus Walleij 	       .flags = IORESOURCE_IRQ,
4636af75ecdSLinus Walleij 	},
4646af75ecdSLinus Walleij 	{
4656af75ecdSLinus Walleij 	       .name = "ACC_DETECT_21DB_R",
4666af75ecdSLinus Walleij 	       .start = AB8500_INT_ACC_DETECT_21DB_R,
4676af75ecdSLinus Walleij 	       .end = AB8500_INT_ACC_DETECT_21DB_R,
4686af75ecdSLinus Walleij 	       .flags = IORESOURCE_IRQ,
4696af75ecdSLinus Walleij 	},
4706af75ecdSLinus Walleij 	{
4716af75ecdSLinus Walleij 	       .name = "ACC_DETECT_22DB_F",
4726af75ecdSLinus Walleij 	       .start = AB8500_INT_ACC_DETECT_22DB_F,
4736af75ecdSLinus Walleij 	       .end = AB8500_INT_ACC_DETECT_22DB_F,
4746af75ecdSLinus Walleij 	       .flags = IORESOURCE_IRQ,
4756af75ecdSLinus Walleij 	},
4766af75ecdSLinus Walleij 	{
4776af75ecdSLinus Walleij 	       .name = "ACC_DETECT_22DB_R",
4786af75ecdSLinus Walleij 	       .start = AB8500_INT_ACC_DETECT_22DB_R,
4796af75ecdSLinus Walleij 	       .end = AB8500_INT_ACC_DETECT_22DB_R,
4806af75ecdSLinus Walleij 	       .flags = IORESOURCE_IRQ,
4816af75ecdSLinus Walleij 	},
4826af75ecdSLinus Walleij };
4836af75ecdSLinus Walleij 
4846af75ecdSLinus Walleij static struct resource __devinitdata ab8500_charger_resources[] = {
4856af75ecdSLinus Walleij 	{
486e098adedSMattias Wallin 		.name = "MAIN_CH_UNPLUG_DET",
487e098adedSMattias Wallin 		.start = AB8500_INT_MAIN_CH_UNPLUG_DET,
488e098adedSMattias Wallin 		.end = AB8500_INT_MAIN_CH_UNPLUG_DET,
489e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
490e098adedSMattias Wallin 	},
491e098adedSMattias Wallin 	{
492e098adedSMattias Wallin 		.name = "MAIN_CHARGE_PLUG_DET",
493e098adedSMattias Wallin 		.start = AB8500_INT_MAIN_CH_PLUG_DET,
494e098adedSMattias Wallin 		.end = AB8500_INT_MAIN_CH_PLUG_DET,
495e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
496e098adedSMattias Wallin 	},
497e098adedSMattias Wallin 	{
498e098adedSMattias Wallin 		.name = "VBUS_DET_R",
499e098adedSMattias Wallin 		.start = AB8500_INT_VBUS_DET_R,
500e098adedSMattias Wallin 		.end = AB8500_INT_VBUS_DET_R,
501e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
502e098adedSMattias Wallin 	},
503e098adedSMattias Wallin 	{
5046af75ecdSLinus Walleij 		.name = "VBUS_DET_F",
5056af75ecdSLinus Walleij 		.start = AB8500_INT_VBUS_DET_F,
5066af75ecdSLinus Walleij 		.end = AB8500_INT_VBUS_DET_F,
507e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
508e098adedSMattias Wallin 	},
509e098adedSMattias Wallin 	{
5106af75ecdSLinus Walleij 		.name = "USB_LINK_STATUS",
5116af75ecdSLinus Walleij 		.start = AB8500_INT_USB_LINK_STATUS,
5126af75ecdSLinus Walleij 		.end = AB8500_INT_USB_LINK_STATUS,
5136af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
5146af75ecdSLinus Walleij 	},
5156af75ecdSLinus Walleij 	{
5166af75ecdSLinus Walleij 		.name = "USB_CHARGE_DET_DONE",
5176af75ecdSLinus Walleij 		.start = AB8500_INT_USB_CHG_DET_DONE,
5186af75ecdSLinus Walleij 		.end = AB8500_INT_USB_CHG_DET_DONE,
519e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
520e098adedSMattias Wallin 	},
521e098adedSMattias Wallin 	{
522e098adedSMattias Wallin 		.name = "VBUS_OVV",
523e098adedSMattias Wallin 		.start = AB8500_INT_VBUS_OVV,
524e098adedSMattias Wallin 		.end = AB8500_INT_VBUS_OVV,
525e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
526e098adedSMattias Wallin 	},
527e098adedSMattias Wallin 	{
5286af75ecdSLinus Walleij 		.name = "USB_CH_TH_PROT_R",
5296af75ecdSLinus Walleij 		.start = AB8500_INT_USB_CH_TH_PROT_R,
5306af75ecdSLinus Walleij 		.end = AB8500_INT_USB_CH_TH_PROT_R,
531e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
532e098adedSMattias Wallin 	},
533e098adedSMattias Wallin 	{
5346af75ecdSLinus Walleij 		.name = "USB_CH_TH_PROT_F",
5356af75ecdSLinus Walleij 		.start = AB8500_INT_USB_CH_TH_PROT_F,
5366af75ecdSLinus Walleij 		.end = AB8500_INT_USB_CH_TH_PROT_F,
537e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
538e098adedSMattias Wallin 	},
539e098adedSMattias Wallin 	{
5406af75ecdSLinus Walleij 		.name = "MAIN_EXT_CH_NOT_OK",
5416af75ecdSLinus Walleij 		.start = AB8500_INT_MAIN_EXT_CH_NOT_OK,
5426af75ecdSLinus Walleij 		.end = AB8500_INT_MAIN_EXT_CH_NOT_OK,
5436af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
5446af75ecdSLinus Walleij 	},
5456af75ecdSLinus Walleij 	{
5466af75ecdSLinus Walleij 		.name = "MAIN_CH_TH_PROT_R",
5476af75ecdSLinus Walleij 		.start = AB8500_INT_MAIN_CH_TH_PROT_R,
5486af75ecdSLinus Walleij 		.end = AB8500_INT_MAIN_CH_TH_PROT_R,
5496af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
5506af75ecdSLinus Walleij 	},
5516af75ecdSLinus Walleij 	{
5526af75ecdSLinus Walleij 		.name = "MAIN_CH_TH_PROT_F",
5536af75ecdSLinus Walleij 		.start = AB8500_INT_MAIN_CH_TH_PROT_F,
5546af75ecdSLinus Walleij 		.end = AB8500_INT_MAIN_CH_TH_PROT_F,
5556af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
5566af75ecdSLinus Walleij 	},
5576af75ecdSLinus Walleij 	{
5586af75ecdSLinus Walleij 		.name = "USB_CHARGER_NOT_OKR",
5596af75ecdSLinus Walleij 		.start = AB8500_INT_USB_CHARGER_NOT_OK,
5606af75ecdSLinus Walleij 		.end = AB8500_INT_USB_CHARGER_NOT_OK,
5616af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
5626af75ecdSLinus Walleij 	},
5636af75ecdSLinus Walleij 	{
5646af75ecdSLinus Walleij 		.name = "USB_CHARGER_NOT_OKF",
5656af75ecdSLinus Walleij 		.start = AB8500_INT_USB_CHARGER_NOT_OKF,
5666af75ecdSLinus Walleij 		.end = AB8500_INT_USB_CHARGER_NOT_OKF,
5676af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
5686af75ecdSLinus Walleij 	},
5696af75ecdSLinus Walleij 	{
5706af75ecdSLinus Walleij 		.name = "CH_WD_EXP",
5716af75ecdSLinus Walleij 		.start = AB8500_INT_CH_WD_EXP,
5726af75ecdSLinus Walleij 		.end = AB8500_INT_CH_WD_EXP,
5736af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
5746af75ecdSLinus Walleij 	},
5756af75ecdSLinus Walleij };
5766af75ecdSLinus Walleij 
5776af75ecdSLinus Walleij static struct resource __devinitdata ab8500_btemp_resources[] = {
5786af75ecdSLinus Walleij 	{
5796af75ecdSLinus Walleij 		.name = "BAT_CTRL_INDB",
5806af75ecdSLinus Walleij 		.start = AB8500_INT_BAT_CTRL_INDB,
5816af75ecdSLinus Walleij 		.end = AB8500_INT_BAT_CTRL_INDB,
582e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
583e098adedSMattias Wallin 	},
584e098adedSMattias Wallin 	{
585e098adedSMattias Wallin 		.name = "BTEMP_LOW",
586e098adedSMattias Wallin 		.start = AB8500_INT_BTEMP_LOW,
587e098adedSMattias Wallin 		.end = AB8500_INT_BTEMP_LOW,
588e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
589e098adedSMattias Wallin 	},
590e098adedSMattias Wallin 	{
591e098adedSMattias Wallin 		.name = "BTEMP_HIGH",
592e098adedSMattias Wallin 		.start = AB8500_INT_BTEMP_HIGH,
593e098adedSMattias Wallin 		.end = AB8500_INT_BTEMP_HIGH,
594e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
595e098adedSMattias Wallin 	},
596e098adedSMattias Wallin 	{
5976af75ecdSLinus Walleij 		.name = "BTEMP_LOW_MEDIUM",
5986af75ecdSLinus Walleij 		.start = AB8500_INT_BTEMP_LOW_MEDIUM,
5996af75ecdSLinus Walleij 		.end = AB8500_INT_BTEMP_LOW_MEDIUM,
600e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
601e098adedSMattias Wallin 	},
602e098adedSMattias Wallin 	{
6036af75ecdSLinus Walleij 		.name = "BTEMP_MEDIUM_HIGH",
6046af75ecdSLinus Walleij 		.start = AB8500_INT_BTEMP_MEDIUM_HIGH,
6056af75ecdSLinus Walleij 		.end = AB8500_INT_BTEMP_MEDIUM_HIGH,
606e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
607e098adedSMattias Wallin 	},
608e098adedSMattias Wallin };
609e098adedSMattias Wallin 
6106af75ecdSLinus Walleij static struct resource __devinitdata ab8500_fg_resources[] = {
6116af75ecdSLinus Walleij 	{
6126af75ecdSLinus Walleij 		.name = "NCONV_ACCU",
6136af75ecdSLinus Walleij 		.start = AB8500_INT_CCN_CONV_ACC,
6146af75ecdSLinus Walleij 		.end = AB8500_INT_CCN_CONV_ACC,
6156af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
6166af75ecdSLinus Walleij 	},
6176af75ecdSLinus Walleij 	{
6186af75ecdSLinus Walleij 		.name = "BATT_OVV",
6196af75ecdSLinus Walleij 		.start = AB8500_INT_BATT_OVV,
6206af75ecdSLinus Walleij 		.end = AB8500_INT_BATT_OVV,
6216af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
6226af75ecdSLinus Walleij 	},
6236af75ecdSLinus Walleij 	{
6246af75ecdSLinus Walleij 		.name = "LOW_BAT_F",
6256af75ecdSLinus Walleij 		.start = AB8500_INT_LOW_BAT_F,
6266af75ecdSLinus Walleij 		.end = AB8500_INT_LOW_BAT_F,
6276af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
6286af75ecdSLinus Walleij 	},
6296af75ecdSLinus Walleij 	{
6306af75ecdSLinus Walleij 		.name = "LOW_BAT_R",
6316af75ecdSLinus Walleij 		.start = AB8500_INT_LOW_BAT_R,
6326af75ecdSLinus Walleij 		.end = AB8500_INT_LOW_BAT_R,
6336af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
6346af75ecdSLinus Walleij 	},
6356af75ecdSLinus Walleij 	{
6366af75ecdSLinus Walleij 		.name = "CC_INT_CALIB",
6376af75ecdSLinus Walleij 		.start = AB8500_INT_CC_INT_CALIB,
6386af75ecdSLinus Walleij 		.end = AB8500_INT_CC_INT_CALIB,
6396af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
6406af75ecdSLinus Walleij 	},
6416af75ecdSLinus Walleij };
6426af75ecdSLinus Walleij 
6436af75ecdSLinus Walleij static struct resource __devinitdata ab8500_chargalg_resources[] = {};
6446af75ecdSLinus Walleij 
645df720647SAxel Lin #ifdef CONFIG_DEBUG_FS
6465cef8df5SRobert Rosengren static struct resource __devinitdata ab8500_debug_resources[] = {
647e098adedSMattias Wallin 	{
648e098adedSMattias Wallin 		.name	= "IRQ_FIRST",
649e098adedSMattias Wallin 		.start	= AB8500_INT_MAIN_EXT_CH_NOT_OK,
650e098adedSMattias Wallin 		.end	= AB8500_INT_MAIN_EXT_CH_NOT_OK,
651e098adedSMattias Wallin 		.flags	= IORESOURCE_IRQ,
652e098adedSMattias Wallin 	},
653e098adedSMattias Wallin 	{
654e098adedSMattias Wallin 		.name	= "IRQ_LAST",
655e098adedSMattias Wallin 		.start	= AB8500_INT_USB_CHARGER_NOT_OKF,
656e098adedSMattias Wallin 		.end	= AB8500_INT_USB_CHARGER_NOT_OKF,
657e098adedSMattias Wallin 		.flags	= IORESOURCE_IRQ,
658e098adedSMattias Wallin 	},
659e098adedSMattias Wallin };
660df720647SAxel Lin #endif
661e098adedSMattias Wallin 
6625cef8df5SRobert Rosengren static struct resource __devinitdata ab8500_usb_resources[] = {
663e098adedSMattias Wallin 	{
664e098adedSMattias Wallin 		.name = "ID_WAKEUP_R",
665e098adedSMattias Wallin 		.start = AB8500_INT_ID_WAKEUP_R,
666e098adedSMattias Wallin 		.end = AB8500_INT_ID_WAKEUP_R,
667e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
668e098adedSMattias Wallin 	},
669e098adedSMattias Wallin 	{
670e098adedSMattias Wallin 		.name = "ID_WAKEUP_F",
671e098adedSMattias Wallin 		.start = AB8500_INT_ID_WAKEUP_F,
672e098adedSMattias Wallin 		.end = AB8500_INT_ID_WAKEUP_F,
673e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
674e098adedSMattias Wallin 	},
675e098adedSMattias Wallin 	{
676e098adedSMattias Wallin 		.name = "VBUS_DET_F",
677e098adedSMattias Wallin 		.start = AB8500_INT_VBUS_DET_F,
678e098adedSMattias Wallin 		.end = AB8500_INT_VBUS_DET_F,
679e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
680e098adedSMattias Wallin 	},
681e098adedSMattias Wallin 	{
682e098adedSMattias Wallin 		.name = "VBUS_DET_R",
683e098adedSMattias Wallin 		.start = AB8500_INT_VBUS_DET_R,
684e098adedSMattias Wallin 		.end = AB8500_INT_VBUS_DET_R,
685e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
686e098adedSMattias Wallin 	},
68792d50a41SMattias Wallin 	{
68892d50a41SMattias Wallin 		.name = "USB_LINK_STATUS",
68992d50a41SMattias Wallin 		.start = AB8500_INT_USB_LINK_STATUS,
69092d50a41SMattias Wallin 		.end = AB8500_INT_USB_LINK_STATUS,
69192d50a41SMattias Wallin 		.flags = IORESOURCE_IRQ,
69292d50a41SMattias Wallin 	},
6936af75ecdSLinus Walleij 	{
6946af75ecdSLinus Walleij 		.name = "USB_ADP_PROBE_PLUG",
6956af75ecdSLinus Walleij 		.start = AB8500_INT_ADP_PROBE_PLUG,
6966af75ecdSLinus Walleij 		.end = AB8500_INT_ADP_PROBE_PLUG,
6976af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
6986af75ecdSLinus Walleij 	},
6996af75ecdSLinus Walleij 	{
7006af75ecdSLinus Walleij 		.name = "USB_ADP_PROBE_UNPLUG",
7016af75ecdSLinus Walleij 		.start = AB8500_INT_ADP_PROBE_UNPLUG,
7026af75ecdSLinus Walleij 		.end = AB8500_INT_ADP_PROBE_UNPLUG,
7036af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
7046af75ecdSLinus Walleij 	},
705e098adedSMattias Wallin };
706e098adedSMattias Wallin 
7075cef8df5SRobert Rosengren static struct resource __devinitdata ab8500_temp_resources[] = {
708e098adedSMattias Wallin 	{
709e098adedSMattias Wallin 		.name  = "AB8500_TEMP_WARM",
710e098adedSMattias Wallin 		.start = AB8500_INT_TEMP_WARM,
711e098adedSMattias Wallin 		.end   = AB8500_INT_TEMP_WARM,
712e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
713e098adedSMattias Wallin 	},
714e098adedSMattias Wallin };
715e098adedSMattias Wallin 
7165cef8df5SRobert Rosengren static struct mfd_cell __devinitdata ab8500_devs[] = {
7175814fc35SMattias Wallin #ifdef CONFIG_DEBUG_FS
7185814fc35SMattias Wallin 	{
7195814fc35SMattias Wallin 		.name = "ab8500-debug",
720e098adedSMattias Wallin 		.num_resources = ARRAY_SIZE(ab8500_debug_resources),
721e098adedSMattias Wallin 		.resources = ab8500_debug_resources,
7225814fc35SMattias Wallin 	},
7235814fc35SMattias Wallin #endif
72462579266SRabin Vincent 	{
725e098adedSMattias Wallin 		.name = "ab8500-sysctrl",
726e098adedSMattias Wallin 	},
727e098adedSMattias Wallin 	{
728e098adedSMattias Wallin 		.name = "ab8500-regulator",
729e098adedSMattias Wallin 	},
730e098adedSMattias Wallin 	{
7310cb3fcd7SBibek Basu 		.name = "ab8500-gpio",
7320cb3fcd7SBibek Basu 		.num_resources = ARRAY_SIZE(ab8500_gpio_resources),
7330cb3fcd7SBibek Basu 		.resources = ab8500_gpio_resources,
7340cb3fcd7SBibek Basu 	},
7350cb3fcd7SBibek Basu 	{
73662579266SRabin Vincent 		.name = "ab8500-gpadc",
73762579266SRabin Vincent 		.num_resources = ARRAY_SIZE(ab8500_gpadc_resources),
73862579266SRabin Vincent 		.resources = ab8500_gpadc_resources,
73962579266SRabin Vincent 	},
74062579266SRabin Vincent 	{
74162579266SRabin Vincent 		.name = "ab8500-rtc",
74262579266SRabin Vincent 		.num_resources = ARRAY_SIZE(ab8500_rtc_resources),
74362579266SRabin Vincent 		.resources = ab8500_rtc_resources,
74462579266SRabin Vincent 	},
745f0f05b1cSArun Murthy 	{
7466af75ecdSLinus Walleij 		.name = "ab8500-charger",
7476af75ecdSLinus Walleij 		.num_resources = ARRAY_SIZE(ab8500_charger_resources),
7486af75ecdSLinus Walleij 		.resources = ab8500_charger_resources,
749e098adedSMattias Wallin 	},
7506af75ecdSLinus Walleij 	{
7516af75ecdSLinus Walleij 		.name = "ab8500-btemp",
7526af75ecdSLinus Walleij 		.num_resources = ARRAY_SIZE(ab8500_btemp_resources),
7536af75ecdSLinus Walleij 		.resources = ab8500_btemp_resources,
7546af75ecdSLinus Walleij 	},
7556af75ecdSLinus Walleij 	{
7566af75ecdSLinus Walleij 		.name = "ab8500-fg",
7576af75ecdSLinus Walleij 		.num_resources = ARRAY_SIZE(ab8500_fg_resources),
7586af75ecdSLinus Walleij 		.resources = ab8500_fg_resources,
7596af75ecdSLinus Walleij 	},
7606af75ecdSLinus Walleij 	{
7616af75ecdSLinus Walleij 		.name = "ab8500-chargalg",
7626af75ecdSLinus Walleij 		.num_resources = ARRAY_SIZE(ab8500_chargalg_resources),
7636af75ecdSLinus Walleij 		.resources = ab8500_chargalg_resources,
7646af75ecdSLinus Walleij 	},
7656af75ecdSLinus Walleij 	{
7666af75ecdSLinus Walleij 		.name = "ab8500-acc-det",
7676af75ecdSLinus Walleij 		.num_resources = ARRAY_SIZE(ab8500_av_acc_detect_resources),
7686af75ecdSLinus Walleij 		.resources = ab8500_av_acc_detect_resources,
7696af75ecdSLinus Walleij 	},
7706af75ecdSLinus Walleij 	{
7716af75ecdSLinus Walleij 		.name = "ab8500-codec",
7726af75ecdSLinus Walleij 	},
773e098adedSMattias Wallin 	{
774e098adedSMattias Wallin 		.name = "ab8500-usb",
775e098adedSMattias Wallin 		.num_resources = ARRAY_SIZE(ab8500_usb_resources),
776e098adedSMattias Wallin 		.resources = ab8500_usb_resources,
777e098adedSMattias Wallin 	},
778e098adedSMattias Wallin 	{
779e098adedSMattias Wallin 		.name = "ab8500-poweron-key",
780e098adedSMattias Wallin 		.num_resources = ARRAY_SIZE(ab8500_poweronkey_db_resources),
781e098adedSMattias Wallin 		.resources = ab8500_poweronkey_db_resources,
782e098adedSMattias Wallin 	},
783e098adedSMattias Wallin 	{
784f0f05b1cSArun Murthy 		.name = "ab8500-pwm",
785f0f05b1cSArun Murthy 		.id = 1,
786f0f05b1cSArun Murthy 	},
787f0f05b1cSArun Murthy 	{
788f0f05b1cSArun Murthy 		.name = "ab8500-pwm",
789f0f05b1cSArun Murthy 		.id = 2,
790f0f05b1cSArun Murthy 	},
791f0f05b1cSArun Murthy 	{
792f0f05b1cSArun Murthy 		.name = "ab8500-pwm",
793f0f05b1cSArun Murthy 		.id = 3,
794f0f05b1cSArun Murthy 	},
795e098adedSMattias Wallin 	{ .name = "ab8500-leds", },
79677686517SSundar R Iyer 	{
797e098adedSMattias Wallin 		.name = "ab8500-denc",
798e098adedSMattias Wallin 	},
799e098adedSMattias Wallin 	{
800e098adedSMattias Wallin 		.name = "ab8500-temp",
801e098adedSMattias Wallin 		.num_resources = ARRAY_SIZE(ab8500_temp_resources),
802e098adedSMattias Wallin 		.resources = ab8500_temp_resources,
80377686517SSundar R Iyer 	},
80462579266SRabin Vincent };
80562579266SRabin Vincent 
806cca69b67SMattias Wallin static ssize_t show_chip_id(struct device *dev,
807cca69b67SMattias Wallin 				struct device_attribute *attr, char *buf)
808cca69b67SMattias Wallin {
809cca69b67SMattias Wallin 	struct ab8500 *ab8500;
810cca69b67SMattias Wallin 
811cca69b67SMattias Wallin 	ab8500 = dev_get_drvdata(dev);
812cca69b67SMattias Wallin 	return sprintf(buf, "%#x\n", ab8500 ? ab8500->chip_id : -EINVAL);
813cca69b67SMattias Wallin }
814cca69b67SMattias Wallin 
815e5c238c3SMattias Wallin /*
816e5c238c3SMattias Wallin  * ab8500 has switched off due to (SWITCH_OFF_STATUS):
817e5c238c3SMattias Wallin  * 0x01 Swoff bit programming
818e5c238c3SMattias Wallin  * 0x02 Thermal protection activation
819e5c238c3SMattias Wallin  * 0x04 Vbat lower then BattOk falling threshold
820e5c238c3SMattias Wallin  * 0x08 Watchdog expired
821e5c238c3SMattias Wallin  * 0x10 Non presence of 32kHz clock
822e5c238c3SMattias Wallin  * 0x20 Battery level lower than power on reset threshold
823e5c238c3SMattias Wallin  * 0x40 Power on key 1 pressed longer than 10 seconds
824e5c238c3SMattias Wallin  * 0x80 DB8500 thermal shutdown
825e5c238c3SMattias Wallin  */
826e5c238c3SMattias Wallin static ssize_t show_switch_off_status(struct device *dev,
827e5c238c3SMattias Wallin 				struct device_attribute *attr, char *buf)
828e5c238c3SMattias Wallin {
829e5c238c3SMattias Wallin 	int ret;
830e5c238c3SMattias Wallin 	u8 value;
831e5c238c3SMattias Wallin 	struct ab8500 *ab8500;
832e5c238c3SMattias Wallin 
833e5c238c3SMattias Wallin 	ab8500 = dev_get_drvdata(dev);
834e5c238c3SMattias Wallin 	ret = get_register_interruptible(ab8500, AB8500_RTC,
835e5c238c3SMattias Wallin 		AB8500_SWITCH_OFF_STATUS, &value);
836e5c238c3SMattias Wallin 	if (ret < 0)
837e5c238c3SMattias Wallin 		return ret;
838e5c238c3SMattias Wallin 	return sprintf(buf, "%#x\n", value);
839e5c238c3SMattias Wallin }
840e5c238c3SMattias Wallin 
841b4a31037SAndrew Lynn /*
842b4a31037SAndrew Lynn  * ab8500 has turned on due to (TURN_ON_STATUS):
843b4a31037SAndrew Lynn  * 0x01 PORnVbat
844b4a31037SAndrew Lynn  * 0x02 PonKey1dbF
845b4a31037SAndrew Lynn  * 0x04 PonKey2dbF
846b4a31037SAndrew Lynn  * 0x08 RTCAlarm
847b4a31037SAndrew Lynn  * 0x10 MainChDet
848b4a31037SAndrew Lynn  * 0x20 VbusDet
849b4a31037SAndrew Lynn  * 0x40 UsbIDDetect
850b4a31037SAndrew Lynn  * 0x80 Reserved
851b4a31037SAndrew Lynn  */
852b4a31037SAndrew Lynn static ssize_t show_turn_on_status(struct device *dev,
853b4a31037SAndrew Lynn 				struct device_attribute *attr, char *buf)
854b4a31037SAndrew Lynn {
855b4a31037SAndrew Lynn 	int ret;
856b4a31037SAndrew Lynn 	u8 value;
857b4a31037SAndrew Lynn 	struct ab8500 *ab8500;
858b4a31037SAndrew Lynn 
859b4a31037SAndrew Lynn 	ab8500 = dev_get_drvdata(dev);
860b4a31037SAndrew Lynn 	ret = get_register_interruptible(ab8500, AB8500_SYS_CTRL1_BLOCK,
861b4a31037SAndrew Lynn 		AB8500_TURN_ON_STATUS, &value);
862b4a31037SAndrew Lynn 	if (ret < 0)
863b4a31037SAndrew Lynn 		return ret;
864b4a31037SAndrew Lynn 	return sprintf(buf, "%#x\n", value);
865b4a31037SAndrew Lynn }
866b4a31037SAndrew Lynn 
867cca69b67SMattias Wallin static DEVICE_ATTR(chip_id, S_IRUGO, show_chip_id, NULL);
868e5c238c3SMattias Wallin static DEVICE_ATTR(switch_off_status, S_IRUGO, show_switch_off_status, NULL);
869b4a31037SAndrew Lynn static DEVICE_ATTR(turn_on_status, S_IRUGO, show_turn_on_status, NULL);
870cca69b67SMattias Wallin 
871cca69b67SMattias Wallin static struct attribute *ab8500_sysfs_entries[] = {
872cca69b67SMattias Wallin 	&dev_attr_chip_id.attr,
873e5c238c3SMattias Wallin 	&dev_attr_switch_off_status.attr,
874b4a31037SAndrew Lynn 	&dev_attr_turn_on_status.attr,
875cca69b67SMattias Wallin 	NULL,
876cca69b67SMattias Wallin };
877cca69b67SMattias Wallin 
878cca69b67SMattias Wallin static struct attribute_group ab8500_attr_group = {
879cca69b67SMattias Wallin 	.attrs	= ab8500_sysfs_entries,
880cca69b67SMattias Wallin };
881cca69b67SMattias Wallin 
8820f620837SLinus Walleij int __devinit ab8500_init(struct ab8500 *ab8500, enum ab8500_version version)
88362579266SRabin Vincent {
88462579266SRabin Vincent 	struct ab8500_platform_data *plat = dev_get_platdata(ab8500->dev);
88562579266SRabin Vincent 	int ret;
88662579266SRabin Vincent 	int i;
88747c16975SMattias Wallin 	u8 value;
88862579266SRabin Vincent 
88962579266SRabin Vincent 	if (plat)
89062579266SRabin Vincent 		ab8500->irq_base = plat->irq_base;
89162579266SRabin Vincent 
89262579266SRabin Vincent 	mutex_init(&ab8500->lock);
89362579266SRabin Vincent 	mutex_init(&ab8500->irq_lock);
89462579266SRabin Vincent 
8950f620837SLinus Walleij 	if (version != AB8500_VERSION_UNDEFINED)
8960f620837SLinus Walleij 		ab8500->version = version;
8970f620837SLinus Walleij 	else {
8980f620837SLinus Walleij 		ret = get_register_interruptible(ab8500, AB8500_MISC,
8990f620837SLinus Walleij 			AB8500_IC_NAME_REG, &value);
9000f620837SLinus Walleij 		if (ret < 0)
9010f620837SLinus Walleij 			return ret;
9020f620837SLinus Walleij 
9030f620837SLinus Walleij 		ab8500->version = value;
9040f620837SLinus Walleij 	}
9050f620837SLinus Walleij 
90647c16975SMattias Wallin 	ret = get_register_interruptible(ab8500, AB8500_MISC,
90747c16975SMattias Wallin 		AB8500_REV_REG, &value);
90862579266SRabin Vincent 	if (ret < 0)
90962579266SRabin Vincent 		return ret;
91062579266SRabin Vincent 
91147c16975SMattias Wallin 	ab8500->chip_id = value;
91262579266SRabin Vincent 
9130f620837SLinus Walleij 	dev_info(ab8500->dev, "detected chip, %s rev. %1x.%1x\n",
9140f620837SLinus Walleij 			ab8500_version_str[ab8500->version],
9150f620837SLinus Walleij 			ab8500->chip_id >> 4,
9160f620837SLinus Walleij 			ab8500->chip_id & 0x0F);
9170f620837SLinus Walleij 
918*2ced445eSLinus Walleij 	ab8500->mask_size = AB8500_NUM_IRQ_REGS;
919*2ced445eSLinus Walleij 	ab8500->irq_reg_offset = ab8500_irq_regoffset;
920*2ced445eSLinus Walleij 	ab8500->mask = kzalloc(ab8500->mask_size, GFP_KERNEL);
921*2ced445eSLinus Walleij 	if (!ab8500->mask)
922*2ced445eSLinus Walleij 		return -ENOMEM;
923*2ced445eSLinus Walleij 	ab8500->oldmask = kzalloc(ab8500->mask_size, GFP_KERNEL);
924*2ced445eSLinus Walleij 	if (!ab8500->oldmask) {
925*2ced445eSLinus Walleij 		ret = -ENOMEM;
926*2ced445eSLinus Walleij 		goto out_freemask;
927*2ced445eSLinus Walleij 	}
928e5c238c3SMattias Wallin 	/*
929e5c238c3SMattias Wallin 	 * ab8500 has switched off due to (SWITCH_OFF_STATUS):
930e5c238c3SMattias Wallin 	 * 0x01 Swoff bit programming
931e5c238c3SMattias Wallin 	 * 0x02 Thermal protection activation
932e5c238c3SMattias Wallin 	 * 0x04 Vbat lower then BattOk falling threshold
933e5c238c3SMattias Wallin 	 * 0x08 Watchdog expired
934e5c238c3SMattias Wallin 	 * 0x10 Non presence of 32kHz clock
935e5c238c3SMattias Wallin 	 * 0x20 Battery level lower than power on reset threshold
936e5c238c3SMattias Wallin 	 * 0x40 Power on key 1 pressed longer than 10 seconds
937e5c238c3SMattias Wallin 	 * 0x80 DB8500 thermal shutdown
938e5c238c3SMattias Wallin 	 */
939e5c238c3SMattias Wallin 
940e5c238c3SMattias Wallin 	ret = get_register_interruptible(ab8500, AB8500_RTC,
941e5c238c3SMattias Wallin 		AB8500_SWITCH_OFF_STATUS, &value);
942e5c238c3SMattias Wallin 	if (ret < 0)
943e5c238c3SMattias Wallin 		return ret;
944e5c238c3SMattias Wallin 	dev_info(ab8500->dev, "switch off status: %#x", value);
945e5c238c3SMattias Wallin 
94662579266SRabin Vincent 	if (plat && plat->init)
94762579266SRabin Vincent 		plat->init(ab8500);
94862579266SRabin Vincent 
94962579266SRabin Vincent 	/* Clear and mask all interrupts */
950*2ced445eSLinus Walleij 	for (i = 0; i < ab8500->mask_size; i++) {
9510f620837SLinus Walleij 		/*
9520f620837SLinus Walleij 		 * Interrupt register 12 doesn't exist prior to AB8500 version
9530f620837SLinus Walleij 		 * 2.0
9540f620837SLinus Walleij 		 */
9550f620837SLinus Walleij 		if (ab8500->irq_reg_offset[i] == 11 &&
9560f620837SLinus Walleij 				is_ab8500_1p1_or_earlier(ab8500))
95792d50a41SMattias Wallin 			continue;
95862579266SRabin Vincent 
95947c16975SMattias Wallin 		get_register_interruptible(ab8500, AB8500_INTERRUPT,
960*2ced445eSLinus Walleij 			AB8500_IT_LATCH1_REG + ab8500->irq_reg_offset[i],
96192d50a41SMattias Wallin 			&value);
96247c16975SMattias Wallin 		set_register_interruptible(ab8500, AB8500_INTERRUPT,
963*2ced445eSLinus Walleij 			AB8500_IT_MASK1_REG + ab8500->irq_reg_offset[i], 0xff);
96462579266SRabin Vincent 	}
96562579266SRabin Vincent 
96647c16975SMattias Wallin 	ret = abx500_register_ops(ab8500->dev, &ab8500_ops);
96747c16975SMattias Wallin 	if (ret)
968*2ced445eSLinus Walleij 		goto out_freeoldmask;
96947c16975SMattias Wallin 
970*2ced445eSLinus Walleij 	for (i = 0; i < ab8500->mask_size; i++)
97162579266SRabin Vincent 		ab8500->mask[i] = ab8500->oldmask[i] = 0xff;
97262579266SRabin Vincent 
97362579266SRabin Vincent 	if (ab8500->irq_base) {
97462579266SRabin Vincent 		ret = ab8500_irq_init(ab8500);
97562579266SRabin Vincent 		if (ret)
976*2ced445eSLinus Walleij 			goto out_freeoldmask;
97762579266SRabin Vincent 
97862579266SRabin Vincent 		ret = request_threaded_irq(ab8500->irq, NULL, ab8500_irq,
9794f079985SMattias Wallin 					   IRQF_ONESHOT | IRQF_NO_SUSPEND,
9804f079985SMattias Wallin 					   "ab8500", ab8500);
98162579266SRabin Vincent 		if (ret)
98262579266SRabin Vincent 			goto out_removeirq;
98362579266SRabin Vincent 	}
98462579266SRabin Vincent 
985549931f9SSundar R Iyer 	ret = mfd_add_devices(ab8500->dev, 0, ab8500_devs,
98662579266SRabin Vincent 			      ARRAY_SIZE(ab8500_devs), NULL,
98762579266SRabin Vincent 			      ab8500->irq_base);
98862579266SRabin Vincent 	if (ret)
98962579266SRabin Vincent 		goto out_freeirq;
99062579266SRabin Vincent 
991cca69b67SMattias Wallin 	ret = sysfs_create_group(&ab8500->dev->kobj, &ab8500_attr_group);
992cca69b67SMattias Wallin 	if (ret)
993cca69b67SMattias Wallin 		dev_err(ab8500->dev, "error creating sysfs entries\n");
994cca69b67SMattias Wallin 
99562579266SRabin Vincent 	return ret;
99662579266SRabin Vincent 
99762579266SRabin Vincent out_freeirq:
9986d95b7fdSLinus Walleij 	if (ab8500->irq_base)
99962579266SRabin Vincent 		free_irq(ab8500->irq, ab8500);
100062579266SRabin Vincent out_removeirq:
10016d95b7fdSLinus Walleij 	if (ab8500->irq_base)
100262579266SRabin Vincent 		ab8500_irq_remove(ab8500);
1003*2ced445eSLinus Walleij out_freeoldmask:
1004*2ced445eSLinus Walleij 	kfree(ab8500->oldmask);
1005*2ced445eSLinus Walleij out_freemask:
1006*2ced445eSLinus Walleij 	kfree(ab8500->mask);
10076d95b7fdSLinus Walleij 
100862579266SRabin Vincent 	return ret;
100962579266SRabin Vincent }
101062579266SRabin Vincent 
101162579266SRabin Vincent int __devexit ab8500_exit(struct ab8500 *ab8500)
101262579266SRabin Vincent {
1013cca69b67SMattias Wallin 	sysfs_remove_group(&ab8500->dev->kobj, &ab8500_attr_group);
101462579266SRabin Vincent 	mfd_remove_devices(ab8500->dev);
101562579266SRabin Vincent 	if (ab8500->irq_base) {
101662579266SRabin Vincent 		free_irq(ab8500->irq, ab8500);
101762579266SRabin Vincent 		ab8500_irq_remove(ab8500);
101862579266SRabin Vincent 	}
1019*2ced445eSLinus Walleij 	kfree(ab8500->oldmask);
1020*2ced445eSLinus Walleij 	kfree(ab8500->mask);
102162579266SRabin Vincent 
102262579266SRabin Vincent 	return 0;
102362579266SRabin Vincent }
102462579266SRabin Vincent 
1025adceed62SMattias Wallin MODULE_AUTHOR("Mattias Wallin, Srinidhi Kasagar, Rabin Vincent");
102662579266SRabin Vincent MODULE_DESCRIPTION("AB8500 MFD core");
102762579266SRabin Vincent MODULE_LICENSE("GPL v2");
1028