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

surface3_spi.c (9901B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 *  Driver for Ntrig/Microsoft Touchscreens over SPI
      4 *
      5 *  Copyright (c) 2016 Red Hat Inc.
      6 */
      7
      8
      9#include <linux/kernel.h>
     10
     11#include <linux/delay.h>
     12#include <linux/gpio/consumer.h>
     13#include <linux/input.h>
     14#include <linux/input/mt.h>
     15#include <linux/interrupt.h>
     16#include <linux/module.h>
     17#include <linux/slab.h>
     18#include <linux/spi/spi.h>
     19#include <linux/acpi.h>
     20
     21#include <asm/unaligned.h>
     22
     23#define SURFACE3_PACKET_SIZE	264
     24
     25#define SURFACE3_REPORT_TOUCH	0xd2
     26#define SURFACE3_REPORT_PEN	0x16
     27
     28struct surface3_ts_data {
     29	struct spi_device *spi;
     30	struct gpio_desc *gpiod_rst[2];
     31	struct input_dev *input_dev;
     32	struct input_dev *pen_input_dev;
     33	int pen_tool;
     34
     35	u8 rd_buf[SURFACE3_PACKET_SIZE]		____cacheline_aligned;
     36};
     37
     38struct surface3_ts_data_finger {
     39	u8 status;
     40	__le16 tracking_id;
     41	__le16 x;
     42	__le16 cx;
     43	__le16 y;
     44	__le16 cy;
     45	__le16 width;
     46	__le16 height;
     47	u32 padding;
     48} __packed;
     49
     50struct surface3_ts_data_pen {
     51	u8 status;
     52	__le16 x;
     53	__le16 y;
     54	__le16 pressure;
     55	u8 padding;
     56} __packed;
     57
     58static int surface3_spi_read(struct surface3_ts_data *ts_data)
     59{
     60	struct spi_device *spi = ts_data->spi;
     61
     62	memset(ts_data->rd_buf, 0, sizeof(ts_data->rd_buf));
     63	return spi_read(spi, ts_data->rd_buf, sizeof(ts_data->rd_buf));
     64}
     65
     66static void surface3_spi_report_touch(struct surface3_ts_data *ts_data,
     67				   struct surface3_ts_data_finger *finger)
     68{
     69	int st = finger->status & 0x01;
     70	int slot;
     71
     72	slot = input_mt_get_slot_by_key(ts_data->input_dev,
     73				get_unaligned_le16(&finger->tracking_id));
     74	if (slot < 0)
     75		return;
     76
     77	input_mt_slot(ts_data->input_dev, slot);
     78	input_mt_report_slot_state(ts_data->input_dev, MT_TOOL_FINGER, st);
     79	if (st) {
     80		input_report_abs(ts_data->input_dev,
     81				 ABS_MT_POSITION_X,
     82				 get_unaligned_le16(&finger->x));
     83		input_report_abs(ts_data->input_dev,
     84				 ABS_MT_POSITION_Y,
     85				 get_unaligned_le16(&finger->y));
     86		input_report_abs(ts_data->input_dev,
     87				 ABS_MT_WIDTH_MAJOR,
     88				 get_unaligned_le16(&finger->width));
     89		input_report_abs(ts_data->input_dev,
     90				 ABS_MT_WIDTH_MINOR,
     91				 get_unaligned_le16(&finger->height));
     92	}
     93}
     94
     95static void surface3_spi_process_touch(struct surface3_ts_data *ts_data, u8 *data)
     96{
     97	unsigned int i;
     98
     99	for (i = 0; i < 13; i++) {
    100		struct surface3_ts_data_finger *finger;
    101
    102		finger = (struct surface3_ts_data_finger *)&data[17 +
    103				i * sizeof(struct surface3_ts_data_finger)];
    104
    105		/*
    106		 * When bit 5 of status is 1, it marks the end of the report:
    107		 * - touch present: 0xe7
    108		 * - touch released: 0xe4
    109		 * - nothing valuable: 0xff
    110		 */
    111		if (finger->status & 0x10)
    112			break;
    113
    114		surface3_spi_report_touch(ts_data, finger);
    115	}
    116
    117	input_mt_sync_frame(ts_data->input_dev);
    118	input_sync(ts_data->input_dev);
    119}
    120
    121static void surface3_spi_report_pen(struct surface3_ts_data *ts_data,
    122				    struct surface3_ts_data_pen *pen)
    123{
    124	struct input_dev *dev = ts_data->pen_input_dev;
    125	int st = pen->status;
    126	int prox = st & 0x01;
    127	int rubber = st & 0x18;
    128	int tool = (prox && rubber) ? BTN_TOOL_RUBBER : BTN_TOOL_PEN;
    129
    130	/* fake proximity out to switch tools */
    131	if (ts_data->pen_tool != tool) {
    132		input_report_key(dev, ts_data->pen_tool, 0);
    133		input_sync(dev);
    134		ts_data->pen_tool = tool;
    135	}
    136
    137	input_report_key(dev, BTN_TOUCH, st & 0x12);
    138
    139	input_report_key(dev, ts_data->pen_tool, prox);
    140
    141	if (st) {
    142		input_report_key(dev,
    143				 BTN_STYLUS,
    144				 st & 0x04);
    145
    146		input_report_abs(dev,
    147				 ABS_X,
    148				 get_unaligned_le16(&pen->x));
    149		input_report_abs(dev,
    150				 ABS_Y,
    151				 get_unaligned_le16(&pen->y));
    152		input_report_abs(dev,
    153				 ABS_PRESSURE,
    154				 get_unaligned_le16(&pen->pressure));
    155	}
    156}
    157
    158static void surface3_spi_process_pen(struct surface3_ts_data *ts_data, u8 *data)
    159{
    160	struct surface3_ts_data_pen *pen;
    161
    162	pen = (struct surface3_ts_data_pen *)&data[15];
    163
    164	surface3_spi_report_pen(ts_data, pen);
    165	input_sync(ts_data->pen_input_dev);
    166}
    167
    168static void surface3_spi_process(struct surface3_ts_data *ts_data)
    169{
    170	static const char header[] = {
    171		0xff, 0xff, 0xff, 0xff, 0xa5, 0x5a, 0xe7, 0x7e, 0x01
    172	};
    173	u8 *data = ts_data->rd_buf;
    174
    175	if (memcmp(header, data, sizeof(header)))
    176		dev_err(&ts_data->spi->dev,
    177			"%s header error: %*ph, ignoring...\n",
    178			__func__, (int)sizeof(header), data);
    179
    180	switch (data[9]) {
    181	case SURFACE3_REPORT_TOUCH:
    182		surface3_spi_process_touch(ts_data, data);
    183		break;
    184	case SURFACE3_REPORT_PEN:
    185		surface3_spi_process_pen(ts_data, data);
    186		break;
    187	default:
    188		dev_err(&ts_data->spi->dev,
    189			"%s unknown packet type: %x, ignoring...\n",
    190			__func__, data[9]);
    191		break;
    192	}
    193}
    194
    195static irqreturn_t surface3_spi_irq_handler(int irq, void *dev_id)
    196{
    197	struct surface3_ts_data *data = dev_id;
    198
    199	if (surface3_spi_read(data))
    200		return IRQ_HANDLED;
    201
    202	dev_dbg(&data->spi->dev, "%s received -> %*ph\n",
    203		__func__, SURFACE3_PACKET_SIZE, data->rd_buf);
    204	surface3_spi_process(data);
    205
    206	return IRQ_HANDLED;
    207}
    208
    209static void surface3_spi_power(struct surface3_ts_data *data, bool on)
    210{
    211	gpiod_set_value(data->gpiod_rst[0], on);
    212	gpiod_set_value(data->gpiod_rst[1], on);
    213	/* let the device settle a little */
    214	msleep(20);
    215}
    216
    217/**
    218 * surface3_spi_get_gpio_config - Get GPIO config from ACPI/DT
    219 *
    220 * @data: surface3_spi_ts_data pointer
    221 */
    222static int surface3_spi_get_gpio_config(struct surface3_ts_data *data)
    223{
    224	int error;
    225	struct device *dev;
    226	struct gpio_desc *gpiod;
    227	int i;
    228
    229	dev = &data->spi->dev;
    230
    231	/* Get the reset lines GPIO pin number */
    232	for (i = 0; i < 2; i++) {
    233		gpiod = devm_gpiod_get_index(dev, NULL, i, GPIOD_OUT_LOW);
    234		if (IS_ERR(gpiod)) {
    235			error = PTR_ERR(gpiod);
    236			if (error != -EPROBE_DEFER)
    237				dev_err(dev,
    238					"Failed to get power GPIO %d: %d\n",
    239					i,
    240					error);
    241			return error;
    242		}
    243
    244		data->gpiod_rst[i] = gpiod;
    245	}
    246
    247	return 0;
    248}
    249
    250static int surface3_spi_create_touch_input(struct surface3_ts_data *data)
    251{
    252	struct input_dev *input;
    253	int error;
    254
    255	input = devm_input_allocate_device(&data->spi->dev);
    256	if (!input)
    257		return -ENOMEM;
    258
    259	data->input_dev = input;
    260
    261	input_set_abs_params(input, ABS_MT_POSITION_X, 0, 9600, 0, 0);
    262	input_abs_set_res(input, ABS_MT_POSITION_X, 40);
    263	input_set_abs_params(input, ABS_MT_POSITION_Y, 0, 7200, 0, 0);
    264	input_abs_set_res(input, ABS_MT_POSITION_Y, 48);
    265	input_set_abs_params(input, ABS_MT_WIDTH_MAJOR, 0, 1024, 0, 0);
    266	input_set_abs_params(input, ABS_MT_WIDTH_MINOR, 0, 1024, 0, 0);
    267	input_mt_init_slots(input, 10, INPUT_MT_DIRECT);
    268
    269	input->name = "Surface3 SPI Capacitive TouchScreen";
    270	input->phys = "input/ts";
    271	input->id.bustype = BUS_SPI;
    272	input->id.vendor = 0x045e;	/* Microsoft */
    273	input->id.product = 0x0001;
    274	input->id.version = 0x0000;
    275
    276	error = input_register_device(input);
    277	if (error) {
    278		dev_err(&data->spi->dev,
    279			"Failed to register input device: %d", error);
    280		return error;
    281	}
    282
    283	return 0;
    284}
    285
    286static int surface3_spi_create_pen_input(struct surface3_ts_data *data)
    287{
    288	struct input_dev *input;
    289	int error;
    290
    291	input = devm_input_allocate_device(&data->spi->dev);
    292	if (!input)
    293		return -ENOMEM;
    294
    295	data->pen_input_dev = input;
    296	data->pen_tool = BTN_TOOL_PEN;
    297
    298	__set_bit(INPUT_PROP_DIRECT, input->propbit);
    299	__set_bit(INPUT_PROP_POINTER, input->propbit);
    300	input_set_abs_params(input, ABS_X, 0, 9600, 0, 0);
    301	input_abs_set_res(input, ABS_X, 40);
    302	input_set_abs_params(input, ABS_Y, 0, 7200, 0, 0);
    303	input_abs_set_res(input, ABS_Y, 48);
    304	input_set_abs_params(input, ABS_PRESSURE, 0, 1024, 0, 0);
    305	input_set_capability(input, EV_KEY, BTN_TOUCH);
    306	input_set_capability(input, EV_KEY, BTN_STYLUS);
    307	input_set_capability(input, EV_KEY, BTN_TOOL_PEN);
    308	input_set_capability(input, EV_KEY, BTN_TOOL_RUBBER);
    309
    310	input->name = "Surface3 SPI Pen Input";
    311	input->phys = "input/ts";
    312	input->id.bustype = BUS_SPI;
    313	input->id.vendor = 0x045e;     /* Microsoft */
    314	input->id.product = 0x0002;
    315	input->id.version = 0x0000;
    316
    317	error = input_register_device(input);
    318	if (error) {
    319		dev_err(&data->spi->dev,
    320			"Failed to register input device: %d", error);
    321		return error;
    322	}
    323
    324	return 0;
    325}
    326
    327static int surface3_spi_probe(struct spi_device *spi)
    328{
    329	struct surface3_ts_data *data;
    330	int error;
    331
    332	/* Set up SPI*/
    333	spi->bits_per_word = 8;
    334	spi->mode = SPI_MODE_0;
    335	error = spi_setup(spi);
    336	if (error)
    337		return error;
    338
    339	data = devm_kzalloc(&spi->dev, sizeof(*data), GFP_KERNEL);
    340	if (!data)
    341		return -ENOMEM;
    342
    343	data->spi = spi;
    344	spi_set_drvdata(spi, data);
    345
    346	error = surface3_spi_get_gpio_config(data);
    347	if (error)
    348		return error;
    349
    350	surface3_spi_power(data, true);
    351	surface3_spi_power(data, false);
    352	surface3_spi_power(data, true);
    353
    354	error = surface3_spi_create_touch_input(data);
    355	if (error)
    356		return error;
    357
    358	error = surface3_spi_create_pen_input(data);
    359	if (error)
    360		return error;
    361
    362	error = devm_request_threaded_irq(&spi->dev, spi->irq,
    363					  NULL, surface3_spi_irq_handler,
    364					  IRQF_ONESHOT,
    365					  "Surface3-irq", data);
    366	if (error)
    367		return error;
    368
    369	return 0;
    370}
    371
    372static int __maybe_unused surface3_spi_suspend(struct device *dev)
    373{
    374	struct spi_device *spi = to_spi_device(dev);
    375	struct surface3_ts_data *data = spi_get_drvdata(spi);
    376
    377	disable_irq(data->spi->irq);
    378
    379	surface3_spi_power(data, false);
    380
    381	return 0;
    382}
    383
    384static int __maybe_unused surface3_spi_resume(struct device *dev)
    385{
    386	struct spi_device *spi = to_spi_device(dev);
    387	struct surface3_ts_data *data = spi_get_drvdata(spi);
    388
    389	surface3_spi_power(data, true);
    390
    391	enable_irq(data->spi->irq);
    392
    393	return 0;
    394}
    395
    396static SIMPLE_DEV_PM_OPS(surface3_spi_pm_ops,
    397			 surface3_spi_suspend,
    398			 surface3_spi_resume);
    399
    400#ifdef CONFIG_ACPI
    401static const struct acpi_device_id surface3_spi_acpi_match[] = {
    402	{ "MSHW0037", 0 },
    403	{ }
    404};
    405MODULE_DEVICE_TABLE(acpi, surface3_spi_acpi_match);
    406#endif
    407
    408static struct spi_driver surface3_spi_driver = {
    409	.driver = {
    410		.name	= "Surface3-spi",
    411		.acpi_match_table = ACPI_PTR(surface3_spi_acpi_match),
    412		.pm = &surface3_spi_pm_ops,
    413	},
    414	.probe = surface3_spi_probe,
    415};
    416
    417module_spi_driver(surface3_spi_driver);
    418
    419MODULE_AUTHOR("Benjamin Tissoires <benjamin.tissoires@gmail.com>");
    420MODULE_DESCRIPTION("Surface 3 SPI touchscreen driver");
    421MODULE_LICENSE("GPL v2");