From: Russell King <rmk+ker...@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

Reply via email to