2 /****************************************************************************
3 * Copyright (C) 2003-2006 by XGI Technology, Taiwan.
5 * All Rights Reserved. *
7 * Permission is hereby granted, free of charge, to any person obtaining
8 * a copy of this software and associated documentation files (the
9 * "Software"), to deal in the Software without restriction, including
10 * without limitation on the rights to use, copy, modify, merge,
11 * publish, distribute, sublicense, and/or sell copies of the Software,
12 * and to permit persons to whom the Software is furnished to do so,
13 * subject to the following conditions:
15 * The above copyright notice and this permission notice (including the
16 * next paragraph) shall be included in all copies or substantial
17 * portions of the Software.
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
20 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
22 * NON-INFRINGEMENT. IN NO EVENT SHALL XGI AND/OR
23 * ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
24 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
26 * DEALINGS IN THE SOFTWARE.
27 ***************************************************************************/
32 int xgi_ge_reset_ioctl(DRM_IOCTL_ARGS)
35 struct xgi_info *info = dev->dev_private;
47 #define STALL_INTERRUPT_RESET_THRESHOLD 0xffff
49 static unsigned int s_invalid_begin = 0;
51 static bool xgi_validate_signal(volatile u8 *mmio_vbase)
53 volatile u32 *const ge_3d_status =
54 (volatile u32 *)(mmio_vbase + 0x2800);
55 const u32 old_ge_status = ge_3d_status[0x00];
57 if (old_ge_status & 0x001c0000) {
60 /* Check Read back status */
61 *(mmio_vbase + 0x235c) = 0x80;
62 check = *((volatile u16 *)(mmio_vbase + 0x2360));
64 if ((check & 0x3f) != ((check & 0x3f00) >> 8)) {
68 /* Check RO channel */
69 *(mmio_vbase + 0x235c) = 0x83;
70 check = *((volatile u16 *)(mmio_vbase + 0x2360));
71 if ((check & 0x0f) != ((check & 0xf0) >> 4)) {
75 /* Check RW channel */
76 *(mmio_vbase + 0x235c) = 0x88;
77 check = *((volatile u16 *)(mmio_vbase + 0x2360));
78 if ((check & 0x0f) != ((check & 0xf0) >> 4)) {
82 /* Check RO channel outstanding */
83 *(mmio_vbase + 0x235c) = 0x8f;
84 check = *((volatile u16 *)(mmio_vbase + 0x2360));
85 if (0 != (check & 0x3ff)) {
89 /* Check RW channel outstanding */
90 *(mmio_vbase + 0x235c) = 0x90;
91 check = *((volatile u16 *)(mmio_vbase + 0x2360));
92 if (0 != (check & 0x3ff)) {
96 /* No pending PCIE request. GE stall. */
103 static void xgi_ge_hang_reset(volatile u8 *mmio_vbase)
105 volatile u32 *const ge_3d_status =
106 (volatile u32 *)(mmio_vbase + 0x2800);
107 int time_out = 0xffff;
109 *(mmio_vbase + 0xb057) = 8;
110 while (0 != (ge_3d_status[0x00] & 0xf0000000)) {
111 while (0 != ((--time_out) & 0xfff))
120 DRM_INFO("Can not reset back 0x%x!\n",
123 *(mmio_vbase + 0xb057) = 0;
125 /* Have to use 3x5.36 to reset. */
126 /* Save and close dynamic gating */
128 old_3ce = *(mmio_vbase + 0x3ce);
129 *(mmio_vbase + 0x3ce) = 0x2a;
130 old_3cf = *(mmio_vbase + 0x3cf);
131 *(mmio_vbase + 0x3cf) = old_3cf & 0xfe;
134 old_index = *(mmio_vbase + 0x3d4);
135 *(mmio_vbase + 0x3d4) = 0x36;
136 old_36 = *(mmio_vbase + 0x3d5);
137 *(mmio_vbase + 0x3d5) = old_36 | 0x10;
139 while (0 != ((--time_out) & 0xfff))
142 *(mmio_vbase + 0x3d5) = old_36;
143 *(mmio_vbase + 0x3d4) = old_index;
145 /* Restore dynamic gating */
146 *(mmio_vbase + 0x3cf) = old_3cf;
147 *(mmio_vbase + 0x3ce) = old_3ce;
152 *(mmio_vbase + 0xb057) = 0;
156 bool xgi_ge_irq_handler(struct xgi_info * info)
158 volatile u8 *const mmio_vbase = info->mmio_map->handle;
159 volatile u32 *const ge_3d_status =
160 (volatile u32 *)(mmio_vbase + 0x2800);
161 const u32 int_status = ge_3d_status[4];
162 bool is_support_auto_reset = FALSE;
164 /* Check GE on/off */
165 if (0 == (0xffffc0f0 & int_status)) {
166 u32 old_pcie_cmd_fetch_Addr = ge_3d_status[0x0a];
168 if (0 != (0x1000 & int_status)) {
169 /* We got GE stall interrupt.
171 ge_3d_status[0x04] = int_status | 0x04000000;
173 if (is_support_auto_reset) {
174 static cycles_t last_tick;
175 static unsigned continue_int_count = 0;
179 if (!xgi_validate_signal(mmio_vbase)) {
180 /* Nothing but skip. */
181 } else if (0 == continue_int_count++) {
182 last_tick = get_cycles();
184 const cycles_t new_tick = get_cycles();
185 if ((new_tick - last_tick) >
186 STALL_INTERRUPT_RESET_THRESHOLD) {
187 continue_int_count = 0;
188 } else if (continue_int_count >= 3) {
189 continue_int_count = 0;
191 /* GE Hung up, need reset. */
192 DRM_INFO("Reset GE!\n");
194 xgi_ge_hang_reset(mmio_vbase);
198 } else if (0 != (0x1 & int_status)) {
200 ge_3d_status[0x04] = (int_status & ~0x01) | 0x04000000;
209 bool xgi_crt_irq_handler(struct xgi_info * info)
212 u8 save_3ce = DRM_READ8(info->mmio_map, 0x3ce);
214 if (IN3CFB(info->mmio_map, 0x37) & 0x01) // CRT1 interrupt just happened
220 op3cf_37 = IN3CFB(info->mmio_map, 0x37);
222 // Clear CRT interrupt
223 op3cf_3d = IN3CFB(info->mmio_map, 0x3d);
224 OUT3CFB(info->mmio_map, 0x3d, (op3cf_3d | 0x04));
225 OUT3CFB(info->mmio_map, 0x3d, (op3cf_3d & ~0x04));
228 DRM_WRITE8(info->mmio_map, 0x3ce, save_3ce);
233 bool xgi_dvi_irq_handler(struct xgi_info * info)
236 const u8 save_3ce = DRM_READ8(info->mmio_map, 0x3ce);
238 if (IN3CFB(info->mmio_map, 0x38) & 0x20) { // DVI interrupt just happened
239 const u8 save_3x4 = DRM_READ8(info->mmio_map, 0x3d4);
245 op3cf_37 = IN3CFB(info->mmio_map, 0x37);
247 //Notify BIOS that DVI plug/unplug happened
248 op3x5_5a = IN3X5B(info->mmio_map, 0x5a);
249 OUT3X5B(info->mmio_map, 0x5a, op3x5_5a & 0xf7);
251 DRM_WRITE8(info->mmio_map, 0x3d4, save_3x4);
253 // Clear DVI interrupt
254 op3cf_39 = IN3CFB(info->mmio_map, 0x39);
255 OUT3C5B(info->mmio_map, 0x39, (op3cf_39 & ~0x01)); //Set 3cf.39 bit 0 to 0
256 OUT3C5B(info->mmio_map, 0x39, (op3cf_39 | 0x01)); //Set 3cf.39 bit 0 to 1
260 DRM_WRITE8(info->mmio_map, 0x3ce, save_3ce);
266 void xgi_dump_register(struct xgi_info * info)
272 printk("\r\n=====xgi_dump_register========0x%x===============\r\n",
275 for (i = 0; i < 0x10; i++) {
284 for (i = 0; i < 0x10; i++) {
287 for (j = 0; j < 0x10; j++) {
288 temp = IN3C5B(info->mmio_map, i * 0x10 + j);
295 printk("\r\n====xgi_dump_register=========0x%x===============\r\n",
297 for (i = 0; i < 0x10; i++) {
306 for (i = 0; i < 0x10; i++) {
309 for (j = 0; j < 0x10; j++) {
310 temp = IN3X5B(info->mmio_map, i * 0x10 + j);
317 printk("\r\n=========xgi_dump_register====0x%x===============\r\n",
319 for (i = 0; i < 0x10; i++) {
328 for (i = 0; i < 0x10; i++) {
331 for (j = 0; j < 0x10; j++) {
332 temp = IN3CFB(info->mmio_map, i * 0x10 + j);
338 printk("\r\n=====xgi_dump_register======0x%x===============\r\n",
340 for (i = 0; i < 0x10; i++) {
349 for (i = 0; i < 0x5; i++) {
352 for (j = 0; j < 0x10; j++) {
353 temp = DRM_READ8(info->mmio_map, 0xB000 + i * 0x10 + j);
359 printk("\r\n==================0x%x===============\r\n", 0x2200);
360 for (i = 0; i < 0x10; i++) {
369 for (i = 0; i < 0xB; i++) {
372 for (j = 0; j < 0x10; j++) {
373 temp = DRM_READ8(info->mmio_map, 0x2200 + i * 0x10 + j);
379 printk("\r\n==================0x%x===============\r\n", 0x2300);
380 for (i = 0; i < 0x10; i++) {
389 for (i = 0; i < 0x7; i++) {
392 for (j = 0; j < 0x10; j++) {
393 temp = DRM_READ8(info->mmio_map, 0x2300 + i * 0x10 + j);
399 printk("\r\n==================0x%x===============\r\n", 0x2400);
400 for (i = 0; i < 0x10; i++) {
409 for (i = 0; i < 0x10; i++) {
412 for (j = 0; j < 0x10; j++) {
413 temp = DRM_READ8(info->mmio_map, 0x2400 + i * 0x10 + j);
419 printk("\r\n==================0x%x===============\r\n", 0x2800);
420 for (i = 0; i < 0x10; i++) {
429 for (i = 0; i < 0x10; i++) {
432 for (j = 0; j < 0x10; j++) {
433 temp = DRM_READ8(info->mmio_map, 0x2800 + i * 0x10 + j);
441 int xgi_dump_register_ioctl(DRM_IOCTL_ARGS)
444 struct xgi_info *info = dev->dev_private;
446 xgi_dump_register(info);
452 int xgi_restore_registers_ioctl(DRM_IOCTL_ARGS)
455 struct xgi_info *info = dev->dev_private;
457 OUT3X5B(info->mmio_map, 0x13, 0);
458 OUT3X5B(info->mmio_map, 0x8b, 2);
463 void xgi_waitfor_pci_idle(struct xgi_info * info)
465 #define WHOLD_GE_STATUS 0x2800
466 #define IDLE_MASK ~0x90200000
469 while (idleCount < 5) {
470 if (DRM_READ32(info->mmio_map, WHOLD_GE_STATUS) & IDLE_MASK) {