mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-15 01:01:56 -04:00
defender: TP: Seperate focaltech_flash.c
TP: Download function for different touch IC is different. Seperate flash function info common part and IC unique part Change-Id: I31637e889e2d0cb789d53d21418e1f3a1532ae12 Signed-off-by: haojl2 <haojl2@motorola.com> Reviewed-on: https://gerrit.mot.com/1369612 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Guobin Zhang <zhanggb@motorola.com> Submit-Approved: Jira Key Reviewed-on: https://gerrit.mot.com/1371168 Reviewed-by: Jianqi Yang <yangj@motorola.com> Reviewed-on: https://gerrit.mot.com/1371912
This commit is contained in:
parent
fd3d2b00a6
commit
409f18bb04
5 changed files with 835 additions and 331 deletions
|
|
@ -20,8 +20,10 @@ focaltech_0flash_mmi-objs += focaltech_test/focaltech_test_ini.o
|
|||
ifneq ($(filter ft8719,$(CONFIG_INPUT_FOCALTECH_0FLASH_MMI_IC_NAME)),)
|
||||
EXTRA_CFLAGS += -DCONFIG_INPUT_FOCALTECH_0FLASH_MMI_IC_NAME_FT8719
|
||||
focaltech_0flash_mmi-objs += focaltech_test/supported_ic/focaltech_test_ft8719.o
|
||||
focaltech_0flash_mmi-objs += focaltech_flash_ft8719.o
|
||||
endif
|
||||
ifneq ($(filter ft8756,$(CONFIG_INPUT_FOCALTECH_0FLASH_MMI_IC_NAME)),)
|
||||
EXTRA_CFLAGS += -DCONFIG_INPUT_FOCALTECH_0FLASH_MMI_IC_NAME_FT8756
|
||||
focaltech_0flash_mmi-objs += focaltech_test/supported_ic/focaltech_test_ft8756.o
|
||||
focaltech_0flash_mmi-objs += focaltech_flash_ft8756.o
|
||||
endif
|
||||
|
|
|
|||
|
|
@ -41,9 +41,6 @@
|
|||
#define FTS_FW_REQUEST_SUPPORT 1
|
||||
/* Example: focaltech_ts_fw_tianma.bin */
|
||||
#define FTS_FW_NAME_PREX_WITH_REQUEST ""
|
||||
#define FTS_READ_BOOT_ID_TIMEOUT 3
|
||||
#define FTS_FLASH_PACKET_LENGTH_SPI_LOW (4 * 1024 - 4)
|
||||
#define FTS_FLASH_PACKET_LENGTH_SPI (64 * 1024)
|
||||
|
||||
/*****************************************************************************
|
||||
* Global variable or extern global variabls/functions
|
||||
|
|
@ -65,7 +62,7 @@ struct upgrade_module module_list[] = {
|
|||
|
||||
struct fts_upgrade *fwupgrade;
|
||||
|
||||
static int fts_check_bootid(void)
|
||||
int fts_check_bootid(void)
|
||||
{
|
||||
int ret = 0;
|
||||
u8 cmd = 0;
|
||||
|
|
@ -87,323 +84,6 @@ static int fts_check_bootid(void)
|
|||
return -EIO;
|
||||
}
|
||||
|
||||
static int fts_fwupg_hardware_reset_to_boot(void)
|
||||
{
|
||||
fts_reset_proc(0);
|
||||
mdelay(8);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int fts_enter_into_boot(void)
|
||||
{
|
||||
int ret = 0;
|
||||
int i = 0;
|
||||
int j = 0;
|
||||
u8 cmd = 0;
|
||||
|
||||
FTS_INFO("enter into boot environment");
|
||||
for (i = 0; i < FTS_UPGRADE_LOOP; i++) {
|
||||
/* hardware tp reset to boot */
|
||||
fts_fwupg_hardware_reset_to_boot();
|
||||
|
||||
/* enter into boot & check boot id*/
|
||||
for (j = 0; j < FTS_READ_BOOT_ID_TIMEOUT; j++) {
|
||||
cmd = FTS_CMD_START1;
|
||||
ret = fts_write(&cmd, 1);
|
||||
if (ret >= 0) {
|
||||
mdelay(8);
|
||||
ret = fts_check_bootid();
|
||||
if (0 == ret) {
|
||||
FTS_INFO("boot id check pass, retry=%d", i);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
static bool fts_check_fast_download(void)
|
||||
{
|
||||
int ret = 0;
|
||||
u8 cmd[6] = {0xF2, 0x00, 0x78, 0x0A, 0x00, 0x02};
|
||||
u8 value = 0;
|
||||
u8 value2[2] = { 0 };
|
||||
|
||||
ret = fts_read_reg(0xdb, &value);
|
||||
if (ret < 0) {
|
||||
FTS_ERROR("read 0xdb fail");
|
||||
goto read_err;
|
||||
}
|
||||
|
||||
ret = fts_read(cmd, 6, value2, 2);
|
||||
if (ret < 0) {
|
||||
FTS_ERROR("read f2 fail");
|
||||
goto read_err;
|
||||
}
|
||||
|
||||
FTS_INFO("0xdb = 0x%x, 0xF2 = 0x%x", value, value2[0]);
|
||||
if ((value >= 0x18) && (value2[0] == 0x55)) {
|
||||
FTS_INFO("IC support fast-download");
|
||||
return true;
|
||||
}
|
||||
|
||||
read_err:
|
||||
FTS_INFO("IC not support fast-download");
|
||||
return false;
|
||||
}
|
||||
|
||||
static int fts_pram_write(u32 saddr, const u8 *buf, u32 len)
|
||||
{
|
||||
int ret = 0;
|
||||
int i = 0;
|
||||
int j = 0;
|
||||
u8 *cmd;
|
||||
u32 addr = 0;
|
||||
u32 offset = 0;
|
||||
u32 remainder = 0;
|
||||
u32 packet_number;
|
||||
u32 packet_len = 0;
|
||||
u32 packet_size = FTS_FLASH_PACKET_LENGTH_SPI;
|
||||
bool fd_support = true;
|
||||
|
||||
FTS_INFO("pram write");
|
||||
if (NULL == buf) {
|
||||
FTS_ERROR("fw buf is null");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if ((len < FTS_MIN_LEN) || (len > FTS_MAX_LEN_APP)) {
|
||||
FTS_ERROR("fw length(%d) fail", len);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
fd_support = fts_check_fast_download();
|
||||
if (!fd_support)
|
||||
packet_size = FTS_FLASH_PACKET_LENGTH_SPI_LOW;
|
||||
cmd = kzalloc(packet_size + FTS_CMD_WRITE_LEN, GFP_KERNEL);
|
||||
if (NULL == cmd) {
|
||||
FTS_ERROR("malloc memory for pram write buffer fail");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
packet_number = len / packet_size;
|
||||
remainder = len % packet_size;
|
||||
if (remainder > 0)
|
||||
packet_number++;
|
||||
packet_len = packet_size;
|
||||
|
||||
cmd[0] = FTS_ROMBOOT_CMD_WRITE;
|
||||
for (i = 0; i < packet_number; i++) {
|
||||
offset = i * packet_size;
|
||||
addr = saddr + offset;
|
||||
cmd[1] = BYTE_OFF_16(addr);
|
||||
cmd[2] = BYTE_OFF_8(addr);
|
||||
cmd[3] = BYTE_OFF_0(addr);
|
||||
|
||||
/* last packet */
|
||||
if ((i == (packet_number - 1)) && remainder)
|
||||
packet_len = remainder;
|
||||
cmd[4] = BYTE_OFF_8(packet_len);
|
||||
cmd[5] = BYTE_OFF_0(packet_len);
|
||||
|
||||
for (j = 0; j < packet_len; j++) {
|
||||
cmd[FTS_CMD_WRITE_LEN + j] = buf[offset + j];
|
||||
}
|
||||
ret = fts_write(&cmd[0], FTS_CMD_WRITE_LEN + packet_len);
|
||||
if (ret < 0) {
|
||||
FTS_ERROR("write fw to pram(%d) fail", i);
|
||||
goto write_pram_err;
|
||||
}
|
||||
|
||||
if (!fd_support)
|
||||
mdelay(3);
|
||||
}
|
||||
|
||||
write_pram_err:
|
||||
if (cmd) {
|
||||
kfree(cmd);
|
||||
cmd = NULL;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int fts_ecc_cal_tp(u32 ecc_saddr, u32 ecc_len, u16 *ecc_value)
|
||||
{
|
||||
int ret = 0;
|
||||
int i = 0;
|
||||
u8 cmd[FTS_ROMBOOT_CMD_ECC_NEW_LEN] = { 0 };
|
||||
u8 value[2] = { 0 };
|
||||
|
||||
FTS_INFO("ecc calc in tp");
|
||||
cmd[0] = FTS_ROMBOOT_CMD_ECC;
|
||||
cmd[1] = BYTE_OFF_16(ecc_saddr);
|
||||
cmd[2] = BYTE_OFF_8(ecc_saddr);
|
||||
cmd[3] = BYTE_OFF_0(ecc_saddr);
|
||||
cmd[4] = BYTE_OFF_16(ecc_len);
|
||||
cmd[5] = BYTE_OFF_8(ecc_len);
|
||||
cmd[6] = BYTE_OFF_0(ecc_len);
|
||||
|
||||
/* make boot to calculate ecc in pram */
|
||||
ret = fts_write(cmd, FTS_ROMBOOT_CMD_ECC_NEW_LEN);
|
||||
if (ret < 0) {
|
||||
FTS_ERROR("ecc calc cmd fail");
|
||||
return ret;
|
||||
}
|
||||
mdelay(3);
|
||||
|
||||
/* wait boot calculate ecc finish */
|
||||
cmd[0] = FTS_ROMBOOT_CMD_ECC_FINISH;
|
||||
for (i = 0; i < FTS_ECC_FINISH_TIMEOUT; i++) {
|
||||
ret = fts_read(cmd, 1, value, 1);
|
||||
if (ret < 0) {
|
||||
FTS_ERROR("ecc finish cmd fail");
|
||||
return ret;
|
||||
}
|
||||
if (0 == value[0])
|
||||
break;
|
||||
mdelay(1);
|
||||
}
|
||||
if (i >= FTS_ECC_FINISH_TIMEOUT) {
|
||||
FTS_ERROR("wait ecc finish timeout");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/* get ecc value calculate in boot */
|
||||
cmd[0] = FTS_ROMBOOT_CMD_ECC_READ;
|
||||
ret = fts_read(cmd, 1, value, 2);
|
||||
if (ret < 0) {
|
||||
FTS_ERROR("ecc read cmd fail");
|
||||
return ret;
|
||||
}
|
||||
|
||||
*ecc_value = ((u16)(value[0] << 8) + value[1]) & 0x0000FFFF;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int fts_ecc_cal_host(const u8 *data, u32 data_len, u16 *ecc_value)
|
||||
{
|
||||
u16 ecc = 0;
|
||||
u16 i = 0;
|
||||
u16 j = 0;
|
||||
u16 al2_fcs_coef = AL2_FCS_COEF;
|
||||
|
||||
for (i = 0; i < data_len; i += 2 ) {
|
||||
ecc ^= ((data[i] << 8) | (data[i + 1]));
|
||||
for (j = 0; j < 16; j ++) {
|
||||
if (ecc & 0x01)
|
||||
ecc = (u16)((ecc >> 1) ^ al2_fcs_coef);
|
||||
else
|
||||
ecc >>= 1;
|
||||
}
|
||||
}
|
||||
|
||||
*ecc_value = ecc & 0x0000FFFF;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int fts_pram_start(void)
|
||||
{
|
||||
int ret = 0;
|
||||
u8 cmd = FTS_ROMBOOT_CMD_START_APP;
|
||||
|
||||
FTS_INFO("remap to start pram");
|
||||
ret = fts_write(&cmd, 1);
|
||||
if (ret < 0) {
|
||||
FTS_ERROR("write start pram cmd fail");
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* description: download fw to IC and run
|
||||
*
|
||||
* param - buf: const, fw data buffer
|
||||
* len: length of fw
|
||||
*
|
||||
* return 0 if success, otherwise return error code
|
||||
*/
|
||||
static int fts_fw_write_start(const u8 *buf, u32 len, bool need_reset)
|
||||
{
|
||||
int ret = 0;
|
||||
u16 ecc_in_host = 0;
|
||||
u16 ecc_in_tp = 0;
|
||||
u32 fw_start_addr = 0;
|
||||
u32 fw_len = 0;
|
||||
u16 code_len = 0;
|
||||
u16 code_len_n = 0;
|
||||
|
||||
FTS_INFO("begin to write and start fw(bin len:%d)", len);
|
||||
/* get app length */
|
||||
code_len = ((u16)buf[FTS_APP_INFO_OFFSET + 0] << 8)
|
||||
+ buf[FTS_APP_INFO_OFFSET + 1];
|
||||
code_len_n = ((u16)buf[FTS_APP_INFO_OFFSET + 2] << 8)
|
||||
+ buf[FTS_APP_INFO_OFFSET + 3];
|
||||
if ((code_len + code_len_n) != 0xFFFF) {
|
||||
FTS_ERROR("code len(%x %x) fail", code_len, code_len_n);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
fw_len = (u32)code_len;
|
||||
if ((fw_len < FTS_MIN_LEN) || (fw_len > FTS_MAX_LEN_APP)) {
|
||||
FTS_ERROR("fw length(%d) is invalid", fw_len);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
FTS_INFO("fw length in fact:%d", fw_len);
|
||||
fts_data->fw_is_running = false;
|
||||
|
||||
if (need_reset) {
|
||||
/* enter into boot environment */
|
||||
ret = fts_enter_into_boot();
|
||||
if (ret < 0) {
|
||||
FTS_ERROR("enter into boot environment fail");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
/* write pram */
|
||||
ret = fts_pram_write(fw_start_addr, buf, fw_len);
|
||||
if (ret < 0) {
|
||||
FTS_ERROR("write pram fail");
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* ecc check */
|
||||
ret = fts_ecc_cal_host(buf, fw_len, &ecc_in_host);
|
||||
if (ret < 0) {
|
||||
FTS_ERROR("ecc in host calc fail");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = fts_ecc_cal_tp(fw_start_addr, fw_len, &ecc_in_tp);
|
||||
if (ret < 0) {
|
||||
FTS_ERROR("ecc in tp calc fail");
|
||||
return ret;
|
||||
}
|
||||
|
||||
FTS_INFO("ecc in tp:%04x host:%04x", ecc_in_tp, ecc_in_host);
|
||||
if (ecc_in_tp != ecc_in_host) {
|
||||
FTS_ERROR("ecc check fail");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/* remap pram and run fw */
|
||||
ret = fts_pram_start();
|
||||
if (ret < 0) {
|
||||
FTS_ERROR("pram start fail");
|
||||
return ret;
|
||||
}
|
||||
|
||||
fts_data->fw_is_running = true;
|
||||
FTS_INFO("fw download successfully");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int fts_fw_download(const u8 *buf, u32 len, bool need_reset)
|
||||
{
|
||||
int ret = 0;
|
||||
|
|
@ -428,21 +108,24 @@ static int fts_fw_download(const u8 *buf, u32 len, bool need_reset)
|
|||
if (0 == ret)
|
||||
break;
|
||||
}
|
||||
if (i >= 3) {
|
||||
FTS_ERROR("fw download fail");
|
||||
ret = -EIO;
|
||||
goto err_fw_download;
|
||||
}
|
||||
|
||||
#if FTS_ESDCHECK_EN
|
||||
fts_esdcheck_switch(ENABLE);
|
||||
#endif
|
||||
|
||||
ret = 0;
|
||||
err_fw_download:
|
||||
fts_irq_enable();
|
||||
ts_data->fw_loading = 0;
|
||||
|
||||
if (i >= 3) {
|
||||
FTS_ERROR("fw download fail");
|
||||
return -EIO;
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int fts_read_file(char *file_name, u8 **file_buf)
|
||||
{
|
||||
int ret = 0;
|
||||
|
|
@ -542,8 +225,8 @@ int fts_enter_test_environment(bool test_state)
|
|||
struct fts_upgrade *upg = fwupgrade;
|
||||
|
||||
FTS_INFO("fw test download function");
|
||||
if (!upg || !upg->fw) {
|
||||
FTS_ERROR("upg/fw is null");
|
||||
if (!upg) {
|
||||
FTS_ERROR("upg is null");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
|
@ -552,7 +235,7 @@ int fts_enter_test_environment(bool test_state)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (upg->fw_length <= FTS_MAX_LEN_APP) {
|
||||
if (!upg->fw || (upg->fw_length <= FTS_MAX_LEN_APP)) {
|
||||
FTS_INFO("not multi-app");
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -668,10 +351,11 @@ int fts_fw_recovery(void)
|
|||
ret = fts_read_reg(0xD0, &boot_state);
|
||||
if (ret < 0) {
|
||||
FTS_ERROR("read boot state failed, ret=%d", ret);
|
||||
upg->ts_data->fw_is_running = true;
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (boot_state != 0x02) {
|
||||
if (boot_state != 0x01) {
|
||||
FTS_INFO("not in boot mode(0x%x),exit", boot_state);
|
||||
upg->ts_data->fw_is_running = true;
|
||||
return -EIO;
|
||||
|
|
@ -906,6 +590,10 @@ int fts_fwupg_init(struct fts_ts_data *ts_data)
|
|||
return -ENOMEM;
|
||||
}
|
||||
|
||||
#if FTS_ESDCHECK_EN
|
||||
fts_esdcheck_switch(DISABLE);
|
||||
#endif
|
||||
|
||||
fwupgrade->ts_data = ts_data;
|
||||
INIT_WORK(&ts_data->fwupg_work, fts_fwupg_work);
|
||||
queue_work(ts_data->ts_workqueue, &ts_data->fwupg_work);
|
||||
|
|
|
|||
|
|
@ -176,6 +176,8 @@ struct fts_upgrade {
|
|||
/*****************************************************************************
|
||||
* Global variable or extern global variabls/functions
|
||||
*****************************************************************************/
|
||||
int fts_check_bootid(void);
|
||||
int fts_fw_write_start(const u8 *buf, u32 len, bool need_reset);
|
||||
|
||||
/*****************************************************************************
|
||||
* Static function prototypes
|
||||
|
|
|
|||
364
drivers/input/touchscreen/focaltech_0flash_mmi/focaltech_flash_ft8719.c
Executable file
364
drivers/input/touchscreen/focaltech_0flash_mmi/focaltech_flash_ft8719.c
Executable file
|
|
@ -0,0 +1,364 @@
|
|||
/*
|
||||
*
|
||||
* FocalTech fts TouchScreen driver.
|
||||
*
|
||||
* Copyright (c) 2012-2019, Focaltech Ltd. All rights reserved.
|
||||
*
|
||||
* This software is licensed under the terms of the GNU General Public
|
||||
* License version 2, as published by the Free Software Foundation, and
|
||||
* may be copied, distributed, and modified under those terms.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* File Name: focaltech_flash.c
|
||||
*
|
||||
* Author: Focaltech Driver Team
|
||||
*
|
||||
* Created: 2017-12-06
|
||||
*
|
||||
* Abstract:
|
||||
*
|
||||
* Reference:
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
/*****************************************************************************
|
||||
* 1.Included header files
|
||||
*****************************************************************************/
|
||||
#include "focaltech_core.h"
|
||||
#include "focaltech_flash.h"
|
||||
|
||||
/*****************************************************************************
|
||||
* Static variables
|
||||
*****************************************************************************/
|
||||
#define FTS_READ_BOOT_ID_TIMEOUT 3
|
||||
#define FTS_FLASH_PACKET_LENGTH_SPI_LOW (4 * 1024 - 4)
|
||||
#define FTS_FLASH_PACKET_LENGTH_SPI (64 * 1024)
|
||||
|
||||
/*****************************************************************************
|
||||
* Global variable or extern global variabls/functions
|
||||
*****************************************************************************/
|
||||
static int fts_fwupg_hardware_reset_to_boot(void)
|
||||
{
|
||||
fts_reset_proc(0);
|
||||
mdelay(8);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int fts_enter_into_boot(void)
|
||||
{
|
||||
int ret = 0;
|
||||
int i = 0;
|
||||
int j = 0;
|
||||
u8 cmd = 0;
|
||||
|
||||
FTS_INFO("enter into boot environment");
|
||||
for (i = 0; i < FTS_UPGRADE_LOOP; i++) {
|
||||
/* hardware tp reset to boot */
|
||||
fts_fwupg_hardware_reset_to_boot();
|
||||
|
||||
/* enter into boot & check boot id*/
|
||||
for (j = 0; j < FTS_READ_BOOT_ID_TIMEOUT; j++) {
|
||||
cmd = FTS_CMD_START1;
|
||||
ret = fts_write(&cmd, 1);
|
||||
if (ret >= 0) {
|
||||
mdelay(8);
|
||||
ret = fts_check_bootid();
|
||||
if (0 == ret) {
|
||||
FTS_INFO("boot id check pass, retry=%d", i);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
static bool fts_check_fast_download(void)
|
||||
{
|
||||
int ret = 0;
|
||||
u8 cmd[6] = {0xF2, 0x00, 0x78, 0x0A, 0x00, 0x02};
|
||||
u8 value = 0;
|
||||
u8 value2[2] = { 0 };
|
||||
|
||||
ret = fts_read_reg(0xdb, &value);
|
||||
if (ret < 0) {
|
||||
FTS_ERROR("read 0xdb fail");
|
||||
goto read_err;
|
||||
}
|
||||
|
||||
ret = fts_read(cmd, 6, value2, 2);
|
||||
if (ret < 0) {
|
||||
FTS_ERROR("read f2 fail");
|
||||
goto read_err;
|
||||
}
|
||||
|
||||
FTS_INFO("0xdb = 0x%x, 0xF2 = 0x%x", value, value2[0]);
|
||||
if ((value >= 0x18) && (value2[0] == 0x55)) {
|
||||
FTS_INFO("IC support fast-download");
|
||||
return true;
|
||||
}
|
||||
|
||||
read_err:
|
||||
FTS_INFO("IC not support fast-download");
|
||||
return false;
|
||||
}
|
||||
|
||||
static int fts_pram_write(u32 saddr, const u8 *buf, u32 len)
|
||||
{
|
||||
int ret = 0;
|
||||
int i = 0;
|
||||
int j = 0;
|
||||
u8 *cmd;
|
||||
u32 addr = 0;
|
||||
u32 offset = 0;
|
||||
u32 remainder = 0;
|
||||
u32 packet_number;
|
||||
u32 packet_len = 0;
|
||||
u32 packet_size = FTS_FLASH_PACKET_LENGTH_SPI;
|
||||
bool fd_support = true;
|
||||
|
||||
FTS_INFO("pram write");
|
||||
if (NULL == buf) {
|
||||
FTS_ERROR("fw buf is null");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if ((len < FTS_MIN_LEN) || (len > FTS_MAX_LEN_APP)) {
|
||||
FTS_ERROR("fw length(%d) fail", len);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
fd_support = fts_check_fast_download();
|
||||
if (!fd_support)
|
||||
packet_size = FTS_FLASH_PACKET_LENGTH_SPI_LOW;
|
||||
cmd = kzalloc(packet_size + FTS_CMD_WRITE_LEN, GFP_KERNEL);
|
||||
if (NULL == cmd) {
|
||||
FTS_ERROR("malloc memory for pram write buffer fail");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
packet_number = len / packet_size;
|
||||
remainder = len % packet_size;
|
||||
if (remainder > 0)
|
||||
packet_number++;
|
||||
packet_len = packet_size;
|
||||
|
||||
cmd[0] = FTS_ROMBOOT_CMD_WRITE;
|
||||
for (i = 0; i < packet_number; i++) {
|
||||
offset = i * packet_size;
|
||||
addr = saddr + offset;
|
||||
cmd[1] = BYTE_OFF_16(addr);
|
||||
cmd[2] = BYTE_OFF_8(addr);
|
||||
cmd[3] = BYTE_OFF_0(addr);
|
||||
|
||||
/* last packet */
|
||||
if ((i == (packet_number - 1)) && remainder)
|
||||
packet_len = remainder;
|
||||
cmd[4] = BYTE_OFF_8(packet_len);
|
||||
cmd[5] = BYTE_OFF_0(packet_len);
|
||||
|
||||
for (j = 0; j < packet_len; j++) {
|
||||
cmd[FTS_CMD_WRITE_LEN + j] = buf[offset + j];
|
||||
}
|
||||
ret = fts_write(&cmd[0], FTS_CMD_WRITE_LEN + packet_len);
|
||||
if (ret < 0) {
|
||||
FTS_ERROR("write fw to pram(%d) fail", i);
|
||||
goto write_pram_err;
|
||||
}
|
||||
|
||||
if (!fd_support)
|
||||
mdelay(3);
|
||||
}
|
||||
|
||||
write_pram_err:
|
||||
if (cmd) {
|
||||
kfree(cmd);
|
||||
cmd = NULL;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int fts_ecc_cal_tp(u32 ecc_saddr, u32 ecc_len, u16 *ecc_value)
|
||||
{
|
||||
int ret = 0;
|
||||
int i = 0;
|
||||
u8 cmd[FTS_ROMBOOT_CMD_ECC_NEW_LEN] = { 0 };
|
||||
u8 value[2] = { 0 };
|
||||
|
||||
FTS_INFO("ecc calc in tp");
|
||||
cmd[0] = FTS_ROMBOOT_CMD_ECC;
|
||||
cmd[1] = BYTE_OFF_16(ecc_saddr);
|
||||
cmd[2] = BYTE_OFF_8(ecc_saddr);
|
||||
cmd[3] = BYTE_OFF_0(ecc_saddr);
|
||||
cmd[4] = BYTE_OFF_16(ecc_len);
|
||||
cmd[5] = BYTE_OFF_8(ecc_len);
|
||||
cmd[6] = BYTE_OFF_0(ecc_len);
|
||||
|
||||
/* make boot to calculate ecc in pram */
|
||||
ret = fts_write(cmd, FTS_ROMBOOT_CMD_ECC_NEW_LEN);
|
||||
if (ret < 0) {
|
||||
FTS_ERROR("ecc calc cmd fail");
|
||||
return ret;
|
||||
}
|
||||
mdelay(3);
|
||||
|
||||
/* wait boot calculate ecc finish */
|
||||
cmd[0] = FTS_ROMBOOT_CMD_ECC_FINISH;
|
||||
for (i = 0; i < FTS_ECC_FINISH_TIMEOUT; i++) {
|
||||
ret = fts_read(cmd, 1, value, 1);
|
||||
if (ret < 0) {
|
||||
FTS_ERROR("ecc finish cmd fail");
|
||||
return ret;
|
||||
}
|
||||
if (0 == value[0])
|
||||
break;
|
||||
mdelay(1);
|
||||
}
|
||||
if (i >= FTS_ECC_FINISH_TIMEOUT) {
|
||||
FTS_ERROR("wait ecc finish timeout");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/* get ecc value calculate in boot */
|
||||
cmd[0] = FTS_ROMBOOT_CMD_ECC_READ;
|
||||
ret = fts_read(cmd, 1, value, 2);
|
||||
if (ret < 0) {
|
||||
FTS_ERROR("ecc read cmd fail");
|
||||
return ret;
|
||||
}
|
||||
|
||||
*ecc_value = ((u16)(value[0] << 8) + value[1]) & 0x0000FFFF;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int fts_ecc_cal_host(const u8 *data, u32 data_len, u16 *ecc_value)
|
||||
{
|
||||
u16 ecc = 0;
|
||||
u16 i = 0;
|
||||
u16 j = 0;
|
||||
u16 al2_fcs_coef = AL2_FCS_COEF;
|
||||
|
||||
for (i = 0; i < data_len; i += 2 ) {
|
||||
ecc ^= ((data[i] << 8) | (data[i + 1]));
|
||||
for (j = 0; j < 16; j ++) {
|
||||
if (ecc & 0x01)
|
||||
ecc = (u16)((ecc >> 1) ^ al2_fcs_coef);
|
||||
else
|
||||
ecc >>= 1;
|
||||
}
|
||||
}
|
||||
|
||||
*ecc_value = ecc & 0x0000FFFF;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int fts_pram_start(void)
|
||||
{
|
||||
int ret = 0;
|
||||
u8 cmd = FTS_ROMBOOT_CMD_START_APP;
|
||||
|
||||
FTS_INFO("remap to start pram");
|
||||
ret = fts_write(&cmd, 1);
|
||||
if (ret < 0) {
|
||||
FTS_ERROR("write start pram cmd fail");
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* description: download fw to IC and run
|
||||
*
|
||||
* param - buf: const, fw data buffer
|
||||
* len: length of fw
|
||||
*
|
||||
* return 0 if success, otherwise return error code
|
||||
*/
|
||||
int fts_fw_write_start(const u8 *buf, u32 len, bool need_reset)
|
||||
{
|
||||
int ret = 0;
|
||||
u16 ecc_in_host = 0;
|
||||
u16 ecc_in_tp = 0;
|
||||
u32 fw_start_addr = 0;
|
||||
u32 fw_len = 0;
|
||||
u16 code_len = 0;
|
||||
u16 code_len_n = 0;
|
||||
|
||||
FTS_INFO("begin to write and start fw(bin len:%d)", len);
|
||||
/* get app length */
|
||||
code_len = ((u16)buf[FTS_APP_INFO_OFFSET + 0] << 8)
|
||||
+ buf[FTS_APP_INFO_OFFSET + 1];
|
||||
code_len_n = ((u16)buf[FTS_APP_INFO_OFFSET + 2] << 8)
|
||||
+ buf[FTS_APP_INFO_OFFSET + 3];
|
||||
if ((code_len + code_len_n) != 0xFFFF) {
|
||||
FTS_ERROR("code len(%x %x) fail", code_len, code_len_n);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
fw_len = (u32)code_len;
|
||||
if ((fw_len < FTS_MIN_LEN) || (fw_len > FTS_MAX_LEN_APP)) {
|
||||
FTS_ERROR("fw length(%d) is invalid", fw_len);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
FTS_INFO("fw length in fact:%d", fw_len);
|
||||
fts_data->fw_is_running = false;
|
||||
|
||||
if (need_reset) {
|
||||
/* enter into boot environment */
|
||||
ret = fts_enter_into_boot();
|
||||
if (ret < 0) {
|
||||
FTS_ERROR("enter into boot environment fail");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
/* write pram */
|
||||
ret = fts_pram_write(fw_start_addr, buf, fw_len);
|
||||
if (ret < 0) {
|
||||
FTS_ERROR("write pram fail");
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* ecc check */
|
||||
ret = fts_ecc_cal_host(buf, fw_len, &ecc_in_host);
|
||||
if (ret < 0) {
|
||||
FTS_ERROR("ecc in host calc fail");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = fts_ecc_cal_tp(fw_start_addr, fw_len, &ecc_in_tp);
|
||||
if (ret < 0) {
|
||||
FTS_ERROR("ecc in tp calc fail");
|
||||
return ret;
|
||||
}
|
||||
|
||||
FTS_INFO("ecc in tp:%04x host:%04x", ecc_in_tp, ecc_in_host);
|
||||
if (ecc_in_tp != ecc_in_host) {
|
||||
FTS_ERROR("ecc check fail");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/* remap pram and run fw */
|
||||
ret = fts_pram_start();
|
||||
if (ret < 0) {
|
||||
FTS_ERROR("pram start fail");
|
||||
return ret;
|
||||
}
|
||||
|
||||
fts_data->fw_is_running = true;
|
||||
FTS_INFO("fw download successfully");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,448 @@
|
|||
/*
|
||||
*
|
||||
* FocalTech fts TouchScreen driver.
|
||||
*
|
||||
* Copyright (c) 2012-2019, Focaltech Ltd. All rights reserved.
|
||||
*
|
||||
* This software is licensed under the terms of the GNU General Public
|
||||
* License version 2, as published by the Free Software Foundation, and
|
||||
* may be copied, distributed, and modified under those terms.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* File Name: focaltech_flash.c
|
||||
*
|
||||
* Author: Focaltech Driver Team
|
||||
*
|
||||
* Created: 2017-12-06
|
||||
*
|
||||
* Abstract:
|
||||
*
|
||||
* Reference:
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
/*****************************************************************************
|
||||
* 1.Included header files
|
||||
*****************************************************************************/
|
||||
#include "focaltech_core.h"
|
||||
#include "focaltech_flash.h"
|
||||
|
||||
/*****************************************************************************
|
||||
* Static variables
|
||||
*****************************************************************************/
|
||||
#define FTS_READ_BOOT_ID_TIMEOUT 3
|
||||
#define FTS_FLASH_PACKET_LENGTH_SPI (32 * 1024 - 16)
|
||||
|
||||
#define FTS_CMD_ECC_LENGTH_MAX 32766
|
||||
#define FTS_ROMBOOT_CMD_ECC_FINISH_OK 0xA5
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* Global variable or extern global variabls/functions
|
||||
*****************************************************************************/
|
||||
static int fts_fwupg_hardware_reset_to_boot(void)
|
||||
{
|
||||
fts_reset_proc(0);
|
||||
mdelay(8);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int fts_enter_into_boot(void)
|
||||
{
|
||||
int ret = 0;
|
||||
int i = 0;
|
||||
int j = 0;
|
||||
u8 cmd[2] = { 0 };
|
||||
|
||||
FTS_INFO("enter into boot environment");
|
||||
for (i = 0; i < FTS_UPGRADE_LOOP; i++) {
|
||||
/* hardware tp reset to boot */
|
||||
fts_fwupg_hardware_reset_to_boot();
|
||||
|
||||
/* enter into boot & check boot id*/
|
||||
for (j = 0; j < FTS_READ_BOOT_ID_TIMEOUT; j++) {
|
||||
cmd[0] = FTS_CMD_START1;
|
||||
ret = fts_write(cmd, 1);
|
||||
if (ret >= 0) {
|
||||
mdelay(8);
|
||||
ret = fts_check_bootid();
|
||||
if (0 == ret) {
|
||||
FTS_INFO("boot id check pass, retry=%d", i);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
|
||||
static int fts_dpram_write(u32 saddr, const u8 *buf, u32 len, bool wpram)
|
||||
{
|
||||
int ret = 0;
|
||||
int i = 0;
|
||||
int j = 0;
|
||||
u8 *cmd = NULL;
|
||||
u32 addr = 0;
|
||||
u32 baseaddr = wpram ? FTS_PRAM_SADDR : FTS_DRAM_SADDR;
|
||||
u32 offset = 0;
|
||||
u32 remainder = 0;
|
||||
u32 packet_number = 0;
|
||||
u32 packet_len = 0;
|
||||
u32 packet_size = FTS_FLASH_PACKET_LENGTH_SPI;
|
||||
|
||||
FTS_INFO("dpram write");
|
||||
if (NULL == buf) {
|
||||
FTS_ERROR("fw buf is null");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if ((len < FTS_MIN_LEN) || (len > FTS_MAX_LEN_APP)) {
|
||||
FTS_ERROR("fw length(%d) fail", len);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
cmd = vmalloc(packet_size + FTS_CMD_WRITE_LEN);
|
||||
if (NULL == cmd) {
|
||||
FTS_ERROR("malloc memory for pram write buffer fail");
|
||||
return -ENOMEM;
|
||||
}
|
||||
memset(cmd, 0, packet_size + FTS_CMD_WRITE_LEN);
|
||||
|
||||
packet_number = len / packet_size;
|
||||
remainder = len % packet_size;
|
||||
if (remainder > 0)
|
||||
packet_number++;
|
||||
packet_len = packet_size;
|
||||
FTS_INFO("write data, num:%d remainder:%d", packet_number, remainder);
|
||||
|
||||
for (i = 0; i < packet_number; i++) {
|
||||
offset = i * packet_size;
|
||||
addr = saddr + offset + baseaddr;
|
||||
/* last packet */
|
||||
if ((i == (packet_number - 1)) && remainder)
|
||||
packet_len = remainder;
|
||||
|
||||
/* set pram address */
|
||||
cmd[0] = FTS_ROMBOOT_CMD_SET_PRAM_ADDR;
|
||||
cmd[1] = BYTE_OFF_16(addr);
|
||||
cmd[2] = BYTE_OFF_8(addr);
|
||||
cmd[3] = BYTE_OFF_0(addr);
|
||||
ret = fts_write(&cmd[0], FTS_ROMBOOT_CMD_SET_PRAM_ADDR_LEN);
|
||||
if (ret < 0) {
|
||||
FTS_ERROR("set pram(%d) addr(%d) fail", i, addr);
|
||||
goto write_pram_err;
|
||||
}
|
||||
|
||||
/* write pram data */
|
||||
cmd[0] = FTS_ROMBOOT_CMD_WRITE;
|
||||
for (j = 0; j < packet_len; j++) {
|
||||
cmd[1 + j] = buf[offset + j];
|
||||
}
|
||||
ret = fts_write(&cmd[0], 1 + packet_len);
|
||||
if (ret < 0) {
|
||||
FTS_ERROR("write fw to pram(%d) fail", i);
|
||||
goto write_pram_err;
|
||||
}
|
||||
}
|
||||
|
||||
write_pram_err:
|
||||
if (cmd) {
|
||||
vfree(cmd);
|
||||
cmd = NULL;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int fts_ecc_cal_tp(u32 ecc_saddr, u32 ecc_len, u16 *ecc_value)
|
||||
{
|
||||
int ret = 0;
|
||||
int i = 0;
|
||||
u8 cmd[FTS_ROMBOOT_CMD_ECC_NEW_LEN] = { 0 };
|
||||
u8 value[2] = { 0 };
|
||||
|
||||
FTS_INFO("ecc calc in tp");
|
||||
cmd[0] = FTS_ROMBOOT_CMD_ECC;
|
||||
cmd[1] = BYTE_OFF_16(ecc_saddr);
|
||||
cmd[2] = BYTE_OFF_8(ecc_saddr);
|
||||
cmd[3] = BYTE_OFF_0(ecc_saddr);
|
||||
cmd[4] = BYTE_OFF_16(ecc_len);
|
||||
cmd[5] = BYTE_OFF_8(ecc_len);
|
||||
cmd[6] = BYTE_OFF_0(ecc_len);
|
||||
|
||||
/* make boot to calculate ecc in pram */
|
||||
ret = fts_write(cmd, FTS_ROMBOOT_CMD_ECC_NEW_LEN);
|
||||
if (ret < 0) {
|
||||
FTS_ERROR("ecc calc cmd fail");
|
||||
return ret;
|
||||
}
|
||||
mdelay(2);
|
||||
|
||||
/* wait boot calculate ecc finish */
|
||||
cmd[0] = FTS_ROMBOOT_CMD_ECC_FINISH;
|
||||
for (i = 0; i < FTS_ECC_FINISH_TIMEOUT; i++) {
|
||||
ret = fts_read(cmd, 1, value, 1);
|
||||
if (ret < 0) {
|
||||
FTS_ERROR("ecc finish cmd fail");
|
||||
return ret;
|
||||
}
|
||||
if (FTS_ROMBOOT_CMD_ECC_FINISH_OK == value[0])
|
||||
break;
|
||||
mdelay(1);
|
||||
}
|
||||
if (i >= FTS_ECC_FINISH_TIMEOUT) {
|
||||
FTS_ERROR("wait ecc finish timeout,ecc_finish=%x", value[0]);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/* get ecc value calculate in boot */
|
||||
cmd[0] = FTS_ROMBOOT_CMD_ECC_READ;
|
||||
ret = fts_read(cmd, 1, value, 2);
|
||||
if (ret < 0) {
|
||||
FTS_ERROR("ecc read cmd fail");
|
||||
return ret;
|
||||
}
|
||||
|
||||
*ecc_value = ((u16)(value[0] << 8) + value[1]) & 0x0000FFFF;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int fts_ecc_cal_host(const u8 *data, u32 data_len, u16 *ecc_value)
|
||||
{
|
||||
u16 ecc = 0;
|
||||
u16 i = 0;
|
||||
u16 j = 0;
|
||||
u16 al2_fcs_coef = AL2_FCS_COEF;
|
||||
|
||||
for (i = 0; i < data_len; i += 2 ) {
|
||||
ecc ^= ((data[i] << 8) | (data[i + 1]));
|
||||
for (j = 0; j < 16; j ++) {
|
||||
if (ecc & 0x01)
|
||||
ecc = (u16)((ecc >> 1) ^ al2_fcs_coef);
|
||||
else
|
||||
ecc >>= 1;
|
||||
}
|
||||
}
|
||||
|
||||
*ecc_value = ecc & 0x0000FFFF;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int fts_ecc_check(const u8 *buf, u32 len, u32 ecc_saddr)
|
||||
{
|
||||
int ret = 0;
|
||||
int i = 0;
|
||||
u16 ecc_in_host = 0;
|
||||
u16 ecc_in_tp = 0;
|
||||
int packet_length = 0;
|
||||
int packet_number = 0;
|
||||
int packet_remainder = 0;
|
||||
int offset = 0;
|
||||
u32 packet_size = FTS_CMD_ECC_LENGTH_MAX;
|
||||
|
||||
packet_number = len / packet_size;
|
||||
packet_remainder = len % packet_size;
|
||||
if (packet_remainder)
|
||||
packet_number++;
|
||||
packet_length = packet_size;
|
||||
|
||||
for (i = 0; i < packet_number; i++) {
|
||||
/* last packet */
|
||||
if ((i == (packet_number - 1)) && packet_remainder)
|
||||
packet_length = packet_remainder;
|
||||
|
||||
ret = fts_ecc_cal_host(buf + offset, packet_length, &ecc_in_host);
|
||||
if (ret < 0) {
|
||||
FTS_ERROR("ecc in host calc fail");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = fts_ecc_cal_tp(ecc_saddr + offset, packet_length, &ecc_in_tp);
|
||||
if (ret < 0) {
|
||||
FTS_ERROR("ecc in tp calc fail");
|
||||
return ret;
|
||||
}
|
||||
|
||||
FTS_DEBUG("ecc in tp:%04x,host:%04x,i:%d", ecc_in_tp, ecc_in_host, i);
|
||||
if (ecc_in_tp != ecc_in_host) {
|
||||
FTS_ERROR("ecc_in_tp(%x) != ecc_in_host(%x), ecc check fail",
|
||||
ecc_in_tp, ecc_in_host);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
offset += packet_length;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int fts_pram_write_ecc(const u8 *buf, u32 len)
|
||||
{
|
||||
int ret = 0;
|
||||
u32 pram_app_size = 0;
|
||||
u16 code_len = 0;
|
||||
u16 code_len_n = 0;
|
||||
u32 pram_start_addr = 0;
|
||||
|
||||
FTS_INFO("begin to write pram app(bin len:%d)", len);
|
||||
/* get pram app length */
|
||||
code_len = ((u16)buf[FTS_APP_INFO_OFFSET + 0] << 8)
|
||||
+ buf[FTS_APP_INFO_OFFSET + 1];
|
||||
code_len_n = ((u16)buf[FTS_APP_INFO_OFFSET + 2] << 8)
|
||||
+ buf[FTS_APP_INFO_OFFSET + 3];
|
||||
if ((code_len + code_len_n) != 0xFFFF) {
|
||||
FTS_ERROR("pram code len(%x %x) fail", code_len, code_len_n);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
pram_app_size = (u32)code_len;
|
||||
pram_app_size = pram_app_size * 2;
|
||||
if ((pram_app_size < FTS_MIN_LEN) || (pram_app_size > FTS_MAX_LEN_APP)) {
|
||||
FTS_ERROR("pram app length(%d) is invalid", pram_app_size);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
FTS_INFO("pram app length in fact:%d", pram_app_size);
|
||||
/* write pram */
|
||||
ret = fts_dpram_write(pram_start_addr, buf, pram_app_size, true);
|
||||
if (ret < 0) {
|
||||
FTS_ERROR("write pram fail");
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* check ecc */
|
||||
ret = fts_ecc_check(buf, pram_app_size, pram_start_addr);
|
||||
if (ret < 0) {
|
||||
FTS_ERROR("pram ecc check fail");
|
||||
return ret;
|
||||
}
|
||||
|
||||
FTS_INFO("pram app write successfully");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int fts_dram_write_ecc(const u8 *buf, u32 len)
|
||||
{
|
||||
int ret = 0;
|
||||
u32 dram_size = 0;
|
||||
u32 pram_app_size = 0;
|
||||
u32 dram_start_addr = 0;
|
||||
u16 const_len = 0;
|
||||
u16 const_len_n = 0;
|
||||
const u8 *dram_buf = NULL;
|
||||
|
||||
FTS_INFO("begin to write dram data(bin len:%d)", len);
|
||||
/* get dram data length */
|
||||
const_len = ((u16)buf[FTS_APP_INFO_OFFSET + 0x8] << 8)
|
||||
+ buf[FTS_APP_INFO_OFFSET + 0x9];
|
||||
const_len_n = ((u16)buf[FTS_APP_INFO_OFFSET + 0x0A] << 8)
|
||||
+ buf[FTS_APP_INFO_OFFSET + 0x0B];
|
||||
if (((const_len + const_len_n) != 0xFFFF) || (const_len == 0)) {
|
||||
FTS_INFO("no support dram,const len(%x %x)", const_len, const_len_n);
|
||||
return 0;
|
||||
}
|
||||
|
||||
dram_size = ((u32)const_len) * 2;
|
||||
if ((dram_size <= 0) || (dram_size > FTS_MAX_LEN_APP_PARAMS)) {
|
||||
FTS_ERROR("dram data length(%d) is invalid", dram_size);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
pram_app_size = ((u32)(((u16)buf[FTS_APP_INFO_OFFSET + 0] << 8)
|
||||
+ buf[FTS_APP_INFO_OFFSET + 1])) * 2;
|
||||
|
||||
dram_buf = buf + pram_app_size;
|
||||
FTS_INFO("dram buf length in fact:%d,offset:%d", dram_size, pram_app_size);
|
||||
/* write pram */
|
||||
ret = fts_dpram_write(dram_start_addr, dram_buf, dram_size, false);
|
||||
if (ret < 0) {
|
||||
FTS_ERROR("write dram fail");
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* check ecc */
|
||||
ret = fts_ecc_check(dram_buf, dram_size, dram_start_addr);
|
||||
if (ret < 0) {
|
||||
FTS_ERROR("dram ecc check fail");
|
||||
return ret;
|
||||
}
|
||||
|
||||
FTS_INFO("dram data write successfully");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int fts_pram_start(void)
|
||||
{
|
||||
int ret = 0;
|
||||
u8 cmd = FTS_ROMBOOT_CMD_START_APP;
|
||||
|
||||
FTS_INFO("remap to start pram");
|
||||
ret = fts_write(&cmd, 1);
|
||||
if (ret < 0) {
|
||||
FTS_ERROR("write start pram cmd fail");
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* description: download fw to IC and run
|
||||
*
|
||||
* param - buf: const, fw data buffer
|
||||
* len: length of fw
|
||||
*
|
||||
* return 0 if success, otherwise return error code
|
||||
*/
|
||||
int fts_fw_write_start(const u8 *buf, u32 len, bool need_reset)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
FTS_INFO("begin to write and start fw(bin len:%d)", len);
|
||||
fts_data->fw_is_running = false;
|
||||
|
||||
if (need_reset) {
|
||||
/* enter into boot environment */
|
||||
ret = fts_enter_into_boot();
|
||||
if (ret < 0) {
|
||||
FTS_ERROR("enter into boot environment fail");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
/* write pram */
|
||||
ret = fts_pram_write_ecc(buf, len);
|
||||
if (ret < 0) {
|
||||
FTS_ERROR("write pram fail");
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* write dram */
|
||||
ret = fts_dram_write_ecc(buf, len);
|
||||
if (ret < 0) {
|
||||
FTS_ERROR("write dram fail");
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* remap pram and run fw */
|
||||
ret = fts_pram_start();
|
||||
if (ret < 0) {
|
||||
FTS_ERROR("pram start fail");
|
||||
return ret;
|
||||
}
|
||||
|
||||
fts_data->fw_is_running = true;
|
||||
FTS_INFO("fw download successfully");
|
||||
return 0;
|
||||
}
|
||||
|
||||
Loading…
Reference in a new issue