uboot/arch/x86/cpu/sc520/sc520_sdram.c
<<
>>
Prefs
   1/*
   2 * (C) Copyright 2010,2011
   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/arch/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
  44int dram_init_f(void)
  45{
  46        sc520_sizemem();
  47        sc520_set_dram_timing();
  48        sc520_set_dram_refresh_rate();
  49        sc520_enable_dram_refresh();
  50        sc520_enable_sdram();
  51
  52        return 0;
  53}
  54
  55static inline void sc520_dummy_write(void)
  56{
  57        writew(0x0000, CACHELINESZ);
  58}
  59static inline void sc520_issue_sdram_op_mode_select(u8 command)
  60{
  61        writeb(command, &sc520_mmcr->drcctl);
  62        sc520_dummy_write();
  63}
  64
  65static inline int check_long(u32 test_long)
  66{
  67        u8 i;
  68        u8 tmp_byte = (u8)(test_long & 0x000000ff);
  69
  70        for (i = 1; i < 4; i++) {
  71                if ((u8)((test_long >> (i * 8)) & 0x000000ff) != tmp_byte)
  72                                return -1;
  73        }
  74
  75        return 0;
  76}
  77
  78static inline int write_and_test(u32 data, u32 address)
  79{
  80        writel(data, address);
  81        if (readl(address) == data)
  82                return 0; /* Good */
  83        else
  84                return -1; /* Bad */
  85}
  86
  87static void sc520_enable_sdram(void)
  88{
  89        u32 par_config;
  90
  91        /* Enable Writes, Caching and Code Execution to SDRAM */
  92        par_config = readl(&sc520_mmcr->par[3]);
  93        par_config &= ~(SC520_PAR_EXEC_DIS |
  94                        SC520_PAR_CACHE_DIS |
  95                        SC520_PAR_WRITE_DIS);
  96        writel(par_config, &sc520_mmcr->par[3]);
  97
  98        par_config = readl(&sc520_mmcr->par[4]);
  99        par_config &= ~(SC520_PAR_EXEC_DIS |
 100                        SC520_PAR_CACHE_DIS |
 101                        SC520_PAR_WRITE_DIS);
 102        writel(par_config, &sc520_mmcr->par[4]);
 103}
 104
 105static void sc520_set_dram_timing(void)
 106{
 107        u8 drctmctl = 0x00;
 108
 109#if defined CONFIG_SYS_SDRAM_DRCTMCTL
 110        /* just have your hardware designer _GIVE_ you what you need here! */
 111        drctmctl = CONFIG_SYS_SDRAM_DRCTMCTL;
 112#else
 113        switch (CONFIG_SYS_SDRAM_RAS_CAS_DELAY) {
 114        case 2:
 115                break;
 116        case 3:
 117                drctmctl |= 0x01;
 118                break;
 119        case 4:
 120        default:
 121                drctmctl |= 0x02;
 122                break;
 123        }
 124
 125        switch (CONFIG_SYS_SDRAM_PRECHARGE_DELAY) {
 126        case 2:
 127                break;
 128        case 3:
 129                drctmctl |= 0x04;
 130                break;
 131        case 4:
 132        default:
 133                drctmctl |= 0x08;
 134                break;
 135
 136        case 6:
 137                drctmctl |= 0x0c;
 138                break;
 139        }
 140
 141        switch (CONFIG_SYS_SDRAM_CAS_LATENCY) {
 142        case 2:
 143                break;
 144        case 3:
 145        default:
 146                drctmctl |= 0x10;
 147                break;
 148        }
 149#endif
 150        writeb(drctmctl, &sc520_mmcr->drctmctl);
 151
 152        /* Issue load mode register command */
 153        sc520_issue_sdram_op_mode_select(0x03);
 154}
 155
 156static void sc520_set_dram_refresh_rate(void)
 157{
 158        u8 drctl;
 159
 160        drctl = readb(&sc520_mmcr->drcctl);
 161        drctl &= 0xcf;
 162
 163        switch (CONFIG_SYS_SDRAM_REFRESH_RATE) {
 164        case 78:
 165                break;
 166        case 156:
 167        default:
 168                drctl |= 0x10;
 169                break;
 170        case 312:
 171                drctl |= 0x20;
 172                break;
 173        case 624:
 174                drctl |= 0x30;
 175                break;
 176        }
 177
 178        writeb(drctl, &sc520_mmcr->drcctl);
 179}
 180
 181static void sc520_enable_dram_refresh(void)
 182{
 183        u8 drctl;
 184
 185        drctl = readb(&sc520_mmcr->drcctl);
 186        drctl &= 0x30; /* keep refresh rate */
 187        drctl |= 0x08; /* enable refresh, normal mode */
 188
 189        writeb(drctl, &sc520_mmcr->drcctl);
 190}
 191
 192static void sc520_get_bank_info(int bank, struct sc520_sdram_info *bank_info)
 193{
 194        u32 col_data;
 195        u32 row_data;
 196
 197        u32 drcbendadr;
 198        u16 drccfg;
 199
 200        u8 banks = 0x00;
 201        u8 columns = 0x00;
 202        u8 rows = 0x00;
 203
 204        bank_info->banks = 0x00;
 205        bank_info->columns = 0x00;
 206        bank_info->rows = 0x00;
 207        bank_info->size = 0x00;
 208
 209        if ((bank < 0) || (bank > 3)) {
 210                printf("Bad Bank ID\n");
 211                return;
 212        }
 213
 214        /* Save configuration */
 215        drcbendadr = readl(&sc520_mmcr->drcbendadr);
 216        drccfg = readw(&sc520_mmcr->drccfg);
 217
 218        /* Setup SDRAM Bank to largest possible size */
 219        writew(0x000b << (bank * 4), &sc520_mmcr->drccfg);
 220
 221        /* Set ending address for this bank */
 222        writel(0x000000ff << (bank * 8), &sc520_mmcr->drcbendadr);
 223
 224        /* write col 11 wrap adr */
 225        if (write_and_test(COL11_DATA, COL11_ADR) != 0)
 226                goto restore_and_exit;
 227
 228        /* write col 10 wrap adr */
 229        if (write_and_test(COL10_DATA, COL10_ADR) != 0)
 230                goto restore_and_exit;
 231
 232        /* write col 9 wrap adr */
 233        if (write_and_test(COL09_DATA, COL09_ADR) != 0)
 234                goto restore_and_exit;
 235
 236        /* write col 8 wrap adr */
 237        if (write_and_test(COL08_DATA, COL08_ADR) != 0)
 238                goto restore_and_exit;
 239
 240        col_data = readl(COL11_ADR);
 241
 242        /* All four bytes in the read long must be the same */
 243        if (check_long(col_data) < 0)
 244                goto restore_and_exit;
 245
 246        if ((col_data >= COL08_DATA) && (col_data <= COL11_DATA))
 247                columns = (u8)(col_data & 0x000000ff);
 248        else
 249                goto restore_and_exit;
 250
 251        /* write row 14 wrap adr */
 252        if (write_and_test(ROW14_DATA, ROW14_ADR) != 0)
 253                goto restore_and_exit;
 254
 255        /* write row 13 wrap adr */
 256        if (write_and_test(ROW13_DATA, ROW13_ADR) != 0)
 257                goto restore_and_exit;
 258
 259        /* write row 12 wrap adr */
 260        if (write_and_test(ROW12_DATA, ROW12_ADR) != 0)
 261                goto restore_and_exit;
 262
 263        /* write row 11 wrap adr */
 264        if (write_and_test(ROW11_DATA, ROW11_ADR) != 0)
 265                goto restore_and_exit;
 266
 267        if (write_and_test(ROW10_DATA, ROW10_ADR) != 0)
 268                goto restore_and_exit;
 269
 270        /*
 271         * read data @ row 12 wrap adr to determine number of banks,
 272         * and read data @ row 14 wrap adr to determine number of rows.
 273         * if data @ row 12 wrap adr is not AA, 11 or 12 we have bad RAM.
 274         * if data @ row 12 wrap == AA, we only have 2 banks, NOT 4
 275         * if data @ row 12 wrap == 11 or 12, we have 4 banks,
 276         */
 277        row_data = readl(ROW12_ADR);
 278
 279        /* All four bytes in the read long must be the same */
 280        if (check_long(row_data) != 0)
 281                goto restore_and_exit;
 282
 283        switch (row_data) {
 284        case ROW10_DATA:
 285                banks = 2;
 286                break;
 287
 288        case ROW11_DATA:
 289        case ROW12_DATA:
 290                banks = 4;
 291                break;
 292
 293        default:
 294                goto restore_and_exit;
 295        }
 296
 297        row_data = readl(ROW14_ADR);
 298
 299        /* All four bytes in the read long must be the same */
 300        if (check_long(row_data) != 0)
 301                goto restore_and_exit;
 302
 303        switch (row_data) {
 304        case ROW11_DATA:
 305        case ROW12_DATA:
 306        case ROW13_DATA:
 307        case ROW14_DATA:
 308                rows = (u8)(row_data & 0x000000ff);
 309                break;
 310
 311        default:
 312                goto restore_and_exit;
 313        }
 314
 315        bank_info->banks = banks;
 316        bank_info->columns = columns;
 317        bank_info->rows = rows;
 318
 319        if ((bank_info->banks != 0) &&
 320            (bank_info->columns != 0) &&
 321            (bank_info->rows != 0)) {
 322                bank_info->size = bank_info->rows;
 323                bank_info->size >>= (11 - bank_info->columns);
 324                bank_info->size++;
 325        }
 326
 327restore_and_exit:
 328        /* Restore configuration */
 329        writel(drcbendadr, &sc520_mmcr->drcbendadr);
 330        writew(drccfg, &sc520_mmcr->drccfg);
 331}
 332
 333static void sc520_setup_sizemem(void)
 334{
 335        u8 i;
 336
 337        /* Disable write buffer */
 338        writeb(0x00, &sc520_mmcr->dbctl);
 339
 340        /* Disable ECC */
 341        writeb(0x00, &sc520_mmcr->eccctl);
 342
 343        /* Set slowest SDRAM timing */
 344        writeb(0x1e, &sc520_mmcr->drctmctl);
 345
 346        /* Issue a NOP to all SDRAM banks */
 347        sc520_issue_sdram_op_mode_select(0x01);
 348
 349        /* Delay for 100 microseconds */
 350        udelay(100);
 351
 352        /* Issue 'All Banks Precharge' command */
 353        sc520_issue_sdram_op_mode_select(0x02);
 354
 355        /* Issue 2 'Auto Refresh Enable' command */
 356        sc520_issue_sdram_op_mode_select(0x04);
 357        sc520_dummy_write();
 358
 359        /* Issue 'Load Mode Register' command */
 360        sc520_issue_sdram_op_mode_select(0x03);
 361
 362        /* Issue 8 more 'Auto Refresh Enable' commands */
 363        sc520_issue_sdram_op_mode_select(0x04);
 364        for (i = 0; i < 7; i++)
 365                sc520_dummy_write();
 366
 367        /* Set control register to 'Normal Mode' */
 368        writeb(0x00, &sc520_mmcr->drcctl);
 369}
 370
 371static void sc520_sizemem(void)
 372{
 373        struct sc520_sdram_info sdram_info[4];
 374        u8 bank_config = 0x00;
 375        u8 end_addr = 0x00;
 376        u16 drccfg = 0x0000;
 377        u32 drcbendadr = 0x00000000;
 378        u8 i;
 379
 380        /* Use PARs to disable caching of maximum allowable 256MB SDRAM */
 381        writel(SC520_SDRAM1_PAR | SC520_PAR_CACHE_DIS, &sc520_mmcr->par[3]);
 382        writel(SC520_SDRAM2_PAR | SC520_PAR_CACHE_DIS, &sc520_mmcr->par[4]);
 383
 384        sc520_setup_sizemem();
 385
 386        gd->ram_size = 0;
 387
 388        /* Size each SDRAM bank */
 389        for (i = 0; i <= 3; i++) {
 390                sc520_get_bank_info(i, &sdram_info[i]);
 391
 392                if (sdram_info[i].banks != 0) {
 393                        /* Update Configuration register */
 394                        bank_config = sdram_info[i].columns - 8;
 395
 396                        if (sdram_info[i].banks == 4)
 397                                bank_config |= 0x08;
 398
 399                        drccfg |= bank_config << (i * 4);
 400
 401                        /* Update End Address register */
 402                        end_addr += sdram_info[i].size;
 403                        drcbendadr |= (end_addr | 0x80) << (i * 8);
 404
 405                        gd->ram_size += sdram_info[i].size << 22;
 406                }
 407
 408                /* Issue 'All Banks Precharge' command */
 409                sc520_issue_sdram_op_mode_select(0x02);
 410
 411                /* Set control register to 'Normal Mode' */
 412                writeb(0x00, &sc520_mmcr->drcctl);
 413        }
 414
 415        writel(drcbendadr, &sc520_mmcr->drcbendadr);
 416        writew(drccfg, &sc520_mmcr->drccfg);
 417
 418        /* Clear PARs preventing caching of SDRAM */
 419        writel(0x00000000, &sc520_mmcr->par[3]);
 420        writel(0x00000000, &sc520_mmcr->par[4]);
 421}
 422
 423int dram_init(void)
 424{
 425        ulong dram_ctrl;
 426        ulong dram_present = 0x00000000;
 427
 428        /*
 429         * We read-back the configuration of the dram
 430         * controller that the assembly code wrote
 431         */
 432        dram_ctrl = readl(&sc520_mmcr->drcbendadr);
 433
 434        gd->bd->bi_dram[0].start = 0;
 435        if (dram_ctrl & 0x80) {
 436                /* bank 0 enabled */
 437                gd->bd->bi_dram[1].start = (dram_ctrl & 0x7f) << 22;
 438                dram_present = gd->bd->bi_dram[1].start;
 439                gd->bd->bi_dram[0].size = gd->bd->bi_dram[1].start;
 440        } else {
 441                gd->bd->bi_dram[0].size = 0;
 442                gd->bd->bi_dram[1].start = gd->bd->bi_dram[0].start;
 443        }
 444
 445        if (dram_ctrl & 0x8000) {
 446                /* bank 1 enabled */
 447                gd->bd->bi_dram[2].start = (dram_ctrl & 0x7f00) << 14;
 448                dram_present = gd->bd->bi_dram[2].start;
 449                gd->bd->bi_dram[1].size = gd->bd->bi_dram[2].start -
 450                                gd->bd->bi_dram[1].start;
 451        } else {
 452                gd->bd->bi_dram[1].size = 0;
 453                gd->bd->bi_dram[2].start = gd->bd->bi_dram[1].start;
 454        }
 455
 456        if (dram_ctrl & 0x800000) {
 457                /* bank 2 enabled */
 458                gd->bd->bi_dram[3].start = (dram_ctrl & 0x7f0000) << 6;
 459                dram_present = gd->bd->bi_dram[3].start;
 460                gd->bd->bi_dram[2].size = gd->bd->bi_dram[3].start -
 461                                gd->bd->bi_dram[2].start;
 462        } else {
 463                gd->bd->bi_dram[2].size = 0;
 464                gd->bd->bi_dram[3].start = gd->bd->bi_dram[2].start;
 465        }
 466
 467        if (dram_ctrl & 0x80000000) {
 468                /* bank 3 enabled */
 469                dram_present  = (dram_ctrl & 0x7f000000) >> 2;
 470                gd->bd->bi_dram[3].size = dram_present -
 471                                gd->bd->bi_dram[3].start;
 472        } else {
 473                gd->bd->bi_dram[3].size = 0;
 474        }
 475
 476        gd->ram_size = dram_present;
 477
 478        return 0;
 479}
 480