Merge tag 'drm-next-2021-02-26' of git://anongit.freedesktop.org/drm/drm
[linux-block.git] / drivers / gpu / drm / msm / adreno / a6xx_gmu.c
index 05e0ef58fe3266ba3dae8fadfeaeba265051d03e..71c917f909af7235fc9540f9923d65c1e9abd917 100644 (file)
@@ -245,37 +245,66 @@ static int a6xx_gmu_hfi_start(struct a6xx_gmu *gmu)
        return ret;
 }
 
+struct a6xx_gmu_oob_bits {
+       int set, ack, set_new, ack_new;
+       const char *name;
+};
+
+/* These are the interrupt / ack bits for each OOB request that are set
+ * in a6xx_gmu_set_oob and a6xx_clear_oob
+ */
+static const struct a6xx_gmu_oob_bits a6xx_gmu_oob_bits[] = {
+       [GMU_OOB_GPU_SET] = {
+               .name = "GPU_SET",
+               .set = 16,
+               .ack = 24,
+               .set_new = 30,
+               .ack_new = 31,
+       },
+
+       [GMU_OOB_PERFCOUNTER_SET] = {
+               .name = "PERFCOUNTER",
+               .set = 17,
+               .ack = 25,
+               .set_new = 28,
+               .ack_new = 30,
+       },
+
+       [GMU_OOB_BOOT_SLUMBER] = {
+               .name = "BOOT_SLUMBER",
+               .set = 22,
+               .ack = 30,
+       },
+
+       [GMU_OOB_DCVS_SET] = {
+               .name = "GPU_DCVS",
+               .set = 23,
+               .ack = 31,
+       },
+};
+
 /* Trigger a OOB (out of band) request to the GMU */
 int a6xx_gmu_set_oob(struct a6xx_gmu *gmu, enum a6xx_gmu_oob_state state)
 {
        int ret;
        u32 val;
        int request, ack;
-       const char *name;
 
-       switch (state) {
-       case GMU_OOB_GPU_SET:
-               if (gmu->legacy) {
-                       request = GMU_OOB_GPU_SET_REQUEST;
-                       ack = GMU_OOB_GPU_SET_ACK;
-               } else {
-                       request = GMU_OOB_GPU_SET_REQUEST_NEW;
-                       ack = GMU_OOB_GPU_SET_ACK_NEW;
-               }
-               name = "GPU_SET";
-               break;
-       case GMU_OOB_BOOT_SLUMBER:
-               request = GMU_OOB_BOOT_SLUMBER_REQUEST;
-               ack = GMU_OOB_BOOT_SLUMBER_ACK;
-               name = "BOOT_SLUMBER";
-               break;
-       case GMU_OOB_DCVS_SET:
-               request = GMU_OOB_DCVS_REQUEST;
-               ack = GMU_OOB_DCVS_ACK;
-               name = "GPU_DCVS";
-               break;
-       default:
+       if (state >= ARRAY_SIZE(a6xx_gmu_oob_bits))
                return -EINVAL;
+
+       if (gmu->legacy) {
+               request = a6xx_gmu_oob_bits[state].set;
+               ack = a6xx_gmu_oob_bits[state].ack;
+       } else {
+               request = a6xx_gmu_oob_bits[state].set_new;
+               ack = a6xx_gmu_oob_bits[state].ack_new;
+               if (!request || !ack) {
+                       DRM_DEV_ERROR(gmu->dev,
+                                     "Invalid non-legacy GMU request %s\n",
+                                     a6xx_gmu_oob_bits[state].name);
+                       return -EINVAL;
+               }
        }
 
        /* Trigger the equested OOB operation */
@@ -288,7 +317,7 @@ int a6xx_gmu_set_oob(struct a6xx_gmu *gmu, enum a6xx_gmu_oob_state state)
        if (ret)
                DRM_DEV_ERROR(gmu->dev,
                        "Timeout waiting for GMU OOB set %s: 0x%x\n",
-                               name,
+                               a6xx_gmu_oob_bits[state].name,
                                gmu_read(gmu, REG_A6XX_GMU_GMU2HOST_INTR_INFO));
 
        /* Clear the acknowledge interrupt */
@@ -300,27 +329,17 @@ int a6xx_gmu_set_oob(struct a6xx_gmu *gmu, enum a6xx_gmu_oob_state state)
 /* Clear a pending OOB state in the GMU */
 void a6xx_gmu_clear_oob(struct a6xx_gmu *gmu, enum a6xx_gmu_oob_state state)
 {
-       if (!gmu->legacy) {
-               WARN_ON(state != GMU_OOB_GPU_SET);
-               gmu_write(gmu, REG_A6XX_GMU_HOST2GMU_INTR_SET,
-                       1 << GMU_OOB_GPU_SET_CLEAR_NEW);
+       int bit;
+
+       if (state >= ARRAY_SIZE(a6xx_gmu_oob_bits))
                return;
-       }
 
-       switch (state) {
-       case GMU_OOB_GPU_SET:
-               gmu_write(gmu, REG_A6XX_GMU_HOST2GMU_INTR_SET,
-                       1 << GMU_OOB_GPU_SET_CLEAR);
-               break;
-       case GMU_OOB_BOOT_SLUMBER:
-               gmu_write(gmu, REG_A6XX_GMU_HOST2GMU_INTR_SET,
-                       1 << GMU_OOB_BOOT_SLUMBER_CLEAR);
-               break;
-       case GMU_OOB_DCVS_SET:
-               gmu_write(gmu, REG_A6XX_GMU_HOST2GMU_INTR_SET,
-                       1 << GMU_OOB_DCVS_CLEAR);
-               break;
-       }
+       if (gmu->legacy)
+               bit = a6xx_gmu_oob_bits[state].ack;
+       else
+               bit = a6xx_gmu_oob_bits[state].ack_new;
+
+       gmu_write(gmu, REG_A6XX_GMU_HOST2GMU_INTR_SET, bit);
 }
 
 /* Enable CPU control of SPTP power power collapse */