new file mode 100644
@@ -0,0 +1,27 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+#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_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 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_AW963XX, aw963xx_check_chipid, aw963xx_init, aw963xx_deinit },
+};
+
+#endif
new file mode 100644
@@ -0,0 +1,639 @@
+// SPDX-License-Identifier: GPL-2.0
+#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);
+}
+
+/**
+ * @aw_sar_i2c_read() - Read register interface
+ *
+ * @i2c: i2c client.
+ * @reg_addr16: 16 bit register address.
+ * @reg_data32: 32 bit register data.
+ * @return 0 if init succeeded.
+ */
+int32_t aw_sar_i2c_read(struct i2c_client *i2c, uint16_t reg_addr16, uint32_t *reg_data32)
+{
+ uint8_t r_buf[6] = { 0 };
+ int8_t cnt = 5;
+ int32_t ret;
+
+ if (!i2c)
+ return -EINVAL;
+
+ 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)
+ dev_err(&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) {
+ dev_err(&i2c->dev, "i2c read error!");
+ return ret;
+ }
+
+ *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 0;
+}
+
+/**
+ * @aw_sar_i2c_write - write register interface
+ *
+ * @i2c: i2c client.
+ * @reg_addr16: 16 bit register address.
+ * @reg_data32: 32 bit register data.
+ * @return 0 if init succeeded.
+ */
+int32_t aw_sar_i2c_write(struct i2c_client *i2c, uint16_t reg_addr16, uint32_t reg_data32)
+{
+ uint8_t w_buf[6] = { 0 };
+ int8_t cnt = 5;
+ int32_t ret;
+
+ if (!i2c)
+ return -EINVAL;
+
+ /*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) {
+ dev_err(&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) {
+ dev_err(&i2c->dev, "i2c write error!");
+ return ret;
+ }
+
+ return 0;
+}
+
+/**
+ * @aw_sar_i2c_write_bits() - Write the corresponding bit of the register
+ *
+ * @i2c:i2c client.
+ * @reg_addr16: 16 bit register address.
+ * @mask: Write the corresponding bit as 0
+ * @val: Write corresponding data to the register
+ * @return 0 if init succeeded.
+ */
+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 0;
+}
+
+/**
+ * @aw_sar_i2c_write_seq() - Continuously write data to the chip
+ *
+ * @i2c:i2c client.
+ * @tr_data: Data written
+ * @len: Length of data written
+ * @return 0 if init succeeded.
+ */
+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;
+
+ do {
+ ret = awinic_i2c_write(i2c, tr_data, len);
+ if (ret < 0)
+ dev_err(&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) {
+ dev_err(&i2c->dev, "awinic i2c write error!");
+ return ret;
+ }
+
+ return 0;
+}
+
+/**
+ * @aw_sar_i2c_read_seq() - Continuously Read data from chip
+ *
+ * @i2c:i2c client.
+ * @addr: Read address
+ * @addr_len: Length of read address (byte)
+ * @data: Data written
+ * @data_len: Length of data written
+ * @return 0 if init succeeded.
+ */
+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;
+
+ do {
+ ret = awinic_i2c_read(i2c, addr, addr_len, data, data_len);
+ if (ret < 0)
+ dev_err(&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) {
+ dev_err(&i2c->dev, "awinic sar i2c read error!");
+ return ret;
+ }
+
+ return 0;
+}
+
+/******************************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,
+};
+
+#define BigLittleSwap16(A) ((((unsigned short int)(A) & 0xff00) >> 8) | \
+ (((unsigned short int)(A) & 0x00ff) << 8))
+
+#define BigLittleSwap32(A) ((((unsigned long)(A) & 0xff000000) >> 24) | \
+ (((unsigned long)(A) & 0x00ff0000) >> 8) | \
+ (((unsigned long)(A) & 0x0000ff00) << 8) | \
+ (((unsigned long)(A) & 0x000000ff) << 24))
+
+static enum aw_bin_err_val aw_parse_bin_header_1_0_0(struct aw_bin *bin);
+
+/********************************************************
+ *
+ * check sum data
+ *
+ ********************************************************/
+static enum aw_bin_err_val aw_check_sum(struct aw_bin *bin, int bin_num)
+{
+ unsigned char *p_check_sum;
+ unsigned int sum_data = 0;
+ unsigned int check_sum;
+ unsigned int i;
+
+ p_check_sum = &(bin->info.data[(bin->header_info[bin_num].valid_data_addr -
+ bin->header_info[bin_num].header_len)]);
+ 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);
+
+ if (sum_data != check_sum) {
+ p_check_sum = NULL;
+ return AW_BIN_ERROR_SUM_OR_DATA_LEN;
+ }
+ p_check_sum = NULL;
+
+ return AW_BIN_ERROR_NONE;
+}
+
+static enum aw_bin_err_val aw_check_register_num_v1(struct aw_bin *bin, int bin_num)
+{
+ unsigned int check_register_num;
+ unsigned int parse_register_num;
+ char *p_check_sum;
+
+ p_check_sum =
+ &(bin->info.data[(bin->header_info[bin_num].valid_data_addr)]);
+ 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);
+ if (parse_register_num != check_register_num) {
+ p_check_sum = NULL;
+ return AW_BIN_ERROR_REGISTER_NUM;
+ }
+ 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 AW_BIN_ERROR_NONE;
+}
+
+static enum aw_bin_err_val aw_check_dsp_reg_num_v1(struct aw_bin *bin, int bin_num)
+{
+ unsigned int check_dsp_reg_num;
+ unsigned int parse_dsp_reg_num;
+ char *p_check_sum;
+
+ p_check_sum =
+ &(bin->info.data[(bin->header_info[bin_num].valid_data_addr)]);
+ 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;
+ if (parse_dsp_reg_num != check_dsp_reg_num) {
+ p_check_sum = NULL;
+ return AW_BIN_ERROR_DSP_REG_NUM;
+ }
+ 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 AW_BIN_ERROR_NONE;
+}
+
+static enum aw_bin_err_val aw_check_soc_app_num_v1(struct aw_bin *bin, int bin_num)
+{
+ unsigned int check_soc_app_num;
+ unsigned int parse_soc_app_num;
+ char *p_check_sum;
+
+ p_check_sum = &(bin->info.data[(bin->header_info[bin_num].valid_data_addr)]);
+ 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;
+ if (parse_soc_app_num != check_soc_app_num) {
+ p_check_sum = NULL;
+ return AW_BIN_ERROR_SOC_APP_NUM;
+ }
+ 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 AW_BIN_ERROR_NONE;
+}
+
+/************************
+ *
+ ***bin header 1_0_0
+ ***
+ ************************/
+static void aw_get_single_bin_header_1_0_0(struct aw_bin *bin)
+{
+ int i;
+
+ 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("enter chip_type is %s\n", 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 enum aw_bin_err_val aw_parse_each_of_multi_bins_1_0_0(unsigned int bin_num,
+ int bin_serial_num, struct aw_bin *bin)
+{
+ unsigned int bin_start_addr;
+ unsigned int valid_data_len;
+ enum aw_bin_err_val ret;
+
+ 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 enum aw_bin_err_val aw_get_multi_bin_header_1_0_0(struct aw_bin *bin)
+{
+ unsigned int bin_num;
+ enum aw_bin_err_val ret;
+ int i;
+
+ 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++) {
+ ret = aw_parse_each_of_multi_bins_1_0_0(bin_num, i, bin);
+ if (ret < 0)
+ return ret;
+ }
+ return AW_BIN_ERROR_NONE;
+}
+
+/********************************************************
+ *
+ * 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 enum aw_bin_err_val aw_parse_bin_header_1_0_0(struct aw_bin *bin)
+{
+ unsigned int bin_data_type;
+ enum aw_bin_err_val ret;
+
+ bin_data_type = AW_SAR_GET_32_DATA(*(bin->p_addr + 11),
+ *(bin->p_addr + 10),
+ *(bin->p_addr + 9), *(bin->p_addr + 8));
+ 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
+ bin->single_bin_parse_num += 1;
+ 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 */
+ bin->multi_bin_parse_num += 1;
+ ret = aw_get_multi_bin_header_1_0_0(bin);
+ if (ret < 0)
+ return ret;
+ break;
+ default:
+ return AW_BIN_ERROR_DATA_TYPE;
+ }
+ return AW_BIN_ERROR_NONE;
+}
+
+/* get the bin's header version */
+static enum aw_bin_err_val aw_check_bin_header_version(struct aw_bin *bin)
+{
+ unsigned int header_version;
+ enum aw_bin_err_val ret;
+
+ header_version = AW_SAR_GET_32_DATA(*(bin->p_addr + 7), *(bin->p_addr + 6),
+ *(bin->p_addr + 5), *(bin->p_addr + 4));
+
+
+ // 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:
+ return AW_BIN_ERROR_HEADER_VERSION;
+ }
+}
+
+/**
+ * @aw_sar_parsing_bin_file() - Parse bin file
+ *
+ * @bin: Store the contents of the parsed bin file
+ * @return 0 if init succeeded, other if error
+ */
+enum aw_bin_err_val aw_sar_parsing_bin_file(struct aw_bin *bin)
+{
+ enum aw_bin_err_val ret;
+ int i;
+
+ if (!bin)
+ return AW_BIN_ERROR_NULL_POINT;
+ 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)
+ 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)
+ return ret;
+
+ /* 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)
+ 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)
+ 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)
+ return ret;
+ } else {
+ bin->header_info[i].valid_data_len = bin->header_info[i].bin_data_len;
+ }
+ }
+
+ return AW_BIN_ERROR_NONE;
+}
+/*********************************Parse bin file code end************************************/
+
+/**
+ * @aw_sar_pow2() - Calculate the second power
+ *
+ * @cnt: ifrequency
+ * @return the second power
+ */
+uint32_t aw_sar_pow2(uint32_t cnt)
+{
+ uint32_t sum = 1;
+ uint32_t i;
+
+ if (cnt == 0) {
+ sum = 1;
+ } else {
+ for (i = 0; i < cnt; i++)
+ sum *= 2;
+ }
+
+ return sum;
+}
+
+/**
+ * @aw_sar_load_reg() - Calculate the second power
+ *
+ * @aw_bin: Information after parsing bin file
+ * @i2c: i2c client.
+ * @return 0 if init succeeded.
+ */
+int32_t aw_sar_load_reg(struct aw_bin *aw_bin, struct i2c_client *i2c)
+{
+ uint32_t start_addr = aw_bin->header_info[0].valid_data_addr;
+ uint16_t reg_addr;
+ uint32_t reg_data;
+ int32_t ret;
+ uint32_t i;
+
+ 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) {
+ dev_err(&i2c->dev, "i2c write err");
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
+void aw_sar_delay_ms(uint32_t ms)
+{
+ mdelay(ms);
+}
+
new file mode 100644
@@ -0,0 +1,172 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+#ifndef _AW_SAR_PLAT_HW_INTERFACE_H_
+#define _AW_SAR_PLAT_HW_INTERFACE_H_
+#include <linux/delay.h>
+#include <linux/firmware.h>
+#include <linux/i2c.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/of_gpio.h>
+#include <linux/power_supply.h>
+#include <linux/pinctrl/consumer.h>
+#include <linux/regulator/consumer.h>
+#include <linux/slab.h>
+
+enum aw_sar_chip_list_t {
+ AW_SAR_NONE_CHECK_CHIP,
+
+ SAR_AW9610X = 1 << 1,
+ SAR_AW9610XA = 1 << 2,
+
+ 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,
+};
+
+#ifndef AW_TRUE
+#define AW_TRUE (1)
+#endif
+
+#ifndef AW_FALSE
+#define AW_FALSE (0)
+#endif
+
+#define AW_ERR_IRQ_INIT_OVER (0xAA)
+
+enum aw_sar_rst_val {
+ AW_OK,
+ AW_BIN_PARA_INVALID,
+ AW_PROT_UPDATE_ERR,
+ AW_REG_LOAD_ERR,
+};
+
+#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
+
+#define AW_SAR_GET_32_DATA(w, x, y, z) ((unsigned int)(((w) << 24) | ((x) << 16) | ((y) << 8) | (z)))
+
+enum AW_SAR_HOST_IRQ_STAT {
+ IRQ_ENABLE,
+ IRQ_DISABLE,
+};
+
+#define AW_SAR_BIN_NUM_MAX 100
+
+enum aw_bin_err_val {
+ AW_BIN_ERROR_NONE = 0,
+ AW_BIN_ERROR_HEADER_VERSION = -1,
+ AW_BIN_ERROR_DATA_TYPE = -2,
+ AW_BIN_ERROR_SUM_OR_DATA_LEN = -3,
+ AW_BIN_ERROR_DATA_VERSION = -4,
+ AW_BIN_ERROR_REGISTER_NUM = -5,
+ AW_BIN_ERROR_DSP_REG_NUM = -6,
+ AW_BIN_ERROR_SOC_APP_NUM = -7,
+ AW_BIN_ERROR_NULL_POINT = -8,
+};
+
+/**
+ * struct bin_header_info -
+ * @header_len: Frame header length
+ * @check_sum: Frame header information-Checksum
+ * @header_ver: Frame header information-Frame header version
+ * @bin_data_type: Frame header information-Data type
+ * @bin_data_ver: Frame header information-Data version
+ * @bin_data_len: Frame header information-Data length
+ * @ui_ver: Frame header information-ui version
+ * @chip_type: Frame header information-chip type
+ * @reg_byte_len: Frame header information-reg byte len
+ * @data_byte_len: Frame header information-data byte len
+ * @device_addr: Frame header information-device addr
+ * @valid_data_len: Length of valid data obtained after parsing
+ * @valid_data_addr: The offset address of the valid data obtained
+ * after parsing relative to info
+ * @reg_num: The number of registers obtained after parsing
+ * @reg_data_byte_len: The byte length of the register obtained after parsing
+ * @download_addr: The starting address or download address obtained after parsing
+ * @app_version: The software version number obtained after parsing
+ */
+struct bin_header_info {
+ unsigned int header_len;
+ unsigned int check_sum;
+ unsigned int header_ver;
+ unsigned int bin_data_type;
+ unsigned int bin_data_ver;
+ unsigned int bin_data_len;
+ unsigned int ui_ver;
+ unsigned char chip_type[8];
+ unsigned int reg_byte_len;
+ unsigned int data_byte_len;
+ unsigned int device_addr;
+ unsigned int valid_data_len;
+ unsigned int valid_data_addr;
+ unsigned int reg_num;
+ unsigned int reg_data_byte_len;
+ unsigned int download_addr;
+ unsigned int app_version;
+};
+
+/**
+ * struct bin_container -
+ * @len: The size of the bin file obtained from the firmware
+ * @data: Store the bin file obtained from the firmware
+ */
+struct bin_container {
+ unsigned int len;
+ unsigned char data[];
+};
+
+/**
+ * struct aw_bin -
+ * @p_addr: Offset pointer (backward offset pointer to obtain frame header information and
+ * important information)
+ * @all_bin_parse_num: The number of all bin files
+ * @multi_bin_parse_num: The number of single bin files
+ * @single_bin_parse_num: The number of multiple bin files
+ * @header_info: Frame header information and
+ * other important data obtained after parsing
+ * @info: Obtained bin file data that needs to be parsed
+ */
+struct aw_bin {
+ char *p_addr;
+ unsigned int all_bin_parse_num;
+ unsigned int multi_bin_parse_num;
+ unsigned int single_bin_parse_num;
+ struct bin_header_info header_info[AW_SAR_BIN_NUM_MAX];
+ struct bin_container info;
+};
+
+//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 enum aw_bin_err_val 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
new file mode 100644
@@ -0,0 +1,396 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+#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,
+};
+
+enum sar_health_check {
+ AW_SAR_HEALTHY = 0,
+ AW_SAR_UNHEALTHY = 1,
+};
+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;
+ bool monitor_esd_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];
+ uint32_t bin_data_ver;
+ 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;
+};
+
+struct aw_sar_power_on_prox_detection_t {
+ //en_flag is true enable
+ void (*p_power_on_prox_detection_en_fn)(void *data, uint8_t en_flag);
+ uint32_t irq_en_cali_bit;
+ uint8_t power_on_prox_en_flag;
+};
+
+
+/*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;
+
+ const struct aw_sar_power_on_prox_detection_t *power_on_prox_detection;
+};
+
+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;
+ /* eds work */
+ struct delayed_work monitor_work;
+ struct workqueue_struct *monitor_wq;
+
+ uint8_t chip_type;
+ uint8_t chip_name[20];
+
+ bool power_enable;
+ bool fw_fail_flag;
+ uint8_t last_mode;
+
+ /*handler_anomalies*/
+ uint8_t fault_flag;
+ uint8_t driver_code_initover_flag;
+ /*handler_anomalies*/
+
+ uint8_t ret_val;
+ uint8_t curr_use_driver_type;
+ int32_t prot_update_state;
+
+ uint8_t aot_irq_num;
+ uint8_t enter_irq_handle_num;
+ uint8_t exit_power_on_prox_detection;
+
+ struct work_struct ps_notify_work;
+ struct notifier_block ps_notif;
+ bool ps_is_present;
+
+ //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