Re: [PATCH v3 3/4] HID: touchscreen: Add initial support for Himax HID-over-SPI

From: Benjamin Tissoires
Date: Wed Oct 18 2023 - 03:23:28 EST


Hi Tylor,

On Oct 17 2023, Tylor Yang wrote:
> The hx83102j is a TDDI IC (Touch with Display Driver). The
> IC using SPI to transferring HID packet to host CPU. The IC also
> report HID report descriptor for driver to register HID device.
> The driver is designed as a framework for future expansion and
> hx83102j is the first case. Each hx_spi_hid_hx8xxxxx modules are
> mutual exclusive, it should be initiate one at a time.
>
> This driver takes a position similar to i2c-hid, it initialize
> and control the touch IC below and register HID to upper hid-core.
> When touch ic report an interrupt, it receive the data from IC
> and report as HID input to hid-core. Let hid-core dispatch input
> to registered hid-protocol and report to related input sub-system.
>
> This driver also provide advanced functions by hidraw interface:
> - runtime firmware update
> - debug functions, such as reg r/w
> - self test for touch panel
>
> Due to patch size is too big, separate into 3 part. This is part 2.

This is just wrong.

A commit message is supposed to reflect what's in the code and why.
Here you just copied/pasted the same commit message on all 3 patches,
which means the information here is useless.

I just don't know why you added 3260 lines to hx_ic_core.c, and I don't
even want to know.

I'm not sending the same email to 4/4, but the same comment applies to
it.

Please read the docs, watch talks from maintainers on how to submit a
patch series, and/or try to get a mentor, because this really isn't
the proper way to submit patches.

Cheers,
Benjamin


>
> Signed-off-by: Tylor Yang <tylor_yang@xxxxxxxxxxxxxxxxxxxxxxxxxxxxx>
> ---
> drivers/hid/hx-hid/hx_ic_core.c | 3260 +++++++++++++++++++++++++++++++
> 1 file changed, 3260 insertions(+)
> create mode 100644 drivers/hid/hx-hid/hx_ic_core.c
>
> diff --git a/drivers/hid/hx-hid/hx_ic_core.c b/drivers/hid/hx-hid/hx_ic_core.c
> new file mode 100644
> index 000000000000..f1a53a5b8ccf
> --- /dev/null
> +++ b/drivers/hid/hx-hid/hx_ic_core.c
> @@ -0,0 +1,3260 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/* Himax Driver Code for Common IC to simulate HID
> + *
> + * Copyright (C) 2023 Himax Corporation.
> + *
> + * This software is licensed under the terms of the GNU General Public
> + * License version 2, as published by the Free Software Foundation, and
> + * may be copied, distributed, and modified under those terms.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + */
> +
> +#include "hx_ic_core.h"
> +#include "hx_plat.h"
> +#include "hx_hid.h"
> +
> +/* CORE_IC */
> +/* IC side start*/
> +static void himax_mcu_burst_enable(struct himax_ts_data *ts,
> + u8 auto_add_4_byte)
> +{
> + u8 tmp_data[DATA_LEN_4];
> + int ret;
> +
> + /*I("Entering");*/
> + tmp_data[0] = IC_GET_VAL(data_conti);
> +
> + ret = himax_bus_write(ts, IC_GET_VAL(addr_conti), NULL, tmp_data, 1);
> + if (ret < 0) {
> + E("bus access fail!");
> + return;
> + }
> +
> + tmp_data[0] = (IC_GET_VAL(data_incr4) | auto_add_4_byte);
> +
> + ret = himax_bus_write(ts, IC_GET_VAL(addr_incr4), NULL, tmp_data, 1);
> + if (ret < 0) {
> + E("bus access fail!");
> + return;
> + }
> +}
> +
> +static int himax_mcu_register_read(struct himax_ts_data *ts, u8 *addr,
> + u8 *buf, u32 len)
> +{
> + int ret = -1;
> +
> + mutex_lock(&ts->reg_lock);
> +
> + if (memcmp(addr, FLASH_GET_ARRAY(addr_spi200_data), 4) == 0)
> + g_core_fp.fp_burst_enable(ts, 0);
> + else if (len > DATA_LEN_4)
> + g_core_fp.fp_burst_enable(ts, 1);
> + else
> + g_core_fp.fp_burst_enable(ts, 0);
> +
> + ret = himax_bus_write(ts, IC_GET_VAL(addr_ahb_addr_byte_0), addr, NULL, 4);
> + if (ret < 0) {
> + E("bus access fail!");
> + mutex_unlock(&ts->reg_lock);
> + return BUS_FAIL;
> + }
> +
> + ret = himax_bus_write(ts, IC_GET_VAL(addr_ahb_access_direction), NULL,
> + IC_GET_ARRAY(data_ahb_access_direction_read), 1);
> + if (ret < 0) {
> + E("bus access fail!");
> + mutex_unlock(&ts->reg_lock);
> + return BUS_FAIL;
> + }
> +
> + ret = himax_bus_read(ts, IC_GET_VAL(addr_ahb_rdata_byte_0), buf, len);
> + if (ret < 0) {
> + E("bus access fail!");
> + mutex_unlock(&ts->reg_lock);
> + return BUS_FAIL;
> + }
> +
> + mutex_unlock(&ts->reg_lock);
> +
> + return NO_ERR;
> +}
> +
> +static int himax_mcu_reg_read(struct himax_ts_data *ts, struct hx_reg_t *addr,
> + struct data_pack_t *data)
> +{
> + return g_core_fp.fp_register_read(ts,
> + addr->data.byte, data->data.byte, data->len);
> +}
> +
> +static int himax_mcu_register_write(struct himax_ts_data *ts, u8 *addr,
> + u8 *val, u32 len)
> +{
> + int ret = -1;
> + const u32 max_trans_sz = 4 * 1024;
> + int i = 0;
> + u32 orig_addr = 0;
> + union hx_dword_data_t temp_addr = {0};
> + u32 temp_len = 0;
> +
> + mutex_lock(&ts->reg_lock);
> +
> + if (memcmp(addr, FLASH_GET_ARRAY(addr_spi200_data), 4) == 0)
> + g_core_fp.fp_burst_enable(ts, 0);
> + else if (len > DATA_LEN_4)
> + g_core_fp.fp_burst_enable(ts, 1);
> + else
> + g_core_fp.fp_burst_enable(ts, 0);
> +
> + if (len > max_trans_sz) {
> + orig_addr = le32_to_cpup((__le32 *)addr);
> + for (i = 0; i < len; i += max_trans_sz) {
> + if ((len - i) > max_trans_sz)
> + temp_len = max_trans_sz;
> + else
> + temp_len = len % max_trans_sz;
> + temp_addr.dword = cpu_to_le32(orig_addr + i);
> + ret = himax_bus_write(ts, IC_GET_VAL(addr_ahb_addr_byte_0),
> + temp_addr.byte, val + i, temp_len + ADDR_LEN_4);
> + if (ret < 0) {
> + E("xfer fail!");
> + mutex_unlock(&ts->reg_lock);
> + return BUS_FAIL;
> + }
> + }
> + } else {
> + ret = himax_bus_write(ts, IC_GET_VAL(addr_ahb_addr_byte_0), addr, val,
> + len + ADDR_LEN_4);
> + if (ret < 0) {
> + E("xfer fail!");
> + mutex_unlock(&ts->reg_lock);
> + return BUS_FAIL;
> + }
> + }
> +
> + mutex_unlock(&ts->reg_lock);
> +
> + return NO_ERR;
> +}
> +
> +static int himax_mcu_reg_write(struct himax_ts_data *ts,
> + struct hx_reg_t *addr, struct data_pack_t *data)
> +{
> + return g_core_fp.fp_register_write(ts,
> + addr->data.byte, data->data.byte, data->len);
> +}
> +
> +static int himax_write_read_reg(struct himax_ts_data *ts, u8 *tmp_addr,
> + u8 *tmp_data, u8 hb, u8 lb)
> +{
> + u16 retry = 0;
> + union hx_dword_data_t r_data = {0};
> + union hx_dword_data_t t_addr = {0};
> + union hx_dword_data_t t_data = {0};
> +
> + memcpy(t_addr.byte, tmp_addr, ADDR_LEN_4);
> + memcpy(t_data.byte, tmp_data, DATA_LEN_4);
> +
> + while (retry++ < 40) { /* ceil[16.6*2] */
> + g_core_fp.fp_register_read(ts, t_addr.byte, r_data.byte, DATA_LEN_4);
> + D("Read handshake = 0x%08X:0x%08X", le32_to_cpu(t_addr.dword),
> + le32_to_cpu(r_data.dword));
> + if (r_data.byte[1] == lb && r_data.byte[0] == hb)
> + break;
> + else if (r_data.byte[1] == hb && r_data.byte[0] == lb)
> + return NO_ERR;
> +
> + g_core_fp.fp_register_write(ts, t_addr.byte, t_data.byte, DATA_LEN_4);
> + D("Write handshake = 0x%08X:0x%08X", le32_to_cpu(t_addr.dword),
> + le32_to_cpu(t_data.dword));
> + usleep_range(1000, 1100);
> + }
> +
> + if (retry >= 40)
> + goto FAIL;
> +
> + retry = 0;
> + while (retry++ < 200) { /* self test item might take long time */
> + g_core_fp.fp_register_read(ts, t_addr.byte, r_data.byte, DATA_LEN_4);
> + if (r_data.byte[1] == hb && r_data.byte[0] == lb)
> + return NO_ERR;
> +
> + D("wait data ready %d times, handshake = 0x%08X:0x%08X", retry,
> + le32_to_cpu(t_addr.dword), le32_to_cpu(r_data.dword));
> + usleep_range(10000, 10100);
> + }
> +
> +FAIL:
> + E("failed to handshaking with DSRAM");
> + E("addr = 0x%02X%02X%02X%02X; data = 0x%02X%02X%02X%02X",
> + tmp_addr[3], tmp_addr[2], tmp_addr[1], tmp_addr[0],
> + tmp_data[3], tmp_data[2], tmp_data[1], tmp_data[0]);
> + E("target = %02X%02X; r_data = %02X%02X",
> + hb, lb, r_data.byte[1], r_data.byte[0]);
> +
> + return HX_RW_REG_FAIL;
> +}
> +
> +static void himax_mcu_interface_on(struct himax_ts_data *ts)
> +{
> + u8 tmp_data[DATA_LEN_4];
> + u8 tmp_data2[DATA_LEN_4];
> + int cnt = 0;
> + int ret = 0;
> +
> + /* Read a dummy register to wake up BUS.*/
> + ret = himax_bus_read(ts, IC_GET_VAL(addr_ahb_rdata_byte_0), tmp_data,
> + DATA_LEN_4);
> + if (ret < 0) {/* to knock BUS*/
> + E("bus access fail!");
> + return;
> + }
> +
> + do {
> + tmp_data[0] = IC_GET_VAL(data_conti);
> +
> + ret = himax_bus_write(ts, IC_GET_VAL(addr_conti), NULL, tmp_data, 1);
> + if (ret < 0) {
> + E("bus access fail!");
> + return;
> + }
> +
> + tmp_data[0] = IC_GET_VAL(data_incr4);
> +
> + ret = himax_bus_write(ts, IC_GET_VAL(addr_incr4), NULL, tmp_data, 1);
> + if (ret < 0) {
> + E("bus access fail!");
> + return;
> + }
> +
> + /*Check cmd*/
> + himax_bus_read(ts, IC_GET_VAL(addr_conti), tmp_data, 1);
> + himax_bus_read(ts, IC_GET_VAL(addr_incr4), tmp_data2, 1);
> +
> + if (tmp_data[0] == IC_GET_VAL(data_conti) &&
> + tmp_data2[0] == IC_GET_VAL(data_incr4))
> + break;
> +
> + usleep_range(1000, 1100);
> + } while (++cnt < 10);
> +
> + if (cnt > 0)
> + I("Polling burst mode: %d times", cnt);
> +}
> +
> +static void himax_mcu_sense_on(struct himax_ts_data *ts, u8 flash_mode)
> +{
> + u8 tmp_data[DATA_LEN_4];
> + int retry = 0;
> + int ret = 0;
> +
> + I("Enter");
> + ts->notouch_frame = ts->ic_notouch_frame;
> + g_core_fp.fp_interface_on(ts);
> + g_core_fp.fp_register_write(ts, FW_GET_ARRAY(addr_ctrl_fw_isr),
> + FW_GET_ARRAY(data_clear), FW_GET_SZ(data_clear));
> + usleep_range(10000, 11000);
> + if (!flash_mode) {
> + g_core_fp.fp_ic_reset(ts, false, false);
> + } else {
> + do {
> + g_core_fp.fp_register_read(ts,
> + FW_GET_ARRAY(addr_flag_reset_event),
> + tmp_data, DATA_LEN_4);
> + I("Read status from IC = %X,%X", tmp_data[0], tmp_data[1]);
> + } while ((tmp_data[1] != 0x01 ||
> + tmp_data[0] != 0x00) &&
> + retry++ < 5);
> +
> + if (retry >= 5) {
> + E("Fail");
> + g_core_fp.fp_ic_reset(ts, false, false);
> + } else {
> + I("OK and Read status from IC = %X,%X",
> + tmp_data[0], tmp_data[1]);
> + /* reset code*/
> + tmp_data[0] = 0x00;
> +
> + ret = himax_bus_write(ts, IC_GET_VAL(adr_i2c_psw_lb), NULL,
> + tmp_data, 1);
> + if (ret < 0) {
> + E("cmd=%x bus access fail!",
> + IC_GET_VAL(adr_i2c_psw_lb));
> + }
> + ret = himax_bus_write(ts, IC_GET_VAL(adr_i2c_psw_ub), NULL,
> + tmp_data, 1);
> + if (ret < 0) {
> + E("cmd=%x bus access fail!",
> + IC_GET_VAL(adr_i2c_psw_ub));
> + }
> + }
> + }
> +}
> +
> +static bool himax_mcu_sense_off(struct himax_ts_data *ts, bool check_en)
> +{
> + u8 cnt = 0;
> + u8 tmp_data[DATA_LEN_4];
> + int ret = 0;
> +
> + do {
> + tmp_data[0] = IC_GET_VAL(data_i2c_psw_lb);
> + tmp_data[1] = IC_GET_VAL(data_i2c_psw_ub);
> +
> + ret = himax_bus_write(ts, IC_GET_VAL(adr_i2c_psw_lb), NULL, tmp_data,
> + 2);
> + if (ret < 0) {
> + E("bus access fail!");
> + return false;
> + }
> +
> + g_core_fp.fp_register_read(ts, IC_GET_ARRAY(addr_cs_central_state),
> + tmp_data, ADDR_LEN_4);
> + I("Check enter_save_mode data[0]=%X", tmp_data[0]);
> +
> + if (tmp_data[0] == 0x0C) {
> + g_core_fp.fp_register_write(ts, IC_GET_ARRAY(addr_tcon_on_rst),
> + IC_GET_ARRAY(data_rst), DATA_LEN_4);
> + usleep_range(1000, 1100);
> +
> + g_core_fp.fp_register_write(ts, IC_GET_ARRAY(addr_adc_on_rst),
> + IC_GET_ARRAY(data_rst), DATA_LEN_4);
> + usleep_range(1000, 1100);
> + tmp_data[3] = IC_GET_ARRAY(data_rst)[3];
> + tmp_data[2] = IC_GET_ARRAY(data_rst)[2];
> + tmp_data[1] = IC_GET_ARRAY(data_rst)[1];
> + tmp_data[0] = IC_GET_ARRAY(data_rst)[0] | 0x01;
> + g_core_fp.fp_register_write(ts, IC_GET_ARRAY(addr_adc_on_rst),
> + tmp_data, DATA_LEN_4);
> + goto TRUE_END;
> + } else {
> + /* usleep_range(10000, 10001); */
> + g_core_fp.fp_ic_reset(ts, false, false);
> + }
> + } while (cnt++ < 15);
> +
> + return false;
> +TRUE_END:
> + return true;
> +}
> +
> +#define WIP_PRT_LOG "retry:%d, bf[0]=%d, bf[1]=%d,bf[2]=%d, bf[3]=%d"
> +static bool himax_mcu_wait_wip(struct himax_ts_data *ts, int timing)
> +{
> + u8 tmp_data[DATA_LEN_4];
> + int retry_cnt = 0;
> +
> + g_core_fp.fp_register_write(ts, FLASH_GET_ARRAY(addr_spi200_trans_fmt),
> + FLASH_GET_ARRAY(data_spi200_trans_fmt), DATA_LEN_4);
> + tmp_data[0] = 0x01;
> +
> + do {
> + g_core_fp.fp_register_write(ts,
> + FLASH_GET_ARRAY(addr_spi200_trans_ctrl),
> + FLASH_GET_ARRAY(data_spi200_trans_ctrl_1), DATA_LEN_4);
> +
> + g_core_fp.fp_register_write(ts, FLASH_GET_ARRAY(addr_spi200_cmd),
> + FLASH_GET_ARRAY(data_spi200_cmd_1), DATA_LEN_4);
> + memset(tmp_data, 0xFF, DATA_LEN_4);
> + g_core_fp.fp_register_read(ts, FLASH_GET_ARRAY(addr_spi200_data),
> + tmp_data, 4);
> +
> + if ((tmp_data[0] & 0x01) == 0x00)
> + return true;
> +
> + retry_cnt++;
> +
> + if (tmp_data[0] != 0x00 ||
> + tmp_data[1] != 0x00 ||
> + tmp_data[2] != 0x00 ||
> + tmp_data[3] != 0x00)
> + I(WIP_PRT_LOG,
> + retry_cnt, tmp_data[0],
> + tmp_data[1], tmp_data[2], tmp_data[3]);
> +
> + if (retry_cnt > 100) {
> + E("Wait wip error!");
> + return false;
> + }
> +
> + usleep_range(timing * 1000, timing * 1000 + 1);
> + } while ((tmp_data[0] & 0x01) == 0x01);
> +
> + return true;
> +}
> +
> +/*power saving level*/
> +static void himax_mcu_init_psl(struct himax_ts_data *ts)
> +{
> + g_core_fp.fp_register_write(ts, IC_GET_ARRAY(addr_psl),
> + IC_GET_ARRAY(data_rst), IC_GET_SZ(data_rst));
> + I("power saving level reset OK!");
> +}
> +
> +static void himax_mcu_resume_ic_action(struct himax_ts_data *ts)
> +{
> + /* Nothing to do */
> +}
> +
> +static void himax_mcu_suspend_ic_action(struct himax_ts_data *ts)
> +{
> + /* Nothing to do */
> +}
> +
> +static void himax_mcu_power_on_init(struct himax_ts_data *ts)
> +{
> + union hx_dword_data_t tmp_data = { .byte = {0x01, 0x00, 0x00, 0x00} };
> + u8 retry = 0;
> +
> + /*RawOut select initial*/
> + g_core_fp.fp_register_write(ts, FW_GET_ARRAY(addr_raw_out_sel),
> + FW_GET_ARRAY(data_clear), FW_GET_SZ(data_clear));
> + /*DSRAM func initial*/
> + g_core_fp.fp_assign_sorting_mode(ts, FW_GET_ARRAY(data_clear));
> + /*N frame initial*/
> + /* reset N frame back to default value 1 for normal mode */
> + g_core_fp.fp_register_write(ts, FW_GET_ARRAY(addr_set_frame_addr),
> + tmp_data.byte, 4);
> + /*FW reload done initial*/
> + g_core_fp.fp_register_write(ts,
> + DRV_GET_ARRAY(addr_fw_define_2nd_flash_reload),
> + FW_GET_ARRAY(data_clear), FW_GET_SZ(data_clear));
> +
> + g_core_fp.fp_sense_on(ts, 0x00);
> +
> + I("waiting for FW reload data");
> +
> + while (retry++ < 30) {
> + g_core_fp.fp_register_read(ts,
> + DRV_GET_ARRAY(addr_fw_define_2nd_flash_reload), tmp_data.byte,
> + DATA_LEN_4);
> +
> + /* use all 4 bytes to compare */
> + if (le32_to_cpu(tmp_data.dword) == 0x72C0) {
> + I("FW reload done");
> + break;
> + }
> + I("wait FW reload %d times", retry);
> + g_core_fp.fp_read_FW_status(ts);
> + usleep_range(10000, 11000);
> + }
> +}
> +
> +/* IC side end*/
> +/* CORE_IC */
> +
> +/* CORE_FW */
> +/* FW side start*/
> +static void himax_mcu_system_reset(struct himax_ts_data *ts)
> +{
> + int ret = 0;
> + u8 tmp_data[DATA_LEN_4];
> + int retry = 0;
> +
> + g_core_fp.fp_interface_on(ts);
> + g_core_fp.fp_register_write(ts, FW_GET_ARRAY(addr_ctrl_fw_isr),
> + FW_GET_ARRAY(data_clear), FW_GET_SZ(data_clear));
> + do {
> + /* reset code*/
> + /**
> + * I2C_password[7:0] set Enter safe mode : 0x31 ==> 0x27
> + */
> + tmp_data[0] = IC_GET_VAL(data_i2c_psw_lb);
> +
> + ret = himax_bus_write(ts, IC_GET_VAL(adr_i2c_psw_lb), NULL, tmp_data,
> + 1);
> + if (ret < 0)
> + E("bus access fail!");
> +
> + /**
> + * I2C_password[15:8] set Enter safe mode :0x32 ==> 0x95
> + */
> + tmp_data[0] = IC_GET_VAL(data_i2c_psw_ub);
> +
> + ret = himax_bus_write(ts, IC_GET_VAL(adr_i2c_psw_ub), NULL, tmp_data,
> + 1);
> + if (ret < 0)
> + E("bus access fail!");
> +
> + /**
> + * I2C_password[7:0] set Enter safe mode : 0x31 ==> 0x00
> + */
> + tmp_data[0] = 0x00;
> +
> + ret = himax_bus_write(ts, IC_GET_VAL(adr_i2c_psw_lb), NULL, tmp_data,
> + 1);
> + if (ret < 0)
> + E("bus access fail!");
> +
> + usleep_range(10000, 11000);
> +
> + g_core_fp.fp_register_read(ts, FW_GET_ARRAY(addr_flag_reset_event),
> + tmp_data, DATA_LEN_4);
> + I("Read status from IC = %X,%X", tmp_data[0], tmp_data[1]);
> + } while ((tmp_data[1] != 0x02 || tmp_data[0] != 0x00) && retry++ < 5);
> +}
> +
> +static int himax_mcu_calculate_crc_with_ap(const unsigned char *FW_content,
> + int CRC_from_FW, int len)
> +{
> + int i, j, length = 0;
> + int fw_data;
> + int fw_data_2;
> + int CRC = 0xFFFFFFFF;
> + int polynomial = 0x82F63B78;
> +
> + length = len / 4;
> +
> + for (i = 0; i < length; i++) {
> + fw_data = FW_content[i * 4];
> +
> + for (j = 1; j < 4; j++) {
> + fw_data_2 = FW_content[i * 4 + j];
> + fw_data += (fw_data_2) << (8 * j);
> + }
> + CRC = fw_data ^ CRC;
> + for (j = 0; j < 32; j++) {
> + if ((CRC % 2) != 0)
> + CRC = ((CRC >> 1) & 0x7FFFFFFF) ^ polynomial;
> + else
> + CRC = (((CRC >> 1) & 0x7FFFFFFF));
> + }
> + }
> +
> + return CRC;
> +}
> +
> +static u32 himax_mcu_check_crc(struct himax_ts_data *ts,
> + u8 *start_addr, int reload_length)
> +{
> + u32 result = 0;
> + union {
> + u8 byte[4];
> + u16 word[2];
> + u32 dword;
> + } tmp_data = {0};
> + int cnt = 0, ret = 0;
> + int length = reload_length / DATA_LEN_4;
> +
> + ret = g_core_fp.fp_register_write(ts, FW_GET_ARRAY(addr_reload_addr_from),
> + start_addr, DATA_LEN_4);
> + if (ret < NO_ERR) {
> + E("bus access fail!");
> + return HW_CRC_FAIL;
> + }
> +
> + tmp_data.word[1] = 0x0099;
> + tmp_data.word[1] = cpu_to_le16(tmp_data.word[1]);
> + tmp_data.word[0] = length;
> + tmp_data.word[0] = cpu_to_le16(tmp_data.word[0]);
> + ret = g_core_fp.fp_register_write(ts,
> + FW_GET_ARRAY(addr_reload_addr_cmd_beat), tmp_data.byte, DATA_LEN_4);
> + if (ret < NO_ERR) {
> + E("bus access fail!");
> + return HW_CRC_FAIL;
> + }
> + tmp_data.word[0] = 0x0000;
> +
> + ret = g_core_fp.fp_register_read(ts,
> + FW_GET_ARRAY(addr_reload_addr_cmd_beat), tmp_data.byte, DATA_LEN_4);
> +
> + if (le16_to_cpu(tmp_data.word[0]) != length) {
> + E("Flash content is Wrong");
> + return HW_CRC_FAIL;
> + }
> +
> + cnt = 0;
> +
> + do {
> + ret = g_core_fp.fp_register_read(ts, FW_GET_ARRAY(addr_reload_status),
> + tmp_data.byte, DATA_LEN_4);
> + if (ret < NO_ERR) {
> + E("bus access fail!");
> + return HW_CRC_FAIL;
> + }
> +
> + if ((tmp_data.byte[0] & 0x01) != 0x01) {
> + ret = g_core_fp.fp_register_read(ts,
> + FW_GET_ARRAY(addr_reload_crc32_result), tmp_data.byte,
> + DATA_LEN_4);
> + if (ret < NO_ERR) {
> + E("bus access fail!");
> + return HW_CRC_FAIL;
> + }
> + I("data[3]=%X,data[2]=%X,data[1]=%X,data[0]=%X",
> + tmp_data.byte[3],
> + tmp_data.byte[2],
> + tmp_data.byte[1],
> + tmp_data.byte[0]);
> + result = tmp_data.dword;
> + goto END;
> + } else {
> + I("Waiting for HW ready!");
> + usleep_range(1000, 1100);
> + if (cnt >= 100)
> + g_core_fp.fp_read_FW_status(ts);
> + }
> +
> + } while (cnt++ < 100);
> +END:
> + return result;
> +}
> +
> +static void himax_mcu_set_reload_cmd(u8 *write_data, int idx,
> + u32 cmd_from, u32 cmd_to, u32 cmd_beat)
> +{
> + int index = idx * 12;
> + int i;
> +
> + for (i = 3; i >= 0; i--) {
> + write_data[index + i] = (cmd_from >> (8 * i));
> + write_data[index + 4 + i] = (cmd_to >> (8 * i));
> + write_data[index + 8 + i] = (cmd_beat >> (8 * i));
> + }
> +}
> +
> +static bool himax_mcu_program_reload(void)
> +{
> + return true;
> +}
> +
> +static void himax_mcu_usb_detect_set(struct himax_ts_data *ts,
> + const u8 *cable_config)
> +{
> + struct hx_reg_t tmp_reg;
> + struct hx_reg_t back_reg;
> + u8 retry_cnt = 0;
> +
> + do {
> + if (cable_config[1] == 0x01) {
> + WORD_REG(tmp_reg, fw_func_handshaking_pwd);
> + g_core_fp.fp_register_write(ts, FW_GET_ARRAY(addr_usb_detect),
> + REG_GET_ARRAY(tmp_reg), REG_GET_SZ(tmp_reg));
> + WORD_REG(back_reg, fw_func_handshaking_pwd);
> + I("USB detect status IN!");
> + } else {
> + WORD_REG(tmp_reg, fw_data_safe_mode_release_pw_reset);
> + g_core_fp.fp_register_write(ts, FW_GET_ARRAY(addr_usb_detect),
> + REG_GET_ARRAY(tmp_reg), REG_GET_SZ(tmp_reg));
> + WORD_REG(back_reg, fw_data_safe_mode_release_pw_reset);
> + I("USB detect status OUT!");
> + }
> +
> + g_core_fp.fp_register_read(ts, FW_GET_ARRAY(addr_usb_detect),
> + REG_GET_ARRAY(tmp_reg), REG_GET_SZ(tmp_reg));
> + /*I("tmp_data[0]=%d, USB detect=%d, retry_cnt=%d",
> + * tmp_data[0], cable_config[1], retry_cnt);
> + */
> + retry_cnt++;
> + } while ((REG_GET_ARRAY(tmp_reg)[3] != REG_GET_ARRAY(back_reg)[3] ||
> + REG_GET_ARRAY(tmp_reg)[2] != REG_GET_ARRAY(back_reg)[2] ||
> + REG_GET_ARRAY(tmp_reg)[1] != REG_GET_ARRAY(back_reg)[1] ||
> + REG_GET_ARRAY(tmp_reg)[0] != REG_GET_ARRAY(back_reg)[0]) &&
> + retry_cnt < HIMAX_REG_RETRY_TIMES);
> +}
> +
> +#define PRT_DATA "[3]=0x%02X, [2]=0x%02X, [1]=0x%02X, [0]=0x%02X"
> +static void himax_mcu_diag_register_set(struct himax_ts_data *ts,
> + u8 diag_command)
> +{
> + u8 tmp_data[DATA_LEN_4];
> + u8 back_data[DATA_LEN_4];
> + u8 cnt = 50;
> +
> + tmp_data[0] = diag_command;
> + I("diag_command = %d, tmp_data[0] = %X", diag_command, tmp_data[0]);
> + g_core_fp.fp_interface_on(ts);
> + tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00;
> + do {
> + g_core_fp.fp_register_write(ts, FW_GET_ARRAY(addr_raw_out_sel),
> + tmp_data, DATA_LEN_4);
> + g_core_fp.fp_register_read(ts, FW_GET_ARRAY(addr_raw_out_sel), back_data,
> + DATA_LEN_4);
> + I(PRT_DATA, back_data[3], back_data[2], back_data[1], back_data[0]);
> + cnt--;
> + } while (tmp_data[0] != back_data[0] && cnt > 0);
> +}
> +
> +static int himax_mcu_diag_register_get(struct himax_ts_data *ts,
> + u32 *diag_value)
> +{
> + int ret = 0;
> + union hx_dword_data_t *tmp_data = (union hx_dword_data_t *)diag_value;
> +
> + if (tmp_data) {
> + ret = g_core_fp.fp_register_read(ts, FW_GET_ARRAY(addr_raw_out_sel),
> + tmp_data->byte, DATA_LEN_4);
> + } else {
> + E("diag_value is NULL");
> + ret = -EINVAL;
> + }
> +
> + return ret;
> +}
> +
> +#define PRT_TMP_DATA "[0]=0x%2X,[1]=0x%2X, [2]=0x%2X,[3]=0x%2X"
> +static void himax_mcu_idle_mode(struct himax_ts_data *ts, int disable)
> +{
> + int retry = 20;
> + u8 tmp_data[DATA_LEN_4];
> + u8 switch_cmd = 0x00;
> +
> + I("entering");
> +
> + do {
> + I("now %d times!", retry);
> + g_core_fp.fp_register_read(ts, FW_GET_ARRAY(addr_fw_mode_status),
> + tmp_data, DATA_LEN_4);
> +
> + if (disable)
> + switch_cmd = FW_GET_ARRAY(data_idle_dis_pwd)[0];
> + else
> + switch_cmd = FW_GET_ARRAY(data_idle_en_pwd)[0];
> +
> + tmp_data[0] = switch_cmd;
> + g_core_fp.fp_register_write(ts, FW_GET_ARRAY(addr_fw_mode_status),
> + tmp_data, DATA_LEN_4);
> + g_core_fp.fp_register_read(ts, FW_GET_ARRAY(addr_fw_mode_status),
> + tmp_data, DATA_LEN_4);
> +
> + I(PRT_TMP_DATA, tmp_data[0], tmp_data[1], tmp_data[2], tmp_data[3]);
> +
> + retry--;
> + usleep_range(10000, 11000);
> + } while ((tmp_data[0] != switch_cmd) && retry > 0);
> +
> + I("setting OK!");
> +}
> +
> +static void himax_mcu_reload_disable(struct himax_ts_data *ts, int disable)
> +{
> + I("entering");
> +
> + if (disable) { /*reload disable*/
> + g_core_fp.fp_register_write(ts,
> + DRV_GET_ARRAY(addr_fw_define_flash_reload),
> + DRV_GET_ARRAY(data_fw_define_flash_reload_dis),
> + DATA_LEN_4);
> + } else { /*reload enable*/
> + g_core_fp.fp_register_write(ts,
> + DRV_GET_ARRAY(addr_fw_define_flash_reload),
> + DRV_GET_ARRAY(data_fw_define_flash_reload_en),
> + DATA_LEN_4);
> + }
> +
> + I("setting OK!");
> +}
> +
> +static int himax_mcu_read_ic_trigger_type(struct himax_ts_data *ts)
> +{
> + u8 tmp_data[DATA_LEN_4];
> + int trigger_type = false;
> +
> + g_core_fp.fp_register_read(ts, DRV_GET_ARRAY(addr_fw_define_int_is_edge),
> + tmp_data, DATA_LEN_4);
> +
> + if ((tmp_data[1] & 0x01) == 1)
> + trigger_type = true;
> +
> + return trigger_type;
> +}
> +
> +/* Please call this function after FW finish reload done */
> +static void himax_mcu_read_FW_ver(struct himax_ts_data *ts)
> +{
> + u8 data[12] = {0};
> +
> + g_core_fp.fp_register_read(ts, FW_GET_ARRAY(addr_fw_ver_addr), data,
> + DATA_LEN_4);
> + ts->ic_data->vendor_panel_ver = data[0];
> + ts->ic_data->vendor_fw_ver = data[1] << 8 | data[2];
> + I("PANEL_VER : %X", ts->ic_data->vendor_panel_ver);
> + I("FW_VER : %X", ts->ic_data->vendor_fw_ver);
> + g_core_fp.fp_register_read(ts, FW_GET_ARRAY(addr_fw_cfg_addr), data,
> + DATA_LEN_4);
> + ts->ic_data->vendor_config_ver = data[2] << 8 | data[3];
> + /*I("CFG_VER : %X",ts->ic_data->vendor_config_ver);*/
> + ts->ic_data->vendor_touch_cfg_ver = data[2];
> + I("TOUCH_VER : %X", ts->ic_data->vendor_touch_cfg_ver);
> + ts->ic_data->vendor_display_cfg_ver = data[3];
> + I("DISPLAY_VER : %X", ts->ic_data->vendor_display_cfg_ver);
> + g_core_fp.fp_register_read(ts, FW_GET_ARRAY(addr_fw_vendor_addr), data,
> + DATA_LEN_4);
> + ts->ic_data->vendor_cid_maj_ver = data[2];
> + ts->ic_data->vendor_cid_min_ver = data[3];
> + I("CID_VER : %X", (ts->ic_data->vendor_cid_maj_ver << 8
> + | ts->ic_data->vendor_cid_min_ver));
> + g_core_fp.fp_register_read(ts, FW_GET_ARRAY(addr_cus_info), data, 12);
> + memcpy(ts->ic_data->vendor_cus_info, data, 12);
> + I("Cusomer ID = %s", ts->ic_data->vendor_cus_info);
> + g_core_fp.fp_register_read(ts, FW_GET_ARRAY(addr_proj_info), data, 12);
> + memcpy(ts->ic_data->vendor_proj_info, data, 12);
> + I("Project ID = %s", ts->ic_data->vendor_proj_info);
> + hx_hid_update_info(ts);
> +}
> +
> +static bool himax_mcu_read_event_stack(struct himax_ts_data *ts, u8 *buf,
> + u32 length)
> +{
> + u8 cmd[DATA_LEN_4];
> + struct time_var t_start, t_end, t_delta;
> + int len = length;
> + int i2c_speed = 0;
> + int ret = 0;
> +
> + /* AHB_I2C Burst Read Off */
> + cmd[0] = FW_GET_VAL(data_ahb_dis);
> +
> + ret = himax_bus_write(ts, FW_GET_VAL(addr_ahb_addr), NULL, cmd, 1);
> + if (ret < 0) {
> + E("bus access fail!");
> + return 0;
> + }
> + if (ts->debug_log_level & BIT(2))
> + time_func(&t_start);
> +
> + himax_bus_read(ts, FW_GET_VAL(addr_event_addr), buf, length);
> +
> + if (ts->debug_log_level & BIT(2)) {
> + time_func(&t_end);
> + t_delta.tv_nsec = (t_end.tv_sec * 1000000000 + t_end.tv_nsec)
> + - (t_start.tv_sec * 1000000000 + t_start.tv_nsec);
> +
> + i2c_speed = (len * 9 * 1000000
> + / (int)t_delta.tv_nsec) * 13 / 10;
> + ts->bus_speed = (int)i2c_speed;
> + }
> +
> + /* AHB_I2C Burst Read On */
> + cmd[0] = FW_GET_VAL(data_ahb_en);
> +
> + ret = himax_bus_write(ts, FW_GET_VAL(addr_ahb_addr), NULL, cmd, 1);
> + if (ret < 0) {
> + E("bus access fail!");
> + return 0;
> + }
> +
> + return 1;
> +}
> +
> +static void himax_mcu_return_event_stack(struct himax_ts_data *ts)
> +{
> + int retry = 20, i;
> + u8 tmp_data[DATA_LEN_4];
> +
> + I("entering");
> +
> + do {
> + I("now %d times!", retry);
> +
> + for (i = 0; i < DATA_LEN_4; i++)
> + tmp_data[i] = SRAM_GET_ARRAY(addr_rawdata_end)[i];
> +
> + g_core_fp.fp_register_write(ts, SRAM_GET_ARRAY(addr_rawdata_addr),
> + tmp_data, DATA_LEN_4);
> + g_core_fp.fp_register_read(ts, SRAM_GET_ARRAY(addr_rawdata_addr),
> + tmp_data, DATA_LEN_4);
> + retry--;
> + usleep_range(10000, 11000);
> + } while ((tmp_data[1] != SRAM_GET_ARRAY(addr_rawdata_end)[1] &&
> + tmp_data[0] != SRAM_GET_ARRAY(addr_rawdata_end)[0]) &&
> + retry > 0);
> +
> + I("End of setting!");
> +}
> +
> +static bool himax_mcu_calculate_checksum(struct himax_ts_data *ts,
> + bool change_iref, u32 size)
> +{
> + u32 CRC_result = 0xFFFFFFFF;
> + u8 i;
> + u8 tmp_data[DATA_LEN_4];
> +
> + I("Now size=%d", size);
> + for (i = 0; i < DATA_LEN_4; i++)
> + tmp_data[i] = SRAM_GET_ARRAY(addr_rawdata_end)[i];
> +
> + CRC_result = g_core_fp.fp_check_crc(ts, tmp_data, size);
> + usleep_range(50000, 50001);
> +
> + if (CRC_result != 0)
> + I("CRC Fail=%d", CRC_result);
> +
> + return (CRC_result == 0) ? true : false;
> +}
> +
> +static u32 dbg_reg_ary[4] = {fw_addr_fw_dbg_msg_addr,
> + fw_addr_chk_fw_status, fw_addr_chk_dd_status, fw_addr_flag_reset_event};
> +
> +static void himax_mcu_read_FW_status(struct himax_ts_data *ts)
> +{
> + u8 len = 0;
> + u8 i = 0;
> + struct hx_reg_t addr_reg;
> + u8 data[4] = {0};
> +
> + len = (u8)(sizeof(dbg_reg_ary) / sizeof(u32));
> +
> + for (i = 0; i < len; i++) {
> + WORD_REG(addr_reg, dbg_reg_ary[i]);
> + g_core_fp.fp_register_read(ts, REG_GET_ARRAY(addr_reg),
> + data, DATA_LEN_4);
> +
> + I("reg[0-3] : 0x%08X = 0x%02X, 0x%02X, 0x%02X, 0x%02X",
> + dbg_reg_ary[i], data[0], data[1], data[2], data[3]);
> + }
> +}
> +
> +static void himax_mcu_irq_switch(struct himax_ts_data *ts, int switch_on)
> +{
> + if (switch_on) {
> + if (ts->use_irq)
> + himax_int_enable(ts, switch_on);
> + else
> + hrtimer_start(&ts->timer, ktime_set(1, 0),
> + HRTIMER_MODE_REL);
> + } else {
> + if (ts->use_irq) {
> + himax_int_enable(ts, switch_on);
> + } else {
> + hrtimer_cancel(&ts->timer);
> + cancel_work_sync(&ts->work);
> + }
> + }
> +}
> +
> +static int himax_mcu_assign_sorting_mode(struct himax_ts_data *ts,
> + u8 *tmp_data_in)
> +{
> + u8 retry = 0;
> + union hx_dword_data_t rdata = {0};
> + u32 sorting_addr = FW_GET_VAL(addr_sorting_mode_en);
> + union hx_dword_data_t *tmp_data = (union hx_dword_data_t *)tmp_data_in;
> +
> + I("addr: 0x%08X, write: 0x%08X",
> + sorting_addr, le32_to_cpu(tmp_data->dword));
> +
> + while (retry++ < 3) {
> + g_core_fp.fp_register_write(ts, FW_GET_ARRAY(addr_sorting_mode_en),
> + tmp_data->byte, DATA_LEN_4);
> + usleep_range(1000, 1100);
> + g_core_fp.fp_register_read(ts, FW_GET_ARRAY(addr_sorting_mode_en),
> + rdata.byte, DATA_LEN_4);
> +
> + if (rdata.dword == tmp_data->dword) {
> + I("success to write sorting mode");
> + return NO_ERR;
> + }
> + E("fail to write sorting mode");
> + }
> +
> + return BUS_FAIL;
> +}
> +
> +static int himax_mcu_check_sorting_mode(struct himax_ts_data *ts,
> + u8 *tmp_data_in)
> +{
> + int ret = NO_ERR;
> + u32 sorting_addr = FW_GET_VAL(addr_sorting_mode_en);
> + union hx_dword_data_t *tmp_data = (union hx_dword_data_t *)tmp_data_in;
> +
> + ret = g_core_fp.fp_register_read(ts, FW_GET_ARRAY(addr_sorting_mode_en),
> + tmp_data->byte, DATA_LEN_4);
> + I("addr: 0x%08X, Now is:0x%08X",
> + sorting_addr, le32_to_cpu(tmp_data->dword));
> + if (tmp_data->dword == 0xFFFFFFFF) {
> + ret = BUS_FAIL;
> + I("All 0xFF, Fail!");
> + }
> +
> + return ret;
> +}
> +
> +static u8 himax_mcu_read_DD_status(struct himax_ts_data *ts,
> + u8 *cmd_set, u8 *tmp_data)
> +{
> + int cnt = 0;
> + u8 req_size = cmd_set[0];
> +
> + cmd_set[3] = FW_GET_ARRAY(data_dd_request)[0];
> + g_core_fp.fp_register_write(ts, FW_GET_ARRAY(addr_dd_handshak_addr),
> + cmd_set, DATA_LEN_4);
> + I("cmd set[0]=0x%2X,set[1]=0x%2X,set[2]=0x%2X,set[3]=0x%2X",
> + cmd_set[0], cmd_set[1], cmd_set[2], cmd_set[3]);
> +
> + /* Doing hand shaking 0xAA -> 0xBB */
> + for (cnt = 0; cnt < 100; cnt++) {
> + g_core_fp.fp_register_read(ts, FW_GET_ARRAY(addr_dd_handshak_addr),
> + tmp_data, DATA_LEN_4);
> + usleep_range(10000, 11000);
> +
> + if (tmp_data[3] == FW_GET_ARRAY(data_dd_ack)[0]) {
> + I("Data ready goto moving data");
> + goto FINALIZE;
> + } else {
> + if (cnt >= 99) {
> + I("Data not ready in FW");
> + return FW_NOT_READY;
> + }
> + }
> + }
> +FINALIZE:
> + g_core_fp.fp_register_read(ts, FW_GET_ARRAY(addr_dd_data_addr), tmp_data,
> + req_size);
> + return NO_ERR;
> +}
> +
> +static void hx_clr_fw_reord_dd_sts(struct himax_ts_data *ts)
> +{
> + union hx_dword_data_t tmp_data = {0};
> +
> + g_core_fp.fp_register_read(ts, IC_GET_ARRAY(addr_cs_central_state),
> + tmp_data.byte, ADDR_LEN_4);
> + I("Check enter_save_mode data[0]=%02X", tmp_data.byte[0]);
> +
> + if (tmp_data.byte[0] == 0x0C) {
> + I("Enter safe mode, OK!");
> + } else {
> + E("It doen't enter safe mode, please check it again");
> + return;
> + }
> + g_core_fp.fp_register_read(ts, FW_GET_ARRAY(addr_clr_fw_record_dd_sts),
> + tmp_data.byte, DATA_LEN_4);
> + I("Before Write :Now 10007FCC=0x%08X",
> + le32_to_cpu(tmp_data.dword));
> + usleep_range(10000, 10001);
> +
> + tmp_data.byte[2] = 0x00;
> + tmp_data.byte[3] = 0x00;
> + g_core_fp.fp_register_write(ts, FW_GET_ARRAY(addr_clr_fw_record_dd_sts),
> + tmp_data.byte, DATA_LEN_4);
> + usleep_range(10000, 10001);
> +
> + g_core_fp.fp_register_read(ts, FW_GET_ARRAY(addr_clr_fw_record_dd_sts),
> + tmp_data.byte, DATA_LEN_4);
> + I("After Write :Now 10007FCC=0x%08X",
> + le32_to_cpu(tmp_data.dword));
> +}
> +
> +static void hx_ap_notify_fw_sus(struct himax_ts_data *ts, int suspend)
> +{
> + int retry = 0;
> + int read_sts = 0;
> + union hx_dword_data_t read_tmp = {0};
> + union hx_dword_data_t addr_tmp = {0};
> + union hx_dword_data_t data_tmp = {0};
> +
> + addr_tmp.dword = FW_GET_VAL(addr_ap_notify_fw_sus);
> +
> + if (suspend) {
> + I("Suspend mode!");
> + data_tmp.dword = FW_GET_VAL(data_ap_notify_fw_sus_en);
> + } else {
> + I("Non-Suspend mode!");
> + data_tmp.dword = FW_GET_VAL(data_ap_notify_fw_sus_dis);
> + }
> +
> + I("R%08XH<-0x%08X", addr_tmp.dword, data_tmp.dword);
> + addr_tmp.dword = cpu_to_le32(addr_tmp.dword);
> + data_tmp.dword = cpu_to_le32(data_tmp.dword);
> + do {
> + g_core_fp.fp_register_write(ts, addr_tmp.byte, data_tmp.byte,
> + sizeof(data_tmp.byte));
> + usleep_range(1000, 1001);
> + read_sts = g_core_fp.fp_register_read(ts, addr_tmp.byte, read_tmp.byte,
> + sizeof(read_tmp.byte));
> + I("read bus status=%d", read_sts);
> + I("Now retry=%d, data=0x%08X", retry,
> + le32_to_cpu(read_tmp.dword));
> + } while ((retry++ < 10) && (read_sts != NO_ERR) &&
> + (read_tmp.dword != data_tmp.dword));
> +}
> +
> +/* FW side end*/
> +/* CORE_FW */
> +
> +/* CORE_FLASH */
> +/* FLASH side start*/
> +static void himax_mcu_chip_erase(struct himax_ts_data *ts)
> +{
> + g_core_fp.fp_interface_on(ts);
> +
> + /* Reset power saving level */
> + if (g_core_fp.fp_init_psl)
> + g_core_fp.fp_init_psl(ts);
> +
> + g_core_fp.fp_register_write(ts, FLASH_GET_ARRAY(addr_spi200_trans_fmt),
> + FLASH_GET_ARRAY(data_spi200_trans_fmt), DATA_LEN_4);
> +
> + g_core_fp.fp_register_write(ts, FLASH_GET_ARRAY(addr_spi200_trans_ctrl),
> + FLASH_GET_ARRAY(data_spi200_trans_ctrl_2), DATA_LEN_4);
> + g_core_fp.fp_register_write(ts, FLASH_GET_ARRAY(addr_spi200_cmd),
> + FLASH_GET_ARRAY(data_spi200_cmd_2), DATA_LEN_4);
> +
> + g_core_fp.fp_register_write(ts, FLASH_GET_ARRAY(addr_spi200_cmd),
> + FLASH_GET_ARRAY(data_spi200_cmd_3), DATA_LEN_4);
> + usleep_range(2000000, 2000001);
> +
> + if (!g_core_fp.fp_wait_wip(ts, 100))
> + E("Chip_Erase Fail");
> + else
> + I("Chip_Erase Success");
> +}
> +
> +static bool himax_mcu_block_erase(struct himax_ts_data *ts, int start_addr,
> + int length)
> +{
> + u32 page_prog_start = 0;
> + u32 block_size = 0x10000;
> +
> + DEF_WORD_DATA(tmp_data);
> +
> + g_core_fp.fp_interface_on(ts);
> +
> + g_core_fp.fp_init_psl(ts);
> +
> + g_core_fp.fp_register_write(ts, FLASH_GET_ARRAY(addr_spi200_trans_fmt),
> + FLASH_GET_ARRAY(data_spi200_trans_fmt), DATA_LEN_4);
> +
> + for (page_prog_start = start_addr;
> + page_prog_start < start_addr + length;
> + page_prog_start = page_prog_start + block_size) {
> + g_core_fp.fp_register_write(ts,
> + FLASH_GET_ARRAY(addr_spi200_trans_ctrl),
> + FLASH_GET_ARRAY(data_spi200_trans_ctrl_2), DATA_LEN_4);
> + g_core_fp.fp_register_write(ts,
> + FLASH_GET_ARRAY(addr_spi200_cmd),
> + FLASH_GET_ARRAY(data_spi200_cmd_2), DATA_LEN_4);
> +
> + VAL_SET(tmp_data, page_prog_start);
> + g_core_fp.fp_register_write(ts, FLASH_GET_ARRAY(addr_spi200_addr),
> + tmp_data.data.byte, DATA_LEN_4);
> +
> + g_core_fp.fp_register_write(ts,
> + FLASH_GET_ARRAY(addr_spi200_trans_ctrl),
> + FLASH_GET_ARRAY(data_spi200_trans_ctrl_3), DATA_LEN_4);
> + g_core_fp.fp_register_write(ts,
> + FLASH_GET_ARRAY(addr_spi200_cmd),
> + FLASH_GET_ARRAY(data_spi200_cmd_4), DATA_LEN_4);
> + usleep_range(1000000, 1000001);
> +
> + if (!g_core_fp.fp_wait_wip(ts, 100)) {
> + E("Erase Fail");
> + return false;
> + }
> + }
> +
> + I("END");
> + return true;
> +}
> +
> +static bool himax_mcu_sector_erase(int start_addr)
> +{
> + return true;
> +}
> +
> +static bool himax_mcu_flash_programming(struct himax_ts_data *ts,
> + u8 *FW_content, int fw_size)
> +{
> + int page_prog_start = 0;
> + union hx_dword_data_t tmp_data = {0};
> + int ret = 0;
> + /* 4 bytes for padding*/
> + g_core_fp.fp_interface_on(ts);
> +
> + g_core_fp.fp_register_write(ts,
> + FLASH_GET_ARRAY(addr_spi200_trans_fmt),
> + FLASH_GET_ARRAY(data_spi200_trans_fmt), DATA_LEN_4);
> +
> + for (page_prog_start = 0; page_prog_start < fw_size;
> + page_prog_start += FLASH_RW_MAX_LEN) {
> + /* ===Flash Write Enable ===*/
> +
> + g_core_fp.fp_register_write(ts,
> + FLASH_GET_ARRAY(addr_spi200_trans_ctrl),
> + FLASH_GET_ARRAY(data_spi200_trans_ctrl_2), DATA_LEN_4);
> +
> + g_core_fp.fp_register_write(ts, FLASH_GET_ARRAY(addr_spi200_cmd),
> + FLASH_GET_ARRAY(data_spi200_cmd_2), DATA_LEN_4);
> +
> + /* ===WEL Write Control ===*/
> + g_core_fp.fp_register_write(ts,
> + FLASH_GET_ARRAY(addr_spi200_trans_ctrl),
> + FLASH_GET_ARRAY(data_spi200_trans_ctrl_6), DATA_LEN_4);
> +
> + g_core_fp.fp_register_write(ts,
> + FLASH_GET_ARRAY(addr_spi200_cmd),
> + FLASH_GET_ARRAY(data_spi200_cmd_1), DATA_LEN_4);
> +
> + g_core_fp.fp_register_read(ts, FLASH_GET_ARRAY(addr_spi200_data),
> + tmp_data.byte, DATA_LEN_4);
> +
> + /* === Check WEL Fail ===*/
> + if (((tmp_data.byte[0] & 0x02) >> 1) == 0) {
> + I("SPI 0x8000002c = %d, Check WEL Fail",
> + tmp_data.byte[0]);
> + return false;
> + }
> +
> + g_core_fp.fp_register_write(ts,
> + FLASH_GET_ARRAY(addr_spi200_trans_ctrl),
> + FLASH_GET_ARRAY(data_spi200_trans_ctrl_2), DATA_LEN_4);
> + g_core_fp.fp_register_write(ts,
> + FLASH_GET_ARRAY(addr_spi200_cmd),
> + FLASH_GET_ARRAY(data_spi200_cmd_2), DATA_LEN_4);
> +
> + /*Programmable size = 1 page = 256 bytes,*/
> + /*word_number = 256 byte / 4 = 64*/
> + g_core_fp.fp_register_write(ts,
> + FLASH_GET_ARRAY(addr_spi200_trans_ctrl),
> + FLASH_GET_ARRAY(data_spi200_trans_ctrl_4), DATA_LEN_4);
> +
> + /* Flash start address 1st : 0x0000_0000*/
> + tmp_data.dword = cpu_to_le32(page_prog_start);
> + g_core_fp.fp_register_write(ts,
> + FLASH_GET_ARRAY(addr_spi200_addr), tmp_data.byte, DATA_LEN_4);
> +
> + ret = g_core_fp.fp_register_write(ts,
> + FLASH_GET_ARRAY(addr_spi200_data),
> + &FW_content[page_prog_start], 16);
> + if (ret < 0) {
> + E("bus access fail!");
> + return false;
> + }
> +
> + g_core_fp.fp_register_write(ts, FLASH_GET_ARRAY(addr_spi200_cmd),
> + FLASH_GET_ARRAY(data_spi200_cmd_6), DATA_LEN_4);
> +
> + ret = g_core_fp.fp_register_write(ts,
> + FLASH_GET_ARRAY(addr_spi200_data),
> + &FW_content[page_prog_start + 16], 240);
> + if (ret < 0) {
> + E("bus access fail!");
> + return false;
> + }
> +
> + if (!g_core_fp.fp_wait_wip(ts, 1)) {
> + E("Flash_Programming Fail");
> + return false;
> + }
> + }
> + return true;
> +}
> +
> +static void himax_mcu_flash_page_write(u8 *write_addr, int length,
> + u8 *write_data)
> +{
> +}
> +
> +static void himax_flash_speed_set(struct himax_ts_data *ts, u8 speed)
> +{
> + struct hx_reg_t reg_addr;
> + struct hx_reg_t reg_data;
> +
> + reg_data.data.word = 0;
> + reg_data.data.byte[1] = 0x02; /*extand cs high to 100ns*/
> + reg_data.data.byte[0] = speed;
> + WORD_REG(reg_addr, flash_clk_setup_addr);
> + g_core_fp.fp_register_write(ts, REG_GET_ARRAY(reg_addr),
> + REG_GET_ARRAY(reg_data), 4);
> +}
> +
> +static int himax_mcu_fts_ctpm_fw_upgrade_with_sys_fs_32k
> + (struct himax_ts_data *ts, unsigned char *fw,
> + int len, bool change_iref)
> +{
> + /* Not use */
> + return 0;
> +}
> +
> +static int himax_mcu_fts_ctpm_fw_upgrade_with_sys_fs_60k
> + (struct himax_ts_data *ts, unsigned char *fw,
> + int len, bool change_iref)
> +{
> + /* Not use */
> + return 0;
> +}
> +
> +static int himax_mcu_fts_ctpm_fw_upgrade_with_sys_fs_64k
> + (struct himax_ts_data *ts, unsigned char *fw,
> + int len, bool change_iref)
> +{
> + int burn_firmware_success = 0;
> + int counter = 0;
> +
> + if (len != FW_SIZE_64k) {
> + E("The file size is not 64K bytes");
> + return false;
> + }
> +
> + g_core_fp.fp_ic_reset(ts, false, false);
> + for (counter = 0; counter < 3; counter++) {
> + g_core_fp.fp_sense_off(ts, true);
> + himax_flash_speed_set(ts, HX_FLASH_SPEED_12p5M);
> + g_core_fp.fp_block_erase(ts, 0x00, FW_SIZE_64k);
> + if (g_core_fp.fp_flash_programming(ts, fw, FW_SIZE_64k) == false) {
> + g_core_fp.fp_ic_reset(ts, false, false);
> + continue;
> + }
> +
> + if (g_core_fp.fp_check_crc(ts, FW_GET_ARRAY(addr_program_reload_from),
> + FW_SIZE_64k) == 0) {
> + burn_firmware_success = 1;
> + break;
> + }
> + }
> + /*RawOut select initial*/
> + g_core_fp.fp_register_write(ts, FW_GET_ARRAY(addr_raw_out_sel),
> + FW_GET_ARRAY(data_clear), FW_GET_SZ(data_clear));
> + /*DSRAM func initial*/
> + g_core_fp.fp_assign_sorting_mode(ts, FW_GET_ARRAY(data_clear));
> + g_core_fp.fp_ic_reset(ts, false, false);
> +
> + return burn_firmware_success;
> +}
> +
> +static int himax_mcu_fts_ctpm_fw_upgrade_with_sys_fs_124k
> + (struct himax_ts_data *ts, unsigned char *fw,
> + int len, bool change_iref)
> +{
> + /* Not use */
> + return 0;
> +}
> +
> +static int himax_mcu_fts_ctpm_fw_upgrade_with_sys_fs_128k
> + (struct himax_ts_data *ts, unsigned char *fw,
> + int len, bool change_iref)
> +{
> + int burn_firmware_success = 0;
> + int counter = 0;
> +
> + if (len != FW_SIZE_128k) {
> + E("The file size is not 128K bytes");
> + return false;
> + }
> +
> + g_core_fp.fp_ic_reset(ts, false, false);
> + for (counter = 0; counter < 3; counter++) {
> + g_core_fp.fp_sense_off(ts, true);
> + himax_flash_speed_set(ts, HX_FLASH_SPEED_12p5M);
> + g_core_fp.fp_block_erase(ts, 0x00, FW_SIZE_128k);
> + if (g_core_fp.fp_flash_programming(ts, fw, FW_SIZE_128k) == false) {
> + g_core_fp.fp_ic_reset(ts, false, false);
> + continue;
> + }
> +
> + if (g_core_fp.fp_check_crc(ts, FW_GET_ARRAY(addr_program_reload_from),
> + FW_SIZE_128k) == 0) {
> + burn_firmware_success = 1;
> + break;
> + }
> + }
> + /*RawOut select initial*/
> + g_core_fp.fp_register_write(ts, FW_GET_ARRAY(addr_raw_out_sel),
> + FW_GET_ARRAY(data_clear), FW_GET_SZ(data_clear));
> + /*DSRAM func initial*/
> + g_core_fp.fp_assign_sorting_mode(ts, FW_GET_ARRAY(data_clear));
> +
> + return burn_firmware_success;
> +}
> +
> +static int himax_mcu_fts_ctpm_fw_upgrade_with_sys_fs_255k
> + (struct himax_ts_data *ts, unsigned char *fw,
> + int len, bool change_iref)
> +{
> + int burn_firmware_success = 0;
> + int counter = 0;
> +
> + if (len != FW_SIZE_255k) {
> + E("The file size is not 255K bytes");
> + return false;
> + }
> +
> + g_core_fp.fp_ic_reset(ts, false, false);
> + for (counter = 0; counter < 3; counter++) {
> + g_core_fp.fp_sense_off(ts, true);
> + himax_flash_speed_set(ts, HX_FLASH_SPEED_12p5M);
> + g_core_fp.fp_block_erase(ts, 0x00, FW_SIZE_255k);
> + if (g_core_fp.fp_flash_programming(ts, fw, FW_SIZE_255k) == false) {
> + g_core_fp.fp_ic_reset(ts, false, false);
> + continue;
> + }
> + if (g_core_fp.fp_check_crc(ts, FW_GET_ARRAY(addr_program_reload_from),
> + FW_SIZE_255k) == 0) {
> + burn_firmware_success = 1;
> + break;
> + }
> + }
> + /*RawOut select initial*/
> + g_core_fp.fp_register_write(ts, FW_GET_ARRAY(addr_raw_out_sel),
> + FW_GET_ARRAY(data_clear), FW_GET_SZ(data_clear));
> + /*DSRAM func initial*/
> + g_core_fp.fp_assign_sorting_mode(ts, FW_GET_ARRAY(data_clear));
> +
> + return burn_firmware_success;
> +}
> +
> +static void himax_mcu_flash_dump_func
> + (struct himax_ts_data *ts, u8 local_flash_command,
> + int flash_size, u8 *flash_buffer)
> +{
> + struct hx_reg_t tmp_addr;
> + int page_prog_start = 0;
> +
> + g_core_fp.fp_sense_off(ts, true);
> +
> + for (page_prog_start = 0; page_prog_start < flash_size;
> + page_prog_start += 128) {
> + WORD_REG(tmp_addr, page_prog_start);
> + g_core_fp.fp_register_read(ts, REG_GET_ARRAY(tmp_addr),
> + flash_buffer + page_prog_start, 128);
> + }
> +
> + g_core_fp.fp_sense_on(ts, 0x01);
> +}
> +
> +static bool himax_mcu_flash_lastdata_check(struct himax_ts_data *ts,
> + u32 size)
> +{
> + struct hx_reg_t tmp_addr;
> + /* 64K - 0x80, which is the address of
> + * the last 128bytes in 64K, default value
> + */
> + u32 start_addr = 0xFFFFFFFF;
> + u32 temp_addr = 0;
> + u32 flash_page_len = 0x80;
> + u8 flash_tmp_buffer[128];
> +
> + if (size < flash_page_len) {
> + E("flash size is wrong, terminated");
> + E("flash size = %08X; flash page len = %08X",
> + size, flash_page_len);
> + goto FAIL;
> + }
> +
> + /* In order to match other size of fw */
> + start_addr = size - flash_page_len;
> + I("Now size is %d, the start_addr is 0x%08X",
> + size, start_addr);
> + for (temp_addr = start_addr; temp_addr < (start_addr + flash_page_len);
> + temp_addr = temp_addr + flash_page_len) {
> + /*I("temp_addr=%d,tmp_addr[0]=0x%2X, tmp_addr[1]=0x%2X,
> + * tmp_addr[2]=0x%2X,tmp_addr[3]=0x%2X",
> + * temp_addr,tmp_addr[0], tmp_addr[1],
> + * tmp_addr[2],tmp_addr[3]);
> + */
> + WORD_REG(tmp_addr, temp_addr);
> + g_core_fp.fp_register_read(ts, REG_GET_ARRAY(tmp_addr),
> + &flash_tmp_buffer[0], flash_page_len);
> + }
> +
> + I("FLASH[%08X] ~ FLASH[%08X] = %02X%02X%02X%02X", size - 4, size - 1,
> + flash_tmp_buffer[flash_page_len - 4],
> + flash_tmp_buffer[flash_page_len - 3],
> + flash_tmp_buffer[flash_page_len - 2],
> + flash_tmp_buffer[flash_page_len - 1]);
> +
> + if (!flash_tmp_buffer[flash_page_len - 4] &&
> + !flash_tmp_buffer[flash_page_len - 3] &&
> + !flash_tmp_buffer[flash_page_len - 2] &&
> + !flash_tmp_buffer[flash_page_len - 1]) {
> + I("Fail, Last four Bytes are all 0x00:");
> + goto FAIL;
> + } else if (flash_tmp_buffer[flash_page_len - 4] == 0xFF &&
> + (flash_tmp_buffer[flash_page_len - 3] == 0xFF) &&
> + (flash_tmp_buffer[flash_page_len - 2] == 0xFF) &&
> + (flash_tmp_buffer[flash_page_len - 1] == 0xFF)) {
> + I("Fail, Last four Bytes are all 0xFF:");
> + goto FAIL;
> + } else {
> + return 0;
> + }
> +
> +FAIL:
> + return 1;
> +}
> +
> +static bool hx_bin_desc_data_get(struct himax_ts_data *ts,
> + u32 addr, u8 *flash_buf,
> + const u8 *fw_all_data)
> +{
> + u8 data_sz = 0x10;
> + u32 i = 0, j = 0;
> + u16 chk_end = 0;
> + u16 chk_sum = 0;
> + u32 map_code = 0;
> + unsigned long flash_addr = 0;
> + u32 hid_table_addr = 0;
> + union {
> + u8 *buf;
> + u32 *word;
> + } map_data;
> +
> + for (i = 0; i < FW_PAGE_SZ; i = i + data_sz) {
> + for (j = i; j < (i + data_sz); j++) {
> + chk_end |= flash_buf[j];
> + chk_sum += flash_buf[j];
> + }
> + if (!chk_end) { /*1. Check all zero*/
> + I("End in %X", i + addr);
> + return false;
> + } else if (chk_sum % 0x100) { /*2. Check sum*/
> + I("chk sum failed in %X", i + addr);
> + } else { /*3. get data*/
> + map_data.buf = &flash_buf[i];
> + map_code = le32_to_cpup(map_data.word);
> + map_data.buf = &flash_buf[i + 4];
> + flash_addr = le32_to_cpup(map_data.word);
> + switch (map_code) {
> + case FW_CID:
> + WORD_REG(g_core_regs.flash_ver_info.addr_cid_ver_major,
> + flash_addr);
> + WORD_REG(g_core_regs.flash_ver_info.addr_cid_ver_minor,
> + flash_addr + 1);
> + I("CID_VER in %X", FLASH_VER_GET_VAL(addr_cid_ver_major));
> + memcpy(&ts->fw_bin_desc, &fw_all_data
> + [flash_addr - sizeof(ts->hid_info.fw_bin_desc.passwd)],
> + sizeof(struct hx_bin_desc_t));
> + break;
> + case FW_VER:
> + WORD_REG(g_core_regs.flash_ver_info.addr_fw_ver_major,
> + flash_addr);
> + WORD_REG(g_core_regs.flash_ver_info.addr_fw_ver_minor,
> + flash_addr + 1);
> + I("FW_VER in %X", FLASH_VER_GET_VAL(addr_fw_ver_major));
> + break;
> + case CFG_VER:
> + WORD_REG(g_core_regs.flash_ver_info.addr_cfg_ver_major,
> + flash_addr);
> + WORD_REG(g_core_regs.flash_ver_info.addr_cfg_ver_minor,
> + flash_addr + 1);
> + I("CFG_VER in = %08X", FLASH_VER_GET_VAL(addr_cfg_ver_major));
> + break;
> + case TP_CONFIG_TABLE:
> + WORD_REG(g_core_regs.flash_ver_info.addr_cfg_table,
> + flash_addr);
> + I("CONFIG_TABLE in %X", FLASH_VER_GET_VAL(addr_cfg_table));
> + break;
> + case HID_TABLE:
> + WORD_REG(g_core_regs.flash_ver_info.addr_hid_table,
> + flash_addr);
> + I("HID_TABLE in %X", FLASH_VER_GET_VAL(addr_hid_table));
> + hid_table_addr = FLASH_VER_GET_VAL(addr_hid_table);
> + WORD_REG(g_core_regs.flash_ver_info.addr_hid_desc,
> + hid_table_addr);
> + I("HID_DESC in %X", FLASH_VER_GET_VAL(addr_hid_desc));
> + WORD_REG(g_core_regs.flash_ver_info.addr_hid_rd_desc,
> + (hid_table_addr + 24));
> + I("HID_RD_DESC in %X", FLASH_VER_GET_VAL(addr_hid_rd_desc));
> + break;
> + }
> + }
> + chk_end = 0;
> + chk_sum = 0;
> + }
> +
> + return true;
> +}
> +
> +static bool hx_mcu_bin_desc_get(unsigned char *fw, struct himax_ts_data *ts,
> + u32 max_sz)
> +{
> + u32 addr_t = 0;
> + unsigned char *fw_buf = NULL;
> + bool keep_on_flag = false;
> + bool bin_desc_flag = false;
> +
> + do {
> + fw_buf = &fw[addr_t];
> +
> + /*Check bin is with description table or not*/
> + if (!bin_desc_flag) {
> + if (fw_buf[0x00] == 0x00 && fw_buf[0x01] == 0x00 &&
> + fw_buf[0x02] == 0x00 && fw_buf[0x03] == 0x00 &&
> + fw_buf[0x04] == 0x00 && fw_buf[0x05] == 0x00 &&
> + fw_buf[0x06] == 0x00 && fw_buf[0x07] == 0x00 &&
> + fw_buf[0x0E] == 0x87)
> + bin_desc_flag = true;
> + }
> + if (!bin_desc_flag) {
> + I("fw_buf[0x00] = %2X, fw_buf[0x0E] = %2X",
> + fw_buf[0x00], fw_buf[0x0E]);
> + I("No description table");
> + break;
> + }
> +
> + /*Get related data*/
> + keep_on_flag = hx_bin_desc_data_get(ts, addr_t, fw_buf, fw);
> + if (FLASH_VER_GET_VAL(addr_hid_table) >= ts->hxfw->size ||
> + (FLASH_VER_GET_VAL(addr_hid_rd_desc) +
> + ts->hid_rd_data.rd_length) >= ts->hxfw->size) {
> + W("hid_table_addr = %d, ts->hxfw->size = %lu!",
> + FLASH_VER_GET_VAL(addr_hid_table), ts->hxfw->size);
> + W("hid_rd_desc_addr = %d, rd_len = %d, ts->hxfw->size = %lu!",
> + FLASH_VER_GET_VAL(addr_hid_rd_desc),
> + ts->hid_rd_data.rd_length,
> + ts->hxfw->size);
> + WORD_REG(g_core_regs.flash_ver_info.addr_hid_table, 0);
> + WORD_REG(g_core_regs.flash_ver_info.addr_hid_desc, 0);
> + WORD_REG(g_core_regs.flash_ver_info.addr_hid_rd_desc, 0);
> + }
> +
> + addr_t = addr_t + FW_PAGE_SZ;
> + } while (max_sz > addr_t && keep_on_flag);
> +
> + return bin_desc_flag;
> +}
> +
> +static int hx_mcu_diff_overlay_flash(struct himax_ts_data *ts)
> +{
> + int rslt = 0;
> + int diff_val = 0;
> +
> + diff_val = (ts->ic_data->vendor_fw_ver);
> + I("Now fw ID is 0x%04X", diff_val);
> + diff_val = (diff_val >> 12);
> + I("Now diff value=0x%04X", diff_val);
> +
> + if (diff_val == 1)
> + I("Now size should be 128K!");
> + else
> + I("Now size should be 64K!");
> + rslt = diff_val;
> + return rslt;
> +}
> +
> +/* FLASH side end*/
> +/* CORE_FLASH */
> +
> +/* CORE_SRAM */
> +/* SRAM side start*/
> +static void himax_mcu_sram_write(struct himax_ts_data *ts, u8 *fw_content)
> +{
> +}
> +
> +static bool himax_mcu_sram_verify(struct himax_ts_data *ts, u8 *fw_file,
> + int fw_size)
> +{
> + return true;
> +}
> +
> +static bool himax_mcu_get_DSRAM_data(struct himax_ts_data *ts,
> + u8 *info_data, bool dsram_flag)
> +{
> + unsigned int i = 0;
> + struct hx_reg_t tmp_addr;
> + union hx_dword_data_t tmp_data = {0};
> + unsigned int max_bus_size = MAX_I2C_TRANS_SZ;
> + const u32 x_num = ts->ic_data->HX_RX_NUM;
> + const u32 y_num = ts->ic_data->HX_TX_NUM;
> + unsigned int total_size = (x_num * y_num + x_num + y_num) * 2 + 4;
> + unsigned int remain_size;
> + u32 retry = 0;
> + unsigned int addr = 0;
> + u8 *temp_info_data = NULL; /*max mkey size = 8*/
> + u32 checksum = 0;
> + s32 fw_run_flag = -1;
> +
> +#if defined(BUS_R_DLEN)
> + max_bus_size = BUS_R_DLEN;
> +#endif
> +
> + if (strcmp(ts->chip_name, HX83121A_ID) == 0) {
> + if (max_bus_size > 4096)
> + max_bus_size = 4096;
> + }
> +
> + temp_info_data = kcalloc((total_size + 8), sizeof(u8), GFP_KERNEL);
> + if (!temp_info_data) {
> + E("Failed to allocate memory");
> + return false;
> + }
> + /* 1. Read number of MKey R100070E8H to determin data size */
> + /* m_key_num = g_hx_ic_data->HX_BT_NUM; */
> + /* I("m_key_num=%d", m_key_num); */
> + /* total_size += m_key_num * 2; */
> +
> + /* 2. Start DSRAM Rawdata and Wait Data Ready */
> + tmp_data.dword = SRAM_GET_VAL(passwrd_start);
> + tmp_data.dword = cpu_to_le32(tmp_data.dword);
> + fw_run_flag = himax_write_read_reg(ts, SRAM_GET_ARRAY(addr_rawdata_addr),
> + tmp_data.byte,
> + SRAM_GET_ARRAY(passwrd_end)[1],
> + SRAM_GET_ARRAY(passwrd_end)[0]);
> +
> + if (fw_run_flag < 0) {
> + E("Data NOT ready => bypass");
> + kfree(temp_info_data);
> + return false;
> + }
> +
> + /* 3. Read RawData */
> + while (retry++ < 5) {
> + remain_size = total_size;
> + while (remain_size > 0) {
> + i = total_size - remain_size;
> + addr = sram_adr_rawdata_addr + i;
> +
> + WORD_REG(tmp_addr, addr);
> +
> + if (remain_size >= max_bus_size) {
> + g_core_fp.fp_register_read(ts, REG_GET_ARRAY(tmp_addr),
> + &temp_info_data[i], max_bus_size);
> + remain_size -= max_bus_size;
> + } else {
> + g_core_fp.fp_register_read(ts, REG_GET_ARRAY(tmp_addr),
> + &temp_info_data[i], remain_size);
> + remain_size = 0;
> + }
> + }
> +
> + /* 5. Data Checksum Check */
> + /* 2 is meaning PASSWORD NOT included */
> + checksum = 0;
> + for (i = 2; i < total_size; i += 2)
> + checksum += temp_info_data[i + 1] << 8 | temp_info_data[i];
> +
> + if (checksum % 0x10000 != 0) {
> + E("check_sum_cal fail=%08X", checksum);
> +
> + } else {
> + memcpy(info_data, temp_info_data,
> + total_size * sizeof(u8));
> + break;
> + }
> + }
> +
> + /* 4. FW stop outputing */
> + tmp_data.dword = 0;
> + tmp_data.byte[3] = temp_info_data[3];
> + tmp_data.byte[2] = temp_info_data[2];
> + g_core_fp.fp_register_write(ts, SRAM_GET_ARRAY(addr_rawdata_addr),
> + tmp_data.byte, DATA_LEN_4);
> +
> + kfree(temp_info_data);
> + if (retry >= 5)
> + return false;
> + else
> + return true;
> +}
> +
> +/* SRAM side end*/
> +/* CORE_SRAM */
> +
> +/* CORE_DRIVER */
> +static void himax_mcu_init_ic(struct himax_ts_data *ts)
> +{
> + I("use default incell init.");
> +}
> +
> +static void himax_suspend_proc(struct himax_ts_data *ts, bool suspended)
> +{
> + I("himax suspend.");
> +}
> +
> +static void himax_resume_proc(struct himax_ts_data *ts, bool suspended)
> +{
> + int result = 0;
> +
> + I("himax resume.");
> + if (!ts->ic_data->has_flash) {
> + if (g_core_fp.fp_0f_op_file_dirly) {
> + result = g_core_fp.fp_0f_op_file_dirly(g_fw_boot_upgrade_name,
> + ts);
> + if (result)
> + E("update FW fail, code[%d]!!", result);
> + else
> + ts->resume_success = true;
> + }
> + } else {
> + if (g_core_fp.fp_resend_cmd_func) {
> + g_core_fp.fp_resend_cmd_func(ts, suspended);
> + ts->resume_success = true;
> + }
> + }
> +
> + if (g_core_fp.fp_ap_notify_fw_sus && result == 0)
> + g_core_fp.fp_ap_notify_fw_sus(ts, 0);
> +}
> +
> +static void himax_mcu_pin_reset(struct himax_ts_data *ts)
> +{
> + const int rst_low_period_s = RST_LOW_PERIOD_S;
> + const int rst_low_period_e = RST_LOW_PERIOD_E;
> + int rst_high_period_s;
> + int rst_high_period_e;
> +
> + I("Now reset the Touch chip.");
> + if (!ts->ic_data->has_flash) {
> + rst_high_period_s = RST_HIGH_PERIOD_ZF_S;
> + rst_high_period_e = RST_HIGH_PERIOD_ZF_E;
> + } else {
> + rst_high_period_s = RST_HIGH_PERIOD_S;
> + rst_high_period_e = RST_HIGH_PERIOD_E;
> + }
> + himax_rst_gpio_set(ts->rst_gpio, 0);
> + usleep_range(rst_low_period_s, rst_low_period_e);
> + himax_rst_gpio_set(ts->rst_gpio, 1);
> + usleep_range(rst_high_period_s, rst_high_period_e);
> +}
> +
> +static void himax_mcu_ic_reset(struct himax_ts_data *ts, u8 loadconfig,
> + u8 int_off)
> +{
> + I("status: loadconfig=%d,int_off=%d", loadconfig, int_off);
> +
> + if (ts->rst_gpio >= 0) {
> + if (int_off)
> + g_core_fp.fp_irq_switch(ts, 0);
> +
> + g_core_fp.fp_pin_reset(ts);
> +
> + if (int_off)
> + g_core_fp.fp_irq_switch(ts, 1);
> + }
> +}
> +
> +static u8 himax_mcu_tp_info_check(struct himax_ts_data *ts)
> +{
> + union hx_dword_data_t addr;
> + char data[DATA_LEN_4] = {0};
> + u32 rx_num;
> + u32 tx_num;
> + u32 bt_num;
> + u32 max_pt;
> + u32 y_res;
> + u32 x_res;
> + u8 int_is_edge;
> + u8 stylus_func;
> + u8 stylus_id_v2;
> + u8 stylus_ratio;
> +
> + g_core_fp.fp_register_read(ts,
> + DRV_GET_ARRAY(addr_fw_define_rxnum_txnum), data, DATA_LEN_4);
> + rx_num = data[2];
> + tx_num = data[3];
> +
> + g_core_fp.fp_register_read(ts,
> + DRV_GET_ARRAY(addr_fw_define_maxpt_xyrvs), data, DATA_LEN_4);
> + max_pt = data[0];
> +
> + g_core_fp.fp_register_read(ts,
> + DRV_GET_ARRAY(addr_fw_define_x_y_res), data, DATA_LEN_4);
> + y_res = be16_to_cpup((u16 *)&data[0]);
> + x_res = be16_to_cpup((u16 *)&data[2]);
> + /* I("rx_num=%d, tx_num=%d, max_pt=%d, y_res=%d, x_res=%d",
> + * rx_num, tx_num, max_pt, y_res, x_res);
> + */
> +
> + g_core_fp.fp_register_read(ts,
> + DRV_GET_ARRAY(addr_fw_define_int_is_edge), data, DATA_LEN_4);
> + if ((data[1] & 0x01) == 1)
> + int_is_edge = true;
> + else
> + int_is_edge = false;
> +
> + /*1. Read number of MKey R100070E8H to determin data size*/
> + g_core_fp.fp_register_read(ts, SRAM_GET_ARRAY(addr_mkey), data,
> + DATA_LEN_4);
> + bt_num = data[0] & 0x03;
> + ts->ic_data->HX_BT_NUM = bt_num;
> +
> + addr.dword = 0x1000719C;
> + addr.dword = cpu_to_le32(addr.dword);
> +
> + g_core_fp.fp_register_read(ts, addr.byte, data, DATA_LEN_4);
> + stylus_func = data[3];
> + ts->ic_data->HX_STYLUS_FUNC = stylus_func;
> +
> + ts->ic_data->HX_RX_NUM = rx_num;
> +
> + ts->ic_data->HX_TX_NUM = tx_num;
> +
> + ts->ic_data->HX_X_RES = x_res;
> + ts->ic_data->HX_Y_RES = y_res;
> + ts->ic_data->HX_MAX_PT = max_pt;
> + ts->ic_data->HX_INT_IS_EDGE = int_is_edge;
> +
> + if (ts->ic_data->HX_STYLUS_FUNC) {
> + addr.dword = 0x100071FC;
> + addr.dword = cpu_to_le32(addr.dword);
> + g_core_fp.fp_register_read(ts, addr.byte, data, DATA_LEN_4);
> + stylus_id_v2 = data[2];/* 0x100071FE 0=off 1=on */
> + stylus_ratio = data[3];
> + /* 0x100071FF 0=ratio_1 10=ratio_10 */
> + ts->ic_data->HX_STYLUS_ID_V2 = stylus_id_v2;
> + ts->ic_data->HX_STYLUS_RATIO = stylus_ratio;
> + }
> +
> + I("TOUCH_INFO updated");
> +
> + return 0;
> +}
> +
> +static void himax_mcu_touch_information(struct himax_ts_data *ts)
> +{
> + if (ts->ic_data->HX_RX_NUM == 0xFFFFFFFF)
> + ts->ic_data->HX_RX_NUM = FIX_HX_RX_NUM;
> +
> + if (ts->ic_data->HX_TX_NUM == 0xFFFFFFFF)
> + ts->ic_data->HX_TX_NUM = FIX_HX_TX_NUM;
> +
> + if (ts->ic_data->HX_BT_NUM == 0xFFFFFFFF)
> + ts->ic_data->HX_BT_NUM = FIX_HX_BT_NUM;
> +
> + if (ts->ic_data->HX_MAX_PT == 0xFFFFFFFF)
> + ts->ic_data->HX_MAX_PT = FIX_HX_MAX_PT;
> +
> + if (ts->ic_data->HX_INT_IS_EDGE == 0xFF)
> + ts->ic_data->HX_INT_IS_EDGE = FIX_HX_INT_IS_EDGE;
> +
> + if (ts->ic_data->HX_STYLUS_FUNC == 0xFF)
> + ts->ic_data->HX_STYLUS_FUNC = FIX_HX_STYLUS_FUNC;
> +
> + if (ts->ic_data->HX_STYLUS_ID_V2 == 0xFF)
> + ts->ic_data->HX_STYLUS_ID_V2 = FIX_HX_STYLUS_ID_V2;
> +
> + if (ts->ic_data->HX_STYLUS_RATIO == 0xFF)
> + ts->ic_data->HX_STYLUS_RATIO = FIX_HX_STYLUS_RATIO;
> +
> + I("HX_RX_NUM = %d,HX_TX_NUM = %d",
> + ts->ic_data->HX_RX_NUM, ts->ic_data->HX_TX_NUM);
> + I("HX_MAX_PT = %d", ts->ic_data->HX_MAX_PT);
> + I("HX_INT_IS_EDGE = %d,HX_STYLUS_FUNC = %d",
> + ts->ic_data->HX_INT_IS_EDGE, ts->ic_data->HX_STYLUS_FUNC);
> + I("HX_STYLUS_ID_V2 = %d,HX_STYLUS_RATIO = %d",
> + ts->ic_data->HX_STYLUS_ID_V2, ts->ic_data->HX_STYLUS_RATIO);
> +}
> +
> +static void himax_mcu_calc_touch_data_size(struct himax_ts_data *ts)
> +{
> + ts->x_channel = ts->ic_data->HX_RX_NUM;
> + ts->y_channel = ts->ic_data->HX_TX_NUM;
> + ts->n_finger_support = ts->ic_data->HX_MAX_PT;
> +}
> +
> +static int himax_mcu_get_touch_data_size(void)
> +{
> + return HIMAX_TOUCH_DATA_SIZE;
> +}
> +
> +static int himax_mcu_hand_shaking(void)
> +{
> + /* 0:Running, 1:Stop, 2:I2C Fail */
> + int result = 0;
> + return result;
> +}
> +
> +static int himax_mcu_determin_diag_rawdata(int diag_command)
> +{
> + return diag_command % 10;
> +}
> +
> +static int himax_mcu_determin_diag_storage(int diag_command)
> +{
> + return diag_command / 10;
> +}
> +
> +static int himax_mcu_cal_data_len(int raw_cnt_rmd, int HX_MAX_PT,
> + int raw_cnt_max)
> +{
> + int raw_data_len;
> + /* rawdata checksum is 2 bytes */
> + if (raw_cnt_rmd != 0x00)
> + raw_data_len = MAX_I2C_TRANS_SZ
> + - ((HX_MAX_PT + raw_cnt_max + 3) * 4) - 2;
> + else
> + raw_data_len = MAX_I2C_TRANS_SZ
> + - ((HX_MAX_PT + raw_cnt_max + 2) * 4) - 2;
> +
> + return raw_data_len;
> +}
> +
> +static bool himax_mcu_diag_check_sum(struct himax_ts_data *ts)
> +{
> + u16 check_sum_cal = 0;
> + int i;
> +
> + /* Check 128th byte CRC */
> + for (i = 0, check_sum_cal = 0;
> + i < (ts->touch_all_size
> + - ts->touch_info_size);
> + i += 2) {
> + check_sum_cal += (ts->hx_rawdata_buf[i + 1]
> + * FLASH_RW_MAX_LEN
> + + ts->hx_rawdata_buf[i]);
> + }
> +
> + if (check_sum_cal % HX64K != 0) {
> + I("fail = %2X", check_sum_cal);
> + return 0;
> + }
> +
> + return 1;
> +}
> +
> +static int himax_mcu_ic_excp_recovery
> + (struct himax_ts_data *ts,
> + u32 hx_excp_event,
> + u32 hx_zero_event,
> + u32 length)
> +{
> + int ret_val = NO_ERR;
> +
> + if (hx_excp_event == length) {
> + ts->excp_zero_event_count = 0;
> + ret_val = HX_EXCP_EVENT;
> + } else if (hx_zero_event == length) {
> + if (ts->excp_zero_event_count > 5) {
> + ts->excp_zero_event_count = 0;
> + I("EXCEPTION event checked - ALL Zero.");
> + ret_val = HX_EXCP_EVENT;
> + } else {
> + ts->excp_zero_event_count++;
> + I("ALL Zero event is %d times.",
> + ts->excp_zero_event_count);
> + ret_val = HX_ZERO_EVENT_COUNT;
> + }
> + }
> +
> + return ret_val;
> +}
> +
> +static void himax_mcu_excp_ic_reset(struct himax_ts_data *ts)
> +{
> + ts->excp_reset_active = 0;
> + himax_mcu_pin_reset(ts);
> + I("reset!");
> +}
> +
> +static void himax_mcu_resend_cmd_func(struct himax_ts_data *ts, bool suspended)
> +{
> + himax_cable_detect_func(ts, true);
> +}
> +
> +/* CORE_DRIVER */
> +
> +static int hx_turn_on_mp_func(struct himax_ts_data *ts, int on)
> +{
> + int rslt = 0;
> + int retry = 3;
> + struct hx_reg_t tmp_addr;
> + struct hx_reg_t tmp_data;
> + u8 tmp_read[4] = {0};
> +
> + if (strcmp(HX83102D_ID, ts->chip_name) == 0) {
> + WORD_REG(tmp_addr, fw_addr_ctrl_mpap_ovl);
> + if (on) {
> + I("Turn on MPAP mode!");
> + WORD_REG(tmp_data, fw_data_ctrl_mpap_ovl_on);
> + do {
> + g_core_fp.fp_register_write(ts, REG_GET_ARRAY(tmp_addr),
> + REG_GET_ARRAY(tmp_data), REG_GET_SZ(tmp_data));
> + usleep_range(10000, 10001);
> + g_core_fp.fp_register_read(ts, REG_GET_ARRAY(tmp_addr),
> + tmp_read, 4);
> +
> + I("read2=0x%02X,read1=0x%02X,read0=0x%02X",
> + tmp_read[2], tmp_read[1],
> + tmp_read[0]);
> +
> + retry--;
> + } while (((retry > 0) &&
> + (tmp_read[2] != REG_GET_ARRAY(tmp_data)[2] &&
> + tmp_read[1] != REG_GET_ARRAY(tmp_data)[1] &&
> + tmp_read[0] != REG_GET_ARRAY(tmp_data)[0])));
> + } else {
> + I("Turn off MPAP mode!");
> + WORD_REG(tmp_data, fw_data_clear);
> + do {
> + g_core_fp.fp_register_write(ts, REG_GET_ARRAY(tmp_addr),
> + REG_GET_ARRAY(tmp_data), REG_GET_SZ(tmp_data));
> + usleep_range(10000, 10001);
> + g_core_fp.fp_register_read(ts, REG_GET_ARRAY(tmp_addr),
> + tmp_read, sizeof(tmp_read));
> +
> + I("read2=0x%02X,read1=0x%02X,read0=0x%02X",
> + tmp_read[2], tmp_read[1], tmp_read[0]);
> +
> + retry--;
> + } while ((retry > 0) &&
> + (tmp_read[2] != REG_GET_ARRAY(tmp_data)[2] &&
> + tmp_read[1] != REG_GET_ARRAY(tmp_data)[1] &&
> + tmp_read[0] != REG_GET_ARRAY(tmp_data)[0]));
> + }
> + } else {
> + I("Nothing to be done!");
> + }
> +
> + return rslt;
> +}
> +
> +static void hx_dis_rload_0f(struct himax_ts_data *ts, int disable)
> +{
> + /*Disable Flash Reload*/
> + g_core_fp.fp_register_write(ts,
> + DRV_GET_ARRAY(addr_fw_define_flash_reload),
> + ZF_GET_ARRAY(data_dis_flash_reload), DATA_LEN_4);
> +}
> +
> +static void himax_mcu_clean_sram_0f(struct himax_ts_data *ts, u8 *addr,
> + int write_len, int type)
> +{
> + int total_read_times = 0;
> + int max_bus_size = MAX_I2C_TRANS_SZ;
> + int total_size_temp = 0;
> + int address = 0;
> + int i = 0;
> +
> + u8 fix_data = 0x00;
> + union hx_dword_data_t tmp_addr;
> + u8 tmp_data[MAX_I2C_TRANS_SZ] = {0};
> +
> + I("Entering");
> +
> + total_size_temp = write_len;
> +
> + tmp_addr.dword = le32_to_cpup((__le32 *)addr);
> + I("addr = 0x%08X", tmp_addr.dword);
> +
> + switch (type) {
> + case 0:
> + fix_data = 0x00;
> + break;
> + case 1:
> + fix_data = 0xAA;
> + break;
> + case 2:
> + fix_data = 0xBB;
> + break;
> + }
> +
> + for (i = 0; i < MAX_I2C_TRANS_SZ; i++)
> + tmp_data[i] = fix_data;
> +
> + I("total size=%d", total_size_temp);
> +
> + if (total_size_temp % max_bus_size == 0)
> + total_read_times = total_size_temp / max_bus_size;
> + else
> + total_read_times = total_size_temp / max_bus_size + 1;
> +
> + tmp_addr.dword = cpu_to_le32(tmp_addr.dword);
> + for (i = 0; i < (total_read_times); i++) {
> + I("[log]write %d time start!", i);
> + if (total_size_temp >= max_bus_size) {
> + g_core_fp.fp_register_write(ts, tmp_addr.byte, tmp_data,
> + max_bus_size);
> + total_size_temp = total_size_temp - max_bus_size;
> + } else {
> + I("last total_size_temp=%d", total_size_temp);
> + g_core_fp.fp_register_write(ts, tmp_addr.byte, tmp_data,
> + total_size_temp % max_bus_size);
> + }
> + address = ((i + 1) * max_bus_size);
> + tmp_addr.dword = cpu_to_le32(address);
> +
> + usleep_range(10000, 11000);
> + }
> +
> + I("END");
> +}
> +
> +static void himax_mcu_write_sram_0f(struct himax_ts_data *ts,
> + u8 *addr, const u8 *data, u32 len)
> +{
> + int max_bus_size = MAX_I2C_TRANS_SZ;
> + u32 remain_len = 0;
> + u32 address = 0;
> + u32 i;
> + struct hx_reg_t tmp_addr;
> +
> + I("Entering - total write size = %d", len);
> +
> +#if defined(BUS_W_DLEN)
> + max_bus_size = BUS_W_DLEN - ADDR_LEN_4;
> +#endif
> +
> + if (strcmp(ts->chip_name, HX83121A_ID) == 0) {
> + if (max_bus_size > 4096)
> + max_bus_size = 4096;
> + }
> +
> + remain_len = len;
> + address = le32_to_cpup((__le32 *)addr);
> +
> + while (remain_len > 0) {
> + i = len - remain_len;
> + WORD_REG(tmp_addr, address + i);
> +
> + if (remain_len > max_bus_size) {
> + g_core_fp.fp_register_write(ts, REG_GET_ARRAY(tmp_addr),
> + (u8 *)data + i, max_bus_size);
> + remain_len -= max_bus_size;
> + } else {
> + g_core_fp.fp_register_write(ts, REG_GET_ARRAY(tmp_addr),
> + (u8 *)data + i, remain_len);
> + remain_len = 0;
> + }
> + }
> +
> + I("End");
> +}
> +
> +static int himax_sram_write_crc_check(struct himax_ts_data *ts,
> + u8 *addr, const u8 *data, u32 len)
> +{
> + int retry = 0;
> + int crc = -1;
> +
> + do {
> + g_core_fp.fp_write_sram_0f(ts, addr, data, len);
> + crc = g_core_fp.fp_check_crc(ts, addr, len);
> + retry++;
> + I("HW CRC %s in %d time",
> + (crc == 0) ? "OK" : "Fail", retry);
> + } while (crc != 0 && retry < 3);
> +
> + return crc;
> +}
> +
> +static int code_overlay(struct zf_info *info, const struct firmware *fw,
> + struct himax_ts_data *ts, int type)
> +{
> + int ret = 0;
> + int retry = 0;
> + union hx_dword_data_t tmp_addr = { .dword = 0x10007FFC };
> + union hx_dword_data_t rdata = {0};
> + u8 code_idx_t = 0;
> + union hx_dword_data_t code_sdata = {0};
> +
> + /* ovl_idx[0] - sorting */
> + /* ovl_idx[1] - gesture */
> + /* ovl_idx[2] - border */
> +
> + code_idx_t = ts->ovl_idx[0];
> + code_sdata.dword = ovl_sorting_reply;
> +
> + if (type == 0) {
> + code_idx_t = ts->ovl_idx[2];
> + code_sdata.dword = ovl_border_reply;
> + }
> + if (code_idx_t == 0 || info[code_idx_t].write_size == 0) {
> + E("wrong code overlay section[%d, %d]!",
> + code_idx_t, info[code_idx_t].write_size);
> + ret = FW_NOT_READY;
> + goto ALOC_CFG_BUF_FAIL;
> + }
> +
> + I("upgrade code overlay section[%d]", code_idx_t);
> + if (himax_sram_write_crc_check(ts, info[code_idx_t].sram_addr,
> + &fw->data[info[code_idx_t].fw_addr],
> + info[code_idx_t].write_size) != 0) {
> + E("code overlay HW CRC FAIL");
> + code_sdata.dword = ovl_fault;
> + ret = 2;
> + }
> +
> + retry = 0;
> + tmp_addr.dword = cpu_to_le32(tmp_addr.dword);
> + code_sdata.dword = cpu_to_le32(code_sdata.dword);
> + do {
> + g_core_fp.fp_register_write(ts, tmp_addr.byte, code_sdata.byte,
> + DATA_LEN_4);
> + usleep_range(1000, 1100);
> + g_core_fp.fp_register_read(ts, tmp_addr.byte, rdata.byte,
> + DATA_LEN_4);
> + retry++;
> + } while ((code_sdata.dword != rdata.dword) &&
> + (retry < HIMAX_REG_RETRY_TIMES));
> +
> + if (retry >= HIMAX_REG_RETRY_TIMES)
> + E("fail code rpl data = 0x%08X", rdata.dword);
> +
> +ALOC_CFG_BUF_FAIL:
> + return ret;
> +}
> +
> +static int alg_overlay(struct himax_ts_data *ts, u8 alg_idx_t,
> + struct zf_info *info, const struct firmware *fw)
> +{
> + int ret = 0;
> + int retry = 0;
> + union hx_dword_data_t tmp_addr = { .dword = 0x10007FFC };
> + union hx_dword_data_t rdata = {0};
> + u8 i = 0;
> + union hx_dword_data_t alg_sdata = { .dword = 0xA55A5AA5 };
> + union hx_dword_data_t data = { .dword = 0x00000001 };
> +
> + if (alg_idx_t == 0 || info[alg_idx_t].write_size == 0) {
> + E("wrong alg overlay section[%d, %d]!",
> + alg_idx_t, info[alg_idx_t].write_size);
> + ret = FW_NOT_READY;
> + goto ALOC_CFG_BUF_FAIL;
> + }
> +
> + // clear handshaking to 0xA55A5AA5
> +
> + retry = 0;
> + tmp_addr.dword = cpu_to_le32(tmp_addr.dword);
> + alg_sdata.dword = cpu_to_le32(alg_sdata.dword);
> + do {
> + g_core_fp.fp_register_write(ts, tmp_addr.byte, alg_sdata.byte,
> + DATA_LEN_4);
> + usleep_range(1000, 1100);
> + g_core_fp.fp_register_read(ts, tmp_addr.byte, rdata.byte,
> + DATA_LEN_4);
> + } while ((rdata.dword != alg_sdata.dword) &&
> + retry++ < HIMAX_REG_RETRY_TIMES);
> +
> + if (retry > HIMAX_REG_RETRY_TIMES) {
> + E("init handshaking data FAIL[0x%08X]!!",
> + le32_to_cpu(rdata.dword));
> + }
> +
> + alg_sdata.dword = ovl_alg_reply;
> +
> + g_core_fp.fp_reload_disable(ts, 0);
> +
> + /*Rawout Sel initial*/
> + g_core_fp.fp_register_write(ts, FW_GET_ARRAY(addr_raw_out_sel),
> + FW_GET_ARRAY(data_clear), FW_GET_SZ(data_clear));
> + /*DSRAM func initial*/
> + g_core_fp.fp_assign_sorting_mode(ts, FW_GET_ARRAY(data_clear));
> + /* reset N frame back to default for normal mode */
> + g_core_fp.fp_register_write(ts, FW_GET_ARRAY(addr_set_frame_addr),
> + data.byte, 4);
> + /*FW reload done initial*/
> + g_core_fp.fp_register_write(ts,
> + DRV_GET_ARRAY(addr_fw_define_2nd_flash_reload),
> + FW_GET_ARRAY(data_clear), FW_GET_SZ(data_clear));
> +
> + g_core_fp.fp_sense_on(ts, 0x00);
> +
> + retry = 0;
> + do {
> + usleep_range(3000, 3100);
> + g_core_fp.fp_register_read(ts, tmp_addr.byte, rdata.byte, DATA_LEN_4);
> + } while ((rdata.dword != ovl_alg_request) && retry++ < 30);
> +
> + if (retry > 30) {
> + E("fail req data = 0x%08X", le32_to_cpu(rdata.dword));
> + /* monitor FW status for debug */
> + for (i = 0; i < 10; i++) {
> + usleep_range(10000, 10100);
> + g_core_fp.fp_register_read(ts, tmp_addr.byte, rdata.byte,
> + DATA_LEN_4);
> + I("req data = 0x%08X", le32_to_cpu(rdata.dword));
> + g_core_fp.fp_read_FW_status(ts);
> + }
> + ret = 3;
> + goto BURN_OVL_FAIL;
> + }
> +
> + I("upgrade alg overlay section[%d]", alg_idx_t);
> +
> + if (himax_sram_write_crc_check(ts, info[alg_idx_t].sram_addr,
> + &fw->data[info[alg_idx_t].fw_addr],
> + info[alg_idx_t].write_size) != 0) {
> + E("Alg Overlay HW CRC FAIL");
> + ret = 2;
> + }
> +
> + retry = 0;
> + do {
> + g_core_fp.fp_register_write(ts, tmp_addr.byte, alg_sdata.byte,
> + DATA_LEN_4);
> + usleep_range(1000, 1100);
> + g_core_fp.fp_register_read(ts, tmp_addr.byte, rdata.byte, DATA_LEN_4);
> + } while ((alg_sdata.dword != rdata.dword) &&
> + retry++ < HIMAX_REG_RETRY_TIMES);
> +
> + if (retry > HIMAX_REG_RETRY_TIMES) {
> + E("fail rpl data = 0x%08X", le32_to_cpu(rdata.dword));
> + // maybe need to reset
> + } else {
> + I("waiting for FW reload data");
> +
> + retry = 0;
> + while (retry++ < 30) {
> + g_core_fp.fp_register_read(ts,
> + DRV_GET_ARRAY(addr_fw_define_2nd_flash_reload),
> + data.byte, DATA_LEN_4);
> +
> + /* use all 4 bytes to compare */
> + if (le32_to_cpu(data.dword) == 0x72C0) {
> + I("FW reload done");
> + break;
> + }
> + I("wait FW reload %d times", retry);
> + g_core_fp.fp_read_FW_status(ts);
> + usleep_range(10000, 11000);
> + }
> + }
> +
> +BURN_OVL_FAIL:
> +ALOC_CFG_BUF_FAIL:
> + return ret;
> +}
> +
> +int himax_zf_part_info(const struct firmware *fw, struct himax_ts_data *ts,
> + int type)
> +{
> + u32 table_addr = FLASH_VER_GET_VAL(addr_cfg_table);
> + int pnum = 0;
> + int ret = 0;
> + u8 buf[16];
> + struct zf_info *info;
> + u8 sram_min[4];
> + int cfg_sz = 0;
> + int cfg_crc_sw = 0;
> + int cfg_crc_hw = 0;
> + s32 i = 0;
> + int i_max = 0;
> + int i_min = 0;
> + u32 dsram_base = 0xFFFFFFFF;
> + u32 dsram_max = 0;
> + int retry = 0;
> + int allovlidx = 0;
> + s32 alg_idx_t = 0;
> + s32 j = 0;
> + bool has_code_overlay = false;
> +
> + ts->has_alg_overlay = false;
> +
> + /* 1. initial check */
> + if (g_core_fp._en_hw_crc)
> + g_core_fp._en_hw_crc(ts, 1);
> + pnum = fw->data[table_addr + 12];
> + if (pnum < 2) {
> + E("partition number is not correct");
> + return FW_NOT_READY;
> + }
> +
> + info = kcalloc(pnum, sizeof(struct zf_info), GFP_KERNEL);
> + if (!info) {
> + E("memory allocation fail[info]!!");
> + return 1;
> + }
> + memset(info, 0, pnum * sizeof(struct zf_info));
> + if (!ts->ovl_idx) {
> + ts->ovl_idx = kcalloc(ovl_section_num, sizeof(u8), GFP_KERNEL);
> + if (!ts->ovl_idx) {
> + E("memory allocation fail[ovl_idx]!!");
> + ret = 1;
> + goto ALOC_CFG_BUF_FAIL;
> + }
> + }
> + memset(ts->ovl_idx, 0, ovl_section_num);
> +
> + /* 2. record partition information */
> + memcpy(buf, &fw->data[table_addr], 16);
> + memcpy(info[0].sram_addr, buf, 4);
> + info[0].write_size = le32_to_cpup((u32 *)&buf[4]);
> + info[0].fw_addr = le32_to_cpup((u32 *)&buf[8]);
> + I("[%d]SRAM addr=%08X, fw_addr=%08X, write_size=%d",
> + 0, info[0].cfg_addr, info[0].fw_addr,
> + info[0].write_size);
> +
> + for (i = 1; i < pnum; i++) {
> + memcpy(buf, &fw->data[i * 0x10 + table_addr], 16);
> +
> + memcpy(info[i].sram_addr, buf, 4);
> + info[i].write_size = le32_to_cpup((u32 *)&buf[4]);
> + info[i].fw_addr = le32_to_cpup((u32 *)&buf[8]);
> + info[i].cfg_addr = le32_to_cpup((u32 *)&info[i].sram_addr[0]);
> +
> + if (info[i].cfg_addr % 4 != 0)
> + info[i].cfg_addr -= (info[i].cfg_addr % 4);
> +
> + I("[%d]SRAM addr=%08X, fw_addr=%08X, write_size=%d",
> + i, info[i].cfg_addr, info[i].fw_addr,
> + info[i].write_size);
> +
> + /* alg overlay section */
> + if ((buf[15] == 0x77 && buf[14] == 0x88)) {
> + I("find alg overlay section in index %d", i);
> + /* record index of alg overlay section */
> + allovlidx |= 1 << i;
> + alg_idx_t = i;
> + ts->has_alg_overlay = true;
> + continue;
> + }
> +
> + /* code overlay section */
> + if ((buf[15] == 0x55 && buf[14] == 0x66) ||
> + le32_to_cpup((u32 *)&buf[0]) == 0x20008CE0) {
> + I("find code overlay section in index %d", i);
> + has_code_overlay = true;
> + /* record index of code overlay section */
> + allovlidx |= 1 << i;
> + if (buf[15] == 0x55 && buf[14] == 0x66) {
> + /* current mechanism */
> + j = buf[13];
> + if (j < ovl_section_num)
> + ts->ovl_idx[j] = i;
> + } else {
> + /* previous mechanism */
> + if (j < ovl_section_num)
> + ts->ovl_idx[j++] = i;
> + }
> + continue;
> + }
> +
> + if (dsram_base > info[i].cfg_addr) {
> + dsram_base = info[i].cfg_addr;
> + i_min = i;
> + }
> + if (dsram_max < info[i].cfg_addr) {
> + dsram_max = info[i].cfg_addr;
> + i_max = i;
> + }
> + }
> +
> + /* 3. prepare data to update */
> + for (i = 0; i < ADDR_LEN_4; i++)
> + sram_min[i] = (info[i_min].cfg_addr >> (8 * i)) & 0xFF;
> +
> + D("dsram_max: %d, dsram_base: %d, write_size: %d",
> + dsram_max, dsram_base, info[i_max].write_size);
> + cfg_sz = (dsram_max - dsram_base) + info[i_max].write_size;
> + if (cfg_sz % 16 != 0)
> + cfg_sz = cfg_sz + 16 - (cfg_sz % 16);
> +
> + I("cfg_sz = %d!, dsram_base = %X, dsram_max = %X",
> + cfg_sz, dsram_base, dsram_max);
> + /* config size should be smaller than DSRAM size */
> + if (cfg_sz > ts->chip_max_dsram_size) {
> + E("config size error[%d, %d]!!",
> + cfg_sz, ts->chip_max_dsram_size);
> + ret = LENGTH_FAIL;
> + goto ALOC_CFG_BUF_FAIL;
> + }
> +
> + memset(ts->zf_update_cfg_buffer, 0x00,
> + ts->chip_max_dsram_size * sizeof(u8));
> +
> + for (i = 1; i < pnum; i++) {
> + /* overlay section */
> + if (allovlidx & (1 << i)) {
> + I("skip overlay section %d", i);
> + continue;
> + }
> +
> + memcpy(&ts->zf_update_cfg_buffer[info[i].cfg_addr - dsram_base],
> + &fw->data[info[i].fw_addr], info[i].write_size);
> + }
> +
> + /* 4. write to sram */
> + /* FW entity */
> + if (himax_sram_write_crc_check(ts, info[0].sram_addr,
> + &fw->data[info[0].fw_addr], info[0].write_size) != 0) {
> + E("HW CRC FAIL");
> + ret = 2;
> + goto BURN_SRAM_FAIL;
> + }
> +
> + cfg_crc_sw = g_core_fp.fp_calculate_crc_with_ap(ts->zf_update_cfg_buffer,
> + 0, cfg_sz);
> + do {
> + g_core_fp.fp_write_sram_0f(ts, sram_min, ts->zf_update_cfg_buffer,
> + cfg_sz);
> + cfg_crc_hw = g_core_fp.fp_check_crc(ts, sram_min, cfg_sz);
> + if (cfg_crc_hw != cfg_crc_sw) {
> + E("Cfg CRC FAIL,HWCRC=%X,SWCRC=%X,retry=%d",
> + cfg_crc_hw, cfg_crc_sw, retry);
> + }
> + } while (cfg_crc_hw != cfg_crc_sw && retry++ < 3);
> +
> + if (retry > 3) {
> + ret = 2;
> + goto BURN_SRAM_FAIL;
> + }
> +
> + /*write back system config*/
> + if (type == 0)
> + g_core_fp.fp_resend_cmd_func(ts, ts->suspended);
> +
> + if (ts->has_alg_overlay)
> + ret = alg_overlay(ts, alg_idx_t, info, fw);
> + if (has_code_overlay)
> + ret = code_overlay(info, fw, ts, type);
> +
> +BURN_SRAM_FAIL:
> +ALOC_CFG_BUF_FAIL:
> + kfree(info);
> +
> + return ret;
> +/* ret = 1, memory allocation fail
> + * = 2, crc fail
> + * = 3, flow control error
> + */
> +}
> +
> +int himax_mcu_firmware_update_0f(const struct firmware *fw,
> + struct himax_ts_data *ts, int type)
> +{
> + int ret = 0;
> + bool bret;
> +
> + I("Entering - total FW size=%d", (int)fw->size);
> +
> + g_core_fp.fp_register_write(ts, ZF_GET_ARRAY(addr_system_reset),
> + ZF_GET_ARRAY(data_system_reset), 4);
> +
> + bret = g_core_fp.fp_sense_off(ts, false);
> + if (!bret) {
> + E("sense off fail");
> + return -1;
> + }
> +
> + if ((int)fw->size > HX64K) {
> + ret = himax_zf_part_info(fw, ts, type);
> + } else {
> + /* first 48K */
> + ret = himax_sram_write_crc_check
> + (ts, ZF_GET_ARRAY(data_sram_start_addr), &fw->data[0], HX_48K_SZ);
> + if (ret != 0)
> + E("HW CRC FAIL - Main SRAM 48K");
> +
> + /*config info*/
> + if (!ts->ic_data->has_flash) {
> + ret = himax_sram_write_crc_check(ts, ZF_GET_ARRAY(data_cfg_info),
> + &fw->data[0xc000], 128);
> + if (ret != 0)
> + E("Config info CRC Fail!");
> + } else {
> + g_core_fp.fp_clean_sram_0f(ts, ZF_GET_ARRAY(data_cfg_info),
> + 128, 2);
> + }
> +
> + if (!ts->ic_data->has_flash) {
> + ret = himax_sram_write_crc_check(ts, ZF_GET_ARRAY(data_fw_cfg_1),
> + &fw->data[0xc0fe], 528);
> + if (ret != 0)
> + E("FW config 1 CRC Fail!");
> + } else {
> + g_core_fp.fp_clean_sram_0f(ts, ZF_GET_ARRAY(data_fw_cfg_1),
> + 528, 1);
> + }
> +
> + if (!ts->ic_data->has_flash) {
> + ret = himax_sram_write_crc_check(ts, ZF_GET_ARRAY(data_fw_cfg_3),
> + &fw->data[0xca00], 128);
> + if (ret != 0)
> + E("FW config 3 CRC Fail!");
> + } else {
> + g_core_fp.fp_clean_sram_0f(ts, ZF_GET_ARRAY(data_fw_cfg_3),
> + 128, 2);
> + }
> +
> + /*ADC config*/
> + if (!ts->ic_data->has_flash) {
> + ret = himax_sram_write_crc_check(ts, ZF_GET_ARRAY(data_adc_cfg_1),
> + &fw->data[0xd640], 1200);
> + if (ret != 0)
> + E("ADC config 1 CRC Fail!");
> + } else {
> + g_core_fp.fp_clean_sram_0f(ts, ZF_GET_ARRAY(data_adc_cfg_1),
> + 1200, 2);
> + }
> +
> + if (!ts->ic_data->has_flash) {
> + ret = himax_sram_write_crc_check(ts, ZF_GET_ARRAY(data_adc_cfg_2),
> + &fw->data[0xd320], 800);
> + if (ret != 0)
> + E("ADC config 2 CRC Fail!");
> + } else {
> + g_core_fp.fp_clean_sram_0f(ts, ZF_GET_ARRAY(data_adc_cfg_2),
> + 800, 2);
> + }
> +
> + /*mapping table*/
> + if (!ts->ic_data->has_flash) {
> + ret = himax_sram_write_crc_check(ts, ZF_GET_ARRAY(data_map_table),
> + &fw->data[0xe000], 1536);
> + if (ret != 0)
> + E("Mapping table CRC Fail!");
> + } else {
> + g_core_fp.fp_clean_sram_0f(ts, ZF_GET_ARRAY(data_map_table),
> + 1536, 2);
> + }
> + }
> +
> + I("End");
> +
> + return ret;
> +}
> +
> +int hx_0f_op_file_dirly(char *file_name, struct himax_ts_data *ts)
> +{
> + const struct firmware *fw = NULL;
> + int reqret = -1;
> + int ret = -1;
> + int type = 0; /* FW type: 0, normal; 1, MPAP */
> +
> + if (ts->zf_update_flag) {
> + W("Other thread is updating now!");
> + return ret;
> + }
> + ts->zf_update_flag = true;
> + I("Preparing to update %s!", file_name);
> +
> + reqret = request_firmware(&fw, file_name, ts->dev);
> + if (reqret < 0) {
> + ret = reqret;
> + E("request firmware fail, code[%d]!!", ret);
> + goto END;
> + }
> +
> + if (strcmp(file_name, MPAP_FWNAME) == 0)
> + type = 1;
> +
> + ret = g_core_fp.fp_firmware_update_0f(fw, ts, type);
> +
> + if (reqret >= 0)
> + release_firmware(fw);
> +
> + if (ret < 0)
> + goto END;
> +
> + if (!ts->has_alg_overlay) {
> + if (type == 1)
> + g_core_fp.fp_turn_on_mp_func(ts, 1);
> + else
> + g_core_fp.fp_turn_on_mp_func(ts, 0);
> + g_core_fp.fp_reload_disable(ts, 0);
> + g_core_fp.fp_power_on_init(ts);
> + }
> +
> +END:
> + ts->zf_update_flag = false;
> +
> + I("END");
> + return ret;
> +}
> +
> +static int himax_mcu_0f_excp_check(void)
> +{
> + return NO_ERR;
> +}
> +
> +void himax_mcu_read_sram_0f(struct himax_ts_data *ts,
> + const struct firmware *fw_entry,
> + u8 *addr, int start_index, int read_len)
> +{
> + int total_read_times = 0;
> + int max_bus_size = MAX_I2C_TRANS_SZ;
> + int total_size_temp = 0;
> + int total_size = 0;
> + int address = 0;
> + int i = 0, j = 0;
> + int not_same = 0;
> + struct hx_reg_t in_addr = { .data = {0}, .len = 4 };
> + struct hx_reg_t tmp_addr = { .data = {0}, .len = 4 };
> + u8 *temp_info_data = NULL;
> + int *not_same_buff = NULL;
> +
> + I("Entering");
> + PTR_SET(in_addr, addr, 4);
> + total_size = read_len;
> + total_size_temp = read_len;
> +
> + if (read_len > 2048)
> + max_bus_size = 2048;
> + else
> + max_bus_size = read_len;
> +
> + if (total_size % max_bus_size == 0)
> + total_read_times = total_size / max_bus_size;
> + else
> + total_read_times = total_size / max_bus_size + 1;
> +
> + I("total size=%d, bus size=%d, read time=%d",
> + total_size, max_bus_size, total_read_times);
> +
> + memcpy(REG_GET_ARRAY(tmp_addr), addr, 4);
> + I("addr[3]=0x%2X,addr[2]=0x%2X,addr[1]=0x%2X,addr[0]=0x%2X",
> + REG_GET_ARRAY(tmp_addr)[3], REG_GET_ARRAY(tmp_addr)[2],
> + REG_GET_ARRAY(tmp_addr)[1], REG_GET_ARRAY(tmp_addr)[0]);
> +
> + temp_info_data = kcalloc(total_size, sizeof(u8), GFP_KERNEL);
> + if (!temp_info_data) {
> + E("Failed to allocate temp_info_data");
> + goto err_malloc_temp_info_data;
> + }
> +
> + not_same_buff = kcalloc(total_size, sizeof(int), GFP_KERNEL);
> + if (!not_same_buff) {
> + E("Failed to allocate not_same_buff");
> + goto err_malloc_not_same_buff;
> + }
> +
> + for (i = 0; i < (total_read_times); i++) {
> + if (total_size_temp >= max_bus_size) {
> + g_core_fp.fp_register_read(ts, REG_GET_ARRAY(tmp_addr),
> + &temp_info_data[i * max_bus_size], max_bus_size);
> + total_size_temp = total_size_temp - max_bus_size;
> + } else {
> + g_core_fp.fp_register_read(ts, REG_GET_ARRAY(tmp_addr),
> + &temp_info_data[i * max_bus_size],
> + total_size_temp % max_bus_size);
> + }
> +
> + address = ((i + 1) * max_bus_size);
> + WORD_REG(tmp_addr, address + REG_GET_VAL(in_addr));
> + }
> + I("READ Start, start_index = %d", start_index);
> +
> + j = start_index;
> + for (i = 0; i < read_len; i++, j++) {
> + if (fw_entry->data[j] != temp_info_data[i]) {
> + not_same++;
> + not_same_buff[i] = 1;
> + }
> +
> + I("0x%2.2X, ", temp_info_data[i]);
> +
> + if (i > 0 && i % 16 == 15)
> + pr_info("\n");
> + }
> + I("READ END,Not Same count=%d", not_same);
> +
> + if (not_same != 0) {
> + j = start_index;
> + for (i = 0; i < read_len; i++, j++) {
> + if (not_same_buff[i] == 1)
> + I("bin=[%d] 0x%2.2X", i, fw_entry->data[j]);
> + }
> + for (i = 0; i < read_len; i++, j++) {
> + if (not_same_buff[i] == 1)
> + I("sram=[%d] 0x%2.2X", i, temp_info_data[i]);
> + }
> + }
> + I("READ END, Not Same count=%d", not_same);
> +
> + kfree(not_same_buff);
> +err_malloc_not_same_buff:
> + kfree(temp_info_data);
> +err_malloc_temp_info_data:
> + return;
> +}
> +
> +void himax_mcu_read_all_sram(struct himax_ts_data *ts, u8 *addr,
> + int read_len)
> +{
> + int total_read_times = 0;
> + int max_bus_size = MAX_I2C_TRANS_SZ;
> + int total_size_temp = 0;
> + int total_size = 0;
> + int address = 0;
> + int i = 0;
> + struct hx_reg_t tmp_addr = { .data = {0}, .len = 4 };
> + u8 *temp_info_data;
> +
> + I("Entering");
> +
> + total_size = read_len;
> + total_size_temp = read_len;
> +
> + if (total_size % max_bus_size == 0)
> + total_read_times = total_size / max_bus_size;
> + else
> + total_read_times = total_size / max_bus_size + 1;
> +
> + I("total size=%d", total_size);
> +
> + PTR_SET(tmp_addr, addr, 4);
> + I("addr[3]=0x%2X,addr[2]=0x%2X,addr[1]=0x%2X,addr[0]=0x%2X",
> + REG_GET_ARRAY(tmp_addr)[3], REG_GET_ARRAY(tmp_addr)[2],
> + REG_GET_ARRAY(tmp_addr)[1], REG_GET_ARRAY(tmp_addr)[0]);
> +
> + temp_info_data = kcalloc(total_size, sizeof(u8), GFP_KERNEL);
> + if (!temp_info_data) {
> + E("Failed to allocate temp_info_data");
> + return;
> + }
> +
> + for (i = 0; i < (total_read_times); i++) {
> + if (total_size_temp >= max_bus_size) {
> + g_core_fp.fp_register_read(ts, REG_GET_ARRAY(tmp_addr),
> + &temp_info_data[i * max_bus_size], max_bus_size);
> + total_size_temp = total_size_temp - max_bus_size;
> + } else {
> + g_core_fp.fp_register_read(ts, REG_GET_ARRAY(tmp_addr),
> + &temp_info_data[i * max_bus_size],
> + total_size_temp % max_bus_size);
> + }
> +
> + address = ((i + 1) * max_bus_size);
> + WORD_REG(tmp_addr, address + REG_GET_VAL(tmp_addr));
> + }
> + I("addr[3]=0x%2X,addr[2]=0x%2X,addr[1]=0x%2X,addr[0]=0x%2X",
> + REG_GET_ARRAY(tmp_addr)[3], REG_GET_ARRAY(tmp_addr)[2],
> + REG_GET_ARRAY(tmp_addr)[1], REG_GET_ARRAY(tmp_addr)[0]);
> +
> + kfree(temp_info_data);
> +
> + I("END");
> +}
> +
> +void himax_mcu_firmware_read_0f(struct himax_ts_data *ts,
> + const struct firmware *fw_entry, int type)
> +{
> + u8 tmp_addr[4];
> +
> + I("Entering");
> + if (type == 0) { /* first 48K */
> + g_core_fp.fp_read_sram_0f(ts, fw_entry,
> + ZF_GET_ARRAY(data_sram_start_addr),
> + 0,
> + HX_48K_SZ);
> + g_core_fp.fp_read_all_sram(ts, tmp_addr, 0xC000);
> + } else { /*last 16k*/
> + g_core_fp.fp_read_sram_0f(ts, fw_entry, ZF_GET_ARRAY(data_cfg_info),
> + 0xC000, 132);
> +
> + /*FW config*/
> + g_core_fp.fp_read_sram_0f(ts, fw_entry, ZF_GET_ARRAY(data_fw_cfg_1),
> + 0xC0FE, 484);
> + g_core_fp.fp_read_sram_0f(ts, fw_entry, ZF_GET_ARRAY(data_fw_cfg_2),
> + 0xC9DE, 36);
> + g_core_fp.fp_read_sram_0f(ts, fw_entry, ZF_GET_ARRAY(data_fw_cfg_3),
> + 0xCA00, 72);
> +
> + /*ADC config*/
> +
> + g_core_fp.fp_read_sram_0f(ts, fw_entry, ZF_GET_ARRAY(data_adc_cfg_1),
> + 0xD630, 1188);
> + g_core_fp.fp_read_sram_0f(ts, fw_entry, ZF_GET_ARRAY(data_adc_cfg_2),
> + 0xD318, 792);
> +
> + /*mapping table*/
> + g_core_fp.fp_read_sram_0f(ts, fw_entry, ZF_GET_ARRAY(data_map_table),
> + 0xE000, 1536);
> +
> + /* set n frame=0*/
> + g_core_fp.fp_read_sram_0f(ts, fw_entry,
> + FW_GET_ARRAY(addr_set_frame_addr), 0xC30C, 4);
> + }
> +
> + I("END");
> +}
> +
> +void himax_ic_reg_init(struct himax_core_command_regs *reg_data)
> +{
> + I("Entering!");
> +/* CORE_IC -start- */
> + BYTE_REG(reg_data->ic_op.addr_ahb_addr_byte_0, ic_adr_ahb_addr_byte_0);
> + BYTE_REG(reg_data->ic_op.addr_ahb_rdata_byte_0, ic_adr_ahb_rdata_byte_0);
> + BYTE_REG(reg_data->ic_op.addr_ahb_access_direction, ic_adr_ahb_access_direction);
> + BYTE_REG(reg_data->ic_op.addr_conti, ic_adr_conti);
> + BYTE_REG(reg_data->ic_op.addr_incr4, ic_adr_incr4);
> + BYTE_REG(reg_data->ic_op.adr_i2c_psw_lb, ic_adr_i2c_psw_lb);
> + BYTE_REG(reg_data->ic_op.adr_i2c_psw_ub, ic_adr_i2c_psw_ub);
> + BYTE_REG(reg_data->ic_op.data_ahb_access_direction_read, ic_cmd_ahb_access_direction_read);
> + BYTE_REG(reg_data->ic_op.data_conti, ic_cmd_conti);
> + BYTE_REG(reg_data->ic_op.data_incr4, ic_cmd_incr4);
> + BYTE_REG(reg_data->ic_op.data_i2c_psw_lb, ic_cmd_i2c_psw_lb);
> + BYTE_REG(reg_data->ic_op.data_i2c_psw_ub, ic_cmd_i2c_psw_ub);
> + WORD_REG(reg_data->ic_op.addr_tcon_on_rst, ic_adr_tcon_on_rst);
> + WORD_REG(reg_data->ic_op.addr_adc_on_rst, ic_addr_adc_on_rst);
> + WORD_REG(reg_data->ic_op.addr_psl, ic_adr_psl);
> + WORD_REG(reg_data->ic_op.addr_cs_central_state, ic_adr_cs_central_state);
> + WORD_REG(reg_data->ic_op.data_rst, ic_cmd_rst);
> + WORD_REG(reg_data->ic_op.adr_osc_en, ic_adr_osc_en);
> + WORD_REG(reg_data->ic_op.adr_osc_pw, ic_adr_osc_pw);
> +/* CORE_IC -end- */
> +/* CORE_FW -start- */
> + WORD_REG(reg_data->fw_op.addr_system_reset, fw_addr_system_reset);
> + WORD_REG(reg_data->fw_op.addr_ctrl_fw_isr, fw_addr_ctrl_fw);
> + WORD_REG(reg_data->fw_op.addr_flag_reset_event, fw_addr_flag_reset_event);
> + WORD_REG(reg_data->fw_op.addr_hsen_enable, fw_addr_hsen_enable);
> + WORD_REG(reg_data->fw_op.addr_program_reload_from,
> + fw_addr_program_reload_from);
> + WORD_REG(reg_data->fw_op.addr_program_reload_to,
> + fw_addr_program_reload_to);
> + WORD_REG(reg_data->fw_op.addr_program_reload_page_write,
> + fw_addr_program_reload_page_write);
> + WORD_REG(reg_data->fw_op.addr_raw_out_sel, fw_addr_raw_out_sel);
> + WORD_REG(reg_data->fw_op.addr_reload_status, fw_addr_reload_status);
> + WORD_REG(reg_data->fw_op.addr_reload_crc32_result,
> + fw_addr_reload_crc32_result);
> + WORD_REG(reg_data->fw_op.addr_reload_addr_from, fw_addr_reload_addr_from);
> + WORD_REG(reg_data->fw_op.addr_reload_addr_cmd_beat,
> + fw_addr_reload_addr_cmd_beat);
> + WORD_REG(reg_data->fw_op.addr_selftest_addr_en, fw_addr_selftest_addr_en);
> + WORD_REG(reg_data->fw_op.addr_criteria_addr, fw_addr_criteria_addr);
> + WORD_REG(reg_data->fw_op.addr_set_frame_addr, fw_addr_set_frame_addr);
> + WORD_REG(reg_data->fw_op.addr_selftest_result_addr,
> + fw_addr_selftest_result_addr);
> + WORD_REG(reg_data->fw_op.addr_sorting_mode_en, fw_addr_sorting_mode_en);
> + WORD_REG(reg_data->fw_op.addr_fw_mode_status, fw_addr_fw_mode_status);
> + WORD_REG(reg_data->fw_op.addr_icid_addr, fw_addr_icid_addr);
> + WORD_REG(reg_data->fw_op.addr_fw_ver_addr, fw_addr_fw_ver_addr);
> + WORD_REG(reg_data->fw_op.addr_fw_cfg_addr, fw_addr_fw_cfg_addr);
> + WORD_REG(reg_data->fw_op.addr_fw_vendor_addr, fw_addr_fw_vendor_addr);
> + WORD_REG(reg_data->fw_op.addr_cus_info, fw_addr_cus_info);
> + WORD_REG(reg_data->fw_op.addr_proj_info, fw_addr_proj_info);
> + WORD_REG(reg_data->fw_op.addr_fw_state_addr, fw_addr_fw_state_addr);
> + WORD_REG(reg_data->fw_op.addr_fw_dbg_msg_addr, fw_addr_fw_dbg_msg_addr);
> + WORD_REG(reg_data->fw_op.addr_chk_fw_status, fw_addr_chk_fw_status);
> + WORD_REG(reg_data->fw_op.addr_dd_handshak_addr, fw_addr_dd_handshak_addr);
> + WORD_REG(reg_data->fw_op.addr_dd_data_addr, fw_addr_dd_data_addr);
> + WORD_REG(reg_data->fw_op.addr_clr_fw_record_dd_sts,
> + fw_addr_clr_fw_record_dd_sts);
> + WORD_REG(reg_data->fw_op.addr_ap_notify_fw_sus, fw_addr_ap_notify_fw_sus);
> + WORD_REG(reg_data->fw_op.data_ap_notify_fw_sus_en,
> + fw_data_ap_notify_fw_sus_en);
> + WORD_REG(reg_data->fw_op.data_ap_notify_fw_sus_dis,
> + fw_data_ap_notify_fw_sus_dis);
> + WORD_REG(reg_data->fw_op.data_system_reset, fw_data_system_reset);
> + WORD_REG(reg_data->fw_op.data_safe_mode_release_pw_active,
> + fw_data_safe_mode_release_pw_active);
> + WORD_REG(reg_data->fw_op.data_safe_mode_release_pw_reset,
> + fw_data_safe_mode_release_pw_reset);
> + WORD_REG(reg_data->fw_op.data_clear, fw_data_clear);
> + WORD_REG(reg_data->fw_op.data_fw_stop, fw_data_fw_stop);
> + WORD_REG(reg_data->fw_op.data_program_reload_start,
> + fw_data_program_reload_start);
> + WORD_REG(reg_data->fw_op.data_program_reload_compare,
> + fw_data_program_reload_compare);
> + WORD_REG(reg_data->fw_op.data_program_reload_break,
> + fw_data_program_reload_break);
> + WORD_REG(reg_data->fw_op.data_selftest_request, fw_data_selftest_request);
> + BYTE_REG(reg_data->fw_op.data_criteria_aa_top, fw_data_criteria_aa_top);
> + BYTE_REG(reg_data->fw_op.data_criteria_aa_bot, fw_data_criteria_aa_bot);
> + BYTE_REG(reg_data->fw_op.data_criteria_key_top, fw_data_criteria_key_top);
> + BYTE_REG(reg_data->fw_op.data_criteria_key_bot, fw_data_criteria_key_bot);
> + BYTE_REG(reg_data->fw_op.data_criteria_avg_top, fw_data_criteria_avg_top);
> + BYTE_REG(reg_data->fw_op.data_criteria_avg_bot, fw_data_criteria_avg_bot);
> + WORD_REG(reg_data->fw_op.data_set_frame, fw_data_set_frame);
> + BYTE_REG(reg_data->fw_op.data_selftest_ack_hb, fw_data_selftest_ack_hb);
> + BYTE_REG(reg_data->fw_op.data_selftest_ack_lb, fw_data_selftest_ack_lb);
> + BYTE_REG(reg_data->fw_op.data_selftest_pass, fw_data_selftest_pass);
> + BYTE_REG(reg_data->fw_op.data_normal_cmd, fw_data_normal_cmd);
> + BYTE_REG(reg_data->fw_op.data_normal_status, fw_data_normal_status);
> + BYTE_REG(reg_data->fw_op.data_sorting_cmd, fw_data_sorting_cmd);
> + BYTE_REG(reg_data->fw_op.data_sorting_status, fw_data_sorting_status);
> + BYTE_REG(reg_data->fw_op.data_dd_request, fw_data_dd_request);
> + BYTE_REG(reg_data->fw_op.data_dd_ack, fw_data_dd_ack);
> + BYTE_REG(reg_data->fw_op.data_idle_dis_pwd, fw_data_idle_dis_pwd);
> + BYTE_REG(reg_data->fw_op.data_idle_en_pwd, fw_data_idle_en_pwd);
> + BYTE_REG(reg_data->fw_op.data_rawdata_ready_hb, fw_data_rawdata_ready_hb);
> + BYTE_REG(reg_data->fw_op.data_rawdata_ready_lb, fw_data_rawdata_ready_lb);
> + BYTE_REG(reg_data->fw_op.addr_ahb_addr, fw_addr_ahb_addr);
> + BYTE_REG(reg_data->fw_op.data_ahb_dis, fw_data_ahb_dis);
> + BYTE_REG(reg_data->fw_op.data_ahb_en, fw_data_ahb_en);
> + BYTE_REG(reg_data->fw_op.addr_event_addr, fw_addr_event_addr);
> + WORD_REG(reg_data->fw_op.addr_usb_detect, fw_usb_detect_addr);
> +/* CORE_FW -end- */
> +/* CORE_FLASH -start- */
> + WORD_REG(reg_data->flash_op.addr_spi200_trans_fmt,
> + flash_addr_spi200_trans_fmt);
> + WORD_REG(reg_data->flash_op.addr_spi200_trans_ctrl,
> + flash_addr_spi200_trans_ctrl);
> + WORD_REG(reg_data->flash_op.addr_spi200_fifo_rst,
> + flash_addr_spi200_fifo_rst);
> + WORD_REG(reg_data->flash_op.addr_spi200_flash_speed,
> + flash_addr_spi200_flash_speed);
> + WORD_REG(reg_data->flash_op.addr_spi200_rst_status,
> + flash_addr_spi200_rst_status);
> + WORD_REG(reg_data->flash_op.addr_spi200_cmd, flash_addr_spi200_cmd);
> + WORD_REG(reg_data->flash_op.addr_spi200_addr, flash_addr_spi200_addr);
> + WORD_REG(reg_data->flash_op.addr_spi200_data, flash_addr_spi200_data);
> + WORD_REG(reg_data->flash_op.addr_spi200_bt_num, flash_addr_spi200_bt_num);
> + WORD_REG(reg_data->flash_op.data_spi200_trans_fmt,
> + flash_data_spi200_trans_fmt);
> + WORD_REG(reg_data->flash_op.data_spi200_txfifo_rst,
> + flash_data_spi200_txfifo_rst);
> + WORD_REG(reg_data->flash_op.data_spi200_rxfifo_rst,
> + flash_data_spi200_rxfifo_rst);
> + WORD_REG(reg_data->flash_op.data_spi200_trans_ctrl_1,
> + flash_data_spi200_trans_ctrl_1);
> + WORD_REG(reg_data->flash_op.data_spi200_trans_ctrl_2,
> + flash_data_spi200_trans_ctrl_2);
> + WORD_REG(reg_data->flash_op.data_spi200_trans_ctrl_3,
> + flash_data_spi200_trans_ctrl_3);
> + WORD_REG(reg_data->flash_op.data_spi200_trans_ctrl_4,
> + flash_data_spi200_trans_ctrl_4);
> + WORD_REG(reg_data->flash_op.data_spi200_trans_ctrl_5,
> + flash_data_spi200_trans_ctrl_5);
> + WORD_REG(reg_data->flash_op.data_spi200_trans_ctrl_6,
> + flash_data_spi200_trans_ctrl_6);
> + WORD_REG(reg_data->flash_op.data_spi200_trans_ctrl_7,
> + flash_data_spi200_trans_ctrl_7);
> + WORD_REG(reg_data->flash_op.data_spi200_cmd_1, flash_data_spi200_cmd_1);
> + WORD_REG(reg_data->flash_op.data_spi200_cmd_2, flash_data_spi200_cmd_2);
> + WORD_REG(reg_data->flash_op.data_spi200_cmd_3, flash_data_spi200_cmd_3);
> + WORD_REG(reg_data->flash_op.data_spi200_cmd_4, flash_data_spi200_cmd_4);
> + WORD_REG(reg_data->flash_op.data_spi200_cmd_5, flash_data_spi200_cmd_5);
> + WORD_REG(reg_data->flash_op.data_spi200_cmd_6, flash_data_spi200_cmd_6);
> + WORD_REG(reg_data->flash_op.data_spi200_cmd_7, flash_data_spi200_cmd_7);
> + WORD_REG(reg_data->flash_op.data_spi200_cmd_8, flash_data_spi200_cmd_8);
> + WORD_REG(reg_data->flash_op.data_spi200_addr, flash_data_spi200_addr);
> +/* CORE_FLASH -end- */
> +/* CORE_SRAM */
> + /* sram start*/
> + WORD_REG(reg_data->sram_op.addr_mkey, sram_adr_mkey);
> + WORD_REG(reg_data->sram_op.addr_rawdata_addr, sram_adr_rawdata_addr);
> + WORD_REG(reg_data->sram_op.addr_rawdata_end, sram_adr_rawdata_end);
> + HALF_REG(reg_data->sram_op.passwrd_start, sram_passwrd_start);
> + HALF_REG(reg_data->sram_op.passwrd_end, sram_passwrd_end);
> + /* sram end*/
> +/* CORE_SRAM */
> +/* CORE_DRIVER -start- */
> + WORD_REG(reg_data->driver_op.addr_fw_define_flash_reload,
> + driver_addr_fw_define_flash_reload);
> + WORD_REG(reg_data->driver_op.addr_fw_define_2nd_flash_reload,
> + driver_addr_fw_define_2nd_flash_reload);
> + WORD_REG(reg_data->driver_op.addr_fw_define_int_is_edge,
> + driver_addr_fw_define_int_is_edge);
> + WORD_REG(reg_data->driver_op.addr_fw_define_rxnum_txnum,
> + driver_addr_fw_define_rxnum_txnum);
> + WORD_REG(reg_data->driver_op.addr_fw_define_maxpt_xyrvs,
> + driver_addr_fw_define_maxpt_xyrvs);
> + WORD_REG(reg_data->driver_op.addr_fw_define_x_y_res,
> + driver_addr_fw_define_x_y_res);
> + BYTE_REG(reg_data->driver_op.data_df_rx, driver_data_df_rx);
> + BYTE_REG(reg_data->driver_op.data_df_tx, driver_data_df_tx);
> + BYTE_REG(reg_data->driver_op.data_df_pt, driver_data_df_pt);
> + WORD_REG(reg_data->driver_op.data_fw_define_flash_reload_dis,
> + driver_data_fw_define_flash_reload_dis);
> + WORD_REG(reg_data->driver_op.data_fw_define_flash_reload_en,
> + driver_data_fw_define_flash_reload_en);
> + WORD_REG(reg_data->driver_op.data_fw_define_rxnum_txnum_maxpt_sorting,
> + driver_data_fw_define_rxnum_txnum_maxpt_sorting);
> + WORD_REG(reg_data->driver_op.data_fw_define_rxnum_txnum_maxpt_normal,
> + driver_data_fw_define_rxnum_txnum_maxpt_normal);
> +/* CORE_DRIVER -end- */
> + WORD_REG(reg_data->zf_op.data_dis_flash_reload, zf_data_dis_flash_reload);
> + WORD_REG(reg_data->zf_op.addr_system_reset, zf_addr_system_reset);
> + BYTE_REG(reg_data->zf_op.data_system_reset, zf_data_system_reset);
> + WORD_REG(reg_data->zf_op.data_sram_start_addr, zf_data_sram_start_addr);
> + WORD_REG(reg_data->zf_op.data_cfg_info, zf_data_cfg_info);
> + WORD_REG(reg_data->zf_op.data_fw_cfg_1, zf_data_fw_cfg_1);
> + WORD_REG(reg_data->zf_op.data_fw_cfg_2, zf_data_fw_cfg_2);
> + WORD_REG(reg_data->zf_op.data_fw_cfg_3, zf_data_fw_cfg_3);
> + WORD_REG(reg_data->zf_op.data_adc_cfg_1, zf_data_adc_cfg_1);
> + WORD_REG(reg_data->zf_op.data_adc_cfg_2, zf_data_adc_cfg_2);
> + WORD_REG(reg_data->zf_op.data_adc_cfg_3, zf_data_adc_cfg_3);
> + WORD_REG(reg_data->zf_op.data_map_table, zf_data_map_table);
> + WORD_REG(reg_data->zf_op.addr_sts_chk, zf_addr_sts_chk);
> + BYTE_REG(reg_data->zf_op.data_activ_sts, zf_data_activ_sts);
> + WORD_REG(reg_data->zf_op.addr_activ_relod, zf_addr_activ_relod);
> + BYTE_REG(reg_data->zf_op.data_activ_in, zf_data_activ_in);
> +}
> +
> +/* CORE_INIT */
> +/* init start */
> +void himax_ic_fp_init(void)
> +{
> +/* CORE_IC */
> + g_core_fp.fp_burst_enable = himax_mcu_burst_enable;
> + g_core_fp.fp_register_read = himax_mcu_register_read;
> + g_core_fp.fp_reg_read = himax_mcu_reg_read;
> + /*
> + * g_core_fp.fp_flash_write_burst = himax_mcu_flash_write_burst;
> + */
> + /*
> + * g_core_fp.fp_flash_write_burst_length =
> + * himax_mcu_flash_write_burst_length;
> + */
> + g_core_fp.fp_register_write = himax_mcu_register_write;
> + g_core_fp.fp_reg_write = himax_mcu_reg_write;
> + g_core_fp.fp_interface_on = himax_mcu_interface_on;
> + g_core_fp.fp_sense_on = himax_mcu_sense_on;
> + g_core_fp.fp_sense_off = himax_mcu_sense_off;
> + g_core_fp.fp_wait_wip = himax_mcu_wait_wip;
> + g_core_fp.fp_init_psl = himax_mcu_init_psl;
> + g_core_fp.fp_resume_ic_action = himax_mcu_resume_ic_action;
> + g_core_fp.fp_suspend_ic_action = himax_mcu_suspend_ic_action;
> + g_core_fp.fp_power_on_init = himax_mcu_power_on_init;
> +/* CORE_IC */
> +/* CORE_FW */
> + g_core_fp.fp_system_reset = himax_mcu_system_reset;
> + g_core_fp.fp_calculate_crc_with_ap = himax_mcu_calculate_crc_with_ap;
> + g_core_fp.fp_check_crc = himax_mcu_check_crc;
> + g_core_fp.fp_set_reload_cmd = himax_mcu_set_reload_cmd;
> + g_core_fp.fp_program_reload = himax_mcu_program_reload;
> + g_core_fp.fp_usb_detect_set = himax_mcu_usb_detect_set;
> + g_core_fp.fp_diag_register_set = himax_mcu_diag_register_set;
> + g_core_fp.fp_diag_register_get = himax_mcu_diag_register_get;
> + g_core_fp.fp_idle_mode = himax_mcu_idle_mode;
> + g_core_fp.fp_reload_disable = himax_mcu_reload_disable;
> + g_core_fp.fp_read_ic_trigger_type = himax_mcu_read_ic_trigger_type;
> + g_core_fp.fp_read_FW_ver = himax_mcu_read_FW_ver;
> + g_core_fp.fp_read_event_stack = himax_mcu_read_event_stack;
> + g_core_fp.fp_return_event_stack = himax_mcu_return_event_stack;
> + g_core_fp.fp_calculate_checksum = himax_mcu_calculate_checksum;
> + g_core_fp.fp_read_FW_status = himax_mcu_read_FW_status;
> + g_core_fp.fp_irq_switch = himax_mcu_irq_switch;
> + g_core_fp.fp_assign_sorting_mode = himax_mcu_assign_sorting_mode;
> + g_core_fp.fp_check_sorting_mode = himax_mcu_check_sorting_mode;
> + g_core_fp.fp_read_DD_status = himax_mcu_read_DD_status;
> + g_core_fp.fp_clr_fw_reord_dd_sts = hx_clr_fw_reord_dd_sts;
> + g_core_fp.fp_ap_notify_fw_sus = hx_ap_notify_fw_sus;
> +/* CORE_FW */
> +/* CORE_FLASH */
> + g_core_fp.fp_chip_erase = himax_mcu_chip_erase;
> + g_core_fp.fp_block_erase = himax_mcu_block_erase;
> + g_core_fp.fp_sector_erase = himax_mcu_sector_erase;
> + g_core_fp.fp_flash_programming = himax_mcu_flash_programming;
> + g_core_fp.fp_flash_page_write = himax_mcu_flash_page_write;
> + g_core_fp.fp_fts_ctpm_fw_upgrade_with_sys_fs_32k =
> + himax_mcu_fts_ctpm_fw_upgrade_with_sys_fs_32k;
> + g_core_fp.fp_fts_ctpm_fw_upgrade_with_sys_fs_60k =
> + himax_mcu_fts_ctpm_fw_upgrade_with_sys_fs_60k;
> + g_core_fp.fp_fts_ctpm_fw_upgrade_with_sys_fs_64k =
> + himax_mcu_fts_ctpm_fw_upgrade_with_sys_fs_64k;
> + g_core_fp.fp_fts_ctpm_fw_upgrade_with_sys_fs_124k =
> + himax_mcu_fts_ctpm_fw_upgrade_with_sys_fs_124k;
> + g_core_fp.fp_fts_ctpm_fw_upgrade_with_sys_fs_128k =
> + himax_mcu_fts_ctpm_fw_upgrade_with_sys_fs_128k;
> + g_core_fp.fp_fts_ctpm_fw_upgrade_with_sys_fs_255k =
> + himax_mcu_fts_ctpm_fw_upgrade_with_sys_fs_255k;
> + g_core_fp.fp_flash_dump_func = himax_mcu_flash_dump_func;
> + g_core_fp.fp_flash_lastdata_check = himax_mcu_flash_lastdata_check;
> + g_core_fp.fp_bin_desc_get = hx_mcu_bin_desc_get;
> + g_core_fp.fp_diff_overlay_flash = hx_mcu_diff_overlay_flash;
> +/* CORE_FLASH */
> +/* CORE_SRAM */
> + g_core_fp.fp_sram_write = himax_mcu_sram_write;
> + g_core_fp.fp_sram_verify = himax_mcu_sram_verify;
> + g_core_fp.fp_get_DSRAM_data = himax_mcu_get_DSRAM_data;
> +/* CORE_SRAM */
> +/* CORE_DRIVER */
> + g_core_fp.fp_chip_init = himax_mcu_init_ic;
> + g_core_fp.fp_pin_reset = himax_mcu_pin_reset;
> + g_core_fp.fp_ic_reset = himax_mcu_ic_reset;
> + g_core_fp.fp_tp_info_check = himax_mcu_tp_info_check;
> + g_core_fp.fp_touch_information = himax_mcu_touch_information;
> + g_core_fp.fp_calc_touch_data_size = himax_mcu_calc_touch_data_size;
> + g_core_fp.fp_get_touch_data_size = himax_mcu_get_touch_data_size;
> + g_core_fp.fp_hand_shaking = himax_mcu_hand_shaking;
> + g_core_fp.fp_determin_diag_rawdata = himax_mcu_determin_diag_rawdata;
> + g_core_fp.fp_determin_diag_storage = himax_mcu_determin_diag_storage;
> + g_core_fp.fp_cal_data_len = himax_mcu_cal_data_len;
> + g_core_fp.fp_diag_check_sum = himax_mcu_diag_check_sum;
> + g_core_fp.fp_ic_excp_recovery = himax_mcu_ic_excp_recovery;
> + g_core_fp.fp_excp_ic_reset = himax_mcu_excp_ic_reset;
> + g_core_fp.fp_resend_cmd_func = himax_mcu_resend_cmd_func;
> +/* CORE_DRIVER */
> + g_core_fp.fp_turn_on_mp_func = hx_turn_on_mp_func;
> + g_core_fp.fp_reload_disable = hx_dis_rload_0f;
> + g_core_fp.fp_clean_sram_0f = himax_mcu_clean_sram_0f;
> + g_core_fp.fp_write_sram_0f = himax_mcu_write_sram_0f;
> + g_core_fp.fp_write_sram_0f_crc = himax_sram_write_crc_check;
> + g_core_fp.fp_firmware_update_0f = himax_mcu_firmware_update_0f;
> + g_core_fp.fp_0f_op_file_dirly = hx_0f_op_file_dirly;
> + g_core_fp.fp_0f_excp_check = himax_mcu_0f_excp_check;
> + g_core_fp.fp_read_sram_0f = himax_mcu_read_sram_0f;
> + g_core_fp.fp_read_all_sram = himax_mcu_read_all_sram;
> + g_core_fp.fp_firmware_read_0f = himax_mcu_firmware_read_0f;
> + g_core_fp.fp_suspend_proc = himax_suspend_proc;
> + g_core_fp.fp_resume_proc = himax_resume_proc;
> +}
> --
> 2.25.1
>