diff options
Diffstat (limited to 'cpu/mpc83xx')
-rw-r--r-- | cpu/mpc83xx/cpu.c | 81 | ||||
-rw-r--r-- | cpu/mpc83xx/cpu_init.c | 31 | ||||
-rw-r--r-- | cpu/mpc83xx/spd_sdram.c | 21 |
3 files changed, 130 insertions, 3 deletions
diff --git a/cpu/mpc83xx/cpu.c b/cpu/mpc83xx/cpu.c index 8d543d5..4e82a8b 100644 --- a/cpu/mpc83xx/cpu.c +++ b/cpu/mpc83xx/cpu.c @@ -69,9 +69,72 @@ int checkcpu(void) } +/** + * Program a UPM with the code supplied in the table. + * + * The 'dummy' variable is used to increment the MAD. 'dummy' is + * supposed to be a pointer to the memory of the device being + * programmed by the UPM. The data in the MDR is written into + * memory and the MAD is incremented every time there's a read + * from 'dummy'. Unfortunately, the current prototype for this + * function doesn't allow for passing the address of this + * device, and changing the prototype will break a number lots + * of other code, so we need to use a round-about way of finding + * the value for 'dummy'. + * + * The value can be extracted from the base address bits of the + * Base Register (BR) associated with the specific UPM. To find + * that BR, we need to scan all 8 BRs until we find the one that + * has its MSEL bits matching the UPM we want. Once we know the + * right BR, we can extract the base address bits from it. + * + * The MxMR and the BR and OR of the chosen bank should all be + * configured before calling this function. + * + * Parameters: + * upm: 0=UPMA, 1=UPMB, 2=UPMC + * table: Pointer to an array of values to program + * size: Number of elements in the array. Must be 64 or less. +*/ void upmconfig (uint upm, uint *table, uint size) { - hang(); /* FIXME: upconfig() needed? */ +#if defined(CONFIG_MPC834X) + volatile immap_t *immap = (immap_t *) CFG_IMMRBAR; + volatile lbus83xx_t *lbus = &immap->lbus; + volatile uchar *dummy = NULL; + const u32 msel = (upm + 4) << BR_MSEL_SHIFT; /* What the MSEL field in BRn should be */ + volatile u32 *mxmr = &lbus->mamr + upm; /* Pointer to mamr, mbmr, or mcmr */ + uint i; + + /* Scan all the banks to determine the base address of the device */ + for (i = 0; i < 8; i++) { + if ((lbus->bank[i].br & BR_MSEL) == msel) { + dummy = (uchar *) (lbus->bank[i].br & BR_BA); + break; + } + } + + if (!dummy) { + printf("Error: %s() could not find matching BR\n", __FUNCTION__); + hang(); + } + + /* Set the OP field in the MxMR to "write" and the MAD field to 000000 */ + *mxmr = (*mxmr & 0xCFFFFFC0) | 0x10000000; + + for (i = 0; i < size; i++) { + lbus->mdr = table[i]; + __asm__ __volatile__ ("sync"); + *dummy; /* Write the value to memory and increment MAD */ + __asm__ __volatile__ ("sync"); + } + + /* Set the OP field in the MxMR to "normal" and the MAD field to 000000 */ + *mxmr &= 0xCFFFFFC0; +#else + printf("Error: %s() not defined for this configuration.\n", __FUNCTION__); + hang(); +#endif } @@ -150,9 +213,21 @@ unsigned long get_tbclk(void) #if defined(CONFIG_WATCHDOG) void watchdog_reset (void) { - hang(); /* FIXME: implement watchdog_reset()? */ +#ifdef CONFIG_MPC834X + int re_enable = disable_interrupts(); + + /* Reset the 83xx watchdog */ + volatile immap_t *immr = (immap_t *) CFG_IMMRBAR; + immr->wdt.swsrr = 0x556c; + immr->wdt.swsrr = 0xaa39; + + if (re_enable) + enable_interrupts (); +#else + hang(); +#endif } -#endif /* CONFIG_WATCHDOG */ +#endif #if defined(CONFIG_OF_FLAT_TREE) void diff --git a/cpu/mpc83xx/cpu_init.c b/cpu/mpc83xx/cpu_init.c index 6ed0992..999fe71 100644 --- a/cpu/mpc83xx/cpu_init.c +++ b/cpu/mpc83xx/cpu_init.c @@ -46,6 +46,37 @@ void cpu_init_f (volatile immap_t * im) /* Clear initial global data */ memset ((void *) gd, 0, sizeof (gd_t)); + /* system performance tweaking */ + +#ifdef CFG_ACR_PIPE_DEP + /* Arbiter pipeline depth */ + im->arbiter.acr = (im->arbiter.acr & ~ACR_PIPE_DEP) | (3 << ACR_PIPE_DEP_SHIFT); +#endif + +#ifdef CFG_SPCR_TSEC1EP + /* TSEC1 Emergency priority */ + im->sysconf.spcr = (im->sysconf.spcr & ~SPCR_TSEC1EP) | (3 << SPCR_TSEC1EP_SHIFT); +#endif + +#ifdef CFG_SPCR_TSEC2EP + /* TSEC2 Emergency priority */ + im->sysconf.spcr = (im->sysconf.spcr & ~SPCR_TSEC2EP) | (3 << SPCR_TSEC2EP_SHIFT); +#endif + +#ifdef CFG_SCCR_TSEC1CM + /* TSEC1 clock mode */ + im->clk.sccr = (im->clk.sccr & ~SCCR_TSEC1CM) | (1 << SCCR_TSEC1CM_SHIFT); +#endif +#ifdef CFG_SCCR_TSEC2CM + /* TSEC2 & I2C1 clock mode */ + im->clk.sccr = (im->clk.sccr & ~SCCR_TSEC2CM) | (1 << SCCR_TSEC2CM_SHIFT); +#endif + +#ifdef CFG_ACR_RPTCNT + /* Arbiter repeat count */ + im->arbiter.acr = ((im->arbiter.acr & ~(ACR_RPTCNT)) | (3 << ACR_RPTCNT_SHIFT)); +#endif + /* RSR - Reset Status Register - clear all status (4.6.1.3) */ gd->reset_status = im->reset.rsr; im->reset.rsr = ~(RSR_RES); diff --git a/cpu/mpc83xx/spd_sdram.c b/cpu/mpc83xx/spd_sdram.c index 8ee4234..3dfde8a 100644 --- a/cpu/mpc83xx/spd_sdram.c +++ b/cpu/mpc83xx/spd_sdram.c @@ -133,6 +133,26 @@ long int spd_sdram() /* Read SPD parameters with I2C */ +#ifdef CFG_83XX_DDR_USES_CS0 + ddr->csbnds[0].csbnds = (banksize(spd.row_dens) >> 24) - 1; + ddr->cs_config[0] = ( 1 << 31 + | (spd.nrow_addr - 12) << 8 + | (spd.ncol_addr - 8) ); + debug("\n"); + debug("cs0_bnds = 0x%08x\n",ddr->csbnds[0].csbnds); + debug("cs0_config = 0x%08x\n",ddr->cs_config[0]); + + if (spd.nrows == 2) { + ddr->csbnds[1].csbnds = ( (banksize(spd.row_dens) >> 8) + | ((banksize(spd.row_dens) >> 23) - 1) ); + ddr->cs_config[1] = ( 1<<31 + | (spd.nrow_addr-12) << 8 + | (spd.ncol_addr-8) ); + debug("cs1_bnds = 0x%08x\n",ddr->csbnds[1].csbnds); + debug("cs1_config = 0x%08x\n",ddr->cs_config[1]); + } + +#else CFG_READ_SPD(SPD_EEPROM_ADDRESS, 0, 1, (uchar *) & spd, sizeof (spd)); #ifdef SPD_DEBUG spd_debug(&spd); @@ -180,6 +200,7 @@ long int spd_sdram() debug("cs3_bnds = 0x%08x\n",ddr->csbnds[3].csbnds); debug("cs3_config = 0x%08x\n",ddr->cs_config[3]); } +#endif if (spd.mem_type != 0x07) { puts("No DDR module found!\n"); |