diff mbox series

[3/4] memory: mtk-smi: mt8188: Add SMI clamp function

Message ID 20240821082845.11792-4-friday.yang@mediatek.com (mailing list archive)
State New
Headers show
Series Add SMI clamp and reset | expand

Commit Message

Friday Yang (杨阳) Aug. 21, 2024, 8:26 a.m. UTC
In order to avoid handling glitch signal when MTCMOS on/off, SMI need
clamp and reset operation. Parse power reset settings for LARBs which
need to reset. Register genpd callback for SMI LARBs and apply reset
operations in the callback.

Signed-off-by: friday.yang <friday.yang@mediatek.com>
---
 drivers/memory/mtk-smi.c | 148 ++++++++++++++++++++++++++++++++++++++-
 1 file changed, 146 insertions(+), 2 deletions(-)

Comments

Krzysztof Kozlowski Aug. 21, 2024, 9 a.m. UTC | #1
On 21/08/2024 10:26, friday.yang wrote:
> In order to avoid handling glitch signal when MTCMOS on/off, SMI need
> clamp and reset operation. Parse power reset settings for LARBs which
> need to reset. Register genpd callback for SMI LARBs and apply reset
> operations in the callback.
> 
> Signed-off-by: friday.yang <friday.yang@mediatek.com>
> ---
>  drivers/memory/mtk-smi.c | 148 ++++++++++++++++++++++++++++++++++++++-
>  1 file changed, 146 insertions(+), 2 deletions(-)
> 

...

> +
> +static int mtk_smi_larb_parse_reset_info(struct mtk_smi_larb *larb)
> +{
> +	struct device_node *reset_node;
> +	struct device *dev = larb->dev;
> +	int ret;
> +
> +	/* only larb with "resets" need to get reset setting */
> +	reset_node = of_parse_phandle(dev->of_node, "resets", 0);

Nope, you do not parse rasets.

> +	if (!reset_node)
> +		return 0;
> +	of_node_put(reset_node);
> +
> +	larb->rst_con = devm_reset_control_get(dev, "larb_rst");

Where are the bindings? Why do you add undocumented properties? How
possible this passes dtbs_check???


> +	if (IS_ERR(larb->rst_con))
> +		return dev_err_probe(dev, PTR_ERR(larb->rst_con),
> +				     "cannot get larb reset controller\n");
> +
> +	larb->nb.notifier_call = mtk_smi_genpd_callback;
> +	ret = dev_pm_genpd_add_notifier(dev, &larb->nb);
> +	if (ret) {
> +		dev_err(dev, "Failed to add genpd callback %d\n", ret);
> +		return -EINVAL;
> +	}
> +
> +	return 0;
> +}
> +
>  static int mtk_smi_larb_probe(struct platform_device *pdev)
>  {
>  	struct mtk_smi_larb *larb;
> @@ -538,6 +662,7 @@ static int mtk_smi_larb_probe(struct platform_device *pdev)
>  	if (!larb)
>  		return -ENOMEM;
>  
> +	larb->dev = dev;
>  	larb->larb_gen = of_device_get_match_data(dev);
>  	larb->base = devm_platform_ioremap_resource(pdev, 0);
>  	if (IS_ERR(larb->base))
> @@ -554,15 +679,29 @@ static int mtk_smi_larb_probe(struct platform_device *pdev)
>  	if (ret < 0)
>  		return ret;
>  
> -	pm_runtime_enable(dev);
> +	/* find sub common to clamp larb for ISP software reset */
> +	ret = mtk_smi_larb_parse_clamp_info(larb);
> +	if (ret) {
> +		dev_err(dev, "Failed to get clamp setting for larb\n");
> +		goto err_pm_disable;
> +	}
> +
> +	ret = mtk_smi_larb_parse_reset_info(larb);
> +	if (ret) {
> +		dev_err(dev, "Failed to get power setting for larb\n");
> +		goto err_pm_disable;
> +	}
> +
>  	platform_set_drvdata(pdev, larb);
>  	ret = component_add(dev, &mtk_smi_larb_component_ops);
>  	if (ret)
>  		goto err_pm_disable;
> +
> +	pm_runtime_enable(dev);
> +
>  	return 0;
>  
>  err_pm_disable:
> -	pm_runtime_disable(dev);
>  	device_link_remove(dev, larb->smi_common_dev);

Label asls pm disable. Where is the pm disable?

>  	return ret;
>  }
> @@ -686,6 +825,10 @@ static const struct mtk_smi_common_plat mtk_smi_common_mt8188_vpp = {
>  	.init     = mtk_smi_common_mt8195_init,
>  };

Best regards,
Krzysztof
Friday Yang (杨阳) Oct. 24, 2024, 1:29 a.m. UTC | #2
On Wed, 2024-08-21 at 11:00 +0200, Krzysztof Kozlowski wrote:
>  	 
> External email : Please do not click links or open attachments until
> you have verified the sender or the content.
>  On 21/08/2024 10:26, friday.yang wrote:
> > In order to avoid handling glitch signal when MTCMOS on/off, SMI
> need
> > clamp and reset operation. Parse power reset settings for LARBs
> which
> > need to reset. Register genpd callback for SMI LARBs and apply
> reset
> > operations in the callback.
> > 
> > Signed-off-by: friday.yang <friday.yang@mediatek.com>
> > ---
> >  drivers/memory/mtk-smi.c | 148
> ++++++++++++++++++++++++++++++++++++++-
> >  1 file changed, 146 insertions(+), 2 deletions(-)
> > 
> 
> ...
> 
> > +
> > +static int mtk_smi_larb_parse_reset_info(struct mtk_smi_larb
> *larb)
> > +{
> > +struct device_node *reset_node;
> > +struct device *dev = larb->dev;
> > +int ret;
> > +
> > +/* only larb with "resets" need to get reset setting */
> > +reset_node = of_parse_phandle(dev->of_node, "resets", 0);
> 
> Nope, you do not parse rasets.

1.If I need to use the Linux reset control framework, 'resets' is the
required property.
2.'reset-names' give the list of reset signal name strings sorted in
the same order as the 'resets' property. SMI driver will use 'reset-
names' to match reset signal names with reset specifiers.
3.Not all SMI larbs need to apply reset operations, only SMI larbs
which may have bus glitch issues need this. Just to confirm if this
larb support reset function.

> 
> > +if (!reset_node)
> > +return 0;
> > +of_node_put(reset_node);
> > +
> > +larb->rst_con = devm_reset_control_get(dev, "larb_rst");
> 
> Where are the bindings? Why do you add undocumented properties? How
> possible this passes dtbs_check???
> 

This is not the new added property in SMI larb DT node.
It is the reset signal name which is inclued in 'reset-names'.
Just like this:

resets = <&imgsys1_dip_nr_rst MT8188_SIM_RST_LARB15>;
reset-name = 'larb_rst';

Maybe I can add this name to the 'reset-name' property binding
description, like this, is this clear for you?

reset-name:
    const: larb_rst
    description: the name of reset signal. SMI driver need to obtain 		
 the reset controller based on this.

> 
> > +if (IS_ERR(larb->rst_con))
> > +return dev_err_probe(dev, PTR_ERR(larb->rst_con),
> > +     "cannot get larb reset controller\n");
> > +
> > +larb->nb.notifier_call = mtk_smi_genpd_callback;
> > +ret = dev_pm_genpd_add_notifier(dev, &larb->nb);
> > +if (ret) {
> > +dev_err(dev, "Failed to add genpd callback %d\n", ret);
> > +return -EINVAL;
> > +}
> > +
> > +return 0;
> > +}
> > +
> >  static int mtk_smi_larb_probe(struct platform_device *pdev)
> >  {
> >  struct mtk_smi_larb *larb;
> > @@ -538,6 +662,7 @@ static int mtk_smi_larb_probe(struct
> platform_device *pdev)
> >  if (!larb)
> >  return -ENOMEM;
> >  
> > +larb->dev = dev;
> >  larb->larb_gen = of_device_get_match_data(dev);
> >  larb->base = devm_platform_ioremap_resource(pdev, 0);
> >  if (IS_ERR(larb->base))
> > @@ -554,15 +679,29 @@ static int mtk_smi_larb_probe(struct
> platform_device *pdev)
> >  if (ret < 0)
> >  return ret;
> >  
> > -pm_runtime_enable(dev);
> > +/* find sub common to clamp larb for ISP software reset */
> > +ret = mtk_smi_larb_parse_clamp_info(larb);
> > +if (ret) {
> > +dev_err(dev, "Failed to get clamp setting for larb\n");
> > +goto err_pm_disable;
> > +}
> > +
> > +ret = mtk_smi_larb_parse_reset_info(larb);
> > +if (ret) {
> > +dev_err(dev, "Failed to get power setting for larb\n");
> > +goto err_pm_disable;
> > +}
> > +
> >  platform_set_drvdata(pdev, larb);
> >  ret = component_add(dev, &mtk_smi_larb_component_ops);
> >  if (ret)
> >  goto err_pm_disable;
> > +
> > +pm_runtime_enable(dev);
> > +
> >  return 0;
> >  
> >  err_pm_disable:
> > -pm_runtime_disable(dev);
> >  device_link_remove(dev, larb->smi_common_dev);
> 
> Label asls pm disable. Where is the pm disable?
> 

Thanks, I will fix it to 'err_link_remove'.

> >  return ret;
> >  }
> > @@ -686,6 +825,10 @@ static const struct mtk_smi_common_plat
> mtk_smi_common_mt8188_vpp = {
> >  .init     = mtk_smi_common_mt8195_init,
> >  };
> 
> Best regards,
> Krzysztof
>
AngeloGioacchino Del Regno Oct. 24, 2024, 11:56 a.m. UTC | #3
Il 24/10/24 03:29, Friday Yang (杨阳) ha scritto:
> On Wed, 2024-08-21 at 11:00 +0200, Krzysztof Kozlowski wrote:
>>   	
>> External email : Please do not click links or open attachments until
>> you have verified the sender or the content.
>>   On 21/08/2024 10:26, friday.yang wrote:
>>> In order to avoid handling glitch signal when MTCMOS on/off, SMI
>> need
>>> clamp and reset operation. Parse power reset settings for LARBs
>> which
>>> need to reset. Register genpd callback for SMI LARBs and apply
>> reset
>>> operations in the callback.
>>>
>>> Signed-off-by: friday.yang <friday.yang@mediatek.com>
>>> ---
>>>   drivers/memory/mtk-smi.c | 148
>> ++++++++++++++++++++++++++++++++++++++-
>>>   1 file changed, 146 insertions(+), 2 deletions(-)
>>>
>>
>> ...
>>
>>> +
>>> +static int mtk_smi_larb_parse_reset_info(struct mtk_smi_larb
>> *larb)
>>> +{
>>> +struct device_node *reset_node;
>>> +struct device *dev = larb->dev;
>>> +int ret;
>>> +
>>> +/* only larb with "resets" need to get reset setting */
>>> +reset_node = of_parse_phandle(dev->of_node, "resets", 0);
>>
>> Nope, you do not parse rasets.
> 
> 1.If I need to use the Linux reset control framework, 'resets' is the
> required property.

Leave that to the reset API, don't manually parse the resets phandle here,
that's what Krzysztof was meaning.

> 2.'reset-names' give the list of reset signal name strings sorted in
> the same order as the 'resets' property. SMI driver will use 'reset-
> names' to match reset signal names with reset specifiers.
> 3.Not all SMI larbs need to apply reset operations, only SMI larbs
> which may have bus glitch issues need this. Just to confirm if this
> larb support reset function.
> 
>>
>>> +if (!reset_node)
>>> +return 0;
>>> +of_node_put(reset_node);
>>> +
>>> +larb->rst_con = devm_reset_control_get(dev, "larb_rst");

"larb" is just fine as a name: it's clear that this is a reset, as
it's specified as `reset-names = "name"`.

>>
>> Where are the bindings? Why do you add undocumented properties? How
>> possible this passes dtbs_check???
>>
> 
> This is not the new added property in SMI larb DT node.
> It is the reset signal name which is inclued in 'reset-names'.
> Just like this:
> 
> resets = <&imgsys1_dip_nr_rst MT8188_SIM_RST_LARB15>;
> reset-name = 'larb_rst';
> 
> Maybe I can add this name to the 'reset-name' property binding
> description, like this, is this clear for you?
> 
> reset-name:

It's "reset-names" btw.

>      const: larb_rst
>      description: the name of reset signal. SMI driver need to obtain 		
>   the reset controller based on this.
> 
>>
>>> +if (IS_ERR(larb->rst_con))
>>> +return dev_err_probe(dev, PTR_ERR(larb->rst_con),
>>> +     "cannot get larb reset controller\n");
>>> +
>>> +larb->nb.notifier_call = mtk_smi_genpd_callback;
>>> +ret = dev_pm_genpd_add_notifier(dev, &larb->nb);
>>> +if (ret) {
>>> +dev_err(dev, "Failed to add genpd callback %d\n", ret);
>>> +return -EINVAL;
>>> +}
>>> +
>>> +return 0;
>>> +}
>>> +
>>>   static int mtk_smi_larb_probe(struct platform_device *pdev)
>>>   {
>>>   struct mtk_smi_larb *larb;
>>> @@ -538,6 +662,7 @@ static int mtk_smi_larb_probe(struct
>> platform_device *pdev)
>>>   if (!larb)
>>>   return -ENOMEM;
>>>   
>>> +larb->dev = dev;
>>>   larb->larb_gen = of_device_get_match_data(dev);
>>>   larb->base = devm_platform_ioremap_resource(pdev, 0);
>>>   if (IS_ERR(larb->base))
>>> @@ -554,15 +679,29 @@ static int mtk_smi_larb_probe(struct
>> platform_device *pdev)
>>>   if (ret < 0)
>>>   return ret;
>>>   
>>> -pm_runtime_enable(dev);
>>> +/* find sub common to clamp larb for ISP software reset */
>>> +ret = mtk_smi_larb_parse_clamp_info(larb);
>>> +if (ret) {
>>> +dev_err(dev, "Failed to get clamp setting for larb\n");
>>> +goto err_pm_disable;
>>> +}
>>> +
>>> +ret = mtk_smi_larb_parse_reset_info(larb);
>>> +if (ret) {
>>> +dev_err(dev, "Failed to get power setting for larb\n");
>>> +goto err_pm_disable;
>>> +}
>>> +
>>>   platform_set_drvdata(pdev, larb);
>>>   ret = component_add(dev, &mtk_smi_larb_component_ops);
>>>   if (ret)
>>>   goto err_pm_disable;
>>> +
>>> +pm_runtime_enable(dev);
>>> +
>>>   return 0;
>>>   
>>>   err_pm_disable:
>>> -pm_runtime_disable(dev);
>>>   device_link_remove(dev, larb->smi_common_dev);
>>
>> Label asls pm disable. Where is the pm disable?
>>
> 
> Thanks, I will fix it to 'err_link_remove'.
> 

...or you can just use devm_pm_runtime_enable() instead, and not worry
about disabling it on your own.

Regards,
Angelo
Friday Yang (杨阳) Oct. 25, 2024, 9:33 a.m. UTC | #4
On Thu, 2024-10-24 at 13:56 +0200, AngeloGioacchino Del Regno wrote:
> Il 24/10/24 03:29, Friday Yang (杨阳) ha scritto:
> > On Wed, 2024-08-21 at 11:00 +0200, Krzysztof Kozlowski wrote:
> > >   	
> > > External email : Please do not click links or open attachments
> > > until
> > > you have verified the sender or the content.
> > >   On 21/08/2024 10:26, friday.yang wrote:
> > > > In order to avoid handling glitch signal when MTCMOS on/off,
> > > > SMI
> > > 
> > > need
> > > > clamp and reset operation. Parse power reset settings for LARBs
> > > 
> > > which
> > > > need to reset. Register genpd callback for SMI LARBs and apply
> > > 
> > > reset
> > > > operations in the callback.
> > > > 
> > > > Signed-off-by: friday.yang <friday.yang@mediatek.com>
> > > > ---
> > > >   drivers/memory/mtk-smi.c | 148
> > > 
> > > ++++++++++++++++++++++++++++++++++++++-
> > > >   1 file changed, 146 insertions(+), 2 deletions(-)
> > > > 
> > > 
> > > ...
> > > 
> > > > +
> > > > +static int mtk_smi_larb_parse_reset_info(struct mtk_smi_larb
> > > 
> > > *larb)
> > > > +{
> > > > +struct device_node *reset_node;
> > > > +struct device *dev = larb->dev;
> > > > +int ret;
> > > > +
> > > > +/* only larb with "resets" need to get reset setting */
> > > > +reset_node = of_parse_phandle(dev->of_node, "resets", 0);
> > > 
> > > Nope, you do not parse rasets.
> > 
> > 1.If I need to use the Linux reset control framework, 'resets' is
> > the
> > required property.
> 
> Leave that to the reset API, don't manually parse the resets phandle
> here,
> that's what Krzysztof was meaning.

OK, I will just use 'larb->rst_con' to judge whether this larb need
reset or not, not parse 'resets' here.

> 
> > 2.'reset-names' give the list of reset signal name strings sorted
> > in
> > the same order as the 'resets' property. SMI driver will use
> > 'reset-
> > names' to match reset signal names with reset specifiers.
> > 3.Not all SMI larbs need to apply reset operations, only SMI larbs
> > which may have bus glitch issues need this. Just to confirm if this
> > larb support reset function.
> > 
> > > 
> > > > +if (!reset_node)
> > > > +return 0;
> > > > +of_node_put(reset_node);
> > > > +
> > > > +larb->rst_con = devm_reset_control_get(dev, "larb_rst");
> 
> "larb" is just fine as a name: it's clear that this is a reset, as
> it's specified as `reset-names = "name"`.

Thanks, I will fix it to 'larb'.

> 
> > > 
> > > Where are the bindings? Why do you add undocumented properties?
> > > How
> > > possible this passes dtbs_check???
> > > 
> > 
> > This is not the new added property in SMI larb DT node.
> > It is the reset signal name which is inclued in 'reset-names'.
> > Just like this:
> > 
> > resets = <&imgsys1_dip_nr_rst MT8188_SIM_RST_LARB15>;
> > reset-name = 'larb_rst';
> > 
> > Maybe I can add this name to the 'reset-name' property binding
> > description, like this, is this clear for you?
> > 
> > reset-name:
> 
> It's "reset-names" btw.

Yes, you are right.

> 
> >      const: larb_rst
> >      description: the name of reset signal. SMI driver need to
> > obtain 		
> >   the reset controller based on this.
> > 
> > > 
> > > > +if (IS_ERR(larb->rst_con))
> > > > +return dev_err_probe(dev, PTR_ERR(larb->rst_con),
> > > > +     "cannot get larb reset controller\n");
> > > > +
> > > > +larb->nb.notifier_call = mtk_smi_genpd_callback;
> > > > +ret = dev_pm_genpd_add_notifier(dev, &larb->nb);
> > > > +if (ret) {
> > > > +dev_err(dev, "Failed to add genpd callback %d\n", ret);
> > > > +return -EINVAL;
> > > > +}
> > > > +
> > > > +return 0;
> > > > +}
> > > > +
> > > >   static int mtk_smi_larb_probe(struct platform_device *pdev)
> > > >   {
> > > >   struct mtk_smi_larb *larb;
> > > > @@ -538,6 +662,7 @@ static int mtk_smi_larb_probe(struct
> > > 
> > > platform_device *pdev)
> > > >   if (!larb)
> > > >   return -ENOMEM;
> > > >   
> > > > +larb->dev = dev;
> > > >   larb->larb_gen = of_device_get_match_data(dev);
> > > >   larb->base = devm_platform_ioremap_resource(pdev, 0);
> > > >   if (IS_ERR(larb->base))
> > > > @@ -554,15 +679,29 @@ static int mtk_smi_larb_probe(struct
> > > 
> > > platform_device *pdev)
> > > >   if (ret < 0)
> > > >   return ret;
> > > >   
> > > > -pm_runtime_enable(dev);
> > > > +/* find sub common to clamp larb for ISP software reset */
> > > > +ret = mtk_smi_larb_parse_clamp_info(larb);
> > > > +if (ret) {
> > > > +dev_err(dev, "Failed to get clamp setting for larb\n");
> > > > +goto err_pm_disable;
> > > > +}
> > > > +
> > > > +ret = mtk_smi_larb_parse_reset_info(larb);
> > > > +if (ret) {
> > > > +dev_err(dev, "Failed to get power setting for larb\n");
> > > > +goto err_pm_disable;
> > > > +}
> > > > +
> > > >   platform_set_drvdata(pdev, larb);
> > > >   ret = component_add(dev, &mtk_smi_larb_component_ops);
> > > >   if (ret)
> > > >   goto err_pm_disable;
> > > > +
> > > > +pm_runtime_enable(dev);
> > > > +
> > > >   return 0;
> > > >   
> > > >   err_pm_disable:
> > > > -pm_runtime_disable(dev);
> > > >   device_link_remove(dev, larb->smi_common_dev);
> > > 
> > > Label asls pm disable. Where is the pm disable?
> > > 
> > 
> > Thanks, I will fix it to 'err_link_remove'.
> > 
> 
> ...or you can just use devm_pm_runtime_enable() instead, and not
> worry
> about disabling it on your own.
> 

This is a good choice, but in this smi clamp patchset, I will just
modify the label as 'err_link_remove'.

> Regards,
> Angelo
Krzysztof Kozlowski Oct. 29, 2024, 6:32 a.m. UTC | #5
On 24/10/2024 03:29, Friday Yang (杨阳) wrote:
> On Wed, 2024-08-21 at 11:00 +0200, Krzysztof Kozlowski wrote:
>>  	 
>> External email : Please do not click links or open attachments until
>> you have verified the sender or the content.
>>  On 21/08/2024 10:26, friday.yang wrote:
>>> In order to avoid handling glitch signal when MTCMOS on/off, SMI
>> need
>>> clamp and reset operation. Parse power reset settings for LARBs
>> which
>>> need to reset. Register genpd callback for SMI LARBs and apply
>> reset
>>> operations in the callback.
>>>
>>> Signed-off-by: friday.yang <friday.yang@mediatek.com>
>>> ---
>>>  drivers/memory/mtk-smi.c | 148
>> ++++++++++++++++++++++++++++++++++++++-
>>>  1 file changed, 146 insertions(+), 2 deletions(-)
>>>
>>
>> ...
>>
>>> +
>>> +static int mtk_smi_larb_parse_reset_info(struct mtk_smi_larb
>> *larb)
>>> +{
>>> +struct device_node *reset_node;
>>> +struct device *dev = larb->dev;
>>> +int ret;
>>> +
>>> +/* only larb with "resets" need to get reset setting */
>>> +reset_node = of_parse_phandle(dev->of_node, "resets", 0);
>>
>> Nope, you do not parse rasets.
> 
> 1.If I need to use the Linux reset control framework, 'resets' is the
> required property.

And you never parse it directly. Find me existing examples of this, if
you disagree.

> 2.'reset-names' give the list of reset signal name strings sorted in
> the same order as the 'resets' property. SMI driver will use 'reset-
> names' to match reset signal names with reset specifiers.

?

> 3.Not all SMI larbs need to apply reset operations, only SMI larbs
> which may have bus glitch issues need this. Just to confirm if this
> larb support reset function.

?

Really, read kernel API about reset framework first.

> 
>>
>>> +if (!reset_node)
>>> +return 0;
>>> +of_node_put(reset_node);
>>> +
>>> +larb->rst_con = devm_reset_control_get(dev, "larb_rst");
>>
>> Where are the bindings? Why do you add undocumented properties? How
>> possible this passes dtbs_check???
>>
> 
> This is not the new added property in SMI larb DT node.
> It is the reset signal name which is inclued in 'reset-names'.
> Just like this:

$ git grep larb_rst
No such property, so how this could be "not the new added"?

If you keep responding with some random or irrelevant responses, this
won't work. This is really poor way to upstream. I suggest first perform
extensive internal review which would point out all such trivial issues.



Best regards,
Krzysztof
diff mbox series

Patch

diff --git a/drivers/memory/mtk-smi.c b/drivers/memory/mtk-smi.c
index fbe52ecc0eca..1ccd62a17b1d 100644
--- a/drivers/memory/mtk-smi.c
+++ b/drivers/memory/mtk-smi.c
@@ -10,11 +10,16 @@ 
 #include <linux/err.h>
 #include <linux/io.h>
 #include <linux/iopoll.h>
+#include <linux/mfd/syscon.h>
 #include <linux/module.h>
 #include <linux/of.h>
 #include <linux/of_platform.h>
 #include <linux/platform_device.h>
+#include <linux/pm_domain.h>
 #include <linux/pm_runtime.h>
+#include <linux/regmap.h>
+#include <linux/reset.h>
+#include <linux/reset-controller.h>
 #include <linux/soc/mediatek/mtk_sip_svc.h>
 #include <soc/mediatek/smi.h>
 #include <dt-bindings/memory/mt2701-larb-port.h>
@@ -36,6 +41,13 @@ 
 #define SMI_DCM				0x300
 #define SMI_DUMMY			0x444
 
+#define SMI_COMMON_CLAMP_EN		0x3c0
+#define SMI_COMMON_CLAMP_EN_SET		0x3c4
+#define SMI_COMMON_CLAMP_EN_CLR		0x3c8
+#define SMI_COMMON_CLAMP_MASK(inport)	BIT(inport)
+
+#define SMI_SUB_COMM_INPORT_NR		(8)
+
 /* SMI LARB */
 #define SMI_LARB_SLP_CON                0xc
 #define SLP_PROT_EN                     BIT(0)
@@ -150,6 +162,7 @@  struct mtk_smi {
 };
 
 struct mtk_smi_larb { /* larb: local arbiter */
+	struct device			*dev;
 	struct mtk_smi			smi;
 	void __iomem			*base;
 	struct device			*smi_common_dev; /* common or sub-common dev */
@@ -157,6 +170,10 @@  struct mtk_smi_larb { /* larb: local arbiter */
 	int				larbid;
 	u32				*mmu;
 	unsigned char			*bank;
+	struct regmap			*sub_comm_syscon;
+	int				sub_comm_inport;
+	struct notifier_block		nb;
+	struct reset_control		*rst_con;
 };
 
 static int
@@ -472,6 +489,60 @@  static void mtk_smi_larb_sleep_ctrl_disable(struct mtk_smi_larb *larb)
 	writel_relaxed(0, larb->base + SMI_LARB_SLP_CON);
 }
 
+static int mtk_smi_larb_clamp_protect_enable(struct device *dev)
+{
+	struct mtk_smi_larb *larb = dev_get_drvdata(dev);
+	int ret;
+
+	/* sub_comm_syscon could be NULL if larb directly linked to SMI common */
+	if (!larb->sub_comm_syscon)
+		return -EINVAL;
+
+	ret = regmap_write(larb->sub_comm_syscon, SMI_COMMON_CLAMP_EN_SET,
+			   SMI_COMMON_CLAMP_MASK(larb->sub_comm_inport));
+	if (ret)
+		dev_err(dev, "Unable to enable clamp, inport %d, ret %d\n",
+			larb->sub_comm_inport, ret);
+
+	return ret;
+}
+
+static int mtk_smi_larb_clamp_protect_disble(struct device *dev)
+{
+	struct mtk_smi_larb *larb = dev_get_drvdata(dev);
+	int ret;
+
+	/* sub_comm_syscon could be NULL if larb directly linked to SMI common */
+	if (!larb->sub_comm_syscon)
+		return -EINVAL;
+
+	ret = regmap_write(larb->sub_comm_syscon, SMI_COMMON_CLAMP_EN_CLR,
+			   SMI_COMMON_CLAMP_MASK(larb->sub_comm_inport));
+	if (ret)
+		dev_err(dev, "Unable to disable clamp, inport %d, ret %d\n",
+			larb->sub_comm_inport, ret);
+
+	return ret;
+}
+
+static int mtk_smi_genpd_callback(struct notifier_block *nb,
+				  unsigned long flags, void *data)
+{
+	struct mtk_smi_larb *larb = container_of(nb, struct mtk_smi_larb, nb);
+	struct device *dev = larb->dev;
+
+	if (flags == GENPD_NOTIFY_PRE_ON || flags == GENPD_NOTIFY_PRE_OFF) {
+		/* disable related SMI sub-common port */
+		mtk_smi_larb_clamp_protect_enable(dev);
+	} else if (flags == GENPD_NOTIFY_ON) {
+		/* enable related SMI sub-common port */
+		reset_control_reset(larb->rst_con);
+		mtk_smi_larb_clamp_protect_disble(dev);
+	}
+
+	return NOTIFY_OK;
+}
+
 static int mtk_smi_device_link_common(struct device *dev, struct device **com_dev)
 {
 	struct platform_device *smi_com_pdev;
@@ -528,6 +599,59 @@  static int mtk_smi_dts_clk_init(struct device *dev, struct mtk_smi *smi,
 	return ret;
 }
 
+static int mtk_smi_larb_parse_clamp_info(struct mtk_smi_larb *larb)
+{
+	struct device *dev = larb->dev;
+	struct device_node *smi_node;
+	int ret;
+
+	/* smi_node could be NULL if larb directly linked to SMI common */
+	smi_node = of_parse_phandle(dev->of_node, "mediatek,smi-sub-comm", 0);
+	if (!smi_node)
+		return 0;
+
+	larb->sub_comm_syscon = device_node_to_regmap(smi_node);
+	of_node_put(smi_node);
+	ret = of_property_read_u32(dev->of_node,
+				   "mediatek,smi-sub-comm-in-portid",
+				   &larb->sub_comm_inport);
+
+	if (IS_ERR(larb->sub_comm_syscon) || ret ||
+	    larb->sub_comm_inport >= SMI_SUB_COMM_INPORT_NR) {
+		larb->sub_comm_syscon = NULL;
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int mtk_smi_larb_parse_reset_info(struct mtk_smi_larb *larb)
+{
+	struct device_node *reset_node;
+	struct device *dev = larb->dev;
+	int ret;
+
+	/* only larb with "resets" need to get reset setting */
+	reset_node = of_parse_phandle(dev->of_node, "resets", 0);
+	if (!reset_node)
+		return 0;
+	of_node_put(reset_node);
+
+	larb->rst_con = devm_reset_control_get(dev, "larb_rst");
+	if (IS_ERR(larb->rst_con))
+		return dev_err_probe(dev, PTR_ERR(larb->rst_con),
+				     "cannot get larb reset controller\n");
+
+	larb->nb.notifier_call = mtk_smi_genpd_callback;
+	ret = dev_pm_genpd_add_notifier(dev, &larb->nb);
+	if (ret) {
+		dev_err(dev, "Failed to add genpd callback %d\n", ret);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
 static int mtk_smi_larb_probe(struct platform_device *pdev)
 {
 	struct mtk_smi_larb *larb;
@@ -538,6 +662,7 @@  static int mtk_smi_larb_probe(struct platform_device *pdev)
 	if (!larb)
 		return -ENOMEM;
 
+	larb->dev = dev;
 	larb->larb_gen = of_device_get_match_data(dev);
 	larb->base = devm_platform_ioremap_resource(pdev, 0);
 	if (IS_ERR(larb->base))
@@ -554,15 +679,29 @@  static int mtk_smi_larb_probe(struct platform_device *pdev)
 	if (ret < 0)
 		return ret;
 
-	pm_runtime_enable(dev);
+	/* find sub common to clamp larb for ISP software reset */
+	ret = mtk_smi_larb_parse_clamp_info(larb);
+	if (ret) {
+		dev_err(dev, "Failed to get clamp setting for larb\n");
+		goto err_pm_disable;
+	}
+
+	ret = mtk_smi_larb_parse_reset_info(larb);
+	if (ret) {
+		dev_err(dev, "Failed to get power setting for larb\n");
+		goto err_pm_disable;
+	}
+
 	platform_set_drvdata(pdev, larb);
 	ret = component_add(dev, &mtk_smi_larb_component_ops);
 	if (ret)
 		goto err_pm_disable;
+
+	pm_runtime_enable(dev);
+
 	return 0;
 
 err_pm_disable:
-	pm_runtime_disable(dev);
 	device_link_remove(dev, larb->smi_common_dev);
 	return ret;
 }
@@ -686,6 +825,10 @@  static const struct mtk_smi_common_plat mtk_smi_common_mt8188_vpp = {
 	.init     = mtk_smi_common_mt8195_init,
 };
 
+static const struct mtk_smi_common_plat mtk_smi_sub_common_mt8188 = {
+	.type     = MTK_SMI_GEN2_SUB_COMM,
+};
+
 static const struct mtk_smi_common_plat mtk_smi_common_mt8192 = {
 	.type     = MTK_SMI_GEN2,
 	.has_gals = true,
@@ -729,6 +872,7 @@  static const struct of_device_id mtk_smi_common_of_ids[] = {
 	{.compatible = "mediatek,mt8186-smi-common", .data = &mtk_smi_common_mt8186},
 	{.compatible = "mediatek,mt8188-smi-common-vdo", .data = &mtk_smi_common_mt8188_vdo},
 	{.compatible = "mediatek,mt8188-smi-common-vpp", .data = &mtk_smi_common_mt8188_vpp},
+	{.compatible = "mediatek,mt8188-smi-sub-common", .data = &mtk_smi_sub_common_mt8188},
 	{.compatible = "mediatek,mt8192-smi-common", .data = &mtk_smi_common_mt8192},
 	{.compatible = "mediatek,mt8195-smi-common-vdo", .data = &mtk_smi_common_mt8195_vdo},
 	{.compatible = "mediatek,mt8195-smi-common-vpp", .data = &mtk_smi_common_mt8195_vpp},