Commit a82ec814 authored by Lin Huang's avatar Lin Huang Committed by Xing Zheng
Browse files

rockchip: rk3399: check vop status when we wait dma finish flag



When vop is disabled and we read the vop register the system will
hang, so check vop status when we wait for the DMA finish flag to
avoid this sitiuation. This is done by checking for standby, DMA stop
mode, and disabled window states. Any one of these will prevent the
DMA finish flag from triggering.
Signed-off-by: default avatarLin Huang <hl@rock-chips.com>
Signed-off-by: default avatarDerek Basehore <dbasehore@chromium.org>
parent 95c3f422
......@@ -86,12 +86,17 @@
/* VOP */
#define VOP_SYS_CTRL 0x8
#define VOP_SYS_CTRL1 0xc
#define VOP_WIN0_CTRL0 0x30
#define VOP_INTR_CLEAR0 0x284
#define VOP_INTR_RAW_STATUS0 0x28c
/* VOP_SYS_CTRL */
#define VOP_DMA_STOP_EN (1 << 21)
#define VOP_STANDBY_EN (1 << 22)
/* VOP_WIN0_CTRL0 */
#define WB_ENABLE (1 << 0)
/* VOP_INTR_CLEAR0 */
#define INT_CLR_DMA_FINISH (1 << 15)
#define INT_CLR_LINE_FLAG1 (1 << 4)
......@@ -107,65 +112,72 @@
#define CIC_CTRL1 0x4
#define CIC_STATUS0 0x10
struct ddr_freq_param {
uint32_t vop_big_en;
uint32_t vop_lit_en;
uint32_t dclk0_div;
uint32_t dclk1_div;
};
static struct ddr_freq_param rk3399_ddr_arg;
static void get_vop_status(void)
static inline int check_dma_status(uint32_t vop_addr, uint32_t *clr_dma_flag)
{
rk3399_ddr_arg.vop_big_en = 0;
rk3399_ddr_arg.vop_lit_en = 0;
if ((mmio_read_32(PMU_BASE + PMU_PWRDN_ST) & PD_VOP_PWR_STAT) == 0) {
/* get vop0 status */
if ((mmio_read_32(CRU_BASE_ADDR + CRU_CLKGATE10_CON) &
(DCLK_VOP0_SRC_EN | ACLK_VOP0_PRE_SRC_EN |
HCLK_VOP0_PRE_EN)) == 0)
if ((mmio_read_32(CRU_BASE_ADDR + CRU_CLKGATE28_CON) &
(HCLK_VOP0_EN | ACLK_VOP0_EN)) == 0)
if ((mmio_read_32(VOP_BIG_BASE_ADDR +
VOP_SYS_CTRL) &
VOP_STANDBY_EN) == 0)
rk3399_ddr_arg.vop_big_en = 1;
/* get vop1 satus */
if ((mmio_read_32(CRU_BASE_ADDR + CRU_CLKGATE10_CON) &
(DCLK_VOP1_SRC_EN | ACLK_VOP1_PRE_SRC_EN |
HCLK_VOP1_PRE_EN)) == 0)
if ((mmio_read_32(CRU_BASE_ADDR + CRU_CLKGATE28_CON) &
(HCLK_VOP1_EN | ACLK_VOP1_EN)) == 0)
if ((mmio_read_32(VOP_LITE_BASE_ADDR +
VOP_SYS_CTRL) &
VOP_STANDBY_EN) == 0)
rk3399_ddr_arg.vop_lit_en = 1;
if (*clr_dma_flag) {
mmio_write_32(vop_addr + VOP_INTR_CLEAR0, 0x80008000);
*clr_dma_flag = 0;
}
}
static void wait_vop_dma_finish(void)
{
uint32_t vop_adr;
if ((mmio_read_32(vop_addr + VOP_SYS_CTRL) &
(VOP_STANDBY_EN | VOP_DMA_STOP_EN)) ||
!(mmio_read_32(vop_addr + VOP_WIN0_CTRL0) & WB_ENABLE) ||
(mmio_read_32(vop_addr + VOP_INTR_RAW_STATUS0) &
INT_RAW_STATUS_DMA_FINISH))
return 1;
get_vop_status();
return 0;
}
if (rk3399_ddr_arg.vop_big_en)
vop_adr = VOP_BIG_BASE_ADDR;
else if (rk3399_ddr_arg.vop_lit_en)
vop_adr = VOP_LITE_BASE_ADDR;
else
static int wait_vop_dma_finish(void)
{
uint32_t clr_dma_flag = 1;
uint32_t ret = 0;
stopwatch_init_usecs_expire(60000);
while (((mmio_read_32(PMU_BASE + PMU_PWRDN_ST) &
PD_VOP_PWR_STAT) == 0)) {
/*
* VOPL case:
* CRU_CLKGATE10_CON(bit10): ACLK_VOP1_PRE_SRC_EN
* CRU_CLKGATE10_CON(bit11): HCLK_VOP1_PRE_EN
* CRU_CLKGATE10_CON(bit13): DCLK_VOP1_SRC_EN
* CRU_CLKGATE28_CON(bit7): ACLK_VOP1_EN
* CRU_CLKGATE28_CON(bit6): HCLK_VOP1_EN
*
* VOPB case:
* CRU_CLKGATE10_CON(bit8): ACLK_VOP0_PRE_SRC_EN
* CRU_CLKGATE10_CON(bit9): HCLK_VOP0_PRE_EN
* CRU_CLKGATE10_CON(bit12): DCLK_VOP0_SRC_EN
* CRU_CLKGATE28_CON(bit3): ACLK_VOP0_EN
* CRU_CLKGATE28_CON(bit2): HCLK_VOP0_EN
*/
if (((mmio_read_32(CRU_BASE_ADDR + CRU_CLKGATE10_CON) &
0x2c00) == 0) &&
((mmio_read_32(CRU_BASE_ADDR + CRU_CLKGATE28_CON) &
0xc0) == 0)) {
if (check_dma_status(VOP_LITE_BASE_ADDR, &clr_dma_flag))
return;
} else if (((mmio_read_32(CRU_BASE_ADDR + CRU_CLKGATE10_CON) &
0x1300) == 0) &&
((mmio_read_32(CRU_BASE_ADDR + CRU_CLKGATE28_CON) &
0x0c) == 0)) {
if (check_dma_status(VOP_BIG_BASE_ADDR, &clr_dma_flag))
return;
} else {
/* No VOPs are enabled, so don't wait. */
return;
}
/* clean dma finish irq and wait for it */
mmio_write_32(vop_adr + VOP_INTR_CLEAR0,
INT_CLR_DMA_FINISH | (INT_CLR_DMA_FINISH << 16));
if (stopwatch_expired()) {
ret = 1;
goto out;
}
}
while ((mmio_read_32(vop_adr + VOP_INTR_RAW_STATUS0) &
INT_RAW_STATUS_DMA_FINISH) == 0)
;
out:
stopwatch_reset();
return ret;
}
static void idle_port(void)
......@@ -207,6 +219,7 @@ static void ddr_set_pll(void)
void handle_dram(void)
{
wait_vop_dma_finish();
idle_port();
mmio_write_32(CIC_BASE_ADDR + CIC_CTRL0,
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment