cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

wdt87xx_i2c.c (28596B)


      1/*
      2 * Weida HiTech WDT87xx TouchScreen I2C driver
      3 *
      4 * Copyright (c) 2015  Weida Hi-Tech Co., Ltd.
      5 * HN Chen <hn.chen@weidahitech.com>
      6 *
      7 * This software is licensed under the terms of the GNU General Public
      8 * License, as published by the Free Software Foundation, and
      9 * may be copied, distributed, and modified under those terms.
     10 */
     11
     12#include <linux/i2c.h>
     13#include <linux/input.h>
     14#include <linux/interrupt.h>
     15#include <linux/delay.h>
     16#include <linux/irq.h>
     17#include <linux/io.h>
     18#include <linux/module.h>
     19#include <linux/slab.h>
     20#include <linux/firmware.h>
     21#include <linux/input/mt.h>
     22#include <linux/acpi.h>
     23#include <asm/unaligned.h>
     24
     25#define WDT87XX_NAME		"wdt87xx_i2c"
     26#define WDT87XX_FW_NAME		"wdt87xx_fw.bin"
     27#define WDT87XX_CFG_NAME	"wdt87xx_cfg.bin"
     28
     29#define MODE_ACTIVE			0x01
     30#define MODE_READY			0x02
     31#define MODE_IDLE			0x03
     32#define MODE_SLEEP			0x04
     33#define MODE_STOP			0xFF
     34
     35#define WDT_MAX_FINGER			10
     36#define WDT_RAW_BUF_COUNT		54
     37#define WDT_V1_RAW_BUF_COUNT		74
     38#define WDT_FIRMWARE_ID			0xa9e368f5
     39
     40#define PG_SIZE				0x1000
     41#define MAX_RETRIES			3
     42
     43#define MAX_UNIT_AXIS			0x7FFF
     44
     45#define PKT_READ_SIZE			72
     46#define PKT_WRITE_SIZE			80
     47
     48/* the finger definition of the report event */
     49#define FINGER_EV_OFFSET_ID		0
     50#define FINGER_EV_OFFSET_X		1
     51#define FINGER_EV_OFFSET_Y		3
     52#define FINGER_EV_SIZE			5
     53
     54#define FINGER_EV_V1_OFFSET_ID		0
     55#define FINGER_EV_V1_OFFSET_W		1
     56#define FINGER_EV_V1_OFFSET_P		2
     57#define FINGER_EV_V1_OFFSET_X		3
     58#define FINGER_EV_V1_OFFSET_Y		5
     59#define FINGER_EV_V1_SIZE		7
     60
     61/* The definition of a report packet */
     62#define TOUCH_PK_OFFSET_REPORT_ID	0
     63#define TOUCH_PK_OFFSET_EVENT		1
     64#define TOUCH_PK_OFFSET_SCAN_TIME	51
     65#define TOUCH_PK_OFFSET_FNGR_NUM	53
     66
     67#define TOUCH_PK_V1_OFFSET_REPORT_ID	0
     68#define TOUCH_PK_V1_OFFSET_EVENT	1
     69#define TOUCH_PK_V1_OFFSET_SCAN_TIME	71
     70#define TOUCH_PK_V1_OFFSET_FNGR_NUM	73
     71
     72/* The definition of the controller parameters */
     73#define CTL_PARAM_OFFSET_FW_ID		0
     74#define CTL_PARAM_OFFSET_PLAT_ID	2
     75#define CTL_PARAM_OFFSET_XMLS_ID1	4
     76#define CTL_PARAM_OFFSET_XMLS_ID2	6
     77#define CTL_PARAM_OFFSET_PHY_CH_X	8
     78#define CTL_PARAM_OFFSET_PHY_CH_Y	10
     79#define CTL_PARAM_OFFSET_PHY_X0		12
     80#define CTL_PARAM_OFFSET_PHY_X1		14
     81#define CTL_PARAM_OFFSET_PHY_Y0		16
     82#define CTL_PARAM_OFFSET_PHY_Y1		18
     83#define CTL_PARAM_OFFSET_PHY_W		22
     84#define CTL_PARAM_OFFSET_PHY_H		24
     85#define CTL_PARAM_OFFSET_FACTOR		32
     86
     87/* The definition of the device descriptor */
     88#define WDT_GD_DEVICE			1
     89#define DEV_DESC_OFFSET_VID		8
     90#define DEV_DESC_OFFSET_PID		10
     91
     92/* Communication commands */
     93#define PACKET_SIZE			56
     94#define VND_REQ_READ			0x06
     95#define VND_READ_DATA			0x07
     96#define VND_REQ_WRITE			0x08
     97
     98#define VND_CMD_START			0x00
     99#define VND_CMD_STOP			0x01
    100#define VND_CMD_RESET			0x09
    101
    102#define VND_CMD_ERASE			0x1A
    103
    104#define VND_GET_CHECKSUM		0x66
    105
    106#define VND_SET_DATA			0x83
    107#define VND_SET_COMMAND_DATA		0x84
    108#define VND_SET_CHECKSUM_CALC		0x86
    109#define VND_SET_CHECKSUM_LENGTH		0x87
    110
    111#define VND_CMD_SFLCK			0xFC
    112#define VND_CMD_SFUNL			0xFD
    113
    114#define CMD_SFLCK_KEY			0xC39B
    115#define CMD_SFUNL_KEY			0x95DA
    116
    117#define STRIDX_PLATFORM_ID		0x80
    118#define STRIDX_PARAMETERS		0x81
    119
    120#define CMD_BUF_SIZE			8
    121#define PKT_BUF_SIZE			64
    122
    123/* The definition of the command packet */
    124#define CMD_REPORT_ID_OFFSET		0x0
    125#define CMD_TYPE_OFFSET			0x1
    126#define CMD_INDEX_OFFSET		0x2
    127#define CMD_KEY_OFFSET			0x3
    128#define CMD_LENGTH_OFFSET		0x4
    129#define CMD_DATA_OFFSET			0x8
    130
    131/* The definition of firmware chunk tags */
    132#define FOURCC_ID_RIFF			0x46464952
    133#define FOURCC_ID_WHIF			0x46494857
    134#define FOURCC_ID_FRMT			0x544D5246
    135#define FOURCC_ID_FRWR			0x52575246
    136#define FOURCC_ID_CNFG			0x47464E43
    137
    138#define CHUNK_ID_FRMT			FOURCC_ID_FRMT
    139#define CHUNK_ID_FRWR			FOURCC_ID_FRWR
    140#define CHUNK_ID_CNFG			FOURCC_ID_CNFG
    141
    142#define FW_FOURCC1_OFFSET		0
    143#define FW_SIZE_OFFSET			4
    144#define FW_FOURCC2_OFFSET		8
    145#define FW_PAYLOAD_OFFSET		40
    146
    147#define FW_CHUNK_ID_OFFSET		0
    148#define FW_CHUNK_SIZE_OFFSET		4
    149#define FW_CHUNK_TGT_START_OFFSET	8
    150#define FW_CHUNK_PAYLOAD_LEN_OFFSET	12
    151#define FW_CHUNK_SRC_START_OFFSET	16
    152#define FW_CHUNK_VERSION_OFFSET		20
    153#define FW_CHUNK_ATTR_OFFSET		24
    154#define FW_CHUNK_PAYLOAD_OFFSET		32
    155
    156/* Controller requires minimum 300us between commands */
    157#define WDT_COMMAND_DELAY_MS		2
    158#define WDT_FLASH_WRITE_DELAY_MS	4
    159#define WDT_FLASH_ERASE_DELAY_MS	200
    160#define WDT_FW_RESET_TIME		2500
    161
    162struct wdt87xx_sys_param {
    163	u16	fw_id;
    164	u16	plat_id;
    165	u16	xmls_id1;
    166	u16	xmls_id2;
    167	u16	phy_ch_x;
    168	u16	phy_ch_y;
    169	u16	phy_w;
    170	u16	phy_h;
    171	u16	scaling_factor;
    172	u32	max_x;
    173	u32	max_y;
    174	u16	vendor_id;
    175	u16	product_id;
    176};
    177
    178struct wdt87xx_data {
    179	struct i2c_client		*client;
    180	struct input_dev		*input;
    181	/* Mutex for fw update to prevent concurrent access */
    182	struct mutex			fw_mutex;
    183	struct wdt87xx_sys_param	param;
    184	u8				phys[32];
    185};
    186
    187static int wdt87xx_i2c_xfer(struct i2c_client *client,
    188			    void *txdata, size_t txlen,
    189			    void *rxdata, size_t rxlen)
    190{
    191	struct i2c_msg msgs[] = {
    192		{
    193			.addr	= client->addr,
    194			.flags	= 0,
    195			.len	= txlen,
    196			.buf	= txdata,
    197		},
    198		{
    199			.addr	= client->addr,
    200			.flags	= I2C_M_RD,
    201			.len	= rxlen,
    202			.buf	= rxdata,
    203		},
    204	};
    205	int error;
    206	int ret;
    207
    208	ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
    209	if (ret != ARRAY_SIZE(msgs)) {
    210		error = ret < 0 ? ret : -EIO;
    211		dev_err(&client->dev, "%s: i2c transfer failed: %d\n",
    212			__func__, error);
    213		return error;
    214	}
    215
    216	return 0;
    217}
    218
    219static int wdt87xx_get_desc(struct i2c_client *client, u8 desc_idx,
    220			    u8 *buf, size_t len)
    221{
    222	u8 tx_buf[] = { 0x22, 0x00, 0x10, 0x0E, 0x23, 0x00 };
    223	int error;
    224
    225	tx_buf[2] |= desc_idx & 0xF;
    226
    227	error = wdt87xx_i2c_xfer(client, tx_buf, sizeof(tx_buf),
    228				 buf, len);
    229	if (error) {
    230		dev_err(&client->dev, "get desc failed: %d\n", error);
    231		return error;
    232	}
    233
    234	if (buf[0] != len) {
    235		dev_err(&client->dev, "unexpected response to get desc: %d\n",
    236			buf[0]);
    237		return -EINVAL;
    238	}
    239
    240	mdelay(WDT_COMMAND_DELAY_MS);
    241
    242	return 0;
    243}
    244
    245static int wdt87xx_get_string(struct i2c_client *client, u8 str_idx,
    246			      u8 *buf, size_t len)
    247{
    248	u8 tx_buf[] = { 0x22, 0x00, 0x13, 0x0E, str_idx, 0x23, 0x00 };
    249	u8 rx_buf[PKT_WRITE_SIZE];
    250	size_t rx_len = len + 2;
    251	int error;
    252
    253	if (rx_len > sizeof(rx_buf))
    254		return -EINVAL;
    255
    256	error = wdt87xx_i2c_xfer(client, tx_buf, sizeof(tx_buf),
    257				 rx_buf, rx_len);
    258	if (error) {
    259		dev_err(&client->dev, "get string failed: %d\n", error);
    260		return error;
    261	}
    262
    263	if (rx_buf[1] != 0x03) {
    264		dev_err(&client->dev, "unexpected response to get string: %d\n",
    265			rx_buf[1]);
    266		return -EINVAL;
    267	}
    268
    269	rx_len = min_t(size_t, len, rx_buf[0]);
    270	memcpy(buf, &rx_buf[2], rx_len);
    271
    272	mdelay(WDT_COMMAND_DELAY_MS);
    273
    274	return 0;
    275}
    276
    277static int wdt87xx_get_feature(struct i2c_client *client,
    278			       u8 *buf, size_t buf_size)
    279{
    280	u8 tx_buf[8];
    281	u8 rx_buf[PKT_WRITE_SIZE];
    282	size_t tx_len = 0;
    283	size_t rx_len = buf_size + 2;
    284	int error;
    285
    286	if (rx_len > sizeof(rx_buf))
    287		return -EINVAL;
    288
    289	/* Get feature command packet */
    290	tx_buf[tx_len++] = 0x22;
    291	tx_buf[tx_len++] = 0x00;
    292	if (buf[CMD_REPORT_ID_OFFSET] > 0xF) {
    293		tx_buf[tx_len++] = 0x30;
    294		tx_buf[tx_len++] = 0x02;
    295		tx_buf[tx_len++] = buf[CMD_REPORT_ID_OFFSET];
    296	} else {
    297		tx_buf[tx_len++] = 0x30 | buf[CMD_REPORT_ID_OFFSET];
    298		tx_buf[tx_len++] = 0x02;
    299	}
    300	tx_buf[tx_len++] = 0x23;
    301	tx_buf[tx_len++] = 0x00;
    302
    303	error = wdt87xx_i2c_xfer(client, tx_buf, tx_len, rx_buf, rx_len);
    304	if (error) {
    305		dev_err(&client->dev, "get feature failed: %d\n", error);
    306		return error;
    307	}
    308
    309	rx_len = min_t(size_t, buf_size, get_unaligned_le16(rx_buf));
    310	memcpy(buf, &rx_buf[2], rx_len);
    311
    312	mdelay(WDT_COMMAND_DELAY_MS);
    313
    314	return 0;
    315}
    316
    317static int wdt87xx_set_feature(struct i2c_client *client,
    318			       const u8 *buf, size_t buf_size)
    319{
    320	u8 tx_buf[PKT_WRITE_SIZE];
    321	int tx_len = 0;
    322	int error;
    323
    324	/* Set feature command packet */
    325	tx_buf[tx_len++] = 0x22;
    326	tx_buf[tx_len++] = 0x00;
    327	if (buf[CMD_REPORT_ID_OFFSET] > 0xF) {
    328		tx_buf[tx_len++] = 0x30;
    329		tx_buf[tx_len++] = 0x03;
    330		tx_buf[tx_len++] = buf[CMD_REPORT_ID_OFFSET];
    331	} else {
    332		tx_buf[tx_len++] = 0x30 | buf[CMD_REPORT_ID_OFFSET];
    333		tx_buf[tx_len++] = 0x03;
    334	}
    335	tx_buf[tx_len++] = 0x23;
    336	tx_buf[tx_len++] = 0x00;
    337	tx_buf[tx_len++] = (buf_size & 0xFF);
    338	tx_buf[tx_len++] = ((buf_size & 0xFF00) >> 8);
    339
    340	if (tx_len + buf_size > sizeof(tx_buf))
    341		return -EINVAL;
    342
    343	memcpy(&tx_buf[tx_len], buf, buf_size);
    344	tx_len += buf_size;
    345
    346	error = i2c_master_send(client, tx_buf, tx_len);
    347	if (error < 0) {
    348		dev_err(&client->dev, "set feature failed: %d\n", error);
    349		return error;
    350	}
    351
    352	mdelay(WDT_COMMAND_DELAY_MS);
    353
    354	return 0;
    355}
    356
    357static int wdt87xx_send_command(struct i2c_client *client, int cmd, int value)
    358{
    359	u8 cmd_buf[CMD_BUF_SIZE];
    360
    361	/* Set the command packet */
    362	cmd_buf[CMD_REPORT_ID_OFFSET] = VND_REQ_WRITE;
    363	cmd_buf[CMD_TYPE_OFFSET] = VND_SET_COMMAND_DATA;
    364	put_unaligned_le16((u16)cmd, &cmd_buf[CMD_INDEX_OFFSET]);
    365
    366	switch (cmd) {
    367	case VND_CMD_START:
    368	case VND_CMD_STOP:
    369	case VND_CMD_RESET:
    370		/* Mode selector */
    371		put_unaligned_le32((value & 0xFF), &cmd_buf[CMD_LENGTH_OFFSET]);
    372		break;
    373
    374	case VND_CMD_SFLCK:
    375		put_unaligned_le16(CMD_SFLCK_KEY, &cmd_buf[CMD_KEY_OFFSET]);
    376		break;
    377
    378	case VND_CMD_SFUNL:
    379		put_unaligned_le16(CMD_SFUNL_KEY, &cmd_buf[CMD_KEY_OFFSET]);
    380		break;
    381
    382	case VND_CMD_ERASE:
    383	case VND_SET_CHECKSUM_CALC:
    384	case VND_SET_CHECKSUM_LENGTH:
    385		put_unaligned_le32(value, &cmd_buf[CMD_KEY_OFFSET]);
    386		break;
    387
    388	default:
    389		cmd_buf[CMD_REPORT_ID_OFFSET] = 0;
    390		dev_err(&client->dev, "Invalid command: %d\n", cmd);
    391		return -EINVAL;
    392	}
    393
    394	return wdt87xx_set_feature(client, cmd_buf, sizeof(cmd_buf));
    395}
    396
    397static int wdt87xx_sw_reset(struct i2c_client *client)
    398{
    399	int error;
    400
    401	dev_dbg(&client->dev, "resetting device now\n");
    402
    403	error = wdt87xx_send_command(client, VND_CMD_RESET, 0);
    404	if (error) {
    405		dev_err(&client->dev, "reset failed\n");
    406		return error;
    407	}
    408
    409	/* Wait the device to be ready */
    410	msleep(WDT_FW_RESET_TIME);
    411
    412	return 0;
    413}
    414
    415static const void *wdt87xx_get_fw_chunk(const struct firmware *fw, u32 id)
    416{
    417	size_t pos = FW_PAYLOAD_OFFSET;
    418	u32 chunk_id, chunk_size;
    419
    420	while (pos < fw->size) {
    421		chunk_id = get_unaligned_le32(fw->data +
    422					      pos + FW_CHUNK_ID_OFFSET);
    423		if (chunk_id == id)
    424			return fw->data + pos;
    425
    426		chunk_size = get_unaligned_le32(fw->data +
    427						pos + FW_CHUNK_SIZE_OFFSET);
    428		pos += chunk_size + 2 * sizeof(u32); /* chunk ID + size */
    429	}
    430
    431	return NULL;
    432}
    433
    434static int wdt87xx_get_sysparam(struct i2c_client *client,
    435				struct wdt87xx_sys_param *param)
    436{
    437	u8 buf[PKT_READ_SIZE];
    438	int error;
    439
    440	error = wdt87xx_get_desc(client, WDT_GD_DEVICE, buf, 18);
    441	if (error) {
    442		dev_err(&client->dev, "failed to get device desc\n");
    443		return error;
    444	}
    445
    446	param->vendor_id = get_unaligned_le16(buf + DEV_DESC_OFFSET_VID);
    447	param->product_id = get_unaligned_le16(buf + DEV_DESC_OFFSET_PID);
    448
    449	error = wdt87xx_get_string(client, STRIDX_PARAMETERS, buf, 34);
    450	if (error) {
    451		dev_err(&client->dev, "failed to get parameters\n");
    452		return error;
    453	}
    454
    455	param->xmls_id1 = get_unaligned_le16(buf + CTL_PARAM_OFFSET_XMLS_ID1);
    456	param->xmls_id2 = get_unaligned_le16(buf + CTL_PARAM_OFFSET_XMLS_ID2);
    457	param->phy_ch_x = get_unaligned_le16(buf + CTL_PARAM_OFFSET_PHY_CH_X);
    458	param->phy_ch_y = get_unaligned_le16(buf + CTL_PARAM_OFFSET_PHY_CH_Y);
    459	param->phy_w = get_unaligned_le16(buf + CTL_PARAM_OFFSET_PHY_W) / 10;
    460	param->phy_h = get_unaligned_le16(buf + CTL_PARAM_OFFSET_PHY_H) / 10;
    461
    462	/* Get the scaling factor of pixel to logical coordinate */
    463	param->scaling_factor =
    464			get_unaligned_le16(buf + CTL_PARAM_OFFSET_FACTOR);
    465
    466	param->max_x = MAX_UNIT_AXIS;
    467	param->max_y = DIV_ROUND_CLOSEST(MAX_UNIT_AXIS * param->phy_h,
    468					 param->phy_w);
    469
    470	error = wdt87xx_get_string(client, STRIDX_PLATFORM_ID, buf, 8);
    471	if (error) {
    472		dev_err(&client->dev, "failed to get platform id\n");
    473		return error;
    474	}
    475
    476	param->plat_id = buf[1];
    477
    478	buf[0] = 0xf2;
    479	error = wdt87xx_get_feature(client, buf, 16);
    480	if (error) {
    481		dev_err(&client->dev, "failed to get firmware id\n");
    482		return error;
    483	}
    484
    485	if (buf[0] != 0xf2) {
    486		dev_err(&client->dev, "wrong id of fw response: 0x%x\n",
    487			buf[0]);
    488		return -EINVAL;
    489	}
    490
    491	param->fw_id = get_unaligned_le16(&buf[1]);
    492
    493	dev_info(&client->dev,
    494		 "fw_id: 0x%x, plat_id: 0x%x, xml_id1: %04x, xml_id2: %04x\n",
    495		 param->fw_id, param->plat_id,
    496		 param->xmls_id1, param->xmls_id2);
    497
    498	return 0;
    499}
    500
    501static int wdt87xx_validate_firmware(struct wdt87xx_data *wdt,
    502				     const struct firmware *fw)
    503{
    504	const void *fw_chunk;
    505	u32 data1, data2;
    506	u32 size;
    507	u8 fw_chip_id;
    508	u8 chip_id;
    509
    510	data1 = get_unaligned_le32(fw->data + FW_FOURCC1_OFFSET);
    511	data2 = get_unaligned_le32(fw->data + FW_FOURCC2_OFFSET);
    512	if (data1 != FOURCC_ID_RIFF || data2 != FOURCC_ID_WHIF) {
    513		dev_err(&wdt->client->dev, "check fw tag failed\n");
    514		return -EINVAL;
    515	}
    516
    517	size = get_unaligned_le32(fw->data + FW_SIZE_OFFSET);
    518	if (size != fw->size) {
    519		dev_err(&wdt->client->dev,
    520			"fw size mismatch: expected %d, actual %zu\n",
    521			size, fw->size);
    522		return -EINVAL;
    523	}
    524
    525	/*
    526	 * Get the chip_id from the firmware. Make sure that it is the
    527	 * right controller to do the firmware and config update.
    528	 */
    529	fw_chunk = wdt87xx_get_fw_chunk(fw, CHUNK_ID_FRWR);
    530	if (!fw_chunk) {
    531		dev_err(&wdt->client->dev,
    532			"unable to locate firmware chunk\n");
    533		return -EINVAL;
    534	}
    535
    536	fw_chip_id = (get_unaligned_le32(fw_chunk +
    537					 FW_CHUNK_VERSION_OFFSET) >> 12) & 0xF;
    538	chip_id = (wdt->param.fw_id >> 12) & 0xF;
    539
    540	if (fw_chip_id != chip_id) {
    541		dev_err(&wdt->client->dev,
    542			"fw version mismatch: fw %d vs. chip %d\n",
    543			fw_chip_id, chip_id);
    544		return -ENODEV;
    545	}
    546
    547	return 0;
    548}
    549
    550static int wdt87xx_validate_fw_chunk(const void *data, int id)
    551{
    552	if (id == CHUNK_ID_FRWR) {
    553		u32 fw_id;
    554
    555		fw_id = get_unaligned_le32(data + FW_CHUNK_PAYLOAD_OFFSET);
    556		if (fw_id != WDT_FIRMWARE_ID)
    557			return -EINVAL;
    558	}
    559
    560	return 0;
    561}
    562
    563static int wdt87xx_write_data(struct i2c_client *client, const char *data,
    564			      u32 address, int length)
    565{
    566	u16 packet_size;
    567	int count = 0;
    568	int error;
    569	u8 pkt_buf[PKT_BUF_SIZE];
    570
    571	/* Address and length should be 4 bytes aligned */
    572	if ((address & 0x3) != 0 || (length & 0x3) != 0) {
    573		dev_err(&client->dev,
    574			"addr & len must be 4 bytes aligned %x, %x\n",
    575			address, length);
    576		return -EINVAL;
    577	}
    578
    579	while (length) {
    580		packet_size = min(length, PACKET_SIZE);
    581
    582		pkt_buf[CMD_REPORT_ID_OFFSET] = VND_REQ_WRITE;
    583		pkt_buf[CMD_TYPE_OFFSET] = VND_SET_DATA;
    584		put_unaligned_le16(packet_size, &pkt_buf[CMD_INDEX_OFFSET]);
    585		put_unaligned_le32(address, &pkt_buf[CMD_LENGTH_OFFSET]);
    586		memcpy(&pkt_buf[CMD_DATA_OFFSET], data, packet_size);
    587
    588		error = wdt87xx_set_feature(client, pkt_buf, sizeof(pkt_buf));
    589		if (error)
    590			return error;
    591
    592		length -= packet_size;
    593		data += packet_size;
    594		address += packet_size;
    595
    596		/* Wait for the controller to finish the write */
    597		mdelay(WDT_FLASH_WRITE_DELAY_MS);
    598
    599		if ((++count % 32) == 0) {
    600			/* Delay for fw to clear watch dog */
    601			msleep(20);
    602		}
    603	}
    604
    605	return 0;
    606}
    607
    608static u16 misr(u16 cur_value, u8 new_value)
    609{
    610	u32 a, b;
    611	u32 bit0;
    612	u32 y;
    613
    614	a = cur_value;
    615	b = new_value;
    616	bit0 = a ^ (b & 1);
    617	bit0 ^= a >> 1;
    618	bit0 ^= a >> 2;
    619	bit0 ^= a >> 4;
    620	bit0 ^= a >> 5;
    621	bit0 ^= a >> 7;
    622	bit0 ^= a >> 11;
    623	bit0 ^= a >> 15;
    624	y = (a << 1) ^ b;
    625	y = (y & ~1) | (bit0 & 1);
    626
    627	return (u16)y;
    628}
    629
    630static u16 wdt87xx_calculate_checksum(const u8 *data, size_t length)
    631{
    632	u16 checksum = 0;
    633	size_t i;
    634
    635	for (i = 0; i < length; i++)
    636		checksum = misr(checksum, data[i]);
    637
    638	return checksum;
    639}
    640
    641static int wdt87xx_get_checksum(struct i2c_client *client, u16 *checksum,
    642				u32 address, int length)
    643{
    644	int error;
    645	int time_delay;
    646	u8 pkt_buf[PKT_BUF_SIZE];
    647	u8 cmd_buf[CMD_BUF_SIZE];
    648
    649	error = wdt87xx_send_command(client, VND_SET_CHECKSUM_LENGTH, length);
    650	if (error) {
    651		dev_err(&client->dev, "failed to set checksum length\n");
    652		return error;
    653	}
    654
    655	error = wdt87xx_send_command(client, VND_SET_CHECKSUM_CALC, address);
    656	if (error) {
    657		dev_err(&client->dev, "failed to set checksum address\n");
    658		return error;
    659	}
    660
    661	/* Wait the operation to complete */
    662	time_delay = DIV_ROUND_UP(length, 1024);
    663	msleep(time_delay * 30);
    664
    665	memset(cmd_buf, 0, sizeof(cmd_buf));
    666	cmd_buf[CMD_REPORT_ID_OFFSET] = VND_REQ_READ;
    667	cmd_buf[CMD_TYPE_OFFSET] = VND_GET_CHECKSUM;
    668	error = wdt87xx_set_feature(client, cmd_buf, sizeof(cmd_buf));
    669	if (error) {
    670		dev_err(&client->dev, "failed to request checksum\n");
    671		return error;
    672	}
    673
    674	memset(pkt_buf, 0, sizeof(pkt_buf));
    675	pkt_buf[CMD_REPORT_ID_OFFSET] = VND_READ_DATA;
    676	error = wdt87xx_get_feature(client, pkt_buf, sizeof(pkt_buf));
    677	if (error) {
    678		dev_err(&client->dev, "failed to read checksum\n");
    679		return error;
    680	}
    681
    682	*checksum = get_unaligned_le16(&pkt_buf[CMD_DATA_OFFSET]);
    683	return 0;
    684}
    685
    686static int wdt87xx_write_firmware(struct i2c_client *client, const void *chunk)
    687{
    688	u32 start_addr = get_unaligned_le32(chunk + FW_CHUNK_TGT_START_OFFSET);
    689	u32 size = get_unaligned_le32(chunk + FW_CHUNK_PAYLOAD_LEN_OFFSET);
    690	const void *data = chunk + FW_CHUNK_PAYLOAD_OFFSET;
    691	int error;
    692	int err1;
    693	int page_size;
    694	int retry = 0;
    695	u16 device_checksum, firmware_checksum;
    696
    697	dev_dbg(&client->dev, "start 4k page program\n");
    698
    699	error = wdt87xx_send_command(client, VND_CMD_STOP, MODE_STOP);
    700	if (error) {
    701		dev_err(&client->dev, "stop report mode failed\n");
    702		return error;
    703	}
    704
    705	error = wdt87xx_send_command(client, VND_CMD_SFUNL, 0);
    706	if (error) {
    707		dev_err(&client->dev, "unlock failed\n");
    708		goto out_enable_reporting;
    709	}
    710
    711	mdelay(10);
    712
    713	while (size) {
    714		dev_dbg(&client->dev, "%s: %x, %x\n", __func__,
    715			start_addr, size);
    716
    717		page_size = min_t(u32, size, PG_SIZE);
    718		size -= page_size;
    719
    720		for (retry = 0; retry < MAX_RETRIES; retry++) {
    721			error = wdt87xx_send_command(client, VND_CMD_ERASE,
    722						     start_addr);
    723			if (error) {
    724				dev_err(&client->dev,
    725					"erase failed at %#08x\n", start_addr);
    726				break;
    727			}
    728
    729			msleep(WDT_FLASH_ERASE_DELAY_MS);
    730
    731			error = wdt87xx_write_data(client, data, start_addr,
    732						   page_size);
    733			if (error) {
    734				dev_err(&client->dev,
    735					"write failed at %#08x (%d bytes)\n",
    736					start_addr, page_size);
    737				break;
    738			}
    739
    740			error = wdt87xx_get_checksum(client, &device_checksum,
    741						     start_addr, page_size);
    742			if (error) {
    743				dev_err(&client->dev,
    744					"failed to retrieve checksum for %#08x (len: %d)\n",
    745					start_addr, page_size);
    746				break;
    747			}
    748
    749			firmware_checksum =
    750				wdt87xx_calculate_checksum(data, page_size);
    751
    752			if (device_checksum == firmware_checksum)
    753				break;
    754
    755			dev_err(&client->dev,
    756				"checksum fail: %d vs %d, retry %d\n",
    757				device_checksum, firmware_checksum, retry);
    758		}
    759
    760		if (retry == MAX_RETRIES) {
    761			dev_err(&client->dev, "page write failed\n");
    762			error = -EIO;
    763			goto out_lock_device;
    764		}
    765
    766		start_addr = start_addr + page_size;
    767		data = data + page_size;
    768	}
    769
    770out_lock_device:
    771	err1 = wdt87xx_send_command(client, VND_CMD_SFLCK, 0);
    772	if (err1)
    773		dev_err(&client->dev, "lock failed\n");
    774
    775	mdelay(10);
    776
    777out_enable_reporting:
    778	err1 = wdt87xx_send_command(client, VND_CMD_START, 0);
    779	if (err1)
    780		dev_err(&client->dev, "start to report failed\n");
    781
    782	return error ? error : err1;
    783}
    784
    785static int wdt87xx_load_chunk(struct i2c_client *client,
    786			      const struct firmware *fw, u32 ck_id)
    787{
    788	const void *chunk;
    789	int error;
    790
    791	chunk = wdt87xx_get_fw_chunk(fw, ck_id);
    792	if (!chunk) {
    793		dev_err(&client->dev, "unable to locate chunk (type %d)\n",
    794			ck_id);
    795		return -EINVAL;
    796	}
    797
    798	error = wdt87xx_validate_fw_chunk(chunk, ck_id);
    799	if (error) {
    800		dev_err(&client->dev, "invalid chunk (type %d): %d\n",
    801			ck_id, error);
    802		return error;
    803	}
    804
    805	error = wdt87xx_write_firmware(client, chunk);
    806	if (error) {
    807		dev_err(&client->dev,
    808			"failed to write fw chunk (type %d): %d\n",
    809			ck_id, error);
    810		return error;
    811	}
    812
    813	return 0;
    814}
    815
    816static int wdt87xx_do_update_firmware(struct i2c_client *client,
    817				      const struct firmware *fw,
    818				      unsigned int chunk_id)
    819{
    820	struct wdt87xx_data *wdt = i2c_get_clientdata(client);
    821	int error;
    822
    823	error = wdt87xx_validate_firmware(wdt, fw);
    824	if (error)
    825		return error;
    826
    827	error = mutex_lock_interruptible(&wdt->fw_mutex);
    828	if (error)
    829		return error;
    830
    831	disable_irq(client->irq);
    832
    833	error = wdt87xx_load_chunk(client, fw, chunk_id);
    834	if (error) {
    835		dev_err(&client->dev,
    836			"firmware load failed (type: %d): %d\n",
    837			chunk_id, error);
    838		goto out;
    839	}
    840
    841	error = wdt87xx_sw_reset(client);
    842	if (error) {
    843		dev_err(&client->dev, "soft reset failed: %d\n", error);
    844		goto out;
    845	}
    846
    847	/* Refresh the parameters */
    848	error = wdt87xx_get_sysparam(client, &wdt->param);
    849	if (error)
    850		dev_err(&client->dev,
    851			"failed to refresh system parameters: %d\n", error);
    852out:
    853	enable_irq(client->irq);
    854	mutex_unlock(&wdt->fw_mutex);
    855
    856	return error ? error : 0;
    857}
    858
    859static int wdt87xx_update_firmware(struct device *dev,
    860				   const char *fw_name, unsigned int chunk_id)
    861{
    862	struct i2c_client *client = to_i2c_client(dev);
    863	const struct firmware *fw;
    864	int error;
    865
    866	error = request_firmware(&fw, fw_name, dev);
    867	if (error) {
    868		dev_err(&client->dev, "unable to retrieve firmware %s: %d\n",
    869			fw_name, error);
    870		return error;
    871	}
    872
    873	error = wdt87xx_do_update_firmware(client, fw, chunk_id);
    874
    875	release_firmware(fw);
    876
    877	return error ? error : 0;
    878}
    879
    880static ssize_t config_csum_show(struct device *dev,
    881				struct device_attribute *attr, char *buf)
    882{
    883	struct i2c_client *client = to_i2c_client(dev);
    884	struct wdt87xx_data *wdt = i2c_get_clientdata(client);
    885	u32 cfg_csum;
    886
    887	cfg_csum = wdt->param.xmls_id1;
    888	cfg_csum = (cfg_csum << 16) | wdt->param.xmls_id2;
    889
    890	return scnprintf(buf, PAGE_SIZE, "%x\n", cfg_csum);
    891}
    892
    893static ssize_t fw_version_show(struct device *dev,
    894			       struct device_attribute *attr, char *buf)
    895{
    896	struct i2c_client *client = to_i2c_client(dev);
    897	struct wdt87xx_data *wdt = i2c_get_clientdata(client);
    898
    899	return scnprintf(buf, PAGE_SIZE, "%x\n", wdt->param.fw_id);
    900}
    901
    902static ssize_t plat_id_show(struct device *dev,
    903			    struct device_attribute *attr, char *buf)
    904{
    905	struct i2c_client *client = to_i2c_client(dev);
    906	struct wdt87xx_data *wdt = i2c_get_clientdata(client);
    907
    908	return scnprintf(buf, PAGE_SIZE, "%x\n", wdt->param.plat_id);
    909}
    910
    911static ssize_t update_config_store(struct device *dev,
    912				   struct device_attribute *attr,
    913				   const char *buf, size_t count)
    914{
    915	int error;
    916
    917	error = wdt87xx_update_firmware(dev, WDT87XX_CFG_NAME, CHUNK_ID_CNFG);
    918
    919	return error ? error : count;
    920}
    921
    922static ssize_t update_fw_store(struct device *dev,
    923			       struct device_attribute *attr,
    924			       const char *buf, size_t count)
    925{
    926	int error;
    927
    928	error = wdt87xx_update_firmware(dev, WDT87XX_FW_NAME, CHUNK_ID_FRWR);
    929
    930	return error ? error : count;
    931}
    932
    933static DEVICE_ATTR_RO(config_csum);
    934static DEVICE_ATTR_RO(fw_version);
    935static DEVICE_ATTR_RO(plat_id);
    936static DEVICE_ATTR_WO(update_config);
    937static DEVICE_ATTR_WO(update_fw);
    938
    939static struct attribute *wdt87xx_attrs[] = {
    940	&dev_attr_config_csum.attr,
    941	&dev_attr_fw_version.attr,
    942	&dev_attr_plat_id.attr,
    943	&dev_attr_update_config.attr,
    944	&dev_attr_update_fw.attr,
    945	NULL
    946};
    947
    948static const struct attribute_group wdt87xx_attr_group = {
    949	.attrs = wdt87xx_attrs,
    950};
    951
    952static void wdt87xx_report_contact(struct input_dev *input,
    953				   struct wdt87xx_sys_param *param,
    954				   u8 *buf)
    955{
    956	int finger_id;
    957	u32 x, y, w;
    958	u8 p;
    959
    960	finger_id = (buf[FINGER_EV_V1_OFFSET_ID] >> 3) - 1;
    961	if (finger_id < 0)
    962		return;
    963
    964	/* Check if this is an active contact */
    965	if (!(buf[FINGER_EV_V1_OFFSET_ID] & 0x1))
    966		return;
    967
    968	w = buf[FINGER_EV_V1_OFFSET_W];
    969	w *= param->scaling_factor;
    970
    971	p = buf[FINGER_EV_V1_OFFSET_P];
    972
    973	x = get_unaligned_le16(buf + FINGER_EV_V1_OFFSET_X);
    974
    975	y = get_unaligned_le16(buf + FINGER_EV_V1_OFFSET_Y);
    976	y = DIV_ROUND_CLOSEST(y * param->phy_h, param->phy_w);
    977
    978	/* Refuse incorrect coordinates */
    979	if (x > param->max_x || y > param->max_y)
    980		return;
    981
    982	dev_dbg(input->dev.parent, "tip on (%d), x(%d), y(%d)\n",
    983		finger_id, x, y);
    984
    985	input_mt_slot(input, finger_id);
    986	input_mt_report_slot_state(input, MT_TOOL_FINGER, 1);
    987	input_report_abs(input, ABS_MT_TOUCH_MAJOR, w);
    988	input_report_abs(input, ABS_MT_PRESSURE, p);
    989	input_report_abs(input, ABS_MT_POSITION_X, x);
    990	input_report_abs(input, ABS_MT_POSITION_Y, y);
    991}
    992
    993static irqreturn_t wdt87xx_ts_interrupt(int irq, void *dev_id)
    994{
    995	struct wdt87xx_data *wdt = dev_id;
    996	struct i2c_client *client = wdt->client;
    997	int i, fingers;
    998	int error;
    999	u8 raw_buf[WDT_V1_RAW_BUF_COUNT] = {0};
   1000
   1001	error = i2c_master_recv(client, raw_buf, WDT_V1_RAW_BUF_COUNT);
   1002	if (error < 0) {
   1003		dev_err(&client->dev, "read v1 raw data failed: %d\n", error);
   1004		goto irq_exit;
   1005	}
   1006
   1007	fingers = raw_buf[TOUCH_PK_V1_OFFSET_FNGR_NUM];
   1008	if (!fingers)
   1009		goto irq_exit;
   1010
   1011	for (i = 0; i < WDT_MAX_FINGER; i++)
   1012		wdt87xx_report_contact(wdt->input,
   1013				       &wdt->param,
   1014				       &raw_buf[TOUCH_PK_V1_OFFSET_EVENT +
   1015						i * FINGER_EV_V1_SIZE]);
   1016
   1017	input_mt_sync_frame(wdt->input);
   1018	input_sync(wdt->input);
   1019
   1020irq_exit:
   1021	return IRQ_HANDLED;
   1022}
   1023
   1024static int wdt87xx_ts_create_input_device(struct wdt87xx_data *wdt)
   1025{
   1026	struct device *dev = &wdt->client->dev;
   1027	struct input_dev *input;
   1028	unsigned int res = DIV_ROUND_CLOSEST(MAX_UNIT_AXIS, wdt->param.phy_w);
   1029	int error;
   1030
   1031	input = devm_input_allocate_device(dev);
   1032	if (!input) {
   1033		dev_err(dev, "failed to allocate input device\n");
   1034		return -ENOMEM;
   1035	}
   1036	wdt->input = input;
   1037
   1038	input->name = "WDT87xx Touchscreen";
   1039	input->id.bustype = BUS_I2C;
   1040	input->id.vendor = wdt->param.vendor_id;
   1041	input->id.product = wdt->param.product_id;
   1042	input->phys = wdt->phys;
   1043
   1044	input_set_abs_params(input, ABS_MT_POSITION_X, 0,
   1045			     wdt->param.max_x, 0, 0);
   1046	input_set_abs_params(input, ABS_MT_POSITION_Y, 0,
   1047			     wdt->param.max_y, 0, 0);
   1048	input_abs_set_res(input, ABS_MT_POSITION_X, res);
   1049	input_abs_set_res(input, ABS_MT_POSITION_Y, res);
   1050
   1051	input_set_abs_params(input, ABS_MT_TOUCH_MAJOR,
   1052			     0, wdt->param.max_x, 0, 0);
   1053	input_set_abs_params(input, ABS_MT_PRESSURE, 0, 0xFF, 0, 0);
   1054
   1055	input_mt_init_slots(input, WDT_MAX_FINGER,
   1056			    INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED);
   1057
   1058	error = input_register_device(input);
   1059	if (error) {
   1060		dev_err(dev, "failed to register input device: %d\n", error);
   1061		return error;
   1062	}
   1063
   1064	return 0;
   1065}
   1066
   1067static int wdt87xx_ts_probe(struct i2c_client *client,
   1068			    const struct i2c_device_id *id)
   1069{
   1070	struct wdt87xx_data *wdt;
   1071	int error;
   1072
   1073	dev_dbg(&client->dev, "adapter=%d, client irq: %d\n",
   1074		client->adapter->nr, client->irq);
   1075
   1076	/* Check if the I2C function is ok in this adaptor */
   1077	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
   1078		return -ENXIO;
   1079
   1080	wdt = devm_kzalloc(&client->dev, sizeof(*wdt), GFP_KERNEL);
   1081	if (!wdt)
   1082		return -ENOMEM;
   1083
   1084	wdt->client = client;
   1085	mutex_init(&wdt->fw_mutex);
   1086	i2c_set_clientdata(client, wdt);
   1087
   1088	snprintf(wdt->phys, sizeof(wdt->phys), "i2c-%u-%04x/input0",
   1089		 client->adapter->nr, client->addr);
   1090
   1091	error = wdt87xx_get_sysparam(client, &wdt->param);
   1092	if (error)
   1093		return error;
   1094
   1095	error = wdt87xx_ts_create_input_device(wdt);
   1096	if (error)
   1097		return error;
   1098
   1099	error = devm_request_threaded_irq(&client->dev, client->irq,
   1100					  NULL, wdt87xx_ts_interrupt,
   1101					  IRQF_ONESHOT,
   1102					  client->name, wdt);
   1103	if (error) {
   1104		dev_err(&client->dev, "request irq failed: %d\n", error);
   1105		return error;
   1106	}
   1107
   1108	error = devm_device_add_group(&client->dev, &wdt87xx_attr_group);
   1109	if (error) {
   1110		dev_err(&client->dev, "create sysfs failed: %d\n", error);
   1111		return error;
   1112	}
   1113
   1114	return 0;
   1115}
   1116
   1117static int __maybe_unused wdt87xx_suspend(struct device *dev)
   1118{
   1119	struct i2c_client *client = to_i2c_client(dev);
   1120	int error;
   1121
   1122	disable_irq(client->irq);
   1123
   1124	error = wdt87xx_send_command(client, VND_CMD_STOP, MODE_IDLE);
   1125	if (error) {
   1126		enable_irq(client->irq);
   1127		dev_err(&client->dev,
   1128			"failed to stop device when suspending: %d\n",
   1129			error);
   1130		return error;
   1131	}
   1132
   1133	return 0;
   1134}
   1135
   1136static int __maybe_unused wdt87xx_resume(struct device *dev)
   1137{
   1138	struct i2c_client *client = to_i2c_client(dev);
   1139	int error;
   1140
   1141	/*
   1142	 * The chip may have been reset while system is resuming,
   1143	 * give it some time to settle.
   1144	 */
   1145	msleep(100);
   1146
   1147	error = wdt87xx_send_command(client, VND_CMD_START, 0);
   1148	if (error)
   1149		dev_err(&client->dev,
   1150			"failed to start device when resuming: %d\n",
   1151			error);
   1152
   1153	enable_irq(client->irq);
   1154
   1155	return 0;
   1156}
   1157
   1158static SIMPLE_DEV_PM_OPS(wdt87xx_pm_ops, wdt87xx_suspend, wdt87xx_resume);
   1159
   1160static const struct i2c_device_id wdt87xx_dev_id[] = {
   1161	{ WDT87XX_NAME, 0 },
   1162	{ }
   1163};
   1164MODULE_DEVICE_TABLE(i2c, wdt87xx_dev_id);
   1165
   1166static const struct acpi_device_id wdt87xx_acpi_id[] = {
   1167	{ "WDHT0001", 0 },
   1168	{ }
   1169};
   1170MODULE_DEVICE_TABLE(acpi, wdt87xx_acpi_id);
   1171
   1172static struct i2c_driver wdt87xx_driver = {
   1173	.probe		= wdt87xx_ts_probe,
   1174	.id_table	= wdt87xx_dev_id,
   1175	.driver	= {
   1176		.name	= WDT87XX_NAME,
   1177		.pm     = &wdt87xx_pm_ops,
   1178		.acpi_match_table = ACPI_PTR(wdt87xx_acpi_id),
   1179	},
   1180};
   1181module_i2c_driver(wdt87xx_driver);
   1182
   1183MODULE_AUTHOR("HN Chen <hn.chen@weidahitech.com>");
   1184MODULE_DESCRIPTION("WeidaHiTech WDT87XX Touchscreen driver");
   1185MODULE_LICENSE("GPL");