xref: /openbmc/linux/drivers/mfd/ab8500-core.c (revision abee26cdb685fa47d3d17ec9cf39f6149ce67083)
162579266SRabin Vincent /*
262579266SRabin Vincent  * Copyright (C) ST-Ericsson SA 2010
362579266SRabin Vincent  *
462579266SRabin Vincent  * License Terms: GNU General Public License v2
562579266SRabin Vincent  * Author: Srinidhi Kasagar <srinidhi.kasagar@stericsson.com>
662579266SRabin Vincent  * Author: Rabin Vincent <rabin.vincent@stericsson.com>
7adceed62SMattias Wallin  * Author: Mattias Wallin <mattias.wallin@stericsson.com>
862579266SRabin Vincent  */
962579266SRabin Vincent 
1062579266SRabin Vincent #include <linux/kernel.h>
1162579266SRabin Vincent #include <linux/slab.h>
1262579266SRabin Vincent #include <linux/init.h>
1362579266SRabin Vincent #include <linux/irq.h>
1406e589efSLee Jones #include <linux/irqdomain.h>
1562579266SRabin Vincent #include <linux/delay.h>
1662579266SRabin Vincent #include <linux/interrupt.h>
1762579266SRabin Vincent #include <linux/module.h>
1862579266SRabin Vincent #include <linux/platform_device.h>
1962579266SRabin Vincent #include <linux/mfd/core.h>
2047c16975SMattias Wallin #include <linux/mfd/abx500.h>
21ee66e653SLinus Walleij #include <linux/mfd/abx500/ab8500.h>
2200441b5eSLee Jones #include <linux/mfd/abx500/ab8500-bm.h>
23d28f1db8SLee Jones #include <linux/mfd/dbx500-prcmu.h>
24549931f9SSundar R Iyer #include <linux/regulator/ab8500.h>
256bc4a568SLee Jones #include <linux/of.h>
266bc4a568SLee Jones #include <linux/of_device.h>
2762579266SRabin Vincent 
2862579266SRabin Vincent /*
2962579266SRabin Vincent  * Interrupt register offsets
3062579266SRabin Vincent  * Bank : 0x0E
3162579266SRabin Vincent  */
3247c16975SMattias Wallin #define AB8500_IT_SOURCE1_REG		0x00
3347c16975SMattias Wallin #define AB8500_IT_SOURCE2_REG		0x01
3447c16975SMattias Wallin #define AB8500_IT_SOURCE3_REG		0x02
3547c16975SMattias Wallin #define AB8500_IT_SOURCE4_REG		0x03
3647c16975SMattias Wallin #define AB8500_IT_SOURCE5_REG		0x04
3747c16975SMattias Wallin #define AB8500_IT_SOURCE6_REG		0x05
3847c16975SMattias Wallin #define AB8500_IT_SOURCE7_REG		0x06
3947c16975SMattias Wallin #define AB8500_IT_SOURCE8_REG		0x07
40d6255529SLinus Walleij #define AB9540_IT_SOURCE13_REG		0x0C
4147c16975SMattias Wallin #define AB8500_IT_SOURCE19_REG		0x12
4247c16975SMattias Wallin #define AB8500_IT_SOURCE20_REG		0x13
4347c16975SMattias Wallin #define AB8500_IT_SOURCE21_REG		0x14
4447c16975SMattias Wallin #define AB8500_IT_SOURCE22_REG		0x15
4547c16975SMattias Wallin #define AB8500_IT_SOURCE23_REG		0x16
4647c16975SMattias Wallin #define AB8500_IT_SOURCE24_REG		0x17
4762579266SRabin Vincent 
4862579266SRabin Vincent /*
4962579266SRabin Vincent  * latch registers
5062579266SRabin Vincent  */
5147c16975SMattias Wallin #define AB8500_IT_LATCH1_REG		0x20
5247c16975SMattias Wallin #define AB8500_IT_LATCH2_REG		0x21
5347c16975SMattias Wallin #define AB8500_IT_LATCH3_REG		0x22
5447c16975SMattias Wallin #define AB8500_IT_LATCH4_REG		0x23
5547c16975SMattias Wallin #define AB8500_IT_LATCH5_REG		0x24
5647c16975SMattias Wallin #define AB8500_IT_LATCH6_REG		0x25
5747c16975SMattias Wallin #define AB8500_IT_LATCH7_REG		0x26
5847c16975SMattias Wallin #define AB8500_IT_LATCH8_REG		0x27
5947c16975SMattias Wallin #define AB8500_IT_LATCH9_REG		0x28
6047c16975SMattias Wallin #define AB8500_IT_LATCH10_REG		0x29
6192d50a41SMattias Wallin #define AB8500_IT_LATCH12_REG		0x2B
62d6255529SLinus Walleij #define AB9540_IT_LATCH13_REG		0x2C
6347c16975SMattias Wallin #define AB8500_IT_LATCH19_REG		0x32
6447c16975SMattias Wallin #define AB8500_IT_LATCH20_REG		0x33
6547c16975SMattias Wallin #define AB8500_IT_LATCH21_REG		0x34
6647c16975SMattias Wallin #define AB8500_IT_LATCH22_REG		0x35
6747c16975SMattias Wallin #define AB8500_IT_LATCH23_REG		0x36
6847c16975SMattias Wallin #define AB8500_IT_LATCH24_REG		0x37
6962579266SRabin Vincent 
7062579266SRabin Vincent /*
7162579266SRabin Vincent  * mask registers
7262579266SRabin Vincent  */
7362579266SRabin Vincent 
7447c16975SMattias Wallin #define AB8500_IT_MASK1_REG		0x40
7547c16975SMattias Wallin #define AB8500_IT_MASK2_REG		0x41
7647c16975SMattias Wallin #define AB8500_IT_MASK3_REG		0x42
7747c16975SMattias Wallin #define AB8500_IT_MASK4_REG		0x43
7847c16975SMattias Wallin #define AB8500_IT_MASK5_REG		0x44
7947c16975SMattias Wallin #define AB8500_IT_MASK6_REG		0x45
8047c16975SMattias Wallin #define AB8500_IT_MASK7_REG		0x46
8147c16975SMattias Wallin #define AB8500_IT_MASK8_REG		0x47
8247c16975SMattias Wallin #define AB8500_IT_MASK9_REG		0x48
8347c16975SMattias Wallin #define AB8500_IT_MASK10_REG		0x49
8447c16975SMattias Wallin #define AB8500_IT_MASK11_REG		0x4A
8547c16975SMattias Wallin #define AB8500_IT_MASK12_REG		0x4B
8647c16975SMattias Wallin #define AB8500_IT_MASK13_REG		0x4C
8747c16975SMattias Wallin #define AB8500_IT_MASK14_REG		0x4D
8847c16975SMattias Wallin #define AB8500_IT_MASK15_REG		0x4E
8947c16975SMattias Wallin #define AB8500_IT_MASK16_REG		0x4F
9047c16975SMattias Wallin #define AB8500_IT_MASK17_REG		0x50
9147c16975SMattias Wallin #define AB8500_IT_MASK18_REG		0x51
9247c16975SMattias Wallin #define AB8500_IT_MASK19_REG		0x52
9347c16975SMattias Wallin #define AB8500_IT_MASK20_REG		0x53
9447c16975SMattias Wallin #define AB8500_IT_MASK21_REG		0x54
9547c16975SMattias Wallin #define AB8500_IT_MASK22_REG		0x55
9647c16975SMattias Wallin #define AB8500_IT_MASK23_REG		0x56
9747c16975SMattias Wallin #define AB8500_IT_MASK24_REG		0x57
98a29264b6SLee Jones #define AB8500_IT_MASK25_REG		0x58
9962579266SRabin Vincent 
1007ccfe9b1SMichel JAOUEN /*
1017ccfe9b1SMichel JAOUEN  * latch hierarchy registers
1027ccfe9b1SMichel JAOUEN  */
1037ccfe9b1SMichel JAOUEN #define AB8500_IT_LATCHHIER1_REG	0x60
1047ccfe9b1SMichel JAOUEN #define AB8500_IT_LATCHHIER2_REG	0x61
1057ccfe9b1SMichel JAOUEN #define AB8500_IT_LATCHHIER3_REG	0x62
1063e1a498fSLee Jones #define AB8540_IT_LATCHHIER4_REG	0x63
1077ccfe9b1SMichel JAOUEN 
1087ccfe9b1SMichel JAOUEN #define AB8500_IT_LATCHHIER_NUM		3
1093e1a498fSLee Jones #define AB8540_IT_LATCHHIER_NUM		4
1107ccfe9b1SMichel JAOUEN 
11147c16975SMattias Wallin #define AB8500_REV_REG			0x80
1120f620837SLinus Walleij #define AB8500_IC_NAME_REG		0x82
113e5c238c3SMattias Wallin #define AB8500_SWITCH_OFF_STATUS	0x00
11462579266SRabin Vincent 
115b4a31037SAndrew Lynn #define AB8500_TURN_ON_STATUS		0x00
116b4a31037SAndrew Lynn 
117f04a9d8aSRajkumar Kasirajan #define AB8500_CH_USBCH_STAT1_REG	0x02
118f04a9d8aSRajkumar Kasirajan #define VBUS_DET_DBNC100		0x02
119f04a9d8aSRajkumar Kasirajan #define VBUS_DET_DBNC1			0x01
120f04a9d8aSRajkumar Kasirajan 
121f04a9d8aSRajkumar Kasirajan static DEFINE_SPINLOCK(on_stat_lock);
122f04a9d8aSRajkumar Kasirajan static u8 turn_on_stat_mask = 0xFF;
123f04a9d8aSRajkumar Kasirajan static u8 turn_on_stat_set;
1246ef9418cSRickard Andersson static bool no_bm; /* No battery management */
1256ef9418cSRickard Andersson module_param(no_bm, bool, S_IRUGO);
1266ef9418cSRickard Andersson 
127d6255529SLinus Walleij #define AB9540_MODEM_CTRL2_REG			0x23
128d6255529SLinus Walleij #define AB9540_MODEM_CTRL2_SWDBBRSTN_BIT	BIT(2)
129d6255529SLinus Walleij 
13062579266SRabin Vincent /*
13162579266SRabin Vincent  * Map interrupt numbers to the LATCH and MASK register offsets, Interrupt
1322ced445eSLinus Walleij  * numbers are indexed into this array with (num / 8). The interupts are
1332ced445eSLinus Walleij  * defined in linux/mfd/ab8500.h
13462579266SRabin Vincent  *
13562579266SRabin Vincent  * This is one off from the register names, i.e. AB8500_IT_MASK1_REG is at
13662579266SRabin Vincent  * offset 0.
13762579266SRabin Vincent  */
1382ced445eSLinus Walleij /* AB8500 support */
13962579266SRabin Vincent static const int ab8500_irq_regoffset[AB8500_NUM_IRQ_REGS] = {
14092d50a41SMattias Wallin 	0, 1, 2, 3, 4, 6, 7, 8, 9, 11, 18, 19, 20, 21,
14162579266SRabin Vincent };
14262579266SRabin Vincent 
143a29264b6SLee Jones /* AB9540 / AB8505 support */
144d6255529SLinus Walleij static const int ab9540_irq_regoffset[AB9540_NUM_IRQ_REGS] = {
145a29264b6SLee Jones 	0, 1, 2, 3, 4, 6, 7, 8, 9, 11, 18, 19, 20, 21, 12, 13, 24, 5, 22, 23
146d6255529SLinus Walleij };
147d6255529SLinus Walleij 
1483e1a498fSLee Jones /* AB8540 support */
1493e1a498fSLee Jones static const int ab8540_irq_regoffset[AB8540_NUM_IRQ_REGS] = {
1503e1a498fSLee Jones 	0, 1, 2, 3, 4, -1, -1, -1, -1, 11, 18, 19, 20, 21, 12, 13, 24, 5, 22, 23,
1513e1a498fSLee Jones 	25, 26, 27, 28, 29, 30, 31,
1523e1a498fSLee Jones };
1533e1a498fSLee Jones 
1540f620837SLinus Walleij static const char ab8500_version_str[][7] = {
1550f620837SLinus Walleij 	[AB8500_VERSION_AB8500] = "AB8500",
1560f620837SLinus Walleij 	[AB8500_VERSION_AB8505] = "AB8505",
1570f620837SLinus Walleij 	[AB8500_VERSION_AB9540] = "AB9540",
1580f620837SLinus Walleij 	[AB8500_VERSION_AB8540] = "AB8540",
1590f620837SLinus Walleij };
1600f620837SLinus Walleij 
161822672a7SLee Jones static int ab8500_prcmu_write(struct ab8500 *ab8500, u16 addr, u8 data)
162d28f1db8SLee Jones {
163d28f1db8SLee Jones 	int ret;
164d28f1db8SLee Jones 
165d28f1db8SLee Jones 	ret = prcmu_abb_write((u8)(addr >> 8), (u8)(addr & 0xFF), &data, 1);
166d28f1db8SLee Jones 	if (ret < 0)
167d28f1db8SLee Jones 		dev_err(ab8500->dev, "prcmu i2c error %d\n", ret);
168d28f1db8SLee Jones 	return ret;
169d28f1db8SLee Jones }
170d28f1db8SLee Jones 
171822672a7SLee Jones static int ab8500_prcmu_write_masked(struct ab8500 *ab8500, u16 addr, u8 mask,
172d28f1db8SLee Jones 	u8 data)
173d28f1db8SLee Jones {
174d28f1db8SLee Jones 	int ret;
175d28f1db8SLee Jones 
176d28f1db8SLee Jones 	ret = prcmu_abb_write_masked((u8)(addr >> 8), (u8)(addr & 0xFF), &data,
177d28f1db8SLee Jones 		&mask, 1);
178d28f1db8SLee Jones 	if (ret < 0)
179d28f1db8SLee Jones 		dev_err(ab8500->dev, "prcmu i2c error %d\n", ret);
180d28f1db8SLee Jones 	return ret;
181d28f1db8SLee Jones }
182d28f1db8SLee Jones 
183822672a7SLee Jones static int ab8500_prcmu_read(struct ab8500 *ab8500, u16 addr)
184d28f1db8SLee Jones {
185d28f1db8SLee Jones 	int ret;
186d28f1db8SLee Jones 	u8 data;
187d28f1db8SLee Jones 
188d28f1db8SLee Jones 	ret = prcmu_abb_read((u8)(addr >> 8), (u8)(addr & 0xFF), &data, 1);
189d28f1db8SLee Jones 	if (ret < 0) {
190d28f1db8SLee Jones 		dev_err(ab8500->dev, "prcmu i2c error %d\n", ret);
191d28f1db8SLee Jones 		return ret;
192d28f1db8SLee Jones 	}
193d28f1db8SLee Jones 	return (int)data;
194d28f1db8SLee Jones }
195d28f1db8SLee Jones 
19647c16975SMattias Wallin static int ab8500_get_chip_id(struct device *dev)
19747c16975SMattias Wallin {
1986bce7bf1SMattias Wallin 	struct ab8500 *ab8500;
1996bce7bf1SMattias Wallin 
2006bce7bf1SMattias Wallin 	if (!dev)
2016bce7bf1SMattias Wallin 		return -EINVAL;
2026bce7bf1SMattias Wallin 	ab8500 = dev_get_drvdata(dev->parent);
2036bce7bf1SMattias Wallin 	return ab8500 ? (int)ab8500->chip_id : -EINVAL;
20447c16975SMattias Wallin }
20547c16975SMattias Wallin 
20647c16975SMattias Wallin static int set_register_interruptible(struct ab8500 *ab8500, u8 bank,
20747c16975SMattias Wallin 	u8 reg, u8 data)
20862579266SRabin Vincent {
20962579266SRabin Vincent 	int ret;
21047c16975SMattias Wallin 	/*
21147c16975SMattias Wallin 	 * Put the u8 bank and u8 register together into a an u16.
21247c16975SMattias Wallin 	 * The bank on higher 8 bits and register in lower 8 bits.
21347c16975SMattias Wallin 	 * */
21447c16975SMattias Wallin 	u16 addr = ((u16)bank) << 8 | reg;
21562579266SRabin Vincent 
21662579266SRabin Vincent 	dev_vdbg(ab8500->dev, "wr: addr %#x <= %#x\n", addr, data);
21762579266SRabin Vincent 
218392cbd1eSRabin Vincent 	mutex_lock(&ab8500->lock);
21947c16975SMattias Wallin 
22047c16975SMattias Wallin 	ret = ab8500->write(ab8500, addr, data);
22147c16975SMattias Wallin 	if (ret < 0)
22247c16975SMattias Wallin 		dev_err(ab8500->dev, "failed to write reg %#x: %d\n",
22347c16975SMattias Wallin 			addr, ret);
22447c16975SMattias Wallin 	mutex_unlock(&ab8500->lock);
22547c16975SMattias Wallin 
22647c16975SMattias Wallin 	return ret;
22747c16975SMattias Wallin }
22847c16975SMattias Wallin 
22947c16975SMattias Wallin static int ab8500_set_register(struct device *dev, u8 bank,
23047c16975SMattias Wallin 	u8 reg, u8 value)
23147c16975SMattias Wallin {
232112a80d2SJonas Aaberg 	int ret;
23347c16975SMattias Wallin 	struct ab8500 *ab8500 = dev_get_drvdata(dev->parent);
23447c16975SMattias Wallin 
235112a80d2SJonas Aaberg 	atomic_inc(&ab8500->transfer_ongoing);
236112a80d2SJonas Aaberg 	ret = set_register_interruptible(ab8500, bank, reg, value);
237112a80d2SJonas Aaberg 	atomic_dec(&ab8500->transfer_ongoing);
238112a80d2SJonas Aaberg 	return ret;
23947c16975SMattias Wallin }
24047c16975SMattias Wallin 
24147c16975SMattias Wallin static int get_register_interruptible(struct ab8500 *ab8500, u8 bank,
24247c16975SMattias Wallin 	u8 reg, u8 *value)
24347c16975SMattias Wallin {
24447c16975SMattias Wallin 	int ret;
24547c16975SMattias Wallin 	/* put the u8 bank and u8 reg together into a an u16.
24647c16975SMattias Wallin 	 * bank on higher 8 bits and reg in lower */
24747c16975SMattias Wallin 	u16 addr = ((u16)bank) << 8 | reg;
24847c16975SMattias Wallin 
249392cbd1eSRabin Vincent 	mutex_lock(&ab8500->lock);
25047c16975SMattias Wallin 
25147c16975SMattias Wallin 	ret = ab8500->read(ab8500, addr);
25247c16975SMattias Wallin 	if (ret < 0)
25347c16975SMattias Wallin 		dev_err(ab8500->dev, "failed to read reg %#x: %d\n",
25447c16975SMattias Wallin 			addr, ret);
25547c16975SMattias Wallin 	else
25647c16975SMattias Wallin 		*value = ret;
25747c16975SMattias Wallin 
25847c16975SMattias Wallin 	mutex_unlock(&ab8500->lock);
25947c16975SMattias Wallin 	dev_vdbg(ab8500->dev, "rd: addr %#x => data %#x\n", addr, ret);
26047c16975SMattias Wallin 
26147c16975SMattias Wallin 	return ret;
26247c16975SMattias Wallin }
26347c16975SMattias Wallin 
26447c16975SMattias Wallin static int ab8500_get_register(struct device *dev, u8 bank,
26547c16975SMattias Wallin 	u8 reg, u8 *value)
26647c16975SMattias Wallin {
267112a80d2SJonas Aaberg 	int ret;
26847c16975SMattias Wallin 	struct ab8500 *ab8500 = dev_get_drvdata(dev->parent);
26947c16975SMattias Wallin 
270112a80d2SJonas Aaberg 	atomic_inc(&ab8500->transfer_ongoing);
271112a80d2SJonas Aaberg 	ret = get_register_interruptible(ab8500, bank, reg, value);
272112a80d2SJonas Aaberg 	atomic_dec(&ab8500->transfer_ongoing);
273112a80d2SJonas Aaberg 	return ret;
27447c16975SMattias Wallin }
27547c16975SMattias Wallin 
27647c16975SMattias Wallin static int mask_and_set_register_interruptible(struct ab8500 *ab8500, u8 bank,
27747c16975SMattias Wallin 	u8 reg, u8 bitmask, u8 bitvalues)
27847c16975SMattias Wallin {
27947c16975SMattias Wallin 	int ret;
28047c16975SMattias Wallin 	/* put the u8 bank and u8 reg together into a an u16.
28147c16975SMattias Wallin 	 * bank on higher 8 bits and reg in lower */
28247c16975SMattias Wallin 	u16 addr = ((u16)bank) << 8 | reg;
28347c16975SMattias Wallin 
284392cbd1eSRabin Vincent 	mutex_lock(&ab8500->lock);
28547c16975SMattias Wallin 
286bc628fd1SMattias Nilsson 	if (ab8500->write_masked == NULL) {
287bc628fd1SMattias Nilsson 		u8 data;
288bc628fd1SMattias Nilsson 
28947c16975SMattias Wallin 		ret = ab8500->read(ab8500, addr);
29047c16975SMattias Wallin 		if (ret < 0) {
29147c16975SMattias Wallin 			dev_err(ab8500->dev, "failed to read reg %#x: %d\n",
29247c16975SMattias Wallin 				addr, ret);
29347c16975SMattias Wallin 			goto out;
29447c16975SMattias Wallin 		}
29547c16975SMattias Wallin 
29647c16975SMattias Wallin 		data = (u8)ret;
29747c16975SMattias Wallin 		data = (~bitmask & data) | (bitmask & bitvalues);
29847c16975SMattias Wallin 
29962579266SRabin Vincent 		ret = ab8500->write(ab8500, addr, data);
30062579266SRabin Vincent 		if (ret < 0)
30162579266SRabin Vincent 			dev_err(ab8500->dev, "failed to write reg %#x: %d\n",
30262579266SRabin Vincent 				addr, ret);
30362579266SRabin Vincent 
304bc628fd1SMattias Nilsson 		dev_vdbg(ab8500->dev, "mask: addr %#x => data %#x\n", addr,
305bc628fd1SMattias Nilsson 			data);
306bc628fd1SMattias Nilsson 		goto out;
307bc628fd1SMattias Nilsson 	}
308bc628fd1SMattias Nilsson 	ret = ab8500->write_masked(ab8500, addr, bitmask, bitvalues);
309bc628fd1SMattias Nilsson 	if (ret < 0)
310bc628fd1SMattias Nilsson 		dev_err(ab8500->dev, "failed to modify reg %#x: %d\n", addr,
311bc628fd1SMattias Nilsson 			ret);
31262579266SRabin Vincent out:
31362579266SRabin Vincent 	mutex_unlock(&ab8500->lock);
31462579266SRabin Vincent 	return ret;
31562579266SRabin Vincent }
31647c16975SMattias Wallin 
31747c16975SMattias Wallin static int ab8500_mask_and_set_register(struct device *dev,
31847c16975SMattias Wallin 	u8 bank, u8 reg, u8 bitmask, u8 bitvalues)
31947c16975SMattias Wallin {
320112a80d2SJonas Aaberg 	int ret;
32147c16975SMattias Wallin 	struct ab8500 *ab8500 = dev_get_drvdata(dev->parent);
32247c16975SMattias Wallin 
323112a80d2SJonas Aaberg 	atomic_inc(&ab8500->transfer_ongoing);
324112a80d2SJonas Aaberg 	ret= mask_and_set_register_interruptible(ab8500, bank, reg,
32547c16975SMattias Wallin 						 bitmask, bitvalues);
326112a80d2SJonas Aaberg 	atomic_dec(&ab8500->transfer_ongoing);
327112a80d2SJonas Aaberg 	return ret;
32847c16975SMattias Wallin }
32947c16975SMattias Wallin 
33047c16975SMattias Wallin static struct abx500_ops ab8500_ops = {
33147c16975SMattias Wallin 	.get_chip_id = ab8500_get_chip_id,
33247c16975SMattias Wallin 	.get_register = ab8500_get_register,
33347c16975SMattias Wallin 	.set_register = ab8500_set_register,
33447c16975SMattias Wallin 	.get_register_page = NULL,
33547c16975SMattias Wallin 	.set_register_page = NULL,
33647c16975SMattias Wallin 	.mask_and_set_register = ab8500_mask_and_set_register,
33747c16975SMattias Wallin 	.event_registers_startup_state_get = NULL,
33847c16975SMattias Wallin 	.startup_irq_enabled = NULL,
3391d843a6cSMian Yousaf Kaukab 	.dump_all_banks = ab8500_dump_all_banks,
34047c16975SMattias Wallin };
34162579266SRabin Vincent 
3429505a0a0SMark Brown static void ab8500_irq_lock(struct irq_data *data)
34362579266SRabin Vincent {
3449505a0a0SMark Brown 	struct ab8500 *ab8500 = irq_data_get_irq_chip_data(data);
34562579266SRabin Vincent 
34662579266SRabin Vincent 	mutex_lock(&ab8500->irq_lock);
347112a80d2SJonas Aaberg 	atomic_inc(&ab8500->transfer_ongoing);
34862579266SRabin Vincent }
34962579266SRabin Vincent 
3509505a0a0SMark Brown static void ab8500_irq_sync_unlock(struct irq_data *data)
35162579266SRabin Vincent {
3529505a0a0SMark Brown 	struct ab8500 *ab8500 = irq_data_get_irq_chip_data(data);
35362579266SRabin Vincent 	int i;
35462579266SRabin Vincent 
3552ced445eSLinus Walleij 	for (i = 0; i < ab8500->mask_size; i++) {
35662579266SRabin Vincent 		u8 old = ab8500->oldmask[i];
35762579266SRabin Vincent 		u8 new = ab8500->mask[i];
35862579266SRabin Vincent 		int reg;
35962579266SRabin Vincent 
36062579266SRabin Vincent 		if (new == old)
36162579266SRabin Vincent 			continue;
36262579266SRabin Vincent 
3630f620837SLinus Walleij 		/*
3640f620837SLinus Walleij 		 * Interrupt register 12 doesn't exist prior to AB8500 version
3650f620837SLinus Walleij 		 * 2.0
3660f620837SLinus Walleij 		 */
3670f620837SLinus Walleij 		if (ab8500->irq_reg_offset[i] == 11 &&
3680f620837SLinus Walleij 			is_ab8500_1p1_or_earlier(ab8500))
36992d50a41SMattias Wallin 			continue;
37092d50a41SMattias Wallin 
3713e1a498fSLee Jones 		if (ab8500->irq_reg_offset[i] < 0)
3723e1a498fSLee Jones 			continue;
3733e1a498fSLee Jones 
37462579266SRabin Vincent 		ab8500->oldmask[i] = new;
37562579266SRabin Vincent 
3762ced445eSLinus Walleij 		reg = AB8500_IT_MASK1_REG + ab8500->irq_reg_offset[i];
37747c16975SMattias Wallin 		set_register_interruptible(ab8500, AB8500_INTERRUPT, reg, new);
37862579266SRabin Vincent 	}
379112a80d2SJonas Aaberg 	atomic_dec(&ab8500->transfer_ongoing);
38062579266SRabin Vincent 	mutex_unlock(&ab8500->irq_lock);
38162579266SRabin Vincent }
38262579266SRabin Vincent 
3839505a0a0SMark Brown static void ab8500_irq_mask(struct irq_data *data)
38462579266SRabin Vincent {
3859505a0a0SMark Brown 	struct ab8500 *ab8500 = irq_data_get_irq_chip_data(data);
38606e589efSLee Jones 	int offset = data->hwirq;
38762579266SRabin Vincent 	int index = offset / 8;
38862579266SRabin Vincent 	int mask = 1 << (offset % 8);
38962579266SRabin Vincent 
39062579266SRabin Vincent 	ab8500->mask[index] |= mask;
3919c677b9bSLee Jones 
3929c677b9bSLee Jones 	/* The AB8500 GPIOs have two interrupts each (rising & falling). */
3939c677b9bSLee Jones 	if (offset >= AB8500_INT_GPIO6R && offset <= AB8500_INT_GPIO41R)
3949c677b9bSLee Jones 		ab8500->mask[index + 2] |= mask;
3959c677b9bSLee Jones 	if (offset >= AB9540_INT_GPIO50R && offset <= AB9540_INT_GPIO54R)
3969c677b9bSLee Jones 		ab8500->mask[index + 1] |= mask;
3979c677b9bSLee Jones 	if (offset == AB8540_INT_GPIO43R || offset == AB8540_INT_GPIO44R)
398e2ddf46aSLinus Walleij 		/* Here the falling IRQ is one bit lower */
399e2ddf46aSLinus Walleij 		ab8500->mask[index] |= (mask << 1);
40062579266SRabin Vincent }
40162579266SRabin Vincent 
4029505a0a0SMark Brown static void ab8500_irq_unmask(struct irq_data *data)
40362579266SRabin Vincent {
4049505a0a0SMark Brown 	struct ab8500 *ab8500 = irq_data_get_irq_chip_data(data);
4059c677b9bSLee Jones 	unsigned int type = irqd_get_trigger_type(data);
40606e589efSLee Jones 	int offset = data->hwirq;
40762579266SRabin Vincent 	int index = offset / 8;
40862579266SRabin Vincent 	int mask = 1 << (offset % 8);
40962579266SRabin Vincent 
4109c677b9bSLee Jones 	if (type & IRQ_TYPE_EDGE_RISING)
41162579266SRabin Vincent 		ab8500->mask[index] &= ~mask;
4129c677b9bSLee Jones 
4139c677b9bSLee Jones 	/* The AB8500 GPIOs have two interrupts each (rising & falling). */
4149c677b9bSLee Jones 	if (type & IRQ_TYPE_EDGE_FALLING) {
4159c677b9bSLee Jones 		if (offset >= AB8500_INT_GPIO6R && offset <= AB8500_INT_GPIO41R)
4169c677b9bSLee Jones 			ab8500->mask[index + 2] &= ~mask;
4179c677b9bSLee Jones 		else if (offset >= AB9540_INT_GPIO50R && offset <= AB9540_INT_GPIO54R)
4189c677b9bSLee Jones 			ab8500->mask[index + 1] &= ~mask;
4199c677b9bSLee Jones 		else if (offset == AB8540_INT_GPIO43R || offset == AB8540_INT_GPIO44R)
420e2ddf46aSLinus Walleij 			/* Here the falling IRQ is one bit lower */
421e2ddf46aSLinus Walleij 			ab8500->mask[index] &= ~(mask << 1);
4229c677b9bSLee Jones 		else
4239c677b9bSLee Jones 			ab8500->mask[index] &= ~mask;
424e2ddf46aSLinus Walleij 	} else {
4259c677b9bSLee Jones 		/* Satisfies the case where type is not set. */
42662579266SRabin Vincent 		ab8500->mask[index] &= ~mask;
42762579266SRabin Vincent 	}
428e2ddf46aSLinus Walleij }
42962579266SRabin Vincent 
43040f6e5a2SLee Jones static int ab8500_irq_set_type(struct irq_data *data, unsigned int type)
43140f6e5a2SLee Jones {
43240f6e5a2SLee Jones 	return 0;
43362579266SRabin Vincent }
43462579266SRabin Vincent 
43562579266SRabin Vincent static struct irq_chip ab8500_irq_chip = {
43662579266SRabin Vincent 	.name			= "ab8500",
4379505a0a0SMark Brown 	.irq_bus_lock		= ab8500_irq_lock,
4389505a0a0SMark Brown 	.irq_bus_sync_unlock	= ab8500_irq_sync_unlock,
4399505a0a0SMark Brown 	.irq_mask		= ab8500_irq_mask,
440e6f9306eSVirupax Sadashivpetimath 	.irq_disable		= ab8500_irq_mask,
4419505a0a0SMark Brown 	.irq_unmask		= ab8500_irq_unmask,
44240f6e5a2SLee Jones 	.irq_set_type		= ab8500_irq_set_type,
44362579266SRabin Vincent };
44462579266SRabin Vincent 
4453e1a498fSLee Jones static void update_latch_offset(u8 *offset, int i)
4463e1a498fSLee Jones {
4473e1a498fSLee Jones 	/* Fix inconsistent ITFromLatch25 bit mapping... */
4483e1a498fSLee Jones 	if (unlikely(*offset == 17))
4493e1a498fSLee Jones 			*offset = 24;
4503e1a498fSLee Jones 	/* Fix inconsistent ab8540 bit mapping... */
4513e1a498fSLee Jones 	if (unlikely(*offset == 16))
4523e1a498fSLee Jones 			*offset = 25;
4533e1a498fSLee Jones 	if ((i==3) && (*offset >= 24))
4543e1a498fSLee Jones 			*offset += 2;
4553e1a498fSLee Jones }
4563e1a498fSLee Jones 
4577ccfe9b1SMichel JAOUEN static int ab8500_handle_hierarchical_line(struct ab8500 *ab8500,
4587ccfe9b1SMichel JAOUEN 					int latch_offset, u8 latch_val)
4597ccfe9b1SMichel JAOUEN {
4607ccfe9b1SMichel JAOUEN 	int int_bit = __ffs(latch_val);
4617ccfe9b1SMichel JAOUEN 	int line, i;
4627ccfe9b1SMichel JAOUEN 
4637ccfe9b1SMichel JAOUEN 	do {
4647ccfe9b1SMichel JAOUEN 		int_bit = __ffs(latch_val);
4657ccfe9b1SMichel JAOUEN 
4667ccfe9b1SMichel JAOUEN 		for (i = 0; i < ab8500->mask_size; i++)
4677ccfe9b1SMichel JAOUEN 			if (ab8500->irq_reg_offset[i] == latch_offset)
4687ccfe9b1SMichel JAOUEN 				break;
4697ccfe9b1SMichel JAOUEN 
4707ccfe9b1SMichel JAOUEN 		if (i >= ab8500->mask_size) {
4717ccfe9b1SMichel JAOUEN 			dev_err(ab8500->dev, "Register offset 0x%2x not declared\n",
4727ccfe9b1SMichel JAOUEN 					latch_offset);
4737ccfe9b1SMichel JAOUEN 			return -ENXIO;
4747ccfe9b1SMichel JAOUEN 		}
4757ccfe9b1SMichel JAOUEN 
4767ccfe9b1SMichel JAOUEN 		line = (i << 3) + int_bit;
4777ccfe9b1SMichel JAOUEN 		latch_val &= ~(1 << int_bit);
4787ccfe9b1SMichel JAOUEN 
479e2ddf46aSLinus Walleij 		/*
480e2ddf46aSLinus Walleij 		 * This handles the falling edge hwirqs from the GPIO
481e2ddf46aSLinus Walleij 		 * lines. Route them back to the line registered for the
482e2ddf46aSLinus Walleij 		 * rising IRQ, as this is merely a flag for the same IRQ
483e2ddf46aSLinus Walleij 		 * in linux terms.
484e2ddf46aSLinus Walleij 		 */
485e2ddf46aSLinus Walleij 		if (line >= AB8500_INT_GPIO6F && line <= AB8500_INT_GPIO41F)
486e2ddf46aSLinus Walleij 			line -= 16;
487e2ddf46aSLinus Walleij 		if (line >= AB9540_INT_GPIO50F && line <= AB9540_INT_GPIO54F)
488e2ddf46aSLinus Walleij 			line -= 8;
489e2ddf46aSLinus Walleij 		if (line == AB8540_INT_GPIO43F || line == AB8540_INT_GPIO44F)
490e2ddf46aSLinus Walleij 			line += 1;
491e2ddf46aSLinus Walleij 
4927ccfe9b1SMichel JAOUEN 		handle_nested_irq(ab8500->irq_base + line);
4937ccfe9b1SMichel JAOUEN 	} while (latch_val);
4947ccfe9b1SMichel JAOUEN 
4957ccfe9b1SMichel JAOUEN 	return 0;
4967ccfe9b1SMichel JAOUEN }
4977ccfe9b1SMichel JAOUEN 
4987ccfe9b1SMichel JAOUEN static int ab8500_handle_hierarchical_latch(struct ab8500 *ab8500,
4997ccfe9b1SMichel JAOUEN 					int hier_offset, u8 hier_val)
5007ccfe9b1SMichel JAOUEN {
5017ccfe9b1SMichel JAOUEN 	int latch_bit, status;
5027ccfe9b1SMichel JAOUEN 	u8 latch_offset, latch_val;
5037ccfe9b1SMichel JAOUEN 
5047ccfe9b1SMichel JAOUEN 	do {
5057ccfe9b1SMichel JAOUEN 		latch_bit = __ffs(hier_val);
5067ccfe9b1SMichel JAOUEN 		latch_offset = (hier_offset << 3) + latch_bit;
5077ccfe9b1SMichel JAOUEN 
5083e1a498fSLee Jones 		update_latch_offset(&latch_offset, hier_offset);
5097ccfe9b1SMichel JAOUEN 
5107ccfe9b1SMichel JAOUEN 		status = get_register_interruptible(ab8500,
5117ccfe9b1SMichel JAOUEN 				AB8500_INTERRUPT,
5127ccfe9b1SMichel JAOUEN 				AB8500_IT_LATCH1_REG + latch_offset,
5137ccfe9b1SMichel JAOUEN 				&latch_val);
5147ccfe9b1SMichel JAOUEN 		if (status < 0 || latch_val == 0)
5157ccfe9b1SMichel JAOUEN 			goto discard;
5167ccfe9b1SMichel JAOUEN 
5177ccfe9b1SMichel JAOUEN 		status = ab8500_handle_hierarchical_line(ab8500,
5187ccfe9b1SMichel JAOUEN 				latch_offset, latch_val);
5197ccfe9b1SMichel JAOUEN 		if (status < 0)
5207ccfe9b1SMichel JAOUEN 			return status;
5217ccfe9b1SMichel JAOUEN discard:
5227ccfe9b1SMichel JAOUEN 		hier_val &= ~(1 << latch_bit);
5237ccfe9b1SMichel JAOUEN 	} while (hier_val);
5247ccfe9b1SMichel JAOUEN 
5257ccfe9b1SMichel JAOUEN 	return 0;
5267ccfe9b1SMichel JAOUEN }
5277ccfe9b1SMichel JAOUEN 
5287ccfe9b1SMichel JAOUEN static irqreturn_t ab8500_hierarchical_irq(int irq, void *dev)
5297ccfe9b1SMichel JAOUEN {
5307ccfe9b1SMichel JAOUEN 	struct ab8500 *ab8500 = dev;
5317ccfe9b1SMichel JAOUEN 	u8 i;
5327ccfe9b1SMichel JAOUEN 
5337ccfe9b1SMichel JAOUEN 	dev_vdbg(ab8500->dev, "interrupt\n");
5347ccfe9b1SMichel JAOUEN 
5357ccfe9b1SMichel JAOUEN 	/*  Hierarchical interrupt version */
5363e1a498fSLee Jones 	for (i = 0; i < (ab8500->it_latchhier_num); i++) {
5377ccfe9b1SMichel JAOUEN 		int status;
5387ccfe9b1SMichel JAOUEN 		u8 hier_val;
5397ccfe9b1SMichel JAOUEN 
5407ccfe9b1SMichel JAOUEN 		status = get_register_interruptible(ab8500, AB8500_INTERRUPT,
5417ccfe9b1SMichel JAOUEN 			AB8500_IT_LATCHHIER1_REG + i, &hier_val);
5427ccfe9b1SMichel JAOUEN 		if (status < 0 || hier_val == 0)
5437ccfe9b1SMichel JAOUEN 			continue;
5447ccfe9b1SMichel JAOUEN 
5457ccfe9b1SMichel JAOUEN 		status = ab8500_handle_hierarchical_latch(ab8500, i, hier_val);
5467ccfe9b1SMichel JAOUEN 		if (status < 0)
5477ccfe9b1SMichel JAOUEN 			break;
5487ccfe9b1SMichel JAOUEN 	}
5497ccfe9b1SMichel JAOUEN 	return IRQ_HANDLED;
5507ccfe9b1SMichel JAOUEN }
5517ccfe9b1SMichel JAOUEN 
55280633f05SLee Jones /**
55380633f05SLee Jones  * ab8500_irq_get_virq(): Map an interrupt on a chip to a virtual IRQ
55480633f05SLee Jones  *
55580633f05SLee Jones  * @ab8500: ab8500_irq controller to operate on.
55680633f05SLee Jones  * @irq: index of the interrupt requested in the chip IRQs
55780633f05SLee Jones  *
55880633f05SLee Jones  * Useful for drivers to request their own IRQs.
55980633f05SLee Jones  */
56080633f05SLee Jones static int ab8500_irq_get_virq(struct ab8500 *ab8500, int irq)
56180633f05SLee Jones {
56280633f05SLee Jones 	if (!ab8500)
56380633f05SLee Jones 		return -EINVAL;
56480633f05SLee Jones 
56580633f05SLee Jones 	return irq_create_mapping(ab8500->domain, irq);
56680633f05SLee Jones }
56780633f05SLee Jones 
56862579266SRabin Vincent static irqreturn_t ab8500_irq(int irq, void *dev)
56962579266SRabin Vincent {
57062579266SRabin Vincent 	struct ab8500 *ab8500 = dev;
57162579266SRabin Vincent 	int i;
57262579266SRabin Vincent 
57362579266SRabin Vincent 	dev_vdbg(ab8500->dev, "interrupt\n");
57462579266SRabin Vincent 
575112a80d2SJonas Aaberg 	atomic_inc(&ab8500->transfer_ongoing);
576112a80d2SJonas Aaberg 
5772ced445eSLinus Walleij 	for (i = 0; i < ab8500->mask_size; i++) {
5782ced445eSLinus Walleij 		int regoffset = ab8500->irq_reg_offset[i];
57962579266SRabin Vincent 		int status;
58047c16975SMattias Wallin 		u8 value;
58162579266SRabin Vincent 
5820f620837SLinus Walleij 		/*
5830f620837SLinus Walleij 		 * Interrupt register 12 doesn't exist prior to AB8500 version
5840f620837SLinus Walleij 		 * 2.0
5850f620837SLinus Walleij 		 */
5860f620837SLinus Walleij 		if (regoffset == 11 && is_ab8500_1p1_or_earlier(ab8500))
58792d50a41SMattias Wallin 			continue;
58892d50a41SMattias Wallin 
5893e1a498fSLee Jones 		if (regoffset < 0)
5903e1a498fSLee Jones 			continue;
5913e1a498fSLee Jones 
59247c16975SMattias Wallin 		status = get_register_interruptible(ab8500, AB8500_INTERRUPT,
59347c16975SMattias Wallin 			AB8500_IT_LATCH1_REG + regoffset, &value);
59447c16975SMattias Wallin 		if (status < 0 || value == 0)
59562579266SRabin Vincent 			continue;
59662579266SRabin Vincent 
59762579266SRabin Vincent 		do {
59888aec4f7SMattias Wallin 			int bit = __ffs(value);
59962579266SRabin Vincent 			int line = i * 8 + bit;
6000a37fc56SLee Jones 			int virq = ab8500_irq_get_virq(ab8500, line);
60162579266SRabin Vincent 
6020a37fc56SLee Jones 			handle_nested_irq(virq);
6038f0eb43bSBengt Jonsson 			ab8500_debug_register_interrupt(line);
60447c16975SMattias Wallin 			value &= ~(1 << bit);
605112a80d2SJonas Aaberg 
60647c16975SMattias Wallin 		} while (value);
60762579266SRabin Vincent 	}
608112a80d2SJonas Aaberg 	atomic_dec(&ab8500->transfer_ongoing);
60962579266SRabin Vincent 	return IRQ_HANDLED;
61062579266SRabin Vincent }
61162579266SRabin Vincent 
61206e589efSLee Jones static int ab8500_irq_map(struct irq_domain *d, unsigned int virq,
61306e589efSLee Jones 				irq_hw_number_t hwirq)
61406e589efSLee Jones {
61506e589efSLee Jones 	struct ab8500 *ab8500 = d->host_data;
61606e589efSLee Jones 
61706e589efSLee Jones 	if (!ab8500)
61806e589efSLee Jones 		return -EINVAL;
61906e589efSLee Jones 
62006e589efSLee Jones 	irq_set_chip_data(virq, ab8500);
62106e589efSLee Jones 	irq_set_chip_and_handler(virq, &ab8500_irq_chip,
62206e589efSLee Jones 				handle_simple_irq);
62306e589efSLee Jones 	irq_set_nested_thread(virq, 1);
62406e589efSLee Jones #ifdef CONFIG_ARM
62506e589efSLee Jones 	set_irq_flags(virq, IRQF_VALID);
62606e589efSLee Jones #else
62706e589efSLee Jones 	irq_set_noprobe(virq);
62806e589efSLee Jones #endif
62962579266SRabin Vincent 
63062579266SRabin Vincent 	return 0;
63162579266SRabin Vincent }
63262579266SRabin Vincent 
63306e589efSLee Jones static struct irq_domain_ops ab8500_irq_ops = {
63406e589efSLee Jones         .map    = ab8500_irq_map,
63506e589efSLee Jones         .xlate  = irq_domain_xlate_twocell,
63606e589efSLee Jones };
63706e589efSLee Jones 
63806e589efSLee Jones static int ab8500_irq_init(struct ab8500 *ab8500, struct device_node *np)
63962579266SRabin Vincent {
6402ced445eSLinus Walleij 	int num_irqs;
64162579266SRabin Vincent 
6423e1a498fSLee Jones 	if (is_ab8540(ab8500))
6433e1a498fSLee Jones 		num_irqs = AB8540_NR_IRQS;
6443e1a498fSLee Jones 	else if (is_ab9540(ab8500))
645d6255529SLinus Walleij 		num_irqs = AB9540_NR_IRQS;
646a982362cSBengt Jonsson 	else if (is_ab8505(ab8500))
647a982362cSBengt Jonsson 		num_irqs = AB8505_NR_IRQS;
648d6255529SLinus Walleij 	else
6492ced445eSLinus Walleij 		num_irqs = AB8500_NR_IRQS;
6502ced445eSLinus Walleij 
651f1d11f39SLinus Walleij 	/* If ->irq_base is zero this will give a linear mapping */
652f1d11f39SLinus Walleij 	ab8500->domain = irq_domain_add_simple(NULL,
653f1d11f39SLinus Walleij 			num_irqs, ab8500->irq_base,
654f1d11f39SLinus Walleij 			&ab8500_irq_ops, ab8500);
65506e589efSLee Jones 
65606e589efSLee Jones 	if (!ab8500->domain) {
65706e589efSLee Jones 		dev_err(ab8500->dev, "Failed to create irqdomain\n");
65806e589efSLee Jones 		return -ENOSYS;
65906e589efSLee Jones 	}
66006e589efSLee Jones 
66106e589efSLee Jones 	return 0;
66262579266SRabin Vincent }
66362579266SRabin Vincent 
664112a80d2SJonas Aaberg int ab8500_suspend(struct ab8500 *ab8500)
665112a80d2SJonas Aaberg {
666112a80d2SJonas Aaberg 	if (atomic_read(&ab8500->transfer_ongoing))
667112a80d2SJonas Aaberg 		return -EINVAL;
668112a80d2SJonas Aaberg 	else
669112a80d2SJonas Aaberg 		return 0;
670112a80d2SJonas Aaberg }
671112a80d2SJonas Aaberg 
672a9e9ce4cSBill Pemberton static struct resource ab8500_gpadc_resources[] = {
67362579266SRabin Vincent 	{
67462579266SRabin Vincent 		.name	= "HW_CONV_END",
67562579266SRabin Vincent 		.start	= AB8500_INT_GP_HW_ADC_CONV_END,
67662579266SRabin Vincent 		.end	= AB8500_INT_GP_HW_ADC_CONV_END,
67762579266SRabin Vincent 		.flags	= IORESOURCE_IRQ,
67862579266SRabin Vincent 	},
67962579266SRabin Vincent 	{
68062579266SRabin Vincent 		.name	= "SW_CONV_END",
68162579266SRabin Vincent 		.start	= AB8500_INT_GP_SW_ADC_CONV_END,
68262579266SRabin Vincent 		.end	= AB8500_INT_GP_SW_ADC_CONV_END,
68362579266SRabin Vincent 		.flags	= IORESOURCE_IRQ,
68462579266SRabin Vincent 	},
68562579266SRabin Vincent };
68662579266SRabin Vincent 
6874b106fb9SLee Jones static struct resource ab8505_gpadc_resources[] = {
688c0eda9aeSLee Jones 	{
689c0eda9aeSLee Jones 		.name	= "SW_CONV_END",
690c0eda9aeSLee Jones 		.start	= AB8500_INT_GP_SW_ADC_CONV_END,
691c0eda9aeSLee Jones 		.end	= AB8500_INT_GP_SW_ADC_CONV_END,
692c0eda9aeSLee Jones 		.flags	= IORESOURCE_IRQ,
693c0eda9aeSLee Jones 	},
694c0eda9aeSLee Jones };
695c0eda9aeSLee Jones 
696a9e9ce4cSBill Pemberton static struct resource ab8500_rtc_resources[] = {
69762579266SRabin Vincent 	{
69862579266SRabin Vincent 		.name	= "60S",
69962579266SRabin Vincent 		.start	= AB8500_INT_RTC_60S,
70062579266SRabin Vincent 		.end	= AB8500_INT_RTC_60S,
70162579266SRabin Vincent 		.flags	= IORESOURCE_IRQ,
70262579266SRabin Vincent 	},
70362579266SRabin Vincent 	{
70462579266SRabin Vincent 		.name	= "ALARM",
70562579266SRabin Vincent 		.start	= AB8500_INT_RTC_ALARM,
70662579266SRabin Vincent 		.end	= AB8500_INT_RTC_ALARM,
70762579266SRabin Vincent 		.flags	= IORESOURCE_IRQ,
70862579266SRabin Vincent 	},
70962579266SRabin Vincent };
71062579266SRabin Vincent 
711a9e9ce4cSBill Pemberton static struct resource ab8500_poweronkey_db_resources[] = {
71277686517SSundar R Iyer 	{
71377686517SSundar R Iyer 		.name	= "ONKEY_DBF",
71477686517SSundar R Iyer 		.start	= AB8500_INT_PON_KEY1DB_F,
71577686517SSundar R Iyer 		.end	= AB8500_INT_PON_KEY1DB_F,
71677686517SSundar R Iyer 		.flags	= IORESOURCE_IRQ,
71777686517SSundar R Iyer 	},
71877686517SSundar R Iyer 	{
71977686517SSundar R Iyer 		.name	= "ONKEY_DBR",
72077686517SSundar R Iyer 		.start	= AB8500_INT_PON_KEY1DB_R,
72177686517SSundar R Iyer 		.end	= AB8500_INT_PON_KEY1DB_R,
72277686517SSundar R Iyer 		.flags	= IORESOURCE_IRQ,
72377686517SSundar R Iyer 	},
72477686517SSundar R Iyer };
72577686517SSundar R Iyer 
726a9e9ce4cSBill Pemberton static struct resource ab8500_av_acc_detect_resources[] = {
727e098adedSMattias Wallin 	{
7286af75ecdSLinus Walleij 	       .name = "ACC_DETECT_1DB_F",
7296af75ecdSLinus Walleij 	       .start = AB8500_INT_ACC_DETECT_1DB_F,
7306af75ecdSLinus Walleij 	       .end = AB8500_INT_ACC_DETECT_1DB_F,
731e098adedSMattias Wallin 	       .flags = IORESOURCE_IRQ,
732e098adedSMattias Wallin 	},
733e098adedSMattias Wallin 	{
7346af75ecdSLinus Walleij 	       .name = "ACC_DETECT_1DB_R",
7356af75ecdSLinus Walleij 	       .start = AB8500_INT_ACC_DETECT_1DB_R,
7366af75ecdSLinus Walleij 	       .end = AB8500_INT_ACC_DETECT_1DB_R,
737e098adedSMattias Wallin 	       .flags = IORESOURCE_IRQ,
738e098adedSMattias Wallin 	},
739e098adedSMattias Wallin 	{
7406af75ecdSLinus Walleij 	       .name = "ACC_DETECT_21DB_F",
7416af75ecdSLinus Walleij 	       .start = AB8500_INT_ACC_DETECT_21DB_F,
7426af75ecdSLinus Walleij 	       .end = AB8500_INT_ACC_DETECT_21DB_F,
7436af75ecdSLinus Walleij 	       .flags = IORESOURCE_IRQ,
7446af75ecdSLinus Walleij 	},
7456af75ecdSLinus Walleij 	{
7466af75ecdSLinus Walleij 	       .name = "ACC_DETECT_21DB_R",
7476af75ecdSLinus Walleij 	       .start = AB8500_INT_ACC_DETECT_21DB_R,
7486af75ecdSLinus Walleij 	       .end = AB8500_INT_ACC_DETECT_21DB_R,
7496af75ecdSLinus Walleij 	       .flags = IORESOURCE_IRQ,
7506af75ecdSLinus Walleij 	},
7516af75ecdSLinus Walleij 	{
7526af75ecdSLinus Walleij 	       .name = "ACC_DETECT_22DB_F",
7536af75ecdSLinus Walleij 	       .start = AB8500_INT_ACC_DETECT_22DB_F,
7546af75ecdSLinus Walleij 	       .end = AB8500_INT_ACC_DETECT_22DB_F,
7556af75ecdSLinus Walleij 	       .flags = IORESOURCE_IRQ,
7566af75ecdSLinus Walleij 	},
7576af75ecdSLinus Walleij 	{
7586af75ecdSLinus Walleij 	       .name = "ACC_DETECT_22DB_R",
7596af75ecdSLinus Walleij 	       .start = AB8500_INT_ACC_DETECT_22DB_R,
7606af75ecdSLinus Walleij 	       .end = AB8500_INT_ACC_DETECT_22DB_R,
7616af75ecdSLinus Walleij 	       .flags = IORESOURCE_IRQ,
7626af75ecdSLinus Walleij 	},
7636af75ecdSLinus Walleij };
7646af75ecdSLinus Walleij 
765a9e9ce4cSBill Pemberton static struct resource ab8500_charger_resources[] = {
7666af75ecdSLinus Walleij 	{
767e098adedSMattias Wallin 		.name = "MAIN_CH_UNPLUG_DET",
768e098adedSMattias Wallin 		.start = AB8500_INT_MAIN_CH_UNPLUG_DET,
769e098adedSMattias Wallin 		.end = AB8500_INT_MAIN_CH_UNPLUG_DET,
770e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
771e098adedSMattias Wallin 	},
772e098adedSMattias Wallin 	{
773e098adedSMattias Wallin 		.name = "MAIN_CHARGE_PLUG_DET",
774e098adedSMattias Wallin 		.start = AB8500_INT_MAIN_CH_PLUG_DET,
775e098adedSMattias Wallin 		.end = AB8500_INT_MAIN_CH_PLUG_DET,
776e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
777e098adedSMattias Wallin 	},
778e098adedSMattias Wallin 	{
779e098adedSMattias Wallin 		.name = "VBUS_DET_R",
780e098adedSMattias Wallin 		.start = AB8500_INT_VBUS_DET_R,
781e098adedSMattias Wallin 		.end = AB8500_INT_VBUS_DET_R,
782e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
783e098adedSMattias Wallin 	},
784e098adedSMattias Wallin 	{
7856af75ecdSLinus Walleij 		.name = "VBUS_DET_F",
7866af75ecdSLinus Walleij 		.start = AB8500_INT_VBUS_DET_F,
7876af75ecdSLinus Walleij 		.end = AB8500_INT_VBUS_DET_F,
788e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
789e098adedSMattias Wallin 	},
790e098adedSMattias Wallin 	{
7916af75ecdSLinus Walleij 		.name = "USB_LINK_STATUS",
7926af75ecdSLinus Walleij 		.start = AB8500_INT_USB_LINK_STATUS,
7936af75ecdSLinus Walleij 		.end = AB8500_INT_USB_LINK_STATUS,
7946af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
7956af75ecdSLinus Walleij 	},
7966af75ecdSLinus Walleij 	{
797e098adedSMattias Wallin 		.name = "VBUS_OVV",
798e098adedSMattias Wallin 		.start = AB8500_INT_VBUS_OVV,
799e098adedSMattias Wallin 		.end = AB8500_INT_VBUS_OVV,
800e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
801e098adedSMattias Wallin 	},
802e098adedSMattias Wallin 	{
8036af75ecdSLinus Walleij 		.name = "USB_CH_TH_PROT_R",
8046af75ecdSLinus Walleij 		.start = AB8500_INT_USB_CH_TH_PROT_R,
8056af75ecdSLinus Walleij 		.end = AB8500_INT_USB_CH_TH_PROT_R,
806e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
807e098adedSMattias Wallin 	},
808e098adedSMattias Wallin 	{
8096af75ecdSLinus Walleij 		.name = "USB_CH_TH_PROT_F",
8106af75ecdSLinus Walleij 		.start = AB8500_INT_USB_CH_TH_PROT_F,
8116af75ecdSLinus Walleij 		.end = AB8500_INT_USB_CH_TH_PROT_F,
812e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
813e098adedSMattias Wallin 	},
814e098adedSMattias Wallin 	{
8156af75ecdSLinus Walleij 		.name = "MAIN_EXT_CH_NOT_OK",
8166af75ecdSLinus Walleij 		.start = AB8500_INT_MAIN_EXT_CH_NOT_OK,
8176af75ecdSLinus Walleij 		.end = AB8500_INT_MAIN_EXT_CH_NOT_OK,
8186af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
8196af75ecdSLinus Walleij 	},
8206af75ecdSLinus Walleij 	{
8216af75ecdSLinus Walleij 		.name = "MAIN_CH_TH_PROT_R",
8226af75ecdSLinus Walleij 		.start = AB8500_INT_MAIN_CH_TH_PROT_R,
8236af75ecdSLinus Walleij 		.end = AB8500_INT_MAIN_CH_TH_PROT_R,
8246af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
8256af75ecdSLinus Walleij 	},
8266af75ecdSLinus Walleij 	{
8276af75ecdSLinus Walleij 		.name = "MAIN_CH_TH_PROT_F",
8286af75ecdSLinus Walleij 		.start = AB8500_INT_MAIN_CH_TH_PROT_F,
8296af75ecdSLinus Walleij 		.end = AB8500_INT_MAIN_CH_TH_PROT_F,
8306af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
8316af75ecdSLinus Walleij 	},
8326af75ecdSLinus Walleij 	{
8336af75ecdSLinus Walleij 		.name = "USB_CHARGER_NOT_OKR",
834a982362cSBengt Jonsson 		.start = AB8500_INT_USB_CHARGER_NOT_OKR,
835a982362cSBengt Jonsson 		.end = AB8500_INT_USB_CHARGER_NOT_OKR,
8366af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
8376af75ecdSLinus Walleij 	},
8386af75ecdSLinus Walleij 	{
8396af75ecdSLinus Walleij 		.name = "CH_WD_EXP",
8406af75ecdSLinus Walleij 		.start = AB8500_INT_CH_WD_EXP,
8416af75ecdSLinus Walleij 		.end = AB8500_INT_CH_WD_EXP,
8426af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
8436af75ecdSLinus Walleij 	},
84434c11a70SPaer-Olof Haakansson 	{
84534c11a70SPaer-Olof Haakansson 		.name = "VBUS_CH_DROP_END",
84634c11a70SPaer-Olof Haakansson 		.start = AB8500_INT_VBUS_CH_DROP_END,
84734c11a70SPaer-Olof Haakansson 		.end = AB8500_INT_VBUS_CH_DROP_END,
84834c11a70SPaer-Olof Haakansson 		.flags = IORESOURCE_IRQ,
84934c11a70SPaer-Olof Haakansson 	},
8506af75ecdSLinus Walleij };
8516af75ecdSLinus Walleij 
852a9e9ce4cSBill Pemberton static struct resource ab8500_btemp_resources[] = {
8536af75ecdSLinus Walleij 	{
8546af75ecdSLinus Walleij 		.name = "BAT_CTRL_INDB",
8556af75ecdSLinus Walleij 		.start = AB8500_INT_BAT_CTRL_INDB,
8566af75ecdSLinus Walleij 		.end = AB8500_INT_BAT_CTRL_INDB,
857e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
858e098adedSMattias Wallin 	},
859e098adedSMattias Wallin 	{
860e098adedSMattias Wallin 		.name = "BTEMP_LOW",
861e098adedSMattias Wallin 		.start = AB8500_INT_BTEMP_LOW,
862e098adedSMattias Wallin 		.end = AB8500_INT_BTEMP_LOW,
863e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
864e098adedSMattias Wallin 	},
865e098adedSMattias Wallin 	{
866e098adedSMattias Wallin 		.name = "BTEMP_HIGH",
867e098adedSMattias Wallin 		.start = AB8500_INT_BTEMP_HIGH,
868e098adedSMattias Wallin 		.end = AB8500_INT_BTEMP_HIGH,
869e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
870e098adedSMattias Wallin 	},
871e098adedSMattias Wallin 	{
8726af75ecdSLinus Walleij 		.name = "BTEMP_LOW_MEDIUM",
8736af75ecdSLinus Walleij 		.start = AB8500_INT_BTEMP_LOW_MEDIUM,
8746af75ecdSLinus Walleij 		.end = AB8500_INT_BTEMP_LOW_MEDIUM,
875e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
876e098adedSMattias Wallin 	},
877e098adedSMattias Wallin 	{
8786af75ecdSLinus Walleij 		.name = "BTEMP_MEDIUM_HIGH",
8796af75ecdSLinus Walleij 		.start = AB8500_INT_BTEMP_MEDIUM_HIGH,
8806af75ecdSLinus Walleij 		.end = AB8500_INT_BTEMP_MEDIUM_HIGH,
881e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
882e098adedSMattias Wallin 	},
883e098adedSMattias Wallin };
884e098adedSMattias Wallin 
885a9e9ce4cSBill Pemberton static struct resource ab8500_fg_resources[] = {
8866af75ecdSLinus Walleij 	{
8876af75ecdSLinus Walleij 		.name = "NCONV_ACCU",
8886af75ecdSLinus Walleij 		.start = AB8500_INT_CCN_CONV_ACC,
8896af75ecdSLinus Walleij 		.end = AB8500_INT_CCN_CONV_ACC,
8906af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
8916af75ecdSLinus Walleij 	},
8926af75ecdSLinus Walleij 	{
8936af75ecdSLinus Walleij 		.name = "BATT_OVV",
8946af75ecdSLinus Walleij 		.start = AB8500_INT_BATT_OVV,
8956af75ecdSLinus Walleij 		.end = AB8500_INT_BATT_OVV,
8966af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
8976af75ecdSLinus Walleij 	},
8986af75ecdSLinus Walleij 	{
8996af75ecdSLinus Walleij 		.name = "LOW_BAT_F",
9006af75ecdSLinus Walleij 		.start = AB8500_INT_LOW_BAT_F,
9016af75ecdSLinus Walleij 		.end = AB8500_INT_LOW_BAT_F,
9026af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
9036af75ecdSLinus Walleij 	},
9046af75ecdSLinus Walleij 	{
9056af75ecdSLinus Walleij 		.name = "LOW_BAT_R",
9066af75ecdSLinus Walleij 		.start = AB8500_INT_LOW_BAT_R,
9076af75ecdSLinus Walleij 		.end = AB8500_INT_LOW_BAT_R,
9086af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
9096af75ecdSLinus Walleij 	},
9106af75ecdSLinus Walleij 	{
9116af75ecdSLinus Walleij 		.name = "CC_INT_CALIB",
9126af75ecdSLinus Walleij 		.start = AB8500_INT_CC_INT_CALIB,
9136af75ecdSLinus Walleij 		.end = AB8500_INT_CC_INT_CALIB,
9146af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
9156af75ecdSLinus Walleij 	},
916a982362cSBengt Jonsson 	{
917a982362cSBengt Jonsson 		.name = "CCEOC",
918a982362cSBengt Jonsson 		.start = AB8500_INT_CCEOC,
919a982362cSBengt Jonsson 		.end = AB8500_INT_CCEOC,
920a982362cSBengt Jonsson 		.flags = IORESOURCE_IRQ,
921a982362cSBengt Jonsson 	},
9226af75ecdSLinus Walleij };
9236af75ecdSLinus Walleij 
924a9e9ce4cSBill Pemberton static struct resource ab8500_chargalg_resources[] = {};
9256af75ecdSLinus Walleij 
926df720647SAxel Lin #ifdef CONFIG_DEBUG_FS
927a9e9ce4cSBill Pemberton static struct resource ab8500_debug_resources[] = {
928e098adedSMattias Wallin 	{
929e098adedSMattias Wallin 		.name	= "IRQ_FIRST",
930e098adedSMattias Wallin 		.start	= AB8500_INT_MAIN_EXT_CH_NOT_OK,
931e098adedSMattias Wallin 		.end	= AB8500_INT_MAIN_EXT_CH_NOT_OK,
932e098adedSMattias Wallin 		.flags	= IORESOURCE_IRQ,
933e098adedSMattias Wallin 	},
934e098adedSMattias Wallin 	{
935e098adedSMattias Wallin 		.name	= "IRQ_LAST",
936a982362cSBengt Jonsson 		.start	= AB8500_INT_XTAL32K_KO,
937a982362cSBengt Jonsson 		.end	= AB8500_INT_XTAL32K_KO,
938e098adedSMattias Wallin 		.flags	= IORESOURCE_IRQ,
939e098adedSMattias Wallin 	},
940e098adedSMattias Wallin };
941df720647SAxel Lin #endif
942e098adedSMattias Wallin 
943a9e9ce4cSBill Pemberton static struct resource ab8500_usb_resources[] = {
944e098adedSMattias Wallin 	{
945e098adedSMattias Wallin 		.name = "ID_WAKEUP_R",
946e098adedSMattias Wallin 		.start = AB8500_INT_ID_WAKEUP_R,
947e098adedSMattias Wallin 		.end = AB8500_INT_ID_WAKEUP_R,
948e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
949e098adedSMattias Wallin 	},
950e098adedSMattias Wallin 	{
951e098adedSMattias Wallin 		.name = "ID_WAKEUP_F",
952e098adedSMattias Wallin 		.start = AB8500_INT_ID_WAKEUP_F,
953e098adedSMattias Wallin 		.end = AB8500_INT_ID_WAKEUP_F,
954e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
955e098adedSMattias Wallin 	},
956e098adedSMattias Wallin 	{
957e098adedSMattias Wallin 		.name = "VBUS_DET_F",
958e098adedSMattias Wallin 		.start = AB8500_INT_VBUS_DET_F,
959e098adedSMattias Wallin 		.end = AB8500_INT_VBUS_DET_F,
960e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
961e098adedSMattias Wallin 	},
962e098adedSMattias Wallin 	{
963e098adedSMattias Wallin 		.name = "VBUS_DET_R",
964e098adedSMattias Wallin 		.start = AB8500_INT_VBUS_DET_R,
965e098adedSMattias Wallin 		.end = AB8500_INT_VBUS_DET_R,
966e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
967e098adedSMattias Wallin 	},
96892d50a41SMattias Wallin 	{
96992d50a41SMattias Wallin 		.name = "USB_LINK_STATUS",
97092d50a41SMattias Wallin 		.start = AB8500_INT_USB_LINK_STATUS,
97192d50a41SMattias Wallin 		.end = AB8500_INT_USB_LINK_STATUS,
97292d50a41SMattias Wallin 		.flags = IORESOURCE_IRQ,
97392d50a41SMattias Wallin 	},
9746af75ecdSLinus Walleij 	{
9756af75ecdSLinus Walleij 		.name = "USB_ADP_PROBE_PLUG",
9766af75ecdSLinus Walleij 		.start = AB8500_INT_ADP_PROBE_PLUG,
9776af75ecdSLinus Walleij 		.end = AB8500_INT_ADP_PROBE_PLUG,
9786af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
9796af75ecdSLinus Walleij 	},
9806af75ecdSLinus Walleij 	{
9816af75ecdSLinus Walleij 		.name = "USB_ADP_PROBE_UNPLUG",
9826af75ecdSLinus Walleij 		.start = AB8500_INT_ADP_PROBE_UNPLUG,
9836af75ecdSLinus Walleij 		.end = AB8500_INT_ADP_PROBE_UNPLUG,
9846af75ecdSLinus Walleij 		.flags = IORESOURCE_IRQ,
9856af75ecdSLinus Walleij 	},
986e098adedSMattias Wallin };
987e098adedSMattias Wallin 
988a9e9ce4cSBill Pemberton static struct resource ab8505_iddet_resources[] = {
98944f72e53SVirupax Sadashivpetimath 	{
99044f72e53SVirupax Sadashivpetimath 		.name  = "KeyDeglitch",
99144f72e53SVirupax Sadashivpetimath 		.start = AB8505_INT_KEYDEGLITCH,
99244f72e53SVirupax Sadashivpetimath 		.end   = AB8505_INT_KEYDEGLITCH,
99344f72e53SVirupax Sadashivpetimath 		.flags = IORESOURCE_IRQ,
99444f72e53SVirupax Sadashivpetimath 	},
99544f72e53SVirupax Sadashivpetimath 	{
99644f72e53SVirupax Sadashivpetimath 		.name  = "KP",
99744f72e53SVirupax Sadashivpetimath 		.start = AB8505_INT_KP,
99844f72e53SVirupax Sadashivpetimath 		.end   = AB8505_INT_KP,
99944f72e53SVirupax Sadashivpetimath 		.flags = IORESOURCE_IRQ,
100044f72e53SVirupax Sadashivpetimath 	},
100144f72e53SVirupax Sadashivpetimath 	{
100244f72e53SVirupax Sadashivpetimath 		.name  = "IKP",
100344f72e53SVirupax Sadashivpetimath 		.start = AB8505_INT_IKP,
100444f72e53SVirupax Sadashivpetimath 		.end   = AB8505_INT_IKP,
100544f72e53SVirupax Sadashivpetimath 		.flags = IORESOURCE_IRQ,
100644f72e53SVirupax Sadashivpetimath 	},
100744f72e53SVirupax Sadashivpetimath 	{
100844f72e53SVirupax Sadashivpetimath 		.name  = "IKR",
100944f72e53SVirupax Sadashivpetimath 		.start = AB8505_INT_IKR,
101044f72e53SVirupax Sadashivpetimath 		.end   = AB8505_INT_IKR,
101144f72e53SVirupax Sadashivpetimath 		.flags = IORESOURCE_IRQ,
101244f72e53SVirupax Sadashivpetimath 	},
101344f72e53SVirupax Sadashivpetimath 	{
101444f72e53SVirupax Sadashivpetimath 		.name  = "KeyStuck",
101544f72e53SVirupax Sadashivpetimath 		.start = AB8505_INT_KEYSTUCK,
101644f72e53SVirupax Sadashivpetimath 		.end   = AB8505_INT_KEYSTUCK,
101744f72e53SVirupax Sadashivpetimath 		.flags = IORESOURCE_IRQ,
101844f72e53SVirupax Sadashivpetimath 	},
1019492390c8SLee Jones 	{
1020492390c8SLee Jones 		.name = "VBUS_DET_R",
1021492390c8SLee Jones 		.start = AB8500_INT_VBUS_DET_R,
1022492390c8SLee Jones 		.end = AB8500_INT_VBUS_DET_R,
1023492390c8SLee Jones 		.flags = IORESOURCE_IRQ,
1024492390c8SLee Jones 	},
1025492390c8SLee Jones 	{
1026492390c8SLee Jones 		.name = "VBUS_DET_F",
1027492390c8SLee Jones 		.start = AB8500_INT_VBUS_DET_F,
1028492390c8SLee Jones 		.end = AB8500_INT_VBUS_DET_F,
1029492390c8SLee Jones 		.flags = IORESOURCE_IRQ,
1030492390c8SLee Jones 	},
1031492390c8SLee Jones 	{
1032492390c8SLee Jones 		.name = "ID_DET_PLUGR",
1033492390c8SLee Jones 		.start = AB8500_INT_ID_DET_PLUGR,
1034492390c8SLee Jones 		.end = AB8500_INT_ID_DET_PLUGR,
1035492390c8SLee Jones 		.flags = IORESOURCE_IRQ,
1036492390c8SLee Jones 	},
1037492390c8SLee Jones 	{
1038492390c8SLee Jones 		.name = "ID_DET_PLUGF",
1039492390c8SLee Jones 		.start = AB8500_INT_ID_DET_PLUGF,
1040492390c8SLee Jones 		.end = AB8500_INT_ID_DET_PLUGF,
1041492390c8SLee Jones 		.flags = IORESOURCE_IRQ,
1042492390c8SLee Jones 	},
104344f72e53SVirupax Sadashivpetimath };
104444f72e53SVirupax Sadashivpetimath 
1045a9e9ce4cSBill Pemberton static struct resource ab8500_temp_resources[] = {
1046e098adedSMattias Wallin 	{
1047151621a7SHongbo Zhang 		.name  = "ABX500_TEMP_WARM",
1048e098adedSMattias Wallin 		.start = AB8500_INT_TEMP_WARM,
1049e098adedSMattias Wallin 		.end   = AB8500_INT_TEMP_WARM,
1050e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
1051e098adedSMattias Wallin 	},
1052e098adedSMattias Wallin };
1053e098adedSMattias Wallin 
1054a9e9ce4cSBill Pemberton static struct mfd_cell ab8500_bm_devs[] = {
10556ef9418cSRickard Andersson 	{
10566ef9418cSRickard Andersson 		.name = "ab8500-charger",
10574aef72dbSRajanikanth H.V 		.of_compatible = "stericsson,ab8500-charger",
10586ef9418cSRickard Andersson 		.num_resources = ARRAY_SIZE(ab8500_charger_resources),
10596ef9418cSRickard Andersson 		.resources = ab8500_charger_resources,
10604aef72dbSRajanikanth H.V 		.platform_data = &ab8500_bm_data,
10614aef72dbSRajanikanth H.V 		.pdata_size = sizeof(ab8500_bm_data),
10626ef9418cSRickard Andersson 	},
10636ef9418cSRickard Andersson 	{
10646ef9418cSRickard Andersson 		.name = "ab8500-btemp",
1065bd9e8ab2SRajanikanth H.V 		.of_compatible = "stericsson,ab8500-btemp",
10666ef9418cSRickard Andersson 		.num_resources = ARRAY_SIZE(ab8500_btemp_resources),
10676ef9418cSRickard Andersson 		.resources = ab8500_btemp_resources,
1068bd9e8ab2SRajanikanth H.V 		.platform_data = &ab8500_bm_data,
1069bd9e8ab2SRajanikanth H.V 		.pdata_size = sizeof(ab8500_bm_data),
10706ef9418cSRickard Andersson 	},
10716ef9418cSRickard Andersson 	{
10726ef9418cSRickard Andersson 		.name = "ab8500-fg",
1073e0f1abebSRajanikanth H.V 		.of_compatible = "stericsson,ab8500-fg",
10746ef9418cSRickard Andersson 		.num_resources = ARRAY_SIZE(ab8500_fg_resources),
10756ef9418cSRickard Andersson 		.resources = ab8500_fg_resources,
1076e0f1abebSRajanikanth H.V 		.platform_data = &ab8500_bm_data,
1077e0f1abebSRajanikanth H.V 		.pdata_size = sizeof(ab8500_bm_data),
10786ef9418cSRickard Andersson 	},
10796ef9418cSRickard Andersson 	{
10806ef9418cSRickard Andersson 		.name = "ab8500-chargalg",
1081a12810abSRajanikanth H.V 		.of_compatible = "stericsson,ab8500-chargalg",
10826ef9418cSRickard Andersson 		.num_resources = ARRAY_SIZE(ab8500_chargalg_resources),
10836ef9418cSRickard Andersson 		.resources = ab8500_chargalg_resources,
1084a12810abSRajanikanth H.V 		.platform_data = &ab8500_bm_data,
1085a12810abSRajanikanth H.V 		.pdata_size = sizeof(ab8500_bm_data),
10866ef9418cSRickard Andersson 	},
10876ef9418cSRickard Andersson };
10886ef9418cSRickard Andersson 
1089a9e9ce4cSBill Pemberton static struct mfd_cell ab8500_devs[] = {
10904b106fb9SLee Jones #ifdef CONFIG_DEBUG_FS
1091d6255529SLinus Walleij 	{
10924b106fb9SLee Jones 		.name = "ab8500-debug",
10934b106fb9SLee Jones 		.of_compatible = "stericsson,ab8500-debug",
10944b106fb9SLee Jones 		.num_resources = ARRAY_SIZE(ab8500_debug_resources),
10954b106fb9SLee Jones 		.resources = ab8500_debug_resources,
10964b106fb9SLee Jones 	},
10974b106fb9SLee Jones #endif
10984b106fb9SLee Jones 	{
10994b106fb9SLee Jones 		.name = "ab8500-sysctrl",
11004b106fb9SLee Jones 		.of_compatible = "stericsson,ab8500-sysctrl",
11014b106fb9SLee Jones 	},
11024b106fb9SLee Jones 	{
11034b106fb9SLee Jones 		.name = "ab8500-regulator",
11044b106fb9SLee Jones 		.of_compatible = "stericsson,ab8500-regulator",
11054b106fb9SLee Jones 	},
11064b106fb9SLee Jones 	{
11074b106fb9SLee Jones 		.name = "abx500-clk",
11084b106fb9SLee Jones 		.of_compatible = "stericsson,abx500-clk",
11094b106fb9SLee Jones 	},
11104b106fb9SLee Jones 	{
11114b106fb9SLee Jones 		.name = "ab8500-gpadc",
11124b106fb9SLee Jones 		.num_resources = ARRAY_SIZE(ab8500_gpadc_resources),
11134b106fb9SLee Jones 		.resources = ab8500_gpadc_resources,
11144b106fb9SLee Jones 	},
11154b106fb9SLee Jones 	{
11164b106fb9SLee Jones 		.name = "ab8500-rtc",
11174b106fb9SLee Jones 		.of_compatible = "stericsson,ab8500-rtc",
11184b106fb9SLee Jones 		.num_resources = ARRAY_SIZE(ab8500_rtc_resources),
11194b106fb9SLee Jones 		.resources = ab8500_rtc_resources,
11204b106fb9SLee Jones 	},
11214b106fb9SLee Jones 	{
11224b106fb9SLee Jones 		.name = "ab8500-acc-det",
11234b106fb9SLee Jones 		.of_compatible = "stericsson,ab8500-acc-det",
11244b106fb9SLee Jones 		.num_resources = ARRAY_SIZE(ab8500_av_acc_detect_resources),
11254b106fb9SLee Jones 		.resources = ab8500_av_acc_detect_resources,
11264b106fb9SLee Jones 	},
11274b106fb9SLee Jones 	{
11284b106fb9SLee Jones 
11294b106fb9SLee Jones 		.name = "ab8500-poweron-key",
11304b106fb9SLee Jones 		.of_compatible = "stericsson,ab8500-poweron-key",
11314b106fb9SLee Jones 		.num_resources = ARRAY_SIZE(ab8500_poweronkey_db_resources),
11324b106fb9SLee Jones 		.resources = ab8500_poweronkey_db_resources,
11334b106fb9SLee Jones 	},
11344b106fb9SLee Jones 	{
11354b106fb9SLee Jones 		.name = "ab8500-pwm",
11364b106fb9SLee Jones 		.of_compatible = "stericsson,ab8500-pwm",
11374b106fb9SLee Jones 		.id = 1,
11384b106fb9SLee Jones 	},
11394b106fb9SLee Jones 	{
11404b106fb9SLee Jones 		.name = "ab8500-pwm",
11414b106fb9SLee Jones 		.of_compatible = "stericsson,ab8500-pwm",
11424b106fb9SLee Jones 		.id = 2,
11434b106fb9SLee Jones 	},
11444b106fb9SLee Jones 	{
11454b106fb9SLee Jones 		.name = "ab8500-pwm",
11464b106fb9SLee Jones 		.of_compatible = "stericsson,ab8500-pwm",
11474b106fb9SLee Jones 		.id = 3,
11484b106fb9SLee Jones 	},
11494b106fb9SLee Jones 	{
11504b106fb9SLee Jones 		.name = "ab8500-leds",
11514b106fb9SLee Jones 		.of_compatible = "stericsson,ab8500-leds",
11524b106fb9SLee Jones 	},
11534b106fb9SLee Jones 	{
11544b106fb9SLee Jones 		.name = "ab8500-denc",
11554b106fb9SLee Jones 		.of_compatible = "stericsson,ab8500-denc",
11564b106fb9SLee Jones 	},
11574b106fb9SLee Jones 	{
11584b106fb9SLee Jones 		.name = "ab8500-gpio",
1159bad76991SLee Jones 		.of_compatible = "stericsson,ab8500-gpio",
1160d6255529SLinus Walleij 	},
1161d6255529SLinus Walleij 	{
11624b106fb9SLee Jones 		.name = "abx500-temp",
11634b106fb9SLee Jones 		.of_compatible = "stericsson,abx500-temp",
11644b106fb9SLee Jones 		.num_resources = ARRAY_SIZE(ab8500_temp_resources),
11654b106fb9SLee Jones 		.resources = ab8500_temp_resources,
11664b106fb9SLee Jones 	},
11674b106fb9SLee Jones 	{
1168d6255529SLinus Walleij 		.name = "ab8500-usb",
1169d6255529SLinus Walleij 		.num_resources = ARRAY_SIZE(ab8500_usb_resources),
1170d6255529SLinus Walleij 		.resources = ab8500_usb_resources,
1171d6255529SLinus Walleij 	},
117244f72e53SVirupax Sadashivpetimath 	{
117344f72e53SVirupax Sadashivpetimath 		.name = "ab8500-codec",
11744b106fb9SLee Jones 	},
11754b106fb9SLee Jones };
11764b106fb9SLee Jones 
11774b106fb9SLee Jones static struct mfd_cell ab9540_devs[] = {
11784b106fb9SLee Jones #ifdef CONFIG_DEBUG_FS
11794b106fb9SLee Jones 	{
11804b106fb9SLee Jones 		.name = "ab8500-debug",
11814b106fb9SLee Jones 		.num_resources = ARRAY_SIZE(ab8500_debug_resources),
11824b106fb9SLee Jones 		.resources = ab8500_debug_resources,
11834b106fb9SLee Jones 	},
11844b106fb9SLee Jones #endif
11854b106fb9SLee Jones 	{
11864b106fb9SLee Jones 		.name = "ab8500-sysctrl",
11874b106fb9SLee Jones 	},
11884b106fb9SLee Jones 	{
11894b106fb9SLee Jones 		.name = "ab8500-regulator",
119044f72e53SVirupax Sadashivpetimath 	},
1191c0eda9aeSLee Jones 	{
1192c0eda9aeSLee Jones 		.name = "ab8500-gpadc",
1193c0eda9aeSLee Jones 		.of_compatible = "stericsson,ab8500-gpadc",
1194c0eda9aeSLee Jones 		.num_resources = ARRAY_SIZE(ab8500_gpadc_resources),
1195c0eda9aeSLee Jones 		.resources = ab8500_gpadc_resources,
1196c0eda9aeSLee Jones 	},
11974b106fb9SLee Jones 	{
11984b106fb9SLee Jones 		.name = "ab8500-rtc",
11994b106fb9SLee Jones 		.num_resources = ARRAY_SIZE(ab8500_rtc_resources),
12004b106fb9SLee Jones 		.resources = ab8500_rtc_resources,
12014b106fb9SLee Jones 	},
12024b106fb9SLee Jones 	{
12034b106fb9SLee Jones 		.name = "ab8500-acc-det",
12044b106fb9SLee Jones 		.num_resources = ARRAY_SIZE(ab8500_av_acc_detect_resources),
12054b106fb9SLee Jones 		.resources = ab8500_av_acc_detect_resources,
12064b106fb9SLee Jones 	},
12074b106fb9SLee Jones 	{
12084b106fb9SLee Jones 		.name = "ab8500-poweron-key",
12094b106fb9SLee Jones 		.num_resources = ARRAY_SIZE(ab8500_poweronkey_db_resources),
12104b106fb9SLee Jones 		.resources = ab8500_poweronkey_db_resources,
12114b106fb9SLee Jones 	},
12124b106fb9SLee Jones 	{
12134b106fb9SLee Jones 		.name = "ab8500-pwm",
12144b106fb9SLee Jones 		.id = 1,
12154b106fb9SLee Jones 	},
12164b106fb9SLee Jones 	{
12174b106fb9SLee Jones 		.name = "ab8500-leds",
12184b106fb9SLee Jones 	},
12194b106fb9SLee Jones 	{
12204b106fb9SLee Jones 		.name = "abx500-temp",
12214b106fb9SLee Jones 		.num_resources = ARRAY_SIZE(ab8500_temp_resources),
12224b106fb9SLee Jones 		.resources = ab8500_temp_resources,
12234b106fb9SLee Jones 	},
1224d6255529SLinus Walleij 	{
1225e64d905eSLee Jones 		.name = "pinctrl-ab9540",
1226e64d905eSLee Jones 		.of_compatible = "stericsson,ab9540-gpio",
1227d6255529SLinus Walleij 	},
1228d6255529SLinus Walleij 	{
1229d6255529SLinus Walleij 		.name = "ab9540-usb",
1230d6255529SLinus Walleij 		.num_resources = ARRAY_SIZE(ab8500_usb_resources),
1231d6255529SLinus Walleij 		.resources = ab8500_usb_resources,
1232d6255529SLinus Walleij 	},
123344f72e53SVirupax Sadashivpetimath 	{
123444f72e53SVirupax Sadashivpetimath 		.name = "ab9540-codec",
123544f72e53SVirupax Sadashivpetimath 	},
1236c0eda9aeSLee Jones 	{
1237c0eda9aeSLee Jones 		.name = "ab-iddet",
1238c0eda9aeSLee Jones 		.num_resources = ARRAY_SIZE(ab8505_iddet_resources),
1239c0eda9aeSLee Jones 		.resources = ab8505_iddet_resources,
1240c0eda9aeSLee Jones 	},
124144f72e53SVirupax Sadashivpetimath };
124244f72e53SVirupax Sadashivpetimath 
1243c0eda9aeSLee Jones /* Device list for ab8505  */
1244c0eda9aeSLee Jones static struct mfd_cell ab8505_devs[] = {
12454b106fb9SLee Jones #ifdef CONFIG_DEBUG_FS
12464b106fb9SLee Jones 	{
12474b106fb9SLee Jones 		.name = "ab8500-debug",
12484b106fb9SLee Jones 		.num_resources = ARRAY_SIZE(ab8500_debug_resources),
12494b106fb9SLee Jones 		.resources = ab8500_debug_resources,
12504b106fb9SLee Jones 	},
12514b106fb9SLee Jones #endif
12524b106fb9SLee Jones 	{
12534b106fb9SLee Jones 		.name = "ab8500-sysctrl",
12544b106fb9SLee Jones 	},
12554b106fb9SLee Jones 	{
12564b106fb9SLee Jones 		.name = "ab8500-regulator",
12574b106fb9SLee Jones 	},
12584b106fb9SLee Jones 	{
12594b106fb9SLee Jones 		.name = "ab8500-gpadc",
12604b106fb9SLee Jones 		.num_resources = ARRAY_SIZE(ab8505_gpadc_resources),
12614b106fb9SLee Jones 		.resources = ab8505_gpadc_resources,
12624b106fb9SLee Jones 	},
12634b106fb9SLee Jones 	{
12644b106fb9SLee Jones 		.name = "ab8500-rtc",
12654b106fb9SLee Jones 		.num_resources = ARRAY_SIZE(ab8500_rtc_resources),
12664b106fb9SLee Jones 		.resources = ab8500_rtc_resources,
12674b106fb9SLee Jones 	},
12684b106fb9SLee Jones 	{
12694b106fb9SLee Jones 		.name = "ab8500-acc-det",
12704b106fb9SLee Jones 		.num_resources = ARRAY_SIZE(ab8500_av_acc_detect_resources),
12714b106fb9SLee Jones 		.resources = ab8500_av_acc_detect_resources,
12724b106fb9SLee Jones 	},
12734b106fb9SLee Jones 	{
12744b106fb9SLee Jones 		.name = "ab8500-poweron-key",
12754b106fb9SLee Jones 		.num_resources = ARRAY_SIZE(ab8500_poweronkey_db_resources),
12764b106fb9SLee Jones 		.resources = ab8500_poweronkey_db_resources,
12774b106fb9SLee Jones 	},
12784b106fb9SLee Jones 	{
12794b106fb9SLee Jones 		.name = "ab8500-pwm",
12804b106fb9SLee Jones 		.id = 1,
12814b106fb9SLee Jones 	},
12824b106fb9SLee Jones 	{
12834b106fb9SLee Jones 		.name = "ab8500-leds",
12844b106fb9SLee Jones 	},
12854b106fb9SLee Jones 	{
12864b106fb9SLee Jones 		.name = "ab8500-gpio",
12874b106fb9SLee Jones 	},
12884b106fb9SLee Jones 	{
12894b106fb9SLee Jones 		.name = "ab8500-usb",
12904b106fb9SLee Jones 		.num_resources = ARRAY_SIZE(ab8500_usb_resources),
12914b106fb9SLee Jones 		.resources = ab8500_usb_resources,
12924b106fb9SLee Jones 	},
12934b106fb9SLee Jones 	{
12944b106fb9SLee Jones 		.name = "ab8500-codec",
12954b106fb9SLee Jones 	},
1296c0eda9aeSLee Jones 	{
1297c0eda9aeSLee Jones 		.name = "ab-iddet",
1298c0eda9aeSLee Jones 		.num_resources = ARRAY_SIZE(ab8505_iddet_resources),
1299c0eda9aeSLee Jones 		.resources = ab8505_iddet_resources,
1300c0eda9aeSLee Jones 	},
1301c0eda9aeSLee Jones };
1302c0eda9aeSLee Jones 
1303c0eda9aeSLee Jones static struct mfd_cell ab8540_devs[] = {
13044b106fb9SLee Jones #ifdef CONFIG_DEBUG_FS
13054b106fb9SLee Jones 	{
13064b106fb9SLee Jones 		.name = "ab8500-debug",
13074b106fb9SLee Jones 		.num_resources = ARRAY_SIZE(ab8500_debug_resources),
13084b106fb9SLee Jones 		.resources = ab8500_debug_resources,
13094b106fb9SLee Jones 	},
13104b106fb9SLee Jones #endif
13114b106fb9SLee Jones 	{
13124b106fb9SLee Jones 		.name = "ab8500-sysctrl",
13134b106fb9SLee Jones 	},
13144b106fb9SLee Jones 	{
13154b106fb9SLee Jones 		.name = "ab8500-regulator",
13164b106fb9SLee Jones 	},
13174b106fb9SLee Jones 	{
13184b106fb9SLee Jones 		.name = "ab8500-gpadc",
13194b106fb9SLee Jones 		.num_resources = ARRAY_SIZE(ab8505_gpadc_resources),
13204b106fb9SLee Jones 		.resources = ab8505_gpadc_resources,
13214b106fb9SLee Jones 	},
13224b106fb9SLee Jones 	{
13234b106fb9SLee Jones 		.name = "ab8500-rtc",
13244b106fb9SLee Jones 		.num_resources = ARRAY_SIZE(ab8500_rtc_resources),
13254b106fb9SLee Jones 		.resources = ab8500_rtc_resources,
13264b106fb9SLee Jones 	},
13274b106fb9SLee Jones 	{
13284b106fb9SLee Jones 		.name = "ab8500-acc-det",
13294b106fb9SLee Jones 		.num_resources = ARRAY_SIZE(ab8500_av_acc_detect_resources),
13304b106fb9SLee Jones 		.resources = ab8500_av_acc_detect_resources,
13314b106fb9SLee Jones 	},
13324b106fb9SLee Jones 	{
13334b106fb9SLee Jones 		.name = "ab8500-poweron-key",
13344b106fb9SLee Jones 		.num_resources = ARRAY_SIZE(ab8500_poweronkey_db_resources),
13354b106fb9SLee Jones 		.resources = ab8500_poweronkey_db_resources,
13364b106fb9SLee Jones 	},
13374b106fb9SLee Jones 	{
13384b106fb9SLee Jones 		.name = "ab8500-pwm",
13394b106fb9SLee Jones 		.id = 1,
13404b106fb9SLee Jones 	},
13414b106fb9SLee Jones 	{
13424b106fb9SLee Jones 		.name = "ab8500-leds",
13434b106fb9SLee Jones 	},
13444b106fb9SLee Jones 	{
13454b106fb9SLee Jones 		.name = "abx500-temp",
13464b106fb9SLee Jones 		.num_resources = ARRAY_SIZE(ab8500_temp_resources),
13474b106fb9SLee Jones 		.resources = ab8500_temp_resources,
13484b106fb9SLee Jones 	},
1349c0eda9aeSLee Jones 	{
1350c0eda9aeSLee Jones 		.name = "ab8500-gpio",
1351c0eda9aeSLee Jones 	},
1352c0eda9aeSLee Jones 	{
1353c0eda9aeSLee Jones 		.name = "ab8540-usb",
1354c0eda9aeSLee Jones 		.num_resources = ARRAY_SIZE(ab8500_usb_resources),
1355c0eda9aeSLee Jones 		.resources = ab8500_usb_resources,
1356c0eda9aeSLee Jones 	},
1357c0eda9aeSLee Jones 	{
1358c0eda9aeSLee Jones 		.name = "ab8540-codec",
1359c0eda9aeSLee Jones 	},
1360c0eda9aeSLee Jones 	{
136144f72e53SVirupax Sadashivpetimath 		.name = "ab-iddet",
136244f72e53SVirupax Sadashivpetimath 		.num_resources = ARRAY_SIZE(ab8505_iddet_resources),
136344f72e53SVirupax Sadashivpetimath 		.resources = ab8505_iddet_resources,
136444f72e53SVirupax Sadashivpetimath 	},
1365d6255529SLinus Walleij };
1366d6255529SLinus Walleij 
1367cca69b67SMattias Wallin static ssize_t show_chip_id(struct device *dev,
1368cca69b67SMattias Wallin 				struct device_attribute *attr, char *buf)
1369cca69b67SMattias Wallin {
1370cca69b67SMattias Wallin 	struct ab8500 *ab8500;
1371cca69b67SMattias Wallin 
1372cca69b67SMattias Wallin 	ab8500 = dev_get_drvdata(dev);
1373e436ddffSLee Jones 
1374cca69b67SMattias Wallin 	return sprintf(buf, "%#x\n", ab8500 ? ab8500->chip_id : -EINVAL);
1375cca69b67SMattias Wallin }
1376cca69b67SMattias Wallin 
1377e5c238c3SMattias Wallin /*
1378e5c238c3SMattias Wallin  * ab8500 has switched off due to (SWITCH_OFF_STATUS):
1379e5c238c3SMattias Wallin  * 0x01 Swoff bit programming
1380e5c238c3SMattias Wallin  * 0x02 Thermal protection activation
1381e5c238c3SMattias Wallin  * 0x04 Vbat lower then BattOk falling threshold
1382e5c238c3SMattias Wallin  * 0x08 Watchdog expired
1383e5c238c3SMattias Wallin  * 0x10 Non presence of 32kHz clock
1384e5c238c3SMattias Wallin  * 0x20 Battery level lower than power on reset threshold
1385e5c238c3SMattias Wallin  * 0x40 Power on key 1 pressed longer than 10 seconds
1386e5c238c3SMattias Wallin  * 0x80 DB8500 thermal shutdown
1387e5c238c3SMattias Wallin  */
1388e5c238c3SMattias Wallin static ssize_t show_switch_off_status(struct device *dev,
1389e5c238c3SMattias Wallin 				struct device_attribute *attr, char *buf)
1390e5c238c3SMattias Wallin {
1391e5c238c3SMattias Wallin 	int ret;
1392e5c238c3SMattias Wallin 	u8 value;
1393e5c238c3SMattias Wallin 	struct ab8500 *ab8500;
1394e5c238c3SMattias Wallin 
1395e5c238c3SMattias Wallin 	ab8500 = dev_get_drvdata(dev);
1396e5c238c3SMattias Wallin 	ret = get_register_interruptible(ab8500, AB8500_RTC,
1397e5c238c3SMattias Wallin 		AB8500_SWITCH_OFF_STATUS, &value);
1398e5c238c3SMattias Wallin 	if (ret < 0)
1399e5c238c3SMattias Wallin 		return ret;
1400e5c238c3SMattias Wallin 	return sprintf(buf, "%#x\n", value);
1401e5c238c3SMattias Wallin }
1402e5c238c3SMattias Wallin 
1403f04a9d8aSRajkumar Kasirajan /* use mask and set to override the register turn_on_stat value */
1404f04a9d8aSRajkumar Kasirajan void ab8500_override_turn_on_stat(u8 mask, u8 set)
1405f04a9d8aSRajkumar Kasirajan {
1406f04a9d8aSRajkumar Kasirajan 	spin_lock(&on_stat_lock);
1407f04a9d8aSRajkumar Kasirajan 	turn_on_stat_mask = mask;
1408f04a9d8aSRajkumar Kasirajan 	turn_on_stat_set = set;
1409f04a9d8aSRajkumar Kasirajan 	spin_unlock(&on_stat_lock);
1410f04a9d8aSRajkumar Kasirajan }
1411f04a9d8aSRajkumar Kasirajan 
1412b4a31037SAndrew Lynn /*
1413b4a31037SAndrew Lynn  * ab8500 has turned on due to (TURN_ON_STATUS):
1414b4a31037SAndrew Lynn  * 0x01 PORnVbat
1415b4a31037SAndrew Lynn  * 0x02 PonKey1dbF
1416b4a31037SAndrew Lynn  * 0x04 PonKey2dbF
1417b4a31037SAndrew Lynn  * 0x08 RTCAlarm
1418b4a31037SAndrew Lynn  * 0x10 MainChDet
1419b4a31037SAndrew Lynn  * 0x20 VbusDet
1420b4a31037SAndrew Lynn  * 0x40 UsbIDDetect
1421b4a31037SAndrew Lynn  * 0x80 Reserved
1422b4a31037SAndrew Lynn  */
1423b4a31037SAndrew Lynn static ssize_t show_turn_on_status(struct device *dev,
1424b4a31037SAndrew Lynn 				struct device_attribute *attr, char *buf)
1425b4a31037SAndrew Lynn {
1426b4a31037SAndrew Lynn 	int ret;
1427b4a31037SAndrew Lynn 	u8 value;
1428b4a31037SAndrew Lynn 	struct ab8500 *ab8500;
1429b4a31037SAndrew Lynn 
1430b4a31037SAndrew Lynn 	ab8500 = dev_get_drvdata(dev);
1431b4a31037SAndrew Lynn 	ret = get_register_interruptible(ab8500, AB8500_SYS_CTRL1_BLOCK,
1432b4a31037SAndrew Lynn 		AB8500_TURN_ON_STATUS, &value);
1433b4a31037SAndrew Lynn 	if (ret < 0)
1434b4a31037SAndrew Lynn 		return ret;
1435f04a9d8aSRajkumar Kasirajan 
1436f04a9d8aSRajkumar Kasirajan 	/*
1437f04a9d8aSRajkumar Kasirajan 	 * In L9540, turn_on_status register is not updated correctly if
1438f04a9d8aSRajkumar Kasirajan 	 * the device is rebooted with AC/USB charger connected. Due to
1439f04a9d8aSRajkumar Kasirajan 	 * this, the device boots android instead of entering into charge
1440f04a9d8aSRajkumar Kasirajan 	 * only mode. Read the AC/USB status register to detect the charger
1441f04a9d8aSRajkumar Kasirajan 	 * presence and update the turn on status manually.
1442f04a9d8aSRajkumar Kasirajan 	 */
1443f04a9d8aSRajkumar Kasirajan 	if (is_ab9540(ab8500)) {
1444f04a9d8aSRajkumar Kasirajan 		spin_lock(&on_stat_lock);
1445f04a9d8aSRajkumar Kasirajan 		value = (value & turn_on_stat_mask) | turn_on_stat_set;
1446f04a9d8aSRajkumar Kasirajan 		spin_unlock(&on_stat_lock);
1447f04a9d8aSRajkumar Kasirajan 	}
1448f04a9d8aSRajkumar Kasirajan 
1449b4a31037SAndrew Lynn 	return sprintf(buf, "%#x\n", value);
1450b4a31037SAndrew Lynn }
1451b4a31037SAndrew Lynn 
1452d6255529SLinus Walleij static ssize_t show_ab9540_dbbrstn(struct device *dev,
1453d6255529SLinus Walleij 				struct device_attribute *attr, char *buf)
1454d6255529SLinus Walleij {
1455d6255529SLinus Walleij 	struct ab8500 *ab8500;
1456d6255529SLinus Walleij 	int ret;
1457d6255529SLinus Walleij 	u8 value;
1458d6255529SLinus Walleij 
1459d6255529SLinus Walleij 	ab8500 = dev_get_drvdata(dev);
1460d6255529SLinus Walleij 
1461d6255529SLinus Walleij 	ret = get_register_interruptible(ab8500, AB8500_REGU_CTRL2,
1462d6255529SLinus Walleij 		AB9540_MODEM_CTRL2_REG, &value);
1463d6255529SLinus Walleij 	if (ret < 0)
1464d6255529SLinus Walleij 		return ret;
1465d6255529SLinus Walleij 
1466d6255529SLinus Walleij 	return sprintf(buf, "%d\n",
1467d6255529SLinus Walleij 			(value & AB9540_MODEM_CTRL2_SWDBBRSTN_BIT) ? 1 : 0);
1468d6255529SLinus Walleij }
1469d6255529SLinus Walleij 
1470d6255529SLinus Walleij static ssize_t store_ab9540_dbbrstn(struct device *dev,
1471d6255529SLinus Walleij 	struct device_attribute *attr, const char *buf, size_t count)
1472d6255529SLinus Walleij {
1473d6255529SLinus Walleij 	struct ab8500 *ab8500;
1474d6255529SLinus Walleij 	int ret = count;
1475d6255529SLinus Walleij 	int err;
1476d6255529SLinus Walleij 	u8 bitvalues;
1477d6255529SLinus Walleij 
1478d6255529SLinus Walleij 	ab8500 = dev_get_drvdata(dev);
1479d6255529SLinus Walleij 
1480d6255529SLinus Walleij 	if (count > 0) {
1481d6255529SLinus Walleij 		switch (buf[0]) {
1482d6255529SLinus Walleij 		case '0':
1483d6255529SLinus Walleij 			bitvalues = 0;
1484d6255529SLinus Walleij 			break;
1485d6255529SLinus Walleij 		case '1':
1486d6255529SLinus Walleij 			bitvalues = AB9540_MODEM_CTRL2_SWDBBRSTN_BIT;
1487d6255529SLinus Walleij 			break;
1488d6255529SLinus Walleij 		default:
1489d6255529SLinus Walleij 			goto exit;
1490d6255529SLinus Walleij 		}
1491d6255529SLinus Walleij 
1492d6255529SLinus Walleij 		err = mask_and_set_register_interruptible(ab8500,
1493d6255529SLinus Walleij 			AB8500_REGU_CTRL2, AB9540_MODEM_CTRL2_REG,
1494d6255529SLinus Walleij 			AB9540_MODEM_CTRL2_SWDBBRSTN_BIT, bitvalues);
1495d6255529SLinus Walleij 		if (err)
1496d6255529SLinus Walleij 			dev_info(ab8500->dev,
1497d6255529SLinus Walleij 				"Failed to set DBBRSTN %c, err %#x\n",
1498d6255529SLinus Walleij 				buf[0], err);
1499d6255529SLinus Walleij 	}
1500d6255529SLinus Walleij 
1501d6255529SLinus Walleij exit:
1502d6255529SLinus Walleij 	return ret;
1503d6255529SLinus Walleij }
1504d6255529SLinus Walleij 
1505cca69b67SMattias Wallin static DEVICE_ATTR(chip_id, S_IRUGO, show_chip_id, NULL);
1506e5c238c3SMattias Wallin static DEVICE_ATTR(switch_off_status, S_IRUGO, show_switch_off_status, NULL);
1507b4a31037SAndrew Lynn static DEVICE_ATTR(turn_on_status, S_IRUGO, show_turn_on_status, NULL);
1508d6255529SLinus Walleij static DEVICE_ATTR(dbbrstn, S_IRUGO | S_IWUSR,
1509d6255529SLinus Walleij 			show_ab9540_dbbrstn, store_ab9540_dbbrstn);
1510cca69b67SMattias Wallin 
1511cca69b67SMattias Wallin static struct attribute *ab8500_sysfs_entries[] = {
1512cca69b67SMattias Wallin 	&dev_attr_chip_id.attr,
1513e5c238c3SMattias Wallin 	&dev_attr_switch_off_status.attr,
1514b4a31037SAndrew Lynn 	&dev_attr_turn_on_status.attr,
1515cca69b67SMattias Wallin 	NULL,
1516cca69b67SMattias Wallin };
1517cca69b67SMattias Wallin 
1518d6255529SLinus Walleij static struct attribute *ab9540_sysfs_entries[] = {
1519d6255529SLinus Walleij 	&dev_attr_chip_id.attr,
1520d6255529SLinus Walleij 	&dev_attr_switch_off_status.attr,
1521d6255529SLinus Walleij 	&dev_attr_turn_on_status.attr,
1522d6255529SLinus Walleij 	&dev_attr_dbbrstn.attr,
1523d6255529SLinus Walleij 	NULL,
1524d6255529SLinus Walleij };
1525d6255529SLinus Walleij 
1526cca69b67SMattias Wallin static struct attribute_group ab8500_attr_group = {
1527cca69b67SMattias Wallin 	.attrs	= ab8500_sysfs_entries,
1528cca69b67SMattias Wallin };
1529cca69b67SMattias Wallin 
1530d6255529SLinus Walleij static struct attribute_group ab9540_attr_group = {
1531d6255529SLinus Walleij 	.attrs	= ab9540_sysfs_entries,
1532d6255529SLinus Walleij };
1533d6255529SLinus Walleij 
1534f791be49SBill Pemberton static int ab8500_probe(struct platform_device *pdev)
153562579266SRabin Vincent {
1536b04c530cSJonas Aaberg 	static char *switch_off_status[] = {
1537b04c530cSJonas Aaberg 		"Swoff bit programming",
1538b04c530cSJonas Aaberg 		"Thermal protection activation",
1539b04c530cSJonas Aaberg 		"Vbat lower then BattOk falling threshold",
1540b04c530cSJonas Aaberg 		"Watchdog expired",
1541b04c530cSJonas Aaberg 		"Non presence of 32kHz clock",
1542b04c530cSJonas Aaberg 		"Battery level lower than power on reset threshold",
1543b04c530cSJonas Aaberg 		"Power on key 1 pressed longer than 10 seconds",
1544b04c530cSJonas Aaberg 		"DB8500 thermal shutdown"};
1545*abee26cdSMattias Wallin 	static char *turn_on_status[] = {
1546*abee26cdSMattias Wallin 		"Battery rising (Vbat)",
1547*abee26cdSMattias Wallin 		"Power On Key 1 dbF",
1548*abee26cdSMattias Wallin 		"Power On Key 2 dbF",
1549*abee26cdSMattias Wallin 		"RTC Alarm",
1550*abee26cdSMattias Wallin 		"Main Charger Detect",
1551*abee26cdSMattias Wallin 		"Vbus Detect (USB)",
1552*abee26cdSMattias Wallin 		"USB ID Detect",
1553*abee26cdSMattias Wallin 		"UART Factory Mode Detect"};
1554d28f1db8SLee Jones 	struct ab8500_platform_data *plat = dev_get_platdata(&pdev->dev);
1555d28f1db8SLee Jones 	const struct platform_device_id *platid = platform_get_device_id(pdev);
15566bc4a568SLee Jones 	enum ab8500_version version = AB8500_VERSION_UNDEFINED;
15576bc4a568SLee Jones 	struct device_node *np = pdev->dev.of_node;
1558d28f1db8SLee Jones 	struct ab8500 *ab8500;
1559d28f1db8SLee Jones 	struct resource *resource;
156062579266SRabin Vincent 	int ret;
156162579266SRabin Vincent 	int i;
156247c16975SMattias Wallin 	u8 value;
156362579266SRabin Vincent 
15648c4203cbSLee Jones 	ab8500 = devm_kzalloc(&pdev->dev, sizeof *ab8500, GFP_KERNEL);
1565d28f1db8SLee Jones 	if (!ab8500)
1566d28f1db8SLee Jones 		return -ENOMEM;
1567d28f1db8SLee Jones 
156862579266SRabin Vincent 	if (plat)
156962579266SRabin Vincent 		ab8500->irq_base = plat->irq_base;
157062579266SRabin Vincent 
1571d28f1db8SLee Jones 	ab8500->dev = &pdev->dev;
1572d28f1db8SLee Jones 
1573d28f1db8SLee Jones 	resource = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
15748c4203cbSLee Jones 	if (!resource)
15758c4203cbSLee Jones 		return -ENODEV;
1576d28f1db8SLee Jones 
1577d28f1db8SLee Jones 	ab8500->irq = resource->start;
1578d28f1db8SLee Jones 
1579822672a7SLee Jones 	ab8500->read = ab8500_prcmu_read;
1580822672a7SLee Jones 	ab8500->write = ab8500_prcmu_write;
1581822672a7SLee Jones 	ab8500->write_masked = ab8500_prcmu_write_masked;
1582d28f1db8SLee Jones 
158362579266SRabin Vincent 	mutex_init(&ab8500->lock);
158462579266SRabin Vincent 	mutex_init(&ab8500->irq_lock);
1585112a80d2SJonas Aaberg 	atomic_set(&ab8500->transfer_ongoing, 0);
158662579266SRabin Vincent 
1587d28f1db8SLee Jones 	platform_set_drvdata(pdev, ab8500);
1588d28f1db8SLee Jones 
15896bc4a568SLee Jones 	if (platid)
15906bc4a568SLee Jones 		version = platid->driver_data;
15916bc4a568SLee Jones 
15920f620837SLinus Walleij 	if (version != AB8500_VERSION_UNDEFINED)
15930f620837SLinus Walleij 		ab8500->version = version;
15940f620837SLinus Walleij 	else {
15950f620837SLinus Walleij 		ret = get_register_interruptible(ab8500, AB8500_MISC,
15960f620837SLinus Walleij 			AB8500_IC_NAME_REG, &value);
15970f620837SLinus Walleij 		if (ret < 0)
15988c4203cbSLee Jones 			return ret;
15990f620837SLinus Walleij 
16000f620837SLinus Walleij 		ab8500->version = value;
16010f620837SLinus Walleij 	}
16020f620837SLinus Walleij 
160347c16975SMattias Wallin 	ret = get_register_interruptible(ab8500, AB8500_MISC,
160447c16975SMattias Wallin 		AB8500_REV_REG, &value);
160562579266SRabin Vincent 	if (ret < 0)
16068c4203cbSLee Jones 		return ret;
160762579266SRabin Vincent 
160847c16975SMattias Wallin 	ab8500->chip_id = value;
160962579266SRabin Vincent 
16100f620837SLinus Walleij 	dev_info(ab8500->dev, "detected chip, %s rev. %1x.%1x\n",
16110f620837SLinus Walleij 			ab8500_version_str[ab8500->version],
16120f620837SLinus Walleij 			ab8500->chip_id >> 4,
16130f620837SLinus Walleij 			ab8500->chip_id & 0x0F);
16140f620837SLinus Walleij 
16153e1a498fSLee Jones 	/* Configure AB8540 */
16163e1a498fSLee Jones 	if (is_ab8540(ab8500)) {
16173e1a498fSLee Jones 		ab8500->mask_size = AB8540_NUM_IRQ_REGS;
16183e1a498fSLee Jones 		ab8500->irq_reg_offset = ab8540_irq_regoffset;
16193e1a498fSLee Jones 		ab8500->it_latchhier_num = AB8540_IT_LATCHHIER_NUM;
16203e1a498fSLee Jones 	}/* Configure AB8500 or AB9540 IRQ */
16213e1a498fSLee Jones 	else if (is_ab9540(ab8500) || is_ab8505(ab8500)) {
1622d6255529SLinus Walleij 		ab8500->mask_size = AB9540_NUM_IRQ_REGS;
1623d6255529SLinus Walleij 		ab8500->irq_reg_offset = ab9540_irq_regoffset;
16243e1a498fSLee Jones 		ab8500->it_latchhier_num = AB8500_IT_LATCHHIER_NUM;
1625d6255529SLinus Walleij 	} else {
16262ced445eSLinus Walleij 		ab8500->mask_size = AB8500_NUM_IRQ_REGS;
16272ced445eSLinus Walleij 		ab8500->irq_reg_offset = ab8500_irq_regoffset;
16283e1a498fSLee Jones 		ab8500->it_latchhier_num = AB8500_IT_LATCHHIER_NUM;
1629d6255529SLinus Walleij 	}
16308c4203cbSLee Jones 	ab8500->mask = devm_kzalloc(&pdev->dev, ab8500->mask_size, GFP_KERNEL);
16312ced445eSLinus Walleij 	if (!ab8500->mask)
16322ced445eSLinus Walleij 		return -ENOMEM;
16338c4203cbSLee Jones 	ab8500->oldmask = devm_kzalloc(&pdev->dev, ab8500->mask_size, GFP_KERNEL);
16348c4203cbSLee Jones 	if (!ab8500->oldmask)
16358c4203cbSLee Jones 		return -ENOMEM;
16368c4203cbSLee Jones 
1637e5c238c3SMattias Wallin 	/*
1638e5c238c3SMattias Wallin 	 * ab8500 has switched off due to (SWITCH_OFF_STATUS):
1639e5c238c3SMattias Wallin 	 * 0x01 Swoff bit programming
1640e5c238c3SMattias Wallin 	 * 0x02 Thermal protection activation
1641e5c238c3SMattias Wallin 	 * 0x04 Vbat lower then BattOk falling threshold
1642e5c238c3SMattias Wallin 	 * 0x08 Watchdog expired
1643e5c238c3SMattias Wallin 	 * 0x10 Non presence of 32kHz clock
1644e5c238c3SMattias Wallin 	 * 0x20 Battery level lower than power on reset threshold
1645e5c238c3SMattias Wallin 	 * 0x40 Power on key 1 pressed longer than 10 seconds
1646e5c238c3SMattias Wallin 	 * 0x80 DB8500 thermal shutdown
1647e5c238c3SMattias Wallin 	 */
1648e5c238c3SMattias Wallin 
1649e5c238c3SMattias Wallin 	ret = get_register_interruptible(ab8500, AB8500_RTC,
1650e5c238c3SMattias Wallin 		AB8500_SWITCH_OFF_STATUS, &value);
1651e5c238c3SMattias Wallin 	if (ret < 0)
1652e5c238c3SMattias Wallin 		return ret;
1653b04c530cSJonas Aaberg 	dev_info(ab8500->dev, "switch off cause(s) (%#x): ", value);
1654b04c530cSJonas Aaberg 
1655b04c530cSJonas Aaberg 	if (value) {
1656b04c530cSJonas Aaberg 		for (i = 0; i < ARRAY_SIZE(switch_off_status); i++) {
1657b04c530cSJonas Aaberg 			if (value & 1)
1658b04c530cSJonas Aaberg 				printk(KERN_CONT " \"%s\"",
1659b04c530cSJonas Aaberg 				       switch_off_status[i]);
1660b04c530cSJonas Aaberg 			value = value >> 1;
1661b04c530cSJonas Aaberg 
1662b04c530cSJonas Aaberg 		}
1663b04c530cSJonas Aaberg 		printk(KERN_CONT "\n");
1664b04c530cSJonas Aaberg 	} else {
1665b04c530cSJonas Aaberg 		printk(KERN_CONT " None\n");
1666b04c530cSJonas Aaberg 	}
1667*abee26cdSMattias Wallin 	ret = get_register_interruptible(ab8500, AB8500_SYS_CTRL1_BLOCK,
1668*abee26cdSMattias Wallin 		AB8500_TURN_ON_STATUS, &value);
1669*abee26cdSMattias Wallin 	if (ret < 0)
1670*abee26cdSMattias Wallin 		return ret;
1671*abee26cdSMattias Wallin 	dev_info(ab8500->dev, "turn on reason(s) (%#x): ", value);
1672*abee26cdSMattias Wallin 
1673*abee26cdSMattias Wallin 	if (value) {
1674*abee26cdSMattias Wallin 		for (i = 0; i < ARRAY_SIZE(turn_on_status); i++) {
1675*abee26cdSMattias Wallin 			if (value & 1)
1676*abee26cdSMattias Wallin 				printk("\"%s\" ", turn_on_status[i]);
1677*abee26cdSMattias Wallin 			value = value >> 1;
1678*abee26cdSMattias Wallin 		}
1679*abee26cdSMattias Wallin 		printk("\n");
1680*abee26cdSMattias Wallin 	} else {
1681*abee26cdSMattias Wallin 		printk("None\n");
1682*abee26cdSMattias Wallin 	}
1683e5c238c3SMattias Wallin 
168462579266SRabin Vincent 	if (plat && plat->init)
168562579266SRabin Vincent 		plat->init(ab8500);
1686*abee26cdSMattias Wallin 
1687f04a9d8aSRajkumar Kasirajan 	if (is_ab9540(ab8500)) {
1688f04a9d8aSRajkumar Kasirajan 		ret = get_register_interruptible(ab8500, AB8500_CHARGER,
1689f04a9d8aSRajkumar Kasirajan 			AB8500_CH_USBCH_STAT1_REG, &value);
1690f04a9d8aSRajkumar Kasirajan 		if (ret < 0)
1691f04a9d8aSRajkumar Kasirajan 			return ret;
1692f04a9d8aSRajkumar Kasirajan 		if ((value & VBUS_DET_DBNC1) && (value & VBUS_DET_DBNC100))
1693f04a9d8aSRajkumar Kasirajan 			ab8500_override_turn_on_stat(~AB8500_POW_KEY_1_ON,
1694f04a9d8aSRajkumar Kasirajan 						     AB8500_VBUS_DET);
1695f04a9d8aSRajkumar Kasirajan 	}
169662579266SRabin Vincent 
169762579266SRabin Vincent 	/* Clear and mask all interrupts */
16982ced445eSLinus Walleij 	for (i = 0; i < ab8500->mask_size; i++) {
16990f620837SLinus Walleij 		/*
17000f620837SLinus Walleij 		 * Interrupt register 12 doesn't exist prior to AB8500 version
17010f620837SLinus Walleij 		 * 2.0
17020f620837SLinus Walleij 		 */
17030f620837SLinus Walleij 		if (ab8500->irq_reg_offset[i] == 11 &&
17040f620837SLinus Walleij 				is_ab8500_1p1_or_earlier(ab8500))
170592d50a41SMattias Wallin 			continue;
170662579266SRabin Vincent 
17073e1a498fSLee Jones 		if (ab8500->irq_reg_offset[i] < 0)
17083e1a498fSLee Jones 			continue;
17093e1a498fSLee Jones 
171047c16975SMattias Wallin 		get_register_interruptible(ab8500, AB8500_INTERRUPT,
17112ced445eSLinus Walleij 			AB8500_IT_LATCH1_REG + ab8500->irq_reg_offset[i],
171292d50a41SMattias Wallin 			&value);
171347c16975SMattias Wallin 		set_register_interruptible(ab8500, AB8500_INTERRUPT,
17142ced445eSLinus Walleij 			AB8500_IT_MASK1_REG + ab8500->irq_reg_offset[i], 0xff);
171562579266SRabin Vincent 	}
171662579266SRabin Vincent 
171747c16975SMattias Wallin 	ret = abx500_register_ops(ab8500->dev, &ab8500_ops);
171847c16975SMattias Wallin 	if (ret)
17198c4203cbSLee Jones 		return ret;
172047c16975SMattias Wallin 
17212ced445eSLinus Walleij 	for (i = 0; i < ab8500->mask_size; i++)
172262579266SRabin Vincent 		ab8500->mask[i] = ab8500->oldmask[i] = 0xff;
172362579266SRabin Vincent 
172406e589efSLee Jones 	ret = ab8500_irq_init(ab8500, np);
172562579266SRabin Vincent 	if (ret)
17268c4203cbSLee Jones 		return ret;
172762579266SRabin Vincent 
17287ccfe9b1SMichel JAOUEN 	/*  Activate this feature only in ab9540 */
17297ccfe9b1SMichel JAOUEN 	/*  till tests are done on ab8500 1p2 or later*/
1730e436ddffSLee Jones 	if (is_ab9540(ab8500) || is_ab8540(ab8500))
17318c4203cbSLee Jones 		ret = devm_request_threaded_irq(&pdev->dev, ab8500->irq, NULL,
17327ccfe9b1SMichel JAOUEN 						ab8500_hierarchical_irq,
17337ccfe9b1SMichel JAOUEN 						IRQF_ONESHOT | IRQF_NO_SUSPEND,
17347ccfe9b1SMichel JAOUEN 						"ab8500", ab8500);
173506e589efSLee Jones 	}
173606e589efSLee Jones 	else {
17378c4203cbSLee Jones 		ret = devm_request_threaded_irq(&pdev->dev, ab8500->irq, NULL,
17387ccfe9b1SMichel JAOUEN 						ab8500_irq,
17394f079985SMattias Wallin 						IRQF_ONESHOT | IRQF_NO_SUSPEND,
17404f079985SMattias Wallin 						"ab8500", ab8500);
174162579266SRabin Vincent 		if (ret)
17428c4203cbSLee Jones 			return ret;
174362579266SRabin Vincent 	}
174462579266SRabin Vincent 
1745d6255529SLinus Walleij 	if (is_ab9540(ab8500))
1746d6255529SLinus Walleij 		ret = mfd_add_devices(ab8500->dev, 0, ab9540_devs,
1747d6255529SLinus Walleij 				ARRAY_SIZE(ab9540_devs), NULL,
174855692af5SMark Brown 				ab8500->irq_base, ab8500->domain);
1749c0eda9aeSLee Jones 	else if (is_ab8540(ab8500))
1750c0eda9aeSLee Jones 		ret = mfd_add_devices(ab8500->dev, 0, ab8540_devs,
1751c0eda9aeSLee Jones 			      ARRAY_SIZE(ab8540_devs), NULL,
1752c0eda9aeSLee Jones 			      ab8500->irq_base, ab8500->domain);
1753c0eda9aeSLee Jones 	else if (is_ab8505(ab8500))
1754c0eda9aeSLee Jones 		ret = mfd_add_devices(ab8500->dev, 0, ab8505_devs,
1755c0eda9aeSLee Jones 			      ARRAY_SIZE(ab8505_devs), NULL,
1756c0eda9aeSLee Jones 			      ab8500->irq_base, ab8500->domain);
1757d6255529SLinus Walleij 	else
1758549931f9SSundar R Iyer 		ret = mfd_add_devices(ab8500->dev, 0, ab8500_devs,
175944f72e53SVirupax Sadashivpetimath 				ARRAY_SIZE(ab8500_devs), NULL,
176055692af5SMark Brown 				ab8500->irq_base, ab8500->domain);
17616bc4a568SLee Jones 	if (ret)
17628c4203cbSLee Jones 		return ret;
176344f72e53SVirupax Sadashivpetimath 
17646ef9418cSRickard Andersson 	if (!no_bm) {
17656ef9418cSRickard Andersson 		/* Add battery management devices */
17666ef9418cSRickard Andersson 		ret = mfd_add_devices(ab8500->dev, 0, ab8500_bm_devs,
17676ef9418cSRickard Andersson 				      ARRAY_SIZE(ab8500_bm_devs), NULL,
176855692af5SMark Brown 				      ab8500->irq_base, ab8500->domain);
17696ef9418cSRickard Andersson 		if (ret)
17706ef9418cSRickard Andersson 			dev_err(ab8500->dev, "error adding bm devices\n");
17716ef9418cSRickard Andersson 	}
17726ef9418cSRickard Andersson 
1773e436ddffSLee Jones 	if (((is_ab8505(ab8500) || is_ab9540(ab8500)) &&
1774e436ddffSLee Jones 			ab8500->chip_id >= AB8500_CUT2P0) || is_ab8540(ab8500))
1775d6255529SLinus Walleij 		ret = sysfs_create_group(&ab8500->dev->kobj,
1776d6255529SLinus Walleij 					&ab9540_attr_group);
1777d6255529SLinus Walleij 	else
1778d6255529SLinus Walleij 		ret = sysfs_create_group(&ab8500->dev->kobj,
1779d6255529SLinus Walleij 					&ab8500_attr_group);
1780cca69b67SMattias Wallin 	if (ret)
1781cca69b67SMattias Wallin 		dev_err(ab8500->dev, "error creating sysfs entries\n");
178206e589efSLee Jones 
178362579266SRabin Vincent 	return ret;
178462579266SRabin Vincent }
178562579266SRabin Vincent 
17864740f73fSBill Pemberton static int ab8500_remove(struct platform_device *pdev)
178762579266SRabin Vincent {
1788d28f1db8SLee Jones 	struct ab8500 *ab8500 = platform_get_drvdata(pdev);
1789d28f1db8SLee Jones 
1790e436ddffSLee Jones 	if (((is_ab8505(ab8500) || is_ab9540(ab8500)) &&
1791e436ddffSLee Jones 			ab8500->chip_id >= AB8500_CUT2P0) || is_ab8540(ab8500))
1792d6255529SLinus Walleij 		sysfs_remove_group(&ab8500->dev->kobj, &ab9540_attr_group);
1793d6255529SLinus Walleij 	else
1794cca69b67SMattias Wallin 		sysfs_remove_group(&ab8500->dev->kobj, &ab8500_attr_group);
179506e589efSLee Jones 
179662579266SRabin Vincent 	mfd_remove_devices(ab8500->dev);
179762579266SRabin Vincent 
179862579266SRabin Vincent 	return 0;
179962579266SRabin Vincent }
180062579266SRabin Vincent 
1801d28f1db8SLee Jones static const struct platform_device_id ab8500_id[] = {
1802d28f1db8SLee Jones 	{ "ab8500-core", AB8500_VERSION_AB8500 },
1803d28f1db8SLee Jones 	{ "ab8505-i2c", AB8500_VERSION_AB8505 },
1804d28f1db8SLee Jones 	{ "ab9540-i2c", AB8500_VERSION_AB9540 },
1805d28f1db8SLee Jones 	{ "ab8540-i2c", AB8500_VERSION_AB8540 },
1806d28f1db8SLee Jones 	{ }
1807d28f1db8SLee Jones };
1808d28f1db8SLee Jones 
1809d28f1db8SLee Jones static struct platform_driver ab8500_core_driver = {
1810d28f1db8SLee Jones 	.driver = {
1811d28f1db8SLee Jones 		.name = "ab8500-core",
1812d28f1db8SLee Jones 		.owner = THIS_MODULE,
1813d28f1db8SLee Jones 	},
1814d28f1db8SLee Jones 	.probe	= ab8500_probe,
181584449216SBill Pemberton 	.remove	= ab8500_remove,
1816d28f1db8SLee Jones 	.id_table = ab8500_id,
1817d28f1db8SLee Jones };
1818d28f1db8SLee Jones 
1819d28f1db8SLee Jones static int __init ab8500_core_init(void)
1820d28f1db8SLee Jones {
1821d28f1db8SLee Jones 	return platform_driver_register(&ab8500_core_driver);
1822d28f1db8SLee Jones }
1823d28f1db8SLee Jones 
1824d28f1db8SLee Jones static void __exit ab8500_core_exit(void)
1825d28f1db8SLee Jones {
1826d28f1db8SLee Jones 	platform_driver_unregister(&ab8500_core_driver);
1827d28f1db8SLee Jones }
1828ba7cbc3eSLee Jones core_initcall(ab8500_core_init);
1829d28f1db8SLee Jones module_exit(ab8500_core_exit);
1830d28f1db8SLee Jones 
1831adceed62SMattias Wallin MODULE_AUTHOR("Mattias Wallin, Srinidhi Kasagar, Rabin Vincent");
183262579266SRabin Vincent MODULE_DESCRIPTION("AB8500 MFD core");
183362579266SRabin Vincent MODULE_LICENSE("GPL v2");
1834