diff options
author | Wolfgang Denk <wd@denx.de> | 2008-06-11 21:33:16 +0200 |
---|---|---|
committer | Wolfgang Denk <wd@denx.de> | 2008-06-11 21:33:16 +0200 |
commit | 5ea67393b8b554b8165c38912d753a8df043020d (patch) | |
tree | 080077826cffcfebbaa0a950c663e7d165cf6b7d /board/tqc/tqm834x | |
parent | 2395db48869e759c4422efa3d3c25161601aa17b (diff) | |
parent | ba04f7010958e88a8910f2a123fee53fdc72e013 (diff) | |
download | u-boot-imx-5ea67393b8b554b8165c38912d753a8df043020d.zip u-boot-imx-5ea67393b8b554b8165c38912d753a8df043020d.tar.gz u-boot-imx-5ea67393b8b554b8165c38912d753a8df043020d.tar.bz2 |
Merge branch 'master' of git://www.denx.de/git/u-boot-mpc85xx
Conflicts:
include/asm-ppc/fsl_lbc.h
Signed-off-by: Wolfgang Denk <wd@denx.de>
Diffstat (limited to 'board/tqc/tqm834x')
-rw-r--r-- | board/tqc/tqm834x/Makefile | 52 | ||||
-rw-r--r-- | board/tqc/tqm834x/config.mk | 23 | ||||
-rw-r--r-- | board/tqc/tqm834x/pci.c | 220 | ||||
-rw-r--r-- | board/tqc/tqm834x/tqm834x.c | 433 |
4 files changed, 728 insertions, 0 deletions
diff --git a/board/tqc/tqm834x/Makefile b/board/tqc/tqm834x/Makefile new file mode 100644 index 0000000..4c0d204 --- /dev/null +++ b/board/tqc/tqm834x/Makefile @@ -0,0 +1,52 @@ +# +# (C) Copyright 2006 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# Copyright 2004 Freescale Semiconductor, Inc. +# +# See file CREDITS for list of people who contributed to this +# project. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, +# MA 02111-1307 USA +# + +include $(TOPDIR)/config.mk + +LIB = $(obj)lib$(BOARD).a + +COBJS = $(BOARD).o pci.o + +SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) +OBJS := $(addprefix $(obj),$(COBJS)) +SOBJS := $(addprefix $(obj),$(SOBJS)) + +$(LIB): $(obj).depend $(OBJS) + $(AR) $(ARFLAGS) $@ $(OBJS) + +clean: + rm -f $(SOBJS) $(OBJS) + +distclean: clean + rm -f $(LIB) core *.bak .depend + +######################################################################### + +# defines $(obj).depend target +include $(SRCTREE)/rules.mk + +sinclude $(obj).depend + +######################################################################### diff --git a/board/tqc/tqm834x/config.mk b/board/tqc/tqm834x/config.mk new file mode 100644 index 0000000..f172c4e --- /dev/null +++ b/board/tqc/tqm834x/config.mk @@ -0,0 +1,23 @@ +# +# Copyright 2004 Freescale Semiconductor, Inc. +# +# See file CREDITS for list of people who contributed to this +# project. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, +# MA 02111-1307 USA +# + +TEXT_BASE = 0x80000000 diff --git a/board/tqc/tqm834x/pci.c b/board/tqc/tqm834x/pci.c new file mode 100644 index 0000000..e3d0309 --- /dev/null +++ b/board/tqc/tqm834x/pci.c @@ -0,0 +1,220 @@ +/* + * (C) Copyright 2005 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + */ + +#include <asm/mmu.h> +#include <common.h> +#include <pci.h> + +#ifdef CONFIG_PCI + +/* System RAM mapped to PCI space */ +#define CONFIG_PCI_SYS_MEM_BUS CFG_SDRAM_BASE +#define CONFIG_PCI_SYS_MEM_PHYS CFG_SDRAM_BASE +#define CONFIG_PCI_SYS_MEM_SIZE (1024 * 1024 * 1024) + +#ifndef CONFIG_PCI_PNP +static struct pci_config_table pci_tqm834x_config_table[] = { + {PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, + PCI_IDSEL_NUMBER, PCI_ANY_ID, + pci_cfgfunc_config_device, {PCI_ENET0_IOADDR, + PCI_ENET0_MEMADDR, + PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER + } + }, + {} +}; +#endif + +static struct pci_controller pci1_hose = { +#ifndef CONFIG_PCI_PNP + config_table:pci_tqm834x_config_table, +#endif +}; + + +/************************************************************************** + * pci_init_board() + * + * NOTICE: MPC8349 internally has two PCI controllers (PCI1 and PCI2) but since + * per TQM834x design physical connections to external devices (PCI sockets) + * are routed only to the PCI1 we do not account for the second one - this code + * supports PCI1 module only. Should support for the PCI2 be required in the + * future it needs a separate pci_controller structure (above) and handling - + * please refer to other boards' implementation for dual PCI host controllers, + * for example board/Marvell/db64360/pci.c, pci_init_board() + * + */ +void +pci_init_board(void) +{ + volatile immap_t * immr; + volatile clk83xx_t * clk; + volatile law83xx_t * pci_law; + volatile pot83xx_t * pci_pot; + volatile pcictrl83xx_t * pci_ctrl; + volatile pciconf83xx_t * pci_conf; + u16 reg16; + u32 reg32; + struct pci_controller * hose; + + immr = (immap_t *)CFG_IMMR; + clk = (clk83xx_t *)&immr->clk; + pci_law = immr->sysconf.pcilaw; + pci_pot = immr->ios.pot; + pci_ctrl = immr->pci_ctrl; + pci_conf = immr->pci_conf; + + hose = &pci1_hose; + + /* + * Configure PCI controller and PCI_CLK_OUTPUT + */ + + /* + * WARNING! only PCI_CLK_OUTPUT1 is enabled here as this is the one + * line actually used for clocking all external PCI devices in TQM83xx. + * Enabling other PCI_CLK_OUTPUT lines may lead to board's hang for + * unknown reasons - particularly PCI_CLK_OUTPUT6 and PCI_CLK_OUTPUT7 + * are known to hang the board; this issue is under investigation + * (13 oct 05) + */ + reg32 = OCCR_PCICOE1; +#if 0 + /* enabling all PCI_CLK_OUTPUT lines HANGS the board... */ + reg32 = 0xff000000; +#endif + if (clk->spmr & SPMR_CKID) { + /* PCI Clock is half CONFIG_83XX_CLKIN so need to set up OCCR + * fields accordingly */ + reg32 |= (OCCR_PCI1CR | OCCR_PCI2CR); + + reg32 |= (OCCR_PCICD0 | OCCR_PCICD1 | OCCR_PCICD2 \ + | OCCR_PCICD3 | OCCR_PCICD4 | OCCR_PCICD5 \ + | OCCR_PCICD6 | OCCR_PCICD7); + } + + clk->occr = reg32; + udelay(2000); + + /* + * Release PCI RST Output signal + */ + pci_ctrl[0].gcr = 0; + udelay(2000); + pci_ctrl[0].gcr = 1; + udelay(2000); + + /* + * Configure PCI Local Access Windows + */ + pci_law[0].bar = CFG_PCI1_MEM_PHYS & LAWBAR_BAR; + pci_law[0].ar = LAWAR_EN | LAWAR_SIZE_512M; + + pci_law[1].bar = CFG_PCI1_IO_PHYS & LAWBAR_BAR; + pci_law[1].ar = LAWAR_EN | LAWAR_SIZE_16M; + + /* + * Configure PCI Outbound Translation Windows + */ + + /* PCI1 mem space */ + pci_pot[0].potar = (CFG_PCI1_MEM_BASE >> 12) & POTAR_TA_MASK; + pci_pot[0].pobar = (CFG_PCI1_MEM_PHYS >> 12) & POBAR_BA_MASK; + pci_pot[0].pocmr = POCMR_EN | (POCMR_CM_512M & POCMR_CM_MASK); + + /* PCI1 IO space */ + pci_pot[1].potar = (CFG_PCI1_IO_BASE >> 12) & POTAR_TA_MASK; + pci_pot[1].pobar = (CFG_PCI1_IO_PHYS >> 12) & POBAR_BA_MASK; + pci_pot[1].pocmr = POCMR_EN | POCMR_IO | (POCMR_CM_16M & POCMR_CM_MASK); + + /* + * Configure PCI Inbound Translation Windows + */ + + /* we need RAM mapped to PCI space for the devices to + * access main memory */ + pci_ctrl[0].pitar1 = 0x0; + pci_ctrl[0].pibar1 = 0x0; + pci_ctrl[0].piebar1 = 0x0; + pci_ctrl[0].piwar1 = PIWAR_EN | PIWAR_PF | PIWAR_RTT_SNOOP | PIWAR_WTT_SNOOP | PIWAR_IWS_256M; + + hose->first_busno = 0; + hose->last_busno = 0xff; + + /* PCI memory space */ + pci_set_region(hose->regions + 0, + CFG_PCI1_MEM_BASE, + CFG_PCI1_MEM_PHYS, + CFG_PCI1_MEM_SIZE, + PCI_REGION_MEM); + + /* PCI IO space */ + pci_set_region(hose->regions + 1, + CFG_PCI1_IO_BASE, + CFG_PCI1_IO_PHYS, + CFG_PCI1_IO_SIZE, + PCI_REGION_IO); + + /* System memory space */ + pci_set_region(hose->regions + 2, + CONFIG_PCI_SYS_MEM_BUS, + CONFIG_PCI_SYS_MEM_PHYS, + CONFIG_PCI_SYS_MEM_SIZE, + PCI_REGION_MEM | PCI_REGION_MEMORY); + + hose->region_count = 3; + + pci_setup_indirect(hose, + (CFG_IMMR+0x8300), + (CFG_IMMR+0x8304)); + + pci_register_hose(hose); + + /* + * Write to Command register + */ + reg16 = 0xff; + pci_hose_read_config_word (hose, PCI_BDF(0,0,0), PCI_COMMAND, + ®16); + reg16 |= PCI_COMMAND_SERR | PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY; + pci_hose_write_config_word(hose, PCI_BDF(0,0,0), PCI_COMMAND, + reg16); + + /* + * Clear non-reserved bits in status register. + */ + pci_hose_write_config_word(hose, PCI_BDF(0,0,0), PCI_STATUS, + 0xffff); + pci_hose_write_config_byte(hose, PCI_BDF(0,0,0), PCI_LATENCY_TIMER, + 0x80); + +#ifdef CONFIG_PCI_SCAN_SHOW + printf("PCI: Bus Dev VenId DevId Class Int\n"); +#endif + /* + * Hose scan. + */ + hose->last_busno = pci_hose_scan(hose); +} +#endif /* CONFIG_PCI */ diff --git a/board/tqc/tqm834x/tqm834x.c b/board/tqc/tqm834x/tqm834x.c new file mode 100644 index 0000000..aea985c --- /dev/null +++ b/board/tqc/tqm834x/tqm834x.c @@ -0,0 +1,433 @@ +/* + * (C) Copyright 2005 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + */ + +#include <common.h> +#include <ioports.h> +#include <mpc83xx.h> +#include <asm/mpc8349_pci.h> +#include <i2c.h> +#include <miiphy.h> +#include <asm-ppc/mmu.h> +#include <pci.h> + +DECLARE_GLOBAL_DATA_PTR; + +#define IOSYNC asm("eieio") +#define ISYNC asm("isync") +#define SYNC asm("sync") +#define FPW FLASH_PORT_WIDTH +#define FPWV FLASH_PORT_WIDTHV + +#define DDR_MAX_SIZE_PER_CS 0x20000000 + +#if defined(DDR_CASLAT_20) +#define TIMING_CASLAT TIMING_CFG1_CASLAT_20 +#define MODE_CASLAT DDR_MODE_CASLAT_20 +#else +#define TIMING_CASLAT TIMING_CFG1_CASLAT_25 +#define MODE_CASLAT DDR_MODE_CASLAT_25 +#endif + +#define INITIAL_CS_CONFIG (CSCONFIG_EN | CSCONFIG_ROW_BIT_12 | \ + CSCONFIG_COL_BIT_9) + +/* Global variable used to store detected number of banks */ +int tqm834x_num_flash_banks; + +/* External definitions */ +ulong flash_get_size (ulong base, int banknum); +extern flash_info_t flash_info[]; + +/* Local functions */ +static int detect_num_flash_banks(void); +static long int get_ddr_bank_size(short cs, volatile long *base); +static void set_cs_bounds(short cs, long base, long size); +static void set_cs_config(short cs, long config); +static void set_ddr_config(void); + +/* Local variable */ +static volatile immap_t *im = (immap_t *)CFG_IMMR; + +/************************************************************************** + * Board initialzation after relocation to RAM. Used to detect the number + * of Flash banks on TQM834x. + */ +int board_early_init_r (void) { + /* sanity check, IMMARBAR should be mirrored at offset zero of IMMR */ + if ((im->sysconf.immrbar & IMMRBAR_BASE_ADDR) != (u32)im) + return 0; + + /* detect the number of Flash banks */ + return detect_num_flash_banks(); +} + +/************************************************************************** + * DRAM initalization and size detection + */ +long int initdram (int board_type) +{ + long bank_size; + long size; + int cs; + + /* during size detection, set up the max DDRLAW size */ + im->sysconf.ddrlaw[0].bar = CFG_DDR_BASE; + im->sysconf.ddrlaw[0].ar = (LAWAR_EN | LAWAR_SIZE_2G); + + /* set CS bounds to maximum size */ + for(cs = 0; cs < 4; ++cs) { + set_cs_bounds(cs, + CFG_DDR_BASE + (cs * DDR_MAX_SIZE_PER_CS), + DDR_MAX_SIZE_PER_CS); + + set_cs_config(cs, INITIAL_CS_CONFIG); + } + + /* configure ddr controller */ + set_ddr_config(); + + udelay(200); + + /* enable DDR controller */ + im->ddr.sdram_cfg = (SDRAM_CFG_MEM_EN | + SDRAM_CFG_SREN | + SDRAM_CFG_SDRAM_TYPE_DDR1); + SYNC; + + /* size detection */ + debug("\n"); + size = 0; + for(cs = 0; cs < 4; ++cs) { + debug("\nDetecting Bank%d\n", cs); + + bank_size = get_ddr_bank_size(cs, + (volatile long*)(CFG_DDR_BASE + size)); + size += bank_size; + + debug("DDR Bank%d size: %d MiB\n\n", cs, bank_size >> 20); + + /* exit if less than one bank */ + if(size < DDR_MAX_SIZE_PER_CS) break; + } + + return size; +} + +/************************************************************************** + * checkboard() + */ +int checkboard (void) +{ + puts("Board: TQM834x\n"); + +#ifdef CONFIG_PCI + volatile immap_t * immr; + u32 w, f; + + immr = (immap_t *)CFG_IMMR; + if (!(immr->reset.rcwh & HRCWH_PCI_HOST)) { + printf("PCI: NOT in host mode..?!\n"); + return 0; + } + + /* get bus width */ + w = 32; + if (immr->reset.rcwh & HRCWH_64_BIT_PCI) + w = 64; + + /* get clock */ + f = gd->pci_clk; + + printf("PCI1: %d bit, %d MHz\n", w, f / 1000000); +#else + printf("PCI: disabled\n"); +#endif + return 0; +} + + +/************************************************************************** + * + * Local functions + * + *************************************************************************/ + +/************************************************************************** + * Detect the number of flash banks (1 or 2). Store it in + * a global variable tqm834x_num_flash_banks. + * Bank detection code based on the Monitor code. + */ +static int detect_num_flash_banks(void) +{ + typedef unsigned long FLASH_PORT_WIDTH; + typedef volatile unsigned long FLASH_PORT_WIDTHV; + FPWV *bank1_base; + FPWV *bank2_base; + FPW bank1_read; + FPW bank2_read; + ulong bank1_size; + ulong bank2_size; + ulong total_size; + + tqm834x_num_flash_banks = 2; /* assume two banks */ + + /* Get bank 1 and 2 information */ + bank1_size = flash_get_size(CFG_FLASH_BASE, 0); + debug("Bank1 size: %lu\n", bank1_size); + bank2_size = flash_get_size(CFG_FLASH_BASE + bank1_size, 1); + debug("Bank2 size: %lu\n", bank2_size); + total_size = bank1_size + bank2_size; + + if (bank2_size > 0) { + /* Seems like we've got bank 2, but maybe it's mirrored 1 */ + + /* Set the base addresses */ + bank1_base = (FPWV *) (CFG_FLASH_BASE); + bank2_base = (FPWV *) (CFG_FLASH_BASE + bank1_size); + + /* Put bank 2 into CFI command mode and read */ + bank2_base[0x55] = 0x00980098; + IOSYNC; + ISYNC; + bank2_read = bank2_base[0x10]; + + /* Read from bank 1 (it's in read mode) */ + bank1_read = bank1_base[0x10]; + + /* Reset Flash */ + bank1_base[0] = 0x00F000F0; + bank2_base[0] = 0x00F000F0; + + if (bank2_read == bank1_read) { + /* + * Looks like just one bank, but not sure yet. Let's + * read from bank 2 in autosoelect mode. + */ + bank2_base[0x0555] = 0x00AA00AA; + bank2_base[0x02AA] = 0x00550055; + bank2_base[0x0555] = 0x00900090; + IOSYNC; + ISYNC; + bank2_read = bank2_base[0x10]; + + /* Read from bank 1 (it's in read mode) */ + bank1_read = bank1_base[0x10]; + + /* Reset Flash */ + bank1_base[0] = 0x00F000F0; + bank2_base[0] = 0x00F000F0; + + if (bank2_read == bank1_read) { + /* + * In both CFI command and autoselect modes, + * we got the some data reading from Flash. + * There is only one mirrored bank. + */ + tqm834x_num_flash_banks = 1; + total_size = bank1_size; + } + } + } + + debug("Number of flash banks detected: %d\n", tqm834x_num_flash_banks); + + /* set OR0 and BR0 */ + im->lbus.bank[0].or = CFG_OR_TIMING_FLASH | + (-(total_size) & OR_GPCM_AM); + im->lbus.bank[0].br = (CFG_FLASH_BASE & BR_BA) | + (BR_MS_GPCM | BR_PS_32 | BR_V); + + return (0); +} + +/************************************************************************* + * Detect the size of a ddr bank. Sets CS bounds and CS config accordingly. + */ +static long int get_ddr_bank_size(short cs, volatile long *base) +{ + /* This array lists all valid DDR SDRAM configurations, with + * Bank sizes in bytes. (Refer to Table 9-27 in the MPC8349E RM). + * The last entry has to to have size equal 0 and is igonred during + * autodection. Bank sizes must be in increasing order of size + */ + struct { + long row; + long col; + long size; + } conf[] = { + {CSCONFIG_ROW_BIT_12, CSCONFIG_COL_BIT_8, 32 << 20}, + {CSCONFIG_ROW_BIT_12, CSCONFIG_COL_BIT_9, 64 << 20}, + {CSCONFIG_ROW_BIT_12, CSCONFIG_COL_BIT_10, 128 << 20}, + {CSCONFIG_ROW_BIT_13, CSCONFIG_COL_BIT_9, 128 << 20}, + {CSCONFIG_ROW_BIT_13, CSCONFIG_COL_BIT_10, 256 << 20}, + {CSCONFIG_ROW_BIT_13, CSCONFIG_COL_BIT_11, 512 << 20}, + {CSCONFIG_ROW_BIT_14, CSCONFIG_COL_BIT_10, 512 << 20}, + {CSCONFIG_ROW_BIT_14, CSCONFIG_COL_BIT_11, 1024 << 20}, + {0, 0, 0} + }; + + int i; + int detected; + long size; + + detected = -1; + for(i = 0; conf[i].size != 0; ++i) { + + /* set sdram bank configuration */ + set_cs_config(cs, CSCONFIG_EN | conf[i].col | conf[i].row); + + debug("Getting RAM size...\n"); + size = get_ram_size(base, DDR_MAX_SIZE_PER_CS); + + if((size == conf[i].size) && (i == detected + 1)) + detected = i; + + debug("Trying %ld x %ld (%ld MiB) at addr %p, detected: %ld MiB\n", + conf[i].row, + conf[i].col, + conf[i].size >> 20, + base, + size >> 20); + } + + if(detected == -1){ + /* disable empty cs */ + debug("\nNo valid configurations for CS%d, disabling...\n", cs); + set_cs_config(cs, 0); + return 0; + } + + debug("\nDetected configuration %ld x %ld (%ld MiB) at addr %p\n", + conf[detected].row, conf[detected].col, conf[detected].size >> 20, base); + + /* configure cs ro detected params */ + set_cs_config(cs, CSCONFIG_EN | conf[detected].row | + conf[detected].col); + + set_cs_bounds(cs, (long)base, conf[detected].size); + + return(conf[detected].size); +} + +/************************************************************************** + * Sets DDR bank CS bounds. + */ +static void set_cs_bounds(short cs, long base, long size) +{ + debug("Setting bounds %08x, %08x for cs %d\n", base, size, cs); + if(size == 0){ + im->ddr.csbnds[cs].csbnds = 0x00000000; + } else { + im->ddr.csbnds[cs].csbnds = + ((base >> CSBNDS_SA_SHIFT) & CSBNDS_SA) | + (((base + size - 1) >> CSBNDS_EA_SHIFT) & + CSBNDS_EA); + } + SYNC; +} + +/************************************************************************** + * Sets DDR banks CS configuration. + * config == 0x00000000 disables the CS. + */ +static void set_cs_config(short cs, long config) +{ + debug("Setting config %08x for cs %d\n", config, cs); + im->ddr.cs_config[cs] = config; + SYNC; +} + +/************************************************************************** + * Sets DDR clocks, timings and configuration. + */ +static void set_ddr_config(void) { + /* clock control */ + im->ddr.sdram_clk_cntl = DDR_SDRAM_CLK_CNTL_SS_EN | + DDR_SDRAM_CLK_CNTL_CLK_ADJUST_05; + SYNC; + + /* timing configuration */ + im->ddr.timing_cfg_1 = + (4 << TIMING_CFG1_PRETOACT_SHIFT) | + (7 << TIMING_CFG1_ACTTOPRE_SHIFT) | + (4 << TIMING_CFG1_ACTTORW_SHIFT) | + (5 << TIMING_CFG1_REFREC_SHIFT) | + (3 << TIMING_CFG1_WRREC_SHIFT) | + (3 << TIMING_CFG1_ACTTOACT_SHIFT) | + (1 << TIMING_CFG1_WRTORD_SHIFT) | + (TIMING_CFG1_CASLAT & TIMING_CASLAT); + + im->ddr.timing_cfg_2 = + TIMING_CFG2_CPO_DEF | + (2 << TIMING_CFG2_WR_DATA_DELAY_SHIFT); + SYNC; + + /* don't enable DDR controller yet */ + im->ddr.sdram_cfg = + SDRAM_CFG_SREN | + SDRAM_CFG_SDRAM_TYPE_DDR1; + SYNC; + + /* Set SDRAM mode */ + im->ddr.sdram_mode = + ((DDR_MODE_EXT_MODEREG | DDR_MODE_WEAK) << + SDRAM_MODE_ESD_SHIFT) | + ((DDR_MODE_MODEREG | DDR_MODE_BLEN_4) << + SDRAM_MODE_SD_SHIFT) | + ((DDR_MODE_CASLAT << SDRAM_MODE_SD_SHIFT) & + MODE_CASLAT); + SYNC; + + /* Set fast SDRAM refresh rate */ + im->ddr.sdram_interval = + (DDR_REFINT_166MHZ_7US << SDRAM_INTERVAL_REFINT_SHIFT) | + (DDR_BSTOPRE << SDRAM_INTERVAL_BSTOPRE_SHIFT); + SYNC; + + /* Workaround for DDR6 Erratum + * see MPC8349E Device Errata Rev.8, 2/2006 + * This workaround influences the MPC internal "input enables" + * dependent on CAS latency and MPC revision. According to errata + * sheet the internal reserved registers for this workaround are + * not available from revision 2.0 and up. + */ + + /* Get REVID from register SPRIDR. Skip workaround if rev >= 2.0 + * (0x200) + */ + if ((im->sysconf.spridr & SPRIDR_REVID) < 0x200) { + + /* There is a internal reserved register at IMMRBAR+0x2F00 + * which has to be written with a certain value defined by + * errata sheet. + */ + u32 *reserved_p = (u32 *)((u8 *)im + 0x2f00); + +#if defined(DDR_CASLAT_20) + *reserved_p = 0x201c0000; +#else + *reserved_p = 0x202c0000; +#endif + } +} |