blob: 50e0a9b69b9dac2ef9d8fd1e881a4af9d13c52d6 [file] [log] [blame]
Abhijeet Dharmapurikarcbdb53e2011-04-05 14:40:52 -07001/*
2 * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 and
6 * only version 2 as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 */
13
14#define pr_fmt(fmt) "%s: " fmt, __func__
15
16#include <linux/kernel.h>
Stephen Boydbc866fc2014-02-26 10:59:19 -080017#include <linux/interrupt.h>
18#include <linux/irq.h>
Jingoo Hanef310f42013-08-20 16:01:26 +090019#include <linux/module.h>
Abhijeet Dharmapurikarcbdb53e2011-04-05 14:40:52 -070020#include <linux/platform_device.h>
21#include <linux/slab.h>
Abhijeet Dharmapurikarc013f0a52011-04-05 14:40:53 -070022#include <linux/err.h>
David Brownce44bf52013-03-12 11:41:54 -070023#include <linux/ssbi.h>
Abhijeet Dharmapurikarcbdb53e2011-04-05 14:40:52 -070024#include <linux/mfd/core.h>
25#include <linux/mfd/pm8xxx/pm8921.h>
26#include <linux/mfd/pm8xxx/core.h>
Stephen Boydbc866fc2014-02-26 10:59:19 -080027#include <linux/mfd/pm8xxx/irq.h>
28
29#define SSBI_REG_ADDR_IRQ_BASE 0x1BB
30
31#define SSBI_REG_ADDR_IRQ_ROOT (SSBI_REG_ADDR_IRQ_BASE + 0)
32#define SSBI_REG_ADDR_IRQ_M_STATUS1 (SSBI_REG_ADDR_IRQ_BASE + 1)
33#define SSBI_REG_ADDR_IRQ_M_STATUS2 (SSBI_REG_ADDR_IRQ_BASE + 2)
34#define SSBI_REG_ADDR_IRQ_M_STATUS3 (SSBI_REG_ADDR_IRQ_BASE + 3)
35#define SSBI_REG_ADDR_IRQ_M_STATUS4 (SSBI_REG_ADDR_IRQ_BASE + 4)
36#define SSBI_REG_ADDR_IRQ_BLK_SEL (SSBI_REG_ADDR_IRQ_BASE + 5)
37#define SSBI_REG_ADDR_IRQ_IT_STATUS (SSBI_REG_ADDR_IRQ_BASE + 6)
38#define SSBI_REG_ADDR_IRQ_CONFIG (SSBI_REG_ADDR_IRQ_BASE + 7)
39#define SSBI_REG_ADDR_IRQ_RT_STATUS (SSBI_REG_ADDR_IRQ_BASE + 8)
40
41#define PM_IRQF_LVL_SEL 0x01 /* level select */
42#define PM_IRQF_MASK_FE 0x02 /* mask falling edge */
43#define PM_IRQF_MASK_RE 0x04 /* mask rising edge */
44#define PM_IRQF_CLR 0x08 /* clear interrupt */
45#define PM_IRQF_BITS_MASK 0x70
46#define PM_IRQF_BITS_SHIFT 4
47#define PM_IRQF_WRITE 0x80
48
49#define PM_IRQF_MASK_ALL (PM_IRQF_MASK_FE | \
50 PM_IRQF_MASK_RE)
Abhijeet Dharmapurikarcbdb53e2011-04-05 14:40:52 -070051
52#define REG_HWREV 0x002 /* PMIC4 revision */
53#define REG_HWREV_2 0x0E8 /* PMIC4 revision 2 */
54
Stephen Boydbc866fc2014-02-26 10:59:19 -080055struct pm_irq_chip {
56 struct device *dev;
57 spinlock_t pm_irq_lock;
58 unsigned int devirq;
59 unsigned int irq_base;
60 unsigned int num_irqs;
61 unsigned int num_blocks;
62 unsigned int num_masters;
63 u8 config[0];
64};
65
Abhijeet Dharmapurikarcbdb53e2011-04-05 14:40:52 -070066struct pm8921 {
67 struct device *dev;
Abhijeet Dharmapurikarc013f0a52011-04-05 14:40:53 -070068 struct pm_irq_chip *irq_chip;
Abhijeet Dharmapurikarcbdb53e2011-04-05 14:40:52 -070069};
70
Stephen Boydbc866fc2014-02-26 10:59:19 -080071static int pm8xxx_read_root_irq(const struct pm_irq_chip *chip, u8 *rp)
72{
73 return pm8xxx_readb(chip->dev, SSBI_REG_ADDR_IRQ_ROOT, rp);
74}
75
76static int pm8xxx_read_master_irq(const struct pm_irq_chip *chip, u8 m, u8 *bp)
77{
78 return pm8xxx_readb(chip->dev,
79 SSBI_REG_ADDR_IRQ_M_STATUS1 + m, bp);
80}
81
82static int pm8xxx_read_block_irq(struct pm_irq_chip *chip, u8 bp, u8 *ip)
83{
84 int rc;
85
86 spin_lock(&chip->pm_irq_lock);
87 rc = pm8xxx_writeb(chip->dev, SSBI_REG_ADDR_IRQ_BLK_SEL, bp);
88 if (rc) {
89 pr_err("Failed Selecting Block %d rc=%d\n", bp, rc);
90 goto bail;
91 }
92
93 rc = pm8xxx_readb(chip->dev, SSBI_REG_ADDR_IRQ_IT_STATUS, ip);
94 if (rc)
95 pr_err("Failed Reading Status rc=%d\n", rc);
96bail:
97 spin_unlock(&chip->pm_irq_lock);
98 return rc;
99}
100
101static int pm8xxx_config_irq(struct pm_irq_chip *chip, u8 bp, u8 cp)
102{
103 int rc;
104
105 spin_lock(&chip->pm_irq_lock);
106 rc = pm8xxx_writeb(chip->dev, SSBI_REG_ADDR_IRQ_BLK_SEL, bp);
107 if (rc) {
108 pr_err("Failed Selecting Block %d rc=%d\n", bp, rc);
109 goto bail;
110 }
111
112 cp |= PM_IRQF_WRITE;
113 rc = pm8xxx_writeb(chip->dev, SSBI_REG_ADDR_IRQ_CONFIG, cp);
114 if (rc)
115 pr_err("Failed Configuring IRQ rc=%d\n", rc);
116bail:
117 spin_unlock(&chip->pm_irq_lock);
118 return rc;
119}
120
121static int pm8xxx_irq_block_handler(struct pm_irq_chip *chip, int block)
122{
123 int pmirq, irq, i, ret = 0;
124 u8 bits;
125
126 ret = pm8xxx_read_block_irq(chip, block, &bits);
127 if (ret) {
128 pr_err("Failed reading %d block ret=%d", block, ret);
129 return ret;
130 }
131 if (!bits) {
132 pr_err("block bit set in master but no irqs: %d", block);
133 return 0;
134 }
135
136 /* Check IRQ bits */
137 for (i = 0; i < 8; i++) {
138 if (bits & (1 << i)) {
139 pmirq = block * 8 + i;
140 irq = pmirq + chip->irq_base;
141 generic_handle_irq(irq);
142 }
143 }
144 return 0;
145}
146
147static int pm8xxx_irq_master_handler(struct pm_irq_chip *chip, int master)
148{
149 u8 blockbits;
150 int block_number, i, ret = 0;
151
152 ret = pm8xxx_read_master_irq(chip, master, &blockbits);
153 if (ret) {
154 pr_err("Failed to read master %d ret=%d\n", master, ret);
155 return ret;
156 }
157 if (!blockbits) {
158 pr_err("master bit set in root but no blocks: %d", master);
159 return 0;
160 }
161
162 for (i = 0; i < 8; i++)
163 if (blockbits & (1 << i)) {
164 block_number = master * 8 + i; /* block # */
165 ret |= pm8xxx_irq_block_handler(chip, block_number);
166 }
167 return ret;
168}
169
170static void pm8xxx_irq_handler(unsigned int irq, struct irq_desc *desc)
171{
172 struct pm_irq_chip *chip = irq_desc_get_handler_data(desc);
173 struct irq_chip *irq_chip = irq_desc_get_chip(desc);
174 u8 root;
175 int i, ret, masters = 0;
176
177 ret = pm8xxx_read_root_irq(chip, &root);
178 if (ret) {
179 pr_err("Can't read root status ret=%d\n", ret);
180 return;
181 }
182
183 /* on pm8xxx series masters start from bit 1 of the root */
184 masters = root >> 1;
185
186 /* Read allowed masters for blocks. */
187 for (i = 0; i < chip->num_masters; i++)
188 if (masters & (1 << i))
189 pm8xxx_irq_master_handler(chip, i);
190
191 irq_chip->irq_ack(&desc->irq_data);
192}
193
194static void pm8xxx_irq_mask_ack(struct irq_data *d)
195{
196 struct pm_irq_chip *chip = irq_data_get_irq_chip_data(d);
197 unsigned int pmirq = d->irq - chip->irq_base;
198 int master, irq_bit;
199 u8 block, config;
200
201 block = pmirq / 8;
202 master = block / 8;
203 irq_bit = pmirq % 8;
204
205 config = chip->config[pmirq] | PM_IRQF_MASK_ALL | PM_IRQF_CLR;
206 pm8xxx_config_irq(chip, block, config);
207}
208
209static void pm8xxx_irq_unmask(struct irq_data *d)
210{
211 struct pm_irq_chip *chip = irq_data_get_irq_chip_data(d);
212 unsigned int pmirq = d->irq - chip->irq_base;
213 int master, irq_bit;
214 u8 block, config;
215
216 block = pmirq / 8;
217 master = block / 8;
218 irq_bit = pmirq % 8;
219
220 config = chip->config[pmirq];
221 pm8xxx_config_irq(chip, block, config);
222}
223
224static int pm8xxx_irq_set_type(struct irq_data *d, unsigned int flow_type)
225{
226 struct pm_irq_chip *chip = irq_data_get_irq_chip_data(d);
227 unsigned int pmirq = d->irq - chip->irq_base;
228 int master, irq_bit;
229 u8 block, config;
230
231 block = pmirq / 8;
232 master = block / 8;
233 irq_bit = pmirq % 8;
234
235 chip->config[pmirq] = (irq_bit << PM_IRQF_BITS_SHIFT)
236 | PM_IRQF_MASK_ALL;
237 if (flow_type & (IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING)) {
238 if (flow_type & IRQF_TRIGGER_RISING)
239 chip->config[pmirq] &= ~PM_IRQF_MASK_RE;
240 if (flow_type & IRQF_TRIGGER_FALLING)
241 chip->config[pmirq] &= ~PM_IRQF_MASK_FE;
242 } else {
243 chip->config[pmirq] |= PM_IRQF_LVL_SEL;
244
245 if (flow_type & IRQF_TRIGGER_HIGH)
246 chip->config[pmirq] &= ~PM_IRQF_MASK_RE;
247 else
248 chip->config[pmirq] &= ~PM_IRQF_MASK_FE;
249 }
250
251 config = chip->config[pmirq] | PM_IRQF_CLR;
252 return pm8xxx_config_irq(chip, block, config);
253}
254
255static int pm8xxx_irq_set_wake(struct irq_data *d, unsigned int on)
256{
257 return 0;
258}
259
260static struct irq_chip pm8xxx_irq_chip = {
261 .name = "pm8xxx",
262 .irq_mask_ack = pm8xxx_irq_mask_ack,
263 .irq_unmask = pm8xxx_irq_unmask,
264 .irq_set_type = pm8xxx_irq_set_type,
265 .irq_set_wake = pm8xxx_irq_set_wake,
266 .flags = IRQCHIP_MASK_ON_SUSPEND,
267};
268
269/**
270 * pm8xxx_get_irq_stat - get the status of the irq line
271 * @chip: pointer to identify a pmic irq controller
272 * @irq: the irq number
273 *
274 * The pm8xxx gpio and mpp rely on the interrupt block to read
275 * the values on their pins. This function is to facilitate reading
276 * the status of a gpio or an mpp line. The caller has to convert the
277 * gpio number to irq number.
278 *
279 * RETURNS:
280 * an int indicating the value read on that line
281 */
282static int pm8xxx_get_irq_stat(struct pm_irq_chip *chip, int irq)
283{
284 int pmirq, rc;
285 u8 block, bits, bit;
286 unsigned long flags;
287
288 if (chip == NULL || irq < chip->irq_base ||
289 irq >= chip->irq_base + chip->num_irqs)
290 return -EINVAL;
291
292 pmirq = irq - chip->irq_base;
293
294 block = pmirq / 8;
295 bit = pmirq % 8;
296
297 spin_lock_irqsave(&chip->pm_irq_lock, flags);
298
299 rc = pm8xxx_writeb(chip->dev, SSBI_REG_ADDR_IRQ_BLK_SEL, block);
300 if (rc) {
301 pr_err("Failed Selecting block irq=%d pmirq=%d blk=%d rc=%d\n",
302 irq, pmirq, block, rc);
303 goto bail_out;
304 }
305
306 rc = pm8xxx_readb(chip->dev, SSBI_REG_ADDR_IRQ_RT_STATUS, &bits);
307 if (rc) {
308 pr_err("Failed Configuring irq=%d pmirq=%d blk=%d rc=%d\n",
309 irq, pmirq, block, rc);
310 goto bail_out;
311 }
312
313 rc = (bits & (1 << bit)) ? 1 : 0;
314
315bail_out:
316 spin_unlock_irqrestore(&chip->pm_irq_lock, flags);
317
318 return rc;
319}
320
321static struct pm_irq_chip *pm8xxx_irq_init(struct device *dev,
322 const struct pm8xxx_irq_platform_data *pdata)
323{
324 struct pm_irq_chip *chip;
325 int devirq, rc;
326 unsigned int pmirq;
327
328 if (!pdata) {
329 pr_err("No platform data\n");
330 return ERR_PTR(-EINVAL);
331 }
332
333 devirq = pdata->devirq;
334 if (devirq < 0) {
335 pr_err("missing devirq\n");
336 rc = devirq;
337 return ERR_PTR(-EINVAL);
338 }
339
340 chip = kzalloc(sizeof(struct pm_irq_chip)
341 + sizeof(u8) * pdata->irq_cdata.nirqs, GFP_KERNEL);
342 if (!chip) {
343 pr_err("Cannot alloc pm_irq_chip struct\n");
344 return ERR_PTR(-EINVAL);
345 }
346
347 chip->dev = dev;
348 chip->devirq = devirq;
349 chip->irq_base = pdata->irq_base;
350 chip->num_irqs = pdata->irq_cdata.nirqs;
351 chip->num_blocks = DIV_ROUND_UP(chip->num_irqs, 8);
352 chip->num_masters = DIV_ROUND_UP(chip->num_blocks, 8);
353 spin_lock_init(&chip->pm_irq_lock);
354
355 for (pmirq = 0; pmirq < chip->num_irqs; pmirq++) {
356 irq_set_chip_and_handler(chip->irq_base + pmirq,
357 &pm8xxx_irq_chip,
358 handle_level_irq);
359 irq_set_chip_data(chip->irq_base + pmirq, chip);
360#ifdef CONFIG_ARM
361 set_irq_flags(chip->irq_base + pmirq, IRQF_VALID);
362#else
363 irq_set_noprobe(chip->irq_base + pmirq);
364#endif
365 }
366
367 irq_set_irq_type(devirq, pdata->irq_trigger_flag);
368 irq_set_handler_data(devirq, chip);
369 irq_set_chained_handler(devirq, pm8xxx_irq_handler);
370 set_irq_wake(devirq, 1);
371
372 return chip;
373}
374
375static int pm8xxx_irq_exit(struct pm_irq_chip *chip)
376{
377 irq_set_chained_handler(chip->devirq, NULL);
378 kfree(chip);
379 return 0;
380}
381
Abhijeet Dharmapurikarcbdb53e2011-04-05 14:40:52 -0700382static int pm8921_readb(const struct device *dev, u16 addr, u8 *val)
383{
384 const struct pm8xxx_drvdata *pm8921_drvdata = dev_get_drvdata(dev);
385 const struct pm8921 *pmic = pm8921_drvdata->pm_chip_data;
386
David Brownce44bf52013-03-12 11:41:54 -0700387 return ssbi_read(pmic->dev->parent, addr, val, 1);
Abhijeet Dharmapurikarcbdb53e2011-04-05 14:40:52 -0700388}
389
390static int pm8921_writeb(const struct device *dev, u16 addr, u8 val)
391{
392 const struct pm8xxx_drvdata *pm8921_drvdata = dev_get_drvdata(dev);
393 const struct pm8921 *pmic = pm8921_drvdata->pm_chip_data;
394
David Brownce44bf52013-03-12 11:41:54 -0700395 return ssbi_write(pmic->dev->parent, addr, &val, 1);
Abhijeet Dharmapurikarcbdb53e2011-04-05 14:40:52 -0700396}
397
398static int pm8921_read_buf(const struct device *dev, u16 addr, u8 *buf,
399 int cnt)
400{
401 const struct pm8xxx_drvdata *pm8921_drvdata = dev_get_drvdata(dev);
402 const struct pm8921 *pmic = pm8921_drvdata->pm_chip_data;
403
David Brownce44bf52013-03-12 11:41:54 -0700404 return ssbi_read(pmic->dev->parent, addr, buf, cnt);
Abhijeet Dharmapurikarcbdb53e2011-04-05 14:40:52 -0700405}
406
407static int pm8921_write_buf(const struct device *dev, u16 addr, u8 *buf,
408 int cnt)
409{
410 const struct pm8xxx_drvdata *pm8921_drvdata = dev_get_drvdata(dev);
411 const struct pm8921 *pmic = pm8921_drvdata->pm_chip_data;
412
David Brownce44bf52013-03-12 11:41:54 -0700413 return ssbi_write(pmic->dev->parent, addr, buf, cnt);
Abhijeet Dharmapurikarcbdb53e2011-04-05 14:40:52 -0700414}
415
Abhijeet Dharmapurikarc013f0a52011-04-05 14:40:53 -0700416static int pm8921_read_irq_stat(const struct device *dev, int irq)
417{
418 const struct pm8xxx_drvdata *pm8921_drvdata = dev_get_drvdata(dev);
419 const struct pm8921 *pmic = pm8921_drvdata->pm_chip_data;
420
421 return pm8xxx_get_irq_stat(pmic->irq_chip, irq);
422}
423
Abhijeet Dharmapurikarcbdb53e2011-04-05 14:40:52 -0700424static struct pm8xxx_drvdata pm8921_drvdata = {
425 .pmic_readb = pm8921_readb,
426 .pmic_writeb = pm8921_writeb,
427 .pmic_read_buf = pm8921_read_buf,
428 .pmic_write_buf = pm8921_write_buf,
Abhijeet Dharmapurikarc013f0a52011-04-05 14:40:53 -0700429 .pmic_read_irq_stat = pm8921_read_irq_stat,
Abhijeet Dharmapurikarcbdb53e2011-04-05 14:40:52 -0700430};
431
Bill Pembertonf791be42012-11-19 13:23:04 -0500432static int pm8921_add_subdevices(const struct pm8921_platform_data
Abhijeet Dharmapurikarc013f0a52011-04-05 14:40:53 -0700433 *pdata,
434 struct pm8921 *pmic,
435 u32 rev)
436{
437 int ret = 0, irq_base = 0;
438 struct pm_irq_chip *irq_chip;
439
440 if (pdata->irq_pdata) {
441 pdata->irq_pdata->irq_cdata.nirqs = PM8921_NR_IRQS;
442 pdata->irq_pdata->irq_cdata.rev = rev;
443 irq_base = pdata->irq_pdata->irq_base;
444 irq_chip = pm8xxx_irq_init(pmic->dev, pdata->irq_pdata);
445
446 if (IS_ERR(irq_chip)) {
447 pr_err("Failed to init interrupts ret=%ld\n",
448 PTR_ERR(irq_chip));
449 return PTR_ERR(irq_chip);
450 }
451 pmic->irq_chip = irq_chip;
452 }
453 return ret;
454}
455
Bill Pembertonf791be42012-11-19 13:23:04 -0500456static int pm8921_probe(struct platform_device *pdev)
Abhijeet Dharmapurikarcbdb53e2011-04-05 14:40:52 -0700457{
Jingoo Han334a41ce2013-07-30 17:10:05 +0900458 const struct pm8921_platform_data *pdata = dev_get_platdata(&pdev->dev);
Abhijeet Dharmapurikarcbdb53e2011-04-05 14:40:52 -0700459 struct pm8921 *pmic;
460 int rc;
461 u8 val;
Abhijeet Dharmapurikarc013f0a52011-04-05 14:40:53 -0700462 u32 rev;
Abhijeet Dharmapurikarcbdb53e2011-04-05 14:40:52 -0700463
464 if (!pdata) {
465 pr_err("missing platform data\n");
466 return -EINVAL;
467 }
468
Jingoo Hanb2cdcfa2013-08-20 16:02:26 +0900469 pmic = devm_kzalloc(&pdev->dev, sizeof(struct pm8921), GFP_KERNEL);
Abhijeet Dharmapurikarcbdb53e2011-04-05 14:40:52 -0700470 if (!pmic) {
471 pr_err("Cannot alloc pm8921 struct\n");
472 return -ENOMEM;
473 }
474
475 /* Read PMIC chip revision */
David Brownce44bf52013-03-12 11:41:54 -0700476 rc = ssbi_read(pdev->dev.parent, REG_HWREV, &val, sizeof(val));
Abhijeet Dharmapurikarcbdb53e2011-04-05 14:40:52 -0700477 if (rc) {
478 pr_err("Failed to read hw rev reg %d:rc=%d\n", REG_HWREV, rc);
Jingoo Hanb2cdcfa2013-08-20 16:02:26 +0900479 return rc;
Abhijeet Dharmapurikarcbdb53e2011-04-05 14:40:52 -0700480 }
481 pr_info("PMIC revision 1: %02X\n", val);
Abhijeet Dharmapurikarc013f0a52011-04-05 14:40:53 -0700482 rev = val;
Abhijeet Dharmapurikarcbdb53e2011-04-05 14:40:52 -0700483
484 /* Read PMIC chip revision 2 */
David Brownce44bf52013-03-12 11:41:54 -0700485 rc = ssbi_read(pdev->dev.parent, REG_HWREV_2, &val, sizeof(val));
Abhijeet Dharmapurikarcbdb53e2011-04-05 14:40:52 -0700486 if (rc) {
487 pr_err("Failed to read hw rev 2 reg %d:rc=%d\n",
488 REG_HWREV_2, rc);
Jingoo Hanb2cdcfa2013-08-20 16:02:26 +0900489 return rc;
Abhijeet Dharmapurikarcbdb53e2011-04-05 14:40:52 -0700490 }
491 pr_info("PMIC revision 2: %02X\n", val);
Abhijeet Dharmapurikarc013f0a52011-04-05 14:40:53 -0700492 rev |= val << BITS_PER_BYTE;
Abhijeet Dharmapurikarcbdb53e2011-04-05 14:40:52 -0700493
494 pmic->dev = &pdev->dev;
495 pm8921_drvdata.pm_chip_data = pmic;
496 platform_set_drvdata(pdev, &pm8921_drvdata);
497
Abhijeet Dharmapurikarc013f0a52011-04-05 14:40:53 -0700498 rc = pm8921_add_subdevices(pdata, pmic, rev);
499 if (rc) {
500 pr_err("Cannot add subdevices rc=%d\n", rc);
501 goto err;
502 }
503
504 /* gpio might not work if no irq device is found */
505 WARN_ON(pmic->irq_chip == NULL);
506
Abhijeet Dharmapurikarcbdb53e2011-04-05 14:40:52 -0700507 return 0;
508
Abhijeet Dharmapurikarc013f0a52011-04-05 14:40:53 -0700509err:
510 mfd_remove_devices(pmic->dev);
Abhijeet Dharmapurikarcbdb53e2011-04-05 14:40:52 -0700511 return rc;
512}
513
Bill Pemberton4740f732012-11-19 13:26:01 -0500514static int pm8921_remove(struct platform_device *pdev)
Abhijeet Dharmapurikarcbdb53e2011-04-05 14:40:52 -0700515{
516 struct pm8xxx_drvdata *drvdata;
517 struct pm8921 *pmic = NULL;
518
519 drvdata = platform_get_drvdata(pdev);
520 if (drvdata)
521 pmic = drvdata->pm_chip_data;
Dan Carpenterd6daef92013-11-07 11:04:20 +0300522 if (pmic) {
Abhijeet Dharmapurikarcbdb53e2011-04-05 14:40:52 -0700523 mfd_remove_devices(pmic->dev);
Dan Carpenterd6daef92013-11-07 11:04:20 +0300524 if (pmic->irq_chip) {
525 pm8xxx_irq_exit(pmic->irq_chip);
526 pmic->irq_chip = NULL;
527 }
Abhijeet Dharmapurikarc013f0a52011-04-05 14:40:53 -0700528 }
Abhijeet Dharmapurikarcbdb53e2011-04-05 14:40:52 -0700529
530 return 0;
531}
532
533static struct platform_driver pm8921_driver = {
534 .probe = pm8921_probe,
Bill Pemberton84449212012-11-19 13:20:24 -0500535 .remove = pm8921_remove,
Abhijeet Dharmapurikarcbdb53e2011-04-05 14:40:52 -0700536 .driver = {
537 .name = "pm8921-core",
538 .owner = THIS_MODULE,
539 },
540};
541
542static int __init pm8921_init(void)
543{
544 return platform_driver_register(&pm8921_driver);
545}
546subsys_initcall(pm8921_init);
547
548static void __exit pm8921_exit(void)
549{
550 platform_driver_unregister(&pm8921_driver);
551}
552module_exit(pm8921_exit);
553
554MODULE_LICENSE("GPL v2");
555MODULE_DESCRIPTION("PMIC 8921 core driver");
556MODULE_VERSION("1.0");
557MODULE_ALIAS("platform:pm8921-core");