blob: 07bba8b3fe8f4ffb10040d84c20cd37a935a599f [file] [log] [blame]
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 */
12
13#include <linux/interrupt.h>
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070014#include <linux/slab.h>
15#include <linux/ratelimit.h>
Anirudh Ghayalc8051a82011-11-17 09:28:24 +053016#include <linux/gpio.h>
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070017#include <linux/mfd/core.h>
Anirudh Ghayalc8051a82011-11-17 09:28:24 +053018#include <linux/msm_ssbi.h>
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070019#include <linux/mfd/pmic8901.h>
20#include <linux/platform_device.h>
21#include <linux/debugfs.h>
22
23/* PMIC8901 Revision */
24#define SSBI_REG_REV 0x002 /* PMIC4 revision */
25
26/* PMIC8901 IRQ */
27#define SSBI_REG_ADDR_IRQ_BASE 0xD5
28
29#define SSBI_REG_ADDR_IRQ_ROOT (SSBI_REG_ADDR_IRQ_BASE + 0)
30#define SSBI_REG_ADDR_IRQ_M_STATUS1 (SSBI_REG_ADDR_IRQ_BASE + 1)
31#define SSBI_REG_ADDR_IRQ_M_STATUS2 (SSBI_REG_ADDR_IRQ_BASE + 2)
32#define SSBI_REG_ADDR_IRQ_M_STATUS3 (SSBI_REG_ADDR_IRQ_BASE + 3)
33#define SSBI_REG_ADDR_IRQ_M_STATUS4 (SSBI_REG_ADDR_IRQ_BASE + 4)
34#define SSBI_REG_ADDR_IRQ_BLK_SEL (SSBI_REG_ADDR_IRQ_BASE + 5)
35#define SSBI_REG_ADDR_IRQ_IT_STATUS (SSBI_REG_ADDR_IRQ_BASE + 6)
36#define SSBI_REG_ADDR_IRQ_CONFIG (SSBI_REG_ADDR_IRQ_BASE + 7)
37#define SSBI_REG_ADDR_IRQ_RT_STATUS (SSBI_REG_ADDR_IRQ_BASE + 8)
38
39#define PM8901_IRQF_LVL_SEL 0x01 /* level select */
40#define PM8901_IRQF_MASK_FE 0x02 /* mask falling edge */
41#define PM8901_IRQF_MASK_RE 0x04 /* mask rising edge */
42#define PM8901_IRQF_CLR 0x08 /* clear interrupt */
43#define PM8901_IRQF_BITS_MASK 0x70
44#define PM8901_IRQF_BITS_SHIFT 4
45#define PM8901_IRQF_WRITE 0x80
46
47#define PM8901_IRQF_MASK_ALL (PM8901_IRQF_MASK_FE | \
48 PM8901_IRQF_MASK_RE)
49#define PM8901_IRQF_W_C_M (PM8901_IRQF_WRITE | \
50 PM8901_IRQF_CLR | \
51 PM8901_IRQF_MASK_ALL)
52
53#define MAX_PM_IRQ 72
54#define MAX_PM_BLOCKS (MAX_PM_IRQ / 8 + 1)
55#define MAX_PM_MASTERS (MAX_PM_BLOCKS / 8 + 1)
56
57#define MPP_IRQ_BLOCK 1
58
59/* FTS regulator PMR registers */
60#define SSBI_REG_ADDR_S1_PMR (0xA7)
61#define SSBI_REG_ADDR_S2_PMR (0xA8)
62#define SSBI_REG_ADDR_S3_PMR (0xA9)
63#define SSBI_REG_ADDR_S4_PMR (0xAA)
64
65#define REGULATOR_PMR_STATE_MASK 0x60
66#define REGULATOR_PMR_STATE_OFF 0x20
67
68struct pm8901_chip {
69 struct pm8901_platform_data pdata;
Anirudh Ghayalc8051a82011-11-17 09:28:24 +053070 struct device *dev;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070071
72 u8 irqs_allowed[MAX_PM_BLOCKS];
73 u8 blocks_allowed[MAX_PM_MASTERS];
74 u8 masters_allowed;
75 int pm_max_irq;
76 int pm_max_blocks;
77 int pm_max_masters;
78
79 u8 config[MAX_PM_IRQ];
80 u8 wake_enable[MAX_PM_IRQ];
81 u16 count_wakeable;
82
83 u8 revision;
84
85 spinlock_t pm_lock;
86};
87
88#if defined(CONFIG_DEBUG_FS)
89struct pm8901_dbg_device {
90 struct mutex dbg_mutex;
91 struct pm8901_chip *pm_chip;
92 struct dentry *dent;
93 int addr;
94};
95
96static struct pm8901_dbg_device *pmic_dbg_device;
97#endif
98
99static struct pm8901_chip *pmic_chip;
100
101/* Helper Functions */
102DEFINE_RATELIMIT_STATE(pm8901_msg_ratelimit, 60 * HZ, 10);
103
104static inline int pm8901_can_print(void)
105{
106 return __ratelimit(&pm8901_msg_ratelimit);
107}
108
109static inline int
Anirudh Ghayalc8051a82011-11-17 09:28:24 +0530110ssbi_read(struct device *dev, u16 addr, u8 *buf, size_t len)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700111{
Anirudh Ghayalc8051a82011-11-17 09:28:24 +0530112 return msm_ssbi_read(dev->parent, addr, buf, len);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700113}
114
115static inline int
Anirudh Ghayalc8051a82011-11-17 09:28:24 +0530116ssbi_write(struct device *dev, u16 addr, u8 *buf, size_t len)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700117{
Anirudh Ghayalc8051a82011-11-17 09:28:24 +0530118 return msm_ssbi_write(dev->parent, addr, buf, len);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700119}
120
121/* External APIs */
122int pm8901_rev(struct pm8901_chip *chip)
123{
124 if (chip == NULL) {
125 if (pmic_chip != NULL)
126 return pmic_chip->revision;
127 else
128 return -EINVAL;
129 }
130
131 return chip->revision;
132}
133EXPORT_SYMBOL(pm8901_rev);
134
135int pm8901_read(struct pm8901_chip *chip, u16 addr, u8 *values,
136 unsigned int len)
137{
138 if (chip == NULL)
139 return -EINVAL;
140
141 return ssbi_read(chip->dev, addr, values, len);
142}
143EXPORT_SYMBOL(pm8901_read);
144
145int pm8901_write(struct pm8901_chip *chip, u16 addr, u8 *values,
146 unsigned int len)
147{
148 if (chip == NULL)
149 return -EINVAL;
150
151 return ssbi_write(chip->dev, addr, values, len);
152}
153EXPORT_SYMBOL(pm8901_write);
154
155int pm8901_irq_get_rt_status(struct pm8901_chip *chip, int irq)
156{
157 int rc;
158 u8 block, bits, bit;
159 unsigned long irqsave;
160
161 if (chip == NULL || irq < chip->pdata.irq_base ||
162 irq >= chip->pdata.irq_base + MAX_PM_IRQ)
163 return -EINVAL;
164
165 irq -= chip->pdata.irq_base;
166
167 block = irq / 8;
168 bit = irq % 8;
169
170 spin_lock_irqsave(&chip->pm_lock, irqsave);
171
172 rc = ssbi_write(chip->dev, SSBI_REG_ADDR_IRQ_BLK_SEL, &block, 1);
173 if (rc) {
174 pr_err("%s: FAIL ssbi_write(): rc=%d (Select Block)\n",
175 __func__, rc);
176 goto bail_out;
177 }
178
179 rc = ssbi_read(chip->dev, SSBI_REG_ADDR_IRQ_RT_STATUS, &bits, 1);
180 if (rc) {
181 pr_err("%s: FAIL ssbi_read(): rc=%d (Read RT Status)\n",
182 __func__, rc);
183 goto bail_out;
184 }
185
186 rc = (bits & (1 << bit)) ? 1 : 0;
187
188bail_out:
189 spin_unlock_irqrestore(&chip->pm_lock, irqsave);
190
191 return rc;
192}
193EXPORT_SYMBOL(pm8901_irq_get_rt_status);
194
195int pm8901_reset_pwr_off(int reset)
196{
197 int rc = 0, i;
198 u8 pmr;
199 u8 pmr_addr[4] = {
200 SSBI_REG_ADDR_S2_PMR,
201 SSBI_REG_ADDR_S3_PMR,
202 SSBI_REG_ADDR_S4_PMR,
203 SSBI_REG_ADDR_S1_PMR,
204 };
205
206 if (pmic_chip == NULL)
207 return -ENODEV;
208
209 /* Turn off regulators S1, S2, S3, S4 when shutting down. */
210 if (!reset) {
211 for (i = 0; i < 4; i++) {
212 rc = ssbi_read(pmic_chip->dev, pmr_addr[i], &pmr, 1);
213 if (rc) {
214 pr_err("%s: FAIL ssbi_read(0x%x): rc=%d\n",
215 __func__, pmr_addr[i], rc);
216 goto get_out;
217 }
218
219 pmr &= ~REGULATOR_PMR_STATE_MASK;
220 pmr |= REGULATOR_PMR_STATE_OFF;
221
222 rc = ssbi_write(pmic_chip->dev, pmr_addr[i], &pmr, 1);
223 if (rc) {
224 pr_err("%s: FAIL ssbi_write(0x%x)=0x%x: rc=%d"
225 "\n", __func__, pmr_addr[i], pmr, rc);
226 goto get_out;
227 }
228 }
229 }
230
231get_out:
232 return rc;
233}
234EXPORT_SYMBOL(pm8901_reset_pwr_off);
235
236/* Internal functions */
237static inline int
238pm8901_config_irq(struct pm8901_chip *chip, u8 *bp, u8 *cp)
239{
240 int rc;
241
242 rc = ssbi_write(chip->dev, SSBI_REG_ADDR_IRQ_BLK_SEL, bp, 1);
243 if (rc) {
244 pr_err("%s: ssbi_write: rc=%d (Select block)\n",
245 __func__, rc);
246 goto bail_out;
247 }
248
249 rc = ssbi_write(chip->dev, SSBI_REG_ADDR_IRQ_CONFIG, cp, 1);
250 if (rc)
251 pr_err("%s: ssbi_write: rc=%d (Configure IRQ)\n",
252 __func__, rc);
253
254bail_out:
255 return rc;
256}
257
258static void pm8901_irq_mask(struct irq_data *d)
259{
260 int master, irq_bit;
261 struct pm8901_chip *chip = irq_data_get_irq_handler_data(d);
262 u8 block, config;
263 unsigned int irq = d->irq;
264
265 irq -= chip->pdata.irq_base;
266 block = irq / 8;
267 master = block / 8;
268 irq_bit = irq % 8;
269
270 chip->irqs_allowed[block] &= ~(1 << irq_bit);
271 if (!chip->irqs_allowed[block]) {
272 chip->blocks_allowed[master] &= ~(1 << (block % 8));
273
274 if (!chip->blocks_allowed[master])
275 chip->masters_allowed &= ~(1 << master);
276 }
277
278 config = PM8901_IRQF_WRITE | chip->config[irq] |
279 PM8901_IRQF_MASK_FE | PM8901_IRQF_MASK_RE;
280 pm8901_config_irq(chip, &block, &config);
281}
282
283static void pm8901_irq_unmask(struct irq_data *d)
284{
285 int master, irq_bit;
286 struct pm8901_chip *chip = irq_data_get_irq_handler_data(d);
287 u8 block, config, old_irqs_allowed, old_blocks_allowed;
288 unsigned int irq = d->irq;
289
290 irq -= chip->pdata.irq_base;
291 block = irq / 8;
292 master = block / 8;
293 irq_bit = irq % 8;
294
295 old_irqs_allowed = chip->irqs_allowed[block];
296 chip->irqs_allowed[block] |= 1 << irq_bit;
297 if (!old_irqs_allowed) {
298 master = block / 8;
299
300 old_blocks_allowed = chip->blocks_allowed[master];
301 chip->blocks_allowed[master] |= 1 << (block % 8);
302
303 if (!old_blocks_allowed)
304 chip->masters_allowed |= 1 << master;
305 }
306
307 config = PM8901_IRQF_WRITE | chip->config[irq];
308 pm8901_config_irq(chip, &block, &config);
309}
310
311static void pm8901_irq_ack(struct irq_data *d)
312{
313 struct pm8901_chip *chip = irq_data_get_irq_handler_data(d);
314 u8 block, config;
315 unsigned int irq = d->irq;
316
317 irq -= chip->pdata.irq_base;
318 block = irq / 8;
319
320 config = PM8901_IRQF_WRITE | chip->config[irq] | PM8901_IRQF_CLR;
321 pm8901_config_irq(chip, &block, &config);
322}
323
324static int pm8901_irq_set_type(struct irq_data *d, unsigned int flow_type)
325{
326 int master, irq_bit;
327 struct pm8901_chip *chip = irq_data_get_irq_handler_data(d);
328 u8 block, config;
329 unsigned int irq = d->irq;
330
331 irq -= chip->pdata.irq_base;
332 if (irq > chip->pm_max_irq) {
333 chip->pm_max_irq = irq;
334 chip->pm_max_blocks =
335 chip->pm_max_irq / 8 + 1;
336 chip->pm_max_masters =
337 chip->pm_max_blocks / 8 + 1;
338 }
339 block = irq / 8;
340 master = block / 8;
341 irq_bit = irq % 8;
342
343 chip->config[irq] = (irq_bit << PM8901_IRQF_BITS_SHIFT) |
344 PM8901_IRQF_MASK_RE | PM8901_IRQF_MASK_FE;
345 if (flow_type & (IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING)) {
346 if (flow_type & IRQF_TRIGGER_RISING)
347 chip->config[irq] &= ~PM8901_IRQF_MASK_RE;
348 if (flow_type & IRQF_TRIGGER_FALLING)
349 chip->config[irq] &= ~PM8901_IRQF_MASK_FE;
350 } else {
351 chip->config[irq] |= PM8901_IRQF_LVL_SEL;
352
353 if (flow_type & IRQF_TRIGGER_HIGH)
354 chip->config[irq] &= ~PM8901_IRQF_MASK_RE;
355 else
356 chip->config[irq] &= ~PM8901_IRQF_MASK_FE;
357 }
358
359 config = PM8901_IRQF_WRITE | chip->config[irq] | PM8901_IRQF_CLR;
360 return pm8901_config_irq(chip, &block, &config);
361}
362
363static int pm8901_irq_set_wake(struct irq_data *d, unsigned int on)
364{
365 struct pm8901_chip *chip = irq_data_get_irq_handler_data(d);
366 unsigned int irq = d->irq;
367
368 irq -= chip->pdata.irq_base;
369 if (on) {
370 if (!chip->wake_enable[irq]) {
371 chip->wake_enable[irq] = 1;
372 chip->count_wakeable++;
373 }
374 } else {
375 if (chip->wake_enable[irq]) {
376 chip->wake_enable[irq] = 0;
377 chip->count_wakeable--;
378 }
379 }
380
381 return 0;
382}
383
384static inline int
385pm8901_read_root(struct pm8901_chip *chip, u8 *rp)
386{
387 int rc;
388
389 rc = ssbi_read(chip->dev, SSBI_REG_ADDR_IRQ_ROOT, rp, 1);
390 if (rc) {
391 pr_err("%s: FAIL ssbi_read(): rc=%d (Read Root)\n",
392 __func__, rc);
393 *rp = 0;
394 }
395
396 return rc;
397}
398
399static inline int
400pm8901_read_master(struct pm8901_chip *chip, u8 m, u8 *bp)
401{
402 int rc;
403
404 rc = ssbi_read(chip->dev, SSBI_REG_ADDR_IRQ_M_STATUS1 + m, bp, 1);
405 if (rc) {
406 pr_err("%s: FAIL ssbi_read(): rc=%d (Read Master)\n",
407 __func__, rc);
408 *bp = 0;
409 }
410
411 return rc;
412}
413
414static inline int
415pm8901_read_block(struct pm8901_chip *chip, u8 *bp, u8 *ip)
416{
417 int rc;
418
419 rc = ssbi_write(chip->dev, SSBI_REG_ADDR_IRQ_BLK_SEL, bp, 1);
420 if (rc) {
421 pr_err("%s: FAIL ssbi_write(): rc=%d (Select Block)\n",
422 __func__, rc);
423 *bp = 0;
424 goto bail_out;
425 }
426
427 rc = ssbi_read(chip->dev, SSBI_REG_ADDR_IRQ_IT_STATUS, ip, 1);
428 if (rc)
429 pr_err("%s: FAIL ssbi_read(): rc=%d (Read Status)\n",
430 __func__, rc);
431
432bail_out:
433 return rc;
434}
435
436static irqreturn_t pm8901_isr_thread(int irq_requested, void *data)
437{
438 struct pm8901_chip *chip = data;
439 int i, j, k;
440 u8 root, block, config, bits;
441 u8 blocks[MAX_PM_MASTERS];
442 int masters = 0, irq, handled = 0, spurious = 0;
443 u16 irqs_to_handle[MAX_PM_IRQ];
444 unsigned long irqsave;
445
446 spin_lock_irqsave(&chip->pm_lock, irqsave);
447
448 /* Read root for masters */
449 if (pm8901_read_root(chip, &root))
450 goto bail_out;
451
452 masters = root >> 1;
453
454 if (!(masters & chip->masters_allowed) ||
455 (masters & ~chip->masters_allowed)) {
456 spurious = 1000000;
457 }
458
459 /* Read allowed masters for blocks. */
460 for (i = 0; i < chip->pm_max_masters; i++) {
461 if (masters & (1 << i)) {
462 if (pm8901_read_master(chip, i, &blocks[i]))
463 goto bail_out;
464
465 if (!blocks[i]) {
466 if (pm8901_can_print())
467 pr_err("%s: Spurious master: %d "
468 "(blocks=0)", __func__, i);
469 spurious += 10000;
470 }
471 } else
472 blocks[i] = 0;
473 }
474
475 /* Select block, read status and call isr */
476 for (i = 0; i < chip->pm_max_masters; i++) {
477 if (!blocks[i])
478 continue;
479
480 for (j = 0; j < 8; j++) {
481 if (!(blocks[i] & (1 << j)))
482 continue;
483
484 block = i * 8 + j; /* block # */
485 if (pm8901_read_block(chip, &block, &bits))
486 goto bail_out;
487
488 if (!bits) {
489 if (pm8901_can_print())
490 pr_err("%s: Spurious block: "
491 "[master, block]=[%d, %d] "
492 "(bits=0)\n", __func__, i, j);
493 spurious += 100;
494 continue;
495 }
496
497 /* Check IRQ bits */
498 for (k = 0; k < 8; k++) {
499 if (!(bits & (1 << k)))
500 continue;
501
502 /* Check spurious interrupts */
503 if (((1 << i) & chip->masters_allowed) &&
504 (blocks[i] & chip->blocks_allowed[i]) &&
505 (bits & chip->irqs_allowed[block])) {
506
507 /* Found one */
508 irq = block * 8 + k;
509 irqs_to_handle[handled] = irq +
510 chip->pdata.irq_base;
511 handled++;
512 } else {
513 /* Clear and mask wrong one */
514 config = PM8901_IRQF_W_C_M |
515 (k < PM8901_IRQF_BITS_SHIFT);
516
517 pm8901_config_irq(chip,
518 &block, &config);
519
520 if (pm8901_can_print())
521 pr_err("%s: Spurious IRQ: "
522 "[master, block, bit]="
523 "[%d, %d (%d), %d]\n",
524 __func__,
525 i, j, block, k);
526 spurious++;
527 }
528 }
529 }
530
531 }
532
533bail_out:
534
535 spin_unlock_irqrestore(&chip->pm_lock, irqsave);
536
537 for (i = 0; i < handled; i++)
538 generic_handle_irq(irqs_to_handle[i]);
539
540 if (spurious) {
541 if (!pm8901_can_print())
542 return IRQ_HANDLED;
543
544 pr_err("%s: spurious = %d (handled = %d)\n",
545 __func__, spurious, handled);
546 pr_err(" root = 0x%x (masters_allowed<<1 = 0x%x)\n",
547 root, chip->masters_allowed << 1);
548 for (i = 0; i < chip->pm_max_masters; i++) {
549 if (masters & (1 << i))
550 pr_err(" blocks[%d]=0x%x, "
551 "allowed[%d]=0x%x\n",
552 i, blocks[i],
553 i, chip->blocks_allowed[i]);
554 }
555 }
556
557 return IRQ_HANDLED;
558}
559
560#if defined(CONFIG_DEBUG_FS)
561
562static int check_addr(int addr, const char *func_name)
563{
564 if (addr < 0 || addr > 0x3FF) {
565 pr_err("%s: PMIC 8901 register address is invalid: %d\n",
566 func_name, addr);
567 return -EINVAL;
568 }
569 return 0;
570}
571
572static int data_set(void *data, u64 val)
573{
574 struct pm8901_dbg_device *dbgdev = data;
575 u8 reg = val;
576 int rc;
577
578 mutex_lock(&dbgdev->dbg_mutex);
579
580 rc = check_addr(dbgdev->addr, __func__);
581 if (rc)
582 goto done;
583
584 rc = pm8901_write(dbgdev->pm_chip, dbgdev->addr, &reg, 1);
585
586 if (rc)
587 pr_err("%s: FAIL pm8901_write(0x%03X)=0x%02X: rc=%d\n",
588 __func__, dbgdev->addr, reg, rc);
589done:
590 mutex_unlock(&dbgdev->dbg_mutex);
591 return rc;
592}
593
594static int data_get(void *data, u64 *val)
595{
596 struct pm8901_dbg_device *dbgdev = data;
597 int rc;
598 u8 reg;
599
600 mutex_lock(&dbgdev->dbg_mutex);
601
602 rc = check_addr(dbgdev->addr, __func__);
603 if (rc)
604 goto done;
605
606 rc = pm8901_read(dbgdev->pm_chip, dbgdev->addr, &reg, 1);
607
608 if (rc) {
609 pr_err("%s: FAIL pm8901_read(0x%03X)=0x%02X: rc=%d\n",
610 __func__, dbgdev->addr, reg, rc);
611 goto done;
612 }
613
614 *val = reg;
615done:
616 mutex_unlock(&dbgdev->dbg_mutex);
617 return rc;
618}
619
620DEFINE_SIMPLE_ATTRIBUTE(dbg_data_fops, data_get, data_set, "0x%02llX\n");
621
622static int addr_set(void *data, u64 val)
623{
624 struct pm8901_dbg_device *dbgdev = data;
625 int rc;
626
627 rc = check_addr(val, __func__);
628 if (rc)
629 return rc;
630
631 mutex_lock(&dbgdev->dbg_mutex);
632 dbgdev->addr = val;
633 mutex_unlock(&dbgdev->dbg_mutex);
634
635 return 0;
636}
637
638static int addr_get(void *data, u64 *val)
639{
640 struct pm8901_dbg_device *dbgdev = data;
641 int rc;
642
643 mutex_lock(&dbgdev->dbg_mutex);
644
645 rc = check_addr(dbgdev->addr, __func__);
646 if (rc) {
647 mutex_unlock(&dbgdev->dbg_mutex);
648 return rc;
649 }
650 *val = dbgdev->addr;
651
652 mutex_unlock(&dbgdev->dbg_mutex);
653
654 return 0;
655}
656
657DEFINE_SIMPLE_ATTRIBUTE(dbg_addr_fops, addr_get, addr_set, "0x%03llX\n");
658
659static int __devinit pmic8901_dbg_probe(struct pm8901_chip *chip)
660{
661 struct pm8901_dbg_device *dbgdev;
662 struct dentry *dent;
663 struct dentry *temp;
Jay Chokshi898340f2011-09-29 17:19:31 -0700664 int rc;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700665
666 if (chip == NULL) {
667 pr_err("%s: no parent data passed in.\n", __func__);
668 return -EINVAL;
669 }
670
671 dbgdev = kzalloc(sizeof *dbgdev, GFP_KERNEL);
672 if (dbgdev == NULL) {
673 pr_err("%s: kzalloc() failed.\n", __func__);
674 return -ENOMEM;
675 }
676
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700677 dbgdev->pm_chip = chip;
678 dbgdev->addr = -1;
679
680 dent = debugfs_create_dir("pm8901-dbg", NULL);
681 if (dent == NULL || IS_ERR(dent)) {
682 pr_err("%s: ERR debugfs_create_dir: dent=0x%X\n",
683 __func__, (unsigned)dent);
Jay Chokshi898340f2011-09-29 17:19:31 -0700684 rc = PTR_ERR(dent);
685 goto dir_error;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700686 }
687
688 temp = debugfs_create_file("addr", S_IRUSR | S_IWUSR, dent,
689 dbgdev, &dbg_addr_fops);
690 if (temp == NULL || IS_ERR(temp)) {
691 pr_err("%s: ERR debugfs_create_file: dent=0x%X\n",
692 __func__, (unsigned)temp);
Jay Chokshi898340f2011-09-29 17:19:31 -0700693 rc = PTR_ERR(temp);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700694 goto debug_error;
695 }
696
697 temp = debugfs_create_file("data", S_IRUSR | S_IWUSR, dent,
698 dbgdev, &dbg_data_fops);
699 if (temp == NULL || IS_ERR(temp)) {
700 pr_err("%s: ERR debugfs_create_file: dent=0x%X\n",
701 __func__, (unsigned)temp);
Jay Chokshi898340f2011-09-29 17:19:31 -0700702 rc = PTR_ERR(temp);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700703 goto debug_error;
704 }
705
Jay Chokshi898340f2011-09-29 17:19:31 -0700706 mutex_init(&dbgdev->dbg_mutex);
707
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700708 dbgdev->dent = dent;
709
710 pmic_dbg_device = dbgdev;
711
712 return 0;
713
714debug_error:
715 debugfs_remove_recursive(dent);
Jay Chokshi898340f2011-09-29 17:19:31 -0700716dir_error:
717 kfree(dbgdev);
718
719 return rc;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700720}
721
722static int __devexit pmic8901_dbg_remove(void)
723{
724 if (pmic_dbg_device) {
725 debugfs_remove_recursive(pmic_dbg_device->dent);
Jay Chokshi898340f2011-09-29 17:19:31 -0700726 mutex_destroy(&pmic_dbg_device->dbg_mutex);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700727 kfree(pmic_dbg_device);
728 }
729 return 0;
730}
731
732#else
733
734static int __devinit pmic8901_dbg_probe(struct pm8901_chip *chip)
735{
736 return 0;
737}
738
739static int __devexit pmic8901_dbg_remove(void)
740{
741 return 0;
742}
743
744#endif
745
746static struct irq_chip pm8901_irq_chip = {
747 .name = "pm8901",
748 .irq_ack = pm8901_irq_ack,
749 .irq_mask = pm8901_irq_mask,
750 .irq_unmask = pm8901_irq_unmask,
751 .irq_set_type = pm8901_irq_set_type,
752 .irq_set_wake = pm8901_irq_set_wake,
753};
754
Anirudh Ghayalc8051a82011-11-17 09:28:24 +0530755static int pm8901_probe(struct platform_device *pdev)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700756{
Anirudh Ghayalc8051a82011-11-17 09:28:24 +0530757 int i, rc;
758 struct pm8901_platform_data *pdata = pdev->dev.platform_data;
759 struct pm8901_chip *chip;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700760
Anirudh Ghayalc8051a82011-11-17 09:28:24 +0530761 if (pdata == NULL || pdata->irq <= 0) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700762 pr_err("%s: No platform_data or IRQ.\n", __func__);
763 return -ENODEV;
764 }
765
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700766 chip = kzalloc(sizeof *chip, GFP_KERNEL);
767 if (chip == NULL) {
768 pr_err("%s: kzalloc() failed.\n", __func__);
769 return -ENOMEM;
770 }
771
Anirudh Ghayalc8051a82011-11-17 09:28:24 +0530772 chip->dev = &pdev->dev;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700773
774 /* Read PMIC chip revision */
775 rc = ssbi_read(chip->dev, SSBI_REG_REV, &chip->revision, 1);
776 if (rc)
777 pr_err("%s: Failed on ssbi_read for revision: rc=%d.\n",
778 __func__, rc);
779 pr_info("%s: PMIC revision: %X\n", __func__, chip->revision);
780
781 (void) memcpy((void *)&chip->pdata, (const void *)pdata,
782 sizeof(chip->pdata));
783
Anirudh Ghayalc8051a82011-11-17 09:28:24 +0530784 irq_set_handler_data(pdata->irq, (void *)chip);
785 irq_set_irq_wake(pdata->irq, 1);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700786
787 chip->pm_max_irq = 0;
788 chip->pm_max_blocks = 0;
789 chip->pm_max_masters = 0;
790
Anirudh Ghayalc8051a82011-11-17 09:28:24 +0530791 platform_set_drvdata(pdev, chip);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700792
793 pmic_chip = chip;
794 spin_lock_init(&chip->pm_lock);
795
796 /* Register for all reserved IRQs */
797 for (i = pdata->irq_base; i < (pdata->irq_base + MAX_PM_IRQ); i++) {
798 irq_set_chip(i, &pm8901_irq_chip);
799 irq_set_handler(i, handle_edge_irq);
800 set_irq_flags(i, IRQF_VALID);
801 irq_set_handler_data(i, (void *)chip);
802 }
803
Anirudh Ghayalc8051a82011-11-17 09:28:24 +0530804 rc = mfd_add_devices(chip->dev, 0, pdata->sub_devices,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700805 pdata->num_subdevs, NULL, 0);
806 if (rc) {
807 pr_err("%s: could not add devices %d\n", __func__, rc);
808 return rc;
809 }
810
Anirudh Ghayalc8051a82011-11-17 09:28:24 +0530811 rc = request_threaded_irq(pdata->irq, NULL, pm8901_isr_thread,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700812 IRQF_ONESHOT | IRQF_DISABLED | pdata->irq_trigger_flags,
813 "pm8901-irq", chip);
814 if (rc)
815 pr_err("%s: could not request irq %d: %d\n", __func__,
Anirudh Ghayalc8051a82011-11-17 09:28:24 +0530816 pdata->irq, rc);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700817
818 rc = pmic8901_dbg_probe(chip);
819 if (rc < 0)
820 pr_err("%s: could not set up debugfs: %d\n", __func__, rc);
821
822 return rc;
823}
824
Anirudh Ghayalc8051a82011-11-17 09:28:24 +0530825static int __devexit pm8901_remove(struct platform_device *pdev)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700826{
827 struct pm8901_chip *chip;
828
Anirudh Ghayalc8051a82011-11-17 09:28:24 +0530829 chip = platform_get_drvdata(pdev);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700830 if (chip) {
831 if (chip->pm_max_irq) {
Anirudh Ghayalc8051a82011-11-17 09:28:24 +0530832 irq_set_irq_wake(chip->pdata.irq, 0);
833 free_irq(chip->pdata.irq, chip);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700834 }
835
Anirudh Ghayalc8051a82011-11-17 09:28:24 +0530836 mfd_remove_devices(chip->dev);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700837
838 chip->dev = NULL;
839
840 kfree(chip);
841 }
842
843 pmic8901_dbg_remove();
844
845 return 0;
846}
847
848#ifdef CONFIG_PM
Anirudh Ghayalc8051a82011-11-17 09:28:24 +0530849static int pm8901_suspend(struct platform_device *pdev, pm_message_t mesg)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700850{
851 struct pm8901_chip *chip;
852 int i;
853 unsigned long irqsave;
854
Anirudh Ghayalc8051a82011-11-17 09:28:24 +0530855 chip = platform_get_drvdata(pdev);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700856
857 for (i = 0; i < MAX_PM_IRQ; i++) {
858 spin_lock_irqsave(&chip->pm_lock, irqsave);
859 if (chip->config[i] && !chip->wake_enable[i]) {
860 if (!((chip->config[i] & PM8901_IRQF_MASK_ALL)
861 == PM8901_IRQF_MASK_ALL))
862 pm8901_irq_mask(irq_get_irq_data(i +
863 chip->pdata.irq_base));
864 }
865 spin_unlock_irqrestore(&chip->pm_lock, irqsave);
866 }
867
868 if (!chip->count_wakeable)
Anirudh Ghayalc8051a82011-11-17 09:28:24 +0530869 disable_irq(chip->pdata.irq);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700870
871 return 0;
872}
873
Anirudh Ghayalc8051a82011-11-17 09:28:24 +0530874static int pm8901_resume(struct platform_device *pdev)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700875{
876 struct pm8901_chip *chip;
877 int i;
878 unsigned long irqsave;
879
Anirudh Ghayalc8051a82011-11-17 09:28:24 +0530880 chip = platform_get_drvdata(pdev);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700881
882 for (i = 0; i < MAX_PM_IRQ; i++) {
883 spin_lock_irqsave(&chip->pm_lock, irqsave);
884 if (chip->config[i] && !chip->wake_enable[i]) {
885 if (!((chip->config[i] & PM8901_IRQF_MASK_ALL)
886 == PM8901_IRQF_MASK_ALL))
887 pm8901_irq_unmask(irq_get_irq_data(i +
888 chip->pdata.irq_base));
889 }
890 spin_unlock_irqrestore(&chip->pm_lock, irqsave);
891 }
892
893 if (!chip->count_wakeable)
Anirudh Ghayalc8051a82011-11-17 09:28:24 +0530894 enable_irq(chip->pdata.irq);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700895
896 return 0;
897}
898#else
899#define pm8901_suspend NULL
900#define pm8901_resume NULL
901#endif
902
Anirudh Ghayalc8051a82011-11-17 09:28:24 +0530903static struct platform_driver pm8901_driver = {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700904 .probe = pm8901_probe,
905 .remove = __devexit_p(pm8901_remove),
Anirudh Ghayalc8051a82011-11-17 09:28:24 +0530906 .driver = {
907 .name = "pm8901-core",
908 .owner = THIS_MODULE,
909 },
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700910 .suspend = pm8901_suspend,
911 .resume = pm8901_resume,
912};
913
914static int __init pm8901_init(void)
915{
Anirudh Ghayalc8051a82011-11-17 09:28:24 +0530916 return platform_driver_register(&pm8901_driver);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700917}
Anirudh Ghayalc8051a82011-11-17 09:28:24 +0530918arch_initcall(pm8901_init);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700919
920static void __exit pm8901_exit(void)
921{
Anirudh Ghayalc8051a82011-11-17 09:28:24 +0530922 platform_driver_unregister(&pm8901_driver);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700923}
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700924module_exit(pm8901_exit);
925
926MODULE_LICENSE("GPL v2");
927MODULE_DESCRIPTION("PMIC8901 core driver");
928MODULE_VERSION("1.0");
929MODULE_ALIAS("platform:pmic8901-core");