@@ -287,9 +287,11 @@ static void etnaviv_hw_identify(struct etnaviv_gpu *gpu)
etnaviv_hw_specs(gpu);
}
-static void etnaviv_hw_reset(struct etnaviv_gpu *gpu)
+static int etnaviv_hw_reset(struct etnaviv_gpu *gpu)
{
u32 control, idle;
+ unsigned long timeout;
+ bool failed = true;
/* TODO
*
@@ -298,7 +300,10 @@ static void etnaviv_hw_reset(struct etnaviv_gpu *gpu)
* - what about VG?
*/
- while (true) {
+ /* We hope that the GPU resets in under one second */
+ timeout = jiffies + msecs_to_jiffies(1000);
+
+ while (time_is_after_jiffies(timeout)) {
control = VIVS_HI_CLOCK_CONTROL_DISABLE_DEBUG_REGISTERS |
VIVS_HI_CLOCK_CONTROL_FSCALE_VAL(0x40);
@@ -342,15 +347,28 @@ static void etnaviv_hw_reset(struct etnaviv_gpu *gpu)
control = gpu_read(gpu, VIVS_HI_CLOCK_CONTROL);
/* is the GPU idle? */
- if (((control & VIVS_HI_CLOCK_CONTROL_IDLE_3D) == 0)
- || ((control & VIVS_HI_CLOCK_CONTROL_IDLE_2D) == 0)) {
+ if (((control & VIVS_HI_CLOCK_CONTROL_IDLE_3D) == 0) ||
+ ((control & VIVS_HI_CLOCK_CONTROL_IDLE_2D) == 0)) {
dev_dbg(gpu->dev, "GPU is not idle\n");
continue;
}
+ failed = false;
break;
}
+ if (failed) {
+ idle = gpu_read(gpu, VIVS_HI_IDLE_STATE);
+ control = gpu_read(gpu, VIVS_HI_CLOCK_CONTROL);
+
+ dev_err(gpu->dev, "GPU failed to reset: FE %sidle, 3D %sidle, 2D %sidle\n",
+ idle & VIVS_HI_IDLE_STATE_FE ? "" : "not ",
+ control & VIVS_HI_CLOCK_CONTROL_IDLE_3D ? "" : "not ",
+ control & VIVS_HI_CLOCK_CONTROL_IDLE_2D ? "" : "not ");
+
+ return -EBUSY;
+ }
+
/* We rely on the GPU running, so program the clock */
control = VIVS_HI_CLOCK_CONTROL_DISABLE_DEBUG_REGISTERS |
VIVS_HI_CLOCK_CONTROL_FSCALE_VAL(0x40);
@@ -359,6 +377,8 @@ static void etnaviv_hw_reset(struct etnaviv_gpu *gpu)
gpu_write(gpu, VIVS_HI_CLOCK_CONTROL, control |
VIVS_HI_CLOCK_CONTROL_FSCALE_CMD_LOAD);
gpu_write(gpu, VIVS_HI_CLOCK_CONTROL, control);
+
+ return 0;
}
int etnaviv_gpu_init(struct etnaviv_gpu *gpu)
@@ -369,7 +389,9 @@ int etnaviv_gpu_init(struct etnaviv_gpu *gpu)
bool mmuv2;
etnaviv_hw_identify(gpu);
- etnaviv_hw_reset(gpu);
+ ret = etnaviv_hw_reset(gpu);
+ if (ret)
+ return ret;
/* set base addresses */
gpu_write(gpu, VIVS_MC_MEMORY_BASE_ADDR_RA, 0x0);