]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - board/mpl/common/common_util.c
* Patches by David Müller, 31 Jan 2003:
[karo-tx-uboot.git] / board / mpl / common / common_util.c
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 <asm/byteorder.h>
31 #include <i2c.h>
32 #include <devices.h>
33 #include <pci.h>
34
35 extern int  gunzip (void *, int, unsigned char *, int *);
36 extern 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
41 extern flash_info_t flash_info[];       /* info for FLASH chips */
42
43 static image_header_t header;
44
45
46
47 int 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];
55
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
62         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 */
71         printf("Erasing at %lx (sector %d) (start %lx)\n",
72                                 start,i,info->start[i]);
73         flash_erase (info, i, info->sector_count-1);
74
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
90         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
101 int 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));
107         if (ntohl(hdr->ih_magic)  != IH_MAGIC) {
108                 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);
122         checksum = ntohl(hdr->ih_hcrc);
123         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);
129         len  = ntohl(hdr->ih_size);
130         printf ("Verifying Checksum ... ");
131         if (crc32 (0, (char *)data, len) != ntohl(hdr->ih_dcrc)) {
132                 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
157 void 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
162 void 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);
175         i = getenv_r("serial#",back.serial_name,16);
176         if(i < 0) {
177                 printf("Not possible to write Backup\n");
178                 return;
179         }
180         back.serial_name[16]=0;
181         i = getenv_r("ethaddr",back.eth_addr,20);
182         if(i < 0) {
183                 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
190 void 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  */
204 int 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
231 static ulong oldsizes[] = {
232         0x200,
233         0x800,
234         0
235 };
236
237 void 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
277 void 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
319 extern device_t *stdio_devices[];
320 extern char *stdio_names[];
321
322 void show_stdio_dev(void)
323 {
324         /* Print information */
325         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
361 #if defined(CONFIG_PIP405) || defined(CONFIG_MIP405)
362 int 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 }
414 #elif defined(CONFIG_VCMA9)
415 int switch_cs(unsigned char boot)
416 {
417     return 0;
418 }
419 #endif /* CONFIG_VCMA9 */
420
421 int 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)
528 extern void doc_probe(ulong physadr);
529 void 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
544 extern GraphicDevice ctfb;
545
546 void 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 */