]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - board/prodrive/alpr/fpga.c
Add initial support for the ALPR board from Prodrive
[karo-tx-uboot.git] / board / prodrive / alpr / fpga.c
1 /*
2  * (C) Copyright 2006
3  * Heiko Schocher, DENX Software Engineering, hs@denx.de
4  *
5  * See file CREDITS for list of people who contributed to this
6  * project.
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License as
10  * published by the Free Software Foundation; either version 2 of
11  * the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
21  * MA 02111-1307 USA
22  *
23  */
24
25 /*
26  * Altera FPGA configuration support for the ALPR computer from prodrive
27  */
28
29 #include <common.h>
30 #include <altera.h>
31 #include <ACEX1K.h>
32 #include <command.h>
33 #include <asm-ppc/processor.h>
34 #include <ppc440.h>
35 #include "fpga.h"
36
37 DECLARE_GLOBAL_DATA_PTR;
38
39 #if (CONFIG_FPGA)
40
41 #ifdef FPGA_DEBUG
42 #define PRINTF(fmt,args...)     printf (fmt ,##args)
43 #else
44 #define PRINTF(fmt,args...)
45 #endif
46
47 static  unsigned long   regval;
48
49 #define SET_GPIO_REG_0(reg, bit) {\
50                                         regval = in32(reg);\
51                                         regval &= ~(0x80000000 >> bit);\
52                                         out32(reg, regval);\
53                                         }
54
55 #define SET_GPIO_REG_1(reg, bit) {\
56                                         regval = in32(reg);\
57                                         regval |= (0x80000000 >> bit);\
58                                         out32(reg, regval);\
59                                         }
60
61 #define GPIO_CLK_PIN                    0x00002000
62 #define GPIO_CLK_PIN_I                  0xffffdfff
63 #define GPIO_DAT_PIN                    0x00001000
64 #define GPIO_DAT_PIN_I                  0xffffefff
65 #define GPIO_CLKDAT_PIN_I               0xffffcfff
66
67 #define SET_GPIO_CLK_0                  out32(GPIO0_OR, in32(GPIO0_OR) & GPIO_CLK_PIN_I);
68 #define SET_GPIO_CLK_1                  out32(GPIO0_OR, in32(GPIO0_OR) | GPIO_CLK_PIN);
69 #define SET_GPIO_DAT_0                  out32(GPIO0_OR, in32(GPIO0_OR) & GPIO_DAT_PIN_I);
70 #define SET_GPIO_DAT_1                  out32(GPIO0_OR, in32(GPIO0_OR) | GPIO_DAT_PIN);
71
72 #define SET_GPIO_0(bit) SET_GPIO_REG_0(GPIO0_OR, bit)
73 #define SET_GPIO_1(bit) SET_GPIO_REG_1(GPIO0_OR, bit)
74
75 #define SET_GPIO_CLK_0_Z1               out32(GPIO0_OR, (in32(GPIO0_OR) & GPIO_CLK_PIN_I) | GPIO_DAT_PIN);
76 #define SET_GPIO_CLK_0_Z0               out32(GPIO0_OR, in32(GPIO0_OR) & GPIO_CLKDAT_PIN_I);
77
78 #define FPGA_WRITE_1 { \
79                         SET_GPIO_CLK_0_Z1\
80                         SET_GPIO_CLK_1}
81
82 #define FPGA_WRITE_0 { \
83                         SET_GPIO_CLK_0_Z0\
84                         SET_GPIO_CLK_1}
85
86 #define P_GP(reg) (reg & 0x00023f00)
87
88 /* Plattforminitializations */
89 /* Here we have to set the FPGA Chain */
90 /* PROGRAM_PROG_EN      = HIGH */
91 /* PROGRAM_SEL_DPR      = LOW */
92 int fpga_pre_fn (int cookie)
93 {
94         unsigned long   reg;
95
96         reg = in32(GPIO0_IR);
97         /* Enable the FPGA Chain */
98         SET_GPIO_REG_1(GPIO0_TCR, CFG_GPIO_PROG_EN);
99         SET_GPIO_REG_0(GPIO0_ODR, CFG_GPIO_PROG_EN);
100         SET_GPIO_1(CFG_GPIO_PROG_EN);
101         SET_GPIO_REG_1(GPIO0_TCR, CFG_GPIO_SEL_DPR);
102         SET_GPIO_REG_0(GPIO0_ODR, CFG_GPIO_SEL_DPR);
103         SET_GPIO_0((CFG_GPIO_SEL_DPR));
104
105         /* initialize the GPIO Pins */  
106         /* output */
107         SET_GPIO_0(CFG_GPIO_CLK);
108         SET_GPIO_REG_1(GPIO0_TCR, CFG_GPIO_CLK);
109         SET_GPIO_REG_0(GPIO0_ODR, CFG_GPIO_CLK);
110
111         /* output */
112         SET_GPIO_0(CFG_GPIO_DATA);
113         SET_GPIO_REG_1(GPIO0_TCR, CFG_GPIO_DATA);
114         SET_GPIO_REG_0(GPIO0_ODR, CFG_GPIO_DATA);
115
116         /* First we set STATUS to 0 then as an input */
117         SET_GPIO_REG_1(GPIO0_TCR, CFG_GPIO_STATUS);
118         SET_GPIO_REG_0(GPIO0_ODR, CFG_GPIO_STATUS);
119         SET_GPIO_0(CFG_GPIO_STATUS);
120         SET_GPIO_REG_0(GPIO0_TCR, CFG_GPIO_STATUS);
121         SET_GPIO_REG_0(GPIO0_ODR, CFG_GPIO_STATUS);
122
123         /* output */
124         SET_GPIO_REG_1(GPIO0_TCR, CFG_GPIO_CONFIG);
125         SET_GPIO_REG_0(GPIO0_ODR, CFG_GPIO_CONFIG);
126         SET_GPIO_0(CFG_GPIO_CONFIG);
127
128         /* input */
129         SET_GPIO_0(CFG_GPIO_CON_DON);
130         SET_GPIO_REG_0(GPIO0_TCR, CFG_GPIO_CON_DON);
131         SET_GPIO_REG_0(GPIO0_ODR, CFG_GPIO_CON_DON);
132
133         /* CONFIG = 0 STATUS = 0 -> FPGA in reset state */
134         SET_GPIO_0(CFG_GPIO_CONFIG);
135         return FPGA_SUCCESS;
136 }
137
138 /* Set the state of CONFIG Pin */
139 int fpga_config_fn (int assert_config, int flush, int cookie)
140 {
141         if (assert_config) {
142                 SET_GPIO_1(CFG_GPIO_CONFIG);
143         } else {
144                 SET_GPIO_0(CFG_GPIO_CONFIG);
145         }
146         return FPGA_SUCCESS;
147 }
148
149 /* Returns the state of STATUS Pin */
150 int fpga_status_fn (int cookie)
151 {
152         unsigned long   reg;
153
154         reg = in32(GPIO0_IR);
155         if (reg &= (0x80000000 >> CFG_GPIO_STATUS)) {
156                 PRINTF("STATUS = HIGH\n");
157                 return FPGA_FAIL;
158         }
159         PRINTF("STATUS = LOW\n");
160         return FPGA_SUCCESS;
161 }
162
163 /* Returns the state of CONF_DONE Pin */
164 int fpga_done_fn (int cookie)
165 {
166         unsigned long   reg;
167         reg = in32(GPIO0_IR);
168         if (reg &= (0x80000000 >> CFG_GPIO_CON_DON)) {
169                 PRINTF("CONF_DON = HIGH\n");
170                 return FPGA_FAIL;
171         }
172         PRINTF("CONF_DON = LOW\n");
173         return FPGA_SUCCESS;
174 }
175
176 /* writes the complete buffer to the FPGA
177    writing the complete buffer in one function is very faster,
178    then calling it for every bit */
179 int fpga_write_fn (void *buf, size_t len, int flush, int cookie)
180 {
181         size_t bytecount = 0;
182         unsigned char *data = (unsigned char *) buf;
183         unsigned char val=0;
184         int             i;
185
186         while (bytecount < len) {
187 #ifdef CFG_FPGA_CHECK_CTRLC
188                 if (ctrlc ()) {
189                         return FPGA_FAIL;
190                 }
191 #endif
192                 val = data[bytecount ++ ];
193                 i = 8;
194                 do {
195                         if (val & 0x01) {
196                                 FPGA_WRITE_1;
197                         } else {
198                                 FPGA_WRITE_0;
199                         }
200                         val >>= 1;
201                         i --;
202                 } while (i > 0);
203
204 #ifdef CFG_FPGA_PROG_FEEDBACK
205                 if (bytecount % (len / 40) == 0)
206                         putc ('.');             /* let them know we are alive */
207 #endif
208         }
209         return FPGA_SUCCESS;
210 }
211
212 /* called, when programming is aborted */
213 int fpga_abort_fn (int cookie)
214 {
215         SET_GPIO_1((CFG_GPIO_SEL_DPR));
216         return FPGA_SUCCESS;
217 }
218
219 /* called, when programming was succesful */
220 int fpga_post_fn (int cookie)
221 {
222         return fpga_abort_fn (cookie);
223 }
224
225 /* Note that these are pointers to code that is in Flash.  They will be
226  * relocated at runtime.
227  */
228 Altera_CYC2_Passive_Serial_fns fpga_fns = {
229         fpga_pre_fn,
230         fpga_config_fn,
231         fpga_status_fn,
232         fpga_done_fn,
233         fpga_write_fn,
234         fpga_abort_fn,
235         fpga_post_fn
236 };
237
238 Altera_desc fpga[CONFIG_FPGA_COUNT] = {
239         {Altera_CYC2,
240          passive_serial,
241          Altera_EP2C35_SIZE,
242          (void *) &fpga_fns,
243          NULL,
244          0}
245 };
246
247 /*
248  * Initialize the fpga.  Return 1 on success, 0 on failure.
249  */
250 int alpr_fpga_init (void)
251 {
252         int i;
253
254         PRINTF ("%s:%d: Initialize FPGA interface (relocation offset = 0x%.8lx)\n", __FUNCTION__, __LINE__, gd->reloc_off);
255         fpga_init (gd->reloc_off);
256
257         for (i = 0; i < CONFIG_FPGA_COUNT; i++) {
258                 PRINTF ("%s:%d: Adding fpga %d\n", __FUNCTION__, __LINE__, i);
259                 fpga_add (fpga_altera, &fpga[i]);
260         }
261         return 1;
262 }
263
264 #endif