RK3128-android7.1-nt68661

本文介绍了如何在RK3128设备上配置Android7.1系统,结合NT6866芯片将HDMI信号转换为LVDS。主要涉及的步骤包括理解NT6866芯片功能,将.bin文件拷贝到系统ETC路径,并在rockchip-hdmi相关的驱动源码中加载文件,如rockchip-hdmi-core.c、rockchip-hdmi-lcdc.c和pwm_bl.c等。

1.首先了解一下6866这个芯片的功能是将HDMI转成LVDS

知道这一步,就要知道如何实现

 将 .bin 文件复制到ETC路径

 

然后加载.bin文件会在nt6866的驱动中下载到芯片内

\sdk\kernel\drivers\video\rockchip\hdmi\rockchip-hdmi-core.c

+    #ifdef CONFIG_NT68661
+	return ;
+	#endif

 \sdk\kernel\drivers\video\rockchip\hdmi\rockchip-hdmi-lcdc.c

+ #ifdef CONFIG_NT68661
+ struct rk_screen * rk_get_screen(void);
+ #endif


int hdmi_find_best_mode(struct hdmi *hdmi, int vic)
{
	struct list_head *pos, *head = &hdmi->edid.modelist;
	struct display_modelist *modelist = NULL;
	int found = 0;
+ #if CONFIG_NT68661
+	struct rk_screen *screen=NULL;
+	
+
+	  screen=rk_get_screen();
+
+      printk("x=%d y=%d \n",screen->mode.xres,screen->mode.yres);
+
+	printk("screen->face=%d screen->lvds_format=%d \n",screen->face,screen->lvds_format); 
+	
+	if(screen->mode.xres==1920&&screen->mode.yres==1080) return HDMI_1920X1080P_60HZ;
+	else if(screen->mode.xres==1366&&screen->mode.yres==768) return (HDMI_VIDEO_DMT | 6);
+	else if(screen->mode.xres==1280&&screen->mode.yres==1024) return (HDMI_VIDEO_DMT | 4);
+
+	return HDMI_1920X1080P_60HZ;// (HDMI_VIDEO_DMT | 4);
+ #else

 

 

// sdk\kernel\drivers\char\nt68661.c

#include <linux/delay.h>

#include <linux/slab.h>
#include <linux/gpio.h>
#include <linux/delay.h>


#include <linux/module.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/fb.h>
#include <linux/rk_fb.h>



typedef unsigned char              Bit;
typedef unsigned char              Bool;

typedef unsigned char   Byte;
typedef unsigned short  Word;
typedef unsigned long	ULong;

#define LOG_TAG "nt68661"


#if 1 //def GSL_DEBUG 
#define debug(fmt, x...) printk("%s: %s() line: %d "fmt, LOG_TAG, __FUNCTION__, __LINE__, ##x);

#else
#define print_info(fmt, args...)
#endif


#define BIT0	0x01
#define BIT1	0x02
#define BIT2	0x04
#define BIT3	0x08
#define BIT4	0x10
#define BIT5	0x20
#define BIT6	0x40
#define BIT7	0x80

#define TARGET0 BIT7



#define NACK 1
#define ACK 0
#define FAIL 0
#define OK 1
#define EMPTY 2


typedef union{
	unsigned long l;
	Byte b[4];
}Union4;

typedef union{
	Word w;
	Byte b[2];	//0:H, 1:L
}Union2;

#define VERSION 17
#define OSC_CLK 12000000//unit Mhz
#define LOW_MCU_CLK OSC_CLK*1
#define MID_MCU_CLK OSC_CLK*3
#define HI_MCU_CLK OSC_CLK*8
#define LOW_SPEED 1
#define MID_SPEED 3
#define HI_SPEED 8

// FE2P mode
#define NORMAL_MODE 0
#define FE2P_MODE 1
#define DIRECT_FE2P_MODE 2



#define true 1
#define false 0
//   En   Name              Id     Pg CPUCLK IICSPD SpcCmd  NewProg Umb  Fe2p  60k  CoP   ExtFlash

typedef struct{
	Byte En;
	Byte Name[15];
	Word Id;
	Word page;
	Byte CpuClk;
	Byte IICSpeed;
	Byte SpcCmd;
	Byte NewProg;
	Byte Umb;
	Byte Fe2p;
	Byte s60k;
	Byte coP;
	Byte ExtFlash;
}MCU_DEF;

	
typedef struct{
	Byte En;
	Byte ID1;
	Byte ID2;
	Byte ID3;
	Byte FE2P;
	Byte ByteWrite;
	Byte SE_Code;
	Byte CE_Code;
	Word Page;
	Byte SE_Time;
	Word CE_Time;
	Byte Name[23];
}FLASH_DEF;

extern const Byte  McuRegTab[];
extern const FLASH_DEF  FlashIDTable[];
extern const MCU_DEF  McuTypeTable[];

#define _tNOVATEK 		0
#define _tFE2P			1
#define _tBLOCK_SAVE	2
#define _tENTER_ISP		3
#define _tCHIP_ERASE	4
#define _tBLCOK_ERASE	5
#define _tPROGRAM		6
#define _tEXIT_ISP		7
#define _tSOURCE_ISP	8
#define _tTARGET_FAIL	9
#define _tPROGRAM_START	10
#define _tPROGRAM_END	11
#define _tCHECK_SUM		12
#define _tFLASH_NAME	13
#define _tSOURCE_READ	14
#define _tFE2P_SUM		15

#define _tPASS			3
#define _tFAIL			4
#define _tON			1
#define _tOFF			2
#define _tFAIL_CH		5
#define _tCHECKSUM		6
#define _tFE2PSUM		7





#define comChipErase	0x1E
#define comBlockErase	0x2D    //new NT68631A
#define comWritePage24M	0x3C
#define comGetPage	    0x4B
#define comWriteOne	    0x5A
#define comGetDirect	0x69
#define comSetRegSRAM	0x78
#define comGetRegSRAM	0x87
#define comGetIntRAM	0x96
#define comGetPageNew   0x4A    //new NT68670&NT68631A
#define comGetCheckSum  0x36    //new NT68670&NT68631A
#define comSetExtendAddr 0x0f   //new NT68670
#define comGetVersion   0x11    //new NT68670&NT68631A
#define comMultiFunc    0x99
#define comSPICmd       0x53


extern Byte pFail;		//For Message process	
extern FLASH_DEF Flash;		//Flash Information
extern Byte McuGear;		//MCY clock ratio
extern Word Timer;			//System Timer
extern Word MaxPages;		//Max programming pages
extern Byte Fe2pMode;		// For FE2P Mode
extern Word DirFE2P_Offset;
Byte MultiID;
extern Word SPageSum;		//Source Page checksum
extern Byte  Buffer[512];
extern Word McuId;
extern Bit ErrorFlag;
Word usSPICmdBufAddr;
Byte ucSPI_BackUpBuf[7] = {0};

extern ULong WpDefine;
extern Byte Wp_PortE;
extern Byte Wp_PortF;
extern ULong Wp_PortG_J;
extern ULong Wp_PortK_M;

#if 1
#define SDA_PIN 7
#define SCL_PIN 6

#else
#define SDA_PIN 84
#define SCL_PIN 85

#endif
#define SET_SCL_H gpio_set_value(SCL_PIN,1)
#define SET_SCL_L   gpio_set_value(SCL_PIN,0)

#define SET_SDA_H gpio_set_value(SDA_PIN,1)
#define SET_SDA_L  gpio_set_value(SDA_PIN,0)

#define GET_SDA()  gpio_get_value(SDA_PIN)
#define GET_SCL()  gpio_get_value(SCL_PIN)

#define SET_SDA_INPUT gpio_direction_input(SDA_PIN)

#define SET_SCL_INPUT gpio_direction_input(SCL_PIN)


#define SET_SDA_OUTPUT {gpio_direction_output(SDA_PIN,1);SET_SDA_H;}

#define SET_SCL_OUTPUT gpio_direction_output(SCL_PIN,1)




Byte pFail;	//For Message process	
Byte McuGear;		//MCU clock ratio
Byte Bypass;		//ByPass Compare
Word Timer;			//System Timer
Word MaxPages;		//Max Flash pages
Word CodePages;     // f/w programming pages
Word FlashOffset;   // start page of Flash
Word SPageSum;		//Source Page checksum
Word McuId;
Byte Fe2pMode;		// For FE2P Mode
Word DirFE2P_Offset;
Word DirFE2P_Length;

#define TOTAL_PAGE_SIZE 200
Byte  BinFilePageBuffer[512] ;// 1024pages for 4M flash
FLASH_DEF Flash;
Bit ErrorFlag;

// please define the WP here(according bit set 1)
ULong WpDefine=0x02000000;
Byte Wp_PortE;
Byte Wp_PortF;
ULong Wp_PortG_J;
ULong Wp_PortK_M;

// Dual F/W
Bit DualFwEnable;



extern void Sleep(Word T);
extern void Sdelay(void);
extern void PulseDelay();

extern void T_CheckIIC(void);
extern void T_IIC_Start(void);
extern void T_IIC_Stop(void);
extern Byte T_IIC_Tx(Byte Data);
extern unsigned char T_IIC_Rx(Bit Ack);
extern void T_WaitSCL(void);
extern void T_HandShake(Word Timeout);
extern void T_ISPMode(Bit On);
extern void T_ISPStatusReply();
extern Byte T_GetPageData(Byte PageNo);
extern Byte T_ChipErase(void);
extern Byte T_ChipEraseReply(void);
extern Byte T_WritePagedata(Byte Pg);
extern void T_WritePageDataReply(void);
extern void T_SetRegSRAM(Byte AddrH,Byte AddrL,Byte Data);
extern void T_SetRegSRAMReply();
extern Byte T_GetCheckSum(Byte PageNo);
extern Byte T_GetCheckSumReply(void);
extern Bit T_GetMcuInformation(Word id);
extern Byte T_BlockErase(Byte From,Byte To);
extern Byte T_BlockEraseReply();
extern Byte T_SpiCommand(Byte *Data,Byte WLen,Byte RLen);
extern void T_GetVersion(void);
extern void T_GetRegSRAM(Byte AddrH,Byte AddrL);
extern unsigned long T_GetRegSRAMReply(void);
extern void Cmd_T_EnterIsp(void);
extern void Cmd_T_Erase(void);
extern void Cmd_T_Program(Byte Pg);
extern void Cmd_T_GetCheckSum(Byte Pg);
extern void Cmd_T_BlockErase();
extern Byte Cmd_T_SetExntend(Word Pg);
extern void Cmd_T_SendSpecialCommand();
extern void Cmd_T_WP_Enable(void);
extern void Cmd_T_BlockProtect(Bit Wp);
extern Bool CheckOverLap(Word PageNo);
extern void Fn68390ProgramEnable(Bit En);
extern void WpEnable(void);
extern void FnEraseIDSector(void);
extern Bit FnUpdateIDSector(void);

void Cmd_T_GetFlashID();
extern Word DirFE2P_Length;
extern Bit DualFwEnable,ErrorFlag;
extern Byte SearchFlashID(Byte *mcuFlashID);
void Cmd_T_BlockProtect0(void);



const MCU_DEF  McuTypeTable[]={
//   En   Name              Id     Pg CPUCLK IICSPD 	SpcCmd  NewProg Umb  Fe2p  60k  CoP   ExtFlash
    {true,"NT68360        ",        0xA536,256,0x50 ,HI_SPEED  ,0x02   ,true ,true ,true ,false,false,true},
    {true,"NT68169        ",        0xA569,256,0x30 ,HI_SPEED  ,0x02   ,true ,true ,true ,false,false,true},
    {true,"NT68661        ",        0xA561,256,0x30 ,HI_SPEED  ,0x02   ,true ,true ,true ,false,false,true},
    {true,"NT68850        ",        0xA585,256,0x30 ,HI_SPEED  ,0x02   ,true ,true ,true ,false,false,true},
    {true,"NT68770        ",        0xA577,256,0x30 ,HI_SPEED  ,0x02   ,true ,true ,true ,false,false,true},
    {true,"NT68655        ",        0xA555,256,0x30 ,HI_SPEED  ,0x02   ,true ,true ,true ,false,false,true},
    {true,"NT68150        ",        0xA515,256,0x30 ,HI_SPEED  ,0x02   ,true ,true ,true ,false,false,true},
    {true,"NT68370        ",        0xA537,256,0x30 ,HI_SPEED  ,0x02   ,true ,true ,true ,false,true, true},
    {true,"NT68790        ",        0xA790,256,0x30 ,HI_SPEED  ,0x02   ,true ,true ,true ,false,false,true},
    {true,"NT68658        ",        0xA658,256,0x30 ,HI_SPEED  ,0x02   ,true ,true ,true ,false,false,true},
    {true,"NT68380        ",        0xA380,256,0x30 ,HI_SPEED  ,0x02   ,true ,true ,true ,false,true, true},
    {true,"NT68390        ",        0xA390,256,0x40 ,HI_SPEED  ,0x02   ,true ,true ,true ,false,true, true},
    {true,"NT68810        ",        0xA810,256,0x30 ,HI_SPEED  ,0x02   ,true ,true ,true ,false,false,true},
    {true,"NT68870        ",        0xA870,256,0x30 ,HI_SPEED  ,0x02   ,true ,true ,true ,false,false,true},
    {true,"NT68400        ",        0xA400,256,0x40 ,HI_SPEED  ,0x02   ,true ,true, true, false,false,true},
    {true,"NT68450        ",        0xA450,256,0x40 ,HI_SPEED  ,0x02   ,true ,true ,true ,false,false,true},
};


const FLASH_DEF  FlashIDTable[]={
//   En    ID1  ID2  ID3  FE2P  BYTE  SE   CE  PAGE SE_T CE_T  NAME
    {true ,0x55,0xaa,0x00,false,false,0xd7,0xc7,256 ,0   ,100 ,"Embeded/Unknown Flash "},
    {true ,0x9d,0x7f,0x7c,true ,false,0xd7,0xc7,256 ,70  ,100 ,"PMC Pm25LV010A 128KB "},
    {true ,0x9d,0x7f,0x7d,true ,false,0xd7,0xc7,512 ,70  ,100 ,"PMC Pm25LV020A 256KB "},
    {true ,0x9d,0x7f,0x7e,true ,false,0xd7,0xc7,1024,300  ,3000 ,"PMC Pm25LV040A 512KB "}, // modify SE_T, CE_T to be compatible with Pm25LQ040B because their flash ID are the same.
    {true ,0x9d,0x7f,0x10,true ,false,0xd7,0xc7,256 ,70  ,100 ,"PMC_Pm25LD010C 128KB "},
    {true ,0x9d,0x7f,0x11,true ,false,0xd7,0xc7,512 ,70  ,100 ,"PMC_Pm25LD020C 256KB "},
    {true ,0x9d,0x7f,0x12,true ,false,0xd7,0xc7,1024,70  ,100 ,"PMC_Pm25LD040C 512KB "},
    {true ,0x9d,0x40,0x11,true ,false,0xd7,0xc7,256,300  ,1500 ,"ISSI IS25LQ010B   1MB"},
    {true ,0x9d,0x60,0x14,true ,false,0xd7,0xc7,2048,300  ,6000 ,"ISSI IS25LP080D   1MB"},
    {true ,0xc2,0x20,0x11,true ,false,0x20,0xc7,256 ,120 ,2000,"MXIC MX25L1005 128K  "},
    {true ,0xc2,0x20,0x12,true ,false,0x20,0xc7,512 ,120 ,3000,"MXIC MX25L2005 256K  "},
    {true ,0xc2,0x20,0x13,true ,false,0x20,0xc7,1024,120 ,5000,"MXIC MX25L4005A 512K "},
    {true ,0xc2,0x20,0x14,true ,false,0x20,0xc7,2048,300 ,15000,"MXIC MX25L8006E 1MB  "},
    {true ,0xc2,0x20,0x15,true ,false,0x20,0xc7,4096,300 ,30000,"MXIC MX25L1606E 2MB  "},
    {true ,0xc2,0x20,0x17,true ,false,0x20,0xc7,2048,300 ,80000,"MXIC MX25L6406E 8MB  "}, // page set to 2048 means only read first 2048 pages, don't care other pages.
	{true ,0xc2,0x23,0x11,true ,false,0x20,0xc7, 256,240 , 2300,"MXIC MX25V1035F 128KB "},
	{true ,0xc2,0x23,0x12,true ,false,0x20,0xc7, 512,240 , 9000,"MXIC MX25V2035F 256KB "},
	{true ,0xc2,0x23,0x13,true ,false,0x20,0xc7,1024,240 , 9000,"MXIC MX25V4035F 512KB "},
	{true ,0xc2,0x23,0x14,true ,false,0x20,0xc7,2048,240 ,18000,"MXIC MX25V8035F 1MB  "},
    {true ,0xc2,0x23,0x15,true ,false,0x20,0xc7,4096,240 ,38000,"MXIC MX25V1635F 2MB  "},
	{true ,0xbf,0x49,0xff,true ,true ,0x20,0xc7,256 ,70  ,100 ,"SST SST25VF010A 128K "},
    {true ,0xbf,0x43,0xff,true ,true ,0x20,0xc7,512 ,70  ,100 ,"SST SST25VF020 256K  "},
    {true ,0xbf,0x44,0xff,true ,true ,0x20,0xc7,1024,70  ,100 ,"SST SST25LF040 512K  "},
    {true ,0xbf,0x8c,0xff,true ,true ,0x20,0xc7,512 ,30  ,60  ,"SST SST25VF020B 256K "},
    {true ,0xbf,0x8e,0xff,true ,true ,0x20,0xc7,2048 ,30  ,60  ,"PCT/SST 25VF080B 1MB "},
    {true ,0xef,0x11,0xff,true ,false,0x20,0xc7,256 ,150 ,3000,"WINBOND W25X10 128K  "},
    {true ,0xef,0x10,0xff,true ,false,0x20,0xc7,512 ,150 ,3000,"WINBOND W25X20 256K  "},
    {true ,0xef,0x12,0xff,true ,false,0x20,0xc7,1024,150 ,5000,"WINBOND W25X40 512K  "},
    {true ,0xef,0x40,0x12,true ,false,0x20,0xc7,512 ,300 ,2000,"WINBOND W25Q20CL 256K"},
    {true ,0xef,0x40,0x13,true ,false,0x20,0xc7,1024,300 ,5000,"WINBOND W25Q40CL 512K"},
    {true ,0xef,0x40,0x14,true ,false,0x20,0xc7,2048,400 ,8000,"WINBOND W25Q80BV 1MB "},
    {true ,0xef,0x70,0x14,true ,false,0x20,0xc7,2048,400 ,10000,"WINBOND W25Q80JV 1MB"},
    {true ,0xef,0x40,0x15,true ,false,0x20,0xc7,4096,400 ,10000,"WINBOND W25Q16CL/DV 2MB"},
    {true ,0xef,0x70,0x15,true ,false,0x20,0xc7,4096,400 ,25000,"WINBOND W25Q16JV 2MB"},
    {true ,0xef,0x40,0x16,true ,false,0x20,0xc7,4096,400 ,50000,"WINBOND W25Q32FV  4MB"},
    {true ,0x00,0x10,0x10,false,false,0xd8,0xc7,256 ,100 ,3000,"ST M25P10 128K       "},
    {true ,0x00,0x11,0x11,false,false,0xd8,0xc7,512 ,100 ,3000,"ST M25P20 256K       "},
    {true ,0x00,0x12,0x12,false,false,0xd8,0xc7,1024,100 ,5000,"ST M25P40 512K       "},
    {true ,0x20,0x20,0x12,false,false,0xd8,0xc7,512 ,100 ,6000,"NUMONYX M25P20  256K "},
    {true ,0x20,0x10,0x11,false,false,0xd8,0xc7,256 ,100 ,3000,"NUMONYX/ST M25P10 128K"},
    {true ,0x37,0x11,0x30,true ,false,0x20,0xc7,256 ,120 ,2000,"AMIC A25L010A(B) 128K"},
    {true ,0x37,0x12,0x30,true ,false,0x20,0xc7,512 ,120 ,4000,"AMIC A25L020A(B) 256K"},
    {true ,0x37,0x13,0x30,true ,false,0x20,0xc7,1024,120 ,6000,"AMIC A25L040A(B) 512K"},
    {true ,0x1c,0x11,0x31,true ,false,0x20,0xc7,256 ,300 ,3000,"EON EN25F10 128K     "},
    {true ,0x1c,0x12,0x31,true ,false,0x20,0xc7,512 ,300 ,4000,"EON EN25F20 256K     "},
    {true ,0x1c,0x13,0x31,true ,false,0x20,0xc7,1024,300 ,6000,"EON EN25F40 512K     "},
    {true ,0x1c,0x32,0xff,false,false,0xd8,0xc7,1024,300 ,6000,"EON EN25B40 512K     "},
    {true ,0x1c,0x13,0x30,false,false,0x20,0xc7,1024,300 ,7500,"EON EN25Q40A 512K    "},
    {true ,0x1c,0x14,0x30,false,false,0x20,0xc7,2048,300 ,15000,"EON EN25Q80B 1MB    "},
    {true ,0x1c,0x15,0x70,true ,false,0x20,0xc7,4096,300 ,30000,"EON EN25QH16A 2MB   "},
    {true ,0x8c,0x30,0x12,true ,true ,0x20,0xc7,512, 200 ,4000,"ESMT F25L02PA 256K   "},
    {true ,0x8c,0x30,0x13,true ,true ,0x20,0xc7,1024,200 ,4000,"ESMT F25L04PA 512K   "},
    {true ,0x8c,0x30,0x14,true ,true ,0x20,0xc7,2048,200 ,5000,"ESMT F25L08PT  1024K "},
    {true ,0x8c,0x31,0x12,true ,true ,0x20,0xc7,512, 200 ,4000,"ESMT F25L02PTA 256K  "},
    {true ,0x8c,0x31,0x13,true ,true ,0x20,0xc7,1024,200 ,4000,"ESMT F25L04PTA 512K  "},
    {true ,0x8c,0x31,0x14,true ,true ,0x20,0xc7,2048,200 ,5000,"ESMT F25L08PTA 1024K "},
    {true ,0x8c,0x40,0x14,true ,true ,0x20,0xc7,2048,400 ,20000,"ESMT F25L08QA 1024K "},
    {true ,0xc8,0x40,0x11,true ,false,0x20,0xc7,256, 500 ,2000,"GIGA GD25Q10 128K    "},
    {true ,0xc8,0x40,0x12,true ,false,0x20,0xc7,512, 500 ,5000,"GIGA GD25Q20 256K    "},
	{true ,0xc8,0x41,0x12,true ,false,0x20,0xc7,512, 500 ,4000,"GIGA GD25M21 256K	 "},
    {true ,0xc8,0x40,0x13,true ,false,0x20,0xc7,1024,500 ,11250, "GIGA 25Q40/41B/40C 512K"},
	{true ,0xc8,0x41,0x13,true ,false,0x20,0xc7,1024,400 ,5000, "GIGA GD25M41 512K	 "},
    {true ,0xc8,0x40,0x14,true ,false,0x20,0xc7,2048, 300 ,10000,"GIGA GD25Q80C 1MB  "},
    {true ,0xc8,0x40,0x15,true ,false,0x20,0xc7,4096, 300 ,20000,"GIGA GD25Q16C 2MB  "},
    {true ,0xd5,0x30,0x13,true ,false,0x20,0xc7,1024,200 ,7500,"NANTRONICS N25S40 512k"},
    {true ,0xa1,0x31,0x13,true ,false,0x20,0xc7,1024,300 ,10000,"FUDAN FM25F04 512k    "},
    {true ,0xa1,0x31,0x12,true ,false,0x20,0xc7,512 ,300 ,5000,"FUDAN FM25F02 256k    "},
    {true ,0xa1,0x31,0x11,true ,false,0x20,0xc7,256 ,300 ,4000,  "FUDAN FM25F01 128k    "},
    {true ,0xa1,0x40,0x12,true ,false,0x20,0xc7,512,300 ,2500,"FUDAN FM25Q02 256k    "},
    {true ,0xa1,0x40,0x13,true ,false,0x20,0xc7,1024 ,300 ,5000,"FUDAN FM25Q04 512k    "},
    {true ,0xa1,0x40,0x14,true ,false,0x20,0xc7,2048 ,300 ,32000,  "FUDAN FM25Q08 1MB    "},
    {true ,0xa1,0x40,0x15,true ,false,0x20,0xc7,4096 ,300 ,20000,  "FUDAN FM25Q16 2MB    "},
    {true ,0xe0,0x40,0x15,true ,false,0x20,0xc7,1024 ,300 ,25000,"BergMicro BG25Q40 512k"},
    {true ,0xe0,0x40,0x12,true ,false,0x20,0xc7,512 ,300 ,5000,"BergMicro BG25Q20 256k"},
    {true ,0xe0,0x40,0x11,true ,false,0x20,0xc7,256 ,300 ,5000,"BergMicro BG25Q10 128k"},
    {true ,0x1f,0x01,0x86,true ,false,0x20,0xc7,4096 ,300 ,20000,"adesto AT25SF161 2MB  "},
    {true ,0x5e,0x60,0x12,true ,false,0x20,0xc7,512 ,300 ,5000,"ZB25VQ20 256KB        "},
    {true ,0x5e,0x60,0x13,true ,false,0x20,0xc7,1024 ,300 ,5000,"ZB25VQ40 512KB        "},
    {true ,0x68,0x40,0x12,true ,false,0x20,0xc7,512 ,300 ,30000,"BoHong BH25D20A 256KB "},
    {true ,0x68,0x40,0x13,true ,false,0x20,0xc7,1024 ,300 ,30000,"BoHong BH25D40A 512KB "},
    {false,0xff,0xff,0xff,false,false,0xff,0   ,0   ,0   ,0   ,"END OF TABLE         "},
    };



void Sleep(Word T)	//delay 100uS
{
	Word i,j,k;
	if(McuGear == LOW_SPEED)
		k = 3;
	else
		if(McuGear == MID_SPEED)
			k = 12;
	else
		k = 32;
	for(j=0;j<T;j++) udelay(100);
}

void Sdelay()
{
	//Byte i;
//	for(i=0;i<2;i++);
		udelay(2);
}

void PulseDelay()
{
	//Byte i;
	//for(i=0;i<4;i++);
	udelay(7);
}


	

void T_IIC_Start(void)
{
	

	SET_SDA_L;//TSDA &= 0x7f;
	PulseDelay();
	SET_SCL_L;//TSCL &= 0x7f;
	PulseDelay();
}

void T_IIC_Stop(void)
{
	SET_SDA_L;//TSDA &= 0x7f;
	PulseDelay();
	SET_SCL_H;//TSCL |= 0x80;
	PulseDelay();
	SET_SDA_H;//TSDA |= 0x80;
	PulseDelay();
}

Byte T_IIC_Tx(Byte Data)
{	//subroutine total time 630us
	Byte AckLoop,Ack;
	Byte i;
	for(i=0;i<8;i++)
	{
	    SET_SCL_L;//TSCL &= 0x7f;
	     udelay(5);
		if(Data & BIT7)
			SET_SDA_H;//TSDA |= 0x80;
		else
			SET_SDA_L;//TSDA &= 0x7f;
		SET_SCL_H;//TSCL |= 0x80;
//		TSCL = 0xff;
		Data <<= 1;
             udelay(5);

	}
	//
	SET_SCL_L;//TSCL &= 0x7f;
	udelay(2);
	SET_SDA_H;//TSDA |= 0x80;
	SET_SCL_H;//TSCL |= 0x80;
	//RDSDA |= 0x80;	//Input
	SET_SDA_INPUT;
	udelay(2);
	for(AckLoop=0;AckLoop<40;AckLoop++) //300uS
		{
		udelay(5);
		Ack = GET_SDA();//TSDA;//TSDA & 0x80;
	//	Ack &= ~pFail;	//check ack & bypass fail channel
		if(Ack == 0x00)
			break;
		}
	SET_SDA_OUTPUT;
	udelay(2);
	//RDSDA &= 0x7f;	//Output
	SET_SCL_L;//TSCL &= 0x7f;

	PulseDelay();

//	send_asc("ack=",Ack);
	return Ack;			//return success=0 / failure=1
}

unsigned char T_IIC_Rx(Bit Ack)
{
	Byte Temp,D1;
	Byte i;
	SET_SCL_L;//TSCL &= 0x0f;
	SET_SDA_H;//TSDA |= 0xf0;
//	RDSDA |= 0xf0;
       SET_SDA_INPUT;
	for(i=0;i<8;i++)
	{
		D1 <<= 1;
		SET_SCL_L;//TSCL &= 0x7f;
		udelay(5);
		SET_SCL_H;//TSCL |= 0x80;
		udelay(5);
		Temp =GET_SDA() ;// TSDA;
		//Temp = TSDA;
		//Temp = TSDA;
		if(Temp==1)
			D1++;
	}
	//RDSDA &= 0x7f;
	SET_SDA_OUTPUT;
	SET_SCL_L;//TSCL &= 0x7f;
	udelay(2);
	if(Ack == ACK)
		SET_SDA_L;//TSDA &= 0x7f;
	else
		SET_SDA_H;//TSDA |= 0x80;
	SET_SCL_H;//TSCL |= 0x80;
	SET_SCL_H;//TSCL |= 0x80;
	SET_SCL_H;//TSCL |= 0x80;
	udelay(2);
	SET_SCL_L;//TSCL &= 0x7f;
	udelay(2);
	return D1;
}

void T_WaitSCL(void)	//wait SCL all HI
{
	Word i;
	Byte Ck;
	
	SET_SCL_H;//TSCL |= 0x80;
	PulseDelay();
//	RDSCL |= 0x80;
	//for(i=0;i<1500;i++) //10ms

      SET_SCL_INPUT;
	for(i=0;i<1500;i++) //10ms
		{
		udelay(2);
		Ck = GET_SCL();//TSCL;//TSCL & 0x80;
		Ck |= pFail;
		if(Ck == 1)//0x80)
			break;
		}
//RDSCL &= 0x7f;
 SET_SCL_OUTPUT;
}

void T_HandShake(Word Timeout)	//unit 1mS
{
	Timer = Timeout*10;	//timer count down
	Sleep(3);	//delay 300us

	SET_SCL_INPUT;
	while(Timer > 0)
		{
		if(GET_SCL()== 1) break;	//Wait SCL == Hi
			

			if(Timer>0) Timer--;
			Sleep(1);
			 
		}


	SET_SCL_OUTPUT;
	
	if(Timer == 0){
		
		ErrorFlag = 1;
              debug("t shake error \n");

	}
	
}


void send_sync(){

int i;


SET_SDA_OUTPUT;
SET_SCL_OUTPUT;

for(i=0;i<10;i++) {
SET_SDA_L;
PulseDelay();
SET_SCL_L;
PulseDelay();
PulseDelay();
SET_SCL_H;
PulseDelay();
SET_SDA_H;
PulseDelay();
}

mdelay(5);
udelay(400);
//for(i=0;i<5000;i++);



for(i=0;i<10;i++) {

SET_SDA_L;
PulseDelay();
SET_SCL_L;
PulseDelay();
PulseDelay();
PulseDelay();
PulseDelay();
SET_SCL_H;
PulseDelay();
SET_SDA_H;
PulseDelay();



}







}


void T_ISPMode(Bit On)
{
 char ret;


	T_IIC_Start();
	ret=T_IIC_Tx(0x04);
	T_WaitSCL();	//wait SCL go hi or delay >10uS
	//
	T_IIC_Start();
	ret=T_IIC_Tx(0x34);
	T_WaitSCL();	//wait SCL go hi or delay >10uS
	//
	T_IIC_Start();
	ret=T_IIC_Tx(0x06);
	T_WaitSCL();	//wait SCL go hi or delay >10uS
	//
	T_IIC_Start();
	if(On)
		T_IIC_Tx(0x36);
	else
		T_IIC_Tx(0x3c);

	T_IIC_Stop();
	
}

void T_ISPStatusReply()
{
	Byte ID_H,ID_L;
	Byte d1,d2;

	T_IIC_Start();
	T_IIC_Tx(0x6f);
       udelay(200);
	//PulseDelay();	//delay >100uS for stability
	d1=T_IIC_Rx(ACK);
	ID_H = T_IIC_Rx(ACK);
	ID_L = T_IIC_Rx(ACK);
	d2=T_IIC_Rx(NACK);
	T_IIC_Stop();
	McuId = ID_H;
	McuId <<= 8;
	McuId |= ID_L;


debug("McuId==d1=%x  d2=%x d3=%x d4=%x \n",d1,ID_H,ID_L,d2);

//	debug("McuId===%x \n",McuId);

	//send_int16("id=",McuId);
}


EXPORT_SYMBOL(T_ISPStatusReply);


Byte T_GetPageData(Byte PageNo)
{
	Byte Ack,CheckSum;
	T_IIC_Start();
	Ack = T_IIC_Tx(0x6e);
	T_IIC_Tx(0x02);
	T_IIC_Tx(0x4b);
	T_IIC_Tx(PageNo);
	CheckSum = 0x6e^0x02^0x4b^PageNo;
	T_IIC_Tx(CheckSum);
	T_IIC_Stop();
	return Ack;
}

Byte T_ChipErase(void)
{
	Byte Ack,CheckSum;
	T_IIC_Start();
	Ack = T_IIC_Tx(0x6e);
	T_IIC_Tx(0x07);
	T_IIC_Tx(comChipErase);
	T_IIC_Tx(0xaa);
	T_IIC_Tx(0x55);
	T_IIC_Tx(0xcc);
	T_IIC_Tx(0x33);
	T_IIC_Tx(0xe2);
	T_IIC_Tx(0x1d);
	CheckSum = 0x6e^0x07^comChipErase^0xaa^0x55^0xcc^0x33^0xe2^0x1d;
	T_IIC_Tx(CheckSum);
	T_IIC_Stop();
	return Ack;
}

Byte T_ChipEraseReply(void)
{
	Byte ReplyCode;
	T_IIC_Start();
	T_IIC_Tx(0x6f);
	//PulseDelay();	//delay > 100us

	Sleep(2);	
	T_IIC_Rx(ACK);	//length, no used
	ReplyCode = T_IIC_Rx(ACK);	//status
	T_IIC_Rx(NACK);	//Checksum, no used
	T_IIC_Stop();

	debug("lizz T_ChipEraseReply=%x \n",ReplyCode);
	
	if((ReplyCode^comChipErase) != 0xff)
		ErrorFlag = 1;

		return 0;
}

Byte T_BlockErase(Byte From,Byte To)
{
	Byte Ack,CheckSum;
	T_IIC_Start();
	Ack = T_IIC_Tx(0x6e);
	T_IIC_Tx(0x09);
	T_IIC_Tx(comBlockErase);
	T_IIC_Tx(0xaa);
	T_IIC_Tx(0x55);
	T_IIC_Tx(0xcc);
	T_IIC_Tx(0x33);
	T_IIC_Tx(0xe2);
	T_IIC_Tx(0x1d);
	T_IIC_Tx(From);
	T_IIC_Tx(To);
	CheckSum = 0x6e^0x09^comBlockErase^0xaa^0x55^0xcc^0x33^0xe2^0x1d^From^To;
	T_IIC_Tx(CheckSum);
	T_IIC_Stop();
	return Ack;
}

Byte T_BlockEraseReply(void)
{
	Byte ReplyCode;
	T_IIC_Start();
	T_IIC_Tx(0x6f);
       udelay(100);
	//PulseDelay();	//delay > 100us
	T_IIC_Rx(ACK);	//length, no used
	ReplyCode = T_IIC_Rx(ACK);	//status
	T_IIC_Rx(NACK);	//Checksum, no used
	T_IIC_Stop();

	debug("T_BlockEraseReply==%x \n",ReplyCode);
	if((ReplyCode^comBlockErase) != 0xff)
		ErrorFlag = 1;
		return 0;
}

Byte T_WritePagedata(Byte Pg)
{
	Byte Ack,CheckSum;
	Word i;
	T_IIC_Start();
	T_IIC_Tx(0x6e);
	T_IIC_Tx(0x00);
	T_IIC_Tx(comWritePage24M);
	T_IIC_Tx(Pg);
	T_IIC_Tx(0xf0);
	T_IIC_Tx(0x0f);
	T_IIC_Tx(0x6e);
	T_IIC_Tx(0x91);
	T_IIC_Tx(0x13);
	T_IIC_Tx(0xec);
	CheckSum = 0x6e^0x00^comWritePage24M^Pg^0xf0^0x0f^0x6e^0x91^0x13^0xec;
	for(i=0;i<512;i++)
		{
		T_IIC_Tx(BinFilePageBuffer[i]);
		CheckSum ^= BinFilePageBuffer[i];
		}
	T_IIC_Tx(CheckSum);
	T_IIC_Stop();
	return Ack;
	
}

void T_WritePageDataReply(void)
{
	Byte ReplyCode;//Dummy,;
	T_IIC_Start();
	T_IIC_Tx(0x6f);
	//PulseDelay();	//delay > 100us

	Sleep(2);	
	T_IIC_Rx(ACK);	//length
	ReplyCode = T_IIC_Rx(ACK);	//status
	T_IIC_Rx(NACK);	//Checksum
	T_IIC_Stop();

	//debug("T_WritePageDataReply=%x \n",ReplyCode);
	if((ReplyCode^comWritePage24M) != 0xff)
		ErrorFlag = 1;
}

void T_SetRegSRAM(Byte AddrH,Byte AddrL,Byte Data)
{
	Byte CheckSum;
	T_IIC_Start();
	T_IIC_Tx(0x6e);
	T_IIC_Tx(0x04);
	T_IIC_Tx(comSetRegSRAM);	//OP code = 0x78
	T_IIC_Tx(AddrH);
	T_IIC_Tx(AddrL);
	T_IIC_Tx(Data);
	CheckSum = 0x6e^0x04^comSetRegSRAM^AddrH^AddrL^Data;
	T_IIC_Tx(CheckSum);
	T_IIC_Stop();
}

void T_SetRegSRAMReply()
{
	Byte ReplyCode;
	T_IIC_Start();
	T_IIC_Tx(0x6f);
	Sleep(1);//PulseDelay();	//delay >100uS for stability
	T_IIC_Rx(ACK);
	ReplyCode = T_IIC_Rx(ACK);
	T_IIC_Rx(NACK);
	T_IIC_Stop();

	//debug("ReplyCode=%x \n",ReplyCode);
	if((ReplyCode^comSetRegSRAM) != 0xff)
		ErrorFlag = 1;
}

void T_GetVersion(void)	//for Get Flash ID
{
	T_IIC_Start();
	T_IIC_Tx(0x6e);
	T_IIC_Tx(0x01);
	T_IIC_Tx(comGetVersion);
	T_IIC_Tx(0x6e^0x01^0x11);
	T_IIC_Stop();
}

void T_GetRegSRAM(Byte AddrH,Byte AddrL)
{
	Byte CheckSum;
	T_IIC_Start();
	T_IIC_Tx(0x6e);
	T_IIC_Tx(0x03);
	T_IIC_Tx(comGetRegSRAM);
	T_IIC_Tx(AddrH);
	T_IIC_Tx(AddrL);
	CheckSum = 0x6e^0x03^comGetRegSRAM^AddrH^AddrL;
	T_IIC_Tx(CheckSum);
	T_IIC_Stop();
}

unsigned long T_GetRegSRAMReply(void)
{
	Byte Status;
	unsigned long Data;
	T_IIC_Start();
	T_IIC_Tx(0x6f);
	//PulseDelay();
	//PulseDelay();
	Sleep(1);
	T_IIC_Rx(ACK);
	Status = T_IIC_Rx(ACK);
	Data = T_IIC_Rx(ACK);
	T_IIC_Rx(NACK);
	T_IIC_Stop();

//	debug("Status==%x \n",Status);
	if((Status^comGetRegSRAM) != 0xff)
		pFail |= TARGET0;
	return Data;
}

Byte T_MultiFunc(Byte Data)
{
	Byte ack;
	
	T_IIC_Start();
	ack = T_IIC_Tx(0x6e);
	T_IIC_Tx(0x02);
	T_IIC_Tx(comMultiFunc);
	T_IIC_Tx(Data);
	T_IIC_Tx(0x6E^0x02^comMultiFunc^Data);
	T_IIC_Stop();
	return ack;
}

void Cmd_T_EnterIsp(void)
{
	Byte i;

	 send_sync();
	 
	for(i=0;i<1;i++)
	{
		T_ISPMode(1);		//enter ISP mode
		Sleep(1);			//sleep >100us
		T_ISPMode(1);
		Sleep(100);			//sleep >5ms
		T_ISPStatusReply();
	}
	if(!ErrorFlag)
		Cmd_T_SendSpecialCommand();	
	debug("ErrorFlag1==%x \n",ErrorFlag);
	if(!ErrorFlag)
		Cmd_T_GetFlashID();
	debug("ErrorFlag2==%x \n",ErrorFlag);
	if(!ErrorFlag)
		WpEnable();
	debug("ErrorFlag3==%x \n",ErrorFlag);
	if(!ErrorFlag)
		Cmd_T_BlockProtect(0); 

	debug("ErrorFlag4==%x \n",ErrorFlag);

	//Cmd_T_BlockProtect0();
}



EXPORT_SYMBOL(Cmd_T_EnterIsp);


void SetSectorErasePage(Bool page)
{
    if(page)
        MultiID |= 0x08;
    else
        MultiID &= ~0x08;
        
    T_MultiFunc(MultiID);
	T_HandShake(10);
}

void BlockErase(Byte StartBlock, Byte EndBlock)
{
	Byte TimeOutBlocks;
	
	TimeOutBlocks = EndBlock-StartBlock;

	if (TimeOutBlocks == 0)
		TimeOutBlocks = 1; // this means only erase 1 sector, so we delay at least 1 sector time


		debug("liz blockerase s=%d end=%d \n",StartBlock,EndBlock);

	T_BlockErase(StartBlock,EndBlock);
	Sleep(10*Flash.SE_Time*TimeOutBlocks);
	T_BlockEraseReply();
}

void Cmd_T_Erase(void)
{
	Word i, BlkStart, BlkEnd;

	debug("Cmd_T_Erase=id=%x \n",McuId);
	if (McuId == 0xa390 || McuId == 0xA400 || McuId == 0xA450)	
		Fn68390ProgramEnable(true);


		debug("Fe2pMode==%x \n",Fe2pMode);
	
	if (Fe2pMode == FE2P_MODE) {

		debug("t1---\n");
		for (i=0;i<Flash.Page/8;i+=16)   //each block = 4k
		{
			BlkStart = i;
			BlkEnd = (i+16)-2;	//with FE2P, do not erase 60~64K

			if (Flash.Page >= 4096) {
				if (BlkStart < 256)
					SetSectorErasePage(0);
				else
					SetSectorErasePage(1);
			}
			BlockErase(BlkStart,BlkEnd);
			if (ErrorFlag)
				break;
		}
	}
	else if (Fe2pMode == DIRECT_FE2P_MODE) {
			debug("t2---\n");
		if (Flash.Page >= 4096) {
			if (DirFE2P_Offset >= 256) {
				//Erase first half 8M of 16M flash.
				SetSectorErasePage(0);
				BlockErase(0,255);

				//Erase from 8M to DirFE2P_Offset.
				SetSectorErasePage(1);
				BlockErase(0,DirFE2P_Offset-1-256);

				if (DirFE2P_Length) {
					//Erase from DirFE2P_Offset+DirFE2P_Length to Flash End.
					BlkStart = DirFE2P_Offset+DirFE2P_Length-256;
				}
				else {
					//Erase from DirFE2P_Offset+4 to Flash End.
					BlkStart = DirFE2P_Offset+4-256;
				}
				BlkEnd = Flash.Page/8 -1-256;
				if(BlkEnd > BlkStart)
					BlockErase(BlkStart,BlkEnd);
			}
			else {
				//Erase from 0 to DirFE2P_Offset.
				SetSectorErasePage(0);
				BlockErase(0,DirFE2P_Offset-1);

				if (DirFE2P_Length) {
					BlkStart = DirFE2P_Offset+DirFE2P_Length; // DirFE2P_Length unit is 4k.
				}
				else {
					BlkStart = DirFE2P_Offset+4;
				}
				BlockErase(BlkStart,255);

				//Erase second half 8M of 16M flash.
				SetSectorErasePage(1);
				BlockErase(0,255);
			}
		}
		else {
			BlockErase(0,DirFE2P_Offset-1); //Erase all Flash data address < Offset

			if (DirFE2P_Length) {
				BlkStart = DirFE2P_Offset+DirFE2P_Length; // DirFE2P_Length unit is 4k.
			}
			else {
				BlkStart = DirFE2P_Offset+4;
			}
			BlkEnd = Flash.Page/8 -1;

			if (BlkEnd > BlkStart)
				BlockErase(BlkStart,BlkEnd);	 //Erase all Flash data address > Offset
		}
	}
    else if (DualFwEnable) {
			debug("t3-page--==%d\n",Flash.Page);
        // only erase Bottom/second half flash.
        if (Flash.Page >= 4096) {
			debug("t3--1--\n");
            SetSectorErasePage(1);
            BlockErase(0,255);
        }
        else {
				debug("t3--2--p=%d \n",Flash.Page);
            BlkStart = (Flash.Page/8)/2; // Mcu.Page/8 = how many sectors.
            BlkEnd = (Flash.Page/8)-1;
            BlockErase(BlkStart,BlkEnd);
        }
    }
	else {
		debug("t4---\n");
		T_ChipErase();
	    //6seconds M25P20 erase time max<6sec
	    //5seconds w25x40b erase time max<4sec
		T_HandShake(Flash.CE_Time);	
		Sleep(300*10);
		T_ChipEraseReply();
	}
    
	if (McuId == 0xa390 || McuId == 0xA400 || McuId == 0xA450)	
		Fn68390ProgramEnable(false);
}

void Cmd_T_Program(Byte Pg)
{
	T_WritePagedata(Pg);
	T_HandShake(200);	//Handshake time out 200mS, W25x40b program time 3ms x 2pages(256bytes)
	T_WritePageDataReply();
}

Byte T_GetCheckSum(Byte PageNo)
{
	Byte CheckSum;
	T_IIC_Start();
	T_IIC_Tx(0x6e);
	T_IIC_Tx(0x02);
	T_IIC_Tx(comGetCheckSum);
	T_IIC_Tx(PageNo);
	CheckSum = 0x6e^0x02^comGetCheckSum^PageNo;
	T_IIC_Tx(CheckSum);
	T_IIC_Stop();
	return 0;
}

Byte T_GetCheckSumReply(void)
{
	Byte ReplyCode,ChkH,ChkL;

	T_IIC_Start();
	T_IIC_Tx(0x6f);
	Sleep(3);	
	//PulseDelay();	//delay >100us
	T_IIC_Rx(ACK);	//length
	ReplyCode = T_IIC_Rx(ACK);	//length
	ChkH = T_IIC_Rx(ACK);	//checksum from scaler msb
	ChkL = T_IIC_Rx(ACK);	//checksum from scaler lsb
	T_IIC_Rx(NACK);
	T_IIC_Stop();
	//debug("SPageSum==%x chk=%x \n",SPageSum,(ChkH*0x100+ChkL));
	if(SPageSum != (Word)(ChkH*0x100+ChkL))
     	ErrorFlag = 1;


	//debug("T_GetCheckSumReply==%x \n",ReplyCode);
   	if((ReplyCode^comGetCheckSum)!=0xFF)
     	ErrorFlag = 1;

	return 0;
}

void T_SetExtendAddr(Byte Block)
{
	Byte CheckSum;
	T_IIC_Start();
	T_IIC_Tx(0x6e);
	T_IIC_Tx(0x02);
	T_IIC_Tx(comSetExtendAddr);	//op code =0x0f
	T_IIC_Tx(Block);
	CheckSum = 0x6e^0x02^comSetExtendAddr^Block;
	T_IIC_Tx(CheckSum);
	T_IIC_Stop();
}

Byte T_SetExtendAddrReply()
{
	Byte ReplyCode;
	T_IIC_Start();
	T_IIC_Tx(0x6f);
	//PulseDelay();	//delay >100us
	Sleep(3);	
	T_IIC_Rx(ACK);
	ReplyCode = T_IIC_Rx(ACK);
	T_IIC_Rx(ACK);
	T_IIC_Rx(NACK);
	T_IIC_Stop();
   	if((ReplyCode^comSetExtendAddr)!=0xFF)
     	ErrorFlag = 1;

		return 0;
}

void Cmd_T_GetCheckSum(Byte Pg)
{
      // debug("page-sum=%d \n",Pg);
	T_GetCheckSum(Pg);
	T_HandShake(200);	//handshake timeout 200ms
	T_GetCheckSumReply();
}

Byte Cmd_T_SetExntend(Word Pg)
{
    if ((Pg%256) == 0 && (Pg/256) <= 15)
	{
	T_SetExtendAddr(Pg>>8);
	Sleep(3);	//delay > 300us
	T_SetExtendAddrReply();
	}
	return 0;
}

Byte T_SpiCommand(Byte *Data,Byte WLen,Byte RLen)
{
    Byte i;
    Byte Length,chksum;

	char tp[7];
	memcpy(tp,Data,7);
	
    Length = (RLen<<4) | WLen;
	
	T_IIC_Start();
	T_IIC_Tx(0x6e);
	T_IIC_Tx(0x09);
	T_IIC_Tx(0x53);
    chksum = 0x6e^0x09^0x53;
	for(i=0;i<7;i++)
    	{
		T_IIC_Tx(*Data);
	    chksum ^= *Data;
    	Data++;
    	}
	T_IIC_Tx(Length);
	chksum ^= Length;
	T_IIC_Tx(chksum);
	T_IIC_Stop();

	//for(i=0;i<7;i++) debug("d=%x \n",tp[i]);


	//debug("Length=%x chksum=%x \n",Length,chksum);
	return 0;
}

Byte T_SpiCommandReply()
{
	Byte ReplyCode;
	T_IIC_Start();
	T_IIC_Tx(0x6f);
	//PulseDelay();	//delay >100us
       Sleep(2);
	T_IIC_Rx(ACK);
	ReplyCode = T_IIC_Rx(ACK);
	T_IIC_Rx(NACK);
	T_IIC_Stop();

	debug("T_SpiCommandReply=%x  r222=%x \n",ReplyCode,(ReplyCode^comSPICmd));
   	if((ReplyCode^comSPICmd)!=0xFF)
     	ErrorFlag = 1;
		return 0;

}


void Cmd_T_SendSpecialCommand()
{
    Byte i,No,temp;
	Union2 Ad,Dat;
    const Word  NT_Table[]={
        0xf054,0x00,
        0xf04f,0x11,
        0xf050,0x90,
        0xf053,0x83,
        0x8b57,0xff, 
        0x8b04,0x00,
        0x80d0,0x41,
        0x8b46,0x00,
        0xf022,0x00,
        0xf024,0x00,
        0xf067,0x20, // SE command
        0xf04c,0x40,	//set scaler speed
        };

	const Word  NT68370_380Table[] = {
        0xf0de,0x23,0xf071,0x01,0xf054,0x00,0xf04f,0x11,0xf050,0x94,0xf053,0x83, 0x8b57,0xff,0x8b04,0x00,0x80d0,0x41,0x8b46,0x00,0xf022,0x00,0xf024,0x00,
	};

	const Word  NT810_870Table[] = {
		0xf054,0x00,0xf04f,0x11,0xf050,0x90,0xf053,0x83, 0x8b57,0xff,0x8b04,0x00,0x80d0,0x41,0xf022,0x00,0xf024,0x00, // don't set 0xB46 = 0x00
		0xf050,0x91,
		0x8b3e,0xf2,
		0x8b3f,0x51,
		0x8b45,0x60,
	};

   const int  NT68390_Table[]={
		0xf0de,0x23,
		0xf1e0,0x01, // power down USB COP
		0xf1e6,0x01, // power down OSD COP
		0xf1eb,0x01, // power down DPTX COP
		0xf054,0x00,
		0xf04f,0x11,
		0xf053,0x83,
		0xf022,0x00,
		0xf024,0x00,
		0xf067,0x20, // SE command
		0xd904,0xf6,
		0xd905,0xd1,
		0xd908,0x05,
		0xd909,0x61,
		0xd90a,0xff,
		0xd90b,0x84,
		0xd90c,0x30,
		0xf054,0x00,
		//0xd929,0x04, // speed up		
	};


      debug("lizz McuId==%x \n",McuId);
	if (McuId == 0xa515) {
		T_SetRegSRAM(0xf0,0x80,0x00);
		T_HandShake(5); //wait SCL go High for 5mS
		T_SetRegSRAMReply();
	}
	
	if (McuId == 0xA390 || McuId == 0xA400 || McuId == 0xA450) {
		for(i=0;i<(sizeof(NT68390_Table)/sizeof(Word));i+=2)
		{
			Ad.w = NT68390_Table[i];
			Dat.w = NT68390_Table[i+1];
			T_SetRegSRAM(Ad.b[0],Ad.b[1],Dat.b[1]); //ex. AD.b[0]=0xf0,AD.b[1]=0x54,Dat.b[1]=0x00
			T_HandShake(5); //wait SCL go High for 5mS
			T_SetRegSRAMReply();
			if(ErrorFlag)
				return;
		}

        // set NT68400 clock speed
        T_SetRegSRAM(0xF0, 0x4C, 0x40);
		T_HandShake(5);
		T_SetRegSRAMReply();
        T_HandShake(10);
        T_SetRegSRAM(0xD9, 0x29, 0x04);
		T_HandShake(5);
		T_SetRegSRAMReply();
        Sleep(500); // T_HandShake(50);
	}
	else if (McuId == 0xa537 || McuId == 0xa380) {
		for(i=0;i<(sizeof(NT68370_380Table)/sizeof(Word));i+=2)
		{
			Ad.w = NT68370_380Table[i];
			Dat.w = NT68370_380Table[i+1];
			T_SetRegSRAM(Ad.b[0],Ad.b[1],Dat.b[1]); //ex. AD.b[0]=0xf0,AD.b[1]=0x54,Dat.b[1]=0x00
			T_HandShake(5); //wait SCL go High for 5mS
			T_SetRegSRAMReply();
			if(ErrorFlag)
				return;
		}
	}
	else if (McuId == 0xa810 || McuId == 0xa870) {
		for(i=0;i<(sizeof(NT810_870Table)/sizeof(Word));i+=2)
		{
			Ad.w = NT810_870Table[i];
			Dat.w = NT810_870Table[i+1];
			T_SetRegSRAM(Ad.b[0],Ad.b[1],Dat.b[1]); //ex. AD.b[0]=0xf0,AD.b[1]=0x54,Dat.b[1]=0x00
			T_HandShake(5); //wait SCL go High for 5mS
			T_SetRegSRAMReply();
			if(ErrorFlag)
				return;
		}
	}
	else {
		for(i=0;i<(sizeof(NT_Table)/sizeof(Word));i+=2)
		{
			Ad.w = NT_Table[i];
			Dat.w = NT_Table[i+1];
			T_SetRegSRAM(Ad.b[0],Ad.b[1],Dat.b[1]); //ex. AD.b[0]=0xf0,AD.b[1]=0x54,Dat.b[1]=0x00
			T_HandShake(5); //wait SCL go High for 5mS
			T_SetRegSRAMReply();
			if(ErrorFlag)
				return;
		}
	}
}


#if 0
void Cmd_T_BlockProtect(Bit Wp)
{
	Byte i,Cmd[7],sta;
	for(i=0;i<7;i++)
		Cmd[i] = 0;
	/*if(Flash.ByteWrite)	//SST Only
		Cmd[0] = 0x50;
	else
		Cmd[0] = 0x06;

    if(Wp)
        sta = 0x9c;
    else
        sta = 0;*/
        if(Wp){
       Cmd[0] =0xaa;
	Cmd[1] =0xaa;
	Cmd[2] =0xa0;
	Cmd[3] =0x55;

	}
	else {
	Cmd[0] =0xaa;
	Cmd[1] =0x2c;
	Cmd[2] =0x02;
	Cmd[3] =0x02;
			
	}
    T_SpiCommand(Cmd,1,0);	//WEN
	T_HandShake(20);	//timeout 20mS
	T_SpiCommandReply();
    //Cmd[0] = 0x01;
    //Cmd[1] = sta;

	 if(Wp) Cmd[0] =0x06;
	 else Cmd[0] =0x55;
    T_SpiCommand(Cmd,1,0);	//WRSR
	T_HandShake(20);	//timeout 20mS
	T_SpiCommandReply();
	//Sleep(1200);	//delay 120mS for Flash block protect time
	T_HandShake(Flash.SE_Time);	//120mS
}


void Cmd_T_BlockProtect0(void)
{
	Byte i,Cmd[7],sta;
	for(i=0;i<7;i++)
		Cmd[i] = 0;
	
       Cmd[0] =0x06;
	Cmd[1] =0x2c;
	Cmd[2] =0x02;
	Cmd[3] =0x02;

	
      T_SpiCommand(Cmd,1,0);	//WEN
	T_HandShake(20);	//timeout 20mS
	T_SpiCommandReply();
      Cmd[0] = 0x01;
      Cmd[1] = 0x00;

    T_SpiCommand(Cmd,2,0);	//WRSR
	T_HandShake(20);	//timeout 20mS
	T_SpiCommandReply();
	//Sleep(1200);	//delay 120mS for Flash block protect time
	T_HandShake(Flash.SE_Time);	//120mS
}


#else
void Cmd_T_BlockProtect(Bit Wp)
{
	Byte i,Cmd[7],sta;
	for(i=0;i<7;i++)
		Cmd[i] = 0;
	if(Flash.ByteWrite)	//SST Only
		Cmd[0] = 0x50;
	else
		Cmd[0] = 0x06;

    if(Wp)
        sta = 0x9c;
    else
        sta = 0;
    T_SpiCommand(Cmd,1,0);	//WEN
	T_HandShake(20);	//timeout 20mS
	T_SpiCommandReply();
    Cmd[0] = 0x01;
    Cmd[1] = sta;
    T_SpiCommand(Cmd,2,0);	//WRSR
	T_HandShake(20);	//timeout 20mS
	T_SpiCommandReply();
	Sleep(1200);	//delay 120mS for Flash block protect time
	T_HandShake(Flash.SE_Time);	//120mS
}

#endif


EXPORT_SYMBOL(Cmd_T_BlockProtect);


void T_RunNewSPICmd(void)
{
	Byte CheckSum;
	
	T_IIC_Start();
	T_IIC_Tx(0x6e);
	T_IIC_Tx(0x01);
	T_IIC_Tx(0x25);
	CheckSum = 0x6e^0x01^0x25;
	T_IIC_Tx(CheckSum);
	T_IIC_Stop();
}

void T_RunNewSPICmdReply(void)
{
	Byte Status;
	
	T_IIC_Start();
	T_IIC_Tx(0x6f);
//	PulseDelay();
	//PulseDelay();
	Sleep(3);	
	T_IIC_Rx(ACK);
	Status = T_IIC_Rx(ACK);
	T_IIC_Rx(NACK);
	T_IIC_Stop();
	if((Status^0x25) != 0xff)
		ErrorFlag = 1;
}

void FnSetSPICmdBufAndBackUpValue()
{
	Byte Dat, tmp, i;

	T_HandShake(10);
	T_GetRegSRAM(0xa0,0x00);
    T_HandShake(5);
    Dat = T_GetRegSRAMReply();
	tmp = Dat;
	
	T_SetRegSRAM(0xa0,0x00,0xaa);
	T_HandShake(5);
	T_SetRegSRAMReply();

	T_HandShake(10);
	T_GetRegSRAM(0xa0,0x00);
	T_HandShake(5);
	Dat = T_GetRegSRAMReply();	
	if (Dat == 0xaa) {
		T_SetRegSRAM(0xa0,0x00,0x55);
		T_HandShake(5);
		T_SetRegSRAMReply();
		T_HandShake(100);
		T_GetRegSRAM(0xa0,0x00);
		T_HandShake(5);
		Dat = T_GetRegSRAMReply();	

		if (Dat == 0x55) {
			usSPICmdBufAddr = 0xa800;
		}
		else
			usSPICmdBufAddr = 0x9800;
	}
	else {
		usSPICmdBufAddr = 0x9800;
	}
	T_SetRegSRAM(0xa0,0x00,0x55);
	T_HandShake(5);
	T_SetRegSRAMReply();
	T_HandShake(10);

	// back up f0c0~f0c6
	for (i=0; i<sizeof(ucSPI_BackUpBuf); i++) {
		T_GetRegSRAM(0xf0,0xc0+i);
		T_HandShake(5);
		Dat = T_GetRegSRAMReply();	
		ucSPI_BackUpBuf[i] = Dat;
		//printf("%x ",(Word)Dat);
	}
}

void RestoreSPIRegValue()
{
	Byte i;

	for (i=0; i<sizeof(ucSPI_BackUpBuf); i++) {		
		T_SetRegSRAM(0xf0,0xc0+i,ucSPI_BackUpBuf[i]);
		T_HandShake(5);
		T_SetRegSRAMReply();
		T_HandShake(10);
	}
}

Bool CheckSpecialFlash(void)
{
    Byte WrtCntTab[16] = {0};
    Byte WData[16] = {0};
	Byte WrtCntTabLength = 0;
	Byte WDataLength = 0;
    Word SPI_Cmd_Buf_Addr = usSPICmdBufAddr;
    Word TmpAddr;
    Word i;
    Byte F0C0_value, dummy;
    Byte RData[16] = {0};

	Byte Id;
	Byte fID[3];
	Byte ret;

	// Setup write count table and write data sequence according to different flash spec.
	// WrtCntTabLength and WDataLength will accumulate automatically.
	WrtCntTab[WrtCntTabLength++] = 1;
	WrtCntTab[WrtCntTabLength++] = 3;
	WData[WDataLength++] = 0x9f;

    TmpAddr = SPI_Cmd_Buf_Addr;
    F0C0_value = (WrtCntTabLength/2)<<4|0x03;
	
	T_SetRegSRAM(0xf0,0xc0,F0C0_value);
	T_HandShake(5);
	T_SetRegSRAMReply();

	T_SetRegSRAM(0xf0,0xc1,SPI_Cmd_Buf_Addr>>8);
	T_HandShake(5);
	T_SetRegSRAMReply();

    dummy = SPI_Cmd_Buf_Addr&0xFF;	
	T_SetRegSRAM(0xf0,0xc2,dummy);
	T_HandShake(5);
	T_SetRegSRAMReply();
	
	T_SetRegSRAM(0xf0,0xc3,SPI_Cmd_Buf_Addr>>8);
	T_HandShake(5);
	T_SetRegSRAMReply();

    dummy = (SPI_Cmd_Buf_Addr + WrtCntTabLength)&0xFF;	
	T_SetRegSRAM(0xf0,0xc4,dummy);
	T_HandShake(5);
	T_SetRegSRAMReply();

	T_SetRegSRAM(0xf0,0xc5,SPI_Cmd_Buf_Addr>>8);
	T_HandShake(5);
	T_SetRegSRAMReply();

    dummy = (SPI_Cmd_Buf_Addr + WrtCntTabLength + WDataLength)&0xFF;
	T_SetRegSRAM(0xf0,0xc6,dummy);
	T_HandShake(5);
	T_SetRegSRAMReply();

    for (i=0; i<WrtCntTabLength; i++) {		
		T_SetRegSRAM((Byte)(TmpAddr>>8),(Byte)TmpAddr,WrtCntTab[i]);
		T_HandShake(5);
		T_SetRegSRAMReply();
		TmpAddr++;
    }
    for (i=0; i<WDataLength; i++) {
		T_SetRegSRAM((Byte)(TmpAddr>>8),(Byte)TmpAddr,WData[i]);
		T_HandShake(5);
		T_SetRegSRAMReply();
		TmpAddr++;
    }

    // send New SPI Command.
    T_RunNewSPICmd();
	T_HandShake(100);
	T_RunNewSPICmdReply();
	T_HandShake(200);

    for (i=0; i<sizeof(RData); i++) {		
		T_GetRegSRAM((Byte)((SPI_Cmd_Buf_Addr+i)>>8),(Byte)(SPI_Cmd_Buf_Addr+i));
		T_HandShake(5);
		RData[i] = T_GetRegSRAMReply();	
		//printf("RData[%d]=%x\r\n", (Word)i, (Word)RData[i]);
    }
	
	// Read return data and identify which flash
	// W25Q16DV flash
	fID[0] = RData[WrtCntTabLength + WDataLength];
	fID[1] = RData[WrtCntTabLength + WDataLength+1];
	fID[2] = RData[WrtCntTabLength + WDataLength+2];

	debug("lizz flash id1===%x  id2=%x id3=%x \n",fID[0],fID[1],fID[2]);

	Id = SearchFlashID(fID);

	
	if(Id != 0xff)
	{
	    Flash = FlashIDTable[Id];    //default flash PMC010A W/O fe2p

		debug("lizz flash=%s \n",Flash.Name);
		MaxPages = Flash.Page;
		T_SetRegSRAM(0xf0,0x67,Flash.SE_Code);
		T_HandShake(5);
		T_SetRegSRAMReply();
		
		//MultiID = 0x04;	//MX2026 CMD if use this flash
		MultiID = 0x00;
		
		if(Flash.ByteWrite && ErrorFlag == 0)
			MultiID |= 0x02;
		ret = T_MultiFunc(MultiID);	//Byte Write
		T_HandShake(5);
		return true;
	}
	
    return false;
}

Byte SearchFlashID(Byte *mcuFlashID)
{
    Byte i,j;
    Byte m1,m2,m3;
	
    for(i=0;i<128;i++)
	{
        m1 = 0;
		m2 = 0;
		m3 = 0;
        if(FlashIDTable[i].ID1 == 0xff)
        	break;
        for(j=0;j<3;j++)
    	{
        	if(mcuFlashID[j] == FlashIDTable[i].ID1 && !m1)
            	m1 = 1;
            else
                if(mcuFlashID[j] == FlashIDTable[i].ID2 && !m2)
                	m2 = 1;
            else
                if(mcuFlashID[j] == FlashIDTable[i].ID3 && !m3)
                	m3 = 1;
        }
        if(FlashIDTable[i].ID3 == 0xff)
        	m3 = 1;
        if(m1 && m2 && m3)
			return i;
    }
	return 0xff;
}

void Cmd_T_GetFlashID()
{
    Byte SPI_ID_Tab[]={0x90,0x9f,0xab};
	Byte i,l,Id;
	Byte Data;
	Byte fID[3];
	Word ret;

	debug("lizz Cmd_T_GetFlashID=\n");
	
	Flash.En = 0;

	// use new spi command to get flash id
	FnSetSPICmdBufAndBackUpValue();
	if (CheckSpecialFlash()) {
		RestoreSPIRegValue();
		return;
	}
	RestoreSPIRegValue();

	debug("lizz Cmd_T_GetFlashID=2===\n");
	
    for(l=0;l<3;l++)
    {
		T_SetRegSRAM(0xf0,0x68,SPI_ID_Tab[l]);
		T_HandShake(5);
		T_SetRegSRAMReply();
		if(ErrorFlag)
		{
			return;
		}
		T_GetVersion();
		T_HandShake(20);	//delay 20mS
        for(i=0;i<3;i++)
        {
            T_GetRegSRAM(0xf0,0x64+i);
            T_HandShake(5);
            Data = T_GetRegSRAMReply();
			if(ErrorFlag)
			{
				return;
			}
			fID[i] = Data;	
            if(fID[0] == 0x00 || fID[0] == 0xff)
                break;
        }
		Id = SearchFlashID(fID);

		debug("flashid=%x \n",Id);
		if(Id != 0xff)
		{
		    Flash = FlashIDTable[Id];    //default flash PMC010A W/O fe2p
			MaxPages = Flash.Page;
			T_SetRegSRAM(0xf0,0x67,Flash.SE_Code);
			T_HandShake(5);
			T_SetRegSRAMReply();
			//MultiID = 0x04;	//MX2026 CMD if used.
			MultiID = 0x00;
			if(Flash.ByteWrite && ErrorFlag == 0)
				MultiID |= 0x02;
			
			T_MultiFunc(MultiID);	//Byte Write
			T_HandShake(5);
			return;
		}
	}
}

Bool CheckOverLap(Word PageNo)
{
    ULong i,Offset;

    if(Fe2pMode == DIRECT_FE2P_MODE)
    {
        Offset = DirFE2P_Offset*4096;

        if (DirFE2P_Length) {
            if((PageNo*512) >= Offset && (PageNo*512)<(Offset+DirFE2P_Length*4096))
                return true;
        }
        else {
            if((PageNo*512) >= Offset && (PageNo*512)<(Offset+16384))   //FE2P area max 16K
                return true;
        }
    }
    else if (Fe2pMode == FE2P_MODE) {
        for(i=0;i<1024;i+=128)  //max 512k 8*64K banks
        {
            if(PageNo > 119+i && PageNo <128+i)
                return true;
        }
    }

    return false;
}

void Fn68390ProgramEnable(Bit En)
{
	Byte ret;

	T_GetRegSRAM(0xF0,0xDE);
	T_HandShake(5); //wait SCL go High for 5mS
	ret = T_GetRegSRAMReply();
	Sleep(100);

	if (En) {
		ret &= ~0x02;
		T_SetRegSRAM(0xF0,0xDE,ret);
		T_HandShake(5); //wait SCL go High for 5mS
		T_SetRegSRAMReply();
		Sleep(20);
	}
	else {
		ret |= 0x02;
		T_SetRegSRAM(0xF0,0xDE,ret);
		T_HandShake(5); //wait SCL go High for 5mS
		T_SetRegSRAMReply();
		Sleep(20);
	}
}

void WpEnable(void)
{
    const unsigned short McuAddr[][3]={
        {0xf005,0xf000,0xf0b0}, //PA
        {0xf006,0xf001,0xf0b1}, //PB
        {0xf007,0xf002,0xf0b2}, //PC
        {0xf008,0xf003,0xf0b3}, //PD
		{0xf009,0xf004,0xf0b4}, //PE
		{0xf011,0xf010,0xf0b5}, //PF

        {0xf012,0xf013,0xf0b6}, //PG
        {0xf114,0xf115,0xf130}, //PH
        {0xf116,0xf117,0xf131}, //PI
        {0xf118,0xf119,0xf132}, //PJ
		{0xf11A,0xf11B,0xf133}, //PK
		{0xf11C,0xf11D,0xf134}, //PL
		{0xf11E,0xf11F,0xf135}, //PM
    };
    Byte temp;
    Byte Mask;
    int i,j;

    for (i=0;i<13;i++) {
		if (i >= 5 && i <= 6) { // PortF, PortG
			if (McuId != 0xa537 && McuId != 0xa380 && McuId != 0xa390 && McuId != 0xA400 && McuId != 0xA450)
				break;
		}
		else if (i >=7) { // PortH~M
			if (McuId != 0xa390 && McuId != 0xA400 && McuId != 0xA450)
				break;
		}
			
        switch(i) {
        case 0:
            Mask = WpDefine >> 24;  //PA7-0
            Mask &= 0xff;
            break;
        case 1:
            Mask = WpDefine >> 16;  //PB7-0
            Mask &= 0xff;
            break;
        case 2:
            Mask = WpDefine >> 8;  //PC7-0
            Mask &= 0xff;
            break;
        case 3:
            Mask = (Byte)WpDefine;  //PD7-0
            Mask &= 0xff;
            break;
		case 4:
			Mask = Wp_PortE;
			Mask &= 0xff;
			break;
		case 5:
			Mask = Wp_PortF;
			Mask &= 0xff;
			break;
			
        case 6:
            Mask = (Byte)Wp_PortG_J;  //PG7-0
            Mask &= 0xff;
            break;
        case 7:
            Mask = Wp_PortG_J >> 8;  //PH7-0
            Mask &= 0xff;
            break;
        case 8:
            Mask = Wp_PortG_J >> 16;  //PI7-0
            Mask &= 0xff;
            break;
        case 9:
            Mask = Wp_PortG_J >> 24;  //PJ7-0
            Mask &= 0xff;
            break;
			
		case 10:
			Mask = (Byte)Wp_PortK_M;  //PK7-0
			Mask &= 0xff;
			break;
		case 11:
			Mask = Wp_PortK_M >> 8;	  //PL7-0
			Mask &= 0xff;
			break;
		case 12:
			Mask = Wp_PortK_M >> 16;  //PM7-0
			Mask &= 0xff;
			break;
        };

        for (j=0;j<3;j++) {
			T_GetRegSRAM(McuAddr[i][j]>>8,(Byte)McuAddr[i][j]);
			T_HandShake(5); //wait SCL go High for 5mS
			temp = T_GetRegSRAMReply();
			Sleep(100);
	
			if(j == 0)	//Port direction
				temp &= ~Mask;
			else
				if(j == 1) // Port Hi/Lo
				{
					temp |= Mask;
				}
				else
					if(j == 2)	//Port struct
						temp |= Mask;
            
			T_SetRegSRAM(McuAddr[i][j]>>8,(Byte)McuAddr[i][j],temp);
			T_HandShake(5); //wait SCL go High for 5mS
			T_SetRegSRAMReply();
			Sleep(20);
        }
    }
}

void FnEraseIDSector(void)
{
    Word SectorNo;
	SectorNo = (0xEFF0/4096); // make ID string address as sector unit.
	
	if (Flash.Page >= 4096) {
		SetSectorErasePage(0);
		BlockErase(SectorNo,SectorNo);
	}
	else {
		BlockErase(SectorNo,SectorNo);
	}
}

Bit FnUpdateIDSector(void)
{
	Byte  Data[512];
    Word Checksum=0;
	Word i,IDPageNo;
	
	IDPageNo = (0xEFF0/512); // make ID string address as page unit.

    //backup bin buffer then update data
    for (i=0;i<512;i++) {
        Data[i] = BinFilePageBuffer[i];
        BinFilePageBuffer[i] = 0xff;
    }
    
	// copy ID to the buffer
    BinFilePageBuffer[0x1F0] = 'D';
    BinFilePageBuffer[0x1F1] = 'U';
    BinFilePageBuffer[0x1F2] = 'A';
    BinFilePageBuffer[0x1F3] = 'L';
    BinFilePageBuffer[0x1F4] = 'F';
    BinFilePageBuffer[0x1F5] = 'W';
    
	// set flash bank number
    BinFilePageBuffer[0x1F6] = Flash.Page/128;

    // calculate checksum
    for (i=0;i<512;i++) {
        Checksum += BinFilePageBuffer[i];
    }
    SPageSum = Checksum;

	Fn68390ProgramEnable(true);
    Cmd_T_SetExntend(0);
	if(ErrorFlag == 0)
	{
        Cmd_T_Program(IDPageNo);	
        if(ErrorFlag) {
            Fn68390ProgramEnable(false);
            // restore buffer
            for (i=0;i<512;i++) {
                BinFilePageBuffer[i] = Data[i];
            }
            return false;
        }

        Cmd_T_GetCheckSum(IDPageNo);
        if(ErrorFlag) {
            Fn68390ProgramEnable(false);
            // restore buffer
            for (i=0;i<512;i++) {
                BinFilePageBuffer[i] = Data[i];
            }
            return false;
        }
	}
	Fn68390ProgramEnable(false);

    // restore buffer
    for (i=0;i<512;i++) {
        BinFilePageBuffer[i] = Data[i];
    }
    return true;
}



void exit_isp(void ){

Cmd_T_BlockProtect(1); 
	  T_ISPMode(0);   //exit ISP mode 
	  

}


EXPORT_SYMBOL(exit_isp);

struct rk_screen * rk_get_screen(void);



void ISP_Process(void)
{
    Word Page,i;
    Bit SkipPage;
    ErrorFlag = 0;

	// Must initial fe2p related settings
	Fe2pMode = NORMAL_MODE;
	DirFE2P_Offset = 0;
	DirFE2P_Length = 0;
    DualFwEnable =0;// 1; // if adopt dual f/w, need to set as 1, otherwise set as 0.


struct  file *file = NULL;
      char *path="/etc/1920.bin";
	mm_segment_t old_fs;
	ssize_t ret;
	char *bin_buf;
	bin_buf = kmalloc(128*1024, GFP_KERNEL);

	

	//memset(eth_mac, 0, 6);

	struct rk_screen *screen=NULL;
	screen=rk_get_screen();
      printk("x=%d y=%d \n",screen->mode.xres,screen->mode.yres);
      printk("screen->face=%d screen->lvds_format=%d \n",screen->face,screen->lvds_format); 
      if(screen->mode.xres==1920&&screen->mode.yres==1080){

		if(screen->face==1){ //6bit

		path="/etc/1920-6bit.bin";

		}
		else {
		if(screen->lvds_format==0) path="/etc/1920.bin";
		else if(screen->lvds_format==1) path="/etc/1920-2.bin";	
		}
	}
      else if(screen->mode.xres==1366&&screen->mode.yres==768){
		  path="/etc/1366.bin"; 

      }
      else if(screen->mode.xres==1280&&screen->mode.yres==1024){
		  path="/etc/1280x1024.bin"; 

      }
	
	//file = filp_open("/system/etc/1920.bin", O_RDWR|O_CREAT,0644);
	file = filp_open(path, O_RDWR|O_CREAT,0644);
	if (IS_ERR(file))
	{
		printk("open failed.");
		return -ENOENT;
	} 

	old_fs = get_fs();
    	set_fs(get_ds());
    
    	file->f_op->llseek(file,0,0);
    	ret = file->f_op->read(file, bin_buf, 128*1024, &file->f_pos);
    
    	set_fs(old_fs);
    
   	 if(ret > 0){

#if 0
		int n;
		printk("--start---\n");
		for (n= 0;n< 128*1024;n++){
			if(n%16==0) printk("%08x ",n);
			printk("%02x ",bin_buf[n]);
			  if(n%16==15) printk("\n");
		}
		printk("--end---\n");
#endif		
	 }


filp_close(file,NULL);

debug("lizz isp1111\n");


	gpio_request(SCL_PIN, NULL);
	gpio_request(SDA_PIN, NULL);

	SET_SCL_L;//write_data(sda, 0);
	udelay(6);
	SET_SCL_L;//write_data(scl, 0);
	udelay(14);
 
	// stop 
 
	SET_SCL_H;//write_data(sda, 1);
	udelay(6);
	SET_SCL_H;//write_data(scl, 1);
	udelay(20);
	

    //Set HOST IIC to <=70KHz
    Cmd_T_EnterIsp();
    //Speed up HOST IIC to 300~400KHz

	//send_asc("ErrorFlag==",ErrorFlag);

	debug("ErrorFlag==%x \n",ErrorFlag);
    if(ErrorFlag)
        goto end;

	debug("lizz isp222\n");

    if (DualFwEnable)
        FnEraseIDSector();
    
    Cmd_T_Erase();

	debug("lizz isp333\n");

	debug("ErrorFlag5==%x \n",ErrorFlag);
    if(ErrorFlag)
        goto end;

    MaxPages = Flash.Page;
    
    if (DualFwEnable) {
        CodePages = MaxPages/2;
        FlashOffset = MaxPages/2;
    }
    else {
        CodePages = MaxPages;
        FlashOffset = 0;
    }

	//send_int16("McuId===",McuId);

      debug("McuId==%x \n",McuId);

	debug("lizz isp444\n");

	if (McuId == 0xa390 || McuId == 0xA400 || McuId == 0xA450)	
		Fn68390ProgramEnable(true);
	
    for(Page=FlashOffset;Page<(CodePages+FlashOffset);Page++)	// 1024pages for 4M flash
    {

	int cnt=Page;
	cnt%=256;
	cnt*=512;

      printk("Page=%d \n",Page);
	memcpy(BinFilePageBuffer,bin_buf+cnt,512);

        Cmd_T_SetExntend(Page);
		
        if(ErrorFlag)
            goto end;

        SPageSum = 0;	//bin file page checksum
        SkipPage = 1;
        for(i=0;i<512;i++)
        {
            //binFilePageBuffer is use for binary file page buffer, size is 512bytes
            if(BinFilePageBuffer[i] != 0xff)	//not empty
                SkipPage = 0;
            SPageSum += BinFilePageBuffer[i];	//calculate binary file page checksum
        }

		//debug("lizz isp555\n");

		if (CheckOverLap(Page))
			SkipPage = 1;

        if(!SkipPage)	//Bypass program?
            Cmd_T_Program(Page);	
        if(ErrorFlag){

			debug("Cmd_T_Program err \n");
            goto end;
        	}


		//debug("lizz isp666\n");

        if(!SkipPage)	//Bypass compare?
            Cmd_T_GetCheckSum(Page);
        if(ErrorFlag){

		debug("Cmd_T_GetCheckSum err \n");
            goto end;
        	}

		
		
    }


	debug("lizz isp777\n");
	
	if (McuId == 0xa390 || McuId == 0xA400 || McuId == 0xA450)	
		Fn68390ProgramEnable(false);


	debug("lizz isp888\n");
    
    if (DualFwEnable) {
        if (FnUpdateIDSector() == false)
            goto end;
    }

	debug("lizz isp9999\n");
    
    end:

		kfree(bin_buf);
		debug("lizz ispeeeeeeeeeee-end--\n");
        Cmd_T_BlockProtect(1); 
        T_ISPMode(0);	//exit ISP mode and reset
		
}


EXPORT_SYMBOL(ISP_Process);

 \sdk\kernel\drivers\video\backlight\pwm_bl.c

 sdk\kernel\drivers\char\ir_drv.c

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

旋风旋风

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值