3 Copyright 2002 Broadcom Corp. All Rights Reserved.
5 This program is free software; you can distribute it and/or modify it
6 under the terms of the GNU General Public License (Version 2) as
7 published by the Free Software Foundation.
9 This program is distributed in the hope it will be useful, but WITHOUT
10 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 You should have received a copy of the GNU General Public License along
15 with this program; if not, write to the Free Software Foundation, Inc.,
16 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
20 ***************************************************************************
21 * File Name : bcm63xx_flash.c
23 * Description: This file contains the flash device driver APIs for bcm63xx board.
25 * Created on : 8/10/2002 seanl: use cfiflash.c, cfliflash.h (AMD specific)
27 ***************************************************************************/
32 #include <linux/capability.h>
33 #include <linux/slab.h>
34 #include <linux/errno.h>
35 #include <linux/module.h>
36 #include <linux/interrupt.h>
37 #include <asm/uaccess.h>
39 #include <bcm_map_part.h>
41 #define BCMTAG_EXE_USE
43 #include "flash_api.h"
44 #include "boardparms.h"
48 extern PFILE_TAG kerSysImageTagGet(void);
50 static FLASH_ADDR_INFO fInfo;
51 static int flashInitialized = 0;
53 /*Michael: for fix crash when push reset button */
54 void *retriedKmallocRESET(size_t size)
59 // try 1000 times before quit
60 /*Michael: for fix crash when push reset button */
61 /* if we kill pppd and do reset button push, it goes fine. This method provided by viclin */
62 // while (((pBuf = kmalloc(size, GFP_KERNEL)) == NULL) && (tryCount++ < 1000)){
63 while (((pBuf = kmalloc(size, GFP_ATOMIC)) == NULL) && (tryCount++ < 1000)){
64 current->state = TASK_INTERRUPTIBLE;
65 schedule_timeout(HZ/10);
70 memset(pBuf, 0, size);
76 void *retriedKmalloc(size_t size)
80 int allocType = GFP_KERNEL;
84 allocType = GFP_ATOMIC;
88 // try 1000 times before quit
89 while (((pBuf = kmalloc(size, allocType)) == NULL) && (++tryCount < 1000))
91 current->state = TASK_INTERRUPTIBLE;
92 schedule_timeout(HZ/10);
97 memset(pBuf, 0, size);
102 void retriedKfree(void *pBuf)
107 /***************************************************************************
108 // Function Name: getCrc32
109 // Description : caculate the CRC 32 of the given data.
110 // Parameters : pdata - array of data.
111 // size - number of input data bytes.
112 // crc - either CRC32_INIT_VALUE or previous return value.
114 ****************************************************************************/
115 UINT32 getCrc32(byte *pdata, UINT32 size, UINT32 crc)
118 crc = (crc >> 8) ^ Crc32_table[(crc ^ *pdata++) & 0xff];
123 // get the nvram start addr
125 unsigned long get_nvram_start_addr(void)
127 return ((unsigned long)
128 (flash_get_memptr(fInfo.flash_nvram_start_blk) + fInfo.flash_nvram_blk_offset));
131 // get the scratch_pad start addr
133 unsigned long get_scratch_pad_start_addr(void)
135 return ((unsigned long)
136 (flash_get_memptr(fInfo.flash_scratch_pad_start_blk) + fInfo.flash_scratch_pad_blk_offset));
140 #if defined(CONFIG_BCM96348)
141 /* *********************************************************************
142 * kerSysImageTagGet()
147 * point to tag -- Found
149 ********************************************************************* */
150 PFILE_TAG kerSysImageTagGet(void)
153 int totalBlks = flash_get_numsectors();
154 int totalSize = flash_get_total_size();
156 unsigned char *sectAddr;
158 unsigned char nbootflag,*bootflag;
160 bootflag=flash_get_memptr((byte) 0);
162 if (totalSize == 0x800000) {nbootflag=*bootflag;}
165 if (nbootflag == 2) nbootflag = 0; /*binfs is valid to boot from bfc00000*/
166 startblock = (nbootflag?1:(totalBlks>>1)+1);
167 #if defined(DEBUG_FLASH)
168 printk("totalblks in tagGet=%d\n", totalBlks);
172 // start blk, assume 1st one is always CFE
173 for (i = startblock; i < startblock + (totalBlks>>1); i++)
175 sectAddr = flash_get_memptr((byte) i);
176 crc = CRC32_INIT_VALUE;
177 crc = getCrc32(sectAddr, (UINT32)TAG_LEN-TOKEN_LEN, crc);
178 pTag = (PFILE_TAG) sectAddr;
180 #if defined(DEBUG_FLASH)
181 printk("Check Tag crc on blk [%d]\n", i);
184 if (crc == (UINT32)(*(UINT32*)(pTag->tagValidationToken)))
188 return (PFILE_TAG) NULL;
191 PFILE_TAG kerSysImageTagGet2(void)
194 int totalBlks = flash_get_numsectors();
195 int totalSize = flash_get_total_size();
197 unsigned char *sectAddr;
199 unsigned char nbootflag,*bootflag;
201 bootflag=flash_get_memptr((byte) 0);
203 if (totalSize == 0x800000) nbootflag=1; /*always get from bf800000 */
204 else return (PFILE_TAG) NULL;
206 startblock = (nbootflag?1:(totalBlks>>1)+1);
207 #if defined(DEBUG_FLASH)
208 printk("totalblks in tagGet=%d\n", totalBlks);
212 // start blk, assume 1st one is always CFE
213 for (i = startblock; i < startblock + (totalBlks>>1); i++)
215 sectAddr = flash_get_memptr((byte) i);
216 crc = CRC32_INIT_VALUE;
217 crc = getCrc32(sectAddr, (UINT32)TAG_LEN-TOKEN_LEN, crc);
218 pTag = (PFILE_TAG) sectAddr;
220 if (*((unsigned char*) pTag->kernelLen) == 0x30 ) {
222 #if defined(DEBUG_FLASH)
223 printk("Check Tag crc on blk [%d]\n", i);
226 if (crc == (UINT32)(*(UINT32*)(pTag->tagValidationToken)))
231 return (PFILE_TAG) NULL;
237 #if defined(CONFIG_BCM96338)
238 PFILE_TAG kerSysImageTagGet(void)
241 int totalBlks = flash_get_numsectors();
242 int totalSize = flash_get_total_size();
244 unsigned char *sectAddr;
246 unsigned char bootf1,bootf2,nbootflag=0;
249 if (totalSize == 0x400000) {
250 bootf1 = *(unsigned char*) (0xbfe00000 -1); /*see design note 4MB flash layout*/
251 bootf2 = *(unsigned char*) (0xbfff0000 -1);
252 if ((bootf1 >> 2) == 0 && bootf1 ) {
253 if ((bootf2 >> 2) == 0 && bootf2 ) { /* both are valid */
254 if ((bootf1+1) == bootf2 || ((bootf1+1) >>2 == bootf2) ) nbootflag=1; /*bank2*/
255 if ((bootf2+1) == bootf1 || ((bootf2+1) >>2 == bootf1) ) nbootflag=0; /*bank1*/
256 } else nbootflag = 0; /* bank2 invalid bank1 valid */
258 else if ((bootf2 >> 2) == 0 && bootf2) nbootflag =1; /*bank 1 invalid,bank 2 valid*/
259 else nbootflag=0; /* bank1 bank2 both invalid */
261 printk("bootf1=%x bootf2=%x\n", bootf1,bootf2);
265 startblock = nbootflag?flash_get_blk(0xbfe00000):1;
266 #if defined(DEBUG_FLASH)
267 printk("totalblks in tagGet=%d\n", totalBlks);
271 // start blk, assume 1st one is always CFE
272 for (i = startblock; i < startblock + (totalBlks>>1); i++)
274 sectAddr = flash_get_memptr((byte) i);
275 crc = CRC32_INIT_VALUE;
276 crc = getCrc32(sectAddr, (UINT32)TAG_LEN-TOKEN_LEN, crc);
277 pTag = (PFILE_TAG) sectAddr;
279 #if defined(DEBUG_FLASH)
280 printk("Check Tag crc on blk [%d]\n", i);
283 if (crc == (UINT32)(*(UINT32*)(pTag->tagValidationToken)))
287 return (PFILE_TAG) NULL;
290 // Initialize the flash and fill out the fInfo structure
291 void kerSysFlashInit( void )
298 NVRAM_DATA nvramData;
299 UINT32 crc = CRC32_INIT_VALUE, savedCrc;
300 PFILE_TAG pTag = NULL;
301 unsigned long kernelEndAddr = 0;
302 unsigned long spAddr = 0;
304 if (flashInitialized)
307 flashInitialized = 1;
310 totalBlks = flash_get_numsectors();
311 totalSize = flash_get_total_size();
313 printk("Total Flash size: %dK with %d sectors\n", totalSize/1024, totalBlks);
315 /* nvram is always at the end of flash */
316 fInfo.flash_nvram_length = NVRAM_LENGTH;
317 printk("FLASH_BASE %x,blk %d\n",FLASH_BASE,flash_get_blk(FLASH_BASE));
318 fInfo.flash_nvram_start_blk = flash_get_blk(FLASH_BASE); /* denny 09/13/04' modified, set the nvram locate at boot loader sector */
319 fInfo.flash_nvram_number_blk = 1; /*always fits in the first block */
320 fInfo.flash_nvram_blk_offset = NVRAM_DATA_OFFSET;
323 memcpy((char *)&nvramData, (char *)get_nvram_start_addr(), sizeof(NVRAM_DATA));
324 savedCrc = nvramData.ulCheckSum;
325 nvramData.ulCheckSum = 0;
326 crc = getCrc32((char *)&nvramData, (UINT32) sizeof(NVRAM_DATA), crc);
328 BpSetBoardId( nvramData.szBoardId );
330 fInfo.flash_persistent_length = NVRAM_PSI_DEFAULT;
333 printk("***Board is not initialized****: Using the default PSI size: %d\n",
334 fInfo.flash_persistent_length);
338 unsigned long ulPsiSize;
339 if( BpGetPsiSize( &ulPsiSize ) == BP_SUCCESS )
340 fInfo.flash_persistent_length = ulPsiSize;
343 printk("***Board id is not set****: Using the default PSI size: %d\n",
344 fInfo.flash_persistent_length);
348 fInfo.flash_persistent_length *= ONEK;
349 startAddr = totalSize - fInfo.flash_persistent_length;
350 #if defined (CONFIG_BCM96348) || defined(CONFIG_BCM96338)
351 fInfo.flash_persistent_start_blk = flash_get_blk(startAddr+get_flash_base(0));
353 #if defined (CONFIG_BCM96358)
354 fInfo.flash_persistent_start_blk = flash_get_blk(startAddr+FLASH_BASE);
356 fInfo.flash_persistent_number_blk = totalBlks - fInfo.flash_persistent_start_blk;
357 // save abs SP address (Scratch Pad). it is before PSI
358 spAddr = startAddr - SP_MAX_LEN ;
359 // find out the offset in the start_blk
361 for (i = fInfo.flash_persistent_start_blk;
362 i < (fInfo.flash_persistent_start_blk + fInfo.flash_persistent_number_blk); i++)
364 usedBlkSize += flash_get_sector_size( i);
366 fInfo.flash_persistent_blk_offset = usedBlkSize - fInfo.flash_persistent_length;
368 // get the info for sp
369 if (!(pTag = kerSysImageTagGet()))
371 printk("Failed to read image tag from flash\n");
374 kernelEndAddr = (unsigned long)simple_strtoul(pTag->kernelAddress,NULL,10)+ \
375 (unsigned long) simple_strtoul(pTag->kernelLen, NULL, 10) + BOOT_OFFSET;
378 #if defined (CONFIG_BCM96348) || defined(CONFIG_BCM96338)
379 fInfo.flash_scratch_pad_start_blk = flash_get_blk(spAddr+get_flash_base(0));
382 #if defined (CONFIG_BCM96358)
383 // make suer sp does not share kernel block
384 fInfo.flash_scratch_pad_start_blk = flash_get_blk(spAddr+FLASH_BASE);
386 if (fInfo.flash_scratch_pad_start_blk != flash_get_blk(kernelEndAddr))
388 fInfo.flash_scratch_pad_length = SP_MAX_LEN;
389 if (fInfo.flash_persistent_start_blk == fInfo.flash_scratch_pad_start_blk) // share blk
391 #if 0 /* do not used scratch pad unless it's in its own sector */
392 printk("Scratch pad is not used for this flash part.\n");
393 fInfo.flash_scratch_pad_length = 0; // no sp
394 #else /* allow scratch pad to share a sector with another section such as PSI */
395 fInfo.flash_scratch_pad_number_blk = 1;
396 fInfo.flash_scratch_pad_blk_offset = fInfo.flash_persistent_blk_offset - fInfo.flash_scratch_pad_length;
399 else // on different blk
401 fInfo.flash_scratch_pad_number_blk = fInfo.flash_persistent_start_blk\
402 - fInfo.flash_scratch_pad_start_blk;
403 // find out the offset in the start_blk
405 for (i = fInfo.flash_scratch_pad_start_blk;
406 i < (fInfo.flash_scratch_pad_start_blk + fInfo.flash_scratch_pad_number_blk); i++)
407 usedBlkSize += flash_get_sector_size(i);
408 fInfo.flash_scratch_pad_blk_offset = usedBlkSize - fInfo.flash_scratch_pad_length;
413 printk("No flash for scratch pad!\n");
414 fInfo.flash_scratch_pad_length = 0; // no sp
417 /*==== add by Andrew (2004/09/14) ====*/
418 #if defined(CFG_XFER_TO_FACDEFLT)
419 // save abs factdeflt address (Factory Default). it is before SP
420 unsigned long dfAddr;
422 if(fInfo.flash_scratch_pad_length>0) {
423 dfAddr = spAddr - NVRAM_PSI_DEFAULT*ONEK;
424 // make sure factdeflt does not share kernel block
425 #if defined (CONFIG_BCM96348) || defined(CONFIG_BCM96338)
426 fInfo.flash_factdeflt_start_blk = flash_get_blk(dfAddr+get_flash_base(0));
428 #if defined (CONFIG_BCM96358)
429 fInfo.flash_factdeflt_start_blk = flash_get_blk(dfAddr+FLASH_BASE);
431 if (fInfo.flash_factdeflt_start_blk != flash_get_blk(kernelEndAddr)) {
432 fInfo.flash_factdeflt_length = NVRAM_PSI_DEFAULT*ONEK;
433 if (fInfo.flash_factdeflt_start_blk == fInfo.flash_scratch_pad_start_blk) // share blk
435 fInfo.flash_factdeflt_number_blk = 1;
436 fInfo.flash_factdeflt_blk_offset = fInfo.flash_scratch_pad_blk_offset - fInfo.flash_factdeflt_length;
437 } else { // on different blk
438 fInfo.flash_factdeflt_number_blk = fInfo.flash_scratch_pad_start_blk - fInfo.flash_factdeflt_start_blk;
439 // find out the offset in the start_blk
441 for (i = fInfo.flash_factdeflt_start_blk;
442 i < (fInfo.flash_factdeflt_start_blk + fInfo.flash_factdeflt_number_blk); i++)
443 usedBlkSize += flash_get_sector_size( i);
444 fInfo.flash_factdeflt_blk_offset = usedBlkSize - fInfo.flash_factdeflt_length;
447 printk("Not enough flash space to store factory default setting!\n");
448 fInfo.flash_factdeflt_length = 0; // no df
451 dfAddr = startAddr - NVRAM_PSI_DEFAULT*ONEK;
452 // make sure factdeflt does not share kernel block
453 #if defined (CONFIG_BCM96348) || defined(CONFIG_BCM96338)
454 fInfo.flash_factdeflt_start_blk = flash_get_blk(dfAddr+get_flash_base(0));
456 #if defined (CONFIG_BCM96358)
457 fInfo.flash_factdeflt_start_blk = flash_get_blk(dfAddr+FLASH_BASE);
459 if (fInfo.flash_factdeflt_start_blk != flash_get_blk(kernelEndAddr)) {
460 fInfo.flash_factdeflt_length = NVRAM_PSI_DEFAULT*ONEK;
461 if (fInfo.flash_factdeflt_start_blk == fInfo.flash_persistent_start_blk) // share blk
463 fInfo.flash_factdeflt_number_blk = 1;
464 fInfo.flash_factdeflt_blk_offset = fInfo.flash_persistent_blk_offset - fInfo.flash_factdeflt_length;
465 } else { // on different blk
466 fInfo.flash_factdeflt_number_blk = fInfo.flash_persistent_start_blk - fInfo.flash_factdeflt_start_blk;
467 // find out the offset in the start_blk
469 for (i = fInfo.flash_factdeflt_start_blk;
470 i < (fInfo.flash_factdeflt_start_blk + fInfo.flash_factdeflt_number_blk); i++)
471 usedBlkSize += flash_get_sector_size( i);
472 fInfo.flash_factdeflt_blk_offset = usedBlkSize - fInfo.flash_factdeflt_length;
475 printk("Not enough flash space to store factory default setting!\n");
476 fInfo.flash_factdeflt_length = 0; // no df
481 #if defined(DEBUG_FLASH)
482 #if defined(CFG_XFER_TO_FACDEFLT)
483 #if defined (CONFIG_BCM96348) || defined(CONFIG_BCM96338)
484 printk("dfAddr = %x\n", dfAddr+get_flash_base(0));
486 #if defined (CONFIG_BCM96358)
487 printk("dfAddr = %x\n", dfAddr+FLASH_BASE);
489 printk("fInfo.flash_factdeflt_start_blk = %d\n", fInfo.flash_factdeflt_start_blk);
490 printk("fInfo.flash_factdeflt_number_blk = %d\n", fInfo.flash_factdeflt_number_blk);
491 printk("fInfo.flash_factdeflt_length = 0x%x\n", fInfo.flash_factdeflt_length);
492 printk("fInfo.flash_factdeflt_blk_offset = 0x%x\n", (unsigned int)fInfo.flash_factdeflt_blk_offset);
494 printk("fInfo.flash_scratch_pad_start_blk = %d\n", fInfo.flash_scratch_pad_start_blk);
495 printk("fInfo.flash_scratch_pad_number_blk = %d\n", fInfo.flash_scratch_pad_number_blk);
496 printk("fInfo.flash_scratch_pad_length = 0x%x\n", fInfo.flash_scratch_pad_length);
497 printk("fInfo.flash_scratch_pad_blk_offset = 0x%x\n", (unsigned int)fInfo.flash_scratch_pad_blk_offset);
499 printk("fInfo.flash_nvram_start_blk = %d\n", fInfo.flash_nvram_start_blk);
500 printk("fInfo.flash_nvram_blk_offset = 0x%x\n", (unsigned int)fInfo.flash_nvram_blk_offset);
501 printk("fInfo.flash_nvram_number_blk = %d\n", fInfo.flash_nvram_number_blk);
502 #if defined (CONFIG_BCM96348) || defined(CONFIG_BCM96338)
503 printk("psi startAddr = %x\n", startAddr+get_flash_base(0));
505 #if defined (CONFIG_BCM96358)
506 printk("psi startAddr = %x\n", startAddr+FLASH_BASE);
508 printk("fInfo.flash_persistent_start_blk = %d\n", fInfo.flash_persistent_start_blk);
509 printk("fInfo.flash_persistent_blk_offset = 0x%x\n", (unsigned int)fInfo.flash_persistent_blk_offset);
510 printk("fInfo.flash_persistent_number_blk = %d\n", fInfo.flash_persistent_number_blk);
517 /***********************************************************************
518 * Function Name: kerSysFlashAddrInfoGet
519 * Description : Fills in a structure with information about the NVRAM
520 * and persistent storage sections of flash memory.
521 * Fro physmap.c to mount the fs vol.
523 ***********************************************************************/
524 void kerSysFlashAddrInfoGet(PFLASH_ADDR_INFO pflash_addr_info)
526 pflash_addr_info->flash_nvram_blk_offset = fInfo.flash_nvram_blk_offset;
527 pflash_addr_info->flash_nvram_length = fInfo.flash_nvram_length;
528 pflash_addr_info->flash_nvram_number_blk = fInfo.flash_nvram_number_blk;
529 pflash_addr_info->flash_nvram_start_blk = fInfo.flash_nvram_start_blk;
530 pflash_addr_info->flash_persistent_blk_offset = fInfo.flash_persistent_blk_offset;
531 pflash_addr_info->flash_persistent_length = fInfo.flash_persistent_length;
532 pflash_addr_info->flash_persistent_number_blk = fInfo.flash_persistent_number_blk;
533 pflash_addr_info->flash_persistent_start_blk = fInfo.flash_persistent_start_blk;
537 // get shared blks into *** pTempBuf *** which has to be released bye the caller!
538 // return: if pTempBuf != NULL, poits to the data with the dataSize of the buffer
541 static char *getSharedBlks(int start_blk, int end_blk)
546 char *pTempBuf = NULL;
549 for (i = start_blk; i < end_blk; i++)
550 usedBlkSize += flash_get_sector_size( i);
552 #if defined(DEBUG_FLASH)
553 printk("usedBlkSize = %d\n", usedBlkSize);
556 if ((pTempBuf = (char *) retriedKmalloc(usedBlkSize)) == NULL)
558 printk("failed to allocate memory with size: %d\n", usedBlkSize);
563 for (i = start_blk; i < end_blk; i++)
565 sect_size = flash_get_sector_size( i);
567 #if defined(DEBUG_FLASH)
568 printk("i = %d, sect_size = %d, end_blk = %d\n", i, sect_size, end_blk);
570 flash_read_buf(i, 0, pBuf, sect_size);
577 /*Michael: for fix crash when push reset button */
578 /* We add this because it happen only at 2Mflash 8M SDRAM. */
579 static char *getSharedBlksRESET(int start_blk, int end_blk)
584 char *pTempBuf = NULL;
587 for (i = start_blk; i < end_blk; i++)
588 usedBlkSize += flash_get_sector_size( i);
590 #if defined(DEBUG_FLASH)
591 printk("usedBlkSize = %d\n", usedBlkSize);
594 if ((pTempBuf = (char *) retriedKmallocRESET(usedBlkSize)) == NULL)
596 printk("failed to allocate memory with size: %d\n", usedBlkSize);
601 for (i = start_blk; i < end_blk; i++)
603 sect_size = flash_get_sector_size( i);
604 #if defined(DEBUG_FLASH)
605 printk("i = %d, sect_size = %d, end_blk = %d\n", i, sect_size, end_blk);
607 flash_read_buf(i, 0, pBuf, sect_size);
614 // Set the pTempBuf to flash from start_blk to end_blk
618 static int setSharedBlks(int start_blk, int end_blk, char *pTempBuf)
623 char *pBuf = pTempBuf;
625 for (i = start_blk; i < end_blk; i++)
627 sect_size = flash_get_sector_size( i);
628 flash_sector_erase_int(i);
629 if (flash_write_buf(i, 0, pBuf, sect_size) != sect_size)
631 printk("Error writing flash sector %d.", i);
643 /*******************************************************************************
645 *******************************************************************************/
651 int kerSysNvRamGet(char *string, int strLen, int offset)
655 if (!flashInitialized)
658 if (strLen > NVRAM_LENGTH)
661 if ((pBuf = getSharedBlks(fInfo.flash_nvram_start_blk,
662 (fInfo.flash_nvram_start_blk + fInfo.flash_nvram_number_blk))) == NULL)
665 // get string off the memory buffer
666 memcpy(string, (pBuf + fInfo.flash_nvram_blk_offset + offset), strLen);
673 #if defined(CONFIG_BCM96348)
680 i+=flash_get_sector_size(j);
684 flash_sector_erase_int(j);
688 int kerSysBootFlagSet(char bootflag)
693 char *pTempBuf = NULL;
695 printk("set bootflag %d\n",bootflag);
696 sect_size = flash_get_sector_size(0); /* denny 09/13/04' modified */
697 if ((pTempBuf = (char *) retriedKmalloc(sect_size)) == NULL) {
698 printk("failed to allocate memory with size: %d\n", sect_size);
702 flash_read_buf(0, 0, pTempBuf, sect_size);
703 flash_sector_erase_int(0);
704 *((char *) pTempBuf) = bootflag;
705 if (flash_write_buf(0, 0, pTempBuf, sect_size) != sect_size)
707 printk("Error writing flash sector %d.\n", i);
710 retriedKfree(pTempBuf);
715 #if defined(CONFIG_BCM96338) || defined(CONFIG_BCM96358)
719 #if defined(CONFIG_BCM96338)
720 if (flash_get_total_size() == 0x400000) {
721 j=flash_get_blk(0xbfe00000);
722 flash_sector_erase_int(j); /*erase the first block of bank 2*/
723 j=flash_get_blk(0xbffe0000);
724 flash_sector_erase_int(j); /*erase the bootflag of bank 2*/
727 #if defined(CONFIG_BCM96358)
728 if (flash_get_total_size() == 0x800000) {
729 j=flash_get_blk(0xbe400000);
730 flash_sector_erase_int(j); /*erase the first block of bank 2*/
731 j=flash_get_blk(0xbe7e0000);
732 flash_sector_erase_int(j); /*erase the bootflag of bank 2*/
737 /* bootflag will indicate which bank will be set */
738 int kerSysBootFlagSet(char bootflag)
743 char *pTempBuf = NULL;
744 unsigned char bootnum;
747 unsigned int totalSize = (unsigned int) flash_get_total_size();
750 sector =bootflag?flash_get_blk(FLASH_BASE+totalSize-FLASH_RESERVED_AT_END-1):flash_get_blk(FLASH_BASE+(totalSize/2)-1);
751 bootnum=bootflag?*(unsigned char*) (FLASH_BASE+(totalSize/2)-1):*(unsigned char*) (FLASH_BASE+totalSize-FLASH_RESERVED_AT_END-1); /*flash bank1 get bootnum from bank2*/
753 sector =bootflag?flash_get_blk(0xbffe0000):flash_get_blk(0xbfdf0000);
754 bootnum=bootflag?*(unsigned char*) (0xbfe00000-1):*(unsigned char*) (0xbfff0000-1); /*flash bank1 get bootnum from bank2*/
757 if ((bootnum >> 2)==0 && bootnum) {
759 if (bootnum>>2) bootnum>>=2;
763 sect_size = flash_get_sector_size(sector); /* denny 09/13/04' modified */
764 if ((pTempBuf = (char *) retriedKmalloc(sect_size)) == NULL) {
765 printk("failed to allocate memory with size: %d\n", sect_size);
769 flash_read_buf(sector, 0, pTempBuf, sect_size);
770 flash_sector_erase_int(sector);
771 *((char *) (pTempBuf+sect_size-1)) = bootnum;
772 if (flash_write_buf(sector, 0, pTempBuf, sect_size) != sect_size)
774 printk("Error writing flash sector %d.\n", i);
777 retriedKfree(pTempBuf);
778 printk("Next bbank %d/flag %d\n",bootflag,bootnum);
786 int kerSysNvRamSet(char *string, int strLen, int offset)
791 if (strLen > NVRAM_LENGTH)
794 if ((pBuf = getSharedBlks(fInfo.flash_nvram_start_blk,
795 (fInfo.flash_nvram_start_blk + fInfo.flash_nvram_number_blk))) == NULL)
798 // set string to the memory buffer
799 memcpy((pBuf + fInfo.flash_nvram_blk_offset + offset), string, strLen);
801 if (setSharedBlks(fInfo.flash_nvram_start_blk,
802 (fInfo.flash_nvram_number_blk + fInfo.flash_nvram_start_blk), pBuf) != 0)
811 /***********************************************************************
812 * Function Name: kerSysEraseNvRam
813 * Description : Erase the NVRAM storage section of flash memory.
814 * Returns : 1 -- ok, 0 -- fail
815 ***********************************************************************/
816 int kerSysEraseNvRam(void)
819 char *tempStorage = retriedKmalloc(NVRAM_LENGTH);
821 // just write the whole buf with '0xff' to the flash
826 memset(tempStorage, 0xff, NVRAM_LENGTH);
827 if (kerSysNvRamSet(tempStorage, NVRAM_LENGTH, 0) != 0)
829 retriedKfree(tempStorage);
835 /*==== add by Andrew (2004/09/14) ====*/
836 #if defined(CFG_XFER_TO_FACDEFLT)
837 int kerSysFactDefltGet(char *string, int strLen, int offset)
841 if (strLen > fInfo.flash_factdeflt_length)
844 if ((pBuf = getSharedBlks(fInfo.flash_factdeflt_start_blk,
845 (fInfo.flash_factdeflt_start_blk + fInfo.flash_factdeflt_number_blk))) == NULL)
848 // get string off the memory buffer
849 memcpy(string, (pBuf + fInfo.flash_factdeflt_blk_offset + offset), strLen);
861 int kerSysFactDefltSet(char *string, int strLen, int offset)
866 if (strLen > fInfo.flash_factdeflt_length)
869 if ((pBuf = getSharedBlks(fInfo.flash_factdeflt_start_blk,
870 (fInfo.flash_factdeflt_start_blk + fInfo.flash_factdeflt_number_blk))) == NULL)
873 // set string to the memory buffer
874 memcpy((pBuf + fInfo.flash_factdeflt_blk_offset + offset), string, strLen);
875 if (setSharedBlks(fInfo.flash_factdeflt_start_blk,
876 (fInfo.flash_factdeflt_number_blk + fInfo.flash_factdeflt_start_blk), pBuf) != 0)
884 /*******************************************************************************
886 *******************************************************************************/
891 int kerSysPersistentGet(char *string, int strLen, int offset)
895 if (strLen > fInfo.flash_persistent_length)
898 if ((pBuf = getSharedBlks(fInfo.flash_persistent_start_blk,
899 (fInfo.flash_persistent_start_blk + fInfo.flash_persistent_number_blk))) == NULL)
902 // get string off the memory buffer
903 memcpy(string, (pBuf + fInfo.flash_persistent_blk_offset + offset), strLen);
915 int kerSysPersistentSet(char *string, int strLen, int offset)
920 if (strLen > fInfo.flash_persistent_length)
923 if ((pBuf = getSharedBlks(fInfo.flash_persistent_start_blk,
924 (fInfo.flash_persistent_start_blk + fInfo.flash_persistent_number_blk))) == NULL)
927 // set string to the memory buffer
928 memcpy((pBuf + fInfo.flash_persistent_blk_offset + offset), string, strLen);
930 if (setSharedBlks(fInfo.flash_persistent_start_blk,
931 (fInfo.flash_persistent_number_blk + fInfo.flash_persistent_start_blk), pBuf) != 0)
939 /*Michael: for fix crash when push reset button */
940 /* We add this because it happen only at 2Mflash 8M SDRAM. */
941 int kerSysPersistentSetRESET()
946 // if (strLen > fInfo.flash_persistent_length)
948 if ((pBuf = getSharedBlksRESET(fInfo.flash_persistent_start_blk,
949 (fInfo.flash_persistent_start_blk + fInfo.flash_persistent_number_blk))) == NULL)
951 // set string to the memory buffer
952 memset((pBuf + fInfo.flash_persistent_blk_offset), 0xff, fInfo.flash_persistent_length);
953 // memcpy((pBuf + fInfo.flash_persistent_blk_offset + offset), string, strLen);
954 if (setSharedBlks(fInfo.flash_persistent_start_blk,
955 (fInfo.flash_persistent_number_blk + fInfo.flash_persistent_start_blk), pBuf) != 0)
964 // !0 - the sector number fail to be flashed (should not be 0)
965 int kerSysBcmImageSet( int flash_start_addr, char *string, int size)
971 char *pTempBuf = NULL;
974 blk_start = flash_get_blk(flash_start_addr);
978 if (flash_start_addr == FLASH_BASE && size > FLASH_LENGTH_BOOT_ROM)
981 /* write image to flash memory */
984 sect_size = flash_get_sector_size(blk_start);
985 // NOTE: for memory problem in multiple PVC configuration, temporary get rid of kmalloc this 64K for now.
986 // if ((pTempBuf = (char *)retriedKmalloc(sect_size)) == NULL)
988 // printk("Failed to allocate memory with size: %d. Reset the router...\n", sect_size);
989 // kerSysMipsSoftReset(); // reset the board right away.
991 // for whole image, no check on psi
992 if (!whole_image && blk_start == fInfo.flash_persistent_start_blk) // share the blk with psi
994 if (size > (sect_size - fInfo.flash_persistent_length))
996 printk("Image is too big\n");
997 break; // image is too big. Can not overwrite to nvram
999 if ((pTempBuf = (char *)retriedKmalloc(sect_size)) == NULL)
1001 printk("Failed to allocate memory with size: %d. Reset the router...\n", sect_size);
1002 kerSysMipsSoftReset(); // reset the board right away.
1004 flash_read_buf(blk_start, 0, pTempBuf, sect_size);
1005 if (copy_from_user((void *)pTempBuf,(void *)string, size) != 0)
1007 flash_sector_erase_int(blk_start); // erase blk before flash
1008 if (flash_write_buf(blk_start, 0, pTempBuf, sect_size) == sect_size)
1009 size = 0; // break out and say all is ok
1010 retriedKfree(pTempBuf);
1014 flash_sector_erase_int(blk_start); // erase blk before flash
1016 if (sect_size > size)
1023 if ((i = flash_write_buf(blk_start, 0, string, sect_size)) != sect_size) {
1027 string += sect_size;
1033 // If flashing a whole image, erase to end of flash.
1034 int total_blks = flash_get_numsectors();
1035 while( blk_start < total_blks )
1037 flash_sector_erase_int(blk_start);
1042 retriedKfree(pTempBuf);
1047 sts = blk_start; // failed to flash this sector
1052 /***********************************************************************
1053 * Function Name: kerSysErasePersistent
1054 * Description : Erase the Psi storage section of flash memory.
1055 * Returns : 1 -- ok, 0 -- fail
1056 ***********************************************************************/
1058 /* This funtion ONLY called by user when reset to default button is pressed */
1061 int kerSysErasePersistent(void)
1064 char *tempStorage = NULL;
1065 int i, size=0, unit = fInfo.flash_persistent_length/8;
1069 printk("psi 0x%08x #blks 0x%08x len 0x%08x offset 0x%08x \n",fInfo.flash_persistent_start_blk,fInfo.flash_persistent_number_blk,fInfo.flash_persistent_length,fInfo.flash_persistent_blk_offset);
1070 printk("pad 0x%08x #blks 0x%08x len 0x%08x offset 0x%08x \n",fInfo.flash_scratch_pad_start_blk,fInfo.flash_scratch_pad_number_blk,fInfo.flash_scratch_pad_length,fInfo.flash_scratch_pad_blk_offset);
1071 printk("nvram 0x%08x #blks 0x%08x len 0x%08x offset 0x%08x \n",fInfo.flash_nvram_start_blk,fInfo.flash_nvram_number_blk,fInfo.flash_nvram_length,fInfo.flash_nvram_blk_offset);
1073 printk("\nErasing PSI storage section of flash memory....\n");
1075 tempStorage = retriedKmallocRESET(unit);
1076 // just write the whole buf with '0xff' to the flash
1080 memset(tempStorage, 0xff, unit);
1081 if(kerSysPersistentSetRESET(tempStorage, unit, size) != 0)
1083 retriedKfree(tempStorage);
1086 if(!sts) {printk("Cannot alloc %d\n",i); return sts;}
1087 else printk("success in %d\n",i);
1090 unit = fInfo.flash_persistent_length - size;
1091 printk("try to alloc %d\n",unit);
1092 tempStorage = retriedKmalloc(unit);
1096 printk("success in last\n");
1097 memset(tempStorage, 0xff, unit);
1098 if(kerSysPersistentSet(tempStorage, unit, size) != 0)
1100 retriedKfree(tempStorage);
1103 printk("\nErasing PSI....\n");
1104 if (kerSysPersistentSetRESET() != 0)
1107 printk("\nRebooting ADSL router.........");
1113 /*******************************************************************************
1115 *******************************************************************************/
1116 // get sp data. NOTE: memcpy work here -- not using copy_from/to_user
1118 // >0 - number of bytes copied to tokBuf
1120 int kerSysScratchPadGet(char *tokenId, char *tokBuf, int bufLen)
1122 PSP_TOKEN pToken = NULL;
1124 char *pShareBuf = NULL;
1125 char *startPtr = NULL;
1129 if (fInfo.flash_scratch_pad_length == 0)
1132 if( bufLen >= (fInfo.flash_scratch_pad_length - sizeof(SP_HEADER) -
1135 printk("Exceed scratch pad space by %d\n", bufLen -
1136 fInfo.flash_scratch_pad_length - sizeof(SP_HEADER) -
1141 if( (pShareBuf = getSharedBlks(fInfo.flash_scratch_pad_start_blk,
1142 (fInfo.flash_scratch_pad_start_blk +
1143 fInfo.flash_scratch_pad_number_blk))) == NULL )
1148 // pBuf points to SP buf
1149 pBuf = pShareBuf + fInfo.flash_scratch_pad_blk_offset;
1151 if(memcmp(((PSP_HEADER)pBuf)->SPMagicNum, MAGIC_NUMBER, MAGIC_NUM_LEN) != 0)
1153 printk("Scratch pad is not initialized.\n");
1154 retriedKfree(pShareBuf);
1158 // search for the token
1159 usedLen = sizeof(SP_HEADER);
1160 startPtr = pBuf + sizeof(SP_HEADER);
1161 pToken = (PSP_TOKEN) startPtr;
1162 while( pToken->tokenName[0] != '\0' && pToken->tokenLen > 0 &&
1163 pToken->tokenLen < fInfo.flash_scratch_pad_length &&
1164 usedLen < fInfo.flash_scratch_pad_length )
1167 if (strncmp(pToken->tokenName, tokenId, TOKEN_NAME_LEN) == 0)
1169 if ( pToken->tokenLen > bufLen )
1171 printk("The length %d of token %s is greater than buffer len %d.\n", pToken->tokenLen, pToken->tokenName, bufLen);
1174 sts = pToken->tokenLen;
1175 memcpy(tokBuf, startPtr + sizeof(SP_TOKEN), sts);
1179 usedLen += ((pToken->tokenLen + 0x03) & ~0x03);
1180 startPtr += sizeof(SP_TOKEN) + ((pToken->tokenLen + 0x03) & ~0x03);
1181 pToken = (PSP_TOKEN) startPtr;
1184 retriedKfree(pShareBuf);
1190 // set sp. NOTE: memcpy work here -- not using copy_from/to_user
1194 int kerSysScratchPadSet(char *tokenId, char *tokBuf, int bufLen)
1196 PSP_TOKEN pToken = NULL;
1197 char *pShareBuf = NULL;
1204 if (fInfo.flash_scratch_pad_length == 0)
1207 if( bufLen >= fInfo.flash_scratch_pad_length - sizeof(SP_HEADER) -
1210 printk("Scratch pad overflow by %d bytes. Information not saved.\n",
1211 bufLen - fInfo.flash_scratch_pad_length - sizeof(SP_HEADER) -
1216 if( (pShareBuf = getSharedBlks( fInfo.flash_scratch_pad_start_blk,
1217 (fInfo.flash_scratch_pad_start_blk +
1218 fInfo.flash_scratch_pad_number_blk) )) == NULL )
1223 // pBuf points to SP buf
1224 pBuf = pShareBuf + fInfo.flash_scratch_pad_blk_offset;
1226 // form header info.
1227 memset((char *)&SPHead, 0, sizeof(SP_HEADER));
1228 memcpy(SPHead.SPMagicNum, MAGIC_NUMBER, MAGIC_NUM_LEN);
1229 SPHead.SPVersion = SP_VERSION;
1232 memset((char*)&SPToken, 0, sizeof(SP_TOKEN));
1233 strncpy(SPToken.tokenName, tokenId, TOKEN_NAME_LEN - 1);
1234 SPToken.tokenLen = bufLen;
1236 if(memcmp(((PSP_HEADER)pBuf)->SPMagicNum, MAGIC_NUMBER, MAGIC_NUM_LEN) != 0)
1238 // new sp, so just flash the token
1239 printk("No scratch pad found. Initialize scratch pad...\n");
1240 memcpy(pBuf, (char *)&SPHead, sizeof(SP_HEADER));
1241 curPtr = pBuf + sizeof(SP_HEADER);
1242 memcpy(curPtr, (char *)&SPToken, sizeof(SP_TOKEN));
1243 curPtr += sizeof(SP_TOKEN);
1245 memcpy(curPtr, tokBuf, bufLen);
1254 /* Calculate the used length. */
1255 usedLen = sizeof(SP_HEADER);
1256 curPtr = pBuf + sizeof(SP_HEADER);
1257 pToken = (PSP_TOKEN) curPtr;
1258 skipLen = (pToken->tokenLen + 0x03) & ~0x03;
1259 while( pToken->tokenName[0] >= 'A' && pToken->tokenName[0] <= 'z' &&
1260 strlen(pToken->tokenName) < TOKEN_NAME_LEN &&
1261 pToken->tokenLen > 0 &&
1262 pToken->tokenLen < fInfo.flash_scratch_pad_length &&
1263 usedLen < fInfo.flash_scratch_pad_length )
1265 usedLen += sizeof(SP_TOKEN) + skipLen;
1266 curPtr += sizeof(SP_TOKEN) + skipLen;
1267 pToken = (PSP_TOKEN) curPtr;
1268 skipLen = (pToken->tokenLen + 0x03) & ~0x03;
1271 if( usedLen + SPToken.tokenLen + sizeof(SP_TOKEN) >
1272 fInfo.flash_scratch_pad_length )
1274 printk("Scratch pad overflow by %d bytes. Information not saved.\n",
1275 (usedLen + SPToken.tokenLen + sizeof(SP_TOKEN)) -
1276 fInfo.flash_scratch_pad_length);
1280 curPtr = pBuf + sizeof(SP_HEADER);
1281 curLen = sizeof(SP_HEADER);
1282 while( curLen < usedLen )
1284 pToken = (PSP_TOKEN) curPtr;
1285 skipLen = (pToken->tokenLen + 0x03) & ~0x03;
1286 if (strncmp(pToken->tokenName, tokenId, TOKEN_NAME_LEN) == 0)
1288 // The token id already exists.
1289 if( tokBuf && pToken->tokenLen == bufLen )
1291 // The length of the new data and the existing data is the
1292 // same. Overwrite the existing data.
1293 memcpy((curPtr+sizeof(SP_TOKEN)), tokBuf, bufLen);
1298 // The length of the new data and the existing data is
1299 // different. Shift the rest of the scratch pad to this
1300 // token's location and put this token's data at the end.
1301 char *nextPtr = curPtr + sizeof(SP_TOKEN) + skipLen;
1302 int copyLen = usedLen - (curLen+sizeof(SP_TOKEN) + skipLen);
1303 memcpy( curPtr, nextPtr, copyLen );
1304 memset( curPtr + copyLen, 0x00,
1305 fInfo.flash_scratch_pad_length - (curLen + copyLen) );
1306 usedLen -= sizeof(SP_TOKEN) + skipLen;
1312 curPtr += sizeof(SP_TOKEN) + skipLen;
1313 curLen += sizeof(SP_TOKEN) + skipLen;
1320 memcpy( pBuf + usedLen, &SPToken, sizeof(SP_TOKEN) );
1321 memcpy( pBuf + usedLen + sizeof(SP_TOKEN), tokBuf, bufLen );
1323 memcpy( pBuf, &SPHead, sizeof(SP_HEADER) );
1326 } // else if not new sp
1328 sts = setSharedBlks(fInfo.flash_scratch_pad_start_blk,
1329 (fInfo.flash_scratch_pad_number_blk + fInfo.flash_scratch_pad_start_blk),
1332 retriedKfree(pShareBuf);
1339 // wipe out the scratchPad
1343 int kerSysScratchPadClearAll(void)
1346 char *pShareBuf = NULL;
1350 if (fInfo.flash_scratch_pad_length == 0)
1352 if( (pShareBuf = getSharedBlks( fInfo.flash_scratch_pad_start_blk,
1353 (fInfo.flash_scratch_pad_start_blk + fInfo.flash_scratch_pad_number_blk) )) == NULL )
1355 pBuf = pShareBuf + fInfo.flash_scratch_pad_blk_offset;
1356 memset(pBuf, 0x00, fInfo.flash_scratch_pad_length);
1357 sts = setSharedBlks(fInfo.flash_scratch_pad_start_blk,
1358 (fInfo.flash_scratch_pad_number_blk + fInfo.flash_scratch_pad_start_blk), pBuf);
1360 retriedKfree(pShareBuf);
1365 int kerSysFlashSizeGet(void)
1367 return flash_get_total_size();
1370 int kerSysMemoryMappedFlashSizeGet(void)
1372 return( flash_get_total_memory_mapped_size() );
1375 unsigned long kerSysReadFromFlash( void *toaddr, unsigned long fromaddr,
1378 int sect = flash_get_blk((int) fromaddr);
1379 unsigned char *start = flash_get_memptr(sect);
1380 flash_read_buf( sect, (int) fromaddr - (int) start, toaddr, len );
1385 /*This function is copied from V2.10.1 to fix the bug SDRAM change from 16M to 8M
1386 during upgrade include CFE */
1387 /***********************************************************************
1388 * Function Name: kerSysMemoryTypeSet
1389 * Description : set the memory type 4 bytes
1390 * Returns : 1 -- ok, 0 -- fail
1391 ***********************************************************************/
1392 int kerSysMemoryTypeSet(int flash_start_addr, char *string, int size)
1398 blk_start = flash_get_blk(flash_start_addr);
1399 sect_size = flash_get_sector_size(blk_start);
1400 if ((pTempBuf = (char *) retriedKmalloc(sect_size)) == NULL)
1402 printk("Failed to allocate memory with size: %d\n", sect_size);
1405 flash_read_buf(blk_start, 0, pTempBuf, sect_size);
1406 memcpy(pTempBuf+SDRAM_TYPE_ADDRESS_OFFSET, string, size);
1407 flash_sector_erase_int(blk_start); // erase blk before flash
1409 if (flash_write_buf(blk_start, 0, pTempBuf, sect_size) != sect_size)
1410 printk("Failed to flash the memory type\n");
1411 // flash_reset_ub();
1415 /*This function is copied from V2.10.1 to fix the bug SDRAM change from 16M to 8M
1416 during upgrade include CFE */
1417 /***********************************************************************
1418 * Function Name: kerSysMemoryTypeSet
1419 * Description : set the memory type 4 bytes
1420 * Returns : 1 -- ok, 0 -- fail
1421 ***********************************************************************/
1422 int kerSysThreadNumSet(int flash_start_addr, char *string, int size)
1428 blk_start = flash_get_blk(flash_start_addr);
1429 sect_size = flash_get_sector_size(blk_start);
1430 if ((pTempBuf = (char *) retriedKmalloc(sect_size)) == NULL)
1432 printk("Failed to allocate memory with size: %d\n", sect_size);
1435 flash_read_buf(blk_start, 0, pTempBuf, sect_size);
1436 memcpy(pTempBuf+THREAD_NUM_ADDRESS_OFFSET, string, size);
1437 flash_sector_erase_int(blk_start); // erase blk before flash
1439 if (flash_write_buf(blk_start, 0, pTempBuf, sect_size) != sect_size)
1440 printk("Failed to flash the thread num\n");
1441 // flash_reset_ub();