From 798206f02db2cd1b52017e954cfc3490434b8eed Mon Sep 17 00:00:00 2001 From: Janghyuck Kim Date: Mon, 2 Jan 2017 20:41:27 +0900 Subject: [PATCH] [COMMON] iommu/exynos: add slot property setting This patch added parsing DT about slot properties, and parsed information is used at the beginning of sysmmu. Change-Id: I1148177911eff50ee71282c4bba508368b1a4a0b Signed-off-by: Janghyuck Kim --- drivers/iommu/exynos-iommu.c | 37 ++++++++++++++++++++++++++++++++++-- drivers/iommu/exynos-iommu.h | 3 +++ 2 files changed, 38 insertions(+), 2 deletions(-) diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c index bc5a3add2601..348674f987ce 100644 --- a/drivers/iommu/exynos-iommu.c +++ b/drivers/iommu/exynos-iommu.c @@ -768,11 +768,34 @@ static int __init sysmmu_parse_tlb_port_dt(struct device *sysmmu, struct sysmmu_drvdata *drvdata) { const char *props_name = "sysmmu,tlb_property"; + const char *slot_props_name = "sysmmu,slot_property"; struct tlb_props *tlb_props = &drvdata->tlb_props; struct tlb_port_cfg *port_cfg = NULL; + unsigned int *slot_cfg = NULL; int i, cnt, ret; int port_id_cnt = 0; + cnt = of_property_count_u32_elems(sysmmu->of_node, slot_props_name); + if (cnt > 0) { + slot_cfg = kzalloc(sizeof(*slot_cfg) * cnt, GFP_KERNEL); + if (!slot_cfg) + return -ENOMEM; + + for (i = 0; i < cnt; i++) { + ret = of_property_read_u32_index(sysmmu->of_node, + slot_props_name, i, &slot_cfg[i]); + if (ret) { + dev_err(sysmmu, "failed to get slot property." + "cnt = %d, ret = %d\n", i, ret); + ret = -EINVAL; + goto err_slot_prop; + } + } + + tlb_props->port_props.slot_cnt = cnt; + tlb_props->port_props.slot_cfg = slot_cfg; + } + cnt = of_property_count_u32_elems(sysmmu->of_node, props_name); if (!cnt || cnt < 0) { dev_info(sysmmu, "No TLB port propeties found.\n"); @@ -780,8 +803,10 @@ static int __init sysmmu_parse_tlb_port_dt(struct device *sysmmu, } port_cfg = kzalloc(sizeof(*port_cfg) * (cnt/2), GFP_KERNEL); - if (!port_cfg) - return -ENOMEM; + if (!port_cfg) { + ret = -ENOMEM; + goto err_slot_prop; + } for (i = 0; i < cnt; i+=2) { ret = of_property_read_u32_index(sysmmu->of_node, @@ -812,6 +837,9 @@ static int __init sysmmu_parse_tlb_port_dt(struct device *sysmmu, err_port_prop: kfree(port_cfg); +err_slot_prop: + kfree(slot_cfg); + return ret; } @@ -1114,6 +1142,7 @@ static void __sysmmu_set_tlb_port_dedication(struct sysmmu_drvdata *drvdata) struct tlb_props *tlb_props = &drvdata->tlb_props; unsigned int i; int port_id_cnt = tlb_props->port_props.port_id_cnt; + int slot_cnt = tlb_props->port_props.slot_cnt; if (port_id_cnt > tlb_num) { dev_warn(drvdata->sysmmu, @@ -1124,6 +1153,10 @@ static void __sysmmu_set_tlb_port_dedication(struct sysmmu_drvdata *drvdata) for (i = 0; i < port_id_cnt; i++) __sysmmu_set_tlb_port(drvdata, i); + + for (i = 0; i < slot_cnt; i++) + writel_relaxed(tlb_props->port_props.slot_cfg[i], + drvdata->sfrbase + REG_SLOT_RSV(i)); } static void __sysmmu_init_config(struct sysmmu_drvdata *drvdata) diff --git a/drivers/iommu/exynos-iommu.h b/drivers/iommu/exynos-iommu.h index 9526b883bdec..89f45636b02c 100644 --- a/drivers/iommu/exynos-iommu.h +++ b/drivers/iommu/exynos-iommu.h @@ -182,6 +182,7 @@ typedef u32 sysmmu_pte_t; #define REG_CAPA1_SBB_VPN 0x8024 #define REG_CAPA1_SBB_LINK 0x8028 #define REG_CAPA1_SBB_ATTR 0x802C +#define REG_SLOT_RSV(n) (0x4000 + ((n) * 0x20)) #define MMU_CAPA1_SET_TLB_READ_ENTRY(tid, set, way, line) \ ((set) | ((way) << 8) | ((line) << 16) | ((tid) << 20)) #define MMU_TLB_CFG_MASK(reg) ((reg) & ((0x7 << 5) | (0x3 << 2) | (0x1 << 1))) @@ -305,7 +306,9 @@ struct tlb_way_props { struct tlb_port_props { int port_id_cnt; + int slot_cnt; struct tlb_port_cfg *port_cfg; + unsigned int *slot_cfg; }; struct tlb_props { -- 2.20.1