return 0;
}
+static int a6xx_gmu_gxpd_get(struct a6xx_gmu *gmu)
+{
+ struct a6xx_gpu *a6xx_gpu = container_of(gmu, struct a6xx_gpu, gmu);
+ struct adreno_gpu *adreno_gpu = &a6xx_gpu->base;
+
+ if (IS_ERR_OR_NULL(gmu->gxpd))
+ return 0;
+
+ /*
+ * On A8xx HW, GX GDSC is moved to a new clk controller block under GX
+ * power domain. The clock driver for this new block keeps the GX rail
+ * voted when gxpd is voted. So, use the gxpd only during gpu recovery.
+ */
+ if (adreno_gpu->info->family >= ADRENO_8XX_GEN1)
+ return 0;
+
+ /*
+ * On A6x/A7x, "enable" the GX power domain which won't actually do
+ * anything but it will make sure that the refcounting is correct in
+ * case we need to bring down the GX after a GMU failure
+ */
+ return pm_runtime_get_sync(gmu->gxpd);
+}
+
+static int a6xx_gmu_gxpd_put(struct a6xx_gmu *gmu)
+{
+ struct a6xx_gpu *a6xx_gpu = container_of(gmu, struct a6xx_gpu, gmu);
+ struct adreno_gpu *adreno_gpu = &a6xx_gpu->base;
+
+ if (IS_ERR_OR_NULL(gmu->gxpd))
+ return 0;
+
+ if (adreno_gpu->info->family < ADRENO_8XX_GEN1)
+ return pm_runtime_put_sync(gmu->gxpd);
+
+ /*
+ * On A8x, GX GDSC collapse should be triggered only when it is stuck ON
+ */
+ if (adreno_gpu->funcs->gx_is_on(adreno_gpu)) {
+ pm_runtime_get_sync(gmu->gxpd);
+ /*
+ * Hint to gfxclkctl driver to do a hw collapse during the next
+ * RPM PUT. This is a special behavior in the gfxclkctl driver
+ */
+ dev_pm_genpd_synced_poweroff(gmu->gxpd);
+ pm_runtime_put_sync(gmu->gxpd);
+ }
+
+ return 0;
+}
int a6xx_gmu_resume(struct a6xx_gpu *a6xx_gpu)
{
/* Turn on the resources */
pm_runtime_get_sync(gmu->dev);
- /*
- * "enable" the GX power domain which won't actually do anything but it
- * will make sure that the refcounting is correct in case we need to
- * bring down the GX after a GMU failure
- */
- if (!IS_ERR_OR_NULL(gmu->gxpd))
- pm_runtime_get_sync(gmu->gxpd);
+ a6xx_gmu_gxpd_get(gmu);
/* Use a known rate to bring up the GMU */
clk_set_rate(gmu->core_clk, 200000000);
disable_clk:
clk_bulk_disable_unprepare(gmu->nr_clocks, gmu->clocks);
rpm_put:
- pm_runtime_put(gmu->gxpd);
+ a6xx_gmu_gxpd_put(gmu);
+
pm_runtime_put(gmu->dev);
return ret;
* domain. Usually the GMU does this but only if the shutdown sequence
* was successful
*/
- if (!IS_ERR_OR_NULL(gmu->gxpd))
- pm_runtime_put_sync(gmu->gxpd);
+ a6xx_gmu_gxpd_put(gmu);
clk_bulk_disable_unprepare(gmu->nr_clocks, gmu->clocks);