From 5540075a2b2cc758ef130115684a344e153cba12 Mon Sep 17 00:00:00 2001 From: tnyangc Date: Mon, 27 Mar 2023 15:24:51 +0800 Subject: [PATCH] sar sensor bring up -aw 1.sar sensor bring up 2.add aw driver Change-Id: I42564cc4393fdbe30a63722d544b7e84c578a177 Signed-off-by: tnyangc Reviewed-on: https://gerrit.mot.com/2554436 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Reviewed-by: Yuchang Guo Reviewed-by: Xiangpo Zhao Submit-Approved: Jira Key --- drivers/misc/awinic/sarsensor/Android.mk | 28 + drivers/misc/awinic/sarsensor/Kbuild | 30 + drivers/misc/awinic/sarsensor/Makefile | 11 + .../misc/awinic/sarsensor/aw9610x/aw9610x.c | 875 +++++++ .../misc/awinic/sarsensor/aw9620x/aw9620x.c | 655 +++++ .../awinic/sarsensor/aw9620x/aw_update_fw.c | 1557 ++++++++++++ .../misc/awinic/sarsensor/aw963xx/aw963xx.c | 1334 ++++++++++ drivers/misc/awinic/sarsensor/aw_sar.c | 2221 +++++++++++++++++ .../sarsensor/comm/aw_sar_comm_interface.c | 786 ++++++ include/linux/input/awinic/aw9610x.h | 582 +++++ include/linux/input/awinic/aw9620x.h | 453 ++++ include/linux/input/awinic/aw963xx.h | 1542 ++++++++++++ include/linux/input/awinic/aw_sar.h | 13 + .../input/awinic/aw_sar_chip_interface.h | 33 + .../input/awinic/aw_sar_comm_interface.h | 221 ++ include/linux/input/awinic/aw_sar_type.h | 359 +++ include/linux/input/awinic/aw_update_fw.h | 335 +++ .../input/awinic/aw_update_fw_interface.h | 14 + 18 files changed, 11049 insertions(+) create mode 100644 drivers/misc/awinic/sarsensor/Android.mk create mode 100644 drivers/misc/awinic/sarsensor/Kbuild create mode 100644 drivers/misc/awinic/sarsensor/Makefile create mode 100644 drivers/misc/awinic/sarsensor/aw9610x/aw9610x.c create mode 100644 drivers/misc/awinic/sarsensor/aw9620x/aw9620x.c create mode 100644 drivers/misc/awinic/sarsensor/aw9620x/aw_update_fw.c create mode 100644 drivers/misc/awinic/sarsensor/aw963xx/aw963xx.c create mode 100644 drivers/misc/awinic/sarsensor/aw_sar.c create mode 100644 drivers/misc/awinic/sarsensor/comm/aw_sar_comm_interface.c create mode 100644 include/linux/input/awinic/aw9610x.h create mode 100644 include/linux/input/awinic/aw9620x.h create mode 100644 include/linux/input/awinic/aw963xx.h create mode 100644 include/linux/input/awinic/aw_sar.h create mode 100644 include/linux/input/awinic/aw_sar_chip_interface.h create mode 100644 include/linux/input/awinic/aw_sar_comm_interface.h create mode 100644 include/linux/input/awinic/aw_sar_type.h create mode 100644 include/linux/input/awinic/aw_update_fw.h create mode 100644 include/linux/input/awinic/aw_update_fw_interface.h diff --git a/drivers/misc/awinic/sarsensor/Android.mk b/drivers/misc/awinic/sarsensor/Android.mk new file mode 100644 index 000000000000..b6ce7ab787e5 --- /dev/null +++ b/drivers/misc/awinic/sarsensor/Android.mk @@ -0,0 +1,28 @@ +DLKM_DIR := motorola/kernel/modules +LOCAL_PATH := $(call my-dir) + +ifeq ($(AW96XX_MTK_CHARGER),true) + KERNEL_CFLAGS += CONFIG_AW96XX_MTK_CHARGER=y +endif + +ifeq ($(AW96XX_USB_USE_ONLINE),true) + KERNEL_CFLAGS += CONFIG_AW96XX_POWER_SUPPLY_ONLINE=y +endif + +ifeq ($(AW96XX_MTK_KERNEL419_CHARGER_TYPE), true) + KERNEL_CFLAGS += CONFIG_AW96XX_MTK_KERNEL419_CHARGER_TYPE=y +endif + +ifeq ($(AW96XX_MTK_KERNEL5XX_CHARGER_TYPE),true) + KERNEL_CFLAGS += CONFIG_AW96XX_MTK_KERNEL5XX_CHARGER_TYPE=y +endif + +include $(CLEAR_VARS) +LOCAL_MODULE := awinic_sar.ko +LOCAL_MODULE_TAGS := optional +LOCAL_MODULE_PATH := $(KERNEL_MODULES_OUT) +LOCAL_ADDITIONAL_DEPENDENCIES := $(KERNEL_MODULES_OUT)/sensors_class.ko +#LOCAL_REQUIRED_MODULES := sensors_class.ko +KBUILD_OPTIONS_GKI += GKI_OBJ_MODULE_DIR=gki +include $(DLKM_DIR)/AndroidKernelModule.mk + diff --git a/drivers/misc/awinic/sarsensor/Kbuild b/drivers/misc/awinic/sarsensor/Kbuild new file mode 100644 index 000000000000..d33134f776de --- /dev/null +++ b/drivers/misc/awinic/sarsensor/Kbuild @@ -0,0 +1,30 @@ +# add -Wall to try to catch everything we can. +#MTK have kernel-4.14 and kernel-4.19 and kernel-5.10 in the same dir,so we can't use below method +#KERNEL_DIR_PATH = $(shell find $(TOP)/kernel* -type d -name "kernel-*" | head -1) +KERNEL_VERSION_NAME = $(shell basename $(KERNEL_DIR_PATH)) +EXTRA_CFLAGS += -Wall +EXTRA_CFLAGS += -I$(ANDROID_BUILD_TOP)/motorola/kernel/modules/include +EXTRA_CFLAGS += -I$(ANDROID_BUILD_TOP)/motorola/kernel/modules/include/linux/input/awinic +EXTRA_CFLAGS += -I$(ANDROID_BUILD_TOP)/$(KERNEL_VERSION_NAME)/drivers/base + +ifneq ($(filter m y,$(CONFIG_AW96XX_POWER_SUPPLY_ONLINE)),) + EXTRA_CFLAGS += -DCONFIG_USE_POWER_SUPPLY_ONLINE +endif + +ifneq ($(filter m y,$(CONFIG_AW96XX_MTK_CHARGER)),) + EXTRA_CFLAGS += -DCONFIG_AW96XX_MTK_CHARGER +endif + +ifneq ($(filter m y,$(CONFIG_AW96XX_MTK_KERNEL419_CHARGER_TYPE)),) + EXTRA_CFLAGS += -DCONFIG_AW96XX_MTK_KERNEL419_CHARGER_TYPE +endif + +ifneq ($(filter m y,$(CONFIG_AW96XX_MTK_KERNEL5XX_CHARGER_TYPE)),) + EXTRA_CFLAGS += -DCONFIG_AW96XX_MTK_KERNEL5XX_CHARGER_TYPE +endif + +KBUILD_EXTRA_SYMBOLS += $(CURDIR)/$(KBUILD_EXTMOD)/../../../sensors/$(GKI_OBJ_MODULE_DIR)/Module.symvers + +obj-m := awinic_sar.o +awinic_sar-objs := ./comm/aw_sar_comm_interface.o aw_sar.o ./aw9610x/aw9610x.o ./aw9620x/aw9620x.o ./aw9620x/aw_update_fw.o ./aw963xx/aw963xx.o + diff --git a/drivers/misc/awinic/sarsensor/Makefile b/drivers/misc/awinic/sarsensor/Makefile new file mode 100644 index 000000000000..62a13fd28500 --- /dev/null +++ b/drivers/misc/awinic/sarsensor/Makefile @@ -0,0 +1,11 @@ +KERNEL_SRC ?= /lib/modules/$(shell uname -r)/build + +all: + $(MAKE) -C $(KERNEL_SRC) M=$(shell pwd) modules $(KBUILD_OPTIONS) + +modules_install: + $(MAKE) INSTALL_MOD_STRIP=1 -C $(KERNEL_SRC) M=$(shell pwd) modules_install + +clean: + $(MAKE) -C $(KERNEL_SRC) M=$(PWD) clean + diff --git a/drivers/misc/awinic/sarsensor/aw9610x/aw9610x.c b/drivers/misc/awinic/sarsensor/aw9610x/aw9610x.c new file mode 100644 index 000000000000..2ac7804c9739 --- /dev/null +++ b/drivers/misc/awinic/sarsensor/aw9610x/aw9610x.c @@ -0,0 +1,875 @@ +#include "aw9610x.h" + +#define AW9610X_I2C_NAME "aw9610x_sar" +#define AW9610X_DRIVER_VERSION "v2.3.3" + +#define AW9610X_RETRIES (3) + +static struct aw_sar *g_aw_sar = NULL; + +//#define AW_INPUT_TRIGGER_TH1 +//#define AW_INPUT_TRIGGER_TH2 +//#define AW_INPUT_TRIGGER_TH3 + +static int32_t aw9610x_baseline_filter(struct aw_sar *p_sar) +{ + uint8_t i = 0; + uint32_t status0 = 0; + uint32_t status1 = 0; + struct aw9610x *aw9610x = (struct aw9610x *)p_sar->priv_data; + + aw_sar_i2c_read(p_sar->i2c, REG_STAT1, &status1); + aw_sar_i2c_read(p_sar->i2c, REG_STAT0, &status0); + + for (i = 0; i < AW9610X_CHANNEL_MAX; i++) { + if (((status1 >> i) & 0x01) == 1) { + if (aw9610x->satu_flag[i] == 0) { + aw_sar_i2c_read(p_sar->i2c, REG_BLFILT_CH0 + i * AW_CL1SPE_DEAL_OS, &aw9610x->satu_data[i]); + aw_sar_i2c_write(p_sar->i2c, REG_BLFILT_CH0 + i * AW_CL1SPE_DEAL_OS, ((aw9610x->satu_data[i] | 0x1fc) & 0x3fffffff)); + aw9610x->satu_flag[i] = 1; + } + } else if (((status1 >> i) & 0x01) == 0) { + if (aw9610x->satu_flag[i] == 1) { + if (((status0 >> (i + 24)) & 0x01) == 0) { + aw_sar_i2c_write(p_sar->i2c, REG_BLFILT_CH0 + i * AW_CL1SPE_DEAL_OS, aw9610x->satu_data[i]); + aw9610x->satu_flag[i] = 0; + } + } + } + } + + return AW_OK; +} + +static void aw9610x_saturat_release_handle(struct aw_sar *p_sar) +{ + uint32_t satu_irq = 0; + uint8_t i = 0; + uint32_t status0 = 0; + struct aw9610x *aw9610x = (struct aw9610x *)p_sar->priv_data; + + AWLOGD(p_sar->dev, "enter"); + + satu_irq = (aw9610x->irq_status >> 7) & 0x01; + if (satu_irq == 1) { + aw9610x_baseline_filter(p_sar); + } else { + aw_sar_i2c_read(p_sar->i2c, REG_STAT0, &status0); + for (i = 0; i < AW9610X_CHANNEL_MAX; i++) { + if (aw9610x->satu_flag[i] == 1) { + if (((status0 >> (i + 24)) & 0x01) == 0) { + aw_sar_i2c_write(p_sar->i2c, REG_BLFILT_CH0 + i * AW_CL1SPE_DEAL_OS, aw9610x->satu_data[i]); + aw9610x->satu_flag[i] = 0; + } + } + } + } + + AWLOGI(p_sar->dev, "satu_irq handle over!"); +} + +static void aw9610x_irq_handle(struct aw_sar *p_sar) +{ + uint8_t i = 0; + uint32_t curr_status = 0; + uint32_t curr_status_val = 0; + + AWLOGD(p_sar->dev, "enter"); + + aw_sar_i2c_read(p_sar->i2c, REG_STAT0, &curr_status_val); + AWLOGD(p_sar->dev, "channel = 0x%08x", curr_status_val); + + if (p_sar->channels_arr == NULL) { + AWLOGE(p_sar->dev, "input err!!!"); + return; + } + + for (i = 0; i < AW9610X_CHANNEL_MAX; i++) { + curr_status = + (((uint8_t)(curr_status_val >> (24 + i)) & 0x1)) +#ifdef AW_INPUT_TRIGGER_TH1 + | (((uint8_t)(curr_status_val >> (16 + i)) & 0x1) << 1) +#endif +#ifdef AW_INPUT_TRIGGER_TH2 + | (((uint8_t)(curr_status_val >> (8 + i)) & 0x1) << 2) +#endif +#ifdef AW_INPUT_TRIGGER_TH3 + | (((uint8_t)(curr_status_val >> (i)) & 0x1) << 3) +#endif + ; + //AWLOGI(p_sar->dev, "curr_state[%d] = 0x%x", i, curr_status); + + if (p_sar->channels_arr[i].used == AW_FALSE) { + //AWLOGD(p_sar->dev, "channels_arr[%d] no user", i); + continue; + } + if (p_sar->channels_arr[i].last_channel_info == curr_status) { + continue; + } + + switch (curr_status) { + case AW9610X_FAR: + input_report_abs(p_sar->channels_arr[i].input, ABS_DISTANCE, 0); + break; + case AW9610X_TRIGGER_TH0: + input_report_abs(p_sar->channels_arr[i].input, ABS_DISTANCE, 1); + break; +#ifdef AW_INPUT_TRIGGER_TH1 + case AW9610X_TRIGGER_TH1: + input_report_abs(p_sar->channels_arr[i].input, ABS_DISTANCE, 2); + break; +#endif +#ifdef AW_INPUT_TRIGGER_TH2 + case AW9610X_TRIGGER_TH2: + input_report_abs(p_sar->channels_arr[i].input, ABS_DISTANCE, 3); + break; +#endif +#ifdef AW_INPUT_TRIGGER_TH3 + case AW9610X_TRIGGER_TH3: + input_report_abs(p_sar->channels_arr[i].input, ABS_DISTANCE, 4); + break; +#endif + default: + AWLOGE(p_sar->dev, "error abs distance"); + return; + } + input_sync(p_sar->channels_arr[i].input); + + p_sar->channels_arr[i].last_channel_info = curr_status; + } +} + +static void aw9610x_version_aw9610x_private(struct aw_sar *p_sar) +{ + struct aw9610x *aw9610x = (struct aw9610x *)p_sar->priv_data; + + AWLOGD(p_sar->dev, "AW9610X enter"); + + if (aw9610x->satu_release == AW9610X_FUNC_ON) + aw9610x_saturat_release_handle(p_sar); +} + +static void aw9610x_irq_handle_func(uint32_t irq_status, void *data) +{ + struct aw_sar *p_sar = (struct aw_sar *)data; + struct aw9610x *aw9610x = (struct aw9610x *)p_sar->priv_data; + + AWLOGD(p_sar->dev, "enter"); + + AWLOGI(p_sar->dev, "IRQSRC = 0x%x", irq_status); + + switch (aw9610x->vers) { + case AW9610X: + aw9610x_version_aw9610x_private(p_sar); + break; + case AW9610XA: + break; + default: + break; + } + + aw9610x_irq_handle(p_sar); +} + +int32_t aw9610x_check_chipid(void *data) +{ + int32_t ret = -1; + uint32_t reg_val = 0; + struct aw_sar *p_sar = (struct aw_sar *)data; + + if (p_sar == NULL) { + return -AW_BIN_PARA_INVALID; + } + + ret = aw_sar_i2c_read(p_sar->i2c, REG_CHIPID, ®_val); + if (ret < 0) { + AWLOGE(p_sar->dev, "read CHIP ID failed: %d", ret); + } else { + reg_val = reg_val >> 16; + } + + if (reg_val == AW9610X_CHIP_ID) { + AWLOGI(p_sar->dev, "aw9610x detected, 0x%04x", reg_val); + return AW_OK; + } else { + AWLOGE(p_sar->dev, "unsupport dev, chipid is (0x%04x)", reg_val); + } + + return -AW_ERR; +} + +static const struct aw_sar_check_chipid_t g_aw9610x_check_chipid = { + .p_check_chipid_fn = aw9610x_check_chipid, +}; + +static ssize_t aw9610x_operation_mode_get(void *data, char *buf) +{ + ssize_t len = 0; + struct aw_sar *p_sar = (struct aw_sar *)data; + struct aw9610x *aw9610x = (struct aw9610x *)p_sar->priv_data; + + if (p_sar->last_mode == AW9610X_ACTIVE_MODE) + len += snprintf(buf + len, PAGE_SIZE - len, "operation mode: Active\n"); + else if (p_sar->last_mode == AW9610X_SLEEP_MODE) + len += snprintf(buf + len, PAGE_SIZE - len, "operation mode: Sleep\n"); + else if ((p_sar->last_mode == AW9610X_DEEPSLEEP_MODE) && (aw9610x->vers == AW9610XA)) + len += snprintf(buf + len, PAGE_SIZE - len, "operation mode: DeepSleep\n"); + else + len += snprintf(buf + len, PAGE_SIZE - len, "operation mode: Unconfirmed\n"); + + return len; +} + +static void aw9610x_chip_info_get(void *data, char *buf, ssize_t *p_len) +{ + uint32_t reg_data = 0; + struct aw_sar *p_sar = (struct aw_sar *)data; + struct aw9610x *aw9610x = (struct aw9610x *)p_sar->priv_data; + + *p_len += snprintf(buf + *p_len, PAGE_SIZE - *p_len, "sar%d, aw9610x chip driver version %s\n", p_sar->dts_info.sar_num, AW9610X_DRIVER_VERSION); + *p_len += snprintf(buf + *p_len, PAGE_SIZE - *p_len, "The driver supports UI\n"); + + aw_sar_i2c_read(p_sar->i2c, REG_CHIPID, ®_data); + *p_len += snprintf(buf + *p_len, PAGE_SIZE - *p_len, "chipid is 0x%08x\n", reg_data); + + aw_sar_i2c_read(p_sar->i2c, REG_IRQEN, ®_data); + *p_len += snprintf(buf + *p_len, PAGE_SIZE - *p_len, "REG_HOSTIRQEN is 0x%08x\n", reg_data); + + *p_len += snprintf(buf + *p_len, PAGE_SIZE - *p_len, "chip_name:%s bin_prase_chip_name:%s\n", + aw9610x->chip_name, aw9610x->chip_type); +} + +static const struct aw_sar_get_chip_info_t g_aw9610x_get_chip_info = { + .p_get_chip_info_node_fn = aw9610x_chip_info_get, +}; + +static void aw9610x_reg_version_comp(struct aw_sar *p_sar, struct aw_bin *aw_bin) +{ + uint8_t i = 0; + uint32_t blfilt1_data = 0; + uint32_t blfilt1_tmp = 0; + struct aw9610x *aw9610x = (struct aw9610x *)p_sar->priv_data; + + if ((aw9610x->chip_name[7] == 'A') && + (aw_bin->header_info[0].chip_type[7] == '\0')) { + AWLOGI(p_sar->dev, "enter"); + for (i = 0; i < 6; i++) { + aw_sar_i2c_read(p_sar->i2c, REG_BLFILT_CH0 + (0x3c * i), &blfilt1_data); + AWLOGD(p_sar->dev, "addr 0x%04x val: 0x%08x", REG_BLFILT_CH0 + (0x3c * i), blfilt1_data); + blfilt1_tmp = (blfilt1_data >> 25) & 0x1; + if (blfilt1_tmp == 1) { + AWLOGD(p_sar->dev, "ablfilt1_tmp is 1"); + aw_sar_i2c_write_bits(p_sar->i2c, REG_BLRSTRNG_CH0 + (0x3c * i), ~(0x3f), 1 << i); + } + } + } +} + +static int32_t aw9610x_load_reg_bin(struct aw_bin *aw_bin, struct aw_sar *p_sar) +{ + int32_t ret = 0; + + struct aw9610x *aw9610x = (struct aw9610x *)p_sar->priv_data; + + snprintf(aw9610x->chip_type, sizeof(aw9610x->chip_type), "%s", aw_bin->header_info[0].chip_type); + AWLOGE(p_sar->dev, "chip name: %s", aw9610x->chip_type); + + ret = aw_sar_load_reg(aw_bin, p_sar->i2c); + aw9610x_reg_version_comp(p_sar, aw_bin); + + return ret; +} + +static ssize_t aw9610x_get_self_cap_offset(void *data, char *buf) +{ + ssize_t len = 0; + uint8_t i = 0; + uint32_t reg_val = 0; + uint32_t coff_data = 0; + uint32_t coff_data_int = 0; + uint32_t coff_data_dec = 0; + uint8_t temp_data[20] = { 0 }; + struct aw_sar *p_sar = (struct aw_sar *)data; + + for (i = 0; i < AW9610X_CHANNEL_MAX; i++) { + aw_sar_i2c_read(p_sar->i2c, + REG_AFECFG1_CH0 + i * AW_CL1SPE_CALI_OS, ®_val); + coff_data = (reg_val >> 24) * 900 + + ((reg_val >> 16) & 0xff) * 13; + coff_data_int = coff_data / 1000; + coff_data_dec = coff_data % 1000; + snprintf(temp_data, sizeof(temp_data), "%d.%d", coff_data_int, + coff_data_dec); + len += snprintf(buf+len, PAGE_SIZE-len, + "PARASITIC_DATA_CH%d = %s pf\n", i, temp_data); + } + + return len; +} + +static const struct aw_sar_offset_t g_aw9610x_offset = { + .p_get_offset_node_fn = aw9610x_get_self_cap_offset, +}; + +static uint32_t attr_buf[] = { + 8, 10, + 9, 100, + 10, 1000, +}; + +static void aw9610x_addrblock_load(struct aw_sar *p_sar, const char *buf) +{ + uint32_t addrbuf[4] = { 0 }; + uint8_t temp_buf[2] = { 0 }; + uint32_t i = 0; + struct aw9610x *aw9610x = p_sar->priv_data; + uint8_t addr_bytes = aw9610x->aw_i2c_package.addr_bytes; + uint8_t reg_num = aw9610x->aw_i2c_package.reg_num; + + for (i = 0; i < addr_bytes; i++) { + if (reg_num < attr_buf[1]) { + temp_buf[0] = buf[attr_buf[0] + i * 5]; + temp_buf[1] = buf[attr_buf[0] + i * 5 + 1]; + } else if (reg_num >= attr_buf[1] && reg_num < attr_buf[3]) { + temp_buf[0] = buf[attr_buf[2] + i * 5]; + temp_buf[1] = buf[attr_buf[2] + i * 5 + 1]; + } else if (reg_num >= attr_buf[3] && reg_num < attr_buf[5]) { + temp_buf[0] = buf[attr_buf[4] + i * 5]; + temp_buf[1] = buf[attr_buf[4] + i * 5 + 1]; + } + if (sscanf(temp_buf, "%02x", &addrbuf[i]) == 1) + aw9610x->aw_i2c_package.init_addr[i] = (uint8_t)addrbuf[i]; + } +} + +static int32_t aw9610x_awrw_write_seq(struct aw_sar *p_sar) +{ + struct aw9610x *aw9610x = (struct aw9610x *)p_sar->priv_data; + uint8_t w_buf[228]; + uint8_t addr_bytes = aw9610x->aw_i2c_package.addr_bytes; + uint8_t msg_cnt = 0; + uint8_t data_bytes = aw9610x->aw_i2c_package.data_bytes; + uint8_t reg_num = aw9610x->aw_i2c_package.reg_num; + uint8_t *p_reg_data = aw9610x->aw_i2c_package.p_reg_data; + uint32_t msg_idx = 0; + + for (msg_idx = 0; msg_idx < addr_bytes; msg_idx++) { + w_buf[msg_idx] = aw9610x->aw_i2c_package.init_addr[msg_idx]; + AWLOGI(p_sar->dev, "w_buf_addr[%d] = 0x%02x", msg_idx, w_buf[msg_idx]); + } + + msg_cnt = addr_bytes; + for (msg_idx = 0; msg_idx < data_bytes * reg_num; msg_idx++) { + w_buf[msg_cnt] = *p_reg_data++; + msg_cnt++; + } + + return aw_sar_i2c_write_seq(p_sar->i2c, w_buf, msg_cnt); +} + +static void aw9610x_datablock_load(struct aw_sar *p_sar, const char *buf) +{ + uint32_t i = 0; + uint8_t reg_data[220] = { 0 }; + uint32_t databuf[220] = { 0 }; + uint8_t temp_buf[2] = { 0 }; + struct aw9610x *aw9610x = p_sar->priv_data; + uint8_t addr_bytes = aw9610x->aw_i2c_package.addr_bytes; + uint8_t data_bytes = aw9610x->aw_i2c_package.data_bytes; + uint8_t reg_num = aw9610x->aw_i2c_package.reg_num; + + for (i = 0; i < data_bytes * reg_num; i++) { + if (reg_num < attr_buf[1]) { + temp_buf[0] = buf[attr_buf[0] + (addr_bytes + i) * 5]; + temp_buf[1] = + buf[attr_buf[0] + (addr_bytes + i) * 5 + 1]; + } else if (reg_num >= attr_buf[1] && reg_num < attr_buf[3]) { + temp_buf[0] = buf[attr_buf[2] + (addr_bytes + i) * 5]; + temp_buf[1] = + buf[attr_buf[2] + (addr_bytes + i) * 5 + 1]; + } else if (reg_num >= attr_buf[3] && reg_num < attr_buf[5]) { + temp_buf[0] = buf[attr_buf[4] + (addr_bytes + i) * 5]; + temp_buf[1] = + buf[attr_buf[4] + (addr_bytes + i) * 5 + 1]; + } + sscanf(temp_buf, "%02x", &databuf[i]); + reg_data[i] = (uint8_t)databuf[i]; + } + aw9610x->aw_i2c_package.p_reg_data = reg_data; + aw9610x_awrw_write_seq(p_sar); +} + +static int32_t aw9610x_awrw_read_seq(struct aw_sar *p_sar, uint8_t *reg_data) +{ + struct aw9610x *aw9610x= (struct aw9610x *)p_sar->priv_data; + int32_t ret = 0; + uint8_t w_buf[4]; + uint8_t buf[228]; + uint8_t data_bytes = aw9610x->aw_i2c_package.data_bytes; + uint8_t addr_bytes = aw9610x->aw_i2c_package.addr_bytes; + uint8_t reg_num = aw9610x->aw_i2c_package.reg_num; + uint32_t msg_idx = 0; + uint32_t msg_cnt = data_bytes * reg_num; + + for (msg_idx = 0; msg_idx < addr_bytes; msg_idx++) { + w_buf[msg_idx] = aw9610x->aw_i2c_package.init_addr[msg_idx]; + AWLOGD(p_sar->dev, "w_buf_addr[%d] = 0x%02x", + msg_idx, w_buf[msg_idx]); + } + + ret = aw_sar_i2c_read_seq(p_sar->i2c, w_buf, 2, (uint8_t *)buf, msg_cnt); + + for (msg_idx = 0; msg_idx < msg_cnt; msg_idx++) { + reg_data[msg_idx] = buf[msg_idx]; + AWLOGD(p_sar->dev, "buf = 0x%02x", buf[msg_idx]); + } + + return ret; +} + +static ssize_t aw9610x_awrw_get(void *data, char *buf) +{ + struct aw_sar *p_sar = (struct aw_sar *)data; + struct aw9610x *aw9610x= (struct aw9610x *)p_sar->priv_data; + uint8_t reg_data[228] = { 0 }; + uint8_t i = 0; + ssize_t len = 0; + uint8_t reg_num = aw9610x->aw_i2c_package.reg_num; + uint8_t data_bytes = aw9610x->aw_i2c_package.data_bytes; + + aw9610x_awrw_read_seq(p_sar, reg_data); + for (i = 0; i < reg_num * data_bytes; i++) { + len += snprintf(buf + len, PAGE_SIZE - len, + "0x%02x,", reg_data[i]); + } + + snprintf(buf + len - 1, PAGE_SIZE - len, "\n"); + + return len; +}; + +static ssize_t aw9610x_awrw_set(void *data, const char *buf, size_t count) +{ + uint32_t datatype[3] = { 0 }; + struct aw_sar *p_sar = (struct aw_sar *)data; + struct aw9610x *aw9610x= (struct aw9610x *)p_sar->priv_data; + + if (sscanf(buf, "%d %d %d", &datatype[0], &datatype[1], &datatype[2]) == 3) { + aw9610x->aw_i2c_package.addr_bytes = (uint8_t)datatype[0]; + aw9610x->aw_i2c_package.data_bytes = (uint8_t)datatype[1]; + aw9610x->aw_i2c_package.reg_num = (uint8_t)datatype[2]; + + aw9610x_addrblock_load(p_sar, buf); + if (count > 7 + 5 * aw9610x->aw_i2c_package.addr_bytes) + aw9610x_datablock_load(p_sar, buf); + } + + return count; +} + +static int32_t aw9610x_get_chip_version(void *data) +{ + uint32_t fw_ver = 0; + int32_t ret = 0; + uint32_t firmvers = 0; + struct aw_sar *p_sar = (struct aw_sar *)data; + struct aw9610x *aw9610x = (struct aw9610x *)p_sar->priv_data; + + aw_sar_i2c_read(p_sar->i2c, REG_FWVER, &firmvers); + AWLOGD(p_sar->dev, "REG_FWVER = 0x%08x", firmvers); + + ret = aw_sar_i2c_read(p_sar->i2c, REG_FWVER2, &fw_ver); + if (ret < 0) { + AWLOGE(p_sar->dev, "read REG_FWVER2 err!"); + return -AW_ERR; + } + snprintf(aw9610x->chip_name, sizeof(aw9610x->chip_name), "AW9610X"); + p_sar->chip_type = AW_SAR_NONE_CHECK_CHIP; + + AWLOGD(p_sar->dev, "REG_FWVER2 : 0x%08x", fw_ver); + if (fw_ver == AW_CHIP_AW9610XA) { + aw9610x->vers = AW9610XA; + memcpy(aw9610x->chip_name + strlen(aw9610x->chip_name), "A", 2); + p_sar->chip_type = SAR_AW9610XA; + } else { + aw9610x->vers = AW9610X; + p_sar->chip_type = SAR_AW9610X; + aw9610x->chip_name[7] = '\0'; + } + AWLOGI(p_sar->dev, "the IC is = %s", aw9610x->chip_name); + + return AW_OK; +} + +#ifdef AW9610X_TVS_ABNORMAL_CAIL +static ssize_t aw9610x_set_aot(void *data) +{ + struct aw_sar *p_sar = (struct aw_sar *)data; + struct aw9610x *aw9610x = (struct aw9610x *)p_sar->priv_data; + uint32_t i = 0; + uint32_t irqen_reg_val = 0; + uint32_t reg_val_tmp = 0; + uint32_t max_delay_ms = AW9610X_AOT_OVER_DELAY_MAX_MS; + uint32_t scan_over_cnt = 0; + uint32_t ch_en = 0; + uint32_t scan_over_en = 0; + + //1. disable chip irq + aw_sar_i2c_read(p_sar->i2c, REG_IRQEN, &irqen_reg_val); + aw_sar_i2c_write(p_sar->i2c, REG_IRQEN, AW_REG_IRQEN_CLOSE); + + //2. aot cail + aw_sar_i2c_write_bits(p_sar->i2c, REG_SCANCTRL0, ~(AW9610X_AOT_MASK << AW9610X_AOT_BIT), + AW9610X_AOT_MASK << AW9610X_AOT_BIT); + // aot over + for (i = 0; i < max_delay_ms; i++) { + aw_sar_i2c_read(p_sar->i2c, REG_IRQSRC, ®_val_tmp); + if (((reg_val_tmp >> AW_REG_IRQSRC_AOT_OVER_BIT) & 0x01) == 1) { + AWLOGD(p_sar->dev, "aot over i = %d REG_IRQSRC:0X%X", i, reg_val_tmp); + break; + } + AWLOGD(p_sar->dev, "aot over i = %d REG_IRQSRC:0X%X", i, reg_val_tmp); + msleep(1); + } + + //3. scan 8 cnt over + aw_sar_i2c_read(p_sar->i2c, REG_SCANCTRL0, &ch_en); + aw_sar_i2c_read(p_sar->i2c, REG_CHINTEN, &scan_over_en); + if ((ch_en & AW9610X_AOT_MASK) != (scan_over_en & AW9610X_AOT_MASK)) { + aw_sar_i2c_write_bits(p_sar->i2c, REG_CHINTEN, ~(AW9610X_AOT_MASK), ch_en & (AW9610X_AOT_MASK)); + } + + for (scan_over_cnt = 0; scan_over_cnt < AW9610X_AOT_SCAN_OVER_CNT; scan_over_cnt++) { + for (i = 0; i < max_delay_ms; i++) { + aw_sar_i2c_read(p_sar->i2c, REG_IRQSRC, ®_val_tmp); + if (((reg_val_tmp >> REG_IRQSRC_SCAN_OVER_BIT) & 0x01) == 1) { + //AWLOGD(p_sar->dev, "scan %d cnt over REG_IRQSRC %d:0X%X", scan_over_cnt, i, reg_val_tmp); + break; + } + msleep(1); + } + } + if ((ch_en & AW9610X_AOT_MASK) != (scan_over_en & AW9610X_AOT_MASK)) { + aw_sar_i2c_write_bits(p_sar->i2c, REG_CHINTEN, ~(AW9610X_AOT_MASK), ch_en & (AW9610X_AOT_MASK)); + } + + if (aw9610x->vers == AW9610XA) { + //4. chip set sleep mode + aw_sar_i2c_write(p_sar->i2c, REG_CMD, AW9610X_SLEEP_MODE); + } else if (aw9610x->vers == AW9610X) { + aw_sar_i2c_write(p_sar->i2c, REG_CMD, AW9610X_DEEPSLEEP_MODE); //set aw9610x sleep mode + } + for (i = 0; i < max_delay_ms; i++) { + aw_sar_i2c_read(p_sar->i2c, REG_WST, ®_val_tmp); + if ((reg_val_tmp & 0xFF) == REG_REG_WST_SLEEP_MODE) { + AWLOGD(p_sar->dev, "sleep i = %d REG_WST:0X%X", i, reg_val_tmp); + break; + } + msleep(1); + } + + //5. write baseline data + for (i = 0; i < AW9610X_CHANNEL_MAX; i++) { + aw_sar_i2c_read(p_sar->i2c, REG_COMP_CH0 + i * AW9610X_REG_OFFSET_STEP, ®_val_tmp); + aw_sar_i2c_write(p_sar->i2c, REG_BASELINE_CH0 + i *AW9610X_REG_OFFSET_STEP, reg_val_tmp); + } + + //6. chip set active, irq recovery + aw_sar_i2c_write(p_sar->i2c, REG_CMD, AW9610X_ACTIVE_MODE); + aw_sar_i2c_write(p_sar->i2c, REG_IRQEN, irqen_reg_val); + + AWLOGD(p_sar->dev, "AW9610X_TVS_ABNORMAL_CAIL OVER!"); + + return AW_OK; +} +#else +static ssize_t aw9610x_set_aot(void *data) +{ + struct aw_sar *p_sar = (struct aw_sar *)data; + + aw_sar_i2c_write_bits(p_sar->i2c, REG_SCANCTRL0, ~(AW9610X_AOT_MASK << AW9610X_AOT_BIT), + (AW9610X_AOT_MASK) << AW9610X_AOT_BIT); + return AW_OK; +} +#endif + +static const struct aw_sar_aot_t g_aw9610x_aot = { + .p_set_aot_node_fn = aw9610x_set_aot, +}; + +/**********************mode operation start*******************************/ +static void aw9610x_enable_clock(void *i2c) +{ + aw_sar_i2c_write(i2c, REG_OSCEN, AW9610X_CPU_WORK_MASK); +} + +static uint32_t aw9610x_rc_irqscr(void *i2c) +{ + uint32_t val = 0; + aw_sar_i2c_read(i2c, REG_IRQSRC, &val); + return val; +} + +//Note: TVS exceptions need to be handled after active +static void aw9610x_set_active_cmd(void *i2c) +{ + aw_sar_i2c_write(i2c, REG_CMD, AW9610X_ACTIVE_MODE); + +#ifdef AW9610X_TVS_ABNORMAL_CAIL + AWLOGD(g_aw_sar->dev, "AW9610X_TVS_ABNORMAL_CAIL"); + if (g_aw_sar != NULL) { + aw9610x_set_aot(g_aw_sar); + } +#endif +} + +static void aw9610x_set_sleep_cmd(void *i2c) +{ + aw_sar_i2c_write(i2c, REG_CMD, AW9610X_SLEEP_MODE); +} + +static void aw9610x_set_deepsleep_cmd(void *i2c) +{ + aw_sar_i2c_write(i2c, REG_CMD, AW9610X_DEEPSLEEP_MODE); +} + +static const struct aw_sar_mode_set_t g_aw9610x_mode_set[] = { + { + .chip_id = SAR_AW9610XA | SAR_AW9610X, + .chip_mode = { + .curr_mode = AW9610X_ACTIVE_MODE, + .last_mode = AW9610X_DEEPSLEEP_MODE, + }, + .mode_switch_ops = { + .enable_clock = aw9610x_enable_clock, + .rc_irqscr = NULL, + .mode_update = aw9610x_set_active_cmd, + }, + }, + { + .chip_id = SAR_AW9610XA | SAR_AW9610X, + .chip_mode = { + .curr_mode = AW9610X_ACTIVE_MODE, + .last_mode = AW9610X_SLEEP_MODE, + }, + .mode_switch_ops = { + .enable_clock = NULL, + .rc_irqscr = NULL, + .mode_update = aw9610x_set_active_cmd, + }, + }, + { + .chip_id = SAR_AW9610XA | SAR_AW9610X, + .chip_mode = { + .curr_mode = AW9610X_ACTIVE_MODE, + .last_mode = AW9610X_ACTIVE_MODE, + }, + .mode_switch_ops = { + .enable_clock = NULL, + .rc_irqscr = NULL, + .mode_update = aw9610x_set_active_cmd, + }, + }, + { + .chip_id = SAR_AW9610XA | SAR_AW9610X, + .chip_mode = { + .curr_mode = AW9610X_SLEEP_MODE, + .last_mode = AW9610X_DEEPSLEEP_MODE, + }, + .mode_switch_ops = { + .enable_clock = aw9610x_enable_clock, + .rc_irqscr = NULL, + .mode_update = aw9610x_set_sleep_cmd, + }, + }, + { + .chip_id = SAR_AW9610XA | SAR_AW9610X, + .chip_mode = { + .curr_mode = AW9610X_SLEEP_MODE, + .last_mode = AW9610X_ACTIVE_MODE, + }, + .mode_switch_ops = { + .enable_clock = NULL, + .rc_irqscr = NULL, + .mode_update = aw9610x_set_sleep_cmd, + }, + }, + { + .chip_id = SAR_AW9610XA | SAR_AW9610X, + .chip_mode = { + .curr_mode = AW9610X_DEEPSLEEP_MODE, + .last_mode = AW9610X_SLEEP_MODE, + }, + .mode_switch_ops = { + .enable_clock = NULL, + .rc_irqscr = NULL, + .mode_update = aw9610x_set_deepsleep_cmd, + }, + }, + { + .chip_id = SAR_AW9610XA, + .chip_mode = { + .curr_mode = AW9610X_DEEPSLEEP_MODE, + .last_mode = AW9610X_ACTIVE_MODE, + }, + .mode_switch_ops = { + .enable_clock = NULL, + .rc_irqscr = aw9610x_rc_irqscr, + .mode_update = aw9610x_set_deepsleep_cmd, + }, + }, + { + .chip_id = SAR_AW9610X, + .chip_mode = { + .curr_mode = AW9610X_DEEPSLEEP_MODE, + .last_mode = AW9610X_ACTIVE_MODE, + }, + .mode_switch_ops = { + .enable_clock = NULL, + .rc_irqscr = NULL, + .mode_update = NULL, + }, + }, +}; +/**********************mode operation end*******************************/ + +static const struct aw_sar_irq_init_t g_aw9610x_irq_init = { + .flags = GPIOF_DIR_IN | GPIOF_INIT_HIGH, + .irq_flags = IRQF_TRIGGER_FALLING | IRQF_ONESHOT, + .handler = NULL, + .thread_fn = NULL, + .rc_irq_fn = aw9610x_rc_irqscr, + .irq_spec_handler_fn = aw9610x_irq_handle_func, +}; + +static const struct aw_sar_soft_rst_t g_aw9610x_soft_rst = { + .reg_rst = REG_RESET, + .reg_rst_val = 0, + .delay_ms = 20, +}; + +static const struct aw_sar_init_over_irq_t g_aw9610x_init_over_irq = { + .wait_times = 20, + .daley_step = 1, + .reg_irqsrc = REG_IRQSRC, + .irq_offset_bit = 0, + .irq_mask = 0x1, + .irq_flag = 0x1, +}; + +static const struct aw_sar_load_bin_t g_aw9610x_load_reg_bin = { + .bin_name = "aw9610x", + .bin_opera_func = (aw_sar_bin_opera_t)aw9610x_load_reg_bin, + .p_update_fn = NULL, +}; + +static const struct aw_sar_para_load_t g_aw9610x_reg_arr_para = { + .reg_arr = aw9610x_reg_default, + .reg_arr_len = (sizeof(aw9610x_reg_default) / sizeof(aw9610x_reg_default[0])), +}; + +static const struct aw_sar_diff_t g_aw9610x_diff = { + .diff0_reg = REG_DIFF_CH0, + .diff_step = 4, + .rm_float = AW9610x_DATA_PROCESS_FACTOR, +}; + +static const struct aw_sar_mode_t g_aw9610x_mode = { + .mode_set_arr = &g_aw9610x_mode_set[0], + .mode_set_arr_len = sizeof(g_aw9610x_mode_set) / sizeof(g_aw9610x_mode_set[0]), + .p_set_mode_node_fn = NULL, + .p_get_mode_node_fn = aw9610x_operation_mode_get, +}; + +static const struct aw_sar_reg_list_t g_aw9610x_reg_list = { + .reg_none_access = REG_NONE_ACCESS, + .reg_rd_access = REG_RD_ACCESS, + .reg_wd_access = REG_WR_ACCESS, + .reg_perm = (struct aw_sar_reg_data *)&g_aw9610x_reg_access[0], + .reg_num = sizeof(g_aw9610x_reg_access) / sizeof(g_aw9610x_reg_access[0]), +}; + +static const struct aw_sar_pm_t g_aw9610x_pm_chip_mode = { + .suspend_set_mode = AW9610X_SLEEP_MODE, + .resume_set_mode = AW9610X_ACTIVE_MODE, + .shutdown_set_mode = AW9610X_SLEEP_MODE, +}; + +static const struct aw_sar_chip_mode_t g_aw9610x_chip_mode = { + .init_mode = AW9610X_ACTIVE_MODE, + .active = AW9610X_ACTIVE_MODE, + .pre_init_mode = AW9610X_SLEEP_MODE, +}; + +static const struct aw_sar_regulator_config_t g_regulator_config = { + .vcc_name = "vcc", + .min_uV = AW9610X_SAR_VCC_MIN_UV, + .max_uV = AW9610X_SAR_VCC_MAX_UV, +}; + +struct aw_sar_awrw_t g_aw9610x_awrw = { + .p_set_awrw_node_fn = aw9610x_awrw_set, + .p_get_awrw_node_fn = aw9610x_awrw_get, +}; + +static const struct aw_sar_platform_config g_aw9610x_platform_config = { + .p_regulator_config = &g_regulator_config, + .p_irq_init = &g_aw9610x_irq_init, + .p_pm_chip_mode = &g_aw9610x_pm_chip_mode, +}; + +static const struct aw_sar_chip_config g_aw9610x_chip_config = { + .ch_num_max = AW9610X_CHANNEL_MAX, + + .p_platform_config = &g_aw9610x_platform_config, + + .p_check_chipid = &g_aw9610x_check_chipid, + .p_soft_rst = &g_aw9610x_soft_rst, + .p_init_over_irq = &g_aw9610x_init_over_irq, + .p_fw_bin = NULL, + .p_reg_bin = &g_aw9610x_load_reg_bin, + .p_chip_mode = &g_aw9610x_chip_mode, + + //Node usage parameters + .p_reg_list = &g_aw9610x_reg_list, + .p_reg_arr = &g_aw9610x_reg_arr_para, + .p_aot = &g_aw9610x_aot, + .p_diff = &g_aw9610x_diff, + .p_offset = &g_aw9610x_offset, + .p_mode = &g_aw9610x_mode, + .p_prox_fw = NULL, + .p_get_chip_info = &g_aw9610x_get_chip_info, + .p_aw_sar_awrw = &g_aw9610x_awrw, + .p_boot_bin = NULL, + + .p_other_operation = aw9610x_get_chip_version, + .p_other_opera_free = NULL, +}; + +int32_t aw9610x_init(struct aw_sar *p_sar) +{ + if (p_sar == NULL) { + AWLOGE(p_sar->dev, "para is NULL, error!"); + return -AW_ERR; + } + + g_aw_sar = p_sar; + + p_sar->priv_data = devm_kzalloc(p_sar->dev, sizeof(struct aw9610x), GFP_KERNEL); + if (p_sar->priv_data == NULL) { + AWLOGE(p_sar->dev, "priv_data failed to malloc memory!"); + return -AW_ERR; + } + + //Chip private function operation + p_sar->p_sar_para = &g_aw9610x_chip_config; + + return AW_OK; +} + +void aw9610x_deinit(struct aw_sar *p_sar) +{ + if (p_sar->priv_data != NULL) { + devm_kfree(p_sar->dev, p_sar->priv_data); + } +} diff --git a/drivers/misc/awinic/sarsensor/aw9620x/aw9620x.c b/drivers/misc/awinic/sarsensor/aw9620x/aw9620x.c new file mode 100644 index 000000000000..ed3f3f621268 --- /dev/null +++ b/drivers/misc/awinic/sarsensor/aw9620x/aw9620x.c @@ -0,0 +1,655 @@ +#include "aw9620x.h" +#include "aw_update_fw_interface.h" + +#define AW9620X_DRIVER_VERSION "v0.0.8" + +static uint32_t aw9620x_rc_irqscr(void *i2c); + +static void aw9620x_irq_handle_func(uint32_t irq_status, void *data) +{ + int32_t ret = 0; + uint32_t curr_status_val = 0; + uint32_t curr_status = 0; + uint8_t i = 0; + struct aw_sar *p_sar = (struct aw_sar *)data; + + AWLOGD(p_sar->dev, "IRQSRC = 0x%x", irq_status); + + ret = aw_sar_i2c_read(p_sar->i2c, REG_STAT0, &curr_status_val); + if (ret < 0) { + AWLOGE(p_sar->dev, "i2c IO error"); + return; + } + AWLOGD(p_sar->dev, "STAT0 = 0x%x", curr_status_val); + + for (i = 0; i < AW9620X_CHANNEL_NUM_MAX; i++) { + curr_status = (((curr_status_val >> (OFFSET_BIT_8 + i)) & 0x1) << 1) | + (((curr_status_val >> (i)) & 0x1)); + if (p_sar->channels_arr[i].used == AW_FALSE) { + continue; + } + if (p_sar->channels_arr[i].last_channel_info == curr_status) { + continue; + } + + switch (curr_status) { + case AW9620X_TRIGGER_FAR: + input_report_abs(p_sar->channels_arr[i].input, ABS_DISTANCE, AW9620X_TRIGGER_FAR); + break; + case AW9620X_TRIGGER_TH0: + input_report_abs(p_sar->channels_arr[i].input, ABS_DISTANCE, AW9620X_TRIGGER_TH0); + break; + case AW9620X_TRIGGER_TH1: + input_report_abs(p_sar->channels_arr[i].input, ABS_DISTANCE, AW9620X_TRIGGER_TH1); + break; + default: + AWLOGD(p_sar->dev, "error abs distance"); + return; + } + input_sync(p_sar->channels_arr[i].input); + + p_sar->channels_arr[i].last_channel_info = curr_status; + } +} + +int32_t aw9620x_check_chipid(void *data) +{ + int32_t ret = -AW_ERR; + uint32_t reg_val = 0; + struct aw_sar *p_sar = (struct aw_sar *)data; + + if ((p_sar == NULL) && ( p_sar->priv_data == NULL)) { + return -AW_BIN_PARA_INVALID; + } + + AWLOGD(p_sar->dev, "enter"); + + ret = aw_sar_i2c_read(p_sar->i2c, REG_CHIP_ID, ®_val); + if (ret < 0) { + AWLOGE(p_sar->dev, "read CHIP ID failed: %d", ret); + return -AW_ERR; + } + + switch (reg_val) + { + case AW96203CSR_CHIP_ID: + memcpy(p_sar->chip_name, "aw96203", 8); + AWLOGD(p_sar->dev, "AW96203CSR CHIP ID : 0x%x", reg_val); + break; + case AW96205DNR_CHIP_ID: + memcpy(p_sar->chip_name, "aw96205", 8); + AWLOGD(p_sar->dev, "AW96205DNR CHIP ID : 0x%x", reg_val); + break; + case AW96208CSR_CHIP_ID: + memcpy(p_sar->chip_name, "aw96208", 8); + AWLOGD(p_sar->dev, "AW96208CSR CHIP ID : 0x%x", reg_val); + break; + default: + AWLOGD(p_sar->dev, "no chipid,need update root and frimware,CHIP ID : 0x%x", reg_val); + return -AW_ERR_CHIPID; + break; + } + + p_sar->chip_type = AW_SAR_NONE_CHECK_CHIP; + + return AW_OK; +} + +static int32_t aw9620x_soft_reset(void *data) +{ + int32_t ret = 0; + struct aw_sar *p_sar = (struct aw_sar *)data; + + AWLOGD(p_sar->dev, "enter"); + + ret = aw_sar_i2c_write(p_sar->i2c, REG_ACCESSEN, REG_OPEN_APB_ACCESS_EN); + if (ret < 0) { + AWLOGE(p_sar->dev, "read REG_APB_ACCESS_EN err: %d", ret); + return -AW_ERR; + } + + ret = aw_sar_i2c_write(p_sar->i2c, AW_REG_FLASH_WAKE_UP, AW_REG_FLASH_WAKE_UP_ON); + if (ret < 0) { + AWLOGE(p_sar->dev, "read REG_APB_ACCESS_EN err: %d", ret); + return -AW_ERR; + } + msleep(1); + + ret = aw_sar_i2c_write(p_sar->i2c, REG_MCFG, REG_SET_MCFG00); + if (ret != AW_OK) { + AWLOGD(p_sar->dev, "REG_MCFG err"); + return ret; + } + msleep(AW9620X_REG_MCFG_DELAY_MS); + + ret = aw_sar_i2c_write(p_sar->i2c, REG_RSTNALL, AW9620X_REG_RSTNALL_VAL); + if (ret < 0) { + AWLOGE(p_sar->dev, "read soft_reset err: %d", ret); + return -AW_ERR; + } + + msleep(AW9620X_POWER_ON_DELAY_MS); + + ret = aw_sar_i2c_write(p_sar->i2c, AW_REG_FLASH_WAKE_UP, AW_REG_FLASH_WAKE_UP_OFF); + if (ret < 0) { + AWLOGE(p_sar->dev, "read REG_APB_ACCESS_EN err: %d", ret); + return -AW_ERR; + } + + return AW_OK; +} + +static int32_t aw9620x_load_reg_bin(struct aw_bin *aw_bin, void *load_bin_para) +{ + int32_t ret = 0; + struct aw_sar *p_sar = (struct aw_sar *)load_bin_para; +/* + if (p_sar->chip_name == NULL) { + AWLOGE(p_sar->dev, "p_sar->chip_name is NULL, error!"); + return -AW_ERR; + } +*/ + AWLOGE(p_sar->dev, "reg chip name: %s, soc chip name: %s, len = %d", + p_sar->chip_name, aw_bin->header_info[0].chip_type, aw_bin->info.len); + + ret = strncmp(p_sar->chip_name, aw_bin->header_info[0].chip_type, sizeof(aw_bin->header_info[0].chip_type)); + if (ret != 0) { + AWLOGE(p_sar->dev, + "load_binname(%s) incompatible with chip type(%s)", + p_sar->chip_name, aw_bin->header_info[0].chip_type); + //return -AW_ERR; + } + ret = aw_sar_load_reg(aw_bin, p_sar->i2c); + + return ret; +} + +/*************************fw update start************************/ +static int32_t aw9620x_reg_update_firmware(struct aw_bin *aw_bin, void *load_bin_para) +{ + uint32_t start_index = aw_bin->header_info[0].valid_data_addr; + int32_t ret = 0; + struct aw_sar *p_sar = (struct aw_sar *)load_bin_para; + + ret = aw9620x_reg_update_fw(p_sar->i2c, + &(aw_bin->info.data[start_index]), aw_bin->header_info[0].valid_data_len); + if (ret != AW_OK) { + AWLOGE(p_sar->dev, "reg update fw error"); + } + + ret = aw9620x_soft_reset(p_sar); + aw9620x_rc_irqscr(p_sar->i2c); + + return ret; +} + +//BOOT update +static int32_t aw9620x_reg_update_bt(struct aw_bin *aw_bin, void *load_bin_para) +{ + uint32_t start_index = aw_bin->header_info[0].valid_data_addr; + struct aw_sar *p_sar = (struct aw_sar *)load_bin_para; + + return aw9620x_reg_update_boot(p_sar->i2c, + &(aw_bin->info.data[start_index]), aw_bin->header_info[0].valid_data_len); +} + +static int32_t aw9620x_prot_update_firmware(struct aw_bin *aw_bin,void *load_bin_para) +{ + uint32_t start_index = aw_bin->header_info[0].valid_data_addr; + uint32_t fw_bin_version = aw_bin->header_info[0].app_version; + struct aw_sar *p_sar = (struct aw_sar *)load_bin_para; + //If the verification of flash firmware area fails, the version number will not be compared, and it will be loaded directly + uint8_t direct_updata_flag = p_sar->fw_fail_flag; + + return aw9620x_prot_update_fw(p_sar->i2c, direct_updata_flag, + &(aw_bin->info.data[start_index]), aw_bin->header_info[0].valid_data_len, fw_bin_version); +} + +static int32_t aw9620x_prox_direct_upgrade_firmware(struct aw_bin *aw_bin, void *load_bin_para) +{ + uint32_t start_index = aw_bin->header_info[0].valid_data_addr; + uint32_t fw_bin_version = aw_bin->header_info[0].app_version; + struct aw_sar *p_sar = (struct aw_sar *)load_bin_para; + + return aw9620x_prot_update_fw(p_sar->i2c, AW_TRUE, + &(aw_bin->info.data[start_index]), aw_bin->header_info[0].valid_data_len, fw_bin_version); +} + +/*************************fw update end************************/ + +/**********************mode operation start*******************************/ +static void aw9620x_enable_clock(void *i2c) +{ + aw_sar_i2c_write(i2c, REG_HOSTCTRL, REG_HOSTCTRL_EN); +} + +static uint32_t aw9620x_rc_irqscr(void *i2c) +{ + uint32_t val = 0; + aw_sar_i2c_read(i2c, REG_IRQSRC, &val); + return val; +} + +static void aw9620x_set_active_cmd(void *i2c) +{ + aw_sar_i2c_write(i2c, REG_CMD, AW9620X_ACTIVE_MODE); +} + +static void aw9620x_set_sleep_cmd(void *i2c) +{ + aw_sar_i2c_write(i2c, REG_CMD, AW9620X_SLEEP_MODE); +} + +static void aw9620x_set_deepsleep_cmd(void *i2c) +{ + aw_sar_i2c_write(i2c, REG_CMD, AW9620X_DEEPSLEEP_MODE); +} + +static ssize_t aw9620x_mode_operation_get(void *data, char *buf) +{ + uint32_t reg_val = 0; + struct aw_sar *p_sar = (struct aw_sar *)data; + + aw_sar_i2c_read(p_sar->i2c, REG_WST, ®_val); + + return snprintf(buf, PAGE_SIZE, "mode : %d, REG_WST :0x%x \n", + p_sar->last_mode, reg_val); +} + +static void aw9620x_mul_cap_parasitic_data_get(struct aw_sar *p_sar, + char *buf, uint32_t ch, uint32_t *p_len, uint32_t reg_data) +{ + uint32_t j = 0; + uint32_t reg_data_cfg_val = 0; + uint32_t off_m = 0; + uint32_t fine_off_f_temp = 0; + uint32_t off_f = 0; + uint32_t off_c = 0; + int32_t s_off_c = 0; + int32_t parasitic_data_temp = 0; + int32_t parasitic_data_int = 0; + int32_t parasitic_data_float = 0; + + if (((reg_data >> AW9620X_AFECFG3_CVOFF2X) & 0x1) == 0) { + aw_sar_i2c_read(p_sar->i2c, REG_AFECFG1_CH0 + AW9620X_CFG_REG_STEP * ch, ®_data_cfg_val); + off_m = (reg_data_cfg_val >> 16) & 0xff; + off_f = reg_data_cfg_val & 0xff; + fine_off_f_temp = off_f * AW9620X_FINE_ADJUST_STEP0; + off_c = (reg_data_cfg_val >> 8) & 0xff; + for (j = 0; j < 8; j++) { + s_off_c += ((1 - 2 * ((off_m >> j) & 0x1)) * ((off_c >> j) & 0x1) * aw_sar_pow2(j)) * AW9620X_COARSE_ADJUST_STEP0; + } + + parasitic_data_temp = AW_SAR_ABS((int32_t)fine_off_f_temp + s_off_c); + parasitic_data_int = parasitic_data_temp / AW9620X_PARA_TIMES; + parasitic_data_float = parasitic_data_temp % AW9620X_PARA_TIMES; + *p_len += snprintf(buf + *p_len, PAGE_SIZE - *p_len, "ch%d parasitic_data %d.%d pf\n", ch, parasitic_data_int, parasitic_data_float); + } else { + *p_len += snprintf(buf + *p_len, PAGE_SIZE - *p_len, "ch%d Mutual tolerance mode does not allow 2x to be configured", ch); + } +} + +static void aw9620x_self_cap_parasitic_data_get(struct aw_sar *p_sar, + char *buf, uint32_t ch, uint32_t *p_len, uint32_t reg_data) +{ + uint32_t reg_data_cfg = 0; + uint32_t reg_data_cfg_val = 0; + uint32_t reg_data_cfg_tmp0 = 0; + uint32_t reg_data_cfg_tmp1 = 0; + uint32_t cfg_int = 0; + uint32_t cfg_float = 0; + + aw_sar_i2c_read(p_sar->i2c, REG_AFECFG1_CH0 + AW9620X_CFG_REG_STEP * ch, ®_data_cfg_val); + + if (((reg_data >> AW9620X_AFECFG3_CVOFF2X) & 0x1) == 0) { + reg_data_cfg_tmp0 = (reg_data_cfg_val & 0xff) * AW9620X_FINE_ADJUST_STEP0; + reg_data_cfg_tmp1 = ((reg_data_cfg_val >> 8) & 0xff) * AW9620X_COARSE_ADJUST_STEP0; + } else { + reg_data_cfg_tmp0 = (reg_data_cfg_val & 0xff) * AW9620X_FINE_ADJUST_STEP1; + reg_data_cfg_tmp1 = ((reg_data_cfg_val >> 8) & 0xff) * AW9620X_COARSE_ADJUST_STEP1; + } + reg_data_cfg = reg_data_cfg_tmp0 + reg_data_cfg_tmp1; + cfg_int = reg_data_cfg / AW9620X_PARA_TIMES; + cfg_float = reg_data_cfg % AW9620X_PARA_TIMES; + *p_len+= snprintf(buf + *p_len, PAGE_SIZE - *p_len, "ch%d parasitic_data %d.%d pf\n", ch, cfg_int, cfg_float); +} + +static ssize_t aw9620x_offset_get(void *data, char *buf) +{ + uint32_t len = 0; + uint32_t i = 0; + uint32_t reg_data = 0; + struct aw_sar *p_sar = (struct aw_sar *)data; + + for (i = 0; i < AW9620X_CHANNEL_NUM_MAX; i++) { + aw_sar_i2c_read(p_sar->i2c, REG_AFECFG3_CH0 + AW9620X_CFG_REG_STEP * i, ®_data); + if (((reg_data >> AW9620X_AFECFG3_CVMULTUALMOD) & 0x1) != 1) { + //self contained + aw9620x_self_cap_parasitic_data_get(p_sar, buf, i, &len, reg_data); + } else { + //mutual compatibility + aw9620x_mul_cap_parasitic_data_get(p_sar, buf, i, &len, reg_data); + } + } + + return len; +} + +static void aw9620x_sar_chip_info_get(void *data, char *buf, ssize_t *p_len) +{ + uint32_t reg_data = 0; + struct aw_sar *p_sar = (struct aw_sar *)data; + + *p_len += snprintf(buf + *p_len, PAGE_SIZE - *p_len, "sar%d, aw9620x chip driver version:%s\n", + p_sar->dts_info.sar_num, AW9620X_DRIVER_VERSION); + *p_len += snprintf(buf + *p_len, PAGE_SIZE - *p_len, "The driver supports UI\n"); + + aw_sar_i2c_read(p_sar->i2c, REG_CHIP_ID, ®_data); + *p_len += snprintf(buf + *p_len, PAGE_SIZE - *p_len, "chipid is 0x%08x\n", reg_data); + + aw_sar_i2c_read(p_sar->i2c, REG_IRQEN, ®_data); + *p_len += snprintf(buf + *p_len, PAGE_SIZE - *p_len, "REG_HOSTIRQEN is 0x%08x\n", reg_data); +} + +static void aw9620x_get_firmware_version(void *data, char *buf, ssize_t *p_len) +{ + uint32_t fw_ver = 0; + struct aw_sar *p_sar = (struct aw_sar *)data; + + aw_sar_i2c_read(p_sar->i2c, REG_FWVER, &fw_ver); + + *p_len += snprintf(buf + *p_len, PAGE_SIZE - *p_len, "current firmware version is 0x%08x\n", fw_ver); +} + +static int32_t aw9320x_get_err_info(void *data) +{ + uint32_t err_code = 0; + uint32_t boot_mode = 0; + uint32_t jump_info = 0; + struct aw_sar *p_sar = (struct aw_sar *)data; + + aw_sar_i2c_write(p_sar->i2c, REG_ACCESSEN, REG_ACCESSEN_OPEN); + + //Get error check code,(0x09: Firmware verification failed.0x7:boot verification failed) + aw_sar_i2c_read(p_sar->i2c, AW9320X_SRAM_ERROR_CODE, &err_code); + + //The bit[31:24] must be 0, otherwise the boot cannot be jumped out actively + aw_sar_i2c_read(p_sar->i2c, REG_UPDATA_DIS, &jump_info); + + //bit8 0:Boot from ROM, 1: Boot from RAM + aw_sar_i2c_read(p_sar->i2c, REG_MCFG, &boot_mode); + + AWLOGE(p_sar->dev, "0x1c00:0x%x, 0x4744:0x%x, 0x4444:0x%x", err_code, jump_info, boot_mode); + + aw_sar_i2c_write(p_sar->i2c, REG_ACCESSEN, REG_ACCESSEN_CLOSE); + + return AW_OK; +} + + +static const struct aw_sar_mode_set_t g_aw9620x_mode_set[] = { + //0 + { + .chip_id = AW_SAR_NONE_CHECK_CHIP, + .chip_mode = { + .curr_mode = AW9620X_ACTIVE_MODE, + .last_mode = AW9620X_DEEPSLEEP_MODE, + }, + .mode_switch_ops = { + .enable_clock = aw9620x_enable_clock, + .rc_irqscr = NULL, + .mode_update = aw9620x_set_active_cmd, + }, + }, + //1 + { + .chip_id = AW_SAR_NONE_CHECK_CHIP, + .chip_mode = { + .curr_mode = AW9620X_ACTIVE_MODE, + .last_mode = AW9620X_SLEEP_MODE, + }, + .mode_switch_ops = { + .enable_clock = NULL, + .rc_irqscr = NULL, + .mode_update = aw9620x_set_active_cmd, + }, + }, + //1 + { + .chip_id = AW_SAR_NONE_CHECK_CHIP, + .chip_mode = { + .curr_mode = AW9620X_ACTIVE_MODE, + .last_mode = AW9620X_ACTIVE_MODE, + }, + .mode_switch_ops = { + .enable_clock = NULL, + .rc_irqscr = NULL, + .mode_update = aw9620x_set_active_cmd, + }, + }, + //2 + { + .chip_id = AW_SAR_NONE_CHECK_CHIP, + .chip_mode = { + .curr_mode = AW9620X_SLEEP_MODE, + .last_mode = AW9620X_DEEPSLEEP_MODE, + }, + .mode_switch_ops = { + .enable_clock = aw9620x_enable_clock, + .rc_irqscr = NULL, + .mode_update = aw9620x_set_sleep_cmd, + }, + }, + //3 + { + .chip_id = AW_SAR_NONE_CHECK_CHIP, + .chip_mode = { + .curr_mode = AW9620X_SLEEP_MODE, + .last_mode = AW9620X_ACTIVE_MODE, + }, + .mode_switch_ops = { + .enable_clock = NULL, + .rc_irqscr = NULL, + .mode_update = aw9620x_set_sleep_cmd, + }, + }, + //4 + { + .chip_id = AW_SAR_NONE_CHECK_CHIP, + .chip_mode = { + .curr_mode = AW9620X_DEEPSLEEP_MODE, + .last_mode = AW9620X_SLEEP_MODE, + }, + .mode_switch_ops = { + .enable_clock = NULL, + .rc_irqscr = NULL, + .mode_update = aw9620x_set_deepsleep_cmd, + }, + }, + //5 + { + .chip_id = AW_SAR_NONE_CHECK_CHIP, + .chip_mode = { + .curr_mode = AW9620X_DEEPSLEEP_MODE, + .last_mode = AW9620X_ACTIVE_MODE, + }, + .mode_switch_ops = { + .enable_clock = NULL, + .rc_irqscr = aw9620x_rc_irqscr, + .mode_update = aw9620x_set_deepsleep_cmd, + }, + }, +}; + +static const struct aw_sar_check_chipid_t g_aw9620x_check_chipid = { + .p_check_chipid_fn = aw9620x_check_chipid, +}; + +static const struct aw_sar_soft_rst_t g_aw9620x_soft_rst = { + .p_soft_reset_fn = aw9620x_soft_reset, +}; + +static const struct aw_sar_get_chip_info_t g_aw9620x_get_chip_info = { + .p_get_chip_info_node_fn = aw9620x_sar_chip_info_get, +}; + +#define AW9620X_MODE_SET_ARR_LEN (sizeof(g_aw9620x_mode_set) / sizeof(g_aw9620x_mode_set[0])) + +static const struct aw_sar_irq_init_t g_aw9620x_irq_init = { + .flags = GPIOF_DIR_IN | GPIOF_INIT_HIGH, + .irq_flags = IRQF_TRIGGER_FALLING | IRQF_ONESHOT, + .handler = NULL, + .thread_fn = NULL, + .rc_irq_fn = aw9620x_rc_irqscr, + .irq_spec_handler_fn = aw9620x_irq_handle_func, +}; + +static const struct aw_sar_init_over_irq_t g_aw9620x_init_over_irq = { + .wait_times = 100, + .daley_step = 1, + .reg_irqsrc = REG_IRQSRC, + .irq_offset_bit = 0, + .irq_mask = 0x1, + .irq_flag = 0x1, + .p_check_init_over_irq_fn = NULL, + .p_get_err_type_fn = aw9320x_get_err_info, +}; + +static const struct aw_sar_load_bin_t g_aw9620x_load_reg_bin = { + .bin_name = "aw9620x_reg", + .bin_opera_func = aw9620x_load_reg_bin, + .bin_load_fail_opera = NULL, + .p_update_fn = NULL, +}; + +static const struct aw_sar_load_bin_t g_aw9620x_load_boot_bin = { + .bin_name = "aw9620x_boot", + .bin_opera_func = aw9620x_reg_update_bt, + .bin_load_fail_opera = NULL, +}; + +static const struct aw_sar_load_bin_t g_aw9620x_load_fw_bin = { + .bin_name = "aw9620x_fw", + .bin_opera_func = aw9620x_prot_update_firmware, + .bin_load_fail_opera = aw9620x_reg_update_firmware, +}; + +//Node prox upgrade firmware +static const struct aw_sar_load_bin_t g_aw9620x_node_prox_load_fw_bin = { + .bin_name = "aw9620x_fw", + .bin_opera_func = aw9620x_prox_direct_upgrade_firmware, + .p_get_prot_update_fw_node_fn = aw9620x_get_firmware_version, + .bin_load_fail_opera = NULL, +}; + +//Node reg upgrade firmware +static const struct aw_sar_load_bin_t g_aw9620x_node_reg_load_fw_bin = { + .bin_name = "aw9620x_fw", + .bin_opera_func = aw9620x_reg_update_firmware, + .bin_load_fail_opera = NULL, +}; + +static const struct aw_sar_para_load_t g_aw9620x_reg_arr_para = { + .reg_arr = aw9620x_reg_default, + .reg_arr_len = sizeof(aw9620x_reg_default) / sizeof(aw9620x_reg_default[0]), +}; + +static const struct aw_sar_aot_t g_aw9620x_aot = { + .aot_reg = REG_SCANCTRL0, + .aot_mask = ~(0xff << 8), + .aot_flag = 0xff << 8, +}; + +static const struct aw_sar_diff_t g_aw9620x_diff = { + .diff0_reg = REG_DIFF_CH0, + .diff_step = AW9620X_REG_STEP, + .rm_float = AW9620X_REMOVE_FLOAT_COEF, +}; + +static const struct aw_sar_offset_t g_aw9620x_offset = { + .p_get_offset_node_fn = aw9620x_offset_get, +}; + +static const struct aw_sar_mode_t g_aw9620x_mode = { + .mode_set_arr = &g_aw9620x_mode_set[0], + .mode_set_arr_len = AW9620X_MODE_SET_ARR_LEN, + .p_get_mode_node_fn = aw9620x_mode_operation_get, +}; + +static const struct aw_sar_reg_list_t g_aw9620x_reg_list = { + .reg_none_access = REG_NONE_ACCESS, + .reg_rd_access = REG_RD_ACCESS, + .reg_wd_access = REG_WR_ACCESS, + .reg_perm = (struct aw_sar_reg_data *)&g_aw9620x_reg_access[0], + .reg_num = sizeof(g_aw9620x_reg_access) / sizeof(g_aw9620x_reg_access[0]), +}; + +static const struct aw_sar_pm_t g_aw9620x_pm_chip_mode = { + .suspend_set_mode = AW9620X_SLEEP_MODE, + .resume_set_mode = AW9620X_ACTIVE_MODE, + .shutdown_set_mode = AW9620X_SLEEP_MODE, +}; + +static const struct aw_sar_chip_mode_t g_aw9620x_chip_mode = { + .init_mode = AW9620X_ACTIVE_MODE, + .active = AW9620X_ACTIVE_MODE, + .pre_init_mode = AW9620X_SLEEP_MODE, +}; + +static const struct aw_sar_regulator_config_t g_aw9620x_regulator_config = { + .vcc_name = "vcc", + .min_uV = AW9620X_SAR_VCC_MIN_UV, + .max_uV = AW9620X_SAR_VCC_MAX_UV, +}; + +static const struct aw_sar_platform_config g_aw9620x_platform_config = { + .p_regulator_config = &g_aw9620x_regulator_config, + .p_irq_init = &g_aw9620x_irq_init, + .p_pm_chip_mode = &g_aw9620x_pm_chip_mode, +}; + +static const struct aw_sar_chip_config g_aw9620x_chip_config = { + .ch_num_max = AW9620X_CHANNEL_NUM_MAX, + + .p_platform_config = &g_aw9620x_platform_config, + + .p_check_chipid = &g_aw9620x_check_chipid, + .p_soft_rst = &g_aw9620x_soft_rst, + .p_init_over_irq = &g_aw9620x_init_over_irq, + .p_fw_bin = &g_aw9620x_load_fw_bin, + .p_reg_bin = &g_aw9620x_load_reg_bin, + .p_chip_mode = &g_aw9620x_chip_mode, + + //Node usage parameters + .p_reg_list = &g_aw9620x_reg_list, + .p_reg_arr = &g_aw9620x_reg_arr_para, + .p_aot = &g_aw9620x_aot, + .p_diff = &g_aw9620x_diff, + .p_offset = &g_aw9620x_offset, + .p_mode = &g_aw9620x_mode, + .p_prox_fw = &g_aw9620x_node_prox_load_fw_bin, + .p_reg_fw = &g_aw9620x_node_reg_load_fw_bin, + .p_get_chip_info = &g_aw9620x_get_chip_info, + .p_aw_sar_awrw = NULL, + .p_boot_bin = &g_aw9620x_load_boot_bin, +}; + +int32_t aw9620x_init(struct aw_sar *p_sar) +{ + if (p_sar == NULL) { + AWLOGE(p_sar->dev, "para is NULL, error!"); + return -AW_ERR; + } + + //Chip private function operation + p_sar->p_sar_para = &g_aw9620x_chip_config; + + return AW_OK; +} + +void aw9620x_deinit(struct aw_sar *p_sar) +{ + if (p_sar->priv_data != NULL) { + devm_kfree(p_sar->dev, p_sar->priv_data); + } +} diff --git a/drivers/misc/awinic/sarsensor/aw9620x/aw_update_fw.c b/drivers/misc/awinic/sarsensor/aw9620x/aw_update_fw.c new file mode 100644 index 000000000000..a50ea2c4bd15 --- /dev/null +++ b/drivers/misc/awinic/sarsensor/aw9620x/aw_update_fw.c @@ -0,0 +1,1557 @@ +#include +#include +/*********************protocol update frimware start****************** *****/ +//#define AW_FW_INFO_LOG + +//If it is a bin file, the size side conversion is required +#define AW_SAR_BIN_TR + +static uint8_t g_prot_update_fw_flag = 0; + +static int32_t aw_check_isp_go_reg(AW_SAR_I2C_TYPE i2c) +{ + int32_t delay_cnt = 100; + uint32_t r_isp_go_reg = 0; + int32_t ret = 0; + + do { + ret = aw_sar_i2c_read(i2c, REG_ISPGO, &r_isp_go_reg); + if (ret != AW_FW_OK) { + AWLOGE_FW("read REG_ISPGO"); + return ret; + } + if (r_isp_go_reg == 0) { + break; + } + aw_sar_delay_ms(1); + } while (delay_cnt--); + + if (delay_cnt < 0) { + AWLOGE_FW("check_isp_go_reg err!"); + return -AW_FW_ERR; + } + + return AW_FW_OK; +} + +static int32_t aw_reg_read_val(AW_SAR_I2C_TYPE i2c, uint32_t *p_read_data, uint16_t start_addr) +{ + int32_t ret = 0; + + //3.config ISPADR reg + ret = aw_sar_i2c_write(i2c, REG_ISPADR, start_addr); + if (ret != AW_FW_OK) { + AWLOGE_FW("write REG_ISPADR"); + return -AW_FW_ERR; + } + //4.config ISP_CMD reg + ret = aw_sar_i2c_write(i2c, REG_ISPCMD, REG_ISP_CMD_MAIN_ARR); + if (ret != AW_FW_OK) { + AWLOGE_FW("write REG_ISPCMD"); + return -AW_FW_ERR; + } + //5.config ISP_GO reg + ret = aw_sar_i2c_write(i2c, REG_ISPGO, REG_SET_ISP_GO); + if (ret != AW_FW_OK) { + AWLOGE_FW("write ISP_CMD "); + return -AW_FW_ERR; + } + //6.check isp_go reg + ret = aw_check_isp_go_reg(i2c); + if (ret != AW_FW_OK) { + AWLOGE_FW("check_isp_go_reg"); + return -AW_FW_ERR; + } + //7 read data + ret = aw_sar_i2c_read(i2c, REG_ISPRDATA, p_read_data); + if (ret != AW_FW_OK) { + AWLOGE_FW("read REG_ISPRDATA p_read_data = 0x%08x", *p_read_data); + return -AW_FW_ERR; + } + + return AW_FW_OK; +} + +static uint32_t get_pack_checksum(uint8_t *data, uint16_t length, + uint8_t module, uint8_t command) +{ + uint32_t i = 0; + uint32_t check_sum = 0; + + check_sum = module + command + length; + for (i = 0; i < length; i += 4) { + check_sum += AW_SAR_GET_32_DATA(data[i + 0], data[i + 1], + data[i + 2], data[i + 3]); + } + + return (~check_sum + 1); +} + +static int32_t dri_to_soc_pack_send(AW_SAR_I2C_TYPE i2c, uint8_t module, uint8_t command, + uint16_t length, uint8_t *data) +{ + int8_t cnt = AW_RETRIES; +#ifdef AW_FW_INFO_LOG + uint32_t i = 0; +#endif + int32_t ret = -1; + uint32_t checksum = 0; + uint8_t *prot_pack_w = (uint8_t *)malloc(AW_PACK_FIXED_SIZE + length + SEND_ADDR_LEN); + if (prot_pack_w == NULL) { + AWLOGE_FW("malloc application failed!"); + return -1; + } + + prot_pack_w[0] = ((uint16_t)PROT_SEND_ADDR & GET_BITS_15_8) >> OFFSET_BIT_8; + prot_pack_w[1] = (uint16_t)PROT_SEND_ADDR & GET_BITS_7_0; + + //header + prot_pack_w[2] = ((uint16_t)AW_HEADER_VAL & GET_BITS_15_8) >> OFFSET_BIT_8; + prot_pack_w[3] = (uint16_t)AW_HEADER_VAL & GET_BITS_7_0; + + //size + prot_pack_w[4] = ((uint16_t)(AW_PACK_FIXED_SIZE + length) & GET_BITS_15_8) >> OFFSET_BIT_8; + prot_pack_w[5] = (uint16_t)(AW_PACK_FIXED_SIZE + length) & GET_BITS_7_0; + + //checksum + checksum = get_pack_checksum(data, length, module, command); + prot_pack_w[6] = ((uint32_t)checksum & GET_BITS_31_25) >> OFFSET_BIT_24; + prot_pack_w[7] = ((uint32_t)checksum & GET_BITS_24_16) >> OFFSET_BIT_16; + prot_pack_w[8] = ((uint32_t)checksum & GET_BITS_15_8) >> OFFSET_BIT_8; + prot_pack_w[9] = (uint32_t)checksum & GET_BITS_7_0; + + //module + prot_pack_w[10] = module; + + //command + prot_pack_w[11] = command; + + //length + prot_pack_w[12] = ((uint16_t)length & 0xff00) >> OFFSET_BIT_8; + prot_pack_w[13] = (uint16_t)length & 0x00ff; + + if (length != 0 && data != NULL) { + memcpy(prot_pack_w + AW_PACK_FIXED_SIZE + SEND_ADDR_LEN, data, length); + } + +#ifdef AW_FW_INFO_LOG + //Protocol sending content + AWLOGD_FW("Protocol sending content PROT_SEND_ADDR:0x%x", PROT_SEND_ADDR); + for (i = 2; i < AW_PACK_FIXED_SIZE + length + AW_ADDR_SIZE; i += 4) { + AWLOGD_FW("i = %d, 0x%02x 0x%02x 0x%02x 0x%02x", + i, prot_pack_w[i + 0], prot_pack_w[i + 1], + prot_pack_w[i + 2], prot_pack_w[i + 3]); + } +#endif + + do { + ret = aw_sar_i2c_write_seq(i2c, prot_pack_w, AW_PACK_FIXED_SIZE + AW_ADDR_SIZE + length); + if (ret < 0) { + AWLOGE_FW("aw_sar_i2c_write_seq err cnt = %d ret = %d", cnt, ret); + } else { + break; + } + } while(cnt--); + + free(prot_pack_w); + + if (cnt < 0) { + AWLOGE_FW("aw_sar_i2c_write_seq err! ret = %d", ret); + return -AW_FW_ERR; + } + + return AW_FW_OK; +} + +static int32_t soc_to_dri_pack_recv(AW_SAR_I2C_TYPE i2c, struct aw_soc_protocol *prot_pack, + uint32_t pack_len, uint8_t *addr) +{ + int8_t cnt = AW_RETRIES; + int32_t ret = -1; + + if (prot_pack == NULL || pack_len == 0) { + return -1; + } + + do { + ret = aw_sar_i2c_read_seq(i2c, addr, 2, (uint8_t *)prot_pack, pack_len); + if (ret < 0) { + AWLOGE_FW("aw_sar_i2c_read_seq cnt = %d ret = %d", cnt, ret); + } else { + break; + } + } while(cnt--); + + if (cnt < 0) { + AWLOGE_FW("aw_sar_i2c_read_seq! ret = %d", ret); + return -AW_FW_ERR; + } + + return AW_FW_OK; +} + +/** + * @brief flash init + * @param parse pack value + * @retval err code + */ +#define AW_SAR_FLIP_U16(value) ((((value) & (0x00FF)) << (8)) | (((value) & (0xFF00)) >> (8))) +#define AW_SAR_FLIP_U32(value) ((((value) & (0x000000FF)) << (24)) | ((((value) & (0x0000FF00))) << (8)) | (((value) & (0x00FF0000)) >> (8)) | (((value) & (0xFF000000)) >> (24))) +static int32_t soc_to_dri_pack_parse(AW_SAR_I2C_TYPE i2c, uint32_t length, + uint8_t module, uint8_t command) +{ + int32_t ret = -1; + uint32_t pack_len = AW_PACK_FIXED_SIZE + length; + uint8_t ack_addr[2] = { 0 }; + uint32_t cmd_status = 0; + + struct aw_soc_protocol *prot_pack_r = (struct aw_soc_protocol *)malloc(pack_len); + if (prot_pack_r == NULL) { + AWLOGE_FW("malloc application failed!"); + return -AW_FW_ERR; + } + + ack_addr[0] = (uint8_t)(AW_ACK_ADDR >> OFFSET_BIT_8); + ack_addr[1] = (uint8_t)AW_ACK_ADDR; + + ret = soc_to_dri_pack_recv(i2c, prot_pack_r, pack_len, ack_addr); + if (ret != AW_FW_OK) { + AWLOGE_FW("soc_to_dri_pack_recv failed!"); + goto err_pack_parse; + } + + prot_pack_r->header = AW_SAR_FLIP_U16(prot_pack_r->header); + prot_pack_r->size = AW_SAR_FLIP_U16(prot_pack_r->size); + prot_pack_r->length = AW_SAR_FLIP_U16(prot_pack_r->length); + prot_pack_r->checksum = AW_SAR_FLIP_U32(prot_pack_r->checksum); + + cmd_status = AW_SAR_GET_32_DATA(prot_pack_r->value[3], prot_pack_r->value[2], + prot_pack_r->value[1], prot_pack_r->value[0]); + + //parse soc to dri pack +/* AWLOGD_FW("header= 0x%x, size= 0x%x, length= 0x%x, checksum= 0x%x,", + prot_pack_r->header, prot_pack_r->size, + prot_pack_r->length, prot_pack_r->checksum); + AWLOGD_FW("module= 0x%x, command= 0x%x, length=0x%x, cmd_status = %d", + prot_pack_r->module, prot_pack_r->command, + prot_pack_r->length, cmd_status);*/ + + if ((module == prot_pack_r->module) && (command == prot_pack_r->command) && (cmd_status == 0)) { + } else { + AWLOGE_FW("soc to dri send pack parse failed!"); + return -AW_FW_ERR; + } + + free(prot_pack_r); + + return AW_FW_OK; + +err_pack_parse: + free(prot_pack_r); + return -AW_FW_ERR; +} + +static uint32_t aw_get_bin_checksum(const uint8_t *w_bin_offset, + uint32_t update_data_len, uint32_t check_len) +{ + uint32_t i = 0; + uint32_t check_sum = 0; + uint32_t tmp = 0; + uint32_t index = 0; + + AWLOGD_FW("update_data_len:0x%x, check_len:0x%x", update_data_len, check_len); + + for (i = 0; i < check_len; i += WORD_LEN) { + if (i < update_data_len) { +#ifdef AW_SAR_BIN_TR + tmp = AW_SAR_GET_32_DATA(w_bin_offset[index + 3], + w_bin_offset[index + 2], + w_bin_offset[index + 1], + w_bin_offset[index + 0]); +#else + tmp = AW_SAR_GET_32_DATA(w_bin_offset[index + 0], + w_bin_offset[index + 1], + w_bin_offset[index + 2], + w_bin_offset[index + 3]); +#endif + index += WORD_LEN; + } else { + tmp = AW_FLASH_DEFAULT_VAL; + } + check_sum += tmp; + } + check_sum = ~check_sum + 1; + + return check_sum; +} + +static int32_t aw_read_ack_irq(AW_SAR_I2C_TYPE i2c) +{ + uint32_t irq_stat = 0; + int32_t cnt = AW_WAIT_IRQ_CYCLES; + int32_t ret = 0; + + if (g_prot_update_fw_flag == SEND_UPDATE_FW_CMD) { + cnt = AW_PROT_STOP_WAIT_IRQ_CYCLES; + } + + do { + ret = aw_sar_i2c_read(i2c, REG_IRQSRC, &irq_stat); + if (ret != AW_FW_OK) { + AWLOGE_FW("read REG_IRQSRC fail"); + return -AW_FW_ERR; + } + if (((irq_stat >> 29) & 0x01) == 1) { + break; + } else { + //AWLOGE_FW("REG_IRQSRC val: 0x%x cnt: %d", irq_stat, cnt); + } + aw_sar_delay_ms(1); + } while (cnt--); + + if (cnt == -1) { + AWLOGE_FW("read irqsrc failed!, REG_IRQSRC val: 0x%x", irq_stat); + return -AW_FW_ERR; + } + + return AW_FW_OK; +} + +static int32_t aw_read_init_comp_irq(AW_SAR_I2C_TYPE i2c) +{ + uint32_t irq_stat = 0; + int32_t cnt = 10; + int32_t ret = 0; + + do { + ret = aw_sar_i2c_read(i2c, REG_IRQSRC, &irq_stat); + if (ret != AW_FW_OK) { + AWLOGD_FW("read REG_HOSTIRQSRC err"); + return -AW_FW_ERR; + } + + if (irq_stat == INIT_OVER_IRQ_OK) { + AWLOGD_FW("read init over irq ok success!,stop cmd success!"); + break; + } else { + AWLOGE_FW("stop cmd failed, REG_IRQSRC val: 0x%x cnt: %d", irq_stat, cnt); + } + + aw_sar_delay_ms(1); + } while (cnt--); + + if (cnt == -1) { + AWLOGD_FW("stop cmd failed!"); + return -AW_FW_ERR; + } + + return AW_FW_OK; +} + +static int32_t aw_send_once_cmd(AW_SAR_I2C_TYPE i2c, uint8_t module, uint8_t command, + uint8_t* send_value, uint16_t send_val_len) +{ + int32_t ret = -AW_FW_ERR; + uint8_t recv_len = 0; + uint32_t delay_ms_cnt = 0; + + //1.send cmd + ret = dri_to_soc_pack_send(i2c, module, command, + send_val_len, send_value); + if (ret != AW_FW_OK) { + AWLOGE_FW("UPDATE_START_CMD err"); + return -AW_FW_ERR; + } + + ret = aw_sar_i2c_write(i2c, AW_BT_PROT_CMD_PACK_ADDR, AW_SRAM_FIRST_DETECT); + if (ret != AW_FW_OK) { + AWLOGE_FW("REG_CMD_SEND_TIRG err"); + return -AW_FW_ERR; + } + + //2.send trig + ret = aw_sar_i2c_write(i2c, REG_CMD, REG_H2C_TRIG_PARSE_CMD); + if (ret != AW_FW_OK) { + AWLOGE_FW("REG_CMD_SEND_TIRG err"); + return -AW_FW_ERR; + } + + switch (g_prot_update_fw_flag) { + case SEND_START_CMD: + recv_len = SEND_START_CMD_RECV_LEN; + delay_ms_cnt = SEND_START_CMD_DELAY_MS; + break; + case SEND_ERASE_SECTOR_CMD: + recv_len = SEND_ERASE_CHIP_CMD_RECV_LEN; + delay_ms_cnt = SEND_ERASE_SECTOR_CMD_DELAY_MS; + break; + case SEND_UPDATE_FW_CMD: + recv_len = SEND_UPDATE_FW_CMD_RECV_LEN; + delay_ms_cnt = 0; + break; + case SEND_UPDATE_CHECK_CODE_CMD: + recv_len = SEND_UPDATE_CHECK_CODE_CMD_RECV_LEN; + delay_ms_cnt = SEND_UPDATE_CHECK_CODE_CMD_DELAY_MS; + break; + case SEND_RESTORE_CMD: + recv_len = SEND_RESTORE_CMD_RECV_LEN; + delay_ms_cnt = SEND_RESTORE_CMD_DELAY_MS; + break; + default: + recv_len = 0; + delay_ms_cnt = 0; + break; + } + + aw_sar_delay_ms(delay_ms_cnt); + + //3.Read interrupt information, wait 100ms + ret = aw_read_ack_irq(i2c); + if (ret != AW_FW_OK) { + AWLOGE_FW("read_ack_irq err"); + return -AW_FW_ERR; + } + + //4.read start ack and pare pack + ret = soc_to_dri_pack_parse(i2c, recv_len, module, command); + if (ret != AW_FW_OK) { + AWLOGE_FW("soc_to_dri_pack_parse err"); + return -AW_FW_ERR; + } + + return AW_FW_OK; +} + +static int32_t aw_send_stop_cmd(AW_SAR_I2C_TYPE i2c) +{ + int32_t ret = -AW_FW_ERR; + + AWLOGD_FW("enter"); + + aw_sar_i2c_write(i2c, AW_REG_MCFG, AW_CPU_HALT); + aw_sar_i2c_write(i2c, AW_REG_ACESS_EN, AW_ACC_PERI); + aw_sar_i2c_write_bits(i2c, REG_UPDATA_DIS, AW_REG_UPDATA_DIS_MASK, 0); + aw_sar_i2c_write(i2c, REG_ACCESSEN, REG_ACCESSEN_CLOSE); + aw_sar_i2c_write(i2c, AW_REG_MCFG, AW_CPU_RUN); + + aw_sar_delay_ms(SEND_STOP_CMD_DELAY_MS); + + //Read interrupt information, wait 10ms + ret = aw_read_init_comp_irq(i2c); + if (ret != AW_FW_OK) { + AWLOGE_FW("stop read_ack_irq err"); + return -AW_FW_ERR; + } + + return AW_FW_OK; +} + +static int32_t aw_reg_read_flash_val(AW_SAR_I2C_TYPE i2c, uint32_t *read_data, uint16_t start_addr) +{ + int32_t ret = 0; + + //1.config FMC reg + ret = aw_sar_i2c_write(i2c, REG_ACCESSEN, REG_OPEN_APB_ACCESS_EN); + if (ret != AW_FW_OK) { + AWLOGE_FW("write REG_ACCESSEN failed!"); + return -AW_FW_ERR; + } + //2.config PMU_CFG reg + ret = aw_sar_i2c_write(i2c, REG_PMU_CFG, REG_ENSET_PMU_CFG); + if (ret != AW_FW_OK) { + AWLOGE_FW("config PMU_CFG failed"); + return -AW_FW_ERR; + } + + ret = aw_reg_read_val(i2c, read_data, start_addr); + if (ret != AW_FW_OK) { + AWLOGD_FW("read addr:0x%x failed", start_addr); + return -AW_FW_ERR; + } + + return AW_FW_OK; +} + + +#ifdef AW_SAR_BIN_TR +static void aw_swap(uint8_t *a, uint8_t *b) +{ + uint8_t tmp = 0; + + tmp = *a; + *a = *b; + *b = tmp; +} + +static void aw_bin_conver(uint8_t *data, uint32_t len) +{ + uint32_t i = 0; + + for (i = 0; i < len; i += WORD_LEN) { + aw_swap(&(data[i + 0]), &(data[i + 3])); + aw_swap(&(data[i + 1]), &(data[i + 2])); + } +} +#endif + +static int32_t aw_cycle_write_firmware(AW_SAR_I2C_TYPE i2c, + const uint8_t *fw_data, uint32_t firmware_len, + uint32_t flash_addr, uint32_t single_wr_len) +{ + uint8_t value_head_len = TRANSFER_SEQ_LEN + TRANSFER_DTS_ADDR_LEN; + uint32_t seq = 1; + int32_t ret = -AW_FW_ERR; + uint32_t i = 0; + uint32_t start_addr = 0; + uint32_t word_comp_len = 0; + uint32_t cycle_cnt = 0; + uint32_t cycle_cnt_last_len = 0; + uint8_t *firmware_info = NULL; + + AWLOGD_FW("enter single_wr_len = %d", single_wr_len); + + //If firmware len is not a multiple of 4, + //let it be equal to the multiple of 4 over there, + //and the less part is supplemented by 1 + if (firmware_len % WORD_LEN != 0) { + word_comp_len = WORD_LEN - firmware_len % WORD_LEN; + AWLOGE_FW("word_comp_len = %d", word_comp_len); + } + + firmware_len = firmware_len + word_comp_len; + cycle_cnt = firmware_len / single_wr_len; + cycle_cnt_last_len = firmware_len % single_wr_len; + + for (i = 0; i < cycle_cnt; i++) { + firmware_info = (uint8_t *)malloc(single_wr_len + value_head_len); + if (firmware_info == NULL) { + AWLOGE_FW("malloc application failed"); + return -AW_FW_ERR; + } + + //Insufficient word makes up for 0xff + memset(firmware_info, 1, single_wr_len + value_head_len); + + firmware_info[0] = (uint8_t)(seq >> OFFSET_BIT_24); + firmware_info[1] = (uint8_t)(seq >> OFFSET_BIT_16); + firmware_info[2] = (uint8_t)(seq >> OFFSET_BIT_8); + firmware_info[3] = (uint8_t)(seq); + + firmware_info[4] = (uint8_t)(flash_addr >> OFFSET_BIT_24); + firmware_info[5] = (uint8_t)(flash_addr >> OFFSET_BIT_16); + firmware_info[6] = (uint8_t)(flash_addr >> OFFSET_BIT_8); + firmware_info[7] = (uint8_t)(flash_addr); + + AWLOGD_FW("cnt = %d firmware addr written to flash 0x%02x 0x%02x 0x%02x 0x%02x", + i, firmware_info[4], firmware_info[5], + firmware_info[6], firmware_info[7]); + + memcpy(firmware_info + value_head_len, + &(fw_data[start_addr + single_wr_len * i]), single_wr_len); +#ifdef AW_SAR_BIN_TR + aw_bin_conver(firmware_info + value_head_len, single_wr_len); +#endif + ret = aw_send_once_cmd(i2c, UPDATE_MODULE, UPDATE_TRANSFER_CMD, + firmware_info, single_wr_len + value_head_len); + if (ret != AW_FW_OK) { + AWLOGE_FW("aw_send_once_cmd failed"); + goto err_hand; + } + + flash_addr += single_wr_len; + seq++; + + if (firmware_info != NULL) { + free(firmware_info); + firmware_info = NULL; + } + } + + if (cycle_cnt_last_len != 0) { + firmware_info = (uint8_t *)malloc(cycle_cnt_last_len + value_head_len); + if (firmware_info == NULL) { + AWLOGE_FW("malloc application failed"); + goto err_hand; + } + //Insufficient word makes up for 0xff + memset(firmware_info, 1, cycle_cnt_last_len + value_head_len); + + firmware_info[0] = (uint8_t)(seq >> OFFSET_BIT_24); + firmware_info[1] = (uint8_t)(seq >> OFFSET_BIT_16); + firmware_info[2] = (uint8_t)(seq >> OFFSET_BIT_8); + firmware_info[3] = (uint8_t)(seq); + firmware_info[4] = (uint8_t)(flash_addr >> OFFSET_BIT_24); + firmware_info[5] = (uint8_t)(flash_addr >> OFFSET_BIT_16); + firmware_info[6] = (uint8_t)(flash_addr >> OFFSET_BIT_8); + firmware_info[7] = (uint8_t)(flash_addr); + + AWLOGD_FW("last transfer, len = %d ,firmware addr written to flash 0x%02x 0x%02x 0x%02x 0x%02x", + cycle_cnt_last_len, firmware_info[4], firmware_info[5], + firmware_info[6], firmware_info[7]); + + memcpy(firmware_info + value_head_len, + &(fw_data[start_addr + cycle_cnt * single_wr_len]), + cycle_cnt_last_len); +#ifdef AW_SAR_BIN_TR + + aw_bin_conver(firmware_info + value_head_len, cycle_cnt_last_len); +#endif + + ret = aw_send_once_cmd(i2c, UPDATE_MODULE, UPDATE_TRANSFER_CMD, + firmware_info, cycle_cnt_last_len + value_head_len); + if (ret != AW_FW_OK) { + AWLOGD_FW("aw_send_once_cmd fail"); + goto err_hand; + } + if (firmware_info != NULL) { + free(firmware_info); + firmware_info = NULL; + } + } + + return AW_FW_OK; +err_hand: + if (firmware_info != NULL) { + free(firmware_info); + firmware_info = NULL; + } + return -AW_FW_ERR; +} + +static int32_t aw_write_firmware_checksum(AW_SAR_I2C_TYPE i2c, uint8_t *p_checksum, + uint32_t fw_check_en_addr, + uint32_t check_en_val, + uint32_t fw_check_code_addr) +{ + uint8_t i = 0; + uint8_t j = 0; + uint8_t transfer_value_w[AW_EN_TR_CHECK_VALUE_LEN] = { 0 }; + int32_t ret = 0; + uint32_t r_check_en = 0; + uint32_t r_checksum = 0; + uint32_t w_checksum = 0; + + for (i = 0; i < 4; i++) { + transfer_value_w[i] = (uint8_t)(0 >> ((3 - i) * 8)); + } + + for (i = 4; i < 8; i++) { + transfer_value_w[i] = (uint8_t)(fw_check_en_addr >> ((3 - j) * 8)); + j++; + } + + j = 0; + for (i = 8; i < 12; i++) { + transfer_value_w[i] = (uint8_t)(check_en_val >> ((3 - j) * 8)); + j++; + } + + j = 0; + for (i = 12; i < 16; i++) { + transfer_value_w[i] = p_checksum[j]; + j++; + } + + AWLOGD_FW("fw_check_en_addr:0x%8x, check_en_val:0x%8x", fw_check_en_addr, check_en_val); + + ret = aw_send_once_cmd(i2c, UPDATE_MODULE, UPDATE_TRANSFER_CMD, + transfer_value_w, AW_EN_TR_CHECK_VALUE_LEN); + if (ret != AW_FW_OK) { + AWLOGD_FW("aw_write_firmware_checksum err"); + return -AW_FW_ERR; + } + ret = aw_reg_read_flash_val(i2c, &r_check_en, (uint16_t)fw_check_en_addr); + if (ret != AW_FW_OK) { + AWLOGD_FW("aw_read check_en err"); + return -AW_FW_ERR; + } + ret = aw_reg_read_flash_val(i2c, &r_checksum, (uint16_t)fw_check_code_addr); + if (ret != AW_FW_OK) { + AWLOGD_FW("aw_read check_en err"); + return -AW_FW_ERR; + } + w_checksum = AW_SAR_GET_32_DATA(p_checksum[0], p_checksum[1], p_checksum[2], p_checksum[3]); + if ((r_check_en == check_en_val) && (r_checksum == w_checksum)) { + return AW_FW_OK; + } else { + AWLOGE_FW("r_check_en:0x%08x, check_en_val:0x%08x, r_checksum:0x%08x, w_checksum:0x%08x", + r_check_en, check_en_val, r_checksum, w_checksum); + return -AW_FW_ERR; + } + + return AW_FW_OK; +} + +static int32_t aw_get_fw_and_bt_info(AW_SAR_I2C_TYPE i2c, + const uint8_t *fw_data, uint32_t fw_len, + uint8_t *p_fw_check_sum, uint32_t check_len) +{ + uint32_t fw_checksum = 0; + int32_t ret = 0; + uint32_t bt_version = 0; + uint32_t bt_date = 0; + uint32_t bt_checksum = 0; + + ret = aw_sar_i2c_read(i2c, AW_BT_VER_INF_VERSION, &bt_version); + if (ret != AW_FW_OK) { + AWLOGE_FW("read AW_BT_VER_INF_VERSION fail!"); + return -AW_FW_ERR; + } + + ret = aw_sar_i2c_read(i2c, AW_BT_VER_INF_DATE, &bt_date); + if (ret != AW_FW_OK) { + AWLOGE_FW("read AW_BT_VER_INF_DATE fail"); + return -AW_FW_ERR; + } + + ret = aw_reg_read_flash_val(i2c, &bt_checksum, AW_BT_CHECK_SUM_ADDR); + if (ret != AW_FW_OK) { + AWLOGE_FW("read bt_checksum fail"); + return -AW_FW_ERR; + } + AWLOGD_FW("boot version:0x%08x, date:0x%08x checksum:0x%08x", bt_version, bt_date, bt_checksum); + + fw_checksum = aw_get_bin_checksum(fw_data, fw_len, check_len); + p_fw_check_sum[0] = (uint8_t)(fw_checksum >> 24); + p_fw_check_sum[1] = (uint8_t)(fw_checksum >> 16); + p_fw_check_sum[2] = (uint8_t)(fw_checksum >> 8); + p_fw_check_sum[3] = (uint8_t)(fw_checksum >> 0); + + AWLOGD_FW("firmware checksum is 0x%08x", fw_checksum); + + return AW_FW_OK; +} + +static int32_t aw_flash_erase_sector(AW_SAR_I2C_TYPE i2c, uint32_t erase_addr, uint32_t erase_sector_cnt, uint32_t sector_size) +{ + uint8_t i = 0; + uint8_t addr_buf[4] = { 0 }; + int32_t ret = 0; + + for (i = 0; i < erase_sector_cnt; i++) { + addr_buf[0] = (uint8_t)(erase_addr >> OFFSET_BIT_24); + addr_buf[1] = (uint8_t)(erase_addr >> OFFSET_BIT_16); + addr_buf[2] = (uint8_t)(erase_addr >> OFFSET_BIT_8); + addr_buf[3] = (uint8_t)(erase_addr); + g_prot_update_fw_flag = SEND_ERASE_SECTOR_CMD; + ret = aw_send_once_cmd(i2c, FLASH_MODULE, FLASH_ERASE_SECTOR_CMD, + addr_buf, sizeof(addr_buf)); + if (ret != AW_FW_OK) { + AWLOGE_FW("send erase sector once cmd i = %d", i); + break; + } + erase_addr += sector_size; + } + AWLOGD_FW("erase sector success!"); + + return ret; +} + +static int32_t aw_flash_erase_last_sector(AW_SAR_I2C_TYPE i2c, uint32_t erase_addr) +{ + uint8_t addr_buf[4] = { 0 }; + int32_t ret = 0; + + addr_buf[0] = (uint8_t)(erase_addr >> OFFSET_BIT_24); + addr_buf[1] = (uint8_t)(erase_addr >> OFFSET_BIT_16); + addr_buf[2] = (uint8_t)(erase_addr >> OFFSET_BIT_8); + addr_buf[3] = (uint8_t)(erase_addr); + g_prot_update_fw_flag = SEND_ERASE_SECTOR_CMD; + ret = aw_send_once_cmd(i2c, FLASH_MODULE, FLASH_ERASE_SECTOR_CMD, + addr_buf, sizeof(addr_buf)); + if (ret != AW_FW_OK) { + AWLOGE_FW("flash_erase_last_sector fail"); + return -AW_FW_ERR; + } + AWLOGD_FW("erase last sector addr = 0x%x", erase_addr); + + return AW_FW_OK; +} + +static int32_t aw_send_online_cmd(AW_SAR_I2C_TYPE i2c) +{ + int32_t ret = 0; + int32_t cnt = 200; + uint32_t irq_stat = 0; + + ret = aw_sar_i2c_write(i2c, AW_BT_HOST2CPU_TRIG, AW_BT_HOST2CPU_TRIG_ONLINE_UPGRADE_CMD); + if (ret != AW_FW_OK) { + AWLOGE_FW("write AW_BT_HOST2CPU_TRIG failed"); + return -AW_FW_ERR; + } + + aw_sar_delay_ms(1); + + do { + ret = aw_sar_i2c_read(i2c, REG_IRQSRC, &irq_stat); + if (ret != AW_FW_OK) { + AWLOGE_FW("read REG_IRQSRC fail"); + return -AW_FW_ERR; + } + if (((irq_stat >> 29) & 0x01) == 1) { + break; + } + aw_sar_delay_ms(1); + } while (cnt--); + + if (cnt == -1) { + AWLOGE_FW("read irqsrc failed!, REG_IRQSRC val: 0x%x", irq_stat); + return -AW_FW_ERR; + } + + return AW_FW_OK; +} + +static int32_t aw_send_all_update_cmd(AW_SAR_I2C_TYPE i2c, struct aw_update_fw *update_fw) +{ + int8_t update_flag = AW_TRUE; + int32_t ret = -AW_FW_ERR; + uint32_t data_tmp = 0; + uint8_t fw_check_sum[4] = { 0 }; + uint32_t reg_boot_loader_active_val = 0; + const uint8_t *fw_data = update_fw->fw_data_info->data_start_offset; + uint32_t fw_data_len = update_fw->fw_data_info->update_data_len; + const struct aw_flash_update_info *flash_update_info = update_fw->fw_info->flash_info; + uint8_t direct_update_flag = update_fw->update_para->direct_update_flag; + uint32_t fw_check_len = flash_update_info->check_len; + + do { + //1.Send online upgrade command + AWLOGD_FW("1.Send online upgrade command"); + ret = aw_send_online_cmd(i2c); + if (ret != AW_FW_OK) { + AWLOGE_FW("1.Send online upgrade command failed!"); + update_flag = AW_FALSE; + break; + } + + ret = aw_get_fw_and_bt_info(i2c, fw_data, fw_data_len, fw_check_sum, fw_check_len); + if (ret != AW_FW_OK) { + AWLOGE_FW("aw_get_fw_and_bt_info failed!"); + update_flag = AW_FALSE; + break; + } + + //2.send start cmd + AWLOGD_FW("2.send start cmd"); + g_prot_update_fw_flag = SEND_START_CMD; + ret = aw_send_once_cmd(i2c, UPDATE_MODULE, UPDATE_START_CMD, + P_AW_START_CMD_SEND_VALUE, AW_START_CMD_SEND_VALUE_LEN); + if (ret != AW_FW_OK) { + AWLOGE_FW("send start cmd failed!"); + update_flag = AW_FALSE; + break; + } + + //3.a en fw check erase_last_sector" + AWLOGD_FW("3.a en fw check erase_last_sector"); + ret = aw_flash_erase_last_sector(i2c, flash_update_info->erase_start_addr + + (flash_update_info->erase_sector_cnt - 1) * flash_update_info->sector_size); + if (ret != AW_FW_OK) { + AWLOGD_FW("send erase_last_sector failed!"); + update_flag = AW_FALSE; + break; + } + + //3.b en fw check + AWLOGD_FW("3.b en fw check"); + g_prot_update_fw_flag = SEND_UPDATE_CHECK_CODE_CMD; + ret = aw_write_firmware_checksum(i2c, fw_check_sum, flash_update_info->check_en_addr, + flash_update_info->check_en_val, + flash_update_info->check_code_addr); + if (ret != AW_FW_OK) { + AWLOGD_FW("aw_write_firmware_checksum err"); + update_flag = AW_FALSE; + break; + } + + //4.send Erase flash firmware area cmd, except for the last sector + AWLOGD_FW("4.send Erase Chip Cmd"); + ret = aw_flash_erase_sector(i2c, flash_update_info->erase_start_addr, + (flash_update_info->erase_sector_cnt - 1), + flash_update_info->sector_size); + if (ret != AW_FW_OK) { + AWLOGD_FW("send Erase flash firmware area cmd failed!"); + update_flag = AW_FALSE; + break; + } + //5.Cycle write firmware + AWLOGD_FW("5. Cycle write firmware"); + g_prot_update_fw_flag = SEND_UPDATE_FW_CMD; + ret = aw_cycle_write_firmware(i2c, fw_data, fw_data_len, flash_update_info->tr_start_addr, + update_fw->fw_info->single_wr_len); + if (ret != AW_FW_OK) { + AWLOGD_FW("Cycle write firmware"); + update_flag = AW_FALSE; + break; + } + //6.send stop cmd + AWLOGD_FW("6.send stop cmd"); + g_prot_update_fw_flag = SEND_STOP_CMD; + ret = aw_send_stop_cmd(i2c); + if (ret != AW_FW_OK) { + AWLOGD_FW("stop cmd failed, protocol update firmware failed"); + update_flag = AW_FALSE; + break; + } else { + AWLOGI_FW("protocol update firmware succeeded!"); + } + } while(0); + + if (update_flag == AW_FALSE) { + AWLOGD_FW("protocol update firmware failed, recovery reg"); + ret = aw_sar_i2c_write(i2c, REG_ACCESSEN, REG_ACCESSEN_OPEN); + if (ret != AW_FW_OK) { + AWLOGE_FW("write REG_ACCESSEN failed!"); + return -AW_FW_ERR; + } + + ret = aw_sar_i2c_read(i2c, REG_BOOT_LOADER_ACTIVE, ®_boot_loader_active_val); + if (ret != AW_FW_OK) { + AWLOGE_FW("read REG_BOOT_LOADER_ACTIVE failed!"); + return -AW_FW_ERR; + } + if (reg_boot_loader_active_val != 0) { + ret = aw_sar_i2c_write(i2c, REG_BOOT_LOADER_ACTIVE, 0); + if (ret != AW_FW_OK) { + AWLOGE_FW("write REG_BOOT_LOADER_ACTIVE failed!"); + return -AW_FW_ERR; + } + } + + ret = aw_sar_i2c_read(i2c, REG_UPDATA_DIS, &data_tmp); + if (ret != AW_FW_OK) { + AWLOGE_FW("read REG_UPDATA_DIS failed!"); + return -AW_FW_ERR; + } + if (((data_tmp >> 24) & 0xff) != 0) { + ret = aw_sar_i2c_write(i2c, REG_UPDATA_DIS, data_tmp & AW_REG_UPDATA_DIS_MASK); + if (ret != AW_FW_OK) { + AWLOGE_FW("write REG_UPDATA_DIS failed!"); + return -AW_FW_ERR; + } + } + + ret = aw_sar_i2c_write(i2c, REG_ACCESSEN, REG_ACCESSEN_CLOSE); + if (ret != AW_FW_OK) { + AWLOGE_FW("write REG_ACCESSEN failed!"); + return -AW_FW_ERR; + } + if (direct_update_flag == AW_TRUE) { + AWLOGI_FW("protocol update firmware failed!, exit load"); + return -AW_FW_ERR; + } + AWLOGI_FW("protocol update firmware failed, start reg mode upgrade"); + return -AW_PROT_UPDATE_ERR; + } + + return AW_FW_OK; +} + +static int32_t aw_fw_version_cmp(AW_SAR_I2C_TYPE i2c, int8_t *cmp_val, uint32_t flash_app_version, uint16_t fwver_reg) +{ + uint32_t firmware_version = 0; + int32_t ret = -AW_FW_ERR; + + ret = aw_sar_i2c_read(i2c, fwver_reg, &firmware_version); + if (ret < 0) { + AWLOGD_FW("read fwver_reg failed!"); + return -AW_FW_ERR; + } + AWLOGI_FW("chip_firmware version :0x%08x bin_irmware version :0x%08x!", + firmware_version, flash_app_version); + + if (flash_app_version != firmware_version) { + *cmp_val = BIN_VER_NOT_EQUALS_SOC_VER; + } else { + *cmp_val = BIN_VER_EQUALS_SOC_VER; + } + + return AW_FW_OK; +} + +static int32_t aw_prox_update_para_check(struct aw_update_fw *update_fw) +{ + if ((update_fw == NULL) || + (update_fw->fw_info == NULL) || + (update_fw->update_para == NULL) || + (update_fw->fw_data_info == NULL)) { + AWLOGE_FW("para1 is NULL"); + return -AW_FW_ERR; + } + + if (update_fw->fw_info->flash_info == NULL) { + AWLOGE_FW("para3 is NULL"); + return -AW_FW_ERR; + } + if (update_fw->update_para->aw_update_diff == NULL) { + AWLOGE_FW("para4 is NULL"); + return -AW_FW_ERR; + } + if (update_fw->fw_data_info->data_start_offset == NULL) { + AWLOGE_FW("para5 is NULL"); + return -AW_FW_ERR; + } + + return AW_FW_OK; +} + +int32_t aw_prot_update(AW_SAR_I2C_TYPE i2c, struct aw_update_fw *update_fw) +{ + int8_t cmp_val = 0; + int32_t ret = 0; + + ret = aw_prox_update_para_check(update_fw); + if (ret != AW_FW_OK) { + AWLOGE_FW("para check failed!"); + return -AW_FW_ERR; + } + + if (update_fw->update_para->direct_update_flag == AW_FALSE) { + aw_fw_version_cmp(i2c, &cmp_val, update_fw->fw_data_info->fw_version, + update_fw->update_para->aw_update_diff->fwver_reg_addr); + if (cmp_val == BIN_VER_EQUALS_SOC_VER) { + AWLOGI_FW("Same version number, no update!"); + return AW_FW_OK; + } else { + AWLOGD_FW("firmware Version number is different, update!"); + } + } + + return aw_send_all_update_cmd(i2c, update_fw); +} + +/********aw_reg_mode_update start********/ + +static int32_t aw_close_write_flash_protect(AW_SAR_I2C_TYPE i2c, uint32_t flash_addr_flag) +{ + int32_t ret = 0; + + //Open host read/write FMC protection + ret = aw_sar_i2c_write(i2c, REG_ACCESSEN, REG_OPEN_APB_ACCESS_EN); + if (ret != AW_FW_OK) { + AWLOGE_FW("write REG_ACCESSEN failed"); + return -AW_FW_ERR; + } + + //Configure PMC_ CFG register + ret = aw_sar_i2c_write(i2c, REG_PMU_CFG, REG_SET_PMU_CFG); + if (ret != AW_FW_OK) { + AWLOGE_FW("write REG_PMU_CFG failed!"); + return -AW_FW_ERR; + } + + //Turn on flash write protection + if (flash_addr_flag == BOOT_UPDATE) { + ret = aw_sar_i2c_write(i2c, REG_ARRAY2_EW_EN, REG_SET_BTROM_EW_EN); + if (ret != AW_FW_OK) { + AWLOGE_FW("write REG_ARRAY2_EW_EN failed"); + return -AW_FW_ERR; + } + } + + return AW_FW_OK; +} + +static int32_t aw_reg_write_to_flash_once(AW_SAR_I2C_TYPE i2c, uint16_t addr, uint32_t w_data) +{ + int32_t ret = 0; + + //Write access address + ret = aw_sar_i2c_write(i2c, REG_ISPADR, addr); + if (ret != AW_FW_OK) { + AWLOGE_FW("write 0xff20 err"); + return -AW_FW_ERR; + } + + //Write data + ret = aw_sar_i2c_write(i2c, REG_ISPWDATA, w_data); + if (ret != AW_FW_OK) { + AWLOGE_FW("write 0xff20 err"); + return -AW_FW_ERR; + } + + //Configure ISP_CMD reg + ret = aw_sar_i2c_write(i2c, REG_ISPCMD, REG_ISP_CMD_CONFIG); + if (ret != AW_FW_OK) { + AWLOGE_FW("write 0xff20 err"); + return -AW_FW_ERR; + } + + //Configure ISP_GO reg + ret = aw_sar_i2c_write(i2c, REG_ISPGO, REG_SET_ISP_GO); + if (ret != AW_FW_OK) { + AWLOGE_FW("write 0xff20 err"); + return -AW_FW_ERR; + } + + ret = aw_check_isp_go_reg(i2c); + if (ret != AW_FW_OK) { + AWLOGE_FW("check_isp_go_reg err"); + return -AW_FW_ERR; + } + + return AW_FW_OK; +} + + +static int32_t aw_reg_write_val_to_flash(AW_SAR_I2C_TYPE i2c, uint8_t update_flag, uint16_t addr, uint32_t val) +{ + int32_t ret = 0; + + AWLOGD_FW("enter"); + + ret = aw_close_write_flash_protect(i2c, update_flag); + if (ret != AW_FW_OK) { + AWLOGE_FW("close_write_flash_protect failed!"); + return -AW_FW_ERR; + } + + ret = aw_reg_write_to_flash_once(i2c, addr, val); + if (ret != AW_FW_OK) { + AWLOGE_FW("write aw_reg_write_bin_once failed!"); + return -AW_FW_ERR; + } + + //Configure PMU_ CFG register + ret = aw_sar_i2c_write(i2c, REG_PMU_CFG, REG_ENSET_PMU_CFG); + if (ret != AW_FW_OK) { + AWLOGE_FW("write REG_PMU_CFG failed!"); + return -AW_FW_ERR; + } + + return AW_FW_OK; +} + +static int32_t aw_rd_or_wi_cmp(AW_SAR_I2C_TYPE i2c, struct aw_update_common *update_info, + const uint8_t *w_bin_offset, uint32_t update_data_len) +{ + int32_t ret = 0; + uint32_t i = 0; + uint32_t r_data = 0; + uint32_t w_data = 0; + uint32_t read_cnt = update_info->update_data_len; + + AWLOGD_FW("enter"); + + //1.config FMC reg + ret = aw_sar_i2c_write(i2c, REG_ACCESSEN, REG_OPEN_APB_ACCESS_EN); + if (ret != AW_FW_OK) { + AWLOGE_FW("write REG_ACCESSEN failed!"); + return -AW_FW_ERR; + } + //2.config PMU_CFG reg + ret = aw_sar_i2c_write(i2c, REG_PMU_CFG, REG_ENSET_PMU_CFG); + if (ret != AW_FW_OK) { + AWLOGE_FW("config PMU_CFG reg failed"); + return -AW_FW_ERR; + } + + AWLOGE_FW("read_cnt = %d", read_cnt); + for (i = 0; i < read_cnt; i += WORD_LEN) { + ret = aw_reg_read_val(i2c, &r_data, + update_info->flash_info->tr_start_addr + i); + if (ret != AW_FW_OK) { + AWLOGE_FW("reg_read_bin failed"); + return -AW_FW_ERR; + } +#ifdef AW_SAR_BIN_TR + w_data = AW_SAR_GET_32_DATA(w_bin_offset[i + 3], + w_bin_offset[i + 2], + w_bin_offset[i + 1], + w_bin_offset[i + 0]); + +#else + w_data = AW_SAR_GET_32_DATA(w_bin_offset[i + 0], + w_bin_offset[i + 1], + w_bin_offset[i + 2], + w_bin_offset[i + 3]); + +#endif +#ifdef AW_FW_INFO_LOG + AWLOGD_FW("i= %d, addr= 0x%08x, W_DATA= 0x%08x, R_DATA= 0x%08x", + i, update_info->flash_info->tr_start_addr + i, w_data, r_data); +#endif + if (w_data != r_data) { + AWLOGE_FW("read and write check failed! i=%d, w_data=0x%08x, r_data=0x%08x", + i, w_data, r_data); + return -AW_FW_ERR; + } + } + + return AW_FW_OK; +} + +static int32_t aw_reg_write_bin_to_flash(AW_SAR_I2C_TYPE i2c, struct aw_update_common *update_info) +{ + int32_t ret = 0; + uint32_t i = 0; + uint32_t w_data = 0; + uint32_t index = 0; + const uint8_t *p_data = update_info->w_bin_offset; + uint32_t len = update_info->update_data_len; + uint16_t flash_addr = update_info->flash_info->tr_start_addr; + + AWLOGD_FW("enter"); + + ret = aw_close_write_flash_protect(i2c, update_info->update_flag); + if (ret != AW_FW_OK) { + AWLOGE_FW("close_write_flash_protect failed!"); + return -AW_FW_ERR; + + } + for (i = 0; i < len; i += WORD_LEN, index += WORD_LEN) { +#ifdef AW_SAR_BIN_TR + w_data = AW_SAR_GET_32_DATA(p_data[index + 3], p_data[index + 2], + p_data[index + 1], p_data[index + 0]); +#else + w_data = AW_SAR_GET_32_DATA(p_data[index + 0], p_data[index + 1], + p_data[index + 2], p_data[index + 3]); +#endif + ret = aw_reg_write_to_flash_once(i2c, flash_addr + i, w_data); + if (ret != AW_FW_OK) { + AWLOGE_FW("write aw_reg_write_bin_once failed!"); + return -AW_FW_ERR; + } + } + + //Configure PMU_ CFG register + ret = aw_sar_i2c_write(i2c, REG_PMU_CFG, REG_ENSET_PMU_CFG); + if (ret != AW_FW_OK) { + AWLOGE_FW("write REG_PMU_CFG failed!"); + return -AW_FW_ERR; + } + + return AW_FW_OK; +} + +static int32_t aw_erase_sector(AW_SAR_I2C_TYPE i2c, struct aw_update_common *update_info) +{ + int32_t ret = 0; + uint32_t i = 0; + uint32_t erase_len = update_info->flash_info->check_len; + uint32_t erase_cnt = update_info->flash_info->erase_sector_cnt; + uint32_t erase_addr = update_info->flash_info->erase_start_addr; + + AWLOGD_FW("erase_addr = 0x%08x, erase_len = %d, erase_cnt = %d", erase_addr, erase_len, erase_cnt); + erase_len = erase_len * 1; + + //1.close write protect + AWLOGD_FW("1.open host write FMC protect"); + ret = aw_sar_i2c_write(i2c, REG_ACCESSEN, REG_OPEN_APB_ACCESS_EN); + if (ret != AW_FW_OK) { + AWLOGE_FW("write REG_ACCESSEN err"); + return ret; + } + + ret = aw_sar_i2c_write(i2c, REG_PMU_CFG, REG_SET_PMU_CFG); + if (ret != AW_FW_OK) { + AWLOGE_FW("write REG_PMU_CFG err"); + return ret; + } + + if (update_info->update_flag == BOOT_UPDATE) { + ret = aw_sar_i2c_write(i2c, REG_ARRAY2_EW_EN, REG_SET_BTROM_EW_EN); + if (ret != AW_FW_OK) { + AWLOGE_FW("write REG_ARRAY2_EW_EN failed!"); + return ret; + } + } + + for (i = 0; i < erase_cnt; i++) { + //2.Erase one sector at a time + ret = aw_sar_i2c_write(i2c, REG_ISPADR, erase_addr + i * update_info->flash_info->sector_size); + if (ret != AW_FW_OK) { + AWLOGE_FW("write REG_ISPADR failed!"); + return ret; + } + + ret = aw_sar_i2c_write(i2c, REG_ISPCMD, REG_ACCESS_MAIN_ARR); + if (ret != AW_FW_OK) { + AWLOGE_FW("write REG_ISPCMD failed!"); + return ret; + } + + ret = aw_sar_i2c_write(i2c, REG_T_RCV, REG_SET_T_RCV); + if (ret != AW_FW_OK) { + AWLOGE_FW("write REG_T_RCV failed!"); + return ret; + } + + ret = aw_sar_i2c_write(i2c, REG_ISPGO, REG_SET_ISP_GO); + if (ret != AW_FW_OK) { + AWLOGE_FW("write REG_ISPGO failed!"); + return ret; + } + + ret = aw_check_isp_go_reg(i2c); + if (ret != AW_FW_OK) { + AWLOGE_FW("check_isp_go_reg failed!"); + return ret; + } + } + ret = aw_sar_i2c_write(i2c, REG_T_RCV, REG_SET_T_RCV_EN); + if (ret != AW_FW_OK) { + AWLOGE_FW("write REG_T_RCV failed!"); + return ret; + } + + ret = aw_sar_i2c_write(i2c, REG_PMU_CFG, REG_ENSET_PMU_CFG); + if (ret != AW_FW_OK) { + AWLOGE_FW("write REG_PMU_CFG failed!"); + return ret; + } + + return AW_FW_OK; +} + +static int32_t aw_flash_update(AW_SAR_I2C_TYPE i2c, struct aw_update_common *update_info) +{ + int32_t ret = 0; + uint32_t check_sum = 0; + + AWLOGD_FW("enter read_len = %d", update_info->update_data_len); + + //1.open register access enable + AWLOGE_FW("1.opne register access enable"); + ret = aw_sar_i2c_write(i2c, REG_ACCESSEN, REG_OPEN_REG_ACCESS_EN); + if (ret != AW_FW_OK) { + AWLOGE_FW("write REG_ACCESSEN failed!"); + return ret; + } + ret = aw_sar_i2c_write(i2c, REG_MCFG, REG_OPEN_MCFG_EN); + if (ret != AW_FW_OK) { + AWLOGE_FW("write REG_MCFG failed!"); + return ret; + } + ret = aw_sar_i2c_write(i2c, REG_PMU_CFG, REG_SET_PMU_CFG); + if (ret != AW_FW_OK) { + AWLOGE_FW("write REG_PMU_CFG failed!"); + return ret; + } + if (update_info->update_flag == FIRMWARE_UPDATE) { + ret = aw_sar_i2c_write(i2c, REG_ARRAY2_EW_EN, REG_SET_BTROM_EW_EN); + if (ret != AW_FW_OK) { + AWLOGE_FW("write REG_ARRAY2_EW_EN failed!"); + return ret; + } + } + + //2.Erase sector + AWLOGD_FW("2.Erase sector, flash_erase_start_addr:0x%08x, erase_len:0x%08x", + update_info->flash_info->erase_start_addr, update_info->flash_info->check_len); + ret = aw_erase_sector(i2c, update_info); + if (ret != AW_FW_OK) { + AWLOGE_FW("2. Erase sector failed!"); + return ret; + } + + //3.write flash + AWLOGD_FW("3.write flash"); + ret = aw_reg_write_bin_to_flash(i2c, update_info); + if (ret != AW_FW_OK) { + AWLOGE_FW("3. write flash failed!"); + return ret; + } + + //4.read data check + AWLOGD_FW("4.read data check"); + ret = aw_rd_or_wi_cmp(i2c, update_info, + update_info->w_bin_offset, + update_info->update_data_len); + if (ret != AW_FW_OK) { + AWLOGE_FW("4. read data check failed!"); + return -AW_FW_ERR; + } + + //5.write checksum + AWLOGD_FW("5.write checksum"); + //Turn on verification enable + ret = aw_reg_write_val_to_flash(i2c, update_info->update_flag, + update_info->flash_info->check_en_addr, + update_info->flash_info->check_en_val); + if (ret != AW_FW_OK) { + AWLOGE_FW("5.write check enable failed!"); + return -AW_FW_ERR; + } + + check_sum = aw_get_bin_checksum(update_info->w_bin_offset, + update_info->update_data_len, + update_info->flash_info->check_len); + AWLOGI_FW("check_sum = 0x%x", check_sum); + ret = aw_reg_write_val_to_flash(i2c, update_info->update_flag, + update_info->flash_info->check_code_addr, + check_sum); + if (ret != AW_FW_OK) { + AWLOGE_FW("5.write checksum failed!"); + return -AW_FW_ERR; + } + + //6.open flash protect + AWLOGD_FW("6.open flash protect"); + if (update_info->update_flag == FIRMWARE_UPDATE) { + ret = aw_sar_i2c_write(i2c, REG_ARRAY2_EW_EN, REG_ENSET_BTROM_EW_EN); + if (ret != AW_FW_OK) { + AWLOGE_FW("6.open flash protect failed"); + return ret; + } + } + + AWLOGI_FW("%s reg mode update succeeded!!!", + ((update_info->update_flag == BOOT_UPDATE)? "boot":"firmware")); + + return AW_FW_OK; +} + +int32_t aw_reg_update_para_check(struct aw_update_common *update_info) +{ + if ((update_info == NULL) || (update_info->flash_info == NULL)) { + return -AW_FW_ERR; + } + + if (update_info->w_bin_offset == NULL) { + return -AW_FW_ERR; + } + + return AW_FW_OK; +} + +int32_t aw_reg_update(AW_SAR_I2C_TYPE i2c, struct aw_update_common *update_info) +{ + int32_t ret = 0; + + ret = aw_reg_update_para_check(update_info); + if (ret != AW_FW_OK) { + return -AW_FW_ERR; + } + + return aw_flash_update(i2c, update_info); +} + +#define AW9620X_STAT_BASE_ADDR (0x1A00) +#define AW9620X_REG_FWVER ((0x000C) + AW9620X_STAT_BASE_ADDR) +#define AW9620X_REG_WST ((0x0010) + AW9620X_STAT_BASE_ADDR) + +#define AW_WORD_SZIE (4) + +#define AW9620X_BT_STAET_ADDR (0x10000000) +#define AW9620X_BT_END_ADDR (0x100007F4) +//Check the firmware area except the check code and check enable position +#define AW9620X_BT_CHECK_LEN (AW9620X_BT_END_ADDR - AW9620X_BT_STAET_ADDR + AW_WORD_SZIE) +#define AW9620X_BT_CHECK_EN_ADDR (0x100007F8) +#define AW9620X_BT_CHECK_CODE_ADDR (0x100007FC) +#define AW9620X_BT_CHECK_CODE_VAL (0x20222022) +#define AW9620X_BT_ERASE_START_ADDR (0x10000000) +#define AW9620X_BT_SECTOR_SIZE (128) +#define AW9620X_BT_ERASE_CNT ((AW9620X_BT_CHECK_CODE_ADDR - AW9620X_BT_ERASE_START_ADDR + AW_WORD_SZIE) / AW9620X_BT_SECTOR_SIZE) + +#define AW9620X_FW_START_ADDR (0x10002000) +#define AW9620X_FW_END_ADDR (0x10003FF4) +#define AW9620X_FW_CHECK_EN_ADDR (0x10003FF8) +#define AW9620X_FW_CHECK_CODE_ADDR (0x10003FFC) + +//Check the firmware area except the check code and check enable position +#define AW9620X_FW_CHECK_LEN (AW9620X_FW_END_ADDR - AW9620X_BT_CHECK_CODE_ADDR) + +#define AW9620X_FW_CHECK_CODE_VAL (0x20222022) +#define AW9620X_FW_ERASE_START_ADDR (0x10002000) +#define AW9620X_FW_SECTOR_SIZE (128) +//The number of sectors in the flash FW area is reduced by one +#define AW9620X_FW_ERASE_CNT ((AW9620X_FW_CHECK_CODE_ADDR - AW9620X_FW_ERASE_START_ADDR + AW_WORD_SZIE) / AW9620X_FW_SECTOR_SIZE) +#define AW9620X_CACHE_LEN (0x1000) + +static const struct aw_flash_update_info g_aw_prot_update_fw_info = { + .tr_start_addr = AW9620X_FW_START_ADDR, + .check_en_addr = AW9620X_FW_CHECK_EN_ADDR, + .check_code_addr = AW9620X_FW_CHECK_CODE_ADDR, + .check_en_val = AW9620X_FW_CHECK_CODE_VAL, + .check_len = AW9620X_FW_CHECK_LEN, + .erase_start_addr = AW9620X_FW_ERASE_START_ADDR, + .erase_sector_cnt = AW9620X_FW_ERASE_CNT, + .sector_size = AW9620X_FW_SECTOR_SIZE, +}; + +static const struct aw_update_chip_diff update_chip_diff = { + .fwver_reg_addr = AW9620X_REG_FWVER, + .chip_flag = CHIP_AW9620X, +}; + +int32_t aw9620x_prot_update_fw(AW_SAR_I2C_TYPE i2c, uint8_t direct_update_flag, + const uint8_t *data_start_offset, uint32_t update_data_len ,uint32_t fw_version) +{ + struct aw_update_para update_para = { + .direct_update_flag = direct_update_flag, //Upgrade without comparing version numbers + .aw_update_diff = &update_chip_diff, //Differences in chip updates + }; + //.cache_len = AW9620X_CACHE_LEN, + struct aw_fw_data_info fw_data_info = { + .data_start_offset = data_start_offset, + .update_data_len = update_data_len, + .fw_version = fw_version, + }; + + struct aw_fw_info fw_info = { + //.single_wr_len = AW9620X_CACHE_LEN / 4, + .single_wr_len = AW9620X_CACHE_LEN - 0x40, + .flash_info = &g_aw_prot_update_fw_info, + }; + + struct aw_update_fw update_fw = { + .fw_info = &fw_info, + .update_para = &update_para, + .fw_data_info = &fw_data_info, + }; + + return aw_prot_update(i2c, &update_fw); +} + +static const struct aw_flash_update_info g_aw_reg_fw_flash_info = { + .tr_start_addr = AW9620X_FW_START_ADDR, + .check_len = AW9620X_FW_CHECK_LEN, //37f8 + .check_en_addr = AW9620X_FW_CHECK_EN_ADDR, + .check_code_addr = AW9620X_FW_CHECK_CODE_ADDR, + .check_en_val = AW9620X_FW_CHECK_CODE_VAL, + + .erase_start_addr = AW9620X_FW_ERASE_START_ADDR, + .erase_sector_cnt = AW9620X_FW_ERASE_CNT, + .sector_size = AW9620X_FW_SECTOR_SIZE, + }; + +int32_t aw9620x_reg_update_fw(AW_SAR_I2C_TYPE i2c, + const uint8_t *data_start_offset, uint32_t update_data_len) +{ + struct aw_update_common update_info = { + .update_flag = FIRMWARE_UPDATE, + .w_bin_offset = data_start_offset, + .update_data_len = update_data_len, + .flash_info = &g_aw_reg_fw_flash_info, + }; + + return aw_reg_update(i2c, &update_info); +} + +static const struct aw_flash_update_info g_aw_reg_boot_flash_info = { + .tr_start_addr = AW9620X_BT_STAET_ADDR, + .check_len = AW9620X_BT_CHECK_LEN, //7f8 + .check_en_addr = AW9620X_BT_CHECK_EN_ADDR, + .check_code_addr = AW9620X_BT_CHECK_CODE_ADDR, + .check_en_val = AW9620X_BT_CHECK_CODE_VAL, + + .erase_start_addr = AW9620X_BT_STAET_ADDR, + .erase_sector_cnt = AW9620X_BT_ERASE_CNT, + .sector_size = AW9620X_BT_SECTOR_SIZE, +}; + +int32_t aw9620x_reg_update_boot(AW_SAR_I2C_TYPE i2c, + const uint8_t *data_start_offset, uint32_t update_data_len) +{ + struct aw_update_common update_info = { + .update_flag = BOOT_UPDATE, + .w_bin_offset = data_start_offset, + .update_data_len = update_data_len, + .flash_info = &g_aw_reg_boot_flash_info, + }; + + return aw_reg_update(i2c, &update_info); +} + diff --git a/drivers/misc/awinic/sarsensor/aw963xx/aw963xx.c b/drivers/misc/awinic/sarsensor/aw963xx/aw963xx.c new file mode 100644 index 000000000000..ee103a750bd9 --- /dev/null +++ b/drivers/misc/awinic/sarsensor/aw963xx/aw963xx.c @@ -0,0 +1,1334 @@ +#include "aw963xx.h" +#include "aw_sar.h" + +#define AW963XX_I2C_NAME "aw963xx_sar" +#define AW963XX_DRIVER_VERSION "v0.1.1.2" + +static void aw963xx_set_cs_as_irq(struct aw_sar *p_sar, int flag); +static void aw963xx_get_ref_ch_enable(struct aw_sar *p_sar); + +static int32_t aw963xx_read_init_over_irq(void *load_bin_para) +{ + uint32_t cnt = 1000; + uint32_t reg = 0; + int32_t ret = 0; + struct aw_sar *p_sar = (struct aw_sar *)load_bin_para; + + while (cnt--) { + ret = aw_sar_i2c_read(p_sar->i2c, REG_IRQSRC, ®); + if (ret != 0) { + AWLOGE(p_sar->dev, "i2c error %d", ret); + return ret; + } + if ((reg & 0x01) == 0x01) { + AWLOGI(p_sar->dev, "read init irq success!"); + aw_sar_i2c_read(p_sar->i2c, REG_FWVER, ®); + AWLOGI(p_sar->dev, "firmware version = 0x%08x", reg); + return AW_OK; + } + mdelay(1); + } + + aw_sar_i2c_read(p_sar->i2c, REG_FWVER, ®); + AWLOGI(p_sar->dev, "firmware version = 0x%08x", reg); + + return -AW_ERR; +} + +static void aw963xx_convert_little_endian_2_big_endian(struct aw_bin *aw_bin) +{ + int i = 0; + uint32_t start_index = aw_bin->header_info[0].valid_data_addr; + uint32_t fw_len = aw_bin->header_info[0].reg_num; + uint32_t uints = fw_len / AW963XX_SRAM_UPDATE_ONE_UINT_SIZE; + + for (i = 0; i < uints; i++) { + uint8_t tmp1 = aw_bin->info.data[start_index + i * AW963XX_SRAM_UPDATE_ONE_UINT_SIZE + 3]; + uint8_t tmp2 = aw_bin->info.data[start_index + i * AW963XX_SRAM_UPDATE_ONE_UINT_SIZE + 2]; + uint8_t tmp3 = aw_bin->info.data[start_index + i * AW963XX_SRAM_UPDATE_ONE_UINT_SIZE + 1]; + uint8_t tmp4 = aw_bin->info.data[start_index + i * AW963XX_SRAM_UPDATE_ONE_UINT_SIZE]; + aw_bin->info.data[start_index + i * AW963XX_SRAM_UPDATE_ONE_UINT_SIZE] = tmp1; + aw_bin->info.data[start_index + i * AW963XX_SRAM_UPDATE_ONE_UINT_SIZE + 1] = tmp2; + aw_bin->info.data[start_index + i * AW963XX_SRAM_UPDATE_ONE_UINT_SIZE + 2] = tmp3; + aw_bin->info.data[start_index + i * AW963XX_SRAM_UPDATE_ONE_UINT_SIZE + 3] = tmp4; + } +} + +/** + * @brief |----------------code ram-----------------| + * 0x2000 0x4fff + * |--- app wrote here ---|--fill with 0xff--| + * + * if the size of app is less than the size of code ram, the rest of the + * ram is filled with 0xff. + * @param load_bin_para + * @param offset the rear addr of app + * @return int32_t + */ +static int32_t aw963xx_sram_fill_not_wrote_area(void *load_bin_para, uint32_t offset) +{ + uint8_t buf[AW963XX_SRAM_UPDATE_ONE_PACK_SIZE + 2] = { 0 }; + uint8_t *r_buf = NULL; + int32_t ret = 0; + uint32_t i = 0; + uint32_t download_addr_with_ofst = 0; + uint32_t last_pack_len = (AW963XX_SRAM_END_ADDR - offset) % AW963XX_SRAM_UPDATE_ONE_PACK_SIZE; + uint32_t pack_cnt = last_pack_len == 0 ? + ((AW963XX_SRAM_END_ADDR - offset) / AW963XX_SRAM_UPDATE_ONE_PACK_SIZE) : + ((AW963XX_SRAM_END_ADDR - offset) / AW963XX_SRAM_UPDATE_ONE_PACK_SIZE) + 1; + struct aw_sar *p_sar = (struct aw_sar *)load_bin_para; + + r_buf = (uint8_t *)devm_kzalloc(p_sar->dev, AW963XX_SRAM_UPDATE_ONE_PACK_SIZE, GFP_KERNEL); + if (r_buf == NULL) { + AWLOGE(p_sar->dev, "devm_kzalloc error"); + return -AW_ERR; + } + + AWLOGI(p_sar->dev, "last_pack_len = %d", last_pack_len); + AWLOGI(p_sar->dev, "pack_cnt = %d", pack_cnt); + AWLOGI(p_sar->dev, "offset = 0x%x", offset); + + memset(buf, 0xff, sizeof(buf)); + + for (i = 0; i < pack_cnt; i++) { + memset(r_buf, 0, AW963XX_SRAM_UPDATE_ONE_PACK_SIZE); + download_addr_with_ofst = offset + i * AW963XX_SRAM_UPDATE_ONE_PACK_SIZE; + buf[0] = (uint8_t)(download_addr_with_ofst >> OFFSET_BIT_8); + buf[1] = (uint8_t)(download_addr_with_ofst); + if (i != (pack_cnt - 1)) { + ret = aw_sar_i2c_write_seq(p_sar->i2c, buf, AW963XX_SRAM_UPDATE_ONE_PACK_SIZE + 2); + if (ret != AW_OK) { + AWLOGI(p_sar->dev, "cnt%d, write_seq error!", i); + devm_kfree(p_sar->dev, r_buf); + return ret; + } + ret = aw_sar_i2c_read_seq(p_sar->i2c, buf, 2, r_buf, AW963XX_SRAM_UPDATE_ONE_PACK_SIZE); + if (ret != AW_OK) { + AWLOGI(p_sar->dev, "cnt%d, read_seq error!", i); + devm_kfree(p_sar->dev, r_buf); + return ret; + } + if (memcmp(&buf[2], r_buf, AW963XX_SRAM_UPDATE_ONE_PACK_SIZE) != 0) { + AWLOGE(p_sar->dev, "read is not equal to write "); + devm_kfree(p_sar->dev, r_buf); + return -AW_ERR; + } + } else { + ret = aw_sar_i2c_write_seq(p_sar->i2c, buf, last_pack_len + 2); + if (ret != AW_OK) { + AWLOGI(p_sar->dev, "cnt%d, write_seq error!", i); + devm_kfree(p_sar->dev, r_buf); + return ret; + } + ret = aw_sar_i2c_read_seq(p_sar->i2c, buf, 2, r_buf, last_pack_len); + if (ret != AW_OK) { + AWLOGI(p_sar->dev, "cnt%d, read_seq error!", i); + devm_kfree(p_sar->dev, r_buf); + return ret; + } + if (memcmp(&buf[2], r_buf, last_pack_len) != 0) { + AWLOGE(p_sar->dev, "read is not equal to write "); + devm_kfree(p_sar->dev, r_buf); + return -AW_ERR; + } + } + } + + devm_kfree(p_sar->dev, r_buf); + + return AW_OK; +} + +static int32_t aw963xx_sram_data_write(struct aw_bin *aw_bin, void *load_bin_para) +{ + uint8_t buf[AW963XX_SRAM_UPDATE_ONE_PACK_SIZE + 2] = { 0 }; + uint8_t *r_buf = NULL; + int32_t ret = 0; + uint32_t i = 0; + uint32_t pack_cnt = 0; + uint32_t start_index = aw_bin->header_info[0].valid_data_addr; + uint32_t fw_bin_version = aw_bin->header_info[0].app_version; + uint32_t download_addr = AW963XX_RAM_START_ADDR; + uint32_t fw_len = aw_bin->header_info[0].reg_num; + uint32_t last_pack_len = fw_len % AW963XX_SRAM_UPDATE_ONE_PACK_SIZE; + struct aw_sar *p_sar = (struct aw_sar *)load_bin_para; + uint32_t download_addr_with_ofst = 0; + + r_buf = (uint8_t *)devm_kzalloc(p_sar->dev, AW963XX_SRAM_UPDATE_ONE_PACK_SIZE, GFP_KERNEL); + if (r_buf == NULL) { + AWLOGE(p_sar->dev, "devm_kzalloc error"); + return -AW_ERR; + } + + pack_cnt = ((fw_len % AW963XX_SRAM_UPDATE_ONE_PACK_SIZE) == 0) ? + (fw_len / AW963XX_SRAM_UPDATE_ONE_PACK_SIZE) : + (fw_len / AW963XX_SRAM_UPDATE_ONE_PACK_SIZE) + 1; + + AWLOGI(p_sar->dev, "fw_bin_version = 0x%x", fw_bin_version); + AWLOGI(p_sar->dev, "download_addr = 0x%x", download_addr); + AWLOGI(p_sar->dev, "start_index = %d", start_index); + AWLOGI(p_sar->dev, "fw_len = %d", fw_len); + + for (i = 0; i < pack_cnt; i++) { + memset(r_buf, 0, AW963XX_SRAM_UPDATE_ONE_PACK_SIZE); + download_addr_with_ofst = download_addr + i * AW963XX_SRAM_UPDATE_ONE_PACK_SIZE; + buf[0] = (uint8_t)(download_addr_with_ofst >> OFFSET_BIT_8); + buf[1] = (uint8_t)(download_addr_with_ofst); + if (i != (pack_cnt - 1)) { + memcpy(&buf[2], &aw_bin->info.data[start_index + i * AW963XX_SRAM_UPDATE_ONE_PACK_SIZE], AW963XX_SRAM_UPDATE_ONE_PACK_SIZE); + ret = aw_sar_i2c_write_seq(p_sar->i2c, buf, AW963XX_SRAM_UPDATE_ONE_PACK_SIZE + 2); + if (ret != AW_OK) { + AWLOGI(p_sar->dev, "cnt%d, write_seq error!", i); + devm_kfree(p_sar->dev, r_buf); + return ret; + } + ret = aw_sar_i2c_read_seq(p_sar->i2c, buf, 2, r_buf, AW963XX_SRAM_UPDATE_ONE_PACK_SIZE); + if (ret != AW_OK) { + AWLOGI(p_sar->dev, "cnt%d, read_seq error!", i); + devm_kfree(p_sar->dev, r_buf); + return ret; + } + if (memcmp(&buf[2], r_buf, AW963XX_SRAM_UPDATE_ONE_PACK_SIZE) != 0) { + AWLOGE(p_sar->dev, "read is not equal to write "); + devm_kfree(p_sar->dev, r_buf); + return -AW_ERR; + } + } else { // last pack process + memcpy(&buf[2], &aw_bin->info.data[start_index + i * AW963XX_SRAM_UPDATE_ONE_PACK_SIZE], last_pack_len); + ret = aw_sar_i2c_write_seq(p_sar->i2c, buf, last_pack_len + 2); + if (ret != AW_OK) { + AWLOGI(p_sar->dev, "cnt%d, write_seq error!", i); + devm_kfree(p_sar->dev, r_buf); + return ret; + } + ret = aw_sar_i2c_read_seq(p_sar->i2c, buf, 2, r_buf, last_pack_len); + if (ret != AW_OK) { + AWLOGI(p_sar->dev, "cnt%d, read_seq error!", i); + devm_kfree(p_sar->dev, r_buf); + return ret; + } + if (memcmp(&buf[2], r_buf, last_pack_len) != 0) { + AWLOGE(p_sar->dev, "read is not equal to write "); + devm_kfree(p_sar->dev, r_buf); + return ret; + } + /* fill 0xff in the area that not worte. */ + ret = aw963xx_sram_fill_not_wrote_area(load_bin_para, download_addr_with_ofst + last_pack_len); + if (ret != AW_OK) { + AWLOGI(p_sar->dev, "cnt%d, sram_fill_not_wrote_area error!", i); + devm_kfree(p_sar->dev, r_buf); + return ret; + } + } + } + devm_kfree(p_sar->dev, r_buf); + + return AW_OK; +} + +static int32_t aw963xx_update_firmware(struct aw_bin *aw_bin, void *load_bin_para) +{ + struct aw_sar *p_sar = (struct aw_sar *)load_bin_para; + struct aw963xx *aw963xx = (struct aw963xx *)p_sar->priv_data; + struct i2c_client *i2c = p_sar->i2c; + int32_t ret = 0; + + if (aw963xx->start_mode == AW963XX_ROM_MODE) { + AWLOGI(p_sar->dev, "no need to update fw."); + return AW_OK; + } + + //step1: close coderam shutdown mode + aw_sar_i2c_write(i2c, 0xfff4, 0x3c00d11f); + aw_sar_i2c_write(i2c, 0xc400, 0x21660000); + + // step 2: reset mcu only and set boot mode to 1. (0xf800 0x00010100) + aw_sar_i2c_write(i2c, REG_CPU_MODE_SET, AW963XX_RESET_CPU_SET_BOOT_SATRT); + + // step 3: enable data ram. (0xFFE4 0x3C000000) + aw_sar_i2c_write(i2c, REG_RAM_PASSWORD, AW963XX_NO_ENCRYPTION); + + // setp 4: convert LD to BD + aw963xx_convert_little_endian_2_big_endian(aw_bin); + + // step 5: write ram data. + ret = aw963xx_sram_data_write(aw_bin, load_bin_para); + if (ret == AW_OK) { + AWLOGI(p_sar->dev, "sram_data_write OK"); + } else { + AWLOGI(p_sar->dev, "sram_data_write error"); + } + mdelay(3); + + // step 6: exit reset mcu and boot cpu in ram. (0xf800 0x00000100) + aw_sar_i2c_write(i2c, REG_CPU_MODE_SET, AW963XX_EXIT_RESET_CPU_SET_BOOT_SATRT); + + // step 7: reset cpu (0xFF0C 0x0) + aw_sar_i2c_write(i2c, REG_CPU_RESET, AW963XX_RESET_SET); + + //step 8: Wait for chip initialization to complete + msleep(AW963XX_CHIP_INIT_MAX_TIME_MS); + + return aw963xx_read_init_over_irq(load_bin_para); +} + +static int32_t aw963xx_load_reg_bin(struct aw_bin *aw_bin, void *load_bin_para) +{ + int32_t ret = 0; + struct aw_sar *p_sar = (struct aw_sar *)load_bin_para; + struct aw963xx *aw963xx = (struct aw963xx *)p_sar->priv_data; +/* + if (p_sar->chip_name == NULL) { + AWLOGE(p_sar->dev, "p_sar->chip_name is NULL, error!"); + return -AW_ERR; + } +*/ + AWLOGD(p_sar->dev, "reg chip name: %s, soc chip name: %s, len = %d", + p_sar->chip_name, aw_bin->header_info[0].chip_type, aw_bin->info.len); + + ret = strncmp(p_sar->chip_name, aw_bin->header_info[0].chip_type, sizeof(aw_bin->header_info[0].chip_type)); + if (ret != 0) { + AWLOGE(p_sar->dev, + "load_binname(%s) incompatible with chip type(%s)", + p_sar->chip_name, aw_bin->header_info[0].chip_type); + //return -AW_ERR; + } + + ret = aw_sar_load_reg(aw_bin, p_sar->i2c); + + if (!strncmp(p_sar->chip_name, AW96308, sizeof(AW96308)) || + !strncmp(p_sar->chip_name, AW96310, sizeof(AW96310))) { + AWLOGD(p_sar->dev, "set cs%d as irq", aw963xx->irq_mux); + aw963xx_set_cs_as_irq(p_sar, aw963xx->irq_mux); + } + + return ret; +} + +static void aw963xx_irq_handle_func(uint32_t irq_status, void *data) +{ + int8_t i = 0; + int8_t j = 0; + int32_t ret = 0; + uint32_t curr_status_val = 0; + struct aw_sar *p_sar = (struct aw_sar *)data; + + AWLOGD(p_sar->dev, "IRQSRC = 0x%x", irq_status); + + if (((irq_status >> 1) & 0x01) == 1) { + for (i = (AW963XX_VALID_TH - 1); i >= 0; i--) { + ret = aw_sar_i2c_read(p_sar->i2c, + REG_STAT0 + i * (REG_STAT1 - REG_STAT0), + &curr_status_val); + if (ret < 0) { + AWLOGE(p_sar->dev, "i2c IO error"); + return; + } + + for (j = 0; j < AW963XX_CHANNEL_NUM_MAX; j++) { + if ((((curr_status_val >> j) & 0x01) == AW963XX_APPROACH) && + (p_sar->channels_arr[j].last_channel_info == AW963XX_FAR_AWAY)) { + if (p_sar->channels_arr[j].input == NULL) { + continue; + } + p_sar->channels_arr[j].last_channel_info = AW963XX_APPROACH; + input_report_abs(p_sar->channels_arr[j].input, ABS_DISTANCE, i + 1); + input_sync(p_sar->channels_arr[j].input); + AWLOGD(p_sar->dev, "approach ch = %d th = %d", j, i); + break; + } + } + } + } + + if (((irq_status >> 2) & 0x01) == 1) { + ret = aw_sar_i2c_read(p_sar->i2c, REG_STAT0, &curr_status_val); + if (ret < 0) { + AWLOGE(p_sar->dev, "i2c IO error"); + return; + } + + for (j = 0; j < AW963XX_CHANNEL_NUM_MAX; j++) { + if ((((curr_status_val >> j) & 0x01) == AW963XX_FAR_AWAY) && + (p_sar->channels_arr[j].last_channel_info == AW963XX_APPROACH)) { + p_sar->channels_arr[j].last_channel_info = AW963XX_FAR_AWAY; + if (p_sar->channels_arr[i].used == AW_FALSE) { + continue; + } + input_report_abs(p_sar->channels_arr[j].input, ABS_DISTANCE, 0); + input_sync(p_sar->channels_arr[j].input); + AWLOGD(p_sar->dev, "far away ch = %d", j); + } + } + } +} + +static ssize_t aw963xx_operation_mode_get(void *data, char *buf) +{ + ssize_t len = 0; + struct aw_sar *p_sar = (struct aw_sar *)data; + + if (p_sar->last_mode == AW963XX_ACTIVE_MODE) + len += snprintf(buf + len, PAGE_SIZE - len, "operation mode: Active\n"); + else if (p_sar->last_mode == AW963XX_SLEEP_MODE) + len += snprintf(buf + len, PAGE_SIZE - len, "operation mode: Sleep\n"); + else if (p_sar->last_mode == AW963XX_DEEPSLEEP_MODE) + len += snprintf(buf + len, PAGE_SIZE - len, "operation mode: DeepSleep\n"); + else + len += snprintf(buf + len, PAGE_SIZE - len, "operation mode: Unconfirmed\n"); + + return len; +} + +static void aw963xx_sar_chip_info_get(void *data, char *buf, ssize_t *p_len) +{ + uint32_t reg_data = 0; + struct aw_sar *p_sar = (struct aw_sar *)data; + + *p_len += snprintf(buf + *p_len, PAGE_SIZE - *p_len, "sar%d, aw963xx chip driver version:%s\n", + p_sar->dts_info.sar_num, AW963XX_DRIVER_VERSION); + *p_len += snprintf(buf + *p_len, PAGE_SIZE - *p_len, "The driver supports UI\n"); + + aw_sar_i2c_read(p_sar->i2c, REG_CHIP_ID0, ®_data); + *p_len += snprintf(buf + *p_len, PAGE_SIZE - *p_len, "chipid is 0x%08x\n", reg_data); + + aw_sar_i2c_read(p_sar->i2c, REG_IRQEN, ®_data); + *p_len += snprintf(buf + *p_len, PAGE_SIZE - *p_len, "REG_HOSTIRQEN is 0x%08x\n", reg_data); +} + +static int32_t aw963xx_get_signed_cap(void *data, uint16_t reg_addr) +{ + uint32_t reg_data = 0; + int32_t off_f = 0; + uint32_t off_c = 0; + uint32_t off_m = 0; + uint32_t off_m_bit = 0; + uint32_t off_c_bit = 0; + int32_t s_ofst_c = 0; + uint32_t i = 0; + struct aw_sar *p_sar = (struct aw_sar *)data; + + aw_sar_i2c_read(p_sar->i2c, reg_addr, ®_data); + + off_f =((reg_data >> AW_BIT16) & ONE_WORD) * AW963XX_STEP_LEN_UNSIGNED_CAP_FINE_ADJ; + off_c = (reg_data >> AW_BIT8) & ONE_WORD; + off_m = reg_data & ONE_WORD; + + for (i = 0; i < 8; i++) { + off_m_bit = (off_m >> i) & 0x01; + off_c_bit = (off_c >> i) & 0x01; + s_ofst_c += ((1 - 2 * off_m_bit) * off_c_bit * aw_sar_pow2(i)) * AW963XX_STEP_LEN_UNSIGNED_CAP_ROUGH_ADJ; + } + + return (s_ofst_c + off_f); +} + +static uint32_t aw963xx_get_unsigned_cap(void *data, uint16_t reg_addr) +{ + uint32_t reg_data = 0; + uint32_t rough = 0; + uint32_t fine = 0; + struct aw_sar *p_sar = (struct aw_sar *)data; + + aw_sar_i2c_read(p_sar->i2c, reg_addr, ®_data); + + rough = ((reg_data >> AW_BIT8) & ONE_WORD) * AW963XX_STEP_LEN_UNSIGNED_CAP_ROUGH_ADJ; + fine =((reg_data >> AW_BIT16) & ONE_WORD) * AW963XX_STEP_LEN_UNSIGNED_CAP_FINE_ADJ; + + return (rough + fine); +} + +static void aw963xx_get_ref_ch_enable(struct aw_sar *p_sar) +{ + int32_t i = 0; + uint32_t refa_ch = 0; + uint32_t refb_ch = 0; + uint32_t reg_data = 0; + struct aw963xx *aw963xx = (struct aw963xx *)p_sar->priv_data; + + for (i = 0; i < AW963XX_CHANNEL_NUM_MAX; i++) { + aw_sar_i2c_read(p_sar->i2c, + REG_FILTCTRL0_CH0 + + i * (REG_FILTCTRL0_CH1 - REG_FILTCTRL0_CH0), + ®_data); + if ((reg_data >> AW963XX_FILTCTRL0_CHX_REFAEN) & 0x01) { + refa_ch = (reg_data >> AW963XX_FILTCTRL0_CHX_REFASEL) & 0x1f; + aw963xx->ref_ch_en[refa_ch] = AW963XX_REF_EN; + } + if ((reg_data >> AW963XX_FILTCTRL0_CHX_REFBEN) & 0x01) { + refb_ch = (reg_data >> AW963XX_FILTCTRL0_CHX_REFBSEL) & 0x1f; + aw963xx->ref_ch_en[refb_ch] = AW963XX_REF_EN; + } + AWLOGI(p_sar->dev, "ch%d = %d", i, aw963xx->ref_ch_en[i]); + } +} + +static ssize_t aw963xx_get_cap_offset(void *data, char *buf) +{ + ssize_t len = 0; + uint32_t reg_data = 0; + uint32_t mode = 0xff; + uint32_t i = 0; + uint32_t cap_ofst = 0; + int32_t signed_cap_ofst = 0; + uint32_t tmp = 0; + struct aw_sar *p_sar = (struct aw_sar *)data; + struct aw963xx *aw963xx = (struct aw963xx *)p_sar->priv_data; + + aw963xx_get_ref_ch_enable(p_sar); + + for (i = 0; i < AW963XX_CHANNEL_NUM_MAX; i++) { + aw_sar_i2c_read(p_sar->i2c, + REG_AFESOFTCFG0_CH0 + + i * (REG_AFESOFTCFG0_CH1 - REG_AFESOFTCFG0_CH0), + ®_data); + mode = reg_data & 0x0ff; + switch (mode) { + case AW963XX_UNSIGNED_CAP: //self-capacitance mode unsigned cail + cap_ofst = aw963xx_get_unsigned_cap(p_sar, + REG_AFECFG1_CH0 + i * (REG_AFECFG1_CH1 - REG_AFECFG1_CH0)); + AWLOGI(p_sar->dev, "cap_ofst = 0x%08x", cap_ofst); + AWLOGI(p_sar->dev, "unsigned cap ofst ch%d: %d.%dpf", + i, + cap_ofst / AW963XX_STEP_LEN_UNSIGNED_CAP_ENLARGE, + cap_ofst % AW963XX_STEP_LEN_UNSIGNED_CAP_ENLARGE); + break; + case AW963XX_SIGNED_CAP: //self-capacitance mode signed cail + cap_ofst = aw963xx_get_signed_cap(p_sar, + REG_AFECFG1_CH0 + i * (REG_AFECFG1_CH1 - REG_AFECFG1_CH0)); + signed_cap_ofst = (int)cap_ofst; + AWLOGI(p_sar->dev, "cap_ofst1 =0x%08x", signed_cap_ofst); + if (signed_cap_ofst < 0) { + + tmp = -signed_cap_ofst; + //AWLOGI(p_sar->dev, "cap_ofst2 = 0x%x", signed_cap_ofst); + AWLOGI(p_sar->dev, + "signed cap ofst ch%d: -%d.%dpf", + i, + tmp / AW963XX_STEP_LEN_UNSIGNED_CAP_ENLARGE, + tmp % AW963XX_STEP_LEN_UNSIGNED_CAP_ENLARGE); + } else { + //AWLOGI(p_sar->dev, "cap_ofst2 = 0x%x", signed_cap_ofst); + AWLOGI(p_sar->dev, + "signed cap ofst ch%d: %d.%dpf", + i, + signed_cap_ofst / AW963XX_STEP_LEN_UNSIGNED_CAP_ENLARGE, + signed_cap_ofst % AW963XX_STEP_LEN_UNSIGNED_CAP_ENLARGE); + } + break; + case AW963XX_MUTUAL_CAP: //mutual-capacitance mode + if (aw963xx->ref_ch_en[i] == AW963XX_REF_EN) { + cap_ofst = aw963xx_get_unsigned_cap(p_sar, + REG_AFECFG1_M_CH0 + i * (REG_AFECFG1_M_CH1 - REG_AFECFG1_M_CH0)); + AWLOGI(p_sar->dev, "cap_ofst = 0x%08x", cap_ofst); + AWLOGI(p_sar->dev, + "ref cap ofst ch%d: %d.%dpf", + i, + cap_ofst / AW963XX_STEP_LEN_UNSIGNED_CAP_ENLARGE, + cap_ofst % AW963XX_STEP_LEN_UNSIGNED_CAP_ENLARGE); + } else { + cap_ofst = aw963xx_get_signed_cap(p_sar, + REG_AFECFG1_CH0 + i * (REG_AFECFG1_CH1 - REG_AFECFG1_CH0)); + signed_cap_ofst = (int)cap_ofst; + AWLOGI(p_sar->dev, "cap_ofst1 = 0x%08x", signed_cap_ofst); + if (signed_cap_ofst < 0) { + + tmp = -signed_cap_ofst; + AWLOGI(p_sar->dev, "cap_ofst2 = 0x%x", signed_cap_ofst); + AWLOGI(p_sar->dev, + "mutual cap ofst ch%d: -%d.%dpf", + i, + tmp / AW963XX_STEP_LEN_UNSIGNED_CAP_ENLARGE, + tmp % AW963XX_STEP_LEN_UNSIGNED_CAP_ENLARGE); + } else { + AWLOGI(p_sar->dev, "cap_ofst2 = 0x%x", signed_cap_ofst); + AWLOGI(p_sar->dev, + "mutual cap ofst ch%d: %d.%dpf", + i, + signed_cap_ofst / AW963XX_STEP_LEN_UNSIGNED_CAP_ENLARGE, + signed_cap_ofst % AW963XX_STEP_LEN_UNSIGNED_CAP_ENLARGE); + } + } + break; + default: + AWLOGI(p_sar->dev, "aw963xx ofst error 0x%x", reg_data & 0x0f); + break; + } + cap_ofst /= 10000; + buf[i * 4 + 0] = (uint8_t)((cap_ofst >> 0) & 0xff); + buf[i * 4 + 1] = (uint8_t)((cap_ofst >> 8) & 0xff); + buf[i * 4 + 2] = (uint8_t)((cap_ofst >> 16) & 0xff); + buf[i * 4 + 3] = (uint8_t)((cap_ofst >> 24) & 0xff); + len +=4; + } + + return len; +} + +static void aw963xx_set_cs_as_irq(struct aw_sar *p_sar, int flag) +{ + if (flag == AW963XX_CS2_IRQ) { + aw_sar_i2c_write(p_sar->i2c, 0xfff4, 0x3c00d013); + aw_sar_i2c_write(p_sar->i2c, 0xc100, 0x00000020); + aw_sar_i2c_write(p_sar->i2c, 0xe018, 0x00000004); + } else if (flag == AW963XX_CS5_IRQ) { + aw_sar_i2c_write(p_sar->i2c, 0xfff4, 0x3c00d013); + aw_sar_i2c_write(p_sar->i2c, 0xc100, 0x00000800); + aw_sar_i2c_write(p_sar->i2c, 0xe018, 0x00000020); + } +} + +int32_t aw963xx_check_chipid(void *data) +{ + int32_t ret = -AW_ERR; + uint32_t reg_val = 0; + struct aw_sar *p_sar = (struct aw_sar *)data; + + if (p_sar == NULL) { + return -AW_BIN_PARA_INVALID; + } + + ret = aw_sar_i2c_read(p_sar->i2c, REG_CHIP_ID0, ®_val); + if (ret < 0) { + AWLOGE(p_sar->dev, "read CHIP ID failed: %d", ret); + return ret; + } + + switch (reg_val) { + case AW96303_CHIP_ID: + AWLOGI(p_sar->dev, "aw96303 detected, 0x%04x", reg_val); + memcpy(p_sar->chip_name, AW96303, 8); + ret = AW_OK; + break; + case AW96305_CHIP_ID: + AWLOGI(p_sar->dev, "aw96305 detected, 0x%04x", reg_val); + memcpy(p_sar->chip_name, AW96305, 8); + ret = AW_OK; + break; + case AW96308_CHIP_ID: + AWLOGI(p_sar->dev, "aw96308 detected, 0x%04x", reg_val); + memcpy(p_sar->chip_name, AW96308, 8); + ret = AW_OK; + break; + case AW96310_CHIP_ID: + AWLOGI(p_sar->dev, "aw96310 detected, 0x%04x", reg_val); + memcpy(p_sar->chip_name, AW96310, 8); + ret = AW_OK; + break; + default: + AWLOGI(p_sar->dev, "chip id error, 0x%04x", reg_val); + ret = -AW_ERR; + break; + } + + return ret; +} + +/**********************mode operation start*******************************/ +static void aw963xx_enable_clock(void *i2c) +{ + aw_sar_i2c_write_bits(i2c, REG_CHIPSTAT, ~AW963XX_CPU_OSC_CTRL_MASK, AW963XX_CPU_OSC_CTRL_MASK); +} + +static uint32_t aw963xx_rc_irqscr(void *i2c) +{ + uint32_t val = 0; + aw_sar_i2c_read(i2c, REG_IRQSRC, &val); + return val; +} + +static void aw963xx_set_active_cmd(void *i2c) +{ + aw_sar_i2c_write(i2c, REG_CMD, AW963XX_ACTIVE_MODE); +} + +static void aw963xx_set_sleep_cmd(void *i2c) +{ + aw_sar_i2c_write(i2c, REG_CMD, AW963XX_SLEEP_MODE); +} + +static void aw963xx_set_deepsleep_cmd(void *i2c) +{ + aw_sar_i2c_write(i2c, REG_CMD, AW963XX_DEEPSLEEP_MODE); +} + +static const struct aw_sar_mode_set_t g_aw963xx_mode_set[] = { + { + .chip_id = AW_SAR_NONE_CHECK_CHIP, + .chip_mode = { + .curr_mode = AW963XX_ACTIVE_MODE, + .last_mode = AW963XX_DEEPSLEEP_MODE, + }, + .mode_switch_ops = { + .enable_clock = aw963xx_enable_clock, + .rc_irqscr = NULL, + .mode_update = aw963xx_set_active_cmd, + }, + }, + { + .chip_id = AW_SAR_NONE_CHECK_CHIP, + .chip_mode = { + .curr_mode = AW963XX_ACTIVE_MODE, + .last_mode = AW963XX_SLEEP_MODE, + }, + .mode_switch_ops = { + .enable_clock = NULL, + .rc_irqscr = NULL, + .mode_update = aw963xx_set_active_cmd, + }, + }, + { + .chip_id = AW_SAR_NONE_CHECK_CHIP, + .chip_mode = { + .curr_mode = AW963XX_ACTIVE_MODE, + .last_mode = AW963XX_ACTIVE_MODE, + }, + .mode_switch_ops = { + .enable_clock = NULL, + .rc_irqscr = NULL, + .mode_update = aw963xx_set_active_cmd, + }, + }, + { + .chip_id = AW_SAR_NONE_CHECK_CHIP, + .chip_mode = { + .curr_mode = AW963XX_SLEEP_MODE, + .last_mode = AW963XX_DEEPSLEEP_MODE, + }, + .mode_switch_ops = { + .enable_clock = aw963xx_enable_clock, + .rc_irqscr = aw963xx_rc_irqscr, + .mode_update = aw963xx_set_sleep_cmd, + }, + }, + { + .chip_id = AW_SAR_NONE_CHECK_CHIP, + .chip_mode = { + .curr_mode = AW963XX_SLEEP_MODE, + .last_mode = AW963XX_ACTIVE_MODE, + }, + .mode_switch_ops = { + .enable_clock = NULL, + .rc_irqscr = aw963xx_rc_irqscr, + .mode_update = aw963xx_set_sleep_cmd, + }, + }, + { + .chip_id = AW_SAR_NONE_CHECK_CHIP, + .chip_mode = { + .curr_mode = AW963XX_DEEPSLEEP_MODE, + .last_mode = AW963XX_SLEEP_MODE, + }, + .mode_switch_ops = { + .enable_clock = NULL, + .rc_irqscr = aw963xx_rc_irqscr, + .mode_update = aw963xx_set_deepsleep_cmd, + }, + }, + { + .chip_id = AW_SAR_NONE_CHECK_CHIP, + .chip_mode = { + .curr_mode = AW963XX_DEEPSLEEP_MODE, + .last_mode = AW963XX_ACTIVE_MODE, + }, + .mode_switch_ops = { + .enable_clock = NULL, + .rc_irqscr = aw963xx_rc_irqscr, + .mode_update = aw963xx_set_deepsleep_cmd, + }, + }, +}; + +static void aw963xx_sar_get_firmware_info(void *data, char *buf, ssize_t *p_len) +{ + uint32_t reg_data = 0; + struct aw_sar *p_sar = (struct aw_sar *)data; + + aw_sar_i2c_read(p_sar->i2c, REG_FWVER, ®_data); + *p_len += snprintf(buf + *p_len, PAGE_SIZE - *p_len, "firmware is 0x%08x\n", reg_data); +} + +static int32_t aw963xx_parse_dts(void *data) +{ + int32_t val = 0; + struct aw_sar *p_sar = (struct aw_sar *)data; + struct aw963xx *aw963xx = (struct aw963xx *)p_sar->priv_data; + struct device_node *np = p_sar->i2c->dev.of_node; + + val = of_property_read_u32(np, "irq-mux", &aw963xx->irq_mux); + if (val != 0) { + AWLOGE(p_sar->dev, "irq-mux not detected"); + } else { + AWLOGI(p_sar->dev, "irq-mux = %d", aw963xx->irq_mux); + } + + val = of_property_read_u32(np, "start-mode", &aw963xx->start_mode); + if (val != 0) { + AWLOGE(p_sar->dev, "start-mode not detected"); + } else { + AWLOGI(p_sar->dev, "start-mode = %d", aw963xx->start_mode); + } + + return AW_OK; +} + +static const struct aw_sar_mode_t g_aw963xx_mode = { + .mode_set_arr = &g_aw963xx_mode_set[0], + .mode_set_arr_len = sizeof(g_aw963xx_mode_set) / sizeof(g_aw963xx_mode_set[0]), + .p_set_mode_node_fn = NULL, + .p_get_mode_node_fn = aw963xx_operation_mode_get, +}; + +static const struct aw_sar_diff_t g_aw963xx_diff = { + .diff0_reg = REG_DIFF_CH0, + .diff_step = REG_DIFF_CH1 - REG_DIFF_CH0, + .rm_float = AW963XX_DATA_PROCESS_FACTOR, + .p_get_diff_node_fn = NULL, +}; + +static const struct aw_sar_offset_t g_aw963xx_offset = { + .p_get_offset_node_fn = aw963xx_get_cap_offset, +}; + +static const struct aw_sar_aot_t g_aw963xx_aot = { + .aot_reg = REG_SCANCTRL1, + .aot_mask = ~0xfff, + .aot_flag = 0xfff, +}; + +static const struct aw_sar_para_load_t g_aw963xx_reg_arr_para = { + .reg_arr = aw963xx_reg_default, + .reg_arr_len = (sizeof(aw963xx_reg_default) / sizeof(aw963xx_reg_default[0])), +}; + +static const struct aw_sar_regulator_config_t g_regulator_config = { + .vcc_name = "vcc", + .min_uV = AW9620X_SAR_VCC_MIN_UV, + .max_uV = AW9620X_SAR_VCC_MAX_UV, +}; + +static const struct aw_sar_reg_list_t g_aw963xx_reg_list = { + .reg_none_access = REG_NONE_ACCESS, + .reg_rd_access = REG_RD_ACCESS, + .reg_wd_access = REG_WR_ACCESS, + .reg_perm = (struct aw_sar_reg_data *)&g_aw963xx_reg_access[0], + .reg_num = sizeof(g_aw963xx_reg_access) / sizeof(g_aw963xx_reg_access[0]), +}; + +static const struct aw_sar_chip_mode_t g_aw963xx_chip_mode = { + //.init_mode = AW963XX_ACTIVE_MODE, + .init_mode = AW963XX_SLEEP_MODE, + .active = AW963XX_ACTIVE_MODE, + .pre_init_mode = AW963XX_SLEEP_MODE, +}; + +static const struct aw_sar_load_bin_t g_aw963xx_load_reg_bin = { + .bin_name = "aw963xx_reg", + .bin_opera_func = aw963xx_load_reg_bin, + .p_update_fn = NULL, +}; + +static const struct aw_sar_load_bin_t g_aw963xx_load_fw_bin = { + .bin_name = "aw963xx_fw", + .bin_opera_func = aw963xx_update_firmware, + .p_get_prot_update_fw_node_fn = aw963xx_sar_get_firmware_info, + .bin_load_fail_opera = NULL, +}; + +static const struct aw_sar_get_chip_info_t g_aw963xx_get_chip_info = { + .p_get_chip_info_node_fn = aw963xx_sar_chip_info_get, +}; + +static const struct aw_sar_check_chipid_t g_aw963xx_check_chipid = { + .p_check_chipid_fn = aw963xx_check_chipid, +}; + +static const struct aw_sar_irq_init_t g_aw963xx_irq_init = { + .flags = GPIOF_DIR_IN | GPIOF_INIT_HIGH, + .irq_flags = IRQF_TRIGGER_FALLING | IRQF_ONESHOT, + .handler = NULL, + .thread_fn = NULL, + .rc_irq_fn = aw963xx_rc_irqscr, + .irq_spec_handler_fn = aw963xx_irq_handle_func, + + .p_irq_init_fn = NULL, + .p_irq_deinit_fn = NULL, +}; + +static const struct aw_sar_soft_rst_t g_aw963xx_soft_rst = { + .reg_rst = REG_SA_RSTNALL, + .reg_rst_val = AW963XX_SOFT_RST_EN, + .delay_ms = AW963XX_CHIP_INIT_MAX_TIME_MS, + .p_soft_reset_fn = NULL, +}; + +static const struct aw_sar_init_over_irq_t g_aw963xx_init_over_irq = { + .wait_times = 100, + .daley_step = 1, + .reg_irqsrc = REG_IRQSRC, + .irq_offset_bit = 0, + .irq_mask = 0x1, + .irq_flag = 0x1, + + .p_check_init_over_irq_fn = NULL, + .p_get_err_type_fn = NULL, +}; + +static ssize_t cali_show(struct class *class, + struct class_attribute *attr, + char *buf) +{ + struct aw963xx *aw963xx = container_of(class, struct aw963xx, capsense_class); + struct aw_sar *p_sar = NULL; + int32_t ret = 0; + + if (aw963xx == NULL) { + return 0; + } + p_sar = aw963xx->p_aw_sar; + if (p_sar == NULL) { + return 0; + } + + ret = aw_sar_i2c_write_bits(p_sar->i2c, REG_SCANCTRL1, ~0xfff, 0xfff); + + return snprintf(buf, 8, "%d\n", ret); +} + +static CLASS_ATTR_RO(cali); + +static ssize_t mode_show(struct class *class, + struct class_attribute *attr, + char *buf) +{ + struct aw963xx *aw963xx = container_of(class, struct aw963xx, capsense_class); + struct aw_sar *p_sar = NULL; + int mode = 0; + + if (aw963xx == NULL) { + return 0; + } + p_sar = aw963xx->p_aw_sar; + if (p_sar == NULL) { + return 0; + } + + if (p_sar->last_mode == AW963XX_ACTIVE_MODE) + mode = 1; + else + mode = 0; + + AWLOGD(p_sar->dev, "mode:0X%x", p_sar->last_mode); + + return snprintf(buf, 8, "%d\n", mode); +} + + +static ssize_t mode_store(struct class *class, + struct class_attribute *attr, + const char *buf, size_t count) +{ + int8_t mode = 0; + int set_mode = 0; + struct aw963xx *aw963xx = container_of(class, struct aw963xx, capsense_class); + struct aw_sar *p_sar = NULL; + + if (aw963xx == NULL) { + return 0; + } + p_sar = aw963xx->p_aw_sar; + if (p_sar == NULL) { + return 0; + } + + mode = buf[0]; + + AWLOGD(p_sar->dev, "mode:0X%x", mode); + + if (mode == 0x01) + set_mode = AW963XX_ACTIVE_MODE; + else + set_mode = AW963XX_SLEEP_MODE; + + aw_sar_mode_set(p_sar, set_mode); + + return count; +} + +static CLASS_ATTR_RW(mode); + +static ssize_t reg_show(struct class *class, + struct class_attribute *attr, + char *buf) +{ + u32 *p = (u32*)buf; + struct aw963xx *aw963xx = container_of(class, struct aw963xx, capsense_class); + struct aw_sar *p_sar = NULL; + + if (aw963xx == NULL) { + return 0; + } + p_sar = aw963xx->p_aw_sar; + if (p_sar == NULL) { + return 0; + } + + if(aw963xx->read_flag){ + aw963xx->read_flag = 0; + aw_sar_i2c_read(p_sar->i2c, aw963xx->read_reg, p); + AWLOGD(p_sar->dev, "read_reg = 0x%x, val = 0x%x", aw963xx->read_reg, *p); + return 4; + } + + return -1; +} + +static ssize_t reg_store(struct class *class, + struct class_attribute *attr, + const char *buf, size_t count) +{ + uint16_t regaddr = 0; + uint32_t val = 0; + int i = 0; + struct aw963xx *aw963xx = container_of(class, struct aw963xx, capsense_class); + struct aw_sar *p_sar = NULL; + + if (aw963xx == NULL) { + return 0; + } + p_sar = aw963xx->p_aw_sar; + if (p_sar == NULL) { + return 0; + } + + if( count != 7){ + AWLOGE(p_sar->dev, "params error[ count == %lu !=2]\n", count); + return -1; + } + for(i = 0 ; i < count ; i++) + AWLOGD(p_sar->dev, "buf[%d] = 0x%x\n", i, buf[i]); + + if(buf[6] == 0){ + regaddr = ((uint16_t)buf[0]<<8) | (uint16_t)buf[1]; + val= ((uint32_t)buf[2]<<24) | ((uint32_t)buf[3]<<16) | ((uint32_t)buf[4]<<8) | ((uint32_t)buf[5]); + AWLOGD(p_sar->dev, "regaddr:0x%x, val:0x%x", regaddr, val); + aw_sar_i2c_write(p_sar->i2c, regaddr, val); + } else if(buf[6] == 1) { + aw963xx->read_reg = ((uint16_t)buf[0]<<8) | (uint16_t)buf[1]; + AWLOGD(p_sar->dev, "aw963xx->read_reg:0x%x", aw963xx->read_reg); + aw963xx->read_flag = true; + AWLOGD(p_sar->dev, "-----------\n"); + } + return count; +} +static CLASS_ATTR_RW(reg); + +static ssize_t int_state_show(struct class *class, + struct class_attribute *attr, + char *buf) +{ + struct aw963xx *aw963xx = container_of(class, struct aw963xx, capsense_class); + struct aw_sar *p_sar = NULL; + + if (aw963xx == NULL) { + return 0; + } + p_sar = aw963xx->p_aw_sar; + if (p_sar == NULL) { + return 0; + } + AWLOGD(p_sar->dev, + "%d", p_sar->ret_val ); + + return snprintf(buf, 8, "%d\n", p_sar->intrrupt_init_state); +} +static CLASS_ATTR_RO(int_state); + +static ssize_t offset_show(struct class *class, + struct class_attribute *attr, + char *buf) +{ + struct aw963xx *aw963xx = container_of(class, struct aw963xx, capsense_class); + struct aw_sar *p_sar = NULL; + + if (aw963xx == NULL) { + return 0; + } + p_sar = aw963xx->p_aw_sar; + if (p_sar == NULL) { + return 0; + } + + return aw963xx_get_cap_offset(p_sar, buf); +} +static CLASS_ATTR_RO(offset); + +#ifdef USE_SENSORS_CLASS +static struct aw963xx *g_aw963xx = NULL; +static int capsensor_set_enable(struct sensors_classdev *sensors_cdev, unsigned int enable) +{ + uint8_t i = 0; + struct aw963xx *aw963xx = g_aw963xx; + struct aw_sar *p_sar = NULL; + uint8_t set_mode = 0; + + if (aw963xx == NULL) { + return 0; + } + + p_sar = aw963xx->p_aw_sar; + if (p_sar == NULL) { + return 0; + } + + for (i = 0; i < AW963XX_CHANNEL_NUM_MAX; i++) { + if ((p_sar->channels_arr[i].used == AW_FALSE) || + (p_sar->channels_arr[i].input == NULL)) { + continue; + } + if (enable == 1) { + input_report_abs(p_sar->channels_arr[i].input, ABS_DISTANCE, 0); + input_sync(p_sar->channels_arr[i].input); + aw_sar_i2c_write_bits(p_sar->i2c, REG_SCANCTRL1, ~0xfff, 0xfff); + } else { + input_report_abs(p_sar->channels_arr[i].input, ABS_DISTANCE, -1); + input_sync(p_sar->channels_arr[i].input); + } + AWLOGD(p_sar->dev, "enable cap sensor: %s", sensors_cdev->name); + } + + AWLOGD(p_sar->dev, "enable %d", enable); + + if (enable == 0x01) + set_mode = AW963XX_ACTIVE_MODE; + else + set_mode = AW963XX_SLEEP_MODE; + + aw_sar_mode_set(p_sar, set_mode); + + return 0; +} + +static const char *g_aw963xx_ch_name[] = { + "Moto CapSense Ch0", "Moto CapSense Ch1", "Moto CapSense Ch2", + "Moto CapSense Ch3", "Moto CapSense Ch4", "Moto CapSensor Ch5", + "Moto CapSense Ch6", "Moto CapSense Ch7", "Moto CapSense Ch8" + "Moto CapSensor Ch9", "Moto CapSensor Ch10", "Moto CapSensor Ch11", + "Moto CapSensor Ch12", "Moto CapSensor Ch13", "Moto CapSensor Ch14" +}; +static int32_t g_aw963xx_counter = 0; +#endif + +//moto_customization +static int32_t aw_sar_custom_flie_node_create(void *data) +{ + struct aw_sar *p_sar = NULL; + int32_t ret = 0; + struct aw963xx *aw963xx = NULL; +#ifdef USE_SENSORS_CLASS + int i = 0; +#endif + + if (data == NULL) { + return -1; + } + + p_sar = (struct aw_sar *)data; + aw963xx = (struct aw963xx *)p_sar->priv_data; + + AWLOGD(p_sar->dev, "aw_sar_custom_flie_node"); + + aw963xx->capsense_class.name = "capsense"; + aw963xx->capsense_class.owner = THIS_MODULE; + + ret = class_register(&aw963xx->capsense_class); + if (ret < 0) { + AWLOGE(p_sar->dev, "Create fsys class failed (%d)\n", ret); + return ret; + } + + ret = class_create_file(&aw963xx->capsense_class, &class_attr_cali); + if (ret < 0) { + AWLOGE(p_sar->dev, "Create cali file failed (%d)\n", ret); + return ret; + } + + ret = class_create_file(&aw963xx->capsense_class, &class_attr_int_state); + if (ret < 0) { + AWLOGE(p_sar->dev, "Create int_state file failed (%d)\n", ret); + return ret; + } + + ret = class_create_file(&aw963xx->capsense_class, &class_attr_mode); + if (ret < 0) { + AWLOGE(p_sar->dev, "Create mode file failed (%d)\n", ret); + return ret; + } + + ret = class_create_file(&aw963xx->capsense_class, &class_attr_reg); + if (ret < 0) { + AWLOGE(p_sar->dev, "Create reg file failed (%d)\n", ret); + return ret; + } + + ret = class_create_file(&aw963xx->capsense_class, &class_attr_offset); + if (ret < 0) { + AWLOGE(p_sar->dev, "Create offset file failed (%d)\n", ret); + return ret; + } + +#ifdef USE_SENSORS_CLASS + for (i = 0; i < AW963XX_CHANNEL_NUM_MAX; i++){ + if ((p_sar->channels_arr[i].used == AW_FALSE) || + (p_sar->channels_arr[i].input == NULL)) { + continue; + } + + aw963xx->sensors_capsensor_chs[i].sensors_enable = capsensor_set_enable; + aw963xx->sensors_capsensor_chs[i].sensors_poll_delay = NULL; + aw963xx->sensors_capsensor_chs[i].name = g_aw963xx_ch_name[g_aw963xx_counter]; + aw963xx->sensors_capsensor_chs[i].vendor = "awinic"; + aw963xx->sensors_capsensor_chs[i].version = 1; + aw963xx->sensors_capsensor_chs[i].type = SENSOR_TYPE_MOTO_CAPSENSE; + aw963xx->sensors_capsensor_chs[i].max_range = "5"; + aw963xx->sensors_capsensor_chs[i].resolution = "5.0"; + aw963xx->sensors_capsensor_chs[i].sensor_power = "0.1"; + aw963xx->sensors_capsensor_chs[i].min_delay = 0; + aw963xx->sensors_capsensor_chs[i].fifo_reserved_event_count = 0; + aw963xx->sensors_capsensor_chs[i].fifo_max_event_count = 0; + aw963xx->sensors_capsensor_chs[i].delay_msec = 100; + aw963xx->sensors_capsensor_chs[i].enabled = 0; + + AWLOGD(p_sar->dev, "cap sensor_class channel_name:%s", g_aw963xx_ch_name[g_aw963xx_counter]); + AWLOGD(p_sar->dev, "ch:%d sensors_capsensor_chs:%p", i, &aw963xx->sensors_capsensor_chs[i]); + ret = sensors_classdev_register(&p_sar->channels_arr[i].input->dev, &aw963xx->sensors_capsensor_chs[i]); + if (ret < 0) + AWLOGE(p_sar->dev, "create ch0 cap sensor_class file failed (%d)\n", ret); + g_aw963xx_counter++; + g_aw963xx_counter = g_aw963xx_counter > (sizeof(g_aw963xx_ch_name) / sizeof(g_aw963xx_ch_name[0])) ? + (sizeof(g_aw963xx_ch_name) / sizeof(g_aw963xx_ch_name[0])) : g_aw963xx_counter; + } +#endif + + return ret; +} + +static void aw_sar_custom_flie_node_free(void *data) +{ + struct aw_sar *p_sar = NULL; + struct aw963xx *aw963xx = NULL; +#ifdef USE_SENSORS_CLASS + int i = 0; +#endif + + if (data == NULL) { + return; + } + + p_sar = (struct aw_sar *)data; + aw963xx = (struct aw963xx *)p_sar->priv_data; + +#ifdef USE_SENSORS_CLASS + for (i = 0; i < AW963XX_CHANNEL_NUM_MAX; i++){ + if ((p_sar->channels_arr[i].used == AW_FALSE) || + (p_sar->channels_arr[i].input == NULL)) { + continue; + } + g_aw963xx_counter--; + g_aw963xx_counter = g_aw963xx_counter < 0 ? 0 : g_aw963xx_counter; + sensors_classdev_unregister(&aw963xx->sensors_capsensor_chs[g_aw963xx_counter]); + } +#endif + + class_remove_file(&aw963xx->capsense_class, &class_attr_offset); + class_remove_file(&aw963xx->capsense_class, &class_attr_reg); + class_remove_file(&aw963xx->capsense_class, &class_attr_mode); + class_remove_file(&aw963xx->capsense_class, &class_attr_int_state); + class_remove_file(&aw963xx->capsense_class, &class_attr_cali); + + class_unregister(&aw963xx->capsense_class); +} + +static const struct aw_sar_pm_t g_aw963xx_pm_chip_mode = { + .suspend_set_mode = AW963XX_SLEEP_MODE, + .resume_set_mode = AW963XX_ACTIVE_MODE, + .shutdown_set_mode = AW963XX_SLEEP_MODE, +}; + +static const struct aw_sar_platform_config g_aw963xx_platform_config = { + .p_add_parse_dts_fn = &aw963xx_parse_dts, + .p_regulator_config = &g_regulator_config, + .p_irq_init = &g_aw963xx_irq_init, + .p_pm_chip_mode = &g_aw963xx_pm_chip_mode, +}; + +static const struct aw_sar_chip_config g_aw963xx_chip_config = { + .ch_num_max = AW963XX_CHANNEL_NUM_MAX, + .p_platform_config = &g_aw963xx_platform_config, + + .p_check_chipid = &g_aw963xx_check_chipid, + .p_soft_rst = &g_aw963xx_soft_rst, + .p_init_over_irq = &g_aw963xx_init_over_irq, + .p_fw_bin = &g_aw963xx_load_fw_bin, + .p_reg_bin = &g_aw963xx_load_reg_bin, + .p_chip_mode = &g_aw963xx_chip_mode, + + //Node usage parameters + .p_reg_list = &g_aw963xx_reg_list, + .p_reg_arr = &g_aw963xx_reg_arr_para, + .p_aot = &g_aw963xx_aot, + .p_diff = &g_aw963xx_diff, + .p_offset = &g_aw963xx_offset, + .p_mode = &g_aw963xx_mode, + .p_prox_fw = &g_aw963xx_load_fw_bin, + .p_get_chip_info = &g_aw963xx_get_chip_info, + .p_aw_sar_awrw = NULL, + .p_boot_bin = NULL, + + .p_other_operation = aw_sar_custom_flie_node_create, + .p_other_opera_free = aw_sar_custom_flie_node_free, +}; + +int32_t aw963xx_init(struct aw_sar *p_sar) +{ + struct aw963xx *aw963xx = NULL; + + if (p_sar == NULL) { + AWLOGE(p_sar->dev, "para is NULL, error!"); + return -AW_ERR; + } + + p_sar->priv_data = devm_kzalloc(p_sar->dev, sizeof(struct aw963xx), GFP_KERNEL); + if (p_sar->priv_data == NULL) { + AWLOGE(p_sar->dev, "priv_data failed to malloc memory!"); + return -AW_ERR; + } + + //Chip private function operation + p_sar->p_sar_para = &g_aw963xx_chip_config; + + aw963xx = (struct aw963xx *)p_sar->priv_data; + aw963xx->p_aw_sar = (void *)p_sar; + g_aw963xx = aw963xx; + + return AW_OK; +} + +void aw963xx_deinit(struct aw_sar *p_sar) +{ + struct aw963xx *aw963xx = NULL; + + if ((p_sar == NULL) || (p_sar->priv_data == NULL)) { + return; + } + + aw963xx = (struct aw963xx *)p_sar->priv_data; + + del_timer_sync(&aw963xx->abnormal_irq_timer); + + if (p_sar->priv_data != NULL) { + devm_kfree(p_sar->dev, p_sar->priv_data); + } + + AWLOGI(p_sar->dev, "aw963xx_deinit ok!"); +} diff --git a/drivers/misc/awinic/sarsensor/aw_sar.c b/drivers/misc/awinic/sarsensor/aw_sar.c new file mode 100644 index 000000000000..cc0b94734226 --- /dev/null +++ b/drivers/misc/awinic/sarsensor/aw_sar.c @@ -0,0 +1,2221 @@ +#include "aw_sar_chip_interface.h" +#include "aw_sar.h" + +#define AW_SAR_I2C_NAME "awinic_sar" +#define AW_SAR_DRIVER_VERSION "v0.1.5.2" + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,9,0) +#ifdef CONFIG_AW96XX_MTK_KERNEL419_CHARGER_TYPE +#define USB_POWER_SUPPLY_NAME "mtk_charger_type" +#elif defined(CONFIG_AW96XX_MTK_KERNEL5XX_CHARGER_TYPE) +#define USB_POWER_SUPPLY_NAME "mtk-master-charger" +#else +#define USB_POWER_SUPPLY_NAME "charger" +#endif +#else +#define USB_POWER_SUPPLY_NAME "usb" +#endif + + +#define AW_I2C_RW_RETRY_TIME_MIN (2000) +#define AW_I2C_RW_RETRY_TIME_MAX (3000) +#define AW_RETRIES (5) + +#define AW_SAR_AWRW_OffSET (20) +#define AW_SAR_AWRW_DATA_WIDTH (5) +#define AW_DATA_OffSET_2 (2) +#define AW_DATA_OffSET_3 (3) +#define AW_SAR_CH_MAX (20) +#define AW_POWER_ON_SYSFS_DELAY_MS (5000) +#define AW_SAR_OFFSET_LEN (15) + +static struct mutex aw_sar_lock; + +static int32_t aw_sar_get_chip_info(struct aw_sar *p_sar); +static void aw_sar_sensor_free(struct aw_sar *p_sar); + +//Because disable/enable_irq api Therefore, IRQ is embedded +void aw_sar_disable_irq(struct aw_sar *p_sar) +{ + if (p_sar->irq_init.host_irq_stat == IRQ_ENABLE) { + disable_irq(p_sar->irq_init.to_irq); + p_sar->irq_init.host_irq_stat = IRQ_DISABLE; + } +} + +void aw_sar_enable_irq(struct aw_sar *p_sar) +{ + if (p_sar->irq_init.host_irq_stat == IRQ_DISABLE) { + enable_irq(p_sar->irq_init.to_irq); + p_sar->irq_init.host_irq_stat = IRQ_ENABLE; + } +} + +//Chip logic part start +//Load default array function +static int32_t aw_sar_para_loaded_func(struct i2c_client *i2c, + const struct aw_sar_para_load_t *para_load) +{ + int32_t i = 0; + int32_t ret = 0; + + for (i = 0; i < para_load->reg_arr_len; i = i + 2) { + ret = aw_sar_i2c_write(i2c, (uint16_t)para_load->reg_arr[i], + para_load->reg_arr[i + 1]); + if (ret != AW_OK) { + return -AW_REG_LOAD_ERR; + } + AWLOGD(&i2c->dev,"reg_addr = 0x%04x, reg_data = 0x%08x", + para_load->reg_arr[i], + para_load->reg_arr[i + 1]); + } + + AWLOGD(&i2c->dev, "para writen completely"); + + return AW_OK; +} + +//Mode setting function +static void aw_sar_mode_set_func(struct i2c_client *i2c, int to_irq, struct aw_sar_mode_set_t *mode_set_para, + const struct aw_sar_mode_set_t *mode_set, uint8_t len) +{ + uint8_t i = 0; + + AWLOGD(&i2c->dev, "enter"); + + for(i = 0; i < len; i++) { + //AWLOGD(&i2c->dev, "i = %d mode_set:%d chip_id:%d", i, mode_set[i].chip_id, mode_set_para->chip_id); + if ((mode_set[i].chip_mode.curr_mode == mode_set_para->chip_mode.curr_mode) && + (mode_set[i].chip_mode.last_mode == mode_set_para->chip_mode.last_mode) && + ((mode_set[i].chip_id == AW_SAR_NONE_CHECK_CHIP) || + ((mode_set[i].chip_id & mode_set_para->chip_id) != 0))) { + if (mode_set[i].mode_switch_ops.enable_clock != NULL) { + mode_set[i].mode_switch_ops.enable_clock(i2c); + } + if (mode_set[i].mode_switch_ops.rc_irqscr != NULL) { + mode_set[i].mode_switch_ops.rc_irqscr(i2c); + } + if (mode_set[i].mode_switch_ops.mode_update != NULL) { + AWLOGD(&i2c->dev, "set curr_mode:%d, ok", mode_set_para->chip_mode.curr_mode); + mode_set[i].mode_switch_ops.mode_update(i2c); + } + break; + } + } +} + +static int32_t aw_sar_check_init_over_irq_func(struct i2c_client *i2c, + const struct aw_sar_init_over_irq_t *p_check_irq) +{ + int32_t ret = -AW_ERR; + uint32_t irq_stat = 0; + int16_t cnt = p_check_irq->wait_times; + + do { + ret = aw_sar_i2c_read(i2c, p_check_irq->reg_irqsrc, &irq_stat); + if (ret < 0) { + return -AW_ERR; + } + if (((irq_stat >> p_check_irq->irq_offset_bit) & p_check_irq->irq_mask) == p_check_irq->irq_flag) { + AWLOGD(&i2c->dev, "check_init_over_irqt ok!"); + return AW_OK; + } else { + AWLOGE(&i2c->dev, "init over irq no ok! val:0x%x cnt: %d", irq_stat, cnt); + } + mdelay(1); + } while (cnt--); + + if (cnt < 0) { + AWLOGE(&i2c->dev, "init over irq error!"); + } + + return -AW_ERR_IRQ_INIT_OVER; +} + +static int32_t aw_sar_soft_reset_func(struct i2c_client *i2c, const struct aw_sar_soft_rst_t *p_soft_rst) +{ + int32_t ret = 0; + + AWLOGD(&i2c->dev, "enter"); + + ret = aw_sar_i2c_write(i2c, p_soft_rst->reg_rst, p_soft_rst->reg_rst_val); + if (ret < 0) { + AWLOGE(&i2c->dev, "soft_reset error: %d", ret); + return -AW_ERR; + } + + msleep(p_soft_rst->delay_ms); + + return AW_OK; +} +//Chip logic part end + +static int32_t aw_sar_parse_bin(const struct firmware *cont, struct aw_sar *p_sar) +{ + struct aw_bin *aw_bin = NULL; + int32_t ret = -AW_ERR; + + if (!cont) { + AWLOGE(p_sar->dev, "def_reg_bin request error!"); + return -AW_ERR; + } else { + AWLOGI(p_sar->dev, "def_reg_bin request successfully"); + } + + AWLOGD(p_sar->dev, "Bin file size: %d", (uint32_t)cont->size); + + aw_bin = kzalloc(cont->size + sizeof(struct aw_bin), GFP_KERNEL); + if (!aw_bin) { + kfree(aw_bin); + release_firmware(cont); + AWLOGE(p_sar->dev, "failed to allcating memory!"); + return -AW_ERR; + } + + aw_bin->info.len = cont->size; + memcpy(aw_bin->info.data, cont->data, cont->size); + + if (cont != NULL) { + release_firmware(cont); + } + + ret = aw_sar_parsing_bin_file(aw_bin); + if (ret < 0) { + AWLOGE(p_sar->dev, "parse bin fail! ret = %d", ret); + goto err; + } + + //Write bin file execution process + if (p_sar->load_bin.bin_opera_func != NULL) { + ret = p_sar->load_bin.bin_opera_func(aw_bin, p_sar); + if (ret != AW_OK) { + AWLOGE(p_sar->dev, "load_bin_to_chip error!"); + if (p_sar->load_bin.bin_load_fail_opera_func != NULL) { + ret = p_sar->load_bin.bin_load_fail_opera_func(aw_bin, p_sar); + if (ret != AW_OK) { + AWLOGE(p_sar->dev, "bin_load_fail_opera_func error!"); + goto err; + } else { + AWLOGD(p_sar->dev, "bin_load_fail_opera_func OK!"); + } + } else { + goto err; + } + } + } else { + AWLOGE(p_sar->dev, "bin_opera_func is null error!"); + } + + if (aw_bin != NULL) { + kfree(aw_bin); + } + + AWLOGE(p_sar->dev, "load_def_reg_bin ok!!!"); + + return AW_OK; +err: + if (aw_bin != NULL) { + kfree(aw_bin); + } + return -AW_ERR; +} + +int32_t aw_sar_load_bin_comm(struct aw_sar *p_sar) +{ + int32_t ret = -AW_ERR; + const struct firmware *fw = NULL; + + AWLOGD(p_sar->dev, "name :%s", p_sar->load_bin.bin_name); + + ret = request_firmware(&fw, p_sar->load_bin.bin_name, p_sar->dev); + AWLOGD(p_sar->dev, "ret = %d", ret); + if (ret != AW_OK) { + AWLOGE(p_sar->dev, "parse %s error!", p_sar->load_bin.bin_name); + return -AW_ERR; + } else { + AWLOGD(p_sar->dev, "parse %s ok!", p_sar->load_bin.bin_name); + } + + ret = aw_sar_parse_bin(fw, p_sar); + if (ret != AW_OK) { + AWLOGE(p_sar->dev, "reg_bin %s load error!", p_sar->load_bin.bin_name); + return -AW_ERR; + } else { + AWLOGD(p_sar->dev, "reg_bin %s load ok!",p_sar->load_bin.bin_name); + } + + return AW_OK; +} + +int32_t aw_sar_parse_dts_comm(struct device *dev, struct device_node *np, struct aw_sar_dts_info *p_dts_info) +{ + int32_t val = 0; + + val = of_property_read_u32(np, "sar-num", &p_dts_info->sar_num); + if (val != 0) { + AWLOGE(dev, "multiple sar failed!"); + return -AW_ERR; + } else { + AWLOGI(dev, "sar num = %d", p_dts_info->sar_num); + } + + p_dts_info->irq_gpio = of_get_named_gpio(np, "irq-gpio", 0); + if (p_dts_info->irq_gpio < 0) { + p_dts_info->irq_gpio = -1; + AWLOGE(dev, "no irq gpio provided."); + return -AW_ERR; + } else { + AWLOGI(dev, "irq gpio provided ok."); + } + + val = of_property_read_u32(np, "channel_use_flag", &p_dts_info->channel_use_flag); + if (val != 0) { + AWLOGE(dev, "channel_use_flag failed!"); + return -AW_ERR; + } else { + AWLOGI(dev, "channel_use_flag = 0x%x", p_dts_info->channel_use_flag); + } + + //GPIO is set as internal pull-up input + p_dts_info->use_inter_pull_up = of_property_read_bool(np, "aw_sar,pin_set_inter_pull-up"); + AWLOGI(dev, "aw_sar,use_inter_pull_up = <%d>", p_dts_info->use_inter_pull_up); + + p_dts_info->use_pm = of_property_read_bool(np, "aw_sar,using_pm_ops"); + AWLOGI(dev, "aw_sar,pin_set_inter_pull-up = <%d>", p_dts_info->use_pm); + + p_dts_info->update_fw_flag = of_property_read_bool(np, "aw_sar,update_fw"); + AWLOGI(dev, "aw_sar,update_fw = <%d>", p_dts_info->update_fw_flag); + + p_dts_info->use_plug_cail_flag = of_property_read_bool(np, "aw_sar,use_plug_cail"); + AWLOGI(dev, "aw_sar,use_plug_cail_flag = <%d>", p_dts_info->use_plug_cail_flag); + + return AW_OK; +} + +static int32_t aw_sar_parse_dts(struct aw_sar *p_sar) +{ + int32_t ret = 0; + + AWLOGD(p_sar->dev, "enter"); + + ret = aw_sar_parse_dts_comm(p_sar->dev, p_sar->i2c->dev.of_node, &p_sar->dts_info); + + //Special requirements of SAR chip + if (p_sar->p_sar_para->p_platform_config->p_add_parse_dts_fn != NULL) { + ret |= p_sar->p_sar_para->p_platform_config->p_add_parse_dts_fn(p_sar); + } + + return ret; +} + +static irqreturn_t aw_sar_irq(int32_t irq, void *data) +{ + struct aw_sar *p_sar = (struct aw_sar *)data; + uint32_t irq_status = 0; + + //step1: read clear interrupt + if (p_sar->p_sar_para->p_platform_config->p_irq_init->rc_irq_fn != NULL) { + irq_status = p_sar->p_sar_para->p_platform_config->p_irq_init->rc_irq_fn(p_sar->i2c); + } + + //step2: Read the status register for status reporting + if (p_sar->p_sar_para->p_platform_config->p_irq_init->irq_spec_handler_fn != NULL) { + p_sar->p_sar_para->p_platform_config->p_irq_init->irq_spec_handler_fn(irq_status, p_sar); + } + + return IRQ_HANDLED; +} + +static int32_t aw_sar_irq_init_comm(struct aw_sar *p_sar, const struct aw_sar_irq_init_t *p_irq_init) +{ + int32_t ret = 0; + irq_handler_t thread_fn = p_irq_init->thread_fn; + + snprintf(p_sar->irq_init.label, sizeof(p_sar->irq_init.label), + "aw_sar%d_gpio", p_sar->dts_info.sar_num); + snprintf(p_sar->irq_init.dev_id, sizeof(p_sar->irq_init.dev_id), + "aw_sar%d_irq", p_sar->dts_info.sar_num); + + if (gpio_is_valid(p_sar->dts_info.irq_gpio)) { + p_sar->irq_init.to_irq = gpio_to_irq(p_sar->dts_info.irq_gpio); + ret = devm_gpio_request_one(p_sar->dev, + p_sar->dts_info.irq_gpio, + p_irq_init->flags, + p_sar->irq_init.label); + if (ret) { + AWLOGE(p_sar->dev, + "request irq gpio failed, ret = %d", ret); + ret = -AW_ERR; + } else { + if (thread_fn == NULL) { + thread_fn = aw_sar_irq; + } + ret = devm_request_threaded_irq(p_sar->dev, + p_sar->irq_init.to_irq, + p_irq_init->handler, + thread_fn, + p_irq_init->irq_flags, + p_sar->irq_init.dev_id, + p_sar); + if (ret != 0) { + AWLOGE(p_sar->dev, + "failed to request IRQ %d: %d", + p_sar->irq_init.to_irq, ret); + ret = -AW_ERR; + } else { + AWLOGI(p_sar->dev, + "IRQ request successfully!"); + ret = AW_OK; + p_sar->intrrupt_init_state = AW_TRUE; + AWLOGI(p_sar->dev, + "%d", p_sar->ret_val ); + } + } + } else { + AWLOGE(p_sar->dev, "irq gpio invalid!"); + return -AW_ERR; + } + + AWLOGI(p_sar->dev, "disable_irq"); + p_sar->irq_init.host_irq_stat = IRQ_DISABLE; + disable_irq(p_sar->irq_init.to_irq); + + AWLOGD(p_sar->dev, "irq init success!"); + + return AW_OK; +} + +static int32_t aw_sar_irq_init(struct aw_sar *p_sar) +{ + AWLOGD(p_sar->dev, "aw_sar_irq_init enter!"); + + if (p_sar->p_sar_para->p_platform_config->p_irq_init == NULL) { + AWLOGE(p_sar->dev, "AW_INVALID_PARA"); + return AW_INVALID_PARA; + } + + if (p_sar->p_sar_para->p_platform_config->p_irq_init->p_irq_init_fn != NULL) { + AWLOGE(p_sar->dev, "p_irq_init_fn"); + return p_sar->p_sar_para->p_platform_config->p_irq_init->p_irq_init_fn(p_sar); + } + + return aw_sar_irq_init_comm(p_sar, p_sar->p_sar_para->p_platform_config->p_irq_init); +} + +static void aw_sar_irq_free(struct aw_sar *p_sar) +{ + if ((p_sar->p_sar_para->p_platform_config != NULL) && + (p_sar->p_sar_para->p_platform_config->p_irq_init != NULL) && + (p_sar->p_sar_para->p_platform_config->p_irq_init->p_irq_deinit_fn != NULL)) { + p_sar->p_sar_para->p_platform_config->p_irq_init->p_irq_deinit_fn(p_sar); + AWLOGE(p_sar->dev, "AW_INVALID_PARA"); + return; + } + AWLOGE(p_sar->dev, "aw_sar_irq_free"); + +} + +static int32_t aw_sar_input_init_comm(struct aw_sar *p_sar) +{ + uint32_t i = 0; + int32_t ret = 0; + + p_sar->channels_arr = devm_kzalloc(p_sar->dev, + sizeof(struct aw_channels_info) * + p_sar->p_sar_para->ch_num_max, + GFP_KERNEL); + if (p_sar->channels_arr == NULL) { + AWLOGE(p_sar->dev, "devm_kzalloc err"); + return -AW_ERR; + } + + for (i = 0; i < p_sar->p_sar_para->ch_num_max; i++) { + //snprintf(p_sar->channels_arr[i].name, + // sizeof(p_sar->channels_arr->name), + // "aw_sar%d_ch%d", + // p_sar->dts_info.sar_num, i); + snprintf(p_sar->channels_arr[i].name, + sizeof(p_sar->channels_arr->name), + "Moto CapSense Ch%d", i); + + p_sar->channels_arr[i].last_channel_info = 0; + + if ((p_sar->dts_info.channel_use_flag >> i) & 0x01) { + p_sar->channels_arr[i].used = AW_TRUE; + p_sar->channels_arr[i].input = input_allocate_device(); + if (p_sar->channels_arr[i].input == NULL) { + return -AW_ERR; + } + p_sar->channels_arr[i].input->name = p_sar->channels_arr[i].name; + __set_bit(EV_ABS, p_sar->channels_arr[i].input->evbit); + input_set_abs_params(p_sar->channels_arr[i].input, + ABS_DISTANCE, -1, 100, 0, 0); + ret = input_register_device(p_sar->channels_arr[i].input); + if (ret) { + AWLOGE(p_sar->dev, "failed to register input device"); + return -AW_ERR; + } + input_report_abs(p_sar->channels_arr[i].input, ABS_DISTANCE, -1); + input_sync(p_sar->channels_arr[i].input); + } else { + p_sar->channels_arr[i].used = AW_FALSE; + p_sar->channels_arr[i].input = NULL; + } + } + + return AW_OK; +} + +static int32_t aw_sar_input_init(struct aw_sar *p_sar) +{ + if (p_sar->p_sar_para->p_platform_config->p_input_init_fn != NULL) { + return p_sar->p_sar_para->p_platform_config->p_input_init_fn(p_sar); + } + + return aw_sar_input_init_comm(p_sar); +} + +static void aw_sar_input_free_comm(struct aw_sar *p_sar) +{ + uint8_t i = 0; + + for (i = 0; i < p_sar->p_sar_para->ch_num_max; i++) { + if (p_sar->channels_arr[i].input != NULL) { + input_unregister_device(p_sar->channels_arr[i].input); + input_free_device(p_sar->channels_arr[i].input); + } + } + AWLOGE(p_sar->dev, "aw_sar_input_free ok"); +} + +static void aw_sar_input_free(struct aw_sar *p_sar) +{ + if ((p_sar->p_sar_para->p_platform_config != NULL) && + (p_sar->p_sar_para->p_platform_config->p_input_deinit_fn != NULL)) { + p_sar->p_sar_para->p_platform_config->p_input_deinit_fn(p_sar); + AWLOGE(p_sar->dev, "AW_INVALID_PARA"); + return; + } + AWLOGE(p_sar->dev, "aw_sar_input_free_comm"); + + aw_sar_input_free_comm(p_sar); +} + +static int32_t aw_sar_check_init_over_irq_comm(struct aw_sar *p_sar) +{ + int32_t ret = 0; + + AWLOGD(p_sar->dev, "enter"); + + if (p_sar->p_sar_para->p_init_over_irq == NULL) { + return AW_INVALID_PARA; + } + + ret = aw_sar_check_init_over_irq_func(p_sar->i2c, p_sar->p_sar_para->p_init_over_irq); + if (ret == -AW_ERR_IRQ_INIT_OVER) { + AWLOGD(p_sar->dev, "ret is AW_ERR_IRQ_INIT_OVER"); + if (p_sar->p_sar_para->p_init_over_irq->p_get_err_type_fn != NULL) { + //Consider the abnormality reasonable + if (p_sar->p_sar_para->p_init_over_irq->p_get_err_type_fn(p_sar) == AW_OK) { + AWLOGD(p_sar->dev, "get_err_type return ok"); + p_sar->fw_fail_flag = AW_TRUE; + return AW_OK; + } + } + } + + return ret; +} + +//If there is no special operation on the chip, execute the common process +int32_t aw_sar_check_init_over_irq(struct aw_sar *p_sar) +{ + if (p_sar->p_sar_para->p_init_over_irq == NULL) { + return AW_INVALID_PARA; + } + + if (p_sar->p_sar_para->p_init_over_irq->p_check_init_over_irq_fn != NULL) { + return p_sar->p_sar_para->p_init_over_irq->p_check_init_over_irq_fn(p_sar); + } + + return aw_sar_check_init_over_irq_comm(p_sar); +} + +static int32_t aw_sar_chip_other_operation(struct aw_sar *p_sar) +{ + if (p_sar->p_sar_para->p_other_operation != NULL) { + return p_sar->p_sar_para->p_other_operation(p_sar); + } + + return AW_OK; +} + +static void aw_sar_chip_other_operation_free(struct aw_sar *p_sar) +{ + if (p_sar->p_sar_para->p_other_opera_free != NULL) { + p_sar->p_sar_para->p_other_opera_free(p_sar); + } +} + +int32_t aw_sar_soft_reset(struct aw_sar *p_sar) +{ + AWLOGD(p_sar->dev, "enter"); + + //If a private interface is defined, the private interface is used + if ((p_sar->p_sar_para->p_soft_rst != NULL) && + (p_sar->p_sar_para->p_soft_rst->p_soft_reset_fn != NULL)) { + return p_sar->p_sar_para->p_soft_rst->p_soft_reset_fn(p_sar); + } + + return aw_sar_soft_reset_func(p_sar->i2c, p_sar->p_sar_para->p_soft_rst); +} + +static int32_t aw_sar_check_chipid(struct aw_sar *p_sar) +{ + if (p_sar->p_sar_para == NULL) { + return AW_INVALID_PARA; + } + + if (p_sar->p_sar_para->p_check_chipid != NULL) { + if (p_sar->p_sar_para->p_check_chipid->p_check_chipid_fn != NULL) { + return p_sar->p_sar_para->p_check_chipid->p_check_chipid_fn(p_sar); + } + } + + return -AW_ERR; +} + +int32_t aw_sar_load_def_reg_bin(struct aw_sar *p_sar) +{ + AWLOGD(p_sar->dev, "enter"); + + if ((p_sar->p_sar_para->p_reg_bin == NULL) || + (p_sar->p_sar_para->p_reg_bin->bin_name == NULL)) { + AWLOGE(p_sar->dev, "p_reg_bin is NULL or bin_name is NULL error"); + p_sar->ret_val = AW_BIN_PARA_INVALID; + return AW_INVALID_PARA; + } + + snprintf(p_sar->load_bin.bin_name, sizeof(p_sar->load_bin.bin_name), + "%s_%d.bin", p_sar->p_sar_para->p_reg_bin->bin_name, p_sar->dts_info.sar_num); + + p_sar->load_bin.bin_opera_func = p_sar->p_sar_para->p_reg_bin->bin_opera_func; + + return aw_sar_load_bin_comm(p_sar); +} + +static int32_t aw_sar_para_loaded(struct aw_sar *p_sar) +{ + if (p_sar->p_sar_para->p_reg_arr == NULL) { + return AW_INVALID_PARA; + } + + aw_sar_para_loaded_func(p_sar->i2c, p_sar->p_sar_para->p_reg_arr); + + return AW_OK; +} + +static int32_t aw_sar_reg_update_boot_work(struct aw_sar *p_sar) +{ + AWLOGD(p_sar->dev, "enter"); + + if ((p_sar->p_sar_para->p_boot_bin == NULL) || (p_sar->p_sar_para->p_boot_bin->bin_name == NULL)) { + return AW_INVALID_PARA; + } + + snprintf(p_sar->load_bin.bin_name, sizeof(p_sar->load_bin.bin_name), + "%s_%d.bin", p_sar->p_sar_para->p_boot_bin->bin_name, p_sar->dts_info.sar_num); + + p_sar->load_bin.bin_opera_func = p_sar->p_sar_para->p_boot_bin->bin_opera_func; + + return aw_sar_load_bin_comm(p_sar); +} + +static int32_t aw_sar_update_fw_para(struct aw_sar *p_sar, const struct aw_sar_load_bin_t *p_bin) +{ + if ((p_bin == NULL) || (p_bin->bin_name == NULL)) { + return AW_INVALID_PARA; + } + + p_sar->load_bin.bin_opera_func = p_bin->bin_opera_func; + p_sar->load_bin.bin_load_fail_opera_func = p_bin->bin_load_fail_opera; + + snprintf(p_sar->load_bin.bin_name, sizeof(p_sar->load_bin.bin_name), + "%s_%d.bin", p_bin->bin_name, p_sar->dts_info.sar_num); + + return AW_OK; +} + +int32_t aw_sar_update_fw(struct aw_sar *p_sar) +{ + AWLOGD(p_sar->dev, "enter"); + + if (aw_sar_update_fw_para(p_sar, p_sar->p_sar_para->p_fw_bin) != AW_OK) { + return -AW_ERR; + } + + return aw_sar_load_bin_comm(p_sar); +} + +static int32_t aw_sar_node_prox_update_fw(struct aw_sar *p_sar) +{ + AWLOGD(p_sar->dev, "enter"); + + if (aw_sar_update_fw_para(p_sar, p_sar->p_sar_para->p_prox_fw) != AW_OK) { + return -AW_ERR; + } + + return aw_sar_load_bin_comm(p_sar); +} + +static int32_t aw_sar_node_reg_update_fw(struct aw_sar *p_sar) +{ + AWLOGD(p_sar->dev, "enter"); + + if (aw_sar_update_fw_para(p_sar, p_sar->p_sar_para->p_reg_fw)) { + return -AW_ERR; + } + + return aw_sar_load_bin_comm(p_sar); +} + +static int32_t aw_sar_awrw_data_analysis(struct aw_sar *p_sar, + const char *buf, uint8_t len) +{ + uint32_t i = 0 ; + uint8_t data_temp[2] = { 0 }; + uint8_t index = 0; + uint32_t tranfar_data_temp = 0; + uint32_t theory_len = len * AW_SAR_AWRW_DATA_WIDTH + AW_SAR_AWRW_OffSET; + uint32_t actual_len = strlen(buf); + + AWLOGD(p_sar->dev, "enter"); + + if (theory_len != actual_len) { + AWLOGD(p_sar->dev, + "error theory_len = %d actual_len = %d", + theory_len, actual_len); + return -AW_ERR; + } + + for (i = 0; i < len * AW_SAR_AWRW_DATA_WIDTH; + i += AW_SAR_AWRW_DATA_WIDTH) { + data_temp[0] = buf[AW_SAR_AWRW_OffSET + i + AW_DATA_OffSET_2]; + data_temp[1] = buf[AW_SAR_AWRW_OffSET + i + AW_DATA_OffSET_3]; + + if (sscanf(data_temp, "%02x", &tranfar_data_temp) == 1) { + p_sar->awrw_info.p_i2c_tranfar_data[index] = + (uint8_t)tranfar_data_temp; + AWLOGD(p_sar->dev, "tranfar_data = 0x%2x", + p_sar->awrw_info.p_i2c_tranfar_data[index]); + } + index++; + } + + return 0; +} + +static int32_t aw_sar_awrw_write(struct aw_sar *p_sar, const char *buf) +{ + int32_t ret = 0; + + ret = aw_sar_awrw_data_analysis(p_sar, buf, + p_sar->awrw_info.i2c_tranfar_data_len); + if (ret == 0) { + aw_sar_i2c_write_seq(p_sar->i2c, p_sar->awrw_info.p_i2c_tranfar_data, + p_sar->awrw_info.i2c_tranfar_data_len); + } + + return ret; +} + +static int32_t aw_sar_awrw_read(struct aw_sar *p_sar, const char *buf) +{ + int32_t ret = 0; + uint8_t *p_buf = p_sar->awrw_info.p_i2c_tranfar_data + p_sar->awrw_info.addr_len; + uint32_t len = (uint16_t)(p_sar->awrw_info.data_len * p_sar->awrw_info.reg_num); + + ret = aw_sar_awrw_data_analysis(p_sar, buf, p_sar->awrw_info.addr_len); + if (ret == 0) { + ret = aw_sar_i2c_read_seq(p_sar->i2c, + p_sar->awrw_info.p_i2c_tranfar_data, + p_sar->awrw_info.addr_len, + p_sar->awrw_info.p_i2c_tranfar_data + p_sar->awrw_info.addr_len, + (uint16_t)(p_sar->awrw_info.data_len * p_sar->awrw_info.reg_num)); + if (ret != AW_OK) { + memset(p_buf, 0xff, len); + } + } + + return ret; +} + +static int32_t aw_sar_awrw_get_func(struct aw_sar *p_sar, char *buf) +{ + uint32_t len = 0; + uint i = 0; + + if (p_sar->awrw_info.p_i2c_tranfar_data == NULL) { + AWLOGE(p_sar->dev, "p_i2c_tranfar_data is NULL"); + return len; + } + + if (p_sar->awrw_info.rw_flag == AW_SAR_PACKAGE_RD) { + for (i = 0; i < p_sar->awrw_info.i2c_tranfar_data_len; i++) { + len += snprintf(buf + len, PAGE_SIZE - len, + "0x%02x,", + p_sar->awrw_info.p_i2c_tranfar_data[i]); + } + } else { + for (i = 0; i < (p_sar->awrw_info.data_len) * + (p_sar->awrw_info.reg_num); i++) { + len += snprintf(buf + len, PAGE_SIZE - len, + "0x%02x,", + p_sar->awrw_info.p_i2c_tranfar_data[p_sar->awrw_info.addr_len + i]); + } + } + snprintf(buf + len - 1, PAGE_SIZE - len, "\n"); + + devm_kfree(p_sar->dev, p_sar->awrw_info.p_i2c_tranfar_data); + p_sar->awrw_info.p_i2c_tranfar_data = NULL; + + return len; +} + +//Function: continuous read register interface +static ssize_t aw_sar_awrw_get(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct aw_sar *p_sar = dev_get_drvdata(dev); + ssize_t ret = 0; + + mutex_lock(&aw_sar_lock); + if ((p_sar->p_sar_para->p_aw_sar_awrw != NULL) && + (p_sar->p_sar_para->p_aw_sar_awrw->p_get_awrw_node_fn != NULL)) { + ret = (ssize_t)p_sar->p_sar_para->p_aw_sar_awrw->p_get_awrw_node_fn(p_sar, buf); + mutex_unlock(&aw_sar_lock); + return ret; + } + + ret = (ssize_t)aw_sar_awrw_get_func(p_sar, buf); + + mutex_unlock(&aw_sar_lock); + + return ret; +} + +static int32_t aw_sar_awrw_handle(struct aw_sar *p_sar, const char *buf) +{ + int32_t ret = 0; + + p_sar->awrw_info.i2c_tranfar_data_len = + p_sar->awrw_info.addr_len + + p_sar->awrw_info.data_len * + p_sar->awrw_info.reg_num; + if (p_sar->awrw_info.p_i2c_tranfar_data != NULL) { + devm_kfree(p_sar->dev, p_sar->awrw_info.p_i2c_tranfar_data); + p_sar->awrw_info.p_i2c_tranfar_data = NULL; + } + + p_sar->awrw_info.p_i2c_tranfar_data = + devm_kzalloc(p_sar->dev, + p_sar->awrw_info.i2c_tranfar_data_len, GFP_KERNEL); + if (p_sar->awrw_info.p_i2c_tranfar_data == NULL) { + AWLOGE(p_sar->dev, "devm_kzalloc error"); + return -AW_ERR; + } + + if (p_sar->awrw_info.rw_flag == AW_SAR_I2C_WR) { + ret = aw_sar_awrw_write(p_sar, buf); + if (ret != 0) + AWLOGE(p_sar->dev, "awrw_write error"); + if (p_sar->awrw_info.p_i2c_tranfar_data != NULL) { + devm_kfree(p_sar->dev, + p_sar->awrw_info.p_i2c_tranfar_data); + p_sar->awrw_info.p_i2c_tranfar_data = NULL; + } + } else if (p_sar->awrw_info.rw_flag == AW_SAR_I2C_RD) { + ret = aw_sar_awrw_read(p_sar, buf); + if (ret != 0) + AWLOGE(p_sar->dev, "awrw_read error"); + } else { + return -AW_ERR; + } + + return AW_OK; +} + +static int32_t aw_sar_awrw_set_func(struct aw_sar *p_sar, const char *buf) +{ + uint32_t rw_flag = 0; + uint32_t addr_bytes = 0; + uint32_t data_bytes = 0; + uint32_t package_nums = 0; + uint32_t reg_num = 0; + uint32_t i = 0; + uint32_t j = 0; + uint32_t addr_tmp = 0; + uint32_t buf_index0 = 0; + uint32_t buf_index1 = 0; + uint32_t r_buf_len = 0; + uint32_t tr_offset = 0; + uint8_t addr[4] = { 0 }; + uint32_t theory_len = 0; + uint32_t actual_len = 0; + + //step1: Parse frame header + if (sscanf(buf, "0x%02x 0x%02x 0x%02x ", &rw_flag, &addr_bytes, &data_bytes) != 3) { + AWLOGE(p_sar->dev, "sscanf0 parse error!"); + return -AW_ERR; + } + p_sar->awrw_info.rw_flag = (uint8_t)rw_flag; + p_sar->awrw_info.addr_len = (uint8_t)addr_bytes; + p_sar->awrw_info.data_len = (uint8_t)data_bytes; + + if (addr_bytes > 4) { + return -AW_ERR; + AWLOGE(p_sar->dev, "para error!"); + } + + if ((rw_flag == AW_SAR_I2C_WR) || (rw_flag == AW_SAR_I2C_RD)) { + if (sscanf(buf + AW_SAR_OFFSET_LEN, "0x%02x ", ®_num) != 1) { + AWLOGE(p_sar->dev, "sscanf1 parse error!"); + return -AW_ERR; + } + p_sar->awrw_info.reg_num = (uint8_t)reg_num; + aw_sar_awrw_handle(p_sar, buf); + } else if (rw_flag == AW_SAR_PACKAGE_RD){ + //step2: Get number of packages + if (sscanf(buf + AW_SAR_OFFSET_LEN, "0x%02x ", &package_nums) != 1) { + AWLOGE(p_sar->dev, "sscanf2 parse error!"); + return -AW_ERR; + } + theory_len = AW_SAR_OFFSET_LEN + AW_SAR_AWRW_DATA_WIDTH + + package_nums * (AW_SAR_AWRW_DATA_WIDTH + AW_SAR_AWRW_DATA_WIDTH * addr_bytes); + actual_len = strlen(buf); + // AWLOGD(p_sar->dev, "theory_len:%d, actual_len:%d", theory_len, actual_len); + if (theory_len != actual_len) { + + AWLOGE(p_sar->dev, "theory_len:%d, actual_len:%d error!", theory_len, actual_len); + return -AW_ERR; + } + + //step3: Get the size of read data and apply for space + // AWLOGE(p_sar->dev, "package_nums:%d", package_nums); + for (i = 0; i < package_nums; i++) { + buf_index0 = AW_SAR_OFFSET_LEN + AW_SAR_AWRW_DATA_WIDTH + + (AW_SAR_AWRW_DATA_WIDTH * addr_bytes + AW_SAR_AWRW_DATA_WIDTH) * i; + if (sscanf(buf + buf_index0, "0x%02x", ®_num) != 1) { + AWLOGE(p_sar->dev, "sscanf3 parse error!"); + return -AW_ERR; + } + //AWLOGE(p_sar->dev, "reg_num:%d", reg_num); + r_buf_len += reg_num * data_bytes; + } + + // AWLOGD(p_sar->dev, "r_buf_len:%d", r_buf_len); + p_sar->awrw_info.i2c_tranfar_data_len = r_buf_len; + + if (p_sar->awrw_info.p_i2c_tranfar_data != NULL) { + devm_kfree(p_sar->dev, p_sar->awrw_info.p_i2c_tranfar_data); + p_sar->awrw_info.p_i2c_tranfar_data = NULL; + } + p_sar->awrw_info.p_i2c_tranfar_data = devm_kzalloc(p_sar->dev, + r_buf_len, GFP_KERNEL); + if (p_sar->awrw_info.p_i2c_tranfar_data == NULL) { + AWLOGE(p_sar->dev, "devm_kzalloc error"); + return -AW_ERR; + } + + //step3: Resolve register address and read data in packets + for (i = 0; i < package_nums; i++) { + buf_index0 = AW_SAR_OFFSET_LEN + AW_SAR_AWRW_DATA_WIDTH + + (AW_SAR_AWRW_DATA_WIDTH * addr_bytes + AW_SAR_AWRW_DATA_WIDTH) * i; + if (sscanf(buf + buf_index0, "0x%02x", ®_num) != 1) { + AWLOGE(p_sar->dev, "sscanf4 parse error!"); + return -AW_ERR; + } + + for (j = 0; j < addr_bytes; j += 1) { + buf_index1 = buf_index0 + AW_SAR_AWRW_DATA_WIDTH + (j * AW_SAR_AWRW_DATA_WIDTH); + // AWLOGD(p_sar->dev, "buf_index1 = %d", buf_index1); + if (sscanf(buf + buf_index1, "0x%02x", &addr_tmp) == 1) { + addr[j] = (uint8_t)addr_tmp; + //AWLOGD(p_sar->dev, "tranfar_data = 0x%2x", addr[j]); + } else { + AWLOGE(p_sar->dev, "sscanf5 parse error!"); + return -AW_ERR; + } + } + // AWLOGD(p_sar->dev, "tr_offset = %d", tr_offset); + aw_sar_i2c_read_seq(p_sar->i2c, + addr, + addr_bytes, + p_sar->awrw_info.p_i2c_tranfar_data + tr_offset, + (uint16_t)(data_bytes * reg_num)); + tr_offset += data_bytes * reg_num; + } + } + + return AW_OK; +} + +//Function: continuous write register interface +static ssize_t aw_sar_awrw_set(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct aw_sar *p_sar = dev_get_drvdata(dev); + + mutex_lock(&aw_sar_lock); + + if ((p_sar->p_sar_para->p_aw_sar_awrw != NULL) && + (p_sar->p_sar_para->p_aw_sar_awrw->p_set_awrw_node_fn != NULL)) { + p_sar->p_sar_para->p_aw_sar_awrw->p_set_awrw_node_fn (p_sar, buf, count); + mutex_unlock(&aw_sar_lock); + return count; + } + + aw_sar_awrw_set_func(p_sar, buf); + + mutex_unlock(&aw_sar_lock); + + return count; +} +//Print all readable register values +static ssize_t aw_sar_reg_get(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct aw_sar *p_sar = dev_get_drvdata(dev); + ssize_t len = 0; + uint16_t i = 0; + uint32_t reg_data = 0; + int32_t ret = 0; + uint8_t reg_rd_access = 0; + + if (p_sar->p_sar_para->p_reg_list == NULL) { + return len; + } + + reg_rd_access = p_sar->p_sar_para->p_reg_list->reg_rd_access; + + for (i = 0; i < p_sar->p_sar_para->p_reg_list->reg_num; i++) { + if (p_sar->p_sar_para->p_reg_list->reg_perm[i].rw & reg_rd_access) { + ret = aw_sar_i2c_read(p_sar->i2c, p_sar->p_sar_para->p_reg_list->reg_perm[i].reg, ®_data); + if (ret < 0) { + len += snprintf(buf + len, PAGE_SIZE - len, + "i2c read error ret = %d\n", ret); + } + len+= snprintf(buf + len, PAGE_SIZE - len, + "%x,%x\n", + p_sar->p_sar_para->p_reg_list->reg_perm[i].reg, + reg_data); + } + } + AWLOGD(p_sar->dev, "len %d", (int)len); + + return len; +} + +//Write register interface with write permission +static ssize_t aw_sar_reg_set(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + uint16_t i = 0; + struct aw_sar *p_sar = dev_get_drvdata(dev); + uint32_t databuf[2] = { 0, 0 }; + uint8_t reg_wd_access = 0; + + if (p_sar->p_sar_para->p_reg_list == NULL) { + AWLOGE(p_sar->dev, "AW_INVALID_PARA"); + return count; + } + + reg_wd_access = p_sar->p_sar_para->p_reg_list->reg_wd_access; + + if (sscanf(buf, "%x %x", &databuf[0], &databuf[1]) != 2) + return count; + + for (i = 0; i < p_sar->p_sar_para->p_reg_list->reg_num; i++) { + if ((uint16_t)databuf[0] == p_sar->p_sar_para->p_reg_list->reg_perm[i].reg) { + if (p_sar->p_sar_para->p_reg_list->reg_perm[i].rw & reg_wd_access) { + aw_sar_i2c_write(p_sar->i2c, + (uint16_t)databuf[0], (uint32_t)databuf[1]); + } + break; + } + } + + return count; +} + +//set chip Soft reset +static ssize_t aw_sar_soft_rst_set(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + uint32_t flag = 0; + struct aw_sar *p_sar = dev_get_drvdata(dev); + + if (sscanf(buf, "%d", &flag) != 1) { + AWLOGE(p_sar->dev, "sscanf parse err"); + return count; + } + + if (flag == AW_TRUE) { + aw_sar_soft_reset(p_sar); + } + + return count; +} + +static int32_t aw_sar_aot(struct aw_sar *p_sar) +{ + if (p_sar->p_sar_para->p_aot == NULL) { + return AW_INVALID_PARA; + } + + if (p_sar->p_sar_para->p_aot->p_set_aot_node_fn != NULL) { + return p_sar->p_sar_para->p_aot->p_set_aot_node_fn(p_sar); + } + + return aw_sar_i2c_write_bits(p_sar->i2c, p_sar->p_sar_para->p_aot->aot_reg, + p_sar->p_sar_para->p_aot->aot_mask, p_sar->p_sar_para->p_aot->aot_flag); +} + +//Perform Auto-Offset-Tuning (AOT) +static ssize_t aw_sar_aot_set(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct aw_sar *p_sar = dev_get_drvdata(dev); + uint32_t cali_flag = 0; + + if (sscanf(buf, "%d", &cali_flag) != 1) + return count; + + if (cali_flag == AW_TRUE) { + aw_sar_aot(p_sar); + } else { + AWLOGE(p_sar->dev, "fail to set aot cali"); + } + + return count; +} + +//update Register configuration and set the chip active mode +int32_t aw_sar_update_reg_set_func(struct aw_sar *p_sar) +{ + AWLOGD(p_sar->dev, "enter"); + + aw_sar_load_def_reg_bin(p_sar); + aw_sar_mode_set(p_sar, p_sar->p_sar_para->p_chip_mode->active); + + return AW_OK; +} + +//Update register configuration +static ssize_t aw_sar_update_reg_set(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + uint32_t flag = 0; + struct aw_sar *p_sar = dev_get_drvdata(dev); + + if (sscanf(buf, "%d", &flag) != 1) { + AWLOGE(p_sar->dev, "sscanf parse error"); + return count; + } + + if (flag == AW_TRUE) { + mutex_lock(&aw_sar_lock); + aw_sar_soft_reset(p_sar); + aw_sar_update_reg_set_func(p_sar); + mutex_unlock(&aw_sar_lock); + } + + return count; +} + +//get chip diff val +static ssize_t aw_sar_get_diff(struct aw_sar *p_sar, char *buf) +{ + uint32_t i = 0; + int32_t ret = 0; + ssize_t len = 0; + uint32_t data = 0; + int32_t diff_val = 0; + const struct aw_sar_diff_t *diff = p_sar->p_sar_para->p_diff; + + if (p_sar->p_sar_para->p_diff == NULL) { + return AW_INVALID_PARA; + } + + //If a private interface is defined, the private interface is used + if (p_sar->p_sar_para->p_diff->p_get_diff_node_fn != NULL) { + return p_sar->p_sar_para->p_diff->p_get_diff_node_fn(p_sar, buf); + } + + for (i = 0; i < p_sar->p_sar_para->ch_num_max; i++) { + ret = aw_sar_i2c_read(p_sar->i2c, diff->diff0_reg + i * diff->diff_step, &data); + if (ret != AW_OK) { + AWLOGE(p_sar->dev, "read diff err: %d", ret); + return -AW_ERR; + } + diff_val = (int32_t)data / (int32_t)diff->rm_float; + len += snprintf(buf + len, PAGE_SIZE - len, "DIFF_CH%d = %d\n", i, diff_val); + } + + return len; +} + + +//Print diff values of all channels of the chip. +static ssize_t aw_sar_diff_get(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct aw_sar *p_sar = dev_get_drvdata(dev); + + return aw_sar_get_diff(p_sar, buf); +} + +void aw_sar_mode_set(struct aw_sar *p_sar, uint8_t curr_mode) +{ + struct aw_sar_mode_set_t mode_set_para; + + if (p_sar->p_sar_para->p_mode == NULL) { + return; + } + + //If a private interface is defined, the private interface is used + if (p_sar->p_sar_para->p_mode->p_set_mode_node_fn != NULL) { + p_sar->p_sar_para->p_mode->p_set_mode_node_fn(p_sar, curr_mode); + return; + } + + mode_set_para.chip_id = p_sar->chip_type; + mode_set_para.chip_mode.curr_mode = curr_mode; + mode_set_para.chip_mode.last_mode = p_sar->last_mode; + + aw_sar_mode_set_func(p_sar->i2c, p_sar->irq_init.to_irq, &mode_set_para, + p_sar->p_sar_para->p_mode->mode_set_arr, p_sar->p_sar_para->p_mode->mode_set_arr_len); + p_sar->last_mode = curr_mode; +} + +//Set the chip to enter different modes +static ssize_t aw_sar_mode_operation_set(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct aw_sar *p_sar = dev_get_drvdata(dev); + uint32_t mode = 0; + + if (sscanf(buf, "%d", &mode) != 1) { + AWLOGE(p_sar->dev, "sscanf parse err"); + return count; + } + aw_sar_mode_set(p_sar, mode); + + return count; +} + +//Get the current mode of the chip +static ssize_t aw_sar_mode_operation_get(struct device *dev, + struct device_attribute *attr, char *buf) +{ + ssize_t len = 0; + struct aw_sar *p_sar = dev_get_drvdata(dev); + + if (p_sar->p_sar_para->p_mode == NULL) { + return len; + } + + if (p_sar->p_sar_para->p_mode->p_get_mode_node_fn != NULL) { + len = p_sar->p_sar_para->p_mode->p_get_mode_node_fn(p_sar, buf); + } + + return len; +} + +//Print information related information +static ssize_t aw_sar_chip_info_get(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct aw_sar *p_sar = dev_get_drvdata(dev); + ssize_t len = 0; + + len += snprintf(buf + len, PAGE_SIZE - len, "driver version: %s\n", AW_SAR_DRIVER_VERSION); + len += snprintf(buf + len, PAGE_SIZE - len, "reg_load_state: %d\n", p_sar->ret_val); + + if ((p_sar->p_sar_para->p_get_chip_info != NULL) && + (p_sar->p_sar_para->p_get_chip_info->p_get_chip_info_node_fn != NULL)) { + p_sar->p_sar_para->p_get_chip_info->p_get_chip_info_node_fn(p_sar, buf, &len); + } + + return len; +} + +static ssize_t aw_sar_offset_get(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct aw_sar *p_sar = dev_get_drvdata(dev); + ssize_t len = 0; + + if ((p_sar->p_sar_para->p_offset != NULL) && + (p_sar->p_sar_para->p_offset->p_get_offset_node_fn != NULL)) { + len = (ssize_t)p_sar->p_sar_para->p_offset->p_get_offset_node_fn(p_sar, buf); + } + + return len; +} + +static DEVICE_ATTR(awrw, 0664, aw_sar_awrw_get, aw_sar_awrw_set); +static DEVICE_ATTR(reg, 0664, aw_sar_reg_get, aw_sar_reg_set); +static DEVICE_ATTR(soft_rst, 0664, NULL, aw_sar_soft_rst_set); +static DEVICE_ATTR(aot, 0664, NULL, aw_sar_aot_set); +static DEVICE_ATTR(update_reg, 0664, NULL, aw_sar_update_reg_set); +static DEVICE_ATTR(diff, 0664, aw_sar_diff_get, NULL); +static DEVICE_ATTR(mode_operation, 0664, aw_sar_mode_operation_get, aw_sar_mode_operation_set); +static DEVICE_ATTR(chip_info, 0664, aw_sar_chip_info_get, NULL); +static DEVICE_ATTR(offset, 0664, aw_sar_offset_get, NULL); + +static struct attribute *aw_sar_attributes[] = { + &dev_attr_awrw.attr, + &dev_attr_reg.attr, + &dev_attr_soft_rst.attr, + &dev_attr_aot.attr, + &dev_attr_update_reg.attr, + &dev_attr_diff.attr, + &dev_attr_mode_operation.attr, + &dev_attr_chip_info.attr, + &dev_attr_offset.attr, + NULL +}; + +const static struct attribute_group aw_sar_attribute_group = { + .attrs = aw_sar_attributes, +}; + +//firmware upgrade through write register mode, and the operation is supported by flash chip +static ssize_t aw_sar_prot_update_fw_set(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct aw_sar *p_sar = dev_get_drvdata(dev); + + + mutex_lock(&aw_sar_lock); + aw_sar_disable_irq(p_sar); + + AWLOGD(p_sar->dev, "enter"); + p_sar->prot_update_state = aw_sar_node_prox_update_fw(p_sar); + + aw_sar_enable_irq(p_sar); + mutex_unlock(&aw_sar_lock); + + return count; +} + +//firmware upgrade throughr Write register mode,and the operation is supported by flash chip +static ssize_t aw_sar_reg_update_fw_set(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct aw_sar *p_sar = dev_get_drvdata(dev); + + mutex_lock(&aw_sar_lock); + aw_sar_disable_irq(p_sar); + + AWLOGD(p_sar->dev, "enter"); + aw_sar_node_reg_update_fw(p_sar); + + aw_sar_enable_irq(p_sar); + mutex_unlock(&aw_sar_lock); + + return count; +} + +//boot upgrade throughr Write register mode,and the operation is supported by flash chip +static ssize_t aw_sar_reg_update_boot_set(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct aw_sar *p_sar = dev_get_drvdata(dev); + + if (p_sar->p_sar_para->p_boot_bin == NULL) { + return count; + } + + mutex_lock(&aw_sar_lock); + aw_sar_disable_irq(p_sar); + + AWLOGD(p_sar->dev, "enter"); + + aw_sar_reg_update_boot_work(p_sar); + + aw_sar_enable_irq(p_sar); + mutex_unlock(&aw_sar_lock); + + return count; +} + +//Print the protocol upgrade status. 0 is success, Not 0 is failure +//Print the current firmware version number +static ssize_t aw_sar_prot_update_fw_get(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct aw_sar *p_sar = dev_get_drvdata(dev); + ssize_t len = 0; + + len += snprintf(buf + len, PAGE_SIZE - len, + "protocol update state:%s!\n", + (p_sar->prot_update_state == 0) ? "ok" : "error"); + if ((p_sar->p_sar_para->p_prox_fw != NULL) && + (p_sar->p_sar_para->p_prox_fw->p_get_prot_update_fw_node_fn != NULL)) { + p_sar->p_sar_para->p_prox_fw->p_get_prot_update_fw_node_fn(p_sar, buf, &len); + } + + return len; +} + +static DEVICE_ATTR(prot_update_fw, 0664, aw_sar_prot_update_fw_get, aw_sar_prot_update_fw_set); +static DEVICE_ATTR(reg_update_fw, 0664, NULL, aw_sar_reg_update_fw_set); +static DEVICE_ATTR(reg_update_boot, 0664, NULL, aw_sar_reg_update_boot_set); + +static struct attribute *aw_sar_update_attributes[] = { + &dev_attr_prot_update_fw.attr, + &dev_attr_reg_update_fw.attr, + &dev_attr_reg_update_boot.attr, + NULL +}; + +const static struct attribute_group aw_sar_update_attribute_group = { + .attrs = aw_sar_update_attributes, +}; + +static void aw_sar_update_work(struct work_struct *work) +{ + int32_t ret = 0; + struct aw_sar *p_sar = container_of(work, struct aw_sar, update_work.work); + + mutex_lock(&aw_sar_lock); + + if (p_sar->dts_info.update_fw_flag == true) { + AWLOGI(p_sar->dev, "firmware upgrade start!"); + ret = aw_sar_update_fw(p_sar); + if (ret != AW_OK) { + AWLOGE(p_sar->dev, "protocol upgrade firmware error!"); + p_sar->ret_val = AW_PROT_UPDATE_ERR; + } else { + AWLOGI(p_sar->dev, "protocol upgrade firmware ok!"); + } + } + + //2.Parse the bin file and load the register configuration + ret = aw_sar_load_def_reg_bin(p_sar); + if (ret != AW_OK) { + p_sar->ret_val = AW_REG_LOAD_ERR; + AWLOGE(p_sar->dev, "reg_bin load err!"); + aw_sar_para_loaded(p_sar); + } + + //3.active chip + aw_sar_mode_set(p_sar, p_sar->p_sar_para->p_chip_mode->init_mode); + if (p_sar->irq_init.host_irq_stat == IRQ_DISABLE) { + enable_irq(p_sar->irq_init.to_irq); + p_sar->irq_init.host_irq_stat = IRQ_ENABLE; + } + + mutex_unlock(&aw_sar_lock); + + return; +} + +static void aw_sar_update(struct aw_sar *p_sar) +{ + AWLOGD(p_sar->dev, "enter"); + + if (p_sar->p_sar_para->p_reg_bin == NULL) { + return; + } + + if (p_sar->p_sar_para->p_reg_bin->p_update_fn != NULL) { + p_sar->p_sar_para->p_reg_bin->p_update_fn(p_sar); + } + + INIT_DELAYED_WORK(&p_sar->update_work, aw_sar_update_work); + schedule_delayed_work(&p_sar->update_work, + msecs_to_jiffies(AW_POWER_ON_SYSFS_DELAY_MS)); +} + +static int32_t aw_sar_create_node(struct aw_sar *p_sar) +{ + int32_t ret = 0; + + AWLOGD(p_sar->dev, "enter"); + + i2c_set_clientdata(p_sar->i2c, p_sar); + + ret = sysfs_create_group(&p_sar->i2c->dev.kobj, &aw_sar_attribute_group); + + if (p_sar->dts_info.update_fw_flag == true) { + ret |= sysfs_create_group(&p_sar->i2c->dev.kobj, &aw_sar_update_attribute_group); + } + + //Special requirements of SAR chip + if (p_sar->p_sar_para->p_platform_config->p_add_node_create_fn != NULL) { + ret |= p_sar->p_sar_para->p_platform_config->p_add_node_create_fn(p_sar); + } + + return ret; +} + +static void aw_sar_node_free(struct aw_sar *p_sar) +{ + sysfs_remove_group(&p_sar->i2c->dev.kobj, &aw_sar_attribute_group); + + if (p_sar->dts_info.update_fw_flag == true) { + sysfs_remove_group(&p_sar->i2c->dev.kobj, &aw_sar_update_attribute_group); + } + //Special requirements of SAR chip + if ((p_sar->p_sar_para->p_platform_config != NULL) && + (p_sar->p_sar_para->p_platform_config->p_add_node_free_fn != NULL)) { + p_sar->p_sar_para->p_platform_config->p_add_node_free_fn(p_sar); + } +} + +//The interrupt pin is set to internal pull-up start +void aw_sar_int_output(struct aw_sar *p_sar, int32_t level) +{ + pr_info("%s enter aw_sar int level:%d\n", __func__, level); + if (level == 0) { + if (p_sar->pinctrl.pinctrl) { + pinctrl_select_state(p_sar->pinctrl.pinctrl, + p_sar->pinctrl.int_out_low); + } else { + pr_info("%s Failed set int pin output low\n", __func__); + } + } else if (level == 1) { + if (p_sar->pinctrl.pinctrl) { + pinctrl_select_state(p_sar->pinctrl.pinctrl, + p_sar->pinctrl.int_out_high); + } else { + pr_info("%s Failed set int pin output high\n", __func__); + } + } +} + +static int32_t aw_sar_pinctrl_init(struct aw_sar *p_sar) +{ + struct aw_sar_pinctrl *pinctrl = &p_sar->pinctrl; + uint8_t pin_default_name[50] = { 0 }; + uint8_t pin_output_low_name[50] = { 0 }; + uint8_t pin_output_high_name[50] = { 0 }; + + AWLOGD(p_sar->dev, "enter"); + + pinctrl->pinctrl = devm_pinctrl_get(p_sar->dev); + if (IS_ERR_OR_NULL(pinctrl->pinctrl)) { + pr_info("%s:No pinctrl found\n", __func__); + pinctrl->pinctrl = NULL; + return -EINVAL; + } + + snprintf(pin_default_name, sizeof(pin_default_name), + "aw_default_sar%d", p_sar->dts_info.sar_num); + AWLOGD(p_sar->dev, "pin_default_name = %s", pin_default_name); + pinctrl->default_sta = pinctrl_lookup_state(pinctrl->pinctrl, + pin_default_name); + if (IS_ERR_OR_NULL(pinctrl->default_sta)) { + AWLOGE(p_sar->dev, "Failed get pinctrl state:default state"); + goto exit_pinctrl_init; + } + + snprintf(pin_output_high_name, sizeof(pin_output_high_name), + "aw_int_output_high_sar%d", p_sar->dts_info.sar_num); + AWLOGD(p_sar->dev, "pin_output_high_name = %s", pin_output_high_name); + pinctrl->int_out_high = pinctrl_lookup_state(pinctrl->pinctrl, + pin_output_high_name); + if (IS_ERR_OR_NULL(pinctrl->int_out_high)) { + AWLOGE(p_sar->dev, "Failed get pinctrl state:output_high"); + goto exit_pinctrl_init; + } + + snprintf(pin_output_low_name, sizeof(pin_output_low_name), + "aw_int_output_low_sar%d", p_sar->dts_info.sar_num); + AWLOGD(p_sar->dev, "pin_output_low_name = %s", pin_output_low_name); + pinctrl->int_out_low = pinctrl_lookup_state(pinctrl->pinctrl, + pin_output_low_name); + if (IS_ERR_OR_NULL(pinctrl->int_out_low)) { + AWLOGE(p_sar->dev, "Failed get pinctrl state:output_low"); + goto exit_pinctrl_init; + } + + AWLOGD(p_sar->dev, "Success init pinctrl"); + + return 0; + +exit_pinctrl_init: + devm_pinctrl_put(pinctrl->pinctrl); + pinctrl->pinctrl = NULL; + + return -EINVAL; +} + +static void aw_sar_pinctrl_deinit(struct aw_sar *p_sar) +{ + if (p_sar->pinctrl.pinctrl) { + devm_pinctrl_put(p_sar->pinctrl.pinctrl); + } +} +//The interrupt pin is set to internal pull-up end + +//AW_SAR_REGULATOR_POWER_ON start +static int32_t aw_sar_regulator_power_init(struct aw_sar *p_sar) +{ + int32_t rc = 0; + uint8_t vcc_name[20] = { 0 }; + + AWLOGD(p_sar->dev, "aw_sar power init enter"); + + if (p_sar->p_sar_para->p_platform_config->p_regulator_config == NULL) { + return AW_INVALID_PARA; + } + + snprintf(vcc_name, sizeof(vcc_name), "%s%d", + p_sar->p_sar_para->p_platform_config->p_regulator_config->vcc_name, + p_sar->dts_info.sar_num); + AWLOGD(p_sar->dev, "vcc_name = %s", vcc_name); + + p_sar->vcc = regulator_get(p_sar->dev, vcc_name); + if (IS_ERR(p_sar->vcc)) { + rc = PTR_ERR(p_sar->vcc); + AWLOGE(p_sar->dev, "regulator get failed vcc rc = %d", rc); + return rc; + } + + if (regulator_count_voltages(p_sar->vcc) > 0) { + rc = regulator_set_voltage(p_sar->vcc, + p_sar->p_sar_para->p_platform_config->p_regulator_config->min_uV, + p_sar->p_sar_para->p_platform_config->p_regulator_config->max_uV); + if (rc) { + AWLOGE(p_sar->dev, + "regulator set vol failed rc = %d", rc); + goto reg_vcc_put; + } + } + + return rc; + +reg_vcc_put: + regulator_put(p_sar->vcc); + return rc; +} + +static void aw_sar_power_deinit(struct aw_sar *p_sar) +{ + if (p_sar->power_enable) { + //Turn off the power output. However, + //it may not be turned off immediately + //There are scenes where power sharing can exist + regulator_disable(p_sar->vcc); + regulator_put(p_sar->vcc); + } +} + +static void aw_sar_power_enable(struct aw_sar *p_sar, bool on) +{ + int32_t rc = 0; + + AWLOGD(p_sar->dev, "aw_sar power enable enter"); + + if (on) { + rc = regulator_enable(p_sar->vcc); + if (rc) { + AWLOGE(p_sar->dev, + "regulator_enable vol failed rc = %d", rc); + } else { + p_sar->power_enable = AW_TRUE; + msleep(20); + } + } else { + rc = regulator_disable(p_sar->vcc); + if (rc) { + AWLOGE(p_sar->dev, + "regulator_disable vol failed rc = %d", rc); + } else { + p_sar->power_enable = AW_FALSE; + } + } +} + +static int32_t regulator_is_get_voltage(struct aw_sar *p_sar) +{ + uint32_t cnt = 10; + int32_t voltage_val = 0; + + AWLOGD(p_sar->dev, "enter"); + + while(cnt--) { + voltage_val = regulator_get_voltage(p_sar->vcc); + AWLOGD(p_sar->dev, "aw_sar voltage is : %d uv", voltage_val); + if (voltage_val >= p_sar->p_sar_para->p_platform_config->p_regulator_config->min_uV) { + return AW_OK; + } + mdelay(1); + } + //Ensure that the chip initialization is completed + msleep(20); + + return -AW_VERS_ERR; +} +//AW_SAR_REGULATOR_POWER_ON end + +static void aw_sar_init_lock(struct aw_sar *p_sar) +{ + //Initialize lock, To protect the thread safety of updating bin file + mutex_init(&aw_sar_lock); + //Required for mode setting + p_sar->last_mode = p_sar->p_sar_para->p_chip_mode->pre_init_mode; + p_sar->fw_fail_flag = AW_FALSE; + p_sar->ret_val = AW_OK; +} + +// AW_SAR_USB_PLUG_CAIL start +static void aw_sar_ps_notify_callback_work(struct work_struct *work) +{ + struct aw_sar *p_sar = container_of(work, struct aw_sar, ps_notify_work); + + AWLOGD(p_sar->dev, "enter"); + + aw_sar_aot(p_sar); +} + +static int aw_sar_ps_get_state(struct aw_sar *p_sar, struct power_supply *psy, bool *present) +{ + union power_supply_propval pval = { 0 }; + int retval; + +#ifdef CONFIG_USE_POWER_SUPPLY_ONLINE + retval = power_supply_get_property(psy, POWER_SUPPLY_PROP_ONLINE, &pval); +#else + retval = power_supply_get_property(psy, POWER_SUPPLY_PROP_PRESENT, &pval); +#endif + if (retval) { + AWLOGE(p_sar->dev, "%s psy get property failed", psy->desc->name); + return retval; + } + *present = (pval.intval) ? true : false; +#ifdef CONFIG_USE_POWER_SUPPLY_ONLINE + AWLOGI(p_sar->dev, "%s is %s", psy->desc->name, + (*present) ? "online" : "not online"); +#else + AWLOGI(p_sar->dev, "%s is %s", psy->desc->name, + (*present) ? "present" : "not present"); +#endif + return 0; +} + +static int aw_sar_ps_notify_callback(struct notifier_block *self, + unsigned long event, void *p) +{ + struct aw_sar *p_sar = container_of(self, struct aw_sar, ps_notif); + struct power_supply *psy = p; + bool present; + int retval; + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,9,0) + if (event == PSY_EVENT_PROP_CHANGED +#else + //注意4.4无法找到PSY_EVENT_PROP_ADDED +// if ((event == PSY_EVENT_PROP_ADDED || event == PSY_EVENT_PROP_CHANGED) + if (event == PSY_EVENT_PROP_CHANGED +#endif + && psy && psy->desc->get_property && psy->desc->name && + !strncmp(psy->desc->name, USB_POWER_SUPPLY_NAME, sizeof(USB_POWER_SUPPLY_NAME))) { + AWLOGI(p_sar->dev, "ps notification: event = %lu", event); + retval = aw_sar_ps_get_state(p_sar, psy, &present); + if (retval) { + AWLOGE(p_sar->dev, "psy get property failed"); + return retval; + } + if (event == PSY_EVENT_PROP_CHANGED) { + if (p_sar->ps_is_present == present) { + AWLOGE(p_sar->dev, "ps present state not change"); + return 0; + } + } + p_sar->ps_is_present = present; + schedule_work(&p_sar->ps_notify_work); + } + return 0; +} + +static int aw_sar_ps_notify_init(struct aw_sar *p_sar) +{ + struct power_supply *psy = NULL; + int ret = 0; + + INIT_WORK(&p_sar->ps_notify_work, aw_sar_ps_notify_callback_work); + p_sar->ps_notif.notifier_call = (notifier_fn_t)aw_sar_ps_notify_callback; + ret = power_supply_reg_notifier(&p_sar->ps_notif); + if (ret) { + AWLOGE(p_sar->dev,"Unable to register ps_notifier: %d", ret); + return -AW_ERR; + } + psy = power_supply_get_by_name(USB_POWER_SUPPLY_NAME); + if (psy) { + ret = aw_sar_ps_get_state(p_sar, psy, &p_sar->ps_is_present); + if (ret) { + AWLOGE(p_sar->dev, "psy get property failed rc=%d", + ret); + goto free_ps_notifier; + } + } + return AW_OK; +free_ps_notifier: + power_supply_unreg_notifier(&p_sar->ps_notif); + return -AW_ERR; +} +// AW_SAR_USB_PLUG_CAIL end + + +static int32_t aw_sar_platform_rsc_init(struct aw_sar *p_sar) +{ + int32_t ret = 0; + + if (p_sar->p_sar_para->p_platform_config == NULL) { + return AW_INVALID_PARA; + } + + //step 1.parsing dts data + ret = aw_sar_parse_dts(p_sar); + if (ret != AW_OK) { + AWLOGE(p_sar->dev, "parse dts error!"); + return ret; + } + + //Initialization lock and some variables + aw_sar_init_lock(p_sar); + + //Configure whether to use USB plug-in calibration in DTS according to customer requirements + if (p_sar->dts_info.use_plug_cail_flag == true) { + ret = aw_sar_ps_notify_init(p_sar); + if (ret < 0) { + AWLOGE(p_sar->dev, "error creating power supply notify"); + goto free_usb_plug_cail; + } + } + + //The interrupt pin is set to internal pull-up and configured by DTS + if (p_sar->dts_info.use_inter_pull_up == true) { + ret = aw_sar_pinctrl_init(p_sar); + if (ret < 0) { + /* if define pinctrl must define the following state + * to let int-pin work normally: default, int_output_high, + * int_output_low, int_input + */ + AWLOGE(p_sar->dev, "Failed get wanted pinctrl state"); + goto err_pinctrl; + } + aw_sar_int_output(p_sar, 1); + } + + //step 2.Create debug file node + ret = aw_sar_create_node(p_sar); + if (ret != AW_OK) { + AWLOGE(p_sar->dev, "create node error!"); + goto free_sysfs_nodes; + } + + //step 3.Initialization interrupt + ret = aw_sar_irq_init(p_sar); + if (ret != AW_OK) { + AWLOGE(p_sar->dev, "interrupt initialization error!"); + goto free_irq; + } + + //step 4.Initialization input Subsystem + ret = aw_sar_input_init(p_sar); + if (ret != AW_OK) { + AWLOGE(p_sar->dev, "input_init error!"); + goto free_input; + } + + return AW_OK; + +free_input: + aw_sar_input_free(p_sar); +free_irq: + aw_sar_irq_free(p_sar); +free_sysfs_nodes: + aw_sar_node_free(p_sar); +err_pinctrl: +if (p_sar->dts_info.use_inter_pull_up == true) { + aw_sar_pinctrl_deinit(p_sar); +} +free_usb_plug_cail: +if (p_sar->dts_info.use_plug_cail_flag == true) { + power_supply_unreg_notifier(&p_sar->ps_notif); +} + + return -AW_ERR; +} + +/** + * @brief sar sensor initialization logic. + * + * @param p_sar data stored in type 'struct aw_sar *'. + * @return AW_OK 0 if init successed. others if unpack error. + */ +int32_t aw_sar_chip_init(struct aw_sar *p_sar) +{ + int32_t ret = 0; + + //step 1.check chipid,Verify whether the chip communication is successful + ret = aw_sar_check_chipid(p_sar); + if (ret != AW_OK) { + AWLOGE(p_sar->dev, "check_chipid error!"); + goto communication_fail; + } + + //step 2.Check chip initialization completed, + ret = aw_sar_soft_reset(p_sar); + if (ret != AW_OK) { + AWLOGE(p_sar->dev, "soft_reset error!"); + goto communication_fail; + } + + ret = aw_sar_check_init_over_irq(p_sar); + if (ret != AW_OK) { + AWLOGE(p_sar->dev, "check_init_over_irqt error!"); + goto communication_fail; + } + + //step 3.chip other operation + ret = aw_sar_chip_other_operation(p_sar); + if (ret != AW_OK) { + AWLOGE(p_sar->dev, "chip_other_operation error!"); + goto free_other_opera; + } + + //step 4.Parse the bin file, upgrade the firmware, and load the register prize + aw_sar_update(p_sar); + + AWLOGD(p_sar->dev, "init success!"); + + return AW_OK; +free_other_opera: + aw_sar_chip_other_operation_free(p_sar); +communication_fail: + + return -AW_ERR; +} + +static int32_t aw_sar_init(struct aw_sar *p_sar) +{ + int32_t ret = 0; + + //step 1: Platform resource initialization + ret = aw_sar_platform_rsc_init(p_sar); + if (ret != AW_OK) { + AWLOGE(p_sar->dev, "platform_rsc_init error!"); + return -AW_ERR; + } + + //step 2: Chip initialization + ret = aw_sar_chip_init(p_sar); + if (ret != AW_OK) { + aw_sar_input_free(p_sar); + aw_sar_irq_free(p_sar); + aw_sar_node_free(p_sar); + if (p_sar->dts_info.use_inter_pull_up == true) { + aw_sar_pinctrl_deinit(p_sar); + } + return -AW_ERR; + } + + return AW_OK; +} + +static int32_t aw_sar_regulator_power(struct aw_sar *p_sar) +{ + struct aw_sar_dts_info *p_dts_info = &p_sar->dts_info; + int32_t ret = 0; + + p_dts_info->use_regulator_flag = of_property_read_bool(p_sar->i2c->dev.of_node, "aw_sar,regulator-power-supply"); + AWLOGI(p_sar->dev, "regulator-power-supply = <%d>", p_dts_info->use_regulator_flag); + + //Configure the use of regulator power supply in DTS + if (p_sar->dts_info.use_regulator_flag == true) { + ret = aw_sar_regulator_power_init(p_sar); + if (ret) { + AWLOGE(p_sar->dev, "power init failed"); + } else { + aw_sar_power_enable(p_sar, AW_TRUE); + } + ret = regulator_is_get_voltage(p_sar); + if (ret != AW_OK) { + AWLOGE(p_sar->dev, "get_voltage failed"); + aw_sar_power_deinit(p_sar); + } + } + + return ret; +} + +/** + * @brief Drive logic entry + * + */ +static int32_t aw_sar_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) +{ + int32_t ret = 0; + struct aw_sar *p_sar = NULL; + + pr_info("%s enter", __func__); + + if (!i2c_check_functionality(i2c->adapter, I2C_FUNC_I2C)) { + pr_err("check_functionality failed!\n"); + return -EIO; + } + + p_sar = devm_kzalloc(&i2c->dev, sizeof(struct aw_sar), GFP_KERNEL); + if (p_sar == NULL) { + pr_err("p_sar failed to malloc memory!"); + ret = -AW_ERR; + goto err_malloc; + } + + p_sar->dev = &i2c->dev; + p_sar->i2c = i2c; + i2c_set_clientdata(i2c, p_sar); + + //1.Judge whether to use regular power supply. If yes, supply power + ret = aw_sar_regulator_power(p_sar); + if (ret != AW_OK) { + AWLOGE(&i2c->dev, "regulator_power error!"); + goto err_get_voltage; + } + + //2.Get chip initialization resources + ret = aw_sar_get_chip_info(p_sar); + if (ret != AW_OK) { + AWLOGE(&i2c->dev, "chip_init error!"); + goto err_chip_init; + } + + //3.Chip initialization process + ret = aw_sar_init(p_sar); + if (ret != AW_OK) { + AWLOGE(&i2c->dev, "chip_init error!"); + goto err_chip_init; + } + + AWLOGD(&i2c->dev, "probe success!"); + + return 0; +err_chip_init: + aw_sar_sensor_free(p_sar); +err_get_voltage: +if (p_sar->dts_info.use_regulator_flag == true) { + aw_sar_power_deinit(p_sar); +} + +err_malloc: + return ret; +} + +static int32_t aw_sar_i2c_remove(struct i2c_client *i2c) +{ + struct aw_sar *p_sar = i2c_get_clientdata(i2c); + + aw_sar_chip_other_operation_free(p_sar); + + aw_sar_node_free(p_sar); + + aw_sar_irq_free(p_sar); + + aw_sar_input_free(p_sar); + + if (p_sar->dts_info.use_inter_pull_up == true) { + aw_sar_pinctrl_deinit(p_sar); + } + if (p_sar->dts_info.use_regulator_flag == true) { + aw_sar_power_deinit(p_sar); + } + + if (p_sar->dts_info.use_plug_cail_flag == true) { + power_supply_unreg_notifier(&p_sar->ps_notif); + } + + aw_sar_sensor_free(p_sar); + + AWLOGI(p_sar->dev, "aw_sar_i2c_remove ok!"); + + return 0; +} + +static int aw_sar_suspend(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct aw_sar *p_sar = i2c_get_clientdata(client); + + AWLOGI(p_sar->dev, "enter"); + + if (p_sar->dts_info.use_pm == true) { + if ((p_sar->p_sar_para->p_platform_config == NULL) || + (p_sar->p_sar_para->p_platform_config->p_pm_chip_mode == NULL)) { + return 0; + } + if (p_sar->p_sar_para->p_platform_config->p_pm_chip_mode->p_suspend_fn) { + p_sar->p_sar_para->p_platform_config->p_pm_chip_mode->p_suspend_fn(p_sar); + return 0; + } + aw_sar_mode_set(p_sar, p_sar->p_sar_para->p_platform_config->p_pm_chip_mode->suspend_set_mode); + } + + return 0; +} + +static int aw_sar_resume(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct aw_sar *p_sar = i2c_get_clientdata(client); + + AWLOGI(p_sar->dev, "enter"); + + if (p_sar->dts_info.use_pm == true) { + if ((p_sar->p_sar_para->p_platform_config == NULL) || + (p_sar->p_sar_para->p_platform_config->p_pm_chip_mode == NULL)) { + return 0; + } + if (p_sar->p_sar_para->p_platform_config->p_pm_chip_mode->p_resume_fn) { + p_sar->p_sar_para->p_platform_config->p_pm_chip_mode->p_resume_fn(p_sar); + return 0; + } + aw_sar_mode_set(p_sar, p_sar->p_sar_para->p_platform_config->p_pm_chip_mode->resume_set_mode); + } + return 0; +} + +static void aw_sar_i2c_shutdown(struct i2c_client *i2c) +{ + struct aw_sar *p_sar = i2c_get_clientdata(i2c); + + AWLOGI(p_sar->dev, "enter"); + + if ((p_sar->p_sar_para->p_platform_config == NULL) || + (p_sar->p_sar_para->p_platform_config->p_pm_chip_mode == NULL)) { + return; + } + + if (p_sar->p_sar_para->p_platform_config->p_pm_chip_mode->p_shutdown_fn) { + p_sar->p_sar_para->p_platform_config->p_pm_chip_mode->p_shutdown_fn(p_sar); + return; + } + + aw_sar_mode_set(p_sar, p_sar->p_sar_para->p_platform_config->p_pm_chip_mode->shutdown_set_mode); +} + +static const struct dev_pm_ops aw_sar_pm_ops = { + .suspend = aw_sar_suspend, + .resume = aw_sar_resume, +}; + +static const struct of_device_id aw_sar_dt_match[] = { + { .compatible = "awinic,aw_sar" }, +}; + +static const struct i2c_device_id aw_sar_i2c_id[] = { + { AW_SAR_I2C_NAME, 0 }, + { }, +}; +MODULE_DEVICE_TABLE(i2c, aw_sar_i2c_id); + +static struct i2c_driver aw_sar_i2c_driver = { + .driver = { + .name = AW_SAR_I2C_NAME, + .owner = THIS_MODULE, + .of_match_table = of_match_ptr(aw_sar_dt_match), + .pm = &aw_sar_pm_ops, + }, + .probe = aw_sar_i2c_probe, + .remove = aw_sar_i2c_remove, + .shutdown = aw_sar_i2c_shutdown, + .id_table = aw_sar_i2c_id, +}; + +static int32_t __init aw_sar_i2c_init(void) +{ + int32_t ret = 0; + + pr_info("awinic sar driver version %s\n", AW_SAR_DRIVER_VERSION); + + ret = i2c_add_driver(&aw_sar_i2c_driver); + if (ret) { + pr_err("fail to add aw_sar device into i2c\n"); + return ret; + } + + return 0; +} + +module_init(aw_sar_i2c_init); +static void __exit aw_sar_i2c_exit(void) +{ + i2c_del_driver(&aw_sar_i2c_driver); +} +module_exit(aw_sar_i2c_exit); + +/** + * @brief Distinguish different chips by chip name and obtain relevant chip information + * + * @param p_sar Structure to be filled + * @return AW_OK 0 if init successed. -AW_ERR -1 if error. + */ +static int32_t aw_sar_get_chip_info(struct aw_sar *p_sar) +{ + uint8_t i = 0; + int32_t ret = 0; + + AWLOGD(p_sar->dev, "enter"); + + for(i = 0; i < AW_SAR_DRIVER_MAX; i++) { + if (g_aw_sar_driver_list[i].p_who_am_i != NULL) { + ret = g_aw_sar_driver_list[i].p_who_am_i(p_sar); + if (ret == AW_OK) { + p_sar->curr_use_driver_type = g_aw_sar_driver_list[i].driver_type; + if (g_aw_sar_driver_list[i].p_chip_init == NULL) { + AWLOGE(p_sar->dev, "drvier:%d p_chip_init is null error!", i); + continue; + } + g_aw_sar_driver_list[i].p_chip_init(p_sar); + AWLOGI(p_sar->dev, "current use drvier is :%d", g_aw_sar_driver_list[i].driver_type); + return AW_OK; + } else { + AWLOGI(p_sar->dev, "drvier:%d Not supported", i); + } + } + } + + return -AW_ERR; +} + +/** + * @brief Distinguish different chips by chip name and obtain relevant chip information + * + * @param p_sar Associated release resource information,Follow priv_data member + * @return AW_OK 0 if init successed. -AW_ERR -1 if error. + */ +static void aw_sar_sensor_free(struct aw_sar *p_sar) +{ + if (g_aw_sar_driver_list[p_sar->curr_use_driver_type].p_chip_deinit != NULL) { + g_aw_sar_driver_list[p_sar->curr_use_driver_type].p_chip_deinit(p_sar); + } +} + +MODULE_DESCRIPTION("AWINIC SAR Driver"); + +MODULE_LICENSE("GPL v2"); diff --git a/drivers/misc/awinic/sarsensor/comm/aw_sar_comm_interface.c b/drivers/misc/awinic/sarsensor/comm/aw_sar_comm_interface.c new file mode 100644 index 000000000000..dda27396be34 --- /dev/null +++ b/drivers/misc/awinic/sarsensor/comm/aw_sar_comm_interface.c @@ -0,0 +1,786 @@ +#include "aw_sar_comm_interface.h" + +#define AW_I2C_RW_RETRY_TIME_MIN (2000) +#define AW_I2C_RW_RETRY_TIME_MAX (3000) +#define AW_RETRIES (5) + +static int32_t awinic_i2c_write(struct i2c_client *i2c, uint8_t *tr_data, uint16_t len) +{ + struct i2c_msg msg; + + msg.addr = i2c->addr; + msg.flags = 0; + msg.len = len; + msg.buf = tr_data; + + return i2c_transfer(i2c->adapter, &msg, 1); +} + +static int32_t awinic_i2c_read(struct i2c_client *i2c, uint8_t *addr, + uint8_t addr_len, uint8_t *data, uint16_t data_len) +{ + struct i2c_msg msg[2]; + + msg[0].addr = i2c->addr; + msg[0].flags = 0; + msg[0].len = addr_len; + msg[0].buf = addr; + + msg[1].addr = i2c->addr; + msg[1].flags = 1; + msg[1].len = data_len; + msg[1].buf = data; + + return i2c_transfer(i2c->adapter, msg, 2); +} + +/** + * @brief Read register interface + * + * @param i2c: i2c client. + * @param reg_addr16: 16 bit register address. + * @param *reg_data32: 32 bit register data. + * @return AW_OK 0 if init successed. -AW_ERR -1 if error. + */ +int32_t aw_sar_i2c_read(struct i2c_client *i2c, uint16_t reg_addr16, uint32_t *reg_data32) +{ + int8_t cnt = 5; + int32_t ret = -1; + uint8_t r_buf[6] = { 0 }; + + if (i2c == NULL) { + AWLOGE(&i2c->dev, "i2c_dev is null error!"); + return -AW_ERR; + } + + r_buf[0] = (unsigned char)(reg_addr16 >> OFFSET_BIT_8); + r_buf[1] = (unsigned char)(reg_addr16); + + do { + ret = awinic_i2c_read(i2c, r_buf, 2, &r_buf[2], 4); + if (ret < 0) { + AWLOGE(&i2c->dev, "i2c read error reg: 0x%04x, ret= %d cnt= %d", reg_addr16, ret, cnt); + } else { + break; + } + usleep_range(2000, 3000); + } while (cnt--); + + if (cnt < 0) { + AWLOGE(&i2c->dev, "i2c read error!"); + return -AW_ERR; + } + + *reg_data32 = ((uint32_t)r_buf[5] << OFFSET_BIT_0) | ((uint32_t)r_buf[4] << OFFSET_BIT_8) | + ((uint32_t)r_buf[3] << OFFSET_BIT_16) | ((uint32_t)r_buf[2] << OFFSET_BIT_24); + + return AW_OK; +} + +/** + * @brief write register interface + * + * @param i2c: i2c client. + * @param reg_addr16: 16 bit register address. + * @param reg_data32: 32 bit register data. + * @return AW_OK 0 if init successed. -AW_ERR -1 if error. + */ +int32_t aw_sar_i2c_write(struct i2c_client *i2c, uint16_t reg_addr16, uint32_t reg_data32) +{ + int8_t cnt = 5; + int32_t ret = -1; + uint8_t w_buf[6] = { 0 }; + + if (i2c == NULL) { + AWLOGE(&i2c->dev, "i2c_dev is null error!"); + return -AW_ERR; + } + + /*reg_addr*/ + w_buf[0] = (uint8_t)(reg_addr16 >> OFFSET_BIT_8); + w_buf[1] = (uint8_t)(reg_addr16); + /*data*/ + w_buf[2] = (uint8_t)(reg_data32 >> OFFSET_BIT_24); + w_buf[3] = (uint8_t)(reg_data32 >> OFFSET_BIT_16); + w_buf[4] = (uint8_t)(reg_data32 >> OFFSET_BIT_8); + w_buf[5] = (uint8_t)(reg_data32); + + do { + ret = awinic_i2c_write(i2c, w_buf, ARRAY_SIZE(w_buf)); + if (ret < 0) { + AWLOGE(&i2c->dev, "i2c write error reg: 0x%04x data: 0x%08x, ret= %d cnt= %d", + reg_addr16, reg_data32, ret, cnt); + } else { + break; + } + } while (cnt--); + + if (cnt < 0) { + AWLOGE(&i2c->dev, "i2c write error!"); + return -AW_ERR; + } + + return AW_OK; +} + +/** + * @brief Write the corresponding bit of the register + * + * @param i2c:i2c client. + * @param reg_addr16: 16 bit register address. + * @param mask: Write the corresponding bit as 0 + * @param val: Write corresponding data to the register + * @return AW_OK 0 if init successed. -AW_ERR -1 if error. + */ +int32_t aw_sar_i2c_write_bits(struct i2c_client *i2c, uint16_t reg_addr16, + uint32_t mask, uint32_t val) +{ + uint32_t reg_val; + + aw_sar_i2c_read(i2c, reg_addr16, ®_val); + reg_val &= mask; + reg_val |= (val & (~mask)); + aw_sar_i2c_write(i2c, reg_addr16, reg_val); + + return AW_OK; +} + +/** + * @brief Continuously write data to the chip + * + * @param i2c:i2c client. + * @param *tr_data: Data written + * @param len: Length of data written + * @return AW_OK 0 if init successed. -AW_ERR -1 if error. + */ +int32_t aw_sar_i2c_write_seq(struct i2c_client *i2c, uint8_t *tr_data, uint16_t len) +{ + int8_t cnt = AW_RETRIES; + int32_t ret = -AW_ERR; + + do { + ret = awinic_i2c_write(i2c, tr_data, len); + if (ret < 0) + AWLOGE(&i2c->dev, "awinic i2c write seq error %d", ret); + else + break; + usleep_range(AW_I2C_RW_RETRY_TIME_MIN, AW_I2C_RW_RETRY_TIME_MAX); + } while (cnt--); + + if (cnt < 0) { + AWLOGE(&i2c->dev, "awinic i2c write error!"); + return -AW_ERR; + } + + return AW_OK; +} + +/** + * @brief Continuously Read data from chip + * + * @param i2c:i2c client. + * @param *addr: Read address + * @param addr_len: Length of read address (byte) + * @param *data: Data written + * @param data_len: Length of data written + * @return AW_OK 0 if init successed. -AW_ERR -1 if error. + */ +int32_t aw_sar_i2c_read_seq(struct i2c_client *i2c, uint8_t *addr, + uint8_t addr_len, uint8_t *data, uint16_t data_len) +{ + int8_t cnt = AW_RETRIES; + int32_t ret = -AW_ERR; + + do { + ret = awinic_i2c_read(i2c, addr, addr_len, data, data_len); + if (ret < 0) { + AWLOGE(&i2c->dev, "awinic sar i2c write error %d", ret); + } else { + break; + } + usleep_range(AW_I2C_RW_RETRY_TIME_MIN, AW_I2C_RW_RETRY_TIME_MAX); + } while (cnt--); + + if (cnt < 0) { + AWLOGE(&i2c->dev, "awinic sar i2c read error!"); + return -AW_ERR; + } + + return AW_OK; +} + +/*********************************Parse bin file code start**************************************************/ + +#define AWINIC_CODE_VERSION "V0.0.7-V1.0.4" /* "code version"-"excel version" */ + +enum bin_header_version_enum { + HEADER_VERSION_1_0_0 = 0x01000000, +}; + +enum data_type_enum { + DATA_TYPE_REGISTER = 0x00000000, + DATA_TYPE_DSP_REG = 0x00000010, + DATA_TYPE_DSP_CFG = 0x00000011, + DATA_TYPE_SOC_REG = 0x00000020, + DATA_TYPE_SOC_APP = 0x00000021, + DATA_TYPE_MULTI_BINS = 0x00002000, +}; + +enum data_version_enum { + DATA_VERSION_V1 = 0X00000001, /*default little edian */ + DATA_VERSION_MAX, +}; + +#define DEBUG_LOG_LEVEL +#ifdef DEBUG_LOG_LEVEL +#define DBG(fmt, arg...) do {\ +printk("AWINIC_BIN %s,line= %d,"fmt, __func__, __LINE__, ##arg);\ +} while (0) +#define DBG_ERR(fmt, arg...) do {\ +printk("AWINIC_BIN_ERR %s,line= %d,"fmt, __func__, __LINE__, ##arg);\ +} while (0) +#else +#define DBG(fmt, arg...) do {} while (0) +#define DBG_ERR(fmt, arg...) do {} while (0) +#endif + +#define printing_data_code + +typedef unsigned short int aw_uint16; +typedef unsigned long int aw_uint32; + +#define BigLittleSwap16(A) ((((aw_uint16)(A) & 0xff00) >> 8) | \ + (((aw_uint16)(A) & 0x00ff) << 8)) + +#define BigLittleSwap32(A) ((((aw_uint32)(A) & 0xff000000) >> 24) | \ + (((aw_uint32)(A) & 0x00ff0000) >> 8) | \ + (((aw_uint32)(A) & 0x0000ff00) << 8) | \ + (((aw_uint32)(A) & 0x000000ff) << 24)) + +static int aw_parse_bin_header_1_0_0(struct aw_bin *bin); + +/** +* +* Interface function +* +* return value: +* value = 0 :success; +* value = -1 :check bin header version +* value = -2 :check bin data type +* value = -3 :check sum or check bin data len error +* value = -4 :check data version +* value = -5 :check register num +* value = -6 :check dsp reg num +* value = -7 :check soc app num +* value = -8 :bin is NULL point +* +**/ + +/******************************************************** +* +* check sum data +* +********************************************************/ +static int aw_check_sum(struct aw_bin *bin, int bin_num) +{ + unsigned int i = 0; + unsigned int sum_data = 0; + unsigned int check_sum = 0; + char *p_check_sum = NULL; + + DBG("enter\n"); + + p_check_sum = + &(bin->info.data[(bin->header_info[bin_num].valid_data_addr - + bin->header_info[bin_num].header_len)]); + DBG("aw_bin_parse p_check_sum = %p\n", p_check_sum); + check_sum = AW_SAR_GET_32_DATA(*(p_check_sum + 3), + *(p_check_sum + 2), + *(p_check_sum + 1), *(p_check_sum)); + + for (i = 4; + i < + bin->header_info[bin_num].bin_data_len + + bin->header_info[bin_num].header_len; i++) { + sum_data += *(p_check_sum + i); + } + DBG("aw_bin_parse bin_num=%d, check_sum = 0x%x, sum_data = 0x%x\n", + bin_num, check_sum, sum_data); + if (sum_data != check_sum) { + p_check_sum = NULL; + DBG_ERR("aw_bin_parse check sum or check bin data len error\n"); + DBG_ERR("aw_bin_parse bin_num=%d, check_sum = 0x%x, sum_data = 0x%x\n", bin_num, check_sum, sum_data); + return -3; + } + p_check_sum = NULL; + + return 0; +} + +static int aw_check_data_version(struct aw_bin *bin, int bin_num) +{ + int i = 0; + DBG("enter\n"); + + for (i = DATA_VERSION_V1; i < DATA_VERSION_MAX; i++) { + if (bin->header_info[bin_num].bin_data_ver == i) { + return 0; + } + } + DBG_ERR("aw_bin_parse Unrecognized this bin data version\n"); + return -4; +} + +static int aw_check_register_num_v1(struct aw_bin *bin, int bin_num) +{ + unsigned int check_register_num = 0; + unsigned int parse_register_num = 0; + char *p_check_sum = NULL; + + DBG("enter\n"); + + p_check_sum = + &(bin->info.data[(bin->header_info[bin_num].valid_data_addr)]); + DBG("aw_bin_parse p_check_sum = %p\n", p_check_sum); + parse_register_num = AW_SAR_GET_32_DATA(*(p_check_sum + 3), + *(p_check_sum + 2), + *(p_check_sum + 1), *(p_check_sum)); + check_register_num = (bin->header_info[bin_num].bin_data_len - 4) / + (bin->header_info[bin_num].reg_byte_len + + bin->header_info[bin_num].data_byte_len); + DBG + ("aw_bin_parse bin_num=%d, parse_register_num = 0x%x, check_register_num = 0x%x\n", + bin_num, parse_register_num, check_register_num); + if (parse_register_num != check_register_num) { + p_check_sum = NULL; + DBG_ERR("aw_bin_parse register num is error\n"); + DBG_ERR("aw_bin_parse bin_num=%d, parse_register_num = 0x%x, check_register_num = 0x%x\n", bin_num, parse_register_num, check_register_num); + return -5; + } + bin->header_info[bin_num].reg_num = parse_register_num; + bin->header_info[bin_num].valid_data_len = + bin->header_info[bin_num].bin_data_len - 4; + p_check_sum = NULL; + bin->header_info[bin_num].valid_data_addr = + bin->header_info[bin_num].valid_data_addr + 4; + return 0; +} + +static int aw_check_dsp_reg_num_v1(struct aw_bin *bin, int bin_num) +{ + unsigned int check_dsp_reg_num = 0; + unsigned int parse_dsp_reg_num = 0; + char *p_check_sum = NULL; + + DBG("enter\n"); + + p_check_sum = + &(bin->info.data[(bin->header_info[bin_num].valid_data_addr)]); + DBG("aw_bin_parse p_check_sum = %p\n", p_check_sum); + parse_dsp_reg_num = AW_SAR_GET_32_DATA(*(p_check_sum + 7), + *(p_check_sum + 6), + *(p_check_sum + 5), + *(p_check_sum + 4)); + bin->header_info[bin_num].reg_data_byte_len = + AW_SAR_GET_32_DATA(*(p_check_sum + 11), *(p_check_sum + 10), + *(p_check_sum + 9), *(p_check_sum + 8)); + check_dsp_reg_num = + (bin->header_info[bin_num].bin_data_len - + 12) / bin->header_info[bin_num].reg_data_byte_len; + DBG + ("aw_bin_parse bin_num=%d, parse_dsp_reg_num = 0x%x, check_dsp_reg_num = 0x%x\n", + bin_num, parse_dsp_reg_num, check_dsp_reg_num); + if (parse_dsp_reg_num != check_dsp_reg_num) { + p_check_sum = NULL; + DBG_ERR("aw_bin_parse dsp reg num is error\n"); + DBG_ERR("aw_bin_parse bin_num=%d, parse_dsp_reg_num = 0x%x, check_dsp_reg_num = 0x%x\n", bin_num, parse_dsp_reg_num, check_dsp_reg_num); + return -6; + } + bin->header_info[bin_num].download_addr = + AW_SAR_GET_32_DATA(*(p_check_sum + 3), *(p_check_sum + 2), + *(p_check_sum + 1), *(p_check_sum)); + bin->header_info[bin_num].reg_num = parse_dsp_reg_num; + bin->header_info[bin_num].valid_data_len = + bin->header_info[bin_num].bin_data_len - 12; + p_check_sum = NULL; + bin->header_info[bin_num].valid_data_addr = + bin->header_info[bin_num].valid_data_addr + 12; + return 0; +} + +static int aw_check_soc_app_num_v1(struct aw_bin *bin, int bin_num) +{ + unsigned int check_soc_app_num = 0; + unsigned int parse_soc_app_num = 0; + char *p_check_sum = NULL; + + DBG("enter\n"); + + p_check_sum = + &(bin->info.data[(bin->header_info[bin_num].valid_data_addr)]); + DBG("aw_bin_parse p_check_sum = %p\n", p_check_sum); + bin->header_info[bin_num].app_version = AW_SAR_GET_32_DATA(*(p_check_sum + 3), + *(p_check_sum + 2), + *(p_check_sum + 1), + *(p_check_sum)); + parse_soc_app_num = AW_SAR_GET_32_DATA(*(p_check_sum + 11), + *(p_check_sum + 10), + *(p_check_sum + 9), *(p_check_sum + 8)); + check_soc_app_num = bin->header_info[bin_num].bin_data_len - 12; + DBG + ("aw_bin_parse bin_num=%d, parse_soc_app_num = 0x%x, check_soc_app_num = 0x%x\n", + bin_num, parse_soc_app_num, check_soc_app_num); + if (parse_soc_app_num != check_soc_app_num) { + p_check_sum = NULL; + DBG_ERR("aw_bin_parse soc app num is error\n"); + DBG_ERR("aw_bin_parse bin_num=%d, parse_soc_app_num = 0x%x, check_soc_app_num = 0x%x\n", bin_num, parse_soc_app_num, check_soc_app_num); + return -7; + } + bin->header_info[bin_num].reg_num = parse_soc_app_num; + bin->header_info[bin_num].download_addr = + AW_SAR_GET_32_DATA(*(p_check_sum + 7), *(p_check_sum + 6), + *(p_check_sum + 5), *(p_check_sum + 4)); + bin->header_info[bin_num].valid_data_len = + bin->header_info[bin_num].bin_data_len - 12; + p_check_sum = NULL; + bin->header_info[bin_num].valid_data_addr = + bin->header_info[bin_num].valid_data_addr + 12; + return 0; +} + +/************************ +*** +***bin header 1_0_0 +*** +************************/ +static void aw_get_single_bin_header_1_0_0(struct aw_bin *bin) +{ + int i; + DBG("enter %s\n", __func__); + bin->header_info[bin->all_bin_parse_num].header_len = 60; + bin->header_info[bin->all_bin_parse_num].check_sum = + AW_SAR_GET_32_DATA(*(bin->p_addr + 3), *(bin->p_addr + 2), + *(bin->p_addr + 1), *(bin->p_addr)); + bin->header_info[bin->all_bin_parse_num].header_ver = + AW_SAR_GET_32_DATA(*(bin->p_addr + 7), *(bin->p_addr + 6), + *(bin->p_addr + 5), *(bin->p_addr + 4)); + bin->header_info[bin->all_bin_parse_num].bin_data_type = + AW_SAR_GET_32_DATA(*(bin->p_addr + 11), *(bin->p_addr + 10), + *(bin->p_addr + 9), *(bin->p_addr + 8)); + bin->header_info[bin->all_bin_parse_num].bin_data_ver = + AW_SAR_GET_32_DATA(*(bin->p_addr + 15), *(bin->p_addr + 14), + *(bin->p_addr + 13), *(bin->p_addr + 12)); + bin->header_info[bin->all_bin_parse_num].bin_data_len = + AW_SAR_GET_32_DATA(*(bin->p_addr + 19), *(bin->p_addr + 18), + *(bin->p_addr + 17), *(bin->p_addr + 16)); + bin->header_info[bin->all_bin_parse_num].ui_ver = + AW_SAR_GET_32_DATA(*(bin->p_addr + 23), *(bin->p_addr + 22), + *(bin->p_addr + 21), *(bin->p_addr + 20)); + bin->header_info[bin->all_bin_parse_num].reg_byte_len = + AW_SAR_GET_32_DATA(*(bin->p_addr + 35), *(bin->p_addr + 34), + *(bin->p_addr + 33), *(bin->p_addr + 32)); + bin->header_info[bin->all_bin_parse_num].data_byte_len = + AW_SAR_GET_32_DATA(*(bin->p_addr + 39), *(bin->p_addr + 38), + *(bin->p_addr + 37), *(bin->p_addr + 36)); + bin->header_info[bin->all_bin_parse_num].device_addr = + AW_SAR_GET_32_DATA(*(bin->p_addr + 43), *(bin->p_addr + 42), + *(bin->p_addr + 41), *(bin->p_addr + 40)); + for (i = 0; i < 8; i++) { + bin->header_info[bin->all_bin_parse_num].chip_type[i] = + *(bin->p_addr + 24 + i); + } +// bin->header_info[bin->all_bin_parse_num].chip_type[i] = '\0'; +// DBG("%s : enter chip_type is %s\n", __func__, +// bin->header_info[bin->all_bin_parse_num].chip_type); + + bin->header_info[bin->all_bin_parse_num].reg_num = 0x00000000; + bin->header_info[bin->all_bin_parse_num].reg_data_byte_len = 0x00000000; + bin->header_info[bin->all_bin_parse_num].download_addr = 0x00000000; + bin->header_info[bin->all_bin_parse_num].app_version = 0x00000000; + bin->header_info[bin->all_bin_parse_num].valid_data_len = 0x00000000; + bin->all_bin_parse_num += 1; +} + +static int aw_parse_each_of_multi_bins_1_0_0(unsigned int bin_num, int bin_serial_num, + struct aw_bin *bin) +{ + int ret = 0; + unsigned int bin_start_addr = 0; + unsigned int valid_data_len = 0; + DBG("aw_bin_parse enter multi bin branch -- %s\n", __func__); + if (!bin_serial_num) { + bin_start_addr = AW_SAR_GET_32_DATA(*(bin->p_addr + 67), + *(bin->p_addr + 66), + *(bin->p_addr + 65), + *(bin->p_addr + 64)); + bin->p_addr += (60 + bin_start_addr); + bin->header_info[bin->all_bin_parse_num].valid_data_addr = + bin->header_info[bin->all_bin_parse_num - + 1].valid_data_addr + 4 + 8 * bin_num + 60; + } else { + valid_data_len = + bin->header_info[bin->all_bin_parse_num - 1].bin_data_len; + bin->p_addr += (60 + valid_data_len); + bin->header_info[bin->all_bin_parse_num].valid_data_addr = + bin->header_info[bin->all_bin_parse_num - + 1].valid_data_addr + + bin->header_info[bin->all_bin_parse_num - 1].bin_data_len + + 60; + } + + ret = aw_parse_bin_header_1_0_0(bin); + return ret; +} + +/* Get the number of bins in multi bins, and set a for loop, loop processing each bin data */ +static int aw_get_multi_bin_header_1_0_0(struct aw_bin *bin) +{ + int i = 0; + int ret = 0; + unsigned int bin_num = 0; + DBG("aw_bin_parse enter multi bin branch -- %s\n", __func__); + bin_num = AW_SAR_GET_32_DATA(*(bin->p_addr + 63), + *(bin->p_addr + 62), + *(bin->p_addr + 61), *(bin->p_addr + 60)); + if (bin->multi_bin_parse_num == 1) { + bin->header_info[bin->all_bin_parse_num].valid_data_addr = 60; + } + aw_get_single_bin_header_1_0_0(bin); + + for (i = 0; i < bin_num; i++) { + DBG("aw_bin_parse enter multi bin for is %d\n", i); + ret = aw_parse_each_of_multi_bins_1_0_0(bin_num, i, bin); + if (ret < 0) { + return ret; + } + } + return 0; +} + +/******************************************************** +* +* If the bin framework header version is 1.0.0, + determine the data type of bin, and then perform different processing + according to the data type + If it is a single bin data type, write the data directly into the structure array + If it is a multi-bin data type, first obtain the number of bins, + and then recursively call the bin frame header processing function + according to the bin number to process the frame header information of each bin separately +* +********************************************************/ +static int aw_parse_bin_header_1_0_0(struct aw_bin *bin) +{ + int ret = 0; + unsigned int bin_data_type; + DBG("enter %s\n", __func__); + bin_data_type = AW_SAR_GET_32_DATA(*(bin->p_addr + 11), + *(bin->p_addr + 10), + *(bin->p_addr + 9), *(bin->p_addr + 8)); + DBG("aw_bin_parse bin_data_type 0x%x\n", bin_data_type); + switch (bin_data_type) { + case DATA_TYPE_REGISTER: + case DATA_TYPE_DSP_REG: + case DATA_TYPE_SOC_APP: + /* Divided into two processing methods, + one is single bin processing, + and the other is single bin processing in multi bin */ + DBG("aw_bin_parse enter single bin branch\n"); + bin->single_bin_parse_num += 1; + DBG("%s bin->single_bin_parse_num is %d\n", __func__, + bin->single_bin_parse_num); + if (!bin->multi_bin_parse_num) { + bin->header_info[bin-> + all_bin_parse_num].valid_data_addr = + 60; + } + aw_get_single_bin_header_1_0_0(bin); + break; + case DATA_TYPE_MULTI_BINS: + /* Get the number of times to enter multi bins */ + DBG("aw_bin_parse enter multi bin branch\n"); + bin->multi_bin_parse_num += 1; + DBG("%s bin->multi_bin_parse_num is %d\n", __func__, + bin->multi_bin_parse_num); + ret = aw_get_multi_bin_header_1_0_0(bin); + if (ret < 0) { + return ret; + } + break; + default: + DBG_ERR("aw_bin_parse Unrecognized this bin data type\n"); + return -2; + } + return 0; +} + +/* get the bin's header version */ +static int aw_check_bin_header_version(struct aw_bin *bin) +{ + int ret = 0; + unsigned int header_version = 0; + + header_version = AW_SAR_GET_32_DATA(*(bin->p_addr + 7), + *(bin->p_addr + 6), + *(bin->p_addr + 5), *(bin->p_addr + 4)); + + DBG("aw_bin_parse header_version 0x%x\n", header_version); + + /* Write data to the corresponding structure array + according to different formats of the bin frame header version */ + switch (header_version) { + case HEADER_VERSION_1_0_0: + ret = aw_parse_bin_header_1_0_0(bin); + return ret; + default: + DBG_ERR("aw_bin_parse Unrecognized this bin header version \n"); + return -1; + } +} + +/** + * @brief Parse bin file + * + * @param bin: Store the contents of the parsed bin file + * @return 0 if init successed, other if error + */ +int aw_sar_parsing_bin_file(struct aw_bin *bin) +{ + int i = 0; + int ret = 0; + + DBG("aw_bin_parse code version:%s\n", AWINIC_CODE_VERSION); + if (!bin) { + DBG_ERR("aw_bin_parse bin is NULL\n"); + return -8; + } + bin->p_addr = bin->info.data; + bin->all_bin_parse_num = 0; + bin->multi_bin_parse_num = 0; + bin->single_bin_parse_num = 0; + + /* filling bins header info */ + ret = aw_check_bin_header_version(bin); + if (ret < 0) { + DBG_ERR("aw_bin_parse check bin header version error\n"); + return ret; + } + bin->p_addr = NULL; + + /* check bin header info */ + for (i = 0; i < bin->all_bin_parse_num; i++) { + /* check sum */ + ret = aw_check_sum(bin, i); + if (ret < 0) { + DBG_ERR("aw_bin_parse check sum data error\n"); + return ret; + } + /* check bin data version */ + ret = aw_check_data_version(bin, i); + if (ret < 0) { + DBG_ERR("aw_bin_parse check data version error\n"); + return ret; + } + /* check valid data */ + if (bin->header_info[i].bin_data_ver == DATA_VERSION_V1) { + /* check register num */ + if (bin->header_info[i].bin_data_type == + DATA_TYPE_REGISTER) { + ret = aw_check_register_num_v1(bin, i); + if (ret < 0) { + DBG_ERR + ("aw_bin_parse check register num error\n"); + return ret; + } + /* check dsp reg num */ + } else if (bin->header_info[i].bin_data_type == + DATA_TYPE_DSP_REG) { + ret = aw_check_dsp_reg_num_v1(bin, i); + if (ret < 0) { + DBG_ERR + ("aw_bin_parse check dsp reg num error\n"); + return ret; + } + /* check soc app num */ + } else if (bin->header_info[i].bin_data_type == + DATA_TYPE_SOC_APP) { + ret = aw_check_soc_app_num_v1(bin, i); + if (ret < 0) { + DBG_ERR + ("aw_bin_parse check soc app num error\n"); + return ret; + } + } else { + bin->header_info[i].valid_data_len = + bin->header_info[i].bin_data_len; + } + } + } + DBG("aw_bin_parse parsing success\n"); + + return 0; +} +/*********************************Parse bin file code end**************************************************/ + +/** + * @brief Calculate the second power + * + * @param cnt: ifrequency + * @return the second power + */ +uint32_t aw_sar_pow2(uint32_t cnt) +{ + uint32_t i = 0; + uint32_t sum = 1; + + if (cnt == 0) { + sum = 1; + } else { + for (i = 0; i < cnt; i++) { + sum *= 2; + } + } + + return sum; +} + +/** + * @brief Calculate the second power + * + * @param *aw_bin: Information after parsing bin file + * @param *i2c: i2c client. + * @return AW_OK 0 if init successed. -AW_ERR -1 if error + */ +int32_t aw_sar_load_reg(struct aw_bin *aw_bin, struct i2c_client *i2c) +{ + uint32_t i = 0; + int32_t ret = 0; + uint16_t reg_addr = 0; + uint32_t reg_data = 0; + uint32_t start_addr = aw_bin->header_info[0].valid_data_addr; + + for (i = 0; i < aw_bin->header_info[0].valid_data_len; + i += 6, start_addr += 6) { + reg_addr = (aw_bin->info.data[start_addr]) | + aw_bin->info.data[start_addr + 1] << OFFSET_BIT_8; + reg_data = aw_bin->info.data[start_addr + 2] | + (aw_bin->info.data[start_addr + 3] << OFFSET_BIT_8) | + (aw_bin->info.data[start_addr + 4] << OFFSET_BIT_16) | + (aw_bin->info.data[start_addr + 5] << OFFSET_BIT_24); + + ret = aw_sar_i2c_write(i2c, reg_addr, reg_data); + if (ret < 0) { + AWLOGE(&i2c->dev, "i2c write err"); + return -AW_ERR; + } + + AWLOGD(&i2c->dev, "reg_addr = 0x%04x, reg_data = 0x%08x", reg_addr, reg_data); + } + + return AW_OK; +} + +void aw_sar_delay_ms(uint32_t ms) +{ + mdelay(ms); +} + diff --git a/include/linux/input/awinic/aw9610x.h b/include/linux/input/awinic/aw9610x.h new file mode 100644 index 000000000000..01f5b6dc2a69 --- /dev/null +++ b/include/linux/input/awinic/aw9610x.h @@ -0,0 +1,582 @@ +#ifndef _AW9610X_H_ +#define _AW9610X_H_ +#include "aw_sar_type.h" + +//#define AW9610X_TVS_ABNORMAL_CAIL +#define AW9610X_AOT_SCAN_OVER_CNT (32) + +#define AW9610X_CHIP_ID (0xa961) +#define AW9610x_DATA_PROCESS_FACTOR (1024) +#define AW_CHIP_AW9610XA (0x03000b00) +#define AW9610X_CPU_WORK_MASK (1) + +#define AW9610X_SAR_VCC_MIN_UV (1700000) +#define AW9610X_SAR_VCC_MAX_UV (3600000) + +#define AW_REG_IRQEN_CLOSE (0) +#define AW_REG_IRQSRC_AOT_OVER_BIT (3) +#define REG_IRQSRC_SCAN_OVER_BIT (4) +#define REG_REG_WST_SLEEP_MODE (0x3) +#define AW9610X_AOT_OVER_DELAY_MAX_MS (6000) +#define AW9610X_AOT_MASK (0x3f) +#define AW9610X_AOT_BIT (8) +#define AW9610X_REG_OFFSET_STEP (4) + +enum aw9610x_sar_vers { + AW9610X = 2, + AW9610XA = 6, + AW9610XB = 0xa, +}; + +enum aw9610x_operation_mode { + AW9610X_ACTIVE_MODE = 1, + AW9610X_SLEEP_MODE, + AW9610X_DEEPSLEEP_MODE, + AW9610XB_DEEPSLEEP_MODE, +}; + +/********************************************** +*spereg addr offset +**********************************************/ +enum aw9610x_spereg_addr_offset { + AW_CL1SPE_CALI_OS = 20, + AW_CL1SPE_DEAL_OS = 60, + AW_CL2SPE_CALI_OS = 4, + AW_CL2SPE_DEAL_OS = 4, +}; + + +/********************************************** + *the flag of i2c read/write + **********************************************/ +enum aw9610x_function_flag { + AW9610X_FUNC_OFF, + AW9610X_FUNC_ON, +}; + +/********************************************** +* mutiple sar define +**********************************************/ +enum aw9610x_multiple_sar { + AW_SAR0, + AW_SAR1, + AW_SAR_MAX, +}; + +#define AW9610X_CHANNEL_MAX (6) + +enum aw9610x_irq_trigger_position { + AW9610X_FAR, + AW9610X_TRIGGER_TH0, + AW9610X_TRIGGER_TH1 = 0x03, + AW9610X_TRIGGER_TH2 = 0x07, + AW9610X_TRIGGER_TH3 = 0x0f, +}; + +struct aw_i2c_package { + uint8_t addr_bytes; + uint8_t data_bytes; + uint8_t reg_num; + uint8_t init_addr[4]; + uint8_t *p_reg_data; +}; + +struct aw9610x { + uint8_t vers; + uint8_t channel; + uint32_t irq_status; + uint8_t chip_name[9]; + uint8_t chip_type[9]; + bool satu_release; + + struct aw_i2c_package aw_i2c_package; + + uint8_t satu_flag[6]; + uint32_t satu_data[6]; +}; + +/******************************************** +* Register List +********************************************/ +#define AFE_BASE_ADDR (0x0000) +#define DSP_BASE_ADDR (0x0000) +#define STAT_BASE_ADDR (0x0000) +#define SFR_BASE_ADDR (0x0000) +#define DATA_BASE_ADDR (0x0000) +/* registers list */ +//AW96105A_UI_REGISTER_AFE MAP +#define REG_SCANCTRL0 ((0x0000) + AFE_BASE_ADDR) +#define REG_SCANCTRL1 ((0x0004) + AFE_BASE_ADDR) +#define REG_AFECFG0_CH0 ((0x0010) + AFE_BASE_ADDR) +#define REG_AFECFG1_CH0 ((0x0014) + AFE_BASE_ADDR) +#define REG_AFECFG3_CH0 ((0x001C) + AFE_BASE_ADDR) +#define REG_AFECFG4_CH0 ((0x0020) + AFE_BASE_ADDR) +#define REG_AFECFG0_CH1 ((0x0024) + AFE_BASE_ADDR) +#define REG_AFECFG1_CH1 ((0x0028) + AFE_BASE_ADDR) +#define REG_AFECFG3_CH1 ((0x0030) + AFE_BASE_ADDR) +#define REG_AFECFG4_CH1 ((0x0034) + AFE_BASE_ADDR) +#define REG_AFECFG0_CH2 ((0x0038) + AFE_BASE_ADDR) +#define REG_AFECFG1_CH2 ((0x003C) + AFE_BASE_ADDR) +#define REG_AFECFG3_CH2 ((0x0044) + AFE_BASE_ADDR) +#define REG_AFECFG4_CH2 ((0x0048) + AFE_BASE_ADDR) +#define REG_AFECFG0_CH3 ((0x004C) + AFE_BASE_ADDR) +#define REG_AFECFG1_CH3 ((0x0050) + AFE_BASE_ADDR) +#define REG_AFECFG3_CH3 ((0x0058) + AFE_BASE_ADDR) +#define REG_AFECFG4_CH3 ((0x005C) + AFE_BASE_ADDR) +#define REG_AFECFG0_CH4 ((0x0060) + AFE_BASE_ADDR) +#define REG_AFECFG1_CH4 ((0x0064) + AFE_BASE_ADDR) +#define REG_AFECFG3_CH4 ((0x006C) + AFE_BASE_ADDR) +#define REG_AFECFG4_CH4 ((0x0070) + AFE_BASE_ADDR) +#define REG_AFECFG0_CH5 ((0x0074) + AFE_BASE_ADDR) +#define REG_AFECFG1_CH5 ((0x0078) + AFE_BASE_ADDR) +#define REG_AFECFG3_CH5 ((0x0080) + AFE_BASE_ADDR) +#define REG_AFECFG4_CH5 ((0x0084) + AFE_BASE_ADDR) + +/* registers list */ +//AW96105A_UI_REGISTER_DSP MAP +#define REG_DSPCFG0_CH0 ((0x00A0) + DSP_BASE_ADDR) +#define REG_DSPCFG1_CH0 ((0x00A4) + DSP_BASE_ADDR) +#define REG_BLFILT_CH0 ((0x00A8) + DSP_BASE_ADDR) +#define REG_PROXCTRL_CH0 ((0x00B0) + DSP_BASE_ADDR) +#define REG_BLRSTRNG_CH0 ((0x00B4) + DSP_BASE_ADDR) +#define REG_PROXTH0_CH0 ((0x00B8) + DSP_BASE_ADDR) +#define REG_PROXTH1_CH0 ((0x00BC) + DSP_BASE_ADDR) +#define REG_PROXTH2_CH0 ((0x00C0) + DSP_BASE_ADDR) +#define REG_PROXTH3_CH0 ((0x00C4) + DSP_BASE_ADDR) +#define REG_STDDET_CH0 ((0x00C8) + DSP_BASE_ADDR) +#define REG_INITPROX0_CH0 ((0x00CC) + DSP_BASE_ADDR) +#define REG_INITPROX1_CH0 ((0x00D0) + DSP_BASE_ADDR) +#define REG_DATAOFFSET_CH0 ((0x00D4) + DSP_BASE_ADDR) +#define REG_AOTTAR_CH0 ((0x00D8) + DSP_BASE_ADDR) +#define REG_DSPCFG0_CH1 ((0x00DC) + DSP_BASE_ADDR) +#define REG_DSPCFG1_CH1 ((0x00E0) + DSP_BASE_ADDR) +#define REG_BLFILT_CH1 ((0x00E4) + DSP_BASE_ADDR) +#define REG_PROXCTRL_CH1 ((0x00EC) + DSP_BASE_ADDR) +#define REG_BLRSTRNG_CH1 ((0x00F0) + DSP_BASE_ADDR) +#define REG_PROXTH0_CH1 ((0x00F4) + DSP_BASE_ADDR) +#define REG_PROXTH1_CH1 ((0x00F8) + DSP_BASE_ADDR) +#define REG_PROXTH2_CH1 ((0x00FC) + DSP_BASE_ADDR) +#define REG_PROXTH3_CH1 ((0x0100) + DSP_BASE_ADDR) +#define REG_STDDET_CH1 ((0x0104) + DSP_BASE_ADDR) +#define REG_INITPROX0_CH1 ((0x0108) + DSP_BASE_ADDR) +#define REG_INITPROX1_CH1 ((0x010C) + DSP_BASE_ADDR) +#define REG_RAWOFFSET_CH1 ((0x0110) + DSP_BASE_ADDR) +#define REG_AOTTAR_CH1 ((0x0114) + DSP_BASE_ADDR) +#define REG_DSPCFG0_CH2 ((0x0118) + DSP_BASE_ADDR) +#define REG_DSPCFG1_CH2 ((0x011C) + DSP_BASE_ADDR) +#define REG_BLFILT_CH2 ((0x0120) + DSP_BASE_ADDR) +#define REG_PROXCTRL_CH2 ((0x0128) + DSP_BASE_ADDR) +#define REG_BLRSTRNG_CH2 ((0x012C) + DSP_BASE_ADDR) +#define REG_PROXTH0_CH2 ((0x0130) + DSP_BASE_ADDR) +#define REG_PROXTH1_CH2 ((0x0134) + DSP_BASE_ADDR) +#define REG_PROXTH2_CH2 ((0x0138) + DSP_BASE_ADDR) +#define REG_PROXTH3_CH2 ((0x013C) + DSP_BASE_ADDR) +#define REG_STDDET_CH2 ((0x0140) + DSP_BASE_ADDR) +#define REG_INITPROX0_CH2 ((0x0144) + DSP_BASE_ADDR) +#define REG_INITPROX1_CH2 ((0x0148) + DSP_BASE_ADDR) +#define REG_DATAOFFSET_CH2 ((0x014C) + DSP_BASE_ADDR) +#define REG_AOTTAR_CH2 ((0x0150) + DSP_BASE_ADDR) +#define REG_DSPCFG0_CH3 ((0x0154) + DSP_BASE_ADDR) +#define REG_DSPCFG1_CH3 ((0x0158) + DSP_BASE_ADDR) +#define REG_BLFILT_CH3 ((0x015C) + DSP_BASE_ADDR) +#define REG_PROXCTRL_CH3 ((0x0164) + DSP_BASE_ADDR) +#define REG_BLRSTRNG_CH3 ((0x0168) + DSP_BASE_ADDR) +#define REG_PROXTH0_CH3 ((0x016C) + DSP_BASE_ADDR) +#define REG_PROXTH1_CH3 ((0x0170) + DSP_BASE_ADDR) +#define REG_PROXTH2_CH3 ((0x0174) + DSP_BASE_ADDR) +#define REG_PROXTH3_CH3 ((0x0178) + DSP_BASE_ADDR) +#define REG_STDDET_CH3 ((0x017C) + DSP_BASE_ADDR) +#define REG_INITPROX0_CH3 ((0x0180) + DSP_BASE_ADDR) +#define REG_INITPROX1_CH3 ((0x0184) + DSP_BASE_ADDR) +#define REG_DATAOFFSET_CH3 ((0x0188) + DSP_BASE_ADDR) +#define REG_AOTTAR_CH3 ((0x018C) + DSP_BASE_ADDR) +#define REG_DSPCFG0_CH4 ((0x0190) + DSP_BASE_ADDR) +#define REG_DSPCFG1_CH4 ((0x0194) + DSP_BASE_ADDR) +#define REG_BLFILT_CH4 ((0x0198) + DSP_BASE_ADDR) +#define REG_PROXCTRL_CH4 ((0x01A0) + DSP_BASE_ADDR) +#define REG_BLRSTRNG_CH4 ((0x01A4) + DSP_BASE_ADDR) +#define REG_PROXTH0_CH4 ((0x01A8) + DSP_BASE_ADDR) +#define REG_PROXTH1_CH4 ((0x01AC) + DSP_BASE_ADDR) +#define REG_PROXTH2_CH4 ((0x01B0) + DSP_BASE_ADDR) +#define REG_PROXTH3_CH4 ((0x01B4) + DSP_BASE_ADDR) +#define REG_STDDET_CH4 ((0x01B8) + DSP_BASE_ADDR) +#define REG_INITPROX0_CH4 ((0x01BC) + DSP_BASE_ADDR) +#define REG_INITPROX1_CH4 ((0x01C0) + DSP_BASE_ADDR) +#define REG_DATAOFFSET_CH4 ((0x01C4) + DSP_BASE_ADDR) +#define REG_AOTTAR_CH4 ((0x01C8) + DSP_BASE_ADDR) +#define REG_DSPCFG0_CH5 ((0x01CC) + DSP_BASE_ADDR) +#define REG_DSPCFG1_CH5 ((0x01D0) + DSP_BASE_ADDR) +#define REG_BLFILT_CH5 ((0x01D4) + DSP_BASE_ADDR) +#define REG_PROXCTRL_CH5 ((0x01DC) + DSP_BASE_ADDR) +#define REG_BLRSTRNG_CH5 ((0x01E0) + DSP_BASE_ADDR) +#define REG_PROXTH0_CH5 ((0x01E4) + DSP_BASE_ADDR) +#define REG_PROXTH1_CH5 ((0x01E8) + DSP_BASE_ADDR) +#define REG_PROXTH2_CH5 ((0x01EC) + DSP_BASE_ADDR) +#define REG_PROXTH3_CH5 ((0x01F0) + DSP_BASE_ADDR) +#define REG_STDDET_CH5 ((0x01F4) + DSP_BASE_ADDR) +#define REG_INITPROX0_CH5 ((0x01F8) + DSP_BASE_ADDR) +#define REG_INITPROX1_CH5 ((0x01FC) + DSP_BASE_ADDR) +#define REG_DATAOFFSET_CH5 ((0x0200) + DSP_BASE_ADDR) +#define REG_AOTTAR_CH5 ((0x0204) + DSP_BASE_ADDR) +#define REG_ATCCR0 ((0x0208) + DSP_BASE_ADDR) +#define REG_ATCCR1 ((0x020C) + DSP_BASE_ADDR) + +/* registers list */ +//AW96105A_UI_REGISTER_STAT MAP +#define REG_FWVER ((0x0088) + STAT_BASE_ADDR) +#define REG_WST ((0x008C) + STAT_BASE_ADDR) +#define REG_STAT0 ((0x0090) + STAT_BASE_ADDR) +#define REG_STAT1 ((0x0094) + STAT_BASE_ADDR) +#define REG_STAT2 ((0x0098) + STAT_BASE_ADDR) +#define REG_CHINTEN ((0x009C) + STAT_BASE_ADDR) + +/* registers list */ +//AW96105A_UI_REGISTER_SFR MAP +#define REG_CMD ((0xF008) + SFR_BASE_ADDR) +#define REG_IRQSRC ((0xF080) + SFR_BASE_ADDR) +#define REG_IRQEN ((0xF084) + SFR_BASE_ADDR) +#define REG_I2CADDR ((0xF0F0) + SFR_BASE_ADDR) +#define REG_OSCEN ((0xFF00) + SFR_BASE_ADDR) +#define REG_RESET ((0xFF0C) + SFR_BASE_ADDR) +#define REG_CHIPID ((0xFF10) + SFR_BASE_ADDR) + +/* registers list */ +//AW96105A_UI_REGISTER_DATA MAP +#define REG_COMP_CH0 ((0x0210) + DATA_BASE_ADDR) +#define REG_COMP_CH1 ((0x0214) + DATA_BASE_ADDR) +#define REG_COMP_CH2 ((0x0218) + DATA_BASE_ADDR) +#define REG_COMP_CH3 ((0x021C) + DATA_BASE_ADDR) +#define REG_COMP_CH4 ((0x0220) + DATA_BASE_ADDR) +#define REG_COMP_CH5 ((0x0224) + DATA_BASE_ADDR) +#define REG_BASELINE_CH0 ((0x0228) + DATA_BASE_ADDR) +#define REG_BASELINE_CH1 ((0x022C) + DATA_BASE_ADDR) +#define REG_BASELINE_CH2 ((0x0230) + DATA_BASE_ADDR) +#define REG_BASELINE_CH3 ((0x0234) + DATA_BASE_ADDR) +#define REG_BASELINE_CH4 ((0x0238) + DATA_BASE_ADDR) +#define REG_BASELINE_CH5 ((0x023C) + DATA_BASE_ADDR) +#define REG_DIFF_CH0 ((0x0240) + DATA_BASE_ADDR) +#define REG_DIFF_CH1 ((0x0244) + DATA_BASE_ADDR) +#define REG_DIFF_CH2 ((0x0248) + DATA_BASE_ADDR) +#define REG_DIFF_CH3 ((0x024C) + DATA_BASE_ADDR) +#define REG_DIFF_CH4 ((0x0250) + DATA_BASE_ADDR) +#define REG_DIFF_CH5 ((0x0254) + DATA_BASE_ADDR) +#define REG_FWVER2 ((0x0410) + DATA_BASE_ADDR) + +struct aw_reg_data { + unsigned char rw; + unsigned short reg; +}; +/******************************************** + * Register Access + *******************************************/ +#define REG_NONE_ACCESS (0) +#define REG_RD_ACCESS (1 << 0) +#define REG_WR_ACCESS (1 << 1) + +static const struct aw_reg_data g_aw9610x_reg_access[] = { + //AFE MAP + { .reg = REG_SCANCTRL0, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_SCANCTRL1, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_AFECFG0_CH0, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_AFECFG1_CH0, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_AFECFG3_CH0, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_AFECFG4_CH0, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_AFECFG0_CH1, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_AFECFG1_CH1, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_AFECFG3_CH1, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_AFECFG4_CH1, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_AFECFG0_CH2, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_AFECFG1_CH2, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_AFECFG3_CH2, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_AFECFG4_CH2, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_AFECFG0_CH3, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_AFECFG1_CH3, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_AFECFG3_CH3, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_AFECFG4_CH3, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_AFECFG0_CH4, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_AFECFG1_CH4, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_AFECFG3_CH4, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_AFECFG4_CH4, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_AFECFG0_CH5, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_AFECFG1_CH5, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_AFECFG3_CH5, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_AFECFG4_CH5, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + + //DSP MAP + { .reg = REG_DSPCFG0_CH0, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_DSPCFG1_CH0, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_BLFILT_CH0, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_PROXCTRL_CH0, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_BLRSTRNG_CH0, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_PROXTH0_CH0, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_PROXTH1_CH0, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_PROXTH2_CH0, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_PROXTH3_CH0, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_STDDET_CH0, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_INITPROX0_CH0, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_INITPROX1_CH0, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_DATAOFFSET_CH0, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_AOTTAR_CH0, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_DSPCFG0_CH1, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_DSPCFG1_CH1, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_BLFILT_CH1, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_PROXCTRL_CH1, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_BLRSTRNG_CH1, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_PROXTH0_CH1, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_PROXTH1_CH1, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_PROXTH2_CH1, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_PROXTH3_CH1, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_STDDET_CH1, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_INITPROX0_CH1, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_INITPROX1_CH1, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_RAWOFFSET_CH1, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_AOTTAR_CH1, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_DSPCFG0_CH2, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_DSPCFG1_CH2, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_BLFILT_CH2, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_PROXCTRL_CH2, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_BLRSTRNG_CH2, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_PROXTH0_CH2, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_PROXTH1_CH2, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_PROXTH2_CH2, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_PROXTH3_CH2, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_STDDET_CH2, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_INITPROX0_CH2, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_INITPROX1_CH2, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_DATAOFFSET_CH2, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_AOTTAR_CH2, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_DSPCFG0_CH3, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_DSPCFG1_CH3, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_BLFILT_CH3, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_PROXCTRL_CH3, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_BLRSTRNG_CH3, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_PROXTH0_CH3, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_PROXTH1_CH3, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_PROXTH2_CH3, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_PROXTH3_CH3, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_STDDET_CH3, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_INITPROX0_CH3, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_INITPROX1_CH3, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_DATAOFFSET_CH3, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_AOTTAR_CH3, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_DSPCFG0_CH4, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_DSPCFG1_CH4, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_BLFILT_CH4, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_PROXCTRL_CH4, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_BLRSTRNG_CH4, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_PROXTH0_CH4, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_PROXTH1_CH4, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_PROXTH2_CH4, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_PROXTH3_CH4, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_STDDET_CH4, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_INITPROX0_CH4, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_INITPROX1_CH4, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_DATAOFFSET_CH4, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_AOTTAR_CH4, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_DSPCFG0_CH5, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_DSPCFG1_CH5, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_BLFILT_CH5, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_PROXCTRL_CH5, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_BLRSTRNG_CH5, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_PROXTH0_CH5, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_PROXTH1_CH5, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_PROXTH2_CH5, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_PROXTH3_CH5, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_STDDET_CH5, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_INITPROX0_CH5, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_INITPROX1_CH5, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_DATAOFFSET_CH5, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_AOTTAR_CH5, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_ATCCR0, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_ATCCR1, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + + //STAT MAP + { .reg = REG_FWVER, .rw = REG_RD_ACCESS, }, + { .reg = REG_WST, .rw = REG_RD_ACCESS, }, + { .reg = REG_STAT0, .rw = REG_RD_ACCESS, }, + { .reg = REG_STAT1, .rw = REG_RD_ACCESS, }, + { .reg = REG_STAT2, .rw = REG_RD_ACCESS, }, + { .reg = REG_CHINTEN, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + + //SFR MAP + { .reg = REG_CMD, .rw = REG_NONE_ACCESS, }, + { .reg = REG_IRQSRC, .rw = REG_RD_ACCESS, }, + { .reg = REG_IRQEN, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_I2CADDR, .rw = REG_RD_ACCESS, }, + { .reg = REG_OSCEN, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_RESET, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_CHIPID, .rw = REG_RD_ACCESS, }, + + //DATA MAP + { .reg = REG_COMP_CH0, .rw = REG_RD_ACCESS, }, + { .reg = REG_COMP_CH1, .rw = REG_RD_ACCESS, }, + { .reg = REG_COMP_CH2, .rw = REG_RD_ACCESS, }, + { .reg = REG_COMP_CH3, .rw = REG_RD_ACCESS, }, + { .reg = REG_COMP_CH4, .rw = REG_RD_ACCESS, }, + { .reg = REG_COMP_CH5, .rw = REG_RD_ACCESS, }, + { .reg = REG_BASELINE_CH0, .rw = REG_RD_ACCESS, }, + { .reg = REG_BASELINE_CH1, .rw = REG_RD_ACCESS, }, + { .reg = REG_BASELINE_CH2, .rw = REG_RD_ACCESS, }, + { .reg = REG_BASELINE_CH3, .rw = REG_RD_ACCESS, }, + { .reg = REG_BASELINE_CH4, .rw = REG_RD_ACCESS, }, + { .reg = REG_BASELINE_CH5, .rw = REG_RD_ACCESS, }, + { .reg = REG_DIFF_CH0, .rw = REG_RD_ACCESS, }, + { .reg = REG_DIFF_CH1, .rw = REG_RD_ACCESS, }, + { .reg = REG_DIFF_CH2, .rw = REG_RD_ACCESS, }, + { .reg = REG_DIFF_CH3, .rw = REG_RD_ACCESS, }, + { .reg = REG_DIFF_CH4, .rw = REG_RD_ACCESS, }, + { .reg = REG_DIFF_CH5, .rw = REG_RD_ACCESS, }, + { .reg = REG_FWVER2, .rw = REG_RD_ACCESS, }, +}; + + +/****************************************************** +* Register Detail +******************************************************/ +const static uint32_t aw9610x_reg_default[] = { + 0x0000, 0x00003f3f, + 0x0004, 0x00000064, + 0x0008, 0x0017c11e, + 0x000c, 0x05000000, + 0x0010, 0x00093ffd, + 0x0014, 0x19240009, + 0x0018, 0xd81c0207, + 0x001c, 0xff000000, + 0x0020, 0x00241900, + 0x0024, 0x00093ff7, + 0x0028, 0x58020009, + 0x002c, 0xd81c0207, + 0x0030, 0xff000000, + 0x0034, 0x00025800, + 0x0038, 0x00093fdf, + 0x003c, 0x7d3b0009, + 0x0040, 0xd81c0207, + 0x0044, 0xff000000, + 0x0048, 0x003b7d00, + 0x004c, 0x00093f7f, + 0x0050, 0xe9310009, + 0x0054, 0xd81c0207, + 0x0058, 0xff000000, + 0x005c, 0x0031e900, + 0x0060, 0x00093dff, + 0x0064, 0x1a0c0009, + 0x0068, 0xd81c0207, + 0x006c, 0xff000000, + 0x0070, 0x000c1a00, + 0x0074, 0x80093fff, + 0x0078, 0x043d0009, + 0x007c, 0xd81c0207, + 0x0080, 0xff000000, + 0x0084, 0x003d0400, + 0x00a0, 0xe6400000, + 0x00a4, 0x00000000, + 0x00a8, 0x010408d2, + 0x00ac, 0x00000000, + 0x00b0, 0x00000000, + 0x00b8, 0x00005fff, + 0x00bc, 0x00000000, + 0x00c0, 0x00000000, + 0x00c4, 0x00000000, + 0x00c8, 0x00000000, + 0x00cc, 0x00000000, + 0x00d0, 0x00000000, + 0x00d4, 0x00000000, + 0x00d8, 0x00000000, + 0x00dc, 0xe6447800, + 0x00e0, 0x78000000, + 0x00e4, 0x010408d2, + 0x00e8, 0x00000000, + 0x00ec, 0x00000000, + 0x00f4, 0x00005fff, + 0x00f8, 0x00000000, + 0x00fc, 0x00000000, + 0x0100, 0x00000000, + 0x0104, 0x00000000, + 0x0108, 0x00000000, + 0x010c, 0x02000000, + 0x0110, 0x00000000, + 0x0114, 0x00000000, + 0x0118, 0xe6447800, + 0x011c, 0x78000000, + 0x0120, 0x010408d2, + 0x0124, 0x00000000, + 0x0128, 0x00000000, + 0x0130, 0x00005fff, + 0x0134, 0x00000000, + 0x0138, 0x00000000, + 0x013c, 0x00000000, + 0x0140, 0x00000000, + 0x0144, 0x00000000, + 0x0148, 0x02000000, + 0x014c, 0x00000000, + 0x0150, 0x00000000, + 0x0154, 0xe6447800, + 0x0158, 0x78000000, + 0x015c, 0x010408d2, + 0x0160, 0x00000000, + 0x0164, 0x00000000, + 0x016c, 0x00005fff, + 0x0170, 0x00000000, + 0x0174, 0x00000000, + 0x0178, 0x00000000, + 0x017c, 0x00000000, + 0x0180, 0x00000000, + 0x0184, 0x02000000, + 0x0188, 0x00000000, + 0x018c, 0x00000000, + 0x0190, 0xe6447800, + 0x0194, 0x78000000, + 0x0198, 0x010408d2, + 0x019c, 0x00000000, + 0x01a0, 0x00000000, + 0x01a8, 0x00005fff, + 0x01ac, 0x00000000, + 0x01b0, 0x00000000, + 0x01b4, 0x00000000, + 0x01b8, 0x00000000, + 0x01bc, 0x00000000, + 0x01c0, 0x02000000, + 0x01c4, 0x00000000, + 0x01c8, 0x00000000, + 0x01cc, 0xe6407800, + 0x01d0, 0x78000000, + 0x01d4, 0x010408d2, + 0x01d8, 0x00000000, + 0x01dc, 0x00000000, + 0x01e4, 0x00005fff, + 0x01e8, 0x00000000, + 0x01ec, 0x00000000, + 0x01f0, 0x00000000, + 0x01f4, 0x00000000, + 0x01f8, 0x00000000, + 0x01fc, 0x02000000, + 0x0200, 0x00000000, + 0x0204, 0x00000000, + 0x0208, 0x00000008, + 0x020c, 0x0000000d, + 0x41fc, 0x00000000, + 0x4400, 0x00000000, + 0x4410, 0x00000000, + 0x4420, 0x00000000, + 0x4430, 0x00000000, + 0x4440, 0x00000000, + 0x4450, 0x00000000, + 0x4460, 0x00000000, + 0x4470, 0x00000000, + 0xf080, 0x00003018, + 0xf084, 0x00000fff, + 0xf800, 0x00000000, + 0xf804, 0x00002e00, + 0xf8d0, 0x00000001, + 0xf8d4, 0x00000000, + 0xff00, 0x00000301, + 0xff0c, 0x01000000, + 0xffe0, 0x00000000, + 0xfff4, 0x00004011, + 0x0090, 0x00000000, + 0x0094, 0x00000000, + 0x0098, 0x00000000, + 0x009c, 0x3f3f3f3f, +}; + +#endif diff --git a/include/linux/input/awinic/aw9620x.h b/include/linux/input/awinic/aw9620x.h new file mode 100644 index 000000000000..be74cb9c1d1b --- /dev/null +++ b/include/linux/input/awinic/aw9620x.h @@ -0,0 +1,453 @@ +#ifndef AW9620X_H_ +#define AW9620X_H_ +#include "aw_sar_type.h" + +#define AW9620X_CHANNEL_NUM_MAX (8) +#define AW9620X_FINE_ADJUST_STEP0 (165) +#define AW9620X_COARSE_ADJUST_STEP0 (9900) +#define AW9620X_FINE_ADJUST_STEP1 (330) +#define AW9620X_COARSE_ADJUST_STEP1 (19800) +#define AW9620X_CFG_REG_STEP (0x8c) +#define AW9620X_PARA_TIMES (10000) +#define AW9620X_PROT_STOP_WAIT_IRQ_CYCLES (100) +#define AW9620X_REG_UPDATA_DIS_MASK (0x00ffffff) +#define AW9620X_AFECFG3_CVMULTUALMOD (11) +#define AW9620X_AFECFG3_CVOFF2X (10) +#define AW9620X_REMOVE_FLOAT_COEF (1024) +#define AW9620X_REG_MCFG_DELAY_MS (20) + +#define AW9620X_REG_RSTNALL_VAL (0x3c) +#define AW9620X_POWER_ON_DELAY_MS (25) +#define AW9620X_REG_STEP (0x8c) +#define AW9620X_REMOVE_FLOAT_COEF (1024) + +#define AW9620X_SAR_VCC_MIN_UV (1700000) +#define AW9620X_SAR_VCC_MAX_UV (3600000) +#define AW9320X_SRAM_ERROR_CODE (0x1c00) + +enum aw_sar_irq_trigger_position { + AW9620X_TRIGGER_FAR, + AW9620X_TRIGGER_TH0, + AW9620X_TRIGGER_TH1 = 0x03, +}; + +enum AW9620X_CHIP_ID_VALUE { + AW96203CSR_CHIP_ID = 0x20226203, + AW96205DNR_CHIP_ID = 0x20226205, + AW96208CSR_CHIP_ID = 0x20226208, +}; + +enum AW9620X_OPERAION_MODE { + AW9620X_ACTIVE_MODE = 1, + AW9620X_SLEEP_MODE, + AW9620X_DEEPSLEEP_MODE, +}; + +/******************************************** +* Register List +********************************************/ +#define AFE_BASE_ADDR (0x1A00) +#define DSP_BASE_ADDR (0x1A00) +#define STAT_BASE_ADDR (0x1A00) +#define DATA_BASE_ADDR (0x1A00) +#define SFR_BASE_ADDR (0x0000) +/* registers list */ +//96208_0917_AFE MAP +#define REG_SCANCTRL0 ((0x0000) + AFE_BASE_ADDR) +#define REG_SCANCTRL1 ((0x0004) + AFE_BASE_ADDR) +#define REG_AFECFG0_CH0 ((0x0040) + AFE_BASE_ADDR) +#define REG_AFECFG1_CH0 ((0x0044) + AFE_BASE_ADDR) +#define REG_AFECFG3_CH0 ((0x004C) + AFE_BASE_ADDR) +#define REG_AFECFG0_CH1 ((0x00CC) + AFE_BASE_ADDR) +#define REG_AFECFG1_CH1 ((0x00D0) + AFE_BASE_ADDR) +#define REG_AFECFG3_CH1 ((0x00D8) + AFE_BASE_ADDR) +#define REG_AFECFG0_CH2 ((0x0158) + AFE_BASE_ADDR) +#define REG_AFECFG1_CH2 ((0x015C) + AFE_BASE_ADDR) +#define REG_AFECFG3_CH2 ((0x0164) + AFE_BASE_ADDR) +#define REG_AFECFG0_CH3 ((0x01E4) + AFE_BASE_ADDR) +#define REG_AFECFG1_CH3 ((0x01E8) + AFE_BASE_ADDR) +#define REG_AFECFG3_CH3 ((0x01F0) + AFE_BASE_ADDR) +#define REG_AFECFG0_CH4 ((0x0270) + AFE_BASE_ADDR) +#define REG_AFECFG1_CH4 ((0x0274) + AFE_BASE_ADDR) +#define REG_AFECFG3_CH4 ((0x027C) + AFE_BASE_ADDR) +#define REG_AFECFG0_CH5 ((0x02FC) + AFE_BASE_ADDR) +#define REG_AFECFG1_CH5 ((0x0300) + AFE_BASE_ADDR) +#define REG_AFECFG3_CH5 ((0x0308) + AFE_BASE_ADDR) +#define REG_AFECFG0_CH6 ((0x0388) + AFE_BASE_ADDR) +#define REG_AFECFG1_CH6 ((0x038C) + AFE_BASE_ADDR) +#define REG_AFECFG3_CH6 ((0x0394) + AFE_BASE_ADDR) +#define REG_AFECFG0_CH7 ((0x0414) + AFE_BASE_ADDR) +#define REG_AFECFG1_CH7 ((0x0418) + AFE_BASE_ADDR) +#define REG_AFECFG3_CH7 ((0x0420) + AFE_BASE_ADDR) + +/* registers list */ +//96208_0917_DSP MAP +#define REG_FILTCTRL0_CH0 ((0x0050) + DSP_BASE_ADDR) +#define REG_BLFILT_CH0 ((0x0078) + DSP_BASE_ADDR) +#define REG_BLERRAOT_CH0 ((0x008C) + DSP_BASE_ADDR) +#define REG_PROXCTRL_CH0 ((0x0090) + DSP_BASE_ADDR) +#define REG_PROXTH0_CH0 ((0x0094) + DSP_BASE_ADDR) +#define REG_PROXTH1_CH0 ((0x0098) + DSP_BASE_ADDR) +#define REG_AOTTAR_CH0 ((0x009C) + DSP_BASE_ADDR) +#define REG_FILTCTRL0_CH1 ((0x00DC) + DSP_BASE_ADDR) +#define REG_BLFILT_CH1 ((0x0104) + DSP_BASE_ADDR) +#define REG_BLERRAOT_CH1 ((0x0118) + DSP_BASE_ADDR) +#define REG_PROXCTRL_CH1 ((0x011C) + DSP_BASE_ADDR) +#define REG_PROXTH0_CH1 ((0x0120) + DSP_BASE_ADDR) +#define REG_PROXTH1_CH1 ((0x0124) + DSP_BASE_ADDR) +#define REG_AOTTAR_CH1 ((0x0128) + DSP_BASE_ADDR) +#define REG_FILTCTRL0_CH2 ((0x0168) + DSP_BASE_ADDR) +#define REG_BLFILT_CH2 ((0x0190) + DSP_BASE_ADDR) +#define REG_BLERRAOT_CH2 ((0x01A4) + DSP_BASE_ADDR) +#define REG_PROXCTRL_CH2 ((0x01A8) + DSP_BASE_ADDR) +#define REG_PROXTH0_CH2 ((0x01AC) + DSP_BASE_ADDR) +#define REG_PROXTH1_CH2 ((0x01B0) + DSP_BASE_ADDR) +#define REG_AOTTAR_CH2 ((0x01B4) + DSP_BASE_ADDR) +#define REG_FILTCTRL0_CH3 ((0x01F4) + DSP_BASE_ADDR) +#define REG_BLFILT_CH3 ((0x021C) + DSP_BASE_ADDR) +#define REG_BLERRAOT_CH3 ((0x0230) + DSP_BASE_ADDR) +#define REG_PROXCTRL_CH3 ((0x0234) + DSP_BASE_ADDR) +#define REG_PROXTH0_CH3 ((0x0238) + DSP_BASE_ADDR) +#define REG_PROXTH1_CH3 ((0x023C) + DSP_BASE_ADDR) +#define REG_AOTTAR_CH3 ((0x0240) + DSP_BASE_ADDR) +#define REG_FILTCTRL0_CH4 ((0x0280) + DSP_BASE_ADDR) +#define REG_BLFILT_CH4 ((0x02A8) + DSP_BASE_ADDR) +#define REG_BLERRAOT_CH4 ((0x02BC) + DSP_BASE_ADDR) +#define REG_PROXCTRL_CH4 ((0x02C0) + DSP_BASE_ADDR) +#define REG_PROXTH0_CH4 ((0x02C4) + DSP_BASE_ADDR) +#define REG_PROXTH1_CH4 ((0x02C8) + DSP_BASE_ADDR) +#define REG_AOTTAR_CH4 ((0x02CC) + DSP_BASE_ADDR) +#define REG_FILTCTRL0_CH5 ((0x030C) + DSP_BASE_ADDR) +#define REG_BLFILT_CH5 ((0x0334) + DSP_BASE_ADDR) +#define REG_BLERRAOT_CH5 ((0x0348) + DSP_BASE_ADDR) +#define REG_PROXCTRL_CH5 ((0x034C) + DSP_BASE_ADDR) +#define REG_PROXTH0_CH5 ((0x0350) + DSP_BASE_ADDR) +#define REG_PROXTH1_CH5 ((0x0354) + DSP_BASE_ADDR) +#define REG_AOTTAR_CH5 ((0x0358) + DSP_BASE_ADDR) +#define REG_FILTCTRL0_CH6 ((0x0398) + DSP_BASE_ADDR) +#define REG_BLFILT_CH6 ((0x03C0) + DSP_BASE_ADDR) +#define REG_BLERRAOT_CH6 ((0x03D4) + DSP_BASE_ADDR) +#define REG_PROXCTRL_CH6 ((0x03D8) + DSP_BASE_ADDR) +#define REG_PROXTH0_CH6 ((0x03DC) + DSP_BASE_ADDR) +#define REG_PROXTH1_CH6 ((0x03E0) + DSP_BASE_ADDR) +#define REG_AOTTAR_CH6 ((0x03E4) + DSP_BASE_ADDR) +#define REG_FILTCTRL0_CH7 ((0x0424) + DSP_BASE_ADDR) +#define REG_BLFILT_CH7 ((0x044C) + DSP_BASE_ADDR) +#define REG_BLERRAOT_CH7 ((0x0460) + DSP_BASE_ADDR) +#define REG_PROXCTRL_CH7 ((0x0464) + DSP_BASE_ADDR) +#define REG_PROXTH0_CH7 ((0x0468) + DSP_BASE_ADDR) +#define REG_PROXTH1_CH7 ((0x046C) + DSP_BASE_ADDR) +#define REG_AOTTAR_CH7 ((0x0470) + DSP_BASE_ADDR) + +/* registers list */ +//96208_0917_STAT MAP +#define REG_FWVER ((0x000C) + STAT_BASE_ADDR) +#define REG_WST ((0x0010) + STAT_BASE_ADDR) +#define REG_STAT0 ((0x0014) + STAT_BASE_ADDR) +#define REG_STAT1 ((0x0018) + STAT_BASE_ADDR) + +/* registers list */ +//96208_0917_DATA MAP +#define REG_TEMPERATURE ((0x001C) + DATA_BASE_ADDR) +#define REG_BASELINE_CH0 ((0x00AC) + DATA_BASE_ADDR) +#define REG_DIFF_CH0 ((0x00B0) + DATA_BASE_ADDR) +#define REG_BASELINE_CH1 ((0x0138) + DATA_BASE_ADDR) +#define REG_DIFF_CH1 ((0x013C) + DATA_BASE_ADDR) +#define REG_BASELINE_CH2 ((0x01C4) + DATA_BASE_ADDR) +#define REG_DIFF_CH2 ((0x01C8) + DATA_BASE_ADDR) +#define REG_BASELINE_CH3 ((0x0250) + DATA_BASE_ADDR) +#define REG_DIFF_CH3 ((0x0254) + DATA_BASE_ADDR) +#define REG_BASELINE_CH4 ((0x02DC) + DATA_BASE_ADDR) +#define REG_DIFF_CH4 ((0x02E0) + DATA_BASE_ADDR) +#define REG_BASELINE_CH5 ((0x0368) + DATA_BASE_ADDR) +#define REG_DIFF_CH5 ((0x036C) + DATA_BASE_ADDR) +#define REG_BASELINE_CH6 ((0x03F4) + DATA_BASE_ADDR) +#define REG_DIFF_CH6 ((0x03F8) + DATA_BASE_ADDR) +#define REG_BASELINE_CH7 ((0x0480) + DATA_BASE_ADDR) +#define REG_DIFF_CH7 ((0x0484) + DATA_BASE_ADDR) + +/* registers list */ +//96208_0917_SFR MAP +#define REG_IRQSRC ((0x4410) + SFR_BASE_ADDR) +#define REG_IRQEN ((0x4414) + SFR_BASE_ADDR) +#define REG_I2CDEVID ((0x4440) + SFR_BASE_ADDR) +#define REG_CHIP_ID ((0xFF00) + SFR_BASE_ADDR) +#define REG_CHIPSTAT ((0xFF04) + SFR_BASE_ADDR) +#define REG_HOSTCTRL ((0xFF10) + SFR_BASE_ADDR) +#define REG_RSTNALL ((0xFF18) + SFR_BASE_ADDR) + +//driver user +#define REG_ACCESSEN ((0xFF20) + SFR_BASE_ADDR) +#define REG_MCFG ((0x4444) + SFR_BASE_ADDR) +#define REG_ISPGO ((0x4714) + SFR_BASE_ADDR) +#define REG_PMU_CFG ((0x4820) + SFR_BASE_ADDR) +#define REG_ARRAY2_EW_EN ((0x4794) + SFR_BASE_ADDR) +#define REG_ISPADR ((0x4704) + SFR_BASE_ADDR) +#define REG_ISPWDATA ((0x4708) + SFR_BASE_ADDR) +#define REG_ISPRDATA ((0x470C) + SFR_BASE_ADDR) +#define REG_ISPCMD ((0x4710) + SFR_BASE_ADDR) +#define REG_T_RCV ((0x472C) + SFR_BASE_ADDR) +#define REG_CMD ((0x4408) + SFR_BASE_ADDR) +#define REG_BOOT_LOADER_ACTIVE ((0x4748) + SFR_BASE_ADDR) + +#define REG_OPEN_APB_ACCESS_EN (0x3c00f091) +#define REG_SET_PMU_CFG (0x6) +#define REG_SET_BTROM_EW_EN (0x5a637955) +#define REG_ISP_CMD_CONFIG (0x0c) +#define REG_SET_ISP_GO (0x1) +#define REG_ENSET_PMU_CFG (0x4) +#define REG_ACCESS_MAIN_ARR (0x05) +#define REG_SET_T_RCV (0xf0) +#define REG_SET_T_RCV_EN (0x16) +#define REG_OPEN_REG_ACCESS_EN (0x3c00ffff) +#define REG_OPEN_MCFG_EN (0x10000) +#define REG_ENSET_BTROM_EW_EN (0x0) +#define REG_SET_MCFG00 (0x0) +#define REG_ISP_CMD_MAIN_ARR (0X03) +#define REG_HOSTCTRL_EN (0x1) +#define REG_ACCESSEN_OPEN (0x3c00F091) +#define REG_ACCESSEN_CLOSE (0x3c00f011) +#define AW_REG_FLASH_WAKE_UP (0x4700) +#define REG_UPDATA_DIS (0x4744) +#define AW_REG_FLASH_WAKE_UP_ON (0x110) +#define AW_REG_FLASH_WAKE_UP_OFF (0x102) + +#define AW_BT_HOST2CPU_TRIG_ONLINE_UPGRADE_CMD (0x14) + +#define AW_BT_STATE_INFO_ERR (0x1c00) +#define AW_BT_STATE_INFO_PST (0x1C04) +#define AW_BT_STATE_INFO_FLAG (0x1C08) +#define AW_BT_PROT_CMD_PACK_ADDR (0x1C10) +#define AW_BT_PROT_ACK_PACK_ADDR (0x1C14) +#define AW_BT_MESSAGE_MSG0 (0x1C20) +#define AW_BT_MESSAGE_MSG1 (0x1C24) +#define AW_BT_MESSAGE_MSG_FLAG (0x1C28) +#define AW_BT_VER_INF_VERSION (0x1C30) +#define AW_BT_VER_INF_DATE (0x1C34) +#define AW_BT_HOST2CPU_TRIG (0x4408) +#define AW_BTCPU2HOST_TRIG (0x4410) + +#define AW_SRAM_FIRST_DETECT (0x20000800) + +struct aw_reg_data { + unsigned char rw; + unsigned short reg; +}; +/******************************************** + * Register Access + *******************************************/ +#define REG_NONE_ACCESS (0) +#define REG_RD_ACCESS (1 << 0) +#define REG_WR_ACCESS (1 << 1) + +static const struct aw_reg_data g_aw9620x_reg_access[] = { + //AFE MAP + { .reg = REG_SCANCTRL0, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_SCANCTRL1, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_AFECFG0_CH0, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_AFECFG1_CH0, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_AFECFG3_CH0, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_AFECFG0_CH1, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_AFECFG1_CH1, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_AFECFG3_CH1, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_AFECFG0_CH2, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_AFECFG1_CH2, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_AFECFG3_CH2, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_AFECFG0_CH3, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_AFECFG1_CH3, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_AFECFG3_CH3, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_AFECFG0_CH4, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_AFECFG1_CH4, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_AFECFG3_CH4, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_AFECFG0_CH5, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_AFECFG1_CH5, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_AFECFG3_CH5, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_AFECFG0_CH6, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_AFECFG1_CH6, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_AFECFG3_CH6, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_AFECFG0_CH7, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_AFECFG1_CH7, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_AFECFG3_CH7, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + + //DSP MAP + { .reg = REG_FILTCTRL0_CH0, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_BLFILT_CH0, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_BLERRAOT_CH0, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_PROXCTRL_CH0, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_PROXTH0_CH0, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_PROXTH1_CH0, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_AOTTAR_CH0, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_FILTCTRL0_CH1, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_BLFILT_CH1, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_BLERRAOT_CH1, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_PROXCTRL_CH1, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_PROXTH0_CH1, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_PROXTH1_CH1, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_AOTTAR_CH1, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_FILTCTRL0_CH2, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_BLFILT_CH2, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_BLERRAOT_CH2, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_PROXCTRL_CH2, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_PROXTH0_CH2, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_PROXTH1_CH2, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_AOTTAR_CH2, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_FILTCTRL0_CH3, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_BLFILT_CH3, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_BLERRAOT_CH3, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_PROXCTRL_CH3, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_PROXTH0_CH3, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_PROXTH1_CH3, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_AOTTAR_CH3, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_FILTCTRL0_CH4, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_BLFILT_CH4, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_BLERRAOT_CH4, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_PROXCTRL_CH4, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_PROXTH0_CH4, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_PROXTH1_CH4, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_AOTTAR_CH4, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_FILTCTRL0_CH5, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_BLFILT_CH5, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_BLERRAOT_CH5, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_PROXCTRL_CH5, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_PROXTH0_CH5, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_PROXTH1_CH5, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_AOTTAR_CH5, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_FILTCTRL0_CH6, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_BLFILT_CH6, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_BLERRAOT_CH6, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_PROXCTRL_CH6, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_PROXTH0_CH6, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_PROXTH1_CH6, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_AOTTAR_CH6, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_FILTCTRL0_CH7, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_BLFILT_CH7, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_BLERRAOT_CH7, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_PROXCTRL_CH7, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_PROXTH0_CH7, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_PROXTH1_CH7, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_AOTTAR_CH7, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + + //STAT MAP + { .reg = REG_FWVER, .rw = REG_RD_ACCESS, }, + { .reg = REG_WST, .rw = REG_RD_ACCESS, }, + { .reg = REG_STAT0, .rw = REG_RD_ACCESS, }, + { .reg = REG_STAT1, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + + //DATA MAP + { .reg = REG_TEMPERATURE, .rw = REG_RD_ACCESS, }, + { .reg = REG_BASELINE_CH0, .rw = REG_RD_ACCESS, }, + { .reg = REG_DIFF_CH0, .rw = REG_RD_ACCESS, }, + { .reg = REG_BASELINE_CH1, .rw = REG_RD_ACCESS, }, + { .reg = REG_DIFF_CH1, .rw = REG_RD_ACCESS, }, + { .reg = REG_BASELINE_CH2, .rw = REG_RD_ACCESS, }, + { .reg = REG_DIFF_CH2, .rw = REG_RD_ACCESS, }, + { .reg = REG_BASELINE_CH3, .rw = REG_RD_ACCESS, }, + { .reg = REG_DIFF_CH3, .rw = REG_RD_ACCESS, }, + { .reg = REG_BASELINE_CH4, .rw = REG_RD_ACCESS, }, + { .reg = REG_DIFF_CH4, .rw = REG_RD_ACCESS, }, + { .reg = REG_BASELINE_CH5, .rw = REG_RD_ACCESS, }, + { .reg = REG_DIFF_CH5, .rw = REG_RD_ACCESS, }, + { .reg = REG_BASELINE_CH6, .rw = REG_RD_ACCESS, }, + { .reg = REG_DIFF_CH6, .rw = REG_RD_ACCESS, }, + { .reg = REG_BASELINE_CH7, .rw = REG_RD_ACCESS, }, + { .reg = REG_DIFF_CH7, .rw = REG_RD_ACCESS, }, + + //SFR MAP + { .reg = REG_IRQSRC, .rw = REG_RD_ACCESS, }, + { .reg = REG_IRQEN, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_I2CDEVID, .rw = REG_RD_ACCESS, }, + { .reg = REG_CHIP_ID, .rw = REG_RD_ACCESS, }, + { .reg = REG_CHIPSTAT, .rw = REG_RD_ACCESS, }, + { .reg = REG_HOSTCTRL, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_RSTNALL, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, +}; + +//aw96208 reg config +static const uint32_t aw9620x_reg_default[] = { + 0x1A00, 0x003FFFFF, + 0x1A04, 0x00000032, + 0x1A40, 0x09500001, + 0x1A44, 0x3F000000, + 0x1A4C, 0x00000000, + 0x1ACC, 0x09500004, + 0x1AD0, 0x3F000000, + 0x1AD8, 0x00000000, + 0x1B58, 0x09500010, + 0x1B5C, 0x3F000000, + 0x1B64, 0x00000000, + 0x1BE4, 0x09500040, + 0x1BE8, 0x3F000000, + 0x1BF0, 0x00000000, + 0x1C70, 0x09500100, + 0x1C74, 0x3F000000, + 0x1C7C, 0x00000000, + 0x1CFC, 0x09500400, + 0x1D00, 0x3F000000, + 0x1D08, 0x00000000, + 0x1D88, 0x09501000, + 0x1D8C, 0x3F000000, + 0x1D94, 0x00000000, + 0x1E14, 0x09504000, + 0x1E18, 0x3F000000, + 0x1E20, 0x00000000, + 0x1A50, 0x00000004, + 0x1A78, 0x00640000, + 0x1A8C, 0xFF000001, + 0x1A90, 0x00000000, + 0x1A94, 0x00002710, + 0x1A98, 0x00004E20, + 0x1A9C, 0x00000000, + 0x1ADC, 0x00000004, + 0x1B04, 0x00640000, + 0x1B18, 0xFF000001, + 0x1B1C, 0x00000000, + 0x1B20, 0x00002710, + 0x1B24, 0x00004E20, + 0x1B28, 0x00000000, + 0x1B68, 0x00000004, + 0x1B90, 0x00640000, + 0x1BA4, 0xFF000001, + 0x1BA8, 0x00000000, + 0x1BAC, 0x00002710, + 0x1BB0, 0x00004E20, + 0x1BB4, 0x00000000, + 0x1BF4, 0x00000004, + 0x1C1C, 0x00640000, + 0x1C30, 0xFF000001, + 0x1C34, 0x00000000, + 0x1C38, 0x00002710, + 0x1C3C, 0x00004E20, + 0x1C40, 0x00000000, + 0x1C80, 0x00000004, + 0x1CA8, 0x00640000, + 0x1CBC, 0xFF000001, + 0x1CC0, 0x00000000, + 0x1CC4, 0x00002710, + 0x1CC8, 0x00004E20, + 0x1CCC, 0x00000000, + 0x1D0C, 0x00000004, + 0x1D34, 0x00640000, + 0x1D48, 0xFF000001, + 0x1D4C, 0x00000000, + 0x1D50, 0x00002710, + 0x1D54, 0x00004E20, + 0x1D58, 0x00000000, + 0x1D98, 0x00000004, + 0x1DC0, 0x00640000, + 0x1DD4, 0xFF000001, + 0x1DD8, 0x00000000, + 0x1DDC, 0x00002710, + 0x1DE0, 0x00004E20, + 0x1DE4, 0x00000000, + 0x1E24, 0x00000004, + 0x1E4C, 0x00640000, + 0x1E60, 0xFF000001, + 0x1E64, 0x00000000, + 0x1E68, 0x00002710, + 0x1E6C, 0x00004E20, + 0x1E70, 0x00000000, + 0x4414, 0x0000081F, + 0x1A18, 0x00FFFFFF, +}; + +#endif diff --git a/include/linux/input/awinic/aw963xx.h b/include/linux/input/awinic/aw963xx.h new file mode 100644 index 000000000000..7d0ee96033df --- /dev/null +++ b/include/linux/input/awinic/aw963xx.h @@ -0,0 +1,1542 @@ +#ifndef AW963XX_H_ +#define AW963XX_H_ +#include "aw_sar_type.h" +#include "linux/sensors.h" + +#define USE_SENSORS_CLASS +#define AW963XX_CHANNEL_NUM_MAX (12) +#define AW963XX_VALID_TH (3) +#define AW963XX_DATA_PROCESS_FACTOR (1024) +#define AW9620X_SAR_VCC_MIN_UV (1700000) +#define AW9620X_SAR_VCC_MAX_UV (3600000) +#define AW963XX_SRAM_UPDATE_ONE_PACK_SIZE (1024) +#define AW963XX_SRAM_UPDATE_ONE_UINT_SIZE (4) +#define AW963XX_SRAM_START_ADDR (0x2000) +#define AW963XX_SRAM_END_ADDR (0x4ff4 + 4) +#define AW963XX_SRAM_SIZE (AW963XX_SRAM_END_ADDR - AW963XX_SRAM_START_ADDR) +#define AW963XX_SRAM_DEFAULT_VAL (0xffffffff) + +#define AW963XX_TRIGGER_FAR (0) + +#define AW963XX_STEP_LEN_UNSIGNED_CAP_ROUGH_ADJ (9900) +#define AW963XX_STEP_LEN_UNSIGNED_CAP_FINE_ADJ (152) +#define AW963XX_STEP_LEN_UNSIGNED_CAP_ENLARGE (10000) + +#define AW963XX_CPU_OSC_CTRL_MASK (1) + +#define AW963XX_ABNORMAL_IRQ_HANDLE_DELAY_MS (30000) + +#define HALF_WORD (0xf) +#define ONE_WORD (0xff) +#define AW_BIT8 (8) +#define AW_BIT16 (16) +#define AW96303 ("aw96303") +#define AW96305 ("aw96305") +#define AW96308 ("aw96308") +#define AW96310 ("aw96310") + +enum aw963xx_cap_mode { + AW963XX_UNSIGNED_CAP = 0, + AW963XX_SIGNED_CAP = 4, + AW963XX_MUTUAL_CAP = 5, +}; + +enum aw963xx_approach_state { + AW963XX_FAR_AWAY = 0, + AW963XX_APPROACH = 1, +}; + +enum aw963xx_cs_2_irq { + AW963XX_CS2_IRQ = 2, + AW963XX_CS5_IRQ = 5, +}; + +enum aw963xx_operation_mode { + AW963XX_ACTIVE_MODE = 0x01, + AW963XX_SLEEP_MODE = 0x02, + AW963XX_DEEPSLEEP_MODE = 0x03, +}; + +enum aw963xx_operation_ap_mode { + AW963XX_SLEEP_AP_MODE = 0, + AW963XX_ACTIVE_AP_MODE, + AW963XX_DEEPSLEEP_AP_MODE, +}; + + +enum aw963xx_chip_id { + AW96303_CHIP_ID = 0xA9630340, + AW96305_CHIP_ID = 0xA9630520, + AW96308_CHIP_ID = 0xA9630810, + AW96310_CHIP_ID = 0xA9631010, +}; + +enum aw963xx_boot_mode { + AW963XX_ROM_MODE = 0, + AW963XX_RAM_MODE = 1, +}; + +struct aw963xx { + uint32_t irq_mux; + uint32_t start_mode; + uint32_t ref_ch_en[AW963XX_CHANNEL_NUM_MAX]; + void *p_aw_sar; + + struct work_struct abnormal_irq_work; + struct timer_list abnormal_irq_timer; + + struct class capsense_class; + + uint8_t read_flag; + uint16_t read_reg; +#ifdef USE_SENSORS_CLASS + struct sensors_classdev sensors_capsensor_chs[AW963XX_CHANNEL_NUM_MAX]; +#endif + +}; + +#define REG_CPU_MODE_SET (0xf800) +#define AW963XX_RESET_CPU_SET_BOOT_SATRT (0x00010100) +#define AW963XX_EXIT_RESET_CPU_SET_BOOT_SATRT (0x00000100) +#define REG_CPU_RESET (0XFF0C) +#define AW963XX_RESET_SET (0) +#define REG_ENABLE_RAM (0xfff4) +#define AW963XX_ENABLE_DATA_RAM (0x3c00C11f) +#define REG_RAM_PASSWORD (0xFFE4) +#define AW963XX_NO_ENCRYPTION (0x3C000000) +#define REG_ENABLE_CHECKSUM_ADDR (0x4FF8) +#define AW963XX_EN_CHECKSUM_CODE (0x21662166) +#define AW963XX_START_CPU (0x00000100) +#define AW963XX_FILTCTRL0_CHX_REFAEN (16) +#define AW963XX_FILTCTRL0_CHX_REFASEL (11) +#define AW963XX_FILTCTRL0_CHX_REFBEN (9) +#define AW963XX_FILTCTRL0_CHX_REFBSEL (4) +#define AW963XX_REF_EN (1) +#define AW963XX_REF_DIS (0) +#define REG_SA_RSTNALL (0xFF0C) +#define AW963XX_SOFT_RST_EN (0) +#define AW963XX_CHIP_INIT_MAX_TIME_MS (30) + +#define AW963XX_RAM_START_ADDR (0x2000) + +#define AFE_BASE_ADDR (0x0000) +#define DSP_BASE_ADDR (0x0000) +#define DSPEX_BASE_ADDR (0x0000) +#define STAT_BASE_ADDR (0x0000) +#define DATA_BASE_ADDR (0x0000) +#define SFR_BASE_ADDR (0x0000) +#define HIDDEN_BASE_ADDR (0x0000) +/* registers list */ +//AFE MAP +#define REG_SCANCTRL0 ((0x0000) + AFE_BASE_ADDR) +#define REG_SCANCTRL1 ((0x0004) + AFE_BASE_ADDR) +#define REG_SCANCTRL2 ((0x0008) + AFE_BASE_ADDR) +#define REG_SCANCTRL3 ((0x000C) + AFE_BASE_ADDR) +#define REG_AFESOFTCFG0_CH0 ((0x010C) + AFE_BASE_ADDR) +#define REG_AFECFG0_CH0 ((0x0114) + AFE_BASE_ADDR) +#define REG_AFECFG1_CH0 ((0x0118) + AFE_BASE_ADDR) +#define REG_AFECFG3_CH0 ((0x0120) + AFE_BASE_ADDR) +#define REG_AFECFG4_CH0 ((0x0124) + AFE_BASE_ADDR) +#define REG_CHLSEL0_CH0 ((0x0128) + AFE_BASE_ADDR) +#define REG_AFESOFTCFG0_CH1 ((0x0224) + AFE_BASE_ADDR) +#define REG_AFECFG0_CH1 ((0x022C) + AFE_BASE_ADDR) +#define REG_AFECFG1_CH1 ((0x0230) + AFE_BASE_ADDR) +#define REG_AFECFG3_CH1 ((0x0238) + AFE_BASE_ADDR) +#define REG_AFECFG4_CH1 ((0x023C) + AFE_BASE_ADDR) +#define REG_CHLSEL0_CH1 ((0x0240) + AFE_BASE_ADDR) +#define REG_AFESOFTCFG0_CH2 ((0x033C) + AFE_BASE_ADDR) +#define REG_AFECFG0_CH2 ((0x0344) + AFE_BASE_ADDR) +#define REG_AFECFG1_CH2 ((0x0348) + AFE_BASE_ADDR) +#define REG_AFECFG3_CH2 ((0x0350) + AFE_BASE_ADDR) +#define REG_AFECFG4_CH2 ((0x0354) + AFE_BASE_ADDR) +#define REG_CHLSEL0_CH2 ((0x0358) + AFE_BASE_ADDR) +#define REG_AFESOFTCFG0_CH3 ((0x0454) + AFE_BASE_ADDR) +#define REG_AFECFG0_CH3 ((0x045C) + AFE_BASE_ADDR) +#define REG_AFECFG1_CH3 ((0x0460) + AFE_BASE_ADDR) +#define REG_AFECFG3_CH3 ((0x0468) + AFE_BASE_ADDR) +#define REG_AFECFG4_CH3 ((0x046C) + AFE_BASE_ADDR) +#define REG_CHLSEL0_CH3 ((0x0470) + AFE_BASE_ADDR) +#define REG_AFESOFTCFG0_CH4 ((0x056C) + AFE_BASE_ADDR) +#define REG_AFECFG0_CH4 ((0x0574) + AFE_BASE_ADDR) +#define REG_AFECFG1_CH4 ((0x0578) + AFE_BASE_ADDR) +#define REG_AFECFG3_CH4 ((0x0580) + AFE_BASE_ADDR) +#define REG_AFECFG4_CH4 ((0x0584) + AFE_BASE_ADDR) +#define REG_CHLSEL0_CH4 ((0x0588) + AFE_BASE_ADDR) +#define REG_AFESOFTCFG0_CH5 ((0x0684) + AFE_BASE_ADDR) +#define REG_AFECFG0_CH5 ((0x068C) + AFE_BASE_ADDR) +#define REG_AFECFG1_CH5 ((0x0690) + AFE_BASE_ADDR) +#define REG_AFECFG3_CH5 ((0x0698) + AFE_BASE_ADDR) +#define REG_AFECFG4_CH5 ((0x069C) + AFE_BASE_ADDR) +#define REG_CHLSEL0_CH5 ((0x06A0) + AFE_BASE_ADDR) +#define REG_AFESOFTCFG0_CH6 ((0x079C) + AFE_BASE_ADDR) +#define REG_AFECFG0_CH6 ((0x07A4) + AFE_BASE_ADDR) +#define REG_AFECFG1_CH6 ((0x07A8) + AFE_BASE_ADDR) +#define REG_AFECFG3_CH6 ((0x07B0) + AFE_BASE_ADDR) +#define REG_AFECFG4_CH6 ((0x07B4) + AFE_BASE_ADDR) +#define REG_CHLSEL0_CH6 ((0x07B8) + AFE_BASE_ADDR) +#define REG_AFESOFTCFG0_CH7 ((0x08B4) + AFE_BASE_ADDR) +#define REG_AFECFG0_CH7 ((0x08BC) + AFE_BASE_ADDR) +#define REG_AFECFG1_CH7 ((0x08C0) + AFE_BASE_ADDR) +#define REG_AFECFG3_CH7 ((0x08C8) + AFE_BASE_ADDR) +#define REG_AFECFG4_CH7 ((0x08CC) + AFE_BASE_ADDR) +#define REG_CHLSEL0_CH7 ((0x08D0) + AFE_BASE_ADDR) +#define REG_AFESOFTCFG0_CH8 ((0x09CC) + AFE_BASE_ADDR) +#define REG_AFECFG0_CH8 ((0x09D4) + AFE_BASE_ADDR) +#define REG_AFECFG1_CH8 ((0x09D8) + AFE_BASE_ADDR) +#define REG_AFECFG3_CH8 ((0x09E0) + AFE_BASE_ADDR) +#define REG_AFECFG4_CH8 ((0x09E4) + AFE_BASE_ADDR) +#define REG_CHLSEL0_CH8 ((0x09E8) + AFE_BASE_ADDR) + +/* registers list */ +//DSP MAP +#define REG_FILTCTRL0_CH0 ((0x0130) + DSP_BASE_ADDR) +#define REG_FILTCTRL1_CH0 ((0x013C) + DSP_BASE_ADDR) +#define REG_BLFILTA_CH0 ((0x0140) + DSP_BASE_ADDR) +#define REG_PROXCTRL_CH0 ((0x0148) + DSP_BASE_ADDR) +#define REG_PROXTH0_CH0 ((0x014C) + DSP_BASE_ADDR) +#define REG_PROXTH1_CH0 ((0x0150) + DSP_BASE_ADDR) +#define REG_PROXTH2_CH0 ((0x0154) + DSP_BASE_ADDR) +#define REG_PROXTH3_CH0 ((0x0158) + DSP_BASE_ADDR) +#define REG_NEGPROXTH_CH0 ((0x015C) + DSP_BASE_ADDR) +#define REG_STDDET_CH0 ((0x0160) + DSP_BASE_ADDR) +#define REG_INITPROX0_CH0 ((0x0164) + DSP_BASE_ADDR) +#define REG_INITPROX1_CH0 ((0x0168) + DSP_BASE_ADDR) +#define REG_FILTCTRL0_CH1 ((0x0248) + DSP_BASE_ADDR) +#define REG_FILTCTRL1_CH1 ((0x0254) + DSP_BASE_ADDR) +#define REG_BLFILTA_CH1 ((0x0258) + DSP_BASE_ADDR) +#define REG_PROXCTRL_CH1 ((0x0260) + DSP_BASE_ADDR) +#define REG_PROXTH0_CH1 ((0x0264) + DSP_BASE_ADDR) +#define REG_PROXTH1_CH1 ((0x0268) + DSP_BASE_ADDR) +#define REG_PROXTH2_CH1 ((0x026C) + DSP_BASE_ADDR) +#define REG_PROXTH3_CH1 ((0x0270) + DSP_BASE_ADDR) +#define REG_NEGPROXTH_CH1 ((0x0274) + DSP_BASE_ADDR) +#define REG_STDDET_CH1 ((0x0278) + DSP_BASE_ADDR) +#define REG_INITPROX0_CH1 ((0x027C) + DSP_BASE_ADDR) +#define REG_INITPROX1_CH1 ((0x0280) + DSP_BASE_ADDR) +#define REG_FILTCTRL0_CH2 ((0x0360) + DSP_BASE_ADDR) +#define REG_FILTCTRL1_CH2 ((0x036C) + DSP_BASE_ADDR) +#define REG_BLFILTA_CH2 ((0x0370) + DSP_BASE_ADDR) +#define REG_PROXCTRL_CH2 ((0x0378) + DSP_BASE_ADDR) +#define REG_PROXTH0_CH2 ((0x037C) + DSP_BASE_ADDR) +#define REG_PROXTH1_CH2 ((0x0380) + DSP_BASE_ADDR) +#define REG_PROXTH2_CH2 ((0x0384) + DSP_BASE_ADDR) +#define REG_PROXTH3_CH2 ((0x0388) + DSP_BASE_ADDR) +#define REG_NEGPROXTH_CH2 ((0x038C) + DSP_BASE_ADDR) +#define REG_STDDET_CH2 ((0x0390) + DSP_BASE_ADDR) +#define REG_INITPROX0_CH2 ((0x0394) + DSP_BASE_ADDR) +#define REG_INITPROX1_CH2 ((0x0398) + DSP_BASE_ADDR) +#define REG_FILTCTRL0_CH3 ((0x0478) + DSP_BASE_ADDR) +#define REG_FILTCTRL1_CH3 ((0x0484) + DSP_BASE_ADDR) +#define REG_BLFILTA_CH3 ((0x0488) + DSP_BASE_ADDR) +#define REG_PROXCTRL_CH3 ((0x0490) + DSP_BASE_ADDR) +#define REG_PROXTH0_CH3 ((0x0494) + DSP_BASE_ADDR) +#define REG_PROXTH1_CH3 ((0x0498) + DSP_BASE_ADDR) +#define REG_PROXTH2_CH3 ((0x049C) + DSP_BASE_ADDR) +#define REG_PROXTH3_CH3 ((0x04A0) + DSP_BASE_ADDR) +#define REG_NEGPROXTH_CH3 ((0x04A4) + DSP_BASE_ADDR) +#define REG_STDDET_CH3 ((0x04A8) + DSP_BASE_ADDR) +#define REG_INITPROX0_CH3 ((0x04AC) + DSP_BASE_ADDR) +#define REG_INITPROX1_CH3 ((0x04B0) + DSP_BASE_ADDR) +#define REG_FILTCTRL0_CH4 ((0x0590) + DSP_BASE_ADDR) +#define REG_FILTCTRL1_CH4 ((0x059C) + DSP_BASE_ADDR) +#define REG_BLFILTA_CH4 ((0x05A0) + DSP_BASE_ADDR) +#define REG_PROXCTRL_CH4 ((0x05A8) + DSP_BASE_ADDR) +#define REG_PROXTH0_CH4 ((0x05AC) + DSP_BASE_ADDR) +#define REG_PROXTH1_CH4 ((0x05B0) + DSP_BASE_ADDR) +#define REG_PROXTH2_CH4 ((0x05B4) + DSP_BASE_ADDR) +#define REG_PROXTH3_CH4 ((0x05B8) + DSP_BASE_ADDR) +#define REG_NEGPROXTH_CH4 ((0x05BC) + DSP_BASE_ADDR) +#define REG_STDDET_CH4 ((0x05C0) + DSP_BASE_ADDR) +#define REG_INITPROX0_CH4 ((0x05C4) + DSP_BASE_ADDR) +#define REG_INITPROX1_CH4 ((0x05C8) + DSP_BASE_ADDR) +#define REG_FILTCTRL0_CH5 ((0x06A8) + DSP_BASE_ADDR) +#define REG_FILTCTRL1_CH5 ((0x06B4) + DSP_BASE_ADDR) +#define REG_BLFILTA_CH5 ((0x06B8) + DSP_BASE_ADDR) +#define REG_PROXCTRL_CH5 ((0x06C0) + DSP_BASE_ADDR) +#define REG_PROXTH0_CH5 ((0x06C4) + DSP_BASE_ADDR) +#define REG_PROXTH1_CH5 ((0x06C8) + DSP_BASE_ADDR) +#define REG_PROXTH2_CH5 ((0x06CC) + DSP_BASE_ADDR) +#define REG_PROXTH3_CH5 ((0x06D0) + DSP_BASE_ADDR) +#define REG_NEGPROXTH_CH5 ((0x06D4) + DSP_BASE_ADDR) +#define REG_STDDET_CH5 ((0x06D8) + DSP_BASE_ADDR) +#define REG_INITPROX0_CH5 ((0x06DC) + DSP_BASE_ADDR) +#define REG_INITPROX1_CH5 ((0x06E0) + DSP_BASE_ADDR) +#define REG_FILTCTRL0_CH6 ((0x07C0) + DSP_BASE_ADDR) +#define REG_FILTCTRL1_CH6 ((0x07CC) + DSP_BASE_ADDR) +#define REG_BLFILTA_CH6 ((0x07D0) + DSP_BASE_ADDR) +#define REG_PROXCTRL_CH6 ((0x07D8) + DSP_BASE_ADDR) +#define REG_PROXTH0_CH6 ((0x07DC) + DSP_BASE_ADDR) +#define REG_PROXTH1_CH6 ((0x07E0) + DSP_BASE_ADDR) +#define REG_PROXTH2_CH6 ((0x07E4) + DSP_BASE_ADDR) +#define REG_PROXTH3_CH6 ((0x07E8) + DSP_BASE_ADDR) +#define REG_NEGPROXTH_CH6 ((0x07EC) + DSP_BASE_ADDR) +#define REG_STDDET_CH6 ((0x07F0) + DSP_BASE_ADDR) +#define REG_INITPROX0_CH6 ((0x07F4) + DSP_BASE_ADDR) +#define REG_INITPROX1_CH6 ((0x07F8) + DSP_BASE_ADDR) +#define REG_FILTCTRL0_CH7 ((0x08D8) + DSP_BASE_ADDR) +#define REG_FILTCTRL1_CH7 ((0x08E4) + DSP_BASE_ADDR) +#define REG_BLFILTA_CH7 ((0x08E8) + DSP_BASE_ADDR) +#define REG_PROXCTRL_CH7 ((0x08F0) + DSP_BASE_ADDR) +#define REG_PROXTH0_CH7 ((0x08F4) + DSP_BASE_ADDR) +#define REG_PROXTH1_CH7 ((0x08F8) + DSP_BASE_ADDR) +#define REG_PROXTH2_CH7 ((0x08FC) + DSP_BASE_ADDR) +#define REG_PROXTH3_CH7 ((0x0900) + DSP_BASE_ADDR) +#define REG_NEGPROXTH_CH7 ((0x0904) + DSP_BASE_ADDR) +#define REG_STDDET_CH7 ((0x0908) + DSP_BASE_ADDR) +#define REG_INITPROX0_CH7 ((0x090C) + DSP_BASE_ADDR) +#define REG_INITPROX1_CH7 ((0x0910) + DSP_BASE_ADDR) +#define REG_FILTCTRL0_CH8 ((0x09F0) + DSP_BASE_ADDR) +#define REG_FILTCTRL1_CH8 ((0x09FC) + DSP_BASE_ADDR) +#define REG_BLFILTA_CH8 ((0x0A00) + DSP_BASE_ADDR) +#define REG_PROXCTRL_CH8 ((0x0A08) + DSP_BASE_ADDR) +#define REG_PROXTH0_CH8 ((0x0A0C) + DSP_BASE_ADDR) +#define REG_PROXTH1_CH8 ((0x0A10) + DSP_BASE_ADDR) +#define REG_PROXTH2_CH8 ((0x0A14) + DSP_BASE_ADDR) +#define REG_PROXTH3_CH8 ((0x0A18) + DSP_BASE_ADDR) +#define REG_NEGPROXTH_CH8 ((0x0A1C) + DSP_BASE_ADDR) +#define REG_STDDET_CH8 ((0x0A20) + DSP_BASE_ADDR) +#define REG_INITPROX0_CH8 ((0x0A24) + DSP_BASE_ADDR) +#define REG_INITPROX1_CH8 ((0x0A28) + DSP_BASE_ADDR) + +/* registers list */ +//DSPEX MAP +#define REG_REFRAWTH_CH0 ((0x019C) + DSPEX_BASE_ADDR) +#define REG_REFCOEFMAX_CH0 ((0x01A0) + DSPEX_BASE_ADDR) +#define REG_REFCOEFMIN_CH0 ((0x01A4) + DSPEX_BASE_ADDR) +#define REG_REFCOEFINIT_CH0 ((0x01A8) + DSPEX_BASE_ADDR) +#define REG_REFCOEFLAST_CH0 ((0x01AC) + DSPEX_BASE_ADDR) +#define REG_REFKP_CH0 ((0x01B0) + DSPEX_BASE_ADDR) +#define REG_REFCOEFLIMIT_CH0 ((0x01B4) + DSPEX_BASE_ADDR) +#define REG_REFCOMP_CH0 ((0x01B8) + DSPEX_BASE_ADDR) +#define REG_REFVALIDTAR_CH0 ((0x01BC) + DSPEX_BASE_ADDR) +#define REG_REFRAWLAST_CH0 ((0x01C0) + DSPEX_BASE_ADDR) +#define REG_BLNEWFILTERA_CH0 ((0x01D0) + DSPEX_BASE_ADDR) +#define REG_BLNEWFILTERB_CH0 ((0x01D4) + DSPEX_BASE_ADDR) +#define REG_THCOMPARE_CH0 ((0x01D8) + DSPEX_BASE_ADDR) +#define REG_THDELTA1_CH0 ((0x01DC) + DSPEX_BASE_ADDR) +#define REG_THDELTA2_CH0 ((0x01E0) + DSPEX_BASE_ADDR) +#define REG_JUDGE_CH0 ((0x01E4) + DSPEX_BASE_ADDR) +#define REG_REFRAWTH_CH1 ((0x02B4) + DSPEX_BASE_ADDR) +#define REG_REFCOEFMAX_CH1 ((0x02B8) + DSPEX_BASE_ADDR) +#define REG_REFCOEFMIN_CH1 ((0x02BC) + DSPEX_BASE_ADDR) +#define REG_REFCOEFINIT_CH1 ((0x02C0) + DSPEX_BASE_ADDR) +#define REG_REFCOEFLAST_CH1 ((0x02C4) + DSPEX_BASE_ADDR) +#define REG_REFKP_CH1 ((0x02C8) + DSPEX_BASE_ADDR) +#define REG_REFCOEFLIMIT_CH1 ((0x02CC) + DSPEX_BASE_ADDR) +#define REG_REFCOMP_CH1 ((0x02D0) + DSPEX_BASE_ADDR) +#define REG_REFVALIDTAR_CH1 ((0x02D4) + DSPEX_BASE_ADDR) +#define REG_REFRAWLAST_CH1 ((0x02D8) + DSPEX_BASE_ADDR) +#define REG_BLNEWFILTERA_CH1 ((0x02E8) + DSPEX_BASE_ADDR) +#define REG_BLNEWFILTERB_CH1 ((0x02EC) + DSPEX_BASE_ADDR) +#define REG_THCOMPARE_CH1 ((0x02F0) + DSPEX_BASE_ADDR) +#define REG_THDELTA1_CH1 ((0x02F4) + DSPEX_BASE_ADDR) +#define REG_THDELTA2_CH1 ((0x02F8) + DSPEX_BASE_ADDR) +#define REG_JUDGE_CH1 ((0x02FC) + DSPEX_BASE_ADDR) +#define REG_REFRAWTH_CH2 ((0x03CC) + DSPEX_BASE_ADDR) +#define REG_REFCOEFMAX_CH2 ((0x03D0) + DSPEX_BASE_ADDR) +#define REG_REFCOEFMIN_CH2 ((0x03D4) + DSPEX_BASE_ADDR) +#define REG_REFCOEFINIT_CH2 ((0x03D8) + DSPEX_BASE_ADDR) +#define REG_REFCOEFLAST_CH2 ((0x03DC) + DSPEX_BASE_ADDR) +#define REG_REFKP_CH2 ((0x03E0) + DSPEX_BASE_ADDR) +#define REG_REFCOEFLIMIT_CH2 ((0x03E4) + DSPEX_BASE_ADDR) +#define REG_REFCOMP_CH2 ((0x03E8) + DSPEX_BASE_ADDR) +#define REG_REFVALIDTAR_CH2 ((0x03EC) + DSPEX_BASE_ADDR) +#define REG_REFRAWLAST_CH2 ((0x03F0) + DSPEX_BASE_ADDR) +#define REG_BLNEWFILTERA_CH2 ((0x0400) + DSPEX_BASE_ADDR) +#define REG_BLNEWFILTERB_CH2 ((0x0404) + DSPEX_BASE_ADDR) +#define REG_THCOMPARE_CH2 ((0x0408) + DSPEX_BASE_ADDR) +#define REG_THDELTA1_CH2 ((0x040C) + DSPEX_BASE_ADDR) +#define REG_THDELTA2_CH2 ((0x0410) + DSPEX_BASE_ADDR) +#define REG_JUDGE_CH2 ((0x0414) + DSPEX_BASE_ADDR) +#define REG_REFRAWTH_CH3 ((0x04E4) + DSPEX_BASE_ADDR) +#define REG_REFCOEFMAX_CH3 ((0x04E8) + DSPEX_BASE_ADDR) +#define REG_REFCOEFMIN_CH3 ((0x04EC) + DSPEX_BASE_ADDR) +#define REG_REFCOEFINIT_CH3 ((0x04F0) + DSPEX_BASE_ADDR) +#define REG_REFCOEFLAST_CH3 ((0x04F4) + DSPEX_BASE_ADDR) +#define REG_REFKP_CH3 ((0x04F8) + DSPEX_BASE_ADDR) +#define REG_REFCOEFLIMIT_CH3 ((0x04FC) + DSPEX_BASE_ADDR) +#define REG_REFCOMP_CH3 ((0x0500) + DSPEX_BASE_ADDR) +#define REG_REFVALIDTAR_CH3 ((0x0504) + DSPEX_BASE_ADDR) +#define REG_REFRAWLAST_CH3 ((0x0508) + DSPEX_BASE_ADDR) +#define REG_BLNEWFILTERA_CH3 ((0x0518) + DSPEX_BASE_ADDR) +#define REG_BLNEWFILTERB_CH3 ((0x051C) + DSPEX_BASE_ADDR) +#define REG_THCOMPARE_CH3 ((0x0520) + DSPEX_BASE_ADDR) +#define REG_THDELTA1_CH3 ((0x0524) + DSPEX_BASE_ADDR) +#define REG_THDELTA2_CH3 ((0x0528) + DSPEX_BASE_ADDR) +#define REG_JUDGE_CH3 ((0x052C) + DSPEX_BASE_ADDR) +#define REG_REFRAWTH_CH4 ((0x05FC) + DSPEX_BASE_ADDR) +#define REG_REFCOEFMAX_CH4 ((0x0600) + DSPEX_BASE_ADDR) +#define REG_REFCOEFMIN_CH4 ((0x0604) + DSPEX_BASE_ADDR) +#define REG_REFCOEFINIT_CH4 ((0x0608) + DSPEX_BASE_ADDR) +#define REG_REFCOEFLAST_CH4 ((0x060C) + DSPEX_BASE_ADDR) +#define REG_REFKP_CH4 ((0x0610) + DSPEX_BASE_ADDR) +#define REG_REFCOEFLIMIT_CH4 ((0x0614) + DSPEX_BASE_ADDR) +#define REG_REFCOMP_CH4 ((0x0618) + DSPEX_BASE_ADDR) +#define REG_REFVALIDTAR_CH4 ((0x061C) + DSPEX_BASE_ADDR) +#define REG_REFRAWLAST_CH4 ((0x0620) + DSPEX_BASE_ADDR) +#define REG_BLNEWFILTERA_CH4 ((0x0630) + DSPEX_BASE_ADDR) +#define REG_BLNEWFILTERB_CH4 ((0x0634) + DSPEX_BASE_ADDR) +#define REG_THCOMPARE_CH4 ((0x0638) + DSPEX_BASE_ADDR) +#define REG_THDELTA1_CH4 ((0x063C) + DSPEX_BASE_ADDR) +#define REG_THDELTA2_CH4 ((0x0640) + DSPEX_BASE_ADDR) +#define REG_JUDGE_CH4 ((0x0644) + DSPEX_BASE_ADDR) +#define REG_REFRAWTH_CH5 ((0x0714) + DSPEX_BASE_ADDR) +#define REG_REFCOEFMAX_CH5 ((0x0718) + DSPEX_BASE_ADDR) +#define REG_REFCOEFMIN_CH5 ((0x071C) + DSPEX_BASE_ADDR) +#define REG_REFCOEFINIT_CH5 ((0x0720) + DSPEX_BASE_ADDR) +#define REG_REFCOEFLAST_CH5 ((0x0724) + DSPEX_BASE_ADDR) +#define REG_REFKP_CH5 ((0x0728) + DSPEX_BASE_ADDR) +#define REG_REFCOEFLIMIT_CH5 ((0x072C) + DSPEX_BASE_ADDR) +#define REG_REFCOMP_CH5 ((0x0730) + DSPEX_BASE_ADDR) +#define REG_REFVALIDTAR_CH5 ((0x0734) + DSPEX_BASE_ADDR) +#define REG_REFRAWLAST_CH5 ((0x0738) + DSPEX_BASE_ADDR) +#define REG_BLNEWFILTERA_CH5 ((0x0748) + DSPEX_BASE_ADDR) +#define REG_BLNEWFILTERB_CH5 ((0x074C) + DSPEX_BASE_ADDR) +#define REG_THCOMPARE_CH5 ((0x0750) + DSPEX_BASE_ADDR) +#define REG_THDELTA1_CH5 ((0x0754) + DSPEX_BASE_ADDR) +#define REG_THDELTA2_CH5 ((0x0758) + DSPEX_BASE_ADDR) +#define REG_JUDGE_CH5 ((0x075C) + DSPEX_BASE_ADDR) +#define REG_REFRAWTH_CH6 ((0x082C) + DSPEX_BASE_ADDR) +#define REG_REFCOEFMAX_CH6 ((0x0830) + DSPEX_BASE_ADDR) +#define REG_REFCOEFMIN_CH6 ((0x0834) + DSPEX_BASE_ADDR) +#define REG_REFCOEFINIT_CH6 ((0x0838) + DSPEX_BASE_ADDR) +#define REG_REFCOEFLAST_CH6 ((0x083C) + DSPEX_BASE_ADDR) +#define REG_REFKP_CH6 ((0x0840) + DSPEX_BASE_ADDR) +#define REG_REFCOEFLIMIT_CH6 ((0x0844) + DSPEX_BASE_ADDR) +#define REG_REFCOMP_CH6 ((0x0848) + DSPEX_BASE_ADDR) +#define REG_REFVALIDTAR_CH6 ((0x084C) + DSPEX_BASE_ADDR) +#define REG_REFRAWLAST_CH6 ((0x0850) + DSPEX_BASE_ADDR) +#define REG_BLNEWFILTERA_CH6 ((0x0860) + DSPEX_BASE_ADDR) +#define REG_BLNEWFILTERB_CH6 ((0x0864) + DSPEX_BASE_ADDR) +#define REG_THCOMPARE_CH6 ((0x0868) + DSPEX_BASE_ADDR) +#define REG_THDELTA1_CH6 ((0x086C) + DSPEX_BASE_ADDR) +#define REG_THDELTA2_CH6 ((0x0870) + DSPEX_BASE_ADDR) +#define REG_JUDGE_CH6 ((0x0874) + DSPEX_BASE_ADDR) +#define REG_REFRAWTH_CH7 ((0x0944) + DSPEX_BASE_ADDR) +#define REG_REFCOEFMAX_CH7 ((0x0948) + DSPEX_BASE_ADDR) +#define REG_REFCOEFMIN_CH7 ((0x094C) + DSPEX_BASE_ADDR) +#define REG_REFCOEFINIT_CH7 ((0x0950) + DSPEX_BASE_ADDR) +#define REG_REFCOEFLAST_CH7 ((0x0954) + DSPEX_BASE_ADDR) +#define REG_REFKP_CH7 ((0x0958) + DSPEX_BASE_ADDR) +#define REG_REFCOEFLIMIT_CH7 ((0x095C) + DSPEX_BASE_ADDR) +#define REG_REFCOMP_CH7 ((0x0960) + DSPEX_BASE_ADDR) +#define REG_REFVALIDTAR_CH7 ((0x0964) + DSPEX_BASE_ADDR) +#define REG_REFRAWLAST_CH7 ((0x0968) + DSPEX_BASE_ADDR) +#define REG_BLNEWFILTERA_CH7 ((0x0978) + DSPEX_BASE_ADDR) +#define REG_BLNEWFILTERB_CH7 ((0x097C) + DSPEX_BASE_ADDR) +#define REG_THCOMPARE_CH7 ((0x0980) + DSPEX_BASE_ADDR) +#define REG_THDELTA1_CH7 ((0x0984) + DSPEX_BASE_ADDR) +#define REG_THDELTA2_CH7 ((0x0988) + DSPEX_BASE_ADDR) +#define REG_JUDGE_CH7 ((0x098C) + DSPEX_BASE_ADDR) +#define REG_REFRAWTH_CH8 ((0x0A5C) + DSPEX_BASE_ADDR) +#define REG_REFCOEFMAX_CH8 ((0x0A60) + DSPEX_BASE_ADDR) +#define REG_REFCOEFMIN_CH8 ((0x0A64) + DSPEX_BASE_ADDR) +#define REG_REFCOEFINIT_CH8 ((0x0A68) + DSPEX_BASE_ADDR) +#define REG_REFCOEFLAST_CH8 ((0x0A6C) + DSPEX_BASE_ADDR) +#define REG_REFKP_CH8 ((0x0A70) + DSPEX_BASE_ADDR) +#define REG_REFCOEFLIMIT_CH8 ((0x0A74) + DSPEX_BASE_ADDR) +#define REG_REFCOMP_CH8 ((0x0A78) + DSPEX_BASE_ADDR) +#define REG_REFVALIDTAR_CH8 ((0x0A7C) + DSPEX_BASE_ADDR) +#define REG_REFRAWLAST_CH8 ((0x0A80) + DSPEX_BASE_ADDR) +#define REG_BLNEWFILTERA_CH8 ((0x0A90) + DSPEX_BASE_ADDR) +#define REG_BLNEWFILTERB_CH8 ((0x0A94) + DSPEX_BASE_ADDR) +#define REG_THCOMPARE_CH8 ((0x0A98) + DSPEX_BASE_ADDR) +#define REG_THDELTA1_CH8 ((0x0A9C) + DSPEX_BASE_ADDR) +#define REG_THDELTA2_CH8 ((0x0AA0) + DSPEX_BASE_ADDR) +#define REG_JUDGE_CH8 ((0x0AA4) + DSPEX_BASE_ADDR) +#define REG_PIDCONTROLCFG ((0x0E2C) + DSPEX_BASE_ADDR) +#define REG_PIDCFG_CH0 ((0x0E30) + DSPEX_BASE_ADDR) +#define REG_PIDCFG_CH1 ((0x0E40) + DSPEX_BASE_ADDR) +#define REG_PIDCFG_CH2 ((0x0E50) + DSPEX_BASE_ADDR) +#define REG_PIDCFG_CH3 ((0x0E60) + DSPEX_BASE_ADDR) +#define REG_PIDCFG_CH4 ((0x0E70) + DSPEX_BASE_ADDR) +#define REG_PIDCFG_CH5 ((0x0E80) + DSPEX_BASE_ADDR) +#define REG_PIDCFG_CH6 ((0x0E90) + DSPEX_BASE_ADDR) +#define REG_PIDCFG_CH7 ((0x0EA0) + DSPEX_BASE_ADDR) +#define REG_PIDCFG_CH8 ((0x0EB0) + DSPEX_BASE_ADDR) + +/* registers list */ +//STAT MAP +#define REG_WST ((0x001C) + STAT_BASE_ADDR) +#define REG_STAT0 ((0x0020) + STAT_BASE_ADDR) +#define REG_STAT1 ((0x0024) + STAT_BASE_ADDR) +#define REG_STAT2 ((0x0028) + STAT_BASE_ADDR) +#define REG_STAT3 ((0x002C) + STAT_BASE_ADDR) +#define REG_STAT4 ((0x0030) + STAT_BASE_ADDR) +#define REG_STAT5 ((0x0034) + STAT_BASE_ADDR) +#define REG_STAT7 ((0x003C) + STAT_BASE_ADDR) +#define REG_STAT8 ((0x0040) + STAT_BASE_ADDR) +#define REG_STAT9 ((0x0044) + STAT_BASE_ADDR) +#define REG_STAT10 ((0x0048) + STAT_BASE_ADDR) +#define REG_STAT11 ((0x004C) + STAT_BASE_ADDR) +#define REG_STAT12 ((0x0050) + STAT_BASE_ADDR) +#define REG_STAT13 ((0x0054) + STAT_BASE_ADDR) +#define REG_STAT14 ((0x0058) + STAT_BASE_ADDR) +#define REG_FWVER ((0x005C) + STAT_BASE_ADDR) + +/* registers list */ +//DATA MAP +#define REG_BASELINE_CH0 ((0x01E8) + DATA_BASE_ADDR) +#define REG_DIFF_CH0 ((0x01EC) + DATA_BASE_ADDR) +#define REG_BASELINE_CH1 ((0x0300) + DATA_BASE_ADDR) +#define REG_DIFF_CH1 ((0x0304) + DATA_BASE_ADDR) +#define REG_BASELINE_CH2 ((0x0418) + DATA_BASE_ADDR) +#define REG_DIFF_CH2 ((0x041C) + DATA_BASE_ADDR) +#define REG_BASELINE_CH3 ((0x0530) + DATA_BASE_ADDR) +#define REG_DIFF_CH3 ((0x0534) + DATA_BASE_ADDR) +#define REG_BASELINE_CH4 ((0x0648) + DATA_BASE_ADDR) +#define REG_DIFF_CH4 ((0x064C) + DATA_BASE_ADDR) +#define REG_BASELINE_CH5 ((0x0760) + DATA_BASE_ADDR) +#define REG_DIFF_CH5 ((0x0764) + DATA_BASE_ADDR) +#define REG_BASELINE_CH6 ((0x0878) + DATA_BASE_ADDR) +#define REG_DIFF_CH6 ((0x087C) + DATA_BASE_ADDR) +#define REG_BASELINE_CH7 ((0x0990) + DATA_BASE_ADDR) +#define REG_DIFF_CH7 ((0x0994) + DATA_BASE_ADDR) +#define REG_BASELINE_CH8 ((0x0AA8) + DATA_BASE_ADDR) +#define REG_DIFF_CH8 ((0x0AAC) + DATA_BASE_ADDR) + +/* registers list */ +//SFR MAP +#define REG_IRQSRC ((0xF080) + SFR_BASE_ADDR) +#define REG_IRQEN ((0xF084) + SFR_BASE_ADDR) +#define REG_I2CTIMEOUTEN ((0xF0E4) + SFR_BASE_ADDR) +#define REG_ANACFG ((0xF804) + SFR_BASE_ADDR) +#define REG_CHIPSTAT ((0xFF00) + SFR_BASE_ADDR) +#define REG_CHIP_ID0 ((0xFF10) + SFR_BASE_ADDR) +#define REG_CHIP_ID1 ((0xFF14) + SFR_BASE_ADDR) +#define REG_CHIP_ID2 ((0xFF20) + SFR_BASE_ADDR) +#define REG_I3C_OSC_EN ((0xFF40) + SFR_BASE_ADDR) + +/* registers list */ +// MAP +#define REG_BASELINE_OLD_CH0 ((0x10D4) + HIDDEN_BASE_ADDR) +#define REG_BASELINE_PRE_CH0 ((0x10D8) + HIDDEN_BASE_ADDR) +#define REG_AFECFG1_M_CH0 ((0x10F8) + HIDDEN_BASE_ADDR) +#define REG_BASELINE_OLD_CH1 ((0x1160) + HIDDEN_BASE_ADDR) +#define REG_BASELINE_PRE_CH1 ((0x1164) + HIDDEN_BASE_ADDR) +#define REG_AFECFG1_M_CH1 ((0x1184) + HIDDEN_BASE_ADDR) +#define REG_BASELINE_OLD_CH2 ((0x11EC) + HIDDEN_BASE_ADDR) +#define REG_BASELINE_PRE_CH2 ((0x11F0) + HIDDEN_BASE_ADDR) +#define REG_AFECFG1_M_CH2 ((0x1210) + HIDDEN_BASE_ADDR) +#define REG_BASELINE_OLD_CH3 ((0x1278) + HIDDEN_BASE_ADDR) +#define REG_BASELINE_PRE_CH3 ((0x127C) + HIDDEN_BASE_ADDR) +#define REG_AFECFG1_M_CH3 ((0x129C) + HIDDEN_BASE_ADDR) +#define REG_BASELINE_OLD_CH4 ((0x1304) + HIDDEN_BASE_ADDR) +#define REG_BASELINE_PRE_CH4 ((0x1308) + HIDDEN_BASE_ADDR) +#define REG_AFECFG1_M_CH4 ((0x1328) + HIDDEN_BASE_ADDR) +#define REG_BASELINE_OLD_CH5 ((0x1390) + HIDDEN_BASE_ADDR) +#define REG_BASELINE_PRE_CH5 ((0x1394) + HIDDEN_BASE_ADDR) +#define REG_AFECFG1_M_CH5 ((0x13B4) + HIDDEN_BASE_ADDR) +#define REG_BASELINE_OLD_CH6 ((0x141C) + HIDDEN_BASE_ADDR) +#define REG_BASELINE_PRE_CH6 ((0x1420) + HIDDEN_BASE_ADDR) +#define REG_AFECFG1_M_CH6 ((0x1440) + HIDDEN_BASE_ADDR) +#define REG_BASELINE_OLD_CH7 ((0x14A8) + HIDDEN_BASE_ADDR) +#define REG_BASELINE_PRE_CH7 ((0x14AC) + HIDDEN_BASE_ADDR) +#define REG_AFECFG1_M_CH7 ((0x14CC) + HIDDEN_BASE_ADDR) +#define REG_BASELINE_OLD_CH8 ((0x1534) + HIDDEN_BASE_ADDR) +#define REG_BASELINE_PRE_CH8 ((0x1538) + HIDDEN_BASE_ADDR) +#define REG_AFECFG1_M_CH8 ((0x1558) + HIDDEN_BASE_ADDR) + +#define REG_CMD ((0xf008) + SFR_BASE_ADDR) + +struct reg_data { + unsigned char rw; + unsigned short reg; +}; +/******************************************** + * Register Access + *******************************************/ +#define REG_NONE_ACCESS (0) +#define REG_RD_ACCESS (1 << 0) +#define REG_WR_ACCESS (1 << 1) + +static const struct reg_data g_aw963xx_reg_access[] = { + //AFE MAP + { .reg = REG_SCANCTRL0, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_SCANCTRL1, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_SCANCTRL2, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_SCANCTRL3, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_AFESOFTCFG0_CH0, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_AFECFG0_CH0, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_AFECFG1_CH0, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_AFECFG3_CH0, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_AFECFG4_CH0, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_CHLSEL0_CH0, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_AFESOFTCFG0_CH1, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_AFECFG0_CH1, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_AFECFG1_CH1, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_AFECFG3_CH1, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_AFECFG4_CH1, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_CHLSEL0_CH1, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_AFESOFTCFG0_CH2, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_AFECFG0_CH2, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_AFECFG1_CH2, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_AFECFG3_CH2, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_AFECFG4_CH2, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_CHLSEL0_CH2, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_AFESOFTCFG0_CH3, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_AFECFG0_CH3, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_AFECFG1_CH3, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_AFECFG3_CH3, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_AFECFG4_CH3, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_CHLSEL0_CH3, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_AFESOFTCFG0_CH4, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_AFECFG0_CH4, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_AFECFG1_CH4, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_AFECFG3_CH4, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_AFECFG4_CH4, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_CHLSEL0_CH4, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_AFESOFTCFG0_CH5, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_AFECFG0_CH5, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_AFECFG1_CH5, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_AFECFG3_CH5, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_AFECFG4_CH5, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_CHLSEL0_CH5, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_AFESOFTCFG0_CH6, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_AFECFG0_CH6, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_AFECFG1_CH6, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_AFECFG3_CH6, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_AFECFG4_CH6, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_CHLSEL0_CH6, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_AFESOFTCFG0_CH7, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_AFECFG0_CH7, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_AFECFG1_CH7, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_AFECFG3_CH7, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_AFECFG4_CH7, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_CHLSEL0_CH7, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_AFESOFTCFG0_CH8, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_AFECFG0_CH8, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_AFECFG1_CH8, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_AFECFG3_CH8, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_AFECFG4_CH8, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_CHLSEL0_CH8, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + + //DSP MAP + { .reg = REG_FILTCTRL0_CH0, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_FILTCTRL1_CH0, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_BLFILTA_CH0, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_PROXCTRL_CH0, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_PROXTH0_CH0, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_PROXTH1_CH0, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_PROXTH2_CH0, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_PROXTH3_CH0, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_NEGPROXTH_CH0, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_STDDET_CH0, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_INITPROX0_CH0, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_INITPROX1_CH0, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_FILTCTRL0_CH1, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_FILTCTRL1_CH1, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_BLFILTA_CH1, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_PROXCTRL_CH1, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_PROXTH0_CH1, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_PROXTH1_CH1, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_PROXTH2_CH1, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_PROXTH3_CH1, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_NEGPROXTH_CH1, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_STDDET_CH1, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_INITPROX0_CH1, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_INITPROX1_CH1, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_FILTCTRL0_CH2, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_FILTCTRL1_CH2, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_BLFILTA_CH2, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_PROXCTRL_CH2, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_PROXTH0_CH2, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_PROXTH1_CH2, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_PROXTH2_CH2, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_PROXTH3_CH2, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_NEGPROXTH_CH2, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_STDDET_CH2, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_INITPROX0_CH2, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_INITPROX1_CH2, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_FILTCTRL0_CH3, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_FILTCTRL1_CH3, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_BLFILTA_CH3, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_PROXCTRL_CH3, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_PROXTH0_CH3, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_PROXTH1_CH3, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_PROXTH2_CH3, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_PROXTH3_CH3, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_NEGPROXTH_CH3, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_STDDET_CH3, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_INITPROX0_CH3, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_INITPROX1_CH3, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_FILTCTRL0_CH4, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_FILTCTRL1_CH4, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_BLFILTA_CH4, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_PROXCTRL_CH4, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_PROXTH0_CH4, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_PROXTH1_CH4, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_PROXTH2_CH4, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_PROXTH3_CH4, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_NEGPROXTH_CH4, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_STDDET_CH4, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_INITPROX0_CH4, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_INITPROX1_CH4, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_FILTCTRL0_CH5, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_FILTCTRL1_CH5, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_BLFILTA_CH5, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_PROXCTRL_CH5, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_PROXTH0_CH5, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_PROXTH1_CH5, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_PROXTH2_CH5, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_PROXTH3_CH5, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_NEGPROXTH_CH5, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_STDDET_CH5, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_INITPROX0_CH5, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_INITPROX1_CH5, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_FILTCTRL0_CH6, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_FILTCTRL1_CH6, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_BLFILTA_CH6, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_PROXCTRL_CH6, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_PROXTH0_CH6, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_PROXTH1_CH6, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_PROXTH2_CH6, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_PROXTH3_CH6, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_NEGPROXTH_CH6, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_STDDET_CH6, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_INITPROX0_CH6, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_INITPROX1_CH6, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_FILTCTRL0_CH7, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_FILTCTRL1_CH7, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_BLFILTA_CH7, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_PROXCTRL_CH7, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_PROXTH0_CH7, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_PROXTH1_CH7, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_PROXTH2_CH7, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_PROXTH3_CH7, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_NEGPROXTH_CH7, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_STDDET_CH7, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_INITPROX0_CH7, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_INITPROX1_CH7, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_FILTCTRL0_CH8, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_FILTCTRL1_CH8, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_BLFILTA_CH8, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_PROXCTRL_CH8, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_PROXTH0_CH8, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_PROXTH1_CH8, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_PROXTH2_CH8, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_PROXTH3_CH8, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_NEGPROXTH_CH8, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_STDDET_CH8, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_INITPROX0_CH8, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_INITPROX1_CH8, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + + //DSPEX MAP + { .reg = REG_REFRAWTH_CH0, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_REFCOEFMAX_CH0, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_REFCOEFMIN_CH0, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_REFCOEFINIT_CH0, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_REFCOEFLAST_CH0, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_REFKP_CH0, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_REFCOEFLIMIT_CH0, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_REFCOMP_CH0, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_REFVALIDTAR_CH0, .rw = REG_RD_ACCESS, }, + { .reg = REG_REFRAWLAST_CH0, .rw = REG_RD_ACCESS, }, + { .reg = REG_BLNEWFILTERA_CH0, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_BLNEWFILTERB_CH0, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_THCOMPARE_CH0, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_THDELTA1_CH0, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_THDELTA2_CH0, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_JUDGE_CH0, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_REFRAWTH_CH1, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_REFCOEFMAX_CH1, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_REFCOEFMIN_CH1, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_REFCOEFINIT_CH1, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_REFCOEFLAST_CH1, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_REFKP_CH1, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_REFCOEFLIMIT_CH1, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_REFCOMP_CH1, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_REFVALIDTAR_CH1, .rw = REG_RD_ACCESS, }, + { .reg = REG_REFRAWLAST_CH1, .rw = REG_RD_ACCESS, }, + { .reg = REG_BLNEWFILTERA_CH1, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_BLNEWFILTERB_CH1, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_THCOMPARE_CH1, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_THDELTA1_CH1, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_THDELTA2_CH1, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_JUDGE_CH1, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_REFRAWTH_CH2, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_REFCOEFMAX_CH2, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_REFCOEFMIN_CH2, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_REFCOEFINIT_CH2, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_REFCOEFLAST_CH2, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_REFKP_CH2, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_REFCOEFLIMIT_CH2, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_REFCOMP_CH2, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_REFVALIDTAR_CH2, .rw = REG_RD_ACCESS, }, + { .reg = REG_REFRAWLAST_CH2, .rw = REG_RD_ACCESS, }, + { .reg = REG_BLNEWFILTERA_CH2, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_BLNEWFILTERB_CH2, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_THCOMPARE_CH2, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_THDELTA1_CH2, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_THDELTA2_CH2, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_JUDGE_CH2, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_REFRAWTH_CH3, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_REFCOEFMAX_CH3, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_REFCOEFMIN_CH3, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_REFCOEFINIT_CH3, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_REFCOEFLAST_CH3, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_REFKP_CH3, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_REFCOEFLIMIT_CH3, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_REFCOMP_CH3, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_REFVALIDTAR_CH3, .rw = REG_RD_ACCESS, }, + { .reg = REG_REFRAWLAST_CH3, .rw = REG_RD_ACCESS, }, + { .reg = REG_BLNEWFILTERA_CH3, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_BLNEWFILTERB_CH3, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_THCOMPARE_CH3, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_THDELTA1_CH3, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_THDELTA2_CH3, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_JUDGE_CH3, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_REFRAWTH_CH4, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_REFCOEFMAX_CH4, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_REFCOEFMIN_CH4, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_REFCOEFINIT_CH4, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_REFCOEFLAST_CH4, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_REFKP_CH4, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_REFCOEFLIMIT_CH4, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_REFCOMP_CH4, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_REFVALIDTAR_CH4, .rw = REG_RD_ACCESS, }, + { .reg = REG_REFRAWLAST_CH4, .rw = REG_RD_ACCESS, }, + { .reg = REG_BLNEWFILTERA_CH4, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_BLNEWFILTERB_CH4, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_THCOMPARE_CH4, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_THDELTA1_CH4, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_THDELTA2_CH4, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_JUDGE_CH4, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_REFRAWTH_CH5, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_REFCOEFMAX_CH5, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_REFCOEFMIN_CH5, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_REFCOEFINIT_CH5, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_REFCOEFLAST_CH5, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_REFKP_CH5, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_REFCOEFLIMIT_CH5, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_REFCOMP_CH5, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_REFVALIDTAR_CH5, .rw = REG_RD_ACCESS, }, + { .reg = REG_REFRAWLAST_CH5, .rw = REG_RD_ACCESS, }, + { .reg = REG_BLNEWFILTERA_CH5, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_BLNEWFILTERB_CH5, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_THCOMPARE_CH5, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_THDELTA1_CH5, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_THDELTA2_CH5, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_JUDGE_CH5, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_REFRAWTH_CH6, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_REFCOEFMAX_CH6, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_REFCOEFMIN_CH6, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_REFCOEFINIT_CH6, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_REFCOEFLAST_CH6, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_REFKP_CH6, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_REFCOEFLIMIT_CH6, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_REFCOMP_CH6, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_REFVALIDTAR_CH6, .rw = REG_RD_ACCESS, }, + { .reg = REG_REFRAWLAST_CH6, .rw = REG_RD_ACCESS, }, + { .reg = REG_BLNEWFILTERA_CH6, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_BLNEWFILTERB_CH6, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_THCOMPARE_CH6, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_THDELTA1_CH6, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_THDELTA2_CH6, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_JUDGE_CH6, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_REFRAWTH_CH7, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_REFCOEFMAX_CH7, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_REFCOEFMIN_CH7, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_REFCOEFINIT_CH7, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_REFCOEFLAST_CH7, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_REFKP_CH7, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_REFCOEFLIMIT_CH7, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_REFCOMP_CH7, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_REFVALIDTAR_CH7, .rw = REG_RD_ACCESS, }, + { .reg = REG_REFRAWLAST_CH7, .rw = REG_RD_ACCESS, }, + { .reg = REG_BLNEWFILTERA_CH7, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_BLNEWFILTERB_CH7, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_THCOMPARE_CH7, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_THDELTA1_CH7, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_THDELTA2_CH7, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_JUDGE_CH7, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_REFRAWTH_CH8, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_REFCOEFMAX_CH8, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_REFCOEFMIN_CH8, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_REFCOEFINIT_CH8, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_REFCOEFLAST_CH8, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_REFKP_CH8, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_REFCOEFLIMIT_CH8, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_REFCOMP_CH8, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_REFVALIDTAR_CH8, .rw = REG_RD_ACCESS, }, + { .reg = REG_REFRAWLAST_CH8, .rw = REG_RD_ACCESS, }, + { .reg = REG_BLNEWFILTERA_CH8, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_BLNEWFILTERB_CH8, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_THCOMPARE_CH8, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_THDELTA1_CH8, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_THDELTA2_CH8, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_JUDGE_CH8, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_PIDCONTROLCFG, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_PIDCFG_CH0, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_PIDCFG_CH1, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_PIDCFG_CH2, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_PIDCFG_CH3, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_PIDCFG_CH4, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_PIDCFG_CH5, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_PIDCFG_CH6, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_PIDCFG_CH7, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_PIDCFG_CH8, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + + //STAT MAP + { .reg = REG_WST, .rw = REG_RD_ACCESS, }, + { .reg = REG_STAT0, .rw = REG_RD_ACCESS, }, + { .reg = REG_STAT1, .rw = REG_RD_ACCESS, }, + { .reg = REG_STAT2, .rw = REG_RD_ACCESS, }, + { .reg = REG_STAT3, .rw = REG_RD_ACCESS, }, + { .reg = REG_STAT4, .rw = REG_RD_ACCESS, }, + { .reg = REG_STAT5, .rw = REG_RD_ACCESS, }, + { .reg = REG_STAT7, .rw = REG_RD_ACCESS, }, + { .reg = REG_STAT8, .rw = REG_RD_ACCESS, }, + { .reg = REG_STAT9, .rw = REG_RD_ACCESS, }, + { .reg = REG_STAT10, .rw = REG_RD_ACCESS, }, + { .reg = REG_STAT11, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_STAT12, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_STAT13, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_STAT14, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_FWVER, .rw = REG_RD_ACCESS, }, + + //DATA MAP + { .reg = REG_BASELINE_CH0, .rw = REG_RD_ACCESS, }, + { .reg = REG_DIFF_CH0, .rw = REG_RD_ACCESS, }, + { .reg = REG_BASELINE_CH1, .rw = REG_RD_ACCESS, }, + { .reg = REG_DIFF_CH1, .rw = REG_RD_ACCESS, }, + { .reg = REG_BASELINE_CH2, .rw = REG_RD_ACCESS, }, + { .reg = REG_DIFF_CH2, .rw = REG_RD_ACCESS, }, + { .reg = REG_BASELINE_CH3, .rw = REG_RD_ACCESS, }, + { .reg = REG_DIFF_CH3, .rw = REG_RD_ACCESS, }, + { .reg = REG_BASELINE_CH4, .rw = REG_RD_ACCESS, }, + { .reg = REG_DIFF_CH4, .rw = REG_RD_ACCESS, }, + { .reg = REG_BASELINE_CH5, .rw = REG_RD_ACCESS, }, + { .reg = REG_DIFF_CH5, .rw = REG_RD_ACCESS, }, + { .reg = REG_BASELINE_CH6, .rw = REG_RD_ACCESS, }, + { .reg = REG_DIFF_CH6, .rw = REG_RD_ACCESS, }, + { .reg = REG_BASELINE_CH7, .rw = REG_RD_ACCESS, }, + { .reg = REG_DIFF_CH7, .rw = REG_RD_ACCESS, }, + { .reg = REG_BASELINE_CH8, .rw = REG_RD_ACCESS, }, + { .reg = REG_DIFF_CH8, .rw = REG_RD_ACCESS, }, + + //SFR MAP + { .reg = REG_IRQSRC, .rw = REG_RD_ACCESS, }, + { .reg = REG_IRQEN, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_I2CTIMEOUTEN, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_ANACFG, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_CHIPSTAT, .rw = REG_RD_ACCESS, }, + { .reg = REG_CHIP_ID0, .rw = REG_RD_ACCESS, }, + { .reg = REG_CHIP_ID1, .rw = REG_RD_ACCESS, }, + { .reg = REG_CHIP_ID2, .rw = REG_RD_ACCESS, }, + { .reg = REG_I3C_OSC_EN, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + + //MAP + { .reg = REG_BASELINE_OLD_CH0, .rw = REG_RD_ACCESS, }, + { .reg = REG_BASELINE_PRE_CH0, .rw = REG_RD_ACCESS, }, + { .reg = REG_AFECFG1_M_CH0, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_BASELINE_OLD_CH1, .rw = REG_RD_ACCESS, }, + { .reg = REG_BASELINE_PRE_CH1, .rw = REG_RD_ACCESS, }, + { .reg = REG_AFECFG1_M_CH1, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_BASELINE_OLD_CH2, .rw = REG_RD_ACCESS, }, + { .reg = REG_BASELINE_PRE_CH2, .rw = REG_RD_ACCESS, }, + { .reg = REG_AFECFG1_M_CH2, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_BASELINE_OLD_CH3, .rw = REG_RD_ACCESS, }, + { .reg = REG_BASELINE_PRE_CH3, .rw = REG_RD_ACCESS, }, + { .reg = REG_AFECFG1_M_CH3, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_BASELINE_OLD_CH4, .rw = REG_RD_ACCESS, }, + { .reg = REG_BASELINE_PRE_CH4, .rw = REG_RD_ACCESS, }, + { .reg = REG_AFECFG1_M_CH4, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_BASELINE_OLD_CH5, .rw = REG_RD_ACCESS, }, + { .reg = REG_BASELINE_PRE_CH5, .rw = REG_RD_ACCESS, }, + { .reg = REG_AFECFG1_M_CH5, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_BASELINE_OLD_CH6, .rw = REG_RD_ACCESS, }, + { .reg = REG_BASELINE_PRE_CH6, .rw = REG_RD_ACCESS, }, + { .reg = REG_AFECFG1_M_CH6, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_BASELINE_OLD_CH7, .rw = REG_RD_ACCESS, }, + { .reg = REG_BASELINE_PRE_CH7, .rw = REG_RD_ACCESS, }, + { .reg = REG_AFECFG1_M_CH7, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, + { .reg = REG_BASELINE_OLD_CH8, .rw = REG_RD_ACCESS, }, + { .reg = REG_BASELINE_PRE_CH8, .rw = REG_RD_ACCESS, }, + { .reg = REG_AFECFG1_M_CH8, .rw = REG_RD_ACCESS | REG_WR_ACCESS, }, +}; +static const uint32_t aw963xx_reg_default[] = { + 0x0000,0x000000FF, + 0x0004,0x00000FFF, + 0x0008,0x00000FFF, + 0x000C,0x00000064, + 0x0010,0x0000705F, + 0x0014,0x80000000, + 0x0060,0x00000000, + 0x0064,0x00000000, + 0x0068,0x00000000, + 0x006C,0x00000000, + 0x0070,0x00000000, + 0x0074,0x00000000, + 0x0078,0x00000000, + 0x007C,0x00000000, + 0x0080,0x00000000, + 0x0084,0x00000000, + 0x0088,0x00000000, + 0x008C,0x00000000, + 0x0168,0x00000000, + 0x016C,0x003F0000, + 0x0170,0x00050100, + 0x0174,0x00000000, + 0x0178,0x341C9207, + 0x017C,0x00008000, + 0x0180,0x00000909, + 0x0184,0x00000001, + 0x0188,0x00000000, + 0x0318,0x00000000, + 0x031C,0x003F0000, + 0x0320,0x00050100, + 0x0324,0x00000000, + 0x0328,0x341C9207, + 0x032C,0x00008000, + 0x0330,0x00000909, + 0x0334,0x00000008, + 0x0338,0x00000000, + 0x04C8,0x00000000, + 0x04CC,0x003F0000, + 0x04D0,0x00050100, + 0x04D4,0x00000000, + 0x04D8,0x341C9207, + 0x04DC,0x00008000, + 0x04E0,0x00000909, + 0x04E4,0x00000040, + 0x04E8,0x00000000, + 0x0678,0x00000000, + 0x067C,0x003F0000, + 0x0680,0x00050100, + 0x0684,0x00000000, + 0x0688,0x341C9207, + 0x068C,0x00008000, + 0x0690,0x00000909, + 0x0694,0x00000200, + 0x0698,0x00000000, + 0x0828,0x00000000, + 0x082C,0x003F0000, + 0x0830,0x00050100, + 0x0834,0x00000000, + 0x0838,0x341C9207, + 0x083C,0x00008000, + 0x0840,0x00000909, + 0x0844,0x00001000, + 0x0848,0x00000000, + 0x09D8,0x00000000, + 0x09DC,0x003F0000, + 0x09E0,0x00050100, + 0x09E4,0x00000000, + 0x09E8,0x341C9207, + 0x09EC,0x00008000, + 0x09F0,0x00000909, + 0x09F4,0x00008000, + 0x09F8,0x00000000, + 0x0B88,0x00000000, + 0x0B8C,0x003F0000, + 0x0B90,0x00050100, + 0x0B94,0x00000000, + 0x0B98,0x341C9207, + 0x0B9C,0x00008000, + 0x0BA0,0x00000909, + 0x0BA4,0x00040000, + 0x0BA8,0x00000000, + 0x0D38,0x00000000, + 0x0D3C,0x003F0000, + 0x0D40,0x00050100, + 0x0D44,0x00000000, + 0x0D48,0x341C9207, + 0x0D4C,0x00008000, + 0x0D50,0x00000909, + 0x0D54,0x00200000, + 0x0D58,0x00000000, + 0x0EE8,0x00000000, + 0x0EEC,0x003F0000, + 0x0EF0,0x00050100, + 0x0EF4,0x00000000, + 0x0EF8,0x341C9207, + 0x0EFC,0x00008000, + 0x0F00,0x00000909, + 0x0F04,0x00000000, + 0x0F08,0x00000000, + 0x1098,0x00000000, + 0x109C,0x003F0000, + 0x10A0,0x00050100, + 0x10A4,0x00000000, + 0x10A8,0x341C9207, + 0x10AC,0x00008000, + 0x10B0,0x00000909, + 0x10B4,0x00000000, + 0x10B8,0x00000000, + 0x1248,0x00000000, + 0x124C,0x003F0000, + 0x1250,0x00050100, + 0x1254,0x00000000, + 0x1258,0x341C9207, + 0x125C,0x00008000, + 0x1260,0x00000909, + 0x1264,0x00000000, + 0x1268,0x00000000, + 0x13F8,0x00000000, + 0x13FC,0x003F0000, + 0x1400,0x00050100, + 0x1404,0x00000000, + 0x1408,0x341C9207, + 0x140C,0x00008000, + 0x1410,0x00000909, + 0x1414,0x00000000, + 0x1418,0x00000000, + 0x018C,0xE0400000, + 0x0190,0x00000000, + 0x0194,0x00000000, + 0x0198,0x000A0000, + 0x019C,0x000008D2, + 0x01A0,0x00000000, + 0x01A4,0x00000040, + 0x01A8,0x000186A0, + 0x01AC,0x00030D40, + 0x01B0,0x00061A80, + 0x01B4,0x000C3500, + 0x01B8,0x00000000, + 0x01BC,0x00000000, + 0x01C0,0x00000000, + 0x01C4,0x00000000, + 0x01C8,0x00000000, + 0x01CC,0x00000000, + 0x033C,0xE0400000, + 0x0340,0x00000000, + 0x0344,0x00000000, + 0x0348,0x000A0000, + 0x034C,0x000008D2, + 0x0350,0x00000000, + 0x0354,0x00000040, + 0x0358,0x000186A0, + 0x035C,0x00030D40, + 0x0360,0x00061A80, + 0x0364,0x000C3500, + 0x0368,0x00000000, + 0x036C,0x00000000, + 0x0370,0x00000000, + 0x0374,0x00000000, + 0x0378,0x00000000, + 0x037C,0x00000000, + 0x04EC,0xE0400000, + 0x04F0,0x00000000, + 0x04F4,0x00000000, + 0x04F8,0x000A0000, + 0x04FC,0x000008D2, + 0x0500,0x00000000, + 0x0504,0x00000040, + 0x0508,0x000186A0, + 0x050C,0x00030D40, + 0x0510,0x00061A80, + 0x0514,0x000C3500, + 0x0518,0x00000000, + 0x051C,0x00000000, + 0x0520,0x00000000, + 0x0524,0x00000000, + 0x0528,0x00000000, + 0x052C,0x00000000, + 0x069C,0xE0400000, + 0x06A0,0x00000000, + 0x06A4,0x00000000, + 0x06A8,0x000A0000, + 0x06AC,0x000008D2, + 0x06B0,0x00000000, + 0x06B4,0x00000040, + 0x06B8,0x000186A0, + 0x06BC,0x00030D40, + 0x06C0,0x00061A80, + 0x06C4,0x000C3500, + 0x06C8,0x00000000, + 0x06CC,0x00000000, + 0x06D0,0x00000000, + 0x06D4,0x00000000, + 0x06D8,0x00000000, + 0x06DC,0x00000000, + 0x084C,0xE0400000, + 0x0850,0x00000000, + 0x0854,0x00000000, + 0x0858,0x000A0000, + 0x085C,0x000008D2, + 0x0860,0x00000000, + 0x0864,0x00000040, + 0x0868,0x000186A0, + 0x086C,0x00030D40, + 0x0870,0x00061A80, + 0x0874,0x000C3500, + 0x0878,0x00000000, + 0x087C,0x00000000, + 0x0880,0x00000000, + 0x0884,0x00000000, + 0x0888,0x00000000, + 0x088C,0x00000000, + 0x09FC,0xE0400000, + 0x0A00,0x00000000, + 0x0A04,0x00000000, + 0x0A08,0x000A0000, + 0x0A0C,0x000008D2, + 0x0A10,0x00000000, + 0x0A14,0x00000040, + 0x0A18,0x000186A0, + 0x0A1C,0x00030D40, + 0x0A20,0x00061A80, + 0x0A24,0x000C3500, + 0x0A28,0x00000000, + 0x0A2C,0x00000000, + 0x0A30,0x00000000, + 0x0A34,0x00000000, + 0x0A38,0x00000000, + 0x0A3C,0x00000000, + 0x0BAC,0xE0400000, + 0x0BB0,0x00000000, + 0x0BB4,0x00000000, + 0x0BB8,0x000A0000, + 0x0BBC,0x000008D2, + 0x0BC0,0x00000000, + 0x0BC4,0x00000040, + 0x0BC8,0x000186A0, + 0x0BCC,0x00030D40, + 0x0BD0,0x00061A80, + 0x0BD4,0x000C3500, + 0x0BD8,0x00000000, + 0x0BDC,0x00000000, + 0x0BE0,0x00000000, + 0x0BE4,0x00000000, + 0x0BE8,0x00000000, + 0x0BEC,0x00000000, + 0x0D5C,0xE0400000, + 0x0D60,0x00000000, + 0x0D64,0x00000000, + 0x0D68,0x000A0000, + 0x0D6C,0x000008D2, + 0x0D70,0x00000000, + 0x0D74,0x00000040, + 0x0D78,0x000186A0, + 0x0D7C,0x00030D40, + 0x0D80,0x00061A80, + 0x0D84,0x000C3500, + 0x0D88,0x00000000, + 0x0D8C,0x00000000, + 0x0D90,0x00000000, + 0x0D94,0x00000000, + 0x0D98,0x00000000, + 0x0D9C,0x00000000, + 0x0F0C,0xE0400000, + 0x0F10,0x00000000, + 0x0F14,0x00000000, + 0x0F18,0x000A0000, + 0x0F1C,0x000008D2, + 0x0F20,0x00000000, + 0x0F24,0x00000040, + 0x0F28,0x000186A0, + 0x0F2C,0x00000000, + 0x0F30,0x00000000, + 0x0F34,0x00000000, + 0x0F38,0x00000000, + 0x0F3C,0x00000000, + 0x0F40,0x00000000, + 0x0F44,0x00000000, + 0x0F48,0x00000000, + 0x0F4C,0x00000000, + 0x10BC,0xE0400000, + 0x10C0,0x00000000, + 0x10C4,0x00000000, + 0x10C8,0x000A0000, + 0x10CC,0x000008D2, + 0x10D0,0x00000000, + 0x10D4,0x00000040, + 0x10D8,0x00000000, + 0x10DC,0x00000000, + 0x10E0,0x00000000, + 0x10E4,0x00000000, + 0x10E8,0x00000000, + 0x10EC,0x00000000, + 0x10F0,0x00000000, + 0x10F4,0x00000000, + 0x10F8,0x00000000, + 0x10FC,0x00000000, + 0x126C,0xE0400000, + 0x1270,0x00000000, + 0x1274,0x00000000, + 0x1278,0x000A0000, + 0x127C,0x000008D2, + 0x1280,0x00000000, + 0x1284,0x00000040, + 0x1288,0x00000000, + 0x128C,0x00000000, + 0x1290,0x00000000, + 0x1294,0x00000000, + 0x1298,0x00000000, + 0x129C,0x00000000, + 0x12A0,0x00000000, + 0x12A4,0x00000000, + 0x12A8,0x00000000, + 0x12AC,0x00000000, + 0x141C,0xE0400000, + 0x1420,0x00000000, + 0x1424,0x00000000, + 0x1428,0x000A0000, + 0x142C,0x000008D2, + 0x1430,0x00000000, + 0x1434,0x00000040, + 0x1438,0x00000000, + 0x143C,0x00000000, + 0x1440,0x00000000, + 0x1444,0x00000000, + 0x1448,0x00000000, + 0x144C,0x00000000, + 0x1450,0x00000000, + 0x1454,0x00000000, + 0x1458,0x00000000, + 0x145C,0x00000000, + 0x01D0,0x00000000, + 0x01D4,0x00000000, + 0x01D8,0x00000000, + 0x01DC,0x00000000, + 0x01E0,0x00000000, + 0x01E4,0xFFFFFFFF, + 0x01E8,0x00000000, + 0x01EC,0x00000000, + 0x01F0,0x00000000, + 0x01F4,0x00000000, + 0x01F8,0x070004B0, + 0x01FC,0x0E000000, + 0x0200,0xF2000000, + 0x0204,0x02000000, + 0x0208,0x02000000, + 0x020C,0x00002000, + 0x0210,0x00010000, + 0x0214,0x80007530, + 0x0220,0x00000000, + 0x0224,0x00000000, + 0x0380,0x00000000, + 0x0384,0x00000000, + 0x0388,0x00000000, + 0x038C,0x00000000, + 0x0390,0x00000000, + 0x0394,0xFFFFFFFF, + 0x0398,0x00000000, + 0x039C,0x00000000, + 0x03A0,0x00000000, + 0x03A4,0x00000000, + 0x03A8,0x070004B0, + 0x03AC,0x0E000000, + 0x03B0,0xF2000000, + 0x03B4,0x02000000, + 0x03B8,0x02000000, + 0x03BC,0x00002000, + 0x03C0,0x00010000, + 0x03C4,0x80007530, + 0x03D0,0x00000000, + 0x03D4,0x00000000, + 0x0530,0x00000000, + 0x0534,0x00000000, + 0x0538,0x00000000, + 0x053C,0x00000000, + 0x0540,0x00000000, + 0x0544,0xFFFFFFFF, + 0x0548,0x00000000, + 0x054C,0x00000000, + 0x0550,0x00000000, + 0x0554,0x00000000, + 0x0558,0x070004B0, + 0x055C,0x0E000000, + 0x0560,0xF2000000, + 0x0564,0x02000000, + 0x0568,0x02000000, + 0x056C,0x00002000, + 0x0570,0x00010000, + 0x0574,0x80007530, + 0x0580,0x00000000, + 0x0584,0x00000000, + 0x06E0,0x00000000, + 0x06E4,0x00000000, + 0x06E8,0x00000000, + 0x06EC,0x00000000, + 0x06F0,0x00000000, + 0x06F4,0xFFFFFFFF, + 0x06F8,0x00000000, + 0x06FC,0x00000000, + 0x0700,0x00000000, + 0x0704,0x00000000, + 0x0708,0x070004B0, + 0x070C,0x0E000000, + 0x0710,0xF2000000, + 0x0714,0x02000000, + 0x0718,0x02000000, + 0x071C,0x00002000, + 0x0720,0x00010000, + 0x0724,0x80007530, + 0x0730,0x00000000, + 0x0734,0x00000000, + 0x0890,0x00000000, + 0x0894,0x00000000, + 0x0898,0x00000000, + 0x089C,0x00000000, + 0x08A0,0x00000000, + 0x08A4,0xFFFFFFFF, + 0x08A8,0x00000000, + 0x08AC,0x00000000, + 0x08B0,0x00000000, + 0x08B4,0x00000000, + 0x08B8,0x070004B0, + 0x08BC,0x0E000000, + 0x08C0,0xF2000000, + 0x08C4,0x02000000, + 0x08C8,0x02000000, + 0x08CC,0x00002000, + 0x08D0,0x00010000, + 0x08D4,0x80007530, + 0x08E0,0x00000000, + 0x08E4,0x00000000, + 0x0A40,0x00000000, + 0x0A44,0x00000000, + 0x0A48,0x00000000, + 0x0A4C,0x00000000, + 0x0A50,0x00000000, + 0x0A54,0xFFFFFFFF, + 0x0A58,0x00000000, + 0x0A5C,0x00000000, + 0x0A60,0x00000000, + 0x0A64,0x00000000, + 0x0A68,0x070004B0, + 0x0A6C,0x0E000000, + 0x0A70,0xF2000000, + 0x0A74,0x02000000, + 0x0A78,0x02000000, + 0x0A7C,0x00002000, + 0x0A80,0x00010000, + 0x0A84,0x80007530, + 0x0A90,0x00000000, + 0x0A94,0x00000000, + 0x0BF0,0x00000000, + 0x0BF4,0x00000000, + 0x0BF8,0x00000000, + 0x0BFC,0x00000000, + 0x0C00,0x00000000, + 0x0C04,0xFFFFFFFF, + 0x0C08,0x00000000, + 0x0C0C,0x00000000, + 0x0C10,0x00000000, + 0x0C14,0x00000000, + 0x0C18,0x070004B0, + 0x0C1C,0x0E000000, + 0x0C20,0xF2000000, + 0x0C24,0x02000000, + 0x0C28,0x02000000, + 0x0C2C,0x00002000, + 0x0C30,0x00010000, + 0x0C34,0x80007530, + 0x0C40,0x00000000, + 0x0C44,0x00000000, + 0x0DA0,0x00000000, + 0x0DA4,0x00000000, + 0x0DA8,0x00000000, + 0x0DAC,0x00000000, + 0x0DB0,0x00000000, + 0x0DB4,0xFFFFFFFF, + 0x0DB8,0x00000000, + 0x0DBC,0x00000000, + 0x0DC0,0x00000000, + 0x0DC4,0x00000000, + 0x0DC8,0x070004B0, + 0x0DCC,0x0E000000, + 0x0DD0,0xF2000000, + 0x0DD4,0x02000000, + 0x0DD8,0x02000000, + 0x0DDC,0x00002000, + 0x0DE0,0x00010000, + 0x0DE4,0x80007530, + 0x0DF0,0x00000000, + 0x0DF4,0x00000000, + 0x0F50,0x00000000, + 0x0F54,0x00000000, + 0x0F58,0x00000000, + 0x0F5C,0x00000000, + 0x0F60,0x00000000, + 0x0F64,0xFFFFFFFF, + 0x0F68,0x00000000, + 0x0F6C,0x00000000, + 0x0F70,0x00000000, + 0x0F74,0x00000000, + 0x0F78,0x070004B0, + 0x0F7C,0x0E000000, + 0x0F80,0xF2000000, + 0x0F84,0x02000000, + 0x0F88,0x02000000, + 0x0F8C,0x00002000, + 0x0F90,0x00010000, + 0x0F94,0x80007530, + 0x0FA0,0x00000000, + 0x0FA4,0x00000000, + 0x1100,0x00000000, + 0x1104,0x00000000, + 0x1108,0x00000000, + 0x110C,0x00000000, + 0x1110,0x00000000, + 0x1114,0xFFFFFFFF, + 0x1118,0x00000000, + 0x111C,0x00000000, + 0x1120,0x00000000, + 0x1124,0x00000000, + 0x1128,0x070004B0, + 0x112C,0x0E000000, + 0x1130,0xF2000000, + 0x1134,0x02000000, + 0x1138,0x02000000, + 0x113C,0x00002000, + 0x1140,0x00010000, + 0x1144,0x80007530, + 0x1150,0x00000000, + 0x1154,0x00000000, + 0x12B0,0x00000000, + 0x12B4,0x00000000, + 0x12B8,0x00000000, + 0x12BC,0x00000000, + 0x12C0,0x00000000, + 0x12C4,0xFFFFFFFF, + 0x12C8,0x00000000, + 0x12CC,0x00000000, + 0x12D0,0x00000000, + 0x12D4,0x00000000, + 0x12D8,0x070004B0, + 0x12DC,0x0E000000, + 0x12E0,0xF2000000, + 0x12E4,0x02000000, + 0x12E8,0x02000000, + 0x12EC,0x00002000, + 0x12F0,0x00010000, + 0x12F4,0x80007530, + 0x1300,0x00000000, + 0x1304,0x00000000, + 0x1460,0x00000000, + 0x1464,0x00000000, + 0x1468,0x00000000, + 0x146C,0x00000000, + 0x1470,0x00000000, + 0x1474,0xFFFFFFFF, + 0x1478,0x00000000, + 0x147C,0x00000000, + 0x1480,0x00000000, + 0x1484,0x00000000, + 0x1488,0x070004B0, + 0x148C,0x0E000000, + 0x1490,0xF2000000, + 0x1494,0x02000000, + 0x1498,0x02000000, + 0x149C,0x00002000, + 0x14A0,0x00010000, + 0x14A4,0x80007530, + 0x14B0,0x00000000, + 0x14B4,0x00000000, + 0xF084,0x00000006, + 0x004C,0xFFFFFFFF, + 0x0050,0xFFFFFFFF, + 0x0054,0xFFFFFFFF, + 0x0058,0xFFFFFFFF, + 0x0090,0x00000000, + 0x0094,0x00000064, + 0x0098,0x40000000, + 0x009C,0x00000000, + 0x00A0,0x00140014, + 0x00A4,0x0019000D, + 0x00A8,0x0096004B, +}; +#endif diff --git a/include/linux/input/awinic/aw_sar.h b/include/linux/input/awinic/aw_sar.h new file mode 100644 index 000000000000..cf0ebfc425d1 --- /dev/null +++ b/include/linux/input/awinic/aw_sar.h @@ -0,0 +1,13 @@ +#ifndef AW_SAR_H_ +#define AW_SAR_H_ + +void aw_sar_disable_irq(struct aw_sar *p_sar); +void aw_sar_enable_irq(struct aw_sar *p_sar); + +int32_t aw_sar_soft_reset(struct aw_sar *p_sar); +int32_t aw_sar_check_init_over_irq(struct aw_sar *p_sar); +int32_t aw_sar_update_fw(struct aw_sar *p_sar); +int32_t aw_sar_load_def_reg_bin(struct aw_sar *p_sar); +void aw_sar_mode_set(struct aw_sar *p_sar, uint8_t curr_mode); +int32_t aw_sar_update_reg_set_func(struct aw_sar *p_sar); +#endif \ No newline at end of file diff --git a/include/linux/input/awinic/aw_sar_chip_interface.h b/include/linux/input/awinic/aw_sar_chip_interface.h new file mode 100644 index 000000000000..e26e06a2f584 --- /dev/null +++ b/include/linux/input/awinic/aw_sar_chip_interface.h @@ -0,0 +1,33 @@ +#ifndef _SAR_SUPPORT_CHIP_H_ +#define _SAR_SUPPORT_CHIP_H_ +#include "aw_sar_type.h" + +enum aw_sar_driver_list_t { + AW_SAR_AW9610X, + AW_SAR_AW9620X, + AW_SAR_AW963XX, + + AW_SAR_DRIVER_MAX, +}; + +int32_t aw9610x_check_chipid(void *data); +int32_t aw9610x_init(struct aw_sar *p_sar); +void aw9610x_deinit(struct aw_sar *p_sar); + +int32_t aw9620x_check_chipid(void *data); +int32_t aw9620x_init(struct aw_sar *p_sar); +void aw9620x_deinit(struct aw_sar *p_sar); + +int32_t aw963xx_check_chipid(void *data); +int32_t aw963xx_init(struct aw_sar *p_sar); +void aw963xx_deinit(struct aw_sar *p_sar); + + +static const struct aw_sar_driver_type g_aw_sar_driver_list[] = { + { AW_SAR_AW9610X, aw9610x_check_chipid, aw9610x_init, aw9610x_deinit }, + { AW_SAR_AW9620X, aw9620x_check_chipid, aw9620x_init, aw9620x_deinit }, + { AW_SAR_AW963XX, aw963xx_check_chipid, aw963xx_init, aw963xx_deinit }, +}; + + +#endif diff --git a/include/linux/input/awinic/aw_sar_comm_interface.h b/include/linux/input/awinic/aw_sar_comm_interface.h new file mode 100644 index 000000000000..796aa39004f5 --- /dev/null +++ b/include/linux/input/awinic/aw_sar_comm_interface.h @@ -0,0 +1,221 @@ +#ifndef _AW_SAR_PLAT_HW_INTERFACE_H_ +#define _AW_SAR_PLAT_HW_INTERFACE_H_ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +enum aw_sar_chip_list_t { + AW_SAR_NONE_CHECK_CHIP, + + SAR_AW9610X = 1 << 1, + SAR_AW9610XA = 1 << 2, + + SAR_AW96203 = 1 << 3, + SAR_AW96205 = 1 << 4, + SAR_AW96208 = 1 << 5, + + SAR_AW96303 = 1 << 6, + SAR_AW96305 = 1 << 7, + SAR_AW96308 = 1 << 8, + SAR_AW96310 = 1 << 9, + SAR_AW96312 = 1 << 10, +}; + +enum AW_SAR_UPDATE_FW_MODE { + PROT_UPDATE_FW, + REG_UPDATE_FW, +}; + +#define AW_SAR_LABLE " " +#define AW_SAR_FILENAME(x) strrchr((x), '/') ? (strrchr((x), '/') + 1) : (x) +//dev_dbg +#define AW_SAR_DEBUG_LOG +#ifdef AW_SAR_DEBUG_LOG +#define AWLOGD(dev, format, arg...) \ + do {\ + dev_dbg(dev, \ + AW_SAR_LABLE"[%s:%s:%d] "format"\n", AW_SAR_FILENAME(__FILE__), __func__, __LINE__, ##arg);\ + } while (0) +#else +#define AWLOGD(dev, format, arg...) +#endif + +#define AW_SAR_INFO_LOG +#ifdef AW_SAR_INFO_LOG +#define AWLOGI(dev, format, arg...) \ + do {\ + dev_info(dev, \ + AW_SAR_LABLE"[%s:%s:%d] "format"\n", AW_SAR_FILENAME(__FILE__), __func__, __LINE__, ##arg);\ + } while (0) +#else +#define AWLOGI(dev, format, arg...) +#endif + +#define AW_SAR_ERR_LOG +#ifdef AW_SAR_ERR_LOG +#define AWLOGE(dev, format, arg...) \ + do {\ + dev_err(dev, \ + AW_SAR_LABLE"[%s:%s:%d] "format"\n", AW_SAR_FILENAME(__FILE__), __func__, __LINE__, ##arg);\ + } while (0) +#else +#define AWLOGE(dev, format, arg...) +#endif + +#ifndef AW_TRUE +#define AW_TRUE (1) +#endif + +#ifndef AW_FALSE +#define AW_FALSE (0) +#endif + +/* +typedef unsigned char uint8_t; +typedef unsigned short uint16_t; +typedef unsigned int uint32_t; + +typedef char int8_t; +typedef short int16_t; +typedef int int32_t; + +typedef uint8_t bool; +*/ +enum aw_sar_rst_val { + AW_OK, + AW_ERR, + AW_PARA_ERR, + AW_VERS_ERR, + AW_ERR_CHIPID, + AW_ERR_IRQ_INIT_OVER, + AW_PROT_UPDATE_ERR, + AW_REG_LOAD_ERR, + AW_INVALID_PARA, + AW_BIN_PARA_INVALID, + + AW_FW_CHECK_ERR, + AW_BT_CHECK_ERR, + AW_OTEHR_CHECK_ERR, + AW_BIN_NAME_CHECK_ERR, +}; + +#define AW_SAR_FLIP_U16(value) ((((value) & (0x00FF)) << (8)) | (((value) & (0xFF00)) >> (8))) +#define AW_SAR_FLIP_U32(value) ((((value) & (0x000000FF)) << (24)) | ((((value) & (0x0000FF00))) << (8)) | (((value) & (0x00FF0000)) >> (8)) | (((value) & (0xFF000000)) >> (24))) + +#ifndef OFFSET_BIT_0 +#define OFFSET_BIT_0 (0) +#endif + +#ifndef OFFSET_BIT_8 +#define OFFSET_BIT_8 (8) +#endif + +#ifndef OFFSET_BIT_16 +#define OFFSET_BIT_16 (16) +#endif + +#ifndef OFFSET_BIT_24 +#define OFFSET_BIT_24 (24) +#endif + +#ifndef WORD_LEN +#define WORD_LEN (4) +#endif + +#ifndef GET_BITS_7_0 +#define GET_BITS_7_0 (0x00FF) +#endif + +#ifndef GET_BITS_15_8 +#define GET_BITS_15_8 (0xFF00) +#endif + +#ifndef GET_BITS_24_16 +#define GET_BITS_24_16 (0x00FF0000) +#endif + +#ifndef GET_BITS_31_25 +#define GET_BITS_31_25 (0xFF000000) +#endif + +#define AW_SAR_ABS(x) (((x) > 0) ? (x) : (-(x))) +#define AW_SAR_GET_32_DATA(w, x, y, z) ((unsigned int)(((w) << 24) | ((x) << 16) | ((y) << 8) | (z))) +#define AW_SAR_GET_16_DATA(a, b) (((uint32_t)(a) << (8)) | ((uint32_t)(b) << (0))) + +enum AW_SAR_HOST_IRQ_STAT { + IRQ_ENABLE, + IRQ_DISABLE, +}; + +#define AW_SAR_BIN_NUM_MAX 100 +#define AW_SAR_HEADER_LEN 60 + +struct bin_header_info { + unsigned int header_len; /* Frame header length */ + unsigned int check_sum; /* Frame header information-Checksum */ + unsigned int header_ver; /* Frame header information-Frame header version */ + unsigned int bin_data_type; /* Frame header information-Data type */ + unsigned int bin_data_ver; /* Frame header information-Data version */ + unsigned int bin_data_len; /* Frame header information-Data length */ + unsigned int ui_ver; /* Frame header information-ui version */ + unsigned char chip_type[8]; /* Frame header information-chip type */ + unsigned int reg_byte_len; /* Frame header information-reg byte len */ + unsigned int data_byte_len; /* Frame header information-data byte len */ + unsigned int device_addr; /* Frame header information-device addr */ + unsigned int valid_data_len; /* Length of valid data obtained after parsing */ + unsigned int valid_data_addr; /* The offset address of the valid data obtained after parsing relative to info */ + + unsigned int reg_num; /* The number of registers obtained after parsing */ + unsigned int reg_data_byte_len; /* The byte length of the register obtained after parsing */ + unsigned int download_addr; /* The starting address or download address obtained after parsing */ + unsigned int app_version; /* The software version number obtained after parsing */ +}; + +struct bin_container { + unsigned int len; /* The size of the bin file obtained from the firmware */ + unsigned char data[]; /* Store the bin file obtained from the firmware */ +}; + +struct aw_bin { + char *p_addr; /* Offset pointer (backward offset pointer to obtain frame header information and important information) */ + unsigned int all_bin_parse_num; /* The number of all bin files */ + unsigned int multi_bin_parse_num; /* The number of single bin files */ + unsigned int single_bin_parse_num; /* The number of multiple bin files */ + struct bin_header_info header_info[AW_SAR_BIN_NUM_MAX]; /* Frame header information and other important data obtained after parsing */ + struct bin_container info; /* Obtained bin file data that needs to be parsed */ +}; + +//I2C communication API +extern int32_t aw_sar_i2c_read(struct i2c_client *i2c, uint16_t reg_addr16, uint32_t *reg_data32); +extern int32_t aw_sar_i2c_write(struct i2c_client *i2c, uint16_t reg_addr16, uint32_t reg_data32); +extern int32_t aw_sar_i2c_write_bits(struct i2c_client *i2c, uint16_t reg_addr16, uint32_t mask, uint32_t val); +extern int32_t aw_sar_i2c_write_seq(struct i2c_client *i2c, uint8_t *tr_data, uint16_t len); +extern int32_t aw_sar_i2c_read_seq(struct i2c_client *i2c, uint8_t *addr, uint8_t addr_len, uint8_t *data, uint16_t data_len); +extern void aw_sar_delay_ms(uint32_t ms); + +extern int aw_sar_parsing_bin_file(struct aw_bin *bin); +extern uint32_t aw_sar_pow2(uint32_t cnt); +extern int32_t aw_sar_load_reg(struct aw_bin *aw_bin, struct i2c_client *i2c); + +#endif diff --git a/include/linux/input/awinic/aw_sar_type.h b/include/linux/input/awinic/aw_sar_type.h new file mode 100644 index 000000000000..21173b7d8d29 --- /dev/null +++ b/include/linux/input/awinic/aw_sar_type.h @@ -0,0 +1,359 @@ +#ifndef _SAR_TYPE_H_ +#define _SAR_TYPE_H_ + +#include "aw_sar_comm_interface.h" + +typedef int32_t (*aw_sar_chip_other_operation_t)(void *data); +typedef void (*aw_sar_chip_other_opera_free_t)(void *data); + +enum aw_i2c_flags { + AW_SAR_I2C_WR, + AW_SAR_I2C_RD, + AW_SAR_PACKAGE_RD, +}; + +typedef int32_t (*aw_sar_bin_opera_t)(struct aw_bin *aw_bin, void *load_bin_para); +typedef int32_t (*aw_sar_bin_load_fail_opera_t)(struct aw_bin *aw_bin, void *load_bin_para); + +struct aw_sar_get_chip_info_t { + void (*p_get_chip_info_node_fn)(void *data, char *buf, ssize_t *p_len); +}; + +struct aw_sar_load_bin_t { + const uint8_t *bin_name; + aw_sar_bin_opera_t bin_opera_func; + aw_sar_bin_load_fail_opera_t bin_load_fail_opera; + + void (*p_get_prot_update_fw_node_fn)(void *data, char *buf, ssize_t *p_len); + + /*Perform different operations to update parameters*/ + int32_t (*p_update_fn)(void *data); +}; + +struct aw_sar_reg_data { + unsigned char rw; + unsigned short reg; +}; + +struct aw_sar_awrw_t { + ssize_t (*p_set_awrw_node_fn)(void *data, const char *buf, size_t count); + ssize_t (*p_get_awrw_node_fn)(void *data, char *buf); +}; + +struct aw_sar_reg_list_t { + uint8_t reg_none_access; + uint8_t reg_rd_access; + uint8_t reg_wd_access; + const struct aw_sar_reg_data *reg_perm; + uint32_t reg_num; +}; + +typedef void (*aw_sar_update_work_t)(struct work_struct *work); +struct aw_sar_update_static_t { + aw_sar_update_work_t update_work_func; + uint32_t delay_ms; +}; + +typedef irqreturn_t (*aw_sar_irq_t)(int irq, void *data); +typedef uint32_t (*sar_rc_irqscr_t)(void *i2c); +//If the return value is 1, there is an initialization completion interrupt; if the return value is 0, there is no +typedef uint32_t (*aw_sar_is_init_over_irq)(uint32_t irq_status); +typedef void (*aw_sar_irq_spec_handler_t)(uint32_t irq_status, void *data); + +struct aw_sar_check_chipid_t { + /*Read chipid and check chipid, Must be implemented externally*/ + int32_t (*p_check_chipid_fn)(void *data); +}; + +struct aw_sar_irq_init_t { + unsigned long flags; + unsigned long irq_flags; + irq_handler_t handler; + irq_handler_t thread_fn; + /*Interrupt processing parameters*/ + sar_rc_irqscr_t rc_irq_fn; + //aw_sar_is_init_over_irq is_init_over_irq_fn; + aw_sar_irq_spec_handler_t irq_spec_handler_fn; + + /*Use a different initialization interrupt to initialize the operation*/ + int32_t (*p_irq_init_fn)(void *data); + /*Release interrupt resource*/ +// void const (*p_irq_deinit_fn)(void *data); + int (*p_irq_deinit_fn)(void *data); +}; + +struct aw_sar_pm_t { + uint32_t suspend_set_mode; + uint32_t resume_set_mode; + uint32_t shutdown_set_mode; + //system api + int32_t (*p_suspend_fn)(void *data); + int32_t (*p_resume_fn)(void *data); + int32_t (*p_shutdown_fn)(void *data); +}; + +struct aw_sar_chip_mode_t { + uint32_t init_mode; + uint32_t active; + uint32_t pre_init_mode; +}; + +struct aw_sar_regulator_config_t { + //Note that "_sar_num" after VCC name is defined by SAR C auto add + const uint8_t *vcc_name; + int32_t min_uV; + int32_t max_uV; +}; + +struct aw_channels_info { + uint16_t used; + uint32_t last_channel_info; + struct input_dev *input; + uint8_t name[20]; +}; + +struct aw_sar_dts_info { + uint32_t sar_num; + int32_t irq_gpio; + uint32_t channel_use_flag; + bool use_regulator_flag; + bool use_inter_pull_up; + bool use_pm; + bool update_fw_flag; + bool use_plug_cail_flag; +}; + +struct aw_sar_irq_init_comm_t { + int32_t to_irq; + uint8_t host_irq_stat; + void *data; + uint8_t label[30]; + uint8_t dev_id[30]; +}; + +struct aw_sar_load_bin_comm_t { + uint8_t bin_name[30]; + aw_sar_bin_opera_t bin_opera_func; + aw_sar_bin_load_fail_opera_t bin_load_fail_opera_func; +}; + +struct aw_awrw_info { + uint8_t rw_flag; + uint8_t addr_len; + uint8_t data_len; + uint8_t reg_num; + uint32_t i2c_tranfar_data_len; + uint8_t *p_i2c_tranfar_data; +}; + +/****************mode set start******************/ +typedef void (*sar_enable_clock_t)(void *i2c); +typedef void (*sar_operation_irq_t)(int to_irq); +typedef void (*sar_mode_update_t)(void *i2c); + +struct aw_sar_mode_switch_ops { + sar_enable_clock_t enable_clock; + sar_rc_irqscr_t rc_irqscr; + sar_mode_update_t mode_update; +}; + +struct aw_sar_chip_mode { + uint8_t curr_mode; + uint8_t last_mode; +}; + +struct aw_sar_mode_set_t { + uint8_t chip_id; + struct aw_sar_chip_mode chip_mode; + struct aw_sar_mode_switch_ops mode_switch_ops; +}; + +struct aw_sar_mode_t { + const struct aw_sar_mode_set_t *mode_set_arr; + uint8_t mode_set_arr_len; + ssize_t (*p_set_mode_node_fn)(void *data, uint8_t curr_mode); + ssize_t (*p_get_mode_node_fn)(void *data, char *buf); +}; +/********************mode set end****************/ + +struct aw_sar_init_over_irq_t { + int16_t wait_times; + uint8_t daley_step; + uint32_t reg_irqsrc; + uint32_t irq_offset_bit; + uint32_t irq_mask; + uint32_t irq_flag; + /*Perform different verification initialization to complete the interrupt operation*/ + int32_t (*p_check_init_over_irq_fn)(void *data); + /*When initialization fails, get the corresponding error type and apply it to the chip with flash*/ + int32_t (*p_get_err_type_fn)(void *data); +}; + +struct aw_sar_soft_rst_t { + uint16_t reg_rst; + uint32_t reg_rst_val; + uint32_t delay_ms; + /*Perform different soft reset operations*/ + int32_t (*p_soft_reset_fn)(void *data); +}; + +struct aw_sar_aot_t { + uint32_t aot_reg; + uint32_t aot_mask; + uint32_t aot_flag; + ssize_t (*p_set_aot_node_fn)(void *data); +}; + +struct aw_sar_diff_t { + uint16_t diff0_reg; + uint16_t diff_step; + //Data format:S21.10, Floating point types generally need to be removed + uint32_t rm_float; + + ssize_t (*p_get_diff_node_fn)(void *data, char *buf); +}; + +struct aw_sar_offset_t { + ssize_t (*p_get_offset_node_fn)(void *data, char *buf); +}; + +struct aw_sar_pinctrl { + struct pinctrl *pinctrl; + struct pinctrl_state *default_sta; + struct pinctrl_state *int_out_high; + struct pinctrl_state *int_out_low; +}; + +//update reg node +struct aw_sar_para_load_t { + const uint32_t *reg_arr; + uint32_t reg_arr_len; +}; + +struct aw_sar_platform_config { + /*The chip needs to parse more DTS contents for addition*/ + int32_t (*p_add_parse_dts_fn)(void *data); + + const struct aw_sar_regulator_config_t *p_regulator_config; + + /*The chip needs to add more nodes*/ + int32_t (*p_add_node_create_fn)(void *data); + /*Release the added node*/ + int32_t (*p_add_node_free_fn)(void *data); + + /*Use a different initialization interrupt to initialize the operation*/ + int32_t (*p_input_init_fn)(void *data); + /*Release input resource*/ + int32_t (*p_input_deinit_fn)(void *data); + + //The parameters passed in are required for interrupt initialization + const struct aw_sar_irq_init_t *p_irq_init; + + //The chip is set to different modes in different power management interfaces + const struct aw_sar_pm_t *p_pm_chip_mode; +}; + +/*Parameter passed in by different SAR sensors. + It must be implemented in each sensor code. + If it is not necessary that some members can be assigned null, + the corresponding function will not be implemented +*/ +struct aw_sar_chip_config { + uint8_t ch_num_max; //Number of channels of the chip + + //Chip related platform content configuration + const struct aw_sar_platform_config *p_platform_config; + //Parameters required for verification of chipid + const struct aw_sar_check_chipid_t *p_check_chipid; + //Parameters required for soft reset + const struct aw_sar_soft_rst_t *p_soft_rst; + //Verify the parameters required to initialize a complete interrupt + const struct aw_sar_init_over_irq_t *p_init_over_irq; + //Parameters required for load boot bin file, + //If the chip does not have flash, please ignore and assign the value to null + const struct aw_sar_load_bin_t *p_fw_bin; + //Parameters required for load register bin file + const struct aw_sar_load_bin_t *p_reg_bin; + //The mode set before and after the initialization of the chip + const struct aw_sar_chip_mode_t *p_chip_mode; + + //Node usage parameters + //Register permission table + const struct aw_sar_reg_list_t *p_reg_list; + //Default register table + const struct aw_sar_para_load_t *p_reg_arr; + //Parameters required for set Auto-Offset-Tuning(aot) + const struct aw_sar_aot_t *p_aot; + //Parameters required for get chip diff val + const struct aw_sar_diff_t *p_diff; + //Parameters required for get chip offset val + const struct aw_sar_offset_t *p_offset; + //Set the parameters of different working modes of the chip + const struct aw_sar_mode_t *p_mode; + //Upgrading firmware using the debug node protocol + const struct aw_sar_load_bin_t *p_prox_fw; + //Upgrading firmware using the debug node reg + const struct aw_sar_load_bin_t *p_reg_fw; + //Obtain the necessary information of the chip + const struct aw_sar_get_chip_info_t *p_get_chip_info; + //Continuous read/write register interface + const struct aw_sar_awrw_t *p_aw_sar_awrw; + //Parameters required for load boot bin file, + //If the chip does not have flash, please ignore and assign the value to null + const struct aw_sar_load_bin_t *p_boot_bin; + + /*Other operations during initialization, Add according to different usage*/ + aw_sar_chip_other_operation_t p_other_operation; + /*If requested by resources, please release*/ + aw_sar_chip_other_opera_free_t p_other_opera_free; +}; + +struct aw_sar { + struct i2c_client *i2c; + struct device *dev; + struct regulator *vcc; + struct delayed_work update_work; + //Set pin pull-up mode + struct aw_sar_pinctrl pinctrl; + struct work_struct ps_notify_work; + struct notifier_block ps_notif; + + bool ps_is_present; + uint8_t chip_type; + uint8_t chip_name[20]; + + bool power_enable; + bool fw_fail_flag; + uint8_t last_mode; + uint8_t ret_val; + uint8_t curr_use_driver_type; + int32_t prot_update_state; + + uint8_t intrrupt_init_state; + + //Parameters related to platform logic + struct aw_sar_dts_info dts_info; + struct aw_sar_load_bin_comm_t load_bin; + struct aw_sar_irq_init_comm_t irq_init; + struct aw_awrw_info awrw_info; + struct aw_channels_info *channels_arr; + + //Private arguments required for public functions + const struct aw_sar_chip_config *p_sar_para; + //Private arguments required for private functions + void *priv_data; +}; + +//Determine whether the chip exists by verifying chipid +typedef int32_t (*aw_sar_who_am_i_t)(void *data); +typedef int32_t (*aw_sar_chip_init_t)(struct aw_sar *p_sar); +typedef void (*aw_sar_chip_deinit_t)(struct aw_sar *p_sar); + +struct aw_sar_driver_type { + uint8_t driver_type; + aw_sar_who_am_i_t p_who_am_i; + aw_sar_chip_init_t p_chip_init; + aw_sar_chip_deinit_t p_chip_deinit; +}; + +#endif diff --git a/include/linux/input/awinic/aw_update_fw.h b/include/linux/input/awinic/aw_update_fw.h new file mode 100644 index 000000000000..d2bd469525cc --- /dev/null +++ b/include/linux/input/awinic/aw_update_fw.h @@ -0,0 +1,335 @@ +#ifndef __AW_UPDATE_H_ +#define __AW_UPDATE_H_ +#include "aw_sar_comm_interface.h" +#include "aw_sar_type.h" +#include "aw_update_fw_interface.h" +#ifdef __cplusplus +extern "C" { +#endif + +#define AW_SAR_LOG_TAG "awinic sar " +#define AW_FW_UPDATE_DEBUG_LOG +#ifdef AW_FW_UPDATE_DEBUG_LOG +#define AWLOGD_FW(format, arg...) \ + do {\ + pr_info(AW_SAR_LOG_TAG "[%s:%d] "format"\n", __func__, __LINE__, ##arg);\ + } while (0) +#else +#define AWLOGD_FW(format, arg...) +#endif + +#define AW_FW_UPDATE_DEBUG_LOG +#ifdef AW_FW_UPDATE_DEBUG_LOG +#define AWLOGI_FW(format, arg...) \ + do {\ + pr_info(AW_SAR_LOG_TAG "[%s:%d] "format"\n", __func__, __LINE__, ##arg);\ + } while (0) +#else +#define AWLOGI_FW(format, arg...) +#endif + +#define AW_FW_UPDATE_DEBUG_LOG +#ifdef AW_FW_UPDATE_DEBUG_LOG +#define AWLOGE_FW(format, arg...) \ + do {\ + pr_err(AW_SAR_LOG_TAG "[%s:%d] "format"\n", __func__, __LINE__, ##arg);\ + } while (0) +#else +#define AWLOGE_FW(format, arg...) +#endif + +#define REG_IRQSRC (0x4410) + +//driver user +#define REG_ACCESSEN (0xFF20) +#define REG_MCFG (0x4444) +#define REG_ISPGO (0x4714) +#define REG_PMU_CFG (0x4820) +#define REG_ARRAY2_EW_EN (0x4794) +#define REG_ISPADR (0x4704) +#define REG_ISPWDATA (0x4708) +#define REG_ISPRDATA (0x470C) +#define REG_ISPCMD (0x4710) +#define REG_T_RCV (0x472C) +#define REG_CMD (0x4408) +#define REG_BOOT_LOADER_ACTIVE (0x4748) + +#define REG_OPEN_APB_ACCESS_EN (0x3c00f091) +#define REG_SET_PMU_CFG (0x6) +#define REG_SET_BTROM_EW_EN (0x5a637955) +#define REG_ISP_CMD_CONFIG (0x0c) +#define REG_SET_ISP_GO (0x1) +#define REG_ENSET_PMU_CFG (0x4) +#define REG_ACCESS_MAIN_ARR (0x05) +#define REG_SET_T_RCV (0xf0) +#define REG_SET_T_RCV_EN (0x16) +#define REG_OPEN_REG_ACCESS_EN (0x3c00ffff) +#define REG_OPEN_MCFG_EN (0x10000) +#define REG_ENSET_BTROM_EW_EN (0x0) +#define REG_SET_MCFG00 (0x0) +#define REG_ISP_CMD_MAIN_ARR (0X03) +#define REG_HOSTCTRL_EN (0x1) +#define REG_ACCESSEN_OPEN (0x3c00F091) +#define REG_ACCESSEN_CLOSE (0x3c00f011) +#define AW_REG_FLASH_WAKE_UP (0x4700) +#define REG_UPDATA_DIS (0x4744) +#define AW_REG_FLASH_WAKE_UP_ON (0x110) +#define AW_REG_FLASH_WAKE_UP_OFF (0x102) + +#define AW_BT_HOST2CPU_TRIG_ONLINE_UPGRADE_CMD (0x14) + +#define AW_BT_STATE_INFO_ERR (0x1c00) +#define AW_BT_STATE_INFO_PST (0x1C04) +#define AW_BT_STATE_INFO_FLAG (0x1C08) +#define AW_BT_PROT_CMD_PACK_ADDR (0x1C10) +#define AW_BT_PROT_ACK_PACK_ADDR (0x1C14) +#define AW_BT_MESSAGE_MSG0 (0x1C20) +#define AW_BT_MESSAGE_MSG1 (0x1C24) +#define AW_BT_MESSAGE_MSG_FLAG (0x1C28) +#define AW_BT_VER_INF_VERSION (0x1C30) +#define AW_BT_VER_INF_DATE (0x1C34) +#define AW_BT_HOST2CPU_TRIG (0x4408) +#define AW_BTCPU2HOST_TRIG (0x4410) + +#define AW_SRAM_FIRST_DETECT (0x20000800) + +#define AW_POWER_ON_DELAY_MS (25) +#define REG_MCFG_DELAY_MS (20) +#define AW_IRQ_DELAY_MS (100) +#define REG_RSTNALL_VAL (0x3c) +#define INIT_OVER_IRQ (1) +#define CMD_SLEEP_MODE (2) + +#define AW_WORD_LEN (4) +#define AW_REG_DATA_LEN (4) +#define AW_REG_ADDR_LEN (2) +#define AW_TX_BUF_LEN (AW_REG_DATA_LEN + AW_REG_ADDR_LEN) + +#define AW_RETRIES (5) +#define TRANSFER_SEQ_LEN (4) +#define TRANSFER_DTS_ADDR_LEN (4) +#define AW_FLASH_DEFAULT_VAL (0xffffffff) + +#define AW_PROT_STOP_WAIT_IRQ_CYCLES (100) +#define AW_REG_UPDATA_DIS_MASK (0x00ffffff) +#define AW_AFECFG3_CVMULTUALMOD (11) +#define AW_AFECFG3_CVOFF2X (10) + +#define AW_REG_MCFG (0x4444) +#define AW_REG_ACESS_EN (0xff20) +#define AW_REG_BOOTLOADER_ACTIVER (0x4748) +#define AW_REG_MCFG (0x4444) +#define AW_REG_RSTNALL (0xff18) +#define AW_CPU_HALT (0x00010000) +#define AW_ACC_PERI (0x3c00ffff) +#define AWDIS_HARD_BT_MODE (0x00000000) +#define AW_CPU_RUN (0x00000000) +#define AW_RSTNALL (0x0000003c) + +enum AW_UPDATE_RET { + AW_FW_OK, + AW_FW_ERR, +}; +enum AW9620X_UPDATE_MODE { + BOOT_UPDATE, + FIRMWARE_UPDATE, +}; + +#define PROT_SEND_ADDR (0x0800) +#define SEND_ADDR_LEN (2) +#define AW_ACK_ADDR (0x1800) + + +#define AW_PACK_FIXED_SIZE (12) +#define AW_ADDR_SIZE (2) + +//hecksum_en host->slave +#define AW_HEADER_VAL (0x02) + +#define REG_H2C_TRIG_PARSE_CMD (0x15) + +#define AW_WAIT_IRQ_CYCLES (10) +#define AW_WAIT_ENTER_SLEEP_MODE (100) +#define AW_WAIT_ENTER_TR_MODE (100) + +#define INIT_OVER_IRQ_OK (1) + +#define TRANSFER_SEQ_LEN (4) +#define TRANSFER_DTS_ADDR_LEN (4) + +#define AW_BT_CHECK_SUM_ADDR (0x07fc) + +#define AW_START_CMD_ACK_STATUS (2) +#define AW_START_CMD_ACK_ADDR_LEN (2) + +#define P_AW_START_CMD_SEND_VALUE (NULL) +#define AW_START_CMD_SEND_VALUE_LEN (0) +#define P_AW_ERASE_CHIP_CMD_SEND_VALUE (NULL) +#define AW_ERASE_CHIP_CMD_SEND_VALUE_LEN (0) +#define P_AW_RESTORE_CMD_SEND_VALUE (NULL) +#define AW_RESTORE_CMD_SEND_VALUE_LEN (0) + +#define AW_EN_TR_CHECK_VALUE_LEN (16) +#define AW_FLASH_ERASE_CHIO_CMD_ACK_LEN (4) + +#define AW_REG_WST_MODE_SLEEP (0x03000000) + + +enum AW9620X_FLASH_ADDR { + FLASH_ADDR_BOOT, + FLASH_ADDR_FW, +}; + +enum AW9620X_CMP_VAL { + BIN_VER_EQUALS_SOC_VER, + BIN_VER_NOT_EQUALS_SOC_VER, +}; + +enum AW_MODULE { + UPDATE_MODULE = 0x01, + FLASH_MODULE, + QUERY_MODULE, +}; + +enum AW_UPDATE_COMMAND { + UPDATE_START_CMD = 0X01, + UPDATE_TRANSFER_CMD, + UPDATE_STOP_CMD, + UPDATE_RESTORE_FLASHBT_CMD, +}; + +enum AW_UPDATE_COMMAND_ACK { + UPDATE_START_CMD_ACK = 0X01, + UPDATE_RANSFER_CMD_ACK, + UPDATE_STOP_CMD_ACK, + UPDATE_RESTORE_FLASHBT_CMD_ACK, +}; + +enum AW_FLASH_COMMAND { + FLASH_ERASE_CHIP_CMD = 0X01, + FLASH_ERASE_SECTOR_CMD, +}; + +enum AW_FLASH_COMMAND_ACK { + FLASH_ERASE_CHIP_CMD_ACK = 0X01, + FLASH_ERASE_SECTOR_CMD_ACK, +}; + +enum AW_QUERY_COMMAND { + QUERY_BT_VER_CMD = 0X01, + QUERY_BT_DATE_CMD, + QUERY_ERR_CODE_CMD, + QUERY_PST_CMD, + QUERY_CACHE_CMD, +}; + +enum AW_QUERY_COMMAND_ACK { + QUERY_BT_VER_CMD_ACK = 0X01, + QUERY_BT_DATE_CMD_ACK, + QUERY_ERR_CODE_CMD_ACK, + QUERY_PST_CMD_ACK, + QUERY_CACHE_CMD_ACK, +}; + +struct aw_soc_protocol { + uint16_t header; + uint16_t size; + uint32_t checksum; + uint8_t module; + uint8_t command; + uint16_t length; + uint8_t value[0]; +}; + +enum AW_UPDATE_FW_STATE { + SEND_UPDTAE_CMD, + SEND_START_CMD, + SEND_ERASE_SECTOR_CMD, + SEND_UPDATE_FW_CMD, + SEND_UPDATE_CHECK_CODE_CMD, + SEND_RESTORE_CMD, + SEND_STOP_CMD, +}; + +enum AW_PROT_UPDATE_FW_DELAY_TIME{ + SEND_UPDTAE_CMD_DELAY_MS = 1, + SEND_START_CMD_DELAY_MS = 3, + SEND_ERASE_SECTOR_CMD_DELAY_MS = 5, + SEND_UPDATE_FW_CMD_DELAY_MS = 100, + SEND_UPDATE_CHECK_CODE_CMD_DELAY_MS = 1, + SEND_RESTORE_CMD_DELAY_MS = 27, + SEND_STOP_CMD_DELAY_MS = 25, +}; + +enum AW_PROT_RECV_LEN { + SEND_START_CMD_RECV_LEN = 8, + SEND_ERASE_CHIP_CMD_RECV_LEN = 4, + SEND_UPDATE_FW_CMD_RECV_LEN = 8, + SEND_UPDATE_CHECK_CODE_CMD_RECV_LEN = 4, + SEND_RESTORE_CMD_RECV_LEN = 4, +}; +/********************reg update end****************/ +struct aw_flash_update_info { + uint32_t tr_start_addr; + uint32_t check_len;//The verification code is calculated by the verification length and the firmware chip + uint32_t check_en_addr; + uint32_t check_code_addr; + uint32_t check_en_val; + + uint32_t erase_start_addr; + uint32_t erase_sector_cnt; + uint32_t sector_size; +}; + +enum chip_select_flag { + CHIP_AW9620X, + //CHIP_AW9320X, + //CHIP_AW9328XQNR, +}; + +struct aw_fw_data_info { + const uint8_t *data_start_offset; + uint32_t update_data_len; + uint32_t fw_version; +}; + +struct aw_update_chip_diff { + uint16_t fwver_reg_addr; + //uint16_t wst_reg_addr; + + uint16_t cmd_reg_addr; + uint32_t cmd_sleep_mode; + enum chip_select_flag chip_flag; +}; + +struct aw_fw_info { + uint32_t single_wr_len; + const struct aw_flash_update_info *flash_info; +}; + +struct aw_update_para { + uint8_t direct_update_flag; //Upgrade without comparing version numbers + const struct aw_update_chip_diff *aw_update_diff; //Differences in chip updates +}; + +struct aw_update_fw { + struct aw_fw_info *fw_info; + struct aw_update_para *update_para; + struct aw_fw_data_info *fw_data_info; //Firmware information +}; + + +struct aw_update_common { + uint8_t update_flag; + const uint8_t *w_bin_offset; + uint32_t update_data_len; + const struct aw_flash_update_info *flash_info; +}; + + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/include/linux/input/awinic/aw_update_fw_interface.h b/include/linux/input/awinic/aw_update_fw_interface.h new file mode 100644 index 000000000000..8c917621bd5c --- /dev/null +++ b/include/linux/input/awinic/aw_update_fw_interface.h @@ -0,0 +1,14 @@ +#ifndef __AW_UPDATE_FW_INTERFAACE_H_ +#define __AW_UPDATE_FW_INTERFAACE_H_ + +#define AW_SAR_I2C_TYPE struct i2c_client * + +int32_t aw9620x_prot_update_fw(AW_SAR_I2C_TYPE i2c, uint8_t direct_update_flag, + const uint8_t *data_start_offset, uint32_t update_data_len ,uint32_t fw_version); + +int32_t aw9620x_reg_update_fw(AW_SAR_I2C_TYPE i2c, + const uint8_t *data_start_offset, uint32_t update_data_len); + +int32_t aw9620x_reg_update_boot(AW_SAR_I2C_TYPE i2c, + const uint8_t *data_start_offset, uint32_t update_data_len); +#endif \ No newline at end of file