drm/msm: Clean up GMU OOB set/clear handling.
Now that the bug is fixed in the minimal way for stable, go make the code table-driven. Signed-off-by: Eric Anholt <eric@anholt.net> Reviewed-by: Jordan Crouse <jcrouse@codeaurora.org> Signed-off-by: Rob Clark <robdclark@chromium.org>
This commit is contained in:
parent
5f98b33b04
commit
555c50a4a1
@ -245,47 +245,66 @@ static int a6xx_gmu_hfi_start(struct a6xx_gmu *gmu)
|
|||||||
return ret;
|
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 */
|
/* 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 a6xx_gmu_set_oob(struct a6xx_gmu *gmu, enum a6xx_gmu_oob_state state)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
u32 val;
|
u32 val;
|
||||||
int request, ack;
|
int request, ack;
|
||||||
const char *name;
|
|
||||||
|
|
||||||
switch (state) {
|
if (state >= ARRAY_SIZE(a6xx_gmu_oob_bits))
|
||||||
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_PERFCOUNTER_SET:
|
|
||||||
if (gmu->legacy) {
|
|
||||||
request = GMU_OOB_PERFCOUNTER_REQUEST;
|
|
||||||
ack = GMU_OOB_PERFCOUNTER_ACK;
|
|
||||||
} else {
|
|
||||||
request = GMU_OOB_PERFCOUNTER_REQUEST_NEW;
|
|
||||||
ack = GMU_OOB_PERFCOUNTER_ACK_NEW;
|
|
||||||
}
|
|
||||||
name = "PERFCOUNTER";
|
|
||||||
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:
|
|
||||||
return -EINVAL;
|
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 */
|
/* Trigger the equested OOB operation */
|
||||||
@ -298,7 +317,7 @@ int a6xx_gmu_set_oob(struct a6xx_gmu *gmu, enum a6xx_gmu_oob_state state)
|
|||||||
if (ret)
|
if (ret)
|
||||||
DRM_DEV_ERROR(gmu->dev,
|
DRM_DEV_ERROR(gmu->dev,
|
||||||
"Timeout waiting for GMU OOB set %s: 0x%x\n",
|
"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));
|
gmu_read(gmu, REG_A6XX_GMU_GMU2HOST_INTR_INFO));
|
||||||
|
|
||||||
/* Clear the acknowledge interrupt */
|
/* Clear the acknowledge interrupt */
|
||||||
@ -310,36 +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 */
|
/* Clear a pending OOB state in the GMU */
|
||||||
void a6xx_gmu_clear_oob(struct a6xx_gmu *gmu, enum a6xx_gmu_oob_state state)
|
void a6xx_gmu_clear_oob(struct a6xx_gmu *gmu, enum a6xx_gmu_oob_state state)
|
||||||
{
|
{
|
||||||
if (!gmu->legacy) {
|
int bit;
|
||||||
if (state == GMU_OOB_GPU_SET) {
|
|
||||||
gmu_write(gmu, REG_A6XX_GMU_HOST2GMU_INTR_SET,
|
|
||||||
1 << GMU_OOB_GPU_SET_CLEAR_NEW);
|
|
||||||
} else {
|
|
||||||
WARN_ON(state != GMU_OOB_PERFCOUNTER_SET);
|
|
||||||
gmu_write(gmu, REG_A6XX_GMU_HOST2GMU_INTR_SET,
|
|
||||||
1 << GMU_OOB_PERFCOUNTER_CLEAR_NEW);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (state) {
|
if (state >= ARRAY_SIZE(a6xx_gmu_oob_bits))
|
||||||
case GMU_OOB_GPU_SET:
|
return;
|
||||||
gmu_write(gmu, REG_A6XX_GMU_HOST2GMU_INTR_SET,
|
|
||||||
1 << GMU_OOB_GPU_SET_CLEAR);
|
if (gmu->legacy)
|
||||||
break;
|
bit = a6xx_gmu_oob_bits[state].ack;
|
||||||
case GMU_OOB_PERFCOUNTER_SET:
|
else
|
||||||
gmu_write(gmu, REG_A6XX_GMU_HOST2GMU_INTR_SET,
|
bit = a6xx_gmu_oob_bits[state].ack_new;
|
||||||
1 << GMU_OOB_PERFCOUNTER_CLEAR);
|
|
||||||
break;
|
gmu_write(gmu, REG_A6XX_GMU_HOST2GMU_INTR_SET, bit);
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Enable CPU control of SPTP power power collapse */
|
/* Enable CPU control of SPTP power power collapse */
|
||||||
|
@ -153,52 +153,27 @@ static inline void gmu_write_rscc(struct a6xx_gmu *gmu, u32 offset, u32 value)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
enum a6xx_gmu_oob_state {
|
enum a6xx_gmu_oob_state {
|
||||||
|
/*
|
||||||
|
* Let the GMU know that a boot or slumber operation has started. The value in
|
||||||
|
* REG_A6XX_GMU_BOOT_SLUMBER_OPTION lets the GMU know which operation we are
|
||||||
|
* doing
|
||||||
|
*/
|
||||||
GMU_OOB_BOOT_SLUMBER = 0,
|
GMU_OOB_BOOT_SLUMBER = 0,
|
||||||
|
/*
|
||||||
|
* Let the GMU know to not turn off any GPU registers while the CPU is in a
|
||||||
|
* critical section
|
||||||
|
*/
|
||||||
GMU_OOB_GPU_SET,
|
GMU_OOB_GPU_SET,
|
||||||
|
/*
|
||||||
|
* Set a new power level for the GPU when the CPU is doing frequency scaling
|
||||||
|
*/
|
||||||
GMU_OOB_DCVS_SET,
|
GMU_OOB_DCVS_SET,
|
||||||
|
/*
|
||||||
|
* Used to keep the GPU on for CPU-side reads of performance counters.
|
||||||
|
*/
|
||||||
GMU_OOB_PERFCOUNTER_SET,
|
GMU_OOB_PERFCOUNTER_SET,
|
||||||
};
|
};
|
||||||
|
|
||||||
/* These are the interrupt / ack bits for each OOB request that are set
|
|
||||||
* in a6xx_gmu_set_oob and a6xx_clear_oob
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Let the GMU know that a boot or slumber operation has started. The value in
|
|
||||||
* REG_A6XX_GMU_BOOT_SLUMBER_OPTION lets the GMU know which operation we are
|
|
||||||
* doing
|
|
||||||
*/
|
|
||||||
#define GMU_OOB_BOOT_SLUMBER_REQUEST 22
|
|
||||||
#define GMU_OOB_BOOT_SLUMBER_ACK 30
|
|
||||||
#define GMU_OOB_BOOT_SLUMBER_CLEAR 30
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Set a new power level for the GPU when the CPU is doing frequency scaling
|
|
||||||
*/
|
|
||||||
#define GMU_OOB_DCVS_REQUEST 23
|
|
||||||
#define GMU_OOB_DCVS_ACK 31
|
|
||||||
#define GMU_OOB_DCVS_CLEAR 31
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Let the GMU know to not turn off any GPU registers while the CPU is in a
|
|
||||||
* critical section
|
|
||||||
*/
|
|
||||||
#define GMU_OOB_GPU_SET_REQUEST 16
|
|
||||||
#define GMU_OOB_GPU_SET_ACK 24
|
|
||||||
#define GMU_OOB_GPU_SET_CLEAR 24
|
|
||||||
|
|
||||||
#define GMU_OOB_GPU_SET_REQUEST_NEW 30
|
|
||||||
#define GMU_OOB_GPU_SET_ACK_NEW 31
|
|
||||||
#define GMU_OOB_GPU_SET_CLEAR_NEW 31
|
|
||||||
|
|
||||||
#define GMU_OOB_PERFCOUNTER_REQUEST 17
|
|
||||||
#define GMU_OOB_PERFCOUNTER_ACK 25
|
|
||||||
#define GMU_OOB_PERFCOUNTER_CLEAR 25
|
|
||||||
|
|
||||||
#define GMU_OOB_PERFCOUNTER_REQUEST_NEW 28
|
|
||||||
#define GMU_OOB_PERFCOUNTER_ACK_NEW 30
|
|
||||||
#define GMU_OOB_PERFCOUNTER_CLEAR_NEW 30
|
|
||||||
|
|
||||||
void a6xx_hfi_init(struct a6xx_gmu *gmu);
|
void a6xx_hfi_init(struct a6xx_gmu *gmu);
|
||||||
int a6xx_hfi_start(struct a6xx_gmu *gmu, int boot_state);
|
int a6xx_hfi_start(struct a6xx_gmu *gmu, int boot_state);
|
||||||
void a6xx_hfi_stop(struct a6xx_gmu *gmu);
|
void a6xx_hfi_stop(struct a6xx_gmu *gmu);
|
||||||
|
Loading…
Reference in New Issue
Block a user