diff options
| author | Yong Wu <yong.wu@mediatek.com> | 2017-08-21 07:00:16 -0400 |
|---|---|---|
| committer | Joerg Roedel <jroedel@suse.de> | 2017-08-22 10:37:58 -0400 |
| commit | e6dec92308628cff5f1f8bd1bcdf87581c9dc676 (patch) | |
| tree | d17007990ff95de3df378b2d6625f25e8b815b54 /drivers/memory | |
| parent | a9467d954226f1a513cfe789a3a39d8fc73b5d16 (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.c | 54 |
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 | |||
| 44 | struct mtk_smi_larb_gen { | 51 | struct 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 | ||
| 162 | static void mtk_smi_larb_config_port(struct device *dev) | 178 | static 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 | ||
| 198 | static 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 | ||
| 170 | static void mtk_smi_larb_config_port_gen1(struct device *dev) | 205 | static 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 | ||
| 212 | static const struct mtk_smi_larb_gen mtk_smi_larb_mt8173 = { | 247 | static 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 | ||
| 217 | static const struct mtk_smi_larb_gen mtk_smi_larb_mt2701 = { | 252 | static 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 | ||
| 261 | static 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 | |||
| 226 | static const struct of_device_id mtk_smi_larb_of_ids[] = { | 266 | static 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 | ||
