summaryrefslogtreecommitdiffstats
path: root/shared/opensource/flash/flash_common.c
diff options
context:
space:
mode:
Diffstat (limited to 'shared/opensource/flash/flash_common.c')
-rwxr-xr-xshared/opensource/flash/flash_common.c280
1 files changed, 280 insertions, 0 deletions
diff --git a/shared/opensource/flash/flash_common.c b/shared/opensource/flash/flash_common.c
new file mode 100755
index 0000000..0d4a75d
--- /dev/null
+++ b/shared/opensource/flash/flash_common.c
@@ -0,0 +1,280 @@
+/*
+ Copyright 2000-2010 Broadcom Corporation
+
+ Unless you and Broadcom execute a separate written software license
+ agreement governing use of this software, this software is licensed
+ to you under the terms of the GNU General Public License version 2
+ (the “GPL”), available at http://www.broadcom.com/licenses/GPLv2.php,
+ with the following added to such license:
+
+ As a special exception, the copyright holders of this software give
+ you permission to link this software with independent modules, and to
+ copy and distribute the resulting executable under terms of your
+ choice, provided that you also meet, for each linked independent
+ module, the terms and conditions of the license of that module.
+ An independent module is a module which is not derived from this
+ software. The special exception does not apply to any modifications
+ of the software.
+
+ Notwithstanding the above, under no circumstances may you combine this
+ software in any way with any other Broadcom software provided under a
+ license other than the GPL, without Broadcom's express prior written
+ consent.
+*/
+
+/*!\file flash_common.c
+ * \brief This file contains NOR flash related functions used by both
+ * CFE and kernel.
+ *
+ */
+
+/** Includes. */
+#ifdef _CFE_
+#include "lib_types.h"
+#include "lib_printf.h"
+#include "lib_string.h"
+#include "bcm_map.h"
+#define printk printf
+#else // Linux
+#include <linux/kernel.h>
+#include "bcm_map_part.h"
+#endif
+
+#include "bcmtypes.h"
+#include "bcm_hwdefs.h"
+#include "flash_api.h"
+#include "flash_common.h"
+
+// #define DEBUG_FLASH
+
+void flash_init_info(const NVRAM_DATA *nvRam, FLASH_ADDR_INFO *fInfo)
+{
+ int i = 0;
+ int totalBlks = 0;
+ int totalSize = 0;
+ int psiStartAddr = 0;
+ int spStartAddr = 0;
+ int usedBlkSize = 0;
+ int needBytes = 0;
+
+ if (flash_get_flash_type() == FLASH_IFC_NAND)
+ {
+ /* When using NAND flash disable Bcm_flash */
+ totalSize = 0;
+ }
+ else {
+ totalBlks = flash_get_numsectors();
+ totalSize = flash_get_total_size();
+ printk("Total Flash size: %dK with %d sectors\n", totalSize/1024, totalBlks);
+ }
+
+ if (totalSize <= FLASH_LENGTH_BOOT_ROM) {
+ /* NAND flash settings. NAND flash does not use raw flash partitioins
+ * to store psi, backup psi, scratch pad and syslog. These data items
+ * are stored as files on a JFFS2 file system.
+ */
+ if ((nvRam->ulPsiSize != -1) && (nvRam->ulPsiSize != 0))
+ fInfo->flash_persistent_length = nvRam->ulPsiSize * ONEK;
+ else
+ fInfo->flash_persistent_length = DEFAULT_PSI_SIZE * ONEK;
+
+ fInfo->flash_persistent_start_blk = 0;
+ fInfo->flash_rootfs_start_offset = 0;
+ fInfo->flash_scratch_pad_length = SP_MAX_LEN;
+ fInfo->flash_syslog_length = nvRam->ulSyslogSize * 1024;
+
+ /* This is a boolean field for NAND flash. */
+ fInfo->flash_backup_psi_number_blk = nvRam->backupPsi;
+ return;
+ }
+
+ /*
+ * calculate mandatory primary PSI size and set its fInfo parameters.
+ */
+ if ((nvRam->ulPsiSize != -1) && (nvRam->ulPsiSize != 0))
+ fInfo->flash_persistent_length = nvRam->ulPsiSize * ONEK;
+ else
+ fInfo->flash_persistent_length = DEFAULT_PSI_SIZE * ONEK;
+
+ psiStartAddr = totalSize - fInfo->flash_persistent_length;
+ fInfo->flash_persistent_start_blk = flash_get_blk(FLASH_BASE+psiStartAddr);
+ fInfo->flash_persistent_number_blk = totalBlks - fInfo->flash_persistent_start_blk;
+
+ usedBlkSize = 0;
+ for (i = fInfo->flash_persistent_start_blk;
+ i < (fInfo->flash_persistent_start_blk + fInfo->flash_persistent_number_blk); i++)
+ {
+ usedBlkSize += flash_get_sector_size((unsigned short) i);
+ }
+ fInfo->flash_persistent_blk_offset = usedBlkSize - fInfo->flash_persistent_length;
+ fInfo->flash_meta_start_blk = fInfo->flash_persistent_start_blk;
+
+ /*
+ * Next is the optional scratch pad, which is on top of the primary PSI.
+ * Old code allowed scratch pad to share a sector with primary PSI.
+ * That is retained for backward compatibility. (Although depending on your
+ * NOR flash sector sizes, they may still be in different sectors.)
+ * If you have a new deployment, consider forcing separate sectors.
+ */
+ if ((fInfo->flash_persistent_blk_offset > 0) &&
+ (fInfo->flash_persistent_blk_offset < SP_MAX_LEN))
+ {
+ /*
+ * there is some room left in the first persistent sector, but it is
+ * not big enough for the scratch pad. (Use this line unconditionally
+ * if you want to guarentee scratch pad and primary PSI are on different
+ * sectors.)
+ */
+ spStartAddr = psiStartAddr - fInfo->flash_persistent_blk_offset - SP_MAX_LEN;
+ }
+ else
+ {
+ /* either the primary PSI starts on a sector boundary, or there is
+ * enough room at the top of the first sector for the scratch pad. */
+ spStartAddr = psiStartAddr - SP_MAX_LEN ;
+ }
+
+ fInfo->flash_scratch_pad_start_blk = flash_get_blk(FLASH_BASE+spStartAddr);
+ fInfo->flash_scratch_pad_length = SP_MAX_LEN;
+
+ if (fInfo->flash_persistent_start_blk == fInfo->flash_scratch_pad_start_blk) // share blk
+ {
+#if 0 /* do not used scratch pad unless it's in its own sector */
+ printk("Scratch pad is not used for this flash part.\n");
+ fInfo->flash_scratch_pad_length = 0; // no sp
+#else /* allow scratch pad to share a sector with another section such as PSI */
+ fInfo->flash_scratch_pad_number_blk = 1;
+ fInfo->flash_scratch_pad_blk_offset = fInfo->flash_persistent_blk_offset - fInfo->flash_scratch_pad_length;
+#endif
+ }
+ else // on different blk
+ {
+ fInfo->flash_scratch_pad_number_blk = fInfo->flash_persistent_start_blk - fInfo->flash_scratch_pad_start_blk;
+ // find out the offset in the start_blk
+ usedBlkSize = 0;
+ for (i = fInfo->flash_scratch_pad_start_blk;
+ i < (fInfo->flash_scratch_pad_start_blk + fInfo->flash_scratch_pad_number_blk); i++)
+ usedBlkSize += flash_get_sector_size((unsigned short) i);
+ fInfo->flash_scratch_pad_blk_offset = usedBlkSize - fInfo->flash_scratch_pad_length;
+ }
+
+ if (fInfo->flash_scratch_pad_length > 0) {
+
+ fInfo->flash_meta_start_blk = fInfo->flash_scratch_pad_start_blk;
+ }
+
+ /*
+ * Next is the optional backup PSI.
+ */
+ if (nvRam->backupPsi == 0x01)
+ {
+ needBytes = fInfo->flash_persistent_length;
+ i = fInfo->flash_meta_start_blk;
+ while (needBytes > 0)
+ {
+ i--;
+ needBytes -= flash_get_sector_size((unsigned short) i);
+ }
+ fInfo->flash_backup_psi_start_blk = i;
+ /* calclate how many blocks we actually consumed */
+ needBytes = fInfo->flash_persistent_length;
+ fInfo->flash_backup_psi_number_blk = 0;
+ while (needBytes > 0)
+ {
+ needBytes -= flash_get_sector_size((unsigned short) i);
+ i++;
+ fInfo->flash_backup_psi_number_blk++;
+ }
+
+ fInfo->flash_meta_start_blk = fInfo->flash_backup_psi_start_blk;
+ }
+ else
+ {
+ fInfo->flash_backup_psi_number_blk = 0;
+ }
+
+ /*
+ * Next is the optional persistent syslog.
+ */
+ if (nvRam->ulSyslogSize != 0 && nvRam->ulSyslogSize != -1)
+ {
+ fInfo->flash_syslog_length = nvRam->ulSyslogSize * 1024;
+ needBytes = fInfo->flash_syslog_length;
+ i = fInfo->flash_meta_start_blk;
+ while (needBytes > 0)
+ {
+ i--;
+ needBytes -= flash_get_sector_size((unsigned short) i);
+ }
+ fInfo->flash_syslog_start_blk = i;
+ /* calclate how many blocks we actually consumed */
+ needBytes = fInfo->flash_syslog_length;
+ fInfo->flash_syslog_number_blk = 0;
+ while (needBytes > 0)
+ {
+ needBytes -= flash_get_sector_size((unsigned short) i);
+ i++;
+ fInfo->flash_syslog_number_blk++;
+ }
+
+ fInfo->flash_meta_start_blk = fInfo->flash_syslog_start_blk;
+ }
+ else
+ {
+ fInfo->flash_syslog_length = 0;
+ fInfo->flash_syslog_number_blk = 0;
+ }
+
+#ifdef DEBUG_FLASH_TOO_MUCH
+ /* dump sizes of all sectors in flash */
+ for (i=0; i<totalBlks; i++)
+ printk("blk %03d: %d\n", i, flash_get_sector_size((unsigned short) i));
+#endif
+
+#if defined(DEBUG_FLASH)
+ printk("FLASH_BASE =0x%08x\n\n", (unsigned int)FLASH_BASE);
+
+ printk("fInfo->flash_rootfs_start_offset =0x%08x\n\n", (unsigned int)fInfo->flash_rootfs_start_offset);
+
+ printk("fInfo->flash_meta_start_blk = %d\n\n", fInfo->flash_meta_start_blk);
+
+ printk("fInfo->flash_syslog_start_blk = %d\n", fInfo->flash_syslog_start_blk);
+ printk("fInfo->flash_syslog_number_blk = %d\n", fInfo->flash_syslog_number_blk);
+ printk("fInfo->flash_syslog_length=0x%x\n\n", (unsigned int)fInfo->flash_syslog_length);
+
+ printk("fInfo->flash_backup_psi_start_blk = %d\n", fInfo->flash_backup_psi_start_blk);
+ printk("fInfo->flash_backup_psi_number_blk = %d\n\n", fInfo->flash_backup_psi_number_blk);
+
+ printk("sp startAddr = %x\n", (unsigned int) (FLASH_BASE+spStartAddr));
+ printk("fInfo->flash_scratch_pad_start_blk = %d\n", fInfo->flash_scratch_pad_start_blk);
+ printk("fInfo->flash_scratch_pad_number_blk = %d\n", fInfo->flash_scratch_pad_number_blk);
+ printk("fInfo->flash_scratch_pad_length = 0x%x\n", fInfo->flash_scratch_pad_length);
+ printk("fInfo->flash_scratch_pad_blk_offset = 0x%x\n\n", (unsigned int)fInfo->flash_scratch_pad_blk_offset);
+
+ printk("psi startAddr = %x\n", (unsigned int) (FLASH_BASE+psiStartAddr));
+ printk("fInfo->flash_persistent_start_blk = %d\n", fInfo->flash_persistent_start_blk);
+ printk("fInfo->flash_persistent_number_blk = %d\n", fInfo->flash_persistent_number_blk);
+ printk("fInfo->flash_persistent_length=0x%x\n", (unsigned int)fInfo->flash_persistent_length);
+ printk("fInfo->flash_persistent_blk_offset = 0x%x\n\n", (unsigned int)fInfo->flash_persistent_blk_offset);
+#endif
+}
+
+unsigned int flash_get_reserved_bytes_at_end(const FLASH_ADDR_INFO *fInfo)
+{
+ unsigned int reserved=0;
+ int i = fInfo->flash_meta_start_blk;
+ int totalBlks = flash_get_numsectors();
+
+ while (i < totalBlks)
+ {
+ reserved += flash_get_sector_size((unsigned short) i);
+ i++;
+ }
+
+#if defined(DEBUG_FLASH)
+ printk("reserved at bottom=%dKB\n", reserved/1024);
+#endif
+
+ return reserved;
+}
+