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