OSHW-DEIMOS/SOFTWARE/A64-TERES/linux-a64/drivers/input/touchscreen/gt818/gt818_update.c
Dimitar Gamishev f9b0e7a283 linux
2017-10-13 14:07:04 +03:00

1159 lines
29 KiB
C
Executable File
Raw Permalink Blame History

/* drivers/input/touchscreen/gt816_818_update.c
*
* 2010 - 2012 Goodix Technology.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be a reference
* to you, when you are integrating the GOODiX's CTP IC into your system,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* Version:1.2
* V1.0:2012/05/01,create file.
* V1.2:2012/06/08,update some statement.
*
*/
#include <linux/kthread.h>
#include "gt818.h"
//-----------------------------------------------
//Do not change the order |
#define HEADER_UPDATE_DATA NULL // |
#if GUP_USE_HEADER_FILE // |
#include "gt816_818_firmware.h" // |
#endif // |
//-----------------------------------------------
//#ifdef GTP_AUTO_UPDATE
#define BIT_NVRAM_STROE 0
#define BIT_NVRAM_RECALL 1
#define BIT_NVRAM_LOCK 2
#define REG_NVRCS 0x1201
#define READ_FW_MSG_ADDR 0x0F7C
#define READ_MSK_VER_ADDR 0xC009
#define FW_HEAD_LENGTH 30
#define FILE_HEAD_LENGTH 100
#define IGNORE_LENGTH 100
#define FW_MSG_LENGTH 7
#define UPDATE_DATA_LENGTH 5000
#define TPD_CHIP_VERSION_C_FIRMWARE_BASE 0x5A
#define TPD_CHIP_VERSION_D1_FIRMWARE_BASE 0x7A
#define TPD_CHIP_VERSION_E_FIRMWARE_BASE 0x9A
#define TPD_CHIP_VERSION_D2_FIRMWARE_BASE 0xBA
#define MAGIC_NUMBER_1 0x4D454449
#define MAGIC_NUMBER_2 0x4154454B
enum
{
TPD_GT818_VERSION_B,
TPD_GT818_VERSION_C,
TPD_GT818_VERSION_D1,
TPD_GT818_VERSION_E,
TPD_GT818_VERSION_D2
};
#define fail 0
#define success 1
#define false 0
#define true 1
u16 show_len;
u16 total_len;
static struct i2c_client *guitar_client = NULL;
//extern s32 gtp_i2c_read(struct i2c_client *client, u8 *buf, s32 len);
//extern s32 gtp_i2c_write(struct i2c_client *client,u8 *data,s32 len);
//extern s32 gtp_i2c_end_cmd(struct i2c_client *client);
//extern void gtp_reset_guitar(s32 ms);
//extern s32 gtp_send_cfg(struct i2c_client *client);
//extern s32 gtp_read_version(struct i2c_client *client, u16 *version);
//extern void gtp_set_int_value(int status);
#pragma pack(1)
typedef struct
{
s32 magic_number_1;
s32 magic_number_2;
u16 version;
u16 length;
u16 checksum;
}st_check_msg;
#pragma pack()
typedef struct
{
u8 st_addr[2];
u16 lenth;
}st_fw_head;
typedef struct
{
u16 version;
u8 fw_flag;
loff_t gt_loc;
struct file *file;
st_check_msg fw_msg;
mm_segment_t old_fs;
}st_update_msg;
static st_update_msg update_msg;
//******************************************************************************
static u8 gup_get_ic_msg(struct i2c_client *client, u16 addr, u8* msg, s32 len)
{
s32 i = 0;
msg[0] = (addr >> 8) & 0xff;
msg[1] = addr & 0xff;
for (i = 0; i < 5; i++)
{
if (gtp_i2c_read(client, msg, GTP_ADDR_LENGTH + len) > 0)
{
break;
}
}
gtp_i2c_end_cmd(client);
if (i >= 5)
{
GTP_ERROR("Read data from 0x%02x%02x failed!", msg[0], msg[1]);
return fail;
}
return success;
}
#if 0
static u8 gup_clear_mix_flag(struct i2c_client *client)
{
s32 i = 0;
u8 buf[3];
buf[0] = 0x14;
buf[1] = 0x00;
buf[2] = 0x8C;
for (i = 0; i < 5; i++)
{
if (gtp_i2c_write(client, buf, 3) > 0)
{
break;
}
}
gtp_i2c_end_cmd(client);
if (i >= 5)
{
GTP_DEBUG("Clear mix flag failed!");
return fail;
}
return success;
}
#endif
#if 0
static u8 gup_get_ic_fw_msg(struct i2c_client *client)
{
s32 ret = 0;
s32 i = 0;
u8 buf[32];
if (fail == gup_clear_mix_flag(client))
{
return fail;
}
//Get the mask version in rom of IC
if (fail == gup_get_ic_msg(client, READ_MSK_VER_ADDR, buf, 4))
{
GTP_ERROR("Read mask version failed!");
return fail;
}
memcpy(update_msg.ic_fw_msg.msk_ver, &buf[GTP_ADDR_LENGTH], 4);
GTP_DEBUG("IC The mask version in rom is %c%c%c%c.",
update_msg.ic_fw_msg.msk_ver[0],update_msg.ic_fw_msg.msk_ver[1],
update_msg.ic_fw_msg.msk_ver[2],update_msg.ic_fw_msg.msk_ver[3]);
//Get the firmware msg in IC, include firmware version and checksum flag
for (i = 0; i < 2; i++)
{
if (fail == gup_get_ic_msg(client, READ_FW_MSG_ADDR, buf, 4))
{
GTP_DEBUG("Get firmware msg in IC error.");
return fail;
}
update_msg.force_update = buf[GTP_ADDR_LENGTH];
if (i == 0 && update_msg.force_update == 0xAA)
{
GTP_INFO("The check sum in ic is error.");
GTP_INFO("IC will be reset.");
GTP_INFO("If the check sum is still error, ");
GTP_INFO("The IC will be updated by force.");
gtp_reset_guitar(10);
continue;
//msleep(100);
}
break;
}
//ic_fw_msg.type = buf[GTP_ADDR_LENGTH + 1];
update_msg.ic_fw_msg.version = buf[GTP_ADDR_LENGTH + 2] << 8 | buf[GTP_ADDR_LENGTH + 3];
GTP_DEBUG("IC VID:0x%x", (int)update_msg.ic_fw_msg.version);
GTP_DEBUG("IC force update:%x", update_msg.force_update);
//Cuts the frequency
buf[0] = 0x15;
buf[1] = 0x22;
buf[2] = 0x18;
ret = gtp_i2c_write(client, buf, 3);
if (ret <= 0)
{
return fail;
}
gtp_i2c_end_cmd(client);
//Get the pid at 0x4011 in nvram
if (fail == gup_get_ic_msg(client, 0x4011, buf, 1))
{
GTP_ERROR("Read pid failed!");
return fail;
}
update_msg.ic_fw_msg.type = buf[GTP_ADDR_LENGTH];
GTP_DEBUG("IC PID:%x", update_msg.ic_fw_msg.type);
return success;
}
#endif
/*
* Steps of reset guitar
*1. INT<4E><54><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͣ<EFBFBD><CDA3><EFBFBD>ʱ5ms
*2. RESET<45><54><EFBFBD><EFBFBD><EFBFBD><EFBFBD>100ms<6D><73>ת<EFBFBD><D7AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>̬
*3. I2CѰַGUITAR
*4. <20><>ʱ100ms<6D><73>ȡ0xff(3<><33>4<EFBFBD><34>ѯ80<38>Σ<EFBFBD>ֱ<EFBFBD><D6B1><EFBFBD>ɹ<EFBFBD>)
*5. Oxff<66><66><EFBFBD><EFBFBD>0x55<35>򷵻سɹ<D8B3><C9B9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʧ<EFBFBD><CAA7>
*/
s32 gup_enter_update_mode(struct i2c_client *client)
{
int ret = 1;
u8 retry;
unsigned char inbuf[3] = {0,0xff,0};
// step 1
// GTP_GPIO_OUTPUT(GTP_INT_PORT, 0);
gtp_set_int_value(0);
msleep(5);
//step 2
gtp_reset_guitar(100);
for(retry=0;retry < 20; retry++)
{
//step 3
ret = gtp_i2c_write(client, inbuf, 2); //Test I2C connection.
if (ret > 0)
{
GTP_DEBUG("<Set update mode>I2C is OK!");
//step 4
msleep(100);
ret = gtp_i2c_read(client, inbuf, 3);
if (ret > 0)
{
GTP_DEBUG("The value of 0x00ff is 0x%02x", inbuf[2]);
//step 5
if(inbuf[2] == 0x55)
{
return success;
}
}
}
msleep(40);
}
GTP_ERROR(KERN_INFO"Detect address %0X", client->addr);
return fail;
}
void gup_leave_update_mode(void)
{
GTP_GPIO_AS_INT(GTP_INT_PORT);
}
/*******************************************************
Function:
Check chip version function.
Input:
sw_ver:vendor id.
Output:
Executive outcomes.
*********************************************************/
static s16 gup_check_version(u16 sw_ver)
{
if ((sw_ver&0xff) < TPD_CHIP_VERSION_C_FIRMWARE_BASE )
{
return TPD_GT818_VERSION_B;
}
else if ((sw_ver&0xff) < TPD_CHIP_VERSION_D1_FIRMWARE_BASE )
{
return TPD_GT818_VERSION_C;
}
else if((sw_ver&0xff) < TPD_CHIP_VERSION_E_FIRMWARE_BASE)
{
return TPD_GT818_VERSION_D1;
}
else if((sw_ver&0xff) < TPD_CHIP_VERSION_D2_FIRMWARE_BASE)
{
return TPD_GT818_VERSION_E;
}
else
{
return TPD_GT818_VERSION_D2;
}
}
static s32 gup_comfirm_version(struct i2c_client *client)
{
s32 i = 0;
s32 count = 0;
u16 version;
u16 version_tmp;
gtp_read_version(client, &version);
gtp_read_version(client, &version_tmp);
for ( i = 0; i < 15; i++)
{
if (version != version_tmp)
{
count = 0;
}
else
{
count ++;
if (count > 10)
{
update_msg.version = version;
return success;
}
}
version = version_tmp;
gtp_read_version(client, &version_tmp);
}
return fail;
}
static u8 gup_load_update_file(struct i2c_client *client, st_fw_head* fw_head, u8* data, u8* path)
{
//u8 mask_num = 0;
u16 checksum = 0;
int ret = 0;
int i = 0;
//u8 buf[FW_HEAD_LENGTH];
if (path)
{
GTP_DEBUG("File path:%s, %d", path, strlen(path));
update_msg.file = filp_open(path, O_RDONLY, 0644);
if (IS_ERR(update_msg.file))
{
GTP_ERROR("Open update file(%s) error!", path);
return fail;
}
}
else
{
//Begin to search update file
for (i = 0; i < SEARCH_FILE_TIMES; i++)
{
update_msg.file = filp_open(UPDATE_FILE_PATH_1, O_RDWR, 0666);
if (IS_ERR(update_msg.file))
{
update_msg.file = filp_open(UPDATE_FILE_PATH_2, O_RDWR, 0666);//O_RDWR
if (IS_ERR(update_msg.file))
{
GTP_DEBUG("%3d:Searching file...", i);
msleep(3000);
continue;
}
else
{
break;
}
}
else
{
break;
}
}
if (i >= SEARCH_FILE_TIMES)
{
GTP_ERROR("Can't find update file.");
return fail;
}
GTP_DEBUG("Find the update file.");
}
update_msg.old_fs = get_fs();
set_fs(KERNEL_DS);
//Read firmware head message in file
ret = update_msg.file->f_op->read(update_msg.file, (char*)&update_msg.fw_msg,
sizeof(st_check_msg), &update_msg.file->f_pos);
if (ret < 0)
{
GTP_ERROR("Read firmware body error.");
goto load_failed;
}
//1. Compare magic numbers
if ((update_msg.fw_msg.magic_number_1 != MAGIC_NUMBER_1)
|| (update_msg.fw_msg.magic_number_2 != MAGIC_NUMBER_2))
{
GTP_ERROR("Magic number not match, Exit.");
GTP_INFO("[FW]magic number:0x%08x&0x%08x", update_msg.fw_msg.magic_number_1, update_msg.fw_msg.magic_number_2);
GTP_INFO("[DV]magic number:0x%08x&0x%08x", MAGIC_NUMBER_1, MAGIC_NUMBER_2);
goto load_failed;
}
//2. Compare version
if (update_msg.version >= update_msg.fw_msg.version)
{
GTP_ERROR("The firmware version is lower than current.");
goto load_failed;
}
//3. Check the versions
if(gup_check_version(update_msg.version) != gup_check_version(update_msg.fw_msg.version))
{
GTP_ERROR("Chip version not match,Exit.");
goto load_failed;
}
//Read firmware body message in file
ret = update_msg.file->f_op->read(update_msg.file, (char*)data, update_msg.fw_msg.length,
&update_msg.file->f_pos);
if (ret < 0)
{
GTP_ERROR("Read firmware head error.");
goto load_failed;
}
//.4 Check check sum
for (i = 0; i < update_msg.fw_msg.length; i++)
{
checksum += data[i];
}
if (checksum != update_msg.fw_msg.checksum)
{
GTP_ERROR("Checksum not match,Exit.");
goto load_failed;
}
GTP_DEBUG("Load data successfully!");
fw_head->lenth = update_msg.fw_msg.length;
fw_head->st_addr[0] = 0x41;
fw_head->st_addr[1] = 0x00;
set_fs(update_msg.old_fs);
filp_close(update_msg.file, NULL);
return success;
load_failed:
set_fs(update_msg.old_fs);
filp_close(update_msg.file, NULL);
return fail;
}
static u8 gup_load_update_header(struct i2c_client *client, st_fw_head* fw_head, u8** data)
{
u16 checksum = 0;
// s32 ret = -1;
s32 i = 0;
u8* pos = NULL;
pos = HEADER_UPDATE_DATA;
//Read firmware head message in file
memcpy((u8*)&update_msg.fw_msg, pos, sizeof(st_check_msg));
//1. Compare magic numbers
if ((update_msg.fw_msg.magic_number_1 != MAGIC_NUMBER_1)
|| (update_msg.fw_msg.magic_number_2 != MAGIC_NUMBER_2))
{
GTP_ERROR("Magic number not match, Exit.");
GTP_INFO("[FW]magic number:0x%08x&0x%08x", update_msg.fw_msg.magic_number_1, update_msg.fw_msg.magic_number_2);
GTP_INFO("[DV]magic number:0x%08x&0x%08x", MAGIC_NUMBER_1, MAGIC_NUMBER_2);
goto load_failed;
}
GTP_INFO("Magic number match.");
//2. Compare version
if (update_msg.version >= update_msg.fw_msg.version)
{
GTP_INFO("Current version:%04x.", update_msg.version);
GTP_INFO("Firmware version:%04x.", update_msg.fw_msg.version);
GTP_ERROR("The firmware version is lower than current.");
goto load_failed;
}
GTP_INFO("Version lower.");
//3. Check the versions
if(gup_check_version(update_msg.version) != gup_check_version(update_msg.fw_msg.version))
{
GTP_ERROR("Chip version not match,Exit.");
goto load_failed;
}
GTP_INFO("Version match.");
//Read firmware body message in file
*data = pos + sizeof(st_check_msg);
//.4 Check check sum
for (i = 0; i < update_msg.fw_msg.length; i++)
{
checksum += (*data)[i];
}
if (checksum != update_msg.fw_msg.checksum)
{
GTP_ERROR("Checksum not match,Exit.");
goto load_failed;
}
GTP_INFO("Check sum match.");
GTP_DEBUG("Load data successfully!");
fw_head->lenth = update_msg.fw_msg.length;
fw_head->st_addr[0] = 0x41;
fw_head->st_addr[1] = 0x00;
return success;
load_failed:
return fail;
}
static u8 gup_nvram_store(struct i2c_client *client)
{
int ret;
int i;
u8 inbuf[3] = {REG_NVRCS >> 8, REG_NVRCS & 0xff, 0x18};
ret = gtp_i2c_read(client, inbuf, 3);
if ( ret < 0 )
{
return fail;
}
if ((inbuf[2] & BIT_NVRAM_LOCK ) == BIT_NVRAM_LOCK)
{
return fail;
}
inbuf[2] = 0x18;
inbuf[2] |= (1<<BIT_NVRAM_STROE); //store command
for ( i = 0 ; i < 300 ; i++ )
{
ret = gtp_i2c_write(client, inbuf, 3);
if ( ret > 0 )
return success;
}
return fail;
}
static u8 gup_nvram_recall(struct i2c_client *client)
{
int ret;
u8 inbuf[3] = {REG_NVRCS >> 8, REG_NVRCS & 0xff, 0};
ret = gtp_i2c_read(client, inbuf, 3);
if ( ret < 0 )
{
return fail;
}
if ( ( inbuf[2]&BIT_NVRAM_LOCK) == BIT_NVRAM_LOCK )
{
return fail;
}
inbuf[2] = ( 1 << BIT_NVRAM_RECALL ); //recall command
ret = gtp_i2c_write(client , inbuf, 3);
if (ret <= 0)
{
return fail;
}
return success;
}
static u8 gup_update_nvram(struct i2c_client *client, st_fw_head* fw_head, u8 *nvram)
{
int length = 0;
int ret = 0;
int write_bytes = 0;
int retry = 0;
int i = 0;
int comp = 0;
u16 st_addr = 0;
u8 w_buf[PACK_SIZE + GTP_ADDR_LENGTH];
u8 r_buf[PACK_SIZE + GTP_ADDR_LENGTH];
if (fw_head->lenth > PACK_SIZE)
{
write_bytes = PACK_SIZE;
}
else
{
write_bytes = fw_head->lenth;
}
// gup_clear_mix_flag(ts);
st_addr = (fw_head->st_addr[0] << 8) | (fw_head->st_addr[1]&0xff);
memcpy(&w_buf[2], &nvram[length], write_bytes);
GTP_DEBUG("Total length:%d", (int)fw_head->lenth);
while(length < fw_head->lenth)
{
w_buf[0] = st_addr >> 8;
w_buf[1] = st_addr & 0xff;
GTP_DEBUG("Write address:0x%02x%02x\tlength:%d", w_buf[0], w_buf[1], write_bytes);
ret = gtp_i2c_write(client, w_buf, GTP_ADDR_LENGTH + write_bytes);
if (ret <= 0)
{
if (retry++ > 10)
{
GTP_DEBUG("Write the same address 10 times.Give up!");
return fail;
}
GTP_DEBUG("Write error![gup_update_nvram]");
continue;
}
else
{
// GTP_DEBUG("w_buf:");
// GTP_DEBUG_ARRAY(w_buf, GTP_ADDR_LENGTH + write_bytes);
/* r_buf[0] = 0x14;
r_buf[1] = 0x00;
r_buf[2] = 0x80;
gtp_i2c_write(ts->client, r_buf, 3);
r_buf[0] = 0x14;
r_buf[1] = 0x00;
gtp_i2c_read(ts->client, r_buf, 3);
GTP_DEBUG("I2CCS:0x%x", r_buf[2]);//*/
r_buf[0] = w_buf[0];
r_buf[1] = w_buf[1];
for (i = 0; i < 10; i++)
{
ret = gtp_i2c_read(client, r_buf, GTP_ADDR_LENGTH + write_bytes);
if (ret <= 0)
{
continue;
}
break;
}
if (i >= 10)
{
GTP_DEBUG("Read error! Can't check the nvram data.");
return fail;
}
// GTP_DEBUG("r_buf:");
// GTP_DEBUG_ARRAY(r_buf, GTP_ADDR_LENGTH + write_bytes);
#if 0
if (fail == gup_nvram_store(ts))
{
GTP_DEBUG("Store nvram failed.");
//continue;
}
return fail;
#endif
if (memcmp(r_buf, w_buf, GTP_ADDR_LENGTH + write_bytes))
{
if (comp ++ > 10)
{
GTP_DEBUG("Compare error!");
return fail;
}
GTP_DEBUG("Updating nvram: Not equal!");
GTP_DEBUG("r_buf:");
GTP_DEBUG_ARRAY(r_buf, GTP_ADDR_LENGTH + write_bytes);
GTP_DEBUG("w_buf:");
// GTP_DEBUG_ARRAY(w_buf, GTP_ADDR_LENGTH + write_bytes);
continue;
//return fail;
}
}
comp = 0;
retry = 0;
length += PACK_SIZE;
st_addr += PACK_SIZE;
if ((length + PACK_SIZE) > fw_head->lenth)
{
write_bytes = fw_head->lenth - length;
}
memcpy(&w_buf[2], &nvram[length], write_bytes);
}
return success;
}
static u8 gup_update_firmware(struct i2c_client *client, st_fw_head* fw_head, u8 *nvram)
{
s32 retry;
// s32 i, j;
// s32 ret;
// s32 right_count = 0;
u32 status = 0;
// u16 check_sum = 0;
// u8 buf[150];
// u8 tmp[150];
#if 0
//Cuts the frequency
buf[0] = 0x15;
buf[1] = 0x22;
buf[2] = 0x18;
ret = gtp_i2c_write(client, buf, 3);
if (ret <= 0)
{
return fail;
}
gup_get_ic_msg(client, 0x1522, buf, 1);
GTP_DEBUG("IC OSC_CAL:0x%02x.", buf[2]);
gup_clear_mix_flag(client);
#endif
for (retry = 0; retry < 10; retry++)
{
#if 0
if (!(status & 0x01))
{
tmp[0] = 0x4f;
tmp[1] = 0x70;
gtp_i2c_read(client, tmp, 130);
for (i = 0; i < 50; i++)
{
buf[0] = 0x4f;
buf[1] = 0x70;
ret = gtp_i2c_read(client, buf, 130);
if (ret <= 0)
{
continue;
}
else
{
GTP_DEBUG("Read solidified config successfully!");
ret = !memcmp(tmp, buf, 130);
memcpy(tmp, buf, 130);
if (true == ret)
{
if (right_count++ < 3)
{
continue;
}
else
{
for (j = 0; j < 128; j++)
{
check_sum += buf[j + 2];
}
GTP_DEBUG("check sum of solidified config is %04x", check_sum);
status |= 0x01;
break;
}
}
else
{
right_count = 0;
}
if (i >= 40)
{
GTP_DEBUG("Compare solidified config failed!");
return fail;
}
}
}
}
#endif
//Write the 2nd part (nvram)
if (!(status & 0x02))
{
if (fail == gup_update_nvram(client, fw_head, nvram))
{
continue;
}
else
{
GTP_DEBUG("Update nvram successfully!");
status |= 0x02;
msleep(1);
break;
}
}
#if 0
//Write the 3rd part (check sum)
if (1)
{
u32 sum = 0;
sum |= fw_head->chk_sum[0] << 16;
sum |= fw_head->chk_sum[1] << 8;
sum |= fw_head->chk_sum[2];
sum += check_sum;
fw_head->chk_sum[0] = sum >> 16;
fw_head->chk_sum[1] = sum >> 8;
fw_head->chk_sum[2] = sum;
GTP_DEBUG("FILE chksum after addition:0x%02x%02x%02x", fw_head->chk_sum[0],
fw_head->chk_sum[1], fw_head->chk_sum[2]);
buf[0] = 0x4f;
buf[1] = 0xf3;
memcpy(&buf[2], fw_head->chk_sum, sizeof(fw_head->chk_sum));
ret = gtp_i2c_write(client, buf, 5);
if (ret <= 0)
{
continue;
}
else
{
GTP_DEBUG("Update check sum successfully!");
break;
}
}
#endif
}
if (retry >= 10)
{
return fail;
}
else
{
return success;
#if 0
for (retry = 0; retry < 10; retry++)
{
buf[0] = 0x00;
buf[1] = 0xff;
buf[2] = 0x44;
ret = gtp_i2c_write(client, buf, 3);
if (ret > 0)
{
break;
}
}
if (retry >= 10)
{
GTP_DEBUG("Write address at 0x00ff error!\n");
return fail;
}
msleep(10);
}
for (retry = 0; retry < 30; retry++)
{
msleep(1);
if (fail == gup_get_ic_msg(client, 0x00ff, buf, 1))
{
GTP_DEBUG("Read address at 0x00ff error!\t retry:%d\n", retry);
continue;
}
if (0xcc == buf[GTP_ADDR_LENGTH])
{
return success;
}
else
{
GTP_DEBUG("The value of 0x00ff: 0x%02x!\t retry:%d\n", buf[GTP_ADDR_LENGTH], retry);
continue;
}
#endif
}
GTP_DEBUG("The value of 0x00ff error.\n");
return fail;
}
s32 gup_update_proc(void *dir)
{
s32 ret;
u32 retry = 100;
u32 i = 0;
struct goodix_ts_data* ts = NULL;
u8* data = NULL;
u8* ic_nvram = NULL;
st_fw_head fw_head;
u8 buf[32];
show_len = 20;
total_len = 100;
ts = i2c_get_clientdata(guitar_client);
if (!(HEADER_UPDATE_DATA != NULL && dir == NULL))
{
data = kzalloc(UPDATE_DATA_LENGTH, GFP_KERNEL);
if (NULL == data)
{
GTP_ERROR("data failed apply for memory.");
return fail;
}
}
ic_nvram = kzalloc(UPDATE_DATA_LENGTH, GFP_KERNEL);
if (NULL == ic_nvram)
{
GTP_ERROR("ic_nvram failed apply for memory.");
goto app_mem_failed;
}
GTP_DEBUG("Apply for memory successfully.memory size: %d.", UPDATE_DATA_LENGTH);
if (dir != NULL)
{
// gup_get_ic_fw_msg(guitar_client);
// gtp_reset_guitar(10);
}
else
{
msleep(1000);
}
GTP_DEBUG("Updating...");
if (!(HEADER_UPDATE_DATA != NULL && dir == NULL))
{
if (fail == gup_load_update_file(guitar_client, &fw_head, data, (u8*)dir))
{
GTP_ERROR("Load file data failed!");
goto load_failed;
}
}
else
{
if (fail == gup_load_update_header(guitar_client, &fw_head, &data))
{
GTP_ERROR("Load file data failed!");
goto load_failed;
}
}
GTP_DEBUG("Load file data successfully!");
show_len = 40;
total_len = 100;
ts->enter_update = 1;
for (i = 0; i < 5; i++)
{
if (fail == gup_enter_update_mode(guitar_client))
{
GTP_ERROR("Next try![Enter update mode]");
continue;
}
else
{
GTP_ERROR("Set update mode successfully.");
break;
}
}
if (i >= 5)
{
GTP_ERROR("Set update mode failed.");
kfree(ic_nvram);
return fail;
}
retry = 0;
while(retry++ < 5)
{
if (fail == gup_update_firmware(guitar_client, &fw_head, data))
{
GTP_ERROR("Update firmware failed.");
continue;
}
GTP_DEBUG("Update firmware successfully.");
//while(1) // simulation store operation failed
if (fail == gup_nvram_store(guitar_client))
{
GTP_ERROR("Store nvram failed.");
continue;
}
msleep(100);
if (fail == gup_get_ic_msg(guitar_client, 0x1201, buf, 1))
{
GTP_ERROR("Read NVRCS failed.(Store)");
continue;
}
if (buf[GTP_ADDR_LENGTH] & 0x01)
{
GTP_ERROR("Check NVRCS(0x%02x) failed.(Store)", buf[GTP_ADDR_LENGTH]);
continue;
}
GTP_DEBUG("Store nvram successfully.");
if (fail == gup_nvram_recall(guitar_client))
{
GTP_ERROR("Recall nvram failed.");
continue;
}
msleep(5);
if (fail == gup_get_ic_msg(guitar_client, 0x1201, buf, 1))
{
GTP_ERROR("Read NVRCS failed.(Recall)");
continue;
}
if (buf[GTP_ADDR_LENGTH] & 0x02)
{
GTP_ERROR("Check NVRCS(0x%02x) failed.(Recall)", buf[GTP_ADDR_LENGTH]);
continue;
}
GTP_DEBUG("Recall nvram successfully.");
ic_nvram[0] = fw_head.st_addr[0];
ic_nvram[1] = fw_head.st_addr[1];
for ( i = 0; i < 10; i++)
{
ret = gtp_i2c_read(guitar_client, ic_nvram, GTP_ADDR_LENGTH + fw_head.lenth);
if (ret <= 0)
{
continue;
}
break;
}
if (i >= 10)
{
GTP_ERROR("Read nvram failed!");
continue;
}
GTP_DEBUG("Read nvram successfully!");
if (memcmp(data, &ic_nvram[2], fw_head.lenth))
{
GTP_ERROR("Nvram not equal!");
continue;
}
GTP_DEBUG("Check nvram by byte successfully!");
// if (HEADER_UPDATE_DATA == NULL || dir != NULL)
if (HEADER_UPDATE_DATA == NULL && dir == NULL)
{
if (update_msg.gt_loc > 0)
{
GTP_DEBUG("Location:%d, Ret:%d.", (s32)update_msg.gt_loc, (s32)ret);
memset(buf, 0, sizeof(buf));
ret = update_msg.file->f_op->write(update_msg.file, (char*)buf, 6, &update_msg.gt_loc);
if (ret < 0)
{
GTP_ERROR("Didn't clear the focre update flag in file.");
}
else
{
GTP_DEBUG("Clear the focre update flag in file.Location:%d, Ret:%d.", (s32)update_msg.gt_loc, (s32)ret);
}
}
}
GTP_DEBUG("Update successfully!");
break;
}
if (!(HEADER_UPDATE_DATA != NULL && dir == NULL))
{
set_fs(update_msg.old_fs);
filp_close(update_msg.file, NULL);
}
gup_leave_update_mode();
GTP_DEBUG("Leave update mode!");
//Reset guitar
GTP_DEBUG("Reset IC and send config!");
gtp_reset_guitar(10);
ret = gtp_send_cfg(guitar_client);
if (ret < 0)
{
GTP_ERROR("Send config data failed.");
}
msleep(10);
ts->enter_update = 0;
load_failed:
kfree(ic_nvram);
app_mem_failed:
if (!(HEADER_UPDATE_DATA != NULL && dir == NULL))
{
kfree(data);
}
if (retry < 5)
{
show_len = 100;
return success;
}
show_len = 200;
GTP_DEBUG("Update failed!");
if(NULL!=data)
kfree(data);
return fail;
}
u8 gup_init_update_proc(struct goodix_ts_data *ts)
{
struct task_struct *thread = NULL;
pr_debug("gup_init_update_proc start ...............................\n\n ");
if (fail == gup_comfirm_version(ts->client))
{
GTP_ERROR("Comfirm version fail.");
GTP_ERROR("Update thread won't be created.");
return -1;
}
GTP_DEBUG("Comfirm version successfully!");
guitar_client = ts->client;
thread = kthread_run(gup_update_proc, (void*)NULL, "guitar_update");
if (IS_ERR(thread))
{
GTP_ERROR("Failed to create update thread.");
return -1;
}
return 0;
}
//#endif //endif GTP_AUTO_UPDATE
//******************************End of firmware update surpport*******************************