Re: [PATCH v12 2/2] iommu/mediatek: Allow page table PA up to 35bit
On Thu, 2022-06-30 at 17:29 +0800, yf.w...@mediatek.com wrote: > From: Yunfei Wang > > Single memory zone feature will remove ZONE_DMA32 and ZONE_DMA. So > add > the quirk IO_PGTABLE_QUIRK_ARM_MTK_TTBR_EXT to let level 1 and level > 2 > pgtable support at most 35bit PA. > > Signed-off-by: Ning Li > Signed-off-by: Yunfei Wang Reviewed-by: Yong Wu ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH v3 7/7] iommu/mediatek: Remove unused "mapping" member from mtk_iommu_data
Just remove a unused variable that only is for mtk_iommu_v1. Signed-off-by: Yong Wu Reviewed-by: AngeloGioacchino Del Regno Reviewed-by: Matthias Brugger --- drivers/iommu/mtk_iommu.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c index 573b8a7f76f7..df49d3907f36 100644 --- a/drivers/iommu/mtk_iommu.c +++ b/drivers/iommu/mtk_iommu.c @@ -221,10 +221,7 @@ struct mtk_iommu_data { struct device *smicomm_dev; struct mtk_iommu_bank_data *bank; - - struct dma_iommu_mapping*mapping; /* For mtk_iommu_v1.c */ struct regmap *pericfg; - struct mutexmutex; /* Protect m4u_group/m4u_dom above */ /* -- 2.18.0 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH v3 6/7] iommu/mediatek: Improve safety for mediatek, smi property in larb nodes
No functional change. Just improve safety from dts. All the larbs that connect to one IOMMU must connect with the same smi-common. This patch checks all the mediatek,smi property for each larb, If their mediatek,smi are different, it will return fails. Also avoid there is no available smi-larb nodes. Suggested-by: Guenter Roeck Signed-off-by: Yong Wu --- drivers/iommu/mtk_iommu.c | 53 +++ 1 file changed, 37 insertions(+), 16 deletions(-) diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c index 88d0dad36067..573b8a7f76f7 100644 --- a/drivers/iommu/mtk_iommu.c +++ b/drivers/iommu/mtk_iommu.c @@ -1044,7 +1044,7 @@ static const struct component_master_ops mtk_iommu_com_ops = { static int mtk_iommu_mm_dts_parse(struct device *dev, struct component_match **match, struct mtk_iommu_data *data) { - struct device_node *larbnode, *smicomm_node, *smi_subcomm_node; + struct device_node *larbnode, *frst_avail_smicomm_node = NULL; struct platform_device *plarbdev, *pcommdev; struct device_link *link; int i, larb_nr, ret; @@ -1056,6 +1056,7 @@ static int mtk_iommu_mm_dts_parse(struct device *dev, struct component_match **m return -EINVAL; for (i = 0; i < larb_nr; i++) { + struct device_node *smicomm_node, *smi_subcomm_node; u32 id; larbnode = of_parse_phandle(dev->of_node, "mediatek,larbs", i); @@ -1096,29 +1097,49 @@ static int mtk_iommu_mm_dts_parse(struct device *dev, struct component_match **m goto err_larbdev_put; } + /* Get smi-(sub)-common dev from the last larb. */ + smi_subcomm_node = of_parse_phandle(larbnode, "mediatek,smi", 0); + if (!smi_subcomm_node) { + ret = -EINVAL; + goto err_larbdev_put; + } + + /* +* It may have two level smi-common. the node is smi-sub-common if it +* has a new mediatek,smi property. otherwise it is smi-commmon. +*/ + smicomm_node = of_parse_phandle(smi_subcomm_node, "mediatek,smi", 0); + if (smicomm_node) + of_node_put(smi_subcomm_node); + else + smicomm_node = smi_subcomm_node; + + /* +* All the larbs that connect to one IOMMU must connect with the same +* smi-common. +*/ + if (!frst_avail_smicomm_node) { + frst_avail_smicomm_node = smicomm_node; + } else if (frst_avail_smicomm_node != smicomm_node) { + dev_err(dev, "mediatek,smi property is not right @larb%d.", id); + of_node_put(smicomm_node); + ret = -EINVAL; + goto err_larbdev_put; + } else { + of_node_put(smicomm_node); + } + component_match_add(dev, match, component_compare_dev, &plarbdev->dev); platform_device_put(plarbdev); } - /* Get smi-(sub)-common dev from the last larb. */ - smi_subcomm_node = of_parse_phandle(larbnode, "mediatek,smi", 0); - if (!smi_subcomm_node) { + if (!frst_avail_smicomm_node) { ret = -EINVAL; goto err_larbdev_put; } - /* -* It may have two level smi-common. the node is smi-sub-common if it -* has a new mediatek,smi property. otherwise it is smi-commmon. -*/ - smicomm_node = of_parse_phandle(smi_subcomm_node, "mediatek,smi", 0); - if (smicomm_node) - of_node_put(smi_subcomm_node); - else - smicomm_node = smi_subcomm_node; - - pcommdev = of_find_device_by_node(smicomm_node); - of_node_put(smicomm_node); + pcommdev = of_find_device_by_node(frst_avail_smicomm_node); + of_node_put(frst_avail_smicomm_node); if (!pcommdev) { ret = -EINVAL; goto err_larbdev_put; -- 2.18.0 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH v3 5/7] iommu/mediatek: Validate number of phandles associated with "mediatek, larbs"
From: Guenter Roeck Fix the smatch warnings: drivers/iommu/mtk_iommu.c:878 mtk_iommu_mm_dts_parse() error: uninitialized symbol 'larbnode'. If someone abuse the dtsi node(Don't follow the definition of dt-binding), for example "mediatek,larbs" is provided as boolean property, "larb_nr" will be zero and cause abnormal. To fix this problem and improve the code safety, add some checking for the invalid input from dtsi, e.g. checking the larb_nr/larbid valid range, and avoid "mediatek,larb-id" property conflicts in the smi-larb nodes. Fixes: d2e9a1102cfc ("iommu/mediatek: Contain MM IOMMU flow with the MM TYPE") Reported-by: kernel test robot Reported-by: Dan Carpenter Signed-off-by: Guenter Roeck Signed-off-by: Yong Wu Reviewed-by: AngeloGioacchino Del Regno --- drivers/iommu/mtk_iommu.c | 12 1 file changed, 12 insertions(+) diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c index aa0973bafde1..88d0dad36067 100644 --- a/drivers/iommu/mtk_iommu.c +++ b/drivers/iommu/mtk_iommu.c @@ -1052,6 +1052,8 @@ static int mtk_iommu_mm_dts_parse(struct device *dev, struct component_match **m larb_nr = of_count_phandle_with_args(dev->of_node, "mediatek,larbs", NULL); if (larb_nr < 0) return larb_nr; + if (larb_nr == 0 || larb_nr > MTK_LARB_NR_MAX) + return -EINVAL; for (i = 0; i < larb_nr; i++) { u32 id; @@ -1070,6 +1072,11 @@ static int mtk_iommu_mm_dts_parse(struct device *dev, struct component_match **m ret = of_property_read_u32(larbnode, "mediatek,larb-id", &id); if (ret)/* The id is consecutive if there is no this property */ id = i; + if (id >= MTK_LARB_NR_MAX) { + of_node_put(larbnode); + ret = -EINVAL; + goto err_larbdev_put; + } plarbdev = of_find_device_by_node(larbnode); of_node_put(larbnode); @@ -1077,6 +1084,11 @@ static int mtk_iommu_mm_dts_parse(struct device *dev, struct component_match **m ret = -ENODEV; goto err_larbdev_put; } + if (data->larb_imu[id].dev) { + platform_device_put(plarbdev); + ret = -EEXIST; + goto err_larbdev_put; + } data->larb_imu[id].dev = &plarbdev->dev; if (!plarbdev->dev.driver) { -- 2.18.0 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH v3 4/7] iommu/mediatek: Add error path for loop of mm_dts_parse
The mtk_iommu_mm_dts_parse will parse the smi larbs nodes. if the i+1 larb is parsed fail, we should put_device for the 0..i larbs. There are two places need to comment: 1) The larbid may be not linear mapping, we should loop whole the array in the error path. 2) I move this line position: "data->larb_imu[id].dev = &plarbdev->dev;" That means set data->larb_imu[id].dev before the error path. then we don't need "platform_device_put(plarbdev)" again while probe_defer case. All depend on "put_device" in the error path in error cases. Fixes: d2e9a1102cfc ("iommu/mediatek: Contain MM IOMMU flow with the MM TYPE") Signed-off-by: Yong Wu --- drivers/iommu/mtk_iommu.c | 42 --- 1 file changed, 30 insertions(+), 12 deletions(-) diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c index 3da8c6252c2c..aa0973bafde1 100644 --- a/drivers/iommu/mtk_iommu.c +++ b/drivers/iommu/mtk_iommu.c @@ -1057,8 +1057,10 @@ static int mtk_iommu_mm_dts_parse(struct device *dev, struct component_match **m u32 id; larbnode = of_parse_phandle(dev->of_node, "mediatek,larbs", i); - if (!larbnode) - return -EINVAL; + if (!larbnode) { + ret = -EINVAL; + goto err_larbdev_put; + } if (!of_device_is_available(larbnode)) { of_node_put(larbnode); @@ -1071,14 +1073,16 @@ static int mtk_iommu_mm_dts_parse(struct device *dev, struct component_match **m plarbdev = of_find_device_by_node(larbnode); of_node_put(larbnode); - if (!plarbdev) - return -ENODEV; + if (!plarbdev) { + ret = -ENODEV; + goto err_larbdev_put; + } + data->larb_imu[id].dev = &plarbdev->dev; if (!plarbdev->dev.driver) { - platform_device_put(plarbdev); - return -EPROBE_DEFER; + ret = -EPROBE_DEFER; + goto err_larbdev_put; } - data->larb_imu[id].dev = &plarbdev->dev; component_match_add(dev, match, component_compare_dev, &plarbdev->dev); platform_device_put(plarbdev); @@ -1086,8 +1090,10 @@ static int mtk_iommu_mm_dts_parse(struct device *dev, struct component_match **m /* Get smi-(sub)-common dev from the last larb. */ smi_subcomm_node = of_parse_phandle(larbnode, "mediatek,smi", 0); - if (!smi_subcomm_node) - return -EINVAL; + if (!smi_subcomm_node) { + ret = -EINVAL; + goto err_larbdev_put; + } /* * It may have two level smi-common. the node is smi-sub-common if it @@ -1101,8 +1107,10 @@ static int mtk_iommu_mm_dts_parse(struct device *dev, struct component_match **m pcommdev = of_find_device_by_node(smicomm_node); of_node_put(smicomm_node); - if (!pcommdev) - return -EINVAL; + if (!pcommdev) { + ret = -EINVAL; + goto err_larbdev_put; + } data->smicomm_dev = &pcommdev->dev; link = device_link_add(data->smicomm_dev, dev, @@ -1110,9 +1118,19 @@ static int mtk_iommu_mm_dts_parse(struct device *dev, struct component_match **m platform_device_put(pcommdev); if (!link) { dev_err(dev, "Unable to link %s.\n", dev_name(data->smicomm_dev)); - return -EINVAL; + ret = -EINVAL; + goto err_larbdev_put; } return 0; + +err_larbdev_put: + /* id may be not linear mapping, loop whole the array */ + for (i = 0; i < MTK_LARB_NR_MAX; i++) { + if (!data->larb_imu[i].dev) + continue; + put_device(data->larb_imu[i].dev); + } + return ret; } static int mtk_iommu_probe(struct platform_device *pdev) -- 2.18.0 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH v3 3/7] iommu/mediatek: Use component_match_add
In order to simplify the error patch(avoid call of_node_put), Use component_match_add instead component_match_add_release since we are only interested in the "device" here. Then we could always call of_node_put in normal path. Strictly this is not a fixes patch, but it is a prepare for adding the error path, thus I add a Fixes tag too. Fixes: d2e9a1102cfc ("iommu/mediatek: Contain MM IOMMU flow with the MM TYPE") Suggested-by: Robin Murphy Signed-off-by: Yong Wu --- drivers/iommu/mtk_iommu.c | 10 -- 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c index 151ab46d4eac..3da8c6252c2c 100644 --- a/drivers/iommu/mtk_iommu.c +++ b/drivers/iommu/mtk_iommu.c @@ -1070,19 +1070,17 @@ static int mtk_iommu_mm_dts_parse(struct device *dev, struct component_match **m id = i; plarbdev = of_find_device_by_node(larbnode); - if (!plarbdev) { - of_node_put(larbnode); + of_node_put(larbnode); + if (!plarbdev) return -ENODEV; - } + if (!plarbdev->dev.driver) { - of_node_put(larbnode); platform_device_put(plarbdev); return -EPROBE_DEFER; } data->larb_imu[id].dev = &plarbdev->dev; - component_match_add_release(dev, match, component_release_of, - component_compare_of, larbnode); + component_match_add(dev, match, component_compare_dev, &plarbdev->dev); platform_device_put(plarbdev); } -- 2.18.0 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH v3 2/7] iommu/mediatek: Add platform_device_put for recovering the device refcnt
Add platform_device_put to match with of_find_device_by_node. Meanwhile, I add a new variable "pcommdev" which is for smi common device. Otherwise, "platform_device_put(plarbdev)" for smi-common dev may be not readable. And add a checking for whether pcommdev is NULL. Fixes: d2e9a1102cfc ("iommu/mediatek: Contain MM IOMMU flow with the MM TYPE") Signed-off-by: Yong Wu --- drivers/iommu/mtk_iommu.c | 11 --- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c index 3b2489e8a6dd..151ab46d4eac 100644 --- a/drivers/iommu/mtk_iommu.c +++ b/drivers/iommu/mtk_iommu.c @@ -1045,7 +1045,7 @@ static int mtk_iommu_mm_dts_parse(struct device *dev, struct component_match **m struct mtk_iommu_data *data) { struct device_node *larbnode, *smicomm_node, *smi_subcomm_node; - struct platform_device *plarbdev; + struct platform_device *plarbdev, *pcommdev; struct device_link *link; int i, larb_nr, ret; @@ -1076,12 +1076,14 @@ static int mtk_iommu_mm_dts_parse(struct device *dev, struct component_match **m } if (!plarbdev->dev.driver) { of_node_put(larbnode); + platform_device_put(plarbdev); return -EPROBE_DEFER; } data->larb_imu[id].dev = &plarbdev->dev; component_match_add_release(dev, match, component_release_of, component_compare_of, larbnode); + platform_device_put(plarbdev); } /* Get smi-(sub)-common dev from the last larb. */ @@ -1099,12 +1101,15 @@ static int mtk_iommu_mm_dts_parse(struct device *dev, struct component_match **m else smicomm_node = smi_subcomm_node; - plarbdev = of_find_device_by_node(smicomm_node); + pcommdev = of_find_device_by_node(smicomm_node); of_node_put(smicomm_node); - data->smicomm_dev = &plarbdev->dev; + if (!pcommdev) + return -EINVAL; + data->smicomm_dev = &pcommdev->dev; link = device_link_add(data->smicomm_dev, dev, DL_FLAG_STATELESS | DL_FLAG_PM_RUNTIME); + platform_device_put(pcommdev); if (!link) { dev_err(dev, "Unable to link %s.\n", dev_name(data->smicomm_dev)); return -EINVAL; -- 2.18.0 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH v3 1/7] iommu/mediatek: Use dev_err_probe to mute probe_defer err log
Mute the probe defer log: [2.654806] mtk-iommu 14018000.iommu: mm dts parse fail(-517). [2.656168] mtk-iommu 1c01f000.iommu: mm dts parse fail(-517). Fixes: d2e9a1102cfc ("iommu/mediatek: Contain MM IOMMU flow with the MM TYPE") Signed-off-by: Yong Wu Reviewed-by: AngeloGioacchino Del Regno Reviewed-by: Guenter Roeck Reviewed-by: Matthias Brugger --- drivers/iommu/mtk_iommu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c index bb9dd92c9898..3b2489e8a6dd 100644 --- a/drivers/iommu/mtk_iommu.c +++ b/drivers/iommu/mtk_iommu.c @@ -1204,7 +1204,7 @@ static int mtk_iommu_probe(struct platform_device *pdev) if (MTK_IOMMU_IS_TYPE(data->plat_data, MTK_IOMMU_TYPE_MM)) { ret = mtk_iommu_mm_dts_parse(dev, &match, data); if (ret) { - dev_err(dev, "mm dts parse fail(%d).", ret); + dev_err_probe(dev, ret, "mm dts parse fail."); goto out_runtime_disable; } } else if (MTK_IOMMU_IS_TYPE(data->plat_data, MTK_IOMMU_TYPE_INFRA) && -- 2.18.0 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH v3 0/7] iommu/mediatek: Improve safety from invalid dts input
This patchset contains misc improve patches. Mainly to improve safety from invalid dts input. Change notes: v3: a) Add platform_device_put from Robin. b) Use component_match_add instead component_match_add_release suggested from Robin. v2: https://lore.kernel.org/linux-mediatek/20220616054203.11365-1-yong...@mediatek.com/ a) Rebase on v5.19-rc1. b) Add a New patch [5/5] just remove a variable that only is for v1. v1: https://lore.kernel.org/linux-mediatek/20220511064920.18455-1-yong...@mediatek.com/ Base on linux-next-20220510. the improve safety from dts is base on: https://lore.kernel.org/linux-mediatek/20211210205704.1664928-1-li...@roeck-us.net/ Guenter Roeck (1): iommu/mediatek: Validate number of phandles associated with "mediatek,larbs" Yong Wu (6): iommu/mediatek: Use dev_err_probe to mute probe_defer err log iommu/mediatek: Remove unused "mapping" member from mtk_iommu_data iommu/mediatek: Add platform_device_put for recovering the device refcnt iommu/mediatek: Use component_match_add iommu/mediatek: Add error path for loop of mm_dts_parse iommu/mediatek: Improve safety for mediatek,smi property in larb nodes drivers/iommu/mtk_iommu.c | 117 +++--- 1 file changed, 84 insertions(+), 33 deletions(-) -- 2.18.0 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH v3 1/5] iommu: Return -EMEDIUMTYPE for incompatible domain and device/group
On Wed, 2022-06-29 at 12:47 -0700, Nicolin Chen wrote: > On Fri, Jun 24, 2022 at 03:19:43PM -0300, Jason Gunthorpe wrote: > > On Fri, Jun 24, 2022 at 06:35:49PM +0800, Yong Wu wrote: > > > > > > > It's not used in VFIO context. "return 0" just satisfy the > > > > > iommu > > > > > framework to go ahead. and yes, here we only allow the shared > > > > > "mapping-domain" (All the devices share a domain created > > > > > internally). > > > > What part of the iommu framework is trying to attach a domain and > > wants to see success when the domain was not actually attached ? > > > > > > What prevent this driver from being used in VFIO context? > > > > > > Nothing prevent this. Just I didn't test. > > > > This is why it is wrong to return success here. > > Hi Yong, would you or someone you know be able to confirm whether > this "return 0" is still a must or not? > > Considering that it's an old 32-bit platform for MTK, if it would > take time to do so, I'd like to drop the change in MTK driver and > note in commit log for you or other MTK folks to change in future. Yes. Please help drop the change in this file. Sorry I don't have the board at hand right now and I could not list the backtrace where this is needed(should be bus_iommu_probe from the previous debug...) > > Thanks > Nic ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH v3 1/5] iommu: Return -EMEDIUMTYPE for incompatible domain and device/group
On Fri, 2022-06-24 at 06:16 +, Tian, Kevin wrote: > > From: Yong Wu > > Sent: Friday, June 24, 2022 1:39 PM > > > > On Thu, 2022-06-23 at 19:44 -0700, Nicolin Chen wrote: > > > On Fri, Jun 24, 2022 at 09:35:49AM +0800, Baolu Lu wrote: > > > > External email: Use caution opening links or attachments > > > > > > > > > > > > On 2022/6/24 04:00, Nicolin Chen wrote: > > > > > diff --git a/drivers/iommu/mtk_iommu_v1.c > > > > > b/drivers/iommu/mtk_iommu_v1.c > > > > > index e1cb51b9866c..5386d889429d 100644 > > > > > --- a/drivers/iommu/mtk_iommu_v1.c > > > > > +++ b/drivers/iommu/mtk_iommu_v1.c > > > > > @@ -304,7 +304,7 @@ static int > > > > > mtk_iommu_v1_attach_device(struct > > > > > iommu_domain *domain, struct device > > > > > /* Only allow the domain created internally. */ > > > > > mtk_mapping = data->mapping; > > > > > if (mtk_mapping->domain != domain) > > > > > - return 0; > > > > > + return -EMEDIUMTYPE; > > > > > > > > > > if (!data->m4u_dom) { > > > > > data->m4u_dom = dom; > > > > > > > > This change looks odd. It turns the return value from success > > > > to > > > > failure. Is it a bug? If so, it should go through a separated > > > > fix > > > > patch. > > > > Thanks for the review:) > > > > > > > > Makes sense. > > > > > > I read the commit log of the original change: > > > > > > > https://lore.kernel.org/r/1589530123-30240-1-git-send-email- > > yong...@mediatek.com > > > > > > It doesn't seem to allow devices to get attached to different > > > domains other than the shared mapping->domain, created in the > > > in the mtk_iommu_probe_device(). So it looks like returning 0 > > > is intentional. Though I am still very confused by this return > > > value here, I doubt it has ever been used in a VFIO context. > > > > It's not used in VFIO context. "return 0" just satisfy the iommu > > framework to go ahead. and yes, here we only allow the shared > > "mapping- > > > domain" (All the devices share a domain created internally). > > > > thus I think we should still keep "return 0" here. > > > > What prevent this driver from being used in VFIO context? Nothing prevent this. Just I didn't test. mtk_iommu_v1.c only is used in mt2701 and there is no VFIO scenario. I'm not sure if it supports VFIO. (mtk_iommu.c support VFIO.) > and why would we want to go ahead when an obvious error occurs > i.e. when a device is attached to an unexpected domain? The iommu flow in this file always is a bit odd as we need share iommu domain in ARM32. As I tested before in the above link, "The iommu framework will create a iommu domain for each a device.", therefore we have to *workaround* in this file. And this was expected to be fixed by: https://lore.kernel.org/linux-iommu/cover.1597931875.git.robin.mur...@arm.com/ sorry, I don't know its current status. Thanks. ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH v3 1/5] iommu: Return -EMEDIUMTYPE for incompatible domain and device/group
On Thu, 2022-06-23 at 19:44 -0700, Nicolin Chen wrote: > On Fri, Jun 24, 2022 at 09:35:49AM +0800, Baolu Lu wrote: > > External email: Use caution opening links or attachments > > > > > > On 2022/6/24 04:00, Nicolin Chen wrote: > > > diff --git a/drivers/iommu/mtk_iommu_v1.c > > > b/drivers/iommu/mtk_iommu_v1.c > > > index e1cb51b9866c..5386d889429d 100644 > > > --- a/drivers/iommu/mtk_iommu_v1.c > > > +++ b/drivers/iommu/mtk_iommu_v1.c > > > @@ -304,7 +304,7 @@ static int mtk_iommu_v1_attach_device(struct > > > iommu_domain *domain, struct device > > > /* Only allow the domain created internally. */ > > > mtk_mapping = data->mapping; > > > if (mtk_mapping->domain != domain) > > > - return 0; > > > + return -EMEDIUMTYPE; > > > > > > if (!data->m4u_dom) { > > > data->m4u_dom = dom; > > > > This change looks odd. It turns the return value from success to > > failure. Is it a bug? If so, it should go through a separated fix > > patch. Thanks for the review:) > > Makes sense. > > I read the commit log of the original change: > https://lore.kernel.org/r/1589530123-30240-1-git-send-email-yong...@mediatek.com > > It doesn't seem to allow devices to get attached to different > domains other than the shared mapping->domain, created in the > in the mtk_iommu_probe_device(). So it looks like returning 0 > is intentional. Though I am still very confused by this return > value here, I doubt it has ever been used in a VFIO context. It's not used in VFIO context. "return 0" just satisfy the iommu framework to go ahead. and yes, here we only allow the shared "mapping- >domain" (All the devices share a domain created internally). thus I think we should still keep "return 0" here. Thanks:) > > Young, would you please give us some input? > > Overall, I feel it's better to play it safe here by dropping > this part. If we later confirm there is a need to fix it, we > will do that in a separate patch anyway. > > Thanks > Nic ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH v2 2/5] iommu/mediatek: Add error path for loop of mm_dts_parse
On Thu, 2022-06-16 at 15:49 +0200, Matthias Brugger wrote: > > On 16/06/2022 07:42, Yong Wu wrote: > > The mtk_iommu_mm_dts_parse will parse the smi larbs nodes. if the > > i+1 > > larb is parsed fail(return -EINVAL), we should of_node_put for the > > 0..i > > larbs. In the fail path, one of_node_put matches with > > of_parse_phandle in > > it. > > > > Fixes: d2e9a1102cfc ("iommu/mediatek: Contain MM IOMMU flow with > > the MM TYPE") > > Signed-off-by: Yong Wu > > --- > > drivers/iommu/mtk_iommu.c | 21 - > > 1 file changed, 16 insertions(+), 5 deletions(-) > > > > diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c > > index 3b2489e8a6dd..ab24078938bf 100644 > > --- a/drivers/iommu/mtk_iommu.c > > +++ b/drivers/iommu/mtk_iommu.c > > @@ -1071,12 +1071,12 @@ static int mtk_iommu_mm_dts_parse(struct > > device *dev, struct component_match **m > > > > Don't we need to call the goto also on error case of: > > larbnode = of_parse_phandle(dev->of_node, "mediatek,larbs", i); Thanks very much. exactly right. I will add in next version. > Regards, > Matthias ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH v2 2/5] iommu/mediatek: Add error path for loop of mm_dts_parse
On Thu, 2022-06-16 at 11:31 +0100, Robin Murphy wrote: > On 2022-06-16 11:08, Yong Wu wrote: > > On Thu, 2022-06-16 at 09:59 +0100, Robin Murphy wrote: > > > On 2022-06-16 06:42, Yong Wu wrote: > > > > The mtk_iommu_mm_dts_parse will parse the smi larbs nodes. if > > > > the > > > > i+1 > > > > larb is parsed fail(return -EINVAL), we should of_node_put for > > > > the > > > > 0..i > > > > larbs. In the fail path, one of_node_put matches with > > > > of_parse_phandle in > > > > it. > > > > > > > > Fixes: d2e9a1102cfc ("iommu/mediatek: Contain MM IOMMU flow > > > > with > > > > the MM TYPE") > > > > Signed-off-by: Yong Wu > > > > --- > > > >drivers/iommu/mtk_iommu.c | 21 - > > > >1 file changed, 16 insertions(+), 5 deletions(-) [snip..] > > > > +err_larbnode_put: > > > > + while (i--) { > > > > + larbnode = of_parse_phandle(dev->of_node, > > > > "mediatek,larbs", i); > > > > + if (larbnode && > > > > of_device_is_available(larbnode)) { > > > > + of_node_put(larbnode); > > > > + of_node_put(larbnode); > > > > + } > > > > > > This looks a bit awkward - could we not just iterate through > > > data->larb_imu and put dev->of_node for each valid dev? > > > > It should work. Thanks very much. > > > > > > > > Also, of_find_device_by_node() takes a reference on the struct > > > device > > > itself, so strictly we should be doing put_device() on those as > > > well > > > if we're bailing out. > > > > Thanks for this hint. A new reference for me. I will add it. > > In fact, thinking about it some more we may as well do the > of_node_put() > unconditionally immediately after the of_find_device_by_node() call, of_node_put is called in component_release_of in the normal case, thus we shouldn't call of_node_put unconditionally. Right? (Sorry for reply late) > so > then it's *only* the device references we'd need to worry about > cleaning > up in the failure path. > > Robin. ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH v10 1/2] iommu/io-pgtable-arm-v7s: Add a quirk to allow pgtable PA up to 35bit
On Thu, 2022-06-16 at 20:07 +0800, yf.w...@mediatek.com wrote: > From: Yunfei Wang > > Single memory zone feature will remove ZONE_DMA32 and ZONE_DMA and > cause pgtable PA size larger than 32bit. > > Since Mediatek IOMMU hardware support at most 35bit PA in pgtable, > so add a quirk to allow the PA of pgtables support up to bit35. > > Signed-off-by: Ning Li > Signed-off-by: Yunfei Wang > --- > drivers/iommu/io-pgtable-arm-v7s.c | 67 +++- > -- > include/linux/io-pgtable.h | 15 --- > 2 files changed, 63 insertions(+), 19 deletions(-) [...] > /* TTBR */ > - cfg->arm_v7s_cfg.ttbr = virt_to_phys(data->pgd) | > ARM_V7S_TTBR_S | > + paddr = virt_to_phys(data->pgd); > + cfg->arm_v7s_cfg.ttbr = paddr | ARM_V7S_TTBR_S | > (cfg->coherent_walk ? (ARM_V7S_TTBR_NOS > | >ARM_V7S_TTBR_IRGN_ATTR(ARM_V7S_RGN_WBW > A) | >ARM_V7S_TTBR_ORGN_ATTR(ARM_V7S_RGN_WBW > A)) : > (ARM_V7S_TTBR_IRGN_ATTR(ARM_V7S_RGN_NC) > | >ARM_V7S_TTBR_ORGN_ATTR(ARM_V7S_RGN_NC) > )); > + > + if (cfg->quirks & IO_PGTABLE_QUIRK_ARM_MTK_TTBR_EXT) > + cfg->arm_v7s_cfg.ttbr = (paddr & GENMASK(31, 7)) | > + upper_32_bits(paddr); If we keep ttbr u32, we have to put the special logic here. This line is ok for all the MediaTek cases, not only for this quirk. It means: if (arm_v7s_is_mtk_enabled(cfg)) cfg->arm_v7s_cfg.ttbr = (virt_to_phys(data->pgd) & GENMASK(31, 7)) | upper_32_bits(paddr); else xxx Then we don't need add "& MMU_PT_ADDR_MASK" in mtk_iommu.c since you have done it here. > + > return &data->iop; > ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH v2 2/5] iommu/mediatek: Add error path for loop of mm_dts_parse
On Thu, 2022-06-16 at 09:59 +0100, Robin Murphy wrote: > On 2022-06-16 06:42, Yong Wu wrote: > > The mtk_iommu_mm_dts_parse will parse the smi larbs nodes. if the > > i+1 > > larb is parsed fail(return -EINVAL), we should of_node_put for the > > 0..i > > larbs. In the fail path, one of_node_put matches with > > of_parse_phandle in > > it. > > > > Fixes: d2e9a1102cfc ("iommu/mediatek: Contain MM IOMMU flow with > > the MM TYPE") > > Signed-off-by: Yong Wu > > --- > > drivers/iommu/mtk_iommu.c | 21 - > > 1 file changed, 16 insertions(+), 5 deletions(-) > > > > diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c > > index 3b2489e8a6dd..ab24078938bf 100644 > > --- a/drivers/iommu/mtk_iommu.c > > +++ b/drivers/iommu/mtk_iommu.c > > @@ -1071,12 +1071,12 @@ static int mtk_iommu_mm_dts_parse(struct > > device *dev, struct component_match **m > > > > plarbdev = of_find_device_by_node(larbnode); > > if (!plarbdev) { > > - of_node_put(larbnode); > > - return -ENODEV; > > + ret = -ENODEV; > > + goto err_larbnode_put; > > } > > if (!plarbdev->dev.driver) { > > - of_node_put(larbnode); > > - return -EPROBE_DEFER; > > + ret = -EPROBE_DEFER; > > + goto err_larbnode_put; > > } > > data->larb_imu[id].dev = &plarbdev->dev; > > > > @@ -1107,9 +1107,20 @@ static int mtk_iommu_mm_dts_parse(struct > > device *dev, struct component_match **m > >DL_FLAG_STATELESS | DL_FLAG_PM_RUNTIME); > > if (!link) { > > dev_err(dev, "Unable to link %s.\n", dev_name(data- > > >smicomm_dev)); > > - return -EINVAL; > > + ret = -EINVAL; > > + goto err_larbnode_put; > > } > > return 0; > > + > > +err_larbnode_put: > > + while (i--) { > > + larbnode = of_parse_phandle(dev->of_node, > > "mediatek,larbs", i); > > + if (larbnode && of_device_is_available(larbnode)) { > > + of_node_put(larbnode); > > + of_node_put(larbnode); > > + } > > This looks a bit awkward - could we not just iterate through > data->larb_imu and put dev->of_node for each valid dev? It should work. Thanks very much. > > Also, of_find_device_by_node() takes a reference on the struct > device > itself, so strictly we should be doing put_device() on those as well > if we're bailing out. Thanks for this hint. A new reference for me. I will add it. > > Robin. > > > + } > > + return ret; > > } > > > > static int mtk_iommu_probe(struct platform_device *pdev) ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH v3 6/6] iommu: mtk_iommu: Lookup phandle to retrieve syscon to pericfg
On Mon, 2022-06-13 at 10:13 +0200, AngeloGioacchino Del Regno wrote: > Il 13/06/22 07:32, Yong Wu ha scritto: > > On Thu, 2022-06-09 at 12:08 +0200, AngeloGioacchino Del Regno > > wrote: > > > On some SoCs (of which only MT8195 is supported at the time of > > > writing), > > > the "R" and "W" (I/O) enable bits for the IOMMUs are in the > > > pericfg_ao > > > register space and not in the IOMMU space: as it happened already > > > with > > > infracfg, it is expected that this list will grow. > > > > Currently I don't see the list will grow. As commented before, In > > the > > lastest SoC, The IOMMU enable bits for IOMMU will be in ATF, rather > > than in this pericfg register region. In this case, Is this patch > > unnecessary? or we could add this patch when there are 2 SoCs use > > this > > setting at least? what's your opinion? > > > > Perhaps I've misunderstood... besides, can you please check if > there's any > other SoC (not just chromebooks, also smartphone SoCs) that need this > logic? As far as I know, SmartPhone SoCs don't enable the infra iommu until now. they don't have this logic. I don't object this patch, I think we could add it when at least 2 SoCs need this. Thanks very much for help improving here. > > Thanks, > Angelo > > ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH v2 5/5] iommu/mediatek: Remove a unused "mapping" which is only for v1
Just remove a unused variable that only is for mtk_iommu_v1. Fixes: 9485a04a5bb9 ("iommu/mediatek: Separate mtk_iommu_data for v1 and v2") Signed-off-by: Yong Wu --- drivers/iommu/mtk_iommu.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c index 5e86fd48928a..e65e705d9fc1 100644 --- a/drivers/iommu/mtk_iommu.c +++ b/drivers/iommu/mtk_iommu.c @@ -221,10 +221,7 @@ struct mtk_iommu_data { struct device *smicomm_dev; struct mtk_iommu_bank_data *bank; - - struct dma_iommu_mapping*mapping; /* For mtk_iommu_v1.c */ struct regmap *pericfg; - struct mutexmutex; /* Protect m4u_group/m4u_dom above */ /* -- 2.18.0 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH v2 4/5] iommu/mediatek: Improve safety for mediatek, smi property in larb nodes
No functional change. Just improve safety from dts. All the larbs that connect to one IOMMU must connect with the same smi-common. This patch checks all the mediatek,smi property for each larb, If their mediatek,smi are different, it will return fails. Also avoid there is no available smi-larb nodes. Suggested-by: Guenter Roeck Signed-off-by: Yong Wu --- drivers/iommu/mtk_iommu.c | 49 ++- 1 file changed, 33 insertions(+), 16 deletions(-) diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c index a869d4aee7b3..5e86fd48928a 100644 --- a/drivers/iommu/mtk_iommu.c +++ b/drivers/iommu/mtk_iommu.c @@ -1044,7 +1044,7 @@ static const struct component_master_ops mtk_iommu_com_ops = { static int mtk_iommu_mm_dts_parse(struct device *dev, struct component_match **match, struct mtk_iommu_data *data) { - struct device_node *larbnode, *smicomm_node, *smi_subcomm_node; + struct device_node *larbnode, *frst_avail_smicomm_node = NULL; struct platform_device *plarbdev; struct device_link *link; int i, larb_nr, ret; @@ -1056,6 +1056,7 @@ static int mtk_iommu_mm_dts_parse(struct device *dev, struct component_match **m return -EINVAL; for (i = 0; i < larb_nr; i++) { + struct device_node *smicomm_node, *smi_subcomm_node; u32 id; larbnode = of_parse_phandle(dev->of_node, "mediatek,larbs", i); @@ -1091,27 +1092,43 @@ static int mtk_iommu_mm_dts_parse(struct device *dev, struct component_match **m } data->larb_imu[id].dev = &plarbdev->dev; + /* Get smi-(sub)-common dev from the last larb. */ + smi_subcomm_node = of_parse_phandle(larbnode, "mediatek,smi", 0); + if (!smi_subcomm_node) { + ret = -EINVAL; + goto err_larbnode_put; + } + + /* +* It may have two level smi-common. the node is smi-sub-common if it +* has a new mediatek,smi property. otherwise it is smi-commmon. +*/ + smicomm_node = of_parse_phandle(smi_subcomm_node, "mediatek,smi", 0); + if (smicomm_node) + of_node_put(smi_subcomm_node); + else + smicomm_node = smi_subcomm_node; + + if (!frst_avail_smicomm_node) { + frst_avail_smicomm_node = smicomm_node; + } else if (frst_avail_smicomm_node != smicomm_node) { + dev_err(dev, "mediatek,smi is not right @larb%d.", id); + of_node_put(smicomm_node); + ret = -EINVAL; + goto err_larbnode_put; + } else { + of_node_put(smicomm_node); + } + component_match_add_release(dev, match, component_release_of, component_compare_of, larbnode); } - /* Get smi-(sub)-common dev from the last larb. */ - smi_subcomm_node = of_parse_phandle(larbnode, "mediatek,smi", 0); - if (!smi_subcomm_node) + if (!frst_avail_smicomm_node) return -EINVAL; - /* -* It may have two level smi-common. the node is smi-sub-common if it -* has a new mediatek,smi property. otherwise it is smi-commmon. -*/ - smicomm_node = of_parse_phandle(smi_subcomm_node, "mediatek,smi", 0); - if (smicomm_node) - of_node_put(smi_subcomm_node); - else - smicomm_node = smi_subcomm_node; - - plarbdev = of_find_device_by_node(smicomm_node); - of_node_put(smicomm_node); + plarbdev = of_find_device_by_node(frst_avail_smicomm_node); + of_node_put(frst_avail_smicomm_node); data->smicomm_dev = &plarbdev->dev; link = device_link_add(data->smicomm_dev, dev, -- 2.18.0 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH v2 3/5] iommu/mediatek: Validate number of phandles associated with "mediatek, larbs"
From: Guenter Roeck Fix the smatch warnings: drivers/iommu/mtk_iommu.c:878 mtk_iommu_mm_dts_parse() error: uninitialized symbol 'larbnode'. If someone abuse the dtsi node(Don't follow the definition of dt-binding), for example "mediatek,larbs" is provided as boolean property, "larb_nr" will be zero and cause abnormal. To fix this problem and improve the code safety, add some checking for the invalid input from dtsi, e.g. checking the larb_nr/larbid valid range, and avoid "mediatek,larb-id" property conflicts in the smi-larb nodes. Fixes: d2e9a1102cfc ("iommu/mediatek: Contain MM IOMMU flow with the MM TYPE") Reported-by: kernel test robot Reported-by: Dan Carpenter Signed-off-by: Guenter Roeck Signed-off-by: Yong Wu Reviewed-by: AngeloGioacchino Del Regno --- drivers/iommu/mtk_iommu.c | 11 +++ 1 file changed, 11 insertions(+) diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c index ab24078938bf..a869d4aee7b3 100644 --- a/drivers/iommu/mtk_iommu.c +++ b/drivers/iommu/mtk_iommu.c @@ -1052,6 +1052,8 @@ static int mtk_iommu_mm_dts_parse(struct device *dev, struct component_match **m larb_nr = of_count_phandle_with_args(dev->of_node, "mediatek,larbs", NULL); if (larb_nr < 0) return larb_nr; + if (larb_nr == 0 || larb_nr > MTK_LARB_NR_MAX) + return -EINVAL; for (i = 0; i < larb_nr; i++) { u32 id; @@ -1068,6 +1070,10 @@ static int mtk_iommu_mm_dts_parse(struct device *dev, struct component_match **m ret = of_property_read_u32(larbnode, "mediatek,larb-id", &id); if (ret)/* The id is consecutive if there is no this property */ id = i; + if (id >= MTK_LARB_NR_MAX) { + ret = -EINVAL; + goto err_larbnode_put; + } plarbdev = of_find_device_by_node(larbnode); if (!plarbdev) { @@ -1078,6 +1084,11 @@ static int mtk_iommu_mm_dts_parse(struct device *dev, struct component_match **m ret = -EPROBE_DEFER; goto err_larbnode_put; } + + if (data->larb_imu[id].dev) { + ret = -EEXIST; + goto err_larbnode_put; + } data->larb_imu[id].dev = &plarbdev->dev; component_match_add_release(dev, match, component_release_of, -- 2.18.0 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH v2 2/5] iommu/mediatek: Add error path for loop of mm_dts_parse
The mtk_iommu_mm_dts_parse will parse the smi larbs nodes. if the i+1 larb is parsed fail(return -EINVAL), we should of_node_put for the 0..i larbs. In the fail path, one of_node_put matches with of_parse_phandle in it. Fixes: d2e9a1102cfc ("iommu/mediatek: Contain MM IOMMU flow with the MM TYPE") Signed-off-by: Yong Wu --- drivers/iommu/mtk_iommu.c | 21 - 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c index 3b2489e8a6dd..ab24078938bf 100644 --- a/drivers/iommu/mtk_iommu.c +++ b/drivers/iommu/mtk_iommu.c @@ -1071,12 +1071,12 @@ static int mtk_iommu_mm_dts_parse(struct device *dev, struct component_match **m plarbdev = of_find_device_by_node(larbnode); if (!plarbdev) { - of_node_put(larbnode); - return -ENODEV; + ret = -ENODEV; + goto err_larbnode_put; } if (!plarbdev->dev.driver) { - of_node_put(larbnode); - return -EPROBE_DEFER; + ret = -EPROBE_DEFER; + goto err_larbnode_put; } data->larb_imu[id].dev = &plarbdev->dev; @@ -1107,9 +1107,20 @@ static int mtk_iommu_mm_dts_parse(struct device *dev, struct component_match **m DL_FLAG_STATELESS | DL_FLAG_PM_RUNTIME); if (!link) { dev_err(dev, "Unable to link %s.\n", dev_name(data->smicomm_dev)); - return -EINVAL; + ret = -EINVAL; + goto err_larbnode_put; } return 0; + +err_larbnode_put: + while (i--) { + larbnode = of_parse_phandle(dev->of_node, "mediatek,larbs", i); + if (larbnode && of_device_is_available(larbnode)) { + of_node_put(larbnode); + of_node_put(larbnode); + } + } + return ret; } static int mtk_iommu_probe(struct platform_device *pdev) -- 2.18.0 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH v2 1/5] iommu/mediatek: Use dev_err_probe to mute probe_defer err log
Mute the probe defer log: [2.654806] mtk-iommu 14018000.iommu: mm dts parse fail(-517). [2.656168] mtk-iommu 1c01f000.iommu: mm dts parse fail(-517). Fixes: d2e9a1102cfc ("iommu/mediatek: Contain MM IOMMU flow with the MM TYPE") Signed-off-by: Yong Wu Reviewed-by: AngeloGioacchino Del Regno Reviewed-by: Guenter Roeck --- drivers/iommu/mtk_iommu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c index bb9dd92c9898..3b2489e8a6dd 100644 --- a/drivers/iommu/mtk_iommu.c +++ b/drivers/iommu/mtk_iommu.c @@ -1204,7 +1204,7 @@ static int mtk_iommu_probe(struct platform_device *pdev) if (MTK_IOMMU_IS_TYPE(data->plat_data, MTK_IOMMU_TYPE_MM)) { ret = mtk_iommu_mm_dts_parse(dev, &match, data); if (ret) { - dev_err(dev, "mm dts parse fail(%d).", ret); + dev_err_probe(dev, ret, "mm dts parse fail."); goto out_runtime_disable; } } else if (MTK_IOMMU_IS_TYPE(data->plat_data, MTK_IOMMU_TYPE_INFRA) && -- 2.18.0 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH v2 0/5] iommu/mediatek: Improve safety from dts
This patchset contains misc improve patches: [1/5] When mt8195 v7, I added a error log for dts parse fail, but it doesn't ignore probe_defer case.(v6 doesn't have this err log.) [2/5] Add a error path for MM dts parse. [3/5][4/5] To improve safety from dts. Base on this: https://lore.kernel.org/linux-mediatek/20211210205704.1664928-1-li...@roeck-us.net/ Change notes: v2: a) Rebase on v5.19-rc1. b) Add a New patch [5/5] just remove a variable that only is for v1. v1: https://lore.kernel.org/linux-mediatek/20220511064920.18455-1-yong...@mediatek.com/ Base on linux-next-20220510. Guenter Roeck (1): iommu/mediatek: Validate number of phandles associated with "mediatek, larbs" Yong Wu (4): iommu/mediatek: Use dev_err_probe to mute probe_defer err log iommu/mediatek: Add error path for loop of mm_dts_parse iommu/mediatek: Improve safety for mediatek, smi property in larb nodes iommu/mediatek: Remove a unused "mapping" which is only for v1 drivers/iommu/mtk_iommu.c | 86 +++ 1 file changed, 61 insertions(+), 25 deletions(-) -- 2.18.0 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH v8 1/3] iommu/io-pgtable-arm-v7s: Add a quirk to allow pgtable PA up to 35bit
On Tue, 2022-06-14 at 13:56 +0100, Will Deacon wrote: > > @@ -74,17 +74,22 @@ struct io_pgtable_cfg { > > * to support up to 35 bits PA where the bit32, bit33 and > > bit34 are > > * encoded in the bit9, bit4 and bit5 of the PTE respectively. > > * > > +* IO_PGTABLE_QUIRK_ARM_MTK_TTBR_EXT: (ARM v7s format) MediaTek > > IOMMUs > > +* extend the translation table base support up to 35 bits PA, > > the > > +* encoding format is same with IO_PGTABLE_QUIRK_ARM_MTK_EXT. > > +* > > One thing I don't get is how the existing driver handles this. It > seems > as though if the HAS_4GB_MODE flag is not set, then we set oas to 35 > but > without any pgtable changes. How does this work? Regarding the pgtable, we already use the quirk IO_PGTABLE_QUIRK_ARM_MTK_EXT to support 35bits oas. HAS_4GB_MODE is the flag for the previous SoC that only supports 33bits oas, it also is covered by IO_PGTABLE_QUIRK_ARM_MTK_EXT. and in 4GB mode we add PA32 manually in mtk_iommu_map. > > If it turns out that the existing devices can't handle 35-bit PAs, > then > could we use an oas of 35 to indicate that this new format is in use > instead of introducing another quirk? The existed devices can handle 35bits oas. The problem is that if the pgtable PA could support up to 35bits. The previous SoC like mt8173 can't support while the lastest SoC can. This is the purpose of this new quick. therefore we need GFP_DMA/DMA32 for pgtable allocating in mt8173 and GFP_DMA/DMA32 is not needed in the new quirk. > > Will ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH v8 3/3] iommu/mediatek: Allow page table PA up to 35bit
On Sat, 2022-06-11 at 18:26 +0800, yf.w...@mediatek.com wrote: > From: Yunfei Wang > > Single memory zone feature will remove ZONE_DMA32 and ZONE_DMA. So > add > the quirk IO_PGTABLE_QUIRK_ARM_MTK_TTBR_EXT to let level 1 and level > 2 > pgtable support at most 35bit PA. > > Signed-off-by: Ning Li > Signed-off-by: Yunfei Wang Reviewed-by: Yong Wu Thanks very much for this function. All the lastest SoCs like mt8192/mt8195 support this. > --- > drivers/iommu/mtk_iommu.c | 14 +- > 1 file changed, 9 insertions(+), 5 deletions(-) > > diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c > index 3d62399e8865..4dbc33758711 100644 > --- a/drivers/iommu/mtk_iommu.c > +++ b/drivers/iommu/mtk_iommu.c > @@ -138,6 +138,7 @@ > /* PM and clock always on. e.g. infra iommu */ > #define PM_CLK_AOBIT(15) > #define IFA_IOMMU_PCIE_SUPPORT BIT(16) > +#define PGTABLE_PA_35_EN BIT(17) > > #define MTK_IOMMU_HAS_FLAG_MASK(pdata, _x, mask) \ > pdata)->flags) & (mask)) == (_x)) > @@ -240,6 +241,7 @@ struct mtk_iommu_data { > struct mtk_iommu_domain { > struct io_pgtable_cfg cfg; > struct io_pgtable_ops *iop; > + u32 ttbr; > > struct mtk_iommu_bank_data *bank; > struct iommu_domain domain; > @@ -596,6 +598,9 @@ static int mtk_iommu_domain_finalise(struct > mtk_iommu_domain *dom, > .iommu_dev = data->dev, > }; > > + if (MTK_IOMMU_HAS_FLAG(data->plat_data, PGTABLE_PA_35_EN)) > + dom->cfg.quirks |= IO_PGTABLE_QUIRK_ARM_MTK_TTBR_EXT; > + > if (MTK_IOMMU_HAS_FLAG(data->plat_data, HAS_4GB_MODE)) > dom->cfg.oas = data->enable_4GB ? 33 : 32; > else > @@ -684,8 +689,8 @@ static int mtk_iommu_attach_device(struct > iommu_domain *domain, > goto err_unlock; > } > bank->m4u_dom = dom; > - writel(dom->cfg.arm_v7s_cfg.ttbr & MMU_PT_ADDR_MASK, > -bank->base + REG_MMU_PT_BASE_ADDR); > + bank->m4u_dom->ttbr = MTK_IOMMU_ADDR(dom- > >cfg.arm_v7s_cfg.ttbr); > + writel(bank->m4u_dom->ttbr, data->base + > REG_MMU_PT_BASE_ADDR); > > pm_runtime_put(m4udev); > } > @@ -1366,8 +1371,7 @@ static int __maybe_unused > mtk_iommu_runtime_resume(struct device *dev) > writel_relaxed(reg->int_control[i], base + > REG_MMU_INT_CONTROL0); > writel_relaxed(reg->int_main_control[i], base + > REG_MMU_INT_MAIN_CONTROL); > writel_relaxed(reg->ivrp_paddr[i], base + > REG_MMU_IVRP_PADDR); > - writel(m4u_dom->cfg.arm_v7s_cfg.ttbr & > MMU_PT_ADDR_MASK, > -base + REG_MMU_PT_BASE_ADDR); > + writel(m4u_dom->ttbr, base + REG_MMU_PT_BASE_ADDR); > } while (++i < data->plat_data->banks_num); > > /* > @@ -1401,7 +1405,7 @@ static const struct mtk_iommu_plat_data > mt2712_data = { > static const struct mtk_iommu_plat_data mt6779_data = { > .m4u_plat = M4U_MT6779, > .flags = HAS_SUB_COMM_2BITS | OUT_ORDER_WR_EN | > WR_THROT_EN | > - MTK_IOMMU_TYPE_MM, > + MTK_IOMMU_TYPE_MM | PGTABLE_PA_35_EN, > .inv_sel_reg = REG_MMU_INV_SEL_GEN2, > .banks_num= 1, > .banks_enable = {true}, ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH v8 2/3] iommu/mediatek: Rename MTK_IOMMU_TLB_ADDR to MTK_IOMMU_ADDR
On Sat, 2022-06-11 at 18:26 +0800, yf.w...@mediatek.com wrote: > From: Yunfei Wang > > Rename MTK_IOMMU_TLB_ADDR to MTK_IOMMU_ADDR, and update > MTK_IOMMU_ADDR > definition for better generality. Comment more about why you need this. Prepare for supporting TTBR up to 35bit which also need this macro. Currently it is dma_addr_t while ttbr is phys_addr_t, thus change the type to "unsigned long long" for generality. Anyway, Reviewed-by: Yong Wu > > Signed-off-by: Ning Li > Signed-off-by: Yunfei Wang > --- > drivers/iommu/mtk_iommu.c | 8 > 1 file changed, 4 insertions(+), 4 deletions(-) > > diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c > index bb9dd92c9898..3d62399e8865 100644 > --- a/drivers/iommu/mtk_iommu.c > +++ b/drivers/iommu/mtk_iommu.c > @@ -265,8 +265,8 @@ static const struct iommu_ops mtk_iommu_ops; > > static int mtk_iommu_hw_init(const struct mtk_iommu_data *data, > unsigned int bankid); > > -#define MTK_IOMMU_TLB_ADDR(iova) ({ > \ > - dma_addr_t _addr = iova;\ > +#define MTK_IOMMU_ADDR(addr) ({ > \ > + unsigned long long _addr = addr;\ > ((lower_32_bits(_addr) & GENMASK(31, 12)) | > upper_32_bits(_addr));\ > }) > > @@ -381,8 +381,8 @@ static void > mtk_iommu_tlb_flush_range_sync(unsigned long iova, size_t size, > writel_relaxed(F_INVLD_EN1 | F_INVLD_EN0, > base + data->plat_data->inv_sel_reg); > > - writel_relaxed(MTK_IOMMU_TLB_ADDR(iova), base + > REG_MMU_INVLD_START_A); > - writel_relaxed(MTK_IOMMU_TLB_ADDR(iova + size - 1), > + writel_relaxed(MTK_IOMMU_ADDR(iova), base + > REG_MMU_INVLD_START_A); > + writel_relaxed(MTK_IOMMU_ADDR(iova + size - 1), > base + REG_MMU_INVLD_END_A); > writel_relaxed(F_MMU_INV_RANGE, base + > REG_MMU_INVALIDATE); > ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH v3 3/3] iommu: mtk_iommu: Add support for MT6795 Helio X10 M4Us
On Thu, 2022-06-09 at 12:40 +0200, AngeloGioacchino Del Regno wrote: > Add support for the M4Us found in the MT6795 Helio X10 SoC. > > Signed-off-by: AngeloGioacchino Del Regno < > angelogioacchino.delre...@collabora.com> Retitle to: iommu/mediatek: Xxx, then Reviewed-by: Yong Wu > --- > drivers/iommu/mtk_iommu.c | 15 +++ > 1 file changed, 15 insertions(+) > > diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c > index 8611cf8e4bd5..beca1c5a6c10 100644 > --- a/drivers/iommu/mtk_iommu.c > +++ b/drivers/iommu/mtk_iommu.c > @@ -160,6 +160,7 @@ > enum mtk_iommu_plat { > M4U_MT2712, > M4U_MT6779, > + M4U_MT6795, > M4U_MT8167, > M4U_MT8173, > M4U_MT8183, > @@ -1424,6 +1425,19 @@ static const struct mtk_iommu_plat_data > mt6779_data = { > .larbid_remap = {{0}, {1}, {2}, {3}, {5}, {7, 8}, {10}, {9}}, > }; > > +static const struct mtk_iommu_plat_data mt6795_data = { > + .m4u_plat = M4U_MT6795, > + .flags= HAS_4GB_MODE | HAS_BCLK | RESET_AXI | > + HAS_LEGACY_IVRP_PADDR | MTK_IOMMU_TYPE_MM | > + TF_PORT_TO_ADDR_MT8173, > + .inv_sel_reg = REG_MMU_INV_SEL_GEN1, > + .banks_num= 1, > + .banks_enable = {true}, > + .iova_region = single_domain, > + .iova_region_nr = ARRAY_SIZE(single_domain), > + .larbid_remap = {{0}, {1}, {2}, {3}, {4}}, /* Linear mapping. > */ > +}; > + > static const struct mtk_iommu_plat_data mt8167_data = { > .m4u_plat = M4U_MT8167, > .flags= RESET_AXI | HAS_LEGACY_IVRP_PADDR | > MTK_IOMMU_TYPE_MM, > @@ -1536,6 +1550,7 @@ static const struct mtk_iommu_plat_data > mt8195_data_vpp = { > static const struct of_device_id mtk_iommu_of_ids[] = { > { .compatible = "mediatek,mt2712-m4u", .data = &mt2712_data}, > { .compatible = "mediatek,mt6779-m4u", .data = &mt6779_data}, > + { .compatible = "mediatek,mt6795-m4u", .data = &mt6795_data}, > { .compatible = "mediatek,mt8167-m4u", .data = &mt8167_data}, > { .compatible = "mediatek,mt8173-m4u", .data = &mt8173_data}, > { .compatible = "mediatek,mt8183-m4u", .data = &mt8183_data}, ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH v3 1/3] dt-bindings: mediatek: Add bindings for MT6795 M4U
On Thu, 2022-06-09 at 12:39 +0200, AngeloGioacchino Del Regno wrote: > Add bindings for the MediaTek Helio X10 (MT6795) IOMMU/M4U. > > Signed-off-by: AngeloGioacchino Del Regno < > angelogioacchino.delre...@collabora.com> > Acked-by: Rob Herring > --- > .../bindings/iommu/mediatek,iommu.yaml| 4 + > include/dt-bindings/memory/mt6795-larb-port.h | 96 > +++ > 2 files changed, 100 insertions(+) > create mode 100644 include/dt-bindings/memory/mt6795-larb-port.h > > diff --git > a/Documentation/devicetree/bindings/iommu/mediatek,iommu.yaml > b/Documentation/devicetree/bindings/iommu/mediatek,iommu.yaml > index d5e3272a54e8..20902c387520 100644 > --- a/Documentation/devicetree/bindings/iommu/mediatek,iommu.yaml > +++ b/Documentation/devicetree/bindings/iommu/mediatek,iommu.yaml > @@ -73,6 +73,7 @@ properties: >- mediatek,mt2701-m4u # generation one >- mediatek,mt2712-m4u # generation two >- mediatek,mt6779-m4u # generation two > + - mediatek,mt6795-m4u # generation two >- mediatek,mt8167-m4u # generation two >- mediatek,mt8173-m4u # generation two >- mediatek,mt8183-m4u # generation two > @@ -128,6 +129,7 @@ properties: >dt-binding/memory/mt2701-larb-port.h for mt2701 and mt7623, >dt-binding/memory/mt2712-larb-port.h for mt2712, >dt-binding/memory/mt6779-larb-port.h for mt6779, > + dt-binding/memory/mt6795-larb-port.h for mt6795, >dt-binding/memory/mt8167-larb-port.h for mt8167, >dt-binding/memory/mt8173-larb-port.h for mt8173, >dt-binding/memory/mt8183-larb-port.h for mt8183, > @@ -152,6 +154,7 @@ allOf: > enum: >- mediatek,mt2701-m4u >- mediatek,mt2712-m4u > + - mediatek,mt6795-m4u >- mediatek,mt8173-m4u >- mediatek,mt8186-iommu-mm >- mediatek,mt8192-m4u > @@ -181,6 +184,7 @@ allOf: >contains: > enum: >- mediatek,mt2712-m4u > + - mediatek,mt6795-m4u >- mediatek,mt8173-m4u > > then: > diff --git a/include/dt-bindings/memory/mt6795-larb-port.h > b/include/dt-bindings/memory/mt6795-larb-port.h > new file mode 100644 > index ..223aca8fd350 > --- /dev/null > +++ b/include/dt-bindings/memory/mt6795-larb-port.h > @@ -0,0 +1,96 @@ > +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */ > +/* > + * Copyright (c) 2022 Collabora Ltd. > + * Author: AngeloGioacchino Del Regno < > angelogioacchino.delre...@collabora.com> > + */ > + > +#ifndef _DT_BINDINGS_MEMORY_MT6795_LARB_PORT_H_ > +#define _DT_BINDINGS_MEMORY_MT6795_LARB_PORT_H_ > + > +#include > + > +#define M4U_LARB0_ID 0 > +#define M4U_LARB1_ID 1 > +#define M4U_LARB2_ID 2 > +#define M4U_LARB3_ID 3 > +#define M4U_LARB4_ID 4 > +#define M4U_LARB5_ID 5 Just a nitpick: M4U_LARB5_ID is not used, then remove this. > + > +/* larb0 */ > +#define M4U_PORT_DISP_OVL0 MTK_M4U_ID(M4U_LARB0_ID, 0) > +#define M4U_PORT_DISP_RDMA0 MTK_M4U_ID(M4U_LARB0_ID, 1) > +#define M4U_PORT_DISP_RDMA1 MTK_M4U_ID(M4U_LARB0_ID, 2) > +#define M4U_PORT_DISP_WDMA0 MTK_M4U_ID(M4U_LARB0_ID, 3) > +#define M4U_PORT_DISP_OVL1 MTK_M4U_ID(M4U_LARB0_ID, 4) > +#define M4U_PORT_DISP_RDMA2 MTK_M4U_ID(M4U_LARB0_ID, 5) > +#define M4U_PORT_DISP_WDMA1 MTK_M4U_ID(M4U_LARB0_ID, 6) > +#define M4U_PORT_DISP_OD_R MTK_M4U_ID(M4U_LARB0_ID, 7) > +#define M4U_PORT_DISP_OD_W MTK_M4U_ID(M4U_LARB0_ID, 8) > +#define M4U_PORT_MDP_RDMA0 MTK_M4U_ID(M4U_LARB0_ID, 9) > +#define M4U_PORT_MDP_RDMA1 MTK_M4U_ID(M4U_LARB0_ID, 10) > +#define M4U_PORT_MDP_WDMAMTK_M4U_ID(M4U_LARB0_ID, 11) > +#define M4U_PORT_MDP_WROT0 MTK_M4U_ID(M4U_LARB0_ID, 12) > +#define M4U_PORT_MDP_WROT1 MTK_M4U_ID(M4U_LARB0_ID, 13) > + > +/* larb1 */ > +#define M4U_PORT_VDEC_MC MTK_M4U_ID(M4U_LARB1_ID, 0) > +#define M4U_PORT_VDEC_PP MTK_M4U_ID(M4U_LARB1_ID, 1) > +#define M4U_PORT_VDEC_UFOMTK_M4U_ID(M4U_LARB1_ID, 2) > +#define M4U_PORT_VDEC_VLDMTK_M4U_ID(M4U_LARB1_ID, 3) > +#define M4U_PORT_VDEC_VLD2 MTK_M4U_ID(M4U_LARB1_ID, 4) > +#define M4U_PORT_VDEC_AVC_MV MTK_M4U_ID(M4U_LARB1_ID, 5) > +#define M4U_PORT_VDEC_PRED_RDMTK_M4U_ID(M4U_LARB1_ID > , 6) > +#define M4U_PORT_VDEC_PRED_WRMTK_M4U_ID(M4U_LARB1_ID > , 7) > +#define M4U_PORT_VDEC_PPWRAP MTK_M4U_ID(M4U_LARB1_ID, 8) > + > +/* larb2 */ > +#define M4U_PORT_CAM_IMGOMTK_M4U_ID(M4U_LARB2_ID, 0) > +#define M4U_PORT_CAM_RRZOMTK_M4U_ID(M4U_LARB2_ID, 1) > +#define M4U_PORT_CAM_AAO MTK_M4U_ID(M4U_LARB2_ID, 2) > +#define M4U_PORT_CAM_LCSOMTK_M4U_ID(M4U_LARB2_ID, 3) > +#define M4
Re: [PATCH v3 2/3] iommu: mtk_iommu: Introduce new flag TF_PORT_TO_ADDR_MT8173
On Thu, 2022-06-09 at 12:40 +0200, AngeloGioacchino Del Regno wrote: > In preparation for adding support for MT6795, add a new flag named > TF_PORT_TO_ADDR_MT8173 and use that instead of checking for m4u_plat > type in mtk_iommu_hw_init() to avoid seeing a long list of m4u_plat > checks there in the future. > > Signed-off-by: AngeloGioacchino Del Regno < > angelogioacchino.delre...@collabora.com> Retitle to: iommu/mediatek: Xxx, then Reviewed-by: Yong Wu > --- > drivers/iommu/mtk_iommu.c | 6 -- > 1 file changed, 4 insertions(+), 2 deletions(-) > > diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c > index 0ea0848581e9..8611cf8e4bd5 100644 > --- a/drivers/iommu/mtk_iommu.c > +++ b/drivers/iommu/mtk_iommu.c > @@ -140,6 +140,7 @@ > #define IFA_IOMMU_PCIE_SUPPORT BIT(16) > /* IOMMU I/O (r/w) is enabled using PERICFG_IOMMU_1 register */ > #define HAS_PERI_IOMMU1_REG BIT(17) > +#define TF_PORT_TO_ADDR_MT8173 BIT(18) > > #define MTK_IOMMU_HAS_FLAG_MASK(pdata, _x, mask) \ > pdata)->flags) & (mask)) == (_x)) > @@ -960,7 +961,7 @@ static int mtk_iommu_hw_init(const struct > mtk_iommu_data *data, unsigned int ban >* Global control settings are in bank0. May re-init these > global registers >* since no sure if there is bank0 consumers. >*/ > - if (data->plat_data->m4u_plat == M4U_MT8173) { > + if (MTK_IOMMU_HAS_FLAG(data->plat_data, > TF_PORT_TO_ADDR_MT8173)) { > regval = F_MMU_PREFETCH_RT_REPLACE_MOD | >F_MMU_TF_PROT_TO_PROGRAM_ADDR_MT8173; > } else { > @@ -1437,7 +1438,8 @@ static const struct mtk_iommu_plat_data > mt8167_data = { > static const struct mtk_iommu_plat_data mt8173_data = { > .m4u_plat = M4U_MT8173, > .flags= HAS_4GB_MODE | HAS_BCLK | RESET_AXI | > - HAS_LEGACY_IVRP_PADDR | MTK_IOMMU_TYPE_MM, > + HAS_LEGACY_IVRP_PADDR | MTK_IOMMU_TYPE_MM | > + TF_PORT_TO_ADDR_MT8173, > .inv_sel_reg = REG_MMU_INV_SEL_GEN1, > .banks_num= 1, > .banks_enable = {true}, ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH v3 6/6] iommu: mtk_iommu: Lookup phandle to retrieve syscon to pericfg
On Thu, 2022-06-09 at 12:08 +0200, AngeloGioacchino Del Regno wrote: > On some SoCs (of which only MT8195 is supported at the time of > writing), > the "R" and "W" (I/O) enable bits for the IOMMUs are in the > pericfg_ao > register space and not in the IOMMU space: as it happened already > with > infracfg, it is expected that this list will grow. Currently I don't see the list will grow. As commented before, In the lastest SoC, The IOMMU enable bits for IOMMU will be in ATF, rather than in this pericfg register region. In this case, Is this patch unnecessary? or we could add this patch when there are 2 SoCs use this setting at least? what's your opinion? > > Instead of specifying pericfg compatibles on a per-SoC basis, > following > what was done with infracfg, let's lookup the syscon by phandle > instead. > > Signed-off-by: AngeloGioacchino Del Regno < > angelogioacchino.delre...@collabora.com> > --- > drivers/iommu/mtk_iommu.c | 23 +-- > 1 file changed, 13 insertions(+), 10 deletions(-) > > diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c > index 90685946fcbe..0ea0848581e9 100644 > --- a/drivers/iommu/mtk_iommu.c > +++ b/drivers/iommu/mtk_iommu.c > @@ -138,6 +138,8 @@ > /* PM and clock always on. e.g. infra iommu */ > #define PM_CLK_AOBIT(15) > #define IFA_IOMMU_PCIE_SUPPORT BIT(16) > +/* IOMMU I/O (r/w) is enabled using PERICFG_IOMMU_1 register */ > +#define HAS_PERI_IOMMU1_REG BIT(17) > > #define MTK_IOMMU_HAS_FLAG_MASK(pdata, _x, mask) \ > pdata)->flags) & (mask)) == (_x)) > @@ -187,7 +189,6 @@ struct mtk_iommu_plat_data { > u32 flags; > u32 inv_sel_reg; > > - char*pericfg_comp_str; > struct list_head*hw_list; > unsigned intiova_region_nr; > const struct mtk_iommu_iova_region *iova_region; > @@ -1218,14 +1219,16 @@ static int mtk_iommu_probe(struct > platform_device *pdev) > goto out_runtime_disable; > } > } else if (MTK_IOMMU_IS_TYPE(data->plat_data, > MTK_IOMMU_TYPE_INFRA) && > -data->plat_data->pericfg_comp_str) { > - infracfg = syscon_regmap_lookup_by_compatible(data- > >plat_data->pericfg_comp_str); > - if (IS_ERR(infracfg)) { > - ret = PTR_ERR(infracfg); > - goto out_runtime_disable; > +MTK_IOMMU_HAS_FLAG(data->plat_data, > HAS_PERI_IOMMU1_REG)) { > + data->pericfg = syscon_regmap_lookup_by_phandle(dev- > >of_node, "mediatek,pericfg"); > + if (IS_ERR(data->pericfg)) { > + p = "mediatek,mt8195-pericfg_ao"; > + data->pericfg = > syscon_regmap_lookup_by_compatible(p); Upstream doesn't have the mt8195 iommu node currently, thus We don't need to recover for the previous dts case. right? > + if (IS_ERR(data->pericfg)) { > + ret = PTR_ERR(data->pericfg); > + goto out_runtime_disable; > + } > } > - > - data->pericfg = infracfg; > } > > platform_set_drvdata(pdev, data); > @@ -1484,8 +1487,8 @@ static const struct mtk_iommu_plat_data > mt8192_data = { > static const struct mtk_iommu_plat_data mt8195_data_infra = { > .m4u_plat = M4U_MT8195, > .flags= WR_THROT_EN | DCM_DISABLE | STD_AXI_MODE | > PM_CLK_AO | > - MTK_IOMMU_TYPE_INFRA | > IFA_IOMMU_PCIE_SUPPORT, > - .pericfg_comp_str = "mediatek,mt8195-pericfg_ao", > + HAS_PERI_IOMMU1_REG | MTK_IOMMU_TYPE_INFRA > | > + IFA_IOMMU_PCIE_SUPPORT, > .inv_sel_reg = REG_MMU_INV_SEL_GEN2, > .banks_num= 5, > .banks_enable = {true, false, false, false, true}, ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH v3 2/6] iommu: mtk_iommu: Lookup phandle to retrieve syscon to infracfg
On Thu, 2022-06-09 at 12:07 +0200, AngeloGioacchino Del Regno wrote: > This driver will get support for more SoCs and the list of infracfg > compatibles is expected to grow: in order to prevent getting this > situation out of control and see a long list of compatible strings, > add support to retrieve a handle to infracfg's regmap through a > new "mediatek,infracfg" phandle. > > In order to keep retrocompatibility with older devicetrees, the old > way is kept in place. > > Signed-off-by: AngeloGioacchino Del Regno < > angelogioacchino.delre...@collabora.com> Retitle to: iommu/mediatek: Xxx, then Reviewed-by: Yong Wu > --- > drivers/iommu/mtk_iommu.c | 38 - > - > 1 file changed, 24 insertions(+), 14 deletions(-) > > diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c > index bb9dd92c9898..90685946fcbe 100644 > --- a/drivers/iommu/mtk_iommu.c > +++ b/drivers/iommu/mtk_iommu.c > @@ -1140,22 +1140,32 @@ static int mtk_iommu_probe(struct > platform_device *pdev) > data->protect_base = ALIGN(virt_to_phys(protect), > MTK_PROTECT_PA_ALIGN); > > if (MTK_IOMMU_HAS_FLAG(data->plat_data, HAS_4GB_MODE)) { > - switch (data->plat_data->m4u_plat) { > - case M4U_MT2712: > - p = "mediatek,mt2712-infracfg"; > - break; > - case M4U_MT8173: > - p = "mediatek,mt8173-infracfg"; > - break; > - default: > - p = NULL; > + infracfg = syscon_regmap_lookup_by_phandle(dev- > >of_node, "mediatek,infracfg"); > + if (IS_ERR(infracfg)) { > + /* > + * Legacy devicetrees will not specify a > phandle to > + * mediatek,infracfg: in that case, we use the > older > + * way to retrieve a syscon to infra. > + * > + * This is for retrocompatibility purposes > only, hence > + * no more compatibles shall be added to this. > + */ > + switch (data->plat_data->m4u_plat) { > + case M4U_MT2712: > + p = "mediatek,mt2712-infracfg"; > + break; > + case M4U_MT8173: > + p = "mediatek,mt8173-infracfg"; > + break; > + default: > + p = NULL; > + } > + > + infracfg = > syscon_regmap_lookup_by_compatible(p); > + if (IS_ERR(infracfg)) > + return PTR_ERR(infracfg); > } > > - infracfg = syscon_regmap_lookup_by_compatible(p); > - > - if (IS_ERR(infracfg)) > - return PTR_ERR(infracfg); > - > ret = regmap_read(infracfg, REG_INFRA_MISC, &val); > if (ret) > return ret; ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH 1/3] dt-bindings: iommu: mediatek: add binding documentation for MT8365 SoC
On Thu, 2022-06-02 at 16:42 +0800, Macpaul Lin wrote: > On 6/2/22 4:27 PM, Macpaul Lin wrote: > > On 6/2/22 2:18 PM, Yong Wu wrote: > > > On Mon, 2022-05-30 at 20:03 +0200, Fabien Parent wrote: > > > > Add IOMMU binding documentation for the MT8365 SoC. > > > > > > > > Signed-off-by: Fabien Parent > > > > --- > > > > .../bindings/iommu/mediatek,iommu.yaml| 2 + > > > > include/dt-bindings/memory/mt8365-larb-port.h | 96 > > > > +++ > > > > 2 files changed, 98 insertions(+) > > > > create mode 100644 include/dt-bindings/memory/mt8365-larb- > > > > port.h > > > > > > [snip...] > > > > > > > +#ifndef _DT_BINDINGS_MEMORY_MT8365_LARB_PORT_H_ > > > > +#define _DT_BINDINGS_MEMORY_MT8365_LARB_PORT_H_ > > > > + > > > > +#include > > > > + > > > > +#define M4U_LARB0_ID0 > > > > +#define M4U_LARB1_ID1 > > > > +#define M4U_LARB2_ID2 > > > > +#define M4U_LARB3_ID3 > > > > +#define M4U_LARB4_ID4 > > > > +#define M4U_LARB5_ID5 > > > > +#define M4U_LARB6_ID6 > > > > +#define M4U_LARB7_ID7 > > > > > > Remove these. they are no used, right? > > > > AIOT and customers are using the modules and their related IOMMU > > modules. > > DISP0, VENC, VDEC, ISP (CAMSYS), and APU (as far as I know, which > > should > > be VP6?) were all supported. > > Dear Yong, > How about to replace the following definitions? > > For example, replace > #define M4U_PORT_DISP_OVL0MTK_M4U_ID(0, 0) > to > #define M4U_PORT_DISP_OVL0 MTK_M4U_ID(M4U_LARB0_ID , 0) Yes. It is ok. > > > > > > > > + > > > > +/* larb0 */ > > > > +#define M4U_PORT_DISP_OVL0MTK_M4U_ID(0, 0) > > > > +#define M4U_PORT_DISP_OVL0_2LMTK_M4U_ID(0, 1) > > > > > > [...] > > > > > > > > > > > +/* larb4 */ > > > > +#define M4U_PORT_APU_READMTK_M4U_ID(0, 0) > > > > +#define M4U_PORT_APU_WRITEMTK_M4U_ID(0, 1) > > > > > > Please remove these two APU definitions. currently these are not > > > supported. > > > > Kidd, please help to check if APU use these definitions with Yong. > > However, I think these are all available to the customers. > > > > Thanks > > Macpaul Lin > > Thanks > Macpaul Lin ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH 2/3] iommu: mtk_iommu: add support for 6-bit encoded port IDs
Hi Fabien, Thanks for very much for this patch. Retitle to iommu/mediatek: Xxx On Mon, 2022-05-30 at 20:03 +0200, Fabien Parent wrote: > Until now the port ID was always encoded as a 5-bit data. On MT8365, > the port ID is encoded as a 6-bit data. This requires to rework the > macros F_MMU_INT_ID_LARB_ID, and F_MMU_INT_ID_PORT_ID in order > to support 5-bit and 6-bit encoded port IDs. > > Signed-off-by: Fabien Parent > --- > drivers/iommu/mtk_iommu.c | 17 + > drivers/iommu/mtk_iommu.h | 1 + > 2 files changed, 14 insertions(+), 4 deletions(-) > > diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c > index 6fd75a60abd6..b692347d8d56 100644 > --- a/drivers/iommu/mtk_iommu.c > +++ b/drivers/iommu/mtk_iommu.c > @@ -103,8 +103,10 @@ > #define REG_MMU1_INT_ID 0x154 > #define F_MMU_INT_ID_COMM_ID(a) (((a) >> 9) & > 0x7) > #define F_MMU_INT_ID_SUB_COMM_ID(a) (((a) >> 7) & 0x3) > -#define F_MMU_INT_ID_LARB_ID(a) (((a) >> 7) & > 0x7) > -#define F_MMU_INT_ID_PORT_ID(a) (((a) >> 2) & > 0x1f) > +#define F_MMU_INT_ID_LARB_ID(a, port_width) \ > + ((a) >> ((port_width + 2) & 0x7)) > +#define F_MMU_INT_ID_PORT_ID(a, port_width) \ > + (((a) >> 2) & GENMASK(port_width - 1, > 0)) Add () for port_width. > > #define MTK_PROTECT_PA_ALIGN 256 > > @@ -291,12 +293,13 @@ static irqreturn_t mtk_iommu_isr(int irq, void > *dev_id) > fault_pa |= (u64)pa34_32 << 32; > } > > - fault_port = F_MMU_INT_ID_PORT_ID(regval); > + fault_port = F_MMU_INT_ID_PORT_ID(regval, data->plat_data- > >port_width); > if (MTK_IOMMU_HAS_FLAG(data->plat_data, HAS_SUB_COMM)) { > fault_larb = F_MMU_INT_ID_COMM_ID(regval); > sub_comm = F_MMU_INT_ID_SUB_COMM_ID(regval); > } else { > - fault_larb = F_MMU_INT_ID_LARB_ID(regval); > + fault_larb = F_MMU_INT_ID_LARB_ID(regval, > + data->plat_data- > >port_width); > } > fault_larb = data->plat_data- > >larbid_remap[fault_larb][sub_comm]; > > @@ -1034,6 +1037,7 @@ static const struct mtk_iommu_plat_data > mt2712_data = { > .iova_region = single_domain, > .iova_region_nr = ARRAY_SIZE(single_domain), > .larbid_remap = {{0}, {1}, {2}, {3}, {4}, {5}, {6}, {7}}, > + .port_width = 5, > }; > > static const struct mtk_iommu_plat_data mt6779_data = { > @@ -1043,6 +1047,7 @@ static const struct mtk_iommu_plat_data > mt6779_data = { > .iova_region = single_domain, > .iova_region_nr = ARRAY_SIZE(single_domain), > .larbid_remap = {{0}, {1}, {2}, {3}, {5}, {7, 8}, {10}, {9}}, > + .port_width= 5, > }; > > static const struct mtk_iommu_plat_data mt8167_data = { > @@ -1052,6 +1057,7 @@ static const struct mtk_iommu_plat_data > mt8167_data = { > .iova_region = single_domain, > .iova_region_nr = ARRAY_SIZE(single_domain), > .larbid_remap = {{0}, {1}, {2}}, /* Linear mapping. */ > + .port_width = 5, > }; > > static const struct mtk_iommu_plat_data mt8173_data = { > @@ -1062,6 +1068,7 @@ static const struct mtk_iommu_plat_data > mt8173_data = { > .iova_region = single_domain, > .iova_region_nr = ARRAY_SIZE(single_domain), > .larbid_remap = {{0}, {1}, {2}, {3}, {4}, {5}}, /* Linear > mapping. */ > + .port_width = 5, > }; > > static const struct mtk_iommu_plat_data mt8183_data = { > @@ -1071,6 +1078,7 @@ static const struct mtk_iommu_plat_data > mt8183_data = { > .iova_region = single_domain, > .iova_region_nr = ARRAY_SIZE(single_domain), > .larbid_remap = {{0}, {4}, {5}, {6}, {7}, {2}, {3}, {1}}, > + .port_width = 5, > }; > > static const struct mtk_iommu_plat_data mt8192_data = { > @@ -1082,6 +1090,7 @@ static const struct mtk_iommu_plat_data > mt8192_data = { > .iova_region_nr = ARRAY_SIZE(mt8192_multi_dom), > .larbid_remap = {{0}, {1}, {4, 5}, {7}, {2}, {9, 11, 19, 20}, > {0, 14, 16}, {0, 13, 18, 17}}, > + .port_width = 5, > }; > > static const struct of_device_id mtk_iommu_of_ids[] = { > diff --git a/drivers/iommu/mtk_iommu.h b/drivers/iommu/mtk_iommu.h > index b742432220c5..84cecaf6d61c 100644 > --- a/drivers/iommu/mtk_iommu.h > +++ b/drivers/iommu/mtk_iommu.h > @@ -54,6 +54,7 @@ struct mtk_iommu_plat_data { > enum mtk_iommu_plat m4u_plat; > u32 flags; > u32 inv_sel_reg; > + u8 port_width; Please help rename to int_id_port_width for more detailed from the register name (REG_MMU0_INT_ID). > > unsigned intiova_region_nr; > const struct mtk_iommu_iova_region *iova_region; > -- > 2.36.1 > ___ iommu mailing lis
Re: [PATCH 1/3] dt-bindings: iommu: mediatek: add binding documentation for MT8365 SoC
On Mon, 2022-05-30 at 20:03 +0200, Fabien Parent wrote: > Add IOMMU binding documentation for the MT8365 SoC. > > Signed-off-by: Fabien Parent > --- > .../bindings/iommu/mediatek,iommu.yaml| 2 + > include/dt-bindings/memory/mt8365-larb-port.h | 96 > +++ > 2 files changed, 98 insertions(+) > create mode 100644 include/dt-bindings/memory/mt8365-larb-port.h [snip...] > +#ifndef _DT_BINDINGS_MEMORY_MT8365_LARB_PORT_H_ > +#define _DT_BINDINGS_MEMORY_MT8365_LARB_PORT_H_ > + > +#include > + > +#define M4U_LARB0_ID 0 > +#define M4U_LARB1_ID 1 > +#define M4U_LARB2_ID 2 > +#define M4U_LARB3_ID 3 > +#define M4U_LARB4_ID 4 > +#define M4U_LARB5_ID 5 > +#define M4U_LARB6_ID 6 > +#define M4U_LARB7_ID 7 Remove these. they are no used, right? > + > +/* larb0 */ > +#define M4U_PORT_DISP_OVL0 MTK_M4U_ID(0, 0) > +#define M4U_PORT_DISP_OVL0_2LMTK_M4U_ID(0, 1) [...] > > +/* larb4 */ > +#define M4U_PORT_APU_READMTK_M4U_ID(0, 0) > +#define M4U_PORT_APU_WRITE MTK_M4U_ID(0, 1) Please remove these two APU definitions. currently these are not supported. Thanks. > + > +#endif ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH v2 3/7] iommu: mtk_iommu: Lookup phandle to retrieve syscon to pericfg
On Wed, 2022-05-18 at 12:04 +0200, AngeloGioacchino Del Regno wrote: > On some SoCs (of which only MT8195 is supported at the time of > writing), > the "R" and "W" (I/O) enable bits for the IOMMUs are in the > pericfg_ao > register space and not in the IOMMU space: as it happened already > with > infracfg, it is expected that this list will grow. > > Instead of specifying pericfg compatibles on a per-SoC basis, > following > what was done with infracfg, let's lookup the syscon by phandle > instead. > Also following the previous infracfg change, add a warning for > outdated > devicetrees, in hope that the user will take action. > > Signed-off-by: AngeloGioacchino Del Regno < > angelogioacchino.delre...@collabora.com> > --- > drivers/iommu/mtk_iommu.c | 26 -- > 1 file changed, 16 insertions(+), 10 deletions(-) > > diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c > index d16b95e71ded..090cf6e15f85 100644 > --- a/drivers/iommu/mtk_iommu.c > +++ b/drivers/iommu/mtk_iommu.c > @@ -138,6 +138,8 @@ > /* PM and clock always on. e.g. infra iommu */ > #define PM_CLK_AOBIT(15) > #define IFA_IOMMU_PCIE_SUPPORT BIT(16) > +/* IOMMU I/O (r/w) is enabled using PERICFG_IOMMU_1 register */ > +#define HAS_PERI_IOMMU1_REG BIT(17) > > #define MTK_IOMMU_HAS_FLAG_MASK(pdata, _x, mask) \ > pdata)->flags) & (mask)) == (_x)) > @@ -187,7 +189,6 @@ struct mtk_iommu_plat_data { > u32 flags; > u32 inv_sel_reg; > > - char*pericfg_comp_str; > struct list_head*hw_list; > unsigned intiova_region_nr; > const struct mtk_iommu_iova_region *iova_region; > @@ -1214,14 +1215,19 @@ static int mtk_iommu_probe(struct > platform_device *pdev) > goto out_runtime_disable; > } > } else if (MTK_IOMMU_IS_TYPE(data->plat_data, > MTK_IOMMU_TYPE_INFRA) && > -data->plat_data->pericfg_comp_str) { > - infracfg = syscon_regmap_lookup_by_compatible(data- > >plat_data->pericfg_comp_str); > - if (IS_ERR(infracfg)) { > - ret = PTR_ERR(infracfg); > - goto out_runtime_disable; > - } > +MTK_IOMMU_HAS_FLAG(data->plat_data, > HAS_PERI_IOMMU1_REG)) { > + data->pericfg = syscon_regmap_lookup_by_phandle(dev- > >of_node, "mediatek,pericfg"); I'm not keen to add this property. Currently only mt8195 use this setting. In the lastest SoC, we move this setting to ATF. thus I think we could keep the current way, no need add a new DT property only for mt8195. > + if (IS_ERR(data->pericfg)) { > + dev_info(dev, "Cannot find phandle to > mediatek,pericfg:" > + " Please update your > devicetree.\n"); > > - data->pericfg = infracfg; > + p = "mediatek,mt8195-pericfg_ao"; > + data->pericfg = > syscon_regmap_lookup_by_compatible(p); > + if (IS_ERR(data->pericfg)) { > + ret = PTR_ERR(data->pericfg); > + goto out_runtime_disable; > + } > + } > } > > platform_set_drvdata(pdev, data); > @@ -1480,8 +1486,8 @@ static const struct mtk_iommu_plat_data > mt8192_data = { > static const struct mtk_iommu_plat_data mt8195_data_infra = { > .m4u_plat = M4U_MT8195, > .flags= WR_THROT_EN | DCM_DISABLE | STD_AXI_MODE | > PM_CLK_AO | > - MTK_IOMMU_TYPE_INFRA | > IFA_IOMMU_PCIE_SUPPORT, > - .pericfg_comp_str = "mediatek,mt8195-pericfg_ao", > + HAS_PERI_IOMMU1_REG | MTK_IOMMU_TYPE_INFRA > | > + IFA_IOMMU_PCIE_SUPPORT, > .inv_sel_reg = REG_MMU_INV_SEL_GEN2, > .banks_num= 5, > .banks_enable = {true, false, false, false, true}, ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH v2 2/7] iommu: mtk_iommu: Lookup phandle to retrieve syscon to infracfg
On Wed, 2022-05-18 at 12:04 +0200, AngeloGioacchino Del Regno wrote: > This driver will get support for more SoCs and the list of infracfg > compatibles is expected to grow: in order to prevent getting this > situation out of control and see a long list of compatible strings, > add support to retrieve a handle to infracfg's regmap through a > new "mediatek,infracfg" phandle. > > In order to keep retrocompatibility with older devicetrees, the old > way is kept in place, but also a dev_warn() was added to advertise > this change in hope that the user will see it and eventually update > the devicetree if this is possible. > > Signed-off-by: AngeloGioacchino Del Regno < > angelogioacchino.delre...@collabora.com> > --- > drivers/iommu/mtk_iommu.c | 40 +-- > > 1 file changed, 26 insertions(+), 14 deletions(-) > > diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c > index 71b2ace74cd6..d16b95e71ded 100644 > --- a/drivers/iommu/mtk_iommu.c > +++ b/drivers/iommu/mtk_iommu.c > @@ -1134,22 +1134,34 @@ static int mtk_iommu_probe(struct > platform_device *pdev) > data->protect_base = ALIGN(virt_to_phys(protect), > MTK_PROTECT_PA_ALIGN); > > if (MTK_IOMMU_HAS_FLAG(data->plat_data, HAS_4GB_MODE)) { > - switch (data->plat_data->m4u_plat) { > - case M4U_MT2712: > - p = "mediatek,mt2712-infracfg"; > - break; > - case M4U_MT8173: > - p = "mediatek,mt8173-infracfg"; > - break; > - default: > - p = NULL; > + infracfg = syscon_regmap_lookup_by_phandle(dev- > >of_node, "mediatek,infracfg"); > + if (IS_ERR(infracfg)) { > + dev_info(dev, "Cannot find phandle to > mediatek,infracfg:" > + " Please update your > devicetree.\n"); Remove the log from Robin? > + /* > + * Legacy devicetrees will not specify a > phandle to > + * mediatek,infracfg: in that case, we use the > older > + * way to retrieve a syscon to infra. > + * > + * This is for retrocompatibility purposes > only, hence > + * no more compatibles shall be added to this. > + */ > + switch (data->plat_data->m4u_plat) { > + case M4U_MT2712: > + p = "mediatek,mt2712-infracfg"; > + break; > + case M4U_MT8173: > + p = "mediatek,mt8173-infracfg"; > + break; > + default: > + p = NULL; > + } We already use "mediatek,infracfg" property for commonizing. For the previous SoC, I also prefer to put the string into the platform data. After this, "->m4u_plat" could be removed. Of course, this is not the main purpose of this patchset. it also is ok currently. > + > + infracfg = > syscon_regmap_lookup_by_compatible(p); > + if (IS_ERR(infracfg)) > + return PTR_ERR(infracfg); > } > > - infracfg = syscon_regmap_lookup_by_compatible(p); > - > - if (IS_ERR(infracfg)) > - return PTR_ERR(infracfg); > - > ret = regmap_read(infracfg, REG_INFRA_MISC, &val); > if (ret) > return ret; ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH v2 1/7] dt-bindings: iommu: mediatek: Add phandles for mediatek infra/pericfg
On Wed, 2022-05-18 at 12:04 +0200, AngeloGioacchino Del Regno wrote: > Add properties "mediatek,infracfg" and "mediatek,pericfg" to let the > mtk_iommu driver retrieve phandles to the infracfg and pericfg > syscon(s) > instead of performing a per-soc compatible lookup. > > Signed-off-by: AngeloGioacchino Del Regno < > angelogioacchino.delre...@collabora.com> > --- > .../devicetree/bindings/iommu/mediatek,iommu.yaml | 8 > > 1 file changed, 8 insertions(+) > > diff --git > a/Documentation/devicetree/bindings/iommu/mediatek,iommu.yaml > b/Documentation/devicetree/bindings/iommu/mediatek,iommu.yaml > index 2ae3bbad7f1a..c4af41947593 100644 > --- a/Documentation/devicetree/bindings/iommu/mediatek,iommu.yaml > +++ b/Documentation/devicetree/bindings/iommu/mediatek,iommu.yaml > @@ -101,6 +101,10 @@ properties: > items: >- const: bclk > > + mediatek,infracfg: > +$ref: /schemas/types.yaml#/definitions/phandle > +description: The phandle to the mediatek infracfg syscon > + Just curious, why not put this "mediatek,infracfg" and its required segment[6/7] into one patch? >mediatek,larbs: > $ref: /schemas/types.yaml#/definitions/phandle-array > minItems: 1 > @@ -112,6 +116,10 @@ properties: >Refer to bindings/memory-controllers/mediatek,smi-larb.yaml. > It must sort >according to the local arbiter index, like larb0, larb1, > larb2... > > + mediatek,pericfg: > +$ref: /schemas/types.yaml#/definitions/phandle > +description: The phandle to the mediatek pericfg syscon > + >'#iommu-cells': > const: 1 > description: | ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH v2 2/2] iommu: mtk_iommu: Add support for MT6795 Helio X10 M4Us
On Wed, 2022-05-18 at 12:18 +0200, AngeloGioacchino Del Regno wrote: > Add support for the M4Us found in the MT6795 Helio X10 SoC. > > Signed-off-by: AngeloGioacchino Del Regno < > angelogioacchino.delre...@collabora.com> > --- > drivers/iommu/mtk_iommu.c | 17 - > 1 file changed, 16 insertions(+), 1 deletion(-) > > diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c > index 090cf6e15f85..97ff30ed2d0f 100644 > --- a/drivers/iommu/mtk_iommu.c > +++ b/drivers/iommu/mtk_iommu.c > @@ -159,6 +159,7 @@ > enum mtk_iommu_plat { > M4U_MT2712, > M4U_MT6779, > + M4U_MT6795, > M4U_MT8167, > M4U_MT8173, > M4U_MT8183, > @@ -954,7 +955,8 @@ static int mtk_iommu_hw_init(const struct > mtk_iommu_data *data, unsigned int ban >* Global control settings are in bank0. May re-init these > global registers >* since no sure if there is bank0 consumers. >*/ > - if (data->plat_data->m4u_plat == M4U_MT8173) { > + if (data->plat_data->m4u_plat == M4U_MT6795 || > + data->plat_data->m4u_plat == M4U_MT8173) { Add a new flag for this. This setting difference is that the offset for TF_PROT_TO_PROGRAM_ADDR is 5 in mt8173 while the others' offset is 4. thus, we could rename the flag like TF_PORT_TO_ADDR_MT8173 or TF_PORT_TO_ADDR_OFFSET_IS_5. > regval = F_MMU_PREFETCH_RT_REPLACE_MOD | >F_MMU_TF_PROT_TO_PROGRAM_ADDR_MT8173; > } else { > @@ -1422,6 +1424,18 @@ static const struct mtk_iommu_plat_data > mt6779_data = { > .larbid_remap = {{0}, {1}, {2}, {3}, {5}, {7, 8}, {10}, {9}}, > }; > > +static const struct mtk_iommu_plat_data mt6795_data = { > + .m4u_plat = M4U_MT6795, > + .flags= HAS_4GB_MODE | HAS_BCLK | RESET_AXI | > + HAS_LEGACY_IVRP_PADDR | MTK_IOMMU_TYPE_MM, > + .inv_sel_reg = REG_MMU_INV_SEL_GEN1, > + .banks_num= 1, > + .banks_enable = {true}, > + .iova_region = single_domain, > + .iova_region_nr = ARRAY_SIZE(single_domain), > + .larbid_remap = {{0}, {1}, {2}, {3}, {4}}, /* Linear mapping. > */ > +}; > + > static const struct mtk_iommu_plat_data mt8167_data = { > .m4u_plat = M4U_MT8167, > .flags= RESET_AXI | HAS_LEGACY_IVRP_PADDR | > MTK_IOMMU_TYPE_MM, > @@ -1533,6 +1547,7 @@ static const struct mtk_iommu_plat_data > mt8195_data_vpp = { > static const struct of_device_id mtk_iommu_of_ids[] = { > { .compatible = "mediatek,mt2712-m4u", .data = &mt2712_data}, > { .compatible = "mediatek,mt6779-m4u", .data = &mt6779_data}, > + { .compatible = "mediatek,mt6795-m4u", .data = &mt6795_data}, > { .compatible = "mediatek,mt8167-m4u", .data = &mt8167_data}, > { .compatible = "mediatek,mt8173-m4u", .data = &mt8173_data}, > { .compatible = "mediatek,mt8183-m4u", .data = &mt8183_data}, ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH v5 2/2] iommu/mediatek: Allow page table PA up to 35bit
On Mon, 2022-05-16 at 22:16 +0800, yf.w...@mediatek.com wrote: > From: Yunfei Wang > > Add the quirk IO_PGTABLE_QUIRK_ARM_MTK_TTBR_EXT support, so that > allows > page table PA up to 35bit, not only in ZONE_DMA32. Comment why this is needed. e.g. For single normal zone. > > Signed-off-by: Ning Li > Signed-off-by: Yunfei Wang > --- > drivers/iommu/mtk_iommu.c | 29 + > 1 file changed, 25 insertions(+), 4 deletions(-) > > diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c > index 6fd75a60abd6..1b9a876ef271 100644 > --- a/drivers/iommu/mtk_iommu.c > +++ b/drivers/iommu/mtk_iommu.c > @@ -33,6 +33,7 @@ > > #define REG_MMU_PT_BASE_ADDR 0x000 > #define MMU_PT_ADDR_MASK GENMASK(31, 7) > +#define MMU_PT_ADDR_2_0_MASK GENMASK(2, 0) > > #define REG_MMU_INVALIDATE 0x020 > #define F_ALL_INVLD 0x2 > @@ -118,6 +119,7 @@ > #define WR_THROT_EN BIT(6) > #define HAS_LEGACY_IVRP_PADDRBIT(7) > #define IOVA_34_EN BIT(8) > +#define PGTABLE_PA_35_EN BIT(9) > > #define MTK_IOMMU_HAS_FLAG(pdata, _x) \ > pdata)->flags) & (_x)) == (_x)) > @@ -401,6 +403,9 @@ static int mtk_iommu_domain_finalise(struct > mtk_iommu_domain *dom, > .iommu_dev = data->dev, > }; > > + if (MTK_IOMMU_HAS_FLAG(data->plat_data, PGTABLE_PA_35_EN)) > + dom->cfg.quirks |= IO_PGTABLE_QUIRK_ARM_MTK_TTBR_EXT; > + > if (MTK_IOMMU_HAS_FLAG(data->plat_data, HAS_4GB_MODE)) > dom->cfg.oas = data->enable_4GB ? 33 : 32; > else > @@ -450,6 +455,7 @@ static int mtk_iommu_attach_device(struct > iommu_domain *domain, > struct mtk_iommu_domain *dom = to_mtk_domain(domain); > struct device *m4udev = data->dev; > int ret, domid; > + u32 regval; > > domid = mtk_iommu_get_domain_id(dev, data->plat_data); > if (domid < 0) > @@ -472,8 +478,14 @@ static int mtk_iommu_attach_device(struct > iommu_domain *domain, > return ret; > } > data->m4u_dom = dom; > - writel(dom->cfg.arm_v7s_cfg.ttbr & MMU_PT_ADDR_MASK, > -data->base + REG_MMU_PT_BASE_ADDR); > + > + /* Bits[6:3] are invalid for mediatek platform */ > + if (MTK_IOMMU_HAS_FLAG(data->plat_data, > PGTABLE_PA_35_EN)) > + regval = (dom->cfg.arm_v7s_cfg.ttbr & > MMU_PT_ADDR_MASK) | > + (dom->cfg.arm_v7s_cfg.ttbr & > MMU_PT_ADDR_2_0_MASK); The bits[2:0] has already handled in ARM_V7S_TTBR_35BIT_PA of patch[1/2], we need calculate it again here? 1) Extend arm_v7s_cfg.ttbr to u64, then we could put the special ttbr logical into our file. 2) if 1) is not allowed, We have to put this in v7s. if (cfg->quirks & IO_PGTABLE_QUIRK_ARM_MTK_TTBR_EXT) { cfg->arm_v7s_cfg.ttbr = (paddr & GENMASK(31, 7)) | upper_32_bits(paddr); return &data->iop; } This need Robin/Will confirm. > + else > + regval = dom->cfg.arm_v7s_cfg.ttbr & > MMU_PT_ADDR_MASK; Save this value to our data. then we don't need calculate it again in the resume cb. > + writel(regval, data->base + REG_MMU_PT_BASE_ADDR); > > pm_runtime_put(m4udev); > } > @@ -987,6 +999,7 @@ static int __maybe_unused > mtk_iommu_runtime_resume(struct device *dev) > struct mtk_iommu_suspend_reg *reg = &data->reg; > struct mtk_iommu_domain *m4u_dom = data->m4u_dom; > void __iomem *base = data->base; > + u32 regval; > int ret; > > ret = clk_prepare_enable(data->bclk); > @@ -1010,7 +1023,14 @@ static int __maybe_unused > mtk_iommu_runtime_resume(struct device *dev) > writel_relaxed(reg->int_main_control, base + > REG_MMU_INT_MAIN_CONTROL); > writel_relaxed(reg->ivrp_paddr, base + REG_MMU_IVRP_PADDR); > writel_relaxed(reg->vld_pa_rng, base + REG_MMU_VLD_PA_RNG); > - writel(m4u_dom->cfg.arm_v7s_cfg.ttbr & MMU_PT_ADDR_MASK, base + > REG_MMU_PT_BASE_ADDR); > + > + /* Bits[6:3] are invalid for mediatek platform */ > + if (MTK_IOMMU_HAS_FLAG(data->plat_data, PGTABLE_PA_35_EN)) > + regval = (m4u_dom->cfg.arm_v7s_cfg.ttbr & > MMU_PT_ADDR_MASK) | > + (m4u_dom->cfg.arm_v7s_cfg.ttbr & > MMU_PT_ADDR_2_0_MASK); > + else > + regval = m4u_dom->cfg.arm_v7s_cfg.ttbr & > MMU_PT_ADDR_MASK; > + writel(regval, base + REG_MMU_PT_BASE_ADDR); > > /* >* Users may allocate dma buffer before they call > pm_runtime_get, > @@ -1038,7 +1058,8 @@ static const struct mtk_iommu_plat_data > mt2712_data = { > > static const struct mtk_iommu_plat_data mt6779_data = { > .m4u_plat = M4U_MT6779, > - .flags = HAS_SUB_COMM | OUT_ORDER_WR_EN | WR_THROT_EN, > + .flags = HAS_SUB_COMM | OUT_ORDER_WR_EN | WR_T
Re: [PATCH 2/2] iommu: mtk_iommu: Add support for MT6795 Helio X10 M4Us
On Tue, 2022-05-17 at 11:26 +0200, AngeloGioacchino Del Regno wrote: > Il 17/05/22 11:08, Yong Wu ha scritto: > > On Fri, 2022-05-13 at 17:14 +0200, AngeloGioacchino Del Regno > > wrote: > > > Add support for the M4Us found in the MT6795 Helio X10 SoC. > > > > > > Signed-off-by: AngeloGioacchino Del Regno < > > > angelogioacchino.delre...@collabora.com> > > > --- > > > drivers/iommu/mtk_iommu.c | 20 +++- > > > 1 file changed, 19 insertions(+), 1 deletion(-) [...] > > > +static const struct mtk_iommu_plat_data mt6795_data = { > > > + .m4u_plat = M4U_MT6795, > > > + .flags= HAS_4GB_MODE | HAS_BCLK | RESET_AXI | > > > + HAS_LEGACY_IVRP_PADDR | MTK_IOMMU_TYPE_MM, > > > + .inv_sel_reg = REG_MMU_INV_SEL_GEN1, > > > + .banks_num= 1, > > > + .banks_enable = {true}, > > > + .iova_region = single_domain, > > > + .iova_region_nr = ARRAY_SIZE(single_domain), > > > + .larbid_remap = {{0}, {1}, {2}, {3}, {4}}, /* Linear mapping. > > > */ > > > +}; > > > > This is nearly same with mt8173_data. mt8173 has one more larb than > > mt6795, its larbid_remap is also ok for mt6795. > > > > I think that we should be explicit about the larbid_remap property, > since mt6795 has one less larb, we should explicitly say that like > I did there... that's only for human readability I admit ... but, > still, I wouldn't want to see people thinking that MT6795 has 6 LARBs > because they've read that larbid_remap having 6 entries. In the linear mapping case, It does help. Strictly larbid_remap is two- dimensional array now, It doesn't indicate how many larbs this SoC has. If someone would like to know this, he could read the mtxxx-larb- port.h. We also could document the larb numbers in the binding for readability. Anyway, It is not a big problem. A new structure is ok for me. I just complain there are too many structures, specially in the internal branch which contains many non-upstream SoCs, and there may be several IOMMU HWs in one SoC. thus I'd like to group it personally. > > > thus it looks we could use mt8173 as the backward compatible. > > compatible = "mediatek,mt6795-m4u", > > "mediatek,mt8173-m4u"; > > > > After this, the only thing is about "mediatek,mt6795-infracfg". we > > have > > to try again with mediatek,mt6795-infracfg after mediatek,mt8173- > > infracfg fail. I think we should allow the backward case in 4GB > > mode > > judgment if we have. > > > > What's your opinion? or some other suggestion? > > Thanks. > > I know, I may have a plan for that, but I wanted to have a good > reason to > propose such a thing, as if it's just about two SoCs needing that, > there > would be no good reason to get things done differently. > > ...so, in order to provide a good cleanup, we have two possible roads > to > follow here: either we add a generic "mediatek,infracfg" compatible > to the > infra node (but I don't like that), or we can do it like it was > previously > done in mtk-pm-domains.c (I prefer that approach): > > iommu: iommu@somewhere { > ... something ... > mediatek,infracfg = <&infracfg>; We like this too. But this was not suggested from Rob long before. https://lore.kernel.org/linux-mediatek/20200715205120.GA778876@bogus/ > }; > > infracfg = syscon_regmap_lookup_by_compatible(node, > "mediatek,infracfg"); > if (IS_ERR(infracfg)) { > /* try with the older way */ > switch (...) { > case p = "mediatek,mt2712-infracfg"; > ... blah blah ... > } > /* legacy also failed, ouch! */ > if (IS_ERR(infracfg)) > return PTR_ERR(infracfg); > } > > ret = regmap_read ... etc etc etc > > Cheers, > Angelo ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH 2/2] iommu: mtk_iommu: Add support for MT6795 Helio X10 M4Us
On Fri, 2022-05-13 at 17:14 +0200, AngeloGioacchino Del Regno wrote: > Add support for the M4Us found in the MT6795 Helio X10 SoC. > > Signed-off-by: AngeloGioacchino Del Regno < > angelogioacchino.delre...@collabora.com> > --- > drivers/iommu/mtk_iommu.c | 20 +++- > 1 file changed, 19 insertions(+), 1 deletion(-) > > diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c > index 71b2ace74cd6..3d802dd3f377 100644 > --- a/drivers/iommu/mtk_iommu.c > +++ b/drivers/iommu/mtk_iommu.c > @@ -157,6 +157,7 @@ > enum mtk_iommu_plat { > M4U_MT2712, > M4U_MT6779, > + M4U_MT6795, > M4U_MT8167, > M4U_MT8173, > M4U_MT8183, > @@ -953,7 +954,8 @@ static int mtk_iommu_hw_init(const struct > mtk_iommu_data *data, unsigned int ban >* Global control settings are in bank0. May re-init these > global registers >* since no sure if there is bank0 consumers. >*/ > - if (data->plat_data->m4u_plat == M4U_MT8173) { > + if (data->plat_data->m4u_plat == M4U_MT6795 || > + data->plat_data->m4u_plat == M4U_MT8173) { > regval = F_MMU_PREFETCH_RT_REPLACE_MOD | >F_MMU_TF_PROT_TO_PROGRAM_ADDR_MT8173; > } else { > @@ -1138,6 +1140,9 @@ static int mtk_iommu_probe(struct > platform_device *pdev) > case M4U_MT2712: > p = "mediatek,mt2712-infracfg"; > break; > + case M4U_MT6795: > + p = "mediatek,mt6795-infracfg"; > + break; > case M4U_MT8173: > p = "mediatek,mt8173-infracfg"; > break; > @@ -1404,6 +1409,18 @@ static const struct mtk_iommu_plat_data > mt6779_data = { > .larbid_remap = {{0}, {1}, {2}, {3}, {5}, {7, 8}, {10}, {9}}, > }; > > +static const struct mtk_iommu_plat_data mt6795_data = { > + .m4u_plat = M4U_MT6795, > + .flags= HAS_4GB_MODE | HAS_BCLK | RESET_AXI | > + HAS_LEGACY_IVRP_PADDR | MTK_IOMMU_TYPE_MM, > + .inv_sel_reg = REG_MMU_INV_SEL_GEN1, > + .banks_num= 1, > + .banks_enable = {true}, > + .iova_region = single_domain, > + .iova_region_nr = ARRAY_SIZE(single_domain), > + .larbid_remap = {{0}, {1}, {2}, {3}, {4}}, /* Linear mapping. > */ > +}; This is nearly same with mt8173_data. mt8173 has one more larb than mt6795, its larbid_remap is also ok for mt6795. thus it looks we could use mt8173 as the backward compatible. compatible = "mediatek,mt6795-m4u", "mediatek,mt8173-m4u"; After this, the only thing is about "mediatek,mt6795-infracfg". we have to try again with mediatek,mt6795-infracfg after mediatek,mt8173- infracfg fail. I think we should allow the backward case in 4GB mode judgment if we have. What's your opinion? or some other suggestion? Thanks. > + > static const struct mtk_iommu_plat_data mt8167_data = { > .m4u_plat = M4U_MT8167, > .flags= RESET_AXI | HAS_LEGACY_IVRP_PADDR | > MTK_IOMMU_TYPE_MM, > @@ -1515,6 +1532,7 @@ static const struct mtk_iommu_plat_data > mt8195_data_vpp = { > static const struct of_device_id mtk_iommu_of_ids[] = { > { .compatible = "mediatek,mt2712-m4u", .data = &mt2712_data}, > { .compatible = "mediatek,mt6779-m4u", .data = &mt6779_data}, > + { .compatible = "mediatek,mt6795-m4u", .data = &mt6795_data}, > { .compatible = "mediatek,mt8167-m4u", .data = &mt8167_data}, > { .compatible = "mediatek,mt8173-m4u", .data = &mt8173_data}, > { .compatible = "mediatek,mt8183-m4u", .data = &mt8183_data}, ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH] iommu/dma: Fix iova map result check bug
On Sat, 2022-05-07 at 16:52 +0800, yf.w...@mediatek.com wrote: > From: Yunfei Wang > > The data type of the return value of the iommu_map_sg_atomic > is ssize_t, but the data type of iova size is size_t, > e.g. one is int while the other is unsigned int. > > When iommu_map_sg_atomic return value is compared with iova size, > it will force the signed int to be converted to unsigned int, if > iova map fails and iommu_map_sg_atomic return error code is less > than 0, then (ret < iova_len) is false, which will to cause not > do free iova, and the master can still successfully get the iova > of map fail, which is not expected. > > Therefore, we need to check the return value of iommu_map_sg_atomic > in two cases according to whether it is less than 0. > > Fixes: ad8f36e4b6b1 ("iommu: return full error code from > iommu_map_sg[_atomic]()") > Signed-off-by: Yunfei Wang > Cc: # 5.15.* > --- > drivers/iommu/dma-iommu.c | 7 --- > 1 file changed, 4 insertions(+), 3 deletions(-) > > diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c > index 09f6e1c0f9c0..2932281e93fc 100644 > --- a/drivers/iommu/dma-iommu.c > +++ b/drivers/iommu/dma-iommu.c > @@ -776,6 +776,7 @@ static struct page > **__iommu_dma_alloc_noncontiguous(struct device *dev, > unsigned int count, min_size, alloc_sizes = domain- > >pgsize_bitmap; > struct page **pages; > dma_addr_t iova; > + ssize_t ret; > > if (static_branch_unlikely(&iommu_deferred_attach_enabled) && > iommu_deferred_attach(dev, domain)) > @@ -813,8 +814,8 @@ static struct page > **__iommu_dma_alloc_noncontiguous(struct device *dev, > arch_dma_prep_coherent(sg_page(sg), sg- > >length); > } > > - if (iommu_map_sg_atomic(domain, iova, sgt->sgl, sgt- > >orig_nents, ioprot) > - < size) > + ret = iommu_map_sg_atomic(domain, iova, sgt->sgl, sgt- > >orig_nents, ioprot); > + if (ret < 0 || ret < size) if (IS_ERR_VALUE(ret) || ret < size) for readable? > goto out_free_sg; > > sgt->sgl->dma_address = iova; > @@ -1209,7 +1210,7 @@ static int iommu_dma_map_sg(struct device *dev, > struct scatterlist *sg, >* implementation - it knows better than we do. >*/ > ret = iommu_map_sg_atomic(domain, iova, sg, nents, prot); > - if (ret < iova_len) > + if (ret < 0 || ret < iova_len) > goto out_free_iova; > > return __finalise_sg(dev, sg, nents, iova); ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH 4/4] iommu/mediatek: Improve safety for mediatek, smi property in larb nodes
No functional change. Just improve safety from dts. All the larbs that connect to one IOMMU must connect with the same smi-common. This patch checks all the mediatek,smi property for each larb, If their mediatek,smi are different, it will return fails. Also avoid there is no available smi-larb nodes. Suggested-by: Guenter Roeck Signed-off-by: Yong Wu --- drivers/iommu/mtk_iommu.c | 49 ++- 1 file changed, 33 insertions(+), 16 deletions(-) diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c index 1ba92751e9df..75b9ede45a1a 100644 --- a/drivers/iommu/mtk_iommu.c +++ b/drivers/iommu/mtk_iommu.c @@ -1038,7 +1038,7 @@ static const struct component_master_ops mtk_iommu_com_ops = { static int mtk_iommu_mm_dts_parse(struct device *dev, struct component_match **match, struct mtk_iommu_data *data) { - struct device_node *larbnode, *smicomm_node, *smi_subcomm_node; + struct device_node *larbnode, *frst_avail_smicomm_node = NULL; struct platform_device *plarbdev; struct device_link *link; int i, larb_nr, ret; @@ -1050,6 +1050,7 @@ static int mtk_iommu_mm_dts_parse(struct device *dev, struct component_match **m return -EINVAL; for (i = 0; i < larb_nr; i++) { + struct device_node *smicomm_node, *smi_subcomm_node; u32 id; larbnode = of_parse_phandle(dev->of_node, "mediatek,larbs", i); @@ -1085,27 +1086,43 @@ static int mtk_iommu_mm_dts_parse(struct device *dev, struct component_match **m } data->larb_imu[id].dev = &plarbdev->dev; + /* Get smi-(sub)-common dev from the last larb. */ + smi_subcomm_node = of_parse_phandle(larbnode, "mediatek,smi", 0); + if (!smi_subcomm_node) { + ret = -EINVAL; + goto err_larbnode_put; + } + + /* +* It may have two level smi-common. the node is smi-sub-common if it +* has a new mediatek,smi property. otherwise it is smi-commmon. +*/ + smicomm_node = of_parse_phandle(smi_subcomm_node, "mediatek,smi", 0); + if (smicomm_node) + of_node_put(smi_subcomm_node); + else + smicomm_node = smi_subcomm_node; + + if (!frst_avail_smicomm_node) { + frst_avail_smicomm_node = smicomm_node; + } else if (frst_avail_smicomm_node != smicomm_node) { + dev_err(dev, "mediatek,smi is not right @larb%d.", id); + of_node_put(smicomm_node); + ret = -EINVAL; + goto err_larbnode_put; + } else { + of_node_put(smicomm_node); + } + component_match_add_release(dev, match, component_release_of, component_compare_of, larbnode); } - /* Get smi-(sub)-common dev from the last larb. */ - smi_subcomm_node = of_parse_phandle(larbnode, "mediatek,smi", 0); - if (!smi_subcomm_node) + if (!frst_avail_smicomm_node) return -EINVAL; - /* -* It may have two level smi-common. the node is smi-sub-common if it -* has a new mediatek,smi property. otherwise it is smi-commmon. -*/ - smicomm_node = of_parse_phandle(smi_subcomm_node, "mediatek,smi", 0); - if (smicomm_node) - of_node_put(smi_subcomm_node); - else - smicomm_node = smi_subcomm_node; - - plarbdev = of_find_device_by_node(smicomm_node); - of_node_put(smicomm_node); + plarbdev = of_find_device_by_node(frst_avail_smicomm_node); + of_node_put(frst_avail_smicomm_node); data->smicomm_dev = &plarbdev->dev; link = device_link_add(data->smicomm_dev, dev, -- 2.18.0 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH 3/4] iommu/mediatek: Validate number of phandles associated with "mediatek, larbs"
From: Guenter Roeck Fix the smatch warnings: drivers/iommu/mtk_iommu.c:878 mtk_iommu_mm_dts_parse() error: uninitialized symbol 'larbnode'. If someone abuse the dtsi node(Don't follow the definition of dt-binding), for example "mediatek,larbs" is provided as boolean property, the code may crash. To fix this problem and improve the code safety, add some checking for the invalid input from dtsi, e.g. checking the larb_nr/larbid valid range, and avoid "mediatek,larb-id" property conflicts in the smi-larb nodes. Fixes: d2e9a1102cfc ("iommu/mediatek: Contain MM IOMMU flow with the MM TYPE") Reported-by: kernel test robot Reported-by: Dan Carpenter Signed-off-by: Guenter Roeck Signed-off-by: Yong Wu --- drivers/iommu/mtk_iommu.c | 11 +++ 1 file changed, 11 insertions(+) diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c index 523bf59264e1..1ba92751e9df 100644 --- a/drivers/iommu/mtk_iommu.c +++ b/drivers/iommu/mtk_iommu.c @@ -1046,6 +1046,8 @@ static int mtk_iommu_mm_dts_parse(struct device *dev, struct component_match **m larb_nr = of_count_phandle_with_args(dev->of_node, "mediatek,larbs", NULL); if (larb_nr < 0) return larb_nr; + if (larb_nr == 0 || larb_nr > MTK_LARB_NR_MAX) + return -EINVAL; for (i = 0; i < larb_nr; i++) { u32 id; @@ -1062,6 +1064,10 @@ static int mtk_iommu_mm_dts_parse(struct device *dev, struct component_match **m ret = of_property_read_u32(larbnode, "mediatek,larb-id", &id); if (ret)/* The id is consecutive if there is no this property */ id = i; + if (id >= MTK_LARB_NR_MAX) { + ret = -EINVAL; + goto err_larbnode_put; + } plarbdev = of_find_device_by_node(larbnode); if (!plarbdev) { @@ -1072,6 +1078,11 @@ static int mtk_iommu_mm_dts_parse(struct device *dev, struct component_match **m ret = -EPROBE_DEFER; goto err_larbnode_put; } + + if (data->larb_imu[id].dev) { + ret = -EEXIST; + goto err_larbnode_put; + } data->larb_imu[id].dev = &plarbdev->dev; component_match_add_release(dev, match, component_release_of, -- 2.18.0 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH 2/4] iommu/mediatek: Add error path for loop of mm_dts_parse
The mtk_iommu_mm_dts_parse will parse the smi larbs nodes. if the i+1 larb is parsed fail(return -EINVAL), we should of_node_put for the 0..i larbs. Fixes: d2e9a1102cfc ("iommu/mediatek: Contain MM IOMMU flow with the MM TYPE") Signed-off-by: Yong Wu --- drivers/iommu/mtk_iommu.c | 21 - 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c index 0f6ec4a4d9d4..523bf59264e1 100644 --- a/drivers/iommu/mtk_iommu.c +++ b/drivers/iommu/mtk_iommu.c @@ -1065,12 +1065,12 @@ static int mtk_iommu_mm_dts_parse(struct device *dev, struct component_match **m plarbdev = of_find_device_by_node(larbnode); if (!plarbdev) { - of_node_put(larbnode); - return -ENODEV; + ret = -ENODEV; + goto err_larbnode_put; } if (!plarbdev->dev.driver) { - of_node_put(larbnode); - return -EPROBE_DEFER; + ret = -EPROBE_DEFER; + goto err_larbnode_put; } data->larb_imu[id].dev = &plarbdev->dev; @@ -1101,9 +1101,20 @@ static int mtk_iommu_mm_dts_parse(struct device *dev, struct component_match **m DL_FLAG_STATELESS | DL_FLAG_PM_RUNTIME); if (!link) { dev_err(dev, "Unable to link %s.\n", dev_name(data->smicomm_dev)); - return -EINVAL; + ret = -EINVAL; + goto err_larbnode_put; } return 0; + +err_larbnode_put: + while (i--) { + larbnode = of_parse_phandle(dev->of_node, "mediatek,larbs", i); + if (larbnode && of_device_is_available(larbnode)) { + of_node_put(larbnode); + of_node_put(larbnode); + } + } + return ret; } static int mtk_iommu_probe(struct platform_device *pdev) -- 2.18.0 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH 1/4] iommu/mediatek: Use dev_err_probe to mute probe_defer err log
Mute the probe defer log: [2.654806] mtk-iommu 14018000.iommu: mm dts parse fail(-517). [2.656168] mtk-iommu 1c01f000.iommu: mm dts parse fail(-517). Fixes: d2e9a1102cfc ("iommu/mediatek: Contain MM IOMMU flow with the MM TYPE") Signed-off-by: Yong Wu --- The Fixes tag commit-id is from linux-next. --- drivers/iommu/mtk_iommu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c index 71b2ace74cd6..0f6ec4a4d9d4 100644 --- a/drivers/iommu/mtk_iommu.c +++ b/drivers/iommu/mtk_iommu.c @@ -1198,7 +1198,7 @@ static int mtk_iommu_probe(struct platform_device *pdev) if (MTK_IOMMU_IS_TYPE(data->plat_data, MTK_IOMMU_TYPE_MM)) { ret = mtk_iommu_mm_dts_parse(dev, &match, data); if (ret) { - dev_err(dev, "mm dts parse fail(%d).", ret); + dev_err_probe(dev, ret, "mm dts parse fail."); goto out_runtime_disable; } } else if (MTK_IOMMU_IS_TYPE(data->plat_data, MTK_IOMMU_TYPE_INFRA) && -- 2.18.0 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH 0/4] iommu/mediatek: Improve safety from dts
This patchset contains several improved patches: [1/4] When mt8195 v7, I added a error log for dts parse fail, but it doesn't ignore probe_defer case.(v6 doesn't have this err log.) [2/4] Add a error path for MM dts parse. [3/4][4/4] To improve safety from dts. Base on this: https://lore.kernel.org/linux-mediatek/20211210205704.1664928-1-li...@roeck-us.net/ Base on linux-next-20220510. Guenter Roeck (1): iommu/mediatek: Validate number of phandles associated with "mediatek,larbs" Yong Wu (3): iommu/mediatek: Use dev_err_probe to mute probe_defer err log iommu/mediatek: Add error path for loop of mm_dts_parse iommu/mediatek: Improve safety for mediatek,smi property in larb nodes drivers/iommu/mtk_iommu.c | 83 --- 1 file changed, 61 insertions(+), 22 deletions(-) -- 2.18.0 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH v3] iommu/mediatek: Fix NULL pointer dereference when printing dev_name
On Thu, 2022-05-05 at 21:27 +0800, Miles Chen wrote: > When larbdev is NULL (in the case I hit, the node is incorrectly set > iommus = <&iommu NUM>), it will cause device_link_add() fail and > kernel crashes when we try to print dev_name(larbdev). > > Let's fail the probe if a larbdev is NULL to avoid invalid inputs > from > dts. > > It should work for normal correct setting and avoid the crash caused > by my incorrect setting. > > Error log: > [ 18.189042][ T301] Unable to handle kernel NULL pointer > dereference at virtual address 0050 > ... > [ 18.344519][ T301] pstate: a045 (NzCv daif +PAN -UAO) > [ 18.345213][ T301] pc : mtk_iommu_probe_device+0xf8/0x118 > [mtk_iommu] > [ 18.346050][ T301] lr : mtk_iommu_probe_device+0xd0/0x118 > [mtk_iommu] > [ 18.346884][ T301] sp : ffc00a5635e0 > [ 18.347392][ T301] x29: ffc00a5635e0 x28: ffd44a46c1d8 > [ 18.348156][ T301] x27: ff80c39a8000 x26: ffd44a80cc38 > [ 18.348917][ T301] x25: x24: ffd44a80cc38 > [ 18.349677][ T301] x23: ffd44e4da4c6 x22: ffd44a80cc38 > [ 18.350438][ T301] x21: ff80cecd1880 x20: > [ 18.351198][ T301] x19: ff80c439f010 x18: ffc00a50d0c0 > [ 18.351959][ T301] x17: x16: 0004 > [ 18.352719][ T301] x15: 0004 x14: ffd44eb5d420 > [ 18.353480][ T301] x13: 0ad2 x12: 0003 > [ 18.354241][ T301] x11: fad2 x10: c000fad2 > [ 18.355003][ T301] x9 : a0d288d8d7142d00 x8 : a0d288d8d7142d00 > [ 18.355763][ T301] x7 : ffd44c2bc640 x6 : > [ 18.356524][ T301] x5 : 0080 x4 : 0001 > [ 18.357284][ T301] x3 : x2 : 0005 > [ 18.358045][ T301] x1 : x0 : > [ 18.360208][ T301] Hardware name: MT6873 (DT) > [ 18.360771][ T301] Call trace: > [ 18.361168][ T301] dump_backtrace+0xf8/0x1f0 > [ 18.361737][ T301] dump_stack_lvl+0xa8/0x11c > [ 18.362305][ T301] dump_stack+0x1c/0x2c > [ 18.362816][ T301] mrdump_common_die+0x184/0x40c [mrdump] > [ 18.363575][ T301] ipanic_die+0x24/0x38 [mrdump] > [ 18.364230][ T301] atomic_notifier_call_chain+0x128/0x2b8 > [ 18.364937][ T301] die+0x16c/0x568 > [ 18.365394][ T301] __do_kernel_fault+0x1e8/0x214 > [ 18.365402][ T301] do_page_fault+0xb8/0x678 > [ 18.366934][ T301] do_translation_fault+0x48/0x64 > [ 18.368645][ T301] do_mem_abort+0x68/0x148 > [ 18.368652][ T301] el1_abort+0x40/0x64 > [ 18.368660][ T301] el1h_64_sync_handler+0x54/0x88 > [ 18.368668][ T301] el1h_64_sync+0x68/0x6c > [ 18.368673][ T301] mtk_iommu_probe_device+0xf8/0x118 [mtk_iommu] > ... > > Cc: Robin Murphy > Cc: Yong Wu > Reported-by: kernel test robot > Fixes: 635319a4a744 ("media: iommu/mediatek: Add device_link between > the consumer and the larb devices") > Signed-off-by: Miles Chen Reviewed-by: Yong Wu And this doesn't conflict with the MT8195 patchset. Thanks. ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH 2/2] iommu/mediatek: Enable allocating page table in normal memory
Hi YF, Thanks very much for this patch. Nearly all the lastest SoC like mt8192/mt8195 support this. On Fri, 2022-04-29 at 22:34 +0800, yf.w...@mediatek.com wrote: > From: Yunfei Wang > > Add the quirk IO_PGTABLE_QUIRK_ARM_MTK_TTBR_EXT support, so that > level 2 page table can allocate in normal memory. Could you help comment more detailedly here and in the title?, this patch just allows the level 2 pgtable PA up to 35bits, not only in ZONE_DMA32(GFP_DMA32). > > Signed-off-by: Ning Li > Signed-off-by: Yunfei Wang > Cc: # 5.10.* If you add this for stable, Which commit do you need for "Fixes:" tag? It looks you add a new feature, rather than fixing a bug of the current kernel. I didn't get a issue report for this. If this is a bug, we need more information like under which condition/SoC the error will occur. The code is ok for me. Thanks. > --- > drivers/iommu/mtk_iommu.c | 7 ++- > 1 file changed, 6 insertions(+), 1 deletion(-) > > diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c > index 6fd75a60abd6..27481f562df7 100644 > --- a/drivers/iommu/mtk_iommu.c > +++ b/drivers/iommu/mtk_iommu.c > @@ -118,6 +118,7 @@ > #define WR_THROT_EN BIT(6) > #define HAS_LEGACY_IVRP_PADDRBIT(7) > #define IOVA_34_EN BIT(8) > +#define PGTABLE_L2_PA_35_EN BIT(9) > > #define MTK_IOMMU_HAS_FLAG(pdata, _x) \ > pdata)->flags) & (_x)) == (_x)) > @@ -401,6 +402,9 @@ static int mtk_iommu_domain_finalise(struct > mtk_iommu_domain *dom, > .iommu_dev = data->dev, > }; > > + if (MTK_IOMMU_HAS_FLAG(data->plat_data, PGTABLE_L2_PA_35_EN)) > + dom->cfg.quirks |= IO_PGTABLE_QUIRK_ARM_MTK_TTBR_EXT; > + > if (MTK_IOMMU_HAS_FLAG(data->plat_data, HAS_4GB_MODE)) > dom->cfg.oas = data->enable_4GB ? 33 : 32; > else > @@ -1038,7 +1042,8 @@ static const struct mtk_iommu_plat_data > mt2712_data = { > > static const struct mtk_iommu_plat_data mt6779_data = { > .m4u_plat = M4U_MT6779, > - .flags = HAS_SUB_COMM | OUT_ORDER_WR_EN | WR_THROT_EN, > + .flags = HAS_SUB_COMM | OUT_ORDER_WR_EN | WR_THROT_EN | > + PGTABLE_L2_PA_35_EN, > .inv_sel_reg = REG_MMU_INV_SEL_GEN2, > .iova_region = single_domain, > .iova_region_nr = ARRAY_SIZE(single_domain), ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH v7 36/36] iommu/mediatek: Add mt8186 iommu support
Add mt8186 iommu supports. Signed-off-by: Anan Sun Signed-off-by: Yong Wu Reviewed-by: Matthias Brugger Reviewed-by: AngeloGioacchino Del Regno --- drivers/iommu/mtk_iommu.c | 16 1 file changed, 16 insertions(+) diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c index 0fa1d5240ac6..71b2ace74cd6 100644 --- a/drivers/iommu/mtk_iommu.c +++ b/drivers/iommu/mtk_iommu.c @@ -160,6 +160,7 @@ enum mtk_iommu_plat { M4U_MT8167, M4U_MT8173, M4U_MT8183, + M4U_MT8186, M4U_MT8192, M4U_MT8195, }; @@ -1437,6 +1438,20 @@ static const struct mtk_iommu_plat_data mt8183_data = { .larbid_remap = {{0}, {4}, {5}, {6}, {7}, {2}, {3}, {1}}, }; +static const struct mtk_iommu_plat_data mt8186_data_mm = { + .m4u_plat = M4U_MT8186, + .flags = HAS_BCLK | HAS_SUB_COMM_2BITS | OUT_ORDER_WR_EN | + WR_THROT_EN | IOVA_34_EN | MTK_IOMMU_TYPE_MM, + .larbid_remap = {{0}, {1, MTK_INVALID_LARBID, 8}, {4}, {7}, {2}, {9, 11, 19, 20}, + {MTK_INVALID_LARBID, 14, 16}, + {MTK_INVALID_LARBID, 13, MTK_INVALID_LARBID, 17}}, + .inv_sel_reg= REG_MMU_INV_SEL_GEN2, + .banks_num = 1, + .banks_enable = {true}, + .iova_region= mt8192_multi_dom, + .iova_region_nr = ARRAY_SIZE(mt8192_multi_dom), +}; + static const struct mtk_iommu_plat_data mt8192_data = { .m4u_plat = M4U_MT8192, .flags = HAS_BCLK | HAS_SUB_COMM_2BITS | OUT_ORDER_WR_EN | @@ -1503,6 +1518,7 @@ static const struct of_device_id mtk_iommu_of_ids[] = { { .compatible = "mediatek,mt8167-m4u", .data = &mt8167_data}, { .compatible = "mediatek,mt8173-m4u", .data = &mt8173_data}, { .compatible = "mediatek,mt8183-m4u", .data = &mt8183_data}, + { .compatible = "mediatek,mt8186-iommu-mm",.data = &mt8186_data_mm}, /* mm: m4u */ { .compatible = "mediatek,mt8192-m4u", .data = &mt8192_data}, { .compatible = "mediatek,mt8195-iommu-infra", .data = &mt8195_data_infra}, { .compatible = "mediatek,mt8195-iommu-vdo", .data = &mt8195_data_vdo}, -- 2.18.0 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH v7 35/36] iommu/mediatek: mt8195: Enable multi banks for infra iommu
Enable the multi-bank functions for infra-iommu. We put PCIE in bank0 and USB in the last bank(bank4). and we don't use the other banks currently, disable them. Signed-off-by: Yong Wu Reviewed-by: AngeloGioacchino Del Regno --- drivers/iommu/mtk_iommu.c | 7 +-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c index d3e8773b4c47..0fa1d5240ac6 100644 --- a/drivers/iommu/mtk_iommu.c +++ b/drivers/iommu/mtk_iommu.c @@ -1456,8 +1456,11 @@ static const struct mtk_iommu_plat_data mt8195_data_infra = { MTK_IOMMU_TYPE_INFRA | IFA_IOMMU_PCIE_SUPPORT, .pericfg_comp_str = "mediatek,mt8195-pericfg_ao", .inv_sel_reg = REG_MMU_INV_SEL_GEN2, - .banks_num= 1, - .banks_enable = {true}, + .banks_num= 5, + .banks_enable = {true, false, false, false, true}, + .banks_portmsk= {[0] = GENMASK(19, 16), /* PCIe */ +[4] = GENMASK(31, 20), /* USB */ + }, .iova_region = single_domain, .iova_region_nr = ARRAY_SIZE(single_domain), }; -- 2.18.0 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH v7 34/36] iommu/mediatek: Backup/restore regsiters for multi banks
Each bank has some independent registers. thus backup/restore them for each a bank when suspend and resume. Signed-off-by: Yong Wu Reviewed-by: AngeloGioacchino Del Regno --- drivers/iommu/mtk_iommu.c | 46 ++- 1 file changed, 31 insertions(+), 15 deletions(-) diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c index 400dea33aea1..d3e8773b4c47 100644 --- a/drivers/iommu/mtk_iommu.c +++ b/drivers/iommu/mtk_iommu.c @@ -173,11 +173,12 @@ struct mtk_iommu_suspend_reg { u32 misc_ctrl; u32 dcm_dis; u32 ctrl_reg; - u32 int_control0; - u32 int_main_control; - u32 ivrp_paddr; u32 vld_pa_rng; u32 wr_len_ctrl; + + u32 int_control[MTK_IOMMU_BANK_MAX]; + u32 int_main_control[MTK_IOMMU_BANK_MAX]; + u32 ivrp_paddr[MTK_IOMMU_BANK_MAX]; }; struct mtk_iommu_plat_data { @@ -1302,16 +1303,23 @@ static int __maybe_unused mtk_iommu_runtime_suspend(struct device *dev) { struct mtk_iommu_data *data = dev_get_drvdata(dev); struct mtk_iommu_suspend_reg *reg = &data->reg; - void __iomem *base = data->bank[0].base; + void __iomem *base; + int i = 0; + base = data->bank[i].base; reg->wr_len_ctrl = readl_relaxed(base + REG_MMU_WR_LEN_CTRL); reg->misc_ctrl = readl_relaxed(base + REG_MMU_MISC_CTRL); reg->dcm_dis = readl_relaxed(base + REG_MMU_DCM_DIS); reg->ctrl_reg = readl_relaxed(base + REG_MMU_CTRL_REG); - reg->int_control0 = readl_relaxed(base + REG_MMU_INT_CONTROL0); - reg->int_main_control = readl_relaxed(base + REG_MMU_INT_MAIN_CONTROL); - reg->ivrp_paddr = readl_relaxed(base + REG_MMU_IVRP_PADDR); reg->vld_pa_rng = readl_relaxed(base + REG_MMU_VLD_PA_RNG); + do { + if (!data->plat_data->banks_enable[i]) + continue; + base = data->bank[i].base; + reg->int_control[i] = readl_relaxed(base + REG_MMU_INT_CONTROL0); + reg->int_main_control[i] = readl_relaxed(base + REG_MMU_INT_MAIN_CONTROL); + reg->ivrp_paddr[i] = readl_relaxed(base + REG_MMU_IVRP_PADDR); + } while (++i < data->plat_data->banks_num); clk_disable_unprepare(data->bclk); return 0; } @@ -1320,9 +1328,9 @@ static int __maybe_unused mtk_iommu_runtime_resume(struct device *dev) { struct mtk_iommu_data *data = dev_get_drvdata(dev); struct mtk_iommu_suspend_reg *reg = &data->reg; - struct mtk_iommu_domain *m4u_dom = data->bank[0].m4u_dom; - void __iomem *base = data->bank[0].base; - int ret; + struct mtk_iommu_domain *m4u_dom; + void __iomem *base; + int ret, i = 0; ret = clk_prepare_enable(data->bclk); if (ret) { @@ -1334,18 +1342,26 @@ static int __maybe_unused mtk_iommu_runtime_resume(struct device *dev) * Uppon first resume, only enable the clk and return, since the values of the * registers are not yet set. */ - if (!m4u_dom) + if (!reg->wr_len_ctrl) return 0; + base = data->bank[i].base; writel_relaxed(reg->wr_len_ctrl, base + REG_MMU_WR_LEN_CTRL); writel_relaxed(reg->misc_ctrl, base + REG_MMU_MISC_CTRL); writel_relaxed(reg->dcm_dis, base + REG_MMU_DCM_DIS); writel_relaxed(reg->ctrl_reg, base + REG_MMU_CTRL_REG); - writel_relaxed(reg->int_control0, base + REG_MMU_INT_CONTROL0); - writel_relaxed(reg->int_main_control, base + REG_MMU_INT_MAIN_CONTROL); - writel_relaxed(reg->ivrp_paddr, base + REG_MMU_IVRP_PADDR); writel_relaxed(reg->vld_pa_rng, base + REG_MMU_VLD_PA_RNG); - writel(m4u_dom->cfg.arm_v7s_cfg.ttbr & MMU_PT_ADDR_MASK, base + REG_MMU_PT_BASE_ADDR); + do { + m4u_dom = data->bank[i].m4u_dom; + if (!data->plat_data->banks_enable[i] || !m4u_dom) + continue; + base = data->bank[i].base; + writel_relaxed(reg->int_control[i], base + REG_MMU_INT_CONTROL0); + writel_relaxed(reg->int_main_control[i], base + REG_MMU_INT_MAIN_CONTROL); + writel_relaxed(reg->ivrp_paddr[i], base + REG_MMU_IVRP_PADDR); + writel(m4u_dom->cfg.arm_v7s_cfg.ttbr & MMU_PT_ADDR_MASK, + base + REG_MMU_PT_BASE_ADDR); + } while (++i < data->plat_data->banks_num); /* * Users may allocate dma buffer before they call pm_runtime_get, -- 2.18.0 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH v7 33/36] iommu/mediatek: Initialise/Remove for multi bank dev
The registers for each bank of the IOMMU base are in order, delta is 0x1000. Initialise the base for each bank. For all the previous SoC, we only have bank0. thus use "do {} while()" to allow bank0 always go. When removing the device, Not always all the banks are initialised, it depend on if there is masters for that bank. Signed-off-by: Yong Wu Reviewed-by: AngeloGioacchino Del Regno --- drivers/iommu/mtk_iommu.c | 44 ++- 1 file changed, 30 insertions(+), 14 deletions(-) diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c index 5f3e88c44514..400dea33aea1 100644 --- a/drivers/iommu/mtk_iommu.c +++ b/drivers/iommu/mtk_iommu.c @@ -113,6 +113,7 @@ #define F_MMU_INT_ID_PORT_ID(a)(((a) >> 2) & 0x1f) #define MTK_PROTECT_PA_ALIGN 256 +#define MTK_IOMMU_BANK_SZ 0x1000 #define PERICFG_IOMMU_10x714 @@ -1112,7 +1113,7 @@ static int mtk_iommu_probe(struct platform_device *pdev) struct component_match *match = NULL; struct regmap *infracfg; void*protect; - int ret, banks_num; + int ret, banks_num, i = 0; u32 val; char*p; struct mtk_iommu_bank_data *bank; @@ -1153,27 +1154,36 @@ static int mtk_iommu_probe(struct platform_device *pdev) data->enable_4GB = !!(val & F_DDR_4GB_SUPPORT_EN); } + banks_num = data->plat_data->banks_num; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (resource_size(res) < banks_num * MTK_IOMMU_BANK_SZ) { + dev_err(dev, "banknr %d. res %pR is not enough.\n", banks_num, res); + return -EINVAL; + } base = devm_ioremap_resource(dev, res); if (IS_ERR(base)) return PTR_ERR(base); ioaddr = res->start; - banks_num = data->plat_data->banks_num; data->bank = devm_kmalloc(dev, banks_num * sizeof(*data->bank), GFP_KERNEL); if (!data->bank) return -ENOMEM; - bank = &data->bank[0]; - bank->id = 0; - bank->base = base; - bank->m4u_dom = NULL; - bank->irq = platform_get_irq(pdev, 0); - if (bank->irq < 0) - return bank->irq; - bank->parent_dev = dev; - bank->parent_data = data; - spin_lock_init(&bank->tlb_lock); + do { + if (!data->plat_data->banks_enable[i]) + continue; + bank = &data->bank[i]; + bank->id = i; + bank->base = base + i * MTK_IOMMU_BANK_SZ; + bank->m4u_dom = NULL; + + bank->irq = platform_get_irq(pdev, i); + if (bank->irq < 0) + return bank->irq; + bank->parent_dev = dev; + bank->parent_data = data; + spin_lock_init(&bank->tlb_lock); + } while (++i < banks_num); if (MTK_IOMMU_HAS_FLAG(data->plat_data, HAS_BCLK)) { data->bclk = devm_clk_get(dev, "bclk"); @@ -1261,7 +1271,8 @@ static int mtk_iommu_probe(struct platform_device *pdev) static int mtk_iommu_remove(struct platform_device *pdev) { struct mtk_iommu_data *data = platform_get_drvdata(pdev); - struct mtk_iommu_bank_data *bank = &data->bank[0]; + struct mtk_iommu_bank_data *bank; + int i; iommu_device_sysfs_remove(&data->iommu); iommu_device_unregister(&data->iommu); @@ -1278,7 +1289,12 @@ static int mtk_iommu_remove(struct platform_device *pdev) #endif } pm_runtime_disable(&pdev->dev); - devm_free_irq(&pdev->dev, bank->irq, bank); + for (i = 0; i < data->plat_data->banks_num; i++) { + bank = &data->bank[i]; + if (!bank->m4u_dom) + continue; + devm_free_irq(&pdev->dev, bank->irq, bank); + } return 0; } -- 2.18.0 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH v7 32/36] iommu/mediatek: Get the proper bankid for multi banks
We preassign some ports in a special bank via the new defined banks_portmsk. Put it in the plat_data means it is not expected to be adjusted dynamically. If the iommu id in the iommu consumer's dtsi node is inside this banks_portmsk, then we switch it to this special iommu bank, and initialise the IOMMU bank HW. Each bank has the independent pgtable(4GB iova range). Each bank is a independent iommu domain/group. Currently we don't separate different iova ranges inside a bank. Signed-off-by: Yong Wu Reviewed-by: AngeloGioacchino Del Regno --- drivers/iommu/mtk_iommu.c | 55 ++- 1 file changed, 48 insertions(+), 7 deletions(-) diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c index 023bb7d3ffb2..5f3e88c44514 100644 --- a/drivers/iommu/mtk_iommu.c +++ b/drivers/iommu/mtk_iommu.c @@ -191,6 +191,7 @@ struct mtk_iommu_plat_data { u8 banks_num; boolbanks_enable[MTK_IOMMU_BANK_MAX]; + unsigned intbanks_portmsk[MTK_IOMMU_BANK_MAX]; unsigned char larbid_remap[MTK_LARB_COM_MAX][MTK_LARB_SUBCOM_MAX]; }; @@ -467,6 +468,30 @@ static irqreturn_t mtk_iommu_isr(int irq, void *dev_id) return IRQ_HANDLED; } +static unsigned int mtk_iommu_get_bank_id(struct device *dev, + const struct mtk_iommu_plat_data *plat_data) +{ + struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev); + unsigned int i, portmsk = 0, bankid = 0; + + if (plat_data->banks_num == 1) + return bankid; + + for (i = 0; i < fwspec->num_ids; i++) + portmsk |= BIT(MTK_M4U_TO_PORT(fwspec->ids[i])); + + for (i = 0; i < plat_data->banks_num && i < MTK_IOMMU_BANK_MAX; i++) { + if (!plat_data->banks_enable[i]) + continue; + + if (portmsk & plat_data->banks_portmsk[i]) { + bankid = i; + break; + } + } + return bankid; /* default is 0 */ +} + static int mtk_iommu_get_iova_region_id(struct device *dev, const struct mtk_iommu_plat_data *plat_data) { @@ -619,13 +644,14 @@ static int mtk_iommu_attach_device(struct iommu_domain *domain, struct list_head *hw_list = data->hw_list; struct device *m4udev = data->dev; struct mtk_iommu_bank_data *bank; - unsigned int bankid = 0; + unsigned int bankid; int ret, region_id; region_id = mtk_iommu_get_iova_region_id(dev, data->plat_data); if (region_id < 0) return region_id; + bankid = mtk_iommu_get_bank_id(dev, data->plat_data); mutex_lock(&dom->mutex); if (!dom->bank) { /* Data is in the frstdata in sharing pgtable case. */ @@ -797,27 +823,42 @@ static void mtk_iommu_release_device(struct device *dev) iommu_fwspec_free(dev); } +static int mtk_iommu_get_group_id(struct device *dev, const struct mtk_iommu_plat_data *plat_data) +{ + unsigned int bankid; + + /* +* If the bank function is enabled, each bank is a iommu group/domain. +* Otherwise, each iova region is a iommu group/domain. +*/ + bankid = mtk_iommu_get_bank_id(dev, plat_data); + if (bankid) + return bankid; + + return mtk_iommu_get_iova_region_id(dev, plat_data); +} + static struct iommu_group *mtk_iommu_device_group(struct device *dev) { struct mtk_iommu_data *c_data = dev_iommu_priv_get(dev), *data; struct list_head *hw_list = c_data->hw_list; struct iommu_group *group; - int regionid; + int groupid; data = mtk_iommu_get_frst_data(hw_list); if (!data) return ERR_PTR(-ENODEV); - regionid = mtk_iommu_get_iova_region_id(dev, data->plat_data); - if (regionid < 0) - return ERR_PTR(regionid); + groupid = mtk_iommu_get_group_id(dev, data->plat_data); + if (groupid < 0) + return ERR_PTR(groupid); mutex_lock(&data->mutex); - group = data->m4u_group[regionid]; + group = data->m4u_group[groupid]; if (!group) { group = iommu_group_alloc(); if (!IS_ERR(group)) - data->m4u_group[regionid] = group; + data->m4u_group[groupid] = group; } else { iommu_group_ref_get(group); } -- 2.18.0 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH v7 31/36] iommu/mediatek: Change the domid to iova_region_id
Prepare for adding bankid, also no functional change. In the previous SoC, each a iova_region is a domain; In the multi-banks case, each a bank is a domain, then the original function name "mtk_iommu_get_domain_id" is not proper. Use "iova_region_id" instead of "domain_id". Signed-off-by: Yong Wu Reviewed-by: AngeloGioacchino Del Regno --- drivers/iommu/mtk_iommu.c | 46 +++ 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c index 5f298cf6aac3..023bb7d3ffb2 100644 --- a/drivers/iommu/mtk_iommu.c +++ b/drivers/iommu/mtk_iommu.c @@ -467,8 +467,8 @@ static irqreturn_t mtk_iommu_isr(int irq, void *dev_id) return IRQ_HANDLED; } -static int mtk_iommu_get_domain_id(struct device *dev, - const struct mtk_iommu_plat_data *plat_data) +static int mtk_iommu_get_iova_region_id(struct device *dev, + const struct mtk_iommu_plat_data *plat_data) { const struct mtk_iommu_iova_region *rgn = plat_data->iova_region; const struct bus_dma_region *dma_rgn = dev->dma_range_map; @@ -498,7 +498,7 @@ static int mtk_iommu_get_domain_id(struct device *dev, } static int mtk_iommu_config(struct mtk_iommu_data *data, struct device *dev, - bool enable, unsigned int domid) + bool enable, unsigned int regionid) { struct mtk_smi_larb_iommu*larb_mmu; unsigned int larbid, portid; @@ -514,12 +514,12 @@ static int mtk_iommu_config(struct mtk_iommu_data *data, struct device *dev, if (MTK_IOMMU_IS_TYPE(data->plat_data, MTK_IOMMU_TYPE_MM)) { larb_mmu = &data->larb_imu[larbid]; - region = data->plat_data->iova_region + domid; + region = data->plat_data->iova_region + regionid; larb_mmu->bank[portid] = upper_32_bits(region->iova_base); - dev_dbg(dev, "%s iommu for larb(%s) port %d dom %d bank %d.\n", + dev_dbg(dev, "%s iommu for larb(%s) port %d region %d rgn-bank %d.\n", enable ? "enable" : "disable", dev_name(larb_mmu->dev), - portid, domid, larb_mmu->bank[portid]); + portid, regionid, larb_mmu->bank[portid]); if (enable) larb_mmu->mmu |= MTK_SMI_MMU_EN(portid); @@ -545,7 +545,7 @@ static int mtk_iommu_config(struct mtk_iommu_data *data, struct device *dev, static int mtk_iommu_domain_finalise(struct mtk_iommu_domain *dom, struct mtk_iommu_data *data, -unsigned int domid) +unsigned int region_id) { const struct mtk_iommu_iova_region *region; struct mtk_iommu_domain *m4u_dom; @@ -584,7 +584,7 @@ static int mtk_iommu_domain_finalise(struct mtk_iommu_domain *dom, update_iova_region: /* Update the iova region for this domain */ - region = data->plat_data->iova_region + domid; + region = data->plat_data->iova_region + region_id; dom->domain.geometry.aperture_start = region->iova_base; dom->domain.geometry.aperture_end = region->iova_base + region->size - 1; dom->domain.geometry.force_aperture = true; @@ -620,18 +620,18 @@ static int mtk_iommu_attach_device(struct iommu_domain *domain, struct device *m4udev = data->dev; struct mtk_iommu_bank_data *bank; unsigned int bankid = 0; - int ret, domid; + int ret, region_id; - domid = mtk_iommu_get_domain_id(dev, data->plat_data); - if (domid < 0) - return domid; + region_id = mtk_iommu_get_iova_region_id(dev, data->plat_data); + if (region_id < 0) + return region_id; mutex_lock(&dom->mutex); if (!dom->bank) { /* Data is in the frstdata in sharing pgtable case. */ frstdata = mtk_iommu_get_frst_data(hw_list); - ret = mtk_iommu_domain_finalise(dom, frstdata, domid); + ret = mtk_iommu_domain_finalise(dom, frstdata, region_id); if (ret) { mutex_unlock(&dom->mutex); return -ENODEV; @@ -662,7 +662,7 @@ static int mtk_iommu_attach_device(struct iommu_domain *domain, } mutex_unlock(&data->mutex); - return mtk_iommu_config(data, dev, true, domid); + return mtk_iommu_config(data, dev, true, region_id); err_unlock: mutex_unlock(&data->mutex); @@ -802,22 +802,22 @@ static struct iommu_group *mtk_iommu_device_group(struct device *dev) struct mtk_iommu_data *c_data = dev_iommu_priv_get(dev), *data; struct list_head *hw_list = c_data->hw_list; struct iom
[PATCH v7 30/36] iommu/mediatek: Initialise bank HW for each a bank
The mt8195 IOMMU HW max support 5 banks, and regarding the banks' registers, it looks like: |bank0 | bank1 | bank2 | bank3 | bank4| |global | |control| null |regs | - |bank |bank |bank |bank |bank | |regs |regs |regs |regs |regs | | | | | | | - Each bank has some special bank registers and it share bank0's global control registers. this patch initialise the bank hw with the bankid. In the hw_init, we always initialise bank0's control register since we don't know if the bank0 is initialised. Additionally, About each bank's register base, always delta 0x1000. like bank[x + 1] = bank[x] + 0x1000. Signed-off-by: Yong Wu Reviewed-by: AngeloGioacchino Del Regno --- drivers/iommu/mtk_iommu.c | 32 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c index 968e1486e6fd..5f298cf6aac3 100644 --- a/drivers/iommu/mtk_iommu.c +++ b/drivers/iommu/mtk_iommu.c @@ -259,7 +259,7 @@ static void mtk_iommu_unbind(struct device *dev) static const struct iommu_ops mtk_iommu_ops; -static int mtk_iommu_hw_init(const struct mtk_iommu_data *data); +static int mtk_iommu_hw_init(const struct mtk_iommu_data *data, unsigned int bankid); #define MTK_IOMMU_TLB_ADDR(iova) ({\ dma_addr_t _addr = iova;\ @@ -642,12 +642,14 @@ static int mtk_iommu_attach_device(struct iommu_domain *domain, mutex_lock(&data->mutex); bank = &data->bank[bankid]; - if (!bank->m4u_dom) { /* Initialize the M4U HW */ + if (!bank->m4u_dom) { /* Initialize the M4U HW for each a BANK */ ret = pm_runtime_resume_and_get(m4udev); - if (ret < 0) + if (ret < 0) { + dev_err(m4udev, "pm get fail(%d) in attach.\n", ret); goto err_unlock; + } - ret = mtk_iommu_hw_init(data); + ret = mtk_iommu_hw_init(data, bankid); if (ret) { pm_runtime_put(m4udev); goto err_unlock; @@ -897,11 +899,16 @@ static const struct iommu_ops mtk_iommu_ops = { } }; -static int mtk_iommu_hw_init(const struct mtk_iommu_data *data) +static int mtk_iommu_hw_init(const struct mtk_iommu_data *data, unsigned int bankid) { + const struct mtk_iommu_bank_data *bankx = &data->bank[bankid]; const struct mtk_iommu_bank_data *bank0 = &data->bank[0]; u32 regval; + /* +* Global control settings are in bank0. May re-init these global registers +* since no sure if there is bank0 consumers. +*/ if (data->plat_data->m4u_plat == M4U_MT8173) { regval = F_MMU_PREFETCH_RT_REPLACE_MOD | F_MMU_TF_PROT_TO_PROGRAM_ADDR_MT8173; @@ -944,13 +951,14 @@ static int mtk_iommu_hw_init(const struct mtk_iommu_data *data) } writel_relaxed(regval, bank0->base + REG_MMU_MISC_CTRL); + /* Independent settings for each bank */ regval = F_L2_MULIT_HIT_EN | F_TABLE_WALK_FAULT_INT_EN | F_PREETCH_FIFO_OVERFLOW_INT_EN | F_MISS_FIFO_OVERFLOW_INT_EN | F_PREFETCH_FIFO_ERR_INT_EN | F_MISS_FIFO_ERR_INT_EN; - writel_relaxed(regval, bank0->base + REG_MMU_INT_CONTROL0); + writel_relaxed(regval, bankx->base + REG_MMU_INT_CONTROL0); regval = F_INT_TRANSLATION_FAULT | F_INT_MAIN_MULTI_HIT_FAULT | @@ -959,19 +967,19 @@ static int mtk_iommu_hw_init(const struct mtk_iommu_data *data) F_INT_TLB_MISS_FAULT | F_INT_MISS_TRANSACTION_FIFO_FAULT | F_INT_PRETETCH_TRANSATION_FIFO_FAULT; - writel_relaxed(regval, bank0->base + REG_MMU_INT_MAIN_CONTROL); + writel_relaxed(regval, bankx->base + REG_MMU_INT_MAIN_CONTROL); if (MTK_IOMMU_HAS_FLAG(data->plat_data, HAS_LEGACY_IVRP_PADDR)) regval = (data->protect_base >> 1) | (data->enable_4GB << 31); else regval = lower_32_bits(data->protect_base) | upper_32_bits(data->protect_base); - writel_relaxed(regval, bank0->base + REG_MMU_IVRP_PADDR); + writel_relaxed(regval, bankx->base + REG_MMU_IVRP_PADDR); - if (devm_request_irq(bank0->parent_dev, bank0->irq, mtk_iommu_isr, 0, -dev_name(bank0->parent_dev), (void *)bank0)) { - writel_relaxed(0, bank0->base + REG_MMU_PT_BASE_ADDR); - dev_err(bank0->parent_dev, "Failed @ IRQ-%d Request\n", bank0->irq); + if (devm_request_irq(bankx->parent_dev, bankx->irq, mtk_iomm
[PATCH v7 29/36] iommu/mediatek: Add mtk_iommu_bank_data structure
Prepare for supporting multi-banks for the IOMMU HW, No functional change. Add a new structure(mtk_iommu_bank_data) for each a bank. Each a bank have the independent HW base/IRQ/tlb-range ops, and each a bank has its special iommu-domain(independent pgtable), thus, also move the domain information into it. In previous SoC, we have only one bank which could be treated as bank0( bankid always is 0 for the previous SoC). After adding this structure, the tlb operations and irq could use bank_data as parameter. Signed-off-by: Yong Wu Reviewed-by: AngeloGioacchino Del Regno --- drivers/iommu/mtk_iommu.c | 179 +- 1 file changed, 117 insertions(+), 62 deletions(-) diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c index 349640bcbd01..968e1486e6fd 100644 --- a/drivers/iommu/mtk_iommu.c +++ b/drivers/iommu/mtk_iommu.c @@ -151,6 +151,7 @@ #define MTK_LARB_SUBCOM_MAX8 #define MTK_IOMMU_GROUP_MAX8 +#define MTK_IOMMU_BANK_MAX 5 enum mtk_iommu_plat { M4U_MT2712, @@ -187,25 +188,36 @@ struct mtk_iommu_plat_data { struct list_head*hw_list; unsigned intiova_region_nr; const struct mtk_iommu_iova_region *iova_region; + + u8 banks_num; + boolbanks_enable[MTK_IOMMU_BANK_MAX]; unsigned char larbid_remap[MTK_LARB_COM_MAX][MTK_LARB_SUBCOM_MAX]; }; -struct mtk_iommu_data { +struct mtk_iommu_bank_data { void __iomem*base; int irq; + u8 id; + struct device *parent_dev; + struct mtk_iommu_data *parent_data; + spinlock_t tlb_lock; /* lock for tlb range flush */ + struct mtk_iommu_domain *m4u_dom; /* Each bank has a domain */ +}; + +struct mtk_iommu_data { struct device *dev; struct clk *bclk; phys_addr_t protect_base; /* protect memory base */ struct mtk_iommu_suspend_regreg; - struct mtk_iommu_domain *m4u_dom; struct iommu_group *m4u_group[MTK_IOMMU_GROUP_MAX]; boolenable_4GB; - spinlock_t tlb_lock; /* lock for tlb range flush */ struct iommu_device iommu; const struct mtk_iommu_plat_data *plat_data; struct device *smicomm_dev; + struct mtk_iommu_bank_data *bank; + struct dma_iommu_mapping*mapping; /* For mtk_iommu_v1.c */ struct regmap *pericfg; @@ -225,7 +237,7 @@ struct mtk_iommu_domain { struct io_pgtable_cfg cfg; struct io_pgtable_ops *iop; - struct mtk_iommu_data *data; + struct mtk_iommu_bank_data *bank; struct iommu_domain domain; struct mutexmutex; /* Protect "data" in this structure */ @@ -311,20 +323,24 @@ static struct mtk_iommu_domain *to_mtk_domain(struct iommu_domain *dom) static void mtk_iommu_tlb_flush_all(struct mtk_iommu_data *data) { - void __iomem *base = data->base; + /* Tlb flush all always is in bank0. */ + struct mtk_iommu_bank_data *bank = &data->bank[0]; + void __iomem *base = bank->base; unsigned long flags; - spin_lock_irqsave(&data->tlb_lock, flags); + spin_lock_irqsave(&bank->tlb_lock, flags); writel_relaxed(F_INVLD_EN1 | F_INVLD_EN0, base + data->plat_data->inv_sel_reg); writel_relaxed(F_ALL_INVLD, base + REG_MMU_INVALIDATE); wmb(); /* Make sure the tlb flush all done */ - spin_unlock_irqrestore(&data->tlb_lock, flags); + spin_unlock_irqrestore(&bank->tlb_lock, flags); } static void mtk_iommu_tlb_flush_range_sync(unsigned long iova, size_t size, - struct mtk_iommu_data *data) + struct mtk_iommu_bank_data *bank) { - struct list_head *head = data->hw_list; + struct list_head *head = bank->parent_data->hw_list; + struct mtk_iommu_bank_data *curbank; + struct mtk_iommu_data *data; bool check_pm_status; unsigned long flags; void __iomem *base; @@ -354,9 +370,10 @@ static void mtk_iommu_tlb_flush_range_sync(unsigned long iova, size_t size, continue; } - base = data->base; + curbank = &data->bank[bank->id]; + base = curbank->base; - spin_lock_irqsave(&data->tlb_lock, flags); + spin_lock_irqsave(&curbank->tlb_lock, flags); writel_relaxed(F_INVLD_EN1 | F_INVLD_EN0, base + data->plat_data->inv_sel_reg); @@ -371,7 +388,7 @@ static void mtk
[PATCH v7 28/36] iommu/mediatek-v1: Just rename mtk_iommu to mtk_iommu_v1
No functional change. Just rename this for readable. Differentiate this from mtk_iommu.c Signed-off-by: Yong Wu Reviewed-by: AngeloGioacchino Del Regno --- drivers/iommu/mtk_iommu_v1.c | 211 +-- 1 file changed, 103 insertions(+), 108 deletions(-) diff --git a/drivers/iommu/mtk_iommu_v1.c b/drivers/iommu/mtk_iommu_v1.c index 3d1f0897d1cc..62669e60991f 100644 --- a/drivers/iommu/mtk_iommu_v1.c +++ b/drivers/iommu/mtk_iommu_v1.c @@ -85,53 +85,53 @@ */ #define M2701_IOMMU_PGT_SIZE SZ_4M -struct mtk_iommu_suspend_reg { +struct mtk_iommu_v1_suspend_reg { u32 standard_axi_mode; u32 dcm_dis; u32 ctrl_reg; u32 int_control0; }; -struct mtk_iommu_data { +struct mtk_iommu_v1_data { void __iomem*base; int irq; struct device *dev; struct clk *bclk; phys_addr_t protect_base; /* protect memory base */ - struct mtk_iommu_domain *m4u_dom; + struct mtk_iommu_v1_domain *m4u_dom; struct iommu_device iommu; struct dma_iommu_mapping*mapping; struct mtk_smi_larb_iommu larb_imu[MTK_LARB_NR_MAX]; - struct mtk_iommu_suspend_regreg; + struct mtk_iommu_v1_suspend_reg reg; }; -struct mtk_iommu_domain { +struct mtk_iommu_v1_domain { spinlock_t pgtlock; /* lock for page table */ struct iommu_domain domain; u32 *pgt_va; dma_addr_t pgt_pa; - struct mtk_iommu_data *data; + struct mtk_iommu_v1_data*data; }; -static int mtk_iommu_bind(struct device *dev) +static int mtk_iommu_v1_bind(struct device *dev) { - struct mtk_iommu_data *data = dev_get_drvdata(dev); + struct mtk_iommu_v1_data *data = dev_get_drvdata(dev); return component_bind_all(dev, &data->larb_imu); } -static void mtk_iommu_unbind(struct device *dev) +static void mtk_iommu_v1_unbind(struct device *dev) { - struct mtk_iommu_data *data = dev_get_drvdata(dev); + struct mtk_iommu_v1_data *data = dev_get_drvdata(dev); component_unbind_all(dev, &data->larb_imu); } -static struct mtk_iommu_domain *to_mtk_domain(struct iommu_domain *dom) +static struct mtk_iommu_v1_domain *to_mtk_domain(struct iommu_domain *dom) { - return container_of(dom, struct mtk_iommu_domain, domain); + return container_of(dom, struct mtk_iommu_v1_domain, domain); } static const int mt2701_m4u_in_larb[] = { @@ -157,7 +157,7 @@ static inline int mt2701_m4u_to_port(int id) return id - mt2701_m4u_in_larb[larb]; } -static void mtk_iommu_tlb_flush_all(struct mtk_iommu_data *data) +static void mtk_iommu_v1_tlb_flush_all(struct mtk_iommu_v1_data *data) { writel_relaxed(F_INVLD_EN1 | F_INVLD_EN0, data->base + REG_MMU_INV_SEL); @@ -165,8 +165,8 @@ static void mtk_iommu_tlb_flush_all(struct mtk_iommu_data *data) wmb(); /* Make sure the tlb flush all done */ } -static void mtk_iommu_tlb_flush_range(struct mtk_iommu_data *data, - unsigned long iova, size_t size) +static void mtk_iommu_v1_tlb_flush_range(struct mtk_iommu_v1_data *data, +unsigned long iova, size_t size) { int ret; u32 tmp; @@ -184,16 +184,16 @@ static void mtk_iommu_tlb_flush_range(struct mtk_iommu_data *data, if (ret) { dev_warn(data->dev, "Partial TLB flush timed out, falling back to full flush\n"); - mtk_iommu_tlb_flush_all(data); + mtk_iommu_v1_tlb_flush_all(data); } /* Clear the CPE status */ writel_relaxed(0, data->base + REG_MMU_CPE_DONE); } -static irqreturn_t mtk_iommu_isr(int irq, void *dev_id) +static irqreturn_t mtk_iommu_v1_isr(int irq, void *dev_id) { - struct mtk_iommu_data *data = dev_id; - struct mtk_iommu_domain *dom = data->m4u_dom; + struct mtk_iommu_v1_data *data = dev_id; + struct mtk_iommu_v1_domain *dom = data->m4u_dom; u32 int_state, regval, fault_iova, fault_pa; unsigned int fault_larb, fault_port; @@ -223,13 +223,13 @@ static irqreturn_t mtk_iommu_isr(int irq, void *dev_id) regval |= F_INT_CLR_BIT; writel_relaxed(regval, data->base + REG_MMU_INT_CONTROL); - mtk_iommu_tlb_flush_all(data); + mtk_iommu_v1_tlb_flush_all(data); return IRQ_HANDLED; } -static void mtk_iommu_config(struct mtk_iommu_data *data, -struct device *dev, bool enable) +static void mtk_iommu_v1_config(struct mtk_iommu_v1_data *data, + struct device *dev, boo
[PATCH v7 27/36] iommu/mediatek: Remove mtk_iommu.h
Currently there is a suspend structure in the header file. It's no need to keep a header file only for this. Move these into the c file and rm this header file. Signed-off-by: Yong Wu Reviewed-by: AngeloGioacchino Del Regno --- drivers/iommu/mtk_iommu.c| 14 +- drivers/iommu/mtk_iommu.h| 32 drivers/iommu/mtk_iommu_v1.c | 11 --- 3 files changed, 21 insertions(+), 36 deletions(-) delete mode 100644 drivers/iommu/mtk_iommu.h diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c index 7383a5df6021..349640bcbd01 100644 --- a/drivers/iommu/mtk_iommu.c +++ b/drivers/iommu/mtk_iommu.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -30,7 +31,7 @@ #include #include -#include "mtk_iommu.h" +#include #define REG_MMU_PT_BASE_ADDR 0x000 #define MMU_PT_ADDR_MASK GENMASK(31, 7) @@ -166,6 +167,17 @@ struct mtk_iommu_iova_region { unsigned long long size; }; +struct mtk_iommu_suspend_reg { + u32 misc_ctrl; + u32 dcm_dis; + u32 ctrl_reg; + u32 int_control0; + u32 int_main_control; + u32 ivrp_paddr; + u32 vld_pa_rng; + u32 wr_len_ctrl; +}; + struct mtk_iommu_plat_data { enum mtk_iommu_plat m4u_plat; u32 flags; diff --git a/drivers/iommu/mtk_iommu.h b/drivers/iommu/mtk_iommu.h deleted file mode 100644 index 305243e18aa9.. --- a/drivers/iommu/mtk_iommu.h +++ /dev/null @@ -1,32 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * Copyright (c) 2015-2016 MediaTek Inc. - * Author: Honghui Zhang - */ - -#ifndef _MTK_IOMMU_H_ -#define _MTK_IOMMU_H_ - -#include -#include -#include -#include -#include -#include -#include - -struct mtk_iommu_suspend_reg { - union { - u32 standard_axi_mode;/* v1 */ - u32 misc_ctrl;/* v2 */ - }; - u32 dcm_dis; - u32 ctrl_reg; - u32 int_control0; - u32 int_main_control; - u32 ivrp_paddr; - u32 vld_pa_rng; - u32 wr_len_ctrl; -}; - -#endif diff --git a/drivers/iommu/mtk_iommu_v1.c b/drivers/iommu/mtk_iommu_v1.c index 6d1c09c91e1f..3d1f0897d1cc 100644 --- a/drivers/iommu/mtk_iommu_v1.c +++ b/drivers/iommu/mtk_iommu_v1.c @@ -7,7 +7,6 @@ * * Based on driver/iommu/mtk_iommu.c */ -#include #include #include #include @@ -28,10 +27,9 @@ #include #include #include -#include +#include #include #include -#include "mtk_iommu.h" #define REG_MMU_PT_BASE_ADDR 0x000 @@ -87,6 +85,13 @@ */ #define M2701_IOMMU_PGT_SIZE SZ_4M +struct mtk_iommu_suspend_reg { + u32 standard_axi_mode; + u32 dcm_dis; + u32 ctrl_reg; + u32 int_control0; +}; + struct mtk_iommu_data { void __iomem*base; int irq; -- 2.18.0 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH v7 26/36] iommu/mediatek: Separate mtk_iommu_data for v1 and v2
Prepare for adding the structure "mtk_iommu_bank_data". No functional change. The mtk_iommu_domain in v1 and v2 are different, we could not add current data as bank[0] in v1 simplistically. Currently we have no plan to add new SoC for v1, in order to avoid affect v1 when we add many new features for v2, I totally separate v1 and v2 in this patch, there are many structures only for v2. Signed-off-by: Yong Wu Reviewed-by: AngeloGioacchino Del Regno --- drivers/iommu/mtk_iommu.c| 82 +--- drivers/iommu/mtk_iommu.h| 81 --- drivers/iommu/mtk_iommu_v1.c | 29 + 3 files changed, 106 insertions(+), 86 deletions(-) diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c index ac1681858af8..7383a5df6021 100644 --- a/drivers/iommu/mtk_iommu.c +++ b/drivers/iommu/mtk_iommu.c @@ -146,6 +146,69 @@ #define MTK_INVALID_LARBID MTK_LARB_NR_MAX +#define MTK_LARB_COM_MAX 8 +#define MTK_LARB_SUBCOM_MAX8 + +#define MTK_IOMMU_GROUP_MAX8 + +enum mtk_iommu_plat { + M4U_MT2712, + M4U_MT6779, + M4U_MT8167, + M4U_MT8173, + M4U_MT8183, + M4U_MT8192, + M4U_MT8195, +}; + +struct mtk_iommu_iova_region { + dma_addr_t iova_base; + unsigned long long size; +}; + +struct mtk_iommu_plat_data { + enum mtk_iommu_plat m4u_plat; + u32 flags; + u32 inv_sel_reg; + + char*pericfg_comp_str; + struct list_head*hw_list; + unsigned intiova_region_nr; + const struct mtk_iommu_iova_region *iova_region; + unsigned char larbid_remap[MTK_LARB_COM_MAX][MTK_LARB_SUBCOM_MAX]; +}; + +struct mtk_iommu_data { + void __iomem*base; + int irq; + struct device *dev; + struct clk *bclk; + phys_addr_t protect_base; /* protect memory base */ + struct mtk_iommu_suspend_regreg; + struct mtk_iommu_domain *m4u_dom; + struct iommu_group *m4u_group[MTK_IOMMU_GROUP_MAX]; + boolenable_4GB; + spinlock_t tlb_lock; /* lock for tlb range flush */ + + struct iommu_device iommu; + const struct mtk_iommu_plat_data *plat_data; + struct device *smicomm_dev; + + struct dma_iommu_mapping*mapping; /* For mtk_iommu_v1.c */ + struct regmap *pericfg; + + struct mutexmutex; /* Protect m4u_group/m4u_dom above */ + + /* +* In the sharing pgtable case, list data->list to the global list like m4ulist. +* In the non-sharing pgtable case, list data->list to the itself hw_list_head. +*/ + struct list_head*hw_list; + struct list_headhw_list_head; + struct list_headlist; + struct mtk_smi_larb_iommu larb_imu[MTK_LARB_NR_MAX]; +}; + struct mtk_iommu_domain { struct io_pgtable_cfg cfg; struct io_pgtable_ops *iop; @@ -156,6 +219,20 @@ struct mtk_iommu_domain { struct mutexmutex; /* Protect "data" in this structure */ }; +static int mtk_iommu_bind(struct device *dev) +{ + struct mtk_iommu_data *data = dev_get_drvdata(dev); + + return component_bind_all(dev, &data->larb_imu); +} + +static void mtk_iommu_unbind(struct device *dev) +{ + struct mtk_iommu_data *data = dev_get_drvdata(dev); + + component_unbind_all(dev, &data->larb_imu); +} + static const struct iommu_ops mtk_iommu_ops; static int mtk_iommu_hw_init(const struct mtk_iommu_data *data); @@ -193,11 +270,6 @@ static LIST_HEAD(m4ulist); /* List all the M4U HWs */ #define for_each_m4u(data, head) list_for_each_entry(data, head, list) -struct mtk_iommu_iova_region { - dma_addr_t iova_base; - unsigned long long size; -}; - static const struct mtk_iommu_iova_region single_domain[] = { {.iova_base = 0,.size = SZ_4G}, }; diff --git a/drivers/iommu/mtk_iommu.h b/drivers/iommu/mtk_iommu.h index f2ee11cd254a..305243e18aa9 100644 --- a/drivers/iommu/mtk_iommu.h +++ b/drivers/iommu/mtk_iommu.h @@ -7,23 +7,14 @@ #ifndef _MTK_IOMMU_H_ #define _MTK_IOMMU_H_ -#include -#include #include #include #include #include -#include #include -#include #include #include -#define MTK_LARB_COM_MAX 8 -#define MTK_LARB_SUBCOM_MAX8 - -#define MTK_IOMMU_GROUP_MAX8 - struct mtk_iommu_suspend_reg { union { u32 standard_axi_mode;/* v1 */ @@ -38,76 +29,4 @@ struct mtk_iommu_suspend_reg { u32 wr_len_ctrl; }; -enum mt
[PATCH v7 25/36] iommu/mediatek: Just move code position in hw_init
No functional change too, prepare for mt8195 IOMMU support bank functions. Some global control settings are in bank0 while the other banks have their bank independent setting. Here only move the global control settings and the independent registers together. Signed-off-by: Yong Wu Reviewed-by: AngeloGioacchino Del Regno --- drivers/iommu/mtk_iommu.c | 48 +++ 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c index de448d056135..ac1681858af8 100644 --- a/drivers/iommu/mtk_iommu.c +++ b/drivers/iommu/mtk_iommu.c @@ -803,30 +803,6 @@ static int mtk_iommu_hw_init(const struct mtk_iommu_data *data) } writel_relaxed(regval, data->base + REG_MMU_CTRL_REG); - regval = F_L2_MULIT_HIT_EN | - F_TABLE_WALK_FAULT_INT_EN | - F_PREETCH_FIFO_OVERFLOW_INT_EN | - F_MISS_FIFO_OVERFLOW_INT_EN | - F_PREFETCH_FIFO_ERR_INT_EN | - F_MISS_FIFO_ERR_INT_EN; - writel_relaxed(regval, data->base + REG_MMU_INT_CONTROL0); - - regval = F_INT_TRANSLATION_FAULT | - F_INT_MAIN_MULTI_HIT_FAULT | - F_INT_INVALID_PA_FAULT | - F_INT_ENTRY_REPLACEMENT_FAULT | - F_INT_TLB_MISS_FAULT | - F_INT_MISS_TRANSACTION_FIFO_FAULT | - F_INT_PRETETCH_TRANSATION_FIFO_FAULT; - writel_relaxed(regval, data->base + REG_MMU_INT_MAIN_CONTROL); - - if (MTK_IOMMU_HAS_FLAG(data->plat_data, HAS_LEGACY_IVRP_PADDR)) - regval = (data->protect_base >> 1) | (data->enable_4GB << 31); - else - regval = lower_32_bits(data->protect_base) | -upper_32_bits(data->protect_base); - writel_relaxed(regval, data->base + REG_MMU_IVRP_PADDR); - if (data->enable_4GB && MTK_IOMMU_HAS_FLAG(data->plat_data, HAS_VLD_PA_RNG)) { /* @@ -860,6 +836,30 @@ static int mtk_iommu_hw_init(const struct mtk_iommu_data *data) } writel_relaxed(regval, data->base + REG_MMU_MISC_CTRL); + regval = F_L2_MULIT_HIT_EN | + F_TABLE_WALK_FAULT_INT_EN | + F_PREETCH_FIFO_OVERFLOW_INT_EN | + F_MISS_FIFO_OVERFLOW_INT_EN | + F_PREFETCH_FIFO_ERR_INT_EN | + F_MISS_FIFO_ERR_INT_EN; + writel_relaxed(regval, data->base + REG_MMU_INT_CONTROL0); + + regval = F_INT_TRANSLATION_FAULT | + F_INT_MAIN_MULTI_HIT_FAULT | + F_INT_INVALID_PA_FAULT | + F_INT_ENTRY_REPLACEMENT_FAULT | + F_INT_TLB_MISS_FAULT | + F_INT_MISS_TRANSACTION_FIFO_FAULT | + F_INT_PRETETCH_TRANSATION_FIFO_FAULT; + writel_relaxed(regval, data->base + REG_MMU_INT_MAIN_CONTROL); + + if (MTK_IOMMU_HAS_FLAG(data->plat_data, HAS_LEGACY_IVRP_PADDR)) + regval = (data->protect_base >> 1) | (data->enable_4GB << 31); + else + regval = lower_32_bits(data->protect_base) | +upper_32_bits(data->protect_base); + writel_relaxed(regval, data->base + REG_MMU_IVRP_PADDR); + if (devm_request_irq(data->dev, data->irq, mtk_iommu_isr, 0, dev_name(data->dev), (void *)data)) { writel_relaxed(0, data->base + REG_MMU_PT_BASE_ADDR); -- 2.18.0 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH v7 24/36] iommu/mediatek: Only adjust code about register base
No functional change. Use "base" instead of the data->base. This is avoid to touch too many lines in the next patches. Signed-off-by: Yong Wu Reviewed-by: AngeloGioacchino Del Regno --- drivers/iommu/mtk_iommu.c | 51 +-- 1 file changed, 27 insertions(+), 24 deletions(-) diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c index 47355010502e..de448d056135 100644 --- a/drivers/iommu/mtk_iommu.c +++ b/drivers/iommu/mtk_iommu.c @@ -227,12 +227,12 @@ static struct mtk_iommu_domain *to_mtk_domain(struct iommu_domain *dom) static void mtk_iommu_tlb_flush_all(struct mtk_iommu_data *data) { + void __iomem *base = data->base; unsigned long flags; spin_lock_irqsave(&data->tlb_lock, flags); - writel_relaxed(F_INVLD_EN1 | F_INVLD_EN0, - data->base + data->plat_data->inv_sel_reg); - writel_relaxed(F_ALL_INVLD, data->base + REG_MMU_INVALIDATE); + writel_relaxed(F_INVLD_EN1 | F_INVLD_EN0, base + data->plat_data->inv_sel_reg); + writel_relaxed(F_ALL_INVLD, base + REG_MMU_INVALIDATE); wmb(); /* Make sure the tlb flush all done */ spin_unlock_irqrestore(&data->tlb_lock, flags); } @@ -243,6 +243,7 @@ static void mtk_iommu_tlb_flush_range_sync(unsigned long iova, size_t size, struct list_head *head = data->hw_list; bool check_pm_status; unsigned long flags; + void __iomem *base; int ret; u32 tmp; @@ -269,23 +270,23 @@ static void mtk_iommu_tlb_flush_range_sync(unsigned long iova, size_t size, continue; } + base = data->base; + spin_lock_irqsave(&data->tlb_lock, flags); writel_relaxed(F_INVLD_EN1 | F_INVLD_EN0, - data->base + data->plat_data->inv_sel_reg); + base + data->plat_data->inv_sel_reg); - writel_relaxed(MTK_IOMMU_TLB_ADDR(iova), - data->base + REG_MMU_INVLD_START_A); + writel_relaxed(MTK_IOMMU_TLB_ADDR(iova), base + REG_MMU_INVLD_START_A); writel_relaxed(MTK_IOMMU_TLB_ADDR(iova + size - 1), - data->base + REG_MMU_INVLD_END_A); - writel_relaxed(F_MMU_INV_RANGE, - data->base + REG_MMU_INVALIDATE); + base + REG_MMU_INVLD_END_A); + writel_relaxed(F_MMU_INV_RANGE, base + REG_MMU_INVALIDATE); /* tlb sync */ - ret = readl_poll_timeout_atomic(data->base + REG_MMU_CPE_DONE, + ret = readl_poll_timeout_atomic(base + REG_MMU_CPE_DONE, tmp, tmp != 0, 10, 1000); /* Clear the CPE status */ - writel_relaxed(0, data->base + REG_MMU_CPE_DONE); + writel_relaxed(0, base + REG_MMU_CPE_DONE); spin_unlock_irqrestore(&data->tlb_lock, flags); if (ret) { @@ -305,23 +306,25 @@ static irqreturn_t mtk_iommu_isr(int irq, void *dev_id) struct mtk_iommu_domain *dom = data->m4u_dom; unsigned int fault_larb = MTK_INVALID_LARBID, fault_port = 0, sub_comm = 0; u32 int_state, regval, va34_32, pa34_32; + const struct mtk_iommu_plat_data *plat_data = data->plat_data; + void __iomem *base = data->base; u64 fault_iova, fault_pa; bool layer, write; /* Read error info from registers */ - int_state = readl_relaxed(data->base + REG_MMU_FAULT_ST1); + int_state = readl_relaxed(base + REG_MMU_FAULT_ST1); if (int_state & F_REG_MMU0_FAULT_MASK) { - regval = readl_relaxed(data->base + REG_MMU0_INT_ID); - fault_iova = readl_relaxed(data->base + REG_MMU0_FAULT_VA); - fault_pa = readl_relaxed(data->base + REG_MMU0_INVLD_PA); + regval = readl_relaxed(base + REG_MMU0_INT_ID); + fault_iova = readl_relaxed(base + REG_MMU0_FAULT_VA); + fault_pa = readl_relaxed(base + REG_MMU0_INVLD_PA); } else { - regval = readl_relaxed(data->base + REG_MMU1_INT_ID); - fault_iova = readl_relaxed(data->base + REG_MMU1_FAULT_VA); - fault_pa = readl_relaxed(data->base + REG_MMU1_INVLD_PA); + regval = readl_relaxed(base + REG_MMU1_INT_ID); + fault_iova = readl_relaxed(base + REG_MMU1_FAULT_VA); + fault_pa = readl_relaxed(base + REG_MMU1_INVLD_PA); } layer = fault_iova & F_MMU_FAULT_VA_LAYER_BIT; write = fault_iova & F_MMU_FAULT_VA_WRITE_BIT; - if (MTK_IOMMU_HAS_FLAG(data->plat_data, IOVA_34_EN)) { + if (MTK_IOMMU_HAS_FLAG(plat_data, IOVA_34_EN)) { va34_32 = FIELD_GET(F_MMU_INVAL_VA_34_32_MASK, fault_iova); fault_iova = fault_iova & F_MMU_INVAL_VA_31_12_MASK;
[PATCH v7 23/36] iommu/mediatek: Add mt8195 support
mt8195 has 3 IOMMU, containing 2 MM IOMMUs, one is for vdo, the other is for vpp. and 1 INFRA IOMMU. Signed-off-by: Yong Wu Reviewed-by: AngeloGioacchino Del Regno --- drivers/iommu/mtk_iommu.c | 41 +++ drivers/iommu/mtk_iommu.h | 1 + 2 files changed, 42 insertions(+) diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c index d63fe28c1403..47355010502e 100644 --- a/drivers/iommu/mtk_iommu.c +++ b/drivers/iommu/mtk_iommu.c @@ -1233,6 +1233,44 @@ static const struct mtk_iommu_plat_data mt8192_data = { {0, 14, 16}, {0, 13, 18, 17}}, }; +static const struct mtk_iommu_plat_data mt8195_data_infra = { + .m4u_plat = M4U_MT8195, + .flags= WR_THROT_EN | DCM_DISABLE | STD_AXI_MODE | PM_CLK_AO | + MTK_IOMMU_TYPE_INFRA | IFA_IOMMU_PCIE_SUPPORT, + .pericfg_comp_str = "mediatek,mt8195-pericfg_ao", + .inv_sel_reg = REG_MMU_INV_SEL_GEN2, + .iova_region = single_domain, + .iova_region_nr = ARRAY_SIZE(single_domain), +}; + +static const struct mtk_iommu_plat_data mt8195_data_vdo = { + .m4u_plat = M4U_MT8195, + .flags = HAS_BCLK | HAS_SUB_COMM_2BITS | OUT_ORDER_WR_EN | + WR_THROT_EN | IOVA_34_EN | SHARE_PGTABLE | MTK_IOMMU_TYPE_MM, + .hw_list= &m4ulist, + .inv_sel_reg= REG_MMU_INV_SEL_GEN2, + .iova_region= mt8192_multi_dom, + .iova_region_nr = ARRAY_SIZE(mt8192_multi_dom), + .larbid_remap = {{2, 0}, {21}, {24}, {7}, {19}, {9, 10, 11}, + {13, 17, 15/* 17b */, 25}, {5}}, +}; + +static const struct mtk_iommu_plat_data mt8195_data_vpp = { + .m4u_plat = M4U_MT8195, + .flags = HAS_BCLK | HAS_SUB_COMM_3BITS | OUT_ORDER_WR_EN | + WR_THROT_EN | IOVA_34_EN | SHARE_PGTABLE | MTK_IOMMU_TYPE_MM, + .hw_list= &m4ulist, + .inv_sel_reg= REG_MMU_INV_SEL_GEN2, + .iova_region= mt8192_multi_dom, + .iova_region_nr = ARRAY_SIZE(mt8192_multi_dom), + .larbid_remap = {{1}, {3}, + {22, MTK_INVALID_LARBID, MTK_INVALID_LARBID, MTK_INVALID_LARBID, 23}, + {8}, {20}, {12}, + /* 16: 16a; 29: 16b; 30: CCUtop0; 31: CCUtop1 */ + {14, 16, 29, 26, 30, 31, 18}, + {4, MTK_INVALID_LARBID, MTK_INVALID_LARBID, MTK_INVALID_LARBID, 6}}, +}; + static const struct of_device_id mtk_iommu_of_ids[] = { { .compatible = "mediatek,mt2712-m4u", .data = &mt2712_data}, { .compatible = "mediatek,mt6779-m4u", .data = &mt6779_data}, @@ -1240,6 +1278,9 @@ static const struct of_device_id mtk_iommu_of_ids[] = { { .compatible = "mediatek,mt8173-m4u", .data = &mt8173_data}, { .compatible = "mediatek,mt8183-m4u", .data = &mt8183_data}, { .compatible = "mediatek,mt8192-m4u", .data = &mt8192_data}, + { .compatible = "mediatek,mt8195-iommu-infra", .data = &mt8195_data_infra}, + { .compatible = "mediatek,mt8195-iommu-vdo", .data = &mt8195_data_vdo}, + { .compatible = "mediatek,mt8195-iommu-vpp", .data = &mt8195_data_vpp}, {} }; diff --git a/drivers/iommu/mtk_iommu.h b/drivers/iommu/mtk_iommu.h index 56838fad8c73..f2ee11cd254a 100644 --- a/drivers/iommu/mtk_iommu.h +++ b/drivers/iommu/mtk_iommu.h @@ -46,6 +46,7 @@ enum mtk_iommu_plat { M4U_MT8173, M4U_MT8183, M4U_MT8192, + M4U_MT8195, }; struct mtk_iommu_iova_region; -- 2.18.0 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH v7 21/36] iommu/mediatek: Add infra iommu support
The infra iommu enable bits in mt8195 is in the pericfg register segment, use regmap to update it. If infra iommu master translation fault, It doesn't have the larbid/portid, thus print out the whole register value. Since regmap_update_bits may fail, add return value for mtk_iommu_config. Signed-off-by: Yong Wu Reviewed-by: AngeloGioacchino Del Regno --- drivers/iommu/mtk_iommu.c | 36 +--- drivers/iommu/mtk_iommu.h | 2 ++ 2 files changed, 31 insertions(+), 7 deletions(-) diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c index cd89c109e8c4..ff48506b480c 100644 --- a/drivers/iommu/mtk_iommu.c +++ b/drivers/iommu/mtk_iommu.c @@ -112,6 +112,8 @@ #define MTK_PROTECT_PA_ALIGN 256 +#define PERICFG_IOMMU_10x714 + #define HAS_4GB_MODE BIT(0) /* HW will use the EMI clock if there isn't the "bclk". */ #define HAS_BCLK BIT(1) @@ -343,8 +345,8 @@ static irqreturn_t mtk_iommu_isr(int irq, void *dev_id) write ? IOMMU_FAULT_WRITE : IOMMU_FAULT_READ)) { dev_err_ratelimited( data->dev, - "fault type=0x%x iova=0x%llx pa=0x%llx larb=%d port=%d layer=%d %s\n", - int_state, fault_iova, fault_pa, fault_larb, fault_port, + "fault type=0x%x iova=0x%llx pa=0x%llx master=0x%x(larb=%d port=%d) layer=%d %s\n", + int_state, fault_iova, fault_pa, regval, fault_larb, fault_port, layer, write ? "write" : "read"); } @@ -388,14 +390,15 @@ static int mtk_iommu_get_domain_id(struct device *dev, return -EINVAL; } -static void mtk_iommu_config(struct mtk_iommu_data *data, struct device *dev, -bool enable, unsigned int domid) +static int mtk_iommu_config(struct mtk_iommu_data *data, struct device *dev, + bool enable, unsigned int domid) { struct mtk_smi_larb_iommu*larb_mmu; unsigned int larbid, portid; struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev); const struct mtk_iommu_iova_region *region; - int i; + u32 peri_mmuen, peri_mmuen_msk; + int i, ret = 0; for (i = 0; i < fwspec->num_ids; ++i) { larbid = MTK_M4U_TO_LARB(fwspec->ids[i]); @@ -415,8 +418,19 @@ static void mtk_iommu_config(struct mtk_iommu_data *data, struct device *dev, larb_mmu->mmu |= MTK_SMI_MMU_EN(portid); else larb_mmu->mmu &= ~MTK_SMI_MMU_EN(portid); + } else if (MTK_IOMMU_IS_TYPE(data->plat_data, MTK_IOMMU_TYPE_INFRA)) { + peri_mmuen_msk = BIT(portid); + peri_mmuen = enable ? peri_mmuen_msk : 0; + + ret = regmap_update_bits(data->pericfg, PERICFG_IOMMU_1, +peri_mmuen_msk, peri_mmuen); + if (ret) + dev_err(dev, "%s iommu(%s) inframaster 0x%x fail(%d).\n", + enable ? "enable" : "disable", + dev_name(data->dev), peri_mmuen_msk, ret); } } + return ret; } static int mtk_iommu_domain_finalise(struct mtk_iommu_domain *dom, @@ -531,8 +545,7 @@ static int mtk_iommu_attach_device(struct iommu_domain *domain, } mutex_unlock(&data->mutex); - mtk_iommu_config(data, dev, true, domid); - return 0; + return mtk_iommu_config(data, dev, true, domid); err_unlock: mutex_unlock(&data->mutex); @@ -997,6 +1010,15 @@ static int mtk_iommu_probe(struct platform_device *pdev) dev_err(dev, "mm dts parse fail(%d).", ret); goto out_runtime_disable; } + } else if (MTK_IOMMU_IS_TYPE(data->plat_data, MTK_IOMMU_TYPE_INFRA) && + data->plat_data->pericfg_comp_str) { + infracfg = syscon_regmap_lookup_by_compatible(data->plat_data->pericfg_comp_str); + if (IS_ERR(infracfg)) { + ret = PTR_ERR(infracfg); + goto out_runtime_disable; + } + + data->pericfg = infracfg; } platform_set_drvdata(pdev, data); diff --git a/drivers/iommu/mtk_iommu.h b/drivers/iommu/mtk_iommu.h index f41e32252056..56838fad8c73 100644 --- a/drivers/iommu/mtk_iommu.h +++ b/drivers/iommu/mtk_iommu.h @@ -55,6 +55,7 @@ struct mtk_iommu_plat_data { u32 flags; u32 inv_sel_reg; + char*pericfg_comp_str; struct list_head*hw_list; unsigned intiova_region_nr;
[PATCH v7 22/36] iommu/mediatek: Add PCIe support
Currently the code for of_iommu_configure_dev_id is like this: static int of_iommu_configure_dev_id(struct device_node *master_np, struct device *dev, const u32 *id) { struct of_phandle_args iommu_spec = { .args_count = 1 }; err = of_map_id(master_np, *id, "iommu-map", "iommu-map-mask", &iommu_spec.np, iommu_spec.args); ... } It supports only one id output. BUT our PCIe HW has two ID(one is for writing, the other is for reading). I'm not sure if we should change of_map_id to support output MAX_PHANDLE_ARGS. Here add the solution in ourselve drivers. If it's pcie case, enable one more bit. Not all infra iommu support PCIe, thus add a PCIe support flag here. Signed-off-by: Yong Wu Reviewed-by: AngeloGioacchino Del Regno --- drivers/iommu/mtk_iommu.c | 21 - 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c index ff48506b480c..d63fe28c1403 100644 --- a/drivers/iommu/mtk_iommu.c +++ b/drivers/iommu/mtk_iommu.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -134,6 +135,7 @@ #define MTK_IOMMU_TYPE_MASK(0x3 << 13) /* PM and clock always on. e.g. infra iommu */ #define PM_CLK_AO BIT(15) +#define IFA_IOMMU_PCIE_SUPPORT BIT(16) #define MTK_IOMMU_HAS_FLAG_MASK(pdata, _x, mask) \ pdata)->flags) & (mask)) == (_x)) @@ -420,8 +422,11 @@ static int mtk_iommu_config(struct mtk_iommu_data *data, struct device *dev, larb_mmu->mmu &= ~MTK_SMI_MMU_EN(portid); } else if (MTK_IOMMU_IS_TYPE(data->plat_data, MTK_IOMMU_TYPE_INFRA)) { peri_mmuen_msk = BIT(portid); - peri_mmuen = enable ? peri_mmuen_msk : 0; + /* PCI dev has only one output id, enable the next writing bit for PCIe */ + if (dev_is_pci(dev)) + peri_mmuen_msk |= BIT(portid + 1); + peri_mmuen = enable ? peri_mmuen_msk : 0; ret = regmap_update_bits(data->pericfg, PERICFG_IOMMU_1, peri_mmuen_msk, peri_mmuen); if (ret) @@ -1054,6 +1059,15 @@ static int mtk_iommu_probe(struct platform_device *pdev) ret = component_master_add_with_match(dev, &mtk_iommu_com_ops, match); if (ret) goto out_bus_set_null; + } else if (MTK_IOMMU_IS_TYPE(data->plat_data, MTK_IOMMU_TYPE_INFRA) && + MTK_IOMMU_HAS_FLAG(data->plat_data, IFA_IOMMU_PCIE_SUPPORT)) { +#ifdef CONFIG_PCI + if (!iommu_present(&pci_bus_type)) { + ret = bus_set_iommu(&pci_bus_type, &mtk_iommu_ops); + if (ret) /* PCIe fail don't affect platform_bus. */ + goto out_list_del; + } +#endif } return ret; @@ -1084,6 +1098,11 @@ static int mtk_iommu_remove(struct platform_device *pdev) 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); + } else if (MTK_IOMMU_IS_TYPE(data->plat_data, MTK_IOMMU_TYPE_INFRA) && + MTK_IOMMU_HAS_FLAG(data->plat_data, IFA_IOMMU_PCIE_SUPPORT)) { +#ifdef CONFIG_PCI + bus_set_iommu(&pci_bus_type, NULL); +#endif } pm_runtime_disable(&pdev->dev); devm_free_irq(&pdev->dev, data->irq, data); -- 2.18.0 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH v7 20/36] iommu/mediatek: Add a PM_CLK_AO flag for infra iommu
The power/clock of infra iommu is always on, and it doesn't have the device link with the master devices, then the infra iommu device's PM status is not active, thus we add A PM_CLK_AO flag for infra iommu. The tlb operation is a bit not clear here, there are 2 special cases. Comment them in the code. Signed-off-by: Yong Wu Reviewed-by: AngeloGioacchino Del Regno --- drivers/iommu/mtk_iommu.c | 29 ++--- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c index 0121d71c315f..cd89c109e8c4 100644 --- a/drivers/iommu/mtk_iommu.c +++ b/drivers/iommu/mtk_iommu.c @@ -130,6 +130,8 @@ #define MTK_IOMMU_TYPE_MM (0x0 << 13) #define MTK_IOMMU_TYPE_INFRA (0x1 << 13) #define MTK_IOMMU_TYPE_MASK(0x3 << 13) +/* PM and clock always on. e.g. infra iommu */ +#define PM_CLK_AO BIT(15) #define MTK_IOMMU_HAS_FLAG_MASK(pdata, _x, mask) \ pdata)->flags) & (mask)) == (_x)) @@ -235,13 +237,33 @@ static void mtk_iommu_tlb_flush_range_sync(unsigned long iova, size_t size, struct mtk_iommu_data *data) { struct list_head *head = data->hw_list; + bool check_pm_status; unsigned long flags; int ret; u32 tmp; for_each_m4u(data, head) { - if (pm_runtime_get_if_in_use(data->dev) <= 0) - continue; + /* +* To avoid resume the iommu device frequently when the iommu device +* is not active, it doesn't always call pm_runtime_get here, then tlb +* flush depends on the tlb flush all in the runtime resume. +* +* There are 2 special cases: +* +* Case1: The iommu dev doesn't have power domain but has bclk. This case +* should also avoid the tlb flush while the dev is not active to mute +* the tlb timeout log. like mt8173. +* +* Case2: The power/clock of infra iommu is always on, and it doesn't +* have the device link with the master devices. This case should avoid +* the PM status check. +*/ + check_pm_status = !MTK_IOMMU_HAS_FLAG(data->plat_data, PM_CLK_AO); + + if (check_pm_status) { + if (pm_runtime_get_if_in_use(data->dev) <= 0) + continue; + } spin_lock_irqsave(&data->tlb_lock, flags); writel_relaxed(F_INVLD_EN1 | F_INVLD_EN0, @@ -268,7 +290,8 @@ static void mtk_iommu_tlb_flush_range_sync(unsigned long iova, size_t size, mtk_iommu_tlb_flush_all(data); } - pm_runtime_put(data->dev); + if (check_pm_status) + pm_runtime_put(data->dev); } } -- 2.18.0 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH v7 19/36] iommu/mediatek: Allow IOMMU_DOMAIN_UNMANAGED for PCIe VFIO
Allow the type IOMMU_DOMAIN_UNMANAGED since vfio_iommu_type1.c always call iommu_domain_alloc. The PCIe EP works ok when going through vfio. Signed-off-by: Yong Wu Reviewed-by: AngeloGioacchino Del Regno --- drivers/iommu/mtk_iommu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c index bcdc932cd473..0121d71c315f 100644 --- a/drivers/iommu/mtk_iommu.c +++ b/drivers/iommu/mtk_iommu.c @@ -446,7 +446,7 @@ static struct iommu_domain *mtk_iommu_domain_alloc(unsigned type) { struct mtk_iommu_domain *dom; - if (type != IOMMU_DOMAIN_DMA) + if (type != IOMMU_DOMAIN_DMA && type != IOMMU_DOMAIN_UNMANAGED) return NULL; dom = kzalloc(sizeof(*dom), GFP_KERNEL); -- 2.18.0 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH v7 18/36] iommu/mediatek: Adjust device link when it is sub-common
For MM IOMMU, We always add device link between smi-common and IOMMU HW. In mt8195, we add smi-sub-common. Thus, if the node is sub-common, we still need find again to get smi-common, then do device link. Signed-off-by: Yong Wu Reviewed-by: AngeloGioacchino Del Regno --- drivers/iommu/mtk_iommu.c | 18 ++ 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c index 7d4bc562b2a3..bcdc932cd473 100644 --- a/drivers/iommu/mtk_iommu.c +++ b/drivers/iommu/mtk_iommu.c @@ -834,7 +834,7 @@ static const struct component_master_ops mtk_iommu_com_ops = { static int mtk_iommu_mm_dts_parse(struct device *dev, struct component_match **match, struct mtk_iommu_data *data) { - struct device_node *larbnode, *smicomm_node; + struct device_node *larbnode, *smicomm_node, *smi_subcomm_node; struct platform_device *plarbdev; struct device_link *link; int i, larb_nr, ret; @@ -874,11 +874,21 @@ static int mtk_iommu_mm_dts_parse(struct device *dev, struct component_match **m component_compare_of, larbnode); } - /* Get smi-common dev from the last larb. */ - smicomm_node = of_parse_phandle(larbnode, "mediatek,smi", 0); - if (!smicomm_node) + /* Get smi-(sub)-common dev from the last larb. */ + smi_subcomm_node = of_parse_phandle(larbnode, "mediatek,smi", 0); + if (!smi_subcomm_node) return -EINVAL; + /* +* It may have two level smi-common. the node is smi-sub-common if it +* has a new mediatek,smi property. otherwise it is smi-commmon. +*/ + smicomm_node = of_parse_phandle(smi_subcomm_node, "mediatek,smi", 0); + if (smicomm_node) + of_node_put(smi_subcomm_node); + else + smicomm_node = smi_subcomm_node; + plarbdev = of_find_device_by_node(smicomm_node); of_node_put(smicomm_node); data->smicomm_dev = &plarbdev->dev; -- 2.18.0 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH v7 17/36] 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 Reviewed-by: AngeloGioacchino Del Regno --- drivers/iommu/mtk_iommu.c | 213 ++ 1 file changed, 122 insertions(+), 91 deletions(-) diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c index b5b95d9a372e..7d4bc562b2a3 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) +#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 = dev_id; struct mtk_iommu_domain *dom = data->m4u_dom; - unsigned int fault_larb, fault_port, sub_comm = 0; + unsigned int fault_larb = MTK_INVALID_LARBID, fault_port = 0, sub_comm = 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_id) pa34_32 = FIELD_GET(F_MMU_INVAL_PA_34_32_MASK, fault_iova); fault_pa |= (u64)pa34_32 << 32; - fault_port = F_MMU_INT_ID_PORT_ID(regval); - if (MTK_IOMMU_HAS_FLAG(data->plat_data, HAS_SUB_COMM_2BITS)) { - fault_larb = F_MMU_INT_ID_COMM_ID(regval); - sub_comm = F_MMU_INT_ID_SUB_COMM_ID(regval); - } else if (MTK_IOMMU_HAS_FLAG(data->plat_data, HAS_SUB_COMM_3BITS)) { - fault_larb = F_MMU_INT_ID_COMM_ID_EXT(regval); - sub_comm = F_MMU_INT_ID_SUB_COMM_ID_EXT(regval); - } else { - fault_larb = F_MMU_INT_ID_LARB_ID(regval); + if (MTK_IOMMU_IS_TYPE(data->plat_data, MTK_IOMMU_TYPE_MM)) { + fault_port = F_MMU_INT_ID_PORT_ID(regval); + if (MTK_IOMMU_HAS_FLAG(data->plat_data, HAS_SUB_COMM_2BITS)) { + fault_larb = F_MMU_INT_ID_COMM_ID(regval); + sub_comm = F_MMU_INT_ID_SUB_COMM_ID(regval); + } else if (MTK_IOMMU_HAS_FLAG(data->plat_data, HAS_SUB_COMM_3BITS)) { + fault_larb = F_MMU_INT_ID_COMM_ID_EXT(regval); + sub_comm = F_MMU_INT_ID_SUB_COMM_ID_EXT(regval); + } else { + fault_larb = F_MMU_INT_ID_LARB_ID(regval); + } + fault_larb = data->plat_data->larbid_remap[fault_larb][sub_comm]; } - fault_larb = data->plat_data->larbid_remap[fault_larb][sub_comm]; 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 *data, struct device *dev, larbid = MTK_M4U_TO_LARB(fwspec->ids[i]); portid = MTK_M4U_TO_PORT(fwspec->ids[i]); - larb_mmu = &data->larb_imu[larbid]; + if (MTK_IOMMU_IS_TYPE(data->plat_data, MTK_IOMMU_TYPE_MM)) { + larb_mmu = &data->larb_imu[larbid]; - region = data->plat_data->iova_region + domid; - larb_mmu->bank[portid] = upper_32_bits(region->iova_base); + region = data->plat_data->iova_region + domid; + larb_mmu->bank[portid] = upper_32_bits(region->iova_base); - 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]); - if (enable) - larb_mmu->mmu |= MTK_SMI_MMU_EN(portid); - else - larb_mmu->mmu &= ~MTK_SMI_MMU_EN(portid); + if (enable) + larb_mmu->mmu |= MTK_SMI_MMU_EN(portid); + else + larb_mmu->mmu &= ~MTK_SMI_MMU_EN(portid); + } } } @@ -593,6 +599,9 @@ static struct iommu_device *mtk_iommu_probe_device(struct device *dev)
[PATCH v7 16/36] iommu/mediatek: Add IOMMU_TYPE flag
Add IOMMU_TYPE definition. In the mt8195, we have another IOMMU_TYPE: infra iommu, also there will be another APU_IOMMU, thus, use 2bits for the IOMMU_TYPE. Signed-off-by: Yong Wu Reviewed-by: AngeloGioacchino Del Regno --- drivers/iommu/mtk_iommu.c | 12 ++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c index 937478cd8966..b5b95d9a372e 100644 --- a/drivers/iommu/mtk_iommu.c +++ b/drivers/iommu/mtk_iommu.c @@ -126,9 +126,17 @@ #define SHARE_PGTABLE BIT(10) /* 2 HW share pgtable */ #define DCM_DISABLEBIT(11) #define STD_AXI_MODE BIT(12) /* For non MM iommu */ +/* 2 bits: iommu type */ +#define MTK_IOMMU_TYPE_MM (0x0 << 13) +#define MTK_IOMMU_TYPE_INFRA (0x1 << 13) +#define MTK_IOMMU_TYPE_MASK(0x3 << 13) -#define MTK_IOMMU_HAS_FLAG(pdata, _x) \ - pdata)->flags) & (_x)) == (_x)) +#define MTK_IOMMU_HAS_FLAG_MASK(pdata, _x, mask) \ + pdata)->flags) & (mask)) == (_x)) + +#define MTK_IOMMU_HAS_FLAG(pdata, _x) MTK_IOMMU_HAS_FLAG_MASK(pdata, _x, _x) +#define MTK_IOMMU_IS_TYPE(pdata, _x) MTK_IOMMU_HAS_FLAG_MASK(pdata, _x,\ + MTK_IOMMU_TYPE_MASK) struct mtk_iommu_domain { struct io_pgtable_cfg cfg; -- 2.18.0 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH v7 15/36] iommu/mediatek: Add SUB_COMMON_3BITS flag
In prevous SoC, the sub common id occupy 2 bits. the mt8195's sub common id has 3bits. Add a new flag for this. and rename the previous flag to _2BITS. For readable, I put these two flags together, then move the other flags. no functional change. Signed-off-by: Yong Wu Reviewed-by: AngeloGioacchino Del Regno --- drivers/iommu/mtk_iommu.c | 26 -- drivers/iommu/mtk_iommu.h | 2 +- 2 files changed, 17 insertions(+), 11 deletions(-) diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c index d9689e041336..937478cd8966 100644 --- a/drivers/iommu/mtk_iommu.c +++ b/drivers/iommu/mtk_iommu.c @@ -105,6 +105,8 @@ #define REG_MMU1_INT_ID0x154 #define F_MMU_INT_ID_COMM_ID(a)(((a) >> 9) & 0x7) #define F_MMU_INT_ID_SUB_COMM_ID(a)(((a) >> 7) & 0x3) +#define F_MMU_INT_ID_COMM_ID_EXT(a)(((a) >> 10) & 0x7) +#define F_MMU_INT_ID_SUB_COMM_ID_EXT(a)(((a) >> 7) & 0x7) #define F_MMU_INT_ID_LARB_ID(a)(((a) >> 7) & 0x7) #define F_MMU_INT_ID_PORT_ID(a)(((a) >> 2) & 0x1f) @@ -116,13 +118,14 @@ #define HAS_VLD_PA_RNG BIT(2) #define RESET_AXI BIT(3) #define OUT_ORDER_WR_ENBIT(4) -#define HAS_SUB_COMM BIT(5) -#define WR_THROT_ENBIT(6) -#define HAS_LEGACY_IVRP_PADDR BIT(7) -#define IOVA_34_EN BIT(8) -#define SHARE_PGTABLE BIT(9) /* 2 HW share pgtable */ -#define DCM_DISABLEBIT(10) -#define STD_AXI_MODE BIT(11) /* For non MM iommu */ +#define HAS_SUB_COMM_2BITS BIT(5) +#define HAS_SUB_COMM_3BITS BIT(6) +#define WR_THROT_ENBIT(7) +#define HAS_LEGACY_IVRP_PADDR BIT(8) +#define IOVA_34_EN BIT(9) +#define SHARE_PGTABLE BIT(10) /* 2 HW share pgtable */ +#define DCM_DISABLEBIT(11) +#define STD_AXI_MODE BIT(12) /* For non MM iommu */ #define MTK_IOMMU_HAS_FLAG(pdata, _x) \ pdata)->flags) & (_x)) == (_x)) @@ -290,9 +293,12 @@ static irqreturn_t mtk_iommu_isr(int irq, void *dev_id) fault_pa |= (u64)pa34_32 << 32; fault_port = F_MMU_INT_ID_PORT_ID(regval); - if (MTK_IOMMU_HAS_FLAG(data->plat_data, HAS_SUB_COMM)) { + if (MTK_IOMMU_HAS_FLAG(data->plat_data, HAS_SUB_COMM_2BITS)) { fault_larb = F_MMU_INT_ID_COMM_ID(regval); sub_comm = F_MMU_INT_ID_SUB_COMM_ID(regval); + } else if (MTK_IOMMU_HAS_FLAG(data->plat_data, HAS_SUB_COMM_3BITS)) { + fault_larb = F_MMU_INT_ID_COMM_ID_EXT(regval); + sub_comm = F_MMU_INT_ID_SUB_COMM_ID_EXT(regval); } else { fault_larb = F_MMU_INT_ID_LARB_ID(regval); } @@ -1068,7 +1074,7 @@ static const struct mtk_iommu_plat_data mt2712_data = { static const struct mtk_iommu_plat_data mt6779_data = { .m4u_plat = M4U_MT6779, - .flags = HAS_SUB_COMM | OUT_ORDER_WR_EN | WR_THROT_EN, + .flags = HAS_SUB_COMM_2BITS | OUT_ORDER_WR_EN | WR_THROT_EN, .inv_sel_reg = REG_MMU_INV_SEL_GEN2, .iova_region = single_domain, .iova_region_nr = ARRAY_SIZE(single_domain), @@ -1105,7 +,7 @@ static const struct mtk_iommu_plat_data mt8183_data = { static const struct mtk_iommu_plat_data mt8192_data = { .m4u_plat = M4U_MT8192, - .flags = HAS_BCLK | HAS_SUB_COMM | OUT_ORDER_WR_EN | + .flags = HAS_BCLK | HAS_SUB_COMM_2BITS | OUT_ORDER_WR_EN | WR_THROT_EN | IOVA_34_EN, .inv_sel_reg= REG_MMU_INV_SEL_GEN2, .iova_region= mt8192_multi_dom, diff --git a/drivers/iommu/mtk_iommu.h b/drivers/iommu/mtk_iommu.h index dc868fce0d2a..f41e32252056 100644 --- a/drivers/iommu/mtk_iommu.h +++ b/drivers/iommu/mtk_iommu.h @@ -20,7 +20,7 @@ #include #define MTK_LARB_COM_MAX 8 -#define MTK_LARB_SUBCOM_MAX4 +#define MTK_LARB_SUBCOM_MAX8 #define MTK_IOMMU_GROUP_MAX8 -- 2.18.0 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH v7 14/36] iommu/mediatek: Always enable output PA over 32bits in isr
Currently the output PA[32:33] is contained by the flag IOVA_34. This is not right. the iova_34 has no relation with pa[32:33], the 32bits iova still could map to pa[32:33]. Move it out from the flag. No need fix tag since currently only mt8192 use the calulation and it always has this IOVA_34 flag. Prepare for the IOMMU that still use IOVA 32bits but its dram size may be over 4GB. Signed-off-by: Yong Wu Reviewed-by: AngeloGioacchino Del Regno --- drivers/iommu/mtk_iommu.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c index ca77e7f1ce5d..d9689e041336 100644 --- a/drivers/iommu/mtk_iommu.c +++ b/drivers/iommu/mtk_iommu.c @@ -283,11 +283,11 @@ static irqreturn_t mtk_iommu_isr(int irq, void *dev_id) write = fault_iova & F_MMU_FAULT_VA_WRITE_BIT; if (MTK_IOMMU_HAS_FLAG(data->plat_data, IOVA_34_EN)) { va34_32 = FIELD_GET(F_MMU_INVAL_VA_34_32_MASK, fault_iova); - pa34_32 = FIELD_GET(F_MMU_INVAL_PA_34_32_MASK, fault_iova); fault_iova = fault_iova & F_MMU_INVAL_VA_31_12_MASK; fault_iova |= (u64)va34_32 << 32; - fault_pa |= (u64)pa34_32 << 32; } + pa34_32 = FIELD_GET(F_MMU_INVAL_PA_34_32_MASK, fault_iova); + fault_pa |= (u64)pa34_32 << 32; fault_port = F_MMU_INT_ID_PORT_ID(regval); if (MTK_IOMMU_HAS_FLAG(data->plat_data, HAS_SUB_COMM)) { -- 2.18.0 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH v7 13/36] iommu/mediatek: Remove the granule in the tlb flush
The MediaTek IOMMU doesn't care about granule when tlb flushing. Remove this variable. Signed-off-by: Yong Wu Reviewed-by: AngeloGioacchino Del Regno --- drivers/iommu/mtk_iommu.c | 6 ++ 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c index 22e2b104e3ee..ca77e7f1ce5d 100644 --- a/drivers/iommu/mtk_iommu.c +++ b/drivers/iommu/mtk_iommu.c @@ -219,7 +219,6 @@ static void mtk_iommu_tlb_flush_all(struct mtk_iommu_data *data) } static void mtk_iommu_tlb_flush_range_sync(unsigned long iova, size_t size, - size_t granule, struct mtk_iommu_data *data) { struct list_head *head = data->hw_list; @@ -541,8 +540,7 @@ static void mtk_iommu_iotlb_sync(struct iommu_domain *domain, struct mtk_iommu_domain *dom = to_mtk_domain(domain); size_t length = gather->end - gather->start + 1; - mtk_iommu_tlb_flush_range_sync(gather->start, length, gather->pgsize, - dom->data); + mtk_iommu_tlb_flush_range_sync(gather->start, length, dom->data); } static void mtk_iommu_sync_map(struct iommu_domain *domain, unsigned long iova, @@ -550,7 +548,7 @@ static void mtk_iommu_sync_map(struct iommu_domain *domain, unsigned long iova, { struct mtk_iommu_domain *dom = to_mtk_domain(domain); - mtk_iommu_tlb_flush_range_sync(iova, size, size, dom->data); + mtk_iommu_tlb_flush_range_sync(iova, size, dom->data); } static phys_addr_t mtk_iommu_iova_to_phys(struct iommu_domain *domain, -- 2.18.0 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH v7 12/36] iommu/mediatek: Add a flag STD_AXI_MODE
Add a new flag STD_AXI_MODE which is prepared for infra and apu iommu which use the standard axi mode. All the current SoC don't use this flag. Signed-off-by: Yong Wu Reviewed-by: AngeloGioacchino Del Regno --- drivers/iommu/mtk_iommu.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c index 92f172a772d1..22e2b104e3ee 100644 --- a/drivers/iommu/mtk_iommu.c +++ b/drivers/iommu/mtk_iommu.c @@ -122,6 +122,7 @@ #define IOVA_34_EN BIT(8) #define SHARE_PGTABLE BIT(9) /* 2 HW share pgtable */ #define DCM_DISABLEBIT(10) +#define STD_AXI_MODE BIT(11) /* For non MM iommu */ #define MTK_IOMMU_HAS_FLAG(pdata, _x) \ pdata)->flags) & (_x)) == (_x)) @@ -785,7 +786,8 @@ static int mtk_iommu_hw_init(const struct mtk_iommu_data *data) regval = 0; } else { regval = readl_relaxed(data->base + REG_MMU_MISC_CTRL); - regval &= ~F_MMU_STANDARD_AXI_MODE_MASK; + if (!MTK_IOMMU_HAS_FLAG(data->plat_data, STD_AXI_MODE)) + regval &= ~F_MMU_STANDARD_AXI_MODE_MASK; if (MTK_IOMMU_HAS_FLAG(data->plat_data, OUT_ORDER_WR_EN)) regval &= ~F_MMU_IN_ORDER_WR_EN_MASK; } -- 2.18.0 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH v7 11/36] iommu/mediatek: Add a flag DCM_DISABLE
In the infra iommu, we should disable DCM. add a new flag for this. Signed-off-by: Yong Wu Reviewed-by: AngeloGioacchino Del Regno --- drivers/iommu/mtk_iommu.c | 9 - 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c index d91a0c138536..92f172a772d1 100644 --- a/drivers/iommu/mtk_iommu.c +++ b/drivers/iommu/mtk_iommu.c @@ -51,6 +51,8 @@ #define F_MMU_STANDARD_AXI_MODE_MASK (BIT(3) | BIT(19)) #define REG_MMU_DCM_DIS0x050 +#define F_MMU_DCM BIT(8) + #define REG_MMU_WR_LEN_CTRL0x054 #define F_MMU_WR_THROT_DIS_MASK(BIT(5) | BIT(21)) @@ -119,6 +121,7 @@ #define HAS_LEGACY_IVRP_PADDR BIT(7) #define IOVA_34_EN BIT(8) #define SHARE_PGTABLE BIT(9) /* 2 HW share pgtable */ +#define DCM_DISABLEBIT(10) #define MTK_IOMMU_HAS_FLAG(pdata, _x) \ pdata)->flags) & (_x)) == (_x)) @@ -765,7 +768,11 @@ static int mtk_iommu_hw_init(const struct mtk_iommu_data *data) regval = F_MMU_VLD_PA_RNG(7, 4); writel_relaxed(regval, data->base + REG_MMU_VLD_PA_RNG); } - writel_relaxed(0, data->base + REG_MMU_DCM_DIS); + if (MTK_IOMMU_HAS_FLAG(data->plat_data, DCM_DISABLE)) + writel_relaxed(F_MMU_DCM, data->base + REG_MMU_DCM_DIS); + else + writel_relaxed(0, data->base + REG_MMU_DCM_DIS); + if (MTK_IOMMU_HAS_FLAG(data->plat_data, WR_THROT_EN)) { /* write command throttling mode */ regval = readl_relaxed(data->base + REG_MMU_WR_LEN_CTRL); -- 2.18.0 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH v7 10/36] iommu/mediatek: Add 12G~16G support for multi domains
In mt8192, we preassign 0-4G; 4G-8G; 8G-12G for different multimedia engines. This depends on the "dma-ranges=" in the iommu consumer's dtsi node. Adds 12G-16G region here. and reword the previous comment. we don't limit which master locate in which region. CCU still is 8G-12G. Don't change it here. Signed-off-by: Yong Wu Reviewed-by: AngeloGioacchino Del Regno --- drivers/iommu/mtk_iommu.c | 8 +--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c index 1b8e4405dd0f..d91a0c138536 100644 --- a/drivers/iommu/mtk_iommu.c +++ b/drivers/iommu/mtk_iommu.c @@ -180,10 +180,12 @@ static const struct mtk_iommu_iova_region single_domain[] = { }; static const struct mtk_iommu_iova_region mt8192_multi_dom[] = { - { .iova_base = 0x0, .size = SZ_4G}, /* disp: 0 ~ 4G */ + { .iova_base = 0x0, .size = SZ_4G}, /* 0 ~ 4G */ #if IS_ENABLED(CONFIG_ARCH_DMA_ADDR_T_64BIT) - { .iova_base = SZ_4G, .size = SZ_4G}, /* vdec: 4G ~ 8G */ - { .iova_base = SZ_4G * 2, .size = SZ_4G}, /* CAM/MDP: 8G ~ 12G */ + { .iova_base = SZ_4G, .size = SZ_4G}, /* 4G ~ 8G */ + { .iova_base = SZ_4G * 2, .size = SZ_4G}, /* 8G ~ 12G */ + { .iova_base = SZ_4G * 3, .size = SZ_4G}, /* 12G ~ 16G */ + { .iova_base = 0x24000ULL, .size = 0x400}, /* CCU0 */ { .iova_base = 0x24400ULL, .size = 0x400}, /* CCU1 */ #endif -- 2.18.0 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH v7 09/36] iommu/mediatek: Adapt sharing and non-sharing pgtable case
In previous mt2712, Both IOMMUs are MM IOMMU, and they will share pgtable. However in the latest SoC, another is infra IOMMU, there is no reason to share pgtable between MM with INFRA IOMMU. This patch manage to implement the two case(sharing and non-sharing pgtable). Currently we use for_each_m4u to loop the 2 HWs. Add the list_head into this macro. In the sharing pgtable case, the list_head is the global "m4ulist". In the non-sharing pgtable case, the list_head is hw_list_head which is a variable in the "data". then for_each_m4u will only loop itself. Signed-off-by: Yong Wu Reviewed-by: AngeloGioacchino Del Regno --- drivers/iommu/mtk_iommu.c | 43 +-- drivers/iommu/mtk_iommu.h | 7 +++ 2 files changed, 30 insertions(+), 20 deletions(-) diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c index ecdce5d3e8cf..1b8e4405dd0f 100644 --- a/drivers/iommu/mtk_iommu.c +++ b/drivers/iommu/mtk_iommu.c @@ -118,6 +118,7 @@ #define WR_THROT_ENBIT(6) #define HAS_LEGACY_IVRP_PADDR BIT(7) #define IOVA_34_EN BIT(8) +#define SHARE_PGTABLE BIT(9) /* 2 HW share pgtable */ #define MTK_IOMMU_HAS_FLAG(pdata, _x) \ pdata)->flags) & (_x)) == (_x)) @@ -167,7 +168,7 @@ static int mtk_iommu_hw_init(const struct mtk_iommu_data *data); static LIST_HEAD(m4ulist); /* List all the M4U HWs */ -#define for_each_m4u(data) list_for_each_entry(data, &m4ulist, list) +#define for_each_m4u(data, head) list_for_each_entry(data, head, list) struct mtk_iommu_iova_region { dma_addr_t iova_base; @@ -188,21 +189,10 @@ static const struct mtk_iommu_iova_region mt8192_multi_dom[] = { #endif }; -/* - * There may be 1 or 2 M4U HWs, But we always expect they are in the same domain - * for the performance. - * - * Here always return the mtk_iommu_data of the first probed M4U where the - * iommu domain information is recorded. - */ -static struct mtk_iommu_data *mtk_iommu_get_m4u_data(void) +/* If 2 M4U share a domain(use the same hwlist), Put the corresponding info in first data.*/ +static struct mtk_iommu_data *mtk_iommu_get_frst_data(struct list_head *hwlist) { - struct mtk_iommu_data *data; - - for_each_m4u(data) - return data; - - return NULL; + return list_first_entry(hwlist, struct mtk_iommu_data, list); } static struct mtk_iommu_domain *to_mtk_domain(struct iommu_domain *dom) @@ -226,11 +216,12 @@ static void mtk_iommu_tlb_flush_range_sync(unsigned long iova, size_t size, size_t granule, struct mtk_iommu_data *data) { + struct list_head *head = data->hw_list; unsigned long flags; int ret; u32 tmp; - for_each_m4u(data) { + for_each_m4u(data, head) { if (pm_runtime_get_if_in_use(data->dev) <= 0) continue; @@ -451,6 +442,7 @@ static int mtk_iommu_attach_device(struct iommu_domain *domain, { struct mtk_iommu_data *data = dev_iommu_priv_get(dev), *frstdata; struct mtk_iommu_domain *dom = to_mtk_domain(domain); + struct list_head *hw_list = data->hw_list; struct device *m4udev = data->dev; int ret, domid; @@ -461,7 +453,7 @@ static int mtk_iommu_attach_device(struct iommu_domain *domain, mutex_lock(&dom->mutex); if (!dom->data) { /* Data is in the frstdata in sharing pgtable case. */ - frstdata = mtk_iommu_get_m4u_data(); + frstdata = mtk_iommu_get_frst_data(hw_list); ret = mtk_iommu_domain_finalise(dom, frstdata, domid); if (ret) { @@ -625,10 +617,12 @@ static void mtk_iommu_release_device(struct device *dev) static struct iommu_group *mtk_iommu_device_group(struct device *dev) { - struct mtk_iommu_data *data = mtk_iommu_get_m4u_data(); + struct mtk_iommu_data *c_data = dev_iommu_priv_get(dev), *data; + struct list_head *hw_list = c_data->hw_list; struct iommu_group *group; int domid; + data = mtk_iommu_get_frst_data(hw_list); if (!data) return ERR_PTR(-ENODEV); @@ -938,7 +932,15 @@ static int mtk_iommu_probe(struct platform_device *pdev) goto out_sysfs_remove; spin_lock_init(&data->tlb_lock); - list_add_tail(&data->list, &m4ulist); + + if (MTK_IOMMU_HAS_FLAG(data->plat_data, SHARE_PGTABLE)) { + list_add_tail(&data->list, data->plat_data->hw_list); + data->hw_list = data->plat_data->hw_list; + } else { + INIT_LIST_HEAD(&data->hw_list_head); + list_add_tail(&data->list, &data->hw_list_head); + data->hw_list = &data->hw_list_head; + } if (!iommu_present(&platform_bus_type)) { ret = bus_set_iom
[PATCH v7 08/36] iommu/mediatek: Add mutex for data in the mtk_iommu_domain
Same with the previous patch, add a mutex for the "data" in the mtk_iommu_domain. Just improve the safety for multi devices enter attach_device at the same time. We don't get the real issue for this. Signed-off-by: Yong Wu Reviewed-by: AngeloGioacchino Del Regno --- drivers/iommu/mtk_iommu.c | 10 +- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c index 3413cc98e57e..ecdce5d3e8cf 100644 --- a/drivers/iommu/mtk_iommu.c +++ b/drivers/iommu/mtk_iommu.c @@ -128,6 +128,8 @@ struct mtk_iommu_domain { struct mtk_iommu_data *data; struct iommu_domain domain; + + struct mutexmutex; /* Protect "data" in this structure */ }; static const struct iommu_ops mtk_iommu_ops; @@ -434,6 +436,7 @@ static struct iommu_domain *mtk_iommu_domain_alloc(unsigned type) dom = kzalloc(sizeof(*dom), GFP_KERNEL); if (!dom) return NULL; + mutex_init(&dom->mutex); return &dom->domain; } @@ -455,14 +458,19 @@ static int mtk_iommu_attach_device(struct iommu_domain *domain, if (domid < 0) return domid; + mutex_lock(&dom->mutex); if (!dom->data) { /* Data is in the frstdata in sharing pgtable case. */ frstdata = mtk_iommu_get_m4u_data(); - if (mtk_iommu_domain_finalise(dom, frstdata, domid)) + ret = mtk_iommu_domain_finalise(dom, frstdata, domid); + if (ret) { + mutex_unlock(&dom->mutex); return -ENODEV; + } dom->data = data; } + mutex_unlock(&dom->mutex); mutex_lock(&data->mutex); if (!data->m4u_dom) { /* Initialize the M4U HW */ -- 2.18.0 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH v7 07/36] iommu/mediatek: Add mutex for m4u_group and m4u_dom in data
Add a mutex to protect the data in the structure mtk_iommu_data, like ->"m4u_group" ->"m4u_dom". For the internal data, we should protect it in ourselves driver. Add a mutex for this. This could be a fix for the multi-groups support. Fixes: c3045f39244e ("iommu/mediatek: Support for multi domains") Signed-off-by: Yunfei Wang Signed-off-by: Yong Wu Reviewed-by: AngeloGioacchino Del Regno --- drivers/iommu/mtk_iommu.c | 13 +++-- drivers/iommu/mtk_iommu.h | 2 ++ 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c index 81b8db450eac..3413cc98e57e 100644 --- a/drivers/iommu/mtk_iommu.c +++ b/drivers/iommu/mtk_iommu.c @@ -464,15 +464,16 @@ static int mtk_iommu_attach_device(struct iommu_domain *domain, dom->data = data; } + mutex_lock(&data->mutex); if (!data->m4u_dom) { /* Initialize the M4U HW */ ret = pm_runtime_resume_and_get(m4udev); if (ret < 0) - return ret; + goto err_unlock; ret = mtk_iommu_hw_init(data); if (ret) { pm_runtime_put(m4udev); - return ret; + goto err_unlock; } data->m4u_dom = dom; writel(dom->cfg.arm_v7s_cfg.ttbr & MMU_PT_ADDR_MASK, @@ -480,9 +481,14 @@ static int mtk_iommu_attach_device(struct iommu_domain *domain, pm_runtime_put(m4udev); } + mutex_unlock(&data->mutex); mtk_iommu_config(data, dev, true, domid); return 0; + +err_unlock: + mutex_unlock(&data->mutex); + return ret; } static void mtk_iommu_detach_device(struct iommu_domain *domain, @@ -622,6 +628,7 @@ static struct iommu_group *mtk_iommu_device_group(struct device *dev) if (domid < 0) return ERR_PTR(domid); + mutex_lock(&data->mutex); group = data->m4u_group[domid]; if (!group) { group = iommu_group_alloc(); @@ -630,6 +637,7 @@ static struct iommu_group *mtk_iommu_device_group(struct device *dev) } else { iommu_group_ref_get(group); } + mutex_unlock(&data->mutex); return group; } @@ -910,6 +918,7 @@ static int mtk_iommu_probe(struct platform_device *pdev) } platform_set_drvdata(pdev, data); + mutex_init(&data->mutex); ret = iommu_device_sysfs_add(&data->iommu, dev, NULL, "mtk-iommu.%pa", &ioaddr); diff --git a/drivers/iommu/mtk_iommu.h b/drivers/iommu/mtk_iommu.h index b742432220c5..5e8da947affc 100644 --- a/drivers/iommu/mtk_iommu.h +++ b/drivers/iommu/mtk_iommu.h @@ -80,6 +80,8 @@ struct mtk_iommu_data { struct dma_iommu_mapping*mapping; /* For mtk_iommu_v1.c */ + struct mutexmutex; /* Protect m4u_group/m4u_dom above */ + struct list_headlist; struct mtk_smi_larb_iommu larb_imu[MTK_LARB_NR_MAX]; }; -- 2.18.0 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH v7 05/36] iommu/mediatek: Add list_del in mtk_iommu_remove
Lack the list_del in the mtk_iommu_remove, and remove bus_set_iommu(*, NULL) since there may be several iommu HWs. we can not bus_set_iommu null when one iommu driver unbind. This could be a fix for mt2712 which support 2 M4U HW and list them. Fixes: 7c3a2ec02806 ("iommu/mediatek: Merge 2 M4U HWs into one iommu domain") Signed-off-by: Yong Wu Reviewed-by: AngeloGioacchino Del Regno --- drivers/iommu/mtk_iommu.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c index 95c82b8bcc35..e4b4ebbcb73f 100644 --- a/drivers/iommu/mtk_iommu.c +++ b/drivers/iommu/mtk_iommu.c @@ -955,8 +955,7 @@ static int mtk_iommu_remove(struct platform_device *pdev) iommu_device_sysfs_remove(&data->iommu); iommu_device_unregister(&data->iommu); - if (iommu_present(&platform_bus_type)) - bus_set_iommu(&platform_bus_type, NULL); + list_del(&data->list); clk_disable_unprepare(data->bclk); device_link_remove(data->smicomm_dev, &pdev->dev); -- 2.18.0 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH v7 06/36] iommu/mediatek: Remove clk_disable in mtk_iommu_remove
After the commit b34ea31fe013 ("iommu/mediatek: Always enable the clk on resume"), the iommu clock is controlled by the runtime callback. thus remove the clk control in the mtk_iommu_remove. Otherwise, it will warning like: echo 14018000.iommu > /sys/bus/platform/drivers/mtk-iommu/unbind [ 51.413044] [ cut here ] [ 51.413648] vpp0_smi_iommu already disabled [ 51.414233] WARNING: CPU: 2 PID: 157 at */v5.15-rc1/kernel/mediatek/ drivers/clk/clk.c:952 clk_core_disable+0xb0/0xb8 [ 51.417174] Hardware name: MT8195V/C(ENG) (DT) [ 51.418635] pc : clk_core_disable+0xb0/0xb8 [ 51.419177] lr : clk_core_disable+0xb0/0xb8 ... [ 51.429375] Call trace: [ 51.429694] clk_core_disable+0xb0/0xb8 [ 51.430193] clk_core_disable_lock+0x24/0x40 [ 51.430745] clk_disable+0x20/0x30 [ 51.431189] mtk_iommu_remove+0x58/0x118 [ 51.431705] platform_remove+0x28/0x60 [ 51.432197] device_release_driver_internal+0x110/0x1f0 [ 51.432873] device_driver_detach+0x18/0x28 [ 51.433418] unbind_store+0xd4/0x108 [ 51.433886] drv_attr_store+0x24/0x38 [ 51.434363] sysfs_kf_write+0x40/0x58 [ 51.434843] kernfs_fop_write_iter+0x164/0x1e0 Fixes: b34ea31fe013 ("iommu/mediatek: Always enable the clk on resume") Reported-by: Hsin-Yi Wang Signed-off-by: Yong Wu Reviewed-by: AngeloGioacchino Del Regno --- drivers/iommu/mtk_iommu.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c index e4b4ebbcb73f..81b8db450eac 100644 --- a/drivers/iommu/mtk_iommu.c +++ b/drivers/iommu/mtk_iommu.c @@ -957,7 +957,6 @@ static int mtk_iommu_remove(struct platform_device *pdev) list_del(&data->list); - clk_disable_unprepare(data->bclk); device_link_remove(data->smicomm_dev, &pdev->dev); pm_runtime_disable(&pdev->dev); devm_free_irq(&pdev->dev, data->irq, data); -- 2.18.0 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH v7 04/36] iommu/mediatek: Fix 2 HW sharing pgtable issue
In the commit 4f956c97d26b ("iommu/mediatek: Move domain_finalise into attach_device"), I overlooked the sharing pgtable case. After that commit, the "data" in the mtk_iommu_domain_finalise always is the data of the current IOMMU HW. Fix this for the sharing pgtable case. Only affect mt2712 which is the only SoC that share pgtable currently. Fixes: 4f956c97d26b ("iommu/mediatek: Move domain_finalise into attach_device") Signed-off-by: Yong Wu Reviewed-by: AngeloGioacchino Del Regno --- drivers/iommu/mtk_iommu.c | 7 +-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c index 6fd75a60abd6..95c82b8bcc35 100644 --- a/drivers/iommu/mtk_iommu.c +++ b/drivers/iommu/mtk_iommu.c @@ -446,7 +446,7 @@ static void mtk_iommu_domain_free(struct iommu_domain *domain) static int mtk_iommu_attach_device(struct iommu_domain *domain, struct device *dev) { - struct mtk_iommu_data *data = dev_iommu_priv_get(dev); + struct mtk_iommu_data *data = dev_iommu_priv_get(dev), *frstdata; struct mtk_iommu_domain *dom = to_mtk_domain(domain); struct device *m4udev = data->dev; int ret, domid; @@ -456,7 +456,10 @@ static int mtk_iommu_attach_device(struct iommu_domain *domain, return domid; if (!dom->data) { - if (mtk_iommu_domain_finalise(dom, data, domid)) + /* Data is in the frstdata in sharing pgtable case. */ + frstdata = mtk_iommu_get_m4u_data(); + + if (mtk_iommu_domain_finalise(dom, frstdata, domid)) return -ENODEV; dom->data = data; } -- 2.18.0 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH v7 03/36] dt-bindings: mediatek: mt8186: Add binding for MM iommu
Add mt8186 iommu binding. "-mm" means the iommu is for Multimedia. Signed-off-by: Yong Wu Acked-by: Krzysztof Kozlowski Reviewed-by: Rob Herring Reviewed-by: Matthias Brugger Reviewed-by: AngeloGioacchino Del Regno --- .../bindings/iommu/mediatek,iommu.yaml| 4 + .../dt-bindings/memory/mt8186-memory-port.h | 217 ++ 2 files changed, 221 insertions(+) create mode 100644 include/dt-bindings/memory/mt8186-memory-port.h diff --git a/Documentation/devicetree/bindings/iommu/mediatek,iommu.yaml b/Documentation/devicetree/bindings/iommu/mediatek,iommu.yaml index eed59ec00e78..91a3629a8e6e 100644 --- a/Documentation/devicetree/bindings/iommu/mediatek,iommu.yaml +++ b/Documentation/devicetree/bindings/iommu/mediatek,iommu.yaml @@ -76,6 +76,7 @@ properties: - mediatek,mt8167-m4u # generation two - mediatek,mt8173-m4u # generation two - mediatek,mt8183-m4u # generation two + - mediatek,mt8186-iommu-mm # generation two - mediatek,mt8192-m4u # generation two - mediatek,mt8195-iommu-vdo# generation two - mediatek,mt8195-iommu-vpp# generation two @@ -122,6 +123,7 @@ properties: dt-binding/memory/mt8167-larb-port.h for mt8167, dt-binding/memory/mt8173-larb-port.h for mt8173, dt-binding/memory/mt8183-larb-port.h for mt8183, + dt-binding/memory/mt8186-memory-port.h for mt8186, dt-binding/memory/mt8192-larb-port.h for mt8192. dt-binding/memory/mt8195-memory-port.h for mt8195. @@ -143,6 +145,7 @@ allOf: - mediatek,mt2701-m4u - mediatek,mt2712-m4u - mediatek,mt8173-m4u + - mediatek,mt8186-iommu-mm - mediatek,mt8192-m4u - mediatek,mt8195-iommu-vdo - mediatek,mt8195-iommu-vpp @@ -155,6 +158,7 @@ allOf: properties: compatible: enum: +- mediatek,mt8186-iommu-mm - mediatek,mt8192-m4u - mediatek,mt8195-iommu-vdo - mediatek,mt8195-iommu-vpp diff --git a/include/dt-bindings/memory/mt8186-memory-port.h b/include/dt-bindings/memory/mt8186-memory-port.h new file mode 100644 index ..2bc6e4433048 --- /dev/null +++ b/include/dt-bindings/memory/mt8186-memory-port.h @@ -0,0 +1,217 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2022 MediaTek Inc. + * + * Author: Anan Sun + * Author: Yong Wu + */ +#ifndef _DT_BINDINGS_MEMORY_MT8186_LARB_PORT_H_ +#define _DT_BINDINGS_MEMORY_MT8186_LARB_PORT_H_ + +#include + +/* + * MM IOMMU supports 16GB dma address. We separate it to four ranges: + * 0 ~ 4G; 4G ~ 8G; 8G ~ 12G; 12G ~ 16G, we could adjust these masters + * locate in anyone region. BUT: + * a) Make sure all the ports inside a larb are in one range. + * b) The iova of any master can NOT cross the 4G/8G/12G boundary. + * + * This is the suggested mapping in this SoC: + * + * modulesdma-address-region larbs-ports + * disp 0 ~ 4G larb0/1/2 + * vcodec 4G ~ 8G larb4/7 + * cam/mdp 8G ~ 12G the other larbs. + * N/A 12G ~ 16G + * CCU0 0x24000_ ~ 0x243ff_ larb13: port 9/10 + * CCU1 0x24400_ ~ 0x247ff_ larb14: port 4/5 + */ + +/* MM IOMMU ports */ +/* LARB 0 -- MMSYS */ +#define IOMMU_PORT_L0_DISP_POSTMASK0 MTK_M4U_ID(0, 0) +#define IOMMU_PORT_L0_REVERSED MTK_M4U_ID(0, 1) +#define IOMMU_PORT_L0_OVL_RDMA0MTK_M4U_ID(0, 2) +#define IOMMU_PORT_L0_DISP_FAKE0 MTK_M4U_ID(0, 3) + +/* LARB 1 -- MMSYS */ +#define IOMMU_PORT_L1_DISP_RDMA1 MTK_M4U_ID(1, 0) +#define IOMMU_PORT_L1_OVL_2L_RDMA0 MTK_M4U_ID(1, 1) +#define IOMMU_PORT_L1_DISP_RDMA0 MTK_M4U_ID(1, 2) +#define IOMMU_PORT_L1_DISP_WDMA0 MTK_M4U_ID(1, 3) +#define IOMMU_PORT_L1_DISP_FAKE1 MTK_M4U_ID(1, 4) + +/* LARB 2 -- MMSYS */ +#define IOMMU_PORT_L2_MDP_RDMA0MTK_M4U_ID(2, 0) +#define IOMMU_PORT_L2_MDP_RDMA1MTK_M4U_ID(2, 1) +#define IOMMU_PORT_L2_MDP_WROT0MTK_M4U_ID(2, 2) +#define IOMMU_PORT_L2_MDP_WROT1MTK_M4U_ID(2, 3) +#define IOMMU_PORT_L2_DISP_FAKE0 MTK_M4U_ID(2, 4) + +/* LARB 4 -- VDEC */ +#define IOMMU_PORT_L4_HW_VDEC_MC_EXT MTK_M4U_ID(4, 0) +#define IOMMU_PORT_L4_HW_VDEC_UFO_EXT MTK_M4U_ID(4, 1) +#define IOMMU_PORT_L4_HW_VDEC_PP_EXT MTK_M4U_ID(4, 2) +#define IOMMU_PORT_L4_HW_VDEC_PRED_RD_EXT MTK_M4U_ID(4, 3) +#define IOMMU_PORT_L4_HW_VDEC_PRED_WR_EXT MTK_M4U_ID(4, 4) +#define IOMMU_PORT_L4_HW_VDEC_PPWRAP_EXT MTK_M4U_ID(4, 5) +#define IOMMU_PORT_L4_HW_VDEC_TILE_EXT MTK_M4U_ID(4, 6) +#define IOMMU_PORT_L4_HW_VDEC_VLD_EXT MTK_M4U_ID(4, 7) +#define IOMMU_PORT_L4_HW_VDEC_VLD2_EXT MTK_M4U_ID(4, 8) +#define IOMMU_PORT_L4_HW_VDEC_AVC_MV_EXT MTK_M4U_ID(4, 9) +#define IOMMU_PORT_L4_HW_VDEC_UFO_ENC_EXT MTK_M4U
[PATCH v7 02/36] dt-bindings: mediatek: mt8195: Add binding for infra IOMMU
In mt8195, we have a new IOMMU that is for INFRA IOMMU. its masters mainly are PCIe and USB. Different with MM IOMMU, all these masters connect with IOMMU directly, there is no mediatek,larbs property for infra IOMMU. Another thing is about PCIe ports. currently the function "of_iommu_configure_dev_id" only support the id number is 1, But our PCIe have two ports, one is for reading and the other is for writing. see more about the PCIe patch in this patchset. Thus, I only list the reading id here and add the other id in our driver. Signed-off-by: Yong Wu Acked-by: Krzysztof Kozlowski Reviewed-by: Rob Herring --- .../bindings/iommu/mediatek,iommu.yaml | 13 - .../dt-bindings/memory/mt8195-memory-port.h| 18 ++ include/dt-bindings/memory/mtk-memory-port.h | 2 ++ 3 files changed, 32 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/iommu/mediatek,iommu.yaml b/Documentation/devicetree/bindings/iommu/mediatek,iommu.yaml index 2223408e91a9..eed59ec00e78 100644 --- a/Documentation/devicetree/bindings/iommu/mediatek,iommu.yaml +++ b/Documentation/devicetree/bindings/iommu/mediatek,iommu.yaml @@ -79,6 +79,7 @@ properties: - mediatek,mt8192-m4u # generation two - mediatek,mt8195-iommu-vdo# generation two - mediatek,mt8195-iommu-vpp# generation two + - mediatek,mt8195-iommu-infra # generation two - description: mt7623 generation one items: @@ -131,7 +132,6 @@ required: - compatible - reg - interrupts - - mediatek,larbs - '#iommu-cells' allOf: @@ -163,6 +163,17 @@ allOf: required: - power-domains + - if: # The IOMMUs don't have larbs. + not: +properties: + compatible: +contains: + const: mediatek,mt8195-iommu-infra + +then: + required: +- mediatek,larbs + additionalProperties: false examples: diff --git a/include/dt-bindings/memory/mt8195-memory-port.h b/include/dt-bindings/memory/mt8195-memory-port.h index c10e8b61f1e8..70ba9f498eeb 100644 --- a/include/dt-bindings/memory/mt8195-memory-port.h +++ b/include/dt-bindings/memory/mt8195-memory-port.h @@ -387,4 +387,22 @@ #define M4U_PORT_L28_CAM_DRZS4NO_R1MTK_M4U_ID(28, 5) #define M4U_PORT_L28_CAM_TNCSO_R1 MTK_M4U_ID(28, 6) +/* Infra iommu ports */ +/* PCIe1: read: BIT16; write BIT17. */ +#define IOMMU_PORT_INFRA_PCIE1 MTK_IFAIOMMU_PERI_ID(16) +/* PCIe0: read: BIT18; write BIT19. */ +#define IOMMU_PORT_INFRA_PCIE0 MTK_IFAIOMMU_PERI_ID(18) +#define IOMMU_PORT_INFRA_SSUSB_P3_RMTK_IFAIOMMU_PERI_ID(20) +#define IOMMU_PORT_INFRA_SSUSB_P3_WMTK_IFAIOMMU_PERI_ID(21) +#define IOMMU_PORT_INFRA_SSUSB_P2_RMTK_IFAIOMMU_PERI_ID(22) +#define IOMMU_PORT_INFRA_SSUSB_P2_WMTK_IFAIOMMU_PERI_ID(23) +#define IOMMU_PORT_INFRA_SSUSB_P1_1_R MTK_IFAIOMMU_PERI_ID(24) +#define IOMMU_PORT_INFRA_SSUSB_P1_1_W MTK_IFAIOMMU_PERI_ID(25) +#define IOMMU_PORT_INFRA_SSUSB_P1_0_R MTK_IFAIOMMU_PERI_ID(26) +#define IOMMU_PORT_INFRA_SSUSB_P1_0_W MTK_IFAIOMMU_PERI_ID(27) +#define IOMMU_PORT_INFRA_SSUSB2_R MTK_IFAIOMMU_PERI_ID(28) +#define IOMMU_PORT_INFRA_SSUSB2_W MTK_IFAIOMMU_PERI_ID(29) +#define IOMMU_PORT_INFRA_SSUSB_R MTK_IFAIOMMU_PERI_ID(30) +#define IOMMU_PORT_INFRA_SSUSB_W MTK_IFAIOMMU_PERI_ID(31) + #endif diff --git a/include/dt-bindings/memory/mtk-memory-port.h b/include/dt-bindings/memory/mtk-memory-port.h index 7d64103209af..2f68a0511a25 100644 --- a/include/dt-bindings/memory/mtk-memory-port.h +++ b/include/dt-bindings/memory/mtk-memory-port.h @@ -12,4 +12,6 @@ #define MTK_M4U_TO_LARB(id)(((id) >> 5) & 0x1f) #define MTK_M4U_TO_PORT(id)((id) & 0x1f) +#define MTK_IFAIOMMU_PERI_ID(port) MTK_M4U_ID(0, port) + #endif -- 2.18.0 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH v7 01/36] dt-bindings: mediatek: mt8195: Add binding for MM IOMMU
This patch adds descriptions for mt8195 IOMMU which also use ARM Short-Descriptor translation table format. In mt8195, there are two smi-common HW and IOMMU, one is for vdo(video output), the other is for vpp(video processing pipe). They connects with different smi-larbs, then some setting(larbid_remap) is different. Differentiate them with the compatible string. Something like this: IOMMU(VDO) IOMMU(VPP) | | SMI_COMMON_VDO SMI_COMMON_VPP --- | | ... | | ... larb0 larb2 ...larb1 larb3... Another change is that we have a new IOMMU that is for infra master like PCIe and USB. The infra master don't have the larb and ports, thus we rename the port header file to mt8195-memory-port.h rather than mt8195-larb-port.h. Also, the IOMMU is not only for MM, thus, we don't call it "m4u" which means "MultiMedia Memory Management UNIT". thus, use the "iommu" as the compatiable string. Signed-off-by: Yong Wu Acked-by: Krzysztof Kozlowski Reviewed-by: Rob Herring --- .../bindings/iommu/mediatek,iommu.yaml| 7 + .../dt-bindings/memory/mt8195-memory-port.h | 390 ++ 2 files changed, 397 insertions(+) create mode 100644 include/dt-bindings/memory/mt8195-memory-port.h diff --git a/Documentation/devicetree/bindings/iommu/mediatek,iommu.yaml b/Documentation/devicetree/bindings/iommu/mediatek,iommu.yaml index 97e8c471a5e8..2223408e91a9 100644 --- a/Documentation/devicetree/bindings/iommu/mediatek,iommu.yaml +++ b/Documentation/devicetree/bindings/iommu/mediatek,iommu.yaml @@ -77,6 +77,8 @@ properties: - mediatek,mt8173-m4u # generation two - mediatek,mt8183-m4u # generation two - mediatek,mt8192-m4u # generation two + - mediatek,mt8195-iommu-vdo# generation two + - mediatek,mt8195-iommu-vpp# generation two - description: mt7623 generation one items: @@ -120,6 +122,7 @@ properties: dt-binding/memory/mt8173-larb-port.h for mt8173, dt-binding/memory/mt8183-larb-port.h for mt8183, dt-binding/memory/mt8192-larb-port.h for mt8192. + dt-binding/memory/mt8195-memory-port.h for mt8195. power-domains: maxItems: 1 @@ -141,6 +144,8 @@ allOf: - mediatek,mt2712-m4u - mediatek,mt8173-m4u - mediatek,mt8192-m4u + - mediatek,mt8195-iommu-vdo + - mediatek,mt8195-iommu-vpp then: required: @@ -151,6 +156,8 @@ allOf: compatible: enum: - mediatek,mt8192-m4u +- mediatek,mt8195-iommu-vdo +- mediatek,mt8195-iommu-vpp then: required: diff --git a/include/dt-bindings/memory/mt8195-memory-port.h b/include/dt-bindings/memory/mt8195-memory-port.h new file mode 100644 index ..c10e8b61f1e8 --- /dev/null +++ b/include/dt-bindings/memory/mt8195-memory-port.h @@ -0,0 +1,390 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2022 MediaTek Inc. + * Author: Yong Wu + */ +#ifndef _DT_BINDINGS_MEMORY_MT8195_LARB_PORT_H_ +#define _DT_BINDINGS_MEMORY_MT8195_LARB_PORT_H_ + +#include + +/* + * MM IOMMU supports 16GB dma address. We separate it to four ranges: + * 0 ~ 4G; 4G ~ 8G; 8G ~ 12G; 12G ~ 16G, we could adjust these masters + * locate in anyone region. BUT: + * a) Make sure all the ports inside a larb are in one range. + * b) The iova of any master can NOT cross the 4G/8G/12G boundary. + * + * This is the suggested mapping in this SoC: + * + * modulesdma-address-region larbs-ports + * disp 0 ~ 4G larb0/1/2/3 + * vcodec 4G ~ 8G larb19/20/21/22/23/24 + * cam/mdp 8G ~ 12G the other larbs. + * N/A 12G ~ 16G + * CCU0 0x24000_ ~ 0x243ff_ larb18: port 0/1 + * CCU1 0x24400_ ~ 0x247ff_ larb18: port 2/3 + * + * This SoC have two IOMMU HWs, this is the detailed connected information: + * iommu-vdo: larb0/2/5/7/9/10/11/13/17/19/21/24/25/28 + * iommu-vpp: larb1/3/4/6/8/12/14/16/18/20/22/23/26/27 + */ + +/* MM IOMMU ports */ +/* larb0 */ +#define M4U_PORT_L0_DISP_RDMA0 MTK_M4U_ID(0, 0) +#define M4U_PORT_L0_DISP_WDMA0 MTK_M4U_ID(0, 1) +#define M4U_PORT_L0_DISP_OVL0_RDMA0MTK_M4U_ID(0, 2) +#define M4U_PORT_L0_DISP_OVL0_RDMA1MTK_M4U_ID(0, 3) +#define M4U_PORT_L0_DISP_OVL0_HDR MTK_M4U_ID(0, 4) +#define M4U_PORT_L0_DISP_FAKE0 MTK_M4U_ID(0, 5) + +/* larb1 */ +#define M4U_PORT_L1_DISP_RDMA0 MTK_M4U_ID(1, 0) +#define M4U_PORT_L1_DISP_WDMA0 MTK_M4U_ID(1, 1) +#define M4U_PORT_L1_DISP_OVL0_RDMA0MTK_M4U_ID(1, 2) +#define M4U_PORT_L1_DISP_OVL0_RDMA1MTK_M4U_ID(1, 3) +#define M4U_PORT_L1_DISP_OVL0_HDR MTK_M4U_ID(1, 4) +#define M4U_PORT_L1_DISP_FAKE0 MTK_M4U_ID(1, 5)
[PATCH v7 00/36] MT8195 and MT8186 IOMMU SUPPORT
This patchset adds MT8195 and MT8186 iommu support. MT8195 have 3 IOMMU HWs. 2 IOMMU HW is for multimedia, and 1 IOMMU HW is for infra-master, like PCIe/USB. About the 2 MM IOMMU HW, something like this: IOMMU(VDO) IOMMU(VPP) | | SMI_COMMON(VDO) SMI_COMMON(VPP) --- | | ... | | ... larb0 larb2 ...larb1 larb3... these two MM IOMMU HW share a pgtable. About the INFRA IOMMU, it don't have larbs, the master connects the iommu directly. It use a independent pgtable. Also, mt8195 IOMMU bank supports. Normally the IOMMU register size only is 0x1000. In this IOMMU HW, the register size is 5 * 0x1000. each 0x1000 is a bank. the banks' register look like this: |bank0 | bank1 | bank2 | bank3 | bank4| |global | |control| null |regs | - |bank |bank |bank |bank |bank | |regs |regs |regs |regs |regs | | | | | | | - All the banks share some global control registers, and each bank have its special bank registers, like pgtable base register, tlb operation registers, the fault status registers. In mt8195, we enable this bank feature for infra iommu, We put PCIe in bank0 and USB in bank4. they have independent pgtable. MT8186 is based on MT8195, it just has two patches. Change note: v7: 1) Update the changes from Matthias. like add a new function for readability. 2) Add mt8186 into this patchset, It may be helpful for maintainer to apply. v6: https://lore.kernel.org/linux-iommu/20220407075726.17771-1-yong...@mediatek.com/ Rebase on v5.18-rc1. v5: https://lore.kernel.org/linux-iommu/20220217113453.13658-1-yong...@mediatek.com 1) Base on next-20220216 2) Remove a patch for kmalloc for protect buffer. keep the kzalloc for it. 3) minor fix from AngeloGioacchino, like rename the error label name (data_unlock to err_unlock). Note, keep the TODO for component compare_of[26/34]. v4: https://lore.kernel.org/linux-iommu/20220125085634.17972-1-yong...@mediatek.com/ 1) Base on v5.16-rc1 2) Base on tlb logic 2 patchset, some patches in v3 has already gone through that patchset. 3) Due to the unreadable union for v1/v2(comment in 26/33 of v3), I separate mtk_iommu_data for v1 and v2 totally, then remove mtk_iommu.h. please see patch[26/35][27/35]. 4) add two mutex for the internal data. patch[6/35][7/35]. 5) add a new flag PM_CLK_AO. v3: https://lore.kernel.org/linux-mediatek/20210923115840.17813-1-yong...@mediatek.com/ 1) base on v5.15-rc1 2) Adjust devlink with smi-common, not use the property(sub-sommon). 3) Adjust tlb_flush_all flow, a) Fix tlb_flush_all only is supported in bank0. b) add tlb-flush-all in the resume callback. c) remove the pm status checking in tlb-flush-all. The reason are showed in the commit message. 4) Allow IOMMU_DOMAIN_UNMANAGED since PCIe VFIO use that. 5) Fix a clk warning and a null abort when unbind the iommu driver. v2: https://lore.kernel.org/linux-mediatek/20210813065324.29220-1-yong...@mediatek.com/ 1) Base on v5.14-rc1. 2) Fix build fail for arm32. 3) Fix dt-binding issue from Rob. 4) Fix the bank issue when tlb flush. v1 always use bank->base. 5) adjust devlink with smi-common since the node may be smi-sub-common. 6) other changes: like reword some commit message(removing many "This patch..."); seperate serveral patches. v1: https://lore.kernel.org/linux-mediatek/20210630023504.18177-1-yong...@mediatek.com/ Base on v5.13-rc1 Yong Wu (36): dt-bindings: mediatek: mt8195: Add binding for MM IOMMU dt-bindings: mediatek: mt8195: Add binding for infra IOMMU dt-bindings: mediatek: mt8186: Add binding for MM iommu iommu/mediatek: Fix 2 HW sharing pgtable issue iommu/mediatek: Add list_del in mtk_iommu_remove iommu/mediatek: Remove clk_disable in mtk_iommu_remove iommu/mediatek: Add mutex for m4u_group and m4u_dom in data iommu/mediatek: Add mutex for data in the mtk_iommu_domain iommu/mediatek: Adapt sharing and non-sharing pgtable case iommu/mediatek: Add 12G~16G support for multi domains iommu/mediatek: Add a flag DCM_DISABLE iommu/mediatek: Add a flag STD_AXI_MODE iommu/mediatek: Remove the granule in the tlb flush iommu/mediatek: Always enable output PA over 32bits in isr iommu/mediatek: Add SUB_COMMON_3BITS flag iommu/mediatek: Add IOMMU_TYPE flag iommu/mediatek: Contain MM IOMMU flow with the MM TYPE iommu/mediatek: Adjust device link when it is sub-common iommu/mediatek: Allow IOMMU_DOMAIN_UNMANAGED for PCIe VFIO iommu/mediatek: Add a PM_CLK_AO flag for infra iommu iommu/mediatek: Add infra iommu support
Re: [PATCH v6 31/34] iommu/mediatek: Get the proper bankid for multi banks
Hi Matthias, Thanks very much for reviewing. On Thu, 2022-04-28 at 16:14 +0200, Matthias Brugger wrote: > > On 07/04/2022 09:57, Yong Wu wrote: > > We preassign some ports in a special bank via the new defined > > banks_portmsk. Put it in the plat_data means it is not expected to > > be > > adjusted dynamically. > > > > If the iommu id in the iommu consumer's dtsi node is inside this > > banks_portmsk, then we switch it to this special iommu bank, and > > initialise the IOMMU bank HW. > > > > Each a bank has the independent pgtable(4GB iova range). Each a > > bank > > is a independent iommu domain/group. Currently we don't separate > > different > > iova ranges inside a bank. > > > > Signed-off-by: Yong Wu > > Reviewed-by: AngeloGioacchino Del Regno < > > angelogioacchino.delre...@collabora.com> > > --- > > drivers/iommu/mtk_iommu.c | 39 > > --- > > 1 file changed, 36 insertions(+), 3 deletions(-) > > > > diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c > > index 0828cff97625..d42b3d35a36e 100644 > > --- a/drivers/iommu/mtk_iommu.c > > +++ b/drivers/iommu/mtk_iommu.c [snip] > > @@ -802,6 +828,7 @@ static struct iommu_group > > *mtk_iommu_device_group(struct device *dev) > > struct mtk_iommu_data *c_data = dev_iommu_priv_get(dev), *data; > > struct list_head *hw_list = c_data->hw_list; > > struct iommu_group *group; > > + unsigned int bankid, groupid; > > int regionid; > > > > data = mtk_iommu_get_frst_data(hw_list); > > @@ -812,12 +839,18 @@ static struct iommu_group > > *mtk_iommu_device_group(struct device *dev) > > if (regionid < 0) > > return ERR_PTR(regionid); > > > > + bankid = mtk_iommu_get_bank_id(dev, data->plat_data); > > I think code readability would be improved if we add a new function > like > mtk_iommu_get_id which call mtk_iommu_get_bankid and if necessary > mtk_iommu_get_regionid. OK, I will define a new function, like mtk_iommu_get_group_id for the readability. > > > mutex_lock(&data->mutex); > > - group = data->m4u_group[regionid]; > > + /* > > +* If the bank function is enabled, each a bank is a iommu > > group/domain. > > +* otherwise, each a iova region is a iommu group/domain. > > While at it: > "If the bank function is enabled, each bank is a iommu group/domain. > Otherwise, > each iova region is a iommu group/domain." And move this comment into the new funtion. Also of course, I will fix the other two comments and send v7. Thanks. > > Regards, > Matthias > > > +*/ > > + groupid = bankid ? bankid : regionid; > > + group = data->m4u_group[groupid]; > > if (!group) { > > group = iommu_group_alloc(); > > if (!IS_ERR(group)) > > - data->m4u_group[regionid] = group; > > + data->m4u_group[groupid] = group; > > } else { > > iommu_group_ref_get(group); > > } ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH v2] iommu/mediatek: fix NULL pointer dereference when printing dev_name
On Mon, 2022-04-25 at 11:03 +0100, Robin Murphy wrote: > On 2022-04-25 09:24, Miles Chen via iommu wrote: > > When larbdev is NULL (in the case I hit, the node is incorrectly > > set > > iommus = <&iommu NUM>), it will cause device_link_add() fail and > > kernel crashes when we try to print dev_name(larbdev). > > > > Fix it by adding a NULL pointer check before > > device_link_add/device_link_remove. > > > > It should work for normal correct setting and avoid the crash > > caused > > by my incorrect setting. > > > > Error log: > > [ 18.189042][ T301] Unable to handle kernel NULL pointer > > dereference at virtual address 0050 > > [ 18.190247][ T301] Mem abort info: > > [ 18.190255][ T301] ESR = 0x9605 > > [ 18.190263][ T301] EC = 0x25: DABT (current EL), IL = 32 bits > > [ 18.192142][ T301] SET = 0, FnV = 0 > > [ 18.192151][ T301] EA = 0, S1PTW = 0 > > [ 18.194710][ T301] FSC = 0x05: level 1 translation fault > > [ 18.195424][ T301] Data abort info: > > [ 18.195888][ T301] ISV = 0, ISS = 0x0005 > > [ 18.196500][ T301] CM = 0, WnR = 0 > > [ 18.196977][ T301] user pgtable: 4k pages, 39-bit VAs, > > pgdp=000104f9e000 > > [ 18.197889][ T301] [0050] pgd=, > > p4d=, pud= > > [ 18.199220][ T301] Internal error: Oops: 9605 [#1] PREEMPT > > SMP > > [ 18.343152][ T301] Kernel Offset: 0x144408 from > > 0xffc00800 > > [ 18.343988][ T301] PHYS_OFFSET: 0x4000 > > [ 18.344519][ T301] pstate: a045 (NzCv daif +PAN -UAO) > > [ 18.345213][ T301] pc : mtk_iommu_probe_device+0xf8/0x118 > > [mtk_iommu] > > [ 18.346050][ T301] lr : mtk_iommu_probe_device+0xd0/0x118 > > [mtk_iommu] > > [ 18.346884][ T301] sp : ffc00a5635e0 > > [ 18.347392][ T301] x29: ffc00a5635e0 x28: ffd44a46c1d8 > > [ 18.348156][ T301] x27: ff80c39a8000 x26: ffd44a80cc38 > > [ 18.348917][ T301] x25: x24: ffd44a80cc38 > > [ 18.349677][ T301] x23: ffd44e4da4c6 x22: ffd44a80cc38 > > [ 18.350438][ T301] x21: ff80cecd1880 x20: > > [ 18.351198][ T301] x19: ff80c439f010 x18: ffc00a50d0c0 > > [ 18.351959][ T301] x17: x16: 0004 > > [ 18.352719][ T301] x15: 0004 x14: ffd44eb5d420 > > [ 18.353480][ T301] x13: 0ad2 x12: 0003 > > [ 18.354241][ T301] x11: fad2 x10: c000fad2 > > [ 18.355003][ T301] x9 : a0d288d8d7142d00 x8 : a0d288d8d7142d00 > > [ 18.355763][ T301] x7 : ffd44c2bc640 x6 : > > [ 18.356524][ T301] x5 : 0080 x4 : 0001 > > [ 18.357284][ T301] x3 : x2 : 0005 > > [ 18.358045][ T301] x1 : x0 : > > [ 18.360208][ T301] Hardware name: MT6873 (DT) > > [ 18.360771][ T301] Call trace: > > [ 18.361168][ T301] dump_backtrace+0xf8/0x1f0 > > [ 18.361737][ T301] dump_stack_lvl+0xa8/0x11c > > [ 18.362305][ T301] dump_stack+0x1c/0x2c > > [ 18.362816][ T301] mrdump_common_die+0x184/0x40c [mrdump] > > [ 18.363575][ T301] ipanic_die+0x24/0x38 [mrdump] > > [ 18.364230][ T301] atomic_notifier_call_chain+0x128/0x2b8 > > [ 18.364937][ T301] die+0x16c/0x568 > > [ 18.365394][ T301] __do_kernel_fault+0x1e8/0x214 > > [ 18.365402][ T301] do_page_fault+0xb8/0x678 > > [ 18.366934][ T301] do_translation_fault+0x48/0x64 > > [ 18.368645][ T301] do_mem_abort+0x68/0x148 > > [ 18.368652][ T301] el1_abort+0x40/0x64 > > [ 18.368660][ T301] el1h_64_sync_handler+0x54/0x88 > > [ 18.368668][ T301] el1h_64_sync+0x68/0x6c > > [ 18.368673][ T301] mtk_iommu_probe_device+0xf8/0x118 > > [mtk_iommu] > > [ 18.369840][ T301] __iommu_probe_device+0x12c/0x358 > > [ 18.370880][ T301] iommu_probe_device+0x3c/0x31c > > [ 18.372026][ T301] of_iommu_configure+0x200/0x274 > > [ 18.373587][ T301] of_dma_configure_id+0x1b8/0x230 > > [ 18.375200][ T301] platform_dma_configure+0x24/0x3c > > [ 18.376456][ T301] really_probe+0x110/0x504 > > [ 18.376464][ T301] __driver_probe_device+0xb4/0x188 > > [ 18.376472][ T301] driver_probe_device+0x5c/0x2b8 > > [ 18.376481][ T301] __driver_attach+0x338/0x42c > > [ 18.377992][ T301] bus_add_driver+0x218/0x4c8 > > [ 18.379389][ T301] driver_register+0x84/0x17c > > [ 18.380580][ T301] __platform_driver_register+0x28/0x38 > > ... > > > > Reported-by: kernel test robot > > Fixes: 635319a4a744 ("media: iommu/mediatek: Add device_link > > between the consumer and the larb devices") > > Signed-off-by: Miles Chen > > > > --- > > > > Change since v1 > > fix a build warning reported by kernel test robot > > https://lore.kernel.org/lkml/202204231446.iykdz674-...@intel.com/ > > > > --- > > drivers/iommu/mtk_iommu.c| 13 - > > drivers/iommu/mtk_iommu_v1.c | 13
[PATCH v3 2/2] iommu/mediatek: Add mt8186 iommu support
Add mt8186 iommu supports. Signed-off-by: Anan Sun Signed-off-by: Yong Wu Reviewed-by: Matthias Brugger --- drivers/iommu/mtk_iommu.c | 17 + 1 file changed, 17 insertions(+) diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c index 22c95ed78b3c..8d2b6dc89177 100644 --- a/drivers/iommu/mtk_iommu.c +++ b/drivers/iommu/mtk_iommu.c @@ -160,6 +160,7 @@ enum mtk_iommu_plat { M4U_MT8167, M4U_MT8173, M4U_MT8183, + M4U_MT8186, M4U_MT8192, M4U_MT8195, }; @@ -1429,6 +1430,21 @@ static const struct mtk_iommu_plat_data mt8183_data = { .larbid_remap = {{0}, {4}, {5}, {6}, {7}, {2}, {3}, {1}}, }; +static const struct mtk_iommu_plat_data mt8186_data_mm = { + .m4u_plat = M4U_MT8186, + .flags = HAS_BCLK | HAS_SUB_COMM_2BITS | OUT_ORDER_WR_EN | + WR_THROT_EN | IOVA_34_EN | NOT_STD_AXI_MODE | + MTK_IOMMU_TYPE_MM, + .larbid_remap = {{0}, {1, MTK_INVALID_LARBID, 8}, {4}, {7}, {2}, {9, 11, 19, 20}, + {MTK_INVALID_LARBID, 14, 16}, + {MTK_INVALID_LARBID, 13, MTK_INVALID_LARBID, 17}}, + .inv_sel_reg= REG_MMU_INV_SEL_GEN2, + .banks_num = 1, + .banks_enable = {true}, + .iova_region= mt8192_multi_dom, + .iova_region_nr = ARRAY_SIZE(mt8192_multi_dom), +}; + static const struct mtk_iommu_plat_data mt8192_data = { .m4u_plat = M4U_MT8192, .flags = HAS_BCLK | HAS_SUB_COMM_2BITS | OUT_ORDER_WR_EN | @@ -1498,6 +1514,7 @@ static const struct of_device_id mtk_iommu_of_ids[] = { { .compatible = "mediatek,mt8167-m4u", .data = &mt8167_data}, { .compatible = "mediatek,mt8173-m4u", .data = &mt8173_data}, { .compatible = "mediatek,mt8183-m4u", .data = &mt8183_data}, + { .compatible = "mediatek,mt8186-iommu-mm",.data = &mt8186_data_mm}, /* mm: m4u */ { .compatible = "mediatek,mt8192-m4u", .data = &mt8192_data}, { .compatible = "mediatek,mt8195-iommu-infra", .data = &mt8195_data_infra}, { .compatible = "mediatek,mt8195-iommu-vdo", .data = &mt8195_data_vdo}, -- 2.18.0 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH v3 1/2] dt-bindings: mediatek: mt8186: Add binding for MM iommu
Add mt8186 iommu binding. "-mm" means the iommu is for Multimedia. Signed-off-by: Yong Wu Acked-by: Krzysztof Kozlowski Reviewed-by: Rob Herring Reviewed-by: Matthias Brugger --- .../bindings/iommu/mediatek,iommu.yaml| 4 + .../dt-bindings/memory/mt8186-memory-port.h | 217 ++ 2 files changed, 221 insertions(+) create mode 100644 include/dt-bindings/memory/mt8186-memory-port.h diff --git a/Documentation/devicetree/bindings/iommu/mediatek,iommu.yaml b/Documentation/devicetree/bindings/iommu/mediatek,iommu.yaml index eed59ec00e78..91a3629a8e6e 100644 --- a/Documentation/devicetree/bindings/iommu/mediatek,iommu.yaml +++ b/Documentation/devicetree/bindings/iommu/mediatek,iommu.yaml @@ -76,6 +76,7 @@ properties: - mediatek,mt8167-m4u # generation two - mediatek,mt8173-m4u # generation two - mediatek,mt8183-m4u # generation two + - mediatek,mt8186-iommu-mm # generation two - mediatek,mt8192-m4u # generation two - mediatek,mt8195-iommu-vdo# generation two - mediatek,mt8195-iommu-vpp# generation two @@ -122,6 +123,7 @@ properties: dt-binding/memory/mt8167-larb-port.h for mt8167, dt-binding/memory/mt8173-larb-port.h for mt8173, dt-binding/memory/mt8183-larb-port.h for mt8183, + dt-binding/memory/mt8186-memory-port.h for mt8186, dt-binding/memory/mt8192-larb-port.h for mt8192. dt-binding/memory/mt8195-memory-port.h for mt8195. @@ -143,6 +145,7 @@ allOf: - mediatek,mt2701-m4u - mediatek,mt2712-m4u - mediatek,mt8173-m4u + - mediatek,mt8186-iommu-mm - mediatek,mt8192-m4u - mediatek,mt8195-iommu-vdo - mediatek,mt8195-iommu-vpp @@ -155,6 +158,7 @@ allOf: properties: compatible: enum: +- mediatek,mt8186-iommu-mm - mediatek,mt8192-m4u - mediatek,mt8195-iommu-vdo - mediatek,mt8195-iommu-vpp diff --git a/include/dt-bindings/memory/mt8186-memory-port.h b/include/dt-bindings/memory/mt8186-memory-port.h new file mode 100644 index ..2bc6e4433048 --- /dev/null +++ b/include/dt-bindings/memory/mt8186-memory-port.h @@ -0,0 +1,217 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2022 MediaTek Inc. + * + * Author: Anan Sun + * Author: Yong Wu + */ +#ifndef _DT_BINDINGS_MEMORY_MT8186_LARB_PORT_H_ +#define _DT_BINDINGS_MEMORY_MT8186_LARB_PORT_H_ + +#include + +/* + * MM IOMMU supports 16GB dma address. We separate it to four ranges: + * 0 ~ 4G; 4G ~ 8G; 8G ~ 12G; 12G ~ 16G, we could adjust these masters + * locate in anyone region. BUT: + * a) Make sure all the ports inside a larb are in one range. + * b) The iova of any master can NOT cross the 4G/8G/12G boundary. + * + * This is the suggested mapping in this SoC: + * + * modulesdma-address-region larbs-ports + * disp 0 ~ 4G larb0/1/2 + * vcodec 4G ~ 8G larb4/7 + * cam/mdp 8G ~ 12G the other larbs. + * N/A 12G ~ 16G + * CCU0 0x24000_ ~ 0x243ff_ larb13: port 9/10 + * CCU1 0x24400_ ~ 0x247ff_ larb14: port 4/5 + */ + +/* MM IOMMU ports */ +/* LARB 0 -- MMSYS */ +#define IOMMU_PORT_L0_DISP_POSTMASK0 MTK_M4U_ID(0, 0) +#define IOMMU_PORT_L0_REVERSED MTK_M4U_ID(0, 1) +#define IOMMU_PORT_L0_OVL_RDMA0MTK_M4U_ID(0, 2) +#define IOMMU_PORT_L0_DISP_FAKE0 MTK_M4U_ID(0, 3) + +/* LARB 1 -- MMSYS */ +#define IOMMU_PORT_L1_DISP_RDMA1 MTK_M4U_ID(1, 0) +#define IOMMU_PORT_L1_OVL_2L_RDMA0 MTK_M4U_ID(1, 1) +#define IOMMU_PORT_L1_DISP_RDMA0 MTK_M4U_ID(1, 2) +#define IOMMU_PORT_L1_DISP_WDMA0 MTK_M4U_ID(1, 3) +#define IOMMU_PORT_L1_DISP_FAKE1 MTK_M4U_ID(1, 4) + +/* LARB 2 -- MMSYS */ +#define IOMMU_PORT_L2_MDP_RDMA0MTK_M4U_ID(2, 0) +#define IOMMU_PORT_L2_MDP_RDMA1MTK_M4U_ID(2, 1) +#define IOMMU_PORT_L2_MDP_WROT0MTK_M4U_ID(2, 2) +#define IOMMU_PORT_L2_MDP_WROT1MTK_M4U_ID(2, 3) +#define IOMMU_PORT_L2_DISP_FAKE0 MTK_M4U_ID(2, 4) + +/* LARB 4 -- VDEC */ +#define IOMMU_PORT_L4_HW_VDEC_MC_EXT MTK_M4U_ID(4, 0) +#define IOMMU_PORT_L4_HW_VDEC_UFO_EXT MTK_M4U_ID(4, 1) +#define IOMMU_PORT_L4_HW_VDEC_PP_EXT MTK_M4U_ID(4, 2) +#define IOMMU_PORT_L4_HW_VDEC_PRED_RD_EXT MTK_M4U_ID(4, 3) +#define IOMMU_PORT_L4_HW_VDEC_PRED_WR_EXT MTK_M4U_ID(4, 4) +#define IOMMU_PORT_L4_HW_VDEC_PPWRAP_EXT MTK_M4U_ID(4, 5) +#define IOMMU_PORT_L4_HW_VDEC_TILE_EXT MTK_M4U_ID(4, 6) +#define IOMMU_PORT_L4_HW_VDEC_VLD_EXT MTK_M4U_ID(4, 7) +#define IOMMU_PORT_L4_HW_VDEC_VLD2_EXT MTK_M4U_ID(4, 8) +#define IOMMU_PORT_L4_HW_VDEC_AVC_MV_EXT MTK_M4U_ID(4, 9) +#define IOMMU_PORT_L4_HW_VDEC_UFO_ENC_EXT MTK_M4U_ID(4, 10) +#define IOMMU_PORT_L4_HW_VDEC_
[PATCH v3 0/2] MT8186 IOMMU SUPPORT
This patchset adds mt8186 iommu support. Change note: v3: Rebase on v5.18-rc1 and mt8195 iommu v6: https://lore.kernel.org/linux-iommu/20220407075726.17771-1-yong...@mediatek.com/ v2: https://lore.kernel.org/linux-iommu/20220223072402.17518-1-yong...@mediatek.com/ a)Base on v5.17-rc1 and mt8195 iommu v5. b)Add a comment "mm: m4u" in the code for readable. v1: https://lore.kernel.org/linux-mediatek/20220125093244.18230-1-yong...@mediatek.com/ Yong Wu (2): dt-bindings: mediatek: mt8186: Add binding for MM iommu iommu/mediatek: Add mt8186 iommu support .../bindings/iommu/mediatek,iommu.yaml| 4 + drivers/iommu/mtk_iommu.c | 17 ++ .../dt-bindings/memory/mt8186-memory-port.h | 217 ++ 3 files changed, 238 insertions(+) create mode 100644 include/dt-bindings/memory/mt8186-memory-port.h -- 2.18.0 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH v6 34/34] iommu/mediatek: mt8195: Enable multi banks for infra iommu
Enable the multi-bank functions for infra-iommu. We put PCIE in bank0 and USB in the last bank(bank4). and we don't use the other banks currently, disable them. Signed-off-by: Yong Wu Reviewed-by: AngeloGioacchino Del Regno --- drivers/iommu/mtk_iommu.c | 7 +-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c index 027bbbced80d..22c95ed78b3c 100644 --- a/drivers/iommu/mtk_iommu.c +++ b/drivers/iommu/mtk_iommu.c @@ -1449,8 +1449,11 @@ static const struct mtk_iommu_plat_data mt8195_data_infra = { MTK_IOMMU_TYPE_INFRA | IFA_IOMMU_PCIE_SUPPORT, .pericfg_comp_str = "mediatek,mt8195-pericfg_ao", .inv_sel_reg = REG_MMU_INV_SEL_GEN2, - .banks_num= 1, - .banks_enable = {true}, + .banks_num= 5, + .banks_enable = {true, false, false, false, true}, + .banks_portmsk= {[0] = GENMASK(19, 16), /* PCIe */ +[4] = GENMASK(31, 20), /* USB */ + }, .iova_region = single_domain, .iova_region_nr = ARRAY_SIZE(single_domain), }; -- 2.18.0 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH v6 33/34] iommu/mediatek: Backup/restore regsiters for multi banks
Each bank has some independent registers. thus backup/restore them for each a bank when suspend and resume. Signed-off-by: Yong Wu Reviewed-by: AngeloGioacchino Del Regno --- drivers/iommu/mtk_iommu.c | 46 ++- 1 file changed, 31 insertions(+), 15 deletions(-) diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c index 028dc642a31e..027bbbced80d 100644 --- a/drivers/iommu/mtk_iommu.c +++ b/drivers/iommu/mtk_iommu.c @@ -173,11 +173,12 @@ struct mtk_iommu_suspend_reg { u32 misc_ctrl; u32 dcm_dis; u32 ctrl_reg; - u32 int_control0; - u32 int_main_control; - u32 ivrp_paddr; u32 vld_pa_rng; u32 wr_len_ctrl; + + u32 int_control[MTK_IOMMU_BANK_MAX]; + u32 int_main_control[MTK_IOMMU_BANK_MAX]; + u32 ivrp_paddr[MTK_IOMMU_BANK_MAX]; }; struct mtk_iommu_plat_data { @@ -1292,16 +1293,23 @@ static int __maybe_unused mtk_iommu_runtime_suspend(struct device *dev) { struct mtk_iommu_data *data = dev_get_drvdata(dev); struct mtk_iommu_suspend_reg *reg = &data->reg; - void __iomem *base = data->bank[0].base; + void __iomem *base; + int i = 0; + base = data->bank[i].base; reg->wr_len_ctrl = readl_relaxed(base + REG_MMU_WR_LEN_CTRL); reg->misc_ctrl = readl_relaxed(base + REG_MMU_MISC_CTRL); reg->dcm_dis = readl_relaxed(base + REG_MMU_DCM_DIS); reg->ctrl_reg = readl_relaxed(base + REG_MMU_CTRL_REG); - reg->int_control0 = readl_relaxed(base + REG_MMU_INT_CONTROL0); - reg->int_main_control = readl_relaxed(base + REG_MMU_INT_MAIN_CONTROL); - reg->ivrp_paddr = readl_relaxed(base + REG_MMU_IVRP_PADDR); reg->vld_pa_rng = readl_relaxed(base + REG_MMU_VLD_PA_RNG); + do { + if (!data->plat_data->banks_enable[i]) + continue; + base = data->bank[i].base; + reg->int_control[i] = readl_relaxed(base + REG_MMU_INT_CONTROL0); + reg->int_main_control[i] = readl_relaxed(base + REG_MMU_INT_MAIN_CONTROL); + reg->ivrp_paddr[i] = readl_relaxed(base + REG_MMU_IVRP_PADDR); + } while (++i < data->plat_data->banks_num); clk_disable_unprepare(data->bclk); return 0; } @@ -1310,9 +1318,9 @@ static int __maybe_unused mtk_iommu_runtime_resume(struct device *dev) { struct mtk_iommu_data *data = dev_get_drvdata(dev); struct mtk_iommu_suspend_reg *reg = &data->reg; - struct mtk_iommu_domain *m4u_dom = data->bank[0].m4u_dom; - void __iomem *base = data->bank[0].base; - int ret; + struct mtk_iommu_domain *m4u_dom; + void __iomem *base; + int ret, i = 0; ret = clk_prepare_enable(data->bclk); if (ret) { @@ -1324,18 +1332,26 @@ static int __maybe_unused mtk_iommu_runtime_resume(struct device *dev) * Uppon first resume, only enable the clk and return, since the values of the * registers are not yet set. */ - if (!m4u_dom) + if (!reg->wr_len_ctrl) return 0; + base = data->bank[i].base; writel_relaxed(reg->wr_len_ctrl, base + REG_MMU_WR_LEN_CTRL); writel_relaxed(reg->misc_ctrl, base + REG_MMU_MISC_CTRL); writel_relaxed(reg->dcm_dis, base + REG_MMU_DCM_DIS); writel_relaxed(reg->ctrl_reg, base + REG_MMU_CTRL_REG); - writel_relaxed(reg->int_control0, base + REG_MMU_INT_CONTROL0); - writel_relaxed(reg->int_main_control, base + REG_MMU_INT_MAIN_CONTROL); - writel_relaxed(reg->ivrp_paddr, base + REG_MMU_IVRP_PADDR); writel_relaxed(reg->vld_pa_rng, base + REG_MMU_VLD_PA_RNG); - writel(m4u_dom->cfg.arm_v7s_cfg.ttbr & MMU_PT_ADDR_MASK, base + REG_MMU_PT_BASE_ADDR); + do { + m4u_dom = data->bank[i].m4u_dom; + if (!data->plat_data->banks_enable[i] || !m4u_dom) + continue; + base = data->bank[i].base; + writel_relaxed(reg->int_control[i], base + REG_MMU_INT_CONTROL0); + writel_relaxed(reg->int_main_control[i], base + REG_MMU_INT_MAIN_CONTROL); + writel_relaxed(reg->ivrp_paddr[i], base + REG_MMU_IVRP_PADDR); + writel(m4u_dom->cfg.arm_v7s_cfg.ttbr & MMU_PT_ADDR_MASK, + base + REG_MMU_PT_BASE_ADDR); + } while (++i < data->plat_data->banks_num); /* * Users may allocate dma buffer before they call pm_runtime_get, -- 2.18.0 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH v6 32/34] iommu/mediatek: Initialise/Remove for multi bank dev
The registers for each bank of the IOMMU base are in order, delta is 0x1000. Initialise the base for each bank. For all the previous SoC, we only have bank0. thus use "do {} while()" to allow bank0 always go. When removing the device, Not always all the banks are initialised, it depend on if there is masters for that bank. Signed-off-by: Yong Wu Reviewed-by: AngeloGioacchino Del Regno --- drivers/iommu/mtk_iommu.c | 44 ++- 1 file changed, 30 insertions(+), 14 deletions(-) diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c index d42b3d35a36e..028dc642a31e 100644 --- a/drivers/iommu/mtk_iommu.c +++ b/drivers/iommu/mtk_iommu.c @@ -113,6 +113,7 @@ #define F_MMU_INT_ID_PORT_ID(a)(((a) >> 2) & 0x1f) #define MTK_PROTECT_PA_ALIGN 256 +#define MTK_IOMMU_BANK_SZ 0x1000 #define PERICFG_IOMMU_10x714 @@ -1104,7 +1105,7 @@ static int mtk_iommu_probe(struct platform_device *pdev) struct component_match *match = NULL; struct regmap *infracfg; void*protect; - int ret, banks_num; + int ret, banks_num, i = 0; u32 val; char*p; struct mtk_iommu_bank_data *bank; @@ -1145,27 +1146,36 @@ static int mtk_iommu_probe(struct platform_device *pdev) data->enable_4GB = !!(val & F_DDR_4GB_SUPPORT_EN); } + banks_num = data->plat_data->banks_num; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (resource_size(res) < banks_num * MTK_IOMMU_BANK_SZ) { + dev_err(dev, "banknr %d. res %pR is not enough.\n", banks_num, res); + return -EINVAL; + } base = devm_ioremap_resource(dev, res); if (IS_ERR(base)) return PTR_ERR(base); ioaddr = res->start; - banks_num = data->plat_data->banks_num; data->bank = devm_kmalloc(dev, banks_num * sizeof(*data->bank), GFP_KERNEL); if (!data->bank) return -ENOMEM; - bank = &data->bank[0]; - bank->id = 0; - bank->base = base; - bank->m4u_dom = NULL; - bank->irq = platform_get_irq(pdev, 0); - if (bank->irq < 0) - return bank->irq; - bank->parent_dev = dev; - bank->parent_data = data; - spin_lock_init(&bank->tlb_lock); + do { + if (!data->plat_data->banks_enable[i]) + continue; + bank = &data->bank[i]; + bank->id = i; + bank->base = base + i * MTK_IOMMU_BANK_SZ; + bank->m4u_dom = NULL; + + bank->irq = platform_get_irq(pdev, i); + if (bank->irq < 0) + return bank->irq; + bank->parent_dev = dev; + bank->parent_data = data; + spin_lock_init(&bank->tlb_lock); + } while (++i < banks_num); if (MTK_IOMMU_HAS_FLAG(data->plat_data, HAS_BCLK)) { data->bclk = devm_clk_get(dev, "bclk"); @@ -1251,7 +1261,8 @@ static int mtk_iommu_probe(struct platform_device *pdev) static int mtk_iommu_remove(struct platform_device *pdev) { struct mtk_iommu_data *data = platform_get_drvdata(pdev); - struct mtk_iommu_bank_data *bank = &data->bank[0]; + struct mtk_iommu_bank_data *bank; + int i; iommu_device_sysfs_remove(&data->iommu); iommu_device_unregister(&data->iommu); @@ -1268,7 +1279,12 @@ static int mtk_iommu_remove(struct platform_device *pdev) #endif } pm_runtime_disable(&pdev->dev); - devm_free_irq(&pdev->dev, bank->irq, bank); + for (i = 0; i < data->plat_data->banks_num; i++) { + bank = &data->bank[i]; + if (!bank->m4u_dom) + continue; + devm_free_irq(&pdev->dev, bank->irq, bank); + } return 0; } -- 2.18.0 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH v6 31/34] iommu/mediatek: Get the proper bankid for multi banks
We preassign some ports in a special bank via the new defined banks_portmsk. Put it in the plat_data means it is not expected to be adjusted dynamically. If the iommu id in the iommu consumer's dtsi node is inside this banks_portmsk, then we switch it to this special iommu bank, and initialise the IOMMU bank HW. Each a bank has the independent pgtable(4GB iova range). Each a bank is a independent iommu domain/group. Currently we don't separate different iova ranges inside a bank. Signed-off-by: Yong Wu Reviewed-by: AngeloGioacchino Del Regno --- drivers/iommu/mtk_iommu.c | 39 --- 1 file changed, 36 insertions(+), 3 deletions(-) diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c index 0828cff97625..d42b3d35a36e 100644 --- a/drivers/iommu/mtk_iommu.c +++ b/drivers/iommu/mtk_iommu.c @@ -191,6 +191,7 @@ struct mtk_iommu_plat_data { u8 banks_num; boolbanks_enable[MTK_IOMMU_BANK_MAX]; + unsigned intbanks_portmsk[MTK_IOMMU_BANK_MAX]; unsigned char larbid_remap[MTK_LARB_COM_MAX][MTK_LARB_SUBCOM_MAX]; }; @@ -467,6 +468,30 @@ static irqreturn_t mtk_iommu_isr(int irq, void *dev_id) return IRQ_HANDLED; } +static unsigned int mtk_iommu_get_bank_id(struct device *dev, + const struct mtk_iommu_plat_data *plat_data) +{ + struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev); + unsigned int i, portmsk = 0, bankid = 0; + + if (plat_data->banks_num == 1) + return bankid; + + for (i = 0; i < fwspec->num_ids; i++) + portmsk |= BIT(MTK_M4U_TO_PORT(fwspec->ids[i])); + + for (i = 0; i < plat_data->banks_num && i < MTK_IOMMU_BANK_MAX; i++) { + if (!plat_data->banks_enable[i]) + continue; + + if (portmsk & plat_data->banks_portmsk[i]) { + bankid = i; + break; + } + } + return bankid; /* default is 0 */ +} + static int mtk_iommu_get_iova_region_id(struct device *dev, const struct mtk_iommu_plat_data *plat_data) { @@ -619,13 +644,14 @@ static int mtk_iommu_attach_device(struct iommu_domain *domain, struct list_head *hw_list = data->hw_list; struct device *m4udev = data->dev; struct mtk_iommu_bank_data *bank; - unsigned int bankid = 0; + unsigned int bankid; int ret, region_id; region_id = mtk_iommu_get_iova_region_id(dev, data->plat_data); if (region_id < 0) return region_id; + bankid = mtk_iommu_get_bank_id(dev, data->plat_data); mutex_lock(&dom->mutex); if (!dom->bank) { /* Data is in the frstdata in sharing pgtable case. */ @@ -802,6 +828,7 @@ static struct iommu_group *mtk_iommu_device_group(struct device *dev) struct mtk_iommu_data *c_data = dev_iommu_priv_get(dev), *data; struct list_head *hw_list = c_data->hw_list; struct iommu_group *group; + unsigned int bankid, groupid; int regionid; data = mtk_iommu_get_frst_data(hw_list); @@ -812,12 +839,18 @@ static struct iommu_group *mtk_iommu_device_group(struct device *dev) if (regionid < 0) return ERR_PTR(regionid); + bankid = mtk_iommu_get_bank_id(dev, data->plat_data); mutex_lock(&data->mutex); - group = data->m4u_group[regionid]; + /* +* If the bank function is enabled, each a bank is a iommu group/domain. +* otherwise, each a iova region is a iommu group/domain. +*/ + groupid = bankid ? bankid : regionid; + group = data->m4u_group[groupid]; if (!group) { group = iommu_group_alloc(); if (!IS_ERR(group)) - data->m4u_group[regionid] = group; + data->m4u_group[groupid] = group; } else { iommu_group_ref_get(group); } -- 2.18.0 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH v6 30/34] iommu/mediatek: Change the domid to iova_region_id
Prepare for adding bankid, also no functional change. In the previous SoC, each a iova_region is a domain; In the multi-banks case, each a bank is a domain, then the original function name "mtk_iommu_get_domain_id" is not proper. Use "iova_region_id" instead of "domain_id". Signed-off-by: Yong Wu Reviewed-by: AngeloGioacchino Del Regno --- drivers/iommu/mtk_iommu.c | 46 +++ 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c index 9c27b99ca0cd..0828cff97625 100644 --- a/drivers/iommu/mtk_iommu.c +++ b/drivers/iommu/mtk_iommu.c @@ -467,8 +467,8 @@ static irqreturn_t mtk_iommu_isr(int irq, void *dev_id) return IRQ_HANDLED; } -static int mtk_iommu_get_domain_id(struct device *dev, - const struct mtk_iommu_plat_data *plat_data) +static int mtk_iommu_get_iova_region_id(struct device *dev, + const struct mtk_iommu_plat_data *plat_data) { const struct mtk_iommu_iova_region *rgn = plat_data->iova_region; const struct bus_dma_region *dma_rgn = dev->dma_range_map; @@ -498,7 +498,7 @@ static int mtk_iommu_get_domain_id(struct device *dev, } static int mtk_iommu_config(struct mtk_iommu_data *data, struct device *dev, - bool enable, unsigned int domid) + bool enable, unsigned int regionid) { struct mtk_smi_larb_iommu*larb_mmu; unsigned int larbid, portid; @@ -514,12 +514,12 @@ static int mtk_iommu_config(struct mtk_iommu_data *data, struct device *dev, if (MTK_IOMMU_IS_TYPE(data->plat_data, MTK_IOMMU_TYPE_MM)) { larb_mmu = &data->larb_imu[larbid]; - region = data->plat_data->iova_region + domid; + region = data->plat_data->iova_region + regionid; larb_mmu->bank[portid] = upper_32_bits(region->iova_base); - dev_dbg(dev, "%s iommu for larb(%s) port %d dom %d bank %d.\n", + dev_dbg(dev, "%s iommu for larb(%s) port %d region %d rgn-bank %d.\n", enable ? "enable" : "disable", dev_name(larb_mmu->dev), - portid, domid, larb_mmu->bank[portid]); + portid, regionid, larb_mmu->bank[portid]); if (enable) larb_mmu->mmu |= MTK_SMI_MMU_EN(portid); @@ -545,7 +545,7 @@ static int mtk_iommu_config(struct mtk_iommu_data *data, struct device *dev, static int mtk_iommu_domain_finalise(struct mtk_iommu_domain *dom, struct mtk_iommu_data *data, -unsigned int domid) +unsigned int region_id) { const struct mtk_iommu_iova_region *region; struct mtk_iommu_domain *m4u_dom; @@ -584,7 +584,7 @@ static int mtk_iommu_domain_finalise(struct mtk_iommu_domain *dom, update_iova_region: /* Update the iova region for this domain */ - region = data->plat_data->iova_region + domid; + region = data->plat_data->iova_region + region_id; dom->domain.geometry.aperture_start = region->iova_base; dom->domain.geometry.aperture_end = region->iova_base + region->size - 1; dom->domain.geometry.force_aperture = true; @@ -620,18 +620,18 @@ static int mtk_iommu_attach_device(struct iommu_domain *domain, struct device *m4udev = data->dev; struct mtk_iommu_bank_data *bank; unsigned int bankid = 0; - int ret, domid; + int ret, region_id; - domid = mtk_iommu_get_domain_id(dev, data->plat_data); - if (domid < 0) - return domid; + region_id = mtk_iommu_get_iova_region_id(dev, data->plat_data); + if (region_id < 0) + return region_id; mutex_lock(&dom->mutex); if (!dom->bank) { /* Data is in the frstdata in sharing pgtable case. */ frstdata = mtk_iommu_get_frst_data(hw_list); - ret = mtk_iommu_domain_finalise(dom, frstdata, domid); + ret = mtk_iommu_domain_finalise(dom, frstdata, region_id); if (ret) { mutex_unlock(&dom->mutex); return -ENODEV; @@ -662,7 +662,7 @@ static int mtk_iommu_attach_device(struct iommu_domain *domain, } mutex_unlock(&data->mutex); - return mtk_iommu_config(data, dev, true, domid); + return mtk_iommu_config(data, dev, true, region_id); err_unlock: mutex_unlock(&data->mutex); @@ -802,22 +802,22 @@ static struct iommu_group *mtk_iommu_device_group(struct device *dev) struct mtk_iommu_data *c_data = dev_iommu_priv_get(dev), *data; struct list_head *hw_list = c_data->hw_list; struct iom
[PATCH v6 28/34] iommu/mediatek: Add mtk_iommu_bank_data structure
Prepare for supporting multi-banks for the IOMMU HW, No functional change. Add a new structure(mtk_iommu_bank_data) for each a bank. Each a bank have the independent HW base/IRQ/tlb-range ops, and each a bank has its special iommu-domain(independent pgtable), thus, also move the domain information into it. In previous SoC, we have only one bank which could be treated as bank0( bankid always is 0 for the previous SoC). After adding this structure, the tlb operations and irq could use bank_data as parameter. Signed-off-by: Yong Wu Reviewed-by: AngeloGioacchino Del Regno --- drivers/iommu/mtk_iommu.c | 179 +- 1 file changed, 117 insertions(+), 62 deletions(-) diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c index d46eb745492f..f2a29399f10f 100644 --- a/drivers/iommu/mtk_iommu.c +++ b/drivers/iommu/mtk_iommu.c @@ -151,6 +151,7 @@ #define MTK_LARB_SUBCOM_MAX8 #define MTK_IOMMU_GROUP_MAX8 +#define MTK_IOMMU_BANK_MAX 5 enum mtk_iommu_plat { M4U_MT2712, @@ -187,25 +188,36 @@ struct mtk_iommu_plat_data { struct list_head*hw_list; unsigned intiova_region_nr; const struct mtk_iommu_iova_region *iova_region; + + u8 banks_num; + boolbanks_enable[MTK_IOMMU_BANK_MAX]; unsigned char larbid_remap[MTK_LARB_COM_MAX][MTK_LARB_SUBCOM_MAX]; }; -struct mtk_iommu_data { +struct mtk_iommu_bank_data { void __iomem*base; int irq; + u8 id; + struct device *parent_dev; + struct mtk_iommu_data *parent_data; + spinlock_t tlb_lock; /* lock for tlb range flush */ + struct mtk_iommu_domain *m4u_dom; /* Each bank has a domain */ +}; + +struct mtk_iommu_data { struct device *dev; struct clk *bclk; phys_addr_t protect_base; /* protect memory base */ struct mtk_iommu_suspend_regreg; - struct mtk_iommu_domain *m4u_dom; struct iommu_group *m4u_group[MTK_IOMMU_GROUP_MAX]; boolenable_4GB; - spinlock_t tlb_lock; /* lock for tlb range flush */ struct iommu_device iommu; const struct mtk_iommu_plat_data *plat_data; struct device *smicomm_dev; + struct mtk_iommu_bank_data *bank; + struct dma_iommu_mapping*mapping; /* For mtk_iommu_v1.c */ struct regmap *pericfg; @@ -225,7 +237,7 @@ struct mtk_iommu_domain { struct io_pgtable_cfg cfg; struct io_pgtable_ops *iop; - struct mtk_iommu_data *data; + struct mtk_iommu_bank_data *bank; struct iommu_domain domain; struct mutexmutex; /* Protect "data" in this structure */ @@ -311,20 +323,24 @@ static struct mtk_iommu_domain *to_mtk_domain(struct iommu_domain *dom) static void mtk_iommu_tlb_flush_all(struct mtk_iommu_data *data) { - void __iomem *base = data->base; + /* Tlb flush all always is in bank0. */ + struct mtk_iommu_bank_data *bank = &data->bank[0]; + void __iomem *base = bank->base; unsigned long flags; - spin_lock_irqsave(&data->tlb_lock, flags); + spin_lock_irqsave(&bank->tlb_lock, flags); writel_relaxed(F_INVLD_EN1 | F_INVLD_EN0, base + data->plat_data->inv_sel_reg); writel_relaxed(F_ALL_INVLD, base + REG_MMU_INVALIDATE); wmb(); /* Make sure the tlb flush all done */ - spin_unlock_irqrestore(&data->tlb_lock, flags); + spin_unlock_irqrestore(&bank->tlb_lock, flags); } static void mtk_iommu_tlb_flush_range_sync(unsigned long iova, size_t size, - struct mtk_iommu_data *data) + struct mtk_iommu_bank_data *bank) { - struct list_head *head = data->hw_list; + struct list_head *head = bank->parent_data->hw_list; + struct mtk_iommu_bank_data *curbank; + struct mtk_iommu_data *data; bool check_pm_status; unsigned long flags; void __iomem *base; @@ -354,9 +370,10 @@ static void mtk_iommu_tlb_flush_range_sync(unsigned long iova, size_t size, continue; } - base = data->base; + curbank = &data->bank[bank->id]; + base = curbank->base; - spin_lock_irqsave(&data->tlb_lock, flags); + spin_lock_irqsave(&curbank->tlb_lock, flags); writel_relaxed(F_INVLD_EN1 | F_INVLD_EN0, base + data->plat_data->inv_sel_reg); @@ -371,7 +388,7 @@ static void mtk
[PATCH v6 29/34] iommu/mediatek: Initialise bank HW for each a bank
The mt8195 IOMMU HW max support 5 banks, and regarding the banks' registers, it looks like: |bank0 | bank1 | bank2 | bank3 | bank4| |global | |control| null |regs | - |bank |bank |bank |bank |bank | |regs |regs |regs |regs |regs | | | | | | | - Each bank has some special bank registers and it share bank0's global control registers. this patch initialise the bank hw with the bankid. In the hw_init, we always initialise bank0's control register since we don't know if the bank0 is initialised. Additionally, About each bank's register base, always delta 0x1000. like bank[x + 1] = bank[x] + 0x1000. Signed-off-by: Yong Wu Reviewed-by: AngeloGioacchino Del Regno --- drivers/iommu/mtk_iommu.c | 32 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c index f2a29399f10f..9c27b99ca0cd 100644 --- a/drivers/iommu/mtk_iommu.c +++ b/drivers/iommu/mtk_iommu.c @@ -259,7 +259,7 @@ static void mtk_iommu_unbind(struct device *dev) static const struct iommu_ops mtk_iommu_ops; -static int mtk_iommu_hw_init(const struct mtk_iommu_data *data); +static int mtk_iommu_hw_init(const struct mtk_iommu_data *data, unsigned int bankid); #define MTK_IOMMU_TLB_ADDR(iova) ({\ dma_addr_t _addr = iova;\ @@ -642,12 +642,14 @@ static int mtk_iommu_attach_device(struct iommu_domain *domain, mutex_lock(&data->mutex); bank = &data->bank[bankid]; - if (!bank->m4u_dom) { /* Initialize the M4U HW */ + if (!bank->m4u_dom) { /* Initialize the M4U HW for each a BANK */ ret = pm_runtime_resume_and_get(m4udev); - if (ret < 0) + if (ret < 0) { + dev_err(m4udev, "pm get fail(%d) in attach.\n", ret); goto err_unlock; + } - ret = mtk_iommu_hw_init(data); + ret = mtk_iommu_hw_init(data, bankid); if (ret) { pm_runtime_put(m4udev); goto err_unlock; @@ -897,11 +899,16 @@ static const struct iommu_ops mtk_iommu_ops = { } }; -static int mtk_iommu_hw_init(const struct mtk_iommu_data *data) +static int mtk_iommu_hw_init(const struct mtk_iommu_data *data, unsigned int bankid) { + const struct mtk_iommu_bank_data *bankx = &data->bank[bankid]; const struct mtk_iommu_bank_data *bank0 = &data->bank[0]; u32 regval; + /* +* Global control settings are in bank0. May re-init these global registers +* since no sure if there is bank0 consumers. +*/ if (data->plat_data->m4u_plat == M4U_MT8173) { regval = F_MMU_PREFETCH_RT_REPLACE_MOD | F_MMU_TF_PROT_TO_PROGRAM_ADDR_MT8173; @@ -944,13 +951,14 @@ static int mtk_iommu_hw_init(const struct mtk_iommu_data *data) } writel_relaxed(regval, bank0->base + REG_MMU_MISC_CTRL); + /* Independent settings for each bank */ regval = F_L2_MULIT_HIT_EN | F_TABLE_WALK_FAULT_INT_EN | F_PREETCH_FIFO_OVERFLOW_INT_EN | F_MISS_FIFO_OVERFLOW_INT_EN | F_PREFETCH_FIFO_ERR_INT_EN | F_MISS_FIFO_ERR_INT_EN; - writel_relaxed(regval, bank0->base + REG_MMU_INT_CONTROL0); + writel_relaxed(regval, bankx->base + REG_MMU_INT_CONTROL0); regval = F_INT_TRANSLATION_FAULT | F_INT_MAIN_MULTI_HIT_FAULT | @@ -959,19 +967,19 @@ static int mtk_iommu_hw_init(const struct mtk_iommu_data *data) F_INT_TLB_MISS_FAULT | F_INT_MISS_TRANSACTION_FIFO_FAULT | F_INT_PRETETCH_TRANSATION_FIFO_FAULT; - writel_relaxed(regval, bank0->base + REG_MMU_INT_MAIN_CONTROL); + writel_relaxed(regval, bankx->base + REG_MMU_INT_MAIN_CONTROL); if (MTK_IOMMU_HAS_FLAG(data->plat_data, HAS_LEGACY_IVRP_PADDR)) regval = (data->protect_base >> 1) | (data->enable_4GB << 31); else regval = lower_32_bits(data->protect_base) | upper_32_bits(data->protect_base); - writel_relaxed(regval, bank0->base + REG_MMU_IVRP_PADDR); + writel_relaxed(regval, bankx->base + REG_MMU_IVRP_PADDR); - if (devm_request_irq(bank0->parent_dev, bank0->irq, mtk_iommu_isr, 0, -dev_name(bank0->parent_dev), (void *)bank0)) { - writel_relaxed(0, bank0->base + REG_MMU_PT_BASE_ADDR); - dev_err(bank0->parent_dev, "Failed @ IRQ-%d Request\n", bank0->irq); + if (devm_request_irq(bankx->parent_dev, bankx->irq, mtk_iomm
[PATCH v6 27/34] iommu/mediatek-v1: Just rename mtk_iommu to mtk_iommu_v1
No functional change. Just rename this for readable. Differentiate this from mtk_iommu.c Signed-off-by: Yong Wu Reviewed-by: AngeloGioacchino Del Regno --- drivers/iommu/mtk_iommu_v1.c | 211 +-- 1 file changed, 103 insertions(+), 108 deletions(-) diff --git a/drivers/iommu/mtk_iommu_v1.c b/drivers/iommu/mtk_iommu_v1.c index 3d1f0897d1cc..62669e60991f 100644 --- a/drivers/iommu/mtk_iommu_v1.c +++ b/drivers/iommu/mtk_iommu_v1.c @@ -85,53 +85,53 @@ */ #define M2701_IOMMU_PGT_SIZE SZ_4M -struct mtk_iommu_suspend_reg { +struct mtk_iommu_v1_suspend_reg { u32 standard_axi_mode; u32 dcm_dis; u32 ctrl_reg; u32 int_control0; }; -struct mtk_iommu_data { +struct mtk_iommu_v1_data { void __iomem*base; int irq; struct device *dev; struct clk *bclk; phys_addr_t protect_base; /* protect memory base */ - struct mtk_iommu_domain *m4u_dom; + struct mtk_iommu_v1_domain *m4u_dom; struct iommu_device iommu; struct dma_iommu_mapping*mapping; struct mtk_smi_larb_iommu larb_imu[MTK_LARB_NR_MAX]; - struct mtk_iommu_suspend_regreg; + struct mtk_iommu_v1_suspend_reg reg; }; -struct mtk_iommu_domain { +struct mtk_iommu_v1_domain { spinlock_t pgtlock; /* lock for page table */ struct iommu_domain domain; u32 *pgt_va; dma_addr_t pgt_pa; - struct mtk_iommu_data *data; + struct mtk_iommu_v1_data*data; }; -static int mtk_iommu_bind(struct device *dev) +static int mtk_iommu_v1_bind(struct device *dev) { - struct mtk_iommu_data *data = dev_get_drvdata(dev); + struct mtk_iommu_v1_data *data = dev_get_drvdata(dev); return component_bind_all(dev, &data->larb_imu); } -static void mtk_iommu_unbind(struct device *dev) +static void mtk_iommu_v1_unbind(struct device *dev) { - struct mtk_iommu_data *data = dev_get_drvdata(dev); + struct mtk_iommu_v1_data *data = dev_get_drvdata(dev); component_unbind_all(dev, &data->larb_imu); } -static struct mtk_iommu_domain *to_mtk_domain(struct iommu_domain *dom) +static struct mtk_iommu_v1_domain *to_mtk_domain(struct iommu_domain *dom) { - return container_of(dom, struct mtk_iommu_domain, domain); + return container_of(dom, struct mtk_iommu_v1_domain, domain); } static const int mt2701_m4u_in_larb[] = { @@ -157,7 +157,7 @@ static inline int mt2701_m4u_to_port(int id) return id - mt2701_m4u_in_larb[larb]; } -static void mtk_iommu_tlb_flush_all(struct mtk_iommu_data *data) +static void mtk_iommu_v1_tlb_flush_all(struct mtk_iommu_v1_data *data) { writel_relaxed(F_INVLD_EN1 | F_INVLD_EN0, data->base + REG_MMU_INV_SEL); @@ -165,8 +165,8 @@ static void mtk_iommu_tlb_flush_all(struct mtk_iommu_data *data) wmb(); /* Make sure the tlb flush all done */ } -static void mtk_iommu_tlb_flush_range(struct mtk_iommu_data *data, - unsigned long iova, size_t size) +static void mtk_iommu_v1_tlb_flush_range(struct mtk_iommu_v1_data *data, +unsigned long iova, size_t size) { int ret; u32 tmp; @@ -184,16 +184,16 @@ static void mtk_iommu_tlb_flush_range(struct mtk_iommu_data *data, if (ret) { dev_warn(data->dev, "Partial TLB flush timed out, falling back to full flush\n"); - mtk_iommu_tlb_flush_all(data); + mtk_iommu_v1_tlb_flush_all(data); } /* Clear the CPE status */ writel_relaxed(0, data->base + REG_MMU_CPE_DONE); } -static irqreturn_t mtk_iommu_isr(int irq, void *dev_id) +static irqreturn_t mtk_iommu_v1_isr(int irq, void *dev_id) { - struct mtk_iommu_data *data = dev_id; - struct mtk_iommu_domain *dom = data->m4u_dom; + struct mtk_iommu_v1_data *data = dev_id; + struct mtk_iommu_v1_domain *dom = data->m4u_dom; u32 int_state, regval, fault_iova, fault_pa; unsigned int fault_larb, fault_port; @@ -223,13 +223,13 @@ static irqreturn_t mtk_iommu_isr(int irq, void *dev_id) regval |= F_INT_CLR_BIT; writel_relaxed(regval, data->base + REG_MMU_INT_CONTROL); - mtk_iommu_tlb_flush_all(data); + mtk_iommu_v1_tlb_flush_all(data); return IRQ_HANDLED; } -static void mtk_iommu_config(struct mtk_iommu_data *data, -struct device *dev, bool enable) +static void mtk_iommu_v1_config(struct mtk_iommu_v1_data *data, + struct device *dev, boo
[PATCH v6 26/34] iommu/mediatek: Remove mtk_iommu.h
Currently there is a suspend structure in the header file. It's no need to keep a header file only for this. Move these into the c file and rm this header file. Signed-off-by: Yong Wu Reviewed-by: AngeloGioacchino Del Regno --- drivers/iommu/mtk_iommu.c| 14 +- drivers/iommu/mtk_iommu.h| 32 drivers/iommu/mtk_iommu_v1.c | 11 --- 3 files changed, 21 insertions(+), 36 deletions(-) delete mode 100644 drivers/iommu/mtk_iommu.h diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c index ab3b1aedfdc3..d46eb745492f 100644 --- a/drivers/iommu/mtk_iommu.c +++ b/drivers/iommu/mtk_iommu.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -30,7 +31,7 @@ #include #include -#include "mtk_iommu.h" +#include #define REG_MMU_PT_BASE_ADDR 0x000 #define MMU_PT_ADDR_MASK GENMASK(31, 7) @@ -166,6 +167,17 @@ struct mtk_iommu_iova_region { unsigned long long size; }; +struct mtk_iommu_suspend_reg { + u32 misc_ctrl; + u32 dcm_dis; + u32 ctrl_reg; + u32 int_control0; + u32 int_main_control; + u32 ivrp_paddr; + u32 vld_pa_rng; + u32 wr_len_ctrl; +}; + struct mtk_iommu_plat_data { enum mtk_iommu_plat m4u_plat; u32 flags; diff --git a/drivers/iommu/mtk_iommu.h b/drivers/iommu/mtk_iommu.h deleted file mode 100644 index 305243e18aa9.. --- a/drivers/iommu/mtk_iommu.h +++ /dev/null @@ -1,32 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * Copyright (c) 2015-2016 MediaTek Inc. - * Author: Honghui Zhang - */ - -#ifndef _MTK_IOMMU_H_ -#define _MTK_IOMMU_H_ - -#include -#include -#include -#include -#include -#include -#include - -struct mtk_iommu_suspend_reg { - union { - u32 standard_axi_mode;/* v1 */ - u32 misc_ctrl;/* v2 */ - }; - u32 dcm_dis; - u32 ctrl_reg; - u32 int_control0; - u32 int_main_control; - u32 ivrp_paddr; - u32 vld_pa_rng; - u32 wr_len_ctrl; -}; - -#endif diff --git a/drivers/iommu/mtk_iommu_v1.c b/drivers/iommu/mtk_iommu_v1.c index 6d1c09c91e1f..3d1f0897d1cc 100644 --- a/drivers/iommu/mtk_iommu_v1.c +++ b/drivers/iommu/mtk_iommu_v1.c @@ -7,7 +7,6 @@ * * Based on driver/iommu/mtk_iommu.c */ -#include #include #include #include @@ -28,10 +27,9 @@ #include #include #include -#include +#include #include #include -#include "mtk_iommu.h" #define REG_MMU_PT_BASE_ADDR 0x000 @@ -87,6 +85,13 @@ */ #define M2701_IOMMU_PGT_SIZE SZ_4M +struct mtk_iommu_suspend_reg { + u32 standard_axi_mode; + u32 dcm_dis; + u32 ctrl_reg; + u32 int_control0; +}; + struct mtk_iommu_data { void __iomem*base; int irq; -- 2.18.0 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu