Add port for the lpc2292sodimm evaluation board from EmbeddedArtists
authorGary Jennejohn <garyj@pollux.denx.de>
Wed, 24 Jan 2007 11:16:56 +0000 (12:16 +0100)
committerGary Jennejohn <garyj@pollux.denx.de>
Wed, 24 Jan 2007 11:16:56 +0000 (12:16 +0100)
24 files changed:
MAKEALL
Makefile
board/lpc2292sodimm/Makefile [new file with mode: 0644]
board/lpc2292sodimm/config.mk [new file with mode: 0644]
board/lpc2292sodimm/eth.c [new file with mode: 0644]
board/lpc2292sodimm/flash.c [new file with mode: 0644]
board/lpc2292sodimm/iap_entry.S [new file with mode: 0644]
board/lpc2292sodimm/lowlevel_init.S [new file with mode: 0644]
board/lpc2292sodimm/lpc2292sodimm.c [new file with mode: 0644]
board/lpc2292sodimm/mmc.c [new file with mode: 0644]
board/lpc2292sodimm/mmc_hw.c [new file with mode: 0644]
board/lpc2292sodimm/mmc_hw.h [new file with mode: 0644]
board/lpc2292sodimm/spi.c [new file with mode: 0644]
board/lpc2292sodimm/spi.h [new file with mode: 0644]
board/lpc2292sodimm/u-boot.lds [new file with mode: 0644]
cpu/arm720t/cpu.c
cpu/arm720t/interrupts.c
cpu/arm720t/serial.c
cpu/arm720t/start.S
include/asm-arm/arch-arm720t/hardware.h
include/asm-arm/arch-arm720t/lpc2292_registers.h [new file with mode: 0644]
include/asm-arm/arch-arm720t/mmc.h [new file with mode: 0644]
include/configs/lpc2292sodimm.h [new file with mode: 0644]
include/flash.h

diff --git a/MAKEALL b/MAKEALL
index 40a5c773e59408c679805ac19a078030568ab751..4e4d04b567db7eaec8c2fdaa325d9d52326d07eb 100755 (executable)
--- a/MAKEALL
+++ b/MAKEALL
@@ -181,7 +181,7 @@ LIST_SA="assabet dnp1110 gcplus lart shannon"
 LIST_ARM7="    \
        armadillo       B2              ep7312          evb4510         \
        impa7           integratorap    ap7             ap720t          \
-       modnet50                                                        \
+       lpc2292sodimm   modnet50                                        \
 "
 
 #########################################################################
index b1952edfe7f2d3f62bda2fcdea43996b75e31dc2..a44cba0102ebacb4b16e51811ad382c6e1df45f7 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -2029,6 +2029,9 @@ modnet50_config : unconfig
 evb4510_config :       unconfig
        @$(MKCONFIG) $(@:_config=) arm arm720t evb4510
 
+lpc2292sodimm_config:  unconfig
+       @$(MKCONFIG) $(@:_config=) arm arm720t lpc2292sodimm
+
 #########################################################################
 ## XScale Systems
 #########################################################################
diff --git a/board/lpc2292sodimm/Makefile b/board/lpc2292sodimm/Makefile
new file mode 100644 (file)
index 0000000..5a30198
--- /dev/null
@@ -0,0 +1,58 @@
+#
+# (C) Copyright 2002
+# Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+# Marius Groeger <mgroeger@sysgo.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   := lpc2292sodimm.o flash.o mmc.o spi.o mmc_hw.o eth.o
+SOBJS  := lowlevel_init.o iap_entry.o
+
+$(LIB):        $(OBJS) $(SOBJS)
+       $(AR) crv $@ $(OBJS) $(SOBJS)
+
+# this MUST be compiled as thumb code!
+iap_entry.o:
+       arm-linux-gcc  -D__ASSEMBLY__ -g  -Os   -fno-strict-aliasing  \
+       -fno-common -ffixed-r8 -msoft-float  -D__KERNEL__ \
+       -DTEXT_BASE=0x81500000  -I/home/garyj/proj/LPC/u-boot/include \
+       -fno-builtin -ffreestanding -nostdinc -isystem \
+       /opt/eldk/arm/usr/bin/../lib/gcc/arm-linux/4.0.0/include -pipe  \
+       -DCONFIG_ARM -D__ARM__ -march=armv4t -mtune=arm7tdmi -mabi=apcs-gnu \
+       -c -o iap_entry.o iap_entry.S
+
+clean:
+       rm -f $(SOBJS) $(OBJS)
+
+distclean:     clean
+       rm -f $(LIB) core *.bak .depend
+
+#########################################################################
+
+.depend:       Makefile $(SOBJS:.o=.S) $(OBJS:.o=.c)
+               $(CC) -M $(CPPFLAGS) $(SOBJS:.o=.S) $(OBJS:.o=.c) > $@
+
+-include .depend
+
+#########################################################################
diff --git a/board/lpc2292sodimm/config.mk b/board/lpc2292sodimm/config.mk
new file mode 100644 (file)
index 0000000..4146dac
--- /dev/null
@@ -0,0 +1,31 @@
+#
+# (C) Copyright 2000
+# Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+# Marius Groeger <mgroeger@sysgo.de>
+#
+# (C) Copyright 2000
+# 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
+#
+
+#address where u-boot will be relocated
+#TEXT_BASE = 0x0
+TEXT_BASE = 0x81500000
+
diff --git a/board/lpc2292sodimm/eth.c b/board/lpc2292sodimm/eth.c
new file mode 100644 (file)
index 0000000..14bec19
--- /dev/null
@@ -0,0 +1,884 @@
+/*
+ * 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 <common.h>
+#include <net.h>
+#include <asm/arch/hardware.h>
+#include "spi.h"
+
+/*
+ * Control Registers in Bank 0
+ */
+
+#define CTL_REG_ERDPTL   0x00
+#define CTL_REG_ERDPTH   0x01
+#define CTL_REG_EWRPTL   0x02
+#define CTL_REG_EWRPTH   0x03
+#define CTL_REG_ETXSTL   0x04
+#define CTL_REG_ETXSTH   0x05
+#define CTL_REG_ETXNDL   0x06
+#define CTL_REG_ETXNDH   0x07
+#define CTL_REG_ERXSTL   0x08
+#define CTL_REG_ERXSTH   0x09
+#define CTL_REG_ERXNDL   0x0A
+#define CTL_REG_ERXNDA   0x0B
+#define CTL_REG_ERXRDPTL 0x0C
+#define CTL_REG_ERXRDPTH 0x0D
+#define CTL_REG_ERXWRPTL 0x0E
+#define CTL_REG_ERXWRPTH 0x0F
+#define CTL_REG_EDMASTL  0x10
+#define CTL_REG_EDMASTH  0x11
+#define CTL_REG_EDMANDL  0x12
+#define CTL_REG_EDMANDH  0x13
+#define CTL_REG_EDMADSTL 0x14
+#define CTL_REG_EDMADSTH 0x15
+#define CTL_REG_EDMACSL  0x16
+#define CTL_REG_EDMACSH  0x17
+/* these are common in all banks */
+#define CTL_REG_EIE      0x1B
+#define CTL_REG_EIR      0x1C
+#define CTL_REG_ESTAT    0x1D
+#define CTL_REG_ECON2    0x1E
+#define CTL_REG_ECON1    0x1F
+
+/*
+ * Control Registers in Bank 1
+ */
+
+#define CTL_REG_EHT0    0x00
+#define CTL_REG_EHT1    0x01
+#define CTL_REG_EHT2    0x02
+#define CTL_REG_EHT3    0x03
+#define CTL_REG_EHT4    0x04
+#define CTL_REG_EHT5    0x05
+#define CTL_REG_EHT6    0x06
+#define CTL_REG_EHT7    0x07
+#define CTL_REG_EPMM0   0x08
+#define CTL_REG_EPMM1   0x09
+#define CTL_REG_EPMM2   0x0A
+#define CTL_REG_EPMM3   0x0B
+#define CTL_REG_EPMM4   0x0C
+#define CTL_REG_EPMM5   0x0D
+#define CTL_REG_EPMM6   0x0E
+#define CTL_REG_EPMM7   0x0F
+#define CTL_REG_EPMCSL  0x10
+#define CTL_REG_EPMCSH  0x11
+#define CTL_REG_EPMOL   0x14
+#define CTL_REG_EPMOH   0x15
+#define CTL_REG_EWOLIE  0x16
+#define CTL_REG_EWOLIR  0x17
+#define CTL_REG_ERXFCON 0x18
+#define CTL_REG_EPKTCNT 0x19
+
+/*
+ * Control Registers in Bank 2
+ */
+
+#define CTL_REG_MACON1   0x00
+#define CTL_REG_MACON2   0x01
+#define CTL_REG_MACON3   0x02
+#define CTL_REG_MACON4   0x03
+#define CTL_REG_MABBIPG  0x04
+#define CTL_REG_MAIPGL   0x06
+#define CTL_REG_MAIPGH   0x07
+#define CTL_REG_MACLCON1 0x08
+#define CTL_REG_MACLCON2 0x09
+#define CTL_REG_MAMXFLL  0x0A
+#define CTL_REG_MAMXFLH  0x0B
+#define CTL_REG_MAPHSUP  0x0D
+#define CTL_REG_MICON    0x11
+#define CTL_REG_MICMD    0x12
+#define CTL_REG_MIREGADR 0x14
+#define CTL_REG_MIWRL    0x16
+#define CTL_REG_MIWRH    0x17
+#define CTL_REG_MIRDL    0x18
+#define CTL_REG_MIRDH    0x19
+
+/*
+ * Control Registers in Bank 3
+ */
+
+#define CTL_REG_MAADR1  0x00
+#define CTL_REG_MAADR0  0x01
+#define CTL_REG_MAADR3  0x02
+#define CTL_REG_MAADR2  0x03
+#define CTL_REG_MAADR5  0x04
+#define CTL_REG_MAADR4  0x05
+#define CTL_REG_EBSTSD  0x06
+#define CTL_REG_EBSTCON 0x07
+#define CTL_REG_EBSTCSL 0x08
+#define CTL_REG_EBSTCSH 0x09
+#define CTL_REG_MISTAT  0x0A
+#define CTL_REG_EREVID  0x12
+#define CTL_REG_ECOCON  0x15
+#define CTL_REG_EFLOCON 0x17
+#define CTL_REG_EPAUSL  0x18
+#define CTL_REG_EPAUSH  0x19
+
+
+/*
+ * PHY Register
+ */
+
+#define PHY_REG_PHID1 0x02
+#define PHY_REG_PHID2 0x03
+
+
+/*
+ * Receive Filter Register (ERXFCON) bits
+ */
+
+#define ENC_RFR_UCEN  0x80
+#define ENC_RFR_ANDOR 0x40
+#define ENC_RFR_CRCEN 0x20
+#define ENC_RFR_PMEN  0x10
+#define ENC_RFR_MPEN  0x08
+#define ENC_RFR_HTEN  0x04
+#define ENC_RFR_MCEN  0x02
+#define ENC_RFR_BCEN  0x01
+
+/*
+ * ECON1 Register Bits
+ */
+
+#define ENC_ECON1_TXRST  0x80
+#define ENC_ECON1_RXRST  0x40
+#define ENC_ECON1_DMAST  0x20
+#define ENC_ECON1_CSUMEN 0x10
+#define ENC_ECON1_TXRTS  0x08
+#define ENC_ECON1_RXEN   0x04
+#define ENC_ECON1_BSEL1  0x02
+#define ENC_ECON1_BSEL0  0x01
+
+/*
+ * ECON2 Register Bits
+ */
+#define ENC_ECON2_AUTOINC 0x80
+#define ENC_ECON2_PKTDEC  0x40
+#define ENC_ECON2_PWRSV   0x20
+#define ENC_ECON2_VRPS    0x08
+
+/*
+ * EIR Register Bits
+ */
+#define ENC_EIR_PKTIF  0x40
+#define ENC_EIR_DMAIF  0x20
+#define ENC_EIR_LINKIF 0x10
+#define ENC_EIR_TXIF   0x08
+#define ENC_EIR_WOLIF  0x04
+#define ENC_EIR_TXERIF 0x02
+#define ENC_EIR_RXERIF 0x01
+
+/*
+ * ESTAT Register Bits
+ */
+
+#define ENC_ESTAT_INT     0x80
+#define ENC_ESTAT_LATECOL 0x10
+#define ENC_ESTAT_RXBUSY  0x04
+#define ENC_ESTAT_TXABRT  0x02
+#define ENC_ESTAT_CLKRDY  0x01
+
+/*
+ * EIE Register Bits
+ */
+
+#define ENC_EIE_INTIE  0x80
+#define ENC_EIE_PKTIE  0x40
+#define ENC_EIE_DMAIE  0x20
+#define ENC_EIE_LINKIE 0x10
+#define ENC_EIE_TXIE   0x08
+#define ENC_EIE_WOLIE  0x04
+#define ENC_EIE_TXERIE 0x02
+#define ENC_EIE_RXERIE 0x01
+
+/*
+ * MACON1 Register Bits
+ */
+#define ENC_MACON1_LOOPBK  0x10
+#define ENC_MACON1_TXPAUS  0x08
+#define ENC_MACON1_RXPAUS  0x04
+#define ENC_MACON1_PASSALL 0x02
+#define ENC_MACON1_MARXEN  0x01
+
+
+/*
+ * MACON2 Register Bits
+ */
+#define ENC_MACON2_MARST   0x80
+#define ENC_MACON2_RNDRST  0x40
+#define ENC_MACON2_MARXRST 0x08
+#define ENC_MACON2_RFUNRST 0x04
+#define ENC_MACON2_MATXRST 0x02
+#define ENC_MACON2_TFUNRST 0x01
+
+/*
+ * MACON3 Register Bits
+ */
+#define ENC_MACON3_PADCFG2 0x80
+#define ENC_MACON3_PADCFG1 0x40
+#define ENC_MACON3_PADCFG0 0x20
+#define ENC_MACON3_TXCRCEN 0x10
+#define ENC_MACON3_PHDRLEN 0x08
+#define ENC_MACON3_HFRMEN  0x04
+#define ENC_MACON3_FRMLNEN 0x02
+#define ENC_MACON3_FULDPX  0x01
+
+/*
+ * MICMD Register Bits
+ */
+#define ENC_MICMD_MIISCAN 0x02
+#define ENC_MICMD_MIIRD   0x01
+
+/*
+ * MISTAT Register Bits
+ */
+#define ENC_MISTAT_NVALID 0x04
+#define ENC_MISTAT_SCAN   0x02
+#define ENC_MISTAT_BUSY   0x01
+
+/*
+ * PHID1 and PHID2 values
+ */
+#define ENC_PHID1_VALUE 0x0083
+#define ENC_PHID2_VALUE 0x1400
+#define ENC_PHID2_MASK  0xFC00
+
+
+#define ENC_SPI_SLAVE_CS 0x00010000  /* pin P1.16 */
+#define ENC_RESET        0x00020000  /* pin P1.17 */
+
+#define FAILSAFE_VALUE 5000
+
+/*
+ * Controller memory layout:
+ *
+ * 0x0000 - 0x17ff  6k bytes receive buffer
+ * 0x1800 - 0x1fff  2k bytes transmit buffer
+ */
+/* Use the lower memory for receiver buffer. See errata pt. 5 */
+#define ENC_RX_BUF_START 0x0000
+#define ENC_TX_BUF_START 0x1800
+
+/* maximum frame length */
+#define ENC_MAX_FRM_LEN 1518
+
+#define enc_enable() PUT32(IO1CLR, ENC_SPI_SLAVE_CS)
+#define enc_disable() PUT32(IO1SET, ENC_SPI_SLAVE_CS)
+#define enc_cfg_spi() spi_set_cfg(0, 0, 0); spi_set_clock(8); 
+
+
+static unsigned char encReadReg(unsigned char regNo);
+static void encWriteReg(unsigned char regNo, unsigned char data);
+static void encWriteRegRetry(unsigned char regNo, unsigned char data, int c);
+static void encReadBuff(unsigned short length, unsigned char *pBuff);
+static void encWriteBuff(unsigned short length, unsigned char *pBuff);
+static void encBitSet(unsigned char regNo, unsigned char data);
+static void encBitClr(unsigned char regNo, unsigned char data);
+static void encReset(void);
+static void encInit(unsigned char *pEthAddr);
+static unsigned short phyRead(unsigned char addr);
+static void encPoll(void);
+static void encRx(void);
+
+#define m_nic_read(reg) encReadReg(reg)
+#define m_nic_write(reg, data) encWriteReg(reg, data)
+#define m_nic_write_retry(reg, data, count) encWriteRegRetry(reg, data, count)
+#define m_nic_read_data(len, buf) encReadBuff((len), (buf))
+#define m_nic_write_data(len, buf) encWriteBuff((len), (buf))
+
+/* bit field set */
+#define m_nic_bfs(reg, data) encBitSet(reg, data)
+
+/* bit field clear */
+#define m_nic_bfc(reg, data) encBitClr(reg, data)
+
+static unsigned char bank = 0;  /* current bank in enc28j60 */
+static unsigned char next_pointer_lsb;
+static unsigned char next_pointer_msb;
+
+static unsigned char buffer[ENC_MAX_FRM_LEN];
+static int rxResetCounter = 0;
+#define RX_RESET_COUNTER 1000;
+
+/*-----------------------------------------------------------------------------
+ * Returns 0 when failes otherwize 1
+ */
+int eth_init(bd_t *bis)
+{
+       /* configure GPIO */
+       (*((volatile unsigned long *) IO1DIR)) |= ENC_SPI_SLAVE_CS;
+       (*((volatile unsigned long *) IO1DIR)) |= ENC_RESET;
+
+       /* CS and RESET active low */
+       PUT32(IO1SET, ENC_SPI_SLAVE_CS);
+       PUT32(IO1SET, ENC_RESET);
+
+       spi_init();
+
+       /* initialize controller */
+       encReset();
+       encInit(bis->bi_enetaddr);
+
+       m_nic_bfs(CTL_REG_ECON1, ENC_ECON1_RXEN); /* enable receive */  
+
+       return 0;
+}
+
+int eth_send(volatile void *packet, int length)
+{
+       /* check frame length, etc. */
+       /* TODO: */
+
+       /* switch to bank 0 */
+       m_nic_bfc(CTL_REG_ECON1, (ENC_ECON1_BSEL1 | ENC_ECON1_BSEL0));  
+
+       /* set EWRPT */
+       m_nic_write(CTL_REG_EWRPTL, (ENC_TX_BUF_START & 0xff));
+       m_nic_write(CTL_REG_EWRPTH, (ENC_TX_BUF_START >> 8));
+
+       /* set ETXST */
+       m_nic_write(CTL_REG_ETXSTL, ENC_TX_BUF_START & 0xFF);
+       m_nic_write(CTL_REG_ETXSTH, ENC_TX_BUF_START >> 8);
+
+       /* write packet */
+       m_nic_write_data(length, (unsigned char*)packet);
+
+       /* set ETXND */
+       m_nic_write(CTL_REG_ETXNDL, (length + ENC_TX_BUF_START) & 0xFF);
+       m_nic_write(CTL_REG_ETXNDH, (length + ENC_TX_BUF_START) >> 8);
+
+       /* set ECON1.TXRTS */
+       m_nic_bfs(CTL_REG_ECON1, ENC_ECON1_TXRTS);
+
+       return 0;
+}
+
+
+/*****************************************************************************
+ * This function resets the receiver only. This function may be called from
+ * interrupt-context.
+ */
+static void encReceiverReset(void)
+{
+       unsigned char econ1;
+
+       econ1 = m_nic_read(CTL_REG_ECON1);
+       if((econ1 & ENC_ECON1_RXRST) == 0) {
+               m_nic_bfs(CTL_REG_ECON1, ENC_ECON1_RXRST);
+               rxResetCounter = RX_RESET_COUNTER;
+       }
+}
+
+/*****************************************************************************
+ * receiver reset timer
+ */
+static void encReceiverResetCallback(void)
+{
+       m_nic_bfc(CTL_REG_ECON1, ENC_ECON1_RXRST);
+       m_nic_bfs(CTL_REG_ECON1, ENC_ECON1_RXEN); /* enable receive */
+}
+
+/*-----------------------------------------------------------------------------
+ * Check for received packets. Call NetReceive for each packet. The return
+ * value is ignored by the caller.
+ */
+int eth_rx(void)
+{
+       if(rxResetCounter > 0 && --rxResetCounter == 0)
+       {
+               encReceiverResetCallback();
+       }
+
+       encPoll();
+
+       return 0;
+}
+
+void eth_halt(void)
+{
+       m_nic_bfc(CTL_REG_ECON1, ENC_ECON1_RXEN); /* disable receive */
+}
+
+/*****************************************************************************/
+
+static void encPoll(void) 
+{
+       unsigned char eir_reg;
+       volatile unsigned char estat_reg;
+       unsigned char pkt_cnt;
+
+       /* clear global interrupt enable bit in enc28j60 */
+       m_nic_bfc(CTL_REG_EIE, ENC_EIE_INTIE);
+       estat_reg = m_nic_read(CTL_REG_ESTAT);
+
+       eir_reg = m_nic_read(CTL_REG_EIR);
+
+       if (eir_reg & ENC_EIR_TXIF){
+               /* clear TXIF bit in EIR */
+               m_nic_bfc(CTL_REG_EIR, ENC_EIR_TXIF);
+       }
+
+       /* We have to use pktcnt and not pktif bit, see errata pt. 6 */
+
+       /* move to bank 1 */
+       m_nic_bfc(CTL_REG_ECON1, ENC_ECON1_BSEL1);
+       m_nic_bfs(CTL_REG_ECON1, ENC_ECON1_BSEL0);
+
+       /* read pktcnt */
+       pkt_cnt = m_nic_read(CTL_REG_EPKTCNT);
+
+       if (pkt_cnt > 0) {
+               if ((eir_reg & ENC_EIR_PKTIF) == 0) {
+                 /*printf("encPoll: pkt cnt > 0, but pktif not set\n"); */
+               }
+               encRx();
+               /* clear PKTIF bit in EIR, this should not need to be done but it
+                  seems like we get problems if we do not */
+               m_nic_bfc(CTL_REG_EIR, ENC_EIR_PKTIF);
+       }
+
+       if (eir_reg & ENC_EIR_RXERIF) {
+               printf("encPoll: rx error\n");
+               m_nic_bfc(CTL_REG_EIR, ENC_EIR_RXERIF);
+       }
+       if (eir_reg & ENC_EIR_TXERIF) {
+               printf("encPoll: tx error\n");
+               m_nic_bfc(CTL_REG_EIR, ENC_EIR_TXERIF);
+       }
+
+       /* set global interrupt enable bit in enc28j60 */
+       m_nic_bfs(CTL_REG_EIE, ENC_EIE_INTIE);
+}
+
+static void encRx(void)
+{
+       unsigned short pkt_len;
+       unsigned short copy_len;
+       unsigned short status;
+       unsigned char eir_reg;
+       unsigned char pkt_cnt = 0;
+
+       /* switch to bank 0 */
+       m_nic_bfc(CTL_REG_ECON1, (ENC_ECON1_BSEL1 | ENC_ECON1_BSEL0));
+
+       m_nic_write(CTL_REG_ERDPTL, next_pointer_lsb);
+       m_nic_write(CTL_REG_ERDPTH, next_pointer_msb);
+
+       do {
+               m_nic_read_data(6, buffer);
+               next_pointer_lsb = buffer[0];
+               next_pointer_msb = buffer[1];
+               pkt_len = buffer[2];
+               pkt_len |= (unsigned short)buffer[3] << 8;
+               status = buffer[4];
+               status |= (unsigned short)buffer[5] << 8;
+
+               if (pkt_len <= ENC_MAX_FRM_LEN) {
+                       copy_len = pkt_len;
+               } else {
+                       copy_len = 0;
+                       /*      p_priv->stats.rx_dropped++; */
+                       /* we will drop this packet */
+               }
+
+               if ((status & (1L << 7)) == 0) { /* check Received Ok bit */
+                       copy_len = 0;
+                       /*      p_priv->stats.rx_errors++; */
+               }
+
+               if (copy_len > 0) { 
+                       m_nic_read_data(copy_len, buffer);
+               }    
+
+               /* advance read pointer to next pointer */
+               m_nic_write(CTL_REG_ERDPTL, next_pointer_lsb);
+               m_nic_write(CTL_REG_ERDPTH, next_pointer_msb);
+
+               /* decrease packet counter */
+               m_nic_bfs(CTL_REG_ECON2, ENC_ECON2_PKTDEC);
+
+               /* move to bank 1 */
+               m_nic_bfc(CTL_REG_ECON1, ENC_ECON1_BSEL1);
+               m_nic_bfs(CTL_REG_ECON1, ENC_ECON1_BSEL0);
+
+               /* read pktcnt */
+               pkt_cnt = m_nic_read(CTL_REG_EPKTCNT);
+
+               /* switch to bank 0 */
+               m_nic_bfc(CTL_REG_ECON1, (ENC_ECON1_BSEL1 | ENC_ECON1_BSEL0));    
+
+               if (copy_len == 0) {
+                       eir_reg = m_nic_read(CTL_REG_EIR);
+                       encReceiverReset();
+                       printf("eth_rx: copy_len=0\n");
+                       continue;
+               }
+
+               NetReceive((unsigned char *)buffer, pkt_len);
+
+               eir_reg = m_nic_read(CTL_REG_EIR);
+       } while (pkt_cnt); /* Use EPKTCNT not EIR.PKTIF flag, see errata pt. 6 */
+       m_nic_write(CTL_REG_ERXRDPTL, next_pointer_lsb);
+       m_nic_write(CTL_REG_ERXRDPTH, next_pointer_msb);
+}
+
+static void encWriteReg(unsigned char regNo, unsigned char data)
+{
+       spi_lock();
+       enc_cfg_spi();
+       enc_enable();
+
+       spi_write(0x40 | regNo);  /* write in regNo */
+       spi_write(data);
+
+       enc_disable();
+       enc_enable();
+
+       spi_write(0x1f);      /* write reg 0x1f */
+
+       enc_disable();
+       spi_unlock();
+}
+
+static void encWriteRegRetry(unsigned char regNo, unsigned char data, int c)
+{
+       unsigned char readback;
+       int i;
+
+       spi_lock();
+
+       for (i = 0; i < c; i++) {
+               enc_cfg_spi();
+               enc_enable();
+
+               spi_write(0x40 | regNo);    /* write in regNo */
+               spi_write(data);
+
+               enc_disable();
+               enc_enable();
+
+               spi_write(0x1f);        /* write reg 0x1f */
+
+               enc_disable();
+
+               spi_unlock();       /* we must unlock spi first */
+
+               readback = encReadReg(regNo);
+
+               spi_lock();
+
+               if (readback == data)
+                       break;
+       }
+       spi_unlock();
+
+       if (i == c) {
+               printf("enc28j60: write reg %d failed\n", regNo);
+       }
+}
+
+static unsigned char encReadReg(unsigned char regNo)
+{
+       unsigned char rxByte;
+
+       spi_lock();
+       enc_cfg_spi();
+       enc_enable();
+
+       spi_write(0x1f);      /* read reg 0x1f */
+
+       bank = spi_read() & 0x3;
+
+       enc_disable();
+       enc_enable();
+
+       spi_write(regNo);
+       rxByte = spi_read();
+
+       /* check if MAC or MII register */
+       if (((bank == 2) && (regNo <= 0x1a)) ||
+                       ((bank == 3) && (regNo <= 0x05 || regNo == 0x0a))) {
+               /* ignore first byte and read another byte */
+               rxByte = spi_read();
+       }
+
+       enc_disable();
+       spi_unlock();
+
+       return rxByte;
+}
+
+static void encReadBuff(unsigned short length, unsigned char *pBuff)
+{
+       spi_lock();
+       enc_cfg_spi();
+       enc_enable();
+
+       spi_write(0x20 | 0x1a);         /* read buffer memory */
+
+       while(length--) {
+               if(pBuff != NULL)
+                       *pBuff++ = spi_read();
+               else
+                       spi_write(0);
+       }
+
+       enc_disable();
+       spi_unlock();
+}
+
+static void encWriteBuff(unsigned short length, 
+             unsigned char *pBuff)
+{
+       spi_lock();
+       enc_cfg_spi();
+       enc_enable();
+
+       spi_write(0x60 | 0x1a);         /* write buffer memory */
+
+       spi_write(0x00);      /* control byte */
+
+       while(length--)
+               spi_write(*pBuff++);
+
+       enc_disable();
+       spi_unlock();
+}
+
+static void encBitSet(unsigned char regNo, unsigned char data)
+{
+       spi_lock();
+       enc_cfg_spi();
+       enc_enable();
+
+       spi_write(0x80 | regNo);  /* bit field set */
+       spi_write(data);
+
+       enc_disable();
+       spi_unlock();
+}
+
+static void encBitClr(unsigned char regNo, unsigned char data)
+{
+       spi_lock();
+       enc_cfg_spi();
+       enc_enable();
+
+       spi_write(0xA0 | regNo);  /* bit field clear */
+       spi_write(data);
+
+       enc_disable();
+       spi_unlock();
+}
+
+static void encReset(void)
+{
+       spi_lock();
+       enc_cfg_spi();
+       enc_enable();
+
+       spi_write(0xff);      /* soft reset */
+
+       enc_disable();
+       spi_unlock();
+
+       /* sleep 1 ms. See errata pt. 2 */
+       udelay(1000);
+
+#if 0
+       (*((volatile unsigned long*)IO1CLR)) &= ENC_RESET;
+       mdelay(5);
+       (*((volatile unsigned long*)IO1SET)) &= ENC_RESET;
+#endif
+}
+
+static void encInit(unsigned char *pEthAddr)
+{
+       unsigned short phid1 = 0;
+       unsigned short phid2 = 0;
+
+       /* switch to bank 0 */
+       m_nic_bfc(CTL_REG_ECON1, (ENC_ECON1_BSEL1 | ENC_ECON1_BSEL0));
+
+       /* 
+       * Setup the buffer space. The reset values are valid for the
+       * other pointers. 
+       */  
+#if 0
+       /* We shall not write to ERXST, see errata pt. 5. Instead we 
+        have to make sure that ENC_RX_BUS_START is 0. */
+       m_nic_write_retry(CTL_REG_ERXSTL, (ENC_RX_BUF_START & 0xFF), 1);
+       m_nic_write_retry(CTL_REG_ERXSTH, (ENC_RX_BUF_START >> 8), 1);
+#endif
+       m_nic_write_retry(CTL_REG_ERDPTL, (ENC_RX_BUF_START & 0xFF), 1);
+       m_nic_write_retry(CTL_REG_ERDPTH, (ENC_RX_BUF_START >> 8), 1);
+
+       next_pointer_lsb = (ENC_RX_BUF_START & 0xFF);
+       next_pointer_msb = (ENC_RX_BUF_START >> 8);
+
+       /*
+       * For tracking purposes, the ERXRDPT registers should be programmed with 
+       * the same value. This is the read pointer.
+       */
+       m_nic_write(CTL_REG_ERXRDPTL, (ENC_RX_BUF_START & 0xFF));
+       m_nic_write_retry(CTL_REG_ERXRDPTH, (ENC_RX_BUF_START >> 8), 1);
+
+       /* Setup receive filters. */
+
+       /* move to bank 1 */
+       m_nic_bfc(CTL_REG_ECON1, ENC_ECON1_BSEL1);
+       m_nic_bfs(CTL_REG_ECON1, ENC_ECON1_BSEL0);
+
+       /* OR-filtering, Unicast, CRC-check and broadcast */
+       m_nic_write_retry(CTL_REG_ERXFCON, 
+                       (ENC_RFR_UCEN|ENC_RFR_CRCEN|ENC_RFR_BCEN), 1);
+
+       /* Wait for Oscillator Start-up Timer (OST). */
+       while((m_nic_read(CTL_REG_ESTAT) & ENC_ESTAT_CLKRDY) == 0) {
+               static int cnt = 0;
+               if(cnt++ >= 1000){
+                 cnt = 0;
+               }
+       }
+
+       /* verify identification */
+       phid1 = phyRead(PHY_REG_PHID1);
+       phid2 = phyRead(PHY_REG_PHID2);
+
+       if(phid1 != ENC_PHID1_VALUE 
+        || (phid2 & ENC_PHID2_MASK) != ENC_PHID2_VALUE) {
+               printf("ERROR: failed to identify controller\n");
+               printf("phid1 = %x, phid2 = %x\n", 
+                       phid1, (phid2&ENC_PHID2_MASK));
+               printf("should be phid1 = %x, phid2 = %x\n", 
+                       ENC_PHID1_VALUE, ENC_PHID2_VALUE);
+       }
+
+       /*
+       * --- MAC Initialization ---
+       */
+
+       /* Pull MAC out of Reset */
+
+       /* switch to bank 2 */
+       m_nic_bfc(CTL_REG_ECON1, ENC_ECON1_BSEL0);
+       m_nic_bfs(CTL_REG_ECON1, ENC_ECON1_BSEL1);
+       /* clear MAC reset bits */
+       m_nic_write_retry(CTL_REG_MACON2, 0, 1);
+
+       /* enable MAC to receive frames */
+       m_nic_write_retry(CTL_REG_MACON1, ENC_MACON1_MARXEN, 10);
+
+       /* configure pad, tx-crc and duplex */ 
+       /* TODO maybe enable FRMLNEN */
+       m_nic_write_retry(CTL_REG_MACON3, (ENC_MACON3_PADCFG0|ENC_MACON3_TXCRCEN), 
+                       10);
+
+       /* set maximum frame length */
+       m_nic_write_retry(CTL_REG_MAMXFLL, (ENC_MAX_FRM_LEN & 0xff), 10);
+       m_nic_write_retry(CTL_REG_MAMXFLH, (ENC_MAX_FRM_LEN >> 8), 10);
+
+       /* 
+       * Set MAC back-to-back inter-packet gap. Recommended 0x12 for half duplex
+       * and 0x15 for full duplex.
+       */
+       m_nic_write_retry(CTL_REG_MABBIPG, 0x12, 10);
+
+       /* Set (low byte) Non-Back-to_Back Inter-Packet Gap. Recommended 0x12 */
+       m_nic_write_retry(CTL_REG_MAIPGL, 0x12, 10);
+
+       /* 
+       * Set (high byte) Non-Back-to_Back Inter-Packet Gap. Recommended 
+       * 0x0c for half-duplex. Nothing for full-duplex
+       */
+       m_nic_write_retry(CTL_REG_MAIPGH, 0x0C, 10);
+
+       /* set MAC address */
+
+       /* switch to bank 3 */
+       m_nic_bfs(CTL_REG_ECON1, (ENC_ECON1_BSEL0|ENC_ECON1_BSEL1));
+
+       m_nic_write_retry(CTL_REG_MAADR0, pEthAddr[5], 1);
+       m_nic_write_retry(CTL_REG_MAADR1, pEthAddr[4], 1);
+       m_nic_write_retry(CTL_REG_MAADR2, pEthAddr[3], 1);
+       m_nic_write_retry(CTL_REG_MAADR3, pEthAddr[2], 1);
+       m_nic_write_retry(CTL_REG_MAADR4, pEthAddr[1], 1);
+       m_nic_write_retry(CTL_REG_MAADR5, pEthAddr[0], 1);
+
+       /*
+       * Receive settings
+       */
+
+       /* auto-increment RX-pointer when reading a received packet */
+       m_nic_bfs(CTL_REG_ECON2, ENC_ECON2_AUTOINC);
+
+       /* enable interrupts */
+       m_nic_bfs(CTL_REG_EIE, ENC_EIE_PKTIE);
+       m_nic_bfs(CTL_REG_EIE, ENC_EIE_TXIE);
+       m_nic_bfs(CTL_REG_EIE, ENC_EIE_RXERIE);
+       m_nic_bfs(CTL_REG_EIE, ENC_EIE_TXERIE);
+       m_nic_bfs(CTL_REG_EIE, ENC_EIE_INTIE);
+}
+
+/*****************************************************************************
+ *
+ * Description:
+ *    Read PHY registers.
+ *
+ *    NOTE! This function will change to Bank 2.
+ *
+ * Params:
+ *    [in] addr address of the register to read
+ *
+ * Returns:
+ *    The value in the register
+ */
+static unsigned short phyRead(unsigned char addr)
+{
+       unsigned short ret = 0;
+
+       /* move to bank 2 */
+       m_nic_bfc(CTL_REG_ECON1, ENC_ECON1_BSEL0);
+       m_nic_bfs(CTL_REG_ECON1, ENC_ECON1_BSEL1);
+
+       /* write address to MIREGADR */
+       m_nic_write(CTL_REG_MIREGADR, addr);
+
+       /* set MICMD.MIIRD */
+       m_nic_write(CTL_REG_MICMD, ENC_MICMD_MIIRD);
+
+       /* poll MISTAT.BUSY bit until operation is complete */
+       while((m_nic_read(CTL_REG_MISTAT) & ENC_MISTAT_BUSY) != 0) {
+               static int cnt = 0;
+
+               if(cnt++ >= 1000) {
+                       /* GJ - this seems extremely dangerous! */
+                       /* printf("#"); */
+                       cnt = 0;
+               }
+       }
+
+       /* clear MICMD.MIIRD */
+       m_nic_write(CTL_REG_MICMD, 0);
+
+       ret  = (m_nic_read(CTL_REG_MIRDH) << 8);
+       ret |= (m_nic_read(CTL_REG_MIRDL) & 0xFF);
+
+       return ret;
+}
diff --git a/board/lpc2292sodimm/flash.c b/board/lpc2292sodimm/flash.c
new file mode 100644 (file)
index 0000000..dcef7dd
--- /dev/null
@@ -0,0 +1,477 @@
+/*
+ * (C) Copyright 2006 Embedded Artists AB <www.embeddedartists.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/hardware.h>
+
+/* IAP commands use 32 bytes at the top of CPU internal sram, we
+   use 512 bytes below that */
+#define COPY_BUFFER_LOCATION 0x40003de0
+
+#define IAP_LOCATION 0x7ffffff1
+#define IAP_CMD_PREPARE 50
+#define IAP_CMD_COPY 51
+#define IAP_CMD_ERASE 52
+#define IAP_CMD_CHECK 53
+#define IAP_CMD_ID 54
+#define IAP_CMD_VERSION 55
+#define IAP_CMD_COMPARE 56
+
+#define IAP_RET_CMD_SUCCESS 0
+
+#define SST_BASEADDR 0x80000000
+#define SST_ADDR1 ((volatile ushort*)(SST_BASEADDR + (0x5555 << 1)))
+#define SST_ADDR2 ((volatile ushort*)(SST_BASEADDR + (0x2AAA << 1)))
+
+
+static unsigned long command[5];
+static unsigned long result[2];
+
+flash_info_t flash_info[CFG_MAX_FLASH_BANKS];
+
+extern void iap_entry(unsigned long * command, unsigned long * result);
+
+/*-----------------------------------------------------------------------
+ *
+ */
+int get_flash_sector(flash_info_t * info, ulong flash_addr)
+{
+       int i;
+
+       for(i=1; i < (info->sector_count); i++) {
+               if (flash_addr < (info->start[i]))
+                       break;
+       }
+
+       return (i-1);
+}
+
+/*-----------------------------------------------------------------------
+ * This function assumes that flash_addr is aligned on 512 bytes boundary
+ * in flash. This function also assumes that prepare have been called 
+ * for the sector in question.
+ */
+int copy_buffer_to_flash(flash_info_t * info, ulong flash_addr)
+{
+       int first_sector;
+       int last_sector;
+
+       first_sector = get_flash_sector(info, flash_addr);
+       last_sector = get_flash_sector(info, flash_addr + 512 - 1);
+
+       /* prepare sectors for write */
+       command[0] = IAP_CMD_PREPARE;
+       command[1] = first_sector;
+       command[2] = last_sector;
+       iap_entry(command, result);
+       if (result[0] != IAP_RET_CMD_SUCCESS) {
+               printf("IAP prepare failed\n");
+               return ERR_PROG_ERROR;
+       }
+
+       command[0] = IAP_CMD_COPY;
+       command[1] = flash_addr;
+       command[2] = COPY_BUFFER_LOCATION;
+       command[3] = 512;
+       command[4] = CFG_SYS_CLK_FREQ >> 10;
+       iap_entry(command, result);
+       if (result[0] != IAP_RET_CMD_SUCCESS) {
+               printf("IAP copy failed\n");
+               return 1;
+       }
+
+       return 0;
+}
+
+/*-----------------------------------------------------------------------
+ *
+ */
+void write_word_sst(ulong addr, ushort data)
+{
+       ushort tmp;
+
+       *SST_ADDR1 = 0x00AA;
+       *SST_ADDR2 = 0x0055;
+       *SST_ADDR1 = 0x00A0;
+       *((volatile ushort*)addr) = data;
+       /* do data polling */
+       do {
+               tmp = *((volatile ushort*)addr);
+       } while (tmp != data);
+}
+
+/*-----------------------------------------------------------------------
+ */
+
+ulong flash_init (void)
+{
+       int j, k;
+       ulong size = 0;
+       ulong flashbase = 0;
+
+       flash_info[0].flash_id = (PHILIPS_LPC2292 & FLASH_VENDMASK);
+       flash_info[0].size = 0x003E000; /* 256 - 8 KB */
+       flash_info[0].sector_count = 17;
+       memset (flash_info[0].protect, 0, 17);
+       flashbase = 0x00000000;
+       for (j = 0, k = 0; j < 8; j++, k++) {
+               flash_info[0].start[k] = flashbase;
+               flashbase += 0x00002000;
+       }
+       for (j = 0; j < 2; j++, k++) {
+               flash_info[0].start[k] = flashbase;
+               flashbase += 0x00010000;
+       }
+       for (j = 0; j < 7; j++, k++) {
+               flash_info[0].start[k] = flashbase;
+               flashbase += 0x00002000;
+       }               
+       size += flash_info[0].size;
+
+       flash_info[1].flash_id = (SST_MANUFACT & FLASH_VENDMASK);
+       flash_info[1].size = 0x00200000; /* 2 MB */
+       flash_info[1].sector_count = 512;
+       memset (flash_info[1].protect, 0, 512);
+       flashbase = SST_BASEADDR;
+       for (j=0; j<512; j++) {
+               flash_info[1].start[j] = flashbase;
+               flashbase += 0x1000;    /* 4 KB sectors */
+       }
+       size += flash_info[1].size;
+
+       /* Protect monitor and environment sectors */
+       flash_protect (FLAG_PROTECT_SET,
+                0x0,
+                0x0 + 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_print_info (flash_info_t * info)
+{
+       int i;
+       int erased = 0;
+       unsigned long j;
+       unsigned long count;
+       unsigned char *p;
+
+       switch (info->flash_id & FLASH_VENDMASK) {
+       case (SST_MANUFACT & FLASH_VENDMASK):
+               printf("SST: ");
+               break;
+       case (PHILIPS_LPC2292 & FLASH_VENDMASK):
+               printf("Philips: ");
+               break;
+       default:
+               printf ("Unknown Vendor ");
+               break;
+       }
+
+       printf ("  Size: %ld KB in %d Sectors\n",
+         info->size >> 10, info->sector_count);
+
+       printf ("  Sector Start Addresses:");
+       for (i = 0; i < info->sector_count; i++) {
+               if ((i % 5) == 0) {
+                       printf ("\n   ");
+               }
+               if (i < (info->sector_count - 1)) {
+                       count = info->start[i+1] - info->start[i];
+               }
+               else {
+                       count = info->start[0] + info->size - info->start[i];
+               }
+               p = (unsigned char*)(info->start[i]);
+               erased = 1;
+               for (j = 0; j < count; j++) {
+                       if (*p != 0xFF) {
+                               erased = 0;
+                               break;
+                       }
+                       p++;
+               }
+               printf (" %08lX%s%s", info->start[i], info->protect[i] ? " RO" : "   ",
+                       erased ? " E" : "  ");
+       }
+       printf ("\n");
+}
+
+/*-----------------------------------------------------------------------
+ */
+
+int flash_erase_philips (flash_info_t * info, int s_first, int s_last)
+{
+       int flag;
+       int prot;
+       int sect;
+
+       prot = 0;
+       for (sect = s_first; sect <= s_last; ++sect) {
+               if (info->protect[sect]) {
+                       prot++;
+               }
+       }
+       if (prot)
+               return ERR_PROTECTED;
+
+
+       flag = disable_interrupts();
+
+       printf ("Erasing %d sectors starting at sector %2d.\n"
+       "This make take some time ... ",
+       s_last - s_first + 1, s_first);
+
+       command[0] = IAP_CMD_PREPARE;
+       command[1] = s_first;
+       command[2] = s_last;
+       iap_entry(command, result);
+       if (result[0] != IAP_RET_CMD_SUCCESS) {
+               printf("IAP prepare failed\n");
+               return ERR_PROTECTED;
+       }
+
+       command[0] = IAP_CMD_ERASE;
+       command[1] = s_first;
+       command[2] = s_last;
+       command[3] = CFG_SYS_CLK_FREQ >> 10;
+       iap_entry(command, result);
+       if (result[0] != IAP_RET_CMD_SUCCESS) {
+               printf("IAP erase failed\n");
+               return ERR_PROTECTED;
+       }
+
+       if (flag)
+               enable_interrupts();
+
+       return ERR_OK;
+}
+
+int flash_erase_sst (flash_info_t * info, int s_first, int s_last)
+{
+       int i;
+
+       for (i = s_first; i <= s_last; i++) {
+               *SST_ADDR1 = 0x00AA;
+               *SST_ADDR2 = 0x0055;
+               *SST_ADDR1 = 0x0080;
+               *SST_ADDR1 = 0x00AA;
+               *SST_ADDR2 = 0x0055;
+               *((volatile ushort*)(info->start[i])) = 0x0030;
+               /* wait for erase to finish */
+               udelay(25000);
+       }
+
+       return ERR_OK;
+}
+
+int flash_erase (flash_info_t * info, int s_first, int s_last)
+{
+       switch (info->flash_id & FLASH_VENDMASK) {
+               case (SST_MANUFACT & FLASH_VENDMASK):
+                       return flash_erase_sst(info, s_first, s_last);  
+               case (PHILIPS_LPC2292 & FLASH_VENDMASK):
+                       return flash_erase_philips(info, s_first, s_last);  
+               default:
+                       return ERR_PROTECTED;
+       }
+       return ERR_PROTECTED;
+}
+
+/*-----------------------------------------------------------------------
+ * Copy memory to flash.
+ *
+ * cnt is in bytes
+ */
+
+int write_buff_sst (flash_info_t * info, uchar * src, ulong addr, ulong cnt)
+{
+       ushort tmp;
+       ulong i;
+       uchar* src_org;
+       uchar* dst_org;
+       ulong cnt_org = cnt;
+       int ret = ERR_OK;
+
+       src_org = src;
+       dst_org = (uchar*)addr;
+
+       if (addr & 1) {         /* if odd address */
+               tmp = *((uchar*)(addr - 1)); /* little endian */
+               tmp |= (*src << 8);
+               write_word_sst(addr - 1, tmp);
+               addr += 1;
+               cnt -= 1;
+               src++;
+       }
+       while (cnt > 1) {
+               tmp = ((*(src+1)) << 8) + (*src); /* little endian */
+               write_word_sst(addr, tmp);
+               addr += 2;
+               src += 2;
+               cnt -= 2;
+       }
+       if (cnt > 0) {
+               tmp = (*((uchar*)(addr + 1))) << 8;
+               tmp |= *src;
+               write_word_sst(addr, tmp);
+       }
+
+       for (i = 0; i < cnt_org; i++) {
+               if (*dst_org != *src_org) {
+                       printf("Write failed. Byte %lX differs\n", i);
+                       ret = ERR_PROG_ERROR;
+                       break;
+               }
+               dst_org++;
+               src_org++;
+       }
+
+
+       return ret;
+}
+
+int write_buff_philips (flash_info_t * info, 
+                       uchar * src, 
+                       ulong addr, 
+                       ulong cnt)
+{
+       int first_copy_size;
+       int last_copy_size;
+       int first_block;
+       int last_block;
+       int nbr_mid_blocks;
+       uchar memmap_value;
+       ulong i;
+       uchar* src_org;
+       uchar* dst_org;
+       int ret = ERR_OK;
+
+       src_org = src;
+       dst_org = (uchar*)addr;
+
+       first_block = addr / 512;
+       last_block = (addr + cnt) / 512;
+       nbr_mid_blocks = last_block - first_block - 1;
+
+       first_copy_size = 512 - (addr % 512);
+       last_copy_size = (addr + cnt) % 512;
+
+#if 0
+       printf("\ncopy first block: (1) %lX -> %lX 0x200 bytes, "
+               "(2) %lX -> %lX 0x%X bytes, (3) %lX -> %lX 0x200 bytes\n",
+       (ulong)(first_block * 512),
+       (ulong)COPY_BUFFER_LOCATION,
+       (ulong)src,
+       (ulong)(COPY_BUFFER_LOCATION + 512 - first_copy_size),
+       first_copy_size,
+       (ulong)COPY_BUFFER_LOCATION,
+       (ulong)(first_block * 512));
+#endif
+
+       /* copy first block */
+       memcpy((void*)COPY_BUFFER_LOCATION, 
+               (void*)(first_block * 512), 512);
+       memcpy((void*)(COPY_BUFFER_LOCATION + 512 - first_copy_size), 
+               src, first_copy_size);
+       copy_buffer_to_flash(info, first_block * 512);
+       src += first_copy_size;
+       addr += first_copy_size;
+
+       /* copy middle blocks */
+       for (i = 0; i < nbr_mid_blocks; i++) {
+#if 0
+               printf("copy middle block: %lX -> %lX 512 bytes, "
+               "%lX -> %lX 512 bytes\n",
+               (ulong)src,
+               (ulong)COPY_BUFFER_LOCATION,
+               (ulong)COPY_BUFFER_LOCATION,
+               (ulong)addr);
+#endif
+               memcpy((void*)COPY_BUFFER_LOCATION, src, 512);
+               copy_buffer_to_flash(info, addr);
+               src += 512;
+               addr += 512;    
+       }
+
+
+       if (last_copy_size > 0) {
+#if 0
+               printf("copy last block: (1) %lX -> %lX 0x200 bytes, "
+               "(2) %lX -> %lX 0x%X bytes, (3) %lX -> %lX x200 bytes\n",
+               (ulong)(last_block * 512),
+               (ulong)COPY_BUFFER_LOCATION,
+               (ulong)src,
+               (ulong)(COPY_BUFFER_LOCATION),
+               last_copy_size,
+               (ulong)COPY_BUFFER_LOCATION,
+               (ulong)addr);
+#endif
+               /* copy last block */
+               memcpy((void*)COPY_BUFFER_LOCATION, 
+                       (void*)(last_block * 512), 512);
+               memcpy((void*)COPY_BUFFER_LOCATION, 
+                       src, last_copy_size);
+               copy_buffer_to_flash(info, addr);
+       }
+
+       /* verify write */
+       memmap_value = GET8(MEMMAP);
+
+       disable_interrupts();
+
+       PUT8(MEMMAP, 01);               /* we must make sure that initial 64
+                                                          bytes are taken from flash when we
+                                                          do the compare */
+
+       for (i = 0; i < cnt; i++) {
+               if (*dst_org != *src_org){
+                       printf("Write failed. Byte %lX differs\n", i);
+                       ret = ERR_PROG_ERROR;
+                       break;
+               }
+               dst_org++;
+               src_org++;
+       }
+
+       PUT8(MEMMAP, memmap_value);
+       enable_interrupts();
+
+       return ret;
+}
+
+int write_buff (flash_info_t * info, uchar * src, ulong addr, ulong cnt)
+{
+       switch (info->flash_id & FLASH_VENDMASK) {
+               case (SST_MANUFACT & FLASH_VENDMASK):
+                       return write_buff_sst(info, src, addr, cnt);  
+               case (PHILIPS_LPC2292 & FLASH_VENDMASK):
+                       return write_buff_philips(info, src, addr, cnt);  
+               default:
+                       return ERR_PROG_ERROR;
+       }
+       return ERR_PROG_ERROR;
+}
diff --git a/board/lpc2292sodimm/iap_entry.S b/board/lpc2292sodimm/iap_entry.S
new file mode 100644 (file)
index 0000000..28ed805
--- /dev/null
@@ -0,0 +1,7 @@
+IAP_ADDRESS:   .word   0x7FFFFFF1
+       
+.globl iap_entry
+iap_entry:
+       ldr     r2, IAP_ADDRESS
+       bx      r2
+       mov     pc, lr
diff --git a/board/lpc2292sodimm/lowlevel_init.S b/board/lpc2292sodimm/lowlevel_init.S
new file mode 100644 (file)
index 0000000..a91e678
--- /dev/null
@@ -0,0 +1,87 @@
+/*
+ * (C) Copyright 2006 Embedded Artists AB <www.embeddedartists.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 <config.h>
+#include <version.h>
+#include <asm/arch/hardware.h>
+
+/* some parameters for the board */
+/* setting up the memory */
+#define        SRAM_START      0x40000000
+#define        SRAM_SIZE       0x00004000
+#define   BCFG0_VALUE 0x1000ffef
+#define   BCFG1_VALUE 0x10001C61
+       
+_TEXT_BASE:
+       .word   TEXT_BASE
+MEMMAP_ADR:    
+       .word   MEMMAP
+BCFG0_ADR:
+  .word BCFG0
+_BCFG0_VALUE:
+  .word BCFG0_VALUE
+BCFG1_ADR:
+       .word   BCFG1
+_BCFG1_VALUE:
+       .word   BCFG1_VALUE
+PINSEL2_ADR:
+       .word   PINSEL2
+PINSEL2_MASK:
+       .word   0x00000000
+PINSEL2_VALUE:
+       .word   0x0F800914
+
+.extern _start
+
+.globl lowlevel_init
+lowlevel_init:
+       /* set up memory control register for bank 0 */
+       ldr r0, _BCFG0_VALUE
+       ldr r1, BCFG0_ADR
+       str r0, [r1]
+
+       /* set up memory control register for bank 1 */
+       ldr     r0, _BCFG1_VALUE
+       ldr     r1, BCFG1_ADR
+       str     r0, [r1]
+
+       /* set up PINSEL2 for bus-pins */
+       ldr     r0, PINSEL2_ADR
+       ldr     r1, [r0]
+       ldr     r2, PINSEL2_MASK
+       ldr     r3, PINSEL2_VALUE
+       and     r1, r1, r2
+       orr     r1, r1, r3
+       str     r1, [r0]
+               
+       /* move vectors to beginning of SRAM */
+       mov     r2, #SRAM_START         
+       mov     r0, #0 /*_start*/
+       ldmneia r0!, {r3-r10}           
+       stmneia r2!, {r3-r10}           
+       ldmneia r0, {r3-r9}
+       stmneia r2, {r3-r9}
+
+        /* Set-up MEMMAP register, so vectors are taken from SRAM */
+       ldr     r0, MEMMAP_ADR
+       mov     r1, #0x02       /* vectors re-mapped to static RAM */
+       str     r1, [r0]
+                       
+       /* everything is fine now */
+       mov     pc, lr
diff --git a/board/lpc2292sodimm/lpc2292sodimm.c b/board/lpc2292sodimm/lpc2292sodimm.c
new file mode 100644 (file)
index 0000000..de04c66
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * (C) Copyright 2002
+ * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Marius Groeger <mgroeger@sysgo.de>
+ *
+ * (C) Copyright 2005 Rowel Atienza <rowel@diwalabs.com>
+ * Armadillo board HT1070
+ *
+ * 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 <clps7111.h>
+
+/* ------------------------------------------------------------------------- */
+
+
+/*
+ * Miscelaneous platform dependent initialisations
+ */
+
+int board_init (void)
+{
+       DECLARE_GLOBAL_DATA_PTR;
+
+       /* Activate LED flasher */
+       IO_LEDFLSH = 0x40;
+
+       /* arch number MACH_TYPE_ARMADILLO - not official*/
+       gd->bd->bi_arch_number = 83;
+
+       /* location of boot parameters */
+       gd->bd->bi_boot_params = 0xc0000100;
+
+       return 0;
+}
+
+int dram_init (void)
+{
+       DECLARE_GLOBAL_DATA_PTR;
+
+       gd->bd->bi_dram[0].start = PHYS_SDRAM_1;
+       gd->bd->bi_dram[0].size = PHYS_SDRAM_1_SIZE;
+
+       return (0);
+}
diff --git a/board/lpc2292sodimm/mmc.c b/board/lpc2292sodimm/mmc.c
new file mode 100644 (file)
index 0000000..e361db1
--- /dev/null
@@ -0,0 +1,154 @@
+/*
+ * 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 <common.h>
+#include <mmc.h>
+#include <asm/errno.h>
+#include <asm/arch/hardware.h>
+#include <part.h>
+#include <fat.h>
+#include "mmc_hw.h"
+#include "spi.h"
+
+#ifdef CONFIG_MMC
+
+#undef MMC_DEBUG
+
+static block_dev_desc_t mmc_dev;
+
+/* these are filled out by a call to mmc_hw_get_parameters */
+static int hw_size;            /* in kbytes */
+static int hw_nr_sects;
+static int hw_sect_size;       /* in bytes */
+
+block_dev_desc_t * mmc_get_dev(int dev)
+{
+       return (block_dev_desc_t *)(&mmc_dev);
+}
+
+unsigned long mmc_block_read(int dev, 
+                            unsigned long start, 
+                            lbaint_t blkcnt,
+                            unsigned long *buffer)
+{
+       unsigned long rc = 0;
+       unsigned char *p = (unsigned char *)buffer;
+       unsigned long i;
+       unsigned long addr = start;
+
+#ifdef MMC_DEBUG
+       printf("mmc_block_read: start=%lu, blkcnt=%lu\n", start, 
+                (unsigned long)blkcnt);
+#endif
+
+       for(i = 0; i < (unsigned long)blkcnt; i++) {
+#ifdef MMC_DEBUG
+               printf("mmc_read_sector: addr=%lu, buffer=%p\n", addr, p);
+#endif
+               (void)mmc_read_sector(addr, p);
+               rc++;
+               addr++;
+               p += hw_sect_size;
+       } 
+
+       return rc;
+}
+
+/*-----------------------------------------------------------------------------
+ * Read hardware paramterers (sector size, size, number of sectors)
+ */
+static int mmc_hw_get_parameters(void)
+{
+       unsigned char csddata[16];
+       unsigned int sizemult;
+       unsigned int size;
+
+       mmc_read_csd(csddata);
+       hw_sect_size = 1<<(csddata[5] & 0x0f);
+       size = ((csddata[6]&0x03)<<10)+(csddata[7]<<2)+(csddata[8]&0xc0);
+       sizemult = ((csddata[10] & 0x80)>>7)+((csddata[9] & 0x03)<<1);
+       hw_nr_sects = (size+1)*(1<<(sizemult+2));
+       hw_size = hw_nr_sects*hw_sect_size/1024;
+
+#ifdef MMC_DEBUG
+       printf("mmc_hw_get_parameters: hw_sect_size=%d, hw_nr_sects=%d, "
+                "hw_size=%d\n", hw_sect_size, hw_nr_sects, hw_size);
+#endif
+
+       return 0;
+}
+
+int mmc_init(int verbose)
+{
+       int ret = -ENODEV;
+
+       if (verbose)
+               printf("mmc_init\n");
+
+       spi_init();
+       mmc_hw_init();
+
+       mmc_hw_get_parameters();
+
+       mmc_dev.if_type = IF_TYPE_MMC;
+       mmc_dev.part_type = PART_TYPE_DOS;
+       mmc_dev.dev = 0;
+       mmc_dev.lun = 0;
+       mmc_dev.type = 0;
+       mmc_dev.blksz = hw_sect_size;
+       mmc_dev.lba = hw_nr_sects;
+       sprintf((char*)mmc_dev.vendor, "Unknown vendor");
+       sprintf((char*)mmc_dev.product, "Unknown product");
+       sprintf((char*)mmc_dev.revision, "N/A");
+       mmc_dev.removable = 0;  /* should be true??? */
+       mmc_dev.block_read = mmc_block_read;
+
+       fat_register_device(&mmc_dev, 1);
+
+       ret = 0;
+
+       return ret;
+}
+
+int mmc_write(uchar * src, ulong dst, int size)
+{
+#ifdef MMC_DEBUG
+       printf("mmc_write: src=%p, dst=%lu, size=%u\n", src, dst, size);
+#endif
+       /* Since mmc2info always returns 0 this function will never be called */
+       return 0;
+}
+
+int mmc_read(ulong src, uchar * dst, int size)
+{
+#ifdef MMC_DEBUG
+       printf("mmc_read: src=%lu, dst=%p, size=%u\n", src, dst, size);
+#endif
+       /* Since mmc2info always returns 0 this function will never be called */
+       return 0;
+}
+
+int mmc2info(ulong addr)
+{
+       /* This function is used by cmd_cp to determine if source or destination
+        address resides on MMC-card or not. We do not support copy to and from
+        MMC-card so we always return 0. */
+       return 0;
+}
+
+#endif /* CONFIG_MMC */
diff --git a/board/lpc2292sodimm/mmc_hw.c b/board/lpc2292sodimm/mmc_hw.c
new file mode 100644 (file)
index 0000000..0b5ddf9
--- /dev/null
@@ -0,0 +1,233 @@
+/*
+    This code was original written by Ulrich Radig and modified by
+    Embedded Artists AB (www.embeddedartists.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 <config.h>
+#include <common.h>
+#include <asm/arch/hardware.h>
+#include "spi.h"
+
+#define MMC_Enable() PUT32(IO1CLR, 1l << 22)
+#define MMC_Disable() PUT32(IO1SET, 1l << 22)
+#define mmc_spi_cfg() spi_set_clock(8); spi_set_cfg(0, 1, 0); 
+
+static unsigned char Write_Command_MMC (unsigned char *CMD);
+static void MMC_Read_Block(unsigned char *CMD, unsigned char *Buffer,
+                   unsigned short int Bytes);
+
+/* initialize the hardware */
+int mmc_hw_init(void)
+{
+       unsigned long a;
+       unsigned short int Timeout = 0;
+       unsigned char b;
+       unsigned char CMD[] = {0x40, 0x00, 0x00, 0x00, 0x00, 0x95};
+
+       /* set-up GPIO and SPI */
+       (*((volatile unsigned long *)PINSEL2)) &= ~(1l << 3); /* clear bit 3 */
+       (*((volatile unsigned long *)IO1DIR)) |= (1l << 22); /* set bit 22 (output) */
+
+       MMC_Disable();
+
+       spi_lock();
+       spi_set_clock(248);
+       spi_set_cfg(0, 1, 0);
+       MMC_Enable();
+
+       /* waste some time */
+       for(a=0; a < 20000; a++)
+               asm("nop");
+
+       /* Put the MMC/SD-card into SPI-mode */
+       for (b = 0; b < 10; b++) /* Sends min 74+ clocks to the MMC/SD-card */
+               spi_write(0xff);
+
+       /* Sends command CMD0 to MMC/SD-card */
+       while (Write_Command_MMC(CMD) != 1) {
+               if (Timeout++ > 200) {
+                       MMC_Disable();
+                       spi_unlock();
+                       return(1); /* Abort with command 1 (return 1) */
+               }
+       }
+       /* Sends Command CMD1 an MMC/SD-card */
+       Timeout = 0;
+       CMD[0] = 0x41;/* Command 1 */
+       CMD[5] = 0xFF;
+
+       while (Write_Command_MMC(CMD) != 0) {
+               if (Timeout++ > 200) {
+                       MMC_Disable();
+                       spi_unlock();
+                       return (2); /* Abort with command 2 (return 2) */
+               }
+       }
+
+       MMC_Disable();
+       spi_unlock();
+
+       return 0;
+}
+
+/* ############################################################################
+   Sends a command to the MMC/SD-card
+   ######################################################################### */
+static unsigned char Write_Command_MMC (unsigned char *CMD)
+{
+       unsigned char a, tmp = 0xff;
+       unsigned short int Timeout = 0;
+
+       MMC_Disable();
+       spi_write(0xFF);
+       MMC_Enable();
+
+       for (a = 0; a < 0x06; a++)
+               spi_write(*CMD++);
+
+       while (tmp == 0xff) {
+               tmp = spi_read();
+               if (Timeout++ > 5000)
+                 break;
+       }
+
+       return (tmp);
+}
+
+/* ############################################################################
+   Routine to read the CID register from the MMC/SD-card (16 bytes)
+   ######################################################################### */
+void MMC_Read_Block(unsigned char *CMD, unsigned char *Buffer, unsigned short
+       int Bytes)
+{
+       unsigned short int a;
+
+       spi_lock();
+       mmc_spi_cfg();
+       MMC_Enable();
+
+       if (Write_Command_MMC(CMD) != 0) {
+               MMC_Disable();
+               spi_unlock();
+               return;
+       }       
+
+       while (spi_read() != 0xfe) {};
+       for (a = 0; a < Bytes; a++)
+               *Buffer++ = spi_read();
+
+       /* Read the CRC-byte */
+       spi_read(); /* CRC - byte is discarded */
+       spi_read(); /* CRC - byte is discarded */
+       /* set MMC_Chip_Select to high (MMC/SD-card Inaktiv) */
+       MMC_Disable();
+       spi_unlock();
+
+       return;
+}
+
+/* ############################################################################
+   Routine to read a block (512 bytes) from the MMC/SD-card
+   ######################################################################### */
+unsigned char mmc_read_sector (unsigned long addr,unsigned char *Buffer)
+{
+       /* Command 16 to read aBlocks from the MMC/SD - caed */
+       unsigned char CMD[] = {0x51,0x00,0x00,0x00,0x00,0xFF}; 
+
+       /* The addres on the MMC/SD-card is in bytes,
+       addr is transformed from blocks to bytes and the result is
+       placed into the command */
+
+       addr = addr << 9; /* addr = addr * 512 */
+
+       CMD[1] = ((addr & 0xFF000000) >> 24);
+       CMD[2] = ((addr & 0x00FF0000) >> 16);
+       CMD[3] = ((addr & 0x0000FF00) >> 8 );
+
+       MMC_Read_Block(CMD, Buffer, 512);
+
+       return (0);
+}
+
+/* ############################################################################
+   Routine to write a block (512 byte) to the MMC/SD-card
+   ######################################################################### */
+unsigned char mmc_write_sector (unsigned long addr,unsigned char *Buffer)
+{
+       unsigned char tmp, a;
+       unsigned short int b;
+       /* Command 24 to write a block to the MMC/SD - card */
+       unsigned char CMD[] = {0x58, 0x00, 0x00, 0x00, 0x00, 0xFF}; 
+
+       /* The addres on the MMC/SD-card is in bytes,
+       addr is transformed from blocks to bytes and the result is
+       placed into the command */
+
+       addr = addr << 9; /* addr = addr * 512 */
+
+       CMD[1] = ((addr & 0xFF000000) >> 24);
+       CMD[2] = ((addr & 0x00FF0000) >> 16);
+       CMD[3] = ((addr & 0x0000FF00) >> 8 );
+
+       spi_lock();
+       mmc_spi_cfg();
+       MMC_Enable();
+
+       /* Send command CMD24 to the MMC/SD-card (Write 1 Block/512 Bytes) */
+       tmp = Write_Command_MMC(CMD);
+       if (tmp != 0) {
+               MMC_Disable();
+               spi_unlock();
+               return(tmp);
+       }       
+
+       /* Do a short delay and send a clock-pulse to the MMC/SD-card */
+       for (a = 0; a < 100; a++)
+               spi_read();
+
+       /* Send a start byte to the MMC/SD-card */
+       spi_write(0xFE);        
+
+       /* Write the block (512 bytes) to the MMC/SD-card */
+       for (b = 0; b < 512; b++)
+               spi_write(*Buffer++);
+
+       /* write the CRC-Byte */
+       spi_write(0xFF); /* write a dummy CRC */
+       spi_write(0xFF); /* CRC code is not used */
+
+       /* Wait for MMC/SD-card busy */
+       while (spi_read() != 0xff) {};
+
+       /* set MMC_Chip_Select to high (MMC/SD-card inactive) */
+       MMC_Disable();
+       spi_unlock();
+       return (0);
+}
+
+/* #########################################################################
+   Routine to read the CSD register from the MMC/SD-card (16 bytes)
+   ######################################################################### */
+unsigned char mmc_read_csd (unsigned char *Buffer)
+{
+       /* Command to read the CSD register */
+       unsigned char CMD[] = {0x49, 0x00, 0x00, 0x00, 0x00, 0xFF};
+
+       MMC_Read_Block(CMD, Buffer, 16);
+
+       return (0);
+}
diff --git a/board/lpc2292sodimm/mmc_hw.h b/board/lpc2292sodimm/mmc_hw.h
new file mode 100644 (file)
index 0000000..3687dbf
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+    This module implements a linux character device driver for the 24c256 chip.
+    Copyright (C) 2006  Embedded Artists AB (www.embeddedartists.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
+*/
+
+#ifndef _MMC_HW_
+#define _MMC_HW_
+
+unsigned char mmc_read_csd(unsigned char *Buffer);
+unsigned char mmc_read_sector (unsigned long addr,
+                              unsigned char *Buffer);
+unsigned char mmc_write_sector (unsigned long addr,unsigned char *Buffer);
+int mmc_hw_init(void);
+
+#endif /* _MMC_HW_ */
diff --git a/board/lpc2292sodimm/spi.c b/board/lpc2292sodimm/spi.c
new file mode 100644 (file)
index 0000000..4ba1468
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+    This module implements an interface to the SPI on the lpc22xx.
+    Copyright (C) 2006  Embedded Artists AB (www.embeddedartists.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 <config.h>
+#include <common.h>
+#include <asm/errno.h>
+#include <asm/arch/hardware.h>
+#include "spi.h"
+
+unsigned long spi_flags;
+unsigned char spi_idle = 0x00;
+
+int spi_init(void)
+{
+       unsigned long pinsel0_value;
+
+       /* activate spi pins */
+       pinsel0_value = GET32(PINSEL0);
+       pinsel0_value &= ~(0xFFl << 8);
+       pinsel0_value |= (0x55l << 8);
+       PUT32(PINSEL0, pinsel0_value);
+
+       return 0;
+}
diff --git a/board/lpc2292sodimm/spi.h b/board/lpc2292sodimm/spi.h
new file mode 100644 (file)
index 0000000..64f088c
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+    This file defines the interface to the lpc22xx SPI module.
+    Copyright (C) 2006  Embedded Artists AB (www.embeddedartists.com)
+
+    This file may be included in software not adhering to the GPL.
+
+    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
+*/
+
+#ifndef SPI_H
+#define SPI_H
+
+#include <config.h>
+#include <common.h>
+#include <asm/errno.h>
+#include <asm/arch/hardware.h>
+
+#define SPIF 0x80
+
+#define spi_lock() disable_interrupts();
+#define spi_unlock() enable_interrupts();
+
+extern unsigned long spi_flags;
+extern unsigned char spi_idle;
+
+int spi_init(void);
+
+static inline unsigned char spi_read(void)
+{
+       unsigned char b;
+
+       PUT8(S0SPDR, spi_idle);
+       while (!(GET8(S0SPSR) & SPIF));
+       b = GET8(S0SPDR);
+
+       return b;
+}
+
+static inline void spi_write(unsigned char b)
+{
+       PUT8(S0SPDR, b);
+       while (!(GET8(S0SPSR) & SPIF));
+       GET8(S0SPDR);           /* this will clear the SPIF bit */
+}
+
+static inline void spi_set_clock(unsigned char clk_value)
+{
+       PUT8(S0SPCCR, clk_value);
+}
+
+static inline void spi_set_cfg(unsigned char phase,
+                              unsigned char polarity,
+                              unsigned char lsbf)
+{
+       unsigned char v = 0x20; /* master bit set */
+
+       if (phase)
+               v |= 0x08;                      /* set phase bit */
+       if (polarity) {
+               v |= 0x10;                      /* set polarity bit */
+               spi_idle = 0xFF;
+       } else {
+               spi_idle = 0x00;
+       }
+       if (lsbf)
+               v |= 0x40;                      /* set lsbf bit */
+
+       PUT8(S0SPCR, v);
+}
+
+#endif
+
diff --git a/board/lpc2292sodimm/u-boot.lds b/board/lpc2292sodimm/u-boot.lds
new file mode 100644 (file)
index 0000000..64d946c
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * (C) Copyright 2000
+ * 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
+ */
+
+OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
+OUTPUT_ARCH(arm)
+ENTRY(_start)
+SECTIONS
+{
+       . = 0x00000000;
+
+       . = ALIGN(4);
+       .text      :
+       {
+         cpu/arm720t/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 = .;
+}
index a5b6de7605525783eebe3608170f8cfa255cc2f8..60c1aa90b6b97d6f133b62a3e7820df47ff8af03 100644 (file)
@@ -73,7 +73,7 @@ int cleanup_before_linux (void)
        /* go to high speed */
        IO_SYSCON3 = (IO_SYSCON3 & ~CLKCTL) | CLKCTL_73;
 #endif
-#elif defined(CONFIG_NETARM) || defined(CONFIG_S3C4510B)
+#elif defined(CONFIG_NETARM) || defined(CONFIG_S3C4510B) || defined(CONFIG_LPC2292)
        disable_interrupts ();
        /* Nothing more needed */
 #elif defined(CONFIG_INTEGRATOR) && defined(CONFIG_ARCH_INTEGRATOR)
@@ -252,6 +252,7 @@ int dcache_status (void)
        void icache_enable (void)
        {
        }
+#elif defined(CONFIG_LPC2292) /* just to satisfy the compiler */
 #else
 #error No icache/dcache enable/disable functions defined for this CPU type
 #endif
index da62502d6144e21ae375a935e4216bf06c211cc7..8f32124d373f548c427f79ecfb01779f8726a02c 100644 (file)
 #define TIMER_LOAD_VAL 0xffff
 /* macro to read the 16 bit timer */
 #define READ_TIMER (IO_TC1D & 0xffff)
+
+#ifdef CONFIG_LPC2292
+#undef READ_TIMER
+#define READ_TIMER (0xFFFFFFFF - GET32(T0TC))
+#endif
+
 #else
 #define IRQEN  (*(volatile unsigned int *)(NETARM_GEN_MODULE_BASE + NETARM_GEN_INTR_ENABLE))
 #define TM2CTRL (*(volatile unsigned int *)(NETARM_GEN_MODULE_BASE + NETARM_GEN_TIMER2_CONTROL))
@@ -195,6 +201,13 @@ void do_irq (struct pt_regs *pt_regs)
        }
 #elif defined(CONFIG_INTEGRATOR) && defined(CONFIG_ARCH_INTEGRATOR)
        /* No do_irq() for IntegratorAP/CM720T as yet */
+#elif defined(CONFIG_LPC2292)
+
+    void (*pfnct)(void);
+
+    pfnct = (void (*)(void))VICVectAddr;
+
+    (*pfnct)();
 #else
 #error do_irq() not defined for this CPU type
 #endif
@@ -293,6 +306,13 @@ int interrupt_init (void)
 
        /* Start timer */
        SET_REG( REG_TMOD, TM0_RUN);
+#elif defined(CONFIG_LPC2292)
+       PUT32(T0IR, 0);         /* disable all timer0 interrupts */
+       PUT32(T0TCR, 0);        /* disable timer0 */
+       PUT32(T0PR, CFG_SYS_CLK_FREQ / CFG_HZ);
+       PUT32(T0MCR, 0);
+       PUT32(T0TC, 0);
+       PUT32(T0TCR, 1);        /* enable timer0 */
 
 #else
 #error No interrupt_init() defined for this CPU type
@@ -309,7 +329,7 @@ int interrupt_init (void)
  */
 
 
-#if defined(CONFIG_IMPA7) || defined(CONFIG_EP7312) || defined(CONFIG_NETARM) || defined(CONFIG_ARMADILLO)
+#if defined(CONFIG_IMPA7) || defined(CONFIG_EP7312) || defined(CONFIG_NETARM) || defined(CONFIG_ARMADILLO) || defined(CONFIG_LPC2292)
 
 void reset_timer (void)
 {
@@ -337,7 +357,12 @@ void udelay (unsigned long usec)
        tmo += get_timer (0);
 
        while (get_timer_masked () < tmo)
+#ifdef CONFIG_LPC2292
+               /* GJ - not sure whether this is really needed or a misunderstanding */
+               __asm__ __volatile__(" nop");
+#else
                /*NOP*/;
+#endif
 }
 
 void reset_timer_masked (void)
index 054bab98112f194c62da23741887e0e1b9bfd502..15c54af08b789caa97fd2077aaadc325322c8c6f 100644 (file)
@@ -123,4 +123,80 @@ serial_puts (const char *s)
        }
 }
 
-#endif /* defined(CONFIG_IMPA7) || defined(CONFIG_EP7312) */
+#elif defined(CONFIG_LPC2292)
+
+#include <asm/arch/hardware.h>
+
+void serial_setbrg (void)
+{
+       DECLARE_GLOBAL_DATA_PTR;
+
+       unsigned short divisor = 0;
+
+       switch (gd->baudrate) {
+       case   1200:    divisor = 3072; break;
+       case   9600:    divisor =  384; break;
+       case  19200:    divisor =  192; break;
+       case  38400:    divisor =   96; break;
+       case  57600:    divisor =   64; break;
+       case 115200:    divisor =   32; break;
+       default:        hang ();        break;
+       }
+
+       /* init serial UART0 */
+       PUT8(U0LCR, 0);
+       PUT8(U0IER, 0);
+       PUT8(U0LCR, 0x80);      /* DLAB=1 */
+       PUT8(U0DLL, (unsigned char)(divisor & 0x00FF));
+       PUT8(U0DLM, (unsigned char)(divisor >> 8));
+       PUT8(U0LCR, 0x03);      /* 8N1, DLAB=0  */
+       PUT8(U0FCR, 1);         /* Enable RX and TX FIFOs */
+}
+
+int serial_init (void)
+{
+       unsigned long pinsel0;
+
+       serial_setbrg ();
+
+       pinsel0 = GET32(PINSEL0);
+       pinsel0 &= ~(0x00000003);
+       pinsel0 |= 5;
+       PUT32(PINSEL0, pinsel0);
+
+       return (0);
+}
+
+void serial_putc (const char c)
+{
+       if (c == '\n')
+       {
+               while((GET8(U0LSR) & (1<<5)) == 0); /* Wait for empty U0THR */
+               PUT8(U0THR, '\r');
+       }
+
+       while((GET8(U0LSR) & (1<<5)) == 0); /* Wait for empty U0THR */
+       PUT8(U0THR, c);
+}
+
+int serial_getc (void)
+{
+       while((GET8(U0LSR) & 1) == 0);
+       return GET8(U0RBR);
+}
+
+void
+serial_puts (const char *s)
+{
+       while (*s) {
+               serial_putc (*s++);
+       }
+}
+
+/* Test if there is a byte to read */
+int serial_tstc (void)
+{
+       return (GET8(U0LSR) & 1);
+}
+
+#endif
index e66d109443a18f4260dd4c219e09083442d1cc9a..96d5f54bace7883b0a1bba9839f6a9276e5f3429 100644 (file)
@@ -43,7 +43,11 @@ _start: b    reset
        ldr     pc, _software_interrupt
        ldr     pc, _prefetch_abort
        ldr     pc, _data_abort
+#ifdef CONFIG_LPC2292
+       .word   0xB4405F76 /* 2's complement of the checksum of the vectors */
+#else
        ldr     pc, _not_used
+#endif
        ldr     pc, _irq
        ldr     pc, _fiq
 
@@ -123,6 +127,10 @@ reset:
        bl      cpu_init_crit
 #endif
 
+#ifdef CONFIG_LPC2292
+       bl      lowlevel_init
+#endif
+
 #ifndef CONFIG_SKIP_RELOCATE_UBOOT
 relocate:                              /* relocate U-Boot to RAM           */
        adr     r0, _start              /* r0 <- current position of code   */
@@ -131,6 +139,7 @@ relocate:                           /* relocate U-Boot to RAM           */
        beq     stack_setup
 
 #if TEXT_BASE
+#ifndef CONFIG_LPC2292 /* already done in lowlevel_init */
        ldr     r2, =0x0                /* Relocate the exception vectors   */
        cmp     r1, r2                  /* and associated data to address   */
        ldmneia r0!, {r3-r10}           /* 0x0. Do nothing if TEXT_BASE is  */
@@ -138,6 +147,7 @@ relocate:                           /* relocate U-Boot to RAM           */
        ldmneia r0, {r3-r9}
        stmneia r2, {r3-r9}
        adrne   r0, _start              /* restore r0                       */
+#endif /* !CONFIG_LPC2292 */
 #endif
 
        ldr     r2, _armboot_start
@@ -206,6 +216,14 @@ SYSCON3:   .word   0x80002200
 #define CLKCTL_49      0x4  /* 49.152 MHz */
 #define CLKCTL_73      0x6  /* 73.728 MHz */
 
+#elif defined(CONFIG_LPC2292)
+PLLCFG_ADR:    .word   PLLCFG
+PLLFEED_ADR:   .word   PLLFEED
+PLLCON_ADR:    .word   PLLCON
+PLLSTAT_ADR:   .word   PLLSTAT
+VPBDIV_ADR:    .word   VPBDIV
+MEMMAP_ADR:    .word   MEMMAP
+
 #endif
 
 cpu_init_crit:
@@ -306,6 +324,50 @@ cpu_init_crit:
 
 #elif defined(CONFIG_INTEGRATOR) && defined(CONFIG_ARCH_INTEGRATOR)
        /* No specific initialisation for IntegratorAP/CM720T as yet */
+#elif defined(CONFIG_LPC2292)
+       /* Set-up PLL */
+       mov     r3, #0xAA
+       mov     r4, #0x55
+       /* First disconnect and disable the PLL */      
+       ldr     r0, PLLCON_ADR
+       mov     r1, #0x00
+       str     r1, [r0]
+       ldr     r0, PLLFEED_ADR /* start feed sequence */
+       str     r3, [r0]
+       str     r4, [r0]        /* feed sequence done */        
+       /* Set new M and P values */
+       ldr     r0, PLLCFG_ADR
+       mov     r1, #0x23       /* M=4 and P=2 */
+       str     r1, [r0]
+       ldr     r0, PLLFEED_ADR /* start feed sequence */
+       str     r3, [r0]
+       str     r4, [r0]        /* feed sequence done */
+       /* Then enable the PLL */
+       ldr     r0, PLLCON_ADR
+       mov     r1, #0x01       /* PLL enable bit */
+       str     r1, [r0]
+       ldr     r0, PLLFEED_ADR /* start feed sequence */
+       str     r3, [r0]
+       str     r4, [r0]        /* feed sequence done */
+       /* Wait for the lock */ 
+       ldr     r0, PLLSTAT_ADR
+       mov     r1, #0x400      /* lock bit */
+lock_loop:     
+       ldr     r2, [r0]
+       and     r2, r1, r2
+       cmp     r2, #0
+       beq     lock_loop
+       /* And finally connect the PLL */
+       ldr     r0, PLLCON_ADR
+       mov     r1, #0x03       /* PLL enable bit and connect bit */
+       str     r1, [r0]
+       ldr     r0, PLLFEED_ADR /* start feed sequence */
+       str     r3, [r0]
+       str     r4, [r0]        /* feed sequence done */                
+       /* Set-up VPBDIV register */
+       ldr     r0, VPBDIV_ADR
+       mov     r1, #0x01       /* VPB clock is same as process clock */
+       str     r1, [r0]
 #else
 #error No cpu_init_crit() defined for current CPU type
 #endif
@@ -321,6 +383,7 @@ cpu_init_crit:
        str     r1, [r0]
 #endif
 
+#ifndef CONFIG_LPC2292
        mov     ip, lr
        /*
         * before relocating, we have to setup RAM timing
@@ -329,6 +392,7 @@ cpu_init_crit:
         */
        bl      lowlevel_init
        mov     lr, ip
+#endif
 
        mov     pc, lr
 
@@ -537,6 +601,11 @@ reset_cpu:
  * on external peripherals such as watchdog timers, etc. */
 #elif defined(CONFIG_INTEGRATOR) && defined(CONFIG_ARCH_INTEGRATOR)
        /* No specific reset actions for IntegratorAP/CM720T as yet */
+#elif defined(CONFIG_LPC2292)
+       .align  5
+.globl reset_cpu
+reset_cpu:
+       mov     pc, r0
 #else
 #error No reset_cpu() defined for current CPU type
 #endif
index 3056ca7f673ad919f170e6083eb5026122853e25..1e9cd41169d437b830525d8e4e5a2ff14eb81823 100644 (file)
@@ -36,6 +36,8 @@
 /* include armadillo specific hardware file if there was one */
 #elif defined(CONFIG_INTEGRATOR) && defined(CONFIG_ARCH_INTEGRATOR)
 /* include IntegratorCP/CM720T specific hardware file if there was one */
+#elif defined(CONFIG_LPC2292)
+#include <asm-arm/arch-arm720t/lpc2292_registers.h>
 #else
 #error No hardware file defined for this configuration
 #endif
diff --git a/include/asm-arm/arch-arm720t/lpc2292_registers.h b/include/asm-arm/arch-arm720t/lpc2292_registers.h
new file mode 100644 (file)
index 0000000..5715f3e
--- /dev/null
@@ -0,0 +1,225 @@
+#ifndef __LPC2292_REGISTERS_H
+#define __LPC2292_REGISTERS_H
+
+#include <config.h>
+
+/* Macros for reading/writing registers */
+#define PUT8(reg, value) (*(volatile unsigned char*)(reg) = (value))
+#define PUT16(reg, value) (*(volatile unsigned short*)(reg) = (value))
+#define PUT32(reg, value) (*(volatile unsigned int*)(reg) = (value))
+#define GET8(reg) (*(volatile unsigned char*)(reg))
+#define GET16(reg) (*(volatile unsigned short*)(reg))
+#define GET32(reg) (*(volatile unsigned int*)(reg))
+
+/* External Memory Controller */
+
+#define BCFG0 0xFFE00000       /* 32-bits */
+#define BCFG1 0xFFE00004       /* 32-bits */
+#define BCFG2 0xFFE00008       /* 32-bits */
+#define BCFG3 0xFFE0000c       /* 32-bits */
+
+/* System Control Block */
+
+#define EXTINT   0xE01FC140
+#define EXTWAKE  0xE01FC144
+#define EXTMODE  0xE01FC148
+#define EXTPOLAR 0xE01FC14C
+#define MEMMAP   0xE01FC040
+#define PLLCON   0xE01FC080
+#define PLLCFG   0xE01FC084
+#define PLLSTAT  0xE01FC088
+#define PLLFEED  0xE01FC08C
+#define PCON     0xE01FC0C0
+#define PCONP    0xE01FC0C4
+#define VPBDIV   0xE01FC100
+
+/* Memory Acceleration Module */
+
+#define MAMCR  0xE01FC000
+#define MAMTIM 0xE01FC004
+
+/* Vectored Interrupt Controller */
+
+#define VICIRQStatus    0xFFFFF000
+#define VICFIQStatus    0xFFFFF004
+#define VICRawIntr      0xFFFFF008
+#define VICIntSelect    0xFFFFF00C
+#define VICIntEnable    0xFFFFF010
+#define VICIntEnClr     0xFFFFF014
+#define VICSoftInt      0xFFFFF018
+#define VICSoftIntClear 0xFFFFF01C
+#define VICProtection   0xFFFFF020
+#define VICVectAddr     0xFFFFF030
+#define VICDefVectAddr  0xFFFFF034
+#define VICVectAddr0    0xFFFFF100
+#define VICVectAddr1    0xFFFFF104
+#define VICVectAddr2    0xFFFFF108
+#define VICVectAddr3    0xFFFFF10C
+#define VICVectAddr4    0xFFFFF110
+#define VICVectAddr5    0xFFFFF114
+#define VICVectAddr6    0xFFFFF118
+#define VICVectAddr7    0xFFFFF11C
+#define VICVectAddr8    0xFFFFF120
+#define VICVectAddr9    0xFFFFF124
+#define VICVectAddr10   0xFFFFF128
+#define VICVectAddr11   0xFFFFF12C
+#define VICVectAddr12   0xFFFFF130
+#define VICVectAddr13   0xFFFFF134
+#define VICVectAddr14   0xFFFFF138
+#define VICVectAddr15   0xFFFFF13C
+#define VICVectCntl0    0xFFFFF200
+#define VICVectCntl1   0xFFFFF204
+#define VICVectCntl2   0xFFFFF208
+#define VICVectCntl3   0xFFFFF20C
+#define VICVectCntl4   0xFFFFF210
+#define VICVectCntl5   0xFFFFF214
+#define VICVectCntl6   0xFFFFF218
+#define VICVectCntl7   0xFFFFF21C
+#define VICVectCntl8   0xFFFFF220
+#define VICVectCntl9   0xFFFFF224
+#define VICVectCntl10  0xFFFFF228
+#define VICVectCntl11  0xFFFFF22C
+#define VICVectCntl12  0xFFFFF230
+#define VICVectCntl13  0xFFFFF234
+#define VICVectCntl14  0xFFFFF238
+#define VICVectCntl15  0xFFFFF23C
+
+/* Pin connect block */
+
+#define PINSEL0 0xE002C000     /* 32 bits */
+#define PINSEL1 0xE002C004     /* 32 bits */
+#define PINSEL2 0xE002C014     /* 32 bits */
+
+/* GPIO */
+
+#define IO0PIN 0xE0028000
+#define IO0SET 0xE0028004
+#define IO0DIR 0xE0028008
+#define IO0CLR 0xE002800C
+#define IO1PIN 0xE0028010
+#define IO1SET 0xE0028014
+#define IO1DIR 0xE0028018
+#define IO1CLR 0xE002801C
+#define IO2PIN 0xE0028020
+#define IO2SET 0xE0028024
+#define IO2DIR 0xE0028028
+#define IO2CLR 0xE002802C
+#define IO3PIN 0xE0028030
+#define IO3SET 0xE0028034
+#define IO3DIR 0xE0028038
+#define IO3CLR 0xE002803C
+
+/* Uarts */
+
+#define U0RBR 0xE000C000
+#define U0THR 0xE000C000
+#define U0IER 0xE000C004
+#define U0IIR 0xE000C008
+#define U0FCR 0xE000C008
+#define U0LCR 0xE000C00C
+#define U0LSR 0xE000C014
+#define U0SCR 0xE000C01C
+#define U0DLL 0xE000C000
+#define U0DLM 0xE000C004
+
+#define U1RBR 0xE0010000
+#define U1THR 0xE0010000
+#define U1IER 0xE0010004
+#define U1IIR 0xE0010008
+#define U1FCR 0xE0010008
+#define U1LCR 0xE001000C
+#define U1MCR 0xE0010010
+#define U1LSR 0xE0010014
+#define U1MSR 0xE0010018
+#define U1SCR 0xE001001C
+#define U1DLL 0xE0010000
+#define U1DLM 0xE0010004
+
+/* I2C */
+
+#define I2CONSET 0xE001C000
+#define I2STAT   0xE001C004
+#define I2DAT    0xE001C008
+#define I2ADR    0xE001C00C
+#define I2SCLH   0xE001C010
+#define I2SCLL   0xE001C014
+#define I2CONCLR 0xE001C018
+
+/* SPI */
+
+#define S0SPCR  0xE0020000
+#define S0SPSR  0xE0020004
+#define S0SPDR  0xE0020008
+#define S0SPCCR 0xE002000C
+#define S0SPINT 0xE002001C
+
+#define S1SPCR  0xE0030000
+#define S1SPSR  0xE0030004
+#define S1SPDR  0xE0030008
+#define S1SPCCR 0xE003000C
+#define S1SPINT 0xE003001C
+
+/* CAN controller */
+
+/* skip for now */
+
+/* Timers */
+
+#define T0IR  0xE0004000
+#define T0TCR 0xE0004004
+#define T0TC  0xE0004008
+#define T0PR  0xE000400C
+#define T0PC  0xE0004010
+#define T0MCR 0xE0004014
+#define T0MR0 0xE0004018
+#define T0MR1 0xE000401C
+#define T0MR2 0xE0004020
+#define T0MR3 0xE0004024
+#define T0CCR 0xE0004028
+#define T0CR0 0xE000402C
+#define T0CR1 0xE0004030
+#define T0CR2 0xE0004034
+#define T0CR3 0xE0004038
+#define T0EMR 0xE000403C
+
+#define T1IR  0xE0008000
+#define T1TCR 0xE0008004
+#define T1TC  0xE0008008
+#define T1PR  0xE000800C
+#define T1PC  0xE0008010
+#define T1MCR 0xE0008014
+#define T1MR0 0xE0008018
+#define T1MR1 0xE000801C
+#define T1MR2 0xE0008020
+#define T1MR3 0xE0008024
+#define T1CCR 0xE0008028
+#define T1CR0 0xE000802C
+#define T1CR1 0xE0008030
+#define T1CR2 0xE0008034
+#define T1CR3 0xE0008038
+#define T1EMR 0xE000803C
+
+/* PWM */
+
+/* skip for now */
+
+/* A/D converter */
+
+/* skip for now */
+
+/* Real Time Clock */
+
+/* skip for now */
+
+/* Watchdog */
+
+#define WDMOD  0xE0000000
+#define WDTC   0xE0000004
+#define WDFEED 0xE0000008
+#define WDTV   0xE000000C
+
+/* EmbeddedICE LOGIC */
+
+/* skip for now */
+
+#endif
diff --git a/include/asm-arm/arch-arm720t/mmc.h b/include/asm-arm/arch-arm720t/mmc.h
new file mode 100644 (file)
index 0000000..e664a5f
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ * A dummy header file for use with the LPC2292 port to keep the
+ * compiler happy.
+ *
+ * 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
+ */
+#ifndef _MMC_ARM_TDM_H_
+#define _MMC_ARM_TDM_H_
+#endif /* _MMC_ARM_TDM_H_ */
diff --git a/include/configs/lpc2292sodimm.h b/include/configs/lpc2292sodimm.h
new file mode 100644 (file)
index 0000000..7e51523
--- /dev/null
@@ -0,0 +1,158 @@
+/*
+ * (C) Copyright 2000
+ * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Marius Groeger <mgroeger@sysgo.de>
+ *
+ * Configuation settings for the EP7312 board.
+ *
+ * Modified to work on Armadillo HT1070 ARM720T board
+ * (C) Copyright 2005 Rowel Atienza rowel@diwalabs.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
+ */
+
+#ifndef __CONFIG_H
+#define __CONFIG_H
+
+/*
+ * If we are developing, we might want to start armboot from ram
+ * so we MUST NOT initialize critical regs like mem-timing ...
+ */
+#undef CONFIG_INIT_CRITICAL            /* undef for developing */
+
+#undef CONFIG_SKIP_LOWLEVEL_INIT
+#undef CONFIG_SKIP_RELOCATE_UBOOT
+
+/*
+ * High Level Configuration Options
+ * (easy to change)
+ */
+#define CONFIG_ARM7            1       /* This is a ARM7 CPU   */
+#define CONFIG_ARM_THUMB       1       /* this is an ARM720TDMI */
+#define CONFIG_LPC2292
+#undef  CONFIG_ARM7_REVD               /* disable ARM720 REV.D Workarounds */
+
+#undef CONFIG_USE_IRQ                  /* don't need them anymore */
+
+/*
+ * Size of malloc() pool
+ */
+#define CFG_MALLOC_LEN         (CFG_ENV_SIZE + 128*1024)
+#define CFG_GBL_DATA_SIZE      128     /* size in bytes reserved for initial data */
+
+/*
+ * Hardware drivers
+ */
+
+/*
+ * select serial console configuration
+ */
+#define CONFIG_SERIAL1         1       /* we use Serial line 1 */
+
+/* allow to overwrite serial and ethaddr */
+#define CONFIG_ENV_OVERWRITE
+
+#define CONFIG_BAUDRATE                115200
+
+#define CONFIG_BOOTP_MASK       (CONFIG_BOOTP_DEFAULT|CONFIG_BOOTP_BOOTFILESIZE)
+
+/*
+ * Supported commands
+ */
+#define CONFIG_COMMANDS               (CONFIG_CMD_DFL  | \
+                               CFG_CMD_DHCP    | \
+                               CFG_CMD_FAT     | \
+                               CFG_CMD_MMC     | \
+                               CFG_CMD_NET     | \
+                               CFG_CMD_PING)
+
+#define CONFIG_MAC_PARTITION
+#define CONFIG_DOS_PARTITION
+
+/* this must be included AFTER the definition of CONFIG_COMMANDS (if any) */
+#include <cmd_confdefs.h>
+
+#define CONFIG_BOOTDELAY       5
+
+/*
+ * Miscellaneous configurable options
+ */
+#define        CFG_LONGHELP                            /* undef to save memory         */
+#define        CFG_PROMPT              "LPC2292SODIMM # " /* Monitor Command Prompt    */
+#define        CFG_CBSIZE              256             /* Console I/O Buffer Size      */
+#define        CFG_PBSIZE (CFG_CBSIZE+sizeof(CFG_PROMPT)+16) /* Print Buffer Size */
+#define        CFG_MAXARGS             16              /* max number of command args   */
+#define CFG_BARGSIZE           CFG_CBSIZE      /* Boot Argument Buffer Size    */
+
+#define CFG_MEMTEST_START      0x40000000      /* memtest works on     */
+#define CFG_MEMTEST_END                0x40000000      /* 4 ... 8 MB in DRAM   */
+
+#undef  CFG_CLKS_IN_HZ         /* everything, incl board info, in Hz */
+
+#define        CFG_LOAD_ADDR           0x00040000      /* default load address for armadillo: kernel img is here*/
+
+#define CFG_SYS_CLK_FREQ        58982400        /* Hz */
+#define        CFG_HZ                  2048            /* decrementer freq in Hz */
+
+                                               /* valid baudrates */
+#define CFG_BAUDRATE_TABLE     { 9600, 19200, 38400, 57600, 115200 }
+
+/*-----------------------------------------------------------------------
+ * Stack sizes
+ *
+ * The stack sizes are set up in start.S using the settings below
+ */
+#define CONFIG_STACKSIZE       (128*1024)      /* regular stack */
+#ifdef CONFIG_USE_IRQ
+#define CONFIG_STACKSIZE_IRQ   (4*1024)        /* IRQ stack */
+#define CONFIG_STACKSIZE_FIQ   (4*1024)        /* FIQ stack */
+#endif
+
+/*-----------------------------------------------------------------------
+ * Physical Memory Map
+ */
+#define CONFIG_NR_DRAM_BANKS   1          /* we have 1 bank of DRAM */
+#define PHYS_SDRAM_1           0x81000000 /* SDRAM Bank #1 */
+#define PHYS_SDRAM_1_SIZE      0x00800000 /* 8 MB SDRAM */
+
+#define PHYS_FLASH_1           0x80000000 /* Flash Bank #1 */
+#define PHYS_FLASH_SIZE                0x00200000 /* 2 MB */
+
+#define CFG_FLASH_BASE         PHYS_FLASH_1
+
+/*-----------------------------------------------------------------------
+ * FLASH and environment organization
+ */
+#define CFG_MAX_FLASH_BANKS    2       /* max number of memory banks           */
+#define CFG_MAX_FLASH_SECT     1024    /* max number of sectors on one chip    */
+
+/* timeout values are in ticks */
+#define CFG_FLASH_ERASE_TOUT   (2*CFG_HZ) /* Timeout for Flash Erase */
+#define CFG_FLASH_WRITE_TOUT   (2*CFG_HZ) /* Timeout for Flash Write */
+
+#define        CFG_ENV_IS_IN_FLASH     1
+#define CFG_ENV_ADDR           (0x0 + 0x3C000) /* Addr of Environment Sector   */
+#define CFG_ENV_SIZE           0x2000 /* Total Size of Environment Sector      */
+
+#define CONFIG_CMDLINE_TAG
+#define CONFIG_SETUP_MEMORY_TAGS
+#define CONFIG_INITRD_TAG
+#define CONFIG_MMC 1
+
+#endif /* __CONFIG_H */
index 8b7e824cca08d495379b7b528a15738ee3e9e7ec..55b6d8f3885c1871e5583cfad7193a7d5c5abd33 100644 (file)
@@ -304,6 +304,7 @@ extern void flash_read_factory_serial(flash_info_t * info, void * buffer, int of
 
 #define TOSH_ID_FVT160 0xC2            /* TC58FVT160 ID (16 M, top )           */
 #define TOSH_ID_FVB160 0x43            /* TC58FVT160 ID (16 M, bottom )        */
+#define PHILIPS_LPC2292 0x0401FF13  /* LPC2292 internal FLASH                  */
 
 /*-----------------------------------------------------------------------
  * Internal FLASH identification codes