Re: [PATCH v12 2/2] iommu/mediatek: Allow page table PA up to 35bit

2022-07-04 Thread Yong Wu via iommu
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

2022-06-30 Thread Yong Wu via iommu
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

2022-06-30 Thread Yong Wu via iommu
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"

2022-06-30 Thread Yong Wu via iommu
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

2022-06-30 Thread Yong Wu via iommu
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

2022-06-30 Thread Yong Wu via iommu
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

2022-06-30 Thread Yong Wu via iommu
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

2022-06-30 Thread Yong Wu via iommu
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

2022-06-30 Thread Yong Wu via iommu
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

2022-06-30 Thread Yong Wu via iommu
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

2022-06-24 Thread Yong Wu via iommu
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

2022-06-23 Thread Yong Wu via iommu
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

2022-06-22 Thread Yong Wu via iommu
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

2022-06-22 Thread Yong Wu via iommu
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

2022-06-21 Thread Yong Wu via iommu
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

2022-06-16 Thread Yong Wu via iommu
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

2022-06-15 Thread Yong Wu via iommu
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

2022-06-15 Thread Yong Wu via iommu
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

2022-06-15 Thread Yong Wu via iommu
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"

2022-06-15 Thread Yong Wu via iommu
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

2022-06-15 Thread Yong Wu via iommu
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

2022-06-15 Thread Yong Wu via iommu
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

2022-06-15 Thread Yong Wu via iommu
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

2022-06-14 Thread Yong Wu via iommu
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

2022-06-13 Thread Yong Wu via iommu
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

2022-06-13 Thread Yong Wu via iommu
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

2022-06-12 Thread Yong Wu via iommu
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

2022-06-12 Thread Yong Wu via iommu
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

2022-06-12 Thread Yong Wu via iommu
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

2022-06-12 Thread Yong Wu via iommu
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

2022-06-12 Thread Yong Wu via iommu
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

2022-06-02 Thread Yong Wu via iommu
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

2022-06-01 Thread Yong Wu via iommu
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

2022-06-01 Thread Yong Wu via iommu
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

2022-05-26 Thread Yong Wu via iommu
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

2022-05-26 Thread Yong Wu via iommu
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

2022-05-26 Thread Yong Wu via iommu
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

2022-05-26 Thread Yong Wu via iommu
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

2022-05-18 Thread Yong Wu via iommu
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

2022-05-17 Thread Yong Wu via iommu
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

2022-05-17 Thread Yong Wu via iommu
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

2022-05-11 Thread Yong Wu via iommu
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

2022-05-10 Thread Yong Wu via iommu
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"

2022-05-10 Thread Yong Wu via iommu
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

2022-05-10 Thread Yong Wu via iommu
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

2022-05-10 Thread Yong Wu via iommu
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

2022-05-10 Thread Yong Wu via iommu
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

2022-05-05 Thread Yong Wu via iommu
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

2022-05-03 Thread Yong Wu via iommu
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

2022-05-03 Thread Yong Wu via iommu
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

2022-05-03 Thread Yong Wu via 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

2022-05-03 Thread Yong Wu via iommu
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

2022-05-03 Thread Yong Wu via iommu
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

2022-05-03 Thread Yong Wu via iommu
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

2022-05-03 Thread Yong Wu via iommu
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

2022-05-03 Thread Yong Wu via iommu
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

2022-05-03 Thread Yong Wu via iommu
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

2022-05-03 Thread Yong Wu via iommu
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

2022-05-03 Thread Yong Wu via iommu
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

2022-05-03 Thread Yong Wu via iommu
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

2022-05-03 Thread Yong Wu via iommu
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

2022-05-03 Thread Yong Wu via iommu
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

2022-05-03 Thread Yong Wu via iommu
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

2022-05-03 Thread Yong Wu via iommu
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

2022-05-03 Thread Yong Wu via iommu
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

2022-05-03 Thread Yong Wu via 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

2022-05-03 Thread Yong Wu via iommu
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

2022-05-03 Thread Yong Wu via iommu
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

2022-05-03 Thread Yong Wu via iommu
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

2022-05-03 Thread Yong Wu via iommu
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

2022-05-03 Thread Yong Wu via iommu
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

2022-05-03 Thread Yong Wu via iommu
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

2022-05-03 Thread Yong Wu via iommu
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

2022-05-03 Thread Yong Wu via iommu
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

2022-05-03 Thread Yong Wu via iommu
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

2022-05-03 Thread Yong Wu via iommu
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

2022-05-03 Thread Yong Wu via iommu
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

2022-05-03 Thread Yong Wu via iommu
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

2022-05-03 Thread Yong Wu via iommu
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

2022-05-03 Thread Yong Wu via iommu
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

2022-05-03 Thread Yong Wu via iommu
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

2022-05-03 Thread Yong Wu via iommu
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

2022-05-03 Thread Yong Wu via 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

2022-05-03 Thread Yong Wu via 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

2022-05-03 Thread Yong Wu via 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

2022-05-03 Thread Yong Wu via iommu
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

2022-04-30 Thread Yong Wu via iommu
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

2022-04-25 Thread Yong Wu via iommu
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

2022-04-07 Thread Yong Wu via iommu
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

2022-04-07 Thread Yong Wu via 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

2022-04-07 Thread Yong Wu via iommu
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

2022-04-07 Thread Yong Wu via 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

2022-04-07 Thread Yong Wu via iommu
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

2022-04-07 Thread Yong Wu via iommu
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

2022-04-07 Thread Yong Wu via iommu
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

2022-04-07 Thread Yong Wu via iommu
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

2022-04-07 Thread Yong Wu via iommu
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

2022-04-07 Thread Yong Wu via iommu
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

2022-04-07 Thread Yong Wu via iommu
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

2022-04-07 Thread Yong Wu via iommu
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


  1   2   >