Root/
1 | /* |
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> |
7 | * Author: Mattias Wallin <mattias.wallin@stericsson.com> |
8 | */ |
9 | |
10 | #include <linux/kernel.h> |
11 | #include <linux/slab.h> |
12 | #include <linux/init.h> |
13 | #include <linux/irq.h> |
14 | #include <linux/irqdomain.h> |
15 | #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> |
20 | #include <linux/mfd/abx500.h> |
21 | #include <linux/mfd/abx500/ab8500.h> |
22 | #include <linux/mfd/abx500/ab8500-bm.h> |
23 | #include <linux/mfd/dbx500-prcmu.h> |
24 | #include <linux/regulator/ab8500.h> |
25 | #include <linux/of.h> |
26 | #include <linux/of_device.h> |
27 | |
28 | /* |
29 | * Interrupt register offsets |
30 | * Bank : 0x0E |
31 | */ |
32 | #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 |
40 | #define AB9540_IT_SOURCE13_REG 0x0C |
41 | #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 |
47 | |
48 | /* |
49 | * latch registers |
50 | */ |
51 | #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 |
61 | #define AB8500_IT_LATCH12_REG 0x2B |
62 | #define AB9540_IT_LATCH13_REG 0x2C |
63 | #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 |
69 | |
70 | /* |
71 | * mask registers |
72 | */ |
73 | |
74 | #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 |
98 | |
99 | /* |
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 | |
108 | #define AB8500_REV_REG 0x80 |
109 | #define AB8500_IC_NAME_REG 0x82 |
110 | #define AB8500_SWITCH_OFF_STATUS 0x00 |
111 | |
112 | #define AB8500_TURN_ON_STATUS 0x00 |
113 | |
114 | static bool no_bm; /* No battery management */ |
115 | module_param(no_bm, bool, S_IRUGO); |
116 | |
117 | #define AB9540_MODEM_CTRL2_REG 0x23 |
118 | #define AB9540_MODEM_CTRL2_SWDBBRSTN_BIT BIT(2) |
119 | |
120 | /* |
121 | * Map interrupt numbers to the LATCH and MASK register offsets, Interrupt |
122 | * numbers are indexed into this array with (num / 8). The interupts are |
123 | * defined in linux/mfd/ab8500.h |
124 | * |
125 | * This is one off from the register names, i.e. AB8500_IT_MASK1_REG is at |
126 | * offset 0. |
127 | */ |
128 | /* AB8500 support */ |
129 | static const int ab8500_irq_regoffset[AB8500_NUM_IRQ_REGS] = { |
130 | 0, 1, 2, 3, 4, 6, 7, 8, 9, 11, 18, 19, 20, 21, |
131 | }; |
132 | |
133 | /* AB9540 support */ |
134 | static 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 | |
138 | static 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 | |
145 | static int ab8500_prcmu_write(struct ab8500 *ab8500, u16 addr, u8 data) |
146 | { |
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 | |
155 | static int ab8500_prcmu_write_masked(struct ab8500 *ab8500, u16 addr, u8 mask, |
156 | 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 | |
167 | static int ab8500_prcmu_read(struct ab8500 *ab8500, u16 addr) |
168 | { |
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 | |
180 | static int ab8500_get_chip_id(struct device *dev) |
181 | { |
182 | 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; |
188 | } |
189 | |
190 | static int set_register_interruptible(struct ab8500 *ab8500, u8 bank, |
191 | u8 reg, u8 data) |
192 | { |
193 | int ret; |
194 | /* |
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; |
199 | |
200 | dev_vdbg(ab8500->dev, "wr: addr %#x <= %#x\n", addr, data); |
201 | |
202 | mutex_lock(&ab8500->lock); |
203 | |
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 | |
213 | static int ab8500_set_register(struct device *dev, u8 bank, |
214 | u8 reg, u8 value) |
215 | { |
216 | int ret; |
217 | struct ab8500 *ab8500 = dev_get_drvdata(dev->parent); |
218 | |
219 | atomic_inc(&ab8500->transfer_ongoing); |
220 | ret = set_register_interruptible(ab8500, bank, reg, value); |
221 | atomic_dec(&ab8500->transfer_ongoing); |
222 | return ret; |
223 | } |
224 | |
225 | static 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 | |
233 | mutex_lock(&ab8500->lock); |
234 | |
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 | |
248 | static int ab8500_get_register(struct device *dev, u8 bank, |
249 | u8 reg, u8 *value) |
250 | { |
251 | int ret; |
252 | struct ab8500 *ab8500 = dev_get_drvdata(dev->parent); |
253 | |
254 | atomic_inc(&ab8500->transfer_ongoing); |
255 | ret = get_register_interruptible(ab8500, bank, reg, value); |
256 | atomic_dec(&ab8500->transfer_ongoing); |
257 | return ret; |
258 | } |
259 | |
260 | static int mask_and_set_register_interruptible(struct ab8500 *ab8500, u8 bank, |
261 | u8 reg, u8 bitmask, u8 bitvalues) |
262 | { |
263 | int ret; |
264 | /* 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 | |
268 | mutex_lock(&ab8500->lock); |
269 | |
270 | 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); |
290 | goto out; |
291 | } |
292 | ret = ab8500->write_masked(ab8500, addr, bitmask, bitvalues); |
293 | if (ret < 0) |
294 | dev_err(ab8500->dev, "failed to modify reg %#x: %d\n", addr, |
295 | ret); |
296 | out: |
297 | mutex_unlock(&ab8500->lock); |
298 | return ret; |
299 | } |
300 | |
301 | static int ab8500_mask_and_set_register(struct device *dev, |
302 | u8 bank, u8 reg, u8 bitmask, u8 bitvalues) |
303 | { |
304 | int ret; |
305 | struct ab8500 *ab8500 = dev_get_drvdata(dev->parent); |
306 | |
307 | 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; |
312 | } |
313 | |
314 | static 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 | .dump_all_banks = ab8500_dump_all_banks, |
324 | }; |
325 | |
326 | static void ab8500_irq_lock(struct irq_data *data) |
327 | { |
328 | struct ab8500 *ab8500 = irq_data_get_irq_chip_data(data); |
329 | |
330 | mutex_lock(&ab8500->irq_lock); |
331 | atomic_inc(&ab8500->transfer_ongoing); |
332 | } |
333 | |
334 | static void ab8500_irq_sync_unlock(struct irq_data *data) |
335 | { |
336 | struct ab8500 *ab8500 = irq_data_get_irq_chip_data(data); |
337 | int i; |
338 | |
339 | for (i = 0; i < ab8500->mask_size; i++) { |
340 | u8 old = ab8500->oldmask[i]; |
341 | u8 new = ab8500->mask[i]; |
342 | int reg; |
343 | |
344 | if (new == old) |
345 | continue; |
346 | |
347 | /* |
348 | * Interrupt register 12 doesn't exist prior to AB8500 version |
349 | * 2.0 |
350 | */ |
351 | if (ab8500->irq_reg_offset[i] == 11 && |
352 | is_ab8500_1p1_or_earlier(ab8500)) |
353 | continue; |
354 | |
355 | ab8500->oldmask[i] = new; |
356 | |
357 | reg = AB8500_IT_MASK1_REG + ab8500->irq_reg_offset[i]; |
358 | set_register_interruptible(ab8500, AB8500_INTERRUPT, reg, new); |
359 | } |
360 | atomic_dec(&ab8500->transfer_ongoing); |
361 | mutex_unlock(&ab8500->irq_lock); |
362 | } |
363 | |
364 | static void ab8500_irq_mask(struct irq_data *data) |
365 | { |
366 | struct ab8500 *ab8500 = irq_data_get_irq_chip_data(data); |
367 | int offset = data->hwirq; |
368 | int index = offset / 8; |
369 | int mask = 1 << (offset % 8); |
370 | |
371 | ab8500->mask[index] |= mask; |
372 | |
373 | /* The AB8500 GPIOs have two interrupts each (rising & falling). */ |
374 | if (offset >= AB8500_INT_GPIO6R && offset <= AB8500_INT_GPIO41R) |
375 | ab8500->mask[index + 2] |= mask; |
376 | if (offset >= AB9540_INT_GPIO50R && offset <= AB9540_INT_GPIO54R) |
377 | ab8500->mask[index + 1] |= mask; |
378 | if (offset == AB8540_INT_GPIO43R || offset == AB8540_INT_GPIO44R) |
379 | /* Here the falling IRQ is one bit lower */ |
380 | ab8500->mask[index] |= (mask << 1); |
381 | } |
382 | |
383 | static void ab8500_irq_unmask(struct irq_data *data) |
384 | { |
385 | struct ab8500 *ab8500 = irq_data_get_irq_chip_data(data); |
386 | unsigned int type = irqd_get_trigger_type(data); |
387 | int offset = data->hwirq; |
388 | int index = offset / 8; |
389 | int mask = 1 << (offset % 8); |
390 | |
391 | if (type & IRQ_TYPE_EDGE_RISING) |
392 | ab8500->mask[index] &= ~mask; |
393 | |
394 | /* The AB8500 GPIOs have two interrupts each (rising & falling). */ |
395 | if (type & IRQ_TYPE_EDGE_FALLING) { |
396 | if (offset >= AB8500_INT_GPIO6R && offset <= AB8500_INT_GPIO41R) |
397 | ab8500->mask[index + 2] &= ~mask; |
398 | else if (offset >= AB9540_INT_GPIO50R && offset <= AB9540_INT_GPIO54R) |
399 | ab8500->mask[index + 1] &= ~mask; |
400 | else if (offset == AB8540_INT_GPIO43R || offset == AB8540_INT_GPIO44R) |
401 | /* Here the falling IRQ is one bit lower */ |
402 | ab8500->mask[index] &= ~(mask << 1); |
403 | else |
404 | ab8500->mask[index] &= ~mask; |
405 | } else { |
406 | /* Satisfies the case where type is not set. */ |
407 | ab8500->mask[index] &= ~mask; |
408 | } |
409 | } |
410 | |
411 | static int ab8500_irq_set_type(struct irq_data *data, unsigned int type) |
412 | { |
413 | return 0; |
414 | } |
415 | |
416 | static struct irq_chip ab8500_irq_chip = { |
417 | .name = "ab8500", |
418 | .irq_bus_lock = ab8500_irq_lock, |
419 | .irq_bus_sync_unlock = ab8500_irq_sync_unlock, |
420 | .irq_mask = ab8500_irq_mask, |
421 | .irq_disable = ab8500_irq_mask, |
422 | .irq_unmask = ab8500_irq_unmask, |
423 | .irq_set_type = ab8500_irq_set_type, |
424 | }; |
425 | |
426 | static int ab8500_handle_hierarchical_line(struct ab8500 *ab8500, |
427 | int latch_offset, u8 latch_val) |
428 | { |
429 | int int_bit = __ffs(latch_val); |
430 | int line, i; |
431 | |
432 | do { |
433 | int_bit = __ffs(latch_val); |
434 | |
435 | for (i = 0; i < ab8500->mask_size; i++) |
436 | if (ab8500->irq_reg_offset[i] == latch_offset) |
437 | break; |
438 | |
439 | if (i >= ab8500->mask_size) { |
440 | dev_err(ab8500->dev, "Register offset 0x%2x not declared\n", |
441 | latch_offset); |
442 | return -ENXIO; |
443 | } |
444 | |
445 | line = (i << 3) + int_bit; |
446 | latch_val &= ~(1 << int_bit); |
447 | |
448 | /* |
449 | * This handles the falling edge hwirqs from the GPIO |
450 | * lines. Route them back to the line registered for the |
451 | * rising IRQ, as this is merely a flag for the same IRQ |
452 | * in linux terms. |
453 | */ |
454 | if (line >= AB8500_INT_GPIO6F && line <= AB8500_INT_GPIO41F) |
455 | line -= 16; |
456 | if (line >= AB9540_INT_GPIO50F && line <= AB9540_INT_GPIO54F) |
457 | line -= 8; |
458 | if (line == AB8540_INT_GPIO43F || line == AB8540_INT_GPIO44F) |
459 | line += 1; |
460 | |
461 | handle_nested_irq(ab8500->irq_base + line); |
462 | } while (latch_val); |
463 | |
464 | return 0; |
465 | } |
466 | |
467 | static int ab8500_handle_hierarchical_latch(struct ab8500 *ab8500, |
468 | int hier_offset, u8 hier_val) |
469 | { |
470 | int latch_bit, status; |
471 | u8 latch_offset, latch_val; |
472 | |
473 | do { |
474 | latch_bit = __ffs(hier_val); |
475 | latch_offset = (hier_offset << 3) + latch_bit; |
476 | |
477 | /* Fix inconsistent ITFromLatch25 bit mapping... */ |
478 | if (unlikely(latch_offset == 17)) |
479 | latch_offset = 24; |
480 | |
481 | status = get_register_interruptible(ab8500, |
482 | AB8500_INTERRUPT, |
483 | AB8500_IT_LATCH1_REG + latch_offset, |
484 | &latch_val); |
485 | if (status < 0 || latch_val == 0) |
486 | goto discard; |
487 | |
488 | status = ab8500_handle_hierarchical_line(ab8500, |
489 | latch_offset, latch_val); |
490 | if (status < 0) |
491 | return status; |
492 | discard: |
493 | hier_val &= ~(1 << latch_bit); |
494 | } while (hier_val); |
495 | |
496 | return 0; |
497 | } |
498 | |
499 | static irqreturn_t ab8500_hierarchical_irq(int irq, void *dev) |
500 | { |
501 | struct ab8500 *ab8500 = dev; |
502 | u8 i; |
503 | |
504 | dev_vdbg(ab8500->dev, "interrupt\n"); |
505 | |
506 | /* Hierarchical interrupt version */ |
507 | for (i = 0; i < AB8500_IT_LATCHHIER_NUM; i++) { |
508 | int status; |
509 | u8 hier_val; |
510 | |
511 | status = get_register_interruptible(ab8500, AB8500_INTERRUPT, |
512 | AB8500_IT_LATCHHIER1_REG + i, &hier_val); |
513 | if (status < 0 || hier_val == 0) |
514 | continue; |
515 | |
516 | status = ab8500_handle_hierarchical_latch(ab8500, i, hier_val); |
517 | if (status < 0) |
518 | break; |
519 | } |
520 | return IRQ_HANDLED; |
521 | } |
522 | |
523 | /** |
524 | * ab8500_irq_get_virq(): Map an interrupt on a chip to a virtual IRQ |
525 | * |
526 | * @ab8500: ab8500_irq controller to operate on. |
527 | * @irq: index of the interrupt requested in the chip IRQs |
528 | * |
529 | * Useful for drivers to request their own IRQs. |
530 | */ |
531 | static int ab8500_irq_get_virq(struct ab8500 *ab8500, int irq) |
532 | { |
533 | if (!ab8500) |
534 | return -EINVAL; |
535 | |
536 | return irq_create_mapping(ab8500->domain, irq); |
537 | } |
538 | |
539 | static irqreturn_t ab8500_irq(int irq, void *dev) |
540 | { |
541 | struct ab8500 *ab8500 = dev; |
542 | int i; |
543 | |
544 | dev_vdbg(ab8500->dev, "interrupt\n"); |
545 | |
546 | atomic_inc(&ab8500->transfer_ongoing); |
547 | |
548 | for (i = 0; i < ab8500->mask_size; i++) { |
549 | int regoffset = ab8500->irq_reg_offset[i]; |
550 | int status; |
551 | u8 value; |
552 | |
553 | /* |
554 | * Interrupt register 12 doesn't exist prior to AB8500 version |
555 | * 2.0 |
556 | */ |
557 | if (regoffset == 11 && is_ab8500_1p1_or_earlier(ab8500)) |
558 | continue; |
559 | |
560 | status = get_register_interruptible(ab8500, AB8500_INTERRUPT, |
561 | AB8500_IT_LATCH1_REG + regoffset, &value); |
562 | if (status < 0 || value == 0) |
563 | continue; |
564 | |
565 | do { |
566 | int bit = __ffs(value); |
567 | int line = i * 8 + bit; |
568 | int virq = ab8500_irq_get_virq(ab8500, line); |
569 | |
570 | handle_nested_irq(virq); |
571 | ab8500_debug_register_interrupt(line); |
572 | value &= ~(1 << bit); |
573 | |
574 | } while (value); |
575 | } |
576 | atomic_dec(&ab8500->transfer_ongoing); |
577 | return IRQ_HANDLED; |
578 | } |
579 | |
580 | static int ab8500_irq_map(struct irq_domain *d, unsigned int virq, |
581 | irq_hw_number_t hwirq) |
582 | { |
583 | struct ab8500 *ab8500 = d->host_data; |
584 | |
585 | if (!ab8500) |
586 | return -EINVAL; |
587 | |
588 | irq_set_chip_data(virq, ab8500); |
589 | irq_set_chip_and_handler(virq, &ab8500_irq_chip, |
590 | handle_simple_irq); |
591 | irq_set_nested_thread(virq, 1); |
592 | #ifdef CONFIG_ARM |
593 | set_irq_flags(virq, IRQF_VALID); |
594 | #else |
595 | irq_set_noprobe(virq); |
596 | #endif |
597 | |
598 | return 0; |
599 | } |
600 | |
601 | static struct irq_domain_ops ab8500_irq_ops = { |
602 | .map = ab8500_irq_map, |
603 | .xlate = irq_domain_xlate_twocell, |
604 | }; |
605 | |
606 | static int ab8500_irq_init(struct ab8500 *ab8500, struct device_node *np) |
607 | { |
608 | int num_irqs; |
609 | |
610 | if (is_ab9540(ab8500)) |
611 | num_irqs = AB9540_NR_IRQS; |
612 | else if (is_ab8505(ab8500)) |
613 | num_irqs = AB8505_NR_IRQS; |
614 | else |
615 | num_irqs = AB8500_NR_IRQS; |
616 | |
617 | /* If ->irq_base is zero this will give a linear mapping */ |
618 | ab8500->domain = irq_domain_add_simple(NULL, |
619 | num_irqs, ab8500->irq_base, |
620 | &ab8500_irq_ops, ab8500); |
621 | |
622 | if (!ab8500->domain) { |
623 | dev_err(ab8500->dev, "Failed to create irqdomain\n"); |
624 | return -ENOSYS; |
625 | } |
626 | |
627 | return 0; |
628 | } |
629 | |
630 | int ab8500_suspend(struct ab8500 *ab8500) |
631 | { |
632 | if (atomic_read(&ab8500->transfer_ongoing)) |
633 | return -EINVAL; |
634 | else |
635 | return 0; |
636 | } |
637 | |
638 | static struct resource ab8500_gpadc_resources[] = { |
639 | { |
640 | .name = "HW_CONV_END", |
641 | .start = AB8500_INT_GP_HW_ADC_CONV_END, |
642 | .end = AB8500_INT_GP_HW_ADC_CONV_END, |
643 | .flags = IORESOURCE_IRQ, |
644 | }, |
645 | { |
646 | .name = "SW_CONV_END", |
647 | .start = AB8500_INT_GP_SW_ADC_CONV_END, |
648 | .end = AB8500_INT_GP_SW_ADC_CONV_END, |
649 | .flags = IORESOURCE_IRQ, |
650 | }, |
651 | }; |
652 | |
653 | static struct resource ab8500_rtc_resources[] = { |
654 | { |
655 | .name = "60S", |
656 | .start = AB8500_INT_RTC_60S, |
657 | .end = AB8500_INT_RTC_60S, |
658 | .flags = IORESOURCE_IRQ, |
659 | }, |
660 | { |
661 | .name = "ALARM", |
662 | .start = AB8500_INT_RTC_ALARM, |
663 | .end = AB8500_INT_RTC_ALARM, |
664 | .flags = IORESOURCE_IRQ, |
665 | }, |
666 | }; |
667 | |
668 | static struct resource ab8500_poweronkey_db_resources[] = { |
669 | { |
670 | .name = "ONKEY_DBF", |
671 | .start = AB8500_INT_PON_KEY1DB_F, |
672 | .end = AB8500_INT_PON_KEY1DB_F, |
673 | .flags = IORESOURCE_IRQ, |
674 | }, |
675 | { |
676 | .name = "ONKEY_DBR", |
677 | .start = AB8500_INT_PON_KEY1DB_R, |
678 | .end = AB8500_INT_PON_KEY1DB_R, |
679 | .flags = IORESOURCE_IRQ, |
680 | }, |
681 | }; |
682 | |
683 | static struct resource ab8500_av_acc_detect_resources[] = { |
684 | { |
685 | .name = "ACC_DETECT_1DB_F", |
686 | .start = AB8500_INT_ACC_DETECT_1DB_F, |
687 | .end = AB8500_INT_ACC_DETECT_1DB_F, |
688 | .flags = IORESOURCE_IRQ, |
689 | }, |
690 | { |
691 | .name = "ACC_DETECT_1DB_R", |
692 | .start = AB8500_INT_ACC_DETECT_1DB_R, |
693 | .end = AB8500_INT_ACC_DETECT_1DB_R, |
694 | .flags = IORESOURCE_IRQ, |
695 | }, |
696 | { |
697 | .name = "ACC_DETECT_21DB_F", |
698 | .start = AB8500_INT_ACC_DETECT_21DB_F, |
699 | .end = AB8500_INT_ACC_DETECT_21DB_F, |
700 | .flags = IORESOURCE_IRQ, |
701 | }, |
702 | { |
703 | .name = "ACC_DETECT_21DB_R", |
704 | .start = AB8500_INT_ACC_DETECT_21DB_R, |
705 | .end = AB8500_INT_ACC_DETECT_21DB_R, |
706 | .flags = IORESOURCE_IRQ, |
707 | }, |
708 | { |
709 | .name = "ACC_DETECT_22DB_F", |
710 | .start = AB8500_INT_ACC_DETECT_22DB_F, |
711 | .end = AB8500_INT_ACC_DETECT_22DB_F, |
712 | .flags = IORESOURCE_IRQ, |
713 | }, |
714 | { |
715 | .name = "ACC_DETECT_22DB_R", |
716 | .start = AB8500_INT_ACC_DETECT_22DB_R, |
717 | .end = AB8500_INT_ACC_DETECT_22DB_R, |
718 | .flags = IORESOURCE_IRQ, |
719 | }, |
720 | }; |
721 | |
722 | static struct resource ab8500_charger_resources[] = { |
723 | { |
724 | .name = "MAIN_CH_UNPLUG_DET", |
725 | .start = AB8500_INT_MAIN_CH_UNPLUG_DET, |
726 | .end = AB8500_INT_MAIN_CH_UNPLUG_DET, |
727 | .flags = IORESOURCE_IRQ, |
728 | }, |
729 | { |
730 | .name = "MAIN_CHARGE_PLUG_DET", |
731 | .start = AB8500_INT_MAIN_CH_PLUG_DET, |
732 | .end = AB8500_INT_MAIN_CH_PLUG_DET, |
733 | .flags = IORESOURCE_IRQ, |
734 | }, |
735 | { |
736 | .name = "VBUS_DET_R", |
737 | .start = AB8500_INT_VBUS_DET_R, |
738 | .end = AB8500_INT_VBUS_DET_R, |
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 = "USB_LINK_STATUS", |
749 | .start = AB8500_INT_USB_LINK_STATUS, |
750 | .end = AB8500_INT_USB_LINK_STATUS, |
751 | .flags = IORESOURCE_IRQ, |
752 | }, |
753 | { |
754 | .name = "VBUS_OVV", |
755 | .start = AB8500_INT_VBUS_OVV, |
756 | .end = AB8500_INT_VBUS_OVV, |
757 | .flags = IORESOURCE_IRQ, |
758 | }, |
759 | { |
760 | .name = "USB_CH_TH_PROT_R", |
761 | .start = AB8500_INT_USB_CH_TH_PROT_R, |
762 | .end = AB8500_INT_USB_CH_TH_PROT_R, |
763 | .flags = IORESOURCE_IRQ, |
764 | }, |
765 | { |
766 | .name = "USB_CH_TH_PROT_F", |
767 | .start = AB8500_INT_USB_CH_TH_PROT_F, |
768 | .end = AB8500_INT_USB_CH_TH_PROT_F, |
769 | .flags = IORESOURCE_IRQ, |
770 | }, |
771 | { |
772 | .name = "MAIN_EXT_CH_NOT_OK", |
773 | .start = AB8500_INT_MAIN_EXT_CH_NOT_OK, |
774 | .end = AB8500_INT_MAIN_EXT_CH_NOT_OK, |
775 | .flags = IORESOURCE_IRQ, |
776 | }, |
777 | { |
778 | .name = "MAIN_CH_TH_PROT_R", |
779 | .start = AB8500_INT_MAIN_CH_TH_PROT_R, |
780 | .end = AB8500_INT_MAIN_CH_TH_PROT_R, |
781 | .flags = IORESOURCE_IRQ, |
782 | }, |
783 | { |
784 | .name = "MAIN_CH_TH_PROT_F", |
785 | .start = AB8500_INT_MAIN_CH_TH_PROT_F, |
786 | .end = AB8500_INT_MAIN_CH_TH_PROT_F, |
787 | .flags = IORESOURCE_IRQ, |
788 | }, |
789 | { |
790 | .name = "USB_CHARGER_NOT_OKR", |
791 | .start = AB8500_INT_USB_CHARGER_NOT_OKR, |
792 | .end = AB8500_INT_USB_CHARGER_NOT_OKR, |
793 | .flags = IORESOURCE_IRQ, |
794 | }, |
795 | { |
796 | .name = "CH_WD_EXP", |
797 | .start = AB8500_INT_CH_WD_EXP, |
798 | .end = AB8500_INT_CH_WD_EXP, |
799 | .flags = IORESOURCE_IRQ, |
800 | }, |
801 | { |
802 | .name = "VBUS_CH_DROP_END", |
803 | .start = AB8500_INT_VBUS_CH_DROP_END, |
804 | .end = AB8500_INT_VBUS_CH_DROP_END, |
805 | .flags = IORESOURCE_IRQ, |
806 | }, |
807 | }; |
808 | |
809 | static struct resource ab8500_btemp_resources[] = { |
810 | { |
811 | .name = "BAT_CTRL_INDB", |
812 | .start = AB8500_INT_BAT_CTRL_INDB, |
813 | .end = AB8500_INT_BAT_CTRL_INDB, |
814 | .flags = IORESOURCE_IRQ, |
815 | }, |
816 | { |
817 | .name = "BTEMP_LOW", |
818 | .start = AB8500_INT_BTEMP_LOW, |
819 | .end = AB8500_INT_BTEMP_LOW, |
820 | .flags = IORESOURCE_IRQ, |
821 | }, |
822 | { |
823 | .name = "BTEMP_HIGH", |
824 | .start = AB8500_INT_BTEMP_HIGH, |
825 | .end = AB8500_INT_BTEMP_HIGH, |
826 | .flags = IORESOURCE_IRQ, |
827 | }, |
828 | { |
829 | .name = "BTEMP_LOW_MEDIUM", |
830 | .start = AB8500_INT_BTEMP_LOW_MEDIUM, |
831 | .end = AB8500_INT_BTEMP_LOW_MEDIUM, |
832 | .flags = IORESOURCE_IRQ, |
833 | }, |
834 | { |
835 | .name = "BTEMP_MEDIUM_HIGH", |
836 | .start = AB8500_INT_BTEMP_MEDIUM_HIGH, |
837 | .end = AB8500_INT_BTEMP_MEDIUM_HIGH, |
838 | .flags = IORESOURCE_IRQ, |
839 | }, |
840 | }; |
841 | |
842 | static struct resource ab8500_fg_resources[] = { |
843 | { |
844 | .name = "NCONV_ACCU", |
845 | .start = AB8500_INT_CCN_CONV_ACC, |
846 | .end = AB8500_INT_CCN_CONV_ACC, |
847 | .flags = IORESOURCE_IRQ, |
848 | }, |
849 | { |
850 | .name = "BATT_OVV", |
851 | .start = AB8500_INT_BATT_OVV, |
852 | .end = AB8500_INT_BATT_OVV, |
853 | .flags = IORESOURCE_IRQ, |
854 | }, |
855 | { |
856 | .name = "LOW_BAT_F", |
857 | .start = AB8500_INT_LOW_BAT_F, |
858 | .end = AB8500_INT_LOW_BAT_F, |
859 | .flags = IORESOURCE_IRQ, |
860 | }, |
861 | { |
862 | .name = "LOW_BAT_R", |
863 | .start = AB8500_INT_LOW_BAT_R, |
864 | .end = AB8500_INT_LOW_BAT_R, |
865 | .flags = IORESOURCE_IRQ, |
866 | }, |
867 | { |
868 | .name = "CC_INT_CALIB", |
869 | .start = AB8500_INT_CC_INT_CALIB, |
870 | .end = AB8500_INT_CC_INT_CALIB, |
871 | .flags = IORESOURCE_IRQ, |
872 | }, |
873 | { |
874 | .name = "CCEOC", |
875 | .start = AB8500_INT_CCEOC, |
876 | .end = AB8500_INT_CCEOC, |
877 | .flags = IORESOURCE_IRQ, |
878 | }, |
879 | }; |
880 | |
881 | static struct resource ab8500_chargalg_resources[] = {}; |
882 | |
883 | #ifdef CONFIG_DEBUG_FS |
884 | static struct resource ab8500_debug_resources[] = { |
885 | { |
886 | .name = "IRQ_FIRST", |
887 | .start = AB8500_INT_MAIN_EXT_CH_NOT_OK, |
888 | .end = AB8500_INT_MAIN_EXT_CH_NOT_OK, |
889 | .flags = IORESOURCE_IRQ, |
890 | }, |
891 | { |
892 | .name = "IRQ_LAST", |
893 | .start = AB8500_INT_XTAL32K_KO, |
894 | .end = AB8500_INT_XTAL32K_KO, |
895 | .flags = IORESOURCE_IRQ, |
896 | }, |
897 | }; |
898 | #endif |
899 | |
900 | static struct resource ab8500_usb_resources[] = { |
901 | { |
902 | .name = "ID_WAKEUP_R", |
903 | .start = AB8500_INT_ID_WAKEUP_R, |
904 | .end = AB8500_INT_ID_WAKEUP_R, |
905 | .flags = IORESOURCE_IRQ, |
906 | }, |
907 | { |
908 | .name = "ID_WAKEUP_F", |
909 | .start = AB8500_INT_ID_WAKEUP_F, |
910 | .end = AB8500_INT_ID_WAKEUP_F, |
911 | .flags = IORESOURCE_IRQ, |
912 | }, |
913 | { |
914 | .name = "VBUS_DET_F", |
915 | .start = AB8500_INT_VBUS_DET_F, |
916 | .end = AB8500_INT_VBUS_DET_F, |
917 | .flags = IORESOURCE_IRQ, |
918 | }, |
919 | { |
920 | .name = "VBUS_DET_R", |
921 | .start = AB8500_INT_VBUS_DET_R, |
922 | .end = AB8500_INT_VBUS_DET_R, |
923 | .flags = IORESOURCE_IRQ, |
924 | }, |
925 | { |
926 | .name = "USB_LINK_STATUS", |
927 | .start = AB8500_INT_USB_LINK_STATUS, |
928 | .end = AB8500_INT_USB_LINK_STATUS, |
929 | .flags = IORESOURCE_IRQ, |
930 | }, |
931 | { |
932 | .name = "USB_ADP_PROBE_PLUG", |
933 | .start = AB8500_INT_ADP_PROBE_PLUG, |
934 | .end = AB8500_INT_ADP_PROBE_PLUG, |
935 | .flags = IORESOURCE_IRQ, |
936 | }, |
937 | { |
938 | .name = "USB_ADP_PROBE_UNPLUG", |
939 | .start = AB8500_INT_ADP_PROBE_UNPLUG, |
940 | .end = AB8500_INT_ADP_PROBE_UNPLUG, |
941 | .flags = IORESOURCE_IRQ, |
942 | }, |
943 | }; |
944 | |
945 | static struct resource ab8505_iddet_resources[] = { |
946 | { |
947 | .name = "KeyDeglitch", |
948 | .start = AB8505_INT_KEYDEGLITCH, |
949 | .end = AB8505_INT_KEYDEGLITCH, |
950 | .flags = IORESOURCE_IRQ, |
951 | }, |
952 | { |
953 | .name = "KP", |
954 | .start = AB8505_INT_KP, |
955 | .end = AB8505_INT_KP, |
956 | .flags = IORESOURCE_IRQ, |
957 | }, |
958 | { |
959 | .name = "IKP", |
960 | .start = AB8505_INT_IKP, |
961 | .end = AB8505_INT_IKP, |
962 | .flags = IORESOURCE_IRQ, |
963 | }, |
964 | { |
965 | .name = "IKR", |
966 | .start = AB8505_INT_IKR, |
967 | .end = AB8505_INT_IKR, |
968 | .flags = IORESOURCE_IRQ, |
969 | }, |
970 | { |
971 | .name = "KeyStuck", |
972 | .start = AB8505_INT_KEYSTUCK, |
973 | .end = AB8505_INT_KEYSTUCK, |
974 | .flags = IORESOURCE_IRQ, |
975 | }, |
976 | }; |
977 | |
978 | static struct resource ab8500_temp_resources[] = { |
979 | { |
980 | .name = "ABX500_TEMP_WARM", |
981 | .start = AB8500_INT_TEMP_WARM, |
982 | .end = AB8500_INT_TEMP_WARM, |
983 | .flags = IORESOURCE_IRQ, |
984 | }, |
985 | }; |
986 | |
987 | static struct mfd_cell abx500_common_devs[] = { |
988 | #ifdef CONFIG_DEBUG_FS |
989 | { |
990 | .name = "ab8500-debug", |
991 | .of_compatible = "stericsson,ab8500-debug", |
992 | .num_resources = ARRAY_SIZE(ab8500_debug_resources), |
993 | .resources = ab8500_debug_resources, |
994 | }, |
995 | #endif |
996 | { |
997 | .name = "ab8500-sysctrl", |
998 | .of_compatible = "stericsson,ab8500-sysctrl", |
999 | }, |
1000 | { |
1001 | .name = "ab8500-regulator", |
1002 | .of_compatible = "stericsson,ab8500-regulator", |
1003 | }, |
1004 | { |
1005 | .name = "abx500-clk", |
1006 | .of_compatible = "stericsson,abx500-clk", |
1007 | }, |
1008 | { |
1009 | .name = "ab8500-gpadc", |
1010 | .of_compatible = "stericsson,ab8500-gpadc", |
1011 | .num_resources = ARRAY_SIZE(ab8500_gpadc_resources), |
1012 | .resources = ab8500_gpadc_resources, |
1013 | }, |
1014 | { |
1015 | .name = "ab8500-rtc", |
1016 | .of_compatible = "stericsson,ab8500-rtc", |
1017 | .num_resources = ARRAY_SIZE(ab8500_rtc_resources), |
1018 | .resources = ab8500_rtc_resources, |
1019 | }, |
1020 | { |
1021 | .name = "ab8500-acc-det", |
1022 | .of_compatible = "stericsson,ab8500-acc-det", |
1023 | .num_resources = ARRAY_SIZE(ab8500_av_acc_detect_resources), |
1024 | .resources = ab8500_av_acc_detect_resources, |
1025 | }, |
1026 | { |
1027 | .name = "ab8500-poweron-key", |
1028 | .of_compatible = "stericsson,ab8500-poweron-key", |
1029 | .num_resources = ARRAY_SIZE(ab8500_poweronkey_db_resources), |
1030 | .resources = ab8500_poweronkey_db_resources, |
1031 | }, |
1032 | { |
1033 | .name = "ab8500-pwm", |
1034 | .of_compatible = "stericsson,ab8500-pwm", |
1035 | .id = 1, |
1036 | }, |
1037 | { |
1038 | .name = "ab8500-pwm", |
1039 | .of_compatible = "stericsson,ab8500-pwm", |
1040 | .id = 2, |
1041 | }, |
1042 | { |
1043 | .name = "ab8500-pwm", |
1044 | .of_compatible = "stericsson,ab8500-pwm", |
1045 | .id = 3, |
1046 | }, |
1047 | { |
1048 | .name = "ab8500-leds", |
1049 | .of_compatible = "stericsson,ab8500-leds", |
1050 | }, |
1051 | { |
1052 | .name = "ab8500-denc", |
1053 | .of_compatible = "stericsson,ab8500-denc", |
1054 | }, |
1055 | { |
1056 | .name = "abx500-temp", |
1057 | .of_compatible = "stericsson,abx500-temp", |
1058 | .num_resources = ARRAY_SIZE(ab8500_temp_resources), |
1059 | .resources = ab8500_temp_resources, |
1060 | }, |
1061 | }; |
1062 | |
1063 | static struct mfd_cell ab8500_bm_devs[] = { |
1064 | { |
1065 | .name = "ab8500-charger", |
1066 | .of_compatible = "stericsson,ab8500-charger", |
1067 | .num_resources = ARRAY_SIZE(ab8500_charger_resources), |
1068 | .resources = ab8500_charger_resources, |
1069 | .platform_data = &ab8500_bm_data, |
1070 | .pdata_size = sizeof(ab8500_bm_data), |
1071 | }, |
1072 | { |
1073 | .name = "ab8500-btemp", |
1074 | .of_compatible = "stericsson,ab8500-btemp", |
1075 | .num_resources = ARRAY_SIZE(ab8500_btemp_resources), |
1076 | .resources = ab8500_btemp_resources, |
1077 | .platform_data = &ab8500_bm_data, |
1078 | .pdata_size = sizeof(ab8500_bm_data), |
1079 | }, |
1080 | { |
1081 | .name = "ab8500-fg", |
1082 | .of_compatible = "stericsson,ab8500-fg", |
1083 | .num_resources = ARRAY_SIZE(ab8500_fg_resources), |
1084 | .resources = ab8500_fg_resources, |
1085 | .platform_data = &ab8500_bm_data, |
1086 | .pdata_size = sizeof(ab8500_bm_data), |
1087 | }, |
1088 | { |
1089 | .name = "ab8500-chargalg", |
1090 | .of_compatible = "stericsson,ab8500-chargalg", |
1091 | .num_resources = ARRAY_SIZE(ab8500_chargalg_resources), |
1092 | .resources = ab8500_chargalg_resources, |
1093 | .platform_data = &ab8500_bm_data, |
1094 | .pdata_size = sizeof(ab8500_bm_data), |
1095 | }, |
1096 | }; |
1097 | |
1098 | static struct mfd_cell ab8500_devs[] = { |
1099 | { |
1100 | .name = "pinctrl-ab8500", |
1101 | .of_compatible = "stericsson,ab8500-gpio", |
1102 | }, |
1103 | { |
1104 | .name = "ab8500-usb", |
1105 | .of_compatible = "stericsson,ab8500-usb", |
1106 | .num_resources = ARRAY_SIZE(ab8500_usb_resources), |
1107 | .resources = ab8500_usb_resources, |
1108 | }, |
1109 | { |
1110 | .name = "ab8500-codec", |
1111 | .of_compatible = "stericsson,ab8500-codec", |
1112 | }, |
1113 | }; |
1114 | |
1115 | static struct mfd_cell ab9540_devs[] = { |
1116 | { |
1117 | .name = "pinctrl-ab9540", |
1118 | .of_compatible = "stericsson,ab9540-gpio", |
1119 | }, |
1120 | { |
1121 | .name = "ab9540-usb", |
1122 | .num_resources = ARRAY_SIZE(ab8500_usb_resources), |
1123 | .resources = ab8500_usb_resources, |
1124 | }, |
1125 | { |
1126 | .name = "ab9540-codec", |
1127 | }, |
1128 | }; |
1129 | |
1130 | /* Device list common to ab9540 and ab8505 */ |
1131 | static struct mfd_cell ab9540_ab8505_devs[] = { |
1132 | { |
1133 | .name = "ab-iddet", |
1134 | .num_resources = ARRAY_SIZE(ab8505_iddet_resources), |
1135 | .resources = ab8505_iddet_resources, |
1136 | }, |
1137 | }; |
1138 | |
1139 | static ssize_t show_chip_id(struct device *dev, |
1140 | struct device_attribute *attr, char *buf) |
1141 | { |
1142 | struct ab8500 *ab8500; |
1143 | |
1144 | ab8500 = dev_get_drvdata(dev); |
1145 | return sprintf(buf, "%#x\n", ab8500 ? ab8500->chip_id : -EINVAL); |
1146 | } |
1147 | |
1148 | /* |
1149 | * ab8500 has switched off due to (SWITCH_OFF_STATUS): |
1150 | * 0x01 Swoff bit programming |
1151 | * 0x02 Thermal protection activation |
1152 | * 0x04 Vbat lower then BattOk falling threshold |
1153 | * 0x08 Watchdog expired |
1154 | * 0x10 Non presence of 32kHz clock |
1155 | * 0x20 Battery level lower than power on reset threshold |
1156 | * 0x40 Power on key 1 pressed longer than 10 seconds |
1157 | * 0x80 DB8500 thermal shutdown |
1158 | */ |
1159 | static ssize_t show_switch_off_status(struct device *dev, |
1160 | struct device_attribute *attr, char *buf) |
1161 | { |
1162 | int ret; |
1163 | u8 value; |
1164 | struct ab8500 *ab8500; |
1165 | |
1166 | ab8500 = dev_get_drvdata(dev); |
1167 | ret = get_register_interruptible(ab8500, AB8500_RTC, |
1168 | AB8500_SWITCH_OFF_STATUS, &value); |
1169 | if (ret < 0) |
1170 | return ret; |
1171 | return sprintf(buf, "%#x\n", value); |
1172 | } |
1173 | |
1174 | /* |
1175 | * ab8500 has turned on due to (TURN_ON_STATUS): |
1176 | * 0x01 PORnVbat |
1177 | * 0x02 PonKey1dbF |
1178 | * 0x04 PonKey2dbF |
1179 | * 0x08 RTCAlarm |
1180 | * 0x10 MainChDet |
1181 | * 0x20 VbusDet |
1182 | * 0x40 UsbIDDetect |
1183 | * 0x80 Reserved |
1184 | */ |
1185 | static ssize_t show_turn_on_status(struct device *dev, |
1186 | struct device_attribute *attr, char *buf) |
1187 | { |
1188 | int ret; |
1189 | u8 value; |
1190 | struct ab8500 *ab8500; |
1191 | |
1192 | ab8500 = dev_get_drvdata(dev); |
1193 | ret = get_register_interruptible(ab8500, AB8500_SYS_CTRL1_BLOCK, |
1194 | AB8500_TURN_ON_STATUS, &value); |
1195 | if (ret < 0) |
1196 | return ret; |
1197 | return sprintf(buf, "%#x\n", value); |
1198 | } |
1199 | |
1200 | static ssize_t show_ab9540_dbbrstn(struct device *dev, |
1201 | struct device_attribute *attr, char *buf) |
1202 | { |
1203 | struct ab8500 *ab8500; |
1204 | int ret; |
1205 | u8 value; |
1206 | |
1207 | ab8500 = dev_get_drvdata(dev); |
1208 | |
1209 | ret = get_register_interruptible(ab8500, AB8500_REGU_CTRL2, |
1210 | AB9540_MODEM_CTRL2_REG, &value); |
1211 | if (ret < 0) |
1212 | return ret; |
1213 | |
1214 | return sprintf(buf, "%d\n", |
1215 | (value & AB9540_MODEM_CTRL2_SWDBBRSTN_BIT) ? 1 : 0); |
1216 | } |
1217 | |
1218 | static ssize_t store_ab9540_dbbrstn(struct device *dev, |
1219 | struct device_attribute *attr, const char *buf, size_t count) |
1220 | { |
1221 | struct ab8500 *ab8500; |
1222 | int ret = count; |
1223 | int err; |
1224 | u8 bitvalues; |
1225 | |
1226 | ab8500 = dev_get_drvdata(dev); |
1227 | |
1228 | if (count > 0) { |
1229 | switch (buf[0]) { |
1230 | case '0': |
1231 | bitvalues = 0; |
1232 | break; |
1233 | case '1': |
1234 | bitvalues = AB9540_MODEM_CTRL2_SWDBBRSTN_BIT; |
1235 | break; |
1236 | default: |
1237 | goto exit; |
1238 | } |
1239 | |
1240 | err = mask_and_set_register_interruptible(ab8500, |
1241 | AB8500_REGU_CTRL2, AB9540_MODEM_CTRL2_REG, |
1242 | AB9540_MODEM_CTRL2_SWDBBRSTN_BIT, bitvalues); |
1243 | if (err) |
1244 | dev_info(ab8500->dev, |
1245 | "Failed to set DBBRSTN %c, err %#x\n", |
1246 | buf[0], err); |
1247 | } |
1248 | |
1249 | exit: |
1250 | return ret; |
1251 | } |
1252 | |
1253 | static DEVICE_ATTR(chip_id, S_IRUGO, show_chip_id, NULL); |
1254 | static DEVICE_ATTR(switch_off_status, S_IRUGO, show_switch_off_status, NULL); |
1255 | static DEVICE_ATTR(turn_on_status, S_IRUGO, show_turn_on_status, NULL); |
1256 | static DEVICE_ATTR(dbbrstn, S_IRUGO | S_IWUSR, |
1257 | show_ab9540_dbbrstn, store_ab9540_dbbrstn); |
1258 | |
1259 | static struct attribute *ab8500_sysfs_entries[] = { |
1260 | &dev_attr_chip_id.attr, |
1261 | &dev_attr_switch_off_status.attr, |
1262 | &dev_attr_turn_on_status.attr, |
1263 | NULL, |
1264 | }; |
1265 | |
1266 | static struct attribute *ab9540_sysfs_entries[] = { |
1267 | &dev_attr_chip_id.attr, |
1268 | &dev_attr_switch_off_status.attr, |
1269 | &dev_attr_turn_on_status.attr, |
1270 | &dev_attr_dbbrstn.attr, |
1271 | NULL, |
1272 | }; |
1273 | |
1274 | static struct attribute_group ab8500_attr_group = { |
1275 | .attrs = ab8500_sysfs_entries, |
1276 | }; |
1277 | |
1278 | static struct attribute_group ab9540_attr_group = { |
1279 | .attrs = ab9540_sysfs_entries, |
1280 | }; |
1281 | |
1282 | static int ab8500_probe(struct platform_device *pdev) |
1283 | { |
1284 | static char *switch_off_status[] = { |
1285 | "Swoff bit programming", |
1286 | "Thermal protection activation", |
1287 | "Vbat lower then BattOk falling threshold", |
1288 | "Watchdog expired", |
1289 | "Non presence of 32kHz clock", |
1290 | "Battery level lower than power on reset threshold", |
1291 | "Power on key 1 pressed longer than 10 seconds", |
1292 | "DB8500 thermal shutdown"}; |
1293 | struct ab8500_platform_data *plat = dev_get_platdata(&pdev->dev); |
1294 | const struct platform_device_id *platid = platform_get_device_id(pdev); |
1295 | enum ab8500_version version = AB8500_VERSION_UNDEFINED; |
1296 | struct device_node *np = pdev->dev.of_node; |
1297 | struct ab8500 *ab8500; |
1298 | struct resource *resource; |
1299 | int ret; |
1300 | int i; |
1301 | u8 value; |
1302 | |
1303 | ab8500 = devm_kzalloc(&pdev->dev, sizeof *ab8500, GFP_KERNEL); |
1304 | if (!ab8500) |
1305 | return -ENOMEM; |
1306 | |
1307 | if (plat) |
1308 | ab8500->irq_base = plat->irq_base; |
1309 | |
1310 | ab8500->dev = &pdev->dev; |
1311 | |
1312 | resource = platform_get_resource(pdev, IORESOURCE_IRQ, 0); |
1313 | if (!resource) |
1314 | return -ENODEV; |
1315 | |
1316 | ab8500->irq = resource->start; |
1317 | |
1318 | ab8500->read = ab8500_prcmu_read; |
1319 | ab8500->write = ab8500_prcmu_write; |
1320 | ab8500->write_masked = ab8500_prcmu_write_masked; |
1321 | |
1322 | mutex_init(&ab8500->lock); |
1323 | mutex_init(&ab8500->irq_lock); |
1324 | atomic_set(&ab8500->transfer_ongoing, 0); |
1325 | |
1326 | platform_set_drvdata(pdev, ab8500); |
1327 | |
1328 | if (platid) |
1329 | version = platid->driver_data; |
1330 | |
1331 | if (version != AB8500_VERSION_UNDEFINED) |
1332 | ab8500->version = version; |
1333 | else { |
1334 | ret = get_register_interruptible(ab8500, AB8500_MISC, |
1335 | AB8500_IC_NAME_REG, &value); |
1336 | if (ret < 0) |
1337 | return ret; |
1338 | |
1339 | ab8500->version = value; |
1340 | } |
1341 | |
1342 | ret = get_register_interruptible(ab8500, AB8500_MISC, |
1343 | AB8500_REV_REG, &value); |
1344 | if (ret < 0) |
1345 | return ret; |
1346 | |
1347 | ab8500->chip_id = value; |
1348 | |
1349 | dev_info(ab8500->dev, "detected chip, %s rev. %1x.%1x\n", |
1350 | ab8500_version_str[ab8500->version], |
1351 | ab8500->chip_id >> 4, |
1352 | ab8500->chip_id & 0x0F); |
1353 | |
1354 | /* Configure AB8500 or AB9540 IRQ */ |
1355 | if (is_ab9540(ab8500) || is_ab8505(ab8500)) { |
1356 | ab8500->mask_size = AB9540_NUM_IRQ_REGS; |
1357 | ab8500->irq_reg_offset = ab9540_irq_regoffset; |
1358 | } else { |
1359 | ab8500->mask_size = AB8500_NUM_IRQ_REGS; |
1360 | ab8500->irq_reg_offset = ab8500_irq_regoffset; |
1361 | } |
1362 | ab8500->mask = devm_kzalloc(&pdev->dev, ab8500->mask_size, GFP_KERNEL); |
1363 | if (!ab8500->mask) |
1364 | return -ENOMEM; |
1365 | ab8500->oldmask = devm_kzalloc(&pdev->dev, ab8500->mask_size, GFP_KERNEL); |
1366 | if (!ab8500->oldmask) |
1367 | return -ENOMEM; |
1368 | |
1369 | /* |
1370 | * ab8500 has switched off due to (SWITCH_OFF_STATUS): |
1371 | * 0x01 Swoff bit programming |
1372 | * 0x02 Thermal protection activation |
1373 | * 0x04 Vbat lower then BattOk falling threshold |
1374 | * 0x08 Watchdog expired |
1375 | * 0x10 Non presence of 32kHz clock |
1376 | * 0x20 Battery level lower than power on reset threshold |
1377 | * 0x40 Power on key 1 pressed longer than 10 seconds |
1378 | * 0x80 DB8500 thermal shutdown |
1379 | */ |
1380 | |
1381 | ret = get_register_interruptible(ab8500, AB8500_RTC, |
1382 | AB8500_SWITCH_OFF_STATUS, &value); |
1383 | if (ret < 0) |
1384 | return ret; |
1385 | dev_info(ab8500->dev, "switch off cause(s) (%#x): ", value); |
1386 | |
1387 | if (value) { |
1388 | for (i = 0; i < ARRAY_SIZE(switch_off_status); i++) { |
1389 | if (value & 1) |
1390 | printk(KERN_CONT " \"%s\"", |
1391 | switch_off_status[i]); |
1392 | value = value >> 1; |
1393 | |
1394 | } |
1395 | printk(KERN_CONT "\n"); |
1396 | } else { |
1397 | printk(KERN_CONT " None\n"); |
1398 | } |
1399 | |
1400 | if (plat && plat->init) |
1401 | plat->init(ab8500); |
1402 | |
1403 | /* Clear and mask all interrupts */ |
1404 | for (i = 0; i < ab8500->mask_size; i++) { |
1405 | /* |
1406 | * Interrupt register 12 doesn't exist prior to AB8500 version |
1407 | * 2.0 |
1408 | */ |
1409 | if (ab8500->irq_reg_offset[i] == 11 && |
1410 | is_ab8500_1p1_or_earlier(ab8500)) |
1411 | continue; |
1412 | |
1413 | get_register_interruptible(ab8500, AB8500_INTERRUPT, |
1414 | AB8500_IT_LATCH1_REG + ab8500->irq_reg_offset[i], |
1415 | &value); |
1416 | set_register_interruptible(ab8500, AB8500_INTERRUPT, |
1417 | AB8500_IT_MASK1_REG + ab8500->irq_reg_offset[i], 0xff); |
1418 | } |
1419 | |
1420 | ret = abx500_register_ops(ab8500->dev, &ab8500_ops); |
1421 | if (ret) |
1422 | return ret; |
1423 | |
1424 | for (i = 0; i < ab8500->mask_size; i++) |
1425 | ab8500->mask[i] = ab8500->oldmask[i] = 0xff; |
1426 | |
1427 | ret = ab8500_irq_init(ab8500, np); |
1428 | if (ret) |
1429 | return ret; |
1430 | |
1431 | /* Activate this feature only in ab9540 */ |
1432 | /* till tests are done on ab8500 1p2 or later*/ |
1433 | if (is_ab9540(ab8500)) { |
1434 | ret = devm_request_threaded_irq(&pdev->dev, ab8500->irq, NULL, |
1435 | ab8500_hierarchical_irq, |
1436 | IRQF_ONESHOT | IRQF_NO_SUSPEND, |
1437 | "ab8500", ab8500); |
1438 | } |
1439 | else { |
1440 | ret = devm_request_threaded_irq(&pdev->dev, ab8500->irq, NULL, |
1441 | ab8500_irq, |
1442 | IRQF_ONESHOT | IRQF_NO_SUSPEND, |
1443 | "ab8500", ab8500); |
1444 | if (ret) |
1445 | return ret; |
1446 | } |
1447 | |
1448 | ret = mfd_add_devices(ab8500->dev, 0, abx500_common_devs, |
1449 | ARRAY_SIZE(abx500_common_devs), NULL, |
1450 | ab8500->irq_base, ab8500->domain); |
1451 | if (ret) |
1452 | return ret; |
1453 | |
1454 | if (is_ab9540(ab8500)) |
1455 | ret = mfd_add_devices(ab8500->dev, 0, ab9540_devs, |
1456 | ARRAY_SIZE(ab9540_devs), NULL, |
1457 | ab8500->irq_base, ab8500->domain); |
1458 | else |
1459 | ret = mfd_add_devices(ab8500->dev, 0, ab8500_devs, |
1460 | ARRAY_SIZE(ab8500_devs), NULL, |
1461 | ab8500->irq_base, ab8500->domain); |
1462 | if (ret) |
1463 | return ret; |
1464 | |
1465 | if (is_ab9540(ab8500) || is_ab8505(ab8500)) |
1466 | ret = mfd_add_devices(ab8500->dev, 0, ab9540_ab8505_devs, |
1467 | ARRAY_SIZE(ab9540_ab8505_devs), NULL, |
1468 | ab8500->irq_base, ab8500->domain); |
1469 | if (ret) |
1470 | return ret; |
1471 | |
1472 | if (!no_bm) { |
1473 | /* Add battery management devices */ |
1474 | ret = mfd_add_devices(ab8500->dev, 0, ab8500_bm_devs, |
1475 | ARRAY_SIZE(ab8500_bm_devs), NULL, |
1476 | ab8500->irq_base, ab8500->domain); |
1477 | if (ret) |
1478 | dev_err(ab8500->dev, "error adding bm devices\n"); |
1479 | } |
1480 | |
1481 | if (is_ab9540(ab8500)) |
1482 | ret = sysfs_create_group(&ab8500->dev->kobj, |
1483 | &ab9540_attr_group); |
1484 | else |
1485 | ret = sysfs_create_group(&ab8500->dev->kobj, |
1486 | &ab8500_attr_group); |
1487 | if (ret) |
1488 | dev_err(ab8500->dev, "error creating sysfs entries\n"); |
1489 | |
1490 | return ret; |
1491 | } |
1492 | |
1493 | static int ab8500_remove(struct platform_device *pdev) |
1494 | { |
1495 | struct ab8500 *ab8500 = platform_get_drvdata(pdev); |
1496 | |
1497 | if (is_ab9540(ab8500)) |
1498 | sysfs_remove_group(&ab8500->dev->kobj, &ab9540_attr_group); |
1499 | else |
1500 | sysfs_remove_group(&ab8500->dev->kobj, &ab8500_attr_group); |
1501 | |
1502 | mfd_remove_devices(ab8500->dev); |
1503 | |
1504 | return 0; |
1505 | } |
1506 | |
1507 | static const struct platform_device_id ab8500_id[] = { |
1508 | { "ab8500-core", AB8500_VERSION_AB8500 }, |
1509 | { "ab8505-i2c", AB8500_VERSION_AB8505 }, |
1510 | { "ab9540-i2c", AB8500_VERSION_AB9540 }, |
1511 | { "ab8540-i2c", AB8500_VERSION_AB8540 }, |
1512 | { } |
1513 | }; |
1514 | |
1515 | static struct platform_driver ab8500_core_driver = { |
1516 | .driver = { |
1517 | .name = "ab8500-core", |
1518 | .owner = THIS_MODULE, |
1519 | }, |
1520 | .probe = ab8500_probe, |
1521 | .remove = ab8500_remove, |
1522 | .id_table = ab8500_id, |
1523 | }; |
1524 | |
1525 | static int __init ab8500_core_init(void) |
1526 | { |
1527 | return platform_driver_register(&ab8500_core_driver); |
1528 | } |
1529 | |
1530 | static void __exit ab8500_core_exit(void) |
1531 | { |
1532 | platform_driver_unregister(&ab8500_core_driver); |
1533 | } |
1534 | core_initcall(ab8500_core_init); |
1535 | module_exit(ab8500_core_exit); |
1536 | |
1537 | MODULE_AUTHOR("Mattias Wallin, Srinidhi Kasagar, Rabin Vincent"); |
1538 | MODULE_DESCRIPTION("AB8500 MFD core"); |
1539 | MODULE_LICENSE("GPL v2"); |
1540 |
Branches:
ben-wpan
ben-wpan-stefan
javiroman/ks7010
jz-2.6.34
jz-2.6.34-rc5
jz-2.6.34-rc6
jz-2.6.34-rc7
jz-2.6.35
jz-2.6.36
jz-2.6.37
jz-2.6.38
jz-2.6.39
jz-3.0
jz-3.1
jz-3.11
jz-3.12
jz-3.13
jz-3.15
jz-3.16
jz-3.18-dt
jz-3.2
jz-3.3
jz-3.4
jz-3.5
jz-3.6
jz-3.6-rc2-pwm
jz-3.9
jz-3.9-clk
jz-3.9-rc8
jz47xx
jz47xx-2.6.38
master
Tags:
od-2011-09-04
od-2011-09-18
v2.6.34-rc5
v2.6.34-rc6
v2.6.34-rc7
v3.9