emigen_v1.pm 73 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916
  1. #!/usr/local/bin/perl
  2. #
  3. #*****************************************************************************
  4. # Copyright Statement:
  5. # --------------------
  6. # This software is protected by Copyright and the information contained
  7. # herein is confidential. The software may not be copied and the information
  8. # contained herein may not be used or disclosed except with the written
  9. # permission of MediaTek Inc. (C) 2008
  10. #
  11. # BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
  12. # THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
  13. # RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
  14. # AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
  15. # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
  16. # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
  17. # NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
  18. # SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
  19. # SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
  20. # THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
  21. # NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
  22. # SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
  23. #
  24. # BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
  25. # LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
  26. # AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
  27. # OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
  28. # MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
  29. #
  30. # THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
  31. # WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
  32. # LAWS PRINCIPLES. ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
  33. # RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
  34. # THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
  35. #
  36. #****************************************************************************/
  37. #*
  38. #* Filename:
  39. #* ---------
  40. #* emigen_sp.pl
  41. #*
  42. #* Project:
  43. #* --------
  44. #*
  45. #*
  46. #* Description:
  47. #* ------------
  48. #* This script will
  49. #* 1. parse custom_MemoryDevice.h to get memory device type and part number
  50. #* 2. read a excel file to get appropriate emi setting based on the part number
  51. #* 3. based on the emi settings, generate custom_EMI.c if not exist
  52. #* 4. based on the emi settings, generate custom_EMI.h if not exist
  53. #*
  54. #* Author:
  55. #* -------
  56. #*
  57. #*============================================================================
  58. #* HISTORY
  59. #* Below this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
  60. #*------------------------------------------------------------------------------
  61. #* $Revision$
  62. #* $Modtime$
  63. #* $Log$
  64. #*
  65. #*
  66. #*------------------------------------------------------------------------------
  67. #* Upper this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
  68. #*============================================================================
  69. #****************************************************************************/
  70. #****************************************************************************
  71. # Included Modules
  72. #****************************************************************************
  73. package emigen_v1;
  74. use strict;
  75. use File::Basename;
  76. use File::Path qw(make_path);
  77. use Class::Struct;
  78. my $LOCAL_PATH;
  79. BEGIN {
  80. $LOCAL_PATH = dirname($0);
  81. }
  82. use lib "$LOCAL_PATH/../";
  83. use pack_dep_gen;
  84. use lib "$LOCAL_PATH";
  85. use xls_v1;
  86. my $start_num = 0;
  87. our @ISA= qw( Exporter );
  88. our @EXPORT_OK = qw( emigen_set_id emigen_support_ddr emigen_support_hw_trap emigen_check_bldr emigen_opt_set emigen_run );
  89. our @EXPORT = qw( emigen_set_id emigen_support_ddr emigen_support_hw_trap emigen_check_bldr emigen_opt_set emigen_run );
  90. #****************************************************************************
  91. # Field define, add new field into SCAN_COL for scan
  92. #****************************************************************************
  93. struct( Column => {
  94. index => '$',
  95. name => '$', # index used in $MDL[$id]->data()
  96. field_name => '$', # field name used in xls
  97. });
  98. my $COL_VENDOR = Column->new(field_name => 'Vendor', name => 'VENDER');
  99. my $COL_PART_NUMBER = Column->new(field_name => 'Part Number', name => 'PARTNUM');
  100. my $COL_TYPE = Column->new(field_name => 'Type', name => 'DEV_TYPE');
  101. my $COL_MODE = Column->new(field_name => 'Mode', name => 'DEV_MODE');
  102. my $COL_DENSITY = Column->new(field_name => 'Density (Mb)', name => 'DENSITY');
  103. my $COL_BOARD_ID = Column->new(field_name => 'Board ID');
  104. my $COL_NAND_EMMC_ID = Column->new(field_name => 'NAND/eMMC ID', name => 'NAND_EMMC_ID');
  105. my $COL_FW_ID = Column->new(field_name => 'FW ID', name => 'FW_ID');
  106. my $COL_NAND_PAGE_SIZE = Column->new(field_name => 'Nand Page Size (B)', name => 'NAND_PAGE_SIZE');
  107. my $COL_CONA = Column->new(field_name => 'CONA_VAL', name => 'EMI_CONA_VAL');
  108. my $COL_CHN0_CONA = Column->new(field_name => 'CHN0_CONA_VAL', name => 'CHN0_EMI_CONA_VAL');
  109. my $COL_CHN1_CONA = Column->new(field_name => 'CHN1_CONA_VAL', name => 'CHN1_EMI_CONA_VAL');
  110. my $COL_CONF = Column->new(field_name => 'CONF_VAL', name => 'EMI_CONF_VAL');
  111. my $COL_CONH = Column->new(field_name => 'CONH_VAL', name => 'EMI_CONH_VAL');
  112. my $COL_CHIP_ID = Column->new(field_name => 'CHIP_ID', name => 'CHIP_ID');
  113. my $COL_MODE_REG5 = Column->new(field_name => 'MODE_REG5', name => 'MODE_REG5');
  114. my $COL_PINMUX_TYPE = Column->new(field_name => 'PIN_MUX_TYPE', name => 'PIN_MUX_TYPE');
  115. my @SCAN_COL = ( $COL_VENDOR, $COL_PART_NUMBER, $COL_TYPE, $COL_MODE, $COL_DENSITY, $COL_BOARD_ID,
  116. $COL_NAND_EMMC_ID, $COL_FW_ID, $COL_NAND_PAGE_SIZE, $COL_CONA, $COL_CHN0_CONA, $COL_CHN1_CONA,
  117. $COL_CONF, $COL_CONH, $COL_CHIP_ID, $COL_MODE_REG5, $COL_PINMUX_TYPE );
  118. #****************************************************************************
  119. # Actiming field, add new field into SCAN_AC_TIMING for scan
  120. #****************************************************************************
  121. my $AC_TIMING_FREQ = Column->new(field_name => 'FREQUENCY', name => 'AC_TIME_EMI_FREQUENCY');
  122. my $AC_TIMING_TRAS = Column->new(field_name => 'TRAS', name => 'AC_TIME_EMI_TRAS');
  123. my $AC_TIMING_TRP = Column->new(field_name => 'TRP', name => 'AC_TIME_EMI_TRP');
  124. my $AC_TIMING_TRPAB = Column->new(field_name => 'TRPAB', name => 'AC_TIME_EMI_TRPAB');
  125. my $AC_TIMING_TRC = Column->new(field_name => 'TRC', name => 'AC_TIME_EMI_TRC');
  126. my $AC_TIMING_TRFC = Column->new(field_name => 'TRFC', name => 'AC_TIME_EMI_TRFC');
  127. my $AC_TIMING_TRFCPB = Column->new(field_name => 'TRFCPB', name => 'AC_TIME_EMI_TRFCPB');
  128. my $AC_TIMING_TXP = Column->new(field_name => 'TXP', name => 'AC_TIME_EMI_TXP');
  129. my $AC_TIMING_TRTP = Column->new(field_name => 'TRTP', name => 'AC_TIME_EMI_TRTP');
  130. my $AC_TIMING_TRCD = Column->new(field_name => 'TRCD', name => 'AC_TIME_EMI_TRCD');
  131. my $AC_TIMING_TWR = Column->new(field_name => 'TWR', name => 'AC_TIME_EMI_TWR');
  132. my $AC_TIMING_TWTR = Column->new(field_name => 'TWTR', name => 'AC_TIME_EMI_TWTR');
  133. my $AC_TIMING_TRRD = Column->new(field_name => 'TRRD', name => 'AC_TIME_EMI_TRRD');
  134. my $AC_TIMING_TFAW = Column->new(field_name => 'TFAW', name => 'AC_TIME_EMI_TFAW');
  135. my $AC_TIMING_TRTW_ODT_OFF = Column->new(field_name => 'TRTW_ODT_OFF', name => 'AC_TIME_EMI_TRTW_ODT_OFF');
  136. my $AC_TIMING_TRTW_ODT_ON = Column->new(field_name => 'TRTW_ODT_ON', name => 'AC_TIME_EMI_TRTW_ODT_ON');
  137. my $AC_TIMING_REFCNT = Column->new(field_name => 'REFCNT', name => 'AC_TIME_EMI_REFCNT');
  138. my $AC_TIMING_REFCNT_FR_CLK = Column->new(field_name => 'REFCNT_FR_CLK', name => 'AC_TIME_EMI_REFCNT_FR_CLK');
  139. my $AC_TIMING_TXREFCNT = Column->new(field_name => 'TXREFCNT', name => 'AC_TIME_EMI_TXREFCNT');
  140. my $AC_TIMING_TZQCS = Column->new(field_name => 'TZQCS', name => 'AC_TIME_EMI_TZQCS');
  141. my $AC_TIMING_TRTPD = Column->new(field_name => 'TRTPD', name => 'AC_TIME_EMI_TRTPD');
  142. my $AC_TIMING_TWTPD = Column->new(field_name => 'TWTPD', name => 'AC_TIME_EMI_TWTPD');
  143. my $AC_TIMING_TMRR2W_ODT_OFF = Column->new(field_name => 'TMRR2W_ODT_OFF', name => 'AC_TIME_EMI_TMRR2W_ODT_OFF');
  144. my $AC_TIMING_TMRR2W_ODT_ON = Column->new(field_name => 'TMRR2W_ODT_ON', name => 'AC_TIME_EMI_TMRR2W_ODT_ON');
  145. my $AC_TIMING_TRAS_05T = Column->new(field_name => 'TRAS_05T', name => 'AC_TIME_EMI_TRAS_05T');
  146. my $AC_TIMING_TRP_05T = Column->new(field_name => 'TRP_05T', name => 'AC_TIME_EMI_TRP_05T');
  147. my $AC_TIMING_TRPAB_05T = Column->new(field_name => 'TRPAB_05T', name => 'AC_TIME_EMI_TRPAB_05T');
  148. my $AC_TIMING_TRC_05T = Column->new(field_name => 'TRC_05T', name => 'AC_TIME_EMI_TRC_05T');
  149. my $AC_TIMING_TRFC_05T = Column->new(field_name => 'TRFC_05T', name => 'AC_TIME_EMI_TRFC_05T');
  150. my $AC_TIMING_TRFCPB_05T = Column->new(field_name => 'TRFCPB_05T', name => 'AC_TIME_EMI_TRFCPB_05T');
  151. my $AC_TIMING_TXP_05T = Column->new(field_name => 'TXP_05T', name => 'AC_TIME_EMI_TXP_05T');
  152. my $AC_TIMING_TRTP_05T = Column->new(field_name => 'TRTP_05T', name => 'AC_TIME_EMI_TRTP_05T');
  153. my $AC_TIMING_TRCD_05T = Column->new(field_name => 'TRCD_05T', name => 'AC_TIME_EMI_TRCD_05T');
  154. my $AC_TIMING_TWR_05T = Column->new(field_name => 'TWR_05T', name => 'AC_TIME_EMI_TWR_05T');
  155. my $AC_TIMING_TWTR_05T = Column->new(field_name => 'TWTR_05T', name => 'AC_TIME_EMI_TWTR_05T');
  156. my $AC_TIMING_TRRD_05T = Column->new(field_name => 'TRRD_05T', name => 'AC_TIME_EMI_TRRD_05T');
  157. my $AC_TIMING_TFAW_05T = Column->new(field_name => 'TFAW_05T', name => 'AC_TIME_EMI_TFAW_05T');
  158. my $AC_TIMING_TRTW_ODT_OFF_05T = Column->new(field_name => 'TRTW_ODT_OFF_05T', name => 'AC_TIME_EMI_TRTW_ODT_OFF_05T');
  159. my $AC_TIMING_TRTW_ODT_ON_05T = Column->new(field_name => 'TRTW_ODT_ON_05T', name => 'AC_TIME_EMI_TRTW_ODT_ON_05T');
  160. my $AC_TIMING_TRTPD_05T = Column->new(field_name => 'TRTPD_05T', name => 'AC_TIME_EMI_TRTPD_05T');
  161. my $AC_TIMING_TWTPD_05T = Column->new(field_name => 'TWTPD_05T', name => 'AC_TIME_EMI_TWTPD_05T');
  162. my $AC_TIMING_TMRR2W_ODT_OFF_05T = Column->new(field_name => 'TMRR2W_ODT_OFF_05T', name => 'AC_TIME_EMI_TMRR2W_ODT_OFF_05T');
  163. my $AC_TIMING_TMRR2W_ODT_ON_05T = Column->new(field_name => 'TMRR2W_ODT_ON_05T', name => 'AC_TIME_EMI_TMRR2W_ODT_ON_05T');
  164. my @SCAN_AC_TIMING = ( $AC_TIMING_FREQ, $AC_TIMING_TRAS, $AC_TIMING_TRP, $AC_TIMING_TRPAB, $AC_TIMING_TRC, $AC_TIMING_TRFC, $AC_TIMING_TRFCPB,
  165. $AC_TIMING_TXP, $AC_TIMING_TRTP, $AC_TIMING_TRCD, $AC_TIMING_TWR, $AC_TIMING_TWTR, $AC_TIMING_TRRD, $AC_TIMING_TFAW, $AC_TIMING_TRTW_ODT_OFF,
  166. $AC_TIMING_TRTW_ODT_ON, $AC_TIMING_REFCNT, $AC_TIMING_REFCNT_FR_CLK, $AC_TIMING_TXREFCNT, $AC_TIMING_TZQCS, $AC_TIMING_TRTPD, $AC_TIMING_TWTPD,
  167. $AC_TIMING_TMRR2W_ODT_OFF, $AC_TIMING_TMRR2W_ODT_ON, $AC_TIMING_TRAS_05T, $AC_TIMING_TRP_05T, $AC_TIMING_TRPAB_05T, $AC_TIMING_TRC_05T, $AC_TIMING_TRFC_05T,
  168. $AC_TIMING_TRFCPB_05T, $AC_TIMING_TXP_05T, $AC_TIMING_TRTP_05T, $AC_TIMING_TRCD_05T, $AC_TIMING_TWR_05T, $AC_TIMING_TWTR_05T, $AC_TIMING_TRRD_05T,
  169. $AC_TIMING_TFAW_05T, $AC_TIMING_TRTW_ODT_OFF_05T, $AC_TIMING_TRTW_ODT_ON_05T, $AC_TIMING_TRTPD_05T, $AC_TIMING_TWTPD_05T, $AC_TIMING_TMRR2W_ODT_OFF_05T,
  170. $AC_TIMING_TMRR2W_ODT_ON_05T );
  171. #****************************************************************************
  172. # DDR type define, add new type into SCAN_COL for scan
  173. #****************************************************************************
  174. struct( DdrType => {
  175. name => '$',
  176. type_id => '$',
  177. support_multi_dis => '$', # support multiple discrete dram in one load (ie. different rank size)
  178. supported => '$',
  179. hw_trap_defined => '$',
  180. found_mcp => '$',
  181. found_discrete => '$',
  182. });
  183. my $DDR_TYPE_DDR1 = DdrType->new(name => 'DDR1', type_id => '01');
  184. my $DDR_TYPE_LPDDR2 = DdrType->new(name => 'LPDDR2', type_id => '02', support_multi_dis => 1);
  185. my $DDR_TYPE_LPDDR3 = DdrType->new(name => 'LPDDR3', type_id => '03', support_multi_dis => 1);
  186. my $DDR_TYPE_PCDDR3 = DdrType->new(name => 'PCDDR3', type_id => '04');
  187. my $DDR_TYPE_LPDDR4 = DdrType->new(name => 'LPDDR4', type_id => '05', support_multi_dis => 1);
  188. my $DDR_TYPE_LPDR4X = DdrType->new(name => 'LPDR4X', type_id => '06', support_multi_dis => 1);
  189. my $DDR_TYPE_LPDR4P = DdrType->new(name => 'LPDR4P', type_id => '07', support_multi_dis => 1);
  190. my @ALL_DDR_TYPE = ( $DDR_TYPE_DDR1, $DDR_TYPE_LPDDR2, $DDR_TYPE_LPDDR3, $DDR_TYPE_PCDDR3, $DDR_TYPE_LPDDR4, $DDR_TYPE_LPDR4X, $DDR_TYPE_LPDR4P );
  191. #****************************************************************************
  192. # data structure for parsing data
  193. #****************************************************************************
  194. struct( MemDevice => {
  195. data => '%',
  196. sub_version => '$',
  197. mcp_type => '$',
  198. cbt_mode => '%',
  199. ddr => '$',
  200. actiming => '@',
  201. mcp_id_str => '$',
  202. mcp_id_len => '$',
  203. fw_id_str => '$',
  204. fw_id_len => '$',
  205. dram_rank_size => '@',
  206. emi_setting_str => '$',
  207. });
  208. #****************************************************************************
  209. # Constants
  210. #****************************************************************************
  211. my $EMIGEN_VERNO = " V0.01";
  212. # V0.01, Zhen Jiang, Porting emigen to DUMA project
  213. #
  214. my $DebugPrint = 1; # 1 for debug; 0 for non-debug
  215. my $TotalCustemChips = 0 ;
  216. my $CustBoard_ID ;
  217. my $EMIGEN_CHIP_ID;
  218. my $EMIGEN_TAG_ID;
  219. ######################################################################################
  220. my @MDL;
  221. ######################################################################################
  222. my $USE_EMMC_ID_LEN=9;
  223. my $MAX_NAND_EMMC_ID_LEN=16;
  224. my $MAX_FW_ID_LEN=8;
  225. my $Discrete_DDR = 0;
  226. my @DISCRETE_MDLS;
  227. my $BLDR_CHECK = 0;
  228. #****************************************************************************
  229. # COMBO_MCP_RULE_V
  230. # 1: same emmc id can not be comboed
  231. # 2: same emmc id and same dram type and same rank size can noe be comboed
  232. #****************************************************************************
  233. my $COMBO_MCP_RULE_V = 1;
  234. #****************************************************************************
  235. # PINMUX_CHECK
  236. # 1: Only same pinmux can be comboed
  237. #****************************************************************************
  238. my $PINMUX_CHECK = 0;
  239. #
  240. # all above are arrays, each represents an user defined chip.
  241. #
  242. # this is the ID of the custom board.
  243. #****************************************************************************************
  244. # subroutine: emigen_set_id
  245. # saving platform information before parsing
  246. # porting: no need
  247. # input: $chip_id - chip name (ex: "MT6763")
  248. # input: $tag_id - tag id for flashtool (ex: "v30")
  249. # return: void
  250. #****************************************************************************************
  251. sub emigen_set_id {
  252. $EMIGEN_CHIP_ID = shift;
  253. $EMIGEN_TAG_ID = shift;
  254. }
  255. #****************************************************************************************
  256. # subroutine: emigen_support_ddr
  257. # specify ddr type which is supported, can be called multiple times
  258. # porting: no need
  259. # input: $type - ddr type name (ex: "LPDR4X")
  260. # return: void
  261. #****************************************************************************************
  262. sub emigen_support_ddr {
  263. my $type = shift;
  264. foreach my $n (@ALL_DDR_TYPE) {
  265. if ($n->name eq $type) {
  266. $n->supported(1);
  267. last;
  268. }
  269. }
  270. }
  271. #****************************************************************************************
  272. # subroutine: emigen_support_hw_trap
  273. # specify ddr type which could be identify by hw trapping
  274. # porting: no need
  275. # input: $type - ddr type name (ex: "LPDR4X")
  276. # return: void
  277. #****************************************************************************************
  278. sub emigen_support_hw_trap {
  279. my $type = shift;
  280. foreach my $n (@ALL_DDR_TYPE) {
  281. if ($n->name eq $type) {
  282. die("[Error] Need to set support before setting hw trap\n") if ($n->supported ne 1);
  283. $n->hw_trap_defined(1);
  284. last;
  285. }
  286. }
  287. }
  288. #****************************************************************************************
  289. # subroutine: emigen_check_bldr
  290. # specify ddr type which could be identify by hw trapping
  291. # porting: no need
  292. # input: $check - 0: dont check bldr with MDL (default) , 1: check bldr with MDL
  293. # return: void
  294. #****************************************************************************************
  295. sub emigen_check_bldr {
  296. my $check = shift;
  297. if ($check == 1) {
  298. $BLDR_CHECK = 1;
  299. } else {
  300. $BLDR_CHECK = 0;
  301. }
  302. }
  303. #****************************************************************************************
  304. # subroutine: emigen_opt_set
  305. # set config for emigen
  306. # porting: no need
  307. # input: $opt - config
  308. # input: $val - value
  309. # return: void
  310. #****************************************************************************************
  311. sub emigen_opt_set {
  312. my $opt = shift;
  313. my $val = shift;
  314. if ($opt eq "COMBO_MCP_RULE_V") {
  315. $COMBO_MCP_RULE_V = $val if ($val >=1 && $val <= 2);
  316. }
  317. if ($opt eq "PINMUX_CHECK") {
  318. $PINMUX_CHECK = $val if ($val >=0 && $val <= 1);
  319. }
  320. }
  321. #****************************************************************************************
  322. # subroutine: emigen_run
  323. # parsing mdl from xls and generate hdr file and tag file
  324. # porting: TBD
  325. # input: $custom_memory_device_hdr - custom_MemoryDevice.h
  326. # input: $memory_device_list_xls - XLS file
  327. # input: $platform - platform id (ex: "MT6763")
  328. # input: $project - project name
  329. # input: $mtk_emigen_out_dir - output dir
  330. # input: $build_opt - 0: gen hdr file, 1: gen tag file
  331. # return: void
  332. #****************************************************************************************
  333. sub emigen_run {
  334. my $custom_memory_device_hdr = shift;
  335. my $memory_device_list_xls = shift;
  336. my $project = shift;
  337. my $mtk_emigen_out_dir = shift;
  338. my $build_opt = shift;
  339. my $custom_emi_h = "$mtk_emigen_out_dir/custom_emi.h";
  340. my $info_tag = "$mtk_emigen_out_dir/MTK_Loader_Info.tag";
  341. PrintDependModule($0);
  342. if ($DebugPrint == 1) {
  343. print "$custom_memory_device_hdr\n$memory_device_list_xls\n$EMIGEN_CHIP_ID\n";
  344. print "$mtk_emigen_out_dir\n";
  345. print "$custom_emi_h\n$info_tag\n"
  346. }
  347. my @CustCS_PART_NUMBER = &parse_custom_memory_device_hdr($custom_memory_device_hdr);
  348. my $bldr_mcp_type;
  349. $bldr_mcp_type = &parse_cust_bldr_mak($custom_memory_device_hdr) if ($BLDR_CHECK == 1);
  350. my $Book = &xls_open($memory_device_list_xls);
  351. PrintDependency($memory_device_list_xls);
  352. # select worksheet
  353. my $Sheet = &get_sheet($Book, lc $EMIGEN_CHIP_ID) ;
  354. # find cell address of the specified Nand ID
  355. die("[Error] Can not find worksheet ".lc($EMIGEN_CHIP_ID)."\n") if ($Sheet eq undef);
  356. # scan column index
  357. &find_field_position($Sheet);
  358. print "COMBO_MCP_RULE_V: $COMBO_MCP_RULE_V\n";
  359. my $iter = 0 ;
  360. while ($iter<scalar(@CustCS_PART_NUMBER)) {
  361. &DeviceListParser_LPSDRAM($Sheet, $CustCS_PART_NUMBER[$iter++]);
  362. }
  363. $iter = 0 ;
  364. print "TotalCustemChips:$TotalCustemChips\n";
  365. while ($iter < $TotalCustemChips) {
  366. die("[Error] Type(".$MDL[$iter]->data('PARTNUM').") is not in supported list !!!\n") if (!&IsSupportedDram($MDL[$iter]));
  367. if (&IsDiscreteDram($MDL[$iter])) {
  368. # if all discrete dram are LPDDR2, LPDDR3, LPDDR4, LPDDR4X and LPDDR4P, it is allowed
  369. if (&SupportMultipleDiscrete($MDL[$iter])) {
  370. my $iter_dis_dram;
  371. $iter_dis_dram = $iter + 1;
  372. while ($iter_dis_dram < $TotalCustemChips) {
  373. if (&IsDiscreteDram($MDL[$iter_dis_dram])) {
  374. &CanBeComboDiscrete($MDL[$iter], $MDL[$iter_dis_dram]);
  375. }
  376. $iter_dis_dram++;
  377. }
  378. $Discrete_DDR++;
  379. } else {
  380. # DDR1,DDR3 only support one discrete DRAM in the Combo List
  381. # if more then one discrete DRAM in the list, send build error
  382. if ($Discrete_DDR == 0) {
  383. $Discrete_DDR++;
  384. if ($TotalCustemChips > 1) {
  385. print "[Error]At most one discrete PCDDR3 DRAM is allowed in the Combo MCP list\n" ;
  386. die "[Error]Combo discrete DRAM only support LPDDR2, LPDDR3, LPDDR4, LPDDR4X and LPDDR4P\n" ;
  387. }
  388. } else {
  389. die "[Error]more than 1 Discrete DDR used!\n" ;
  390. }
  391. }
  392. } else {
  393. # Nand or eMMC's + FW ID must unique
  394. my $iter2 ;
  395. $iter2 = $iter + 1 ;
  396. while ($iter2 < $TotalCustemChips) {
  397. if (!&IsDiscreteDram($MDL[$iter2])) {
  398. &CanBeComboMCP($MDL[$iter], $MDL[$iter2]);
  399. }
  400. $iter2++;
  401. }
  402. }
  403. $iter++;
  404. }
  405. die "[Error] PCDDR3 not support Combo Discrete DRAM feature.\n" if ($DDR_TYPE_PCDDR3->found_discrete > 1);
  406. die "[Error] PCDDR3 not support Combo Discrete DRAM feature.\n" if (($DDR_TYPE_PCDDR3->found_discrete == 1) && (scalar(@CustCS_PART_NUMBER)>1) );
  407. &check_bldr_with_mdl($bldr_mcp_type) if ($BLDR_CHECK == 1);
  408. &check_pinmux_with_mdl() if ($PINMUX_CHECK == 1);
  409. if ($build_opt == 0) {
  410. &write_header_file($custom_emi_h, $memory_device_list_xls);
  411. } elsif ($build_opt == 1) {
  412. # Build Preloader TAG!
  413. &write_tag($project, $info_tag, $EMIGEN_TAG_ID);
  414. }
  415. }
  416. #****************************************************************************************
  417. # subroutine: parse_cust_bldr_mak
  418. # parse cust_bldr.mak, and save CFG_BOOT_DEV into variables
  419. # porting: only when new mcp type are added
  420. # input: $filename - file path to custom_MemoryDevice.h
  421. # return: $mcp_type - mcp type defined in cust_bldr.mak
  422. #****************************************************************************************
  423. sub parse_cust_bldr_mak {
  424. my $custom_memory_device_hdr_filename = shift;
  425. my $filename;
  426. my $bldr;
  427. my $mcp_type;
  428. $filename = basename(dirname(dirname($custom_memory_device_hdr_filename))."/cust_bldr.mak");
  429. $filename = dirname(dirname($custom_memory_device_hdr_filename))."/cust_bldr.mak";
  430. open CUST_BLDR_MAK, "<$filename" or &error_handler("$filename: file error!", __FILE__, __LINE__);
  431. PrintDependency($filename);
  432. while (<CUST_BLDR_MAK>) {
  433. if (/^CFG_BOOT_DEV\s?:=\s?(\w*)/) {
  434. $bldr = $1;
  435. if ($bldr eq "BOOTDEV_SDMMC") {
  436. $mcp_type = "02";
  437. } elsif ($bldr eq "BOOTDEV_UFS") {
  438. $mcp_type = "03";
  439. }
  440. }
  441. }
  442. print "\nBLDR: $bldr, mcp_type: $mcp_type\n" if ($DebugPrint == 1);
  443. close CUST_BLDR_MAK;
  444. return $mcp_type;
  445. }
  446. #****************************************************************************************
  447. # subroutine: parse_custom_memory_device_hdr
  448. # parse custom_MemoryDevice.h, and save part number into variables
  449. # porting: no need
  450. # input: $filename - file path to custom_MemoryDevice.h
  451. # return: $CustCS_PART_NUMBER - array with found part number
  452. # return: $CustCS_CustemChips - total number of found part number
  453. #****************************************************************************************
  454. sub parse_custom_memory_device_hdr {
  455. my $filename = shift;
  456. my @CustCS_PART_NUMBER;
  457. my $CustCS_CustemChips;
  458. open CUSTOM_MEMORY_DEVICE_HDR, "<$filename" or &error_handler("$filename: file error!", __FILE__, __LINE__);
  459. PrintDependency($filename);
  460. @CustCS_PART_NUMBER = ();
  461. while (<CUSTOM_MEMORY_DEVICE_HDR>) {
  462. if (/^#if|^#ifdef|^#ifndef|^#elif|^#else/) {
  463. &error_handler("$filename: Not allowed to set conditional keywords $_ in custom_MemoryDevice.h!", __FILE__, __LINE__)
  464. unless (/^#ifndef\s+__CUSTOM_MEMORYDEVICE__/);
  465. }
  466. if (/^#define\s+(\w+)\[(\d+)\]\s+\(([-\w]*)\)/ || /^#define\s+(\w+)\[(\d+)\]\s+([-\w]*)/ ||
  467. /^#define\s+(MEMORY_DEVICE_TYPE)\s+\((\w*)\)/ || /^#define\s+(MEMORY_DEVICE_TYPE)\s+(\w*)/ ||
  468. /^#define\s+(BOARD_ID)\s+\((\w*)\)/ || /^#define\s+(BOARD_ID)\s+(\w*)/) {
  469. if ($1 eq "BOARD_ID") {
  470. print "\nBOARD_ID $2\n";
  471. $CustBoard_ID = $2 ;
  472. } elsif ($1 eq "CS_PART_NUMBER") {
  473. print "\nCS0 $2, $3\n" ;
  474. push @CustCS_PART_NUMBER, $3;
  475. }
  476. }
  477. }
  478. $CustCS_CustemChips = scalar(@CustCS_PART_NUMBER);
  479. print "\n$CustCS_CustemChips\n" if ($DebugPrint == 1);
  480. close CUSTOM_MEMORY_DEVICE_HDR;
  481. die "\n[Error]CustCS_CustemChips($CustCS_CustemChips) > 10\n" if ($CustCS_CustemChips > 10);
  482. die "\n[Error]CustCS_CustemChips($CustCS_CustemChips) = 0?\n" if ($CustCS_CustemChips == 0);
  483. return @CustCS_PART_NUMBER;
  484. }
  485. #****************************************************************************************
  486. # subroutine: error_handler
  487. # print error msg and stop program
  488. # porting: no need
  489. # input: $error_msg - error msg
  490. # input: $file - file
  491. # input: $line_no - error line
  492. # return: void
  493. #****************************************************************************************
  494. sub error_handler {
  495. my ($error_msg, $file, $line_no) = @_;
  496. my $final_error_msg = "[Error]EMIGEN ERROR: $error_msg at $file line $line_no\n";
  497. print $final_error_msg;
  498. die $final_error_msg;
  499. }
  500. #****************************************************************************************
  501. # subroutine: find_field_position
  502. # find all field's position in xls, make sure all field are found
  503. # porting: no need
  504. # input: $Sheet - XLS sheet object
  505. # return: void
  506. #****************************************************************************************
  507. sub find_field_position {
  508. my ($Sheet) = shift;
  509. foreach my $n (@SCAN_COL) {
  510. die("[Error] Not valid Column in @SCAN_COL, please check !!!!!\n") if (ref($n) ne "Column");
  511. }
  512. foreach my $n (@SCAN_AC_TIMING) {
  513. die("[Error] Not valid Column in @SCAN_AC_TIMING, please check !!!!!\n") if (ref($n) ne "Column");
  514. }
  515. foreach my $n (@ALL_DDR_TYPE) {
  516. die("[Error] Not valid DdrType in @ALL_DDR_TYPE, please check !!!!!\n") if (ref($n) ne "DdrType");
  517. $n->found_mcp(0);
  518. $n->found_discrete(0);
  519. }
  520. col_scan:
  521. for (my $col = 0;$col < 78;$col++) {
  522. for (my $row = 0;$row < 3;$row++) {
  523. my $field = &xls_cell_value($Sheet, $row, $col);
  524. next if (length($field) == 0);
  525. foreach my $n (@SCAN_COL) {
  526. next if (defined $n->index);
  527. if ($n->field_name eq $field) {
  528. $n->index($col);
  529. next col_scan;
  530. }
  531. }
  532. foreach my $n (@SCAN_AC_TIMING) {
  533. next if (defined $n->index);
  534. if ($n->field_name eq $field) {
  535. $n->index($col);
  536. next col_scan;
  537. }
  538. }
  539. }
  540. }
  541. foreach my $n (@SCAN_COL) {
  542. die("Column scan: '".$n->field_name."' not found\n") if (!defined $n->index);
  543. }
  544. foreach my $n (@SCAN_AC_TIMING) {
  545. die("AC Timing scan: '".$n->field_name."' not found\n") if (!defined $n->index);
  546. }
  547. }
  548. #****************************************************************************************
  549. # subroutine: IsDdrType
  550. # check if $dev's ddr type is $check_type
  551. # porting: no need
  552. # input: $dev - MDL object
  553. # input: $check_type - ddr type (ex: "LPDR4X")
  554. # return: 1: if $dev's ddr type is $check_type
  555. #****************************************************************************************
  556. sub IsDdrType {
  557. my $dev = shift;
  558. my $check_type = shift;
  559. return 1 if ($check_type eq $dev->ddr->name);
  560. return 0;
  561. }
  562. #****************************************************************************************
  563. # subroutine: IsDiscreteDram
  564. # check if $dev is discrete dram
  565. # porting: no need
  566. # input: $dev - MDL object
  567. # return: 1: if $dev is discrete dram
  568. #****************************************************************************************
  569. sub IsDiscreteDram {
  570. my $dev = shift;
  571. return 1 if ($dev->mcp_type eq "00" || $dev->mcp_type eq "0F");
  572. return 0;
  573. }
  574. #****************************************************************************************
  575. # subroutine: IsSameTypeDram
  576. # check if $dev1's ddr type equals $dev2's ddr type
  577. # porting: no need
  578. # input: $dev1 - MDL object
  579. # input: $dev2 - MDL object
  580. # return: 1: if $dev1's ddr type equals $dev2's ddr type
  581. #****************************************************************************************
  582. sub IsSameTypeDram {
  583. my $dev1 = shift;
  584. my $dev2 = shift;
  585. return 1 if ($dev1->ddr eq $dev2->ddr);
  586. return 0;
  587. }
  588. #****************************************************************************************
  589. # subroutine: SupportMultipleDiscrete
  590. # check if $dev could be runtime indentify (ex: by rank size, vendor id)
  591. # porting: no need
  592. # input: $dev - MDL object
  593. # return: 1: $dev cound be runtime indentify
  594. #****************************************************************************************
  595. sub SupportMultipleDiscrete {
  596. my $dev = shift;
  597. return 1 if ($dev->ddr->support_multi_dis == 1);
  598. return 0;
  599. }
  600. #****************************************************************************************
  601. # subroutine: SupportHWTrap
  602. # check if $dev could be identify by HW trapping
  603. # porting: no need
  604. # input: $dev - MDL object
  605. # return: 1: $dev could be identify by HW trapping
  606. #****************************************************************************************
  607. sub SupportHWTrap {
  608. my $dev = shift;
  609. return 1 if ($dev->ddr->hw_trap_defined == 1);
  610. return 0;
  611. }
  612. #****************************************************************************************
  613. # subroutine: IsSupportedDram
  614. # check if $dev could be supported by platform
  615. # porting: no need
  616. # input: $dev - MDL object
  617. # return: 1: $dev could be support by platform
  618. #****************************************************************************************
  619. sub IsSupportedDram {
  620. my $dev = shift;
  621. return 1 if ($dev->ddr->supported == 1);
  622. return 0;
  623. }
  624. #****************************************************************************************
  625. # subroutine: DeviceListParser_LPSDRAM
  626. # Find MDL whose part number equals to $CustCS_id from XLS, and parse data into MDL object
  627. # porting: always need to check
  628. # input: $Book - XLS object
  629. # input: $PartNum - the part number want to find
  630. # return: total number of found MDL
  631. #****************************************************************************************
  632. sub DeviceListParser_LPSDRAM {
  633. my ($Sheet) ;
  634. my ($PartNum) ;
  635. my ($id) ;
  636. my ($iter);
  637. my ($num_part_found);
  638. my ($eos_flag);
  639. $num_part_found = 0 ;
  640. $Sheet = shift;
  641. $PartNum = shift;
  642. $id = $TotalCustemChips;
  643. my $row;
  644. my $col;
  645. my $rows_part_found; # stores the part numbers found in MDL
  646. $eos_flag = 5; # if this flag counts to '0', it means End Of Sheet
  647. $row = $start_num - 1 ; # scan from row 2
  648. my $scan_idx;
  649. my @rows_part_found;
  650. do {{
  651. ++$row ;
  652. $scan_idx = &xls_cell_value($Sheet, $row, $COL_PART_NUMBER->index) ;
  653. print "[Bike Check] scan_idx= $scan_idx\n";
  654. unless (defined $scan_idx) {
  655. print "[$row][scan_idx]No Value, $eos_flag\n" if $DebugPrint == 1 ;
  656. $eos_flag -- ;
  657. next ;
  658. }
  659. if ($scan_idx eq "") {
  660. print "[$row][scan_idx]EQ null, $eos_flag\n" if $DebugPrint == 1 ;
  661. $eos_flag -- ;
  662. next ;
  663. }
  664. $eos_flag = 5 ;
  665. # remove leading and tailing spaces
  666. $scan_idx =~ s/^\s+// if $DebugPrint == 1 ;
  667. $scan_idx =~ s/\s+$// if $DebugPrint == 1 ;
  668. $scan_idx =~ s/^\s+// ;
  669. $scan_idx =~ s/\s+$// ;
  670. print "$scan_idx ?= $PartNum\n" ;
  671. if ($scan_idx eq $PartNum) { # scan column 2 for Part Number
  672. my $boardid ;
  673. $boardid = &xls_cell_value($Sheet, $row, $COL_BOARD_ID->index) ;
  674. if ($CustBoard_ID eq $boardid) {
  675. $rows_part_found[$num_part_found] = $row;
  676. print "\nPartNum($PartNum==$scan_idx) found in row $row\n" ;
  677. $num_part_found ++;
  678. $TotalCustemChips ++;
  679. }
  680. }
  681. }} while (defined ($scan_idx) && ($eos_flag > 0));
  682. print("[Bike Check]num_part_found $num_part_found\n");
  683. if ($num_part_found == 0) {
  684. print "\n[Error]unsupported part number $PartNum\n" ;
  685. die "\n[Error]unsupported part number $PartNum\n" ;
  686. }
  687. my $dev;
  688. $iter = 0;
  689. while ($iter<$num_part_found) {
  690. $dev = MemDevice->new();
  691. $MDL[$id] = $dev;
  692. $_ = $rows_part_found[$iter] ;
  693. $iter ++;
  694. foreach my $n (@SCAN_COL) {
  695. next if (!defined $n->name);
  696. $MDL[$id]->data($n->name, &xls_cell_value($Sheet, $_, $n->index));
  697. }
  698. foreach my $n (@SCAN_AC_TIMING) {
  699. next if (!defined $n->name);
  700. $MDL[$id]->data($n->name, &xls_cell_value($Sheet, $_, $n->index));
  701. }
  702. $MDL[$id]->sub_version("0x1");
  703. # This function will overwrite NAND_EMMC_ID/FW_ID for discrete
  704. &check_support_dram_type_mcp_fw_id($MDL[$id]);
  705. if (!($MDL[$id]->data('CHIP_ID') eq lc($EMIGEN_CHIP_ID))) {
  706. die "[Error] Wrong Chip ID:".$MDL[$id]->data('CHIP_ID')."\n";
  707. }
  708. &check_cbt_mode($MDL[$id]);
  709. &check_channel_and_rank_in_EMI_settings($MDL[$id]);
  710. &check_dram_rank_size_by_EMI_settings($MDL[$id]); #Darren+
  711. &gen_ac_timing($MDL[$id]);
  712. &gen_emi_setting($MDL[$id], 0);
  713. $id ++;
  714. }
  715. return $id;
  716. }
  717. #****************************************************************************************
  718. # subroutine: CanBeComboDiscrete
  719. # check if two discrete dram $dev1 could be co-load with $dev2
  720. # porting: only when co-load rule changed
  721. # input: $dev1 - MDL object
  722. # input: $dev2 - MDL object
  723. # return: void
  724. #****************************************************************************************
  725. sub CanBeComboDiscrete {
  726. my $dev1 = shift;
  727. my $dev2 = shift;
  728. if (&IsSameTypeDram($dev1, $dev2)) {
  729. if ($dev1->data('MODE_REG5') eq $dev2->data('MODE_REG5')) {
  730. if (&IsDdrType($dev1, "LPDDR2")) {
  731. die "[Error] MODE_REG5(DRAM vendor_ID) should not be the same in the Combo list, MODE_REG5(".$dev1->data('PARTNUM').")==MODE_REG5(".$dev2->data('PARTNUM').")\n" ;
  732. } elsif (&IsDdrType($dev1, "LPDDR3")) {
  733. if ((($dev1->dram_rank_size(0) eq $dev2->dram_rank_size(0)) && ($dev1->dram_rank_size(1) eq $dev2->dram_rank_size(1)))) {
  734. die "[Error] LPDDR3 MODE_REG5+DRAM_RANKx_SIZE should not be the same in the Combo list, MODE_REG5+DRAM_RANKx_SIZE(".$dev1->data('PARTNUM').")==MODE_REG5+DRAM_RANKx_SIZE(".$dev2->data('PARTNUM').")\n" ;
  735. }
  736. } elsif (&IsDdrType($dev1, "LPDDR4") || &IsDdrType($dev1, "LPDR4X") || &IsDdrType($dev1, "LPDR4P")) {
  737. if ((($dev1->dram_rank_size(0) eq $dev2->dram_rank_size(0)) && ($dev1->dram_rank_size(1) eq $dev2->dram_rank_size(1)))) {
  738. die "[Error] LPDDR4 MODE_REG5+DRAM_RANKx_SIZE should not be the same in the Combo list, MODE_REG5+DRAM_RANKx_SIZE(".$dev1->data('PARTNUM').")==DRAM_RANKx_SIZE(".$dev2->data('PARTNUM').")\n" ;
  739. }
  740. }
  741. }
  742. } else {
  743. if (!&SupportHWTrap($dev1) || !&SupportHWTrap($dev2)) {
  744. die("[Error] Not support different type of discrete dram Type(".$dev1->data('PARTNUM').")!=Type(".$dev2->data('PARTNUM').")\n");
  745. }
  746. }
  747. }
  748. #****************************************************************************************
  749. # subroutine: CanBeComboMCP
  750. # check if two MCP $dev1 could be co-load with $dev2
  751. # porting: only when co-load rule changed
  752. # input: $dev1 - MDL object
  753. # input: $dev2 - MDL object
  754. # return: void
  755. #****************************************************************************************
  756. sub CanBeComboMCP {
  757. my $dev1 = shift;
  758. my $dev2 = shift;
  759. if ((!&SupportHWTrap($dev1) || !&SupportHWTrap($dev2)) && !&IsSameTypeDram($dev1, $dev2)) {
  760. die("[Error] Not support different type of dram Type(".$dev1->data('PARTNUM').")!=Type(".$dev2->data('PARTNUM').") without HW TRAP\n");
  761. }
  762. # NAND can't use different page size.
  763. if ($dev1->mcp_type == "01" && $dev2->mcp_type == "01") {
  764. die "[Error]different MCP page size! NAND_PAGE_SIZE(".$dev1->data('PARTNUM').")!=NAND_PAGE_SIZE(".$dev2->data('PARTNUM').")\n" if ($dev1->data('NAND_PAGE_SIZE') != $dev2->data('NAND_PAGE_SIZE'));
  765. }
  766. if ($dev1->data('NAND_EMMC_ID') eq $dev2->data('NAND_EMMC_ID')) {
  767. if ($COMBO_MCP_RULE_V > 1) {
  768. return if (!&IsSameTypeDram($dev1, $dev2));
  769. return if ((($dev1->dram_rank_size(0) ne $dev2->dram_rank_size(0)) || ($dev1->dram_rank_size(1) ne $dev2->dram_rank_size(1))));
  770. }
  771. if ( $dev1->data('PARTNUM') ne $dev2->data('PARTNUM') ) {
  772. die "[Error]Different part number:".$dev1->data('PARTNUM').",".$dev2->data('PARTNUM')." with same NAND/eMMC ID:".$dev1->data('NAND_EMMC_ID')."\n";
  773. } else {
  774. if ($dev1->data('FW_ID') eq $dev2->data('FW_ID')) {
  775. die "[Error]Two same part number:".$dev1->data('PARTNUM').",".$dev2->data('PARTNUM')." with same NAND/eMMC ID:".$dev1->data('NAND_EMMC_ID')." and same FW ID:".$dev2->data('FW_ID')."\n";
  776. }
  777. }
  778. }
  779. }
  780. #****************************************************************************************
  781. #****************************************************************************************
  782. # Parsing/Checking function
  783. #****************************************************************************************
  784. #****************************************************************************************
  785. #****************************************************************************************
  786. # subroutine: format_mcp_fw_id
  787. # format mcp_id and fw_id from hex to string array
  788. # porting: only when new id are added
  789. # input: $dev - MDL object
  790. # input: $type - 'NAND_EMMC_ID' or 'FW_ID'
  791. # return: void
  792. #****************************************************************************************
  793. sub format_mcp_fw_id {
  794. my $dev = shift;
  795. my $type = shift;
  796. my $string;
  797. my $id_str;
  798. my $id_len = 0;
  799. my $max_id_len;
  800. if ($type eq "NAND_EMMC_ID") {
  801. $id_str = "{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}";
  802. $max_id_len = $MAX_NAND_EMMC_ID_LEN;
  803. } elsif ($type eq "FW_ID") {
  804. $id_str = "{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}";
  805. $max_id_len = $MAX_FW_ID_LEN;
  806. } else {
  807. die("[Error] Wrong type for format_mcp_fw_id!!!!\n");
  808. }
  809. $string = $dev->data($type);
  810. $id_len = length($string);
  811. die ("[Error] The wrong ".$type.": ".$string." !! It is not byte align\n") if ($id_len & 0x1);
  812. $id_len = ($id_len - 2) / 2;
  813. $id_len = 0 if ($id_len < 0);
  814. if ($id_len > $max_id_len) {
  815. die("[Error] ".$type." length too long\n");
  816. }
  817. if ($id_len > 0) {
  818. my @VEC = ($string =~ m/([\dA-Fa-f]{2})/gs);
  819. my $last = pop(@VEC);
  820. $id_str = "{";
  821. foreach my $a (@VEC) {
  822. $id_str .= "0x$a,";
  823. }
  824. $id_str .= "0x$last";
  825. if ($id_len < $max_id_len) {
  826. for(my $i = 0; $i <($max_id_len - $id_len); $i++) {
  827. $id_str.= ",0x0"
  828. }
  829. }
  830. $id_str .= "}";
  831. }
  832. if ($type eq "NAND_EMMC_ID") {
  833. $dev->mcp_id_len($id_len);
  834. $dev->mcp_id_str($id_str);
  835. } else {
  836. $dev->fw_id_len($id_len);
  837. $dev->fw_id_str($id_str);
  838. }
  839. }
  840. #****************************************************************************************
  841. # subroutine: check_support_dram_type_mcp_fw_id
  842. # check $dev's mcp type and ddr type, then format mcp_id and fw_id if needed
  843. # porting: only when new mcp type or ddr type are added
  844. # input: $dev - MDL object
  845. # input: $PartNum - Part Number
  846. # return: void
  847. #****************************************************************************************
  848. sub check_support_dram_type_mcp_fw_id {
  849. my $dev = shift;
  850. my ($mcp_type, $ddr_str, $ddr_type, $is_discrete);
  851. if ($dev->data('DEV_TYPE') =~ /^Discrete Tablet (\S+)$/) {
  852. $dev->mcp_type("0F");
  853. $dev->data('NAND_EMMC_ID', "");
  854. $dev->data('FW_ID', "");
  855. $is_discrete = 1;
  856. $ddr_str = $1;
  857. } elsif ($dev->data('DEV_TYPE') =~ /^Discrete (\S+)$/) {
  858. $dev->mcp_type("00");
  859. $dev->data('NAND_EMMC_ID', "");
  860. $dev->data('FW_ID', "");
  861. $is_discrete = 1;
  862. $ddr_str = $1;
  863. } elsif ($dev->data('DEV_TYPE') =~ /^MCP\(NAND\+(\S+)\)$/) {
  864. $dev->mcp_type("01");
  865. $is_discrete = 0;
  866. $ddr_str = $1;
  867. } elsif ($dev->data('DEV_TYPE') =~ /^MCP\(eMMC\+(\S+)\)$/) {
  868. $dev->mcp_type("02");
  869. $is_discrete = 0;
  870. $ddr_str = $1;
  871. } elsif ($dev->data('DEV_TYPE') =~ /^MCP\(UFS\+(\S+)\)$/) {
  872. $dev->mcp_type("03");
  873. $is_discrete = 0;
  874. $ddr_str = $1;
  875. } else {
  876. die "[Error] unknown MCP type ".$dev->data('DEV_TYPE')." for ".$dev->data('PARTNUM')."\n" ;
  877. }
  878. &format_mcp_fw_id($dev, "NAND_EMMC_ID");
  879. &format_mcp_fw_id($dev, "FW_ID");
  880. if ($ddr_str eq "DDR1") {
  881. $dev->ddr($DDR_TYPE_DDR1);
  882. $is_discrete = 1;
  883. } elsif ($ddr_str eq "LPDDR2") {
  884. $dev->ddr($DDR_TYPE_LPDDR2);
  885. } elsif ($ddr_str eq "LPDDR3") {
  886. $dev->ddr($DDR_TYPE_LPDDR3);
  887. } elsif ($ddr_str eq "PCDDR3") {
  888. $dev->ddr($DDR_TYPE_PCDDR3);
  889. } elsif ($ddr_str eq "LPDDR4") {
  890. $dev->ddr($DDR_TYPE_LPDDR4);
  891. } elsif ($ddr_str eq "LPDR4X") {
  892. $dev->ddr($DDR_TYPE_LPDR4X);
  893. } elsif ($ddr_str eq "LPDR4P") {
  894. $dev->ddr($DDR_TYPE_LPDR4P);
  895. } else {
  896. die "[Error] unknown DDR type ".$dev->data('DEV_TYPE')." for ".$dev->data('PARTNUM')."\n" ;
  897. }
  898. if ($ddr_str eq "LPDDR3" || $ddr_str eq "LPDDR4" || $ddr_str eq "LPDR4X" || $ddr_str eq "LPDR4P") {
  899. if (!$dev->data('MODE_REG5')) {
  900. die "[Error](".$dev->data('PARTNUM').")MDL error, no MODE_REG5 information found, please update the MDL\n";
  901. }
  902. }
  903. $dev->ddr->found_discrete($dev->ddr->found_discrete + 1) if ($is_discrete == 1);
  904. $dev->ddr->found_mcp($dev->ddr->found_mcp + 1) if ($is_discrete == 0);
  905. push(@DISCRETE_MDLS, $dev) if ($is_discrete == 1);
  906. }
  907. #****************************************************************************************
  908. # subroutine: check_bldr_with_mdl
  909. # check if MDL and cust_bldr.mak are not match
  910. # porting: only when new mcp type are added
  911. # input: $mcp_type - MCP type defined in bldr
  912. # return: void
  913. #****************************************************************************************
  914. sub check_bldr_with_mdl {
  915. my $mcp_type = shift;
  916. my $iter = 0 ;
  917. for $iter (0..$TotalCustemChips-1) {
  918. return if (&IsDiscreteDram($MDL[$iter]) || $MDL[$iter]->mcp_type eq $mcp_type);
  919. }
  920. die("[Error] No discrete dram and none of MCP matched CFG_BOOT_DEV, please check MDL\n");
  921. }
  922. #****************************************************************************************
  923. # subroutine: check_pinmux_with_mdl
  924. # check if all pinmux in MDL are same
  925. # porting: none
  926. # return: void
  927. #****************************************************************************************
  928. sub check_pinmux_with_mdl {
  929. my $pinmux_type;
  930. my $iter = 0 ;
  931. return if ($TotalCustemChips == 0);
  932. $pinmux_type = $MDL[0]->data('PIN_MUX_TYPE');
  933. for $iter (1..$TotalCustemChips-1) {
  934. if ($MDL[$iter]->data('PIN_MUX_TYPE') ne $pinmux_type) {
  935. die("[Error] Not support different type of Pinmux PIN_MUX_TYPE(".$MDL[0]->data('PARTNUM').")!=PIN_MUX_TYPE(".$MDL[$iter]->data('PARTNUM').")\n");
  936. }
  937. }
  938. }
  939. #****************************************************************************************
  940. # subroutine: check_channel_and_rank_in_EMI_settings
  941. # check density and dual rank config are synced, channel and dual rank config are synced
  942. # porting: need to check EMI CODA, porting when adding new dram type
  943. # input: $dev - MDL object
  944. # return: void
  945. #****************************************************************************************
  946. sub check_channel_and_rank_in_EMI_settings {
  947. my $dev = shift;
  948. my $hex_val = hex($dev->data('EMI_CONA_VAL'));
  949. my $hex_val_ch0 = hex($dev->data('CHN0_EMI_CONA_VAL'));
  950. my $hex_val_ch1 = hex($dev->data('CHN1_EMI_CONA_VAL'));
  951. if ($dev->data('DENSITY') =~ /^(\d+)\+(\d+)$/) {
  952. &check_and_format_density_size($dev, 0, $1);
  953. &check_and_format_density_size($dev, 1, $2);
  954. if (($dev->data('DEV_TYPE') =~ /LPDDR4/) || ($dev->data('DEV_TYPE') =~ /LPDR4X/) || ($dev->data('DEV_TYPE') =~ /LPDR4P/)) {
  955. if (!($hex_val & 0x20000)) {# dual rank
  956. die "[Error] LPDDR4 Rank number incorrect between EMI CONA and MDL Density:".$dev->data('DENSITY').",".$dev->data('EMI_CONA_VAL')."\n";
  957. } else {
  958. if ($hex_val & 0x300) {# dual ch
  959. if (!($hex_val & 0x10000)) {# 2nd ch dual rank
  960. die "[Error] LPDDR4 Rank number incorrect between dual CH in EMI CONA:".$dev->data('EMI_CONA_VAL')."\n";
  961. }
  962. if (!(($hex_val_ch0 & 0x1) && ($hex_val_ch1 & 0x1))) { # dual ch dual rank
  963. die "[Error] LPDDR4 Rank number incorrect in CHN CONA:".$dev->data('CHN0_EMI_CONA_VAL').",".$dev->data('CHN1_EMI_CONA_VAL')."\n";
  964. }
  965. } else { #single ch
  966. if (!($hex_val_ch0 & 0x1)) {
  967. die "[Error] LPDDR4 Rank number incorrect in CHN CONA:".$dev->data('CHN0_EMI_CONA_VAL')."\n";
  968. }
  969. }
  970. }
  971. } else {# LPDDR3
  972. if (!($hex_val & 0x20000)) {
  973. die "[Error] LPDDR3 Rank number incorrect between EMI CONA and MDL Density:".$dev->data('DENSITY').",".$dev->data('EMI_CONA_VAL')."\n";
  974. }
  975. if (!($hex_val_ch0 & 0x1)) {
  976. die "[Error] LPDDR3 Rank number incorrect in CHN CONA:".$dev->data('CHN0_EMI_CONA_VAL')."\n";
  977. }
  978. }
  979. } elsif ($dev->data('DENSITY') =~ /^(\d+)$/) {
  980. &check_and_format_density_size($dev, 0, $1);
  981. $dev->dram_rank_size(1, 0);
  982. if (($dev->data('DEV_TYPE') =~ /LPDDR4/) || ($dev->data('DEV_TYPE') =~ /LPDR4X/) || ($dev->data('DEV_TYPE') =~ /LPDR4P/)) {
  983. if ($hex_val & 0x20000) {
  984. die "[Error] LPDDR4 Ranks number incorrect between EMI CONA and MDL Density:".$dev->data('DENSITY').",".$dev->data('EMI_CONA_VAL')."\n";
  985. } else {
  986. if ($hex_val & 0x300) {# dual ch
  987. if ($hex_val & 0x10000) {# 2nd ch rank
  988. die "[Error] LPDDR4 Rank number incorrect between dual CH in EMI CONA:".$dev->data('EMI_CONA_VAL')."\n";
  989. }
  990. if (($hex_val_ch0 & 0x1) || ($hex_val_ch1 & 0x1)) {# dual ch
  991. die "[Error] LPDDR4 Rank number incorrect in CHN CONA:".$dev->data('CHN0_EMI_CONA_VAL').",".$dev->data('CHN1_EMI_CONA_VAL')."\n";
  992. }
  993. } else {# single ch
  994. if (($hex_val_ch0 & 0x1)) {
  995. die "[Error] LPDDR4 Rank number incorrect in CHN CONA:".$dev->data('CHN0_EMI_CONA_VAL')."\n";
  996. }
  997. }
  998. }
  999. } else {# LPDDR3
  1000. if ($hex_val & 0x20000) {
  1001. die "[Error] LPDDR3 Ranks number incorrect between EMI CONA and MDL Density:".$dev->data('DENSITY').",".$dev->data('EMI_CONA_VAL')."\n";
  1002. }
  1003. if (($hex_val_ch0 & 0x1)) {
  1004. die "[Error] LPDDR3 Rank number incorrect in CHN CONA:".$dev->data('CHN0_EMI_CONA_VAL')."\n";
  1005. }
  1006. }
  1007. } else {
  1008. die "[Error]Wrong Density size!!DENSITY:".$dev->data('DENSITY').", Please check Density in MDL.\n";
  1009. }
  1010. }
  1011. #****************************************************************************************
  1012. # subroutine: check_and_format_density_size
  1013. # specify ddr type which could be identify by hw trapping
  1014. # porting: no need
  1015. # input: $dev - MDL object
  1016. # input: $rank - 0: rank0, 1: rank1
  1017. # input: $raw - raw string parsed from XLS
  1018. # return: void
  1019. #****************************************************************************************
  1020. sub check_and_format_density_size {
  1021. my $dev = shift;
  1022. my $rank = shift;
  1023. my $raw = shift;
  1024. my $q = $raw / 2048;
  1025. die ("Wrong density size!!!DENSITY:".$raw) if ($q * 2048 != $raw);
  1026. $dev->dram_rank_size($rank, sprintf("0x%X", 0x10000000 * $q));
  1027. }
  1028. #****************************************************************************************
  1029. # subroutine: gen_ac_timing
  1030. # gen ac timing value from XLS
  1031. # porting: only when emi setting structure are modified
  1032. # input: $dev - MDL object
  1033. # return: void
  1034. #****************************************************************************************
  1035. sub gen_ac_timing {
  1036. my $dev = shift;
  1037. if ($dev->data('AC_TIME_EMI_FREQUENCY')) {
  1038. $dev->actiming(0, sprintf("0x%08X",($dev->data('AC_TIME_EMI_FREQUENCY') + ($dev->data('AC_TIME_EMI_TRAS') << 16) + ($dev->data('AC_TIME_EMI_TRP') << 24))));
  1039. $dev->actiming(1, sprintf("0x%08X",(($dev->data('AC_TIME_EMI_TRPAB')) + ($dev->data('AC_TIME_EMI_TRC') << 8) + ($dev->data('AC_TIME_EMI_TRFC') << 16) + ($dev->data('AC_TIME_EMI_TRFCPB') << 24))));
  1040. $dev->actiming(2, sprintf("0x%08X",(($dev->data('AC_TIME_EMI_TXP')) + ($dev->data('AC_TIME_EMI_TRTP') << 8) + ($dev->data('AC_TIME_EMI_TRCD') << 16) + ($dev->data('AC_TIME_EMI_TWR') << 24))));
  1041. $dev->actiming(3, sprintf("0x%08X",(($dev->data('AC_TIME_EMI_TWTR')) + ($dev->data('AC_TIME_EMI_TRRD') << 8) + ($dev->data('AC_TIME_EMI_TFAW') << 16) + ($dev->data('AC_TIME_EMI_TRTW_ODT_OFF') << 24) + ($dev->data('AC_TIME_EMI_TRTW_ODT_ON') << 28))));
  1042. $dev->actiming(4, sprintf("0x%08X",(($dev->data('AC_TIME_EMI_REFCNT')) + ($dev->data('AC_TIME_EMI_REFCNT_FR_CLK') << 8) + ($dev->data('AC_TIME_EMI_TXREFCNT') << 16) + ($dev->data('AC_TIME_EMI_TZQCS') << 24))));
  1043. $dev->actiming(5, sprintf("0x%08X",(($dev->data('AC_TIME_EMI_TRTPD')) + ($dev->data('AC_TIME_EMI_TWTPD') << 8) + ($dev->data('AC_TIME_EMI_TMRR2W_ODT_OFF') << 16) + ($dev->data('AC_TIME_EMI_TMRR2W_ODT_ON') << 24))));
  1044. $dev->actiming(6, sprintf("0x%08X",(($dev->data('AC_TIME_EMI_TRAS_05T')) + ($dev->data('AC_TIME_EMI_TRP_05T') << 2) + ($dev->data('AC_TIME_EMI_TRPAB_05T') << 4) +
  1045. ($dev->data('AC_TIME_EMI_TRC_05T') << 6) + ($dev->data('AC_TIME_EMI_TRFC_05T') << 8) + ($dev->data('AC_TIME_EMI_TRFCPB_05T') << 10) +
  1046. ($dev->data('AC_TIME_EMI_TXP_05T') << 12) + ($dev->data('AC_TIME_EMI_TRTP_05T') << 14) + ($dev->data('AC_TIME_EMI_TRCD_05T') << 16) +
  1047. ($dev->data('AC_TIME_EMI_TWR_05T') << 18) + ($dev->data('AC_TIME_EMI_TWTR_05T') << 20) + ($dev->data('AC_TIME_EMI_TRRD_05T') << 22) +
  1048. ($dev->data('AC_TIME_EMI_TFAW_05T') << 24) + ($dev->data('AC_TIME_EMI_TRTW_ODT_OFF_05T') << 26) + ($dev->data('AC_TIME_EMI_TRTW_ODT_ON_05T') << 28) +
  1049. ($dev->data('AC_TIME_EMI_TRTPD_05T') << 30))));
  1050. $dev->actiming(7, sprintf("0x%08X",(($dev->data('AC_TIME_EMI_TWTPD_05T')) + ($dev->data('AC_TIME_EMI_TMRR2W_ODT_OFF_05T') << 2) + ($dev->data('AC_TIME_EMI_TMRR2W_ODT_ON_05T') << 4))));
  1051. } else {
  1052. $dev->actiming(0, sprintf("0x%08X",0));
  1053. $dev->actiming(1, sprintf("0x%08X",0));
  1054. $dev->actiming(2, sprintf("0x%08X",0));
  1055. $dev->actiming(3, sprintf("0x%08X",0));
  1056. $dev->actiming(4, sprintf("0x%08X",0));
  1057. $dev->actiming(5, sprintf("0x%08X",0));
  1058. $dev->actiming(6, sprintf("0x%08X",0));
  1059. $dev->actiming(7, sprintf("0x%08X",0));
  1060. }
  1061. }
  1062. #****************************************************************************************
  1063. # subroutine: check_dram_rank_size_by_EMI_settings
  1064. # check if density and rank size config are synced
  1065. # porting: need to check EMI CODA
  1066. # input: $dev - MDL object
  1067. # return: void
  1068. #****************************************************************************************
  1069. sub check_dram_rank_size_by_EMI_settings {
  1070. my $dev = shift;
  1071. my $hex_CONA = hex($dev->data('EMI_CONA_VAL'));
  1072. my $hex_CONH = hex($dev->data('EMI_CONH_VAL'));
  1073. my $shift_for_16bit = 1;
  1074. #Is it 32-bit or 16-bit I/O
  1075. if ($hex_CONA & 0x2) {
  1076. $shift_for_16bit = 0;
  1077. }
  1078. my $dram_rank0_size = 0;
  1079. my $dram_rank1_size = 0;
  1080. my $ch0_rank0_size = ($hex_CONH >> 16) & 0xf;
  1081. my $ch0_rank1_size = ($hex_CONH >> 20) & 0xf;
  1082. my $ch1_rank0_size = ($hex_CONH >> 24) & 0xf;
  1083. my $ch1_rank1_size = ($hex_CONH >> 28) & 0xf;
  1084. my ($col_bit, $row_bit);
  1085. if($ch0_rank0_size == 0) {
  1086. #rank 0 setting
  1087. $col_bit = (($hex_CONA >> 4) & 0x03) + 9;
  1088. $row_bit = ((($hex_CONA >> 24) & 0x1) << 2) + (($hex_CONA >> 12) & 0x03) + 13;
  1089. $dram_rank0_size = (1 << ($row_bit + $col_bit)) * (4 >> $shift_for_16bit) * 8; #4 or 2 byte * 8 banks
  1090. print "[Debug] dram_rank0_size: $dram_rank0_size\n";
  1091. } else {
  1092. $dram_rank0_size = ($ch0_rank0_size * 256 << 20);
  1093. }
  1094. if (0 != ($hex_CONA & (1 << 17))) { #rank 1 exist
  1095. if($ch0_rank1_size == 0) {
  1096. $col_bit = (($hex_CONA >> 6) & 0x03) + 9;
  1097. $row_bit = ((($hex_CONA >> 25) & 0x1) << 2) + (($hex_CONA >> 14) & 0x03) + 13;
  1098. $dram_rank1_size = ((1 << ($row_bit + $col_bit)) * (4 >> $shift_for_16bit) * 8); #4 or 2 byte * 8 banks
  1099. print "[Debug] dram_rank1_size: $dram_rank1_size\n";
  1100. } else {
  1101. $dram_rank1_size = ($ch0_rank1_size * 256 << 20);
  1102. }
  1103. }
  1104. if(0 != (($hex_CONA >> 8) & 0x01)) { #channel 1 exist
  1105. if($ch1_rank0_size == 0) {
  1106. #rank0 setting
  1107. $col_bit = (($hex_CONA >> 20) & 0x03) + 9;
  1108. $row_bit = ((($hex_CONH >> 4) & 0x1) << 2) + (($hex_CONA >> 28) & 0x03) + 13;
  1109. $dram_rank0_size += ((1 << ($row_bit + $col_bit)) * (4 >> $shift_for_16bit) * 8); #4 or 2 byte * 8 banks
  1110. print "[Debug] dram_rank0_size: $dram_rank0_size\n";
  1111. } else {
  1112. $dram_rank0_size += ($ch1_rank0_size * 256 << 20);
  1113. }
  1114. if (0 != ($hex_CONA & (1 << 16))) { #rank 1 exist
  1115. if($ch1_rank1_size == 0) {
  1116. $col_bit = (($hex_CONA >> 22) & 0x03) + 9;
  1117. $row_bit = ((($hex_CONH >> 5) & 0x1) << 2) + (($hex_CONA >> 30) & 0x03) + 13;
  1118. $dram_rank1_size += ((1 << ($row_bit + $col_bit)) * (4 >> $shift_for_16bit) * 8); #4 or 2 byte * 8 banks
  1119. print "[Debug] dram_rank1_size: $dram_rank1_size\n";
  1120. } else {
  1121. $dram_rank1_size += ($ch1_rank1_size * 256 << 20);
  1122. }
  1123. }
  1124. }
  1125. if((($hex_CONA >> 8) & 0x01) >= 2) {# for qual channel
  1126. $dram_rank0_size = $dram_rank0_size * 2;
  1127. $dram_rank1_size = $dram_rank1_size * 2;
  1128. }
  1129. print "[Debug] DRAM rank0 size: $dram_rank0_size, DRAM rank1 size: $dram_rank1_size\n";
  1130. my $mdl_r0_size = hex($dev->dram_rank_size(0));
  1131. my $mdl_r1_size = hex($dev->dram_rank_size(1));
  1132. print "[Debug] DRAM_RANK0_SIZE: $mdl_r0_size, DRAM_RANK1_SIZE: $mdl_r1_size\n";
  1133. if (($mdl_r0_size != $dram_rank0_size) || ($mdl_r1_size != $dram_rank1_size)) {
  1134. die "[Error][DRAMC] DRAM size settings incorrect between EMI CONA/CONH and MDL Density !!!\n";
  1135. }
  1136. }
  1137. #****************************************************************************************
  1138. # subroutine: check_cbt_mode
  1139. # transfer cbt mode into enum and id
  1140. # porting: only when cbt mode enum changed
  1141. # input: $dev - MDL object
  1142. # return: void
  1143. #****************************************************************************************
  1144. sub check_cbt_mode {
  1145. use Switch;
  1146. my $dev = shift;
  1147. switch ($dev->data('DEV_MODE')) {
  1148. case "R0_NORMAL+R1_NORMAL" {
  1149. $dev->cbt_mode('enum', "CBT_R0_R1_NORMAL");
  1150. $dev->cbt_mode('id', "0");
  1151. }
  1152. case "R0_BYTE+R1_BYTE" {
  1153. $dev->cbt_mode('enum', "CBT_R0_R1_BYTE");
  1154. $dev->cbt_mode('id', "1");
  1155. }
  1156. case "R0_NORMAL+R1_BYTE" {
  1157. $dev->cbt_mode('enum', "CBT_R0_NORMAL_R1_BYTE");
  1158. $dev->cbt_mode('id', "2");
  1159. }
  1160. case "R0_BYTE+R1_NORMAL" {
  1161. $dev->cbt_mode('enum', "CBT_R0_BYTE_R1_NORMAL");
  1162. $dev->cbt_mode('id', "3");
  1163. } else {
  1164. die "[Error]Wrong Mode !!!\n";
  1165. }
  1166. }
  1167. }
  1168. #****************************************************************************************
  1169. # subroutine: clone_default_discrete
  1170. # clone a MDL object from $dev, but make the clone one into discrete dram
  1171. # porting: only when emi structure are modified, or new dram type are added
  1172. # input: $dev - MDL object
  1173. # return: $clone - MDL object
  1174. #****************************************************************************************
  1175. sub clone_default_discrete {
  1176. my $dev = shift;
  1177. my $clone = bless { %$dev }, ref $dev;
  1178. # non scalar need to copy again
  1179. $clone->data({ %{$dev->data} });
  1180. $clone->cbt_mode({ %{$dev->cbt_mode} });
  1181. $clone->actiming([ @{$dev->actiming} ]);
  1182. $clone->dram_rank_size([ @{$dev->dram_rank_size} ]);
  1183. $clone->sub_version("0x0");
  1184. $clone->dram_rank_size(0, "0x20000000");
  1185. $clone->dram_rank_size(1, 0);
  1186. $clone->data('EMI_CONA_VAL', sprintf("0x%x", hex($clone->data('EMI_CONA_VAL')) | 0x00030000));
  1187. $clone->data('CHN0_EMI_CONA_VAL', sprintf("0x%x", hex($clone->data('CHN0_EMI_CONA_VAL')) | 0x00000001));
  1188. $clone->data('CHN1_EMI_CONA_VAL', sprintf("0x%x", hex($clone->data('CHN1_EMI_CONA_VAL')) | 0x00000001));
  1189. $clone->mcp_type("00");
  1190. $clone->data('NAND_EMMC_ID', '');
  1191. $clone->data('FW_ID', '');
  1192. &format_mcp_fw_id($clone, "NAND_EMMC_ID");
  1193. &format_mcp_fw_id($clone, "FW_ID");
  1194. if (&IsDdrType($clone, "LPDDR4") || &IsDdrType($clone, "LPDR4X") || &IsDdrType($clone, "LPDR4P")) {
  1195. $clone->data('DEV_MODE', "R0_BYTE+R1_BYTE");
  1196. } else {
  1197. $clone->data('DEV_MODE', "R0_NORMAL+R1_NORMAL");
  1198. }
  1199. &check_cbt_mode($clone);
  1200. $clone->data('AC_TIME_EMI_FREQUENCY', 0);
  1201. &gen_ac_timing($clone);
  1202. $clone->data('MODE_REG5', '0x00000000');
  1203. &gen_emi_setting($clone, 1);
  1204. return $clone;
  1205. }
  1206. #****************************************************************************************
  1207. # subroutine: gen_emi_setting
  1208. # transform MDL into emi_settings string
  1209. # porting: when changing emi settings structure, or new dram type are added
  1210. # input: $dev - MDL object
  1211. # input: $is_discrete - if empty, print "for discrete" in comment
  1212. # return: void
  1213. #****************************************************************************************
  1214. sub gen_emi_setting {
  1215. my $dev = shift;
  1216. my $is_discrete = shift;
  1217. my $emi_settings = "";
  1218. $emi_settings .= "\n\t//".$dev->data('PARTNUM');
  1219. $emi_settings .= " for discrete" if ($is_discrete);
  1220. $emi_settings .= "\n\t{\n\t\t";
  1221. $emi_settings .= $dev->sub_version . ",\t\t/* sub_version */\n\t\t" ;
  1222. $emi_settings .= "0x" . $dev->mcp_type . $dev->ddr->type_id . ",\t\t/* TYPE */\n\t\t" ;
  1223. $emi_settings .= $dev->mcp_id_len . ",\t\t/* EMMC ID/FW ID checking length */\n\t\t" ;
  1224. $emi_settings .= $dev->fw_id_len . ",\t\t/* FW length */\n\t\t" ;
  1225. $emi_settings .= $dev->mcp_id_str . ",\t\t/* NAND_EMMC_ID */\n\t\t" ;
  1226. $emi_settings .= $dev->fw_id_str . ",\t\t/* FW_ID */\n\t\t" ;
  1227. $emi_settings .= $dev->data('EMI_CONA_VAL') . ",\t\t/* EMI_CONA_VAL */\n\t\t" ;
  1228. $emi_settings .= $dev->data('EMI_CONH_VAL') . ",\t\t/* EMI_CONH_VAL */\n\t\t" ;
  1229. $emi_settings .= $dev->actiming(0) . ",\t\t/* U 00 */\n\t\t" ;
  1230. $emi_settings .= $dev->actiming(1) . ",\t\t/* U 01 */\n\t\t" ;
  1231. $emi_settings .= $dev->actiming(2) . ",\t\t/* U 02 */\n\t\t" ;
  1232. $emi_settings .= $dev->actiming(3) . ",\t\t/* U 03 */\n\t\t" ;
  1233. $emi_settings .= $dev->actiming(4) . ",\t\t/* U 04 */\n\t\t" ;
  1234. $emi_settings .= $dev->actiming(5) . ",\t\t/* U 05 */\n\t\t" ;
  1235. $emi_settings .= $dev->actiming(6) . ",\t\t/* U 06 */\n\t\t" ;
  1236. $emi_settings .= $dev->actiming(7) . ",\t\t/* U 07 */\n\t\t" ;
  1237. $emi_settings .= "{" . $dev->dram_rank_size(0) . "," . $dev->dram_rank_size(1) . ",0,0},\t\t/* DRAM RANK SIZE */\n\t\t" ;
  1238. $emi_settings .= $dev->data('EMI_CONF_VAL') . ",\t\t/* EMI_CONF_VAL */\n\t\t" ;
  1239. $emi_settings .= $dev->data('CHN0_EMI_CONA_VAL') . ",\t\t/* CHN0_EMI_CONA_VAL */\n\t\t" ;
  1240. $emi_settings .= $dev->data('CHN1_EMI_CONA_VAL') . ",\t\t/* CHN1_EMI_CONA_VAL */\n\t\t" ;
  1241. $emi_settings .= $dev->cbt_mode('enum') . ",\t\t/* dram_cbt_mode_extern */\n\t\t" ;
  1242. $emi_settings .= "{0,0,0,0,0,0},\t\t/* reserved 6 */\n\t\t" ;
  1243. if (&IsDdrType($dev, "DDR1")) {
  1244. } elsif (&IsDdrType($dev, "LPDDR2")) {
  1245. } elsif (&IsDdrType($dev, "LPDDR3")) {
  1246. $emi_settings .= $dev->data('MODE_REG5') . ",\t\t/* LPDDR3_MODE_REG5 */\n\t\t" ;
  1247. } elsif (&IsDdrType($dev, "PCDDR3")) {
  1248. } elsif (&IsDdrType($dev, "LPDDR4")) {
  1249. $emi_settings .= $dev->data('MODE_REG5') . ",\t\t/* LPDDR4_MODE_REG5 */\n\t\t" ;
  1250. } elsif (&IsDdrType($dev, "LPDR4X")) {
  1251. $emi_settings .= $dev->data('MODE_REG5') . ",\t\t/* LPDDR4X_MODE_REG5 */\n\t\t" ;
  1252. } elsif (&IsDdrType($dev, "LPDR4P")) {
  1253. $emi_settings .= $dev->data('MODE_REG5') . ",\t\t/* LPDDR4P_MODE_REG5 */\n\t\t" ;
  1254. }
  1255. $emi_settings .= $dev->data('PIN_MUX_TYPE') . ",\t\t/* PIN_MUX_TYPE for tablet */\n\t}" ;
  1256. print $emi_settings ;
  1257. print "\n\n" ;
  1258. $dev->emi_setting_str($emi_settings);
  1259. }
  1260. #****************************************************************************************
  1261. # subroutine: write_header_file
  1262. # write header file for c code
  1263. # porting: no need
  1264. # input: $custom_emi_h - file path to c header file
  1265. # input: $memory_device_list_xls - file path to xls
  1266. # return: void
  1267. #****************************************************************************************
  1268. sub write_header_file {
  1269. my $custom_emi_h = shift;
  1270. my $memory_device_list_xls = shift;
  1271. unlink ($custom_emi_h) if (-e $custom_emi_h);
  1272. my $temp_path = &dirname($custom_emi_h);
  1273. &make_path($temp_path);
  1274. open (CUSTOM_EMI_H, ">$custom_emi_h") or &error_handler("CUSTOM_EMI_H: file error!", __FILE__, __LINE__);
  1275. print CUSTOM_EMI_H &copyright_file_header();
  1276. print CUSTOM_EMI_H &description_file_header("custom_emi.h", $memory_device_list_xls,
  1277. "This Module defines the EMI (external memory interface) related setting.",
  1278. "EMI auto generator". $EMIGEN_VERNO);
  1279. print CUSTOM_EMI_H &custom_EMI_h_file_body();
  1280. close CUSTOM_EMI_H or &error_handler("$custom_emi_h: file error!", __FILE__, __LINE__);
  1281. print "\n$custom_emi_h is generated\n";
  1282. }
  1283. #****************************************************************************************
  1284. # subroutine: copyright_file_header
  1285. # generate copyright header string
  1286. # porting: no need
  1287. # input: void
  1288. # return: copyright header string
  1289. #****************************************************************************************
  1290. sub copyright_file_header {
  1291. my $template = <<"__TEMPLATE";
  1292. /*****************************************************************************
  1293. * Copyright Statement:
  1294. * --------------------
  1295. * This software is protected by Copyright and the information contained
  1296. * herein is confidential. The software may not be copied and the information
  1297. * contained herein may not be used or disclosed except with the written
  1298. * permission of MediaTek Inc. (C) 2008
  1299. *
  1300. * BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
  1301. * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
  1302. * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
  1303. * AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
  1304. * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
  1305. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
  1306. * NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
  1307. * SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
  1308. * SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
  1309. * THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
  1310. * NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
  1311. * SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
  1312. *
  1313. * BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
  1314. * LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
  1315. * AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
  1316. * OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
  1317. * MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
  1318. *
  1319. * THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
  1320. * WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
  1321. * LAWS PRINCIPLES. ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
  1322. * RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
  1323. * THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
  1324. *
  1325. *****************************************************************************/
  1326. __TEMPLATE
  1327. return $template;
  1328. }
  1329. #****************************************************************************************
  1330. # subroutine: description_file_header
  1331. # generate header for c header file
  1332. # porting: no need
  1333. # input: $filename: filename
  1334. # input: $description: one line description
  1335. # input: $author: optional
  1336. # return: file header -- description
  1337. #****************************************************************************
  1338. sub description_file_header {
  1339. my ($filename, $xls, $description, $author) = @_;
  1340. my @stat_ar = stat $xls;
  1341. my ($day, $month, $year) = (localtime($stat_ar[9]))[3,4,5]; $month++; $year+=1900;
  1342. my $template = <<"__TEMPLATE";
  1343. /*****************************************************************************
  1344. *
  1345. * Filename:
  1346. * ---------
  1347. * $filename
  1348. *
  1349. * Project:
  1350. * --------
  1351. * Android
  1352. *
  1353. * Description:
  1354. * ------------
  1355. * $description
  1356. *
  1357. * Author:
  1358. * -------
  1359. * $author
  1360. *
  1361. * Memory Device database last modified on $year/$month/$day
  1362. *
  1363. *============================================================================
  1364. * HISTORY
  1365. * Below this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
  1366. *------------------------------------------------------------------------------
  1367. * \$Revision\$
  1368. * \$Modtime\$
  1369. * \$Log\$
  1370. *
  1371. *------------------------------------------------------------------------------
  1372. * WARNING!!! WARNING!!! WARNING!!! WARNING!!! WARNING!!! WARNING!!!
  1373. * This file is generated by EMI Auto-gen Tool.
  1374. * Please do not modify the content directly!
  1375. * It could be overwritten!
  1376. *============================================================================
  1377. * Upper this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
  1378. *============================================================================
  1379. ****************************************************************************/
  1380. __TEMPLATE
  1381. return $template;
  1382. }
  1383. #****************************************************************************************
  1384. # subroutine: custom_EMI_h_file_body
  1385. # generate body of c header file
  1386. # porting: no need
  1387. # input: void
  1388. # return: void
  1389. #****************************************************************************************
  1390. sub custom_EMI_h_file_body {
  1391. my $EMI_SETTINGS_string = "" ;
  1392. my $DEF_EMI_SETTINGS_string = "" ;
  1393. my $DEF_MDL;
  1394. my $ddr = -1 ;
  1395. my $iter = 0 ;
  1396. if ($#DISCRETE_MDLS > 0) {
  1397. $DEF_MDL = &clone_default_discrete($DISCRETE_MDLS[0]);
  1398. } else {
  1399. $DEF_MDL = &clone_default_discrete($MDL[0]);
  1400. }
  1401. $DEF_EMI_SETTINGS_string = $DEF_MDL->emi_setting_str;
  1402. for $iter (0..$TotalCustemChips-1) {
  1403. if (!&IsDiscreteDram($MDL[$iter])) {
  1404. $EMI_SETTINGS_string .= $MDL[$iter]->emi_setting_str;
  1405. $EMI_SETTINGS_string .= " ," ;
  1406. }
  1407. }
  1408. for $iter (0..$TotalCustemChips-1) {
  1409. if (&IsDiscreteDram($MDL[$iter])) {
  1410. $EMI_SETTINGS_string .= $MDL[$iter]->emi_setting_str;
  1411. $EMI_SETTINGS_string .= " ," ;
  1412. }
  1413. }
  1414. my $template = <<"__TEMPLATE";
  1415. #ifndef __CUSTOM_EMI__
  1416. #define __CUSTOM_EMI__
  1417. #include "dramc_pi_api.h"
  1418. #include "emi.h"
  1419. #define COMBO_LPDDR2 (@{[$DDR_TYPE_LPDDR2->found_mcp]}+@{[$DDR_TYPE_LPDDR2->found_discrete]})
  1420. #define COMBO_LPDDR3 (@{[$DDR_TYPE_LPDDR3->found_mcp]}+@{[$DDR_TYPE_LPDDR3->found_discrete]})
  1421. #define COMBO_LPDDR4 (@{[$DDR_TYPE_LPDDR4->found_mcp]}+@{[$DDR_TYPE_LPDDR4->found_discrete]})
  1422. #define COMBO_LPDR4X (@{[$DDR_TYPE_LPDR4X->found_mcp]}+@{[$DDR_TYPE_LPDR4X->found_discrete]})
  1423. #define COMBO_LPDR4P (@{[$DDR_TYPE_LPDR4P->found_mcp]}+@{[$DDR_TYPE_LPDR4P->found_discrete]})
  1424. #define COMBO_PCDDR3 (@{[$DDR_TYPE_PCDDR3->found_mcp]}+@{[$DDR_TYPE_PCDDR3->found_discrete]})
  1425. #define NUM_EMI_RECORD ($TotalCustemChips)
  1426. int num_of_emi_records = NUM_EMI_RECORD ;
  1427. EMI_SETTINGS default_emi_setting =
  1428. $DEF_EMI_SETTINGS_string;
  1429. EMI_SETTINGS emi_settings[] =
  1430. {
  1431. $EMI_SETTINGS_string
  1432. };
  1433. #endif /* __CUSTOM_EMI__ */
  1434. __TEMPLATE
  1435. return $template ;
  1436. }
  1437. #****************************************************************************************
  1438. # subroutine: write_tag
  1439. # generate tag file
  1440. # porting: only when tag file format are modified
  1441. # input: $project - project name
  1442. # input: $info_tag - file path to tag file
  1443. # input: $platform_tag_id - tag id for flashtool (ex: "v30")
  1444. # return: void
  1445. #****************************************************************************************
  1446. sub write_tag {
  1447. my $project = lc(shift);
  1448. my $info_tag = shift;
  1449. my $platform_tag_id = shift;
  1450. my $filesize = 0x0 ;
  1451. my $ddr = -1 ;
  1452. my $DEF_MDL;
  1453. unlink ($info_tag) if (-e $info_tag);
  1454. my $temp_path = &dirname($info_tag);
  1455. &make_path($temp_path);
  1456. open FILE,">$info_tag";
  1457. print FILE pack("a24", "MTK_BLOADER_INFO_".$platform_tag_id); #MT6763
  1458. # print FILE pack("a24", "MTK_BLOADER_INFO_v00");
  1459. $filesize = $filesize + 24 ;
  1460. seek(FILE, 0x1b, 0);
  1461. my $pre_bin = "preloader_${project}.bin";
  1462. print "PROJECT = $project, pre_bin = $pre_bin\n";
  1463. print FILE pack("a64", $pre_bin);
  1464. $filesize = $filesize + 64 ;
  1465. seek(FILE, 0x58, 0);
  1466. print FILE pack("H8", 56313136);
  1467. $filesize = $filesize + 4 ;
  1468. print FILE pack("H8", 22884433);
  1469. $filesize = $filesize + 4 ;
  1470. print FILE pack("H8", "90007000");
  1471. $filesize = $filesize + 4 ;
  1472. print FILE pack("a8", "MTK_BIN");
  1473. $filesize = $filesize + 8 ;
  1474. # print FILE pack("H8", bc000000);
  1475. seek(FILE,0x6c, 0);
  1476. # 1.LPDDR2/LPDDR3/LPDDR4/LPDDR4X/LPDDR4P discrete dram number >= 2
  1477. #[DEL] 2.LPDDR2 discrete dram > 0, LPDDR2 MCP > 0
  1478. #[DEL] 3.LPDDR3 discrete dram > 0, LPDDR3 MCP > 0
  1479. #[DEL] 4.LPDDR4 discrete dram > 0, LPDDR4 MCP > 0
  1480. #[DEL] 5.LPDDR4X discrete dram > 0, LPDDR4X MCP > 0
  1481. if (($Discrete_DDR >= 2)) {
  1482. #if (($Discrete_DDR >= 2) || (($DIS_LPDDR2 > 0) && ($MCP_LPDDR2 > 0)) || (($DIS_LPDDR3 > 0) && ($MCP_LPDDR3 > 0)))
  1483. print "[EMIgen] Have multiple discrete dram\n";
  1484. print FILE pack("L", $TotalCustemChips+1); # number of emi settings + 1 default value emi_settings.
  1485. }else {
  1486. print FILE pack("L", $TotalCustemChips); # number of emi settings.
  1487. }
  1488. $filesize = $filesize + 4 ;
  1489. my $iter = 0 ;
  1490. # 1.LPDDR2/LPDDR3/LPDDR4/LPDDR4X/LPDDR4P discrete dram number >= 2
  1491. #[DEL] 2.LPDDR2 discrete dram > 0, LPDDR2 MCP > 0
  1492. #[DEL] 3.LPDDR3 discrete dram > 0, LPDDR3 MCP > 0
  1493. #[DEL] 4.LPDDR4 discrete dram > 0, LPDDR4 MCP > 0
  1494. #[DEL] 5.LPDDR4X discrete dram > 0, LPDDR4X MCP > 0
  1495. #[DEL] 6.LPDDR4P discrete dram > 0, LPDDR4P MCP > 0
  1496. if (($Discrete_DDR >= 2)) {
  1497. #if (($Discrete_DDR >= 2) || (($DIS_LPDDR2 > 0) && ($MCP_LPDDR2 > 0)) || (($DIS_LPDDR3 > 0) && ($MCP_LPDDR3 > 0)))
  1498. if ($#DISCRETE_MDLS > 0) {
  1499. $DEF_MDL = &clone_default_discrete($DISCRETE_MDLS[0]);
  1500. } else {
  1501. die("[Error] No default emi settings!!!\n");
  1502. }
  1503. $filesize = $filesize + &write_tag_one_element($DEF_MDL) ;
  1504. }
  1505. for $iter (0..$TotalCustemChips-1) {
  1506. # generate MCP dram
  1507. if (!&IsDiscreteDram($MDL[$iter])) {
  1508. $filesize = $filesize + &write_tag_one_element ($MDL[$iter]) ;
  1509. }
  1510. }
  1511. for $iter (0..$TotalCustemChips-1) {
  1512. # generate discrete dram
  1513. if (&IsDiscreteDram($MDL[$iter])) {
  1514. $filesize = $filesize + &write_tag_one_element ($MDL[$iter]) ;
  1515. }
  1516. }
  1517. # $filesize = $filesize + 4 ;
  1518. # print "2.file size is $filesize \n";
  1519. print FILE pack("L", $filesize) ;
  1520. close (FILE) ;
  1521. print "$info_tag is generated!\n";
  1522. return ;
  1523. }
  1524. #****************************************************************************************
  1525. # subroutine: write_tag_one_element
  1526. # output binary for emi structure
  1527. # porting: only when emi structure are modified
  1528. # input: $dev - MDL object
  1529. # return: void
  1530. #****************************************************************************************
  1531. sub write_tag_one_element {
  1532. my $dev = shift;
  1533. my $type = "0x".$dev->mcp_type.$dev->ddr->type_id ;
  1534. my $fs = 0 ;
  1535. print FILE pack ("L", hex (lc($dev->sub_version))) ; # Sub_version checking for flash tool
  1536. $fs = $fs + 4 ;
  1537. print FILE pack("L", hex($type)); #type
  1538. $fs = $fs + 4 ;
  1539. print FILE pack ("L", scalar($dev->mcp_id_len)) ; # EMMC ID checking length
  1540. $fs = $fs + 4 ;
  1541. print FILE pack ("L", scalar($dev->fw_id_len)) ; # FW ID checking length
  1542. $fs = $fs + 4 ;
  1543. $_ = $dev->mcp_id_str ;
  1544. if (/(\w+),(\w+),(\w+),(\w+),(\w+),(\w+),(\w+),(\w+),(\w+),(\w+),(\w+),(\w+),(\w+),(\w+),(\w+),(\w+)/) {
  1545. print FILE pack ("C", hex ($1)) ; #id
  1546. print FILE pack ("C", hex ($2)) ;
  1547. print FILE pack ("C", hex ($3)) ;
  1548. print FILE pack ("C", hex ($4)) ;
  1549. print FILE pack ("C", hex ($5)) ;
  1550. print FILE pack ("C", hex ($6)) ;
  1551. print FILE pack ("C", hex ($7)) ;
  1552. print FILE pack ("C", hex ($8)) ;
  1553. print FILE pack ("C", hex ($9)) ;
  1554. print FILE pack ("C", hex ($10)) ;
  1555. print FILE pack ("C", hex ($11)) ;
  1556. print FILE pack ("C", hex ($12)) ;
  1557. print FILE pack ("C", hex ($13)) ;
  1558. print FILE pack ("C", hex ($14)) ;
  1559. print FILE pack ("C", hex ($15)) ;
  1560. print FILE pack ("C", hex ($16)) ;
  1561. $fs = $fs + 16 ;
  1562. }
  1563. $_= $dev->fw_id_str;
  1564. if (/(\w+),(\w+),(\w+),(\w+),(\w+),(\w+),(\w+),(\w+)/) {
  1565. print FILE pack ("C", hex ($1)) ; #fw id
  1566. print FILE pack ("C", hex ($2)) ;
  1567. print FILE pack ("C", hex ($3)) ;
  1568. print FILE pack ("C", hex ($4)) ;
  1569. print FILE pack ("C", hex ($5)) ;
  1570. print FILE pack ("C", hex ($6)) ;
  1571. print FILE pack ("C", hex ($7)) ;
  1572. print FILE pack ("C", hex ($8)) ;
  1573. $fs = $fs + 8 ;
  1574. }
  1575. print FILE pack ("L", hex (lc($dev->data('EMI_CONA_VAL')))) ; # EMI_CONA_VAL
  1576. $fs = $fs + 4 ;
  1577. print FILE pack ("L", hex (lc($dev->data('EMI_CONH_VAL')))) ; # EMI_CONH_VAL
  1578. $fs = $fs + 4 ;
  1579. print FILE pack ("L", hex (lc($dev->actiming(0)))) ; # AC Timing U 00
  1580. $fs = $fs + 4 ;
  1581. print FILE pack ("L", hex (lc($dev->actiming(1)))) ; # AC Timing U 01
  1582. $fs = $fs + 4 ;
  1583. print FILE pack ("L", hex (lc($dev->actiming(2)))) ; # AC Timing U 02
  1584. $fs = $fs + 4 ;
  1585. print FILE pack ("L", hex (lc($dev->actiming(3)))) ; # AC Timing U 03
  1586. $fs = $fs + 4 ;
  1587. print FILE pack ("L", hex (lc($dev->actiming(4)))) ; # AC Timing U 04
  1588. $fs = $fs + 4 ;
  1589. print FILE pack ("L", hex (lc($dev->actiming(5)))) ; # AC Timing U 05
  1590. $fs = $fs + 4 ;
  1591. print FILE pack ("L", hex (lc($dev->actiming(6)))) ; # AC Timing U 06
  1592. $fs = $fs + 4 ;
  1593. print FILE pack ("L", hex (lc($dev->actiming(7)))) ; # AC Timing U 07
  1594. $fs = $fs + 4 ;
  1595. print FILE pack ("Q", hex (lc($dev->dram_rank_size(0)))) ; # DRAM_RANK_SIZE[4]
  1596. print FILE pack ("Q", hex (lc($dev->dram_rank_size(1)))) ;
  1597. print FILE pack ("Q", hex ("0")) ;
  1598. print FILE pack ("Q", hex ("0")) ;
  1599. $fs = $fs + 32 ;
  1600. print FILE pack ("L", hex (lc($dev->data('EMI_CONF_VAL')))) ; # EMI_CONF_VAL
  1601. $fs = $fs + 4 ;
  1602. print FILE pack ("L", hex (lc($dev->data('CHN0_EMI_CONA_VAL')))) ; # CHN0_EMI_CONA_VAL
  1603. $fs = $fs + 4 ;
  1604. print FILE pack ("L", hex (lc($dev->data('CHN1_EMI_CONA_VAL')))) ; # CHN1_EMI_CONA_VAL
  1605. $fs = $fs + 4 ;
  1606. print FILE pack ("L", hex (lc($dev->cbt_mode('id')))) ; # MODE_EXTERN_VAL
  1607. $fs = $fs + 4 ;
  1608. print FILE pack ("L", hex ("0")) ; #reserved[6]
  1609. print FILE pack ("L", hex ("0")) ;
  1610. print FILE pack ("L", hex ("0")) ;
  1611. print FILE pack ("L", hex ("0")) ;
  1612. print FILE pack ("L", hex ("0")) ;
  1613. print FILE pack ("L", hex ("0")) ;
  1614. $fs = $fs + 24 ;
  1615. if (&IsDdrType($dev, "LPDDR3") || &IsDdrType($dev, "LPDDR4") || &IsDdrType($dev, "LPDR4X") || &IsDdrType($dev, "LPDR4P")) {
  1616. print FILE pack ("L", hex (lc($dev->data('MODE_REG5')))) ; # LPDDR3_MODE_REG5
  1617. $fs = $fs + 4 ;
  1618. }
  1619. print FILE pack ("L", hex (lc($dev->data('PIN_MUX_TYPE')))) ; # pin mux type for tablet
  1620. $fs = $fs + 4 ;
  1621. # print "1.file size is $fs \n";
  1622. return $fs;
  1623. }
  1624. 1;