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