]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - board/mpl/common/common_util.c
60c49af151032f25f61026098427f48056f7c329
[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 <i2c.h>
31 #include <devices.h>
32 #include <pci.h>
33
34 extern int  gunzip (void *, int, unsigned char *, int *);
35 extern 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
40 extern flash_info_t flash_info[];       /* info for FLASH chips */
41
42 image_header_t header;
43
44
45
46 int 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
81 int 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
137 void 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
142 void 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
170 void 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  */
184 int 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
211 static ulong oldsizes[] = {
212         0x200,
213         0x800,
214         0
215 };
216
217 void 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
257 void 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
299 extern device_t *stdio_devices[];
300 extern char *stdio_names[];
301
302 void 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
342 int 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
396 int 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)
503 extern void doc_probe(ulong physadr);
504 void 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
519 extern GraphicDevice ctfb;
520
521 void 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 */