1 /* 2 * sbc8349.c -- WindRiver SBC8349 board support. 3 * Copyright (c) 2006-2007 Wind River Systems, Inc. 4 * 5 * Paul Gortmaker <paul.gortmaker@windriver.com> 6 * Based on board/mpc8349emds/mpc8349emds.c (and previous 834x releases.) 7 * 8 * See file CREDITS for list of people who contributed to this 9 * project. 10 * 11 * This program is free software; you can redistribute it and/or 12 * modify it under the terms of the GNU General Public License as 13 * published by the Free Software Foundation; either version 2 of 14 * the License, or (at your option) any later version. 15 * 16 * This program is distributed in the hope that it will be useful, 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 * GNU General Public License for more details. 20 * 21 * You should have received a copy of the GNU General Public License 22 * along with this program; if not, write to the Free Software 23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 24 * MA 02111-1307 USA 25 * 26 */ 27 28 #include <common.h> 29 #include <ioports.h> 30 #include <mpc83xx.h> 31 #include <asm/mpc8349_pci.h> 32 #include <i2c.h> 33 #include <spd.h> 34 #include <miiphy.h> 35 #include <command.h> 36 #if defined(CONFIG_SPD_EEPROM) 37 #include <spd_sdram.h> 38 #endif 39 #if defined(CONFIG_OF_FLAT_TREE) 40 #include <ft_build.h> 41 #endif 42 43 int fixed_sdram(void); 44 void sdram_init(void); 45 46 #if defined(CONFIG_DDR_ECC) && defined(CONFIG_MPC83XX) 47 void ddr_enable_ecc(unsigned int dram_size); 48 #endif 49 50 #ifdef CONFIG_BOARD_EARLY_INIT_F 51 int board_early_init_f (void) 52 { 53 return 0; 54 } 55 #endif 56 57 #define ns2clk(ns) (ns / (1000000000 / CONFIG_8349_CLKIN) + 1) 58 59 long int initdram (int board_type) 60 { 61 volatile immap_t *im = (immap_t *)CFG_IMMR; 62 u32 msize = 0; 63 64 if ((im->sysconf.immrbar & IMMRBAR_BASE_ADDR) != (u32)im) 65 return -1; 66 67 /* DDR SDRAM - Main SODIMM */ 68 im->sysconf.ddrlaw[0].bar = CFG_DDR_BASE & LAWBAR_BAR; 69 #if defined(CONFIG_SPD_EEPROM) 70 msize = spd_sdram(); 71 #else 72 msize = fixed_sdram(); 73 #endif 74 /* 75 * Initialize SDRAM if it is on local bus. 76 */ 77 sdram_init(); 78 79 #if defined(CONFIG_DDR_ECC) && !defined(CONFIG_ECC_INIT_VIA_DDRCONTROLLER) 80 /* 81 * Initialize and enable DDR ECC. 82 */ 83 ddr_enable_ecc(msize * 1024 * 1024); 84 #endif 85 /* return total bus SDRAM size(bytes) -- DDR */ 86 return (msize * 1024 * 1024); 87 } 88 89 #if !defined(CONFIG_SPD_EEPROM) 90 /************************************************************************* 91 * fixed sdram init -- doesn't use serial presence detect. 92 ************************************************************************/ 93 int fixed_sdram(void) 94 { 95 volatile immap_t *im = (immap_t *)CFG_IMMR; 96 u32 msize = 0; 97 u32 ddr_size; 98 u32 ddr_size_log2; 99 100 msize = CFG_DDR_SIZE; 101 for (ddr_size = msize << 20, ddr_size_log2 = 0; 102 (ddr_size > 1); 103 ddr_size = ddr_size>>1, ddr_size_log2++) { 104 if (ddr_size & 1) { 105 return -1; 106 } 107 } 108 im->sysconf.ddrlaw[0].bar = ((CFG_DDR_SDRAM_BASE>>12) & 0xfffff); 109 im->sysconf.ddrlaw[0].ar = LAWAR_EN | ((ddr_size_log2 - 1) & LAWAR_SIZE); 110 111 #if (CFG_DDR_SIZE != 256) 112 #warning Currently any ddr size other than 256 is not supported 113 #endif 114 im->ddr.csbnds[2].csbnds = 0x0000000f; 115 im->ddr.cs_config[2] = CFG_DDR_CONFIG; 116 117 /* currently we use only one CS, so disable the other banks */ 118 im->ddr.cs_config[0] = 0; 119 im->ddr.cs_config[1] = 0; 120 im->ddr.cs_config[3] = 0; 121 122 im->ddr.timing_cfg_1 = CFG_DDR_TIMING_1; 123 im->ddr.timing_cfg_2 = CFG_DDR_TIMING_2; 124 125 im->ddr.sdram_cfg = 126 SDRAM_CFG_SREN 127 #if defined(CONFIG_DDR_2T_TIMING) 128 | SDRAM_CFG_2T_EN 129 #endif 130 | SDRAM_CFG_SDRAM_TYPE_DDR1; 131 #if defined (CONFIG_DDR_32BIT) 132 /* for 32-bit mode burst length is 8 */ 133 im->ddr.sdram_cfg |= (SDRAM_CFG_32_BE | SDRAM_CFG_8_BE); 134 #endif 135 im->ddr.sdram_mode = CFG_DDR_MODE; 136 137 im->ddr.sdram_interval = CFG_DDR_INTERVAL; 138 udelay(200); 139 140 /* enable DDR controller */ 141 im->ddr.sdram_cfg |= SDRAM_CFG_MEM_EN; 142 return msize; 143 } 144 #endif/*!CFG_SPD_EEPROM*/ 145 146 147 int checkboard (void) 148 { 149 puts("Board: Wind River SBC834x\n"); 150 return 0; 151 } 152 153 /* 154 * if board is fitted with SDRAM 155 */ 156 #if defined(CFG_BR2_PRELIM) \ 157 && defined(CFG_OR2_PRELIM) \ 158 && defined(CFG_LBLAWBAR2_PRELIM) \ 159 && defined(CFG_LBLAWAR2_PRELIM) 160 /* 161 * Initialize SDRAM memory on the Local Bus. 162 */ 163 164 void sdram_init(void) 165 { 166 volatile immap_t *immap = (immap_t *)CFG_IMMR; 167 volatile lbus83xx_t *lbc= &immap->lbus; 168 uint *sdram_addr = (uint *)CFG_LBC_SDRAM_BASE; 169 170 puts("\n SDRAM on Local Bus: "); 171 print_size (CFG_LBC_SDRAM_SIZE * 1024 * 1024, "\n"); 172 173 /* 174 * Setup SDRAM Base and Option Registers, already done in cpu_init.c 175 */ 176 177 /* setup mtrpt, lsrt and lbcr for LB bus */ 178 lbc->lbcr = CFG_LBC_LBCR; 179 lbc->mrtpr = CFG_LBC_MRTPR; 180 lbc->lsrt = CFG_LBC_LSRT; 181 asm("sync"); 182 183 /* 184 * Configure the SDRAM controller Machine Mode Register. 185 */ 186 lbc->lsdmr = CFG_LBC_LSDMR_5; /* 0x40636733; normal operation */ 187 188 lbc->lsdmr = CFG_LBC_LSDMR_1; /* 0x68636733; precharge all the banks */ 189 asm("sync"); 190 *sdram_addr = 0xff; 191 udelay(100); 192 193 lbc->lsdmr = CFG_LBC_LSDMR_2; /* 0x48636733; auto refresh */ 194 asm("sync"); 195 /*1 times*/ 196 *sdram_addr = 0xff; 197 udelay(100); 198 /*2 times*/ 199 *sdram_addr = 0xff; 200 udelay(100); 201 /*3 times*/ 202 *sdram_addr = 0xff; 203 udelay(100); 204 /*4 times*/ 205 *sdram_addr = 0xff; 206 udelay(100); 207 /*5 times*/ 208 *sdram_addr = 0xff; 209 udelay(100); 210 /*6 times*/ 211 *sdram_addr = 0xff; 212 udelay(100); 213 /*7 times*/ 214 *sdram_addr = 0xff; 215 udelay(100); 216 /*8 times*/ 217 *sdram_addr = 0xff; 218 udelay(100); 219 220 /* 0x58636733; mode register write operation */ 221 lbc->lsdmr = CFG_LBC_LSDMR_4; 222 asm("sync"); 223 *sdram_addr = 0xff; 224 udelay(100); 225 226 lbc->lsdmr = CFG_LBC_LSDMR_5; /* 0x40636733; normal operation */ 227 asm("sync"); 228 *sdram_addr = 0xff; 229 udelay(100); 230 } 231 #else 232 void sdram_init(void) 233 { 234 puts(" SDRAM on Local Bus: Disabled in config\n"); 235 } 236 #endif 237 238 #if defined(CONFIG_DDR_ECC) && defined(CONFIG_DDR_ECC_CMD) 239 /* 240 * ECC user commands 241 */ 242 void ecc_print_status(void) 243 { 244 volatile immap_t *immap = (immap_t *)CFG_IMMR; 245 volatile ddr83xx_t *ddr = &immap->ddr; 246 247 printf("\nECC mode: %s\n\n", (ddr->sdram_cfg & SDRAM_CFG_ECC_EN) ? "ON" : "OFF"); 248 249 /* Interrupts */ 250 printf("Memory Error Interrupt Enable:\n"); 251 printf(" Multiple-Bit Error Interrupt Enable: %d\n", 252 (ddr->err_int_en & ECC_ERR_INT_EN_MBEE) ? 1 : 0); 253 printf(" Single-Bit Error Interrupt Enable: %d\n", 254 (ddr->err_int_en & ECC_ERR_INT_EN_SBEE) ? 1 : 0); 255 printf(" Memory Select Error Interrupt Enable: %d\n\n", 256 (ddr->err_int_en & ECC_ERR_INT_EN_MSEE) ? 1 : 0); 257 258 /* Error disable */ 259 printf("Memory Error Disable:\n"); 260 printf(" Multiple-Bit Error Disable: %d\n", 261 (ddr->err_disable & ECC_ERROR_DISABLE_MBED) ? 1 : 0); 262 printf(" Sinle-Bit Error Disable: %d\n", 263 (ddr->err_disable & ECC_ERROR_DISABLE_SBED) ? 1 : 0); 264 printf(" Memory Select Error Disable: %d\n\n", 265 (ddr->err_disable & ECC_ERROR_DISABLE_MSED) ? 1 : 0); 266 267 /* Error injection */ 268 printf("Memory Data Path Error Injection Mask High/Low: %08lx %08lx\n", 269 ddr->data_err_inject_hi, ddr->data_err_inject_lo); 270 271 printf("Memory Data Path Error Injection Mask ECC:\n"); 272 printf(" ECC Mirror Byte: %d\n", 273 (ddr->ecc_err_inject & ECC_ERR_INJECT_EMB) ? 1 : 0); 274 printf(" ECC Injection Enable: %d\n", 275 (ddr->ecc_err_inject & ECC_ERR_INJECT_EIEN) ? 1 : 0); 276 printf(" ECC Error Injection Mask: 0x%02x\n\n", 277 ddr->ecc_err_inject & ECC_ERR_INJECT_EEIM); 278 279 /* SBE counter/threshold */ 280 printf("Memory Single-Bit Error Management (0..255):\n"); 281 printf(" Single-Bit Error Threshold: %d\n", 282 (ddr->err_sbe & ECC_ERROR_MAN_SBET) >> ECC_ERROR_MAN_SBET_SHIFT); 283 printf(" Single-Bit Error Counter: %d\n\n", 284 (ddr->err_sbe & ECC_ERROR_MAN_SBEC) >> ECC_ERROR_MAN_SBEC_SHIFT); 285 286 /* Error detect */ 287 printf("Memory Error Detect:\n"); 288 printf(" Multiple Memory Errors: %d\n", 289 (ddr->err_detect & ECC_ERROR_DETECT_MME) ? 1 : 0); 290 printf(" Multiple-Bit Error: %d\n", 291 (ddr->err_detect & ECC_ERROR_DETECT_MBE) ? 1 : 0); 292 printf(" Single-Bit Error: %d\n", 293 (ddr->err_detect & ECC_ERROR_DETECT_SBE) ? 1 : 0); 294 printf(" Memory Select Error: %d\n\n", 295 (ddr->err_detect & ECC_ERROR_DETECT_MSE) ? 1 : 0); 296 297 /* Capture data */ 298 printf("Memory Error Address Capture: 0x%08lx\n", ddr->capture_address); 299 printf("Memory Data Path Read Capture High/Low: %08lx %08lx\n", 300 ddr->capture_data_hi, ddr->capture_data_lo); 301 printf("Memory Data Path Read Capture ECC: 0x%02x\n\n", 302 ddr->capture_ecc & CAPTURE_ECC_ECE); 303 304 printf("Memory Error Attributes Capture:\n"); 305 printf(" Data Beat Number: %d\n", 306 (ddr->capture_attributes & ECC_CAPT_ATTR_BNUM) >> ECC_CAPT_ATTR_BNUM_SHIFT); 307 printf(" Transaction Size: %d\n", 308 (ddr->capture_attributes & ECC_CAPT_ATTR_TSIZ) >> ECC_CAPT_ATTR_TSIZ_SHIFT); 309 printf(" Transaction Source: %d\n", 310 (ddr->capture_attributes & ECC_CAPT_ATTR_TSRC) >> ECC_CAPT_ATTR_TSRC_SHIFT); 311 printf(" Transaction Type: %d\n", 312 (ddr->capture_attributes & ECC_CAPT_ATTR_TTYP) >> ECC_CAPT_ATTR_TTYP_SHIFT); 313 printf(" Error Information Valid: %d\n\n", 314 ddr->capture_attributes & ECC_CAPT_ATTR_VLD); 315 } 316 317 int do_ecc ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) 318 { 319 volatile immap_t *immap = (immap_t *)CFG_IMMR; 320 volatile ddr83xx_t *ddr = &immap->ddr; 321 volatile u32 val; 322 u64 *addr, count, val64; 323 register u64 *i; 324 325 if (argc > 4) { 326 printf ("Usage:\n%s\n", cmdtp->usage); 327 return 1; 328 } 329 330 if (argc == 2) { 331 if (strcmp(argv[1], "status") == 0) { 332 ecc_print_status(); 333 return 0; 334 } else if (strcmp(argv[1], "captureclear") == 0) { 335 ddr->capture_address = 0; 336 ddr->capture_data_hi = 0; 337 ddr->capture_data_lo = 0; 338 ddr->capture_ecc = 0; 339 ddr->capture_attributes = 0; 340 return 0; 341 } 342 } 343 344 if (argc == 3) { 345 if (strcmp(argv[1], "sbecnt") == 0) { 346 val = simple_strtoul(argv[2], NULL, 10); 347 if (val > 255) { 348 printf("Incorrect Counter value, should be 0..255\n"); 349 return 1; 350 } 351 352 val = (val << ECC_ERROR_MAN_SBEC_SHIFT); 353 val |= (ddr->err_sbe & ECC_ERROR_MAN_SBET); 354 355 ddr->err_sbe = val; 356 return 0; 357 } else if (strcmp(argv[1], "sbethr") == 0) { 358 val = simple_strtoul(argv[2], NULL, 10); 359 if (val > 255) { 360 printf("Incorrect Counter value, should be 0..255\n"); 361 return 1; 362 } 363 364 val = (val << ECC_ERROR_MAN_SBET_SHIFT); 365 val |= (ddr->err_sbe & ECC_ERROR_MAN_SBEC); 366 367 ddr->err_sbe = val; 368 return 0; 369 } else if (strcmp(argv[1], "errdisable") == 0) { 370 val = ddr->err_disable; 371 372 if (strcmp(argv[2], "+sbe") == 0) { 373 val |= ECC_ERROR_DISABLE_SBED; 374 } else if (strcmp(argv[2], "+mbe") == 0) { 375 val |= ECC_ERROR_DISABLE_MBED; 376 } else if (strcmp(argv[2], "+mse") == 0) { 377 val |= ECC_ERROR_DISABLE_MSED; 378 } else if (strcmp(argv[2], "+all") == 0) { 379 val |= (ECC_ERROR_DISABLE_SBED | 380 ECC_ERROR_DISABLE_MBED | 381 ECC_ERROR_DISABLE_MSED); 382 } else if (strcmp(argv[2], "-sbe") == 0) { 383 val &= ~ECC_ERROR_DISABLE_SBED; 384 } else if (strcmp(argv[2], "-mbe") == 0) { 385 val &= ~ECC_ERROR_DISABLE_MBED; 386 } else if (strcmp(argv[2], "-mse") == 0) { 387 val &= ~ECC_ERROR_DISABLE_MSED; 388 } else if (strcmp(argv[2], "-all") == 0) { 389 val &= ~(ECC_ERROR_DISABLE_SBED | 390 ECC_ERROR_DISABLE_MBED | 391 ECC_ERROR_DISABLE_MSED); 392 } else { 393 printf("Incorrect err_disable field\n"); 394 return 1; 395 } 396 397 ddr->err_disable = val; 398 __asm__ __volatile__ ("sync"); 399 __asm__ __volatile__ ("isync"); 400 return 0; 401 } else if (strcmp(argv[1], "errdetectclr") == 0) { 402 val = ddr->err_detect; 403 404 if (strcmp(argv[2], "mme") == 0) { 405 val |= ECC_ERROR_DETECT_MME; 406 } else if (strcmp(argv[2], "sbe") == 0) { 407 val |= ECC_ERROR_DETECT_SBE; 408 } else if (strcmp(argv[2], "mbe") == 0) { 409 val |= ECC_ERROR_DETECT_MBE; 410 } else if (strcmp(argv[2], "mse") == 0) { 411 val |= ECC_ERROR_DETECT_MSE; 412 } else if (strcmp(argv[2], "all") == 0) { 413 val |= (ECC_ERROR_DETECT_MME | 414 ECC_ERROR_DETECT_MBE | 415 ECC_ERROR_DETECT_SBE | 416 ECC_ERROR_DETECT_MSE); 417 } else { 418 printf("Incorrect err_detect field\n"); 419 return 1; 420 } 421 422 ddr->err_detect = val; 423 return 0; 424 } else if (strcmp(argv[1], "injectdatahi") == 0) { 425 val = simple_strtoul(argv[2], NULL, 16); 426 427 ddr->data_err_inject_hi = val; 428 return 0; 429 } else if (strcmp(argv[1], "injectdatalo") == 0) { 430 val = simple_strtoul(argv[2], NULL, 16); 431 432 ddr->data_err_inject_lo = val; 433 return 0; 434 } else if (strcmp(argv[1], "injectecc") == 0) { 435 val = simple_strtoul(argv[2], NULL, 16); 436 if (val > 0xff) { 437 printf("Incorrect ECC inject mask, should be 0x00..0xff\n"); 438 return 1; 439 } 440 val |= (ddr->ecc_err_inject & ~ECC_ERR_INJECT_EEIM); 441 442 ddr->ecc_err_inject = val; 443 return 0; 444 } else if (strcmp(argv[1], "inject") == 0) { 445 val = ddr->ecc_err_inject; 446 447 if (strcmp(argv[2], "en") == 0) 448 val |= ECC_ERR_INJECT_EIEN; 449 else if (strcmp(argv[2], "dis") == 0) 450 val &= ~ECC_ERR_INJECT_EIEN; 451 else 452 printf("Incorrect command\n"); 453 454 ddr->ecc_err_inject = val; 455 __asm__ __volatile__ ("sync"); 456 __asm__ __volatile__ ("isync"); 457 return 0; 458 } else if (strcmp(argv[1], "mirror") == 0) { 459 val = ddr->ecc_err_inject; 460 461 if (strcmp(argv[2], "en") == 0) 462 val |= ECC_ERR_INJECT_EMB; 463 else if (strcmp(argv[2], "dis") == 0) 464 val &= ~ECC_ERR_INJECT_EMB; 465 else 466 printf("Incorrect command\n"); 467 468 ddr->ecc_err_inject = val; 469 return 0; 470 } 471 } 472 473 if (argc == 4) { 474 if (strcmp(argv[1], "test") == 0) { 475 addr = (u64 *)simple_strtoul(argv[2], NULL, 16); 476 count = simple_strtoul(argv[3], NULL, 16); 477 478 if ((u32)addr % 8) { 479 printf("Address not alligned on double word boundary\n"); 480 return 1; 481 } 482 483 disable_interrupts(); 484 icache_disable(); 485 486 for (i = addr; i < addr + count; i++) { 487 /* enable injects */ 488 ddr->ecc_err_inject |= ECC_ERR_INJECT_EIEN; 489 __asm__ __volatile__ ("sync"); 490 __asm__ __volatile__ ("isync"); 491 492 /* write memory location injecting errors */ 493 *i = 0x1122334455667788ULL; 494 __asm__ __volatile__ ("sync"); 495 496 /* disable injects */ 497 ddr->ecc_err_inject &= ~ECC_ERR_INJECT_EIEN; 498 __asm__ __volatile__ ("sync"); 499 __asm__ __volatile__ ("isync"); 500 501 /* read data, this generates ECC error */ 502 val64 = *i; 503 __asm__ __volatile__ ("sync"); 504 505 /* disable errors for ECC */ 506 ddr->err_disable |= ~ECC_ERROR_ENABLE; 507 __asm__ __volatile__ ("sync"); 508 __asm__ __volatile__ ("isync"); 509 510 /* re-initialize memory, write the location again 511 * NOT injecting errors this time */ 512 *i = 0xcafecafecafecafeULL; 513 __asm__ __volatile__ ("sync"); 514 515 /* enable errors for ECC */ 516 ddr->err_disable &= ECC_ERROR_ENABLE; 517 __asm__ __volatile__ ("sync"); 518 __asm__ __volatile__ ("isync"); 519 } 520 521 icache_enable(); 522 enable_interrupts(); 523 524 return 0; 525 } 526 } 527 528 printf ("Usage:\n%s\n", cmdtp->usage); 529 return 1; 530 } 531 532 U_BOOT_CMD( 533 ecc, 4, 0, do_ecc, 534 "ecc - support for DDR ECC features\n", 535 "status - print out status info\n" 536 "ecc captureclear - clear capture regs data\n" 537 "ecc sbecnt <val> - set Single-Bit Error counter\n" 538 "ecc sbethr <val> - set Single-Bit Threshold\n" 539 "ecc errdisable <flag> - clear/set disable Memory Error Disable, flag:\n" 540 " [-|+]sbe - Single-Bit Error\n" 541 " [-|+]mbe - Multiple-Bit Error\n" 542 " [-|+]mse - Memory Select Error\n" 543 " [-|+]all - all errors\n" 544 "ecc errdetectclr <flag> - clear Memory Error Detect, flag:\n" 545 " mme - Multiple Memory Errors\n" 546 " sbe - Single-Bit Error\n" 547 " mbe - Multiple-Bit Error\n" 548 " mse - Memory Select Error\n" 549 " all - all errors\n" 550 "ecc injectdatahi <hi> - set Memory Data Path Error Injection Mask High\n" 551 "ecc injectdatalo <lo> - set Memory Data Path Error Injection Mask Low\n" 552 "ecc injectecc <ecc> - set ECC Error Injection Mask\n" 553 "ecc inject <en|dis> - enable/disable error injection\n" 554 "ecc mirror <en|dis> - enable/disable mirror byte\n" 555 "ecc test <addr> <cnt> - test mem region:\n" 556 " - enables injects\n" 557 " - writes pattern injecting errors\n" 558 " - disables injects\n" 559 " - reads pattern back, generates error\n" 560 " - re-inits memory" 561 ); 562 #endif /* if defined(CONFIG_DDR_ECC) && defined(CONFIG_DDR_ECC_CMD) */ 563 564 #if defined(CONFIG_OF_FLAT_TREE) && defined(CONFIG_OF_BOARD_SETUP) 565 void 566 ft_board_setup(void *blob, bd_t *bd) 567 { 568 u32 *p; 569 int len; 570 571 #ifdef CONFIG_PCI 572 ft_pci_setup(blob, bd); 573 #endif 574 ft_cpu_setup(blob, bd); 575 576 p = ft_get_prop(blob, "/memory/reg", &len); 577 if (p != NULL) { 578 *p++ = cpu_to_be32(bd->bi_memstart); 579 *p = cpu_to_be32(bd->bi_memsize); 580 } 581 } 582 #endif 583