diff mbox series

[1/7] media: hantro: add support for reset lines

Message ID 20211122184702.768341-2-jernej.skrabec@gmail.com (mailing list archive)
State New, archived
Headers show
Series media: hantro: add Allwinner H6 support | expand

Commit Message

Jernej Škrabec Nov. 22, 2021, 6:46 p.m. UTC
Some SoCs like Allwinner H6 use reset lines for resetting Hantro G2. Add
support for them.

Signed-off-by: Jernej Skrabec <jernej.skrabec@gmail.com>
---
 drivers/staging/media/hantro/hantro.h     |  3 +++
 drivers/staging/media/hantro/hantro_drv.c | 15 ++++++++++++++-
 2 files changed, 17 insertions(+), 1 deletion(-)

Comments

Andrzej Pietrasiewicz Nov. 23, 2021, 11:09 a.m. UTC | #1
Hi Jernej,

Thanks for the patch.

W dniu 22.11.2021 o 19:46, Jernej Skrabec pisze:
> Some SoCs like Allwinner H6 use reset lines for resetting Hantro G2. Add
> support for them.
> 
> Signed-off-by: Jernej Skrabec <jernej.skrabec@gmail.com>
> ---
>   drivers/staging/media/hantro/hantro.h     |  3 +++
>   drivers/staging/media/hantro/hantro_drv.c | 15 ++++++++++++++-
>   2 files changed, 17 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/staging/media/hantro/hantro.h b/drivers/staging/media/hantro/hantro.h
> index 7da23f7f207a..33eb3e092cc1 100644
> --- a/drivers/staging/media/hantro/hantro.h
> +++ b/drivers/staging/media/hantro/hantro.h
> @@ -16,6 +16,7 @@
>   #include <linux/videodev2.h>
>   #include <linux/wait.h>
>   #include <linux/clk.h>
> +#include <linux/reset.h>
>   
>   #include <media/v4l2-ctrls.h>
>   #include <media/v4l2-device.h>
> @@ -171,6 +172,7 @@ hantro_vdev_to_func(struct video_device *vdev)
>    * @dev:		Pointer to device for convenient logging using
>    *			dev_ macros.
>    * @clocks:		Array of clock handles.
> + * @resets:		Array of reset handles.
>    * @reg_bases:		Mapped addresses of VPU registers.
>    * @enc_base:		Mapped address of VPU encoder register for convenience.
>    * @dec_base:		Mapped address of VPU decoder register for convenience.
> @@ -190,6 +192,7 @@ struct hantro_dev {
>   	struct platform_device *pdev;
>   	struct device *dev;
>   	struct clk_bulk_data *clocks;
> +	struct reset_control *resets;
>   	void __iomem **reg_bases;
>   	void __iomem *enc_base;
>   	void __iomem *dec_base;
> diff --git a/drivers/staging/media/hantro/hantro_drv.c b/drivers/staging/media/hantro/hantro_drv.c
> index ab2467998d29..8c3de31f51b3 100644
> --- a/drivers/staging/media/hantro/hantro_drv.c
> +++ b/drivers/staging/media/hantro/hantro_drv.c
> @@ -905,6 +905,10 @@ static int hantro_probe(struct platform_device *pdev)
>   			return PTR_ERR(vpu->clocks[0].clk);
>   	}
>   
> +	vpu->resets = devm_reset_control_array_get(&pdev->dev, false, true);
> +	if (IS_ERR(vpu->resets))
> +		return PTR_ERR(vpu->resets);
> +
>   	num_bases = vpu->variant->num_regs ?: 1;
>   	vpu->reg_bases = devm_kcalloc(&pdev->dev, num_bases,
>   				      sizeof(*vpu->reg_bases), GFP_KERNEL);
> @@ -978,10 +982,16 @@ static int hantro_probe(struct platform_device *pdev)
>   	pm_runtime_use_autosuspend(vpu->dev);
>   	pm_runtime_enable(vpu->dev);
>   
> +	ret = reset_control_deassert(vpu->resets);
> +	if (ret) {
> +		dev_err(&pdev->dev, "Failed to deassert resets\n");
> +		return ret;
> +	}
> +
>   	ret = clk_bulk_prepare(vpu->variant->num_clocks, vpu->clocks);
>   	if (ret) {
>   		dev_err(&pdev->dev, "Failed to prepare clocks\n");
> -		return ret;
> +		goto err_rst_assert;

Before your patch is applied if clk_bulk_prepare() fails, we
simply return on the spot. After the patch is applied not only
do you...

>   	}
>   
>   	ret = v4l2_device_register(&pdev->dev, &vpu->v4l2_dev);
> @@ -1037,6 +1047,8 @@ static int hantro_probe(struct platform_device *pdev)
>   	v4l2_device_unregister(&vpu->v4l2_dev);
>   err_clk_unprepare:
>   	clk_bulk_unprepare(vpu->variant->num_clocks, vpu->clocks);
> +err_rst_assert:
> +	reset_control_assert(vpu->resets);

...revert the effect of reset_control_deassert(), you also...

>   	pm_runtime_dont_use_autosuspend(vpu->dev);
>   	pm_runtime_disable(vpu->dev);

... do pm_*() stuff. Is there any reason why this is needed?

Andrzej

>   	return ret;
> @@ -1055,6 +1067,7 @@ static int hantro_remove(struct platform_device *pdev)
>   	v4l2_m2m_release(vpu->m2m_dev);
>   	v4l2_device_unregister(&vpu->v4l2_dev);
>   	clk_bulk_unprepare(vpu->variant->num_clocks, vpu->clocks);
> +	reset_control_assert(vpu->resets);
>   	pm_runtime_dont_use_autosuspend(vpu->dev);
>   	pm_runtime_disable(vpu->dev);
>   	return 0;
>
Dan Carpenter Nov. 23, 2021, 2:59 p.m. UTC | #2
On Tue, Nov 23, 2021 at 12:09:03PM +0100, Andrzej Pietrasiewicz wrote:
> > diff --git a/drivers/staging/media/hantro/hantro_drv.c b/drivers/staging/media/hantro/hantro_drv.c
> > index ab2467998d29..8c3de31f51b3 100644
> > --- a/drivers/staging/media/hantro/hantro_drv.c
> > +++ b/drivers/staging/media/hantro/hantro_drv.c
> > @@ -905,6 +905,10 @@ static int hantro_probe(struct platform_device *pdev)
> >   			return PTR_ERR(vpu->clocks[0].clk);
> >   	}
> > +	vpu->resets = devm_reset_control_array_get(&pdev->dev, false, true);
> > +	if (IS_ERR(vpu->resets))
> > +		return PTR_ERR(vpu->resets);
> > +
> >   	num_bases = vpu->variant->num_regs ?: 1;
> >   	vpu->reg_bases = devm_kcalloc(&pdev->dev, num_bases,
> >   				      sizeof(*vpu->reg_bases), GFP_KERNEL);
> > @@ -978,10 +982,16 @@ static int hantro_probe(struct platform_device *pdev)
> >   	pm_runtime_use_autosuspend(vpu->dev);
> >   	pm_runtime_enable(vpu->dev);
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^
It looks like this is the pm stuff that we have to unwind on error

> > +	ret = reset_control_deassert(vpu->resets);
> > +	if (ret) {
> > +		dev_err(&pdev->dev, "Failed to deassert resets\n");
> > +		return ret;
                ^^^^^^^^^^
So this return should be a goto undo_pm_stuff


> > +	}
> > +
> >   	ret = clk_bulk_prepare(vpu->variant->num_clocks, vpu->clocks);
> >   	if (ret) {
> >   		dev_err(&pdev->dev, "Failed to prepare clocks\n");
> > -		return ret;

And this return should also have been a goto so it's a bug in the
original code.

> > +		goto err_rst_assert;
> 
> Before your patch is applied if clk_bulk_prepare() fails, we
> simply return on the spot. After the patch is applied not only
> do you...
> 
> >   	}
> >   	ret = v4l2_device_register(&pdev->dev, &vpu->v4l2_dev);
> > @@ -1037,6 +1047,8 @@ static int hantro_probe(struct platform_device *pdev)
> >   	v4l2_device_unregister(&vpu->v4l2_dev);
> >   err_clk_unprepare:
> >   	clk_bulk_unprepare(vpu->variant->num_clocks, vpu->clocks);
> > +err_rst_assert:
> > +	reset_control_assert(vpu->resets);
> 
> ...revert the effect of reset_control_deassert(), you also...
> 
> >   	pm_runtime_dont_use_autosuspend(vpu->dev);
> >   	pm_runtime_disable(vpu->dev);
> 
> ... do pm_*() stuff. Is there any reason why this is needed?

So, yes, it's needed, but you're correct to spot that it's not
consistent.

regards,
dan carpenter
Andrzej Pietrasiewicz Nov. 23, 2021, 4:36 p.m. UTC | #3
Hi Dan, hi Jernej,

W dniu 23.11.2021 o 15:59, Dan Carpenter pisze:
> On Tue, Nov 23, 2021 at 12:09:03PM +0100, Andrzej Pietrasiewicz wrote:
>>> diff --git a/drivers/staging/media/hantro/hantro_drv.c b/drivers/staging/media/hantro/hantro_drv.c
>>> index ab2467998d29..8c3de31f51b3 100644
>>> --- a/drivers/staging/media/hantro/hantro_drv.c
>>> +++ b/drivers/staging/media/hantro/hantro_drv.c
>>> @@ -905,6 +905,10 @@ static int hantro_probe(struct platform_device *pdev)
>>>    			return PTR_ERR(vpu->clocks[0].clk);
>>>    	}
>>> +	vpu->resets = devm_reset_control_array_get(&pdev->dev, false, true);
>>> +	if (IS_ERR(vpu->resets))
>>> +		return PTR_ERR(vpu->resets);
>>> +
>>>    	num_bases = vpu->variant->num_regs ?: 1;
>>>    	vpu->reg_bases = devm_kcalloc(&pdev->dev, num_bases,
>>>    				      sizeof(*vpu->reg_bases), GFP_KERNEL);
>>> @@ -978,10 +982,16 @@ static int hantro_probe(struct platform_device *pdev)
>>>    	pm_runtime_use_autosuspend(vpu->dev);
>>>    	pm_runtime_enable(vpu->dev);
>          ^^^^^^^^^^^^^^^^^^^^^^^^^^^
> It looks like this is the pm stuff that we have to unwind on error
> 
>>> +	ret = reset_control_deassert(vpu->resets);
>>> +	if (ret) {
>>> +		dev_err(&pdev->dev, "Failed to deassert resets\n");
>>> +		return ret;
>                  ^^^^^^^^^^
> So this return should be a goto undo_pm_stuff
> 
> 
>>> +	}
>>> +
>>>    	ret = clk_bulk_prepare(vpu->variant->num_clocks, vpu->clocks);
>>>    	if (ret) {
>>>    		dev_err(&pdev->dev, "Failed to prepare clocks\n");
>>> -		return ret;
> 
> And this return should also have been a goto so it's a bug in the
> original code.

So we probably want a separate patch addressing that first, and then
the series proper on top of that.

Regards,

Andrzej

> 
>>> +		goto err_rst_assert;
>>
>> Before your patch is applied if clk_bulk_prepare() fails, we
>> simply return on the spot. After the patch is applied not only
>> do you...
>>
>>>    	}
>>>    	ret = v4l2_device_register(&pdev->dev, &vpu->v4l2_dev);
>>> @@ -1037,6 +1047,8 @@ static int hantro_probe(struct platform_device *pdev)
>>>    	v4l2_device_unregister(&vpu->v4l2_dev);
>>>    err_clk_unprepare:
>>>    	clk_bulk_unprepare(vpu->variant->num_clocks, vpu->clocks);
>>> +err_rst_assert:
>>> +	reset_control_assert(vpu->resets);
>>
>> ...revert the effect of reset_control_deassert(), you also...
>>
>>>    	pm_runtime_dont_use_autosuspend(vpu->dev);
>>>    	pm_runtime_disable(vpu->dev);
>>
>> ... do pm_*() stuff. Is there any reason why this is needed?
> 
> So, yes, it's needed, but you're correct to spot that it's not
> consistent.
> 
> regards,
> dan carpenter
>
Jernej Škrabec Nov. 23, 2021, 4:46 p.m. UTC | #4
Hi all,

Dne torek, 23. november 2021 ob 17:36:57 CET je Andrzej Pietrasiewicz 
napisal(a):
> Hi Dan, hi Jernej,
> 
> W dniu 23.11.2021 o 15:59, Dan Carpenter pisze:
> > On Tue, Nov 23, 2021 at 12:09:03PM +0100, Andrzej Pietrasiewicz wrote:
> >>> diff --git a/drivers/staging/media/hantro/hantro_drv.c b/drivers/staging/
media/hantro/hantro_drv.c
> >>> index ab2467998d29..8c3de31f51b3 100644
> >>> --- a/drivers/staging/media/hantro/hantro_drv.c
> >>> +++ b/drivers/staging/media/hantro/hantro_drv.c
> >>> @@ -905,6 +905,10 @@ static int hantro_probe(struct platform_device 
*pdev)
> >>>    			return PTR_ERR(vpu->clocks[0].clk);
> >>>    	}
> >>> +	vpu->resets = devm_reset_control_array_get(&pdev->dev, false, 
true);
> >>> +	if (IS_ERR(vpu->resets))
> >>> +		return PTR_ERR(vpu->resets);
> >>> +
> >>>    	num_bases = vpu->variant->num_regs ?: 1;
> >>>    	vpu->reg_bases = devm_kcalloc(&pdev->dev, num_bases,
> >>>    				      sizeof(*vpu->reg_bases), 
GFP_KERNEL);
> >>> @@ -978,10 +982,16 @@ static int hantro_probe(struct platform_device 
*pdev)
> >>>    	pm_runtime_use_autosuspend(vpu->dev);
> >>>    	pm_runtime_enable(vpu->dev);
> >          ^^^^^^^^^^^^^^^^^^^^^^^^^^^
> > It looks like this is the pm stuff that we have to unwind on error
> > 
> >>> +	ret = reset_control_deassert(vpu->resets);
> >>> +	if (ret) {
> >>> +		dev_err(&pdev->dev, "Failed to deassert resets\n");
> >>> +		return ret;
> >                  ^^^^^^^^^^
> > So this return should be a goto undo_pm_stuff
> > 
> > 
> >>> +	}
> >>> +
> >>>    	ret = clk_bulk_prepare(vpu->variant->num_clocks, vpu->clocks);
> >>>    	if (ret) {
> >>>    		dev_err(&pdev->dev, "Failed to prepare clocks\n");
> >>> -		return ret;
> > 
> > And this return should also have been a goto so it's a bug in the
> > original code.
> 
> So we probably want a separate patch addressing that first, and then
> the series proper on top of that.

I was just about to suggest that.

Other drivers usually enable PM last, so they don't have PM calls in unwind 
code. However, I think current approach is just as valid (with a fix).

Best regards,
Jernej

> 
> Regards,
> 
> Andrzej
> 
> > 
> >>> +		goto err_rst_assert;
> >>
> >> Before your patch is applied if clk_bulk_prepare() fails, we
> >> simply return on the spot. After the patch is applied not only
> >> do you...
> >>
> >>>    	}
> >>>    	ret = v4l2_device_register(&pdev->dev, &vpu->v4l2_dev);
> >>> @@ -1037,6 +1047,8 @@ static int hantro_probe(struct platform_device 
*pdev)
> >>>    	v4l2_device_unregister(&vpu->v4l2_dev);
> >>>    err_clk_unprepare:
> >>>    	clk_bulk_unprepare(vpu->variant->num_clocks, vpu->clocks);
> >>> +err_rst_assert:
> >>> +	reset_control_assert(vpu->resets);
> >>
> >> ...revert the effect of reset_control_deassert(), you also...
> >>
> >>>    	pm_runtime_dont_use_autosuspend(vpu->dev);
> >>>    	pm_runtime_disable(vpu->dev);
> >>
> >> ... do pm_*() stuff. Is there any reason why this is needed?
> > 
> > So, yes, it's needed, but you're correct to spot that it's not
> > consistent.
> > 
> > regards,
> > dan carpenter
> > 
> 
>
Andrzej Pietrasiewicz Nov. 30, 2021, 10:39 a.m. UTC | #5
Hi Ezequiel,

W dniu 23.11.2021 o 19:07, Ezequiel Garcia pisze:
> Hi all,
> 
> Reset logic tends to be highly integration-specific, so it  could be more robust 
> to deal  with this in  the machine specific file. I have some vague recollection 
> of our experience here when we  integrated vc8000 last year, but I cannot recall 
> the outcome.
> 

Do you mean vpu->variant->init()?

That is the very first thing we do after the devm_*() calls. So any subsequent
initialization that fails would want vpu->variant->deinit(). Maybe at this
moment handling the resets at the common level is simpler? Existing drivers
will get NULL anyway from devm_reset_control_array_get().

Regards,

Andrzej

> I'm Ccing Bob who might remember better.
> 
> Thanks,
> Ezequiel
> 
> 
> 
> El mar., nov. 23, 2021 1:46 PM, Jernej Škrabec <jernej.skrabec@gmail.com 
> <mailto:jernej.skrabec@gmail.com>> escribió:
> 
>     Hi all,
> 
>     Dne torek, 23. november 2021 ob 17:36:57 CET je Andrzej Pietrasiewicz
>     napisal(a):
>      > Hi Dan, hi Jernej,
>      >
>      > W dniu 23.11.2021 o 15:59, Dan Carpenter pisze:
>      > > On Tue, Nov 23, 2021 at 12:09:03PM +0100, Andrzej Pietrasiewicz wrote:
>      > >>> diff --git a/drivers/staging/media/hantro/hantro_drv.c b/drivers/staging/
>     media/hantro/hantro_drv.c
>      > >>> index ab2467998d29..8c3de31f51b3 100644
>      > >>> --- a/drivers/staging/media/hantro/hantro_drv.c
>      > >>> +++ b/drivers/staging/media/hantro/hantro_drv.c
>      > >>> @@ -905,6 +905,10 @@ static int hantro_probe(struct platform_device
>     *pdev)
>      > >>>                           return PTR_ERR(vpu->clocks[0].clk);
>      > >>>           }
>      > >>> + vpu->resets = devm_reset_control_array_get(&pdev->dev, false,
>     true);
>      > >>> + if (IS_ERR(vpu->resets))
>      > >>> +         return PTR_ERR(vpu->resets);
>      > >>> +
>      > >>>           num_bases = vpu->variant->num_regs ?: 1;
>      > >>>           vpu->reg_bases = devm_kcalloc(&pdev->dev, num_bases,
>      > >>>                                         sizeof(*vpu->reg_bases),
>     GFP_KERNEL);
>      > >>> @@ -978,10 +982,16 @@ static int hantro_probe(struct platform_device
>     *pdev)
>      > >>>           pm_runtime_use_autosuspend(vpu->dev);
>      > >>>           pm_runtime_enable(vpu->dev);
>      > >          ^^^^^^^^^^^^^^^^^^^^^^^^^^^
>      > > It looks like this is the pm stuff that we have to unwind on error
>      > >
>      > >>> + ret = reset_control_deassert(vpu->resets);
>      > >>> + if (ret) {
>      > >>> +         dev_err(&pdev->dev, "Failed to deassert resets\n");
>      > >>> +         return ret;
>      > >                  ^^^^^^^^^^
>      > > So this return should be a goto undo_pm_stuff
>      > >
>      > >
>      > >>> + }
>      > >>> +
>      > >>>           ret = clk_bulk_prepare(vpu->variant->num_clocks, vpu->clocks);
>      > >>>           if (ret) {
>      > >>>                   dev_err(&pdev->dev, "Failed to prepare clocks\n");
>      > >>> -         return ret;
>      > >
>      > > And this return should also have been a goto so it's a bug in the
>      > > original code.
>      >
>      > So we probably want a separate patch addressing that first, and then
>      > the series proper on top of that.
> 
>     I was just about to suggest that.
> 
>     Other drivers usually enable PM last, so they don't have PM calls in unwind
>     code. However, I think current approach is just as valid (with a fix).
> 
>     Best regards,
>     Jernej
> 
>      >
>      > Regards,
>      >
>      > Andrzej
>      >
>      > >
>      > >>> +         goto err_rst_assert;
>      > >>
>      > >> Before your patch is applied if clk_bulk_prepare() fails, we
>      > >> simply return on the spot. After the patch is applied not only
>      > >> do you...
>      > >>
>      > >>>           }
>      > >>>           ret = v4l2_device_register(&pdev->dev, &vpu->v4l2_dev);
>      > >>> @@ -1037,6 +1047,8 @@ static int hantro_probe(struct platform_device
>     *pdev)
>      > >>>           v4l2_device_unregister(&vpu->v4l2_dev);
>      > >>>    err_clk_unprepare:
>      > >>>           clk_bulk_unprepare(vpu->variant->num_clocks, vpu->clocks);
>      > >>> +err_rst_assert:
>      > >>> + reset_control_assert(vpu->resets);
>      > >>
>      > >> ...revert the effect of reset_control_deassert(), you also...
>      > >>
>      > >>>           pm_runtime_dont_use_autosuspend(vpu->dev);
>      > >>>           pm_runtime_disable(vpu->dev);
>      > >>
>      > >> ... do pm_*() stuff. Is there any reason why this is needed?
>      > >
>      > > So, yes, it's needed, but you're correct to spot that it's not
>      > > consistent.
>      > >
>      > > regards,
>      > > dan carpenter
>      > >
>      >
>      >
> 
>
diff mbox series

Patch

diff --git a/drivers/staging/media/hantro/hantro.h b/drivers/staging/media/hantro/hantro.h
index 7da23f7f207a..33eb3e092cc1 100644
--- a/drivers/staging/media/hantro/hantro.h
+++ b/drivers/staging/media/hantro/hantro.h
@@ -16,6 +16,7 @@ 
 #include <linux/videodev2.h>
 #include <linux/wait.h>
 #include <linux/clk.h>
+#include <linux/reset.h>
 
 #include <media/v4l2-ctrls.h>
 #include <media/v4l2-device.h>
@@ -171,6 +172,7 @@  hantro_vdev_to_func(struct video_device *vdev)
  * @dev:		Pointer to device for convenient logging using
  *			dev_ macros.
  * @clocks:		Array of clock handles.
+ * @resets:		Array of reset handles.
  * @reg_bases:		Mapped addresses of VPU registers.
  * @enc_base:		Mapped address of VPU encoder register for convenience.
  * @dec_base:		Mapped address of VPU decoder register for convenience.
@@ -190,6 +192,7 @@  struct hantro_dev {
 	struct platform_device *pdev;
 	struct device *dev;
 	struct clk_bulk_data *clocks;
+	struct reset_control *resets;
 	void __iomem **reg_bases;
 	void __iomem *enc_base;
 	void __iomem *dec_base;
diff --git a/drivers/staging/media/hantro/hantro_drv.c b/drivers/staging/media/hantro/hantro_drv.c
index ab2467998d29..8c3de31f51b3 100644
--- a/drivers/staging/media/hantro/hantro_drv.c
+++ b/drivers/staging/media/hantro/hantro_drv.c
@@ -905,6 +905,10 @@  static int hantro_probe(struct platform_device *pdev)
 			return PTR_ERR(vpu->clocks[0].clk);
 	}
 
+	vpu->resets = devm_reset_control_array_get(&pdev->dev, false, true);
+	if (IS_ERR(vpu->resets))
+		return PTR_ERR(vpu->resets);
+
 	num_bases = vpu->variant->num_regs ?: 1;
 	vpu->reg_bases = devm_kcalloc(&pdev->dev, num_bases,
 				      sizeof(*vpu->reg_bases), GFP_KERNEL);
@@ -978,10 +982,16 @@  static int hantro_probe(struct platform_device *pdev)
 	pm_runtime_use_autosuspend(vpu->dev);
 	pm_runtime_enable(vpu->dev);
 
+	ret = reset_control_deassert(vpu->resets);
+	if (ret) {
+		dev_err(&pdev->dev, "Failed to deassert resets\n");
+		return ret;
+	}
+
 	ret = clk_bulk_prepare(vpu->variant->num_clocks, vpu->clocks);
 	if (ret) {
 		dev_err(&pdev->dev, "Failed to prepare clocks\n");
-		return ret;
+		goto err_rst_assert;
 	}
 
 	ret = v4l2_device_register(&pdev->dev, &vpu->v4l2_dev);
@@ -1037,6 +1047,8 @@  static int hantro_probe(struct platform_device *pdev)
 	v4l2_device_unregister(&vpu->v4l2_dev);
 err_clk_unprepare:
 	clk_bulk_unprepare(vpu->variant->num_clocks, vpu->clocks);
+err_rst_assert:
+	reset_control_assert(vpu->resets);
 	pm_runtime_dont_use_autosuspend(vpu->dev);
 	pm_runtime_disable(vpu->dev);
 	return ret;
@@ -1055,6 +1067,7 @@  static int hantro_remove(struct platform_device *pdev)
 	v4l2_m2m_release(vpu->m2m_dev);
 	v4l2_device_unregister(&vpu->v4l2_dev);
 	clk_bulk_unprepare(vpu->variant->num_clocks, vpu->clocks);
+	reset_control_assert(vpu->resets);
 	pm_runtime_dont_use_autosuspend(vpu->dev);
 	pm_runtime_disable(vpu->dev);
 	return 0;