[Feature][ZXW-179]merge P52U02 version

Only Configure: No
Affected branch: master
Affected module: unknow
Is it affected on both ZXIC and MTK: only ZXIC
Self-test: Yes
Doc Update: No

Change-Id: I4fa8f86757e71388ae88400914dae8b50cd00338
diff --git a/ap/os/linux/linux-3.4.x/drivers/cpko/cpko_main.c b/ap/os/linux/linux-3.4.x/drivers/cpko/cpko_main.c
index 0156d92..f8b5c94 100755
--- a/ap/os/linux/linux-3.4.x/drivers/cpko/cpko_main.c
+++ b/ap/os/linux/linux-3.4.x/drivers/cpko/cpko_main.c
@@ -82,30 +82,30 @@
 unsigned int __comm_modem_text_start;unsigned int modem_text_end;unsigned int 
 cpko_data_start;unsigned int cpko_bss_start;unsigned int cpko_text_offset;}
 cpko_section_layout;cpko_section_layout cpko_ps_section;int raise(int signo){
-return(0x206f+93-0x20cc);}extern unsigned int SysEntry(void);static int 
+return(0x171+4684-0x13bd);}extern unsigned int SysEntry(void);static int 
 ko_Main_Thread(void*data){struct sched_param param={.sched_priority=
-MAX_USER_RT_PRIO/(0xbb5+4500-0x1d47)-(0x1a9f+2511-0x246b)};int ret=
-(0xea4+1943-0x163b);sched_setscheduler(current,SCHED_FIFO,&param);ret=SysEntry()
-;if(ret!=(0xe82+1292-0x138e))panic("Main_Thread\n");param.sched_priority=
-MAX_USER_RT_PRIO-(0x61a+276-0x700);sched_setscheduler(kthreadd_task,SCHED_FIFO,&
-param);return(0x11f5+5025-0x2596);}int zte_modem_ko_start(void){kthread_run(
+MAX_USER_RT_PRIO/(0x73+9710-0x265f)-(0x67a+3427-0x13da)};int ret=
+(0xd57+70-0xd9d);sched_setscheduler(current,SCHED_FIFO,&param);ret=SysEntry();if
+(ret!=(0x13f8+3144-0x2040))panic("Main_Thread\n");param.sched_priority=
+MAX_USER_RT_PRIO-(0x267+6787-0x1cbc);sched_setscheduler(kthreadd_task,SCHED_FIFO
+,&param);return(0x14f0+1755-0x1bcb);}int zte_modem_ko_start(void){kthread_run(
 ko_Main_Thread,NULL,"\x5a\x54\x45\x4d\x61\x69\x6e\x54\x68\x72\x65\x61\x64");
-return(0x413+6337-0x1cd4);}static void cpko_sectioninfo_set(void){int ret;struct
- file*fp;mm_segment_t old_fs;loff_t cpko_pos=(0x18fb+3159-0x2552);struct 
+return(0x1fa0+1069-0x23cd);}static void cpko_sectioninfo_set(void){int ret;
+struct file*fp;mm_segment_t old_fs;loff_t cpko_pos=(0x1e57+1652-0x24cb);struct 
 cpps_globalModem globalVar;fp=filp_open(
 "\x2f\x6c\x69\x62\x2f\x63\x70\x6b\x6f\x2f\x63\x70\x6b\x6f\x5f\x73\x65\x63\x69\x6e\x66\x6f\x2e\x62\x69\x6e"
-,(0xe1a+5551-0x23c9),(0x8eb+2503-0x12b2));if(IS_ERR(fp)||fp==NULL)panic(
+,(0x12f9+2130-0x1b4b),(0x5f9+6793-0x2082));if(IS_ERR(fp)||fp==NULL)panic(
 "\x6f\x70\x65\x6e\x20\x66\x69\x6c\x65\x20\x65\x72\x72\x6f\x72" "\n");old_fs=
 get_fs();set_fs(KERNEL_DS);ret=vfs_read(fp,(char*)&cpko_ps_section,sizeof(
-cpko_section_layout),&cpko_pos);if(ret<=(0x1000+5673-0x2629))panic(
+cpko_section_layout),&cpko_pos);if(ret<=(0x5f5+5890-0x1cf7))panic(
 "\x72\x65\x61\x64\x20\x66\x69\x6c\x65\x20\x65\x72\x72\x6f\x72" "\n");filp_close(
 fp,NULL);
 #ifdef CONFIG_MODEM_CODE_IS_MAPPING
 fp=filp_open(
 "\x2f\x6c\x69\x62\x2f\x63\x70\x6b\x6f\x2f\x63\x70\x6b\x6f\x2e\x6b\x6f",
-(0x12bc+3747-0x215f),(0xa52+6384-0x2342));if(IS_ERR(fp)||fp==NULL)panic(
+(0xa83+3340-0x178f),(0x5c5+7296-0x2245));if(IS_ERR(fp)||fp==NULL)panic(
 "\x6f\x70\x65\x6e\x20\x66\x69\x6c\x65\x20\x65\x72\x72\x6f\x72" "\n");fp->f_ra.
-ra_pages=(0xcb9+2686-0x1737);
+ra_pages=(0xeec+1627-0x1547);
 #endif
 if(cpko_ps_section.cpko_text_start){globalVar.cpko_text_start=(unsigned long)
 cpko_ps_section.cpko_text_start;globalVar.cpko_rodata_start=(unsigned long)
@@ -125,7 +125,7 @@
 vfree_modem_section(globalVar.cpko_text_start,globalVar.modem_text_end);
 #endif
 }else panic("\x66\x69\x6c\x65\x20\x65\x72\x72\x6f\x72" "\n");}static int 
-cpko_start(void){struct cpps_callbacks callback={(0x189d+3603-0x26b0)};callback.
+cpko_start(void){struct cpps_callbacks callback={(0xb25+3026-0x16f7)};callback.
 zOss_ResetNVFactory=zOss_ResetNVFactory;callback.zOss_NvramFlush=zOss_NvramFlush
 ;callback.zOss_NvItemWrite=zOss_NvItemWrite;callback.zOss_NvItemWriteFactory=
 zOss_NvItemWriteFactory;callback.zOss_NvItemRead=zOss_NvItemRead;callback.
@@ -196,5 +196,5 @@
 psm_GetModemSleepFlagStatus=psm_GetModemSleepFlagStatus;
 #endif
 cpps_callbacks_register(&callback);cpko_sectioninfo_set();zte_modem_ko_start();
-return(0xcac+1499-0x1287);}static int cpko_stop(void){return(0x70b+453-0x8d0);}
-module_init(cpko_start);module_exit(cpko_stop);
+return(0x6aa+3593-0x14b3);}static int cpko_stop(void){return(0xaf3+1843-0x1226);
+}module_init(cpko_start);module_exit(cpko_stop);
diff --git a/ap/os/linux/linux-3.4.x/drivers/misc/zcat/Makefile b/ap/os/linux/linux-3.4.x/drivers/misc/zcat/Makefile
index 44df896..4358cf2 100755
--- a/ap/os/linux/linux-3.4.x/drivers/misc/zcat/Makefile
+++ b/ap/os/linux/linux-3.4.x/drivers/misc/zcat/Makefile
@@ -11,4 +11,6 @@
 ifndef CONFIG_SYSTEM_CAP
 obj-y	+= logcat_drv_cp.o
 endif
-endif
\ No newline at end of file
+endif
+
+ccflags-y += -I$(TOPDIR)/pub/include/tools
\ No newline at end of file
diff --git a/ap/os/linux/linux-3.4.x/drivers/misc/zcat/debug_info.c b/ap/os/linux/linux-3.4.x/drivers/misc/zcat/debug_info.c
index 00b5cbe..5ac8819 100755
--- a/ap/os/linux/linux-3.4.x/drivers/misc/zcat/debug_info.c
+++ b/ap/os/linux/linux-3.4.x/drivers/misc/zcat/debug_info.c
@@ -31,6 +31,7 @@
 // #include "debuginfo.h"
 #include "pub_debug_info.h"
 #include "ringbuf.h"
+#include "ZspTrace.h"
 
 #if defined(_USE_ZXIC_DEBUG_INFO) && !defined(CONFIG_SYSTEM_RECOVERY)
 /*******************************************************************************
@@ -45,6 +46,7 @@
 
 #define DEBUG_INFO_CHANNEL          (channel_9)
 #define DEBUG_INFO_MSG_CAP_SIZE     (2 * 1024)
+#define DEBUG_INFO_SWITCH_ON        (0)
 
 // #define DEBUG_INFO_MEM_TYPE_KERNEL  (0)
 // #define DEBUG_INFO_MEM_TYPE_USER    (1)
@@ -196,9 +198,15 @@
 
 static int sc_debug_info_send_to_cap(T_SHARED_MEM_DATA *debug_msg, unsigned int len)
 {
-    int ret;
+    int    ret = -1;
+    UINT32 wake_flag = 0;
     T_ZDrvRpMsg_Msg rpmsg = {0};
-
+	
+    wake_flag = *(volatile UINT32 *)ZCAT_DEBUG_INFO_DISABLE;
+    if (wake_flag != DEBUG_INFO_SWITCH_ON)
+    {
+        return ret;
+    }
     rpmsg.actorID = CAP_ID;
     rpmsg.chID = DEBUG_INFO_CHANNEL;
     rpmsg.flag = RPMSG_WRITE_INT;
diff --git a/ap/os/linux/linux-3.4.x/drivers/mtd/mtdadapter.c b/ap/os/linux/linux-3.4.x/drivers/mtd/mtdadapter.c
old mode 100644
new mode 100755
index c7b418a..1cc4218
--- a/ap/os/linux/linux-3.4.x/drivers/mtd/mtdadapter.c
+++ b/ap/os/linux/linux-3.4.x/drivers/mtd/mtdadapter.c
@@ -19,6 +19,7 @@
 #include <linux/kernel.h> 
 #include <linux/mtd/mtd.h>
 #include <linux/module.h>
+#include <linux/soc/zte/otp/otp_zx.h>
 
 #define READ_ZLOADER_FLAG_SIZE 0x800
 #define WRITE_ZLOADER_FLAG_SIZE 0x3000
@@ -26,6 +27,8 @@
 
 extern struct mtd_info *mtd_fota;
 extern int g_zload_read_only_flag;
+extern char *nor_cmdline;
+unsigned char nor_flag = 0;
 
 #ifndef USE_CPPS_KO
 extern unsigned int zOss_NvItemRead(unsigned int NvItemID, unsigned char *NvItemData, unsigned int NvItemLen);
@@ -212,23 +215,59 @@
     if( buffer == NULL )
         return -1;
 
-    if(mtd_read(mtd_fota,0,READ_ZLOADER_FLAG_SIZE,&retlen,buffer))/* BOOTFLAGÔÚnandµÄµÚ20~27×Ö½Ú */
-    {
-        kfree(buffer);
-        return 1;
-    }
-	memcpy(&value, buffer+2, 1); 
-	bootflag = value;
-   
-    if( bootflag == 0x5a)
-    {
-        bootflag = 1;
-    }
+	if(nor_cmdline != NULL)
+	{
+		if (!strcmp(nor_cmdline, "1"))
+		{
+		    nor_flag = 1;
+			printk("----------EnhancedSecurity---------\n");
+		}
+	}
+	if(1 == nor_flag)
+	{
+#ifndef CONFIG_SPI_ZXIC_NOR
+
+		if(nor_read(0, 256, buffer))
+	    {
+	        kfree(buffer);
+	        return 1;
+	    }
+		memcpy(&value, buffer+2, 1); 
+		bootflag = value;
+	   
+	    if( bootflag == 0x5a)
+	    {
+	        bootflag = 1;
+	    }
+		else
+		{
+	        bootflag = 0;
+		}
+	    kfree(buffer);
+#endif
+	}
 	else
 	{
-        bootflag = 0;
-	}
-    kfree(buffer);
+		if(mtd_read(mtd_fota,0,READ_ZLOADER_FLAG_SIZE,&retlen,buffer))/* BOOTFLAGÔÚnandµÄµÚ20~27×Ö½Ú */
+	    {
+	        kfree(buffer);
+	        return 1;
+	    }
+		memcpy(&value, buffer+2, 1); 
+		bootflag = value;
+	   
+	    if( bootflag == 0x5a)
+	    {
+	        bootflag = 1;
+	    }
+		else
+		{
+	        bootflag = 0;
+		}
+	    kfree(buffer);
+
+	}  
+    
 
 	return bootflag;
 }
@@ -246,38 +285,87 @@
 	int bootflag = 0;
 	int retlen = 0;
     struct erase_info ei;
-	
-    unsigned char *buffer = kzalloc(WRITE_ZLOADER_FLAG_SIZE,GFP_KERNEL);
 
-    if( buffer == NULL )
-        return -1;
-
-    if(mtd_read(mtd_fota,0,WRITE_ZLOADER_FLAG_SIZE,&retlen,buffer))/* BOOTFLAGÔÚnandµÄµÚ20~27×Ö½Ú */
-    {
-        kfree(buffer);
-        return -1;
-    }
-	if(flag == 0 )
+	if(nor_cmdline != NULL)
 	{
-	    bootflag = 0x00;
-        memset(&value, bootflag, 1);
+		if (!strcmp(nor_cmdline, "1"))
+		{
+		    nor_flag = 1;
+			printk("----------EnhancedSecurity---------\n");
+		}else{
+			printk("----------normal---------\n");
+		}
+	}else{
+	    printk("----------nor cmdline is null!---------\n");
 	}
-    else
-    {
-        bootflag = 0x5a;
-        memset(&value, bootflag, 1);
-    }
+
+	if(1 == nor_flag)
+	{
+#ifndef CONFIG_SPI_ZXIC_NOR
+
+	    unsigned char *buffer = kmalloc(0x10000, GFP_KERNEL);
+
+	    if( buffer == NULL )
+	        return -1;
 	
-    memcpy(buffer+2, &value, 1);
-    memset(&ei, 0, sizeof(struct erase_info));
-    ei.mtd  = mtd_fota;
-    ei.addr = 0;
-    ei.len  = mtd_fota->erasesize;
-	g_zload_read_only_flag = 1;
-    ret = mtd_erase(mtd_fota, &ei);                  /*²Á³ýµÚÒ»¿é*/
-	ret = mtd_write(mtd_fota,0,WRITE_ZLOADER_FLAG_SIZE,&retlen,buffer);
-	g_zload_read_only_flag = 0;
-    kfree(buffer);
+	    if(nor_read(0,0x10000,buffer))
+		{
+			kfree(buffer);
+			return -1;
+		}
+		if(flag == 0 )
+		{
+			bootflag = 0x00;
+			memset(&value, bootflag, 1);
+		}
+		else
+		{
+			bootflag = 0x5a;
+			memset(&value, bootflag, 1);
+		}
+
+		memcpy(buffer+2, &value, 1);
+
+		ret = nor_erase(0);
+		ret = nor_write(0,0x10000,buffer);
+		kfree(buffer);
+#endif
+	}
+	else
+	{
+	    unsigned char *buffer = kzalloc(WRITE_ZLOADER_FLAG_SIZE,GFP_KERNEL);
+
+	    if( buffer == NULL )
+	        return -1;
+
+	    if(mtd_read(mtd_fota,0,WRITE_ZLOADER_FLAG_SIZE,&retlen,buffer))/* BOOTFLAGÔÚnandµÄµÚ20~27×Ö½Ú */
+	    {
+	        kfree(buffer);
+	        return -1;
+	    }
+		if(flag == 0 )
+		{
+		    bootflag = 0x00;
+	        memset(&value, bootflag, 1);
+		}
+	    else
+	    {
+	        bootflag = 0x5a;
+	        memset(&value, bootflag, 1);
+	    }
+		
+	    memcpy(buffer+2, &value, 1);
+	    memset(&ei, 0, sizeof(struct erase_info));
+	    ei.mtd  = mtd_fota;
+	    ei.addr = 0;
+	    ei.len  = mtd_fota->erasesize;
+		g_zload_read_only_flag = 1;
+	    ret = mtd_erase(mtd_fota, &ei);                  /*²Á³ýµÚÒ»¿é*/
+		ret = mtd_write(mtd_fota,0,WRITE_ZLOADER_FLAG_SIZE,&retlen,buffer);
+		g_zload_read_only_flag = 0;
+	    kfree(buffer);
+
+	}   
 
     return 0;
 
diff --git a/ap/os/linux/linux-3.4.x/drivers/mtd/nand/nand_base.c b/ap/os/linux/linux-3.4.x/drivers/mtd/nand/nand_base.c
index d259c4c..edb5c5a 100755
--- a/ap/os/linux/linux-3.4.x/drivers/mtd/nand/nand_base.c
+++ b/ap/os/linux/linux-3.4.x/drivers/mtd/nand/nand_base.c
@@ -114,6 +114,8 @@
 
 extern struct cmdline_mtd_partition *partitions;
 
+extern struct mutex otpMutex;
+
 extern  void denali_set_intr_modes(struct denali_nand_info *denali,
 					uint16_t INT_ENABLE);
 static int nand_get_device(struct nand_chip *chip, struct mtd_info *mtd,
@@ -1729,6 +1731,8 @@
 	int ret;
 	
 	nand_get_device(chip, mtd, FL_READING);
+	mutex_lock(&otpMutex);
+	
 	/*ops.len = len;
 	ops.datbuf = buf;
 	ops.oobbuf = NULL;
@@ -1741,6 +1745,8 @@
 	
 	//*retlen = ops.retlen;
 	*retlen = chip->ops.retlen;
+
+	mutex_unlock(&otpMutex);
 	nand_release_device(mtd);
 	return ret;
 }
@@ -2011,6 +2017,7 @@
 		return -EINVAL;
 	}
 	nand_get_device(chip, mtd, FL_READING);
+	mutex_lock(&otpMutex);
 
 	switch (ops->mode) {
 	case MTD_OPS_PLACE_OOB:
@@ -2027,6 +2034,7 @@
 	else
 		ret = nand_do_read_ops(mtd, from, ops);
 out:
+	mutex_unlock(&otpMutex);
 	nand_release_device(mtd);
 	return ret;
 }
@@ -2473,12 +2481,14 @@
 	int ret;
 		
 	nand_get_device(chip, mtd, FL_WRITING);
+	mutex_lock(&otpMutex);
 	ops.len = len;
 	ops.datbuf = (uint8_t *)buf;
 	ops.oobbuf = NULL;
 	ops.mode = 0;
 	ret = nand_do_write_ops(mtd, to, &ops);
 	*retlen = ops.retlen;
+	mutex_unlock(&otpMutex);
 	nand_release_device(mtd);
 		
 	return ret;
@@ -2596,6 +2606,7 @@
 	}
 
 	nand_get_device(chip, mtd, FL_WRITING);
+	mutex_lock(&otpMutex);
 
 	switch (ops->mode) {
 	case MTD_OPS_PLACE_OOB:
@@ -2612,6 +2623,7 @@
 	else
 		ret = nand_do_write_ops(mtd, to, ops);
 out:
+	mutex_unlock(&otpMutex);
 	nand_release_device(mtd);	
 	return ret;
 }
@@ -2695,6 +2707,7 @@
 
 	/* Grab the lock and see if the device is available */
 	nand_get_device(chip, mtd, FL_ERASING);
+	mutex_lock(&otpMutex);
 
 	/* Shift to get first page */
 	page = (int)(instr->addr >> chip->page_shift);
@@ -2804,6 +2817,7 @@
 	ret = instr->state == MTD_ERASE_DONE ? 0 : -EIO;
 
 	/* Deselect and wake up anyone waiting on the device */
+	mutex_unlock(&otpMutex);
 	nand_release_device(mtd);
 
 	/* Do call back function */
diff --git a/ap/os/linux/linux-3.4.x/drivers/mtd/nand/spi_nand.c b/ap/os/linux/linux-3.4.x/drivers/mtd/nand/spi_nand.c
index e1ac821..0cc1f5b 100755
--- a/ap/os/linux/linux-3.4.x/drivers/mtd/nand/spi_nand.c
+++ b/ap/os/linux/linux-3.4.x/drivers/mtd/nand/spi_nand.c
@@ -670,6 +670,7 @@
 {
     int ret = 0;
     uint32_t ecc = 0;
+	uint8_t feature = (ECC_EN|QE);
     struct spi_nand_info *spi_nand = mtd_to_spi_nand(mtd);
 	struct spi_nand_ctrl_ops *ctrl = spi_nand->ctrl;
 	int real_page; 
@@ -685,6 +686,15 @@
         
     }
 
+	/*check ecc enable*/
+	/*
+	ctrl->get_feature(REG_FEATURE, &feature);
+	if(!(feature & ECC_EN))
+	{
+		printk("[SPI-NAND] read page 0x%x while ecc is disable!,feature is 0x%x\n",page,feature);
+		//BUG_ON(1);
+	}*/
+
 	real_page = spi_nand_get_real_page(mtd, page);
 
     ret = ctrl->read_page_to_cache(real_page);
@@ -700,11 +710,13 @@
         printk("[SPI-NAND][spi_nand_check_ecc]\n");
         
     }
-    if ( ecc != 0 )
+	
+    if ( ecc != 0 && (chip->ops.mode != MTD_OPS_RAW))
     {
 		g_cur_ecc_page_addr = real_page*mtd->writesize;
 #ifdef __ECC_CHECK_SUPPORT__
 		mtd->ecc_stats.failed++;
+        printk("ecc_stats.failed++\n");
 #endif
     }
 	if((spi_nand->para->planes == 2) && (((real_page >> 6)%2) != 0))
diff --git a/ap/os/linux/linux-3.4.x/drivers/mtd/nand/zxic_spifc.c b/ap/os/linux/linux-3.4.x/drivers/mtd/nand/zxic_spifc.c
index 16c0efe..e6034ef 100755
--- a/ap/os/linux/linux-3.4.x/drivers/mtd/nand/zxic_spifc.c
+++ b/ap/os/linux/linux-3.4.x/drivers/mtd/nand/zxic_spifc.c
@@ -55,6 +55,8 @@
 static uint32_t spi_fc_wait_cmd_end(void);
 int winbond_dev_id2 = 0;
 unsigned char g_nor_flag = 0;
+struct mutex otpMutex;
+
 /* SPI NAND FLASH COMMAND FORMAT TYPE */
 /********************************************************************************
   [Instruction]                 |--write enable
@@ -923,6 +925,10 @@
             continue;   /* ´«Êäʧ°Ü£¬½áÊø±¾´ÎÑ­»·²¢ÖØ´« */
         }
 
+		if(g_nor_flag == 1)
+			gpio_set_value(86,GPIO_HIGH);//spp
+		
+
         ret = spi_fc_read_fifo(len,value);     /* ¶ÁÈ¡Êý¾Ý */
 		
         if ( ret != SUCCESS )
@@ -930,9 +936,6 @@
             //spi_fc_disable();
             continue;   /* ´«Êäʧ°Ü£¬½áÊø±¾´ÎÑ­»·²¢ÖØ´« */
         }
-
-		if(g_nor_flag == 1)
-			gpio_set_value(86,GPIO_HIGH);//spp
 		
         break;
     }
@@ -1869,8 +1872,11 @@
 		}
 	}
 
+
 	pr_info("----------spi_nand_probe-----------\n");
 
+	mutex_init(&otpMutex);
+
 	spifc = kzalloc(sizeof(*spifc), GFP_KERNEL);
 	if (!spifc)
 		return -ENOMEM;
diff --git a/ap/os/linux/linux-3.4.x/drivers/net/wireless/aic8800/Makefile b/ap/os/linux/linux-3.4.x/drivers/net/wireless/aic8800/Makefile
old mode 100644
new mode 100755
index 3957046..7caf507
--- a/ap/os/linux/linux-3.4.x/drivers/net/wireless/aic8800/Makefile
+++ b/ap/os/linux/linux-3.4.x/drivers/net/wireless/aic8800/Makefile
@@ -150,6 +150,8 @@
 CONFIG_AGGRESSIVE_TX = n
 CONFIG_ONE_TXQ = y
 CONFIG_TXRX_THREAD_PRIO = y
+CONFIG_DPD = y
+CONFIG_FORCE_DPD_CALIB = y
 
 # Support of MU-MIMO transmission (need FW support)
 ifeq ($(CONFIG_RWNX_BFMER), y)
@@ -263,6 +265,8 @@
 ccflags-$(CONFIG_AGGRESSIVE_TX)  += -DCONFIG_AGGRESSIVE_TX
 ccflags-$(CONFIG_ONE_TXQ)  += -DCONFIG_ONE_TXQ
 ccflags-$(CONFIG_TXRX_THREAD_PRIO) += -DCONFIG_TXRX_THREAD_PRIO
+ccflags-$(CONFIG_DPD)  += -DCONFIG_DPD
+ccflags-$(CONFIG_FORCE_DPD_CALIB) += -DCONFIG_FORCE_DPD_CALIB -DCONFIG_DPD
 
 ifeq ($(CONFIG_LESS_SKB), y)
 ccflags-y += -DLESS_SKB
diff --git a/ap/os/linux/linux-3.4.x/drivers/net/wireless/aic8800/aicwf_sdio.c b/ap/os/linux/linux-3.4.x/drivers/net/wireless/aic8800/aicwf_sdio.c
index 192e78e..d966cb0 100755
--- a/ap/os/linux/linux-3.4.x/drivers/net/wireless/aic8800/aicwf_sdio.c
+++ b/ap/os/linux/linux-3.4.x/drivers/net/wireless/aic8800/aicwf_sdio.c
@@ -306,11 +306,14 @@
 	}
 
     host->caps |= MMC_CAP_NONREMOVABLE;
-    aicwf_rwnx_sdio_platform_init(sdiodev);
+    if(aicwf_rwnx_sdio_platform_init(sdiodev) != 0){
+		err = -2;
+		goto fail;
+	}
     aicwf_hostif_ready();
 
     g_sdiodev = sdiodev;
-
+	sdio_dbg("aicwf_sdio_probe over.\n");
     return 0;
 fail:
 	aicwf_sdio_func_deinit(sdiodev);
diff --git a/ap/os/linux/linux-3.4.x/drivers/net/wireless/aic8800/rwnx_debugfs.c b/ap/os/linux/linux-3.4.x/drivers/net/wireless/aic8800/rwnx_debugfs.c
old mode 100644
new mode 100755
index 0c4190b..b934564
--- a/ap/os/linux/linux-3.4.x/drivers/net/wireless/aic8800/rwnx_debugfs.c
+++ b/ap/os/linux/linux-3.4.x/drivers/net/wireless/aic8800/rwnx_debugfs.c
@@ -1406,6 +1406,62 @@
 	}
 }
 
+static void idx_to_rate_cfg1(unsigned int formatmod,
+	unsigned int mcs,unsigned int nss,
+	unsigned int bwTx,unsigned int gi,
+	 union rwnx_rate_ctrl_info *r_cfg, int *ru_size)
+{
+    r_cfg->value = 0;
+    switch(formatmod){
+		case FORMATMOD_NON_HT:
+		{
+			r_cfg->formatModTx = formatmod;
+			r_cfg->giAndPreTypeTx = 1;
+			r_cfg->mcsIndexTx = mcs;
+            break;
+		}
+		case FORMATMOD_NON_HT_DUP_OFDM:
+		{
+			r_cfg->formatModTx = formatmod;
+			r_cfg->giAndPreTypeTx = gi;
+			r_cfg->mcsIndexTx = mcs;
+            break;
+		}
+        case FORMATMOD_HT_MF:
+		{
+			union rwnx_mcs_index *r = (union rwnx_mcs_index *)r_cfg;
+			r_cfg->formatModTx = formatmod;
+            r->ht.nss = nss;
+            r->ht.mcs = mcs;
+            r_cfg->bwTx = bwTx;
+            r_cfg->giAndPreTypeTx = gi;
+            break;
+        }
+        case FORMATMOD_VHT:
+        case FORMATMOD_HE_SU:
+        {
+			union rwnx_mcs_index *r = (union rwnx_mcs_index *)r_cfg;
+			r_cfg->formatModTx = formatmod;
+            r->vht.nss = nss;
+            r->vht.mcs = mcs;
+            r_cfg->bwTx = bwTx;
+            r_cfg->giAndPreTypeTx = gi;
+            break;
+        }
+        case FORMATMOD_HE_MU:
+        {
+			union rwnx_mcs_index *r = (union rwnx_mcs_index *)r_cfg;
+			r_cfg->formatModTx = formatmod;
+            r->he.nss = nss;
+            r->he.mcs = mcs;
+            r_cfg->bwTx = 0;
+            r_cfg->giAndPreTypeTx = gi;
+            break;
+        }
+        default:
+            printk("Don't have the formatmod");
+    }
+}
 static ssize_t rwnx_dbgfs_rc_stats_read(struct file *file,
 										char __user *user_buf,
 										size_t count, loff_t *ppos)
@@ -1555,8 +1611,8 @@
 	struct rwnx_sta *sta = NULL;
 	struct rwnx_hw *priv = file->private_data;
 	u8 mac[6];
-	char buf[10];
-	int fixed_rate_idx = -1;
+	char buf[20];
+	//int fixed_rate_idx = -1;
 	union rwnx_rate_ctrl_info rate_config;
 	int error = 0;
 	size_t len = min_t(size_t, count, sizeof(buf) - 1);
@@ -1576,6 +1632,7 @@
 	if (copy_from_user(buf, user_buf, len))
 		return -EFAULT;
 	buf[len] = '\0';
+#if 0
 	sscanf(buf, "%i\n", &fixed_rate_idx);
 
 	/* Convert rate index into rate configuration */
@@ -1585,7 +1642,20 @@
 	} else {
 		idx_to_rate_cfg(fixed_rate_idx, &rate_config, NULL);
 	}
+#else
 
+	scanf(buf, "%u %u %u %u %u",&formatmod, &mcs, &nss, &bwTx, &gi);
+        printk("%u %u %u %u %u\n",formatmod, mcs, nss, bwTx, gi);
+    if((formatmod > 6) || (mcs > 11) || (nss > 8) || (bwTx > 6) || (gi > 3)){
+        printk("error parameter");
+        rate_config.value = (u32)-1;
+    }
+    else
+    {
+        idx_to_rate_cfg1(formatmod, mcs, nss, bwTx, gi, &rate_config, NULL);
+    }
+#endif
+        printk("formatModTx=%u mcsIndexTx=%u bwTx=%u giAndPreTypeTx=%u\n",r_cfg->formatModTx,r_cfg->mcsIndexTx,r_cfg->bwTx,r_cfg->giAndPreTypeTx);
 	// Forward the request to the LMAC
 	error = rwnx_send_me_rc_set_rate(priv, sta->sta_idx, (u16)rate_config.value);
 	if (error != 0) {
diff --git a/ap/os/linux/linux-3.4.x/drivers/net/wireless/aic8800/rwnx_main.c b/ap/os/linux/linux-3.4.x/drivers/net/wireless/aic8800/rwnx_main.c
index a4d924a..537334d 100755
--- a/ap/os/linux/linux-3.4.x/drivers/net/wireless/aic8800/rwnx_main.c
+++ b/ap/os/linux/linux-3.4.x/drivers/net/wireless/aic8800/rwnx_main.c
@@ -1138,6 +1138,16 @@
     RDWR_EFUSE_PWROFST,
     RDWR_EFUSE_DRVIBIT,
     SET_PAPR,
+    SET_CAL_XTAL,
+    GET_CAL_XTAL_RES,
+    SET_COB_CAL,
+    GET_COB_CAL_RES,
+    RDWR_EFUSE_USRDATA,
+    SET_NOTCH,
+    RDWR_PWROFSTFINE,
+    RDWR_EFUSE_PWROFSTFINE,
+    RDWR_EFUSE_SDIOCFG,
+    RDWR_EFUSE_USBVIDPID,
 
     #ifdef CONFIG_RFTEST_USB_BT
     BT_CMD_BASE = 0x100,
@@ -1676,6 +1686,16 @@
             } else {
                 printk("wrong args\n");
             }
+        }  else if (strcasecmp(argv[0], "SET_NOTCH") == 0) {
+            if (argc > 1) {
+                u8_l func = (u8_l)command_strtoul(argv[1], NULL, 10);
+                printk("set notch: %d\n", func);
+                rwnx_send_rftest_req(p_rwnx_hw, SET_NOTCH, sizeof(func), (u8_l *)&func, NULL);
+            } else {
+                printk("wrong args\n");
+                bytes_written = -EINVAL;
+                break;
+            }
         }
         #ifdef CONFIG_RFTEST_USB_BT
         else if (strcasecmp(argv[0], "BT_RESET") == 0) {
@@ -7589,30 +7609,6 @@
     {0x00110bf0, 0x00181001},
 };
 
-int aicwf_misc_ram_init_8800dc(struct rwnx_hw *rwnx_hw)
-{
-    int ret = 0;
-    const uint32_t cfg_base = 0x10164;
-    struct dbg_mem_read_cfm cfm;
-    uint32_t misc_ram_addr;
-    uint32_t misc_ram_size = 12;
-    int i;
-    ret = rwnx_send_dbg_mem_read_req(rwnx_hw, cfg_base + 0x14, &cfm);
-    if (ret) {
-        printk("rf misc ram[0x%x] rd fail: %d\n", cfg_base + 0x14, ret);
-        return ret;
-    }
-    misc_ram_addr = cfm.memdata;
-    printk("misc_ram_addr=%x\n", misc_ram_addr);
-    for (i = 0; i < (misc_ram_size / 4); i++) {
-        ret = rwnx_send_dbg_mem_write_req(rwnx_hw, misc_ram_addr + i * 4, 0);
-        if (ret) {
-            printk("rf misc ram[0x%x] wr fail: %d\n",  misc_ram_addr + i * 4, ret);
-            return ret;
-        }
-    }
-    return ret;
-}
 static void patch_config(struct rwnx_hw *rwnx_hw)
 {
     #ifdef CONFIG_ROM_PATCH_EN
@@ -7967,7 +7963,7 @@
     }
     #endif
 }
-
+extern int aicwf_fdrv_dpd_result_load_8800dc(struct rwnx_hw *rwnx_hw);
 static int start_from_bootrom(struct rwnx_hw *rwnx_hw)
 {
     int ret = 0;
@@ -8255,6 +8251,19 @@
 		if ((ret = rwnx_send_rf_config_req(rwnx_hw, 32,  0, (u8_l *)wifi_rxgain_table_24g_40m_8800dcdw, 256)))
             goto err_lmac_reqs;
 
+	}else if (testmode == 1) {
+		if (chip_sub_id == 1) {
+            #ifdef CONFIG_DPD
+            if (is_file_exist(FW_DPDRESULT_NAME_8800DC) == 1) {
+                printk("%s load dpd bin\n", __func__);
+                ret = aicwf_fdrv_dpd_result_load_8800dc(rwnx_hw);
+                if (ret) {
+                    printk("load dpd bin fail: %d\n", ret);
+                    return ret;
+                }
+            }
+            #endif
+        }
 	}
         if ((ret = rwnx_send_rf_calib_req(rwnx_hw, &cfm))) {
             goto err_lmac_reqs;
diff --git a/ap/os/linux/linux-3.4.x/drivers/net/wireless/aic8800/rwnx_mod_params.c b/ap/os/linux/linux-3.4.x/drivers/net/wireless/aic8800/rwnx_mod_params.c
index 1bd369b..a6eda76 100755
--- a/ap/os/linux/linux-3.4.x/drivers/net/wireless/aic8800/rwnx_mod_params.c
+++ b/ap/os/linux/linux-3.4.x/drivers/net/wireless/aic8800/rwnx_mod_params.c
@@ -1242,8 +1242,8 @@
     he_cap->he_cap_elem.phy_cap_info[8] |= IEEE80211_HE_PHY_CAP8_20MHZ_IN_40MHZ_HE_PPDU_IN_2G;
     he_cap->he_cap_elem.phy_cap_info[9] |= IEEE80211_HE_PHY_CAP9_RX_FULL_BW_SU_USING_MU_WITH_COMP_SIGB |
                                            IEEE80211_HE_PHY_CAP9_RX_FULL_BW_SU_USING_MU_WITH_NON_COMP_SIGB;
-    //mcs_map = rwnx_hw->mod_params->he_mcs_map;
-    mcs_map = min_t(int, rwnx_hw->mod_params->he_mcs_map, IEEE80211_HE_MCS_SUPPORT_0_9);
+    mcs_map = rwnx_hw->mod_params->he_mcs_map;
+    //mcs_map = min_t(int, rwnx_hw->mod_params->he_mcs_map, IEEE80211_HE_MCS_SUPPORT_0_9);
     memset(&he_cap->he_mcs_nss_supp, 0, sizeof(he_cap->he_mcs_nss_supp));
     for (i = 0; i < nss; i++) {
         __le16 unsup_for_ss = cpu_to_le16(IEEE80211_HE_MCS_NOT_SUPPORTED << (i*2));
@@ -1367,8 +1367,8 @@
     he_cap->he_cap_elem.phy_cap_info[9] |= IEEE80211_HE_PHY_CAP9_RX_FULL_BW_SU_USING_MU_WITH_COMP_SIGB |
                                            IEEE80211_HE_PHY_CAP9_RX_FULL_BW_SU_USING_MU_WITH_NON_COMP_SIGB;
     #endif
-    //mcs_map = rwnx_hw->mod_params->he_mcs_map;
-    mcs_map = min_t(int, rwnx_hw->mod_params->he_mcs_map, IEEE80211_HE_MCS_SUPPORT_0_9);
+    mcs_map = rwnx_hw->mod_params->he_mcs_map;
+    //mcs_map = min_t(int, rwnx_hw->mod_params->he_mcs_map, IEEE80211_HE_MCS_SUPPORT_0_9);
     memset(&he_cap->he_mcs_nss_supp, 0, sizeof(he_cap->he_mcs_nss_supp));
     for (i = 0; i < nss; i++) {
         __le16 unsup_for_ss = cpu_to_le16(IEEE80211_HE_MCS_NOT_SUPPORTED << (i*2));
@@ -1471,8 +1471,8 @@
     he_cap->he_cap_elem.phy_cap_info[9] |= IEEE80211_HE_PHY_CAP9_RX_FULL_BW_SU_USING_MU_WITH_COMP_SIGB |
                                            IEEE80211_HE_PHY_CAP9_RX_FULL_BW_SU_USING_MU_WITH_NON_COMP_SIGB;
     #endif
-    //mcs_map = rwnx_hw->mod_params->he_mcs_map;
-    mcs_map = min_t(int, rwnx_hw->mod_params->he_mcs_map, IEEE80211_HE_MCS_SUPPORT_0_9);
+    mcs_map = rwnx_hw->mod_params->he_mcs_map;
+    //mcs_map = min_t(int, rwnx_hw->mod_params->he_mcs_map, IEEE80211_HE_MCS_SUPPORT_0_9);
     memset(&he_cap->he_mcs_nss_supp, 0, sizeof(he_cap->he_mcs_nss_supp));
     for (i = 0; i < nss; i++) {
         __le16 unsup_for_ss = cpu_to_le16(IEEE80211_HE_MCS_NOT_SUPPORTED << (i*2));
diff --git a/ap/os/linux/linux-3.4.x/drivers/net/wireless/aic8800/rwnx_platform.c b/ap/os/linux/linux-3.4.x/drivers/net/wireless/aic8800/rwnx_platform.c
old mode 100644
new mode 100755
index e766a54..2129cf7
--- a/ap/os/linux/linux-3.4.x/drivers/net/wireless/aic8800/rwnx_platform.c
+++ b/ap/os/linux/linux-3.4.x/drivers/net/wireless/aic8800/rwnx_platform.c
@@ -117,9 +117,9 @@
     void *buffer = NULL;
     char *path = NULL;
     struct file *fp = NULL;
-    int size = 0, len = 0, i = 0;
+    int size = 0, len = 0;
     ssize_t rdlen = 0;
-    u32 *src = NULL, *dst = NULL;
+    //u32 *src = NULL, *dst = NULL;
 
     /* get the firmware path */
     path = __getname();
@@ -128,7 +128,11 @@
         return -1;
     }
 
+	if(strcmp(name, FW_DPDRESULT_NAME_8800DC) == 0) {
+		len = snprintf(path, FW_PATH_MAX_LEN, "%s/%s", VENDOR_SPECIFIED_DPD_PATH, name);
+	} else {
     len = snprintf(path, FW_PATH_MAX_LEN, "%s/%s", VENDOR_SPECIFIED_FW_PATH, name);
+	}
     if (len >= FW_PATH_MAX_LEN) {
         printk("%s: %s file's path too long\n", __func__, name);
         *fw_buf = NULL;
@@ -188,6 +192,7 @@
         fp->f_pos += rdlen;
     }
 
+#if 0
     /*start to transform the data format*/
     src = (u32 *)buffer;
     dst = (u32 *)kzalloc(size, GFP_KERNEL);
@@ -205,13 +210,13 @@
     for (i = 0; i < (size/4); i++) {
         dst[i] = src[i];
     }
-
+#endif
     __putname(path);
     filp_close(fp, NULL);
     fp = NULL;
-    kfree(buffer);
-    buffer = NULL;
-    *fw_buf = dst;
+    //kfree(buffer);
+    //buffer = NULL;
+    *fw_buf = (u32 *)buffer;
 
     return size;
 }
@@ -1532,9 +1537,9 @@
     RWNX_DBG(RWNX_FN_ENTRY_STR);
     #if defined(CONFIG_NANOPI_M4) || defined(CONFIG_PLATFORM_ALLWINNER)
     if (testmode) {
-        ret = rwnx_plat_bin_fw_upload_android(rwnx_hw, RAM_FMAC_FW_ADDR, RWNX_MAC_FW_RF_BASE_NAME);
+        ret = rwnx_plat_bin_fw_upload_2(rwnx_hw, RAM_FMAC_FW_ADDR, RWNX_MAC_FW_RF_BASE_NAME);
     } else {
-        ret = rwnx_plat_bin_fw_upload_android(rwnx_hw, RAM_FMAC_FW_ADDR, RWNX_MAC_FW_NAME2);
+        ret = rwnx_plat_bin_fw_upload_2(rwnx_hw, RAM_FMAC_FW_ADDR, RWNX_MAC_FW_NAME2);
     }
     #else
     if (testmode) {
@@ -1551,6 +1556,8 @@
  *
  * @rwnx_hw: Main driver data
  */
+ uint32_t dpd_res[DPD_RESULT_SIZE_8800DC / 4] = {0,};
+extern int aicwf_dpd_calib_8800dc(struct rwnx_hw *rwnx_hw, uint32_t *dpd_res);
 static int rwnx_plat_patch_load(struct rwnx_hw *rwnx_hw)
 {
     int ret = 0;
@@ -1562,21 +1569,284 @@
         ret = rwnx_plat_bin_fw_upload_2(rwnx_hw, ROM_FMAC_PATCH_ADDR_U01, RWNX_MAC_PATCH_NAME2);
         } else if (chip_sub_id == 1) {
             ret = rwnx_plat_bin_fw_upload_2(rwnx_hw, ROM_FMAC_PATCH_ADDR, RWNX_MAC_PATCH_NAME2_U02);
+#ifdef CONFIG_DPD
+#ifdef CONFIG_FORCE_DPD_CALIB
+		if (1) {
+			printk("dpd calib & write\n");
+			ret = aicwf_dpd_calib_8800dc(rwnx_hw, &dpd_res[0]);
+			if (ret) {
+				printk("dpd calib fail: %d\n", ret);
+				return ret;
+			}
+			ret = aicwf_dpd_result_write_8800dc((void *)dpd_res, DPD_RESULT_SIZE_8800DC);
+			if (ret) {
+				printk("file write fail: %d\n", ret);
+				return ret;
+			}
+		}
+#else
+		if (is_file_exist(FW_DPDRESULT_NAME_8800DC) == 1) {
+			printk("dpd bin load\n");
+			ret = aicwf_dpd_result_load_8800dc(rwnx_hw);
+			if (ret) {
+				printk("load dpd bin fail: %d\n", ret);
+				return ret;
+			}
+		}
+#endif
+		else
+#endif
+		{
+			aicwf_misc_ram_init_8800dc(rwnx_hw);
+		}
         } else {
             printk("unsupported id: %d\n", chip_sub_id);
         }
         #endif
-    } else {
+    } else if (testmode == 1) {
+    	ret = rwnx_plat_bin_fw_upload_2(rwnx_hw, ROM_FMAC_PATCH_ADDR, RWNX_MAC_PATCH_NAME2_U02);
+			printk("patch load\n");
+#ifdef CONFIG_DPD
+#ifdef CONFIG_FORCE_DPD_CALIB
+			if (1) {
+				printk("dpd calib & write\n");
+				ret = aicwf_dpd_calib_8800dc(rwnx_hw, &dpd_res[0]);
+				if (ret) {
+					printk("dpd calib fail: %d\n", ret);
+					return ret;
+				}
+				ret = aicwf_dpd_result_write_8800dc((void *)dpd_res, DPD_RESULT_SIZE_8800DC);
+				if (ret) {
+					printk("file write fail: %d\n", ret);
+					return ret;
+				}
+			}
+#endif
+#endif
         if (chip_sub_id == 0) {
         ret = rwnx_plat_bin_fw_upload_2(rwnx_hw, ROM_FMAC_PATCH_ADDR_U01, RWNX_MAC_RF_PATCH_NAME);
         }
         if (!ret) {
             ret = rwnx_plat_bin_fw_upload_2(rwnx_hw, RAM_LMAC_FW_ADDR, RWNX_MAC_FW_RF_BASE_NAME);
+        	}
         }
+	else if (testmode == 4) {
+                #ifdef CONFIG_DPD
+					if (is_file_exist(FW_DPDRESULT_NAME_8800DC) == 0) {
+						printk("patch load\n");
+						ret = rwnx_plat_bin_fw_upload_2(rwnx_hw, ROM_FMAC_PATCH_ADDR, RWNX_MAC_PATCH_NAME2_U02);
+						if (ret) {
+							printk("load patch bin fail: %d\n", ret);
+							return ret;
+						}
+						printk("dpd calib & write\n");
+						ret = aicwf_dpd_calib_8800dc(rwnx_hw, &dpd_res[0]);
+						if (ret) {
+							printk("dpd calib fail: %d\n", ret);
+							return ret;
+						}
+						ret = aicwf_dpd_result_write_8800dc((void *)dpd_res, DPD_RESULT_SIZE_8800DC);
+						if (ret) {
+							printk("file write fail: %d\n", ret);
+							return ret;
+						}
+					}
+                #endif
+					return 1; // exit calib mode
     }
 
     return ret;
 }
+#ifdef CONFIG_DPD
+#define RAM_LMAC_FW_ADDR               0x00150000
+int aicwf_plat_calib_load_8800dc(struct rwnx_hw *rwnx_hw)
+{
+    int ret = 0;
+    if (chip_sub_id == 1) {
+        ret = rwnx_plat_bin_fw_upload_2(rwnx_hw, ROM_FMAC_CALIB_ADDR, RWNX_MAC_CALIB_NAME_8800DC_U02);
+        if (ret) {
+            printk("load rftest bin fail: %d\n", ret);
+            return ret;
+        }
+    }
+    return ret;
+}
+int is_file_exist(char* name)
+{
+    char *path = NULL;
+    struct file *fp = NULL;
+    int len;
+    path = __getname();
+    if (!path) {
+        printk("%s getname fail\n", __func__);
+        return -1;
+    }
+    len = snprintf(path, FW_PATH_MAX_LEN, "%s/%s", VENDOR_SPECIFIED_DPD_PATH, name);
+    fp = filp_open(path, O_RDONLY, 0);
+    if (IS_ERR(fp)) {
+        __putname(path);
+        fp = NULL;
+        return 0;
+    } else {
+        __putname(path);
+        filp_close(fp, NULL);
+		fp = NULL;
+        return 1;
+    }
+}
+EXPORT_SYMBOL(is_file_exist);
+int aicwf_fdrv_dpd_result_load_8800dc(struct rwnx_hw *rwnx_hw)
+{
+    int ret = 0;
+    uint32_t cfg_base = 0x10164;
+    struct dbg_mem_read_cfm cfm;
+    uint32_t misc_ram_addr;
+	printk("%s\n", __func__);
+    if (testmode == 1) {
+        cfg_base = RAM_LMAC_FW_ADDR + 0x0164;
+    }
+    if ((ret = rwnx_send_dbg_mem_read_req(rwnx_hw, cfg_base + 0x14, &cfm))) {
+        printk("rf misc ram[0x%x] rd fail: %d\n", cfg_base + 0x14, ret);
+        return ret;
+    }
+    misc_ram_addr = cfm.memdata;
+    ret = rwnx_plat_bin_fw_upload_2(rwnx_hw, misc_ram_addr, FW_DPDRESULT_NAME_8800DC);
+    if (ret) {
+        printk("load calib bin fail: %d\n", ret);
+        return ret;
+    }
+    return ret;
+}
+#endif
+int aicwf_misc_ram_init_8800dc(struct rwnx_hw *rwnx_hw)
+{
+    int ret = 0;
+    const uint32_t cfg_base = 0x10164;
+    struct dbg_mem_read_cfm cfm;
+    uint32_t misc_ram_addr;
+    uint32_t misc_ram_size = 12;
+    int i;
+    ret = rwnx_send_dbg_mem_read_req(rwnx_hw, cfg_base + 0x14, &cfm);
+    if (ret) {
+        printk("rf misc ram[0x%x] rd fail: %d\n", cfg_base + 0x14, ret);
+        return ret;
+    }
+    misc_ram_addr = cfm.memdata;
+    printk("misc_ram_addr=%x\n", misc_ram_addr);
+    for (i = 0; i < (misc_ram_size / 4); i++) {
+        ret = rwnx_send_dbg_mem_write_req(rwnx_hw, misc_ram_addr + i * 4, 0);
+        if (ret) {
+            printk("rf misc ram[0x%x] wr fail: %d\n",  misc_ram_addr + i * 4, ret);
+            return ret;
+        }
+    }
+    return ret;
+}
+#ifdef CONFIG_DPD
+int aicwf_dpd_calib_8800dc(struct rwnx_hw *rwnx_hw, uint32_t *dpd_res)
+{
+    int ret = 0;
+    uint32_t fw_addr, boot_type;
+	printk("%s\n", __func__);
+    ret = aicwf_plat_calib_load_8800dc(rwnx_hw);
+    if (ret) {
+        printk("load calib bin fail: %d\n", ret);
+        return ret;
+    }
+    fw_addr = 0x00130009;
+    boot_type = 4;//HOST_START_APP_FNCALL;
+    printk("Start app: %08x, %d\n", fw_addr, boot_type);
+    ret = rwnx_send_dbg_start_app_req(rwnx_hw, fw_addr, boot_type);
+    if (ret) {
+        printk("start app fail: %d\n", ret);
+        return ret;
+    }
+    { // read dpd res
+        const uint32_t cfg_base = 0x10164;
+        struct dbg_mem_read_cfm cfm;
+        uint32_t misc_ram_addr;
+        uint32_t misc_ram_size = DPD_RESULT_SIZE_8800DC;
+        int i;
+        ret = rwnx_send_dbg_mem_read_req(rwnx_hw, cfg_base + 0x14, &cfm);
+        if (ret) {
+            printk("rf misc ram[0x%x] rd fail: %d\n", cfg_base + 0x14, ret);
+            return ret;
+        }
+        misc_ram_addr = cfm.memdata;
+        for (i = 0; i < (misc_ram_size / 4); i++) {
+            ret = rwnx_send_dbg_mem_read_req(rwnx_hw, misc_ram_addr + i * 4, &cfm);
+            if (ret) {
+                 printk("rf misc ram[0x%x] rd fail: %d\n",  misc_ram_addr + i * 4, ret);
+                return ret;
+            }
+            dpd_res[i] = cfm.memdata;
+        }
+    }
+    return ret;
+}
+int aicwf_dpd_result_load_8800dc(struct rwnx_hw *rwnx_hw)
+{
+	printk("%s\n", __func__);
+    int ret = 0;
+    uint32_t cfg_base = 0x10164;
+    struct dbg_mem_read_cfm cfm;
+    uint32_t misc_ram_addr;
+	if (testmode == 1) {
+		cfg_base = RAM_LMAC_FW_ADDR + 0x0164;
+	}
+    if ((ret = rwnx_send_dbg_mem_read_req(rwnx_hw, cfg_base + 0x14, &cfm))) {
+        printk("rf misc ram[0x%x] rd fail: %d\n", cfg_base + 0x14, ret);
+        return ret;
+    }
+    misc_ram_addr = cfm.memdata;
+    ret = rwnx_plat_bin_fw_upload_2(rwnx_hw, misc_ram_addr, FW_DPDRESULT_NAME_8800DC);
+    if (ret) {
+        printk("load calib bin fail: %d\n", ret);
+        return ret;
+    }
+    return ret;
+}
+int aicwf_dpd_result_write_8800dc(void *buf, int buf_len)
+{
+	printk("%s\n", __func__);
+    int sum = 0, len = 0;
+    char *path = NULL;
+    struct file *fp = NULL;
+    loff_t pos = 0;
+    mm_segment_t fs;
+    path = __getname();
+    if (!path) {
+        printk("get path fail\n");
+        return -1;
+    }
+    len = snprintf(path, FW_PATH_MAX_LEN, "%s/%s", VENDOR_SPECIFIED_DPD_PATH, FW_DPDRESULT_NAME_8800DC);
+    printk("%s\n", path);
+
+    fp = filp_open(path, O_RDWR | O_CREAT, 0644);
+    if (IS_ERR(fp)) {
+        printk("fp open fial\n");
+		__putname(path);
+        fp = NULL;
+        return -1;
+    }
+
+    fs = get_fs();
+    set_fs(KERNEL_DS);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0)
+    sum = kernel_write(fp, buf, buf_len, &pos);
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0)
+    sum = kernel_write(fp, (char *)buf, buf_len, pos);
+#else
+    sum = vfs_write(fp, (char *)buf, buf_len, &pos);
+#endif
+
+    set_fs(fs);
+    __putname(path);
+    filp_close(fp, NULL);
+	fp = NULL;
+    return 0;
+}
+#endif
 
 #if 0
 /**
@@ -1913,6 +2183,7 @@
     #ifdef CONFIG_ROM_PATCH_EN
     ret = rwnx_plat_patch_load(rwnx_hw);
     if (ret) {
+		printk("patch load return %d\n", ret);
         return ret;
     }
     #endif
diff --git a/ap/os/linux/linux-3.4.x/drivers/net/wireless/aic8800/rwnx_platform.h b/ap/os/linux/linux-3.4.x/drivers/net/wireless/aic8800/rwnx_platform.h
old mode 100644
new mode 100755
index 54ce2ca..a5883de
--- a/ap/os/linux/linux-3.4.x/drivers/net/wireless/aic8800/rwnx_platform.h
+++ b/ap/os/linux/linux-3.4.x/drivers/net/wireless/aic8800/rwnx_platform.h
@@ -41,7 +41,17 @@
 #define RWNX_MAC_FW_NAME2 RWNX_MAC_FW_BASE_NAME".bin"
 #endif
 #endif
+#define RWNX_MAC_CALIB_BASE_NAME_8800DC        "fmacfw_calib_8800dc"
+#define RWNX_MAC_CALIB_NAME_8800DC_U02          RWNX_MAC_CALIB_BASE_NAME_8800DC"_u02.bin"
 
+#ifdef CONFIG_DPD
+#define ROM_FMAC_CALIB_ADDR            0x00130000
+#define FW_DPDRESULT_NAME_8800DC        "aic_dpdresult_8800dc.bin"
+#define DPD_RESULT_SIZE_8800DC 1880
+#define FW_PATH_MAX_LEN 200
+int aicwf_dpd_result_write_8800dc(void *buf, int buf_len);
+int is_file_exist(char* name);
+#endif
 #define RWNX_MAC_PATCH_BASE_NAME        "fmacfw_patch_8800dc"
 #define RWNX_MAC_PATCH_NAME2 RWNX_MAC_PATCH_BASE_NAME".bin"
 #define RWNX_MAC_PATCH_NAME2_U02 RWNX_MAC_PATCH_BASE_NAME"_u02.bin"
@@ -62,6 +72,7 @@
 #ifdef CONFIG_VENDOR_SUBDIR_NAME
 #define VENDOR_SUBDIR_NAME          CONFIG_VENDOR_SUBDIR_NAME
 #endif
+#define VENDOR_SPECIFIED_DPD_PATH "/mnt/userdata/etc_rw/wifi"
 
 /**
  * Type of memory to access (cf rwnx_plat.get_address)
@@ -163,5 +174,6 @@
 {
     return rwnx_plat->pci_dev->irq;
 }
+int aicwf_misc_ram_init_8800dc(struct rwnx_hw *rwnx_hw);
 
 #endif /* _RWNX_PLATFORM_H_ */
diff --git a/ap/os/linux/linux-3.4.x/drivers/soc/zte/otp/otp_zx.c b/ap/os/linux/linux-3.4.x/drivers/soc/zte/otp/otp_zx.c
index 3ff3107..87ef398 100755
--- a/ap/os/linux/linux-3.4.x/drivers/soc/zte/otp/otp_zx.c
+++ b/ap/os/linux/linux-3.4.x/drivers/soc/zte/otp/otp_zx.c
@@ -27,7 +27,7 @@
 #include <mach/iomap.h>

 #include <mach/gpio.h>

 

-struct mutex otpMutex;

+extern struct mutex otpMutex;

 extern char *nor_cmdline;

 

 typedef volatile struct

@@ -441,6 +441,214 @@
 	 

  }

 

+ int spi_nor_erase(uint32_t offs)

+{

+	int ret;

+	int nor_status = 0;

+	spinor_cmd_t *cmd = NULL;

+

+	cmd = cmd_seek(CMD_64KBE);

+	if(cmd == NULL)

+	{

+		printk("cmd_seek unkown cmd = 0x%x error.\n", CMD_64KBE);

+		return -1;

+	}

+

+	cmd->tx_dma_en = TX_DMA_DIS;

+	cs_open();

+	spifc_setup_cmd(cmd, offs, 0);

+

+	spifc_start();

+    ret = spifc_wait_cmd_end();             

+    if(ret != 0)

+    {

+		printk("spifc_wait_cmd_end error.\n");

+	   	return ret;

+    }

+    cs_close();

+	udelay(5);

+	

+	do{

+		ret = nor_read_reg(CMD_RDSR0, 1, &nor_status);

+		if(ret != 0)

+		{

+			printk("read WIP fail.\n");

+		}

+	}while(nor_status & 0x1);

+	

+	return 0;

+}

+int nor_erase(u32 addr)

+{

+    int ret;

+	u32 page_offset, page_size, i;

+	struct nor_info *info = spi_nor_flash;

+

+	soft_spin_lock(NAND_SFLOCK);

+	mutex_lock(&otpMutex);

+	

+	nor_write_reg(CMD_WREN, NULL, 0);

+	ret = spi_nor_erase(addr);

+

+	mutex_unlock(&otpMutex);

+	soft_spin_unlock(NAND_SFLOCK);

+	

+	return ret;

+}

+ int spi_nor_write(uint32_t to, size_t len, u_char *buf)

+   {

+	  int ret;

+	  int nor_status = 0;

+	  spinor_cmd_t *cmd = NULL;

+ 

+	  cmd = cmd_seek(CMD_PP);

+	  

+	  if(cmd == NULL)

+	  {

+		  printk("cmd_seek unkown cmd = 0x%x error.\n", CMD_PSR);

+		  return -1;

+	  }

+  

+	  cmd->tx_dma_en = TX_DMA_DIS;

+	  cs_open();//spp

+	  spifc_setup_cmd(cmd, to, len); 

+ 

+	  spifc_start();

+ 

+	  ret = spifc_write_data(buf, len);

+	  if(ret < 0)

+	  {

+		  printk("spifc_write_fifo error.\n");

+		  return ret;

+	  }

+ 

+	  ret = spifc_wait_cmd_end();			   

+	  if(ret != 0)

+	  {

+		  printk("spifc_wait_cmd_end error.\n");

+		  return ret;

+	  }

+	  cs_close();//spp

+	  udelay(5);

+	  

+	  do{

+		  ret = nor_read_reg(CMD_RDSR0, 1, &nor_status);

+		  if(ret != 0)

+		  {

+			  printk("read WIP fail.\n");

+		  }

+	  }while(nor_status & 0x1);

+	  

+	  return 0;

+   }

+   

+   int nor_write(u32 to, u32 len, u32 buf)

+  {

+	  int ret;

+	  u32 page_offset, page_size, i;

+	  struct nor_info *info = spi_nor_flash;

+

+	  soft_spin_lock(NAND_SFLOCK);

+	  mutex_lock(&otpMutex);

+ 

+	  nor_write_reg(CMD_WREN, NULL, 0);

+	  

+	  page_offset = to & (info->page_size - 1);

+  

+	  /* do all the bytes fit onto one page? */

+	  if (page_offset + len <= info->page_size) {

+		  ret = spi_nor_write(to, len, (uint8_t *)buf);

+	  } else {

+		  /* the size of data remaining on the first page */

+		  page_size = info->page_size - page_offset;

+		  ret = spi_nor_write(to, page_size, (uint8_t *)buf);

+  

+		  /* read everything in nor->page_size chunks */

+		  for (i = page_size; i < len; i += page_size) {

+			  page_size = len - i;

+			  if (page_size > info->page_size)

+				  page_size = info->page_size;

+ 

+			  nor_write_reg(CMD_WREN, NULL, 0);

+			  ret = spi_nor_write(to + i, page_size, ((uint8_t *)buf + i));

+		  }

+	  }

+

+	  mutex_unlock(&otpMutex);

+	  soft_spin_unlock(NAND_SFLOCK);

+  

+	  return ret;

+  }

+  int spi_nor_read(uint32_t from, size_t len, u_char *buf)

+  {

+	  int ret;

+	  spinor_cmd_t *cmd = NULL;

+  

+	  cmd = cmd_seek(CMD_RDFT);

+ 

+	  if(cmd == NULL)

+	  {

+		  printk("cmd_seek unkown error.\n");

+		  return -1;

+	  }

+ 

+	  cmd->rx_dma_en = RX_DMA_DIS;

+	  cs_open();//spp

+	  spifc_setup_cmd(cmd, from, len);				  

+	  spifc_start();

+	  ret = spifc_read_fifo(buf, len);

+	  if(ret < 0)

+	  {

+		  printk("spifc_read_fifo error.\n");

+		  return ret;

+	  }

+  

+	  ret = spifc_wait_cmd_end();			  

+	  if(ret != 0)

+	  {

+		  printk("spifc_wait_cmd_end error.\n");

+		  cs_close();//spp

+		  return ret;

+	  }

+	  cs_close();//spp

+	  return 0;

+  }

+  

+  int nor_read(u32 from, u32 len, u32 to)

+  {

+	  int ret;

+	  u32 page_offset, page_size, i;

+	  struct nor_info *info = spi_nor_flash;

+

+	  soft_spin_lock(NAND_SFLOCK);

+	  mutex_lock(&otpMutex);

+	  

+	  page_offset = from & (info->page_size - 1);

+  

+	  /* do all the bytes fit onto one page? */

+	  if (page_offset + len <= info->page_size) {

+		  ret = spi_nor_read(from, len, (uint8_t *)to);

+	  } else {

+		  /* the size of data remaining on the first page */

+		  page_size = info->page_size - page_offset;

+		  ret = spi_nor_read(from, page_size, (uint8_t *)to);

+  

+		  /* read everything in nor->page_size chunks */

+		  for (i = page_size; i < len; i += page_size) {

+			  page_size = len - i;

+			  if (page_size > info->page_size)

+				  page_size = info->page_size;

+  

+			  ret = spi_nor_read(from + i, page_size, ((uint8_t *)to + i));

+		  }

+	  }

+

+	  mutex_unlock(&otpMutex);

+	  soft_spin_unlock(NAND_SFLOCK);

+  

+	  return ret;

+  }

+

   int spi_nor_write_security_register(uint32_t to, size_t len, u_char *buf)

   {

 	 int ret;

@@ -854,7 +1062,7 @@
 {

 	int ret = 0;

 

-	mutex_init(&otpMutex);

+	//mutex_init(&otpMutex);

 	

 	ret = misc_register(&zx_otp_miscdev);

 	if (ret) {

diff --git a/ap/os/linux/linux-3.4.x/drivers/staging/voicebufferdrv/voice_buffer_dev.c b/ap/os/linux/linux-3.4.x/drivers/staging/voicebufferdrv/voice_buffer_dev.c
index a856de7..be78b0a 100755
--- a/ap/os/linux/linux-3.4.x/drivers/staging/voicebufferdrv/voice_buffer_dev.c
+++ b/ap/os/linux/linux-3.4.x/drivers/staging/voicebufferdrv/voice_buffer_dev.c
@@ -179,6 +179,7 @@
 	if (true == isEmpty) {
 		if (voicebuff_ratelimit())
 			pr_info("voicebuffer_ulqueue_read ulqueue is empty\n");
+		memset(buf,0, size);// add for repeat play old data
 		mutex_unlock(&queue->quelock);
 		return -ENODATA;
 	} else {
diff --git a/ap/os/linux/linux-3.4.x/drivers/tty/serial/zx29_uart.c b/ap/os/linux/linux-3.4.x/drivers/tty/serial/zx29_uart.c
index efdc0d2..43a208a 100755
--- a/ap/os/linux/linux-3.4.x/drivers/tty/serial/zx29_uart.c
+++ b/ap/os/linux/linux-3.4.x/drivers/tty/serial/zx29_uart.c
@@ -2794,7 +2794,7 @@
 	zup->port_close = true;
 	up(&zup->sema);
 	tasklet_kill(&zup->write_wakeup);
-	raw_spin_lock_irqsave(&port->lock, flags);
+
 #if RX_DMA_WORK
 	if(zx29_dma_rx_work_scheduled(zup)){
 		del_timer_sync(&(zup->rx_dma_timer));
@@ -2802,6 +2802,7 @@
 	}
 #endif	
 	/* Disable and clear all interrupts now */
+	raw_spin_lock_irqsave(&port->lock, flags);
 	zup->imr = 0;
 	UART_PUT_IMSC(port, zup->imr);
 	UART_PUT_ICR(port, 0xFFFF);
diff --git a/ap/os/linux/linux-3.4.x/drivers/usb/gadget/adb_server.c b/ap/os/linux/linux-3.4.x/drivers/usb/gadget/adb_server.c
index a71960d..1b37e4b 100755
--- a/ap/os/linux/linux-3.4.x/drivers/usb/gadget/adb_server.c
+++ b/ap/os/linux/linux-3.4.x/drivers/usb/gadget/adb_server.c
@@ -370,7 +370,10 @@
 	g_adb_agent->agent_state = 0;
 	g_adb_agent->agt_error = 1;
 	
-
+	if(atomic_read(&g_adb_agent->write_busy)){
+		atomic_set(&g_adb_agent->write_busy, 0);
+		wake_up(&g_adb_agent->agt_write_wq);
+	}
 #if 0	
 	g_adb_agent->rx_done = 1;
 	wake_up(&g_adb_agent->read_wq);
@@ -439,13 +442,13 @@
 			adb_server_plug_notify(USB_RPMSG_NOTIFY_ADB_ONLINE);
 			dev->agent_start = 1;	
 			dev->agt_error = 0;
-			wake_up(&dev->agt_start_wait);
 		//wakeup adb read and return	
 		//dev->rx_done = 1;
 		//wake_up(&dev->read_wq);
 			if (atomic_read(&dev->read_excl)){
 				adb_agent_dequeue_rx(dev);
 			}
+			wake_up(&dev->agt_start_wait);
 		}else{	
 			//dev->agent_start = 0;
 			//disable agent