📄 fpga.c
字号:
/* * (C) Copyright 2007 * Matthias Fuchs, esd gmbh, matthias.fuchs@esd-electronics.com. * * See file CREDITS for list of people who contributed to this * project. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, * MA 02111-1307 USA */#include <common.h>#include <asm/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_CODEXilinx_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,};#elseXilinx_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,};#endifXilinx_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_CODEint 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 only: enable ledlink */ if ((s = getenv("bd_type")) && !strcmp(s, "ngcc")) 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_CODEint 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_OUTvoid 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 (relocation offset = 0x%.8lx)\n", __FUNCTION__, __LINE__, gd->reloc_off); fpga_init(gd->reloc_off); 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 */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -