radeonfb_bios.c revision 1.1.32.1 1 /* $NetBSD: radeonfb_bios.c,v 1.1.32.1 2007/10/26 15:46:54 joerg Exp $ */
2
3 /*-
4 * Copyright (c) 2006 Itronix Inc.
5 * All rights reserved.
6 *
7 * Written by Garrett D'Amore for Itronix Inc.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. The name of Itronix Inc. may not be used to endorse
18 * or promote products derived from this software without specific
19 * prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY ITRONIX INC. ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
23 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ITRONIX INC. BE LIABLE FOR ANY
25 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
28 * ON ANY THEORY OF LIABILITY, WHETHER IN
29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 * POSSIBILITY OF SUCH DAMAGE.
32 */
33
34 /*
35 * ATI Technologies Inc. ("ATI") has not assisted in the creation of, and
36 * does not endorse, this software. ATI will not be responsible or liable
37 * for any actual or alleged damage or loss caused by or in connection with
38 * the use of or reliance on this software.
39 */
40
41 #include <sys/cdefs.h>
42 __KERNEL_RCSID(0, "$NetBSD: radeonfb_bios.c,v 1.1.32.1 2007/10/26 15:46:54 joerg Exp $");
43
44 #include <sys/param.h>
45 #include <sys/systm.h>
46 #include <sys/device.h>
47 #include <sys/malloc.h>
48 #include <sys/bus.h>
49
50 #include <dev/pci/pcidevs.h>
51 #include <dev/pci/pcireg.h>
52 #include <dev/pci/pcivar.h>
53 #include <dev/pci/radeonfbreg.h>
54 #include <dev/pci/radeonfbvar.h>
55
56 #ifdef RADEON_BIOS_INIT
57
58 /*
59 * Globals for the entire BIOS.
60 */
61 #define ROM_HEADER_OFFSET 0x48
62 #define MAX_REVISION 0x10
63 #define SINGLE_TABLE_REVISION 0x09
64 #define MIN_OFFSET 0x60
65
66 /*
67 * Offsets of specific tables.
68 */
69 #define RAGE_REGS1_OFFSET 0x0c
70 #define RAGE_REGS2_OFFSET 0x4e
71 #define DYN_CLOCK_OFFSET 0x52
72 #define PLL_INIT_OFFSET 0x46
73 #define MEM_CONFIG_OFFSET 0x48
74
75 /*
76 * Values related to generic intialization tables.
77 */
78 #define TABLE_ENTRY_FLAG_MASK 0xe000
79 #define TABLE_ENTRY_INDEX_MASK 0x1fff
80 #define TABLE_ENTRY_COMMAND_MASK 0x00ff
81
82 #define TABLE_FLAG_WRITE_INDEXED 0x0000
83 #define TABLE_FLAG_WRITE_DIRECT 0x2000
84 #define TABLE_FLAG_MASK_INDEXED 0x4000
85 #define TABLE_FLAG_MASK_DIRECT 0x6000
86 #define TABLE_FLAG_DELAY 0x8000
87 #define TABLE_FLAG_SCOMMAND 0xa000
88
89 #define TABLE_SCOMMAND_WAIT_MC_BUSY_MASK 0x03
90 #define TABLE_SCOMMAND_WAIT_MEM_PWRUP_COMPLETE 0x08
91
92 /*
93 * PLL initialization block values.
94 */
95 #define PLL_FLAG_MASK 0xc0
96 #define PLL_INDEX_MASK 0x3f
97
98 #define PLL_FLAG_WRITE 0x00
99 #define PLL_FLAG_MASK_BYTE 0x40
100 #define PLL_FLAG_WAIT 0x80
101
102 #define PLL_WAIT_150MKS 1
103 #define PLL_WAIT_5MS 2
104 #define PLL_WAIT_MC_BUSY_MASK 3
105 #define PLL_WAIT_DLL_READY_MASK 4
106 #define PLL_WAIT_CHK_SET_CLK_PWRMGT_CNTL24 5
107
108
109 #ifdef RADEON_BIOS_DEBUG
110 #define DPRINTF(x) printf x
111 #else
112 #define DPRINTF(x)
113 #endif
114
115 struct rb_table;
116
117 static void rb_validate(struct radeonfb_softc *, struct rb_table *);
118 static uint16_t rb_find_asic_table(struct radeonfb_softc *, struct rb_table *);
119 static uint16_t rb_find_mem_reset_table(struct radeonfb_softc *,
120 struct rb_table *);
121 static uint16_t rb_find_short_mem_reset_table(struct radeonfb_softc *,
122 struct rb_table *);
123 static int rb_load_init_block(struct radeonfb_softc *, struct rb_table *);
124 static int rb_load_pll_block(struct radeonfb_softc *, struct rb_table *);
125 static int rb_reset_sdram(struct radeonfb_softc *, struct rb_table *);
126
127 static void rb_wait_mc_busy_mask(struct radeonfb_softc *, uint16_t);
128 static void rb_wait_mem_pwrup_complete(struct radeonfb_softc *, uint16_t);
129 static void rb_wait_dll_ready_mask(struct radeonfb_softc *, uint16_t);
130 static void rb_wait_chk_set_clk_pwrmgt_cntl24(struct radeonfb_softc *);
131
132 /*
133 * Generic structure describing the tables.
134 */
135 struct rb_table {
136 const unsigned char *name;
137 uint16_t offset;
138 struct rb_table *parent;
139
140 /* validate that the table looks sane */
141 void (*validate)(struct radeonfb_softc *, struct rb_table *);
142
143 /* find looks for the table relative to its "parent" */
144 uint16_t (*find)(struct radeonfb_softc *, struct rb_table *);
145 };
146
147 /*
148 * Instances of specific tables.
149 */
150 static struct rb_table rb_rage_regs1_table = {
151 "rage_regs_1", /* name */
152 RAGE_REGS1_OFFSET, /* offset */
153 NULL, /* parent */
154 rb_validate, /* validate */
155 NULL, /* find */
156 };
157
158 static struct rb_table rb_rage_regs2_table = {
159 "rage_regs_2", /* name */
160 RAGE_REGS2_OFFSET, /* offset */
161 NULL, /* parent */
162 rb_validate, /* validate */
163 NULL, /* find */
164 };
165
166 static struct rb_table rb_dyn_clock_table = {
167 "dyn_clock", /* name */
168 DYN_CLOCK_OFFSET, /* offset */
169 NULL, /* parent */
170 rb_validate, /* validate */
171 NULL, /* find */
172 };
173
174 static struct rb_table rb_pll_init_table = {
175 "pll_init", /* name */
176 PLL_INIT_OFFSET, /* offset */
177 NULL, /* parent */
178 rb_validate, /* validate */
179 NULL, /* find */
180 };
181
182 static struct rb_table rb_mem_config_table = {
183 "mem_config", /* name */
184 MEM_CONFIG_OFFSET, /* offset */
185 NULL, /* parent */
186 rb_validate, /* validate */
187 NULL, /* find */
188 };
189
190 static struct rb_table rb_mem_reset_table = {
191 "mem_reset", /* name */
192 0, /* offset */
193 &rb_mem_config_table, /* parent */
194 NULL, /* validate */
195 rb_find_mem_reset_table, /* find */
196 };
197
198 static struct rb_table rb_short_mem_reset_table = {
199 "short_mem_reset", /* name */
200 0, /* offset */
201 &rb_mem_config_table, /* parent */
202 NULL, /* validate */
203 rb_find_short_mem_reset_table, /* find */
204 };
205
206 static struct rb_table rb_rage_regs3_table = {
207 "rage_regs_3", /* name */
208 0, /* offset */
209 &rb_rage_regs2_table, /* parent */
210 NULL, /* validate */
211 rb_find_asic_table, /* find */
212 };
213
214 static struct rb_table rb_rage_regs4_table = {
215 "rage_regs_4", /* name */
216 0, /* offset */
217 &rb_rage_regs3_table, /* parent */
218 NULL, /* validate */
219 rb_find_asic_table, /* find */
220 };
221
222 static struct rb_table *rb_tables[] = {
223 &rb_rage_regs1_table,
224 &rb_rage_regs2_table,
225 &rb_dyn_clock_table,
226 &rb_pll_init_table,
227 &rb_mem_config_table,
228 &rb_mem_reset_table,
229 &rb_short_mem_reset_table,
230 &rb_rage_regs3_table,
231 &rb_rage_regs4_table,
232 NULL
233 };
234
235 void
236 rb_validate(struct radeonfb_softc *sc, struct rb_table *tp)
237 {
238 uint8_t rev;
239
240 rev = GETBIOS8(sc, tp->offset - 1);
241
242 if (rev > MAX_REVISION) {
243 DPRINTF(("%s: bad rev %x of %s\n", XNAME(sc), rev, tp->name));
244 tp->offset = 0;
245 return;
246 }
247
248 if (tp->offset < MIN_OFFSET) {
249 DPRINTF(("%s: wrong pointer to %s!\n", XNAME(sc), tp->name));
250 tp->offset = 0;
251 return;
252 }
253 }
254
255 uint16_t
256 rb_find_asic_table(struct radeonfb_softc *sc, struct rb_table *tp)
257 {
258 uint16_t offset;
259 uint8_t c;
260
261 if ((offset = tp->offset) != 0) {
262 while ((c = GETBIOS8(sc, offset + 1)) != 0) {
263 if (c & 0x40)
264 offset += 10;
265 else if (c & 0x80)
266 offset += 4;
267 else
268 offset += 6;
269 }
270 return offset + 2;
271 }
272 return 0;
273 }
274
275 uint16_t
276 rb_find_mem_reset_table(struct radeonfb_softc *sc, struct rb_table *tp)
277 {
278 uint16_t offset;
279
280 if ((offset = tp->offset) != 0) {
281 while (GETBIOS8(sc, offset))
282 offset++;
283 offset++;
284 return offset + 2; /* skip table revision and mask */
285 }
286 return 0;
287 }
288
289 uint16_t
290 rb_find_short_mem_reset_table(struct radeonfb_softc *sc, struct rb_table *tp)
291 {
292
293 if ((tp->offset != 0) && (GETBIOS8(sc, tp->offset - 2) <= 64))
294 return (tp->offset + GETBIOS8(sc, tp->offset - 3));
295
296 return 0;
297 }
298
299 /* helper commands */
300 void
301 rb_wait_mc_busy_mask(struct radeonfb_softc *sc, uint16_t count)
302 {
303 DPRINTF(("WAIT_MC_BUSY_MASK: %d ", count));
304 while (count--) {
305 if (!(radeonfb_getpll(sc, RADEON_CLK_PWRMGT_CNTL) &
306 RADEON_MC_BUSY_MASK))
307 break;
308 }
309 DPRINTF(("%d\n", count));
310 }
311
312 void
313 rb_wait_mem_pwrup_complete(struct radeonfb_softc *sc, uint16_t count)
314 {
315 DPRINTF(("WAIT_MEM_PWRUP_COMPLETE: %d ", count));
316 while (count--) {
317 if ((radeonfb_getindex(sc, RADEON_MEM_STR_CNTL) &
318 RADEON_MEM_PWRUP_COMPLETE) ==
319 RADEON_MEM_PWRUP_COMPLETE)
320 break;
321 }
322 DPRINTF(("%d\n", count));
323 }
324
325 void
326 rb_wait_dll_ready_mask(struct radeonfb_softc *sc, uint16_t count)
327 {
328 DPRINTF(("WAIT_DLL_READY_MASK: %d ", count));
329 while (count--) {
330 if (radeonfb_getpll(sc, RADEON_CLK_PWRMGT_CNTL) &
331 RADEON_DLL_READY_MASK)
332 break;
333 }
334 DPRINTF(("%d\n", count));
335 }
336
337 void
338 rb_wait_chk_set_clk_pwrmgt_cntl24(struct radeonfb_softc *sc)
339 {
340 uint32_t pmc;
341 DPRINTF(("WAIT CHK_SET_CLK_PWRMGT_CNTL24\n"));
342 pmc = radeonfb_getpll(sc, RADEON_CLK_PWRMGT_CNTL);
343
344 if (pmc & RADEON_CLK_PWRMGT_CNTL24) {
345 radeonfb_maskpll(sc, RADEON_MCLK_CNTL, 0xFFFF0000,
346 RADEON_SET_ALL_SRCS_TO_PCI);
347 delay(10000);
348 radeonfb_putpll(sc, RADEON_CLK_PWRMGT_CNTL,
349 pmc & ~RADEON_CLK_PWRMGT_CNTL24);
350 delay(10000);
351 }
352 }
353
354 /*
355 * Block initialization routines. These take action based on data in
356 * the tables.
357 */
358 int
359 rb_load_init_block(struct radeonfb_softc *sc, struct rb_table *tp)
360 {
361 uint16_t offset;
362 uint16_t value;
363
364 if ((tp == NULL) || ((offset = tp->offset) == 0))
365 return 1;
366
367 DPRINTF(("%s: load_init_block processing %s\n", XNAME(sc), tp->name));
368 while ((value = GETBIOS16(sc, offset)) != 0) {
369 uint16_t flag = value & TABLE_ENTRY_FLAG_MASK;
370 uint16_t index = value & TABLE_ENTRY_INDEX_MASK;
371 uint8_t command = value & TABLE_ENTRY_COMMAND_MASK;
372 uint32_t ormask;
373 uint32_t andmask;
374 uint16_t count;
375
376 offset += 2;
377
378 switch (flag) {
379 case TABLE_FLAG_WRITE_INDEXED:
380 DPRINTF(("WRITE INDEXED: %x %x\n",
381 index, (uint32_t)GETBIOS32(sc, offset)));
382 radeonfb_putindex(sc, index, GETBIOS32(sc, offset));
383 offset += 4;
384 break;
385
386 case TABLE_FLAG_WRITE_DIRECT:
387 DPRINTF(("WRITE DIRECT: %x %x\n",
388 index, (uint32_t)GETBIOS32(sc, offset)));
389 radeonfb_put32(sc, index, GETBIOS32(sc, offset));
390 offset += 4;
391 break;
392
393 case TABLE_FLAG_MASK_INDEXED:
394 andmask = GETBIOS32(sc, offset);
395 offset += 4;
396 ormask = GETBIOS32(sc, offset);
397 offset += 4;
398 DPRINTF(("MASK INDEXED: %x %x %x\n",
399 index, andmask, ormask));
400 radeonfb_maskindex(sc, index, andmask, ormask);
401 break;
402
403 case TABLE_FLAG_MASK_DIRECT:
404 andmask = GETBIOS32(sc, offset);
405 offset += 4;
406 ormask = GETBIOS32(sc, offset);
407 offset += 4;
408 DPRINTF(("MASK DIRECT: %x %x %x\n",
409 index, andmask, ormask));
410 radeonfb_mask32(sc, index, andmask, ormask);
411 break;
412
413 case TABLE_FLAG_DELAY:
414 /* in the worst case, this would be 16msec */
415 count = GETBIOS16(sc, offset);
416 DPRINTF(("DELAY: %d\n", count));
417 delay(count);
418 offset += 2;
419 break;
420
421 case TABLE_FLAG_SCOMMAND:
422 DPRINTF(("SCOMMAND %x\n", command));
423 switch (command) {
424
425 case TABLE_SCOMMAND_WAIT_MC_BUSY_MASK:
426 count = GETBIOS16(sc, offset);
427 rb_wait_mc_busy_mask(sc, count);
428 break;
429
430 case TABLE_SCOMMAND_WAIT_MEM_PWRUP_COMPLETE:
431 count = GETBIOS16(sc, offset);
432 rb_wait_mem_pwrup_complete(sc, count);
433 break;
434
435 }
436 offset += 2;
437 break;
438 }
439 }
440 return 0;
441 }
442
443 int
444 rb_load_pll_block(struct radeonfb_softc *sc, struct rb_table *tp)
445 {
446 uint16_t offset;
447 uint8_t index;
448 uint8_t shift;
449 uint32_t andmask;
450 uint32_t ormask;
451
452 if ((tp == NULL) || ((offset = tp->offset) == 0))
453 return 1;
454
455 DPRINTF(("%s: load_pll_block processing %s\n", XNAME(sc), tp->name));
456 while ((index = GETBIOS8(sc, offset)) != 0) {
457 offset++;
458
459 switch (index & PLL_FLAG_MASK) {
460 case PLL_FLAG_WAIT:
461 switch (index & PLL_INDEX_MASK) {
462 case PLL_WAIT_150MKS:
463 delay(150);
464 break;
465 case PLL_WAIT_5MS:
466 /* perhaps this should be tsleep? */
467 delay(5000);
468 break;
469
470 case PLL_WAIT_MC_BUSY_MASK:
471 rb_wait_mc_busy_mask(sc, 1000);
472 break;
473
474 case PLL_WAIT_DLL_READY_MASK:
475 rb_wait_dll_ready_mask(sc, 1000);
476 break;
477
478 case PLL_WAIT_CHK_SET_CLK_PWRMGT_CNTL24:
479 rb_wait_chk_set_clk_pwrmgt_cntl24(sc);
480 break;
481 }
482 break;
483
484 case PLL_FLAG_MASK_BYTE:
485 shift = GETBIOS8(sc, offset) * 8;
486 offset++;
487
488 andmask =
489 (((uint32_t)GETBIOS8(sc, offset)) << shift) |
490 ~((uint32_t)0xff << shift);
491 offset++;
492
493 ormask = ((uint32_t)GETBIOS8(sc, offset)) << shift;
494 offset++;
495
496 DPRINTF(("PLL_MASK_BYTE %u %u %x %x\n", index,
497 shift, andmask, ormask));
498 radeonfb_maskpll(sc, index, andmask, ormask);
499 break;
500
501 case PLL_FLAG_WRITE:
502 DPRINTF(("PLL_WRITE %u %x\n", index,
503 GETBIOS32(sc, offset)));
504 radeonfb_putpll(sc, index, GETBIOS32(sc, offset));
505 offset += 4;
506 break;
507 }
508 }
509
510 return 0;
511 }
512
513 int
514 rb_reset_sdram(struct radeonfb_softc *sc, struct rb_table *tp)
515 {
516 uint16_t offset;
517 uint8_t index;
518
519 if ((tp == NULL) || ((offset = tp->offset) == 0))
520 return 1;
521
522 DPRINTF(("%s: reset_sdram processing %s\n", XNAME(sc), tp->name));
523
524 while ((index = GETBIOS8(sc, offset)) != 0xff) {
525 offset++;
526 if (index == 0x0f) {
527 rb_wait_mem_pwrup_complete(sc, 20000);
528 } else {
529 uint32_t ormask;
530
531 ormask = GETBIOS16(sc, offset);
532 offset += 2;
533
534 DPRINTF(("INDEX reg RADEON_MEM_SDRAM_MODE_REG %x %x\n",
535 RADEON_SDRAM_MODE_MASK, ormask));
536 radeonfb_maskindex(sc, RADEON_MEM_SDRAM_MODE_REG,
537 RADEON_SDRAM_MODE_MASK, ormask);
538
539 ormask = (uint32_t)index << 24;
540 DPRINTF(("INDEX reg RADEON_MEM_SDRAM_MODE_REG %x %x\n",
541 RADEON_B3MEM_RESET_MASK, ormask));
542 radeonfb_maskindex(sc, RADEON_MEM_SDRAM_MODE_REG,
543 RADEON_B3MEM_RESET_MASK, ormask);
544 }
545 }
546 return 0;
547 }
548
549 /*
550 * Master entry point to parse and act on table data.
551 */
552 int
553 radeonfb_bios_init(struct radeonfb_softc *sc)
554 {
555 uint16_t revision;
556 uint16_t scratch;
557 int i;
558 struct rb_table *tp;
559
560 if (!sc->sc_biossz)
561 return 1;
562
563 scratch = GETBIOS16(sc, ROM_HEADER_OFFSET);
564 revision = GETBIOS8(sc, scratch);
565 DPRINTF(("%s: Bios Rev: %d\n", XNAME(sc), revision));
566
567
568 /* First parse pass -- locate tables */
569 for (i = 0; (tp = rb_tables[i]) != NULL; i++) {
570
571 DPRINTF(("%s: parsing table %s\n", XNAME(sc), tp->name));
572
573 if (tp->offset != 0) {
574 uint16_t temp, offset;;
575
576 temp = GETBIOS16(sc, ROM_HEADER_OFFSET);
577 offset = GETBIOS16(sc, temp + tp->offset);
578 if (offset)
579 tp->offset = offset;
580
581 } else {
582 tp->offset = tp->find(sc, tp->parent);
583 }
584
585 if (tp->validate)
586 tp->validate(sc, tp);
587
588 if (revision > SINGLE_TABLE_REVISION)
589 break;
590 }
591
592 if (rb_rage_regs3_table.offset + 1 == rb_pll_init_table.offset) {
593 rb_rage_regs3_table.offset = 0;
594 rb_rage_regs4_table.offset = 0;
595 }
596
597 if (rb_rage_regs1_table.offset)
598 rb_load_init_block(sc, &rb_rage_regs1_table);
599
600 if (revision < SINGLE_TABLE_REVISION) {
601 if (rb_pll_init_table.offset)
602 rb_load_pll_block(sc, &rb_pll_init_table);
603 if (rb_rage_regs2_table.offset)
604 rb_load_init_block(sc, &rb_rage_regs2_table);
605 if (rb_rage_regs4_table.offset)
606 rb_load_init_block(sc, &rb_rage_regs4_table);
607 if (rb_mem_reset_table.offset)
608 rb_reset_sdram(sc, &rb_mem_reset_table);
609 if (rb_rage_regs3_table.offset)
610 rb_load_init_block(sc, &rb_rage_regs3_table);
611 if (rb_dyn_clock_table.offset)
612 rb_load_pll_block(sc, &rb_dyn_clock_table);
613 }
614
615 DPRINTF(("%s: BIOS parse done\n", XNAME(sc)));
616 return 0;
617 }
618
619 #endif
620