aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mfd/mfd-core.c
diff options
context:
space:
mode:
authorLee Jones <lee.jones@linaro.org>2012-06-29 13:01:03 -0400
committerSamuel Ortiz <sameo@linux.intel.com>2012-07-08 18:16:08 -0400
commitc94bb233a9fee3314dc5d9c7de9fa702e91283f2 (patch)
tree4a56392bad862f3871d516afba97eda68a8121e1 /drivers/mfd/mfd-core.c
parent822672a7b496e724f879af703693f342e2215163 (diff)
mfd: Make MFD core code Device Tree and IRQ domain aware
During Device Tree enablement of the ab8500 and db8500-prcmu drivers, a decision was made to omit registration through the MFD API and use Device Tree directly. However, because MFD devices have a different address space and the ab8500 and db8500 both use I2C to communicate, this causes issues with address translation during execution of of_platform_populate(). So the solution is to make the MFD core aware of Device Tree and have it assign the correct node pointers instead. To make this work the MFD core also needs to be awere of IRQ domains, as Device Tree insists on IRQ domain compatibility. So, instead of providing an irq-base via platform code, in the DT case we simply look up the IRQ domain and map to the correct virtual IRQ. Signed-off-by: Lee Jones <lee.jones@linaro.org> Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
Diffstat (limited to 'drivers/mfd/mfd-core.c')
-rw-r--r--drivers/mfd/mfd-core.c30
1 files changed, 26 insertions, 4 deletions
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 @@
18#include <linux/pm_runtime.h> 18#include <linux/pm_runtime.h>
19#include <linux/slab.h> 19#include <linux/slab.h>
20#include <linux/module.h> 20#include <linux/module.h>
21#include <linux/irqdomain.h>
22#include <linux/of.h>
21 23
22int mfd_cell_enable(struct platform_device *pdev) 24int mfd_cell_enable(struct platform_device *pdev)
23{ 25{
@@ -76,6 +78,8 @@ static int mfd_add_device(struct device *parent, int id,
76{ 78{
77 struct resource *res; 79 struct resource *res;
78 struct platform_device *pdev; 80 struct platform_device *pdev;
81 struct device_node *np = NULL;
82 struct irq_domain *domain = NULL;
79 int ret = -ENOMEM; 83 int ret = -ENOMEM;
80 int r; 84 int r;
81 85
@@ -89,6 +93,16 @@ static int mfd_add_device(struct device *parent, int id,
89 93
90 pdev->dev.parent = parent; 94 pdev->dev.parent = parent;
91 95
96 if (parent->of_node && cell->of_compatible) {
97 for_each_child_of_node(parent->of_node, np) {
98 if (of_device_is_compatible(np, cell->of_compatible)) {
99 pdev->dev.of_node = np;
100 domain = irq_find_host(parent->of_node);
101 break;
102 }
103 }
104 }
105
92 if (cell->pdata_size) { 106 if (cell->pdata_size) {
93 ret = platform_device_add_data(pdev, 107 ret = platform_device_add_data(pdev,
94 cell->platform_data, cell->pdata_size); 108 cell->platform_data, cell->pdata_size);
@@ -112,10 +126,18 @@ static int mfd_add_device(struct device *parent, int id,
112 res[r].end = mem_base->start + 126 res[r].end = mem_base->start +
113 cell->resources[r].end; 127 cell->resources[r].end;
114 } else if (cell->resources[r].flags & IORESOURCE_IRQ) { 128 } else if (cell->resources[r].flags & IORESOURCE_IRQ) {
115 res[r].start = irq_base + 129 if (domain) {
116 cell->resources[r].start; 130 /* Unable to create mappings for IRQ ranges. */
117 res[r].end = irq_base + 131 WARN_ON(cell->resources[r].start !=
118 cell->resources[r].end; 132 cell->resources[r].end);
133 res[r].start = res[r].end = irq_create_mapping(
134 domain, cell->resources[r].start);
135 } else {
136 res[r].start = irq_base +
137 cell->resources[r].start;
138 res[r].end = irq_base +
139 cell->resources[r].end;
140 }
119 } else { 141 } else {
120 res[r].parent = cell->resources[r].parent; 142 res[r].parent = cell->resources[r].parent;
121 res[r].start = cell->resources[r].start; 143 res[r].start = cell->resources[r].start;