Commit 8ed96046 authored by wdenk's avatar wdenk
Browse files

* Patches by Richard Woodruff, 01 Oct 2004:

  add support for the TI OMAP2420 processor and its H4 reference
  board

* Patch by Christian Pellegrin, 24 Sep 2004:
  Added support for NE2000 compatible (DP8390, DP83902) NICs.
parent ff36fd85
......@@ -2,6 +2,13 @@
Changes for U-Boot 1.1.3:
======================================================================
* Patches by Richard Woodruff, 01 Oct 2004:
add support for the TI OMAP2420 processor and its H4 reference
board
* Patch by Christian Pellegrin, 24 Sep 2004:
Added support for NE2000 compatible (DP8390, DP83902) NICs.
* Patch by Leif Lindholm, 23 Sep 2004:
add support for the AMD db1550 board
......
......@@ -382,6 +382,10 @@ Rishi Bhattacharya <rishi@ti.com>
omap5912osk ARM926EJS
Richard Woodruff <r-woodruff2@ti.com>
omap2420h4 ARM1136EJS
David Mller <d.mueller@elsoft.ch>
smdk2410 ARM920T
......
......@@ -157,6 +157,11 @@ LIST_ARM9=" \
versatile \
"
#########################################################################
## ARM11 Systems
#########################################################################
LIST_ARM11="omap2420h4"
#########################################################################
## Xscale Systems
#########################################################################
......@@ -170,7 +175,11 @@ LIST_pxa=" \
LIST_ixp="ixdp425"
LIST_arm="${LIST_SA} ${LIST_ARM7} ${LIST_ARM9} ${LIST_pxa} ${LIST_ixp}"
LIST_arm=" \
${LIST_SA} \
${LIST_ARM7} ${LIST_ARM9} ${LIST_ARM11} \
${LIST_pxa} ${LIST_ixp} \
"
#########################################################################
## MIPS Systems
......@@ -238,7 +247,7 @@ for arg in $@
do
case "$arg" in
ppc|5xx|5xxx|8xx|8220|824x|8260|85xx|4xx|7xx|74xx| \
arm|SA|ARM7|ARM9|pxa|ixp| \
arm|SA|ARM7|ARM9|ARM11|pxa|ixp| \
microblaze| \
mips| \
nios|nios2| \
......
......@@ -1403,6 +1403,12 @@ xm250_config : unconfig
xsengine_config : unconfig
@./mkconfig $(@:_config=) arm pxa xsengine
#########################################################################
## ARM1136 Systems
#########################################################################
omap2420h4_config : unconfig
@./mkconfig $(@:_config=) arm arm1136 omap2420h4
#========================================================================
# i386
#========================================================================
......
......@@ -130,6 +130,7 @@ Directory Hierarchy:
- s3c24x0 Files specific to Samsung S3C24X0 CPUs
- arm925t Files specific to ARM 925 CPUs
- arm926ejs Files specific to ARM 926 CPUs
- arm1136 Files specific to ARM 1136 CPUs
- at91rm9200 Files specific to Atmel AT91RM9200 CPUs
- i386 Files specific to i386 CPUs
- ixp Files specific to Intel XScale IXP CPUs
......@@ -301,13 +302,13 @@ The following options need to be configured:
ARM based boards:
-----------------
CONFIG_AT91RM9200DK, CONFIG_CERF250, CONFIG_DNP1110,
CONFIG_EP7312, CONFIG_H2_OMAP1610, CONFIG_HHP_CRADLE,
CONFIG_IMPA7, CONFIG_INNOVATOROMAP1510, CONFIG_INNOVATOROMAP1610,
CONFIG_LART, CONFIG_LPD7A400 CONFIG_LUBBOCK,
CONFIG_OSK_OMAP5912, CONFIG_SHANNON, CONFIG_P2_OMAP730,
CONFIG_SMDK2400, CONFIG_SMDK2410, CONFIG_TRAB,
CONFIG_VCMA9
CONFIG_AT91RM9200DK, CONFIG_CERF250, CONFIG_DNP1110,
CONFIG_EP7312, CONFIG_H2_OMAP1610, CONFIG_HHP_CRADLE,
CONFIG_IMPA7, CONFIG_INNOVATOROMAP1510, CONFIG_INNOVATOROMAP1610,
CONFIG_LART, CONFIG_LPD7A400 CONFIG_LUBBOCK,
CONFIG_OSK_OMAP5912, CONFIG_OMAP2420H4, CONFIG_SHANNON,
CONFIG_P2_OMAP730, CONFIG_SMDK2400, CONFIG_SMDK2410,
CONFIG_TRAB, CONFIG_VCMA9
MicroBlaze based boards:
------------------------
......@@ -2177,7 +2178,7 @@ configurations; the following names are supported:
FADS850SAR_config omap1610h2_config TQM850L_config
FADS860T_config omap1610inn_config TQM855L_config
FPS850L_config omap5912osk_config TQM860L_config
WALNUT405_config
omap2420h4_config WALNUT405_config
Yukon8220_config
ZPC1900_config
......
#
# (C) Copyright 2000, 2001, 2002
# 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 = lib$(BOARD).a
OBJS := omap2420h4.o flash.o mem.o sys_info.o
SOBJS := platform.o
$(LIB): $(OBJS) $(SOBJS)
$(AR) crv $@ $^
clean:
rm -f $(SOBJS) $(OBJS)
distclean: clean
rm -f $(LIB) core *.bak .depend
#########################################################################
.depend: Makefile $(SOBJS:.o=.S) $(OBJS:.o=.c)
$(CC) -M $(CPPFLAGS) $(SOBJS:.o=.S) $(OBJS:.o=.c) > $@
-include .depend
#########################################################################
#
# (C) Copyright 2004
# Texas Instruments, <www.ti.com>
#
# TI H4 board with OMAP2420 (ARM1136) cpu
# see http://www.ti.com/ for more information on Texas Instruments
#
# H4 has 1 bank of 32MB or 64MB mDDR-SDRAM on CS0
# H4 has 1 bank of 32MB or 00MB mDDR-SDRAM on CS1
# Physical Address:
# 8000'0000 (bank0)
# A000/0000 (bank1) ES2 will be configurable
# Linux-Kernel is expected to be at 8000'8000, entry 8000'8000
# (mem base + reserved)
# For use with external or internal boots.
# CONFIG_PARTIAL_SRAM must be defined to use this.
TEXT_BASE = 0x80e80000
# Used with full SRAM boot.
# This is either with a GP system or a signed boot image.
# easiest, and safest way to go if you can.
# Comment out //CONFIG_PARTIAL_SRAM for this one.
#
#TEXT_BASE = 0x40280000
/*
* (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 <asm/arch/sizes.h>
#include <linux/byteorder/swab.h>
#define PHYS_FLASH_SECT_SIZE SZ_128K
flash_info_t flash_info[CFG_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, SZ_32K}, /* 4 * 32kBytes sectors */
{255, SZ_128K}, /* 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);
void flash_unlock(flash_info_t * info, int bank);
int flash_probe(void);
/*-----------------------------------------------------------------------
*/
/* see if flash is ok */
int flash_probe(void)
{
return(flash_get_size ((FPW *) PHYS_FLASH_1, &flash_info[0]));
}
unsigned long flash_init (void)
{
int i;
ulong size = 0;
for (i = 0; i < CFG_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]);
/* to reset the lock bit */
flash_unlock(&flash_info[i],i);
break;
case 1:
flash_get_size ((FPW *) PHYS_FLASH_2, &flash_info[i]);
flash_get_offsets (PHYS_FLASH_2, &flash_info[i]);
/* to reset the lock bit */
flash_unlock(&flash_info[i],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,
CFG_FLASH_BASE,
CFG_FLASH_BASE + monitor_flash_len - 1, &flash_info[0]);
flash_protect (FLAG_PROTECT_SET,
CFG_ENV_ADDR,
CFG_ENV_ADDR + CFG_ENV_SIZE - 1, &flash_info[0]);
return size;
}
/*-----------------------------------------------------------------------
*/
void flash_unlock(flash_info_t * info, int bank)
{
int j;
if (!bank)
j=2; /* leave 0,1 locked for boot bank */
else
j=0; /* get the whole bank for #2 */
for (;j<CFG_MAX_FLASH_SECT;j++) {
FPWV *addr = (FPWV *) (info->start[j]);
if (addr == NULL) {
printf("Warning Flash probe failed\n");
break;
}
flash_unprotect_sectors (addr);
*addr = (FPW) 0x00500050;/* clear status register */
*addr = (FPW) 0x00FF00FF;/* resest to read mode */
}
}
/*-----------------------------------------------------------------------
*/
static void flash_get_offsets (ulong base, flash_info_t * info)
{
int i;
volatile int r; /* gcc 3.4.0-1 strangeness, need to follow up.*/
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 > 254) { /* 255,256,257,258 */
r=i;
info->start[i] = base + (((r-(int)255) * SZ_32K) + (255*PHYS_FLASH_SECT_SIZE));
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;
/* mb(); this one makes ARM11 err go away, but I want it :) as a guide to problems */
/* Write auto select command: read Manufacturer ID */
addr[0x5555] = (FPW) 0x00AA00AA;
addr[0x2AAA] = (FPW) 0x00550055;
addr[0x5555] = (FPW) 0x00900090;
mb ();
value = addr[0] & 0xFF; /* just looking for 89 (8989 is hw pat)*/
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): /* 880D */
info->flash_id += FLASH_28F256L18T;
info->sector_count = 259; /*0-258*/
info->size = SZ_32M;
break; /* => 32 MB */
default:
info->flash_id = FLASH_UNKNOWN;
break;
}
if (info->sector_count > CFG_MAX_FLASH_SECT) {
printf ("** ERROR: sector count %d > max (%d) **\n",
info->sector_count, CFG_MAX_FLASH_SECT);
info->sector_count = CFG_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 prot, sect;
ulong type, start, last;
int rcode = 0;
#ifdef CONFIG_USE_IRQ
int iflag;
#endif
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;
#ifdef CONFIG_USE_IRQ
/* Disable interrupts which might cause a timeout here */
iflag = disable_interrupts ();
#endif
/* 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 () >
CFG_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");
}
}
#ifdef CONFIG_USE_IRQ
if (iflag)
enable_interrupts();
#endif
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;
#ifdef CONFIG_USE_IRQ
int iflag;
#endif
/* Check if Flash is (sufficiently) erased */
if ((*addr & data) != data) {
printf ("not erased at %08lx (%x)\n", (ulong) addr, *addr);
return(2);
}
/* Disable interrupts which might cause a timeout here */
#ifdef CONFIG_USE_IRQ
iflag = disable_interrupts ();
#endif
*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 () > CFG_FLASH_WRITE_TOUT) {
*addr = (FPW) 0x00FF00FF; /* restore read mode */
return(1);
}
}
*addr = (FPW) 0x00FF00FF; /* restore read mode */
#ifdef CONFIG_USE_IRQ
if (iflag)
enable_interrupts();
#endif
return(0);
}
void inline spin_wheel (void)
{
static int p = 0;
static char w[] = "\\/-";
printf ("\010%c", w[p]);
(++p == 3) ? (p = 0) : 0;
}
/*
* (C) Copyright 2004
* Texas Instruments, <www.ti.com>
* Richard Woodruff <r-woodruff2@ti.com>
*
* 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 <asm/arch/omap2420.h>
#include <asm/io.h>
#include <asm/arch/bits.h>
#include <asm/arch/mux.h>
#include <asm/arch/mem.h>
#include <asm/arch/clocks.h>
#include <asm/arch/sys_proto.h>
#include <asm/arch/sys_info.h>
/************************************************************
* sdelay() - simple spin loop. Will be constant time as
* its generally used in 12MHz bypass conditions only. This
* is necessary until timers are accessible.
*
* not inline to increase chances its in cache when called
*************************************************************/
void sdelay (unsigned long loops)
{
__asm__ volatile ("1:\n"
"subs %0, %1, #1\n"
"bne 1b":"=r" (loops):"0" (loops));
}
/*********************************************************************************
* prcm_init() - inits clocks for PRCM as defined in clocks.h (config II default).
* -- called from SRAM, or Flash (using temp SRAM stack).
*********************************************************************************/
void prcm_init(void)
{
u32 rev,div;
#ifdef CONFIG_PARTIAL_SRAM
void (*f_lock_pll) (u32, u32, u32, u32);
extern void *_end_vect, *_start;
f_lock_pll = (void *)((u32)&_end_vect - (u32)&_start + SRAM_VECT_CODE);
#endif
__raw_writel(0, CM_FCLKEN1_CORE); /* stop all clocks to reduce ringing */
__raw_writel(0, CM_FCLKEN2_CORE); /* may not be necessary */
__raw_writel(0, CM_ICLKEN1_CORE);
__raw_writel(0, CM_ICLKEN2_CORE);
__raw_writel(DPLL_OUT, CM_CLKSEL2_PLL); /* set DPLL out */
__raw_writel(MPU_DIV, CM_CLKSEL_MPU); /* set MPU divider */
__raw_writel(DSP_DIV, CM_CLKSEL_DSP); /* set dsp and iva dividers */
__raw_writel(GFX_DIV, CM_CLKSEL_GFX); /* set gfx dividers */
rev = get_cpu_rev();
if (rev == CPU_2420_ES1 || rev == CPU_2422_ES1)
div = BUS_DIV_ES1;
else
div = BUS_DIV;
__raw_writel(div, CM_CLKSEL1_CORE);/* set L3/L4/USB/Display/Vlnc/SSi dividers */
sdelay(1000);
#ifndef CONFIG_PARTIAL_SRAM
/* If running fully from SRAM this is OK. The Flash bus drops out for just a little.
* but then comes back. If running from Flash this sequence kills you, thus you need
* to run it using CONFIG_PARTIAL_SRAM.
*/
__raw_writel(MODE_BYPASS_FAST, CM_CLKEN_PLL); /* go to bypass, fast relock */
wait_on_value(BIT0|BIT1, BIT1, CM_IDLEST_CKGEN, LDELAY); /* wait till in bypass */
/* set clock selection and dpll dividers. */
__raw_writel(DPLL_VAL, CM_CLKSEL1_PLL); /* set pll for target rate */
__raw_writel(COMMIT_DIVIDERS, PRCM_CLKCFG_CTRL); /* commit dividers */
sdelay(10000);
__raw_writel(DPLL_LOCK, CM_CLKEN_PLL); /* enable dpll */
sdelay(10000);
wait_on_value(BIT0|BIT1, BIT2, CM_IDLEST_CKGEN, LDELAY); /*wait for dpll lock */
#else
/* if running from flash, need to jump to small relocated code area in SRAM.
* This is the only safe spot to do configurations from.
*/
(*f_lock_pll)(PRCM_CLKCFG_CTRL, CM_CLKEN_PLL, DPLL_LOCK, CM_IDLEST_CKGEN);
#endif
__raw_writel(DPLL_LOCK|APLL_LOCK, CM_CLKEN_PLL); /* enable apll */
wait_on_value(BIT8, BIT8, CM_IDLEST_CKGEN, LDELAY); /* wait for apll lock */
sdelay(1000);
}
/***********************************************
* memif_init() - init the gpmc and sdrc
* - early init routines, called from flash or
* SRAM.
***********************************************/
void memif_init(void)
{
sdrc_init();
#ifndef CONFIG_PARTIAL_SRAM /* don't init if calling from flash */
gpmc_init();
#endif
}
/********************************************************
* mem_ok() - test used to see if timings are correct
* for a part. Helps in gussing which part
* we are currently using.
*******************************************************/
u32 mem_ok(void)
{ u32 val;
__raw_writel(0x0,OMAP2420_SDRC_CS0+0x400); /* clear pos A */
__raw_writel(0x12345678, OMAP2420_SDRC_CS0);/* pattern to pos B */
val = __raw_readl(OMAP2420_SDRC_CS0+0x400); /* get pos A value */
if (val != 0) /* see if pos A value changed*/
return(0);
else
return(1);
}
/********************************************************
* sdrc_init() - init the sdrc chip selects CS0 and CS1
* - early init routines, called from flash or
* SRAM.
*******************************************************/
void sdrc_init(void)
{
#define EARLY_INIT 1
do_sdrc_init(SDRC_CS0_OSET, EARLY_INIT); /* only init up first bank here */
}
/**********************************************************
* do_sdrc_init(): initialize the SDRAM for use.
* -called from low level code with stack only.
* -code sets up SDRAM timing and muxing for 2422 or 2420.
* -optimal settings can be placed here, or redone after i2c
* inspection of board info
*
* !!! When ES1 comes out need to conditionalize RFR value!!!
**********************************************************/
void do_sdrc_init(u32 offset, u32 early)
{
u32 cpu, bug=0, rev, shared=0, cs0=0, pmask=0,first=1;
sdrc_data_t *sdata; /* do not change type */
static const sdrc_data_t sdrc_2422 =
{
H4_2422_SDRC_SHARING, H4_2422_SDRC_MDCFG_0, H4_2422_SDRC_ACTIM_CTRLA_0,
H4_2422_SDRC_ACTIM_CTRLB_0, H4_2422_SDRC_RFR_CTRL_ES1, H4_2422_SDRC_MR_0,
H4_2422_SDRC_DLLA_CTRL, H4_2422_SDRC_DLLB_CTRL
};
static const sdrc_data_t sdrc_2420 =
{
H4_2420_SDRC_SHARING, H4_2420_SDRC_MDCFG_0, H4_2420_SDRC_ACTIM_CTRLA_0,
H4_2420_SDRC_ACTIM_CTRLB_0, H4_2420_SDRC_RFR_CTRL_ES1, H4_2420_SDRC_MR_0,
H4_2420_SDRC_DLLA_CTRL, H4_2420_SDRC_DLLB_CTRL
};
if (offset == SDRC_CS0_OSET)
cs0 = shared = 1; /* int regs shared between both chip select */
cpu = get_cpu_type();
/* warning generated, though code generation is correct. this may bite later, but is ok for now.
* there is only so much C code you can do on stack only operation.
*/
if (cpu == CPU_2422)
sdata = &sdrc_2422;
else
sdata = &sdrc_2420;
__asm__ __volatile__("": : :"memory");
#ifdef CONFIG_PARTIAL_SRAM
/* u-boot is compiled to run in DDR at 8xxxxxxx. If we use data here which is not pc relative
* we need to get the address correct. We need to find the current flash mapping to dress up
* the initial pointer load. As long as this is const data we should be ok.
*/
if(early)
sdata = (sdrc_data_t *)(((u32)sdata & 0x0003FFFF) | get_gpmc0_base());
#endif
men_combo:
if (!early && get_mem_type() == DDR_COMBO) { /* combo part has a shared CKE signal, can't use feature */
pmask = BIT2;
first = 0; /* trigger ddr_combo init */
}
if (shared) {
__raw_writel(__raw_readl(SMS_SYSCONFIG)|SMART_IDLE, SMS_SYSCONFIG);
__raw_writel(SMART_IDLE|SOFTRESET, SDRC_SYSCONFIG); /* reset sdrc */
wait_on_value(BIT0, BIT0, SDRC_STATUS, 12000000); /* wait till reset done set */
__raw_writel(SMART_IDLE, SDRC_SYSCONFIG); /* clear soft reset */
__raw_writel(sdata->sdrc_sharing, SDRC_SHARING);
__raw_writel((__raw_readl(SDRC_POWER)|SMART_IDLE) & ~pmask, SDRC_POWER);
}
if (first)
__raw_writel(sdata->sdrc_mdcfg_0, SDRC_MCFG_0+offset);
else {
__raw_writel((__raw_readl(SDRC_POWER)|SMART_IDLE) & ~pmask, SDRC_POWER);
__raw_writel(H4_2420_COMBO_MDCFG_0,SDRC_MCFG_0+offset);
}
if (cs0) {
__raw_writel(sdata->sdrc_actim_ctrla_0, SDRC_ACTIM_CTRLA_0);
__raw_writel(sdata->sdrc_actim_ctrlb_0, SDRC_ACTIM_CTRLB_0);
} else {
__raw_writel(sdata->sdrc_actim_ctrla_0, SDRC_ACTIM_CTRLA_1);
__raw_writel(sdata->sdrc_actim_ctrlb_0, SDRC_ACTIM_CTRLB_1);
}
__raw_writel(sdata->sdrc_rfr_ctrl, SDRC_RFR_CTRL+offset);
/* init sequence for _mDDR_ using manual commands (DDR is a bit different) */
__raw_writel(CMD_NOP, SDRC_MANUAL_0+offset);
sdelay(5000); /* susposed to be 100us per design spec for mddr*/
__raw_writel(CMD_PRECHARGE, SDRC_MANUAL_0+offset);
__raw_writel(CMD_AUTOREFRESH, SDRC_MANUAL_0+offset);
__raw_writel(CMD_AUTOREFRESH, SDRC_MANUAL_0+offset);
/*
* CSx SDRC Mode Register
* Burst length = 4 - DDR memory
* Serial mode
* CAS latency = x
*/
__raw_writel(sdata->sdrc_mr_0, SDRC_MR_0+offset);
/* NOTE: ES1 242x _BUG_ DLL */
rev = get_cpu_rev();
if (rev == CPU_2420_ES1 || rev == CPU_2422_ES1)
bug = BIT0;
/* enable & load up DLL with good value for 75MHz, and set phase to 90% */
if (shared) {
__raw_writel(sdata->sdrc_dlla_ctrl, SDRC_DLLA_CTRL);
__raw_writel(sdata->sdrc_dlla_ctrl & ~(BIT2|bug), SDRC_DLLA_CTRL);
__raw_writel(sdata->sdrc_dllb_ctrl, SDRC_DLLB_CTRL);
__raw_writel(sdata->sdrc_dllb_ctrl & ~(BIT2|bug) , SDRC_DLLB_CTRL);
}
sdelay(9000);
if (!first || mem_ok()) /* passed test or 2nd bank init */
return;
else {
first = 0;
goto men_combo;
}
}
/*****************************************************
* gpmc_init(): init gpmc bus
* Init GPMC for x16, MuxMode (SDRAM in x32).
* This code can only be executed from SRAM or SDRAM.
*****************************************************/
void gpmc_init(void)
{
u32 mux=0, mtype, mwidth;
/* global settings */
__raw_writel(0x10, GPMC_SYSCONFIG); /* smart idle */
__raw_writel(0x0, GPMC_IRQENABLE); /* isr's sources masked */
__raw_writel(0x1, GPMC_TIMEOUT_CONTROL);/* timeout disable */
__raw_writel(0x111, GPMC_CONFIG); /* set nWP, disable limited addr */
/* discover bus connection from sysboot */
if (is_gpmc_muxed() == GPMC_MUXED)
mux = BIT9;
mtype = get_gpmc0_type();
mwidth = get_gpmc0_width();
/* setup cs0 */
__raw_writel(0x0, GPMC_CONFIG7_0); /* disable current map */
sdelay(1000);
__raw_writel(H4_24XX_GPMC_CONFIG1_0|mux|mtype|mwidth, GPMC_CONFIG1_0);
//__raw_writel(H4_24XX_GPMC_CONFIG2_0, GPMC_CONFIG2_0);
__raw_writel(H4_24XX_GPMC_CONFIG3_0, GPMC_CONFIG3_0);
__raw_writel(H4_24XX_GPMC_CONFIG4_0, GPMC_CONFIG4_0);
//__raw_writel(H4_24XX_GPMC_CONFIG5_0, GPMC_CONFIG5_0);
__raw_writel(H4_24XX_GPMC_CONFIG7_0, GPMC_CONFIG7_0);/* enable new mapping */
sdelay(2000);
/* setup cs1 */
__raw_writel(0, GPMC_CONFIG7_1); /* disable any mapping */
sdelay(1000);
__raw_writel(H4_24XX_GPMC_CONFIG1_1|mux, GPMC_CONFIG1_1);
__raw_writel(H4_24XX_GPMC_CONFIG2_1, GPMC_CONFIG2_1);
__raw_writel(H4_24XX_GPMC_CONFIG3_1, GPMC_CONFIG3_1);
__raw_writel(H4_24XX_GPMC_CONFIG4_1, GPMC_CONFIG4_1);
__raw_writel(H4_24XX_GPMC_CONFIG5_1, GPMC_CONFIG5_1);
__raw_writel(H4_24XX_GPMC_CONFIG6_1, GPMC_CONFIG6_1);
__raw_writel(H4_24XX_GPMC_CONFIG7_1, GPMC_CONFIG7_1); /* enable mapping */
sdelay(2000);
}
This diff is collapsed.
/*
* Board specific setup info
*
* (C) Copyright 2004
* Texas Instruments, <www.ti.com>
* Richard Woodruff <r-woodruff2@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 <config.h>
#include <version.h>
#include <asm/arch/omap2420.h>
#include <asm/arch/mem.h>
#include <asm/arch/clocks.h>
_TEXT_BASE:
.word TEXT_BASE /* sdram load addr from config.mk */
#ifdef CONFIG_PARTIAL_SRAM
/**************************************************************************
* cpy_clk_code: relocates clock code into SRAM where its safer to execute
* R1 = SRAM destination address.
*************************************************************************/
.global cpy_clk_code
cpy_clk_code:
/* Copy DPLL code into SRAM */
adr r0, go_to_speed /* get addr of clock setting code */
mov r2, #384 /* r2 size to copy (div by 32 bytes) */
mov r1, r1 /* r1 <- dest address (passed in) */
add r2, r2, r0 /* r2 <- source end address */
next2:
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] */
bne next2
mov pc, lr /* back to caller */
/* ****************************************************************************
* go_to_speed: -Moves to bypass, -Commits clock dividers, -puts dpll at speed
* -executed from SRAM.
* R0 = PRCM_CLKCFG_CTRL - addr of valid reg
* R1 = CM_CLKEN_PLL - addr dpll ctlr reg
* R2 = dpll value
* R3 = CM_IDLEST_CKGEN - addr dpll lock wait
******************************************************************************/
.global go_to_speed
go_to_speed:
sub sp, sp, #0x4 /* get some stack space */
str r4, [sp] /* save r4's value */
/* move into fast relock bypass */
ldr r8, pll_ctl_add
mov r4, #0x2
str r4, [r8]
ldr r4, pll_stat
block:
ldr r8, [r4] /* wait for bypass to take effect */
and r8, r8, #0x3
cmp r8, #0x1
bne block
/* set new dpll dividers _after_ in bypass */
ldr r4, pll_div_add
ldr r8, pll_div_val
str r8, [r4]
/* now prepare GPMC (flash) for new dpll speed */
/* flash needs to be stable when we jump back to it */
ldr r4, cfg3_0_addr
ldr r8, cfg3_0_val
str r8, [r4]
ldr r4, cfg4_0_addr
ldr r8, cfg4_0_val
str r8, [r4]
ldr r4, cfg1_0_addr
ldr r8, [r4]
orr r8, r8, #0x3 /* up gpmc divider */
str r8, [r4]
/* setup to 2x loop though code. The first loop pre-loads the
* icache, the 2nd commits the prcm config, and locks the dpll
*/
mov r4, #0x1000 /* spin spin spin */
mov r8, #0x4 /* first pass condition & set registers */
cmp r8, #0x4
2:
ldrne r8, [r3] /* DPLL lock check */
and r8, r8, #0x7
cmp r8, #0x2
beq 4f
3:
subeq r8, r8, #0x1
streq r8, [r0] /* commit dividers (2nd time) */
nop
lloop1:
sub r4, r4, #0x1 /* Loop currently necessary else bad jumps */
nop
cmp r4, #0x0
bne lloop1
mov r4, #0x40000
cmp r8, #0x1
nop
streq r2, [r1] /* lock dpll (2nd time) */
nop
lloop2:
sub r4, r4, #0x1 /* loop currently necessary else bad jumps */
nop
cmp r4, #0x0
bne lloop2
mov r4, #0x40000
cmp r8, #0x1
nop
ldreq r8, [r3] /* get lock condition for dpll */
cmp r8, #0x4 /* first time though? */
bne 2b
moveq r8, #0x2 /* set to dpll check condition. */
beq 3b /* if condition not true branch */
4:
ldr r4, [sp]
add sp, sp, #0x4 /* return stack space */
mov pc, lr /* back to caller, locked */
_go_to_speed: .word go_to_speed
/* these constants need to be close for PIC code */
cfg3_0_addr:
.word GPMC_CONFIG3_0
cfg3_0_val:
.word H4_24XX_GPMC_CONFIG3_0
cfg4_0_addr:
.word GPMC_CONFIG4_0
cfg4_0_val:
.word H4_24XX_GPMC_CONFIG4_0
cfg1_0_addr:
.word GPMC_CONFIG1_0
pll_ctl_add:
.word CM_CLKEN_PLL
pll_stat:
.word CM_IDLEST_CKGEN
pll_div_add:
.word CM_CLKSEL1_PLL
pll_div_val:
.word DPLL_VAL /* DPLL setting (300MHz default) */
#endif
.globl platformsetup
platformsetup:
mov r3, r0 /* save skip information */
#ifdef CONFIG_APTIX
ldr r0, REG_SDRC_MCFG_0
ldr r1, VAL_SDRC_MCFG_0
str r1, [r0]
ldr r0, REG_SDRC_MR_0
ldr r1, VAL_SDRC_MR_0
str r1, [r0]
/* a ddr needs emr1 set here */
ldr r0, REG_SDRC_SHARING
ldr r1, VAL_SDRC_SHARING
str r1, [r0]
ldr r0, REG_SDRC_RFR_CTRL_0
ldr r1, VAL_SDRC_RFR_CTRL_0
str r1, [r0]
/* little delay after init */
mov r2, #0x1800
1:
subs r2, r2, #0x1
bne 1b
#endif
#ifdef CONFIG_PARTIAL_SRAM
ldr sp, SRAM_STACK
str ip, [sp] /* stash old link register */
mov ip, lr /* save link reg across call */
mov r0, r3 /* pass skip info to s_init */
bl s_init /* go setup pll,mux,memory */
ldr ip, [sp] /* restore save ip */
mov lr, ip /* restore link reg */
#endif
/* map interrupt controller */
ldr r0, VAL_INTH_SETUP
mcr p15, 0, r0, c15, c2, 4
/* back to arch calling code */
mov pc, lr
/* the literal pools origin */
.ltorg
REG_CONTROL_STATUS:
.word CONTROL_STATUS
VAL_INTH_SETUP:
.word PERIFERAL_PORT_BASE
SRAM_STACK:
.word LOW_LEVEL_SRAM_STACK
#ifdef CONFIG_APTIX
REG_SDRC_SHARING:
.word SDRC_SHARING
REG_SDRC_MCFG_0:
.word SDRC_MCFG_0
REG_SDRC_MR_0:
.word SDRC_MR_0
REG_SDRC_RFR_CTRL_0:
.word SDRC_RFR_CTRL
VAL_SDRC_SHARING:
.word VAL_H4_SDRC_SHARING
VAL_SDRC_MCFG_0:
.word VAL_H4_SDRC_MCFG_0
VAL_SDRC_MR_0:
.word VAL_H4_SDRC_MR_0
VAL_SDRC_RFR_CTRL_0:
.word VAL_H4_SDRC_RFR_CTRL_0
#endif
/*
* (C) Copyright 2004
* Texas Instruments, <www.ti.com>
* Richard Woodruff <r-woodruff2@ti.com>
*
* 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 <asm/arch/omap2420.h>
#include <asm/io.h>
#include <asm/arch/bits.h>
#include <asm/arch/mem.h> /* get mem tables */
#include <asm/arch/sys_proto.h>
#include <asm/arch/sys_info.h>
#include <i2c.h>
/**************************************************************************
* get_cpu_type() - low level get cpu type
* - no C globals yet.
* - just looking to say if this is a 2422 or 2420 or ...
* - to start with we will look at switch settings..
* - 2422 id's same as 2420 for ES1 will rely on H4 board characteristics
* (mux for 2420, non-mux for 2422).
***************************************************************************/
u32 get_cpu_type(void)
{
u32 v;
v = __raw_readl(TAP_IDCODE_REG);
v &= CPU_24XX_ID_MASK;
if (v == CPU_2420_CHIPID) { /* currently 2420 and 2422 have same id */
if (is_gpmc_muxed() == GPMC_MUXED) /* if mux'ed */
return(CPU_2420);
else
return(CPU_2422);
} else
return(CPU_2420); /* don't know, say 2420 */
}
/******************************************
* get_cpu_rev(void) - extract version info
******************************************/
u32 get_cpu_rev(void)
{
u32 v;
v = __raw_readl(TAP_IDCODE_REG);
v = v >> 28;
return(v+1); /* currently 2422 and 2420 match up */
}
/***********************************************************
* get_mem_type() - identify type of mDDR part used.
* 2422 uses stacked DDR, 2 parts CS0/CS1.
* 2420 may have 1 or 2, no good way to know...only init 1...
* when eeprom data is up we can select 1 more.
*************************************************************/
u32 get_mem_type(void)
{
if (get_cpu_type() == CPU_2422)
return(DDR_STACKED);
if (get_board_type() == BOARD_H4_MENELAUS)
return(DDR_COMBO);
else
return(DDR_DISCRETE);
}
/***********************************************************************
* get_board_type() - get board type based on current production stats.
* --- NOTE: 2 I2C EEPROMs will someday be populated with proper info.
* when they are available we can get info from there. This should
* be correct of all known boards up until today.
************************************************************************/
u32 get_board_type(void)
{
if (i2c_probe(I2C_MENELAUS) == 0)
return(BOARD_H4_MENELAUS);
else
return(BOARD_H4_SDP);
}
/******************************************************************
* get_sysboot_value() - get init word settings (dip switch on h4)
******************************************************************/
u32 get_sysboot_value(void)
{
return(0x00000FFF & __raw_readl(CONTROL_STATUS));
}
/***************************************************************************
* get_gpmc0_base() - Return current address hardware will be
* fetching from. The below effectively gives what is correct, its a bit
* mis-leading compared to the TRM. For the most general case the mask
* needs to be also taken into account this does work in practice.
* - for u-boot we currently map:
* -- 0 to nothing,
* -- 4 to flash
* -- 8 to enent
* -- c to wifi
****************************************************************************/
u32 get_gpmc0_base(void)
{
u32 b;
b = __raw_readl(GPMC_CONFIG7_0);
b &= 0x1F; /* keep base [5:0] */
b = b << 24; /* ret 0x0b000000 */
return(b);
}
/*****************************************************************
* is_gpmc_muxed() - tells if address/data lines are multiplexed
*****************************************************************/
u32 is_gpmc_muxed(void)
{
u32 mux;
mux = get_sysboot_value();
if (mux & BIT1) /* if mux'ed */
return(GPMC_MUXED);
else
return(GPMC_NONMUXED);
}
/************************************************************************
* get_gpmc0_type() - read sysboot lines to see type of memory attached
************************************************************************/
u32 get_gpmc0_type(void)
{
u32 type;
type = get_sysboot_value();
if ((type & (BIT3|BIT2)) == (BIT3|BIT2))
return(TYPE_NAND);
else
return(TYPE_NOR);
}
/*******************************************************************
* get_gpmc0_width() - See if bus is in x8 or x16 (mainly for nand)
*******************************************************************/
u32 get_gpmc0_width(void)
{
u32 width;
width = get_sysboot_value();
if ((width & 0xF) == (BIT3|BIT2))
return(WIDTH_8BIT);
else
return(WIDTH_16BIT);
}
/*********************************************************************
* wait_on_value() - common routine to allow waiting for changes in
* volatile regs.
*********************************************************************/
u32 wait_on_value(u32 read_bit_mask, u32 match_value, u32 read_addr, u32 bound)
{
u32 i = 0, val;
do {
++i;
val = __raw_readl(read_addr) & read_bit_mask;
if (val == match_value)
return(1);
if (i==bound)
return(0);
} while (1);
}
/*********************************************************************
* display_board_info() - print banner with board info.
*********************************************************************/
void display_board_info(u32 btype)
{
char cpu_2420[] = "2420";
char cpu_2422[] = "2422";
char db_men[] = "Menelaus";
char db_ip[]= "IP";
char *cpu_s, *db_s;
u32 cpu = get_cpu_type();
if(cpu == CPU_2420)
cpu_s = cpu_2420;
else
cpu_s = cpu_2422;
if(btype == BOARD_H4_MENELAUS)
db_s = db_men;
else
db_s = db_ip;
printf("TI H4 SDP Base Board with OMAP%s %s Daughter Board\n",cpu_s, db_s);
}
/*
* January 2004 - Changed to support H4 device
* Copyright (c) 2004 Texas Instruments
*
* (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/arm1136/start.o (.text)
*(.text)
}
. = ALIGN(4);
.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 = .;
}
......@@ -99,11 +99,7 @@ uchar env_get_char_spec (int index)
int env_init(void)
{
DECLARE_GLOBAL_DATA_PTR;
int crc1_ok =
(crc32(0, flash_addr->data, ENV_SIZE) == flash_addr->crc);
int crc2_ok =
(crc32(0, flash_addr_new->data, ENV_SIZE) == flash_addr_new->crc);
int crc1_ok = 0, crc2_ok = 0;
uchar flag1 = flash_addr->flags;
uchar flag2 = flash_addr_new->flags;
......@@ -112,6 +108,16 @@ int env_init(void)
ulong addr1 = (ulong)&(flash_addr->data);
ulong addr2 = (ulong)&(flash_addr_new->data);
#ifdef CONFIG_OMAP2420H4
int flash_probe(void);
if(flash_probe() == 0)
goto bad_flash;
#endif
crc1_ok = (crc32(0, flash_addr->data, ENV_SIZE) == flash_addr->crc);
crc2_ok = (crc32(0, flash_addr_new->data, ENV_SIZE) == flash_addr_new->crc);
if (crc1_ok && ! crc2_ok) {
gd->env_addr = addr1;
gd->env_valid = 1;
......@@ -138,6 +144,9 @@ int env_init(void)
gd->env_valid = 2;
}
#ifdef CONFIG_OMAP2420H4
bad_flash:
#endif
return (0);
}
......@@ -252,15 +261,22 @@ Done:
int env_init(void)
{
DECLARE_GLOBAL_DATA_PTR;
#ifdef CONFIG_OMAP2420H4
int flash_probe(void);
if(flash_probe() == 0)
goto bad_flash;
#endif
if (crc32(0, env_ptr->data, ENV_SIZE) == env_ptr->crc) {
gd->env_addr = (ulong)&(env_ptr->data);
gd->env_valid = 1;
} else {
gd->env_addr = (ulong)&default_environment[0];
gd->env_valid = 0;
return(0);
}
#ifdef CONFIG_OMAP2420H4
bad_flash:
#endif
gd->env_addr = (ulong)&default_environment[0];
gd->env_valid = 0;
return (0);
}
......
#
# (C) Copyright 2000-2003
# 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 = lib$(CPU).a
START = start.o
OBJS = interrupts.o cpu.o
all: .depend $(START) $(LIB)
$(LIB): $(OBJS)
$(AR) crv $@ $(OBJS)
#########################################################################
.depend: Makefile $(START:.o=.S) $(OBJS:.o=.c)
$(CC) -M $(CFLAGS) $(START:.o=.S) $(OBJS:.o=.c) > $@
sinclude .depend
#########################################################################
#
# (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
#
PLATFORM_RELFLAGS += -fno-strict-aliasing -fno-common -ffixed-r8 \
PLATFORM_CPPFLAGS += -mapcs-32 -march=armv6
/*
* (C) Copyright 2004 Texas Insturments
*
* (C) Copyright 2002
* Sysgo Real-Time Solutions, GmbH <www.elinos.com>
* Marius Groeger <mgroeger@sysgo.de>
*
* (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
*/
/*
* CPU specific code
*/
#include <common.h>
#include <command.h>
#include <asm/arch/omap2420.h>
/* read co-processor 15, register #1 (control register) */
static unsigned long read_p15_c1 (void)
{
unsigned long value;
__asm__ __volatile__(
"mrc p15, 0, %0, c1, c0, 0 @ read control reg\n"
: "=r" (value)
:
: "memory");
return value;
}
/* write to co-processor 15, register #1 (control register) */
static void write_p15_c1 (unsigned long value)
{
__asm__ __volatile__(
"mcr p15, 0, %0, c1, c0, 0 @ write it back\n"
:
: "r" (value)
: "memory");
read_p15_c1 ();
}
static void cp_delay (void)
{
volatile int i;
/* Many OMAP regs need at least 2 nops */
for (i = 0; i < 100; i++);
}
/* See also ARM Ref. Man. */
#define C1_MMU (1<<0) /* mmu off/on */
#define C1_ALIGN (1<<1) /* alignment faults off/on */
#define C1_DC (1<<2) /* dcache off/on */
#define C1_WB (1<<3) /* merging write buffer on/off */
#define C1_BIG_ENDIAN (1<<7) /* big endian off/on */
#define C1_SYS_PROT (1<<8) /* system protection */
#define C1_ROM_PROT (1<<9) /* ROM protection */
#define C1_IC (1<<12) /* icache off/on */
#define C1_HIGH_VECTORS (1<<13) /* location of vectors: low/high addresses */
#define RESERVED_1 (0xf << 3) /* must be 111b for R/W */
int cpu_init (void)
{
/*
* setup up stacks if necessary
*/
#ifdef CONFIG_USE_IRQ
DECLARE_GLOBAL_DATA_PTR;
IRQ_STACK_START = _armboot_start - CFG_MALLOC_LEN - CFG_GBL_DATA_SIZE - 4;
FIQ_STACK_START = IRQ_STACK_START - CONFIG_STACKSIZE_IRQ;
#endif
return 0;
}
int cleanup_before_linux (void)
{
/*
* this function is called just before we call linux
* it prepares the processor for linux
*
* we turn off caches etc ...
*/
unsigned long i;
disable_interrupts ();
#ifdef CONFIG_LCD
{
extern void lcd_disable(void);
extern void lcd_panel_disable(void);
lcd_disable(); /* proper disable of lcd & panel */
lcd_panel_disable();
}
#endif
/* turn off I/D-cache */
asm ("mrc p15, 0, %0, c1, c0, 0":"=r" (i));
i &= ~(C1_DC | C1_IC);
asm ("mcr p15, 0, %0, c1, c0, 0": :"r" (i));
/* flush I/D-cache */
i = 0;
asm ("mcr p15, 0, %0, c7, c7, 0": :"r" (i)); // invalidate both caches and flush btb
asm ("mcr p15, 0, %0, c7, c10, 4": :"r" (i)); // mem barrier to sync things
return(0);
}
int do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
{
extern void reset_cpu (ulong addr);
disable_interrupts ();
reset_cpu (0);
/*NOTREACHED*/
return(0);
}
void icache_enable (void)
{
ulong reg;
reg = read_p15_c1 (); /* get control reg. */
cp_delay ();
write_p15_c1 (reg | C1_IC);
}
void icache_disable (void)
{
ulong reg;
reg = read_p15_c1 ();
cp_delay ();
write_p15_c1 (reg & ~C1_IC);
}
int icache_status (void)
{
return(read_p15_c1 () & C1_IC) != 0;
}
/*
* (C) Copyright 2004
* Texas Instruments
* Richard Woodruff <r-woodruff2@ti.com>
*
* (C) Copyright 2002
* Sysgo Real-Time Solutions, GmbH <www.elinos.com>
* Marius Groeger <mgroeger@sysgo.de>
*
* (C) Copyright 2002
* Sysgo Real-Time Solutions, GmbH <www.elinos.com>
* Alex Zuepke <azu@sysgo.de>
*
* (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
*/
#include <common.h>
#include <asm/arch/bits.h>
#include <asm/arch/omap2420.h>
#include <asm/proc-armv/ptrace.h>
extern void reset_cpu(ulong addr);
#define TIMER_LOAD_VAL 0
/* macro to read the 32 bit timer */
#define READ_TIMER (*(volatile ulong *)(CFG_TIMERBASE+TCRR))
#ifdef CONFIG_USE_IRQ
/* enable IRQ interrupts */
void enable_interrupts (void)
{
unsigned long temp;
__asm__ __volatile__("mrs %0, cpsr\n"
"bic %0, %0, #0x80\n"
"msr cpsr_c, %0"
: "=r" (temp)
:
: "memory");
}
/*
* disable IRQ/FIQ interrupts
* returns true if interrupts had been enabled before we disabled them
*/
int disable_interrupts (void)
{
unsigned long old,temp;
__asm__ __volatile__("mrs %0, cpsr\n"
"orr %1, %0, #0xc0\n"
"msr cpsr_c, %1"
: "=r" (old), "=r" (temp)
:
: "memory");
return(old & 0x80) == 0;
}
#else
void enable_interrupts (void)
{
return;
}
int disable_interrupts (void)
{
return 0;
}
#endif
void bad_mode (void)
{
panic ("Resetting CPU ...\n");
reset_cpu (0);
}
void show_regs (struct pt_regs *regs)
{
unsigned long flags;
const char *processor_modes[] = {
"USER_26", "FIQ_26", "IRQ_26", "SVC_26",
"UK4_26", "UK5_26", "UK6_26", "UK7_26",
"UK8_26", "UK9_26", "UK10_26", "UK11_26",
"UK12_26", "UK13_26", "UK14_26", "UK15_26",
"USER_32", "FIQ_32", "IRQ_32", "SVC_32",
"UK4_32", "UK5_32", "UK6_32", "ABT_32",
"UK8_32", "UK9_32", "UK10_32", "UND_32",
"UK12_32", "UK13_32", "UK14_32", "SYS_32",
};
flags = condition_codes (regs);
printf ("pc : [<%08lx>] lr : [<%08lx>]\n"
"sp : %08lx ip : %08lx fp : %08lx\n",
instruction_pointer (regs),
regs->ARM_lr, regs->ARM_sp, regs->ARM_ip, regs->ARM_fp);
printf ("r10: %08lx r9 : %08lx r8 : %08lx\n",
regs->ARM_r10, regs->ARM_r9, regs->ARM_r8);
printf ("r7 : %08lx r6 : %08lx r5 : %08lx r4 : %08lx\n",
regs->ARM_r7, regs->ARM_r6, regs->ARM_r5, regs->ARM_r4);
printf ("r3 : %08lx r2 : %08lx r1 : %08lx r0 : %08lx\n",
regs->ARM_r3, regs->ARM_r2, regs->ARM_r1, regs->ARM_r0);
printf ("Flags: %c%c%c%c",
flags & CC_N_BIT ? 'N' : 'n',
flags & CC_Z_BIT ? 'Z' : 'z',
flags & CC_C_BIT ? 'C' : 'c', flags & CC_V_BIT ? 'V' : 'v');
printf (" IRQs %s FIQs %s Mode %s%s\n",
interrupts_enabled (regs) ? "on" : "off",
fast_interrupts_enabled (regs) ? "on" : "off",
processor_modes[processor_mode (regs)],
thumb_mode (regs) ? " (T)" : "");
}
void do_undefined_instruction (struct pt_regs *pt_regs)
{
printf ("undefined instruction\n");
show_regs (pt_regs);
bad_mode ();
}
void do_software_interrupt (struct pt_regs *pt_regs)
{
printf ("software interrupt\n");
show_regs (pt_regs);
bad_mode ();
}
void do_prefetch_abort (struct pt_regs *pt_regs)
{
printf ("prefetch abort\n");
show_regs (pt_regs);
bad_mode ();
}
void do_data_abort (struct pt_regs *pt_regs)
{
printf ("data abort\n");
show_regs (pt_regs);
bad_mode ();
}
void do_not_used (struct pt_regs *pt_regs)
{
printf ("not used\n");
show_regs (pt_regs);
bad_mode ();
}
void do_fiq (struct pt_regs *pt_regs)
{
printf ("fast interrupt request\n");
show_regs (pt_regs);
bad_mode ();
}
void do_irq (struct pt_regs *pt_regs)
{
printf ("interrupt request\n");
show_regs (pt_regs);
bad_mode ();
}
static ulong timestamp;
static ulong lastinc;
/* nothing really to do with interrupts, just starts up a counter. */
int interrupt_init (void)
{
int32_t val;
/* Start the counter ticking up */
*((int32_t *) (CFG_TIMERBASE + TLDR)) = TIMER_LOAD_VAL; /* reload value on overflow*/
val = (CFG_PVT << 2) | BIT5 | BIT1 | BIT0; /* mask to enable timer*/
*((int32_t *) (CFG_TIMERBASE + TCLR)) = val; /* start timer */
reset_timer_masked(); /* init the timestamp and lastinc value */
return(0);
}
/*
* timer without interrupts
*/
void reset_timer (void)
{
reset_timer_masked ();
}
ulong get_timer (ulong base)
{
return get_timer_masked () - base;
}
void set_timer (ulong t)
{
timestamp = t;
}
/* delay x useconds AND perserve advance timstamp value */
void udelay (unsigned long usec)
{
ulong tmo, tmp;
if (usec >= 1000) { /* if "big" number, spread normalization to seconds */
tmo = usec / 1000; /* start to normalize for usec to ticks per sec */
tmo *= CFG_HZ; /* find number of "ticks" to wait to achieve target */
tmo /= 1000; /* finish normalize. */
} else { /* else small number, don't kill it prior to HZ multiply */
tmo = usec * CFG_HZ;
tmo /= (1000*1000);
}
tmp = get_timer (0); /* get current timestamp */
if ( (tmo + tmp + 1) < tmp )/* if setting this forward will roll time stamp */
reset_timer_masked (); /* reset "advancing" timestamp to 0, set lastinc value */
else
tmo += tmp; /* else, set advancing stamp wake up time */
while (get_timer_masked () < tmo)/* loop till event */
/*NOP*/;
}
void reset_timer_masked (void)
{
/* reset time */
lastinc = READ_TIMER; /* capture current incrementer value time */
timestamp = 0; /* start "advancing" time stamp from 0 */
}
ulong get_timer_masked (void)
{
ulong now = READ_TIMER; /* current tick value */
if (now >= lastinc) /* normal mode (non roll) */
timestamp += (now - lastinc); /* move stamp fordward with absoulte diff ticks */
else /* we have rollover of incrementer */
timestamp += (0xFFFFFFFF - lastinc) + now;
lastinc = now;
return timestamp;
}
/* waits specified delay value and resets timestamp */
void udelay_masked (unsigned long usec)
{
ulong tmo;
if (usec >= 1000) { /* if "big" number, spread normalization to seconds */
tmo = usec / 1000; /* start to normalize for usec to ticks per sec */
tmo *= CFG_HZ; /* find number of "ticks" to wait to achieve target */
tmo /= 1000; /* finish normalize. */
} else { /* else small number, don't kill it prior to HZ multiply */
tmo = usec * CFG_HZ;
tmo /= (1000*1000);
}
reset_timer_masked (); /* set "advancing" timestamp to 0, set lastinc vaule */
while (get_timer_masked () < tmo) /* wait for time stamp to overtake tick number.*/
/* NOP */;
}
/*
* 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);
}
/*
* This function is derived from PowerPC code (timebase clock frequency).
* On ARM it returns the number of timer ticks per second.
*/
ulong get_tbclk (void)
{
ulong tbclk;
tbclk = CFG_HZ;
return tbclk;
}
/*
* armboot - Startup Code for OMP2420/ARM1136 CPU-core
*
* Copyright (c) 2004 Texas Instruments <r-woodruff2@ti.com>
*
* Copyright (c) 2001 Marius Grger <mag@sysgo.de>
* Copyright (c) 2002 Alex Zpke <azu@sysgo.de>
* Copyright (c) 2002 Gary Jennejohn <gj@denx.de>
* Copyright (c) 2003 Richard Woodruff <r-woodruff2@ti.com>
* Copyright (c) 2003 Kshitij <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 <config.h>
#include <version.h>
#include <asm/arch/omap2420.h>
.globl _start
_start: b reset
ldr pc, _undefined_instruction
ldr pc, _software_interrupt
ldr pc, _prefetch_abort
ldr pc, _data_abort
ldr pc, _not_used
ldr pc, _irq
ldr pc, _fiq
_undefined_instruction: .word undefined_instruction
_software_interrupt: .word software_interrupt
_prefetch_abort: .word prefetch_abort
_data_abort: .word data_abort
_not_used: .word not_used
_irq: .word irq
_fiq: .word fiq
_pad: .word 0x12345678 /* now 16*4=64 */
.global _end_vect
_end_vect:
.balignl 16,0xdeadbeef
/*
*************************************************************************
*
* Startup Code (reset vector)
*
* do important init only if we don't start from memory!
* setup Memory and board specific bits prior to relocation.
* relocate armboot to ram
* setup stack
*
*************************************************************************
*/
_TEXT_BASE:
.word TEXT_BASE
.globl _armboot_start
_armboot_start:
.word _start
/*
* These are defined in the board-specific linker script.
*/
.globl _bss_start
_bss_start:
.word __bss_start
.globl _bss_end
_bss_end:
.word _end
#ifdef CONFIG_USE_IRQ
/* IRQ stack memory (calculated at run-time) */
.globl IRQ_STACK_START
IRQ_STACK_START:
.word 0x0badc0de
/* IRQ stack memory (calculated at run-time) */
.globl FIQ_STACK_START
FIQ_STACK_START:
.word 0x0badc0de
#endif
/*
* the actual reset code
*/
reset:
/*
* set the cpu to SVC32 mode
*/
mrs r0,cpsr
bic r0,r0,#0x1f
orr r0,r0,#0xd3
msr cpsr,r0
#ifdef CONFIG_OMAP2420H4
/* Copy vectors to mask ROM indirect addr */
adr r0, _start /* r0 <- current position of code */
mov r2, #64 /* r2 <- size to copy */
add r2, r0, r2 /* r2 <- source end address */
mov r1, #SRAM_OFFSET0 /* build vect addr */
mov r3, #SRAM_OFFSET1
add r1, r1, r3
mov r3, #SRAM_OFFSET2
add r1, r1, r3
next:
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] */
bne next /* loop until equal */
#ifdef CONFIG_PARTIAL_SRAM
bl cpy_clk_code /* put dpll adjust code behind vectors */
#endif
#endif
/* the mask ROM code should have PLL and others stable */
bl cpu_init_crit
relocate: /* relocate U-Boot to RAM */
adr r0, _start /* r0 <- current position of code */
ldr r1, _TEXT_BASE /* test if we run from flash or RAM */
cmp r0, r1 /* don't reloc during debug */
beq stack_setup
ldr r2, _armboot_start
ldr r3, _bss_start
sub r2, r3, r2 /* r2 <- size of armboot */
add r2, r0, r2 /* r2 <- source end address */
copy_loop:
ldmia r0!, {r3-r10} /* copy from source address [r0] */
stmia r1!, {r3-r10} /* copy to target address [r1] */
cmp r0, r2 /* until source end addreee [r2] */
ble copy_loop
/* Set up the stack */
stack_setup:
ldr r0, _TEXT_BASE /* upper 128 KiB: relocated uboot */
sub r0, r0, #CFG_MALLOC_LEN /* malloc area */
sub r0, r0, #CFG_GBL_DATA_SIZE /* bdinfo */
#ifdef CONFIG_USE_IRQ
sub r0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ)
#endif
sub sp, r0, #12 /* leave 3 words for abort-stack */
clear_bss:
ldr r0, _bss_start /* find start of bss segment */
ldr r1, _bss_end /* stop here */
mov r2, #0x00000000 /* clear */
clbss_l:str r2, [r0] /* clear loop... */
add r0, r0, #4
cmp r0, r1
bne clbss_l
ldr pc, _start_armboot
_start_armboot: .word start_armboot
/*
*************************************************************************
*
* CPU_init_critical registers
*
* setup important registers
* setup memory timing
*
*************************************************************************
*/
cpu_init_crit:
/*
* flush v4 I/D caches
*/
mov r0, #0
mcr p15, 0, r0, c7, c7, 0 /* flush v3/v4 cache */
mcr p15, 0, r0, c8, c7, 0 /* flush v4 TLB */
/*
* disable MMU stuff and caches
*/
mrc p15, 0, r0, c1, c0, 0
bic r0, r0, #0x00002300 @ clear bits 13, 9:8 (--V- --RS)
bic r0, r0, #0x00000087 @ clear bits 7, 2:0 (B--- -CAM)
orr r0, r0, #0x00000002 @ set bit 2 (A) Align
#ifndef CONFIG_ICACHE_OFF
orr r0, r0, #0x00001000 @ set bit 12 (I) I-Cache
#endif
mcr p15, 0, r0, c1, c0, 0
/*
* Jump to board specific initialization... The Mask ROM will have already initialized
* basic memory. Go here to bump up clock rate and handle wake up conditions.
*/
adr r0, _start /* r0 <- current position of code */
ldr r1, _TEXT_BASE /* test if we run from flash or RAM */
cmp r0, r1 /* pass on info about skipping some init portions */
moveq r0,#0x1 /* flag to skip prcm and sdrc setup */
movne r0,#0x0
mov ip, lr /* persevere link reg across call */
bl platformsetup /* go setup pll,mux,memory */
mov lr, ip /* restore link */
mov pc, lr /* back to my caller */
/*
*************************************************************************
*
* Interrupt handling
*
*************************************************************************
*/
@
@ IRQ stack frame.
@
#define S_FRAME_SIZE 72
#define S_OLD_R0 68
#define S_PSR 64
#define S_PC 60
#define S_LR 56
#define S_SP 52
#define S_IP 48
#define S_FP 44
#define S_R10 40
#define S_R9 36
#define S_R8 32
#define S_R7 28
#define S_R6 24
#define S_R5 20
#define S_R4 16
#define S_R3 12
#define S_R2 8
#define S_R1 4
#define S_R0 0
#define MODE_SVC 0x13
#define I_BIT 0x80
/*
* use bad_save_user_regs for abort/prefetch/undef/swi ...
* use irq_save_user_regs / irq_restore_user_regs for IRQ/FIQ handling
*/
.macro bad_save_user_regs
sub sp, sp, #S_FRAME_SIZE @ carve out a frame on current user stack
stmia sp, {r0 - r12} @ Save user registers (now in svc mode) r0-r12
ldr r2, _armboot_start
sub r2, r2, #(CFG_MALLOC_LEN)
sub r2, r2, #(CFG_GBL_DATA_SIZE+8) @ set base 2 words into abort stack
ldmia r2, {r2 - r3} @ get values for "aborted" pc and cpsr (into parm regs)
add r0, sp, #S_FRAME_SIZE @ grab pointer to old stack
add r5, sp, #S_SP
mov r1, lr
stmia r5, {r0 - r3} @ save sp_SVC, lr_SVC, pc, cpsr
mov r0, sp @ save current stack into r0 (param register)
.endm
.macro irq_save_user_regs
sub sp, sp, #S_FRAME_SIZE
stmia sp, {r0 - r12} @ Calling r0-r12
add r8, sp, #S_PC @ !!!! R8 NEEDS to be saved !!!! a reserved stack spot would be good.
stmdb r8, {sp, lr}^ @ Calling SP, LR
str lr, [r8, #0] @ Save calling PC
mrs r6, spsr
str r6, [r8, #4] @ Save CPSR
str r0, [r8, #8] @ Save OLD_R0
mov r0, sp
.endm
.macro irq_restore_user_regs
ldmia sp, {r0 - lr}^ @ Calling r0 - lr
mov r0, r0
ldr lr, [sp, #S_PC] @ Get PC
add sp, sp, #S_FRAME_SIZE
subs pc, lr, #4 @ return & move spsr_svc into cpsr
.endm
.macro get_bad_stack
ldr r13, _armboot_start @ setup our mode stack (enter in banked mode)
sub r13, r13, #(CFG_MALLOC_LEN) @ move past malloc pool
sub r13, r13, #(CFG_GBL_DATA_SIZE+8) @ move to reserved a couple spots for abort stack
str lr, [r13] @ save caller lr in position 0 of saved stack
mrs lr, spsr @ get the spsr
str lr, [r13, #4] @ save spsr in position 1 of saved stack
mov r13, #MODE_SVC @ prepare SVC-Mode
@ msr spsr_c, r13
msr spsr, r13 @ switch modes, make sure moves will execute
mov lr, pc @ capture return pc
movs pc, lr @ jump to next instruction & switch modes.
.endm
.macro get_bad_stack_swi
sub r13, r13, #4 @ space on current stack for scratch reg.
str r0, [r13] @ save R0's value.
ldr r0, _armboot_start @ get data regions start
sub r0, r0, #(CFG_MALLOC_LEN) @ move past malloc pool
sub r0, r0, #(CFG_GBL_DATA_SIZE+8) @ move past gbl and a couple spots for abort stack
str lr, [r0] @ save caller lr in position 0 of saved stack
mrs r0, spsr @ get the spsr
str lr, [r0, #4] @ save spsr in position 1 of saved stack
ldr r0, [r13] @ restore r0
add r13, r13, #4 @ pop stack entry
.endm
.macro get_irq_stack @ setup IRQ stack
ldr sp, IRQ_STACK_START
.endm
.macro get_fiq_stack @ setup FIQ stack
ldr sp, FIQ_STACK_START
.endm
/*
* exception handlers
*/
.align 5
undefined_instruction:
get_bad_stack
bad_save_user_regs
bl do_undefined_instruction
.align 5
software_interrupt:
get_bad_stack_swi
bad_save_user_regs
bl do_software_interrupt
.align 5
prefetch_abort:
get_bad_stack
bad_save_user_regs
bl do_prefetch_abort
.align 5
data_abort:
get_bad_stack
bad_save_user_regs
bl do_data_abort
.align 5
not_used:
get_bad_stack
bad_save_user_regs
bl do_not_used
#ifdef CONFIG_USE_IRQ
.align 5
irq:
get_irq_stack
irq_save_user_regs
bl do_irq
irq_restore_user_regs
.align 5
fiq:
get_fiq_stack
/* someone ought to write a more effiction fiq_save_user_regs */
irq_save_user_regs
bl do_fiq
irq_restore_user_regs
#else
.align 5
irq:
get_bad_stack
bad_save_user_regs
bl do_irq
.align 5
fiq:
get_bad_stack
bad_save_user_regs
bl do_fiq
#endif
.align 5
.global arm1136_cache_flush
arm1136_cache_flush:
mcr p15, 0, r1, c7, c5, 0 @ invalidate I cache
mov pc, lr @ back to caller
.align 5
.globl reset_cpu
reset_cpu:
ldr r1, rstctl /* get addr for global reset reg */
mov r3, #0x3 /* full reset pll+mpu */
str r3, [r1] /* force reset */
mov r0, r0
_loop_forever:
b _loop_forever
rstctl:
.word PM_RSTCTRL_WKUP
This driver supports NE2000 compatible cards (those based on DP8390,
DP83902 and similar). It can be used with PCMCIA/CF cards provided
that the CCR is correctly initialized.
The code is based on sources from the Linux kernel (pcnet_cs.c,
8390.h) and eCOS(if_dp83902a.c, if_dp83902a.h). Both of these 2
wonderful world are GPL, so this is, of course, GPL.
I developed and tested this driver on a custom PXA255 based system and
with a billionton CF network card connected to the PCMCIA interface of
the micro (have a look at README.PXA_CF for the support of this port).
The options you have to specify in the config file are (with the
value for my board as an example):
#define CONFIG_DRIVER_NE2000
- Enables the driver
#define CONFIG_DRIVER_NE2000_BASE (0x20000000+0x300)
- Address where the board is mapped
#define CONFIG_DRIVER_NE2000_CCR (0x28000000+0x3f8)
- Address of the CCR (card configuration register). It could be found
by enabling DEBUG in cmd_pcmcia.c. If this is not defined nothing is
done as far as PCMCIA support is concerned.
#define CONFIG_DRIVER_NE2000_VAL (0x20)
- The value to be written in the CCR. It selects among different I/O
spaces that could be used by the card.
Enjoy!
Christian Pellegrin <chri@ascensit.com>
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment