1103 lines
36 KiB
C
1103 lines
36 KiB
C
#define LOG_TAG "Firmware"
|
|
|
|
#include "cts_config.h"
|
|
#include "cts_platform.h"
|
|
#include "cts_core.h"
|
|
#include "icnt8xxx_flash.h"
|
|
|
|
#include "cts_firmware.h"
|
|
#include <linux/path.h>
|
|
#include <linux/mount.h>
|
|
#include <linux/namei.h>
|
|
|
|
#ifdef CFG_CTS_DRIVER_BUILTIN_FIRMWARE
|
|
#include "icnt89xx_fw.h"
|
|
#include "icnt88xx_fw.h"
|
|
#include "icnt87xx_fw.h"
|
|
#include "icnt86xx_fw.h"
|
|
#include "icnt85xx_fw.h"
|
|
#include "icnt82xx_fw.h"
|
|
#include "icnt81xx_fw.h"
|
|
|
|
struct cts_firmware cts_driver_builtin_firmwares[] = {
|
|
{
|
|
.name = "ICNT89xx", /* MUST set non-NULL */
|
|
.hwid = CTS_HWID_ICNT89XX,
|
|
.fwid = CTS_FWID_ICNT89XX,
|
|
.data = icnt89xx_driver_builtin_firmware,
|
|
.size = ARRAY_SIZE(icnt89xx_driver_builtin_firmware),
|
|
.ver_offset = 0x114 //maybe = 0x100
|
|
},
|
|
{
|
|
.name = "ICNT86xx", /* MUST set non-NULL */
|
|
.hwid = CTS_HWID_ICNT86XX,
|
|
.fwid = CTS_FWID_ICNT86XX,
|
|
.data = icnt86xx_driver_builtin_firmware,
|
|
.size = ARRAY_SIZE(icnt86xx_driver_builtin_firmware),
|
|
.ver_offset = 0x100
|
|
},
|
|
{
|
|
.name = "ICNT88xx", /* MUST set non-NULL */
|
|
.hwid = CTS_HWID_ICNT88XX,
|
|
.fwid = CTS_FWID_ICNT88XX,
|
|
.data = icnt88xx_driver_builtin_firmware,
|
|
.size = ARRAY_SIZE(icnt88xx_driver_builtin_firmware),
|
|
.ver_offset = 0x100
|
|
},
|
|
{
|
|
.name = "ICNT87xx", /* MUST set non-NULL */
|
|
.hwid = CTS_HWID_ICNT87XX,
|
|
.fwid = CTS_FWID_ICNT87XX,
|
|
.data = icnt87xx_driver_builtin_firmware,
|
|
.size = ARRAY_SIZE(icnt87xx_driver_builtin_firmware),
|
|
.ver_offset = 0x100
|
|
},
|
|
{
|
|
.name = "ICNT85xx", /* MUST set non-NULL */
|
|
.hwid = CTS_HWID_ICNT85XX,
|
|
.fwid = CTS_FWID_ICNT85XX,
|
|
.data = icnt85xx_driver_builtin_firmware,
|
|
.size = ARRAY_SIZE(icnt85xx_driver_builtin_firmware),
|
|
.ver_offset = 0x100
|
|
},
|
|
{
|
|
.name = "ICNT82xx", /* MUST set non-NULL */
|
|
.hwid = CTS_HWID_ICNT82XX,
|
|
.fwid = CTS_FWID_ICNT82XX,
|
|
.data = icnt82xx_driver_builtin_firmware,
|
|
.size = ARRAY_SIZE(icnt82xx_driver_builtin_firmware),
|
|
.ver_offset = 0x114
|
|
},
|
|
{
|
|
.name = "ICNT81xx", /* MUST set non-NULL */
|
|
.hwid = CTS_HWID_ICNT81XX,
|
|
.fwid = CTS_FWID_ICNT81XX,
|
|
.data = icnt81xx_driver_builtin_firmware,
|
|
.size = ARRAY_SIZE(icnt81xx_driver_builtin_firmware),
|
|
.ver_offset = 0x100
|
|
},
|
|
};
|
|
|
|
#define NUM_DRIVER_BUILTIN_FIRMWARE ARRAY_SIZE(cts_driver_builtin_firmwares)
|
|
#endif /* CFG_CTS_DRIVER_BUILTIN_FIRMWARE */
|
|
|
|
#ifdef SUPPORT_SENSOR_ID
|
|
#define MAX_SUPPORT_ID_NUM 9u
|
|
|
|
#ifdef CFG_CTS_DRIVER_BUILTIN_FIRMWARE
|
|
struct _sensor_id_a {
|
|
u8 id;
|
|
u8 *array;
|
|
int size;
|
|
};
|
|
struct sensor_id_array {
|
|
char *name;
|
|
struct _sensor_id_a id_tables[MAX_SUPPORT_ID_NUM+1];
|
|
};
|
|
static struct sensor_id_array sensor_id_array_table[] = {
|
|
{ "ICNT89xx", {
|
|
{0x00, icnt89xx_driver_builtin_firmware_00, sizeof(icnt89xx_driver_builtin_firmware_00),},
|
|
{0x01, icnt89xx_driver_builtin_firmware_01, sizeof(icnt89xx_driver_builtin_firmware_01),},
|
|
{0x02, icnt89xx_driver_builtin_firmware_02, sizeof(icnt89xx_driver_builtin_firmware_02),},
|
|
{0x10, icnt89xx_driver_builtin_firmware_10, sizeof(icnt89xx_driver_builtin_firmware_10),},
|
|
{0x11, icnt89xx_driver_builtin_firmware_11, sizeof(icnt89xx_driver_builtin_firmware_11),},
|
|
{0x12, icnt89xx_driver_builtin_firmware_12, sizeof(icnt89xx_driver_builtin_firmware_12),},
|
|
{0x20, icnt89xx_driver_builtin_firmware_20, sizeof(icnt89xx_driver_builtin_firmware_20),},
|
|
{0x21, icnt89xx_driver_builtin_firmware_21, sizeof(icnt89xx_driver_builtin_firmware_21),},
|
|
{0x22, icnt89xx_driver_builtin_firmware_22, sizeof(icnt89xx_driver_builtin_firmware_22),},
|
|
{0xff, icnt89xx_driver_builtin_firmware, sizeof(icnt89xx_driver_builtin_firmware),},
|
|
},
|
|
},
|
|
{ "ICNT86xx", {
|
|
{0x00, icnt86xx_driver_builtin_firmware_00, sizeof(icnt86xx_driver_builtin_firmware_00),},
|
|
{0x01, icnt86xx_driver_builtin_firmware_01, sizeof(icnt86xx_driver_builtin_firmware_01),},
|
|
{0x02, icnt86xx_driver_builtin_firmware_02, sizeof(icnt86xx_driver_builtin_firmware_02),},
|
|
{0x10, icnt86xx_driver_builtin_firmware_10, sizeof(icnt86xx_driver_builtin_firmware_10),},
|
|
{0x11, icnt86xx_driver_builtin_firmware_11, sizeof(icnt86xx_driver_builtin_firmware_11),},
|
|
{0x12, icnt86xx_driver_builtin_firmware_12, sizeof(icnt86xx_driver_builtin_firmware_12),},
|
|
{0x20, icnt86xx_driver_builtin_firmware_20, sizeof(icnt86xx_driver_builtin_firmware_20),},
|
|
{0x21, icnt86xx_driver_builtin_firmware_21, sizeof(icnt86xx_driver_builtin_firmware_21),},
|
|
{0x22, icnt86xx_driver_builtin_firmware_22, sizeof(icnt86xx_driver_builtin_firmware_22),},
|
|
{0xff, icnt86xx_driver_builtin_firmware, sizeof(icnt86xx_driver_builtin_firmware),},
|
|
},
|
|
},
|
|
{ "ICNT87xx", {
|
|
{0x00, icnt87xx_driver_builtin_firmware_00, sizeof(icnt87xx_driver_builtin_firmware_00),},
|
|
{0x01, icnt87xx_driver_builtin_firmware_01, sizeof(icnt87xx_driver_builtin_firmware_01),},
|
|
{0x02, icnt87xx_driver_builtin_firmware_02, sizeof(icnt87xx_driver_builtin_firmware_02),},
|
|
{0x10, icnt87xx_driver_builtin_firmware_10, sizeof(icnt87xx_driver_builtin_firmware_10),},
|
|
{0x11, icnt87xx_driver_builtin_firmware_11, sizeof(icnt87xx_driver_builtin_firmware_11),},
|
|
{0x12, icnt87xx_driver_builtin_firmware_12, sizeof(icnt87xx_driver_builtin_firmware_12),},
|
|
{0x20, icnt87xx_driver_builtin_firmware_20, sizeof(icnt87xx_driver_builtin_firmware_20),},
|
|
{0x21, icnt87xx_driver_builtin_firmware_21, sizeof(icnt87xx_driver_builtin_firmware_21),},
|
|
{0x22, icnt87xx_driver_builtin_firmware_22, sizeof(icnt87xx_driver_builtin_firmware_22),},
|
|
{0xff, icnt87xx_driver_builtin_firmware, sizeof(icnt87xx_driver_builtin_firmware),},
|
|
},
|
|
},
|
|
{ "ICNT81xx", {
|
|
{0x00, icnt81xx_driver_builtin_firmware_00, sizeof(icnt81xx_driver_builtin_firmware_00),},
|
|
{0x01, icnt81xx_driver_builtin_firmware_01, sizeof(icnt81xx_driver_builtin_firmware_01),},
|
|
{0x02, icnt81xx_driver_builtin_firmware_02, sizeof(icnt81xx_driver_builtin_firmware_02),},
|
|
{0x10, icnt81xx_driver_builtin_firmware_10, sizeof(icnt81xx_driver_builtin_firmware_10),},
|
|
{0x11, icnt81xx_driver_builtin_firmware_11, sizeof(icnt81xx_driver_builtin_firmware_11),},
|
|
{0x12, icnt81xx_driver_builtin_firmware_12, sizeof(icnt81xx_driver_builtin_firmware_12),},
|
|
{0x20, icnt81xx_driver_builtin_firmware_20, sizeof(icnt81xx_driver_builtin_firmware_20),},
|
|
{0x21, icnt81xx_driver_builtin_firmware_21, sizeof(icnt81xx_driver_builtin_firmware_21),},
|
|
{0x22, icnt81xx_driver_builtin_firmware_22, sizeof(icnt81xx_driver_builtin_firmware_22),},
|
|
{0xff, icnt81xx_driver_builtin_firmware, sizeof(icnt81xx_driver_builtin_firmware),},
|
|
},
|
|
},
|
|
// if you want support other chip value ,please add here
|
|
};
|
|
#endif
|
|
|
|
#ifdef CFG_CTS_FIRMWARE_IN_FS
|
|
struct _sensor_id_b {
|
|
u8 id;
|
|
const char *bin;
|
|
};
|
|
struct sensor_id_fs {
|
|
char *name;
|
|
struct _sensor_id_b id_tables[MAX_SUPPORT_ID_NUM +1];
|
|
};
|
|
static struct sensor_id_fs sensor_id_bin_table[] = {
|
|
{ "ICNT89xx", {
|
|
{0x00, "/etc/firmware/ICNT89xx_00.bin",},
|
|
{0x01, "/etc/firmware/ICNT89xx_01.bin",},
|
|
{0x02, "/etc/firmware/ICNT89xx_02.bin",},
|
|
{0x10, "/etc/firmware/ICNT89xx_10.bin",},
|
|
{0x11, "/etc/firmware/ICNT89xx_11.bin",},
|
|
{0x12, "/etc/firmware/ICNT89xx_12.bin",},
|
|
{0x20, "/etc/firmware/ICNT89xx_20.bin",},
|
|
{0x21, "/etc/firmware/ICNT89xx_21.bin",},
|
|
{0x22, "/etc/firmware/ICNT89xx_22.bin",},
|
|
{0xff, "/etc/firmware/ICNT89xx.bin",},
|
|
},
|
|
},
|
|
{ "ICNT86xx", {
|
|
{0x00, "/etc/firmware/ICNT86xx_00.bin",},
|
|
{0x01, "/etc/firmware/ICNT86xx_01.bin",},
|
|
{0x02, "/etc/firmware/ICNT86xx_02.bin",},
|
|
{0x10, "/etc/firmware/ICNT86xx_10.bin",},
|
|
{0x11, "/etc/firmware/ICNT86xx_11.bin",},
|
|
{0x12, "/etc/firmware/ICNT86xx_12.bin",},
|
|
{0x20, "/etc/firmware/ICNT86xx_20.bin",},
|
|
{0x21, "/etc/firmware/ICNT86xx_21.bin",},
|
|
{0x22, "/etc/firmware/ICNT86xx_22.bin",},
|
|
{0xff, "/etc/firmware/ICNT86xx.bin",},
|
|
},
|
|
},
|
|
{ "ICNT87xx", {
|
|
{0x00, "/etc/firmware/ICNT87xx_00.bin",},
|
|
{0x01, "/etc/firmware/ICNT87xx_01.bin",},
|
|
{0x02, "/etc/firmware/ICNT87xx_02.bin",},
|
|
{0x10, "/etc/firmware/ICNT87xx_10.bin",},
|
|
{0x11, "/etc/firmware/ICNT87xx_11.bin",},
|
|
{0x12, "/etc/firmware/ICNT87xx_12.bin",},
|
|
{0x20, "/etc/firmware/ICNT87xx_20.bin",},
|
|
{0x21, "/etc/firmware/ICNT87xx_21.bin",},
|
|
{0x22, "/etc/firmware/ICNT87xx_22.bin",},
|
|
{0xff, "/etc/firmware/ICNT87xx.bin",},
|
|
},
|
|
},
|
|
{ "ICNT81xx", {
|
|
{0x00, "/etc/firmware/ICNT81xx_00.bin",},
|
|
{0x01, "/etc/firmware/ICNT81xx_01.bin",},
|
|
{0x02, "/etc/firmware/ICNT81xx_02.bin",},
|
|
{0x10, "/etc/firmware/ICNT81xx_10.bin",},
|
|
{0x11, "/etc/firmware/ICNT81xx_11.bin",},
|
|
{0x12, "/etc/firmware/ICNT81xx_12.bin",},
|
|
{0x20, "/etc/firmware/ICNT81xx_20.bin",},
|
|
{0x21, "/etc/firmware/ICNT81xx_21.bin",},
|
|
{0x22, "/etc/firmware/ICNT81xx_22.bin",},
|
|
{0xff, "/etc/firmware/ICNT81xx.bin",},
|
|
},
|
|
},
|
|
// if you want support other chip value ,please add here
|
|
};
|
|
#endif
|
|
|
|
#else //undefine SUPPORT_SENSOR_ID
|
|
|
|
#ifdef CFG_CTS_FIRMWARE_IN_FS
|
|
struct bin_in_fs {
|
|
char *name;
|
|
const char *bin;
|
|
};
|
|
static struct bin_in_fs bin_table[] = {
|
|
{ "ICNT89xx", "/etc/firmware/ICNT89xx.bin",},
|
|
{ "ICNT86xx", "/etc/firmware/ICNT86xx.bin",},
|
|
{ "ICNT87xx", "/etc/firmware/ICNT87xx.bin",},
|
|
{ "ICNT85xx", "/etc/firmware/ICNT85xx.bin",},
|
|
{ "ICNT82xx", "/etc/firmware/ICNT82xx.bin",},
|
|
{ "ICNT81xx", "/data/ICNT81xx.bin",},// { "ICNT81xx", "/etc/firmware/ICNT81xx.bin",},
|
|
// if you want support other chip value ,please add here
|
|
};
|
|
#endif
|
|
|
|
|
|
#endif
|
|
#define CTS_FIRMWARE_FILE_SIZE (48*1024)
|
|
//#define CTS_FIRMWARE_MULTI_SECTION_FILE_SIZE (0x20000)
|
|
//#define CTS_SECTION_ENABLE_FLAG (0x0000C35A)
|
|
|
|
#define FIRMWARE_VERSION_OFFSET 0x100
|
|
#define FIRMWARE_VERSION(firmware, offset) \
|
|
get_unaligned_le16((firmware)->data + offset)
|
|
|
|
#if defined CFG_CTS_FIRMWARE_IN_FS
|
|
static bool is_firmware_size_valid(const struct cts_firmware *firmware)
|
|
{
|
|
return (firmware->size > 0x102 &&
|
|
firmware->size <= CTS_FIRMWARE_FILE_SIZE);
|
|
}
|
|
#endif
|
|
|
|
#if defined CFG_CTS_DRIVER_BUILTIN_FIRMWARE
|
|
static bool is_firmware_valid(const struct cts_firmware *firmware)
|
|
{
|
|
if (firmware && firmware->data && is_firmware_size_valid(firmware)) {
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
#endif
|
|
|
|
#ifdef SUPPORT_SENSOR_ID
|
|
|
|
#ifdef CFG_CTS_DRIVER_BUILTIN_FIRMWARE
|
|
int cts_compare_sensor_id_from_bultin(const struct cts_device *cts_dev,
|
|
struct cts_firmware *firmware)
|
|
{
|
|
int i,j;
|
|
|
|
for (i = 0; i < ARRAY_SIZE(sensor_id_array_table); i++) {
|
|
if ((strcmp(firmware->name, sensor_id_array_table[i].name) == 0)) {
|
|
if(cts_dev->rtdata.is_chip_empty){
|
|
cts_info("Chip is empty return default firmware bultin: chip_index:%d id:0x%02x id_index: %d ",
|
|
i, sensor_id_array_table[i].id_tables[MAX_SUPPORT_ID_NUM].id, MAX_SUPPORT_ID_NUM);
|
|
firmware->data = sensor_id_array_table[i].id_tables[MAX_SUPPORT_ID_NUM].array;
|
|
firmware->size = sensor_id_array_table[i].id_tables[MAX_SUPPORT_ID_NUM].size;
|
|
return 0;
|
|
}
|
|
for(j=0; j< ARRAY_SIZE(sensor_id_array_table[i].id_tables); j++){
|
|
if(sensor_id_array_table[i].id_tables[j].id
|
|
== cts_dev->confdata.hw_sensor_id){
|
|
firmware->data = sensor_id_array_table[i].id_tables[j].array;
|
|
firmware->size = sensor_id_array_table[i].id_tables[j].size;
|
|
cts_info("Found %s firmware match sensor id bultin: chip_index:%d id: 0x%02x id_index: %d",
|
|
firmware->name, i, cts_dev->confdata.hw_sensor_id, j);
|
|
return 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
cts_info("Not found %s firmware match sensor id: 0x%02x bultin",
|
|
firmware->name,cts_dev->confdata.hw_sensor_id);
|
|
return -EINVAL;
|
|
}
|
|
#endif
|
|
|
|
#define CTS_DEV_HW_MAX_GPIO_NUM (8)
|
|
|
|
enum CTS_DEV_GPIO_STATUS {
|
|
CTS_DEV_GPIO_PULL_DOWN = 0,
|
|
CTS_DEV_GPIO_PULL_UP = 1,
|
|
CTS_DEV_GPIO_FLOATING = 2,
|
|
};
|
|
|
|
static int cts_dev_hw_reg_set_bit(struct cts_device *cts_dev, u32 reg, int nr)
|
|
{
|
|
int ret = 0;
|
|
u8 val = 0;
|
|
|
|
ret = cts_hw_reg_readb(cts_dev, reg, &val);
|
|
if (ret) {
|
|
cts_err("set bit hw reg %d failed\n",reg);
|
|
return ret;
|
|
}
|
|
|
|
val |= 1u << nr;
|
|
ret = cts_hw_reg_writeb(cts_dev, reg, val);
|
|
if (ret) {
|
|
cts_err("set bit hw write reg %d val %d failed\n",reg,val);
|
|
return ret;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int cts_dev_hw_reg_clr_bit(struct cts_device *cts_dev, u32 reg, int nr)
|
|
{
|
|
int ret = 0;
|
|
u8 val = 0;
|
|
|
|
ret = cts_hw_reg_readb(cts_dev, reg, &val);
|
|
if (ret) {
|
|
cts_err("clr bit hw reg %d failed\n",reg);
|
|
return ret;
|
|
}
|
|
|
|
val &= ~(1u << nr);
|
|
ret = cts_hw_reg_writeb(cts_dev, reg, val);
|
|
if (ret) {
|
|
cts_err("clr bit hw write reg %d val %d failed\n",reg,val);
|
|
return ret;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int cts_dev_set_gpio_direction(struct cts_device *cts_dev, int gpio, bool output)
|
|
{
|
|
int ret = 0;
|
|
|
|
cts_info("Set GPIO%u direction: %s", gpio, output ? "OUTPUT" : "INPUT");
|
|
|
|
if (output) {
|
|
ret = cts_dev_hw_reg_set_bit(cts_dev, CTS_DEVICE_HW_REG_GPIO_DIR, gpio);
|
|
} else {
|
|
ret = cts_dev_hw_reg_clr_bit(cts_dev, CTS_DEVICE_HW_REG_GPIO_DIR, gpio);
|
|
}
|
|
if (ret) {
|
|
cts_err("set gpio direction failed\n");
|
|
return ret;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int cts_dev_set_gpio_pullup(struct cts_device *cts_dev, int gpio)
|
|
{
|
|
int ret = 0;
|
|
cts_info("Set GPIO%u pull up", gpio);
|
|
|
|
ret = cts_dev_hw_reg_set_bit(cts_dev, CTS_DEVICE_HW_REG_GPIO_PULL_UP, gpio);
|
|
if (ret) {
|
|
cts_err("set gpio pullup,set bit failed\n");
|
|
return ret;
|
|
}
|
|
ret = cts_dev_hw_reg_clr_bit(cts_dev, CTS_DEVICE_HW_REG_GPIO_PULL_DOWN, gpio);
|
|
if (ret) {
|
|
cts_err("set gpio pullup,clr bit failed\n");
|
|
return ret;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static int cts_dev_set_gpio_pulldown(struct cts_device *cts_dev, int gpio)
|
|
{
|
|
int ret = 0;
|
|
|
|
cts_info("Set GPIO%u pull down", gpio);
|
|
ret = cts_dev_hw_reg_clr_bit(cts_dev, CTS_DEVICE_HW_REG_GPIO_PULL_UP, gpio);
|
|
if (ret) {
|
|
cts_err("set gpio pulldown,clr bit failed\n");
|
|
return ret;
|
|
}
|
|
ret = cts_dev_hw_reg_set_bit(cts_dev, CTS_DEVICE_HW_REG_GPIO_PULL_DOWN, gpio);
|
|
if (ret) {
|
|
cts_err("set gpio pulldown,set bit failed\n");
|
|
return ret;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static int cts_dev_get_gpio_value(struct cts_device *cts_dev, int gpio, bool *val)
|
|
{
|
|
u8 v = 0;
|
|
int ret = 0;
|
|
|
|
ret = cts_hw_reg_readb(cts_dev, CTS_DEVICE_HW_REG_GPIO_GET_VAL, &v);
|
|
if (ret) {
|
|
cts_err("get gpio value hw reg failed\n");
|
|
return ret;
|
|
}
|
|
|
|
*val = v & (1u << gpio) ? true : false;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int cts_dev_get_gpio_status(struct cts_device *cts_dev, int gpio, u8 *status)
|
|
{
|
|
int ret = 0;
|
|
bool val = 0;
|
|
|
|
cts_info("Get GPIO%u status");
|
|
|
|
if (gpio < 0 || gpio > CTS_DEV_HW_MAX_GPIO_NUM) {
|
|
cts_err("get gpio status gpio invalid\n");
|
|
return -EINVAL;
|
|
}
|
|
|
|
ret = cts_dev_hw_reg_clr_bit(cts_dev, CTS_DEVICE_HW_REG_PINMUX, gpio);
|
|
if (ret) {
|
|
cts_err("get gpio status,he reg clr bit failed\n");
|
|
return ret;
|
|
}
|
|
ret = cts_dev_set_gpio_direction(cts_dev, gpio, false);
|
|
if (ret) {
|
|
cts_err("get gpio status,set gpio direction failed\n");
|
|
return ret;
|
|
}
|
|
|
|
ret = cts_dev_set_gpio_pullup(cts_dev, gpio);
|
|
if (ret) {
|
|
cts_err("get gpio status,set gpio pullup failed\n");
|
|
return ret;
|
|
}
|
|
udelay(100);
|
|
|
|
ret = cts_dev_get_gpio_value(cts_dev, gpio, &val);
|
|
if (ret) {
|
|
cts_err("get gpio status,get gpio value failed\n");
|
|
return ret;
|
|
}
|
|
if (val) {
|
|
ret = cts_dev_set_gpio_pulldown(cts_dev, gpio);
|
|
if (ret) {
|
|
cts_err("get gpio status,set gpio pulldown failed\n");
|
|
return ret;
|
|
}
|
|
udelay(100);
|
|
|
|
cts_dev_get_gpio_value(cts_dev, gpio, &val);
|
|
if (ret) {
|
|
cts_err("get gpio status,get gpio value failed\n");
|
|
return ret;
|
|
}
|
|
if (val) {
|
|
*status = CTS_DEV_GPIO_PULL_UP;
|
|
} else {
|
|
*status = CTS_DEV_GPIO_FLOATING;
|
|
}
|
|
} else {
|
|
*status = CTS_DEV_GPIO_PULL_DOWN;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int cts_dev_get_sensor_id(struct cts_device *cts_dev, u8 *sensor_id)
|
|
{
|
|
int ret = 0;
|
|
u8 id1, id2 = 0;
|
|
|
|
ret = cts_dev_get_gpio_status(cts_dev, 2, &id1);
|
|
if (ret) {
|
|
cts_err("get gpio status id1 failed\n");
|
|
return ret;
|
|
}
|
|
|
|
ret = cts_dev_get_gpio_status(cts_dev, 3, &id2);
|
|
if (ret) {
|
|
cts_err("get gpio status id2 failed\n");
|
|
return ret;
|
|
}
|
|
|
|
*sensor_id = (id2 << 4) | id1;
|
|
return 0;
|
|
}
|
|
|
|
#ifdef CFG_CTS_FIRMWARE_IN_FS
|
|
int cts_compare_sensor_id_from_fs(struct cts_device *cts_dev,
|
|
struct cts_firmware *firmware)
|
|
{
|
|
int i,j = 0;
|
|
int ret = 0;
|
|
int retry=0;
|
|
|
|
cts_info("%s", __func__);
|
|
if(cts_dev->rtdata.is_chip_empty){
|
|
for (retry = 0; retry < 3; retry++) {
|
|
ret = cts_dev_get_sensor_id(cts_dev, &cts_dev->confdata.hw_sensor_id);
|
|
if (ret == 0) {
|
|
cts_info("Get hw sensor id: 0x%02x", cts_dev->confdata.hw_sensor_id);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
for (i = 0; i < ARRAY_SIZE(sensor_id_bin_table); i++) {
|
|
if ((strcmp(firmware->name, sensor_id_bin_table[i].name) == 0)) {
|
|
if(cts_dev->rtdata.is_chip_empty && retry >= 3){
|
|
cts_dev->confdata.fw_name_index = i;
|
|
cts_dev->confdata.fw_sensor_id_index = MAX_SUPPORT_ID_NUM;
|
|
cts_info("Chip %s is empty return default firmware in fs: chip_index:%d id:0x%02x id_index: %d",
|
|
firmware->name, i, sensor_id_bin_table[i].id_tables[MAX_SUPPORT_ID_NUM].id,
|
|
MAX_SUPPORT_ID_NUM);
|
|
return 0;
|
|
}
|
|
|
|
for(j=0; j< ARRAY_SIZE(sensor_id_bin_table[i].id_tables); j++){
|
|
if(sensor_id_bin_table[i].id_tables[j].id
|
|
== cts_dev->confdata.hw_sensor_id){
|
|
cts_dev->confdata.fw_name_index = i;
|
|
cts_dev->confdata.fw_sensor_id_index = j;
|
|
|
|
cts_info("Found %s firmware match sensor id in fs: chip_index:%d id:0x%02x id_index: %d",
|
|
firmware->name, i, cts_dev->confdata.hw_sensor_id, j);
|
|
return 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
cts_info("Not found %s firmware match sensor id: 0x%02x in fs",
|
|
firmware->name,cts_dev->confdata.hw_sensor_id);
|
|
return -EINVAL;
|
|
}
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
#ifdef CFG_CTS_DRIVER_BUILTIN_FIRMWARE
|
|
#ifdef CONFIG_CTS_SYSFS
|
|
int cts_get_chip_type_num_driver_builtin(void)
|
|
{
|
|
return NUM_DRIVER_BUILTIN_FIRMWARE;
|
|
}
|
|
|
|
int cts_get_fw_num_driver_builtin(void)
|
|
{
|
|
#ifdef SUPPORT_SENSOR_ID
|
|
return MAX_SUPPORT_ID_NUM+1;
|
|
#else
|
|
return 1;
|
|
#endif
|
|
}
|
|
|
|
int cts_get_fw_sensor_id_driver_builtin(u32 chip_index, u32 fw_index)
|
|
{
|
|
#ifdef SUPPORT_SENSOR_ID
|
|
return sensor_id_array_table[chip_index].id_tables[fw_index].id;
|
|
#else
|
|
return 0xff;
|
|
#endif
|
|
}
|
|
|
|
int cts_get_fw_version_driver_builtin(const struct cts_firmware *firmware)
|
|
{
|
|
return FIRMWARE_VERSION(firmware, firmware->ver_offset);
|
|
}
|
|
int cts_get_chip_type_index_driver_builtin(struct cts_device *cts_dev)
|
|
{
|
|
int i;
|
|
for(i=0; i< cts_get_chip_type_num_driver_builtin(); i++){
|
|
if(strcmp(cts_dev->hwdata->name, cts_driver_builtin_firmwares[i].name) == 0){
|
|
return i;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
const struct cts_firmware *cts_request_driver_builtin_firmware_by_name(const char *name)
|
|
{
|
|
const struct cts_firmware *firmware;
|
|
int i;
|
|
|
|
#if 1
|
|
cts_info("Request driver builtin by name '%s'", name);
|
|
|
|
firmware = cts_driver_builtin_firmwares;
|
|
for (i = 0; i < NUM_DRIVER_BUILTIN_FIRMWARE; i++, firmware++) {
|
|
if (strcmp(firmware->name, name) == 0) {
|
|
if (is_firmware_valid(firmware)) {
|
|
cts_info("Found driver builtin '%s' "
|
|
"hwid: %04x fwid: %04x size: %zu ver: %04x",
|
|
firmware->name, firmware->hwid, firmware->fwid,
|
|
firmware->size, FIRMWARE_VERSION(firmware, firmware->ver_offset));
|
|
return firmware;
|
|
}
|
|
|
|
cts_warn("Found driver builtin '%s' "
|
|
"hwid: %04x fwid: %04x size: %zu invalid",
|
|
firmware->name, firmware->hwid, firmware->hwid, firmware->size);
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
#endif
|
|
}
|
|
|
|
|
|
const struct cts_firmware *cts_request_driver_builtin_firmware_by_index(
|
|
struct cts_device *cts_dev, u32 chip_index, u32 fw_index)
|
|
{
|
|
const struct cts_firmware *firmware;
|
|
//int i;
|
|
|
|
cts_info("Request driver builtin by chip index %u firmware index %u", chip_index,fw_index);
|
|
|
|
if ((chip_index < NUM_DRIVER_BUILTIN_FIRMWARE)
|
|
&&(fw_index < cts_get_fw_num_driver_builtin())){
|
|
firmware = cts_driver_builtin_firmwares + chip_index;
|
|
#ifdef SUPPORT_SENSOR_ID
|
|
memcpy(&cts_dev->confdata.firmware, firmware, sizeof(struct cts_firmware));
|
|
cts_dev->confdata.firmware.data = sensor_id_array_table[chip_index].id_tables[fw_index].array;
|
|
cts_dev->confdata.firmware.size = sensor_id_array_table[chip_index].id_tables[fw_index].size;
|
|
firmware = &cts_dev->confdata.firmware;
|
|
#else
|
|
|
|
#endif
|
|
if (is_firmware_valid(firmware)) {
|
|
cts_info("Found driver builtin '%s' "
|
|
"hwid: %04x fwid: %04x size: %zu ver: %04x",
|
|
firmware->name, firmware->hwid, firmware->fwid,
|
|
firmware->size, FIRMWARE_VERSION(firmware, firmware->ver_offset));
|
|
return firmware;
|
|
}
|
|
cts_warn("Found driver builtin '%s' "
|
|
"hwid: %04x fwid: %04x size: %zu INVALID",
|
|
firmware->name, firmware->hwid, firmware->hwid, firmware->size);
|
|
} else {
|
|
cts_warn("Request driver builtin by chip_index %u too large >= %d"
|
|
"or fw_index %u too large >= %d",
|
|
chip_index, NUM_DRIVER_BUILTIN_FIRMWARE,
|
|
fw_index,cts_get_fw_num_driver_builtin());
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
#endif /* CONFIG_CTS_SYSFS */
|
|
|
|
static struct cts_firmware * cts_request_newer_driver_builtin_firmware(
|
|
struct cts_device *cts_dev, u16 hwid, u16 fwid, u16 device_fw_ver)
|
|
{
|
|
#define MATCH_HWID(firmware, hwid) \
|
|
((firmware)->hwid == (hwid)) //(hwid) == CTS_HWID_ANY ||
|
|
#define MATCH_FWID(firmware, fwid) \
|
|
((firmware)->fwid == (fwid)) //(fwid) == CTS_FWID_ANY ||
|
|
|
|
struct cts_firmware *firmware = NULL;
|
|
int i = 0;
|
|
#ifdef SUPPORT_SENSOR_ID
|
|
int ret = 0;
|
|
#endif
|
|
|
|
cts_info("Request driver builtin if match hwid: %04x fwid: %04x && ver > %04x",
|
|
hwid, fwid, device_fw_ver);
|
|
|
|
firmware = cts_driver_builtin_firmwares;
|
|
for (i = 0; i < ARRAY_SIZE(cts_driver_builtin_firmwares); i++, firmware++) {
|
|
if (MATCH_HWID(firmware, hwid) || MATCH_FWID(firmware, fwid)) {
|
|
|
|
memcpy(&cts_dev->confdata.firmware, firmware, sizeof(struct cts_firmware));
|
|
|
|
#ifdef SUPPORT_SENSOR_ID
|
|
ret = cts_compare_sensor_id_from_bultin(cts_dev, &cts_dev->confdata.firmware);
|
|
if(ret){
|
|
cts_err("Not found match sensor id firmware, compare sensor id fail");
|
|
goto No_newer_matched_fw;
|
|
}
|
|
#endif
|
|
|
|
#if 1
|
|
if (!is_firmware_valid(&cts_dev->confdata.firmware)) {
|
|
cts_err("Found driver builtin '%s' "
|
|
"hwid: %04x fwid: %04x INVALID ",
|
|
firmware->name, firmware->hwid, firmware->fwid);
|
|
continue;
|
|
}
|
|
|
|
firmware = &cts_dev->confdata.firmware;
|
|
|
|
cts_info("Found match driver builtin '%s' "
|
|
"hwid: %04x fwid: %04x size: %zu ver: %04x",
|
|
firmware->name, firmware->hwid, firmware->fwid,
|
|
firmware->size, FIRMWARE_VERSION(firmware, firmware->ver_offset));
|
|
#endif
|
|
|
|
#ifdef SUPPORT_SENSOR_ID
|
|
if(1 == cts_dev->confdata.is_sensor_matched)
|
|
#else
|
|
if(1)
|
|
#endif
|
|
{
|
|
if(FIRMWARE_VERSION(firmware, firmware->ver_offset) > device_fw_ver) {
|
|
cts_info("Found newer match driver builtin '%s' "
|
|
"hwid: %04x fwid: %04x size: %zu ver: %04x > %04x",
|
|
firmware->name, firmware->hwid, firmware->fwid,
|
|
firmware->size, FIRMWARE_VERSION(firmware, firmware->ver_offset), device_fw_ver);
|
|
return firmware;
|
|
}else{
|
|
goto No_newer_matched_fw;
|
|
}
|
|
}else{
|
|
if(cts_dev->rtdata.is_chip_empty){
|
|
cts_info("Chip is empty force update default firmware!!! ");
|
|
}else{
|
|
cts_info("Firmware in chip is unmatch force update match sensor id firmware!!! ");
|
|
}
|
|
return firmware;
|
|
}
|
|
}
|
|
}
|
|
|
|
No_newer_matched_fw:
|
|
|
|
cts_info("No newer driver builtin found");
|
|
return NULL;
|
|
|
|
#undef MATCH_HWID
|
|
#undef MATCH_FWID
|
|
}
|
|
#endif /* CFG_CTS_DRIVER_BUILTIN_FIRMWARE */
|
|
|
|
#ifdef CFG_CTS_FIRMWARE_IN_FS
|
|
bool is_filesystem_mounted(const char *filepath)
|
|
{
|
|
struct path root_path;
|
|
struct path path;
|
|
int ret = 0;
|
|
|
|
ret = kern_path("/", LOOKUP_FOLLOW, &root_path);
|
|
if (ret) {
|
|
return false;
|
|
}
|
|
|
|
ret = kern_path(filepath, LOOKUP_FOLLOW, &path);
|
|
if (ret) {
|
|
goto err_put_root_path;
|
|
}
|
|
|
|
if (path.mnt->mnt_sb == root_path.mnt->mnt_sb) {
|
|
/* not mounted */
|
|
ret = false;
|
|
} else {
|
|
ret = true;
|
|
}
|
|
|
|
path_put(&path);
|
|
err_put_root_path:
|
|
path_put(&root_path);
|
|
|
|
return !!ret;
|
|
}
|
|
|
|
struct cts_firmware *cts_request_newer_firmware_from_fs(
|
|
const struct cts_device *cts_dev, const char *filepath, u16 curr_version)
|
|
{
|
|
struct cts_firmware *firmware;
|
|
struct file *file;
|
|
int ret, read_size = 0;
|
|
u8 buff[2];
|
|
u16 version = 0;
|
|
loff_t pos = 0;
|
|
|
|
cts_info("Request from file '%s' if version > %04x",
|
|
filepath, curr_version);
|
|
|
|
firmware = (struct cts_firmware *)kzalloc(sizeof(*firmware), GFP_KERNEL);
|
|
if (firmware == NULL) {
|
|
cts_err("Request from file alloc struct firmware failed");
|
|
return NULL;
|
|
}
|
|
|
|
firmware->name = cts_dev->hwdata->name;
|
|
firmware->fwid = cts_dev->hwdata->fwid;
|
|
firmware->hwid = cts_dev->hwdata->hwid;
|
|
firmware->ver_offset = cts_dev->hwdata->ver_offset;
|
|
|
|
file = filp_open(filepath, O_RDONLY, 0);
|
|
if (IS_ERR(file)) {
|
|
cts_err("Open file '%s' failed %ld", filepath, PTR_ERR(file));
|
|
goto err_free_firmware;
|
|
}
|
|
|
|
firmware->size = file_inode(file)->i_size;
|
|
if (!is_firmware_size_valid(firmware)) {
|
|
cts_info("File '%s' size: %zu invalid", filepath, firmware->size);
|
|
goto err_close_file;
|
|
}
|
|
|
|
pos = FIRMWARE_VERSION_OFFSET;
|
|
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,14,0)
|
|
read_size = kernel_read(file, buff, 2, &pos);
|
|
#else
|
|
read_size = kernel_read(file, pos, buff, 2);
|
|
#endif
|
|
if (read_size < 0) {
|
|
cts_err("Read version from offset 0x100 failed");
|
|
goto err_close_file;
|
|
}
|
|
version = get_unaligned_le16(buff);
|
|
|
|
#ifdef SUPPORT_SENSOR_ID
|
|
if(1 == cts_dev->confdata.is_sensor_matched){
|
|
if (version <= curr_version) {
|
|
cts_info("File '%s' size: %zu version: %04x <= %04x",
|
|
filepath, firmware->size, version, curr_version);
|
|
goto err_close_file;
|
|
}
|
|
}
|
|
#else
|
|
if (version <= curr_version) {
|
|
cts_info("File '%s' size: %zu version: %04x <= %04x",
|
|
filepath, firmware->size, version, curr_version);
|
|
goto err_close_file;
|
|
}
|
|
#endif
|
|
|
|
cts_info("File '%s' size: %zu version: %04x",
|
|
filepath, firmware->size, version);
|
|
|
|
firmware->data = (u8 *)kmalloc(firmware->size, GFP_KERNEL);
|
|
if (firmware->data == NULL) {
|
|
cts_err("Request form fs alloc firmware data failed");
|
|
goto err_close_file;
|
|
}
|
|
|
|
pos = 0;
|
|
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,14,0)
|
|
read_size = kernel_read(file, firmware->data, firmware->size, &pos);
|
|
#else
|
|
read_size = kernel_read(file, pos, firmware->data, firmware->size);
|
|
#endif
|
|
if (read_size < 0 || read_size != firmware->size) {
|
|
cts_err("Request from fs read whole file failed %d", read_size);
|
|
goto err_free_firmware_data;
|
|
}
|
|
|
|
ret = filp_close(file, NULL);
|
|
if (ret) {
|
|
cts_warn("Close file '%s' failed %d", filepath, ret);
|
|
}
|
|
|
|
firmware->is_fw_in_fs = true;
|
|
return firmware;
|
|
|
|
err_free_firmware_data:
|
|
kfree(firmware->data);
|
|
err_close_file:
|
|
filp_close(file, NULL);
|
|
err_free_firmware:
|
|
kfree(firmware);
|
|
firmware = NULL;
|
|
|
|
return NULL;
|
|
}
|
|
|
|
const struct cts_firmware *cts_request_firmware_from_fs(
|
|
const struct cts_device *cts_dev, const char *filepath)
|
|
{
|
|
cts_info("Request from file '%s'", filepath);
|
|
|
|
return cts_request_newer_firmware_from_fs(cts_dev,filepath, 0);
|
|
}
|
|
|
|
int cts_update_firmware_from_file(struct cts_device *cts_dev,
|
|
const char *filepath, bool to_flash)
|
|
{
|
|
const struct cts_firmware *firmware;
|
|
int ret = 0;
|
|
|
|
cts_info("Update from file '%s' to %s", filepath,
|
|
to_flash ? "flash" : "sram");
|
|
|
|
firmware = cts_request_firmware_from_fs(cts_dev, filepath);
|
|
if(firmware == NULL) {
|
|
cts_err("Request from file '%s' failed", filepath);
|
|
return -EFAULT;
|
|
}
|
|
|
|
ret = cts_update_firmware(cts_dev, firmware, to_flash);
|
|
if (ret) {
|
|
cts_err("Update to %s from file failed %d",
|
|
to_flash ? "flash" : "sram", ret);
|
|
goto err_release_firmware;
|
|
}
|
|
|
|
cts_info("Update from file success");
|
|
|
|
err_release_firmware:
|
|
cts_release_firmware(firmware);
|
|
|
|
return ret;
|
|
|
|
}
|
|
#endif /*CFG_CTS_FIRMWARE_IN_FS*/
|
|
|
|
struct cts_firmware *cts_request_firmware(
|
|
struct cts_device *cts_dev,u16 hwid, u16 fwid, u16 curr_firmware_ver)
|
|
{
|
|
#ifdef CFG_CTS_FIRMWARE_IN_FS
|
|
int i;
|
|
const u8 *p=NULL;
|
|
#endif
|
|
struct cts_firmware *firmware_builtin = NULL;
|
|
struct cts_firmware *firmware_from_file = NULL;
|
|
#if (defined(CFG_CTS_FIRMWARE_IN_FS) && defined(SUPPORT_SENSOR_ID))
|
|
int ret = 0;
|
|
#endif
|
|
|
|
#if 1
|
|
if (hwid == CTS_HWID_INVALID) {
|
|
hwid = CTS_HWID_ANY;
|
|
}
|
|
if (fwid == CTS_FWID_INVALID) {
|
|
fwid = CTS_FWID_ANY;
|
|
}
|
|
|
|
cts_info("Request newer firmware if match hwid: %04x fwid: %04x && ver > %04x",
|
|
hwid, fwid, curr_firmware_ver);
|
|
|
|
#ifdef CFG_CTS_DRIVER_BUILTIN_FIRMWARE
|
|
firmware_builtin = cts_request_newer_driver_builtin_firmware(
|
|
cts_dev,hwid, fwid, curr_firmware_ver);
|
|
#endif /* CFG_CTS_DRIVER_BUILTIN_FIRMWARE */
|
|
|
|
#ifdef CFG_CTS_KERNEL_BUILTIN_FIRMWARE
|
|
|
|
#endif /* CFG_CTS_DRIVER_BUILTIN_FIRMWARE */
|
|
|
|
#ifdef CFG_CTS_FIRMWARE_IN_FS
|
|
#ifdef SUPPORT_SENSOR_ID
|
|
ret = cts_compare_sensor_id_from_fs(cts_dev, &cts_dev->confdata.firmware);
|
|
if(ret){
|
|
firmware_from_file = NULL;
|
|
}else{
|
|
p= sensor_id_bin_table[cts_dev->confdata.fw_name_index].id_tables[cts_dev->confdata.fw_sensor_id_index].bin;
|
|
cts_info("chip index: %d bin file path index: %d",cts_dev->confdata.fw_name_index,
|
|
cts_dev->confdata.fw_sensor_id_index);
|
|
|
|
if (is_filesystem_mounted(p)){
|
|
firmware_from_file = cts_request_newer_firmware_from_fs(
|
|
cts_dev, p, firmware_builtin ? FIRMWARE_VERSION(firmware_builtin, firmware_builtin->ver_offset) :
|
|
curr_firmware_ver);
|
|
}
|
|
}
|
|
#else
|
|
/* Check firmware in file system when probe only when build to .ko */
|
|
|
|
for (i = 0; i < ARRAY_SIZE(bin_table); i++) {
|
|
if (strcmp(cts_dev->hwdata->name, bin_table[i].name) == 0){
|
|
p = bin_table[i].bin;
|
|
cts_info("Request bin file from fs path index: %d",i);
|
|
break;
|
|
}
|
|
}
|
|
if(p){
|
|
if (is_filesystem_mounted(p)) {
|
|
firmware_from_file = cts_request_newer_firmware_from_fs(
|
|
cts_dev,p,firmware_builtin ?
|
|
FIRMWARE_VERSION(firmware_builtin, firmware_builtin->ver_offset) :curr_firmware_ver);
|
|
}
|
|
}else{
|
|
firmware_from_file = NULL;
|
|
}
|
|
|
|
#endif
|
|
#endif /* CFG_CTS_FIRMWARE_IN_FS */
|
|
|
|
return firmware_from_file ? firmware_from_file : firmware_builtin;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
void cts_release_firmware(const struct cts_firmware *firmware)
|
|
{
|
|
cts_info("Release firmware");
|
|
|
|
/* Builtin firmware with non-NULL name, no need to free*/
|
|
if (firmware && firmware->is_fw_in_fs) {
|
|
kfree(firmware->data);
|
|
kfree(firmware);
|
|
}
|
|
}
|
|
|
|
int cts_update_firmware(struct cts_device *cts_dev,
|
|
const struct cts_firmware *firmware, bool to_flash)
|
|
{
|
|
|
|
int ret, retries = 0;
|
|
|
|
cts_info("Update firmware to %s ver: %04x size: %zu",
|
|
to_flash ? "flash" : "sram",
|
|
FIRMWARE_VERSION(firmware,firmware->ver_offset), firmware->size);
|
|
|
|
cts_dev->rtdata.updating = true;
|
|
|
|
retries = 0;
|
|
|
|
retry_upgrade:
|
|
|
|
retries++;
|
|
ret = cts_enter_program_mode(cts_dev);
|
|
if (ret) {
|
|
cts_err("Device enter program mode failed %d", ret);
|
|
//return ret;
|
|
}
|
|
|
|
if(strcmp(firmware->name, "ICNT81xx") == 0){
|
|
ret = icnt87xx_fw_update(cts_dev, firmware, 1);
|
|
if (ret) {
|
|
cts_err("Update firmware failed %d ",ret);
|
|
}
|
|
}else if(strcmp(firmware->name, "ICNT87xx") == 0){
|
|
ret = icnt87xx_fw_update(cts_dev, firmware, 0);
|
|
if (ret) {
|
|
cts_err("Update firmware failed %d ",ret);
|
|
}
|
|
}else if(strcmp(firmware->name, "ICNT82xx") == 0){
|
|
|
|
|
|
}else if((strcmp(firmware->name, "ICNT85xx") == 0)
|
|
||(strcmp(firmware->name, "ICNT86xx") == 0)||(strcmp(firmware->name, "ICNT88xx") == 0)){
|
|
ret = icnt85xx_fw_update(cts_dev, firmware, to_flash);
|
|
if (ret) {
|
|
cts_err("Update firmware failed %d ",ret);
|
|
}
|
|
}else if(strcmp(firmware->name, "ICNT89xx") == 0){
|
|
ret = icnt89xx_fw_update(cts_dev, firmware, to_flash);
|
|
if (ret) {
|
|
cts_err("Update firmware failed %d ",ret);
|
|
}
|
|
}
|
|
|
|
if(ret){
|
|
if(retries < 3){
|
|
cts_err("Update firmware retry: %d ",retries);
|
|
goto retry_upgrade;
|
|
}
|
|
}
|
|
|
|
ret = cts_enter_normal_mode(cts_dev);
|
|
cts_dev->rtdata.updating = false;
|
|
|
|
#ifdef CONFIG_CTS_CHARGER_DETECT
|
|
if (cts_is_charger_exist(cts_dev)) {
|
|
cts_charger_plugin(cts_dev);
|
|
}
|
|
#endif /* CONFIG_CTS_CHARGER_DETECT */
|
|
|
|
#ifdef CONFIG_CTS_GLOVE
|
|
if (cts_is_glove_enabled(cts_dev)) {
|
|
cts_enter_glove_mode(cts_dev);
|
|
}
|
|
#endif
|
|
|
|
return ret;
|
|
|
|
//if (ret) {
|
|
// cts_err("Device enter normal mode failed %d", ret);
|
|
// goto out;
|
|
// }
|
|
|
|
//cts_dev->rtdata.i2c_addr = CTS_NORMAL_MODE_I2CADDR;
|
|
//cts_dev->rtdata.addr_width = 2;
|
|
// cts_dev->rtdata.program_mode = false;
|
|
// cts_dev->rtdata.updating = false;
|
|
// return ret;
|
|
|
|
}
|
|
|
|
bool cts_is_firmware_updating(const struct cts_device *cts_dev)
|
|
{
|
|
return cts_dev->rtdata.updating;
|
|
}
|
|
|