blob: baaf2ed8095b68fe48c31495323239d3ba922fdc [file] [log] [blame]
Rabin Vincent62579262010-05-19 11:39:02 +02001/*
2 * Copyright (C) ST-Ericsson SA 2010
3 *
4 * License Terms: GNU General Public License v2
5 * Author: Srinidhi Kasagar <srinidhi.kasagar@stericsson.com>
6 * Author: Rabin Vincent <rabin.vincent@stericsson.com>
Mattias Wallinadceed62011-03-02 11:51:11 +01007 * Author: Mattias Wallin <mattias.wallin@stericsson.com>
Rabin Vincent62579262010-05-19 11:39:02 +02008 */
9
10#include <linux/kernel.h>
11#include <linux/slab.h>
12#include <linux/init.h>
13#include <linux/irq.h>
Lee Jones06e589e2012-06-20 13:56:37 +010014#include <linux/irqdomain.h>
Rabin Vincent62579262010-05-19 11:39:02 +020015#include <linux/delay.h>
16#include <linux/interrupt.h>
17#include <linux/module.h>
18#include <linux/platform_device.h>
19#include <linux/mfd/core.h>
Mattias Wallin47c16972010-09-10 17:47:56 +020020#include <linux/mfd/abx500.h>
Linus Walleijee66e652011-12-02 14:16:33 +010021#include <linux/mfd/abx500/ab8500.h>
Lee Jones00441b52013-01-09 10:06:03 +000022#include <linux/mfd/abx500/ab8500-bm.h>
Lee Jonesd28f1db2012-05-19 17:21:37 +020023#include <linux/mfd/dbx500-prcmu.h>
Sundar R Iyer549931f2010-07-13 11:51:28 +053024#include <linux/regulator/ab8500.h>
Lee Jones6bc4a562012-05-17 14:45:13 +010025#include <linux/of.h>
26#include <linux/of_device.h>
Rabin Vincent62579262010-05-19 11:39:02 +020027
28/*
29 * Interrupt register offsets
30 * Bank : 0x0E
31 */
Mattias Wallin47c16972010-09-10 17:47:56 +020032#define AB8500_IT_SOURCE1_REG 0x00
33#define AB8500_IT_SOURCE2_REG 0x01
34#define AB8500_IT_SOURCE3_REG 0x02
35#define AB8500_IT_SOURCE4_REG 0x03
36#define AB8500_IT_SOURCE5_REG 0x04
37#define AB8500_IT_SOURCE6_REG 0x05
38#define AB8500_IT_SOURCE7_REG 0x06
39#define AB8500_IT_SOURCE8_REG 0x07
Linus Walleijd6255522012-02-20 21:42:24 +010040#define AB9540_IT_SOURCE13_REG 0x0C
Mattias Wallin47c16972010-09-10 17:47:56 +020041#define AB8500_IT_SOURCE19_REG 0x12
42#define AB8500_IT_SOURCE20_REG 0x13
43#define AB8500_IT_SOURCE21_REG 0x14
44#define AB8500_IT_SOURCE22_REG 0x15
45#define AB8500_IT_SOURCE23_REG 0x16
46#define AB8500_IT_SOURCE24_REG 0x17
Rabin Vincent62579262010-05-19 11:39:02 +020047
48/*
49 * latch registers
50 */
Mattias Wallin47c16972010-09-10 17:47:56 +020051#define AB8500_IT_LATCH1_REG 0x20
52#define AB8500_IT_LATCH2_REG 0x21
53#define AB8500_IT_LATCH3_REG 0x22
54#define AB8500_IT_LATCH4_REG 0x23
55#define AB8500_IT_LATCH5_REG 0x24
56#define AB8500_IT_LATCH6_REG 0x25
57#define AB8500_IT_LATCH7_REG 0x26
58#define AB8500_IT_LATCH8_REG 0x27
59#define AB8500_IT_LATCH9_REG 0x28
60#define AB8500_IT_LATCH10_REG 0x29
Mattias Wallin92d50a42010-12-07 11:20:47 +010061#define AB8500_IT_LATCH12_REG 0x2B
Linus Walleijd6255522012-02-20 21:42:24 +010062#define AB9540_IT_LATCH13_REG 0x2C
Mattias Wallin47c16972010-09-10 17:47:56 +020063#define AB8500_IT_LATCH19_REG 0x32
64#define AB8500_IT_LATCH20_REG 0x33
65#define AB8500_IT_LATCH21_REG 0x34
66#define AB8500_IT_LATCH22_REG 0x35
67#define AB8500_IT_LATCH23_REG 0x36
68#define AB8500_IT_LATCH24_REG 0x37
Rabin Vincent62579262010-05-19 11:39:02 +020069
70/*
71 * mask registers
72 */
73
Mattias Wallin47c16972010-09-10 17:47:56 +020074#define AB8500_IT_MASK1_REG 0x40
75#define AB8500_IT_MASK2_REG 0x41
76#define AB8500_IT_MASK3_REG 0x42
77#define AB8500_IT_MASK4_REG 0x43
78#define AB8500_IT_MASK5_REG 0x44
79#define AB8500_IT_MASK6_REG 0x45
80#define AB8500_IT_MASK7_REG 0x46
81#define AB8500_IT_MASK8_REG 0x47
82#define AB8500_IT_MASK9_REG 0x48
83#define AB8500_IT_MASK10_REG 0x49
84#define AB8500_IT_MASK11_REG 0x4A
85#define AB8500_IT_MASK12_REG 0x4B
86#define AB8500_IT_MASK13_REG 0x4C
87#define AB8500_IT_MASK14_REG 0x4D
88#define AB8500_IT_MASK15_REG 0x4E
89#define AB8500_IT_MASK16_REG 0x4F
90#define AB8500_IT_MASK17_REG 0x50
91#define AB8500_IT_MASK18_REG 0x51
92#define AB8500_IT_MASK19_REG 0x52
93#define AB8500_IT_MASK20_REG 0x53
94#define AB8500_IT_MASK21_REG 0x54
95#define AB8500_IT_MASK22_REG 0x55
96#define AB8500_IT_MASK23_REG 0x56
97#define AB8500_IT_MASK24_REG 0x57
Lee Jonesa29264b2013-02-25 14:34:26 +000098#define AB8500_IT_MASK25_REG 0x58
Rabin Vincent62579262010-05-19 11:39:02 +020099
Michel JAOUEN7ccfe9b2012-05-07 15:02:03 +0200100/*
101 * latch hierarchy registers
102 */
103#define AB8500_IT_LATCHHIER1_REG 0x60
104#define AB8500_IT_LATCHHIER2_REG 0x61
105#define AB8500_IT_LATCHHIER3_REG 0x62
106
107#define AB8500_IT_LATCHHIER_NUM 3
108
Mattias Wallin47c16972010-09-10 17:47:56 +0200109#define AB8500_REV_REG 0x80
Linus Walleij0f6208372012-02-20 21:42:10 +0100110#define AB8500_IC_NAME_REG 0x82
Mattias Walline5c238c2011-03-02 11:52:36 +0100111#define AB8500_SWITCH_OFF_STATUS 0x00
Rabin Vincent62579262010-05-19 11:39:02 +0200112
Andrew Lynnb4a31032011-10-11 10:49:47 +0200113#define AB8500_TURN_ON_STATUS 0x00
114
Rajkumar Kasirajanf04a9d82012-05-30 16:32:37 +0530115#define AB8500_CH_USBCH_STAT1_REG 0x02
116#define VBUS_DET_DBNC100 0x02
117#define VBUS_DET_DBNC1 0x01
118
119static DEFINE_SPINLOCK(on_stat_lock);
120static u8 turn_on_stat_mask = 0xFF;
121static u8 turn_on_stat_set;
Rickard Andersson6ef94182012-04-17 09:30:57 +0200122static bool no_bm; /* No battery management */
123module_param(no_bm, bool, S_IRUGO);
124
Linus Walleijd6255522012-02-20 21:42:24 +0100125#define AB9540_MODEM_CTRL2_REG 0x23
126#define AB9540_MODEM_CTRL2_SWDBBRSTN_BIT BIT(2)
127
Rabin Vincent62579262010-05-19 11:39:02 +0200128/*
129 * Map interrupt numbers to the LATCH and MASK register offsets, Interrupt
Linus Walleij2ced4452012-02-20 21:42:17 +0100130 * numbers are indexed into this array with (num / 8). The interupts are
131 * defined in linux/mfd/ab8500.h
Rabin Vincent62579262010-05-19 11:39:02 +0200132 *
133 * This is one off from the register names, i.e. AB8500_IT_MASK1_REG is at
134 * offset 0.
135 */
Linus Walleij2ced4452012-02-20 21:42:17 +0100136/* AB8500 support */
Rabin Vincent62579262010-05-19 11:39:02 +0200137static const int ab8500_irq_regoffset[AB8500_NUM_IRQ_REGS] = {
Mattias Wallin92d50a42010-12-07 11:20:47 +0100138 0, 1, 2, 3, 4, 6, 7, 8, 9, 11, 18, 19, 20, 21,
Rabin Vincent62579262010-05-19 11:39:02 +0200139};
140
Lee Jonesa29264b2013-02-25 14:34:26 +0000141/* AB9540 / AB8505 support */
Linus Walleijd6255522012-02-20 21:42:24 +0100142static const int ab9540_irq_regoffset[AB9540_NUM_IRQ_REGS] = {
Lee Jonesa29264b2013-02-25 14:34:26 +0000143 0, 1, 2, 3, 4, 6, 7, 8, 9, 11, 18, 19, 20, 21, 12, 13, 24, 5, 22, 23
Linus Walleijd6255522012-02-20 21:42:24 +0100144};
145
Linus Walleij0f6208372012-02-20 21:42:10 +0100146static const char ab8500_version_str[][7] = {
147 [AB8500_VERSION_AB8500] = "AB8500",
148 [AB8500_VERSION_AB8505] = "AB8505",
149 [AB8500_VERSION_AB9540] = "AB9540",
150 [AB8500_VERSION_AB8540] = "AB8540",
151};
152
Lee Jones822672a2012-06-20 13:56:38 +0100153static int ab8500_prcmu_write(struct ab8500 *ab8500, u16 addr, u8 data)
Lee Jonesd28f1db2012-05-19 17:21:37 +0200154{
155 int ret;
156
157 ret = prcmu_abb_write((u8)(addr >> 8), (u8)(addr & 0xFF), &data, 1);
158 if (ret < 0)
159 dev_err(ab8500->dev, "prcmu i2c error %d\n", ret);
160 return ret;
161}
162
Lee Jones822672a2012-06-20 13:56:38 +0100163static int ab8500_prcmu_write_masked(struct ab8500 *ab8500, u16 addr, u8 mask,
Lee Jonesd28f1db2012-05-19 17:21:37 +0200164 u8 data)
165{
166 int ret;
167
168 ret = prcmu_abb_write_masked((u8)(addr >> 8), (u8)(addr & 0xFF), &data,
169 &mask, 1);
170 if (ret < 0)
171 dev_err(ab8500->dev, "prcmu i2c error %d\n", ret);
172 return ret;
173}
174
Lee Jones822672a2012-06-20 13:56:38 +0100175static int ab8500_prcmu_read(struct ab8500 *ab8500, u16 addr)
Lee Jonesd28f1db2012-05-19 17:21:37 +0200176{
177 int ret;
178 u8 data;
179
180 ret = prcmu_abb_read((u8)(addr >> 8), (u8)(addr & 0xFF), &data, 1);
181 if (ret < 0) {
182 dev_err(ab8500->dev, "prcmu i2c error %d\n", ret);
183 return ret;
184 }
185 return (int)data;
186}
187
Mattias Wallin47c16972010-09-10 17:47:56 +0200188static int ab8500_get_chip_id(struct device *dev)
189{
Mattias Wallin6bce7bf2010-12-02 15:08:32 +0100190 struct ab8500 *ab8500;
191
192 if (!dev)
193 return -EINVAL;
194 ab8500 = dev_get_drvdata(dev->parent);
195 return ab8500 ? (int)ab8500->chip_id : -EINVAL;
Mattias Wallin47c16972010-09-10 17:47:56 +0200196}
197
198static int set_register_interruptible(struct ab8500 *ab8500, u8 bank,
199 u8 reg, u8 data)
Rabin Vincent62579262010-05-19 11:39:02 +0200200{
201 int ret;
Mattias Wallin47c16972010-09-10 17:47:56 +0200202 /*
203 * Put the u8 bank and u8 register together into a an u16.
204 * The bank on higher 8 bits and register in lower 8 bits.
205 * */
206 u16 addr = ((u16)bank) << 8 | reg;
Rabin Vincent62579262010-05-19 11:39:02 +0200207
208 dev_vdbg(ab8500->dev, "wr: addr %#x <= %#x\n", addr, data);
209
Rabin Vincent392cbd12012-03-08 14:01:46 +0100210 mutex_lock(&ab8500->lock);
Mattias Wallin47c16972010-09-10 17:47:56 +0200211
212 ret = ab8500->write(ab8500, addr, data);
213 if (ret < 0)
214 dev_err(ab8500->dev, "failed to write reg %#x: %d\n",
215 addr, ret);
216 mutex_unlock(&ab8500->lock);
217
218 return ret;
219}
220
221static int ab8500_set_register(struct device *dev, u8 bank,
222 u8 reg, u8 value)
223{
Jonas Aaberg112a80d2012-04-17 09:30:33 +0200224 int ret;
Mattias Wallin47c16972010-09-10 17:47:56 +0200225 struct ab8500 *ab8500 = dev_get_drvdata(dev->parent);
226
Jonas Aaberg112a80d2012-04-17 09:30:33 +0200227 atomic_inc(&ab8500->transfer_ongoing);
228 ret = set_register_interruptible(ab8500, bank, reg, value);
229 atomic_dec(&ab8500->transfer_ongoing);
230 return ret;
Mattias Wallin47c16972010-09-10 17:47:56 +0200231}
232
233static int get_register_interruptible(struct ab8500 *ab8500, u8 bank,
234 u8 reg, u8 *value)
235{
236 int ret;
237 /* put the u8 bank and u8 reg together into a an u16.
238 * bank on higher 8 bits and reg in lower */
239 u16 addr = ((u16)bank) << 8 | reg;
240
Rabin Vincent392cbd12012-03-08 14:01:46 +0100241 mutex_lock(&ab8500->lock);
Mattias Wallin47c16972010-09-10 17:47:56 +0200242
243 ret = ab8500->read(ab8500, addr);
244 if (ret < 0)
245 dev_err(ab8500->dev, "failed to read reg %#x: %d\n",
246 addr, ret);
247 else
248 *value = ret;
249
250 mutex_unlock(&ab8500->lock);
251 dev_vdbg(ab8500->dev, "rd: addr %#x => data %#x\n", addr, ret);
252
253 return ret;
254}
255
256static int ab8500_get_register(struct device *dev, u8 bank,
257 u8 reg, u8 *value)
258{
Jonas Aaberg112a80d2012-04-17 09:30:33 +0200259 int ret;
Mattias Wallin47c16972010-09-10 17:47:56 +0200260 struct ab8500 *ab8500 = dev_get_drvdata(dev->parent);
261
Jonas Aaberg112a80d2012-04-17 09:30:33 +0200262 atomic_inc(&ab8500->transfer_ongoing);
263 ret = get_register_interruptible(ab8500, bank, reg, value);
264 atomic_dec(&ab8500->transfer_ongoing);
265 return ret;
Mattias Wallin47c16972010-09-10 17:47:56 +0200266}
267
268static int mask_and_set_register_interruptible(struct ab8500 *ab8500, u8 bank,
269 u8 reg, u8 bitmask, u8 bitvalues)
270{
271 int ret;
Mattias Wallin47c16972010-09-10 17:47:56 +0200272 /* put the u8 bank and u8 reg together into a an u16.
273 * bank on higher 8 bits and reg in lower */
274 u16 addr = ((u16)bank) << 8 | reg;
275
Rabin Vincent392cbd12012-03-08 14:01:46 +0100276 mutex_lock(&ab8500->lock);
Mattias Wallin47c16972010-09-10 17:47:56 +0200277
Mattias Nilssonbc628fd2012-03-08 14:02:20 +0100278 if (ab8500->write_masked == NULL) {
279 u8 data;
280
281 ret = ab8500->read(ab8500, addr);
282 if (ret < 0) {
283 dev_err(ab8500->dev, "failed to read reg %#x: %d\n",
284 addr, ret);
285 goto out;
286 }
287
288 data = (u8)ret;
289 data = (~bitmask & data) | (bitmask & bitvalues);
290
291 ret = ab8500->write(ab8500, addr, data);
292 if (ret < 0)
293 dev_err(ab8500->dev, "failed to write reg %#x: %d\n",
294 addr, ret);
295
296 dev_vdbg(ab8500->dev, "mask: addr %#x => data %#x\n", addr,
297 data);
Mattias Wallin47c16972010-09-10 17:47:56 +0200298 goto out;
299 }
Mattias Nilssonbc628fd2012-03-08 14:02:20 +0100300 ret = ab8500->write_masked(ab8500, addr, bitmask, bitvalues);
Rabin Vincent62579262010-05-19 11:39:02 +0200301 if (ret < 0)
Mattias Nilssonbc628fd2012-03-08 14:02:20 +0100302 dev_err(ab8500->dev, "failed to modify reg %#x: %d\n", addr,
303 ret);
Rabin Vincent62579262010-05-19 11:39:02 +0200304out:
305 mutex_unlock(&ab8500->lock);
306 return ret;
307}
Mattias Wallin47c16972010-09-10 17:47:56 +0200308
309static int ab8500_mask_and_set_register(struct device *dev,
310 u8 bank, u8 reg, u8 bitmask, u8 bitvalues)
311{
Jonas Aaberg112a80d2012-04-17 09:30:33 +0200312 int ret;
Mattias Wallin47c16972010-09-10 17:47:56 +0200313 struct ab8500 *ab8500 = dev_get_drvdata(dev->parent);
314
Jonas Aaberg112a80d2012-04-17 09:30:33 +0200315 atomic_inc(&ab8500->transfer_ongoing);
316 ret= mask_and_set_register_interruptible(ab8500, bank, reg,
317 bitmask, bitvalues);
318 atomic_dec(&ab8500->transfer_ongoing);
319 return ret;
Mattias Wallin47c16972010-09-10 17:47:56 +0200320}
321
322static struct abx500_ops ab8500_ops = {
323 .get_chip_id = ab8500_get_chip_id,
324 .get_register = ab8500_get_register,
325 .set_register = ab8500_set_register,
326 .get_register_page = NULL,
327 .set_register_page = NULL,
328 .mask_and_set_register = ab8500_mask_and_set_register,
329 .event_registers_startup_state_get = NULL,
330 .startup_irq_enabled = NULL,
Mian Yousaf Kaukab1d843a62012-01-27 11:35:41 +0100331 .dump_all_banks = ab8500_dump_all_banks,
Mattias Wallin47c16972010-09-10 17:47:56 +0200332};
Rabin Vincent62579262010-05-19 11:39:02 +0200333
Mark Brown9505a0a2010-12-11 13:16:08 +0000334static void ab8500_irq_lock(struct irq_data *data)
Rabin Vincent62579262010-05-19 11:39:02 +0200335{
Mark Brown9505a0a2010-12-11 13:16:08 +0000336 struct ab8500 *ab8500 = irq_data_get_irq_chip_data(data);
Rabin Vincent62579262010-05-19 11:39:02 +0200337
338 mutex_lock(&ab8500->irq_lock);
Jonas Aaberg112a80d2012-04-17 09:30:33 +0200339 atomic_inc(&ab8500->transfer_ongoing);
Rabin Vincent62579262010-05-19 11:39:02 +0200340}
341
Mark Brown9505a0a2010-12-11 13:16:08 +0000342static void ab8500_irq_sync_unlock(struct irq_data *data)
Rabin Vincent62579262010-05-19 11:39:02 +0200343{
Mark Brown9505a0a2010-12-11 13:16:08 +0000344 struct ab8500 *ab8500 = irq_data_get_irq_chip_data(data);
Rabin Vincent62579262010-05-19 11:39:02 +0200345 int i;
346
Linus Walleij2ced4452012-02-20 21:42:17 +0100347 for (i = 0; i < ab8500->mask_size; i++) {
Rabin Vincent62579262010-05-19 11:39:02 +0200348 u8 old = ab8500->oldmask[i];
349 u8 new = ab8500->mask[i];
350 int reg;
351
352 if (new == old)
353 continue;
354
Linus Walleij0f6208372012-02-20 21:42:10 +0100355 /*
356 * Interrupt register 12 doesn't exist prior to AB8500 version
357 * 2.0
358 */
359 if (ab8500->irq_reg_offset[i] == 11 &&
360 is_ab8500_1p1_or_earlier(ab8500))
Mattias Wallin92d50a42010-12-07 11:20:47 +0100361 continue;
362
Rabin Vincent62579262010-05-19 11:39:02 +0200363 ab8500->oldmask[i] = new;
364
Linus Walleij2ced4452012-02-20 21:42:17 +0100365 reg = AB8500_IT_MASK1_REG + ab8500->irq_reg_offset[i];
Mattias Wallin47c16972010-09-10 17:47:56 +0200366 set_register_interruptible(ab8500, AB8500_INTERRUPT, reg, new);
Rabin Vincent62579262010-05-19 11:39:02 +0200367 }
Jonas Aaberg112a80d2012-04-17 09:30:33 +0200368 atomic_dec(&ab8500->transfer_ongoing);
Rabin Vincent62579262010-05-19 11:39:02 +0200369 mutex_unlock(&ab8500->irq_lock);
370}
371
Mark Brown9505a0a2010-12-11 13:16:08 +0000372static void ab8500_irq_mask(struct irq_data *data)
Rabin Vincent62579262010-05-19 11:39:02 +0200373{
Mark Brown9505a0a2010-12-11 13:16:08 +0000374 struct ab8500 *ab8500 = irq_data_get_irq_chip_data(data);
Lee Jones06e589e2012-06-20 13:56:37 +0100375 int offset = data->hwirq;
Rabin Vincent62579262010-05-19 11:39:02 +0200376 int index = offset / 8;
377 int mask = 1 << (offset % 8);
378
379 ab8500->mask[index] |= mask;
Lee Jones9c677b92012-12-20 11:23:42 +0000380
381 /* The AB8500 GPIOs have two interrupts each (rising & falling). */
382 if (offset >= AB8500_INT_GPIO6R && offset <= AB8500_INT_GPIO41R)
383 ab8500->mask[index + 2] |= mask;
384 if (offset >= AB9540_INT_GPIO50R && offset <= AB9540_INT_GPIO54R)
385 ab8500->mask[index + 1] |= mask;
386 if (offset == AB8540_INT_GPIO43R || offset == AB8540_INT_GPIO44R)
Linus Walleije2ddf462013-02-06 21:54:34 +0100387 /* Here the falling IRQ is one bit lower */
388 ab8500->mask[index] |= (mask << 1);
Rabin Vincent62579262010-05-19 11:39:02 +0200389}
390
Mark Brown9505a0a2010-12-11 13:16:08 +0000391static void ab8500_irq_unmask(struct irq_data *data)
Rabin Vincent62579262010-05-19 11:39:02 +0200392{
Mark Brown9505a0a2010-12-11 13:16:08 +0000393 struct ab8500 *ab8500 = irq_data_get_irq_chip_data(data);
Lee Jones9c677b92012-12-20 11:23:42 +0000394 unsigned int type = irqd_get_trigger_type(data);
Lee Jones06e589e2012-06-20 13:56:37 +0100395 int offset = data->hwirq;
Rabin Vincent62579262010-05-19 11:39:02 +0200396 int index = offset / 8;
397 int mask = 1 << (offset % 8);
398
Lee Jones9c677b92012-12-20 11:23:42 +0000399 if (type & IRQ_TYPE_EDGE_RISING)
400 ab8500->mask[index] &= ~mask;
401
402 /* The AB8500 GPIOs have two interrupts each (rising & falling). */
403 if (type & IRQ_TYPE_EDGE_FALLING) {
404 if (offset >= AB8500_INT_GPIO6R && offset <= AB8500_INT_GPIO41R)
405 ab8500->mask[index + 2] &= ~mask;
406 else if (offset >= AB9540_INT_GPIO50R && offset <= AB9540_INT_GPIO54R)
407 ab8500->mask[index + 1] &= ~mask;
408 else if (offset == AB8540_INT_GPIO43R || offset == AB8540_INT_GPIO44R)
Linus Walleije2ddf462013-02-06 21:54:34 +0100409 /* Here the falling IRQ is one bit lower */
410 ab8500->mask[index] &= ~(mask << 1);
Lee Jones9c677b92012-12-20 11:23:42 +0000411 else
412 ab8500->mask[index] &= ~mask;
Linus Walleije2ddf462013-02-06 21:54:34 +0100413 } else {
Lee Jones9c677b92012-12-20 11:23:42 +0000414 /* Satisfies the case where type is not set. */
415 ab8500->mask[index] &= ~mask;
Linus Walleije2ddf462013-02-06 21:54:34 +0100416 }
Rabin Vincent62579262010-05-19 11:39:02 +0200417}
418
Lee Jones40f6e5a2013-01-07 12:23:48 +0000419static int ab8500_irq_set_type(struct irq_data *data, unsigned int type)
420{
421 return 0;
Rabin Vincent62579262010-05-19 11:39:02 +0200422}
423
424static struct irq_chip ab8500_irq_chip = {
425 .name = "ab8500",
Mark Brown9505a0a2010-12-11 13:16:08 +0000426 .irq_bus_lock = ab8500_irq_lock,
427 .irq_bus_sync_unlock = ab8500_irq_sync_unlock,
428 .irq_mask = ab8500_irq_mask,
Virupax Sadashivpetimathe6f93062011-10-11 10:49:17 +0200429 .irq_disable = ab8500_irq_mask,
Mark Brown9505a0a2010-12-11 13:16:08 +0000430 .irq_unmask = ab8500_irq_unmask,
Lee Jones40f6e5a2013-01-07 12:23:48 +0000431 .irq_set_type = ab8500_irq_set_type,
Rabin Vincent62579262010-05-19 11:39:02 +0200432};
433
Michel JAOUEN7ccfe9b2012-05-07 15:02:03 +0200434static int ab8500_handle_hierarchical_line(struct ab8500 *ab8500,
435 int latch_offset, u8 latch_val)
436{
437 int int_bit = __ffs(latch_val);
438 int line, i;
439
440 do {
441 int_bit = __ffs(latch_val);
442
443 for (i = 0; i < ab8500->mask_size; i++)
444 if (ab8500->irq_reg_offset[i] == latch_offset)
445 break;
446
447 if (i >= ab8500->mask_size) {
448 dev_err(ab8500->dev, "Register offset 0x%2x not declared\n",
449 latch_offset);
450 return -ENXIO;
451 }
452
453 line = (i << 3) + int_bit;
454 latch_val &= ~(1 << int_bit);
455
Linus Walleije2ddf462013-02-06 21:54:34 +0100456 /*
457 * This handles the falling edge hwirqs from the GPIO
458 * lines. Route them back to the line registered for the
459 * rising IRQ, as this is merely a flag for the same IRQ
460 * in linux terms.
461 */
462 if (line >= AB8500_INT_GPIO6F && line <= AB8500_INT_GPIO41F)
463 line -= 16;
464 if (line >= AB9540_INT_GPIO50F && line <= AB9540_INT_GPIO54F)
465 line -= 8;
466 if (line == AB8540_INT_GPIO43F || line == AB8540_INT_GPIO44F)
467 line += 1;
468
Michel JAOUEN7ccfe9b2012-05-07 15:02:03 +0200469 handle_nested_irq(ab8500->irq_base + line);
470 } while (latch_val);
471
472 return 0;
473}
474
475static int ab8500_handle_hierarchical_latch(struct ab8500 *ab8500,
476 int hier_offset, u8 hier_val)
477{
478 int latch_bit, status;
479 u8 latch_offset, latch_val;
480
481 do {
482 latch_bit = __ffs(hier_val);
483 latch_offset = (hier_offset << 3) + latch_bit;
484
485 /* Fix inconsistent ITFromLatch25 bit mapping... */
486 if (unlikely(latch_offset == 17))
487 latch_offset = 24;
488
489 status = get_register_interruptible(ab8500,
490 AB8500_INTERRUPT,
491 AB8500_IT_LATCH1_REG + latch_offset,
492 &latch_val);
493 if (status < 0 || latch_val == 0)
494 goto discard;
495
496 status = ab8500_handle_hierarchical_line(ab8500,
497 latch_offset, latch_val);
498 if (status < 0)
499 return status;
500discard:
501 hier_val &= ~(1 << latch_bit);
502 } while (hier_val);
503
504 return 0;
505}
506
507static irqreturn_t ab8500_hierarchical_irq(int irq, void *dev)
508{
509 struct ab8500 *ab8500 = dev;
510 u8 i;
511
512 dev_vdbg(ab8500->dev, "interrupt\n");
513
514 /* Hierarchical interrupt version */
515 for (i = 0; i < AB8500_IT_LATCHHIER_NUM; i++) {
516 int status;
517 u8 hier_val;
518
519 status = get_register_interruptible(ab8500, AB8500_INTERRUPT,
520 AB8500_IT_LATCHHIER1_REG + i, &hier_val);
521 if (status < 0 || hier_val == 0)
522 continue;
523
524 status = ab8500_handle_hierarchical_latch(ab8500, i, hier_val);
525 if (status < 0)
526 break;
527 }
528 return IRQ_HANDLED;
529}
530
Lee Jones80633f02012-08-20 11:53:36 +0100531/**
532 * ab8500_irq_get_virq(): Map an interrupt on a chip to a virtual IRQ
533 *
534 * @ab8500: ab8500_irq controller to operate on.
535 * @irq: index of the interrupt requested in the chip IRQs
536 *
537 * Useful for drivers to request their own IRQs.
538 */
539static int ab8500_irq_get_virq(struct ab8500 *ab8500, int irq)
540{
541 if (!ab8500)
542 return -EINVAL;
543
544 return irq_create_mapping(ab8500->domain, irq);
545}
546
Rabin Vincent62579262010-05-19 11:39:02 +0200547static irqreturn_t ab8500_irq(int irq, void *dev)
548{
549 struct ab8500 *ab8500 = dev;
550 int i;
551
552 dev_vdbg(ab8500->dev, "interrupt\n");
553
Jonas Aaberg112a80d2012-04-17 09:30:33 +0200554 atomic_inc(&ab8500->transfer_ongoing);
555
Linus Walleij2ced4452012-02-20 21:42:17 +0100556 for (i = 0; i < ab8500->mask_size; i++) {
557 int regoffset = ab8500->irq_reg_offset[i];
Rabin Vincent62579262010-05-19 11:39:02 +0200558 int status;
Mattias Wallin47c16972010-09-10 17:47:56 +0200559 u8 value;
Rabin Vincent62579262010-05-19 11:39:02 +0200560
Linus Walleij0f6208372012-02-20 21:42:10 +0100561 /*
562 * Interrupt register 12 doesn't exist prior to AB8500 version
563 * 2.0
564 */
565 if (regoffset == 11 && is_ab8500_1p1_or_earlier(ab8500))
Mattias Wallin92d50a42010-12-07 11:20:47 +0100566 continue;
567
Mattias Wallin47c16972010-09-10 17:47:56 +0200568 status = get_register_interruptible(ab8500, AB8500_INTERRUPT,
569 AB8500_IT_LATCH1_REG + regoffset, &value);
570 if (status < 0 || value == 0)
Rabin Vincent62579262010-05-19 11:39:02 +0200571 continue;
572
573 do {
Mattias Wallin88aec4f2010-12-02 15:06:49 +0100574 int bit = __ffs(value);
Rabin Vincent62579262010-05-19 11:39:02 +0200575 int line = i * 8 + bit;
Lee Jones0a37fc52012-08-09 16:53:54 +0100576 int virq = ab8500_irq_get_virq(ab8500, line);
Rabin Vincent62579262010-05-19 11:39:02 +0200577
Lee Jones0a37fc52012-08-09 16:53:54 +0100578 handle_nested_irq(virq);
Bengt Jonsson8f0eb432012-02-14 13:01:00 +0100579 ab8500_debug_register_interrupt(line);
Mattias Wallin47c16972010-09-10 17:47:56 +0200580 value &= ~(1 << bit);
Jonas Aaberg112a80d2012-04-17 09:30:33 +0200581
Mattias Wallin47c16972010-09-10 17:47:56 +0200582 } while (value);
Rabin Vincent62579262010-05-19 11:39:02 +0200583 }
Jonas Aaberg112a80d2012-04-17 09:30:33 +0200584 atomic_dec(&ab8500->transfer_ongoing);
Rabin Vincent62579262010-05-19 11:39:02 +0200585 return IRQ_HANDLED;
586}
587
Lee Jones06e589e2012-06-20 13:56:37 +0100588static int ab8500_irq_map(struct irq_domain *d, unsigned int virq,
589 irq_hw_number_t hwirq)
590{
591 struct ab8500 *ab8500 = d->host_data;
592
593 if (!ab8500)
594 return -EINVAL;
595
596 irq_set_chip_data(virq, ab8500);
597 irq_set_chip_and_handler(virq, &ab8500_irq_chip,
598 handle_simple_irq);
599 irq_set_nested_thread(virq, 1);
Rabin Vincent62579262010-05-19 11:39:02 +0200600#ifdef CONFIG_ARM
Lee Jones06e589e2012-06-20 13:56:37 +0100601 set_irq_flags(virq, IRQF_VALID);
Rabin Vincent62579262010-05-19 11:39:02 +0200602#else
Lee Jones06e589e2012-06-20 13:56:37 +0100603 irq_set_noprobe(virq);
Rabin Vincent62579262010-05-19 11:39:02 +0200604#endif
Rabin Vincent62579262010-05-19 11:39:02 +0200605
606 return 0;
607}
608
Lee Jones06e589e2012-06-20 13:56:37 +0100609static struct irq_domain_ops ab8500_irq_ops = {
610 .map = ab8500_irq_map,
611 .xlate = irq_domain_xlate_twocell,
612};
613
614static int ab8500_irq_init(struct ab8500 *ab8500, struct device_node *np)
Rabin Vincent62579262010-05-19 11:39:02 +0200615{
Linus Walleij2ced4452012-02-20 21:42:17 +0100616 int num_irqs;
Rabin Vincent62579262010-05-19 11:39:02 +0200617
Linus Walleijd6255522012-02-20 21:42:24 +0100618 if (is_ab9540(ab8500))
619 num_irqs = AB9540_NR_IRQS;
Bengt Jonssona9823622012-03-08 14:01:57 +0100620 else if (is_ab8505(ab8500))
621 num_irqs = AB8505_NR_IRQS;
Linus Walleijd6255522012-02-20 21:42:24 +0100622 else
623 num_irqs = AB8500_NR_IRQS;
Linus Walleij2ced4452012-02-20 21:42:17 +0100624
Linus Walleijf1d11f32012-10-18 18:18:44 +0200625 /* If ->irq_base is zero this will give a linear mapping */
626 ab8500->domain = irq_domain_add_simple(NULL,
627 num_irqs, ab8500->irq_base,
628 &ab8500_irq_ops, ab8500);
Lee Jones06e589e2012-06-20 13:56:37 +0100629
630 if (!ab8500->domain) {
631 dev_err(ab8500->dev, "Failed to create irqdomain\n");
632 return -ENOSYS;
633 }
634
635 return 0;
Rabin Vincent62579262010-05-19 11:39:02 +0200636}
637
Jonas Aaberg112a80d2012-04-17 09:30:33 +0200638int ab8500_suspend(struct ab8500 *ab8500)
639{
640 if (atomic_read(&ab8500->transfer_ongoing))
641 return -EINVAL;
642 else
643 return 0;
644}
645
Bill Pembertona9e9ce42012-11-19 13:24:21 -0500646static struct resource ab8500_gpadc_resources[] = {
Rabin Vincent62579262010-05-19 11:39:02 +0200647 {
648 .name = "HW_CONV_END",
649 .start = AB8500_INT_GP_HW_ADC_CONV_END,
650 .end = AB8500_INT_GP_HW_ADC_CONV_END,
651 .flags = IORESOURCE_IRQ,
652 },
653 {
654 .name = "SW_CONV_END",
655 .start = AB8500_INT_GP_SW_ADC_CONV_END,
656 .end = AB8500_INT_GP_SW_ADC_CONV_END,
657 .flags = IORESOURCE_IRQ,
658 },
659};
660
Bill Pembertona9e9ce42012-11-19 13:24:21 -0500661static struct resource ab8500_rtc_resources[] = {
Rabin Vincent62579262010-05-19 11:39:02 +0200662 {
663 .name = "60S",
664 .start = AB8500_INT_RTC_60S,
665 .end = AB8500_INT_RTC_60S,
666 .flags = IORESOURCE_IRQ,
667 },
668 {
669 .name = "ALARM",
670 .start = AB8500_INT_RTC_ALARM,
671 .end = AB8500_INT_RTC_ALARM,
672 .flags = IORESOURCE_IRQ,
673 },
674};
675
Bill Pembertona9e9ce42012-11-19 13:24:21 -0500676static struct resource ab8500_poweronkey_db_resources[] = {
Sundar R Iyer77686512010-09-05 12:18:47 -0700677 {
678 .name = "ONKEY_DBF",
679 .start = AB8500_INT_PON_KEY1DB_F,
680 .end = AB8500_INT_PON_KEY1DB_F,
681 .flags = IORESOURCE_IRQ,
682 },
683 {
684 .name = "ONKEY_DBR",
685 .start = AB8500_INT_PON_KEY1DB_R,
686 .end = AB8500_INT_PON_KEY1DB_R,
687 .flags = IORESOURCE_IRQ,
688 },
689};
690
Bill Pembertona9e9ce42012-11-19 13:24:21 -0500691static struct resource ab8500_av_acc_detect_resources[] = {
Mattias Walline098aded72010-12-02 15:40:31 +0100692 {
Linus Walleij6af75ec2011-06-09 23:57:45 +0200693 .name = "ACC_DETECT_1DB_F",
694 .start = AB8500_INT_ACC_DETECT_1DB_F,
695 .end = AB8500_INT_ACC_DETECT_1DB_F,
696 .flags = IORESOURCE_IRQ,
Mattias Walline098aded72010-12-02 15:40:31 +0100697 },
698 {
Linus Walleij6af75ec2011-06-09 23:57:45 +0200699 .name = "ACC_DETECT_1DB_R",
700 .start = AB8500_INT_ACC_DETECT_1DB_R,
701 .end = AB8500_INT_ACC_DETECT_1DB_R,
702 .flags = IORESOURCE_IRQ,
Mattias Walline098aded72010-12-02 15:40:31 +0100703 },
704 {
Linus Walleij6af75ec2011-06-09 23:57:45 +0200705 .name = "ACC_DETECT_21DB_F",
706 .start = AB8500_INT_ACC_DETECT_21DB_F,
707 .end = AB8500_INT_ACC_DETECT_21DB_F,
708 .flags = IORESOURCE_IRQ,
709 },
710 {
711 .name = "ACC_DETECT_21DB_R",
712 .start = AB8500_INT_ACC_DETECT_21DB_R,
713 .end = AB8500_INT_ACC_DETECT_21DB_R,
714 .flags = IORESOURCE_IRQ,
715 },
716 {
717 .name = "ACC_DETECT_22DB_F",
718 .start = AB8500_INT_ACC_DETECT_22DB_F,
719 .end = AB8500_INT_ACC_DETECT_22DB_F,
720 .flags = IORESOURCE_IRQ,
721 },
722 {
723 .name = "ACC_DETECT_22DB_R",
724 .start = AB8500_INT_ACC_DETECT_22DB_R,
725 .end = AB8500_INT_ACC_DETECT_22DB_R,
726 .flags = IORESOURCE_IRQ,
727 },
728};
729
Bill Pembertona9e9ce42012-11-19 13:24:21 -0500730static struct resource ab8500_charger_resources[] = {
Linus Walleij6af75ec2011-06-09 23:57:45 +0200731 {
Mattias Walline098aded72010-12-02 15:40:31 +0100732 .name = "MAIN_CH_UNPLUG_DET",
733 .start = AB8500_INT_MAIN_CH_UNPLUG_DET,
734 .end = AB8500_INT_MAIN_CH_UNPLUG_DET,
735 .flags = IORESOURCE_IRQ,
736 },
737 {
738 .name = "MAIN_CHARGE_PLUG_DET",
739 .start = AB8500_INT_MAIN_CH_PLUG_DET,
740 .end = AB8500_INT_MAIN_CH_PLUG_DET,
741 .flags = IORESOURCE_IRQ,
742 },
743 {
Mattias Walline098aded72010-12-02 15:40:31 +0100744 .name = "VBUS_DET_R",
745 .start = AB8500_INT_VBUS_DET_R,
746 .end = AB8500_INT_VBUS_DET_R,
747 .flags = IORESOURCE_IRQ,
748 },
749 {
Linus Walleij6af75ec2011-06-09 23:57:45 +0200750 .name = "VBUS_DET_F",
751 .start = AB8500_INT_VBUS_DET_F,
752 .end = AB8500_INT_VBUS_DET_F,
Mattias Walline098aded72010-12-02 15:40:31 +0100753 .flags = IORESOURCE_IRQ,
754 },
755 {
Linus Walleij6af75ec2011-06-09 23:57:45 +0200756 .name = "USB_LINK_STATUS",
757 .start = AB8500_INT_USB_LINK_STATUS,
758 .end = AB8500_INT_USB_LINK_STATUS,
759 .flags = IORESOURCE_IRQ,
760 },
761 {
Mattias Walline098aded72010-12-02 15:40:31 +0100762 .name = "VBUS_OVV",
763 .start = AB8500_INT_VBUS_OVV,
764 .end = AB8500_INT_VBUS_OVV,
765 .flags = IORESOURCE_IRQ,
766 },
767 {
Linus Walleij6af75ec2011-06-09 23:57:45 +0200768 .name = "USB_CH_TH_PROT_R",
769 .start = AB8500_INT_USB_CH_TH_PROT_R,
770 .end = AB8500_INT_USB_CH_TH_PROT_R,
Mattias Walline098aded72010-12-02 15:40:31 +0100771 .flags = IORESOURCE_IRQ,
772 },
773 {
Linus Walleij6af75ec2011-06-09 23:57:45 +0200774 .name = "USB_CH_TH_PROT_F",
775 .start = AB8500_INT_USB_CH_TH_PROT_F,
776 .end = AB8500_INT_USB_CH_TH_PROT_F,
Mattias Walline098aded72010-12-02 15:40:31 +0100777 .flags = IORESOURCE_IRQ,
778 },
779 {
Linus Walleij6af75ec2011-06-09 23:57:45 +0200780 .name = "MAIN_EXT_CH_NOT_OK",
781 .start = AB8500_INT_MAIN_EXT_CH_NOT_OK,
782 .end = AB8500_INT_MAIN_EXT_CH_NOT_OK,
783 .flags = IORESOURCE_IRQ,
784 },
785 {
786 .name = "MAIN_CH_TH_PROT_R",
787 .start = AB8500_INT_MAIN_CH_TH_PROT_R,
788 .end = AB8500_INT_MAIN_CH_TH_PROT_R,
789 .flags = IORESOURCE_IRQ,
790 },
791 {
792 .name = "MAIN_CH_TH_PROT_F",
793 .start = AB8500_INT_MAIN_CH_TH_PROT_F,
794 .end = AB8500_INT_MAIN_CH_TH_PROT_F,
795 .flags = IORESOURCE_IRQ,
796 },
797 {
798 .name = "USB_CHARGER_NOT_OKR",
Bengt Jonssona9823622012-03-08 14:01:57 +0100799 .start = AB8500_INT_USB_CHARGER_NOT_OKR,
800 .end = AB8500_INT_USB_CHARGER_NOT_OKR,
Linus Walleij6af75ec2011-06-09 23:57:45 +0200801 .flags = IORESOURCE_IRQ,
802 },
803 {
804 .name = "CH_WD_EXP",
805 .start = AB8500_INT_CH_WD_EXP,
806 .end = AB8500_INT_CH_WD_EXP,
807 .flags = IORESOURCE_IRQ,
808 },
Paer-Olof Haakansson34c11a72012-02-22 19:07:51 +0100809 {
810 .name = "VBUS_CH_DROP_END",
811 .start = AB8500_INT_VBUS_CH_DROP_END,
812 .end = AB8500_INT_VBUS_CH_DROP_END,
813 .flags = IORESOURCE_IRQ,
814 },
Linus Walleij6af75ec2011-06-09 23:57:45 +0200815};
816
Bill Pembertona9e9ce42012-11-19 13:24:21 -0500817static struct resource ab8500_btemp_resources[] = {
Linus Walleij6af75ec2011-06-09 23:57:45 +0200818 {
819 .name = "BAT_CTRL_INDB",
820 .start = AB8500_INT_BAT_CTRL_INDB,
821 .end = AB8500_INT_BAT_CTRL_INDB,
Mattias Walline098aded72010-12-02 15:40:31 +0100822 .flags = IORESOURCE_IRQ,
823 },
824 {
825 .name = "BTEMP_LOW",
826 .start = AB8500_INT_BTEMP_LOW,
827 .end = AB8500_INT_BTEMP_LOW,
828 .flags = IORESOURCE_IRQ,
829 },
830 {
831 .name = "BTEMP_HIGH",
832 .start = AB8500_INT_BTEMP_HIGH,
833 .end = AB8500_INT_BTEMP_HIGH,
834 .flags = IORESOURCE_IRQ,
835 },
836 {
Linus Walleij6af75ec2011-06-09 23:57:45 +0200837 .name = "BTEMP_LOW_MEDIUM",
838 .start = AB8500_INT_BTEMP_LOW_MEDIUM,
839 .end = AB8500_INT_BTEMP_LOW_MEDIUM,
Mattias Walline098aded72010-12-02 15:40:31 +0100840 .flags = IORESOURCE_IRQ,
841 },
842 {
Linus Walleij6af75ec2011-06-09 23:57:45 +0200843 .name = "BTEMP_MEDIUM_HIGH",
844 .start = AB8500_INT_BTEMP_MEDIUM_HIGH,
845 .end = AB8500_INT_BTEMP_MEDIUM_HIGH,
Mattias Walline098aded72010-12-02 15:40:31 +0100846 .flags = IORESOURCE_IRQ,
847 },
848};
849
Bill Pembertona9e9ce42012-11-19 13:24:21 -0500850static struct resource ab8500_fg_resources[] = {
Linus Walleij6af75ec2011-06-09 23:57:45 +0200851 {
852 .name = "NCONV_ACCU",
853 .start = AB8500_INT_CCN_CONV_ACC,
854 .end = AB8500_INT_CCN_CONV_ACC,
855 .flags = IORESOURCE_IRQ,
856 },
857 {
858 .name = "BATT_OVV",
859 .start = AB8500_INT_BATT_OVV,
860 .end = AB8500_INT_BATT_OVV,
861 .flags = IORESOURCE_IRQ,
862 },
863 {
864 .name = "LOW_BAT_F",
865 .start = AB8500_INT_LOW_BAT_F,
866 .end = AB8500_INT_LOW_BAT_F,
867 .flags = IORESOURCE_IRQ,
868 },
869 {
870 .name = "LOW_BAT_R",
871 .start = AB8500_INT_LOW_BAT_R,
872 .end = AB8500_INT_LOW_BAT_R,
873 .flags = IORESOURCE_IRQ,
874 },
875 {
876 .name = "CC_INT_CALIB",
877 .start = AB8500_INT_CC_INT_CALIB,
878 .end = AB8500_INT_CC_INT_CALIB,
879 .flags = IORESOURCE_IRQ,
880 },
Bengt Jonssona9823622012-03-08 14:01:57 +0100881 {
882 .name = "CCEOC",
883 .start = AB8500_INT_CCEOC,
884 .end = AB8500_INT_CCEOC,
885 .flags = IORESOURCE_IRQ,
886 },
Linus Walleij6af75ec2011-06-09 23:57:45 +0200887};
888
Bill Pembertona9e9ce42012-11-19 13:24:21 -0500889static struct resource ab8500_chargalg_resources[] = {};
Linus Walleij6af75ec2011-06-09 23:57:45 +0200890
Axel Lindf720642011-11-10 09:56:18 +0800891#ifdef CONFIG_DEBUG_FS
Bill Pembertona9e9ce42012-11-19 13:24:21 -0500892static struct resource ab8500_debug_resources[] = {
Mattias Walline098aded72010-12-02 15:40:31 +0100893 {
894 .name = "IRQ_FIRST",
895 .start = AB8500_INT_MAIN_EXT_CH_NOT_OK,
896 .end = AB8500_INT_MAIN_EXT_CH_NOT_OK,
897 .flags = IORESOURCE_IRQ,
898 },
899 {
900 .name = "IRQ_LAST",
Bengt Jonssona9823622012-03-08 14:01:57 +0100901 .start = AB8500_INT_XTAL32K_KO,
902 .end = AB8500_INT_XTAL32K_KO,
Mattias Walline098aded72010-12-02 15:40:31 +0100903 .flags = IORESOURCE_IRQ,
904 },
905};
Axel Lindf720642011-11-10 09:56:18 +0800906#endif
Mattias Walline098aded72010-12-02 15:40:31 +0100907
Bill Pembertona9e9ce42012-11-19 13:24:21 -0500908static struct resource ab8500_usb_resources[] = {
Mattias Walline098aded72010-12-02 15:40:31 +0100909 {
910 .name = "ID_WAKEUP_R",
911 .start = AB8500_INT_ID_WAKEUP_R,
912 .end = AB8500_INT_ID_WAKEUP_R,
913 .flags = IORESOURCE_IRQ,
914 },
915 {
916 .name = "ID_WAKEUP_F",
917 .start = AB8500_INT_ID_WAKEUP_F,
918 .end = AB8500_INT_ID_WAKEUP_F,
919 .flags = IORESOURCE_IRQ,
920 },
921 {
922 .name = "VBUS_DET_F",
923 .start = AB8500_INT_VBUS_DET_F,
924 .end = AB8500_INT_VBUS_DET_F,
925 .flags = IORESOURCE_IRQ,
926 },
927 {
928 .name = "VBUS_DET_R",
929 .start = AB8500_INT_VBUS_DET_R,
930 .end = AB8500_INT_VBUS_DET_R,
931 .flags = IORESOURCE_IRQ,
932 },
Mattias Wallin92d50a42010-12-07 11:20:47 +0100933 {
934 .name = "USB_LINK_STATUS",
935 .start = AB8500_INT_USB_LINK_STATUS,
936 .end = AB8500_INT_USB_LINK_STATUS,
937 .flags = IORESOURCE_IRQ,
938 },
Linus Walleij6af75ec2011-06-09 23:57:45 +0200939 {
940 .name = "USB_ADP_PROBE_PLUG",
941 .start = AB8500_INT_ADP_PROBE_PLUG,
942 .end = AB8500_INT_ADP_PROBE_PLUG,
943 .flags = IORESOURCE_IRQ,
944 },
945 {
946 .name = "USB_ADP_PROBE_UNPLUG",
947 .start = AB8500_INT_ADP_PROBE_UNPLUG,
948 .end = AB8500_INT_ADP_PROBE_UNPLUG,
949 .flags = IORESOURCE_IRQ,
950 },
Mattias Walline098aded72010-12-02 15:40:31 +0100951};
952
Bill Pembertona9e9ce42012-11-19 13:24:21 -0500953static struct resource ab8505_iddet_resources[] = {
Virupax Sadashivpetimath44f72e52012-04-17 09:30:14 +0200954 {
955 .name = "KeyDeglitch",
956 .start = AB8505_INT_KEYDEGLITCH,
957 .end = AB8505_INT_KEYDEGLITCH,
958 .flags = IORESOURCE_IRQ,
959 },
960 {
961 .name = "KP",
962 .start = AB8505_INT_KP,
963 .end = AB8505_INT_KP,
964 .flags = IORESOURCE_IRQ,
965 },
966 {
967 .name = "IKP",
968 .start = AB8505_INT_IKP,
969 .end = AB8505_INT_IKP,
970 .flags = IORESOURCE_IRQ,
971 },
972 {
973 .name = "IKR",
974 .start = AB8505_INT_IKR,
975 .end = AB8505_INT_IKR,
976 .flags = IORESOURCE_IRQ,
977 },
978 {
979 .name = "KeyStuck",
980 .start = AB8505_INT_KEYSTUCK,
981 .end = AB8505_INT_KEYSTUCK,
982 .flags = IORESOURCE_IRQ,
983 },
984};
985
Bill Pembertona9e9ce42012-11-19 13:24:21 -0500986static struct resource ab8500_temp_resources[] = {
Mattias Walline098aded72010-12-02 15:40:31 +0100987 {
Hongbo Zhang151621a2013-01-30 18:21:27 +0800988 .name = "ABX500_TEMP_WARM",
Mattias Walline098aded72010-12-02 15:40:31 +0100989 .start = AB8500_INT_TEMP_WARM,
990 .end = AB8500_INT_TEMP_WARM,
991 .flags = IORESOURCE_IRQ,
992 },
993};
994
Bill Pembertona9e9ce42012-11-19 13:24:21 -0500995static struct mfd_cell abx500_common_devs[] = {
Mattias Wallin5814fc32010-09-13 16:05:04 +0200996#ifdef CONFIG_DEBUG_FS
997 {
998 .name = "ab8500-debug",
Lee Jonesbad76992012-07-02 17:10:56 +0200999 .of_compatible = "stericsson,ab8500-debug",
Mattias Walline098aded72010-12-02 15:40:31 +01001000 .num_resources = ARRAY_SIZE(ab8500_debug_resources),
1001 .resources = ab8500_debug_resources,
Mattias Wallin5814fc32010-09-13 16:05:04 +02001002 },
1003#endif
Rabin Vincent62579262010-05-19 11:39:02 +02001004 {
Mattias Walline098aded72010-12-02 15:40:31 +01001005 .name = "ab8500-sysctrl",
Lee Jonesbad76992012-07-02 17:10:56 +02001006 .of_compatible = "stericsson,ab8500-sysctrl",
Mattias Walline098aded72010-12-02 15:40:31 +01001007 },
1008 {
1009 .name = "ab8500-regulator",
Lee Jonesbad76992012-07-02 17:10:56 +02001010 .of_compatible = "stericsson,ab8500-regulator",
Mattias Walline098aded72010-12-02 15:40:31 +01001011 },
1012 {
Ulf Hansson916a8712012-11-22 11:35:40 +01001013 .name = "abx500-clk",
1014 .of_compatible = "stericsson,abx500-clk",
1015 },
1016 {
Rabin Vincent62579262010-05-19 11:39:02 +02001017 .name = "ab8500-gpadc",
Lee Jonesbad76992012-07-02 17:10:56 +02001018 .of_compatible = "stericsson,ab8500-gpadc",
Rabin Vincent62579262010-05-19 11:39:02 +02001019 .num_resources = ARRAY_SIZE(ab8500_gpadc_resources),
1020 .resources = ab8500_gpadc_resources,
1021 },
1022 {
1023 .name = "ab8500-rtc",
Lee Jonesbad76992012-07-02 17:10:56 +02001024 .of_compatible = "stericsson,ab8500-rtc",
Rabin Vincent62579262010-05-19 11:39:02 +02001025 .num_resources = ARRAY_SIZE(ab8500_rtc_resources),
1026 .resources = ab8500_rtc_resources,
1027 },
Arun Murthyf0f05b12010-09-06 12:24:52 +05301028 {
Linus Walleij6af75ec2011-06-09 23:57:45 +02001029 .name = "ab8500-acc-det",
Lee Jonesbad76992012-07-02 17:10:56 +02001030 .of_compatible = "stericsson,ab8500-acc-det",
Linus Walleij6af75ec2011-06-09 23:57:45 +02001031 .num_resources = ARRAY_SIZE(ab8500_av_acc_detect_resources),
1032 .resources = ab8500_av_acc_detect_resources,
1033 },
1034 {
Mattias Walline098aded72010-12-02 15:40:31 +01001035 .name = "ab8500-poweron-key",
Lee Jonesbad76992012-07-02 17:10:56 +02001036 .of_compatible = "stericsson,ab8500-poweron-key",
Mattias Walline098aded72010-12-02 15:40:31 +01001037 .num_resources = ARRAY_SIZE(ab8500_poweronkey_db_resources),
1038 .resources = ab8500_poweronkey_db_resources,
1039 },
1040 {
Arun Murthyf0f05b12010-09-06 12:24:52 +05301041 .name = "ab8500-pwm",
Lee Jonesbad76992012-07-02 17:10:56 +02001042 .of_compatible = "stericsson,ab8500-pwm",
Arun Murthyf0f05b12010-09-06 12:24:52 +05301043 .id = 1,
1044 },
1045 {
1046 .name = "ab8500-pwm",
Lee Jonesbad76992012-07-02 17:10:56 +02001047 .of_compatible = "stericsson,ab8500-pwm",
Arun Murthyf0f05b12010-09-06 12:24:52 +05301048 .id = 2,
1049 },
1050 {
1051 .name = "ab8500-pwm",
Lee Jonesbad76992012-07-02 17:10:56 +02001052 .of_compatible = "stericsson,ab8500-pwm",
Arun Murthyf0f05b12010-09-06 12:24:52 +05301053 .id = 3,
1054 },
Lee Jonesbad76992012-07-02 17:10:56 +02001055 {
1056 .name = "ab8500-leds",
1057 .of_compatible = "stericsson,ab8500-leds",
1058 },
Sundar R Iyer77686512010-09-05 12:18:47 -07001059 {
Mattias Walline098aded72010-12-02 15:40:31 +01001060 .name = "ab8500-denc",
Lee Jonesbad76992012-07-02 17:10:56 +02001061 .of_compatible = "stericsson,ab8500-denc",
Mattias Walline098aded72010-12-02 15:40:31 +01001062 },
1063 {
Hongbo Zhang151621a2013-01-30 18:21:27 +08001064 .name = "abx500-temp",
1065 .of_compatible = "stericsson,abx500-temp",
Mattias Walline098aded72010-12-02 15:40:31 +01001066 .num_resources = ARRAY_SIZE(ab8500_temp_resources),
1067 .resources = ab8500_temp_resources,
Sundar R Iyer77686512010-09-05 12:18:47 -07001068 },
Rabin Vincent62579262010-05-19 11:39:02 +02001069};
1070
Bill Pembertona9e9ce42012-11-19 13:24:21 -05001071static struct mfd_cell ab8500_bm_devs[] = {
Rickard Andersson6ef94182012-04-17 09:30:57 +02001072 {
1073 .name = "ab8500-charger",
Rajanikanth H.V4aef72d2012-11-18 19:17:47 -08001074 .of_compatible = "stericsson,ab8500-charger",
Rickard Andersson6ef94182012-04-17 09:30:57 +02001075 .num_resources = ARRAY_SIZE(ab8500_charger_resources),
1076 .resources = ab8500_charger_resources,
Rajanikanth H.V4aef72d2012-11-18 19:17:47 -08001077 .platform_data = &ab8500_bm_data,
1078 .pdata_size = sizeof(ab8500_bm_data),
Rickard Andersson6ef94182012-04-17 09:30:57 +02001079 },
1080 {
1081 .name = "ab8500-btemp",
Rajanikanth H.Vbd9e8ab2012-11-18 19:16:58 -08001082 .of_compatible = "stericsson,ab8500-btemp",
Rickard Andersson6ef94182012-04-17 09:30:57 +02001083 .num_resources = ARRAY_SIZE(ab8500_btemp_resources),
1084 .resources = ab8500_btemp_resources,
Rajanikanth H.Vbd9e8ab2012-11-18 19:16:58 -08001085 .platform_data = &ab8500_bm_data,
1086 .pdata_size = sizeof(ab8500_bm_data),
Rickard Andersson6ef94182012-04-17 09:30:57 +02001087 },
1088 {
1089 .name = "ab8500-fg",
Rajanikanth H.Ve0f1abe2012-11-18 18:45:41 -08001090 .of_compatible = "stericsson,ab8500-fg",
Rickard Andersson6ef94182012-04-17 09:30:57 +02001091 .num_resources = ARRAY_SIZE(ab8500_fg_resources),
1092 .resources = ab8500_fg_resources,
Rajanikanth H.Ve0f1abe2012-11-18 18:45:41 -08001093 .platform_data = &ab8500_bm_data,
1094 .pdata_size = sizeof(ab8500_bm_data),
Rickard Andersson6ef94182012-04-17 09:30:57 +02001095 },
1096 {
1097 .name = "ab8500-chargalg",
Rajanikanth H.Va12810a2012-10-31 15:40:33 +00001098 .of_compatible = "stericsson,ab8500-chargalg",
Rickard Andersson6ef94182012-04-17 09:30:57 +02001099 .num_resources = ARRAY_SIZE(ab8500_chargalg_resources),
1100 .resources = ab8500_chargalg_resources,
Rajanikanth H.Va12810a2012-10-31 15:40:33 +00001101 .platform_data = &ab8500_bm_data,
1102 .pdata_size = sizeof(ab8500_bm_data),
Rickard Andersson6ef94182012-04-17 09:30:57 +02001103 },
1104};
1105
Bill Pembertona9e9ce42012-11-19 13:24:21 -05001106static struct mfd_cell ab8500_devs[] = {
Linus Walleijd6255522012-02-20 21:42:24 +01001107 {
Lee Jones7d56a462013-01-16 14:49:45 +00001108 .name = "pinctrl-ab8500",
Lee Jonesbad76992012-07-02 17:10:56 +02001109 .of_compatible = "stericsson,ab8500-gpio",
Linus Walleijd6255522012-02-20 21:42:24 +01001110 },
1111 {
1112 .name = "ab8500-usb",
Lee Jonesbad76992012-07-02 17:10:56 +02001113 .of_compatible = "stericsson,ab8500-usb",
Linus Walleijd6255522012-02-20 21:42:24 +01001114 .num_resources = ARRAY_SIZE(ab8500_usb_resources),
1115 .resources = ab8500_usb_resources,
1116 },
Virupax Sadashivpetimath44f72e52012-04-17 09:30:14 +02001117 {
1118 .name = "ab8500-codec",
Lee Jones81a21cd2012-07-27 13:38:51 +01001119 .of_compatible = "stericsson,ab8500-codec",
Virupax Sadashivpetimath44f72e52012-04-17 09:30:14 +02001120 },
Linus Walleijd6255522012-02-20 21:42:24 +01001121};
1122
Bill Pembertona9e9ce42012-11-19 13:24:21 -05001123static struct mfd_cell ab9540_devs[] = {
Linus Walleijd6255522012-02-20 21:42:24 +01001124 {
Lee Jonese64d9052013-01-16 15:09:36 +00001125 .name = "pinctrl-ab9540",
1126 .of_compatible = "stericsson,ab9540-gpio",
Linus Walleijd6255522012-02-20 21:42:24 +01001127 },
1128 {
1129 .name = "ab9540-usb",
1130 .num_resources = ARRAY_SIZE(ab8500_usb_resources),
1131 .resources = ab8500_usb_resources,
1132 },
Virupax Sadashivpetimath44f72e52012-04-17 09:30:14 +02001133 {
1134 .name = "ab9540-codec",
1135 },
1136};
1137
1138/* Device list common to ab9540 and ab8505 */
Bill Pembertona9e9ce42012-11-19 13:24:21 -05001139static struct mfd_cell ab9540_ab8505_devs[] = {
Virupax Sadashivpetimath44f72e52012-04-17 09:30:14 +02001140 {
1141 .name = "ab-iddet",
1142 .num_resources = ARRAY_SIZE(ab8505_iddet_resources),
1143 .resources = ab8505_iddet_resources,
1144 },
Linus Walleijd6255522012-02-20 21:42:24 +01001145};
1146
Mattias Wallincca69b62010-12-02 15:09:36 +01001147static ssize_t show_chip_id(struct device *dev,
1148 struct device_attribute *attr, char *buf)
1149{
1150 struct ab8500 *ab8500;
1151
1152 ab8500 = dev_get_drvdata(dev);
1153 return sprintf(buf, "%#x\n", ab8500 ? ab8500->chip_id : -EINVAL);
1154}
1155
Mattias Walline5c238c2011-03-02 11:52:36 +01001156/*
1157 * ab8500 has switched off due to (SWITCH_OFF_STATUS):
1158 * 0x01 Swoff bit programming
1159 * 0x02 Thermal protection activation
1160 * 0x04 Vbat lower then BattOk falling threshold
1161 * 0x08 Watchdog expired
1162 * 0x10 Non presence of 32kHz clock
1163 * 0x20 Battery level lower than power on reset threshold
1164 * 0x40 Power on key 1 pressed longer than 10 seconds
1165 * 0x80 DB8500 thermal shutdown
1166 */
1167static ssize_t show_switch_off_status(struct device *dev,
1168 struct device_attribute *attr, char *buf)
1169{
1170 int ret;
1171 u8 value;
1172 struct ab8500 *ab8500;
1173
1174 ab8500 = dev_get_drvdata(dev);
1175 ret = get_register_interruptible(ab8500, AB8500_RTC,
1176 AB8500_SWITCH_OFF_STATUS, &value);
1177 if (ret < 0)
1178 return ret;
1179 return sprintf(buf, "%#x\n", value);
1180}
1181
Rajkumar Kasirajanf04a9d82012-05-30 16:32:37 +05301182/* use mask and set to override the register turn_on_stat value */
1183void ab8500_override_turn_on_stat(u8 mask, u8 set)
1184{
1185 spin_lock(&on_stat_lock);
1186 turn_on_stat_mask = mask;
1187 turn_on_stat_set = set;
1188 spin_unlock(&on_stat_lock);
1189}
1190
Andrew Lynnb4a31032011-10-11 10:49:47 +02001191/*
1192 * ab8500 has turned on due to (TURN_ON_STATUS):
1193 * 0x01 PORnVbat
1194 * 0x02 PonKey1dbF
1195 * 0x04 PonKey2dbF
1196 * 0x08 RTCAlarm
1197 * 0x10 MainChDet
1198 * 0x20 VbusDet
1199 * 0x40 UsbIDDetect
1200 * 0x80 Reserved
1201 */
1202static ssize_t show_turn_on_status(struct device *dev,
1203 struct device_attribute *attr, char *buf)
1204{
1205 int ret;
1206 u8 value;
1207 struct ab8500 *ab8500;
1208
1209 ab8500 = dev_get_drvdata(dev);
1210 ret = get_register_interruptible(ab8500, AB8500_SYS_CTRL1_BLOCK,
1211 AB8500_TURN_ON_STATUS, &value);
1212 if (ret < 0)
1213 return ret;
Rajkumar Kasirajanf04a9d82012-05-30 16:32:37 +05301214
1215 /*
1216 * In L9540, turn_on_status register is not updated correctly if
1217 * the device is rebooted with AC/USB charger connected. Due to
1218 * this, the device boots android instead of entering into charge
1219 * only mode. Read the AC/USB status register to detect the charger
1220 * presence and update the turn on status manually.
1221 */
1222 if (is_ab9540(ab8500)) {
1223 spin_lock(&on_stat_lock);
1224 value = (value & turn_on_stat_mask) | turn_on_stat_set;
1225 spin_unlock(&on_stat_lock);
1226 }
1227
Andrew Lynnb4a31032011-10-11 10:49:47 +02001228 return sprintf(buf, "%#x\n", value);
1229}
1230
Linus Walleijd6255522012-02-20 21:42:24 +01001231static ssize_t show_ab9540_dbbrstn(struct device *dev,
1232 struct device_attribute *attr, char *buf)
1233{
1234 struct ab8500 *ab8500;
1235 int ret;
1236 u8 value;
1237
1238 ab8500 = dev_get_drvdata(dev);
1239
1240 ret = get_register_interruptible(ab8500, AB8500_REGU_CTRL2,
1241 AB9540_MODEM_CTRL2_REG, &value);
1242 if (ret < 0)
1243 return ret;
1244
1245 return sprintf(buf, "%d\n",
1246 (value & AB9540_MODEM_CTRL2_SWDBBRSTN_BIT) ? 1 : 0);
1247}
1248
1249static ssize_t store_ab9540_dbbrstn(struct device *dev,
1250 struct device_attribute *attr, const char *buf, size_t count)
1251{
1252 struct ab8500 *ab8500;
1253 int ret = count;
1254 int err;
1255 u8 bitvalues;
1256
1257 ab8500 = dev_get_drvdata(dev);
1258
1259 if (count > 0) {
1260 switch (buf[0]) {
1261 case '0':
1262 bitvalues = 0;
1263 break;
1264 case '1':
1265 bitvalues = AB9540_MODEM_CTRL2_SWDBBRSTN_BIT;
1266 break;
1267 default:
1268 goto exit;
1269 }
1270
1271 err = mask_and_set_register_interruptible(ab8500,
1272 AB8500_REGU_CTRL2, AB9540_MODEM_CTRL2_REG,
1273 AB9540_MODEM_CTRL2_SWDBBRSTN_BIT, bitvalues);
1274 if (err)
1275 dev_info(ab8500->dev,
1276 "Failed to set DBBRSTN %c, err %#x\n",
1277 buf[0], err);
1278 }
1279
1280exit:
1281 return ret;
1282}
1283
Mattias Wallincca69b62010-12-02 15:09:36 +01001284static DEVICE_ATTR(chip_id, S_IRUGO, show_chip_id, NULL);
Mattias Walline5c238c2011-03-02 11:52:36 +01001285static DEVICE_ATTR(switch_off_status, S_IRUGO, show_switch_off_status, NULL);
Andrew Lynnb4a31032011-10-11 10:49:47 +02001286static DEVICE_ATTR(turn_on_status, S_IRUGO, show_turn_on_status, NULL);
Linus Walleijd6255522012-02-20 21:42:24 +01001287static DEVICE_ATTR(dbbrstn, S_IRUGO | S_IWUSR,
1288 show_ab9540_dbbrstn, store_ab9540_dbbrstn);
Mattias Wallincca69b62010-12-02 15:09:36 +01001289
1290static struct attribute *ab8500_sysfs_entries[] = {
1291 &dev_attr_chip_id.attr,
Mattias Walline5c238c2011-03-02 11:52:36 +01001292 &dev_attr_switch_off_status.attr,
Andrew Lynnb4a31032011-10-11 10:49:47 +02001293 &dev_attr_turn_on_status.attr,
Mattias Wallincca69b62010-12-02 15:09:36 +01001294 NULL,
1295};
1296
Linus Walleijd6255522012-02-20 21:42:24 +01001297static struct attribute *ab9540_sysfs_entries[] = {
1298 &dev_attr_chip_id.attr,
1299 &dev_attr_switch_off_status.attr,
1300 &dev_attr_turn_on_status.attr,
1301 &dev_attr_dbbrstn.attr,
1302 NULL,
1303};
1304
Mattias Wallincca69b62010-12-02 15:09:36 +01001305static struct attribute_group ab8500_attr_group = {
1306 .attrs = ab8500_sysfs_entries,
1307};
1308
Linus Walleijd6255522012-02-20 21:42:24 +01001309static struct attribute_group ab9540_attr_group = {
1310 .attrs = ab9540_sysfs_entries,
1311};
1312
Bill Pembertonf791be42012-11-19 13:23:04 -05001313static int ab8500_probe(struct platform_device *pdev)
Rabin Vincent62579262010-05-19 11:39:02 +02001314{
Jonas Aabergb04c530c2012-06-29 17:46:12 +02001315 static char *switch_off_status[] = {
1316 "Swoff bit programming",
1317 "Thermal protection activation",
1318 "Vbat lower then BattOk falling threshold",
1319 "Watchdog expired",
1320 "Non presence of 32kHz clock",
1321 "Battery level lower than power on reset threshold",
1322 "Power on key 1 pressed longer than 10 seconds",
1323 "DB8500 thermal shutdown"};
Lee Jonesd28f1db2012-05-19 17:21:37 +02001324 struct ab8500_platform_data *plat = dev_get_platdata(&pdev->dev);
1325 const struct platform_device_id *platid = platform_get_device_id(pdev);
Lee Jones6bc4a562012-05-17 14:45:13 +01001326 enum ab8500_version version = AB8500_VERSION_UNDEFINED;
1327 struct device_node *np = pdev->dev.of_node;
Lee Jonesd28f1db2012-05-19 17:21:37 +02001328 struct ab8500 *ab8500;
1329 struct resource *resource;
Rabin Vincent62579262010-05-19 11:39:02 +02001330 int ret;
1331 int i;
Mattias Wallin47c16972010-09-10 17:47:56 +02001332 u8 value;
Rabin Vincent62579262010-05-19 11:39:02 +02001333
Lee Jones8c4203c2012-11-05 16:10:35 +01001334 ab8500 = devm_kzalloc(&pdev->dev, sizeof *ab8500, GFP_KERNEL);
Lee Jonesd28f1db2012-05-19 17:21:37 +02001335 if (!ab8500)
1336 return -ENOMEM;
1337
Rabin Vincent62579262010-05-19 11:39:02 +02001338 if (plat)
1339 ab8500->irq_base = plat->irq_base;
1340
Lee Jonesd28f1db2012-05-19 17:21:37 +02001341 ab8500->dev = &pdev->dev;
1342
1343 resource = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
Lee Jones8c4203c2012-11-05 16:10:35 +01001344 if (!resource)
1345 return -ENODEV;
Lee Jonesd28f1db2012-05-19 17:21:37 +02001346
1347 ab8500->irq = resource->start;
1348
Lee Jones822672a2012-06-20 13:56:38 +01001349 ab8500->read = ab8500_prcmu_read;
1350 ab8500->write = ab8500_prcmu_write;
1351 ab8500->write_masked = ab8500_prcmu_write_masked;
Lee Jonesd28f1db2012-05-19 17:21:37 +02001352
Rabin Vincent62579262010-05-19 11:39:02 +02001353 mutex_init(&ab8500->lock);
1354 mutex_init(&ab8500->irq_lock);
Jonas Aaberg112a80d2012-04-17 09:30:33 +02001355 atomic_set(&ab8500->transfer_ongoing, 0);
Rabin Vincent62579262010-05-19 11:39:02 +02001356
Lee Jonesd28f1db2012-05-19 17:21:37 +02001357 platform_set_drvdata(pdev, ab8500);
1358
Lee Jones6bc4a562012-05-17 14:45:13 +01001359 if (platid)
1360 version = platid->driver_data;
Lee Jones6bc4a562012-05-17 14:45:13 +01001361
Linus Walleij0f6208372012-02-20 21:42:10 +01001362 if (version != AB8500_VERSION_UNDEFINED)
1363 ab8500->version = version;
1364 else {
1365 ret = get_register_interruptible(ab8500, AB8500_MISC,
1366 AB8500_IC_NAME_REG, &value);
1367 if (ret < 0)
Lee Jones8c4203c2012-11-05 16:10:35 +01001368 return ret;
Linus Walleij0f6208372012-02-20 21:42:10 +01001369
1370 ab8500->version = value;
1371 }
1372
Mattias Wallin47c16972010-09-10 17:47:56 +02001373 ret = get_register_interruptible(ab8500, AB8500_MISC,
1374 AB8500_REV_REG, &value);
Rabin Vincent62579262010-05-19 11:39:02 +02001375 if (ret < 0)
Lee Jones8c4203c2012-11-05 16:10:35 +01001376 return ret;
Rabin Vincent62579262010-05-19 11:39:02 +02001377
Mattias Wallin47c16972010-09-10 17:47:56 +02001378 ab8500->chip_id = value;
Rabin Vincent62579262010-05-19 11:39:02 +02001379
Linus Walleij0f6208372012-02-20 21:42:10 +01001380 dev_info(ab8500->dev, "detected chip, %s rev. %1x.%1x\n",
1381 ab8500_version_str[ab8500->version],
1382 ab8500->chip_id >> 4,
1383 ab8500->chip_id & 0x0F);
1384
Linus Walleijd6255522012-02-20 21:42:24 +01001385 /* Configure AB8500 or AB9540 IRQ */
Bengt Jonssona9823622012-03-08 14:01:57 +01001386 if (is_ab9540(ab8500) || is_ab8505(ab8500)) {
Linus Walleijd6255522012-02-20 21:42:24 +01001387 ab8500->mask_size = AB9540_NUM_IRQ_REGS;
1388 ab8500->irq_reg_offset = ab9540_irq_regoffset;
1389 } else {
1390 ab8500->mask_size = AB8500_NUM_IRQ_REGS;
1391 ab8500->irq_reg_offset = ab8500_irq_regoffset;
1392 }
Lee Jones8c4203c2012-11-05 16:10:35 +01001393 ab8500->mask = devm_kzalloc(&pdev->dev, ab8500->mask_size, GFP_KERNEL);
Linus Walleij2ced4452012-02-20 21:42:17 +01001394 if (!ab8500->mask)
1395 return -ENOMEM;
Lee Jones8c4203c2012-11-05 16:10:35 +01001396 ab8500->oldmask = devm_kzalloc(&pdev->dev, ab8500->mask_size, GFP_KERNEL);
1397 if (!ab8500->oldmask)
1398 return -ENOMEM;
1399
Mattias Walline5c238c2011-03-02 11:52:36 +01001400 /*
1401 * ab8500 has switched off due to (SWITCH_OFF_STATUS):
1402 * 0x01 Swoff bit programming
1403 * 0x02 Thermal protection activation
1404 * 0x04 Vbat lower then BattOk falling threshold
1405 * 0x08 Watchdog expired
1406 * 0x10 Non presence of 32kHz clock
1407 * 0x20 Battery level lower than power on reset threshold
1408 * 0x40 Power on key 1 pressed longer than 10 seconds
1409 * 0x80 DB8500 thermal shutdown
1410 */
1411
1412 ret = get_register_interruptible(ab8500, AB8500_RTC,
1413 AB8500_SWITCH_OFF_STATUS, &value);
1414 if (ret < 0)
1415 return ret;
Jonas Aabergb04c530c2012-06-29 17:46:12 +02001416 dev_info(ab8500->dev, "switch off cause(s) (%#x): ", value);
1417
1418 if (value) {
1419 for (i = 0; i < ARRAY_SIZE(switch_off_status); i++) {
1420 if (value & 1)
1421 printk(KERN_CONT " \"%s\"",
1422 switch_off_status[i]);
1423 value = value >> 1;
1424
1425 }
1426 printk(KERN_CONT "\n");
1427 } else {
1428 printk(KERN_CONT " None\n");
1429 }
Mattias Walline5c238c2011-03-02 11:52:36 +01001430
Rabin Vincent62579262010-05-19 11:39:02 +02001431 if (plat && plat->init)
1432 plat->init(ab8500);
Rajkumar Kasirajanf04a9d82012-05-30 16:32:37 +05301433 if (is_ab9540(ab8500)) {
1434 ret = get_register_interruptible(ab8500, AB8500_CHARGER,
1435 AB8500_CH_USBCH_STAT1_REG, &value);
1436 if (ret < 0)
1437 return ret;
1438 if ((value & VBUS_DET_DBNC1) && (value & VBUS_DET_DBNC100))
1439 ab8500_override_turn_on_stat(~AB8500_POW_KEY_1_ON,
1440 AB8500_VBUS_DET);
1441 }
Rabin Vincent62579262010-05-19 11:39:02 +02001442
1443 /* Clear and mask all interrupts */
Linus Walleij2ced4452012-02-20 21:42:17 +01001444 for (i = 0; i < ab8500->mask_size; i++) {
Linus Walleij0f6208372012-02-20 21:42:10 +01001445 /*
1446 * Interrupt register 12 doesn't exist prior to AB8500 version
1447 * 2.0
1448 */
1449 if (ab8500->irq_reg_offset[i] == 11 &&
1450 is_ab8500_1p1_or_earlier(ab8500))
Mattias Wallin92d50a42010-12-07 11:20:47 +01001451 continue;
Rabin Vincent62579262010-05-19 11:39:02 +02001452
Mattias Wallin47c16972010-09-10 17:47:56 +02001453 get_register_interruptible(ab8500, AB8500_INTERRUPT,
Linus Walleij2ced4452012-02-20 21:42:17 +01001454 AB8500_IT_LATCH1_REG + ab8500->irq_reg_offset[i],
Mattias Wallin92d50a42010-12-07 11:20:47 +01001455 &value);
Mattias Wallin47c16972010-09-10 17:47:56 +02001456 set_register_interruptible(ab8500, AB8500_INTERRUPT,
Linus Walleij2ced4452012-02-20 21:42:17 +01001457 AB8500_IT_MASK1_REG + ab8500->irq_reg_offset[i], 0xff);
Rabin Vincent62579262010-05-19 11:39:02 +02001458 }
1459
Mattias Wallin47c16972010-09-10 17:47:56 +02001460 ret = abx500_register_ops(ab8500->dev, &ab8500_ops);
1461 if (ret)
Lee Jones8c4203c2012-11-05 16:10:35 +01001462 return ret;
Mattias Wallin47c16972010-09-10 17:47:56 +02001463
Linus Walleij2ced4452012-02-20 21:42:17 +01001464 for (i = 0; i < ab8500->mask_size; i++)
Rabin Vincent62579262010-05-19 11:39:02 +02001465 ab8500->mask[i] = ab8500->oldmask[i] = 0xff;
1466
Lee Jones06e589e2012-06-20 13:56:37 +01001467 ret = ab8500_irq_init(ab8500, np);
1468 if (ret)
Lee Jones8c4203c2012-11-05 16:10:35 +01001469 return ret;
Rabin Vincent62579262010-05-19 11:39:02 +02001470
Lee Jones06e589e2012-06-20 13:56:37 +01001471 /* Activate this feature only in ab9540 */
1472 /* till tests are done on ab8500 1p2 or later*/
1473 if (is_ab9540(ab8500)) {
Lee Jones8c4203c2012-11-05 16:10:35 +01001474 ret = devm_request_threaded_irq(&pdev->dev, ab8500->irq, NULL,
1475 ab8500_hierarchical_irq,
1476 IRQF_ONESHOT | IRQF_NO_SUSPEND,
1477 "ab8500", ab8500);
Lee Jones06e589e2012-06-20 13:56:37 +01001478 }
1479 else {
Lee Jones8c4203c2012-11-05 16:10:35 +01001480 ret = devm_request_threaded_irq(&pdev->dev, ab8500->irq, NULL,
1481 ab8500_irq,
1482 IRQF_ONESHOT | IRQF_NO_SUSPEND,
1483 "ab8500", ab8500);
Rabin Vincent62579262010-05-19 11:39:02 +02001484 if (ret)
Lee Jones8c4203c2012-11-05 16:10:35 +01001485 return ret;
Rabin Vincent62579262010-05-19 11:39:02 +02001486 }
1487
Lee Jonesbad76992012-07-02 17:10:56 +02001488 ret = mfd_add_devices(ab8500->dev, 0, abx500_common_devs,
1489 ARRAY_SIZE(abx500_common_devs), NULL,
Mark Brown55692af2012-09-11 15:16:36 +08001490 ab8500->irq_base, ab8500->domain);
Lee Jonesbad76992012-07-02 17:10:56 +02001491 if (ret)
Lee Jones8c4203c2012-11-05 16:10:35 +01001492 return ret;
Lee Jonesbad76992012-07-02 17:10:56 +02001493
1494 if (is_ab9540(ab8500))
1495 ret = mfd_add_devices(ab8500->dev, 0, ab9540_devs,
1496 ARRAY_SIZE(ab9540_devs), NULL,
Mark Brown55692af2012-09-11 15:16:36 +08001497 ab8500->irq_base, ab8500->domain);
Lee Jonesbad76992012-07-02 17:10:56 +02001498 else
1499 ret = mfd_add_devices(ab8500->dev, 0, ab8500_devs,
1500 ARRAY_SIZE(ab8500_devs), NULL,
Mark Brown55692af2012-09-11 15:16:36 +08001501 ab8500->irq_base, ab8500->domain);
Lee Jonesbad76992012-07-02 17:10:56 +02001502 if (ret)
Lee Jones8c4203c2012-11-05 16:10:35 +01001503 return ret;
Linus Walleijd6255522012-02-20 21:42:24 +01001504
Lee Jonesbad76992012-07-02 17:10:56 +02001505 if (is_ab9540(ab8500) || is_ab8505(ab8500))
1506 ret = mfd_add_devices(ab8500->dev, 0, ab9540_ab8505_devs,
1507 ARRAY_SIZE(ab9540_ab8505_devs), NULL,
Mark Brown55692af2012-09-11 15:16:36 +08001508 ab8500->irq_base, ab8500->domain);
Lee Jonesbad76992012-07-02 17:10:56 +02001509 if (ret)
Lee Jones8c4203c2012-11-05 16:10:35 +01001510 return ret;
Rabin Vincent62579262010-05-19 11:39:02 +02001511
Rickard Andersson6ef94182012-04-17 09:30:57 +02001512 if (!no_bm) {
1513 /* Add battery management devices */
1514 ret = mfd_add_devices(ab8500->dev, 0, ab8500_bm_devs,
1515 ARRAY_SIZE(ab8500_bm_devs), NULL,
Mark Brown55692af2012-09-11 15:16:36 +08001516 ab8500->irq_base, ab8500->domain);
Rickard Andersson6ef94182012-04-17 09:30:57 +02001517 if (ret)
1518 dev_err(ab8500->dev, "error adding bm devices\n");
1519 }
1520
Linus Walleijd6255522012-02-20 21:42:24 +01001521 if (is_ab9540(ab8500))
1522 ret = sysfs_create_group(&ab8500->dev->kobj,
1523 &ab9540_attr_group);
1524 else
1525 ret = sysfs_create_group(&ab8500->dev->kobj,
1526 &ab8500_attr_group);
Mattias Wallincca69b62010-12-02 15:09:36 +01001527 if (ret)
1528 dev_err(ab8500->dev, "error creating sysfs entries\n");
Lee Jones06e589e2012-06-20 13:56:37 +01001529
1530 return ret;
Rabin Vincent62579262010-05-19 11:39:02 +02001531}
1532
Bill Pemberton4740f732012-11-19 13:26:01 -05001533static int ab8500_remove(struct platform_device *pdev)
Rabin Vincent62579262010-05-19 11:39:02 +02001534{
Lee Jonesd28f1db2012-05-19 17:21:37 +02001535 struct ab8500 *ab8500 = platform_get_drvdata(pdev);
1536
Linus Walleijd6255522012-02-20 21:42:24 +01001537 if (is_ab9540(ab8500))
1538 sysfs_remove_group(&ab8500->dev->kobj, &ab9540_attr_group);
1539 else
1540 sysfs_remove_group(&ab8500->dev->kobj, &ab8500_attr_group);
Lee Jones06e589e2012-06-20 13:56:37 +01001541
Rabin Vincent62579262010-05-19 11:39:02 +02001542 mfd_remove_devices(ab8500->dev);
Rabin Vincent62579262010-05-19 11:39:02 +02001543
1544 return 0;
1545}
1546
Lee Jonesd28f1db2012-05-19 17:21:37 +02001547static const struct platform_device_id ab8500_id[] = {
1548 { "ab8500-core", AB8500_VERSION_AB8500 },
1549 { "ab8505-i2c", AB8500_VERSION_AB8505 },
1550 { "ab9540-i2c", AB8500_VERSION_AB9540 },
1551 { "ab8540-i2c", AB8500_VERSION_AB8540 },
1552 { }
1553};
1554
1555static struct platform_driver ab8500_core_driver = {
1556 .driver = {
1557 .name = "ab8500-core",
1558 .owner = THIS_MODULE,
1559 },
1560 .probe = ab8500_probe,
Bill Pemberton84449212012-11-19 13:20:24 -05001561 .remove = ab8500_remove,
Lee Jonesd28f1db2012-05-19 17:21:37 +02001562 .id_table = ab8500_id,
1563};
1564
1565static int __init ab8500_core_init(void)
1566{
1567 return platform_driver_register(&ab8500_core_driver);
1568}
1569
1570static void __exit ab8500_core_exit(void)
1571{
1572 platform_driver_unregister(&ab8500_core_driver);
1573}
Lee Jonesba7cbc32012-06-11 16:25:00 +01001574core_initcall(ab8500_core_init);
Lee Jonesd28f1db2012-05-19 17:21:37 +02001575module_exit(ab8500_core_exit);
1576
Mattias Wallinadceed62011-03-02 11:51:11 +01001577MODULE_AUTHOR("Mattias Wallin, Srinidhi Kasagar, Rabin Vincent");
Rabin Vincent62579262010-05-19 11:39:02 +02001578MODULE_DESCRIPTION("AB8500 MFD core");
1579MODULE_LICENSE("GPL v2");