/* * (C) Copyright 2006 * Heiko Schocher, DENX Software Engineering, hs@denx.de * * SPDX-License-Identifier: GPL-2.0+ */ /* * Altera FPGA configuration support for the ALPR computer from prodrive */ #include <common.h> #include <altera.h> #include <ACEX1K.h> #include <command.h> #include <asm/processor.h> #include <asm/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) do { \ regval = in32(reg); \ regval &= ~(0x80000000 >> bit); \ out32(reg, regval); \ } while (0) #define SET_GPIO_REG_1(reg, bit) do { \ regval = in32(reg); \ regval |= (0x80000000 >> bit); \ out32(reg, regval); \ } while (0) #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 >> CONFIG_SYS_GPIO_PROG_EN) #define FPGA_CONFIG (0x80000000 >> CONFIG_SYS_GPIO_CONFIG) #define FPGA_DATA (0x80000000 >> CONFIG_SYS_GPIO_DATA) #define FPGA_CLK (0x80000000 >> CONFIG_SYS_GPIO_CLK) #define OLD_VAL (FPGA_PRG | FPGA_CONFIG) #define SET_FPGA(data) out32(GPIO0_OR, data) #define FPGA_WRITE_1 do { \ SET_FPGA(OLD_VAL | 0 | FPGA_DATA); /* set data to 1 */ \ SET_FPGA(OLD_VAL | FPGA_CLK | FPGA_DATA); /* set data to 1 */ \ } while (0) #define FPGA_WRITE_0 do { \ SET_FPGA(OLD_VAL | 0 | 0); /* set data to 0 */ \ SET_FPGA(OLD_VAL | FPGA_CLK | 0); /* set data to 1 */ \ } while (0) /* Plattforminitializations */ /* Here we have to set the FPGA Chain */ /* PROGRAM_PROG_EN = HIGH */ /* PROGRAM_SEL_DPR = LOW */ int fpga_pre_fn(int cookie) { /* Enable the FPGA Chain */ SET_GPIO_REG_1(GPIO0_TCR, CONFIG_SYS_GPIO_PROG_EN); SET_GPIO_REG_0(GPIO0_ODR, CONFIG_SYS_GPIO_PROG_EN); SET_GPIO_1(CONFIG_SYS_GPIO_PROG_EN); SET_GPIO_REG_1(GPIO0_TCR, CONFIG_SYS_GPIO_SEL_DPR); SET_GPIO_REG_0(GPIO0_ODR, CONFIG_SYS_GPIO_SEL_DPR); SET_GPIO_0((CONFIG_SYS_GPIO_SEL_DPR)); /* initialize the GPIO Pins */ /* output */ SET_GPIO_0(CONFIG_SYS_GPIO_CLK); SET_GPIO_REG_1(GPIO0_TCR, CONFIG_SYS_GPIO_CLK); SET_GPIO_REG_0(GPIO0_ODR, CONFIG_SYS_GPIO_CLK); /* output */ SET_GPIO_0(CONFIG_SYS_GPIO_DATA); SET_GPIO_REG_1(GPIO0_TCR, CONFIG_SYS_GPIO_DATA); SET_GPIO_REG_0(GPIO0_ODR, CONFIG_SYS_GPIO_DATA); /* First we set STATUS to 0 then as an input */ SET_GPIO_REG_1(GPIO0_TCR, CONFIG_SYS_GPIO_STATUS); SET_GPIO_REG_0(GPIO0_ODR, CONFIG_SYS_GPIO_STATUS); SET_GPIO_0(CONFIG_SYS_GPIO_STATUS); SET_GPIO_REG_0(GPIO0_TCR, CONFIG_SYS_GPIO_STATUS); SET_GPIO_REG_0(GPIO0_ODR, CONFIG_SYS_GPIO_STATUS); /* output */ SET_GPIO_REG_1(GPIO0_TCR, CONFIG_SYS_GPIO_CONFIG); SET_GPIO_REG_0(GPIO0_ODR, CONFIG_SYS_GPIO_CONFIG); SET_GPIO_0(CONFIG_SYS_GPIO_CONFIG); /* input */ SET_GPIO_0(CONFIG_SYS_GPIO_CON_DON); SET_GPIO_REG_0(GPIO0_TCR, CONFIG_SYS_GPIO_CON_DON); SET_GPIO_REG_0(GPIO0_ODR, CONFIG_SYS_GPIO_CON_DON); /* CONFIG = 0 STATUS = 0 -> FPGA in reset state */ SET_GPIO_0(CONFIG_SYS_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(CONFIG_SYS_GPIO_CONFIG); else SET_GPIO_0(CONFIG_SYS_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 >> CONFIG_SYS_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 >> CONFIG_SYS_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(const 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 CONFIG_SYS_FPGA_PROG_FEEDBACK if (bytecount % len_40 == 0) { putc('.'); /* let them know we are alive */ #ifdef CONFIG_SYS_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((CONFIG_SYS_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\n", __func__, __LINE__); fpga_init(); for (i = 0; i < CONFIG_FPGA_COUNT; i++) { PRINTF("%s:%d: Adding fpga %d\n", __func__, __LINE__, i); fpga_add(fpga_altera, &fpga[i]); } return 1; } #endif