1 /* $NetBSD: radeonfb_bios.c,v 1.3 2009/01/03 03:43:22 yamt 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.3 2009/01/03 03:43:22 yamt 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