Das U-Boot: Universal Boot Loader
authorwdenk <wdenk>
Wed, 21 Aug 2002 22:08:56 +0000 (22:08 +0000)
committerwdenk <wdenk>
Wed, 21 Aug 2002 22:08:56 +0000 (22:08 +0000)
common/virtex2.c [new file with mode: 0644]
common/xilinx.c [new file with mode: 0644]
rtc/ds1337.c [new file with mode: 0644]

diff --git a/common/virtex2.c b/common/virtex2.c
new file mode 100644 (file)
index 0000000..b519be9
--- /dev/null
@@ -0,0 +1,543 @@
+/*
+ * (C) Copyright 2002
+ * Rich Ireland, Enterasys Networks, rireland@enterasys.com.
+ * Keith Outwater, keith_outwater@mvis.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
+ *
+ */
+
+/*
+ * Configuration support for Xilinx Virtex2 devices.  Based
+ * on spartan2.c (Rich Ireland, rireland@enterasys.com).
+ */
+
+#include <common.h>
+#include <virtex2.h>
+
+#if (CONFIG_FPGA & (CFG_XILINX | CFG_VIRTEX2))
+
+#ifdef FPGA_DEBUG
+#define        PRINTF(fmt,args...)     printf (fmt ,##args)
+#else
+#define PRINTF(fmt,args...)
+#endif
+
+/*
+ * If the SelectMap interface can be overrun by the processor, define
+ * CFG_FPGA_CHECK_BUSY and/or CONFIG_FPGA_DELAY in the board configuration
+ * file and add board-specific support for checking BUSY status. By default,
+ * assume that the SelectMap interface cannot be overrun.
+ */
+#ifndef CFG_FPGA_CHECK_BUSY
+#undef CFG_FPGA_CHECK_BUSY
+#endif
+
+#ifndef CONFIG_FPGA_DELAY
+#define CONFIG_FPGA_DELAY()
+#endif
+
+#ifndef CFG_FPGA_PROG_FEEDBACK
+#define CFG_FPGA_PROG_FEEDBACK
+#endif
+
+/*
+ * Don't allow config cycle to be interrupted
+ */
+#ifndef CFG_FPGA_CHECK_CTRLC
+#undef CFG_FPGA_CHECK_CTRLC
+#endif
+
+/*
+ * Check for errors during configuration by default
+ */
+#ifndef CFG_FPGA_CHECK_ERROR
+#define CFG_FPGA_CHECK_ERROR
+#endif
+
+/*
+ * The default timeout in mS for INIT_B to deassert after PROG_B has
+ * been deasserted. Per the latest Virtex II Handbook (page 347), the
+ * max time from PORG_B deassertion to INIT_B deassertion is 4uS per
+ * data frame for the XC2V8000.  The XC2V8000 has 2860 data frames
+ * which yields 11.44 mS.  So let's make it bigger in order to handle
+ * an XC2V1000, if anyone can ever get ahold of one.
+ */
+#ifndef CFG_FPGA_WAIT_INIT
+#define CFG_FPGA_WAIT_INIT     500     /* time in milliseconds */
+#endif
+
+/*
+ * The default timeout for waiting for BUSY to deassert during configuration.
+ * This is normally not necessary since for most reasonable configuration
+ * clock frequencies (i.e. 66 MHz or less), BUSY monitoring is unnecessary.
+ */
+#ifndef CFG_FPGA_WAIT_BUSY
+#define CFG_FPGA_WAIT_BUSY     5       /* time in milliseconds */
+#endif
+
+/* Default timeout for waiting for FPGA to enter operational mode after
+ * configuration data has been written.
+ */
+#ifndef        CFG_FPGA_WAIT_CONFIG
+#define CFG_FPGA_WAIT_CONFIG   200     /* time in milliseconds */
+#endif
+
+static int Virtex2_ssm_load (Xilinx_desc * desc, void *buf, size_t bsize);
+static int Virtex2_ssm_dump (Xilinx_desc * desc, void *buf, size_t bsize);
+static int Virtex2_ssm_reloc (Xilinx_desc * desc, ulong reloc_offset);
+
+static int Virtex2_ss_load (Xilinx_desc * desc, void *buf, size_t bsize);
+static int Virtex2_ss_dump (Xilinx_desc * desc, void *buf, size_t bsize);
+static int Virtex2_ss_reloc (Xilinx_desc * desc, ulong reloc_offset);
+
+int Virtex2_load (Xilinx_desc * desc, void *buf, size_t bsize)
+{
+       int ret_val = FPGA_FAIL;
+
+       switch (desc->iface) {
+       case slave_serial:
+               PRINTF ("%s: Launching Slave Serial Load\n", __FUNCTION__);
+               ret_val = Virtex2_ss_load (desc, buf, bsize);
+               break;
+
+       case slave_selectmap:
+               PRINTF ("%s: Launching Slave Parallel Load\n", __FUNCTION__);
+               ret_val = Virtex2_ssm_load (desc, buf, bsize);
+               break;
+
+       default:
+               printf ("%s: Unsupported interface type, %d\n",
+                               __FUNCTION__, desc->iface);
+       }
+       return ret_val;
+}
+
+int Virtex2_dump (Xilinx_desc * desc, void *buf, size_t bsize)
+{
+       int ret_val = FPGA_FAIL;
+
+       switch (desc->iface) {
+       case slave_serial:
+               PRINTF ("%s: Launching Slave Serial Dump\n", __FUNCTION__);
+               ret_val = Virtex2_ss_dump (desc, buf, bsize);
+               break;
+
+       case slave_parallel:
+               PRINTF ("%s: Launching Slave Parallel Dump\n", __FUNCTION__);
+               ret_val = Virtex2_ssm_dump (desc, buf, bsize);
+               break;
+
+       default:
+               printf ("%s: Unsupported interface type, %d\n",
+                               __FUNCTION__, desc->iface);
+       }
+       return ret_val;
+}
+
+int Virtex2_info (Xilinx_desc * desc)
+{
+       return FPGA_SUCCESS;
+}
+
+int Virtex2_reloc (Xilinx_desc * desc, ulong reloc_offset)
+{
+       int ret_val = FPGA_FAIL;
+
+       if (desc->family != Xilinx_Virtex2) {
+               printf ("%s: Unsupported family type, %d\n",
+                               __FUNCTION__, desc->family);
+               return FPGA_FAIL;
+       } else
+               switch (desc->iface) {
+               case slave_serial:
+                       ret_val = Virtex2_ss_reloc (desc, reloc_offset);
+                       break;
+
+               case slave_selectmap:
+                       ret_val = Virtex2_ssm_reloc (desc, reloc_offset);
+                       break;
+
+               default:
+                       printf ("%s: Unsupported interface type, %d\n",
+                                       __FUNCTION__, desc->iface);
+               }
+       return ret_val;
+}
+
+/*
+ * Virtex-II Slave SelectMap configuration loader. Configuration via
+ * SelectMap is as follows:
+ * 1. Set the FPGA's PROG_B line low.
+ * 2. Set the FPGA's PROG_B line high.  Wait for INIT_B to go high.
+ * 3. Write data to the SelectMap port.  If INIT_B goes low at any time
+ *    this process, a configuration error (most likely CRC failure) has
+ *    ocurred.  At this point a status word may be read from the
+ *    SelectMap interface to determine the source of the problem (You
+ *    could, for instance, put this in you 'abort' function handler).
+ * 4. After all data has been written, test the state of the FPGA
+ *    INIT_B and DONE lines.  If both are high, configuration has
+ *    succeeded. Congratulations!
+ */
+static int Virtex2_ssm_load (Xilinx_desc * desc, void *buf, size_t bsize)
+{
+       int ret_val = FPGA_FAIL;
+       Xilinx_Virtex2_Slave_SelectMap_fns *fn = desc->iface_fns;
+
+       PRINTF ("%s:%d: Start with interface functions @ 0x%p\n",
+                       __FUNCTION__, __LINE__, fn);
+
+       if (fn) {
+               size_t bytecount = 0;
+               unsigned char *data = (unsigned char *) buf;
+               int cookie = desc->cookie;
+               unsigned long ts;
+
+               /* Gotta split this one up (so the stack won't blow??) */
+               PRINTF ("%s:%d: Function Table:\n"
+                               "  base   0x%p\n"
+                               "  struct 0x%p\n"
+                               "  pre    0x%p\n"
+                               "  prog   0x%p\n"
+                               "  init   0x%p\n"
+                               "  error  0x%p\n",
+                               __FUNCTION__, __LINE__,
+                               &fn, fn, fn->pre, fn->pgm, fn->init, fn->err);
+               PRINTF ("  clock  0x%p\n"
+                               "  cs     0x%p\n"
+                               "  write  0x%p\n"
+                               "  rdata  0x%p\n"
+                               "  wdata  0x%p\n"
+                               "  busy   0x%p\n"
+                               "  abort  0x%p\n"
+                               "  post   0x%p\n\n",
+                               fn->clk, fn->cs, fn->wr, fn->rdata, fn->wdata,
+                               fn->busy, fn->abort, fn->post);
+
+#ifdef CFG_FPGA_PROG_FEEDBACK
+               printf ("Initializing FPGA Device %d...\n", cookie);
+#endif
+               /*
+                * Run the pre configuration function if there is one.
+                */
+               if (*fn->pre) {
+                       (*fn->pre) (cookie);
+               }
+
+               /*
+                * Assert the program line.  The minimum pulse width for
+                * Virtex II devices is 300 nS (Tprogram parameter in datasheet).
+                * There is no maximum value for the pulse width.  Check to make
+                * sure that INIT_B goes low after assertion of PROG_B
+                */
+               (*fn->pgm) (TRUE, TRUE, cookie);
+               udelay (10);
+               ts = get_timer (0);
+               do {
+                       if (get_timer (ts) > CFG_FPGA_WAIT_INIT) {
+                               printf ("%s:%d: ** Timeout after %d mS waiting for INIT"
+                                               " to assert.\n", __FUNCTION__, __LINE__,
+                                               CFG_FPGA_WAIT_INIT);
+                               (*fn->abort) (cookie);
+                               return FPGA_FAIL;
+                       }
+               } while (!(*fn->init) (cookie));
+
+               (*fn->pgm) (FALSE, TRUE, cookie);
+               CONFIG_FPGA_DELAY ();
+               (*fn->clk) (TRUE, TRUE, cookie);
+
+               /*
+                * Start a timer and wait for INIT_B to go high
+                */
+               ts = get_timer (0);
+               do {
+                       CONFIG_FPGA_DELAY ();
+                       if (get_timer (ts) > CFG_FPGA_WAIT_INIT) {
+                               printf ("%s:%d: ** Timeout after %d mS waiting for INIT"
+                                               " to deassert.\n", __FUNCTION__, __LINE__,
+                                               CFG_FPGA_WAIT_INIT);
+                               (*fn->abort) (cookie);
+                               return FPGA_FAIL;
+                       }
+               } while ((*fn->init) (cookie) && (*fn->busy) (cookie));
+
+               (*fn->wr) (TRUE, TRUE, cookie);
+               (*fn->cs) (TRUE, TRUE, cookie);
+
+               udelay (10000);
+
+               /*
+                * Load the data byte by byte
+                */
+               while (bytecount < bsize) {
+#ifdef CFG_FPGA_CHECK_CTRLC
+                       if (ctrlc ()) {
+                               (*fn->abort) (cookie);
+                               return FPGA_FAIL;
+                       }
+#endif
+#ifdef CFG_FPGA_CHECK_ERROR
+                       if ((*fn->init) (cookie)) {
+                               printf ("%s:%d:  ** Error: INIT asserted during"
+                                               " configuration\n", __FUNCTION__, __LINE__);
+                               (*fn->abort) (cookie);
+                               return FPGA_FAIL;
+                       }
+#endif
+                       (*fn->wdata) (data[bytecount++], TRUE, cookie);
+                       CONFIG_FPGA_DELAY ();
+
+                       /*
+                        * Cycle the clock pin
+                        */
+                       (*fn->clk) (FALSE, TRUE, cookie);
+                       CONFIG_FPGA_DELAY ();
+                       (*fn->clk) (TRUE, TRUE, cookie);
+
+#ifdef CFG_FPGA_CHECK_BUSY
+                       ts = get_timer (0);
+                       while ((*fn->busy) (cookie)) {
+                               if (get_timer (ts) > CFG_FPGA_WAIT_BUSY) {
+                                       printf ("%s:%d: ** Timeout after %d mS waiting for"
+                                                       " BUSY to deassert\n",
+                                                       __FUNCTION__, __LINE__, CFG_FPGA_WAIT_BUSY);
+                                       (*fn->abort) (cookie);
+                                       return FPGA_FAIL;
+                               }
+                       }
+#endif
+
+#ifdef CFG_FPGA_PROG_FEEDBACK
+                       if (bytecount % (bsize / 40) == 0)
+                               putc ('.');
+#endif
+               }
+
+               /*
+                * Finished writing the data; deassert FPGA CS_B and WRITE_B signals.
+                */
+               CONFIG_FPGA_DELAY ();
+               (*fn->cs) (FALSE, TRUE, cookie);
+               (*fn->wr) (FALSE, TRUE, cookie);
+
+#ifdef CFG_FPGA_PROG_FEEDBACK
+               putc ('\n');
+#endif
+
+               /*
+                * Check for successful configuration.  FPGA INIT_B and DONE should
+                * both be high upon successful configuration.
+                */
+               ts = get_timer (0);
+               ret_val = FPGA_SUCCESS;
+               while (((*fn->done) (cookie) == FPGA_FAIL) || (*fn->init) (cookie)) {
+                       if (get_timer (ts) > CFG_FPGA_WAIT_CONFIG) {
+                               printf ("%s:%d: ** Timeout after %d mS waiting for DONE to"
+                                               "assert and INIT to deassert\n",
+                                               __FUNCTION__, __LINE__, CFG_FPGA_WAIT_CONFIG);
+                               (*fn->abort) (cookie);
+                               ret_val = FPGA_FAIL;
+                               break;
+                       }
+               }
+
+               if (ret_val == FPGA_SUCCESS) {
+#ifdef CFG_FPGA_PROG_FEEDBACK
+                       printf ("Initialization of FPGA device %d complete\n", cookie);
+#endif
+                       /*
+                        * Run the post configuration function if there is one.
+                        */
+                       if (*fn->post) {
+                               (*fn->post) (cookie);
+                       }
+               } else {
+#ifdef CFG_FPGA_PROG_FEEDBACK
+                       printf ("** Initialization of FPGA device %d FAILED\n",
+                                       cookie);
+#endif
+               }
+       } else {
+               printf ("%s:%d: NULL Interface function table!\n",
+                               __FUNCTION__, __LINE__);
+       }
+       return ret_val;
+}
+
+/*
+ * Read the FPGA configuration data
+ */
+static int Virtex2_ssm_dump (Xilinx_desc * desc, void *buf, size_t bsize)
+{
+       int ret_val = FPGA_FAIL;
+       Xilinx_Virtex2_Slave_SelectMap_fns *fn = desc->iface_fns;
+
+       if (fn) {
+               unsigned char *data = (unsigned char *) buf;
+               size_t bytecount = 0;
+               int cookie = desc->cookie;
+
+               printf ("Starting Dump of FPGA Device %d...\n", cookie);
+
+               (*fn->cs) (TRUE, TRUE, cookie);
+               (*fn->clk) (TRUE, TRUE, cookie);
+
+               while (bytecount < bsize) {
+#ifdef CFG_FPGA_CHECK_CTRLC
+                       if (ctrlc ()) {
+                               (*fn->abort) (cookie);
+                               return FPGA_FAIL;
+                       }
+#endif
+                       /*
+                        * Cycle the clock and read the data
+                        */
+                       (*fn->clk) (FALSE, TRUE, cookie);
+                       (*fn->clk) (TRUE, TRUE, cookie);
+                       (*fn->rdata) (&(data[bytecount++]), cookie);
+#ifdef CFG_FPGA_PROG_FEEDBACK
+                       if (bytecount % (bsize / 40) == 0)
+                               putc ('.');
+#endif
+               }
+
+               /*
+                * Deassert CS_B and cycle the clock to deselect the device.
+                */
+               (*fn->cs) (FALSE, FALSE, cookie);
+               (*fn->clk) (FALSE, TRUE, cookie);
+               (*fn->clk) (TRUE, TRUE, cookie);
+
+#ifdef CFG_FPGA_PROG_FEEDBACK
+               putc ('\n');
+#endif
+               puts ("Done.\n");
+       } else {
+               printf ("%s:%d: NULL Interface function table!\n",
+                               __FUNCTION__, __LINE__);
+       }
+       return ret_val;
+}
+
+/*
+ * Relocate the addresses in the function table from FLASH (or ROM,
+ * or whatever) to RAM.
+ */
+static int Virtex2_ssm_reloc (Xilinx_desc * desc, ulong reloc_offset)
+{
+       ulong addr;
+       int ret_val = FPGA_FAIL;
+       Xilinx_Virtex2_Slave_SelectMap_fns *fn_r, *fn =
+                       (Xilinx_Virtex2_Slave_SelectMap_fns *) (desc->iface_fns);
+
+       if (fn) {
+               /*
+                * Get the relocated table address
+                */
+               addr = (ulong) fn + reloc_offset;
+               fn_r = (Xilinx_Virtex2_Slave_SelectMap_fns *) addr;
+
+               /*
+                * Check to see if the table has already been relocated.  If not, do
+                * a sanity check to make sure there is a faithful copy of the
+                * FLASH based function table in RAM, then adjust the table.
+                */
+               if (!fn_r->relocated) {
+                       if (memcmp
+                               (fn_r, fn, sizeof (Xilinx_Virtex2_Slave_SelectMap_fns))
+                               == 0) {
+                               desc->iface_fns = fn_r;
+                       } else {
+                               PRINTF ("%s:%d: Invalid function table at 0x%p\n",
+                                               __FUNCTION__, __LINE__, fn_r);
+                               return FPGA_FAIL;
+                       }
+
+                       PRINTF ("%s:%d: Relocating descriptor at 0x%p\n",
+                                       __FUNCTION__, __LINE__, desc);
+
+                       addr = (ulong) (fn->pre) + reloc_offset;
+                       fn_r->pre = (Xilinx_pre_fn) addr;
+                       addr = (ulong) (fn->pgm) + reloc_offset;
+                       fn_r->pgm = (Xilinx_pgm_fn) addr;
+                       addr = (ulong) (fn->init) + reloc_offset;
+                       fn_r->init = (Xilinx_init_fn) addr;
+                       addr = (ulong) (fn->done) + reloc_offset;
+                       fn_r->done = (Xilinx_done_fn) addr;
+                       addr = (ulong) (fn->err) + reloc_offset;
+                       fn_r->err = (Xilinx_err_fn) addr;
+                       addr = (ulong) (fn->clk) + reloc_offset;
+                       fn_r->clk = (Xilinx_clk_fn) addr;
+                       addr = (ulong) (fn->cs) + reloc_offset;
+                       fn_r->cs = (Xilinx_cs_fn) addr;
+                       addr = (ulong) (fn->wr) + reloc_offset;
+                       fn_r->wr = (Xilinx_wr_fn) addr;
+                       addr = (ulong) (fn->rdata) + reloc_offset;
+                       fn_r->rdata = (Xilinx_rdata_fn) addr;
+                       addr = (ulong) (fn->wdata) + reloc_offset;
+                       fn_r->wdata = (Xilinx_wdata_fn) addr;
+                       addr = (ulong) (fn->busy) + reloc_offset;
+                       fn_r->busy = (Xilinx_busy_fn) addr;
+                       addr = (ulong) (fn->abort) + reloc_offset;
+                       fn_r->abort = (Xilinx_abort_fn) addr;
+                       addr = (ulong) (fn->post) + reloc_offset;
+                       fn_r->post = (Xilinx_post_fn) addr;
+                       fn_r->relocated = TRUE;
+               } else {
+                       printf ("%s:%d: Function table @0x%p has already been relocated\n", __FUNCTION__, __LINE__, fn_r);
+                       desc->iface_fns = fn_r;
+               }
+               ret_val = FPGA_SUCCESS;
+       } else {
+               printf ("%s: NULL Interface function table!\n", __FUNCTION__);
+       }
+       return ret_val;
+}
+
+static int Virtex2_ss_load (Xilinx_desc * desc, void *buf, size_t bsize)
+{
+       printf ("%s: Slave Serial Loading is unsupported\n", __FUNCTION__);
+       return FPGA_FAIL;
+}
+
+static int Virtex2_ss_dump (Xilinx_desc * desc, void *buf, size_t bsize)
+{
+       printf ("%s: Slave Serial Dumping is unsupported\n", __FUNCTION__);
+       return FPGA_FAIL;
+}
+
+static int Virtex2_ss_reloc (Xilinx_desc * desc, ulong reloc_offset)
+{
+       int ret_val = FPGA_FAIL;
+       Xilinx_Virtex2_Slave_Serial_fns *fn =
+                       (Xilinx_Virtex2_Slave_Serial_fns *) (desc->iface_fns);
+
+       if (fn) {
+               printf ("%s:%d: Slave Serial Loading is unsupported\n",
+                               __FUNCTION__, __LINE__);
+       } else {
+               printf ("%s:%d: NULL Interface function table!\n",
+                               __FUNCTION__, __LINE__);
+       }
+       return ret_val;
+}
+#endif
+
+/* vim: set ts=4 tw=78: */
diff --git a/common/xilinx.c b/common/xilinx.c
new file mode 100644 (file)
index 0000000..cb153e1
--- /dev/null
@@ -0,0 +1,269 @@
+/*
+ * (C) Copyright 2002
+ * Rich Ireland, Enterasys Networks, rireland@enterasys.com.
+ * Keith Outwater, keith_outwater@mvis.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
+ *
+ */
+
+/*
+ *  Xilinx FPGA support
+ */
+
+#include <common.h>
+#include <virtex2.h>
+#include <spartan2.h>
+
+#if (CONFIG_FPGA & CFG_FPGA_XILINX)
+
+#if 0
+#define FPGA_DEBUG
+#endif
+
+/* Define FPGA_DEBUG to get debug printf's */
+#ifdef FPGA_DEBUG
+#define        PRINTF(fmt,args...)     printf (fmt ,##args)
+#else
+#define PRINTF(fmt,args...)
+#endif
+
+/* Local Static Functions */
+static int xilinx_validate (Xilinx_desc * desc, char *fn);
+
+/* ------------------------------------------------------------------------- */
+
+int xilinx_load (Xilinx_desc * desc, void *buf, size_t bsize)
+{
+       int ret_val = FPGA_FAIL;        /* assume a failure */
+
+       if (!xilinx_validate (desc, __FUNCTION__)) {
+               printf ("%s: Invalid device descriptor\n", __FUNCTION__);
+       } else
+               switch (desc->family) {
+               case Xilinx_Spartan2:
+#if (CONFIG_FPGA & CFG_SPARTAN2)
+                       PRINTF ("%s: Launching the Spartan-II Loader...\n",
+                                       __FUNCTION__);
+                       ret_val = Spartan2_load (desc, buf, bsize);
+#else
+                       printf ("%s: No support for Spartan-II devices.\n",
+                                       __FUNCTION__);
+#endif
+                       break;
+               case Xilinx_Virtex2:
+#if (CONFIG_FPGA & CFG_VIRTEX2)
+                       PRINTF ("%s: Launching the Virtex-II Loader...\n",
+                                       __FUNCTION__);
+                       ret_val = Virtex2_load (desc, buf, bsize);
+#else
+                       printf ("%s: No support for Virtex-II devices.\n",
+                                       __FUNCTION__);
+#endif
+                       break;
+
+               default:
+                       printf ("%s: Unsupported family type, %d\n",
+                                       __FUNCTION__, desc->family);
+               }
+
+       return ret_val;
+}
+
+int xilinx_dump (Xilinx_desc * desc, void *buf, size_t bsize)
+{
+       int ret_val = FPGA_FAIL;        /* assume a failure */
+
+       if (!xilinx_validate (desc, __FUNCTION__)) {
+               printf ("%s: Invalid device descriptor\n", __FUNCTION__);
+       } else
+               switch (desc->family) {
+               case Xilinx_Spartan2:
+#if (CONFIG_FPGA & CFG_SPARTAN2)
+                       PRINTF ("%s: Launching the Spartan-II Reader...\n",
+                                       __FUNCTION__);
+                       ret_val = Spartan2_dump (desc, buf, bsize);
+#else
+                       printf ("%s: No support for Spartan-II devices.\n",
+                                       __FUNCTION__);
+#endif
+                       break;
+               case Xilinx_Virtex2:
+#if (CONFIG_FPGA & CFG_VIRTEX2)
+                       PRINTF ("%s: Launching the Virtex-II Reader...\n",
+                                       __FUNCTION__);
+                       ret_val = Virtex2_dump (desc, buf, bsize);
+#else
+                       printf ("%s: No support for Virtex-II devices.\n",
+                                       __FUNCTION__);
+#endif
+                       break;
+
+               default:
+                       printf ("%s: Unsupported family type, %d\n",
+                                       __FUNCTION__, desc->family);
+               }
+
+       return ret_val;
+}
+
+int xilinx_info (Xilinx_desc * desc)
+{
+       int ret_val = FPGA_FAIL;
+
+       if (xilinx_validate (desc, __FUNCTION__)) {
+               printf ("Family:        \t");
+               switch (desc->family) {
+               case Xilinx_Spartan2:
+                       printf ("Spartan-II\n");
+                       break;
+               case Xilinx_Virtex2:
+                       printf ("Virtex-II\n");
+                       break;
+                       /* Add new family types here */
+               default:
+                       printf ("Unknown family type, %d\n", desc->family);
+               }
+
+               printf ("Interface type:\t");
+               switch (desc->iface) {
+               case slave_serial:
+                       printf ("Slave Serial\n");
+                       break;
+               case master_serial:     /* Not used */
+                       printf ("Master Serial\n");
+                       break;
+               case slave_parallel:
+                       printf ("Slave Parallel\n");
+                       break;
+               case jtag_mode:         /* Not used */
+                       printf ("JTAG Mode\n");
+                       break;
+               case slave_selectmap:
+                       printf ("Slave SelectMap Mode\n");
+                       break;
+               case master_selectmap:
+                       printf ("Master SelectMap Mode\n");
+                       break;
+                       /* Add new interface types here */
+               default:
+                       printf ("Unsupported interface type, %d\n", desc->iface);
+               }
+
+               printf ("Device Size:   \t%d bytes\n"
+                               "Cookie:        \t0x%x (%d)\n",
+                               desc->size, desc->cookie, desc->cookie);
+
+               if (desc->iface_fns) {
+                       printf ("Device Function Table @ 0x%p\n", desc->iface_fns);
+                       switch (desc->family) {
+                       case Xilinx_Spartan2:
+#if (CONFIG_FPGA & CFG_SPARTAN2)
+                               Spartan2_info (desc);
+#else
+                               /* just in case */
+                               printf ("%s: No support for Spartan-II devices.\n",
+                                               __FUNCTION__);
+#endif
+                               break;
+                       case Xilinx_Virtex2:
+#if (CONFIG_FPGA & CFG_VIRTEX2)
+                               Virtex2_info (desc);
+#else
+                               /* just in case */
+                               printf ("%s: No support for Virtex-II devices.\n",
+                                               __FUNCTION__);
+#endif
+                               break;
+                               /* Add new family types here */
+                       default:
+                               /* we don't need a message here - we give one up above */
+                       }
+               } else
+                       printf ("No Device Function Table.\n");
+
+               ret_val = FPGA_SUCCESS;
+       } else {
+               printf ("%s: Invalid device descriptor\n", __FUNCTION__);
+       }
+
+       return ret_val;
+}
+
+int xilinx_reloc (Xilinx_desc * desc, ulong reloc_offset)
+{
+       int ret_val = FPGA_FAIL;        /* assume a failure */
+
+       if (!xilinx_validate (desc, __FUNCTION__)) {
+               printf ("%s: Invalid device descriptor\n", __FUNCTION__);
+       } else
+               switch (desc->family) {
+               case Xilinx_Spartan2:
+#if (CONFIG_FPGA & CFG_SPARTAN2)
+                       ret_val = Spartan2_reloc (desc, reloc_offset);
+#else
+                       printf ("%s: No support for Spartan-II devices.\n",
+                                       __FUNCTION__);
+#endif
+                       break;
+               case Xilinx_Virtex2:
+#if (CONFIG_FPGA & CFG_VIRTEX2)
+                       ret_val = Virtex2_reloc (desc, reloc_offset);
+#else
+                       printf ("%s: No support for Virtex-II devices.\n",
+                                       __FUNCTION__);
+#endif
+                       break;
+                       /* Add new family types here */
+               default:
+                       printf ("%s: Unsupported family type, %d\n",
+                                       __FUNCTION__, desc->family);
+               }
+
+       return ret_val;
+}
+
+
+/* ------------------------------------------------------------------------- */
+
+static int xilinx_validate (Xilinx_desc * desc, char *fn)
+{
+       int ret_val = FALSE;
+
+       if (desc) {
+               if ((desc->family > min_xilinx_type) &&
+                       (desc->family < max_xilinx_type)) {
+                       if ((desc->iface > min_xilinx_iface_type) &&
+                               (desc->iface < max_xilinx_iface_type)) {
+                               if (desc->size) {
+                                       ret_val = TRUE;
+                               } else
+                                       printf ("%s: NULL part size\n", fn);
+                       } else
+                               printf ("%s: Invalid Interface type, %d\n",
+                                               fn, desc->iface);
+               } else
+                       printf ("%s: Invalid family type, %d\n", fn, desc->family);
+       } else
+               printf ("%s: NULL descriptor!\n", fn);
+
+       return ret_val;
+}
+
+#endif                                                 /* CONFIG_FPGA & CFG_FPGA_XILINX */
diff --git a/rtc/ds1337.c b/rtc/ds1337.c
new file mode 100644 (file)
index 0000000..9f0c8c0
--- /dev/null
@@ -0,0 +1,191 @@
+/*
+ * (C) Copyright 2001, 2002
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ * Keith Outwater, keith_outwater@mvis.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
+ */
+
+/*
+ * Date & Time support (no alarms) for Dallas Semiconductor (now Maxim)
+ * DS1337 Real Time Clock (RTC).
+ */
+
+#include <common.h>
+#include <command.h>
+#include <rtc.h>
+#include <i2c.h>
+
+#if defined(CONFIG_RTC_DS1337) && (CONFIG_COMMANDS & CFG_CMD_DATE)
+
+/*---------------------------------------------------------------------*/
+#undef DEBUG_RTC
+
+#ifdef DEBUG_RTC
+#define DEBUGR(fmt,args...) printf(fmt ,##args)
+#else
+#define DEBUGR(fmt,args...)
+#endif
+/*---------------------------------------------------------------------*/
+
+/*
+ * RTC register addresses
+ */
+#define RTC_SEC_REG_ADDR       0x0
+#define RTC_MIN_REG_ADDR       0x1
+#define RTC_HR_REG_ADDR                0x2
+#define RTC_DAY_REG_ADDR       0x3
+#define RTC_DATE_REG_ADDR      0x4
+#define RTC_MON_REG_ADDR       0x5
+#define RTC_YR_REG_ADDR                0x6
+#define RTC_CTL_REG_ADDR       0x0e
+#define RTC_STAT_REG_ADDR      0x0f
+
+/*
+ * RTC control register bits
+ */
+#define RTC_CTL_BIT_A1IE       0x1     /* Alarm 1 interrupt enable     */
+#define RTC_CTL_BIT_A2IE       0x2     /* Alarm 2 interrupt enable     */
+#define RTC_CTL_BIT_INTCN      0x4     /* Interrupt control            */
+#define RTC_CTL_BIT_RS1                0x8     /* Rate select 1                */
+#define RTC_CTL_BIT_RS2                0x10    /* Rate select 2                */
+#define RTC_CTL_BIT_DOSC       0x80    /* Disable Oscillator           */
+
+/*
+ * RTC status register bits
+ */
+#define RTC_STAT_BIT_A1F       0x1     /* Alarm 1 flag                 */
+#define RTC_STAT_BIT_A2F       0x2     /* Alarm 2 flag                 */
+#define RTC_STAT_BIT_OSF       0x80    /* Oscillator stop flag         */
+
+
+static uchar rtc_read (uchar reg);
+static void rtc_write (uchar reg, uchar val);
+static uchar bin2bcd (unsigned int n);
+static unsigned bcd2bin (uchar c);
+
+
+/*
+ * Get the current time from the RTC
+ */
+void rtc_get (struct rtc_time *tmp)
+{
+       uchar sec, min, hour, mday, wday, mon_cent, year, control, status;
+
+       control = rtc_read (RTC_CTL_REG_ADDR);
+       status = rtc_read (RTC_STAT_REG_ADDR);
+       sec = rtc_read (RTC_SEC_REG_ADDR);
+       min = rtc_read (RTC_MIN_REG_ADDR);
+       hour = rtc_read (RTC_HR_REG_ADDR);
+       wday = rtc_read (RTC_DAY_REG_ADDR);
+       mday = rtc_read (RTC_DATE_REG_ADDR);
+       mon_cent = rtc_read (RTC_MON_REG_ADDR);
+       year = rtc_read (RTC_YR_REG_ADDR);
+
+       DEBUGR ("Get RTC year: %02x mon/cent: %02x mday: %02x wday: %02x "
+               "hr: %02x min: %02x sec: %02x control: %02x status: %02x\n",
+               year, mon_cent, mday, wday, hour, min, sec, control, status);
+
+       if (status & RTC_STAT_BIT_OSF) {
+               printf ("### Warning: RTC oscillator has stopped\n");
+               /* clear the OSF flag */
+               rtc_write (RTC_STAT_REG_ADDR,
+                          rtc_read (RTC_STAT_REG_ADDR) & ~RTC_STAT_BIT_OSF);
+       }
+
+       tmp->tm_sec  = bcd2bin (sec & 0x7F);
+       tmp->tm_min  = bcd2bin (min & 0x7F);
+       tmp->tm_hour = bcd2bin (hour & 0x3F);
+       tmp->tm_mday = bcd2bin (mday & 0x3F);
+       tmp->tm_mon  = bcd2bin (mon_cent & 0x1F);
+       tmp->tm_year = bcd2bin (year) + ((mon_cent & 0x80) ? 2000 : 1900);
+       tmp->tm_wday = bcd2bin ((wday - 1) & 0x07);
+       tmp->tm_yday = 0;
+       tmp->tm_isdst= 0;
+
+       DEBUGR ("Get DATE: %4d-%02d-%02d (wday=%d)  TIME: %2d:%02d:%02d\n",
+               tmp->tm_year, tmp->tm_mon, tmp->tm_mday, tmp->tm_wday,
+               tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
+}
+
+
+/*
+ * Set the RTC
+ */
+void rtc_set (struct rtc_time *tmp)
+{
+       uchar century;
+
+       DEBUGR ("Set DATE: %4d-%02d-%02d (wday=%d)  TIME: %2d:%02d:%02d\n",
+               tmp->tm_year, tmp->tm_mon, tmp->tm_mday, tmp->tm_wday,
+               tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
+
+       rtc_write (RTC_YR_REG_ADDR, bin2bcd (tmp->tm_year % 100));
+
+       century = (tmp->tm_year >= 2000) ? 0x80 : 0;
+       rtc_write (RTC_MON_REG_ADDR, bin2bcd (tmp->tm_mon) | century);
+
+       rtc_write (RTC_DAY_REG_ADDR, bin2bcd (tmp->tm_wday + 1));
+       rtc_write (RTC_DATE_REG_ADDR, bin2bcd (tmp->tm_mday));
+       rtc_write (RTC_HR_REG_ADDR, bin2bcd (tmp->tm_hour));
+       rtc_write (RTC_MIN_REG_ADDR, bin2bcd (tmp->tm_min));
+       rtc_write (RTC_SEC_REG_ADDR, bin2bcd (tmp->tm_sec));
+}
+
+
+/*
+ * Reset the RTC.  We also enable the oscillator output on the
+ * SQW/INTB* pin and program it for 32,768 Hz output. Note that
+ * according to the datasheet, turning on the square wave output
+ * increases the current drain on the backup battery from about
+ * 600 nA to 2uA.
+ */
+void rtc_reset (void)
+{
+       rtc_write (RTC_CTL_REG_ADDR, RTC_CTL_BIT_RS1 | RTC_CTL_BIT_RS2);
+}
+
+
+/*
+ * Helper functions
+ */
+
+static
+uchar rtc_read (uchar reg)
+{
+       return (i2c_reg_read (CFG_I2C_RTC_ADDR, reg));
+}
+
+
+static void rtc_write (uchar reg, uchar val)
+{
+       i2c_reg_write (CFG_I2C_RTC_ADDR, reg, val);
+}
+
+static unsigned bcd2bin (uchar n)
+{
+       return ((((n >> 4) & 0x0F) * 10) + (n & 0x0F));
+}
+
+static unsigned char bin2bcd (unsigned int n)
+{
+       return (((n / 10) << 4) | (n % 10));
+}
+
+#endif /* CONFIG_RTC_DS1337 && (CFG_COMMANDS & CFG_CMD_DATE) */