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

rmi_f30.c (10773B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * Copyright (c) 2012-2016 Synaptics Incorporated
      4 */
      5
      6#include <linux/kernel.h>
      7#include <linux/rmi.h>
      8#include <linux/input.h>
      9#include <linux/slab.h>
     10#include "rmi_driver.h"
     11
     12#define RMI_F30_QUERY_SIZE			2
     13
     14/* Defs for Query 0 */
     15#define RMI_F30_EXTENDED_PATTERNS		0x01
     16#define RMI_F30_HAS_MAPPABLE_BUTTONS		BIT(1)
     17#define RMI_F30_HAS_LED				BIT(2)
     18#define RMI_F30_HAS_GPIO			BIT(3)
     19#define RMI_F30_HAS_HAPTIC			BIT(4)
     20#define RMI_F30_HAS_GPIO_DRV_CTL		BIT(5)
     21#define RMI_F30_HAS_MECH_MOUSE_BTNS		BIT(6)
     22
     23/* Defs for Query 1 */
     24#define RMI_F30_GPIO_LED_COUNT			0x1F
     25
     26/* Defs for Control Registers */
     27#define RMI_F30_CTRL_1_GPIO_DEBOUNCE		0x01
     28#define RMI_F30_CTRL_1_HALT			BIT(4)
     29#define RMI_F30_CTRL_1_HALTED			BIT(5)
     30#define RMI_F30_CTRL_10_NUM_MECH_MOUSE_BTNS	0x03
     31
     32#define RMI_F30_CTRL_MAX_REGS		32
     33#define RMI_F30_CTRL_MAX_BYTES		DIV_ROUND_UP(RMI_F30_CTRL_MAX_REGS, 8)
     34#define RMI_F30_CTRL_MAX_REG_BLOCKS	11
     35
     36#define RMI_F30_CTRL_REGS_MAX_SIZE (RMI_F30_CTRL_MAX_BYTES		\
     37					+ 1				\
     38					+ RMI_F30_CTRL_MAX_BYTES	\
     39					+ RMI_F30_CTRL_MAX_BYTES	\
     40					+ RMI_F30_CTRL_MAX_BYTES	\
     41					+ 6				\
     42					+ RMI_F30_CTRL_MAX_REGS		\
     43					+ RMI_F30_CTRL_MAX_REGS		\
     44					+ RMI_F30_CTRL_MAX_BYTES	\
     45					+ 1				\
     46					+ 1)
     47
     48#define TRACKSTICK_RANGE_START		3
     49#define TRACKSTICK_RANGE_END		6
     50
     51struct rmi_f30_ctrl_data {
     52	int address;
     53	int length;
     54	u8 *regs;
     55};
     56
     57struct f30_data {
     58	/* Query Data */
     59	bool has_extended_pattern;
     60	bool has_mappable_buttons;
     61	bool has_led;
     62	bool has_gpio;
     63	bool has_haptic;
     64	bool has_gpio_driver_control;
     65	bool has_mech_mouse_btns;
     66	u8 gpioled_count;
     67
     68	u8 register_count;
     69
     70	/* Control Register Data */
     71	struct rmi_f30_ctrl_data ctrl[RMI_F30_CTRL_MAX_REG_BLOCKS];
     72	u8 ctrl_regs[RMI_F30_CTRL_REGS_MAX_SIZE];
     73	u32 ctrl_regs_size;
     74
     75	u8 data_regs[RMI_F30_CTRL_MAX_BYTES];
     76	u16 *gpioled_key_map;
     77
     78	struct input_dev *input;
     79
     80	struct rmi_function *f03;
     81	bool trackstick_buttons;
     82};
     83
     84static int rmi_f30_read_control_parameters(struct rmi_function *fn,
     85						struct f30_data *f30)
     86{
     87	int error;
     88
     89	error = rmi_read_block(fn->rmi_dev, fn->fd.control_base_addr,
     90			       f30->ctrl_regs, f30->ctrl_regs_size);
     91	if (error) {
     92		dev_err(&fn->dev,
     93			"%s: Could not read control registers at 0x%x: %d\n",
     94			__func__, fn->fd.control_base_addr, error);
     95		return error;
     96	}
     97
     98	return 0;
     99}
    100
    101static void rmi_f30_report_button(struct rmi_function *fn,
    102				  struct f30_data *f30, unsigned int button)
    103{
    104	unsigned int reg_num = button >> 3;
    105	unsigned int bit_num = button & 0x07;
    106	u16 key_code = f30->gpioled_key_map[button];
    107	bool key_down = !(f30->data_regs[reg_num] & BIT(bit_num));
    108
    109	if (f30->trackstick_buttons &&
    110	    button >= TRACKSTICK_RANGE_START &&
    111	    button <= TRACKSTICK_RANGE_END) {
    112		rmi_f03_overwrite_button(f30->f03, key_code, key_down);
    113	} else {
    114		rmi_dbg(RMI_DEBUG_FN, &fn->dev,
    115			"%s: call input report key (0x%04x) value (0x%02x)",
    116			__func__, key_code, key_down);
    117
    118		input_report_key(f30->input, key_code, key_down);
    119	}
    120}
    121
    122static irqreturn_t rmi_f30_attention(int irq, void *ctx)
    123{
    124	struct rmi_function *fn = ctx;
    125	struct f30_data *f30 = dev_get_drvdata(&fn->dev);
    126	struct rmi_driver_data *drvdata = dev_get_drvdata(&fn->rmi_dev->dev);
    127	int error;
    128	int i;
    129
    130	/* Read the gpi led data. */
    131	if (drvdata->attn_data.data) {
    132		if (drvdata->attn_data.size < f30->register_count) {
    133			dev_warn(&fn->dev,
    134				 "F30 interrupted, but data is missing\n");
    135			return IRQ_HANDLED;
    136		}
    137		memcpy(f30->data_regs, drvdata->attn_data.data,
    138			f30->register_count);
    139		drvdata->attn_data.data += f30->register_count;
    140		drvdata->attn_data.size -= f30->register_count;
    141	} else {
    142		error = rmi_read_block(fn->rmi_dev, fn->fd.data_base_addr,
    143				       f30->data_regs, f30->register_count);
    144		if (error) {
    145			dev_err(&fn->dev,
    146				"%s: Failed to read F30 data registers: %d\n",
    147				__func__, error);
    148			return IRQ_RETVAL(error);
    149		}
    150	}
    151
    152	if (f30->has_gpio) {
    153		for (i = 0; i < f30->gpioled_count; i++)
    154			if (f30->gpioled_key_map[i] != KEY_RESERVED)
    155				rmi_f30_report_button(fn, f30, i);
    156		if (f30->trackstick_buttons)
    157			rmi_f03_commit_buttons(f30->f03);
    158	}
    159
    160	return IRQ_HANDLED;
    161}
    162
    163static int rmi_f30_config(struct rmi_function *fn)
    164{
    165	struct f30_data *f30 = dev_get_drvdata(&fn->dev);
    166	struct rmi_driver *drv = fn->rmi_dev->driver;
    167	const struct rmi_device_platform_data *pdata =
    168				rmi_get_platform_data(fn->rmi_dev);
    169	int error;
    170
    171	/* can happen if gpio_data.disable is set */
    172	if (!f30)
    173		return 0;
    174
    175	if (pdata->gpio_data.trackstick_buttons) {
    176		/* Try [re-]establish link to F03. */
    177		f30->f03 = rmi_find_function(fn->rmi_dev, 0x03);
    178		f30->trackstick_buttons = f30->f03 != NULL;
    179	}
    180
    181	if (pdata->gpio_data.disable) {
    182		drv->clear_irq_bits(fn->rmi_dev, fn->irq_mask);
    183	} else {
    184		/* Write Control Register values back to device */
    185		error = rmi_write_block(fn->rmi_dev, fn->fd.control_base_addr,
    186					f30->ctrl_regs, f30->ctrl_regs_size);
    187		if (error) {
    188			dev_err(&fn->dev,
    189				"%s: Could not write control registers at 0x%x: %d\n",
    190				__func__, fn->fd.control_base_addr, error);
    191			return error;
    192		}
    193
    194		drv->set_irq_bits(fn->rmi_dev, fn->irq_mask);
    195	}
    196
    197	return 0;
    198}
    199
    200static void rmi_f30_set_ctrl_data(struct rmi_f30_ctrl_data *ctrl,
    201				  int *ctrl_addr, int len, u8 **reg)
    202{
    203	ctrl->address = *ctrl_addr;
    204	ctrl->length = len;
    205	ctrl->regs = *reg;
    206	*ctrl_addr += len;
    207	*reg += len;
    208}
    209
    210static bool rmi_f30_is_valid_button(int button, struct rmi_f30_ctrl_data *ctrl)
    211{
    212	int byte_position = button >> 3;
    213	int bit_position = button & 0x07;
    214
    215	/*
    216	 * ctrl2 -> dir == 0 -> input mode
    217	 * ctrl3 -> data == 1 -> actual button
    218	 */
    219	return !(ctrl[2].regs[byte_position] & BIT(bit_position)) &&
    220		(ctrl[3].regs[byte_position] & BIT(bit_position));
    221}
    222
    223static int rmi_f30_map_gpios(struct rmi_function *fn,
    224			     struct f30_data *f30)
    225{
    226	const struct rmi_device_platform_data *pdata =
    227					rmi_get_platform_data(fn->rmi_dev);
    228	struct input_dev *input = f30->input;
    229	unsigned int button = BTN_LEFT;
    230	unsigned int trackstick_button = BTN_LEFT;
    231	bool button_mapped = false;
    232	int i;
    233	int button_count = min_t(u8, f30->gpioled_count, TRACKSTICK_RANGE_END);
    234
    235	f30->gpioled_key_map = devm_kcalloc(&fn->dev,
    236					    button_count,
    237					    sizeof(f30->gpioled_key_map[0]),
    238					    GFP_KERNEL);
    239	if (!f30->gpioled_key_map) {
    240		dev_err(&fn->dev, "Failed to allocate gpioled map memory.\n");
    241		return -ENOMEM;
    242	}
    243
    244	for (i = 0; i < button_count; i++) {
    245		if (!rmi_f30_is_valid_button(i, f30->ctrl))
    246			continue;
    247
    248		if (pdata->gpio_data.trackstick_buttons &&
    249		    i >= TRACKSTICK_RANGE_START && i < TRACKSTICK_RANGE_END) {
    250			f30->gpioled_key_map[i] = trackstick_button++;
    251		} else if (!pdata->gpio_data.buttonpad || !button_mapped) {
    252			f30->gpioled_key_map[i] = button;
    253			input_set_capability(input, EV_KEY, button++);
    254			button_mapped = true;
    255		}
    256	}
    257
    258	input->keycode = f30->gpioled_key_map;
    259	input->keycodesize = sizeof(f30->gpioled_key_map[0]);
    260	input->keycodemax = f30->gpioled_count;
    261
    262	/*
    263	 * Buttonpad could be also inferred from f30->has_mech_mouse_btns,
    264	 * but I am not sure, so use only the pdata info and the number of
    265	 * mapped buttons.
    266	 */
    267	if (pdata->gpio_data.buttonpad || (button - BTN_LEFT == 1))
    268		__set_bit(INPUT_PROP_BUTTONPAD, input->propbit);
    269
    270	return 0;
    271}
    272
    273static int rmi_f30_initialize(struct rmi_function *fn, struct f30_data *f30)
    274{
    275	u8 *ctrl_reg = f30->ctrl_regs;
    276	int control_address = fn->fd.control_base_addr;
    277	u8 buf[RMI_F30_QUERY_SIZE];
    278	int error;
    279
    280	error = rmi_read_block(fn->rmi_dev, fn->fd.query_base_addr,
    281			       buf, RMI_F30_QUERY_SIZE);
    282	if (error) {
    283		dev_err(&fn->dev, "Failed to read query register\n");
    284		return error;
    285	}
    286
    287	f30->has_extended_pattern = buf[0] & RMI_F30_EXTENDED_PATTERNS;
    288	f30->has_mappable_buttons = buf[0] & RMI_F30_HAS_MAPPABLE_BUTTONS;
    289	f30->has_led = buf[0] & RMI_F30_HAS_LED;
    290	f30->has_gpio = buf[0] & RMI_F30_HAS_GPIO;
    291	f30->has_haptic = buf[0] & RMI_F30_HAS_HAPTIC;
    292	f30->has_gpio_driver_control = buf[0] & RMI_F30_HAS_GPIO_DRV_CTL;
    293	f30->has_mech_mouse_btns = buf[0] & RMI_F30_HAS_MECH_MOUSE_BTNS;
    294	f30->gpioled_count = buf[1] & RMI_F30_GPIO_LED_COUNT;
    295
    296	f30->register_count = DIV_ROUND_UP(f30->gpioled_count, 8);
    297
    298	if (f30->has_gpio && f30->has_led)
    299		rmi_f30_set_ctrl_data(&f30->ctrl[0], &control_address,
    300				      f30->register_count, &ctrl_reg);
    301
    302	rmi_f30_set_ctrl_data(&f30->ctrl[1], &control_address,
    303			      sizeof(u8), &ctrl_reg);
    304
    305	if (f30->has_gpio) {
    306		rmi_f30_set_ctrl_data(&f30->ctrl[2], &control_address,
    307				      f30->register_count, &ctrl_reg);
    308
    309		rmi_f30_set_ctrl_data(&f30->ctrl[3], &control_address,
    310				      f30->register_count, &ctrl_reg);
    311	}
    312
    313	if (f30->has_led) {
    314		rmi_f30_set_ctrl_data(&f30->ctrl[4], &control_address,
    315				      f30->register_count, &ctrl_reg);
    316
    317		rmi_f30_set_ctrl_data(&f30->ctrl[5], &control_address,
    318				      f30->has_extended_pattern ? 6 : 2,
    319				      &ctrl_reg);
    320	}
    321
    322	if (f30->has_led || f30->has_gpio_driver_control) {
    323		/* control 6 uses a byte per gpio/led */
    324		rmi_f30_set_ctrl_data(&f30->ctrl[6], &control_address,
    325				      f30->gpioled_count, &ctrl_reg);
    326	}
    327
    328	if (f30->has_mappable_buttons) {
    329		/* control 7 uses a byte per gpio/led */
    330		rmi_f30_set_ctrl_data(&f30->ctrl[7], &control_address,
    331				      f30->gpioled_count, &ctrl_reg);
    332	}
    333
    334	if (f30->has_haptic) {
    335		rmi_f30_set_ctrl_data(&f30->ctrl[8], &control_address,
    336				      f30->register_count, &ctrl_reg);
    337
    338		rmi_f30_set_ctrl_data(&f30->ctrl[9], &control_address,
    339				      sizeof(u8), &ctrl_reg);
    340	}
    341
    342	if (f30->has_mech_mouse_btns)
    343		rmi_f30_set_ctrl_data(&f30->ctrl[10], &control_address,
    344				      sizeof(u8), &ctrl_reg);
    345
    346	f30->ctrl_regs_size = ctrl_reg -
    347				f30->ctrl_regs ?: RMI_F30_CTRL_REGS_MAX_SIZE;
    348
    349	error = rmi_f30_read_control_parameters(fn, f30);
    350	if (error) {
    351		dev_err(&fn->dev,
    352			"Failed to initialize F30 control params: %d\n",
    353			error);
    354		return error;
    355	}
    356
    357	if (f30->has_gpio) {
    358		error = rmi_f30_map_gpios(fn, f30);
    359		if (error)
    360			return error;
    361	}
    362
    363	return 0;
    364}
    365
    366static int rmi_f30_probe(struct rmi_function *fn)
    367{
    368	struct rmi_device *rmi_dev = fn->rmi_dev;
    369	const struct rmi_device_platform_data *pdata =
    370					rmi_get_platform_data(rmi_dev);
    371	struct rmi_driver_data *drv_data = dev_get_drvdata(&rmi_dev->dev);
    372	struct f30_data *f30;
    373	int error;
    374
    375	if (pdata->gpio_data.disable)
    376		return 0;
    377
    378	if (!drv_data->input) {
    379		dev_info(&fn->dev, "F30: no input device found, ignoring\n");
    380		return -ENXIO;
    381	}
    382
    383	f30 = devm_kzalloc(&fn->dev, sizeof(*f30), GFP_KERNEL);
    384	if (!f30)
    385		return -ENOMEM;
    386
    387	f30->input = drv_data->input;
    388
    389	error = rmi_f30_initialize(fn, f30);
    390	if (error)
    391		return error;
    392
    393	dev_set_drvdata(&fn->dev, f30);
    394	return 0;
    395}
    396
    397struct rmi_function_handler rmi_f30_handler = {
    398	.driver = {
    399		.name = "rmi4_f30",
    400	},
    401	.func = 0x30,
    402	.probe = rmi_f30_probe,
    403	.config = rmi_f30_config,
    404	.attention = rmi_f30_attention,
    405};