blob: 0a67090feaa9851e85974c51ddef8e7827c0a9bc [file] [log] [blame]
wdenkc6097192002-11-03 00:24:07 +00001/*
2 * (C) Copyright 2001
3 * Denis Peter, MPL AG Switzerland, d.peter@mpl.ch
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
25#include <common.h>
26#include <command.h>
27#include <video_fb.h>
28#include "common_util.h"
29#include <asm/processor.h>
wdenk1cb8e982003-03-06 21:55:29 +000030#include <asm/byteorder.h>
wdenkc6097192002-11-03 00:24:07 +000031#include <i2c.h>
32#include <devices.h>
33#include <pci.h>
34
35extern int gunzip (void *, int, unsigned char *, int *);
36extern int mem_test(unsigned long start, unsigned long ramsize, int quiet);
37
38#define I2C_BACKUP_ADDR 0x7C00 /* 0x200 bytes for backup */
39#define IMAGE_SIZE 0x80000
40
41extern flash_info_t flash_info[]; /* info for FLASH chips */
42
wdenk1cb8e982003-03-06 21:55:29 +000043static image_header_t header;
wdenkc6097192002-11-03 00:24:07 +000044
45
46
47int mpl_prg(unsigned long src,unsigned long size)
48{
49 unsigned long start;
50 flash_info_t *info;
51 int i,rc;
52 unsigned long *magic = (unsigned long *)src;
53
54 info = &flash_info[0];
wdenk1cb8e982003-03-06 21:55:29 +000055
56#if defined(CONFIG_PIP405) || defined(CONFIG_MIP405)
57 if(ntohl(magic[0]) != IH_MAGIC) {
58 printf("Bad Magic number\n");
59 return -1;
60 }
61
wdenkc6097192002-11-03 00:24:07 +000062 start = 0 - size;
63 for(i=info->sector_count-1;i>0;i--)
64 {
65 info->protect[i] = 0; /* unprotect this sector */
66 if(start>=info->start[i])
67 break;
68 }
69 /* set-up flash location */
70 /* now erase flash */
wdenkc6097192002-11-03 00:24:07 +000071 printf("Erasing at %lx (sector %d) (start %lx)\n",
72 start,i,info->start[i]);
73 flash_erase (info, i, info->sector_count-1);
wdenk1cb8e982003-03-06 21:55:29 +000074
75#elif defined(CONFIG_VCMA9)
76 start = 0;
77 for (i = 0; i <info->sector_count; i++)
78 {
79 info->protect[i] = 0; /* unprotect this sector */
80 if (size < info->start[i])
81 break;
82 }
83 /* set-up flash location */
84 /* now erase flash */
85 printf("Erasing at %lx (sector %d) (start %lx)\n",
86 start,0,info->start[0]);
87 flash_erase (info, 0, i);
88
89#endif
wdenkc6097192002-11-03 00:24:07 +000090 printf("flash erased, programming from 0x%lx 0x%lx Bytes\n",src,size);
91 if ((rc = flash_write ((uchar *)src, start, size)) != 0) {
92 puts ("ERROR ");
93 flash_perror (rc);
94 return (1);
95 }
96 puts ("OK programming done\n");
97 return 0;
98}
99
100
101int mpl_prg_image(unsigned long ld_addr)
102{
103 unsigned long data,len,checksum;
104 image_header_t *hdr=&header;
105 /* Copy header so we can blank CRC field for re-calculation */
106 memcpy (&header, (char *)ld_addr, sizeof(image_header_t));
wdenk1cb8e982003-03-06 21:55:29 +0000107 if (ntohl(hdr->ih_magic) != IH_MAGIC) {
wdenkc6097192002-11-03 00:24:07 +0000108 printf ("Bad Magic Number\n");
109 return 1;
110 }
111 print_image_hdr(hdr);
112 if (hdr->ih_os != IH_OS_U_BOOT) {
113 printf ("No U-Boot Image\n");
114 return 1;
115 }
116 if (hdr->ih_type != IH_TYPE_FIRMWARE) {
117 printf ("No Firmware Image\n");
118 return 1;
119 }
120 data = (ulong)&header;
121 len = sizeof(image_header_t);
wdenk1cb8e982003-03-06 21:55:29 +0000122 checksum = ntohl(hdr->ih_hcrc);
wdenkc6097192002-11-03 00:24:07 +0000123 hdr->ih_hcrc = 0;
124 if (crc32 (0, (char *)data, len) != checksum) {
125 printf ("Bad Header Checksum\n");
126 return 1;
127 }
128 data = ld_addr + sizeof(image_header_t);
wdenk1cb8e982003-03-06 21:55:29 +0000129 len = ntohl(hdr->ih_size);
wdenkc6097192002-11-03 00:24:07 +0000130 printf ("Verifying Checksum ... ");
wdenk1cb8e982003-03-06 21:55:29 +0000131 if (crc32 (0, (char *)data, len) != ntohl(hdr->ih_dcrc)) {
wdenkc6097192002-11-03 00:24:07 +0000132 printf ("Bad Data CRC\n");
133 return 1;
134 }
135 switch (hdr->ih_comp) {
136 case IH_COMP_NONE:
137 break;
138 case IH_COMP_GZIP:
139 printf (" Uncompressing ... ");
140 if (gunzip ((void *)(data+0x100000), 0x400000,
141 (uchar *)data, (int *)&len) != 0) {
142 printf ("GUNZIP ERROR\n");
143 return 1;
144 }
145 data+=0x100000;
146 break;
147 default:
148 printf (" Unimplemented compression type %d\n", hdr->ih_comp);
149 return 1;
150 }
151
152 printf (" OK\n");
153 return(mpl_prg(data,len));
154}
155
156
157void get_backup_values(backup_t *buf)
158{
159 i2c_read(CFG_DEF_EEPROM_ADDR, I2C_BACKUP_ADDR,2,(void *)buf,sizeof(backup_t));
160}
161
162void set_backup_values(int overwrite)
163{
164 backup_t back;
165 int i;
166
167 get_backup_values(&back);
168 if(!overwrite) {
169 if(strncmp(back.signature,"MPL\0",4)==0) {
170 printf("Not possible to write Backup\n");
171 return;
172 }
173 }
174 memcpy(back.signature,"MPL\0",4);
wdenk1cb8e982003-03-06 21:55:29 +0000175 i = getenv_r("serial#",back.serial_name,16);
176 if(i < 0) {
wdenkc6097192002-11-03 00:24:07 +0000177 printf("Not possible to write Backup\n");
178 return;
179 }
180 back.serial_name[16]=0;
wdenk1cb8e982003-03-06 21:55:29 +0000181 i = getenv_r("ethaddr",back.eth_addr,20);
182 if(i < 0) {
wdenkc6097192002-11-03 00:24:07 +0000183 printf("Not possible to write Backup\n");
184 return;
185 }
186 back.eth_addr[20]=0;
187 i2c_write(CFG_DEF_EEPROM_ADDR, I2C_BACKUP_ADDR,2,(void *)&back,sizeof(backup_t));
188}
189
190void clear_env_values(void)
191{
192 backup_t back;
193 unsigned char env_crc[4];
194
195 memset(&back,0xff,sizeof(backup_t));
196 memset(env_crc,0x00,4);
197 i2c_write(CFG_DEF_EEPROM_ADDR,I2C_BACKUP_ADDR,2,(void *)&back,sizeof(backup_t));
198 i2c_write(CFG_DEF_EEPROM_ADDR,CFG_ENV_OFFSET,2,(void *)env_crc,4);
199}
200
201/*
202 * check crc of "older" environment
203 */
204int check_env_old_size(ulong oldsize)
205{
206 ulong crc, len, new;
207 unsigned off;
208 uchar buf[64];
209
210 /* read old CRC */
211 eeprom_read (CFG_DEF_EEPROM_ADDR,
212 CFG_ENV_OFFSET,
213 (uchar *)&crc, sizeof(ulong));
214
215 new = 0;
216 len = oldsize;
217 off = sizeof(long);
218 len = oldsize-off;
219 while (len > 0) {
220 int n = (len > sizeof(buf)) ? sizeof(buf) : len;
221
222 eeprom_read (CFG_DEF_EEPROM_ADDR, CFG_ENV_OFFSET+off, buf, n);
223 new = crc32 (new, buf, n);
224 len -= n;
225 off += n;
226 }
227
228 return (crc == new);
229}
230
231static ulong oldsizes[] = {
232 0x200,
233 0x800,
234 0
235};
236
237void copy_old_env(ulong size)
238{
239 uchar name_buf[64];
240 uchar value_buf[0x800];
241 uchar c;
242 ulong len;
243 unsigned off;
244 uchar *name, *value;
245
246 name=&name_buf[0];
247 value=&value_buf[0];
248 len=size;
249 off = sizeof(long);
250 while (len > off) {
251 eeprom_read (CFG_DEF_EEPROM_ADDR, CFG_ENV_OFFSET+off, &c, 1);
252 if(c != '=') {
253 *name++=c;
254 off++;
255 }
256 else {
257 *name++='\0';
258 off++;
259 do {
260 eeprom_read (CFG_DEF_EEPROM_ADDR, CFG_ENV_OFFSET+off, &c, 1);
261 *value++=c;
262 off++;
263 if(c == '\0')
264 break;
265 } while(len > off);
266 name=&name_buf[0];
267 value=&value_buf[0];
268 if(strncmp(name,"baudrate",8)!=0) {
269 setenv(name,value);
270 }
271
272 }
273 }
274}
275
276
277void check_env(void)
278{
279 unsigned char *s;
280 int i=0;
281 char buf[32];
282 backup_t back;
283
284 s=getenv("serial#");
285 if(!s) {
286 while(oldsizes[i]) {
287 if(check_env_old_size(oldsizes[i]))
288 break;
289 i++;
290 }
291 if(!oldsizes[i]) {
292 /* no old environment has been found */
293 get_backup_values (&back);
294 if (strncmp (back.signature, "MPL\0", 4) == 0) {
295 sprintf (buf, "%s", back.serial_name);
296 setenv ("serial#", buf);
297 sprintf (buf, "%s", back.eth_addr);
298 setenv ("ethaddr", buf);
299 printf ("INFO: serial# and ethaddr recovered, use saveenv\n");
300 return;
301 }
302 }
303 else {
304 copy_old_env(oldsizes[i]);
305 printf ("INFO: old environment ajusted, use saveenv\n");
306 }
307 }
308 else {
309 /* check if back up is set */
310 get_backup_values(&back);
311 if(strncmp(back.signature,"MPL\0",4)!=0) {
312 set_backup_values(0);
313 }
314 }
315}
316
317
318
319extern device_t *stdio_devices[];
320extern char *stdio_names[];
321
322void show_stdio_dev(void)
323{
wdenk47cd00f2003-03-06 13:39:27 +0000324 /* Print information */
wdenkc6097192002-11-03 00:24:07 +0000325 printf ("In: ");
326 if (stdio_devices[stdin] == NULL) {
327 printf ("No input devices available!\n");
328 } else {
329 printf ("%s\n", stdio_devices[stdin]->name);
330 }
331
332 printf ("Out: ");
333 if (stdio_devices[stdout] == NULL) {
334 printf ("No output devices available!\n");
335 } else {
336 printf ("%s\n", stdio_devices[stdout]->name);
337 }
338
339 printf ("Err: ");
340 if (stdio_devices[stderr] == NULL) {
341 printf ("No error devices available!\n");
342 } else {
343 printf ("%s\n", stdio_devices[stderr]->name);
344 }
345}
346
347/* ------------------------------------------------------------------------- */
348
349 /* switches the cs0 and the cs1 to the locations.
350 When boot is TRUE, the the mapping is switched
351 to the boot configuration, If it is FALSE, the
352 flash will be switched in the boot area */
353
354#undef SW_CS_DBG
355#ifdef SW_CS_DBG
356#define SW_CS_PRINTF(fmt,args...) printf (fmt ,##args)
357#else
358#define SW_CS_PRINTF(fmt,args...)
359#endif
360
wdenk1cb8e982003-03-06 21:55:29 +0000361#if defined(CONFIG_PIP405) || defined(CONFIG_MIP405)
wdenkc6097192002-11-03 00:24:07 +0000362int switch_cs(unsigned char boot)
363{
364 unsigned long pbcr;
365 mtdcr(ebccfga, pb0cr); /* get cs0 config reg */
366 pbcr = mfdcr(ebccfgd);
367 if((pbcr&0x00002000)==0) {
368 /* we need only to switch if boot from MPS */
369 /*printf(" MPS boot mode detected. ");*/
370 /* printf("cs0 cfg: %lx\n",pbcr); */
371 if(boot) {
372 /* switch to boot configuration */
373 /* this is a 8bit boot, switch cs0 to flash location */
374 SW_CS_PRINTF("switch to boot mode (MPS on High address\n");
375 pbcr&=0x000FFFFF; /*mask base address of the cs0 */
376 pbcr|=(FLASH_BASE0_PRELIM & 0xFFF00000);
377 mtdcr(ebccfga, pb0cr);
378 mtdcr(ebccfgd, pbcr);
379 SW_CS_PRINTF(" new cs0 cfg: %lx\n",pbcr);
380 mtdcr(ebccfga, pb1cr); /* get cs1 config reg (flash) */
381 pbcr = mfdcr(ebccfgd);
382 SW_CS_PRINTF(" old cs1 cfg: %lx\n",pbcr);
383 pbcr&=0x000FFFFF; /*mask base address of the cs1 */
384 pbcr|=(MULTI_PURPOSE_SOCKET_ADDR & 0xFFF00000);
385 mtdcr(ebccfga, pb1cr);
386 mtdcr(ebccfgd, pbcr);
387 SW_CS_PRINTF(" new cs1 cfg: %lx, MPS is on High Address\n",pbcr);
388 }
389 else
390 {
391 /* map flash to boot area, */
392 SW_CS_PRINTF("map Flash to boot area\n");
393 pbcr&=0x000FFFFF; /*mask base address of the cs0 */
394 pbcr|=(MULTI_PURPOSE_SOCKET_ADDR & 0xFFF00000);
395 mtdcr(ebccfga, pb0cr);
396 mtdcr(ebccfgd, pbcr);
397 SW_CS_PRINTF(" new cs0 cfg: %lx\n",pbcr);
398 mtdcr(ebccfga, pb1cr); /* get cs1 config reg (flash) */
399 pbcr = mfdcr(ebccfgd);
400 SW_CS_PRINTF(" cs1 cfg: %lx\n",pbcr);
401 pbcr&=0x000FFFFF; /*mask base address of the cs1 */
402 pbcr|=(FLASH_BASE0_PRELIM & 0xFFF00000);
403 mtdcr(ebccfga, pb1cr);
404 mtdcr(ebccfgd, pbcr);
405 SW_CS_PRINTF(" new cs1 cfg: %lx Flash is on High Address\n",pbcr);
406 }
407 return 1;
408 }
409 else {
410 SW_CS_PRINTF("Normal boot, no switching necessary\n");
411 return 0;
412 }
413}
wdenk1cb8e982003-03-06 21:55:29 +0000414#elif defined(CONFIG_VCMA9)
415int switch_cs(unsigned char boot)
416{
417 return 0;
418}
419#endif /* CONFIG_VCMA9 */
wdenkc6097192002-11-03 00:24:07 +0000420
421int do_mplcommon(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
422{
423 ulong size,src,ld_addr;
424 int result;
425 backup_t back;
426 char sw;
427 src = MULTI_PURPOSE_SOCKET_ADDR;
428 size = IMAGE_SIZE;
429
430 if (strcmp(argv[1], "flash") == 0)
431 {
432 sw = switch_cs(0); /* Switch flash to normal location */
433#if (CONFIG_COMMANDS & CFG_CMD_FDC)
434 if (strcmp(argv[2], "floppy") == 0) {
435 char *local_args[3];
436 extern int do_fdcboot (cmd_tbl_t *, int, int, char *[]);
437 printf ("\nupdating bootloader image from floppy\n");
438 local_args[0] = argv[0];
439 if(argc==4) {
440 local_args[1] = argv[3];
441 local_args[2] = NULL;
442 ld_addr=simple_strtoul(argv[3], NULL, 16);
443 result=do_fdcboot(cmdtp, 0, 2, local_args);
444 }
445 else {
446 local_args[1] = NULL;
447 ld_addr=CFG_LOAD_ADDR;
448 result=do_fdcboot(cmdtp, 0, 1, local_args);
449 }
450 result=mpl_prg_image(ld_addr);
451 switch_cs(sw); /* Switch flash back */
452 return result;
453 }
454#endif /* (CONFIG_COMMANDS & CFG_CMD_FDC) */
455 if (strcmp(argv[2], "mem") == 0) {
456 if(argc==4) {
457 ld_addr=simple_strtoul(argv[3], NULL, 16);
458 }
459 else {
460 ld_addr=load_addr;
461 }
462 printf ("\nupdating bootloader image from memory at %lX\n",ld_addr);
463 result=mpl_prg_image(ld_addr);
464 switch_cs(sw); /* Switch flash back */
465 return result;
466 }
467 if (strcmp(argv[2], "mps") == 0) {
468 printf ("\nupdating bootloader image from MSP\n");
469 result=mpl_prg(src,size);
470 switch_cs(sw); /* Switch flash back */
471 return result;
472 }
473 switch_cs(sw); /* Switch flash back */
474
475 }
476 if (strcmp(argv[1], "mem") == 0)
477 {
478 result=0;
479 if(argc==3)
480 {
481 result = (int)simple_strtol(argv[2], NULL, 16);
482 }
483 src=(unsigned long)&result;
484 src-=CFG_MEMTEST_START;
485 src-=(100*1024); /* - 100k */
486 src&=0xfff00000;
487 size=0;
488 do {
489 size++;
490 printf("\n\nPass %ld\n",size);
491 mem_test(CFG_MEMTEST_START,src,1);
492 if(ctrlc())
493 break;
494 if(result>0)
495 result--;
496
497 }while(result);
498 return 0;
499 }
500 if (strcmp(argv[1], "clearenvvalues") == 0)
501 {
502 if (strcmp(argv[2], "yes") == 0)
503 {
504 clear_env_values();
505 return 0;
506 }
507 }
508 if (strcmp(argv[1], "getback") == 0) {
509 get_backup_values(&back);
510 back.signature[3]=0;
511 back.serial_name[16]=0;
512 back.eth_addr[20]=0;
513 printf("GetBackUp: signature: %s\n",back.signature);
514 printf(" serial#: %s\n",back.serial_name);
515 printf(" ethaddr: %s\n",back.eth_addr);
516 return 0;
517 }
518 if (strcmp(argv[1], "setback") == 0) {
519 set_backup_values(1);
520 return 0;
521 }
522 printf("Usage:\n%s\n", cmdtp->usage);
523 return 1;
524}
525
526
527#if (CONFIG_COMMANDS & CFG_CMD_DOC)
528extern void doc_probe(ulong physadr);
529void doc_init (void)
530{
531 doc_probe(MULTI_PURPOSE_SOCKET_ADDR);
532}
533#endif
534
535
536#ifdef CONFIG_VIDEO
537/******************************************************
538 * Routines to display the Board information
539 * to the screen (since the VGA will be initialized as last,
540 * we must resend the infos)
541 */
542
543#ifdef CONFIG_CONSOLE_EXTRA_INFO
544extern GraphicDevice ctfb;
545
546void video_get_info_str (int line_number, char *info)
547{
548 /* init video info strings for graphic console */
549 DECLARE_GLOBAL_DATA_PTR;
550 PPC405_SYS_INFO sys_info;
551 char rev;
552 int i;
553 unsigned long pvr;
554 char buf[64];
555 char tmp[16];
556 unsigned char *s, *e, bc, sw;
557 switch (line_number)
558 {
559 case 2:
560 /* CPU and board infos */
561 pvr=get_pvr();
562 get_sys_info (&sys_info);
563 switch (pvr) {
564 case PVR_405GP_RB: rev='B'; break;
565 case PVR_405GP_RC: rev='C'; break;
566 case PVR_405GP_RD: rev='D'; break;
567 case PVR_405GP_RE: rev='E'; break;
568 default: rev='?'; break;
569 }
570 /* Board info */
571 i=0;
572 s=getenv ("serial#");
573#ifdef CONFIG_PIP405
574 if (!s || strncmp (s, "PIP405", 6)) {
575 sprintf(buf,"### No HW ID - assuming PIP405");
576 }
577#endif
578#ifdef CONFIG_MIP405
579 if (!s || strncmp (s, "MIP405", 6)) {
580 sprintf(buf,"### No HW ID - assuming MIP405");
581 }
582#endif
583 else {
584 for (e = s; *e; ++e) {
585 if (*e == ' ')
586 break;
587 }
588 for (; s < e; ++s) {
589 if (*s == '_') {
590 ++s;
591 break;
592 }
593 buf[i++]=*s;
594 }
595 sprintf(&buf[i]," SN ");
596 i+=4;
597 for (; s < e; ++s) {
598 buf[i++]=*s;
599 }
600 buf[i++]=0;
601 }
602 sprintf (info," %s PPC405GP %c %s MHz (%lu/%lu/%lu MHz)",
603 buf,rev,
604 strmhz (tmp, gd->cpu_clk), sys_info.freqPLB / 1000000,
605 sys_info.freqPLB / sys_info.pllOpbDiv / 1000000,
606 sys_info.freqPLB / sys_info.pllExtBusDiv / 1000000);
607 return;
608 case 3:
609 /* Memory Info */
610 sw = switch_cs (0);
611 switch_cs (sw);
612 bc = in8 (CONFIG_PORT_ADDR);
613 sprintf(info, " %luMB RAM, %luMB Flash Cfg 0x%02X %s %s",
614 gd->bd->bi_memsize / 0x100000,
615 gd->bd->bi_flashsize / 0x100000,
616 bc,
617 sw ? "MPS boot" : "Flash boot",
618 ctfb.modeIdent);
619 return;
620 case 1:
621 sprintf (buf, "%s",CONFIG_IDENT_STRING);
622 sprintf (info, " %s", &buf[1]);
623 return;
624 }
625 /* no more info lines */
626 *info = 0;
627 return;
628}
629#endif /* CONFIG_CONSOLE_EXTRA_INFO */
630
631#endif /* CONFIG_VIDEO */