diff mbox series

[v8,3/4] mailbox: mtk-cmdq: add gce ddr enable support flow

Message ID 20220930160638.7588-4-yongqiang.niu@mediatek.com (mailing list archive)
State New, archived
Headers show
Series mailbox: mtk-cmdq: add MT8186 support | expand

Commit Message

Yongqiang Niu Sept. 30, 2022, 4:06 p.m. UTC
add gce ddr enable control flow when gce suspend/resume

Signed-off-by: Yongqiang Niu <yongqiang.niu@mediatek.com>
---
 drivers/mailbox/mtk-cmdq-mailbox.c | 22 ++++++++++++++++++++++
 1 file changed, 22 insertions(+)

Comments

CK Hu (胡俊光) Oct. 3, 2022, 5:04 a.m. UTC | #1
Hi, Yongqiang:

On Sat, 2022-10-01 at 00:06 +0800, Yongqiang Niu wrote:
> add gce ddr enable control flow when gce suspend/resume
> 
> Signed-off-by: Yongqiang Niu <yongqiang.niu@mediatek.com>
> ---
>  drivers/mailbox/mtk-cmdq-mailbox.c | 22 ++++++++++++++++++++++
>  1 file changed, 22 insertions(+)
> 
> diff --git a/drivers/mailbox/mtk-cmdq-mailbox.c
> b/drivers/mailbox/mtk-cmdq-mailbox.c
> index 04eb44d89119..2db82ff838ed 100644
> --- a/drivers/mailbox/mtk-cmdq-mailbox.c
> +++ b/drivers/mailbox/mtk-cmdq-mailbox.c
> @@ -94,6 +94,18 @@ struct gce_plat {
>  	u32 gce_num;
>  };
>  
> +static void cmdq_sw_ddr_enable(struct cmdq *cmdq, bool enable)
> +{
> +	WARN_ON(clk_bulk_enable(cmdq->gce_num, cmdq->clocks));
> +
> +	if (enable)
> +		writel(GCE_DDR_EN | GCE_CTRL_BY_SW, cmdq->base +
> GCE_GCTL_VALUE);
> +	else
> +		writel(GCE_CTRL_BY_SW, cmdq->base + GCE_GCTL_VALUE);
> +
> +	clk_bulk_disable(cmdq->gce_num, cmdq->clocks);
> +}
> +
>  u8 cmdq_get_shift_pa(struct mbox_chan *chan)
>  {
>  	struct cmdq *cmdq = container_of(chan->mbox, struct cmdq,
> mbox);
> @@ -319,6 +331,9 @@ static int cmdq_suspend(struct device *dev)
>  	if (task_running)
>  		dev_warn(dev, "exist running task(s) in suspend\n");
>  
> +	if (cmdq->sw_ddr_en)
> +		cmdq_sw_ddr_enable(cmdq, false);

Why do you disable sw ddr function when suspend? Would the problem
happen when you disable sw ddr function. 

Regards,
CK

> +
>  	clk_bulk_unprepare(cmdq->gce_num, cmdq->clocks);
>  
>  	return 0;
> @@ -330,6 +345,10 @@ static int cmdq_resume(struct device *dev)
>  
>  	WARN_ON(clk_bulk_prepare(cmdq->gce_num, cmdq->clocks));
>  	cmdq->suspended = false;
> +
> +	if (cmdq->sw_ddr_en)
> +		cmdq_sw_ddr_enable(cmdq, true);
> +
>  	return 0;
>  }
>  
> @@ -337,6 +356,9 @@ static int cmdq_remove(struct platform_device
> *pdev)
>  {
>  	struct cmdq *cmdq = platform_get_drvdata(pdev);
>  
> +	if (cmdq->sw_ddr_en)
> +		cmdq_sw_ddr_enable(cmdq, false);
> +
>  	clk_bulk_unprepare(cmdq->gce_num, cmdq->clocks);
>  	return 0;
>  }
AngeloGioacchino Del Regno Oct. 3, 2022, 2:54 p.m. UTC | #2
Il 30/09/22 18:06, Yongqiang Niu ha scritto:
> add gce ddr enable control flow when gce suspend/resume
> 
> Signed-off-by: Yongqiang Niu <yongqiang.niu@mediatek.com>
> ---
>   drivers/mailbox/mtk-cmdq-mailbox.c | 22 ++++++++++++++++++++++
>   1 file changed, 22 insertions(+)
> 
> diff --git a/drivers/mailbox/mtk-cmdq-mailbox.c b/drivers/mailbox/mtk-cmdq-mailbox.c
> index 04eb44d89119..2db82ff838ed 100644
> --- a/drivers/mailbox/mtk-cmdq-mailbox.c
> +++ b/drivers/mailbox/mtk-cmdq-mailbox.c
> @@ -94,6 +94,18 @@ struct gce_plat {
>   	u32 gce_num;
>   };
>   
> +static void cmdq_sw_ddr_enable(struct cmdq *cmdq, bool enable)
> +{
> +	WARN_ON(clk_bulk_enable(cmdq->gce_num, cmdq->clocks));
> +
> +	if (enable)
> +		writel(GCE_DDR_EN | GCE_CTRL_BY_SW, cmdq->base + GCE_GCTL_VALUE);

My only concern here is about the previous value stored in the GCE_GCTL_VALUE
register, as you're overwriting it in its entirety with
GCE_DDR_EN | GCE_CTRL_BY_SW.

Can you guarantee that this register is not pre-initialized with some value,
and that these are the only bits to be `1` in this register?

Otherwise, you will have to readl and modify the bits instead... by the way,
if this register doesn't get any changes during runtime, you may cache it
at probe time to avoid reading it for every suspend/resume operation.

Regards,
Angelo
Yongqiang Niu Oct. 4, 2022, 9:30 a.m. UTC | #3
On Mon, 2022-10-03 at 13:04 +0800, CK Hu (胡俊光) wrote:
> Hi, Yongqiang:
> 
> On Sat, 2022-10-01 at 00:06 +0800, Yongqiang Niu wrote:
> > add gce ddr enable control flow when gce suspend/resume
> > 
> > Signed-off-by: Yongqiang Niu <yongqiang.niu@mediatek.com>
> > ---
> >  drivers/mailbox/mtk-cmdq-mailbox.c | 22 ++++++++++++++++++++++
> >  1 file changed, 22 insertions(+)
> > 
> > diff --git a/drivers/mailbox/mtk-cmdq-mailbox.c
> > b/drivers/mailbox/mtk-cmdq-mailbox.c
> > index 04eb44d89119..2db82ff838ed 100644
> > --- a/drivers/mailbox/mtk-cmdq-mailbox.c
> > +++ b/drivers/mailbox/mtk-cmdq-mailbox.c
> > @@ -94,6 +94,18 @@ struct gce_plat {
> >  	u32 gce_num;
> >  };
> >  
> > +static void cmdq_sw_ddr_enable(struct cmdq *cmdq, bool enable)
> > +{
> > +	WARN_ON(clk_bulk_enable(cmdq->gce_num, cmdq->clocks));
> > +
> > +	if (enable)
> > +		writel(GCE_DDR_EN | GCE_CTRL_BY_SW, cmdq->base +
> > GCE_GCTL_VALUE);
> > +	else
> > +		writel(GCE_CTRL_BY_SW, cmdq->base + GCE_GCTL_VALUE);
> > +
> > +	clk_bulk_disable(cmdq->gce_num, cmdq->clocks);
> > +}
> > +
> >  u8 cmdq_get_shift_pa(struct mbox_chan *chan)
> >  {
> >  	struct cmdq *cmdq = container_of(chan->mbox, struct cmdq,
> > mbox);
> > @@ -319,6 +331,9 @@ static int cmdq_suspend(struct device *dev)
> >  	if (task_running)
> >  		dev_warn(dev, "exist running task(s) in suspend\n");
> >  
> > +	if (cmdq->sw_ddr_en)
> > +		cmdq_sw_ddr_enable(cmdq, false);
> 
> Why do you disable sw ddr function when suspend? Would the problem
> happen when you disable sw ddr function. 
> 
> Regards,
> CK

when all cmdq instruction task has been processed done,
we need set this gce ddr enable to disable status to tell
cmdq hardware gce there is none task need process, and the hardware
can go into idle mode and no access ddr anymore, then the spm can go
into suspend.

the original issue is gce still access ddr when cmdq suspend function
call, but there is no task run.
so, we need control gce access ddr with this flow.
when cmdq suspend function, there is no task need process, we can
disable gce access ddr, to make sure system go into suspend success.


> 
> > +
> >  	clk_bulk_unprepare(cmdq->gce_num, cmdq->clocks);
> >  
> >  	return 0;
> > @@ -330,6 +345,10 @@ static int cmdq_resume(struct device *dev)
> >  
> >  	WARN_ON(clk_bulk_prepare(cmdq->gce_num, cmdq->clocks));
> >  	cmdq->suspended = false;
> > +
> > +	if (cmdq->sw_ddr_en)
> > +		cmdq_sw_ddr_enable(cmdq, true);
> > +
> >  	return 0;
> >  }
> >  
> > @@ -337,6 +356,9 @@ static int cmdq_remove(struct platform_device
> > *pdev)
> >  {
> >  	struct cmdq *cmdq = platform_get_drvdata(pdev);
> >  
> > +	if (cmdq->sw_ddr_en)
> > +		cmdq_sw_ddr_enable(cmdq, false);
> > +
> >  	clk_bulk_unprepare(cmdq->gce_num, cmdq->clocks);
> >  	return 0;
> >  }
Yongqiang Niu Oct. 4, 2022, 9:39 a.m. UTC | #4
On Mon, 2022-10-03 at 16:54 +0200, AngeloGioacchino Del Regno wrote:
> Il 30/09/22 18:06, Yongqiang Niu ha scritto:
> > add gce ddr enable control flow when gce suspend/resume
> > 
> > Signed-off-by: Yongqiang Niu <yongqiang.niu@mediatek.com>
> > ---
> >   drivers/mailbox/mtk-cmdq-mailbox.c | 22 ++++++++++++++++++++++
> >   1 file changed, 22 insertions(+)
> > 
> > diff --git a/drivers/mailbox/mtk-cmdq-mailbox.c
> > b/drivers/mailbox/mtk-cmdq-mailbox.c
> > index 04eb44d89119..2db82ff838ed 100644
> > --- a/drivers/mailbox/mtk-cmdq-mailbox.c
> > +++ b/drivers/mailbox/mtk-cmdq-mailbox.c
> > @@ -94,6 +94,18 @@ struct gce_plat {
> >   	u32 gce_num;
> >   };
> >   
> > +static void cmdq_sw_ddr_enable(struct cmdq *cmdq, bool enable)
> > +{
> > +	WARN_ON(clk_bulk_enable(cmdq->gce_num, cmdq->clocks));
> > +
> > +	if (enable)
> > +		writel(GCE_DDR_EN | GCE_CTRL_BY_SW, cmdq->base +
> > GCE_GCTL_VALUE);
> 
> My only concern here is about the previous value stored in the
> GCE_GCTL_VALUE
> register, as you're overwriting it in its entirety with
> GCE_DDR_EN | GCE_CTRL_BY_SW.
> 
> Can you guarantee that this register is not pre-initialized with some
> value,
> and that these are the only bits to be `1` in this register?
> 
> Otherwise, you will have to readl and modify the bits instead... by
> the way,
> if this register doesn't get any changes during runtime, you may
> cache it
> at probe time to avoid reading it for every suspend/resume operation.
> 
> Regards,
> Angelo
> 
> 

0x48[2:0] means control by software
0x48[18:16] means ddr enable 
0x48[2:0] is pre-condition of 0x48[18:16].
if we want set 0x48[18:16] ddr enable, 0x48[2:0] must be set at same
time.
and only these bits is useful, other bits is useless bits

we need set 0x48[18:16] to 0 disable gce access ddr when suspend.
and  set 0x48[18:16] to 0x7 enable gce access ddr when resume, there
will be cmdq client send task to process.
this control flow should controlled in suspend/resume flow.
CK Hu (胡俊光) Oct. 4, 2022, 9:40 a.m. UTC | #5
Hi, Yongqiang:

On Tue, 2022-10-04 at 17:30 +0800, yongqiang.niu wrote:
> On Mon, 2022-10-03 at 13:04 +0800, CK Hu (胡俊光) wrote:
> > Hi, Yongqiang:
> > 
> > On Sat, 2022-10-01 at 00:06 +0800, Yongqiang Niu wrote:
> > > add gce ddr enable control flow when gce suspend/resume
> > > 
> > > Signed-off-by: Yongqiang Niu <yongqiang.niu@mediatek.com>
> > > ---
> > >  drivers/mailbox/mtk-cmdq-mailbox.c | 22 ++++++++++++++++++++++
> > >  1 file changed, 22 insertions(+)
> > > 
> > > diff --git a/drivers/mailbox/mtk-cmdq-mailbox.c
> > > b/drivers/mailbox/mtk-cmdq-mailbox.c
> > > index 04eb44d89119..2db82ff838ed 100644
> > > --- a/drivers/mailbox/mtk-cmdq-mailbox.c
> > > +++ b/drivers/mailbox/mtk-cmdq-mailbox.c
> > > @@ -94,6 +94,18 @@ struct gce_plat {
> > >  	u32 gce_num;
> > >  };
> > >  
> > > +static void cmdq_sw_ddr_enable(struct cmdq *cmdq, bool enable)
> > > +{
> > > +	WARN_ON(clk_bulk_enable(cmdq->gce_num, cmdq->clocks));
> > > +
> > > +	if (enable)
> > > +		writel(GCE_DDR_EN | GCE_CTRL_BY_SW, cmdq->base +
> > > GCE_GCTL_VALUE);
> > > +	else
> > > +		writel(GCE_CTRL_BY_SW, cmdq->base + GCE_GCTL_VALUE);
> > > +
> > > +	clk_bulk_disable(cmdq->gce_num, cmdq->clocks);
> > > +}
> > > +
> > >  u8 cmdq_get_shift_pa(struct mbox_chan *chan)
> > >  {
> > >  	struct cmdq *cmdq = container_of(chan->mbox, struct cmdq,
> > > mbox);
> > > @@ -319,6 +331,9 @@ static int cmdq_suspend(struct device *dev)
> > >  	if (task_running)
> > >  		dev_warn(dev, "exist running task(s) in suspend\n");
> > >  
> > > +	if (cmdq->sw_ddr_en)
> > > +		cmdq_sw_ddr_enable(cmdq, false);
> > 
> > Why do you disable sw ddr function when suspend? Would the problem
> > happen when you disable sw ddr function. 
> > 
> > Regards,
> > CK
> 
> when all cmdq instruction task has been processed done,
> we need set this gce ddr enable to disable status to tell
> cmdq hardware gce there is none task need process, and the hardware
> can go into idle mode and no access ddr anymore, then the spm can go
> into suspend.
> 
> the original issue is gce still access ddr when cmdq suspend function
> call, but there is no task run.
> so, we need control gce access ddr with this flow.
> when cmdq suspend function, there is no task need process, we can
> disable gce access ddr, to make sure system go into suspend success.
> 

OK, and add these explanation to commit message.

> 
> > 
> > > +
> > >  	clk_bulk_unprepare(cmdq->gce_num, cmdq->clocks);
> > >  
> > >  	return 0;
> > > @@ -330,6 +345,10 @@ static int cmdq_resume(struct device *dev)
> > >  
> > >  	WARN_ON(clk_bulk_prepare(cmdq->gce_num, cmdq->clocks));
> > >  	cmdq->suspended = false;
> > > +
> > > +	if (cmdq->sw_ddr_en)
> > > +		cmdq_sw_ddr_enable(cmdq, true);
> > > +
> > >  	return 0;
> > >  }
> > >  
> > > @@ -337,6 +356,9 @@ static int cmdq_remove(struct platform_device
> > > *pdev)
> > >  {
> > >  	struct cmdq *cmdq = platform_get_drvdata(pdev);
> > >  
> > > +	if (cmdq->sw_ddr_en)
> > > +		cmdq_sw_ddr_enable(cmdq, false);
> > > +
> > >  	clk_bulk_unprepare(cmdq->gce_num, cmdq->clocks);
> > >  	return 0;
> > >  }
> 
>
AngeloGioacchino Del Regno Oct. 4, 2022, 9:55 a.m. UTC | #6
Il 04/10/22 11:39, yongqiang.niu ha scritto:
> On Mon, 2022-10-03 at 16:54 +0200, AngeloGioacchino Del Regno wrote:
>> Il 30/09/22 18:06, Yongqiang Niu ha scritto:
>>> add gce ddr enable control flow when gce suspend/resume
>>>
>>> Signed-off-by: Yongqiang Niu <yongqiang.niu@mediatek.com>
>>> ---
>>>    drivers/mailbox/mtk-cmdq-mailbox.c | 22 ++++++++++++++++++++++
>>>    1 file changed, 22 insertions(+)
>>>
>>> diff --git a/drivers/mailbox/mtk-cmdq-mailbox.c
>>> b/drivers/mailbox/mtk-cmdq-mailbox.c
>>> index 04eb44d89119..2db82ff838ed 100644
>>> --- a/drivers/mailbox/mtk-cmdq-mailbox.c
>>> +++ b/drivers/mailbox/mtk-cmdq-mailbox.c
>>> @@ -94,6 +94,18 @@ struct gce_plat {
>>>    	u32 gce_num;
>>>    };
>>>    
>>> +static void cmdq_sw_ddr_enable(struct cmdq *cmdq, bool enable)
>>> +{
>>> +	WARN_ON(clk_bulk_enable(cmdq->gce_num, cmdq->clocks));
>>> +
>>> +	if (enable)
>>> +		writel(GCE_DDR_EN | GCE_CTRL_BY_SW, cmdq->base +
>>> GCE_GCTL_VALUE);
>>
>> My only concern here is about the previous value stored in the
>> GCE_GCTL_VALUE
>> register, as you're overwriting it in its entirety with
>> GCE_DDR_EN | GCE_CTRL_BY_SW.
>>
>> Can you guarantee that this register is not pre-initialized with some
>> value,
>> and that these are the only bits to be `1` in this register?
>>
>> Otherwise, you will have to readl and modify the bits instead... by
>> the way,
>> if this register doesn't get any changes during runtime, you may
>> cache it
>> at probe time to avoid reading it for every suspend/resume operation.
>>
>> Regards,
>> Angelo
>>
>>
> 
> 0x48[2:0] means control by software
> 0x48[18:16] means ddr enable
> 0x48[2:0] is pre-condition of 0x48[18:16].
> if we want set 0x48[18:16] ddr enable, 0x48[2:0] must be set at same
> time.
> and only these bits is useful, other bits is useless bits
> 
> we need set 0x48[18:16] to 0 disable gce access ddr when suspend.
> and  set 0x48[18:16] to 0x7 enable gce access ddr when resume, there
> will be cmdq client send task to process.
> this control flow should controlled in suspend/resume flow.
> 
> 

That's perfect. Thanks for the explanation.

Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
diff mbox series

Patch

diff --git a/drivers/mailbox/mtk-cmdq-mailbox.c b/drivers/mailbox/mtk-cmdq-mailbox.c
index 04eb44d89119..2db82ff838ed 100644
--- a/drivers/mailbox/mtk-cmdq-mailbox.c
+++ b/drivers/mailbox/mtk-cmdq-mailbox.c
@@ -94,6 +94,18 @@  struct gce_plat {
 	u32 gce_num;
 };
 
+static void cmdq_sw_ddr_enable(struct cmdq *cmdq, bool enable)
+{
+	WARN_ON(clk_bulk_enable(cmdq->gce_num, cmdq->clocks));
+
+	if (enable)
+		writel(GCE_DDR_EN | GCE_CTRL_BY_SW, cmdq->base + GCE_GCTL_VALUE);
+	else
+		writel(GCE_CTRL_BY_SW, cmdq->base + GCE_GCTL_VALUE);
+
+	clk_bulk_disable(cmdq->gce_num, cmdq->clocks);
+}
+
 u8 cmdq_get_shift_pa(struct mbox_chan *chan)
 {
 	struct cmdq *cmdq = container_of(chan->mbox, struct cmdq, mbox);
@@ -319,6 +331,9 @@  static int cmdq_suspend(struct device *dev)
 	if (task_running)
 		dev_warn(dev, "exist running task(s) in suspend\n");
 
+	if (cmdq->sw_ddr_en)
+		cmdq_sw_ddr_enable(cmdq, false);
+
 	clk_bulk_unprepare(cmdq->gce_num, cmdq->clocks);
 
 	return 0;
@@ -330,6 +345,10 @@  static int cmdq_resume(struct device *dev)
 
 	WARN_ON(clk_bulk_prepare(cmdq->gce_num, cmdq->clocks));
 	cmdq->suspended = false;
+
+	if (cmdq->sw_ddr_en)
+		cmdq_sw_ddr_enable(cmdq, true);
+
 	return 0;
 }
 
@@ -337,6 +356,9 @@  static int cmdq_remove(struct platform_device *pdev)
 {
 	struct cmdq *cmdq = platform_get_drvdata(pdev);
 
+	if (cmdq->sw_ddr_en)
+		cmdq_sw_ddr_enable(cmdq, false);
+
 	clk_bulk_unprepare(cmdq->gce_num, cmdq->clocks);
 	return 0;
 }