uboot/board/freescale/mpc7448hpc2/asm_init.S
<<
>>
Prefs
   1/*
   2 * (C) Copyright 2004-05;  Tundra Semiconductor Corp.
   3 *
   4 * Added automatic detect of SDC settings
   5 * Copyright (c) 2005 Freescale Semiconductor, Inc.
   6 * Maintainer tie-fei.zang@freescale.com
   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/*
  25 * FILENAME: asm_init.s
  26 *
  27 * Originator: Alex Bounine
  28 *
  29 * DESCRIPTION:
  30 * Initialization code for the Tundra Tsi108 bridge chip
  31 *
  32 */
  33
  34#include <config.h>
  35#include <version.h>
  36
  37#include <ppc_asm.tmpl>
  38#include <ppc_defs.h>
  39#include <asm/processor.h>
  40
  41#include <tsi108.h>
  42
  43/*
  44 * Build Configuration Options
  45 */
  46
  47/* #define DISABLE_PBM          disables usage of PB Master */
  48/* #define SDC_HARDCODED_INIT   config SDRAM controller with hardcoded values */
  49/* #define SDC_AUTOPRECH_EN     enable SDRAM auto precharge */
  50
  51/*
  52 * Hardcoded SDC settings
  53 */
  54
  55#ifdef SDC_HARDCODED_INIT
  56
  57/* Micron MT9HTF6472AY-40EA1 : Unbuffered, 512MB, 400, CL3, Single Rank */
  58
  59#define VAL_SD_REFRESH  (0x61A)
  60#define VAL_SD_TIMING   (0x0308336b)
  61#define VAL_SD_D0_CTRL  (0x07100021)    /* auto-precharge disabled */
  62#define VAL_SD_D0_BAR   (0x0FE00000)    /* 512MB @ 0x00000000 */
  63#define VAL_SD_D1_CTRL  (0x07100021)    /* auto-precharge disabled */
  64#define VAL_SD_D1_BAR   (0x0FE00200)    /* 512MB @ 0x20000000 */
  65
  66#endif /* SDC_HARDCODED_INIT */
  67
  68/*
  69 CPU Configuration:
  70
  71 CPU Address and Data Parity enables.
  72
  73#define CPU_AP
  74#define CPU_DP
  75*/
  76
  77/*
  78 * Macros
  79 * !!! Attention !!! Macros LOAD_PTR, LOAD_U32 and LOAD_MEM defined below are
  80 * expected to work correctly for the CSR space within 32KB range.
  81 *
  82 * LOAD_PTR and LOAD_U32 - load specified register with a 32 bit constant.
  83 * These macros are absolutely identical except their names. This difference
  84 * is provided intentionally for better readable code.
  85 */
  86
  87#define LOAD_PTR(reg,const32) \
  88        addis reg,r0,const32@h; ori reg,reg,const32@l
  89
  90#define LOAD_U32(reg,const32) \
  91        addis reg,r0,const32@h; ori reg,reg,const32@l
  92
  93/* LOADMEM initializes a register with the contents of a specified 32-bit
  94 * memory location, usually a CSR value.
  95 */
  96
  97#define LOAD_MEM(reg,addr32) \
  98        addis reg,r0,addr32@ha; lwz reg,addr32@l(reg)
  99
 100#ifndef SDC_HARDCODED_INIT
 101sdc_clk_sync:
 102        /* MHz: 0,0,183,100,133,167,200,233 */
 103        .long   0, 0, 6, 10, 8, 6, 5, 4         /* nSec */
 104#endif
 105
 106/*
 107 * board_asm_init() - early initialization function. Coded to be portable to
 108 * dual-CPU configuration.
 109 * Checks CPU number and performs board HW initialization if called for CPU0.
 110 * Registers used: r3,r4,r5,r6,r19,r29
 111 *
 112 * NOTE: For dual-CPU configuration only CPU0 is allowed to configure Tsi108
 113 * and the rest of the board. Current implementation demonstrates two
 114 * possible ways to identify CPU number:
 115 * - for MPC74xx platform: uses MSSCR0[ID] bit as defined in UM.
 116 * - for PPC750FX/GX boards: uses WHO_AM_I bit reported by Tsi108.
 117 */
 118
 119        .globl board_asm_init
 120board_asm_init:
 121        mflr    r19     /* Save LR to be able return later. */
 122        bl      icache_enable   /* Enable icache to reduce reads from flash. */
 123
 124/* Initialize pointer to Tsi108 register space */
 125
 126        LOAD_PTR(r29,CONFIG_SYS_TSI108_CSR_RST_BASE)/* r29 - pointer to tsi108 CSR space */
 127        ori r4,r29,TSI108_PB_REG_OFFSET
 128
 129/* Check Processor Version Number */
 130
 131        mfspr   r3, PVR
 132        rlwinm  r3,r3,16,16,23  /* get ((Processor Version Number) & 0xFF00) */
 133
 134        cmpli   0,0,r3,0x8000   /* MPC74xx */
 135        bne     cont_brd_init
 136
 137        /*
 138         * For MPC744x/5x enable extended BATs[4-7]
 139         * Sri: Set HIGH_BAT_EN and XBSEN, and SPD =1
 140         * to disable prefetch
 141         */
 142
 143        mfspr   r5, HID0
 144        oris    r5, r5, 0x0080  /* Set HID0[HIGH_BAT_EN] bit #8 */
 145        ori     r5, r5, 0x0380  /* Set SPD,XBSEN,SGE bits #22,23,24 */
 146        mtspr   HID0, r5
 147        isync
 148        sync
 149
 150        /* Adding code to disable external interventions in MPX bus mode */
 151        mfspr   r3, 1014
 152        oris    r3, r3, 0x0100  /* Set the EIDIS bit in MSSCR0:  bit 7 */
 153        mtspr   1014, r3
 154        isync
 155        sync
 156
 157        /* Sri: code to enable FP unit */
 158        mfmsr   r3
 159        ori     r3, r3, 0x2000
 160        mtmsr   r3
 161        isync
 162        sync
 163
 164        /* def CONFIG_DUAL_CPU
 165         * For MPC74xx processor, use MSSCR0[ID] bit to identify CPU number.
 166         */
 167#if(1)
 168        mfspr   r3,1014         /* read MSSCR0 */
 169        rlwinm. r3,r3,27,31,31  /* get processor ID number */
 170        mtspr   SPRN_PIR,r3     /* Save CPU ID */
 171        sync
 172        bne     init_done
 173        b       do_tsi108_init
 174
 175cont_brd_init:
 176
 177        /* An alternative method of checking the processor number (in addition
 178         * to configuration using MSSCR0[ID] bit on MPC74xx).
 179         * Good for IBM PPC750FX/GX.
 180         */
 181
 182        lwz     r3,PB_BUS_MS_SELECT(r4) /* read PB_ID register */
 183        rlwinm. r3,r3,24,31,31          /* get processor ID number */
 184        bne init_done
 185#else
 186
 187cont_brd_init:
 188
 189#endif /* CONFIG_DUAL_CPU */
 190
 191        /* Initialize Tsi108 chip */
 192
 193do_tsi108_init:
 194
 195        /*
 196         * Adjust HLP/Flash parameters. By default after reset the HLP port is
 197         * set to support slow devices. Better performance can be achived when
 198         * an optimal parameters are used for specific EPROM device.
 199         * NOTE: This should be performed ASAP for the emulation platform
 200         * because it has 5MHz HLP clocking.
 201         */
 202
 203#ifdef CONFIG_TSI108EMU
 204        ori     r4,r29,TSI108_HLP_REG_OFFSET
 205        LOAD_U32(r5,0x434422c0)
 206        stw     r5,0x08(r4)     /* set HLP B0_CTRL0 */
 207        sync
 208        LOAD_U32(r5,0xd0012000)
 209        stw     r5,0x0c(r4)             /* set HLP B0_CTRL1 */
 210        sync
 211#endif
 212
 213        /* Initialize PB interface. */
 214
 215        ori r4,r29,TSI108_PB_REG_OFFSET
 216
 217#if (CONFIG_SYS_TSI108_CSR_BASE != CONFIG_SYS_TSI108_CSR_RST_BASE)
 218        /* Relocate (if required) Tsi108 registers. Set new value for
 219         * PB_REG_BAR:
 220         * Note we are in the 32-bit address mode.
 221         */
 222        LOAD_U32(r5,(CONFIG_SYS_TSI108_CSR_BASE | 0x01)) /* PB_REG_BAR: BA + EN */
 223        stw     r5,PB_REG_BAR(r4)
 224        andis.  r29,r5,0xFFFF
 225        sync
 226        ori     r4,r29,TSI108_PB_REG_OFFSET
 227#endif
 228
 229        /* Set PB Slave configuration register */
 230
 231        LOAD_U32(r5,0x00002481) /* PB_SCR: TEA enabled,AACK delay = 1 */
 232        lwz     r3, PB_RSR(r4)  /* get PB bus mode */
 233        xori    r3,r3,0x0001    /* mask PB_BMODE: r3 -> (0 = 60X, 1 = MPX) */
 234        rlwimi  r5,r3,14,17,17  /* for MPX: set DTI_MODE bit */
 235        stw     r5,PB_SCR(r4)
 236        sync
 237
 238        /* Configure PB Arbiter */
 239
 240        lwz     r5,PB_ARB_CTRL(r4)      /* Read PB Arbiter Control Register */
 241        li      r3, 0x00F0              /* ARB_PIPELINE_DEP mask */
 242#ifdef DISABLE_PBM
 243        ori     r3,r3,0x1000    /* add PBM_EN to clear (enabled by default) */
 244#endif
 245        andc    r5,r5,r3        /* Clear the masked bit fields */
 246        ori     r5,r5,0x0001    /* Set pipeline depth */
 247        stw     r5,PB_ARB_CTRL(r4)
 248
 249#if (0) /* currently using the default settings for PBM after reset */
 250        LOAD_U32(r5,0x)         /* value for PB_MCR */
 251        stw     r5,PB_MCR(r4)
 252        sync
 253
 254        LOAD_U32(r5,0x)         /* value for PB_MCMD */
 255        stw     r5,PB_MCMD(r4)
 256        sync
 257#endif
 258
 259        /* Disable or enable PVT based on processor bus frequency
 260         * 1. Read CG_PWRUP_STATUS register field bits 18,17,16
 261         * 2. See if the value is < or > 133mhz (18:16 = 100)
 262         * 3. If > enable PVT
 263         */
 264
 265        LOAD_U32(r3,0xC0002234)
 266        lwz     r3,0(r3)
 267        rlwinm  r3,r3,16,29,31
 268
 269        cmpi    0,0,r3,0x0004
 270        bgt     sdc_init
 271
 272#ifndef CONFIG_TSI108EMU
 273        /* FIXME: Disable PB calibration control for any real Tsi108 board */
 274        li      r5,0x0101       /* disable calibration control */
 275        stw     r5,PB_PVT_CTRL2(r4)
 276        sync
 277#endif
 278
 279        /* Initialize SDRAM controller. */
 280
 281sdc_init:
 282
 283#ifndef SDC_HARDCODED_INIT
 284        /* get SDC clock prior doing sdram controller autoconfig */
 285        ori     r4,r29,TSI108_CLK_REG_OFFSET    /* r4 - ptr to CG registers */
 286        lwz     r3, CG_PWRUP_STATUS(r4)         /* get CG configuration */
 287        rlwinm  r3,r3,12,29,31                  /* r3 - SD clk */
 288        lis     r5,sdc_clk_sync@h
 289        ori     r5,r5,sdc_clk_sync@l
 290        /* Sri:  At this point check if r3 = 001. If yes,
 291         * the memory frequency should be same as the
 292         * MPX bus frequency
 293         */
 294        cmpi    0,0,r3,0x0001
 295        bne     get_nsec
 296        lwz     r6, CG_PWRUP_STATUS(r4)
 297        rlwinm  r6,r6,16,29,31
 298        mr      r3,r6
 299
 300get_nsec:
 301        rlwinm  r3,r3,2,0,31
 302        lwzx    r9,r5,r3        /* get SD clk rate in nSec */
 303        /* ATTN: r9 will be used by SPD routine */
 304#endif /* !SDC_HARDCODED_INIT */
 305
 306        ori     r4,r29,TSI108_SD_REG_OFFSET /* r4 - ptr to SDRAM registers */
 307
 308        /* Initialize SDRAM controller. SDRAM Size = 512MB, One DIMM. */
 309
 310        LOAD_U32(r5,0x00)
 311        stw     r5,SD_INT_ENABLE(r4) /* Ensure that interrupts are disabled */
 312#ifdef ENABLE_SDRAM_ECC
 313        li      r5, 0x01
 314#endif /* ENABLE_SDRAM_ECC */
 315        stw     r5,SD_ECC_CTRL(r4)      /* Enable/Disable ECC */
 316        sync
 317
 318#ifdef SDC_HARDCODED_INIT /* config sdram controller with hardcoded values */
 319
 320        /* First read the CG_PWRUP_STATUS register to get the
 321         * memory speed from bits 22,21,20
 322         */
 323
 324        LOAD_U32(r3,0xC0002234)
 325        lwz     r3,0(r3)
 326        rlwinm  r3,r3,12,29,31
 327
 328        /* Now first check for 166, then 200, or default */
 329
 330        cmpi    0,0,r3,0x0005
 331        bne     check_for_200mhz
 332
 333        /* set values for 166 Mhz memory speed
 334         * Set refresh rate and timing parameters
 335         */
 336        LOAD_U32(r5,0x00000515)
 337        stw     r5,SD_REFRESH(r4)
 338        LOAD_U32(r5,0x03073368)
 339        stw     r5,SD_TIMING(r4)
 340        sync
 341
 342        /* Initialize DIMM0 control and BAR registers */
 343        LOAD_U32(r5,VAL_SD_D0_CTRL)     /* auto-precharge disabled */
 344#ifdef SDC_AUTOPRECH_EN
 345        oris    r5,r5,0x0001            /* set auto precharge EN bit */
 346#endif
 347        stw     r5,SD_D0_CTRL(r4)
 348        LOAD_U32(r5,VAL_SD_D0_BAR)
 349        stw     r5,SD_D0_BAR(r4)
 350        sync
 351
 352        /* Initialize DIMM1 control and BAR registers
 353         * (same as dimm 0, next 512MB, disabled)
 354         */
 355        LOAD_U32(r5,VAL_SD_D1_CTRL)     /* auto-precharge disabled */
 356#ifdef SDC_AUTOPRECH_EN
 357        oris    r5,r5,0x0001    /* set auto precharge EN bit */
 358#endif
 359        stw     r5,SD_D1_CTRL(r4)
 360        LOAD_U32(r5,VAL_SD_D1_BAR)
 361        stw     r5,SD_D1_BAR(r4)
 362        sync
 363
 364        b       sdc_init_done
 365
 366check_for_200mhz:
 367
 368        cmpi    0,0,r3,0x0006
 369        bne     set_default_values
 370
 371        /* set values for 200Mhz memory speed
 372         * Set refresh rate and timing parameters
 373         */
 374        LOAD_U32(r5,0x0000061a)
 375        stw     r5,SD_REFRESH(r4)
 376        LOAD_U32(r5,0x03083348)
 377        stw     r5,SD_TIMING(r4)
 378        sync
 379
 380        /* Initialize DIMM0 control and BAR registers */
 381        LOAD_U32(r5,VAL_SD_D0_CTRL)     /* auto-precharge disabled */
 382#ifdef SDC_AUTOPRECH_EN
 383        oris    r5,r5,0x0001            /* set auto precharge EN bit */
 384#endif
 385        stw     r5,SD_D0_CTRL(r4)
 386        LOAD_U32(r5,VAL_SD_D0_BAR)
 387        stw     r5,SD_D0_BAR(r4)
 388        sync
 389
 390        /* Initialize DIMM1 control and BAR registers
 391         * (same as dimm 0, next 512MB, disabled)
 392         */
 393        LOAD_U32(r5,VAL_SD_D1_CTRL)     /* auto-precharge disabled */
 394#ifdef SDC_AUTOPRECH_EN
 395        oris    r5,r5,0x0001            /* set auto precharge EN bit */
 396#endif
 397        stw     r5,SD_D1_CTRL(r4)
 398        LOAD_U32(r5,VAL_SD_D1_BAR)
 399        stw     r5,SD_D1_BAR(r4)
 400        sync
 401
 402        b       sdc_init_done
 403
 404set_default_values:
 405
 406        /* Set refresh rate and timing parameters */
 407        LOAD_U32(r5,VAL_SD_REFRESH)
 408        stw     r5,SD_REFRESH(r4)
 409        LOAD_U32(r5,VAL_SD_TIMING)
 410        stw     r5,SD_TIMING(r4)
 411        sync
 412
 413        /* Initialize DIMM0 control and BAR registers */
 414        LOAD_U32(r5,VAL_SD_D0_CTRL)     /* auto-precharge disabled */
 415#ifdef SDC_AUTOPRECH_EN
 416        oris    r5,r5,0x0001            /* set auto precharge EN bit */
 417#endif
 418        stw     r5,SD_D0_CTRL(r4)
 419        LOAD_U32(r5,VAL_SD_D0_BAR)
 420        stw     r5,SD_D0_BAR(r4)
 421        sync
 422
 423        /* Initialize DIMM1 control and BAR registers
 424         * (same as dimm 0, next 512MB, disabled)
 425         */
 426        LOAD_U32(r5,VAL_SD_D1_CTRL)     /* auto-precharge disabled */
 427#ifdef SDC_AUTOPRECH_EN
 428        oris    r5,r5,0x0001            /* set auto precharge EN bit */
 429#endif
 430        stw     r5,SD_D1_CTRL(r4)
 431        LOAD_U32(r5,VAL_SD_D1_BAR)
 432        stw     r5,SD_D1_BAR(r4)
 433        sync
 434#else /* !SDC_HARDCODED_INIT */
 435        bl      tsi108_sdram_spd        /* automatically detect SDC settings */
 436#endif /* SDC_HARDCODED_INIT */
 437
 438sdc_init_done:
 439
 440#ifdef DISABLE_PBM
 441        LOAD_U32(r5,0x00000030)         /* PB_EN + OCN_EN */
 442#else
 443        LOAD_U32(r5,0x00000230)         /* PB_EN + OCN_EN + PB/OCN=80/20 */
 444#endif /* DISABLE_PBM */
 445
 446#ifdef CONFIG_TSI108EMU
 447        oris    r5,r5,0x0010            /* set EMULATION_MODE bit */
 448#endif
 449
 450        stw     r5,SD_CTRL(r4)
 451        eieio
 452        sync
 453
 454        /* Enable SDRAM access */
 455
 456        oris    r5,r5,0x8000            /* start SDC: set SD_CTRL[ENABLE] bit */
 457        stw     r5,SD_CTRL(r4)
 458        sync
 459
 460wait_init_complete:
 461        lwz     r5,SD_STATUS(r4)
 462        andi.   r5,r5,0x0001
 463        /* wait until SDRAM initialization is complete */
 464        beq     wait_init_complete
 465
 466        /* Map SDRAM into the processor bus address space */
 467
 468        ori     r4,r29,TSI108_PB_REG_OFFSET
 469
 470        /* Setup BARs associated with direct path PB<->SDRAM */
 471
 472        /* PB_SDRAM_BAR1:
 473         * provides a direct path to the main system memory (cacheable SDRAM)
 474         */
 475
 476        /* BA=0,Size=512MB, ENable, No Addr.Translation */
 477        LOAD_U32(r5, 0x00000011)
 478        stw     r5,PB_SDRAM_BAR1(r4)
 479        sync
 480
 481        /* Make sure that PB_SDRAM_BAR1 decoder is set
 482         * (to allow following immediate read from SDRAM)
 483         */
 484        lwz     r5,PB_SDRAM_BAR1(r4)
 485        sync
 486
 487        /* PB_SDRAM_BAR2:
 488         * provides non-cacheable alias (via the direct path) to main
 489         * system memory.
 490         * Size = 512MB, ENable, Addr.Translation - ON,
 491         * BA = 0x0_40000000, TA = 0x0_00000000
 492         */
 493
 494        LOAD_U32(r5, 0x40010011)
 495        stw     r5,PB_SDRAM_BAR2(r4)
 496        sync
 497
 498        /* Make sure that PB_SDRAM_BAR2 decoder is set
 499         * (to allow following immediate read from SDRAM)
 500         */
 501        lwz     r5,PB_SDRAM_BAR2(r4)
 502        sync
 503
 504init_done:
 505
 506        /* All done. Restore LR and return. */
 507        mtlr    r19
 508        blr
 509
 510#if (0)
 511        /*
 512         * init_cpu1
 513         * This routine enables CPU1 on the dual-processor system.
 514         * Now there is only one processor in the system
 515         */
 516
 517        .global enable_cpu1
 518enable_cpu1:
 519
 520        lis     r3,Tsi108_Base@ha       /* Get Grendel CSR Base Addr */
 521        addi    r3,r3,Tsi108_Base@l
 522        lwz     r3,0(r3)                /* R3 = CSR Base Addr */
 523        ori     r4,r3,TSI108_PB_REG_OFFSET
 524        lwz     r3,PB_ARB_CTRL(r4)      /* Read PB Arbiter Control Register */
 525        ori     r3,r3,0x0200            /* Set M1_EN bit */
 526        stw     r3,PB_ARB_CTRL(r4)
 527
 528        blr
 529#endif
 530
 531        /*
 532         * enable_EI
 533         * Enable CPU core external interrupt
 534         */
 535
 536        .global enable_EI
 537enable_EI:
 538        mfmsr   r3
 539        ori     r3,r3,0x8000    /* set EE bit */
 540        mtmsr   r3
 541        blr
 542
 543        /*
 544         * disable_EI
 545         * Disable CPU core external interrupt
 546         */
 547
 548        .global disable_EI
 549disable_EI:
 550        mfmsr   r3
 551        li      r4,-32768       /* aka "li  r4,0x8000" */
 552        andc    r3,r3,r4        /* clear EE bit */
 553        mtmsr   r3
 554        blr
 555
 556#ifdef ENABLE_SDRAM_ECC
 557        /* enables SDRAM ECC  */
 558
 559        .global enable_ECC
 560enable_ECC:
 561        ori     r4,r29,TSI108_SD_REG_OFFSET
 562        lwz     r3,SD_ECC_CTRL(r4)      /* Read SDRAM ECC Control Register */
 563        ori     r3,r3,0x0001            /* Set ECC_EN bit */
 564        stw     r3,SD_ECC_CTRL(r4)
 565        blr
 566
 567        /*
 568         * clear_ECC_err
 569         * Clears all pending SDRAM ECC errors
 570         * (normally after SDRAM scrubbing/initialization)
 571         */
 572
 573        .global clear_ECC_err
 574clear_ECC_err:
 575        ori r4,r29,TSI108_SD_REG_OFFSET
 576        ori r3,r0,0x0030        /* ECC_UE_INT + ECC_CE_INT bits */
 577        stw r3,SD_INT_STATUS(r4)
 578        blr
 579
 580#endif /* ENABLE_SDRAM_ECC */
 581
 582#ifndef SDC_HARDCODED_INIT
 583
 584        /* SDRAM SPD Support */
 585#define SD_I2C_CTRL1    (0x400)
 586#define SD_I2C_CTRL2    (0x404)
 587#define SD_I2C_RD_DATA  (0x408)
 588#define SD_I2C_WR_DATA  (0x40C)
 589
 590        /*
 591         * SDRAM SPD Support Macros
 592         */
 593
 594#define SPD_DIMM0       (0x00000100)
 595#define SPD_DIMM1       (0x00000200)    /* SPD_DIMM1 was 0x00000000 */
 596
 597#define SPD_RDIMM                       (0x01)
 598#define SPD_UDIMM                       (0x02)
 599
 600#define SPD_CAS_3                       0x8
 601#define SPD_CAS_4                       0x10
 602#define SPD_CAS_5                       0x20
 603
 604#define ERR_NO_DIMM_FOUND               (0xdb0)
 605#define ERR_TRAS_FAIL                   (0xdb1)
 606#define ERR_TRCD_FAIL                   (0xdb2)
 607#define ERR_TRP_FAIL                    (0xdb3)
 608#define ERR_TWR_FAIL                    (0xdb4)
 609#define ERR_UNKNOWN_PART                (0xdb5)
 610#define ERR_NRANK_INVALID               (0xdb6)
 611#define ERR_DIMM_SIZE                   (0xdb7)
 612#define ERR_ADDR_MODE                   (0xdb8)
 613#define ERR_RFRSH_RATE                  (0xdb9)
 614#define ERR_DIMM_TYPE                   (0xdba)
 615#define ERR_CL_VALUE                    (0xdbb)
 616#define ERR_TRFC_FAIL                   (0xdbc)
 617
 618/* READ_SPD requirements:
 619 * byte - byte address in SPD device (0 - 255)
 620 * r3 = will return data read from I2C Byte location
 621 * r4 - unchanged (SDC base addr)
 622 * r5 - clobbered in routine (I2C status)
 623 * r10 - number of DDR slot where first SPD device is detected
 624 */
 625
 626#define READ_SPD(byte_num)              \
 627        addis   r3, 0, byte_num@l;      \
 628        or      r3, r3, r10;            \
 629        ori     r3, r3, 0x0A;           \
 630        stw     r3, SD_I2C_CTRL1(r4);   \
 631        li      r3, I2C_CNTRL2_START;   \
 632        stw     r3, SD_I2C_CTRL2(r4);   \
 633        eieio;                          \
 634        sync;                           \
 635        li      r3, 0x100;              \
 6361:;                                     \
 637        addic.  r3, r3, -1;             \
 638        bne     1b;                     \
 6392:;                                     \
 640        lwz     r5, SD_I2C_CTRL2(r4);   \
 641        rlwinm. r3,r5,0,23,23;          \
 642        bne     2b;                     \
 643        rlwinm. r3,r5,0,3,3;            \
 644        lwz     r3,SD_I2C_RD_DATA(r4)
 645
 646#define SPD_MIN_RFRSH   (0x80)
 647#define SPD_MAX_RFRSH   (0x85)
 648
 649refresh_rates:  /* in nSec */
 650        .long   15625   /* Normal (0x80) */
 651        .long   3900    /* Reduced 0.25x (0x81) */
 652        .long   7800    /* Reduced 0.5x (0x82) */
 653        .long   31300   /* Extended 2x (0x83) */
 654        .long   62500   /* Extended 4x (0x84) */
 655        .long   125000  /* Extended 8x (0x85) */
 656
 657/*
 658 * tsi108_sdram_spd
 659 *
 660 * Inittializes SDRAM Controller using DDR2 DIMM Serial Presence Detect data
 661 * Uses registers: r4 - SDC base address (not changed)
 662 *                                 r9 - SDC clocking period in nSec
 663 * Changes registers: r3,r5,r6,r7,r8,r10,r11
 664 */
 665
 666tsi108_sdram_spd:
 667
 668        li      r10,SPD_DIMM0
 669        xor     r11,r11,r11             /* DIMM Base Address: starts from 0 */
 670
 671do_first_dimm:
 672
 673        /* Program Refresh Rate Register */
 674
 675        READ_SPD(12)                    /* get Refresh Rate */
 676        beq     check_next_slot
 677        li      r5, ERR_RFRSH_RATE
 678        cmpi    0,0,r3,SPD_MIN_RFRSH
 679        ble     spd_fail
 680        cmpi    0,0,r3,SPD_MAX_RFRSH
 681        bgt     spd_fail
 682        addi    r3,r3,-SPD_MIN_RFRSH
 683        rlwinm  r3,r3,2,0,31
 684        lis     r5,refresh_rates@h
 685        ori     r5,r5,refresh_rates@l
 686        lwzx    r5,r5,r3                /* get refresh rate in nSec */
 687        divwu   r5,r5,r9                /* calculate # of SDC clocks */
 688        stw     r5,SD_REFRESH(r4)       /* Set refresh rate */
 689        sync
 690
 691        /* Program SD Timing Register */
 692
 693        li      r7, 0           /* clear r7 prior parameter collection */
 694
 695        READ_SPD(20)            /* get DIMM type: Registered or Unbuffered */
 696        beq     spd_read_fail
 697        li      r5, ERR_DIMM_TYPE
 698        cmpi    0,0,r3,SPD_UDIMM
 699        beq     do_cl
 700        cmpi    0,0,r3,SPD_RDIMM
 701        bne     spd_fail
 702        oris    r7,r7,0x1000    /* set SD_TIMING[DIMM_TYPE] bit */
 703
 704do_cl:
 705        READ_SPD(18)            /* Get CAS Latency */
 706        beq     spd_read_fail
 707        li      r5,ERR_CL_VALUE
 708        andi.   r6,r3,SPD_CAS_3
 709        beq     cl_4
 710        li      r6,3
 711        b       set_cl
 712cl_4:
 713        andi.   r6,r3,SPD_CAS_4
 714        beq     cl_5
 715        li      r6,4
 716        b       set_cl
 717cl_5:
 718        andi.   r6,r3,SPD_CAS_5
 719        beq     spd_fail
 720        li      r6,5
 721set_cl:
 722        rlwimi  r7,r6,24,5,7
 723
 724        READ_SPD(30)            /* Get tRAS */
 725        beq     spd_read_fail
 726        divwu   r6,r3,r9
 727        mullw   r8,r6,r9
 728        subf.   r8,r8,r3
 729        beq     set_tras
 730        addi    r6,r6,1
 731set_tras:
 732        li r5,ERR_TRAS_FAIL
 733        cmpi    0,0,r6,0x0F     /* max supported value */
 734        bgt     spd_fail
 735        rlwimi  r7,r6,16,12,15
 736
 737        READ_SPD(29)    /* Get tRCD */
 738        beq     spd_read_fail
 739        /* right shift tRCD by 2 bits as per DDR2 spec */
 740        rlwinm  r3,r3,30,2,31
 741        divwu   r6,r3,r9
 742        mullw   r8,r6,r9
 743        subf.   r8,r8,r3
 744        beq     set_trcd
 745        addi    r6,r6,1
 746set_trcd:
 747        li      r5,ERR_TRCD_FAIL
 748        cmpi    0,0,r6,0x07     /* max supported value */
 749        bgt     spd_fail
 750        rlwimi  r7,r6,12,17,19
 751
 752        READ_SPD(27)    /* Get tRP value */
 753        beq     spd_read_fail
 754        rlwinm  r3,r3,30,2,31   /* right shift tRP by 2 bits as per DDR2 spec */
 755        divwu   r6,r3,r9
 756        mullw   r8,r6,r9
 757        subf.   r8,r8,r3
 758        beq     set_trp
 759        addi    r6,r6,1
 760set_trp:
 761        li      r5,ERR_TRP_FAIL
 762        cmpi    0,0,r6,0x07     /* max supported value */
 763        bgt     spd_fail
 764        rlwimi  r7,r6,8,21,23
 765
 766        READ_SPD(36)    /* Get tWR value */
 767        beq     spd_read_fail
 768        rlwinm  r3,r3,30,2,31   /* right shift tWR by 2 bits as per DDR2 spec */
 769        divwu   r6,r3,r9
 770        mullw   r8,r6,r9
 771        subf.   r8,r8,r3
 772        beq     set_twr
 773        addi    r6,r6,1
 774set_twr:
 775        addi    r6,r6,-1        /* Tsi108 SDC always gives one extra clock */
 776        li      r5,ERR_TWR_FAIL
 777        cmpi    0,0,r6,0x07     /* max supported value */
 778        bgt     spd_fail
 779        rlwimi  r7,r6,5,24,26
 780
 781        READ_SPD(42)    /* Get tRFC */
 782        beq     spd_read_fail
 783        li      r5, ERR_TRFC_FAIL
 784        /* Tsi108 spec: tRFC=(tRFC + 1)/2 */
 785        addi    r3,r3,1
 786        rlwinm. r3,r3,31,1,31   /* divide by 2 */
 787        beq     spd_fail
 788        divwu   r6,r3,r9
 789        mullw   r8,r6,r9
 790        subf.   r8,r8,r3
 791        beq     set_trfc
 792        addi    r6,r6,1
 793set_trfc:
 794        cmpi    0,0,r6,0x1F     /* max supported value */
 795        bgt     spd_fail
 796        rlwimi  r7,r6,0,27,31
 797
 798        stw     r7,SD_TIMING(r4)
 799        sync
 800
 801        /*
 802         * The following two registers are set on per-DIMM basis.
 803         * The SD_REFRESH and SD_TIMING settings are common for both DIMMS
 804         */
 805
 806do_each_dimm:
 807
 808        /* Program SDRAM DIMM Control Register */
 809
 810        li      r7, 0           /* clear r7 prior parameter collection */
 811
 812        READ_SPD(13)            /* Get Primary SDRAM Width */
 813        beq     spd_read_fail
 814        cmpi    0,0,r3,4        /* Check for 4-bit SDRAM */
 815        beq     do_nbank
 816        oris    r7,r7,0x0010    /* Set MEM_WIDTH bit */
 817
 818do_nbank:
 819        READ_SPD(17)            /* Get Number of banks on SDRAM device */
 820        beq     spd_read_fail
 821        /* Grendel only distinguish betw. 4 or 8-bank memory parts */
 822        li      r5,ERR_UNKNOWN_PART     /* non-supported memory part */
 823        cmpi    0,0,r3,4
 824        beq     do_nrank
 825        cmpi    0,0,r3,8
 826        bne     spd_fail
 827        ori     r7,r7,0x1000
 828
 829do_nrank:
 830        READ_SPD(5)             /* Get # of Ranks */
 831        beq     spd_read_fail
 832        li      r5,ERR_NRANK_INVALID
 833        andi.   r6,r3,0x7       /* Use bits [2..0] only */
 834        beq     do_addr_mode
 835        cmpi    0,0,r6,1
 836        bgt     spd_fail
 837        rlwimi  r7,r6,8,23,23
 838
 839do_addr_mode:
 840        READ_SPD(4)             /* Get # of Column Addresses */
 841        beq     spd_read_fail
 842        li      r5, ERR_ADDR_MODE
 843        andi.   r3,r3,0x0f      /* cut off reserved bits */
 844        cmpi    0,0,r3,8
 845        ble     spd_fail
 846        cmpi    0,0,r3,15
 847        bgt     spd_fail
 848        addi    r6,r3,-8        /* calculate ADDR_MODE parameter */
 849        rlwimi  r7,r6,4,24,27   /* set ADDR_MODE field */
 850
 851set_dimm_ctrl:
 852#ifdef SDC_AUTOPRECH_EN
 853        oris    r7,r7,0x0001    /* set auto precharge EN bit */
 854#endif
 855        ori     r7,r7,1         /* set ENABLE bit */
 856        cmpi    0,0,r10,SPD_DIMM0
 857        bne     1f
 858        stw     r7,SD_D0_CTRL(r4)
 859        sync
 860        b       set_dimm_bar
 8611:
 862        stw     r7,SD_D1_CTRL(r4)
 863        sync
 864
 865
 866        /* Program SDRAM DIMMx Base Address Register */
 867
 868set_dimm_bar:
 869        READ_SPD(5)             /* get # of Ranks */
 870        beq     spd_read_fail
 871        andi.   r7,r3,0x7
 872        addi    r7,r7,1
 873        READ_SPD(31)            /* Read DIMM rank density */
 874        beq     spd_read_fail
 875        rlwinm  r5,r3,27,29,31
 876        rlwinm  r6,r3,3,24,28
 877        or      r5,r6,r5        /* r5 = Normalized Rank Density byte */
 878        lis     r8, 0x0080      /* 128MB >> 4 */
 879        mullw   r8,r8,r5        /* r8 = (rank_size >> 4) */
 880        mullw   r8,r8,r7        /* r8 = (DIMM_size >> 4) */
 881        neg     r7,r8
 882        rlwinm  r7,r7,28,4,31
 883        or      r7,r7,r11       /* set ADDR field */
 884        rlwinm  r8,r8,12,20,31
 885        add     r11,r11,r8      /* set Base Addr for next DIMM */
 886
 887        cmpi    0,0,r10,SPD_DIMM0
 888        bne     set_dimm1_size
 889        stw     r7,SD_D0_BAR(r4)
 890        sync
 891        li      r10,SPD_DIMM1
 892        READ_SPD(0)
 893        bne do_each_dimm
 894        b spd_done
 895
 896set_dimm1_size:
 897        stw     r7,SD_D1_BAR(r4)
 898        sync
 899spd_done:
 900        blr
 901
 902check_next_slot:
 903        cmpi    0,0,r10,SPD_DIMM1
 904        beq     spd_read_fail
 905        li      r10,SPD_DIMM1
 906        b       do_first_dimm
 907spd_read_fail:
 908        ori     r3,r0,0xdead
 909        b       err_hung
 910spd_fail:
 911        li      r3,0x0bad
 912        sync
 913err_hung:       /* hang here for debugging */
 914        nop
 915        nop
 916        b       err_hung
 917
 918#endif /* !SDC_HARDCODED_INIT */
 919