aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mfd/ab8500-core.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mfd/ab8500-core.c')
-rw-r--r--drivers/mfd/ab8500-core.c130
1 files changed, 70 insertions, 60 deletions
diff --git a/drivers/mfd/ab8500-core.c b/drivers/mfd/ab8500-core.c
index dac0e2998603..f3af34596439 100644
--- a/drivers/mfd/ab8500-core.c
+++ b/drivers/mfd/ab8500-core.c
@@ -11,6 +11,7 @@
11#include <linux/slab.h> 11#include <linux/slab.h>
12#include <linux/init.h> 12#include <linux/init.h>
13#include <linux/irq.h> 13#include <linux/irq.h>
14#include <linux/irqdomain.h>
14#include <linux/delay.h> 15#include <linux/delay.h>
15#include <linux/interrupt.h> 16#include <linux/interrupt.h>
16#include <linux/module.h> 17#include <linux/module.h>
@@ -361,7 +362,7 @@ static void ab8500_irq_sync_unlock(struct irq_data *data)
361static void ab8500_irq_mask(struct irq_data *data) 362static void ab8500_irq_mask(struct irq_data *data)
362{ 363{
363 struct ab8500 *ab8500 = irq_data_get_irq_chip_data(data); 364 struct ab8500 *ab8500 = irq_data_get_irq_chip_data(data);
364 int offset = data->irq - ab8500->irq_base; 365 int offset = data->hwirq;
365 int index = offset / 8; 366 int index = offset / 8;
366 int mask = 1 << (offset % 8); 367 int mask = 1 << (offset % 8);
367 368
@@ -371,7 +372,7 @@ static void ab8500_irq_mask(struct irq_data *data)
371static void ab8500_irq_unmask(struct irq_data *data) 372static void ab8500_irq_unmask(struct irq_data *data)
372{ 373{
373 struct ab8500 *ab8500 = irq_data_get_irq_chip_data(data); 374 struct ab8500 *ab8500 = irq_data_get_irq_chip_data(data);
374 int offset = data->irq - ab8500->irq_base; 375 int offset = data->hwirq;
375 int index = offset / 8; 376 int index = offset / 8;
376 int mask = 1 << (offset % 8); 377 int mask = 1 << (offset % 8);
377 378
@@ -510,38 +511,51 @@ static irqreturn_t ab8500_irq(int irq, void *dev)
510 return IRQ_HANDLED; 511 return IRQ_HANDLED;
511} 512}
512 513
513static int ab8500_irq_init(struct ab8500 *ab8500) 514/**
515 * ab8500_irq_get_virq(): Map an interrupt on a chip to a virtual IRQ
516 *
517 * @ab8500: ab8500_irq controller to operate on.
518 * @irq: index of the interrupt requested in the chip IRQs
519 *
520 * Useful for drivers to request their own IRQs.
521 */
522int ab8500_irq_get_virq(struct ab8500 *ab8500, int irq)
514{ 523{
515 int base = ab8500->irq_base; 524 if (!ab8500)
516 int irq; 525 return -EINVAL;
517 int num_irqs;
518 526
519 if (is_ab9540(ab8500)) 527 return irq_create_mapping(ab8500->domain, irq);
520 num_irqs = AB9540_NR_IRQS; 528}
521 else if (is_ab8505(ab8500)) 529EXPORT_SYMBOL_GPL(ab8500_irq_get_virq);
522 num_irqs = AB8505_NR_IRQS;
523 else
524 num_irqs = AB8500_NR_IRQS;
525 530
526 for (irq = base; irq < base + num_irqs; irq++) { 531static int ab8500_irq_map(struct irq_domain *d, unsigned int virq,
527 irq_set_chip_data(irq, ab8500); 532 irq_hw_number_t hwirq)
528 irq_set_chip_and_handler(irq, &ab8500_irq_chip, 533{
529 handle_simple_irq); 534 struct ab8500 *ab8500 = d->host_data;
530 irq_set_nested_thread(irq, 1); 535
536 if (!ab8500)
537 return -EINVAL;
538
539 irq_set_chip_data(virq, ab8500);
540 irq_set_chip_and_handler(virq, &ab8500_irq_chip,
541 handle_simple_irq);
542 irq_set_nested_thread(virq, 1);
531#ifdef CONFIG_ARM 543#ifdef CONFIG_ARM
532 set_irq_flags(irq, IRQF_VALID); 544 set_irq_flags(virq, IRQF_VALID);
533#else 545#else
534 irq_set_noprobe(irq); 546 irq_set_noprobe(virq);
535#endif 547#endif
536 }
537 548
538 return 0; 549 return 0;
539} 550}
540 551
541static void ab8500_irq_remove(struct ab8500 *ab8500) 552static struct irq_domain_ops ab8500_irq_ops = {
553 .map = ab8500_irq_map,
554 .xlate = irq_domain_xlate_twocell,
555};
556
557static int ab8500_irq_init(struct ab8500 *ab8500, struct device_node *np)
542{ 558{
543 int base = ab8500->irq_base;
544 int irq;
545 int num_irqs; 559 int num_irqs;
546 560
547 if (is_ab9540(ab8500)) 561 if (is_ab9540(ab8500))
@@ -551,13 +565,22 @@ static void ab8500_irq_remove(struct ab8500 *ab8500)
551 else 565 else
552 num_irqs = AB8500_NR_IRQS; 566 num_irqs = AB8500_NR_IRQS;
553 567
554 for (irq = base; irq < base + num_irqs; irq++) { 568 if (ab8500->irq_base) {
555#ifdef CONFIG_ARM 569 ab8500->domain = irq_domain_add_legacy(
556 set_irq_flags(irq, 0); 570 NULL, num_irqs, ab8500->irq_base,
557#endif 571 0, &ab8500_irq_ops, ab8500);
558 irq_set_chip_and_handler(irq, NULL, NULL); 572 }
559 irq_set_chip_data(irq, NULL); 573 else {
574 ab8500->domain = irq_domain_add_linear(
575 np, num_irqs, &ab8500_irq_ops, ab8500);
560 } 576 }
577
578 if (!ab8500->domain) {
579 dev_err(ab8500->dev, "Failed to create irqdomain\n");
580 return -ENOSYS;
581 }
582
583 return 0;
561} 584}
562 585
563int ab8500_suspend(struct ab8500 *ab8500) 586int ab8500_suspend(struct ab8500 *ab8500)
@@ -1233,14 +1256,6 @@ static int __devinit ab8500_probe(struct platform_device *pdev)
1233 1256
1234 if (plat) 1257 if (plat)
1235 ab8500->irq_base = plat->irq_base; 1258 ab8500->irq_base = plat->irq_base;
1236 else if (np)
1237 ret = of_property_read_u32(np, "stericsson,irq-base", &ab8500->irq_base);
1238
1239 if (!ab8500->irq_base) {
1240 dev_info(&pdev->dev, "couldn't find irq-base\n");
1241 ret = -EINVAL;
1242 goto out_free_ab8500;
1243 }
1244 1259
1245 ab8500->dev = &pdev->dev; 1260 ab8500->dev = &pdev->dev;
1246 1261
@@ -1323,7 +1338,7 @@ static int __devinit ab8500_probe(struct platform_device *pdev)
1323 AB8500_SWITCH_OFF_STATUS, &value); 1338 AB8500_SWITCH_OFF_STATUS, &value);
1324 if (ret < 0) 1339 if (ret < 0)
1325 return ret; 1340 return ret;
1326 dev_info(ab8500->dev, "switch off status: %#x", value); 1341 dev_info(ab8500->dev, "switch off status: %#x\n", value);
1327 1342
1328 if (plat && plat->init) 1343 if (plat && plat->init)
1329 plat->init(ab8500); 1344 plat->init(ab8500);
@@ -1352,25 +1367,25 @@ static int __devinit ab8500_probe(struct platform_device *pdev)
1352 for (i = 0; i < ab8500->mask_size; i++) 1367 for (i = 0; i < ab8500->mask_size; i++)
1353 ab8500->mask[i] = ab8500->oldmask[i] = 0xff; 1368 ab8500->mask[i] = ab8500->oldmask[i] = 0xff;
1354 1369
1355 if (ab8500->irq_base) { 1370 ret = ab8500_irq_init(ab8500, np);
1356 ret = ab8500_irq_init(ab8500); 1371 if (ret)
1357 if (ret) 1372 goto out_freeoldmask;
1358 goto out_freeoldmask;
1359 1373
1360 /* Activate this feature only in ab9540 */ 1374 /* Activate this feature only in ab9540 */
1361 /* till tests are done on ab8500 1p2 or later*/ 1375 /* till tests are done on ab8500 1p2 or later*/
1362 if (is_ab9540(ab8500)) 1376 if (is_ab9540(ab8500)) {
1363 ret = request_threaded_irq(ab8500->irq, NULL, 1377 ret = request_threaded_irq(ab8500->irq, NULL,
1364 ab8500_hierarchical_irq, 1378 ab8500_hierarchical_irq,
1365 IRQF_ONESHOT | IRQF_NO_SUSPEND, 1379 IRQF_ONESHOT | IRQF_NO_SUSPEND,
1366 "ab8500", ab8500); 1380 "ab8500", ab8500);
1367 else 1381 }
1368 ret = request_threaded_irq(ab8500->irq, NULL, 1382 else {
1383 ret = request_threaded_irq(ab8500->irq, NULL,
1369 ab8500_irq, 1384 ab8500_irq,
1370 IRQF_ONESHOT | IRQF_NO_SUSPEND, 1385 IRQF_ONESHOT | IRQF_NO_SUSPEND,
1371 "ab8500", ab8500); 1386 "ab8500", ab8500);
1372 if (ret) 1387 if (ret)
1373 goto out_removeirq; 1388 goto out_freeoldmask;
1374 } 1389 }
1375 1390
1376 if (!np) { 1391 if (!np) {
@@ -1417,15 +1432,11 @@ static int __devinit ab8500_probe(struct platform_device *pdev)
1417 &ab8500_attr_group); 1432 &ab8500_attr_group);
1418 if (ret) 1433 if (ret)
1419 dev_err(ab8500->dev, "error creating sysfs entries\n"); 1434 dev_err(ab8500->dev, "error creating sysfs entries\n");
1420 else 1435
1421 return ret; 1436 return ret;
1422 1437
1423out_freeirq: 1438out_freeirq:
1424 if (ab8500->irq_base) 1439 free_irq(ab8500->irq, ab8500);
1425 free_irq(ab8500->irq, ab8500);
1426out_removeirq:
1427 if (ab8500->irq_base)
1428 ab8500_irq_remove(ab8500);
1429out_freeoldmask: 1440out_freeoldmask:
1430 kfree(ab8500->oldmask); 1441 kfree(ab8500->oldmask);
1431out_freemask: 1442out_freemask:
@@ -1444,11 +1455,10 @@ static int __devexit ab8500_remove(struct platform_device *pdev)
1444 sysfs_remove_group(&ab8500->dev->kobj, &ab9540_attr_group); 1455 sysfs_remove_group(&ab8500->dev->kobj, &ab9540_attr_group);
1445 else 1456 else
1446 sysfs_remove_group(&ab8500->dev->kobj, &ab8500_attr_group); 1457 sysfs_remove_group(&ab8500->dev->kobj, &ab8500_attr_group);
1458
1447 mfd_remove_devices(ab8500->dev); 1459 mfd_remove_devices(ab8500->dev);
1448 if (ab8500->irq_base) { 1460 free_irq(ab8500->irq, ab8500);
1449 free_irq(ab8500->irq, ab8500); 1461
1450 ab8500_irq_remove(ab8500);
1451 }
1452 kfree(ab8500->oldmask); 1462 kfree(ab8500->oldmask);
1453 kfree(ab8500->mask); 1463 kfree(ab8500->mask);
1454 kfree(ab8500); 1464 kfree(ab8500);