Skip to content

Commit

Permalink
mfd: Make MFD core code Device Tree and IRQ domain aware
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Lee Jones authored and Samuel Ortiz committed Jul 8, 2012
1 parent 822672a commit c94bb23
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 4 deletions.
1 change: 1 addition & 0 deletions drivers/mfd/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ menu "Multifunction device drivers"

config MFD_CORE
tristate
select IRQ_DOMAIN
default n

config MFD_88PM860X
Expand Down
30 changes: 26 additions & 4 deletions drivers/mfd/mfd-core.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down Expand Up @@ -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;

Expand All @@ -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);
Expand All @@ -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;
Expand Down
1 change: 1 addition & 0 deletions include/linux/mfd/core.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down

0 comments on commit c94bb23

Please sign in to comment.