blob: 08850f0d1523af10f6194eb95c1b06e7e7ab1bbf [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>
14#include <linux/delay.h>
15#include <linux/interrupt.h>
16#include <linux/module.h>
17#include <linux/platform_device.h>
18#include <linux/mfd/core.h>
Mattias Wallin47c16972010-09-10 17:47:56 +020019#include <linux/mfd/abx500.h>
Linus Walleijee66e652011-12-02 14:16:33 +010020#include <linux/mfd/abx500/ab8500.h>
Sundar R Iyer549931f2010-07-13 11:51:28 +053021#include <linux/regulator/ab8500.h>
Rabin Vincent62579262010-05-19 11:39:02 +020022
23/*
24 * Interrupt register offsets
25 * Bank : 0x0E
26 */
Mattias Wallin47c16972010-09-10 17:47:56 +020027#define AB8500_IT_SOURCE1_REG 0x00
28#define AB8500_IT_SOURCE2_REG 0x01
29#define AB8500_IT_SOURCE3_REG 0x02
30#define AB8500_IT_SOURCE4_REG 0x03
31#define AB8500_IT_SOURCE5_REG 0x04
32#define AB8500_IT_SOURCE6_REG 0x05
33#define AB8500_IT_SOURCE7_REG 0x06
34#define AB8500_IT_SOURCE8_REG 0x07
Linus Walleijd6255522012-02-20 21:42:24 +010035#define AB9540_IT_SOURCE13_REG 0x0C
Mattias Wallin47c16972010-09-10 17:47:56 +020036#define AB8500_IT_SOURCE19_REG 0x12
37#define AB8500_IT_SOURCE20_REG 0x13
38#define AB8500_IT_SOURCE21_REG 0x14
39#define AB8500_IT_SOURCE22_REG 0x15
40#define AB8500_IT_SOURCE23_REG 0x16
41#define AB8500_IT_SOURCE24_REG 0x17
Rabin Vincent62579262010-05-19 11:39:02 +020042
43/*
44 * latch registers
45 */
Mattias Wallin47c16972010-09-10 17:47:56 +020046#define AB8500_IT_LATCH1_REG 0x20
47#define AB8500_IT_LATCH2_REG 0x21
48#define AB8500_IT_LATCH3_REG 0x22
49#define AB8500_IT_LATCH4_REG 0x23
50#define AB8500_IT_LATCH5_REG 0x24
51#define AB8500_IT_LATCH6_REG 0x25
52#define AB8500_IT_LATCH7_REG 0x26
53#define AB8500_IT_LATCH8_REG 0x27
54#define AB8500_IT_LATCH9_REG 0x28
55#define AB8500_IT_LATCH10_REG 0x29
Mattias Wallin92d50a42010-12-07 11:20:47 +010056#define AB8500_IT_LATCH12_REG 0x2B
Linus Walleijd6255522012-02-20 21:42:24 +010057#define AB9540_IT_LATCH13_REG 0x2C
Mattias Wallin47c16972010-09-10 17:47:56 +020058#define AB8500_IT_LATCH19_REG 0x32
59#define AB8500_IT_LATCH20_REG 0x33
60#define AB8500_IT_LATCH21_REG 0x34
61#define AB8500_IT_LATCH22_REG 0x35
62#define AB8500_IT_LATCH23_REG 0x36
63#define AB8500_IT_LATCH24_REG 0x37
Rabin Vincent62579262010-05-19 11:39:02 +020064
65/*
66 * mask registers
67 */
68
Mattias Wallin47c16972010-09-10 17:47:56 +020069#define AB8500_IT_MASK1_REG 0x40
70#define AB8500_IT_MASK2_REG 0x41
71#define AB8500_IT_MASK3_REG 0x42
72#define AB8500_IT_MASK4_REG 0x43
73#define AB8500_IT_MASK5_REG 0x44
74#define AB8500_IT_MASK6_REG 0x45
75#define AB8500_IT_MASK7_REG 0x46
76#define AB8500_IT_MASK8_REG 0x47
77#define AB8500_IT_MASK9_REG 0x48
78#define AB8500_IT_MASK10_REG 0x49
79#define AB8500_IT_MASK11_REG 0x4A
80#define AB8500_IT_MASK12_REG 0x4B
81#define AB8500_IT_MASK13_REG 0x4C
82#define AB8500_IT_MASK14_REG 0x4D
83#define AB8500_IT_MASK15_REG 0x4E
84#define AB8500_IT_MASK16_REG 0x4F
85#define AB8500_IT_MASK17_REG 0x50
86#define AB8500_IT_MASK18_REG 0x51
87#define AB8500_IT_MASK19_REG 0x52
88#define AB8500_IT_MASK20_REG 0x53
89#define AB8500_IT_MASK21_REG 0x54
90#define AB8500_IT_MASK22_REG 0x55
91#define AB8500_IT_MASK23_REG 0x56
92#define AB8500_IT_MASK24_REG 0x57
Rabin Vincent62579262010-05-19 11:39:02 +020093
Mattias Wallin47c16972010-09-10 17:47:56 +020094#define AB8500_REV_REG 0x80
Linus Walleij0f6208372012-02-20 21:42:10 +010095#define AB8500_IC_NAME_REG 0x82
Mattias Walline5c238c2011-03-02 11:52:36 +010096#define AB8500_SWITCH_OFF_STATUS 0x00
Rabin Vincent62579262010-05-19 11:39:02 +020097
Andrew Lynnb4a31032011-10-11 10:49:47 +020098#define AB8500_TURN_ON_STATUS 0x00
99
Rickard Andersson6ef94182012-04-17 09:30:57 +0200100static bool no_bm; /* No battery management */
101module_param(no_bm, bool, S_IRUGO);
102
Linus Walleijd6255522012-02-20 21:42:24 +0100103#define AB9540_MODEM_CTRL2_REG 0x23
104#define AB9540_MODEM_CTRL2_SWDBBRSTN_BIT BIT(2)
105
Rabin Vincent62579262010-05-19 11:39:02 +0200106/*
107 * Map interrupt numbers to the LATCH and MASK register offsets, Interrupt
Linus Walleij2ced4452012-02-20 21:42:17 +0100108 * numbers are indexed into this array with (num / 8). The interupts are
109 * defined in linux/mfd/ab8500.h
Rabin Vincent62579262010-05-19 11:39:02 +0200110 *
111 * This is one off from the register names, i.e. AB8500_IT_MASK1_REG is at
112 * offset 0.
113 */
Linus Walleij2ced4452012-02-20 21:42:17 +0100114/* AB8500 support */
Rabin Vincent62579262010-05-19 11:39:02 +0200115static const int ab8500_irq_regoffset[AB8500_NUM_IRQ_REGS] = {
Mattias Wallin92d50a42010-12-07 11:20:47 +0100116 0, 1, 2, 3, 4, 6, 7, 8, 9, 11, 18, 19, 20, 21,
Rabin Vincent62579262010-05-19 11:39:02 +0200117};
118
Linus Walleijd6255522012-02-20 21:42:24 +0100119/* AB9540 support */
120static const int ab9540_irq_regoffset[AB9540_NUM_IRQ_REGS] = {
121 0, 1, 2, 3, 4, 6, 7, 8, 9, 11, 18, 19, 20, 21, 12, 13, 24,
122};
123
Linus Walleij0f6208372012-02-20 21:42:10 +0100124static const char ab8500_version_str[][7] = {
125 [AB8500_VERSION_AB8500] = "AB8500",
126 [AB8500_VERSION_AB8505] = "AB8505",
127 [AB8500_VERSION_AB9540] = "AB9540",
128 [AB8500_VERSION_AB8540] = "AB8540",
129};
130
Mattias Wallin47c16972010-09-10 17:47:56 +0200131static int ab8500_get_chip_id(struct device *dev)
132{
Mattias Wallin6bce7bf2010-12-02 15:08:32 +0100133 struct ab8500 *ab8500;
134
135 if (!dev)
136 return -EINVAL;
137 ab8500 = dev_get_drvdata(dev->parent);
138 return ab8500 ? (int)ab8500->chip_id : -EINVAL;
Mattias Wallin47c16972010-09-10 17:47:56 +0200139}
140
141static int set_register_interruptible(struct ab8500 *ab8500, u8 bank,
142 u8 reg, u8 data)
Rabin Vincent62579262010-05-19 11:39:02 +0200143{
144 int ret;
Mattias Wallin47c16972010-09-10 17:47:56 +0200145 /*
146 * Put the u8 bank and u8 register together into a an u16.
147 * The bank on higher 8 bits and register in lower 8 bits.
148 * */
149 u16 addr = ((u16)bank) << 8 | reg;
Rabin Vincent62579262010-05-19 11:39:02 +0200150
151 dev_vdbg(ab8500->dev, "wr: addr %#x <= %#x\n", addr, data);
152
Rabin Vincent392cbd12012-03-08 14:01:46 +0100153 mutex_lock(&ab8500->lock);
Mattias Wallin47c16972010-09-10 17:47:56 +0200154
155 ret = ab8500->write(ab8500, addr, data);
156 if (ret < 0)
157 dev_err(ab8500->dev, "failed to write reg %#x: %d\n",
158 addr, ret);
159 mutex_unlock(&ab8500->lock);
160
161 return ret;
162}
163
164static int ab8500_set_register(struct device *dev, u8 bank,
165 u8 reg, u8 value)
166{
Jonas Aaberg112a80d2012-04-17 09:30:33 +0200167 int ret;
Mattias Wallin47c16972010-09-10 17:47:56 +0200168 struct ab8500 *ab8500 = dev_get_drvdata(dev->parent);
169
Jonas Aaberg112a80d2012-04-17 09:30:33 +0200170 atomic_inc(&ab8500->transfer_ongoing);
171 ret = set_register_interruptible(ab8500, bank, reg, value);
172 atomic_dec(&ab8500->transfer_ongoing);
173 return ret;
Mattias Wallin47c16972010-09-10 17:47:56 +0200174}
175
176static int get_register_interruptible(struct ab8500 *ab8500, u8 bank,
177 u8 reg, u8 *value)
178{
179 int ret;
180 /* put the u8 bank and u8 reg together into a an u16.
181 * bank on higher 8 bits and reg in lower */
182 u16 addr = ((u16)bank) << 8 | reg;
183
Rabin Vincent392cbd12012-03-08 14:01:46 +0100184 mutex_lock(&ab8500->lock);
Mattias Wallin47c16972010-09-10 17:47:56 +0200185
186 ret = ab8500->read(ab8500, addr);
187 if (ret < 0)
188 dev_err(ab8500->dev, "failed to read reg %#x: %d\n",
189 addr, ret);
190 else
191 *value = ret;
192
193 mutex_unlock(&ab8500->lock);
194 dev_vdbg(ab8500->dev, "rd: addr %#x => data %#x\n", addr, ret);
195
196 return ret;
197}
198
199static int ab8500_get_register(struct device *dev, u8 bank,
200 u8 reg, u8 *value)
201{
Jonas Aaberg112a80d2012-04-17 09:30:33 +0200202 int ret;
Mattias Wallin47c16972010-09-10 17:47:56 +0200203 struct ab8500 *ab8500 = dev_get_drvdata(dev->parent);
204
Jonas Aaberg112a80d2012-04-17 09:30:33 +0200205 atomic_inc(&ab8500->transfer_ongoing);
206 ret = get_register_interruptible(ab8500, bank, reg, value);
207 atomic_dec(&ab8500->transfer_ongoing);
208 return ret;
Mattias Wallin47c16972010-09-10 17:47:56 +0200209}
210
211static int mask_and_set_register_interruptible(struct ab8500 *ab8500, u8 bank,
212 u8 reg, u8 bitmask, u8 bitvalues)
213{
214 int ret;
Mattias Wallin47c16972010-09-10 17:47:56 +0200215 /* put the u8 bank and u8 reg together into a an u16.
216 * bank on higher 8 bits and reg in lower */
217 u16 addr = ((u16)bank) << 8 | reg;
218
Rabin Vincent392cbd12012-03-08 14:01:46 +0100219 mutex_lock(&ab8500->lock);
Mattias Wallin47c16972010-09-10 17:47:56 +0200220
Mattias Nilssonbc628fd2012-03-08 14:02:20 +0100221 if (ab8500->write_masked == NULL) {
222 u8 data;
223
224 ret = ab8500->read(ab8500, addr);
225 if (ret < 0) {
226 dev_err(ab8500->dev, "failed to read reg %#x: %d\n",
227 addr, ret);
228 goto out;
229 }
230
231 data = (u8)ret;
232 data = (~bitmask & data) | (bitmask & bitvalues);
233
234 ret = ab8500->write(ab8500, addr, data);
235 if (ret < 0)
236 dev_err(ab8500->dev, "failed to write reg %#x: %d\n",
237 addr, ret);
238
239 dev_vdbg(ab8500->dev, "mask: addr %#x => data %#x\n", addr,
240 data);
Mattias Wallin47c16972010-09-10 17:47:56 +0200241 goto out;
242 }
Mattias Nilssonbc628fd2012-03-08 14:02:20 +0100243 ret = ab8500->write_masked(ab8500, addr, bitmask, bitvalues);
Rabin Vincent62579262010-05-19 11:39:02 +0200244 if (ret < 0)
Mattias Nilssonbc628fd2012-03-08 14:02:20 +0100245 dev_err(ab8500->dev, "failed to modify reg %#x: %d\n", addr,
246 ret);
Rabin Vincent62579262010-05-19 11:39:02 +0200247out:
248 mutex_unlock(&ab8500->lock);
249 return ret;
250}
Mattias Wallin47c16972010-09-10 17:47:56 +0200251
252static int ab8500_mask_and_set_register(struct device *dev,
253 u8 bank, u8 reg, u8 bitmask, u8 bitvalues)
254{
Jonas Aaberg112a80d2012-04-17 09:30:33 +0200255 int ret;
Mattias Wallin47c16972010-09-10 17:47:56 +0200256 struct ab8500 *ab8500 = dev_get_drvdata(dev->parent);
257
Jonas Aaberg112a80d2012-04-17 09:30:33 +0200258 atomic_inc(&ab8500->transfer_ongoing);
259 ret= mask_and_set_register_interruptible(ab8500, bank, reg,
260 bitmask, bitvalues);
261 atomic_dec(&ab8500->transfer_ongoing);
262 return ret;
Mattias Wallin47c16972010-09-10 17:47:56 +0200263}
264
265static struct abx500_ops ab8500_ops = {
266 .get_chip_id = ab8500_get_chip_id,
267 .get_register = ab8500_get_register,
268 .set_register = ab8500_set_register,
269 .get_register_page = NULL,
270 .set_register_page = NULL,
271 .mask_and_set_register = ab8500_mask_and_set_register,
272 .event_registers_startup_state_get = NULL,
273 .startup_irq_enabled = NULL,
274};
Rabin Vincent62579262010-05-19 11:39:02 +0200275
Mark Brown9505a0a2010-12-11 13:16:08 +0000276static void ab8500_irq_lock(struct irq_data *data)
Rabin Vincent62579262010-05-19 11:39:02 +0200277{
Mark Brown9505a0a2010-12-11 13:16:08 +0000278 struct ab8500 *ab8500 = irq_data_get_irq_chip_data(data);
Rabin Vincent62579262010-05-19 11:39:02 +0200279
280 mutex_lock(&ab8500->irq_lock);
Jonas Aaberg112a80d2012-04-17 09:30:33 +0200281 atomic_inc(&ab8500->transfer_ongoing);
Rabin Vincent62579262010-05-19 11:39:02 +0200282}
283
Mark Brown9505a0a2010-12-11 13:16:08 +0000284static void ab8500_irq_sync_unlock(struct irq_data *data)
Rabin Vincent62579262010-05-19 11:39:02 +0200285{
Mark Brown9505a0a2010-12-11 13:16:08 +0000286 struct ab8500 *ab8500 = irq_data_get_irq_chip_data(data);
Rabin Vincent62579262010-05-19 11:39:02 +0200287 int i;
288
Linus Walleij2ced4452012-02-20 21:42:17 +0100289 for (i = 0; i < ab8500->mask_size; i++) {
Rabin Vincent62579262010-05-19 11:39:02 +0200290 u8 old = ab8500->oldmask[i];
291 u8 new = ab8500->mask[i];
292 int reg;
293
294 if (new == old)
295 continue;
296
Linus Walleij0f6208372012-02-20 21:42:10 +0100297 /*
298 * Interrupt register 12 doesn't exist prior to AB8500 version
299 * 2.0
300 */
301 if (ab8500->irq_reg_offset[i] == 11 &&
302 is_ab8500_1p1_or_earlier(ab8500))
Mattias Wallin92d50a42010-12-07 11:20:47 +0100303 continue;
304
Rabin Vincent62579262010-05-19 11:39:02 +0200305 ab8500->oldmask[i] = new;
306
Linus Walleij2ced4452012-02-20 21:42:17 +0100307 reg = AB8500_IT_MASK1_REG + ab8500->irq_reg_offset[i];
Mattias Wallin47c16972010-09-10 17:47:56 +0200308 set_register_interruptible(ab8500, AB8500_INTERRUPT, reg, new);
Rabin Vincent62579262010-05-19 11:39:02 +0200309 }
Jonas Aaberg112a80d2012-04-17 09:30:33 +0200310 atomic_dec(&ab8500->transfer_ongoing);
Rabin Vincent62579262010-05-19 11:39:02 +0200311 mutex_unlock(&ab8500->irq_lock);
312}
313
Mark Brown9505a0a2010-12-11 13:16:08 +0000314static void ab8500_irq_mask(struct irq_data *data)
Rabin Vincent62579262010-05-19 11:39:02 +0200315{
Mark Brown9505a0a2010-12-11 13:16:08 +0000316 struct ab8500 *ab8500 = irq_data_get_irq_chip_data(data);
317 int offset = data->irq - ab8500->irq_base;
Rabin Vincent62579262010-05-19 11:39:02 +0200318 int index = offset / 8;
319 int mask = 1 << (offset % 8);
320
321 ab8500->mask[index] |= mask;
322}
323
Mark Brown9505a0a2010-12-11 13:16:08 +0000324static void ab8500_irq_unmask(struct irq_data *data)
Rabin Vincent62579262010-05-19 11:39:02 +0200325{
Mark Brown9505a0a2010-12-11 13:16:08 +0000326 struct ab8500 *ab8500 = irq_data_get_irq_chip_data(data);
327 int offset = data->irq - ab8500->irq_base;
Rabin Vincent62579262010-05-19 11:39:02 +0200328 int index = offset / 8;
329 int mask = 1 << (offset % 8);
330
331 ab8500->mask[index] &= ~mask;
332}
333
334static struct irq_chip ab8500_irq_chip = {
335 .name = "ab8500",
Mark Brown9505a0a2010-12-11 13:16:08 +0000336 .irq_bus_lock = ab8500_irq_lock,
337 .irq_bus_sync_unlock = ab8500_irq_sync_unlock,
338 .irq_mask = ab8500_irq_mask,
Virupax Sadashivpetimathe6f93062011-10-11 10:49:17 +0200339 .irq_disable = ab8500_irq_mask,
Mark Brown9505a0a2010-12-11 13:16:08 +0000340 .irq_unmask = ab8500_irq_unmask,
Rabin Vincent62579262010-05-19 11:39:02 +0200341};
342
343static irqreturn_t ab8500_irq(int irq, void *dev)
344{
345 struct ab8500 *ab8500 = dev;
346 int i;
347
348 dev_vdbg(ab8500->dev, "interrupt\n");
349
Jonas Aaberg112a80d2012-04-17 09:30:33 +0200350 atomic_inc(&ab8500->transfer_ongoing);
351
Linus Walleij2ced4452012-02-20 21:42:17 +0100352 for (i = 0; i < ab8500->mask_size; i++) {
353 int regoffset = ab8500->irq_reg_offset[i];
Rabin Vincent62579262010-05-19 11:39:02 +0200354 int status;
Mattias Wallin47c16972010-09-10 17:47:56 +0200355 u8 value;
Rabin Vincent62579262010-05-19 11:39:02 +0200356
Linus Walleij0f6208372012-02-20 21:42:10 +0100357 /*
358 * Interrupt register 12 doesn't exist prior to AB8500 version
359 * 2.0
360 */
361 if (regoffset == 11 && is_ab8500_1p1_or_earlier(ab8500))
Mattias Wallin92d50a42010-12-07 11:20:47 +0100362 continue;
363
Mattias Wallin47c16972010-09-10 17:47:56 +0200364 status = get_register_interruptible(ab8500, AB8500_INTERRUPT,
365 AB8500_IT_LATCH1_REG + regoffset, &value);
366 if (status < 0 || value == 0)
Rabin Vincent62579262010-05-19 11:39:02 +0200367 continue;
368
369 do {
Mattias Wallin88aec4f2010-12-02 15:06:49 +0100370 int bit = __ffs(value);
Rabin Vincent62579262010-05-19 11:39:02 +0200371 int line = i * 8 + bit;
372
373 handle_nested_irq(ab8500->irq_base + line);
Mattias Wallin47c16972010-09-10 17:47:56 +0200374 value &= ~(1 << bit);
Jonas Aaberg112a80d2012-04-17 09:30:33 +0200375
Mattias Wallin47c16972010-09-10 17:47:56 +0200376 } while (value);
Rabin Vincent62579262010-05-19 11:39:02 +0200377 }
Jonas Aaberg112a80d2012-04-17 09:30:33 +0200378 atomic_dec(&ab8500->transfer_ongoing);
Rabin Vincent62579262010-05-19 11:39:02 +0200379 return IRQ_HANDLED;
380}
381
382static int ab8500_irq_init(struct ab8500 *ab8500)
383{
384 int base = ab8500->irq_base;
385 int irq;
Linus Walleij2ced4452012-02-20 21:42:17 +0100386 int num_irqs;
Rabin Vincent62579262010-05-19 11:39:02 +0200387
Linus Walleijd6255522012-02-20 21:42:24 +0100388 if (is_ab9540(ab8500))
389 num_irqs = AB9540_NR_IRQS;
Bengt Jonssona9823622012-03-08 14:01:57 +0100390 else if (is_ab8505(ab8500))
391 num_irqs = AB8505_NR_IRQS;
Linus Walleijd6255522012-02-20 21:42:24 +0100392 else
393 num_irqs = AB8500_NR_IRQS;
Linus Walleij2ced4452012-02-20 21:42:17 +0100394
395 for (irq = base; irq < base + num_irqs; irq++) {
Thomas Gleixnerd5bb1222011-03-25 11:12:32 +0000396 irq_set_chip_data(irq, ab8500);
397 irq_set_chip_and_handler(irq, &ab8500_irq_chip,
Rabin Vincent62579262010-05-19 11:39:02 +0200398 handle_simple_irq);
Thomas Gleixnerd5bb1222011-03-25 11:12:32 +0000399 irq_set_nested_thread(irq, 1);
Rabin Vincent62579262010-05-19 11:39:02 +0200400#ifdef CONFIG_ARM
401 set_irq_flags(irq, IRQF_VALID);
402#else
Thomas Gleixnerd5bb1222011-03-25 11:12:32 +0000403 irq_set_noprobe(irq);
Rabin Vincent62579262010-05-19 11:39:02 +0200404#endif
405 }
406
407 return 0;
408}
409
410static void ab8500_irq_remove(struct ab8500 *ab8500)
411{
412 int base = ab8500->irq_base;
413 int irq;
Linus Walleij2ced4452012-02-20 21:42:17 +0100414 int num_irqs;
Rabin Vincent62579262010-05-19 11:39:02 +0200415
Linus Walleijd6255522012-02-20 21:42:24 +0100416 if (is_ab9540(ab8500))
417 num_irqs = AB9540_NR_IRQS;
Bengt Jonssona9823622012-03-08 14:01:57 +0100418 else if (is_ab8505(ab8500))
419 num_irqs = AB8505_NR_IRQS;
Linus Walleijd6255522012-02-20 21:42:24 +0100420 else
421 num_irqs = AB8500_NR_IRQS;
Linus Walleij2ced4452012-02-20 21:42:17 +0100422
423 for (irq = base; irq < base + num_irqs; irq++) {
Rabin Vincent62579262010-05-19 11:39:02 +0200424#ifdef CONFIG_ARM
425 set_irq_flags(irq, 0);
426#endif
Thomas Gleixnerd5bb1222011-03-25 11:12:32 +0000427 irq_set_chip_and_handler(irq, NULL, NULL);
428 irq_set_chip_data(irq, NULL);
Rabin Vincent62579262010-05-19 11:39:02 +0200429 }
430}
431
Jonas Aaberg112a80d2012-04-17 09:30:33 +0200432int ab8500_suspend(struct ab8500 *ab8500)
433{
434 if (atomic_read(&ab8500->transfer_ongoing))
435 return -EINVAL;
436 else
437 return 0;
438}
439
Linus Walleijd6255522012-02-20 21:42:24 +0100440/* AB8500 GPIO Resources */
Robert Rosengren5cef8df2011-06-09 23:57:33 +0200441static struct resource __devinitdata ab8500_gpio_resources[] = {
Bibek Basu0cb3fcd2011-02-09 11:02:35 +0530442 {
443 .name = "GPIO_INT6",
444 .start = AB8500_INT_GPIO6R,
445 .end = AB8500_INT_GPIO41F,
446 .flags = IORESOURCE_IRQ,
447 }
448};
449
Linus Walleijd6255522012-02-20 21:42:24 +0100450/* AB9540 GPIO Resources */
451static struct resource __devinitdata ab9540_gpio_resources[] = {
452 {
453 .name = "GPIO_INT6",
454 .start = AB8500_INT_GPIO6R,
455 .end = AB8500_INT_GPIO41F,
456 .flags = IORESOURCE_IRQ,
457 },
458 {
459 .name = "GPIO_INT14",
460 .start = AB9540_INT_GPIO50R,
461 .end = AB9540_INT_GPIO54R,
462 .flags = IORESOURCE_IRQ,
463 },
464 {
465 .name = "GPIO_INT15",
466 .start = AB9540_INT_GPIO50F,
467 .end = AB9540_INT_GPIO54F,
468 .flags = IORESOURCE_IRQ,
469 }
470};
471
Robert Rosengren5cef8df2011-06-09 23:57:33 +0200472static struct resource __devinitdata ab8500_gpadc_resources[] = {
Rabin Vincent62579262010-05-19 11:39:02 +0200473 {
474 .name = "HW_CONV_END",
475 .start = AB8500_INT_GP_HW_ADC_CONV_END,
476 .end = AB8500_INT_GP_HW_ADC_CONV_END,
477 .flags = IORESOURCE_IRQ,
478 },
479 {
480 .name = "SW_CONV_END",
481 .start = AB8500_INT_GP_SW_ADC_CONV_END,
482 .end = AB8500_INT_GP_SW_ADC_CONV_END,
483 .flags = IORESOURCE_IRQ,
484 },
485};
486
Robert Rosengren5cef8df2011-06-09 23:57:33 +0200487static struct resource __devinitdata ab8500_rtc_resources[] = {
Rabin Vincent62579262010-05-19 11:39:02 +0200488 {
489 .name = "60S",
490 .start = AB8500_INT_RTC_60S,
491 .end = AB8500_INT_RTC_60S,
492 .flags = IORESOURCE_IRQ,
493 },
494 {
495 .name = "ALARM",
496 .start = AB8500_INT_RTC_ALARM,
497 .end = AB8500_INT_RTC_ALARM,
498 .flags = IORESOURCE_IRQ,
499 },
500};
501
Robert Rosengren5cef8df2011-06-09 23:57:33 +0200502static struct resource __devinitdata ab8500_poweronkey_db_resources[] = {
Sundar R Iyer77686512010-09-05 12:18:47 -0700503 {
504 .name = "ONKEY_DBF",
505 .start = AB8500_INT_PON_KEY1DB_F,
506 .end = AB8500_INT_PON_KEY1DB_F,
507 .flags = IORESOURCE_IRQ,
508 },
509 {
510 .name = "ONKEY_DBR",
511 .start = AB8500_INT_PON_KEY1DB_R,
512 .end = AB8500_INT_PON_KEY1DB_R,
513 .flags = IORESOURCE_IRQ,
514 },
515};
516
Linus Walleij6af75ec2011-06-09 23:57:45 +0200517static struct resource __devinitdata ab8500_av_acc_detect_resources[] = {
Mattias Walline098aded72010-12-02 15:40:31 +0100518 {
Linus Walleij6af75ec2011-06-09 23:57:45 +0200519 .name = "ACC_DETECT_1DB_F",
520 .start = AB8500_INT_ACC_DETECT_1DB_F,
521 .end = AB8500_INT_ACC_DETECT_1DB_F,
522 .flags = IORESOURCE_IRQ,
Mattias Walline098aded72010-12-02 15:40:31 +0100523 },
524 {
Linus Walleij6af75ec2011-06-09 23:57:45 +0200525 .name = "ACC_DETECT_1DB_R",
526 .start = AB8500_INT_ACC_DETECT_1DB_R,
527 .end = AB8500_INT_ACC_DETECT_1DB_R,
528 .flags = IORESOURCE_IRQ,
Mattias Walline098aded72010-12-02 15:40:31 +0100529 },
530 {
Linus Walleij6af75ec2011-06-09 23:57:45 +0200531 .name = "ACC_DETECT_21DB_F",
532 .start = AB8500_INT_ACC_DETECT_21DB_F,
533 .end = AB8500_INT_ACC_DETECT_21DB_F,
534 .flags = IORESOURCE_IRQ,
535 },
536 {
537 .name = "ACC_DETECT_21DB_R",
538 .start = AB8500_INT_ACC_DETECT_21DB_R,
539 .end = AB8500_INT_ACC_DETECT_21DB_R,
540 .flags = IORESOURCE_IRQ,
541 },
542 {
543 .name = "ACC_DETECT_22DB_F",
544 .start = AB8500_INT_ACC_DETECT_22DB_F,
545 .end = AB8500_INT_ACC_DETECT_22DB_F,
546 .flags = IORESOURCE_IRQ,
547 },
548 {
549 .name = "ACC_DETECT_22DB_R",
550 .start = AB8500_INT_ACC_DETECT_22DB_R,
551 .end = AB8500_INT_ACC_DETECT_22DB_R,
552 .flags = IORESOURCE_IRQ,
553 },
554};
555
556static struct resource __devinitdata ab8500_charger_resources[] = {
557 {
Mattias Walline098aded72010-12-02 15:40:31 +0100558 .name = "MAIN_CH_UNPLUG_DET",
559 .start = AB8500_INT_MAIN_CH_UNPLUG_DET,
560 .end = AB8500_INT_MAIN_CH_UNPLUG_DET,
561 .flags = IORESOURCE_IRQ,
562 },
563 {
564 .name = "MAIN_CHARGE_PLUG_DET",
565 .start = AB8500_INT_MAIN_CH_PLUG_DET,
566 .end = AB8500_INT_MAIN_CH_PLUG_DET,
567 .flags = IORESOURCE_IRQ,
568 },
569 {
Mattias Walline098aded72010-12-02 15:40:31 +0100570 .name = "VBUS_DET_R",
571 .start = AB8500_INT_VBUS_DET_R,
572 .end = AB8500_INT_VBUS_DET_R,
573 .flags = IORESOURCE_IRQ,
574 },
575 {
Linus Walleij6af75ec2011-06-09 23:57:45 +0200576 .name = "VBUS_DET_F",
577 .start = AB8500_INT_VBUS_DET_F,
578 .end = AB8500_INT_VBUS_DET_F,
Mattias Walline098aded72010-12-02 15:40:31 +0100579 .flags = IORESOURCE_IRQ,
580 },
581 {
Linus Walleij6af75ec2011-06-09 23:57:45 +0200582 .name = "USB_LINK_STATUS",
583 .start = AB8500_INT_USB_LINK_STATUS,
584 .end = AB8500_INT_USB_LINK_STATUS,
585 .flags = IORESOURCE_IRQ,
586 },
587 {
Mattias Walline098aded72010-12-02 15:40:31 +0100588 .name = "VBUS_OVV",
589 .start = AB8500_INT_VBUS_OVV,
590 .end = AB8500_INT_VBUS_OVV,
591 .flags = IORESOURCE_IRQ,
592 },
593 {
Linus Walleij6af75ec2011-06-09 23:57:45 +0200594 .name = "USB_CH_TH_PROT_R",
595 .start = AB8500_INT_USB_CH_TH_PROT_R,
596 .end = AB8500_INT_USB_CH_TH_PROT_R,
Mattias Walline098aded72010-12-02 15:40:31 +0100597 .flags = IORESOURCE_IRQ,
598 },
599 {
Linus Walleij6af75ec2011-06-09 23:57:45 +0200600 .name = "USB_CH_TH_PROT_F",
601 .start = AB8500_INT_USB_CH_TH_PROT_F,
602 .end = AB8500_INT_USB_CH_TH_PROT_F,
Mattias Walline098aded72010-12-02 15:40:31 +0100603 .flags = IORESOURCE_IRQ,
604 },
605 {
Linus Walleij6af75ec2011-06-09 23:57:45 +0200606 .name = "MAIN_EXT_CH_NOT_OK",
607 .start = AB8500_INT_MAIN_EXT_CH_NOT_OK,
608 .end = AB8500_INT_MAIN_EXT_CH_NOT_OK,
609 .flags = IORESOURCE_IRQ,
610 },
611 {
612 .name = "MAIN_CH_TH_PROT_R",
613 .start = AB8500_INT_MAIN_CH_TH_PROT_R,
614 .end = AB8500_INT_MAIN_CH_TH_PROT_R,
615 .flags = IORESOURCE_IRQ,
616 },
617 {
618 .name = "MAIN_CH_TH_PROT_F",
619 .start = AB8500_INT_MAIN_CH_TH_PROT_F,
620 .end = AB8500_INT_MAIN_CH_TH_PROT_F,
621 .flags = IORESOURCE_IRQ,
622 },
623 {
624 .name = "USB_CHARGER_NOT_OKR",
Bengt Jonssona9823622012-03-08 14:01:57 +0100625 .start = AB8500_INT_USB_CHARGER_NOT_OKR,
626 .end = AB8500_INT_USB_CHARGER_NOT_OKR,
Linus Walleij6af75ec2011-06-09 23:57:45 +0200627 .flags = IORESOURCE_IRQ,
628 },
629 {
630 .name = "CH_WD_EXP",
631 .start = AB8500_INT_CH_WD_EXP,
632 .end = AB8500_INT_CH_WD_EXP,
633 .flags = IORESOURCE_IRQ,
634 },
635};
636
637static struct resource __devinitdata ab8500_btemp_resources[] = {
638 {
639 .name = "BAT_CTRL_INDB",
640 .start = AB8500_INT_BAT_CTRL_INDB,
641 .end = AB8500_INT_BAT_CTRL_INDB,
Mattias Walline098aded72010-12-02 15:40:31 +0100642 .flags = IORESOURCE_IRQ,
643 },
644 {
645 .name = "BTEMP_LOW",
646 .start = AB8500_INT_BTEMP_LOW,
647 .end = AB8500_INT_BTEMP_LOW,
648 .flags = IORESOURCE_IRQ,
649 },
650 {
651 .name = "BTEMP_HIGH",
652 .start = AB8500_INT_BTEMP_HIGH,
653 .end = AB8500_INT_BTEMP_HIGH,
654 .flags = IORESOURCE_IRQ,
655 },
656 {
Linus Walleij6af75ec2011-06-09 23:57:45 +0200657 .name = "BTEMP_LOW_MEDIUM",
658 .start = AB8500_INT_BTEMP_LOW_MEDIUM,
659 .end = AB8500_INT_BTEMP_LOW_MEDIUM,
Mattias Walline098aded72010-12-02 15:40:31 +0100660 .flags = IORESOURCE_IRQ,
661 },
662 {
Linus Walleij6af75ec2011-06-09 23:57:45 +0200663 .name = "BTEMP_MEDIUM_HIGH",
664 .start = AB8500_INT_BTEMP_MEDIUM_HIGH,
665 .end = AB8500_INT_BTEMP_MEDIUM_HIGH,
Mattias Walline098aded72010-12-02 15:40:31 +0100666 .flags = IORESOURCE_IRQ,
667 },
668};
669
Linus Walleij6af75ec2011-06-09 23:57:45 +0200670static struct resource __devinitdata ab8500_fg_resources[] = {
671 {
672 .name = "NCONV_ACCU",
673 .start = AB8500_INT_CCN_CONV_ACC,
674 .end = AB8500_INT_CCN_CONV_ACC,
675 .flags = IORESOURCE_IRQ,
676 },
677 {
678 .name = "BATT_OVV",
679 .start = AB8500_INT_BATT_OVV,
680 .end = AB8500_INT_BATT_OVV,
681 .flags = IORESOURCE_IRQ,
682 },
683 {
684 .name = "LOW_BAT_F",
685 .start = AB8500_INT_LOW_BAT_F,
686 .end = AB8500_INT_LOW_BAT_F,
687 .flags = IORESOURCE_IRQ,
688 },
689 {
690 .name = "LOW_BAT_R",
691 .start = AB8500_INT_LOW_BAT_R,
692 .end = AB8500_INT_LOW_BAT_R,
693 .flags = IORESOURCE_IRQ,
694 },
695 {
696 .name = "CC_INT_CALIB",
697 .start = AB8500_INT_CC_INT_CALIB,
698 .end = AB8500_INT_CC_INT_CALIB,
699 .flags = IORESOURCE_IRQ,
700 },
Bengt Jonssona9823622012-03-08 14:01:57 +0100701 {
702 .name = "CCEOC",
703 .start = AB8500_INT_CCEOC,
704 .end = AB8500_INT_CCEOC,
705 .flags = IORESOURCE_IRQ,
706 },
Linus Walleij6af75ec2011-06-09 23:57:45 +0200707};
708
709static struct resource __devinitdata ab8500_chargalg_resources[] = {};
710
Axel Lindf720642011-11-10 09:56:18 +0800711#ifdef CONFIG_DEBUG_FS
Robert Rosengren5cef8df2011-06-09 23:57:33 +0200712static struct resource __devinitdata ab8500_debug_resources[] = {
Mattias Walline098aded72010-12-02 15:40:31 +0100713 {
714 .name = "IRQ_FIRST",
715 .start = AB8500_INT_MAIN_EXT_CH_NOT_OK,
716 .end = AB8500_INT_MAIN_EXT_CH_NOT_OK,
717 .flags = IORESOURCE_IRQ,
718 },
719 {
720 .name = "IRQ_LAST",
Bengt Jonssona9823622012-03-08 14:01:57 +0100721 .start = AB8500_INT_XTAL32K_KO,
722 .end = AB8500_INT_XTAL32K_KO,
Mattias Walline098aded72010-12-02 15:40:31 +0100723 .flags = IORESOURCE_IRQ,
724 },
725};
Axel Lindf720642011-11-10 09:56:18 +0800726#endif
Mattias Walline098aded72010-12-02 15:40:31 +0100727
Robert Rosengren5cef8df2011-06-09 23:57:33 +0200728static struct resource __devinitdata ab8500_usb_resources[] = {
Mattias Walline098aded72010-12-02 15:40:31 +0100729 {
730 .name = "ID_WAKEUP_R",
731 .start = AB8500_INT_ID_WAKEUP_R,
732 .end = AB8500_INT_ID_WAKEUP_R,
733 .flags = IORESOURCE_IRQ,
734 },
735 {
736 .name = "ID_WAKEUP_F",
737 .start = AB8500_INT_ID_WAKEUP_F,
738 .end = AB8500_INT_ID_WAKEUP_F,
739 .flags = IORESOURCE_IRQ,
740 },
741 {
742 .name = "VBUS_DET_F",
743 .start = AB8500_INT_VBUS_DET_F,
744 .end = AB8500_INT_VBUS_DET_F,
745 .flags = IORESOURCE_IRQ,
746 },
747 {
748 .name = "VBUS_DET_R",
749 .start = AB8500_INT_VBUS_DET_R,
750 .end = AB8500_INT_VBUS_DET_R,
751 .flags = IORESOURCE_IRQ,
752 },
Mattias Wallin92d50a42010-12-07 11:20:47 +0100753 {
754 .name = "USB_LINK_STATUS",
755 .start = AB8500_INT_USB_LINK_STATUS,
756 .end = AB8500_INT_USB_LINK_STATUS,
757 .flags = IORESOURCE_IRQ,
758 },
Linus Walleij6af75ec2011-06-09 23:57:45 +0200759 {
760 .name = "USB_ADP_PROBE_PLUG",
761 .start = AB8500_INT_ADP_PROBE_PLUG,
762 .end = AB8500_INT_ADP_PROBE_PLUG,
763 .flags = IORESOURCE_IRQ,
764 },
765 {
766 .name = "USB_ADP_PROBE_UNPLUG",
767 .start = AB8500_INT_ADP_PROBE_UNPLUG,
768 .end = AB8500_INT_ADP_PROBE_UNPLUG,
769 .flags = IORESOURCE_IRQ,
770 },
Mattias Walline098aded72010-12-02 15:40:31 +0100771};
772
Virupax Sadashivpetimath44f72e52012-04-17 09:30:14 +0200773static struct resource __devinitdata ab8505_iddet_resources[] = {
774 {
775 .name = "KeyDeglitch",
776 .start = AB8505_INT_KEYDEGLITCH,
777 .end = AB8505_INT_KEYDEGLITCH,
778 .flags = IORESOURCE_IRQ,
779 },
780 {
781 .name = "KP",
782 .start = AB8505_INT_KP,
783 .end = AB8505_INT_KP,
784 .flags = IORESOURCE_IRQ,
785 },
786 {
787 .name = "IKP",
788 .start = AB8505_INT_IKP,
789 .end = AB8505_INT_IKP,
790 .flags = IORESOURCE_IRQ,
791 },
792 {
793 .name = "IKR",
794 .start = AB8505_INT_IKR,
795 .end = AB8505_INT_IKR,
796 .flags = IORESOURCE_IRQ,
797 },
798 {
799 .name = "KeyStuck",
800 .start = AB8505_INT_KEYSTUCK,
801 .end = AB8505_INT_KEYSTUCK,
802 .flags = IORESOURCE_IRQ,
803 },
804};
805
Robert Rosengren5cef8df2011-06-09 23:57:33 +0200806static struct resource __devinitdata ab8500_temp_resources[] = {
Mattias Walline098aded72010-12-02 15:40:31 +0100807 {
808 .name = "AB8500_TEMP_WARM",
809 .start = AB8500_INT_TEMP_WARM,
810 .end = AB8500_INT_TEMP_WARM,
811 .flags = IORESOURCE_IRQ,
812 },
813};
814
Linus Walleijd6255522012-02-20 21:42:24 +0100815static struct mfd_cell __devinitdata abx500_common_devs[] = {
Mattias Wallin5814fc32010-09-13 16:05:04 +0200816#ifdef CONFIG_DEBUG_FS
817 {
818 .name = "ab8500-debug",
Mattias Walline098aded72010-12-02 15:40:31 +0100819 .num_resources = ARRAY_SIZE(ab8500_debug_resources),
820 .resources = ab8500_debug_resources,
Mattias Wallin5814fc32010-09-13 16:05:04 +0200821 },
822#endif
Rabin Vincent62579262010-05-19 11:39:02 +0200823 {
Mattias Walline098aded72010-12-02 15:40:31 +0100824 .name = "ab8500-sysctrl",
825 },
826 {
827 .name = "ab8500-regulator",
828 },
829 {
Rabin Vincent62579262010-05-19 11:39:02 +0200830 .name = "ab8500-gpadc",
831 .num_resources = ARRAY_SIZE(ab8500_gpadc_resources),
832 .resources = ab8500_gpadc_resources,
833 },
834 {
835 .name = "ab8500-rtc",
836 .num_resources = ARRAY_SIZE(ab8500_rtc_resources),
837 .resources = ab8500_rtc_resources,
838 },
Arun Murthyf0f05b12010-09-06 12:24:52 +0530839 {
Linus Walleij6af75ec2011-06-09 23:57:45 +0200840 .name = "ab8500-acc-det",
841 .num_resources = ARRAY_SIZE(ab8500_av_acc_detect_resources),
842 .resources = ab8500_av_acc_detect_resources,
843 },
844 {
Mattias Walline098aded72010-12-02 15:40:31 +0100845 .name = "ab8500-poweron-key",
846 .num_resources = ARRAY_SIZE(ab8500_poweronkey_db_resources),
847 .resources = ab8500_poweronkey_db_resources,
848 },
849 {
Arun Murthyf0f05b12010-09-06 12:24:52 +0530850 .name = "ab8500-pwm",
851 .id = 1,
852 },
853 {
854 .name = "ab8500-pwm",
855 .id = 2,
856 },
857 {
858 .name = "ab8500-pwm",
859 .id = 3,
860 },
Mattias Walline098aded72010-12-02 15:40:31 +0100861 { .name = "ab8500-leds", },
Sundar R Iyer77686512010-09-05 12:18:47 -0700862 {
Mattias Walline098aded72010-12-02 15:40:31 +0100863 .name = "ab8500-denc",
864 },
865 {
866 .name = "ab8500-temp",
867 .num_resources = ARRAY_SIZE(ab8500_temp_resources),
868 .resources = ab8500_temp_resources,
Sundar R Iyer77686512010-09-05 12:18:47 -0700869 },
Rabin Vincent62579262010-05-19 11:39:02 +0200870};
871
Rickard Andersson6ef94182012-04-17 09:30:57 +0200872static struct mfd_cell __devinitdata ab8500_bm_devs[] = {
873 {
874 .name = "ab8500-charger",
875 .num_resources = ARRAY_SIZE(ab8500_charger_resources),
876 .resources = ab8500_charger_resources,
877 },
878 {
879 .name = "ab8500-btemp",
880 .num_resources = ARRAY_SIZE(ab8500_btemp_resources),
881 .resources = ab8500_btemp_resources,
882 },
883 {
884 .name = "ab8500-fg",
885 .num_resources = ARRAY_SIZE(ab8500_fg_resources),
886 .resources = ab8500_fg_resources,
887 },
888 {
889 .name = "ab8500-chargalg",
890 .num_resources = ARRAY_SIZE(ab8500_chargalg_resources),
891 .resources = ab8500_chargalg_resources,
892 },
893};
894
Linus Walleijd6255522012-02-20 21:42:24 +0100895static struct mfd_cell __devinitdata ab8500_devs[] = {
896 {
897 .name = "ab8500-gpio",
898 .num_resources = ARRAY_SIZE(ab8500_gpio_resources),
899 .resources = ab8500_gpio_resources,
900 },
901 {
902 .name = "ab8500-usb",
903 .num_resources = ARRAY_SIZE(ab8500_usb_resources),
904 .resources = ab8500_usb_resources,
905 },
Virupax Sadashivpetimath44f72e52012-04-17 09:30:14 +0200906 {
907 .name = "ab8500-codec",
908 },
Linus Walleijd6255522012-02-20 21:42:24 +0100909};
910
911static struct mfd_cell __devinitdata ab9540_devs[] = {
912 {
913 .name = "ab8500-gpio",
914 .num_resources = ARRAY_SIZE(ab9540_gpio_resources),
915 .resources = ab9540_gpio_resources,
916 },
917 {
918 .name = "ab9540-usb",
919 .num_resources = ARRAY_SIZE(ab8500_usb_resources),
920 .resources = ab8500_usb_resources,
921 },
Virupax Sadashivpetimath44f72e52012-04-17 09:30:14 +0200922 {
923 .name = "ab9540-codec",
924 },
925};
926
927/* Device list common to ab9540 and ab8505 */
928static struct mfd_cell __devinitdata ab9540_ab8505_devs[] = {
929 {
930 .name = "ab-iddet",
931 .num_resources = ARRAY_SIZE(ab8505_iddet_resources),
932 .resources = ab8505_iddet_resources,
933 },
Linus Walleijd6255522012-02-20 21:42:24 +0100934};
935
Mattias Wallincca69b62010-12-02 15:09:36 +0100936static ssize_t show_chip_id(struct device *dev,
937 struct device_attribute *attr, char *buf)
938{
939 struct ab8500 *ab8500;
940
941 ab8500 = dev_get_drvdata(dev);
942 return sprintf(buf, "%#x\n", ab8500 ? ab8500->chip_id : -EINVAL);
943}
944
Mattias Walline5c238c2011-03-02 11:52:36 +0100945/*
946 * ab8500 has switched off due to (SWITCH_OFF_STATUS):
947 * 0x01 Swoff bit programming
948 * 0x02 Thermal protection activation
949 * 0x04 Vbat lower then BattOk falling threshold
950 * 0x08 Watchdog expired
951 * 0x10 Non presence of 32kHz clock
952 * 0x20 Battery level lower than power on reset threshold
953 * 0x40 Power on key 1 pressed longer than 10 seconds
954 * 0x80 DB8500 thermal shutdown
955 */
956static ssize_t show_switch_off_status(struct device *dev,
957 struct device_attribute *attr, char *buf)
958{
959 int ret;
960 u8 value;
961 struct ab8500 *ab8500;
962
963 ab8500 = dev_get_drvdata(dev);
964 ret = get_register_interruptible(ab8500, AB8500_RTC,
965 AB8500_SWITCH_OFF_STATUS, &value);
966 if (ret < 0)
967 return ret;
968 return sprintf(buf, "%#x\n", value);
969}
970
Andrew Lynnb4a31032011-10-11 10:49:47 +0200971/*
972 * ab8500 has turned on due to (TURN_ON_STATUS):
973 * 0x01 PORnVbat
974 * 0x02 PonKey1dbF
975 * 0x04 PonKey2dbF
976 * 0x08 RTCAlarm
977 * 0x10 MainChDet
978 * 0x20 VbusDet
979 * 0x40 UsbIDDetect
980 * 0x80 Reserved
981 */
982static ssize_t show_turn_on_status(struct device *dev,
983 struct device_attribute *attr, char *buf)
984{
985 int ret;
986 u8 value;
987 struct ab8500 *ab8500;
988
989 ab8500 = dev_get_drvdata(dev);
990 ret = get_register_interruptible(ab8500, AB8500_SYS_CTRL1_BLOCK,
991 AB8500_TURN_ON_STATUS, &value);
992 if (ret < 0)
993 return ret;
994 return sprintf(buf, "%#x\n", value);
995}
996
Linus Walleijd6255522012-02-20 21:42:24 +0100997static ssize_t show_ab9540_dbbrstn(struct device *dev,
998 struct device_attribute *attr, char *buf)
999{
1000 struct ab8500 *ab8500;
1001 int ret;
1002 u8 value;
1003
1004 ab8500 = dev_get_drvdata(dev);
1005
1006 ret = get_register_interruptible(ab8500, AB8500_REGU_CTRL2,
1007 AB9540_MODEM_CTRL2_REG, &value);
1008 if (ret < 0)
1009 return ret;
1010
1011 return sprintf(buf, "%d\n",
1012 (value & AB9540_MODEM_CTRL2_SWDBBRSTN_BIT) ? 1 : 0);
1013}
1014
1015static ssize_t store_ab9540_dbbrstn(struct device *dev,
1016 struct device_attribute *attr, const char *buf, size_t count)
1017{
1018 struct ab8500 *ab8500;
1019 int ret = count;
1020 int err;
1021 u8 bitvalues;
1022
1023 ab8500 = dev_get_drvdata(dev);
1024
1025 if (count > 0) {
1026 switch (buf[0]) {
1027 case '0':
1028 bitvalues = 0;
1029 break;
1030 case '1':
1031 bitvalues = AB9540_MODEM_CTRL2_SWDBBRSTN_BIT;
1032 break;
1033 default:
1034 goto exit;
1035 }
1036
1037 err = mask_and_set_register_interruptible(ab8500,
1038 AB8500_REGU_CTRL2, AB9540_MODEM_CTRL2_REG,
1039 AB9540_MODEM_CTRL2_SWDBBRSTN_BIT, bitvalues);
1040 if (err)
1041 dev_info(ab8500->dev,
1042 "Failed to set DBBRSTN %c, err %#x\n",
1043 buf[0], err);
1044 }
1045
1046exit:
1047 return ret;
1048}
1049
Mattias Wallincca69b62010-12-02 15:09:36 +01001050static DEVICE_ATTR(chip_id, S_IRUGO, show_chip_id, NULL);
Mattias Walline5c238c2011-03-02 11:52:36 +01001051static DEVICE_ATTR(switch_off_status, S_IRUGO, show_switch_off_status, NULL);
Andrew Lynnb4a31032011-10-11 10:49:47 +02001052static DEVICE_ATTR(turn_on_status, S_IRUGO, show_turn_on_status, NULL);
Linus Walleijd6255522012-02-20 21:42:24 +01001053static DEVICE_ATTR(dbbrstn, S_IRUGO | S_IWUSR,
1054 show_ab9540_dbbrstn, store_ab9540_dbbrstn);
Mattias Wallincca69b62010-12-02 15:09:36 +01001055
1056static struct attribute *ab8500_sysfs_entries[] = {
1057 &dev_attr_chip_id.attr,
Mattias Walline5c238c2011-03-02 11:52:36 +01001058 &dev_attr_switch_off_status.attr,
Andrew Lynnb4a31032011-10-11 10:49:47 +02001059 &dev_attr_turn_on_status.attr,
Mattias Wallincca69b62010-12-02 15:09:36 +01001060 NULL,
1061};
1062
Linus Walleijd6255522012-02-20 21:42:24 +01001063static struct attribute *ab9540_sysfs_entries[] = {
1064 &dev_attr_chip_id.attr,
1065 &dev_attr_switch_off_status.attr,
1066 &dev_attr_turn_on_status.attr,
1067 &dev_attr_dbbrstn.attr,
1068 NULL,
1069};
1070
Mattias Wallincca69b62010-12-02 15:09:36 +01001071static struct attribute_group ab8500_attr_group = {
1072 .attrs = ab8500_sysfs_entries,
1073};
1074
Linus Walleijd6255522012-02-20 21:42:24 +01001075static struct attribute_group ab9540_attr_group = {
1076 .attrs = ab9540_sysfs_entries,
1077};
1078
Linus Walleij0f6208372012-02-20 21:42:10 +01001079int __devinit ab8500_init(struct ab8500 *ab8500, enum ab8500_version version)
Rabin Vincent62579262010-05-19 11:39:02 +02001080{
1081 struct ab8500_platform_data *plat = dev_get_platdata(ab8500->dev);
1082 int ret;
1083 int i;
Mattias Wallin47c16972010-09-10 17:47:56 +02001084 u8 value;
Rabin Vincent62579262010-05-19 11:39:02 +02001085
1086 if (plat)
1087 ab8500->irq_base = plat->irq_base;
1088
1089 mutex_init(&ab8500->lock);
1090 mutex_init(&ab8500->irq_lock);
Jonas Aaberg112a80d2012-04-17 09:30:33 +02001091 atomic_set(&ab8500->transfer_ongoing, 0);
Rabin Vincent62579262010-05-19 11:39:02 +02001092
Linus Walleij0f6208372012-02-20 21:42:10 +01001093 if (version != AB8500_VERSION_UNDEFINED)
1094 ab8500->version = version;
1095 else {
1096 ret = get_register_interruptible(ab8500, AB8500_MISC,
1097 AB8500_IC_NAME_REG, &value);
1098 if (ret < 0)
1099 return ret;
1100
1101 ab8500->version = value;
1102 }
1103
Mattias Wallin47c16972010-09-10 17:47:56 +02001104 ret = get_register_interruptible(ab8500, AB8500_MISC,
1105 AB8500_REV_REG, &value);
Rabin Vincent62579262010-05-19 11:39:02 +02001106 if (ret < 0)
1107 return ret;
1108
Mattias Wallin47c16972010-09-10 17:47:56 +02001109 ab8500->chip_id = value;
Rabin Vincent62579262010-05-19 11:39:02 +02001110
Linus Walleij0f6208372012-02-20 21:42:10 +01001111 dev_info(ab8500->dev, "detected chip, %s rev. %1x.%1x\n",
1112 ab8500_version_str[ab8500->version],
1113 ab8500->chip_id >> 4,
1114 ab8500->chip_id & 0x0F);
1115
Linus Walleijd6255522012-02-20 21:42:24 +01001116 /* Configure AB8500 or AB9540 IRQ */
Bengt Jonssona9823622012-03-08 14:01:57 +01001117 if (is_ab9540(ab8500) || is_ab8505(ab8500)) {
Linus Walleijd6255522012-02-20 21:42:24 +01001118 ab8500->mask_size = AB9540_NUM_IRQ_REGS;
1119 ab8500->irq_reg_offset = ab9540_irq_regoffset;
1120 } else {
1121 ab8500->mask_size = AB8500_NUM_IRQ_REGS;
1122 ab8500->irq_reg_offset = ab8500_irq_regoffset;
1123 }
Linus Walleij2ced4452012-02-20 21:42:17 +01001124 ab8500->mask = kzalloc(ab8500->mask_size, GFP_KERNEL);
1125 if (!ab8500->mask)
1126 return -ENOMEM;
1127 ab8500->oldmask = kzalloc(ab8500->mask_size, GFP_KERNEL);
1128 if (!ab8500->oldmask) {
1129 ret = -ENOMEM;
1130 goto out_freemask;
1131 }
Mattias Walline5c238c2011-03-02 11:52:36 +01001132 /*
1133 * ab8500 has switched off due to (SWITCH_OFF_STATUS):
1134 * 0x01 Swoff bit programming
1135 * 0x02 Thermal protection activation
1136 * 0x04 Vbat lower then BattOk falling threshold
1137 * 0x08 Watchdog expired
1138 * 0x10 Non presence of 32kHz clock
1139 * 0x20 Battery level lower than power on reset threshold
1140 * 0x40 Power on key 1 pressed longer than 10 seconds
1141 * 0x80 DB8500 thermal shutdown
1142 */
1143
1144 ret = get_register_interruptible(ab8500, AB8500_RTC,
1145 AB8500_SWITCH_OFF_STATUS, &value);
1146 if (ret < 0)
1147 return ret;
1148 dev_info(ab8500->dev, "switch off status: %#x", value);
1149
Rabin Vincent62579262010-05-19 11:39:02 +02001150 if (plat && plat->init)
1151 plat->init(ab8500);
1152
1153 /* Clear and mask all interrupts */
Linus Walleij2ced4452012-02-20 21:42:17 +01001154 for (i = 0; i < ab8500->mask_size; i++) {
Linus Walleij0f6208372012-02-20 21:42:10 +01001155 /*
1156 * Interrupt register 12 doesn't exist prior to AB8500 version
1157 * 2.0
1158 */
1159 if (ab8500->irq_reg_offset[i] == 11 &&
1160 is_ab8500_1p1_or_earlier(ab8500))
Mattias Wallin92d50a42010-12-07 11:20:47 +01001161 continue;
Rabin Vincent62579262010-05-19 11:39:02 +02001162
Mattias Wallin47c16972010-09-10 17:47:56 +02001163 get_register_interruptible(ab8500, AB8500_INTERRUPT,
Linus Walleij2ced4452012-02-20 21:42:17 +01001164 AB8500_IT_LATCH1_REG + ab8500->irq_reg_offset[i],
Mattias Wallin92d50a42010-12-07 11:20:47 +01001165 &value);
Mattias Wallin47c16972010-09-10 17:47:56 +02001166 set_register_interruptible(ab8500, AB8500_INTERRUPT,
Linus Walleij2ced4452012-02-20 21:42:17 +01001167 AB8500_IT_MASK1_REG + ab8500->irq_reg_offset[i], 0xff);
Rabin Vincent62579262010-05-19 11:39:02 +02001168 }
1169
Mattias Wallin47c16972010-09-10 17:47:56 +02001170 ret = abx500_register_ops(ab8500->dev, &ab8500_ops);
1171 if (ret)
Linus Walleij2ced4452012-02-20 21:42:17 +01001172 goto out_freeoldmask;
Mattias Wallin47c16972010-09-10 17:47:56 +02001173
Linus Walleij2ced4452012-02-20 21:42:17 +01001174 for (i = 0; i < ab8500->mask_size; i++)
Rabin Vincent62579262010-05-19 11:39:02 +02001175 ab8500->mask[i] = ab8500->oldmask[i] = 0xff;
1176
1177 if (ab8500->irq_base) {
1178 ret = ab8500_irq_init(ab8500);
1179 if (ret)
Linus Walleij2ced4452012-02-20 21:42:17 +01001180 goto out_freeoldmask;
Rabin Vincent62579262010-05-19 11:39:02 +02001181
1182 ret = request_threaded_irq(ab8500->irq, NULL, ab8500_irq,
Mattias Wallin4f079982010-12-02 15:10:27 +01001183 IRQF_ONESHOT | IRQF_NO_SUSPEND,
1184 "ab8500", ab8500);
Rabin Vincent62579262010-05-19 11:39:02 +02001185 if (ret)
1186 goto out_removeirq;
1187 }
1188
Linus Walleijd6255522012-02-20 21:42:24 +01001189 ret = mfd_add_devices(ab8500->dev, 0, abx500_common_devs,
1190 ARRAY_SIZE(abx500_common_devs), NULL,
1191 ab8500->irq_base);
1192
1193 if (ret)
1194 goto out_freeirq;
1195
1196 if (is_ab9540(ab8500))
1197 ret = mfd_add_devices(ab8500->dev, 0, ab9540_devs,
1198 ARRAY_SIZE(ab9540_devs), NULL,
1199 ab8500->irq_base);
1200 else
1201 ret = mfd_add_devices(ab8500->dev, 0, ab8500_devs,
Virupax Sadashivpetimath44f72e52012-04-17 09:30:14 +02001202 ARRAY_SIZE(ab8500_devs), NULL,
Rabin Vincent62579262010-05-19 11:39:02 +02001203 ab8500->irq_base);
Virupax Sadashivpetimath44f72e52012-04-17 09:30:14 +02001204
1205 if (is_ab9540(ab8500) || is_ab8505(ab8500))
1206 ret = mfd_add_devices(ab8500->dev, 0, ab9540_ab8505_devs,
1207 ARRAY_SIZE(ab9540_ab8505_devs), NULL,
1208 ab8500->irq_base);
1209
Rabin Vincent62579262010-05-19 11:39:02 +02001210 if (ret)
1211 goto out_freeirq;
1212
Rickard Andersson6ef94182012-04-17 09:30:57 +02001213 if (!no_bm) {
1214 /* Add battery management devices */
1215 ret = mfd_add_devices(ab8500->dev, 0, ab8500_bm_devs,
1216 ARRAY_SIZE(ab8500_bm_devs), NULL,
1217 ab8500->irq_base);
1218 if (ret)
1219 dev_err(ab8500->dev, "error adding bm devices\n");
1220 }
1221
Linus Walleijd6255522012-02-20 21:42:24 +01001222 if (is_ab9540(ab8500))
1223 ret = sysfs_create_group(&ab8500->dev->kobj,
1224 &ab9540_attr_group);
1225 else
1226 ret = sysfs_create_group(&ab8500->dev->kobj,
1227 &ab8500_attr_group);
Mattias Wallincca69b62010-12-02 15:09:36 +01001228 if (ret)
1229 dev_err(ab8500->dev, "error creating sysfs entries\n");
Linus Walleijd6255522012-02-20 21:42:24 +01001230 else
1231 return ret;
Rabin Vincent62579262010-05-19 11:39:02 +02001232
1233out_freeirq:
Linus Walleij6d95b7f2012-02-20 21:42:03 +01001234 if (ab8500->irq_base)
Rabin Vincent62579262010-05-19 11:39:02 +02001235 free_irq(ab8500->irq, ab8500);
1236out_removeirq:
Linus Walleij6d95b7f2012-02-20 21:42:03 +01001237 if (ab8500->irq_base)
Rabin Vincent62579262010-05-19 11:39:02 +02001238 ab8500_irq_remove(ab8500);
Linus Walleij2ced4452012-02-20 21:42:17 +01001239out_freeoldmask:
1240 kfree(ab8500->oldmask);
1241out_freemask:
1242 kfree(ab8500->mask);
Linus Walleij6d95b7f2012-02-20 21:42:03 +01001243
Rabin Vincent62579262010-05-19 11:39:02 +02001244 return ret;
1245}
1246
1247int __devexit ab8500_exit(struct ab8500 *ab8500)
1248{
Linus Walleijd6255522012-02-20 21:42:24 +01001249 if (is_ab9540(ab8500))
1250 sysfs_remove_group(&ab8500->dev->kobj, &ab9540_attr_group);
1251 else
1252 sysfs_remove_group(&ab8500->dev->kobj, &ab8500_attr_group);
Rabin Vincent62579262010-05-19 11:39:02 +02001253 mfd_remove_devices(ab8500->dev);
1254 if (ab8500->irq_base) {
1255 free_irq(ab8500->irq, ab8500);
1256 ab8500_irq_remove(ab8500);
1257 }
Linus Walleij2ced4452012-02-20 21:42:17 +01001258 kfree(ab8500->oldmask);
1259 kfree(ab8500->mask);
Rabin Vincent62579262010-05-19 11:39:02 +02001260
1261 return 0;
1262}
1263
Mattias Wallinadceed62011-03-02 11:51:11 +01001264MODULE_AUTHOR("Mattias Wallin, Srinidhi Kasagar, Rabin Vincent");
Rabin Vincent62579262010-05-19 11:39:02 +02001265MODULE_DESCRIPTION("AB8500 MFD core");
1266MODULE_LICENSE("GPL v2");