]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - board/hymod/bsp.c
* Patch by Andreas Oberritter, 09 Nov 2002:
[karo-tx-uboot.git] / board / hymod / bsp.c
1 /*
2  * (C) Copyright 2000
3  * Wolfgang Denk, DENX Software Engineering, wd@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  * hacked for Hymod FPGA support by Murray.Jensen@cmst.csiro.au, 29-Jan-01
24  */
25
26 #include <common.h>
27 #include <command.h>
28 #include <net.h>
29 #include <i2c.h>
30 #include <asm/iopin_8260.h>
31 #include <cmd_bsp.h>
32
33 /*-----------------------------------------------------------------------
34  * Board Special Commands: FPGA load/store, EEPROM erase
35  */
36
37 #if (CONFIG_COMMANDS & CFG_CMD_BSP)
38
39 #define LOAD_SUCCESS            0
40 #define LOAD_FAIL_NOCONF        1
41 #define LOAD_FAIL_NOINIT        2
42 #define LOAD_FAIL_NODONE        3
43
44 #define STORE_SUCCESS           0
45
46 /*
47  * Programming the Hymod FPGAs
48  *
49  * The 8260 io port config table is set up so that the INIT pin is
50  * held Low (Open Drain output 0) - this will delay the automatic
51  * Power-On config until INIT is released (by making it an input).
52  *
53  * If the FPGA has been programmed before, then the assertion of PROGRAM
54  * will initiate configuration (i.e. it begins clearing the RAM).
55  *
56  * When the FPGA is ready to receive configuration data (either after
57  * releasing INIT after Power-On, or after asserting PROGRAM), it will
58  * pull INIT high.
59  *
60  * Notes from Paul Dunn:
61  *
62  *  1. program pin should be forced low for >= 300ns
63  *     (about 20 bus clock cycles minimum).
64  *
65  *  2. then wait for init to go high, which signals
66  *     that the FPGA has cleared its internal memory
67  *     and is ready to load
68  *
69  *  3. perform load writes of entire config file
70  *
71  *  4. wait for done to go high, which should be
72  *     within a few bus clock cycles. If done has not
73  *     gone high after reasonable period, then load
74  *     has not worked (wait several ms?)
75  */
76
77 int fpga_load (int mezz, uchar * addr, ulong size)
78 {
79         DECLARE_GLOBAL_DATA_PTR;
80
81         hymod_conf_t *cp = &gd->bd->bi_hymod_conf;
82         xlx_iopins_t *fpgaio;
83         volatile uchar *fpgabase;
84         volatile uint cnt;
85         uchar *eaddr = addr + size;
86         int result;
87
88         if (mezz) {
89                 if (!cp->mezz.mmap[0].prog.exists)
90                         return (LOAD_FAIL_NOCONF);
91                 fpgabase = (uchar *) cp->mezz.mmap[0].prog.base;
92                 fpgaio = &cp->mezz.iopins[0];
93         } else {
94                 if (!cp->main.mmap[0].prog.exists)
95                         return (LOAD_FAIL_NOCONF);
96                 fpgabase = (uchar *) cp->main.mmap[0].prog.base;
97                 fpgaio = &cp->main.iopins[0];
98         }
99
100         /* set enable HIGH if required */
101         if (fpgaio->enable_pin.flag)
102                 iopin_set_high (&fpgaio->enable_pin);
103
104         /* ensure INIT is released (set it to be an input) */
105         iopin_set_in (&fpgaio->init_pin);
106
107         /* toggle PROG Low then High (will already be Low after Power-On) */
108         iopin_set_low (&fpgaio->prog_pin);
109         udelay (1);                                     /* minimum 300ns - 1usec should do it */
110         iopin_set_high (&fpgaio->prog_pin);
111
112         /* wait for INIT High */
113         cnt = 0;
114         while (!iopin_is_high (&fpgaio->init_pin))
115                 if (++cnt == 10000000) {
116                         result = LOAD_FAIL_NOINIT;
117                         goto done;
118                 }
119
120         /* write configuration data */
121         while (addr < eaddr)
122                 *fpgabase = *addr++;
123
124         /* wait for DONE High */
125         cnt = 0;
126         while (!iopin_is_high (&fpgaio->done_pin))
127                 if (++cnt == 100000000) {
128                         result = LOAD_FAIL_NODONE;
129                         goto done;
130                 }
131
132         /* success */
133         result = LOAD_SUCCESS;
134
135   done:
136
137         if (fpgaio->enable_pin.flag)
138                 iopin_set_low (&fpgaio->enable_pin);
139
140         return (result);
141 }
142
143 /* ------------------------------------------------------------------------- */
144 int
145 do_fpga (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
146 {
147         uchar *addr, *save_addr;
148         ulong size;
149         int mezz, arg, result;
150
151         switch (argc) {
152
153         case 0:
154         case 1:
155                 break;
156
157         case 2:
158                 if (strcmp (argv[1], "info") == 0) {
159                         printf ("\nHymod FPGA Info...\n");
160                         printf ("                               Address         Size\n");
161                         printf ("       Main Configuration:     0x%08x  %d\n",
162                                         FPGA_MAIN_CFG_BASE, FPGA_MAIN_CFG_SIZE);
163                         printf ("       Main Register:          0x%08x  %d\n",
164                                         FPGA_MAIN_REG_BASE, FPGA_MAIN_REG_SIZE);
165                         printf ("       Main Port:              0x%08x  %d\n",
166                                         FPGA_MAIN_PORT_BASE, FPGA_MAIN_PORT_SIZE);
167                         printf ("       Mezz Configuration:     0x%08x  %d\n",
168                                         FPGA_MEZZ_CFG_BASE, FPGA_MEZZ_CFG_SIZE);
169                         return 0;
170                 }
171                 break;
172
173         case 3:
174                 if (strcmp (argv[1], "store") == 0) {
175                         addr = (uchar *) simple_strtoul (argv[2], NULL, 16);
176
177                         save_addr = addr;
178 #if 0
179                         /* reading config data unimplemented */
180                         while VM
181                           :more config data * addr++ = *fpga;
182                   result = VM:? ? ?
183 #else
184                         result = 0;
185 #endif
186                         if (result == STORE_SUCCESS) {
187                                 printf ("SUCCEEDED (%d bytes)\n", addr - save_addr);
188                                 return 0;
189                         } else
190                                 printf ("FAILED (%d bytes)\n", addr - save_addr);
191                         return 1;
192                 }
193                 break;
194
195         case 4:
196                 if (strcmp (argv[1], "tftp") == 0) {
197                         copy_filename (BootFile, argv[2], sizeof (BootFile));
198                         load_addr = simple_strtoul (argv[3], NULL, 16);
199
200                         if (NetLoop (TFTP) <= 0) {
201                                 printf ("tftp transfer failed - aborting fgpa load\n");
202                                 return 1;
203                         }
204
205                         if (NetBootFileXferSize == 0) {
206                                 printf ("can't determine file size - aborting fpga load\n");
207                                 return 1;
208                         }
209
210                         printf ("File transfer succeeded - beginning fpga load...");
211
212                         result = fpga_load (0, (uchar *) load_addr,
213                                                                 NetBootFileXferSize);
214                         if (result == LOAD_SUCCESS) {
215                                 printf ("SUCCEEDED\n");
216                                 return 0;
217                         } else if (result == LOAD_FAIL_NOINIT)
218                                 printf ("FAILED (no INIT)\n");
219                         else
220                                 printf ("FAILED (no DONE)\n");
221                         return 1;
222
223                 }
224                 /* fall through ... */
225
226         case 5:
227                 if (strcmp (argv[1], "load") == 0) {
228                         if (argc == 5) {
229                                 if (strcmp (argv[2], "main") == 0)
230                                         mezz = 0;
231                                 else if (strcmp (argv[2], "mezz") == 0)
232                                         mezz = 1;
233                                 else {
234                                         printf ("FPGA type must be either `main' or `mezz'\n");
235                                         return 1;
236                                 }
237                                 arg = 3;
238                         } else {
239                                 mezz = 0;
240                                 arg = 2;
241                         }
242                         addr = (uchar *) simple_strtoul (argv[arg++], NULL, 16);
243                         size = (ulong) simple_strtoul (argv[arg], NULL, 16);
244
245                         result = fpga_load (mezz, addr, size);
246                         if (result == LOAD_SUCCESS) {
247                                 printf ("SUCCEEDED\n");
248                                 return 0;
249                         } else if (result == LOAD_FAIL_NOINIT)
250                                 printf ("FAILED (no INIT)\n");
251                         else
252                                 printf ("FAILED (no DONE)\n");
253                         return 1;
254                 }
255                 break;
256
257         default:
258                 break;
259         }
260
261         printf ("Usage:\n%s\n", cmdtp->usage);
262         return 1;
263 }
264
265 /* ------------------------------------------------------------------------- */
266 int
267 do_eecl (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
268 {
269         uchar data[HYMOD_EEPROM_SIZE];
270         uint offset;
271         int rcode = 0;
272
273         switch (argc) {
274
275         case 1:
276                 offset = HYMOD_EEOFF_MAIN;
277                 break;
278
279         case 2:
280                 if (strcmp (argv[1], "main") == 0) {
281                         offset = HYMOD_EEOFF_MAIN;
282                         break;
283                 }
284                 if (strcmp (argv[1], "mezz") == 0) {
285                         offset = HYMOD_EEOFF_MEZZ;
286                         break;
287                 }
288                 /* fall through ... */
289
290         default:
291                 printf ("Usage:\n%s\n", cmdtp->usage);
292                 return 1;
293         }
294
295         memset (data, 0, HYMOD_EEPROM_SIZE);
296         if (i2c_write
297                 (CFG_I2C_EEPROM_ADDR | offset, 0, CFG_I2C_EEPROM_ADDR_LEN, data,
298                  HYMOD_EEPROM_SIZE)) {
299                 rcode = 1;
300         }
301
302         return rcode;
303 }
304
305 #endif                                                  /* CFG_CMD_BSP */
306
307 /* ------------------------------------------------------------------------- */