aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/iommu/ipmmu-vmsa.c
diff options
context:
space:
mode:
authorLaurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>2014-03-16 20:02:46 -0400
committerLaurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>2015-01-16 11:03:04 -0500
commit275f5053c7786285d2f20d2dd12908f834c47ad8 (patch)
tree9c7482c5617eec8f267a34ed709c41978716fe42 /drivers/iommu/ipmmu-vmsa.c
parent4a93f21d87e769477c0cb2b98d7e7911b8d37c03 (diff)
iommu/ipmmu-vmsa: Add device tree support
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>
Diffstat (limited to 'drivers/iommu/ipmmu-vmsa.c')
-rw-r--r--drivers/iommu/ipmmu-vmsa.c55
1 files changed, 47 insertions, 8 deletions
diff --git a/drivers/iommu/ipmmu-vmsa.c b/drivers/iommu/ipmmu-vmsa.c
index 3a61103ef108..368c852d9ee7 100644
--- a/drivers/iommu/ipmmu-vmsa.c
+++ b/drivers/iommu/ipmmu-vmsa.c
@@ -16,6 +16,7 @@
16#include <linux/io.h> 16#include <linux/io.h>
17#include <linux/iommu.h> 17#include <linux/iommu.h>
18#include <linux/module.h> 18#include <linux/module.h>
19#include <linux/of.h>
19#include <linux/platform_data/ipmmu-vmsa.h> 20#include <linux/platform_data/ipmmu-vmsa.h>
20#include <linux/platform_device.h> 21#include <linux/platform_device.h>
21#include <linux/sizes.h> 22#include <linux/sizes.h>
@@ -58,6 +59,8 @@ static LIST_HEAD(ipmmu_devices);
58 * Registers Definition 59 * Registers Definition
59 */ 60 */
60 61
62#define IM_NS_ALIAS_OFFSET 0x800
63
61#define IM_CTX_SIZE 0x40 64#define IM_CTX_SIZE 0x40
62 65
63#define IMCTR 0x0000 66#define IMCTR 0x0000
@@ -1002,16 +1005,33 @@ static phys_addr_t ipmmu_iova_to_phys(struct iommu_domain *io_domain,
1002 1005
1003static int ipmmu_find_utlb(struct ipmmu_vmsa_device *mmu, struct device *dev) 1006static int ipmmu_find_utlb(struct ipmmu_vmsa_device *mmu, struct device *dev)
1004{ 1007{
1005 const struct ipmmu_vmsa_master *master = mmu->pdata->masters; 1008 struct of_phandle_args args;
1006 const char *devname = dev_name(dev); 1009 int ret;
1007 unsigned int i; 1010
1011 if (mmu->pdata) {
1012 const struct ipmmu_vmsa_master *master = mmu->pdata->masters;
1013 const char *devname = dev_name(dev);
1014 unsigned int i;
1008 1015
1009 for (i = 0; i < mmu->pdata->num_masters; ++i, ++master) { 1016 for (i = 0; i < mmu->pdata->num_masters; ++i, ++master) {
1010 if (strcmp(master->name, devname) == 0) 1017 if (strcmp(master->name, devname) == 0)
1011 return master->utlb; 1018 return master->utlb;
1019 }
1020
1021 return -1;
1012 } 1022 }
1013 1023
1014 return -1; 1024 ret = of_parse_phandle_with_args(dev->of_node, "iommus",
1025 "#iommu-cells", 0, &args);
1026 if (ret < 0)
1027 return -1;
1028
1029 of_node_put(args.np);
1030
1031 if (args.np != mmu->dev->of_node || args.args_count != 1)
1032 return -1;
1033
1034 return args.args[0];
1015} 1035}
1016 1036
1017static int ipmmu_add_device(struct device *dev) 1037static int ipmmu_add_device(struct device *dev)
@@ -1157,7 +1177,7 @@ static int ipmmu_probe(struct platform_device *pdev)
1157 int irq; 1177 int irq;
1158 int ret; 1178 int ret;
1159 1179
1160 if (!pdev->dev.platform_data) { 1180 if (!IS_ENABLED(CONFIG_OF) && !pdev->dev.platform_data) {
1161 dev_err(&pdev->dev, "missing platform data\n"); 1181 dev_err(&pdev->dev, "missing platform data\n");
1162 return -EINVAL; 1182 return -EINVAL;
1163 } 1183 }
@@ -1178,6 +1198,20 @@ static int ipmmu_probe(struct platform_device *pdev)
1178 if (IS_ERR(mmu->base)) 1198 if (IS_ERR(mmu->base))
1179 return PTR_ERR(mmu->base); 1199 return PTR_ERR(mmu->base);
1180 1200
1201 /*
1202 * The IPMMU has two register banks, for secure and non-secure modes.
1203 * The bank mapped at the beginning of the IPMMU address space
1204 * corresponds to the running mode of the CPU. When running in secure
1205 * mode the non-secure register bank is also available at an offset.
1206 *
1207 * Secure mode operation isn't clearly documented and is thus currently
1208 * not implemented in the driver. Furthermore, preliminary tests of
1209 * non-secure operation with the main register bank were not successful.
1210 * Offset the registers base unconditionally to point to the non-secure
1211 * alias space for now.
1212 */
1213 mmu->base += IM_NS_ALIAS_OFFSET;
1214
1181 irq = platform_get_irq(pdev, 0); 1215 irq = platform_get_irq(pdev, 0);
1182 if (irq < 0) { 1216 if (irq < 0) {
1183 dev_err(&pdev->dev, "no IRQ found\n"); 1217 dev_err(&pdev->dev, "no IRQ found\n");
@@ -1223,9 +1257,14 @@ static int ipmmu_remove(struct platform_device *pdev)
1223 return 0; 1257 return 0;
1224} 1258}
1225 1259
1260static const struct of_device_id ipmmu_of_ids[] = {
1261 { .compatible = "renesas,ipmmu-vmsa", },
1262};
1263
1226static struct platform_driver ipmmu_driver = { 1264static struct platform_driver ipmmu_driver = {
1227 .driver = { 1265 .driver = {
1228 .name = "ipmmu-vmsa", 1266 .name = "ipmmu-vmsa",
1267 .of_match_table = of_match_ptr(ipmmu_of_ids),
1229 }, 1268 },
1230 .probe = ipmmu_probe, 1269 .probe = ipmmu_probe,
1231 .remove = ipmmu_remove, 1270 .remove = ipmmu_remove,