718 lines
23 KiB
C
718 lines
23 KiB
C
/*
|
|
* Privileged & confidential All Rights/Copyright Reserved by FocalTech.
|
|
* ** Source code released bellows and hereby must be retained as
|
|
* FocalTech's copyright and with the following disclaimer accepted by
|
|
* Receiver.
|
|
*
|
|
* "THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO
|
|
* EVENT SHALL THE FOCALTECH'S AND ITS AFFILIATES'DIRECTORS AND OFFICERS BE
|
|
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
|
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
|
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE."
|
|
*/
|
|
|
|
/*****************************************************************************
|
|
* Some descriptions about this sample code.
|
|
* fts_fwupg_auto_upgrade() is entry of this sample code.
|
|
*
|
|
* The initial work you should do is to implement the i2c communication function based on your platform:
|
|
* platform_i2c_write() and platform_i2c_read().
|
|
*
|
|
*
|
|
* How to use the upgrade sample code?
|
|
* Firstly, Place firmware file(app.i) into firmware directory.
|
|
* Secondly, modify variable fw_file_ft3x68 to include firmware file you put into firmware directory.
|
|
* Warning: you can ignore the above steps if you want get firmware file as your way. And
|
|
* you should get firmware at the beginning of function fts_fwupg_auto_upgrade().
|
|
* Thirdly, call fts_fwupg_auto_upgrade().
|
|
*
|
|
*
|
|
*****************************************************************************/
|
|
|
|
/*****************************************************************************
|
|
* Included header files
|
|
*****************************************************************************/
|
|
#include "tp_drv_upgrade.h"
|
|
#include "tp_port_ctrl.h"
|
|
#include "sys_config.h"
|
|
#include <stdbool.h>
|
|
#include <stdint.h>
|
|
|
|
#define ENABLE_PRINT_INFO 1
|
|
#if ENABLE_PRINT_INFO
|
|
#define static_print_info(...) sys_tp_log_i(__VA_ARGS__) //一般信息打印宏控制
|
|
#define static_print_warn(...) sys_tp_log_w(__VA_ARGS__) //警告信息打印一般常开
|
|
#define static_print_debug(...) sys_tp_log_d(__VA_ARGS__) //警告信息打印一般常开
|
|
#define static_print_error(...) sys_tp_log_e(__VA_ARGS__) //错误信息打印一般常开
|
|
#else
|
|
#define static_print_info(...)
|
|
#define static_print_warn(...)
|
|
#define static_print_error(...)
|
|
#endif
|
|
|
|
/*****************************************************************************
|
|
* Private constant and macro definitions using #define
|
|
*****************************************************************************/
|
|
/*command*/
|
|
#define FTS_CMD_RESET 0x07
|
|
#define FTS_CMD_FLASH_MODE 0x09
|
|
#define FTS_FLASH_MODE_UPGRADE_VALUE 0x0B
|
|
#define FTS_CMD_FLASH_STATUS 0x6A
|
|
#define FTS_CMD_ERASE_APP 0x61
|
|
#define FTS_RETRIES_REASE 50
|
|
#define FTS_RETRIES_DELAY_REASE 400
|
|
#define FTS_CMD_FLASH_STATUS_ERASE_OK 0xF0AA
|
|
#define FTS_CMD_FLASH_STATUS_ECC_OK 0xF055
|
|
#define FTS_CMD_ECC_INIT 0x64
|
|
#define FTS_CMD_ECC_CAL 0x65
|
|
#define FTS_CMD_ECC_READ 0x66
|
|
#define FTS_CMD_ECC_CAL_LEN 6
|
|
#define FTS_RETRIES_ECC_CAL 10
|
|
#define FTS_RETRIES_DELAY_ECC_CAL 50
|
|
#define FTS_CMD_WRITE 0xBF
|
|
#define FTS_RETRIES_WRITE 100
|
|
#define FTS_CMD_READ_DELAY 1
|
|
#define FTS_CMD_APP_DATA_LEN 0x7A
|
|
#define FTS_CMD_FW_START_ADDRESS 0x0C00
|
|
/*register address*/
|
|
#define FTS_UPGRADE_AA 0xAA
|
|
#define FTS_UPGRADE_55 0x55
|
|
|
|
#define FTS_RETRIES_CHECK_ID 20
|
|
#define FTS_DELAY_UPGRADE_AA 10
|
|
#define FTS_DELAY_UPGRADE_RESET 400
|
|
#define FTS_DELAY_READ_ID 20
|
|
#define FTS_DELAY_UPGRADE 80
|
|
#define FTS_RETRIES_UPGRADE 2
|
|
|
|
#define FTS_MIN_LEN 0x120
|
|
#define FTS_MAX_LEN_APP (64 * 1024)
|
|
#define FTS_VER_IN_FILE_ADDR 0x010A
|
|
|
|
/*Defined Macroes*/
|
|
#define FTS_FLASH_PACKET_LENGTH (128)
|
|
|
|
#define FTS_MAX_LEN_ECC_CALC (0xFFFE) /* must be even */
|
|
|
|
/*****************************************************************************
|
|
* Private variables/functions
|
|
*****************************************************************************/
|
|
static bool tp_fw_valid = false;/*to note firmware in TP controller is valid or not*/
|
|
|
|
/* The array variable fw_file_ft3x68 stores the firmware file that you
|
|
* want to upgrade.
|
|
* Please modify it based on the firmware file you get.
|
|
* Please ignore it if you get firmware file from file system, now you
|
|
* need read firmware file using your method.
|
|
*/
|
|
uint8_t fw_file_ft3x68[] = {
|
|
#include "FT3X68_20240415_app.i"
|
|
};
|
|
|
|
#ifndef FT6146_I2C_ADDR
|
|
#define FT6146_I2C_ADDR 0x38
|
|
#endif
|
|
static uint32_t ft6146_i2c_write(uint8_t cmd)
|
|
{
|
|
return tp_i2c_cmd_write(FT6146_I2C_ADDR, cmd);
|
|
}
|
|
|
|
static uint32_t ft6146_i2c_read(uint8_t reg_addr, uint8_t *data_buf, uint32_t data_len)
|
|
{
|
|
return tp_i2c_data_read(FT6146_I2C_ADDR, reg_addr, 1, data_buf, data_len);
|
|
}
|
|
|
|
static uint32_t ft6146_reg_write(uint8_t reg_addr, uint8_t reg_cfg)
|
|
{
|
|
return tp_i2c_reg_write(FT6146_I2C_ADDR, reg_addr, 1, reg_cfg);
|
|
}
|
|
|
|
static uint32_t ft6146_data_write(uint8_t reg_addr, uint8_t *data_buf, uint32_t data_len)
|
|
{
|
|
return tp_i2c_data_write(FT6146_I2C_ADDR, reg_addr, data_buf, data_len);
|
|
}
|
|
|
|
/*Functions*/
|
|
/************************************************************************
|
|
* Name: fts_fwupg_check_flash_status
|
|
* Brief:
|
|
* read status from tp
|
|
* Input: @flash_status: correct value from tp
|
|
* @retries: read retry times
|
|
* @retries_delay: retry delay
|
|
* Output:
|
|
* Return:
|
|
* return true if flash status check pass, otherwise return false
|
|
***********************************************************************/
|
|
static bool fts_fwupg_check_flash_status(uint16_t flash_status, int retries, int retries_delay)
|
|
{
|
|
int ret = 0;
|
|
int i = 0;
|
|
uint8_t cmd = 0;
|
|
uint8_t val[2] = { 0 };
|
|
uint16_t read_status = 0;
|
|
|
|
for (i = 0; i < retries; i++) {
|
|
cmd = FTS_CMD_FLASH_STATUS;
|
|
ret = ft6146_i2c_read(cmd , val, 2);
|
|
read_status = (((uint16_t)val[0]) << 8) + val[1];
|
|
if (flash_status == read_status) {
|
|
/* static_print_debug("[UPGRADE]flash status ok"); */
|
|
return true;
|
|
}
|
|
/* static_print_debug("flash status fail,ok:%04x read:%04x, retries:%d", flash_status, read_status, i); */
|
|
tp_delay(retries_delay);
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* Name: fts_check_id
|
|
* Brief:
|
|
* The function is used to check id.
|
|
* Input:
|
|
* Output:@id_h, id chiper high
|
|
* @id_l, id chiper low
|
|
* Return:
|
|
* return 0 if check id successfully, otherwise error code.
|
|
*****************************************************************************/
|
|
static int fts_check_id(uint8_t id_h, uint8_t id_l)
|
|
{
|
|
int i = 0;
|
|
uint8_t cmd = FTS_CMD_READ_ID;
|
|
uint8_t buf[2] = { 0 };
|
|
|
|
cmd = 0xC0;
|
|
ft6146_reg_write(FTS_REG_UPGRADE, FTS_UPGRADE_AA);
|
|
ft6146_i2c_read(cmd, buf, 2);
|
|
static_print_info("TOUCH: cmd:%x %x", buf[0], buf[1]);
|
|
ft6146_reg_write(FTS_REG_UPGRADE, FTS_UPGRADE_55);
|
|
ft6146_i2c_read(cmd, buf, 2);
|
|
static_print_info("TOUCH: cmd:%x %x", buf[0], buf[1]);
|
|
tp_delay(FTS_DELAY_UPGRADE);
|
|
/*confirm in boot*/
|
|
for (i = 0; i < FTS_RETRIES_CHECK_ID; i++) {
|
|
ft6146_reg_write(FTS_UPGRADE_55, FTS_UPGRADE_AA);
|
|
tp_delay(FTS_DELAY_UPGRADE_AA);
|
|
cmd = FTS_CMD_READ_ID;
|
|
ft6146_i2c_read(cmd, buf, 2);
|
|
if ((buf[0] != id_h) || (buf[1] != id_l)) {
|
|
static_print_error("TOUCH: check id fail,read id:0x%02x%02x != 0x%02x%02x,retry:%d",
|
|
buf[0], buf[1], id_h, id_l, i);
|
|
return -1;
|
|
} else
|
|
break;
|
|
|
|
ft6146_reg_write(FTS_REG_UPGRADE, FTS_UPGRADE_AA);
|
|
ft6146_reg_write(FTS_REG_UPGRADE, FTS_UPGRADE_55);
|
|
tp_delay(FTS_DELAY_READ_ID);
|
|
}
|
|
|
|
if (i >= 10)
|
|
return -1;
|
|
|
|
static_print_info("TOUCH: read boot id:%x %x", buf[0], buf[1]);
|
|
return 0;
|
|
}
|
|
|
|
/************************************************************************
|
|
* Name: fts_fwupg_enter_into_boot
|
|
* Brief:
|
|
* enter into boot environment, ready for upgrade
|
|
* Input:
|
|
* Output:
|
|
* Return:
|
|
* return 0 if success, otherwise return error code
|
|
***********************************************************************/
|
|
static int fts_fwupg_enter_into_boot(void)
|
|
{
|
|
int ret = 0;
|
|
uint8_t boot_id[2] = { 0 };
|
|
|
|
/*software reset to boot mode*/
|
|
if (tp_fw_valid) {
|
|
ret = ft6146_reg_write(FTS_REG_UPGRADE, FTS_UPGRADE_AA);
|
|
if (ret < 0) {
|
|
static_print_error("TOUCH: write FC=0xAA fail");
|
|
return ret;
|
|
}
|
|
tp_delay(FTS_DELAY_UPGRADE_AA);
|
|
|
|
ret = ft6146_reg_write(FTS_REG_UPGRADE, FTS_UPGRADE_55);
|
|
if (ret < 0) {
|
|
static_print_error("TOUCH: write FC=0x55 fail");
|
|
return ret;
|
|
}
|
|
|
|
tp_delay(FTS_DELAY_UPGRADE);
|
|
}
|
|
|
|
/*confirm TP controller is int romboot state*/
|
|
ret = fts_check_id(FTS_CHIP_IDH, FTS_CHIP_IDL);
|
|
if (ret < 0) {
|
|
static_print_error("TOUCH: checking id fails");
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/************************************************************************
|
|
* Name: fts_fwupg_erase
|
|
* Brief:
|
|
* erase flash area
|
|
* Input: @delay: delay after erase
|
|
* Output:
|
|
* Return:
|
|
* return 0 if success, otherwise return error code
|
|
***********************************************************************/
|
|
static int fts_fwupg_erase(uint32_t delay)
|
|
{
|
|
int ret = 0;
|
|
uint8_t cmd = 0;
|
|
bool flag = false;
|
|
|
|
static_print_info("**********erase now**********");
|
|
/*send to erase flash*/
|
|
cmd = FTS_CMD_ERASE_APP;
|
|
ret = ft6146_i2c_write(cmd);
|
|
if (ret < 0) {
|
|
static_print_error("TOUCH: erase cmd fail");
|
|
return ret;
|
|
}
|
|
tp_delay(delay);
|
|
|
|
/* read status 0xF0AA: success */
|
|
flag = fts_fwupg_check_flash_status(FTS_CMD_FLASH_STATUS_ERASE_OK, FTS_RETRIES_REASE, FTS_RETRIES_DELAY_REASE);
|
|
if (!flag) {
|
|
static_print_error("TOUCH: ecc flash status check fail");
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/************************************************************************
|
|
* Name: fts_flash_write_buf
|
|
* Brief:
|
|
* write buf data to flash address
|
|
* Input: @saddr: start address data write to flash
|
|
* @buf: data buffer
|
|
* @len: data length
|
|
* @delay: delay after write
|
|
* Output:
|
|
* Return:
|
|
* return 0 if success, otherwise return error code
|
|
***********************************************************************/
|
|
static int fts_flash_write_buf(uint32_t saddr, uint8_t *buf, uint16_t len, uint32_t delay)
|
|
{
|
|
int ret = 0;
|
|
uint32_t i = 0;
|
|
uint32_t j = 0;
|
|
uint32_t packet_number = 0;
|
|
uint16_t packet_len = 0;
|
|
uint32_t addr = 0;
|
|
uint32_t offset = 0;
|
|
uint16_t remainder = 0;
|
|
uint8_t packet_buf[FTS_FLASH_PACKET_LENGTH+6] = {0};
|
|
uint8_t cmd = 0;
|
|
uint8_t val[2] = { 0 };
|
|
uint16_t read_status = 0;
|
|
uint16_t wr_ok = 0;
|
|
|
|
if (!buf || !len) {
|
|
static_print_error("TOUCH: buf/len is invalid");
|
|
return -1;
|
|
}
|
|
|
|
static_print_info("TOUCH: data buf start addr=0x%x, len=0x%x", saddr, len);
|
|
packet_number = len / FTS_FLASH_PACKET_LENGTH;
|
|
remainder = len % FTS_FLASH_PACKET_LENGTH;
|
|
if (remainder > 0)
|
|
packet_number++;
|
|
packet_len = FTS_FLASH_PACKET_LENGTH;
|
|
static_print_info("TOUCH: write data, num:%d remainder:%d", packet_number, remainder);
|
|
|
|
for (i = 0; i < packet_number; i++) {
|
|
offset = i * FTS_FLASH_PACKET_LENGTH;
|
|
addr = saddr + offset;
|
|
packet_buf[0] = FTS_CMD_WRITE;
|
|
packet_buf[1] = (addr >> 16);
|
|
packet_buf[2] = (addr >> 8);
|
|
packet_buf[3] = (addr);
|
|
|
|
/* last packet */
|
|
if ((i == (packet_number - 1)) && remainder)
|
|
packet_len = remainder;
|
|
|
|
packet_buf[4] = (packet_len >> 8);
|
|
packet_buf[5] = (packet_len);
|
|
|
|
memcpy(&packet_buf[6],(buf+offset),packet_len);
|
|
|
|
ret = ft6146_data_write(packet_buf[0], &packet_buf[1], (packet_len + 5));
|
|
if (ret < 0) {
|
|
static_print_error("TOUCH: app write fail");
|
|
return ret;
|
|
}
|
|
tp_delay(FTS_CMD_READ_DELAY);
|
|
|
|
/* read status */
|
|
wr_ok = 0x1000 + addr / packet_len;
|
|
for (j = 0; j < FTS_RETRIES_WRITE; j++) {
|
|
cmd = FTS_CMD_FLASH_STATUS;
|
|
ret = ft6146_i2c_read(cmd, val, 2);
|
|
read_status = (((uint16_t)val[0]) << 8) + val[1];
|
|
if (wr_ok == read_status)
|
|
break;
|
|
else
|
|
static_print_debug("%x %x", wr_ok, read_status);
|
|
tp_delay(FTS_CMD_READ_DELAY);
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/************************************************************************
|
|
* Name: fts_fwupg_ecc_cal_host
|
|
* Brief:
|
|
* Calculate the ecc value of firmware program.
|
|
* Input: @data: pointer to firmware program
|
|
* @data_len: length of firmware program
|
|
* @ecc_value: store ecc value
|
|
* Output:
|
|
* Return:
|
|
* ecc value calculated in host using XOR8 algorithm
|
|
***********************************************************************/
|
|
static int fts_ecc_cal_host(const uint8_t *data, uint32_t data_len)
|
|
{
|
|
uint8_t ecc = 0;
|
|
uint32_t i = 0;
|
|
|
|
for (i = 0; i < data_len; i++ ) {
|
|
ecc ^= data[i];
|
|
}
|
|
|
|
return ecc;
|
|
}
|
|
|
|
/************************************************************************
|
|
* Name: fts_fwupg_ecc_cal
|
|
* Brief:
|
|
* calculate and get ecc from tp
|
|
* Input: @saddr: start address need calculate ecc
|
|
* @len: length need calculate ecc
|
|
* Output:
|
|
* Return:
|
|
* return data ecc of tp if success, otherwise return error code
|
|
***********************************************************************/
|
|
static int fts_fwupg_ecc_tp(uint32_t saddr, uint16_t len)
|
|
{
|
|
int ret = 0;
|
|
uint8_t wbuf[7] = { 0 };
|
|
uint8_t val[2] = { 0 };
|
|
bool bflag = false;
|
|
uint8_t cmd = 0;
|
|
uint8_t regaddr = 0;
|
|
uint32_t packet_num = 0;
|
|
uint32_t packet_len = 0;
|
|
uint32_t remainder = 0;
|
|
|
|
/* check sum init */
|
|
cmd = FTS_CMD_ECC_INIT;
|
|
ret = ft6146_i2c_write(cmd);
|
|
if (ret < 0) {
|
|
static_print_error("TOUCH: ecc init cmd write fail");
|
|
return ret;
|
|
}
|
|
|
|
packet_num = len / FTS_MAX_LEN_ECC_CALC;
|
|
remainder = len % FTS_MAX_LEN_ECC_CALC;
|
|
if (remainder)
|
|
packet_num++;
|
|
packet_len = FTS_MAX_LEN_ECC_CALC;
|
|
|
|
for(uint32_t i=0;i < packet_num; i++){
|
|
/* send commond to start checksum */
|
|
wbuf[0] = FTS_CMD_ECC_CAL;
|
|
wbuf[1] = (saddr >> 16);
|
|
wbuf[2] = (saddr >> 8);
|
|
wbuf[3] = (saddr);
|
|
wbuf[4] = (len >> 8);
|
|
wbuf[5] = (len );
|
|
|
|
static_print_debug("ecc calc startaddr:0x%04x, len:%d", saddr, len);
|
|
ret = ft6146_data_write(wbuf[0], &wbuf[1] , (FTS_CMD_ECC_CAL_LEN - 1));
|
|
if (ret < 0) {
|
|
static_print_error("TOUCH: ecc calc cmd write fail");
|
|
return ret;
|
|
}
|
|
|
|
tp_delay(len / 256);
|
|
|
|
/* read status if check sum is finished */
|
|
bflag = fts_fwupg_check_flash_status(FTS_CMD_FLASH_STATUS_ECC_OK, FTS_RETRIES_ECC_CAL, FTS_RETRIES_DELAY_ECC_CAL);
|
|
if (!bflag) {
|
|
static_print_error("TOUCH: ecc flash status read fail");
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
/* read out check sum */
|
|
regaddr = FTS_CMD_ECC_READ;
|
|
ret = ft6146_i2c_read(regaddr, val, 1);
|
|
if (ret < 0) {
|
|
static_print_error( "TOUCH: ecc read cmd write fail");
|
|
return ret;
|
|
}
|
|
|
|
return (val[0]);
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* Name: fts_ft3x68_upgrade
|
|
* Brief:
|
|
* Main flow of FT3x68 firmware upgrade.
|
|
* Input: @fw_file: firmware file buffer
|
|
* @fw_file_size: firmware file size
|
|
* Output:
|
|
* Return:
|
|
* Error code if upgrade fails, 0 if success.
|
|
*****************************************************************************/
|
|
static int fts_ft3x68_upgrade(uint8_t *fw_file, uint32_t fw_file_size)
|
|
{
|
|
int ret = 0;
|
|
uint8_t rst_cmd = FTS_CMD_RESET;
|
|
uint8_t cmd[4] = { 0 };
|
|
uint8_t *firmware;
|
|
uint32_t firmware_size;
|
|
uint32_t start_address = 0;
|
|
int ecc_in_host = 0;
|
|
int ecc_in_tp = 0;
|
|
|
|
if (!fw_file || (fw_file_size < FTS_MIN_LEN) || (fw_file_size > (37 * 1024))) {
|
|
static_print_error("TOUCH: fw file is null, or fw file size(%d) is invalid", fw_file_size);
|
|
return -1;
|
|
}
|
|
|
|
/*get firmware data*/
|
|
firmware = fw_file;
|
|
firmware_size = fw_file_size;
|
|
|
|
/*enter into boot environment*/
|
|
ret = fts_fwupg_enter_into_boot();
|
|
if (ret < 0) {
|
|
static_print_error("TOUCH: enter into boot fails");
|
|
goto err_upgrade;
|
|
}
|
|
#if 0
|
|
/*send firmware size*/
|
|
cmd[0] = FTS_CMD_APP_DATA_LEN;
|
|
cmd[1] = (firmware_size >> 16);
|
|
cmd[2] = (firmware_size >> 8);
|
|
cmd[3] = (firmware_size);
|
|
ret = ft6146_data_write(cmd[0], &cmd[1], 3);
|
|
if (ret < 0) {
|
|
static_print_error("TOUCH: write 7A fails");
|
|
return ret;
|
|
}
|
|
|
|
#endif
|
|
/*Erase firmware part in flash*/
|
|
ret = ft6146_reg_write(FTS_CMD_FLASH_MODE, FTS_FLASH_MODE_UPGRADE_VALUE);
|
|
if (ret < 0) {
|
|
static_print_error("TOUCH: upgrade mode(09) cmd write fail");
|
|
goto err_upgrade;
|
|
}
|
|
|
|
ret = fts_fwupg_erase(60 * (firmware_size / 4096));
|
|
if (ret < 0) {
|
|
static_print_error("TOUCH: erase cmd write fail");
|
|
goto err_upgrade;
|
|
}
|
|
|
|
/*write firmware data into flash*/
|
|
start_address = FTS_CMD_FW_START_ADDRESS;
|
|
ret = fts_flash_write_buf(start_address, firmware, firmware_size, 1);
|
|
if (ret < 0 ) {
|
|
static_print_error("TOUCH: write buffer to flash fail");
|
|
goto err_upgrade;
|
|
}
|
|
|
|
ecc_in_host = fts_ecc_cal_host(firmware, firmware_size);
|
|
ecc_in_tp = fts_fwupg_ecc_tp(start_address, firmware_size);
|
|
static_print_info("TOUCH: ecc in tp:%x, host:%x", ecc_in_tp, ecc_in_host);
|
|
if (ecc_in_tp != ecc_in_host) {
|
|
static_print_error("TOUCH: ecc check fail");
|
|
goto err_upgrade;
|
|
}
|
|
|
|
static_print_info("TOUCH: upgrade success, reset to normal boot");
|
|
ret = ft6146_i2c_write(rst_cmd);
|
|
if (ret < 0) {
|
|
static_print_error("TOUCH: reset to normal boot fail");
|
|
}
|
|
tp_delay(FTS_DELAY_UPGRADE_RESET);
|
|
|
|
return 0;
|
|
|
|
err_upgrade:
|
|
ret = ft6146_i2c_write(rst_cmd);
|
|
if (ret < 0) {
|
|
static_print_error("TOUCH: reset to normal boot fail");
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* Name: fts_fwupg_check_fw_valid
|
|
* Brief:
|
|
* To check firmware in TP controller is valid or not.
|
|
* Input:
|
|
* Output:
|
|
* Return:
|
|
* true: fw is valid, false: fw is invalid
|
|
*****************************************************************************/
|
|
static bool fts_fwupg_check_fw_valid(void)
|
|
{
|
|
int ret = 0;
|
|
int i = 0;
|
|
uint8_t id = 0xFF;
|
|
|
|
do {
|
|
/*loop to read ID because some time is needed for TP controller initialization*/
|
|
ret = ft6146_i2c_read(FTS_REG_CHIP_ID, &id, 1);
|
|
if (id == FTS_CHIP_IDH) {
|
|
static_print_debug("TOUCH: TP Ready,Device ID:0x%02x", id);
|
|
return true;
|
|
} else {
|
|
static_print_debug("TOUCH: TP Not Ready,Read:0x%02x,ret:%d", id, ret);
|
|
}
|
|
tp_delay(INTERVAL_READ_REG);
|
|
} while (i++ < 5);
|
|
|
|
return false;
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* Name: fts_fwupg_need_upgrade
|
|
* Brief:
|
|
* To check firmware upgrade is needed or not. Host need upgrade firmware in
|
|
* the following situations(one of them):
|
|
* a. firwmare in TP controller is invalid.
|
|
* b. firmware versions in TP controller and host are different.
|
|
* Input: @fw_file: firmware file buffer
|
|
* @fw_file_size: firmware file size
|
|
* Output:
|
|
* Return:
|
|
* true: firmware upgrade is needed, false: not needed
|
|
*****************************************************************************/
|
|
static bool fts_fwupg_need_upgrade(uint8_t *fw_file, uint32_t fw_file_size)
|
|
{
|
|
int ret = 0;
|
|
uint8_t fw_ver_in_host = 0;
|
|
uint8_t fw_ver_in_tp = 0;
|
|
|
|
if (!tp_fw_valid) {
|
|
static_print_debug("TOUCH: firmware in TP controller is invalid, need upgrade");
|
|
return true;
|
|
}
|
|
|
|
ret = ft6146_i2c_read(FTS_REG_FW_VER, &fw_ver_in_tp, 1);
|
|
if (ret < 0) {
|
|
static_print_error("TOUCH: read firmware version from reg0xA6 fals");
|
|
return false;
|
|
}
|
|
|
|
if (fw_file_size > FTS_MIN_LEN)
|
|
fw_ver_in_host = fw_file[FTS_VER_IN_FILE_ADDR];
|
|
static_print_info("TOUCH: fw version in tp:%x, host:%x", fw_ver_in_tp, fw_ver_in_host);
|
|
if (fw_ver_in_tp != fw_ver_in_host) {
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* Name: fts_fwupg_upgrade
|
|
* Brief:
|
|
* The whole flow of firmware upgrade.
|
|
* Input: @fw_file: firmware file buffer
|
|
* @fw_file_size: firmware file size
|
|
* Output:
|
|
* Return:
|
|
* Error code if upgrade fails, 0 if success.
|
|
*****************************************************************************/
|
|
static int fts_fwupg_upgrade(uint8_t *fw_file, uint32_t fw_file_size)
|
|
{
|
|
int ret = 0;
|
|
bool upgrade_flag = false;
|
|
uint8_t fw_ver = 0;
|
|
uint8_t upgrade_count = 0;
|
|
|
|
/*check firmware upgrade is needed or not*/
|
|
upgrade_flag = fts_fwupg_need_upgrade(fw_file, fw_file_size);
|
|
static_print_info("TOUCH: fw upgrade flag:%d", upgrade_flag);
|
|
if (upgrade_flag) {
|
|
do {
|
|
upgrade_count++;
|
|
ret = fts_ft3x68_upgrade(fw_file, fw_file_size);
|
|
if (ret >= 0) {
|
|
ft6146_i2c_read(FTS_REG_FW_VER, &fw_ver, 1);
|
|
static_print_info("TOUCH: success upgrade to fw version %02x", fw_ver);
|
|
break;
|
|
}
|
|
} while (upgrade_count < FTS_RETRIES_UPGRADE);
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* Name: fts_fwupg_auto_upgrade
|
|
* Brief:
|
|
* firmware auto upgrade.
|
|
* Input:
|
|
* Output:
|
|
* Return:
|
|
* Error code if auto upgrade fails, 0 if success.
|
|
*****************************************************************************/
|
|
int fts_fwupg_auto_upgrade(void)
|
|
{
|
|
int ret = 0;
|
|
uint8_t *fw_file = fw_file_ft3x68;
|
|
uint32_t fw_file_size = sizeof(fw_file_ft3x68);
|
|
|
|
static_print_info("********************auto upgrade********************");
|
|
/* Get firmware file, and check firmware size
|
|
* we use all.i as an example(variable fw_file_ft3x68 stores the firmware).
|
|
* You should read it if you use all.bin
|
|
*/
|
|
|
|
if (!fw_file || (fw_file_size < FTS_MIN_LEN)) {
|
|
static_print_error("TOUCH: fw_file is null, or firmare file size(%d) is invalid", fw_file_size);
|
|
return -1;
|
|
}
|
|
|
|
/*check firmware is valid or not*/
|
|
tp_fw_valid = fts_fwupg_check_fw_valid();
|
|
if (!tp_fw_valid) {
|
|
static_print_debug("TOUCH: firmware in flash is invalid");
|
|
}
|
|
|
|
/******run firmware upgrade flow******/
|
|
ret = fts_fwupg_upgrade(fw_file, fw_file_size);
|
|
if (ret < 0){
|
|
static_print_error("**********tp fw upgrade fails**********");
|
|
}else{
|
|
static_print_info("**********tp fw no upgrade/upgrade success**********");
|
|
}
|
|
|
|
return ret;
|
|
}
|