* Patch by Scott McNutt, 21 Oct 2004:
authorwdenk <wdenk>
Wed, 30 Mar 2005 23:28:18 +0000 (23:28 +0000)
committerwdenk <wdenk>
Wed, 30 Mar 2005 23:28:18 +0000 (23:28 +0000)
  Add support for Nios-II EPCS Controller core.

* Patch by Scott McNutt, 20 Oct 2004:
  Nios-II cleanups:
  - Add sysid command (Nios-II only).
  - Locate default exception trampoline at proper offset.
  - Implement I/O routines (readb, writeb, etc)
  - Implement do_bootm_linux

CHANGELOG
cpu/nios2/Makefile
cpu/nios2/cpu.c
cpu/nios2/epcs.c [new file with mode: 0644]
cpu/nios2/start.S
cpu/nios2/sysid.c [new file with mode: 0644]
include/asm-nios2/io.h
include/configs/PK1C20.h
include/nios2-epcs.h [new file with mode: 0644]
include/nios2-io.h
lib_nios2/nios_linux.c

index 2c2f0841aee44270f1c74ba5e1643301daf42283..93caa794cecfee3fed44d02b89365b66508ce11a 100644 (file)
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -2,6 +2,16 @@
 Changes for U-Boot 1.1.3:
 ======================================================================
 
+* Patch by Scott McNutt, 21 Oct 2004:
+  Add support for Nios-II EPCS Controller core.
+
+* Patch by Scott McNutt, 20 Oct 2004:
+  Nios-II cleanups:
+  - Add sysid command (Nios-II only).
+  - Locate default exception trampoline at proper offset.
+  - Implement I/O routines (readb, writeb, etc)
+  - Implement do_bootm_linux
+
 * Patches by Martin Krause, 22 Mar 2005:
   - use TQM5200_auto as MAKEALL target for TQM5200 systems
   - add support for SM501 graphics controller
index 76b324a7afec36ec2c861d7969e80f0d1af13e26..11fda50c0c46a0e8e15d0e26cb8bda3b401044d0 100644 (file)
@@ -27,7 +27,7 @@ LIB   = lib$(CPU).a
 
 START  = start.o
 AOBJS  = exceptions.o
-OBJS   = cpu.o interrupts.o serial.o traps.o
+OBJS   = cpu.o interrupts.o serial.o sysid.o traps.o epcs.o
 
 all:   .depend $(START) $(LIB)
 
index c9db1276146f15cea38852c8d2506e255795dfd0..f4217a88cf16652ed687e707f78c920170def312 100644 (file)
 #include <nios2-io.h>
 
 #if defined (CFG_NIOS_SYSID_BASE)
-#include <linux/time.h>
-static void check_sysid (void)
-{
-       struct nios_sysid_t *sysid =
-               (struct nios_sysid_t *)CACHE_BYPASS(CFG_NIOS_SYSID_BASE);
-       struct tm t;
-       char asc[32];
-
-       localtime_r ((time_t *)&sysid->timestamp, &t);
-       asctime_r (&t, asc);
-       printf ("SYSID : %08x, %s", sysid->id, asc);
-
-}
+extern void display_sysid (void);
 #endif /* CFG_NIOS_SYSID_BASE */
 
 int checkcpu (void)
@@ -47,7 +35,7 @@ int checkcpu (void)
 #if !defined(CFG_NIOS_SYSID_BASE)
        printf ("SYSID : <unknown>\n");
 #else
-       check_sysid ();
+       display_sysid ();
 #endif
        return (0);
 }
diff --git a/cpu/nios2/epcs.c b/cpu/nios2/epcs.c
new file mode 100644 (file)
index 0000000..a8851e9
--- /dev/null
@@ -0,0 +1,711 @@
+/*
+ * (C) Copyright 2004, Psyent Corporation <www.psyent.com>
+ * Scott McNutt <smcnutt@psyent.com>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+
+#if defined(CFG_NIOS_EPCSBASE)
+#include <command.h>
+#include <nios2.h>
+#include <nios2-io.h>
+#include <nios2-epcs.h>
+
+
+/*-----------------------------------------------------------------------*/
+#define SHORT_HELP\
+       "epcs    - read/write Cyclone EPCS configuration device.\n"
+
+#define LONG_HELP\
+       "\n"\
+       "epcs erase start [end]\n"\
+       "    - erase sector start or sectors start through end.\n"\
+       "epcs info\n"\
+       "    - display EPCS device information.\n"\
+       "epcs protect on | off\n"\
+       "    - turn device protection on or off.\n"\
+       "epcs read addr offset count\n"\
+       "    - read count bytes from offset to addr.\n"\
+       "epcs write addr offset count\n"\
+       "    - write count bytes to offset from addr.\n"\
+       "epcs verify addr offset count\n"\
+       "    - verify count bytes at offset from addr.\n"
+
+
+/*-----------------------------------------------------------------------*/
+/* Operation codes for serial configuration devices
+ */
+#define EPCS_WRITE_ENA         0x06    /* Write enable */
+#define EPCS_WRITE_DIS         0x04    /* Write disable */
+#define EPCS_READ_STAT         0x05    /* Read status */
+#define EPCS_READ_BYTES                0x03    /* Read bytes */
+#define EPCS_READ_ID           0xab    /* Read silicon id */
+#define EPCS_WRITE_STAT                0x01    /* Write status */
+#define EPCS_WRITE_BYTES       0x02    /* Write bytes */
+#define EPCS_ERASE_BULK                0xc7    /* Erase entire device */
+#define EPCS_ERASE_SECT                0xd8    /* Erase sector */
+
+/* Device status register bits
+ */
+#define EPCS_STATUS_WIP                (1<<0)  /* Write in progress */
+#define EPCS_STATUS_WEL                (1<<1)  /* Write enable latch */
+
+/* Misc
+ */
+#define EPCS_TIMEOUT           100     /* 100 msec timeout */
+
+static nios_spi_t *epcs =
+       (nios_spi_t *)CACHE_BYPASS(CFG_NIOS_EPCSBASE);
+
+/***********************************************************************
+ * Device access
+ ***********************************************************************/
+static int epcs_cs (int assert)
+{
+       ulong start;
+
+       if (assert) {
+               epcs->control |= NIOS_SPI_SSO;
+       } else {
+               /* Let all bits shift out */
+               start = get_timer (0);
+               while ((epcs->status & NIOS_SPI_TMT) == 0)
+                       if (get_timer (start) > EPCS_TIMEOUT)
+                               return (-1);
+               epcs->control &= ~NIOS_SPI_SSO;
+       }
+       return (0);
+}
+
+static int epcs_tx (unsigned char c)
+{
+       ulong start;
+
+       start = get_timer (0);
+       while ((epcs->status & NIOS_SPI_TRDY) == 0)
+               if (get_timer (start) > EPCS_TIMEOUT)
+                       return (-1);
+       epcs->txdata = c;
+       return (0);
+}
+
+static int epcs_rx (void)
+{
+       ulong start;
+
+       start = get_timer (0);
+       while ((epcs->status & NIOS_SPI_RRDY) == 0)
+               if (get_timer (start) > EPCS_TIMEOUT)
+                       return (-1);
+       return (epcs->rxdata);
+}
+
+static unsigned char bitrev[] = {
+       0x00, 0x08, 0x04, 0x0c, 0x02, 0x0a, 0x06, 0x0e,
+       0x01, 0x09, 0x05, 0x0d, 0x03, 0x0b, 0x07, 0x0f
+};
+
+static unsigned char epcs_bitrev (unsigned char c)
+{
+       unsigned char val;
+
+       val  = bitrev[c>>4];
+       val |= bitrev[c & 0x0f]<<4;
+       return (val);
+}
+
+static void epcs_rcv (unsigned char *dst, int len)
+{
+       while (len--) {
+               epcs_tx (0);
+               *dst++ = epcs_rx ();
+       }
+}
+
+static void epcs_rrcv (unsigned char *dst, int len)
+{
+       while (len--) {
+               epcs_tx (0);
+               *dst++ = epcs_bitrev (epcs_rx ());
+       }
+}
+
+static void epcs_snd (unsigned char *src, int len)
+{
+       while (len--) {
+               epcs_tx (*src++);
+               epcs_rx ();
+       }
+}
+
+static void epcs_rsnd (unsigned char *src, int len)
+{
+       while (len--) {
+               epcs_tx (epcs_bitrev (*src++));
+               epcs_rx ();
+       }
+}
+
+static void epcs_wr_enable (void)
+{
+       epcs_cs (1);
+       epcs_tx (EPCS_WRITE_ENA);
+       epcs_rx ();
+       epcs_cs (0);
+}
+
+static unsigned char epcs_status_rd (void)
+{
+       unsigned char status;
+
+       epcs_cs (1);
+       epcs_tx (EPCS_READ_STAT);
+       epcs_rx ();
+       epcs_tx (0);
+       status = epcs_rx ();
+       epcs_cs (0);
+       return (status);
+}
+
+static void epcs_status_wr (unsigned char status)
+{
+       epcs_wr_enable ();
+       epcs_cs (1);
+       epcs_tx (EPCS_WRITE_STAT);
+       epcs_rx ();
+       epcs_tx (status);
+       epcs_rx ();
+       epcs_cs (0);
+       return;
+}
+
+/***********************************************************************
+ * Device information
+ ***********************************************************************/
+
+static struct epcs_devinfo_t devinfo[] = {
+       { "EPCS1 ", 0x10, 17, 4, 15, 8, 0x0c },
+       { "EPCS4 ", 0x12, 19, 8, 16, 8, 0x1c },
+       { 0, 0, 0, 0, 0, 0 }
+};
+
+epcs_devinfo_t *epcs_dev_find (void)
+{
+       unsigned char buf[4];
+       unsigned char id;
+       int i;
+       struct epcs_devinfo_t *dev = NULL;
+
+       /* Read silicon id requires 3 "dummy bytes" before it's put
+        * on the wire.
+        */
+       buf[0] = EPCS_READ_ID;
+       buf[1] = 0;
+       buf[2] = 0;
+       buf[3] = 0;
+
+       epcs_cs (1);
+       epcs_snd (buf,4);
+       epcs_rcv (buf,1);
+       if (epcs_cs (0) == -1)
+               return (NULL);
+       id = buf[0];
+
+       /* Find the info struct */
+       i = 0;
+       while (devinfo[i].name) {
+               if (id == devinfo[i].id) {
+                       dev = &devinfo[i];
+                       break;
+               }
+               i++;
+       }
+
+       return (dev);
+}
+
+/***********************************************************************
+ * Misc Utilities
+ ***********************************************************************/
+int epcs_cfgsz (void)
+{
+       int sz = 0;
+       unsigned char buf[128];
+       unsigned char *p;
+       struct epcs_devinfo_t *dev = epcs_dev_find ();
+
+       if (!dev)
+               return (-1);
+
+       /* Read in the first 128 bytes of the device */
+       buf[0] = EPCS_READ_BYTES;
+       buf[1] = 0;
+       buf[2] = 0;
+       buf[3] = 0;
+
+       epcs_cs (1);
+       epcs_snd (buf,4);
+       epcs_rrcv (buf, sizeof(buf));
+       epcs_cs (0);
+
+       /* Search for the starting 0x6a which is followed by the
+        * 4-byte 'register' and 4-byte bit-count.
+        */
+       p = buf;
+       while (p < buf + sizeof(buf)-8) {
+               if ( *p == 0x6a ) {
+                       /* Point to bit count and extract */
+                       p += 5;
+                       sz = *p++;
+                       sz |= *p++ << 8;
+                       sz |= *p++ << 16;
+                       sz |= *p++ << 24;
+                       /* Convert to byte count */
+                       sz += 7;
+                       sz >>= 3;
+               } else if (*p == 0xff) {
+                       /* 0xff is ok ... just skip */
+                       p++;
+                       continue;
+               } else {
+                       /* Not 0xff or 0x6a ... something's not
+                        * right ... report 'unknown' (sz=0).
+                        */
+                       break;
+               }
+       }
+       return (sz);
+}
+
+int epcs_erase (unsigned start, unsigned end)
+{
+       unsigned off, sectsz;
+       unsigned char buf[4];
+       struct epcs_devinfo_t *dev = epcs_dev_find ();
+
+       if (!dev || (start>end))
+               return (-1);
+
+       /* Erase the requested sectors. An address is required
+        * that lies within the requested sector -- we'll just
+        * use the first address in the sector.
+        */
+       printf ("epcs erasing sector %d ", start);
+       if (start != end)
+               printf ("to %d ", end);
+       sectsz = (1 << dev->sz_sect);
+       while (start <= end) {
+               off = start * sectsz;
+               start++;
+
+               buf[0] = EPCS_ERASE_SECT;
+               buf[1] = off >> 16;
+               buf[2] = off >> 8;
+               buf[3] = off;
+
+               epcs_wr_enable ();
+               epcs_cs (1);
+               epcs_snd (buf,4);
+               epcs_cs (0);
+
+               printf ("."); /* Some user feedback */
+
+               /* Wait for erase to complete */
+               while (epcs_status_rd() & EPCS_STATUS_WIP)
+                       ;
+       }
+       printf (" done.\n");
+       return (0);
+}
+
+int epcs_read (ulong addr, ulong off, ulong cnt)
+{
+       unsigned char buf[4];
+       struct epcs_devinfo_t *dev = epcs_dev_find ();
+
+       if (!dev)
+               return (-1);
+
+       buf[0] = EPCS_READ_BYTES;
+       buf[1] = off >> 16;
+       buf[2] = off >> 8;
+       buf[3] = off;
+
+       epcs_cs (1);
+       epcs_snd (buf,4);
+       epcs_rrcv ((unsigned char *)addr, cnt);
+       epcs_cs (0);
+
+       return (0);
+}
+
+int epcs_write (ulong addr, ulong off, ulong cnt)
+{
+       ulong wrcnt;
+       unsigned pgsz;
+       unsigned char buf[4];
+       struct epcs_devinfo_t *dev = epcs_dev_find ();
+
+       if (!dev)
+               return (-1);
+
+       pgsz = (1<<dev->sz_page);
+       while (cnt) {
+               if (off % pgsz)
+                       wrcnt = pgsz - (off % pgsz);
+               else
+                       wrcnt = pgsz;
+               wrcnt = (wrcnt > cnt) ? cnt : wrcnt;
+
+               buf[0] = EPCS_WRITE_BYTES;
+               buf[1] = off >> 16;
+               buf[2] = off >> 8;
+               buf[3] = off;
+
+               epcs_wr_enable ();
+               epcs_cs (1);
+               epcs_snd (buf,4);
+               epcs_rsnd ((unsigned char *)addr, wrcnt);
+               epcs_cs (0);
+
+               /* Wait for write to complete */
+               while (epcs_status_rd() & EPCS_STATUS_WIP)
+                       ;
+
+               cnt -= wrcnt;
+               off += wrcnt;
+               addr += wrcnt;
+       }
+
+       return (0);
+}
+
+int epcs_verify (ulong addr, ulong off, ulong cnt, ulong *err)
+{
+       ulong rdcnt;
+       unsigned char buf[256];
+       unsigned char *start,*end;
+       int i;
+
+       start = end = (unsigned char *)addr;
+       while (cnt) {
+               rdcnt = (cnt>sizeof(buf)) ? sizeof(buf) : cnt;
+               epcs_read ((ulong)buf, off, rdcnt);
+               for (i=0; i<rdcnt; i++) {
+                       if (*end != buf[i]) {
+                               *err = end - start;
+                               return(-1);
+                       }
+                       end++;
+               }
+               cnt -= rdcnt;
+               off += rdcnt;
+       }
+       return (0);
+}
+
+static int epcs_sect_erased (int sect, unsigned *offset,
+               struct epcs_devinfo_t *dev)
+{
+       unsigned char buf[128];
+       unsigned off, end;
+       unsigned sectsz;
+       int i;
+
+       sectsz = (1 << dev->sz_sect);
+       off = sectsz * sect;
+       end = off + sectsz;
+
+       while (off < end) {
+               epcs_read ((ulong)buf, off, sizeof(buf));
+               for (i=0; i < sizeof(buf); i++) {
+                       if (buf[i] != 0xff) {
+                               *offset = off + i;
+                               return (0);
+                       }
+               }
+               off += sizeof(buf);
+       }
+       return (1);
+}
+
+
+/***********************************************************************
+ * Commands
+ ***********************************************************************/
+static
+void do_epcs_info (struct epcs_devinfo_t *dev, int argc, char *argv[])
+{
+       int i;
+       unsigned char stat;
+       unsigned tmp;
+       int erased;
+
+       /* Basic device info */
+       printf ("%s: %d kbytes (%d sectors x %d kbytes,"
+               " %d bytes/page)\n",
+               dev->name, 1 << (dev->size-10),
+               dev->num_sects, 1 << (dev->sz_sect-10),
+               1 << dev->sz_page );
+
+       /* Status -- for now protection is all-or-nothing */
+       stat = epcs_status_rd();
+       printf ("status: 0x%02x (WIP:%d, WEL:%d, PROT:%s)\n",
+               stat,
+               (stat & EPCS_STATUS_WIP) ? 1 : 0,
+               (stat & EPCS_STATUS_WEL) ? 1 : 0,
+               (stat & dev->prot_mask) ? "on" : "off" );
+
+       /* Configuration  */
+       tmp = epcs_cfgsz ();
+       if (tmp) {
+               printf ("config: 0x%06x (%d) bytes\n", tmp, tmp );
+       } else {
+               printf ("config: unknown\n" );
+       }
+
+       /* Sector info */
+       for (i=0; i<dev->num_sects; i++) {
+               erased = epcs_sect_erased (i, &tmp, dev);
+               printf ("     %d: %06x ",
+                       i, i*(1<<dev->sz_sect) );
+               if (erased)
+                       printf ("erased\n");
+               else
+                       printf ("data @ 0x%06x\n", tmp);
+       }
+
+       return;
+}
+
+static
+void do_epcs_erase (struct epcs_devinfo_t *dev, int argc, char *argv[])
+{
+       unsigned start,end;
+
+       if ((argc < 3) || (argc > 4)) {
+               printf ("USAGE: epcs erase sect [end]\n");
+               return;
+       }
+       if ((epcs_status_rd() & dev->prot_mask) != 0) {
+               printf ( "epcs: device protected.\n");
+               return;
+       }
+
+       start = simple_strtoul (argv[2], NULL, 10);
+       if (argc > 3)
+               end = simple_strtoul (argv[3], NULL, 10);
+       else
+               end = start;
+       if ((start >= dev->num_sects) || (start > end)) {
+               printf ("epcs: invalid sector range: [%d:%d]\n",
+                       start, end );
+               return;
+       }
+
+       epcs_erase (start, end);
+
+       return;
+}
+
+static
+void do_epcs_protect (struct epcs_devinfo_t *dev, int argc, char *argv[])
+{
+       unsigned char stat;
+
+       /* For now protection is all-or-nothing to keep things
+        * simple. The protection bits don't map in a linear
+        * fashion ... and we would rather protect the bottom
+        * of the device since it contains the config data and
+        * leave the top unprotected for app use. But unfortunately
+        * protection works from top-to-bottom so it does
+        * really help very much from a software app point-of-view.
+        */
+       if (argc < 3) {
+               printf ("USAGE: epcs protect on | off\n");
+               return;
+       }
+       if (!dev)
+               return;
+
+       /* Protection on/off is just a matter of setting/clearing
+        * all protection bits in the status register.
+        */
+       stat = epcs_status_rd ();
+       if (strcmp ("on", argv[2]) == 0) {
+               stat |= dev->prot_mask;
+       } else if (strcmp ("off", argv[2]) == 0 ) {
+               stat &= ~dev->prot_mask;
+       } else {
+               printf ("epcs: unknown protection: %s\n", argv[2]);
+               return;
+       }
+       epcs_status_wr (stat);
+       return;
+}
+
+static
+void do_epcs_read (struct epcs_devinfo_t *dev, int argc, char *argv[])
+{
+       ulong addr,off,cnt;
+       ulong sz;
+
+       if (argc < 5) {
+               printf ("USAGE: epcs read addr offset count\n");
+               return;
+       }
+
+       sz = 1 << dev->size;
+       addr = simple_strtoul (argv[2], NULL, 16);
+       off  = simple_strtoul (argv[3], NULL, 16);
+       cnt  = simple_strtoul (argv[4], NULL, 16);
+       if (off > sz) {
+               printf ("offset is greater than device size"
+                       "... aborting.\n");
+               return;
+       }
+       if ((off + cnt) > sz) {
+               printf ("request exceeds device size"
+                       "... truncating.\n");
+               cnt = sz - off;
+       }
+       printf ("epcs: read %08lx <- %06lx (0x%lx bytes)\n",
+                       addr, off, cnt);
+       epcs_read (addr, off, cnt);
+
+       return;
+}
+
+static
+void do_epcs_write (struct epcs_devinfo_t *dev, int argc, char *argv[])
+{
+       ulong addr,off,cnt;
+       ulong sz;
+       ulong err;
+
+       if (argc < 5) {
+               printf ("USAGE: epcs write addr offset count\n");
+               return;
+       }
+       if ((epcs_status_rd() & dev->prot_mask) != 0) {
+               printf ( "epcs: device protected.\n");
+               return;
+       }
+
+       sz = 1 << dev->size;
+       addr = simple_strtoul (argv[2], NULL, 16);
+       off  = simple_strtoul (argv[3], NULL, 16);
+       cnt  = simple_strtoul (argv[4], NULL, 16);
+       if (off > sz) {
+               printf ("offset is greater than device size"
+                       "... aborting.\n");
+               return;
+       }
+       if ((off + cnt) > sz) {
+               printf ("request exceeds device size"
+                       "... truncating.\n");
+               cnt = sz - off;
+       }
+       printf ("epcs: write %08lx -> %06lx (0x%lx bytes)\n",
+                       addr, off, cnt);
+       epcs_write (addr, off, cnt);
+       if (epcs_verify (addr, off, cnt, &err) != 0)
+               printf ("epcs: write error at offset %06lx\n", err);
+
+       return;
+}
+
+static
+void do_epcs_verify (struct epcs_devinfo_t *dev, int argc, char *argv[])
+{
+       ulong addr,off,cnt;
+       ulong sz;
+       ulong err;
+
+       if (argc < 5) {
+               printf ("USAGE: epcs verify addr offset count\n");
+               return;
+       }
+
+       sz = 1 << dev->size;
+       addr = simple_strtoul (argv[2], NULL, 16);
+       off  = simple_strtoul (argv[3], NULL, 16);
+       cnt  = simple_strtoul (argv[4], NULL, 16);
+       if (off > sz) {
+               printf ("offset is greater than device size"
+                       "... aborting.\n");
+               return;
+       }
+       if ((off + cnt) > sz) {
+               printf ("request exceeds device size"
+                       "... truncating.\n");
+               cnt = sz - off;
+       }
+       printf ("epcs: verify %08lx -> %06lx (0x%lx bytes)\n",
+                       addr, off, cnt);
+       if (epcs_verify (addr, off, cnt, &err) != 0)
+               printf ("epcs: verify error at offset %06lx\n", err);
+
+       return;
+}
+
+/*-----------------------------------------------------------------------*/
+int do_epcs (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+       int len;
+       struct epcs_devinfo_t *dev = epcs_dev_find ();
+
+       if (!dev) {
+               printf ("epcs: device not found.\n");
+               return (-1);
+       }
+
+       if (argc < 2) {
+               do_epcs_info (dev, argc, argv);
+               return (0);
+       }
+
+       len = strlen (argv[1]);
+       if (strncmp ("info", argv[1], len) == 0) {
+               do_epcs_info (dev, argc, argv);
+       } else if (strncmp ("erase", argv[1], len) == 0) {
+               do_epcs_erase (dev, argc, argv);
+       } else if (strncmp ("protect", argv[1], len) == 0) {
+               do_epcs_protect (dev, argc, argv);
+       } else if (strncmp ("read", argv[1], len) == 0) {
+               do_epcs_read (dev, argc, argv);
+       } else if (strncmp ("write", argv[1], len) == 0) {
+               do_epcs_write (dev, argc, argv);
+       } else if (strncmp ("verify", argv[1], len) == 0) {
+               do_epcs_verify (dev, argc, argv);
+       } else {
+               printf ("epcs: unknown operation: %s\n", argv[1]);
+       }
+
+       return (0);
+}
+
+/*-----------------------------------------------------------------------*/
+
+
+U_BOOT_CMD( epcs, 5, 0, do_epcs, SHORT_HELP, LONG_HELP );
+
+#endif /* CONFIG_NIOS_EPCS */
index 281d42c2123c5a1de03095681ef82bb03d45e006..4c6e47066a3c770a7c1bc5ee26ee2627c1feddf8 100644 (file)
@@ -39,14 +39,24 @@ _start:
         * just be invalidating the cache a second time. If cache
         * is not implemented initi behaves as nop.
         */
-       movhi   r4, %hi(CFG_ICACHELINE_SIZE)
-       ori     r4, r4, %lo(CFG_ICACHELINE_SIZE)
+       ori     r4, r0, %lo(CFG_ICACHELINE_SIZE)
        movhi   r5, %hi(CFG_ICACHE_SIZE)
        ori     r5, r5, %lo(CFG_ICACHE_SIZE)
        mov     r6, r0
 0:     initi   r6
        add     r6, r6, r4
        bltu    r6, r5, 0b
+       br      _except_end     /* Skip the tramp */
+
+       /* EXCEPTION TRAMPOLINE -- the following gets copied
+        * to the exception address (below), but is otherwise at the
+        * default exception vector offset (0x0020).
+        */
+_except_start:
+       movhi   et, %hi(_exception)
+       ori     et, et, %lo(_exception)
+       jmp     et
+_except_end:
 
        /* INTERRUPTS -- for now, all interrupts masked and globally
         * disabled.
@@ -117,7 +127,9 @@ _cur:       movhi   r5, %hi(_cur - _start)
 _reloc:
 
        /* COPY EXCEPTION TRAMPOLINE -- copy the tramp to the
-        * exception address.
+        * exception address. Define CONFIG_ROM_STUBS to prevent
+        * the copy (e.g. exception in flash or in other
+        * softare/firmware component).
         */
 #if !defined(CONFIG_ROM_STUBS)
        movhi   r4, %hi(_except_start)
@@ -126,12 +138,14 @@ _reloc:
        ori     r5, r5, %lo(_except_end)
        movhi   r6, %hi(CFG_EXCEPTION_ADDR)
        ori     r6, r6, %lo(CFG_EXCEPTION_ADDR)
+       beq     r4, r6, 7f      /* Skip if at proper addr */
 
 6:     ldwio   r7, 0(r4)
        stwio   r7, 0(r6)
        addi    r4, r4, 4
        addi    r6, r6, 4
        bne     r4, r5, 6b
+7:
 #endif
 
        /* STACK INIT -- zero top two words for call back chain.
@@ -155,15 +169,6 @@ _reloc:
         */
        br      _start
 
-       /* EXCEPTION TRAMPOLINE -- the following gets copied
-        * to the exception address.
-        */
-_except_start:
-       movhi   et, %hi(_exception)
-       ori     et, et, %lo(_exception)
-       jmp     et
-_except_end:
-
 
 /*
  * dly_clks -- Nios2 (like Nios1) doesn't have a timebase in
diff --git a/cpu/nios2/sysid.c b/cpu/nios2/sysid.c
new file mode 100644 (file)
index 0000000..2b7a569
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * (C) Copyright 2004, Psyent Corporation <www.psyent.com>
+ * Scott McNutt <smcnutt@psyent.com>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+
+#if defined (CFG_NIOS_SYSID_BASE)
+
+#include <command.h>
+#include <nios2.h>
+#include <nios2-io.h>
+#include <linux/time.h>
+
+void display_sysid (void)
+{
+       struct nios_sysid_t *sysid =
+               (struct nios_sysid_t *)CACHE_BYPASS(CFG_NIOS_SYSID_BASE);
+       struct tm t;
+       char asc[32];
+
+       localtime_r ((time_t *)&sysid->timestamp, &t);
+       asctime_r (&t, asc);
+       printf ("SYSID : %08x, %s", sysid->id, asc);
+
+}
+
+int do_sysid (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+       display_sysid ();
+       return (0);
+}
+
+U_BOOT_CMD(
+       sysid,  1,      1,      do_sysid,
+       "sysid   - display Nios-II system id\n\n",
+       "\n    - display Nios-II system id\n"
+);
+#endif /* CFG_NIOS_SYSID_BASE */
index c2c8ffcc3ffe7c9b49108f4f905836491b548d85..b16a98865ad057c94d095efb1bc8af84c7972164 100644 (file)
 extern unsigned char inb (unsigned char *port);
 extern unsigned short inw (unsigned short *port);
 extern unsigned inl (unsigned port);
-extern void outb (unsigned char val, unsigned char *port);
-extern void outw (unsigned short val, unsigned short *port);
-extern void outl (unsigned val, unsigned port);
+
+#define readb(addr)\
+       ({unsigned char val;\
+        asm volatile( "ldbio %0, 0(%1)" :"=r"(val) : "r" (addr)); val;})
+#define readw(addr)\
+       ({unsigned short val;\
+        asm volatile( "ldhio %0, 0(%1)" :"=r"(val) : "r" (addr)); val;})
+#define readl(addr)\
+       ({unsigned long val;\
+        asm volatile( "ldwio %0, 0(%1)" :"=r"(val) : "r" (addr)); val;})
+#define writeb(addr,val)\
+       asm volatile ("stbio %0, 0(%1)" : : "r" (addr), "r" (val))
+#define writew(addr,val)\
+       asm volatile ("sthio %0, 0(%1)" : : "r" (addr), "r" (val))
+#define writel(addr,val)\
+       asm volatile ("stwio %0, 0(%1)" : : "r" (addr), "r" (val))
+
+#define inb(addr)      readb(addr)
+#define inw(addr)      readw(addr)
+#define inl(addr)      readl(addr)
+#define outb(addr,val) writeb(addr,val)
+#define outw(addr,val) writew(addr,val)
+#define outl(addr,val) writel(addr,val)
+
+static inline void insb (unsigned long port, void *dst, unsigned long count)
+{
+       unsigned char *p = dst;
+       while (count--) *p++ = inb (port);
+}
+static inline void insw (unsigned long port, void *dst, unsigned long count)
+{
+       unsigned short *p = dst;
+       while (count--) *p++ = inw (port);
+}
+static inline void insl (unsigned long port, void *dst, unsigned long count)
+{
+       unsigned long *p = dst;
+       while (count--) *p++ = inl (port);
+}
+
+static inline void outsb (unsigned long port, const void *src, unsigned long count)
+{
+       const unsigned char *p = src;
+       while (count--) outb (*p++, port);
+}
+
+static inline void outsw (unsigned long port, const void *src, unsigned long count)
+{
+       const unsigned short *p = src;
+       while (count--) outw (*p++, port);
+}
+static inline void outsl (unsigned long port, const void *src, unsigned long count)
+{
+       const unsigned long *p = src;
+       while (count--) outl (*p++, port);
+}
 
 #endif /* __ASM_NIOS2_IO_H_ */
index 865c69b5b747f380e43b10aeffea22a8bfbe58cf..91e95186a239401d7e97a6b47c623b42d97056da 100644 (file)
@@ -52,7 +52,7 @@
 #define CFG_SDRAM_BASE         0x01000000      /* SDRAM base addr      */
 #define CFG_SDRAM_SIZE         0x01000000      /* 16 MByte             */
 #define CFG_SRAM_BASE          0x00800000      /* SRAM base addr       */
-#define CFG_SRAM_SIZE          0x00200000      /* 2 MByte              */
+#define CFG_SRAM_SIZE          0x00100000      /* 1 MB (only 1M mapped)*/
 
 /*------------------------------------------------------------------------
  * MEMORY ORGANIZATION
 
 #define CFG_CONSOLE_INFO_QUIET 1               /* Suppress console info*/
 
+/*------------------------------------------------------------------------
+ * EPCS Device -- wne CFG_NIOS_EPCSBASE is defined code/commands for
+ * epcs device access is enabled. The base address is the epcs
+ * _register_ base address, NOT THE ADDRESS OF THE MEMORY BLOCK.
+ * The register base is currently at offset 0x400 from the memory base.
+ *----------------------------------------------------------------------*/
+#define CFG_NIOS_EPCSBASE      0x00900400      /* EPCS register base   */
+
 /*------------------------------------------------------------------------
  * DEBUG
  *----------------------------------------------------------------------*/
                                 CFG_CMD_SAVES  )
 #include <cmd_confdefs.h>
 
+/*------------------------------------------------------------------------
+ * COMPACT FLASH
+ *----------------------------------------------------------------------*/
+#if (CONFIG_COMMANDS & CFG_CMD_IDE)
+#define CONFIG_IDE_PREINIT                     /* Implement id_preinit */
+#define CFG_IDE_MAXBUS         1               /* 1 IDE bus            */
+#define CFG_IDE_MAXDEVICE      1               /* 1 drive per IDE bus  */
+
+#define CFG_ATA_BASE_ADDR      0x00900800      /* ATA base addr        */
+#define CFG_ATA_IDE0_OFFSET    0x0000          /* IDE0 offset          */
+#define CFG_ATA_DATA_OFFSET    0x0040          /* Data IO offset       */
+#define CFG_ATA_REG_OFFSET     0x0040          /* Register offset      */
+#define CFG_ATA_ALT_OFFSET     0x0100          /* Alternate reg offset */
+#define CFG_ATA_STRIDE          4              /* Width betwix addrs   */
+#define CONFIG_DOS_PARTITION
+
+/* Board-specific cf regs */
+#define CFG_CF_PRESENT         0x00900880      /* CF Present PIO base  */
+#define CFG_CF_POWER           0x00900890      /* CF Power FET PIO base*/
+#define CFG_CF_ATASEL          0x009008a0      /* CF ATASEL PIO base   */
+
+#endif /* CONFIG_COMMANDS & CFG_CMD_IDE */
+
+/*------------------------------------------------------------------------
+ * JFFS2
+ *----------------------------------------------------------------------*/
+#if (CONFIG_COMMANDS & CFG_CMD_JFFS2)
+#define CFG_JFFS_CUSTOM_PART                   /* board defined part   */
+#endif
+
 /*------------------------------------------------------------------------
  * MISC
  *----------------------------------------------------------------------*/
 #define CFG_MEMTEST_START      CFG_SDRAM_BASE  /* Start addr for test  */
 #define CFG_MEMTEST_END                CFG_INIT_SP - 0x00020000
 
+#define CFG_HUSH_PARSER
+#define CFG_PROMPT_HUSH_PS2    "> "
+
 #endif /* __CONFIG_H */
diff --git a/include/nios2-epcs.h b/include/nios2-epcs.h
new file mode 100644 (file)
index 0000000..2c9522c
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * (C) Copyright 2004, Psyent Corporation <www.psyent.com>
+ * Scott McNutt <smcnutt@psyent.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
+ */
+
+/*************************************************************************
+ * Altera Nios-II EPCS Controller Core interfaces
+ ************************************************************************/
+
+#ifndef __NIOS2_EPCS_H__
+#define __NIOS2_EPCS_H__
+
+typedef struct epcs_devinfo_t {
+       const char      *name;          /* Device name */
+       unsigned char   id;             /* Device silicon id */
+       unsigned char   size;           /* Total size log2(bytes)*/
+       unsigned char   num_sects;      /* Number of sectors */
+       unsigned char   sz_sect;        /* Sector size log2(bytes) */
+       unsigned char   sz_page;        /* Page size log2(bytes) */
+       unsigned char   prot_mask;      /* Protection mask */
+}epcs_devinfo_t;
+
+/* Returns the devinfo struct if EPCS device is found;
+ * NULL otherwise.
+ */
+extern epcs_devinfo_t *epcs_dev_find (void);
+
+/* Returns the number of bytes used by config data.
+ * Negative on error.
+ */
+extern int epcs_cfgsz (void);
+
+/* Erase sectors 'start' to 'end' - return zero on success
+ */
+extern int epcs_erase (unsigned start, unsigned end);
+
+/* Read 'cnt' bytes from device offset 'off' into buf at 'addr'
+ * Zero return on success
+ */
+extern int epcs_read (ulong addr, ulong off, ulong cnt);
+
+/* Write 'cnt' bytes to device offset 'off' from buf at 'addr'.
+ * Zero return on success
+ */
+extern int epcs_write (ulong addr, ulong off, ulong cnt);
+
+/* Verify 'cnt' bytes at device offset 'off' comparing with buf
+ * at 'addr'. On failure, write first invalid offset to *err.
+ * Zero return on success
+ */
+extern int epcs_verify (ulong addr, ulong off, ulong cnt, ulong *err);
+
+#endif /* __NIOS2_EPCS_H__ */
index d2aeabb9427a32a72e985d03586a8bde215b9268..d5c8652d5d8b0596fb537939427db5c91989b7b8 100644 (file)
@@ -136,37 +136,6 @@ typedef volatile struct nios_spi_t {
 #define NIOS_SPI_IE            (1 << 8)        /* exception int ena */
 #define NIOS_SPI_SSO           (1 << 10)       /* override SS_n output */
 
-/*------------------------------------------------------------------------
- * ASMI
- *----------------------------------------------------------------------*/
-typedef volatile struct nios_asmi_t {
-       unsigned        rxdata;         /* Rx data reg */
-       unsigned        txdata;         /* Tx data reg */
-       unsigned        status;         /* Status reg */
-       unsigned        control;        /* Control reg */
-       unsigned        reserved;
-       unsigned        slavesel;       /* Slave select */
-       unsigned        endofpacket;    /* End-of-packet reg */
-}nios_asmi_t;
-
-/* status register */
-#define NIOS_ASMI_ROE          (1 << 3)        /* rx overrun */
-#define NIOS_ASMI_TOE          (1 << 4)        /* tx overrun */
-#define NIOS_ASMI_TMT          (1 << 5)        /* tx empty */
-#define NIOS_ASMI_TRDY         (1 << 6)        /* tx ready */
-#define NIOS_ASMI_RRDY         (1 << 7)        /* rx ready */
-#define NIOS_ASMI_E            (1 << 8)        /* exception */
-#define NIOS_ASMI_EOP          (1 << 9)        /* eop detected */
-
-/* control register */
-#define NIOS_ASMI_IROE         (1 << 3)        /* rx overrun int ena */
-#define NIOS_ASMI_ITOE         (1 << 4)        /* tx overrun int ena */
-#define NIOS_ASMI_ITRDY                (1 << 6)        /* tx ready int ena */
-#define NIOS_ASMI_IRRDY                (1 << 7)        /* rx ready int ena */
-#define NIOS_ASMI_IE           (1 << 8)        /* exception int ena */
-#define NIOS_ASMI_IEOP         (1 << 9)        /* rx eop int ena */
-#define NIOS_ASMI_SSO          (1 << 10)       /* slave select enable */
-
 /*------------------------------------------------------------------------
  * JTAG UART
  *----------------------------------------------------------------------*/
index 2c848df67cf88b54fd4125968856a2e3a105b272..9eb34264d0bca5b2a400251bbab3e1fc16ed5df8 100644 (file)
 
 #include <common.h>
 #include <command.h>
+#include <asm/byteorder.h>
+
+extern image_header_t header;  /* common/cmd_bootm.c */
 
-/* TODO
- */
 void do_bootm_linux(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[],
                ulong addr, ulong *len_ptr, int   verify)
 {
+       image_header_t *hdr = &header;
+       void (*kernel)(void) = (void (*)(void))ntohl (hdr->ih_ep);
+
+       /* For now we assume the Microtronix linux ... which only
+        * needs to be called ;-)
+        */
+       kernel ();
 }