aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/memory
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 /drivers/memory
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>
Diffstat (limited to 'drivers/memory')
-rw-r--r--drivers/memory/mtk-smi.c54
1 files changed, 51 insertions, 3 deletions
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