Skip to content

Commit

Permalink
iommu/ipmmu-vmsa: Add device tree support
Browse files Browse the repository at this point in the history
Make platform data optional when the device is instantiated from DT and
look up the micro-TLB number in the bus master DT node.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
  • Loading branch information
Laurent Pinchart committed Jan 16, 2015
1 parent 4a93f21 commit 275f505
Showing 1 changed file with 47 additions and 8 deletions.
55 changes: 47 additions & 8 deletions drivers/iommu/ipmmu-vmsa.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include <linux/io.h>
#include <linux/iommu.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_data/ipmmu-vmsa.h>
#include <linux/platform_device.h>
#include <linux/sizes.h>
Expand Down Expand Up @@ -58,6 +59,8 @@ static LIST_HEAD(ipmmu_devices);
* Registers Definition
*/

#define IM_NS_ALIAS_OFFSET 0x800

#define IM_CTX_SIZE 0x40

#define IMCTR 0x0000
Expand Down Expand Up @@ -1002,16 +1005,33 @@ static phys_addr_t ipmmu_iova_to_phys(struct iommu_domain *io_domain,

static int ipmmu_find_utlb(struct ipmmu_vmsa_device *mmu, struct device *dev)
{
const struct ipmmu_vmsa_master *master = mmu->pdata->masters;
const char *devname = dev_name(dev);
unsigned int i;
struct of_phandle_args args;
int ret;

if (mmu->pdata) {
const struct ipmmu_vmsa_master *master = mmu->pdata->masters;
const char *devname = dev_name(dev);
unsigned int i;

for (i = 0; i < mmu->pdata->num_masters; ++i, ++master) {
if (strcmp(master->name, devname) == 0)
return master->utlb;
for (i = 0; i < mmu->pdata->num_masters; ++i, ++master) {
if (strcmp(master->name, devname) == 0)
return master->utlb;
}

return -1;
}

return -1;
ret = of_parse_phandle_with_args(dev->of_node, "iommus",
"#iommu-cells", 0, &args);
if (ret < 0)
return -1;

of_node_put(args.np);

if (args.np != mmu->dev->of_node || args.args_count != 1)
return -1;

return args.args[0];
}

static int ipmmu_add_device(struct device *dev)
Expand Down Expand Up @@ -1157,7 +1177,7 @@ static int ipmmu_probe(struct platform_device *pdev)
int irq;
int ret;

if (!pdev->dev.platform_data) {
if (!IS_ENABLED(CONFIG_OF) && !pdev->dev.platform_data) {
dev_err(&pdev->dev, "missing platform data\n");
return -EINVAL;
}
Expand All @@ -1178,6 +1198,20 @@ static int ipmmu_probe(struct platform_device *pdev)
if (IS_ERR(mmu->base))
return PTR_ERR(mmu->base);

/*
* The IPMMU has two register banks, for secure and non-secure modes.
* The bank mapped at the beginning of the IPMMU address space
* corresponds to the running mode of the CPU. When running in secure
* mode the non-secure register bank is also available at an offset.
*
* Secure mode operation isn't clearly documented and is thus currently
* not implemented in the driver. Furthermore, preliminary tests of
* non-secure operation with the main register bank were not successful.
* Offset the registers base unconditionally to point to the non-secure
* alias space for now.
*/
mmu->base += IM_NS_ALIAS_OFFSET;

irq = platform_get_irq(pdev, 0);
if (irq < 0) {
dev_err(&pdev->dev, "no IRQ found\n");
Expand Down Expand Up @@ -1223,9 +1257,14 @@ static int ipmmu_remove(struct platform_device *pdev)
return 0;
}

static const struct of_device_id ipmmu_of_ids[] = {
{ .compatible = "renesas,ipmmu-vmsa", },
};

static struct platform_driver ipmmu_driver = {
.driver = {
.name = "ipmmu-vmsa",
.of_match_table = of_match_ptr(ipmmu_of_ids),
},
.probe = ipmmu_probe,
.remove = ipmmu_remove,
Expand Down

0 comments on commit 275f505

Please sign in to comment.