Skip to content

Commit d2e9a11

Browse files
YongWu-HFjoergroedel
authored andcommitted
iommu/mediatek: Contain MM IOMMU flow with the MM TYPE
Prepare for supporting INFRA_IOMMU, and APU_IOMMU later. For Infra IOMMU/APU IOMMU, it doesn't have the "larb""port". thus, Use the MM flag contain the MM_IOMMU special flow, Also, it moves a big chunk code about parsing the mediatek,larbs into a function, this is only needed for MM IOMMU. and all the current SoC are MM_IOMMU. The device link between iommu consumer device and smi-larb device only is needed in MM iommu case. Signed-off-by: Yong Wu <yong.wu@mediatek.com> Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com> Reviewed-by: Matthias Brugger <matthias.bgg@gmail.com> Link: https://lore.kernel.org/r/20220503071427.2285-18-yong.wu@mediatek.com Signed-off-by: Joerg Roedel <jroedel@suse.de>
1 parent 8cd1e61 commit d2e9a11

1 file changed

Lines changed: 122 additions & 91 deletions

File tree

drivers/iommu/mtk_iommu.c

Lines changed: 122 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,8 @@
138138
#define MTK_IOMMU_IS_TYPE(pdata, _x) MTK_IOMMU_HAS_FLAG_MASK(pdata, _x,\
139139
MTK_IOMMU_TYPE_MASK)
140140

141+
#define MTK_INVALID_LARBID MTK_LARB_NR_MAX
142+
141143
struct mtk_iommu_domain {
142144
struct io_pgtable_cfg cfg;
143145
struct io_pgtable_ops *iop;
@@ -274,7 +276,7 @@ static irqreturn_t mtk_iommu_isr(int irq, void *dev_id)
274276
{
275277
struct mtk_iommu_data *data = dev_id;
276278
struct mtk_iommu_domain *dom = data->m4u_dom;
277-
unsigned int fault_larb, fault_port, sub_comm = 0;
279+
unsigned int fault_larb = MTK_INVALID_LARBID, fault_port = 0, sub_comm = 0;
278280
u32 int_state, regval, va34_32, pa34_32;
279281
u64 fault_iova, fault_pa;
280282
bool layer, write;
@@ -300,17 +302,19 @@ static irqreturn_t mtk_iommu_isr(int irq, void *dev_id)
300302
pa34_32 = FIELD_GET(F_MMU_INVAL_PA_34_32_MASK, fault_iova);
301303
fault_pa |= (u64)pa34_32 << 32;
302304

303-
fault_port = F_MMU_INT_ID_PORT_ID(regval);
304-
if (MTK_IOMMU_HAS_FLAG(data->plat_data, HAS_SUB_COMM_2BITS)) {
305-
fault_larb = F_MMU_INT_ID_COMM_ID(regval);
306-
sub_comm = F_MMU_INT_ID_SUB_COMM_ID(regval);
307-
} else if (MTK_IOMMU_HAS_FLAG(data->plat_data, HAS_SUB_COMM_3BITS)) {
308-
fault_larb = F_MMU_INT_ID_COMM_ID_EXT(regval);
309-
sub_comm = F_MMU_INT_ID_SUB_COMM_ID_EXT(regval);
310-
} else {
311-
fault_larb = F_MMU_INT_ID_LARB_ID(regval);
305+
if (MTK_IOMMU_IS_TYPE(data->plat_data, MTK_IOMMU_TYPE_MM)) {
306+
fault_port = F_MMU_INT_ID_PORT_ID(regval);
307+
if (MTK_IOMMU_HAS_FLAG(data->plat_data, HAS_SUB_COMM_2BITS)) {
308+
fault_larb = F_MMU_INT_ID_COMM_ID(regval);
309+
sub_comm = F_MMU_INT_ID_SUB_COMM_ID(regval);
310+
} else if (MTK_IOMMU_HAS_FLAG(data->plat_data, HAS_SUB_COMM_3BITS)) {
311+
fault_larb = F_MMU_INT_ID_COMM_ID_EXT(regval);
312+
sub_comm = F_MMU_INT_ID_SUB_COMM_ID_EXT(regval);
313+
} else {
314+
fault_larb = F_MMU_INT_ID_LARB_ID(regval);
315+
}
316+
fault_larb = data->plat_data->larbid_remap[fault_larb][sub_comm];
312317
}
313-
fault_larb = data->plat_data->larbid_remap[fault_larb][sub_comm];
314318

315319
if (report_iommu_fault(&dom->domain, data->dev, fault_iova,
316320
write ? IOMMU_FAULT_WRITE : IOMMU_FAULT_READ)) {
@@ -374,19 +378,21 @@ static void mtk_iommu_config(struct mtk_iommu_data *data, struct device *dev,
374378
larbid = MTK_M4U_TO_LARB(fwspec->ids[i]);
375379
portid = MTK_M4U_TO_PORT(fwspec->ids[i]);
376380

377-
larb_mmu = &data->larb_imu[larbid];
381+
if (MTK_IOMMU_IS_TYPE(data->plat_data, MTK_IOMMU_TYPE_MM)) {
382+
larb_mmu = &data->larb_imu[larbid];
378383

379-
region = data->plat_data->iova_region + domid;
380-
larb_mmu->bank[portid] = upper_32_bits(region->iova_base);
384+
region = data->plat_data->iova_region + domid;
385+
larb_mmu->bank[portid] = upper_32_bits(region->iova_base);
381386

382-
dev_dbg(dev, "%s iommu for larb(%s) port %d dom %d bank %d.\n",
383-
enable ? "enable" : "disable", dev_name(larb_mmu->dev),
384-
portid, domid, larb_mmu->bank[portid]);
387+
dev_dbg(dev, "%s iommu for larb(%s) port %d dom %d bank %d.\n",
388+
enable ? "enable" : "disable", dev_name(larb_mmu->dev),
389+
portid, domid, larb_mmu->bank[portid]);
385390

386-
if (enable)
387-
larb_mmu->mmu |= MTK_SMI_MMU_EN(portid);
388-
else
389-
larb_mmu->mmu &= ~MTK_SMI_MMU_EN(portid);
391+
if (enable)
392+
larb_mmu->mmu |= MTK_SMI_MMU_EN(portid);
393+
else
394+
larb_mmu->mmu &= ~MTK_SMI_MMU_EN(portid);
395+
}
390396
}
391397
}
392398

@@ -593,6 +599,9 @@ static struct iommu_device *mtk_iommu_probe_device(struct device *dev)
593599

594600
data = dev_iommu_priv_get(dev);
595601

602+
if (!MTK_IOMMU_IS_TYPE(data->plat_data, MTK_IOMMU_TYPE_MM))
603+
return &data->iommu;
604+
596605
/*
597606
* Link the consumer device with the smi-larb device(supplier).
598607
* The device that connects with each a larb is a independent HW.
@@ -626,9 +635,11 @@ static void mtk_iommu_release_device(struct device *dev)
626635
return;
627636

628637
data = dev_iommu_priv_get(dev);
629-
larbid = MTK_M4U_TO_LARB(fwspec->ids[0]);
630-
larbdev = data->larb_imu[larbid].dev;
631-
device_link_remove(dev, larbdev);
638+
if (MTK_IOMMU_IS_TYPE(data->plat_data, MTK_IOMMU_TYPE_MM)) {
639+
larbid = MTK_M4U_TO_LARB(fwspec->ids[0]);
640+
larbdev = data->larb_imu[larbid].dev;
641+
device_link_remove(dev, larbdev);
642+
}
632643

633644
iommu_fwspec_free(dev);
634645
}
@@ -820,19 +831,77 @@ static const struct component_master_ops mtk_iommu_com_ops = {
820831
.unbind = mtk_iommu_unbind,
821832
};
822833

834+
static int mtk_iommu_mm_dts_parse(struct device *dev, struct component_match **match,
835+
struct mtk_iommu_data *data)
836+
{
837+
struct device_node *larbnode, *smicomm_node;
838+
struct platform_device *plarbdev;
839+
struct device_link *link;
840+
int i, larb_nr, ret;
841+
842+
larb_nr = of_count_phandle_with_args(dev->of_node, "mediatek,larbs", NULL);
843+
if (larb_nr < 0)
844+
return larb_nr;
845+
846+
for (i = 0; i < larb_nr; i++) {
847+
u32 id;
848+
849+
larbnode = of_parse_phandle(dev->of_node, "mediatek,larbs", i);
850+
if (!larbnode)
851+
return -EINVAL;
852+
853+
if (!of_device_is_available(larbnode)) {
854+
of_node_put(larbnode);
855+
continue;
856+
}
857+
858+
ret = of_property_read_u32(larbnode, "mediatek,larb-id", &id);
859+
if (ret)/* The id is consecutive if there is no this property */
860+
id = i;
861+
862+
plarbdev = of_find_device_by_node(larbnode);
863+
if (!plarbdev) {
864+
of_node_put(larbnode);
865+
return -ENODEV;
866+
}
867+
if (!plarbdev->dev.driver) {
868+
of_node_put(larbnode);
869+
return -EPROBE_DEFER;
870+
}
871+
data->larb_imu[id].dev = &plarbdev->dev;
872+
873+
component_match_add_release(dev, match, component_release_of,
874+
component_compare_of, larbnode);
875+
}
876+
877+
/* Get smi-common dev from the last larb. */
878+
smicomm_node = of_parse_phandle(larbnode, "mediatek,smi", 0);
879+
if (!smicomm_node)
880+
return -EINVAL;
881+
882+
plarbdev = of_find_device_by_node(smicomm_node);
883+
of_node_put(smicomm_node);
884+
data->smicomm_dev = &plarbdev->dev;
885+
886+
link = device_link_add(data->smicomm_dev, dev,
887+
DL_FLAG_STATELESS | DL_FLAG_PM_RUNTIME);
888+
if (!link) {
889+
dev_err(dev, "Unable to link %s.\n", dev_name(data->smicomm_dev));
890+
return -EINVAL;
891+
}
892+
return 0;
893+
}
894+
823895
static int mtk_iommu_probe(struct platform_device *pdev)
824896
{
825897
struct mtk_iommu_data *data;
826898
struct device *dev = &pdev->dev;
827-
struct device_node *larbnode, *smicomm_node;
828-
struct platform_device *plarbdev;
829-
struct device_link *link;
830899
struct resource *res;
831900
resource_size_t ioaddr;
832901
struct component_match *match = NULL;
833902
struct regmap *infracfg;
834903
void *protect;
835-
int i, larb_nr, ret;
904+
int ret;
836905
u32 val;
837906
char *p;
838907

@@ -887,59 +956,14 @@ static int mtk_iommu_probe(struct platform_device *pdev)
887956
return PTR_ERR(data->bclk);
888957
}
889958

890-
larb_nr = of_count_phandle_with_args(dev->of_node,
891-
"mediatek,larbs", NULL);
892-
if (larb_nr < 0)
893-
return larb_nr;
894-
895-
for (i = 0; i < larb_nr; i++) {
896-
u32 id;
897-
898-
larbnode = of_parse_phandle(dev->of_node, "mediatek,larbs", i);
899-
if (!larbnode)
900-
return -EINVAL;
901-
902-
if (!of_device_is_available(larbnode)) {
903-
of_node_put(larbnode);
904-
continue;
905-
}
906-
907-
ret = of_property_read_u32(larbnode, "mediatek,larb-id", &id);
908-
if (ret)/* The id is consecutive if there is no this property */
909-
id = i;
910-
911-
plarbdev = of_find_device_by_node(larbnode);
912-
if (!plarbdev) {
913-
of_node_put(larbnode);
914-
return -ENODEV;
915-
}
916-
if (!plarbdev->dev.driver) {
917-
of_node_put(larbnode);
918-
return -EPROBE_DEFER;
919-
}
920-
data->larb_imu[id].dev = &plarbdev->dev;
921-
922-
component_match_add_release(dev, &match, component_release_of,
923-
component_compare_of, larbnode);
924-
}
925-
926-
/* Get smi-common dev from the last larb. */
927-
smicomm_node = of_parse_phandle(larbnode, "mediatek,smi", 0);
928-
if (!smicomm_node)
929-
return -EINVAL;
930-
931-
plarbdev = of_find_device_by_node(smicomm_node);
932-
of_node_put(smicomm_node);
933-
data->smicomm_dev = &plarbdev->dev;
934-
935959
pm_runtime_enable(dev);
936960

937-
link = device_link_add(data->smicomm_dev, dev,
938-
DL_FLAG_STATELESS | DL_FLAG_PM_RUNTIME);
939-
if (!link) {
940-
dev_err(dev, "Unable to link %s.\n", dev_name(data->smicomm_dev));
941-
ret = -EINVAL;
942-
goto out_runtime_disable;
961+
if (MTK_IOMMU_IS_TYPE(data->plat_data, MTK_IOMMU_TYPE_MM)) {
962+
ret = mtk_iommu_mm_dts_parse(dev, &match, data);
963+
if (ret) {
964+
dev_err(dev, "mm dts parse fail(%d).", ret);
965+
goto out_runtime_disable;
966+
}
943967
}
944968

945969
platform_set_drvdata(pdev, data);
@@ -971,9 +995,11 @@ static int mtk_iommu_probe(struct platform_device *pdev)
971995
goto out_list_del;
972996
}
973997

974-
ret = component_master_add_with_match(dev, &mtk_iommu_com_ops, match);
975-
if (ret)
976-
goto out_bus_set_null;
998+
if (MTK_IOMMU_IS_TYPE(data->plat_data, MTK_IOMMU_TYPE_MM)) {
999+
ret = component_master_add_with_match(dev, &mtk_iommu_com_ops, match);
1000+
if (ret)
1001+
goto out_bus_set_null;
1002+
}
9771003
return ret;
9781004

9791005
out_bus_set_null:
@@ -984,7 +1010,8 @@ static int mtk_iommu_probe(struct platform_device *pdev)
9841010
out_sysfs_remove:
9851011
iommu_device_sysfs_remove(&data->iommu);
9861012
out_link_remove:
987-
device_link_remove(data->smicomm_dev, dev);
1013+
if (MTK_IOMMU_IS_TYPE(data->plat_data, MTK_IOMMU_TYPE_MM))
1014+
device_link_remove(data->smicomm_dev, dev);
9881015
out_runtime_disable:
9891016
pm_runtime_disable(dev);
9901017
return ret;
@@ -999,10 +1026,12 @@ static int mtk_iommu_remove(struct platform_device *pdev)
9991026

10001027
list_del(&data->list);
10011028

1002-
device_link_remove(data->smicomm_dev, &pdev->dev);
1029+
if (MTK_IOMMU_IS_TYPE(data->plat_data, MTK_IOMMU_TYPE_MM)) {
1030+
device_link_remove(data->smicomm_dev, &pdev->dev);
1031+
component_master_del(&pdev->dev, &mtk_iommu_com_ops);
1032+
}
10031033
pm_runtime_disable(&pdev->dev);
10041034
devm_free_irq(&pdev->dev, data->irq, data);
1005-
component_master_del(&pdev->dev, &mtk_iommu_com_ops);
10061035
return 0;
10071036
}
10081037

@@ -1072,7 +1101,8 @@ static const struct dev_pm_ops mtk_iommu_pm_ops = {
10721101

10731102
static const struct mtk_iommu_plat_data mt2712_data = {
10741103
.m4u_plat = M4U_MT2712,
1075-
.flags = HAS_4GB_MODE | HAS_BCLK | HAS_VLD_PA_RNG | SHARE_PGTABLE,
1104+
.flags = HAS_4GB_MODE | HAS_BCLK | HAS_VLD_PA_RNG | SHARE_PGTABLE |
1105+
MTK_IOMMU_TYPE_MM,
10761106
.hw_list = &m4ulist,
10771107
.inv_sel_reg = REG_MMU_INV_SEL_GEN1,
10781108
.iova_region = single_domain,
@@ -1082,7 +1112,8 @@ static const struct mtk_iommu_plat_data mt2712_data = {
10821112

10831113
static const struct mtk_iommu_plat_data mt6779_data = {
10841114
.m4u_plat = M4U_MT6779,
1085-
.flags = HAS_SUB_COMM_2BITS | OUT_ORDER_WR_EN | WR_THROT_EN,
1115+
.flags = HAS_SUB_COMM_2BITS | OUT_ORDER_WR_EN | WR_THROT_EN |
1116+
MTK_IOMMU_TYPE_MM,
10861117
.inv_sel_reg = REG_MMU_INV_SEL_GEN2,
10871118
.iova_region = single_domain,
10881119
.iova_region_nr = ARRAY_SIZE(single_domain),
@@ -1091,7 +1122,7 @@ static const struct mtk_iommu_plat_data mt6779_data = {
10911122

10921123
static const struct mtk_iommu_plat_data mt8167_data = {
10931124
.m4u_plat = M4U_MT8167,
1094-
.flags = RESET_AXI | HAS_LEGACY_IVRP_PADDR,
1125+
.flags = RESET_AXI | HAS_LEGACY_IVRP_PADDR | MTK_IOMMU_TYPE_MM,
10951126
.inv_sel_reg = REG_MMU_INV_SEL_GEN1,
10961127
.iova_region = single_domain,
10971128
.iova_region_nr = ARRAY_SIZE(single_domain),
@@ -1101,7 +1132,7 @@ static const struct mtk_iommu_plat_data mt8167_data = {
11011132
static const struct mtk_iommu_plat_data mt8173_data = {
11021133
.m4u_plat = M4U_MT8173,
11031134
.flags = HAS_4GB_MODE | HAS_BCLK | RESET_AXI |
1104-
HAS_LEGACY_IVRP_PADDR,
1135+
HAS_LEGACY_IVRP_PADDR | MTK_IOMMU_TYPE_MM,
11051136
.inv_sel_reg = REG_MMU_INV_SEL_GEN1,
11061137
.iova_region = single_domain,
11071138
.iova_region_nr = ARRAY_SIZE(single_domain),
@@ -1110,7 +1141,7 @@ static const struct mtk_iommu_plat_data mt8173_data = {
11101141

11111142
static const struct mtk_iommu_plat_data mt8183_data = {
11121143
.m4u_plat = M4U_MT8183,
1113-
.flags = RESET_AXI,
1144+
.flags = RESET_AXI | MTK_IOMMU_TYPE_MM,
11141145
.inv_sel_reg = REG_MMU_INV_SEL_GEN1,
11151146
.iova_region = single_domain,
11161147
.iova_region_nr = ARRAY_SIZE(single_domain),
@@ -1120,7 +1151,7 @@ static const struct mtk_iommu_plat_data mt8183_data = {
11201151
static const struct mtk_iommu_plat_data mt8192_data = {
11211152
.m4u_plat = M4U_MT8192,
11221153
.flags = HAS_BCLK | HAS_SUB_COMM_2BITS | OUT_ORDER_WR_EN |
1123-
WR_THROT_EN | IOVA_34_EN,
1154+
WR_THROT_EN | IOVA_34_EN | MTK_IOMMU_TYPE_MM,
11241155
.inv_sel_reg = REG_MMU_INV_SEL_GEN2,
11251156
.iova_region = mt8192_multi_dom,
11261157
.iova_region_nr = ARRAY_SIZE(mt8192_multi_dom),

0 commit comments

Comments
 (0)