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

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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
> 




[Index of Archives]     [Device Tree Compilter]     [Device Tree Spec]     [Linux Driver Backports]     [Video for Linux]     [Linux USB Devel]     [Linux PCI Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [XFree86]     [Yosemite Backpacking]


  Powered by Linux