xref: /linux/drivers/input/touchscreen/cyttsp_i2c.c (revision 3a39d672e7f48b8d6b91a09afa4b55352773b4b5)
197fb5e8dSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
24065d1e7SJavier Martinez Canillas /*
39664877eSFerruh Yigit  * cyttsp_i2c.c
44065d1e7SJavier Martinez Canillas  * Cypress TrueTouch(TM) Standard Product (TTSP) I2C touchscreen driver.
54065d1e7SJavier Martinez Canillas  * For use with Cypress Txx3xx parts.
64065d1e7SJavier Martinez Canillas  * Supported parts include:
74065d1e7SJavier Martinez Canillas  * CY8CTST341
84065d1e7SJavier Martinez Canillas  * CY8CTMA340
94065d1e7SJavier Martinez Canillas  *
104065d1e7SJavier Martinez Canillas  * Copyright (C) 2009, 2010, 2011 Cypress Semiconductor, Inc.
114065d1e7SJavier Martinez Canillas  * Copyright (C) 2012 Javier Martinez Canillas <javier@dowhile0.org>
124065d1e7SJavier Martinez Canillas  *
139664877eSFerruh Yigit  * Contact Cypress Semiconductor at www.cypress.com <ttdrivers@cypress.com>
144065d1e7SJavier Martinez Canillas  */
154065d1e7SJavier Martinez Canillas 
164065d1e7SJavier Martinez Canillas #include "cyttsp_core.h"
174065d1e7SJavier Martinez Canillas 
184065d1e7SJavier Martinez Canillas #include <linux/i2c.h>
194065d1e7SJavier Martinez Canillas #include <linux/input.h>
204065d1e7SJavier Martinez Canillas 
21d27ac0fbSDmitry Torokhov #define CY_I2C_NAME		"cyttsp-i2c"
22d27ac0fbSDmitry Torokhov 
234065d1e7SJavier Martinez Canillas #define CY_I2C_DATA_SIZE	128
244065d1e7SJavier Martinez Canillas 
cyttsp_i2c_read_block_data(struct device * dev,u8 * xfer_buf,u16 addr,u8 length,void * values)25*25162a4fSDmitry Torokhov static int cyttsp_i2c_read_block_data(struct device *dev, u8 *xfer_buf,
26*25162a4fSDmitry Torokhov 				      u16 addr, u8 length, void *values)
27*25162a4fSDmitry Torokhov {
28*25162a4fSDmitry Torokhov 	struct i2c_client *client = to_i2c_client(dev);
29*25162a4fSDmitry Torokhov 	u8 client_addr = client->addr | ((addr >> 8) & 0x1);
30*25162a4fSDmitry Torokhov 	u8 addr_lo = addr & 0xFF;
31*25162a4fSDmitry Torokhov 	struct i2c_msg msgs[] = {
32*25162a4fSDmitry Torokhov 		{
33*25162a4fSDmitry Torokhov 			.addr = client_addr,
34*25162a4fSDmitry Torokhov 			.flags = 0,
35*25162a4fSDmitry Torokhov 			.len = 1,
36*25162a4fSDmitry Torokhov 			.buf = &addr_lo,
37*25162a4fSDmitry Torokhov 		},
38*25162a4fSDmitry Torokhov 		{
39*25162a4fSDmitry Torokhov 			.addr = client_addr,
40*25162a4fSDmitry Torokhov 			.flags = I2C_M_RD,
41*25162a4fSDmitry Torokhov 			.len = length,
42*25162a4fSDmitry Torokhov 			.buf = values,
43*25162a4fSDmitry Torokhov 		},
44*25162a4fSDmitry Torokhov 	};
45*25162a4fSDmitry Torokhov 	int retval;
46*25162a4fSDmitry Torokhov 
47*25162a4fSDmitry Torokhov 	retval = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
48*25162a4fSDmitry Torokhov 	if (retval < 0)
49*25162a4fSDmitry Torokhov 		return retval;
50*25162a4fSDmitry Torokhov 
51*25162a4fSDmitry Torokhov 	return retval != ARRAY_SIZE(msgs) ? -EIO : 0;
52*25162a4fSDmitry Torokhov }
53*25162a4fSDmitry Torokhov 
cyttsp_i2c_write_block_data(struct device * dev,u8 * xfer_buf,u16 addr,u8 length,const void * values)54*25162a4fSDmitry Torokhov static int cyttsp_i2c_write_block_data(struct device *dev, u8 *xfer_buf,
55*25162a4fSDmitry Torokhov 				       u16 addr, u8 length, const void *values)
56*25162a4fSDmitry Torokhov {
57*25162a4fSDmitry Torokhov 	struct i2c_client *client = to_i2c_client(dev);
58*25162a4fSDmitry Torokhov 	u8 client_addr = client->addr | ((addr >> 8) & 0x1);
59*25162a4fSDmitry Torokhov 	u8 addr_lo = addr & 0xFF;
60*25162a4fSDmitry Torokhov 	struct i2c_msg msgs[] = {
61*25162a4fSDmitry Torokhov 		{
62*25162a4fSDmitry Torokhov 			.addr = client_addr,
63*25162a4fSDmitry Torokhov 			.flags = 0,
64*25162a4fSDmitry Torokhov 			.len = length + 1,
65*25162a4fSDmitry Torokhov 			.buf = xfer_buf,
66*25162a4fSDmitry Torokhov 		},
67*25162a4fSDmitry Torokhov 	};
68*25162a4fSDmitry Torokhov 	int retval;
69*25162a4fSDmitry Torokhov 
70*25162a4fSDmitry Torokhov 	xfer_buf[0] = addr_lo;
71*25162a4fSDmitry Torokhov 	memcpy(&xfer_buf[1], values, length);
72*25162a4fSDmitry Torokhov 
73*25162a4fSDmitry Torokhov 	retval = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
74*25162a4fSDmitry Torokhov 	if (retval < 0)
75*25162a4fSDmitry Torokhov 		return retval;
76*25162a4fSDmitry Torokhov 
77*25162a4fSDmitry Torokhov 	return retval != ARRAY_SIZE(msgs) ? -EIO : 0;
78*25162a4fSDmitry Torokhov }
79*25162a4fSDmitry Torokhov 
804065d1e7SJavier Martinez Canillas static const struct cyttsp_bus_ops cyttsp_i2c_bus_ops = {
814065d1e7SJavier Martinez Canillas 	.bustype	= BUS_I2C,
824065d1e7SJavier Martinez Canillas 	.write		= cyttsp_i2c_write_block_data,
834065d1e7SJavier Martinez Canillas 	.read           = cyttsp_i2c_read_block_data,
844065d1e7SJavier Martinez Canillas };
854065d1e7SJavier Martinez Canillas 
cyttsp_i2c_probe(struct i2c_client * client)86667c577aSUwe Kleine-König static int cyttsp_i2c_probe(struct i2c_client *client)
874065d1e7SJavier Martinez Canillas {
884065d1e7SJavier Martinez Canillas 	struct cyttsp *ts;
894065d1e7SJavier Martinez Canillas 
904065d1e7SJavier Martinez Canillas 	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
914065d1e7SJavier Martinez Canillas 		dev_err(&client->dev, "I2C functionality not Supported\n");
924065d1e7SJavier Martinez Canillas 		return -EIO;
934065d1e7SJavier Martinez Canillas 	}
944065d1e7SJavier Martinez Canillas 
954065d1e7SJavier Martinez Canillas 	ts = cyttsp_probe(&cyttsp_i2c_bus_ops, &client->dev, client->irq,
964065d1e7SJavier Martinez Canillas 			  CY_I2C_DATA_SIZE);
974065d1e7SJavier Martinez Canillas 
984065d1e7SJavier Martinez Canillas 	if (IS_ERR(ts))
994065d1e7SJavier Martinez Canillas 		return PTR_ERR(ts);
1004065d1e7SJavier Martinez Canillas 
1014065d1e7SJavier Martinez Canillas 	i2c_set_clientdata(client, ts);
1024065d1e7SJavier Martinez Canillas 	return 0;
1034065d1e7SJavier Martinez Canillas }
1044065d1e7SJavier Martinez Canillas 
1054065d1e7SJavier Martinez Canillas static const struct i2c_device_id cyttsp_i2c_id[] = {
1065852f2afSUwe Kleine-König 	{ CY_I2C_NAME },
1074065d1e7SJavier Martinez Canillas 	{ }
1084065d1e7SJavier Martinez Canillas };
1094065d1e7SJavier Martinez Canillas MODULE_DEVICE_TABLE(i2c, cyttsp_i2c_id);
1104065d1e7SJavier Martinez Canillas 
111007704c9SLinus Walleij static const struct of_device_id cyttsp_of_i2c_match[] = {
112007704c9SLinus Walleij 	{ .compatible = "cypress,cy8ctma340", },
113007704c9SLinus Walleij 	{ .compatible = "cypress,cy8ctst341", },
114007704c9SLinus Walleij 	{ /* sentinel */ }
115007704c9SLinus Walleij };
116007704c9SLinus Walleij MODULE_DEVICE_TABLE(of, cyttsp_of_i2c_match);
117007704c9SLinus Walleij 
1184065d1e7SJavier Martinez Canillas static struct i2c_driver cyttsp_i2c_driver = {
1194065d1e7SJavier Martinez Canillas 	.driver = {
1204065d1e7SJavier Martinez Canillas 		.name	= CY_I2C_NAME,
121c3c2f2bcSJonathan Cameron 		.pm	= pm_sleep_ptr(&cyttsp_pm_ops),
122007704c9SLinus Walleij 		.of_match_table = cyttsp_of_i2c_match,
1234065d1e7SJavier Martinez Canillas 	},
124d8bde56dSUwe Kleine-König 	.probe		= cyttsp_i2c_probe,
1254065d1e7SJavier Martinez Canillas 	.id_table	= cyttsp_i2c_id,
1264065d1e7SJavier Martinez Canillas };
1274065d1e7SJavier Martinez Canillas 
1284a533835SDmitry Torokhov module_i2c_driver(cyttsp_i2c_driver);
1294065d1e7SJavier Martinez Canillas 
1304065d1e7SJavier Martinez Canillas MODULE_LICENSE("GPL");
1314065d1e7SJavier Martinez Canillas MODULE_DESCRIPTION("Cypress TrueTouch(R) Standard Product (TTSP) I2C driver");
1324065d1e7SJavier Martinez Canillas MODULE_AUTHOR("Cypress");
133