MXC-A36_2024.04.18/fr3092_mcu/components/drivers/bsp/touchpad/chsc6x_comp.c

1065 lines
31 KiB
C
Raw Normal View History

2024-04-17 19:45:26 +08:00
#include "chsc6x_comp.h"
#include "chsc6x_ramcode.h"
#include "chsc6x_flash_boot.h"
#include "chsc6x_platform.h"
#define TXRX_ADDR (0x9000)
#define CMD_ADDR (0x9f00)
#define RSP_ADDR (0x9f40)
//#define MAX_CHIP_ID (10)
//unsigned char chsc6x_chip_name[MAX_CHIP_ID][20];
static unsigned int g_chsc6x_cfg_ver = 0;
static unsigned int g_chsc6x_boot_ver = 0;
static unsigned int g_mccode; /* 1:3536 */
static unsigned int g_upgrade_flag = 0; /* 0:driver init upgrade, 1:OTA upgrade */
static unsigned char g_i2c_addr;
struct ts_fw_infos *g_pfw_infos;
struct chsc6x_updfile_header {
unsigned int sig;
unsigned int resv;
unsigned int n_cfg;
unsigned int n_match;
unsigned int len_cfg;
unsigned int len_boot;
};
typedef struct _test_cmd_wr {
/* offset 0; */
unsigned char id; /* cmd_id; */
unsigned char idv; /* inverse of cmd_id */
unsigned short d0; /* data 0 */
unsigned short d1; /* data 1 */
unsigned short d2; /* data 2 */
/* offset 8; */
unsigned char resv; /* offset 8 */
unsigned char tag; /* offset 9 */
unsigned short chk; /* 16 bit checksum */
unsigned short s2Pad0; /* */
unsigned short s2Pad1; /* */
} ctp_tst_wr_t;
typedef struct _test_cmd_rd {
/* offset 0; */
unsigned char id; /* cmd_id; */
unsigned char cc; /* complete code */
unsigned short d0; /* data 0 */
unsigned short sn; /* session number */
unsigned short chk; /* 16 bit checksum */
} ctp_tst_rd_t;
#define EPERM (1)
#define DIRECTLY_MODE (0x0)
#define DEDICATE_MODE (0x1)
#define LEN_CMD_CHK_TX (10)
#define LEN_CMD_PKG_TX (16)
#define LEN_RSP_CHK_RX (8)
#define MAX_BULK_SIZE (1024)
/* to direct memory access mode */
static unsigned char cmd_2dma_42bd[6] = { /*0x42, 0xbd, */ 0x28, 0x35, 0xc1, 0x00, 0x35, 0xae };
/* RETURN:0->pass else->fail */
static int chsc6x_read_bytes_u16addr(unsigned char id, unsigned short adr, unsigned char *rxbuf, unsigned short lenth)
{
int ret = 0;
int retry;
unsigned short ofs_adr;
int len = lenth;
int rd_len = 0;
int offset = 0;
while (len > 0) {
ofs_adr = adr + offset;
if (len > MAX_IIC_RD_LEN) {
rd_len = MAX_IIC_RD_LEN;
len -= MAX_IIC_RD_LEN;
} else {
rd_len = len;
len = 0;
}
retry = 0;
while (chsc6x_read_bytes_u16addr_sub(id, ofs_adr, &rxbuf[offset], rd_len) != 0) {
if (retry++ == 3) {
ret = -1;
break;
}
}
offset += MAX_IIC_RD_LEN;
if (ret < 0) {
break;
}
}
return ret;
}
/* RETURN:0->pass else->fail */
static int chsc6x_write_bytes_u16addr(unsigned char id, unsigned short adr, unsigned char *rxbuf, unsigned short lenth)
{
int ret = 0;
int retry;
unsigned short ofs_adr;
int len = lenth;
int wr_len = 0;
int offset = 0;
while (len > 0) {
ofs_adr = adr + offset;
if (len > MAX_IIC_WR_LEN) {
wr_len = MAX_IIC_WR_LEN;
len -= MAX_IIC_WR_LEN;
} else {
wr_len = len;
len = 0;
}
retry = 0;
while (chsc6x_write_bytes_u16addr_sub(id, ofs_adr, &rxbuf[offset], wr_len) != 0) {
if (retry++ == 3) {
ret = -1;
break;
}
}
offset += MAX_IIC_WR_LEN;
if (ret < 0) {
break;
}
}
return ret;
}
/* <0 : i2c error */
/* 0: direct address mode */
/* 1: protect mode */
static int chsc6x_get_i2cmode(void)
{
unsigned char regData[4];
if (chsc6x_read_bytes_u16addr(g_i2c_addr, 0x01, regData, 3)) {
return -EPERM;
}
if ((0x5c == regData[0]) && (regData[2] == 0X01)) {
return DIRECTLY_MODE;
}
return DEDICATE_MODE;
}
/* 0:successful */
static int chsc6x_set_dd_mode(void)
{
int mod = -1;
int retry = 0;
int ret = 0;
ret = chsc6x_get_i2cmode();
if (ret < 0) {
return ret;
}
if (ret == DIRECTLY_MODE) {
return 0;
}
while (retry++ < 5) {
chsc6x_msleep(20);
chsc6x_write_bytes_u16addr(g_i2c_addr, 0x42bd, cmd_2dma_42bd, 6);
chsc6x_msleep(30);
mod = chsc6x_get_i2cmode();
if (mod == DIRECTLY_MODE) {
break;
}
}
if (mod == DIRECTLY_MODE) {
return 0;
} else {
return -EPERM;
}
}
/* ret=0 : successful */
/* write with read-back check, in dd mode */
static int chsc6x_bulk_down_check(unsigned char *pbuf, unsigned short addr, unsigned short len)
{
unsigned int j, k, retry;
unsigned char rback[128];
while (len) {
k = (len < 128) ? len : 128;
retry = 0;
do {
rback[k - 1] = pbuf[k - 1] + 1;
chsc6x_write_bytes_u16addr(g_i2c_addr, addr, pbuf, k);
chsc6x_read_bytes_u16addr(g_i2c_addr, addr, rback, k);
for (j = 0; j < k; j++) {
if (pbuf[j] != rback[j]) {
break;
}
}
if (j >= k) {
break; /* match */
}
} while (++retry < 3);
if (j < k) {
break;
}
addr += k;
pbuf += k;
len -= k;
}
return (int)len;
}
static unsigned short chsc6x_checksum_u16(unsigned short *buf, unsigned short length)
{
unsigned short sum, len, i;
sum = 0;
len = length >> 1;
for (i = 0; i < len; i++) {
sum += buf[i];
}
return sum;
}
static unsigned int chsc6x_checksumEx(unsigned char *buf, unsigned short length)
{
unsigned int combChk;
unsigned short k, check, checkEx;
check = 0;
checkEx = 0;
for (k = 0; k < length; k++) {
check += buf[k];
checkEx += (unsigned short) (k * buf[k]);
}
combChk = (checkEx << 16) | check;
return combChk;
}
/* 0:successful */
static int chsc6x_download_ramcode(unsigned char *pcode, unsigned short len)
{
unsigned char dwr, retry;
int ret = -2;
int sig;
if (chsc6x_set_dd_mode()) {
return -EPERM;
}
sig = (int) pcode[3];
sig = (sig<<8) + (int) pcode[2];
sig = (sig<<8) + (int) pcode[1];
sig = (sig<<8) + (int) pcode[0];
if (sig == 0x6d6f8008) {
sig = 0;
chsc6x_read_bytes_u16addr(g_i2c_addr, 0x8000, (unsigned char *) &sig, 4);
if (sig == 0x6d6f8008) {
return 0;
}
}
dwr = 0x05;
if (chsc6x_bulk_down_check(&dwr, 0x0602, 1) == 0) { /* stop mcu */
dwr = 0x00;
chsc6x_bulk_down_check(&dwr, 0x0643, 1); /* disable irq */
} else {
return -EPERM;
}
if (chsc6x_bulk_down_check(pcode, 0x8000, len) == 0) {
dwr = 0x88;
retry = 0;
do {
ret = chsc6x_write_bytes_u16addr(g_i2c_addr, 0x0602, &dwr, 1);
} while ((++retry < 3) && (ret != 0));
}
chsc6x_msleep(30); // let caller decide the delay time ?
return ret;
}
/* return 0=successful: send cmd and get rsp. */
static int chsc6x_cmd_send(ctp_tst_wr_t *ptchcw, ctp_tst_rd_t *pcr)
{
int ret;
unsigned int retry;
retry = 0;
chsc6x_write_bytes_u16addr(g_i2c_addr, RSP_ADDR, (unsigned char *) &retry, 1);
/* send command */
ptchcw->idv = ~(ptchcw->id);
ptchcw->tag = 0x35;
ptchcw->chk = 1 + ~(chsc6x_checksum_u16((unsigned short *) ptchcw, LEN_CMD_CHK_TX));
ptchcw->tag = 0x30;
ret = chsc6x_write_bytes_u16addr(g_i2c_addr, CMD_ADDR, (unsigned char *) ptchcw, LEN_CMD_PKG_TX);
if (ret) {
goto exit;
}
ptchcw->tag = 0x35;
ret = chsc6x_write_bytes_u16addr(g_i2c_addr, CMD_ADDR + 9, (unsigned char *) &(ptchcw->tag), 1);
if (ret) {
goto exit;
}
/* polling rsp, the caller must init rsp buffer. */
ret = -1;
retry = 0;
while (retry++ < 100) { /* 2s */
chsc6x_msleep(20);
if (chsc6x_read_bytes_u16addr(g_i2c_addr, RSP_ADDR, (unsigned char *) pcr, 1)) {
break;
}
if (ptchcw->id != pcr->id) {
continue;
}
/* chsc6x_msleep(50); */
chsc6x_read_bytes_u16addr(g_i2c_addr, RSP_ADDR, (unsigned char *) pcr, LEN_RSP_CHK_RX);
if (!chsc6x_checksum_u16((unsigned short *) pcr, LEN_RSP_CHK_RX)) {
if ((ptchcw->id == pcr->id) && (pcr->cc == 0)) {
ret = 0;
}
}
break;
}
exit:
return ret;
}
/* return 0=successful */
static int chsc6x_read_burn_space(unsigned char *pdes, unsigned short adr, unsigned short len)
{
int rsp = -1;
unsigned int left = len;
unsigned int combChk, retry;
ctp_tst_wr_t m_cmd;
ctp_tst_rd_t m_rsp;
m_cmd.id = 0x31;
m_cmd.resv = 0x03;
while (left) {
len = (left > MAX_BULK_SIZE) ? MAX_BULK_SIZE : left;
m_cmd.d0 = adr;
m_cmd.d1 = len;
rsp = -1;
retry = 0;
while (retry++ < 3) {
m_rsp.id = 0;
if (chsc6x_cmd_send(&m_cmd, &m_rsp) == 0X0) {
chsc6x_read_bytes_u16addr(g_i2c_addr, TXRX_ADDR, pdes, len);
combChk = chsc6x_checksumEx(pdes, len);
if (m_rsp.d0 == (unsigned short)combChk) {
if (m_rsp.sn == (unsigned short)(combChk >> 16)) {
rsp = 0;
break;
}
}
}
}
if (rsp < 0) {
break;
}
left -= len;
adr += len;
pdes += len;
}
return rsp;
}
static int chsc6x_write_burn_space(unsigned char *psrc, unsigned short adr, unsigned short len)
{
int rsp = 0;
unsigned short left = len;
unsigned int retry, combChk;
ctp_tst_wr_t m_cmd;
ctp_tst_rd_t m_rsp;
m_cmd.id = 0x30;
m_cmd.resv = 0x11;
while (left) {
len = (left > MAX_BULK_SIZE) ? MAX_BULK_SIZE : left;
combChk = chsc6x_checksumEx(psrc, len);
m_cmd.d0 = adr;
m_cmd.d1 = len;
m_cmd.d2 = (unsigned short) combChk;
m_cmd.s2Pad0 = (unsigned short) (combChk >> 16);
rsp = -1; /* avoid dead loop */
retry = 0;
while (retry < 3) {
chsc6x_write_bytes_u16addr(g_i2c_addr, TXRX_ADDR, psrc, len);
m_rsp.id = 0;
rsp = chsc6x_cmd_send(&m_cmd, &m_rsp);
if (rsp < 0) {
if ((m_rsp.d0 == 0X05) && (m_rsp.cc == 0X09)) { /* fotal error */
break;
}
retry++;
} else {
left -= len;
adr += len;
psrc += len;
break;
}
}
if (rsp < 0) {
break;
}
}
return (!left) ? 0 : -1;
}
static int is_valid_cfg_data(unsigned short *ptcfg)
{
if (ptcfg == 0) {
return 0;
}
if ((unsigned char) (ptcfg[53] & 0xff) != 0x5c) {
chsc6x_err("chsc6x: cfg iic adr error !\r\n");
return 0;
}
if (chsc6x_checksum_u16(ptcfg, 204)) {
chsc6x_err("chsc6x: cfg chk_sum error !\r\n");
return 0;
}
return 1;
}
/*return: 1 allow; 0 no-allow*/
static int is_tpcfg_update_allow(unsigned short *ptcfg)
{
unsigned int u32tmp;
unsigned short vnow, vbuild;
if (g_chsc6x_cfg_ver == 0) { /* no available version information */
return 0;
}
if (is_valid_cfg_data(ptcfg) == 0) {
return 0;
}
u32tmp = ptcfg[1];
u32tmp = (u32tmp << 16) | ptcfg[0];
if ((g_chsc6x_cfg_ver & 0x3ffffff) != (u32tmp & 0x3ffffff)) {
chsc6x_err("chsc6x: prj info not match,now_cfg=0x%x:build_cfg=0x%x!\r\n",(g_chsc6x_cfg_ver&0x3ffffff), (u32tmp&0x3ffffff));
return 0;
}
vnow = (g_chsc6x_cfg_ver >> 26) & 0x3f;
vbuild = (u32tmp >> 26) & 0x3f;
chsc6x_info("chsc6x: cfg_vnow: 0x%x,cfg_vbuild: 0x%x \r\n", vnow, vbuild);
if (0 == g_upgrade_flag && vbuild <= vnow) {
return 0; //driver init upgrade, must vbuild > vnow
}
if(1 == g_upgrade_flag && vbuild == vnow) {
return 0; //OTA upgrade just vbuild != vnow */
}
return 1;
}
static int chsc6x_update_fcomp_cfg(unsigned short *ptcfg)
{
if (chsc6x_download_ramcode((unsigned char *)fw_fcode_burn, sizeof(fw_fcode_burn))) {
chsc6x_err("chsc6x: update fcomp_cfg error:ram-code error!\r\n");
return -EPERM;
}
if (chsc6x_write_burn_space((unsigned char *)ptcfg, 0x8000, 204)) {
chsc6x_err("chsc6x: update fcomp_cfg fail!\r\n");
return -EPERM;
}
g_chsc6x_cfg_ver = (ptcfg[1] << 16) | ptcfg[0];
g_pfw_infos->chsc6x_cfg_version = g_chsc6x_cfg_ver>>26;
return 0;
}
static int chsc6x_update_fcomp_boot(unsigned char *pdata, unsigned short len)
{
unsigned char buf[1] = {0x4b};
if (chsc6x_download_ramcode((unsigned char *)fw_fcode_burn, sizeof(fw_fcode_burn))) {
chsc6x_err("chsc6x: update fcomp_boot error:ram-code error!\r\n");
return -EPERM;
}
//pdata[8] = 0xff;
if (chsc6x_write_burn_space((unsigned char *)pdata, 0x00, len)) {
chsc6x_err("chsc6x: update fcomp_boot fail!\r\n");
return -EPERM;
}
if (chsc6x_write_burn_space((unsigned char *)buf, 0x08, 1)) {
chsc6x_err("chsc6x:update fcomp_boot last sig-byte fail!\r\n");
return -EPERM;
}
g_chsc6x_boot_ver = pdata[5];
g_chsc6x_boot_ver = (g_chsc6x_boot_ver<<8) + pdata[4];
g_pfw_infos->chsc6x_boot_version = g_chsc6x_boot_ver;
chsc6x_info("chsc6x: fcomp_boot update pass!\r\n");
return 0;
}
/*return: 0 SUCESS else FAIL*/
static int chsc6x_get_running_cfg(unsigned short *ptcfg, unsigned short addr)
{
int retry, err_type;
retry = 0;
err_type = 0;
chsc6x_set_dd_mode();
while (++retry < 5) {
err_type = 0;
if (chsc6x_read_bytes_u16addr(g_i2c_addr, addr, (unsigned char *) ptcfg, 204)) {
chsc6x_msleep(20);
err_type = 2; /* i2c error */
continue;
}
if (is_valid_cfg_data(ptcfg) == 0) {
chsc6x_set_dd_mode();
err_type = 1; /* data error or no data */
chsc6x_msleep(20);
continue;
}
break;
}
return err_type;
}
/*find factory first burnning cfg info*/
/*return: 0 SUCESS else FAIL*/
static int chsc6x_find_ver(void)
{
unsigned short buf_tmpcfg[102];
if (chsc6x_download_ramcode((unsigned char *)fw_fcode_burn, sizeof(fw_fcode_burn))) {
chsc6x_err("chsc6x: find factory cfg error:ram-code error!\r\n");
return -EPERM;
}
if (chsc6x_read_burn_space((unsigned char *) buf_tmpcfg, 0xf000, 204)) {
chsc6x_err("chsc6x: read factory cfg fail !\r\n");
return -EPERM;
}
if (is_valid_cfg_data(buf_tmpcfg)) {
chsc6x_info("chsc6x: read factory cfg OK !\r\n");
g_chsc6x_cfg_ver = (unsigned int)buf_tmpcfg[1];
g_chsc6x_cfg_ver = (g_chsc6x_cfg_ver<<16) + (unsigned int)buf_tmpcfg[0];
g_chsc6x_cfg_ver = g_chsc6x_cfg_ver&0x3ffffff;
g_pfw_infos->chsc6x_cfg_version = 0;
//g_pfw_infos->chsc6x_vendor_id = (g_chsc6x_cfg_ver>>9)&0x7F;
//g_pfw_infos->chsc6x_project_id = g_chsc6x_cfg_ver&0x01FF;
g_pfw_infos->chsc6x_vendor_id = ((g_chsc6x_cfg_ver>>9)&0x7F | ((g_chsc6x_cfg_ver>>22&0x03)<<7));
g_pfw_infos->chsc6x_project_id = ((g_chsc6x_cfg_ver&0x01FF) | ((g_chsc6x_cfg_ver>>20&0x03)<<9));
}
return 0;
}
static int chsc6x_cfg_update(unsigned short *parray, unsigned int cfg_num)
{
unsigned int k;
int new_idx_active = -1;
chsc6x_info("chsc6x: g_chsc6x_cfg_ver is 0x%x \r\n",g_chsc6x_cfg_ver);
if (g_chsc6x_cfg_ver == 0) { /* no available version information */
chsc6x_err("chsc6x: no current version information!\r\n");
return -EPERM;
}
for (k = 0; k < cfg_num; k++) {
if (is_tpcfg_update_allow(parray) == 1) {
new_idx_active = k;
chsc6x_info("chsc6x: new_idx_active is %d.\r\n", new_idx_active);
break;
}
parray = parray + 102;
}
if (new_idx_active < 0) {
chsc6x_info("chsc6x: 3536 cfg not need update!\r\n");
return -EPERM;
}
if (chsc6x_set_dd_mode()) {
chsc6x_err("chsc6x: cfg update error:can't control hw mode!\r\n");
return -EPERM;
}
if (chsc6x_update_fcomp_cfg(parray) == 0) {
chsc6x_info("chsc6x: fcomp_cfg update pass!\r\n");
} else {
chsc6x_err("chsc6x: fcomp_cfg update fail!\r\n");
}
return 0; /* need hw reset */
}
static int chsc6x_boot_ver_comp(unsigned int ver)
{
if (g_chsc6x_boot_ver == 0) {
chsc6x_info("chsc6x: try to force update boot ! \r\n");
return 1; //try to force update
}
if (0 == g_upgrade_flag && ver > g_chsc6x_boot_ver ) {
chsc6x_info("chsc6x: boot_vnow: 0x%x,boot_vbuild: 0x%x \r\n", g_chsc6x_boot_ver, ver);
return 1; //driver init upgrade, must vbuild > vnow
}
if (1 == g_upgrade_flag && ver != g_chsc6x_boot_ver ) {
chsc6x_info("chsc6x: boot_vnow: 0x%x,boot_vbuild: 0x%x \r\n", g_chsc6x_boot_ver, ver);
return 1; //OTA upgrade just vbuild != vnow */
}
chsc6x_info("chsc6x: boot_vnow: 0x%x,boot_vbuild: 0x%x \r\n", g_chsc6x_boot_ver, ver);
return 0; //no-need update boot
}
/*return: 0,no-need update | update succeed; 1,update failed*/
static int chsc6x_boot_update(unsigned char *pdata, unsigned short boot_len)
{
unsigned int ver = 0;
ver = pdata[5];
ver = (ver<<8) + pdata[4];
if (chsc6x_boot_ver_comp(ver) == 0) {
chsc6x_info("chsc6x: 3536 boot not need update!\r\n");
return 0;
}
return chsc6x_update_fcomp_boot(pdata, boot_len);
}
/*analysis the ".h fw" and check burn*/
/*return: 0 SUCESS else FAIL*/
static int chsc6x_update_compat_ctl(unsigned char *pupd, int len)
{
unsigned int k;
unsigned int n;
unsigned int offset;
unsigned int *vlist;
int ret = -1;
struct chsc6x_updfile_header *upd_header;
if (len < sizeof(struct chsc6x_updfile_header)){
chsc6x_err("chsc6x: update file len error_1 ! \r\n");
return -EPERM;
}
upd_header = (struct chsc6x_updfile_header *) pupd;
if (upd_header->sig != 0x43534843) {
chsc6x_err("chsc6x: update file sign error ! \r\n");
return -EPERM;
}
n = upd_header->n_cfg;
offset = (upd_header->n_match * 4) + sizeof(struct chsc6x_updfile_header);
if ((offset + upd_header->len_cfg + upd_header->len_boot) != len) {
chsc6x_err("chsc6x: update file len error_2 ! \r\n");
return -EPERM;
}
if ((n * 204) != upd_header->len_cfg) {
chsc6x_err("chsc6x: update file len error_3 ! \r\n");
return -EPERM;
}
if (n != 0) {
chsc6x_cfg_update((unsigned short *) (pupd + offset), n);
}
n = upd_header->n_match;
if (n != 0) {
vlist = (unsigned int *) (pupd + sizeof(struct chsc6x_updfile_header));
offset = offset + upd_header->len_cfg;
for (k=0; k < n; k++) {
if (vlist[k] == (g_chsc6x_cfg_ver & 0xffffff)) {
ret = chsc6x_boot_update((pupd + offset), upd_header->len_boot);
if(0 == ret) {
break;
}
else {
return -EPERM;
}
}
}
}
return 0;
}
/*return: 0 SUCESS else FAIL*/
static int chsc6x_do_update_ifneed(unsigned char* p_fw_upd, unsigned int fw_len)
{
const unsigned char *fupd;
unsigned int fw_size;
int ret = -1;
#if CHSC6X_MUL_VENDOR_UPGRADE
if(41 == g_pfw_infos->chsc6x_vendor_id && 27 == g_pfw_infos->chsc6x_project_id) {
fupd = chsc_boot_41_27;
fw_size = sizeof(chsc_boot);
ret = chsc6x_update_compat_ctl((unsigned char *) fupd, fw_size);
}
else if(29 == g_pfw_infos->chsc6x_vendor_id && 08 == g_pfw_infos->chsc6x_project_id) {
fupd = chsc_boot_29_08;
fw_size = sizeof(chsc_boot_29_08);
ret = chsc6x_update_compat_ctl((unsigned char *) fupd, fw_size);
}
#else
if(1 == g_upgrade_flag) { //ota upgrade
fupd = p_fw_upd;
fw_size = fw_len;
}else{
fupd = chsc_boot;
fw_size = sizeof(chsc_boot);
}
ret = chsc6x_update_compat_ctl((unsigned char *) fupd, fw_size);
#endif
return ret;
}
static void chsc6x_tp_mccode(void)
{
unsigned int tmp[3];
g_mccode = 0xff;
if (chsc6x_read_bytes_u16addr(g_i2c_addr, 0x8000, (unsigned char *) tmp, 12)) {
chsc6x_err("chsc6x: read 0x8000-12 fail! \r\n");
return;
}
if ( 0x544c4e4b == tmp[2] ) { /* boot code */
if (tmp[0] == 0x35368008) {
g_mccode = 1;
g_chsc6x_boot_ver = tmp[1] & 0xffff;
g_pfw_infos->chsc6x_boot_version = g_chsc6x_boot_ver;
chsc6x_info("chsc6x: read 0x8000-12 OK! \r\n");
}
} else if ( 0x544c4e00 == (tmp[2]&0xffffff00) ) {
if (tmp[0] == 0x35368008) {
g_mccode = 1;
g_chsc6x_boot_ver = 0;
g_pfw_infos->chsc6x_boot_version = g_chsc6x_boot_ver;
chsc6x_err("chsc6x: IC run flag error! \r\n");
}
}else { /* none code */
tmp[0] = 0;
if (chsc6x_read_bytes_u16addr(g_i2c_addr, 0x09, (unsigned char *) tmp, 3)) {
chsc6x_err("chsc6x: read 0x09-3 fail! \r\n");
return;
}
if (tmp[0] == 0x5c5c5c){ //empty ic
g_mccode = 1;
chsc6x_info("chsc6x: empty ic! \r\n");
}
}
}
/* FUNC: get fw info in struct ts_fw_infos you can call this func anytime.
* PARM iic_addr: your iic addr.
* PARM pfw_infos: can get all fw infos in struct ts_fw_infos, after call this interface.
*/
void chsc6x_get_chip_info(struct ts_fw_infos *infos)
{
int ret, cnt = 0;
unsigned char data_t[4] = {0};
g_i2c_addr = CHSC6X_I2C_ID;
for(cnt=0; cnt<3; cnt++) {
chsc6x_tp_reset();
ret = chsc6x_set_dd_mode();
if(ret != 0) {
chsc6x_err("chsc6x: Change to dd mode failed! \r\n");
}
ret = chsc6x_read_bytes_u16addr(g_i2c_addr, 0x9e00, data_t, 4);
if ((ret != 0) || (data_t[0] == 0x0) || (data_t[2] == 0x0)) {
chsc6x_err("chsc6x: Get chip_info failed::0x%02x%02x 0x%02x%02x \r\n", data_t[0], data_t[1], data_t[2], data_t[3]);
continue;
} else {
infos->chsc6x_cfg_version = data_t[3]>>2;
//infos->chsc6x_vendor_id = data_t[1]>>1;
//infos->chsc6x_project_id = ((data_t[1]&1)<<8) | data_t[0];
infos->chsc6x_vendor_id = (data_t[1]>>1) | ((data_t[2]&0xc0)<<1);
infos->chsc6x_project_id = (((data_t[1]&1)<<8) | data_t[0]) | ((data_t[2]&0x30)<<5);
chsc6x_info("chsc6x: TP chip_info OK::fw_ver:%d, vendor_id:%d, prj_id:%d \r\n", infos->chsc6x_cfg_version, infos->chsc6x_vendor_id, infos->chsc6x_project_id);
}
chsc6x_msleep(2);
ret = chsc6x_read_bytes_u16addr(g_i2c_addr, 0x8004, data_t, 2);
if(0 == ret) {
infos->chsc6x_boot_version = (data_t[1]<<8)|data_t[0];
chsc6x_info("chsc6x: boot_ver OK::0x%02x \r\n", infos->chsc6x_boot_version);
} else {
chsc6x_err("chsc6x: Get boot_ver failed! \r\n");
continue;
}
chsc6x_msleep(2);
ret = chsc6x_read_bytes_u16addr(g_i2c_addr, 0x9e4c, data_t, 4);
if(0 == ret) {
infos->chsc6x_rpt_lcd_x = (data_t[1]<<8) + data_t[0];
infos->chsc6x_rpt_lcd_y = (data_t[3]<<8) + data_t[2];
chsc6x_info("chsc6x: rpt_lcd_x & rpt_lcd_y OK::%d:%d \r\n", infos->chsc6x_rpt_lcd_x, infos->chsc6x_rpt_lcd_y);
} else {
chsc6x_err("chsc6x: Get rpt_lcd_x & rpt_lcd_y failed! \r\n");
continue;
}
chsc6x_msleep(2);
ret = chsc6x_read_bytes_u16addr(g_i2c_addr, 0x9e6a, data_t, 2);
if(0 == ret) {
infos->chsc6x_chip_id = data_t[0];
infos->chsc6x_chip_type = data_t[1]&0xf;
chsc6x_info("chsc6x: chsc6x_chip_id & chsc6x_chip_type OK::0x%02x:0x%x \r\n", infos->chsc6x_chip_id, infos->chsc6x_chip_type);
} else {
chsc6x_err("chsc6x: Get chsc6x_chip_id & chsc6x_chip_type failed! \r\n");
continue;
}
chsc6x_msleep(2);
ret = chsc6x_read_bytes_u16addr(g_i2c_addr, 0x9ff8, data_t, 1);
if(0 == ret) {
infos->chsc6x_max_pt_num = data_t[0];
chsc6x_info("chsc6x: chsc6x_max_pt_num OK::%d \r\n", infos->chsc6x_max_pt_num);
} else {
chsc6x_err("chsc6x: Get chsc6x_max_pt_num failed! \r\n");
continue;
}
break;
}
chsc6x_tp_reset();
if(cnt >= 3) {
chsc6x_err("chsc6x: Get chip_info failed! \r\n");
}
}
/* FUNC In your systerm init process,Must call this interface function to detec if the TP IC is Chipsemi corp'.
* PARM pfw_infos: to get top 5 fw info in struct ts_fw_infos.
* PARM update_ret_flag: point value=1 update succeed; point value=0 update failed, If opend CHSC6X_AUTO_UPGRADE macro.
* RETURN 1:is chsc chip, 0:is not chsc chip
*/
int chsc6x_tp_dect(struct ts_fw_infos *pfw_infos, unsigned char *update_ret_flag)
{
int ret = -1;
int try_cnt;
unsigned char dwr=0x05;
unsigned short buf_tmpcfg[102];
g_mccode = 0xff; /* default */
g_i2c_addr = CHSC6X_I2C_ID;
g_pfw_infos = pfw_infos;
for(try_cnt=0; try_cnt<5; try_cnt++) {
if (chsc6x_set_dd_mode()) {
chsc6x_tp_reset_active();
if (chsc6x_bulk_down_check(&dwr, 0x0602, 1) == 0) {
dwr = 0x00;
chsc6x_bulk_down_check(&dwr, 0x0643, 1);
} else {
chsc6x_info("chsc6x: write 0x0602 failed \r\n");
}
} else {
break;
}
}
if(try_cnt >= 5) {
chsc6x_info("chsc6x: chsc6x_set_dd_mode failed \r\n");
}
//chsc6x_info("chsc6x: chsc_boot size=%d \r\n", sizeof(chsc_boot));
chsc6x_tp_mccode(); /* MUST: call this function there!!! */
chsc6x_info("chsc6x: g_mccode is 0x%x \r\n",g_mccode);
if(g_mccode == 0xff) {
chsc6x_err("chsc6x: get mccode fail! \r\n");
return 0;
}
/*try to get running time tp-cfg. if fail : wrong boot? wrong rom-cfg?*/
if (chsc6x_get_running_cfg(buf_tmpcfg, 0x9e00) == 0) {
chsc6x_info("chsc6x: get_running_cfg pass !\r\n");
g_chsc6x_cfg_ver = (unsigned int)buf_tmpcfg[1];
g_chsc6x_cfg_ver = (g_chsc6x_cfg_ver<<16) + (unsigned int)buf_tmpcfg[0];
g_pfw_infos->chsc6x_cfg_version = g_chsc6x_cfg_ver>>26;
//g_pfw_infos->chsc6x_vendor_id = (g_chsc6x_cfg_ver>>9)&0x7F;
//g_pfw_infos->chsc6x_project_id = g_chsc6x_cfg_ver&0x01FF;
g_pfw_infos->chsc6x_vendor_id = ((g_chsc6x_cfg_ver>>9)&0x7F | ((g_chsc6x_cfg_ver>>22&0x03)<<7));
g_pfw_infos->chsc6x_project_id = ((g_chsc6x_cfg_ver&0x01FF) | ((g_chsc6x_cfg_ver>>20&0x03)<<9));
g_pfw_infos->chsc6x_rpt_lcd_x = buf_tmpcfg[38];
g_pfw_infos->chsc6x_rpt_lcd_y = buf_tmpcfg[39];
g_pfw_infos->chsc6x_chip_id = buf_tmpcfg[53]&0xff;
g_pfw_infos->chsc6x_chip_type = (buf_tmpcfg[53]>>8)&0xf;
chsc6x_info("chsc6x: vid=%d,pid=%d,boot_ver=0x%x,cfg_ver=%d,chip_id=0x%x\r\n", \
g_pfw_infos->chsc6x_vendor_id,g_pfw_infos->chsc6x_project_id,g_pfw_infos->chsc6x_boot_version, \
g_pfw_infos->chsc6x_cfg_version,g_pfw_infos->chsc6x_chip_id \
);
} else {
if(0 == buf_tmpcfg[2] && 0 == buf_tmpcfg[3]) {
g_chsc6x_boot_ver = 0;
}
chsc6x_find_ver();
}
if (0 == g_chsc6x_cfg_ver) {
chsc6x_err("chsc6x: get tp-info fail! \r\n");
return 0;
}
#if CHSC6X_AUTO_UPGRADE
g_upgrade_flag = 0;
ret = chsc6x_do_update_ifneed(0, 0);
if(0 != ret) {
*update_ret_flag = 0;
chsc6x_err("chsc6x: do fw update failed !\r\n");
} else {
*update_ret_flag = 1;
chsc6x_info("chsc6x: vid=%d,pid=%d,boot_ver=0x%x,cfg_ver=%d,chip_id=0x%x\r\n", \
g_pfw_infos->chsc6x_vendor_id,g_pfw_infos->chsc6x_project_id, \
g_pfw_infos->chsc6x_boot_version,g_pfw_infos->chsc6x_cfg_version,g_pfw_infos->chsc6x_chip_id \
);
}
#endif
exit:
chsc6x_tp_reset();
return 1;
}
/* FUNC You can call this interfacce function to realize upgrade TP Firmware by OTA.
* PARM pfw_infos: to get top 6 fw infos in struct ts_fw_infos, after ota upgrade.
* PARM p_fw_upd: array address of the upgrade firmware array
* PARM fw_len: total size of the upgrade firmware array
* RETURN NULL
*/
void chsc6x_ota_upgrade_tp_fw(struct ts_fw_infos *pfw_infos, unsigned char* p_fw_upd, unsigned int fw_len)
{
int ret;
int try_cnt;
unsigned char dwr=0x05;
g_mccode = 0xff; /* default */
g_i2c_addr = CHSC6X_I2C_ID;
g_pfw_infos = pfw_infos;
unsigned short buf_tmpcfg[102];
for(try_cnt=0; try_cnt<5; try_cnt++) {
if (chsc6x_set_dd_mode()) {
chsc6x_tp_reset_active();
if (chsc6x_bulk_down_check(&dwr, 0x0602, 1) == 0) {
dwr = 0x00;
chsc6x_bulk_down_check(&dwr, 0x0643, 1);
} else {
chsc6x_info("chsc6x: write 0x0602 failed \r\n");
}
} else {
break;
}
}
if(try_cnt >= 5) {
chsc6x_info("chsc6x: chsc6x_set_dd_mode failed \r\n");
}
chsc6x_tp_mccode(); /* MUST: call this function there!!! */
chsc6x_info("chsc6x: g_mccode is 0x%x\n",g_mccode);
if (g_mccode == 0xff) {
chsc6x_err("chsc6x: get mccode fail\n");
goto exit;
}
if (chsc6x_get_running_cfg(buf_tmpcfg, 0x9e00) == 0) {
chsc6x_info("chsc6x: get_running_cfg pass !\r\n");
g_chsc6x_cfg_ver = (unsigned int)buf_tmpcfg[1];
g_chsc6x_cfg_ver = (g_chsc6x_cfg_ver<<16) + (unsigned int)buf_tmpcfg[0];
g_pfw_infos->chsc6x_cfg_version = g_chsc6x_cfg_ver>>26;
//g_pfw_infos->chsc6x_vendor_id = (g_chsc6x_cfg_ver>>9)&0x7F;
//g_pfw_infos->chsc6x_project_id = g_chsc6x_cfg_ver&0x01FF;
g_pfw_infos->chsc6x_vendor_id = ((g_chsc6x_cfg_ver>>9)&0x7F | ((g_chsc6x_cfg_ver>>22&0x03)<<7));
g_pfw_infos->chsc6x_project_id = ((g_chsc6x_cfg_ver&0x01FF) | ((g_chsc6x_cfg_ver>>20&0x03)<<9));
g_pfw_infos->chsc6x_chip_id = buf_tmpcfg[53]&0xff;
g_pfw_infos->chsc6x_chip_type = (buf_tmpcfg[53]>>8)&0xf;
chsc6x_info("chsc6x: vid=%d,pid=%d,boot_ver=0x%x,cfg_ver=%d,chip_id=0x%x\r\n", \
g_pfw_infos->chsc6x_vendor_id,g_pfw_infos->chsc6x_project_id, \
g_pfw_infos->chsc6x_boot_version,g_pfw_infos->chsc6x_cfg_version,g_pfw_infos->chsc6x_chip_id \
);
} else {
chsc6x_find_ver();
}
if (g_chsc6x_cfg_ver == 0) {
chsc6x_err("chsc6x: get cfg-ver fail\n");
goto exit;
}
g_upgrade_flag = 1;
ret = chsc6x_do_update_ifneed(p_fw_upd, fw_len);
if(0 != ret) {
chsc6x_err("chsc6x: do fw update failed !\r\n");
} else {
chsc6x_info("chsc6x: vid=%d,pid=%d,boot_ver=0x%x,cfg_ver=%d,chip_id=0x%x\r\n", \
g_pfw_infos->chsc6x_vendor_id,g_pfw_infos->chsc6x_project_id, \
g_pfw_infos->chsc6x_boot_version,g_pfw_infos->chsc6x_cfg_version,g_pfw_infos->chsc6x_chip_id \
);
}
exit:
chsc6x_tp_reset();
}