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 void *retriedKmalloc(size_t size)
57 int allocType = GFP_KERNEL;
61 allocType = GFP_ATOMIC;
65 // try 1000 times before quit
66 while (((pBuf = kmalloc(size, allocType)) == NULL) && (++tryCount < 1000))
68 current->state = TASK_INTERRUPTIBLE;
69 schedule_timeout(HZ/10);
74 memset(pBuf, 0, size);
79 void retriedKfree(void *pBuf)
84 /***************************************************************************
85 // Function Name: getCrc32
86 // Description : caculate the CRC 32 of the given data.
87 // Parameters : pdata - array of data.
88 // size - number of input data bytes.
89 // crc - either CRC32_INIT_VALUE or previous return value.
91 ****************************************************************************/
92 UINT32 getCrc32(byte *pdata, UINT32 size, UINT32 crc)
95 crc = (crc >> 8) ^ Crc32_table[(crc ^ *pdata++) & 0xff];
100 // get the nvram start addr
102 unsigned long get_nvram_start_addr(void)
104 return ((unsigned long)
105 (flash_get_memptr(fInfo.flash_nvram_start_blk) + fInfo.flash_nvram_blk_offset));
108 // get the scratch_pad start addr
110 unsigned long get_scratch_pad_start_addr(void)
112 return ((unsigned long)
113 (flash_get_memptr(fInfo.flash_scratch_pad_start_blk) + fInfo.flash_scratch_pad_blk_offset));
116 // Initialize the flash and fill out the fInfo structure
117 void kerSysFlashInit( void )
124 NVRAM_DATA nvramData;
125 UINT32 crc = CRC32_INIT_VALUE, savedCrc;
126 PFILE_TAG pTag = NULL;
127 unsigned long kernelEndAddr = 0;
128 unsigned long spAddr = 0;
130 if (flashInitialized)
133 flashInitialized = 1;
136 totalBlks = flash_get_numsectors();
137 totalSize = flash_get_total_size();
139 printk("Total Flash size: %dK with %d sectors\n", totalSize/1024, totalBlks);
141 /* nvram is always at the end of flash */
142 fInfo.flash_nvram_length = NVRAM_LENGTH;
143 fInfo.flash_nvram_start_blk = 0; /* always the first block */
144 fInfo.flash_nvram_number_blk = 1; /*always fits in the first block */
145 fInfo.flash_nvram_blk_offset = NVRAM_DATA_OFFSET;
148 memcpy((char *)&nvramData, (char *)get_nvram_start_addr(), sizeof(NVRAM_DATA));
149 savedCrc = nvramData.ulCheckSum;
150 nvramData.ulCheckSum = 0;
151 crc = getCrc32((char *)&nvramData, (UINT32) sizeof(NVRAM_DATA), crc);
153 BpSetBoardId( nvramData.szBoardId );
155 fInfo.flash_persistent_length = NVRAM_PSI_DEFAULT;
158 printk("***Board is not initialized****: Using the default PSI size: %d\n",
159 fInfo.flash_persistent_length);
163 unsigned long ulPsiSize;
164 if( BpGetPsiSize( &ulPsiSize ) == BP_SUCCESS )
165 fInfo.flash_persistent_length = ulPsiSize;
168 printk("***Board id is not set****: Using the default PSI size: %d\n",
169 fInfo.flash_persistent_length);
173 fInfo.flash_persistent_length *= ONEK;
174 startAddr = totalSize - fInfo.flash_persistent_length;
175 fInfo.flash_persistent_start_blk = flash_get_blk(startAddr+FLASH_BASE);
176 fInfo.flash_persistent_number_blk = totalBlks - fInfo.flash_persistent_start_blk;
177 // save abs SP address (Scratch Pad). it is before PSI
178 spAddr = startAddr - SP_MAX_LEN ;
179 // find out the offset in the start_blk
181 for (i = fInfo.flash_persistent_start_blk;
182 i < (fInfo.flash_persistent_start_blk + fInfo.flash_persistent_number_blk); i++)
184 usedBlkSize += flash_get_sector_size((unsigned short) i);
186 fInfo.flash_persistent_blk_offset = usedBlkSize - fInfo.flash_persistent_length;
188 // get the info for sp
189 if (!(pTag = kerSysImageTagGet()))
191 printk("Failed to read image tag from flash\n");
194 kernelEndAddr = (unsigned long)simple_strtoul(pTag->kernelAddress,NULL,10)+ \
195 (unsigned long) simple_strtoul(pTag->kernelLen, NULL, 10) + BOOT_OFFSET;
197 // make suer sp does not share kernel block
198 fInfo.flash_scratch_pad_start_blk = flash_get_blk(spAddr+FLASH_BASE);
199 if (fInfo.flash_scratch_pad_start_blk != flash_get_blk(kernelEndAddr))
201 fInfo.flash_scratch_pad_length = SP_MAX_LEN;
202 if (fInfo.flash_persistent_start_blk == fInfo.flash_scratch_pad_start_blk) // share blk
204 #if 0 /* do not used scratch pad unless it's in its own sector */
205 printk("Scratch pad is not used for this flash part.\n");
206 fInfo.flash_scratch_pad_length = 0; // no sp
207 #else /* allow scratch pad to share a sector with another section such as PSI */
208 fInfo.flash_scratch_pad_number_blk = 1;
209 fInfo.flash_scratch_pad_blk_offset = fInfo.flash_persistent_blk_offset - fInfo.flash_scratch_pad_length;
212 else // on different blk
214 fInfo.flash_scratch_pad_number_blk = fInfo.flash_persistent_start_blk\
215 - fInfo.flash_scratch_pad_start_blk;
216 // find out the offset in the start_blk
218 for (i = fInfo.flash_scratch_pad_start_blk;
219 i < (fInfo.flash_scratch_pad_start_blk + fInfo.flash_scratch_pad_number_blk); i++)
220 usedBlkSize += flash_get_sector_size((unsigned short) i);
221 fInfo.flash_scratch_pad_blk_offset = usedBlkSize - fInfo.flash_scratch_pad_length;
226 printk("No flash for scratch pad!\n");
227 fInfo.flash_scratch_pad_length = 0; // no sp
230 #if defined(DEBUG_FLASH)
231 printk("fInfo.flash_scratch_pad_start_blk = %d\n", fInfo.flash_scratch_pad_start_blk);
232 printk("fInfo.flash_scratch_pad_number_blk = %d\n", fInfo.flash_scratch_pad_number_blk);
233 printk("fInfo.flash_scratch_pad_length = 0x%x\n", fInfo.flash_scratch_pad_length);
234 printk("fInfo.flash_scratch_pad_blk_offset = 0x%x\n", (unsigned int)fInfo.flash_scratch_pad_blk_offset);
236 printk("fInfo.flash_nvram_start_blk = %d\n", fInfo.flash_nvram_start_blk);
237 printk("fInfo.flash_nvram_blk_offset = 0x%x\n", (unsigned int)fInfo.flash_nvram_blk_offset);
238 printk("fInfo.flash_nvram_number_blk = %d\n", fInfo.flash_nvram_number_blk);
240 printk("psi startAddr = %x\n", startAddr+FLASH_BASE);
241 printk("fInfo.flash_persistent_start_blk = %d\n", fInfo.flash_persistent_start_blk);
242 printk("fInfo.flash_persistent_blk_offset = 0x%x\n", (unsigned int)fInfo.flash_persistent_blk_offset);
243 printk("fInfo.flash_persistent_number_blk = %d\n", fInfo.flash_persistent_number_blk);
250 /***********************************************************************
251 * Function Name: kerSysFlashAddrInfoGet
252 * Description : Fills in a structure with information about the NVRAM
253 * and persistent storage sections of flash memory.
254 * Fro physmap.c to mount the fs vol.
256 ***********************************************************************/
257 void kerSysFlashAddrInfoGet(PFLASH_ADDR_INFO pflash_addr_info)
259 pflash_addr_info->flash_nvram_blk_offset = fInfo.flash_nvram_blk_offset;
260 pflash_addr_info->flash_nvram_length = fInfo.flash_nvram_length;
261 pflash_addr_info->flash_nvram_number_blk = fInfo.flash_nvram_number_blk;
262 pflash_addr_info->flash_nvram_start_blk = fInfo.flash_nvram_start_blk;
263 pflash_addr_info->flash_persistent_blk_offset = fInfo.flash_persistent_blk_offset;
264 pflash_addr_info->flash_persistent_length = fInfo.flash_persistent_length;
265 pflash_addr_info->flash_persistent_number_blk = fInfo.flash_persistent_number_blk;
266 pflash_addr_info->flash_persistent_start_blk = fInfo.flash_persistent_start_blk;
270 // get shared blks into *** pTempBuf *** which has to be released bye the caller!
271 // return: if pTempBuf != NULL, poits to the data with the dataSize of the buffer
274 static char *getSharedBlks(int start_blk, int end_blk)
279 char *pTempBuf = NULL;
282 for (i = start_blk; i < end_blk; i++)
283 usedBlkSize += flash_get_sector_size((unsigned short) i);
285 #if defined(DEBUG_FLASH)
286 printk("usedBlkSize = %d\n", usedBlkSize);
289 if ((pTempBuf = (char *) retriedKmalloc(usedBlkSize)) == NULL)
291 printk("failed to allocate memory with size: %d\n", usedBlkSize);
296 for (i = start_blk; i < end_blk; i++)
298 sect_size = flash_get_sector_size((unsigned short) i);
300 #if defined(DEBUG_FLASH)
301 printk("i = %d, sect_size = %d, end_blk = %d\n", i, sect_size, end_blk);
303 flash_read_buf((unsigned short)i, 0, pBuf, sect_size);
312 // Set the pTempBuf to flash from start_blk to end_blk
316 static int setSharedBlks(int start_blk, int end_blk, char *pTempBuf)
321 char *pBuf = pTempBuf;
323 for (i = start_blk; i < end_blk; i++)
325 sect_size = flash_get_sector_size((unsigned short) i);
326 flash_sector_erase_int(i);
327 if (flash_write_buf(i, 0, pBuf, sect_size) != sect_size)
329 printk("Error writing flash sector %d.", i);
341 /*******************************************************************************
343 *******************************************************************************/
349 int kerSysNvRamGet(char *string, int strLen, int offset)
353 if (!flashInitialized)
356 if (strLen > NVRAM_LENGTH)
359 if ((pBuf = getSharedBlks(fInfo.flash_nvram_start_blk,
360 (fInfo.flash_nvram_start_blk + fInfo.flash_nvram_number_blk))) == NULL)
363 // get string off the memory buffer
364 memcpy(string, (pBuf + fInfo.flash_nvram_blk_offset + offset), strLen);
376 int kerSysNvRamSet(char *string, int strLen, int offset)
381 if (strLen > NVRAM_LENGTH)
384 if ((pBuf = getSharedBlks(fInfo.flash_nvram_start_blk,
385 (fInfo.flash_nvram_start_blk + fInfo.flash_nvram_number_blk))) == NULL)
388 // set string to the memory buffer
389 memcpy((pBuf + fInfo.flash_nvram_blk_offset + offset), string, strLen);
391 if (setSharedBlks(fInfo.flash_nvram_start_blk,
392 (fInfo.flash_nvram_number_blk + fInfo.flash_nvram_start_blk), pBuf) != 0)
401 /***********************************************************************
402 * Function Name: kerSysEraseNvRam
403 * Description : Erase the NVRAM storage section of flash memory.
404 * Returns : 1 -- ok, 0 -- fail
405 ***********************************************************************/
406 int kerSysEraseNvRam(void)
409 char *tempStorage = retriedKmalloc(NVRAM_LENGTH);
411 // just write the whole buf with '0xff' to the flash
416 memset(tempStorage, 0xff, NVRAM_LENGTH);
417 if (kerSysNvRamSet(tempStorage, NVRAM_LENGTH, 0) != 0)
419 retriedKfree(tempStorage);
426 /*******************************************************************************
428 *******************************************************************************/
433 int kerSysPersistentGet(char *string, int strLen, int offset)
437 if (strLen > fInfo.flash_persistent_length)
440 if ((pBuf = getSharedBlks(fInfo.flash_persistent_start_blk,
441 (fInfo.flash_persistent_start_blk + fInfo.flash_persistent_number_blk))) == NULL)
444 // get string off the memory buffer
445 memcpy(string, (pBuf + fInfo.flash_persistent_blk_offset + offset), strLen);
457 int kerSysPersistentSet(char *string, int strLen, int offset)
462 if (strLen > fInfo.flash_persistent_length)
465 if ((pBuf = getSharedBlks(fInfo.flash_persistent_start_blk,
466 (fInfo.flash_persistent_start_blk + fInfo.flash_persistent_number_blk))) == NULL)
469 // set string to the memory buffer
470 memcpy((pBuf + fInfo.flash_persistent_blk_offset + offset), string, strLen);
472 if (setSharedBlks(fInfo.flash_persistent_start_blk,
473 (fInfo.flash_persistent_number_blk + fInfo.flash_persistent_start_blk), pBuf) != 0)
485 // !0 - the sector number fail to be flashed (should not be 0)
486 int kerSysBcmImageSet( int flash_start_addr, char *string, int size)
492 char *pTempBuf = NULL;
495 blk_start = flash_get_blk(flash_start_addr);
499 if (flash_start_addr == FLASH_BASE && size > FLASH_LENGTH_BOOT_ROM)
502 /* write image to flash memory */
505 sect_size = flash_get_sector_size(blk_start);
506 // NOTE: for memory problem in multiple PVC configuration, temporary get rid of kmalloc this 64K for now.
507 // if ((pTempBuf = (char *)retriedKmalloc(sect_size)) == NULL)
509 // printk("Failed to allocate memory with size: %d. Reset the router...\n", sect_size);
510 // kerSysMipsSoftReset(); // reset the board right away.
512 // for whole image, no check on psi
513 if (!whole_image && blk_start == fInfo.flash_persistent_start_blk) // share the blk with psi
515 if (size > (sect_size - fInfo.flash_persistent_length))
517 printk("Image is too big\n");
518 break; // image is too big. Can not overwrite to nvram
520 if ((pTempBuf = (char *)retriedKmalloc(sect_size)) == NULL)
522 printk("Failed to allocate memory with size: %d. Reset the router...\n", sect_size);
523 kerSysMipsSoftReset(); // reset the board right away.
525 flash_read_buf((unsigned short)blk_start, 0, pTempBuf, sect_size);
526 if (copy_from_user((void *)pTempBuf,(void *)string, size) != 0)
528 flash_sector_erase_int(blk_start); // erase blk before flash
529 if (flash_write_buf(blk_start, 0, pTempBuf, sect_size) == sect_size)
530 size = 0; // break out and say all is ok
531 retriedKfree(pTempBuf);
535 flash_sector_erase_int(blk_start); // erase blk before flash
537 if (sect_size > size)
544 if ((i = flash_write_buf(blk_start, 0, string, sect_size)) != sect_size) {
554 // If flashing a whole image, erase to end of flash.
555 int total_blks = flash_get_numsectors();
556 while( blk_start < total_blks )
558 flash_sector_erase_int(blk_start);
563 retriedKfree(pTempBuf);
568 sts = blk_start; // failed to flash this sector
573 /*******************************************************************************
575 *******************************************************************************/
576 // get sp data. NOTE: memcpy work here -- not using copy_from/to_user
578 // >0 - number of bytes copied to tokBuf
580 int kerSysScratchPadGet(char *tokenId, char *tokBuf, int bufLen)
582 PSP_TOKEN pToken = NULL;
584 char *pShareBuf = NULL;
585 char *startPtr = NULL;
589 if (fInfo.flash_scratch_pad_length == 0)
592 if( bufLen >= (fInfo.flash_scratch_pad_length - sizeof(SP_HEADER) -
595 printk("Exceed scratch pad space by %d\n", bufLen -
596 fInfo.flash_scratch_pad_length - sizeof(SP_HEADER) -
601 if( (pShareBuf = getSharedBlks(fInfo.flash_scratch_pad_start_blk,
602 (fInfo.flash_scratch_pad_start_blk +
603 fInfo.flash_scratch_pad_number_blk))) == NULL )
608 // pBuf points to SP buf
609 pBuf = pShareBuf + fInfo.flash_scratch_pad_blk_offset;
611 if(memcmp(((PSP_HEADER)pBuf)->SPMagicNum, MAGIC_NUMBER, MAGIC_NUM_LEN) != 0)
613 printk("Scratch pad is not initialized.\n");
614 retriedKfree(pShareBuf);
618 // search for the token
619 usedLen = sizeof(SP_HEADER);
620 startPtr = pBuf + sizeof(SP_HEADER);
621 pToken = (PSP_TOKEN) startPtr;
622 while( pToken->tokenName[0] != '\0' && pToken->tokenLen > 0 &&
623 pToken->tokenLen < fInfo.flash_scratch_pad_length &&
624 usedLen < fInfo.flash_scratch_pad_length )
627 if (strncmp(pToken->tokenName, tokenId, TOKEN_NAME_LEN) == 0)
629 if ( pToken->tokenLen > bufLen )
631 printk("The length %d of token %s is greater than buffer len %d.\n", pToken->tokenLen, pToken->tokenName, bufLen);
634 sts = pToken->tokenLen;
635 memcpy(tokBuf, startPtr + sizeof(SP_TOKEN), sts);
639 usedLen += ((pToken->tokenLen + 0x03) & ~0x03);
640 startPtr += sizeof(SP_TOKEN) + ((pToken->tokenLen + 0x03) & ~0x03);
641 pToken = (PSP_TOKEN) startPtr;
644 retriedKfree(pShareBuf);
650 // set sp. NOTE: memcpy work here -- not using copy_from/to_user
654 int kerSysScratchPadSet(char *tokenId, char *tokBuf, int bufLen)
656 PSP_TOKEN pToken = NULL;
657 char *pShareBuf = NULL;
664 if (fInfo.flash_scratch_pad_length == 0)
667 if( bufLen >= fInfo.flash_scratch_pad_length - sizeof(SP_HEADER) -
670 printk("Scratch pad overflow by %d bytes. Information not saved.\n",
671 bufLen - fInfo.flash_scratch_pad_length - sizeof(SP_HEADER) -
676 if( (pShareBuf = getSharedBlks( fInfo.flash_scratch_pad_start_blk,
677 (fInfo.flash_scratch_pad_start_blk +
678 fInfo.flash_scratch_pad_number_blk) )) == NULL )
683 // pBuf points to SP buf
684 pBuf = pShareBuf + fInfo.flash_scratch_pad_blk_offset;
687 memset((char *)&SPHead, 0, sizeof(SP_HEADER));
688 memcpy(SPHead.SPMagicNum, MAGIC_NUMBER, MAGIC_NUM_LEN);
689 SPHead.SPVersion = SP_VERSION;
692 memset((char*)&SPToken, 0, sizeof(SP_TOKEN));
693 strncpy(SPToken.tokenName, tokenId, TOKEN_NAME_LEN - 1);
694 SPToken.tokenLen = bufLen;
696 if(memcmp(((PSP_HEADER)pBuf)->SPMagicNum, MAGIC_NUMBER, MAGIC_NUM_LEN) != 0)
698 // new sp, so just flash the token
699 printk("No scratch pad found. Initialize scratch pad...\n");
700 memcpy(pBuf, (char *)&SPHead, sizeof(SP_HEADER));
701 curPtr = pBuf + sizeof(SP_HEADER);
702 memcpy(curPtr, (char *)&SPToken, sizeof(SP_TOKEN));
703 curPtr += sizeof(SP_TOKEN);
705 memcpy(curPtr, tokBuf, bufLen);
714 /* Calculate the used length. */
715 usedLen = sizeof(SP_HEADER);
716 curPtr = pBuf + sizeof(SP_HEADER);
717 pToken = (PSP_TOKEN) curPtr;
718 skipLen = (pToken->tokenLen + 0x03) & ~0x03;
719 while( pToken->tokenName[0] >= 'A' && pToken->tokenName[0] <= 'z' &&
720 strlen(pToken->tokenName) < TOKEN_NAME_LEN &&
721 pToken->tokenLen > 0 &&
722 pToken->tokenLen < fInfo.flash_scratch_pad_length &&
723 usedLen < fInfo.flash_scratch_pad_length )
725 usedLen += sizeof(SP_TOKEN) + skipLen;
726 curPtr += sizeof(SP_TOKEN) + skipLen;
727 pToken = (PSP_TOKEN) curPtr;
728 skipLen = (pToken->tokenLen + 0x03) & ~0x03;
731 if( usedLen + SPToken.tokenLen + sizeof(SP_TOKEN) >
732 fInfo.flash_scratch_pad_length )
734 printk("Scratch pad overflow by %d bytes. Information not saved.\n",
735 (usedLen + SPToken.tokenLen + sizeof(SP_TOKEN)) -
736 fInfo.flash_scratch_pad_length);
740 curPtr = pBuf + sizeof(SP_HEADER);
741 curLen = sizeof(SP_HEADER);
742 while( curLen < usedLen )
744 pToken = (PSP_TOKEN) curPtr;
745 skipLen = (pToken->tokenLen + 0x03) & ~0x03;
746 if (strncmp(pToken->tokenName, tokenId, TOKEN_NAME_LEN) == 0)
748 // The token id already exists.
749 if( tokBuf && pToken->tokenLen == bufLen )
751 // The length of the new data and the existing data is the
752 // same. Overwrite the existing data.
753 memcpy((curPtr+sizeof(SP_TOKEN)), tokBuf, bufLen);
758 // The length of the new data and the existing data is
759 // different. Shift the rest of the scratch pad to this
760 // token's location and put this token's data at the end.
761 char *nextPtr = curPtr + sizeof(SP_TOKEN) + skipLen;
762 int copyLen = usedLen - (curLen+sizeof(SP_TOKEN) + skipLen);
763 memcpy( curPtr, nextPtr, copyLen );
764 memset( curPtr + copyLen, 0x00,
765 fInfo.flash_scratch_pad_length - (curLen + copyLen) );
766 usedLen -= sizeof(SP_TOKEN) + skipLen;
772 curPtr += sizeof(SP_TOKEN) + skipLen;
773 curLen += sizeof(SP_TOKEN) + skipLen;
780 memcpy( pBuf + usedLen, &SPToken, sizeof(SP_TOKEN) );
781 memcpy( pBuf + usedLen + sizeof(SP_TOKEN), tokBuf, bufLen );
783 memcpy( pBuf, &SPHead, sizeof(SP_HEADER) );
786 } // else if not new sp
788 sts = setSharedBlks(fInfo.flash_scratch_pad_start_blk,
789 (fInfo.flash_scratch_pad_number_blk + fInfo.flash_scratch_pad_start_blk),
792 retriedKfree(pShareBuf);
799 // wipe out the scratchPad
803 int kerSysScratchPadClearAll(void)
806 char *pShareBuf = NULL;
810 if (fInfo.flash_scratch_pad_length == 0)
812 if( (pShareBuf = getSharedBlks( fInfo.flash_scratch_pad_start_blk,
813 (fInfo.flash_scratch_pad_start_blk + fInfo.flash_scratch_pad_number_blk) )) == NULL )
815 pBuf = pShareBuf + fInfo.flash_scratch_pad_blk_offset;
816 memset(pBuf, 0x00, fInfo.flash_scratch_pad_length);
817 sts = setSharedBlks(fInfo.flash_scratch_pad_start_blk,
818 (fInfo.flash_scratch_pad_number_blk + fInfo.flash_scratch_pad_start_blk), pBuf);
820 retriedKfree(pShareBuf);
825 int kerSysFlashSizeGet(void)
827 return flash_get_total_size();
830 int kerSysMemoryMappedFlashSizeGet(void)
832 return( flash_get_total_memory_mapped_size() );
835 unsigned long kerSysReadFromFlash( void *toaddr, unsigned long fromaddr,
838 int sect = flash_get_blk((int) fromaddr);
839 unsigned char *start = flash_get_memptr(sect);
840 flash_read_buf( sect, (int) fromaddr - (int) start, toaddr, len );