#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(); }