]> git.sur5r.net Git - u-boot/blob - board/hermes/hermes.c
97a7745708eb1d7fb14d963da1f4a0622e4b0ea0
[u-boot] / board / hermes / hermes.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
24 #include <common.h>
25 #include <commproc.h>
26 #include <mpc8xx.h>
27
28 #ifdef CONFIG_SHOW_BOOT_PROGRESS
29 # include <status_led.h>
30 # define SHOW_BOOT_PROGRESS(arg)        show_boot_progress(arg)
31 #else
32 # define SHOW_BOOT_PROGRESS(arg)
33 #endif
34
35 /* ------------------------------------------------------------------------- */
36
37 static long int dram_size (long int, long int *, long int);
38 static ulong board_init (void);
39 static void send_smi_frame (volatile scc_t * sp, volatile cbd_t * bd,
40                                                         uchar * msg);
41
42 /* ------------------------------------------------------------------------- */
43
44 #define _NOT_USED_      0xFFFFFFFF
45
46 const uint sdram_table[] = {
47         /*
48          * Single Read. (Offset 0 in UPMA RAM)
49          */
50         0x1f07fc04, 0xeeaefc04, 0x11adfc04, 0xefbbbc00,
51         0x1ff77c47,                                     /* last */
52         /*
53          * SDRAM Initialization (offset 5 in UPMA 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         0x1fe77c35, 0xffaffc34, 0x1fa57c35,     /* last */
61         /*
62          * Burst Read. (Offset 8 in UPMA RAM)
63          */
64         0x1f07fc04, 0xeeaefc04, 0x10adfc04, 0xf0affc00,
65         0xf0affc00, 0xf1affc00, 0xefbbbc00, 0x1ff77c47, /* last */
66         _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_,
67         _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_,
68         /*
69          * Single Write. (Offset 18 in UPMA RAM)
70          */
71         0x1f27fc04, 0xeeaebc00, 0x01b93c04, 0x1ff77c47, /* last */
72         _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_,
73         /*
74          * Burst Write. (Offset 20 in UPMA RAM)
75          */
76         0x1f07fc04, 0xeeaebc00, 0x10ad4c00, 0xf0afcc00,
77         0xf0afcc00, 0xe1bb8c06, 0x1ff77c47,     /* last */
78         _NOT_USED_,
79         _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_,
80         _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_,
81         /*
82          * Refresh  (Offset 30 in UPMA RAM)
83          */
84         0x1ff5fc84, 0xfffffc04, 0xfffffc04, 0xfffffc04,
85         0xfffffc84, 0xfffffc07,         /* last */
86         _NOT_USED_, _NOT_USED_,
87         _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_,
88         /*
89          * Exception. (Offset 3c in UPMA RAM)
90          */
91         0x7ffffc07,                                     /* last */
92         _NOT_USED_, _NOT_USED_, _NOT_USED_,
93 };
94
95 /* ------------------------------------------------------------------------- */
96
97
98 /*
99  * Check Board Identity:
100  *
101  * Test ID string (HERMES...)
102  *
103  * Return code for board revision and network speed
104  */
105
106 int checkboard (void)
107 {
108         DECLARE_GLOBAL_DATA_PTR;
109
110         unsigned char *s = getenv ("serial#");
111         unsigned char *e;
112
113         puts ("Board: ");
114
115         if (!s || strncmp (s, "HERMES", 6)) {
116                 puts ("### No HW ID - assuming HERMES-PRO");
117         } else {
118                 for (e = s; *e; ++e) {
119                         if (*e == ' ')
120                                 break;
121                 }
122
123                 for (; s < e; ++s) {
124                         putc (*s);
125                 }
126         }
127
128         gd->board_type = board_init ();
129
130         printf ("  Rev. %ld.x\n", (gd->board_type >> 16));
131
132         return (0);
133 }
134
135 /* ------------------------------------------------------------------------- */
136
137 long int initdram (int board_type)
138 {
139         volatile immap_t *immap = (immap_t *) CFG_IMMR;
140         volatile memctl8xx_t *memctl = &immap->im_memctl;
141         long int size, size8, size9;
142
143         upmconfig (UPMA, (uint *) sdram_table,
144                            sizeof (sdram_table) / sizeof (uint));
145
146         /*
147          * Preliminary prescaler for refresh
148          */
149         memctl->memc_mptpr = 0x0400;
150
151         memctl->memc_mar = 0x00000088;
152
153         /*
154          * Map controller banks 1 to the SDRAM banks at preliminary address
155          */
156         memctl->memc_or1 = CFG_OR1_PRELIM;
157         memctl->memc_br1 = CFG_BR1_PRELIM;
158
159         /* HERMES-PRO boards have only one bank SDRAM */
160
161
162         udelay (200);
163
164         /* perform SDRAM initializsation sequence */
165
166         memctl->memc_mamr = 0xD0802114;
167         memctl->memc_mcr = 0x80002105;
168         udelay (1);
169         memctl->memc_mamr = 0xD0802118;
170         memctl->memc_mcr = 0x80002130;
171         udelay (1);
172         memctl->memc_mamr = 0xD0802114;
173         memctl->memc_mcr = 0x80002106;
174
175         udelay (1000);
176
177         /*
178          * Check Bank 0 Memory Size for re-configuration
179          *
180          * try 8 column mode
181          */
182         size8 = dram_size (CFG_MAMR_8COL, (ulong *) SDRAM_BASE_PRELIM,
183                                            SDRAM_MAX_SIZE);
184
185         udelay (1000);
186
187         /*
188          * try 9 column mode
189          */
190         size9 = dram_size (CFG_MAMR_9COL, (ulong *) SDRAM_BASE_PRELIM,
191                                            SDRAM_MAX_SIZE);
192
193         if (size8 < size9) {            /* leave configuration at 9 columns */
194                 size = size9;
195 /*      debug ("SDRAM Bank 0 in 9 column mode: %ld MB\n", size >> 20);  */
196         } else {                                        /* back to 8 columns            */
197                 size = size8;
198                 memctl->memc_mamr = CFG_MAMR_8COL;
199                 udelay (500);
200 /*      debug ("SDRAM Bank 0 in 8 column mode: %ld MB\n", size >> 20);  */
201         }
202
203         udelay (1000);
204
205         memctl->memc_or1 = ((-size) & 0xFFFF0000) | SDRAM_TIMING;
206         memctl->memc_br1 = (CFG_SDRAM_BASE & BR_BA_MSK) | BR_MS_UPMA | BR_V;
207
208         udelay (10000);
209
210         return (size);
211 }
212
213 /* ------------------------------------------------------------------------- */
214
215 /*
216  * Check memory range for valid RAM. A simple memory test determines
217  * the actually available RAM size between addresses `base' and
218  * `base + maxsize'. Some (not all) hardware errors are detected:
219  * - short between address lines
220  * - short between data lines
221  */
222
223 static long int dram_size (long int mamr_value, long int *base,
224                                                    long int maxsize)
225 {
226         volatile immap_t *immap = (immap_t *) CFG_IMMR;
227         volatile memctl8xx_t *memctl = &immap->im_memctl;
228         volatile long int *addr;
229         ulong cnt, val;
230         ulong save[32];                         /* to make test non-destructive */
231         unsigned char i = 0;
232
233         memctl->memc_mamr = mamr_value;
234
235         for (cnt = maxsize / sizeof (long); cnt > 0; cnt >>= 1) {
236                 addr = base + cnt;              /* pointer arith! */
237
238                 save[i++] = *addr;
239                 *addr = ~cnt;
240         }
241
242         /* write 0 to base address */
243         addr = base;
244         save[i] = *addr;
245         *addr = 0;
246
247         /* check at base address */
248         if ((val = *addr) != 0) {
249                 *addr = save[i];
250                 return (0);
251         }
252
253         for (cnt = 1; cnt <= maxsize / sizeof (long); cnt <<= 1) {
254                 addr = base + cnt;              /* pointer arith! */
255
256                 val = *addr;
257                 *addr = save[--i];
258
259                 if (val != (~cnt)) {
260                         return (cnt * sizeof (long));
261                 }
262         }
263         return (maxsize);
264 }
265
266 /* ------------------------------------------------------------------------- */
267
268 #define PB_LED_3        0x00020000      /* Status LED's */
269 #define PB_LED_2        0x00010000
270 #define PB_LED_1        0x00008000
271 #define PB_LED_0        0x00004000
272
273 #define PB_LED_ALL      (PB_LED_0 | PB_LED_1 | PB_LED_2 | PB_LED_3)
274
275 #define PC_REP_SPD1     0x00000800
276 #define PC_REP_SPD0     0x00000400
277
278 #define PB_RESET_2081   0x00000020      /* Reset PEB2081 */
279
280 #define PB_MAI_4        0x00000010      /* Configuration */
281 #define PB_MAI_3        0x00000008
282 #define PB_MAI_2        0x00000004
283 #define PB_MAI_1        0x00000002
284 #define PB_MAI_0        0x00000001
285
286 #define PB_MAI_ALL      (PB_MAI_0 | PB_MAI_1 | PB_MAI_2 | PB_MAI_3 | PB_MAI_4)
287
288
289 #define PC_REP_MGRPRS   0x0200
290 #define PC_REP_SPD      0x0040          /* Select 100 Mbps */
291 #define PC_REP_RES      0x0004
292 #define PC_BIT14        0x0002          /* ??? */
293 #define PC_BIT15        0x0001          /* ??? ENDSL ?? */
294
295 /* ------------------------------------------------------------------------- */
296
297 static ulong board_init (void)
298 {
299         volatile immap_t *immr = (immap_t *) CFG_IMMR;
300         ulong reg, revision, speed = 100;
301         int ethspeed;
302         char *s;
303
304         if ((s = getenv ("ethspeed")) != NULL) {
305                 if (strcmp (s, "100") == 0) {
306                         ethspeed = 100;
307                 } else if (strcmp (s, "10") == 0) {
308                         ethspeed = 10;
309                 } else {
310                         ethspeed = 0;
311                 }
312         } else {
313                 ethspeed = 0;
314         }
315
316         /* Configure Port B Output Pins => 0x0003cc3F */
317         reg = PB_LED_ALL | PC_REP_SPD1 | PC_REP_SPD0 | PB_RESET_2081 |
318                         PB_MAI_ALL;
319         immr->im_cpm.cp_pbpar &= ~reg;
320         immr->im_cpm.cp_pbodr &= ~reg;
321         immr->im_cpm.cp_pbdat &= ~reg;  /* all 0 */
322         immr->im_cpm.cp_pbdir |= reg;
323
324         /* Check hardware revision */
325         if ((immr->im_ioport.iop_pcdat & 0x0003) == 0x0003) {
326                 /*
327                  * Revision 3.x hardware
328                  */
329                 revision = 3;
330
331                 immr->im_ioport.iop_pcdat = 0x0240;
332                 immr->im_ioport.iop_pcdir = (PC_REP_MGRPRS | PC_REP_SPD | PC_REP_RES | PC_BIT14);       /* = 0x0246 */
333                 immr->im_ioport.iop_pcdat |= PC_REP_RES;
334         } else {
335                 immr->im_ioport.iop_pcdat = 0x0002;
336                 immr->im_ioport.iop_pcdir = (PC_REP_MGRPRS | PC_REP_RES | PC_BIT14 | PC_BIT15); /* = 0x0207 */
337
338                 if ((immr->im_ioport.iop_pcdat & PC_REP_SPD) == 0) {
339                         /*
340                          * Revision 2.x hardware: PC9 connected to PB21
341                          */
342                         revision = 2;
343
344                         if (ethspeed == 0) {
345                                 /* both 10 and 100 Mbps allowed:
346                                  * select 10 Mbps and autonegotiation
347                                  */
348                                 puts ("  [10+100]");
349                                 immr->im_cpm.cp_pbdat = 0;      /* SPD1:SPD0 = 0:0 - autonegot. */
350                                 speed = 10;
351                         } else if (ethspeed == 10) {
352                                 /* we are asked for 10 Mbps,
353                                  * so select 10 Mbps
354                                  */
355                                 puts ("  [10]");
356                                 immr->im_cpm.cp_pbdat = 0;      /* ??? */
357                                 speed = 10;
358                         } else {
359                                 /* anything else:
360                                  * select 100 Mbps
361                                  */
362                                 puts ("  [100]");
363                                 immr->im_cpm.cp_pbdat = PC_REP_SPD0 | PC_REP_SPD1;
364                                 /* SPD1:SPD0 = 1:1 - 100 Mbps */
365                                 speed = 100;
366                         }
367                         immr->im_ioport.iop_pcdat |= (PC_REP_RES | PC_BIT14);
368
369                         /* must be run from RAM  */
370                         /* start_lxt980 (speed); */
371                 /*************************/
372                 } else {
373                         /*
374                          * Revision 1.x hardware
375                          */
376                         revision = 1;
377
378                         immr->im_ioport.iop_pcdat = PC_REP_MGRPRS | PC_BIT14;   /* = 0x0202 */
379                         immr->im_ioport.iop_pcdir = (PC_REP_MGRPRS | PC_REP_SPD | PC_REP_RES | PC_BIT14 | PC_BIT15);    /* = 0x0247 */
380
381                         if (ethspeed == 0) {
382                                 /* both 10 and 100 Mbps allowed:
383                                  * select 100 Mbps and autonegotiation
384                                  */
385                                 puts ("  [10+100]");
386                                 immr->im_cpm.cp_pbdat = 0;      /* SPD1:SPD0 = 0:0 - autonegot. */
387                                 immr->im_ioport.iop_pcdat |= PC_REP_SPD;
388                         } else if (ethspeed == 10) {
389                                 /* we are asked for 10 Mbps,
390                                    * so select 10 Mbps
391                                  */
392                                 puts ("  [10]");
393                                 immr->im_cpm.cp_pbdat = PC_REP_SPD0;    /* SPD1:SPD0 = 0:1 - 10 Mbps */
394                         } else {
395                                 /* anything else:
396                                    * select 100 Mbps
397                                  */
398                                 puts ("  [100]");
399                                 immr->im_cpm.cp_pbdat = PC_REP_SPD0 | PC_REP_SPD1;
400                                 /* SPD1:SPD0 = 1:1 - 100 Mbps */
401                                 immr->im_ioport.iop_pcdat |= PC_REP_SPD;
402                         }
403
404                         immr->im_ioport.iop_pcdat |= PC_REP_RES;
405                 }
406         }
407         SHOW_BOOT_PROGRESS (0x00);
408
409         return ((revision << 16) | (speed & 0xFFFF));
410 }
411
412 /* ------------------------------------------------------------------------- */
413
414 #define SCC_SM          1                       /* Index => SCC2 */
415 #define PROFF           PROFF_SCC2
416
417 #define SMI_MSGLEN      8                       /* Length of SMI Messages        */
418
419 #define PHYGPCR_ADDR    0x109   /* Port Enable               */
420 #define PHYPCR_ADDR     0x132           /* PHY Port Control Reg. (port 1)    */
421 #define LEDPCR_ADDR     0x141           /* LED Port Control Reg.         */
422 #define RPRESET_ADDR    0x144   /* Repeater Reset            */
423
424 #define PHYPCR_SPEED    0x2000  /* on for 100 Mbps, off for 10 Mbps  */
425 #define PHYPCR_AN       0x1000          /* on to enable  Auto-Negotiation    */
426 #define PHYPCR_REST_AN  0x0200  /* on to restart Auto-Negotiation    */
427 #define PHYPCR_FDX      0x0100          /* on for Full Duplex, off for HDX   */
428 #define PHYPCR_COLT     0x0080          /* on to enable COL signal test      */
429
430 /* ------------------------------------------------------------------------- */
431
432 /*
433  * Must run from RAM:
434  * uses parameter RAM area which is used for stack while running from ROM
435  */
436 void hermes_start_lxt980 (int speed)
437 {
438         volatile immap_t *immr = (immap_t *) CFG_IMMR;
439         volatile cpm8xx_t *cp = (cpm8xx_t *) & (immr->im_cpm);
440         volatile scc_t *sp = (scc_t *) & (cp->cp_scc[SCC_SM]);
441         volatile cbd_t *bd;
442         volatile hdlc_pram_t *hp;
443         uchar smimsg[SMI_MSGLEN];
444         ushort phypcrval;
445         uint bd_off;
446         int pnr;
447
448         printf ("LXT9880: %3d Mbps\n", speed);
449
450         immr->im_ioport.iop_paodr |= 0x0008;    /* init PAODR: PA12 (TXD2) open drain */
451         immr->im_ioport.iop_papar |= 0x400c;    /* init PAPAR: TXD2, RXD2, BRGO4 */
452         immr->im_ioport.iop_padir &= 0xbff3;    /* init PADIR: BRGO4 */
453         immr->im_ioport.iop_padir |= 0x4000;
454
455         /* get temporary BD; no need for permanent alloc */
456         bd_off = dpram_base_align (8);
457
458         bd = (cbd_t *) (immr->im_cpm.cp_dpmem + bd_off);
459
460         bd->cbd_bufaddr = 0;
461         bd->cbd_datlen = 0;
462         bd->cbd_sc = BD_SC_WRAP | BD_SC_LAST | BD_SC_INTRPT | BD_SC_TC;
463
464         /* init. baudrate generator BRG4 */
465         cp->cp_brgc4 = (0x00010000 | (50 << 1));        /* output 1 MHz */
466
467         cp->cp_sicr &= 0xFFFF00FF;      /* SICR: mask SCC2 */
468         cp->cp_sicr |= 0x00001B00;      /* SICR: SCC2 clk BRG4 */
469
470         /* init SCC_SM register */
471         sp->scc_psmr = 0x0000;          /* init PSMR: no additional flags */
472         sp->scc_todr = 0x0000;
473         sp->scc_dsr = 0x7e7e;
474
475         /* init. SCC_SM parameter area */
476         hp = (hdlc_pram_t *) & cp->cp_dparam[PROFF];
477
478         hp->tbase = bd_off;                     /* offset from beginning of DPRAM */
479
480         hp->rfcr = 0x18;
481         hp->tfcr = 0x18;
482         hp->mrblr = 10;
483
484         hp->c_mask = 0x0000f0b8;
485         hp->c_pres = 0x0000ffff;
486
487         hp->disfc = 0;
488         hp->crcec = 0;
489         hp->abtsc = 0;
490         hp->nmarc = 0;
491         hp->retrc = 0;
492
493         hp->mflr = 10;
494
495         hp->rfthr = 1;
496
497         hp->hmask = 0;
498         hp->haddr1 = 0;
499         hp->haddr2 = 0;
500         hp->haddr3 = 0;
501         hp->haddr4 = 0;
502
503         cp->cp_cpcr = SCC_SM << 6 | 0x0001;     /* SCC_SM: init TX/RX params */
504         while (cp->cp_cpcr & CPM_CR_FLG);
505
506         /* clear all outstanding SCC events */
507         sp->scc_scce = ~0;
508
509         /* enable transmitter: GSMR_L: TPL=2(16bits), TPP=3(all ones), ENT */
510         sp->scc_gsmrh = 0;
511         sp->scc_gsmrl |= SCC_GSMRL_TPL_16 | SCC_GSMRL_TPP_ALL1 |
512                         SCC_GSMRL_ENT | SCC_GSMRL_MODE_HDLC;
513
514 #if 0
515         smimsg[0] = 0x00;                       /* CHIP/HUB ID */
516         smimsg[1] = 0x38;                       /* WRITE CMD */
517         smimsg[2] = (RPRESET_ADDR << 4) & 0xf0;
518         smimsg[3] = RPRESET_ADDR >> 4;
519         smimsg[4] = 0x01;
520         smimsg[5] = 0x00;
521         smimsg[6] = 0x00;
522         smimsg[7] = 0x00;
523
524         send_smi_frame (sp, bd, smimsg);
525 #endif
526
527         smimsg[0] = 0x7f;                       /* BROADCAST */
528         smimsg[1] = 0x34;                       /* ASSIGN HUB ID */
529         smimsg[2] = 0x00;
530         smimsg[3] = 0x00;
531         smimsg[4] = 0x00;                       /* HUB ID = 0 */
532         smimsg[5] = 0x00;
533         smimsg[6] = 0x00;
534         smimsg[7] = 0x00;
535
536         send_smi_frame (sp, bd, smimsg);
537
538         smimsg[0] = 0x7f;                       /* BROADCAST */
539         smimsg[1] = 0x3c;                       /* SET ARBOUT TO 0 */
540         smimsg[2] = 0x00;                       /* ADDRESS = 0 */
541         smimsg[3] = 0x00;
542         smimsg[4] = 0x00;                       /* DATA = 0 */
543         smimsg[5] = 0x00;
544         smimsg[6] = 0x00;
545         smimsg[7] = 0x00;
546
547         send_smi_frame (sp, bd, smimsg);
548
549         if (speed == 100) {
550                 phypcrval = PHYPCR_SPEED;       /* 100 MBIT, disable autoneg. */
551         } else {
552                 phypcrval = 0;                  /* 10 MBIT, disable autoneg. */
553         }
554
555         /* send MSGs */
556         for (pnr = 0; pnr < 8; pnr++) {
557                 smimsg[0] = 0x00;               /* CHIP/HUB ID */
558                 smimsg[1] = 0x38;               /* WRITE CMD */
559                 smimsg[2] = ((PHYPCR_ADDR + pnr) << 4) & 0xf0;
560                 smimsg[3] = (PHYPCR_ADDR + pnr) >> 4;
561                 smimsg[4] = (unsigned char) (phypcrval & 0xff);
562                 smimsg[5] = (unsigned char) (phypcrval >> 8);
563                 smimsg[6] = 0x00;
564                 smimsg[7] = 0x00;
565
566                 send_smi_frame (sp, bd, smimsg);
567         }
568
569         smimsg[0] = 0x00;                       /* CHIP/HUB ID */
570         smimsg[1] = 0x38;                       /* WRITE CMD */
571         smimsg[2] = (PHYGPCR_ADDR << 4) & 0xf0;
572         smimsg[3] = PHYGPCR_ADDR >> 4;
573         smimsg[4] = 0xff;                       /* enable port 1-8 */
574         smimsg[5] = 0x01;                       /* enable MII1 (0x01) */
575         smimsg[6] = 0x00;
576         smimsg[7] = 0x00;
577
578         send_smi_frame (sp, bd, smimsg);
579
580         smimsg[0] = 0x00;                       /* CHIP/HUB ID */
581         smimsg[1] = 0x38;                       /* WRITE CMD */
582         smimsg[2] = (LEDPCR_ADDR << 4) & 0xf0;
583         smimsg[3] = LEDPCR_ADDR >> 4;
584         smimsg[4] = 0xaa;                       /* Port 1-8 Conf.bits = 10 (Hardware control) */
585         smimsg[5] = 0xaa;
586         smimsg[6] = 0x00;
587         smimsg[7] = 0x00;
588
589         send_smi_frame (sp, bd, smimsg);
590
591         /*
592          * Disable Transmitter (so that we can free the BD, too)
593          */
594         sp->scc_gsmrl &= ~SCC_GSMRL_ENT;
595 }
596
597 /* ------------------------------------------------------------------------- */
598
599 static void send_smi_frame (volatile scc_t * sp, volatile cbd_t * bd,
600                                                         uchar * msg)
601 {
602 #ifdef DEBUG
603         unsigned hub, chip, cmd, length, addr;
604
605         hub = msg[0] & 0x1F;
606         chip = msg[0] >> 5;
607         cmd = msg[1] & 0x1F;
608         length = (msg[1] >> 5) | ((msg[2] & 0x0F) << 3);
609         addr = (msg[2] >> 4) | (msg[3] << 4);
610
611         printf ("SMI send: Hub %02x Chip %x Cmd %02x Len %d Addr %03x: "
612                         "%02x %02x %02x %02x\n",
613                         hub, chip, cmd, length, addr, msg[4], msg[5], msg[6], msg[7]);
614 #endif /* DEBUG */
615
616         bd->cbd_bufaddr = (uint) msg;
617         bd->cbd_datlen = SMI_MSGLEN;
618         bd->cbd_sc |= BD_SC_READY;
619
620         /* wait for msg transmitted */
621         while ((sp->scc_scce & 0x0002) == 0);
622         /* clear all events */
623         sp->scc_scce = ~0;
624 }
625
626 /* ------------------------------------------------------------------------- */
627
628 void show_boot_progress (int status)
629 {
630         volatile immap_t *immr = (immap_t *) CFG_IMMR;
631
632         status ^= 0x0F;
633         status = (status & 0x0F) << 14;
634         immr->im_cpm.cp_pbdat = (immr->im_cpm.cp_pbdat & ~PB_LED_ALL) | status;
635 }
636
637 /* ------------------------------------------------------------------------- */