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