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