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