| #!/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 = ®ion_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 = ®ion_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 = ®ion_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 = ®ion_info($fs_region_info_size_list_LOCAL, $fs_region_info_count_list_LOCAL, 'DISK0_REGION_INFO_LAYOUT'); |
| my $region_info_disk1 = ®ion_info($fs_region_info_size_list_LOCAL, $fs_region_info_count_list_LOCAL, 'DISK1_REGION_INFO_LAYOUT'); |
| my $region_info_entire = ®ion_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; |