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

chipone_icn8505.c (13137B)


      1// SPDX-License-Identifier: GPL-2.0+
      2/*
      3 * Driver for ChipOne icn8505 i2c touchscreen controller
      4 *
      5 * Copyright (c) 2015-2018 Red Hat Inc.
      6 *
      7 * Red Hat authors:
      8 * Hans de Goede <hdegoede@redhat.com>
      9 */
     10
     11#include <asm/unaligned.h>
     12#include <linux/acpi.h>
     13#include <linux/crc32.h>
     14#include <linux/delay.h>
     15#include <linux/firmware.h>
     16#include <linux/interrupt.h>
     17#include <linux/i2c.h>
     18#include <linux/input.h>
     19#include <linux/input/mt.h>
     20#include <linux/input/touchscreen.h>
     21#include <linux/module.h>
     22
     23/* Normal operation mode defines */
     24#define ICN8505_REG_ADDR_WIDTH		16
     25
     26#define ICN8505_REG_POWER		0x0004
     27#define ICN8505_REG_TOUCHDATA		0x1000
     28#define ICN8505_REG_CONFIGDATA		0x8000
     29
     30/* ICN8505_REG_POWER commands */
     31#define ICN8505_POWER_ACTIVE		0x00
     32#define ICN8505_POWER_MONITOR		0x01
     33#define ICN8505_POWER_HIBERNATE		0x02
     34/*
     35 * The Android driver uses these to turn on/off the charger filter, but the
     36 * filter is way too aggressive making e.g. onscreen keyboards unusable.
     37 */
     38#define ICN8505_POWER_ENA_CHARGER_MODE	0x55
     39#define ICN8505_POWER_DIS_CHARGER_MODE	0x66
     40
     41#define ICN8505_MAX_TOUCHES		10
     42
     43/* Programming mode defines */
     44#define ICN8505_PROG_I2C_ADDR		0x30
     45#define ICN8505_PROG_REG_ADDR_WIDTH	24
     46
     47#define MAX_FW_UPLOAD_TRIES		3
     48
     49struct icn8505_touch {
     50	u8 slot;
     51	u8 x[2];
     52	u8 y[2];
     53	u8 pressure;	/* Seems more like finger width then pressure really */
     54	u8 event;
     55/* The difference between 2 and 3 is unclear */
     56#define ICN8505_EVENT_NO_DATA	1 /* No finger seen yet since wakeup */
     57#define ICN8505_EVENT_UPDATE1	2 /* New or updated coordinates */
     58#define ICN8505_EVENT_UPDATE2	3 /* New or updated coordinates */
     59#define ICN8505_EVENT_END	4 /* Finger lifted */
     60} __packed;
     61
     62struct icn8505_touch_data {
     63	u8 softbutton;
     64	u8 touch_count;
     65	struct icn8505_touch touches[ICN8505_MAX_TOUCHES];
     66} __packed;
     67
     68struct icn8505_data {
     69	struct i2c_client *client;
     70	struct input_dev *input;
     71	struct gpio_desc *wake_gpio;
     72	struct touchscreen_properties prop;
     73	char firmware_name[32];
     74};
     75
     76static int icn8505_read_xfer(struct i2c_client *client, u16 i2c_addr,
     77			     int reg_addr, int reg_addr_width,
     78			     void *data, int len, bool silent)
     79{
     80	u8 buf[3];
     81	int i, ret;
     82	struct i2c_msg msg[2] = {
     83		{
     84			.addr = i2c_addr,
     85			.buf = buf,
     86			.len = reg_addr_width / 8,
     87		},
     88		{
     89			.addr = i2c_addr,
     90			.flags = I2C_M_RD,
     91			.buf = data,
     92			.len = len,
     93		}
     94	};
     95
     96	for (i = 0; i < (reg_addr_width / 8); i++)
     97		buf[i] = (reg_addr >> (reg_addr_width - (i + 1) * 8)) & 0xff;
     98
     99	ret = i2c_transfer(client->adapter, msg, 2);
    100	if (ret != ARRAY_SIZE(msg)) {
    101		if (ret >= 0)
    102			ret = -EIO;
    103		if (!silent)
    104			dev_err(&client->dev,
    105				"Error reading addr %#x reg %#x: %d\n",
    106				i2c_addr, reg_addr, ret);
    107		return ret;
    108	}
    109
    110	return 0;
    111}
    112
    113static int icn8505_write_xfer(struct i2c_client *client, u16 i2c_addr,
    114			      int reg_addr, int reg_addr_width,
    115			      const void *data, int len, bool silent)
    116{
    117	u8 buf[3 + 32]; /* 3 bytes for 24 bit reg-addr + 32 bytes max len */
    118	int i, ret;
    119	struct i2c_msg msg = {
    120		.addr = i2c_addr,
    121		.buf = buf,
    122		.len = reg_addr_width / 8 + len,
    123	};
    124
    125	if (WARN_ON(len > 32))
    126		return -EINVAL;
    127
    128	for (i = 0; i < (reg_addr_width / 8); i++)
    129		buf[i] = (reg_addr >> (reg_addr_width - (i + 1) * 8)) & 0xff;
    130
    131	memcpy(buf + reg_addr_width / 8, data, len);
    132
    133	ret = i2c_transfer(client->adapter, &msg, 1);
    134	if (ret != 1) {
    135		if (ret >= 0)
    136			ret = -EIO;
    137		if (!silent)
    138			dev_err(&client->dev,
    139				"Error writing addr %#x reg %#x: %d\n",
    140				i2c_addr, reg_addr, ret);
    141		return ret;
    142	}
    143
    144	return 0;
    145}
    146
    147static int icn8505_read_data(struct icn8505_data *icn8505, int reg,
    148			     void *buf, int len)
    149{
    150	return icn8505_read_xfer(icn8505->client, icn8505->client->addr, reg,
    151				 ICN8505_REG_ADDR_WIDTH, buf, len, false);
    152}
    153
    154static int icn8505_read_reg_silent(struct icn8505_data *icn8505, int reg)
    155{
    156	u8 buf;
    157	int error;
    158
    159	error = icn8505_read_xfer(icn8505->client, icn8505->client->addr, reg,
    160				  ICN8505_REG_ADDR_WIDTH, &buf, 1, true);
    161	if (error)
    162		return error;
    163
    164	return buf;
    165}
    166
    167static int icn8505_write_reg(struct icn8505_data *icn8505, int reg, u8 val)
    168{
    169	return icn8505_write_xfer(icn8505->client, icn8505->client->addr, reg,
    170				  ICN8505_REG_ADDR_WIDTH, &val, 1, false);
    171}
    172
    173static int icn8505_read_prog_data(struct icn8505_data *icn8505, int reg,
    174				  void *buf, int len)
    175{
    176	return icn8505_read_xfer(icn8505->client, ICN8505_PROG_I2C_ADDR, reg,
    177				 ICN8505_PROG_REG_ADDR_WIDTH, buf, len, false);
    178}
    179
    180static int icn8505_write_prog_data(struct icn8505_data *icn8505, int reg,
    181				   const void *buf, int len)
    182{
    183	return icn8505_write_xfer(icn8505->client, ICN8505_PROG_I2C_ADDR, reg,
    184				  ICN8505_PROG_REG_ADDR_WIDTH, buf, len, false);
    185}
    186
    187static int icn8505_write_prog_reg(struct icn8505_data *icn8505, int reg, u8 val)
    188{
    189	return icn8505_write_xfer(icn8505->client, ICN8505_PROG_I2C_ADDR, reg,
    190				  ICN8505_PROG_REG_ADDR_WIDTH, &val, 1, false);
    191}
    192
    193/*
    194 * Note this function uses a number of magic register addresses and values,
    195 * there are deliberately no defines for these because the algorithm is taken
    196 * from the icn85xx Android driver and I do not want to make up possibly wrong
    197 * names for the addresses and/or values.
    198 */
    199static int icn8505_try_fw_upload(struct icn8505_data *icn8505,
    200				 const struct firmware *fw)
    201{
    202	struct device *dev = &icn8505->client->dev;
    203	size_t offset, count;
    204	int error;
    205	u8 buf[4];
    206	u32 crc;
    207
    208	/* Put the controller in programming mode */
    209	error = icn8505_write_prog_reg(icn8505, 0xcc3355, 0x5a);
    210	if (error)
    211		return error;
    212
    213	usleep_range(2000, 5000);
    214
    215	error = icn8505_write_prog_reg(icn8505, 0x040400, 0x01);
    216	if (error)
    217		return error;
    218
    219	usleep_range(2000, 5000);
    220
    221	error = icn8505_read_prog_data(icn8505, 0x040002, buf, 1);
    222	if (error)
    223		return error;
    224
    225	if (buf[0] != 0x85) {
    226		dev_err(dev, "Failed to enter programming mode\n");
    227		return -ENODEV;
    228	}
    229
    230	usleep_range(1000, 5000);
    231
    232	/* Enable CRC mode */
    233	error = icn8505_write_prog_reg(icn8505, 0x40028, 1);
    234	if (error)
    235		return error;
    236
    237	/* Send the firmware to SRAM */
    238	for (offset = 0; offset < fw->size; offset += count) {
    239		count = min_t(size_t, fw->size - offset, 32);
    240		error = icn8505_write_prog_data(icn8505, offset,
    241					      fw->data + offset, count);
    242		if (error)
    243			return error;
    244	}
    245
    246	/* Disable CRC mode */
    247	error = icn8505_write_prog_reg(icn8505, 0x40028, 0);
    248	if (error)
    249		return error;
    250
    251	/* Get and check length and CRC */
    252	error = icn8505_read_prog_data(icn8505, 0x40034, buf, 2);
    253	if (error)
    254		return error;
    255
    256	if (get_unaligned_le16(buf) != fw->size) {
    257		dev_warn(dev, "Length mismatch after uploading fw\n");
    258		return -EIO;
    259	}
    260
    261	error = icn8505_read_prog_data(icn8505, 0x4002c, buf, 4);
    262	if (error)
    263		return error;
    264
    265	crc = crc32_be(0, fw->data, fw->size);
    266	if (get_unaligned_le32(buf) != crc) {
    267		dev_warn(dev, "CRC mismatch after uploading fw\n");
    268		return -EIO;
    269	}
    270
    271	/* Boot controller from SRAM */
    272	error = icn8505_write_prog_reg(icn8505, 0x40400, 0x03);
    273	if (error)
    274		return error;
    275
    276	usleep_range(2000, 5000);
    277	return 0;
    278}
    279
    280static int icn8505_upload_fw(struct icn8505_data *icn8505)
    281{
    282	struct device *dev = &icn8505->client->dev;
    283	const struct firmware *fw;
    284	int i, error;
    285
    286	/*
    287	 * Always load the firmware, even if we don't need it at boot, we
    288	 * we may need it at resume. Having loaded it once will make the
    289	 * firmware class code cache it at suspend/resume.
    290	 */
    291	error = firmware_request_platform(&fw, icn8505->firmware_name, dev);
    292	if (error) {
    293		dev_err(dev, "Firmware request error %d\n", error);
    294		return error;
    295	}
    296
    297	/* Check if the controller is not already up and running */
    298	if (icn8505_read_reg_silent(icn8505, 0x000a) == 0x85)
    299		goto success;
    300
    301	for (i = 1; i <= MAX_FW_UPLOAD_TRIES; i++) {
    302		error = icn8505_try_fw_upload(icn8505, fw);
    303		if (!error)
    304			goto success;
    305
    306		dev_err(dev, "Failed to upload firmware: %d (attempt %d/%d)\n",
    307			error, i, MAX_FW_UPLOAD_TRIES);
    308		usleep_range(2000, 5000);
    309	}
    310
    311success:
    312	release_firmware(fw);
    313	return error;
    314}
    315
    316static bool icn8505_touch_active(u8 event)
    317{
    318	return event == ICN8505_EVENT_UPDATE1 ||
    319	       event == ICN8505_EVENT_UPDATE2;
    320}
    321
    322static irqreturn_t icn8505_irq(int irq, void *dev_id)
    323{
    324	struct icn8505_data *icn8505 = dev_id;
    325	struct device *dev = &icn8505->client->dev;
    326	struct icn8505_touch_data touch_data;
    327	int i, error;
    328
    329	error = icn8505_read_data(icn8505, ICN8505_REG_TOUCHDATA,
    330				  &touch_data, sizeof(touch_data));
    331	if (error) {
    332		dev_err(dev, "Error reading touch data: %d\n", error);
    333		return IRQ_HANDLED;
    334	}
    335
    336	if (touch_data.touch_count > ICN8505_MAX_TOUCHES) {
    337		dev_warn(dev, "Too many touches %d > %d\n",
    338			 touch_data.touch_count, ICN8505_MAX_TOUCHES);
    339		touch_data.touch_count = ICN8505_MAX_TOUCHES;
    340	}
    341
    342	for (i = 0; i < touch_data.touch_count; i++) {
    343		struct icn8505_touch *touch = &touch_data.touches[i];
    344		bool act = icn8505_touch_active(touch->event);
    345
    346		input_mt_slot(icn8505->input, touch->slot);
    347		input_mt_report_slot_state(icn8505->input, MT_TOOL_FINGER, act);
    348		if (!act)
    349			continue;
    350
    351		touchscreen_report_pos(icn8505->input, &icn8505->prop,
    352				       get_unaligned_le16(touch->x),
    353				       get_unaligned_le16(touch->y),
    354				       true);
    355	}
    356
    357	input_mt_sync_frame(icn8505->input);
    358	input_report_key(icn8505->input, KEY_LEFTMETA,
    359			 touch_data.softbutton == 1);
    360	input_sync(icn8505->input);
    361
    362	return IRQ_HANDLED;
    363}
    364
    365static int icn8505_probe_acpi(struct icn8505_data *icn8505, struct device *dev)
    366{
    367	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
    368	const char *subsys = "unknown";
    369	struct acpi_device *adev;
    370	union acpi_object *obj;
    371	acpi_status status;
    372
    373	adev = ACPI_COMPANION(dev);
    374	if (!adev)
    375		return -ENODEV;
    376
    377	status = acpi_evaluate_object(adev->handle, "_SUB", NULL, &buffer);
    378	if (ACPI_SUCCESS(status)) {
    379		obj = buffer.pointer;
    380		if (obj->type == ACPI_TYPE_STRING)
    381			subsys = obj->string.pointer;
    382		else
    383			dev_warn(dev, "Warning ACPI _SUB did not return a string\n");
    384	} else {
    385		dev_warn(dev, "Warning ACPI _SUB failed: %#x\n", status);
    386		buffer.pointer = NULL;
    387	}
    388
    389	snprintf(icn8505->firmware_name, sizeof(icn8505->firmware_name),
    390		 "chipone/icn8505-%s.fw", subsys);
    391
    392	kfree(buffer.pointer);
    393	return 0;
    394}
    395
    396static int icn8505_probe(struct i2c_client *client)
    397{
    398	struct device *dev = &client->dev;
    399	struct icn8505_data *icn8505;
    400	struct input_dev *input;
    401	__le16 resolution[2];
    402	int error;
    403
    404	if (!client->irq) {
    405		dev_err(dev, "No irq specified\n");
    406		return -EINVAL;
    407	}
    408
    409	icn8505 = devm_kzalloc(dev, sizeof(*icn8505), GFP_KERNEL);
    410	if (!icn8505)
    411		return -ENOMEM;
    412
    413	input = devm_input_allocate_device(dev);
    414	if (!input)
    415		return -ENOMEM;
    416
    417	input->name = client->name;
    418	input->id.bustype = BUS_I2C;
    419
    420	input_set_capability(input, EV_ABS, ABS_MT_POSITION_X);
    421	input_set_capability(input, EV_ABS, ABS_MT_POSITION_Y);
    422	input_set_capability(input, EV_KEY, KEY_LEFTMETA);
    423
    424	icn8505->client = client;
    425	icn8505->input = input;
    426	input_set_drvdata(input, icn8505);
    427
    428	error = icn8505_probe_acpi(icn8505, dev);
    429	if (error)
    430		return error;
    431
    432	error = icn8505_upload_fw(icn8505);
    433	if (error)
    434		return error;
    435
    436	error = icn8505_read_data(icn8505, ICN8505_REG_CONFIGDATA,
    437				resolution, sizeof(resolution));
    438	if (error) {
    439		dev_err(dev, "Error reading resolution: %d\n", error);
    440		return error;
    441	}
    442
    443	input_set_abs_params(input, ABS_MT_POSITION_X, 0,
    444			     le16_to_cpu(resolution[0]) - 1, 0, 0);
    445	input_set_abs_params(input, ABS_MT_POSITION_Y, 0,
    446			     le16_to_cpu(resolution[1]) - 1, 0, 0);
    447
    448	touchscreen_parse_properties(input, true, &icn8505->prop);
    449	if (!input_abs_get_max(input, ABS_MT_POSITION_X) ||
    450	    !input_abs_get_max(input, ABS_MT_POSITION_Y)) {
    451		dev_err(dev, "Error touchscreen-size-x and/or -y missing\n");
    452		return -EINVAL;
    453	}
    454
    455	error = input_mt_init_slots(input, ICN8505_MAX_TOUCHES,
    456				  INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED);
    457	if (error)
    458		return error;
    459
    460	error = devm_request_threaded_irq(dev, client->irq, NULL, icn8505_irq,
    461					IRQF_ONESHOT, client->name, icn8505);
    462	if (error) {
    463		dev_err(dev, "Error requesting irq: %d\n", error);
    464		return error;
    465	}
    466
    467	error = input_register_device(input);
    468	if (error)
    469		return error;
    470
    471	i2c_set_clientdata(client, icn8505);
    472	return 0;
    473}
    474
    475static int __maybe_unused icn8505_suspend(struct device *dev)
    476{
    477	struct icn8505_data *icn8505 = i2c_get_clientdata(to_i2c_client(dev));
    478
    479	disable_irq(icn8505->client->irq);
    480
    481	icn8505_write_reg(icn8505, ICN8505_REG_POWER, ICN8505_POWER_HIBERNATE);
    482
    483	return 0;
    484}
    485
    486static int __maybe_unused icn8505_resume(struct device *dev)
    487{
    488	struct icn8505_data *icn8505 = i2c_get_clientdata(to_i2c_client(dev));
    489	int error;
    490
    491	error = icn8505_upload_fw(icn8505);
    492	if (error)
    493		return error;
    494
    495	enable_irq(icn8505->client->irq);
    496	return 0;
    497}
    498
    499static SIMPLE_DEV_PM_OPS(icn8505_pm_ops, icn8505_suspend, icn8505_resume);
    500
    501static const struct acpi_device_id icn8505_acpi_match[] = {
    502	{ "CHPN0001" },
    503	{ }
    504};
    505MODULE_DEVICE_TABLE(acpi, icn8505_acpi_match);
    506
    507static struct i2c_driver icn8505_driver = {
    508	.driver = {
    509		.name	= "chipone_icn8505",
    510		.pm	= &icn8505_pm_ops,
    511		.acpi_match_table = icn8505_acpi_match,
    512	},
    513	.probe_new = icn8505_probe,
    514};
    515
    516module_i2c_driver(icn8505_driver);
    517
    518MODULE_DESCRIPTION("ChipOne icn8505 I2C Touchscreen Driver");
    519MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
    520MODULE_LICENSE("GPL");