diff --git a/drivers/gpu/msm/a3xx_reg.h b/drivers/gpu/msm/a3xx_reg.h index 676f46da39a85bb4141a24a99525ef3502fe4f65..36b03e2b5ba3e4cca41474e2ec15b5f924df181b 100644 --- a/drivers/gpu/msm/a3xx_reg.h +++ b/drivers/gpu/msm/a3xx_reg.h @@ -487,6 +487,11 @@ #define A3XX_VBIF_PERF_PWR_CNT2_LO 0x307b #define A3XX_VBIF_PERF_PWR_CNT2_HI 0x307c +#define A3XX_VBIF_XIN_HALT_CTRL0 0x3080 +#define A3XX_VBIF_XIN_HALT_CTRL0_MASK 0x3F +#define A3XX_VBIF_XIN_HALT_CTRL1 0x3081 + + /* Bit flags for RBBM_CTL */ #define RBBM_RBBM_CTL_RESET_PWR_CTR0 BIT(0) #define RBBM_RBBM_CTL_RESET_PWR_CTR1 BIT(1) diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c index 84ab89dc3d6717940eccaabc82f2cc05f2e1f364..0d986b7100ecfa26ee8e6ddd2b183ba4a65f40fc 100644 --- a/drivers/gpu/msm/adreno.c +++ b/drivers/gpu/msm/adreno.c @@ -1794,6 +1794,32 @@ error_clk_off: return status; } +/** + * adreno_vbif_clear_pending_transactions() - Clear transactions in VBIF pipe + * @device: Pointer to the device whose VBIF pipe is to be cleared + */ +static void adreno_vbif_clear_pending_transactions(struct kgsl_device *device) +{ + struct adreno_device *adreno_dev = ADRENO_DEVICE(device); + unsigned int mask = A3XX_VBIF_XIN_HALT_CTRL0_MASK; + unsigned int val; + unsigned long wait_for_vbif; + + adreno_writereg(adreno_dev, ADRENO_REG_VBIF_XIN_HALT_CTRL0, mask); + /* wait for the transactions to clear */ + wait_for_vbif = jiffies + msecs_to_jiffies(100); + while (1) { + adreno_readreg(adreno_dev, + ADRENO_REG_VBIF_XIN_HALT_CTRL1, &val); + if ((val & mask) == mask) + break; + if (time_after(jiffies, wait_for_vbif)) + break; + } + adreno_writereg(adreno_dev, ADRENO_REG_VBIF_XIN_HALT_CTRL0, 0); +} + + static int adreno_stop(struct kgsl_device *device) { struct adreno_device *adreno_dev = ADRENO_DEVICE(device); @@ -1837,15 +1863,13 @@ static int adreno_stop(struct kgsl_device *device) int adreno_reset(struct kgsl_device *device) { int ret = -EINVAL; - struct kgsl_mmu *mmu = &device->mmu; int i = 0; - /* Try soft reset first, for non mmu fault case only */ - if (!atomic_read(&mmu->fault)) { - ret = adreno_soft_reset(device); - if (ret) - KGSL_DEV_ERR_ONCE(device, "Device soft reset failed\n"); - } + /* clear pending vbif transactions before reset */ + adreno_vbif_clear_pending_transactions(device); + + /* Try soft reset first */ + ret = adreno_soft_reset(device); if (ret) { /* If soft reset failed/skipped, then pull the power */ adreno_stop(device); diff --git a/drivers/gpu/msm/adreno.h b/drivers/gpu/msm/adreno.h index 23309a12815202c1904a15fbb9af1a1201e3b6a4..15084a086359d81f63069f04d2cee060c597d401 100644 --- a/drivers/gpu/msm/adreno.h +++ b/drivers/gpu/msm/adreno.h @@ -314,6 +314,8 @@ enum adreno_regs { ADRENO_REG_TP0_CHICKEN, ADRENO_REG_RBBM_RBBM_CTL, ADRENO_REG_UCHE_INVALIDATE0, + ADRENO_REG_VBIF_XIN_HALT_CTRL0, + ADRENO_REG_VBIF_XIN_HALT_CTRL1, ADRENO_REG_REGISTER_MAX, }; diff --git a/drivers/gpu/msm/adreno_a3xx.c b/drivers/gpu/msm/adreno_a3xx.c index 65d1d063cd21eabc701a03cacb020db14ffb550c..a68635f36f8f5f2534bcc23c51b4373e85845589 100644 --- a/drivers/gpu/msm/adreno_a3xx.c +++ b/drivers/gpu/msm/adreno_a3xx.c @@ -4407,6 +4407,10 @@ static unsigned int a3xx_register_offsets[ADRENO_REG_REGISTER_MAX] = { ADRENO_REG_DEFINE(ADRENO_REG_RBBM_RBBM_CTL, A3XX_RBBM_RBBM_CTL), ADRENO_REG_DEFINE(ADRENO_REG_UCHE_INVALIDATE0, A3XX_UCHE_CACHE_INVALIDATE0_REG), + ADRENO_REG_DEFINE(ADRENO_REG_VBIF_XIN_HALT_CTRL0, + A3XX_VBIF_XIN_HALT_CTRL0), + ADRENO_REG_DEFINE(ADRENO_REG_VBIF_XIN_HALT_CTRL1, + A3XX_VBIF_XIN_HALT_CTRL1), }; const struct adreno_reg_offsets a3xx_reg_offsets = {