radeon_ms: add hang debuging helper functions
[profile/ivi/libdrm.git] / shared-core / radeon_ms_cp.c
1 /*
2  * Copyright 2007 Jérôme Glisse
3  * Copyright 2007 Dave Airlie
4  * Copyright 2007 Alex Deucher
5  * All Rights Reserved.
6  *
7  * Permission is hereby granted, free of charge, to any person obtaining a
8  * copy of this software and associated documentation files (the "Software"),
9  * to deal in the Software without restriction, including without limitation
10  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11  * and/or sell copies of the Software, and to permit persons to whom the
12  * Software is furnished to do so, subject to the following conditions:
13  *
14  * The above copyright notice and this permission notice (including the next
15  * paragraph) shall be included in all copies or substantial portions of the
16  * Software.
17  *
18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
21  * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
22  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
23  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
24  * DEALINGS IN THE SOFTWARE.
25  */
26 /*
27  * Authors:
28  *    Jerome Glisse <glisse@freedesktop.org>
29  */
30 #include "radeon_ms.h"
31
32 static int radeon_ms_test_ring_buffer(struct drm_device *dev)
33 {
34         struct drm_radeon_private *dev_priv = dev->dev_private;
35         int i, ret;
36         uint32_t cmd[4];
37
38         MMIO_W(SCRATCH_REG4, 0);
39         cmd[0] = CP_PACKET0(SCRATCH_REG4, 0);
40         cmd[1] = 0xdeadbeef;
41         cmd[2] = CP_PACKET0(WAIT_UNTIL, 0);
42         cmd[3] = WAIT_UNTIL__WAIT_2D_IDLECLEAN |
43                 WAIT_UNTIL__WAIT_HOST_IDLECLEAN;
44         DRM_MEMORYBARRIER();
45         ret = radeon_ms_ring_emit(dev, cmd, 4);
46         if (ret) {
47                 return 0;
48         }
49         DRM_UDELAY(100);
50
51         for (i = 0; i < dev_priv->usec_timeout; i++) {
52                 if (MMIO_R(SCRATCH_REG4) == 0xdeadbeef) {
53                         DRM_INFO("[radeon_ms] cp test succeeded in %d usecs\n",
54                                  i);
55                         return 1;
56                 }
57                 DRM_UDELAY(1);
58         }
59         DRM_INFO("[radeon_ms] cp test failed\n");
60         return 0;
61 }
62
63 static int radeon_ms_test_write_back(struct drm_device *dev)
64 {
65         struct drm_radeon_private *dev_priv = dev->dev_private;
66         uint32_t tmp;
67
68         if (dev_priv->ring_buffer_object == NULL ||
69             dev_priv->ring_buffer == NULL)
70             return 0;
71         dev_priv->write_back_area[0] = 0x0;
72         MMIO_W(SCRATCH_REG0, 0xdeadbeef);
73         for (tmp = 0; tmp < dev_priv->usec_timeout; tmp++) {
74                 if (dev_priv->write_back_area[0] == 0xdeadbeef)
75                         break;
76                 DRM_UDELAY(1);
77         }
78         if (tmp < dev_priv->usec_timeout) {
79                 DRM_INFO("[radeon_ms] writeback test succeeded in %d usecs\n",
80                          tmp);
81                 return 1;
82         }
83         MMIO_W(SCRATCH_UMSK, 0x0);
84         DRM_INFO("[radeon_ms] writeback test failed\n");
85         return 0;
86 }
87
88 static __inline__ void radeon_ms_load_mc(struct drm_device *dev)
89 {
90         struct drm_radeon_private *dev_priv = dev->dev_private;
91         int i;
92
93         MMIO_W(CP_ME_RAM_ADDR, 0);
94         for (i = 0; i < 256; i++) {
95                 MMIO_W(CP_ME_RAM_DATAH, dev_priv->microcode[(i * 2) + 1]);
96                 MMIO_W(CP_ME_RAM_DATAL, dev_priv->microcode[(i * 2) + 0]);
97         }
98 }
99
100 int radeon_ms_cp_finish(struct drm_device *dev)
101 {
102         struct drm_radeon_private *dev_priv = dev->dev_private;
103
104         if (!dev_priv->cp_ready) {
105                 return 0;
106         }
107         dev_priv->cp_ready = 0;
108         radeon_ms_wait_for_idle(dev);
109         DRM_INFO("[radeon_ms] cp idle\n");
110         radeon_ms_cp_stop(dev);
111
112         DRM_INFO("[radeon_ms] ring buffer %p\n", dev_priv->ring_buffer);
113         if (dev_priv->ring_buffer) {
114                 drm_bo_kunmap(&dev_priv->ring_buffer_map);
115         }
116         dev_priv->ring_buffer = NULL;
117         DRM_INFO("[radeon_ms] ring buffer object %p\n", dev_priv->ring_buffer_object);
118         if (dev_priv->ring_buffer_object) {
119                 mutex_lock(&dev->struct_mutex);
120                 drm_bo_usage_deref_locked(&dev_priv->ring_buffer_object);
121                 mutex_unlock(&dev->struct_mutex);
122         }
123         return 0;
124 }
125
126 int radeon_ms_cp_init(struct drm_device *dev)
127 {
128         struct drm_radeon_private *dev_priv = dev->dev_private;
129         struct radeon_state *state = &dev_priv->driver_state;
130         int ret = 0;
131
132         dev_priv->cp_ready = -1;
133         if (dev_priv->microcode == NULL) {
134                 DRM_INFO("[radeon_ms] no microcode not starting cp");
135                 return 0;
136         }
137         /* we allocate an extra page for all write back stuff */
138         ret = drm_buffer_object_create(dev,
139                         dev_priv->ring_buffer_size +
140                         dev_priv->write_back_area_size,
141                         drm_bo_type_kernel,
142                         DRM_BO_FLAG_READ |
143                         DRM_BO_FLAG_WRITE |
144                         DRM_BO_FLAG_MEM_TT |
145                         DRM_BO_FLAG_NO_EVICT,
146                         DRM_BO_HINT_DONT_FENCE,
147                         1,
148                         0,
149                         &dev_priv->ring_buffer_object);
150         if (ret) {
151                 return ret;
152         }
153         memset(&dev_priv->ring_buffer_map, 0, sizeof(struct drm_bo_kmap_obj));
154         ret = drm_bo_kmap(dev_priv->ring_buffer_object,
155                         dev_priv->ring_buffer_object->mem.mm_node->start,
156                         dev_priv->ring_buffer_object->mem.num_pages,
157                         &dev_priv->ring_buffer_map);
158         if (ret) {
159                 DRM_INFO("[radeon_ms] error mapping ring buffer: %d\n", ret);
160                 return ret;
161         }
162         dev_priv->ring_buffer = dev_priv->ring_buffer_map.virtual; 
163         dev_priv->write_back_area =
164                 &dev_priv->ring_buffer[dev_priv->ring_buffer_size >> 2];
165         /* setup write back offset */
166         state->scratch_umsk = 0x7; 
167         state->scratch_addr = 
168                 REG_S(SCRATCH_ADDR, SCRATCH_ADDR,
169                                 (dev_priv->ring_buffer_object->offset +
170                                  dev_priv->ring_buffer_size +
171                                  dev_priv->gpu_gart_start) >> 5);
172         MMIO_W(SCRATCH_ADDR, state->scratch_addr);
173         MMIO_W(SCRATCH_UMSK, REG_S(SCRATCH_UMSK, SCRATCH_UMSK, 0x7));
174         DRM_INFO("[radeon_ms] write back at 0x%08X in gpu space\n",
175                  MMIO_R(SCRATCH_ADDR));
176         dev_priv->write_back = radeon_ms_test_write_back(dev);
177
178         /* stop cp so it's in know state */
179         radeon_ms_cp_stop(dev);
180         if (dev_priv->ring_rptr) {
181                 DRM_INFO("[radeon_ms] failed to set cp read ptr to 0\n");
182         } else {
183                 DRM_INFO("[radeon_ms] set cp read ptr to 0\n");
184         }
185         dev_priv->ring_mask = (dev_priv->ring_buffer_size / 4) - 1;
186
187         /* load microcode */
188         DRM_INFO("[radeon_ms] load microcode\n");
189         radeon_ms_load_mc(dev);
190         /* initialize CP registers */
191         state->cp_rb_cntl =
192                 REG_S(CP_RB_CNTL, RB_BUFSZ,
193                                 drm_order(dev_priv->ring_buffer_size / 8)) |
194                 REG_S(CP_RB_CNTL, RB_BLKSZ, drm_order(4096 / 8)) |
195                 REG_S(CP_RB_CNTL, MAX_FETCH, 2);
196         if (!dev_priv->write_back) {
197                 state->cp_rb_cntl |= CP_RB_CNTL__RB_NO_UPDATE;
198         }
199         state->cp_rb_base =
200                 REG_S(CP_RB_BASE, RB_BASE,
201                                 (dev_priv->ring_buffer_object->offset +
202                                  dev_priv->gpu_gart_start) >> 2);
203         /* read ptr writeback just after the
204          * 8 scratch registers 32 = 8*4 */
205         state->cp_rb_rptr_addr =
206                 REG_S(CP_RB_RPTR_ADDR, RB_RPTR_ADDR,
207                                 (dev_priv->ring_buffer_object->offset +
208                                  dev_priv->ring_buffer_size + 32 +
209                                  dev_priv->gpu_gart_start) >> 2);
210         state->cp_rb_wptr = dev_priv->ring_wptr;
211         state->cp_rb_wptr_delay =
212                 REG_S(CP_RB_WPTR_DELAY, PRE_WRITE_TIMER, 64) |
213                 REG_S(CP_RB_WPTR_DELAY, PRE_WRITE_LIMIT, 8);
214         state->cp_rb_wptr_delay = 0; 
215
216         radeon_ms_cp_restore(dev, state);
217         DRM_INFO("[radeon_ms] ring buffer at 0x%08X in gpu space\n",
218                  MMIO_R(CP_RB_BASE));
219
220         /* compute free space */
221         dev_priv->ring_free = 0;
222         ret = radeon_ms_cp_wait(dev, 64);
223         if (ret) {
224                 /* we shouldn't fail here */
225                 DRM_INFO("[radeon_ms] failed to get ring free space\n");
226                 return ret;
227         }
228         DRM_INFO("[radeon_ms] free ring size: %d\n", dev_priv->ring_free * 4);
229
230         MMIO_W(CP_CSQ_CNTL, REG_S(CP_CSQ_CNTL, CSQ_MODE,
231                                 CSQ_MODE__CSQ_PRIBM_INDBM));
232         if (!radeon_ms_test_ring_buffer(dev)) {
233                 DRM_INFO("[radeon_ms] cp doesn't work\n");
234                 /* disable ring should wait idle before */
235                 radeon_ms_cp_stop(dev);
236                 return -EBUSY;
237         }
238         /* waaooo the cp is ready & working */
239         DRM_INFO("[radeon_ms] cp ready, enjoy\n");
240         dev_priv->cp_ready = 1;
241         return 0;
242 }
243
244 void radeon_ms_cp_restore(struct drm_device *dev, struct radeon_state *state)
245 {
246         struct drm_radeon_private *dev_priv = dev->dev_private;
247
248         radeon_ms_wait_for_idle(dev);
249         MMIO_W(SCRATCH_ADDR, state->scratch_addr);
250         MMIO_W(SCRATCH_UMSK, state->scratch_umsk);
251         MMIO_W(CP_RB_BASE, state->cp_rb_base);
252         MMIO_W(CP_RB_RPTR_ADDR, state->cp_rb_rptr_addr);
253         MMIO_W(CP_RB_WPTR_DELAY, state->cp_rb_wptr_delay);
254         MMIO_W(CP_RB_CNTL, state->cp_rb_cntl);
255         /* Sync everything up */
256         MMIO_W(ISYNC_CNTL, ISYNC_CNTL__ISYNC_ANY2D_IDLE3D |
257                            ISYNC_CNTL__ISYNC_ANY3D_IDLE2D |
258                            ISYNC_CNTL__ISYNC_WAIT_IDLEGUI |
259                            ISYNC_CNTL__ISYNC_CPSCRATCH_IDLEGUI);
260 }
261
262 void radeon_ms_cp_save(struct drm_device *dev, struct radeon_state *state)
263 {
264         struct drm_radeon_private *dev_priv = dev->dev_private;
265
266         state->scratch_addr = MMIO_R(SCRATCH_ADDR);
267         state->scratch_umsk = MMIO_R(SCRATCH_UMSK);
268         state->cp_rb_base = MMIO_R(CP_RB_BASE);
269         state->cp_rb_rptr_addr = MMIO_R(CP_RB_RPTR_ADDR);
270         state->cp_rb_wptr_delay = MMIO_R(CP_RB_WPTR_DELAY);
271         state->cp_rb_wptr = MMIO_R(CP_RB_WPTR);
272         state->cp_rb_cntl = MMIO_R(CP_RB_CNTL);
273 }
274
275 void radeon_ms_cp_stop(struct drm_device *dev)
276 {
277         struct drm_radeon_private *dev_priv = dev->dev_private;
278         uint32_t rbbm_status, rbbm_status_cp_mask;
279
280         dev_priv->cp_ready = 0;
281         MMIO_W(CP_CSQ_CNTL, 0);
282         MMIO_R(CP_CSQ_CNTL);
283         MMIO_W(CP_CSQ_MODE, 0);
284         MMIO_R(CP_CSQ_MODE);
285         MMIO_W(RBBM_SOFT_RESET, RBBM_SOFT_RESET__SOFT_RESET_CP);
286         MMIO_R(RBBM_SOFT_RESET);
287         MMIO_W(RBBM_SOFT_RESET, 0);
288         MMIO_R(RBBM_SOFT_RESET);
289         rbbm_status = MMIO_R(RBBM_STATUS);
290         rbbm_status_cp_mask = (RBBM_STATUS__CPRQ_ON_RBB |
291                                RBBM_STATUS__CPRQ_IN_RTBUF |
292                                RBBM_STATUS__CP_CMDSTRM_BUSY);
293         if (rbbm_status & rbbm_status_cp_mask) {
294                 DRM_INFO("[radeon_ms] cp busy (RBBM_STATUS: 0x%08X "
295                          "RBBM_STATUS(cp_mask): 0x%08X)\n", rbbm_status,
296                          rbbm_status_cp_mask);
297         }
298         MMIO_W(CP_RB_CNTL, CP_RB_CNTL__RB_RPTR_WR_ENA);
299         MMIO_W(CP_RB_RPTR_WR, 0);
300         MMIO_W(CP_RB_WPTR, 0);
301         DRM_UDELAY(5);
302         dev_priv->ring_wptr = dev_priv->ring_rptr = MMIO_R(CP_RB_RPTR);
303         MMIO_W(CP_RB_CNTL, 0);
304 }
305
306 int radeon_ms_cp_wait(struct drm_device *dev, int n)
307 {
308         struct drm_radeon_private *dev_priv = dev->dev_private;
309         uint32_t i, last_rptr, p = 0;
310
311         last_rptr = MMIO_R(CP_RB_RPTR);
312         for (i = 0; i < dev_priv->usec_timeout; i++) {
313                 dev_priv->ring_rptr = MMIO_R(CP_RB_RPTR);
314                 if (last_rptr != dev_priv->ring_rptr) {
315                         /* the ring is progressing no lockup */
316                         p = 1;
317                 }
318                 dev_priv->ring_free = (((int)dev_priv->ring_rptr) -
319                                        ((int)dev_priv->ring_wptr));
320                 if (dev_priv->ring_free <= 0)
321                         dev_priv->ring_free += (dev_priv->ring_buffer_size / 4);
322                 if (dev_priv->ring_free > n)
323                         return 0;
324                 last_rptr = dev_priv->ring_rptr;
325                 DRM_UDELAY(1);
326         }
327         if (p) {
328                 DRM_INFO("[radeon_ms] timed out waiting free slot\n");
329         } else {
330                 DRM_INFO("[radeon_ms] cp have lickely locked up\n");
331         }
332         return -EBUSY;
333 }
334
335 int radeon_ms_ring_emit(struct drm_device *dev, uint32_t *cmd, uint32_t count)
336 {
337         static spinlock_t ring_lock = SPIN_LOCK_UNLOCKED;
338         struct drm_radeon_private *dev_priv = dev->dev_private;
339         uint32_t i = 0;
340
341         if (!count)
342                 return -EINVAL;
343
344         spin_lock(&ring_lock);
345         if (dev_priv->ring_free <= (count)) {
346                 spin_unlock(&ring_lock);
347                 return -EBUSY;
348         }
349         dev_priv->ring_free -= count;
350         for (i = 0; i < count; i++) {
351                 dev_priv->ring_buffer[dev_priv->ring_wptr] = cmd[i];
352                 DRM_INFO("ring[%d] = 0x%08X\n", dev_priv->ring_wptr, cmd[i]);
353                 dev_priv->ring_wptr++;
354                 dev_priv->ring_wptr &= dev_priv->ring_mask;
355         }
356         /* commit ring */
357         DRM_MEMORYBARRIER();
358         MMIO_W(CP_RB_WPTR, REG_S(CP_RB_WPTR, RB_WPTR, dev_priv->ring_wptr));
359         /* read from PCI bus to ensure correct posting */
360         MMIO_R(CP_RB_WPTR);
361         spin_unlock(&ring_lock);
362         return 0;
363 }
364
365 int radeon_ms_resetcp(struct drm_device *dev, void *data,
366                       struct drm_file *file_priv)
367 {
368         struct drm_radeon_private *dev_priv = dev->dev_private;
369         int i;
370
371         DRM_INFO("[radeon_ms]--------------------------------------------\n");
372
373         /* reset VAP */
374         DRM_INFO("[radeon_ms] status before VAP : RBBM_STATUS: 0x%08X\n",
375                  MMIO_R(RBBM_STATUS));
376         MMIO_W(RBBM_SOFT_RESET, RBBM_SOFT_RESET__SOFT_RESET_VAP);
377         MMIO_R(RBBM_SOFT_RESET);
378         MMIO_W(RBBM_SOFT_RESET, 0);
379         MMIO_R(RBBM_SOFT_RESET);
380         for (i = 0; i < 100; i++) {
381                 DRM_UDELAY(100);
382         }
383         DRM_INFO("[radeon_ms] status after VAP  : RBBM_STATUS: 0x%08X\n",
384                  MMIO_R(RBBM_STATUS));
385
386         DRM_INFO("[radeon_ms]--------------------------------------------\n");
387         return 0;
388 }