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