Add qemu 2.4.0
[kvmfornfv.git] / qemu / roms / u-boot / board / esd / pmc440 / fpga.c
diff --git a/qemu/roms/u-boot/board/esd/pmc440/fpga.c b/qemu/roms/u-boot/board/esd/pmc440/fpga.c
new file mode 100644 (file)
index 0000000..f876da8
--- /dev/null
@@ -0,0 +1,446 @@
+/*
+ * (C) Copyright 2007
+ * Matthias Fuchs, esd gmbh, matthias.fuchs@esd-electronics.com.
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <spartan2.h>
+#include <spartan3.h>
+#include <command.h>
+#include "fpga.h"
+#include "pmc440.h"
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#if defined(CONFIG_FPGA)
+
+#define USE_SP_CODE
+
+#ifdef USE_SP_CODE
+xilinx_spartan3_slave_parallel_fns pmc440_fpga_fns = {
+       fpga_pre_config_fn,
+       fpga_pgm_fn,
+       fpga_init_fn,
+       NULL, /* err */
+       fpga_done_fn,
+       fpga_clk_fn,
+       fpga_cs_fn,
+       fpga_wr_fn,
+       NULL, /* rdata */
+       fpga_wdata_fn,
+       fpga_busy_fn,
+       fpga_abort_fn,
+       fpga_post_config_fn,
+};
+#else
+xilinx_spartan3_slave_serial_fns pmc440_fpga_fns = {
+       fpga_pre_config_fn,
+       fpga_pgm_fn,
+       fpga_clk_fn,
+       fpga_init_fn,
+       fpga_done_fn,
+       fpga_wr_fn,
+       fpga_post_config_fn,
+};
+#endif
+
+xilinx_spartan2_slave_serial_fns ngcc_fpga_fns = {
+       ngcc_fpga_pre_config_fn,
+       ngcc_fpga_pgm_fn,
+       ngcc_fpga_clk_fn,
+       ngcc_fpga_init_fn,
+       ngcc_fpga_done_fn,
+       ngcc_fpga_wr_fn,
+       ngcc_fpga_post_config_fn
+};
+
+xilinx_desc fpga[CONFIG_FPGA_COUNT] = {
+       XILINX_XC3S1200E_DESC(
+#ifdef USE_SP_CODE
+               slave_parallel,
+#else
+               slave_serial,
+#endif
+               (void *)&pmc440_fpga_fns,
+               0),
+       XILINX_XC2S200_DESC(
+               slave_serial,
+               (void *)&ngcc_fpga_fns,
+               0)
+};
+
+
+/*
+ * Set the active-low FPGA reset signal.
+ */
+void fpga_reset(int assert)
+{
+       debug("%s:%d: RESET ", __FUNCTION__, __LINE__);
+       if (assert) {
+               out_be32((void*)GPIO1_OR, in_be32((void*)GPIO1_OR) & ~GPIO1_FPGA_DATA);
+               debug("asserted\n");
+       } else {
+               out_be32((void*)GPIO1_OR, in_be32((void*)GPIO1_OR) | GPIO1_FPGA_DATA);
+               debug("deasserted\n");
+       }
+}
+
+
+/*
+ * Initialize the SelectMap interface.  We assume that the mode and the
+ * initial state of all of the port pins have already been set!
+ */
+void fpga_serialslave_init(void)
+{
+       debug("%s:%d: Initialize serial slave interface\n", __FUNCTION__,
+             __LINE__);
+       fpga_pgm_fn(false, false, 0);   /* make sure program pin is inactive */
+}
+
+
+/*
+ * Set the FPGA's active-low SelectMap program line to the specified level
+ */
+int fpga_pgm_fn(int assert, int flush, int cookie)
+{
+       debug("%s:%d: FPGA PROGRAM ",
+             __FUNCTION__, __LINE__);
+
+       if (assert) {
+               out_be32((void*)GPIO1_OR, in_be32((void*)GPIO1_OR) & ~GPIO1_FPGA_PRG);
+               debug("asserted\n");
+       } else {
+               out_be32((void*)GPIO1_OR, in_be32((void*)GPIO1_OR) | GPIO1_FPGA_PRG);
+               debug("deasserted\n");
+       }
+       return assert;
+}
+
+
+/*
+ * Test the state of the active-low FPGA INIT line.  Return 1 on INIT
+ * asserted (low).
+ */
+int fpga_init_fn(int cookie)
+{
+       if (in_be32((void*)GPIO1_IR) & GPIO1_FPGA_INIT)
+               return 0;
+       else
+               return 1;
+}
+
+#ifdef USE_SP_CODE
+int fpga_abort_fn(int cookie)
+{
+       return 0;
+}
+
+
+int fpga_cs_fn(int assert_cs, int flush, int cookie)
+{
+       return assert_cs;
+}
+
+
+int fpga_busy_fn(int cookie)
+{
+       return 1;
+}
+#endif
+
+
+/*
+ * Test the state of the active-high FPGA DONE pin
+ */
+int fpga_done_fn(int cookie)
+{
+       if (in_be32((void*)GPIO1_IR) & GPIO1_FPGA_DONE)
+               return 1;
+       else
+               return 0;
+}
+
+
+/*
+ * FPGA pre-configuration function. Just make sure that
+ * FPGA reset is asserted to keep the FPGA from starting up after
+ * configuration.
+ */
+int fpga_pre_config_fn(int cookie)
+{
+       debug("%s:%d: FPGA pre-configuration\n", __FUNCTION__, __LINE__);
+       fpga_reset(true);
+
+       /* release init# */
+       out_be32((void*)GPIO0_OR, in_be32((void*)GPIO0_OR) | GPIO0_FPGA_FORCEINIT);
+       /* disable PLD IOs */
+       out_be32((void*)GPIO1_OR, in_be32((void*)GPIO1_OR) | GPIO1_IOEN_N);
+       return 0;
+}
+
+
+/*
+ * FPGA post configuration function. Blip the FPGA reset line and then see if
+ * the FPGA appears to be running.
+ */
+int fpga_post_config_fn(int cookie)
+{
+       pmc440_fpga_t *fpga = (pmc440_fpga_t *)FPGA_BA;
+       int rc=0;
+       char *s;
+
+       debug("%s:%d: FPGA post configuration\n", __FUNCTION__, __LINE__);
+
+       /* enable PLD0..7 pins */
+       out_be32((void*)GPIO1_OR, in_be32((void*)GPIO1_OR) & ~GPIO1_IOEN_N);
+
+       fpga_reset(true);
+       udelay (100);
+       fpga_reset(false);
+       udelay (100);
+
+       FPGA_OUT32(&fpga->status, (gd->board_type << STATUS_HWREV_SHIFT) & STATUS_HWREV_MASK);
+
+       /* NGCC/CANDES only: enable ledlink */
+       if ((s = getenv("bd_type")) &&
+           ((!strcmp(s, "ngcc")) || (!strcmp(s, "candes"))))
+               FPGA_SETBITS(&fpga->ctrla, 0x29f8c000);
+
+       return rc;
+}
+
+
+int fpga_clk_fn(int assert_clk, int flush, int cookie)
+{
+       if (assert_clk)
+               out_be32((void*)GPIO1_OR, in_be32((void*)GPIO1_OR) | GPIO1_FPGA_CLK);
+       else
+               out_be32((void*)GPIO1_OR, in_be32((void*)GPIO1_OR) & ~GPIO1_FPGA_CLK);
+
+       return assert_clk;
+}
+
+
+int fpga_wr_fn(int assert_write, int flush, int cookie)
+{
+       if (assert_write)
+               out_be32((void*)GPIO1_OR, in_be32((void*)GPIO1_OR) | GPIO1_FPGA_DATA);
+       else
+               out_be32((void*)GPIO1_OR, in_be32((void*)GPIO1_OR) & ~GPIO1_FPGA_DATA);
+
+       return assert_write;
+}
+
+#ifdef USE_SP_CODE
+int fpga_wdata_fn(uchar data, int flush, int cookie)
+{
+       uchar val = data;
+       ulong or = in_be32((void*)GPIO1_OR);
+       int i = 7;
+       do {
+               /* Write data */
+               if (val & 0x80)
+                       or = (or & ~GPIO1_FPGA_CLK) | GPIO1_FPGA_DATA;
+               else
+                       or = or & ~(GPIO1_FPGA_CLK | GPIO1_FPGA_DATA);
+
+               out_be32((void*)GPIO1_OR, or);
+
+               /* Assert the clock */
+               or |= GPIO1_FPGA_CLK;
+               out_be32((void*)GPIO1_OR, or);
+               val <<= 1;
+               i --;
+       } while (i > 0);
+
+       /* Write last data bit (the 8th clock comes from the sp_load() code */
+       if (val & 0x80)
+               or = (or & ~GPIO1_FPGA_CLK) | GPIO1_FPGA_DATA;
+       else
+               or = or & ~(GPIO1_FPGA_CLK | GPIO1_FPGA_DATA);
+
+       out_be32((void*)GPIO1_OR, or);
+
+       return 0;
+}
+#endif
+
+#define NGCC_FPGA_PRG  CLOCK_EN
+#define NGCC_FPGA_DATA RESET_OUT
+#define NGCC_FPGA_DONE CLOCK_IN
+#define NGCC_FPGA_INIT IRIGB_R_IN
+#define NGCC_FPGA_CLK  CLOCK_OUT
+
+void ngcc_fpga_serialslave_init(void)
+{
+       debug("%s:%d: Initialize serial slave interface\n",
+             __FUNCTION__, __LINE__);
+
+       /* make sure program pin is inactive */
+       ngcc_fpga_pgm_fn(false, false, 0);
+}
+
+/*
+ * Set the active-low FPGA reset signal.
+ */
+void ngcc_fpga_reset(int assert)
+{
+       debug("%s:%d: RESET ", __FUNCTION__, __LINE__);
+
+       if (assert) {
+               FPGA_CLRBITS(NGCC_CTRL_BASE, NGCC_CTRL_FPGARST_N);
+               debug("asserted\n");
+       } else {
+               FPGA_SETBITS(NGCC_CTRL_BASE, NGCC_CTRL_FPGARST_N);
+               debug("deasserted\n");
+       }
+}
+
+
+/*
+ * Set the FPGA's active-low SelectMap program line to the specified level
+ */
+int ngcc_fpga_pgm_fn(int assert, int flush, int cookie)
+{
+       pmc440_fpga_t *fpga = (pmc440_fpga_t *)FPGA_BA;
+
+       debug("%s:%d: FPGA PROGRAM ", __FUNCTION__, __LINE__);
+
+       if (assert) {
+               FPGA_CLRBITS(&fpga->ctrla, NGCC_FPGA_PRG);
+               debug("asserted\n");
+       } else {
+               FPGA_SETBITS(&fpga->ctrla, NGCC_FPGA_PRG);
+               debug("deasserted\n");
+       }
+
+       return assert;
+}
+
+
+/*
+ * Test the state of the active-low FPGA INIT line.  Return 1 on INIT
+ * asserted (low).
+ */
+int ngcc_fpga_init_fn(int cookie)
+{
+       pmc440_fpga_t *fpga = (pmc440_fpga_t *)FPGA_BA;
+
+       debug("%s:%d: INIT check... ", __FUNCTION__, __LINE__);
+       if (FPGA_IN32(&fpga->status) & NGCC_FPGA_INIT) {
+               debug("high\n");
+               return 0;
+       } else {
+               debug("low\n");
+               return 1;
+       }
+}
+
+
+/*
+ * Test the state of the active-high FPGA DONE pin
+ */
+int ngcc_fpga_done_fn(int cookie)
+{
+       pmc440_fpga_t *fpga = (pmc440_fpga_t *)FPGA_BA;
+
+       debug("%s:%d: DONE check... ", __FUNCTION__, __LINE__);
+       if (FPGA_IN32(&fpga->status) & NGCC_FPGA_DONE) {
+               debug("DONE high\n");
+               return 1;
+       } else {
+               debug("low\n");
+               return 0;
+       }
+}
+
+
+/*
+ * FPGA pre-configuration function.
+ */
+int ngcc_fpga_pre_config_fn(int cookie)
+{
+       pmc440_fpga_t *fpga = (pmc440_fpga_t *)FPGA_BA;
+       debug("%s:%d: FPGA pre-configuration\n", __FUNCTION__, __LINE__);
+
+       ngcc_fpga_reset(true);
+       FPGA_CLRBITS(&fpga->ctrla, 0xfffffe00);
+
+       ngcc_fpga_reset(true);
+       return 0;
+}
+
+
+/*
+ * FPGA post configuration function. Blip the FPGA reset line and then see if
+ * the FPGA appears to be running.
+ */
+int ngcc_fpga_post_config_fn(int cookie)
+{
+       pmc440_fpga_t *fpga = (pmc440_fpga_t *)FPGA_BA;
+
+       debug("%s:%d: NGCC FPGA post configuration\n", __FUNCTION__, __LINE__);
+
+       udelay (100);
+       ngcc_fpga_reset(false);
+
+       FPGA_SETBITS(&fpga->ctrla, 0x29f8c000);
+
+       return 0;
+}
+
+
+int ngcc_fpga_clk_fn(int assert_clk, int flush, int cookie)
+{
+       pmc440_fpga_t *fpga = (pmc440_fpga_t *)FPGA_BA;
+
+       if (assert_clk)
+               FPGA_SETBITS(&fpga->ctrla, NGCC_FPGA_CLK);
+       else
+               FPGA_CLRBITS(&fpga->ctrla, NGCC_FPGA_CLK);
+
+       return assert_clk;
+}
+
+
+int ngcc_fpga_wr_fn(int assert_write, int flush, int cookie)
+{
+       pmc440_fpga_t *fpga = (pmc440_fpga_t *)FPGA_BA;
+
+       if (assert_write)
+               FPGA_SETBITS(&fpga->ctrla, NGCC_FPGA_DATA);
+       else
+               FPGA_CLRBITS(&fpga->ctrla, NGCC_FPGA_DATA);
+
+       return assert_write;
+}
+
+
+/*
+ * Initialize the fpga.  Return 1 on success, 0 on failure.
+ */
+int pmc440_init_fpga(void)
+{
+       char *s;
+
+       debug("%s:%d: Initialize FPGA interface\n",
+             __FUNCTION__, __LINE__);
+       fpga_init();
+
+       fpga_serialslave_init ();
+       debug("%s:%d: Adding fpga 0\n", __FUNCTION__, __LINE__);
+       fpga_add (fpga_xilinx, &fpga[0]);
+
+       /* NGCC only */
+       if ((s = getenv("bd_type")) && !strcmp(s, "ngcc")) {
+               ngcc_fpga_serialslave_init ();
+               debug("%s:%d: Adding fpga 1\n", __FUNCTION__, __LINE__);
+               fpga_add (fpga_xilinx, &fpga[1]);
+       }
+
+       return 0;
+}
+#endif /* CONFIG_FPGA */