diff options
author | Wolfgang Denk <wd@pollux.denx.de> | 2005-10-15 18:23:43 +0200 |
---|---|---|
committer | Wolfgang Denk <wd@pollux.denx.de> | 2005-10-15 18:23:43 +0200 |
commit | 84bd92bdda05e6aaae3150ed6ef957b3a67398b7 (patch) | |
tree | ea5e3abbeff7e3f8412a2e34645b9773f50578e8 /board/tqm834x | |
parent | 77ddac9480d63a80b6bb76d7ee4dcc2d1070867e (diff) | |
parent | 36247821ef77cc13d5f9fdbf7771564f9f8386bd (diff) | |
download | u-boot-imx-84bd92bdda05e6aaae3150ed6ef957b3a67398b7.zip u-boot-imx-84bd92bdda05e6aaae3150ed6ef957b3a67398b7.tar.gz u-boot-imx-84bd92bdda05e6aaae3150ed6ef957b3a67398b7.tar.bz2 |
Merge with /home/m8/git/u-boot
Diffstat (limited to 'board/tqm834x')
-rw-r--r-- | board/tqm834x/Makefile | 45 | ||||
-rw-r--r-- | board/tqm834x/config.mk | 24 | ||||
-rw-r--r-- | board/tqm834x/tqm834x.c | 416 | ||||
-rw-r--r-- | board/tqm834x/u-boot.lds | 121 |
4 files changed, 606 insertions, 0 deletions
diff --git a/board/tqm834x/Makefile b/board/tqm834x/Makefile new file mode 100644 index 0000000..4327b0d --- /dev/null +++ b/board/tqm834x/Makefile @@ -0,0 +1,45 @@ +# +# 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 = lib$(BOARD).a + +OBJS := $(BOARD).o + +$(LIB): $(OBJS) $(SOBJS) + $(AR) crv $@ $(OBJS) + +clean: + rm -f $(SOBJS) $(OBJS) + +distclean: clean + rm -f $(LIB) core *.bak .depend + +######################################################################### + +.depend: Makefile $(SOBJS:.o=.S) $(OBJS:.o=.c) + $(CC) -M $(CPPFLAGS) $(SOBJS:.o=.S) $(OBJS:.o=.c) > $@ + +-include .depend + +######################################################################### diff --git a/board/tqm834x/config.mk b/board/tqm834x/config.mk new file mode 100644 index 0000000..9295e77 --- /dev/null +++ b/board/tqm834x/config.mk @@ -0,0 +1,24 @@ +# +# 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/tqm834x/tqm834x.c b/board/tqm834x/tqm834x.c new file mode 100644 index 0000000..9e620eb --- /dev/null +++ b/board/tqm834x/tqm834x.c @@ -0,0 +1,416 @@ +/* + * (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 <spd.h> +#include <miiphy.h> +#include <asm-ppc/mmu.h> + +#if defined(CONFIG_PCI) +#include <pci.h> +#endif + +#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[]; +extern long spd_sdram (void); + +/* 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_IMMRBAR; + +/************************************************************************** + * 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_DDR); + 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 + printf("PCI1: 32 bit, %d MHz (compiled)\n", + CONFIG_SYS_CLK_FREQ / 1000000); +#else + printf("PCI1: disabled\n"); +#endif + + return 0; +} + +#if defined(CONFIG_PCI) +/* + * Initialize PCI Devices, report devices found + */ + +/* FIXME: No PCI support */ + +#endif /* CONFIG_PCI */ + +/************************************************************************** + * pci_init_board() + */ +void +pci_init_board(void) +{ +#ifdef CONFIG_PCI + extern void pci_mpc83xx_init(volatile struct pci_controller *hose); + + pci_mpc83xx_init(hose); +#endif /* CONFIG_PCI */ +} + +/************************************************************************** + * + * 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_DDR; + 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; +} diff --git a/board/tqm834x/u-boot.lds b/board/tqm834x/u-boot.lds new file mode 100644 index 0000000..be3e5e8 --- /dev/null +++ b/board/tqm834x/u-boot.lds @@ -0,0 +1,121 @@ +/* + * 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 + */ + +OUTPUT_ARCH(powerpc) +SECTIONS +{ + /* Read-only sections, merged into text segment: */ + . = + SIZEOF_HEADERS; + .interp : { *(.interp) } + .hash : { *(.hash) } + .dynsym : { *(.dynsym) } + .dynstr : { *(.dynstr) } + .rel.text : { *(.rel.text) } + .rela.text : { *(.rela.text) } + .rel.data : { *(.rel.data) } + .rela.data : { *(.rela.data) } + .rel.rodata : { *(.rel.rodata) } + .rela.rodata : { *(.rela.rodata) } + .rel.got : { *(.rel.got) } + .rela.got : { *(.rela.got) } + .rel.ctors : { *(.rel.ctors) } + .rela.ctors : { *(.rela.ctors) } + .rel.dtors : { *(.rel.dtors) } + .rela.dtors : { *(.rela.dtors) } + .rel.bss : { *(.rel.bss) } + .rela.bss : { *(.rela.bss) } + .rel.plt : { *(.rel.plt) } + .rela.plt : { *(.rela.plt) } + .init : { *(.init) } + .plt : { *(.plt) } + .text : + { + cpu/mpc83xx/start.o (.text) + *(.text) + *(.fixup) + *(.got1) + . = ALIGN(16); + *(.rodata) + *(.rodata1) + *(.rodata.str1.4) + } + .fini : { *(.fini) } =0 + .ctors : { *(.ctors) } + .dtors : { *(.dtors) } + + /* Read-write section, merged into data segment: */ + . = (. + 0x0FFF) & 0xFFFFF000; + _erotext = .; + PROVIDE (erotext = .); + .reloc : + { + *(.got) + _GOT2_TABLE_ = .; + *(.got2) + _FIXUP_TABLE_ = .; + *(.fixup) + } + __got2_entries = (_FIXUP_TABLE_ - _GOT2_TABLE_) >> 2; + __fixup_entries = (. - _FIXUP_TABLE_) >> 2; + + .data : + { + *(.data) + *(.data1) + *(.sdata) + *(.sdata2) + *(.dynamic) + CONSTRUCTORS + } + _edata = .; + PROVIDE (edata = .); + + . = .; + __u_boot_cmd_start = .; + .u_boot_cmd : { *(.u_boot_cmd) } + __u_boot_cmd_end = .; + + + . = .; + __start___ex_table = .; + __ex_table : { *(__ex_table) } + __stop___ex_table = .; + + . = ALIGN(4096); + __init_begin = .; + .text.init : { *(.text.init) } + .data.init : { *(.data.init) } + . = ALIGN(4096); + __init_end = .; + + __bss_start = .; + .bss : + { + *(.sbss) *(.scommon) + *(.dynbss) + *(.bss) + *(COMMON) + } + _end = . ; + PROVIDE (end = .); +} +ENTRY(_start) |