aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYong Wu <yong.wu@mediatek.com>2017-08-21 07:00:16 -0400
committerJoerg Roedel <jroedel@suse.de>2017-08-22 10:37:58 -0400
commite6dec92308628cff5f1f8bd1bcdf87581c9dc676 (patch)
treed17007990ff95de3df378b2d6625f25e8b815b54
parenta9467d954226f1a513cfe789a3a39d8fc73b5d16 (diff)
iommu/mediatek: Add mt2712 IOMMU support
The M4U IP blocks in mt2712 is MTK's generation2 M4U which use the ARM Short-descriptor like mt8173, and most of the HW registers are the same. The difference is that there are 2 M4U HWs in mt2712 while there's only one in mt8173. The purpose of 2 M4U HWs is for balance the bandwidth. Normally if there are 2 M4U HWs, there should be 2 iommu domains, each M4U has a iommu domain. Signed-off-by: Yong Wu <yong.wu@mediatek.com> Signed-off-by: Joerg Roedel <jroedel@suse.de>
-rw-r--r--drivers/iommu/mtk_iommu.c71
-rw-r--r--drivers/iommu/mtk_iommu.h7
-rw-r--r--drivers/memory/mtk-smi.c54
-rw-r--r--include/soc/mediatek/smi.h2
4 files changed, 93 insertions, 41 deletions
diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
index 4db6c8f66b0c..df23e0201336 100644
--- a/drivers/iommu/mtk_iommu.c
+++ b/drivers/iommu/mtk_iommu.c
@@ -53,7 +53,11 @@
53 53
54#define REG_MMU_CTRL_REG 0x110 54#define REG_MMU_CTRL_REG 0x110
55#define F_MMU_PREFETCH_RT_REPLACE_MOD BIT(4) 55#define F_MMU_PREFETCH_RT_REPLACE_MOD BIT(4)
56#define F_MMU_TF_PROTECT_SEL(prot) (((prot) & 0x3) << 5) 56#define F_MMU_TF_PROTECT_SEL_SHIFT(data) \
57 ((data)->m4u_plat == M4U_MT2712 ? 4 : 5)
58/* It's named by F_MMU_TF_PROT_SEL in mt2712. */
59#define F_MMU_TF_PROTECT_SEL(prot, data) \
60 (((prot) & 0x3) << F_MMU_TF_PROTECT_SEL_SHIFT(data))
57 61
58#define REG_MMU_IVRP_PADDR 0x114 62#define REG_MMU_IVRP_PADDR 0x114
59#define F_MMU_IVRP_PA_SET(pa, ext) (((pa) >> 1) | ((!!(ext)) << 31)) 63#define F_MMU_IVRP_PA_SET(pa, ext) (((pa) >> 1) | ((!!(ext)) << 31))
@@ -96,7 +100,7 @@
96 * Get the local arbiter ID and the portid within the larb arbiter 100 * Get the local arbiter ID and the portid within the larb arbiter
97 * from mtk_m4u_id which is defined by MTK_M4U_ID. 101 * from mtk_m4u_id which is defined by MTK_M4U_ID.
98 */ 102 */
99#define MTK_M4U_TO_LARB(id) (((id) >> 5) & 0x7) 103#define MTK_M4U_TO_LARB(id) (((id) >> 5) & 0xf)
100#define MTK_M4U_TO_PORT(id) ((id) & 0x1f) 104#define MTK_M4U_TO_PORT(id) ((id) & 0x1f)
101 105
102struct mtk_iommu_domain { 106struct mtk_iommu_domain {
@@ -307,10 +311,6 @@ static int mtk_iommu_attach_device(struct iommu_domain *domain,
307 data->m4u_dom = NULL; 311 data->m4u_dom = NULL;
308 return ret; 312 return ret;
309 } 313 }
310 } else if (data->m4u_dom != dom) {
311 /* All the client devices should be in the same m4u domain */
312 dev_err(dev, "try to attach into the error iommu domain\n");
313 return -EPERM;
314 } 314 }
315 315
316 mtk_iommu_config(data, dev, true); 316 mtk_iommu_config(data, dev, true);
@@ -470,8 +470,9 @@ static int mtk_iommu_hw_init(const struct mtk_iommu_data *data)
470 return ret; 470 return ret;
471 } 471 }
472 472
473 regval = F_MMU_PREFETCH_RT_REPLACE_MOD | 473 regval = F_MMU_TF_PROTECT_SEL(2, data);
474 F_MMU_TF_PROTECT_SEL(2); 474 if (data->m4u_plat == M4U_MT8173)
475 regval |= F_MMU_PREFETCH_RT_REPLACE_MOD;
475 writel_relaxed(regval, data->base + REG_MMU_CTRL_REG); 476 writel_relaxed(regval, data->base + REG_MMU_CTRL_REG);
476 477
477 regval = F_L2_MULIT_HIT_EN | 478 regval = F_L2_MULIT_HIT_EN |
@@ -493,9 +494,11 @@ static int mtk_iommu_hw_init(const struct mtk_iommu_data *data)
493 494
494 writel_relaxed(F_MMU_IVRP_PA_SET(data->protect_base, data->enable_4GB), 495 writel_relaxed(F_MMU_IVRP_PA_SET(data->protect_base, data->enable_4GB),
495 data->base + REG_MMU_IVRP_PADDR); 496 data->base + REG_MMU_IVRP_PADDR);
496
497 writel_relaxed(0, data->base + REG_MMU_DCM_DIS); 497 writel_relaxed(0, data->base + REG_MMU_DCM_DIS);
498 writel_relaxed(0, data->base + REG_MMU_STANDARD_AXI_MODE); 498
499 /* It's MISC control register whose default value is ok except mt8173.*/
500 if (data->m4u_plat == M4U_MT8173)
501 writel_relaxed(0, data->base + REG_MMU_STANDARD_AXI_MODE);
499 502
500 if (devm_request_irq(data->dev, data->irq, mtk_iommu_isr, 0, 503 if (devm_request_irq(data->dev, data->irq, mtk_iommu_isr, 0,
501 dev_name(data->dev), (void *)data)) { 504 dev_name(data->dev), (void *)data)) {
@@ -527,6 +530,7 @@ static int mtk_iommu_probe(struct platform_device *pdev)
527 if (!data) 530 if (!data)
528 return -ENOMEM; 531 return -ENOMEM;
529 data->dev = dev; 532 data->dev = dev;
533 data->m4u_plat = (enum mtk_iommu_plat)of_device_get_match_data(dev);
530 534
531 /* Protect memory. HW will access here while translation fault.*/ 535 /* Protect memory. HW will access here while translation fault.*/
532 protect = devm_kzalloc(dev, MTK_PROTECT_PA_ALIGN * 2, GFP_KERNEL); 536 protect = devm_kzalloc(dev, MTK_PROTECT_PA_ALIGN * 2, GFP_KERNEL);
@@ -560,6 +564,7 @@ static int mtk_iommu_probe(struct platform_device *pdev)
560 for (i = 0; i < larb_nr; i++) { 564 for (i = 0; i < larb_nr; i++) {
561 struct device_node *larbnode; 565 struct device_node *larbnode;
562 struct platform_device *plarbdev; 566 struct platform_device *plarbdev;
567 u32 id;
563 568
564 larbnode = of_parse_phandle(dev->of_node, "mediatek,larbs", i); 569 larbnode = of_parse_phandle(dev->of_node, "mediatek,larbs", i);
565 if (!larbnode) 570 if (!larbnode)
@@ -568,17 +573,14 @@ static int mtk_iommu_probe(struct platform_device *pdev)
568 if (!of_device_is_available(larbnode)) 573 if (!of_device_is_available(larbnode))
569 continue; 574 continue;
570 575
576 ret = of_property_read_u32(larbnode, "mediatek,larb-id", &id);
577 if (ret)/* The id is consecutive if there is no this property */
578 id = i;
579
571 plarbdev = of_find_device_by_node(larbnode); 580 plarbdev = of_find_device_by_node(larbnode);
572 if (!plarbdev) { 581 if (!plarbdev)
573 plarbdev = of_platform_device_create( 582 return -EPROBE_DEFER;
574 larbnode, NULL, 583 data->smi_imu.larb_imu[id].dev = &plarbdev->dev;
575 platform_bus_type.dev_root);
576 if (!plarbdev) {
577 of_node_put(larbnode);
578 return -EPROBE_DEFER;
579 }
580 }
581 data->smi_imu.larb_imu[i].dev = &plarbdev->dev;
582 584
583 component_match_add_release(dev, &match, release_of, 585 component_match_add_release(dev, &match, release_of,
584 compare_of, larbnode); 586 compare_of, larbnode);
@@ -646,8 +648,6 @@ static int __maybe_unused mtk_iommu_resume(struct device *dev)
646 struct mtk_iommu_suspend_reg *reg = &data->reg; 648 struct mtk_iommu_suspend_reg *reg = &data->reg;
647 void __iomem *base = data->base; 649 void __iomem *base = data->base;
648 650
649 writel_relaxed(data->m4u_dom->cfg.arm_v7s_cfg.ttbr[0],
650 base + REG_MMU_PT_BASE_ADDR);
651 writel_relaxed(reg->standard_axi_mode, 651 writel_relaxed(reg->standard_axi_mode,
652 base + REG_MMU_STANDARD_AXI_MODE); 652 base + REG_MMU_STANDARD_AXI_MODE);
653 writel_relaxed(reg->dcm_dis, base + REG_MMU_DCM_DIS); 653 writel_relaxed(reg->dcm_dis, base + REG_MMU_DCM_DIS);
@@ -656,15 +656,19 @@ static int __maybe_unused mtk_iommu_resume(struct device *dev)
656 writel_relaxed(reg->int_main_control, base + REG_MMU_INT_MAIN_CONTROL); 656 writel_relaxed(reg->int_main_control, base + REG_MMU_INT_MAIN_CONTROL);
657 writel_relaxed(F_MMU_IVRP_PA_SET(data->protect_base, data->enable_4GB), 657 writel_relaxed(F_MMU_IVRP_PA_SET(data->protect_base, data->enable_4GB),
658 base + REG_MMU_IVRP_PADDR); 658 base + REG_MMU_IVRP_PADDR);
659 if (data->m4u_dom)
660 writel(data->m4u_dom->cfg.arm_v7s_cfg.ttbr[0],
661 base + REG_MMU_PT_BASE_ADDR);
659 return 0; 662 return 0;
660} 663}
661 664
662const struct dev_pm_ops mtk_iommu_pm_ops = { 665static const struct dev_pm_ops mtk_iommu_pm_ops = {
663 SET_SYSTEM_SLEEP_PM_OPS(mtk_iommu_suspend, mtk_iommu_resume) 666 SET_SYSTEM_SLEEP_PM_OPS(mtk_iommu_suspend, mtk_iommu_resume)
664}; 667};
665 668
666static const struct of_device_id mtk_iommu_of_ids[] = { 669static const struct of_device_id mtk_iommu_of_ids[] = {
667 { .compatible = "mediatek,mt8173-m4u", }, 670 { .compatible = "mediatek,mt2712-m4u", .data = (void *)M4U_MT2712},
671 { .compatible = "mediatek,mt8173-m4u", .data = (void *)M4U_MT8173},
668 {} 672 {}
669}; 673};
670 674
@@ -673,27 +677,20 @@ static struct platform_driver mtk_iommu_driver = {
673 .remove = mtk_iommu_remove, 677 .remove = mtk_iommu_remove,
674 .driver = { 678 .driver = {
675 .name = "mtk-iommu", 679 .name = "mtk-iommu",
676 .of_match_table = mtk_iommu_of_ids, 680 .of_match_table = of_match_ptr(mtk_iommu_of_ids),
677 .pm = &mtk_iommu_pm_ops, 681 .pm = &mtk_iommu_pm_ops,
678 } 682 }
679}; 683};
680 684
681static int mtk_iommu_init_fn(struct device_node *np) 685static int __init mtk_iommu_init(void)
682{ 686{
683 int ret; 687 int ret;
684 struct platform_device *pdev;
685
686 pdev = of_platform_device_create(np, NULL, platform_bus_type.dev_root);
687 if (!pdev)
688 return -ENOMEM;
689 688
690 ret = platform_driver_register(&mtk_iommu_driver); 689 ret = platform_driver_register(&mtk_iommu_driver);
691 if (ret) { 690 if (ret != 0)
692 pr_err("%s: Failed to register driver\n", __func__); 691 pr_err("Failed to register MTK IOMMU driver\n");
693 return ret;
694 }
695 692
696 return 0; 693 return ret;
697} 694}
698 695
699IOMMU_OF_DECLARE(mtkm4u, "mediatek,mt8173-m4u", mtk_iommu_init_fn); 696subsys_initcall(mtk_iommu_init)
diff --git a/drivers/iommu/mtk_iommu.h b/drivers/iommu/mtk_iommu.h
index c06cc91b5d9a..462e593b7d71 100644
--- a/drivers/iommu/mtk_iommu.h
+++ b/drivers/iommu/mtk_iommu.h
@@ -34,6 +34,12 @@ struct mtk_iommu_suspend_reg {
34 u32 int_main_control; 34 u32 int_main_control;
35}; 35};
36 36
37enum mtk_iommu_plat {
38 M4U_MT2701,
39 M4U_MT2712,
40 M4U_MT8173,
41};
42
37struct mtk_iommu_domain; 43struct mtk_iommu_domain;
38 44
39struct mtk_iommu_data { 45struct mtk_iommu_data {
@@ -50,6 +56,7 @@ struct mtk_iommu_data {
50 bool tlb_flush_active; 56 bool tlb_flush_active;
51 57
52 struct iommu_device iommu; 58 struct iommu_device iommu;
59 enum mtk_iommu_plat m4u_plat;
53}; 60};
54 61
55static inline int compare_of(struct device *dev, void *data) 62static inline int compare_of(struct device *dev, void *data)
diff --git a/drivers/memory/mtk-smi.c b/drivers/memory/mtk-smi.c
index 13f8c45dbf0d..8ffe3216d092 100644
--- a/drivers/memory/mtk-smi.c
+++ b/drivers/memory/mtk-smi.c
@@ -23,7 +23,10 @@
23#include <soc/mediatek/smi.h> 23#include <soc/mediatek/smi.h>
24#include <dt-bindings/memory/mt2701-larb-port.h> 24#include <dt-bindings/memory/mt2701-larb-port.h>
25 25
26/* mt8173 */
26#define SMI_LARB_MMU_EN 0xf00 27#define SMI_LARB_MMU_EN 0xf00
28
29/* mt2701 */
27#define REG_SMI_SECUR_CON_BASE 0x5c0 30#define REG_SMI_SECUR_CON_BASE 0x5c0
28 31
29/* every register control 8 port, register offset 0x4 */ 32/* every register control 8 port, register offset 0x4 */
@@ -41,6 +44,10 @@
41/* mt2701 domain should be set to 3 */ 44/* mt2701 domain should be set to 3 */
42#define SMI_SECUR_CON_VAL_DOMAIN(id) (0x3 << ((((id) & 0x7) << 2) + 1)) 45#define SMI_SECUR_CON_VAL_DOMAIN(id) (0x3 << ((((id) & 0x7) << 2) + 1))
43 46
47/* mt2712 */
48#define SMI_LARB_NONSEC_CON(id) (0x380 + ((id) * 4))
49#define F_MMU_EN BIT(0)
50
44struct mtk_smi_larb_gen { 51struct mtk_smi_larb_gen {
45 bool need_larbid; 52 bool need_larbid;
46 int port_in_larb[MTK_LARB_NR_MAX + 1]; 53 int port_in_larb[MTK_LARB_NR_MAX + 1];
@@ -149,6 +156,15 @@ mtk_smi_larb_bind(struct device *dev, struct device *master, void *data)
149 struct mtk_smi_iommu *smi_iommu = data; 156 struct mtk_smi_iommu *smi_iommu = data;
150 unsigned int i; 157 unsigned int i;
151 158
159 if (larb->larb_gen->need_larbid) {
160 larb->mmu = &smi_iommu->larb_imu[larb->larbid].mmu;
161 return 0;
162 }
163
164 /*
165 * If there is no larbid property, Loop to find the corresponding
166 * iommu information.
167 */
152 for (i = 0; i < smi_iommu->larb_nr; i++) { 168 for (i = 0; i < smi_iommu->larb_nr; i++) {
153 if (dev == smi_iommu->larb_imu[i].dev) { 169 if (dev == smi_iommu->larb_imu[i].dev) {
154 /* The 'mmu' may be updated in iommu-attach/detach. */ 170 /* The 'mmu' may be updated in iommu-attach/detach. */
@@ -159,13 +175,32 @@ mtk_smi_larb_bind(struct device *dev, struct device *master, void *data)
159 return -ENODEV; 175 return -ENODEV;
160} 176}
161 177
162static void mtk_smi_larb_config_port(struct device *dev) 178static void mtk_smi_larb_config_port_mt2712(struct device *dev)
163{ 179{
164 struct mtk_smi_larb *larb = dev_get_drvdata(dev); 180 struct mtk_smi_larb *larb = dev_get_drvdata(dev);
181 u32 reg;
182 int i;
165 183
166 writel(*larb->mmu, larb->base + SMI_LARB_MMU_EN); 184 /*
185 * larb 8/9 is the bdpsys larb, the iommu_en is enabled defaultly.
186 * Don't need to set it again.
187 */
188 if (larb->larbid == 8 || larb->larbid == 9)
189 return;
190
191 for_each_set_bit(i, (unsigned long *)larb->mmu, 32) {
192 reg = readl_relaxed(larb->base + SMI_LARB_NONSEC_CON(i));
193 reg |= F_MMU_EN;
194 writel(reg, larb->base + SMI_LARB_NONSEC_CON(i));
195 }
167} 196}
168 197
198static void mtk_smi_larb_config_port_mt8173(struct device *dev)
199{
200 struct mtk_smi_larb *larb = dev_get_drvdata(dev);
201
202 writel(*larb->mmu, larb->base + SMI_LARB_MMU_EN);
203}
169 204
170static void mtk_smi_larb_config_port_gen1(struct device *dev) 205static void mtk_smi_larb_config_port_gen1(struct device *dev)
171{ 206{
@@ -211,7 +246,7 @@ static const struct component_ops mtk_smi_larb_component_ops = {
211 246
212static const struct mtk_smi_larb_gen mtk_smi_larb_mt8173 = { 247static const struct mtk_smi_larb_gen mtk_smi_larb_mt8173 = {
213 /* mt8173 do not need the port in larb */ 248 /* mt8173 do not need the port in larb */
214 .config_port = mtk_smi_larb_config_port, 249 .config_port = mtk_smi_larb_config_port_mt8173,
215}; 250};
216 251
217static const struct mtk_smi_larb_gen mtk_smi_larb_mt2701 = { 252static const struct mtk_smi_larb_gen mtk_smi_larb_mt2701 = {
@@ -223,6 +258,11 @@ static const struct mtk_smi_larb_gen mtk_smi_larb_mt2701 = {
223 .config_port = mtk_smi_larb_config_port_gen1, 258 .config_port = mtk_smi_larb_config_port_gen1,
224}; 259};
225 260
261static const struct mtk_smi_larb_gen mtk_smi_larb_mt2712 = {
262 .need_larbid = true,
263 .config_port = mtk_smi_larb_config_port_mt2712,
264};
265
226static const struct of_device_id mtk_smi_larb_of_ids[] = { 266static const struct of_device_id mtk_smi_larb_of_ids[] = {
227 { 267 {
228 .compatible = "mediatek,mt8173-smi-larb", 268 .compatible = "mediatek,mt8173-smi-larb",
@@ -232,6 +272,10 @@ static const struct of_device_id mtk_smi_larb_of_ids[] = {
232 .compatible = "mediatek,mt2701-smi-larb", 272 .compatible = "mediatek,mt2701-smi-larb",
233 .data = &mtk_smi_larb_mt2701 273 .data = &mtk_smi_larb_mt2701
234 }, 274 },
275 {
276 .compatible = "mediatek,mt2712-smi-larb",
277 .data = &mtk_smi_larb_mt2712
278 },
235 {} 279 {}
236}; 280};
237 281
@@ -318,6 +362,10 @@ static const struct of_device_id mtk_smi_common_of_ids[] = {
318 .compatible = "mediatek,mt2701-smi-common", 362 .compatible = "mediatek,mt2701-smi-common",
319 .data = (void *)MTK_SMI_GEN1 363 .data = (void *)MTK_SMI_GEN1
320 }, 364 },
365 {
366 .compatible = "mediatek,mt2712-smi-common",
367 .data = (void *)MTK_SMI_GEN2
368 },
321 {} 369 {}
322}; 370};
323 371
diff --git a/include/soc/mediatek/smi.h b/include/soc/mediatek/smi.h
index 8893c5eacd07..5201e9022c86 100644
--- a/include/soc/mediatek/smi.h
+++ b/include/soc/mediatek/smi.h
@@ -19,7 +19,7 @@
19 19
20#ifdef CONFIG_MTK_SMI 20#ifdef CONFIG_MTK_SMI
21 21
22#define MTK_LARB_NR_MAX 8 22#define MTK_LARB_NR_MAX 16
23 23
24#define MTK_SMI_MMU_EN(port) BIT(port) 24#define MTK_SMI_MMU_EN(port) BIT(port)
25 25