1 /* 2 * Copyright 2012 Red Hat Inc. 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the 6 * "Software"), to deal in the Software without restriction, including 7 * without limitation the rights to use, copy, modify, merge, publish, 8 * distribute, sub license, and/or sell copies of the Software, and to 9 * permit persons to whom the Software is furnished to do so, subject to 10 * the following conditions: 11 * 12 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 13 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 14 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 15 * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, 16 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 17 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 18 * USE OR OTHER DEALINGS IN THE SOFTWARE. 19 * 20 * The above copyright notice and this permission notice (including the 21 * next paragraph) shall be included in all copies or substantial portions 22 * of the Software. 23 * 24 */ 25 /* 26 * Authors: Dave Airlie <airlied@redhat.com> 27 */ 28 29 #include <drm/drmP.h> 30 #include "ast_drv.h" 31 32 #include "ast_dram_tables.h" 33 34 static void ast_init_dram_2300(struct drm_device *dev); 35 36 static void 37 ast_enable_vga(struct drm_device *dev) 38 { 39 struct ast_private *ast = dev->dev_private; 40 41 ast_io_write8(ast, 0x43, 0x01); 42 ast_io_write8(ast, 0x42, 0x01); 43 } 44 45 #if 0 /* will use later */ 46 static bool 47 ast_is_vga_enabled(struct drm_device *dev) 48 { 49 struct ast_private *ast = dev->dev_private; 50 u8 ch; 51 52 if (ast->chip == AST1180) { 53 /* TODO 1180 */ 54 } else { 55 ch = ast_io_read8(ast, 0x43); 56 if (ch) { 57 ast_open_key(ast); 58 ch = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb6, 0xff); 59 return ch & 0x04; 60 } 61 } 62 return 0; 63 } 64 #endif 65 66 static const u8 extreginfo[] = { 0x0f, 0x04, 0x1c, 0xff }; 67 static const u8 extreginfo_ast2300a0[] = { 0x0f, 0x04, 0x1c, 0xff }; 68 static const u8 extreginfo_ast2300[] = { 0x0f, 0x04, 0x1f, 0xff }; 69 70 static void 71 ast_set_def_ext_reg(struct drm_device *dev) 72 { 73 struct ast_private *ast = dev->dev_private; 74 u8 i, index, reg; 75 const u8 *ext_reg_info; 76 77 /* reset scratch */ 78 for (i = 0x81; i <= 0x8f; i++) 79 ast_set_index_reg(ast, AST_IO_CRTC_PORT, i, 0x00); 80 81 if (ast->chip == AST2300) { 82 if (dev->pdev->revision >= 0x20) 83 ext_reg_info = extreginfo_ast2300; 84 else 85 ext_reg_info = extreginfo_ast2300a0; 86 } else 87 ext_reg_info = extreginfo; 88 89 index = 0xa0; 90 while (*ext_reg_info != 0xff) { 91 ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, index, 0x00, *ext_reg_info); 92 index++; 93 ext_reg_info++; 94 } 95 96 /* disable standard IO/MEM decode if secondary */ 97 /* ast_set_index_reg-mask(ast, AST_IO_CRTC_PORT, 0xa1, 0xff, 0x3); */ 98 99 /* Set Ext. Default */ 100 ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x8c, 0x00, 0x01); 101 ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, 0x00, 0x00); 102 103 /* Enable RAMDAC for A1 */ 104 reg = 0x04; 105 if (ast->chip == AST2300) 106 reg |= 0x20; 107 ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb6, 0xff, reg); 108 } 109 110 static inline u32 mindwm(struct ast_private *ast, u32 r) 111 { 112 ast_write32(ast, 0xf004, r & 0xffff0000); 113 ast_write32(ast, 0xf000, 0x1); 114 115 return ast_read32(ast, 0x10000 + (r & 0x0000ffff)); 116 } 117 118 static inline void moutdwm(struct ast_private *ast, u32 r, u32 v) 119 { 120 ast_write32(ast, 0xf004, r & 0xffff0000); 121 ast_write32(ast, 0xf000, 0x1); 122 ast_write32(ast, 0x10000 + (r & 0x0000ffff), v); 123 } 124 125 /* 126 * AST2100/2150 DLL CBR Setting 127 */ 128 #define CBR_SIZE_AST2150 ((16 << 10) - 1) 129 #define CBR_PASSNUM_AST2150 5 130 #define CBR_THRESHOLD_AST2150 10 131 #define CBR_THRESHOLD2_AST2150 10 132 #define TIMEOUT_AST2150 5000000 133 134 #define CBR_PATNUM_AST2150 8 135 136 static const u32 pattern_AST2150[14] = { 137 0xFF00FF00, 138 0xCC33CC33, 139 0xAA55AA55, 140 0xFFFE0001, 141 0x683501FE, 142 0x0F1929B0, 143 0x2D0B4346, 144 0x60767F02, 145 0x6FBE36A6, 146 0x3A253035, 147 0x3019686D, 148 0x41C6167E, 149 0x620152BF, 150 0x20F050E0 151 }; 152 153 static u32 mmctestburst2_ast2150(struct ast_private *ast, u32 datagen) 154 { 155 u32 data, timeout; 156 157 moutdwm(ast, 0x1e6e0070, 0x00000000); 158 moutdwm(ast, 0x1e6e0070, 0x00000001 | (datagen << 3)); 159 timeout = 0; 160 do { 161 data = mindwm(ast, 0x1e6e0070) & 0x40; 162 if (++timeout > TIMEOUT_AST2150) { 163 moutdwm(ast, 0x1e6e0070, 0x00000000); 164 return 0xffffffff; 165 } 166 } while (!data); 167 moutdwm(ast, 0x1e6e0070, 0x00000000); 168 moutdwm(ast, 0x1e6e0070, 0x00000003 | (datagen << 3)); 169 timeout = 0; 170 do { 171 data = mindwm(ast, 0x1e6e0070) & 0x40; 172 if (++timeout > TIMEOUT_AST2150) { 173 moutdwm(ast, 0x1e6e0070, 0x00000000); 174 return 0xffffffff; 175 } 176 } while (!data); 177 data = (mindwm(ast, 0x1e6e0070) & 0x80) >> 7; 178 moutdwm(ast, 0x1e6e0070, 0x00000000); 179 return data; 180 } 181 182 #if 0 /* unused in DDX driver - here for completeness */ 183 static u32 mmctestsingle2_ast2150(struct ast_private *ast, u32 datagen) 184 { 185 u32 data, timeout; 186 187 moutdwm(ast, 0x1e6e0070, 0x00000000); 188 moutdwm(ast, 0x1e6e0070, 0x00000005 | (datagen << 3)); 189 timeout = 0; 190 do { 191 data = mindwm(ast, 0x1e6e0070) & 0x40; 192 if (++timeout > TIMEOUT_AST2150) { 193 moutdwm(ast, 0x1e6e0070, 0x00000000); 194 return 0xffffffff; 195 } 196 } while (!data); 197 data = (mindwm(ast, 0x1e6e0070) & 0x80) >> 7; 198 moutdwm(ast, 0x1e6e0070, 0x00000000); 199 return data; 200 } 201 #endif 202 203 static int cbrtest_ast2150(struct ast_private *ast) 204 { 205 int i; 206 207 for (i = 0; i < 8; i++) 208 if (mmctestburst2_ast2150(ast, i)) 209 return 0; 210 return 1; 211 } 212 213 static int cbrscan_ast2150(struct ast_private *ast, int busw) 214 { 215 u32 patcnt, loop; 216 217 for (patcnt = 0; patcnt < CBR_PATNUM_AST2150; patcnt++) { 218 moutdwm(ast, 0x1e6e007c, pattern_AST2150[patcnt]); 219 for (loop = 0; loop < CBR_PASSNUM_AST2150; loop++) { 220 if (cbrtest_ast2150(ast)) 221 break; 222 } 223 if (loop == CBR_PASSNUM_AST2150) 224 return 0; 225 } 226 return 1; 227 } 228 229 230 static void cbrdlli_ast2150(struct ast_private *ast, int busw) 231 { 232 u32 dll_min[4], dll_max[4], dlli, data, passcnt; 233 234 cbr_start: 235 dll_min[0] = dll_min[1] = dll_min[2] = dll_min[3] = 0xff; 236 dll_max[0] = dll_max[1] = dll_max[2] = dll_max[3] = 0x0; 237 passcnt = 0; 238 239 for (dlli = 0; dlli < 100; dlli++) { 240 moutdwm(ast, 0x1e6e0068, dlli | (dlli << 8) | (dlli << 16) | (dlli << 24)); 241 data = cbrscan_ast2150(ast, busw); 242 if (data != 0) { 243 if (data & 0x1) { 244 if (dll_min[0] > dlli) 245 dll_min[0] = dlli; 246 if (dll_max[0] < dlli) 247 dll_max[0] = dlli; 248 } 249 passcnt++; 250 } else if (passcnt >= CBR_THRESHOLD_AST2150) 251 goto cbr_start; 252 } 253 if (dll_max[0] == 0 || (dll_max[0]-dll_min[0]) < CBR_THRESHOLD_AST2150) 254 goto cbr_start; 255 256 dlli = dll_min[0] + (((dll_max[0] - dll_min[0]) * 7) >> 4); 257 moutdwm(ast, 0x1e6e0068, dlli | (dlli << 8) | (dlli << 16) | (dlli << 24)); 258 } 259 260 261 262 static void ast_init_dram_reg(struct drm_device *dev) 263 { 264 struct ast_private *ast = dev->dev_private; 265 u8 j; 266 u32 data, temp, i; 267 const struct ast_dramstruct *dram_reg_info; 268 269 j = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xd0, 0xff); 270 271 if ((j & 0x80) == 0) { /* VGA only */ 272 if (ast->chip == AST2000) { 273 dram_reg_info = ast2000_dram_table_data; 274 ast_write32(ast, 0xf004, 0x1e6e0000); 275 ast_write32(ast, 0xf000, 0x1); 276 ast_write32(ast, 0x10100, 0xa8); 277 278 do { 279 ; 280 } while (ast_read32(ast, 0x10100) != 0xa8); 281 } else {/* AST2100/1100 */ 282 if (ast->chip == AST2100 || ast->chip == 2200) 283 dram_reg_info = ast2100_dram_table_data; 284 else 285 dram_reg_info = ast1100_dram_table_data; 286 287 ast_write32(ast, 0xf004, 0x1e6e0000); 288 ast_write32(ast, 0xf000, 0x1); 289 ast_write32(ast, 0x12000, 0x1688A8A8); 290 do { 291 ; 292 } while (ast_read32(ast, 0x12000) != 0x01); 293 294 ast_write32(ast, 0x10000, 0xfc600309); 295 do { 296 ; 297 } while (ast_read32(ast, 0x10000) != 0x01); 298 } 299 300 while (dram_reg_info->index != 0xffff) { 301 if (dram_reg_info->index == 0xff00) {/* delay fn */ 302 for (i = 0; i < 15; i++) 303 udelay(dram_reg_info->data); 304 } else if (dram_reg_info->index == 0x4 && ast->chip != AST2000) { 305 data = dram_reg_info->data; 306 if (ast->dram_type == AST_DRAM_1Gx16) 307 data = 0x00000d89; 308 else if (ast->dram_type == AST_DRAM_1Gx32) 309 data = 0x00000c8d; 310 311 temp = ast_read32(ast, 0x12070); 312 temp &= 0xc; 313 temp <<= 2; 314 ast_write32(ast, 0x10000 + dram_reg_info->index, data | temp); 315 } else 316 ast_write32(ast, 0x10000 + dram_reg_info->index, dram_reg_info->data); 317 dram_reg_info++; 318 } 319 320 /* AST 2100/2150 DRAM calibration */ 321 data = ast_read32(ast, 0x10120); 322 if (data == 0x5061) { /* 266Mhz */ 323 data = ast_read32(ast, 0x10004); 324 if (data & 0x40) 325 cbrdlli_ast2150(ast, 16); /* 16 bits */ 326 else 327 cbrdlli_ast2150(ast, 32); /* 32 bits */ 328 } 329 330 switch (ast->chip) { 331 case AST2000: 332 temp = ast_read32(ast, 0x10140); 333 ast_write32(ast, 0x10140, temp | 0x40); 334 break; 335 case AST1100: 336 case AST2100: 337 case AST2200: 338 case AST2150: 339 temp = ast_read32(ast, 0x1200c); 340 ast_write32(ast, 0x1200c, temp & 0xfffffffd); 341 temp = ast_read32(ast, 0x12040); 342 ast_write32(ast, 0x12040, temp | 0x40); 343 break; 344 default: 345 break; 346 } 347 } 348 349 /* wait ready */ 350 do { 351 j = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xd0, 0xff); 352 } while ((j & 0x40) == 0); 353 } 354 355 void ast_post_gpu(struct drm_device *dev) 356 { 357 u32 reg; 358 struct ast_private *ast = dev->dev_private; 359 360 pci_read_config_dword(ast->dev->pdev, 0x04, ®); 361 reg |= 0x3; 362 pci_write_config_dword(ast->dev->pdev, 0x04, reg); 363 364 ast_enable_vga(dev); 365 ast_open_key(ast); 366 ast_set_def_ext_reg(dev); 367 368 if (ast->chip == AST2300) 369 ast_init_dram_2300(dev); 370 else 371 ast_init_dram_reg(dev); 372 } 373 374 /* AST 2300 DRAM settings */ 375 #define AST_DDR3 0 376 #define AST_DDR2 1 377 378 struct ast2300_dram_param { 379 u32 dram_type; 380 u32 dram_chipid; 381 u32 dram_freq; 382 u32 vram_size; 383 u32 odt; 384 u32 wodt; 385 u32 rodt; 386 u32 dram_config; 387 u32 reg_PERIOD; 388 u32 reg_MADJ; 389 u32 reg_SADJ; 390 u32 reg_MRS; 391 u32 reg_EMRS; 392 u32 reg_AC1; 393 u32 reg_AC2; 394 u32 reg_DQSIC; 395 u32 reg_DRV; 396 u32 reg_IOZ; 397 u32 reg_DQIDLY; 398 u32 reg_FREQ; 399 u32 madj_max; 400 u32 dll2_finetune_step; 401 }; 402 403 /* 404 * DQSI DLL CBR Setting 405 */ 406 #define CBR_SIZE1 ((4 << 10) - 1) 407 #define CBR_SIZE2 ((64 << 10) - 1) 408 #define CBR_PASSNUM 5 409 #define CBR_PASSNUM2 5 410 #define CBR_THRESHOLD 10 411 #define CBR_THRESHOLD2 10 412 #define TIMEOUT 5000000 413 #define CBR_PATNUM 8 414 415 static const u32 pattern[8] = { 416 0xFF00FF00, 417 0xCC33CC33, 418 0xAA55AA55, 419 0x88778877, 420 0x92CC4D6E, 421 0x543D3CDE, 422 0xF1E843C7, 423 0x7C61D253 424 }; 425 426 #if 0 /* unused in DDX, included for completeness */ 427 static int mmc_test_burst(struct ast_private *ast, u32 datagen) 428 { 429 u32 data, timeout; 430 431 moutdwm(ast, 0x1e6e0070, 0x00000000); 432 moutdwm(ast, 0x1e6e0070, 0x000000c1 | (datagen << 3)); 433 timeout = 0; 434 do { 435 data = mindwm(ast, 0x1e6e0070) & 0x3000; 436 if (data & 0x2000) { 437 return 0; 438 } 439 if (++timeout > TIMEOUT) { 440 moutdwm(ast, 0x1e6e0070, 0x00000000); 441 return 0; 442 } 443 } while (!data); 444 moutdwm(ast, 0x1e6e0070, 0x00000000); 445 return 1; 446 } 447 #endif 448 449 static int mmc_test_burst2(struct ast_private *ast, u32 datagen) 450 { 451 u32 data, timeout; 452 453 moutdwm(ast, 0x1e6e0070, 0x00000000); 454 moutdwm(ast, 0x1e6e0070, 0x00000041 | (datagen << 3)); 455 timeout = 0; 456 do { 457 data = mindwm(ast, 0x1e6e0070) & 0x1000; 458 if (++timeout > TIMEOUT) { 459 moutdwm(ast, 0x1e6e0070, 0x0); 460 return -1; 461 } 462 } while (!data); 463 data = mindwm(ast, 0x1e6e0078); 464 data = (data | (data >> 16)) & 0xffff; 465 moutdwm(ast, 0x1e6e0070, 0x0); 466 return data; 467 } 468 469 #if 0 /* Unused in DDX here for completeness */ 470 static int mmc_test_single(struct ast_private *ast, u32 datagen) 471 { 472 u32 data, timeout; 473 474 moutdwm(ast, 0x1e6e0070, 0x00000000); 475 moutdwm(ast, 0x1e6e0070, 0x000000c5 | (datagen << 3)); 476 timeout = 0; 477 do { 478 data = mindwm(ast, 0x1e6e0070) & 0x3000; 479 if (data & 0x2000) 480 return 0; 481 if (++timeout > TIMEOUT) { 482 moutdwm(ast, 0x1e6e0070, 0x0); 483 return 0; 484 } 485 } while (!data); 486 moutdwm(ast, 0x1e6e0070, 0x0); 487 return 1; 488 } 489 #endif 490 491 static int mmc_test_single2(struct ast_private *ast, u32 datagen) 492 { 493 u32 data, timeout; 494 495 moutdwm(ast, 0x1e6e0070, 0x00000000); 496 moutdwm(ast, 0x1e6e0070, 0x00000005 | (datagen << 3)); 497 timeout = 0; 498 do { 499 data = mindwm(ast, 0x1e6e0070) & 0x1000; 500 if (++timeout > TIMEOUT) { 501 moutdwm(ast, 0x1e6e0070, 0x0); 502 return -1; 503 } 504 } while (!data); 505 data = mindwm(ast, 0x1e6e0078); 506 data = (data | (data >> 16)) & 0xffff; 507 moutdwm(ast, 0x1e6e0070, 0x0); 508 return data; 509 } 510 511 static int cbr_test(struct ast_private *ast) 512 { 513 u32 data; 514 int i; 515 data = mmc_test_single2(ast, 0); 516 if ((data & 0xff) && (data & 0xff00)) 517 return 0; 518 for (i = 0; i < 8; i++) { 519 data = mmc_test_burst2(ast, i); 520 if ((data & 0xff) && (data & 0xff00)) 521 return 0; 522 } 523 if (!data) 524 return 3; 525 else if (data & 0xff) 526 return 2; 527 return 1; 528 } 529 530 static int cbr_scan(struct ast_private *ast) 531 { 532 u32 data, data2, patcnt, loop; 533 534 data2 = 3; 535 for (patcnt = 0; patcnt < CBR_PATNUM; patcnt++) { 536 moutdwm(ast, 0x1e6e007c, pattern[patcnt]); 537 for (loop = 0; loop < CBR_PASSNUM2; loop++) { 538 if ((data = cbr_test(ast)) != 0) { 539 data2 &= data; 540 if (!data2) 541 return 0; 542 break; 543 } 544 } 545 if (loop == CBR_PASSNUM2) 546 return 0; 547 } 548 return data2; 549 } 550 551 static u32 cbr_test2(struct ast_private *ast) 552 { 553 u32 data; 554 555 data = mmc_test_burst2(ast, 0); 556 if (data == 0xffff) 557 return 0; 558 data |= mmc_test_single2(ast, 0); 559 if (data == 0xffff) 560 return 0; 561 562 return ~data & 0xffff; 563 } 564 565 static u32 cbr_scan2(struct ast_private *ast) 566 { 567 u32 data, data2, patcnt, loop; 568 569 data2 = 0xffff; 570 for (patcnt = 0; patcnt < CBR_PATNUM; patcnt++) { 571 moutdwm(ast, 0x1e6e007c, pattern[patcnt]); 572 for (loop = 0; loop < CBR_PASSNUM2; loop++) { 573 if ((data = cbr_test2(ast)) != 0) { 574 data2 &= data; 575 if (!data) 576 return 0; 577 break; 578 } 579 } 580 if (loop == CBR_PASSNUM2) 581 return 0; 582 } 583 return data2; 584 } 585 586 #if 0 /* unused in DDX - added for completeness */ 587 static void finetuneDQI(struct ast_private *ast, struct ast2300_dram_param *param) 588 { 589 u32 gold_sadj[2], dllmin[16], dllmax[16], dlli, data, cnt, mask, passcnt; 590 591 gold_sadj[0] = (mindwm(ast, 0x1E6E0024) >> 16) & 0xffff; 592 gold_sadj[1] = gold_sadj[0] >> 8; 593 gold_sadj[0] = gold_sadj[0] & 0xff; 594 gold_sadj[0] = (gold_sadj[0] + gold_sadj[1]) >> 1; 595 gold_sadj[1] = gold_sadj[0]; 596 597 for (cnt = 0; cnt < 16; cnt++) { 598 dllmin[cnt] = 0xff; 599 dllmax[cnt] = 0x0; 600 } 601 passcnt = 0; 602 for (dlli = 0; dlli < 76; dlli++) { 603 moutdwm(ast, 0x1E6E0068, 0x00001400 | (dlli << 16) | (dlli << 24)); 604 /* Wait DQSI latch phase calibration */ 605 moutdwm(ast, 0x1E6E0074, 0x00000010); 606 moutdwm(ast, 0x1E6E0070, 0x00000003); 607 do { 608 data = mindwm(ast, 0x1E6E0070); 609 } while (!(data & 0x00001000)); 610 moutdwm(ast, 0x1E6E0070, 0x00000000); 611 612 moutdwm(ast, 0x1E6E0074, CBR_SIZE1); 613 data = cbr_scan2(ast); 614 if (data != 0) { 615 mask = 0x00010001; 616 for (cnt = 0; cnt < 16; cnt++) { 617 if (data & mask) { 618 if (dllmin[cnt] > dlli) { 619 dllmin[cnt] = dlli; 620 } 621 if (dllmax[cnt] < dlli) { 622 dllmax[cnt] = dlli; 623 } 624 } 625 mask <<= 1; 626 } 627 passcnt++; 628 } else if (passcnt >= CBR_THRESHOLD) { 629 break; 630 } 631 } 632 data = 0; 633 for (cnt = 0; cnt < 8; cnt++) { 634 data >>= 3; 635 if ((dllmax[cnt] > dllmin[cnt]) && ((dllmax[cnt] - dllmin[cnt]) >= CBR_THRESHOLD)) { 636 dlli = (dllmin[cnt] + dllmax[cnt]) >> 1; 637 if (gold_sadj[0] >= dlli) { 638 dlli = (gold_sadj[0] - dlli) >> 1; 639 if (dlli > 3) { 640 dlli = 3; 641 } 642 } else { 643 dlli = (dlli - gold_sadj[0]) >> 1; 644 if (dlli > 4) { 645 dlli = 4; 646 } 647 dlli = (8 - dlli) & 0x7; 648 } 649 data |= dlli << 21; 650 } 651 } 652 moutdwm(ast, 0x1E6E0080, data); 653 654 data = 0; 655 for (cnt = 8; cnt < 16; cnt++) { 656 data >>= 3; 657 if ((dllmax[cnt] > dllmin[cnt]) && ((dllmax[cnt] - dllmin[cnt]) >= CBR_THRESHOLD)) { 658 dlli = (dllmin[cnt] + dllmax[cnt]) >> 1; 659 if (gold_sadj[1] >= dlli) { 660 dlli = (gold_sadj[1] - dlli) >> 1; 661 if (dlli > 3) { 662 dlli = 3; 663 } else { 664 dlli = (dlli - 1) & 0x7; 665 } 666 } else { 667 dlli = (dlli - gold_sadj[1]) >> 1; 668 dlli += 1; 669 if (dlli > 4) { 670 dlli = 4; 671 } 672 dlli = (8 - dlli) & 0x7; 673 } 674 data |= dlli << 21; 675 } 676 } 677 moutdwm(ast, 0x1E6E0084, data); 678 679 } /* finetuneDQI */ 680 #endif 681 682 static void finetuneDQI_L(struct ast_private *ast, struct ast2300_dram_param *param) 683 { 684 u32 gold_sadj[2], dllmin[16], dllmax[16], dlli, data, cnt, mask, passcnt; 685 686 FINETUNE_START: 687 for (cnt = 0; cnt < 16; cnt++) { 688 dllmin[cnt] = 0xff; 689 dllmax[cnt] = 0x0; 690 } 691 passcnt = 0; 692 for (dlli = 0; dlli < 76; dlli++) { 693 moutdwm(ast, 0x1E6E0068, 0x00001400 | (dlli << 16) | (dlli << 24)); 694 /* Wait DQSI latch phase calibration */ 695 moutdwm(ast, 0x1E6E0074, 0x00000010); 696 moutdwm(ast, 0x1E6E0070, 0x00000003); 697 do { 698 data = mindwm(ast, 0x1E6E0070); 699 } while (!(data & 0x00001000)); 700 moutdwm(ast, 0x1E6E0070, 0x00000000); 701 702 moutdwm(ast, 0x1E6E0074, CBR_SIZE1); 703 data = cbr_scan2(ast); 704 if (data != 0) { 705 mask = 0x00010001; 706 for (cnt = 0; cnt < 16; cnt++) { 707 if (data & mask) { 708 if (dllmin[cnt] > dlli) { 709 dllmin[cnt] = dlli; 710 } 711 if (dllmax[cnt] < dlli) { 712 dllmax[cnt] = dlli; 713 } 714 } 715 mask <<= 1; 716 } 717 passcnt++; 718 } else if (passcnt >= CBR_THRESHOLD2) { 719 break; 720 } 721 } 722 gold_sadj[0] = 0x0; 723 passcnt = 0; 724 for (cnt = 0; cnt < 16; cnt++) { 725 if ((dllmax[cnt] > dllmin[cnt]) && ((dllmax[cnt] - dllmin[cnt]) >= CBR_THRESHOLD2)) { 726 gold_sadj[0] += dllmin[cnt]; 727 passcnt++; 728 } 729 } 730 if (passcnt != 16) { 731 goto FINETUNE_START; 732 } 733 gold_sadj[0] = gold_sadj[0] >> 4; 734 gold_sadj[1] = gold_sadj[0]; 735 736 data = 0; 737 for (cnt = 0; cnt < 8; cnt++) { 738 data >>= 3; 739 if ((dllmax[cnt] > dllmin[cnt]) && ((dllmax[cnt] - dllmin[cnt]) >= CBR_THRESHOLD2)) { 740 dlli = dllmin[cnt]; 741 if (gold_sadj[0] >= dlli) { 742 dlli = ((gold_sadj[0] - dlli) * 19) >> 5; 743 if (dlli > 3) { 744 dlli = 3; 745 } 746 } else { 747 dlli = ((dlli - gold_sadj[0]) * 19) >> 5; 748 if (dlli > 4) { 749 dlli = 4; 750 } 751 dlli = (8 - dlli) & 0x7; 752 } 753 data |= dlli << 21; 754 } 755 } 756 moutdwm(ast, 0x1E6E0080, data); 757 758 data = 0; 759 for (cnt = 8; cnt < 16; cnt++) { 760 data >>= 3; 761 if ((dllmax[cnt] > dllmin[cnt]) && ((dllmax[cnt] - dllmin[cnt]) >= CBR_THRESHOLD2)) { 762 dlli = dllmin[cnt]; 763 if (gold_sadj[1] >= dlli) { 764 dlli = ((gold_sadj[1] - dlli) * 19) >> 5; 765 if (dlli > 3) { 766 dlli = 3; 767 } else { 768 dlli = (dlli - 1) & 0x7; 769 } 770 } else { 771 dlli = ((dlli - gold_sadj[1]) * 19) >> 5; 772 dlli += 1; 773 if (dlli > 4) { 774 dlli = 4; 775 } 776 dlli = (8 - dlli) & 0x7; 777 } 778 data |= dlli << 21; 779 } 780 } 781 moutdwm(ast, 0x1E6E0084, data); 782 783 } /* finetuneDQI_L */ 784 785 static void finetuneDQI_L2(struct ast_private *ast, struct ast2300_dram_param *param) 786 { 787 u32 gold_sadj[2], dllmin[16], dllmax[16], dlli, data, cnt, mask, passcnt, data2; 788 789 for (cnt = 0; cnt < 16; cnt++) { 790 dllmin[cnt] = 0xff; 791 dllmax[cnt] = 0x0; 792 } 793 passcnt = 0; 794 for (dlli = 0; dlli < 76; dlli++) { 795 moutdwm(ast, 0x1E6E0068, 0x00001400 | (dlli << 16) | (dlli << 24)); 796 /* Wait DQSI latch phase calibration */ 797 moutdwm(ast, 0x1E6E0074, 0x00000010); 798 moutdwm(ast, 0x1E6E0070, 0x00000003); 799 do { 800 data = mindwm(ast, 0x1E6E0070); 801 } while (!(data & 0x00001000)); 802 moutdwm(ast, 0x1E6E0070, 0x00000000); 803 804 moutdwm(ast, 0x1E6E0074, CBR_SIZE2); 805 data = cbr_scan2(ast); 806 if (data != 0) { 807 mask = 0x00010001; 808 for (cnt = 0; cnt < 16; cnt++) { 809 if (data & mask) { 810 if (dllmin[cnt] > dlli) { 811 dllmin[cnt] = dlli; 812 } 813 if (dllmax[cnt] < dlli) { 814 dllmax[cnt] = dlli; 815 } 816 } 817 mask <<= 1; 818 } 819 passcnt++; 820 } else if (passcnt >= CBR_THRESHOLD2) { 821 break; 822 } 823 } 824 gold_sadj[0] = 0x0; 825 gold_sadj[1] = 0xFF; 826 for (cnt = 0; cnt < 8; cnt++) { 827 if ((dllmax[cnt] > dllmin[cnt]) && ((dllmax[cnt] - dllmin[cnt]) >= CBR_THRESHOLD2)) { 828 if (gold_sadj[0] < dllmin[cnt]) { 829 gold_sadj[0] = dllmin[cnt]; 830 } 831 if (gold_sadj[1] > dllmax[cnt]) { 832 gold_sadj[1] = dllmax[cnt]; 833 } 834 } 835 } 836 gold_sadj[0] = (gold_sadj[1] + gold_sadj[0]) >> 1; 837 gold_sadj[1] = mindwm(ast, 0x1E6E0080); 838 839 data = 0; 840 for (cnt = 0; cnt < 8; cnt++) { 841 data >>= 3; 842 data2 = gold_sadj[1] & 0x7; 843 gold_sadj[1] >>= 3; 844 if ((dllmax[cnt] > dllmin[cnt]) && ((dllmax[cnt] - dllmin[cnt]) >= CBR_THRESHOLD2)) { 845 dlli = (dllmin[cnt] + dllmax[cnt]) >> 1; 846 if (gold_sadj[0] >= dlli) { 847 dlli = (gold_sadj[0] - dlli) >> 1; 848 if (dlli > 0) { 849 dlli = 1; 850 } 851 if (data2 != 3) { 852 data2 = (data2 + dlli) & 0x7; 853 } 854 } else { 855 dlli = (dlli - gold_sadj[0]) >> 1; 856 if (dlli > 0) { 857 dlli = 1; 858 } 859 if (data2 != 4) { 860 data2 = (data2 - dlli) & 0x7; 861 } 862 } 863 } 864 data |= data2 << 21; 865 } 866 moutdwm(ast, 0x1E6E0080, data); 867 868 gold_sadj[0] = 0x0; 869 gold_sadj[1] = 0xFF; 870 for (cnt = 8; cnt < 16; cnt++) { 871 if ((dllmax[cnt] > dllmin[cnt]) && ((dllmax[cnt] - dllmin[cnt]) >= CBR_THRESHOLD2)) { 872 if (gold_sadj[0] < dllmin[cnt]) { 873 gold_sadj[0] = dllmin[cnt]; 874 } 875 if (gold_sadj[1] > dllmax[cnt]) { 876 gold_sadj[1] = dllmax[cnt]; 877 } 878 } 879 } 880 gold_sadj[0] = (gold_sadj[1] + gold_sadj[0]) >> 1; 881 gold_sadj[1] = mindwm(ast, 0x1E6E0084); 882 883 data = 0; 884 for (cnt = 8; cnt < 16; cnt++) { 885 data >>= 3; 886 data2 = gold_sadj[1] & 0x7; 887 gold_sadj[1] >>= 3; 888 if ((dllmax[cnt] > dllmin[cnt]) && ((dllmax[cnt] - dllmin[cnt]) >= CBR_THRESHOLD2)) { 889 dlli = (dllmin[cnt] + dllmax[cnt]) >> 1; 890 if (gold_sadj[0] >= dlli) { 891 dlli = (gold_sadj[0] - dlli) >> 1; 892 if (dlli > 0) { 893 dlli = 1; 894 } 895 if (data2 != 3) { 896 data2 = (data2 + dlli) & 0x7; 897 } 898 } else { 899 dlli = (dlli - gold_sadj[0]) >> 1; 900 if (dlli > 0) { 901 dlli = 1; 902 } 903 if (data2 != 4) { 904 data2 = (data2 - dlli) & 0x7; 905 } 906 } 907 } 908 data |= data2 << 21; 909 } 910 moutdwm(ast, 0x1E6E0084, data); 911 912 } /* finetuneDQI_L2 */ 913 914 static void cbr_dll2(struct ast_private *ast, struct ast2300_dram_param *param) 915 { 916 u32 dllmin[2], dllmax[2], dlli, data, data2, passcnt; 917 918 919 finetuneDQI_L(ast, param); 920 finetuneDQI_L2(ast, param); 921 922 CBR_START2: 923 dllmin[0] = dllmin[1] = 0xff; 924 dllmax[0] = dllmax[1] = 0x0; 925 passcnt = 0; 926 for (dlli = 0; dlli < 76; dlli++) { 927 moutdwm(ast, 0x1E6E0068, 0x00001300 | (dlli << 16) | (dlli << 24)); 928 /* Wait DQSI latch phase calibration */ 929 moutdwm(ast, 0x1E6E0074, 0x00000010); 930 moutdwm(ast, 0x1E6E0070, 0x00000003); 931 do { 932 data = mindwm(ast, 0x1E6E0070); 933 } while (!(data & 0x00001000)); 934 moutdwm(ast, 0x1E6E0070, 0x00000000); 935 936 moutdwm(ast, 0x1E6E0074, CBR_SIZE2); 937 data = cbr_scan(ast); 938 if (data != 0) { 939 if (data & 0x1) { 940 if (dllmin[0] > dlli) { 941 dllmin[0] = dlli; 942 } 943 if (dllmax[0] < dlli) { 944 dllmax[0] = dlli; 945 } 946 } 947 if (data & 0x2) { 948 if (dllmin[1] > dlli) { 949 dllmin[1] = dlli; 950 } 951 if (dllmax[1] < dlli) { 952 dllmax[1] = dlli; 953 } 954 } 955 passcnt++; 956 } else if (passcnt >= CBR_THRESHOLD) { 957 break; 958 } 959 } 960 if (dllmax[0] == 0 || (dllmax[0]-dllmin[0]) < CBR_THRESHOLD) { 961 goto CBR_START2; 962 } 963 if (dllmax[1] == 0 || (dllmax[1]-dllmin[1]) < CBR_THRESHOLD) { 964 goto CBR_START2; 965 } 966 dlli = (dllmin[1] + dllmax[1]) >> 1; 967 dlli <<= 8; 968 dlli += (dllmin[0] + dllmax[0]) >> 1; 969 moutdwm(ast, 0x1E6E0068, (mindwm(ast, 0x1E6E0068) & 0xFFFF) | (dlli << 16)); 970 971 data = (mindwm(ast, 0x1E6E0080) >> 24) & 0x1F; 972 data2 = (mindwm(ast, 0x1E6E0018) & 0xff80ffff) | (data << 16); 973 moutdwm(ast, 0x1E6E0018, data2); 974 moutdwm(ast, 0x1E6E0024, 0x8001 | (data << 1) | (param->dll2_finetune_step << 8)); 975 976 /* Wait DQSI latch phase calibration */ 977 moutdwm(ast, 0x1E6E0074, 0x00000010); 978 moutdwm(ast, 0x1E6E0070, 0x00000003); 979 do { 980 data = mindwm(ast, 0x1E6E0070); 981 } while (!(data & 0x00001000)); 982 moutdwm(ast, 0x1E6E0070, 0x00000000); 983 moutdwm(ast, 0x1E6E0070, 0x00000003); 984 do { 985 data = mindwm(ast, 0x1E6E0070); 986 } while (!(data & 0x00001000)); 987 moutdwm(ast, 0x1E6E0070, 0x00000000); 988 } /* CBRDLL2 */ 989 990 static void get_ddr3_info(struct ast_private *ast, struct ast2300_dram_param *param) 991 { 992 u32 trap, trap_AC2, trap_MRS; 993 994 moutdwm(ast, 0x1E6E2000, 0x1688A8A8); 995 996 /* Ger trap info */ 997 trap = (mindwm(ast, 0x1E6E2070) >> 25) & 0x3; 998 trap_AC2 = 0x00020000 + (trap << 16); 999 trap_AC2 |= 0x00300000 + ((trap & 0x2) << 19); 1000 trap_MRS = 0x00000010 + (trap << 4); 1001 trap_MRS |= ((trap & 0x2) << 18); 1002 1003 param->reg_MADJ = 0x00034C4C; 1004 param->reg_SADJ = 0x00001800; 1005 param->reg_DRV = 0x000000F0; 1006 param->reg_PERIOD = param->dram_freq; 1007 param->rodt = 0; 1008 1009 switch (param->dram_freq) { 1010 case 336: 1011 moutdwm(ast, 0x1E6E2020, 0x0190); 1012 param->wodt = 0; 1013 param->reg_AC1 = 0x22202725; 1014 param->reg_AC2 = 0xAA007613 | trap_AC2; 1015 param->reg_DQSIC = 0x000000BA; 1016 param->reg_MRS = 0x04001400 | trap_MRS; 1017 param->reg_EMRS = 0x00000000; 1018 param->reg_IOZ = 0x00000034; 1019 param->reg_DQIDLY = 0x00000074; 1020 param->reg_FREQ = 0x00004DC0; 1021 param->madj_max = 96; 1022 param->dll2_finetune_step = 3; 1023 break; 1024 default: 1025 case 396: 1026 moutdwm(ast, 0x1E6E2020, 0x03F1); 1027 param->wodt = 1; 1028 param->reg_AC1 = 0x33302825; 1029 param->reg_AC2 = 0xCC009617 | trap_AC2; 1030 param->reg_DQSIC = 0x000000E2; 1031 param->reg_MRS = 0x04001600 | trap_MRS; 1032 param->reg_EMRS = 0x00000000; 1033 param->reg_IOZ = 0x00000034; 1034 param->reg_DRV = 0x000000FA; 1035 param->reg_DQIDLY = 0x00000089; 1036 param->reg_FREQ = 0x000050C0; 1037 param->madj_max = 96; 1038 param->dll2_finetune_step = 4; 1039 1040 switch (param->dram_chipid) { 1041 default: 1042 case AST_DRAM_512Mx16: 1043 case AST_DRAM_1Gx16: 1044 param->reg_AC2 = 0xCC009617 | trap_AC2; 1045 break; 1046 case AST_DRAM_2Gx16: 1047 param->reg_AC2 = 0xCC009622 | trap_AC2; 1048 break; 1049 case AST_DRAM_4Gx16: 1050 param->reg_AC2 = 0xCC00963F | trap_AC2; 1051 break; 1052 } 1053 break; 1054 1055 case 408: 1056 moutdwm(ast, 0x1E6E2020, 0x01F0); 1057 param->wodt = 1; 1058 param->reg_AC1 = 0x33302825; 1059 param->reg_AC2 = 0xCC009617 | trap_AC2; 1060 param->reg_DQSIC = 0x000000E2; 1061 param->reg_MRS = 0x04001600 | trap_MRS; 1062 param->reg_EMRS = 0x00000000; 1063 param->reg_IOZ = 0x00000034; 1064 param->reg_DRV = 0x000000FA; 1065 param->reg_DQIDLY = 0x00000089; 1066 param->reg_FREQ = 0x000050C0; 1067 param->madj_max = 96; 1068 param->dll2_finetune_step = 4; 1069 1070 switch (param->dram_chipid) { 1071 default: 1072 case AST_DRAM_512Mx16: 1073 case AST_DRAM_1Gx16: 1074 param->reg_AC2 = 0xCC009617 | trap_AC2; 1075 break; 1076 case AST_DRAM_2Gx16: 1077 param->reg_AC2 = 0xCC009622 | trap_AC2; 1078 break; 1079 case AST_DRAM_4Gx16: 1080 param->reg_AC2 = 0xCC00963F | trap_AC2; 1081 break; 1082 } 1083 1084 break; 1085 case 456: 1086 moutdwm(ast, 0x1E6E2020, 0x0230); 1087 param->wodt = 0; 1088 param->reg_AC1 = 0x33302926; 1089 param->reg_AC2 = 0xCD44961A; 1090 param->reg_DQSIC = 0x000000FC; 1091 param->reg_MRS = 0x00081830; 1092 param->reg_EMRS = 0x00000000; 1093 param->reg_IOZ = 0x00000045; 1094 param->reg_DQIDLY = 0x00000097; 1095 param->reg_FREQ = 0x000052C0; 1096 param->madj_max = 88; 1097 param->dll2_finetune_step = 4; 1098 break; 1099 case 504: 1100 moutdwm(ast, 0x1E6E2020, 0x0270); 1101 param->wodt = 1; 1102 param->reg_AC1 = 0x33302926; 1103 param->reg_AC2 = 0xDE44A61D; 1104 param->reg_DQSIC = 0x00000117; 1105 param->reg_MRS = 0x00081A30; 1106 param->reg_EMRS = 0x00000000; 1107 param->reg_IOZ = 0x070000BB; 1108 param->reg_DQIDLY = 0x000000A0; 1109 param->reg_FREQ = 0x000054C0; 1110 param->madj_max = 79; 1111 param->dll2_finetune_step = 4; 1112 break; 1113 case 528: 1114 moutdwm(ast, 0x1E6E2020, 0x0290); 1115 param->wodt = 1; 1116 param->rodt = 1; 1117 param->reg_AC1 = 0x33302926; 1118 param->reg_AC2 = 0xEF44B61E; 1119 param->reg_DQSIC = 0x00000125; 1120 param->reg_MRS = 0x00081A30; 1121 param->reg_EMRS = 0x00000040; 1122 param->reg_DRV = 0x000000F5; 1123 param->reg_IOZ = 0x00000023; 1124 param->reg_DQIDLY = 0x00000088; 1125 param->reg_FREQ = 0x000055C0; 1126 param->madj_max = 76; 1127 param->dll2_finetune_step = 3; 1128 break; 1129 case 576: 1130 moutdwm(ast, 0x1E6E2020, 0x0140); 1131 param->reg_MADJ = 0x00136868; 1132 param->reg_SADJ = 0x00004534; 1133 param->wodt = 1; 1134 param->rodt = 1; 1135 param->reg_AC1 = 0x33302A37; 1136 param->reg_AC2 = 0xEF56B61E; 1137 param->reg_DQSIC = 0x0000013F; 1138 param->reg_MRS = 0x00101A50; 1139 param->reg_EMRS = 0x00000040; 1140 param->reg_DRV = 0x000000FA; 1141 param->reg_IOZ = 0x00000023; 1142 param->reg_DQIDLY = 0x00000078; 1143 param->reg_FREQ = 0x000057C0; 1144 param->madj_max = 136; 1145 param->dll2_finetune_step = 3; 1146 break; 1147 case 600: 1148 moutdwm(ast, 0x1E6E2020, 0x02E1); 1149 param->reg_MADJ = 0x00136868; 1150 param->reg_SADJ = 0x00004534; 1151 param->wodt = 1; 1152 param->rodt = 1; 1153 param->reg_AC1 = 0x32302A37; 1154 param->reg_AC2 = 0xDF56B61F; 1155 param->reg_DQSIC = 0x0000014D; 1156 param->reg_MRS = 0x00101A50; 1157 param->reg_EMRS = 0x00000004; 1158 param->reg_DRV = 0x000000F5; 1159 param->reg_IOZ = 0x00000023; 1160 param->reg_DQIDLY = 0x00000078; 1161 param->reg_FREQ = 0x000058C0; 1162 param->madj_max = 132; 1163 param->dll2_finetune_step = 3; 1164 break; 1165 case 624: 1166 moutdwm(ast, 0x1E6E2020, 0x0160); 1167 param->reg_MADJ = 0x00136868; 1168 param->reg_SADJ = 0x00004534; 1169 param->wodt = 1; 1170 param->rodt = 1; 1171 param->reg_AC1 = 0x32302A37; 1172 param->reg_AC2 = 0xEF56B621; 1173 param->reg_DQSIC = 0x0000015A; 1174 param->reg_MRS = 0x02101A50; 1175 param->reg_EMRS = 0x00000004; 1176 param->reg_DRV = 0x000000F5; 1177 param->reg_IOZ = 0x00000034; 1178 param->reg_DQIDLY = 0x00000078; 1179 param->reg_FREQ = 0x000059C0; 1180 param->madj_max = 128; 1181 param->dll2_finetune_step = 3; 1182 break; 1183 } /* switch freq */ 1184 1185 switch (param->dram_chipid) { 1186 case AST_DRAM_512Mx16: 1187 param->dram_config = 0x130; 1188 break; 1189 default: 1190 case AST_DRAM_1Gx16: 1191 param->dram_config = 0x131; 1192 break; 1193 case AST_DRAM_2Gx16: 1194 param->dram_config = 0x132; 1195 break; 1196 case AST_DRAM_4Gx16: 1197 param->dram_config = 0x133; 1198 break; 1199 }; /* switch size */ 1200 1201 switch (param->vram_size) { 1202 default: 1203 case AST_VIDMEM_SIZE_8M: 1204 param->dram_config |= 0x00; 1205 break; 1206 case AST_VIDMEM_SIZE_16M: 1207 param->dram_config |= 0x04; 1208 break; 1209 case AST_VIDMEM_SIZE_32M: 1210 param->dram_config |= 0x08; 1211 break; 1212 case AST_VIDMEM_SIZE_64M: 1213 param->dram_config |= 0x0c; 1214 break; 1215 } 1216 1217 } 1218 1219 static void ddr3_init(struct ast_private *ast, struct ast2300_dram_param *param) 1220 { 1221 u32 data, data2; 1222 1223 moutdwm(ast, 0x1E6E0000, 0xFC600309); 1224 moutdwm(ast, 0x1E6E0018, 0x00000100); 1225 moutdwm(ast, 0x1E6E0024, 0x00000000); 1226 moutdwm(ast, 0x1E6E0034, 0x00000000); 1227 udelay(10); 1228 moutdwm(ast, 0x1E6E0064, param->reg_MADJ); 1229 moutdwm(ast, 0x1E6E0068, param->reg_SADJ); 1230 udelay(10); 1231 moutdwm(ast, 0x1E6E0064, param->reg_MADJ | 0xC0000); 1232 udelay(10); 1233 1234 moutdwm(ast, 0x1E6E0004, param->dram_config); 1235 moutdwm(ast, 0x1E6E0008, 0x90040f); 1236 moutdwm(ast, 0x1E6E0010, param->reg_AC1); 1237 moutdwm(ast, 0x1E6E0014, param->reg_AC2); 1238 moutdwm(ast, 0x1E6E0020, param->reg_DQSIC); 1239 moutdwm(ast, 0x1E6E0080, 0x00000000); 1240 moutdwm(ast, 0x1E6E0084, 0x00000000); 1241 moutdwm(ast, 0x1E6E0088, param->reg_DQIDLY); 1242 moutdwm(ast, 0x1E6E0018, 0x4040A170); 1243 moutdwm(ast, 0x1E6E0018, 0x20402370); 1244 moutdwm(ast, 0x1E6E0038, 0x00000000); 1245 moutdwm(ast, 0x1E6E0040, 0xFF444444); 1246 moutdwm(ast, 0x1E6E0044, 0x22222222); 1247 moutdwm(ast, 0x1E6E0048, 0x22222222); 1248 moutdwm(ast, 0x1E6E004C, 0x00000002); 1249 moutdwm(ast, 0x1E6E0050, 0x80000000); 1250 moutdwm(ast, 0x1E6E0050, 0x00000000); 1251 moutdwm(ast, 0x1E6E0054, 0); 1252 moutdwm(ast, 0x1E6E0060, param->reg_DRV); 1253 moutdwm(ast, 0x1E6E006C, param->reg_IOZ); 1254 moutdwm(ast, 0x1E6E0070, 0x00000000); 1255 moutdwm(ast, 0x1E6E0074, 0x00000000); 1256 moutdwm(ast, 0x1E6E0078, 0x00000000); 1257 moutdwm(ast, 0x1E6E007C, 0x00000000); 1258 /* Wait MCLK2X lock to MCLK */ 1259 do { 1260 data = mindwm(ast, 0x1E6E001C); 1261 } while (!(data & 0x08000000)); 1262 moutdwm(ast, 0x1E6E0034, 0x00000001); 1263 moutdwm(ast, 0x1E6E000C, 0x00005C04); 1264 udelay(10); 1265 moutdwm(ast, 0x1E6E000C, 0x00000000); 1266 moutdwm(ast, 0x1E6E0034, 0x00000000); 1267 data = mindwm(ast, 0x1E6E001C); 1268 data = (data >> 8) & 0xff; 1269 while ((data & 0x08) || ((data & 0x7) < 2) || (data < 4)) { 1270 data2 = (mindwm(ast, 0x1E6E0064) & 0xfff3ffff) + 4; 1271 if ((data2 & 0xff) > param->madj_max) { 1272 break; 1273 } 1274 moutdwm(ast, 0x1E6E0064, data2); 1275 if (data2 & 0x00100000) { 1276 data2 = ((data2 & 0xff) >> 3) + 3; 1277 } else { 1278 data2 = ((data2 & 0xff) >> 2) + 5; 1279 } 1280 data = mindwm(ast, 0x1E6E0068) & 0xffff00ff; 1281 data2 += data & 0xff; 1282 data = data | (data2 << 8); 1283 moutdwm(ast, 0x1E6E0068, data); 1284 udelay(10); 1285 moutdwm(ast, 0x1E6E0064, mindwm(ast, 0x1E6E0064) | 0xC0000); 1286 udelay(10); 1287 data = mindwm(ast, 0x1E6E0018) & 0xfffff1ff; 1288 moutdwm(ast, 0x1E6E0018, data); 1289 data = data | 0x200; 1290 moutdwm(ast, 0x1E6E0018, data); 1291 do { 1292 data = mindwm(ast, 0x1E6E001C); 1293 } while (!(data & 0x08000000)); 1294 1295 moutdwm(ast, 0x1E6E0034, 0x00000001); 1296 moutdwm(ast, 0x1E6E000C, 0x00005C04); 1297 udelay(10); 1298 moutdwm(ast, 0x1E6E000C, 0x00000000); 1299 moutdwm(ast, 0x1E6E0034, 0x00000000); 1300 data = mindwm(ast, 0x1E6E001C); 1301 data = (data >> 8) & 0xff; 1302 } 1303 data = mindwm(ast, 0x1E6E0018) | 0xC00; 1304 moutdwm(ast, 0x1E6E0018, data); 1305 1306 moutdwm(ast, 0x1E6E0034, 0x00000001); 1307 moutdwm(ast, 0x1E6E000C, 0x00000040); 1308 udelay(50); 1309 /* Mode Register Setting */ 1310 moutdwm(ast, 0x1E6E002C, param->reg_MRS | 0x100); 1311 moutdwm(ast, 0x1E6E0030, param->reg_EMRS); 1312 moutdwm(ast, 0x1E6E0028, 0x00000005); 1313 moutdwm(ast, 0x1E6E0028, 0x00000007); 1314 moutdwm(ast, 0x1E6E0028, 0x00000003); 1315 moutdwm(ast, 0x1E6E0028, 0x00000001); 1316 moutdwm(ast, 0x1E6E002C, param->reg_MRS); 1317 moutdwm(ast, 0x1E6E000C, 0x00005C08); 1318 moutdwm(ast, 0x1E6E0028, 0x00000001); 1319 1320 moutdwm(ast, 0x1E6E000C, 0x7FFF5C01); 1321 data = 0; 1322 if (param->wodt) { 1323 data = 0x300; 1324 } 1325 if (param->rodt) { 1326 data = data | 0x3000 | ((param->reg_AC2 & 0x60000) >> 3); 1327 } 1328 moutdwm(ast, 0x1E6E0034, data | 0x3); 1329 1330 /* Wait DQI delay lock */ 1331 do { 1332 data = mindwm(ast, 0x1E6E0080); 1333 } while (!(data & 0x40000000)); 1334 /* Wait DQSI delay lock */ 1335 do { 1336 data = mindwm(ast, 0x1E6E0020); 1337 } while (!(data & 0x00000800)); 1338 /* Calibrate the DQSI delay */ 1339 cbr_dll2(ast, param); 1340 1341 moutdwm(ast, 0x1E6E0120, param->reg_FREQ); 1342 /* ECC Memory Initialization */ 1343 #ifdef ECC 1344 moutdwm(ast, 0x1E6E007C, 0x00000000); 1345 moutdwm(ast, 0x1E6E0070, 0x221); 1346 do { 1347 data = mindwm(ast, 0x1E6E0070); 1348 } while (!(data & 0x00001000)); 1349 moutdwm(ast, 0x1E6E0070, 0x00000000); 1350 moutdwm(ast, 0x1E6E0050, 0x80000000); 1351 moutdwm(ast, 0x1E6E0050, 0x00000000); 1352 #endif 1353 1354 1355 } 1356 1357 static void get_ddr2_info(struct ast_private *ast, struct ast2300_dram_param *param) 1358 { 1359 u32 trap, trap_AC2, trap_MRS; 1360 1361 moutdwm(ast, 0x1E6E2000, 0x1688A8A8); 1362 1363 /* Ger trap info */ 1364 trap = (mindwm(ast, 0x1E6E2070) >> 25) & 0x3; 1365 trap_AC2 = (trap << 20) | (trap << 16); 1366 trap_AC2 += 0x00110000; 1367 trap_MRS = 0x00000040 | (trap << 4); 1368 1369 1370 param->reg_MADJ = 0x00034C4C; 1371 param->reg_SADJ = 0x00001800; 1372 param->reg_DRV = 0x000000F0; 1373 param->reg_PERIOD = param->dram_freq; 1374 param->rodt = 0; 1375 1376 switch (param->dram_freq) { 1377 case 264: 1378 moutdwm(ast, 0x1E6E2020, 0x0130); 1379 param->wodt = 0; 1380 param->reg_AC1 = 0x11101513; 1381 param->reg_AC2 = 0x78117011; 1382 param->reg_DQSIC = 0x00000092; 1383 param->reg_MRS = 0x00000842; 1384 param->reg_EMRS = 0x00000000; 1385 param->reg_DRV = 0x000000F0; 1386 param->reg_IOZ = 0x00000034; 1387 param->reg_DQIDLY = 0x0000005A; 1388 param->reg_FREQ = 0x00004AC0; 1389 param->madj_max = 138; 1390 param->dll2_finetune_step = 3; 1391 break; 1392 case 336: 1393 moutdwm(ast, 0x1E6E2020, 0x0190); 1394 param->wodt = 1; 1395 param->reg_AC1 = 0x22202613; 1396 param->reg_AC2 = 0xAA009016 | trap_AC2; 1397 param->reg_DQSIC = 0x000000BA; 1398 param->reg_MRS = 0x00000A02 | trap_MRS; 1399 param->reg_EMRS = 0x00000040; 1400 param->reg_DRV = 0x000000FA; 1401 param->reg_IOZ = 0x00000034; 1402 param->reg_DQIDLY = 0x00000074; 1403 param->reg_FREQ = 0x00004DC0; 1404 param->madj_max = 96; 1405 param->dll2_finetune_step = 3; 1406 break; 1407 default: 1408 case 396: 1409 moutdwm(ast, 0x1E6E2020, 0x03F1); 1410 param->wodt = 1; 1411 param->rodt = 0; 1412 param->reg_AC1 = 0x33302714; 1413 param->reg_AC2 = 0xCC00B01B | trap_AC2; 1414 param->reg_DQSIC = 0x000000E2; 1415 param->reg_MRS = 0x00000C02 | trap_MRS; 1416 param->reg_EMRS = 0x00000040; 1417 param->reg_DRV = 0x000000FA; 1418 param->reg_IOZ = 0x00000034; 1419 param->reg_DQIDLY = 0x00000089; 1420 param->reg_FREQ = 0x000050C0; 1421 param->madj_max = 96; 1422 param->dll2_finetune_step = 4; 1423 1424 switch (param->dram_chipid) { 1425 case AST_DRAM_512Mx16: 1426 param->reg_AC2 = 0xCC00B016 | trap_AC2; 1427 break; 1428 default: 1429 case AST_DRAM_1Gx16: 1430 param->reg_AC2 = 0xCC00B01B | trap_AC2; 1431 break; 1432 case AST_DRAM_2Gx16: 1433 param->reg_AC2 = 0xCC00B02B | trap_AC2; 1434 break; 1435 case AST_DRAM_4Gx16: 1436 param->reg_AC2 = 0xCC00B03F | trap_AC2; 1437 break; 1438 } 1439 1440 break; 1441 1442 case 408: 1443 moutdwm(ast, 0x1E6E2020, 0x01F0); 1444 param->wodt = 1; 1445 param->rodt = 0; 1446 param->reg_AC1 = 0x33302714; 1447 param->reg_AC2 = 0xCC00B01B | trap_AC2; 1448 param->reg_DQSIC = 0x000000E2; 1449 param->reg_MRS = 0x00000C02 | trap_MRS; 1450 param->reg_EMRS = 0x00000040; 1451 param->reg_DRV = 0x000000FA; 1452 param->reg_IOZ = 0x00000034; 1453 param->reg_DQIDLY = 0x00000089; 1454 param->reg_FREQ = 0x000050C0; 1455 param->madj_max = 96; 1456 param->dll2_finetune_step = 4; 1457 1458 switch (param->dram_chipid) { 1459 case AST_DRAM_512Mx16: 1460 param->reg_AC2 = 0xCC00B016 | trap_AC2; 1461 break; 1462 default: 1463 case AST_DRAM_1Gx16: 1464 param->reg_AC2 = 0xCC00B01B | trap_AC2; 1465 break; 1466 case AST_DRAM_2Gx16: 1467 param->reg_AC2 = 0xCC00B02B | trap_AC2; 1468 break; 1469 case AST_DRAM_4Gx16: 1470 param->reg_AC2 = 0xCC00B03F | trap_AC2; 1471 break; 1472 } 1473 1474 break; 1475 case 456: 1476 moutdwm(ast, 0x1E6E2020, 0x0230); 1477 param->wodt = 0; 1478 param->reg_AC1 = 0x33302815; 1479 param->reg_AC2 = 0xCD44B01E; 1480 param->reg_DQSIC = 0x000000FC; 1481 param->reg_MRS = 0x00000E72; 1482 param->reg_EMRS = 0x00000000; 1483 param->reg_DRV = 0x00000000; 1484 param->reg_IOZ = 0x00000034; 1485 param->reg_DQIDLY = 0x00000097; 1486 param->reg_FREQ = 0x000052C0; 1487 param->madj_max = 88; 1488 param->dll2_finetune_step = 3; 1489 break; 1490 case 504: 1491 moutdwm(ast, 0x1E6E2020, 0x0261); 1492 param->wodt = 1; 1493 param->rodt = 1; 1494 param->reg_AC1 = 0x33302815; 1495 param->reg_AC2 = 0xDE44C022; 1496 param->reg_DQSIC = 0x00000117; 1497 param->reg_MRS = 0x00000E72; 1498 param->reg_EMRS = 0x00000040; 1499 param->reg_DRV = 0x0000000A; 1500 param->reg_IOZ = 0x00000045; 1501 param->reg_DQIDLY = 0x000000A0; 1502 param->reg_FREQ = 0x000054C0; 1503 param->madj_max = 79; 1504 param->dll2_finetune_step = 3; 1505 break; 1506 case 528: 1507 moutdwm(ast, 0x1E6E2020, 0x0120); 1508 param->wodt = 1; 1509 param->rodt = 1; 1510 param->reg_AC1 = 0x33302815; 1511 param->reg_AC2 = 0xEF44D024; 1512 param->reg_DQSIC = 0x00000125; 1513 param->reg_MRS = 0x00000E72; 1514 param->reg_EMRS = 0x00000004; 1515 param->reg_DRV = 0x000000F9; 1516 param->reg_IOZ = 0x00000045; 1517 param->reg_DQIDLY = 0x000000A7; 1518 param->reg_FREQ = 0x000055C0; 1519 param->madj_max = 76; 1520 param->dll2_finetune_step = 3; 1521 break; 1522 case 552: 1523 moutdwm(ast, 0x1E6E2020, 0x02A1); 1524 param->wodt = 1; 1525 param->rodt = 1; 1526 param->reg_AC1 = 0x43402915; 1527 param->reg_AC2 = 0xFF44E025; 1528 param->reg_DQSIC = 0x00000132; 1529 param->reg_MRS = 0x00000E72; 1530 param->reg_EMRS = 0x00000040; 1531 param->reg_DRV = 0x0000000A; 1532 param->reg_IOZ = 0x00000045; 1533 param->reg_DQIDLY = 0x000000AD; 1534 param->reg_FREQ = 0x000056C0; 1535 param->madj_max = 76; 1536 param->dll2_finetune_step = 3; 1537 break; 1538 case 576: 1539 moutdwm(ast, 0x1E6E2020, 0x0140); 1540 param->wodt = 1; 1541 param->rodt = 1; 1542 param->reg_AC1 = 0x43402915; 1543 param->reg_AC2 = 0xFF44E027; 1544 param->reg_DQSIC = 0x0000013F; 1545 param->reg_MRS = 0x00000E72; 1546 param->reg_EMRS = 0x00000004; 1547 param->reg_DRV = 0x000000F5; 1548 param->reg_IOZ = 0x00000045; 1549 param->reg_DQIDLY = 0x000000B3; 1550 param->reg_FREQ = 0x000057C0; 1551 param->madj_max = 76; 1552 param->dll2_finetune_step = 3; 1553 break; 1554 } 1555 1556 switch (param->dram_chipid) { 1557 case AST_DRAM_512Mx16: 1558 param->dram_config = 0x100; 1559 break; 1560 default: 1561 case AST_DRAM_1Gx16: 1562 param->dram_config = 0x121; 1563 break; 1564 case AST_DRAM_2Gx16: 1565 param->dram_config = 0x122; 1566 break; 1567 case AST_DRAM_4Gx16: 1568 param->dram_config = 0x123; 1569 break; 1570 }; /* switch size */ 1571 1572 switch (param->vram_size) { 1573 default: 1574 case AST_VIDMEM_SIZE_8M: 1575 param->dram_config |= 0x00; 1576 break; 1577 case AST_VIDMEM_SIZE_16M: 1578 param->dram_config |= 0x04; 1579 break; 1580 case AST_VIDMEM_SIZE_32M: 1581 param->dram_config |= 0x08; 1582 break; 1583 case AST_VIDMEM_SIZE_64M: 1584 param->dram_config |= 0x0c; 1585 break; 1586 } 1587 } 1588 1589 static void ddr2_init(struct ast_private *ast, struct ast2300_dram_param *param) 1590 { 1591 u32 data, data2; 1592 1593 moutdwm(ast, 0x1E6E0000, 0xFC600309); 1594 moutdwm(ast, 0x1E6E0018, 0x00000100); 1595 moutdwm(ast, 0x1E6E0024, 0x00000000); 1596 moutdwm(ast, 0x1E6E0064, param->reg_MADJ); 1597 moutdwm(ast, 0x1E6E0068, param->reg_SADJ); 1598 udelay(10); 1599 moutdwm(ast, 0x1E6E0064, param->reg_MADJ | 0xC0000); 1600 udelay(10); 1601 1602 moutdwm(ast, 0x1E6E0004, param->dram_config); 1603 moutdwm(ast, 0x1E6E0008, 0x90040f); 1604 moutdwm(ast, 0x1E6E0010, param->reg_AC1); 1605 moutdwm(ast, 0x1E6E0014, param->reg_AC2); 1606 moutdwm(ast, 0x1E6E0020, param->reg_DQSIC); 1607 moutdwm(ast, 0x1E6E0080, 0x00000000); 1608 moutdwm(ast, 0x1E6E0084, 0x00000000); 1609 moutdwm(ast, 0x1E6E0088, param->reg_DQIDLY); 1610 moutdwm(ast, 0x1E6E0018, 0x4040A130); 1611 moutdwm(ast, 0x1E6E0018, 0x20402330); 1612 moutdwm(ast, 0x1E6E0038, 0x00000000); 1613 moutdwm(ast, 0x1E6E0040, 0xFF808000); 1614 moutdwm(ast, 0x1E6E0044, 0x88848466); 1615 moutdwm(ast, 0x1E6E0048, 0x44440008); 1616 moutdwm(ast, 0x1E6E004C, 0x00000000); 1617 moutdwm(ast, 0x1E6E0050, 0x80000000); 1618 moutdwm(ast, 0x1E6E0050, 0x00000000); 1619 moutdwm(ast, 0x1E6E0054, 0); 1620 moutdwm(ast, 0x1E6E0060, param->reg_DRV); 1621 moutdwm(ast, 0x1E6E006C, param->reg_IOZ); 1622 moutdwm(ast, 0x1E6E0070, 0x00000000); 1623 moutdwm(ast, 0x1E6E0074, 0x00000000); 1624 moutdwm(ast, 0x1E6E0078, 0x00000000); 1625 moutdwm(ast, 0x1E6E007C, 0x00000000); 1626 1627 /* Wait MCLK2X lock to MCLK */ 1628 do { 1629 data = mindwm(ast, 0x1E6E001C); 1630 } while (!(data & 0x08000000)); 1631 moutdwm(ast, 0x1E6E0034, 0x00000001); 1632 moutdwm(ast, 0x1E6E000C, 0x00005C04); 1633 udelay(10); 1634 moutdwm(ast, 0x1E6E000C, 0x00000000); 1635 moutdwm(ast, 0x1E6E0034, 0x00000000); 1636 data = mindwm(ast, 0x1E6E001C); 1637 data = (data >> 8) & 0xff; 1638 while ((data & 0x08) || ((data & 0x7) < 2) || (data < 4)) { 1639 data2 = (mindwm(ast, 0x1E6E0064) & 0xfff3ffff) + 4; 1640 if ((data2 & 0xff) > param->madj_max) { 1641 break; 1642 } 1643 moutdwm(ast, 0x1E6E0064, data2); 1644 if (data2 & 0x00100000) { 1645 data2 = ((data2 & 0xff) >> 3) + 3; 1646 } else { 1647 data2 = ((data2 & 0xff) >> 2) + 5; 1648 } 1649 data = mindwm(ast, 0x1E6E0068) & 0xffff00ff; 1650 data2 += data & 0xff; 1651 data = data | (data2 << 8); 1652 moutdwm(ast, 0x1E6E0068, data); 1653 udelay(10); 1654 moutdwm(ast, 0x1E6E0064, mindwm(ast, 0x1E6E0064) | 0xC0000); 1655 udelay(10); 1656 data = mindwm(ast, 0x1E6E0018) & 0xfffff1ff; 1657 moutdwm(ast, 0x1E6E0018, data); 1658 data = data | 0x200; 1659 moutdwm(ast, 0x1E6E0018, data); 1660 do { 1661 data = mindwm(ast, 0x1E6E001C); 1662 } while (!(data & 0x08000000)); 1663 1664 moutdwm(ast, 0x1E6E0034, 0x00000001); 1665 moutdwm(ast, 0x1E6E000C, 0x00005C04); 1666 udelay(10); 1667 moutdwm(ast, 0x1E6E000C, 0x00000000); 1668 moutdwm(ast, 0x1E6E0034, 0x00000000); 1669 data = mindwm(ast, 0x1E6E001C); 1670 data = (data >> 8) & 0xff; 1671 } 1672 data = mindwm(ast, 0x1E6E0018) | 0xC00; 1673 moutdwm(ast, 0x1E6E0018, data); 1674 1675 moutdwm(ast, 0x1E6E0034, 0x00000001); 1676 moutdwm(ast, 0x1E6E000C, 0x00000000); 1677 udelay(50); 1678 /* Mode Register Setting */ 1679 moutdwm(ast, 0x1E6E002C, param->reg_MRS | 0x100); 1680 moutdwm(ast, 0x1E6E0030, param->reg_EMRS); 1681 moutdwm(ast, 0x1E6E0028, 0x00000005); 1682 moutdwm(ast, 0x1E6E0028, 0x00000007); 1683 moutdwm(ast, 0x1E6E0028, 0x00000003); 1684 moutdwm(ast, 0x1E6E0028, 0x00000001); 1685 1686 moutdwm(ast, 0x1E6E000C, 0x00005C08); 1687 moutdwm(ast, 0x1E6E002C, param->reg_MRS); 1688 moutdwm(ast, 0x1E6E0028, 0x00000001); 1689 moutdwm(ast, 0x1E6E0030, param->reg_EMRS | 0x380); 1690 moutdwm(ast, 0x1E6E0028, 0x00000003); 1691 moutdwm(ast, 0x1E6E0030, param->reg_EMRS); 1692 moutdwm(ast, 0x1E6E0028, 0x00000003); 1693 1694 moutdwm(ast, 0x1E6E000C, 0x7FFF5C01); 1695 data = 0; 1696 if (param->wodt) { 1697 data = 0x500; 1698 } 1699 if (param->rodt) { 1700 data = data | 0x3000 | ((param->reg_AC2 & 0x60000) >> 3); 1701 } 1702 moutdwm(ast, 0x1E6E0034, data | 0x3); 1703 moutdwm(ast, 0x1E6E0120, param->reg_FREQ); 1704 1705 /* Wait DQI delay lock */ 1706 do { 1707 data = mindwm(ast, 0x1E6E0080); 1708 } while (!(data & 0x40000000)); 1709 /* Wait DQSI delay lock */ 1710 do { 1711 data = mindwm(ast, 0x1E6E0020); 1712 } while (!(data & 0x00000800)); 1713 /* Calibrate the DQSI delay */ 1714 cbr_dll2(ast, param); 1715 1716 /* ECC Memory Initialization */ 1717 #ifdef ECC 1718 moutdwm(ast, 0x1E6E007C, 0x00000000); 1719 moutdwm(ast, 0x1E6E0070, 0x221); 1720 do { 1721 data = mindwm(ast, 0x1E6E0070); 1722 } while (!(data & 0x00001000)); 1723 moutdwm(ast, 0x1E6E0070, 0x00000000); 1724 moutdwm(ast, 0x1E6E0050, 0x80000000); 1725 moutdwm(ast, 0x1E6E0050, 0x00000000); 1726 #endif 1727 1728 } 1729 1730 static void ast_init_dram_2300(struct drm_device *dev) 1731 { 1732 struct ast_private *ast = dev->dev_private; 1733 struct ast2300_dram_param param; 1734 u32 temp; 1735 u8 reg; 1736 1737 reg = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xd0, 0xff); 1738 if ((reg & 0x80) == 0) {/* vga only */ 1739 ast_write32(ast, 0xf004, 0x1e6e0000); 1740 ast_write32(ast, 0xf000, 0x1); 1741 ast_write32(ast, 0x12000, 0x1688a8a8); 1742 do { 1743 ; 1744 } while (ast_read32(ast, 0x12000) != 0x1); 1745 1746 ast_write32(ast, 0x10000, 0xfc600309); 1747 do { 1748 ; 1749 } while (ast_read32(ast, 0x10000) != 0x1); 1750 1751 /* Slow down CPU/AHB CLK in VGA only mode */ 1752 temp = ast_read32(ast, 0x12008); 1753 temp |= 0x73; 1754 ast_write32(ast, 0x12008, temp); 1755 1756 param.dram_type = AST_DDR3; 1757 if (temp & 0x01000000) 1758 param.dram_type = AST_DDR2; 1759 param.dram_chipid = ast->dram_type; 1760 param.dram_freq = ast->mclk; 1761 param.vram_size = ast->vram_size; 1762 1763 if (param.dram_type == AST_DDR3) { 1764 get_ddr3_info(ast, ¶m); 1765 ddr3_init(ast, ¶m); 1766 } else { 1767 get_ddr2_info(ast, ¶m); 1768 ddr2_init(ast, ¶m); 1769 } 1770 1771 temp = mindwm(ast, 0x1e6e2040); 1772 moutdwm(ast, 0x1e6e2040, temp | 0x40); 1773 } 1774 1775 /* wait ready */ 1776 do { 1777 reg = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xd0, 0xff); 1778 } while ((reg & 0x40) == 0); 1779 } 1780 1781