uboot/arch/i386/cpu/sc520/sc520_sdram.c
<<
>>
Prefs
   1/*
   2 * (C) Copyright 2010
   3 * Graeme Russ <graeme.russ@gmail.com>.
   4 *
   5 * See file CREDITS for list of people who contributed to this
   6 * project.
   7 *
   8 * This program is free software; you can redistribute it and/or
   9 * modify it under the terms of the GNU General Public License as
  10 * published by the Free Software Foundation; either version 2 of
  11 * the License, or (at your option) any later version.
  12 *
  13 * This program is distributed in the hope that it will be useful,
  14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16 * GNU General Public License for more details.
  17 *
  18 * You should have received a copy of the GNU General Public License
  19 * along with this program; if not, write to the Free Software
  20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  21 * MA 02111-1307 USA
  22 */
  23
  24#include <common.h>
  25#include <asm/io.h>
  26#include <asm/processor-flags.h>
  27#include <asm/ic/sc520.h>
  28
  29DECLARE_GLOBAL_DATA_PTR;
  30
  31struct sc520_sdram_info {
  32        u8 banks;
  33        u8 columns;
  34        u8 rows;
  35        u8 size;
  36};
  37
  38static void sc520_sizemem(void);
  39static void sc520_set_dram_timing(void);
  40static void sc520_set_dram_refresh_rate(void);
  41static void sc520_enable_dram_refresh(void);
  42static void sc520_enable_sdram(void);
  43#if CONFIG_SYS_SDRAM_ECC_ENABLE
  44static void sc520_enable_ecc(void)
  45#endif
  46
  47int dram_init_f(void)
  48{
  49        sc520_sizemem();
  50        sc520_set_dram_timing();
  51        sc520_set_dram_refresh_rate();
  52        sc520_enable_dram_refresh();
  53        sc520_enable_sdram();
  54#if CONFIG_SYS_SDRAM_ECC_ENABLE
  55        sc520_enable_ecc();
  56#endif
  57
  58        return 0;
  59}
  60
  61static inline void sc520_dummy_write(void)
  62{
  63        writew(0x0000, CACHELINESZ);
  64}
  65static inline void sc520_issue_sdram_op_mode_select(u8 command)
  66{
  67        writeb(command, &sc520_mmcr->drcctl);
  68        sc520_dummy_write();
  69}
  70
  71static inline int check_long(u32 test_long)
  72{
  73        u8 i;
  74        u8 tmp_byte = (u8)(test_long & 0x000000ff);
  75
  76        for (i = 1; i < 4; i++) {
  77                if ((u8)((test_long >> (i * 8)) & 0x000000ff) != tmp_byte)
  78                                return -1;
  79        }
  80
  81        return 0;
  82}
  83
  84static inline int write_and_test(u32 data, u32 address)
  85{
  86        writel(data, address);
  87        if (readl(address) == data)
  88                return 0; /* Good */
  89        else
  90                return -1; /* Bad */
  91}
  92
  93static void sc520_enable_sdram(void)
  94{
  95        u32 par_config;
  96
  97        /* Enable Writes, Caching and Code Execution to SDRAM */
  98        par_config = readl(&sc520_mmcr->par[3]);
  99        par_config &= ~(SC520_PAR_EXEC_DIS |
 100                        SC520_PAR_CACHE_DIS |
 101                        SC520_PAR_WRITE_DIS);
 102        writel(par_config, &sc520_mmcr->par[3]);
 103
 104        par_config = readl(&sc520_mmcr->par[4]);
 105        par_config &= ~(SC520_PAR_EXEC_DIS |
 106                        SC520_PAR_CACHE_DIS |
 107                        SC520_PAR_WRITE_DIS);
 108        writel(par_config, &sc520_mmcr->par[4]);
 109}
 110
 111static void sc520_set_dram_timing(void)
 112{
 113        u8 drctmctl = 0x00;
 114
 115#if defined CONFIG_SYS_SDRAM_DRCTMCTL
 116        /* just have your hardware designer _GIVE_ you what you need here! */
 117        drctmctl = CONFIG_SYS_SDRAM_DRCTMCTL;
 118#else
 119        switch (CONFIG_SYS_SDRAM_RAS_CAS_DELAY) {
 120        case 2:
 121                break;
 122        case 3:
 123                drctmctl |= 0x01;
 124                break;
 125        case 4:
 126        default:
 127                drctmctl |= 0x02;
 128                break;
 129        }
 130
 131        switch (CONFIG_SYS_SDRAM_PRECHARGE_DELAY) {
 132        case 2:
 133                break;
 134        case 3:
 135                drctmctl |= 0x04;
 136                break;
 137        case 4:
 138        default:
 139                drctmctl |= 0x08;
 140                break;
 141
 142        case 6:
 143                drctmctl |= 0x0c;
 144                break;
 145        }
 146
 147        switch (CONFIG_SYS_SDRAM_CAS_LATENCY) {
 148        case 2:
 149                break;
 150        case 3:
 151        default:
 152                drctmctl |= 0x10;
 153                break;
 154        }
 155#endif
 156        writeb(drctmctl, &sc520_mmcr->drctmctl);
 157
 158        /* Issue load mode register command */
 159        sc520_issue_sdram_op_mode_select(0x03);
 160}
 161
 162static void sc520_set_dram_refresh_rate(void)
 163{
 164        u8 drctl;
 165
 166        drctl = readb(&sc520_mmcr->drcctl);
 167        drctl &= 0xcf;
 168
 169        switch (CONFIG_SYS_SDRAM_REFRESH_RATE) {
 170        case 78:
 171                break;
 172        case 156:
 173        default:
 174                drctl |= 0x10;
 175                break;
 176        case 312:
 177                drctl |= 0x20;
 178                break;
 179        case 624:
 180                drctl |= 0x30;
 181                break;
 182        }
 183
 184        writeb(drctl, &sc520_mmcr->drcctl);
 185}
 186
 187static void sc520_enable_dram_refresh(void)
 188{
 189        u8 drctl;
 190
 191        drctl = readb(&sc520_mmcr->drcctl);
 192        drctl &= 0x30; /* keep refresh rate */
 193        drctl |= 0x08; /* enable refresh, normal mode */
 194
 195        writeb(drctl, &sc520_mmcr->drcctl);
 196}
 197
 198static void sc520_get_bank_info(int bank, struct sc520_sdram_info *bank_info)
 199{
 200        u32 col_data;
 201        u32 row_data;
 202
 203        u32 drcbendadr;
 204        u16 drccfg;
 205
 206        u8 banks = 0x00;
 207        u8 columns = 0x00;
 208        u8 rows = 0x00;
 209
 210        bank_info->banks = 0x00;
 211        bank_info->columns = 0x00;
 212        bank_info->rows = 0x00;
 213        bank_info->size = 0x00;
 214
 215        if ((bank < 0) || (bank > 3)) {
 216                printf("Bad Bank ID\n");
 217                return;
 218        }
 219
 220        /* Save configuration */
 221        drcbendadr = readl(&sc520_mmcr->drcbendadr);
 222        drccfg = readw(&sc520_mmcr->drccfg);
 223
 224        /* Setup SDRAM Bank to largest possible size */
 225        writew(0x000b << (bank * 4), &sc520_mmcr->drccfg);
 226
 227        /* Set ending address for this bank */
 228        writel(0x000000ff << (bank * 8), &sc520_mmcr->drcbendadr);
 229
 230        /* write col 11 wrap adr */
 231        if (write_and_test(COL11_DATA, COL11_ADR) != 0)
 232                goto restore_and_exit;
 233
 234        /* write col 10 wrap adr */
 235        if (write_and_test(COL10_DATA, COL10_ADR) != 0)
 236                goto restore_and_exit;
 237
 238        /* write col 9 wrap adr */
 239        if (write_and_test(COL09_DATA, COL09_ADR) != 0)
 240                goto restore_and_exit;
 241
 242        /* write col 8 wrap adr */
 243        if (write_and_test(COL08_DATA, COL08_ADR) != 0)
 244                goto restore_and_exit;
 245
 246        col_data = readl(COL11_ADR);
 247
 248        /* All four bytes in the read long must be the same */
 249        if (check_long(col_data) < 0)
 250                goto restore_and_exit;
 251
 252        if ((col_data >= COL08_DATA) && (col_data <= COL11_DATA))
 253                columns = (u8)(col_data & 0x000000ff);
 254        else
 255                goto restore_and_exit;
 256
 257        /* write row 14 wrap adr */
 258        if (write_and_test(ROW14_DATA, ROW14_ADR) != 0)
 259                goto restore_and_exit;
 260
 261        /* write row 13 wrap adr */
 262        if (write_and_test(ROW13_DATA, ROW13_ADR) != 0)
 263                goto restore_and_exit;
 264
 265        /* write row 12 wrap adr */
 266        if (write_and_test(ROW12_DATA, ROW12_ADR) != 0)
 267                goto restore_and_exit;
 268
 269        /* write row 11 wrap adr */
 270        if (write_and_test(ROW11_DATA, ROW11_ADR) != 0)
 271                goto restore_and_exit;
 272
 273        if (write_and_test(ROW10_DATA, ROW10_ADR) != 0)
 274                goto restore_and_exit;
 275
 276        /*
 277         * read data @ row 12 wrap adr to determine number of banks,
 278         * and read data @ row 14 wrap adr to determine number of rows.
 279         * if data @ row 12 wrap adr is not AA, 11 or 12 we have bad RAM.
 280         * if data @ row 12 wrap == AA, we only have 2 banks, NOT 4
 281         * if data @ row 12 wrap == 11 or 12, we have 4 banks,
 282         */
 283        row_data = readl(ROW12_ADR);
 284
 285        /* All four bytes in the read long must be the same */
 286        if (check_long(row_data) != 0)
 287                goto restore_and_exit;
 288
 289        switch (row_data) {
 290        case ROW10_DATA:
 291                banks = 2;
 292                break;
 293
 294        case ROW11_DATA:
 295        case ROW12_DATA:
 296                banks = 4;
 297                break;
 298
 299        default:
 300                goto restore_and_exit;
 301        }
 302
 303        row_data = readl(ROW14_ADR);
 304
 305        /* All four bytes in the read long must be the same */
 306        if (check_long(row_data) != 0)
 307                goto restore_and_exit;
 308
 309        switch (row_data) {
 310        case ROW11_DATA:
 311        case ROW12_DATA:
 312        case ROW13_DATA:
 313        case ROW14_DATA:
 314                rows = (u8)(row_data & 0x000000ff);
 315                break;
 316
 317        default:
 318                goto restore_and_exit;
 319        }
 320
 321        bank_info->banks = banks;
 322        bank_info->columns = columns;
 323        bank_info->rows = rows;
 324
 325        if ((bank_info->banks != 0) &&
 326            (bank_info->columns != 0) &&
 327            (bank_info->rows != 0)) {
 328                bank_info->size = bank_info->rows;
 329                bank_info->size >>= (11 - bank_info->columns);
 330                bank_info->size++;
 331        }
 332
 333restore_and_exit:
 334        /* Restore configuration */
 335        writel(drcbendadr, &sc520_mmcr->drcbendadr);
 336        writew(drccfg, &sc520_mmcr->drccfg);
 337}
 338
 339static void sc520_setup_sizemem(void)
 340{
 341        u8 i;
 342
 343        /* Disable write buffer */
 344        writeb(0x00, &sc520_mmcr->dbctl);
 345
 346        /* Disable ECC */
 347        writeb(0x00, &sc520_mmcr->eccctl);
 348
 349        /* Set slowest SDRAM timing */
 350        writeb(0x1e, &sc520_mmcr->drctmctl);
 351
 352        /* Issue a NOP to all SDRAM banks */
 353        sc520_issue_sdram_op_mode_select(0x01);
 354
 355        /* Delay for 100 microseconds */
 356        udelay(100);
 357
 358        /* Issue 'All Banks Precharge' command */
 359        sc520_issue_sdram_op_mode_select(0x02);
 360
 361        /* Issue 2 'Auto Refresh Enable' command */
 362        sc520_issue_sdram_op_mode_select(0x04);
 363        sc520_dummy_write();
 364
 365        /* Issue 'Load Mode Register' command */
 366        sc520_issue_sdram_op_mode_select(0x03);
 367
 368        /* Issue 8 more 'Auto Refresh Enable' commands */
 369        sc520_issue_sdram_op_mode_select(0x04);
 370        for (i = 0; i < 7; i++)
 371                sc520_dummy_write();
 372
 373        /* Set control register to 'Normal Mode' */
 374        writeb(0x00, &sc520_mmcr->drcctl);
 375}
 376
 377static void sc520_sizemem(void)
 378{
 379        struct sc520_sdram_info sdram_info[4];
 380        u8 bank_config = 0x00;
 381        u8 end_addr = 0x00;
 382        u16 drccfg = 0x0000;
 383        u32 drcbendadr = 0x00000000;
 384        u8 i;
 385
 386        /* Use PARs to disable caching of maximum allowable 256MB SDRAM */
 387        writel(SC520_SDRAM1_PAR | SC520_PAR_CACHE_DIS, &sc520_mmcr->par[3]);
 388        writel(SC520_SDRAM2_PAR | SC520_PAR_CACHE_DIS, &sc520_mmcr->par[4]);
 389
 390        sc520_setup_sizemem();
 391
 392        gd->ram_size = 0;
 393
 394        /* Size each SDRAM bank */
 395        for (i = 0; i <= 3; i++) {
 396                sc520_get_bank_info(i, &sdram_info[i]);
 397
 398                if (sdram_info[i].banks != 0) {
 399                        /* Update Configuration register */
 400                        bank_config = sdram_info[i].columns - 8;
 401
 402                        if (sdram_info[i].banks == 4)
 403                                bank_config |= 0x08;
 404
 405                        drccfg |= bank_config << (i * 4);
 406
 407                        /* Update End Address register */
 408                        end_addr += sdram_info[i].size;
 409                        drcbendadr |= (end_addr | 0x80) << (i * 8);
 410
 411                        gd->ram_size += sdram_info[i].size << 22;
 412                }
 413
 414                /* Issue 'All Banks Precharge' command */
 415                sc520_issue_sdram_op_mode_select(0x02);
 416
 417                /* Set control register to 'Normal Mode' */
 418                writeb(0x00, &sc520_mmcr->drcctl);
 419        }
 420
 421        writel(drcbendadr, &sc520_mmcr->drcbendadr);
 422        writew(drccfg, &sc520_mmcr->drccfg);
 423
 424        /* Clear PARs preventing caching of SDRAM */
 425        writel(0x00000000, &sc520_mmcr->par[3]);
 426        writel(0x00000000, &sc520_mmcr->par[4]);
 427}
 428
 429#if CONFIG_SYS_SDRAM_ECC_ENABLE
 430static void sc520_enable_ecc(void)
 431
 432        /* A nominal memory test: just a byte at each address line */
 433        movl    %eax, %ecx
 434        shrl    $0x1, %ecx
 435        movl    $0x1, %edi
 436memtest0:
 437        movb    $0xa5, (%edi)
 438        cmpb    $0xa5, (%edi)
 439        jne     out
 440        shrl    $0x1, %ecx
 441        andl    %ecx, %ecx
 442        jz      set_ecc
 443        shll    $0x1, %edi
 444        jmp     memtest0
 445
 446set_ecc:
 447        /* clear all ram with a memset */
 448        movl    %eax, %ecx
 449        xorl    %esi, %esi
 450        xorl    %edi, %edi
 451        xorl    %eax, %eax
 452        shrl    $0x2, %ecx
 453        cld
 454        rep     stosl
 455
 456        /* enable read, write buffers */
 457        movb    $0x11, %al
 458        movl    $DBCTL, %edi
 459        movb    %al, (%edi)
 460
 461        /* enable NMI mapping for ECC */
 462        movl    $ECCINT, %edi
 463        movb    $0x10, %al
 464        movb    %al, (%edi)
 465
 466        /* Turn on ECC */
 467        movl    $ECCCTL, %edi
 468        movb    $0x05, %al
 469        movb    %al,(%edi)
 470
 471out:
 472        jmp     init_ecc_ret
 473}
 474#endif
 475
 476int dram_init(void)
 477{
 478        ulong dram_ctrl;
 479        ulong dram_present = 0x00000000;
 480
 481        /*
 482         * We read-back the configuration of the dram
 483         * controller that the assembly code wrote
 484         */
 485        dram_ctrl = readl(&sc520_mmcr->drcbendadr);
 486
 487        gd->bd->bi_dram[0].start = 0;
 488        if (dram_ctrl & 0x80) {
 489                /* bank 0 enabled */
 490                gd->bd->bi_dram[1].start = (dram_ctrl & 0x7f) << 22;
 491                dram_present = gd->bd->bi_dram[1].start;
 492                gd->bd->bi_dram[0].size = gd->bd->bi_dram[1].start;
 493        } else {
 494                gd->bd->bi_dram[0].size = 0;
 495                gd->bd->bi_dram[1].start = gd->bd->bi_dram[0].start;
 496        }
 497
 498        if (dram_ctrl & 0x8000) {
 499                /* bank 1 enabled */
 500                gd->bd->bi_dram[2].start = (dram_ctrl & 0x7f00) << 14;
 501                dram_present = gd->bd->bi_dram[2].start;
 502                gd->bd->bi_dram[1].size = gd->bd->bi_dram[2].start -
 503                                gd->bd->bi_dram[1].start;
 504        } else {
 505                gd->bd->bi_dram[1].size = 0;
 506                gd->bd->bi_dram[2].start = gd->bd->bi_dram[1].start;
 507        }
 508
 509        if (dram_ctrl & 0x800000) {
 510                /* bank 2 enabled */
 511                gd->bd->bi_dram[3].start = (dram_ctrl & 0x7f0000) << 6;
 512                dram_present = gd->bd->bi_dram[3].start;
 513                gd->bd->bi_dram[2].size = gd->bd->bi_dram[3].start -
 514                                gd->bd->bi_dram[2].start;
 515        } else {
 516                gd->bd->bi_dram[2].size = 0;
 517                gd->bd->bi_dram[3].start = gd->bd->bi_dram[2].start;
 518        }
 519
 520        if (dram_ctrl & 0x80000000) {
 521                /* bank 3 enabled */
 522                dram_present  = (dram_ctrl & 0x7f000000) >> 2;
 523                gd->bd->bi_dram[3].size = dram_present -
 524                                gd->bd->bi_dram[3].start;
 525        } else {
 526                gd->bd->bi_dram[3].size = 0;
 527        }
 528
 529        gd->ram_size = dram_present;
 530
 531        return 0;
 532}
 533