blob: 23db4fcea49639d3fb47dcb70745c01f31b57cf2 [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
Lee Jones4b106fb2013-02-25 14:42:00 +0000661static struct resource ab8505_gpadc_resources[] = {
Lee Jonesc0eda9a2013-02-12 15:04:09 +0000662 {
663 .name = "SW_CONV_END",
664 .start = AB8500_INT_GP_SW_ADC_CONV_END,
665 .end = AB8500_INT_GP_SW_ADC_CONV_END,
666 .flags = IORESOURCE_IRQ,
667 },
668};
669
Bill Pembertona9e9ce42012-11-19 13:24:21 -0500670static struct resource ab8500_rtc_resources[] = {
Rabin Vincent62579262010-05-19 11:39:02 +0200671 {
672 .name = "60S",
673 .start = AB8500_INT_RTC_60S,
674 .end = AB8500_INT_RTC_60S,
675 .flags = IORESOURCE_IRQ,
676 },
677 {
678 .name = "ALARM",
679 .start = AB8500_INT_RTC_ALARM,
680 .end = AB8500_INT_RTC_ALARM,
681 .flags = IORESOURCE_IRQ,
682 },
683};
684
Bill Pembertona9e9ce42012-11-19 13:24:21 -0500685static struct resource ab8500_poweronkey_db_resources[] = {
Sundar R Iyer77686512010-09-05 12:18:47 -0700686 {
687 .name = "ONKEY_DBF",
688 .start = AB8500_INT_PON_KEY1DB_F,
689 .end = AB8500_INT_PON_KEY1DB_F,
690 .flags = IORESOURCE_IRQ,
691 },
692 {
693 .name = "ONKEY_DBR",
694 .start = AB8500_INT_PON_KEY1DB_R,
695 .end = AB8500_INT_PON_KEY1DB_R,
696 .flags = IORESOURCE_IRQ,
697 },
698};
699
Bill Pembertona9e9ce42012-11-19 13:24:21 -0500700static struct resource ab8500_av_acc_detect_resources[] = {
Mattias Walline098aded72010-12-02 15:40:31 +0100701 {
Linus Walleij6af75ec2011-06-09 23:57:45 +0200702 .name = "ACC_DETECT_1DB_F",
703 .start = AB8500_INT_ACC_DETECT_1DB_F,
704 .end = AB8500_INT_ACC_DETECT_1DB_F,
705 .flags = IORESOURCE_IRQ,
Mattias Walline098aded72010-12-02 15:40:31 +0100706 },
707 {
Linus Walleij6af75ec2011-06-09 23:57:45 +0200708 .name = "ACC_DETECT_1DB_R",
709 .start = AB8500_INT_ACC_DETECT_1DB_R,
710 .end = AB8500_INT_ACC_DETECT_1DB_R,
711 .flags = IORESOURCE_IRQ,
Mattias Walline098aded72010-12-02 15:40:31 +0100712 },
713 {
Linus Walleij6af75ec2011-06-09 23:57:45 +0200714 .name = "ACC_DETECT_21DB_F",
715 .start = AB8500_INT_ACC_DETECT_21DB_F,
716 .end = AB8500_INT_ACC_DETECT_21DB_F,
717 .flags = IORESOURCE_IRQ,
718 },
719 {
720 .name = "ACC_DETECT_21DB_R",
721 .start = AB8500_INT_ACC_DETECT_21DB_R,
722 .end = AB8500_INT_ACC_DETECT_21DB_R,
723 .flags = IORESOURCE_IRQ,
724 },
725 {
726 .name = "ACC_DETECT_22DB_F",
727 .start = AB8500_INT_ACC_DETECT_22DB_F,
728 .end = AB8500_INT_ACC_DETECT_22DB_F,
729 .flags = IORESOURCE_IRQ,
730 },
731 {
732 .name = "ACC_DETECT_22DB_R",
733 .start = AB8500_INT_ACC_DETECT_22DB_R,
734 .end = AB8500_INT_ACC_DETECT_22DB_R,
735 .flags = IORESOURCE_IRQ,
736 },
737};
738
Bill Pembertona9e9ce42012-11-19 13:24:21 -0500739static struct resource ab8500_charger_resources[] = {
Linus Walleij6af75ec2011-06-09 23:57:45 +0200740 {
Mattias Walline098aded72010-12-02 15:40:31 +0100741 .name = "MAIN_CH_UNPLUG_DET",
742 .start = AB8500_INT_MAIN_CH_UNPLUG_DET,
743 .end = AB8500_INT_MAIN_CH_UNPLUG_DET,
744 .flags = IORESOURCE_IRQ,
745 },
746 {
747 .name = "MAIN_CHARGE_PLUG_DET",
748 .start = AB8500_INT_MAIN_CH_PLUG_DET,
749 .end = AB8500_INT_MAIN_CH_PLUG_DET,
750 .flags = IORESOURCE_IRQ,
751 },
752 {
Mattias Walline098aded72010-12-02 15:40:31 +0100753 .name = "VBUS_DET_R",
754 .start = AB8500_INT_VBUS_DET_R,
755 .end = AB8500_INT_VBUS_DET_R,
756 .flags = IORESOURCE_IRQ,
757 },
758 {
Linus Walleij6af75ec2011-06-09 23:57:45 +0200759 .name = "VBUS_DET_F",
760 .start = AB8500_INT_VBUS_DET_F,
761 .end = AB8500_INT_VBUS_DET_F,
Mattias Walline098aded72010-12-02 15:40:31 +0100762 .flags = IORESOURCE_IRQ,
763 },
764 {
Linus Walleij6af75ec2011-06-09 23:57:45 +0200765 .name = "USB_LINK_STATUS",
766 .start = AB8500_INT_USB_LINK_STATUS,
767 .end = AB8500_INT_USB_LINK_STATUS,
768 .flags = IORESOURCE_IRQ,
769 },
770 {
Mattias Walline098aded72010-12-02 15:40:31 +0100771 .name = "VBUS_OVV",
772 .start = AB8500_INT_VBUS_OVV,
773 .end = AB8500_INT_VBUS_OVV,
774 .flags = IORESOURCE_IRQ,
775 },
776 {
Linus Walleij6af75ec2011-06-09 23:57:45 +0200777 .name = "USB_CH_TH_PROT_R",
778 .start = AB8500_INT_USB_CH_TH_PROT_R,
779 .end = AB8500_INT_USB_CH_TH_PROT_R,
Mattias Walline098aded72010-12-02 15:40:31 +0100780 .flags = IORESOURCE_IRQ,
781 },
782 {
Linus Walleij6af75ec2011-06-09 23:57:45 +0200783 .name = "USB_CH_TH_PROT_F",
784 .start = AB8500_INT_USB_CH_TH_PROT_F,
785 .end = AB8500_INT_USB_CH_TH_PROT_F,
Mattias Walline098aded72010-12-02 15:40:31 +0100786 .flags = IORESOURCE_IRQ,
787 },
788 {
Linus Walleij6af75ec2011-06-09 23:57:45 +0200789 .name = "MAIN_EXT_CH_NOT_OK",
790 .start = AB8500_INT_MAIN_EXT_CH_NOT_OK,
791 .end = AB8500_INT_MAIN_EXT_CH_NOT_OK,
792 .flags = IORESOURCE_IRQ,
793 },
794 {
795 .name = "MAIN_CH_TH_PROT_R",
796 .start = AB8500_INT_MAIN_CH_TH_PROT_R,
797 .end = AB8500_INT_MAIN_CH_TH_PROT_R,
798 .flags = IORESOURCE_IRQ,
799 },
800 {
801 .name = "MAIN_CH_TH_PROT_F",
802 .start = AB8500_INT_MAIN_CH_TH_PROT_F,
803 .end = AB8500_INT_MAIN_CH_TH_PROT_F,
804 .flags = IORESOURCE_IRQ,
805 },
806 {
807 .name = "USB_CHARGER_NOT_OKR",
Bengt Jonssona9823622012-03-08 14:01:57 +0100808 .start = AB8500_INT_USB_CHARGER_NOT_OKR,
809 .end = AB8500_INT_USB_CHARGER_NOT_OKR,
Linus Walleij6af75ec2011-06-09 23:57:45 +0200810 .flags = IORESOURCE_IRQ,
811 },
812 {
813 .name = "CH_WD_EXP",
814 .start = AB8500_INT_CH_WD_EXP,
815 .end = AB8500_INT_CH_WD_EXP,
816 .flags = IORESOURCE_IRQ,
817 },
Paer-Olof Haakansson34c11a72012-02-22 19:07:51 +0100818 {
819 .name = "VBUS_CH_DROP_END",
820 .start = AB8500_INT_VBUS_CH_DROP_END,
821 .end = AB8500_INT_VBUS_CH_DROP_END,
822 .flags = IORESOURCE_IRQ,
823 },
Linus Walleij6af75ec2011-06-09 23:57:45 +0200824};
825
Bill Pembertona9e9ce42012-11-19 13:24:21 -0500826static struct resource ab8500_btemp_resources[] = {
Linus Walleij6af75ec2011-06-09 23:57:45 +0200827 {
828 .name = "BAT_CTRL_INDB",
829 .start = AB8500_INT_BAT_CTRL_INDB,
830 .end = AB8500_INT_BAT_CTRL_INDB,
Mattias Walline098aded72010-12-02 15:40:31 +0100831 .flags = IORESOURCE_IRQ,
832 },
833 {
834 .name = "BTEMP_LOW",
835 .start = AB8500_INT_BTEMP_LOW,
836 .end = AB8500_INT_BTEMP_LOW,
837 .flags = IORESOURCE_IRQ,
838 },
839 {
840 .name = "BTEMP_HIGH",
841 .start = AB8500_INT_BTEMP_HIGH,
842 .end = AB8500_INT_BTEMP_HIGH,
843 .flags = IORESOURCE_IRQ,
844 },
845 {
Linus Walleij6af75ec2011-06-09 23:57:45 +0200846 .name = "BTEMP_LOW_MEDIUM",
847 .start = AB8500_INT_BTEMP_LOW_MEDIUM,
848 .end = AB8500_INT_BTEMP_LOW_MEDIUM,
Mattias Walline098aded72010-12-02 15:40:31 +0100849 .flags = IORESOURCE_IRQ,
850 },
851 {
Linus Walleij6af75ec2011-06-09 23:57:45 +0200852 .name = "BTEMP_MEDIUM_HIGH",
853 .start = AB8500_INT_BTEMP_MEDIUM_HIGH,
854 .end = AB8500_INT_BTEMP_MEDIUM_HIGH,
Mattias Walline098aded72010-12-02 15:40:31 +0100855 .flags = IORESOURCE_IRQ,
856 },
857};
858
Bill Pembertona9e9ce42012-11-19 13:24:21 -0500859static struct resource ab8500_fg_resources[] = {
Linus Walleij6af75ec2011-06-09 23:57:45 +0200860 {
861 .name = "NCONV_ACCU",
862 .start = AB8500_INT_CCN_CONV_ACC,
863 .end = AB8500_INT_CCN_CONV_ACC,
864 .flags = IORESOURCE_IRQ,
865 },
866 {
867 .name = "BATT_OVV",
868 .start = AB8500_INT_BATT_OVV,
869 .end = AB8500_INT_BATT_OVV,
870 .flags = IORESOURCE_IRQ,
871 },
872 {
873 .name = "LOW_BAT_F",
874 .start = AB8500_INT_LOW_BAT_F,
875 .end = AB8500_INT_LOW_BAT_F,
876 .flags = IORESOURCE_IRQ,
877 },
878 {
879 .name = "LOW_BAT_R",
880 .start = AB8500_INT_LOW_BAT_R,
881 .end = AB8500_INT_LOW_BAT_R,
882 .flags = IORESOURCE_IRQ,
883 },
884 {
885 .name = "CC_INT_CALIB",
886 .start = AB8500_INT_CC_INT_CALIB,
887 .end = AB8500_INT_CC_INT_CALIB,
888 .flags = IORESOURCE_IRQ,
889 },
Bengt Jonssona9823622012-03-08 14:01:57 +0100890 {
891 .name = "CCEOC",
892 .start = AB8500_INT_CCEOC,
893 .end = AB8500_INT_CCEOC,
894 .flags = IORESOURCE_IRQ,
895 },
Linus Walleij6af75ec2011-06-09 23:57:45 +0200896};
897
Bill Pembertona9e9ce42012-11-19 13:24:21 -0500898static struct resource ab8500_chargalg_resources[] = {};
Linus Walleij6af75ec2011-06-09 23:57:45 +0200899
Axel Lindf720642011-11-10 09:56:18 +0800900#ifdef CONFIG_DEBUG_FS
Bill Pembertona9e9ce42012-11-19 13:24:21 -0500901static struct resource ab8500_debug_resources[] = {
Mattias Walline098aded72010-12-02 15:40:31 +0100902 {
903 .name = "IRQ_FIRST",
904 .start = AB8500_INT_MAIN_EXT_CH_NOT_OK,
905 .end = AB8500_INT_MAIN_EXT_CH_NOT_OK,
906 .flags = IORESOURCE_IRQ,
907 },
908 {
909 .name = "IRQ_LAST",
Bengt Jonssona9823622012-03-08 14:01:57 +0100910 .start = AB8500_INT_XTAL32K_KO,
911 .end = AB8500_INT_XTAL32K_KO,
Mattias Walline098aded72010-12-02 15:40:31 +0100912 .flags = IORESOURCE_IRQ,
913 },
914};
Axel Lindf720642011-11-10 09:56:18 +0800915#endif
Mattias Walline098aded72010-12-02 15:40:31 +0100916
Bill Pembertona9e9ce42012-11-19 13:24:21 -0500917static struct resource ab8500_usb_resources[] = {
Mattias Walline098aded72010-12-02 15:40:31 +0100918 {
919 .name = "ID_WAKEUP_R",
920 .start = AB8500_INT_ID_WAKEUP_R,
921 .end = AB8500_INT_ID_WAKEUP_R,
922 .flags = IORESOURCE_IRQ,
923 },
924 {
925 .name = "ID_WAKEUP_F",
926 .start = AB8500_INT_ID_WAKEUP_F,
927 .end = AB8500_INT_ID_WAKEUP_F,
928 .flags = IORESOURCE_IRQ,
929 },
930 {
931 .name = "VBUS_DET_F",
932 .start = AB8500_INT_VBUS_DET_F,
933 .end = AB8500_INT_VBUS_DET_F,
934 .flags = IORESOURCE_IRQ,
935 },
936 {
937 .name = "VBUS_DET_R",
938 .start = AB8500_INT_VBUS_DET_R,
939 .end = AB8500_INT_VBUS_DET_R,
940 .flags = IORESOURCE_IRQ,
941 },
Mattias Wallin92d50a42010-12-07 11:20:47 +0100942 {
943 .name = "USB_LINK_STATUS",
944 .start = AB8500_INT_USB_LINK_STATUS,
945 .end = AB8500_INT_USB_LINK_STATUS,
946 .flags = IORESOURCE_IRQ,
947 },
Linus Walleij6af75ec2011-06-09 23:57:45 +0200948 {
949 .name = "USB_ADP_PROBE_PLUG",
950 .start = AB8500_INT_ADP_PROBE_PLUG,
951 .end = AB8500_INT_ADP_PROBE_PLUG,
952 .flags = IORESOURCE_IRQ,
953 },
954 {
955 .name = "USB_ADP_PROBE_UNPLUG",
956 .start = AB8500_INT_ADP_PROBE_UNPLUG,
957 .end = AB8500_INT_ADP_PROBE_UNPLUG,
958 .flags = IORESOURCE_IRQ,
959 },
Mattias Walline098aded72010-12-02 15:40:31 +0100960};
961
Bill Pembertona9e9ce42012-11-19 13:24:21 -0500962static struct resource ab8505_iddet_resources[] = {
Virupax Sadashivpetimath44f72e52012-04-17 09:30:14 +0200963 {
964 .name = "KeyDeglitch",
965 .start = AB8505_INT_KEYDEGLITCH,
966 .end = AB8505_INT_KEYDEGLITCH,
967 .flags = IORESOURCE_IRQ,
968 },
969 {
970 .name = "KP",
971 .start = AB8505_INT_KP,
972 .end = AB8505_INT_KP,
973 .flags = IORESOURCE_IRQ,
974 },
975 {
976 .name = "IKP",
977 .start = AB8505_INT_IKP,
978 .end = AB8505_INT_IKP,
979 .flags = IORESOURCE_IRQ,
980 },
981 {
982 .name = "IKR",
983 .start = AB8505_INT_IKR,
984 .end = AB8505_INT_IKR,
985 .flags = IORESOURCE_IRQ,
986 },
987 {
988 .name = "KeyStuck",
989 .start = AB8505_INT_KEYSTUCK,
990 .end = AB8505_INT_KEYSTUCK,
991 .flags = IORESOURCE_IRQ,
992 },
993};
994
Bill Pembertona9e9ce42012-11-19 13:24:21 -0500995static struct resource ab8500_temp_resources[] = {
Mattias Walline098aded72010-12-02 15:40:31 +0100996 {
Hongbo Zhang151621a2013-01-30 18:21:27 +0800997 .name = "ABX500_TEMP_WARM",
Mattias Walline098aded72010-12-02 15:40:31 +0100998 .start = AB8500_INT_TEMP_WARM,
999 .end = AB8500_INT_TEMP_WARM,
1000 .flags = IORESOURCE_IRQ,
1001 },
1002};
1003
Bill Pembertona9e9ce42012-11-19 13:24:21 -05001004static struct mfd_cell ab8500_bm_devs[] = {
Rickard Andersson6ef94182012-04-17 09:30:57 +02001005 {
1006 .name = "ab8500-charger",
Rajanikanth H.V4aef72d2012-11-18 19:17:47 -08001007 .of_compatible = "stericsson,ab8500-charger",
Rickard Andersson6ef94182012-04-17 09:30:57 +02001008 .num_resources = ARRAY_SIZE(ab8500_charger_resources),
1009 .resources = ab8500_charger_resources,
Rajanikanth H.V4aef72d2012-11-18 19:17:47 -08001010 .platform_data = &ab8500_bm_data,
1011 .pdata_size = sizeof(ab8500_bm_data),
Rickard Andersson6ef94182012-04-17 09:30:57 +02001012 },
1013 {
1014 .name = "ab8500-btemp",
Rajanikanth H.Vbd9e8ab2012-11-18 19:16:58 -08001015 .of_compatible = "stericsson,ab8500-btemp",
Rickard Andersson6ef94182012-04-17 09:30:57 +02001016 .num_resources = ARRAY_SIZE(ab8500_btemp_resources),
1017 .resources = ab8500_btemp_resources,
Rajanikanth H.Vbd9e8ab2012-11-18 19:16:58 -08001018 .platform_data = &ab8500_bm_data,
1019 .pdata_size = sizeof(ab8500_bm_data),
Rickard Andersson6ef94182012-04-17 09:30:57 +02001020 },
1021 {
1022 .name = "ab8500-fg",
Rajanikanth H.Ve0f1abe2012-11-18 18:45:41 -08001023 .of_compatible = "stericsson,ab8500-fg",
Rickard Andersson6ef94182012-04-17 09:30:57 +02001024 .num_resources = ARRAY_SIZE(ab8500_fg_resources),
1025 .resources = ab8500_fg_resources,
Rajanikanth H.Ve0f1abe2012-11-18 18:45:41 -08001026 .platform_data = &ab8500_bm_data,
1027 .pdata_size = sizeof(ab8500_bm_data),
Rickard Andersson6ef94182012-04-17 09:30:57 +02001028 },
1029 {
1030 .name = "ab8500-chargalg",
Rajanikanth H.Va12810a2012-10-31 15:40:33 +00001031 .of_compatible = "stericsson,ab8500-chargalg",
Rickard Andersson6ef94182012-04-17 09:30:57 +02001032 .num_resources = ARRAY_SIZE(ab8500_chargalg_resources),
1033 .resources = ab8500_chargalg_resources,
Rajanikanth H.Va12810a2012-10-31 15:40:33 +00001034 .platform_data = &ab8500_bm_data,
1035 .pdata_size = sizeof(ab8500_bm_data),
Rickard Andersson6ef94182012-04-17 09:30:57 +02001036 },
1037};
1038
Bill Pembertona9e9ce42012-11-19 13:24:21 -05001039static struct mfd_cell ab8500_devs[] = {
Lee Jones4b106fb2013-02-25 14:42:00 +00001040#ifdef CONFIG_DEBUG_FS
Linus Walleijd6255522012-02-20 21:42:24 +01001041 {
Lee Jones4b106fb2013-02-25 14:42:00 +00001042 .name = "ab8500-debug",
1043 .of_compatible = "stericsson,ab8500-debug",
1044 .num_resources = ARRAY_SIZE(ab8500_debug_resources),
1045 .resources = ab8500_debug_resources,
1046 },
1047#endif
1048 {
1049 .name = "ab8500-sysctrl",
1050 .of_compatible = "stericsson,ab8500-sysctrl",
1051 },
1052 {
1053 .name = "ab8500-regulator",
1054 .of_compatible = "stericsson,ab8500-regulator",
1055 },
1056 {
1057 .name = "abx500-clk",
1058 .of_compatible = "stericsson,abx500-clk",
1059 },
1060 {
1061 .name = "ab8500-gpadc",
1062 .num_resources = ARRAY_SIZE(ab8500_gpadc_resources),
1063 .resources = ab8500_gpadc_resources,
1064 },
1065 {
1066 .name = "ab8500-rtc",
1067 .of_compatible = "stericsson,ab8500-rtc",
1068 .num_resources = ARRAY_SIZE(ab8500_rtc_resources),
1069 .resources = ab8500_rtc_resources,
1070 },
1071 {
1072 .name = "ab8500-acc-det",
1073 .of_compatible = "stericsson,ab8500-acc-det",
1074 .num_resources = ARRAY_SIZE(ab8500_av_acc_detect_resources),
1075 .resources = ab8500_av_acc_detect_resources,
1076 },
1077 {
1078
1079 .name = "ab8500-poweron-key",
1080 .of_compatible = "stericsson,ab8500-poweron-key",
1081 .num_resources = ARRAY_SIZE(ab8500_poweronkey_db_resources),
1082 .resources = ab8500_poweronkey_db_resources,
1083 },
1084 {
1085 .name = "ab8500-pwm",
1086 .of_compatible = "stericsson,ab8500-pwm",
1087 .id = 1,
1088 },
1089 {
1090 .name = "ab8500-pwm",
1091 .of_compatible = "stericsson,ab8500-pwm",
1092 .id = 2,
1093 },
1094 {
1095 .name = "ab8500-pwm",
1096 .of_compatible = "stericsson,ab8500-pwm",
1097 .id = 3,
1098 },
1099 {
1100 .name = "ab8500-leds",
1101 .of_compatible = "stericsson,ab8500-leds",
1102 },
1103 {
1104 .name = "ab8500-denc",
1105 .of_compatible = "stericsson,ab8500-denc",
1106 },
1107 {
1108 .name = "ab8500-gpio",
Lee Jonesbad76992012-07-02 17:10:56 +02001109 .of_compatible = "stericsson,ab8500-gpio",
Linus Walleijd6255522012-02-20 21:42:24 +01001110 },
1111 {
Lee Jones4b106fb2013-02-25 14:42:00 +00001112 .name = "abx500-temp",
1113 .of_compatible = "stericsson,abx500-temp",
1114 .num_resources = ARRAY_SIZE(ab8500_temp_resources),
1115 .resources = ab8500_temp_resources,
1116 },
1117 {
Linus Walleijd6255522012-02-20 21:42:24 +01001118 .name = "ab8500-usb",
1119 .num_resources = ARRAY_SIZE(ab8500_usb_resources),
1120 .resources = ab8500_usb_resources,
1121 },
Virupax Sadashivpetimath44f72e52012-04-17 09:30:14 +02001122 {
1123 .name = "ab8500-codec",
Lee Jones4b106fb2013-02-25 14:42:00 +00001124 },
1125};
1126
1127static struct mfd_cell ab9540_devs[] = {
1128#ifdef CONFIG_DEBUG_FS
1129 {
1130 .name = "ab8500-debug",
1131 .num_resources = ARRAY_SIZE(ab8500_debug_resources),
1132 .resources = ab8500_debug_resources,
1133 },
1134#endif
1135 {
1136 .name = "ab8500-sysctrl",
1137 },
1138 {
1139 .name = "ab8500-regulator",
Virupax Sadashivpetimath44f72e52012-04-17 09:30:14 +02001140 },
Lee Jonesc0eda9a2013-02-12 15:04:09 +00001141 {
1142 .name = "ab8500-gpadc",
1143 .of_compatible = "stericsson,ab8500-gpadc",
1144 .num_resources = ARRAY_SIZE(ab8500_gpadc_resources),
1145 .resources = ab8500_gpadc_resources,
1146 },
Lee Jones4b106fb2013-02-25 14:42:00 +00001147 {
1148 .name = "ab8500-rtc",
1149 .num_resources = ARRAY_SIZE(ab8500_rtc_resources),
1150 .resources = ab8500_rtc_resources,
1151 },
1152 {
1153 .name = "ab8500-acc-det",
1154 .num_resources = ARRAY_SIZE(ab8500_av_acc_detect_resources),
1155 .resources = ab8500_av_acc_detect_resources,
1156 },
1157 {
1158 .name = "ab8500-poweron-key",
1159 .num_resources = ARRAY_SIZE(ab8500_poweronkey_db_resources),
1160 .resources = ab8500_poweronkey_db_resources,
1161 },
1162 {
1163 .name = "ab8500-pwm",
1164 .id = 1,
1165 },
1166 {
1167 .name = "ab8500-leds",
1168 },
1169 {
1170 .name = "abx500-temp",
1171 .num_resources = ARRAY_SIZE(ab8500_temp_resources),
1172 .resources = ab8500_temp_resources,
1173 },
Linus Walleijd6255522012-02-20 21:42:24 +01001174 {
Lee Jonese64d9052013-01-16 15:09:36 +00001175 .name = "pinctrl-ab9540",
1176 .of_compatible = "stericsson,ab9540-gpio",
Linus Walleijd6255522012-02-20 21:42:24 +01001177 },
1178 {
1179 .name = "ab9540-usb",
1180 .num_resources = ARRAY_SIZE(ab8500_usb_resources),
1181 .resources = ab8500_usb_resources,
1182 },
Virupax Sadashivpetimath44f72e52012-04-17 09:30:14 +02001183 {
1184 .name = "ab9540-codec",
1185 },
Lee Jonesc0eda9a2013-02-12 15:04:09 +00001186 {
Lee Jonesc0eda9a2013-02-12 15:04:09 +00001187 .name = "ab-iddet",
1188 .num_resources = ARRAY_SIZE(ab8505_iddet_resources),
1189 .resources = ab8505_iddet_resources,
1190 },
Virupax Sadashivpetimath44f72e52012-04-17 09:30:14 +02001191};
1192
Lee Jonesc0eda9a2013-02-12 15:04:09 +00001193/* Device list for ab8505 */
1194static struct mfd_cell ab8505_devs[] = {
Lee Jones4b106fb2013-02-25 14:42:00 +00001195#ifdef CONFIG_DEBUG_FS
1196 {
1197 .name = "ab8500-debug",
1198 .num_resources = ARRAY_SIZE(ab8500_debug_resources),
1199 .resources = ab8500_debug_resources,
1200 },
1201#endif
1202 {
1203 .name = "ab8500-sysctrl",
1204 },
1205 {
1206 .name = "ab8500-regulator",
1207 },
1208 {
1209 .name = "ab8500-gpadc",
1210 .num_resources = ARRAY_SIZE(ab8505_gpadc_resources),
1211 .resources = ab8505_gpadc_resources,
1212 },
1213 {
1214 .name = "ab8500-rtc",
1215 .num_resources = ARRAY_SIZE(ab8500_rtc_resources),
1216 .resources = ab8500_rtc_resources,
1217 },
1218 {
1219 .name = "ab8500-acc-det",
1220 .num_resources = ARRAY_SIZE(ab8500_av_acc_detect_resources),
1221 .resources = ab8500_av_acc_detect_resources,
1222 },
1223 {
1224 .name = "ab8500-poweron-key",
1225 .num_resources = ARRAY_SIZE(ab8500_poweronkey_db_resources),
1226 .resources = ab8500_poweronkey_db_resources,
1227 },
1228 {
1229 .name = "ab8500-pwm",
1230 .id = 1,
1231 },
1232 {
1233 .name = "ab8500-leds",
1234 },
1235 {
1236 .name = "ab8500-gpio",
1237 },
1238 {
1239 .name = "ab8500-usb",
1240 .num_resources = ARRAY_SIZE(ab8500_usb_resources),
1241 .resources = ab8500_usb_resources,
1242 },
1243 {
1244 .name = "ab8500-codec",
1245 },
Lee Jonesc0eda9a2013-02-12 15:04:09 +00001246 {
1247 .name = "ab-iddet",
1248 .num_resources = ARRAY_SIZE(ab8505_iddet_resources),
1249 .resources = ab8505_iddet_resources,
1250 },
1251};
1252
1253static struct mfd_cell ab8540_devs[] = {
Lee Jones4b106fb2013-02-25 14:42:00 +00001254#ifdef CONFIG_DEBUG_FS
1255 {
1256 .name = "ab8500-debug",
1257 .num_resources = ARRAY_SIZE(ab8500_debug_resources),
1258 .resources = ab8500_debug_resources,
1259 },
1260#endif
1261 {
1262 .name = "ab8500-sysctrl",
1263 },
1264 {
1265 .name = "ab8500-regulator",
1266 },
1267 {
1268 .name = "ab8500-gpadc",
1269 .num_resources = ARRAY_SIZE(ab8505_gpadc_resources),
1270 .resources = ab8505_gpadc_resources,
1271 },
1272 {
1273 .name = "ab8500-rtc",
1274 .num_resources = ARRAY_SIZE(ab8500_rtc_resources),
1275 .resources = ab8500_rtc_resources,
1276 },
1277 {
1278 .name = "ab8500-acc-det",
1279 .num_resources = ARRAY_SIZE(ab8500_av_acc_detect_resources),
1280 .resources = ab8500_av_acc_detect_resources,
1281 },
1282 {
1283 .name = "ab8500-poweron-key",
1284 .num_resources = ARRAY_SIZE(ab8500_poweronkey_db_resources),
1285 .resources = ab8500_poweronkey_db_resources,
1286 },
1287 {
1288 .name = "ab8500-pwm",
1289 .id = 1,
1290 },
1291 {
1292 .name = "ab8500-leds",
1293 },
1294 {
1295 .name = "abx500-temp",
1296 .num_resources = ARRAY_SIZE(ab8500_temp_resources),
1297 .resources = ab8500_temp_resources,
1298 },
Lee Jonesc0eda9a2013-02-12 15:04:09 +00001299 {
1300 .name = "ab8500-gpio",
1301 },
1302 {
1303 .name = "ab8540-usb",
1304 .num_resources = ARRAY_SIZE(ab8500_usb_resources),
1305 .resources = ab8500_usb_resources,
1306 },
1307 {
1308 .name = "ab8540-codec",
1309 },
1310 {
Virupax Sadashivpetimath44f72e52012-04-17 09:30:14 +02001311 .name = "ab-iddet",
1312 .num_resources = ARRAY_SIZE(ab8505_iddet_resources),
1313 .resources = ab8505_iddet_resources,
1314 },
Linus Walleijd6255522012-02-20 21:42:24 +01001315};
1316
Mattias Wallincca69b62010-12-02 15:09:36 +01001317static ssize_t show_chip_id(struct device *dev,
1318 struct device_attribute *attr, char *buf)
1319{
1320 struct ab8500 *ab8500;
1321
1322 ab8500 = dev_get_drvdata(dev);
1323 return sprintf(buf, "%#x\n", ab8500 ? ab8500->chip_id : -EINVAL);
1324}
1325
Mattias Walline5c238c2011-03-02 11:52:36 +01001326/*
1327 * ab8500 has switched off due to (SWITCH_OFF_STATUS):
1328 * 0x01 Swoff bit programming
1329 * 0x02 Thermal protection activation
1330 * 0x04 Vbat lower then BattOk falling threshold
1331 * 0x08 Watchdog expired
1332 * 0x10 Non presence of 32kHz clock
1333 * 0x20 Battery level lower than power on reset threshold
1334 * 0x40 Power on key 1 pressed longer than 10 seconds
1335 * 0x80 DB8500 thermal shutdown
1336 */
1337static ssize_t show_switch_off_status(struct device *dev,
1338 struct device_attribute *attr, char *buf)
1339{
1340 int ret;
1341 u8 value;
1342 struct ab8500 *ab8500;
1343
1344 ab8500 = dev_get_drvdata(dev);
1345 ret = get_register_interruptible(ab8500, AB8500_RTC,
1346 AB8500_SWITCH_OFF_STATUS, &value);
1347 if (ret < 0)
1348 return ret;
1349 return sprintf(buf, "%#x\n", value);
1350}
1351
Rajkumar Kasirajanf04a9d82012-05-30 16:32:37 +05301352/* use mask and set to override the register turn_on_stat value */
1353void ab8500_override_turn_on_stat(u8 mask, u8 set)
1354{
1355 spin_lock(&on_stat_lock);
1356 turn_on_stat_mask = mask;
1357 turn_on_stat_set = set;
1358 spin_unlock(&on_stat_lock);
1359}
1360
Andrew Lynnb4a31032011-10-11 10:49:47 +02001361/*
1362 * ab8500 has turned on due to (TURN_ON_STATUS):
1363 * 0x01 PORnVbat
1364 * 0x02 PonKey1dbF
1365 * 0x04 PonKey2dbF
1366 * 0x08 RTCAlarm
1367 * 0x10 MainChDet
1368 * 0x20 VbusDet
1369 * 0x40 UsbIDDetect
1370 * 0x80 Reserved
1371 */
1372static ssize_t show_turn_on_status(struct device *dev,
1373 struct device_attribute *attr, char *buf)
1374{
1375 int ret;
1376 u8 value;
1377 struct ab8500 *ab8500;
1378
1379 ab8500 = dev_get_drvdata(dev);
1380 ret = get_register_interruptible(ab8500, AB8500_SYS_CTRL1_BLOCK,
1381 AB8500_TURN_ON_STATUS, &value);
1382 if (ret < 0)
1383 return ret;
Rajkumar Kasirajanf04a9d82012-05-30 16:32:37 +05301384
1385 /*
1386 * In L9540, turn_on_status register is not updated correctly if
1387 * the device is rebooted with AC/USB charger connected. Due to
1388 * this, the device boots android instead of entering into charge
1389 * only mode. Read the AC/USB status register to detect the charger
1390 * presence and update the turn on status manually.
1391 */
1392 if (is_ab9540(ab8500)) {
1393 spin_lock(&on_stat_lock);
1394 value = (value & turn_on_stat_mask) | turn_on_stat_set;
1395 spin_unlock(&on_stat_lock);
1396 }
1397
Andrew Lynnb4a31032011-10-11 10:49:47 +02001398 return sprintf(buf, "%#x\n", value);
1399}
1400
Linus Walleijd6255522012-02-20 21:42:24 +01001401static ssize_t show_ab9540_dbbrstn(struct device *dev,
1402 struct device_attribute *attr, char *buf)
1403{
1404 struct ab8500 *ab8500;
1405 int ret;
1406 u8 value;
1407
1408 ab8500 = dev_get_drvdata(dev);
1409
1410 ret = get_register_interruptible(ab8500, AB8500_REGU_CTRL2,
1411 AB9540_MODEM_CTRL2_REG, &value);
1412 if (ret < 0)
1413 return ret;
1414
1415 return sprintf(buf, "%d\n",
1416 (value & AB9540_MODEM_CTRL2_SWDBBRSTN_BIT) ? 1 : 0);
1417}
1418
1419static ssize_t store_ab9540_dbbrstn(struct device *dev,
1420 struct device_attribute *attr, const char *buf, size_t count)
1421{
1422 struct ab8500 *ab8500;
1423 int ret = count;
1424 int err;
1425 u8 bitvalues;
1426
1427 ab8500 = dev_get_drvdata(dev);
1428
1429 if (count > 0) {
1430 switch (buf[0]) {
1431 case '0':
1432 bitvalues = 0;
1433 break;
1434 case '1':
1435 bitvalues = AB9540_MODEM_CTRL2_SWDBBRSTN_BIT;
1436 break;
1437 default:
1438 goto exit;
1439 }
1440
1441 err = mask_and_set_register_interruptible(ab8500,
1442 AB8500_REGU_CTRL2, AB9540_MODEM_CTRL2_REG,
1443 AB9540_MODEM_CTRL2_SWDBBRSTN_BIT, bitvalues);
1444 if (err)
1445 dev_info(ab8500->dev,
1446 "Failed to set DBBRSTN %c, err %#x\n",
1447 buf[0], err);
1448 }
1449
1450exit:
1451 return ret;
1452}
1453
Mattias Wallincca69b62010-12-02 15:09:36 +01001454static DEVICE_ATTR(chip_id, S_IRUGO, show_chip_id, NULL);
Mattias Walline5c238c2011-03-02 11:52:36 +01001455static DEVICE_ATTR(switch_off_status, S_IRUGO, show_switch_off_status, NULL);
Andrew Lynnb4a31032011-10-11 10:49:47 +02001456static DEVICE_ATTR(turn_on_status, S_IRUGO, show_turn_on_status, NULL);
Linus Walleijd6255522012-02-20 21:42:24 +01001457static DEVICE_ATTR(dbbrstn, S_IRUGO | S_IWUSR,
1458 show_ab9540_dbbrstn, store_ab9540_dbbrstn);
Mattias Wallincca69b62010-12-02 15:09:36 +01001459
1460static struct attribute *ab8500_sysfs_entries[] = {
1461 &dev_attr_chip_id.attr,
Mattias Walline5c238c2011-03-02 11:52:36 +01001462 &dev_attr_switch_off_status.attr,
Andrew Lynnb4a31032011-10-11 10:49:47 +02001463 &dev_attr_turn_on_status.attr,
Mattias Wallincca69b62010-12-02 15:09:36 +01001464 NULL,
1465};
1466
Linus Walleijd6255522012-02-20 21:42:24 +01001467static struct attribute *ab9540_sysfs_entries[] = {
1468 &dev_attr_chip_id.attr,
1469 &dev_attr_switch_off_status.attr,
1470 &dev_attr_turn_on_status.attr,
1471 &dev_attr_dbbrstn.attr,
1472 NULL,
1473};
1474
Mattias Wallincca69b62010-12-02 15:09:36 +01001475static struct attribute_group ab8500_attr_group = {
1476 .attrs = ab8500_sysfs_entries,
1477};
1478
Linus Walleijd6255522012-02-20 21:42:24 +01001479static struct attribute_group ab9540_attr_group = {
1480 .attrs = ab9540_sysfs_entries,
1481};
1482
Bill Pembertonf791be42012-11-19 13:23:04 -05001483static int ab8500_probe(struct platform_device *pdev)
Rabin Vincent62579262010-05-19 11:39:02 +02001484{
Jonas Aabergb04c530c2012-06-29 17:46:12 +02001485 static char *switch_off_status[] = {
1486 "Swoff bit programming",
1487 "Thermal protection activation",
1488 "Vbat lower then BattOk falling threshold",
1489 "Watchdog expired",
1490 "Non presence of 32kHz clock",
1491 "Battery level lower than power on reset threshold",
1492 "Power on key 1 pressed longer than 10 seconds",
1493 "DB8500 thermal shutdown"};
Lee Jonesd28f1db2012-05-19 17:21:37 +02001494 struct ab8500_platform_data *plat = dev_get_platdata(&pdev->dev);
1495 const struct platform_device_id *platid = platform_get_device_id(pdev);
Lee Jones6bc4a562012-05-17 14:45:13 +01001496 enum ab8500_version version = AB8500_VERSION_UNDEFINED;
1497 struct device_node *np = pdev->dev.of_node;
Lee Jonesd28f1db2012-05-19 17:21:37 +02001498 struct ab8500 *ab8500;
1499 struct resource *resource;
Rabin Vincent62579262010-05-19 11:39:02 +02001500 int ret;
1501 int i;
Mattias Wallin47c16972010-09-10 17:47:56 +02001502 u8 value;
Rabin Vincent62579262010-05-19 11:39:02 +02001503
Lee Jones8c4203c2012-11-05 16:10:35 +01001504 ab8500 = devm_kzalloc(&pdev->dev, sizeof *ab8500, GFP_KERNEL);
Lee Jonesd28f1db2012-05-19 17:21:37 +02001505 if (!ab8500)
1506 return -ENOMEM;
1507
Rabin Vincent62579262010-05-19 11:39:02 +02001508 if (plat)
1509 ab8500->irq_base = plat->irq_base;
1510
Lee Jonesd28f1db2012-05-19 17:21:37 +02001511 ab8500->dev = &pdev->dev;
1512
1513 resource = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
Lee Jones8c4203c2012-11-05 16:10:35 +01001514 if (!resource)
1515 return -ENODEV;
Lee Jonesd28f1db2012-05-19 17:21:37 +02001516
1517 ab8500->irq = resource->start;
1518
Lee Jones822672a2012-06-20 13:56:38 +01001519 ab8500->read = ab8500_prcmu_read;
1520 ab8500->write = ab8500_prcmu_write;
1521 ab8500->write_masked = ab8500_prcmu_write_masked;
Lee Jonesd28f1db2012-05-19 17:21:37 +02001522
Rabin Vincent62579262010-05-19 11:39:02 +02001523 mutex_init(&ab8500->lock);
1524 mutex_init(&ab8500->irq_lock);
Jonas Aaberg112a80d2012-04-17 09:30:33 +02001525 atomic_set(&ab8500->transfer_ongoing, 0);
Rabin Vincent62579262010-05-19 11:39:02 +02001526
Lee Jonesd28f1db2012-05-19 17:21:37 +02001527 platform_set_drvdata(pdev, ab8500);
1528
Lee Jones6bc4a562012-05-17 14:45:13 +01001529 if (platid)
1530 version = platid->driver_data;
Lee Jones6bc4a562012-05-17 14:45:13 +01001531
Linus Walleij0f6208372012-02-20 21:42:10 +01001532 if (version != AB8500_VERSION_UNDEFINED)
1533 ab8500->version = version;
1534 else {
1535 ret = get_register_interruptible(ab8500, AB8500_MISC,
1536 AB8500_IC_NAME_REG, &value);
1537 if (ret < 0)
Lee Jones8c4203c2012-11-05 16:10:35 +01001538 return ret;
Linus Walleij0f6208372012-02-20 21:42:10 +01001539
1540 ab8500->version = value;
1541 }
1542
Mattias Wallin47c16972010-09-10 17:47:56 +02001543 ret = get_register_interruptible(ab8500, AB8500_MISC,
1544 AB8500_REV_REG, &value);
Rabin Vincent62579262010-05-19 11:39:02 +02001545 if (ret < 0)
Lee Jones8c4203c2012-11-05 16:10:35 +01001546 return ret;
Rabin Vincent62579262010-05-19 11:39:02 +02001547
Mattias Wallin47c16972010-09-10 17:47:56 +02001548 ab8500->chip_id = value;
Rabin Vincent62579262010-05-19 11:39:02 +02001549
Linus Walleij0f6208372012-02-20 21:42:10 +01001550 dev_info(ab8500->dev, "detected chip, %s rev. %1x.%1x\n",
1551 ab8500_version_str[ab8500->version],
1552 ab8500->chip_id >> 4,
1553 ab8500->chip_id & 0x0F);
1554
Linus Walleijd6255522012-02-20 21:42:24 +01001555 /* Configure AB8500 or AB9540 IRQ */
Bengt Jonssona9823622012-03-08 14:01:57 +01001556 if (is_ab9540(ab8500) || is_ab8505(ab8500)) {
Linus Walleijd6255522012-02-20 21:42:24 +01001557 ab8500->mask_size = AB9540_NUM_IRQ_REGS;
1558 ab8500->irq_reg_offset = ab9540_irq_regoffset;
1559 } else {
1560 ab8500->mask_size = AB8500_NUM_IRQ_REGS;
1561 ab8500->irq_reg_offset = ab8500_irq_regoffset;
1562 }
Lee Jones8c4203c2012-11-05 16:10:35 +01001563 ab8500->mask = devm_kzalloc(&pdev->dev, ab8500->mask_size, GFP_KERNEL);
Linus Walleij2ced4452012-02-20 21:42:17 +01001564 if (!ab8500->mask)
1565 return -ENOMEM;
Lee Jones8c4203c2012-11-05 16:10:35 +01001566 ab8500->oldmask = devm_kzalloc(&pdev->dev, ab8500->mask_size, GFP_KERNEL);
1567 if (!ab8500->oldmask)
1568 return -ENOMEM;
1569
Mattias Walline5c238c2011-03-02 11:52:36 +01001570 /*
1571 * ab8500 has switched off due to (SWITCH_OFF_STATUS):
1572 * 0x01 Swoff bit programming
1573 * 0x02 Thermal protection activation
1574 * 0x04 Vbat lower then BattOk falling threshold
1575 * 0x08 Watchdog expired
1576 * 0x10 Non presence of 32kHz clock
1577 * 0x20 Battery level lower than power on reset threshold
1578 * 0x40 Power on key 1 pressed longer than 10 seconds
1579 * 0x80 DB8500 thermal shutdown
1580 */
1581
1582 ret = get_register_interruptible(ab8500, AB8500_RTC,
1583 AB8500_SWITCH_OFF_STATUS, &value);
1584 if (ret < 0)
1585 return ret;
Jonas Aabergb04c530c2012-06-29 17:46:12 +02001586 dev_info(ab8500->dev, "switch off cause(s) (%#x): ", value);
1587
1588 if (value) {
1589 for (i = 0; i < ARRAY_SIZE(switch_off_status); i++) {
1590 if (value & 1)
1591 printk(KERN_CONT " \"%s\"",
1592 switch_off_status[i]);
1593 value = value >> 1;
1594
1595 }
1596 printk(KERN_CONT "\n");
1597 } else {
1598 printk(KERN_CONT " None\n");
1599 }
Mattias Walline5c238c2011-03-02 11:52:36 +01001600
Rabin Vincent62579262010-05-19 11:39:02 +02001601 if (plat && plat->init)
1602 plat->init(ab8500);
Rajkumar Kasirajanf04a9d82012-05-30 16:32:37 +05301603 if (is_ab9540(ab8500)) {
1604 ret = get_register_interruptible(ab8500, AB8500_CHARGER,
1605 AB8500_CH_USBCH_STAT1_REG, &value);
1606 if (ret < 0)
1607 return ret;
1608 if ((value & VBUS_DET_DBNC1) && (value & VBUS_DET_DBNC100))
1609 ab8500_override_turn_on_stat(~AB8500_POW_KEY_1_ON,
1610 AB8500_VBUS_DET);
1611 }
Rabin Vincent62579262010-05-19 11:39:02 +02001612
1613 /* Clear and mask all interrupts */
Linus Walleij2ced4452012-02-20 21:42:17 +01001614 for (i = 0; i < ab8500->mask_size; i++) {
Linus Walleij0f6208372012-02-20 21:42:10 +01001615 /*
1616 * Interrupt register 12 doesn't exist prior to AB8500 version
1617 * 2.0
1618 */
1619 if (ab8500->irq_reg_offset[i] == 11 &&
1620 is_ab8500_1p1_or_earlier(ab8500))
Mattias Wallin92d50a42010-12-07 11:20:47 +01001621 continue;
Rabin Vincent62579262010-05-19 11:39:02 +02001622
Mattias Wallin47c16972010-09-10 17:47:56 +02001623 get_register_interruptible(ab8500, AB8500_INTERRUPT,
Linus Walleij2ced4452012-02-20 21:42:17 +01001624 AB8500_IT_LATCH1_REG + ab8500->irq_reg_offset[i],
Mattias Wallin92d50a42010-12-07 11:20:47 +01001625 &value);
Mattias Wallin47c16972010-09-10 17:47:56 +02001626 set_register_interruptible(ab8500, AB8500_INTERRUPT,
Linus Walleij2ced4452012-02-20 21:42:17 +01001627 AB8500_IT_MASK1_REG + ab8500->irq_reg_offset[i], 0xff);
Rabin Vincent62579262010-05-19 11:39:02 +02001628 }
1629
Mattias Wallin47c16972010-09-10 17:47:56 +02001630 ret = abx500_register_ops(ab8500->dev, &ab8500_ops);
1631 if (ret)
Lee Jones8c4203c2012-11-05 16:10:35 +01001632 return ret;
Mattias Wallin47c16972010-09-10 17:47:56 +02001633
Linus Walleij2ced4452012-02-20 21:42:17 +01001634 for (i = 0; i < ab8500->mask_size; i++)
Rabin Vincent62579262010-05-19 11:39:02 +02001635 ab8500->mask[i] = ab8500->oldmask[i] = 0xff;
1636
Lee Jones06e589e2012-06-20 13:56:37 +01001637 ret = ab8500_irq_init(ab8500, np);
1638 if (ret)
Lee Jones8c4203c2012-11-05 16:10:35 +01001639 return ret;
Rabin Vincent62579262010-05-19 11:39:02 +02001640
Lee Jones06e589e2012-06-20 13:56:37 +01001641 /* Activate this feature only in ab9540 */
1642 /* till tests are done on ab8500 1p2 or later*/
1643 if (is_ab9540(ab8500)) {
Lee Jones8c4203c2012-11-05 16:10:35 +01001644 ret = devm_request_threaded_irq(&pdev->dev, ab8500->irq, NULL,
1645 ab8500_hierarchical_irq,
1646 IRQF_ONESHOT | IRQF_NO_SUSPEND,
1647 "ab8500", ab8500);
Lee Jones06e589e2012-06-20 13:56:37 +01001648 }
1649 else {
Lee Jones8c4203c2012-11-05 16:10:35 +01001650 ret = devm_request_threaded_irq(&pdev->dev, ab8500->irq, NULL,
1651 ab8500_irq,
1652 IRQF_ONESHOT | IRQF_NO_SUSPEND,
1653 "ab8500", ab8500);
Rabin Vincent62579262010-05-19 11:39:02 +02001654 if (ret)
Lee Jones8c4203c2012-11-05 16:10:35 +01001655 return ret;
Rabin Vincent62579262010-05-19 11:39:02 +02001656 }
1657
Lee Jonesbad76992012-07-02 17:10:56 +02001658 if (is_ab9540(ab8500))
1659 ret = mfd_add_devices(ab8500->dev, 0, ab9540_devs,
1660 ARRAY_SIZE(ab9540_devs), NULL,
Mark Brown55692af2012-09-11 15:16:36 +08001661 ab8500->irq_base, ab8500->domain);
Lee Jonesc0eda9a2013-02-12 15:04:09 +00001662 else if (is_ab8540(ab8500))
1663 ret = mfd_add_devices(ab8500->dev, 0, ab8540_devs,
1664 ARRAY_SIZE(ab8540_devs), NULL,
1665 ab8500->irq_base, ab8500->domain);
1666 else if (is_ab8505(ab8500))
1667 ret = mfd_add_devices(ab8500->dev, 0, ab8505_devs,
1668 ARRAY_SIZE(ab8505_devs), NULL,
1669 ab8500->irq_base, ab8500->domain);
Lee Jonesbad76992012-07-02 17:10:56 +02001670 else
1671 ret = mfd_add_devices(ab8500->dev, 0, ab8500_devs,
1672 ARRAY_SIZE(ab8500_devs), NULL,
Mark Brown55692af2012-09-11 15:16:36 +08001673 ab8500->irq_base, ab8500->domain);
Lee Jonesbad76992012-07-02 17:10:56 +02001674 if (ret)
Lee Jones8c4203c2012-11-05 16:10:35 +01001675 return ret;
Linus Walleijd6255522012-02-20 21:42:24 +01001676
Rickard Andersson6ef94182012-04-17 09:30:57 +02001677 if (!no_bm) {
1678 /* Add battery management devices */
1679 ret = mfd_add_devices(ab8500->dev, 0, ab8500_bm_devs,
1680 ARRAY_SIZE(ab8500_bm_devs), NULL,
Mark Brown55692af2012-09-11 15:16:36 +08001681 ab8500->irq_base, ab8500->domain);
Rickard Andersson6ef94182012-04-17 09:30:57 +02001682 if (ret)
1683 dev_err(ab8500->dev, "error adding bm devices\n");
1684 }
1685
Linus Walleijd6255522012-02-20 21:42:24 +01001686 if (is_ab9540(ab8500))
1687 ret = sysfs_create_group(&ab8500->dev->kobj,
1688 &ab9540_attr_group);
1689 else
1690 ret = sysfs_create_group(&ab8500->dev->kobj,
1691 &ab8500_attr_group);
Mattias Wallincca69b62010-12-02 15:09:36 +01001692 if (ret)
1693 dev_err(ab8500->dev, "error creating sysfs entries\n");
Lee Jones06e589e2012-06-20 13:56:37 +01001694
1695 return ret;
Rabin Vincent62579262010-05-19 11:39:02 +02001696}
1697
Bill Pemberton4740f732012-11-19 13:26:01 -05001698static int ab8500_remove(struct platform_device *pdev)
Rabin Vincent62579262010-05-19 11:39:02 +02001699{
Lee Jonesd28f1db2012-05-19 17:21:37 +02001700 struct ab8500 *ab8500 = platform_get_drvdata(pdev);
1701
Linus Walleijd6255522012-02-20 21:42:24 +01001702 if (is_ab9540(ab8500))
1703 sysfs_remove_group(&ab8500->dev->kobj, &ab9540_attr_group);
1704 else
1705 sysfs_remove_group(&ab8500->dev->kobj, &ab8500_attr_group);
Lee Jones06e589e2012-06-20 13:56:37 +01001706
Rabin Vincent62579262010-05-19 11:39:02 +02001707 mfd_remove_devices(ab8500->dev);
Rabin Vincent62579262010-05-19 11:39:02 +02001708
1709 return 0;
1710}
1711
Lee Jonesd28f1db2012-05-19 17:21:37 +02001712static const struct platform_device_id ab8500_id[] = {
1713 { "ab8500-core", AB8500_VERSION_AB8500 },
1714 { "ab8505-i2c", AB8500_VERSION_AB8505 },
1715 { "ab9540-i2c", AB8500_VERSION_AB9540 },
1716 { "ab8540-i2c", AB8500_VERSION_AB8540 },
1717 { }
1718};
1719
1720static struct platform_driver ab8500_core_driver = {
1721 .driver = {
1722 .name = "ab8500-core",
1723 .owner = THIS_MODULE,
1724 },
1725 .probe = ab8500_probe,
Bill Pemberton84449212012-11-19 13:20:24 -05001726 .remove = ab8500_remove,
Lee Jonesd28f1db2012-05-19 17:21:37 +02001727 .id_table = ab8500_id,
1728};
1729
1730static int __init ab8500_core_init(void)
1731{
1732 return platform_driver_register(&ab8500_core_driver);
1733}
1734
1735static void __exit ab8500_core_exit(void)
1736{
1737 platform_driver_unregister(&ab8500_core_driver);
1738}
Lee Jonesba7cbc32012-06-11 16:25:00 +01001739core_initcall(ab8500_core_init);
Lee Jonesd28f1db2012-05-19 17:21:37 +02001740module_exit(ab8500_core_exit);
1741
Mattias Wallinadceed62011-03-02 11:51:11 +01001742MODULE_AUTHOR("Mattias Wallin, Srinidhi Kasagar, Rabin Vincent");
Rabin Vincent62579262010-05-19 11:39:02 +02001743MODULE_DESCRIPTION("AB8500 MFD core");
1744MODULE_LICENSE("GPL v2");