[PATCH RFC 009/111] staging: etnaviv: fix etnaviv_hw_reset()

Lucas Stach l.stach at pengutronix.de
Thu Apr 2 08:29:11 PDT 2015


From: Russell King <rmk+kernel at arm.linux.org.uk>

Ensure that we reset the GPU with the clocks on, and restore the clock
state after GPU reset has completed.  Without this, register accesses
can fail:

Unhandled fault: external abort on non-linefetch (0x1828) at 0xfe640418
Internal error: : 1828 [#1] PREEMPT ARM
Modules linked in: etnaviv(C+) ...
CPU: 0 PID: 1617 Comm: modprobe Tainted: G C    3.16.0+ #1010
task: d6210140 ti: d4102000 task.ti: d4102000
PC is at etnaviv_writel+0x2c/0x38 [etnaviv]
LR is at etnaviv_gpu_init+0x304/0x5cc [etnaviv]
pc : [<bf104960>]    lr : [<bf107228>]    psr: 600f0013
sp : d4103ba8  ip : d4103bc0  fp : d4103bbc
r10: 00000000  r9 : 00000000  r8 : cd45b034
r7 : d43ee480  r6 : d5ab1c10  r5 : 00000000  r4 : fe640418
r3 : 00000000  r2 : 00000000  r1 : fe640418  r0 : 00000000
Flags: nZCv  IRQs on  FIQs on  Mode SVC_32  ISA ARM  Segment user
Control: 10c5387d  Table: 143d4019  DAC: 00000015
Process modprobe (pid: 1617, stack limit = 0xd4102250)
Backtrace:
[<bf104934>] (etnaviv_writel [etnaviv]) from [<bf107228>] (etnaviv_gpu_init+0x304/0x5cc [etnaviv])
[<bf106f24>] (etnaviv_gpu_init [etnaviv]) from [<bf10481c>] (etnaviv_load+0xbc/0x128 [etnaviv])
[<bf104760>] (etnaviv_load [etnaviv]) from [<c0270a8c>] (drm_dev_register+0xa8/0x108)
[<c02709e4>] (drm_dev_register) from [<c027238c>] (drm_platform_init+0x50/0xe8)
...

Signed-off-by: Russell King <rmk+kernel at arm.linux.org.uk>
---
 drivers/staging/etnaviv/etnaviv_gpu.c | 20 +++++++++++++++++++-
 1 file changed, 19 insertions(+), 1 deletion(-)

diff --git a/drivers/staging/etnaviv/etnaviv_gpu.c b/drivers/staging/etnaviv/etnaviv_gpu.c
index 40ee6ac2ccd7..56afba7625ed 100644
--- a/drivers/staging/etnaviv/etnaviv_gpu.c
+++ b/drivers/staging/etnaviv/etnaviv_gpu.c
@@ -260,7 +260,16 @@ static void etnaviv_hw_reset(struct etnaviv_gpu *gpu)
 	 */
 
 	while (true) {
-		control = gpu_read(gpu, VIVS_HI_CLOCK_CONTROL);
+		control = VIVS_HI_CLOCK_CONTROL_DISABLE_DEBUG_REGISTERS |
+			  VIVS_HI_CLOCK_CONTROL_FSCALE_VAL(0x40);
+
+		/* enable clock */
+		gpu_write(gpu, VIVS_HI_CLOCK_CONTROL, control |
+			  VIVS_HI_CLOCK_CONTROL_FSCALE_CMD_LOAD);
+		gpu_write(gpu, VIVS_HI_CLOCK_CONTROL, control);
+
+		/* Wait for stable clock.  Vivante's code waited for 1ms */
+		usleep_range(1000, 10000);
 
 		/* isolate the GPU. */
 		control |= VIVS_HI_CLOCK_CONTROL_ISOLATE_GPU;
@@ -302,6 +311,15 @@ static void etnaviv_hw_reset(struct etnaviv_gpu *gpu)
 
 		break;
 	}
+
+	/* 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);
+
+	/* enable clock */
+	gpu_write(gpu, VIVS_HI_CLOCK_CONTROL, control |
+		  VIVS_HI_CLOCK_CONTROL_FSCALE_CMD_LOAD);
+	gpu_write(gpu, VIVS_HI_CLOCK_CONTROL, control);
 }
 
 int etnaviv_gpu_init(struct etnaviv_gpu *gpu)
-- 
2.1.4



More information about the dri-devel mailing list