summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBai Ping <ping.bai@nxp.com>2018-10-29 13:28:58 +0800
committerBai Ping <ping.bai@nxp.com>2018-11-01 19:43:01 +0800
commitb6e9e2d823b1ff5f4e83fa34541003df0e70e1c9 (patch)
tree5c08d8da37e1e47ec99ba8023e2346d9083f7d09
parent4f00df596a80cb4b4539d228332d976cf38d4183 (diff)
plat: imx: Add sw workaround for the VPU&GPU reset
ERR050044: GPU/VPU power domain on/off stress test leads to unexpected GPU interrupts and hang. his is caused by no dedicated HW resets for GPU2D/3D. There is one reset for whole GPUmix and GPU2D/3D has their own SW reset signals. The SW reset cannot be asserted while GPU2D/3D is in power off status. So if only GPU2D or GPU3D has to be powered off and on, unknown status leads to the problem. VPU has similiar issue. So we need to assert the SW reset before power up the power domain. Signed-off-by: Bai Ping <ping.bai@nxp.com>
-rw-r--r--plat/imx/imx8mm/gpc.c79
1 files changed, 70 insertions, 9 deletions
diff --git a/plat/imx/imx8mm/gpc.c b/plat/imx/imx8mm/gpc.c
index e6db4116..afbb7b9c 100644
--- a/plat/imx/imx8mm/gpc.c
+++ b/plat/imx/imx8mm/gpc.c
@@ -346,7 +346,6 @@ void imx_a53_plat_slot_config(bool pdn)
pgc_pcr |= 0x1;
mmio_write_32(IMX_GPC_BASE + PLAT_PGC_PCR, pgc_pcr);
-
if (pdn) {
/* config a53 plat pdn/pup slot */
pdn_slot_cfg |= PLAT_PDN_SLT_CTRL;
@@ -355,7 +354,6 @@ void imx_a53_plat_slot_config(bool pdn)
slot_ack = PLAT_PGC_PDN_ACK | PLAT_PGC_PUP_ACK;
/* enable PLAT PGC PCR */
pgc_pcr |= 0x1;
-
} else {
/* clear slot/ack config */
pdn_slot_cfg &= ~PLAT_PDN_SLT_CTRL;
@@ -688,6 +686,62 @@ static void imx_gpc_set_wake_irq(uint32_t hwirq, uint32_t on)
gpc_wake_irqs[idx] | mask;
}
+#define GPU_RCR 0x40
+#define VPU_RCR 0x44
+
+#define VPU_CTL_BASE 0x38330000
+#define BLK_SFT_RSTN_CSR 0x0
+#define H1_SFT_RSTN (1 << 2)
+#define G1_SFT_RSTN (1 << 1)
+#define G2_SFT_RSTN (1 << 0)
+
+void vpu_sft_reset_assert(uint32_t domain_id)
+{
+ uint32_t val;
+
+ val = mmio_read_32(VPU_CTL_BASE + BLK_SFT_RSTN_CSR);
+
+ switch(domain_id) {
+ case VPU_G1:
+ val &= ~G1_SFT_RSTN;
+ mmio_write_32(VPU_CTL_BASE + BLK_SFT_RSTN_CSR, val);
+ break;
+ case VPU_G2:
+ val &= ~G2_SFT_RSTN;
+ mmio_write_32(VPU_CTL_BASE + BLK_SFT_RSTN_CSR, val);
+ break;
+ case VPU_H1:
+ val &= ~H1_SFT_RSTN;
+ mmio_write_32(VPU_CTL_BASE + BLK_SFT_RSTN_CSR, val);
+ break;
+ default:
+ break;
+ }
+}
+
+void vpu_sft_reset_deassert(uint32_t domain_id)
+{
+ uint32_t val;
+
+ val = mmio_read_32(VPU_CTL_BASE + BLK_SFT_RSTN_CSR);
+
+ switch(domain_id) {
+ case VPU_G1:
+ val |= G1_SFT_RSTN;
+ mmio_write_32(VPU_CTL_BASE + BLK_SFT_RSTN_CSR, val);
+ break;
+ case VPU_G2:
+ val |= G2_SFT_RSTN;
+ mmio_write_32(VPU_CTL_BASE + BLK_SFT_RSTN_CSR, val);
+ break;
+ case VPU_H1:
+ val |= H1_SFT_RSTN;
+ mmio_write_32(VPU_CTL_BASE + BLK_SFT_RSTN_CSR, val);
+ break;
+ default:
+ break;
+ }
+}
static void imx_gpc_pm_domain_enable(uint32_t domain_id, uint32_t on)
{
@@ -705,6 +759,9 @@ static void imx_gpc_pm_domain_enable(uint32_t domain_id, uint32_t on)
val &= ~(1 << 0);
mmio_write_32(IMX_GPC_BASE + pwr_domain->pgc_offset, val);
+ if (domain_id == VPU_G1 || domain_id == VPU_G2 || domain_id == VPU_H1)
+ vpu_sft_reset_assert(domain_id);
+
/* power up the domain */
val = mmio_read_32(IMX_GPC_BASE + PU_PGC_UP_TRG);
val |= pwr_domain->pwr_req;
@@ -712,9 +769,16 @@ static void imx_gpc_pm_domain_enable(uint32_t domain_id, uint32_t on)
/* wait for power request done */
while (mmio_read_32(IMX_GPC_BASE + PU_PGC_UP_TRG) & pwr_domain->pwr_req);
+
+ if (domain_id == VPU_G1 || domain_id == VPU_G2 || domain_id == VPU_H1)
+ vpu_sft_reset_deassert(domain_id);
}
if (domain_id == GPUMIX) {
+
+ /* assert reset */
+ mmio_write_32(IMX_SRC_BASE + GPU_RCR, 0x1);
+
/* power up GPU2D */
val = mmio_read_32(IMX_GPC_BASE + GPU2D_PGC);
val &= ~(1 << 0);
@@ -741,20 +805,17 @@ static void imx_gpc_pm_domain_enable(uint32_t domain_id, uint32_t on)
/* wait for power request done */
while (mmio_read_32(IMX_GPC_BASE + PU_PGC_UP_TRG) & GPU3D_PWR_REQ);
- udelay(1);
-
- /* assert reset */
- mmio_write_32(0x30390040, 0x1);
udelay(10);
- mmio_write_32(0x30390040, 0x0);
+ /* release the gpumix reset */
+ mmio_write_32(IMX_SRC_BASE + GPU_RCR, 0x0);
udelay(10);
}
/* vpu sft clock enable */
if (domain_id == VPUMIX) {
- mmio_write_32(0x30390044, 0x1);
+ mmio_write_32(IMX_SRC_BASE + VPU_RCR, 0x1);
udelay(5);
- mmio_write_32(0x30390044, 0x0);
+ mmio_write_32(IMX_SRC_BASE + VPU_RCR, 0x0);
udelay(5);
/* enable all clock */