diff options
Diffstat (limited to 'board/prodrive/alpr/fpga.c')
-rw-r--r-- | board/prodrive/alpr/fpga.c | 257 |
1 files changed, 257 insertions, 0 deletions
diff --git a/board/prodrive/alpr/fpga.c b/board/prodrive/alpr/fpga.c new file mode 100644 index 0000000000..e94360f814 --- /dev/null +++ b/board/prodrive/alpr/fpga.c @@ -0,0 +1,257 @@ +/* + * (C) Copyright 2006 + * Heiko Schocher, DENX Software Engineering, hs@denx.de + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + */ + +/* + * Altera FPGA configuration support for the ALPR computer from prodrive + */ + +#include <common.h> +#include <altera.h> +#include <ACEX1K.h> +#include <command.h> +#include <asm-ppc/processor.h> +#include <ppc440.h> +#include "fpga.h" + +DECLARE_GLOBAL_DATA_PTR; + +#if defined(CONFIG_FPGA) + +#ifdef FPGA_DEBUG +#define PRINTF(fmt,args...) printf (fmt ,##args) +#else +#define PRINTF(fmt,args...) +#endif + +static unsigned long regval; + +#define SET_GPIO_REG_0(reg, bit) { \ + regval = in32(reg); \ + regval &= ~(0x80000000 >> bit); \ + out32(reg, regval); \ + } + +#define SET_GPIO_REG_1(reg, bit) { \ + regval = in32(reg); \ + regval |= (0x80000000 >> bit); \ + out32(reg, regval); \ + } + +#define SET_GPIO_0(bit) SET_GPIO_REG_0(GPIO0_OR, bit) +#define SET_GPIO_1(bit) SET_GPIO_REG_1(GPIO0_OR, bit) + +#define FPGA_PRG (0x80000000 >> CFG_GPIO_PROG_EN) +#define FPGA_CONFIG (0x80000000 >> CFG_GPIO_CONFIG) +#define FPGA_DATA (0x80000000 >> CFG_GPIO_DATA) +#define FPGA_CLK (0x80000000 >> CFG_GPIO_CLK) +#define OLD_VAL (FPGA_PRG | FPGA_CONFIG) + +#define SET_FPGA(data) out32(GPIO0_OR, data) + +#define FPGA_WRITE_1 { \ + SET_FPGA(OLD_VAL | 0 | FPGA_DATA); /* set data to 1 */ \ + SET_FPGA(OLD_VAL | FPGA_CLK | FPGA_DATA);} /* set data to 1 */ + +#define FPGA_WRITE_0 { \ + SET_FPGA(OLD_VAL | 0 | 0 ); /* set data to 0 */ \ + SET_FPGA(OLD_VAL | FPGA_CLK | 0 );} /* set data to 1 */ + +/* Plattforminitializations */ +/* Here we have to set the FPGA Chain */ +/* PROGRAM_PROG_EN = HIGH */ +/* PROGRAM_SEL_DPR = LOW */ +int fpga_pre_fn (int cookie) +{ + unsigned long reg; + + reg = in32(GPIO0_IR); + /* Enable the FPGA Chain */ + SET_GPIO_REG_1(GPIO0_TCR, CFG_GPIO_PROG_EN); + SET_GPIO_REG_0(GPIO0_ODR, CFG_GPIO_PROG_EN); + SET_GPIO_1(CFG_GPIO_PROG_EN); + SET_GPIO_REG_1(GPIO0_TCR, CFG_GPIO_SEL_DPR); + SET_GPIO_REG_0(GPIO0_ODR, CFG_GPIO_SEL_DPR); + SET_GPIO_0((CFG_GPIO_SEL_DPR)); + + /* initialize the GPIO Pins */ + /* output */ + SET_GPIO_0(CFG_GPIO_CLK); + SET_GPIO_REG_1(GPIO0_TCR, CFG_GPIO_CLK); + SET_GPIO_REG_0(GPIO0_ODR, CFG_GPIO_CLK); + + /* output */ + SET_GPIO_0(CFG_GPIO_DATA); + SET_GPIO_REG_1(GPIO0_TCR, CFG_GPIO_DATA); + SET_GPIO_REG_0(GPIO0_ODR, CFG_GPIO_DATA); + + /* First we set STATUS to 0 then as an input */ + SET_GPIO_REG_1(GPIO0_TCR, CFG_GPIO_STATUS); + SET_GPIO_REG_0(GPIO0_ODR, CFG_GPIO_STATUS); + SET_GPIO_0(CFG_GPIO_STATUS); + SET_GPIO_REG_0(GPIO0_TCR, CFG_GPIO_STATUS); + SET_GPIO_REG_0(GPIO0_ODR, CFG_GPIO_STATUS); + + /* output */ + SET_GPIO_REG_1(GPIO0_TCR, CFG_GPIO_CONFIG); + SET_GPIO_REG_0(GPIO0_ODR, CFG_GPIO_CONFIG); + SET_GPIO_0(CFG_GPIO_CONFIG); + + /* input */ + SET_GPIO_0(CFG_GPIO_CON_DON); + SET_GPIO_REG_0(GPIO0_TCR, CFG_GPIO_CON_DON); + SET_GPIO_REG_0(GPIO0_ODR, CFG_GPIO_CON_DON); + + /* CONFIG = 0 STATUS = 0 -> FPGA in reset state */ + SET_GPIO_0(CFG_GPIO_CONFIG); + return FPGA_SUCCESS; +} + +/* Set the state of CONFIG Pin */ +int fpga_config_fn (int assert_config, int flush, int cookie) +{ + if (assert_config) { + SET_GPIO_1(CFG_GPIO_CONFIG); + } else { + SET_GPIO_0(CFG_GPIO_CONFIG); + } + return FPGA_SUCCESS; +} + +/* Returns the state of STATUS Pin */ +int fpga_status_fn (int cookie) +{ + unsigned long reg; + + reg = in32(GPIO0_IR); + if (reg &= (0x80000000 >> CFG_GPIO_STATUS)) { + PRINTF("STATUS = HIGH\n"); + return FPGA_FAIL; + } + PRINTF("STATUS = LOW\n"); + return FPGA_SUCCESS; +} + +/* Returns the state of CONF_DONE Pin */ +int fpga_done_fn (int cookie) +{ + unsigned long reg; + reg = in32(GPIO0_IR); + if (reg &= (0x80000000 >> CFG_GPIO_CON_DON)) { + PRINTF("CONF_DON = HIGH\n"); + return FPGA_FAIL; + } + PRINTF("CONF_DON = LOW\n"); + return FPGA_SUCCESS; +} + +/* writes the complete buffer to the FPGA + writing the complete buffer in one function is much faster, + then calling it for every bit */ +int fpga_write_fn (void *buf, size_t len, int flush, int cookie) +{ + size_t bytecount = 0; + unsigned char *data = (unsigned char *) buf; + unsigned char val=0; + int i; + int len_40 = len / 40; + + while (bytecount < len) { + val = data[bytecount++]; + i = 8; + do { + if (val & 0x01) { + FPGA_WRITE_1; + } else { + FPGA_WRITE_0; + } + val >>= 1; + i --; + } while (i > 0); + +#ifdef CFG_FPGA_PROG_FEEDBACK + if (bytecount % len_40 == 0) { + putc ('.'); /* let them know we are alive */ +#ifdef CFG_FPGA_CHECK_CTRLC + if (ctrlc ()) + return FPGA_FAIL; +#endif + } +#endif + } + return FPGA_SUCCESS; +} + +/* called, when programming is aborted */ +int fpga_abort_fn (int cookie) +{ + SET_GPIO_1((CFG_GPIO_SEL_DPR)); + return FPGA_SUCCESS; +} + +/* called, when programming was succesful */ +int fpga_post_fn (int cookie) +{ + return fpga_abort_fn (cookie); +} + +/* Note that these are pointers to code that is in Flash. They will be + * relocated at runtime. + */ +Altera_CYC2_Passive_Serial_fns fpga_fns = { + fpga_pre_fn, + fpga_config_fn, + fpga_status_fn, + fpga_done_fn, + fpga_write_fn, + fpga_abort_fn, + fpga_post_fn +}; + +Altera_desc fpga[CONFIG_FPGA_COUNT] = { + {Altera_CYC2, + passive_serial, + Altera_EP2C35_SIZE, + (void *) &fpga_fns, + NULL, + 0} +}; + +/* + * Initialize the fpga. Return 1 on success, 0 on failure. + */ +int alpr_fpga_init (void) +{ + int i; + + PRINTF ("%s:%d: Initialize FPGA interface (relocation offset = 0x%.8lx)\n", __FUNCTION__, __LINE__, gd->reloc_off); + fpga_init (gd->reloc_off); + + for (i = 0; i < CONFIG_FPGA_COUNT; i++) { + PRINTF ("%s:%d: Adding fpga %d\n", __FUNCTION__, __LINE__, i); + fpga_add (fpga_altera, &fpga[i]); + } + return 1; +} + +#endif |