All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v4] mailbox: mtk-cmdq: fix gce timeout issue
@ 2022-09-27  4:01 ` Yongqiang Niu
  0 siblings, 0 replies; 6+ messages in thread
From: Yongqiang Niu @ 2022-09-27  4:01 UTC (permalink / raw)
  To: CK Hu, Chun-Kuang Hu
  Cc: Jassi Brar, Matthias Brugger, linux-kernel, linux-arm-kernel,
	linux-mediatek, Project_Global_Chrome_Upstream_Group,
	Hsin-Yi Wang, Yongqiang Niu

1. enable gce ddr enable(gce reigster offset 0x48, bit 16 to 18) when gce work,
and disable gce ddr enable when gce work job done
2. add cmdq ddr enable/disable api, and control gce ddr enable/disable
to make sure it could protect when cmdq is multiple used by display and mdp

this is only for some SOC which has flag "gce_ddr_en".
for this kind of gce, there is a handshake flow between gce and ddr
hardware,
if not set ddr enable flag of gce, ddr will fall into idle mode,
then gce instructions will not process done.
we need set this flag of gce to tell ddr when gce is idle or busy
controlled by software flow.

ddr problem is a special case.
when test suspend/resume case, gce sometimes will pull ddr, and ddr can
not go to suspend.
if we set gce register 0x48 to 0x7, will fix this gce pull ddr issue,
as you have referred [1] and [2] (8192 and 8195)
but for mt8186, the gce is more special, except setting of [1] and [2],
we need add more setting set gce register 0x48 to (0x7 << 16 | 0x7)
when gce working to make sure gce could process all instructions ok.
this case just need normal bootup, if we not set this, display cmdq
task will timeout, and chrome homescreen will always black screen.

and with this patch, we have done these test on mt8186:
1.suspend/resume
2.boot up to home screen
3.playback video with youtube.

suspend issue is special gce hardware issue, gce client  driver
command already process done, but gce still pull ddr.

Signed-off-by: Yongqiang Niu <yongqiang.niu@mediatek.com>

---
change since v3:
split cmdq_sw_ddr_enable/cmdq_sw_ddr_disable into single api to
control mt8186 gce ddr enable flow
---

---
 drivers/mailbox/mtk-cmdq-mailbox.c | 61 ++++++++++++++++++++++++++++++
 1 file changed, 61 insertions(+)

diff --git a/drivers/mailbox/mtk-cmdq-mailbox.c b/drivers/mailbox/mtk-cmdq-mailbox.c
index 9465f9081515..650a1ed1a579 100644
--- a/drivers/mailbox/mtk-cmdq-mailbox.c
+++ b/drivers/mailbox/mtk-cmdq-mailbox.c
@@ -38,6 +38,8 @@
 #define CMDQ_THR_PRIORITY		0x40
 
 #define GCE_GCTL_VALUE			0x48
+#define GCE_CTRL_BY_SW				GENMASK(18, 16)
+#define GCE_DDR_EN				GENMASK(2, 0)
 
 #define CMDQ_THR_ACTIVE_SLOT_CYCLES	0x3200
 #define CMDQ_THR_ENABLED		0x1
@@ -80,16 +82,51 @@ struct cmdq {
 	bool			suspended;
 	u8			shift_pa;
 	bool			control_by_sw;
+	bool			sw_ddr_en;
 	u32			gce_num;
+	atomic_t		usage;
+	spinlock_t		lock;
 };
 
 struct gce_plat {
 	u32 thread_nr;
 	u8 shift;
 	bool control_by_sw;
+	bool sw_ddr_en;
 	u32 gce_num;
 };
 
+static void cmdq_sw_ddr_enable(struct cmdq *cmdq)
+{
+	s32 usage;
+	unsigned long flags;
+
+	spin_lock_irqsave(&cmdq->lock, flags);
+
+	usage = atomic_inc_return(&cmdq->usage);
+
+	if (usage <= 0)
+		dev_err(cmdq->mbox.dev, "ref count %d suspend %d\n",
+			usage, cmdq->suspended);
+	else if (usage == 1)
+		writel(GCE_DDR_EN + GCE_CTRL_BY_SW, cmdq->base + GCE_GCTL_VALUE);
+
+	spin_unlock_irqrestore(&cmdq->lock, flags);
+}
+
+static void cmdq_sw_ddr_disable(struct cmdq *cmdq)
+{
+	s32 usage;
+
+	usage = atomic_dec_return(&cmdq->usage);
+
+	if (usage < 0)
+		dev_err(cmdq->mbox.dev, "ref count %d suspend %d\n",
+			usage, cmdq->suspended);
+	else if (usage == 0)
+		writel(GCE_CTRL_BY_SW, cmdq->base + GCE_GCTL_VALUE);
+}
+
 u8 cmdq_get_shift_pa(struct mbox_chan *chan)
 {
 	struct cmdq *cmdq = container_of(chan->mbox, struct cmdq, mbox);
@@ -266,6 +303,10 @@ static void cmdq_thread_irq_handler(struct cmdq *cmdq,
 
 	if (list_empty(&thread->task_busy_list)) {
 		cmdq_thread_disable(cmdq, thread);
+
+		if (cmdq->sw_ddr_en)
+			cmdq_sw_ddr_disable(cmdq);
+
 		clk_bulk_disable(cmdq->gce_num, cmdq->clocks);
 	}
 }
@@ -357,6 +398,8 @@ static int cmdq_mbox_send_data(struct mbox_chan *chan, void *data)
 	if (list_empty(&thread->task_busy_list)) {
 		WARN_ON(clk_bulk_enable(cmdq->gce_num, cmdq->clocks));
 
+		if (cmdq->sw_ddr_en)
+			cmdq_sw_ddr_enable(cmdq);
 		/*
 		 * The thread reset will clear thread related register to 0,
 		 * including pc, end, priority, irq, suspend and enable. Thus
@@ -427,6 +470,9 @@ static void cmdq_mbox_shutdown(struct mbox_chan *chan)
 		kfree(task);
 	}
 
+	if (cmdq->sw_ddr_en)
+		cmdq_sw_ddr_disable(cmdq);
+
 	cmdq_thread_disable(cmdq, thread);
 	clk_bulk_disable(cmdq->gce_num, cmdq->clocks);
 
@@ -468,6 +514,10 @@ static int cmdq_mbox_flush(struct mbox_chan *chan, unsigned long timeout)
 
 	cmdq_thread_resume(thread);
 	cmdq_thread_disable(cmdq, thread);
+
+	if (cmdq->sw_ddr_en)
+		cmdq_sw_ddr_disable(cmdq);
+
 	clk_bulk_disable(cmdq->gce_num, cmdq->clocks);
 
 out:
@@ -543,6 +593,7 @@ static int cmdq_probe(struct platform_device *pdev)
 	cmdq->thread_nr = plat_data->thread_nr;
 	cmdq->shift_pa = plat_data->shift;
 	cmdq->control_by_sw = plat_data->control_by_sw;
+	cmdq->sw_ddr_en = plat_data->sw_ddr_en;
 	cmdq->gce_num = plat_data->gce_num;
 	cmdq->irq_mask = GENMASK(cmdq->thread_nr - 1, 0);
 	err = devm_request_irq(dev, cmdq->irq, cmdq_irq_handler, IRQF_SHARED,
@@ -615,6 +666,7 @@ static int cmdq_probe(struct platform_device *pdev)
 
 	WARN_ON(clk_bulk_prepare(cmdq->gce_num, cmdq->clocks));
 
+	spin_lock_init(&cmdq->lock);
 	cmdq_init(cmdq);
 
 	return 0;
@@ -660,9 +712,18 @@ static const struct gce_plat gce_plat_v6 = {
 	.gce_num = 2
 };
 
+static const struct gce_plat gce_plat_v7 = {
+	.thread_nr = 24,
+	.shift = 3,
+	.control_by_sw = true,
+	.sw_ddr_en = true,
+	.gce_num = 1
+};
+
 static const struct of_device_id cmdq_of_ids[] = {
 	{.compatible = "mediatek,mt8173-gce", .data = (void *)&gce_plat_v2},
 	{.compatible = "mediatek,mt8183-gce", .data = (void *)&gce_plat_v3},
+	{.compatible = "mediatek,mt8186-gce", .data = (void *)&gce_plat_v7},
 	{.compatible = "mediatek,mt6779-gce", .data = (void *)&gce_plat_v4},
 	{.compatible = "mediatek,mt8192-gce", .data = (void *)&gce_plat_v5},
 	{.compatible = "mediatek,mt8195-gce", .data = (void *)&gce_plat_v6},
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH v4] mailbox: mtk-cmdq: fix gce timeout issue
@ 2022-09-27  4:01 ` Yongqiang Niu
  0 siblings, 0 replies; 6+ messages in thread
From: Yongqiang Niu @ 2022-09-27  4:01 UTC (permalink / raw)
  To: CK Hu, Chun-Kuang Hu
  Cc: Jassi Brar, Matthias Brugger, linux-kernel, linux-arm-kernel,
	linux-mediatek, Project_Global_Chrome_Upstream_Group,
	Hsin-Yi Wang, Yongqiang Niu

1. enable gce ddr enable(gce reigster offset 0x48, bit 16 to 18) when gce work,
and disable gce ddr enable when gce work job done
2. add cmdq ddr enable/disable api, and control gce ddr enable/disable
to make sure it could protect when cmdq is multiple used by display and mdp

this is only for some SOC which has flag "gce_ddr_en".
for this kind of gce, there is a handshake flow between gce and ddr
hardware,
if not set ddr enable flag of gce, ddr will fall into idle mode,
then gce instructions will not process done.
we need set this flag of gce to tell ddr when gce is idle or busy
controlled by software flow.

ddr problem is a special case.
when test suspend/resume case, gce sometimes will pull ddr, and ddr can
not go to suspend.
if we set gce register 0x48 to 0x7, will fix this gce pull ddr issue,
as you have referred [1] and [2] (8192 and 8195)
but for mt8186, the gce is more special, except setting of [1] and [2],
we need add more setting set gce register 0x48 to (0x7 << 16 | 0x7)
when gce working to make sure gce could process all instructions ok.
this case just need normal bootup, if we not set this, display cmdq
task will timeout, and chrome homescreen will always black screen.

and with this patch, we have done these test on mt8186:
1.suspend/resume
2.boot up to home screen
3.playback video with youtube.

suspend issue is special gce hardware issue, gce client  driver
command already process done, but gce still pull ddr.

Signed-off-by: Yongqiang Niu <yongqiang.niu@mediatek.com>

---
change since v3:
split cmdq_sw_ddr_enable/cmdq_sw_ddr_disable into single api to
control mt8186 gce ddr enable flow
---

---
 drivers/mailbox/mtk-cmdq-mailbox.c | 61 ++++++++++++++++++++++++++++++
 1 file changed, 61 insertions(+)

diff --git a/drivers/mailbox/mtk-cmdq-mailbox.c b/drivers/mailbox/mtk-cmdq-mailbox.c
index 9465f9081515..650a1ed1a579 100644
--- a/drivers/mailbox/mtk-cmdq-mailbox.c
+++ b/drivers/mailbox/mtk-cmdq-mailbox.c
@@ -38,6 +38,8 @@
 #define CMDQ_THR_PRIORITY		0x40
 
 #define GCE_GCTL_VALUE			0x48
+#define GCE_CTRL_BY_SW				GENMASK(18, 16)
+#define GCE_DDR_EN				GENMASK(2, 0)
 
 #define CMDQ_THR_ACTIVE_SLOT_CYCLES	0x3200
 #define CMDQ_THR_ENABLED		0x1
@@ -80,16 +82,51 @@ struct cmdq {
 	bool			suspended;
 	u8			shift_pa;
 	bool			control_by_sw;
+	bool			sw_ddr_en;
 	u32			gce_num;
+	atomic_t		usage;
+	spinlock_t		lock;
 };
 
 struct gce_plat {
 	u32 thread_nr;
 	u8 shift;
 	bool control_by_sw;
+	bool sw_ddr_en;
 	u32 gce_num;
 };
 
+static void cmdq_sw_ddr_enable(struct cmdq *cmdq)
+{
+	s32 usage;
+	unsigned long flags;
+
+	spin_lock_irqsave(&cmdq->lock, flags);
+
+	usage = atomic_inc_return(&cmdq->usage);
+
+	if (usage <= 0)
+		dev_err(cmdq->mbox.dev, "ref count %d suspend %d\n",
+			usage, cmdq->suspended);
+	else if (usage == 1)
+		writel(GCE_DDR_EN + GCE_CTRL_BY_SW, cmdq->base + GCE_GCTL_VALUE);
+
+	spin_unlock_irqrestore(&cmdq->lock, flags);
+}
+
+static void cmdq_sw_ddr_disable(struct cmdq *cmdq)
+{
+	s32 usage;
+
+	usage = atomic_dec_return(&cmdq->usage);
+
+	if (usage < 0)
+		dev_err(cmdq->mbox.dev, "ref count %d suspend %d\n",
+			usage, cmdq->suspended);
+	else if (usage == 0)
+		writel(GCE_CTRL_BY_SW, cmdq->base + GCE_GCTL_VALUE);
+}
+
 u8 cmdq_get_shift_pa(struct mbox_chan *chan)
 {
 	struct cmdq *cmdq = container_of(chan->mbox, struct cmdq, mbox);
@@ -266,6 +303,10 @@ static void cmdq_thread_irq_handler(struct cmdq *cmdq,
 
 	if (list_empty(&thread->task_busy_list)) {
 		cmdq_thread_disable(cmdq, thread);
+
+		if (cmdq->sw_ddr_en)
+			cmdq_sw_ddr_disable(cmdq);
+
 		clk_bulk_disable(cmdq->gce_num, cmdq->clocks);
 	}
 }
@@ -357,6 +398,8 @@ static int cmdq_mbox_send_data(struct mbox_chan *chan, void *data)
 	if (list_empty(&thread->task_busy_list)) {
 		WARN_ON(clk_bulk_enable(cmdq->gce_num, cmdq->clocks));
 
+		if (cmdq->sw_ddr_en)
+			cmdq_sw_ddr_enable(cmdq);
 		/*
 		 * The thread reset will clear thread related register to 0,
 		 * including pc, end, priority, irq, suspend and enable. Thus
@@ -427,6 +470,9 @@ static void cmdq_mbox_shutdown(struct mbox_chan *chan)
 		kfree(task);
 	}
 
+	if (cmdq->sw_ddr_en)
+		cmdq_sw_ddr_disable(cmdq);
+
 	cmdq_thread_disable(cmdq, thread);
 	clk_bulk_disable(cmdq->gce_num, cmdq->clocks);
 
@@ -468,6 +514,10 @@ static int cmdq_mbox_flush(struct mbox_chan *chan, unsigned long timeout)
 
 	cmdq_thread_resume(thread);
 	cmdq_thread_disable(cmdq, thread);
+
+	if (cmdq->sw_ddr_en)
+		cmdq_sw_ddr_disable(cmdq);
+
 	clk_bulk_disable(cmdq->gce_num, cmdq->clocks);
 
 out:
@@ -543,6 +593,7 @@ static int cmdq_probe(struct platform_device *pdev)
 	cmdq->thread_nr = plat_data->thread_nr;
 	cmdq->shift_pa = plat_data->shift;
 	cmdq->control_by_sw = plat_data->control_by_sw;
+	cmdq->sw_ddr_en = plat_data->sw_ddr_en;
 	cmdq->gce_num = plat_data->gce_num;
 	cmdq->irq_mask = GENMASK(cmdq->thread_nr - 1, 0);
 	err = devm_request_irq(dev, cmdq->irq, cmdq_irq_handler, IRQF_SHARED,
@@ -615,6 +666,7 @@ static int cmdq_probe(struct platform_device *pdev)
 
 	WARN_ON(clk_bulk_prepare(cmdq->gce_num, cmdq->clocks));
 
+	spin_lock_init(&cmdq->lock);
 	cmdq_init(cmdq);
 
 	return 0;
@@ -660,9 +712,18 @@ static const struct gce_plat gce_plat_v6 = {
 	.gce_num = 2
 };
 
+static const struct gce_plat gce_plat_v7 = {
+	.thread_nr = 24,
+	.shift = 3,
+	.control_by_sw = true,
+	.sw_ddr_en = true,
+	.gce_num = 1
+};
+
 static const struct of_device_id cmdq_of_ids[] = {
 	{.compatible = "mediatek,mt8173-gce", .data = (void *)&gce_plat_v2},
 	{.compatible = "mediatek,mt8183-gce", .data = (void *)&gce_plat_v3},
+	{.compatible = "mediatek,mt8186-gce", .data = (void *)&gce_plat_v7},
 	{.compatible = "mediatek,mt6779-gce", .data = (void *)&gce_plat_v4},
 	{.compatible = "mediatek,mt8192-gce", .data = (void *)&gce_plat_v5},
 	{.compatible = "mediatek,mt8195-gce", .data = (void *)&gce_plat_v6},
-- 
2.25.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [PATCH v4] mailbox: mtk-cmdq: fix gce timeout issue
  2022-09-27  4:01 ` Yongqiang Niu
@ 2022-09-27  5:19   ` CK Hu (胡俊光)
  -1 siblings, 0 replies; 6+ messages in thread
From: CK Hu (胡俊光) @ 2022-09-27  5:19 UTC (permalink / raw)
  To: Yongqiang Niu (牛永强), chunkuang.hu
  Cc: jassisinghbrar, matthias.bgg, linux-kernel, linux-arm-kernel,
	linux-mediatek, Project_Global_Chrome_Upstream_Group, hsinyi

Hi, Yongqiang:

On Tue, 2022-09-27 at 12:01 +0800, Yongqiang Niu wrote:
> 1. enable gce ddr enable(gce reigster offset 0x48, bit 16 to 18) when
> gce work,
> and disable gce ddr enable when gce work job done
> 2. add cmdq ddr enable/disable api, and control gce ddr
> enable/disable
> to make sure it could protect when cmdq is multiple used by display
> and mdp
> 
> this is only for some SOC which has flag "gce_ddr_en".
> for this kind of gce, there is a handshake flow between gce and ddr
> hardware,
> if not set ddr enable flag of gce, ddr will fall into idle mode,
> then gce instructions will not process done.
> we need set this flag of gce to tell ddr when gce is idle or busy
> controlled by software flow.
> 
> ddr problem is a special case.
> when test suspend/resume case, gce sometimes will pull ddr, and ddr
> can
> not go to suspend.
> if we set gce register 0x48 to 0x7, will fix this gce pull ddr issue,
> as you have referred [1] and [2] (8192 and 8195)
> but for mt8186, the gce is more special, except setting of [1] and
> [2],
> we need add more setting set gce register 0x48 to (0x7 << 16 | 0x7)
> when gce working to make sure gce could process all instructions ok.
> this case just need normal bootup, if we not set this, display cmdq
> task will timeout, and chrome homescreen will always black screen.
> 
> and with this patch, we have done these test on mt8186:
> 1.suspend/resume
> 2.boot up to home screen
> 3.playback video with youtube.
> 
> suspend issue is special gce hardware issue, gce client  driver
> command already process done, but gce still pull ddr.
> 
> Signed-off-by: Yongqiang Niu <yongqiang.niu@mediatek.com>
> 
> ---
> change since v3:
> split cmdq_sw_ddr_enable/cmdq_sw_ddr_disable into single api to
> control mt8186 gce ddr enable flow
> ---
> 
> ---
>  drivers/mailbox/mtk-cmdq-mailbox.c | 61
> ++++++++++++++++++++++++++++++
>  1 file changed, 61 insertions(+)
> 
> diff --git a/drivers/mailbox/mtk-cmdq-mailbox.c
> b/drivers/mailbox/mtk-cmdq-mailbox.c
> index 9465f9081515..650a1ed1a579 100644
> --- a/drivers/mailbox/mtk-cmdq-mailbox.c
> +++ b/drivers/mailbox/mtk-cmdq-mailbox.c
> @@ -38,6 +38,8 @@
>  #define CMDQ_THR_PRIORITY		0x40
>  
>  #define GCE_GCTL_VALUE			0x48
> +#define GCE_CTRL_BY_SW				GENMASK(18, 16)
> +#define GCE_DDR_EN				GENMASK(2, 0)
>  
>  #define CMDQ_THR_ACTIVE_SLOT_CYCLES	0x3200
>  #define CMDQ_THR_ENABLED		0x1
> @@ -80,16 +82,51 @@ struct cmdq {
>  	bool			suspended;
>  	u8			shift_pa;
>  	bool			control_by_sw;
> +	bool			sw_ddr_en;
>  	u32			gce_num;
> +	atomic_t		usage;
> +	spinlock_t		lock;
>  };
>  
>  struct gce_plat {
>  	u32 thread_nr;
>  	u8 shift;
>  	bool control_by_sw;
> +	bool sw_ddr_en;
>  	u32 gce_num;
>  };
>  
> +static void cmdq_sw_ddr_enable(struct cmdq *cmdq)
> +{
> +	s32 usage;
> +	unsigned long flags;
> +
> +	spin_lock_irqsave(&cmdq->lock, flags);
> +
> +	usage = atomic_inc_return(&cmdq->usage);
> +
> +	if (usage <= 0)
> +		dev_err(cmdq->mbox.dev, "ref count %d suspend %d\n",
> +			usage, cmdq->suspended);
> +	else if (usage == 1)
> +		writel(GCE_DDR_EN + GCE_CTRL_BY_SW, cmdq->base +
> GCE_GCTL_VALUE);
> +
> +	spin_unlock_irqrestore(&cmdq->lock, flags);
> +}
> +
> +static void cmdq_sw_ddr_disable(struct cmdq *cmdq)
> +{
> +	s32 usage;
> +
> +	usage = atomic_dec_return(&cmdq->usage);
> +
> +	if (usage < 0)
> +		dev_err(cmdq->mbox.dev, "ref count %d suspend %d\n",
> +			usage, cmdq->suspended);
> +	else if (usage == 0)
> +		writel(GCE_CTRL_BY_SW, cmdq->base + GCE_GCTL_VALUE);
> +}
> +
>  u8 cmdq_get_shift_pa(struct mbox_chan *chan)
>  {
>  	struct cmdq *cmdq = container_of(chan->mbox, struct cmdq,
> mbox);
> @@ -266,6 +303,10 @@ static void cmdq_thread_irq_handler(struct cmdq
> *cmdq,
>  
>  	if (list_empty(&thread->task_busy_list)) {
>  		cmdq_thread_disable(cmdq, thread);
> +
> +		if (cmdq->sw_ddr_en)
> +			cmdq_sw_ddr_disable(cmdq);
> +
>  		clk_bulk_disable(cmdq->gce_num, cmdq->clocks);
>  	}
>  }
> @@ -357,6 +398,8 @@ static int cmdq_mbox_send_data(struct mbox_chan
> *chan, void *data)
>  	if (list_empty(&thread->task_busy_list)) {
>  		WARN_ON(clk_bulk_enable(cmdq->gce_num, cmdq->clocks));
>  
> +		if (cmdq->sw_ddr_en)
> +			cmdq_sw_ddr_enable(cmdq);

Why do you dynamically enable/disable it when process every packet? Why
not enable it in cmdq_mbox_startup() and disable it in
cmdq_mbox_shutdown(), so you don't need an extra lock for spinlock.

Regards,
CK

>  		/*
>  		 * The thread reset will clear thread related register
> to 0,
>  		 * including pc, end, priority, irq, suspend and
> enable. Thus
> @@ -427,6 +470,9 @@ static void cmdq_mbox_shutdown(struct mbox_chan
> *chan)
>  		kfree(task);
>  	}
>  
> +	if (cmdq->sw_ddr_en)
> +		cmdq_sw_ddr_disable(cmdq);
> +
>  	cmdq_thread_disable(cmdq, thread);
>  	clk_bulk_disable(cmdq->gce_num, cmdq->clocks);
>  
> @@ -468,6 +514,10 @@ static int cmdq_mbox_flush(struct mbox_chan
> *chan, unsigned long timeout)
>  
>  	cmdq_thread_resume(thread);
>  	cmdq_thread_disable(cmdq, thread);
> +
> +	if (cmdq->sw_ddr_en)
> +		cmdq_sw_ddr_disable(cmdq);
> +
>  	clk_bulk_disable(cmdq->gce_num, cmdq->clocks);
>  
>  out:
> @@ -543,6 +593,7 @@ static int cmdq_probe(struct platform_device
> *pdev)
>  	cmdq->thread_nr = plat_data->thread_nr;
>  	cmdq->shift_pa = plat_data->shift;
>  	cmdq->control_by_sw = plat_data->control_by_sw;
> +	cmdq->sw_ddr_en = plat_data->sw_ddr_en;
>  	cmdq->gce_num = plat_data->gce_num;
>  	cmdq->irq_mask = GENMASK(cmdq->thread_nr - 1, 0);
>  	err = devm_request_irq(dev, cmdq->irq, cmdq_irq_handler,
> IRQF_SHARED,
> @@ -615,6 +666,7 @@ static int cmdq_probe(struct platform_device
> *pdev)
>  
>  	WARN_ON(clk_bulk_prepare(cmdq->gce_num, cmdq->clocks));
>  
> +	spin_lock_init(&cmdq->lock);
>  	cmdq_init(cmdq);
>  
>  	return 0;
> @@ -660,9 +712,18 @@ static const struct gce_plat gce_plat_v6 = {
>  	.gce_num = 2
>  };
>  
> +static const struct gce_plat gce_plat_v7 = {
> +	.thread_nr = 24,
> +	.shift = 3,
> +	.control_by_sw = true,
> +	.sw_ddr_en = true,
> +	.gce_num = 1
> +};
> +
>  static const struct of_device_id cmdq_of_ids[] = {
>  	{.compatible = "mediatek,mt8173-gce", .data = (void
> *)&gce_plat_v2},
>  	{.compatible = "mediatek,mt8183-gce", .data = (void
> *)&gce_plat_v3},
> +	{.compatible = "mediatek,mt8186-gce", .data = (void
> *)&gce_plat_v7},
>  	{.compatible = "mediatek,mt6779-gce", .data = (void
> *)&gce_plat_v4},
>  	{.compatible = "mediatek,mt8192-gce", .data = (void
> *)&gce_plat_v5},
>  	{.compatible = "mediatek,mt8195-gce", .data = (void
> *)&gce_plat_v6},

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH v4] mailbox: mtk-cmdq: fix gce timeout issue
@ 2022-09-27  5:19   ` CK Hu (胡俊光)
  0 siblings, 0 replies; 6+ messages in thread
From: CK Hu (胡俊光) @ 2022-09-27  5:19 UTC (permalink / raw)
  To: Yongqiang Niu (牛永强), chunkuang.hu
  Cc: jassisinghbrar, matthias.bgg, linux-kernel, linux-arm-kernel,
	linux-mediatek, Project_Global_Chrome_Upstream_Group, hsinyi

Hi, Yongqiang:

On Tue, 2022-09-27 at 12:01 +0800, Yongqiang Niu wrote:
> 1. enable gce ddr enable(gce reigster offset 0x48, bit 16 to 18) when
> gce work,
> and disable gce ddr enable when gce work job done
> 2. add cmdq ddr enable/disable api, and control gce ddr
> enable/disable
> to make sure it could protect when cmdq is multiple used by display
> and mdp
> 
> this is only for some SOC which has flag "gce_ddr_en".
> for this kind of gce, there is a handshake flow between gce and ddr
> hardware,
> if not set ddr enable flag of gce, ddr will fall into idle mode,
> then gce instructions will not process done.
> we need set this flag of gce to tell ddr when gce is idle or busy
> controlled by software flow.
> 
> ddr problem is a special case.
> when test suspend/resume case, gce sometimes will pull ddr, and ddr
> can
> not go to suspend.
> if we set gce register 0x48 to 0x7, will fix this gce pull ddr issue,
> as you have referred [1] and [2] (8192 and 8195)
> but for mt8186, the gce is more special, except setting of [1] and
> [2],
> we need add more setting set gce register 0x48 to (0x7 << 16 | 0x7)
> when gce working to make sure gce could process all instructions ok.
> this case just need normal bootup, if we not set this, display cmdq
> task will timeout, and chrome homescreen will always black screen.
> 
> and with this patch, we have done these test on mt8186:
> 1.suspend/resume
> 2.boot up to home screen
> 3.playback video with youtube.
> 
> suspend issue is special gce hardware issue, gce client  driver
> command already process done, but gce still pull ddr.
> 
> Signed-off-by: Yongqiang Niu <yongqiang.niu@mediatek.com>
> 
> ---
> change since v3:
> split cmdq_sw_ddr_enable/cmdq_sw_ddr_disable into single api to
> control mt8186 gce ddr enable flow
> ---
> 
> ---
>  drivers/mailbox/mtk-cmdq-mailbox.c | 61
> ++++++++++++++++++++++++++++++
>  1 file changed, 61 insertions(+)
> 
> diff --git a/drivers/mailbox/mtk-cmdq-mailbox.c
> b/drivers/mailbox/mtk-cmdq-mailbox.c
> index 9465f9081515..650a1ed1a579 100644
> --- a/drivers/mailbox/mtk-cmdq-mailbox.c
> +++ b/drivers/mailbox/mtk-cmdq-mailbox.c
> @@ -38,6 +38,8 @@
>  #define CMDQ_THR_PRIORITY		0x40
>  
>  #define GCE_GCTL_VALUE			0x48
> +#define GCE_CTRL_BY_SW				GENMASK(18, 16)
> +#define GCE_DDR_EN				GENMASK(2, 0)
>  
>  #define CMDQ_THR_ACTIVE_SLOT_CYCLES	0x3200
>  #define CMDQ_THR_ENABLED		0x1
> @@ -80,16 +82,51 @@ struct cmdq {
>  	bool			suspended;
>  	u8			shift_pa;
>  	bool			control_by_sw;
> +	bool			sw_ddr_en;
>  	u32			gce_num;
> +	atomic_t		usage;
> +	spinlock_t		lock;
>  };
>  
>  struct gce_plat {
>  	u32 thread_nr;
>  	u8 shift;
>  	bool control_by_sw;
> +	bool sw_ddr_en;
>  	u32 gce_num;
>  };
>  
> +static void cmdq_sw_ddr_enable(struct cmdq *cmdq)
> +{
> +	s32 usage;
> +	unsigned long flags;
> +
> +	spin_lock_irqsave(&cmdq->lock, flags);
> +
> +	usage = atomic_inc_return(&cmdq->usage);
> +
> +	if (usage <= 0)
> +		dev_err(cmdq->mbox.dev, "ref count %d suspend %d\n",
> +			usage, cmdq->suspended);
> +	else if (usage == 1)
> +		writel(GCE_DDR_EN + GCE_CTRL_BY_SW, cmdq->base +
> GCE_GCTL_VALUE);
> +
> +	spin_unlock_irqrestore(&cmdq->lock, flags);
> +}
> +
> +static void cmdq_sw_ddr_disable(struct cmdq *cmdq)
> +{
> +	s32 usage;
> +
> +	usage = atomic_dec_return(&cmdq->usage);
> +
> +	if (usage < 0)
> +		dev_err(cmdq->mbox.dev, "ref count %d suspend %d\n",
> +			usage, cmdq->suspended);
> +	else if (usage == 0)
> +		writel(GCE_CTRL_BY_SW, cmdq->base + GCE_GCTL_VALUE);
> +}
> +
>  u8 cmdq_get_shift_pa(struct mbox_chan *chan)
>  {
>  	struct cmdq *cmdq = container_of(chan->mbox, struct cmdq,
> mbox);
> @@ -266,6 +303,10 @@ static void cmdq_thread_irq_handler(struct cmdq
> *cmdq,
>  
>  	if (list_empty(&thread->task_busy_list)) {
>  		cmdq_thread_disable(cmdq, thread);
> +
> +		if (cmdq->sw_ddr_en)
> +			cmdq_sw_ddr_disable(cmdq);
> +
>  		clk_bulk_disable(cmdq->gce_num, cmdq->clocks);
>  	}
>  }
> @@ -357,6 +398,8 @@ static int cmdq_mbox_send_data(struct mbox_chan
> *chan, void *data)
>  	if (list_empty(&thread->task_busy_list)) {
>  		WARN_ON(clk_bulk_enable(cmdq->gce_num, cmdq->clocks));
>  
> +		if (cmdq->sw_ddr_en)
> +			cmdq_sw_ddr_enable(cmdq);

Why do you dynamically enable/disable it when process every packet? Why
not enable it in cmdq_mbox_startup() and disable it in
cmdq_mbox_shutdown(), so you don't need an extra lock for spinlock.

Regards,
CK

>  		/*
>  		 * The thread reset will clear thread related register
> to 0,
>  		 * including pc, end, priority, irq, suspend and
> enable. Thus
> @@ -427,6 +470,9 @@ static void cmdq_mbox_shutdown(struct mbox_chan
> *chan)
>  		kfree(task);
>  	}
>  
> +	if (cmdq->sw_ddr_en)
> +		cmdq_sw_ddr_disable(cmdq);
> +
>  	cmdq_thread_disable(cmdq, thread);
>  	clk_bulk_disable(cmdq->gce_num, cmdq->clocks);
>  
> @@ -468,6 +514,10 @@ static int cmdq_mbox_flush(struct mbox_chan
> *chan, unsigned long timeout)
>  
>  	cmdq_thread_resume(thread);
>  	cmdq_thread_disable(cmdq, thread);
> +
> +	if (cmdq->sw_ddr_en)
> +		cmdq_sw_ddr_disable(cmdq);
> +
>  	clk_bulk_disable(cmdq->gce_num, cmdq->clocks);
>  
>  out:
> @@ -543,6 +593,7 @@ static int cmdq_probe(struct platform_device
> *pdev)
>  	cmdq->thread_nr = plat_data->thread_nr;
>  	cmdq->shift_pa = plat_data->shift;
>  	cmdq->control_by_sw = plat_data->control_by_sw;
> +	cmdq->sw_ddr_en = plat_data->sw_ddr_en;
>  	cmdq->gce_num = plat_data->gce_num;
>  	cmdq->irq_mask = GENMASK(cmdq->thread_nr - 1, 0);
>  	err = devm_request_irq(dev, cmdq->irq, cmdq_irq_handler,
> IRQF_SHARED,
> @@ -615,6 +666,7 @@ static int cmdq_probe(struct platform_device
> *pdev)
>  
>  	WARN_ON(clk_bulk_prepare(cmdq->gce_num, cmdq->clocks));
>  
> +	spin_lock_init(&cmdq->lock);
>  	cmdq_init(cmdq);
>  
>  	return 0;
> @@ -660,9 +712,18 @@ static const struct gce_plat gce_plat_v6 = {
>  	.gce_num = 2
>  };
>  
> +static const struct gce_plat gce_plat_v7 = {
> +	.thread_nr = 24,
> +	.shift = 3,
> +	.control_by_sw = true,
> +	.sw_ddr_en = true,
> +	.gce_num = 1
> +};
> +
>  static const struct of_device_id cmdq_of_ids[] = {
>  	{.compatible = "mediatek,mt8173-gce", .data = (void
> *)&gce_plat_v2},
>  	{.compatible = "mediatek,mt8183-gce", .data = (void
> *)&gce_plat_v3},
> +	{.compatible = "mediatek,mt8186-gce", .data = (void
> *)&gce_plat_v7},
>  	{.compatible = "mediatek,mt6779-gce", .data = (void
> *)&gce_plat_v4},
>  	{.compatible = "mediatek,mt8192-gce", .data = (void
> *)&gce_plat_v5},
>  	{.compatible = "mediatek,mt8195-gce", .data = (void
> *)&gce_plat_v6},
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH v4] mailbox: mtk-cmdq: fix gce timeout issue
  2022-09-27  5:19   ` CK Hu (胡俊光)
@ 2022-09-27  8:44     ` yongqiang.niu
  -1 siblings, 0 replies; 6+ messages in thread
From: yongqiang.niu @ 2022-09-27  8:44 UTC (permalink / raw)
  To: CK Hu (胡俊光), chunkuang.hu
  Cc: jassisinghbrar, matthias.bgg, linux-kernel, linux-arm-kernel,
	linux-mediatek, Project_Global_Chrome_Upstream_Group, hsinyi

On Tue, 2022-09-27 at 13:19 +0800, CK Hu (胡俊光) wrote:
> Hi, Yongqiang:
> 
> On Tue, 2022-09-27 at 12:01 +0800, Yongqiang Niu wrote:
> > 1. enable gce ddr enable(gce reigster offset 0x48, bit 16 to 18)
> > when
> > gce work,
> > and disable gce ddr enable when gce work job done
> > 2. add cmdq ddr enable/disable api, and control gce ddr
> > enable/disable
> > to make sure it could protect when cmdq is multiple used by display
> > and mdp
> > 
> > this is only for some SOC which has flag "gce_ddr_en".
> > for this kind of gce, there is a handshake flow between gce and ddr
> > hardware,
> > if not set ddr enable flag of gce, ddr will fall into idle mode,
> > then gce instructions will not process done.
> > we need set this flag of gce to tell ddr when gce is idle or busy
> > controlled by software flow.
> > 
> > ddr problem is a special case.
> > when test suspend/resume case, gce sometimes will pull ddr, and ddr
> > can
> > not go to suspend.
> > if we set gce register 0x48 to 0x7, will fix this gce pull ddr
> > issue,
> > as you have referred [1] and [2] (8192 and 8195)
> > but for mt8186, the gce is more special, except setting of [1] and
> > [2],
> > we need add more setting set gce register 0x48 to (0x7 << 16 | 0x7)
> > when gce working to make sure gce could process all instructions
> > ok.
> > this case just need normal bootup, if we not set this, display cmdq
> > task will timeout, and chrome homescreen will always black screen.
> > 
> > and with this patch, we have done these test on mt8186:
> > 1.suspend/resume
> > 2.boot up to home screen
> > 3.playback video with youtube.
> > 
> > suspend issue is special gce hardware issue, gce client  driver
> > command already process done, but gce still pull ddr.
> > 
> > Signed-off-by: Yongqiang Niu <yongqiang.niu@mediatek.com>
> > 
> > ---
> > change since v3:
> > split cmdq_sw_ddr_enable/cmdq_sw_ddr_disable into single api to
> > control mt8186 gce ddr enable flow
> > ---
> > 
> > ---
> >  drivers/mailbox/mtk-cmdq-mailbox.c | 61
> > ++++++++++++++++++++++++++++++
> >  1 file changed, 61 insertions(+)
> > 
> > diff --git a/drivers/mailbox/mtk-cmdq-mailbox.c
> > b/drivers/mailbox/mtk-cmdq-mailbox.c
> > index 9465f9081515..650a1ed1a579 100644
> > --- a/drivers/mailbox/mtk-cmdq-mailbox.c
> > +++ b/drivers/mailbox/mtk-cmdq-mailbox.c
> > @@ -38,6 +38,8 @@
> >  #define CMDQ_THR_PRIORITY		0x40
> >  
> >  #define GCE_GCTL_VALUE			0x48
> > +#define GCE_CTRL_BY_SW				GENMASK(18, 16)
> > +#define GCE_DDR_EN				GENMASK(2, 0)
> >  
> >  #define CMDQ_THR_ACTIVE_SLOT_CYCLES	0x3200
> >  #define CMDQ_THR_ENABLED		0x1
> > @@ -80,16 +82,51 @@ struct cmdq {
> >  	bool			suspended;
> >  	u8			shift_pa;
> >  	bool			control_by_sw;
> > +	bool			sw_ddr_en;
> >  	u32			gce_num;
> > +	atomic_t		usage;
> > +	spinlock_t		lock;
> >  };
> >  
> >  struct gce_plat {
> >  	u32 thread_nr;
> >  	u8 shift;
> >  	bool control_by_sw;
> > +	bool sw_ddr_en;
> >  	u32 gce_num;
> >  };
> >  
> > +static void cmdq_sw_ddr_enable(struct cmdq *cmdq)
> > +{
> > +	s32 usage;
> > +	unsigned long flags;
> > +
> > +	spin_lock_irqsave(&cmdq->lock, flags);
> > +
> > +	usage = atomic_inc_return(&cmdq->usage);
> > +
> > +	if (usage <= 0)
> > +		dev_err(cmdq->mbox.dev, "ref count %d suspend %d\n",
> > +			usage, cmdq->suspended);
> > +	else if (usage == 1)
> > +		writel(GCE_DDR_EN + GCE_CTRL_BY_SW, cmdq->base +
> > GCE_GCTL_VALUE);
> > +
> > +	spin_unlock_irqrestore(&cmdq->lock, flags);
> > +}
> > +
> > +static void cmdq_sw_ddr_disable(struct cmdq *cmdq)
> > +{
> > +	s32 usage;
> > +
> > +	usage = atomic_dec_return(&cmdq->usage);
> > +
> > +	if (usage < 0)
> > +		dev_err(cmdq->mbox.dev, "ref count %d suspend %d\n",
> > +			usage, cmdq->suspended);
> > +	else if (usage == 0)
> > +		writel(GCE_CTRL_BY_SW, cmdq->base + GCE_GCTL_VALUE);
> > +}
> > +
> >  u8 cmdq_get_shift_pa(struct mbox_chan *chan)
> >  {
> >  	struct cmdq *cmdq = container_of(chan->mbox, struct cmdq,
> > mbox);
> > @@ -266,6 +303,10 @@ static void cmdq_thread_irq_handler(struct
> > cmdq
> > *cmdq,
> >  
> >  	if (list_empty(&thread->task_busy_list)) {
> >  		cmdq_thread_disable(cmdq, thread);
> > +
> > +		if (cmdq->sw_ddr_en)
> > +			cmdq_sw_ddr_disable(cmdq);
> > +
> >  		clk_bulk_disable(cmdq->gce_num, cmdq->clocks);
> >  	}
> >  }
> > @@ -357,6 +398,8 @@ static int cmdq_mbox_send_data(struct mbox_chan
> > *chan, void *data)
> >  	if (list_empty(&thread->task_busy_list)) {
> >  		WARN_ON(clk_bulk_enable(cmdq->gce_num, cmdq->clocks));
> >  
> > +		if (cmdq->sw_ddr_en)
> > +			cmdq_sw_ddr_enable(cmdq);
> 
> Why do you dynamically enable/disable it when process every packet?
> Why
> not enable it in cmdq_mbox_startup() and disable it in
> cmdq_mbox_shutdown(), so you don't need an extra lock for spinlock.
> 
> Regards,
> CK
> 

suspend/resume flow will not call cmdq_mbox_shutdown, we need disable 
gce ddr enable after all packet process done(both include mdp and
display packet), to make sure gce will not access dram any more.

move this ddr control flow into suspend/resume flow in next version


> >  		/*
> >  		 * The thread reset will clear thread related register
> > to 0,
> >  		 * including pc, end, priority, irq, suspend and
> > enable. Thus
> > @@ -427,6 +470,9 @@ static void cmdq_mbox_shutdown(struct mbox_chan
> > *chan)
> >  		kfree(task);
> >  	}
> >  
> > +	if (cmdq->sw_ddr_en)
> > +		cmdq_sw_ddr_disable(cmdq);
> > +
> >  	cmdq_thread_disable(cmdq, thread);
> >  	clk_bulk_disable(cmdq->gce_num, cmdq->clocks);
> >  
> > @@ -468,6 +514,10 @@ static int cmdq_mbox_flush(struct mbox_chan
> > *chan, unsigned long timeout)
> >  
> >  	cmdq_thread_resume(thread);
> >  	cmdq_thread_disable(cmdq, thread);
> > +
> > +	if (cmdq->sw_ddr_en)
> > +		cmdq_sw_ddr_disable(cmdq);
> > +
> >  	clk_bulk_disable(cmdq->gce_num, cmdq->clocks);
> >  
> >  out:
> > @@ -543,6 +593,7 @@ static int cmdq_probe(struct platform_device
> > *pdev)
> >  	cmdq->thread_nr = plat_data->thread_nr;
> >  	cmdq->shift_pa = plat_data->shift;
> >  	cmdq->control_by_sw = plat_data->control_by_sw;
> > +	cmdq->sw_ddr_en = plat_data->sw_ddr_en;
> >  	cmdq->gce_num = plat_data->gce_num;
> >  	cmdq->irq_mask = GENMASK(cmdq->thread_nr - 1, 0);
> >  	err = devm_request_irq(dev, cmdq->irq, cmdq_irq_handler,
> > IRQF_SHARED,
> > @@ -615,6 +666,7 @@ static int cmdq_probe(struct platform_device
> > *pdev)
> >  
> >  	WARN_ON(clk_bulk_prepare(cmdq->gce_num, cmdq->clocks));
> >  
> > +	spin_lock_init(&cmdq->lock);
> >  	cmdq_init(cmdq);
> >  
> >  	return 0;
> > @@ -660,9 +712,18 @@ static const struct gce_plat gce_plat_v6 = {
> >  	.gce_num = 2
> >  };
> >  
> > +static const struct gce_plat gce_plat_v7 = {
> > +	.thread_nr = 24,
> > +	.shift = 3,
> > +	.control_by_sw = true,
> > +	.sw_ddr_en = true,
> > +	.gce_num = 1
> > +};
> > +
> >  static const struct of_device_id cmdq_of_ids[] = {
> >  	{.compatible = "mediatek,mt8173-gce", .data = (void
> > *)&gce_plat_v2},
> >  	{.compatible = "mediatek,mt8183-gce", .data = (void
> > *)&gce_plat_v3},
> > +	{.compatible = "mediatek,mt8186-gce", .data = (void
> > *)&gce_plat_v7},
> >  	{.compatible = "mediatek,mt6779-gce", .data = (void
> > *)&gce_plat_v4},
> >  	{.compatible = "mediatek,mt8192-gce", .data = (void
> > *)&gce_plat_v5},
> >  	{.compatible = "mediatek,mt8195-gce", .data = (void
> > *)&gce_plat_v6},



^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH v4] mailbox: mtk-cmdq: fix gce timeout issue
@ 2022-09-27  8:44     ` yongqiang.niu
  0 siblings, 0 replies; 6+ messages in thread
From: yongqiang.niu @ 2022-09-27  8:44 UTC (permalink / raw)
  To: CK Hu (胡俊光), chunkuang.hu
  Cc: jassisinghbrar, matthias.bgg, linux-kernel, linux-arm-kernel,
	linux-mediatek, Project_Global_Chrome_Upstream_Group, hsinyi

On Tue, 2022-09-27 at 13:19 +0800, CK Hu (胡俊光) wrote:
> Hi, Yongqiang:
> 
> On Tue, 2022-09-27 at 12:01 +0800, Yongqiang Niu wrote:
> > 1. enable gce ddr enable(gce reigster offset 0x48, bit 16 to 18)
> > when
> > gce work,
> > and disable gce ddr enable when gce work job done
> > 2. add cmdq ddr enable/disable api, and control gce ddr
> > enable/disable
> > to make sure it could protect when cmdq is multiple used by display
> > and mdp
> > 
> > this is only for some SOC which has flag "gce_ddr_en".
> > for this kind of gce, there is a handshake flow between gce and ddr
> > hardware,
> > if not set ddr enable flag of gce, ddr will fall into idle mode,
> > then gce instructions will not process done.
> > we need set this flag of gce to tell ddr when gce is idle or busy
> > controlled by software flow.
> > 
> > ddr problem is a special case.
> > when test suspend/resume case, gce sometimes will pull ddr, and ddr
> > can
> > not go to suspend.
> > if we set gce register 0x48 to 0x7, will fix this gce pull ddr
> > issue,
> > as you have referred [1] and [2] (8192 and 8195)
> > but for mt8186, the gce is more special, except setting of [1] and
> > [2],
> > we need add more setting set gce register 0x48 to (0x7 << 16 | 0x7)
> > when gce working to make sure gce could process all instructions
> > ok.
> > this case just need normal bootup, if we not set this, display cmdq
> > task will timeout, and chrome homescreen will always black screen.
> > 
> > and with this patch, we have done these test on mt8186:
> > 1.suspend/resume
> > 2.boot up to home screen
> > 3.playback video with youtube.
> > 
> > suspend issue is special gce hardware issue, gce client  driver
> > command already process done, but gce still pull ddr.
> > 
> > Signed-off-by: Yongqiang Niu <yongqiang.niu@mediatek.com>
> > 
> > ---
> > change since v3:
> > split cmdq_sw_ddr_enable/cmdq_sw_ddr_disable into single api to
> > control mt8186 gce ddr enable flow
> > ---
> > 
> > ---
> >  drivers/mailbox/mtk-cmdq-mailbox.c | 61
> > ++++++++++++++++++++++++++++++
> >  1 file changed, 61 insertions(+)
> > 
> > diff --git a/drivers/mailbox/mtk-cmdq-mailbox.c
> > b/drivers/mailbox/mtk-cmdq-mailbox.c
> > index 9465f9081515..650a1ed1a579 100644
> > --- a/drivers/mailbox/mtk-cmdq-mailbox.c
> > +++ b/drivers/mailbox/mtk-cmdq-mailbox.c
> > @@ -38,6 +38,8 @@
> >  #define CMDQ_THR_PRIORITY		0x40
> >  
> >  #define GCE_GCTL_VALUE			0x48
> > +#define GCE_CTRL_BY_SW				GENMASK(18, 16)
> > +#define GCE_DDR_EN				GENMASK(2, 0)
> >  
> >  #define CMDQ_THR_ACTIVE_SLOT_CYCLES	0x3200
> >  #define CMDQ_THR_ENABLED		0x1
> > @@ -80,16 +82,51 @@ struct cmdq {
> >  	bool			suspended;
> >  	u8			shift_pa;
> >  	bool			control_by_sw;
> > +	bool			sw_ddr_en;
> >  	u32			gce_num;
> > +	atomic_t		usage;
> > +	spinlock_t		lock;
> >  };
> >  
> >  struct gce_plat {
> >  	u32 thread_nr;
> >  	u8 shift;
> >  	bool control_by_sw;
> > +	bool sw_ddr_en;
> >  	u32 gce_num;
> >  };
> >  
> > +static void cmdq_sw_ddr_enable(struct cmdq *cmdq)
> > +{
> > +	s32 usage;
> > +	unsigned long flags;
> > +
> > +	spin_lock_irqsave(&cmdq->lock, flags);
> > +
> > +	usage = atomic_inc_return(&cmdq->usage);
> > +
> > +	if (usage <= 0)
> > +		dev_err(cmdq->mbox.dev, "ref count %d suspend %d\n",
> > +			usage, cmdq->suspended);
> > +	else if (usage == 1)
> > +		writel(GCE_DDR_EN + GCE_CTRL_BY_SW, cmdq->base +
> > GCE_GCTL_VALUE);
> > +
> > +	spin_unlock_irqrestore(&cmdq->lock, flags);
> > +}
> > +
> > +static void cmdq_sw_ddr_disable(struct cmdq *cmdq)
> > +{
> > +	s32 usage;
> > +
> > +	usage = atomic_dec_return(&cmdq->usage);
> > +
> > +	if (usage < 0)
> > +		dev_err(cmdq->mbox.dev, "ref count %d suspend %d\n",
> > +			usage, cmdq->suspended);
> > +	else if (usage == 0)
> > +		writel(GCE_CTRL_BY_SW, cmdq->base + GCE_GCTL_VALUE);
> > +}
> > +
> >  u8 cmdq_get_shift_pa(struct mbox_chan *chan)
> >  {
> >  	struct cmdq *cmdq = container_of(chan->mbox, struct cmdq,
> > mbox);
> > @@ -266,6 +303,10 @@ static void cmdq_thread_irq_handler(struct
> > cmdq
> > *cmdq,
> >  
> >  	if (list_empty(&thread->task_busy_list)) {
> >  		cmdq_thread_disable(cmdq, thread);
> > +
> > +		if (cmdq->sw_ddr_en)
> > +			cmdq_sw_ddr_disable(cmdq);
> > +
> >  		clk_bulk_disable(cmdq->gce_num, cmdq->clocks);
> >  	}
> >  }
> > @@ -357,6 +398,8 @@ static int cmdq_mbox_send_data(struct mbox_chan
> > *chan, void *data)
> >  	if (list_empty(&thread->task_busy_list)) {
> >  		WARN_ON(clk_bulk_enable(cmdq->gce_num, cmdq->clocks));
> >  
> > +		if (cmdq->sw_ddr_en)
> > +			cmdq_sw_ddr_enable(cmdq);
> 
> Why do you dynamically enable/disable it when process every packet?
> Why
> not enable it in cmdq_mbox_startup() and disable it in
> cmdq_mbox_shutdown(), so you don't need an extra lock for spinlock.
> 
> Regards,
> CK
> 

suspend/resume flow will not call cmdq_mbox_shutdown, we need disable 
gce ddr enable after all packet process done(both include mdp and
display packet), to make sure gce will not access dram any more.

move this ddr control flow into suspend/resume flow in next version


> >  		/*
> >  		 * The thread reset will clear thread related register
> > to 0,
> >  		 * including pc, end, priority, irq, suspend and
> > enable. Thus
> > @@ -427,6 +470,9 @@ static void cmdq_mbox_shutdown(struct mbox_chan
> > *chan)
> >  		kfree(task);
> >  	}
> >  
> > +	if (cmdq->sw_ddr_en)
> > +		cmdq_sw_ddr_disable(cmdq);
> > +
> >  	cmdq_thread_disable(cmdq, thread);
> >  	clk_bulk_disable(cmdq->gce_num, cmdq->clocks);
> >  
> > @@ -468,6 +514,10 @@ static int cmdq_mbox_flush(struct mbox_chan
> > *chan, unsigned long timeout)
> >  
> >  	cmdq_thread_resume(thread);
> >  	cmdq_thread_disable(cmdq, thread);
> > +
> > +	if (cmdq->sw_ddr_en)
> > +		cmdq_sw_ddr_disable(cmdq);
> > +
> >  	clk_bulk_disable(cmdq->gce_num, cmdq->clocks);
> >  
> >  out:
> > @@ -543,6 +593,7 @@ static int cmdq_probe(struct platform_device
> > *pdev)
> >  	cmdq->thread_nr = plat_data->thread_nr;
> >  	cmdq->shift_pa = plat_data->shift;
> >  	cmdq->control_by_sw = plat_data->control_by_sw;
> > +	cmdq->sw_ddr_en = plat_data->sw_ddr_en;
> >  	cmdq->gce_num = plat_data->gce_num;
> >  	cmdq->irq_mask = GENMASK(cmdq->thread_nr - 1, 0);
> >  	err = devm_request_irq(dev, cmdq->irq, cmdq_irq_handler,
> > IRQF_SHARED,
> > @@ -615,6 +666,7 @@ static int cmdq_probe(struct platform_device
> > *pdev)
> >  
> >  	WARN_ON(clk_bulk_prepare(cmdq->gce_num, cmdq->clocks));
> >  
> > +	spin_lock_init(&cmdq->lock);
> >  	cmdq_init(cmdq);
> >  
> >  	return 0;
> > @@ -660,9 +712,18 @@ static const struct gce_plat gce_plat_v6 = {
> >  	.gce_num = 2
> >  };
> >  
> > +static const struct gce_plat gce_plat_v7 = {
> > +	.thread_nr = 24,
> > +	.shift = 3,
> > +	.control_by_sw = true,
> > +	.sw_ddr_en = true,
> > +	.gce_num = 1
> > +};
> > +
> >  static const struct of_device_id cmdq_of_ids[] = {
> >  	{.compatible = "mediatek,mt8173-gce", .data = (void
> > *)&gce_plat_v2},
> >  	{.compatible = "mediatek,mt8183-gce", .data = (void
> > *)&gce_plat_v3},
> > +	{.compatible = "mediatek,mt8186-gce", .data = (void
> > *)&gce_plat_v7},
> >  	{.compatible = "mediatek,mt6779-gce", .data = (void
> > *)&gce_plat_v4},
> >  	{.compatible = "mediatek,mt8192-gce", .data = (void
> > *)&gce_plat_v5},
> >  	{.compatible = "mediatek,mt8195-gce", .data = (void
> > *)&gce_plat_v6},


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2022-09-27  9:30 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-09-27  4:01 [PATCH v4] mailbox: mtk-cmdq: fix gce timeout issue Yongqiang Niu
2022-09-27  4:01 ` Yongqiang Niu
2022-09-27  5:19 ` CK Hu (胡俊光)
2022-09-27  5:19   ` CK Hu (胡俊光)
2022-09-27  8:44   ` yongqiang.niu
2022-09-27  8:44     ` yongqiang.niu

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.