// SPDX-License-Identifier: GPL-2.0 /* * ELAN HID-I2C TouchScreen driver. * * Copyright (C) 2014 Elan Microelectronics Corporation. * * Author: Chuming Zhang */ #include "elan_ts.h" #include //define private data //#define IAP_PORTION uint8_t active_pen_fw[]= { #include "MA50_HIDoverI2C_570B.cfg" }; uint8_t passive_pen_fw[]= { // #include "passive_pen.i" }; const struct vendor_map g_vendor_map[]= { {0x2ae2, "fw_data", active_pen_fw, sizeof(active_pen_fw), 0x271F}, {0x2ae1, "passive_pen", passive_pen_fw, sizeof(passive_pen_fw), 0x271F}, }; //#define ELAN_FW_PAGESIZE (132) static int get_hid_iap_ack(struct elan_ts_data *ts, uint8_t *cmd, int len,uint8_t *buf, int rlen) { int err = 0; const uint8_t ack_ok[2] = {0xaa,0xaa}; const uint8_t ack_rewrite[2] = {0x55,0x55}; err = ts->ops->send(cmd,len); if (err != len) { dev_err(&ts->client->dev, "[elan] write page finish command fauled\n"); return err; } err = ts->ops->poll(); if (err) { dev_err(&ts->client->dev, "[elan] wait for int failed\n"); return err; } err = ts->ops->recv(buf,rlen); dev_info(&ts->client->dev, "[elan]%s buf[4]:buf[5]= %x:%x\n",__func__, buf[4],buf[5]); if ( err == rlen) { if (memcmp(buf+4,ack_ok,sizeof(ack_ok)) == 0) { dev_info(&ts->client->dev,"[elan] iap write page response ok\n"); return 0; } else if (memcmp(buf+4, ack_rewrite, sizeof(ack_rewrite))) { dev_err(&ts->client->dev, "[elan] iap rewrite page response\n"); return 1; } else { dev_err(&ts->client->dev, "[elan] iap ack error\n"); return -1; } } else { dev_err(&ts->client->dev, "[elan] recv ack return value error\n"); return err; } return 0; } static int query_remark_id(struct elan_ts_data *ts) { int len = 0; uint8_t remarkid[HID_CMD_LEN] = {0x04,0x00,0x23,0x00,0x03,0x00,0x06,0x96,0x80,0x1F,0x00,0x00,0x21}; uint8_t buf[67] = {0}; u16 remark_id = 0; len = ts->ops->send(remarkid,sizeof(remarkid)); if ( len != sizeof(remarkid) ) { dev_err(&ts->client->dev, "[elan]Send query remark id cmd failed!! len=%d",len); return -EINVAL; } else dev_err(&ts->client->dev,"[elan]Remark id write successfully!"); msleep(5); len = ts->ops->recv(buf, sizeof(buf)); if (len != sizeof(buf)) { dev_err(&ts->client->dev, "[elan]Send Check Address Read Data error. len=%d", len); return -EINVAL; } else { remark_id = (buf[7] << 8) | buf[8]; dev_err(&ts->client->dev, "[elan]Get Remark id = 0x%4x",remark_id); return remark_id; } } static int hid_fw_upgrade_init(struct elan_ts_data *ts) { int err = 0; u16 remark_id; const uint8_t flash_key[HID_CMD_LEN] = {0x04,0x00,0x23,0x00,0x03,0x00,0x04,0x54,0xc0,0xe1,0x5a}; const uint8_t check_addr[HID_CMD_LEN] = {0x04,0x00,0x23,0x00,0x03,0x00,0x01,0x10}; const uint8_t isp_cmd[HID_CMD_LEN] = {0x04,0x00,0x23,0x00,0x03,0x00,0x04,0x54,0x00,0x12,0x34}; uint8_t buf[67] = {0}; uint8_t response_addr = 0x20; elan_ts_hw_reset(&ts->hw_info); mdelay(300); err = elan_ic_status(ts->client); if (err == FORCED_UPGRADE) ts->recover = FORCED_UPGRADE; else if (err == COMPARE_UPGRADE) ts->recover = COMPARE_UPGRADE; else ts->recover = UNKNOW_TYPE; if (err != UNKNOW_TYPE) { dev_err(&ts->client->dev, "[elan] %s bcl = 0x%02x\n", __func__,ts->fw_info.fw_bcl); if (ts->fw_info.fw_bcl >= 0x60) { remark_id = query_remark_id(ts); if ( remark_id != ts->update_info.remark_id) { dev_err(&ts->client->dev, "[elan]Remark id failed,exit update"); return err; } } } dev_err(&ts->client->dev, "[elan] %s get ic status = %d\n", __func__, err); err = ts->ops->send(flash_key,sizeof(flash_key)); if ( err != sizeof(flash_key)) { dev_err(&ts->client->dev, "[elan]send flash key failed ,exit update\n"); return err; } mdelay(20); if (ts->recover == COMPARE_UPGRADE) {//normal mode err = ts->ops->send(isp_cmd, sizeof(isp_cmd)); if ( err != sizeof(isp_cmd)) { dev_err(&ts->client->dev, "[elan] send isp cmd failed, exit update\n"); return err; } } mdelay(20); err = ts->ops->send(check_addr, sizeof(check_addr)); if ( err != sizeof(check_addr)) { dev_err(&ts->client->dev, "[elan] send check addr failed, exit update\n"); return err; } // mdelay(20); ts->ops->poll(); err = ts->ops->recv(buf, sizeof(buf)); if ( err != sizeof(buf)) { dev_err(&ts->client->dev, "[elan] recv check addr response failed\n"); return err; } dev_err(&ts->client->dev, "[elan] %s response_addr = 0x%02x, buf=0x%2x\n",__func__, response_addr, buf[4]); if (memcmp(&buf[4], &response_addr, 1)) { dev_err(&ts->client->dev, "[elan] response addr check failed,exit update\n"); return err; } else { dev_err(&ts->client->dev, "[elan] update init success\n"); err = 0; } return err; } static int hid_fw_upgrade_finshed(struct elan_ts_data *ts) { int ret = 0; uint8_t upgrade_end[HID_CMD_LEN] = {0x04,0x00,0x23,0x00,0x03,0x1A}; ret = ts->ops->send(upgrade_end, sizeof(upgrade_end)); if (ret != sizeof(upgrade_end)) ret = -1; else ret = 0; return ret; } static int Hid_Fw_Update(struct i2c_client *client) { struct elan_ts_data *ts = i2c_get_clientdata(client); struct elan_update_fw_info *update = &ts->update_info; int wRemainLen = 0; int wCopyLen = 0; int wFwSize = update->FwSize; int wCount = 0; int wPayLoadLen = 0; int qOffset = 0; int qCmdLen = 9; int err = 0; int retry = 3; uint8_t ack_buf[67] = {0x00}; uint8_t qIapPagefinishcmd[HID_CMD_LEN] = {0x04,0x00,0x23,0x00,0x03,0x22}; uint8_t qIapWriteCmd[HID_CMD_LEN] = {0x04,0x00,0x23,0x00,0x03,0x21,0x00,0x00,0x1c}; update_retry: err = hid_fw_upgrade_init(ts); if ( err ) { dev_err(&ts->client->dev, "[elan] upgrade init failed\n"); if ((retry-- > 0)) goto update_retry; else return -1; } msleep(50); dev_err(&ts->client->dev, "[elan]%s fw size = %d\n", __func__,wFwSize); while(wFwSize) { wRemainLen = MIN((update->FwSize - wCount),( IAP_FLASH_SIZE -( qOffset % IAP_FLASH_SIZE ))); wCopyLen = MIN(wRemainLen, HID_CMD_LEN - qCmdLen); //dev_info(&ts->client->dev,"[elan]%s wRemainLen:wCopyLen = %d:%d\n", __func__,wRemainLen, wCopyLen); memcpy(qIapWriteCmd+ IAP_CMD_HEADER_LEN, update->FwData + wCount, wCopyLen); qCmdLen += wCopyLen; wPayLoadLen = wCopyLen; qIapWriteCmd[6] = qOffset >> 8; qIapWriteCmd[7] = qOffset & 0xff; qIapWriteCmd[8] = wPayLoadLen; err = ts->ops->send(qIapWriteCmd, sizeof(qIapWriteCmd)); if ( err != sizeof(qIapWriteCmd)) { dev_err(&ts->client->dev,"[elan]write %dbytes failed\n", wCopyLen); if ( (retry--) > 0) { qOffset = 0; wFwSize = update->FwSize; wCount = 0; qCmdLen = IAP_CMD_HEADER_LEN; goto update_retry; } else return -1; } qCmdLen = IAP_CMD_HEADER_LEN; qOffset += wPayLoadLen; wCount += wPayLoadLen; wFwSize -= wPayLoadLen; if( (qOffset % (IAP_FLASH_SIZE) == 0) ||( wCount == update->FwSize)) { err = get_hid_iap_ack(ts,qIapPagefinishcmd,sizeof(qIapPagefinishcmd),ack_buf, sizeof(ack_buf)); if (err) { dev_err(&ts->client->dev, "get iap ack failed\n"); if ( (retry--) > 0) { wFwSize = update->FwSize; wCount = 0; qCmdLen = IAP_CMD_HEADER_LEN; qOffset = 0; goto update_retry; } else return -1; } else qOffset = 0; } } err = hid_fw_upgrade_finshed(ts); if (err) { dev_err(&ts->client->dev,"[elan] fw upgrade finshed failed!!!\n"); return -1; } dev_err(&ts->client->dev,"[elan] fw upgrade success!!!\n"); return 0; } static int elan_fw_write_page(struct i2c_client *client, const void *page) { struct elan_ts_data *ts = i2c_get_clientdata(client); const uint8_t ack_ok[] = { 0xaa, 0xaa }; uint8_t buf[2] = {0x00}; int retry; int error; for (retry = 0; retry < 5; retry++) { error = ts->ops->send(page, FW_PAGE_SIZE); if (error != FW_PAGE_SIZE) { dev_err(&client->dev, "IAP Write Page failed: %d\n", error); continue; } error = ts->ops->recv(buf, sizeof(buf)); if (error != sizeof(buf)) { dev_err(&client->dev, "IAP Ack read failed: %d\n", error); return error; } if (!memcmp(buf, ack_ok, sizeof(ack_ok))) return 0; error = -EIO; dev_err(&client->dev, "IAP Get Ack Error [%02x:%02x]\n", buf[0], buf[1]); } return error; } static int Normal_Fw_Update(struct i2c_client *client) { struct elan_ts_data *ts = i2c_get_clientdata(client); struct elan_update_fw_info *update = &ts->update_info; const uint8_t enter_iap[] = { 0x45, 0x49, 0x41, 0x50 }; // const uint8_t enter_isp[] = { 0x54, 0x00, 0x12, 0x34 }; const uint8_t iap_ack[] = { 0x55, 0xaa, 0x33, 0xcc }; uint8_t buf[4] = {0x00}; int page = 0; int error; uint8_t send_id; elan_ts_hw_reset(&ts->hw_info); msleep(20); error = ts->ops->send(enter_iap, sizeof(enter_iap)); if (error != sizeof(enter_iap)) { dev_err(&client->dev, "failed to enter IAP mode: %d\n", error); return error; } msleep(20); /* check IAP state */ error = ts->ops->recv(buf, sizeof(buf)); if (error != sizeof(buf)) { dev_err(&client->dev, "failed to read IAP acknowledgement: %d\n", error); return error; } if (memcmp(buf, iap_ack, sizeof(iap_ack))) { dev_err(&client->dev, "failed to enter IAP: %*ph (expected %*ph)\n", (int)sizeof(buf), buf, (int)sizeof(iap_ack), iap_ack); return -EIO; } dev_info(&client->dev, "successfully entered IAP mode"); /* send dummy byte */ send_id = client->addr; error = ts->ops->send(&send_id, 1); if (error != 1) { dev_err(&client->dev, "sending dummy byte failed: %d\n", error); return error; } /*write page*/ for (page = 0; page < update->PageNum; page++) { error = elan_fw_write_page(client, update->FwData + page * FW_PAGE_SIZE); if (error) { dev_err(&client->dev, "failed to write FW page %d: %d\n", page, error); return error; } } msleep(300); dev_info(&client->dev, "firmware update completed\n"); return 0; } int elan_FW_Update(struct i2c_client *client) { int err = 0; struct elan_ts_data *ts = i2c_get_clientdata(client); if (ts->chip_type == HID_TYPE_PROTOCOL){ err = Hid_Fw_Update(client); if (!err) ts->recover = COMPARE_UPGRADE; } else if(ts->chip_type == NORMAL_TYPE_PROTOCOL) err = Normal_Fw_Update(client); return err; } static int elan_ts_hid_calibrate(struct i2c_client *client) { uint8_t flash_key[HID_CMD_LEN] = {0x04,0x00,0x23,0x00,0x03,0x00,0x04,CMD_W_PKT,0xc0,0xe1,0x5a}; uint8_t cal_cmd[HID_CMD_LEN] = {0x04,0x00,0x23,0x00,0x03,0x00,0x04,CMD_W_PKT,0x29,0x00,0x01}; int err = 0; uint8_t resp[67] = {0x00}; uint8_t rek_resp[4] = {0x66,0x66,0x66,0x66}; struct elan_ts_data *ts = i2c_get_clientdata(client); dev_info(&client->dev, "[elan] %s: Flash Key cmd\n", __func__); err = ts->ops->send(flash_key, sizeof(flash_key)); if (err != sizeof(flash_key)) { dev_err(&client->dev, "[elan] %s: i2c_master_send failed\n",__func__); return err; } err = ts->ops->send(cal_cmd, sizeof(cal_cmd)); if ( err != sizeof(cal_cmd)) { dev_err(&client->dev, "[elan] %s: i2c_master_send failed\n",__func__); return err; } err = ts->ops->poll(); if (err) { dev_err(&client->dev, "[elan] %s: wait for int low failed %d\n", __func__, err); return err; } else { err = ts->ops->recv(resp,sizeof(resp)); if ( err == sizeof(resp)) { if (memcmp(rek_resp, resp + 4, sizeof(rek_resp))) { dev_err(&client->dev, "%s:%d calibrate failed\n", __func__,__LINE__); return -EINVAL; } else { dev_info(&client->dev,"calibrate success\n"); return 0; } } else { dev_err(&client->dev, "%s:%d recv calibrate data failed\n",__func__,__LINE__); return -EINVAL; } } } static int elan_ts_normal_calibrate(struct i2c_client *client) { struct elan_ts_data *ts = i2c_get_clientdata(client); uint8_t flash_key[] = {CMD_W_PKT, 0xc0, 0xe1, 0x5a}; uint8_t cal_cmd[] = {CMD_W_PKT, 0x29, 0x00, 0x01}; uint8_t rek_resp[4] = {0x66,0x66,0x66,0x66}; uint8_t resp[4] = {0x00}; int err = 0; dev_info(&client->dev, "[elan] %s: Flash Key cmd\n", __func__); err = ts->ops->send(flash_key, sizeof(flash_key)); if (err != sizeof(flash_key)) { dev_err(&client->dev, "[elan] %s: i2c_master_send failed\n",__func__); return err; } err = ts->ops->send(cal_cmd, sizeof(cal_cmd)); if ( err != sizeof(cal_cmd) ) { dev_err(&client->dev, "[elan] %s: i2c_master_send failed\n",__func__); return err; } err = ts->ops->poll(); if ( err ) { } else { err = ts->ops->recv(resp,sizeof(resp)); if ( err == sizeof(resp) ) { if (memcmp(rek_resp, resp, sizeof(rek_resp))) { dev_err(&client->dev, "%s:%d calibrate failed", __func__,__LINE__); return -EINVAL; } else { dev_info(&client->dev,"calibrate success"); return 0; } } else { dev_err(&client->dev, "%s:%d recv calibrate data failed",__func__,__LINE__); return -EINVAL; } } return 0; } int elan_ts_calibrate(struct i2c_client *client) { struct elan_ts_data *ts = i2c_get_clientdata(client); int err = 0; if (ts->chip_type == HID_TYPE_PROTOCOL) err = elan_ts_hid_calibrate(client); else if(ts->chip_type == NORMAL_TYPE_PROTOCOL) err = elan_ts_normal_calibrate(client); return err; } static int check_cal_status(struct i2c_client *client) { struct elan_ts_data *ts = i2c_get_clientdata(client); const uint8_t check_rek_cmd[HID_CMD_LEN] = {0x04, 0x00, 0x23, 0x00, 0x03, 0x00, 0x04, 0x53, 0xD0, 0x00, 0x01}; const uint8_t rek_count[2] = {0xFF,0xFF}; uint8_t resp[67] = {0}; int err = 0; err = ts->ops->send(check_rek_cmd, sizeof(check_rek_cmd)); if (err != sizeof(check_rek_cmd)) { dev_err(&client->dev, "[elan] %s send check rek command failed\n", __func__); return err; } err = ts->ops->poll(); if (err) { dev_err(&client->dev, "[elan] %s wait int failed\n", __func__); return err; } err = ts->ops->recv(resp, sizeof(resp)); if (err != sizeof(resp)){ dev_err(&client->dev, "[elan] %s recv check rek failed\n", __func__); return err; } else { dev_info(&client->dev, "[elan] %s check rek resp 0x%2x:0x%2x:0x%2x:0x%2x\n",__func__,\ resp[6],resp[7],resp[8],resp[9]); if (memcmp(resp+6, rek_count,2)) { dev_info(&client->dev, "[elan] %s check ok!!\n",__func__); return 0; } else { dev_info(&client->dev, "[elan] %s check failed!!\n",__func__); return -1; } } } int elan_ts_check_calibrate(struct i2c_client *client) { int err = 0; struct elan_ts_data *ts = i2c_get_clientdata(client); if (ts->chip_type == HID_TYPE_PROTOCOL) err = check_cal_status(client); else dev_info(&client->dev, "[elan] ok"); return err; } static int elan_read_fw_from_sdcard(struct elan_ts_data *ts) { dev_err(&ts->client->dev, "[elan] can not pass Google GKI, return\n"); return -1; /* * struct elan_update_fw_info *update = &ts->update_info; * mm_segment_t oldfs; * struct file *firmware_fp; * int ret = 0; * int retry = 0; * int file_len; * static uint8_t *fw_data_user; * * if ( fw_data_user != NULL) * kfree(fw_data_user); * * oldfs = get_fs(); * set_fs(KERNEL_DS); * * for (retry = 0; retry < 5; retry++) { * firmware_fp = filp_open(update->fw_local_path, O_RDONLY, 0); * if ( IS_ERR(firmware_fp) ) { * dev_err(&ts->client->dev, "[elan] retry to open user ekt file\n"); * mdelay(100); * } else * break; * } * * if ( retry >= 5 ) { * dev_err(&ts->client->dev, * "[elan] open %s file error!!\n",update->fw_local_path); * ret = -1; * goto out_read_fw_from_user2; * } else * dev_dbg(&ts->client->dev, * "[elan] open %s file sucess!!\n",update->fw_local_path); * * file_len = firmware_fp->f_path.dentry->d_inode->i_size; * if (file_len == 0) { * dev_dbg(&ts->client->dev, * "[elan] Get File len err!!!!"); * ret = -2; * goto out_read_fw_from_user1; * } * * fw_data_user = kzalloc(file_len, GFP_KERNEL); * if (fw_data_user == NULL) { * dev_err(&ts->client->dev, * "[elan] malloc fw_data err\n"); * ret = -3; * goto out_read_fw_from_user1; * } * * ret = firmware_fp->f_op->read(firmware_fp, fw_data_user, * file_len, &firmware_fp->f_pos); * if ( ret != file_len ) { * dev_err(&ts->client->dev, * "[elan] read EKT file size err, ret=%d!\n",ret); * ret = -4; * goto out_read_fw_from_user0; * } else { * update->FwData = fw_data_user; * update->FwSize = file_len; * update->PageNum = update->FwSize/132; * ret = 0; * } *out_read_fw_from_user0: *out_read_fw_from_user1: * filp_close(firmware_fp, NULL); *out_read_fw_from_user2: * set_fs(oldfs); * * return ret; */ } static int get_driver_fw(struct elan_ts_data *ts) { int i,vendor_num = 0, lcm_id; struct elan_update_fw_info *update_info = &ts->update_info; vendor_num = sizeof(g_vendor_map)/sizeof(g_vendor_map[0]); /*if there are more than one display product, ODM should provid lcmid*/ lcm_id = 0x2ae2; /*if there are more than one tp panle, ELAN should provide fwid*/ for (i = 0; i < vendor_num; i++) { dev_err(&ts->client->dev, "[elan] vendor name = %s, lcm_id = 0x%04x, vendor_id = 0x%04x\n",\ g_vendor_map[i].vendor_name,lcm_id, g_vendor_map[i].vendor_id); if (lcm_id == g_vendor_map[i].vendor_id) { update_info->FwData = g_vendor_map[i].fw_array; update_info->FwSize = g_vendor_map[i].fw_size; update_info->PageNum = g_vendor_map[i].fw_size/132; dev_err(&ts->client->dev, "fwSize = %d, pagenum = %d\n", update_info->FwSize,update_info->PageNum ); return 0; } } dev_err(&ts->client->dev,"[elan] ID is error, not support!!\n"); return -1; } int elan_get_vendor_fw(struct elan_ts_data *ts, int type) { int err = 0; struct elan_update_fw_info *update_info = &ts->update_info; const struct firmware *p_fw_entry; if ( type == FROM_SYS_ETC_FIRMWARE) { update_info->FwName = kasprintf(GFP_KERNEL, "elants_i2c.ekt"); if (!update_info->FwName) return -ENOMEM; err = request_firmware(&p_fw_entry, update_info->FwName, &ts->client->dev); if ( err ) { dev_err(&ts->client->dev, "request_firmware fail err=%d\n",err); return -1; } else { dev_dbg(&ts->client->dev, "Firmware Size=%zu",p_fw_entry->size); update_info->FwData = p_fw_entry->data; update_info->FwSize = p_fw_entry->size; update_info->PageNum = update_info->FwSize/132; dev_info(&ts->client->dev, "[elan] %d: FwSize %d, PageNum %d\n", __LINE__, update_info->FwSize, update_info->PageNum ); } } else if ( type == FROM_SDCARD_FIRMWARE ) { update_info->FwName = kasprintf(GFP_KERNEL, "elants_i2c.ekt"); sprintf(update_info->fw_local_path, "%s%s", "/data/local/tmp", update_info->FwName); dev_info(&ts->client->dev, "[elan] Update Firmware from %s\n", update_info->fw_local_path); err = elan_read_fw_from_sdcard(ts); if ( err ) { dev_err(&ts->client->dev, "Get FW Data From %s failed\n",update_info->fw_local_path); return -1; } } else if ( type == FROM_DRIVER_FIRMWARE ) { err = get_driver_fw(ts); if ( err ) { dev_err(&ts->client->dev, "Get FW Data From driver failed\n"); return -1; } } update_info->remark_id = get_unaligned_le16(&update_info->FwData[update_info->FwSize - 4]); return err; } void elan_check_update_flage(struct elan_ts_data *ts) { int New_FW_VERSION = 0; int New_FW_ID = 0; int err = 0; int retry = 0; struct elan_update_fw_info *update_info = &ts->update_info; struct elan_fw_info *fw_info = &ts->fw_info; int try = 30; /* ** support three methods to get fwdata. * FROM_SYS_ETC_FIRMWARE :/system/firmware/elants_i2c.ekt * FROM_SDCARD_FIRMWARE: /data/local/tmp/elants_i2c.ekt * FROM_DRIVER_FIRMWARE: in driver code directory *.i */ RETRY: err = elan_get_vendor_fw(ts,ts->fw_store_type); if (err) { if (try--) { msleep(100); goto RETRY; } dev_err(&ts->client->dev, "[elan] ***counld not get fw,exit update flow!!***\n"); goto exit_fw_upgrade; } else { dev_err(&ts->client->dev, "[elan]%d ***get fw success,enter update flow!! try count %d***\n", __LINE__, 30-try); } if ( ts->recover == FORCED_UPGRADE ) { dev_err(&ts->client->dev, "[elan] *** fw is miss, force update fw!! ***\n"); goto fw_upgrade; } /* ** id and version index maybe change. */ New_FW_ID = update_info->FwData[0xD5ED] << 8 | update_info->FwData[0XD5EC]; New_FW_VERSION = update_info->FwData[0x9F] << 8 | update_info->FwData[0x9E]; dev_info(&ts->client->dev, "[elan] FW_ID=0x%4x,New_FW_ID=0x%4x\n",fw_info->fw_id,New_FW_ID); dev_info(&ts->client->dev, "[elan] FW_VERSION=0x%4x,New_FW_VERSION=0x%4x\n",fw_info->fw_ver,New_FW_VERSION); if ((fw_info->fw_id&0xff) != (New_FW_ID&0xff)) { dev_err(&ts->client->dev,"[elan] fw id is different, can not update!"); goto exit_fw_upgrade; } if ((fw_info->fw_ver&0xff) >= (New_FW_VERSION&0xff)) { dev_info(&ts->client->dev,"[elan] fw version is newest!!\n"); goto exit_fw_upgrade; } fw_upgrade: /*start update fw*/ elan_FW_Update(ts->client); elan_ts_hw_reset(&ts->hw_info); mdelay(300); /*get fw msg*/ for (; retry < 3; retry++) { err = elan__fw_packet_handler(ts->client); if (err) dev_err(&ts->client->dev, "[elan] After update fw get fw msg failed, retry=%d\n",retry); else break; } mdelay(200); /*calibration*/ for (retry = 0; retry < 3; retry++) { err = elan_ts_calibrate(ts->client); if (err) dev_err(&ts->client->dev, "[elan] After update fw calibrate failed, retry=%d\n",retry); else { err = elan_ts_check_calibrate(ts->client); /*ic reponse rek count,count != 0xff? "ok":"failed" */ if (err) dev_err(&ts->client->dev, "[elan] After update fw check rek failed, retry=%d\n",retry); else break; } } exit_fw_upgrade: return; }