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

sentelic.c (25451B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*-
      3 * Finger Sensing Pad PS/2 mouse driver.
      4 *
      5 * Copyright (C) 2005-2007 Asia Vital Components Co., Ltd.
      6 * Copyright (C) 2005-2012 Tai-hwa Liang, Sentelic Corporation.
      7 */
      8
      9#include <linux/module.h>
     10#include <linux/input.h>
     11#include <linux/input/mt.h>
     12#include <linux/ctype.h>
     13#include <linux/libps2.h>
     14#include <linux/serio.h>
     15#include <linux/jiffies.h>
     16#include <linux/slab.h>
     17
     18#include "psmouse.h"
     19#include "sentelic.h"
     20
     21/*
     22 * Timeout for FSP PS/2 command only (in milliseconds).
     23 */
     24#define	FSP_CMD_TIMEOUT		200
     25#define	FSP_CMD_TIMEOUT2	30
     26
     27#define	GET_ABS_X(packet)	((packet[1] << 2) | ((packet[3] >> 2) & 0x03))
     28#define	GET_ABS_Y(packet)	((packet[2] << 2) | (packet[3] & 0x03))
     29
     30/** Driver version. */
     31static const char fsp_drv_ver[] = "1.1.0-K";
     32
     33/*
     34 * Make sure that the value being sent to FSP will not conflict with
     35 * possible sample rate values.
     36 */
     37static unsigned char fsp_test_swap_cmd(unsigned char reg_val)
     38{
     39	switch (reg_val) {
     40	case 10: case 20: case 40: case 60: case 80: case 100: case 200:
     41		/*
     42		 * The requested value being sent to FSP matched to possible
     43		 * sample rates, swap the given value such that the hardware
     44		 * wouldn't get confused.
     45		 */
     46		return (reg_val >> 4) | (reg_val << 4);
     47	default:
     48		return reg_val;	/* swap isn't necessary */
     49	}
     50}
     51
     52/*
     53 * Make sure that the value being sent to FSP will not conflict with certain
     54 * commands.
     55 */
     56static unsigned char fsp_test_invert_cmd(unsigned char reg_val)
     57{
     58	switch (reg_val) {
     59	case 0xe9: case 0xee: case 0xf2: case 0xff:
     60		/*
     61		 * The requested value being sent to FSP matched to certain
     62		 * commands, inverse the given value such that the hardware
     63		 * wouldn't get confused.
     64		 */
     65		return ~reg_val;
     66	default:
     67		return reg_val;	/* inversion isn't necessary */
     68	}
     69}
     70
     71static int fsp_reg_read(struct psmouse *psmouse, int reg_addr, int *reg_val)
     72{
     73	struct ps2dev *ps2dev = &psmouse->ps2dev;
     74	unsigned char param[3];
     75	unsigned char addr;
     76	int rc = -1;
     77
     78	/*
     79	 * We need to shut off the device and switch it into command
     80	 * mode so we don't confuse our protocol handler. We don't need
     81	 * to do that for writes because sysfs set helper does this for
     82	 * us.
     83	 */
     84	psmouse_deactivate(psmouse);
     85
     86	ps2_begin_command(ps2dev);
     87
     88	if (ps2_sendbyte(ps2dev, 0xf3, FSP_CMD_TIMEOUT) < 0)
     89		goto out;
     90
     91	/* should return 0xfe(request for resending) */
     92	ps2_sendbyte(ps2dev, 0x66, FSP_CMD_TIMEOUT2);
     93	/* should return 0xfc(failed) */
     94	ps2_sendbyte(ps2dev, 0x88, FSP_CMD_TIMEOUT2);
     95
     96	if (ps2_sendbyte(ps2dev, 0xf3, FSP_CMD_TIMEOUT) < 0)
     97		goto out;
     98
     99	if ((addr = fsp_test_invert_cmd(reg_addr)) != reg_addr) {
    100		ps2_sendbyte(ps2dev, 0x68, FSP_CMD_TIMEOUT2);
    101	} else if ((addr = fsp_test_swap_cmd(reg_addr)) != reg_addr) {
    102		/* swapping is required */
    103		ps2_sendbyte(ps2dev, 0xcc, FSP_CMD_TIMEOUT2);
    104		/* expect 0xfe */
    105	} else {
    106		/* swapping isn't necessary */
    107		ps2_sendbyte(ps2dev, 0x66, FSP_CMD_TIMEOUT2);
    108		/* expect 0xfe */
    109	}
    110	/* should return 0xfc(failed) */
    111	ps2_sendbyte(ps2dev, addr, FSP_CMD_TIMEOUT);
    112
    113	if (__ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO) < 0)
    114		goto out;
    115
    116	*reg_val = param[2];
    117	rc = 0;
    118
    119 out:
    120	ps2_end_command(ps2dev);
    121	psmouse_activate(psmouse);
    122	psmouse_dbg(psmouse,
    123		    "READ REG: 0x%02x is 0x%02x (rc = %d)\n",
    124		    reg_addr, *reg_val, rc);
    125	return rc;
    126}
    127
    128static int fsp_reg_write(struct psmouse *psmouse, int reg_addr, int reg_val)
    129{
    130	struct ps2dev *ps2dev = &psmouse->ps2dev;
    131	unsigned char v;
    132	int rc = -1;
    133
    134	ps2_begin_command(ps2dev);
    135
    136	if (ps2_sendbyte(ps2dev, 0xf3, FSP_CMD_TIMEOUT) < 0)
    137		goto out;
    138
    139	if ((v = fsp_test_invert_cmd(reg_addr)) != reg_addr) {
    140		/* inversion is required */
    141		ps2_sendbyte(ps2dev, 0x74, FSP_CMD_TIMEOUT2);
    142	} else {
    143		if ((v = fsp_test_swap_cmd(reg_addr)) != reg_addr) {
    144			/* swapping is required */
    145			ps2_sendbyte(ps2dev, 0x77, FSP_CMD_TIMEOUT2);
    146		} else {
    147			/* swapping isn't necessary */
    148			ps2_sendbyte(ps2dev, 0x55, FSP_CMD_TIMEOUT2);
    149		}
    150	}
    151	/* write the register address in correct order */
    152	ps2_sendbyte(ps2dev, v, FSP_CMD_TIMEOUT2);
    153
    154	if (ps2_sendbyte(ps2dev, 0xf3, FSP_CMD_TIMEOUT) < 0)
    155		goto out;
    156
    157	if ((v = fsp_test_invert_cmd(reg_val)) != reg_val) {
    158		/* inversion is required */
    159		ps2_sendbyte(ps2dev, 0x47, FSP_CMD_TIMEOUT2);
    160	} else if ((v = fsp_test_swap_cmd(reg_val)) != reg_val) {
    161		/* swapping is required */
    162		ps2_sendbyte(ps2dev, 0x44, FSP_CMD_TIMEOUT2);
    163	} else {
    164		/* swapping isn't necessary */
    165		ps2_sendbyte(ps2dev, 0x33, FSP_CMD_TIMEOUT2);
    166	}
    167
    168	/* write the register value in correct order */
    169	ps2_sendbyte(ps2dev, v, FSP_CMD_TIMEOUT2);
    170	rc = 0;
    171
    172 out:
    173	ps2_end_command(ps2dev);
    174	psmouse_dbg(psmouse,
    175		    "WRITE REG: 0x%02x to 0x%02x (rc = %d)\n",
    176		    reg_addr, reg_val, rc);
    177	return rc;
    178}
    179
    180/* Enable register clock gating for writing certain registers */
    181static int fsp_reg_write_enable(struct psmouse *psmouse, bool enable)
    182{
    183	int v, nv;
    184
    185	if (fsp_reg_read(psmouse, FSP_REG_SYSCTL1, &v) == -1)
    186		return -1;
    187
    188	if (enable)
    189		nv = v | FSP_BIT_EN_REG_CLK;
    190	else
    191		nv = v & ~FSP_BIT_EN_REG_CLK;
    192
    193	/* only write if necessary */
    194	if (nv != v)
    195		if (fsp_reg_write(psmouse, FSP_REG_SYSCTL1, nv) == -1)
    196			return -1;
    197
    198	return 0;
    199}
    200
    201static int fsp_page_reg_read(struct psmouse *psmouse, int *reg_val)
    202{
    203	struct ps2dev *ps2dev = &psmouse->ps2dev;
    204	unsigned char param[3];
    205	int rc = -1;
    206
    207	psmouse_deactivate(psmouse);
    208
    209	ps2_begin_command(ps2dev);
    210
    211	if (ps2_sendbyte(ps2dev, 0xf3, FSP_CMD_TIMEOUT) < 0)
    212		goto out;
    213
    214	ps2_sendbyte(ps2dev, 0x66, FSP_CMD_TIMEOUT2);
    215	ps2_sendbyte(ps2dev, 0x88, FSP_CMD_TIMEOUT2);
    216
    217	if (ps2_sendbyte(ps2dev, 0xf3, FSP_CMD_TIMEOUT) < 0)
    218		goto out;
    219
    220	ps2_sendbyte(ps2dev, 0x83, FSP_CMD_TIMEOUT2);
    221	ps2_sendbyte(ps2dev, 0x88, FSP_CMD_TIMEOUT2);
    222
    223	/* get the returned result */
    224	if (__ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO))
    225		goto out;
    226
    227	*reg_val = param[2];
    228	rc = 0;
    229
    230 out:
    231	ps2_end_command(ps2dev);
    232	psmouse_activate(psmouse);
    233	psmouse_dbg(psmouse,
    234		    "READ PAGE REG: 0x%02x (rc = %d)\n",
    235		    *reg_val, rc);
    236	return rc;
    237}
    238
    239static int fsp_page_reg_write(struct psmouse *psmouse, int reg_val)
    240{
    241	struct ps2dev *ps2dev = &psmouse->ps2dev;
    242	unsigned char v;
    243	int rc = -1;
    244
    245	ps2_begin_command(ps2dev);
    246
    247	if (ps2_sendbyte(ps2dev, 0xf3, FSP_CMD_TIMEOUT) < 0)
    248		goto out;
    249
    250	ps2_sendbyte(ps2dev, 0x38, FSP_CMD_TIMEOUT2);
    251	ps2_sendbyte(ps2dev, 0x88, FSP_CMD_TIMEOUT2);
    252
    253	if (ps2_sendbyte(ps2dev, 0xf3, FSP_CMD_TIMEOUT) < 0)
    254		goto out;
    255
    256	if ((v = fsp_test_invert_cmd(reg_val)) != reg_val) {
    257		ps2_sendbyte(ps2dev, 0x47, FSP_CMD_TIMEOUT2);
    258	} else if ((v = fsp_test_swap_cmd(reg_val)) != reg_val) {
    259		/* swapping is required */
    260		ps2_sendbyte(ps2dev, 0x44, FSP_CMD_TIMEOUT2);
    261	} else {
    262		/* swapping isn't necessary */
    263		ps2_sendbyte(ps2dev, 0x33, FSP_CMD_TIMEOUT2);
    264	}
    265
    266	ps2_sendbyte(ps2dev, v, FSP_CMD_TIMEOUT2);
    267	rc = 0;
    268
    269 out:
    270	ps2_end_command(ps2dev);
    271	psmouse_dbg(psmouse,
    272		    "WRITE PAGE REG: to 0x%02x (rc = %d)\n",
    273		    reg_val, rc);
    274	return rc;
    275}
    276
    277static int fsp_get_version(struct psmouse *psmouse, int *version)
    278{
    279	if (fsp_reg_read(psmouse, FSP_REG_VERSION, version))
    280		return -EIO;
    281
    282	return 0;
    283}
    284
    285static int fsp_get_revision(struct psmouse *psmouse, int *rev)
    286{
    287	if (fsp_reg_read(psmouse, FSP_REG_REVISION, rev))
    288		return -EIO;
    289
    290	return 0;
    291}
    292
    293static int fsp_get_sn(struct psmouse *psmouse, int *sn)
    294{
    295	int v0, v1, v2;
    296	int rc = -EIO;
    297
    298	/* production number since Cx is available at: 0x0b40 ~ 0x0b42 */
    299	if (fsp_page_reg_write(psmouse, FSP_PAGE_0B))
    300		goto out;
    301	if (fsp_reg_read(psmouse, FSP_REG_SN0, &v0))
    302		goto out;
    303	if (fsp_reg_read(psmouse, FSP_REG_SN1, &v1))
    304		goto out;
    305	if (fsp_reg_read(psmouse, FSP_REG_SN2, &v2))
    306		goto out;
    307	*sn = (v0 << 16) | (v1 << 8) | v2;
    308	rc = 0;
    309out:
    310	fsp_page_reg_write(psmouse, FSP_PAGE_DEFAULT);
    311	return rc;
    312}
    313
    314static int fsp_get_buttons(struct psmouse *psmouse, int *btn)
    315{
    316	static const int buttons[] = {
    317		0x16, /* Left/Middle/Right/Forward/Backward & Scroll Up/Down */
    318		0x06, /* Left/Middle/Right & Scroll Up/Down/Right/Left */
    319		0x04, /* Left/Middle/Right & Scroll Up/Down */
    320		0x02, /* Left/Middle/Right */
    321	};
    322	int val;
    323
    324	if (fsp_reg_read(psmouse, FSP_REG_TMOD_STATUS, &val) == -1)
    325		return -EIO;
    326
    327	*btn = buttons[(val & 0x30) >> 4];
    328	return 0;
    329}
    330
    331/* Enable on-pad command tag output */
    332static int fsp_opc_tag_enable(struct psmouse *psmouse, bool enable)
    333{
    334	int v, nv;
    335	int res = 0;
    336
    337	if (fsp_reg_read(psmouse, FSP_REG_OPC_QDOWN, &v) == -1) {
    338		psmouse_err(psmouse, "Unable get OPC state.\n");
    339		return -EIO;
    340	}
    341
    342	if (enable)
    343		nv = v | FSP_BIT_EN_OPC_TAG;
    344	else
    345		nv = v & ~FSP_BIT_EN_OPC_TAG;
    346
    347	/* only write if necessary */
    348	if (nv != v) {
    349		fsp_reg_write_enable(psmouse, true);
    350		res = fsp_reg_write(psmouse, FSP_REG_OPC_QDOWN, nv);
    351		fsp_reg_write_enable(psmouse, false);
    352	}
    353
    354	if (res != 0) {
    355		psmouse_err(psmouse, "Unable to enable OPC tag.\n");
    356		res = -EIO;
    357	}
    358
    359	return res;
    360}
    361
    362static int fsp_onpad_vscr(struct psmouse *psmouse, bool enable)
    363{
    364	struct fsp_data *pad = psmouse->private;
    365	int val;
    366
    367	if (fsp_reg_read(psmouse, FSP_REG_ONPAD_CTL, &val))
    368		return -EIO;
    369
    370	pad->vscroll = enable;
    371
    372	if (enable)
    373		val |= (FSP_BIT_FIX_VSCR | FSP_BIT_ONPAD_ENABLE);
    374	else
    375		val &= ~FSP_BIT_FIX_VSCR;
    376
    377	if (fsp_reg_write(psmouse, FSP_REG_ONPAD_CTL, val))
    378		return -EIO;
    379
    380	return 0;
    381}
    382
    383static int fsp_onpad_hscr(struct psmouse *psmouse, bool enable)
    384{
    385	struct fsp_data *pad = psmouse->private;
    386	int val, v2;
    387
    388	if (fsp_reg_read(psmouse, FSP_REG_ONPAD_CTL, &val))
    389		return -EIO;
    390
    391	if (fsp_reg_read(psmouse, FSP_REG_SYSCTL5, &v2))
    392		return -EIO;
    393
    394	pad->hscroll = enable;
    395
    396	if (enable) {
    397		val |= (FSP_BIT_FIX_HSCR | FSP_BIT_ONPAD_ENABLE);
    398		v2 |= FSP_BIT_EN_MSID6;
    399	} else {
    400		val &= ~FSP_BIT_FIX_HSCR;
    401		v2 &= ~(FSP_BIT_EN_MSID6 | FSP_BIT_EN_MSID7 | FSP_BIT_EN_MSID8);
    402	}
    403
    404	if (fsp_reg_write(psmouse, FSP_REG_ONPAD_CTL, val))
    405		return -EIO;
    406
    407	/* reconfigure horizontal scrolling packet output */
    408	if (fsp_reg_write(psmouse, FSP_REG_SYSCTL5, v2))
    409		return -EIO;
    410
    411	return 0;
    412}
    413
    414/*
    415 * Write device specific initial parameters.
    416 *
    417 * ex: 0xab 0xcd - write oxcd into register 0xab
    418 */
    419static ssize_t fsp_attr_set_setreg(struct psmouse *psmouse, void *data,
    420				   const char *buf, size_t count)
    421{
    422	unsigned int reg, val;
    423	char *rest;
    424	ssize_t retval;
    425
    426	reg = simple_strtoul(buf, &rest, 16);
    427	if (rest == buf || *rest != ' ' || reg > 0xff)
    428		return -EINVAL;
    429
    430	retval = kstrtouint(rest + 1, 16, &val);
    431	if (retval)
    432		return retval;
    433
    434	if (val > 0xff)
    435		return -EINVAL;
    436
    437	if (fsp_reg_write_enable(psmouse, true))
    438		return -EIO;
    439
    440	retval = fsp_reg_write(psmouse, reg, val) < 0 ? -EIO : count;
    441
    442	fsp_reg_write_enable(psmouse, false);
    443
    444	return retval;
    445}
    446
    447PSMOUSE_DEFINE_WO_ATTR(setreg, S_IWUSR, NULL, fsp_attr_set_setreg);
    448
    449static ssize_t fsp_attr_show_getreg(struct psmouse *psmouse,
    450					void *data, char *buf)
    451{
    452	struct fsp_data *pad = psmouse->private;
    453
    454	return sprintf(buf, "%02x%02x\n", pad->last_reg, pad->last_val);
    455}
    456
    457/*
    458 * Read a register from device.
    459 *
    460 * ex: 0xab -- read content from register 0xab
    461 */
    462static ssize_t fsp_attr_set_getreg(struct psmouse *psmouse, void *data,
    463					const char *buf, size_t count)
    464{
    465	struct fsp_data *pad = psmouse->private;
    466	unsigned int reg, val;
    467	int err;
    468
    469	err = kstrtouint(buf, 16, &reg);
    470	if (err)
    471		return err;
    472
    473	if (reg > 0xff)
    474		return -EINVAL;
    475
    476	if (fsp_reg_read(psmouse, reg, &val))
    477		return -EIO;
    478
    479	pad->last_reg = reg;
    480	pad->last_val = val;
    481
    482	return count;
    483}
    484
    485PSMOUSE_DEFINE_ATTR(getreg, S_IWUSR | S_IRUGO, NULL,
    486			fsp_attr_show_getreg, fsp_attr_set_getreg);
    487
    488static ssize_t fsp_attr_show_pagereg(struct psmouse *psmouse,
    489					void *data, char *buf)
    490{
    491	int val = 0;
    492
    493	if (fsp_page_reg_read(psmouse, &val))
    494		return -EIO;
    495
    496	return sprintf(buf, "%02x\n", val);
    497}
    498
    499static ssize_t fsp_attr_set_pagereg(struct psmouse *psmouse, void *data,
    500					const char *buf, size_t count)
    501{
    502	unsigned int val;
    503	int err;
    504
    505	err = kstrtouint(buf, 16, &val);
    506	if (err)
    507		return err;
    508
    509	if (val > 0xff)
    510		return -EINVAL;
    511
    512	if (fsp_page_reg_write(psmouse, val))
    513		return -EIO;
    514
    515	return count;
    516}
    517
    518PSMOUSE_DEFINE_ATTR(page, S_IWUSR | S_IRUGO, NULL,
    519			fsp_attr_show_pagereg, fsp_attr_set_pagereg);
    520
    521static ssize_t fsp_attr_show_vscroll(struct psmouse *psmouse,
    522					void *data, char *buf)
    523{
    524	struct fsp_data *pad = psmouse->private;
    525
    526	return sprintf(buf, "%d\n", pad->vscroll);
    527}
    528
    529static ssize_t fsp_attr_set_vscroll(struct psmouse *psmouse, void *data,
    530					const char *buf, size_t count)
    531{
    532	unsigned int val;
    533	int err;
    534
    535	err = kstrtouint(buf, 10, &val);
    536	if (err)
    537		return err;
    538
    539	if (val > 1)
    540		return -EINVAL;
    541
    542	fsp_onpad_vscr(psmouse, val);
    543
    544	return count;
    545}
    546
    547PSMOUSE_DEFINE_ATTR(vscroll, S_IWUSR | S_IRUGO, NULL,
    548			fsp_attr_show_vscroll, fsp_attr_set_vscroll);
    549
    550static ssize_t fsp_attr_show_hscroll(struct psmouse *psmouse,
    551					void *data, char *buf)
    552{
    553	struct fsp_data *pad = psmouse->private;
    554
    555	return sprintf(buf, "%d\n", pad->hscroll);
    556}
    557
    558static ssize_t fsp_attr_set_hscroll(struct psmouse *psmouse, void *data,
    559					const char *buf, size_t count)
    560{
    561	unsigned int val;
    562	int err;
    563
    564	err = kstrtouint(buf, 10, &val);
    565	if (err)
    566		return err;
    567
    568	if (val > 1)
    569		return -EINVAL;
    570
    571	fsp_onpad_hscr(psmouse, val);
    572
    573	return count;
    574}
    575
    576PSMOUSE_DEFINE_ATTR(hscroll, S_IWUSR | S_IRUGO, NULL,
    577			fsp_attr_show_hscroll, fsp_attr_set_hscroll);
    578
    579static ssize_t fsp_attr_show_flags(struct psmouse *psmouse,
    580					void *data, char *buf)
    581{
    582	struct fsp_data *pad = psmouse->private;
    583
    584	return sprintf(buf, "%c\n",
    585			pad->flags & FSPDRV_FLAG_EN_OPC ? 'C' : 'c');
    586}
    587
    588static ssize_t fsp_attr_set_flags(struct psmouse *psmouse, void *data,
    589					const char *buf, size_t count)
    590{
    591	struct fsp_data *pad = psmouse->private;
    592	size_t i;
    593
    594	for (i = 0; i < count; i++) {
    595		switch (buf[i]) {
    596		case 'C':
    597			pad->flags |= FSPDRV_FLAG_EN_OPC;
    598			break;
    599		case 'c':
    600			pad->flags &= ~FSPDRV_FLAG_EN_OPC;
    601			break;
    602		default:
    603			return -EINVAL;
    604		}
    605	}
    606	return count;
    607}
    608
    609PSMOUSE_DEFINE_ATTR(flags, S_IWUSR | S_IRUGO, NULL,
    610			fsp_attr_show_flags, fsp_attr_set_flags);
    611
    612static ssize_t fsp_attr_show_ver(struct psmouse *psmouse,
    613					void *data, char *buf)
    614{
    615	return sprintf(buf, "Sentelic FSP kernel module %s\n", fsp_drv_ver);
    616}
    617
    618PSMOUSE_DEFINE_RO_ATTR(ver, S_IRUGO, NULL, fsp_attr_show_ver);
    619
    620static struct attribute *fsp_attributes[] = {
    621	&psmouse_attr_setreg.dattr.attr,
    622	&psmouse_attr_getreg.dattr.attr,
    623	&psmouse_attr_page.dattr.attr,
    624	&psmouse_attr_vscroll.dattr.attr,
    625	&psmouse_attr_hscroll.dattr.attr,
    626	&psmouse_attr_flags.dattr.attr,
    627	&psmouse_attr_ver.dattr.attr,
    628	NULL
    629};
    630
    631static struct attribute_group fsp_attribute_group = {
    632	.attrs = fsp_attributes,
    633};
    634
    635#ifdef	FSP_DEBUG
    636static void fsp_packet_debug(struct psmouse *psmouse, unsigned char packet[])
    637{
    638	static unsigned int ps2_packet_cnt;
    639	static unsigned int ps2_last_second;
    640	unsigned int jiffies_msec;
    641	const char *packet_type = "UNKNOWN";
    642	unsigned short abs_x = 0, abs_y = 0;
    643
    644	/* Interpret & dump the packet data. */
    645	switch (packet[0] >> FSP_PKT_TYPE_SHIFT) {
    646	case FSP_PKT_TYPE_ABS:
    647		packet_type = "Absolute";
    648		abs_x = GET_ABS_X(packet);
    649		abs_y = GET_ABS_Y(packet);
    650		break;
    651	case FSP_PKT_TYPE_NORMAL:
    652		packet_type = "Normal";
    653		break;
    654	case FSP_PKT_TYPE_NOTIFY:
    655		packet_type = "Notify";
    656		break;
    657	case FSP_PKT_TYPE_NORMAL_OPC:
    658		packet_type = "Normal-OPC";
    659		break;
    660	}
    661
    662	ps2_packet_cnt++;
    663	jiffies_msec = jiffies_to_msecs(jiffies);
    664	psmouse_dbg(psmouse,
    665		    "%08dms %s packets: %02x, %02x, %02x, %02x; "
    666		    "abs_x: %d, abs_y: %d\n",
    667		    jiffies_msec, packet_type,
    668		    packet[0], packet[1], packet[2], packet[3], abs_x, abs_y);
    669
    670	if (jiffies_msec - ps2_last_second > 1000) {
    671		psmouse_dbg(psmouse, "PS/2 packets/sec = %d\n", ps2_packet_cnt);
    672		ps2_packet_cnt = 0;
    673		ps2_last_second = jiffies_msec;
    674	}
    675}
    676#else
    677static void fsp_packet_debug(struct psmouse *psmouse, unsigned char packet[])
    678{
    679}
    680#endif
    681
    682static void fsp_set_slot(struct input_dev *dev, int slot, bool active,
    683			 unsigned int x, unsigned int y)
    684{
    685	input_mt_slot(dev, slot);
    686	input_mt_report_slot_state(dev, MT_TOOL_FINGER, active);
    687	if (active) {
    688		input_report_abs(dev, ABS_MT_POSITION_X, x);
    689		input_report_abs(dev, ABS_MT_POSITION_Y, y);
    690	}
    691}
    692
    693static psmouse_ret_t fsp_process_byte(struct psmouse *psmouse)
    694{
    695	struct input_dev *dev = psmouse->dev;
    696	struct fsp_data *ad = psmouse->private;
    697	unsigned char *packet = psmouse->packet;
    698	unsigned char button_status = 0, lscroll = 0, rscroll = 0;
    699	unsigned short abs_x, abs_y, fgrs = 0;
    700
    701	if (psmouse->pktcnt < 4)
    702		return PSMOUSE_GOOD_DATA;
    703
    704	/*
    705	 * Full packet accumulated, process it
    706	 */
    707
    708	fsp_packet_debug(psmouse, packet);
    709
    710	switch (psmouse->packet[0] >> FSP_PKT_TYPE_SHIFT) {
    711	case FSP_PKT_TYPE_ABS:
    712
    713		if ((packet[0] == 0x48 || packet[0] == 0x49) &&
    714		    packet[1] == 0 && packet[2] == 0) {
    715			/*
    716			 * Ignore coordinate noise when finger leaving the
    717			 * surface, otherwise cursor may jump to upper-left
    718			 * corner.
    719			 */
    720			packet[3] &= 0xf0;
    721		}
    722
    723		abs_x = GET_ABS_X(packet);
    724		abs_y = GET_ABS_Y(packet);
    725
    726		if (packet[0] & FSP_PB0_MFMC) {
    727			/*
    728			 * MFMC packet: assume that there are two fingers on
    729			 * pad
    730			 */
    731			fgrs = 2;
    732
    733			/* MFMC packet */
    734			if (packet[0] & FSP_PB0_MFMC_FGR2) {
    735				/* 2nd finger */
    736				if (ad->last_mt_fgr == 2) {
    737					/*
    738					 * workaround for buggy firmware
    739					 * which doesn't clear MFMC bit if
    740					 * the 1st finger is up
    741					 */
    742					fgrs = 1;
    743					fsp_set_slot(dev, 0, false, 0, 0);
    744				}
    745				ad->last_mt_fgr = 2;
    746
    747				fsp_set_slot(dev, 1, fgrs == 2, abs_x, abs_y);
    748			} else {
    749				/* 1st finger */
    750				if (ad->last_mt_fgr == 1) {
    751					/*
    752					 * workaround for buggy firmware
    753					 * which doesn't clear MFMC bit if
    754					 * the 2nd finger is up
    755					 */
    756					fgrs = 1;
    757					fsp_set_slot(dev, 1, false, 0, 0);
    758				}
    759				ad->last_mt_fgr = 1;
    760				fsp_set_slot(dev, 0, fgrs != 0, abs_x, abs_y);
    761			}
    762		} else {
    763			/* SFAC packet */
    764			if ((packet[0] & (FSP_PB0_LBTN|FSP_PB0_PHY_BTN)) ==
    765				FSP_PB0_LBTN) {
    766				/* On-pad click in SFAC mode should be handled
    767				 * by userspace.  On-pad clicks in MFMC mode
    768				 * are real clickpad clicks, and not ignored.
    769				 */
    770				packet[0] &= ~FSP_PB0_LBTN;
    771			}
    772
    773			/* no multi-finger information */
    774			ad->last_mt_fgr = 0;
    775
    776			if (abs_x != 0 && abs_y != 0)
    777				fgrs = 1;
    778
    779			fsp_set_slot(dev, 0, fgrs > 0, abs_x, abs_y);
    780			fsp_set_slot(dev, 1, false, 0, 0);
    781		}
    782		if (fgrs == 1 || (fgrs == 2 && !(packet[0] & FSP_PB0_MFMC_FGR2))) {
    783			input_report_abs(dev, ABS_X, abs_x);
    784			input_report_abs(dev, ABS_Y, abs_y);
    785		}
    786		input_report_key(dev, BTN_LEFT, packet[0] & 0x01);
    787		input_report_key(dev, BTN_RIGHT, packet[0] & 0x02);
    788		input_report_key(dev, BTN_TOUCH, fgrs);
    789		input_report_key(dev, BTN_TOOL_FINGER, fgrs == 1);
    790		input_report_key(dev, BTN_TOOL_DOUBLETAP, fgrs == 2);
    791		break;
    792
    793	case FSP_PKT_TYPE_NORMAL_OPC:
    794		/* on-pad click, filter it if necessary */
    795		if ((ad->flags & FSPDRV_FLAG_EN_OPC) != FSPDRV_FLAG_EN_OPC)
    796			packet[0] &= ~FSP_PB0_LBTN;
    797		fallthrough;
    798
    799	case FSP_PKT_TYPE_NORMAL:
    800		/* normal packet */
    801		/* special packet data translation from on-pad packets */
    802		if (packet[3] != 0) {
    803			if (packet[3] & BIT(0))
    804				button_status |= 0x01;	/* wheel down */
    805			if (packet[3] & BIT(1))
    806				button_status |= 0x0f;	/* wheel up */
    807			if (packet[3] & BIT(2))
    808				button_status |= BIT(4);/* horizontal left */
    809			if (packet[3] & BIT(3))
    810				button_status |= BIT(5);/* horizontal right */
    811			/* push back to packet queue */
    812			if (button_status != 0)
    813				packet[3] = button_status;
    814			rscroll = (packet[3] >> 4) & 1;
    815			lscroll = (packet[3] >> 5) & 1;
    816		}
    817		/*
    818		 * Processing wheel up/down and extra button events
    819		 */
    820		input_report_rel(dev, REL_WHEEL,
    821				 (int)(packet[3] & 8) - (int)(packet[3] & 7));
    822		input_report_rel(dev, REL_HWHEEL, lscroll - rscroll);
    823		input_report_key(dev, BTN_BACK, lscroll);
    824		input_report_key(dev, BTN_FORWARD, rscroll);
    825
    826		/*
    827		 * Standard PS/2 Mouse
    828		 */
    829		psmouse_report_standard_packet(dev, packet);
    830		break;
    831	}
    832
    833	input_sync(dev);
    834
    835	return PSMOUSE_FULL_PACKET;
    836}
    837
    838static int fsp_activate_protocol(struct psmouse *psmouse)
    839{
    840	struct fsp_data *pad = psmouse->private;
    841	struct ps2dev *ps2dev = &psmouse->ps2dev;
    842	unsigned char param[2];
    843	int val;
    844
    845	/*
    846	 * Standard procedure to enter FSP Intellimouse mode
    847	 * (scrolling wheel, 4th and 5th buttons)
    848	 */
    849	param[0] = 200;
    850	ps2_command(ps2dev, param, PSMOUSE_CMD_SETRATE);
    851	param[0] = 200;
    852	ps2_command(ps2dev, param, PSMOUSE_CMD_SETRATE);
    853	param[0] =  80;
    854	ps2_command(ps2dev, param, PSMOUSE_CMD_SETRATE);
    855
    856	ps2_command(ps2dev, param, PSMOUSE_CMD_GETID);
    857	if (param[0] != 0x04) {
    858		psmouse_err(psmouse,
    859			    "Unable to enable 4 bytes packet format.\n");
    860		return -EIO;
    861	}
    862
    863	if (pad->ver < FSP_VER_STL3888_C0) {
    864		/* Preparing relative coordinates output for older hardware */
    865		if (fsp_reg_read(psmouse, FSP_REG_SYSCTL5, &val)) {
    866			psmouse_err(psmouse,
    867				    "Unable to read SYSCTL5 register.\n");
    868			return -EIO;
    869		}
    870
    871		if (fsp_get_buttons(psmouse, &pad->buttons)) {
    872			psmouse_err(psmouse,
    873				    "Unable to retrieve number of buttons.\n");
    874			return -EIO;
    875		}
    876
    877		val &= ~(FSP_BIT_EN_MSID7 | FSP_BIT_EN_MSID8 | FSP_BIT_EN_AUTO_MSID8);
    878		/* Ensure we are not in absolute mode */
    879		val &= ~FSP_BIT_EN_PKT_G0;
    880		if (pad->buttons == 0x06) {
    881			/* Left/Middle/Right & Scroll Up/Down/Right/Left */
    882			val |= FSP_BIT_EN_MSID6;
    883		}
    884
    885		if (fsp_reg_write(psmouse, FSP_REG_SYSCTL5, val)) {
    886			psmouse_err(psmouse,
    887				    "Unable to set up required mode bits.\n");
    888			return -EIO;
    889		}
    890
    891		/*
    892		 * Enable OPC tags such that driver can tell the difference
    893		 * between on-pad and real button click
    894		 */
    895		if (fsp_opc_tag_enable(psmouse, true))
    896			psmouse_warn(psmouse,
    897				     "Failed to enable OPC tag mode.\n");
    898		/* enable on-pad click by default */
    899		pad->flags |= FSPDRV_FLAG_EN_OPC;
    900
    901		/* Enable on-pad vertical and horizontal scrolling */
    902		fsp_onpad_vscr(psmouse, true);
    903		fsp_onpad_hscr(psmouse, true);
    904	} else {
    905		/* Enable absolute coordinates output for Cx/Dx hardware */
    906		if (fsp_reg_write(psmouse, FSP_REG_SWC1,
    907				  FSP_BIT_SWC1_EN_ABS_1F |
    908				  FSP_BIT_SWC1_EN_ABS_2F |
    909				  FSP_BIT_SWC1_EN_FUP_OUT |
    910				  FSP_BIT_SWC1_EN_ABS_CON)) {
    911			psmouse_err(psmouse,
    912				    "Unable to enable absolute coordinates output.\n");
    913			return -EIO;
    914		}
    915	}
    916
    917	return 0;
    918}
    919
    920static int fsp_set_input_params(struct psmouse *psmouse)
    921{
    922	struct input_dev *dev = psmouse->dev;
    923	struct fsp_data *pad = psmouse->private;
    924
    925	if (pad->ver < FSP_VER_STL3888_C0) {
    926		__set_bit(BTN_MIDDLE, dev->keybit);
    927		__set_bit(BTN_BACK, dev->keybit);
    928		__set_bit(BTN_FORWARD, dev->keybit);
    929		__set_bit(REL_WHEEL, dev->relbit);
    930		__set_bit(REL_HWHEEL, dev->relbit);
    931	} else {
    932		/*
    933		 * Hardware prior to Cx performs much better in relative mode;
    934		 * hence, only enable absolute coordinates output as well as
    935		 * multi-touch output for the newer hardware.
    936		 *
    937		 * Maximum coordinates can be computed as:
    938		 *
    939		 *	number of scanlines * 64 - 57
    940		 *
    941		 * where number of X/Y scanline lines are 16/12.
    942		 */
    943		int abs_x = 967, abs_y = 711;
    944
    945		__set_bit(EV_ABS, dev->evbit);
    946		__clear_bit(EV_REL, dev->evbit);
    947		__set_bit(BTN_TOUCH, dev->keybit);
    948		__set_bit(BTN_TOOL_FINGER, dev->keybit);
    949		__set_bit(BTN_TOOL_DOUBLETAP, dev->keybit);
    950		__set_bit(INPUT_PROP_SEMI_MT, dev->propbit);
    951
    952		input_set_abs_params(dev, ABS_X, 0, abs_x, 0, 0);
    953		input_set_abs_params(dev, ABS_Y, 0, abs_y, 0, 0);
    954		input_mt_init_slots(dev, 2, 0);
    955		input_set_abs_params(dev, ABS_MT_POSITION_X, 0, abs_x, 0, 0);
    956		input_set_abs_params(dev, ABS_MT_POSITION_Y, 0, abs_y, 0, 0);
    957	}
    958
    959	return 0;
    960}
    961
    962int fsp_detect(struct psmouse *psmouse, bool set_properties)
    963{
    964	int id;
    965
    966	if (fsp_reg_read(psmouse, FSP_REG_DEVICE_ID, &id))
    967		return -EIO;
    968
    969	if (id != 0x01)
    970		return -ENODEV;
    971
    972	if (set_properties) {
    973		psmouse->vendor = "Sentelic";
    974		psmouse->name = "FingerSensingPad";
    975	}
    976
    977	return 0;
    978}
    979
    980static void fsp_reset(struct psmouse *psmouse)
    981{
    982	fsp_opc_tag_enable(psmouse, false);
    983	fsp_onpad_vscr(psmouse, false);
    984	fsp_onpad_hscr(psmouse, false);
    985}
    986
    987static void fsp_disconnect(struct psmouse *psmouse)
    988{
    989	sysfs_remove_group(&psmouse->ps2dev.serio->dev.kobj,
    990			   &fsp_attribute_group);
    991
    992	fsp_reset(psmouse);
    993	kfree(psmouse->private);
    994}
    995
    996static int fsp_reconnect(struct psmouse *psmouse)
    997{
    998	int version;
    999
   1000	if (fsp_detect(psmouse, 0))
   1001		return -ENODEV;
   1002
   1003	if (fsp_get_version(psmouse, &version))
   1004		return -ENODEV;
   1005
   1006	if (fsp_activate_protocol(psmouse))
   1007		return -EIO;
   1008
   1009	return 0;
   1010}
   1011
   1012int fsp_init(struct psmouse *psmouse)
   1013{
   1014	struct fsp_data *priv;
   1015	int ver, rev, sn = 0;
   1016	int error;
   1017
   1018	if (fsp_get_version(psmouse, &ver) ||
   1019	    fsp_get_revision(psmouse, &rev)) {
   1020		return -ENODEV;
   1021	}
   1022	if (ver >= FSP_VER_STL3888_C0) {
   1023		/* firmware information is only available since C0 */
   1024		fsp_get_sn(psmouse, &sn);
   1025	}
   1026
   1027	psmouse_info(psmouse,
   1028		     "Finger Sensing Pad, hw: %d.%d.%d, sn: %x, sw: %s\n",
   1029		     ver >> 4, ver & 0x0F, rev, sn, fsp_drv_ver);
   1030
   1031	psmouse->private = priv = kzalloc(sizeof(struct fsp_data), GFP_KERNEL);
   1032	if (!priv)
   1033		return -ENOMEM;
   1034
   1035	priv->ver = ver;
   1036	priv->rev = rev;
   1037
   1038	psmouse->protocol_handler = fsp_process_byte;
   1039	psmouse->disconnect = fsp_disconnect;
   1040	psmouse->reconnect = fsp_reconnect;
   1041	psmouse->cleanup = fsp_reset;
   1042	psmouse->pktsize = 4;
   1043
   1044	error = fsp_activate_protocol(psmouse);
   1045	if (error)
   1046		goto err_out;
   1047
   1048	/* Set up various supported input event bits */
   1049	error = fsp_set_input_params(psmouse);
   1050	if (error)
   1051		goto err_out;
   1052
   1053	error = sysfs_create_group(&psmouse->ps2dev.serio->dev.kobj,
   1054				   &fsp_attribute_group);
   1055	if (error) {
   1056		psmouse_err(psmouse,
   1057			    "Failed to create sysfs attributes (%d)", error);
   1058		goto err_out;
   1059	}
   1060
   1061	return 0;
   1062
   1063 err_out:
   1064	kfree(psmouse->private);
   1065	psmouse->private = NULL;
   1066	return error;
   1067}