1 /****************************************************************************
2 * Copyright (C) 2003-2006 by XGI Technology, Taiwan.
6 * Permission is hereby granted, free of charge, to any person obtaining
7 * a copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation on the rights to use, copy, modify, merge,
10 * publish, distribute, sublicense, and/or sell copies of the Software,
11 * and to permit persons to whom the Software is furnished to do so,
12 * subject to the following conditions:
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial
16 * portions of the Software.
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
21 * XGI AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
24 * DEALINGS IN THE SOFTWARE.
25 ***************************************************************************/
30 int xgi_ge_reset_ioctl(DRM_IOCTL_ARGS)
33 struct xgi_info *info = dev->dev_private;
45 #define STALL_INTERRUPT_RESET_THRESHOLD 0xffff
47 static unsigned int s_invalid_begin = 0;
49 static bool xgi_validate_signal(volatile u8 *mmio_vbase)
51 volatile u32 *const ge_3d_status =
52 (volatile u32 *)(mmio_vbase + 0x2800);
53 const u32 old_ge_status = ge_3d_status[0x00];
55 if (old_ge_status & 0x001c0000) {
58 /* Check Read back status */
59 *(mmio_vbase + 0x235c) = 0x80;
60 check = *((volatile u16 *)(mmio_vbase + 0x2360));
62 if ((check & 0x3f) != ((check & 0x3f00) >> 8)) {
66 /* Check RO channel */
67 *(mmio_vbase + 0x235c) = 0x83;
68 check = *((volatile u16 *)(mmio_vbase + 0x2360));
69 if ((check & 0x0f) != ((check & 0xf0) >> 4)) {
73 /* Check RW channel */
74 *(mmio_vbase + 0x235c) = 0x88;
75 check = *((volatile u16 *)(mmio_vbase + 0x2360));
76 if ((check & 0x0f) != ((check & 0xf0) >> 4)) {
80 /* Check RO channel outstanding */
81 *(mmio_vbase + 0x235c) = 0x8f;
82 check = *((volatile u16 *)(mmio_vbase + 0x2360));
83 if (0 != (check & 0x3ff)) {
87 /* Check RW channel outstanding */
88 *(mmio_vbase + 0x235c) = 0x90;
89 check = *((volatile u16 *)(mmio_vbase + 0x2360));
90 if (0 != (check & 0x3ff)) {
94 /* No pending PCIE request. GE stall. */
101 static void xgi_ge_hang_reset(volatile u8 *mmio_vbase)
103 volatile u32 *const ge_3d_status =
104 (volatile u32 *)(mmio_vbase + 0x2800);
105 int time_out = 0xffff;
107 *(mmio_vbase + 0xb057) = 8;
108 while (0 != (ge_3d_status[0x00] & 0xf0000000)) {
109 while (0 != ((--time_out) & 0xfff))
118 DRM_INFO("Can not reset back 0x%x!\n",
121 *(mmio_vbase + 0xb057) = 0;
123 /* Have to use 3x5.36 to reset. */
124 /* Save and close dynamic gating */
126 old_3ce = *(mmio_vbase + 0x3ce);
127 *(mmio_vbase + 0x3ce) = 0x2a;
128 old_3cf = *(mmio_vbase + 0x3cf);
129 *(mmio_vbase + 0x3cf) = old_3cf & 0xfe;
132 old_index = *(mmio_vbase + 0x3d4);
133 *(mmio_vbase + 0x3d4) = 0x36;
134 old_36 = *(mmio_vbase + 0x3d5);
135 *(mmio_vbase + 0x3d5) = old_36 | 0x10;
137 while (0 != ((--time_out) & 0xfff))
140 *(mmio_vbase + 0x3d5) = old_36;
141 *(mmio_vbase + 0x3d4) = old_index;
143 /* Restore dynamic gating */
144 *(mmio_vbase + 0x3cf) = old_3cf;
145 *(mmio_vbase + 0x3ce) = old_3ce;
150 *(mmio_vbase + 0xb057) = 0;
154 bool xgi_ge_irq_handler(struct xgi_info * info)
156 volatile u8 *const mmio_vbase = info->mmio_map->handle;
157 volatile u32 *const ge_3d_status =
158 (volatile u32 *)(mmio_vbase + 0x2800);
159 const u32 int_status = ge_3d_status[4];
160 bool is_support_auto_reset = FALSE;
162 /* Check GE on/off */
163 if (0 == (0xffffc0f0 & int_status)) {
164 u32 old_pcie_cmd_fetch_Addr = ge_3d_status[0x0a];
166 if (0 != (0x1000 & int_status)) {
167 /* We got GE stall interrupt.
169 ge_3d_status[0x04] = int_status | 0x04000000;
171 if (is_support_auto_reset) {
172 static cycles_t last_tick;
173 static unsigned continue_int_count = 0;
177 if (!xgi_validate_signal(mmio_vbase)) {
178 /* Nothing but skip. */
179 } else if (0 == continue_int_count++) {
180 last_tick = get_cycles();
182 const cycles_t new_tick = get_cycles();
183 if ((new_tick - last_tick) >
184 STALL_INTERRUPT_RESET_THRESHOLD) {
185 continue_int_count = 0;
186 } else if (continue_int_count >= 3) {
187 continue_int_count = 0;
189 /* GE Hung up, need reset. */
190 DRM_INFO("Reset GE!\n");
192 xgi_ge_hang_reset(mmio_vbase);
196 } else if (0 != (0x1 & int_status)) {
198 ge_3d_status[0x04] = (int_status & ~0x01) | 0x04000000;
207 bool xgi_crt_irq_handler(struct xgi_info * info)
210 u8 save_3ce = DRM_READ8(info->mmio_map, 0x3ce);
212 if (IN3CFB(info->mmio_map, 0x37) & 0x01) // CRT1 interrupt just happened
218 op3cf_37 = IN3CFB(info->mmio_map, 0x37);
220 // Clear CRT interrupt
221 op3cf_3d = IN3CFB(info->mmio_map, 0x3d);
222 OUT3CFB(info->mmio_map, 0x3d, (op3cf_3d | 0x04));
223 OUT3CFB(info->mmio_map, 0x3d, (op3cf_3d & ~0x04));
226 DRM_WRITE8(info->mmio_map, 0x3ce, save_3ce);
231 bool xgi_dvi_irq_handler(struct xgi_info * info)
234 const u8 save_3ce = DRM_READ8(info->mmio_map, 0x3ce);
236 if (IN3CFB(info->mmio_map, 0x38) & 0x20) { // DVI interrupt just happened
237 const u8 save_3x4 = DRM_READ8(info->mmio_map, 0x3d4);
243 op3cf_37 = IN3CFB(info->mmio_map, 0x37);
245 //Notify BIOS that DVI plug/unplug happened
246 op3x5_5a = IN3X5B(info->mmio_map, 0x5a);
247 OUT3X5B(info->mmio_map, 0x5a, op3x5_5a & 0xf7);
249 DRM_WRITE8(info->mmio_map, 0x3d4, save_3x4);
251 // Clear DVI interrupt
252 op3cf_39 = IN3CFB(info->mmio_map, 0x39);
253 OUT3C5B(info->mmio_map, 0x39, (op3cf_39 & ~0x01)); //Set 3cf.39 bit 0 to 0
254 OUT3C5B(info->mmio_map, 0x39, (op3cf_39 | 0x01)); //Set 3cf.39 bit 0 to 1
258 DRM_WRITE8(info->mmio_map, 0x3ce, save_3ce);
264 void xgi_dump_register(struct xgi_info * info)
270 printk("\r\n=====xgi_dump_register========0x%x===============\r\n",
273 for (i = 0; i < 0x10; i++) {
282 for (i = 0; i < 0x10; i++) {
285 for (j = 0; j < 0x10; j++) {
286 temp = IN3C5B(info->mmio_map, i * 0x10 + j);
293 printk("\r\n====xgi_dump_register=========0x%x===============\r\n",
295 for (i = 0; i < 0x10; i++) {
304 for (i = 0; i < 0x10; i++) {
307 for (j = 0; j < 0x10; j++) {
308 temp = IN3X5B(info->mmio_map, i * 0x10 + j);
315 printk("\r\n=========xgi_dump_register====0x%x===============\r\n",
317 for (i = 0; i < 0x10; i++) {
326 for (i = 0; i < 0x10; i++) {
329 for (j = 0; j < 0x10; j++) {
330 temp = IN3CFB(info->mmio_map, i * 0x10 + j);
336 printk("\r\n=====xgi_dump_register======0x%x===============\r\n",
338 for (i = 0; i < 0x10; i++) {
347 for (i = 0; i < 0x5; i++) {
350 for (j = 0; j < 0x10; j++) {
351 temp = DRM_READ8(info->mmio_map, 0xB000 + i * 0x10 + j);
357 printk("\r\n==================0x%x===============\r\n", 0x2200);
358 for (i = 0; i < 0x10; i++) {
367 for (i = 0; i < 0xB; i++) {
370 for (j = 0; j < 0x10; j++) {
371 temp = DRM_READ8(info->mmio_map, 0x2200 + i * 0x10 + j);
377 printk("\r\n==================0x%x===============\r\n", 0x2300);
378 for (i = 0; i < 0x10; i++) {
387 for (i = 0; i < 0x7; i++) {
390 for (j = 0; j < 0x10; j++) {
391 temp = DRM_READ8(info->mmio_map, 0x2300 + i * 0x10 + j);
397 printk("\r\n==================0x%x===============\r\n", 0x2400);
398 for (i = 0; i < 0x10; i++) {
407 for (i = 0; i < 0x10; i++) {
410 for (j = 0; j < 0x10; j++) {
411 temp = DRM_READ8(info->mmio_map, 0x2400 + i * 0x10 + j);
417 printk("\r\n==================0x%x===============\r\n", 0x2800);
418 for (i = 0; i < 0x10; i++) {
427 for (i = 0; i < 0x10; i++) {
430 for (j = 0; j < 0x10; j++) {
431 temp = DRM_READ8(info->mmio_map, 0x2800 + i * 0x10 + j);
439 int xgi_dump_register_ioctl(DRM_IOCTL_ARGS)
442 struct xgi_info *info = dev->dev_private;
444 xgi_dump_register(info);
450 int xgi_restore_registers_ioctl(DRM_IOCTL_ARGS)
453 struct xgi_info *info = dev->dev_private;
455 OUT3X5B(info->mmio_map, 0x13, 0);
456 OUT3X5B(info->mmio_map, 0x8b, 2);
461 void xgi_waitfor_pci_idle(struct xgi_info * info)
463 #define WHOLD_GE_STATUS 0x2800
464 #define IDLE_MASK ~0x90200000
467 while (idleCount < 5) {
468 if (DRM_READ32(info->mmio_map, WHOLD_GE_STATUS) & IDLE_MASK) {