]>
Commit | Line | Data |
---|---|---|
f8cac651 WD |
1 | /* |
2 | * (C) Copyright 2001 | |
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 | ||
24 | #include <common.h> | |
25 | #include <mpc8xx.h> | |
26 | #include <commproc.h> | |
27 | #include <i2c.h> | |
28 | #include <command.h> | |
f8cac651 WD |
29 | |
30 | /* ------------------------------------------------------------------------- */ | |
31 | ||
32 | static long int dram_size (long int, long int *, long int); | |
33 | static void puma_status (void); | |
34 | static void puma_set_mode (int mode); | |
c83bf6a2 | 35 | static int puma_init_done (void); |
f8cac651 WD |
36 | static void puma_load (ulong addr, ulong len); |
37 | ||
38 | /* ------------------------------------------------------------------------- */ | |
39 | ||
40 | #define _NOT_USED_ 0xFFFFFFFF | |
41 | ||
42 | /* | |
43 | * 50 MHz SDRAM access using UPM A | |
44 | */ | |
c83bf6a2 | 45 | const uint sdram_table[] = { |
f8cac651 WD |
46 | /* |
47 | * Single Read. (Offset 0 in UPM RAM) | |
48 | */ | |
49 | 0x1f0dfc04, 0xeeafbc04, 0x11af7c04, 0xefbeec00, | |
c83bf6a2 | 50 | 0x1ffddc47, /* last */ |
f8cac651 WD |
51 | /* |
52 | * SDRAM Initialization (offset 5 in UPM RAM) | |
53 | * | |
8bde7f77 WD |
54 | * This is no UPM entry point. The following definition uses |
55 | * the remaining space to establish an initialization | |
56 | * sequence, which is executed by a RUN command. | |
f8cac651 WD |
57 | * |
58 | */ | |
c83bf6a2 | 59 | 0x1ffddc35, 0xefceac34, 0x1f3d5c35, /* last */ |
f8cac651 WD |
60 | /* |
61 | * Burst Read. (Offset 8 in UPM RAM) | |
62 | */ | |
63 | 0x1f0dfc04, 0xeeafbc04, 0x10af7c04, 0xf0affc00, | |
c83bf6a2 | 64 | 0xf0affc00, 0xf1affc00, 0xefbeec00, 0x1ffddc47, /* last */ |
f8cac651 WD |
65 | _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_, |
66 | _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_, | |
67 | ||
68 | /* | |
69 | * Single Write. (Offset 18 in UPM RAM) | |
70 | */ | |
c83bf6a2 | 71 | 0x1f0dfc04, 0xeeafac00, 0x01be4c04, 0x1ffddc47, /* last */ |
f8cac651 WD |
72 | _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_, |
73 | /* | |
74 | * Burst Write. (Offset 20 in UPM RAM) | |
75 | */ | |
76 | 0x1f0dfc04, 0xeeafac00, 0x10af5c00, 0xf0affc00, | |
c83bf6a2 WD |
77 | 0xf0affc00, 0xe1beec04, 0x1ffddc47, /* last */ |
78 | _NOT_USED_, | |
f8cac651 WD |
79 | _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_, |
80 | _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_, | |
81 | /* | |
82 | * Refresh (Offset 30 in UPM RAM) | |
83 | */ | |
84 | 0x1ffd7c84, 0xfffffc04, 0xfffffc04, 0xfffffc04, | |
c83bf6a2 WD |
85 | 0xfffffc84, 0xfffffc07, /* last */ |
86 | _NOT_USED_, _NOT_USED_, | |
f8cac651 WD |
87 | _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_, |
88 | /* | |
89 | * Exception. (Offset 3c in UPM RAM) | |
90 | */ | |
c83bf6a2 WD |
91 | 0x7ffffc07, /* last */ |
92 | _NOT_USED_, _NOT_USED_, _NOT_USED_, | |
f8cac651 WD |
93 | }; |
94 | ||
95 | /* ------------------------------------------------------------------------- */ | |
96 | ||
97 | /* | |
98 | * PUMA access using UPM B | |
99 | */ | |
c83bf6a2 | 100 | const uint puma_table[] = { |
f8cac651 WD |
101 | /* |
102 | * Single Read. (Offset 0 in UPM RAM) | |
103 | */ | |
104 | _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_, | |
105 | _NOT_USED_, | |
106 | /* | |
107 | * Precharge and MRS | |
108 | */ | |
c83bf6a2 | 109 | _NOT_USED_, _NOT_USED_, _NOT_USED_, |
f8cac651 WD |
110 | /* |
111 | * Burst Read. (Offset 8 in UPM RAM) | |
112 | */ | |
113 | _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_, | |
114 | _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_, | |
115 | _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_, | |
116 | _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_, | |
117 | /* | |
118 | * Single Write. (Offset 18 in UPM RAM) | |
119 | */ | |
c83bf6a2 WD |
120 | 0x0ffff804, 0x0ffff400, 0x3ffffc47, /* last */ |
121 | _NOT_USED_, | |
f8cac651 WD |
122 | _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_, |
123 | /* | |
124 | * Burst Write. (Offset 20 in UPM RAM) | |
125 | */ | |
126 | _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_, | |
127 | _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_, | |
128 | _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_, | |
129 | _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_, | |
130 | /* | |
131 | * Refresh (Offset 30 in UPM RAM) | |
132 | */ | |
133 | _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_, | |
134 | _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_, | |
135 | _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_, | |
136 | /* | |
137 | * Exception. (Offset 3c in UPM RAM) | |
138 | */ | |
c83bf6a2 WD |
139 | 0x7ffffc07, /* last */ |
140 | _NOT_USED_, _NOT_USED_, _NOT_USED_, | |
f8cac651 WD |
141 | }; |
142 | ||
143 | /* ------------------------------------------------------------------------- */ | |
144 | ||
145 | ||
146 | /* | |
147 | * Check Board Identity: | |
148 | * | |
149 | */ | |
150 | ||
151 | int checkboard (void) | |
152 | { | |
153 | puts ("Board: Siemens PCU E\n"); | |
154 | return (0); | |
155 | } | |
156 | ||
157 | /* ------------------------------------------------------------------------- */ | |
158 | ||
c83bf6a2 | 159 | long int initdram (int board_type) |
f8cac651 | 160 | { |
c83bf6a2 WD |
161 | volatile immap_t *immr = (immap_t *) CFG_IMMR; |
162 | volatile memctl8xx_t *memctl = &immr->im_memctl; | |
163 | long int size_b0, reg; | |
164 | int i; | |
f8cac651 | 165 | |
c83bf6a2 WD |
166 | /* |
167 | * Configure UPMA for SDRAM | |
168 | */ | |
169 | upmconfig (UPMA, (uint *) sdram_table, | |
170 | sizeof (sdram_table) / sizeof (uint)); | |
f8cac651 | 171 | |
c83bf6a2 | 172 | memctl->memc_mptpr = CFG_MPTPR; |
f8cac651 | 173 | |
c83bf6a2 WD |
174 | /* burst length=4, burst type=sequential, CAS latency=2 */ |
175 | memctl->memc_mar = 0x00000088; | |
f8cac651 | 176 | |
c83bf6a2 WD |
177 | /* |
178 | * Map controller bank 2 to the SDRAM bank at preliminary address. | |
179 | */ | |
f8cac651 | 180 | #if PCU_E_WITH_SWAPPED_CS /* XXX */ |
c83bf6a2 WD |
181 | memctl->memc_or5 = CFG_OR5_PRELIM; |
182 | memctl->memc_br5 = CFG_BR5_PRELIM; | |
183 | #else /* XXX */ | |
184 | memctl->memc_or2 = CFG_OR2_PRELIM; | |
185 | memctl->memc_br2 = CFG_BR2_PRELIM; | |
186 | #endif /* XXX */ | |
f8cac651 | 187 | |
c83bf6a2 WD |
188 | /* initialize memory address register */ |
189 | memctl->memc_mamr = CFG_MAMR; /* refresh not enabled yet */ | |
f8cac651 | 190 | |
c83bf6a2 | 191 | /* mode initialization (offset 5) */ |
f8cac651 | 192 | #if PCU_E_WITH_SWAPPED_CS /* XXX */ |
c83bf6a2 WD |
193 | udelay (200); /* 0x8000A105 */ |
194 | memctl->memc_mcr = MCR_OP_RUN | MCR_MB_CS5 | MCR_MLCF (1) | MCR_MAD (0x05); | |
195 | #else /* XXX */ | |
196 | udelay (200); /* 0x80004105 */ | |
197 | memctl->memc_mcr = MCR_OP_RUN | MCR_MB_CS2 | MCR_MLCF (1) | MCR_MAD (0x05); | |
198 | #endif /* XXX */ | |
199 | ||
200 | /* run 2 refresh sequence with 4-beat refresh burst (offset 0x30) */ | |
f8cac651 | 201 | #if PCU_E_WITH_SWAPPED_CS /* XXX */ |
c83bf6a2 WD |
202 | udelay (1); /* 0x8000A830 */ |
203 | memctl->memc_mcr = MCR_OP_RUN | MCR_MB_CS5 | MCR_MLCF (8) | MCR_MAD (0x30); | |
204 | #else /* XXX */ | |
205 | udelay (1); /* 0x80004830 */ | |
206 | memctl->memc_mcr = MCR_OP_RUN | MCR_MB_CS2 | MCR_MLCF (8) | MCR_MAD (0x30); | |
207 | #endif /* XXX */ | |
f8cac651 WD |
208 | |
209 | #if PCU_E_WITH_SWAPPED_CS /* XXX */ | |
c83bf6a2 WD |
210 | udelay (1); /* 0x8000A106 */ |
211 | memctl->memc_mcr = MCR_OP_RUN | MCR_MB_CS5 | MCR_MLCF (1) | MCR_MAD (0x06); | |
212 | #else /* XXX */ | |
213 | udelay (1); /* 0x80004106 */ | |
214 | memctl->memc_mcr = MCR_OP_RUN | MCR_MB_CS2 | MCR_MLCF (1) | MCR_MAD (0x06); | |
215 | #endif /* XXX */ | |
216 | ||
217 | reg = memctl->memc_mamr; | |
218 | reg &= ~MAMR_TLFA_MSK; /* switch timer loop ... */ | |
219 | reg |= MAMR_TLFA_4X; /* ... to 4x */ | |
220 | reg |= MAMR_PTAE; /* enable refresh */ | |
221 | memctl->memc_mamr = reg; | |
222 | ||
223 | udelay (200); | |
224 | ||
225 | /* Need at least 10 DRAM accesses to stabilize */ | |
226 | for (i = 0; i < 10; ++i) { | |
f8cac651 | 227 | #if PCU_E_WITH_SWAPPED_CS /* XXX */ |
c83bf6a2 WD |
228 | volatile unsigned long *addr = |
229 | (volatile unsigned long *) SDRAM_BASE5_PRELIM; | |
230 | #else /* XXX */ | |
231 | volatile unsigned long *addr = | |
232 | (volatile unsigned long *) SDRAM_BASE2_PRELIM; | |
233 | #endif /* XXX */ | |
234 | unsigned long val; | |
235 | ||
236 | val = *(addr + i); | |
237 | *(addr + i) = val; | |
238 | } | |
239 | ||
240 | /* | |
241 | * Check Bank 0 Memory Size for re-configuration | |
242 | */ | |
f8cac651 | 243 | #if PCU_E_WITH_SWAPPED_CS /* XXX */ |
77ddac94 | 244 | size_b0 = dram_size (CFG_MAMR, (long *) SDRAM_BASE5_PRELIM, SDRAM_MAX_SIZE); |
c83bf6a2 | 245 | #else /* XXX */ |
77ddac94 | 246 | size_b0 = dram_size (CFG_MAMR, (long *) SDRAM_BASE2_PRELIM, SDRAM_MAX_SIZE); |
c83bf6a2 | 247 | #endif /* XXX */ |
f8cac651 | 248 | |
c83bf6a2 | 249 | memctl->memc_mamr = CFG_MAMR | MAMR_PTAE; |
f8cac651 | 250 | |
c83bf6a2 WD |
251 | /* |
252 | * Final mapping: | |
253 | */ | |
f8cac651 WD |
254 | |
255 | #if PCU_E_WITH_SWAPPED_CS /* XXX */ | |
c83bf6a2 WD |
256 | memctl->memc_or5 = ((-size_b0) & 0xFFFF0000) | SDRAM_TIMING; |
257 | memctl->memc_br5 = (CFG_SDRAM_BASE & BR_BA_MSK) | BR_MS_UPMA | BR_V; | |
258 | #else /* XXX */ | |
259 | memctl->memc_or2 = ((-size_b0) & 0xFFFF0000) | SDRAM_TIMING; | |
260 | memctl->memc_br2 = (CFG_SDRAM_BASE & BR_BA_MSK) | BR_MS_UPMA | BR_V; | |
261 | #endif /* XXX */ | |
262 | udelay (1000); | |
263 | ||
264 | /* | |
265 | * Configure UPMB for PUMA | |
266 | */ | |
267 | upmconfig (UPMB, (uint *) puma_table, | |
268 | sizeof (puma_table) / sizeof (uint)); | |
269 | ||
270 | return (size_b0); | |
f8cac651 WD |
271 | } |
272 | ||
273 | /* ------------------------------------------------------------------------- */ | |
274 | ||
275 | /* | |
276 | * Check memory range for valid RAM. A simple memory test determines | |
277 | * the actually available RAM size between addresses `base' and | |
278 | * `base + maxsize'. Some (not all) hardware errors are detected: | |
279 | * - short between address lines | |
280 | * - short between data lines | |
281 | */ | |
282 | ||
c83bf6a2 WD |
283 | static long int dram_size (long int mamr_value, long int *base, |
284 | long int maxsize) | |
f8cac651 | 285 | { |
c83bf6a2 WD |
286 | volatile immap_t *immr = (immap_t *) CFG_IMMR; |
287 | volatile memctl8xx_t *memctl = &immr->im_memctl; | |
f8cac651 | 288 | |
c83bf6a2 | 289 | memctl->memc_mamr = mamr_value; |
f8cac651 | 290 | |
c83bf6a2 | 291 | return (get_ram_size (base, maxsize)); |
f8cac651 WD |
292 | } |
293 | ||
294 | /* ------------------------------------------------------------------------- */ | |
295 | ||
c83bf6a2 | 296 | #if PCU_E_WITH_SWAPPED_CS /* XXX */ |
f8cac651 | 297 | #define ETH_CFG_BITS (CFG_PB_ETH_CFG1 | CFG_PB_ETH_CFG2 | CFG_PB_ETH_CFG3 ) |
c83bf6a2 | 298 | #else /* XXX */ |
f8cac651 WD |
299 | #define ETH_CFG_BITS (CFG_PB_ETH_MDDIS | CFG_PB_ETH_CFG1 | \ |
300 | CFG_PB_ETH_CFG2 | CFG_PB_ETH_CFG3 ) | |
301 | #endif /* XXX */ | |
302 | ||
303 | #define ETH_ALL_BITS (ETH_CFG_BITS | CFG_PB_ETH_POWERDOWN | CFG_PB_ETH_RESET) | |
304 | ||
c83bf6a2 | 305 | void reset_phy (void) |
f8cac651 | 306 | { |
c83bf6a2 | 307 | immap_t *immr = (immap_t *) CFG_IMMR; |
f8cac651 WD |
308 | ulong value; |
309 | ||
310 | /* Configure all needed port pins for GPIO */ | |
c83bf6a2 | 311 | #if PCU_E_WITH_SWAPPED_CS /* XXX */ |
42dfe7a1 | 312 | # ifdef CFG_ETH_MDDIS_VALUE |
c83bf6a2 | 313 | immr->im_ioport.iop_padat |= CFG_PA_ETH_MDDIS; |
f8cac651 WD |
314 | # else |
315 | immr->im_ioport.iop_padat &= ~(CFG_PA_ETH_MDDIS); /* Set low */ | |
316 | # endif | |
317 | immr->im_ioport.iop_papar &= ~(CFG_PA_ETH_MDDIS); /* GPIO */ | |
318 | immr->im_ioport.iop_paodr &= ~(CFG_PA_ETH_MDDIS); /* active output */ | |
c83bf6a2 | 319 | immr->im_ioport.iop_padir |= CFG_PA_ETH_MDDIS; /* output */ |
f8cac651 WD |
320 | #endif /* XXX */ |
321 | immr->im_cpm.cp_pbpar &= ~(ETH_ALL_BITS); /* GPIO */ | |
322 | immr->im_cpm.cp_pbodr &= ~(ETH_ALL_BITS); /* active output */ | |
323 | ||
c83bf6a2 | 324 | value = immr->im_cpm.cp_pbdat; |
f8cac651 WD |
325 | |
326 | /* Assert Powerdown and Reset signals */ | |
c83bf6a2 | 327 | value |= CFG_PB_ETH_POWERDOWN; |
f8cac651 WD |
328 | value &= ~(CFG_PB_ETH_RESET); |
329 | ||
330 | /* PHY configuration includes MDDIS and CFG1 ... CFG3 */ | |
331 | #if !PCU_E_WITH_SWAPPED_CS | |
42dfe7a1 | 332 | # ifdef CFG_ETH_MDDIS_VALUE |
c83bf6a2 | 333 | value |= CFG_PB_ETH_MDDIS; |
f8cac651 WD |
334 | # else |
335 | value &= ~(CFG_PB_ETH_MDDIS); | |
336 | # endif | |
337 | #endif | |
42dfe7a1 | 338 | #ifdef CFG_ETH_CFG1_VALUE |
c83bf6a2 | 339 | value |= CFG_PB_ETH_CFG1; |
f8cac651 WD |
340 | #else |
341 | value &= ~(CFG_PB_ETH_CFG1); | |
342 | #endif | |
42dfe7a1 | 343 | #ifdef CFG_ETH_CFG2_VALUE |
c83bf6a2 | 344 | value |= CFG_PB_ETH_CFG2; |
f8cac651 WD |
345 | #else |
346 | value &= ~(CFG_PB_ETH_CFG2); | |
347 | #endif | |
42dfe7a1 | 348 | #ifdef CFG_ETH_CFG3_VALUE |
c83bf6a2 | 349 | value |= CFG_PB_ETH_CFG3; |
f8cac651 WD |
350 | #else |
351 | value &= ~(CFG_PB_ETH_CFG3); | |
352 | #endif | |
353 | ||
354 | /* Drive output signals to initial state */ | |
c83bf6a2 | 355 | immr->im_cpm.cp_pbdat = value; |
f8cac651 WD |
356 | immr->im_cpm.cp_pbdir |= ETH_ALL_BITS; |
357 | udelay (10000); | |
358 | ||
359 | /* De-assert Ethernet Powerdown */ | |
c83bf6a2 | 360 | immr->im_cpm.cp_pbdat &= ~(CFG_PB_ETH_POWERDOWN); /* Enable PHY power */ |
f8cac651 WD |
361 | udelay (10000); |
362 | ||
363 | /* de-assert RESET signal of PHY */ | |
c83bf6a2 | 364 | immr->im_cpm.cp_pbdat |= CFG_PB_ETH_RESET; |
f8cac651 WD |
365 | udelay (1000); |
366 | } | |
367 | ||
368 | /*----------------------------------------------------------------------- | |
369 | * Board Special Commands: access functions for "PUMA" FPGA | |
370 | */ | |
ab3abcba | 371 | #if defined(CONFIG_CMD_BSP) |
f8cac651 WD |
372 | |
373 | #define PUMA_READ_MODE 0 | |
374 | #define PUMA_LOAD_MODE 1 | |
375 | ||
c83bf6a2 | 376 | int do_puma (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) |
f8cac651 WD |
377 | { |
378 | ulong addr, len; | |
379 | ||
380 | switch (argc) { | |
c83bf6a2 WD |
381 | case 2: /* PUMA reset */ |
382 | if (strncmp (argv[1], "stat", 4) == 0) { /* Reset */ | |
f8cac651 WD |
383 | puma_status (); |
384 | return 0; | |
385 | } | |
386 | break; | |
c83bf6a2 WD |
387 | case 4: /* PUMA load addr len */ |
388 | if (strcmp (argv[1], "load") != 0) | |
f8cac651 WD |
389 | break; |
390 | ||
c83bf6a2 WD |
391 | addr = simple_strtoul (argv[2], NULL, 16); |
392 | len = simple_strtoul (argv[3], NULL, 16); | |
f8cac651 WD |
393 | |
394 | printf ("PUMA load: addr %08lX len %ld (0x%lX): ", | |
395 | addr, len, len); | |
396 | puma_load (addr, len); | |
397 | ||
398 | return 0; | |
399 | default: | |
400 | break; | |
401 | } | |
402 | printf ("Usage:\n%s\n", cmdtp->usage); | |
403 | return 1; | |
404 | } | |
405 | ||
c83bf6a2 WD |
406 | U_BOOT_CMD (puma, 4, 1, do_puma, |
407 | "puma - access PUMA FPGA\n", | |
408 | "status - print PUMA status\n" | |
409 | "puma load addr len - load PUMA configuration data\n"); | |
410 | ||
d39b5741 | 411 | #endif |
f8cac651 WD |
412 | |
413 | /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */ | |
414 | ||
415 | static void puma_set_mode (int mode) | |
416 | { | |
c83bf6a2 | 417 | volatile immap_t *immr = (immap_t *) CFG_IMMR; |
f8cac651 WD |
418 | volatile memctl8xx_t *memctl = &immr->im_memctl; |
419 | ||
420 | /* disable PUMA in memory controller */ | |
421 | #if PCU_E_WITH_SWAPPED_CS /* XXX */ | |
c83bf6a2 WD |
422 | memctl->memc_br3 = 0; |
423 | #else /* XXX */ | |
424 | memctl->memc_br4 = 0; | |
425 | #endif /* XXX */ | |
f8cac651 WD |
426 | |
427 | switch (mode) { | |
428 | case PUMA_READ_MODE: | |
429 | #if PCU_E_WITH_SWAPPED_CS /* XXX */ | |
430 | memctl->memc_or3 = PUMA_CONF_OR_READ; | |
431 | memctl->memc_br3 = PUMA_CONF_BR_READ; | |
c83bf6a2 | 432 | #else /* XXX */ |
f8cac651 WD |
433 | memctl->memc_or4 = PUMA_CONF_OR_READ; |
434 | memctl->memc_br4 = PUMA_CONF_BR_READ; | |
c83bf6a2 | 435 | #endif /* XXX */ |
f8cac651 WD |
436 | break; |
437 | case PUMA_LOAD_MODE: | |
438 | #if PCU_E_WITH_SWAPPED_CS /* XXX */ | |
439 | memctl->memc_or3 = PUMA_CONF_OR_LOAD; | |
440 | memctl->memc_br3 = PUMA_CONF_BR_LOAD; | |
c83bf6a2 | 441 | #else /* XXX */ |
f8cac651 WD |
442 | memctl->memc_or4 = PUMA_CONF_OR_READ; |
443 | memctl->memc_br4 = PUMA_CONF_BR_READ; | |
c83bf6a2 | 444 | #endif /* XXX */ |
f8cac651 WD |
445 | break; |
446 | } | |
447 | } | |
448 | ||
449 | /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */ | |
450 | ||
451 | #define PUMA_INIT_TIMEOUT 1000 /* max. 1000 ms = 1 second */ | |
452 | ||
453 | static void puma_load (ulong addr, ulong len) | |
454 | { | |
c83bf6a2 WD |
455 | volatile immap_t *immr = (immap_t *) CFG_IMMR; |
456 | volatile uchar *fpga_addr = (volatile uchar *) PUMA_CONF_BASE; /* XXX ??? */ | |
457 | uchar *data = (uchar *) addr; | |
f8cac651 WD |
458 | int i; |
459 | ||
460 | /* align length */ | |
461 | if (len & 1) | |
462 | ++len; | |
463 | ||
464 | /* Reset FPGA */ | |
465 | immr->im_ioport.iop_pcpar &= ~(CFG_PC_PUMA_INIT); /* make input */ | |
466 | immr->im_ioport.iop_pcso &= ~(CFG_PC_PUMA_INIT); | |
467 | immr->im_ioport.iop_pcdir &= ~(CFG_PC_PUMA_INIT); | |
468 | ||
c83bf6a2 | 469 | #if PCU_E_WITH_SWAPPED_CS /* XXX */ |
f8cac651 WD |
470 | immr->im_cpm.cp_pbpar &= ~(CFG_PB_PUMA_PROG); /* GPIO */ |
471 | immr->im_cpm.cp_pbodr &= ~(CFG_PB_PUMA_PROG); /* active output */ | |
472 | immr->im_cpm.cp_pbdat &= ~(CFG_PB_PUMA_PROG); /* Set low */ | |
473 | immr->im_cpm.cp_pbdir |= CFG_PB_PUMA_PROG; /* output */ | |
474 | #else | |
475 | immr->im_ioport.iop_papar &= ~(CFG_PA_PUMA_PROG); /* GPIO */ | |
476 | immr->im_ioport.iop_padat &= ~(CFG_PA_PUMA_PROG); /* Set low */ | |
477 | immr->im_ioport.iop_paodr &= ~(CFG_PA_PUMA_PROG); /* active output */ | |
478 | immr->im_ioport.iop_padir |= CFG_PA_PUMA_PROG; /* output */ | |
479 | #endif /* XXX */ | |
480 | udelay (100); | |
481 | ||
c83bf6a2 WD |
482 | #if PCU_E_WITH_SWAPPED_CS /* XXX */ |
483 | immr->im_cpm.cp_pbdat |= CFG_PB_PUMA_PROG; /* release reset */ | |
f8cac651 | 484 | #else |
c83bf6a2 | 485 | immr->im_ioport.iop_padat |= CFG_PA_PUMA_PROG; /* release reset */ |
f8cac651 WD |
486 | #endif /* XXX */ |
487 | ||
488 | /* wait until INIT indicates completion of reset */ | |
c83bf6a2 | 489 | for (i = 0; i < PUMA_INIT_TIMEOUT; ++i) { |
f8cac651 WD |
490 | udelay (1000); |
491 | if (immr->im_ioport.iop_pcdat & CFG_PC_PUMA_INIT) | |
492 | break; | |
493 | } | |
494 | if (i == PUMA_INIT_TIMEOUT) { | |
495 | printf ("*** PUMA init timeout ***\n"); | |
496 | return; | |
497 | } | |
498 | ||
499 | puma_set_mode (PUMA_LOAD_MODE); | |
500 | ||
501 | while (len--) | |
502 | *fpga_addr = *data++; | |
503 | ||
504 | puma_set_mode (PUMA_READ_MODE); | |
505 | ||
506 | puma_status (); | |
507 | } | |
508 | ||
509 | /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */ | |
510 | ||
511 | static void puma_status (void) | |
512 | { | |
513 | /* Check state */ | |
514 | printf ("PUMA initialization is %scomplete\n", | |
c83bf6a2 | 515 | puma_init_done ()? "" : "NOT "); |
f8cac651 WD |
516 | } |
517 | ||
518 | /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */ | |
519 | ||
520 | static int puma_init_done (void) | |
521 | { | |
c83bf6a2 | 522 | volatile immap_t *immr = (immap_t *) CFG_IMMR; |
f8cac651 WD |
523 | |
524 | /* make sure pin is GPIO input */ | |
525 | immr->im_ioport.iop_pcpar &= ~(CFG_PC_PUMA_DONE); | |
c83bf6a2 | 526 | immr->im_ioport.iop_pcso &= ~(CFG_PC_PUMA_DONE); |
f8cac651 WD |
527 | immr->im_ioport.iop_pcdir &= ~(CFG_PC_PUMA_DONE); |
528 | ||
529 | return (immr->im_ioport.iop_pcdat & CFG_PC_PUMA_DONE) ? 1 : 0; | |
530 | } | |
531 | ||
532 | /* ------------------------------------------------------------------------- */ | |
533 | ||
534 | int misc_init_r (void) | |
535 | { | |
536 | ulong addr = 0; | |
c83bf6a2 | 537 | ulong len = 0; |
f8cac651 WD |
538 | char *s; |
539 | ||
540 | printf ("PUMA: "); | |
c83bf6a2 | 541 | if (puma_init_done ()) { |
f8cac651 WD |
542 | printf ("initialized\n"); |
543 | return 0; | |
544 | } | |
545 | ||
c83bf6a2 WD |
546 | if ((s = getenv ("puma_addr")) != NULL) |
547 | addr = simple_strtoul (s, NULL, 16); | |
f8cac651 | 548 | |
c83bf6a2 WD |
549 | if ((s = getenv ("puma_len")) != NULL) |
550 | len = simple_strtoul (s, NULL, 16); | |
f8cac651 WD |
551 | |
552 | if ((!addr) || (!len)) { | |
553 | printf ("net list undefined\n"); | |
554 | return 0; | |
555 | } | |
556 | ||
557 | printf ("loading... "); | |
558 | ||
559 | puma_load (addr, len); | |
560 | return (0); | |
561 | } | |
562 | ||
563 | /* ------------------------------------------------------------------------- */ |