147 lines
3.3 KiB
C
147 lines
3.3 KiB
C
/* SPDX-License-Identifier: GPL-2.0 */
|
|
/*
|
|
* Copyright (C) 2016 MediaTek Inc.
|
|
*/
|
|
|
|
#include "../focaltech_flash.h"
|
|
|
|
static int fts_ft5452_upgrade(u8 *buf, u32 len)
|
|
{
|
|
int ret = 0;
|
|
u32 start_addr = 0;
|
|
u8 cmd[4] = { 0 };
|
|
int ecc_in_host = 0;
|
|
int ecc_in_tp = 0;
|
|
|
|
int i = 0;
|
|
u8 wbuf[7] = { 0 };
|
|
u8 reg_val[4] = {0};
|
|
|
|
if (buf == NULL) {
|
|
FTS_ERROR("fw buf is null");
|
|
return -EINVAL;
|
|
}
|
|
|
|
if ((len < FTS_MIN_LEN) || (len > (60 * 1024))) {
|
|
FTS_ERROR("fw buffer len(%x) fail", len);
|
|
return -EINVAL;
|
|
}
|
|
|
|
/* enter into upgrade environment */
|
|
ret = fts_fwupg_enter_into_boot();
|
|
if (ret < 0) {
|
|
FTS_ERROR("enter into pramboot/bootloader fail,ret=%d", ret);
|
|
goto fw_reset;
|
|
}
|
|
|
|
cmd[0] = FTS_CMD_FLASH_MODE;
|
|
cmd[1] = FLASH_MODE_UPGRADE_VALUE;
|
|
ret = fts_write(cmd, 2);
|
|
if (ret < 0) {
|
|
FTS_ERROR("upgrade mode(09) cmd write fail");
|
|
goto fw_reset;
|
|
}
|
|
|
|
cmd[0] = FTS_CMD_DATA_LEN;
|
|
cmd[1] = BYTE_OFF_16(len);
|
|
cmd[2] = BYTE_OFF_8(len);
|
|
cmd[3] = BYTE_OFF_0(len);
|
|
ret = fts_write(cmd, FTS_CMD_DATA_LEN_LEN);
|
|
if (ret < 0) {
|
|
FTS_ERROR("data len cmd write fail");
|
|
goto fw_reset;
|
|
}
|
|
|
|
ret = fts_fwupg_erase(FTS_REASE_APP_DELAY);
|
|
if (ret < 0) {
|
|
FTS_ERROR("erase cmd write fail");
|
|
goto fw_reset;
|
|
}
|
|
|
|
/* write app */
|
|
start_addr = upgrade_func_ft5452.appoff;
|
|
ecc_in_host = fts_flash_write_buf(start_addr, buf, len, 1);
|
|
if (ecc_in_host < 0) {
|
|
FTS_ERROR("lcd initial code write fail");
|
|
goto fw_reset;
|
|
}
|
|
|
|
FTS_INFO("**********read out checksum**********");
|
|
|
|
/* check sum init */
|
|
wbuf[0] = FTS_CMD_ECC_INIT;
|
|
ret = fts_write(wbuf, 1);
|
|
if (ret < 0) {
|
|
FTS_ERROR("ecc init cmd write fail");
|
|
return ret;
|
|
}
|
|
|
|
/* send commond to start checksum */
|
|
wbuf[0] = FTS_CMD_ECC_CAL;
|
|
wbuf[1] = BYTE_OFF_16(start_addr);
|
|
wbuf[2] = BYTE_OFF_8(start_addr);
|
|
wbuf[3] = BYTE_OFF_0(start_addr);
|
|
|
|
wbuf[4] = BYTE_OFF_16(len);
|
|
wbuf[5] = BYTE_OFF_8(len);
|
|
wbuf[6] = BYTE_OFF_0(len);
|
|
|
|
FTS_DEBUG("ecc calc startaddr:0x%04x, len:%d", start_addr, len);
|
|
ret = fts_write(wbuf, 7);
|
|
if (ret < 0) {
|
|
FTS_ERROR("ecc calc cmd write fail");
|
|
return ret;
|
|
}
|
|
|
|
msleep(len / 256);
|
|
|
|
/* read status if check sum is finished */
|
|
for (i = 0; i < FTS_RETRIES_ECC_CAL; i++) {
|
|
wbuf[0] = FTS_CMD_FLASH_STATUS;
|
|
reg_val[0] = reg_val[1] = 0x00;
|
|
fts_read(wbuf, 1, reg_val, 2);
|
|
FTS_DEBUG("[UPGRADE]: reg_val[0]=%02x reg_val[0]=%02x!!", reg_val[0], reg_val[1]);
|
|
if ((reg_val[0] == 0xF0) && (reg_val[1] == 0x55))
|
|
break;
|
|
msleep(FTS_RETRIES_DELAY_ECC_CAL);
|
|
}
|
|
|
|
/* read out check sum */
|
|
wbuf[0] = FTS_CMD_ECC_READ;
|
|
ret = fts_read(wbuf, 1, reg_val, 1);
|
|
if (ret < 0) {
|
|
FTS_ERROR("ecc read cmd write fail");
|
|
return ret;
|
|
}
|
|
ecc_in_tp = reg_val[0];
|
|
FTS_INFO("ecc in tp:%x, host:%x", ecc_in_tp, ecc_in_host);
|
|
if (ecc_in_tp != ecc_in_host) {
|
|
FTS_ERROR("ecc check fail");
|
|
goto fw_reset;
|
|
}
|
|
|
|
FTS_INFO("upgrade success, reset to normal boot");
|
|
ret = fts_fwupg_reset_in_boot();
|
|
if (ret < 0)
|
|
FTS_ERROR("reset to normal boot fail");
|
|
msleep(200);
|
|
return 0;
|
|
|
|
fw_reset:
|
|
FTS_INFO("upgrade fail, reset to normal boot");
|
|
ret = fts_fwupg_reset_in_boot();
|
|
if (ret < 0)
|
|
FTS_ERROR("reset to normal boot fail");
|
|
return -EIO;
|
|
}
|
|
|
|
struct upgrade_func upgrade_func_ft5452 = {
|
|
.ctype = {0x81},
|
|
.fwveroff = 0x010E,
|
|
.fwcfgoff = 0x1FFB0,
|
|
.appoff = 0x0000,
|
|
.pramboot_supported = false,
|
|
.hid_supported = true,
|
|
.upgrade = fts_ft5452_upgrade,
|
|
};
|