diff options
Diffstat (limited to 'board/armltd')
22 files changed, 3663 insertions, 0 deletions
diff --git a/board/armltd/.gitignore b/board/armltd/.gitignore new file mode 100644 index 0000000..a3df156 --- /dev/null +++ b/board/armltd/.gitignore @@ -0,0 +1,2 @@ +/integratorap/u-boot.lds +/integratorcp/u-boot.lds diff --git a/board/armltd/integratorap/Makefile b/board/armltd/integratorap/Makefile new file mode 100644 index 0000000..79f501a --- /dev/null +++ b/board/armltd/integratorap/Makefile @@ -0,0 +1,55 @@ +# +# (C) Copyright 2000-2006 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# (C) Copyright 2004 +# ARM Ltd. +# Philippe Robin, <philippe.robin@arm.com> +# +# 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 := integratorap.o flash.o +SOBJS := lowlevel_init.o + +SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) +OBJS := $(addprefix $(obj),$(COBJS)) +SOBJS := $(addprefix $(obj),$(SOBJS)) + +$(LIB): $(obj).depend $(OBJS) $(SOBJS) + $(AR) $(ARFLAGS) $@ $(OBJS) $(SOBJS) + +clean: + rm -f $(SOBJS) $(OBJS) + +distclean: clean + rm -f $(LIB) core *.bak $(obj).depend + +######################################################################### + +# defines $(obj).depend target +include $(SRCTREE)/rules.mk + +sinclude $(obj).depend + +######################################################################### diff --git a/board/armltd/integratorap/config.mk b/board/armltd/integratorap/config.mk new file mode 100644 index 0000000..e4c5c3b --- /dev/null +++ b/board/armltd/integratorap/config.mk @@ -0,0 +1,11 @@ +# +# image should be loaded at 0x01000000 +# + +TEXT_BASE = 0x01000000 + +ifneq ($(OBJTREE),$(SRCTREE)) +# We are building u-boot in a separate directory, use generated +# .lds script from OBJTREE directory. +LDSCRIPT := $(OBJTREE)/board/$(BOARDDIR)/u-boot.lds +endif diff --git a/board/armltd/integratorap/flash.c b/board/armltd/integratorap/flash.c new file mode 100644 index 0000000..0492be7 --- /dev/null +++ b/board/armltd/integratorap/flash.c @@ -0,0 +1,473 @@ +/* + * (C) Copyright 2001 + * Kyle Harris, Nexus Technologies, Inc. kharris@nexus-tech.net + * + * (C) Copyright 2001-2004 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * (C) Copyright 2003 + * Texas Instruments, <www.ti.com> + * Kshitij Gupta <Kshitij@ti.com> + * + * 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 <linux/byteorder/swab.h> + +#define PHYS_FLASH_SECT_SIZE 0x00020000 /* 256 KB sectors (x2) */ +flash_info_t flash_info[CONFIG_SYS_MAX_FLASH_BANKS]; /* info for FLASH chips */ + +/* Board support for 1 or 2 flash devices */ +#undef FLASH_PORT_WIDTH32 +#define FLASH_PORT_WIDTH16 + +#ifdef FLASH_PORT_WIDTH16 +#define FLASH_PORT_WIDTH ushort +#define FLASH_PORT_WIDTHV vu_short +#define SWAP(x) __swab16(x) +#else +#define FLASH_PORT_WIDTH ulong +#define FLASH_PORT_WIDTHV vu_long +#define SWAP(x) __swab32(x) +#endif + +#define FPW FLASH_PORT_WIDTH +#define FPWV FLASH_PORT_WIDTHV + +#define mb() __asm__ __volatile__ ("" : : : "memory") + + +/* Flash Organization Structure */ +typedef struct OrgDef { + unsigned int sector_number; + unsigned int sector_size; +} OrgDef; + + +/* Flash Organizations */ +OrgDef OrgIntel_28F256L18T[] = { + {4, 32 * 1024}, /* 4 * 32kBytes sectors */ + {255, 128 * 1024}, /* 255 * 128kBytes sectors */ +}; + + +/*----------------------------------------------------------------------- + * Functions + */ +unsigned long flash_init (void); +static ulong flash_get_size (FPW * addr, flash_info_t * info); +static int write_data (flash_info_t * info, ulong dest, FPW data); +static void flash_get_offsets (ulong base, flash_info_t * info); +void inline spin_wheel (void); +void flash_print_info (flash_info_t * info); +void flash_unprotect_sectors (FPWV * addr); +int flash_erase (flash_info_t * info, int s_first, int s_last); +int write_buff (flash_info_t * info, uchar * src, ulong addr, ulong cnt); + +/*----------------------------------------------------------------------- + */ + +unsigned long flash_init (void) +{ + int i; + ulong size = 0; + for (i = 0; i < CONFIG_SYS_MAX_FLASH_BANKS; i++) { + switch (i) { + case 0: + flash_get_size ((FPW *) PHYS_FLASH_1, &flash_info[i]); + flash_get_offsets (PHYS_FLASH_1, &flash_info[i]); + break; + default: + panic ("configured too many flash banks!\n"); + break; + } + size += flash_info[i].size; + } + + /* Protect monitor and environment sectors + */ + flash_protect (FLAG_PROTECT_SET, + CONFIG_SYS_FLASH_BASE, + CONFIG_SYS_FLASH_BASE + monitor_flash_len - 1, &flash_info[0]); + + return size; +} + +/*----------------------------------------------------------------------- + */ +static void flash_get_offsets (ulong base, flash_info_t * info) +{ + int i; + OrgDef *pOrgDef; + + pOrgDef = OrgIntel_28F256L18T; + if (info->flash_id == FLASH_UNKNOWN) { + return; + } + + if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_INTEL) { + for (i = 0; i < info->sector_count; i++) { + if (i > 255) { + info->start[i] = base + (i * 0x8000); + info->protect[i] = 0; + } else { + info->start[i] = base + + (i * PHYS_FLASH_SECT_SIZE); + info->protect[i] = 0; + } + } + } +} + +/*----------------------------------------------------------------------- + */ +void flash_print_info (flash_info_t * info) +{ + int i; + + if (info->flash_id == FLASH_UNKNOWN) { + printf ("missing or unknown FLASH type\n"); + return; + } + + switch (info->flash_id & FLASH_VENDMASK) { + case FLASH_MAN_INTEL: + printf ("INTEL "); + break; + default: + printf ("Unknown Vendor "); + break; + } + + switch (info->flash_id & FLASH_TYPEMASK) { + case FLASH_28F256L18T: + printf ("FLASH 28F256L18T\n"); + break; + default: + printf ("Unknown Chip Type\n"); + break; + } + + printf (" Size: %ld MB in %d Sectors\n", + info->size >> 20, info->sector_count); + + printf (" Sector Start Addresses:"); + for (i = 0; i < info->sector_count; ++i) { + if ((i % 5) == 0) + printf ("\n "); + printf (" %08lX%s", + info->start[i], info->protect[i] ? " (RO)" : " "); + } + printf ("\n"); + return; +} + +/* + * The following code cannot be run from FLASH! + */ +static ulong flash_get_size (FPW * addr, flash_info_t * info) +{ + volatile FPW value; + + /* Write auto select command: read Manufacturer ID */ + addr[0x5555] = (FPW) 0x00AA00AA; + addr[0x2AAA] = (FPW) 0x00550055; + addr[0x5555] = (FPW) 0x00900090; + + mb (); + value = addr[0]; + + switch (value) { + + case (FPW) INTEL_MANUFACT: + info->flash_id = FLASH_MAN_INTEL; + break; + + default: + info->flash_id = FLASH_UNKNOWN; + info->sector_count = 0; + info->size = 0; + addr[0] = (FPW) 0x00FF00FF; /* restore read mode */ + return (0); /* no or unknown flash */ + } + + mb (); + value = addr[1]; /* device ID */ + switch (value) { + + case (FPW) (INTEL_ID_28F256L18T): + info->flash_id += FLASH_28F256L18T; + info->sector_count = 259; + info->size = 0x02000000; + break; /* => 32 MB */ + + default: + info->flash_id = FLASH_UNKNOWN; + break; + } + + if (info->sector_count > CONFIG_SYS_MAX_FLASH_SECT) { + printf ("** ERROR: sector count %d > max (%d) **\n", + info->sector_count, CONFIG_SYS_MAX_FLASH_SECT); + info->sector_count = CONFIG_SYS_MAX_FLASH_SECT; + } + + addr[0] = (FPW) 0x00FF00FF; /* restore read mode */ + + return (info->size); +} + + +/* unprotects a sector for write and erase + * on some intel parts, this unprotects the entire chip, but it + * wont hurt to call this additional times per sector... + */ +void flash_unprotect_sectors (FPWV * addr) +{ +#define PD_FINTEL_WSMS_READY_MASK 0x0080 + + *addr = (FPW) 0x00500050; /* clear status register */ + + /* this sends the clear lock bit command */ + *addr = (FPW) 0x00600060; + *addr = (FPW) 0x00D000D0; +} + + +/*----------------------------------------------------------------------- + */ + +int flash_erase (flash_info_t * info, int s_first, int s_last) +{ + int flag, prot, sect; + ulong type, start, last; + int rcode = 0; + + if ((s_first < 0) || (s_first > s_last)) { + if (info->flash_id == FLASH_UNKNOWN) { + printf ("- missing\n"); + } else { + printf ("- no sectors to erase\n"); + } + return 1; + } + + type = (info->flash_id & FLASH_VENDMASK); + if ((type != FLASH_MAN_INTEL)) { + printf ("Can't erase unknown flash type %08lx - aborted\n", + info->flash_id); + return 1; + } + + prot = 0; + for (sect = s_first; sect <= s_last; ++sect) { + if (info->protect[sect]) { + prot++; + } + } + + if (prot) { + printf ("- Warning: %d protected sectors will not be erased!\n", + prot); + } else { + printf ("\n"); + } + + + start = get_timer (0); + last = start; + + /* Disable interrupts which might cause a timeout here */ + flag = disable_interrupts (); + + /* Start erase on unprotected sectors */ + for (sect = s_first; sect <= s_last; sect++) { + if (info->protect[sect] == 0) { /* not protected */ + FPWV *addr = (FPWV *) (info->start[sect]); + FPW status; + + printf ("Erasing sector %2d ... ", sect); + + flash_unprotect_sectors (addr); + + /* arm simple, non interrupt dependent timer */ + reset_timer_masked (); + + *addr = (FPW) 0x00500050;/* clear status register */ + *addr = (FPW) 0x00200020;/* erase setup */ + *addr = (FPW) 0x00D000D0;/* erase confirm */ + + while (((status = + *addr) & (FPW) 0x00800080) != + (FPW) 0x00800080) { + if (get_timer_masked () > + CONFIG_SYS_FLASH_ERASE_TOUT) { + printf ("Timeout\n"); + /* suspend erase */ + *addr = (FPW) 0x00B000B0; + /* reset to read mode */ + *addr = (FPW) 0x00FF00FF; + rcode = 1; + break; + } + } + + /* clear status register cmd. */ + *addr = (FPW) 0x00500050; + *addr = (FPW) 0x00FF00FF;/* resest to read mode */ + printf (" done\n"); + } + } + return rcode; +} + +/*----------------------------------------------------------------------- + * Copy memory to flash, returns: + * 0 - OK + * 1 - write timeout + * 2 - Flash not erased + * 4 - Flash not identified + */ + +int write_buff (flash_info_t * info, uchar * src, ulong addr, ulong cnt) +{ + ulong cp, wp; + FPW data; + int count, i, l, rc, port_width; + + if (info->flash_id == FLASH_UNKNOWN) { + return 4; + } +/* get lower word aligned address */ +#ifdef FLASH_PORT_WIDTH16 + wp = (addr & ~1); + port_width = 2; +#else + wp = (addr & ~3); + port_width = 4; +#endif + + /* + * handle unaligned start bytes + */ + if ((l = addr - wp) != 0) { + data = 0; + for (i = 0, cp = wp; i < l; ++i, ++cp) { + data = (data << 8) | (*(uchar *) cp); + } + for (; i < port_width && cnt > 0; ++i) { + data = (data << 8) | *src++; + --cnt; + ++cp; + } + for (; cnt == 0 && i < port_width; ++i, ++cp) { + data = (data << 8) | (*(uchar *) cp); + } + + if ((rc = write_data (info, wp, SWAP (data))) != 0) { + return (rc); + } + wp += port_width; + } + + /* + * handle word aligned part + */ + count = 0; + while (cnt >= port_width) { + data = 0; + for (i = 0; i < port_width; ++i) { + data = (data << 8) | *src++; + } + if ((rc = write_data (info, wp, SWAP (data))) != 0) { + return (rc); + } + wp += port_width; + cnt -= port_width; + if (count++ > 0x800) { + spin_wheel (); + count = 0; + } + } + + if (cnt == 0) { + return (0); + } + + /* + * handle unaligned tail bytes + */ + data = 0; + for (i = 0, cp = wp; i < port_width && cnt > 0; ++i, ++cp) { + data = (data << 8) | *src++; + --cnt; + } + for (; i < port_width; ++i, ++cp) { + data = (data << 8) | (*(uchar *) cp); + } + + return (write_data (info, wp, SWAP (data))); +} + +/*----------------------------------------------------------------------- + * Write a word or halfword to Flash, returns: + * 0 - OK + * 1 - write timeout + * 2 - Flash not erased + */ +static int write_data (flash_info_t * info, ulong dest, FPW data) +{ + FPWV *addr = (FPWV *) dest; + ulong status; + int flag; + + /* Check if Flash is (sufficiently) erased */ + if ((*addr & data) != data) { + printf ("not erased at %08lx (%x)\n", (ulong) addr, *addr); + return (2); + } + flash_unprotect_sectors (addr); + /* Disable interrupts which might cause a timeout here */ + flag = disable_interrupts (); + *addr = (FPW) 0x00400040; /* write setup */ + *addr = data; + + /* arm simple, non interrupt dependent timer */ + reset_timer_masked (); + + /* wait while polling the status register */ + while (((status = *addr) & (FPW) 0x00800080) != (FPW) 0x00800080) { + if (get_timer_masked () > CONFIG_SYS_FLASH_WRITE_TOUT) { + *addr = (FPW) 0x00FF00FF; /* restore read mode */ + return (1); + } + } + *addr = (FPW) 0x00FF00FF; /* restore read mode */ + return (0); +} + +void inline spin_wheel (void) +{ + static int p = 0; + static char w[] = "\\/-"; + + printf ("\010%c", w[p]); + (++p == 3) ? (p = 0) : 0; +} diff --git a/board/armltd/integratorap/integratorap.c b/board/armltd/integratorap/integratorap.c new file mode 100644 index 0000000..ddacabb --- /dev/null +++ b/board/armltd/integratorap/integratorap.c @@ -0,0 +1,656 @@ +/* + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Marius Groeger <mgroeger@sysgo.de> + * + * (C) Copyright 2002 + * David Mueller, ELSOFT AG, <d.mueller@elsoft.ch> + * + * (C) Copyright 2003 + * Texas Instruments, <www.ti.com> + * Kshitij Gupta <Kshitij@ti.com> + * + * (C) Copyright 2004 + * ARM Ltd. + * Philippe Robin, <philippe.robin@arm.com> + * + * 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> + +#ifdef CONFIG_PCI +#include <pci.h> +#endif + +#include <netdev.h> + +DECLARE_GLOBAL_DATA_PTR; + +void flash__init (void); +void ether__init (void); +void peripheral_power_enable (void); + +#if defined(CONFIG_SHOW_BOOT_PROGRESS) +void show_boot_progress(int progress) +{ + printf("Boot reached stage %d\n", progress); +} +#endif + +#define COMP_MODE_ENABLE ((unsigned int)0x0000EAEF) + +static inline void delay (unsigned long loops) +{ + __asm__ volatile ("1:\n" + "subs %0, %1, #1\n" + "bne 1b":"=r" (loops):"0" (loops)); +} + +/* + * Miscellaneous platform dependent initialisations + */ + +int board_init (void) +{ + /* arch number of Integrator Board */ + gd->bd->bi_arch_number = MACH_TYPE_INTEGRATOR; + + /* adress of boot parameters */ + gd->bd->bi_boot_params = 0x00000100; + + gd->flags = 0; + +#ifdef CONFIG_CM_REMAP +extern void cm_remap(void); + cm_remap(); /* remaps writeable memory to 0x00000000 */ +#endif + + icache_enable (); + + flash__init (); + return 0; +} + + +int misc_init_r (void) +{ +#ifdef CONFIG_PCI + pci_init(); +#endif + setenv("verify", "n"); + return (0); +} + +/* + * Initialize PCI Devices, report devices found. + */ +#ifdef CONFIG_PCI + +#ifndef CONFIG_PCI_PNP + +static struct pci_config_table pci_integrator_config_table[] = { + { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, 0x0f, PCI_ANY_ID, + pci_cfgfunc_config_device, { PCI_ENET0_IOADDR, + PCI_ENET0_MEMADDR, + PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER }}, + { } +}; +#endif + +/* V3 access routines */ +#define _V3Write16(o,v) (*(volatile unsigned short *)(PCI_V3_BASE + (unsigned int)(o)) = (unsigned short)(v)) +#define _V3Read16(o) (*(volatile unsigned short *)(PCI_V3_BASE + (unsigned int)(o))) + +#define _V3Write32(o,v) (*(volatile unsigned int *)(PCI_V3_BASE + (unsigned int)(o)) = (unsigned int)(v)) +#define _V3Read32(o) (*(volatile unsigned int *)(PCI_V3_BASE + (unsigned int)(o))) + +/* Compute address necessary to access PCI config space for the given */ +/* bus and device. */ +#define PCI_CONFIG_ADDRESS( __bus, __devfn, __offset ) ({ \ + unsigned int __address, __devicebit; \ + unsigned short __mapaddress; \ + unsigned int __dev = PCI_DEV (__devfn); /* FIXME to check!! (slot?) */ \ + \ + if (__bus == 0) { \ + /* local bus segment so need a type 0 config cycle */ \ + /* build the PCI configuration "address" with one-hot in A31-A11 */ \ + __address = PCI_CONFIG_BASE; \ + __address |= ((__devfn & 0x07) << 8); \ + __address |= __offset & 0xFF; \ + __mapaddress = 0x000A; /* 101=>config cycle, 0=>A1=A0=0 */ \ + __devicebit = (1 << (__dev + 11)); \ + \ + if ((__devicebit & 0xFF000000) != 0) { \ + /* high order bits are handled by the MAP register */ \ + __mapaddress |= (__devicebit >> 16); \ + } else { \ + /* low order bits handled directly in the address */ \ + __address |= __devicebit; \ + } \ + } else { /* bus !=0 */ \ + /* not the local bus segment so need a type 1 config cycle */ \ + /* A31-A24 are don't care (so clear to 0) */ \ + __mapaddress = 0x000B; /* 101=>config cycle, 1=>A1&A0 from PCI_CFG */ \ + __address = PCI_CONFIG_BASE; \ + __address |= ((__bus & 0xFF) << 16); /* bits 23..16 = bus number */ \ + __address |= ((__dev & 0x1F) << 11); /* bits 15..11 = device number */ \ + __address |= ((__devfn & 0x07) << 8); /* bits 10..8 = function number */ \ + __address |= __offset & 0xFF; /* bits 7..0 = register number */ \ + } \ + _V3Write16 (V3_LB_MAP1, __mapaddress); \ + __address; \ +}) + +/* _V3OpenConfigWindow - open V3 configuration window */ +#define _V3OpenConfigWindow() { \ + /* Set up base0 to see all 512Mbytes of memory space (not */ \ + /* prefetchable), this frees up base1 for re-use by configuration*/ \ + /* memory */ \ + \ + _V3Write32 (V3_LB_BASE0, ((INTEGRATOR_PCI_BASE & 0xFFF00000) | \ + 0x90 | V3_LB_BASE_M_ENABLE)); \ + /* Set up base1 to point into configuration space, note that MAP1 */ \ + /* register is set up by pciMakeConfigAddress(). */ \ + \ + _V3Write32 (V3_LB_BASE1, ((CPU_PCI_CNFG_ADRS & 0xFFF00000) | \ + 0x40 | V3_LB_BASE_M_ENABLE)); \ +} + +/* _V3CloseConfigWindow - close V3 configuration window */ +#define _V3CloseConfigWindow() { \ + /* Reassign base1 for use by prefetchable PCI memory */ \ + _V3Write32 (V3_LB_BASE1, (((INTEGRATOR_PCI_BASE + 0x10000000) & 0xFFF00000) \ + | 0x84 | V3_LB_BASE_M_ENABLE)); \ + _V3Write16 (V3_LB_MAP1, \ + (((INTEGRATOR_PCI_BASE + 0x10000000) & 0xFFF00000) >> 16) | 0x0006); \ + \ + /* And shrink base0 back to a 256M window (NOTE: MAP0 already correct) */ \ + \ + _V3Write32 (V3_LB_BASE0, ((INTEGRATOR_PCI_BASE & 0xFFF00000) | \ + 0x80 | V3_LB_BASE_M_ENABLE)); \ +} + +static int pci_integrator_read_byte (struct pci_controller *hose, pci_dev_t dev, + int offset, unsigned char *val) +{ + _V3OpenConfigWindow (); + *val = *(volatile unsigned char *) PCI_CONFIG_ADDRESS (PCI_BUS (dev), + PCI_FUNC (dev), + offset); + _V3CloseConfigWindow (); + + return 0; +} + +static int pci_integrator_read__word (struct pci_controller *hose, + pci_dev_t dev, int offset, + unsigned short *val) +{ + _V3OpenConfigWindow (); + *val = *(volatile unsigned short *) PCI_CONFIG_ADDRESS (PCI_BUS (dev), + PCI_FUNC (dev), + offset); + _V3CloseConfigWindow (); + + return 0; +} + +static int pci_integrator_read_dword (struct pci_controller *hose, + pci_dev_t dev, int offset, + unsigned int *val) +{ + _V3OpenConfigWindow (); + *val = *(volatile unsigned short *) PCI_CONFIG_ADDRESS (PCI_BUS (dev), + PCI_FUNC (dev), + offset); + *val |= (*(volatile unsigned int *) + PCI_CONFIG_ADDRESS (PCI_BUS (dev), PCI_FUNC (dev), + (offset + 2))) << 16; + _V3CloseConfigWindow (); + + return 0; +} + +static int pci_integrator_write_byte (struct pci_controller *hose, + pci_dev_t dev, int offset, + unsigned char val) +{ + _V3OpenConfigWindow (); + *(volatile unsigned char *) PCI_CONFIG_ADDRESS (PCI_BUS (dev), + PCI_FUNC (dev), + offset) = val; + _V3CloseConfigWindow (); + + return 0; +} + +static int pci_integrator_write_word (struct pci_controller *hose, + pci_dev_t dev, int offset, + unsigned short val) +{ + _V3OpenConfigWindow (); + *(volatile unsigned short *) PCI_CONFIG_ADDRESS (PCI_BUS (dev), + PCI_FUNC (dev), + offset) = val; + _V3CloseConfigWindow (); + + return 0; +} + +static int pci_integrator_write_dword (struct pci_controller *hose, + pci_dev_t dev, int offset, + unsigned int val) +{ + _V3OpenConfigWindow (); + *(volatile unsigned short *) PCI_CONFIG_ADDRESS (PCI_BUS (dev), + PCI_FUNC (dev), + offset) = (val & 0xFFFF); + *(volatile unsigned short *) PCI_CONFIG_ADDRESS (PCI_BUS (dev), + PCI_FUNC (dev), + (offset + 2)) = ((val >> 16) & 0xFFFF); + _V3CloseConfigWindow (); + + return 0; +} +/****************************** + * PCI initialisation + ******************************/ + +struct pci_controller integrator_hose = { +#ifndef CONFIG_PCI_PNP + config_table: pci_integrator_config_table, +#endif +}; + +void pci_init_board (void) +{ + volatile int i, j; + struct pci_controller *hose = &integrator_hose; + + /* setting this register will take the V3 out of reset */ + + *(volatile unsigned int *) (INTEGRATOR_SC_PCIENABLE) = 1; + + /* wait a few usecs to settle the device and the PCI bus */ + + for (i = 0; i < 100; i++) + j = i + 1; + + /* Now write the Base I/O Address Word to V3_BASE + 0x6C */ + + *(volatile unsigned short *) (V3_BASE + V3_LB_IO_BASE) = + (unsigned short) (V3_BASE >> 16); + + do { + *(volatile unsigned char *) (V3_BASE + V3_MAIL_DATA) = 0xAA; + *(volatile unsigned char *) (V3_BASE + V3_MAIL_DATA + 4) = + 0x55; + } while (*(volatile unsigned char *) (V3_BASE + V3_MAIL_DATA) != 0xAA + || *(volatile unsigned char *) (V3_BASE + V3_MAIL_DATA + + 4) != 0x55); + + /* Make sure that V3 register access is not locked, if it is, unlock it */ + + if ((*(volatile unsigned short *) (V3_BASE + V3_SYSTEM) & + V3_SYSTEM_M_LOCK) + == V3_SYSTEM_M_LOCK) + *(volatile unsigned short *) (V3_BASE + V3_SYSTEM) = 0xA05F; + + /* Ensure that the slave accesses from PCI are disabled while we */ + /* setup windows */ + + *(volatile unsigned short *) (V3_BASE + V3_PCI_CMD) &= + ~(V3_COMMAND_M_MEM_EN | V3_COMMAND_M_IO_EN); + + /* Clear RST_OUT to 0; keep the PCI bus in reset until we've finished */ + + *(volatile unsigned short *) (V3_BASE + V3_SYSTEM) &= + ~V3_SYSTEM_M_RST_OUT; + + /* Make all accesses from PCI space retry until we're ready for them */ + + *(volatile unsigned short *) (V3_BASE + V3_PCI_CFG) |= + V3_PCI_CFG_M_RETRY_EN; + + /* Set up any V3 PCI Configuration Registers that we absolutely have to */ + /* LB_CFG controls Local Bus protocol. */ + /* Enable LocalBus byte strobes for READ accesses too. */ + /* set bit 7 BE_IMODE and bit 6 BE_OMODE */ + + *(volatile unsigned short *) (V3_BASE + V3_LB_CFG) |= 0x0C0; + + /* PCI_CMD controls overall PCI operation. */ + /* Enable PCI bus master. */ + + *(volatile unsigned short *) (V3_BASE + V3_PCI_CMD) |= 0x04; + + /* PCI_MAP0 controls where the PCI to CPU memory window is on Local Bus */ + + *(volatile unsigned int *) (V3_BASE + V3_PCI_MAP0) = + (INTEGRATOR_BOOT_ROM_BASE) | (V3_PCI_MAP_M_ADR_SIZE_512M | + V3_PCI_MAP_M_REG_EN | + V3_PCI_MAP_M_ENABLE); + + /* PCI_BASE0 is the PCI address of the start of the window */ + + *(volatile unsigned int *) (V3_BASE + V3_PCI_BASE0) = + INTEGRATOR_BOOT_ROM_BASE; + + /* PCI_MAP1 is LOCAL address of the start of the window */ + + *(volatile unsigned int *) (V3_BASE + V3_PCI_MAP1) = + (INTEGRATOR_HDR0_SDRAM_BASE) | (V3_PCI_MAP_M_ADR_SIZE_1024M | + V3_PCI_MAP_M_REG_EN | + V3_PCI_MAP_M_ENABLE); + + /* PCI_BASE1 is the PCI address of the start of the window */ + + *(volatile unsigned int *) (V3_BASE + V3_PCI_BASE1) = + INTEGRATOR_HDR0_SDRAM_BASE; + + /* Set up the windows from local bus memory into PCI configuration, */ + /* I/O and Memory. */ + /* PCI I/O, LB_BASE2 and LB_MAP2 are used exclusively for this. */ + + *(volatile unsigned short *) (V3_BASE + V3_LB_BASE2) = + ((CPU_PCI_IO_ADRS >> 24) << 8) | V3_LB_BASE_M_ENABLE; + *(volatile unsigned short *) (V3_BASE + V3_LB_MAP2) = 0; + + /* PCI Configuration, use LB_BASE1/LB_MAP1. */ + + /* PCI Memory use LB_BASE0/LB_MAP0 and LB_BASE1/LB_MAP1 */ + /* Map first 256Mbytes as non-prefetchable via BASE0/MAP0 */ + /* (INTEGRATOR_PCI_BASE == PCI_MEM_BASE) */ + + *(volatile unsigned int *) (V3_BASE + V3_LB_BASE0) = + INTEGRATOR_PCI_BASE | (0x80 | V3_LB_BASE_M_ENABLE); + + *(volatile unsigned short *) (V3_BASE + V3_LB_MAP0) = + ((INTEGRATOR_PCI_BASE >> 20) << 0x4) | 0x0006; + + /* Map second 256 Mbytes as prefetchable via BASE1/MAP1 */ + + *(volatile unsigned int *) (V3_BASE + V3_LB_BASE1) = + INTEGRATOR_PCI_BASE | (0x84 | V3_LB_BASE_M_ENABLE); + + *(volatile unsigned short *) (V3_BASE + V3_LB_MAP1) = + (((INTEGRATOR_PCI_BASE + 0x10000000) >> 20) << 4) | 0x0006; + + /* Allow accesses to PCI Configuration space */ + /* and set up A1, A0 for type 1 config cycles */ + + *(volatile unsigned short *) (V3_BASE + V3_PCI_CFG) = + ((*(volatile unsigned short *) (V3_BASE + V3_PCI_CFG)) & + ~(V3_PCI_CFG_M_RETRY_EN | V3_PCI_CFG_M_AD_LOW1)) | + V3_PCI_CFG_M_AD_LOW0; + + /* now we can allow in PCI MEMORY accesses */ + + *(volatile unsigned short *) (V3_BASE + V3_PCI_CMD) = + (*(volatile unsigned short *) (V3_BASE + V3_PCI_CMD)) | + V3_COMMAND_M_MEM_EN; + + /* Set RST_OUT to take the PCI bus is out of reset, PCI devices can */ + /* initialise and lock the V3 system register so that no one else */ + /* can play with it */ + + *(volatile unsigned short *) (V3_BASE + V3_SYSTEM) = + (*(volatile unsigned short *) (V3_BASE + V3_SYSTEM)) | + V3_SYSTEM_M_RST_OUT; + + *(volatile unsigned short *) (V3_BASE + V3_SYSTEM) = + (*(volatile unsigned short *) (V3_BASE + V3_SYSTEM)) | + V3_SYSTEM_M_LOCK; + + /* + * Register the hose + */ + hose->first_busno = 0; + hose->last_busno = 0xff; + + /* System memory space */ + pci_set_region (hose->regions + 0, + 0x00000000, 0x40000000, 0x01000000, + PCI_REGION_MEM | PCI_REGION_MEMORY); + + /* PCI Memory - config space */ + pci_set_region (hose->regions + 1, + 0x00000000, 0x62000000, 0x01000000, PCI_REGION_MEM); + + /* PCI V3 regs */ + pci_set_region (hose->regions + 2, + 0x00000000, 0x61000000, 0x00080000, PCI_REGION_MEM); + + /* PCI I/O space */ + pci_set_region (hose->regions + 3, + 0x00000000, 0x60000000, 0x00010000, PCI_REGION_IO); + + pci_set_ops (hose, + pci_integrator_read_byte, + pci_integrator_read__word, + pci_integrator_read_dword, + pci_integrator_write_byte, + pci_integrator_write_word, pci_integrator_write_dword); + + hose->region_count = 4; + + pci_register_hose (hose); + + pciauto_config_init (hose); + pciauto_config_device (hose, 0); + + hose->last_busno = pci_hose_scan (hose); +} +#endif + +/****************************** + Routine: + Description: +******************************/ +void flash__init (void) +{ +} +/************************************************************* + Routine:ether__init + Description: take the Ethernet controller out of reset and wait + for the EEPROM load to complete. +*************************************************************/ +void ether__init (void) +{ +} + +/****************************** + Routine: + Description: +******************************/ +int dram_init (void) +{ + gd->bd->bi_dram[0].start = PHYS_SDRAM_1; + gd->bd->bi_dram[0].size = PHYS_SDRAM_1_SIZE; + +#ifdef CONFIG_CM_SPD_DETECT + { +extern void dram_query(void); + unsigned long cm_reg_sdram; + unsigned long sdram_shift; + + dram_query(); /* Assembler accesses to CM registers */ + /* Queries the SPD values */ + + /* Obtain the SDRAM size from the CM SDRAM register */ + + cm_reg_sdram = *(volatile ulong *)(CM_BASE + OS_SDRAM); + /* Register SDRAM size + * + * 0xXXXXXXbbb000bb 16 MB + * 0xXXXXXXbbb001bb 32 MB + * 0xXXXXXXbbb010bb 64 MB + * 0xXXXXXXbbb011bb 128 MB + * 0xXXXXXXbbb100bb 256 MB + * + */ + sdram_shift = ((cm_reg_sdram & 0x0000001C)/4)%4; + gd->bd->bi_dram[0].size = 0x01000000 << sdram_shift; + + } +#endif /* CM_SPD_DETECT */ + + return 0; +} + +/* The Integrator/AP timer1 is clocked at 24MHz + * can be divided by 16 or 256 + * and is a 16-bit counter + */ +/* U-Boot expects a 32 bit timer running at CONFIG_SYS_HZ*/ +static ulong timestamp; /* U-Boot ticks since startup */ +static ulong total_count = 0; /* Total timer count */ +static ulong lastdec; /* Timer reading at last call */ +static ulong div_clock = 256; /* Divisor applied to the timer clock */ +static ulong div_timer = 1; /* Divisor to convert timer reading + * change to U-Boot ticks + */ +/* CONFIG_SYS_HZ = CONFIG_SYS_HZ_CLOCK/(div_clock * div_timer) */ + +#define TIMER_LOAD_VAL 0x0000FFFFL +#define READ_TIMER ((*(volatile ulong *)(CONFIG_SYS_TIMERBASE+4)) & 0x0000FFFFL) + +/* all function return values in U-Boot ticks i.e. (1/CONFIG_SYS_HZ) sec + * - unless otherwise stated + */ + +/* starts a counter + * - the Integrator/AP timer issues an interrupt + * each time it reaches zero + */ +int interrupt_init (void) +{ + /* Load timer with initial value */ + *(volatile ulong *)(CONFIG_SYS_TIMERBASE + 0) = TIMER_LOAD_VAL; + /* Set timer to be + * enabled 1 + * free-running 0 + * XX 00 + * divider 256 10 + * XX 00 + */ + *(volatile ulong *)(CONFIG_SYS_TIMERBASE + 8) = 0x00000088; + total_count = 0; + /* init the timestamp and lastdec value */ + reset_timer_masked(); + + div_timer = CONFIG_SYS_HZ_CLOCK / CONFIG_SYS_HZ; + div_timer /= div_clock; + + return (0); +} + +/* + * timer without interrupts + */ +void reset_timer (void) +{ + reset_timer_masked (); +} + +ulong get_timer (ulong base_ticks) +{ + return get_timer_masked () - base_ticks; +} + +void set_timer (ulong ticks) +{ + timestamp = ticks; + total_count = ticks * div_timer; + reset_timer_masked(); +} + +/* delay x useconds */ +void udelay (unsigned long usec) +{ + ulong tmo, tmp; + + /* Convert to U-Boot ticks */ + tmo = usec * CONFIG_SYS_HZ; + tmo /= (1000000L); + + tmp = get_timer_masked(); /* get current timestamp */ + tmo += tmp; /* wake up timestamp */ + + while (get_timer_masked () < tmo) { /* loop till event */ + /*NOP*/; + } +} + +void reset_timer_masked (void) +{ + /* reset time */ + lastdec = READ_TIMER; /* capture current decrementer value */ + timestamp = 0; /* start "advancing" time stamp from 0 */ +} + +/* converts the timer reading to U-Boot ticks */ +/* the timestamp is the number of ticks since reset */ +/* This routine does not detect wraps unless called regularly + ASSUMES a call at least every 16 seconds to detect every reload */ +ulong get_timer_masked (void) +{ + ulong now = READ_TIMER; /* current count */ + + if (now > lastdec) { + /* Must have wrapped */ + total_count += lastdec + TIMER_LOAD_VAL + 1 - now; + } else { + total_count += lastdec - now; + } + lastdec = now; + timestamp = total_count/div_timer; + + return timestamp; +} + +/* waits specified delay value and resets timestamp */ +void udelay_masked (unsigned long usec) +{ + udelay(usec); +} + +/* + * This function is derived from PowerPC code (read timebase as long long). + * On ARM it just returns the timer value. + */ +unsigned long long get_ticks(void) +{ + return get_timer(0); +} + +/* + * Return the timebase clock frequency + * i.e. how often the timer decrements + */ +ulong get_tbclk (void) +{ + return CONFIG_SYS_HZ_CLOCK/div_clock; +} + +int board_eth_init(bd_t *bis) +{ + return pci_eth_init(bis); +} diff --git a/board/armltd/integratorap/lowlevel_init.S b/board/armltd/integratorap/lowlevel_init.S new file mode 100644 index 0000000..ab9589c --- /dev/null +++ b/board/armltd/integratorap/lowlevel_init.S @@ -0,0 +1,213 @@ +/* + * Board specific setup info + * + * (C) Copyright 2004, ARM Ltd. + * Philippe Robin, <philippe.robin@arm.com> + * + * 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 <config.h> +#include <version.h> + + /* Reset using CM control register */ +.global reset_cpu +reset_cpu: + mov r0, #CM_BASE + ldr r1,[r0,#OS_CTRL] + orr r1,r1,#CMMASK_RESET + str r1,[r0,#OS_CTRL] + +reset_failed: + b reset_failed + +/* Set up the platform, once the cpu has been initialized */ +.globl lowlevel_init +lowlevel_init: + /* If U-Boot has been run after the ARM boot monitor + * then all the necessary actions have been done + * otherwise we are running from user flash mapped to 0x00000000 + * --- DO NOT REMAP BEFORE THE CODE HAS BEEN RELOCATED -- + * Changes to the (possibly soft) reset defaults of the processor + * itself should be performed in cpu/arm<>/start.S + * This function affects only the core module or board settings + */ + +#ifdef CONFIG_CM_INIT + /* CM has an initialization register + * - bits in it are wired into test-chip pins to force + * reset defaults + * - may need to change its contents for U-Boot + */ + + /* set the desired CM specific value */ + mov r2,#CMMASK_LOWVEC /* Vectors at 0x00000000 for all */ + +#if defined (CONFIG_CM10200E) || defined (CONFIG_CM10220E) + orr r2,r2,#CMMASK_INIT_102 +#else + +#if !defined (CONFIG_CM920T) && !defined (CONFIG_CM920T_ETM) && \ + !defined (CONFIG_CM940T) + +#ifdef CONFIG_CM_MULTIPLE_SSRAM + /* set simple mapping */ + and r2,r2,#CMMASK_MAP_SIMPLE +#endif /* #ifdef CONFIG_CM_MULTIPLE_SSRAM */ + +#ifdef CONFIG_CM_TCRAM + /* disable TCRAM */ + and r2,r2,#CMMASK_TCRAM_DISABLE +#endif /* #ifdef CONFIG_CM_TCRAM */ + +#if defined (CONFIG_CM926EJ_S) || defined (CONFIG_CM1026EJ_S) || \ + defined (CONFIG_CM1136JF_S) + + and r2,r2,#CMMASK_LE + +#endif /* cpu with little endian initialization */ + + orr r2,r2,#CMMASK_CMxx6_COMMON + +#endif /* CMxx6 code */ + +#endif /* ARM102xxE value */ + + /* read CM_INIT */ + mov r0, #CM_BASE + ldr r1, [r0, #OS_INIT] + /* check against desired bit setting */ + and r3,r1,r2 + cmp r3,r2 + beq init_reg_OK + + /* lock for change */ + mov r3, #CMVAL_LOCK1 + add r3,r3,#CMVAL_LOCK2 + str r3, [r0, #OS_LOCK] + /* set desired value */ + orr r1,r1,r2 + /* write & relock CM_INIT */ + str r1, [r0, #OS_INIT] + mov r1, #CMVAL_UNLOCK + str r1, [r0, #OS_LOCK] + + /* soft reset so new values used */ + b reset_cpu + +init_reg_OK: + +#endif /* CONFIG_CM_INIT */ + + mov pc, lr + +#ifdef CONFIG_CM_SPD_DETECT + /* Fast memory is available for the DRAM data + * - ensure it has been transferred, then summarize the data + * into a CM register + */ +.globl dram_query +dram_query: + stmfd r13!,{r4-r6,lr} + /* set up SDRAM info */ + /* - based on example code from the CM User Guide */ + mov r0, #CM_BASE + +readspdbit: + ldr r1, [r0, #OS_SDRAM] /* read the SDRAM register */ + and r1, r1, #0x20 /* mask SPD bit (5) */ + cmp r1, #0x20 /* test if set */ + bne readspdbit + +setupsdram: + add r0, r0, #OS_SPD /* address the copy of the SDP data */ + ldrb r1, [r0, #3] /* number of row address lines */ + ldrb r2, [r0, #4] /* number of column address lines */ + ldrb r3, [r0, #5] /* number of banks */ + ldrb r4, [r0, #31] /* module bank density */ + mul r5, r4, r3 /* size of SDRAM (MB divided by 4) */ + mov r5, r5, ASL#2 /* size in MB */ + mov r0, #CM_BASE /* reload for later code */ + cmp r5, #0x10 /* is it 16MB? */ + bne not16 + mov r6, #0x2 /* store size and CAS latency of 2 */ + b writesize + +not16: + cmp r5, #0x20 /* is it 32MB? */ + bne not32 + mov r6, #0x6 + b writesize + +not32: + cmp r5, #0x40 /* is it 64MB? */ + bne not64 + mov r6, #0xa + b writesize + +not64: + cmp r5, #0x80 /* is it 128MB? */ + bne not128 + mov r6, #0xe + b writesize + +not128: + /* if it is none of these sizes then it is either 256MB, or + * there is no SDRAM fitted so default to 256MB + */ + mov r6, #0x12 + +writesize: + mov r1, r1, ASL#8 /* row addr lines from SDRAM reg */ + orr r2, r1, r2, ASL#12 /* OR in column address lines */ + orr r3, r2, r3, ASL#16 /* OR in number of banks */ + orr r6, r6, r3 /* OR in size and CAS latency */ + str r6, [r0, #OS_SDRAM] /* store SDRAM parameters */ + +#endif /* #ifdef CONFIG_CM_SPD_DETECT */ + + ldmfd r13!,{r4-r6,pc} /* back to caller */ + +#ifdef CONFIG_CM_REMAP + /* CM remap bit is operational + * - use it to map writeable memory at 0x00000000, in place of flash + */ +.globl cm_remap +cm_remap: + stmfd r13!,{r4-r10,lr} + + mov r0, #CM_BASE + ldr r1, [r0, #OS_CTRL] + orr r1, r1, #CMMASK_REMAP /* set remap and led bits */ + str r1, [r0, #OS_CTRL] + + /* Now 0x00000000 is writeable, replace the vectors */ + ldr r0, =_start /* r0 <- start of vectors */ + ldr r2, =_armboot_start /* r2 <- past vectors */ + sub r1,r1,r1 /* destination 0x00000000 */ + +copy_vec: + ldmia r0!, {r3-r10} /* copy from source address [r0] */ + stmia r1!, {r3-r10} /* copy to target address [r1] */ + cmp r0, r2 /* until source end address [r2] */ + ble copy_vec + + ldmfd r13!,{r4-r10,pc} /* back to caller */ + +#endif /* #ifdef CONFIG_CM_REMAP */ diff --git a/board/armltd/integratorap/split_by_variant.sh b/board/armltd/integratorap/split_by_variant.sh new file mode 100755 index 0000000..51dc53f --- /dev/null +++ b/board/armltd/integratorap/split_by_variant.sh @@ -0,0 +1,119 @@ +#!/bin/sh +# --------------------------------------------------------- +# Set the platform defines +# --------------------------------------------------------- +echo -n "/* Integrator configuration implied " > tmp.fil +echo " by Makefile target */" >> tmp.fil +echo -n "#define CONFIG_INTEGRATOR" >> tmp.fil +echo " /* Integrator board */" >> tmp.fil +echo -n "#define CONFIG_ARCH_INTEGRATOR" >> tmp.fil +echo " 1 /* Integrator/AP */" >> tmp.fil +# --------------------------------------------------------- +# Set the core module defines according to Core Module +# --------------------------------------------------------- +cpu="arm_intcm" +variant="unknown core module" + +if [ "$1" = "" ] +then + echo "$0:: No parameters - using arm_intcm" +else + case "$1" in + ap7_config) + cpu="arm_intcm" + variant="unported core module CM7TDMI" + ;; + + ap966) + cpu="arm_intcm" + variant="unported core module CM966E-S" + ;; + + ap922_config) + cpu="arm_intcm" + variant="unported core module CM922T" + ;; + + integratorap_config | \ + ap_config) + cpu="arm_intcm" + variant="unspecified core module" + ;; + + ap720t_config) + cpu="arm720t" + echo -n "#define CONFIG_CM720T" >> tmp.fil + echo " 1 /* CPU core is ARM720T */ " >> tmp.fil + variant="Core module CM720T" + ;; + + ap922_XA10_config) + cpu="arm_intcm" + variant="unported core module CM922T_XA10" + echo -n "#define CONFIG_CM922T_XA10" >> tmp.fil + echo " 1 /* CPU core is ARM922T_XA10 */" >> tmp.fil + ;; + + ap920t_config) + cpu="arm920t" + variant="Core module CM920T" + echo -n "#define CONFIG_CM920T" >> tmp.fil + echo " 1 /* CPU core is ARM920T */" >> tmp.fil + ;; + + ap926ejs_config) + cpu="arm926ejs" + variant="Core module CM926EJ-S" + echo -n "#define CONFIG_CM926EJ_S" >> tmp.fil + echo " 1 /* CPU core is ARM926EJ-S */ " >> tmp.fil + ;; + + ap946es_config) + cpu="arm946es" + variant="Core module CM946E-S" + echo -n "#define CONFIG_CM946E_S" >> tmp.fil + echo " 1 /* CPU core is ARM946E-S */ " >> tmp.fil + ;; + + *) + echo "$0:: Unknown core module" + variant="unknown core module" + cpu="arm_intcm" + ;; + + esac +fi + +if [ "$cpu" = "arm_intcm" ] +then + echo "/* Core module undefined/not ported */" >> tmp.fil + echo "#define CONFIG_ARM_INTCM 1" >> tmp.fil + echo -n "#undef CONFIG_CM_MULTIPLE_SSRAM" >> tmp.fil + echo -n " /* CM may not have " >> tmp.fil + echo "multiple SSRAM mapping */" >> tmp.fil + echo -n "#undef CONFIG_CM_SPD_DETECT " >> tmp.fil + echo -n " /* CM may not support SPD " >> tmp.fil + echo "query */" >> tmp.fil + echo -n "#undef CONFIG_CM_REMAP " >> tmp.fil + echo -n " /* CM may not support " >> tmp.fil + echo "remapping */" >> tmp.fil + echo -n "#undef CONFIG_CM_INIT " >> tmp.fil + echo -n " /* CM may not have " >> tmp.fil + echo "initialization reg */" >> tmp.fil + echo -n "#undef CONFIG_CM_TCRAM " >> tmp.fil + echo " /* CM may not have TCRAM */" >> tmp.fil +fi + +mkdir -p ${obj}include +mkdir -p ${obj}board/armltd/integratorap +mv tmp.fil ${obj}include/config.h +# --------------------------------------------------------- +# Ensure correct core object loaded first in U-Boot image +# --------------------------------------------------------- +sed -r 's/CPU_FILE/cpu\/'$cpu'\/start.o/; s/#.*//' ${src}board/armltd/integratorap/u-boot.lds.template > ${obj}board/armltd/integratorap/u-boot.lds +# --------------------------------------------------------- +# Complete the configuration +# --------------------------------------------------------- +$MKCONFIG -a integratorap arm $cpu integratorap armltd; +echo "Variant:: $variant with core $cpu" + diff --git a/board/armltd/integratorap/u-boot.lds.template b/board/armltd/integratorap/u-boot.lds.template new file mode 100644 index 0000000..0ec8087 --- /dev/null +++ b/board/armltd/integratorap/u-boot.lds.template @@ -0,0 +1,53 @@ +/* + * (C) Copyright 2002 + * Gary Jennejohn, DENX Software Engineering, <gj@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 + */ +# Template used during configuration to emsure the core module processor code, +# from CPU_FILE, is placed at the start of the image */ + +OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") +OUTPUT_ARCH(arm) +ENTRY(_start) +SECTIONS +{ + . = 0x00000000; + . = ALIGN(4); + .text : + { + CPU_FILE (.text) + *(.text) + } + .rodata : { *(.rodata) } + . = ALIGN(4); + .data : { *(.data) } + . = ALIGN(4); + .got : { *(.got) } + + . = .; + __u_boot_cmd_start = .; + .u_boot_cmd : { *(.u_boot_cmd) } + __u_boot_cmd_end = .; + + . = ALIGN(4); + __bss_start = .; + .bss : { *(.bss) } + _end = .; +} diff --git a/board/armltd/integratorcp/Makefile b/board/armltd/integratorcp/Makefile new file mode 100644 index 0000000..92a1a07 --- /dev/null +++ b/board/armltd/integratorcp/Makefile @@ -0,0 +1,51 @@ +# +# (C) Copyright 2000-2006 +# 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 $(TOPDIR)/config.mk + +LIB = $(obj)lib$(BOARD).a + +COBJS := integratorcp.o flash.o +SOBJS := lowlevel_init.o + +SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) +OBJS := $(addprefix $(obj),$(COBJS)) +SOBJS := $(addprefix $(obj),$(SOBJS)) + +$(LIB): $(obj).depend $(OBJS) $(SOBJS) + $(AR) $(ARFLAGS) $@ $(OBJS) $(SOBJS) + +clean: + rm -f $(SOBJS) $(OBJS) + +distclean: clean + rm -f $(LIB) core *.bak $(obj).depend + +######################################################################### + +# defines $(obj).depend target +include $(SRCTREE)/rules.mk + +sinclude $(obj).depend + +######################################################################### diff --git a/board/armltd/integratorcp/config.mk b/board/armltd/integratorcp/config.mk new file mode 100644 index 0000000..e4c5c3b --- /dev/null +++ b/board/armltd/integratorcp/config.mk @@ -0,0 +1,11 @@ +# +# image should be loaded at 0x01000000 +# + +TEXT_BASE = 0x01000000 + +ifneq ($(OBJTREE),$(SRCTREE)) +# We are building u-boot in a separate directory, use generated +# .lds script from OBJTREE directory. +LDSCRIPT := $(OBJTREE)/board/$(BOARDDIR)/u-boot.lds +endif diff --git a/board/armltd/integratorcp/flash.c b/board/armltd/integratorcp/flash.c new file mode 100644 index 0000000..5059dae --- /dev/null +++ b/board/armltd/integratorcp/flash.c @@ -0,0 +1,564 @@ +/* + * (C) Copyright 2004 + * Xiaogeng (Shawn) Jin, Agilent Technologies, xiaogeng_jin@agilent.com + * + * (C) Copyright 2001 + * Kyle Harris, Nexus Technologies, Inc. kharris@nexus-tech.net + * + * (C) Copyright 2001-2004 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * (C) Copyright 2003 + * Texas Instruments, <www.ti.com> + * Kshitij Gupta <Kshitij@ti.com> + * + * 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 <linux/byteorder/swab.h> + +#define DEBUG + +#define PHYS_FLASH_SECT_SIZE 0x00040000 /* 256 KB sectors (x2) */ +flash_info_t flash_info[CONFIG_SYS_MAX_FLASH_BANKS]; /* info for FLASH chips */ + +/* Board support for 1 or 2 flash devices */ +#define FLASH_PORT_WIDTH32 +#undef FLASH_PORT_WIDTH16 + +#ifdef FLASH_PORT_WIDTH16 +#define FLASH_PORT_WIDTH ushort +#define FLASH_PORT_WIDTHV vu_short +#define SWAP(x) __swab16(x) +#else +#define FLASH_PORT_WIDTH ulong +#define FLASH_PORT_WIDTHV vu_long +#define SWAP(x) __swab32(x) +#endif + +#define FPW FLASH_PORT_WIDTH +#define FPWV FLASH_PORT_WIDTHV + +#define mb() __asm__ __volatile__ ("" : : : "memory") + + +/* Flash Organization Structure */ +typedef struct OrgDef { + unsigned int sector_number; + unsigned int sector_size; +} OrgDef; + + +/* Flash Organizations */ +OrgDef OrgIntel_28F256L18T[] = { + {4, 32 * 1024}, /* 4 * 32kBytes sectors */ + {255, 128 * 1024}, /* 255 * 128kBytes sectors */ +}; + +/* CP control register base address */ +#define CPCR_BASE 0xCB000000 +#define CPCR_EXTRABANK 0x8 +#define CPCR_FLASHSIZE 0x4 +#define CPCR_FLWREN 0x2 +#define CPCR_FLVPPEN 0x1 + +/*----------------------------------------------------------------------- + * Functions + */ +unsigned long flash_init (void); +static ulong flash_get_size (FPW * addr, flash_info_t * info); +static int write_data (flash_info_t * info, ulong dest, FPW data); +static void flash_get_offsets (ulong base, flash_info_t * info); +void inline spin_wheel (void); +void flash_print_info (flash_info_t * info); +void flash_unprotect_sectors (FPWV * addr); +int flash_erase (flash_info_t * info, int s_first, int s_last); +int write_buff (flash_info_t * info, uchar * src, ulong addr, ulong cnt); + +/*----------------------------------------------------------------------- + */ +unsigned long flash_init (void) +{ + int i, nbanks; + ulong size = 0; + vu_long *cpcr = (vu_long *)CPCR_BASE; + + /* Check if there is an extra bank of flash */ + if (cpcr[1] & CPCR_EXTRABANK) + nbanks = 2; + else + nbanks = 1; + + if (nbanks > CONFIG_SYS_MAX_FLASH_BANKS) + nbanks = CONFIG_SYS_MAX_FLASH_BANKS; + + /* Enable flash write */ + cpcr[1] |= 3; + + for (i = 0; i < nbanks; i++) { + flash_get_size ((FPW *)(CONFIG_SYS_FLASH_BASE + size), &flash_info[i]); + flash_get_offsets (CONFIG_SYS_FLASH_BASE + size, &flash_info[i]); + size += flash_info[i].size; + } + +#if CONFIG_SYS_MONITOR_BASE >= CONFIG_SYS_FLASH_BASE + /* monitor protection */ + flash_protect (FLAG_PROTECT_SET, + CONFIG_SYS_MONITOR_BASE, + CONFIG_SYS_MONITOR_BASE + monitor_flash_len - 1, &flash_info[0]); +#endif + +#ifdef CONFIG_ENV_IS_IN_FLASH + /* ENV protection ON */ + flash_protect(FLAG_PROTECT_SET, + CONFIG_ENV_ADDR, + CONFIG_ENV_ADDR + CONFIG_ENV_SECT_SIZE - 1, + &flash_info[0]); +#endif + + /* Protect SIB (0x24800000) and bootMonitor (0x24c00000) */ + flash_protect (FLAG_PROTECT_SET, + flash_info[0].start[62], + flash_info[0].start[63] + PHYS_FLASH_SECT_SIZE - 1, + &flash_info[0]); + + return size; +} + +/*----------------------------------------------------------------------- + */ +static void flash_get_offsets (ulong base, flash_info_t * info) +{ + int i; + + if (info->flash_id == FLASH_UNKNOWN) { + return; + } + + if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_INTEL) { + for (i = 0; i < info->sector_count; i++) { + info->start[i] = base + (i * PHYS_FLASH_SECT_SIZE); + info->protect[i] = 0; + } + } +} + +/*----------------------------------------------------------------------- + */ +void flash_print_info (flash_info_t * info) +{ + int i; + + if (info->flash_id == FLASH_UNKNOWN) { + printf ("missing or unknown FLASH type\n"); + return; + } + + switch (info->flash_id & FLASH_VENDMASK) { + case FLASH_MAN_INTEL: + printf ("INTEL "); + break; + default: + printf ("Unknown Vendor "); + break; + } + + /* Integrator CP board uses 28F640J3C or 28F128J3C parts, + * which have the same device id numbers as 28F640J3A or + * 28F128J3A + */ + switch (info->flash_id & FLASH_TYPEMASK) { + case FLASH_28F256L18T: + printf ("FLASH 28F256L18T\n"); + break; + case FLASH_28F640J3A: + printf ("FLASH 28F640J3C\n"); + break; + case FLASH_28F128J3A: + printf ("FLASH 28F128J3C\n"); + break; + default: + printf ("Unknown Chip Type\n"); + break; + } + + printf (" Size: %ld MB in %d Sectors\n", + info->size >> 20, info->sector_count); + + printf (" Sector Start Addresses:"); + for (i = 0; i < info->sector_count; ++i) { + if ((i % 5) == 0) + printf ("\n "); + printf (" %08lX%s", + info->start[i], info->protect[i] ? " (RO)" : " "); + } + printf ("\n"); + return; +} + +/* + * The following code cannot be run from FLASH! + */ +static ulong flash_get_size (FPW * addr, flash_info_t * info) +{ + volatile FPW value; + vu_long *cpcr = (vu_long *)CPCR_BASE; + int nsects; + + /* Check the flash size */ + if (cpcr[1] & CPCR_FLASHSIZE) + nsects = 128; + else + nsects = 64; + + if (nsects > CONFIG_SYS_MAX_FLASH_SECT) + nsects = CONFIG_SYS_MAX_FLASH_SECT; + + /* Write auto select command: read Manufacturer ID */ + addr[0x5555] = (FPW) 0x00AA00AA; + addr[0x2AAA] = (FPW) 0x00550055; + addr[0x5555] = (FPW) 0x00900090; + + mb (); + value = addr[0]; + + switch (value) { + + case (FPW) INTEL_MANUFACT: + info->flash_id = FLASH_MAN_INTEL; + break; + + default: + info->flash_id = FLASH_UNKNOWN; + info->sector_count = 0; + info->size = 0; + addr[0] = (FPW) 0x00FF00FF; /* restore read mode */ + return (0); /* no or unknown flash */ + } + + mb (); + value = addr[1]; /* device ID */ + switch (value) { + + case (FPW) (INTEL_ID_28F256L18T): + info->flash_id += FLASH_28F256L18T; + info->sector_count = 259; + info->size = 0x02000000; + break; /* => 32 MB */ + + case (FPW) (INTEL_ID_28F640J3A): + info->flash_id += FLASH_28F640J3A; + info->sector_count = nsects; + info->size = nsects * PHYS_FLASH_SECT_SIZE; + break; + + case (FPW) (INTEL_ID_28F128J3A): + info->flash_id += FLASH_28F128J3A; + info->sector_count = nsects; + info->size = nsects * PHYS_FLASH_SECT_SIZE; + break; + + default: + info->flash_id = FLASH_UNKNOWN; + break; + } + + if (info->sector_count > CONFIG_SYS_MAX_FLASH_SECT) { + printf ("** ERROR: sector count %d > max (%d) **\n", + info->sector_count, CONFIG_SYS_MAX_FLASH_SECT); + info->sector_count = CONFIG_SYS_MAX_FLASH_SECT; + } + + addr[0] = (FPW) 0x00FF00FF; /* restore read mode */ + + return (info->size); +} + + +/* unprotects a sector for write and erase + * on some intel parts, this unprotects the entire chip, but it + * wont hurt to call this additional times per sector... + */ +void flash_unprotect_sectors (FPWV * addr) +{ + FPW status; + + *addr = (FPW) 0x00500050; /* clear status register */ + + /* this sends the clear lock bit command */ + *addr = (FPW) 0x00600060; + *addr = (FPW) 0x00D000D0; + + reset_timer_masked(); + while (((status = *addr) & (FPW)0x00800080) != 0x00800080) { + if (get_timer_masked() > CONFIG_SYS_FLASH_ERASE_TOUT) { + printf("Timeout"); + break; + } + } + + *addr = (FPW) 0x00FF00FF; +} + + +/*----------------------------------------------------------------------- + */ +int flash_erase (flash_info_t * info, int s_first, int s_last) +{ + int flag, prot, sect; + ulong type; + int rcode = 0; + + if ((s_first < 0) || (s_first > s_last)) { + if (info->flash_id == FLASH_UNKNOWN) { + printf ("- missing\n"); + } else { + printf ("- no sectors to erase\n"); + } + return 1; + } + + type = (info->flash_id & FLASH_VENDMASK); + if ((type != FLASH_MAN_INTEL)) { + printf ("Can't erase unknown flash type %08lx - aborted\n", + info->flash_id); + return 1; + } + + prot = 0; + for (sect = s_first; sect <= s_last; ++sect) { + if (info->protect[sect]) { + prot++; + } + } + + if (prot) { + printf ("- Warning: %d protected sectors will not be erased!\n", + prot); + } else { + printf ("\n"); + } + + /* Start erase on unprotected sectors */ + for (sect = s_first; sect <= s_last; sect++) { + if (info->protect[sect] == 0) { /* not protected */ + FPWV *addr = (FPWV *) (info->start[sect]); + FPW status; + + printf ("Erasing sector %2d ... ", sect); + + /* Disable interrupts which might cause a timeout here */ + flag = disable_interrupts (); + + /* flash_unprotect_sectors (addr); */ + + /* arm simple, non interrupt dependent timer */ + reset_timer_masked (); + + *addr = (FPW) 0x00500050; /* clear status register */ + *addr = (FPW) 0x00200020; /* erase setup */ + *addr = (FPW) 0x00D000D0; /* erase confirm */ + mb(); + + udelay(1000); /* Let's wait 1 ms */ + + /* re-enable interrupts if necessary */ + if (flag) + enable_interrupts(); + + while (((status = *addr) & (FPW) 0x00800080) != (FPW) 0x00800080) { + if (get_timer_masked () > CONFIG_SYS_FLASH_ERASE_TOUT) { + *addr = (FPW)0x00700070; + status = *addr; + if ((status & (FPW) 0x00400040) == (FPW) 0x00400040) { + /* erase suspended? Resume it */ + reset_timer_masked(); + *addr = (FPW) 0x00D000D0; + } else { +#ifdef DEBUG + printf ("Timeout,0x%08lx\n", status); +#else + printf("Timeout\n"); +#endif + + *addr = (FPW) 0x00500050; + *addr = (FPW) 0x00FF00FF; /* reset to read mode */ + rcode = 1; + break; + } + } + } + + *addr = (FPW) 0x00FF00FF; /* resest to read mode */ + printf (" done\n"); + } + } + + return rcode; +} + +/*----------------------------------------------------------------------- + * Copy memory to flash, returns: + * 0 - OK + * 1 - write timeout + * 2 - Flash not erased + * 4 - Flash not identified + */ +int write_buff (flash_info_t * info, uchar * src, ulong addr, ulong cnt) +{ + ulong cp, wp; + FPW data; + int count, i, l, rc, port_width; + + if (info->flash_id == FLASH_UNKNOWN) { + return 4; + } +/* get lower word aligned address */ +#ifdef FLASH_PORT_WIDTH16 + wp = (addr & ~1); + port_width = 2; +#else + wp = (addr & ~3); + port_width = 4; +#endif + + /* + * handle unaligned start bytes + */ + if ((l = addr - wp) != 0) { + data = 0; + for (i = 0, cp = wp; i < l; ++i, ++cp) { + data = (data << 8) | (*(uchar *) cp); + } + for (; i < port_width && cnt > 0; ++i) { + data = (data << 8) | *src++; + --cnt; + ++cp; + } + for (; cnt == 0 && i < port_width; ++i, ++cp) { + data = (data << 8) | (*(uchar *) cp); + } + + if ((rc = write_data (info, wp, SWAP (data))) != 0) { + return (rc); + } + wp += port_width; + } + + /* + * handle word aligned part + */ + count = 0; + while (cnt >= port_width) { + data = 0; + for (i = 0; i < port_width; ++i) { + data = (data << 8) | *src++; + } + if ((rc = write_data (info, wp, SWAP (data))) != 0) { + return (rc); + } + wp += port_width; + cnt -= port_width; + if (count++ > 0x800) { + spin_wheel (); + count = 0; + } + } + + if (cnt == 0) { + return (0); + } + + /* + * handle unaligned tail bytes + */ + data = 0; + for (i = 0, cp = wp; i < port_width && cnt > 0; ++i, ++cp) { + data = (data << 8) | *src++; + --cnt; + } + for (; i < port_width; ++i, ++cp) { + data = (data << 8) | (*(uchar *) cp); + } + + return (write_data (info, wp, SWAP (data))); +} + +/*----------------------------------------------------------------------- + * Write a word or halfword to Flash, returns: + * 0 - OK + * 1 - write timeout + * 2 - Flash not erased + */ +static int write_data (flash_info_t * info, ulong dest, FPW data) +{ + FPWV *addr = (FPWV *) dest; + ulong status; + int flag; + + /* Check if Flash is (sufficiently) erased */ + if ((*addr & data) != data) { + printf ("not erased at %08lx (%lx)\n", (ulong) addr, *addr); + return (2); + } + + /* Disable interrupts which might cause a timeout here */ + flag = disable_interrupts (); + + /* flash_unprotect_sectors (addr); */ + + *addr = (FPW) 0x00400040; /* write setup */ + *addr = data; + + mb(); + + /* re-enable interrupts if necessary */ + if (flag) + enable_interrupts(); + + /* arm simple, non interrupt dependent timer */ + reset_timer_masked (); + + /* wait while polling the status register */ + while (((status = *addr) & (FPW) 0x00800080) != (FPW) 0x00800080) { + if (get_timer_masked () > CONFIG_SYS_FLASH_WRITE_TOUT) { +#ifdef DEBUG + *addr = (FPW) 0x00700070; + status = *addr; + printf("## status=0x%08lx, addr=0x%p\n", status, addr); +#endif + *addr = (FPW) 0x00500050; /* clear status register cmd */ + *addr = (FPW) 0x00FF00FF; /* restore read mode */ + return (1); + } + } + + *addr = (FPW) 0x00FF00FF; /* restore read mode */ + return (0); +} + +void inline spin_wheel (void) +{ + static int p = 0; + static char w[] = "\\/-"; + + printf ("\010%c", w[p]); + (++p == 3) ? (p = 0) : 0; +} diff --git a/board/armltd/integratorcp/integratorcp.c b/board/armltd/integratorcp/integratorcp.c new file mode 100644 index 0000000..72629ce --- /dev/null +++ b/board/armltd/integratorcp/integratorcp.c @@ -0,0 +1,279 @@ +/* + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Marius Groeger <mgroeger@sysgo.de> + * + * (C) Copyright 2002 + * David Mueller, ELSOFT AG, <d.mueller@elsoft.ch> + * + * (C) Copyright 2003 + * Texas Instruments, <www.ti.com> + * Kshitij Gupta <Kshitij@ti.com> + * + * (C) Copyright 2004 + * ARM Ltd. + * Philippe Robin, <philippe.robin@arm.com> + * + * 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 <div64.h> + +DECLARE_GLOBAL_DATA_PTR; + +void flash__init (void); +void ether__init (void); +void peripheral_power_enable (void); + +#if defined(CONFIG_SHOW_BOOT_PROGRESS) +void show_boot_progress(int progress) +{ + printf("Boot reached stage %d\n", progress); +} +#endif + +#define COMP_MODE_ENABLE ((unsigned int)0x0000EAEF) + +/* + * Miscellaneous platform dependent initialisations + */ + +int board_init (void) +{ + /* arch number of Integrator Board */ + gd->bd->bi_arch_number = MACH_TYPE_CINTEGRATOR; + + /* adress of boot parameters */ + gd->bd->bi_boot_params = 0x00000100; + + gd->flags = 0; + +#ifdef CONFIG_CM_REMAP +extern void cm_remap(void); + cm_remap(); /* remaps writeable memory to 0x00000000 */ +#endif + + icache_enable (); + + flash__init (); + ether__init (); + return 0; +} + + +int misc_init_r (void) +{ + setenv("verify", "n"); + return (0); +} + +/****************************** + Routine: + Description: +******************************/ +void flash__init (void) +{ +} +/************************************************************* + Routine:ether__init + Description: take the Ethernet controller out of reset and wait + for the EEPROM load to complete. +*************************************************************/ +void ether__init (void) +{ +} + +/****************************** + Routine: + Description: +******************************/ +int dram_init (void) +{ + gd->bd->bi_dram[0].start = PHYS_SDRAM_1; + gd->bd->bi_dram[0].size = PHYS_SDRAM_1_SIZE; + +#ifdef CONFIG_CM_SPD_DETECT + { +extern void dram_query(void); + unsigned long cm_reg_sdram; + unsigned long sdram_shift; + + dram_query(); /* Assembler accesses to CM registers */ + /* Queries the SPD values */ + + /* Obtain the SDRAM size from the CM SDRAM register */ + + cm_reg_sdram = *(volatile ulong *)(CM_BASE + OS_SDRAM); + /* Register SDRAM size + * + * 0xXXXXXXbbb000bb 16 MB + * 0xXXXXXXbbb001bb 32 MB + * 0xXXXXXXbbb010bb 64 MB + * 0xXXXXXXbbb011bb 128 MB + * 0xXXXXXXbbb100bb 256 MB + * + */ + sdram_shift = ((cm_reg_sdram & 0x0000001C)/4)%4; + gd->bd->bi_dram[0].size = 0x01000000 << sdram_shift; + + } +#endif /* CM_SPD_DETECT */ + + return 0; +} + +/* The Integrator/CP timer1 is clocked at 1MHz + * can be divided by 16 or 256 + * and can be set up as a 32-bit timer + */ +/* U-Boot expects a 32 bit timer, running at CONFIG_SYS_HZ */ +/* Keep total timer count to avoid losing decrements < div_timer */ +static unsigned long long total_count = 0; +static unsigned long long lastdec; /* Timer reading at last call */ +static unsigned long long div_clock = 1; /* Divisor applied to timer clock */ +static unsigned long long div_timer = 1; /* Divisor to convert timer reading + * change to U-Boot ticks + */ +/* CONFIG_SYS_HZ = CONFIG_SYS_HZ_CLOCK/(div_clock * div_timer) */ +static ulong timestamp; /* U-Boot ticks since startup */ + +#define TIMER_LOAD_VAL ((ulong)0xFFFFFFFF) +#define READ_TIMER (*(volatile ulong *)(CONFIG_SYS_TIMERBASE+4)) + +/* all function return values in U-Boot ticks i.e. (1/CONFIG_SYS_HZ) sec + * - unless otherwise stated + */ + +/* starts up a counter + * - the Integrator/CP timer can be set up to issue an interrupt */ +int interrupt_init (void) +{ + /* Load timer with initial value */ + *(volatile ulong *)(CONFIG_SYS_TIMERBASE + 0) = TIMER_LOAD_VAL; + /* Set timer to be + * enabled 1 + * periodic 1 + * no interrupts 0 + * X 0 + * divider 1 00 == less rounding error + * 32 bit 1 + * wrapping 0 + */ + *(volatile ulong *)(CONFIG_SYS_TIMERBASE + 8) = 0x000000C2; + /* init the timestamp */ + total_count = 0ULL; + reset_timer_masked(); + + div_timer = (unsigned long long)(CONFIG_SYS_HZ_CLOCK / CONFIG_SYS_HZ); + div_timer /= div_clock; + + return (0); +} + +/* + * timer without interrupts + */ +void reset_timer (void) +{ + reset_timer_masked (); +} + +ulong get_timer (ulong base_ticks) +{ + return get_timer_masked () - base_ticks; +} + +void set_timer (ulong ticks) +{ + timestamp = ticks; + total_count = (unsigned long long)ticks * div_timer; +} + +/* delay usec useconds */ +void udelay (unsigned long usec) +{ + ulong tmo, tmp; + + /* Convert to U-Boot ticks */ + tmo = usec * CONFIG_SYS_HZ; + tmo /= (1000000L); + + tmp = get_timer_masked(); /* get current timestamp */ + tmo += tmp; /* form target timestamp */ + + while (get_timer_masked () < tmo) {/* loop till event */ + /*NOP*/; + } +} + +void reset_timer_masked (void) +{ + /* capure current decrementer value */ + lastdec = (unsigned long long)READ_TIMER; + /* start "advancing" time stamp from 0 */ + timestamp = 0L; +} + +/* converts the timer reading to U-Boot ticks */ +/* the timestamp is the number of ticks since reset */ +ulong get_timer_masked (void) +{ + /* get current count */ + unsigned long long now = (unsigned long long)READ_TIMER; + + if(now > lastdec) { + /* Must have wrapped */ + total_count += lastdec + TIMER_LOAD_VAL + 1 - now; + } else { + total_count += lastdec - now; + } + lastdec = now; + + /* Reuse "now" */ + now = total_count; + do_div(now, div_timer); + timestamp = now; + + return timestamp; +} + +/* waits specified delay value and resets timestamp */ +void udelay_masked (unsigned long usec) +{ + udelay(usec); +} + +/* + * This function is derived from PowerPC code (read timebase as long long). + * On ARM it just returns the timer value. + */ +unsigned long long get_ticks(void) +{ + return (unsigned long long)get_timer(0); +} + +/* + * Return the timebase clock frequency + * i.e. how often the timer decrements + */ +ulong get_tbclk (void) +{ + return (ulong)(((unsigned long long)CONFIG_SYS_HZ_CLOCK)/div_clock); +} diff --git a/board/armltd/integratorcp/lowlevel_init.S b/board/armltd/integratorcp/lowlevel_init.S new file mode 100644 index 0000000..18f7d2e --- /dev/null +++ b/board/armltd/integratorcp/lowlevel_init.S @@ -0,0 +1,214 @@ +/* + * Board specific setup info + * + * (C) Copyright 2003, ARM Ltd. + * Philippe Robin, <philippe.robin@arm.com> + * + * 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 <config.h> +#include <version.h> + +/* Reset using CM control register */ +.global reset_cpu +reset_cpu: + mov r0, #CM_BASE + ldr r1,[r0,#OS_CTRL] + orr r1,r1,#CMMASK_RESET + str r1,[r0,#OS_CTRL] + +reset_failed: + b reset_failed + +/* Set up the platform, once the cpu has been initialized */ +.globl lowlevel_init +lowlevel_init: + /* If U-Boot has been run after the ARM boot monitor + * then all the necessary actions have been done + * otherwise we are running from user flash mapped to 0x00000000 + * --- DO NOT REMAP BEFORE THE CODE HAS BEEN RELOCATED -- + * Changes to the (possibly soft) reset defaults of the processor + * itself should be performed in cpu/arm<>/start.S + * This function affects only the core module or board settings + */ + +#ifdef CONFIG_CM_INIT + /* CM has an initialization register + * - bits in it are wired into test-chip pins to force + * reset defaults + * - may need to change its contents for U-Boot + */ + + /* set the desired CM specific value */ + mov r2,#CMMASK_LOWVEC /* Vectors at 0x00000000 for all */ + +#if defined (CONFIG_CM10200E) || defined (CONFIG_CM10220E) + orr r2,r2,#CMMASK_INIT_102 +#else + +#if !defined (CONFIG_CM920T) && !defined (CONFIG_CM920T_ETM) && \ + !defined (CONFIG_CM940T) + /* CMxx6 code */ + +#ifdef CONFIG_CM_MULTIPLE_SSRAM + /* set simple mapping */ + and r2,r2,#CMMASK_MAP_SIMPLE +#endif /* #ifdef CONFIG_CM_MULTIPLE_SSRAM */ + +#ifdef CONFIG_CM_TCRAM + /* disable TCRAM */ + and r2,r2,#CMMASK_TCRAM_DISABLE +#endif /* #ifdef CONFIG_CM_TCRAM */ + +#if defined (CONFIG_CM926EJ_S) || defined (CONFIG_CM1026EJ_S) || \ + defined (CONFIG_CM1136JF_S) + + and r2,r2,#CMMASK_LE + +#endif /* cpu with little endian initialization */ + + orr r2,r2,#CMMASK_CMxx6_COMMON + +#endif /* CMxx6 code */ + +#endif /* ARM102xxE value */ + + /* read CM_INIT */ + mov r0, #CM_BASE + ldr r1, [r0, #OS_INIT] + /* check against desired bit setting */ + and r3,r1,r2 + cmp r3,r2 + beq init_reg_OK + + /* lock for change */ + mov r3, #CMVAL_LOCK1 + and r3, r3, #CMVAL_LOCK2 + str r3, [r0, #OS_LOCK] + /* set desired value */ + orr r1,r1,r2 + /* write & relock CM_INIT */ + str r1, [r0, #OS_INIT] + mov r1, #CMVAL_UNLOCK + str r1, [r0, #OS_LOCK] + + /* soft reset so new values used */ + b reset_cpu + +init_reg_OK: + +#endif /* CONFIG_CM_INIT */ + + mov pc, lr + +#ifdef CONFIG_CM_SPD_DETECT + /* Fast memory is available for the DRAM data + * - ensure it has been transferred, then summarize the data + * into a CM register + */ +.globl dram_query +dram_query: + stmfd r13!,{r4-r6,lr} + /* set up SDRAM info */ + /* - based on example code from the CM User Guide */ + mov r0, #CM_BASE + +readspdbit: + ldr r1, [r0, #OS_SDRAM] /* read the SDRAM register */ + and r1, r1, #0x20 /* mask SPD bit (5) */ + cmp r1, #0x20 /* test if set */ + bne readspdbit + +setupsdram: + add r0, r0, #OS_SPD /* address the copy of the SDP data */ + ldrb r1, [r0, #3] /* number of row address lines */ + ldrb r2, [r0, #4] /* number of column address lines */ + ldrb r3, [r0, #5] /* number of banks */ + ldrb r4, [r0, #31] /* module bank density */ + mul r5, r4, r3 /* size of SDRAM (MB divided by 4) */ + mov r5, r5, ASL#2 /* size in MB */ + mov r0, #CM_BASE /* reload for later code */ + cmp r5, #0x10 /* is it 16MB? */ + bne not16 + mov r6, #0x2 /* store size and CAS latency of 2 */ + b writesize + +not16: + cmp r5, #0x20 /* is it 32MB? */ + bne not32 + mov r6, #0x6 + b writesize + +not32: + cmp r5, #0x40 /* is it 64MB? */ + bne not64 + mov r6, #0xa + b writesize + +not64: + cmp r5, #0x80 /* is it 128MB? */ + bne not128 + mov r6, #0xe + b writesize + +not128: + /* if it is none of these sizes then it is either 256MB, or + * there is no SDRAM fitted so default to 256MB + */ + mov r6, #0x12 + +writesize: + mov r1, r1, ASL#8 /* row addr lines from SDRAM reg */ + orr r2, r1, r2, ASL#12 /* OR in column address lines */ + orr r3, r2, r3, ASL#16 /* OR in number of banks */ + orr r6, r6, r3 /* OR in size and CAS latency */ + str r6, [r0, #OS_SDRAM] /* store SDRAM parameters */ + +#endif /* #ifdef CONFIG_CM_SPD_DETECT */ + + ldmfd r13!,{r4-r6,pc} /* back to caller */ + +#ifdef CONFIG_CM_REMAP + /* CM remap bit is operational + * - use it to map writeable memory at 0x00000000, in place of flash + */ +.globl cm_remap +cm_remap: + stmfd r13!,{r4-r10,lr} + + mov r0, #CM_BASE + ldr r1, [r0, #OS_CTRL] + orr r1, r1, #CMMASK_REMAP /* set remap and led bits */ + str r1, [r0, #OS_CTRL] + + /* Now 0x00000000 is writeable, replace the vectors */ + ldr r0, =_start /* r0 <- start of vectors */ + ldr r2, =_armboot_start /* r2 <- past vectors */ + sub r1,r1,r1 /* destination 0x00000000 */ + +copy_vec: + ldmia r0!, {r3-r10} /* copy from source address [r0] */ + stmia r1!, {r3-r10} /* copy to target address [r1] */ + cmp r0, r2 /* until source end address [r2] */ + ble copy_vec + + ldmfd r13!,{r4-r10,pc} /* back to caller */ + +#endif /* #ifdef CONFIG_CM_REMAP */ diff --git a/board/armltd/integratorcp/split_by_variant.sh b/board/armltd/integratorcp/split_by_variant.sh new file mode 100755 index 0000000..34422fd --- /dev/null +++ b/board/armltd/integratorcp/split_by_variant.sh @@ -0,0 +1,114 @@ +#!/bin/sh +# --------------------------------------------------------- +# Set the platform defines +# --------------------------------------------------------- +echo -n "/* Integrator configuration implied " > tmp.fil +echo " by Makefile target */" >> tmp.fil +echo -n "#define CONFIG_INTEGRATOR" >> tmp.fil +echo " /* Integrator board */" >> tmp.fil +echo -n "#define CONFIG_ARCH_CINTEGRATOR" >> tmp.fil +echo " 1 /* Integrator/CP */" >> tmp.fil + +cpu="arm_intcm" +variant="unknown core module" + +if [ "$1" = "" ] +then + echo "$0:: No parameters - using arm_intcm" +else + case "$1" in + ap966) + cpu="arm_intcm" + variant="unported core module CM966E-S" + ;; + + ap922_config) + cpu="arm_intcm" + variant="unported core module CM922T" + ;; + + integratorcp_config | \ + cp_config) + cpu="arm_intcm" + variant="unspecified core module" + ;; + + cp922_XA10_config) + cpu="arm_intcm" + variant="unported core module CM922T_XA10" + echo -n "#define CONFIG_CM922T_XA10" >> tmp.fil + echo " 1 /* CPU core is ARM922T_XA10 */" >> tmp.fil + ;; + + cp920t_config) + cpu="arm920t" + variant="Core module CM920T" + echo -n "#define CONFIG_CM920T" >> tmp.fil + echo " 1 /* CPU core is ARM920T */" >> tmp.fil + ;; + + cp926ejs_config) + cpu="arm926ejs" + variant="Core module CM926EJ-S" + echo -n "#define CONFIG_CM926EJ_S" >> tmp.fil + echo " 1 /* CPU core is ARM926EJ-S */ " >> tmp.fil + ;; + + + cp946es_config) + cpu="arm946es" + variant="Core module CM946E-S" + echo -n "#define CONFIG_CM946E_S" >> tmp.fil + echo " 1 /* CPU core is ARM946E-S */ " >> tmp.fil + ;; + + cp1136_config) + cpu="arm1136" + variant="Core module CM1136EJF-S" + echo -n "#define CONFIG_CM1136EJF_S" >> tmp.fil + echo " 1 /* CPU core is ARM1136JF-S */ " >> tmp.fil + ;; + + *) + echo "$0:: Unknown core module" + variant="unknown core module" + cpu="arm_intcm" + ;; + + esac + +fi + +if [ "$cpu" = "arm_intcm" ] +then + echo "/* Core module undefined/not ported */" >> tmp.fil + echo "#define CONFIG_ARM_INTCM 1" >> tmp.fil + echo -n "#undef CONFIG_CM_MULTIPLE_SSRAM" >> tmp.fil + echo -n " /* CM may not have " >> tmp.fil + echo "multiple SSRAM mapping */" >> tmp.fil + echo -n "#undef CONFIG_CM_SPD_DETECT " >> tmp.fil + echo -n " /* CM may not support SPD " >> tmp.fil + echo "query */" >> tmp.fil + echo -n "#undef CONFIG_CM_REMAP " >> tmp.fil + echo -n " /* CM may not support " >> tmp.fil + echo "remapping */" >> tmp.fil + echo -n "#undef CONFIG_CM_INIT " >> tmp.fil + echo -n " /* CM may not have " >> tmp.fil + echo "initialization reg */" >> tmp.fil + echo -n "#undef CONFIG_CM_TCRAM " >> tmp.fil + echo " /* CM may not have TCRAM */" >> tmp.fil +fi + +mkdir -p ${obj}include +mkdir -p ${obj}board/armltd/integratorcp +mv tmp.fil ${obj}include/config.h +# --------------------------------------------------------- +# Ensure correct core object loaded first in U-Boot image +# --------------------------------------------------------- +sed -r 's/CPU_FILE/cpu\/'$cpu'\/start.o/; s/#.*//' ${src}board/armltd/integratorcp/u-boot.lds.template > ${obj}board/armltd/integratorcp/u-boot.lds +# --------------------------------------------------------- +# Complete the configuration +# --------------------------------------------------------- +$MKCONFIG -a integratorcp arm $cpu integratorcp armltd; +echo "Variant:: $variant with core $cpu" + diff --git a/board/armltd/integratorcp/u-boot.lds.template b/board/armltd/integratorcp/u-boot.lds.template new file mode 100644 index 0000000..0ec8087 --- /dev/null +++ b/board/armltd/integratorcp/u-boot.lds.template @@ -0,0 +1,53 @@ +/* + * (C) Copyright 2002 + * Gary Jennejohn, DENX Software Engineering, <gj@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 + */ +# Template used during configuration to emsure the core module processor code, +# from CPU_FILE, is placed at the start of the image */ + +OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") +OUTPUT_ARCH(arm) +ENTRY(_start) +SECTIONS +{ + . = 0x00000000; + . = ALIGN(4); + .text : + { + CPU_FILE (.text) + *(.text) + } + .rodata : { *(.rodata) } + . = ALIGN(4); + .data : { *(.data) } + . = ALIGN(4); + .got : { *(.got) } + + . = .; + __u_boot_cmd_start = .; + .u_boot_cmd : { *(.u_boot_cmd) } + __u_boot_cmd_end = .; + + . = ALIGN(4); + __bss_start = .; + .bss : { *(.bss) } + _end = .; +} diff --git a/board/armltd/versatile/Makefile b/board/armltd/versatile/Makefile new file mode 100644 index 0000000..044a429 --- /dev/null +++ b/board/armltd/versatile/Makefile @@ -0,0 +1,51 @@ +# +# (C) Copyright 2000-2006 +# 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 $(TOPDIR)/config.mk + +LIB = $(obj)lib$(BOARD).a + +COBJS := versatile.o flash.o +SOBJS := lowlevel_init.o + +SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) +OBJS := $(addprefix $(obj),$(COBJS)) +SOBJS := $(addprefix $(obj),$(SOBJS)) + +$(LIB): $(obj).depend $(OBJS) $(SOBJS) + $(AR) $(ARFLAGS) $@ $(OBJS) $(SOBJS) + +clean: + rm -f $(SOBJS) $(OBJS) + +distclean: clean + rm -f $(LIB) core *.bak $(obj).depend + +######################################################################### + +# defines $(obj).depend target +include $(SRCTREE)/rules.mk + +sinclude $(obj).depend + +######################################################################### diff --git a/board/armltd/versatile/config.mk b/board/armltd/versatile/config.mk new file mode 100644 index 0000000..25b79b3 --- /dev/null +++ b/board/armltd/versatile/config.mk @@ -0,0 +1,5 @@ +# +# image should be loaded at 0x01000000 +# + +TEXT_BASE = 0x01000000 diff --git a/board/armltd/versatile/flash.c b/board/armltd/versatile/flash.c new file mode 100644 index 0000000..3bdc895 --- /dev/null +++ b/board/armltd/versatile/flash.c @@ -0,0 +1,514 @@ +/* + * (C) Copyright 2001 + * Kyle Harris, Nexus Technologies, Inc. kharris@nexus-tech.net + * + * (C) Copyright 2001-2004 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * (C) Copyright 2003 + * Texas Instruments, <www.ti.com> + * Kshitij Gupta <Kshitij@ti.com> + * + * 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 <linux/byteorder/swab.h> + +#define PHYS_FLASH_SECT_SIZE 0x00020000 /* 256 KB sectors (x2) */ +flash_info_t flash_info[CONFIG_SYS_MAX_FLASH_BANKS]; /* info for FLASH chips */ + +/* Board support for 1 or 2 flash devices */ +#define FLASH_PORT_WIDTH32 +#undef FLASH_PORT_WIDTH16 + +#ifdef FLASH_PORT_WIDTH16 +#define FLASH_PORT_WIDTH ushort +#define FLASH_PORT_WIDTHV vu_short +#define SWAP(x) __swab16(x) +#else +#define FLASH_PORT_WIDTH ulong +#define FLASH_PORT_WIDTHV vu_long +#define SWAP(x) __swab32(x) +#endif + +#define FPW FLASH_PORT_WIDTH +#define FPWV FLASH_PORT_WIDTHV + +#define mb() __asm__ __volatile__ ("" : : : "memory") + + +/* Flash Organization Structure */ +typedef struct OrgDef { + unsigned int sector_number; + unsigned int sector_size; +} OrgDef; + + +/* Flash Organizations */ +OrgDef OrgIntel_28F256K3[] = { + {256, 128 * 1024}, /* 256 * 128kBytes sectors */ +}; + + +/*----------------------------------------------------------------------- + * Functions + */ +unsigned long flash_init (void); +static ulong flash_get_size (FPW * addr, flash_info_t * info); +static int write_data (flash_info_t * info, ulong dest, FPW data); +static void flash_get_offsets (ulong base, flash_info_t * info); +void inline spin_wheel (void); +void flash_print_info (flash_info_t * info); +void flash_unprotect_sectors (FPWV * addr); +int flash_erase (flash_info_t * info, int s_first, int s_last); +int write_buff (flash_info_t * info, uchar * src, ulong addr, ulong cnt); + +/*----------------------------------------------------------------------- + */ + +static void flash_vpp(int on) +{ + unsigned int tmp; + + tmp = *(unsigned int *)(VERSATILE_FLASHCTRL); + + if (on) + tmp |= VERSATILE_FLASHPROG_FLVPPEN; + else + tmp &= ~VERSATILE_FLASHPROG_FLVPPEN; + + *(unsigned int *)(VERSATILE_FLASHCTRL) = tmp; +} + +unsigned long flash_init (void) +{ + int i; + ulong size = 0; + for (i = 0; i < CONFIG_SYS_MAX_FLASH_BANKS; i++) { + switch (i) { + case 0: + flash_vpp(1); + flash_get_size ((FPW *) PHYS_FLASH_1, &flash_info[i]); + flash_get_offsets (PHYS_FLASH_1, &flash_info[i]); + flash_vpp(0); + break; + default: + panic ("configured too many flash banks!\n"); + break; + } + size += flash_info[i].size; + } + + /* Protect monitor and environment sectors + */ + flash_protect (FLAG_PROTECT_SET, + CONFIG_SYS_FLASH_BASE, + CONFIG_SYS_FLASH_BASE + monitor_flash_len - 1, &flash_info[0]); + + return size; +} + +/*----------------------------------------------------------------------- + */ +static void flash_get_offsets (ulong base, flash_info_t * info) +{ + int i; + OrgDef *pOrgDef; + + pOrgDef = OrgIntel_28F256K3; + if (info->flash_id == FLASH_UNKNOWN) { + return; + } + + if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_INTEL) { + for (i = 0; i < info->sector_count; i++) { + if (i > 255) { + info->start[i] = base + (i * 0x8000); + info->protect[i] = 0; + } else { + info->start[i] = base + + (i * PHYS_FLASH_SECT_SIZE); + info->protect[i] = 0; + } + } + } +} + +/*----------------------------------------------------------------------- + */ +void flash_print_info (flash_info_t * info) +{ + int i; + + if (info->flash_id == FLASH_UNKNOWN) { + printf ("missing or unknown FLASH type\n"); + return; + } + + switch (info->flash_id & FLASH_VENDMASK) { + case FLASH_MAN_INTEL: + printf ("INTEL "); + break; + default: + printf ("Unknown Vendor "); + break; + } + + switch (info->flash_id & FLASH_TYPEMASK) { + case FLASH_28F256L18T: + printf ("FLASH 28F256L18T\n"); + break; + case FLASH_28F256K3: + printf ("FLASH 28F256K3\n"); + break; + default: + printf ("Unknown Chip Type\n"); + break; + } + + printf (" Size: %ld MB in %d Sectors\n", + info->size >> 20, info->sector_count); + + printf (" Sector Start Addresses:"); + for (i = 0; i < info->sector_count; ++i) { + if ((i % 5) == 0) + printf ("\n "); + printf (" %08lX%s", + info->start[i], info->protect[i] ? " (RO)" : " "); + } + printf ("\n"); + return; +} + +/* + * The following code cannot be run from FLASH! + */ +static ulong flash_get_size (FPW * addr, flash_info_t * info) +{ + volatile FPW value; + + /* Write auto select command: read Manufacturer ID */ + addr[0x5555] = (FPW) 0x00AA00AA; + addr[0x2AAA] = (FPW) 0x00550055; + addr[0x5555] = (FPW) 0x00900090; + + mb (); + value = addr[0]; + switch (value) { + + case (FPW) INTEL_MANUFACT: + info->flash_id = FLASH_MAN_INTEL; + break; + + default: + info->flash_id = FLASH_UNKNOWN; + info->sector_count = 0; + info->size = 0; + addr[0] = (FPW) 0x00FF00FF; /* restore read mode */ + return (0); /* no or unknown flash */ + } + + mb (); + value = addr[1]; /* device ID */ + switch (value) { + + case (FPW) (INTEL_ID_28F256L18T): + info->flash_id += FLASH_28F256L18T; + info->sector_count = 259; + info->size = 0x02000000; + break; /* => 32 MB */ + + case (FPW)(INTEL_ID_28F256K3): + info->flash_id += FLASH_28F256K3; + info->sector_count = 256; + info->size = 0x02000000; + break; + + default: + info->flash_id = FLASH_UNKNOWN; + break; + } + + if (info->sector_count > CONFIG_SYS_MAX_FLASH_SECT) { + printf ("** ERROR: sector count %d > max (%d) **\n", + info->sector_count, CONFIG_SYS_MAX_FLASH_SECT); + info->sector_count = CONFIG_SYS_MAX_FLASH_SECT; + } + + addr[0] = (FPW) 0x00FF00FF; /* restore read mode */ + + return (info->size); +} + + +/* unprotects a sector for write and erase + * on some intel parts, this unprotects the entire chip, but it + * wont hurt to call this additional times per sector... + */ +void flash_unprotect_sectors (FPWV * addr) +{ +#define PD_FINTEL_WSMS_READY_MASK 0x0080 + + *addr = (FPW) 0x00500050; /* clear status register */ + + /* this sends the clear lock bit command */ + *addr = (FPW) 0x00600060; + *addr = (FPW) 0x00D000D0; +} + + +/*----------------------------------------------------------------------- + */ + +int flash_erase (flash_info_t * info, int s_first, int s_last) +{ + int flag, prot, sect; + ulong type, start, last; + int rcode = 0; + + if ((s_first < 0) || (s_first > s_last)) { + if (info->flash_id == FLASH_UNKNOWN) { + printf ("- missing\n"); + } else { + printf ("- no sectors to erase\n"); + } + return 1; + } + + type = (info->flash_id & FLASH_VENDMASK); + if ((type != FLASH_MAN_INTEL)) { + printf ("Can't erase unknown flash type %08lx - aborted\n", + info->flash_id); + return 1; + } + + prot = 0; + for (sect = s_first; sect <= s_last; ++sect) { + if (info->protect[sect]) { + prot++; + } + } + + if (prot) { + printf ("- Warning: %d protected sectors will not be erased!\n", + prot); + } else { + printf ("\n"); + } + + flash_vpp(1); + + start = get_timer (0); + last = start; + + /* Disable interrupts which might cause a timeout here */ + flag = disable_interrupts (); + + /* Start erase on unprotected sectors */ + for (sect = s_first; sect <= s_last; sect++) { + if (info->protect[sect] == 0) { /* not protected */ + FPWV *addr = (FPWV *) (info->start[sect]); + FPW status; + + printf ("Erasing sector %2d ... ", sect); + + flash_unprotect_sectors (addr); + + /* arm simple, non interrupt dependent timer */ + reset_timer_masked (); + + *addr = (FPW) 0x00500050;/* clear status register */ + *addr = (FPW) 0x00200020;/* erase setup */ + *addr = (FPW) 0x00D000D0;/* erase confirm */ + + while (((status = + *addr) & (FPW) 0x00800080) != + (FPW) 0x00800080) { + if (get_timer_masked () > + CONFIG_SYS_FLASH_ERASE_TOUT) { + printf ("Timeout\n"); + /* suspend erase */ + *addr = (FPW) 0x00B000B0; + /* reset to read mode */ + *addr = (FPW) 0x00FF00FF; + rcode = 1; + break; + } + } + + /* clear status register cmd. */ + *addr = (FPW) 0x00500050; + *addr = (FPW) 0x00FF00FF;/* resest to read mode */ + printf (" done\n"); + } + } + + flash_vpp(0); + + return rcode; +} + +/*----------------------------------------------------------------------- + * Copy memory to flash, returns: + * 0 - OK + * 1 - write timeout + * 2 - Flash not erased + * 4 - Flash not identified + */ + +int write_buff (flash_info_t * info, uchar * src, ulong addr, ulong cnt) +{ + ulong cp, wp; + FPW data; + int count, i, l, rc, port_width; + + if (info->flash_id == FLASH_UNKNOWN) { + return 4; + } +/* get lower word aligned address */ +#ifdef FLASH_PORT_WIDTH16 + wp = (addr & ~1); + port_width = 2; +#else + wp = (addr & ~3); + port_width = 4; +#endif + + flash_vpp(1); + + /* + * handle unaligned start bytes + */ + if ((l = addr - wp) != 0) { + data = 0; + for (i = 0, cp = wp; i < l; ++i, ++cp) { + data = (data << 8) | (*(uchar *) cp); + } + for (; i < port_width && cnt > 0; ++i) { + data = (data << 8) | *src++; + --cnt; + ++cp; + } + for (; cnt == 0 && i < port_width; ++i, ++cp) { + data = (data << 8) | (*(uchar *) cp); + } + + if ((rc = write_data (info, wp, SWAP (data))) != 0) { + flash_vpp(0); + return (rc); + } + wp += port_width; + } + + /* + * handle word aligned part + */ + count = 0; + while (cnt >= port_width) { + data = 0; + for (i = 0; i < port_width; ++i) { + data = (data << 8) | *src++; + } + if ((rc = write_data (info, wp, SWAP (data))) != 0) { + flash_vpp(0); + return (rc); + } + wp += port_width; + cnt -= port_width; + if (count++ > 0x800) { + spin_wheel (); + count = 0; + } + } + + if (cnt == 0) { + flash_vpp(0); + return (0); + } + + /* + * handle unaligned tail bytes + */ + data = 0; + for (i = 0, cp = wp; i < port_width && cnt > 0; ++i, ++cp) { + data = (data << 8) | *src++; + --cnt; + } + for (; i < port_width; ++i, ++cp) { + data = (data << 8) | (*(uchar *) cp); + } + + rc = write_data (info, wp, SWAP (data)); + + flash_vpp(0); + + return rc; +} + +/*----------------------------------------------------------------------- + * Write a word or halfword to Flash, returns: + * 0 - OK + * 1 - write timeout + * 2 - Flash not erased + */ +static int write_data (flash_info_t * info, ulong dest, FPW data) +{ + FPWV *addr = (FPWV *) dest; + ulong status; + int flag; + + /* Check if Flash is (sufficiently) erased */ + if ((*addr & data) != data) { + printf ("not erased at %08lx (%lx)\n", (ulong) addr, (ulong) *addr); + return (2); + } + + flash_vpp(1); + + flash_unprotect_sectors (addr); + /* Disable interrupts which might cause a timeout here */ + flag = disable_interrupts (); + *addr = (FPW) 0x00400040; /* write setup */ + *addr = data; + + /* arm simple, non interrupt dependent timer */ + reset_timer_masked (); + + /* wait while polling the status register */ + while (((status = *addr) & (FPW) 0x00800080) != (FPW) 0x00800080) { + if (get_timer_masked () > CONFIG_SYS_FLASH_WRITE_TOUT) { + *addr = (FPW) 0x00FF00FF; /* restore read mode */ + flash_vpp(0); + return (1); + } + } + *addr = (FPW) 0x00FF00FF; /* restore read mode */ + flash_vpp(0); + return (0); +} + +void inline spin_wheel (void) +{ + static int p = 0; + static char w[] = "\\/-"; + + printf ("\010%c", w[p]); + (++p == 3) ? (p = 0) : 0; +} diff --git a/board/armltd/versatile/lowlevel_init.S b/board/armltd/versatile/lowlevel_init.S new file mode 100644 index 0000000..bdfce2d --- /dev/null +++ b/board/armltd/versatile/lowlevel_init.S @@ -0,0 +1,34 @@ +/* + * Board specific setup info + * + * (C) Copyright 2003, ARM Ltd. + * Philippe Robin, <philippe.robin@arm.com> + * + * 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 <config.h> +#include <version.h> + +/* Set up the platform, once the cpu has been initialized */ +.globl lowlevel_init +lowlevel_init: + + /* All done by Versatile's boot monitor! */ + mov pc, lr diff --git a/board/armltd/versatile/split_by_variant.sh b/board/armltd/versatile/split_by_variant.sh new file mode 100755 index 0000000..475e5a3 --- /dev/null +++ b/board/armltd/versatile/split_by_variant.sh @@ -0,0 +1,42 @@ +#!/bin/sh +# --------------------------------------------------------- +# Set the core module defines according to Core Module +# --------------------------------------------------------- +# --------------------------------------------------------- +# Set up the Versatile type define +# --------------------------------------------------------- + +mkdir -p ${obj}include +variant=PB926EJ-S +if [ "$1" = "" ] +then + echo "$0:: No parameters - using versatilepb_config" + echo "#define CONFIG_ARCH_VERSATILE_PB" > ${obj}include/config.h + variant=PB926EJ-S +else + case "$1" in + versatilepb_config | \ + versatile_config) + echo "#define CONFIG_ARCH_VERSATILE_PB" > ${obj}include/config.h + ;; + + versatileab_config) + echo "#define CONFIG_ARCH_VERSATILE_AB" > ${obj}include/config.h + variant=AB926EJ-S + ;; + + + *) + echo "$0:: Unrecognised config - using versatilepb_config" + echo "#define CONFIG_ARCH_VERSATILE_PB" > ${obj}include/config.h + variant=PB926EJ-S + ;; + + esac + +fi +# --------------------------------------------------------- +# Complete the configuration +# --------------------------------------------------------- +$MKCONFIG -a versatile arm arm926ejs versatile armltd versatile +echo "Variant:: $variant" diff --git a/board/armltd/versatile/u-boot.lds b/board/armltd/versatile/u-boot.lds new file mode 100644 index 0000000..6e6e29b --- /dev/null +++ b/board/armltd/versatile/u-boot.lds @@ -0,0 +1,51 @@ +/* + * (C) Copyright 2002 + * Gary Jennejohn, DENX Software Engineering, <gj@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 + */ + +OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") +OUTPUT_ARCH(arm) +ENTRY(_start) +SECTIONS +{ + . = 0x00000000; + . = ALIGN(4); + .text : + { + cpu/arm926ejs/start.o (.text) + *(.text) + } + .rodata : { *(.rodata) } + . = ALIGN(4); + .data : { *(.data) } + . = ALIGN(4); + .got : { *(.got) } + + . = .; + __u_boot_cmd_start = .; + .u_boot_cmd : { *(.u_boot_cmd) } + __u_boot_cmd_end = .; + + . = ALIGN(4); + __bss_start = .; + .bss (NOLOAD) : { *(.bss) . = ALIGN(4); } + _end = .; +} diff --git a/board/armltd/versatile/versatile.c b/board/armltd/versatile/versatile.c new file mode 100644 index 0000000..0f35caa --- /dev/null +++ b/board/armltd/versatile/versatile.c @@ -0,0 +1,98 @@ +/* + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Marius Groeger <mgroeger@sysgo.de> + * + * (C) Copyright 2002 + * David Mueller, ELSOFT AG, <d.mueller@elsoft.ch> + * + * (C) Copyright 2003 + * Texas Instruments, <www.ti.com> + * Kshitij Gupta <Kshitij@ti.com> + * + * (C) Copyright 2004 + * ARM Ltd. + * Philippe Robin, <philippe.robin@arm.com> + * + * 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> + +DECLARE_GLOBAL_DATA_PTR; + +#if defined(CONFIG_SHOW_BOOT_PROGRESS) +void show_boot_progress(int progress) +{ + printf("Boot reached stage %d\n", progress); +} +#endif + +#define COMP_MODE_ENABLE ((unsigned int)0x0000EAEF) + +static inline void delay (unsigned long loops) +{ + __asm__ volatile ("1:\n" + "subs %0, %1, #1\n" + "bne 1b":"=r" (loops):"0" (loops)); +} + +/* + * Miscellaneous platform dependent initialisations + */ + +int board_init (void) +{ + /* + * set clock frequency: + * VERSATILE_REFCLK is 32KHz + * VERSATILE_TIMCLK is 1MHz + */ + *(volatile unsigned int *)(VERSATILE_SCTL_BASE) |= + ((VERSATILE_TIMCLK << VERSATILE_TIMER1_EnSel) | (VERSATILE_TIMCLK << VERSATILE_TIMER2_EnSel) | + (VERSATILE_TIMCLK << VERSATILE_TIMER3_EnSel) | (VERSATILE_TIMCLK << VERSATILE_TIMER4_EnSel)); + + /* arch number of Versatile Board */ + gd->bd->bi_arch_number = MACH_TYPE_VERSATILE_PB; + + /* adress of boot parameters */ + gd->bd->bi_boot_params = 0x00000100; + + gd->flags = 0; + + icache_enable (); + + return 0; +} + + +int misc_init_r (void) +{ + setenv("verify", "n"); + return (0); +} + +/****************************** + Routine: + Description: +******************************/ +int dram_init (void) +{ + return 0; +} |