summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/mfd/Kconfig1
-rw-r--r--drivers/mfd/mfd-core.c30
-rw-r--r--include/linux/mfd/core.h1
3 files changed, 28 insertions, 4 deletions
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 8b56c1998ab2..d43876c6da23 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -7,6 +7,7 @@ menu "Multifunction device drivers"
config MFD_CORE
tristate
+ select IRQ_DOMAIN
default n
config MFD_88PM860X
diff --git a/drivers/mfd/mfd-core.c b/drivers/mfd/mfd-core.c
index ffc3d48676ae..0c3a01cde2f7 100644
--- a/drivers/mfd/mfd-core.c
+++ b/drivers/mfd/mfd-core.c
@@ -18,6 +18,8 @@
#include <linux/pm_runtime.h>
#include <linux/slab.h>
#include <linux/module.h>
+#include <linux/irqdomain.h>
+#include <linux/of.h>
int mfd_cell_enable(struct platform_device *pdev)
{
@@ -76,6 +78,8 @@ static int mfd_add_device(struct device *parent, int id,
{
struct resource *res;
struct platform_device *pdev;
+ struct device_node *np = NULL;
+ struct irq_domain *domain = NULL;
int ret = -ENOMEM;
int r;
@@ -89,6 +93,16 @@ static int mfd_add_device(struct device *parent, int id,
pdev->dev.parent = parent;
+ if (parent->of_node && cell->of_compatible) {
+ for_each_child_of_node(parent->of_node, np) {
+ if (of_device_is_compatible(np, cell->of_compatible)) {
+ pdev->dev.of_node = np;
+ domain = irq_find_host(parent->of_node);
+ break;
+ }
+ }
+ }
+
if (cell->pdata_size) {
ret = platform_device_add_data(pdev,
cell->platform_data, cell->pdata_size);
@@ -112,10 +126,18 @@ static int mfd_add_device(struct device *parent, int id,
res[r].end = mem_base->start +
cell->resources[r].end;
} else if (cell->resources[r].flags & IORESOURCE_IRQ) {
- res[r].start = irq_base +
- cell->resources[r].start;
- res[r].end = irq_base +
- cell->resources[r].end;
+ if (domain) {
+ /* Unable to create mappings for IRQ ranges. */
+ WARN_ON(cell->resources[r].start !=
+ cell->resources[r].end);
+ res[r].start = res[r].end = irq_create_mapping(
+ domain, cell->resources[r].start);
+ } else {
+ res[r].start = irq_base +
+ cell->resources[r].start;
+ res[r].end = irq_base +
+ cell->resources[r].end;
+ }
} else {
res[r].parent = cell->resources[r].parent;
res[r].start = cell->resources[r].start;
diff --git a/include/linux/mfd/core.h b/include/linux/mfd/core.h
index 4e76163dd862..99b7eb1961b6 100644
--- a/include/linux/mfd/core.h
+++ b/include/linux/mfd/core.h
@@ -36,6 +36,7 @@ struct mfd_cell {
/* platform data passed to the sub devices drivers */
void *platform_data;
size_t pdata_size;
+ const char *of_compatible;
/*
* These resources can be specified relative to the parent device.