From nobody Sun Sep 22 07:44:37 2024 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id E27CAC43219 for ; Thu, 7 Apr 2022 08:01:07 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231392AbiDGIDF (ORCPT ); Thu, 7 Apr 2022 04:03:05 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:44198 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S242656AbiDGICf (ORCPT ); Thu, 7 Apr 2022 04:02:35 -0400 Received: from mailgw02.mediatek.com (unknown [210.61.82.184]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id E319415A228; Thu, 7 Apr 2022 01:00:33 -0700 (PDT) X-UUID: be15bf2ca06a41be8c8577a6662dd7cf-20220407 X-UUID: be15bf2ca06a41be8c8577a6662dd7cf-20220407 Received: from mtkexhb02.mediatek.inc [(172.21.101.103)] by mailgw02.mediatek.com (envelope-from ) (Generic MTA with TLSv1.2 ECDHE-RSA-AES256-SHA384 256/256) with ESMTP id 1698868561; Thu, 07 Apr 2022 16:00:28 +0800 Received: from mtkcas11.mediatek.inc (172.21.101.40) by mtkmbs10n1.mediatek.inc (172.21.101.34) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384) id 15.2.792.15; Thu, 7 Apr 2022 16:00:07 +0800 Received: from localhost.localdomain (10.17.3.154) by mtkcas11.mediatek.inc (172.21.101.73) with Microsoft SMTP Server id 15.0.1497.2 via Frontend Transport; Thu, 7 Apr 2022 16:00:06 +0800 From: Yong Wu To: Joerg Roedel , Rob Herring , "Matthias Brugger" , Will Deacon CC: Robin Murphy , Krzysztof Kozlowski , Tomasz Figa , , , , , , , Hsin-Yi Wang , , , , , , "AngeloGioacchino Del Regno" , , , , Subject: [PATCH v6 16/34] iommu/mediatek: Contain MM IOMMU flow with the MM TYPE Date: Thu, 7 Apr 2022 15:57:08 +0800 Message-ID: <20220407075726.17771-17-yong.wu@mediatek.com> X-Mailer: git-send-email 2.18.0 In-Reply-To: <20220407075726.17771-1-yong.wu@mediatek.com> References: <20220407075726.17771-1-yong.wu@mediatek.com> MIME-Version: 1.0 X-MTK: N Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" 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 Reviewed-by: AngeloGioacchino Del Regno --- drivers/iommu/mtk_iommu.c | 212 ++++++++++++++++++++++---------------- 1 file changed, 121 insertions(+), 91 deletions(-) diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c index 642949aad47e..b048986913b9 100644 --- a/drivers/iommu/mtk_iommu.c +++ b/drivers/iommu/mtk_iommu.c @@ -138,6 +138,8 @@ #define MTK_IOMMU_IS_TYPE(pdata, _x) MTK_IOMMU_HAS_FLAG_MASK(pdata, _x,\ MTK_IOMMU_TYPE_MASK) =20 +#define MTK_INVALID_LARBID MTK_LARB_NR_MAX + struct mtk_iommu_domain { struct io_pgtable_cfg cfg; struct io_pgtable_ops *iop; @@ -274,7 +276,7 @@ static irqreturn_t mtk_iommu_isr(int irq, void *dev_id) { struct mtk_iommu_data *data =3D dev_id; struct mtk_iommu_domain *dom =3D data->m4u_dom; - unsigned int fault_larb, fault_port, sub_comm =3D 0; + unsigned int fault_larb =3D MTK_INVALID_LARBID, fault_port =3D 0, sub_com= m =3D 0; u32 int_state, regval, va34_32, pa34_32; u64 fault_iova, fault_pa; bool layer, write; @@ -300,17 +302,19 @@ static irqreturn_t mtk_iommu_isr(int irq, void *dev_i= d) pa34_32 =3D FIELD_GET(F_MMU_INVAL_PA_34_32_MASK, fault_iova); fault_pa |=3D (u64)pa34_32 << 32; =20 - fault_port =3D F_MMU_INT_ID_PORT_ID(regval); - if (MTK_IOMMU_HAS_FLAG(data->plat_data, HAS_SUB_COMM_2BITS)) { - fault_larb =3D F_MMU_INT_ID_COMM_ID(regval); - sub_comm =3D F_MMU_INT_ID_SUB_COMM_ID(regval); - } else if (MTK_IOMMU_HAS_FLAG(data->plat_data, HAS_SUB_COMM_3BITS)) { - fault_larb =3D F_MMU_INT_ID_COMM_ID_EXT(regval); - sub_comm =3D F_MMU_INT_ID_SUB_COMM_ID_EXT(regval); - } else { - fault_larb =3D F_MMU_INT_ID_LARB_ID(regval); + if (MTK_IOMMU_IS_TYPE(data->plat_data, MTK_IOMMU_TYPE_MM)) { + fault_port =3D F_MMU_INT_ID_PORT_ID(regval); + if (MTK_IOMMU_HAS_FLAG(data->plat_data, HAS_SUB_COMM_2BITS)) { + fault_larb =3D F_MMU_INT_ID_COMM_ID(regval); + sub_comm =3D F_MMU_INT_ID_SUB_COMM_ID(regval); + } else if (MTK_IOMMU_HAS_FLAG(data->plat_data, HAS_SUB_COMM_3BITS)) { + fault_larb =3D F_MMU_INT_ID_COMM_ID_EXT(regval); + sub_comm =3D F_MMU_INT_ID_SUB_COMM_ID_EXT(regval); + } else { + fault_larb =3D F_MMU_INT_ID_LARB_ID(regval); + } + fault_larb =3D data->plat_data->larbid_remap[fault_larb][sub_comm]; } - fault_larb =3D data->plat_data->larbid_remap[fault_larb][sub_comm]; =20 if (report_iommu_fault(&dom->domain, data->dev, fault_iova, write ? IOMMU_FAULT_WRITE : IOMMU_FAULT_READ)) { @@ -374,19 +378,21 @@ static void mtk_iommu_config(struct mtk_iommu_data *d= ata, struct device *dev, larbid =3D MTK_M4U_TO_LARB(fwspec->ids[i]); portid =3D MTK_M4U_TO_PORT(fwspec->ids[i]); =20 - larb_mmu =3D &data->larb_imu[larbid]; + if (MTK_IOMMU_IS_TYPE(data->plat_data, MTK_IOMMU_TYPE_MM)) { + larb_mmu =3D &data->larb_imu[larbid]; =20 - region =3D data->plat_data->iova_region + domid; - larb_mmu->bank[portid] =3D upper_32_bits(region->iova_base); + region =3D data->plat_data->iova_region + domid; + larb_mmu->bank[portid] =3D upper_32_bits(region->iova_base); =20 - dev_dbg(dev, "%s iommu for larb(%s) port %d dom %d bank %d.\n", - enable ? "enable" : "disable", dev_name(larb_mmu->dev), - portid, domid, larb_mmu->bank[portid]); + dev_dbg(dev, "%s iommu for larb(%s) port %d dom %d bank %d.\n", + enable ? "enable" : "disable", dev_name(larb_mmu->dev), + portid, domid, larb_mmu->bank[portid]); =20 - if (enable) - larb_mmu->mmu |=3D MTK_SMI_MMU_EN(portid); - else - larb_mmu->mmu &=3D ~MTK_SMI_MMU_EN(portid); + if (enable) + larb_mmu->mmu |=3D MTK_SMI_MMU_EN(portid); + else + larb_mmu->mmu &=3D ~MTK_SMI_MMU_EN(portid); + } } } =20 @@ -593,6 +599,9 @@ static struct iommu_device *mtk_iommu_probe_device(stru= ct device *dev) =20 data =3D dev_iommu_priv_get(dev); =20 + if (!MTK_IOMMU_IS_TYPE(data->plat_data, MTK_IOMMU_TYPE_MM)) + return &data->iommu; + /* * Link the consumer device with the smi-larb device(supplier). * The device that connects with each a larb is a independent HW. @@ -626,9 +635,11 @@ static void mtk_iommu_release_device(struct device *de= v) return; =20 data =3D dev_iommu_priv_get(dev); - larbid =3D MTK_M4U_TO_LARB(fwspec->ids[0]); - larbdev =3D data->larb_imu[larbid].dev; - device_link_remove(dev, larbdev); + if (MTK_IOMMU_IS_TYPE(data->plat_data, MTK_IOMMU_TYPE_MM)) { + larbid =3D MTK_M4U_TO_LARB(fwspec->ids[0]); + larbdev =3D data->larb_imu[larbid].dev; + device_link_remove(dev, larbdev); + } =20 iommu_fwspec_free(dev); } @@ -820,19 +831,77 @@ static const struct component_master_ops mtk_iommu_co= m_ops =3D { .unbind =3D mtk_iommu_unbind, }; =20 +static int mtk_iommu_mm_dts_parse(struct device *dev, struct component_mat= ch **match, + struct mtk_iommu_data *data) +{ + struct device_node *larbnode, *smicomm_node; + struct platform_device *plarbdev; + struct device_link *link; + int i, larb_nr, ret; + + larb_nr =3D of_count_phandle_with_args(dev->of_node, "mediatek,larbs", NU= LL); + if (larb_nr < 0) + return larb_nr; + + for (i =3D 0; i < larb_nr; i++) { + u32 id; + + larbnode =3D of_parse_phandle(dev->of_node, "mediatek,larbs", i); + if (!larbnode) + return -EINVAL; + + if (!of_device_is_available(larbnode)) { + of_node_put(larbnode); + continue; + } + + ret =3D of_property_read_u32(larbnode, "mediatek,larb-id", &id); + if (ret)/* The id is consecutive if there is no this property */ + id =3D i; + + plarbdev =3D of_find_device_by_node(larbnode); + if (!plarbdev) { + of_node_put(larbnode); + return -ENODEV; + } + if (!plarbdev->dev.driver) { + of_node_put(larbnode); + return -EPROBE_DEFER; + } + data->larb_imu[id].dev =3D &plarbdev->dev; + + component_match_add_release(dev, match, component_release_of, + component_compare_of, larbnode); + } + + /* Get smi-common dev from the last larb. */ + smicomm_node =3D of_parse_phandle(larbnode, "mediatek,smi", 0); + if (!smicomm_node) + return -EINVAL; + + plarbdev =3D of_find_device_by_node(smicomm_node); + of_node_put(smicomm_node); + data->smicomm_dev =3D &plarbdev->dev; + + link =3D device_link_add(data->smicomm_dev, dev, + DL_FLAG_STATELESS | DL_FLAG_PM_RUNTIME); + if (!link) { + dev_err(dev, "Unable to link %s.\n", dev_name(data->smicomm_dev)); + return -EINVAL; + } + return 0; +} + static int mtk_iommu_probe(struct platform_device *pdev) { struct mtk_iommu_data *data; struct device *dev =3D &pdev->dev; - struct device_node *larbnode, *smicomm_node; - struct platform_device *plarbdev; - struct device_link *link; struct resource *res; resource_size_t ioaddr; struct component_match *match =3D NULL; struct regmap *infracfg; void *protect; - int i, larb_nr, ret; + int ret; u32 val; char *p; =20 @@ -887,59 +956,12 @@ static int mtk_iommu_probe(struct platform_device *pd= ev) return PTR_ERR(data->bclk); } =20 - larb_nr =3D of_count_phandle_with_args(dev->of_node, - "mediatek,larbs", NULL); - if (larb_nr < 0) - return larb_nr; - - for (i =3D 0; i < larb_nr; i++) { - u32 id; - - larbnode =3D of_parse_phandle(dev->of_node, "mediatek,larbs", i); - if (!larbnode) - return -EINVAL; - - if (!of_device_is_available(larbnode)) { - of_node_put(larbnode); - continue; - } - - ret =3D of_property_read_u32(larbnode, "mediatek,larb-id", &id); - if (ret)/* The id is consecutive if there is no this property */ - id =3D i; - - plarbdev =3D of_find_device_by_node(larbnode); - if (!plarbdev) { - of_node_put(larbnode); - return -ENODEV; - } - if (!plarbdev->dev.driver) { - of_node_put(larbnode); - return -EPROBE_DEFER; - } - data->larb_imu[id].dev =3D &plarbdev->dev; - - component_match_add_release(dev, &match, component_release_of, - component_compare_of, larbnode); - } - - /* Get smi-common dev from the last larb. */ - smicomm_node =3D of_parse_phandle(larbnode, "mediatek,smi", 0); - if (!smicomm_node) - return -EINVAL; - - plarbdev =3D of_find_device_by_node(smicomm_node); - of_node_put(smicomm_node); - data->smicomm_dev =3D &plarbdev->dev; - pm_runtime_enable(dev); =20 - link =3D device_link_add(data->smicomm_dev, dev, - DL_FLAG_STATELESS | DL_FLAG_PM_RUNTIME); - if (!link) { - dev_err(dev, "Unable to link %s.\n", dev_name(data->smicomm_dev)); - ret =3D -EINVAL; - goto out_runtime_disable; + if (MTK_IOMMU_IS_TYPE(data->plat_data, MTK_IOMMU_TYPE_MM)) { + ret =3D mtk_iommu_mm_dts_parse(dev, &match, data); + if (ret) + goto out_runtime_disable; } =20 platform_set_drvdata(pdev, data); @@ -971,9 +993,11 @@ static int mtk_iommu_probe(struct platform_device *pde= v) goto out_list_del; } =20 - ret =3D component_master_add_with_match(dev, &mtk_iommu_com_ops, match); - if (ret) - goto out_bus_set_null; + if (MTK_IOMMU_IS_TYPE(data->plat_data, MTK_IOMMU_TYPE_MM)) { + ret =3D component_master_add_with_match(dev, &mtk_iommu_com_ops, match); + if (ret) + goto out_bus_set_null; + } return ret; =20 out_bus_set_null: @@ -984,7 +1008,8 @@ static int mtk_iommu_probe(struct platform_device *pde= v) out_sysfs_remove: iommu_device_sysfs_remove(&data->iommu); out_link_remove: - device_link_remove(data->smicomm_dev, dev); + if (MTK_IOMMU_IS_TYPE(data->plat_data, MTK_IOMMU_TYPE_MM)) + device_link_remove(data->smicomm_dev, dev); out_runtime_disable: pm_runtime_disable(dev); return ret; @@ -999,10 +1024,12 @@ static int mtk_iommu_remove(struct platform_device *= pdev) =20 list_del(&data->list); =20 - device_link_remove(data->smicomm_dev, &pdev->dev); + if (MTK_IOMMU_IS_TYPE(data->plat_data, MTK_IOMMU_TYPE_MM)) { + device_link_remove(data->smicomm_dev, &pdev->dev); + component_master_del(&pdev->dev, &mtk_iommu_com_ops); + } pm_runtime_disable(&pdev->dev); devm_free_irq(&pdev->dev, data->irq, data); - component_master_del(&pdev->dev, &mtk_iommu_com_ops); return 0; } =20 @@ -1073,7 +1100,7 @@ static const struct dev_pm_ops mtk_iommu_pm_ops =3D { static const struct mtk_iommu_plat_data mt2712_data =3D { .m4u_plat =3D M4U_MT2712, .flags =3D HAS_4GB_MODE | HAS_BCLK | HAS_VLD_PA_RNG | SHARE_PGTABL= E | - NOT_STD_AXI_MODE, + NOT_STD_AXI_MODE | MTK_IOMMU_TYPE_MM, .hw_list =3D &m4ulist, .inv_sel_reg =3D REG_MMU_INV_SEL_GEN1, .iova_region =3D single_domain, @@ -1084,7 +1111,7 @@ static const struct mtk_iommu_plat_data mt2712_data = =3D { static const struct mtk_iommu_plat_data mt6779_data =3D { .m4u_plat =3D M4U_MT6779, .flags =3D HAS_SUB_COMM_2BITS | OUT_ORDER_WR_EN | WR_THROT_EN | - NOT_STD_AXI_MODE, + NOT_STD_AXI_MODE | MTK_IOMMU_TYPE_MM, .inv_sel_reg =3D REG_MMU_INV_SEL_GEN2, .iova_region =3D single_domain, .iova_region_nr =3D ARRAY_SIZE(single_domain), @@ -1093,7 +1120,8 @@ static const struct mtk_iommu_plat_data mt6779_data = =3D { =20 static const struct mtk_iommu_plat_data mt8167_data =3D { .m4u_plat =3D M4U_MT8167, - .flags =3D RESET_AXI | HAS_LEGACY_IVRP_PADDR | NOT_STD_AXI_MODE, + .flags =3D RESET_AXI | HAS_LEGACY_IVRP_PADDR | NOT_STD_AXI_MODE | + MTK_IOMMU_TYPE_MM, .inv_sel_reg =3D REG_MMU_INV_SEL_GEN1, .iova_region =3D single_domain, .iova_region_nr =3D ARRAY_SIZE(single_domain), @@ -1103,7 +1131,8 @@ static const struct mtk_iommu_plat_data mt8167_data = =3D { static const struct mtk_iommu_plat_data mt8173_data =3D { .m4u_plat =3D M4U_MT8173, .flags =3D HAS_4GB_MODE | HAS_BCLK | RESET_AXI | - HAS_LEGACY_IVRP_PADDR | NOT_STD_AXI_MODE, + HAS_LEGACY_IVRP_PADDR | NOT_STD_AXI_MODE | + MTK_IOMMU_TYPE_MM, .inv_sel_reg =3D REG_MMU_INV_SEL_GEN1, .iova_region =3D single_domain, .iova_region_nr =3D ARRAY_SIZE(single_domain), @@ -1112,7 +1141,7 @@ static const struct mtk_iommu_plat_data mt8173_data = =3D { =20 static const struct mtk_iommu_plat_data mt8183_data =3D { .m4u_plat =3D M4U_MT8183, - .flags =3D RESET_AXI, + .flags =3D RESET_AXI | MTK_IOMMU_TYPE_MM, .inv_sel_reg =3D REG_MMU_INV_SEL_GEN1, .iova_region =3D single_domain, .iova_region_nr =3D ARRAY_SIZE(single_domain), @@ -1122,7 +1151,8 @@ static const struct mtk_iommu_plat_data mt8183_data = =3D { static const struct mtk_iommu_plat_data mt8192_data =3D { .m4u_plat =3D M4U_MT8192, .flags =3D HAS_BCLK | HAS_SUB_COMM_2BITS | OUT_ORDER_WR_EN | - WR_THROT_EN | IOVA_34_EN | NOT_STD_AXI_MODE, + WR_THROT_EN | IOVA_34_EN | NOT_STD_AXI_MODE | + MTK_IOMMU_TYPE_MM, .inv_sel_reg =3D REG_MMU_INV_SEL_GEN2, .iova_region =3D mt8192_multi_dom, .iova_region_nr =3D ARRAY_SIZE(mt8192_multi_dom), --=20 2.18.0