/* *Name : hynintron_ex_fun.c *Author : steven *Version : V2.0 *Create : 2019-11-11 *Copyright : zxzz */ #include #include #include #include #include #include #include #include #include #include #include #include "hynitron_core.h" #include "hynitron_common.h" #include "hynitron_update_firmware.h" //#include "firmware/capacitive_hynitron_cst3240_update.h" //#include "firmware/capacitive_hynitron_cst0xx_update.h" //#include "firmware/capacitive_hynitron_cst1xxse_update.h" ////#include "firmware/capacitive_hynitron_cst2xx_update.h" //#include "firmware/capacitive_hynitron_cst2xxse_update.h" //#include "firmware/capacitive_hynitron_cst3xx_update.h" //#include "firmware/capacitive_hynitron_cst3xxse_update.h" //#include "firmware/capacitive_hynitron_cst6xx_update.h" //#include "firmware/capacitive_hynitron_cst8xx_update.h" //#include "firmware/capacitive_hynitron_cst9xx_update.h" //#include "firmware/capacitive_hynitron_cst92xx_update.h" //please config the chip series before using. struct hynitron_fw_array hynitron_fw_grp[20] = { //0-name; 1-fw; 2-project_id; 3-module_id; 4-chip_type; 5-fw_length; //{ "capacitive_hynitron_cst0xx_update", cst0xx_fw, 0x2843,0x01, CST016, (sizeof(cst0xx_fw))}, //{ "capacitive_hynitron_cst2xxse_update", cst2xxse_fw, 0x0501,0x01, CST226SE, (sizeof(cst2xxse_fw))}, //{ "capacitive_hynitron_cst1xxse_update", cst1xxse_fw, 0x2107,0x01, CST18858SE, (sizeof(cst1xxse_fw))}, //{ "capacitive_hynitron_cst3xx_update", cst3xx_fw, 0x2117,0x11, CST348, (sizeof(cst3xx_fw))}, //{ "capacitive_hynitron_cst3240_update", cst3240_fw, 0x3604,0x01, CST3240, (sizeof(cst3240_fw))}, //{ "capacitive_hynitron_cst6xx_update", cst6xx_fw, 0x2117,0x11, CST6928S, (sizeof(cst6xx_fw))}, //{ "capacitive_hynitron_cst3xxse_update", cst3xxse_fw, 0x0501,0x01, CST328SE, (sizeof(cst3xxse_fw))}, //{ "capacitive_hynitron_cst8xx_update", cst8xx_fw, 0x0501,0x01, CST836, (sizeof(cst8xx_fw))}, //{ "capacitive_hynitron_cst9xx_update", cst9xx_fw, 0x2208,0x01, CST918, (sizeof(cst9xx_fw))}, //{ "capacitive_hynitron_cst92xx_update", cst92xx_fw, 0x2908,0x01, CST9217, (sizeof(cst92xx_fw))}, }; struct hynitron_chip_type_array hynitron_chip_type_grp[50] = { {CST016 ,HYN_CHIP_CST0XX , HYN_CHIP_PRODUCT_LINE_SEL_CAP, 0x15}, {CST026 ,HYN_CHIP_CST0XX , HYN_CHIP_PRODUCT_LINE_SEL_CAP, 0x15}, {CST036 ,HYN_CHIP_CST0XX , HYN_CHIP_PRODUCT_LINE_SEL_CAP, 0x15}, {CST126 ,HYN_CHIP_CST1XX , HYN_CHIP_PRODUCT_LINE_MUT_CAP, 0x1A}, {CST128 ,HYN_CHIP_CST1XX , HYN_CHIP_PRODUCT_LINE_MUT_CAP, 0x1A}, {CST130 ,HYN_CHIP_CST1XX , HYN_CHIP_PRODUCT_LINE_MUT_CAP, 0x1A}, {CST128SE ,HYN_CHIP_CST1XXSE, HYN_CHIP_PRODUCT_LINE_MUT_CAP, 0x5A}, {CST18858SE ,HYN_CHIP_CST1XXSE, HYN_CHIP_PRODUCT_LINE_MUT_CAP, 0x5A}, {CST140 ,HYN_CHIP_CST1XX , HYN_CHIP_PRODUCT_LINE_MUT_CAP, 0x1A}, {CST148 ,HYN_CHIP_CST1XX , HYN_CHIP_PRODUCT_LINE_MUT_CAP, 0x1A}, {CST226 ,HYN_CHIP_CST2XX , HYN_CHIP_PRODUCT_LINE_MUT_CAP, 0x1A}, {CST226SE ,HYN_CHIP_CST2XXSE, HYN_CHIP_PRODUCT_LINE_MUT_CAP, 0x5A}, {CST237 ,HYN_CHIP_CST2XX , HYN_CHIP_PRODUCT_LINE_MUT_CAP, 0x1A}, {CST240 ,HYN_CHIP_CST2XX , HYN_CHIP_PRODUCT_LINE_MUT_CAP, 0x1A}, {CST326 ,HYN_CHIP_CST1XX , HYN_CHIP_PRODUCT_LINE_MUT_CAP, 0x1A}, {CST328 ,HYN_CHIP_CST1XX , HYN_CHIP_PRODUCT_LINE_MUT_CAP, 0x1A}, {CST328SE ,HYN_CHIP_CST3XXSE, HYN_CHIP_PRODUCT_LINE_MUT_CAP, 0x5A}, {CST340 ,HYN_CHIP_CST3XX , HYN_CHIP_PRODUCT_LINE_MUT_CAP, 0x1A}, {CST348 ,HYN_CHIP_CST3XX , HYN_CHIP_PRODUCT_LINE_MUT_CAP, 0x1A}, {CST356 ,HYN_CHIP_CST3XX , HYN_CHIP_PRODUCT_LINE_MUT_CAP, 0x1A}, {CST3240 ,HYN_CHIP_CST3240 , HYN_CHIP_PRODUCT_LINE_MUT_CAP, 0x5A}, {CST6928S ,HYN_CHIP_CST6XX , HYN_CHIP_PRODUCT_LINE_MUT_CAP, 0x1A}, {CST716 ,HYN_CHIP_CST7XX , HYN_CHIP_PRODUCT_LINE_SEL_CAP, 0x15}, {CST726 ,HYN_CHIP_CST7XX , HYN_CHIP_PRODUCT_LINE_SEL_CAP, 0x15}, {CST736 ,HYN_CHIP_CST7XX , HYN_CHIP_PRODUCT_LINE_SEL_CAP, 0x15}, {CST816 ,HYN_CHIP_CST8XX , HYN_CHIP_PRODUCT_LINE_SEL_CAP, 0x15}, {CST826 ,HYN_CHIP_CST8XX , HYN_CHIP_PRODUCT_LINE_SEL_CAP, 0x15}, {CST836 ,HYN_CHIP_CST8XX , HYN_CHIP_PRODUCT_LINE_SEL_CAP, 0x15}, {CST912 ,HYN_CHIP_CST9XX , HYN_CHIP_PRODUCT_LINE_MUT_CAP, 0x1A}, {CST918 ,HYN_CHIP_CST9XX , HYN_CHIP_PRODUCT_LINE_MUT_CAP, 0x1A}, {CST9217 ,HYN_CHIP_CST92XX , HYN_CHIP_PRODUCT_LINE_MUT_CAP, 0x5A}, {CST9220 ,HYN_CHIP_CST92XX , HYN_CHIP_PRODUCT_LINE_MUT_CAP, 0x5A}, {CST644K ,HYN_CHIP_CST644K , HYN_CHIP_PRODUCT_LINE_MUT_CAP, 0x5A}, }; int cst3xx_firmware_info(struct i2c_client * client); static unsigned char update_fw_flag; #if HYN_EN_AUTO_UPDATE #if HYN_EN_AUTO_UPDATE_CST78xx static unsigned char dev_addr; static unsigned char chip_sumok_flag; /* * */ static int cst78xx_enter_bootmode(void){ char retryCnt = 10; hyn_reset_proc(1); mdelay(5); while(retryCnt--){ u8 cmd[3]; cmd[0] = 0xAA; if (-1 == hyn_i2c_write_bytes(0xA001,cmd,1,REG_LEN_2B)){ // enter program mode mdelay(2); // 4ms continue; } if (-1 == hyn_i2c_read_bytes(0xA003,cmd,1,REG_LEN_2B)) { // read flag mdelay(2); // 4ms continue; }else{ if (cmd[0] != 0x55){ msleep(2); // 4ms continue; }else{ return 0; } } } return -1; } /* * */ static int cst78xx_update(u16 startAddr,u16 len,u8* src){ u16 sum_len; u8 cmd[10]; int ret; ret = 0; HYN_FUNC_ENTER(); if (cst78xx_enter_bootmode() == -1){ return -1; } sum_len = 0; #define PER_LEN 512 do{ if (sum_len >= len){ return -1; } // send address cmd[1] = startAddr>>8; cmd[0] = startAddr&0xFF; hyn_i2c_write_bytes(0xA014,cmd,2,REG_LEN_2B); #if HYN_IIC_TRANSFER_LIMIT { u8 temp_buf[8]; u16 j,iic_addr; iic_addr=0; for(j=0; j<128; j++){ temp_buf[0] = *((u8*)src+iic_addr+0); temp_buf[1] = *((u8*)src+iic_addr+1); temp_buf[2] = *((u8*)src+iic_addr+2); temp_buf[3] = *((u8*)src+iic_addr+3); hyn_i2c_write_bytes((0xA018+iic_addr),(u8* )temp_buf,4,REG_LEN_2B); iic_addr+=4; if(iic_addr==512) break; } } #else hyn_i2c_write_bytes(0xA018,src,PER_LEN,REG_LEN_2B); #endif cmd[0] = 0xEE; hyn_i2c_write_bytes(0xA004,cmd,1,REG_LEN_2B); if(hyn_ts_data->apk_upgrade_flag==0) msleep(300); else msleep(100); { u8 retrycnt = 50; while(retrycnt--){ cmd[0] = 0; hyn_i2c_read_bytes(0xA005,cmd,1,REG_LEN_2B); if (cmd[0] == 0x55){ // success break; } msleep(10); } if(cmd[0]!=0x55) { ret = -1; } } startAddr += PER_LEN; src += PER_LEN; sum_len += PER_LEN; }while(len); // exit program mode cmd[0] = 0x00; hyn_i2c_write_bytes(0xA003,cmd,1,REG_LEN_2B); HYN_FUNC_EXIT(); return ret; } /* * */ static u32 cst78xx_read_checksum(u16 startAddr,u16 len){ union{ u32 sum; u8 buf[4]; }checksum; char cmd[3]; char readback[4] = {0}; if (cst78xx_enter_bootmode() == -1){ return -1; } cmd[0] = 0; if (-1 == hyn_i2c_write_bytes(0xA003,cmd,1,REG_LEN_2B)){ return -1; } msleep(500); if (-1 == hyn_i2c_read_bytes(0xA000,readback,1,REG_LEN_2B)){ return -1; } if (readback[0] != 1){ return -1; } if (-1 == hyn_i2c_read_bytes(0xA008,checksum.buf,4,REG_LEN_2B)){ return -1; } chip_sumok_flag = 1; return checksum.sum; } static int cst8xx_boot_update_fw(struct i2c_client *mclient){ unsigned short startAddr; unsigned short length; unsigned short checksum; unsigned short chipchecksum; HYN_FUNC_ENTER(); update_fw_flag = 1; chip_sumok_flag = 0; hyn_ts_data->client = mclient; if(hyn_ts_data->apk_upgrade_flag==0) cst8xx_firmware_info(mclient); dev_addr = hyn_ts_data->client->addr; hyn_ts_data->client->addr = 0x6A; if (cst78xx_enter_bootmode() == 0){ if((hyn_ts_data->fw_length) > 10){ startAddr = *(hyn_ts_data->p_hynitron_upgrade_firmware+1); length =*(hyn_ts_data->p_hynitron_upgrade_firmware+3); checksum = *(hyn_ts_data->p_hynitron_upgrade_firmware+5); startAddr <<= 8; startAddr |= *(hyn_ts_data->p_hynitron_upgrade_firmware+0); length <<= 8; length |= *(hyn_ts_data->p_hynitron_upgrade_firmware+2); checksum <<= 8; checksum |= *(hyn_ts_data->p_hynitron_upgrade_firmware+4); chipchecksum = cst78xx_read_checksum(startAddr, length); if(update_fw_flag||chip_sumok_flag==0) { HYN_INFO("\r\ncst8xx_boot_update_fw: low version, updating!!!r\n"); HYN_INFO("\r\n CTP cst78xx File, start-0x%04x len-0x%04x fileCheck-0x%04x\r\n",startAddr,length,checksum); if(chipchecksum != checksum){ cst78xx_update(startAddr, length, (hyn_ts_data->p_hynitron_upgrade_firmware+6)); length = cst78xx_read_checksum(startAddr, length); HYN_INFO("\r\nCTP cst78xx update %s, checksum-0x%04x",((length==checksum) ? "success" : "fail"),length); }else{ HYN_INFO("\r\nCTP cst78xx check pass..."); } } else { HYN_INFO("\r\ncst8xx_boot_update_fw: high version not update!!!r\n"); } } goto re; } else { hyn_ts_data->client->addr = dev_addr; return -1; } HYN_FUNC_EXIT(); re: hyn_ts_data->client->addr = dev_addr; hyn_reset_proc(10); return 0; } #endif #if HYN_EN_AUTO_UPDATE_CST2xx #define CST2XX_BASE_ADDR (24 * 1024) #define CST2XX_FW_BIN_SIZE (6*1024) static int cst2xx_enter_download_mode (void) { int ret; unsigned char buf[2]; buf[0] = 0xD1; buf[1] = 0x11; ret = cst3xx_i2c_write (hyn_ts_data->client, buf, 2); if (ret < 0) { return -1; } mdelay (1); //wait enter download mode buf[0] = 0xD0; buf[1] = 0x01; ret = cst3xx_i2c_read_register (hyn_ts_data->client, buf, 1); if (ret < 0) { return -1; } if (buf[0] != 0x55) { HYN_DEBUG ("[HYN]reciev 0x55 failed.\r\n"); return -1; } buf[0] = 0xD1; buf[1] = 0x10; //enter writer register mode ret = cst3xx_i2c_write (hyn_ts_data->client, buf, 2); if (ret < 0) { HYN_DEBUG ("[HYN]Send cmd 0xD110 failed. \r\n"); return -1; } return 0; } static int cst2xx_download_program (unsigned char* data, int len) { int ret; int i, j; unsigned int wr_addr; unsigned char* pData; unsigned char* pSrc; unsigned char* pDst; unsigned char i2c_buf[8]; pData = kmalloc (sizeof (unsigned char) * (1024 + 4), GFP_KERNEL); if(!pData){ HYN_ERROR ("malloc data buffer failed.\n"); return -1; } pSrc = data; HYN_DEBUG ("write program data begain:0x%x.\n", len); for (i = 0; i < (len / 1024); i++) { wr_addr = (i << 10) + CST2XX_BASE_ADDR; pData[0] = (wr_addr >> 24) & 0xFF; pData[1] = (wr_addr >> 16) & 0xFF; pData[2] = (wr_addr >> 8) & 0xFF; pData[3] = wr_addr & 0xFF; pDst = pData + 4; for (j = 0; j < 256; j++) { *pDst = * (pSrc + 3); * (pDst + 1) = * (pSrc + 2); * (pDst + 2) = * (pSrc + 1); * (pDst + 3) = *pSrc; pDst += 4; pSrc += 4; } #if (!HYN_IIC_TRANSFER_LIMIT) for (j = 0; j < 256; j++) { i2c_buf[0] = (wr_addr >> 24) & 0xFF; i2c_buf[1] = (wr_addr >> 16) & 0xFF; i2c_buf[2] = (wr_addr >> 8) & 0xFF; i2c_buf[3] = wr_addr & 0xFF; i2c_buf[4] = pData[j * 4 + 4 + 0]; i2c_buf[5] = pData[j * 4 + 4 + 1]; i2c_buf[6] = pData[j * 4 + 4 + 2]; i2c_buf[7] = pData[j * 4 + 4 + 3]; ret = cst3xx_i2c_write (hyn_ts_data->client, i2c_buf, 8); if (ret < 0) { HYN_ERROR ("program failed.\n"); goto ERR_OUT; } wr_addr += 4; } #else ret = cst3xx_i2c_write (hyn_ts_data->client, pData, 1024 + 4); if (ret < 0) { HYN_ERROR ("program failed.\n"); goto ERR_OUT; } #endif } //clear update key pData[3] = 0x20000FFC & 0xFF; pData[2] = (0x20000FFC >> 8) & 0xFF; pData[1] = (0x20000FFC >> 16) & 0xFF; pData[0] = (0x20000FFC >> 24) & 0xFF; pData[4] = 0x00; pData[5] = 0x00; pData[6] = 0x00; pData[7] = 0x00; ret = cst3xx_i2c_write (hyn_ts_data->client, pData, 8); if (ret < 0) { HYN_ERROR ("clear update key failed.\n"); goto ERR_OUT; } pData[3] = 0xD013D013 & 0xFF; pData[2] = (0xD013D013 >> 8) & 0xFF; pData[1] = (0xD013D013 >> 16) & 0xFF; pData[0] = (0xD013D013 >> 24) & 0xFF; ret = cst3xx_i2c_write (hyn_ts_data->client, pData, 4); if (ret < 0) { HYN_ERROR ("exit register read/write mode failed.\n"); goto ERR_OUT; } HYN_DEBUG("--------write program data end--------.\r\n"); if(pData){ kfree (pData); pData = NULL; } return 0; ERR_OUT: if(pData){ kfree (pData); pData = NULL; } return -1; } static int cst2xx_read_checksum (void) { int ret; int i; unsigned int checksum; unsigned int bin_checksum; unsigned char buf[4]; unsigned char* pData; for (i = 0; i < 10; i++) { buf[0] = 0xD0; buf[1] = 0x00; ret = cst3xx_i2c_read_register (hyn_ts_data->client, buf, 1); if (ret < 0) { mdelay (2); continue; } if ((buf[0] == 0x01) || (buf[0] == 0x02)) break; mdelay (2); } if ((buf[0] == 0x01) || (buf[0] == 0x02)) { buf[0] = 0xD0; buf[1] = 0x08; ret = cst3xx_i2c_read_register (hyn_ts_data->client, buf, 4); if (ret < 0) return -1; //handle read data --> checksum checksum = buf[0] + (buf[1] << 8) + (buf[2] << 16) + (buf[3] << 24); pData = hyn_ts_data->p_hynitron_upgrade_firmware+ 6160; //6*1024+16 bin_checksum = pData[0] + (pData[1] << 8) + (pData[2] << 16) + (pData[3] << 24); if (checksum != bin_checksum) HYN_DEBUG ("Check sum error.\n"); HYN_DEBUG ("checksum ic:0x%x. bin:0x%x-----\n", checksum, bin_checksum); buf[0] = 0xD0; buf[1] = 0x01; buf[2] = 0xA5; ret = cst3xx_i2c_write (hyn_ts_data->client, buf, 3); if (ret < 0) return -1; } else { HYN_DEBUG ("No checksum.\n"); return -1; } return 0; } static int cst2xx_update_firmware (struct i2c_client* client, unsigned char* pdata, int data_len) { int ret; int retry; retry = 0; HYN_DEBUG ("enter the update firmware.\n"); start_flow: client->addr = hyn_ts_data->chip_ic_main_addr; hyn_reset_proc(5+retry); client->addr = hyn_ts_data->chip_ic_bootloader_addr; hyn_ts_data->fw_updating=1; ret = cst2xx_enter_download_mode(); if (ret < 0) { HYN_ERROR ("enter download mode failed.\n"); goto fail_retry; } hyn_ts_data->fw_updating=2; ret = cst2xx_download_program (pdata, data_len); if (ret < 0) { HYN_ERROR ("download program failed.\n"); goto fail_retry; } mdelay (3); hyn_ts_data->fw_updating=3; ret = cst2xx_read_checksum(); if (ret < 0) { HYN_ERROR ("checksum failed.\n"); goto fail_retry; } client->addr = hyn_ts_data->chip_ic_main_addr; HYN_DEBUG ("Download firmware succesfully.\n"); return 0; fail_retry: if (retry < 20) { retry++; mdelay (20); goto start_flow; }else{ client->addr = hyn_ts_data->chip_ic_main_addr; } return -1; } static int cst2xx_boot_update_fw (struct i2c_client* client) { return cst2xx_update_firmware (client, hyn_ts_data->p_hynitron_upgrade_firmware, CST2XX_FW_BIN_SIZE); } #endif #if (HYN_EN_AUTO_UPDATE_CST3xxSE||HYN_EN_AUTO_UPDATE_CST2xxSE||HYN_EN_AUTO_UPDATE_CST1xxSE) #define CST3XXSE_BASE_ADDR (0x00000000) #define CST3XXSE_FW_BIN_SIZE (7*1024+512) static int cst3xxse_enter_download_mode(void) { int ret; unsigned char buf[4]; buf[0] = 0xA0; buf[1] = 0x01; buf[2] = 0xAA; ret = cst3xx_i2c_write(hyn_ts_data->client, buf, 3); if (ret < 0){ return -1; } mdelay(5); //wait enter download mode buf[0] = 0xA0; buf[1] = 0x03; //check whether into program mode ret = cst3xx_i2c_read_register(hyn_ts_data->client, buf, 1); if(ret < 0){ return -1; } if(buf[0] != 0x55){ HYN_ERROR("hyn reciev 0x55 failed.\n"); return -1; } return 0; } static int cst3xxse_download_program(unsigned char *pdata, int len) { int i, ret, j,retry; unsigned char *i2c_buf; unsigned char temp_buf[8]; unsigned short eep_addr, iic_addr; int total_kbyte; i2c_buf = kmalloc(sizeof(unsigned char)*(512 + 2), GFP_KERNEL); if (i2c_buf == NULL) { return -1; } //make sure fwbin len is N*1K total_kbyte = len / 512; for (i=0; i>8; ret = cst3xx_i2c_write(hyn_ts_data->client, i2c_buf, 4); if (ret < 0) goto error_out; #if (!HYN_IIC_TRANSFER_LIMIT) i2c_buf[0] = 0xA0; i2c_buf[1] = 0x18; memcpy(i2c_buf + 2, pdata + eep_addr, 512); ret = cst3xx_i2c_write(hyn_ts_data->client, i2c_buf, 514); if (ret < 0) goto error_out; #else memcpy(i2c_buf, pdata + eep_addr, 512); for(j=0; j<128; j++) { iic_addr = (j<<2); temp_buf[0] = (iic_addr+0xA018)>>8; temp_buf[1] = (iic_addr+0xA018)&0xFF; temp_buf[2] = i2c_buf[iic_addr+0]; temp_buf[3] = i2c_buf[iic_addr+1]; temp_buf[4] = i2c_buf[iic_addr+2]; temp_buf[5] = i2c_buf[iic_addr+3]; ret = cst3xx_i2c_write(hyn_ts_data->client, temp_buf, 6); if (ret < 0) goto error_out; } #endif i2c_buf[0] = 0xA0; i2c_buf[1] = 0x04; i2c_buf[2] = 0xEE; ret = cst3xx_i2c_write(hyn_ts_data->client, i2c_buf, 3); if (ret < 0) goto error_out; mdelay(100); // 60 for(retry=0;retry<10;retry++) { i2c_buf[0] = 0xA0; i2c_buf[1] = 0x05; ret = cst3xx_i2c_read_register(hyn_ts_data->client, i2c_buf, 1); if (ret < 0){ mdelay(100); continue; } else { if (i2c_buf[0] != 0x55) { mdelay(100); continue; } else { break; } } } if(retry==10){ goto error_out; } } i2c_buf[0] = 0xA0; i2c_buf[1] = 0x01; i2c_buf[2] = 0x00; ret = cst3xx_i2c_write(hyn_ts_data->client, i2c_buf, 3); if (ret < 0) goto error_out; i2c_buf[0] = 0xA0; i2c_buf[1] = 0x03; i2c_buf[2] = 0x00; ret = cst3xx_i2c_write(hyn_ts_data->client, i2c_buf, 3); if (ret < 0) goto error_out; if(i2c_buf){ kfree(i2c_buf); i2c_buf = NULL; } return 0; error_out: if(i2c_buf){ kfree(i2c_buf); i2c_buf = NULL; } return -1; } static int cst3xxse_read_checksum(unsigned char *p_fw) { int ret; int i; unsigned int checksum; unsigned int bin_checksum; unsigned char buf[4]; const unsigned char *pData; for(i=0; i<10; i++) { buf[0] = 0xA0; buf[1] = 0x00; ret = cst3xx_i2c_read_register(hyn_ts_data->client, buf, 1); if(ret < 0) { mdelay(2); continue; } if(buf[0]!=0) break; else mdelay(2); } mdelay(4); if(buf[0]==0x01) { buf[0] = 0xA0; buf[1] = 0x08; ret = cst3xx_i2c_read_register(hyn_ts_data->client, buf, 4); if(ret < 0) return -1; checksum = buf[0] + (buf[1]<<8) + (buf[2]<<16) + (buf[3]<<24); pData=(unsigned char *)p_fw +7680-4; //7*1024 +512 bin_checksum = pData[0] + (pData[1]<<8) + (pData[2]<<16) + (pData[3]<<24); HYN_INFO("hyn checksum ic:0x%x. bin:0x%x------\n", checksum, bin_checksum); if(checksum!=bin_checksum) { HYN_ERROR("hyn check sum error.\n"); return -1; } } else { HYN_ERROR("hyn No checksum. buf[0]:%d.\n", buf[0]); return -1; } return 0; } static int cst3xxse_update_firmware(struct i2c_client * client,unsigned char *pdata) { int ret; int retry; unsigned char buf[4]; retry = 0; HYN_INFO("hyn cst3xxse_update_firmware enter.\n"); mdelay(20); start_flow: client->addr = hyn_ts_data->chip_ic_main_addr; hyn_reset_proc(5+retry); client->addr = hyn_ts_data->chip_ic_bootloader_addr; hyn_ts_data->fw_updating=1; ret = cst3xxse_enter_download_mode(); if (ret < 0) { HYN_ERROR("hyn cst3xxse_enter_download_mode enter failed.\n"); goto fail_retry; } hyn_ts_data->fw_updating=2; ret = cst3xxse_download_program(pdata, CST3XXSE_FW_BIN_SIZE); if (ret < 0) { HYN_ERROR("hyn cst3xxse_download_program failed.\n"); goto fail_retry; } mdelay(5); hyn_ts_data->fw_updating=3; ret = cst3xxse_read_checksum(pdata); if (ret < 0) { HYN_ERROR("hyn cst3xxse_read_checksum failed.\n"); goto fail_retry; } else { buf[0] = 0xA0; //exit program buf[1] = 0x06; buf[2] = 0xEE; ret = cst3xx_i2c_write(client, buf, 3); //if(ret < 0) // goto fail_retry;; } HYN_INFO("hyn cst3xxse_update_firmware succesfully.\n"); mdelay(10); client->addr = hyn_ts_data->chip_ic_main_addr; hyn_reset_proc(20); return 0; fail_retry: if (retry < 30) { retry++; mdelay(20); goto start_flow; }else{ client->addr = hyn_ts_data->chip_ic_main_addr; } return -1; } static int cst3xxse_update_judge(unsigned char *fw , int strict) { unsigned short ic_type, project_id; unsigned int bin_checksum,bin_version; unsigned char *pData; unsigned int *pData_check; int i; bin_checksum = 0x55; pData_check = (unsigned int *)fw; for (i=0; i<(CST3XXSE_FW_BIN_SIZE-4); i+=4) { bin_checksum += (*pData_check); pData_check++; } if (bin_checksum != (*pData_check)) { HYN_ERROR("calculated checksum error:0x%x not equal 0x%x.\n", bin_checksum, *pData_check); return -1; //bad fw, so do not update } //checksum pData=(unsigned char *)fw +7680-4; //7*1024 +512 bin_checksum = pData[0] + (pData[1]<<8) + (pData[2]<<16) + (pData[3]<<24); pData=(unsigned char *)fw +7680-8; //7*1024 +512 bin_version = pData[0] + (pData[1]<<8) + (pData[2]<<16) + (pData[3]<<24); pData=(unsigned char *)fw +7680-12; //7*1024 +512 project_id = pData[1]; project_id <<= 8; project_id |= pData[0]; ic_type = pData[3]; ic_type <<= 8; ic_type |= pData[2]; if (strict > 0) { if(hyn_ts_data->chip_ic_checksum!=bin_checksum) { HYN_ERROR("hyn checksum is different******bin_checksum:0x%x, g_cst3xx_ic_checksum:0x%x. \r\n",bin_checksum,hyn_ts_data->chip_ic_checksum); #if HYN_UPDATE_FIRMWARE_FORCE HYN_INFO("update firmware online force.\n"); return 0; #endif if(hyn_ts_data->chip_ic_checkcode ==0xffffffff){ HYN_ERROR("chip ic have no firmware,start update config firmware.\n"); return 0; }else if((hyn_ts_data->chip_ic_type!=ic_type) ||(hyn_ts_data->chip_ic_project_id!=project_id)){ HYN_ERROR("chip_ic_type:0x%04x,chip_ic_project_id:0x%04x,not match.\n",hyn_ts_data->chip_ic_type, hyn_ts_data->chip_ic_project_id ); return -1; } //chip version pData=(unsigned char *)fw +7680-8; //7*1024 +512 bin_version = pData[0] + (pData[1]<<8) + (pData[2]<<16) + (pData[3]<<24); HYN_INFO("hyn bin_version is different******bin_version:0x%x, fw_version:0x%x. \r\n",bin_version,hyn_ts_data->chip_ic_fw_version); mdelay(5); if(bin_versionchip_ic_fw_version) { HYN_ERROR("hyn g_cst3xx_ic_version is higher ,no need to update firmware.\n"); return -1; } }else{ HYN_ERROR("bin_checksum(0x%x), g_cst3xx_ic_checksum(0x%x).\n",bin_checksum, hyn_ts_data->chip_ic_checksum); return -1; } } return 0; } static int cst3xxse_boot_update_fw(struct i2c_client * client) { int ret=-1; if(hyn_ts_data->apk_upgrade_flag==0){ ret = cst3xxse_update_judge(hyn_ts_data->p_hynitron_upgrade_firmware,1); if (ret < 0) { HYN_ERROR("cst3xxse_update_judge fail ,apk_upgrade_flag = %d.\n",hyn_ts_data->apk_upgrade_flag); return 0; } }else { ret = cst3xxse_update_judge(hyn_ts_data->p_hynitron_upgrade_firmware,0); if (ret < 0) { HYN_ERROR("cst3xxse_update_judge fail ,apk_upgrade_flag = %d.\n",hyn_ts_data->apk_upgrade_flag); return 0; } } return cst3xxse_update_firmware(client, hyn_ts_data->p_hynitron_upgrade_firmware); } #endif #if (HYN_EN_AUTO_UPDATE_CST6xx) /******************************************************* Function: read checksum in bootloader mode Input: client: i2c client strict: check checksum value Output: success: 0 fail: -1 *******************************************************/ #define CST6XX_BIN_SIZE (24*1024 + 28) static int cst6xx_check_checksum(struct i2c_client * client) { int ret; int i; unsigned int checksum; unsigned int bin_checksum; unsigned char buf[4]; const unsigned char *pData; for(i=0; i<5; i++) { buf[0] = 0xA0; buf[1] = 0x00; ret = cst3xx_i2c_read_register(client, buf, 1); if(ret < 0) { mdelay(2); continue; } if(buf[0]!=0) break; else mdelay(2); } mdelay(2); if(buf[0]==0x01) { buf[0] = 0xA0; buf[1] = 0x08; ret = cst3xx_i2c_read_register(client, buf, 4); if(ret < 0) return -1; // read chip checksum checksum = buf[0] + (buf[1]<<8) + (buf[2]<<16) + (buf[3]<<24); pData=(unsigned char *)hyn_ts_data->p_hynitron_upgrade_firmware +24*1024+16+4; //7*1024 +512 bin_checksum = pData[0] + (pData[1]<<8) + (pData[2]<<16) + (pData[3]<<24); HYN_INFO(" the updated ic checksum is :0x%x. the updating firmware checksum is:0x%x------\n", checksum, bin_checksum); if(checksum!=bin_checksum) { HYN_ERROR("hyn check sum error.\n"); return -1; } } else { HYN_INFO("hyn No checksum.\n"); return -1; } return 0; } static int cst6xx_into_program_mode(struct i2c_client * client) { int ret; unsigned char buf[4]; buf[0] = 0xA0; buf[1] = 0x01; buf[2] = 0xAB; //set cmd to enter program mode ret = cst3xx_i2c_write(client, buf, 3); if (ret < 0) return -1; mdelay(2); buf[0] = 0xA0; buf[1] = 0x02; //check whether into program mode ret = cst3xx_i2c_read_register(client, buf, 1); if (ret < 0) return -1; if (buf[0] != 0x55) return -1; return 0; } static int cst6xx_exit_program_mode(struct i2c_client * client) { int ret; unsigned char buf[3]; buf[0] = 0xA0; buf[1] = 0x06; buf[2] = 0xEE; ret = cst3xx_i2c_write(client, buf, 3); if (ret < 0) return -1; mdelay(10); //wait for restart return 0; } static int cst6xx_erase_program_area(struct i2c_client * client) { int ret; unsigned char buf[3]; buf[0] = 0xA0; buf[1] = 0x02; buf[2] = 0x00; //set cmd to erase main area ret = cst3xx_i2c_write(client, buf, 3); if (ret < 0) return -1; mdelay(5); buf[0] = 0xA0; buf[1] = 0x03; ret = cst3xx_i2c_read_register(client, buf, 1); if (ret < 0) return -1; if (buf[0] != 0x55) return -1; return 0; } static int cst6xx_write_program_data(struct i2c_client * client, const unsigned char *pdata) { int i, ret; unsigned char *i2c_buf; unsigned short eep_addr; int total_kbyte; #if HYN_IIC_TRANSFER_LIMIT unsigned char temp_buf[8]; unsigned short iic_addr; int j; #endif i2c_buf = kmalloc(sizeof(unsigned char)*(1024 + 2), GFP_KERNEL); if(!i2c_buf) return -1; //make sure fwbin len is N*1K //total_kbyte = len / 1024; total_kbyte = 24; for (i=0; i>8; ret = cst3xx_i2c_write(client, i2c_buf, 4); if (ret < 0) goto error_out; #if HYN_IIC_TRANSFER_LIMIT memcpy(i2c_buf, pdata + eep_addr, 1024); for(j=0; j<256; j++) { iic_addr = (j<<2); temp_buf[0] = (iic_addr+0xA018)>>8; temp_buf[1] = (iic_addr+0xA018)&0xFF; temp_buf[2] = i2c_buf[iic_addr+0]; temp_buf[3] = i2c_buf[iic_addr+1]; temp_buf[4] = i2c_buf[iic_addr+2]; temp_buf[5] = i2c_buf[iic_addr+3]; ret = cst3xx_i2c_write(client, temp_buf, 6); if (ret < 0) goto error_out; } #else i2c_buf[0] = 0xA0; i2c_buf[1] = 0x18; memcpy(i2c_buf + 2, pdata + eep_addr, 1024); ret = cst3xx_i2c_write(client, i2c_buf, 1026); if (ret < 0) goto error_out; #endif i2c_buf[0] = 0xA0; i2c_buf[1] = 0x04; i2c_buf[2] = 0xEE; ret = cst3xx_i2c_write(client, i2c_buf, 3); if (ret < 0) goto error_out; mdelay(60); i2c_buf[0] = 0xA0; i2c_buf[1] = 0x05; ret = cst3xx_i2c_read_register(client, i2c_buf, 1); if (ret < 0) goto error_out; if (i2c_buf[0] != 0x55) goto error_out; } i2c_buf[0] = 0xA0; i2c_buf[1] = 0x03; i2c_buf[2] = 0x00; ret = cst3xx_i2c_write(client, i2c_buf, 3); if (ret < 0) goto error_out; mdelay(8); if(i2c_buf){ kfree(i2c_buf); i2c_buf = NULL; } return 0; error_out: if(i2c_buf){ kfree(i2c_buf); i2c_buf = NULL; } return -1; } static int cst6xx_update_firmware(struct i2c_client * client, const unsigned char *pdata) { int ret; int retry_timer = 0; int retry = 0; HYN_INFO("----------upgrade cst3xx begain------------\n"); mdelay(20); START_FLOW: hyn_reset_proc(5+retry_timer); client->addr = hyn_ts_data->chip_ic_bootloader_addr; hyn_ts_data->fw_updating=1; ret = cst6xx_into_program_mode(client); if (ret < 0) { HYN_ERROR("into program mode failed.\n"); if(retry_timer<20) retry_timer++; goto err_out; } hyn_ts_data->fw_updating=2; ret = cst6xx_erase_program_area(client); if (ret<0) { HYN_ERROR("erase main area failed.\n"); goto err_out; } hyn_ts_data->fw_updating=3; ret = cst6xx_write_program_data(client, pdata); if (ret < 0) { HYN_ERROR("write program data into cstxxx failed.\n"); goto err_out; } hyn_ts_data->fw_updating=4; ret =cst6xx_check_checksum(client); if (ret < 0) { HYN_ERROR("after write program cst6xx_check_checksum failed.\n"); goto err_out; } hyn_ts_data->fw_updating=5; ret = cst6xx_exit_program_mode(client); if (ret < 0) { HYN_ERROR("exit program mode failed.\n"); //goto err_out; } client->addr = hyn_ts_data->chip_ic_main_addr; hyn_reset_proc(30); hyn_ts_data->fw_updating=6; HYN_INFO(" hyn----------cst3xx_update_firmware end------------\n"); return 0; err_out: if (retry < 30) { retry++; mdelay(30); goto START_FLOW; } else { client->addr = hyn_ts_data->chip_ic_main_addr; return -1; } } static int cst6xx_update_judge( unsigned char *pdata, int strict) { unsigned short ic_type, project_id; unsigned int fw_checksum, fw_version; const unsigned int *p; int i; unsigned char *pBuf; fw_checksum = 0x55; p = (const unsigned int *)pdata; for (i=0; i<(CST6XX_BIN_SIZE-4); i+=4) { fw_checksum += (*p); p++; } if (fw_checksum != (*p)) { HYN_ERROR("calculated checksum error:0x%x not equal 0x%x.\n", fw_checksum, *p); return -1; //bad fw, so do not update } pBuf = &pdata[CST6XX_BIN_SIZE-16]; project_id = pBuf[1]; project_id <<= 8; project_id |= pBuf[0]; ic_type = pBuf[3]; ic_type <<= 8; ic_type |= pBuf[2]; fw_version = pBuf[7]; fw_version <<= 8; fw_version |= pBuf[6]; fw_version <<= 8; fw_version |= pBuf[5]; fw_version <<= 8; fw_version |= pBuf[4]; fw_checksum = pBuf[11]; fw_checksum <<= 8; fw_checksum |= pBuf[10]; fw_checksum <<= 8; fw_checksum |= pBuf[9]; fw_checksum <<= 8; fw_checksum |= pBuf[8]; HYN_INFO("the updating firmware:project_id:0x%04x,ic type:0x%04x,fw_version:0x%x,checksum:0x%x\n", project_id, ic_type, fw_version, fw_checksum); #if HYN_UPDATE_FIRMWARE_FORCE HYN_INFO("update firmware online force.\n"); return 0; #endif if(hyn_ts_data->chip_ic_checkcode ==0xffffffff){ HYN_ERROR("chip ic have no firmware,start update config firmware.\n"); return 0; }else if((hyn_ts_data->chip_ic_type!=ic_type) ||((hyn_ts_data->chip_ic_project_id!=project_id)&&(hyn_ts_data->apk_upgrade_flag==0))){ HYN_ERROR("chip_ic_type:0x%04x,chip_ic_project_id:0x%04x,not match.\n",hyn_ts_data->chip_ic_type, hyn_ts_data->chip_ic_project_id ); return -1; } if (strict > 0) { if (hyn_ts_data->chip_ic_checksum != fw_checksum){ if (hyn_ts_data->chip_ic_fw_version >fw_version){ HYN_ERROR("fw version(%d), ic version(%d).\n",fw_version, hyn_ts_data->chip_ic_fw_version ); return -1; } }else{ HYN_ERROR("fw checksum(0x%x), ic checksum(0x%x).\n",fw_checksum, hyn_ts_data->chip_ic_checksum ); return -1; } } return 0; } static int cst6xx_boot_update_fw(struct i2c_client *client) { int ret; HYN_FUNC_ENTER(); if(hyn_ts_data->apk_upgrade_flag==0) ret = cst6xx_update_judge(hyn_ts_data->p_hynitron_upgrade_firmware, 1); else ret = cst6xx_update_judge(hyn_ts_data->p_hynitron_upgrade_firmware, 0); if (ret < 0) { HYN_ERROR(" update_judge fail,no need to update firmware.\n"); return 0; } ret = cst6xx_update_firmware(client, hyn_ts_data->p_hynitron_upgrade_firmware); if (ret < 0){ HYN_ERROR("update firmware failed,fw_updating:%d .\n",hyn_ts_data->fw_updating); return -1; } hyn_ts_data->fw_updating=0; mdelay(50); ret = cst3xx_firmware_info(client); if (ret < 0) { HYN_ERROR(" after update read version and checksum fail.\n"); return -1; } HYN_FUNC_EXIT(); return 0; } #endif #if HYN_EN_AUTO_UPDATE_CST644K #define CST644K_BIN_LEN ((1024*16 - 32)) static int cst644k_into_program_mode(struct i2c_client * client) { int ret; unsigned char buf[4]; buf[0] = 0xA0; buf[1] = 0x01; buf[2] = 0xAA; //set cmd to enter program mode ret = cst3xx_i2c_write(client, buf, 3); if (ret < 0) return -1; mdelay(2); buf[0] = 0xA0; buf[1] = 0x02; //check whether into program mode ret = cst3xx_i2c_read_register(client, buf, 1); if (ret < 0) return -1; if (buf[0] != 0x55) return -1; return 0; } static int cst644k_write_program_data(struct i2c_client * client, const unsigned char *pdata) { int i, ret; unsigned char *i2c_buf; int addr = 0; int bin_len = CST644K_BIN_LEN; int prog_addr = 0,prog_len=0; int CODE_RDADDR = 0x0C; //pg len int CODE_RDTYPE = 0x10; //pg type int CODE_WRADDR = 0x14;//pg dst addr int CODEBUF_ADDR = 0x18;//pg src start i2c_buf = kmalloc(sizeof(unsigned char)*(580), GFP_KERNEL); if(!i2c_buf) return -1; // 1st program last 512 - 32 prog_len = CST644K_BIN_LEN%512; prog_addr = CST644K_BIN_LEN - prog_len; i2c_buf[0] = 0xA0; i2c_buf[1] = CODE_RDTYPE; i2c_buf[2] = 0x02; cst3xx_i2c_write(client, i2c_buf, 3); //write type = 2 i2c_buf[0] = 0xA0; i2c_buf[1] = CODE_RDADDR; i2c_buf[2] = (prog_len) & 0xff; i2c_buf[3] = (prog_len>>8) & 0xff; cst3xx_i2c_write(client, i2c_buf, 4); //write prog len i2c_buf[0] = 0xA0; i2c_buf[1] = CODE_WRADDR; i2c_buf[2] = (prog_addr) & 0xff; i2c_buf[3] = (prog_addr>>8) & 0xff; cst3xx_i2c_write(client, i2c_buf, 4); //write start addr i2c_buf[0] = 0xA0; i2c_buf[1] = CODEBUF_ADDR; memcpy(i2c_buf + 2, pdata + prog_addr, prog_len); cst3xx_i2c_write(client, i2c_buf, prog_len + 2); //write program data i2c_buf[0] = 0xA0; i2c_buf[1] = 0x04; i2c_buf[2] = 0xEE; cst3xx_i2c_write(client, i2c_buf, 3); //start prog for(i=0;i<5;i++) { mdelay(100); i2c_buf[0] = 0xA0; i2c_buf[1] = 0x05; ret = cst3xx_i2c_read_register(client, i2c_buf, 1); if(i2c_buf[0] == 0x55) break; } if (ret < 0 || (i2c_buf[0] != 0x55)) goto error_out; i2c_buf[0] = 0xA0; i2c_buf[1] = CODE_RDTYPE; i2c_buf[2] = 0x00; cst3xx_i2c_write(client, i2c_buf, 3); //write type = 0 for (addr=0; addr<(bin_len - prog_len); addr+=512) { i2c_buf[0] = 0xA0; i2c_buf[1] = CODE_WRADDR; i2c_buf[2] = (addr) & 0xff; i2c_buf[3] = (addr>>8) & 0xff; cst3xx_i2c_write(client, i2c_buf, 4); //write start addr i2c_buf[0] = 0xA0; i2c_buf[1] = CODEBUF_ADDR; memcpy(i2c_buf + 2, pdata + addr, 512); cst3xx_i2c_write(client, i2c_buf, 514); //write program data i2c_buf[0] = 0xA0; i2c_buf[1] = 0x04; i2c_buf[2] = 0xEE; cst3xx_i2c_write(client, i2c_buf, 3); //start prog for(i=0;i<5;i++) { mdelay(100); i2c_buf[0] = 0xA0; i2c_buf[1] = 0x05; ret = cst3xx_i2c_read_register(client, i2c_buf, 1); if(i2c_buf[0] == 0x55) break; } if (ret < 0|| i2c_buf[0] != 0x55) goto error_out; } i2c_buf[0] = 0xA0; i2c_buf[1] = 0x03; i2c_buf[2] = 0x00; ret = cst3xx_i2c_write(client, i2c_buf, 3); if (ret < 0) goto error_out; mdelay(8); if(i2c_buf){ kfree(i2c_buf); i2c_buf = NULL; } return 0; error_out: if(i2c_buf){ kfree(i2c_buf); i2c_buf = NULL; } return -1; } static int cst644k_check_checksum(struct i2c_client * client) { int ret; int i; unsigned int checksum; unsigned int bin_checksum; unsigned char buf[4]; const unsigned char *pData; for(i=0; i<5; i++) { buf[0] = 0xA0; buf[1] = 0x00; ret = cst3xx_i2c_read_register(client, buf, 1); if(ret < 0) { mdelay(2); continue; } if(buf[0]!=0) break; else mdelay(2); } mdelay(2); if(buf[0]==0x01) { buf[0] = 0xA0; buf[1] = 0x08; ret = cst3xx_i2c_read_register(client, buf, 4); if(ret < 0) return -1; // read chip checksum checksum = buf[0] + (buf[1]<<8) + (buf[2]<<16) + (buf[3]<<24); pData=(unsigned char *)hyn_ts_data->p_hynitron_upgrade_firmware + CST644K_BIN_LEN-4; //7*1024 +512 bin_checksum = pData[0] + (pData[1]<<8) + (pData[2]<<16) + (pData[3]<<24); HYN_INFO(" the updated ic checksum is :0x%x. the updating firmware checksum is:0x%x------\n", checksum, bin_checksum); if(checksum!=bin_checksum) { HYN_ERROR("hyn check sum error.\n"); return -1; } } else { HYN_INFO("hyn No checksum.\n"); return -1; } return 0; } static int cst644k_exit_program_mode(struct i2c_client * client) { int ret; unsigned char buf[3]; buf[0] = 0xA0; buf[1] = 0x06; buf[2] = 0xEE; ret = cst3xx_i2c_write(client, buf, 3); if (ret < 0) return -1; mdelay(10); //wait for restart return 0; } static int cst644k_update_firmware(struct i2c_client * client, const unsigned char *pdata) { int ret; int retry_timer = 0; int retry = 0; HYN_INFO("----------upgrade cst644k begain------------\n"); mdelay(20); for(retry=0;retry<30;retry++) { hyn_reset_proc(5+retry_timer); client->addr = hyn_ts_data->chip_ic_bootloader_addr; hyn_ts_data->fw_updating=1; ret = cst644k_into_program_mode(client); if (ret < 0) { HYN_ERROR("into program mode failed.\n"); if(retry_timer<20) retry_timer++; continue; } hyn_ts_data->fw_updating=2; ret = cst644k_write_program_data(client, pdata); if (ret < 0) { HYN_ERROR("write program data into cstxxx failed.\n"); continue; } hyn_ts_data->fw_updating=3; ret =cst644k_check_checksum(client); if (ret < 0) { HYN_ERROR("after write program cst6xx_check_checksum failed.\n"); continue; } hyn_ts_data->fw_updating=4; ret = cst644k_exit_program_mode(client); if (ret < 0) { HYN_ERROR("exit program mode failed.\n"); continue; } client->addr = hyn_ts_data->chip_ic_main_addr; hyn_reset_proc(30); hyn_ts_data->fw_updating=5; HYN_INFO("----------upgrade cst644k end------------\n"); return 0; } client->addr = hyn_ts_data->chip_ic_main_addr; return -1; } static int cst644k_boot_update_fw(struct i2c_client *client) { int ret; HYN_FUNC_ENTER(); ret = cst644k_update_firmware(client, hyn_ts_data->p_hynitron_upgrade_firmware); if (ret < 0){ HYN_ERROR("update firmware failed,fw_updating:%d .\n",hyn_ts_data->fw_updating); return -1; } hyn_ts_data->fw_updating=0; mdelay(50); ret = cst3xx_firmware_info(client); if (ret < 0) { HYN_ERROR(" after update read version and checksum fail.\n"); return -1; } HYN_FUNC_EXIT(); return 0; } #endif #if (HYN_EN_AUTO_UPDATE_CST3xx||HYN_EN_AUTO_UPDATE_CST1xx||HYN_EN_AUTO_UPDATE_CST9xx) /******************************************************* Function: read checksum in bootloader mode Input: client: i2c client strict: check checksum value Output: success: 0 fail: -1 *******************************************************/ #define CST3XX_BIN_SIZE (24*1024 + 24) static int cst3xx_check_checksum(struct i2c_client * client) { int ret; int i; unsigned int checksum; unsigned int bin_checksum; unsigned char buf[4]; const unsigned char *pData; for(i=0; i<5; i++) { buf[0] = 0xA0; buf[1] = 0x00; ret = cst3xx_i2c_read_register(client, buf, 1); if(ret < 0) { mdelay(2); continue; } if(buf[0]!=0) break; else mdelay(2); } mdelay(2); if(buf[0]==0x01) { buf[0] = 0xA0; buf[1] = 0x08; ret = cst3xx_i2c_read_register(client, buf, 4); if(ret < 0) return -1; // read chip checksum checksum = buf[0] + (buf[1]<<8) + (buf[2]<<16) + (buf[3]<<24); pData=(unsigned char *)hyn_ts_data->p_hynitron_upgrade_firmware +24*1024+16; //7*1024 +512 bin_checksum = pData[0] + (pData[1]<<8) + (pData[2]<<16) + (pData[3]<<24); HYN_INFO(" the updated ic checksum is :0x%x. the updating firmware checksum is:0x%x------\n", checksum, bin_checksum); if(checksum!=bin_checksum) { HYN_ERROR("hyn check sum error.\n"); return -1; } } else { HYN_INFO("hyn No checksum.\n"); return -1; } return 0; } static int cst3xx_into_program_mode(struct i2c_client * client) { int ret; unsigned char buf[4]; buf[0] = 0xA0; buf[1] = 0x01; buf[2] = 0xAA; //set cmd to enter program mode ret = cst3xx_i2c_write(client, buf, 3); if (ret < 0) return -1; mdelay(2); buf[0] = 0xA0; buf[1] = 0x02; //check whether into program mode ret = cst3xx_i2c_read_register(client, buf, 1); if (ret < 0) return -1; if(hyn_ts_data->config_chip_series==HYN_CHIP_CST3XX){ if (buf[0] != 0xAC) return -1; }else{ if (buf[0] != 0x55) return -1; } return 0; } static int cst3xx_exit_program_mode(struct i2c_client * client) { int ret; unsigned char buf[3]; buf[0] = 0xA0; buf[1] = 0x06; buf[2] = 0xEE; ret = cst3xx_i2c_write(client, buf, 3); mdelay(10); //wait for restart return 0; } static int cst3xx_erase_program_area(struct i2c_client * client) { int ret; unsigned char buf[3]; buf[0] = 0xA0; buf[1] = 0x02; buf[2] = 0x00; //set cmd to erase main area ret = cst3xx_i2c_write(client, buf, 3); if (ret < 0) return -1; mdelay(5); buf[0] = 0xA0; buf[1] = 0x03; ret = cst3xx_i2c_read_register(client, buf, 1); if (ret < 0) return -1; if (buf[0] != 0x55) return -1; return 0; } static int cst3xx_write_program_data(struct i2c_client * client, const unsigned char *pdata) { int i, ret; unsigned char *i2c_buf; unsigned short eep_addr; int total_kbyte; #if HYN_IIC_TRANSFER_LIMIT unsigned char temp_buf[8]; unsigned short iic_addr; int j; #endif i2c_buf = kmalloc(sizeof(unsigned char)*(1024 + 2), GFP_KERNEL); if(!i2c_buf) return -1; //make sure fwbin len is N*1K //total_kbyte = len / 1024; total_kbyte = 24; for (i=0; i>8; ret = cst3xx_i2c_write(client, i2c_buf, 4); if (ret < 0) goto error_out; #if HYN_IIC_TRANSFER_LIMIT memcpy(i2c_buf, pdata + eep_addr, 1024); for(j=0; j<256; j++) { iic_addr = (j<<2); temp_buf[0] = (iic_addr+0xA018)>>8; temp_buf[1] = (iic_addr+0xA018)&0xFF; temp_buf[2] = i2c_buf[iic_addr+0]; temp_buf[3] = i2c_buf[iic_addr+1]; temp_buf[4] = i2c_buf[iic_addr+2]; temp_buf[5] = i2c_buf[iic_addr+3]; ret = cst3xx_i2c_write(client, temp_buf, 6); if (ret < 0) goto error_out; } #else i2c_buf[0] = 0xA0; i2c_buf[1] = 0x18; memcpy(i2c_buf + 2, pdata + eep_addr, 1024); ret = cst3xx_i2c_write(client, i2c_buf, 1026); if (ret < 0) goto error_out; #endif i2c_buf[0] = 0xA0; i2c_buf[1] = 0x04; i2c_buf[2] = 0xEE; ret = cst3xx_i2c_write(client, i2c_buf, 3); if (ret < 0) goto error_out; mdelay(60); i2c_buf[0] = 0xA0; i2c_buf[1] = 0x05; ret = cst3xx_i2c_read_register(client, i2c_buf, 1); if (ret < 0) goto error_out; if (i2c_buf[0] != 0x55) goto error_out; } i2c_buf[0] = 0xA0; i2c_buf[1] = 0x03; i2c_buf[2] = 0x00; ret = cst3xx_i2c_write(client, i2c_buf, 3); if (ret < 0) goto error_out; mdelay(8); if(i2c_buf){ kfree(i2c_buf); i2c_buf = NULL; } return 0; error_out: if(i2c_buf){ kfree(i2c_buf); i2c_buf = NULL; } return -1; } static int cst3xx_update_firmware(struct i2c_client * client, const unsigned char *pdata) { int ret; int retry_timer = 0; int retry = 0; HYN_INFO("----------upgrade cst3xx begain------------\n"); mdelay(20); START_FLOW: hyn_reset_proc(5+retry_timer); client->addr = hyn_ts_data->chip_ic_bootloader_addr; hyn_ts_data->fw_updating=1; ret = cst3xx_into_program_mode(client); if (ret < 0) { HYN_ERROR("into program mode failed.\n"); if(retry_timer<20) retry_timer++; goto err_out; } hyn_ts_data->fw_updating=2; ret = cst3xx_erase_program_area(client); if (ret<0) { HYN_ERROR("erase main area failed.\n"); goto err_out; } hyn_ts_data->fw_updating=3; ret = cst3xx_write_program_data(client, pdata); if (ret < 0) { HYN_ERROR("write program data into cstxxx failed.\n"); goto err_out; } hyn_ts_data->fw_updating=4; ret =cst3xx_check_checksum(client); if (ret < 0) { HYN_ERROR("after write program cst3xx_check_checksum failed.\n"); goto err_out; } hyn_ts_data->fw_updating=5; ret = cst3xx_exit_program_mode(client); if (ret < 0) { HYN_ERROR("exit program mode failed.\n"); //goto err_out; } client->addr = hyn_ts_data->chip_ic_main_addr; hyn_reset_proc(30); hyn_ts_data->fw_updating=6; HYN_INFO(" hyn----------cst3xx_update_firmware success end------------\n"); return 0; err_out: if (retry < 30) { retry++; mdelay(30); goto START_FLOW; } else { client->addr = hyn_ts_data->chip_ic_main_addr; HYN_INFO(" hyn----------cst3xx_update_firmware failed end------------\n"); return -1; } } static int cst3xx_update_judge( unsigned char *pdata, int strict) { unsigned short ic_type, project_id; unsigned int fw_checksum, fw_version; const unsigned int *p; int i; unsigned char *pBuf; fw_checksum = 0x55; p = (const unsigned int *)pdata; for (i=0; i<(CST3XX_BIN_SIZE-4); i+=4) { fw_checksum += (*p); p++; } if (fw_checksum != (*p)) { HYN_ERROR("calculated checksum error:0x%x not equal 0x%x.\n", fw_checksum, *p); return -1; //bad fw, so do not update } pBuf = &pdata[CST3XX_BIN_SIZE-16]; project_id = pBuf[1]; project_id <<= 8; project_id |= pBuf[0]; ic_type = pBuf[3]; ic_type <<= 8; ic_type |= pBuf[2]; fw_version = pBuf[7]; fw_version <<= 8; fw_version |= pBuf[6]; fw_version <<= 8; fw_version |= pBuf[5]; fw_version <<= 8; fw_version |= pBuf[4]; fw_checksum = pBuf[11]; fw_checksum <<= 8; fw_checksum |= pBuf[10]; fw_checksum <<= 8; fw_checksum |= pBuf[9]; fw_checksum <<= 8; fw_checksum |= pBuf[8]; HYN_INFO("the updating firmware:project_id:0x%04x,ic type:0x%04x,fw_version:0x%x,checksum:0x%x\n", project_id, ic_type, fw_version, fw_checksum); #if HYN_UPDATE_FIRMWARE_FORCE HYN_INFO("update firmware online force.\n"); return 0; #endif if(hyn_ts_data->chip_ic_checkcode ==0xffffffff){ HYN_ERROR("chip ic have no firmware,start update config firmware.\n"); return 0; }else if((hyn_ts_data->chip_ic_type!=ic_type) ||((hyn_ts_data->chip_ic_project_id!=project_id)&&(hyn_ts_data->apk_upgrade_flag==0))){ HYN_ERROR("chip_ic_type:0x%04x,chip_ic_project_id:0x%04x,not match.\n",hyn_ts_data->chip_ic_type, hyn_ts_data->chip_ic_project_id ); return -1; } if (strict > 0) { if (hyn_ts_data->chip_ic_checksum != fw_checksum){ if (hyn_ts_data->chip_ic_fw_version >fw_version){ HYN_ERROR("fw version(%d), ic version(%d).\n",fw_version, hyn_ts_data->chip_ic_fw_version ); return -1; } }else{ HYN_ERROR("fw checksum(0x%x), ic checksum(0x%x).\n",fw_checksum, hyn_ts_data->chip_ic_checksum ); return -1; } } return 0; } static int cst3xx_boot_update_fw(struct i2c_client *client) { int ret; HYN_FUNC_ENTER(); if(hyn_ts_data->apk_upgrade_flag==0) { ret = cst3xx_update_judge(hyn_ts_data->p_hynitron_upgrade_firmware, 1); } else { ret = cst3xx_update_judge(hyn_ts_data->p_hynitron_upgrade_firmware, 0); } if (ret < 0) { HYN_ERROR(" update_judge fail,no need to update firmware.\n"); return 0; } ret = cst3xx_update_firmware(client, hyn_ts_data->p_hynitron_upgrade_firmware); if (ret < 0){ HYN_ERROR("update firmware failed,fw_updating:%d .\n",hyn_ts_data->fw_updating); return -1; } hyn_ts_data->fw_updating=0; mdelay(50); ret = cst3xx_firmware_info(client); if (ret < 0) { HYN_ERROR(" after update read version and checksum fail.\n"); return -1; } HYN_FUNC_EXIT(); return 0; } #endif #if (HYN_EN_AUTO_UPDATE_CST3240) /******************************************************* Function: read checksum in bootloader mode Input: client: i2c client strict: check checksum value Output: success: 0 fail: -1 *******************************************************/ #define CST3240_BIN_SIZE (31*512 + 480) static int cst3240_check_checksum(struct i2c_client * client) { int ret; int i; unsigned int checksum; unsigned int bin_checksum; unsigned char buf[4]; const unsigned char *pData; for(i=0; i<100; i++) { buf[0] = 0xA0; buf[1] = 0x00; ret = cst3xx_i2c_read_register(client, buf, 1); if(ret < 0) { mdelay(2); continue; } if(buf[0]!=0) break; else mdelay(2); } mdelay(2); if(buf[0]==0x01) { buf[0] = 0xA0; buf[1] = 0x08; ret = cst3xx_i2c_read_register(client, buf, 4); if(ret < 0) return -1; // read chip checksum checksum = buf[0] + (buf[1]<<8) + (buf[2]<<16) + (buf[3]<<24); pData=(unsigned char *)hyn_ts_data->p_hynitron_upgrade_firmware +31*512+476; //7*1024 +512 bin_checksum = pData[0] + (pData[1]<<8) + (pData[2]<<16) + (pData[3]<<24); HYN_INFO(" the updated ic checksum is :0x%x. the updating firmware checksum is:0x%x------\n", checksum, bin_checksum); if(checksum!=bin_checksum) { HYN_ERROR("hyn check sum error.\n"); return -1; } } else { HYN_INFO("hyn No checksum.\n"); return -1; } return 0; } static int cst3240_into_program_mode(struct i2c_client * client) { int ret; unsigned char buf[4]; buf[0] = 0xA0; buf[1] = 0x01; buf[2] = 0xAA; //set cmd to enter program mode ret = cst3xx_i2c_write(client, buf, 3); if (ret < 0) return -1; mdelay(2); buf[0] = 0xA0; buf[1] = 0x02; //check whether into program mode ret = cst3xx_i2c_read_register(client, buf, 3); if (ret < 0) return -1; if (buf[0] != 0x55) return -1; mdelay(2); buf[0] = 0xA0; buf[1] = 0x03; //check whether into program mode ret = cst3xx_i2c_read_register(client, buf, 3); if (ret < 0) return -1; if (buf[0] != 0xA8) return -1; mdelay(2); buf[0] = 0xA0; buf[1] = 0x01; buf[2] = 0x00; ret = cst3xx_i2c_write(client, buf, 3); if (ret < 0) return -1; return 0; } static int cst3240_exit_program_mode(struct i2c_client * client) { int ret; unsigned char buf[3]; buf[0] = 0xA0; buf[1] = 0x06; buf[2] = 0xEE; ret = cst3xx_i2c_write(client, buf, 3); mdelay(10); //wait for restart return 0; } static int cst3240_write_program_data(struct i2c_client * client, const unsigned char *pdata) { int i, ret,k; unsigned char *i2c_buf; unsigned short eep_addr; int total_kbyte; #if HYN_IIC_TRANSFER_LIMIT unsigned char temp_buf[8]; unsigned short iic_addr; int j; #endif i2c_buf = kmalloc(sizeof(unsigned char)*(512 + 2), GFP_KERNEL); if(!i2c_buf) return -1; i2c_buf[0] = 0xA0; i2c_buf[1] = 0x10; i2c_buf[2] = 0x00; ret = cst3xx_i2c_write(client, i2c_buf, 3); if (ret < 0) return -1; //make sure fwbin len is N*1K //total_kbyte = len / 1024; total_kbyte = 31; for (i=0; i>8; ret = cst3xx_i2c_write(client, i2c_buf, 4); if (ret < 0) goto error_out; #if HYN_IIC_TRANSFER_LIMIT memcpy(i2c_buf, pdata + eep_addr, 512); for(j=0; j<128; j++) { iic_addr = (j<<2); temp_buf[0] = (iic_addr+0xA018)>>8; temp_buf[1] = (iic_addr+0xA018)&0xFF; temp_buf[2] = i2c_buf[iic_addr+0]; temp_buf[3] = i2c_buf[iic_addr+1]; temp_buf[4] = i2c_buf[iic_addr+2]; temp_buf[5] = i2c_buf[iic_addr+3]; ret = cst3xx_i2c_write(client, temp_buf, 6); if (ret < 0) goto error_out; } #else i2c_buf[0] = 0xA0; i2c_buf[1] = 0x18; memcpy(i2c_buf + 2, pdata + eep_addr, 512); ret = cst3xx_i2c_write(client, i2c_buf, 514); if (ret < 0) goto error_out; #endif i2c_buf[0] = 0xA0; i2c_buf[1] = 0x04; i2c_buf[2] = 0xEE; ret = cst3xx_i2c_write(client, i2c_buf, 3); if (ret < 0) goto error_out; mdelay(5); for(k=0;k<200;k++){ i2c_buf[0] = 0xA0; i2c_buf[1] = 0x05; ret = cst3xx_i2c_read_register(client, i2c_buf, 1); //if (ret < 0) // goto error_out; if (i2c_buf[0] == 0x55) break; mdelay(10); } if(k==200) goto error_out; } i2c_buf[0] = 0xA0; i2c_buf[1] = 0x10; i2c_buf[2] = 0x02; ret = cst3xx_i2c_write(client, i2c_buf, 3); if (ret < 0) return -1; i2c_buf[0] = 0xA0; i2c_buf[1] = 0x0C; i2c_buf[2] = 0x1E0&0xff;//480 i2c_buf[3] = 0x1E0>>8; ret = cst3xx_i2c_write(client, i2c_buf, 4); if (ret < 0) return -1; i2c_buf[0] = 0xA0; i2c_buf[1] = 0x14; eep_addr = 31 << 9; //i * 1024 i2c_buf[2] = eep_addr; i2c_buf[3] = eep_addr>>8; ret = cst3xx_i2c_write(client, i2c_buf, 4); if (ret < 0) goto error_out; #if HYN_IIC_TRANSFER_LIMIT memcpy(i2c_buf, pdata + eep_addr, 480); for(j=0; j<120; j++) { iic_addr = (j<<2); temp_buf[0] = (iic_addr+0xA018)>>8; temp_buf[1] = (iic_addr+0xA018)&0xFF; temp_buf[2] = i2c_buf[iic_addr+0]; temp_buf[3] = i2c_buf[iic_addr+1]; temp_buf[4] = i2c_buf[iic_addr+2]; temp_buf[5] = i2c_buf[iic_addr+3]; ret = cst3xx_i2c_write(client, temp_buf, 6); if (ret < 0) goto error_out; } #else i2c_buf[0] = 0xA0; i2c_buf[1] = 0x18; memcpy(i2c_buf + 2, pdata + eep_addr, 480); ret = cst3xx_i2c_write(client, i2c_buf, 482); if (ret < 0) goto error_out; #endif i2c_buf[0] = 0xA0; i2c_buf[1] = 0x04; i2c_buf[2] = 0xEE; ret = cst3xx_i2c_write(client, i2c_buf, 3); if (ret < 0) goto error_out; mdelay(5); for(k=0;k<200;k++){ i2c_buf[0] = 0xA0; i2c_buf[1] = 0x05; ret = cst3xx_i2c_read_register(client, i2c_buf, 1); //if (ret < 0) // goto error_out; if (i2c_buf[0] == 0x55) break; mdelay(10); } if(k==200) goto error_out; i2c_buf[0] = 0xA0; i2c_buf[1] = 0x03; i2c_buf[2] = 0x00; ret = cst3xx_i2c_write(client, i2c_buf, 3); if (ret < 0) goto error_out; mdelay(8); if(i2c_buf){ kfree(i2c_buf); i2c_buf = NULL; } return 0; error_out: if(i2c_buf){ kfree(i2c_buf); i2c_buf = NULL; } return -1; } static int cst3240_update_firmware(struct i2c_client * client, const unsigned char *pdata) { int ret; int retry_timer = 0; int retry = 0; HYN_INFO("----------upgrade cst3xx begain------------\n"); mdelay(20); START_FLOW: hyn_reset_proc(5+retry_timer); client->addr = hyn_ts_data->chip_ic_bootloader_addr; hyn_ts_data->fw_updating=1; ret = cst3240_into_program_mode(client); if (ret < 0) { HYN_ERROR("into program mode failed.\n"); if(retry_timer<20) retry_timer++; goto err_out; } hyn_ts_data->fw_updating=2; ret = cst3240_write_program_data(client, pdata); if (ret < 0) { HYN_ERROR("write program data into cstxxx failed.\n"); goto err_out; } hyn_ts_data->fw_updating=3; ret =cst3240_check_checksum(client); if (ret < 0) { HYN_ERROR("after write program cst3xx_check_checksum failed.\n"); goto err_out; } hyn_ts_data->fw_updating=4; ret = cst3240_exit_program_mode(client); if (ret < 0) { HYN_ERROR("exit program mode failed.\n"); //goto err_out; } client->addr = hyn_ts_data->chip_ic_main_addr; hyn_reset_proc(30); hyn_ts_data->fw_updating=0; HYN_INFO(" hyn----------cst3xx_update_firmware end------------\n"); return 0; err_out: if (retry < 30) { retry++; mdelay(30); goto START_FLOW; } else { client->addr = hyn_ts_data->chip_ic_main_addr; return -1; } } static int cst3240_update_judge( unsigned char *pdata, int strict) { unsigned short ic_type, project_id; unsigned int fw_checksum, fw_version; const unsigned int *p; int i; unsigned char *pBuf; fw_checksum = 0x55; p = (const unsigned int *)pdata; for (i=0; i<(CST3240_BIN_SIZE-4); i+=4) { fw_checksum += (*p); p++; } if (fw_checksum != (*p)) { HYN_ERROR("calculated checksum error:0x%x not equal 0x%x.\n", fw_checksum, *p); return -1; //bad fw, so do not update } pBuf = &pdata[CST3240_BIN_SIZE-16+4]; project_id = pBuf[1]; project_id <<= 8; project_id |= pBuf[0]; ic_type = pBuf[3]; ic_type <<= 8; ic_type |= pBuf[2]; fw_version = pBuf[7]; fw_version <<= 8; fw_version |= pBuf[6]; fw_version <<= 8; fw_version |= pBuf[5]; fw_version <<= 8; fw_version |= pBuf[4]; fw_checksum = pBuf[11]; fw_checksum <<= 8; fw_checksum |= pBuf[10]; fw_checksum <<= 8; fw_checksum |= pBuf[9]; fw_checksum <<= 8; fw_checksum |= pBuf[8]; HYN_INFO("the updating firmware:project_id:0x%04x,ic type:0x%04x,fw_version:0x%x,checksum:0x%x\n", project_id, ic_type, fw_version, fw_checksum); #if HYN_UPDATE_FIRMWARE_FORCE HYN_INFO("update firmware online force.\n"); return 0; #endif if(hyn_ts_data->chip_ic_checkcode ==0xffffffff){ HYN_ERROR("chip ic have no firmware,start update config firmware.\n"); return 0; }else if((hyn_ts_data->chip_ic_type!=ic_type) ||((hyn_ts_data->chip_ic_project_id!=project_id)&&(hyn_ts_data->apk_upgrade_flag==0))){ HYN_ERROR("chip_ic_type:0x%04x,chip_ic_project_id:0x%04x,not match.\n",hyn_ts_data->chip_ic_type, hyn_ts_data->chip_ic_project_id ); return -1; } if (strict > 0) { if (hyn_ts_data->chip_ic_checksum != fw_checksum){ if (hyn_ts_data->chip_ic_fw_version >fw_version){ HYN_ERROR("fw version(%d), ic version(%d).\n",fw_version, hyn_ts_data->chip_ic_fw_version ); return -1; } }else{ HYN_ERROR("fw checksum(0x%x), ic checksum(0x%x).\n",fw_checksum, hyn_ts_data->chip_ic_checksum ); return -1; } } return 0; } static int cst3240_boot_update_fw(struct i2c_client *client) { int ret = -1; HYN_FUNC_ENTER(); if(hyn_ts_data->apk_upgrade_flag==0){ ret = cst3240_update_judge(hyn_ts_data->p_hynitron_upgrade_firmware, 1); if (ret < 0) { HYN_ERROR(" update_judge fail,no need to update firmware.\n"); return 0; } }else{ ret = cst3240_update_judge(hyn_ts_data->p_hynitron_upgrade_firmware, 0); if (ret < 0) { HYN_ERROR(" update_judge fail,no need to update firmware.\n"); return 0; } } ret = cst3240_update_firmware(client, hyn_ts_data->p_hynitron_upgrade_firmware); if (ret < 0){ HYN_ERROR("update firmware failed,fw_updating:%d .\n",hyn_ts_data->fw_updating); return -1; } hyn_ts_data->fw_updating=0; mdelay(50); ret = cst3xx_firmware_info(client); if (ret < 0) { HYN_ERROR(" after update read version and checksum fail.\n"); return -1; } HYN_FUNC_EXIT(); return 0; } #endif #if (HYN_EN_AUTO_UPDATE_CST92XX) /******************************************************* Function: read checksum in bootloader mode Input: client: i2c client strict: check checksum value Output: success: 0 fail: -1 *******************************************************/ #define CST92XX_BIN_SIZE (32*1024 - 128) static int cst92xx_check_checksum(struct i2c_client * client) { int ret; int i; unsigned int checksum; unsigned int bin_checksum; unsigned char buf[4]; const unsigned char *pData; //enter checksum check buf[0] = 0xA0; buf[1] = 0x03; buf[2] = 0x00; ret = cst3xx_i2c_write(client, buf, 3); if (ret < 0) return -1; mdelay(10); for(i=0; i<40; i++) { buf[0] = 0xA0; buf[1] = 0x00; ret = cst3xx_i2c_read_register(client, buf, 1); if(ret < 0) { mdelay(2); continue; } if(buf[0]== 0x01) break; else mdelay(1); } mdelay(2); if(buf[0]==0x01) { buf[0] = 0xA0; buf[1] = 0x08; ret = cst3xx_i2c_read_register(client, buf, 4); if(ret < 0) return -1; // read chip checksum checksum = buf[0] + (buf[1]<<8) + (buf[2]<<16) + (buf[3]<<24); pData=(unsigned char *)hyn_ts_data->p_hynitron_upgrade_firmware +CST92XX_BIN_SIZE-16-4; bin_checksum = pData[0] + (pData[1]<<8) + (pData[2]<<16) + (pData[3]<<24); HYN_INFO(" the updated ic checksum is :0x%x. the updating firmware checksum is:0x%x------\n", checksum, bin_checksum); if(checksum!=bin_checksum) { HYN_ERROR("hyn check sum error.\n"); return -1; } } else { HYN_INFO("hyn No checksum.\n"); return -1; } return 0; } static int cst92xx_into_program_mode(struct i2c_client * client) { int ret; unsigned char buf[4]; unsigned char check_cnt =0; for(check_cnt = 0; check_cnt < 5;check_cnt++){ buf[0] = 0xA0; buf[1] = 0x01; buf[2] = 0xAA; //set cmd to enter program mode ret = cst3xx_i2c_write(client, buf, 3); if (ret < 0) return -1; mdelay(2); buf[0] = 0xA0; buf[1] = 0x02; //check whether into program mode ret = cst3xx_i2c_read_register(client, buf, 2); if (ret < 0) return -1; if ((buf[0] == 0x55) && (buf[1] == 0xB0)) { break; } } HYN_DEBUG("cst92xx_into_program_mode:%x,%x",buf[0],buf[1]); //mdelay(2); //buf[0] = 0xA0; //buf[1] = 0x03; //check whether into program mode //ret = cst3xx_i2c_read_register(client, buf, 1); //if (ret < 0) return -1; //if (buf[0] != 0xB0) // return -1; mdelay(2); buf[0] = 0xA0; buf[1] = 0x01; buf[2] = 0x00; ret = cst3xx_i2c_write(client, buf, 3); if (ret < 0) return -1; return 0; } static int cst92xx_exit_program_mode(struct i2c_client * client) { int ret; unsigned char buf[3]; buf[0] = 0xA0; buf[1] = 0x06; buf[2] = 0xEE; ret = cst3xx_i2c_write(client, buf, 3); mdelay(10); //wait for restart return 0; } static int cst92xx_erase_flash_data(struct i2c_client * client) { int ret = -1; unsigned char i2c_buf[8]; unsigned char retry = 0; //erse flash i2c_buf[0] = 0xA0; i2c_buf[1] = 0x14; i2c_buf[2] = 0x00; i2c_buf[3] = 0x00; ret = cst3xx_i2c_write(client, i2c_buf, 4); if (ret < 0) return -1; i2c_buf[0] = 0xA0; i2c_buf[1] = 0x0C; i2c_buf[2] = 0x80; i2c_buf[3] = 0x7F; ret = cst3xx_i2c_write(client, i2c_buf, 4); if (ret < 0) return -1; i2c_buf[0] = 0xA0; i2c_buf[1] = 0x04; i2c_buf[2] = 0xEC; ret = cst3xx_i2c_write(client, i2c_buf, 3); if (ret < 0) return -1; for ( retry= 0;retry < 100; retry++) { mdelay(10); // timeout i2c_buf[0] = 0xA0; i2c_buf[1] = 0x05; ret = cst3xx_i2c_read_register(client, i2c_buf, 1); if (ret < 0) return -1; if (i2c_buf[0] == 0x88) { break; } mdelay(10); } if(retry ==100 ) return -1; else return 0; } static int cst92xx_write_program_data(struct i2c_client * client, const unsigned char *pdata) { int i, ret,k; unsigned char *i2c_buf; unsigned short eep_addr; unsigned int total_kbyte; unsigned int single_kbyte; #if HYN_IIC_TRANSFER_LIMIT unsigned char temp_buf[8]; unsigned short iic_addr; int j; #endif i2c_buf = kmalloc(sizeof(unsigned char)*(1024 + 2), GFP_KERNEL); if(!i2c_buf) return -1; // i2c_buf[0] = 0xA0; // i2c_buf[1] = 0x10; // i2c_buf[2] = 0x00; // ret = cst3xx_i2c_write(client, i2c_buf, 3); // if (ret < 0) return -1; //total_kbyte = 32 *1024;-128 total_kbyte = 32; for (i=0; i>8; ret = cst3xx_i2c_write(client, i2c_buf, 4); if (ret < 0) goto error_out; #if HYN_IIC_TRANSFER_LIMIT memcpy(i2c_buf, pdata + eep_addr, single_kbyte); for(j=0; j<(single_kbyte>>2); j++) { iic_addr = (j<<2); temp_buf[0] = (iic_addr+0xA018)>>8; temp_buf[1] = (iic_addr+0xA018)&0xFF; temp_buf[2] = i2c_buf[iic_addr+0]; temp_buf[3] = i2c_buf[iic_addr+1]; temp_buf[4] = i2c_buf[iic_addr+2]; temp_buf[5] = i2c_buf[iic_addr+3]; ret = cst3xx_i2c_write(client, temp_buf, 6); if (ret < 0) goto error_out; } #else i2c_buf[0] = 0xA0; i2c_buf[1] = 0x18; memcpy(i2c_buf + 2, pdata + eep_addr, single_kbyte); ret = cst3xx_i2c_write(client, i2c_buf, (2+single_kbyte)); if (ret < 0) goto error_out; #endif i2c_buf[0] = 0xA0; i2c_buf[1] = 0x04; i2c_buf[2] = 0xEE; ret = cst3xx_i2c_write(client, i2c_buf, 3); if (ret < 0) goto error_out; mdelay(40); for(k=0;k<50;k++){ i2c_buf[0] = 0xA0; i2c_buf[1] = 0x05; ret = cst3xx_i2c_read_register(client, i2c_buf, 1); if (ret < 0) goto error_out; if (i2c_buf[0] == 0x55) break; mdelay(1); } if(k==50) goto error_out; } if(i2c_buf){ kfree(i2c_buf); i2c_buf = NULL; } return 0; error_out: if(i2c_buf){ kfree(i2c_buf); i2c_buf = NULL; } return -1; } static int cst92xx_update_firmware(struct i2c_client * client, const unsigned char *pdata) { int ret; int retry_timer = 0; int retry = 0; HYN_INFO("----------upgrade cst92xx begain------------\n"); mdelay(20); START_FLOW: hyn_reset_proc(5+retry_timer); client->addr = hyn_ts_data->chip_ic_bootloader_addr; hyn_ts_data->fw_updating=1; ret = cst92xx_into_program_mode(client); if (ret < 0) { HYN_ERROR("into program mode failed.\n"); if(retry_timer<20) retry_timer++; goto err_out; } hyn_ts_data->fw_updating=2; ret =cst92xx_erase_flash_data(client); if (ret < 0) { HYN_ERROR("erase flash data failed.\n"); goto err_out; } hyn_ts_data->fw_updating=3; ret = cst92xx_write_program_data(client, pdata); if (ret < 0) { HYN_ERROR("write program data into cstxxx failed.\n"); goto err_out; } hyn_ts_data->fw_updating=4; ret =cst92xx_check_checksum(client); if (ret < 0) { HYN_ERROR("after write program cst3xx_check_checksum failed.\n"); goto err_out; } hyn_ts_data->fw_updating=5; ret = cst92xx_exit_program_mode(client); if (ret < 0) { HYN_ERROR("exit program mode failed.\n"); //goto err_out; } client->addr = hyn_ts_data->chip_ic_main_addr; hyn_reset_proc(30); hyn_ts_data->fw_updating=0; HYN_INFO(" hyn----------cst3xx_update_firmware end------------\n"); return 0; err_out: if (retry < 30) { retry++; mdelay(30); goto START_FLOW; } else { client->addr = hyn_ts_data->chip_ic_main_addr; return -1; } } static int cst92xx_update_judge( unsigned char *pdata, int strict) { unsigned short ic_type, project_id; unsigned int fw_checksum, fw_version; const unsigned int *p; int i; unsigned char *pBuf; fw_checksum = 0x55; p = (const unsigned int *)pdata; for (i=0; i<(CST92XX_BIN_SIZE-20); i+=4) { fw_checksum += (*p); p++; } if (fw_checksum != (*p)) { HYN_ERROR("calculated checksum error:0x%x not equal 0x%x.\n", fw_checksum, *p); return -1; //bad fw, so do not update } pBuf = &pdata[CST92XX_BIN_SIZE-16-12]; project_id = pBuf[1]; project_id <<= 8; project_id |= pBuf[0]; ic_type = pBuf[3]; ic_type <<= 8; ic_type |= pBuf[2]; fw_version = pBuf[7]; fw_version <<= 8; fw_version |= pBuf[6]; fw_version <<= 8; fw_version |= pBuf[5]; fw_version <<= 8; fw_version |= pBuf[4]; fw_checksum = pBuf[11]; fw_checksum <<= 8; fw_checksum |= pBuf[10]; fw_checksum <<= 8; fw_checksum |= pBuf[9]; fw_checksum <<= 8; fw_checksum |= pBuf[8]; HYN_INFO("the updating firmware:project_id:0x%04x,ic type:0x%04x,fw_version:0x%x,checksum:0x%x\n", project_id, ic_type, fw_version, fw_checksum); #if HYN_UPDATE_FIRMWARE_FORCE HYN_INFO("update firmware online force.\n"); return 0; #endif if(hyn_ts_data->chip_ic_checkcode ==0xffffffff){ HYN_ERROR("chip ic have no firmware,start update config firmware.\n"); return 0; }else if((hyn_ts_data->chip_ic_type!=ic_type) ||((hyn_ts_data->chip_ic_project_id!=project_id)&&(hyn_ts_data->apk_upgrade_flag==0))){ HYN_ERROR("chip_ic_type:0x%04x,chip_ic_project_id:0x%04x,not match.\n",hyn_ts_data->chip_ic_type, hyn_ts_data->chip_ic_project_id ); return -1; } if (strict > 0) { if (hyn_ts_data->chip_ic_checksum != fw_checksum){ if (hyn_ts_data->chip_ic_fw_version >fw_version){ HYN_ERROR("fw version(%d), ic version(%d).\n",fw_version, hyn_ts_data->chip_ic_fw_version ); return -1; } }else{ HYN_ERROR("fw checksum(0x%x), ic checksum(0x%x).\n",fw_checksum, hyn_ts_data->chip_ic_checksum ); return -1; } } return 0; } static int cst92xx_boot_update_fw(struct i2c_client *client) { int ret; HYN_FUNC_ENTER(); if(hyn_ts_data->apk_upgrade_flag==0) ret = cst92xx_update_judge(hyn_ts_data->p_hynitron_upgrade_firmware, 1); else ret = cst92xx_update_judge(hyn_ts_data->p_hynitron_upgrade_firmware, 0); if (ret < 0) { HYN_ERROR(" update_judge fail,no need to update firmware.\n"); return 0; } ret = cst92xx_update_firmware(client, hyn_ts_data->p_hynitron_upgrade_firmware); if (ret < 0){ HYN_ERROR("update firmware failed,fw_updating:%d .\n",hyn_ts_data->fw_updating); return -1; } hyn_ts_data->fw_updating=0; mdelay(50); ret = cst3xx_firmware_info(client); if (ret < 0) { HYN_ERROR(" after update read version and checksum fail.\n"); return -1; } HYN_FUNC_EXIT(); return 0; } #endif #endif #if HYN_SYS_AUTO_SEARCH_FIRMWARE //system irrelevant #define ERROR_HN_VER _ERROR(10) //HotKnot version error. #define ERROR_CHECK _ERROR(11) //Compare src and dst error. #define ERROR_RETRY _ERROR(12) //Too many retries. #define ERROR_PATH _ERROR(13) //Mount path error #define ERROR_FW _ERROR(14) #define ERROR_FILE _ERROR(15) #define ERROR_VALUE _ERROR(16) //Illegal value of variables static s32 hyn_check_fs_mounted(char *path_name) { struct path root_path; struct path path; s32 err; err = kern_path("/", LOOKUP_FOLLOW, &root_path); if (err) return -1; err = kern_path(path_name, LOOKUP_FOLLOW, &path); if (err) { err = -1; goto check_fs_fail; } if (path.mnt->mnt_sb == root_path.mnt->mnt_sb) { // not mounted err = -1; } else { err = 0; } path_put(&path); check_fs_fail: path_put(&root_path); return err; } static int hyn_auto_read_file(char *file_name, u8 **file_buf) { int ret = 0; char file_path[FILE_NAME_LENGTH] = { 0 }; struct file *filp = NULL; struct inode *inode; mm_segment_t old_fs; loff_t pos; loff_t file_len = 0; int retry=20; HYN_FUNC_ENTER(); if((!file_name) || (!file_buf)){ HYN_ERROR("filename/filebuf is NULL"); return -EINVAL; } old_fs = get_fs(); set_fs(KERNEL_DS); snprintf(file_path, FILE_NAME_LENGTH, "%s%s", HYN_UPDATE_FIRMWARE_PATH_1, file_name); HYN_INFO("file_path:%s.\n",file_path); while (retry-- > 0) { msleep(500); // check if rootfs is ready if (hyn_check_fs_mounted("/data")) { HYN_INFO("filesystem is not ready"); continue; } } filp = filp_open(file_path, O_RDONLY, 0); if (IS_ERR(filp)) { HYN_ERROR("open %s file fail, try open /sdcard/firmware/", file_path); snprintf(file_path, FILE_NAME_LENGTH, "%s%s",HYN_UPDATE_FIRMWARE_PATH_2 , file_name); HYN_INFO("file_path:%s.\n",file_path); filp = filp_open(file_path, O_RDONLY, 0); if (IS_ERR(filp)) { HYN_ERROR("open %s file fail", file_path); goto ERROR; } } inode = filp->f_inode; file_len = inode->i_size; *file_buf = vmalloc(file_len); if(!(*file_buf)){ HYN_ERROR("file buf malloc fail"); filp_close(filp, NULL); goto ERROR; } pos = 0; ret = vfs_read(filp, *file_buf, file_len, &pos); if (ret < 0) HYN_ERROR("read file fail"); HYN_INFO("file len:%d read len:%d pos:%d", (u32) file_len, ret, (u32) pos); filp_close(filp, NULL); set_fs(old_fs); HYN_FUNC_EXIT(); return ret; ERROR: filp_close(filp, NULL); set_fs(old_fs); return -1; } int hyn_sys_auto_search_firmware(void) { u8 *fw_file_buf = NULL; int ret; char *fw_name= NULL; char fwname[FILE_NAME_LENGTH] = { 0 }; HYN_FUNC_ENTER(); memset(fwname, 0, sizeof(fwname)); snprintf(fwname, PAGE_SIZE, "%s", HYN_UPDATE_FIRMWARE_FILTNAME_1); fwname[sizeof(HYN_UPDATE_FIRMWARE_FILTNAME_1) - 1] = '\0'; HYN_INFO("fwname:%s.\n",fwname); ret = hyn_auto_read_file(fw_name, &fw_file_buf); if (ret < 0) { HYN_ERROR("hyn_auto_read_file.\n"); return -1; } if(fw_file_buf!=NULL){ hyn_ts_data->apk_upgrade_flag=1; hyn_ts_data->p_hynitron_upgrade_firmware=fw_file_buf; }else{ HYN_ERROR("hyn_sys_auto_search_firmware fw_file_buf is null.\n"); } HYN_FUNC_EXIT(); return 0; } #endif /******************************************************* Function: get firmware version, ic type... Input: client: i2c client Output: success: 0 fail: -1 *******************************************************/ int cst3xx_firmware_info(struct i2c_client * client) { int ret; unsigned char buf[28]; HYN_FUNC_ENTER(); buf[0] = 0xD1; buf[1] = 0x01; ret = cst3xx_i2c_write(client, buf, 2); if (ret < 0) return -1; mdelay(10); buf[0] = 0xD1; buf[1] = 0xFC; ret = cst3xx_i2c_read_register(client, buf, 4); if (ret < 0) return -1; //0xCACA0000 hyn_ts_data->chip_ic_checkcode = buf[3]; hyn_ts_data->chip_ic_checkcode <<= 8; hyn_ts_data->chip_ic_checkcode |= buf[2]; hyn_ts_data->chip_ic_checkcode <<= 8; hyn_ts_data->chip_ic_checkcode |= buf[1]; hyn_ts_data->chip_ic_checkcode <<= 8; hyn_ts_data->chip_ic_checkcode |= buf[0]; HYN_INFO("the chip chip_ic_checkcode:0x%x.\r\n",hyn_ts_data->chip_ic_checkcode); if((hyn_ts_data->chip_ic_checkcode&0xffff0000)!=0xCACA0000){ HYN_ERROR("cst3xx_firmware_info read error .\r\n"); hyn_ts_data->chip_ic_checkcode =0xffffffff; return -1; } mdelay(10); buf[0] = 0xD2; buf[1] = 0x04; ret = cst3xx_i2c_read_register(client, buf, 4); if (ret < 0) return -1; hyn_ts_data->chip_ic_type = buf[3]; hyn_ts_data->chip_ic_type <<= 8; hyn_ts_data->chip_ic_type |= buf[2]; hyn_ts_data->config_chip_type =hyn_ts_data->chip_ic_type; hyn_ts_data->chip_ic_project_id = buf[1]; hyn_ts_data->chip_ic_project_id <<= 8; hyn_ts_data->chip_ic_project_id |= buf[0]; HYN_INFO("chip_ic_type :0x%x, chip_ic_project_id:0x%x\r\n", hyn_ts_data->chip_ic_type, hyn_ts_data->chip_ic_project_id); mdelay(2); buf[0] = 0xD2; buf[1] = 0x08; ret = cst3xx_i2c_read_register(client, buf, 8); if (ret < 0) return -1; hyn_ts_data->chip_ic_fw_version = buf[3]; hyn_ts_data->chip_ic_fw_version <<= 8; hyn_ts_data->chip_ic_fw_version |= buf[2]; hyn_ts_data->chip_ic_fw_version <<= 8; hyn_ts_data->chip_ic_fw_version |= buf[1]; hyn_ts_data->chip_ic_fw_version <<= 8; hyn_ts_data->chip_ic_fw_version |= buf[0]; hyn_ts_data->chip_ic_checksum = buf[7]; hyn_ts_data->chip_ic_checksum <<= 8; hyn_ts_data->chip_ic_checksum |= buf[6]; hyn_ts_data->chip_ic_checksum <<= 8; hyn_ts_data->chip_ic_checksum |= buf[5]; hyn_ts_data->chip_ic_checksum <<= 8; hyn_ts_data->chip_ic_checksum |= buf[4]; HYN_INFO("chip_ic_fw_version:0x%x, chip_ic_checksum:0x%x\r\n", hyn_ts_data->chip_ic_fw_version, hyn_ts_data->chip_ic_checksum); if(hyn_ts_data->chip_ic_fw_version==0xA5A5A5A5) { HYN_ERROR(" the chip ic don't have firmware. \n"); return -1; } buf[0] = 0xD0; buf[1] = 0x47; ret = cst3xx_i2c_read_register(client, buf, 1); if (ret < 0) return -1; hyn_ts_data->chip_ic_module_id=buf[0]; HYN_INFO("chip_ic_module_id:0x%x.\n",hyn_ts_data->chip_ic_module_id); buf[0] = 0xD1; buf[1] = 0x09; ret = cst3xx_i2c_write(client, buf, 2); if (ret < 0) return -1; mdelay(5); HYN_FUNC_EXIT(); return 0; } /* * */ int cst8xx_firmware_info(struct i2c_client *mclient) { int ret=-1; unsigned char reg_buf[2]; unsigned char buf[4]; unsigned short fwversion,chipversion; HYN_FUNC_ENTER(); msleep(100); reg_buf[0] = 0xA6; ret = hyn_i2c_read(hyn_ts_data->client,reg_buf,1,buf,2); if (ret < 0){ dev_err(&hyn_ts_data->client->dev, "f%s: i2c read error.\n",__func__); return -1; } fwversion = *(hyn_ts_data->p_hynitron_upgrade_firmware+0x3BFD+6); fwversion <<= 8; fwversion += *(hyn_ts_data->p_hynitron_upgrade_firmware+0x3BFC+6); HYN_INFO("\r\nhyn fwversion: %x\r\n",fwversion); chipversion = buf[1]; chipversion <<= 8; chipversion += buf[0]; hyn_ts_data->chip_ic_fw_version=chipversion; HYN_INFO("\r\nhyn chipversion: %x\r\n",chipversion); if(chipversion>fwversion) { update_fw_flag = 0; HYN_INFO("\r\nhyn update_fw_flag: %x\r\n",update_fw_flag); } HYN_FUNC_EXIT(); return ret; } static int hyn_find_fw_idx(u8 check_project_id) { int i = 0; HYN_FUNC_ENTER(); HYN_INFO("hyn_find_fw_idx check_project_id:%d,chip_ic_type :0x%x,chip_ic_project_id:0x%x,config_chip_type :0x%x.\r\n", check_project_id,hyn_ts_data->chip_ic_type,hyn_ts_data->chip_ic_project_id,hyn_ts_data->config_chip_type); if (0 != hyn_ts_data->config_chip_type ) { for (i=0; ichip_ic_project_id ==hynitron_fw_grp[i].project_id) &&(hyn_ts_data->chip_ic_type ==hynitron_fw_grp[i].chip_type)){ return i; } }else{ if(hyn_ts_data->config_chip_type ==hynitron_fw_grp[i].chip_type){ return i; } } } } HYN_FUNC_EXIT(); return -1; } /******************************************************* Function: get firmware version, ic type... Input: client: i2c client Output: success: 0 fail: -1 *******************************************************/ int hyn_firmware_info(struct i2c_client * client) { int ret=-1; unsigned char retry=0; HYN_FUNC_ENTER(); if(hyn_ts_data->config_chip_product_line==HYN_CHIP_PRODUCT_LINE_MUT_CAP) { //mutcap for(retry=0;retry<3;retry++){ ret=cst3xx_firmware_info(client); if(ret < 0){ HYN_INFO("cst3xx_firmware_info read fail,retry=%d.\r\n",retry); }else{ break; } } }else if(hyn_ts_data->config_chip_product_line==HYN_CHIP_PRODUCT_LINE_SEL_CAP){ //selfcap for(retry=0;retry<3;retry++){ ret=cst8xx_firmware_info(client); if(ret < 0){ HYN_INFO("cst8xx_firmware_info read fail,retry=%d.\r\n",retry); }else{ break; } } } HYN_FUNC_EXIT(); return ret; } int hyn_boot_update_fw(struct i2c_client * client) { int ret=-1; int proj_id=0; int check_proj_id=1; HYN_FUNC_ENTER(); if(hyn_ts_data->apk_upgrade_flag==0){ if(hyn_ts_data->chip_ic_checkcode ==0xffffffff){ HYN_ERROR("hyn ic have no firmware,update default firmware.\n"); check_proj_id=0; proj_id=hyn_find_fw_idx(check_proj_id); HYN_INFO("hyn_find_match chip type,fw_idx: proj_id:%d.\r\n",proj_id); if(proj_id<0){ HYN_ERROR("hyn not find config chip type firmware,please check config chip type or firmware.\n"); proj_id=hyn_find_fw_idx(0); if(proj_id>0){ hyn_ts_data->fw_name =hynitron_fw_grp[proj_id].name; hyn_ts_data->p_hynitron_upgrade_firmware =hynitron_fw_grp[proj_id].fw; hyn_ts_data->fw_length =hynitron_fw_grp[proj_id].fw_length; HYN_INFO("update default TP firmware data for apk update.(%s)!\n", hynitron_fw_grp[proj_id].name); }else{ HYN_INFO("please chekc hynitron_fw_grp fw config!\n"); return 0; } }else{ hyn_ts_data->fw_name =hynitron_fw_grp[proj_id].name; hyn_ts_data->p_hynitron_upgrade_firmware =hynitron_fw_grp[proj_id].fw; hyn_ts_data->fw_length =hynitron_fw_grp[proj_id].fw_length; HYN_INFO("find default TP firmware(%s)!\n", hynitron_fw_grp[proj_id].name); } }else{ check_proj_id=1; proj_id=hyn_find_fw_idx(check_proj_id); HYN_INFO("hyn_find_fw_idx: proj_id:%d.\r\n",proj_id); if(proj_id<0){ HYN_ERROR("not find matched TP firmware,please check chip type and chip project id. !\n"); proj_id=hyn_find_fw_idx(0); if(proj_id>0){ hyn_ts_data->fw_name =hynitron_fw_grp[proj_id].name; hyn_ts_data->p_hynitron_upgrade_firmware =hynitron_fw_grp[proj_id].fw; hyn_ts_data->fw_length =hynitron_fw_grp[proj_id].fw_length; HYN_INFO("update default TP firmware data for apk update.(%s)!\n", hynitron_fw_grp[proj_id].name); }else{ HYN_INFO("please chekc hynitron_fw_grp fw config!\n"); return 0; } }else{ HYN_INFO("find matched TP firmware(%s)!\n", hynitron_fw_grp[proj_id].name); hyn_ts_data->fw_name =hynitron_fw_grp[proj_id].name; hyn_ts_data->p_hynitron_upgrade_firmware =hynitron_fw_grp[proj_id].fw; hyn_ts_data->fw_length =hynitron_fw_grp[proj_id].fw_length; } } } if(!hyn_ts_data->p_hynitron_upgrade_firmware){ HYN_ERROR("hyn_ts_data->p_hynitron_upgrade_firmware is NULL .\n"); return 0; } #if HYN_ESDCHECK_EN hyn_esd_suspend(); #endif hyn_irq_disable(); hyn_ts_data->work_mode = HYN_WORK_MODE_UPDATE; //add work mode switch(hyn_ts_data->config_chip_series){ case HYN_CHIP_CST0XX: break; case HYN_CHIP_CST92XX: #if HYN_EN_AUTO_UPDATE_CST92XX ret =cst92xx_boot_update_fw(client); #endif break; case HYN_CHIP_CST6XX: #if (HYN_EN_AUTO_UPDATE_CST6xx) ret = cst6xx_boot_update_fw(client); #endif break; case HYN_CHIP_CST1XX: case HYN_CHIP_CST3XX: case HYN_CHIP_CST9XX: #if (HYN_EN_AUTO_UPDATE_CST1xx||HYN_EN_AUTO_UPDATE_CST3xx||HYN_EN_AUTO_UPDATE_CST9xx) ret = cst3xx_boot_update_fw(client); #endif break; case HYN_CHIP_CST3240: #if (HYN_EN_AUTO_UPDATE_CST3240) ret = cst3240_boot_update_fw(client); #endif break; case HYN_CHIP_CST1XXSE: case HYN_CHIP_CST2XXSE: case HYN_CHIP_CST3XXSE: #if (HYN_EN_AUTO_UPDATE_CST1xxSE||HYN_EN_AUTO_UPDATE_CST2xxSE||HYN_EN_AUTO_UPDATE_CST3xxSE) ret = cst3xxse_boot_update_fw(client); #endif break; case HYN_CHIP_CST7XX: case HYN_CHIP_CST8XX: #if HYN_EN_AUTO_UPDATE_CST78xx ret = cst8xx_boot_update_fw(client); #endif break; case HYN_CHIP_CST644K: #if HYN_EN_AUTO_UPDATE_CST644K ret = cst644k_boot_update_fw(client); #endif break; default : break; } hyn_irq_enable(); #if HYN_ESDCHECK_EN hyn_esd_resume(); #endif hyn_ts_data->work_mode = HYN_WORK_MODE_NORMAL; //add work mode HYN_FUNC_EXIT(); return ret; } static int cst0xx_bootloader_enter(struct i2c_client *client) { HYN_FUNC_ENTER(); HYN_FUNC_EXIT(); return 0; } static int cst2xx_bootloader_enter(struct i2c_client *client) { int ret=-1; u8 retry; unsigned char buf[4]; HYN_FUNC_ENTER(); for(retry=0;retry<5;retry++){ hyn_reset_proc(7+retry); if(hyn_ts_data->chip_ic_bootloader_addr!=client->addr){ client->addr=hyn_ts_data->chip_ic_bootloader_addr; } HYN_DEBUG(" bootloader mode client->addr:0x%x.\r\n",client->addr); buf[0] = 0xD1; buf[1] = 0x11; ret = cst3xx_i2c_write (hyn_ts_data->client, buf, 2); if (ret < 0) continue; mdelay (1); //wait enter download mode buf[0] = 0xD0; buf[1] = 0x01; ret = cst3xx_i2c_read_register (hyn_ts_data->client, buf, 1); if (ret < 0) continue; if (buf[0] == 0x55) { HYN_DEBUG ("[HYN]receive 0x55 success.\r\n"); break; } } buf[0] = 0xD1; buf[1] = 0x10; //enter writer register mode ret = cst3xx_i2c_write (hyn_ts_data->client, buf, 2); if (ret < 0) { HYN_DEBUG ("[HYN]Send cmd 0xD110 failed. \r\n"); return -1; } HYN_FUNC_EXIT(); return 0; } static int cst3xx_bootloader_enter(struct i2c_client *client) { int ret=-1; u8 retry; unsigned char buf[4]; HYN_FUNC_ENTER(); for(retry=0;retry<10;retry++){ hyn_reset_proc(7+retry); if(hyn_ts_data->chip_ic_bootloader_addr!=client->addr){ client->addr=hyn_ts_data->chip_ic_bootloader_addr; } HYN_DEBUG(" bootloader mode client->addr:0x%x.\r\n",client->addr); buf[0] = 0xA0; buf[1] = 0x01; buf[2] = 0xAA; //set cmd to enter program mode ret = cst3xx_i2c_write(client, buf, 3); if (ret < 0) continue; mdelay(2); buf[0] = 0xA0; buf[1] = 0x02; //check whether into program mode ret = cst3xx_i2c_read_register(client, buf, 1); if (ret < 0) continue; if(hyn_ts_data->config_chip_series==HYN_CHIP_CST3XX){ if (buf[0] == 0xAC) break; }else{ if (buf[0] == 0x55) break; } } if(hyn_ts_data->config_chip_series==HYN_CHIP_CST3XX){ if (buf[0] != 0xAC) { HYN_ERROR("cst3xx_bootloader_enter error,please check VCC/RST/SDA/SCL and chip type.\r\n"); return -1; }else{ HYN_DEBUG("cst3xx_bootloader_enter detect success,buf[0]=%d.\n", buf[0]); } }else{ if (buf[0] != 0x55) { HYN_ERROR("cst1xx_bootloader_enter error,please check VCC/RST/SDA/SCL and chip type.\r\n"); return -1; }else{ HYN_DEBUG("cst1xx_bootloader_enter detect success,buf[0]=%d.\n", buf[0]); } } HYN_FUNC_EXIT(); return 0; } static int cst3240_bootloader_enter(struct i2c_client * client) { int ret=-1; u8 retry; unsigned char buf[4]; HYN_FUNC_ENTER(); for(retry=0;retry<10;retry++){ hyn_reset_proc(7+retry); if(hyn_ts_data->chip_ic_bootloader_addr!=client->addr){ client->addr=hyn_ts_data->chip_ic_bootloader_addr; } HYN_DEBUG(" bootloader mode client->addr:0x%x.\r\n",client->addr); buf[0] = 0xA0; buf[1] = 0x01; buf[2] = 0xAA; //set cmd to enter program mode ret = cst3xx_i2c_write(client, buf, 3); if (ret < 0) continue; mdelay(2); buf[0] = 0xA0; buf[1] = 0x02; //check whether into program mode ret = cst3xx_i2c_read_register(client, buf, 1); if (ret < 0) continue; if (buf[0] == 0x55) break; } if (buf[0] != 0x55) { HYN_ERROR("cst32xx_bootloader_enter error,please check VCC/RST/SDA/SCL and chip type.\r\n"); return -1; }else{ HYN_DEBUG("cst32xx_bootloader_enter detect success,buf[0]=%d.\n", buf[0]); } mdelay(2); buf[0] = 0xA0; buf[1] = 0x03; //check whether into program mode ret = cst3xx_i2c_read_register(client, buf, 3); if (ret < 0) return -1; if (buf[0] != 0xA8) { HYN_DEBUG("cst32xx_bootloader_enter detect 0xA8,buf[0]=%d.\n", buf[0]); return -1; } mdelay(2); buf[0] = 0xA0; buf[1] = 0x01; buf[2] = 0x00; ret = cst3xx_i2c_write(client, buf, 3); if (ret < 0) return -1; HYN_FUNC_EXIT(); return 0; } static int cst92xx_bootloader_enter(struct i2c_client *client) { int ret=-1; u8 retry; unsigned char buf[4]; HYN_FUNC_ENTER(); for(retry=0;retry<10;retry++){ hyn_reset_proc(7+retry); if(hyn_ts_data->chip_ic_bootloader_addr!=client->addr){ client->addr=hyn_ts_data->chip_ic_bootloader_addr; } HYN_DEBUG(" bootloader mode client->addr:0x%x.\r\n",client->addr); buf[0] = 0xA0; buf[1] = 0x01; buf[2] = 0xAA; //set cmd to enter program mode ret = cst3xx_i2c_write(client, buf, 3); if (ret < 0) continue; mdelay(2); buf[0] = 0xA0; buf[1] = 0x02; //check whether into program mode ret = cst3xx_i2c_read_register(client, buf, 2); if (ret < 0) continue; if ((buf[0] == 0x55)&&(buf[1] == 0xB0)) break; } if (retry == 10) { HYN_ERROR("cst92xx_bootloader_enter error,please check VCC/RST/SDA/SCL and chip type.\r\n"); return -1; }else{ HYN_DEBUG("cst92xx_bootloader_enter detect success,buf[0]=0x%x,buf[1]=0x%x.\n", buf[0], buf[1]); } HYN_FUNC_EXIT(); return 0; } static int cst6xx_bootloader_enter(struct i2c_client *client) { int ret=-1; u8 retry; unsigned char buf[4]; HYN_FUNC_ENTER(); for(retry=0;retry<10;retry++){ hyn_reset_proc(7+retry); if(hyn_ts_data->chip_ic_bootloader_addr!=client->addr){ client->addr=hyn_ts_data->chip_ic_bootloader_addr; } HYN_DEBUG(" bootloader mode client->addr:0x%x.\r\n",client->addr); buf[0] = 0xA0; buf[1] = 0x01; buf[2] = 0xAB; //set cmd to enter program mode ret = cst3xx_i2c_write(client, buf, 3); if (ret < 0) continue; mdelay(2); buf[0] = 0xA0; buf[1] = 0x02; //check whether into program mode ret = cst3xx_i2c_read_register(client, buf, 1); if (ret < 0) continue; if (buf[0] == 0x55) break; } if (buf[0] != 0x55) { HYN_ERROR("cst6xx_bootloader_enter error,please check VCC/RST/SDA/SCL and chip type.\r\n"); ret = -1; }else{ HYN_DEBUG("cst6xx_bootloader_enter detect success,buf[0]=0x%x.\n", buf[0]); ret = 0; } HYN_FUNC_EXIT(); return ret; } static int cst3xxse_bootloader_enter(struct i2c_client *client) { int ret=-1; u8 retry; unsigned char buf[4]; HYN_FUNC_ENTER(); for(retry=0;retry<5;retry++){ hyn_reset_proc(7+retry); if(hyn_ts_data->chip_ic_bootloader_addr!=client->addr){ client->addr=hyn_ts_data->chip_ic_bootloader_addr; } HYN_DEBUG(" bootloader mode client->addr:0x%x.\r\n",client->addr); buf[0] = 0xA0; buf[1] = 0x01; buf[2] = 0xAA; //set cmd to enter program mode ret = cst3xx_i2c_write(client, buf, 3); if (ret < 0) continue; mdelay(5); buf[0] = 0xA0; buf[1] = 0x03; //check whether into program mode ret = cst3xx_i2c_read_register(client, buf, 1); if (ret < 0) continue; if (buf[0] == 0x55) break; } if (buf[0] != 0x55){ HYN_ERROR("cst3xx_bootloader_enter error,please check VCC/RST/SDA/SCL and chip type.\r\n"); return -1; }else{ HYN_DEBUG("cst3xx_bootloader_enter detect success,buf[0]=%d.\n", buf[0]); } HYN_FUNC_EXIT(); return 0; } static int cst8xx_bootloader_enter(struct i2c_client *client) { char retryCnt = 10; HYN_FUNC_ENTER(); hyn_reset_proc(1); mdelay(5); if(hyn_ts_data->chip_ic_bootloader_addr!=client->addr){ client->addr=hyn_ts_data->chip_ic_bootloader_addr; } HYN_DEBUG(" bootloader mode client->addr:0x%x.\r\n",client->addr); while(retryCnt--){ u8 cmd[3]; cmd[0] = 0xAA; if (-1 == hyn_i2c_write_bytes(0xA001,cmd,1,REG_LEN_2B)){ // enter program mode mdelay(2); // 4ms continue; } if (-1 == hyn_i2c_read_bytes(0xA003,cmd,1,REG_LEN_2B)) { // read flag mdelay(2); // 4ms continue; }else{ if (cmd[0] != 0x55){ mdelay(2); // 4ms continue; }else{ HYN_DEBUG("cst8xx_bootloader_enter detect success,cmd[0]=%d.\n", cmd[0]); return 0; } } } HYN_FUNC_EXIT(); return -1; } //201 static int cst644K_bootloader_enter(struct i2c_client *client) { int ret=-1; u8 retry; unsigned char buf[4]; HYN_FUNC_ENTER(); for(retry=0;retry<10;retry++){ hyn_reset_proc(7+retry); if(hyn_ts_data->chip_ic_bootloader_addr!=client->addr){ client->addr=hyn_ts_data->chip_ic_bootloader_addr; } HYN_DEBUG(" bootloader mode client->addr:0x%x.\r\n",client->addr); buf[0] = 0xA0; buf[1] = 0x01; buf[2] = 0xAA; //set cmd to enter program mode ret = cst3xx_i2c_write(client, buf, 3); if (ret < 0) continue; mdelay(2); buf[0] = 0xA0; buf[1] = 0x02; //check whether into program mode ret = cst3xx_i2c_read_register(client, buf, 1); if (ret < 0) continue; if (buf[0] == 0x55) break; } if (buf[0] != 0x55) { HYN_ERROR("cst644K_bootloader_enter error,please check VCC/RST/SDA/SCL and chip type.\r\n"); return -1; }else{ HYN_DEBUG("cst644K_bootloader_enter detect success,buf[0]=0x%x.\n", buf[0]); } HYN_FUNC_EXIT(); return 0; } int hyn_detect_bootloader(struct i2c_client *client) { int ret =-1; switch(hyn_ts_data->config_chip_series){ case HYN_CHIP_CST0XX: ret=cst0xx_bootloader_enter(client); break; case HYN_CHIP_CST2XX: ret=cst2xx_bootloader_enter(client); break; case HYN_CHIP_CST6XX: ret=cst6xx_bootloader_enter(client); break; case HYN_CHIP_CST1XX: case HYN_CHIP_CST3XX: ret=cst3xx_bootloader_enter(client); break; case HYN_CHIP_CST3240: ret=cst3240_bootloader_enter(client); break; case HYN_CHIP_CST92XX: ret=cst92xx_bootloader_enter(client); break; case HYN_CHIP_CST1XXSE: case HYN_CHIP_CST2XXSE: case HYN_CHIP_CST3XXSE: ret=cst3xxse_bootloader_enter(client); break; case HYN_CHIP_CST7XX: case HYN_CHIP_CST8XX: ret=cst8xx_bootloader_enter(client); break; case HYN_CHIP_CST644K: ret=cst644K_bootloader_enter(client); break; default : break; } if(hyn_ts_data->chip_ic_main_addr!=client->addr){ client->addr=hyn_ts_data->chip_ic_main_addr; } HYN_DEBUG("exit bootloader mode,client->addr:0x%x.\r\n",client->addr); hyn_reset_proc(40); HYN_FUNC_EXIT(); return ret; }