blob: 3d5da51b6a94f71f642988d5ea99ea37d6d3a407 [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
Rabin Vincent62579262010-05-19 11:39:02 +020098
Michel JAOUEN7ccfe9b2012-05-07 15:02:03 +020099/*
100 * latch hierarchy registers
101 */
102#define AB8500_IT_LATCHHIER1_REG 0x60
103#define AB8500_IT_LATCHHIER2_REG 0x61
104#define AB8500_IT_LATCHHIER3_REG 0x62
105
106#define AB8500_IT_LATCHHIER_NUM 3
107
Mattias Wallin47c16972010-09-10 17:47:56 +0200108#define AB8500_REV_REG 0x80
Linus Walleij0f6208372012-02-20 21:42:10 +0100109#define AB8500_IC_NAME_REG 0x82
Mattias Walline5c238c2011-03-02 11:52:36 +0100110#define AB8500_SWITCH_OFF_STATUS 0x00
Rabin Vincent62579262010-05-19 11:39:02 +0200111
Andrew Lynnb4a31032011-10-11 10:49:47 +0200112#define AB8500_TURN_ON_STATUS 0x00
113
Rickard Andersson6ef94182012-04-17 09:30:57 +0200114static bool no_bm; /* No battery management */
115module_param(no_bm, bool, S_IRUGO);
116
Linus Walleijd6255522012-02-20 21:42:24 +0100117#define AB9540_MODEM_CTRL2_REG 0x23
118#define AB9540_MODEM_CTRL2_SWDBBRSTN_BIT BIT(2)
119
Rabin Vincent62579262010-05-19 11:39:02 +0200120/*
121 * Map interrupt numbers to the LATCH and MASK register offsets, Interrupt
Linus Walleij2ced4452012-02-20 21:42:17 +0100122 * numbers are indexed into this array with (num / 8). The interupts are
123 * defined in linux/mfd/ab8500.h
Rabin Vincent62579262010-05-19 11:39:02 +0200124 *
125 * This is one off from the register names, i.e. AB8500_IT_MASK1_REG is at
126 * offset 0.
127 */
Linus Walleij2ced4452012-02-20 21:42:17 +0100128/* AB8500 support */
Rabin Vincent62579262010-05-19 11:39:02 +0200129static const int ab8500_irq_regoffset[AB8500_NUM_IRQ_REGS] = {
Mattias Wallin92d50a42010-12-07 11:20:47 +0100130 0, 1, 2, 3, 4, 6, 7, 8, 9, 11, 18, 19, 20, 21,
Rabin Vincent62579262010-05-19 11:39:02 +0200131};
132
Linus Walleijd6255522012-02-20 21:42:24 +0100133/* AB9540 support */
134static const int ab9540_irq_regoffset[AB9540_NUM_IRQ_REGS] = {
135 0, 1, 2, 3, 4, 6, 7, 8, 9, 11, 18, 19, 20, 21, 12, 13, 24,
136};
137
Linus Walleij0f6208372012-02-20 21:42:10 +0100138static const char ab8500_version_str[][7] = {
139 [AB8500_VERSION_AB8500] = "AB8500",
140 [AB8500_VERSION_AB8505] = "AB8505",
141 [AB8500_VERSION_AB9540] = "AB9540",
142 [AB8500_VERSION_AB8540] = "AB8540",
143};
144
Lee Jones822672a2012-06-20 13:56:38 +0100145static int ab8500_prcmu_write(struct ab8500 *ab8500, u16 addr, u8 data)
Lee Jonesd28f1db2012-05-19 17:21:37 +0200146{
147 int ret;
148
149 ret = prcmu_abb_write((u8)(addr >> 8), (u8)(addr & 0xFF), &data, 1);
150 if (ret < 0)
151 dev_err(ab8500->dev, "prcmu i2c error %d\n", ret);
152 return ret;
153}
154
Lee Jones822672a2012-06-20 13:56:38 +0100155static int ab8500_prcmu_write_masked(struct ab8500 *ab8500, u16 addr, u8 mask,
Lee Jonesd28f1db2012-05-19 17:21:37 +0200156 u8 data)
157{
158 int ret;
159
160 ret = prcmu_abb_write_masked((u8)(addr >> 8), (u8)(addr & 0xFF), &data,
161 &mask, 1);
162 if (ret < 0)
163 dev_err(ab8500->dev, "prcmu i2c error %d\n", ret);
164 return ret;
165}
166
Lee Jones822672a2012-06-20 13:56:38 +0100167static int ab8500_prcmu_read(struct ab8500 *ab8500, u16 addr)
Lee Jonesd28f1db2012-05-19 17:21:37 +0200168{
169 int ret;
170 u8 data;
171
172 ret = prcmu_abb_read((u8)(addr >> 8), (u8)(addr & 0xFF), &data, 1);
173 if (ret < 0) {
174 dev_err(ab8500->dev, "prcmu i2c error %d\n", ret);
175 return ret;
176 }
177 return (int)data;
178}
179
Mattias Wallin47c16972010-09-10 17:47:56 +0200180static int ab8500_get_chip_id(struct device *dev)
181{
Mattias Wallin6bce7bf2010-12-02 15:08:32 +0100182 struct ab8500 *ab8500;
183
184 if (!dev)
185 return -EINVAL;
186 ab8500 = dev_get_drvdata(dev->parent);
187 return ab8500 ? (int)ab8500->chip_id : -EINVAL;
Mattias Wallin47c16972010-09-10 17:47:56 +0200188}
189
190static int set_register_interruptible(struct ab8500 *ab8500, u8 bank,
191 u8 reg, u8 data)
Rabin Vincent62579262010-05-19 11:39:02 +0200192{
193 int ret;
Mattias Wallin47c16972010-09-10 17:47:56 +0200194 /*
195 * Put the u8 bank and u8 register together into a an u16.
196 * The bank on higher 8 bits and register in lower 8 bits.
197 * */
198 u16 addr = ((u16)bank) << 8 | reg;
Rabin Vincent62579262010-05-19 11:39:02 +0200199
200 dev_vdbg(ab8500->dev, "wr: addr %#x <= %#x\n", addr, data);
201
Rabin Vincent392cbd12012-03-08 14:01:46 +0100202 mutex_lock(&ab8500->lock);
Mattias Wallin47c16972010-09-10 17:47:56 +0200203
204 ret = ab8500->write(ab8500, addr, data);
205 if (ret < 0)
206 dev_err(ab8500->dev, "failed to write reg %#x: %d\n",
207 addr, ret);
208 mutex_unlock(&ab8500->lock);
209
210 return ret;
211}
212
213static int ab8500_set_register(struct device *dev, u8 bank,
214 u8 reg, u8 value)
215{
Jonas Aaberg112a80d2012-04-17 09:30:33 +0200216 int ret;
Mattias Wallin47c16972010-09-10 17:47:56 +0200217 struct ab8500 *ab8500 = dev_get_drvdata(dev->parent);
218
Jonas Aaberg112a80d2012-04-17 09:30:33 +0200219 atomic_inc(&ab8500->transfer_ongoing);
220 ret = set_register_interruptible(ab8500, bank, reg, value);
221 atomic_dec(&ab8500->transfer_ongoing);
222 return ret;
Mattias Wallin47c16972010-09-10 17:47:56 +0200223}
224
225static int get_register_interruptible(struct ab8500 *ab8500, u8 bank,
226 u8 reg, u8 *value)
227{
228 int ret;
229 /* put the u8 bank and u8 reg together into a an u16.
230 * bank on higher 8 bits and reg in lower */
231 u16 addr = ((u16)bank) << 8 | reg;
232
Rabin Vincent392cbd12012-03-08 14:01:46 +0100233 mutex_lock(&ab8500->lock);
Mattias Wallin47c16972010-09-10 17:47:56 +0200234
235 ret = ab8500->read(ab8500, addr);
236 if (ret < 0)
237 dev_err(ab8500->dev, "failed to read reg %#x: %d\n",
238 addr, ret);
239 else
240 *value = ret;
241
242 mutex_unlock(&ab8500->lock);
243 dev_vdbg(ab8500->dev, "rd: addr %#x => data %#x\n", addr, ret);
244
245 return ret;
246}
247
248static int ab8500_get_register(struct device *dev, u8 bank,
249 u8 reg, u8 *value)
250{
Jonas Aaberg112a80d2012-04-17 09:30:33 +0200251 int ret;
Mattias Wallin47c16972010-09-10 17:47:56 +0200252 struct ab8500 *ab8500 = dev_get_drvdata(dev->parent);
253
Jonas Aaberg112a80d2012-04-17 09:30:33 +0200254 atomic_inc(&ab8500->transfer_ongoing);
255 ret = get_register_interruptible(ab8500, bank, reg, value);
256 atomic_dec(&ab8500->transfer_ongoing);
257 return ret;
Mattias Wallin47c16972010-09-10 17:47:56 +0200258}
259
260static int mask_and_set_register_interruptible(struct ab8500 *ab8500, u8 bank,
261 u8 reg, u8 bitmask, u8 bitvalues)
262{
263 int ret;
Mattias Wallin47c16972010-09-10 17:47:56 +0200264 /* put the u8 bank and u8 reg together into a an u16.
265 * bank on higher 8 bits and reg in lower */
266 u16 addr = ((u16)bank) << 8 | reg;
267
Rabin Vincent392cbd12012-03-08 14:01:46 +0100268 mutex_lock(&ab8500->lock);
Mattias Wallin47c16972010-09-10 17:47:56 +0200269
Mattias Nilssonbc628fd2012-03-08 14:02:20 +0100270 if (ab8500->write_masked == NULL) {
271 u8 data;
272
273 ret = ab8500->read(ab8500, addr);
274 if (ret < 0) {
275 dev_err(ab8500->dev, "failed to read reg %#x: %d\n",
276 addr, ret);
277 goto out;
278 }
279
280 data = (u8)ret;
281 data = (~bitmask & data) | (bitmask & bitvalues);
282
283 ret = ab8500->write(ab8500, addr, data);
284 if (ret < 0)
285 dev_err(ab8500->dev, "failed to write reg %#x: %d\n",
286 addr, ret);
287
288 dev_vdbg(ab8500->dev, "mask: addr %#x => data %#x\n", addr,
289 data);
Mattias Wallin47c16972010-09-10 17:47:56 +0200290 goto out;
291 }
Mattias Nilssonbc628fd2012-03-08 14:02:20 +0100292 ret = ab8500->write_masked(ab8500, addr, bitmask, bitvalues);
Rabin Vincent62579262010-05-19 11:39:02 +0200293 if (ret < 0)
Mattias Nilssonbc628fd2012-03-08 14:02:20 +0100294 dev_err(ab8500->dev, "failed to modify reg %#x: %d\n", addr,
295 ret);
Rabin Vincent62579262010-05-19 11:39:02 +0200296out:
297 mutex_unlock(&ab8500->lock);
298 return ret;
299}
Mattias Wallin47c16972010-09-10 17:47:56 +0200300
301static int ab8500_mask_and_set_register(struct device *dev,
302 u8 bank, u8 reg, u8 bitmask, u8 bitvalues)
303{
Jonas Aaberg112a80d2012-04-17 09:30:33 +0200304 int ret;
Mattias Wallin47c16972010-09-10 17:47:56 +0200305 struct ab8500 *ab8500 = dev_get_drvdata(dev->parent);
306
Jonas Aaberg112a80d2012-04-17 09:30:33 +0200307 atomic_inc(&ab8500->transfer_ongoing);
308 ret= mask_and_set_register_interruptible(ab8500, bank, reg,
309 bitmask, bitvalues);
310 atomic_dec(&ab8500->transfer_ongoing);
311 return ret;
Mattias Wallin47c16972010-09-10 17:47:56 +0200312}
313
314static struct abx500_ops ab8500_ops = {
315 .get_chip_id = ab8500_get_chip_id,
316 .get_register = ab8500_get_register,
317 .set_register = ab8500_set_register,
318 .get_register_page = NULL,
319 .set_register_page = NULL,
320 .mask_and_set_register = ab8500_mask_and_set_register,
321 .event_registers_startup_state_get = NULL,
322 .startup_irq_enabled = NULL,
323};
Rabin Vincent62579262010-05-19 11:39:02 +0200324
Mark Brown9505a0a2010-12-11 13:16:08 +0000325static void ab8500_irq_lock(struct irq_data *data)
Rabin Vincent62579262010-05-19 11:39:02 +0200326{
Mark Brown9505a0a2010-12-11 13:16:08 +0000327 struct ab8500 *ab8500 = irq_data_get_irq_chip_data(data);
Rabin Vincent62579262010-05-19 11:39:02 +0200328
329 mutex_lock(&ab8500->irq_lock);
Jonas Aaberg112a80d2012-04-17 09:30:33 +0200330 atomic_inc(&ab8500->transfer_ongoing);
Rabin Vincent62579262010-05-19 11:39:02 +0200331}
332
Mark Brown9505a0a2010-12-11 13:16:08 +0000333static void ab8500_irq_sync_unlock(struct irq_data *data)
Rabin Vincent62579262010-05-19 11:39:02 +0200334{
Mark Brown9505a0a2010-12-11 13:16:08 +0000335 struct ab8500 *ab8500 = irq_data_get_irq_chip_data(data);
Rabin Vincent62579262010-05-19 11:39:02 +0200336 int i;
337
Linus Walleij2ced4452012-02-20 21:42:17 +0100338 for (i = 0; i < ab8500->mask_size; i++) {
Rabin Vincent62579262010-05-19 11:39:02 +0200339 u8 old = ab8500->oldmask[i];
340 u8 new = ab8500->mask[i];
341 int reg;
342
343 if (new == old)
344 continue;
345
Linus Walleij0f6208372012-02-20 21:42:10 +0100346 /*
347 * Interrupt register 12 doesn't exist prior to AB8500 version
348 * 2.0
349 */
350 if (ab8500->irq_reg_offset[i] == 11 &&
351 is_ab8500_1p1_or_earlier(ab8500))
Mattias Wallin92d50a42010-12-07 11:20:47 +0100352 continue;
353
Rabin Vincent62579262010-05-19 11:39:02 +0200354 ab8500->oldmask[i] = new;
355
Linus Walleij2ced4452012-02-20 21:42:17 +0100356 reg = AB8500_IT_MASK1_REG + ab8500->irq_reg_offset[i];
Mattias Wallin47c16972010-09-10 17:47:56 +0200357 set_register_interruptible(ab8500, AB8500_INTERRUPT, reg, new);
Rabin Vincent62579262010-05-19 11:39:02 +0200358 }
Jonas Aaberg112a80d2012-04-17 09:30:33 +0200359 atomic_dec(&ab8500->transfer_ongoing);
Rabin Vincent62579262010-05-19 11:39:02 +0200360 mutex_unlock(&ab8500->irq_lock);
361}
362
Mark Brown9505a0a2010-12-11 13:16:08 +0000363static void ab8500_irq_mask(struct irq_data *data)
Rabin Vincent62579262010-05-19 11:39:02 +0200364{
Mark Brown9505a0a2010-12-11 13:16:08 +0000365 struct ab8500 *ab8500 = irq_data_get_irq_chip_data(data);
Lee Jones06e589e2012-06-20 13:56:37 +0100366 int offset = data->hwirq;
Rabin Vincent62579262010-05-19 11:39:02 +0200367 int index = offset / 8;
368 int mask = 1 << (offset % 8);
369
370 ab8500->mask[index] |= mask;
Lee Jones9c677b92012-12-20 11:23:42 +0000371
372 /* The AB8500 GPIOs have two interrupts each (rising & falling). */
373 if (offset >= AB8500_INT_GPIO6R && offset <= AB8500_INT_GPIO41R)
374 ab8500->mask[index + 2] |= mask;
375 if (offset >= AB9540_INT_GPIO50R && offset <= AB9540_INT_GPIO54R)
376 ab8500->mask[index + 1] |= mask;
377 if (offset == AB8540_INT_GPIO43R || offset == AB8540_INT_GPIO44R)
378 ab8500->mask[index] |= (mask >> 1);
Rabin Vincent62579262010-05-19 11:39:02 +0200379}
380
Mark Brown9505a0a2010-12-11 13:16:08 +0000381static void ab8500_irq_unmask(struct irq_data *data)
Rabin Vincent62579262010-05-19 11:39:02 +0200382{
Mark Brown9505a0a2010-12-11 13:16:08 +0000383 struct ab8500 *ab8500 = irq_data_get_irq_chip_data(data);
Lee Jones9c677b92012-12-20 11:23:42 +0000384 unsigned int type = irqd_get_trigger_type(data);
Lee Jones06e589e2012-06-20 13:56:37 +0100385 int offset = data->hwirq;
Rabin Vincent62579262010-05-19 11:39:02 +0200386 int index = offset / 8;
387 int mask = 1 << (offset % 8);
388
Lee Jones9c677b92012-12-20 11:23:42 +0000389 if (type & IRQ_TYPE_EDGE_RISING)
390 ab8500->mask[index] &= ~mask;
391
392 /* The AB8500 GPIOs have two interrupts each (rising & falling). */
393 if (type & IRQ_TYPE_EDGE_FALLING) {
394 if (offset >= AB8500_INT_GPIO6R && offset <= AB8500_INT_GPIO41R)
395 ab8500->mask[index + 2] &= ~mask;
396 else if (offset >= AB9540_INT_GPIO50R && offset <= AB9540_INT_GPIO54R)
397 ab8500->mask[index + 1] &= ~mask;
398 else if (offset == AB8540_INT_GPIO43R || offset == AB8540_INT_GPIO44R)
399 ab8500->mask[index] &= ~(mask >> 1);
400 else
401 ab8500->mask[index] &= ~mask;
402 } else
403 /* Satisfies the case where type is not set. */
404 ab8500->mask[index] &= ~mask;
Rabin Vincent62579262010-05-19 11:39:02 +0200405}
406
407static struct irq_chip ab8500_irq_chip = {
408 .name = "ab8500",
Mark Brown9505a0a2010-12-11 13:16:08 +0000409 .irq_bus_lock = ab8500_irq_lock,
410 .irq_bus_sync_unlock = ab8500_irq_sync_unlock,
411 .irq_mask = ab8500_irq_mask,
Virupax Sadashivpetimathe6f93062011-10-11 10:49:17 +0200412 .irq_disable = ab8500_irq_mask,
Mark Brown9505a0a2010-12-11 13:16:08 +0000413 .irq_unmask = ab8500_irq_unmask,
Rabin Vincent62579262010-05-19 11:39:02 +0200414};
415
Michel JAOUEN7ccfe9b2012-05-07 15:02:03 +0200416static int ab8500_handle_hierarchical_line(struct ab8500 *ab8500,
417 int latch_offset, u8 latch_val)
418{
419 int int_bit = __ffs(latch_val);
420 int line, i;
421
422 do {
423 int_bit = __ffs(latch_val);
424
425 for (i = 0; i < ab8500->mask_size; i++)
426 if (ab8500->irq_reg_offset[i] == latch_offset)
427 break;
428
429 if (i >= ab8500->mask_size) {
430 dev_err(ab8500->dev, "Register offset 0x%2x not declared\n",
431 latch_offset);
432 return -ENXIO;
433 }
434
435 line = (i << 3) + int_bit;
436 latch_val &= ~(1 << int_bit);
437
438 handle_nested_irq(ab8500->irq_base + line);
439 } while (latch_val);
440
441 return 0;
442}
443
444static int ab8500_handle_hierarchical_latch(struct ab8500 *ab8500,
445 int hier_offset, u8 hier_val)
446{
447 int latch_bit, status;
448 u8 latch_offset, latch_val;
449
450 do {
451 latch_bit = __ffs(hier_val);
452 latch_offset = (hier_offset << 3) + latch_bit;
453
454 /* Fix inconsistent ITFromLatch25 bit mapping... */
455 if (unlikely(latch_offset == 17))
456 latch_offset = 24;
457
458 status = get_register_interruptible(ab8500,
459 AB8500_INTERRUPT,
460 AB8500_IT_LATCH1_REG + latch_offset,
461 &latch_val);
462 if (status < 0 || latch_val == 0)
463 goto discard;
464
465 status = ab8500_handle_hierarchical_line(ab8500,
466 latch_offset, latch_val);
467 if (status < 0)
468 return status;
469discard:
470 hier_val &= ~(1 << latch_bit);
471 } while (hier_val);
472
473 return 0;
474}
475
476static irqreturn_t ab8500_hierarchical_irq(int irq, void *dev)
477{
478 struct ab8500 *ab8500 = dev;
479 u8 i;
480
481 dev_vdbg(ab8500->dev, "interrupt\n");
482
483 /* Hierarchical interrupt version */
484 for (i = 0; i < AB8500_IT_LATCHHIER_NUM; i++) {
485 int status;
486 u8 hier_val;
487
488 status = get_register_interruptible(ab8500, AB8500_INTERRUPT,
489 AB8500_IT_LATCHHIER1_REG + i, &hier_val);
490 if (status < 0 || hier_val == 0)
491 continue;
492
493 status = ab8500_handle_hierarchical_latch(ab8500, i, hier_val);
494 if (status < 0)
495 break;
496 }
497 return IRQ_HANDLED;
498}
499
Lee Jones80633f02012-08-20 11:53:36 +0100500/**
501 * ab8500_irq_get_virq(): Map an interrupt on a chip to a virtual IRQ
502 *
503 * @ab8500: ab8500_irq controller to operate on.
504 * @irq: index of the interrupt requested in the chip IRQs
505 *
506 * Useful for drivers to request their own IRQs.
507 */
508static int ab8500_irq_get_virq(struct ab8500 *ab8500, int irq)
509{
510 if (!ab8500)
511 return -EINVAL;
512
513 return irq_create_mapping(ab8500->domain, irq);
514}
515
Rabin Vincent62579262010-05-19 11:39:02 +0200516static irqreturn_t ab8500_irq(int irq, void *dev)
517{
518 struct ab8500 *ab8500 = dev;
519 int i;
520
521 dev_vdbg(ab8500->dev, "interrupt\n");
522
Jonas Aaberg112a80d2012-04-17 09:30:33 +0200523 atomic_inc(&ab8500->transfer_ongoing);
524
Linus Walleij2ced4452012-02-20 21:42:17 +0100525 for (i = 0; i < ab8500->mask_size; i++) {
526 int regoffset = ab8500->irq_reg_offset[i];
Rabin Vincent62579262010-05-19 11:39:02 +0200527 int status;
Mattias Wallin47c16972010-09-10 17:47:56 +0200528 u8 value;
Rabin Vincent62579262010-05-19 11:39:02 +0200529
Linus Walleij0f6208372012-02-20 21:42:10 +0100530 /*
531 * Interrupt register 12 doesn't exist prior to AB8500 version
532 * 2.0
533 */
534 if (regoffset == 11 && is_ab8500_1p1_or_earlier(ab8500))
Mattias Wallin92d50a42010-12-07 11:20:47 +0100535 continue;
536
Mattias Wallin47c16972010-09-10 17:47:56 +0200537 status = get_register_interruptible(ab8500, AB8500_INTERRUPT,
538 AB8500_IT_LATCH1_REG + regoffset, &value);
539 if (status < 0 || value == 0)
Rabin Vincent62579262010-05-19 11:39:02 +0200540 continue;
541
542 do {
Mattias Wallin88aec4f2010-12-02 15:06:49 +0100543 int bit = __ffs(value);
Rabin Vincent62579262010-05-19 11:39:02 +0200544 int line = i * 8 + bit;
Lee Jones0a37fc52012-08-09 16:53:54 +0100545 int virq = ab8500_irq_get_virq(ab8500, line);
Rabin Vincent62579262010-05-19 11:39:02 +0200546
Lee Jones0a37fc52012-08-09 16:53:54 +0100547 handle_nested_irq(virq);
Mattias Wallin47c16972010-09-10 17:47:56 +0200548 value &= ~(1 << bit);
Jonas Aaberg112a80d2012-04-17 09:30:33 +0200549
Mattias Wallin47c16972010-09-10 17:47:56 +0200550 } while (value);
Rabin Vincent62579262010-05-19 11:39:02 +0200551 }
Jonas Aaberg112a80d2012-04-17 09:30:33 +0200552 atomic_dec(&ab8500->transfer_ongoing);
Rabin Vincent62579262010-05-19 11:39:02 +0200553 return IRQ_HANDLED;
554}
555
Lee Jones06e589e2012-06-20 13:56:37 +0100556static int ab8500_irq_map(struct irq_domain *d, unsigned int virq,
557 irq_hw_number_t hwirq)
558{
559 struct ab8500 *ab8500 = d->host_data;
560
561 if (!ab8500)
562 return -EINVAL;
563
564 irq_set_chip_data(virq, ab8500);
565 irq_set_chip_and_handler(virq, &ab8500_irq_chip,
566 handle_simple_irq);
567 irq_set_nested_thread(virq, 1);
Rabin Vincent62579262010-05-19 11:39:02 +0200568#ifdef CONFIG_ARM
Lee Jones06e589e2012-06-20 13:56:37 +0100569 set_irq_flags(virq, IRQF_VALID);
Rabin Vincent62579262010-05-19 11:39:02 +0200570#else
Lee Jones06e589e2012-06-20 13:56:37 +0100571 irq_set_noprobe(virq);
Rabin Vincent62579262010-05-19 11:39:02 +0200572#endif
Rabin Vincent62579262010-05-19 11:39:02 +0200573
574 return 0;
575}
576
Lee Jones06e589e2012-06-20 13:56:37 +0100577static struct irq_domain_ops ab8500_irq_ops = {
578 .map = ab8500_irq_map,
579 .xlate = irq_domain_xlate_twocell,
580};
581
582static int ab8500_irq_init(struct ab8500 *ab8500, struct device_node *np)
Rabin Vincent62579262010-05-19 11:39:02 +0200583{
Linus Walleij2ced4452012-02-20 21:42:17 +0100584 int num_irqs;
Rabin Vincent62579262010-05-19 11:39:02 +0200585
Linus Walleijd6255522012-02-20 21:42:24 +0100586 if (is_ab9540(ab8500))
587 num_irqs = AB9540_NR_IRQS;
Bengt Jonssona9823622012-03-08 14:01:57 +0100588 else if (is_ab8505(ab8500))
589 num_irqs = AB8505_NR_IRQS;
Linus Walleijd6255522012-02-20 21:42:24 +0100590 else
591 num_irqs = AB8500_NR_IRQS;
Linus Walleij2ced4452012-02-20 21:42:17 +0100592
Linus Walleijf1d11f32012-10-18 18:18:44 +0200593 /* If ->irq_base is zero this will give a linear mapping */
594 ab8500->domain = irq_domain_add_simple(NULL,
595 num_irqs, ab8500->irq_base,
596 &ab8500_irq_ops, ab8500);
Lee Jones06e589e2012-06-20 13:56:37 +0100597
598 if (!ab8500->domain) {
599 dev_err(ab8500->dev, "Failed to create irqdomain\n");
600 return -ENOSYS;
601 }
602
603 return 0;
Rabin Vincent62579262010-05-19 11:39:02 +0200604}
605
Jonas Aaberg112a80d2012-04-17 09:30:33 +0200606int ab8500_suspend(struct ab8500 *ab8500)
607{
608 if (atomic_read(&ab8500->transfer_ongoing))
609 return -EINVAL;
610 else
611 return 0;
612}
613
Bill Pembertona9e9ce42012-11-19 13:24:21 -0500614static struct resource ab8500_gpadc_resources[] = {
Rabin Vincent62579262010-05-19 11:39:02 +0200615 {
616 .name = "HW_CONV_END",
617 .start = AB8500_INT_GP_HW_ADC_CONV_END,
618 .end = AB8500_INT_GP_HW_ADC_CONV_END,
619 .flags = IORESOURCE_IRQ,
620 },
621 {
622 .name = "SW_CONV_END",
623 .start = AB8500_INT_GP_SW_ADC_CONV_END,
624 .end = AB8500_INT_GP_SW_ADC_CONV_END,
625 .flags = IORESOURCE_IRQ,
626 },
627};
628
Bill Pembertona9e9ce42012-11-19 13:24:21 -0500629static struct resource ab8500_rtc_resources[] = {
Rabin Vincent62579262010-05-19 11:39:02 +0200630 {
631 .name = "60S",
632 .start = AB8500_INT_RTC_60S,
633 .end = AB8500_INT_RTC_60S,
634 .flags = IORESOURCE_IRQ,
635 },
636 {
637 .name = "ALARM",
638 .start = AB8500_INT_RTC_ALARM,
639 .end = AB8500_INT_RTC_ALARM,
640 .flags = IORESOURCE_IRQ,
641 },
642};
643
Bill Pembertona9e9ce42012-11-19 13:24:21 -0500644static struct resource ab8500_poweronkey_db_resources[] = {
Sundar R Iyer77686512010-09-05 12:18:47 -0700645 {
646 .name = "ONKEY_DBF",
647 .start = AB8500_INT_PON_KEY1DB_F,
648 .end = AB8500_INT_PON_KEY1DB_F,
649 .flags = IORESOURCE_IRQ,
650 },
651 {
652 .name = "ONKEY_DBR",
653 .start = AB8500_INT_PON_KEY1DB_R,
654 .end = AB8500_INT_PON_KEY1DB_R,
655 .flags = IORESOURCE_IRQ,
656 },
657};
658
Bill Pembertona9e9ce42012-11-19 13:24:21 -0500659static struct resource ab8500_av_acc_detect_resources[] = {
Mattias Walline098aded72010-12-02 15:40:31 +0100660 {
Linus Walleij6af75ec2011-06-09 23:57:45 +0200661 .name = "ACC_DETECT_1DB_F",
662 .start = AB8500_INT_ACC_DETECT_1DB_F,
663 .end = AB8500_INT_ACC_DETECT_1DB_F,
664 .flags = IORESOURCE_IRQ,
Mattias Walline098aded72010-12-02 15:40:31 +0100665 },
666 {
Linus Walleij6af75ec2011-06-09 23:57:45 +0200667 .name = "ACC_DETECT_1DB_R",
668 .start = AB8500_INT_ACC_DETECT_1DB_R,
669 .end = AB8500_INT_ACC_DETECT_1DB_R,
670 .flags = IORESOURCE_IRQ,
Mattias Walline098aded72010-12-02 15:40:31 +0100671 },
672 {
Linus Walleij6af75ec2011-06-09 23:57:45 +0200673 .name = "ACC_DETECT_21DB_F",
674 .start = AB8500_INT_ACC_DETECT_21DB_F,
675 .end = AB8500_INT_ACC_DETECT_21DB_F,
676 .flags = IORESOURCE_IRQ,
677 },
678 {
679 .name = "ACC_DETECT_21DB_R",
680 .start = AB8500_INT_ACC_DETECT_21DB_R,
681 .end = AB8500_INT_ACC_DETECT_21DB_R,
682 .flags = IORESOURCE_IRQ,
683 },
684 {
685 .name = "ACC_DETECT_22DB_F",
686 .start = AB8500_INT_ACC_DETECT_22DB_F,
687 .end = AB8500_INT_ACC_DETECT_22DB_F,
688 .flags = IORESOURCE_IRQ,
689 },
690 {
691 .name = "ACC_DETECT_22DB_R",
692 .start = AB8500_INT_ACC_DETECT_22DB_R,
693 .end = AB8500_INT_ACC_DETECT_22DB_R,
694 .flags = IORESOURCE_IRQ,
695 },
696};
697
Bill Pembertona9e9ce42012-11-19 13:24:21 -0500698static struct resource ab8500_charger_resources[] = {
Linus Walleij6af75ec2011-06-09 23:57:45 +0200699 {
Mattias Walline098aded72010-12-02 15:40:31 +0100700 .name = "MAIN_CH_UNPLUG_DET",
701 .start = AB8500_INT_MAIN_CH_UNPLUG_DET,
702 .end = AB8500_INT_MAIN_CH_UNPLUG_DET,
703 .flags = IORESOURCE_IRQ,
704 },
705 {
706 .name = "MAIN_CHARGE_PLUG_DET",
707 .start = AB8500_INT_MAIN_CH_PLUG_DET,
708 .end = AB8500_INT_MAIN_CH_PLUG_DET,
709 .flags = IORESOURCE_IRQ,
710 },
711 {
Mattias Walline098aded72010-12-02 15:40:31 +0100712 .name = "VBUS_DET_R",
713 .start = AB8500_INT_VBUS_DET_R,
714 .end = AB8500_INT_VBUS_DET_R,
715 .flags = IORESOURCE_IRQ,
716 },
717 {
Linus Walleij6af75ec2011-06-09 23:57:45 +0200718 .name = "VBUS_DET_F",
719 .start = AB8500_INT_VBUS_DET_F,
720 .end = AB8500_INT_VBUS_DET_F,
Mattias Walline098aded72010-12-02 15:40:31 +0100721 .flags = IORESOURCE_IRQ,
722 },
723 {
Linus Walleij6af75ec2011-06-09 23:57:45 +0200724 .name = "USB_LINK_STATUS",
725 .start = AB8500_INT_USB_LINK_STATUS,
726 .end = AB8500_INT_USB_LINK_STATUS,
727 .flags = IORESOURCE_IRQ,
728 },
729 {
Mattias Walline098aded72010-12-02 15:40:31 +0100730 .name = "VBUS_OVV",
731 .start = AB8500_INT_VBUS_OVV,
732 .end = AB8500_INT_VBUS_OVV,
733 .flags = IORESOURCE_IRQ,
734 },
735 {
Linus Walleij6af75ec2011-06-09 23:57:45 +0200736 .name = "USB_CH_TH_PROT_R",
737 .start = AB8500_INT_USB_CH_TH_PROT_R,
738 .end = AB8500_INT_USB_CH_TH_PROT_R,
Mattias Walline098aded72010-12-02 15:40:31 +0100739 .flags = IORESOURCE_IRQ,
740 },
741 {
Linus Walleij6af75ec2011-06-09 23:57:45 +0200742 .name = "USB_CH_TH_PROT_F",
743 .start = AB8500_INT_USB_CH_TH_PROT_F,
744 .end = AB8500_INT_USB_CH_TH_PROT_F,
Mattias Walline098aded72010-12-02 15:40:31 +0100745 .flags = IORESOURCE_IRQ,
746 },
747 {
Linus Walleij6af75ec2011-06-09 23:57:45 +0200748 .name = "MAIN_EXT_CH_NOT_OK",
749 .start = AB8500_INT_MAIN_EXT_CH_NOT_OK,
750 .end = AB8500_INT_MAIN_EXT_CH_NOT_OK,
751 .flags = IORESOURCE_IRQ,
752 },
753 {
754 .name = "MAIN_CH_TH_PROT_R",
755 .start = AB8500_INT_MAIN_CH_TH_PROT_R,
756 .end = AB8500_INT_MAIN_CH_TH_PROT_R,
757 .flags = IORESOURCE_IRQ,
758 },
759 {
760 .name = "MAIN_CH_TH_PROT_F",
761 .start = AB8500_INT_MAIN_CH_TH_PROT_F,
762 .end = AB8500_INT_MAIN_CH_TH_PROT_F,
763 .flags = IORESOURCE_IRQ,
764 },
765 {
766 .name = "USB_CHARGER_NOT_OKR",
Bengt Jonssona9823622012-03-08 14:01:57 +0100767 .start = AB8500_INT_USB_CHARGER_NOT_OKR,
768 .end = AB8500_INT_USB_CHARGER_NOT_OKR,
Linus Walleij6af75ec2011-06-09 23:57:45 +0200769 .flags = IORESOURCE_IRQ,
770 },
771 {
772 .name = "CH_WD_EXP",
773 .start = AB8500_INT_CH_WD_EXP,
774 .end = AB8500_INT_CH_WD_EXP,
775 .flags = IORESOURCE_IRQ,
776 },
777};
778
Bill Pembertona9e9ce42012-11-19 13:24:21 -0500779static struct resource ab8500_btemp_resources[] = {
Linus Walleij6af75ec2011-06-09 23:57:45 +0200780 {
781 .name = "BAT_CTRL_INDB",
782 .start = AB8500_INT_BAT_CTRL_INDB,
783 .end = AB8500_INT_BAT_CTRL_INDB,
Mattias Walline098aded72010-12-02 15:40:31 +0100784 .flags = IORESOURCE_IRQ,
785 },
786 {
787 .name = "BTEMP_LOW",
788 .start = AB8500_INT_BTEMP_LOW,
789 .end = AB8500_INT_BTEMP_LOW,
790 .flags = IORESOURCE_IRQ,
791 },
792 {
793 .name = "BTEMP_HIGH",
794 .start = AB8500_INT_BTEMP_HIGH,
795 .end = AB8500_INT_BTEMP_HIGH,
796 .flags = IORESOURCE_IRQ,
797 },
798 {
Linus Walleij6af75ec2011-06-09 23:57:45 +0200799 .name = "BTEMP_LOW_MEDIUM",
800 .start = AB8500_INT_BTEMP_LOW_MEDIUM,
801 .end = AB8500_INT_BTEMP_LOW_MEDIUM,
Mattias Walline098aded72010-12-02 15:40:31 +0100802 .flags = IORESOURCE_IRQ,
803 },
804 {
Linus Walleij6af75ec2011-06-09 23:57:45 +0200805 .name = "BTEMP_MEDIUM_HIGH",
806 .start = AB8500_INT_BTEMP_MEDIUM_HIGH,
807 .end = AB8500_INT_BTEMP_MEDIUM_HIGH,
Mattias Walline098aded72010-12-02 15:40:31 +0100808 .flags = IORESOURCE_IRQ,
809 },
810};
811
Bill Pembertona9e9ce42012-11-19 13:24:21 -0500812static struct resource ab8500_fg_resources[] = {
Linus Walleij6af75ec2011-06-09 23:57:45 +0200813 {
814 .name = "NCONV_ACCU",
815 .start = AB8500_INT_CCN_CONV_ACC,
816 .end = AB8500_INT_CCN_CONV_ACC,
817 .flags = IORESOURCE_IRQ,
818 },
819 {
820 .name = "BATT_OVV",
821 .start = AB8500_INT_BATT_OVV,
822 .end = AB8500_INT_BATT_OVV,
823 .flags = IORESOURCE_IRQ,
824 },
825 {
826 .name = "LOW_BAT_F",
827 .start = AB8500_INT_LOW_BAT_F,
828 .end = AB8500_INT_LOW_BAT_F,
829 .flags = IORESOURCE_IRQ,
830 },
831 {
832 .name = "LOW_BAT_R",
833 .start = AB8500_INT_LOW_BAT_R,
834 .end = AB8500_INT_LOW_BAT_R,
835 .flags = IORESOURCE_IRQ,
836 },
837 {
838 .name = "CC_INT_CALIB",
839 .start = AB8500_INT_CC_INT_CALIB,
840 .end = AB8500_INT_CC_INT_CALIB,
841 .flags = IORESOURCE_IRQ,
842 },
Bengt Jonssona9823622012-03-08 14:01:57 +0100843 {
844 .name = "CCEOC",
845 .start = AB8500_INT_CCEOC,
846 .end = AB8500_INT_CCEOC,
847 .flags = IORESOURCE_IRQ,
848 },
Linus Walleij6af75ec2011-06-09 23:57:45 +0200849};
850
Bill Pembertona9e9ce42012-11-19 13:24:21 -0500851static struct resource ab8500_chargalg_resources[] = {};
Linus Walleij6af75ec2011-06-09 23:57:45 +0200852
Axel Lindf720642011-11-10 09:56:18 +0800853#ifdef CONFIG_DEBUG_FS
Bill Pembertona9e9ce42012-11-19 13:24:21 -0500854static struct resource ab8500_debug_resources[] = {
Mattias Walline098aded72010-12-02 15:40:31 +0100855 {
856 .name = "IRQ_FIRST",
857 .start = AB8500_INT_MAIN_EXT_CH_NOT_OK,
858 .end = AB8500_INT_MAIN_EXT_CH_NOT_OK,
859 .flags = IORESOURCE_IRQ,
860 },
861 {
862 .name = "IRQ_LAST",
Bengt Jonssona9823622012-03-08 14:01:57 +0100863 .start = AB8500_INT_XTAL32K_KO,
864 .end = AB8500_INT_XTAL32K_KO,
Mattias Walline098aded72010-12-02 15:40:31 +0100865 .flags = IORESOURCE_IRQ,
866 },
867};
Axel Lindf720642011-11-10 09:56:18 +0800868#endif
Mattias Walline098aded72010-12-02 15:40:31 +0100869
Bill Pembertona9e9ce42012-11-19 13:24:21 -0500870static struct resource ab8500_usb_resources[] = {
Mattias Walline098aded72010-12-02 15:40:31 +0100871 {
872 .name = "ID_WAKEUP_R",
873 .start = AB8500_INT_ID_WAKEUP_R,
874 .end = AB8500_INT_ID_WAKEUP_R,
875 .flags = IORESOURCE_IRQ,
876 },
877 {
878 .name = "ID_WAKEUP_F",
879 .start = AB8500_INT_ID_WAKEUP_F,
880 .end = AB8500_INT_ID_WAKEUP_F,
881 .flags = IORESOURCE_IRQ,
882 },
883 {
884 .name = "VBUS_DET_F",
885 .start = AB8500_INT_VBUS_DET_F,
886 .end = AB8500_INT_VBUS_DET_F,
887 .flags = IORESOURCE_IRQ,
888 },
889 {
890 .name = "VBUS_DET_R",
891 .start = AB8500_INT_VBUS_DET_R,
892 .end = AB8500_INT_VBUS_DET_R,
893 .flags = IORESOURCE_IRQ,
894 },
Mattias Wallin92d50a42010-12-07 11:20:47 +0100895 {
896 .name = "USB_LINK_STATUS",
897 .start = AB8500_INT_USB_LINK_STATUS,
898 .end = AB8500_INT_USB_LINK_STATUS,
899 .flags = IORESOURCE_IRQ,
900 },
Linus Walleij6af75ec2011-06-09 23:57:45 +0200901 {
902 .name = "USB_ADP_PROBE_PLUG",
903 .start = AB8500_INT_ADP_PROBE_PLUG,
904 .end = AB8500_INT_ADP_PROBE_PLUG,
905 .flags = IORESOURCE_IRQ,
906 },
907 {
908 .name = "USB_ADP_PROBE_UNPLUG",
909 .start = AB8500_INT_ADP_PROBE_UNPLUG,
910 .end = AB8500_INT_ADP_PROBE_UNPLUG,
911 .flags = IORESOURCE_IRQ,
912 },
Mattias Walline098aded72010-12-02 15:40:31 +0100913};
914
Bill Pembertona9e9ce42012-11-19 13:24:21 -0500915static struct resource ab8505_iddet_resources[] = {
Virupax Sadashivpetimath44f72e52012-04-17 09:30:14 +0200916 {
917 .name = "KeyDeglitch",
918 .start = AB8505_INT_KEYDEGLITCH,
919 .end = AB8505_INT_KEYDEGLITCH,
920 .flags = IORESOURCE_IRQ,
921 },
922 {
923 .name = "KP",
924 .start = AB8505_INT_KP,
925 .end = AB8505_INT_KP,
926 .flags = IORESOURCE_IRQ,
927 },
928 {
929 .name = "IKP",
930 .start = AB8505_INT_IKP,
931 .end = AB8505_INT_IKP,
932 .flags = IORESOURCE_IRQ,
933 },
934 {
935 .name = "IKR",
936 .start = AB8505_INT_IKR,
937 .end = AB8505_INT_IKR,
938 .flags = IORESOURCE_IRQ,
939 },
940 {
941 .name = "KeyStuck",
942 .start = AB8505_INT_KEYSTUCK,
943 .end = AB8505_INT_KEYSTUCK,
944 .flags = IORESOURCE_IRQ,
945 },
946};
947
Bill Pembertona9e9ce42012-11-19 13:24:21 -0500948static struct resource ab8500_temp_resources[] = {
Mattias Walline098aded72010-12-02 15:40:31 +0100949 {
950 .name = "AB8500_TEMP_WARM",
951 .start = AB8500_INT_TEMP_WARM,
952 .end = AB8500_INT_TEMP_WARM,
953 .flags = IORESOURCE_IRQ,
954 },
955};
956
Bill Pembertona9e9ce42012-11-19 13:24:21 -0500957static struct mfd_cell abx500_common_devs[] = {
Mattias Wallin5814fc32010-09-13 16:05:04 +0200958#ifdef CONFIG_DEBUG_FS
959 {
960 .name = "ab8500-debug",
Lee Jonesbad76992012-07-02 17:10:56 +0200961 .of_compatible = "stericsson,ab8500-debug",
Mattias Walline098aded72010-12-02 15:40:31 +0100962 .num_resources = ARRAY_SIZE(ab8500_debug_resources),
963 .resources = ab8500_debug_resources,
Mattias Wallin5814fc32010-09-13 16:05:04 +0200964 },
965#endif
Rabin Vincent62579262010-05-19 11:39:02 +0200966 {
Mattias Walline098aded72010-12-02 15:40:31 +0100967 .name = "ab8500-sysctrl",
Lee Jonesbad76992012-07-02 17:10:56 +0200968 .of_compatible = "stericsson,ab8500-sysctrl",
Mattias Walline098aded72010-12-02 15:40:31 +0100969 },
970 {
971 .name = "ab8500-regulator",
Lee Jonesbad76992012-07-02 17:10:56 +0200972 .of_compatible = "stericsson,ab8500-regulator",
Mattias Walline098aded72010-12-02 15:40:31 +0100973 },
974 {
Ulf Hansson916a8712012-11-22 11:35:40 +0100975 .name = "abx500-clk",
976 .of_compatible = "stericsson,abx500-clk",
977 },
978 {
Rabin Vincent62579262010-05-19 11:39:02 +0200979 .name = "ab8500-gpadc",
Lee Jonesbad76992012-07-02 17:10:56 +0200980 .of_compatible = "stericsson,ab8500-gpadc",
Rabin Vincent62579262010-05-19 11:39:02 +0200981 .num_resources = ARRAY_SIZE(ab8500_gpadc_resources),
982 .resources = ab8500_gpadc_resources,
983 },
984 {
985 .name = "ab8500-rtc",
Lee Jonesbad76992012-07-02 17:10:56 +0200986 .of_compatible = "stericsson,ab8500-rtc",
Rabin Vincent62579262010-05-19 11:39:02 +0200987 .num_resources = ARRAY_SIZE(ab8500_rtc_resources),
988 .resources = ab8500_rtc_resources,
989 },
Arun Murthyf0f05b12010-09-06 12:24:52 +0530990 {
Linus Walleij6af75ec2011-06-09 23:57:45 +0200991 .name = "ab8500-acc-det",
Lee Jonesbad76992012-07-02 17:10:56 +0200992 .of_compatible = "stericsson,ab8500-acc-det",
Linus Walleij6af75ec2011-06-09 23:57:45 +0200993 .num_resources = ARRAY_SIZE(ab8500_av_acc_detect_resources),
994 .resources = ab8500_av_acc_detect_resources,
995 },
996 {
Mattias Walline098aded72010-12-02 15:40:31 +0100997 .name = "ab8500-poweron-key",
Lee Jonesbad76992012-07-02 17:10:56 +0200998 .of_compatible = "stericsson,ab8500-poweron-key",
Mattias Walline098aded72010-12-02 15:40:31 +0100999 .num_resources = ARRAY_SIZE(ab8500_poweronkey_db_resources),
1000 .resources = ab8500_poweronkey_db_resources,
1001 },
1002 {
Arun Murthyf0f05b12010-09-06 12:24:52 +05301003 .name = "ab8500-pwm",
Lee Jonesbad76992012-07-02 17:10:56 +02001004 .of_compatible = "stericsson,ab8500-pwm",
Arun Murthyf0f05b12010-09-06 12:24:52 +05301005 .id = 1,
1006 },
1007 {
1008 .name = "ab8500-pwm",
Lee Jonesbad76992012-07-02 17:10:56 +02001009 .of_compatible = "stericsson,ab8500-pwm",
Arun Murthyf0f05b12010-09-06 12:24:52 +05301010 .id = 2,
1011 },
1012 {
1013 .name = "ab8500-pwm",
Lee Jonesbad76992012-07-02 17:10:56 +02001014 .of_compatible = "stericsson,ab8500-pwm",
Arun Murthyf0f05b12010-09-06 12:24:52 +05301015 .id = 3,
1016 },
Lee Jonesbad76992012-07-02 17:10:56 +02001017 {
1018 .name = "ab8500-leds",
1019 .of_compatible = "stericsson,ab8500-leds",
1020 },
Sundar R Iyer77686512010-09-05 12:18:47 -07001021 {
Mattias Walline098aded72010-12-02 15:40:31 +01001022 .name = "ab8500-denc",
Lee Jonesbad76992012-07-02 17:10:56 +02001023 .of_compatible = "stericsson,ab8500-denc",
Mattias Walline098aded72010-12-02 15:40:31 +01001024 },
1025 {
1026 .name = "ab8500-temp",
Lee Jonesbad76992012-07-02 17:10:56 +02001027 .of_compatible = "stericsson,ab8500-temp",
Mattias Walline098aded72010-12-02 15:40:31 +01001028 .num_resources = ARRAY_SIZE(ab8500_temp_resources),
1029 .resources = ab8500_temp_resources,
Sundar R Iyer77686512010-09-05 12:18:47 -07001030 },
Rabin Vincent62579262010-05-19 11:39:02 +02001031};
1032
Bill Pembertona9e9ce42012-11-19 13:24:21 -05001033static struct mfd_cell ab8500_bm_devs[] = {
Rickard Andersson6ef94182012-04-17 09:30:57 +02001034 {
1035 .name = "ab8500-charger",
Rajanikanth H.V4aef72d2012-11-18 19:17:47 -08001036 .of_compatible = "stericsson,ab8500-charger",
Rickard Andersson6ef94182012-04-17 09:30:57 +02001037 .num_resources = ARRAY_SIZE(ab8500_charger_resources),
1038 .resources = ab8500_charger_resources,
Rajanikanth H.V4aef72d2012-11-18 19:17:47 -08001039#ifndef CONFIG_OF
1040 .platform_data = &ab8500_bm_data,
1041 .pdata_size = sizeof(ab8500_bm_data),
1042#endif
Rickard Andersson6ef94182012-04-17 09:30:57 +02001043 },
1044 {
1045 .name = "ab8500-btemp",
Rajanikanth H.Vbd9e8ab2012-11-18 19:16:58 -08001046 .of_compatible = "stericsson,ab8500-btemp",
Rickard Andersson6ef94182012-04-17 09:30:57 +02001047 .num_resources = ARRAY_SIZE(ab8500_btemp_resources),
1048 .resources = ab8500_btemp_resources,
Rajanikanth H.Vbd9e8ab2012-11-18 19:16:58 -08001049#ifndef CONFIG_OF
1050 .platform_data = &ab8500_bm_data,
1051 .pdata_size = sizeof(ab8500_bm_data),
1052#endif
Rickard Andersson6ef94182012-04-17 09:30:57 +02001053 },
1054 {
1055 .name = "ab8500-fg",
Rajanikanth H.Ve0f1abe2012-11-18 18:45:41 -08001056 .of_compatible = "stericsson,ab8500-fg",
Rickard Andersson6ef94182012-04-17 09:30:57 +02001057 .num_resources = ARRAY_SIZE(ab8500_fg_resources),
1058 .resources = ab8500_fg_resources,
Rajanikanth H.Ve0f1abe2012-11-18 18:45:41 -08001059#ifndef CONFIG_OF
1060 .platform_data = &ab8500_bm_data,
1061 .pdata_size = sizeof(ab8500_bm_data),
1062#endif
Rickard Andersson6ef94182012-04-17 09:30:57 +02001063 },
1064 {
1065 .name = "ab8500-chargalg",
Rajanikanth H.Va12810a2012-10-31 15:40:33 +00001066 .of_compatible = "stericsson,ab8500-chargalg",
Rickard Andersson6ef94182012-04-17 09:30:57 +02001067 .num_resources = ARRAY_SIZE(ab8500_chargalg_resources),
1068 .resources = ab8500_chargalg_resources,
Rajanikanth H.Va12810a2012-10-31 15:40:33 +00001069#ifndef CONFIG_OF
1070 .platform_data = &ab8500_bm_data,
1071 .pdata_size = sizeof(ab8500_bm_data),
1072#endif
Rickard Andersson6ef94182012-04-17 09:30:57 +02001073 },
1074};
1075
Bill Pembertona9e9ce42012-11-19 13:24:21 -05001076static struct mfd_cell ab8500_devs[] = {
Linus Walleijd6255522012-02-20 21:42:24 +01001077 {
1078 .name = "ab8500-gpio",
Lee Jonesbad76992012-07-02 17:10:56 +02001079 .of_compatible = "stericsson,ab8500-gpio",
Linus Walleijd6255522012-02-20 21:42:24 +01001080 },
1081 {
1082 .name = "ab8500-usb",
Lee Jonesbad76992012-07-02 17:10:56 +02001083 .of_compatible = "stericsson,ab8500-usb",
Linus Walleijd6255522012-02-20 21:42:24 +01001084 .num_resources = ARRAY_SIZE(ab8500_usb_resources),
1085 .resources = ab8500_usb_resources,
1086 },
Virupax Sadashivpetimath44f72e52012-04-17 09:30:14 +02001087 {
1088 .name = "ab8500-codec",
Lee Jones81a21cd2012-07-27 13:38:51 +01001089 .of_compatible = "stericsson,ab8500-codec",
Virupax Sadashivpetimath44f72e52012-04-17 09:30:14 +02001090 },
Linus Walleijd6255522012-02-20 21:42:24 +01001091};
1092
Bill Pembertona9e9ce42012-11-19 13:24:21 -05001093static struct mfd_cell ab9540_devs[] = {
Linus Walleijd6255522012-02-20 21:42:24 +01001094 {
1095 .name = "ab8500-gpio",
Linus Walleijd6255522012-02-20 21:42:24 +01001096 },
1097 {
1098 .name = "ab9540-usb",
1099 .num_resources = ARRAY_SIZE(ab8500_usb_resources),
1100 .resources = ab8500_usb_resources,
1101 },
Virupax Sadashivpetimath44f72e52012-04-17 09:30:14 +02001102 {
1103 .name = "ab9540-codec",
1104 },
1105};
1106
1107/* Device list common to ab9540 and ab8505 */
Bill Pembertona9e9ce42012-11-19 13:24:21 -05001108static struct mfd_cell ab9540_ab8505_devs[] = {
Virupax Sadashivpetimath44f72e52012-04-17 09:30:14 +02001109 {
1110 .name = "ab-iddet",
1111 .num_resources = ARRAY_SIZE(ab8505_iddet_resources),
1112 .resources = ab8505_iddet_resources,
1113 },
Linus Walleijd6255522012-02-20 21:42:24 +01001114};
1115
Mattias Wallincca69b62010-12-02 15:09:36 +01001116static ssize_t show_chip_id(struct device *dev,
1117 struct device_attribute *attr, char *buf)
1118{
1119 struct ab8500 *ab8500;
1120
1121 ab8500 = dev_get_drvdata(dev);
1122 return sprintf(buf, "%#x\n", ab8500 ? ab8500->chip_id : -EINVAL);
1123}
1124
Mattias Walline5c238c2011-03-02 11:52:36 +01001125/*
1126 * ab8500 has switched off due to (SWITCH_OFF_STATUS):
1127 * 0x01 Swoff bit programming
1128 * 0x02 Thermal protection activation
1129 * 0x04 Vbat lower then BattOk falling threshold
1130 * 0x08 Watchdog expired
1131 * 0x10 Non presence of 32kHz clock
1132 * 0x20 Battery level lower than power on reset threshold
1133 * 0x40 Power on key 1 pressed longer than 10 seconds
1134 * 0x80 DB8500 thermal shutdown
1135 */
1136static ssize_t show_switch_off_status(struct device *dev,
1137 struct device_attribute *attr, char *buf)
1138{
1139 int ret;
1140 u8 value;
1141 struct ab8500 *ab8500;
1142
1143 ab8500 = dev_get_drvdata(dev);
1144 ret = get_register_interruptible(ab8500, AB8500_RTC,
1145 AB8500_SWITCH_OFF_STATUS, &value);
1146 if (ret < 0)
1147 return ret;
1148 return sprintf(buf, "%#x\n", value);
1149}
1150
Andrew Lynnb4a31032011-10-11 10:49:47 +02001151/*
1152 * ab8500 has turned on due to (TURN_ON_STATUS):
1153 * 0x01 PORnVbat
1154 * 0x02 PonKey1dbF
1155 * 0x04 PonKey2dbF
1156 * 0x08 RTCAlarm
1157 * 0x10 MainChDet
1158 * 0x20 VbusDet
1159 * 0x40 UsbIDDetect
1160 * 0x80 Reserved
1161 */
1162static ssize_t show_turn_on_status(struct device *dev,
1163 struct device_attribute *attr, char *buf)
1164{
1165 int ret;
1166 u8 value;
1167 struct ab8500 *ab8500;
1168
1169 ab8500 = dev_get_drvdata(dev);
1170 ret = get_register_interruptible(ab8500, AB8500_SYS_CTRL1_BLOCK,
1171 AB8500_TURN_ON_STATUS, &value);
1172 if (ret < 0)
1173 return ret;
1174 return sprintf(buf, "%#x\n", value);
1175}
1176
Linus Walleijd6255522012-02-20 21:42:24 +01001177static ssize_t show_ab9540_dbbrstn(struct device *dev,
1178 struct device_attribute *attr, char *buf)
1179{
1180 struct ab8500 *ab8500;
1181 int ret;
1182 u8 value;
1183
1184 ab8500 = dev_get_drvdata(dev);
1185
1186 ret = get_register_interruptible(ab8500, AB8500_REGU_CTRL2,
1187 AB9540_MODEM_CTRL2_REG, &value);
1188 if (ret < 0)
1189 return ret;
1190
1191 return sprintf(buf, "%d\n",
1192 (value & AB9540_MODEM_CTRL2_SWDBBRSTN_BIT) ? 1 : 0);
1193}
1194
1195static ssize_t store_ab9540_dbbrstn(struct device *dev,
1196 struct device_attribute *attr, const char *buf, size_t count)
1197{
1198 struct ab8500 *ab8500;
1199 int ret = count;
1200 int err;
1201 u8 bitvalues;
1202
1203 ab8500 = dev_get_drvdata(dev);
1204
1205 if (count > 0) {
1206 switch (buf[0]) {
1207 case '0':
1208 bitvalues = 0;
1209 break;
1210 case '1':
1211 bitvalues = AB9540_MODEM_CTRL2_SWDBBRSTN_BIT;
1212 break;
1213 default:
1214 goto exit;
1215 }
1216
1217 err = mask_and_set_register_interruptible(ab8500,
1218 AB8500_REGU_CTRL2, AB9540_MODEM_CTRL2_REG,
1219 AB9540_MODEM_CTRL2_SWDBBRSTN_BIT, bitvalues);
1220 if (err)
1221 dev_info(ab8500->dev,
1222 "Failed to set DBBRSTN %c, err %#x\n",
1223 buf[0], err);
1224 }
1225
1226exit:
1227 return ret;
1228}
1229
Mattias Wallincca69b62010-12-02 15:09:36 +01001230static DEVICE_ATTR(chip_id, S_IRUGO, show_chip_id, NULL);
Mattias Walline5c238c2011-03-02 11:52:36 +01001231static DEVICE_ATTR(switch_off_status, S_IRUGO, show_switch_off_status, NULL);
Andrew Lynnb4a31032011-10-11 10:49:47 +02001232static DEVICE_ATTR(turn_on_status, S_IRUGO, show_turn_on_status, NULL);
Linus Walleijd6255522012-02-20 21:42:24 +01001233static DEVICE_ATTR(dbbrstn, S_IRUGO | S_IWUSR,
1234 show_ab9540_dbbrstn, store_ab9540_dbbrstn);
Mattias Wallincca69b62010-12-02 15:09:36 +01001235
1236static struct attribute *ab8500_sysfs_entries[] = {
1237 &dev_attr_chip_id.attr,
Mattias Walline5c238c2011-03-02 11:52:36 +01001238 &dev_attr_switch_off_status.attr,
Andrew Lynnb4a31032011-10-11 10:49:47 +02001239 &dev_attr_turn_on_status.attr,
Mattias Wallincca69b62010-12-02 15:09:36 +01001240 NULL,
1241};
1242
Linus Walleijd6255522012-02-20 21:42:24 +01001243static struct attribute *ab9540_sysfs_entries[] = {
1244 &dev_attr_chip_id.attr,
1245 &dev_attr_switch_off_status.attr,
1246 &dev_attr_turn_on_status.attr,
1247 &dev_attr_dbbrstn.attr,
1248 NULL,
1249};
1250
Mattias Wallincca69b62010-12-02 15:09:36 +01001251static struct attribute_group ab8500_attr_group = {
1252 .attrs = ab8500_sysfs_entries,
1253};
1254
Linus Walleijd6255522012-02-20 21:42:24 +01001255static struct attribute_group ab9540_attr_group = {
1256 .attrs = ab9540_sysfs_entries,
1257};
1258
Bill Pembertonf791be42012-11-19 13:23:04 -05001259static int ab8500_probe(struct platform_device *pdev)
Rabin Vincent62579262010-05-19 11:39:02 +02001260{
Jonas Aabergb04c530c2012-06-29 17:46:12 +02001261 static char *switch_off_status[] = {
1262 "Swoff bit programming",
1263 "Thermal protection activation",
1264 "Vbat lower then BattOk falling threshold",
1265 "Watchdog expired",
1266 "Non presence of 32kHz clock",
1267 "Battery level lower than power on reset threshold",
1268 "Power on key 1 pressed longer than 10 seconds",
1269 "DB8500 thermal shutdown"};
Lee Jonesd28f1db2012-05-19 17:21:37 +02001270 struct ab8500_platform_data *plat = dev_get_platdata(&pdev->dev);
1271 const struct platform_device_id *platid = platform_get_device_id(pdev);
Lee Jones6bc4a562012-05-17 14:45:13 +01001272 enum ab8500_version version = AB8500_VERSION_UNDEFINED;
1273 struct device_node *np = pdev->dev.of_node;
Lee Jonesd28f1db2012-05-19 17:21:37 +02001274 struct ab8500 *ab8500;
1275 struct resource *resource;
Rabin Vincent62579262010-05-19 11:39:02 +02001276 int ret;
1277 int i;
Mattias Wallin47c16972010-09-10 17:47:56 +02001278 u8 value;
Rabin Vincent62579262010-05-19 11:39:02 +02001279
Lee Jones8c4203c2012-11-05 16:10:35 +01001280 ab8500 = devm_kzalloc(&pdev->dev, sizeof *ab8500, GFP_KERNEL);
Lee Jonesd28f1db2012-05-19 17:21:37 +02001281 if (!ab8500)
1282 return -ENOMEM;
1283
Rabin Vincent62579262010-05-19 11:39:02 +02001284 if (plat)
1285 ab8500->irq_base = plat->irq_base;
1286
Lee Jonesd28f1db2012-05-19 17:21:37 +02001287 ab8500->dev = &pdev->dev;
1288
1289 resource = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
Lee Jones8c4203c2012-11-05 16:10:35 +01001290 if (!resource)
1291 return -ENODEV;
Lee Jonesd28f1db2012-05-19 17:21:37 +02001292
1293 ab8500->irq = resource->start;
1294
Lee Jones822672a2012-06-20 13:56:38 +01001295 ab8500->read = ab8500_prcmu_read;
1296 ab8500->write = ab8500_prcmu_write;
1297 ab8500->write_masked = ab8500_prcmu_write_masked;
Lee Jonesd28f1db2012-05-19 17:21:37 +02001298
Rabin Vincent62579262010-05-19 11:39:02 +02001299 mutex_init(&ab8500->lock);
1300 mutex_init(&ab8500->irq_lock);
Jonas Aaberg112a80d2012-04-17 09:30:33 +02001301 atomic_set(&ab8500->transfer_ongoing, 0);
Rabin Vincent62579262010-05-19 11:39:02 +02001302
Lee Jonesd28f1db2012-05-19 17:21:37 +02001303 platform_set_drvdata(pdev, ab8500);
1304
Lee Jones6bc4a562012-05-17 14:45:13 +01001305 if (platid)
1306 version = platid->driver_data;
Lee Jones6bc4a562012-05-17 14:45:13 +01001307
Linus Walleij0f6208372012-02-20 21:42:10 +01001308 if (version != AB8500_VERSION_UNDEFINED)
1309 ab8500->version = version;
1310 else {
1311 ret = get_register_interruptible(ab8500, AB8500_MISC,
1312 AB8500_IC_NAME_REG, &value);
1313 if (ret < 0)
Lee Jones8c4203c2012-11-05 16:10:35 +01001314 return ret;
Linus Walleij0f6208372012-02-20 21:42:10 +01001315
1316 ab8500->version = value;
1317 }
1318
Mattias Wallin47c16972010-09-10 17:47:56 +02001319 ret = get_register_interruptible(ab8500, AB8500_MISC,
1320 AB8500_REV_REG, &value);
Rabin Vincent62579262010-05-19 11:39:02 +02001321 if (ret < 0)
Lee Jones8c4203c2012-11-05 16:10:35 +01001322 return ret;
Rabin Vincent62579262010-05-19 11:39:02 +02001323
Mattias Wallin47c16972010-09-10 17:47:56 +02001324 ab8500->chip_id = value;
Rabin Vincent62579262010-05-19 11:39:02 +02001325
Linus Walleij0f6208372012-02-20 21:42:10 +01001326 dev_info(ab8500->dev, "detected chip, %s rev. %1x.%1x\n",
1327 ab8500_version_str[ab8500->version],
1328 ab8500->chip_id >> 4,
1329 ab8500->chip_id & 0x0F);
1330
Linus Walleijd6255522012-02-20 21:42:24 +01001331 /* Configure AB8500 or AB9540 IRQ */
Bengt Jonssona9823622012-03-08 14:01:57 +01001332 if (is_ab9540(ab8500) || is_ab8505(ab8500)) {
Linus Walleijd6255522012-02-20 21:42:24 +01001333 ab8500->mask_size = AB9540_NUM_IRQ_REGS;
1334 ab8500->irq_reg_offset = ab9540_irq_regoffset;
1335 } else {
1336 ab8500->mask_size = AB8500_NUM_IRQ_REGS;
1337 ab8500->irq_reg_offset = ab8500_irq_regoffset;
1338 }
Lee Jones8c4203c2012-11-05 16:10:35 +01001339 ab8500->mask = devm_kzalloc(&pdev->dev, ab8500->mask_size, GFP_KERNEL);
Linus Walleij2ced4452012-02-20 21:42:17 +01001340 if (!ab8500->mask)
1341 return -ENOMEM;
Lee Jones8c4203c2012-11-05 16:10:35 +01001342 ab8500->oldmask = devm_kzalloc(&pdev->dev, ab8500->mask_size, GFP_KERNEL);
1343 if (!ab8500->oldmask)
1344 return -ENOMEM;
1345
Mattias Walline5c238c2011-03-02 11:52:36 +01001346 /*
1347 * ab8500 has switched off due to (SWITCH_OFF_STATUS):
1348 * 0x01 Swoff bit programming
1349 * 0x02 Thermal protection activation
1350 * 0x04 Vbat lower then BattOk falling threshold
1351 * 0x08 Watchdog expired
1352 * 0x10 Non presence of 32kHz clock
1353 * 0x20 Battery level lower than power on reset threshold
1354 * 0x40 Power on key 1 pressed longer than 10 seconds
1355 * 0x80 DB8500 thermal shutdown
1356 */
1357
1358 ret = get_register_interruptible(ab8500, AB8500_RTC,
1359 AB8500_SWITCH_OFF_STATUS, &value);
1360 if (ret < 0)
1361 return ret;
Jonas Aabergb04c530c2012-06-29 17:46:12 +02001362 dev_info(ab8500->dev, "switch off cause(s) (%#x): ", value);
1363
1364 if (value) {
1365 for (i = 0; i < ARRAY_SIZE(switch_off_status); i++) {
1366 if (value & 1)
1367 printk(KERN_CONT " \"%s\"",
1368 switch_off_status[i]);
1369 value = value >> 1;
1370
1371 }
1372 printk(KERN_CONT "\n");
1373 } else {
1374 printk(KERN_CONT " None\n");
1375 }
Mattias Walline5c238c2011-03-02 11:52:36 +01001376
Rabin Vincent62579262010-05-19 11:39:02 +02001377 if (plat && plat->init)
1378 plat->init(ab8500);
1379
1380 /* Clear and mask all interrupts */
Linus Walleij2ced4452012-02-20 21:42:17 +01001381 for (i = 0; i < ab8500->mask_size; i++) {
Linus Walleij0f6208372012-02-20 21:42:10 +01001382 /*
1383 * Interrupt register 12 doesn't exist prior to AB8500 version
1384 * 2.0
1385 */
1386 if (ab8500->irq_reg_offset[i] == 11 &&
1387 is_ab8500_1p1_or_earlier(ab8500))
Mattias Wallin92d50a42010-12-07 11:20:47 +01001388 continue;
Rabin Vincent62579262010-05-19 11:39:02 +02001389
Mattias Wallin47c16972010-09-10 17:47:56 +02001390 get_register_interruptible(ab8500, AB8500_INTERRUPT,
Linus Walleij2ced4452012-02-20 21:42:17 +01001391 AB8500_IT_LATCH1_REG + ab8500->irq_reg_offset[i],
Mattias Wallin92d50a42010-12-07 11:20:47 +01001392 &value);
Mattias Wallin47c16972010-09-10 17:47:56 +02001393 set_register_interruptible(ab8500, AB8500_INTERRUPT,
Linus Walleij2ced4452012-02-20 21:42:17 +01001394 AB8500_IT_MASK1_REG + ab8500->irq_reg_offset[i], 0xff);
Rabin Vincent62579262010-05-19 11:39:02 +02001395 }
1396
Mattias Wallin47c16972010-09-10 17:47:56 +02001397 ret = abx500_register_ops(ab8500->dev, &ab8500_ops);
1398 if (ret)
Lee Jones8c4203c2012-11-05 16:10:35 +01001399 return ret;
Mattias Wallin47c16972010-09-10 17:47:56 +02001400
Linus Walleij2ced4452012-02-20 21:42:17 +01001401 for (i = 0; i < ab8500->mask_size; i++)
Rabin Vincent62579262010-05-19 11:39:02 +02001402 ab8500->mask[i] = ab8500->oldmask[i] = 0xff;
1403
Lee Jones06e589e2012-06-20 13:56:37 +01001404 ret = ab8500_irq_init(ab8500, np);
1405 if (ret)
Lee Jones8c4203c2012-11-05 16:10:35 +01001406 return ret;
Rabin Vincent62579262010-05-19 11:39:02 +02001407
Lee Jones06e589e2012-06-20 13:56:37 +01001408 /* Activate this feature only in ab9540 */
1409 /* till tests are done on ab8500 1p2 or later*/
1410 if (is_ab9540(ab8500)) {
Lee Jones8c4203c2012-11-05 16:10:35 +01001411 ret = devm_request_threaded_irq(&pdev->dev, ab8500->irq, NULL,
1412 ab8500_hierarchical_irq,
1413 IRQF_ONESHOT | IRQF_NO_SUSPEND,
1414 "ab8500", ab8500);
Lee Jones06e589e2012-06-20 13:56:37 +01001415 }
1416 else {
Lee Jones8c4203c2012-11-05 16:10:35 +01001417 ret = devm_request_threaded_irq(&pdev->dev, ab8500->irq, NULL,
1418 ab8500_irq,
1419 IRQF_ONESHOT | IRQF_NO_SUSPEND,
1420 "ab8500", ab8500);
Rabin Vincent62579262010-05-19 11:39:02 +02001421 if (ret)
Lee Jones8c4203c2012-11-05 16:10:35 +01001422 return ret;
Rabin Vincent62579262010-05-19 11:39:02 +02001423 }
1424
Lee Jonesbad76992012-07-02 17:10:56 +02001425 ret = mfd_add_devices(ab8500->dev, 0, abx500_common_devs,
1426 ARRAY_SIZE(abx500_common_devs), NULL,
Mark Brown55692af2012-09-11 15:16:36 +08001427 ab8500->irq_base, ab8500->domain);
Lee Jonesbad76992012-07-02 17:10:56 +02001428 if (ret)
Lee Jones8c4203c2012-11-05 16:10:35 +01001429 return ret;
Lee Jonesbad76992012-07-02 17:10:56 +02001430
1431 if (is_ab9540(ab8500))
1432 ret = mfd_add_devices(ab8500->dev, 0, ab9540_devs,
1433 ARRAY_SIZE(ab9540_devs), NULL,
Mark Brown55692af2012-09-11 15:16:36 +08001434 ab8500->irq_base, ab8500->domain);
Lee Jonesbad76992012-07-02 17:10:56 +02001435 else
1436 ret = mfd_add_devices(ab8500->dev, 0, ab8500_devs,
1437 ARRAY_SIZE(ab8500_devs), NULL,
Mark Brown55692af2012-09-11 15:16:36 +08001438 ab8500->irq_base, ab8500->domain);
Lee Jonesbad76992012-07-02 17:10:56 +02001439 if (ret)
Lee Jones8c4203c2012-11-05 16:10:35 +01001440 return ret;
Linus Walleijd6255522012-02-20 21:42:24 +01001441
Lee Jonesbad76992012-07-02 17:10:56 +02001442 if (is_ab9540(ab8500) || is_ab8505(ab8500))
1443 ret = mfd_add_devices(ab8500->dev, 0, ab9540_ab8505_devs,
1444 ARRAY_SIZE(ab9540_ab8505_devs), NULL,
Mark Brown55692af2012-09-11 15:16:36 +08001445 ab8500->irq_base, ab8500->domain);
Lee Jonesbad76992012-07-02 17:10:56 +02001446 if (ret)
Lee Jones8c4203c2012-11-05 16:10:35 +01001447 return ret;
Rabin Vincent62579262010-05-19 11:39:02 +02001448
Rickard Andersson6ef94182012-04-17 09:30:57 +02001449 if (!no_bm) {
1450 /* Add battery management devices */
1451 ret = mfd_add_devices(ab8500->dev, 0, ab8500_bm_devs,
1452 ARRAY_SIZE(ab8500_bm_devs), NULL,
Mark Brown55692af2012-09-11 15:16:36 +08001453 ab8500->irq_base, ab8500->domain);
Rickard Andersson6ef94182012-04-17 09:30:57 +02001454 if (ret)
1455 dev_err(ab8500->dev, "error adding bm devices\n");
1456 }
1457
Linus Walleijd6255522012-02-20 21:42:24 +01001458 if (is_ab9540(ab8500))
1459 ret = sysfs_create_group(&ab8500->dev->kobj,
1460 &ab9540_attr_group);
1461 else
1462 ret = sysfs_create_group(&ab8500->dev->kobj,
1463 &ab8500_attr_group);
Mattias Wallincca69b62010-12-02 15:09:36 +01001464 if (ret)
1465 dev_err(ab8500->dev, "error creating sysfs entries\n");
Lee Jones06e589e2012-06-20 13:56:37 +01001466
1467 return ret;
Rabin Vincent62579262010-05-19 11:39:02 +02001468}
1469
Bill Pemberton4740f732012-11-19 13:26:01 -05001470static int ab8500_remove(struct platform_device *pdev)
Rabin Vincent62579262010-05-19 11:39:02 +02001471{
Lee Jonesd28f1db2012-05-19 17:21:37 +02001472 struct ab8500 *ab8500 = platform_get_drvdata(pdev);
1473
Linus Walleijd6255522012-02-20 21:42:24 +01001474 if (is_ab9540(ab8500))
1475 sysfs_remove_group(&ab8500->dev->kobj, &ab9540_attr_group);
1476 else
1477 sysfs_remove_group(&ab8500->dev->kobj, &ab8500_attr_group);
Lee Jones06e589e2012-06-20 13:56:37 +01001478
Rabin Vincent62579262010-05-19 11:39:02 +02001479 mfd_remove_devices(ab8500->dev);
Rabin Vincent62579262010-05-19 11:39:02 +02001480
1481 return 0;
1482}
1483
Lee Jonesd28f1db2012-05-19 17:21:37 +02001484static const struct platform_device_id ab8500_id[] = {
1485 { "ab8500-core", AB8500_VERSION_AB8500 },
1486 { "ab8505-i2c", AB8500_VERSION_AB8505 },
1487 { "ab9540-i2c", AB8500_VERSION_AB9540 },
1488 { "ab8540-i2c", AB8500_VERSION_AB8540 },
1489 { }
1490};
1491
1492static struct platform_driver ab8500_core_driver = {
1493 .driver = {
1494 .name = "ab8500-core",
1495 .owner = THIS_MODULE,
1496 },
1497 .probe = ab8500_probe,
Bill Pemberton84449212012-11-19 13:20:24 -05001498 .remove = ab8500_remove,
Lee Jonesd28f1db2012-05-19 17:21:37 +02001499 .id_table = ab8500_id,
1500};
1501
1502static int __init ab8500_core_init(void)
1503{
1504 return platform_driver_register(&ab8500_core_driver);
1505}
1506
1507static void __exit ab8500_core_exit(void)
1508{
1509 platform_driver_unregister(&ab8500_core_driver);
1510}
Lee Jonesba7cbc32012-06-11 16:25:00 +01001511core_initcall(ab8500_core_init);
Lee Jonesd28f1db2012-05-19 17:21:37 +02001512module_exit(ab8500_core_exit);
1513
Mattias Wallinadceed62011-03-02 11:51:11 +01001514MODULE_AUTHOR("Mattias Wallin, Srinidhi Kasagar, Rabin Vincent");
Rabin Vincent62579262010-05-19 11:39:02 +02001515MODULE_DESCRIPTION("AB8500 MFD core");
1516MODULE_LICENSE("GPL v2");