Commit d5f9c43d authored by simba.hsu's avatar simba.hsu Committed by Dmitry Torokhov
Browse files

Input: raydium_i2c_ts - read device version in bootloader mode



Add support reading device ID when controller is in bootloader mode, which
may happen if firmware update has been interrupted.

Signed-off-by: default avatarsimba.hsu <simba.hsu@rad-ic.com>
Link: https://lore.kernel.org/r/20210818063644.8654-1-simba.hsu@rad-ic.com


Signed-off-by: default avatarDmitry Torokhov <dmitry.torokhov@gmail.com>
parent 58ae4004
Loading
Loading
Loading
Loading
+43 −7
Original line number Diff line number Diff line
@@ -37,6 +37,7 @@
#define RM_CMD_BOOT_READ	0x44		/* send wait bl data ready*/

#define RM_BOOT_RDY		0xFF		/* bl data ready */
#define RM_BOOT_CMD_READHWID	0x0E		/* read hwid */

/* I2C main commands */
#define RM_CMD_QUERY_BANK	0x2B
@@ -290,6 +291,44 @@ static int raydium_i2c_sw_reset(struct i2c_client *client)
	return 0;
}

static int raydium_i2c_query_ts_bootloader_info(struct raydium_data *ts)
{
	struct i2c_client *client = ts->client;
	static const u8 get_hwid[] = { RM_BOOT_CMD_READHWID,
				       0x10, 0xc0, 0x01, 0x00, 0x04, 0x00 };
	u8 rbuf[5] = { 0 };
	u32 hw_ver;
	int error;

	error = raydium_i2c_send(client, RM_CMD_BOOT_WRT,
				 get_hwid, sizeof(get_hwid));
	if (error) {
		dev_err(&client->dev, "WRT HWID command failed: %d\n", error);
		return error;
	}

	error = raydium_i2c_send(client, RM_CMD_BOOT_ACK, rbuf, 1);
	if (error) {
		dev_err(&client->dev, "Ack HWID command failed: %d\n", error);
		return error;
	}

	error = raydium_i2c_read(client, RM_CMD_BOOT_CHK, rbuf, sizeof(rbuf));
	if (error) {
		dev_err(&client->dev, "Read HWID command failed: %d (%4ph)\n",
			error, rbuf + 1);
		hw_ver = 0xffffffffUL;
	} else {
		hw_ver = get_unaligned_be32(rbuf + 1);
	}

	ts->info.hw_ver = cpu_to_le32(hw_ver);
	ts->info.main_ver = 0xff;
	ts->info.sub_ver = 0xff;

	return error;
}

static int raydium_i2c_query_ts_info(struct raydium_data *ts)
{
	struct i2c_client *client = ts->client;
@@ -388,13 +427,10 @@ static int raydium_i2c_initialize(struct raydium_data *ts)
	if (error)
		ts->boot_mode = RAYDIUM_TS_BLDR;

	if (ts->boot_mode == RAYDIUM_TS_BLDR) {
		ts->info.hw_ver = cpu_to_le32(0xffffffffUL);
		ts->info.main_ver = 0xff;
		ts->info.sub_ver = 0xff;
	} else {
	if (ts->boot_mode == RAYDIUM_TS_BLDR)
		raydium_i2c_query_ts_bootloader_info(ts);
	else
		raydium_i2c_query_ts_info(ts);
	}

	return error;
}