Add I2C frequency dividers for ColdFire
[oweals/u-boot.git] / common / ACEX1K.c
1 /*
2  * (C) Copyright 2003
3  * Steven Scholz, imc Measurement & Control, steven.scholz@imc-berlin.de
4  *
5  * (C) Copyright 2002
6  * Rich Ireland, Enterasys Networks, rireland@enterasys.com.
7  *
8  * See file CREDITS for list of people who contributed to this
9  * project.
10  *
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License as
13  * published by the Free Software Foundation; either version 2 of
14  * the License, or (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
24  * MA 02111-1307 USA
25  *
26  */
27
28 #include <common.h>             /* core U-Boot definitions */
29 #include <ACEX1K.h>             /* ACEX device family */
30
31 /* Define FPGA_DEBUG to get debug printf's */
32 #ifdef  FPGA_DEBUG
33 #define PRINTF(fmt,args...)     printf (fmt ,##args)
34 #else
35 #define PRINTF(fmt,args...)
36 #endif
37
38 /* Note: The assumption is that we cannot possibly run fast enough to
39  * overrun the device (the Slave Parallel mode can free run at 50MHz).
40  * If there is a need to operate slower, define CONFIG_FPGA_DELAY in
41  * the board config file to slow things down.
42  */
43 #ifndef CONFIG_FPGA_DELAY
44 #define CONFIG_FPGA_DELAY()
45 #endif
46
47 #ifndef CFG_FPGA_WAIT
48 #define CFG_FPGA_WAIT CFG_HZ/10         /* 100 ms */
49 #endif
50
51 static int ACEX1K_ps_load( Altera_desc *desc, void *buf, size_t bsize );
52 static int ACEX1K_ps_dump( Altera_desc *desc, void *buf, size_t bsize );
53 /* static int ACEX1K_ps_info( Altera_desc *desc ); */
54 static int ACEX1K_ps_reloc( Altera_desc *desc, ulong reloc_offset );
55
56 /* ------------------------------------------------------------------------- */
57 /* ACEX1K Generic Implementation */
58 int ACEX1K_load (Altera_desc * desc, void *buf, size_t bsize)
59 {
60         int ret_val = FPGA_FAIL;
61
62         switch (desc->iface) {
63         case passive_serial:
64                 PRINTF ("%s: Launching Passive Serial Loader\n", __FUNCTION__);
65                 ret_val = ACEX1K_ps_load (desc, buf, bsize);
66                 break;
67
68                 /* Add new interface types here */
69
70         default:
71                 printf ("%s: Unsupported interface type, %d\n",
72                                 __FUNCTION__, desc->iface);
73         }
74
75         return ret_val;
76 }
77
78 int ACEX1K_dump (Altera_desc * desc, void *buf, size_t bsize)
79 {
80         int ret_val = FPGA_FAIL;
81
82         switch (desc->iface) {
83         case passive_serial:
84                 PRINTF ("%s: Launching Passive Serial Dump\n", __FUNCTION__);
85                 ret_val = ACEX1K_ps_dump (desc, buf, bsize);
86                 break;
87
88                 /* Add new interface types here */
89
90         default:
91                 printf ("%s: Unsupported interface type, %d\n",
92                                 __FUNCTION__, desc->iface);
93         }
94
95         return ret_val;
96 }
97
98 int ACEX1K_info( Altera_desc *desc )
99 {
100         return FPGA_SUCCESS;
101 }
102
103
104 int ACEX1K_reloc (Altera_desc * desc, ulong reloc_offset)
105 {
106         int ret_val = FPGA_FAIL;        /* assume a failure */
107
108         if (desc->family != Altera_ACEX1K) {
109                 printf ("%s: Unsupported family type, %d\n",
110                                 __FUNCTION__, desc->family);
111                 return FPGA_FAIL;
112         } else
113                 switch (desc->iface) {
114                 case passive_serial:
115                         ret_val = ACEX1K_ps_reloc (desc, reloc_offset);
116                         break;
117
118                 /* Add new interface types here */
119
120                 default:
121                         printf ("%s: Unsupported interface type, %d\n",
122                                         __FUNCTION__, desc->iface);
123                 }
124
125         return ret_val;
126 }
127
128
129 /* ------------------------------------------------------------------------- */
130 /* ACEX1K Passive Serial Generic Implementation                                  */
131
132 static int ACEX1K_ps_load (Altera_desc * desc, void *buf, size_t bsize)
133 {
134         int ret_val = FPGA_FAIL;        /* assume the worst */
135         Altera_ACEX1K_Passive_Serial_fns *fn = desc->iface_fns;
136         int i;
137
138         PRINTF ("%s: start with interface functions @ 0x%p\n",
139                         __FUNCTION__, fn);
140
141         if (fn) {
142                 size_t bytecount = 0;
143                 unsigned char *data = (unsigned char *) buf;
144                 int cookie = desc->cookie;      /* make a local copy */
145                 unsigned long ts;               /* timestamp */
146
147                 PRINTF ("%s: Function Table:\n"
148                                 "ptr:\t0x%p\n"
149                                 "struct: 0x%p\n"
150                                 "config:\t0x%p\n"
151                                 "status:\t0x%p\n"
152                                 "clk:\t0x%p\n"
153                                 "data:\t0x%p\n"
154                                 "done:\t0x%p\n\n",
155                                 __FUNCTION__, &fn, fn, fn->config, fn->status,
156                                 fn->clk, fn->data, fn->done);
157 #ifdef CFG_FPGA_PROG_FEEDBACK
158                 printf ("Loading FPGA Device %d...", cookie);
159 #endif
160
161                 /*
162                  * Run the pre configuration function if there is one.
163                  */
164                 if (*fn->pre) {
165                         (*fn->pre) (cookie);
166                 }
167
168                 /* Establish the initial state */
169                 (*fn->config) (TRUE, TRUE, cookie);     /* Assert nCONFIG */
170
171                 udelay(2);              /* T_cfg > 2us  */
172
173                 /* nSTATUS should be asserted now */
174                 (*fn->done) (cookie);
175                 if ( !(*fn->status) (cookie) ) {
176                         puts ("** nSTATUS is not asserted.\n");
177                         (*fn->abort) (cookie);
178                         return FPGA_FAIL;
179                 }
180
181                 (*fn->config) (FALSE, TRUE, cookie);    /* Deassert nCONFIG */
182                 udelay(2);              /* T_cf2st1 < 4us       */
183
184                 /* Wait for nSTATUS to be released (i.e. deasserted) */
185                 ts = get_timer (0);             /* get current time */
186                 do {
187                         CONFIG_FPGA_DELAY ();
188                         if (get_timer (ts) > CFG_FPGA_WAIT) {   /* check the time */
189                                 puts ("** Timeout waiting for STATUS to go high.\n");
190                                 (*fn->abort) (cookie);
191                                 return FPGA_FAIL;
192                         }
193                         (*fn->done) (cookie);
194                 } while ((*fn->status) (cookie));
195
196                 /* Get ready for the burn */
197                 CONFIG_FPGA_DELAY ();
198
199                 /* Load the data */
200                 while (bytecount < bsize) {
201                         unsigned char val=0;
202 #ifdef CFG_FPGA_CHECK_CTRLC
203                         if (ctrlc ()) {
204                                 (*fn->abort) (cookie);
205                                 return FPGA_FAIL;
206                         }
207 #endif
208                         /* Altera detects an error if INIT goes low (active)
209                            while DONE is low (inactive) */
210 #if 0 /* not yet implemented */
211                         if ((*fn->done) (cookie) == 0 && (*fn->init) (cookie)) {
212                                 puts ("** CRC error during FPGA load.\n");
213                                 (*fn->abort) (cookie);
214                                 return (FPGA_FAIL);
215                         }
216 #endif
217                         val = data [bytecount ++ ];
218                         i = 8;
219                         do {
220                                 /* Deassert the clock */
221                                 (*fn->clk) (FALSE, TRUE, cookie);
222                                 CONFIG_FPGA_DELAY ();
223                                 /* Write data */
224                                 (*fn->data) ( (val & 0x01), TRUE, cookie);
225                                 CONFIG_FPGA_DELAY ();
226                                 /* Assert the clock */
227                                 (*fn->clk) (TRUE, TRUE, cookie);
228                                 CONFIG_FPGA_DELAY ();
229                                 val >>= 1;
230                                 i --;
231                         } while (i > 0);
232
233 #ifdef CFG_FPGA_PROG_FEEDBACK
234                         if (bytecount % (bsize / 40) == 0)
235                                 putc ('.');             /* let them know we are alive */
236 #endif
237                 }
238
239                 CONFIG_FPGA_DELAY ();
240
241 #ifdef CFG_FPGA_PROG_FEEDBACK
242                 putc (' ');                     /* terminate the dotted line */
243 #endif
244
245         /*
246          * Checking FPGA's CONF_DONE signal - correctly booted ?
247          */
248
249         if ( ! (*fn->done) (cookie) ) {
250                 puts ("** Booting failed! CONF_DONE is still deasserted.\n");
251                 (*fn->abort) (cookie);
252                 return (FPGA_FAIL);
253         }
254
255         /*
256          * "DCLK must be clocked an additional 10 times fpr ACEX 1K..."
257          */
258
259         for (i = 0; i < 12; i++) {
260                 CONFIG_FPGA_DELAY ();
261                 (*fn->clk) (TRUE, TRUE, cookie);        /* Assert the clock pin */
262                 CONFIG_FPGA_DELAY ();
263                 (*fn->clk) (FALSE, TRUE, cookie);       /* Deassert the clock pin */
264         }
265
266         ret_val = FPGA_SUCCESS;
267
268 #ifdef CFG_FPGA_PROG_FEEDBACK
269                 if (ret_val == FPGA_SUCCESS) {
270                         puts ("Done.\n");
271                 }
272                 else {
273                         puts ("Fail.\n");
274                 }
275 #endif
276         (*fn->post) (cookie);
277
278         } else {
279                 printf ("%s: NULL Interface function table!\n", __FUNCTION__);
280         }
281
282         return ret_val;
283 }
284
285 static int ACEX1K_ps_dump (Altera_desc * desc, void *buf, size_t bsize)
286 {
287         /* Readback is only available through the Slave Parallel and         */
288         /* boundary-scan interfaces.                                         */
289         printf ("%s: Passive Serial Dumping is unavailable\n",
290                         __FUNCTION__);
291         return FPGA_FAIL;
292 }
293
294 static int ACEX1K_ps_reloc (Altera_desc * desc, ulong reloc_offset)
295 {
296         int ret_val = FPGA_FAIL;        /* assume the worst */
297         Altera_ACEX1K_Passive_Serial_fns *fn_r, *fn =
298                         (Altera_ACEX1K_Passive_Serial_fns *) (desc->iface_fns);
299
300         if (fn) {
301                 ulong addr;
302
303                 /* Get the relocated table address */
304                 addr = (ulong) fn + reloc_offset;
305                 fn_r = (Altera_ACEX1K_Passive_Serial_fns *) addr;
306
307                 if (!fn_r->relocated) {
308
309                         if (memcmp (fn_r, fn,
310                                                 sizeof (Altera_ACEX1K_Passive_Serial_fns))
311                                 == 0) {
312                                 /* good copy of the table, fix the descriptor pointer */
313                                 desc->iface_fns = fn_r;
314                         } else {
315                                 PRINTF ("%s: Invalid function table at 0x%p\n",
316                                                 __FUNCTION__, fn_r);
317                                 return FPGA_FAIL;
318                         }
319
320                         PRINTF ("%s: Relocating descriptor at 0x%p\n", __FUNCTION__,
321                                         desc);
322
323                         addr = (ulong) (fn->pre) + reloc_offset;
324                         fn_r->pre = (Altera_pre_fn) addr;
325
326                         addr = (ulong) (fn->config) + reloc_offset;
327                         fn_r->config = (Altera_config_fn) addr;
328
329                         addr = (ulong) (fn->status) + reloc_offset;
330                         fn_r->status = (Altera_status_fn) addr;
331
332                         addr = (ulong) (fn->done) + reloc_offset;
333                         fn_r->done = (Altera_done_fn) addr;
334
335                         addr = (ulong) (fn->clk) + reloc_offset;
336                         fn_r->clk = (Altera_clk_fn) addr;
337
338                         addr = (ulong) (fn->data) + reloc_offset;
339                         fn_r->data = (Altera_data_fn) addr;
340
341                         addr = (ulong) (fn->abort) + reloc_offset;
342                         fn_r->abort = (Altera_abort_fn) addr;
343
344                         addr = (ulong) (fn->post) + reloc_offset;
345                         fn_r->post = (Altera_post_fn) addr;
346
347                         fn_r->relocated = TRUE;
348
349                 } else {
350                         /* this table has already been moved */
351                         /* XXX - should check to see if the descriptor is correct */
352                         desc->iface_fns = fn_r;
353                 }
354
355                 ret_val = FPGA_SUCCESS;
356         } else {
357                 printf ("%s: NULL Interface function table!\n", __FUNCTION__);
358         }
359
360         return ret_val;
361
362 }