blob: 3133f942733a6d586ec09e4a273bd15886fdfe02 [file] [log] [blame]
Stefan Roese899620c2006-08-15 14:22:35 +02001/*
2 * (C) Copyright 2006
3 * Heiko Schocher, DENX Software Engineering, hs@denx.de
4 *
Wolfgang Denk1a459662013-07-08 09:37:19 +02005 * SPDX-License-Identifier: GPL-2.0+
Stefan Roese899620c2006-08-15 14:22:35 +02006 */
7
8/*
9 * Altera FPGA configuration support for the ALPR computer from prodrive
10 */
11
12#include <common.h>
13#include <altera.h>
14#include <ACEX1K.h>
15#include <command.h>
Peter Tyser61f2b382010-04-12 22:28:07 -050016#include <asm/processor.h>
Stefan Roeseb36df562010-09-09 19:18:00 +020017#include <asm/ppc440.h>
Stefan Roese899620c2006-08-15 14:22:35 +020018#include "fpga.h"
19
20DECLARE_GLOBAL_DATA_PTR;
21
Stefan Roese1c2ce222006-11-27 14:12:17 +010022#if defined(CONFIG_FPGA)
Stefan Roese899620c2006-08-15 14:22:35 +020023
24#ifdef FPGA_DEBUG
Wolfgang Denk8298fd22011-09-05 12:52:21 +020025#define PRINTF(fmt, args...) printf(fmt , ##args)
Stefan Roese899620c2006-08-15 14:22:35 +020026#else
Wolfgang Denk8298fd22011-09-05 12:52:21 +020027#define PRINTF(fmt, args...)
Stefan Roese899620c2006-08-15 14:22:35 +020028#endif
29
Stefan Roese1c2ce222006-11-27 14:12:17 +010030static unsigned long regval;
Stefan Roese899620c2006-08-15 14:22:35 +020031
Wolfgang Denk8298fd22011-09-05 12:52:21 +020032#define SET_GPIO_REG_0(reg, bit) do { \
Stefan Roese1c2ce222006-11-27 14:12:17 +010033 regval = in32(reg); \
34 regval &= ~(0x80000000 >> bit); \
35 out32(reg, regval); \
Wolfgang Denk8298fd22011-09-05 12:52:21 +020036 } while (0)
Stefan Roese899620c2006-08-15 14:22:35 +020037
Wolfgang Denk8298fd22011-09-05 12:52:21 +020038#define SET_GPIO_REG_1(reg, bit) do { \
Stefan Roese1c2ce222006-11-27 14:12:17 +010039 regval = in32(reg); \
40 regval |= (0x80000000 >> bit); \
41 out32(reg, regval); \
Wolfgang Denk8298fd22011-09-05 12:52:21 +020042 } while (0)
Stefan Roese899620c2006-08-15 14:22:35 +020043
Stefan Roese1c2ce222006-11-27 14:12:17 +010044#define SET_GPIO_0(bit) SET_GPIO_REG_0(GPIO0_OR, bit)
45#define SET_GPIO_1(bit) SET_GPIO_REG_1(GPIO0_OR, bit)
Stefan Roese899620c2006-08-15 14:22:35 +020046
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +020047#define FPGA_PRG (0x80000000 >> CONFIG_SYS_GPIO_PROG_EN)
48#define FPGA_CONFIG (0x80000000 >> CONFIG_SYS_GPIO_CONFIG)
49#define FPGA_DATA (0x80000000 >> CONFIG_SYS_GPIO_DATA)
50#define FPGA_CLK (0x80000000 >> CONFIG_SYS_GPIO_CLK)
Stefan Roese1c2ce222006-11-27 14:12:17 +010051#define OLD_VAL (FPGA_PRG | FPGA_CONFIG)
Stefan Roese899620c2006-08-15 14:22:35 +020052
Stefan Roese1c2ce222006-11-27 14:12:17 +010053#define SET_FPGA(data) out32(GPIO0_OR, data)
Stefan Roese899620c2006-08-15 14:22:35 +020054
Wolfgang Denk8298fd22011-09-05 12:52:21 +020055#define FPGA_WRITE_1 do { \
56 SET_FPGA(OLD_VAL | 0 | FPGA_DATA); /* set data to 1 */ \
57 SET_FPGA(OLD_VAL | FPGA_CLK | FPGA_DATA); /* set data to 1 */ \
58} while (0)
Stefan Roese899620c2006-08-15 14:22:35 +020059
Wolfgang Denk8298fd22011-09-05 12:52:21 +020060#define FPGA_WRITE_0 do { \
61 SET_FPGA(OLD_VAL | 0 | 0); /* set data to 0 */ \
62 SET_FPGA(OLD_VAL | FPGA_CLK | 0); /* set data to 1 */ \
63} while (0)
Stefan Roese899620c2006-08-15 14:22:35 +020064
65/* Plattforminitializations */
66/* Here we have to set the FPGA Chain */
67/* PROGRAM_PROG_EN = HIGH */
68/* PROGRAM_SEL_DPR = LOW */
Wolfgang Denk8298fd22011-09-05 12:52:21 +020069int fpga_pre_fn(int cookie)
Stefan Roese899620c2006-08-15 14:22:35 +020070{
Stefan Roese899620c2006-08-15 14:22:35 +020071 /* Enable the FPGA Chain */
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +020072 SET_GPIO_REG_1(GPIO0_TCR, CONFIG_SYS_GPIO_PROG_EN);
73 SET_GPIO_REG_0(GPIO0_ODR, CONFIG_SYS_GPIO_PROG_EN);
74 SET_GPIO_1(CONFIG_SYS_GPIO_PROG_EN);
75 SET_GPIO_REG_1(GPIO0_TCR, CONFIG_SYS_GPIO_SEL_DPR);
76 SET_GPIO_REG_0(GPIO0_ODR, CONFIG_SYS_GPIO_SEL_DPR);
77 SET_GPIO_0((CONFIG_SYS_GPIO_SEL_DPR));
Stefan Roese899620c2006-08-15 14:22:35 +020078
Stefan Roese1c2ce222006-11-27 14:12:17 +010079 /* initialize the GPIO Pins */
Stefan Roese899620c2006-08-15 14:22:35 +020080 /* output */
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +020081 SET_GPIO_0(CONFIG_SYS_GPIO_CLK);
82 SET_GPIO_REG_1(GPIO0_TCR, CONFIG_SYS_GPIO_CLK);
83 SET_GPIO_REG_0(GPIO0_ODR, CONFIG_SYS_GPIO_CLK);
Stefan Roese899620c2006-08-15 14:22:35 +020084
85 /* output */
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +020086 SET_GPIO_0(CONFIG_SYS_GPIO_DATA);
87 SET_GPIO_REG_1(GPIO0_TCR, CONFIG_SYS_GPIO_DATA);
88 SET_GPIO_REG_0(GPIO0_ODR, CONFIG_SYS_GPIO_DATA);
Stefan Roese899620c2006-08-15 14:22:35 +020089
90 /* First we set STATUS to 0 then as an input */
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +020091 SET_GPIO_REG_1(GPIO0_TCR, CONFIG_SYS_GPIO_STATUS);
92 SET_GPIO_REG_0(GPIO0_ODR, CONFIG_SYS_GPIO_STATUS);
93 SET_GPIO_0(CONFIG_SYS_GPIO_STATUS);
94 SET_GPIO_REG_0(GPIO0_TCR, CONFIG_SYS_GPIO_STATUS);
95 SET_GPIO_REG_0(GPIO0_ODR, CONFIG_SYS_GPIO_STATUS);
Stefan Roese899620c2006-08-15 14:22:35 +020096
97 /* output */
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +020098 SET_GPIO_REG_1(GPIO0_TCR, CONFIG_SYS_GPIO_CONFIG);
99 SET_GPIO_REG_0(GPIO0_ODR, CONFIG_SYS_GPIO_CONFIG);
100 SET_GPIO_0(CONFIG_SYS_GPIO_CONFIG);
Stefan Roese899620c2006-08-15 14:22:35 +0200101
102 /* input */
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200103 SET_GPIO_0(CONFIG_SYS_GPIO_CON_DON);
104 SET_GPIO_REG_0(GPIO0_TCR, CONFIG_SYS_GPIO_CON_DON);
105 SET_GPIO_REG_0(GPIO0_ODR, CONFIG_SYS_GPIO_CON_DON);
Stefan Roese899620c2006-08-15 14:22:35 +0200106
107 /* CONFIG = 0 STATUS = 0 -> FPGA in reset state */
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200108 SET_GPIO_0(CONFIG_SYS_GPIO_CONFIG);
Stefan Roese899620c2006-08-15 14:22:35 +0200109 return FPGA_SUCCESS;
110}
111
112/* Set the state of CONFIG Pin */
Wolfgang Denk8298fd22011-09-05 12:52:21 +0200113int fpga_config_fn(int assert_config, int flush, int cookie)
Stefan Roese899620c2006-08-15 14:22:35 +0200114{
Wolfgang Denk8298fd22011-09-05 12:52:21 +0200115 if (assert_config)
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200116 SET_GPIO_1(CONFIG_SYS_GPIO_CONFIG);
Wolfgang Denk8298fd22011-09-05 12:52:21 +0200117 else
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200118 SET_GPIO_0(CONFIG_SYS_GPIO_CONFIG);
Wolfgang Denk8298fd22011-09-05 12:52:21 +0200119
Stefan Roese899620c2006-08-15 14:22:35 +0200120 return FPGA_SUCCESS;
121}
122
123/* Returns the state of STATUS Pin */
Wolfgang Denk8298fd22011-09-05 12:52:21 +0200124int fpga_status_fn(int cookie)
Stefan Roese899620c2006-08-15 14:22:35 +0200125{
126 unsigned long reg;
127
128 reg = in32(GPIO0_IR);
Wolfgang Denk8298fd22011-09-05 12:52:21 +0200129 if (reg & (0x80000000 >> CONFIG_SYS_GPIO_STATUS)) {
Stefan Roese899620c2006-08-15 14:22:35 +0200130 PRINTF("STATUS = HIGH\n");
131 return FPGA_FAIL;
132 }
133 PRINTF("STATUS = LOW\n");
134 return FPGA_SUCCESS;
135}
136
137/* Returns the state of CONF_DONE Pin */
Wolfgang Denk8298fd22011-09-05 12:52:21 +0200138int fpga_done_fn(int cookie)
Stefan Roese899620c2006-08-15 14:22:35 +0200139{
140 unsigned long reg;
141 reg = in32(GPIO0_IR);
Wolfgang Denk8298fd22011-09-05 12:52:21 +0200142 if (reg & (0x80000000 >> CONFIG_SYS_GPIO_CON_DON)) {
Stefan Roese899620c2006-08-15 14:22:35 +0200143 PRINTF("CONF_DON = HIGH\n");
144 return FPGA_FAIL;
145 }
146 PRINTF("CONF_DON = LOW\n");
147 return FPGA_SUCCESS;
148}
149
150/* writes the complete buffer to the FPGA
Stefan Roese1c2ce222006-11-27 14:12:17 +0100151 writing the complete buffer in one function is much faster,
Stefan Roese899620c2006-08-15 14:22:35 +0200152 then calling it for every bit */
Wolfgang Denk8298fd22011-09-05 12:52:21 +0200153int fpga_write_fn(const void *buf, size_t len, int flush, int cookie)
Stefan Roese899620c2006-08-15 14:22:35 +0200154{
155 size_t bytecount = 0;
156 unsigned char *data = (unsigned char *) buf;
Wolfgang Denk8298fd22011-09-05 12:52:21 +0200157 unsigned char val = 0;
Stefan Roese899620c2006-08-15 14:22:35 +0200158 int i;
Stefan Roese1c2ce222006-11-27 14:12:17 +0100159 int len_40 = len / 40;
Stefan Roese899620c2006-08-15 14:22:35 +0200160
161 while (bytecount < len) {
Stefan Roese1c2ce222006-11-27 14:12:17 +0100162 val = data[bytecount++];
Stefan Roese899620c2006-08-15 14:22:35 +0200163 i = 8;
164 do {
Wolfgang Denk8298fd22011-09-05 12:52:21 +0200165 if (val & 0x01)
Stefan Roese899620c2006-08-15 14:22:35 +0200166 FPGA_WRITE_1;
Wolfgang Denk8298fd22011-09-05 12:52:21 +0200167 else
Stefan Roese899620c2006-08-15 14:22:35 +0200168 FPGA_WRITE_0;
Wolfgang Denk8298fd22011-09-05 12:52:21 +0200169
Stefan Roese899620c2006-08-15 14:22:35 +0200170 val >>= 1;
Wolfgang Denk8298fd22011-09-05 12:52:21 +0200171 i--;
Stefan Roese899620c2006-08-15 14:22:35 +0200172 } while (i > 0);
173
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200174#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
Stefan Roese1c2ce222006-11-27 14:12:17 +0100175 if (bytecount % len_40 == 0) {
Wolfgang Denk8298fd22011-09-05 12:52:21 +0200176 putc('.'); /* let them know we are alive */
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200177#ifdef CONFIG_SYS_FPGA_CHECK_CTRLC
Wolfgang Denk8298fd22011-09-05 12:52:21 +0200178 if (ctrlc())
Stefan Roese1c2ce222006-11-27 14:12:17 +0100179 return FPGA_FAIL;
180#endif
181 }
Stefan Roese899620c2006-08-15 14:22:35 +0200182#endif
183 }
184 return FPGA_SUCCESS;
185}
186
187/* called, when programming is aborted */
Wolfgang Denk8298fd22011-09-05 12:52:21 +0200188int fpga_abort_fn(int cookie)
Stefan Roese899620c2006-08-15 14:22:35 +0200189{
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200190 SET_GPIO_1((CONFIG_SYS_GPIO_SEL_DPR));
Stefan Roese899620c2006-08-15 14:22:35 +0200191 return FPGA_SUCCESS;
192}
193
194/* called, when programming was succesful */
Wolfgang Denk8298fd22011-09-05 12:52:21 +0200195int fpga_post_fn(int cookie)
Stefan Roese899620c2006-08-15 14:22:35 +0200196{
Wolfgang Denk8298fd22011-09-05 12:52:21 +0200197 return fpga_abort_fn(cookie);
Stefan Roese899620c2006-08-15 14:22:35 +0200198}
199
200/* Note that these are pointers to code that is in Flash. They will be
201 * relocated at runtime.
202 */
203Altera_CYC2_Passive_Serial_fns fpga_fns = {
204 fpga_pre_fn,
205 fpga_config_fn,
206 fpga_status_fn,
207 fpga_done_fn,
208 fpga_write_fn,
209 fpga_abort_fn,
210 fpga_post_fn
211};
212
213Altera_desc fpga[CONFIG_FPGA_COUNT] = {
214 {Altera_CYC2,
215 passive_serial,
216 Altera_EP2C35_SIZE,
217 (void *) &fpga_fns,
218 NULL,
219 0}
220};
221
222/*
223 * Initialize the fpga. Return 1 on success, 0 on failure.
224 */
Wolfgang Denk8298fd22011-09-05 12:52:21 +0200225int alpr_fpga_init(void)
Stefan Roese899620c2006-08-15 14:22:35 +0200226{
227 int i;
228
Wolfgang Denk8298fd22011-09-05 12:52:21 +0200229 PRINTF("%s:%d: Initialize FPGA interface\n", __func__, __LINE__);
230 fpga_init();
Stefan Roese899620c2006-08-15 14:22:35 +0200231
232 for (i = 0; i < CONFIG_FPGA_COUNT; i++) {
Wolfgang Denk8298fd22011-09-05 12:52:21 +0200233 PRINTF("%s:%d: Adding fpga %d\n", __func__, __LINE__, i);
234 fpga_add(fpga_altera, &fpga[i]);
Stefan Roese899620c2006-08-15 14:22:35 +0200235 }
236 return 1;
237}
238
239#endif