blob: cdf6c1e59bc370b22eb383a6d20f7cb38da796c3 [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 Jonesc0eda9a2013-02-12 15:04:09 +0000661static struct resource ab8540_gpadc_resources[] = {
662 {
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 abx500_common_devs[] = {
Mattias Wallin5814fc32010-09-13 16:05:04 +02001005#ifdef CONFIG_DEBUG_FS
1006 {
1007 .name = "ab8500-debug",
Lee Jonesbad76992012-07-02 17:10:56 +02001008 .of_compatible = "stericsson,ab8500-debug",
Mattias Walline098aded72010-12-02 15:40:31 +01001009 .num_resources = ARRAY_SIZE(ab8500_debug_resources),
1010 .resources = ab8500_debug_resources,
Mattias Wallin5814fc32010-09-13 16:05:04 +02001011 },
1012#endif
Rabin Vincent62579262010-05-19 11:39:02 +02001013 {
Mattias Walline098aded72010-12-02 15:40:31 +01001014 .name = "ab8500-sysctrl",
Lee Jonesbad76992012-07-02 17:10:56 +02001015 .of_compatible = "stericsson,ab8500-sysctrl",
Mattias Walline098aded72010-12-02 15:40:31 +01001016 },
1017 {
1018 .name = "ab8500-regulator",
Lee Jonesbad76992012-07-02 17:10:56 +02001019 .of_compatible = "stericsson,ab8500-regulator",
Mattias Walline098aded72010-12-02 15:40:31 +01001020 },
1021 {
Ulf Hansson916a8712012-11-22 11:35:40 +01001022 .name = "abx500-clk",
1023 .of_compatible = "stericsson,abx500-clk",
1024 },
1025 {
Rabin Vincent62579262010-05-19 11:39:02 +02001026 .name = "ab8500-rtc",
Lee Jonesbad76992012-07-02 17:10:56 +02001027 .of_compatible = "stericsson,ab8500-rtc",
Rabin Vincent62579262010-05-19 11:39:02 +02001028 .num_resources = ARRAY_SIZE(ab8500_rtc_resources),
1029 .resources = ab8500_rtc_resources,
1030 },
Arun Murthyf0f05b12010-09-06 12:24:52 +05301031 {
Linus Walleij6af75ec2011-06-09 23:57:45 +02001032 .name = "ab8500-acc-det",
Lee Jonesbad76992012-07-02 17:10:56 +02001033 .of_compatible = "stericsson,ab8500-acc-det",
Linus Walleij6af75ec2011-06-09 23:57:45 +02001034 .num_resources = ARRAY_SIZE(ab8500_av_acc_detect_resources),
1035 .resources = ab8500_av_acc_detect_resources,
1036 },
1037 {
Mattias Walline098aded72010-12-02 15:40:31 +01001038 .name = "ab8500-poweron-key",
Lee Jonesbad76992012-07-02 17:10:56 +02001039 .of_compatible = "stericsson,ab8500-poweron-key",
Mattias Walline098aded72010-12-02 15:40:31 +01001040 .num_resources = ARRAY_SIZE(ab8500_poweronkey_db_resources),
1041 .resources = ab8500_poweronkey_db_resources,
1042 },
1043 {
Arun Murthyf0f05b12010-09-06 12:24:52 +05301044 .name = "ab8500-pwm",
Lee Jonesbad76992012-07-02 17:10:56 +02001045 .of_compatible = "stericsson,ab8500-pwm",
Arun Murthyf0f05b12010-09-06 12:24:52 +05301046 .id = 1,
1047 },
1048 {
1049 .name = "ab8500-pwm",
Lee Jonesbad76992012-07-02 17:10:56 +02001050 .of_compatible = "stericsson,ab8500-pwm",
Arun Murthyf0f05b12010-09-06 12:24:52 +05301051 .id = 2,
1052 },
1053 {
1054 .name = "ab8500-pwm",
Lee Jonesbad76992012-07-02 17:10:56 +02001055 .of_compatible = "stericsson,ab8500-pwm",
Arun Murthyf0f05b12010-09-06 12:24:52 +05301056 .id = 3,
1057 },
Lee Jonesbad76992012-07-02 17:10:56 +02001058 {
1059 .name = "ab8500-leds",
1060 .of_compatible = "stericsson,ab8500-leds",
1061 },
Sundar R Iyer77686512010-09-05 12:18:47 -07001062 {
Mattias Walline098aded72010-12-02 15:40:31 +01001063 .name = "ab8500-denc",
Lee Jonesbad76992012-07-02 17:10:56 +02001064 .of_compatible = "stericsson,ab8500-denc",
Mattias Walline098aded72010-12-02 15:40:31 +01001065 },
1066 {
Hongbo Zhang151621a2013-01-30 18:21:27 +08001067 .name = "abx500-temp",
1068 .of_compatible = "stericsson,abx500-temp",
Mattias Walline098aded72010-12-02 15:40:31 +01001069 .num_resources = ARRAY_SIZE(ab8500_temp_resources),
1070 .resources = ab8500_temp_resources,
Sundar R Iyer77686512010-09-05 12:18:47 -07001071 },
Rabin Vincent62579262010-05-19 11:39:02 +02001072};
1073
Bill Pembertona9e9ce42012-11-19 13:24:21 -05001074static struct mfd_cell ab8500_bm_devs[] = {
Rickard Andersson6ef94182012-04-17 09:30:57 +02001075 {
1076 .name = "ab8500-charger",
Rajanikanth H.V4aef72d2012-11-18 19:17:47 -08001077 .of_compatible = "stericsson,ab8500-charger",
Rickard Andersson6ef94182012-04-17 09:30:57 +02001078 .num_resources = ARRAY_SIZE(ab8500_charger_resources),
1079 .resources = ab8500_charger_resources,
Rajanikanth H.V4aef72d2012-11-18 19:17:47 -08001080 .platform_data = &ab8500_bm_data,
1081 .pdata_size = sizeof(ab8500_bm_data),
Rickard Andersson6ef94182012-04-17 09:30:57 +02001082 },
1083 {
1084 .name = "ab8500-btemp",
Rajanikanth H.Vbd9e8ab2012-11-18 19:16:58 -08001085 .of_compatible = "stericsson,ab8500-btemp",
Rickard Andersson6ef94182012-04-17 09:30:57 +02001086 .num_resources = ARRAY_SIZE(ab8500_btemp_resources),
1087 .resources = ab8500_btemp_resources,
Rajanikanth H.Vbd9e8ab2012-11-18 19:16:58 -08001088 .platform_data = &ab8500_bm_data,
1089 .pdata_size = sizeof(ab8500_bm_data),
Rickard Andersson6ef94182012-04-17 09:30:57 +02001090 },
1091 {
1092 .name = "ab8500-fg",
Rajanikanth H.Ve0f1abe2012-11-18 18:45:41 -08001093 .of_compatible = "stericsson,ab8500-fg",
Rickard Andersson6ef94182012-04-17 09:30:57 +02001094 .num_resources = ARRAY_SIZE(ab8500_fg_resources),
1095 .resources = ab8500_fg_resources,
Rajanikanth H.Ve0f1abe2012-11-18 18:45:41 -08001096 .platform_data = &ab8500_bm_data,
1097 .pdata_size = sizeof(ab8500_bm_data),
Rickard Andersson6ef94182012-04-17 09:30:57 +02001098 },
1099 {
1100 .name = "ab8500-chargalg",
Rajanikanth H.Va12810a2012-10-31 15:40:33 +00001101 .of_compatible = "stericsson,ab8500-chargalg",
Rickard Andersson6ef94182012-04-17 09:30:57 +02001102 .num_resources = ARRAY_SIZE(ab8500_chargalg_resources),
1103 .resources = ab8500_chargalg_resources,
Rajanikanth H.Va12810a2012-10-31 15:40:33 +00001104 .platform_data = &ab8500_bm_data,
1105 .pdata_size = sizeof(ab8500_bm_data),
Rickard Andersson6ef94182012-04-17 09:30:57 +02001106 },
1107};
1108
Bill Pembertona9e9ce42012-11-19 13:24:21 -05001109static struct mfd_cell ab8500_devs[] = {
Linus Walleijd6255522012-02-20 21:42:24 +01001110 {
Lee Jones7d56a462013-01-16 14:49:45 +00001111 .name = "pinctrl-ab8500",
Lee Jonesbad76992012-07-02 17:10:56 +02001112 .of_compatible = "stericsson,ab8500-gpio",
Linus Walleijd6255522012-02-20 21:42:24 +01001113 },
1114 {
1115 .name = "ab8500-usb",
Lee Jonesbad76992012-07-02 17:10:56 +02001116 .of_compatible = "stericsson,ab8500-usb",
Linus Walleijd6255522012-02-20 21:42:24 +01001117 .num_resources = ARRAY_SIZE(ab8500_usb_resources),
1118 .resources = ab8500_usb_resources,
1119 },
Virupax Sadashivpetimath44f72e52012-04-17 09:30:14 +02001120 {
1121 .name = "ab8500-codec",
Lee Jones81a21cd2012-07-27 13:38:51 +01001122 .of_compatible = "stericsson,ab8500-codec",
Virupax Sadashivpetimath44f72e52012-04-17 09:30:14 +02001123 },
Lee Jonesc0eda9a2013-02-12 15:04:09 +00001124 {
1125 .name = "ab8500-gpadc",
1126 .of_compatible = "stericsson,ab8500-gpadc",
1127 .num_resources = ARRAY_SIZE(ab8500_gpadc_resources),
1128 .resources = ab8500_gpadc_resources,
1129 },
Linus Walleijd6255522012-02-20 21:42:24 +01001130};
1131
Bill Pembertona9e9ce42012-11-19 13:24:21 -05001132static struct mfd_cell ab9540_devs[] = {
Linus Walleijd6255522012-02-20 21:42:24 +01001133 {
Lee Jonese64d9052013-01-16 15:09:36 +00001134 .name = "pinctrl-ab9540",
1135 .of_compatible = "stericsson,ab9540-gpio",
Linus Walleijd6255522012-02-20 21:42:24 +01001136 },
1137 {
1138 .name = "ab9540-usb",
1139 .num_resources = ARRAY_SIZE(ab8500_usb_resources),
1140 .resources = ab8500_usb_resources,
1141 },
Virupax Sadashivpetimath44f72e52012-04-17 09:30:14 +02001142 {
1143 .name = "ab9540-codec",
1144 },
Lee Jonesc0eda9a2013-02-12 15:04:09 +00001145 {
1146 .name = "ab8500-gpadc",
1147 .num_resources = ARRAY_SIZE(ab8500_gpadc_resources),
1148 .resources = ab8500_gpadc_resources,
1149 },
1150 {
1151 .name = "ab-iddet",
1152 .num_resources = ARRAY_SIZE(ab8505_iddet_resources),
1153 .resources = ab8505_iddet_resources,
1154 },
Virupax Sadashivpetimath44f72e52012-04-17 09:30:14 +02001155};
1156
Lee Jonesc0eda9a2013-02-12 15:04:09 +00001157/* Device list for ab8505 */
1158static struct mfd_cell ab8505_devs[] = {
1159 {
1160 .name = "ab-iddet",
1161 .num_resources = ARRAY_SIZE(ab8505_iddet_resources),
1162 .resources = ab8505_iddet_resources,
1163 },
1164};
1165
1166static struct mfd_cell ab8540_devs[] = {
1167 {
1168 .name = "ab8500-gpio",
1169 },
1170 {
1171 .name = "ab8540-usb",
1172 .num_resources = ARRAY_SIZE(ab8500_usb_resources),
1173 .resources = ab8500_usb_resources,
1174 },
1175 {
1176 .name = "ab8540-codec",
1177 },
1178 {
1179 .name = "ab8500-gpadc",
1180 .num_resources = ARRAY_SIZE(ab8540_gpadc_resources),
1181 .resources = ab8540_gpadc_resources,
1182 },
Virupax Sadashivpetimath44f72e52012-04-17 09:30:14 +02001183 {
1184 .name = "ab-iddet",
1185 .num_resources = ARRAY_SIZE(ab8505_iddet_resources),
1186 .resources = ab8505_iddet_resources,
1187 },
Linus Walleijd6255522012-02-20 21:42:24 +01001188};
1189
Mattias Wallincca69b62010-12-02 15:09:36 +01001190static ssize_t show_chip_id(struct device *dev,
1191 struct device_attribute *attr, char *buf)
1192{
1193 struct ab8500 *ab8500;
1194
1195 ab8500 = dev_get_drvdata(dev);
1196 return sprintf(buf, "%#x\n", ab8500 ? ab8500->chip_id : -EINVAL);
1197}
1198
Mattias Walline5c238c2011-03-02 11:52:36 +01001199/*
1200 * ab8500 has switched off due to (SWITCH_OFF_STATUS):
1201 * 0x01 Swoff bit programming
1202 * 0x02 Thermal protection activation
1203 * 0x04 Vbat lower then BattOk falling threshold
1204 * 0x08 Watchdog expired
1205 * 0x10 Non presence of 32kHz clock
1206 * 0x20 Battery level lower than power on reset threshold
1207 * 0x40 Power on key 1 pressed longer than 10 seconds
1208 * 0x80 DB8500 thermal shutdown
1209 */
1210static ssize_t show_switch_off_status(struct device *dev,
1211 struct device_attribute *attr, char *buf)
1212{
1213 int ret;
1214 u8 value;
1215 struct ab8500 *ab8500;
1216
1217 ab8500 = dev_get_drvdata(dev);
1218 ret = get_register_interruptible(ab8500, AB8500_RTC,
1219 AB8500_SWITCH_OFF_STATUS, &value);
1220 if (ret < 0)
1221 return ret;
1222 return sprintf(buf, "%#x\n", value);
1223}
1224
Rajkumar Kasirajanf04a9d82012-05-30 16:32:37 +05301225/* use mask and set to override the register turn_on_stat value */
1226void ab8500_override_turn_on_stat(u8 mask, u8 set)
1227{
1228 spin_lock(&on_stat_lock);
1229 turn_on_stat_mask = mask;
1230 turn_on_stat_set = set;
1231 spin_unlock(&on_stat_lock);
1232}
1233
Andrew Lynnb4a31032011-10-11 10:49:47 +02001234/*
1235 * ab8500 has turned on due to (TURN_ON_STATUS):
1236 * 0x01 PORnVbat
1237 * 0x02 PonKey1dbF
1238 * 0x04 PonKey2dbF
1239 * 0x08 RTCAlarm
1240 * 0x10 MainChDet
1241 * 0x20 VbusDet
1242 * 0x40 UsbIDDetect
1243 * 0x80 Reserved
1244 */
1245static ssize_t show_turn_on_status(struct device *dev,
1246 struct device_attribute *attr, char *buf)
1247{
1248 int ret;
1249 u8 value;
1250 struct ab8500 *ab8500;
1251
1252 ab8500 = dev_get_drvdata(dev);
1253 ret = get_register_interruptible(ab8500, AB8500_SYS_CTRL1_BLOCK,
1254 AB8500_TURN_ON_STATUS, &value);
1255 if (ret < 0)
1256 return ret;
Rajkumar Kasirajanf04a9d82012-05-30 16:32:37 +05301257
1258 /*
1259 * In L9540, turn_on_status register is not updated correctly if
1260 * the device is rebooted with AC/USB charger connected. Due to
1261 * this, the device boots android instead of entering into charge
1262 * only mode. Read the AC/USB status register to detect the charger
1263 * presence and update the turn on status manually.
1264 */
1265 if (is_ab9540(ab8500)) {
1266 spin_lock(&on_stat_lock);
1267 value = (value & turn_on_stat_mask) | turn_on_stat_set;
1268 spin_unlock(&on_stat_lock);
1269 }
1270
Andrew Lynnb4a31032011-10-11 10:49:47 +02001271 return sprintf(buf, "%#x\n", value);
1272}
1273
Linus Walleijd6255522012-02-20 21:42:24 +01001274static ssize_t show_ab9540_dbbrstn(struct device *dev,
1275 struct device_attribute *attr, char *buf)
1276{
1277 struct ab8500 *ab8500;
1278 int ret;
1279 u8 value;
1280
1281 ab8500 = dev_get_drvdata(dev);
1282
1283 ret = get_register_interruptible(ab8500, AB8500_REGU_CTRL2,
1284 AB9540_MODEM_CTRL2_REG, &value);
1285 if (ret < 0)
1286 return ret;
1287
1288 return sprintf(buf, "%d\n",
1289 (value & AB9540_MODEM_CTRL2_SWDBBRSTN_BIT) ? 1 : 0);
1290}
1291
1292static ssize_t store_ab9540_dbbrstn(struct device *dev,
1293 struct device_attribute *attr, const char *buf, size_t count)
1294{
1295 struct ab8500 *ab8500;
1296 int ret = count;
1297 int err;
1298 u8 bitvalues;
1299
1300 ab8500 = dev_get_drvdata(dev);
1301
1302 if (count > 0) {
1303 switch (buf[0]) {
1304 case '0':
1305 bitvalues = 0;
1306 break;
1307 case '1':
1308 bitvalues = AB9540_MODEM_CTRL2_SWDBBRSTN_BIT;
1309 break;
1310 default:
1311 goto exit;
1312 }
1313
1314 err = mask_and_set_register_interruptible(ab8500,
1315 AB8500_REGU_CTRL2, AB9540_MODEM_CTRL2_REG,
1316 AB9540_MODEM_CTRL2_SWDBBRSTN_BIT, bitvalues);
1317 if (err)
1318 dev_info(ab8500->dev,
1319 "Failed to set DBBRSTN %c, err %#x\n",
1320 buf[0], err);
1321 }
1322
1323exit:
1324 return ret;
1325}
1326
Mattias Wallincca69b62010-12-02 15:09:36 +01001327static DEVICE_ATTR(chip_id, S_IRUGO, show_chip_id, NULL);
Mattias Walline5c238c2011-03-02 11:52:36 +01001328static DEVICE_ATTR(switch_off_status, S_IRUGO, show_switch_off_status, NULL);
Andrew Lynnb4a31032011-10-11 10:49:47 +02001329static DEVICE_ATTR(turn_on_status, S_IRUGO, show_turn_on_status, NULL);
Linus Walleijd6255522012-02-20 21:42:24 +01001330static DEVICE_ATTR(dbbrstn, S_IRUGO | S_IWUSR,
1331 show_ab9540_dbbrstn, store_ab9540_dbbrstn);
Mattias Wallincca69b62010-12-02 15:09:36 +01001332
1333static struct attribute *ab8500_sysfs_entries[] = {
1334 &dev_attr_chip_id.attr,
Mattias Walline5c238c2011-03-02 11:52:36 +01001335 &dev_attr_switch_off_status.attr,
Andrew Lynnb4a31032011-10-11 10:49:47 +02001336 &dev_attr_turn_on_status.attr,
Mattias Wallincca69b62010-12-02 15:09:36 +01001337 NULL,
1338};
1339
Linus Walleijd6255522012-02-20 21:42:24 +01001340static struct attribute *ab9540_sysfs_entries[] = {
1341 &dev_attr_chip_id.attr,
1342 &dev_attr_switch_off_status.attr,
1343 &dev_attr_turn_on_status.attr,
1344 &dev_attr_dbbrstn.attr,
1345 NULL,
1346};
1347
Mattias Wallincca69b62010-12-02 15:09:36 +01001348static struct attribute_group ab8500_attr_group = {
1349 .attrs = ab8500_sysfs_entries,
1350};
1351
Linus Walleijd6255522012-02-20 21:42:24 +01001352static struct attribute_group ab9540_attr_group = {
1353 .attrs = ab9540_sysfs_entries,
1354};
1355
Bill Pembertonf791be42012-11-19 13:23:04 -05001356static int ab8500_probe(struct platform_device *pdev)
Rabin Vincent62579262010-05-19 11:39:02 +02001357{
Jonas Aabergb04c530c2012-06-29 17:46:12 +02001358 static char *switch_off_status[] = {
1359 "Swoff bit programming",
1360 "Thermal protection activation",
1361 "Vbat lower then BattOk falling threshold",
1362 "Watchdog expired",
1363 "Non presence of 32kHz clock",
1364 "Battery level lower than power on reset threshold",
1365 "Power on key 1 pressed longer than 10 seconds",
1366 "DB8500 thermal shutdown"};
Lee Jonesd28f1db2012-05-19 17:21:37 +02001367 struct ab8500_platform_data *plat = dev_get_platdata(&pdev->dev);
1368 const struct platform_device_id *platid = platform_get_device_id(pdev);
Lee Jones6bc4a562012-05-17 14:45:13 +01001369 enum ab8500_version version = AB8500_VERSION_UNDEFINED;
1370 struct device_node *np = pdev->dev.of_node;
Lee Jonesd28f1db2012-05-19 17:21:37 +02001371 struct ab8500 *ab8500;
1372 struct resource *resource;
Rabin Vincent62579262010-05-19 11:39:02 +02001373 int ret;
1374 int i;
Mattias Wallin47c16972010-09-10 17:47:56 +02001375 u8 value;
Rabin Vincent62579262010-05-19 11:39:02 +02001376
Lee Jones8c4203c2012-11-05 16:10:35 +01001377 ab8500 = devm_kzalloc(&pdev->dev, sizeof *ab8500, GFP_KERNEL);
Lee Jonesd28f1db2012-05-19 17:21:37 +02001378 if (!ab8500)
1379 return -ENOMEM;
1380
Rabin Vincent62579262010-05-19 11:39:02 +02001381 if (plat)
1382 ab8500->irq_base = plat->irq_base;
1383
Lee Jonesd28f1db2012-05-19 17:21:37 +02001384 ab8500->dev = &pdev->dev;
1385
1386 resource = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
Lee Jones8c4203c2012-11-05 16:10:35 +01001387 if (!resource)
1388 return -ENODEV;
Lee Jonesd28f1db2012-05-19 17:21:37 +02001389
1390 ab8500->irq = resource->start;
1391
Lee Jones822672a2012-06-20 13:56:38 +01001392 ab8500->read = ab8500_prcmu_read;
1393 ab8500->write = ab8500_prcmu_write;
1394 ab8500->write_masked = ab8500_prcmu_write_masked;
Lee Jonesd28f1db2012-05-19 17:21:37 +02001395
Rabin Vincent62579262010-05-19 11:39:02 +02001396 mutex_init(&ab8500->lock);
1397 mutex_init(&ab8500->irq_lock);
Jonas Aaberg112a80d2012-04-17 09:30:33 +02001398 atomic_set(&ab8500->transfer_ongoing, 0);
Rabin Vincent62579262010-05-19 11:39:02 +02001399
Lee Jonesd28f1db2012-05-19 17:21:37 +02001400 platform_set_drvdata(pdev, ab8500);
1401
Lee Jones6bc4a562012-05-17 14:45:13 +01001402 if (platid)
1403 version = platid->driver_data;
Lee Jones6bc4a562012-05-17 14:45:13 +01001404
Linus Walleij0f6208372012-02-20 21:42:10 +01001405 if (version != AB8500_VERSION_UNDEFINED)
1406 ab8500->version = version;
1407 else {
1408 ret = get_register_interruptible(ab8500, AB8500_MISC,
1409 AB8500_IC_NAME_REG, &value);
1410 if (ret < 0)
Lee Jones8c4203c2012-11-05 16:10:35 +01001411 return ret;
Linus Walleij0f6208372012-02-20 21:42:10 +01001412
1413 ab8500->version = value;
1414 }
1415
Mattias Wallin47c16972010-09-10 17:47:56 +02001416 ret = get_register_interruptible(ab8500, AB8500_MISC,
1417 AB8500_REV_REG, &value);
Rabin Vincent62579262010-05-19 11:39:02 +02001418 if (ret < 0)
Lee Jones8c4203c2012-11-05 16:10:35 +01001419 return ret;
Rabin Vincent62579262010-05-19 11:39:02 +02001420
Mattias Wallin47c16972010-09-10 17:47:56 +02001421 ab8500->chip_id = value;
Rabin Vincent62579262010-05-19 11:39:02 +02001422
Linus Walleij0f6208372012-02-20 21:42:10 +01001423 dev_info(ab8500->dev, "detected chip, %s rev. %1x.%1x\n",
1424 ab8500_version_str[ab8500->version],
1425 ab8500->chip_id >> 4,
1426 ab8500->chip_id & 0x0F);
1427
Linus Walleijd6255522012-02-20 21:42:24 +01001428 /* Configure AB8500 or AB9540 IRQ */
Bengt Jonssona9823622012-03-08 14:01:57 +01001429 if (is_ab9540(ab8500) || is_ab8505(ab8500)) {
Linus Walleijd6255522012-02-20 21:42:24 +01001430 ab8500->mask_size = AB9540_NUM_IRQ_REGS;
1431 ab8500->irq_reg_offset = ab9540_irq_regoffset;
1432 } else {
1433 ab8500->mask_size = AB8500_NUM_IRQ_REGS;
1434 ab8500->irq_reg_offset = ab8500_irq_regoffset;
1435 }
Lee Jones8c4203c2012-11-05 16:10:35 +01001436 ab8500->mask = devm_kzalloc(&pdev->dev, ab8500->mask_size, GFP_KERNEL);
Linus Walleij2ced4452012-02-20 21:42:17 +01001437 if (!ab8500->mask)
1438 return -ENOMEM;
Lee Jones8c4203c2012-11-05 16:10:35 +01001439 ab8500->oldmask = devm_kzalloc(&pdev->dev, ab8500->mask_size, GFP_KERNEL);
1440 if (!ab8500->oldmask)
1441 return -ENOMEM;
1442
Mattias Walline5c238c2011-03-02 11:52:36 +01001443 /*
1444 * ab8500 has switched off due to (SWITCH_OFF_STATUS):
1445 * 0x01 Swoff bit programming
1446 * 0x02 Thermal protection activation
1447 * 0x04 Vbat lower then BattOk falling threshold
1448 * 0x08 Watchdog expired
1449 * 0x10 Non presence of 32kHz clock
1450 * 0x20 Battery level lower than power on reset threshold
1451 * 0x40 Power on key 1 pressed longer than 10 seconds
1452 * 0x80 DB8500 thermal shutdown
1453 */
1454
1455 ret = get_register_interruptible(ab8500, AB8500_RTC,
1456 AB8500_SWITCH_OFF_STATUS, &value);
1457 if (ret < 0)
1458 return ret;
Jonas Aabergb04c530c2012-06-29 17:46:12 +02001459 dev_info(ab8500->dev, "switch off cause(s) (%#x): ", value);
1460
1461 if (value) {
1462 for (i = 0; i < ARRAY_SIZE(switch_off_status); i++) {
1463 if (value & 1)
1464 printk(KERN_CONT " \"%s\"",
1465 switch_off_status[i]);
1466 value = value >> 1;
1467
1468 }
1469 printk(KERN_CONT "\n");
1470 } else {
1471 printk(KERN_CONT " None\n");
1472 }
Mattias Walline5c238c2011-03-02 11:52:36 +01001473
Rabin Vincent62579262010-05-19 11:39:02 +02001474 if (plat && plat->init)
1475 plat->init(ab8500);
Rajkumar Kasirajanf04a9d82012-05-30 16:32:37 +05301476 if (is_ab9540(ab8500)) {
1477 ret = get_register_interruptible(ab8500, AB8500_CHARGER,
1478 AB8500_CH_USBCH_STAT1_REG, &value);
1479 if (ret < 0)
1480 return ret;
1481 if ((value & VBUS_DET_DBNC1) && (value & VBUS_DET_DBNC100))
1482 ab8500_override_turn_on_stat(~AB8500_POW_KEY_1_ON,
1483 AB8500_VBUS_DET);
1484 }
Rabin Vincent62579262010-05-19 11:39:02 +02001485
1486 /* Clear and mask all interrupts */
Linus Walleij2ced4452012-02-20 21:42:17 +01001487 for (i = 0; i < ab8500->mask_size; i++) {
Linus Walleij0f6208372012-02-20 21:42:10 +01001488 /*
1489 * Interrupt register 12 doesn't exist prior to AB8500 version
1490 * 2.0
1491 */
1492 if (ab8500->irq_reg_offset[i] == 11 &&
1493 is_ab8500_1p1_or_earlier(ab8500))
Mattias Wallin92d50a42010-12-07 11:20:47 +01001494 continue;
Rabin Vincent62579262010-05-19 11:39:02 +02001495
Mattias Wallin47c16972010-09-10 17:47:56 +02001496 get_register_interruptible(ab8500, AB8500_INTERRUPT,
Linus Walleij2ced4452012-02-20 21:42:17 +01001497 AB8500_IT_LATCH1_REG + ab8500->irq_reg_offset[i],
Mattias Wallin92d50a42010-12-07 11:20:47 +01001498 &value);
Mattias Wallin47c16972010-09-10 17:47:56 +02001499 set_register_interruptible(ab8500, AB8500_INTERRUPT,
Linus Walleij2ced4452012-02-20 21:42:17 +01001500 AB8500_IT_MASK1_REG + ab8500->irq_reg_offset[i], 0xff);
Rabin Vincent62579262010-05-19 11:39:02 +02001501 }
1502
Mattias Wallin47c16972010-09-10 17:47:56 +02001503 ret = abx500_register_ops(ab8500->dev, &ab8500_ops);
1504 if (ret)
Lee Jones8c4203c2012-11-05 16:10:35 +01001505 return ret;
Mattias Wallin47c16972010-09-10 17:47:56 +02001506
Linus Walleij2ced4452012-02-20 21:42:17 +01001507 for (i = 0; i < ab8500->mask_size; i++)
Rabin Vincent62579262010-05-19 11:39:02 +02001508 ab8500->mask[i] = ab8500->oldmask[i] = 0xff;
1509
Lee Jones06e589e2012-06-20 13:56:37 +01001510 ret = ab8500_irq_init(ab8500, np);
1511 if (ret)
Lee Jones8c4203c2012-11-05 16:10:35 +01001512 return ret;
Rabin Vincent62579262010-05-19 11:39:02 +02001513
Lee Jones06e589e2012-06-20 13:56:37 +01001514 /* Activate this feature only in ab9540 */
1515 /* till tests are done on ab8500 1p2 or later*/
1516 if (is_ab9540(ab8500)) {
Lee Jones8c4203c2012-11-05 16:10:35 +01001517 ret = devm_request_threaded_irq(&pdev->dev, ab8500->irq, NULL,
1518 ab8500_hierarchical_irq,
1519 IRQF_ONESHOT | IRQF_NO_SUSPEND,
1520 "ab8500", ab8500);
Lee Jones06e589e2012-06-20 13:56:37 +01001521 }
1522 else {
Lee Jones8c4203c2012-11-05 16:10:35 +01001523 ret = devm_request_threaded_irq(&pdev->dev, ab8500->irq, NULL,
1524 ab8500_irq,
1525 IRQF_ONESHOT | IRQF_NO_SUSPEND,
1526 "ab8500", ab8500);
Rabin Vincent62579262010-05-19 11:39:02 +02001527 if (ret)
Lee Jones8c4203c2012-11-05 16:10:35 +01001528 return ret;
Rabin Vincent62579262010-05-19 11:39:02 +02001529 }
1530
Lee Jonesbad76992012-07-02 17:10:56 +02001531 ret = mfd_add_devices(ab8500->dev, 0, abx500_common_devs,
1532 ARRAY_SIZE(abx500_common_devs), NULL,
Mark Brown55692af2012-09-11 15:16:36 +08001533 ab8500->irq_base, ab8500->domain);
Lee Jonesbad76992012-07-02 17:10:56 +02001534 if (ret)
Lee Jones8c4203c2012-11-05 16:10:35 +01001535 return ret;
Lee Jonesbad76992012-07-02 17:10:56 +02001536
1537 if (is_ab9540(ab8500))
1538 ret = mfd_add_devices(ab8500->dev, 0, ab9540_devs,
1539 ARRAY_SIZE(ab9540_devs), NULL,
Mark Brown55692af2012-09-11 15:16:36 +08001540 ab8500->irq_base, ab8500->domain);
Lee Jonesc0eda9a2013-02-12 15:04:09 +00001541 else if (is_ab8540(ab8500))
1542 ret = mfd_add_devices(ab8500->dev, 0, ab8540_devs,
1543 ARRAY_SIZE(ab8540_devs), NULL,
1544 ab8500->irq_base, ab8500->domain);
1545 else if (is_ab8505(ab8500))
1546 ret = mfd_add_devices(ab8500->dev, 0, ab8505_devs,
1547 ARRAY_SIZE(ab8505_devs), NULL,
1548 ab8500->irq_base, ab8500->domain);
Lee Jonesbad76992012-07-02 17:10:56 +02001549 else
1550 ret = mfd_add_devices(ab8500->dev, 0, ab8500_devs,
1551 ARRAY_SIZE(ab8500_devs), NULL,
Mark Brown55692af2012-09-11 15:16:36 +08001552 ab8500->irq_base, ab8500->domain);
Lee Jonesbad76992012-07-02 17:10:56 +02001553 if (ret)
Lee Jones8c4203c2012-11-05 16:10:35 +01001554 return ret;
Linus Walleijd6255522012-02-20 21:42:24 +01001555
Rickard Andersson6ef94182012-04-17 09:30:57 +02001556 if (!no_bm) {
1557 /* Add battery management devices */
1558 ret = mfd_add_devices(ab8500->dev, 0, ab8500_bm_devs,
1559 ARRAY_SIZE(ab8500_bm_devs), NULL,
Mark Brown55692af2012-09-11 15:16:36 +08001560 ab8500->irq_base, ab8500->domain);
Rickard Andersson6ef94182012-04-17 09:30:57 +02001561 if (ret)
1562 dev_err(ab8500->dev, "error adding bm devices\n");
1563 }
1564
Linus Walleijd6255522012-02-20 21:42:24 +01001565 if (is_ab9540(ab8500))
1566 ret = sysfs_create_group(&ab8500->dev->kobj,
1567 &ab9540_attr_group);
1568 else
1569 ret = sysfs_create_group(&ab8500->dev->kobj,
1570 &ab8500_attr_group);
Mattias Wallincca69b62010-12-02 15:09:36 +01001571 if (ret)
1572 dev_err(ab8500->dev, "error creating sysfs entries\n");
Lee Jones06e589e2012-06-20 13:56:37 +01001573
1574 return ret;
Rabin Vincent62579262010-05-19 11:39:02 +02001575}
1576
Bill Pemberton4740f732012-11-19 13:26:01 -05001577static int ab8500_remove(struct platform_device *pdev)
Rabin Vincent62579262010-05-19 11:39:02 +02001578{
Lee Jonesd28f1db2012-05-19 17:21:37 +02001579 struct ab8500 *ab8500 = platform_get_drvdata(pdev);
1580
Linus Walleijd6255522012-02-20 21:42:24 +01001581 if (is_ab9540(ab8500))
1582 sysfs_remove_group(&ab8500->dev->kobj, &ab9540_attr_group);
1583 else
1584 sysfs_remove_group(&ab8500->dev->kobj, &ab8500_attr_group);
Lee Jones06e589e2012-06-20 13:56:37 +01001585
Rabin Vincent62579262010-05-19 11:39:02 +02001586 mfd_remove_devices(ab8500->dev);
Rabin Vincent62579262010-05-19 11:39:02 +02001587
1588 return 0;
1589}
1590
Lee Jonesd28f1db2012-05-19 17:21:37 +02001591static const struct platform_device_id ab8500_id[] = {
1592 { "ab8500-core", AB8500_VERSION_AB8500 },
1593 { "ab8505-i2c", AB8500_VERSION_AB8505 },
1594 { "ab9540-i2c", AB8500_VERSION_AB9540 },
1595 { "ab8540-i2c", AB8500_VERSION_AB8540 },
1596 { }
1597};
1598
1599static struct platform_driver ab8500_core_driver = {
1600 .driver = {
1601 .name = "ab8500-core",
1602 .owner = THIS_MODULE,
1603 },
1604 .probe = ab8500_probe,
Bill Pemberton84449212012-11-19 13:20:24 -05001605 .remove = ab8500_remove,
Lee Jonesd28f1db2012-05-19 17:21:37 +02001606 .id_table = ab8500_id,
1607};
1608
1609static int __init ab8500_core_init(void)
1610{
1611 return platform_driver_register(&ab8500_core_driver);
1612}
1613
1614static void __exit ab8500_core_exit(void)
1615{
1616 platform_driver_unregister(&ab8500_core_driver);
1617}
Lee Jonesba7cbc32012-06-11 16:25:00 +01001618core_initcall(ab8500_core_init);
Lee Jonesd28f1db2012-05-19 17:21:37 +02001619module_exit(ab8500_core_exit);
1620
Mattias Wallinadceed62011-03-02 11:51:11 +01001621MODULE_AUTHOR("Mattias Wallin, Srinidhi Kasagar, Rabin Vincent");
Rabin Vincent62579262010-05-19 11:39:02 +02001622MODULE_DESCRIPTION("AB8500 MFD core");
1623MODULE_LICENSE("GPL v2");