/* Set up the idle state for the GMU */ static void a6xx_gmu_power_config(struct a6xx_gmu *gmu) { /* Disable GMU WB/RB buffer */ gmu_write(gmu, REG_A6XX_GMU_SYS_BUS_CONFIG, 0x1); gmu_write(gmu, REG_A6XX_GMU_PWR_COL_INTER_FRAME_CTRL, 0x9c40400); switch (gmu->idle_level) { case GMU_IDLE_STATE_IFPC: gmu_write(gmu, REG_A6XX_GMU_PWR_COL_INTER_FRAME_HYST, GMU_PWR_COL_HYST); gmu_rmw(gmu, REG_A6XX_GMU_PWR_COL_INTER_FRAME_CTRL, 0, A6XX_GMU_PWR_COL_INTER_FRAME_CTRL_IFPC_ENABLE | A6XX_GMU_PWR_COL_INTER_FRAME_CTRL_HM_POWER_COLLAPSE_ENABLE); /* Fall through */ case GMU_IDLE_STATE_SPTP: gmu_write(gmu, REG_A6XX_GMU_PWR_COL_SPTPRAC_HYST, GMU_PWR_COL_HYST); gmu_rmw(gmu, REG_A6XX_GMU_PWR_COL_INTER_FRAME_CTRL, 0, A6XX_GMU_PWR_COL_INTER_FRAME_CTRL_IFPC_ENABLE | A6XX_GMU_PWR_COL_INTER_FRAME_CTRL_SPTPRAC_POWER_CONTROL_ENABLE); } /* Enable RPMh GPU client */ gmu_rmw(gmu, REG_A6XX_GMU_RPMH_CTRL, 0, A6XX_GMU_RPMH_CTRL_RPMH_INTERFACE_ENABLE | A6XX_GMU_RPMH_CTRL_LLC_VOTE_ENABLE | A6XX_GMU_RPMH_CTRL_DDR_VOTE_ENABLE | A6XX_GMU_RPMH_CTRL_MX_VOTE_ENABLE | A6XX_GMU_RPMH_CTRL_CX_VOTE_ENABLE | A6XX_GMU_RPMH_CTRL_GFX_VOTE_ENABLE); }
static int a6xx_rpmh_start(struct a6xx_gmu *gmu) { int ret; u32 val; gmu_write(gmu, REG_A6XX_GMU_RSCC_CONTROL_REQ, 1 << 1); /* Wait for the register to finish posting */ wmb(); ret = gmu_poll_timeout(gmu, REG_A6XX_GMU_RSCC_CONTROL_ACK, val, val & (1 << 1), 100, 10000); if (ret) { DRM_DEV_ERROR(gmu->dev, "Unable to power on the GPU RSC\n"); return ret; } ret = gmu_poll_timeout(gmu, REG_A6XX_RSCC_SEQ_BUSY_DRV0, val, !val, 100, 10000); if (ret) { DRM_DEV_ERROR(gmu->dev, "GPU RSC sequence stuck while waking up the GPU\n"); return ret; } gmu_write(gmu, REG_A6XX_GMU_RSCC_CONTROL_REQ, 0); /* Set up CX GMU counter 0 to count busy ticks */ gmu_write(gmu, REG_A6XX_GPU_GMU_AO_GPU_CX_BUSY_MASK, 0xff000000); gmu_rmw(gmu, REG_A6XX_GMU_CX_GMU_POWER_COUNTER_SELECT_0, 0xff, 0x20); /* Enable the power counter */ gmu_write(gmu, REG_A6XX_GMU_CX_GMU_POWER_COUNTER_ENABLE, 1); return 0; }
/* Disable CPU control of SPTP power power collapse */ static void a6xx_sptprac_disable(struct a6xx_gmu *gmu) { u32 val; int ret; /* Make sure retention is on */ gmu_rmw(gmu, REG_A6XX_GPU_CC_GX_GDSCR, 0, (1 << 11)); gmu_write(gmu, REG_A6XX_GMU_GX_SPTPRAC_POWER_CONTROL, 0x778001); ret = gmu_poll_timeout(gmu, REG_A6XX_GMU_SPTPRAC_PWR_CLK_STATUS, val, (val & 0x04), 100, 10000); if (ret) DRM_DEV_ERROR(gmu->dev, "failed to power off SPTPRAC: 0x%x\n", gmu_read(gmu, REG_A6XX_GMU_SPTPRAC_PWR_CLK_STATUS)); }
static int a6xx_gmu_hfi_start(struct a6xx_gmu *gmu) { u32 val; int ret; gmu_rmw(gmu, REG_A6XX_GMU_GMU2HOST_INTR_MASK, A6XX_GMU_GMU2HOST_INTR_INFO_MSGQ, 0); gmu_write(gmu, REG_A6XX_GMU_HFI_CTRL_INIT, 1); ret = gmu_poll_timeout(gmu, REG_A6XX_GMU_HFI_CTRL_STATUS, val, val & 1, 100, 10000); if (ret) dev_err(gmu->dev, "Unable to start the HFI queues\n"); return ret; }