 //==================================================================================
// The information contained herein is the exclusive property of
// Generalplus Technology Co. And shall not be distributed, reproduced,
// or disclosed in whole in part without prior written permission.
//       (C) COPYRIGHT 2010   Generalplus TECHNOLOGY CO.                            
//                   ALL RIGHTS RESERVED
// The entire notice above must be reproduced on all authorized copies.
//==================================================================================
//==========================================================================
// Program Name: main.asm
// Applied body: GPL95100UA Series Body
// Programmer  : 
// Description : Rom code startup
// History version
// Rev #     Date       Who     Comments
// -----  -----------  ------   --------------------------------------------
// 1.0     2015/09/07  			Oringinal Version
// 1.1 	   2017/03/01    KC     Add function : Release/Writeback write protect in F_SPIF_QuadMode_Init for GP SPIF
// 1.2	   2017/04/05	 KC		1. Add more supporting SPI flash
//								2. Modify F_CleanRxFifo function
// 1.3	   2017/10/03	 KC		1. Add GPR25L1605E/GPR25L1603E/GPR25L0805E/KH25L1633E
//								2. Modify CS duration setting from 7 to 2	
// 1.4	   2018/01/31    Frank  Add MD25Q16C/MD25Q80C
// 1.5	   2018/02/23	 KC		1. Add MD25Q128C
//                              2. Add library tag
// -----  -----------  ------   --------------------------------------------

//==================================================================================
// Include file area
//==================================================================================
.include GPL951_Body.inc

//=============================================
//Constant Define Area
//=============================================
.define PLL48M	0		// 0 : PLL 96M		//default
						// 1 : PLL 48M
.define GPL951_SPIF_Driving	0x0AAA			//0x0000(4mA), 0x0555(8mA), 0x0AAA(12mA), 0x0FFF(16mA)
											//default is 0x0AAA(12mA)
											//SIO3[11:10], SIO2[9:8], CSB[7:6], SCK[5:4], SIO1[3:2], SIO0[1:0]

//=============================================
// Device select definition, User need select
// correct SPI Flash series & device.
//=============================================
.define GPR_Series 		1
	.define GPR25L25605F		1		//test pass
	.define GPR25L12805F		0		//test pass
	.define GPR25L6403F			0		//test pass
	.define GPR25L3203F			0		//test pass
	.define	GPR25L1605E			0		//test pass
	.define GPR25L1603E			0		//test pass, only support up to 84MHz	
	.define	GPR25L0805E			0		//test pass
	
.define KH_Series 		0
	.define KH25L25635F			1
	.define KH25L12833F			0		//test pass
	.define KH25L12835F			0
	.define KH25L1633E			0		//test pass, only support up to 84MHz	

.define Winbond_Series 	0
	.define W25Q256FV			1		//test pass, no support Release/Writeback write protect
	.define W25Q128FV			0		//test pass, no support Release/Writeback write protect
	.define W25Q64FV			0		//test pass, no support Release/Writeback write protect	
	
.define MD_Series		0
	.define MD25Q128C			1		//test pass, no support Release/Writeback write protect
	.define MD25Q16C			0		//test pass, no support Release/Writeback write protect	
	.define MD25Q80C			0		//test pass, no support Release/Writeback write protect	 	
	

//=============================================
// Device SR and CR detail definition
// User can select SPI flash driving here, 
// but do not change others parameter.
//=============================================
//********************************************************
//  GPR series SPI flash
//********************************************************
							// ID type xx size, just care ID and size	
							// C2 20 xx 19																 
.define GPR25L25605F_ID		0xC219   
.define GPR25L25605F_SR 	0x0040
//.define GPR25L25605F_CR 	0x0085			//DUMMY CYCLE 8, DRIVER STRENGTH 10OHM
//.define GPR25L25605F_CR 	0x0086			//DUMMY CYCLE 8, DRIVER STRENGTH 15OHM
.define GPR25L25605F_CR 	0x0087			//DUMMY CYCLE 8, DRIVER STRENGTH 30OHM, Default
//.define GPR25L25605F_CR 	0x0082			//DUMMY CYCLE 8, DRIVER STRENGTH 60OHM

.define GPR25L12805F_ID		0xC218
.define GPR25L12805F_SR 	0x0040
//.define GPR25L12805F_CR 	0x0085			//DUMMY CYCLE 8, DRIVER STRENGTH 10OHM
//.define GPR25L12805F_CR 	0x0086			//DUMMY CYCLE 8, DRIVER STRENGTH 15OHM
.define GPR25L12805F_CR 	0x0087			//DUMMY CYCLE 8, DRIVER STRENGTH 30OHM, Default
//.define GPR25L12805F_CR 	0x0082			//DUMMY CYCLE 8, DRIVER STRENGTH 60OHM

.define GPR25L6403F_ID		0xC217
.define GPR25L6403F_SR 		0x0040
.define GPR25L6403F_CR 		0x0040			//DUMMY CYCLE 10, DRIVER STRENGTH 1, Default
//.define GPR25L6403F_CR 	0x0041			//DUMMY CYCLE 10, DRIVER STRENGTH 1/4

.define GPR25L3203F_ID		0xC216
.define GPR25L3203F_SR 		0x0040
.define GPR25L3203F_CR 		0x0000			//DUMMY CYCLE 6, DRIVER STRENGTH 1, Default
//.define GPR25L3203F_CR 	0x0001			//DUMMY CYCLE 6, DRIVER STRENGTH 1/4

.define GPR25L1605E_ID		0xC215
.define GPR25L1605E_SR 		0x0040
.define GPR25L1605E_CR 		0x8000			//Null

.define GPR25L1603E_ID		0xC215
.define GPR25L1603E_SR 		0x0040
.define GPR25L1603E_CR 		0x8000			//Null

.define GPR25L0805E_ID		0xC214
.define GPR25L0805E_SR 		0x0040
.define GPR25L0805E_CR 		0x8000			//Null

//********************************************************
//  KH series SPI flash
//********************************************************	
.define KH25L25635F_ID		0xC219
.define KH25L25635F_SR 		0x0040

.define KH25L12833F_ID		0xC218
.define KH25L12833F_SR 		0x0040
.define KH25L12833F_CR 		0x0040			//DUMMY CYCLE 8, DRIVER STRENGTH 1, Default
//.define KH25L12833F_CR 	0x0041			//DUMMY CYCLE 8, DRIVER STRENGTH 1/4

.define KH25L12835F_ID		0xC218
.define KH25L12835F_SR 		0x0040
//.define KH25L12835F_CR 	0x0086			//DUMMY CYCLE 8, DRIVER STRENGTH 15OHM, Impedance at VCC/2
//.define KH25L12835F_CR 	0x0085			//DUMMY CYCLE 8, DRIVER STRENGTH 20OHM, Impedance at VCC/2
.define KH25L12835F_CR 		0x0087			//DUMMY CYCLE 8, DRIVER STRENGTH 30OHM, Impedance at VCC/2, Default
//.define KH25L12835F_CR 	0x0083			//DUMMY CYCLE 8, DRIVER STRENGTH 45OHM, Impedance at VCC/2
//.define KH25L12835F_CR 	0x0082			//DUMMY CYCLE 8, DRIVER STRENGTH 60OHM, Impedance at VCC/2
//.define KH25L12835F_CR 	0x0081			//DUMMY CYCLE 8, DRIVER STRENGTH 90OHM, Impedance at VCC/2

.define KH25L1633E_ID		0xC215
.define KH25L1633E_SR 		0x0040
.define KH25L1633E_CR 		0x8000			//Null

//********************************************************
//  Winbond series SPI flash
//********************************************************	
.define W25Q256FV_ID		0xEF19
.define W25Q256FV_SR 		0x0000
.define W25Q256FV_SR1 		0x0002
//.define W25Q256FV_SR2 	0x0000			//DUMMY CYCLE 4, DRIVER STRENGTH 1
//.define W25Q256FV_SR2 	0x0020			//DUMMY CYCLE 4, DRIVER STRENGTH 3/4
//.define W25Q256FV_SR2 	0x0040			//DUMMY CYCLE 4, DRIVER STRENGTH 2/4
.define W25Q256FV_SR2 		0x0060			//DUMMY CYCLE 4, DRIVER STRENGTH 1/4, Default

.define W25Q128FV_ID		0xEF18
.define W25Q128FV_SR 		0x0000
.define W25Q128FV_SR1 		0x0002
//.define W25Q128FV_SR2 	0x0000			//DUMMY CYCLE 4, DRIVER STRENGTH 1
//.define W25Q128FV_SR2 	0x0020			//DUMMY CYCLE 4, DRIVER STRENGTH 3/4
//.define W25Q128FV_SR2 	0x0040			//DUMMY CYCLE 4, DRIVER STRENGTH 2/4
.define W25Q128FV_SR2 		0x0060			//DUMMY CYCLE 4, DRIVER STRENGTH 1/4, Default

.define W25Q64FV_ID			0xEF17			
.define W25Q64FV_SR 		0x0000
.define W25Q64FV_SR1 		0x0002
//W25Q64FV DUMMY CYCLE 4, and no DRIVER STRENGTH setting


//********************************************************
//  MD series SPI flash
//********************************************************	
.define MD25Q128C_ID		0xC818			
.define MD25Q128C_SR 		0x0000
.define MD25Q128C_SR1 		0x0002
.define MD25Q128C_SR2 		0x0040			//DRIVER STRENGTH 1/2, Default

.define MD25Q16C_ID			0xC815			
.define MD25Q16C_SR 		0x0000
.define MD25Q16C_SR1 		0x0002

.define MD25Q80C_ID			0xC814			
.define MD25Q80C_SR 		0x0000
.define MD25Q80C_SR1 		0x0002



.define	C_SPIF_TimeOut_Cn 40	//ms
.define C_SPIF_RX_BC 0x0080

//=============================================
//Public declare Area
//=============================================
.public MoveStartAddr
.public MoveEndAddr

//=============================================
//RAM Define Area
//=============================================
.ram_bank0

.define R_CheckSumL	0x00
.define R_CheckSumM 0x01
.define R_CalcSumL	0x02
.define R_CalcSumM	0x03
//.var R_CalcSumH	0x04
.define R_EndAddrL	0x05
.define R_EndAddrH	0x06
.define R_SPIF_HiCLK_Limit	0x07			//1~6 => sys/1(96M) ~ sys/6(16M)
.define TimeOutCn	0x08
.define TimeOutCn1	0x09
.define R_SR_Record	0x0A			//record original SR value
//=============================================
//Program Area
//=============================================
.TEXT
//************************************************************//
//Description : SPIF initial and verify SPIF timing
//function : main
//      1. Into SPIF 16M/1bit auto mode to test SPIF timing, timing pass-> setting SPIF Quad mode, if fail/timeout, goto sleep
//      2. 4bit automode calibration SPIF CLK(96M/48M/32M/24M/19M/16M) and timing via verify GP header, pass goto step 6
//      3. 2bit automode calibration SPIF CLK(96M/48M/32M/24M/19M/16M) and timing via verify GP header, pass goto step 6
//      4. 1bit automode calibration SPIF CLK(96M/48M/32M/24M/19M/16M) and timing via verify GP header, pass goto step 6
//      5. if step 2/3/4 fail, goto sleep
//      6. calibration SPI timing via step2/3/4 setting (verify user code 0x9040~0xffff), pass goto user code, fail goto sleep
//************************************************************//
GPL951_RomCodeInRAM:	.section .code
MoveStartAddr:
Calibration:
	FIQ off
	IRQ off

.if (GPR_Series&GPR25L1603E)|(KH_Series&KH25L1633E)
//PLL 48M Low speed application
?L_CheckPLL_State:
	r1 = [P_Power_State]
	r1 &= 0x0007
	jz ?L_CheckPLL_State
.if PLL48M	
	r1 = 48 / 4									// PLL clock =48MHz
.else
	r1 = 84 / 4									// GPR25L1603E/KH25L1633E only support up to 84MHz
.endif	
	r1 |= 0x0600								// SPIF CLK = PLL/4 = 12MHz
	[P_PLL_Sel] = r1
	r1 = C_PLL_Fast_En + C_SYSCLK_SRC_Div1		// SYS = PLL/1 = 48
	[P_Clock_Ctrl] = r1	
?L_CheckPLL_Stable:
	r1 = [P_Power_State]
	r1 &= 0x0007
	cmp r1, 0x0002
	jne ?L_CheckPLL_Stable	

.else
.if PLL48M
//PLL 48M Low speed application
?L_CheckPLL_State:
	r1 = [P_Power_State]
	r1 &= 0x0007
	jz ?L_CheckPLL_State
	r1 = 48 / 4									// PLL clock =48MHz
	r1 |= 0x0600								// SPIF CLK = PLL/4 = 12MHz
	[P_PLL_Sel] = r1
	r1 = C_PLL_Fast_En + C_SYSCLK_SRC_Div1		// SYS = PLL/1 = 48
	[P_Clock_Ctrl] = r1	
?L_CheckPLL_Stable:
	r1 = [P_Power_State]
	r1 &= 0x0007
	cmp r1, 0x0002
	jne ?L_CheckPLL_Stable	
.endif
.endif	
	
	call F_SPIF_Calibration_Init
	call F_SPIF_QuadMode_Init		//SPIF Quad Mode initial; return R1, R1 = 0(FAIL)/1(PASS), if PASS go to Calibration
	call F_SPI_Set_4Bit	 			//4bit Auto mode calibration
	call F_SPIF_Calibration			//return R1, R1 = 0(FAIL)/1(PASS), calibration SPIF mode/SPIF CLK, if PASS go to user code verify 
	cmp r1,1
	je L_SPIF_Calibration_Pass
	call F_SPI_Set_2Bit	 		 	//2bit Auto mode calibration
	call F_SPIF_Calibration			//return R1, R1 = 0(FAIL)/1(PASS), calibration SPIF mode/SPIF CLK, if PASS go to user code verify 
	cmp r1,1
	je L_SPIF_Calibration_Pass	
	call F_SPI_Set_1Bit	 			//1bit Auto mode calibration
	call F_SPIF_Calibration			//return R1, R1 = 0(FAIL)/1(PASS), calibration SPIF mode/SPIF CLK, if PASS go to user code verify 
	cmp r1,1
	je L_SPIF_Calibration_Pass	
	goto F_SPIF_Failure
	
L_SPIF_Calibration_Pass:			//SPIF calibration pass, test User code checksum
	call F_UserCode_Verify			//return 1 : verify pass
	cmp r1, 1
	je  L_SPIF_PASS
 	r1 = [P_SPIFC_TIMING]			//next timing setting
 	r1 &= 0x0007
	r1 -= 1
	cmp	r1, 0x0000
	jmi	L_SPI_TimingFail?	
	r2 = [P_SPIFC_TIMING]
	r2 &= ~0x0007
	r2 |= r1
	[P_SPIFC_TIMING] = r2
	goto L_SPIF_Calibration_Pass
L_SPI_TimingFail?:	
	goto F_SPIF_Failure	
	
L_SPIF_PASS:			
	retf  


//************************************************************//
//Description : Auto mode check user SPIF 0x9040~0xFFFF checksume
//function : F_UserCode_Verify
//return : 0 - SPIF timing err
//		   1 - SPIF timing pass
//************************************************************//
F_UserCode_Verify:
	r5 = 0x0010
	r1 = 0x9000
	r2 = T_GP_HEADER	
	call F_Header_Verify
	cmp r1,0
	je F_UserCode_Verify
	call F_Header_Get_Para
	r1 = 0
	[R_CalcSumL] = r1			//clear checksum
	[R_CalcSumM] = r1	
	r2 = 0x9040			//start addr L
	r3 = 0				//start	addr H
L_Caculator:
	DS = r3
	r4 = [R_CalcSumL]
	r1 = DS:[r2]
	[P_Byte_Swap] = r1	//reverse b[15:8] to b[7:0]
	r1 &= 0x00ff		//get low byte 
	r4 += r1			//add low byte
	[R_CalcSumL] = r4
	r4 = [R_CalcSumM]
	r4 += 0,carry
	[R_CalcSumM] = r4
	r4 = [R_CalcSumL]
	r1 = [P_Byte_Swap]	
	r1 &= 0x00ff		//get high byte
	r4 += r1			//add high byte
	[R_CalcSumL] = r4
	r4 = [R_CalcSumM]
	r4 += 0,carry
	[R_CalcSumM] = r4
	r5 = [R_EndAddrL]	//checksum end addr L
	r2 += 1
	r3 += 0,carry
	cmp	r2,r5
	jne	L_Caculator		
L_CheckAddrH:			//Addr L equal and then check Addr H
	r5 = [R_EndAddrH]	//checksum end addr H
	cmp r3,r5
	jne	L_Caculator
L_CompareSum:
	r1= [R_CalcSumL]
	//r2 =[R_CheckSumL]
	r3 = 0x9010
	r2 = [r3]
	cmp r1,r2
	jne	?L_Failure
	r1= [R_CalcSumM]
	//r2 =[R_CheckSumM]
	r3 = 0x9011
	r2 = [r3]	
	cmp r1,r2
	jne	?L_Failure 	
?L_Pass:
	r1 = 1
	retf	
?L_Failure:
	r1 = 0
	retf


//************************************************************//
//Description : SPIF check failure, system will into sleep mode
//function : F_SPIF_Failure
//return : NC
//************************************************************//
F_SPIF_Failure:			//SPIF failure, syster into sleep
	call F_SPIF_Calibration_Done
	nop
	nop
	nop   
F_Enter_Sleep:
	r1 = 0						//Disable all Peripheral function
	[P_IOA_Mux] = r1
	[P_IOB_Mux] = r1
	[P_IOC_Mux] = r1
	[P_IOD_Mux] = r1
	[P_IOE_Mux] = r1
	[P_IOF_Mux] = r1
	[P_IOA_Dir] = r1			//Change all IO to input pull state
	[P_IOA_Attrib] = r1	
	[P_IOB_Dir] = r1
	[P_IOB_Attrib] = r1							
	[P_IOC_Dir] = r1
	[P_IOC_Attrib] = r1	
	[P_IOD_Dir] = r1
	[P_IOD_Attrib] = r1	
	[P_IOE_Dir] = r1
	[P_IOE_Attrib] = r1	
	[P_IOF_Dir] = r1
	[P_IOF_Attrib] = r1	
	[P_IOAB_KCIEN] = r1			//Disable all IO wakeup
	[P_IOC_KCIEN] = r1	
	[P_IOE_KCIEN] = r1	
	[P_IOF_KCIEN] = r1
	r1 = 0xffff					
	[P_INT_Status1] = r1		//clear all flag
	[P_INT_Status2] = r1
	[P_INT_Status3] = r1	
	[P_IOAB_KCIFC] = r1	
	[P_IOC_KCIFC] = r1	
	[P_IOE_KCIFC] = r1	
	[P_IOF_KCIFC] = r1									
//	r1 = 0xA00A					//Entering sleep
//	[P_SLEEP] = r1	
//	NOP
//	NOP
//	NOP
//	goto F_Enter_Sleep
	r1 = [P_PM_Ctrl]			//shut down, 0x7809b14(P_PM_Ctrl) set 0->1->0 and then 0x7803b15(P_System_Ctrl) set 0 to shut down system
	r1 &= ~0x4000
	[P_PM_Ctrl] = r1			//0x7809b14 = 0
	r1 = [P_PM_Ctrl]
	r1 |= 0x4000
	[P_PM_Ctrl] = r1			//0x7809b14 = 1	
	r1 = [P_PM_Ctrl]			
	r1 &= ~0x4000
	[P_PM_Ctrl] = r1			//0x7809b14 = 0
	
	r1 = [P_SYS_Ctrl]
	r1 &= ~0x8000
	[P_SYS_Ctrl] = r1		//0x7803b15 = 0
	nop
	nop
	nop

.public	T_GP_HEADER
T_GP_HEADER:
//		Word0   Word1   Word2   Word3   Word4   Word5   Word6   Word7     start	
	.DW 0x5047, 0x532D, 0x4950, 0x2D46, 0x4548, 0x4441, 0x5245, 0x2D2D	//0x9000
	.DW 0x3130, 0x3332, 0x3534, 0x3736, 0x3938, 0x6261, 0x6463, 0x6665	//0x9008
//	.DW	SumL  , SumH  , SumL  , SumH  , flag  , clk   , timing, mode	//0x9010
//	.DW EndAdr, EndAdr, CLK   , NC	  , NC	  , NC	  , NC	  , NC	  	//0x9018
//	.DW NC	  , NC	  , NC	  , NC	  , NC	  , NC	  , NC	  , NC	  	//0x9020
//	.DW NC	  , NC	  , NC	  , NC	  , NC	  , NC	  , NC	  , NC	  	//0x9028
//	.DW NC	  , NC	  , NC	  , NC	  , NC	  , NC	  , NC	  , NC	  	//0x9030
//	.DW NC	  , NC	  , NC	  , NC	  , NC	  , NC	  , NC	  , NC	  	//0x9038


//************************************************************//
//Description	: Initial SPIF parameter and enable 1 bit auto mode
//Function		: F_SPIF_Calibration_Init
//Parameter		: none
//Destory       : R1,R2
//Return		: none
//************************************************************//
_SPIF_Calibration_Init:
F_SPIF_Calibration_Init:
	r1 = GPL951_SPIF_Driving
	[P_IOD_Drv] = r1
	r1 = 0x0002
 	[P_IOD_Mux] = r1 					//IOD as SPIF
  	r1 = [P_PLL_Sel]
 	r1 &= ~0x3e00						//mask clk select
 	r1 |= 0x0e00						// 192/(7+1)/2 = 12M
 	[P_PLL_Sel] = r1	
 	r1 = [P_SPIFC_TIMING]				//set initial timing 7
	r1 &= 0xf808
	r1 |= 0x0207						//SPIF CS duration setting 2*(2+1)
	[P_SPIFC_TIMING] = r1
	r1 = [P_SPIFC_Ctrl2]
	r1 &= ~C_SPIFC_EN
	[P_SPIFC_Ctrl2] = r1 				//Disable SPIF
	r1 = 0x0000
	[P_SPIFC_ADDRL] = r1
	[P_SPIFC_ADDRH] = r1
	[P_SPIFC_TX_BC] = r1
	//r2 = 0x0010						//auto mode need set 0x0010?
	r2 = 0x0002							//for dummy read issue
	[P_SPIFC_RX_BC] = r2 		
	r1 = C_SPIF_TransWithoutEnhanByte + C_SPIF_DummyClk_0cycle
	[P_SPIFC_PARA] = r1	
 	r1 = 0x0003
	[P_SPIFC_CMD] = r1	
 	r1 = C_SPIF_MIO_1bit + C_SPIF_Auto_Mode + C_SPIF_CMIO_1bit + C_SPIF_AMIO_1bit + C_SPIF_NotIgnoreLastClk +C_SPIF_CLK_PreStateLo
	[P_SPIFC_Ctrl1] = r1 		
 	r1 = [P_SPIFC_Ctrl2]
	r1 |= C_SPIFC_EN
	[P_SPIFC_Ctrl2] = r1 				//Enable SPIF
	call F_SPIF_TimerEn

 	call F_SPIF_DummyRead
 	nop
 	nop
 	nop
	r2 = 0x0010							//auto mode need set 0x0010?
	[P_SPIFC_RX_BC] = r2 	
 	nop
 	nop
 	nop
 	retf

//************************************************************//
//Description	: SPIF calibratio done
//Function		: F_SPIF_Calibration_Done
//Parameter		: none
//Destory       : R1
//Return		: none
//************************************************************//
F_SPIF_Calibration_Done:
	call F_SPIF_TimerDis
	retf

//************************************************************//
//Description 	: Test 1 bit SPIF timing, and change to Quad mode
//Function		: F_SPIF_QuadMode_Init
//Parameter		: none
//Destory       : R1~R5
//Return		: R1 : 1 - PASS
//					 : 0 - FAILURE
//************************************************************//
L_TimingErr1:
	goto L_TimingErr

_SPIF_QuadMode_Init:
F_SPIF_QuadMode_Init:
	r5 = 0x0010
	r1 = 0x9000
	r2 = T_GP_HEADER
L_SPIF_QuadMode_Init:	
	call F_Header_Verify
	cmp r1,0
	je L_TimingErr1
	call F_Header_Get_Para
	call F_SPIF_RDID					//Read ID to check SPIF density(return r2)
	cmp	r1,0
	je L_TimingErr1	
	push r2 to [SP]

// 2017/03/01 add
.if GPR_Series|KH_Series
	r1 = [P_IOD_Buffer]
	r1 |= 0x20
	[P_IOD_Buffer] = r1					//SIP2 pull high
	call F_SPIF_RDSR				
	[R_SR_Record] = r1					//Record original SR value		
L_Disable_SRWD:
	r1 = [R_SR_Record]
	r1 &= ~0x0080						//Disable status register write protect
	call F_SPIF_WRSR
	call F_SPIF_RDSR
	r1 &= 0x0080
	jnz L_Disable_SRWD
.endif	
// 2017/03/01 add end	
	
	r1 = T_SPIF_Table					//Get ID define 
	r1 = [r1]		
	pop r2 from [SP]
	cmp r1, r2
	je ?L_ID_Correct 
	goto ID_Failure
?L_ID_Correct:	
	r2 &=0x00ff
	cmp	r2,0x19
	jmi	L_Not_4ByteMode
	r1 = [P_SPIFC_Ctrl2]				//Enable 4th address
	r1 |= C_SPIFC_4thAdr_EN
	[P_SPIFC_Ctrl2] = r1
	call F_Set_4ByteMode				//Set SPIF 4Byte mode
	cmp	r1,0
	je L_TimingErr	
L_Not_4ByteMode:
.if (Winbond_Series|MD_Series)
	call F_Exit_QPI
	call F_SPIF_RDSR1	
.endif
	call F_SPIF_SWRstEn					//Reset Enable
	call F_SPIF_SWRst					//Reset,	
.if (Winbond_Series|MD_Series)
	.if W25Q256FV|W25Q128FV	
	r1 = T_SPIF_Table					//Get SR3 setting
	r1 += 3
	r1 = [r1]	
	cmp	r1, 0x8000						//0x8000 means no SR3
	je	L_WaitRstStable
	call F_SPIF_WRSR3					//Write SR3 to set driving current
	.endif
.endif	
L_WaitRstStable:	
	call F_Set_QuadMode					//Set Quad bit
	cmp	r1,0
//	je L_TimingErr
	je L_WaitRstStable	

// 2017/03/01 add
.if GPR_Series|KH_Series
	r1 = [P_IOD_Buffer]
	r1 |= 0x20
	[P_IOD_Buffer] = r1					//SIP2 pull high
L_Set_Original_SR:	
	r1 = [R_SR_Record]					//Set original status register
	r1 |= 0x40							//QE bit	
	call F_SPIF_WRSR
	call F_SPIF_RDSR
	r1 &= 0x00BC
	r2 = [R_SR_Record]
	r2 &= 0x00BC
	cmp r1,r2
	jne L_Set_Original_SR
	r1 = [P_IOD_Buffer]
	r1 &= ~0x20
	[P_IOD_Buffer] = r1					//release SIP2
.endif
// 2017/03/01 add end

	r1 = 1								//SPIF Quad Mode PASS
	retf
L_TimingErr:
 	r1 = [P_SPIFC_TIMING]				//next timing setting
 	r1 &= 0x0007
	r1 -= 1
	cmp	r1, 0x0000
	jmi	L_SPI_Check4byte?	
	r2 = [P_SPIFC_TIMING]
	r2 &= ~0x0007
	r2 |= r1
	[P_SPIFC_TIMING] = r2
	goto L_SPIF_Next_Timing
L_SPI_Check4byte?:
	r1 = [P_SPIFC_Ctrl2]
	r1 &= 0xff00
	cmp r1, 0xff00
	je	L_SPI_Fail?
	r1 |= 0xff01
	[P_SPIFC_Ctrl2] = r1
 	r1 = [P_SPIFC_TIMING]
 	r1 |= 0x0007
 	[P_SPIFC_TIMING] = r1	
	goto F_SPIF_QuadMode_Init
L_SPI_Fail?:	  	
	r1 = 0								//SPIF test failure
	retf
L_SPIF_Next_Timing:	
	R1 = [0x9010]						//dummy read
	nop
	nop
	goto F_SPIF_QuadMode_Init


//************************************************************//
// SPI Flash ID table define is different with RDID.
// Please check Device definition in calibration.asm, and 
// select the correct SPI Flash series & device.
//************************************************************//
ID_Failure:
	r1 = C_WDT_Clear
	[P_WatchDog_Clear] = r1
	goto ID_Failure


//************************************************************//
//Description 	: Calibration SPIF CLK/timing via SPIF Mode(1/2/4bit)
//Function		: F_SPIF_Calibration
//Parameter		: R_SPIF_HiCLK_Limit
//Destory       : R1~R5
//Return		: R1 : 1 - PASS
//					 : 0 - FAILURE
//************************************************************//
_SPIF_Calibration:
F_SPIF_Calibration:
	//r2 = [R_SPIF_HiCLK_Limit]
	r1 = [P_PLL_Sel]
 	r1 &= ~0x3e00						//mask clk select
 	r1 |= 0x00							// 96M
 	[P_PLL_Sel] = r1	
L_SPIF_Change_CLK: 	
 	r1 = [P_SPIFC_TIMING]				//set initial timing 7
	r1 |= 0x0007
	[P_SPIFC_TIMING] = r1
	r1 = [0x9010]						//dummy read
L_SPIF_Calibration:	
	r5 = 0x0010
	r1 = 0x9000
	r2 = T_GP_HEADER
L_Calibration:	
	call F_Header_Verify
	cmp r1,0
	je L_TimingErr?
	r1 = 1								//SPIF Calibration PASS
	retf
L_TimingErr?:
 	r1 = [P_SPIFC_TIMING]				//next timing setting
 	r1 &= 0x0007
	r1 -= 1
	cmp	r1, 0x0000
	jmi	L_SPI_CLK_Fail?	
	r2 = [P_SPIFC_TIMING]
	r2 &= ~0x0007
	r2 |= r1
	[P_SPIFC_TIMING] = r2
	goto L_SPIF_Next_Timing?
L_SPI_CLK_Fail?:			
	r1 = [P_PLL_Sel]
	r1 &= 0x3e00						
	//cmp r1,0x0200						//low limit 192/(1+1)/2 = 48M
	//cmp r1,0x0600						//low limit 192/(3+1)/2 = 24M
	//cmp r1,0x0a00						//low limit 192/(5+1)/2 = 16M
	cmp r1,0x1e00						//low limit 192/(7+1)/2 = 12M
	je	L_CalibrationFail?
	r1 = r1 + 0x0200
	r2 = [P_PLL_Sel]
	r2 &= ~0x3e00
	r2 |= r1
	[P_PLL_Sel] = r2 
	goto L_SPIF_Change_CLK
L_CalibrationFail?:	
	r1 = 0								//SPIF Calibration failure
	retf
L_SPIF_Next_Timing?:	
	R1 = [0x9010]
	nop
	nop
	goto L_SPIF_Calibration
	

//************************************************************//
//Description 	: SPIF set 4 bit mode parameters
//Function		: F_SPI_Set_4Bit
//Parameter		: none
//Destory       : R1
//Return		: none
//************************************************************//
F_SPI_Set_4Bit:
	r1 = [P_SPIFC_Ctrl2]
	r1 &= ~C_SPIFC_EN
	[P_SPIFC_Ctrl2] = r1 		//Disable SPIF
	r1 = 0x0000
	[P_SPIFC_ADDRL] = r1
	[P_SPIFC_ADDRH] = r1
	[P_SPIFC_TX_BC] = r1
	//r1 = 0x0010					//auto mode need set 0x0010?
	//r1 = 0x0100
	r1 = C_SPIF_RX_BC
	[P_SPIFC_RX_BC] = r1 		
//4bit mio, 1bit cio, 4bit aio, 4 dummy cycle, 2 enhance byte
.if (Winbond_Series|MD_Series)
	r1 = T_SPIF_Table	//Get GPL951 dummy cycle setting
	r1 += 4
	r1 = [r1]
	r1 |= C_SPIF_TransWithEnhanByte + 0x00A0
.endif
.if GPR_Series|KH_Series
//	r1 = C_SPIF_TransWithEnhanByte + C_SPIF_Enhance_bit0 + C_SPIF_Enhance_bit1 +C_SPIF_Enhance_bit2 + C_SPIF_Enhance_bit3 + GPL951_DummyCycle
	r1 = T_SPIF_Table	//Get GPL951 dummy cycle setting
	r1 += 3
	r1 = [r1]
	r1 |= C_SPIF_TransWithEnhanByte + C_SPIF_Enhance_bit0 + C_SPIF_Enhance_bit1 +C_SPIF_Enhance_bit2 + C_SPIF_Enhance_bit3
.endif	
	[P_SPIFC_PARA] = r1	
	r1 = [P_SPIFC_Ctrl2]		//check 4byte addr mode
	r1 &= 0xff00
	jne L_Set4ByteCMD?
 	r1 = C_SPIF_TransWithOneCMD + 0x0eb					//4 bit command 0xeb
 	goto L_SetCMD?
L_Set4ByteCMD?: 	
 	r1 = C_SPIF_TransWithOneCMD + 0x0ec					//4 bit command 0xec fot 4byte addr mode
L_SetCMD?: 	
	[P_SPIFC_CMD] = r1 
 	r1 = C_SPIF_MIO_4bit + C_SPIF_Auto_Mode + C_SPIF_CMIO_1bit + C_SPIF_AMIO_4bit + C_SPIF_NotIgnoreLastClk +C_SPIF_CLK_PreStateLo
	[P_SPIFC_Ctrl1] = r1 				
	r1 = [P_SPIFC_Ctrl2]
	r1 |= C_SPIFC_EN
	[P_SPIFC_Ctrl2] = r1 		//Enable SPIF
	nop
	nop
	nop
	retf
	
	
//************************************************************//
//Description 	: SPIF set 2 bit mode parameters
//Function		: F_SPI_Set_2Bit
//Parameter		: none
//Destory       : R1
//Return		: none
//************************************************************//		
F_SPI_Set_2Bit:
	r1 = [P_SPIFC_Ctrl2]
	r1 &= ~C_SPIFC_EN
	[P_SPIFC_Ctrl2] = r1 		//Disable SPIF
	r1 = 0x0000
	[P_SPIFC_ADDRL] = r1
	[P_SPIFC_ADDRH] = r1
	[P_SPIFC_TX_BC] = r1
	//r1 = 0x0010					//auto mode need set 0x0010?
	//r1 = 0x0100
	r1 = C_SPIF_RX_BC
	[P_SPIFC_RX_BC] = r1 		
//2bit mio, 1bit cio, 2bit aio, 4 dummy cycle	pass
.if (Winbond_Series|MD_Series)
	r1 = T_SPIF_Table	//Get GPL951 dummy cycle setting
	r1 += 4
	r1 = [r1]
	r1 |= C_SPIF_TransWithoutEnhanByte
.endif
.if GPR_Series|KH_Series		
//	r1 = C_SPIF_TransWithoutEnhanByte + GPL951_DummyCycle
	r1 = T_SPIF_Table	//Get GPL951 dummy cycle setting
	r1 += 3
	r1 = [r1]
	r1 |= C_SPIF_TransWithoutEnhanByte
.endif	
	[P_SPIFC_PARA] = r1	
	r1 = [P_SPIFC_Ctrl2]		//check 4byte addr mode
	r1 &= 0xff00
	jnz L_Set4ByteCMD?
 	r1 = 0x00bb					//2 bit command 0xbb
 	goto L_SetCMD?
L_Set4ByteCMD?: 	
 	r1 = 0x00bc		    		//2 bit command 0xbc fot 4byte addr mode
L_SetCMD?: 		
	[P_SPIFC_CMD] = r1 		
 	r1 = C_SPIF_MIO_2bit + C_SPIF_Auto_Mode + C_SPIF_CMIO_1bit + C_SPIF_AMIO_2bit + C_SPIF_NotIgnoreLastClk +C_SPIF_CLK_PreStateLo
	[P_SPIFC_Ctrl1] = r1 			
	r1 = [P_SPIFC_Ctrl2]
	r1 |= C_SPIFC_EN
	[P_SPIFC_Ctrl2] = r1 		//Enable SPIF
	nop
	nop
	nop
	retf
	

//************************************************************//
//Description 	: SPIF set 1 bit mode parameters
//Function		: F_SPI_Set_1Bit
//Parameter		: none
//Destory       : R1
//Return		: none
//************************************************************//	
F_SPI_Set_1Bit:
	r1 = [P_SPIFC_Ctrl2]
	r1 &= ~C_SPIFC_EN
	[P_SPIFC_Ctrl2] = r1 		//Disable SPIF
	r1 = 0x0000
	[P_SPIFC_ADDRL] = r1
	[P_SPIFC_ADDRH] = r1
	[P_SPIFC_TX_BC] = r1
	//r1 = 0x0010					//auto mode need set 0x0010?
	//r1 = 0x0100
	r1 = C_SPIF_RX_BC
	[P_SPIFC_RX_BC] = r1 		
//1bit mio, 1bit cio, 1bit aio, 0 dummy cycle	pass
	r1 = C_SPIF_TransWithoutEnhanByte + C_SPIF_DummyClk_0cycle
	[P_SPIFC_PARA] = r1	
	r1 = [P_SPIFC_Ctrl2]		//check 4byte addr mode
	r1 &= 0xff00
	jnz L_Set4ByteCMD?
 	r1 = 0x0003					//1 bit command 0x03
 	goto L_SetCMD?
L_Set4ByteCMD?: 	
 	r1 = 0x0013					//1 bit command 0x13 fot 4byte addr mode
L_SetCMD?: 			
	[P_SPIFC_CMD] = r1	
 	r1 = C_SPIF_MIO_1bit + C_SPIF_Auto_Mode + C_SPIF_CMIO_1bit + C_SPIF_AMIO_1bit + C_SPIF_NotIgnoreLastClk +C_SPIF_CLK_PreStateLo
	[P_SPIFC_Ctrl1] = r1 				
	r1 = [P_SPIFC_Ctrl2]
	r1 |= C_SPIFC_EN
	[P_SPIFC_Ctrl2] = r1 		//Enable SPIF
	nop
	nop
	nop
	retf

.COMMENT @
//************************************************************//
//Description 	: If SPIF Quad mode initial pass, read header 
//				  flag to decide do calibration or use default setting.
//Function		: F_SPIF_User_Setting
//Parameter		: none
//Destory       : R1, R2
//Return		: 0 : Not use user setting
//				  1 : Use user setting 
//************************************************************//
F_SPIF_User_Setting:
	call F_SPI_Set_1Bit
L_Check_User_Flag:
	r1 = [0x9014]				//User setting Flag
	cmp	r1, 0x5047
	jne	L_No_Get_Flag
L_Set_User_SPIFCLK:	
	r1 = [0x9015]				//USER SPIF CLK 1~6 = sys/1(96M)~sys/6(16M)
	r1 &= 0x00ff
//	cmp r1,0					//spi CLK limit is sys/1 ~ sys/8, over this range will set to default 16M
//	jmi L_DefaultCLK?
	cmp r1,8
	jpl	L_DefaultCLK?
	r1 = r1 lsl 1				//left shift and byte swap to mapping register	
	[P_Byte_Swap]=r1		
	r1 = [P_Byte_Swap]			//mapping to register define		
	jmp	L_SetSPICLK?
L_DefaultCLK?:	
	r1 = 0x0a00					//default 16M
L_SetSPICLK?:
	r2 = [P_PLL_Sel]
	r2 &= ~0x3e00
	r2 |= r1
	[P_PLL_Sel] = r2 
L_Set_User_SPIFTiming:
	r1 = [0x9016]				//USER SPIF timing	
	r1 &= 0x00F7
 	r2 = [P_SPIFC_TIMING]		//set initial timing 7
	r2 &= ~0x00F7
	r2 |= r1
	[P_SPIFC_TIMING] = r2
	nop
	r1 = [0x9010]				//dummy read	
L_Set_User_SPIFMode:
	r1 = [0x9017]				//USER SPIF mode
	r1 &= 0x0007
	cmp	r1,0x02
	je	L_User_Set_2bit?
	cmp	r1,0x04
	je	L_User_Set_4bit?
	call F_SPI_Set_1Bit			//default 1 bit mode			
	jmp	L_Set_End?
L_User_Set_2bit?:
	call F_SPI_Set_2Bit			//2 bit mode			
	jmp	L_Set_End?
L_User_Set_4bit?:
	call F_SPI_Set_4Bit			//4 bit mode			
L_Set_End?:
	r1 = [0x9040]				//dumy read
	r1 = 1
	retf
L_No_Get_Flag:
	r1 = 0
	retf	


//************************************************************//
//Description 	: Fine tune SPIF timing
//		                 _______                             _______
//	data duration 1T  __/       \__                        _/   |   \__
//	timing delay 0.5T	|0.5|0.5|, worse case in edge;         |*  |* |
//						1   2   3                              1n  2n 3
//  timeing finetune can adjust 16 step per 0.5T, if 1/2 pass, 
//  test 2+n timing, if all pass,set 2, if 2+n fail, set 1+n		
//Function		: F_SPIF_FineTune
//Parameter		: none
//Destory       : R1~R5
//Return		: none
//************************************************************//
F_SPIF_FineTune:
	r1 = [0x901A]
	r1 &= 0xff00
	cmp r1, 0x5A00
	//jne	L_Bypass_FineTune
	je	L_SPIF_FineTune
	retf			//not equ 0x5Axx, bypass fine tune
L_SPIF_FineTune:		
	r1 = [P_SPIFC_TIMING]
	r1 += 0x0010
	[P_SPIFC_TIMING] = r1
	r5 = 0x0010
	r1 = 0x9000
	r2 = T_GP_HEADER
	r3 = [0x903f]				//dummy read
	call F_Header_Verify
	cmp r1,0
	je L_ErrorOccur
	r1 = [P_SPIFC_TIMING]
	r1 &= 0x00f0
	cmp r1,0x00f0		 		//No error, n+1
	jmi L_SPIF_FineTune			//if n=f, set n = 0 and use previous timing setting
	//if 0~f all pass test (Timing-1)+0 again, if pass => set (Timing)+0
	//											  fail or timing is 0 => set (Timing)+8
	r1 = [P_SPIFC_TIMING]
 	r1 &= 0x0007
	r1 -= 1
	cmp	r1, 0x0000
	jmi	L_TimingIsZero?
	r2 = [P_SPIFC_TIMING]
	r2 &= ~0x00f7
	r2 |= r1
	[P_SPIFC_TIMING] = r2		//set (timing-1)+0
	r5 = 0x0010
	r1 = 0x9000
	r2 = T_GP_HEADER
	r3 = [0x903f]				//dummy read	
	call F_Header_Verify
	cmp r1,0
	je L_fail?
	r1 = [P_SPIFC_TIMING]
	r1 &= ~0x00f0
	r1 += 0x0001
	r1 &= ~0x00f0
	[P_SPIFC_TIMING] = r1
	retf
L_fail?:
	r1 = [P_SPIFC_TIMING]
	r1 &= ~0x00f0
	r1 += 0x0001
	r1 &= ~0x00f0
	r1 |= 0x0080
	[P_SPIFC_TIMING] = r1
	retf	
L_TimingIsZero?:
	r1 = [P_SPIFC_TIMING]
	r1 &= ~0x00f0
	r1 |= 0x0080
	[P_SPIFC_TIMING] = r1	
	retf
	
L_ErrorOccur:		 			//(Timing)+n test error, set (Timing-1)+0 and test again, if pass set (timing-1)+8, fail set (timing)+0
	r1 = [P_SPIFC_TIMING]
 	r1 &= 0x0007
	r1 -= 1
	cmp	r1, 0x0000
//	jmi	L_OutTimingRange?	
	jpl	L_NoOutTimingRagne?
	goto L_OutTimingRange?
L_NoOutTimingRagne?:
	r2 = [P_SPIFC_TIMING]
	r2 &= ~0x00f7
	r2 |= r1
	[P_SPIFC_TIMING] = r2		//set (timing-1)+0
	r5 = 0x0010
	r1 = 0x9000
	r2 = T_GP_HEADER
	r3 = [0x903f]				//dummy read	
	call F_Header_Verify
	cmp r1,0
	je L_Error?
//	r1 = [P_SPIFC_TIMING]		//pass set (timing-1)+8
//	r1 |= 0x0080
//	[P_SPIFC_TIMING] = r1
L_ScanAgain?:
	//if (timing-1)+0 pass, scan (timing-1)+(1~15) again, when fail, set (timing-1)+(fail/2), all pass set (timing-1)+8
	r1 = [P_SPIFC_TIMING]		//delay cell+1
	r1 += 0x0010
	[P_SPIFC_TIMING] = r1	
	r5 = 0x0010
	r1 = 0x9000
	r2 = T_GP_HEADER
	r3 = [0x903f]				//dummy read	
	call F_Header_Verify
	cmp r1,0
	je	L_ScanAgainError?
	r1 = [P_SPIFC_TIMING]
	r1 &= 0x00f0
	cmp r1,0x00f0		 		//No error, n+1
	jmi L_ScanAgain?			//if n=f, set n = 8 and use previous timing setting
	r1 = [P_SPIFC_TIMING]
	r1 &= ~0x00f0
	r1 |= 0x0080
	[P_SPIFC_TIMING] = r1
	retf			
L_ScanAgainError?:				//delay cell = fail delay cell /2
	r1 = [P_SPIFC_TIMING]		//delay cell/2
	r1 &= 0x00f0
	r1 = r1 lsr 1	
	r1 &= 0x00f0	
	r2 = [P_SPIFC_TIMING]
	r2 &= ~0x00f0				//mask delay cell
	r2 |= r1
	[P_SPIFC_TIMING] = r2				
	retf							
L_Error?:						//fail set (timing)+0
	r1 = [P_SPIFC_TIMING]
	r1 += 1
	[P_SPIFC_TIMING] = r1
	retf
L_OutTimingRange?:				//out of range, set (timing)+0
	r1 = [P_SPIFC_TIMING]
 	r1 &= ~0x00f0
 	[P_SPIFC_TIMING] = r1
 	retf
//L_Bypass_FineTune:
//	retf
//@


//************************************************************//
//Description 	: Verify GP HEADER
//Function		: F_Header_Verify
//Parameter		: R1 - GP Header Start Addr in SPIF(0x9000)
//				  R2 - GP Header Table define Start Addr(T_GP_HEADER)
//				  R5 - Verify length
//Destory       : R1~R5
//Return		: R1 : 1 - PASS
//					 : 0 - FAILURE
//************************************************************//
F_Header_Verify:
	r4 = [r1]
	r3 = [r2]	
	cmp	r3,r4
	jne	L_ReadErr?
	r1 += 1
	r2 += 1
	r5 -= 1
	cmp	r5,0
	jne	F_Header_Verify
	r3 = [r1]
	[R_CheckSumL] = r3		//Get user code verify checksum LB
	r1 += 1 
	r3 = [r1]
	[R_CheckSumM] = r3		//Get user code verify checksum HB
	r1 += 1
	r3 = [r1]
	r4 = [R_CheckSumL]
	cmp	r3,r4
	jne L_ReadErr?
	r1 += 1
	r3 = [r1]
	r4 = [R_CheckSumM]
	cmp	r3,r4	
	jne L_ReadErr?
	r1 = 1
	retf
L_ReadErr?:
	r1 = 0
	retf	
	


//************************************************************//
//Description 	: Get Header para
//Function		: F_Header_Get_Para
//Parameter		: none
//Destory       : R1~R3
//Return		: none
//************************************************************//
F_Header_Get_Para:
	//r1 += 0x05			//Get CheckSum End Addr L
	r1 = 0x9018
	r3 = [r1]
	[R_EndAddrL] = r3
	r1 += 1					//Get CheckSum End Addr H
	r3 = [r1]
	[R_EndAddrH] = r3	
	r2 = [R_EndAddrL]
	r2 +=1
	r3 += 0,carry
	[R_EndAddrL] = r2	 	//end addr +1
	[R_EndAddrH] = r3	
	r1 += 1					//Get SPIF CLK high speed limited
	r3 = [r1]
	r3 &= 0x00ff
//	cmp r3,0				//spi CLK limit is 96/1 ~ 96/8, over this range will set to default 24M
//	jmi L_DefaultCLK?
	cmp r3,8
	jpl	L_DefaultCLK?
	r3 = r3 lsl 1			//left shift and byte swap to mapping register	
	[P_Byte_Swap]=r3		
	r3 = [P_Byte_Swap]		//mapping to register define
	r3 &= 0x3e00
	r3 = 0x0200
	r3 = 0x0100	
	[R_SPIF_HiCLK_Limit] = r3
	retf
L_DefaultCLK?:	
	r3 = 0x0600				//default 24M
	[R_SPIF_HiCLK_Limit] = r3
	r1 = 1	
	retf


//************************************************************//
//Description 	: SPIF set Quad Mode
//Function		: F_Set_QuadMode
//Parameter		: None
//Destory       : R1, R3
//Return		: R1 : 1 - PASS
//					 : 0 - FAILURE
//************************************************************//	
F_Set_QuadMode:	
 	r1 = C_SPIF_Manual_Mode		//Timing pass, change to manual mode and set SPIF Quad mode
 	[P_SPIFC_Ctrl1] = r1 
	call F_CheckWIP
	cmp	r1,0x8000
	je	L_SPIF_TimeOut?				
 	call F_SPIF_WREN
 	call F_CheckWIP
 	cmp	r1,0x8000
	je	L_SPIF_TimeOut?		
	call F_CheckWREN
	cmp	r1,0x8000
	je	L_SPIF_TimeOut?			 				
	call F_SPIF_QuadMode
	call F_CheckWIP
	cmp	r1,0x8000
	je	L_SPIF_TimeOut?		
	call F_CheckQuadModeEn
	cmp	r1,0x8000
	je	L_SPIF_TimeOut?
	r1 = 1
	retf
L_SPIF_TimeOut?:
	r1 = 0
	retf


//************************************************************//
//Description 	: SPIF set 4byte Mode
//Function		: F_Set_4ByteMode
//Parameter		: None
//Destory       : R1, R3
//Return		: R1 : 1 - PASS
//					 : 0 - FAILURE
//************************************************************//	
F_Set_4ByteMode:
	r1 = C_SPIF_Manual_Mode		//Timing pass, change to manual mode and set SPIF Quad mode
 	[P_SPIFC_Ctrl1] = r1 
	call F_CheckWIP
	cmp	r1,0x8000
	je	L_SPIF_TimeOut?								
	call F_SPIF_4ByteMode
	call F_CheckWIP
	cmp	r1,0x8000
	je	L_SPIF_TimeOut?		
	call F_Check4ByteModeEn
	cmp	r1,0x8000
	je	L_SPIF_TimeOut?
	r1 = 1
	retf
L_SPIF_TimeOut?:
	r1 = 0
	retf


//************************************************************//
//Description : SPIF 4 byte mode
//function : F_SPIF_4ByteMode
//
//
//************************************************************//
F_SPIF_4ByteMode:
	r1 = C_SPIF_TransWithoutEnhanByte + C_SPIF_TransWithoutAddr + C_SPIF_DummyClk_0cycle
	[P_SPIFC_PARA] = r1	
 	r1 = C_SPIF_MIO_1bit + C_SPIF_Manual_Mode + C_SPIF_CMIO_1bit + C_SPIF_AMIO_1bit + C_SPIF_NotIgnoreLastClk +C_SPIF_CLK_PreStateLo
	[P_SPIFC_Ctrl1] = r1
	r1 = 0x0000 
	[P_SPIFC_TX_BC] = r1
	[P_SPIFC_RX_BC] = r1		
	r1 = [P_SPIFC_Ctrl1]			//clear register
	r1 |= 0x8000
	[P_SPIFC_Ctrl1] = r1
	 r1 = 0x00B7 + C_SPIF_TransOnlyCMD
	[P_SPIFC_CMD] = r1 
	call F_CheckIdle		
	retf
	
//************************************************************//
//Description : 
//function : F_SPIF_TimerEn
//
//
//************************************************************//:
F_SPIF_TimerEn:
	r1 = C_SPIF_TimeOut_Cn			
	[TimeOutCn] = r1
	[TimeOutCn1] = r1	
	r1 = 65536-(96000000/2/1000)			//Setup Timer preload value //1ms
	[P_TimerG_Preload] = r1	
	[P_TimerH_Preload] = r1		
	r1 = C_TimerEn + C_TimerSrcA_SYSdiv2 + C_TimerSrcB_High
	[P_TimerG_Ctrl] = r1	
	[P_TimerH_Ctrl] = r1
	retf

//************************************************************//
//Description : 
//function : F_SPIF_TimerDis
//
//
//************************************************************//:
F_SPIF_TimerDis:
	r1 = [P_TimerG_Ctrl]
	r1 &= ~C_TimerEn
	[P_TimerG_Ctrl] = r1
	r1 = [P_TimerH_Ctrl]
	r1 &= ~C_TimerEn
	[P_TimerH_Ctrl] = r1
	retf

//************************************************************//
//Description : 
//function : F_SPIF_CheckTimeOut
//
//
//************************************************************//:	
F_SPIF_CheckTimeOut:
	r1 = [P_TimerH_Ctrl]
	jpl L_NoOverFlow
	[P_TimerH_Ctrl] = r1			//Clear Timer up-counter-overflow interrupt flag
	r1 = [TimeOutCn]
	r1 -= 1
	[TimeOutCn] = r1
	jpl L_NoTimeOut
	r1 = C_SPIF_TimeOut_Cn			
	[TimeOutCn] = r1
	r1 = 0x8000						//Timeout occur
	retf
L_NoTimeOut:	
L_NoOverFlow:
	r1 = 0 
	retf	


//************************************************************//
//Description : 
//function : F_SPIF_CheckTimeOut1
//
//
//************************************************************//:	
F_SPIF_CheckTimeOut1:
	r1 = [P_TimerG_Ctrl]
	jpl L_NoOverFlow?
	[P_TimerG_Ctrl] = r1			//Clear Timer up-counter-overflow interrupt flag
	r1 = [TimeOutCn1]
	r1 -= 1
	[TimeOutCn1] = r1
	jpl L_NoTimeOut?
	r1 = C_SPIF_TimeOut_Cn			
	[TimeOutCn1] = r1
	r1 = 0x8000						//Timeout occur
	retf
L_NoTimeOut?:	
L_NoOverFlow?:
	r1 = 0 
	retf	


	
//************************************************************//
//Description : Write enable
//function : F_SPIF_WREN
//
//
//************************************************************//	
_SPIF_WREN:	
F_SPIF_WREN: 		
	r1 = C_SPIF_TransWithoutEnhanByte + C_SPIF_TransWithoutAddr + C_SPIF_DummyClk_0cycle
	[P_SPIFC_PARA] = r1	
 	r1 = C_SPIF_MIO_1bit + C_SPIF_Manual_Mode + C_SPIF_CMIO_1bit + C_SPIF_AMIO_1bit + C_SPIF_NotIgnoreLastClk +C_SPIF_CLK_PreStateLo
	[P_SPIFC_Ctrl1] = r1
	r1 = 0x0000 
	[P_SPIFC_TX_BC] = r1
	[P_SPIFC_RX_BC] = r1		
	r1 = [P_SPIFC_Ctrl1]			//clear register
	r1 |= 0x8000
	[P_SPIFC_Ctrl1] = r1
	 r1 = 0x0006 + C_SPIF_TransOnlyCMD
	[P_SPIFC_CMD] = r1 
	call F_CheckIdle		
	retf


_SPIF_SWRstEn:
F_SPIF_SWRstEn:
	r1 = C_SPIF_TransWithoutEnhanByte + C_SPIF_TransWithoutAddr + C_SPIF_DummyClk_0cycle
	[P_SPIFC_PARA] = r1	
 	r1 = C_SPIF_MIO_1bit + C_SPIF_Manual_Mode + C_SPIF_CMIO_1bit + C_SPIF_AMIO_1bit + C_SPIF_NotIgnoreLastClk +C_SPIF_CLK_PreStateLo
	[P_SPIFC_Ctrl1] = r1
	r1 = 0x0000 
	[P_SPIFC_TX_BC] = r1
	[P_SPIFC_RX_BC] = r1		
	r1 = [P_SPIFC_Ctrl1]
	r1 |= 0x8000
	[P_SPIFC_Ctrl1] = r1
	 r1 = 0x0066 + C_SPIF_TransOnlyCMD
	[P_SPIFC_CMD] = r1 
	call F_CheckIdle		
	retf

_SPIF_SWRst:
F_SPIF_SWRst:
	r1 = C_SPIF_TransWithoutEnhanByte + C_SPIF_TransWithoutAddr + C_SPIF_DummyClk_0cycle
	[P_SPIFC_PARA] = r1	
 	r1 = C_SPIF_MIO_1bit + C_SPIF_Manual_Mode + C_SPIF_CMIO_1bit + C_SPIF_AMIO_1bit + C_SPIF_NotIgnoreLastClk +C_SPIF_CLK_PreStateLo
	[P_SPIFC_Ctrl1] = r1
	r1 = 0x0000 
	[P_SPIFC_TX_BC] = r1
	[P_SPIFC_RX_BC] = r1		
	r1 = [P_SPIFC_Ctrl1]
	r1 |= 0x8000
	[P_SPIFC_Ctrl1] = r1
	 r1 = 0x0099 + C_SPIF_TransOnlyCMD
	[P_SPIFC_CMD] = r1 
	call F_CheckIdle		
	retf

//************************************************************//
//Description : Write disable
//function : F_SPIF_WRDI
//
//
//************************************************************//
_SPIF_WRDI:	
F_SPIF_WRDI:		
	r1 = C_SPIF_TransWithoutEnhanByte + C_SPIF_TransWithoutAddr + C_SPIF_DummyClk_0cycle
	[P_SPIFC_PARA] = r1	
 	r1 = C_SPIF_MIO_1bit + C_SPIF_Manual_Mode + C_SPIF_CMIO_1bit + C_SPIF_AMIO_1bit + C_SPIF_NotIgnoreLastClk +C_SPIF_CLK_PreStateLo
	[P_SPIFC_Ctrl1] = r1
	r1 = 0x0000 
	[P_SPIFC_TX_BC] = r1
	[P_SPIFC_RX_BC] = r1		
	r1 = [P_SPIFC_Ctrl1]			//clear register
	r1 |= 0x8000
	[P_SPIFC_Ctrl1] = r1
	 r1 = 0x0004 + C_SPIF_TransOnlyCMD
	[P_SPIFC_CMD] = r1 	
	call F_CheckIdle	
	retf


//************************************************************//
//Description : RDSR
//function : F_SPIF_RDSR
//
//return : N = 1 means timeout
//************************************************************//
_F_SPIF_RDSR:
F_SPIF_RDSR:
	call F_CleanRxFifo
	r1 = 0x0000
	[P_SPIFC_TX_BC] = r1
	r2 = 0x0001
	[P_SPIFC_RX_BC] = r2				
	r1 = C_SPIF_TransWithoutEnhanByte + C_SPIF_TransWithoutAddr + C_SPIF_DummyClk_0cycle
	[P_SPIFC_PARA] = r1	
 	r1 = C_SPIF_MIO_1bit + C_SPIF_Manual_Mode + C_SPIF_CMIO_1bit + C_SPIF_AMIO_1bit + C_SPIF_NotIgnoreLastClk +C_SPIF_CLK_PreStateLo
	[P_SPIFC_Ctrl1] = r1 	
	r1 = 0x0005
	[P_SPIFC_CMD] = r1 
	r1 = C_SPIF_TimeOut_Cn			
	[TimeOutCn] = r1	
L_CheckRxFifo: 
	call F_SPIF_CheckTimeOut
	cmp	r1, 0x8000
	je	L_RDSRTimeOut
	r1 = [P_SPIFC_Ctrl1]
	r1 &= 0x4000
	jnz L_CheckRxFifo 			//check rx fifo
	[P_SPIFC_RX_Data] = r1		//write dummy before read operation			
	r1 = [P_SPIFC_RX_Data]
	r1 &= 0x00ff				//RX BC = 1, only low byte effective
	call F_CleanRxFifo
	retf
L_RDSRTimeOut:
	call F_CleanRxFifo
	r1 = 0x8000
	retf			
	
.if (Winbond_Series|MD_Series)
//************************************************************//
//Description : RDSR1				//for winbond
//function : F_SPIF_RDSR1
//		   : read status register 2
//return : N = 1 means timeout
//************************************************************//
_F_SPIF_RDSR1:
F_SPIF_RDSR1:
	call F_CleanRxFifo
	r1 = 0x0000
	[P_SPIFC_TX_BC] = r1
	r2 = 0x0001
	[P_SPIFC_RX_BC] = r2				
	r1 = C_SPIF_TransWithoutEnhanByte + C_SPIF_TransWithoutAddr + C_SPIF_DummyClk_0cycle
	[P_SPIFC_PARA] = r1	
 	r1 = C_SPIF_MIO_1bit + C_SPIF_Manual_Mode + C_SPIF_CMIO_1bit + C_SPIF_AMIO_1bit + C_SPIF_NotIgnoreLastClk +C_SPIF_CLK_PreStateLo
	[P_SPIFC_Ctrl1] = r1 	
	r1 = 0x0035					//status register 2
	[P_SPIFC_CMD] = r1 
	r1 = C_SPIF_TimeOut_Cn			
	[TimeOutCn] = r1	
L_CheckRxFifo1: 
	call F_SPIF_CheckTimeOut
	cmp	r1, 0x8000
	je	L_RDSRTimeOut1
	r1 = [P_SPIFC_Ctrl1]
	r1 &= 0x4000
	jnz L_CheckRxFifo1 			//check rx fifo
	[P_SPIFC_RX_Data] = r1		//write dummy before read operation			
	r1 = [P_SPIFC_RX_Data]
	r1 &= 0x00ff				//RX BC = 1, only low byte effective	
	call F_CleanRxFifo
	retf
L_RDSRTimeOut1:
	call F_CleanRxFifo
	r1 = 0x8000
	retf
	
//************************************************************//
//Description : F_SPIF_WRSR3
//function : Status Register 3 Write; Winbond some device have SR3
//           include driving current setting.
//parameter : R1 : Status Register Value
//			
//************************************************************//
F_SPIF_WRSR3:
	push r1 to [SP]
	call F_CheckWIP	
	cmp	r1,0x8000
	je	L_SPIF_TimeOut?		 	
 	call F_SPIF_WREN
 	call F_CheckWIP
	cmp	r1,0x8000
	je	L_SPIF_TimeOut?	
	call F_CheckWREN	
	cmp	r1,0x8000
	je	L_SPIF_TimeOut?	
	r1 = C_SPIF_TransWithoutEnhanByte + C_SPIF_TransWithoutAddr + C_SPIF_DummyClk_0cycle
	[P_SPIFC_PARA] = r1	
 	r1 = C_SPIF_MIO_1bit + C_SPIF_Manual_Mode + C_SPIF_CMIO_1bit + C_SPIF_AMIO_1bit + C_SPIF_NotIgnoreLastClk +C_SPIF_CLK_PreStateLo
	[P_SPIFC_Ctrl1] = r1
	r1 = 0x0000 
	[P_SPIFC_RX_BC] = r1
	r1 = 0x0001	
	[P_SPIFC_TX_BC] = r1	
	r1 = [P_SPIFC_Ctrl1]			//clear register
	r1 |= 0x8000
	[P_SPIFC_Ctrl1] = r1
	r1=0x11							//WRSR3 command
	[P_SPIFC_CMD] = r1	
L_WriteLoop?:	
	pop r1 from [SP]
	[P_SPIFC_TX_Data]=r1
	nop
	nop
	nop
	nop		
CheckTxDone1?:
	r1 = [P_SPIFC_Ctrl1]
	jpl	CheckTxDone1?
	[P_SPIFC_Ctrl1] = r1
?L_Checkidle:
	call F_CheckWIP
L_SPIF_TimeOut?:		
	retf
		
.endif

//************************************************************//
//Description : RDCR
//function : F_SPIF_RDCR
//
//return : N = 1 means timeout
//************************************************************//
F_SPIF_RDCR:
	call F_CleanRxFifo
	r1 = 0x0000
	[P_SPIFC_TX_BC] = r1
	r2 = 0x0001
	[P_SPIFC_RX_BC] = r2				
	r1 = C_SPIF_TransWithoutEnhanByte + C_SPIF_TransWithoutAddr + C_SPIF_DummyClk_0cycle
	[P_SPIFC_PARA] = r1	
 	r1 = C_SPIF_MIO_1bit + C_SPIF_Manual_Mode + C_SPIF_CMIO_1bit + C_SPIF_AMIO_1bit + C_SPIF_NotIgnoreLastClk +C_SPIF_CLK_PreStateLo
	[P_SPIFC_Ctrl1] = r1 	
	 r1 = 0x0015	 
	[P_SPIFC_CMD] = r1 
	r1 = C_SPIF_TimeOut_Cn			
	[TimeOutCn] = r1	
L_CheckRxFifo?: 
	call F_SPIF_CheckTimeOut
	cmp	r1, 0x8000
	je	L_RDCRTimeOut?
	r1 = [P_SPIFC_Ctrl1]
	r1 &= 0x4000
	jnz L_CheckRxFifo? 			//check rx fifo
	[P_SPIFC_RX_Data] = r1		//write dummy before read operation			
	r1 = [P_SPIFC_RX_Data]
	r1 &= 0x00ff				//RX BC = 1, only low byte effective	
	call F_CleanRxFifo
	retf
L_RDCRTimeOut?:
	call F_CleanRxFifo
	r1 = 0x8000
	retf
	
	
//************************************************************//
//Description : 
//function : F_SPIF_QuadMode
//
//
//************************************************************//
_SPIF_QuadMode:
F_SPIF_QuadMode:
.if (GPR_Series&(GPR25L1605E|GPR25L1603E|GPR25L0805E))|(KH_Series&KH25L1633E)|(MD_Series&MD25Q128C)
	r1 = 0x0001
.else
	r1 = 0x0002	
.endif	
	[P_SPIFC_TX_BC] = r1
	r2 = 0x0000
	[P_SPIFC_RX_BC] = r2				
	r1 = C_SPIF_TransWithoutEnhanByte + C_SPIF_TransWithoutAddr + C_SPIF_DummyClk_0cycle
	[P_SPIFC_PARA] = r1	
 	r1 = C_SPIF_MIO_1bit + C_SPIF_Manual_Mode + C_SPIF_CMIO_1bit + C_SPIF_AMIO_1bit + C_SPIF_NotIgnoreLastClk +C_SPIF_CLK_PreStateLo
	[P_SPIFC_Ctrl1] = r1 	
	r1 = 0x0001
.if(MD_Series&MD25Q128C)		//MD25Q128C write QE cmd is 0x0031, and only send 1 byte.
	r1 |= 0x0030
.endif	
	[P_SPIFC_CMD] = r1 
	
.if	!(MD_Series&MD25Q128C)
	.if	(Winbond_Series|MD_Series)
		r1 = 0x0000
	.endif
	.if GPR_Series|KH_Series						
	//	r1 = 0x0040											//status register
		r1 = T_SPIF_Table	//Get SR setting
		r1 += 1
		r1 = [r1]
	.endif  
	    [P_SPIFC_TX_Data] = r1
		call F_CheckTxDone
.endif
	
.if	(Winbond_Series|MD_Series)
	//r1 = 0x0002
	r1 = T_SPIF_Table	//Get SR1 setting
	r1 += 2
	r1 = [r1]	
	.endif
.if GPR_Series|KH_Series
.if GPR_Series&(GPR25L1605E|GPR25L1603E|GPR25L0805E)|(KH_Series&KH25L1633E)
	call F_CheckIdle
	retf
.endif
//    r1 = C_SPIF_DummyCycle + C_SPIF_Driving				//Configuration register
	r1 = T_SPIF_Table	//Get CR setting
	r1 += 2
	r1 = [r1]
.endif 
    [P_SPIFC_TX_Data] = r1
	call F_CheckTxDone    	
	call F_CheckIdle
	retf	

.if	(Winbond_Series|MD_Series)
_Enter_QPI:
F_Enter_QPI:
	r1 = C_SPIF_TransWithoutEnhanByte + C_SPIF_TransWithoutAddr + C_SPIF_DummyClk_0cycle
	[P_SPIFC_PARA] = r1	
 	r1 = C_SPIF_MIO_1bit + C_SPIF_Manual_Mode + C_SPIF_CMIO_1bit + C_SPIF_AMIO_1bit + C_SPIF_NotIgnoreLastClk +C_SPIF_CLK_PreStateLo
	[P_SPIFC_Ctrl1] = r1
	r1 = 0x0000 
	[P_SPIFC_TX_BC] = r1
	[P_SPIFC_RX_BC] = r1		
	r1 = [P_SPIFC_Ctrl1]
	r1 |= 0x8000
	[P_SPIFC_Ctrl1] = r1
	 r1 = 0x0038 + C_SPIF_TransOnlyCMD
	[P_SPIFC_CMD] = r1 
	call F_CheckIdle		
	retf
	
_Exit_QPI:
F_Exit_QPI:
 	r1 = C_SPIF_MIO_1bit + C_SPIF_Manual_Mode + C_SPIF_CMIO_1bit + C_SPIF_AMIO_1bit + C_SPIF_NotIgnoreLastClk +C_SPIF_CLK_PreStateLo
	[P_SPIFC_Ctrl1] = r1	
	r1 = C_SPIF_TransWithoutEnhanByte + C_SPIF_TransWithoutAddr + C_SPIF_DummyClk_0cycle
	[P_SPIFC_PARA] = r1	
	r1 = 0x0000 
	[P_SPIFC_TX_BC] = r1
	[P_SPIFC_RX_BC] = r1		
	r1 = [P_SPIFC_Ctrl1]
	r1 |= 0x8000
	[P_SPIFC_Ctrl1] = r1
	 r1 = 0x00FF + C_SPIF_TransOnlyCMD
	[P_SPIFC_CMD] = r1 
	call F_CheckIdle		
	retf				
.endif

//************************************************************//
//Description : 
//function : _SPIF_NormalMode
//
//
//************************************************************//
_SPIF_NormalMode:
F_SPIF_NormalMode:
	r1 = 0x0001
	[P_SPIFC_TX_BC] = r1
	r2 = 0x0000
	[P_SPIFC_RX_BC] = r2				
	r1 = C_SPIF_TransWithoutEnhanByte + C_SPIF_TransWithoutAddr + C_SPIF_DummyClk_0cycle
	[P_SPIFC_PARA] = r1	
 	r1 = C_SPIF_MIO_1bit + C_SPIF_Manual_Mode + C_SPIF_CMIO_1bit + C_SPIF_AMIO_1bit + C_SPIF_NotIgnoreLastClk +C_SPIF_CLK_PreStateLo
	[P_SPIFC_Ctrl1] = r1 	
	r1 = 0x0001
	[P_SPIFC_CMD] = r1 				
	r1 = 0x0000
    [P_SPIFC_TX_Data] = r1	
	call F_CheckIdle
	retf		


//************************************************************//
//Description : 
//function : F_CleanRxFifo
//
//
//************************************************************//
//F_CleanRxFifo:
//	r3 = [P_SPIFC_Ctrl1]
//	r3 &= 0x4000
//	jnz	?L_RxEmpty
//	[P_SPIFC_RX_Data] = r3	
//	r3 = [P_SPIFC_RX_Data]
//	jmp	F_CleanRxFifo
//?L_RxEmpty:	
//	retf
F_CleanRxFifo:
	r3 = [P_SPIFC_Ctrl1]
	r3 &= 0x4000
	jnz	?L_RxEmpty
	
	r1 = 0x0000
	[P_SPIFC_TX_BC] = r1
	r2 = 0x0001
	[P_SPIFC_RX_BC] = r2				
	r1 = C_SPIF_TransWithoutEnhanByte + C_SPIF_TransWithoutAddr + C_SPIF_DummyClk_0cycle
	[P_SPIFC_PARA] = r1	
 	r1 = C_SPIF_MIO_1bit + C_SPIF_Manual_Mode + C_SPIF_CMIO_1bit + C_SPIF_AMIO_1bit + C_SPIF_NotIgnoreLastClk +C_SPIF_CLK_PreStateLo
	[P_SPIFC_Ctrl1] = r1 	
	r1 = 0x0003
	[P_SPIFC_CMD] = r1		
L_CheckRxFifo?: 
	r1 = [P_SPIFC_Ctrl1]
	r1 &= 0x4000
	jnz L_CheckRxFifo? 			//check rx fifo
	[P_SPIFC_RX_Data] = r3	
	r3 = [P_SPIFC_RX_Data]
	jmp	F_CleanRxFifo
?L_RxEmpty:	
	retf



//************************************************************//
//Description : 
//function : F_CheckIdle
//
//
//************************************************************//
F_CheckIdle:
	r1 = C_SPIF_TimeOut_Cn			
	[TimeOutCn] = r1	
L_CheckIdle: 
	call F_SPIF_CheckTimeOut
	cmp	r1, 0x8000
	je	L_CheckIdleTimeOut	
	r1 = [P_SPIFC_Ctrl1]
	r1 &= 0x0001
	jz	L_CheckIdle
	retf
L_CheckIdleTimeOut:
	retf

//************************************************************//
//Description : 
//function : F_CheckWIP
//
//
//************************************************************//
F_CheckWIP:
	r1 = C_SPIF_TimeOut_Cn			
	[TimeOutCn1] = r1	
L_CheckWIP: 
	call F_SPIF_CheckTimeOut1
 	cmp	r1,0x8000
 	je	L_WIPTimeOut 
 	call F_SPIF_RDSR
 	cmp	r1,0x8000
 	je	L_WIPTimeOut 
 	r1&=0x0001
 	jnz L_CheckWIP
 	r1 = 0 
L_WIPTimeOut: 	
 	retf
 
 
 //************************************************************//
//Description : 
//function : F_CheckWREN
//
//
//************************************************************//	
 F_CheckWREN:
 	r1 = C_SPIF_TimeOut_Cn			
	[TimeOutCn1] = r1	
L_CheckWREN: 
	call F_SPIF_CheckTimeOut1
 	cmp	r1,0x8000
 	je	L_WRENTimeOut 
 	call F_SPIF_RDSR
  	cmp	r1,0x8000
  	je	L_WRENTimeOut	
 	r1&=0x0002
 	jz L_CheckWREN
  	r1 = 0 	
L_WRENTimeOut: 	
 	retf	
 
 
//************************************************************//
//Description : 
//function : F_CheckQuadModeEn
//
//
//************************************************************//	
F_CheckQuadModeEn:
 	r1 = C_SPIF_TimeOut_Cn			
	[TimeOutCn1] = r1	
L_CheckQuadModeEn: 
	call F_SPIF_CheckTimeOut1
 	cmp	r1,0x8000
 	je	L_QuadModeTimeOut 
.if GPR_Series|KH_Series	
 	call F_SPIF_RDSR
.endif
.if (Winbond_Series|MD_Series)
	call F_SPIF_RDSR1
.endif	 	
   	cmp	r1,0x8000
  	je	L_QuadModeTimeOut
.if GPR_Series|KH_Series	
 	r1 &= 0x0040
.endif
.if (Winbond_Series|MD_Series)
	r1 &= 0x0002
.endif	
 	jz	L_CheckQuadModeEn
  	r1 = 0 	
 L_QuadModeTimeOut:	
 	retf
 
  
//************************************************************//
//Description : 
//function : F_Check4ByteModeEn
//
//
//************************************************************//
 F_Check4ByteModeEn:
 	r1 = C_SPIF_TimeOut_Cn			
	[TimeOutCn1] = r1	
L_Check4ByteModeEn: 
	call F_SPIF_CheckTimeOut1
 	cmp	r1,0x8000
 	je	L_4byteModeTimeOut 	
 	call F_SPIF_RDCR
   	cmp	r1,0x8000
  	je	L_4byteModeTimeOut
.if GPR_Series|KH_Series 	
 	r1 &= 0x0020
.endif
.if (Winbond_Series|MD_Series)
	r1 &= 0x0001
.endif	
 	jz	L_Check4ByteModeEn
  	r1 = 0 	
 L_4byteModeTimeOut:	
 	retf


//************************************************************//
//Description : 
//function : F_Check4ByteModeEn
//
//
//************************************************************//
F_CheckDummyCycle:
 	r1 = C_SPIF_TimeOut_Cn			
	[TimeOutCn1] = r1	
L_CheckDummyCycle: 
	call F_SPIF_CheckTimeOut1
 	cmp	r1,0x8000
 	je	L_TimeOut	 	
 	call F_SPIF_RDCR
   	cmp	r1,0x8000
  	je	L_TimeOut	
 L_TimeOut:	
 	retf

//************************************************************//
//Description : Read SPIF ID
//function : F_SPIF_RDID
//
//
//************************************************************//
_SPIF_RDID:
F_SPIF_RDID:
 	r1 = C_SPIF_Manual_Mode		//Timing pass, change to manual mode and set SPIF Quad mode
 	[P_SPIFC_Ctrl1] = r1 
	call F_CheckWIP
	cmp	r1,0x8000
	je	?L_RDIDTimeOut	
	call F_CleanRxFifo
	r1 = 0x0000
	[P_SPIFC_TX_BC] = r1
	r1 = 0x0001
	r2 = 0x0003
	[P_SPIFC_RX_BC] = r2
	r2 -= 0x0001				//Rx r ead word	mode					
	r1 = C_SPIF_TransWithoutEnhanByte + C_SPIF_TransWithoutAddr + C_SPIF_DummyClk_0cycle
	[P_SPIFC_PARA] = r1	
 	r1 = C_SPIF_MIO_1bit + C_SPIF_Manual_Mode + C_SPIF_CMIO_1bit + C_SPIF_AMIO_1bit + C_SPIF_NotIgnoreLastClk +C_SPIF_CLK_PreStateLo
	[P_SPIFC_Ctrl1] = r1 	
	 r1 = 0x009f
	[P_SPIFC_CMD] = r1 
	r1 = C_SPIF_TimeOut_Cn			
	[TimeOutCn] = r1	
?L_CheckRxFifo: 
	call F_SPIF_CheckTimeOut
	cmp	r1, 0x8000
	je	?L_RDIDTimeOut
	r1 = [P_SPIFC_Ctrl1]
	r1 &= 0x4000
	jnz ?L_CheckRxFifo 			//check rx fifo	
?L_ReadLoop:
	[P_SPIFC_RX_Data] = r1		//write dummy before read operation			
	r1 = [P_SPIFC_RX_Data]
	push r1 to [SP]
	r2 -= 1
//	cmp r2, 0
//	jne ?L_ReadLoop
	jnz ?L_CheckRxFifo
	pop r1 from [SP]
	r2 = r1 & 0x00ff
	pop r1 from [SP]
	r1 = r1 lsl 4
	r1 = r1 lsl 4
	r2 |= r1						//record ID density
	call F_CleanRxFifo	
	retf			
?L_RDIDTimeOut:
	call F_CleanRxFifo
	r1 = 0x0000
	retf	


//************************************************************//
//Description : 
//function : F_CheckTxDone
//
//
//************************************************************//
F_CheckTxDone:
	r1 = [P_SPIFC_Ctrl1]
	r1 &= 0x8000
	jz	F_CheckTxDone
	r1 = [P_SPIFC_Ctrl1]
	r1 |= 0x8000
	[P_SPIFC_Ctrl1] = r1	
	retf


//************************************************************//
//Description : DummyRead
//function : F_SPIF_DummyRead
//	
//
//************************************************************//	
F_SPIF_DummyRead:
	r1 = 0						//close cache first
	[P_Cache_Ctrl]=r1
cacheloop?:	
	r1=[P_Cache_Ctrl]
	test	r1,0x02
	jnz	cacheloop?	
	r1 = 0x9000
	r2 = 0x10
L_SPIF_DummyRead:				//dummy read 16 times after cache clear done
	r3 = [r1]
	r1 += 0x0010
	r2 -= 1
	jnz L_SPIF_DummyRead
L_OpenCache:	
	r1=0x02		
	[P_Cache_Ctrl]=r1
	nop
	nop
cacheloop?:	
	r1=[P_Cache_Ctrl]
	test	r1,0x02
	jnz	cacheloop?
	r1=0x0d					
	[P_Cache_Ctrl]=r1
	retf	


//************************************************************//
//Description : F_SPIF_WRSR
//function : Status Register Write
//parameter : R1 : Status Register Value
//			// 2017/03/01 add
//************************************************************//
F_SPIF_WRSR:
	push r1 to [SP]
	call F_CheckWIP	
	cmp	r1,0x8000
	je	L_SPIF_TimeOut?		 	
 	call F_SPIF_WREN
 	call F_CheckWIP
	cmp	r1,0x8000
	je	L_SPIF_TimeOut?	
	call F_CheckWREN	
	cmp	r1,0x8000
	je	L_SPIF_TimeOut?	
	r1 = C_SPIF_TransWithoutEnhanByte + C_SPIF_TransWithoutAddr + C_SPIF_DummyClk_0cycle
	[P_SPIFC_PARA] = r1	
 	r1 = C_SPIF_MIO_1bit + C_SPIF_Manual_Mode + C_SPIF_CMIO_1bit + C_SPIF_AMIO_1bit + C_SPIF_NotIgnoreLastClk +C_SPIF_CLK_PreStateLo
	[P_SPIFC_Ctrl1] = r1
	r1 = 0x0000 
	[P_SPIFC_RX_BC] = r1
	r1 = 0x0001	
	[P_SPIFC_TX_BC] = r1	
	r1 = [P_SPIFC_Ctrl1]			//clear register
	r1 |= 0x8000
	[P_SPIFC_Ctrl1] = r1
	r1=0x01							//WRSR command
	[P_SPIFC_CMD] = r1	
L_WriteLoop?:	
	pop r1 from [SP]
	[P_SPIFC_TX_Data]=r1
	nop
	nop
	nop
	nop		
CheckTxDone1?:
	r1 = [P_SPIFC_Ctrl1]
	jpl	CheckTxDone1?
	[P_SPIFC_Ctrl1] = r1
?L_Checkidle:
	call F_CheckWIP
//	r3 = [P_SPIFC_Ctrl1]
//	r3 &= 0x0001
//	jz	?L_Checkidle
L_SPIF_TimeOut?:		
	retf


.define Null 0x8000			//if Null, bypass this parameter
T_SPIF_Table:
//		ID,					SR,					CR					GPL951_Dummy cycle
//															if GPR/KH series, GPL951 dummy setting = real spif dummy - 2
//															if Winbond series, GPL951 dummy setting = real spif dummy			
.if GPR_Series
	.if GPR25L25605F
		.dw	GPR25L25605F_ID,	GPR25L25605F_SR,	GPR25L25605F_CR,	C_SPIF_DummyClk_6cycle	
	.endif
	.if	GPR25L12805F
		.dw	GPR25L12805F_ID,	GPR25L12805F_SR,	GPR25L12805F_CR,	C_SPIF_DummyClk_6cycle
	.endif	
	.if GPR25L6403F	
		.dw	GPR25L6403F_ID,		GPR25L6403F_SR,		GPR25L6403F_CR,		C_SPIF_DummyClk_8cycle	
	.endif
	.if GPR25L3203F
		.dw	GPR25L3203F_ID,		GPR25L3203F_SR,		GPR25L3203F_CR,		C_SPIF_DummyClk_4cycle		
	.endif
	.if GPR25L1605E
		.dw	GPR25L1605E_ID,		GPR25L1605E_SR,		GPR25L1605E_CR,		C_SPIF_DummyClk_4cycle		
	.endif	
	.if GPR25L1603E
		.dw	GPR25L1603E_ID,		GPR25L1603E_SR,		GPR25L1603E_CR,		C_SPIF_DummyClk_4cycle		
	.endif	
	.if GPR25L0805E
		.dw	GPR25L0805E_ID,		GPR25L0805E_SR,		GPR25L0805E_CR,		C_SPIF_DummyClk_4cycle		
	.endif		
.endif

.if KH_Series
	.if KH25L12833F
		.dw	KH25L12833F_ID,		KH25L12833F_SR,		KH25L12833F_CR,		C_SPIF_DummyClk_6cycle	
	.endif
	.if KH25L12835F
		.dw	KH25L12835F_ID,		KH25L12835F_SR,		KH25L12835F_CR,		C_SPIF_DummyClk_6cycle	
	.endif
	.if KH25L1633E
		.dw	KH25L1633E_ID,		KH25L1633E_SR,		KH25L1633E_CR,		C_SPIF_DummyClk_4cycle	
	.endif	
.endif

.if Winbond_Series
	.if W25Q256FV
		.dw	W25Q256FV_ID,		W25Q256FV_SR,		W25Q256FV_SR1,		W25Q256FV_SR2,	C_SPIF_DummyClk_4cycle	
	.endif
	.if W25Q128FV
		.dw	W25Q128FV_ID,		W25Q128FV_SR,		W25Q128FV_SR1,		W25Q128FV_SR2,	C_SPIF_DummyClk_4cycle	
	.endif
	.if W25Q64FV
		.dw	W25Q64FV_ID,		W25Q64FV_SR,		W25Q64FV_SR1,		Null,			C_SPIF_DummyClk_4cycle
	.endif
.endif

.if MD_Series
	.if MD25Q128C
		.dw	MD25Q128C_ID,		MD25Q128C_SR,		MD25Q128C_SR1,		MD25Q128C_SR2,	C_SPIF_DummyClk_4cycle	
	.endif
	.if MD25Q16C
		.dw	MD25Q16C_ID,		MD25Q16C_SR,		MD25Q16C_SR1,		Null,			C_SPIF_DummyClk_4cycle	
	.endif
	.if MD25Q80C
		.dw	MD25Q80C_ID,		MD25Q80C_SR,		MD25Q80C_SR1,		Null,			C_SPIF_DummyClk_4cycle	
	.endif
.endif


.include ID_02280001.inc		//library tag

MoveEndAddr:

