xref: /openbmc/linux/drivers/mfd/ab8500-core.c (revision e436ddff5748c459853bb3fb97550a9b8b647b8d)
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 	},
101944f72e53SVirupax Sadashivpetimath };
102044f72e53SVirupax Sadashivpetimath 
1021a9e9ce4cSBill Pemberton static struct resource ab8500_temp_resources[] = {
1022e098adedSMattias Wallin 	{
1023151621a7SHongbo Zhang 		.name  = "ABX500_TEMP_WARM",
1024e098adedSMattias Wallin 		.start = AB8500_INT_TEMP_WARM,
1025e098adedSMattias Wallin 		.end   = AB8500_INT_TEMP_WARM,
1026e098adedSMattias Wallin 		.flags = IORESOURCE_IRQ,
1027e098adedSMattias Wallin 	},
1028e098adedSMattias Wallin };
1029e098adedSMattias Wallin 
1030a9e9ce4cSBill Pemberton static struct mfd_cell ab8500_bm_devs[] = {
10316ef9418cSRickard Andersson 	{
10326ef9418cSRickard Andersson 		.name = "ab8500-charger",
10334aef72dbSRajanikanth H.V 		.of_compatible = "stericsson,ab8500-charger",
10346ef9418cSRickard Andersson 		.num_resources = ARRAY_SIZE(ab8500_charger_resources),
10356ef9418cSRickard Andersson 		.resources = ab8500_charger_resources,
10364aef72dbSRajanikanth H.V 		.platform_data = &ab8500_bm_data,
10374aef72dbSRajanikanth H.V 		.pdata_size = sizeof(ab8500_bm_data),
10386ef9418cSRickard Andersson 	},
10396ef9418cSRickard Andersson 	{
10406ef9418cSRickard Andersson 		.name = "ab8500-btemp",
1041bd9e8ab2SRajanikanth H.V 		.of_compatible = "stericsson,ab8500-btemp",
10426ef9418cSRickard Andersson 		.num_resources = ARRAY_SIZE(ab8500_btemp_resources),
10436ef9418cSRickard Andersson 		.resources = ab8500_btemp_resources,
1044bd9e8ab2SRajanikanth H.V 		.platform_data = &ab8500_bm_data,
1045bd9e8ab2SRajanikanth H.V 		.pdata_size = sizeof(ab8500_bm_data),
10466ef9418cSRickard Andersson 	},
10476ef9418cSRickard Andersson 	{
10486ef9418cSRickard Andersson 		.name = "ab8500-fg",
1049e0f1abebSRajanikanth H.V 		.of_compatible = "stericsson,ab8500-fg",
10506ef9418cSRickard Andersson 		.num_resources = ARRAY_SIZE(ab8500_fg_resources),
10516ef9418cSRickard Andersson 		.resources = ab8500_fg_resources,
1052e0f1abebSRajanikanth H.V 		.platform_data = &ab8500_bm_data,
1053e0f1abebSRajanikanth H.V 		.pdata_size = sizeof(ab8500_bm_data),
10546ef9418cSRickard Andersson 	},
10556ef9418cSRickard Andersson 	{
10566ef9418cSRickard Andersson 		.name = "ab8500-chargalg",
1057a12810abSRajanikanth H.V 		.of_compatible = "stericsson,ab8500-chargalg",
10586ef9418cSRickard Andersson 		.num_resources = ARRAY_SIZE(ab8500_chargalg_resources),
10596ef9418cSRickard Andersson 		.resources = ab8500_chargalg_resources,
1060a12810abSRajanikanth H.V 		.platform_data = &ab8500_bm_data,
1061a12810abSRajanikanth H.V 		.pdata_size = sizeof(ab8500_bm_data),
10626ef9418cSRickard Andersson 	},
10636ef9418cSRickard Andersson };
10646ef9418cSRickard Andersson 
1065a9e9ce4cSBill Pemberton static struct mfd_cell ab8500_devs[] = {
10664b106fb9SLee Jones #ifdef CONFIG_DEBUG_FS
1067d6255529SLinus Walleij 	{
10684b106fb9SLee Jones 		.name = "ab8500-debug",
10694b106fb9SLee Jones 		.of_compatible = "stericsson,ab8500-debug",
10704b106fb9SLee Jones 		.num_resources = ARRAY_SIZE(ab8500_debug_resources),
10714b106fb9SLee Jones 		.resources = ab8500_debug_resources,
10724b106fb9SLee Jones 	},
10734b106fb9SLee Jones #endif
10744b106fb9SLee Jones 	{
10754b106fb9SLee Jones 		.name = "ab8500-sysctrl",
10764b106fb9SLee Jones 		.of_compatible = "stericsson,ab8500-sysctrl",
10774b106fb9SLee Jones 	},
10784b106fb9SLee Jones 	{
10794b106fb9SLee Jones 		.name = "ab8500-regulator",
10804b106fb9SLee Jones 		.of_compatible = "stericsson,ab8500-regulator",
10814b106fb9SLee Jones 	},
10824b106fb9SLee Jones 	{
10834b106fb9SLee Jones 		.name = "abx500-clk",
10844b106fb9SLee Jones 		.of_compatible = "stericsson,abx500-clk",
10854b106fb9SLee Jones 	},
10864b106fb9SLee Jones 	{
10874b106fb9SLee Jones 		.name = "ab8500-gpadc",
10884b106fb9SLee Jones 		.num_resources = ARRAY_SIZE(ab8500_gpadc_resources),
10894b106fb9SLee Jones 		.resources = ab8500_gpadc_resources,
10904b106fb9SLee Jones 	},
10914b106fb9SLee Jones 	{
10924b106fb9SLee Jones 		.name = "ab8500-rtc",
10934b106fb9SLee Jones 		.of_compatible = "stericsson,ab8500-rtc",
10944b106fb9SLee Jones 		.num_resources = ARRAY_SIZE(ab8500_rtc_resources),
10954b106fb9SLee Jones 		.resources = ab8500_rtc_resources,
10964b106fb9SLee Jones 	},
10974b106fb9SLee Jones 	{
10984b106fb9SLee Jones 		.name = "ab8500-acc-det",
10994b106fb9SLee Jones 		.of_compatible = "stericsson,ab8500-acc-det",
11004b106fb9SLee Jones 		.num_resources = ARRAY_SIZE(ab8500_av_acc_detect_resources),
11014b106fb9SLee Jones 		.resources = ab8500_av_acc_detect_resources,
11024b106fb9SLee Jones 	},
11034b106fb9SLee Jones 	{
11044b106fb9SLee Jones 
11054b106fb9SLee Jones 		.name = "ab8500-poweron-key",
11064b106fb9SLee Jones 		.of_compatible = "stericsson,ab8500-poweron-key",
11074b106fb9SLee Jones 		.num_resources = ARRAY_SIZE(ab8500_poweronkey_db_resources),
11084b106fb9SLee Jones 		.resources = ab8500_poweronkey_db_resources,
11094b106fb9SLee Jones 	},
11104b106fb9SLee Jones 	{
11114b106fb9SLee Jones 		.name = "ab8500-pwm",
11124b106fb9SLee Jones 		.of_compatible = "stericsson,ab8500-pwm",
11134b106fb9SLee Jones 		.id = 1,
11144b106fb9SLee Jones 	},
11154b106fb9SLee Jones 	{
11164b106fb9SLee Jones 		.name = "ab8500-pwm",
11174b106fb9SLee Jones 		.of_compatible = "stericsson,ab8500-pwm",
11184b106fb9SLee Jones 		.id = 2,
11194b106fb9SLee Jones 	},
11204b106fb9SLee Jones 	{
11214b106fb9SLee Jones 		.name = "ab8500-pwm",
11224b106fb9SLee Jones 		.of_compatible = "stericsson,ab8500-pwm",
11234b106fb9SLee Jones 		.id = 3,
11244b106fb9SLee Jones 	},
11254b106fb9SLee Jones 	{
11264b106fb9SLee Jones 		.name = "ab8500-leds",
11274b106fb9SLee Jones 		.of_compatible = "stericsson,ab8500-leds",
11284b106fb9SLee Jones 	},
11294b106fb9SLee Jones 	{
11304b106fb9SLee Jones 		.name = "ab8500-denc",
11314b106fb9SLee Jones 		.of_compatible = "stericsson,ab8500-denc",
11324b106fb9SLee Jones 	},
11334b106fb9SLee Jones 	{
11344b106fb9SLee Jones 		.name = "ab8500-gpio",
1135bad76991SLee Jones 		.of_compatible = "stericsson,ab8500-gpio",
1136d6255529SLinus Walleij 	},
1137d6255529SLinus Walleij 	{
11384b106fb9SLee Jones 		.name = "abx500-temp",
11394b106fb9SLee Jones 		.of_compatible = "stericsson,abx500-temp",
11404b106fb9SLee Jones 		.num_resources = ARRAY_SIZE(ab8500_temp_resources),
11414b106fb9SLee Jones 		.resources = ab8500_temp_resources,
11424b106fb9SLee Jones 	},
11434b106fb9SLee Jones 	{
1144d6255529SLinus Walleij 		.name = "ab8500-usb",
1145d6255529SLinus Walleij 		.num_resources = ARRAY_SIZE(ab8500_usb_resources),
1146d6255529SLinus Walleij 		.resources = ab8500_usb_resources,
1147d6255529SLinus Walleij 	},
114844f72e53SVirupax Sadashivpetimath 	{
114944f72e53SVirupax Sadashivpetimath 		.name = "ab8500-codec",
11504b106fb9SLee Jones 	},
11514b106fb9SLee Jones };
11524b106fb9SLee Jones 
11534b106fb9SLee Jones static struct mfd_cell ab9540_devs[] = {
11544b106fb9SLee Jones #ifdef CONFIG_DEBUG_FS
11554b106fb9SLee Jones 	{
11564b106fb9SLee Jones 		.name = "ab8500-debug",
11574b106fb9SLee Jones 		.num_resources = ARRAY_SIZE(ab8500_debug_resources),
11584b106fb9SLee Jones 		.resources = ab8500_debug_resources,
11594b106fb9SLee Jones 	},
11604b106fb9SLee Jones #endif
11614b106fb9SLee Jones 	{
11624b106fb9SLee Jones 		.name = "ab8500-sysctrl",
11634b106fb9SLee Jones 	},
11644b106fb9SLee Jones 	{
11654b106fb9SLee Jones 		.name = "ab8500-regulator",
116644f72e53SVirupax Sadashivpetimath 	},
1167c0eda9aeSLee Jones 	{
1168c0eda9aeSLee Jones 		.name = "ab8500-gpadc",
1169c0eda9aeSLee Jones 		.of_compatible = "stericsson,ab8500-gpadc",
1170c0eda9aeSLee Jones 		.num_resources = ARRAY_SIZE(ab8500_gpadc_resources),
1171c0eda9aeSLee Jones 		.resources = ab8500_gpadc_resources,
1172c0eda9aeSLee Jones 	},
11734b106fb9SLee Jones 	{
11744b106fb9SLee Jones 		.name = "ab8500-rtc",
11754b106fb9SLee Jones 		.num_resources = ARRAY_SIZE(ab8500_rtc_resources),
11764b106fb9SLee Jones 		.resources = ab8500_rtc_resources,
11774b106fb9SLee Jones 	},
11784b106fb9SLee Jones 	{
11794b106fb9SLee Jones 		.name = "ab8500-acc-det",
11804b106fb9SLee Jones 		.num_resources = ARRAY_SIZE(ab8500_av_acc_detect_resources),
11814b106fb9SLee Jones 		.resources = ab8500_av_acc_detect_resources,
11824b106fb9SLee Jones 	},
11834b106fb9SLee Jones 	{
11844b106fb9SLee Jones 		.name = "ab8500-poweron-key",
11854b106fb9SLee Jones 		.num_resources = ARRAY_SIZE(ab8500_poweronkey_db_resources),
11864b106fb9SLee Jones 		.resources = ab8500_poweronkey_db_resources,
11874b106fb9SLee Jones 	},
11884b106fb9SLee Jones 	{
11894b106fb9SLee Jones 		.name = "ab8500-pwm",
11904b106fb9SLee Jones 		.id = 1,
11914b106fb9SLee Jones 	},
11924b106fb9SLee Jones 	{
11934b106fb9SLee Jones 		.name = "ab8500-leds",
11944b106fb9SLee Jones 	},
11954b106fb9SLee Jones 	{
11964b106fb9SLee Jones 		.name = "abx500-temp",
11974b106fb9SLee Jones 		.num_resources = ARRAY_SIZE(ab8500_temp_resources),
11984b106fb9SLee Jones 		.resources = ab8500_temp_resources,
11994b106fb9SLee Jones 	},
1200d6255529SLinus Walleij 	{
1201e64d905eSLee Jones 		.name = "pinctrl-ab9540",
1202e64d905eSLee Jones 		.of_compatible = "stericsson,ab9540-gpio",
1203d6255529SLinus Walleij 	},
1204d6255529SLinus Walleij 	{
1205d6255529SLinus Walleij 		.name = "ab9540-usb",
1206d6255529SLinus Walleij 		.num_resources = ARRAY_SIZE(ab8500_usb_resources),
1207d6255529SLinus Walleij 		.resources = ab8500_usb_resources,
1208d6255529SLinus Walleij 	},
120944f72e53SVirupax Sadashivpetimath 	{
121044f72e53SVirupax Sadashivpetimath 		.name = "ab9540-codec",
121144f72e53SVirupax Sadashivpetimath 	},
1212c0eda9aeSLee Jones 	{
1213c0eda9aeSLee Jones 		.name = "ab-iddet",
1214c0eda9aeSLee Jones 		.num_resources = ARRAY_SIZE(ab8505_iddet_resources),
1215c0eda9aeSLee Jones 		.resources = ab8505_iddet_resources,
1216c0eda9aeSLee Jones 	},
121744f72e53SVirupax Sadashivpetimath };
121844f72e53SVirupax Sadashivpetimath 
1219c0eda9aeSLee Jones /* Device list for ab8505  */
1220c0eda9aeSLee Jones static struct mfd_cell ab8505_devs[] = {
12214b106fb9SLee Jones #ifdef CONFIG_DEBUG_FS
12224b106fb9SLee Jones 	{
12234b106fb9SLee Jones 		.name = "ab8500-debug",
12244b106fb9SLee Jones 		.num_resources = ARRAY_SIZE(ab8500_debug_resources),
12254b106fb9SLee Jones 		.resources = ab8500_debug_resources,
12264b106fb9SLee Jones 	},
12274b106fb9SLee Jones #endif
12284b106fb9SLee Jones 	{
12294b106fb9SLee Jones 		.name = "ab8500-sysctrl",
12304b106fb9SLee Jones 	},
12314b106fb9SLee Jones 	{
12324b106fb9SLee Jones 		.name = "ab8500-regulator",
12334b106fb9SLee Jones 	},
12344b106fb9SLee Jones 	{
12354b106fb9SLee Jones 		.name = "ab8500-gpadc",
12364b106fb9SLee Jones 		.num_resources = ARRAY_SIZE(ab8505_gpadc_resources),
12374b106fb9SLee Jones 		.resources = ab8505_gpadc_resources,
12384b106fb9SLee Jones 	},
12394b106fb9SLee Jones 	{
12404b106fb9SLee Jones 		.name = "ab8500-rtc",
12414b106fb9SLee Jones 		.num_resources = ARRAY_SIZE(ab8500_rtc_resources),
12424b106fb9SLee Jones 		.resources = ab8500_rtc_resources,
12434b106fb9SLee Jones 	},
12444b106fb9SLee Jones 	{
12454b106fb9SLee Jones 		.name = "ab8500-acc-det",
12464b106fb9SLee Jones 		.num_resources = ARRAY_SIZE(ab8500_av_acc_detect_resources),
12474b106fb9SLee Jones 		.resources = ab8500_av_acc_detect_resources,
12484b106fb9SLee Jones 	},
12494b106fb9SLee Jones 	{
12504b106fb9SLee Jones 		.name = "ab8500-poweron-key",
12514b106fb9SLee Jones 		.num_resources = ARRAY_SIZE(ab8500_poweronkey_db_resources),
12524b106fb9SLee Jones 		.resources = ab8500_poweronkey_db_resources,
12534b106fb9SLee Jones 	},
12544b106fb9SLee Jones 	{
12554b106fb9SLee Jones 		.name = "ab8500-pwm",
12564b106fb9SLee Jones 		.id = 1,
12574b106fb9SLee Jones 	},
12584b106fb9SLee Jones 	{
12594b106fb9SLee Jones 		.name = "ab8500-leds",
12604b106fb9SLee Jones 	},
12614b106fb9SLee Jones 	{
12624b106fb9SLee Jones 		.name = "ab8500-gpio",
12634b106fb9SLee Jones 	},
12644b106fb9SLee Jones 	{
12654b106fb9SLee Jones 		.name = "ab8500-usb",
12664b106fb9SLee Jones 		.num_resources = ARRAY_SIZE(ab8500_usb_resources),
12674b106fb9SLee Jones 		.resources = ab8500_usb_resources,
12684b106fb9SLee Jones 	},
12694b106fb9SLee Jones 	{
12704b106fb9SLee Jones 		.name = "ab8500-codec",
12714b106fb9SLee Jones 	},
1272c0eda9aeSLee Jones 	{
1273c0eda9aeSLee Jones 		.name = "ab-iddet",
1274c0eda9aeSLee Jones 		.num_resources = ARRAY_SIZE(ab8505_iddet_resources),
1275c0eda9aeSLee Jones 		.resources = ab8505_iddet_resources,
1276c0eda9aeSLee Jones 	},
1277c0eda9aeSLee Jones };
1278c0eda9aeSLee Jones 
1279c0eda9aeSLee Jones static struct mfd_cell ab8540_devs[] = {
12804b106fb9SLee Jones #ifdef CONFIG_DEBUG_FS
12814b106fb9SLee Jones 	{
12824b106fb9SLee Jones 		.name = "ab8500-debug",
12834b106fb9SLee Jones 		.num_resources = ARRAY_SIZE(ab8500_debug_resources),
12844b106fb9SLee Jones 		.resources = ab8500_debug_resources,
12854b106fb9SLee Jones 	},
12864b106fb9SLee Jones #endif
12874b106fb9SLee Jones 	{
12884b106fb9SLee Jones 		.name = "ab8500-sysctrl",
12894b106fb9SLee Jones 	},
12904b106fb9SLee Jones 	{
12914b106fb9SLee Jones 		.name = "ab8500-regulator",
12924b106fb9SLee Jones 	},
12934b106fb9SLee Jones 	{
12944b106fb9SLee Jones 		.name = "ab8500-gpadc",
12954b106fb9SLee Jones 		.num_resources = ARRAY_SIZE(ab8505_gpadc_resources),
12964b106fb9SLee Jones 		.resources = ab8505_gpadc_resources,
12974b106fb9SLee Jones 	},
12984b106fb9SLee Jones 	{
12994b106fb9SLee Jones 		.name = "ab8500-rtc",
13004b106fb9SLee Jones 		.num_resources = ARRAY_SIZE(ab8500_rtc_resources),
13014b106fb9SLee Jones 		.resources = ab8500_rtc_resources,
13024b106fb9SLee Jones 	},
13034b106fb9SLee Jones 	{
13044b106fb9SLee Jones 		.name = "ab8500-acc-det",
13054b106fb9SLee Jones 		.num_resources = ARRAY_SIZE(ab8500_av_acc_detect_resources),
13064b106fb9SLee Jones 		.resources = ab8500_av_acc_detect_resources,
13074b106fb9SLee Jones 	},
13084b106fb9SLee Jones 	{
13094b106fb9SLee Jones 		.name = "ab8500-poweron-key",
13104b106fb9SLee Jones 		.num_resources = ARRAY_SIZE(ab8500_poweronkey_db_resources),
13114b106fb9SLee Jones 		.resources = ab8500_poweronkey_db_resources,
13124b106fb9SLee Jones 	},
13134b106fb9SLee Jones 	{
13144b106fb9SLee Jones 		.name = "ab8500-pwm",
13154b106fb9SLee Jones 		.id = 1,
13164b106fb9SLee Jones 	},
13174b106fb9SLee Jones 	{
13184b106fb9SLee Jones 		.name = "ab8500-leds",
13194b106fb9SLee Jones 	},
13204b106fb9SLee Jones 	{
13214b106fb9SLee Jones 		.name = "abx500-temp",
13224b106fb9SLee Jones 		.num_resources = ARRAY_SIZE(ab8500_temp_resources),
13234b106fb9SLee Jones 		.resources = ab8500_temp_resources,
13244b106fb9SLee Jones 	},
1325c0eda9aeSLee Jones 	{
1326c0eda9aeSLee Jones 		.name = "ab8500-gpio",
1327c0eda9aeSLee Jones 	},
1328c0eda9aeSLee Jones 	{
1329c0eda9aeSLee Jones 		.name = "ab8540-usb",
1330c0eda9aeSLee Jones 		.num_resources = ARRAY_SIZE(ab8500_usb_resources),
1331c0eda9aeSLee Jones 		.resources = ab8500_usb_resources,
1332c0eda9aeSLee Jones 	},
1333c0eda9aeSLee Jones 	{
1334c0eda9aeSLee Jones 		.name = "ab8540-codec",
1335c0eda9aeSLee Jones 	},
1336c0eda9aeSLee Jones 	{
133744f72e53SVirupax Sadashivpetimath 		.name = "ab-iddet",
133844f72e53SVirupax Sadashivpetimath 		.num_resources = ARRAY_SIZE(ab8505_iddet_resources),
133944f72e53SVirupax Sadashivpetimath 		.resources = ab8505_iddet_resources,
134044f72e53SVirupax Sadashivpetimath 	},
1341d6255529SLinus Walleij };
1342d6255529SLinus Walleij 
1343cca69b67SMattias Wallin static ssize_t show_chip_id(struct device *dev,
1344cca69b67SMattias Wallin 				struct device_attribute *attr, char *buf)
1345cca69b67SMattias Wallin {
1346cca69b67SMattias Wallin 	struct ab8500 *ab8500;
1347cca69b67SMattias Wallin 
1348cca69b67SMattias Wallin 	ab8500 = dev_get_drvdata(dev);
1349*e436ddffSLee Jones 
1350cca69b67SMattias Wallin 	return sprintf(buf, "%#x\n", ab8500 ? ab8500->chip_id : -EINVAL);
1351cca69b67SMattias Wallin }
1352cca69b67SMattias Wallin 
1353e5c238c3SMattias Wallin /*
1354e5c238c3SMattias Wallin  * ab8500 has switched off due to (SWITCH_OFF_STATUS):
1355e5c238c3SMattias Wallin  * 0x01 Swoff bit programming
1356e5c238c3SMattias Wallin  * 0x02 Thermal protection activation
1357e5c238c3SMattias Wallin  * 0x04 Vbat lower then BattOk falling threshold
1358e5c238c3SMattias Wallin  * 0x08 Watchdog expired
1359e5c238c3SMattias Wallin  * 0x10 Non presence of 32kHz clock
1360e5c238c3SMattias Wallin  * 0x20 Battery level lower than power on reset threshold
1361e5c238c3SMattias Wallin  * 0x40 Power on key 1 pressed longer than 10 seconds
1362e5c238c3SMattias Wallin  * 0x80 DB8500 thermal shutdown
1363e5c238c3SMattias Wallin  */
1364e5c238c3SMattias Wallin static ssize_t show_switch_off_status(struct device *dev,
1365e5c238c3SMattias Wallin 				struct device_attribute *attr, char *buf)
1366e5c238c3SMattias Wallin {
1367e5c238c3SMattias Wallin 	int ret;
1368e5c238c3SMattias Wallin 	u8 value;
1369e5c238c3SMattias Wallin 	struct ab8500 *ab8500;
1370e5c238c3SMattias Wallin 
1371e5c238c3SMattias Wallin 	ab8500 = dev_get_drvdata(dev);
1372e5c238c3SMattias Wallin 	ret = get_register_interruptible(ab8500, AB8500_RTC,
1373e5c238c3SMattias Wallin 		AB8500_SWITCH_OFF_STATUS, &value);
1374e5c238c3SMattias Wallin 	if (ret < 0)
1375e5c238c3SMattias Wallin 		return ret;
1376e5c238c3SMattias Wallin 	return sprintf(buf, "%#x\n", value);
1377e5c238c3SMattias Wallin }
1378e5c238c3SMattias Wallin 
1379f04a9d8aSRajkumar Kasirajan /* use mask and set to override the register turn_on_stat value */
1380f04a9d8aSRajkumar Kasirajan void ab8500_override_turn_on_stat(u8 mask, u8 set)
1381f04a9d8aSRajkumar Kasirajan {
1382f04a9d8aSRajkumar Kasirajan 	spin_lock(&on_stat_lock);
1383f04a9d8aSRajkumar Kasirajan 	turn_on_stat_mask = mask;
1384f04a9d8aSRajkumar Kasirajan 	turn_on_stat_set = set;
1385f04a9d8aSRajkumar Kasirajan 	spin_unlock(&on_stat_lock);
1386f04a9d8aSRajkumar Kasirajan }
1387f04a9d8aSRajkumar Kasirajan 
1388b4a31037SAndrew Lynn /*
1389b4a31037SAndrew Lynn  * ab8500 has turned on due to (TURN_ON_STATUS):
1390b4a31037SAndrew Lynn  * 0x01 PORnVbat
1391b4a31037SAndrew Lynn  * 0x02 PonKey1dbF
1392b4a31037SAndrew Lynn  * 0x04 PonKey2dbF
1393b4a31037SAndrew Lynn  * 0x08 RTCAlarm
1394b4a31037SAndrew Lynn  * 0x10 MainChDet
1395b4a31037SAndrew Lynn  * 0x20 VbusDet
1396b4a31037SAndrew Lynn  * 0x40 UsbIDDetect
1397b4a31037SAndrew Lynn  * 0x80 Reserved
1398b4a31037SAndrew Lynn  */
1399b4a31037SAndrew Lynn static ssize_t show_turn_on_status(struct device *dev,
1400b4a31037SAndrew Lynn 				struct device_attribute *attr, char *buf)
1401b4a31037SAndrew Lynn {
1402b4a31037SAndrew Lynn 	int ret;
1403b4a31037SAndrew Lynn 	u8 value;
1404b4a31037SAndrew Lynn 	struct ab8500 *ab8500;
1405b4a31037SAndrew Lynn 
1406b4a31037SAndrew Lynn 	ab8500 = dev_get_drvdata(dev);
1407b4a31037SAndrew Lynn 	ret = get_register_interruptible(ab8500, AB8500_SYS_CTRL1_BLOCK,
1408b4a31037SAndrew Lynn 		AB8500_TURN_ON_STATUS, &value);
1409b4a31037SAndrew Lynn 	if (ret < 0)
1410b4a31037SAndrew Lynn 		return ret;
1411f04a9d8aSRajkumar Kasirajan 
1412f04a9d8aSRajkumar Kasirajan 	/*
1413f04a9d8aSRajkumar Kasirajan 	 * In L9540, turn_on_status register is not updated correctly if
1414f04a9d8aSRajkumar Kasirajan 	 * the device is rebooted with AC/USB charger connected. Due to
1415f04a9d8aSRajkumar Kasirajan 	 * this, the device boots android instead of entering into charge
1416f04a9d8aSRajkumar Kasirajan 	 * only mode. Read the AC/USB status register to detect the charger
1417f04a9d8aSRajkumar Kasirajan 	 * presence and update the turn on status manually.
1418f04a9d8aSRajkumar Kasirajan 	 */
1419f04a9d8aSRajkumar Kasirajan 	if (is_ab9540(ab8500)) {
1420f04a9d8aSRajkumar Kasirajan 		spin_lock(&on_stat_lock);
1421f04a9d8aSRajkumar Kasirajan 		value = (value & turn_on_stat_mask) | turn_on_stat_set;
1422f04a9d8aSRajkumar Kasirajan 		spin_unlock(&on_stat_lock);
1423f04a9d8aSRajkumar Kasirajan 	}
1424f04a9d8aSRajkumar Kasirajan 
1425b4a31037SAndrew Lynn 	return sprintf(buf, "%#x\n", value);
1426b4a31037SAndrew Lynn }
1427b4a31037SAndrew Lynn 
1428d6255529SLinus Walleij static ssize_t show_ab9540_dbbrstn(struct device *dev,
1429d6255529SLinus Walleij 				struct device_attribute *attr, char *buf)
1430d6255529SLinus Walleij {
1431d6255529SLinus Walleij 	struct ab8500 *ab8500;
1432d6255529SLinus Walleij 	int ret;
1433d6255529SLinus Walleij 	u8 value;
1434d6255529SLinus Walleij 
1435d6255529SLinus Walleij 	ab8500 = dev_get_drvdata(dev);
1436d6255529SLinus Walleij 
1437d6255529SLinus Walleij 	ret = get_register_interruptible(ab8500, AB8500_REGU_CTRL2,
1438d6255529SLinus Walleij 		AB9540_MODEM_CTRL2_REG, &value);
1439d6255529SLinus Walleij 	if (ret < 0)
1440d6255529SLinus Walleij 		return ret;
1441d6255529SLinus Walleij 
1442d6255529SLinus Walleij 	return sprintf(buf, "%d\n",
1443d6255529SLinus Walleij 			(value & AB9540_MODEM_CTRL2_SWDBBRSTN_BIT) ? 1 : 0);
1444d6255529SLinus Walleij }
1445d6255529SLinus Walleij 
1446d6255529SLinus Walleij static ssize_t store_ab9540_dbbrstn(struct device *dev,
1447d6255529SLinus Walleij 	struct device_attribute *attr, const char *buf, size_t count)
1448d6255529SLinus Walleij {
1449d6255529SLinus Walleij 	struct ab8500 *ab8500;
1450d6255529SLinus Walleij 	int ret = count;
1451d6255529SLinus Walleij 	int err;
1452d6255529SLinus Walleij 	u8 bitvalues;
1453d6255529SLinus Walleij 
1454d6255529SLinus Walleij 	ab8500 = dev_get_drvdata(dev);
1455d6255529SLinus Walleij 
1456d6255529SLinus Walleij 	if (count > 0) {
1457d6255529SLinus Walleij 		switch (buf[0]) {
1458d6255529SLinus Walleij 		case '0':
1459d6255529SLinus Walleij 			bitvalues = 0;
1460d6255529SLinus Walleij 			break;
1461d6255529SLinus Walleij 		case '1':
1462d6255529SLinus Walleij 			bitvalues = AB9540_MODEM_CTRL2_SWDBBRSTN_BIT;
1463d6255529SLinus Walleij 			break;
1464d6255529SLinus Walleij 		default:
1465d6255529SLinus Walleij 			goto exit;
1466d6255529SLinus Walleij 		}
1467d6255529SLinus Walleij 
1468d6255529SLinus Walleij 		err = mask_and_set_register_interruptible(ab8500,
1469d6255529SLinus Walleij 			AB8500_REGU_CTRL2, AB9540_MODEM_CTRL2_REG,
1470d6255529SLinus Walleij 			AB9540_MODEM_CTRL2_SWDBBRSTN_BIT, bitvalues);
1471d6255529SLinus Walleij 		if (err)
1472d6255529SLinus Walleij 			dev_info(ab8500->dev,
1473d6255529SLinus Walleij 				"Failed to set DBBRSTN %c, err %#x\n",
1474d6255529SLinus Walleij 				buf[0], err);
1475d6255529SLinus Walleij 	}
1476d6255529SLinus Walleij 
1477d6255529SLinus Walleij exit:
1478d6255529SLinus Walleij 	return ret;
1479d6255529SLinus Walleij }
1480d6255529SLinus Walleij 
1481cca69b67SMattias Wallin static DEVICE_ATTR(chip_id, S_IRUGO, show_chip_id, NULL);
1482e5c238c3SMattias Wallin static DEVICE_ATTR(switch_off_status, S_IRUGO, show_switch_off_status, NULL);
1483b4a31037SAndrew Lynn static DEVICE_ATTR(turn_on_status, S_IRUGO, show_turn_on_status, NULL);
1484d6255529SLinus Walleij static DEVICE_ATTR(dbbrstn, S_IRUGO | S_IWUSR,
1485d6255529SLinus Walleij 			show_ab9540_dbbrstn, store_ab9540_dbbrstn);
1486cca69b67SMattias Wallin 
1487cca69b67SMattias Wallin static struct attribute *ab8500_sysfs_entries[] = {
1488cca69b67SMattias Wallin 	&dev_attr_chip_id.attr,
1489e5c238c3SMattias Wallin 	&dev_attr_switch_off_status.attr,
1490b4a31037SAndrew Lynn 	&dev_attr_turn_on_status.attr,
1491cca69b67SMattias Wallin 	NULL,
1492cca69b67SMattias Wallin };
1493cca69b67SMattias Wallin 
1494d6255529SLinus Walleij static struct attribute *ab9540_sysfs_entries[] = {
1495d6255529SLinus Walleij 	&dev_attr_chip_id.attr,
1496d6255529SLinus Walleij 	&dev_attr_switch_off_status.attr,
1497d6255529SLinus Walleij 	&dev_attr_turn_on_status.attr,
1498d6255529SLinus Walleij 	&dev_attr_dbbrstn.attr,
1499d6255529SLinus Walleij 	NULL,
1500d6255529SLinus Walleij };
1501d6255529SLinus Walleij 
1502cca69b67SMattias Wallin static struct attribute_group ab8500_attr_group = {
1503cca69b67SMattias Wallin 	.attrs	= ab8500_sysfs_entries,
1504cca69b67SMattias Wallin };
1505cca69b67SMattias Wallin 
1506d6255529SLinus Walleij static struct attribute_group ab9540_attr_group = {
1507d6255529SLinus Walleij 	.attrs	= ab9540_sysfs_entries,
1508d6255529SLinus Walleij };
1509d6255529SLinus Walleij 
1510f791be49SBill Pemberton static int ab8500_probe(struct platform_device *pdev)
151162579266SRabin Vincent {
1512b04c530cSJonas Aaberg 	static char *switch_off_status[] = {
1513b04c530cSJonas Aaberg 		"Swoff bit programming",
1514b04c530cSJonas Aaberg 		"Thermal protection activation",
1515b04c530cSJonas Aaberg 		"Vbat lower then BattOk falling threshold",
1516b04c530cSJonas Aaberg 		"Watchdog expired",
1517b04c530cSJonas Aaberg 		"Non presence of 32kHz clock",
1518b04c530cSJonas Aaberg 		"Battery level lower than power on reset threshold",
1519b04c530cSJonas Aaberg 		"Power on key 1 pressed longer than 10 seconds",
1520b04c530cSJonas Aaberg 		"DB8500 thermal shutdown"};
1521d28f1db8SLee Jones 	struct ab8500_platform_data *plat = dev_get_platdata(&pdev->dev);
1522d28f1db8SLee Jones 	const struct platform_device_id *platid = platform_get_device_id(pdev);
15236bc4a568SLee Jones 	enum ab8500_version version = AB8500_VERSION_UNDEFINED;
15246bc4a568SLee Jones 	struct device_node *np = pdev->dev.of_node;
1525d28f1db8SLee Jones 	struct ab8500 *ab8500;
1526d28f1db8SLee Jones 	struct resource *resource;
152762579266SRabin Vincent 	int ret;
152862579266SRabin Vincent 	int i;
152947c16975SMattias Wallin 	u8 value;
153062579266SRabin Vincent 
15318c4203cbSLee Jones 	ab8500 = devm_kzalloc(&pdev->dev, sizeof *ab8500, GFP_KERNEL);
1532d28f1db8SLee Jones 	if (!ab8500)
1533d28f1db8SLee Jones 		return -ENOMEM;
1534d28f1db8SLee Jones 
153562579266SRabin Vincent 	if (plat)
153662579266SRabin Vincent 		ab8500->irq_base = plat->irq_base;
153762579266SRabin Vincent 
1538d28f1db8SLee Jones 	ab8500->dev = &pdev->dev;
1539d28f1db8SLee Jones 
1540d28f1db8SLee Jones 	resource = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
15418c4203cbSLee Jones 	if (!resource)
15428c4203cbSLee Jones 		return -ENODEV;
1543d28f1db8SLee Jones 
1544d28f1db8SLee Jones 	ab8500->irq = resource->start;
1545d28f1db8SLee Jones 
1546822672a7SLee Jones 	ab8500->read = ab8500_prcmu_read;
1547822672a7SLee Jones 	ab8500->write = ab8500_prcmu_write;
1548822672a7SLee Jones 	ab8500->write_masked = ab8500_prcmu_write_masked;
1549d28f1db8SLee Jones 
155062579266SRabin Vincent 	mutex_init(&ab8500->lock);
155162579266SRabin Vincent 	mutex_init(&ab8500->irq_lock);
1552112a80d2SJonas Aaberg 	atomic_set(&ab8500->transfer_ongoing, 0);
155362579266SRabin Vincent 
1554d28f1db8SLee Jones 	platform_set_drvdata(pdev, ab8500);
1555d28f1db8SLee Jones 
15566bc4a568SLee Jones 	if (platid)
15576bc4a568SLee Jones 		version = platid->driver_data;
15586bc4a568SLee Jones 
15590f620837SLinus Walleij 	if (version != AB8500_VERSION_UNDEFINED)
15600f620837SLinus Walleij 		ab8500->version = version;
15610f620837SLinus Walleij 	else {
15620f620837SLinus Walleij 		ret = get_register_interruptible(ab8500, AB8500_MISC,
15630f620837SLinus Walleij 			AB8500_IC_NAME_REG, &value);
15640f620837SLinus Walleij 		if (ret < 0)
15658c4203cbSLee Jones 			return ret;
15660f620837SLinus Walleij 
15670f620837SLinus Walleij 		ab8500->version = value;
15680f620837SLinus Walleij 	}
15690f620837SLinus Walleij 
157047c16975SMattias Wallin 	ret = get_register_interruptible(ab8500, AB8500_MISC,
157147c16975SMattias Wallin 		AB8500_REV_REG, &value);
157262579266SRabin Vincent 	if (ret < 0)
15738c4203cbSLee Jones 		return ret;
157462579266SRabin Vincent 
157547c16975SMattias Wallin 	ab8500->chip_id = value;
157662579266SRabin Vincent 
15770f620837SLinus Walleij 	dev_info(ab8500->dev, "detected chip, %s rev. %1x.%1x\n",
15780f620837SLinus Walleij 			ab8500_version_str[ab8500->version],
15790f620837SLinus Walleij 			ab8500->chip_id >> 4,
15800f620837SLinus Walleij 			ab8500->chip_id & 0x0F);
15810f620837SLinus Walleij 
15823e1a498fSLee Jones 	/* Configure AB8540 */
15833e1a498fSLee Jones 	if (is_ab8540(ab8500)) {
15843e1a498fSLee Jones 		ab8500->mask_size = AB8540_NUM_IRQ_REGS;
15853e1a498fSLee Jones 		ab8500->irq_reg_offset = ab8540_irq_regoffset;
15863e1a498fSLee Jones 		ab8500->it_latchhier_num = AB8540_IT_LATCHHIER_NUM;
15873e1a498fSLee Jones 	}/* Configure AB8500 or AB9540 IRQ */
15883e1a498fSLee Jones 	else if (is_ab9540(ab8500) || is_ab8505(ab8500)) {
1589d6255529SLinus Walleij 		ab8500->mask_size = AB9540_NUM_IRQ_REGS;
1590d6255529SLinus Walleij 		ab8500->irq_reg_offset = ab9540_irq_regoffset;
15913e1a498fSLee Jones 		ab8500->it_latchhier_num = AB8500_IT_LATCHHIER_NUM;
1592d6255529SLinus Walleij 	} else {
15932ced445eSLinus Walleij 		ab8500->mask_size = AB8500_NUM_IRQ_REGS;
15942ced445eSLinus Walleij 		ab8500->irq_reg_offset = ab8500_irq_regoffset;
15953e1a498fSLee Jones 		ab8500->it_latchhier_num = AB8500_IT_LATCHHIER_NUM;
1596d6255529SLinus Walleij 	}
15978c4203cbSLee Jones 	ab8500->mask = devm_kzalloc(&pdev->dev, ab8500->mask_size, GFP_KERNEL);
15982ced445eSLinus Walleij 	if (!ab8500->mask)
15992ced445eSLinus Walleij 		return -ENOMEM;
16008c4203cbSLee Jones 	ab8500->oldmask = devm_kzalloc(&pdev->dev, ab8500->mask_size, GFP_KERNEL);
16018c4203cbSLee Jones 	if (!ab8500->oldmask)
16028c4203cbSLee Jones 		return -ENOMEM;
16038c4203cbSLee Jones 
1604e5c238c3SMattias Wallin 	/*
1605e5c238c3SMattias Wallin 	 * ab8500 has switched off due to (SWITCH_OFF_STATUS):
1606e5c238c3SMattias Wallin 	 * 0x01 Swoff bit programming
1607e5c238c3SMattias Wallin 	 * 0x02 Thermal protection activation
1608e5c238c3SMattias Wallin 	 * 0x04 Vbat lower then BattOk falling threshold
1609e5c238c3SMattias Wallin 	 * 0x08 Watchdog expired
1610e5c238c3SMattias Wallin 	 * 0x10 Non presence of 32kHz clock
1611e5c238c3SMattias Wallin 	 * 0x20 Battery level lower than power on reset threshold
1612e5c238c3SMattias Wallin 	 * 0x40 Power on key 1 pressed longer than 10 seconds
1613e5c238c3SMattias Wallin 	 * 0x80 DB8500 thermal shutdown
1614e5c238c3SMattias Wallin 	 */
1615e5c238c3SMattias Wallin 
1616e5c238c3SMattias Wallin 	ret = get_register_interruptible(ab8500, AB8500_RTC,
1617e5c238c3SMattias Wallin 		AB8500_SWITCH_OFF_STATUS, &value);
1618e5c238c3SMattias Wallin 	if (ret < 0)
1619e5c238c3SMattias Wallin 		return ret;
1620b04c530cSJonas Aaberg 	dev_info(ab8500->dev, "switch off cause(s) (%#x): ", value);
1621b04c530cSJonas Aaberg 
1622b04c530cSJonas Aaberg 	if (value) {
1623b04c530cSJonas Aaberg 		for (i = 0; i < ARRAY_SIZE(switch_off_status); i++) {
1624b04c530cSJonas Aaberg 			if (value & 1)
1625b04c530cSJonas Aaberg 				printk(KERN_CONT " \"%s\"",
1626b04c530cSJonas Aaberg 				       switch_off_status[i]);
1627b04c530cSJonas Aaberg 			value = value >> 1;
1628b04c530cSJonas Aaberg 
1629b04c530cSJonas Aaberg 		}
1630b04c530cSJonas Aaberg 		printk(KERN_CONT "\n");
1631b04c530cSJonas Aaberg 	} else {
1632b04c530cSJonas Aaberg 		printk(KERN_CONT " None\n");
1633b04c530cSJonas Aaberg 	}
1634e5c238c3SMattias Wallin 
163562579266SRabin Vincent 	if (plat && plat->init)
163662579266SRabin Vincent 		plat->init(ab8500);
1637f04a9d8aSRajkumar Kasirajan 	if (is_ab9540(ab8500)) {
1638f04a9d8aSRajkumar Kasirajan 		ret = get_register_interruptible(ab8500, AB8500_CHARGER,
1639f04a9d8aSRajkumar Kasirajan 			AB8500_CH_USBCH_STAT1_REG, &value);
1640f04a9d8aSRajkumar Kasirajan 		if (ret < 0)
1641f04a9d8aSRajkumar Kasirajan 			return ret;
1642f04a9d8aSRajkumar Kasirajan 		if ((value & VBUS_DET_DBNC1) && (value & VBUS_DET_DBNC100))
1643f04a9d8aSRajkumar Kasirajan 			ab8500_override_turn_on_stat(~AB8500_POW_KEY_1_ON,
1644f04a9d8aSRajkumar Kasirajan 						     AB8500_VBUS_DET);
1645f04a9d8aSRajkumar Kasirajan 	}
164662579266SRabin Vincent 
164762579266SRabin Vincent 	/* Clear and mask all interrupts */
16482ced445eSLinus Walleij 	for (i = 0; i < ab8500->mask_size; i++) {
16490f620837SLinus Walleij 		/*
16500f620837SLinus Walleij 		 * Interrupt register 12 doesn't exist prior to AB8500 version
16510f620837SLinus Walleij 		 * 2.0
16520f620837SLinus Walleij 		 */
16530f620837SLinus Walleij 		if (ab8500->irq_reg_offset[i] == 11 &&
16540f620837SLinus Walleij 				is_ab8500_1p1_or_earlier(ab8500))
165592d50a41SMattias Wallin 			continue;
165662579266SRabin Vincent 
16573e1a498fSLee Jones 		if (ab8500->irq_reg_offset[i] < 0)
16583e1a498fSLee Jones 			continue;
16593e1a498fSLee Jones 
166047c16975SMattias Wallin 		get_register_interruptible(ab8500, AB8500_INTERRUPT,
16612ced445eSLinus Walleij 			AB8500_IT_LATCH1_REG + ab8500->irq_reg_offset[i],
166292d50a41SMattias Wallin 			&value);
166347c16975SMattias Wallin 		set_register_interruptible(ab8500, AB8500_INTERRUPT,
16642ced445eSLinus Walleij 			AB8500_IT_MASK1_REG + ab8500->irq_reg_offset[i], 0xff);
166562579266SRabin Vincent 	}
166662579266SRabin Vincent 
166747c16975SMattias Wallin 	ret = abx500_register_ops(ab8500->dev, &ab8500_ops);
166847c16975SMattias Wallin 	if (ret)
16698c4203cbSLee Jones 		return ret;
167047c16975SMattias Wallin 
16712ced445eSLinus Walleij 	for (i = 0; i < ab8500->mask_size; i++)
167262579266SRabin Vincent 		ab8500->mask[i] = ab8500->oldmask[i] = 0xff;
167362579266SRabin Vincent 
167406e589efSLee Jones 	ret = ab8500_irq_init(ab8500, np);
167562579266SRabin Vincent 	if (ret)
16768c4203cbSLee Jones 		return ret;
167762579266SRabin Vincent 
16787ccfe9b1SMichel JAOUEN 	/*  Activate this feature only in ab9540 */
16797ccfe9b1SMichel JAOUEN 	/*  till tests are done on ab8500 1p2 or later*/
1680*e436ddffSLee Jones 	if (is_ab9540(ab8500) || is_ab8540(ab8500))
16818c4203cbSLee Jones 		ret = devm_request_threaded_irq(&pdev->dev, ab8500->irq, NULL,
16827ccfe9b1SMichel JAOUEN 						ab8500_hierarchical_irq,
16837ccfe9b1SMichel JAOUEN 						IRQF_ONESHOT | IRQF_NO_SUSPEND,
16847ccfe9b1SMichel JAOUEN 						"ab8500", ab8500);
168506e589efSLee Jones 	}
168606e589efSLee Jones 	else {
16878c4203cbSLee Jones 		ret = devm_request_threaded_irq(&pdev->dev, ab8500->irq, NULL,
16887ccfe9b1SMichel JAOUEN 						ab8500_irq,
16894f079985SMattias Wallin 						IRQF_ONESHOT | IRQF_NO_SUSPEND,
16904f079985SMattias Wallin 						"ab8500", ab8500);
169162579266SRabin Vincent 		if (ret)
16928c4203cbSLee Jones 			return ret;
169362579266SRabin Vincent 	}
169462579266SRabin Vincent 
1695d6255529SLinus Walleij 	if (is_ab9540(ab8500))
1696d6255529SLinus Walleij 		ret = mfd_add_devices(ab8500->dev, 0, ab9540_devs,
1697d6255529SLinus Walleij 				ARRAY_SIZE(ab9540_devs), NULL,
169855692af5SMark Brown 				ab8500->irq_base, ab8500->domain);
1699c0eda9aeSLee Jones 	else if (is_ab8540(ab8500))
1700c0eda9aeSLee Jones 		ret = mfd_add_devices(ab8500->dev, 0, ab8540_devs,
1701c0eda9aeSLee Jones 			      ARRAY_SIZE(ab8540_devs), NULL,
1702c0eda9aeSLee Jones 			      ab8500->irq_base, ab8500->domain);
1703c0eda9aeSLee Jones 	else if (is_ab8505(ab8500))
1704c0eda9aeSLee Jones 		ret = mfd_add_devices(ab8500->dev, 0, ab8505_devs,
1705c0eda9aeSLee Jones 			      ARRAY_SIZE(ab8505_devs), NULL,
1706c0eda9aeSLee Jones 			      ab8500->irq_base, ab8500->domain);
1707d6255529SLinus Walleij 	else
1708549931f9SSundar R Iyer 		ret = mfd_add_devices(ab8500->dev, 0, ab8500_devs,
170944f72e53SVirupax Sadashivpetimath 				ARRAY_SIZE(ab8500_devs), NULL,
171055692af5SMark Brown 				ab8500->irq_base, ab8500->domain);
17116bc4a568SLee Jones 	if (ret)
17128c4203cbSLee Jones 		return ret;
171344f72e53SVirupax Sadashivpetimath 
17146ef9418cSRickard Andersson 	if (!no_bm) {
17156ef9418cSRickard Andersson 		/* Add battery management devices */
17166ef9418cSRickard Andersson 		ret = mfd_add_devices(ab8500->dev, 0, ab8500_bm_devs,
17176ef9418cSRickard Andersson 				      ARRAY_SIZE(ab8500_bm_devs), NULL,
171855692af5SMark Brown 				      ab8500->irq_base, ab8500->domain);
17196ef9418cSRickard Andersson 		if (ret)
17206ef9418cSRickard Andersson 			dev_err(ab8500->dev, "error adding bm devices\n");
17216ef9418cSRickard Andersson 	}
17226ef9418cSRickard Andersson 
1723*e436ddffSLee Jones 	if (((is_ab8505(ab8500) || is_ab9540(ab8500)) &&
1724*e436ddffSLee Jones 			ab8500->chip_id >= AB8500_CUT2P0) || is_ab8540(ab8500))
1725d6255529SLinus Walleij 		ret = sysfs_create_group(&ab8500->dev->kobj,
1726d6255529SLinus Walleij 					&ab9540_attr_group);
1727d6255529SLinus Walleij 	else
1728d6255529SLinus Walleij 		ret = sysfs_create_group(&ab8500->dev->kobj,
1729d6255529SLinus Walleij 					&ab8500_attr_group);
1730cca69b67SMattias Wallin 	if (ret)
1731cca69b67SMattias Wallin 		dev_err(ab8500->dev, "error creating sysfs entries\n");
173206e589efSLee Jones 
173362579266SRabin Vincent 	return ret;
173462579266SRabin Vincent }
173562579266SRabin Vincent 
17364740f73fSBill Pemberton static int ab8500_remove(struct platform_device *pdev)
173762579266SRabin Vincent {
1738d28f1db8SLee Jones 	struct ab8500 *ab8500 = platform_get_drvdata(pdev);
1739d28f1db8SLee Jones 
1740*e436ddffSLee Jones 	if (((is_ab8505(ab8500) || is_ab9540(ab8500)) &&
1741*e436ddffSLee Jones 			ab8500->chip_id >= AB8500_CUT2P0) || is_ab8540(ab8500))
1742d6255529SLinus Walleij 		sysfs_remove_group(&ab8500->dev->kobj, &ab9540_attr_group);
1743d6255529SLinus Walleij 	else
1744cca69b67SMattias Wallin 		sysfs_remove_group(&ab8500->dev->kobj, &ab8500_attr_group);
174506e589efSLee Jones 
174662579266SRabin Vincent 	mfd_remove_devices(ab8500->dev);
174762579266SRabin Vincent 
174862579266SRabin Vincent 	return 0;
174962579266SRabin Vincent }
175062579266SRabin Vincent 
1751d28f1db8SLee Jones static const struct platform_device_id ab8500_id[] = {
1752d28f1db8SLee Jones 	{ "ab8500-core", AB8500_VERSION_AB8500 },
1753d28f1db8SLee Jones 	{ "ab8505-i2c", AB8500_VERSION_AB8505 },
1754d28f1db8SLee Jones 	{ "ab9540-i2c", AB8500_VERSION_AB9540 },
1755d28f1db8SLee Jones 	{ "ab8540-i2c", AB8500_VERSION_AB8540 },
1756d28f1db8SLee Jones 	{ }
1757d28f1db8SLee Jones };
1758d28f1db8SLee Jones 
1759d28f1db8SLee Jones static struct platform_driver ab8500_core_driver = {
1760d28f1db8SLee Jones 	.driver = {
1761d28f1db8SLee Jones 		.name = "ab8500-core",
1762d28f1db8SLee Jones 		.owner = THIS_MODULE,
1763d28f1db8SLee Jones 	},
1764d28f1db8SLee Jones 	.probe	= ab8500_probe,
176584449216SBill Pemberton 	.remove	= ab8500_remove,
1766d28f1db8SLee Jones 	.id_table = ab8500_id,
1767d28f1db8SLee Jones };
1768d28f1db8SLee Jones 
1769d28f1db8SLee Jones static int __init ab8500_core_init(void)
1770d28f1db8SLee Jones {
1771d28f1db8SLee Jones 	return platform_driver_register(&ab8500_core_driver);
1772d28f1db8SLee Jones }
1773d28f1db8SLee Jones 
1774d28f1db8SLee Jones static void __exit ab8500_core_exit(void)
1775d28f1db8SLee Jones {
1776d28f1db8SLee Jones 	platform_driver_unregister(&ab8500_core_driver);
1777d28f1db8SLee Jones }
1778ba7cbc3eSLee Jones core_initcall(ab8500_core_init);
1779d28f1db8SLee Jones module_exit(ab8500_core_exit);
1780d28f1db8SLee Jones 
1781adceed62SMattias Wallin MODULE_AUTHOR("Mattias Wallin, Srinidhi Kasagar, Rabin Vincent");
178262579266SRabin Vincent MODULE_DESCRIPTION("AB8500 MFD core");
178362579266SRabin Vincent MODULE_LICENSE("GPL v2");
1784