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

mms114.c (15882B)


      1// SPDX-License-Identifier: GPL-2.0
      2// Melfas MMS114/MMS136/MMS152 touchscreen device driver
      3//
      4// Copyright (c) 2012 Samsung Electronics Co., Ltd.
      5// Author: Joonyoung Shim <jy0922.shim@samsung.com>
      6
      7#include <linux/module.h>
      8#include <linux/delay.h>
      9#include <linux/of.h>
     10#include <linux/of_device.h>
     11#include <linux/i2c.h>
     12#include <linux/input/mt.h>
     13#include <linux/input/touchscreen.h>
     14#include <linux/interrupt.h>
     15#include <linux/regulator/consumer.h>
     16#include <linux/slab.h>
     17
     18/* Write only registers */
     19#define MMS114_MODE_CONTROL		0x01
     20#define MMS114_OPERATION_MODE_MASK	0xE
     21#define MMS114_ACTIVE			BIT(1)
     22
     23#define MMS114_XY_RESOLUTION_H		0x02
     24#define MMS114_X_RESOLUTION		0x03
     25#define MMS114_Y_RESOLUTION		0x04
     26#define MMS114_CONTACT_THRESHOLD	0x05
     27#define MMS114_MOVING_THRESHOLD		0x06
     28
     29/* Read only registers */
     30#define MMS114_PACKET_SIZE		0x0F
     31#define MMS114_INFORMATION		0x10
     32#define MMS114_TSP_REV			0xF0
     33
     34#define MMS152_FW_REV			0xE1
     35#define MMS152_COMPAT_GROUP		0xF2
     36
     37/* Minimum delay time is 50us between stop and start signal of i2c */
     38#define MMS114_I2C_DELAY		50
     39
     40/* 200ms needs after power on */
     41#define MMS114_POWERON_DELAY		200
     42
     43/* Touchscreen absolute values */
     44#define MMS114_MAX_AREA			0xff
     45
     46#define MMS114_MAX_TOUCH		10
     47#define MMS114_EVENT_SIZE		8
     48#define MMS136_EVENT_SIZE		6
     49
     50/* Touch type */
     51#define MMS114_TYPE_NONE		0
     52#define MMS114_TYPE_TOUCHSCREEN		1
     53#define MMS114_TYPE_TOUCHKEY		2
     54
     55enum mms_type {
     56	TYPE_MMS114	= 114,
     57	TYPE_MMS134S	= 134,
     58	TYPE_MMS136	= 136,
     59	TYPE_MMS152	= 152,
     60	TYPE_MMS345L	= 345,
     61};
     62
     63struct mms114_data {
     64	struct i2c_client	*client;
     65	struct input_dev	*input_dev;
     66	struct regulator	*core_reg;
     67	struct regulator	*io_reg;
     68	struct touchscreen_properties props;
     69	enum mms_type		type;
     70	unsigned int		contact_threshold;
     71	unsigned int		moving_threshold;
     72
     73	/* Use cache data for mode control register(write only) */
     74	u8			cache_mode_control;
     75};
     76
     77struct mms114_touch {
     78	u8 id:4, reserved_bit4:1, type:2, pressed:1;
     79	u8 x_hi:4, y_hi:4;
     80	u8 x_lo;
     81	u8 y_lo;
     82	u8 width;
     83	u8 strength;
     84	u8 reserved[2];
     85} __packed;
     86
     87static int __mms114_read_reg(struct mms114_data *data, unsigned int reg,
     88			     unsigned int len, u8 *val)
     89{
     90	struct i2c_client *client = data->client;
     91	struct i2c_msg xfer[2];
     92	u8 buf = reg & 0xff;
     93	int error;
     94
     95	if (reg <= MMS114_MODE_CONTROL && reg + len > MMS114_MODE_CONTROL)
     96		BUG();
     97
     98	/* Write register */
     99	xfer[0].addr = client->addr;
    100	xfer[0].flags = client->flags & I2C_M_TEN;
    101	xfer[0].len = 1;
    102	xfer[0].buf = &buf;
    103
    104	/* Read data */
    105	xfer[1].addr = client->addr;
    106	xfer[1].flags = (client->flags & I2C_M_TEN) | I2C_M_RD;
    107	xfer[1].len = len;
    108	xfer[1].buf = val;
    109
    110	error = i2c_transfer(client->adapter, xfer, 2);
    111	if (error != 2) {
    112		dev_err(&client->dev,
    113			"%s: i2c transfer failed (%d)\n", __func__, error);
    114		return error < 0 ? error : -EIO;
    115	}
    116	udelay(MMS114_I2C_DELAY);
    117
    118	return 0;
    119}
    120
    121static int mms114_read_reg(struct mms114_data *data, unsigned int reg)
    122{
    123	u8 val;
    124	int error;
    125
    126	if (reg == MMS114_MODE_CONTROL)
    127		return data->cache_mode_control;
    128
    129	error = __mms114_read_reg(data, reg, 1, &val);
    130	return error < 0 ? error : val;
    131}
    132
    133static int mms114_write_reg(struct mms114_data *data, unsigned int reg,
    134			    unsigned int val)
    135{
    136	struct i2c_client *client = data->client;
    137	u8 buf[2];
    138	int error;
    139
    140	buf[0] = reg & 0xff;
    141	buf[1] = val & 0xff;
    142
    143	error = i2c_master_send(client, buf, 2);
    144	if (error != 2) {
    145		dev_err(&client->dev,
    146			"%s: i2c send failed (%d)\n", __func__, error);
    147		return error < 0 ? error : -EIO;
    148	}
    149	udelay(MMS114_I2C_DELAY);
    150
    151	if (reg == MMS114_MODE_CONTROL)
    152		data->cache_mode_control = val;
    153
    154	return 0;
    155}
    156
    157static void mms114_process_mt(struct mms114_data *data, struct mms114_touch *touch)
    158{
    159	struct i2c_client *client = data->client;
    160	struct input_dev *input_dev = data->input_dev;
    161	unsigned int id;
    162	unsigned int x;
    163	unsigned int y;
    164
    165	if (touch->id > MMS114_MAX_TOUCH) {
    166		dev_err(&client->dev, "Wrong touch id (%d)\n", touch->id);
    167		return;
    168	}
    169
    170	if (touch->type != MMS114_TYPE_TOUCHSCREEN) {
    171		dev_err(&client->dev, "Wrong touch type (%d)\n", touch->type);
    172		return;
    173	}
    174
    175	id = touch->id - 1;
    176	x = touch->x_lo | touch->x_hi << 8;
    177	y = touch->y_lo | touch->y_hi << 8;
    178
    179	dev_dbg(&client->dev,
    180		"id: %d, type: %d, pressed: %d, x: %d, y: %d, width: %d, strength: %d\n",
    181		id, touch->type, touch->pressed,
    182		x, y, touch->width, touch->strength);
    183
    184	input_mt_slot(input_dev, id);
    185	input_mt_report_slot_state(input_dev, MT_TOOL_FINGER, touch->pressed);
    186
    187	if (touch->pressed) {
    188		touchscreen_report_pos(input_dev, &data->props, x, y, true);
    189		input_report_abs(input_dev, ABS_MT_TOUCH_MAJOR, touch->width);
    190		input_report_abs(input_dev, ABS_MT_PRESSURE, touch->strength);
    191	}
    192}
    193
    194static irqreturn_t mms114_interrupt(int irq, void *dev_id)
    195{
    196	struct mms114_data *data = dev_id;
    197	struct input_dev *input_dev = data->input_dev;
    198	struct mms114_touch touch[MMS114_MAX_TOUCH];
    199	int packet_size;
    200	int touch_size;
    201	int index;
    202	int error;
    203
    204	mutex_lock(&input_dev->mutex);
    205	if (!input_device_enabled(input_dev)) {
    206		mutex_unlock(&input_dev->mutex);
    207		goto out;
    208	}
    209	mutex_unlock(&input_dev->mutex);
    210
    211	packet_size = mms114_read_reg(data, MMS114_PACKET_SIZE);
    212	if (packet_size <= 0)
    213		goto out;
    214
    215	/* MMS136 has slightly different event size */
    216	if (data->type == TYPE_MMS134S || data->type == TYPE_MMS136)
    217		touch_size = packet_size / MMS136_EVENT_SIZE;
    218	else
    219		touch_size = packet_size / MMS114_EVENT_SIZE;
    220
    221	error = __mms114_read_reg(data, MMS114_INFORMATION, packet_size,
    222			(u8 *)touch);
    223	if (error < 0)
    224		goto out;
    225
    226	for (index = 0; index < touch_size; index++)
    227		mms114_process_mt(data, touch + index);
    228
    229	input_mt_report_pointer_emulation(data->input_dev, true);
    230	input_sync(data->input_dev);
    231
    232out:
    233	return IRQ_HANDLED;
    234}
    235
    236static int mms114_set_active(struct mms114_data *data, bool active)
    237{
    238	int val;
    239
    240	val = mms114_read_reg(data, MMS114_MODE_CONTROL);
    241	if (val < 0)
    242		return val;
    243
    244	val &= ~MMS114_OPERATION_MODE_MASK;
    245
    246	/* If active is false, sleep mode */
    247	if (active)
    248		val |= MMS114_ACTIVE;
    249
    250	return mms114_write_reg(data, MMS114_MODE_CONTROL, val);
    251}
    252
    253static int mms114_get_version(struct mms114_data *data)
    254{
    255	struct device *dev = &data->client->dev;
    256	u8 buf[6];
    257	int group;
    258	int error;
    259
    260	switch (data->type) {
    261	case TYPE_MMS345L:
    262		error = __mms114_read_reg(data, MMS152_FW_REV, 3, buf);
    263		if (error)
    264			return error;
    265
    266		dev_info(dev, "TSP FW Rev: bootloader 0x%x / core 0x%x / config 0x%x\n",
    267			 buf[0], buf[1], buf[2]);
    268		break;
    269
    270	case TYPE_MMS152:
    271		error = __mms114_read_reg(data, MMS152_FW_REV, 3, buf);
    272		if (error)
    273			return error;
    274
    275		group = i2c_smbus_read_byte_data(data->client,
    276						  MMS152_COMPAT_GROUP);
    277		if (group < 0)
    278			return group;
    279
    280		dev_info(dev, "TSP FW Rev: bootloader 0x%x / core 0x%x / config 0x%x, Compat group: %c\n",
    281			 buf[0], buf[1], buf[2], group);
    282		break;
    283
    284	case TYPE_MMS114:
    285	case TYPE_MMS134S:
    286	case TYPE_MMS136:
    287		error = __mms114_read_reg(data, MMS114_TSP_REV, 6, buf);
    288		if (error)
    289			return error;
    290
    291		dev_info(dev, "TSP Rev: 0x%x, HW Rev: 0x%x, Firmware Ver: 0x%x\n",
    292			 buf[0], buf[1], buf[3]);
    293		break;
    294	}
    295
    296	return 0;
    297}
    298
    299static int mms114_setup_regs(struct mms114_data *data)
    300{
    301	const struct touchscreen_properties *props = &data->props;
    302	int val;
    303	int error;
    304
    305	error = mms114_get_version(data);
    306	if (error < 0)
    307		return error;
    308
    309	/* MMS114, MMS134S and MMS136 have configuration and power on registers */
    310	if (data->type != TYPE_MMS114 && data->type != TYPE_MMS134S &&
    311	    data->type != TYPE_MMS136)
    312		return 0;
    313
    314	error = mms114_set_active(data, true);
    315	if (error < 0)
    316		return error;
    317
    318	val = (props->max_x >> 8) & 0xf;
    319	val |= ((props->max_y >> 8) & 0xf) << 4;
    320	error = mms114_write_reg(data, MMS114_XY_RESOLUTION_H, val);
    321	if (error < 0)
    322		return error;
    323
    324	val = props->max_x & 0xff;
    325	error = mms114_write_reg(data, MMS114_X_RESOLUTION, val);
    326	if (error < 0)
    327		return error;
    328
    329	val = props->max_x & 0xff;
    330	error = mms114_write_reg(data, MMS114_Y_RESOLUTION, val);
    331	if (error < 0)
    332		return error;
    333
    334	if (data->contact_threshold) {
    335		error = mms114_write_reg(data, MMS114_CONTACT_THRESHOLD,
    336				data->contact_threshold);
    337		if (error < 0)
    338			return error;
    339	}
    340
    341	if (data->moving_threshold) {
    342		error = mms114_write_reg(data, MMS114_MOVING_THRESHOLD,
    343				data->moving_threshold);
    344		if (error < 0)
    345			return error;
    346	}
    347
    348	return 0;
    349}
    350
    351static int mms114_start(struct mms114_data *data)
    352{
    353	struct i2c_client *client = data->client;
    354	int error;
    355
    356	error = regulator_enable(data->core_reg);
    357	if (error) {
    358		dev_err(&client->dev, "Failed to enable avdd: %d\n", error);
    359		return error;
    360	}
    361
    362	error = regulator_enable(data->io_reg);
    363	if (error) {
    364		dev_err(&client->dev, "Failed to enable vdd: %d\n", error);
    365		regulator_disable(data->core_reg);
    366		return error;
    367	}
    368
    369	msleep(MMS114_POWERON_DELAY);
    370
    371	error = mms114_setup_regs(data);
    372	if (error < 0) {
    373		regulator_disable(data->io_reg);
    374		regulator_disable(data->core_reg);
    375		return error;
    376	}
    377
    378	enable_irq(client->irq);
    379
    380	return 0;
    381}
    382
    383static void mms114_stop(struct mms114_data *data)
    384{
    385	struct i2c_client *client = data->client;
    386	int error;
    387
    388	disable_irq(client->irq);
    389
    390	error = regulator_disable(data->io_reg);
    391	if (error)
    392		dev_warn(&client->dev, "Failed to disable vdd: %d\n", error);
    393
    394	error = regulator_disable(data->core_reg);
    395	if (error)
    396		dev_warn(&client->dev, "Failed to disable avdd: %d\n", error);
    397}
    398
    399static int mms114_input_open(struct input_dev *dev)
    400{
    401	struct mms114_data *data = input_get_drvdata(dev);
    402
    403	return mms114_start(data);
    404}
    405
    406static void mms114_input_close(struct input_dev *dev)
    407{
    408	struct mms114_data *data = input_get_drvdata(dev);
    409
    410	mms114_stop(data);
    411}
    412
    413static int mms114_parse_legacy_bindings(struct mms114_data *data)
    414{
    415	struct device *dev = &data->client->dev;
    416	struct touchscreen_properties *props = &data->props;
    417
    418	if (device_property_read_u32(dev, "x-size", &props->max_x)) {
    419		dev_dbg(dev, "failed to get legacy x-size property\n");
    420		return -EINVAL;
    421	}
    422
    423	if (device_property_read_u32(dev, "y-size", &props->max_y)) {
    424		dev_dbg(dev, "failed to get legacy y-size property\n");
    425		return -EINVAL;
    426	}
    427
    428	device_property_read_u32(dev, "contact-threshold",
    429				&data->contact_threshold);
    430	device_property_read_u32(dev, "moving-threshold",
    431				&data->moving_threshold);
    432
    433	if (device_property_read_bool(dev, "x-invert"))
    434		props->invert_x = true;
    435	if (device_property_read_bool(dev, "y-invert"))
    436		props->invert_y = true;
    437
    438	props->swap_x_y = false;
    439
    440	return 0;
    441}
    442
    443static int mms114_probe(struct i2c_client *client,
    444				  const struct i2c_device_id *id)
    445{
    446	struct mms114_data *data;
    447	struct input_dev *input_dev;
    448	const void *match_data;
    449	int error;
    450
    451	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
    452		dev_err(&client->dev, "Not supported I2C adapter\n");
    453		return -ENODEV;
    454	}
    455
    456	data = devm_kzalloc(&client->dev, sizeof(struct mms114_data),
    457			    GFP_KERNEL);
    458	input_dev = devm_input_allocate_device(&client->dev);
    459	if (!data || !input_dev) {
    460		dev_err(&client->dev, "Failed to allocate memory\n");
    461		return -ENOMEM;
    462	}
    463
    464	data->client = client;
    465	data->input_dev = input_dev;
    466
    467	match_data = device_get_match_data(&client->dev);
    468	if (!match_data)
    469		return -EINVAL;
    470
    471	data->type = (enum mms_type)match_data;
    472
    473	input_set_capability(input_dev, EV_ABS, ABS_MT_POSITION_X);
    474	input_set_capability(input_dev, EV_ABS, ABS_MT_POSITION_Y);
    475	input_set_abs_params(input_dev, ABS_MT_PRESSURE, 0, 255, 0, 0);
    476	input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR,
    477			     0, MMS114_MAX_AREA, 0, 0);
    478
    479	touchscreen_parse_properties(input_dev, true, &data->props);
    480	if (!data->props.max_x || !data->props.max_y) {
    481		dev_dbg(&client->dev,
    482			"missing X/Y size properties, trying legacy bindings\n");
    483		error = mms114_parse_legacy_bindings(data);
    484		if (error)
    485			return error;
    486
    487		input_set_abs_params(input_dev, ABS_MT_POSITION_X,
    488				     0, data->props.max_x, 0, 0);
    489		input_set_abs_params(input_dev, ABS_MT_POSITION_Y,
    490				     0, data->props.max_y, 0, 0);
    491	}
    492
    493	if (data->type == TYPE_MMS114 || data->type == TYPE_MMS134S ||
    494	    data->type == TYPE_MMS136) {
    495		/*
    496		 * The firmware handles movement and pressure fuzz, so
    497		 * don't duplicate that in software.
    498		 */
    499		data->moving_threshold = input_abs_get_fuzz(input_dev,
    500							    ABS_MT_POSITION_X);
    501		data->contact_threshold = input_abs_get_fuzz(input_dev,
    502							     ABS_MT_PRESSURE);
    503		input_abs_set_fuzz(input_dev, ABS_MT_POSITION_X, 0);
    504		input_abs_set_fuzz(input_dev, ABS_MT_POSITION_Y, 0);
    505		input_abs_set_fuzz(input_dev, ABS_MT_PRESSURE, 0);
    506	}
    507
    508	input_dev->name = devm_kasprintf(&client->dev, GFP_KERNEL,
    509					 "MELFAS MMS%d Touchscreen",
    510					 data->type);
    511	if (!input_dev->name)
    512		return -ENOMEM;
    513
    514	input_dev->id.bustype = BUS_I2C;
    515	input_dev->dev.parent = &client->dev;
    516	input_dev->open = mms114_input_open;
    517	input_dev->close = mms114_input_close;
    518
    519	error = input_mt_init_slots(input_dev, MMS114_MAX_TOUCH,
    520				    INPUT_MT_DIRECT);
    521	if (error)
    522		return error;
    523
    524	input_set_drvdata(input_dev, data);
    525	i2c_set_clientdata(client, data);
    526
    527	data->core_reg = devm_regulator_get(&client->dev, "avdd");
    528	if (IS_ERR(data->core_reg)) {
    529		error = PTR_ERR(data->core_reg);
    530		dev_err(&client->dev,
    531			"Unable to get the Core regulator (%d)\n", error);
    532		return error;
    533	}
    534
    535	data->io_reg = devm_regulator_get(&client->dev, "vdd");
    536	if (IS_ERR(data->io_reg)) {
    537		error = PTR_ERR(data->io_reg);
    538		dev_err(&client->dev,
    539			"Unable to get the IO regulator (%d)\n", error);
    540		return error;
    541	}
    542
    543	error = devm_request_threaded_irq(&client->dev, client->irq,
    544					  NULL, mms114_interrupt,
    545					  IRQF_ONESHOT | IRQF_NO_AUTOEN,
    546					  dev_name(&client->dev), data);
    547	if (error) {
    548		dev_err(&client->dev, "Failed to register interrupt\n");
    549		return error;
    550	}
    551
    552	error = input_register_device(data->input_dev);
    553	if (error) {
    554		dev_err(&client->dev, "Failed to register input device\n");
    555		return error;
    556	}
    557
    558	return 0;
    559}
    560
    561static int __maybe_unused mms114_suspend(struct device *dev)
    562{
    563	struct i2c_client *client = to_i2c_client(dev);
    564	struct mms114_data *data = i2c_get_clientdata(client);
    565	struct input_dev *input_dev = data->input_dev;
    566	int id;
    567
    568	/* Release all touch */
    569	for (id = 0; id < MMS114_MAX_TOUCH; id++) {
    570		input_mt_slot(input_dev, id);
    571		input_mt_report_slot_inactive(input_dev);
    572	}
    573
    574	input_mt_report_pointer_emulation(input_dev, true);
    575	input_sync(input_dev);
    576
    577	mutex_lock(&input_dev->mutex);
    578	if (input_device_enabled(input_dev))
    579		mms114_stop(data);
    580	mutex_unlock(&input_dev->mutex);
    581
    582	return 0;
    583}
    584
    585static int __maybe_unused mms114_resume(struct device *dev)
    586{
    587	struct i2c_client *client = to_i2c_client(dev);
    588	struct mms114_data *data = i2c_get_clientdata(client);
    589	struct input_dev *input_dev = data->input_dev;
    590	int error;
    591
    592	mutex_lock(&input_dev->mutex);
    593	if (input_device_enabled(input_dev)) {
    594		error = mms114_start(data);
    595		if (error < 0) {
    596			mutex_unlock(&input_dev->mutex);
    597			return error;
    598		}
    599	}
    600	mutex_unlock(&input_dev->mutex);
    601
    602	return 0;
    603}
    604
    605static SIMPLE_DEV_PM_OPS(mms114_pm_ops, mms114_suspend, mms114_resume);
    606
    607static const struct i2c_device_id mms114_id[] = {
    608	{ "mms114", 0 },
    609	{ }
    610};
    611MODULE_DEVICE_TABLE(i2c, mms114_id);
    612
    613#ifdef CONFIG_OF
    614static const struct of_device_id mms114_dt_match[] = {
    615	{
    616		.compatible = "melfas,mms114",
    617		.data = (void *)TYPE_MMS114,
    618	}, {
    619		.compatible = "melfas,mms134s",
    620		.data = (void *)TYPE_MMS134S,
    621	}, {
    622		.compatible = "melfas,mms136",
    623		.data = (void *)TYPE_MMS136,
    624	}, {
    625		.compatible = "melfas,mms152",
    626		.data = (void *)TYPE_MMS152,
    627	}, {
    628		.compatible = "melfas,mms345l",
    629		.data = (void *)TYPE_MMS345L,
    630	},
    631	{ }
    632};
    633MODULE_DEVICE_TABLE(of, mms114_dt_match);
    634#endif
    635
    636static struct i2c_driver mms114_driver = {
    637	.driver = {
    638		.name	= "mms114",
    639		.pm	= &mms114_pm_ops,
    640		.of_match_table = of_match_ptr(mms114_dt_match),
    641	},
    642	.probe		= mms114_probe,
    643	.id_table	= mms114_id,
    644};
    645
    646module_i2c_driver(mms114_driver);
    647
    648/* Module information */
    649MODULE_AUTHOR("Joonyoung Shim <jy0922.shim@samsung.com>");
    650MODULE_DESCRIPTION("MELFAS mms114 Touchscreen driver");
    651MODULE_LICENSE("GPL v2");