blob: bcdaeebffbf73a2b8181cc1b63952d114ec6fc5d [file] [log] [blame]
#!/usr/bin/perl
#
# Copyright Statement:
# --------------------
# This software is protected by Copyright and the information contained
# herein is confidential. The software may not be copied and the information
# contained herein may not be used or disclosed except with the written
# permission of MediaTek Inc. (C) 2006
#
# BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
# THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
# RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
# AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
# NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
# SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
# SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
# THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
# NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
# SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
#
# BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
# LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
# AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
# OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
# MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
#
# THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
# WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
# LAWS PRINCIPLES. ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
# RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
# THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
#
#*****************************************************************************
#*
#* Filename:
#* ---------
#* emigenflash.pl
#*
#* Project:
#* --------
#*
#*
#* Description:
#* ------------
#* Parse and generate flash parameter
#*
#* Author:
#* -------
#* Way Chen (mtk54483)
#*
#*============================================================================
#* HISTORY
#* Below this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
#*------------------------------------------------------------------------------
#* $Revision$
#* $Modtime$
#* $Log$
#*
#* 04 21 2014 guo-huei.chang
#* [MOLY00063203] [EMIGEN] Update EMIGEN for Smart Phone Project
#* Update emigen to generate EMI size for none EMI support
#*
#*
#*------------------------------------------------------------------------------
#* Upper this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
#*============================================================================
#****************************************************************************/
my $nor_fat_base_offset;
my $nor_fat_size_offset;
my $nor_partition_sector_offset;
my $nor_nand_fat_base_offset;
my $nor_nand_fat_size_offset;
my $nor_nand_partition_sector_offset;
my $nfb_fat_base_offset;
my $nfb_fat_size_offset;
my $nfb_partition_sector_offset;
my $cmem_max_blocks = 0;
my $cmem_max_sectors = 0;
my $DebugPrint = 1; # 1 for debug; 0 for non-debug
#****************************************************************************
# subroutine: Calculate_FAT_Info
# input: $info_list_href: input list reference of list of MDL info
# $combo_mem_count: number of memory devices selected
# $combo_sip_count: number of SIPs
# $mem_dev_type: MEMORY_DEVICE_TYPE
# $info_output_href: output hash reference for common MDL info,
# including minimum physical flash size,
# minimum small block start address
# maximum default FAT base address
# minimum default FAT size
# minimum RAM size
# common flash series information
# common single/multiple-bank definition
# common PBP information
# minimum PBP size
#****************************************************************************
sub Calculate_FAT_Info
{
my ($MAKEFILE_OPTIONS_LOCAL, $CUSTOM_MEM_DEV_OPTIONS_LOCAL, $COMM_MDL_INFO_LOCAL, $MDL_INFO_LIST_LOCAL, $NOR_FLASH_BASE_ADDRESS_VAL_LOCAL, $NOR_ALLOCATED_FAT_SPACE_VAL_LOCAL,$nor_size_Mb_LOCAL, $CUSTOM_FEATURE_CFG_OPTIONS_LOCAL, $ENTIRE_BLOCK_INFO_START_LIST_LOCAL, $ENTIRE_BLOCK_INFO_SIZE_LIST_LOCAL) = @_;
### Print out the physical available flash size
my $flash_limit = sprintf("0x%08X", $COMM_MDL_INFO_LOCAL->{0}->{'Flash Size'});
#print "$COMM_MDL_INFO_LOCAL->{0}->{'Flash Size'}, $COMM_MDL_INFO_LOCAL->{1}->{'Flash Size'}\n" if ($DebugPrint == 1);
### Calculate real FAT start address and size based on customization
if ((defined $CUSTOM_MEM_DEV_OPTIONS_LOCAL->{NOR_BOOTING_NOR_FS_BASE_ADDRESS}) && (defined $CUSTOM_MEM_DEV_OPTIONS_LOCAL->{NOR_BOOTING_NOR_FS_SIZE}))
{
$$NOR_FLASH_BASE_ADDRESS_VAL_LOCAL = hex($CUSTOM_MEM_DEV_OPTIONS_LOCAL->{NOR_BOOTING_NOR_FS_BASE_ADDRESS});
$$NOR_ALLOCATED_FAT_SPACE_VAL_LOCAL = hex($CUSTOM_MEM_DEV_OPTIONS_LOCAL->{NOR_BOOTING_NOR_FS_SIZE});
}
elsif ((defined $CUSTOM_MEM_DEV_OPTIONS_LOCAL->{NOR_BOOTING_NOR_FS_BASE_ADDRESS}) && (!defined $CUSTOM_MEM_DEV_OPTIONS_LOCAL->{NOR_BOOTING_NOR_FS_SIZE}))
{
$$NOR_FLASH_BASE_ADDRESS_VAL_LOCAL = hex($CUSTOM_MEM_DEV_OPTIONS_LOCAL->{NOR_BOOTING_NOR_FS_BASE_ADDRESS});
if (defined $CUSTOM_MEM_DEV_OPTIONS_LOCAL->{__NOR_FDM5__}) # for NOR FDM5, small blocks at the end of the flash should not be used
{
$$NOR_ALLOCATED_FAT_SPACE_VAL_LOCAL = $COMM_MDL_INFO_LOCAL->{0}->{'Small Block Start'} - hex($CUSTOM_MEM_DEV_OPTIONS_LOCAL->{NOR_BOOTING_NOR_FS_BASE_ADDRESS});
}
else
{
$$NOR_ALLOCATED_FAT_SPACE_VAL_LOCAL = $COMM_MDL_INFO_LOCAL->{0}->{'Flash Size'} - hex($CUSTOM_MEM_DEV_OPTIONS_LOCAL->{NOR_BOOTING_NOR_FS_BASE_ADDRESS});
}
}
elsif ((!defined $CUSTOM_MEM_DEV_OPTIONS_LOCAL->{NOR_BOOTING_NOR_FS_BASE_ADDRESS}) && (defined $CUSTOM_MEM_DEV_OPTIONS_LOCAL->{NOR_BOOTING_NOR_FS_SIZE}))
{
$$NOR_FLASH_BASE_ADDRESS_VAL_LOCAL = $COMM_MDL_INFO_LOCAL->{0}->{'Default FAT Base'};
$$NOR_ALLOCATED_FAT_SPACE_VAL_LOCAL = hex($CUSTOM_MEM_DEV_OPTIONS_LOCAL->{NOR_BOOTING_NOR_FS_SIZE});
}
else
{
$$NOR_FLASH_BASE_ADDRESS_VAL_LOCAL = $COMM_MDL_INFO_LOCAL->{0}->{'Default FAT Base'};
$$NOR_ALLOCATED_FAT_SPACE_VAL_LOCAL = $COMM_MDL_INFO_LOCAL->{0}->{'Default FAT Size'};
}
if($MAKEFILE_OPTIONS_LOCAL->{'serial_flash_support'} eq 'TRUE')
{
$COMM_MDL_INFO_LOCAL->{0}->{'Default FAT Base'} = $$NOR_FLASH_BASE_ADDRESS_VAL_LOCAL;
$COMM_MDL_INFO_LOCAL->{0}->{'Default FAT Size'} = $$NOR_ALLOCATED_FAT_SPACE_VAL_LOCAL;
}
elsif($MAKEFILE_OPTIONS_LOCAL->{'nand_support'} eq 'TRUE')
{
$COMM_MDL_INFO_LOCAL->{0}->{'Default FAT Base'} = hex($CUSTOM_MEM_DEV_OPTIONS_LOCAL->{NAND_BOOTING_NAND_FS_BASE_ADDRESS});
$COMM_MDL_INFO_LOCAL->{0}->{'Default FAT Size'} = hex($CUSTOM_MEM_DEV_OPTIONS_LOCAL->{NAND_BOOTING_NAND_FS_SIZE});
}
### work-around for bad small block issue
my $fat_size_shrink;
if ((($$NOR_FLASH_BASE_ADDRESS_VAL_LOCAL+$$NOR_ALLOCATED_FAT_SPACE_VAL_LOCAL)>$COMM_MDL_INFO_LOCAL->{0}->{'Flash Size'}) && (($$NOR_FLASH_BASE_ADDRESS_VAL_LOCAL+$$NOR_ALLOCATED_FAT_SPACE_VAL_LOCAL)<=($nor_size_Mb_LOCAL/8*1024*1024)))
{
$fat_size_shrink = sprintf(" - 0x%08x", $$NOR_FLASH_BASE_ADDRESS_VAL_LOCAL+$$NOR_ALLOCATED_FAT_SPACE_VAL_LOCAL-$COMM_MDL_INFO_LOCAL->{0}->{'Flash Size'});
$$NOR_ALLOCATED_FAT_SPACE_VAL_LOCAL = $$NOR_ALLOCATED_FAT_SPACE_VAL_LOCAL - ($$NOR_FLASH_BASE_ADDRESS_VAL_LOCAL+$$NOR_ALLOCATED_FAT_SPACE_VAL_LOCAL-$COMM_MDL_INFO_LOCAL->{0}->{'Flash Size'});
}
#print "NOR_FLASH_BASE_ADDRESS_VAL = $$NOR_FLASH_BASE_ADDRESS_VAL_LOCAL, NOR_ALLOCATED_FAT_SPACE_VAL = $$NOR_ALLOCATED_FAT_SPACE_VAL_LOCAL\n" if ($DebugPrint == 1);
### Check FAT settings validity
&error_handler("$CUSTOM_MEMORY_DEVICE_HDR_LOCAL: FAT space cannot exceed physical NOR flash size!", __FILE__, __LINE__)
if (($$NOR_FLASH_BASE_ADDRESS_VAL_LOCAL<0) || ($$NOR_ALLOCATED_FAT_SPACE_VAL_LOCAL<0));
&error_handler("$CUSTOM_MEMORY_DEVICE_HDR_LOCAL: FAT space cannot exceed physical NOR flash size!", __FILE__, __LINE__)
if (($$NOR_FLASH_BASE_ADDRESS_VAL_LOCAL+$$NOR_ALLOCATED_FAT_SPACE_VAL_LOCAL) > ($COMM_MDL_INFO_LOCAL->{0}->{'Flash Size'}));
if (defined $CUSTOM_MEM_DEV_OPTIONS_LOCAL->{__NOR_FDM5__})
{
&error_handler("$CUSTOM_MEMORY_DEVICE_HDR_LOCAL: FAT space cannot include small blocks in NOR FDM 5.0!", __FILE__, __LINE__)
if (($$NOR_FLASH_BASE_ADDRESS_VAL_LOCAL+$$NOR_ALLOCATED_FAT_SPACE_VAL_LOCAL) > $COMM_MDL_INFO_LOCAL->{0}->{'Small Block Start'});
}
### FAT tuning for FOTA
$nor_fat_base_offset = "0x0";
$nor_fat_size_offset = "0x0";
$nor_partition_sector_offset = 0;
$nor_nand_fat_base_offset = "0x0";
$nor_nand_fat_size_offset = "0x0";
$nor_nand_partition_sector_offset = 0;
$nfb_fat_base_offset = "0x0";
$nfb_fat_size_offset = "0x0";
$nfb_partition_sector_offset = 0;
##FOTA Feature Related Code, Currently we do not use in MT6291
if ($MAKEFILE_OPTIONS_LOCAL->{'fota_enable'} eq 'FOTA_DM')
{
if ($MAKEFILE_OPTIONS_LOCAL->{'nand_flash_booting'} ne 'NONE')
{
###
# image head area size = block number * block size (0x20000)
# = (1(FOTA_BL_IMG_MAX_SIZE) + 6(FOTA_UE_RESIDENT_FLASH_SPACE_SIZE) + 6(FOTA_UE_BACKUP_FLASH_SPACE_SIZE) + 8(image list block) + 1(ext_bootloader) + 2(bad block margin)) * 0x20000 = 0x300000
my $image_head_area_size = 0x300000;
my ($package_storage_base, $package_storage_size);
###
# FOTA_PACKAGE_STORAGE_BASE = image head area size + all ROM sizes (ROM, SECONDARY_ROM, THIRD_ROM, DEMAND_PAGING_ROM0)
if (defined $MAKEFILE_OPTIONS_LOCAL->{'nand_flash_booting'} and $MAKEFILE_OPTIONS_LOCAL->{'nand_flash_booting'} eq 'ENFB')
{
$package_storage_base = $image_head_area_size + 0x900000 + 0x1500000 + 0x800000;
}
elsif (defined $MAKEFILE_OPTIONS_LOCAL->{'nand_flash_booting'} and $MAKEFILE_OPTIONS_LOCAL->{'nand_flash_booting'} eq 'ONDEMAND')
{
$package_storage_base = $image_head_area_size + 0x400000 + 0xC00000 + 0xE00000;
}
elsif (defined $MAKEFILE_OPTIONS_LOCAL->{'nand_flash_booting'} and $MAKEFILE_OPTIONS_LOCAL->{'nand_flash_booting'} eq 'MIXED')
{
$package_storage_base = $image_head_area_size + 0x400000 + 0xF00000 + 0x800000 + 0x400000;
}
elsif (defined $MAKEFILE_OPTIONS_LOCAL->{'nand_flash_booting'} and $MAKEFILE_OPTIONS_LOCAL->{'nand_flash_booting'} eq 'BASIC')
{
$package_storage_base = $image_head_area_size + 0x800000 + 0x1600000;
}
$package_storage_size = (hex($CUSTOM_FEATURE_CFG_OPTIONS_LOCAL->{CONFIG_FOTA_PACKAGE_AREA_SIZE}) / 0x20000) * 0x20000;
my $recommend_fat_base;
if ($MAKEFILE_OPTIONS_LOCAL->{'secure_support'} eq 'TRUE')
{
# When SECURE_SUPPORT = TRUE, FAT_BASE_ADDRESS = FOTA_PACKAGE_STORAGE_BASE + FOTA_PACKAGE_STORAGE_SIZE + ((4 + FOTA_EXTRA_RESERVED_BLOCKS) * (block size)0x20000)
$recommend_fat_base = $package_storage_base + $package_storage_size + ((4 + 5) * 0x20000);
}
else
{
# When SECURE_SUPPORT = FALSE, FAT_BASE_ADDRESS = FOTA_PACKAGE_STORAGE_BASE + FOTA_PACKAGE_STORAGE_SIZE
$recommend_fat_base = $package_storage_base + $package_storage_size;
}
if (($recommend_fat_base - hex($CUSTOM_MEM_DEV_OPTIONS_LOCAL->{NAND_BOOTING_NAND_FS_BASE_ADDRESS})) > 0)
{
$nfb_fat_base_offset = sprintf("0x%08X", $recommend_fat_base - hex($CUSTOM_MEM_DEV_OPTIONS_LOCAL->{NAND_BOOTING_NAND_FS_BASE_ADDRESS}));
$nfb_fat_size_offset = sprintf("0x%08X", $recommend_fat_base - hex($CUSTOM_MEM_DEV_OPTIONS_LOCAL->{NAND_BOOTING_NAND_FS_BASE_ADDRESS}));
if (defined $CUSTOM_MEM_DEV_OPTIONS_LOCAL->{NAND_BOOTING_NAND_FS_FIRST_DRIVE_SECTORS})
{
my $nand_fat_partition_sectors;
if ($CUSTOM_MEM_DEV_OPTIONS_LOCAL->{NAND_BOOTING_NAND_FS_FIRST_DRIVE_SECTORS} =~ /\(*(\d+)\)*/)
{
$nand_fat_partition_sectors = $1;
}
$nfb_partition_sector_offset = sprintf("%d", ($recommend_fat_base - hex($CUSTOM_MEM_DEV_OPTIONS_LOCAL->{NAND_BOOTING_NAND_FS_BASE_ADDRESS})) / 512) if (($nand_fat_partition_sectors - ($recommend_fat_base-hex($CUSTOM_MEM_DEV_OPTIONS_LOCAL->{NAND_BOOTING_NAND_FS_BASE_ADDRESS}))/512) >= 4096); # NAND user drive should be no less than 4096 sectors
}
}
}
elsif ($MAKEFILE_OPTIONS_LOCAL->{'system_drive_on_nand'} eq 'TRUE' or $MAKEFILE_OPTIONS_LOCAL->{'fota_update_package_on_nand'} eq 'TRUE')
{
my $package_storage_size = (hex($CUSTOM_FEATURE_CFG_OPTIONS_LOCAL->{CONFIG_FOTA_PACKAGE_AREA_SIZE}) / 0x20000) * 0x20000;
$nor_nand_fat_base_offset = sprintf("0x%08X", $package_storage_size);
$nor_nand_fat_size_offset = sprintf("0x%08X", $package_storage_size);
if (defined $CUSTOM_MEM_DEV_OPTIONS_LOCAL->{NOR_BOOTING_NAND_FS_FIRST_DRIVE_SECTORS})
{
my $nand_fat_partition_sectors;
if ($CUSTOM_MEM_DEV_OPTIONS_LOCAL->{NOR_BOOTING_NAND_FS_FIRST_DRIVE_SECTORS} =~ /\(*(\d+)\)*/)
{
$nand_fat_partition_sectors = $1;
}
$nor_nand_partition_sector_offset = sprintf("%d", $package_storage_size / 512) if (($nand_fat_partition_sectors - ($package_storage_size)/512) >= 4096); # NAND user drive should be no less than 4096 sectors
}
}
elsif (!exists $MAKEFILE_OPTIONS_LOCAL->{'emmc_booting'} or $MAKEFILE_OPTIONS_LOCAL->{'emmc_booting'} eq 'NONE') # FOTA update package will be put in a different partition from FS
{
my $fota_block_number = $CUSTOM_FEATURE_CFG_OPTIONS_LOCAL->{CONFIG_FOTA_PACKAGE_BLOCK_NUMBER};
my $ori_nor_flash_base_address_val = $$NOR_FLASH_BASE_ADDRESS_VAL_LOCAL;
my $ori_nor_allocated_fat_space_val = $$NOR_ALLOCATED_FAT_SPACE_VAL_LOCAL;
### Package Storage
while ($fota_block_number > 0)
{
my $tmp_block_sz;
$tmp_block_sz = &config_query_flash_block_sz($$NOR_FLASH_BASE_ADDRESS_VAL_LOCAL, $COMM_MDL_INFO_LOCAL,$ENTIRE_BLOCK_INFO_START_LIST_LOCAL, $ENTIRE_BLOCK_INFO_SIZE_LIST_LOCAL);
$$NOR_FLASH_BASE_ADDRESS_VAL_LOCAL += $tmp_block_sz;
$$NOR_ALLOCATED_FAT_SPACE_VAL_LOCAL -= $tmp_block_sz;
$fota_block_number--;
}
### Backup Storage
my $query_address = 0;
my $max_block_size = 0;
while ($query_address < $COMM_MDL_INFO_LOCAL->{0}->{'Flash Size'})
{
my $cur_block_size = &config_query_flash_block_sz($query_address, $COMM_MDL_INFO_LOCAL, $ENTIRE_BLOCK_INFO_START_LIST_LOCAL, $ENTIRE_BLOCK_INFO_SIZE_LIST_LOCAL);
if ($cur_block_size > $max_block_size)
{
$max_block_size = $cur_block_size;
}
$query_address += $cur_block_size;
}
$$NOR_FLASH_BASE_ADDRESS_VAL_LOCAL += 2 * $max_block_size;
$$NOR_ALLOCATED_FAT_SPACE_VAL_LOCAL -= 2 * $max_block_size;
if (($$NOR_FLASH_BASE_ADDRESS_VAL_LOCAL - $ori_nor_flash_base_address_val) > 0)
{
$nor_fat_base_offset = sprintf("0x%08X", $$NOR_FLASH_BASE_ADDRESS_VAL_LOCAL - $ori_nor_flash_base_address_val);
$nor_fat_size_offset = sprintf("0x%08X", $$ori_nor_allocated_fat_space_val - $$NOR_ALLOCATED_FAT_SPACE_VAL_LOCAL);
if (defined $CUSTOM_MEM_DEV_OPTIONS_LOCAL->{NOR_BOOTING_NOR_FS_FIRST_DRIVE_SECTORS})
{
my $nor_fat_partition_sectors;
if ($CUSTOM_MEM_DEV_OPTIONS_LOCAL->{NOR_BOOTING_NOR_FS_FIRST_DRIVE_SECTORS} =~ /\(*(\d+)\)*/)
{
$nor_fat_partition_sectors = $1;
}
$nor_partition_sector_offset = sprintf("%d", ($ori_nor_allocated_fat_space_val - $$NOR_ALLOCATED_FAT_SPACE_VAL_LOCAL) / 512) if (($nor_fat_partition_sectors - ($ori_nor_allocated_fat_space_val-$NOR_ALLOCATED_FAT_SPACE_VAL_LOCAL)/512) >= 128); # NOR user drive should be no less than 128 sectors
}
}
}
}##end if ($MAKEFILE_OPTIONS_LOCAL->{'fota_enable'} eq 'FOTA_DM')
### Calculate TOTAL_BLOCKS and NOR_BLOCK_SIZE by different memory devices
$cmem_max_blocks = 0;
$cmem_max_sectors = 0;
$nor_block_size = 0;
for (1..$CUSTOM_MEM_DEV_OPTIONS_LOCAL->{COMBO_MEM_ENTRY_COUNT})
{
my $mem_idx = $_;
my (@cur_regions, @cur_banks, @cur_blocks, @cur_new_regions, @cur_blocks_start, @cur_blocks_size);
my $cur_blocks_sum = 0;
my $cur_regions_sum = 0;
my $cur_total_blocks = 0;
my $cur_nor_block_size = 0;
my $cur_total_sectors = 0;
my $cur_sector_size = 0;
my $cur_bank_str = 0;
my $cur_block_str = 0;
$cur_sector_size = ($MDL_INFO_LIST_LOCAL->[$mem_idx]->{1}->{'Comm. Series'} eq 'INTEL_SIBLEY') ? 0x400 : 0x200;
##MDL CS1 is flash, COMM MDL number 0 is flash info
@cur_regions = &split_info($MDL_INFO_LIST_LOCAL->[$mem_idx]->{1}->{'Last Bank'}->{'Region'});
$cur_bank_str = $MDL_INFO_LIST_LOCAL->[$mem_idx]->{1}->{'Device Geometry'}->{'Bank Info.'};
@cur_banks = &split_info($cur_bank_str);
$cur_block_str = $MDL_INFO_LIST_LOCAL->[$mem_idx]->{1}->{'Device Geometry'}->{'Block Info.'};
@cur_blocks = &split_info($cur_block_str);
for (0..$#cur_blocks)
{
if ($cur_blocks[$_] =~ /\{(0x\w+),\s*(0x\w+)\}/) # match {0x0,0x10000}
{
last if (hex($1) >= $COMM_MDL_INFO_LOCAL->{0}->{'Flash Size'}); # end block infor traversal when the flash end among all memories has been reached
push @cur_blocks_start, $1;
push @cur_blocks_size, $2;
}
}
push @cur_blocks_start, $flash_limit;
for (0..($#cur_blocks_start-1))
{
my $target_region = $cur_blocks_size[$_];
my $tmp_block_count = 0;
print "$_: $target_region\n"if ($DebugPrint == 1);
while ($cur_blocks_sum < hex($cur_blocks_start[$_+1]))
{
$cur_blocks_sum += hex($cur_blocks_size[$_]);
if ($cur_blocks_sum > $$NOR_FLASH_BASE_ADDRESS_VAL_LOCAL)
{
$cur_regions_sum += hex($cur_blocks_size[$_]);
$tmp_block_count++;
}
last if ($cur_regions_sum >= $$NOR_ALLOCATED_FAT_SPACE_VAL_LOCAL);
}
if ($tmp_block_count > 0)
{
$cur_total_blocks += $tmp_block_count;
if (hex($target_region) > hex($cur_nor_block_size)) # Find the largest block size within FS
{
$cur_nor_block_size = $target_region;
}
}
last if ($cur_regions_sum >= $$NOR_ALLOCATED_FAT_SPACE_VAL_LOCAL);
}
&error_handler("$CUSTOM_MEMORY_DEVICE_HDR_LOCAL: FAT space must be multiples of blocks!", __FILE__, __LINE__) if ($cur_regions_sum > $$NOR_ALLOCATED_FAT_SPACE_VAL_LOCAL);
### Calculate the current number of sectors
### S1 = ((NOR_ALLOCATED_FAT_SPACE - NOR_BLOCK_SIZEMCP1 * SNOR_ERASE_QUEUE_SIZE) / SECTOR_SIZE)
### NOR_ALLOCATED_FAT_SPACE := NOR_BOOTING_NOR_FS_SIZE
### SNOR_ERASE_QUEUE_SIZE := NOR_FDM4_ESB_PARAMETER_ERASE_QUEUE_SIZE or 5 (default value)
### NOR_SYSTEM_DRIVE_RESERVED_BLOCK := NOR_PARAMETER_SYSTEM_DRIVE_RESERVED_BLOCK or 3 (default value)
### NOR_BLOCK_SIZEMCP1 := The largest block size within FAT in MCP 1.
### SECTOR_SIZE:
### Sibley:=0x400
### Non-Sibley := 0x200
if ($MAKEFILE_OPTIONS_LOCAL->{'enhanced_single_bank_nor_flash_support'} eq 'TRUE')
{
$cur_total_sectors = ($$NOR_ALLOCATED_FAT_SPACE_VAL_LOCAL - (hex($cur_nor_block_size) * $CUSTOM_MEM_DEV_OPTIONS_LOCAL->{NOR_FDM4_ESB_PARAMETER_ERASE_QUEUE_SIZE})) / $cur_sector_size;
}
else
{
$cur_total_sectors = ($$NOR_ALLOCATED_FAT_SPACE_VAL_LOCAL - (hex($cur_nor_block_size) * $CUSTOM_MEM_DEV_OPTIONS_LOCAL->{NOR_PARAMETER_SYSTEM_DRIVE_RESERVED_BLOCK})) / $cur_sector_size;
}
print "FAT SPACE is: $$NOR_ALLOCATED_FAT_SPACE_VAL_LOCAL, BlockSize is: $cur_nor_block_size, SectorSize is $cur_sector_size\n"if ($DebugPrint == 1);
### Find the overall max TOTAL_BLOCKS and NOR_BLOCK_SIZE
if ($nor_block_size < hex($cur_nor_block_size))
{
$nor_block_size = hex($cur_nor_block_size);
}
if ($cmem_max_blocks < $cur_total_blocks)
{
$cmem_max_blocks = $cur_total_blocks;
}
if ($cmem_max_sectors < $cur_total_sectors)
{
$cmem_max_sectors = $cur_total_sectors;
}
}
print "TOTAL_BLOCKS > 127 , recommend enable FDM5.0 feature!\n" if ($cmem_max_blocks > 127);
}
#****************************************************************************
# subroutine: Validate_FAT_NORRAWDISK_OVERLAP
# input: $info_list_href: input list reference of list of MDL info
# $combo_mem_count: number of memory devices selected
# $combo_sip_count: number of SIPs
# $mem_dev_type: MEMORY_DEVICE_TYPE
# $info_output_href: output hash reference for common MDL info,
# including minimum physical flash size,
# minimum small block start address
# maximum default FAT base address
# minimum default FAT size
# minimum RAM size
# common flash series information
# common single/multiple-bank definition
# common PBP information
# minimum PBP size
#****************************************************************************
sub Validate_FAT_NORRAWDISK_OVERLAP
{
my ($CUSTOM_MEM_DEV_OPTIONS_LOCAL, $COMM_MDL_INFO, $NOR_FLASH_BASE_ADDRESS_VAL_LOCAL, $NOR_ALLOCATED_FAT_SPACE_VAL_LOCAL, $CUSTOM_MEMORY_DEVICE_HDR_LOCAL) = @_;
my %dsk_layout_hash;
my @dsk_layout_sort_list;
$dsk_layout_hash{$NOR_FLASH_BASE_ADDRESS_VAL_LOCAL} = $NOR_ALLOCATED_FAT_SPACE_VAL_LOCAL;
if (defined $CUSTOM_MEM_DEV_OPTIONS_LOCAL->{NOR_BOOTING_NOR_DISK0_BASE_ADDRESS})
{
&error_handler("$CUSTOM_MEMORY_DEVICE_HDR_LOCAL: Cannot configure NOR Raw Disk0 larger than physical NOR flash size!", __FILE__, __LINE__)
if ((hex($CUSTOM_MEM_DEV_OPTIONS_LOCAL->{NOR_BOOTING_NOR_DISK0_BASE_ADDRESS})+hex($CUSTOM_MEM_DEV_OPTIONS_LOCAL->{NOR_BOOTING_NOR_DISK0_SIZE})) > $COMM_MDL_INFO_LOCAL->{0}->{'Flash Size'});
&error_handler("$CUSTOM_MEMORY_DEVICE_HDR_LOCAL: Cannot configure NOR Raw Disk0 the same base address as FAT!", __FILE__, __LINE__)
if (hex($CUSTOM_MEM_DEV_OPTIONS_LOCAL->{NOR_BOOTING_NOR_DISK0_BASE_ADDRESS}) == $NOR_FLASH_BASE_ADDRESS_VAL_LOCAL);
$dsk_layout_hash{hex($CUSTOM_MEM_DEV_OPTIONS_LOCAL->{NOR_BOOTING_NOR_DISK0_BASE_ADDRESS})} = hex($CUSTOM_MEM_DEV_OPTIONS_LOCAL->{NOR_BOOTING_NOR_DISK0_SIZE});
}
if (defined $CUSTOM_MEM_DEV_OPTIONS_LOCAL{NOR_BOOTING_NOR_DISK1_BASE_ADDRESS})
{
&error_handler("$CUSTOM_MEMORY_DEVICE_HDR_LOCAL: Cannot configure NOR Raw Disk1 larger than physical NOR flash size!", __FILE__, __LINE__)
if ((hex($CUSTOM_MEM_DEV_OPTIONS_LOCAL->{NOR_BOOTING_NOR_DISK1_BASE_ADDRESS})+hex($CUSTOM_MEM_DEV_OPTIONS_LOCAL->{NOR_BOOTING_NOR_DISK1_SIZE})) > $COMM_MDL_INFO_LOCAL->{0}->{'Flash Size'});
&error_handler("$CUSTOM_MEMORY_DEVICE_HDR_LOCAL: Cannot configure NOR Raw Disk1 the same base address as FAT!", __FILE__, __LINE__)
if (hex($CUSTOM_MEM_DEV_OPTIONS_LOCAL->{NOR_BOOTING_NOR_DISK1_BASE_ADDRESS}) == $NOR_FLASH_BASE_ADDRESS_VAL_LOCAL);
&error_handler("$CUSTOM_MEMORY_DEVICE_HDR_LOCAL: Cannot configure NOR Raw Disk1 the same base address as NOR Raw Disk0!", __FILE__, __LINE__)
if (hex($CUSTOM_MEM_DEV_OPTIONS_LOCAL->{NOR_BOOTING_NOR_DISK1_BASE_ADDRESS}) == hex($CUSTOM_MEM_DEV_OPTIONS_LOCAL->{NOR_BOOTING_NOR_DISK0_BASE_ADDRESS}));
$dsk_layout_hash{hex($CUSTOM_MEM_DEV_OPTIONS_LOCAL->{NOR_BOOTING_NOR_DISK1_BASE_ADDRESS})} = hex($CUSTOM_MEM_DEV_OPTIONS_LOCAL->{NOR_BOOTING_NOR_DISK1_SIZE});
}
foreach (sort {$a <=> $b} keys %dsk_layout_hash)
{
push @dsk_layout_sort_list, $_;
}
foreach (1..$#dsk_layout_sort_list)
{
error_handler("$CUSTOM_MEMORY_DEVICE_HDR_LOCAL: NOR Flash disk overlapping detected. Please check NOR Raw disk and FAT setting!", __FILE__, __LINE__)
if (($dsk_layout_sort_list[$_-1]+$dsk_layout_hash{$dsk_layout_sort_list[$_-1]}) > $dsk_layout_sort_list[$_]);
}
}
#****************************************************************************
# subroutine: Calculate_NORRAWDISK_Region_Info
# input: $info_list_href: input list reference of list of MDL info
# $combo_mem_count: number of memory devices selected
# $combo_sip_count: number of SIPs
# $mem_dev_type: MEMORY_DEVICE_TYPE
# $info_output_href: output hash reference for common MDL info,
# including minimum physical flash size,
# minimum small block start address
# maximum default FAT base address
# minimum default FAT size
# minimum RAM size
# common flash series information
# common single/multiple-bank definition
# common PBP information
# minimum PBP size
#****************************************************************************
sub Calculate_NORRAWDISK_Region_Info
{
my ($CUSTOM_MEM_DEV_OPTIONS_LOCAL) = @_;
my (@regions_disk0, @regions_disk1);
for (0..$CUSTOM_MEM_DEV_OPTIONS_LOCAL->{NOR_BOOTING_NOR_DISK_NUM})
{
my $nor_booting_nor_disk_base_address = sprintf("NOR_BOOTING_NOR_DISK%d_BASE_ADDRESS", $_);
my $nor_booting_nor_disk_size = sprintf("NOR_BOOTING_NOR_DISK%d_SIZE", $_);
my $nor_booting_nor_disk_index = $_;
#print "[$nor_booting_nor_disk_index] Nor Disk Base: $nor_booting_nor_disk_base_address\n"if ($DebugPrint == 1);
#print "[$nor_booting_nor_disk_index] Nor Disk Size: $nor_booting_nor_disk_size\n"if ($DebugPrint == 1);
if (defined $CUSTOM_MEM_DEV_OPTIONS_LOCAL->{$nor_booting_nor_disk_base_address})
{
#print "RAW DISK Check!\n"if ($DebugPrint == 1);
for (0..($#entire_block_info_start_list-1))
{
my $target_region;
my $tmp_block_count = 0;
my $tmp_blocks_sum = 0;
my $tmp_regions_sum = 0;
while ($tmp_blocks_sum < $entire_block_info_start_list[$_+1])
{
$tmp_blocks_sum += $entire_block_info_size_list[$_];
if ($tmp_blocks_sum > hex($CUSTOM_MEM_DEV_OPTIONS_LOCAL->{$nor_booting_nor_disk_base_address}))
{
$tmp_regions_sum += $entire_block_info_size_list[$_];
$target_region = sprintf("0x%X", $entire_block_info_size_list[$_]);
$tmp_block_count++;
}
if ($tmp_regions_sum >= hex($CUSTOM_MEM_DEV_OPTIONS_LOCAL->{$nor_booting_nor_disk_size}))
{
last;
}
}
if ($tmp_block_count > 0)
{
if ($nor_booting_nor_disk_index == 0)
{
push @regions_disk0, "{$target_region,$tmp_block_count}";
}
elsif ($nor_booting_nor_disk_index == 1)
{
push @regions_disk1, "{$target_region,$tmp_block_count}";
}
}
if ($tmp_regions_sum >= hex($CUSTOM_MEM_DEV_OPTIONS_LOCAL->{$nor_booting_nor_disk_size}))
{
last;
}
}
}
}
}
#****************************************************************************
# subroutine: get_common_MDL_info
# input: $info_list_href: input list reference of list of MDL info
# $combo_mem_count: number of memory devices selected
# $combo_sip_count: number of SIPs
# $mem_dev_type: MEMORY_DEVICE_TYPE
# $info_output_href: output hash reference for common MDL info,
# including minimum physical flash size,
# minimum small block start address
# maximum default FAT base address
# minimum default FAT size
# minimum RAM size
# common flash series information
# common single/multiple-bank definition
# common PBP information
# minimum PBP size
#****************************************************************************
sub get_common_MDL_info
{
#my ($info_list_href, $combo_mem_count, $combo_sip_count, $mem_dev_type, $info_output_href, $LPSDRAM_CHIP_SELECT_LOCAL, $MAKEFILE_OPTIONS, $CUSTOM_MEM_DEV_OPTIONS, $CUSTOM_MEMORY_DEVICE_HDR) = @_;
my ($info_list_href, $CUSTOM_MEM_DEV_OPTIONS_LOCAL, $info_output_href, $MAKEFILE_OPTIONS_LOCAL, $LPSDRAM_CHIP_SELECT_LOCAL, $CUSTOM_MEMORY_DEVICE_HDR_LOCAL, $emi_is_existed) = @_;
my $combo_mem_count = $CUSTOM_MEM_DEV_OPTIONS_LOCAL->{COMBO_MEM_ENTRY_COUNT};
my $combo_sip_count = $CUSTOM_MEM_DEV_OPTIONS_LOCAL->{COMBO_SIP_ENTRY_COUNT};
my $mem_dev_type = $CUSTOM_MEM_DEV_OPTIONS_LOCAL->{MEMORY_DEVICE_TYPE};
my $platform = $MAKEFILE_OPTIONS_LOCAL->{'platform'};
my $min_flash_size = 0xffffffff;
my $max_nand_block_size = 0;
my $min_small_block_start = 0xffffffff;
my $max_fat_base = 0;
my $min_fat_space = 0xffffffff;
my $Size_Mb_ram_min = 0xffffffff*8/1024/1024; # minimum size in "Size (Mb)" field for RAM
my $ADMUX_CS0;
my $ADMUX_CS1;
my $if_DRAM;
my $Comm_Series_CS0_all = '*'; # all "Comm. Series" information
my $Comm_Series_CS1_all = '*'; # all "Comm. Series" information
my $Bank_if_S = 'M'; # mark as 'S' if there is any device whose "Bank" field is 'S'
my $PBP_Y_N_if_Y = 'N'; # mark as 'N' if there is any device whose "PBP -> Y/N" field is 'N'
my $PBP_Size_W_min = 0xffffffff; # minimum size in "PBP -> Size(W)" field
my $Last_Bank_Region; # common "Last Bank -> Region" field
my $Geometry_Bank_Info; # common "Geometry -> Bank Info." field
my $Geometry_Block_Info; # common "Geometry -> Block Info." field
#print "Flash PN: $info_list_href->[1]->{1}->{'Part Number'}, $info_list_href->[1]->{1}->{'Flash Size'}\n";
for (1..$combo_mem_count)
{
### Find the smallest default FAT configuration among all MCPs
my $cur_flash_size = 0; # physical flash size (excluding bad small blocks for Toshiba)
my $cur_small_block_start = 0; # the starting location of small blocks at the end of a flash
my $cur_sum_of_regions = 0; # the sum of the regions in the last bank
my $cur_fat_base = 0; # default FAT base (physical flash size - last bank size)
my $cur_fat_space = 0; # default FAT size (last bank size)
my @cur_blocks_start; # list of Block Info starting addresses
my @cur_blocks_size; # list of Block Info sizes
my @cur_regions = &split_info($info_list_href->[$_]->{1}->{'Last Bank'}->{'Region'}); # list of Last Bank -> Region Info.
my $cur_bank_str = $info_list_href->[$_]->{1}->{'Device Geometry'}->{'Bank Info.'};
my @cur_banks = &split_info($cur_bank_str); # list of Bank Info.
my $cur_block_str = $info_list_href->[$_]->{1}->{'Device Geometry'}->{'Block Info.'};
my @cur_blocks = &split_info($cur_block_str); # list of Block Info.
# Calculate default FAT size/start address (Last Bank)
for (0..$#cur_regions) # calculate the sum of last bank
{
if ($cur_regions[$_] =~ /\{(0x\w+)\s*,\s*(\d+)\}/) # match {0x20000, 7}
{
$cur_sum_of_regions += hex($1) * $2;
}
}
for (0..$#cur_banks) # calculate the physical flash size
{
if ($cur_banks[$_] =~ /\{(0x\w+)\s*,\s*(\d+)\}/) # match {0x20000, 7}
{
$cur_flash_size += hex($1) * $2;
$cur_small_block_start += hex($1) * $2;
}
}
if (($#cur_regions>0) && (defined $CUSTOM_MEM_DEV_OPTIONS_LOCAL->{__NOR_FDM5__})) # for NOR FDM5, small blocks at the end of the flash should be excluded
{
if ($cur_blocks[$#cur_blocks] =~ /\{(0x\w+)\s*,\s*(0x\w+)\}/) # match {0xFF0000,0x2000}
{
$cur_small_block_start = hex($1);
}
$cur_fat_space = $cur_sum_of_regions - ($cur_flash_size-$cur_small_block_start);
}
else
{
$cur_fat_space = $cur_sum_of_regions;
}
$cur_fat_base = $cur_flash_size - $cur_sum_of_regions;
##MT6291 Operation
#if($platform eq 'MT6291') # FIXME
{
if ($MAKEFILE_OPTIONS_LOCAL->{'nand_support'} eq 'TRUE')
{
if (defined $info_list_href->[$_]->{1}->{'NAND Size(MB)'})##Fill NAND Flash Size if NAND Flash is exist
{
$cur_flash_size = $info_list_href->[$_]->{1}->{'NAND Size(MB)'} * 1024 * 1024;
}
else
{
$cur_flash_size = 0xffffffff;
}
}
}
# Temporarily store physical flash size, small block start, and default FAT size/base for future reference
$info_list_href->[$_]->{1}->{'Flash Size'} = $cur_flash_size;
$info_list_href->[$_]->{1}->{'Small Block Start'} = $cur_small_block_start;
$info_list_href->[$_]->{1}->{'Default FAT Base'} = $cur_fat_base;
$info_list_href->[$_]->{1}->{'Default FAT Size'} = $cur_fat_space;
#print "Flash PN: $info_list_href->[$_]->{1}->{'Part Number'}, FlashSize: $info_list_href->[$_]->{1}->{'Flash Size'}, SmallBlockStart: $info_list_href->[$_]->{1}->{'Small Block Start'}, FATBase: $info_list_href->[$_]->{1}->{'Default FAT Base'}, FATSize: $info_list_href->[$_]->{1}->{'Default FAT Size'}\n"if ($DebugPrint == 1);
# In order to speed-up, assume the largest FAT base will be smaller than the physical flash size first
# Find the largest FAT base
if ($max_fat_base < $cur_fat_base)
{
$max_fat_base = $cur_fat_base;
}
# Find the smallest flash size
if ($min_flash_size > $cur_flash_size)
{
$min_flash_size = $cur_flash_size;
}
# Find the smallest small block start
if ($min_small_block_start > $cur_small_block_start)
{
$min_small_block_start = $cur_small_block_start;
}
### Find the minimum RAM size in Mb
my $cur_Size_Mb_ram = $info_list_href->[$_]->{0}->{'Density (Mb)'};
if ($Size_Mb_ram_min > $cur_Size_Mb_ram)
{
$Size_Mb_ram_min = $cur_Size_Mb_ram;
}
### Find common ADMUX definition
if ($info_list_href->[$_]->{0}->{'ADMUX'} =~ /YES/i)
{
&error_handler("$CUSTOM_MEMORY_DEVICE_HDR_LOCAL: Cannot select ADMUX/AD-DEMUX at one time! Please change selected MCP!", __FILE__, __LINE__) if ($ADMUX_CS0 eq "NO");
$ADMUX_CS0 = "YES";
}
elsif ($info_list_href->[$_]->{0}->{'ADMUX'} =~ /NO/i)
{
&error_handler("$CUSTOM_MEMORY_DEVICE_HDR_LOCAL: Cannot select ADMUX/AD-DEMUX at one time! Please change selected MCP!", __FILE__, __LINE__) if ($ADMUX_CS0 eq "YES");
$ADMUX_CS0 = "NO";
}
if ($info_list_href->[$_]->{1}->{'ADMUX'} =~ /YES/i)
{
&error_handler("$CUSTOM_MEMORY_DEVICE_HDR_LOCAL: Cannot select ADMUX/AD-DEMUX at one time! Please change selected MCP!", __FILE__, __LINE__) if ($ADMUX_CS1 eq "NO");
$ADMUX_CS1 = "YES";
}
elsif ($info_list_href->[$_]->{1}->{'ADMUX'} =~ /NO/i)
{
&error_handler("$CUSTOM_MEMORY_DEVICE_HDR_LOCAL: Cannot select ADMUX/AD-DEMUX at one time! Please change selected MCP!", __FILE__, __LINE__) if ($ADMUX_CS1 eq "YES");
$ADMUX_CS1 = "NO";
}
### Find common "DRAM" information
if ($info_list_href->[$_]->{1}->{'DRAM'} =~ /YES/i)
{
&error_handler("$CUSTOM_MEMORY_DEVICE_HDR_LOCAL: Cannot select DRAM/PSRAM at one time! Please change selected MCP!", __FILE__, __LINE__) if ($if_DRAM eq "NO");
$if_DRAM = "YES";
}
elsif ($info_list_href->[$_]->{1}->{'DRAM'} =~ /NO/i)
{
&error_handler("$CUSTOM_MEMORY_DEVICE_HDR_LOCAL: Cannot select DRAM/PSRAM at one time! Please change selected MCP!", __FILE__, __LINE__) if ($if_DRAM eq "YES");
$if_DRAM = "NO";
}
### Find common "Comm. Series" information
if ((defined $info_list_href->[$_]->{1}->{'Comm. Series'}) and ($info_list_href->[$_]->{1}->{'Comm. Series'} ne '*'))
{
if ($Comm_Series_CS0_all eq '*')
{
$Comm_Series_CS0_all = $info_list_href->[$_]->{1}->{'Comm. Series'};
}
else
{
$Comm_Series_CS0_all .= " $info_list_href->[$_]->{1}->{'Comm. Series'}";
}
}
if ((defined $info_list_href->[$_]->{1}->{'Comm. Series'}) and ($info_list_href->[$_]->{1}->{'Comm. Series'} ne '*'))
{
if ($Comm_Series_CS1_all eq '*')
{
$Comm_Series_CS1_all = $info_list_href->[$_]->{1}->{'Comm. Series'};
}
else
{
$Comm_Series_CS1_all .= " $info_list_href->[$_]->{1}->{'Comm. Series'}";
}
}
### Find common single/multiple-bank definition
if ($info_list_href->[$_]->{1}->{'Bank'} =~ /S/i)
{
$Bank_if_S = 'S';
}
### Find common PBP information
if ($info_list_href->[$_]->{1}->{'PBP'}->{'Y / N'} =~ /Y/i)
{
$PBP_Y_N_if_Y = 'Y';
}
#print "PBP1: $info_list_href->[$_]->{1}->{'PBP'}->{'Y / N'}, PBP2: $info_list_href->[$_]->{1}->{'PBP'}->{'Size (Byte)'}\n"if ($DebugPrint == 1);
### Find the minimum PBP size
my $cur_PBP_size_W = ($mem_dev_type eq 'NOR_RAM_MCP') ? ($info_list_href->[$_]->{0}->{'PBP'}->{'Size(W)'}) : ($info_list_href->[$_]->{1}->{'PBP'}->{'Size (Byte)'}/2);
if ($cur_PBP_size_W eq '*' or $cur_PBP_size_W eq 'x' or $cur_PBP_size_W eq ' ')
{
$cur_PBP_size_W = 0;
}
if ($PBP_Size_W_min > $cur_PBP_size_W)
{
$PBP_Size_W_min = $cur_PBP_size_W;
}
### Find the max block size
if (defined $info_list_href->[$_]->{$LPSDRAM_CHIP_SELECT_LOCAL}->{'NAND Block Size(KB)'})
{
if ($max_nand_block_size < $info_list_href->[$_]->{$LPSDRAM_CHIP_SELECT_LOCAL}->{'NAND Block Size(KB)'} * 1024)
{
$max_nand_block_size = $info_list_href->[$_]->{$LPSDRAM_CHIP_SELECT_LOCAL}->{'NAND Block Size(KB)'} * 1024;
}
}
}##end for (1..$combo_mem_count)
### Work around when the FAT base is larger than some flash size
if (($max_fat_base > $min_flash_size) or ($max_fat_base > $min_small_block_start))
{
$max_fat_base = 0;
for (1..$combo_mem_count)
{
if (($info_list_href->[$_]->{1}->{'Default FAT Base'} < $min_flash_size) and ($info_list_href->[$_]->{1}->{'Default FAT Base'} < $min_small_block_start) and ($max_fat_base < $info_list_href->[$_]->{1}->{'Default FAT Base'}))
{
$max_fat_base = $info_list_href->[$_]->{1}->{'Default FAT Base'};
}
}
}
$min_fat_space = $min_flash_size - $max_fat_base;
for (1..$combo_mem_count)
{
my $cur_Size_Mb_ram;
$cur_Size_Mb_ram = $info_list_href->[$_]->{0}->{'Density (Mb)'};
if ($Size_Mb_ram_min > $cur_Size_Mb_ram)
{
$Size_Mb_ram_min = $cur_Size_Mb_ram;
}
}
$info_output_href->{0}->{'Flash Size'} = $min_flash_size;
$info_output_href->{0}->{'NAND Block Size(KB)'} = $max_nand_block_size / 1024;
$info_output_href->{0}->{'Small Block Start'} = $min_small_block_start;
$info_output_href->{0}->{'Default FAT Base'} = $max_fat_base;
$info_output_href->{0}->{'Default FAT Size'} = $min_fat_space;
$info_output_href->{1}->{'Size (Mb)'} = $Size_Mb_ram_min;
$info_output_href->{0}->{'ADMUX'} = $ADMUX_CS0;
$info_output_href->{1}->{'ADMUX'} = $ADMUX_CS1;
$info_output_href->{1}->{'DRAM'} = $if_DRAM;
$info_output_href->{0}->{'Comm. Series'} = $Comm_Series_CS0_all;
$info_output_href->{1}->{'Comm. Series'} = $Comm_Series_CS1_all;
$info_output_href->{0}->{'Bank'} = $Bank_if_S;
$info_output_href->{0}->{'PBP'}->{'Y / N'} = $PBP_Y_N_if_Y;
$info_output_href->{0}->{'PBP'}->{'Size(W)'} = $PBP_Size_W_min;
#print "FlashSize[0] is $info_output_href->{0}->{'Flash Size'}, FlashSize[1] is $info_output_href->{1}->{'Flash Size'}\n"if ($DebugPrint == 1);
#print "NANDBlockSize[0] is $info_output_href->{0}->{'NAND Block Size(KB)'}, NANDBlockSize[1] is $info_output_href->{1}->{'NAND Block Size(KB)'}\n"if ($DebugPrint == 1);
#print "SmallBlockStart[0] is $info_output_href->{0}->{'Small Block Start'}, SmallBlockStart[1] is $info_output_href->{1}->{'Small Block Start'}\n"if ($DebugPrint == 1);
#print "DefaultFATBase[0] is $info_output_href->{0}->{'Default FAT Base'}, DefaultFATBase[1] is $info_output_href->{1}->{'Default FAT Base'}\n"if ($DebugPrint == 1);
#print "DefaultFATSize[0] is $info_output_href->{0}->{'Default FAT Size'}, DefaultFATSize[1] is $info_output_href->{1}->{'Default FAT Size'}\n"if ($DebugPrint == 1);
#print "Size[0] is $info_output_href->{0}->{'Size (Mb)'}, Size[1] is $info_output_href->{1}->{'Size (Mb)'}\n"if ($DebugPrint == 1);
#print "ADMUX[0] is $info_output_href->{0}->{'ADMUX'}, ADMUX[1] is $info_output_href->{1}->{'ADMUX'}\n"if ($DebugPrint == 1);
#print "DRAM[0] is $info_output_href->{0}->{'DRAM'}, DRAM[1] is $info_output_href->{1}->{'DRAM'}\n"if ($DebugPrint == 1);
#print "CommSeries[0] is $info_output_href->{0}->{'Comm. Series'}, CommSeries[1] is $info_output_href->{1}->{'Comm. Series'}\n"if ($DebugPrint == 1);
#print "Bank[0] is $info_output_href->{0}->{'Bank'}, Bank[1] is $info_output_href->{1}->{'Bank'}\n"if ($DebugPrint == 1);
#print "PBPYN[0] is $info_output_href->{0}->{'PBP'}->{'Y / N'}, PBPYN[1] is $info_output_href->{1}->{'PBP'}->{'Y / N'}\n"if ($DebugPrint == 1);
#print "PBPSize[0] is $info_output_href->{0}->{'PBP'}->{'Size(W)'}, PBPSize[1] is $info_output_href->{1}->{'PBP'}->{'Size(W)'}\n"if ($DebugPrint == 1);
}
#****************************************************************************
# subroutine: get_common_MDL_Geo_info
# input: $info_list_href: input list reference of list of MDL info
# $combo_count: number of memory devices selected
# $mem_dev_type: MEMORY_DEVICE_TYPE
# $baseaddr: base address where the geometry list starts
# $endaddr: end address where the geometry list ends
# $region_info_size_href: list reference of common RegionInfo of the specified area (Size)
# $region_info_count_href: list of common RegionInfo of the specified area (Count)
# $bank_info_size_href: list of common BankInfo of the specified area (Size)
# $bank_info_count_href: list of common BankInfo of the specified area (Count)
#****************************************************************************
sub get_common_MDL_Geo_info
{
my ($info_list_href, $combo_count, $mem_dev_type, $baseaddr, $endaddr, $region_info_size_href, $region_info_count_href, $bank_info_size_href, $bank_info_count_href) = @_;
my ($prev_addr, $curr_addr, $idx);
### Get common RegionInfo
$prev_addr = $baseaddr;
$curr_addr = $baseaddr;
$idx = 0;
while ($curr_addr < $endaddr) # traverse till the endaddr
{
### Find the largest block/bank offset from the current address to the next boundary
### Stop if the end of BankInfo or RegionInfo has been reached
my $largest_offset = 0; # largest offset from curr_addr to the next block/bank boundary
my $common_size = 0; # final(common) block/bank size of this round
my $size; # current offset from curr_addr to the next block/bank boundary
my $cur_combo_idx;
for (1..$combo_count)
{
$cur_combo_idx = $_;
my $cur_block_str = $info_list_href->[$_]->{1}->{'Device Geometry'}->{'Block Info.'};
my @cur_blocks = &split_info($cur_block_str); # list of Block Info.
my @cur_entire_regions = &convert_blocks_to_regions(\@cur_blocks, $endaddr); # list of Region Info. (of the entire flash)
my (@cur_entire_regions_size, @cur_entire_regions_count);
&convert_geo_hash_from_list(\@cur_entire_regions, \@cur_entire_regions_size, \@cur_entire_regions_count);
### Get the offset to the next boundary
$size = &get_next_Geo_boundary(\@cur_entire_regions_size, \@cur_entire_regions_count, $curr_addr);
last if ($size == 0); # reach the end of RegionInfo/BankInfo
if ($size > $largest_offset)
{
$largest_offset = $size;
}
}
last if ($cur_combo_idx != $combo_count); # early break in for loop represents end of RegionInfo/BankInfo is reached
### Check whether curr_address+largest_offset is still on the boundaries of all MCPs
for (1..$combo_count)
{
$cur_combo_idx = $_;
my $cur_block_str = $info_list_href->[$_]->{1}->{'Device Geometry'}->{'Block Info.'};
my @cur_blocks = &split_info($cur_block_str); # list of Block Info.
my @cur_entire_regions = &convert_blocks_to_regions(\@cur_blocks, $endaddr); # list of Region Info. (of the entire flash)
my (@cur_entire_regions_size, @cur_entire_regions_count);
&convert_geo_hash_from_list(\@cur_entire_regions, \@cur_entire_regions_size, \@cur_entire_regions_count);
last if (&query_if_Geo_boundary(\@cur_entire_regions_size, \@cur_entire_regions_count, $curr_addr+$largest_offset) != 1);
}
# The address is not on the boundaries of all MCPs, need to go to the next address
# The next address is curr_addr + largest_offset
if ($cur_combo_idx != $combo_count)
{
$curr_addr += $largest_offset;
next;
}
### Add the address into the output RegionInfo/BankInfo
# Get the size of common block/bank size
$common_size = $curr_addr + $largest_offset - $prev_addr;
if ($prev_addr == $baseaddr) # the first entry
{
$region_info_size_href->[0] = $common_size;
$region_info_count_href->[0] = 1;
}
elsif ($common_size == $region_info_size_href->[$idx]) # the size is identical to the last bank we added --> count + 1
{
$region_info_count_href->[$idx]++;
}
else # tje soze os different from the last bank we added --> append new entry
{
$idx++;
$region_info_size_href->[$idx] = $common_size;
$region_info_count_href->[$idx] = 1;
}
### Increment the current address and then perform the loop again
$curr_addr += $largest_offset;
$prev_addr = $curr_addr;
}
print "pass block info\n";
### Get common BankInfo
$prev_addr = $baseaddr;
$curr_addr = $baseaddr;
$idx = 0;
while ($curr_addr < $endaddr) # traverse till the endaddr
{
### Find the largest block/bank offset from the current address to the next boundary
### Stop if the end of BankInfo or RegionInfo has been reached
my $largest_offset = 0; # largest offset from curr_addr to the next block/bank boundary
my $common_size = 0; # final(common) block/bank size of this round
my $size; # current offset from curr_addr to the next block/bank boundary
my $cur_combo_idx;
for (1..$combo_count)
{
$cur_combo_idx = $_;
my $cur_bank_str = $info_list_href->[$_]->{1}->{'Device Geometry'}->{'Bank Info.'};
my @cur_banks = &split_info($cur_bank_str); # list of Bank Info.
my (@cur_banks_size, @cur_banks_count);
&convert_geo_hash_from_list(\@cur_banks, \@cur_banks_size, \@cur_banks_count);
### Get the offset to the next boundary
$size = &get_next_Geo_boundary(\@cur_banks_size, \@cur_banks_count, $curr_addr);
last if ($size == 0); # reach the end of RegionInfo/BankInfo
if ($size > $largest_offset)
{
$largest_offset = $size;
}
}
last if ($cur_combo_idx != $combo_count); # early break in for loop represents end of RegionInfo/BankInfo is reached
### Check whether curr_address+largest_offset is still on the boundaries of all MCPs
for (1..$combo_count)
{
$cur_combo_idx = $_;
my $cur_bank_str = $info_list_href->[$_]->{1}->{'Device Geometry'}->{'Bank Info.'};
my @cur_banks = &split_info($cur_bank_str); # list of Bank Info.
my (@cur_banks_size, @cur_banks_count);
&convert_geo_hash_from_list(\@cur_banks, \@cur_banks_size, \@cur_banks_count);
last if (&query_if_Geo_boundary(\@cur_banks_size, \@cur_banks_count, $curr_addr+$largest_offset) != 1);
}
# The address is not on the boundaries of all MCPs, need to go to the next address
# The next address is curr_addr + largest_offset
if ($cur_combo_idx != $combo_count)
{
$curr_addr += $largest_offset;
next;
}
### Add the address into the output RegionInfo/BankInfo
# Get the size of common block/bank size
$common_size = $curr_addr + $largest_offset - $prev_addr;
if ($prev_addr == $baseaddr) # the first entry
{
$bank_info_size_href->[0] = $common_size;
$bank_info_count_href->[0] = 1;
}
elsif ($common_size == $bank_info_size_href->[$idx]) # the size is identical to the last bank we added --> count + 1
{
$bank_info_count_href->[$idx]++;
}
else # tje soze os different from the last bank we added --> append new entry
{
$idx++;
$bank_info_size_href->[$idx] = $common_size;
$bank_info_count_href->[$idx] = 1;
}
### Increment the current address and then perform the loop again
$curr_addr += $largest_offset;
$prev_addr = $curr_addr;
}
}
#****************************************************************************
# subroutine: get_next_Geo_boundary
# input: $geo_size_list_href: input list reference of geometry (Size list)
# $geo_count_list_href: input list reference of geometry (Size list)
# $addr: current address from which to query next boundary
# output: $size: size from current address to the next boundary
#****************************************************************************
sub get_next_Geo_boundary
{
my ($geo_size_list_href, $geo_count_list_href, $addr) = @_;
my $size;
### for all {Size, Count} pairs
for (0..$#$geo_size_list_href)
{
### Treat the address as a pile of blocks. Remove them region by region.
if (($geo_size_list_href->[$_]*$geo_count_list_href->[$_]) <= $addr)
{
$addr -= $geo_size_list_href->[$_]*$geo_count_list_href->[$_];
next;
}
### Blocks that cannot fit-into one region.
# 1. We have found the region that addr belongs to.
# 2. The addr is aligned, if (addr % Size[$_]) equals 0.
# 3. The offset to the next boundary is (Size[$_] - (addr % Size[$_]))
return ($geo_size_list_href->[$_] - ($addr % $geo_size_list_href->[$_]));
}
return 0;
}
#****************************************************************************
# subroutine: query_if_Geo_boundary
# input: $geo_size_list_href: input list reference of geometry (Size list)
# $geo_count_list_href: input list reference of geometry (Size list)
# $addr: address to be checked whether it is on the boundary or not
# output: $is_boundary: 1 if the queried address is on the boundary of all MCPs
#****************************************************************************
sub query_if_Geo_boundary
{
my ($geo_size_list_href, $geo_count_list_href, $addr) = @_;
my $ret;
### for all {Size, Count} pairs
for (0..$#$geo_size_list_href)
{
### Treat the address as a pile of blocks. Remove them region by region.
if (($geo_size_list_href->[$_]*$geo_count_list_href->[$_]) <= $addr)
{
$addr -= $geo_size_list_href->[$_]*$geo_count_list_href->[$_];
next;
}
### Blocks that cannot fit-into one region.
# 1. We have found the region that addr belongs to.
# 2. The addr is aligned, if (addr % Size[$_]) equals 0.
# 3. The offset to the next boundary is (Size[$_] - (addr % Size[$_]))
if (($addr % $geo_size_list_href->[$_]) != 0)
{
return 0;
}
}
return 1;
}
#****************************************************************************
# subroutine: split_info
# return: List of RegionInfo/BlockInfo/BankInfo
# input: $info: Excel value to be split
#****************************************************************************
sub split_info
{
my ($info) = @_;
my $ret_str;
my @ret_info;
if ($info eq '*')
{
push @ret_info, $info;
return @ret_info;
}
while ($info =~ /\{(0x\w+)\s*,\s*(\w+)\}/)
{
$ret_str = "{" . $1 . "," . $2 . "}";
push @ret_info, $ret_str;
$info = $';
}
return @ret_info;
}
#****************************************************************************
# subroutine: split_sfi_driving
# return: List of SFI driving
# input: $driving_str: Excel value to be split
#****************************************************************************
sub split_sfi_driving
{
my ($driving_str) = @_;
my @ret_driving;
$driving_str =~ s/\{//; # remove parentheses
$driving_str =~ s/\}//; # remove parentheses
$driving_str =~ s/\s+//g; # remove spaces
### parse the driving string
my $saved_sep = $/;
undef $/;
@ret_driving = split(/\,/, $driving_str);
$/ = $saved_sep;
return @ret_driving;
}
#****************************************************************************
# subroutine: split_sfi_command
# return: List of SFI commands
# input: $command_str: Excel value to be split
#****************************************************************************
sub split_sfi_command
{
my ($command_str) = @_;
my @ret_command;
while ($command_str =~ /(\{.+\})/)
{
my $tmp_str = $1;
$command_str = $';
$tmp_str =~ s/\{//; # remove parentheses
$tmp_str =~ s/\}//; # remove parentheses
$tmp_str =~ s/\s+//g; # remove spaces
### parse the driving string
my $saved_sep = $/;
undef $/;
my @tmp_list = split(/\,/, $tmp_str);
$/ = $saved_sep;
### for commands {SPI, 0x35}, output "SPI, 1, 0x35", where 1 is the number of commands
if ($tmp_list[0] eq 'SPI' or $tmp_list[0] eq 'QPI')
{
push @ret_command, $tmp_list[0];
push @ret_command, $#tmp_list;
for (1..$#tmp_list)
{
push @ret_command, $tmp_list[$_];
}
}
else
{
&error_handler("$MEMORY_DEVICE_LIST_XLS_E: Unknown SFI commands $command_str!", __FILE__, __LINE__);
}
}
return @ret_command;
}
#****************************************************************************
# subroutine: region_info
# return: template of part "configure flash memory for FAT"
#****************************************************************************
sub region_info
{
my ($region_size_href, $region_count_href, $naming, $newline) = @_;
my $region_info_lines;
for (0..$#$region_size_href)
{
my $tmp_size = sprintf("0x%X", $region_size_href->[$_]);
my $tmp_count = sprintf("%d", $region_count_href->[$_]);
if ($_ == $#$region_size_href)
{
$region_info_lines .= " \{$tmp_size, $tmp_count\},\n";
}
else
{
$region_info_lines .= " \{$tmp_size, $tmp_count\}, \\$newline\n";
}
}
chomp $region_info_lines;
if (!defined $naming)
{
return $region_info_lines;
}
###
my $template;
if (defined $newline)
{
$template .= <<"__TEMPLATE";
$region_info_lines
__TEMPLATE
return $template;
}
my $naming_str = sprintf("$naming\[\]");
if ($naming eq 'oriRegionInfo')
{
$template .= <<"__TEMPLATE";
FLASH_REGIONINFO_VAR_MODIFIER FlashRegionInfo $naming_str =
{
$region_info_lines
EndoriRegionInfo
};
__TEMPLATE
}
else
{
$template .= <<"__TEMPLATE";
#define $naming $region_info_lines
__TEMPLATE
}
chomp $template;
return $template;
}
#****************************************************************************
# subroutine: block_info
# return: template of part "configure flash memory for FAT"
# input: $tmp_blocks: Block Info
# $newline: whether there exists newline character and comments in the output Block Info string
#****************************************************************************
sub block_info
{
my ($block_start_href, $block_size_href, $newline) = @_;
my $block_info_lines;
for (0..$#$block_start_href)
{
my $tmp_start = sprintf("0x%X", $block_start_href->[$_]);
my $tmp_size = sprintf("0x%X", $block_size_href->[$_]);
if ($_ == $#$block_start_href)
{
$block_info_lines .= " \{$tmp_start, $tmp_size\},\n";
}
else
{
$block_info_lines .= " \{$tmp_start, $tmp_size\}, $newline\n";
}
}
chomp $block_info_lines;
###
my $template;
if (defined $newline)
{
$template .= <<"__TEMPLATE";
$block_info_lines
__TEMPLATE
}
else
{
$template .= <<"__TEMPLATE";
/*
FLASH_REGIONINFO_VAR_MODIFIER FlashBlockTBL NOTREADYYET[] =
{
$block_info_lines
EndBlockInfo
};
*/
__TEMPLATE
}
return $template;
}
#****************************************************************************
# subroutine: bank_info
# return: template of part "configure flash memory for FAT"
# input: $bank_size_href: Bank Info size
# $bank_count_href: Bank Info count
# $offset: the offset to start counting bank
# $target_size: the size of the FAT
# $newline: whether there exists newline character and comments in the output Bank Info string
#****************************************************************************
sub bank_info
{
my ($bank_size_href, $bank_count_href, $offset, $target_size, $newline) = @_;
my $template;
if (defined $newline)
{
for (0..$#$bank_size_href)
{
my $tmp_size = sprintf("0x%X", $bank_size_href->[$_]);
my $tmp_count = sprintf("%d", $bank_count_href->[$_]);
if ($_ == $#$bank_size_href)
{
$template .= " \{$tmp_size, $tmp_count\},\n";
}
else
{
$template .= " \{$tmp_size, $tmp_count\}, $newline\n";
}
}
return $template;
}
for (0..$#$bank_size_href)
{
my $tmp_size = sprintf("0x%X", $bank_size_href->[$_]);
my $tmp_count = sprintf("%d", $bank_count_href->[$_]);
my $segment = ( hex($tmp_size) * $tmp_count );
if ($offset <= 0)
# Bank already in
{
if ($target_size >= $segment)
# Bank full in-used
{
$template .= sprintf(" \{ 0x%X, %d \}, %s \\ \n", hex($tmp_size), $tmp_count);
}
elsif ($target_size > 0)
# Bank partial used
{
my $tmp = int($target_size / hex($tmp_size));;
if ( int($target_size / hex($tmp_size)) > 0 )
{
$template .= sprintf(" \{ 0x%X, %d \}, %s\\\n", hex($tmp_size), int($target_size / hex($tmp_size)) );
$target_size -= hex($tmp_size) * int($target_size / hex($tmp_size));
}
if ($target_size > 0)
{
$template .= sprintf(" \{ 0x%X, %d \}, %s\\\n", $target_size , 1 );
}
}
else
# Bank discarded
{
}
$target_size -= $segment;
}
elsif ($offset < $segment)
# Segment cross the FAT Baseaddr
{
my $c = $tmp_count;
while ($offset >= hex($tmp_size))
{
$c--;
$offset -= hex($tmp_size);
}
# Bank partial in-used
if ($offset > 0 and (hex($tmp_size) - $offset) >= $target_size)
{
$template .= sprintf(" \{ 0x%X, %d \}, %s\\\n", $target_size, 1);
$target_size -= hex($tmp_size);
$c--;
}
elsif ($offset > 0)
{
$template .= sprintf(" \{ 0x%X, %d \}, %s\\\n", (hex($tmp_size) - $offset), 1);
$target_size -= (hex($tmp_size) - $offset);
$c--;
}
# discount $offset and make $offset to negative value
$offset -= hex($tmp_size);
next if ($c == 0); # already last one bank on the FAT boundary
if ($target_size >= (hex($tmp_size) * $c))
{
$template .= sprintf(" \{ 0x%X, %d \}, %s \\\n", hex($tmp_size), $c);
$target_size -= (hex($tmp_size) * $c);
}
elsif ($target_size > 0)
{
if ( int($target_size / hex($tmp_size)) > 0 )
{
$template .= sprintf(" \{ 0x%X, %d \}, %s \\\n", hex($tmp_size), int($target_size / hex($tmp_size)) );
$target_size -= hex($1) * int($target_size / hex($tmp_size));
}
if ($target_size > 0)
{
$template .= sprintf(" \{ 0x%X, %d \}, %s \\\n", $target_size , 1 );
}
}
}
# No output and down counting to reach FAT Baseaddr
else
{
$offset -= $segment;
}
}
$template = " {x , x},\n" if not defined $template;
chomp($template);
return $template;
}
#****************************************************************************
# subroutine: convert_blocks_to_regions
# return: RegionInfo of the entire flash, in {size, count} format instead of {start, size} format
# input: $tmp_blocks: input list of blocks
# output: @regions: output list of regions
#****************************************************************************
sub convert_blocks_to_regions
{
my ($tmp_blocks, $endaddr) = @_;
my @regions;
my ($cur_reg_start, $cur_block_size, $prev_reg_start, $prev_block_size);
for (0..$#$tmp_blocks)
{
if ($tmp_blocks->[$_] =~ /\{(\w+)\s*,\s*(\w+)\}/) # match {0x20000, 7}
{
$cur_reg_start = hex($1);
$cur_block_size = hex($2);
}
if ($_ > 0)
{
if ($tmp_blocks->[$_-1] =~ /\{(\w+)\s*,\s*(\w+)\}/) # match {0x20000, 7}
{
$prev_reg_start = hex($1);
$prev_block_size = hex($2);
}
my $tmp_region_info_line = sprintf("\{0x%X,%d\}", $prev_block_size, ($cur_reg_start-$prev_reg_start)/$prev_block_size);
push @regions, $tmp_region_info_line;
}
}
my $tmp_region_info_line;
if ($#$tmp_blocks >= 0)
{
$tmp_region_info_line = sprintf("\{0x%X,%d\}", $cur_block_size, ($endaddr-$cur_reg_start)/$cur_block_size);
}
push @regions, $tmp_region_info_line;
return @regions;
}
#****************************************************************************
# subroutine: convert_regions_to_blocks
# return: BlockInfo of the input RegionInfo, in {start, size} format instead of {size, count} format
# input: $regions_start: start address of region info
# $tmp_regions_size_list: input list of regions size
# $tmp_regions_count_list: input list of regions count
# output: $output_blocks_start_list: output list of blocks start
# $output_blocks_size_list: output list of blocks size
#****************************************************************************
sub convert_regions_to_blocks
{
my ($regions_start, $tmp_regions_size_list, $tmp_regions_count_list, $output_blocks_start_list, $output_blocks_size_list) = @_;
my @ret_blocks;
my $idx = 0;
$output_blocks_start_list->[0] = $regions_start;
for (0..$#$tmp_regions_size_list)
{
$idx = $_;
# the block size is identical to the region block size
$output_blocks_size_list->[$_] = $tmp_regions_size_list->[$_];
# the offset equals to the accumulated size of former regions
if ($_ != $#$tmp_regions_size_list)
{
$output_blocks_start_list->[$_+1] = $output_blocks_start_list->[$_] + ($tmp_regions_size_list->[$_]*$tmp_regions_count_list->[$_]);
}
}
}
#****************************************************************************
# subroutine: convert_geo_hash_from_list
# return: lists of flash geometry in {size, count} format
# input: $list_href: input list of blocks/banks
# $geo_size_list_output_href: Size part of flash geometry pairs
# $geo_count_list_output_href: Count part of flash geometry pairs
#****************************************************************************
sub convert_geo_hash_from_list
{
my ($list_href, $geo_size_list_output_href, $geo_count_list_output_href) = @_;
for (0..$#$list_href)
{
if ($list_href->[$_] =~ /\{(\w+)\s*,\s*(\w+)\}/) # match {0x20000, 7}
{
$geo_size_list_output_href->[$_] = hex($1);
$geo_count_list_output_href->[$_] = $2;
}
}
}
#****************************************************************************
# subroutine: SCHEME Configure Routines :: Query Flash Block Size
# input: Flash Offset Address
# Output: Flash block size
#****************************************************************************
sub config_query_flash_block_sz
{
my ($offset, $COMM_MDL_INFO_LOCAL, $ENTIRE_BLOCK_INFO_START_LIST_LOCAL, $ENTIRE_BLOCK_INFO_SIZE_LIST_LOCAL) = @_;
&error_handler("tools\\emigenflash.pl: Query Block Size at $offset larger than available size!", __FILE__, __LINE__) if ($offset > $COMM_MDL_INFO_LOCAL->{0}->{'Flash Size'});
for (0..$#$ENTIRE_BLOCK_INFO_START_LIST_LOCAL)
{
return ($ENTIRE_BLOCK_INFO_SIZE_LIST_LOCAL->[$#$ENTIRE_BLOCK_INFO_START_LIST_LOCAL-$_]) if ($offset >= $ENTIRE_BLOCK_INFO_START_LIST_LOCAL->[$#$ENTIRE_BLOCK_INFO_START_LIST_LOCAL-$_]);
}
&error_handler("tools\\emigenflash.pl: Unreachable!", __FILE__, __LINE__);
}
#****************************************************************************
# subroutine: flash_opt_h_file_body
# return: flash opt header file
#****************************************************************************
sub flash_opt_gen_h_file_body
{
my ($MAKEFILE_OPTIONS_LOCAL, $CUSTOM_MEM_DEV_OPTIONS_LOCAL, $MDL_INFO_LIST_LOCAL, $COMM_MDL_INFO_LOCAL, $CUSTOM_MEMORY_DEVICE_HDR_LOCAL, $THEMF_LOCAL, $entire_bank_info_size_list_LOCAL, $entire_bank_info_count_list_LOCAL, $entire_block_info_start_list_LOCAL, $entire_block_info_size_list_LOCAL, $entire_region_info_size_list_LOCAL, $entire_region_info_count_list_LOCAL) = @_;
my $current_nor_opt;
##if (($CUSTOM_MEM_DEV_OPTIONS_LOCAL->{MEMORY_DEVICE_TYPE} ne 'LPSDRAM') and ($CUSTOM_MEM_DEV_OPTIONS_LOCAL->{MEMORY_DEVICE_TYPE} ne 'LPDDR') and ($CUSTOM_MEM_DEV_OPTIONS_LOCAL->{MEMORY_DEVICE_TYPE} ne 'LPDDR2'))
#if ($CUSTOM_MEM_DEV_OPTIONS_LOCAL->{MEMORY_DEVICE_TYPE} eq 'LPDDR2')
#if($MAKEFILE_OPTIONS_LOCAL->{'platform'} eq 'MT6291') # FIXME
{
if ($COMM_MDL_INFO_LOCAL->{0}->{'PBP'}->{'Y / N'} =~ /Y/i)
{
$current_nor_opt .= "#define __PAGE_BUFFER_PROGRAM__\n";
}
#if ($CUSTOM_MEM_DEV_OPTIONS_LOCAL->{MEMORY_DEVICE_TYPE} eq 'SERIAL_FLASH')
if ($MAKEFILE_OPTIONS_LOCAL->{'serial_flash_support'} eq 'TRUE')
{
$current_nor_opt .= "#define __SERIAL_FLASH__\n";
}
### Define flash types
my $cnt_sibley = 0;
for (1..$CUSTOM_MEM_DEV_OPTIONS_LOCAL->{COMBO_MEM_ENTRY_COUNT})
{
if ($MDL_INFO_LIST_LOCAL->[$_]->{1}->{'Comm. Series'} =~ /(\w*)/i)
{
my $tmp_series = $1;
if ($current_nor_opt =~ /$tmp_series/)
{
}
else
{
#if ($CUSTOM_MEM_DEV_OPTIONS_LOCAL->{MEMORY_DEVICE_TYPE} eq 'SERIAL_FLASH')
if ($MAKEFILE_OPTIONS_LOCAL->{'serial_flash_support'} eq 'TRUE')
{
$current_nor_opt .= "#define SF_DAL_" . $tmp_series . "\n";
}
else
{
$current_nor_opt .= "#define NOR_FLASH_TYPE_" . $tmp_series . "\n";
if ($tmp_series eq 'INTEL_SIBLEY')
{
$cnt_sibley++;
}
}
}
}
}
if ($MAKEFILE_OPTIONS_LOCAL->{'serial_flash_support'} eq 'TRUE')
{
if ($cnt_sibley != $CUSTOM_MEM_DEV_OPTIONS_LOCAL->{COMBO_MEM_ENTRY_COUNT})
{
$current_nor_opt .= "#define __NON_INTEL_SIBLEY__\n";
}
$current_nor_opt .= "\n";
$current_nor_opt .= "\n";
if ($COMM_MDL_INFO_LOCAL->{0}->{'Bank'} =~ /M/i)
{
$current_nor_opt .= "#define __MULTI_BANK_NOR_DEVICE__\n";
}
elsif ($COMM_MDL_INFO_LOCAL->{0}->{'Bank'} =~ /S/i)
{
$current_nor_opt .= "#define __SINGLE_BANK_NOR_DEVICE__\n";
}
}
}
if (($MAKEFILE_OPTIONS_LOCAL->{'serial_flash_support'} eq 'FALSE') and ($MAKEFILE_OPTIONS_LOCAL->{'nand_support'} eq 'FALSE'))
{
$current_nor_opt .= "#define __SMART_PHONE_PLATFORM__\n";##for Not Run CkSysDrv.pl, will check FAT valid, but no flash now
}
###
my $pbp_size = ($COMM_MDL_INFO_LOCAL->{0}->{'PBP'}->{'Y / N'} =~ /Y/i)
? $COMM_MDL_INFO_LOCAL->{0}->{'PBP'}->{'Size(W)'}
: 0;
###
my $nor_block_size_str = sprintf("0x%X", $nor_block_size);
###
my $nand_total_size = 0;
my $nand_block_size = 0;
#if($MAKEFILE_OPTIONS_LOCAL->{'platform'} eq 'MT6291') # FIXME
{
if ($MAKEFILE_OPTIONS_LOCAL->{'nand_support'} eq 'TRUE')
{
$nand_total_size = ($COMM_MDL_INFO_LOCAL->{0}->{'Flash Size'} == 0xffffffff)
? 0
: ($COMM_MDL_INFO_LOCAL->{0}->{'Flash Size'} / (1024*1024));
$nand_block_size = $COMM_MDL_INFO_LOCAL->{0}->{'NAND Block Size(KB)'};
}
}
my $base_addr_string = sprintf("0x%08X", $COMM_MDL_INFO_LOCAL->{0}->{'Default FAT Base'});
my $fat_space_string = sprintf("0x%08X", $COMM_MDL_INFO_LOCAL->{0}->{'Default FAT Size'});
###
my $fota_check;
if ($MAKEFILE_OPTIONS_LOCAL->{'fota_enable'} eq 'FOTA_DM')
{
$fota_check = <<"__TEMPLATE";
#ifndef __FOTA_DM__
#error "$THEMF: Error! FOTA_ENABLE should be set to FOTA_DM!"
#endif /* __FOTA_DM__ */
__TEMPLATE
}
else
{
$fota_check = <<"__TEMPLATE";
#ifdef __FOTA_DM__
#error "$THEMF_LOCAL: Error! FOTA_ENABLE should not be defined!"
#endif /* __FOTA_DM__ */
__TEMPLATE
}
###
my ($fota_nor_region_def, $fota_nor_block_def, $fota_nor_bank_def);
if ($CUSTOM_MEM_DEV_OPTIONS_LOCAL->{MEMORY_DEVICE_TYPE} eq 'NOR_RAM_MCP')
{
$fota_nor_region_def = &region_info($entire_region_info_size_list_LOCAL, $entire_region_info_count_list_LOCAL, undef, '\\');
$fota_nor_block_def = &block_info($entire_block_info_start_list_LOCAL, $entire_block_info_size_list_LOCAL, '\\');
$fota_nor_bank_def = &bank_info($entire_bank_info_size_list_LOCAL, $entire_bank_info_count_list_LOCAL, 0, $COMM_MDL_INFO_LOCAL->{0}->{'Flash Size'}, '\\');
}
###
my $template = <<"__TEMPLATE";
/*
*******************************************************************************
PART 1:
FLASH CONFIG Options Definition here
*******************************************************************************
*/
$current_nor_opt
/*
*******************************************************************************
PART 2:
FLASH FDM FEATURE CONFIG PARAMETERS translated from Manual custom_Memorydevice.h
*******************************************************************************
*/
#define BUFFER_PROGRAM_ITERATION_LENGTH ($pbp_size)
/*
*******************************************************************************
PART 3:
FLASH GEOMETRY translated from MEMORY DEVICE DATABASE
*******************************************************************************
*/
/* NOR flash maximum block size (Byte) in file system region */
#define NOR_BLOCK_SIZE $nor_block_size_str
/* NAND flash total size (MB). PLEASE configure it as 0 if it is unknown. */
#define NAND_TOTAL_SIZE $nand_total_size
/* NAND flash block size (KB). PLEASE configure it as 0 if it is unknown. */
#define NAND_BLOCK_SIZE $nand_block_size
/*
*******************************************************************************
PART 4:
FLASH FAT CONFIG translated from Manual custom_Memorydevice.h
*******************************************************************************
*/
#define NOR_FLASH_BASE_ADDRESS_DEFAULT ($base_addr_string)
#define NOR_ALLOCATED_FAT_SPACE_DEFAULT ($fat_space_string)
#define FOTA_DM_FS_OFFSET $nfb_fat_size_offset
#define FOTA_DM_FS_SECTOR_OFFSET $nfb_partition_sector_offset
/*
*******************************************************************************
PART 6:
FOTA UPDATABLE FLASH AREA
*******************************************************************************
*/
$fota_check
#define CONFIG_FOTA_NOR_REGION_DEF \\
$fota_nor_region_def
#define CONFIG_FOTA_NOR_BLOCK_DEF \\
$fota_nor_block_def
#define CONFIG_FOTA_NOR_BANK_DEF \\
$fota_nor_bank_def
__TEMPLATE
return $template;
}
#****************************************************************************
# subroutine: combo_flash_config_h_file_body
# return:
#****************************************************************************
sub combo_flash_config_h_file_body
{
my ($MAKEFILE_OPTIONS_LOCAL, $CUSTOM_MEM_DEV_OPTIONS_LOCAL, $MDL_INFO_LIST_LOCAL, $COMM_MDL_INFO_LOCAL) = @_;
### There should be totally 8 BlockInfo and BankInfo
my $MAX_BLOCK_INFO = 8;
my $MAX_BANK_INFO = 8;
### Fill-in the information of each memory
my $combo_mem_info_struct;
for (1..$CUSTOM_MEM_DEV_OPTIONS_LOCAL->{COMBO_MEM_ENTRY_COUNT})
{
my $comma;
my $cmem_fdm_type;
my $pbp_size;
my $cur_block_str;
my @cur_blocks;
my $cur_bank_str;
my @cur_banks;
my $cur_uni_block_str;
my $cur_uni_block;
my ($block_info_template, $bank_info_template);
#if($MAKEFILE_OPTIONS_LOCAL->{'platform'} eq 'MT6291') # FIXME
{
if ($CUSTOM_MEM_DEV_OPTIONS_LOCAL->{MEMORY_DEVICE_TYPE} eq 'NAND_RAM_MCP')##MT6291 MCP
{
#todo
}
else ##MT6291 Discrete DRAM/FLASH
{
if ($MAKEFILE_OPTIONS_LOCAL->{'serial_flash_support'} eq 'TRUE')
{
#print "Serial Flash Support!\n"if ($DebugPrint == 1);
$comma = ($_ < $CUSTOM_MEM_DEV_OPTIONS_LOCAL->{COMBO_MEM_ENTRY_COUNT}) ? "," : "";
$cmem_fdm_type = 'CMEM_FDM_NOR_DEFAULT';
$pbp_size = 0;
if ($MDL_INFO_LIST_LOCAL->[$_]->{1}->{'PBP'}->{'Y / N'} =~ /Y/i)
{
$pbp_size = $MDL_INFO_LIST_LOCAL->[$_]->{1}->{'PBP'}->{'Size (Byte)'};
}
$cur_block_str = $MDL_INFO_LIST_LOCAL->[$_]->{1}->{'Device Geometry'}->{'Block Info.'};
@cur_blocks = &split_info($cur_block_str); # list of Block Info.
$cur_bank_str = $MDL_INFO_LIST_LOCAL->[$_]->{1}->{'Device Geometry'}->{'Bank Info.'};
@cur_banks = &split_info($cur_bank_str); # list of Bank Info.
$cur_uni_block_str = $MDL_INFO_LIST_LOCAL->[$_]->{1}->{'Device Geometry'}->{'Uniform Block (KB)'};
$cur_uni_block = &split_info_for_UB($cur_uni_block_str);
}
else #if ($MAKEFILE_OPTIONS_LOCAL->{'nand_support'} eq 'TRUE'), No flash or NAND gen dummy file
{
#print "NAND Flash Gen Dummy!\n"if ($DebugPrint == 1);
#$comma = 0;
$comma = ($_ < $CUSTOM_MEM_DEV_OPTIONS_LOCAL->{COMBO_MEM_ENTRY_COUNT}) ? "," : "";
$cmem_fdm_type = '';
$pbp_size = 0;
$cur_block_str = '';
@cur_blocks = &split_info($cur_block_str); # list of Block Info.
$cur_bank_str = '';
@cur_banks = &split_info($cur_bank_str); # list of Bank Info.
$cur_uni_block_str = '';
$cur_uni_block = &split_info_for_UB($cur_uni_block_str);
}
}
}
for (0..($MAX_BLOCK_INFO-1))
{
$block_info_template .= " ";
if (defined $cur_blocks[$_])
{
$block_info_template .= $cur_blocks[$_];
}
else
{
$block_info_template .= "EndRegionInfo";
}
if ($_ != ($MAX_BLOCK_INFO-1))
{
$block_info_template .= ",\n";
}
}
for (0..($MAX_BANK_INFO-1))
{
$bank_info_template .= " ";
if (defined $cur_banks[$_])
{
$bank_info_template .= $cur_banks[$_];
}
else
{
$bank_info_template .= "EndBankInfo";
}
if ($_ != ($MAX_BANK_INFO-1))
{
$bank_info_template .= ",\n";
}
}
$combo_mem_info_struct .= <<"__TEMPLATE";
{ // $MDL_INFO_LIST_LOCAL->[$_]->{1}->{'Part Number'}
$cmem_fdm_type,
$pbp_size, // Page Buffer Program Size
$cur_uni_block, // Unifom Blocks
{ // BlockInfo Start
$block_info_template
}, // BlockInfo End
{ // BankInfo Start
$bank_info_template
} // BankInfo End
}$comma
__TEMPLATE
}
###
my $template = <<"__TEMPLATE";
#define CMEM_MAX_BLOCKS $cmem_max_blocks
#define CMEM_MAX_SECTORS $cmem_max_sectors
COMBO_MEM_TYPE_MODIFIER COMBO_MEM_TYPE_NAME COMBO_MEM_INST_NAME = {
COMBO_MEM_STRUCT_HEAD
$combo_mem_info_struct
COMBO_MEM_STRUCT_FOOT
};
__TEMPLATE
}
#****************************************************************************
# subroutine: combo_nfi_config_h_file_body
# return:
#****************************************************************************
sub combo_nfi_config_h_file_body
{
my ($MAKEFILE_OPTIONS_LOCAL, $CUSTOM_MEM_DEV_OPTIONS_LOCAL, $MDL_INFO_LIST_LOCAL, $COMM_MDL_INFO_LOCAL) = @_;
### Fill-in the information of each memory
my $combo_nfi_info_struct;
### There should be totally 8 Flash ID entries
my $MAX_FLASH_ID = 8;
for (1..$CUSTOM_MEM_DEV_OPTIONS_LOCAL->{COMBO_MEM_ENTRY_COUNT})
{
$combo_nfi_info_struct .= "/* $_ */\n";
my $vendor = uc($MDL_INFO_LIST_LOCAL->[$_]->{1}->{'Vendor'});
#$combo_nfi_info_struct .= " {\n" ." {" . "\"$vendor $MDL_INFO_LIST_LOCAL->[$_]->{1}->{'Part Number'}\"" ."}, // DevName_str (64 bytes)\n";#part time number
$combo_nfi_info_struct .= " {\n" ." 0x00000301,\n" ." {" . "\"$vendor $MDL_INFO_LIST_LOCAL->[$_]->{1}->{'Part Number'}\"" ."}, // NFI_Device_Name (64 bytes)\n";#part time number
###get flash id string
my $flash_id_str = $MDL_INFO_LIST_LOCAL->[$_]->{1}->{'Flash ID'};
$flash_id_str =~ s/\{//; # remove parentheses
$flash_id_str =~ s/\}//; # remove parentheses
$flash_id_str =~ s/\s+//g; # remove spaces
### parse the flash id string
my $saved_sep = $/;
undef $/;
my @flash_id = split(/\,/, $flash_id_str);
$/ = $saved_sep;
my $flash_id_cnt = $#flash_id + 1;
my $flash_id_template;
my $flash_id_mask;
#$flash_id_template .= sprintf("0x%02X", hex($flash_id[$_])) .",";
#$flash_id_mask .= "0xFF" .",";
for (0..($MAX_FLASH_ID-1))
{
if (defined $flash_id[$_])
{
$flash_id_template .= sprintf("0x%02X", hex($flash_id[$_]));
$flash_id_mask .= "0xFF";
}
else
{
$flash_id_template .= "0xFF";
$flash_id_mask .= "0x00";
}
if ($_ != ($MAX_FLASH_ID-1))
{
$flash_id_template .= ", ";
$flash_id_mask .= ", ";
}
}
$combo_nfi_info_struct .= " {" .$flash_id_template ."}, // ID_info\n";
$combo_nfi_info_struct .= " {" .$flash_id_mask ."}, // ID_valid_mask\n";
#$combo_nfi_info_struct .= " " .$MDL_INFO_LIST_LOCAL->[$_]->{1}->{'NAND Size(MB)'} .", // deviceSize (MByte)\n";
$combo_nfi_info_struct .= " " .$MDL_INFO_LIST_LOCAL->[$_]->{1}->{'NAND Size(MB)'} .", // NFI_Device_Size (MByte)\n";
#$combo_nfi_info_struct .= " " .sprintf("0x%05x", $MDL_INFO_LIST_LOCAL->[$_]->{1}->{'NAND Block Size(KB)'}*1024) .", // blockSize (byte)\n";
$combo_nfi_info_struct .= " " .sprintf("0x%05x", $MDL_INFO_LIST_LOCAL->[$_]->{1}->{'NAND Block Size(KB)'}*1024) .", // NFI_Block_Size (byte)\n";
###Parsing special info
my $nand_flash_key_ref = $MDL_INFO_LIST_LOCAL->[$_]->{1}->{$MAKEFILE_OPTIONS_LOCAL->{'platform'}};
foreach my $nand_flash_key (sort keys %{$nand_flash_key_ref})
{
#print "1-1 $nand_flash_key\n"if ($DebugPrint == 1);
if ($nand_flash_key =~ /(\d+)MHz NFIC Config/)
{
my $nand_flash_cfg = $nand_flash_key;
foreach my $nand_flash_key (sort keys %{$nand_flash_key_ref->{$nand_flash_cfg}})
{
my $val = $nand_flash_key_ref->{$nand_flash_cfg}->{$nand_flash_key};
if (($val ne 'x') && ($val ne 'X') && ($val ne ''))
{
$combo_nfi_info_struct .=" " .$val .", // $nand_flash_key" . "\n";
}
}
}
else
{
my $val = $nand_flash_key_ref->{$nand_flash_key};
#print "1-2 $val\n"if ($DebugPrint == 1);
if (($val ne 'x') && ($val ne 'X') && ($val ne ''))
{
$combo_nfi_info_struct .= " " .$val .", // $nand_flash_key" . "\n";
}
}
}
if($_ != $CUSTOM_MEM_DEV_OPTIONS_LOCAL->{COMBO_MEM_ENTRY_COUNT})
{
$combo_nfi_info_struct .= " },\n";
}
else
{
$combo_nfi_info_struct .= " }\n";
}
__TEMPLATE
}
###
my $template = <<"__TEMPLATE";
#define COMBO_NAND_FLASH_NUM $CUSTOM_MEM_DEV_OPTIONS_LOCAL->{COMBO_MEM_ENTRY_COUNT}
const combo_nand_flash_list_v01 COMBO_NAND_Table[] =
{
$combo_nfi_info_struct
};
__TEMPLATE
return $template;
}
#****************************************************************************
# subroutine: combo_flash_id_h_file_body
# return:
#****************************************************************************
sub combo_flash_id_h_file_body
{
my ($MAKEFILE_OPTIONS_LOCAL, $CUSTOM_MEM_DEV_OPTIONS_LOCAL, $MDL_INFO_LIST_LOCAL, $COMM_MDL_INFO_LOCAL) = @_;
### There should be totally 8 Flash ID entries
my $MAX_FLASH_ID = 8;
### Fill-in the information of each memory
my $combo_mem_info_struct;
for (1..$CUSTOM_MEM_DEV_OPTIONS_LOCAL->{COMBO_MEM_ENTRY_COUNT})
{
my $comma = ($_ < $CUSTOM_MEM_DEV_OPTIONS_LOCAL->{COMBO_MEM_ENTRY_COUNT}) ? "," : "";
my $cmem_type;
if ($MAKEFILE_OPTIONS_LOCAL->{'nand_support'} eq 'TRUE')
{
$cmem_type = "CMEM_TYPE_NAND";
}
elsif ($MAKEFILE_OPTIONS_LOCAL->{'serial_flash_support'} eq 'TRUE')
{
$cmem_type = "CMEM_TYPE_SERIAL_NOR_FLASH";
}
else
{
print "No flash support!\n"if ($DebugPrint == 1);
}
###get nand page size
my $nand_page_size = $MDL_INFO_LIST_LOCAL->[$_]->{1}->{'NAND Page size(B)'};
my $nand_block_size = $MDL_INFO_LIST_LOCAL->[$_]->{1}->{'NAND Block Size(KB)'};
$nand_page_size = $nand_page_size . "," . $nand_block_size;
###get flash id string
my $flash_id_str = $MDL_INFO_LIST_LOCAL->[$_]->{1}->{'Flash ID'};
$flash_id_str =~ s/\{//; # remove parentheses
$flash_id_str =~ s/\}//; # remove parentheses
$flash_id_str =~ s/\s+//g; # remove spaces
### parse the flash id string
my $saved_sep = $/;
undef $/;
my @flash_id = split(/\,/, $flash_id_str);
$/ = $saved_sep;
my $flash_id_cnt = $#flash_id + 1;
my $flash_id_template;
for (0..($MAX_FLASH_ID-1))
{
if (defined $flash_id[$_])
{
##$flash_id_template .= $flash_id[$_];
if ($MAKEFILE_OPTIONS_LOCAL->{'nand_support'} eq 'TRUE')
{
$flash_id_template .= sprintf("0x%04X", hex($flash_id[$_]));
#print "$_: $flash_id_template\n"if ($DebugPrint == 1);
}
elsif($MAKEFILE_OPTIONS_LOCAL->{'serial_flash_support'} eq 'TRUE')
{
$flash_id_template .= sprintf("0x%02X", hex($flash_id[$_]));
}
}
else
{
if ($MAKEFILE_OPTIONS_LOCAL->{'nand_support'} eq 'TRUE')
{
$flash_id_template .= "0x0000";
}
elsif($MAKEFILE_OPTIONS_LOCAL->{'serial_flash_support'} eq 'TRUE')
{
$flash_id_template .= "0x00";
}
}
if ($_ != ($MAX_FLASH_ID-1))
{
$flash_id_template .= ", ";
}
}
$combo_mem_info_struct .= <<"__TEMPLATE";
{ // $MDL_INFO_LIST_LOCAL->[$_]->{1}->{'Part Number'}
$cmem_type,
$flash_id_cnt, // Valid ID length
{$flash_id_template} // Flash ID
}$comma
__TEMPLATE
}
###
my $template = <<"__TEMPLATE";
COMBO_MEM_TYPE_MODIFIER COMBO_MEM_TYPE_NAME COMBO_MEM_INST_NAME = {
COMBO_MEM_STRUCT_HEAD
$combo_mem_info_struct
COMBO_MEM_STRUCT_FOOT
};
__TEMPLATE
}
#****************************************************************************
# subroutine: custom_flash_c_file_body
# return:
#****************************************************************************
sub custom_flash_h_file_body
{
my ($MAKEFILE_OPTIONS_LOCAL, $CUSTOM_MEM_DEV_OPTIONS_LOCAL, $MDL_INFO_LIST_LOCAL, $COMM_MDL_INFO_LOCAL, $MCP_LIST_LOCAL, $NOR_FLASH_BASE_ADDRESS_VAL_LOCAL, $NOR_ALLOCATED_FAT_SPACE_VAL_LOCAL,$LPSDRAM_CHIP_SELECT_LOCAL, $CUSTOM_MEMORY_DEVICE_HDR_LOCAL, $nor_size_Mb_LOCAL, $entire_bank_info_size_list_LOCAL, $entire_bank_info_count_list_LOCAL, $entire_block_info_start_list_LOCAL, $entire_block_info_size_list_LOCAL, $fs_region_info_size_list_LOCAL, $fs_region_info_count_list_LOCAL, $entire_region_info_size_list_LOCAL, $entire_region_info_count_list_LOCAL) = @_;
my $cs1_base_address = 0;
my $flash_limit = 0;
my $flash_size = 0;
#if($MAKEFILE_OPTIONS_LOCAL->{'platform'} eq 'MT6291') # FIXME
{
my $SPI_Base = 0xA0000000;
$cs1_base_address = sprintf("0x%08X", $SPI_Base);#MT6291 Flash Memory Base Address
$flash_limit = sprintf("0x%08X", $COMM_MDL_INFO_LOCAL->{0}->{'Flash Size'});
$flash_size = sprintf("0x%08X", $COMM_MDL_INFO_LOCAL->{0}->{'Flash Size'});
#print "MT6291: $cs1_base_address, $flash_limit, $flash_size\n"if ($DebugPrint == 1);
if($MAKEFILE_OPTIONS_LOCAL->{'nand_support'} eq 'TRUE')
{
##MT6291 Work aroud for SDS, when in HOSTED/ROUTER Project, NOR_FLASH_SIZE is MD End(96MB), other Projects is Flash Size
if((($MAKEFILE_OPTIONS_LOCAL->{'smart_phone_core'} eq 'ANDROID_MODEM') and ($MAKEFILE_OPTIONS_LOCAL->{'ccci_fs_support'} eq 'FALSE')) or (($MAKEFILE_OPTIONS_LOCAL->{'modem_card'} eq 'FULL') and ($MAKEFILE_OPTIONS_LOCAL->{'smart_phone_core'} eq 'MODEM_HOST')))
#if($MAKEFILE_OPTIONS_LOCAL->{'modem_card'} eq 'FULL')
{
my $MDFlashEnd = 96*1024*1024;
$flash_size = sprintf("0x%08X", $MDFlashEnd);
}
}
}
###
my $pbp_size = ($COMM_MDL_INFO_LOCAL->{0}->{'PBP'}->{'Y / N'} =~ /Y/i)
? $COMM_MDL_INFO_LOCAL->{0}->{'PBP'}->{'Size(W)'}
: 0;
###
my $bank_info_string = &bank_info( $entire_bank_info_size_list_LOCAL, $entire_bank_info_count_list_LOCAL, $NOR_FLASH_BASE_ADDRESS_VAL_LOCAL, $NOR_ALLOCATED_FAT_SPACE_VAL_LOCAL );
###
my $sub_content_block1 = &region_info($fs_region_info_size_list_LOCAL, $fs_region_info_count_list_LOCAL, 'REGION_INFO_LAYOUT');
my $sub_content_block2 = &block_info($entire_block_info_start_list_LOCAL, $entire_block_info_size_list_LOCAL);
my $sub_content_block3;
my $sub_content_block4;
#if($MAKEFILE_OPTIONS_LOCAL->{'platform'} eq 'MT6291') # FIXME
{
my $ori_bank_info = &bank_info($entire_bank_info_size_list_LOCAL, $entire_bank_info_count_list_LOCAL, 0, $COMM_MDL_INFO_LOCAL->{0}->{'Flash Size'});
### ? what is the purpose?
$sub_content_block3 = &region_info($fs_region_info_size_list_LOCAL, $fs_region_info_count_list_LOCAL, 'oriRegionInfo');
$sub_content_block4 .= <<"__TEMPLATE";
static NORBankInfo oriBankInfo[] =
{
$ori_bank_info
EndBankInfo
};
__TEMPLATE
chomp $sub_content_block4;
}
###
my $region_info_disk0 = &region_info($fs_region_info_size_list_LOCAL, $fs_region_info_count_list_LOCAL, 'DISK0_REGION_INFO_LAYOUT');
my $region_info_disk1 = &region_info($fs_region_info_size_list_LOCAL, $fs_region_info_count_list_LOCAL, 'DISK1_REGION_INFO_LAYOUT');
my $region_info_entire = &region_info($entire_region_info_size_list_LOCAL, $entire_region_info_count_list_LOCAL, 'ENTIRE_DISK_REGION_INFO_LAYOUT');
###
my $template1;
$template1 .= <<"__TEMPLATE__";
/*******************************************************************************
NOTICE: Fill the flash region information table, a region is the memory space
that contains continuous sectors of equal size. Each region element
in the table is the format as below:
{S_sector, N_sector},
S_sector: the size of sector in the region
N_sector: the number of sectors in the region
*******************************************************************************/
$sub_content_block1
$region_info_disk0
$region_info_disk1
$region_info_entire
/*******************************************************************************
NOTICE. Modify the value of TOTAL_BLOCKS, which is the sum of the number of
sectors in all regions.
Note : The Maximum value of TOTAL_BLOCKS is (127).
*******************************************************************************/
#define TOTAL_BLOCKS $cmem_max_blocks
/*******************************************************************************
NOTICE. Modify the value of page buffer size in WORD for page buffer program
*******************************************************************************/
//kal_uint32 PAGE_BUFFER_SIZE = $pbp_size;
#define BANK_INFO_LAYOUT $bank_info_string
/*******************************************************************************
NOTICE. NOR FLASH BLOCKS SIZE LOOKUP TABLE
Each entry element
{Offset, Block_Size},
Offset: the offset address
Block_Size: the size of block
*******************************************************************************/
$sub_content_block2
__TEMPLATE__
###
my $flash_id_str;
#if($MAKEFILE_OPTIONS_LOCAL->{'platform'} eq 'MT6291') # FIXME
{
#print "Flash ID: $MDL_INFO_LIST_LOCAL->[1]->{1}->{'Flash ID'}!\n"if ($DebugPrint == 1);
$flash_id_str .= <<"__TEMPLATE__";
const kal_char FLASH_ID[] = "$MDL_INFO_LIST_LOCAL->[1]->{1}->{'Flash ID'}";
__TEMPLATE__
}
chomp $flash_id_str;
###
my ($cs0_info, $cs1_info);
my ($pn0_str, $pn1_str);
if ((!defined $MAKEFILE_OPTIONS_LOCAL->{'combo_memory_support'}) or ($MAKEFILE_OPTIONS_LOCAL->{'combo_memory_support'} eq 'FALSE'))
{
if (defined $MCP_LIST_LOCAL->[1]->{0})
{
$cs0_info .= <<"__TEMPLATE__";
* CS0_PART_NUMBER: $MCP_LIST_LOCAL->[1]->{0}
__TEMPLATE__
chomp $cs0_info;
$pn0_str .= <<"__TEMPLATE__";
const kal_char PART_NUMBER_0[] = "$MCP_LIST_LOCAL->[1]->{0}";
__TEMPLATE__
chomp $pn0_str;
}
if (defined $MCP_LIST_LOCAL->[1]->{1})
{
$cs1_info .= <<"__TEMPLATE__";
* CS1_PART_NUMBER: $MCP_LIST_LOCAL->[1]->{1}
__TEMPLATE__
chomp $cs1_info;
$pn1_str .= <<"__TEMPLATE__";
const kal_char PART_NUMBER_1[] = "$MCP_LIST_LOCAL->[1]->{1}";
__TEMPLATE__
chomp $pn1_str;
}
}
###
my $flash_density;
if ($MAKEFILE_OPTIONS_LOCAL->{'serial_flash_support'} eq 'TRUE')
{
$flash_density .= <<"__TEMPLATE__";
* NOR_FLASH_DENSITY: $flash_limit
* NOR_FLASH_SIZE(Mb): $nor_size_Mb_LOCAL
__TEMPLATE__
chomp $flash_density;
}
###
my $template = <<"__TEMPLATE";
#define NOR_FLASH_BASE_ADDR $cs1_base_address
/*
#ifdef REMAPPING
#define NOR_FLASH_BASE_ADDR $cs1_base_address
#define RAM_BASE_ADDR 0x00000000
#else
#define NOR_FLASH_BASE_ADDR 0x00000000
#define RAM_BASE_ADDR $cs1_base_address
#endif
*/
/*
****************************************************************************
PART 2:
Essential Information of NOR Flash Geometry Layout Information
****************************************************************************
*/
$template1
#define NOR_FLASH_SIZE $flash_size
$flash_id_str
/****************************************************
* This part is for auto-gen validity CHECK *
* Don't modify any content in this comment section *
$cs0_info
$cs1_info
$flash_density
$sub_content_block3
$sub_content_block4
****************************************************/
__TEMPLATE
}
#****************************************************************************
# subroutine: custom_flash_norfdm5_c_file_body
# return:
#****************************************************************************
sub custom_flash_norfdm5_h_file_body
{
my ($MAKEFILE_OPTIONS_LOCAL, $CUSTOM_MEM_DEV_OPTIONS_LOCAL, $MDL_INFO_LIST_LOCAL, $COMM_MDL_INFO_LOCAL, $NOR_FLASH_BASE_ADDRESS_VAL_LOCAL, $NOR_ALLOCATED_FAT_SPACE_VAL_LOCAL, $entire_bank_info_size_list_LOCAL, $entire_bank_info_count_list_LOCAL) = @_;
my $bank_info_string = &bank_info( $entire_bank_info_size_list_LOCAL, $entire_bank_info_count_list_LOCAL, $NOR_FLASH_BASE_ADDRESS_VAL_LOCAL, $NOR_ALLOCATED_FAT_SPACE_VAL_LOCAL );
###
my $nor_total_lsmt = 1;
my $count = 0;
my $sum = 1;
my $tmp_regions_sum = $NOR_ALLOCATED_FAT_SPACE_VAL_LOCAL;
if ($MEM_DEV_LIST_INFO{0}->{'Comm. Series'} eq 'INTEL_SIBLEY')
{
if ($tmp_regions_sum > (64*1024*1024))
{
my $count = 0;
my $sum = 1;
$tmp_regions_sum /= 1024;
while ($sum < $tmp_regions_sum)
{
$sum *= 2;
$count++;
}
$count -= 8;
for (my $i=0; $i<$count; $i++)
{
$nor_total_lsmt *= 2;
}
}
else
{
my $count = 0;
my $sum = 1;
$tmp_regions_sum /= 1024;
while ($sum < $tmp_regions_sum)
{
$sum *= 2;
$count++;
}
if (($count/2) == 1)
{
$count += 1;
}
$count /= 2;
for (my $i=0; $i<$count; $i++)
{
$nor_total_lsmt *= 2;
}
}
}
else
{
if ($tmp_regions_sum > (32*1024*1024))
{
my $count = 0;
my $sum = 1;
$tmp_regions_sum /= 512;
while ($sum < $tmp_regions_sum)
{
$sum *= 2;
$count++;
}
$count -= 8;
for (my $i=0; $i<$count; $i++)
{
$nor_total_lsmt *= 2;
}
}
else
{
my $count = 0;
my $sum = 1;
$tmp_regions_sum /= 512;
while ($sum < $tmp_regions_sum)
{
$sum *= 2;
$count++;
}
if (($count/2) == 1)
{
$count += 1;
}
$count /= 2;
for (my $i=0; $i<$count; $i++)
{
$nor_total_lsmt *= 2;
}
}
}
###
my $template = <<"__TEMPLATE";
#ifdef __NOR_FDM5__
/*******************************************************************************
Follow the 4 steps below to configure flash memory
Step 1. Fill the flash bank (partition) information table,
flash device features flexible, multi-bank read-while-program and
read-while-erase capability, enabling background programming or erasing in
one bank simultaneously with code execution or data reads in another bank.
Each element in the table is the format as below:
{bank size, bank number},
Step 2. Modify the value of LSMT, you can see MemoryDevice_FlashDisk_FAQ for
detail information
Step 2. Define the toal sectors (512bytes) of system drive
the remainder is the size of public drive
If there is no partiton (just one drive, system drive)
set this value to STORAGE_NO_PARTITION (0xFFFFFFFF)
Note : Code region and FAT region can not share the same bank (partition)
*******************************************************************************/
/***********
* Step 1. *
***********/
#define NOR_FDM5_BANK_INFO_LAYOUT $bank_info_string
/***********
* Step 2. *
***********/
#define NOR_TOTAL_LSMT $nor_total_lsmt
/***********
* Step 3. *
***********/
// Set NOR_SYSDRV_SECTORS to 0 will disable this setting and use PARTITION_SECTORS in custom_memorydevice.h to set user drive size.
#define NOR_SYSDRV_SECTORS 0
#endif //__NOR_FDM5__
__TEMPLATE
return $template;
}
#****************************************************************************
# subroutine: split_info_for_UB
# return: List of RegionInfo/BlockInfo/BankInfo
# input: $info: Excel value to be split
#****************************************************************************
sub split_info_for_UB
{
my $text = shift;
my @new = ();
my $ref_str;
my $i;
push(@new, $+) while $text =~ m{
"([^\"\\]*(?:\\.[^\"\\]*)*)", ?
| ([^,]+), ?
| ,
}gx;
push(@new, undef) if substr($text, -1,1) eq ',';
for($i = 0; $i < @new; $i++){
print "$i: $new[$i]\n";
}
$ref_str = "(";
for($i = 0; $i < @new; $i++){
if($i == (@new -1))
{
$ref_str .= $new[$i];
}
else
{
$ref_str .= $new[$i] . "|";
}
}
$ref_str .= ")";
print "$ref_str\n";
return $ref_str;
}
return 1;