1 /*
2 * cyttsp5_i2c.c
3 * Parade TrueTouch(TM) Standard Product V5 I2C Module.
4 * For use with Parade touchscreen controllers.
5 * Supported parts include:
6 * CYTMA5XX
7 * CYTMA448
8 * CYTMA445A
9 * CYTT21XXX
10 * CYTT31XXX
11 *
12 * Copyright (C) 2015 Parade Technologies
13 * Copyright (C) 2012-2015 Cypress Semiconductor
14 *
15 * This program is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU General Public License
17 * version 2, and only version 2, as published by the
18 * Free Software Foundation.
19 *
20 * This program is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
24 *
25 * Contact Parade Technologies at www.paradetech.com <ttdrivers@paradetech.com>
26 *
27 */
28
29 #include "cyttsp5_regs.h"
30
31 #include <linux/i2c.h>
32 #include <linux/version.h>
33
34 #define CY_I2C_DATA_SIZE (2 * 256)
35
36 static int cyttsp5_i2c_remove(struct i2c_client *client);
37
cyttsp5_i2c_read_default(struct device * dev,void * buf,int size)38 static int cyttsp5_i2c_read_default(struct device *dev, void *buf, int size)
39 {
40 struct i2c_client *client = to_i2c_client(dev);
41 int rc;
42
43 if (!buf || !size || size > CY_I2C_DATA_SIZE)
44 return -EINVAL;
45 //printk("*****cyttsp5_i2c_read_default size=%d\n", size);
46 rc = i2c_master_recv(client, buf, size);
47
48 return (rc < 0) ? rc : rc != size ? -EIO : 0;
49 }
50
cyttsp5_i2c_read_default_nosize(struct device * dev,u8 * buf,u32 max)51 static int cyttsp5_i2c_read_default_nosize(struct device *dev, u8 *buf, u32 max)
52 {
53 struct i2c_client *client = to_i2c_client(dev);
54 struct i2c_msg msgs[2];
55 u8 msg_count = 1;
56 int rc;
57 u32 size;
58
59 if (!buf)
60 return -EINVAL;
61
62 //printk("*****cyttsp5_i2c_read_default_nosize max=%d\n", max);
63 msgs[0].addr = client->addr;
64 msgs[0].flags = (client->flags & I2C_M_TEN) | I2C_M_RD;
65 msgs[0].len = 2;
66 msgs[0].buf = buf;
67 rc = i2c_transfer(client->adapter, msgs, msg_count);
68 if (rc < 0 || rc != msg_count)
69 return (rc < 0) ? rc : -EIO;
70
71 size = get_unaligned_le16(&buf[0]);
72 if (!size || size == 2 || size >= CY_PIP_1P7_EMPTY_BUF)
73 /* Before PIP 1.7, empty buffer is 0x0002;
74 From PIP 1.7, empty buffer is 0xFFXX */
75 return 0;
76
77 if (size > max)
78 return -EINVAL;
79
80 rc = i2c_master_recv(client, buf, size);
81
82 return (rc < 0) ? rc : rc != (int)size ? -EIO : 0;
83 }
84
cyttsp5_i2c_write_read_specific(struct device * dev,u8 write_len,u8 * write_buf,u8 * read_buf)85 static int cyttsp5_i2c_write_read_specific(struct device *dev, u8 write_len,
86 u8 *write_buf, u8 *read_buf)
87 {
88 struct i2c_client *client = to_i2c_client(dev);
89 struct i2c_msg msgs[2];
90 u8 msg_count = 1;
91 int rc;
92
93 //printk("*****cyttsp5_i2c_write_read_specific 0x%x, 0x%x, len=%d\n", write_buf[0], write_buf[1],write_len);
94 if (!write_buf || !write_len)
95 return -EINVAL;
96
97 msgs[0].addr = client->addr;
98 msgs[0].flags = client->flags & I2C_M_TEN;
99 msgs[0].len = write_len;
100 msgs[0].buf = write_buf;
101 rc = i2c_transfer(client->adapter, msgs, msg_count);
102
103 //printk("*****cyttsp5_i2c_write_read_specific rc=%d\n", rc);
104 if (rc < 0 || rc != msg_count)
105 return (rc < 0) ? rc : -EIO;
106
107 rc = 0;
108
109 //printk("*****cyttsp5_i2c_write_read_specific read_buf=0x%x\n", read_buf);
110 if (read_buf)
111 rc = cyttsp5_i2c_read_default_nosize(dev, read_buf,
112 CY_I2C_DATA_SIZE);
113
114 return rc;
115 }
116
117 static struct cyttsp5_bus_ops cyttsp5_i2c_bus_ops = {
118 .bustype = BUS_I2C,
119 .read_default = cyttsp5_i2c_read_default,
120 .read_default_nosize = cyttsp5_i2c_read_default_nosize,
121 .write_read_specific = cyttsp5_i2c_write_read_specific,
122 };
123
124 #ifdef CONFIG_TOUCHSCREEN_CYPRESS_CYTTSP5_DEVICETREE_SUPPORT
125 static const struct of_device_id cyttsp5_i2c_of_match[] = {
126 { .compatible = "cy,cyttsp5_i2c_adapter", },
127 { }
128 };
129 MODULE_DEVICE_TABLE(of, cyttsp5_i2c_of_match);
130 #endif
131
cyttsp5_i2c_probe(struct i2c_client * client,const struct i2c_device_id * i2c_id)132 static int cyttsp5_i2c_probe(struct i2c_client *client,
133 const struct i2c_device_id *i2c_id)
134 {
135 struct device *dev = &client->dev;
136 #ifdef CONFIG_TOUCHSCREEN_CYPRESS_CYTTSP5_DEVICETREE_SUPPORT
137 const struct of_device_id *match;
138 #endif
139 struct cyttsp5_platform_data *pdata;
140 int rc;
141
142 printk("*****cyttsp5_i2c_probe start \n");
143 if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
144 dev_err(dev, "I2C functionality not Supported\n");
145 return -EIO;
146 }
147
148
149 #ifdef CONFIG_TOUCHSCREEN_CYPRESS_CYTTSP5_DEVICETREE_SUPPORT
150 match = of_match_device(of_match_ptr(cyttsp5_i2c_of_match), dev);
151 if (match) {
152 rc = cyttsp5_devtree_create_and_get_pdata(dev);
153 if (rc < 0)
154 return rc;
155 }
156 #endif
157 pdata = dev_get_platdata(dev);
158 if (pdata && pdata->core_pdata) {
159 char buf[32];
160 /* Call platform init function */
161 if (pdata->core_pdata->init) {
162 dev_info(dev, "%s: Init HW\n", __func__);
163 rc = pdata->core_pdata->init(pdata->core_pdata, 1, dev);
164 if (rc < 0) {
165 dev_err(dev, "%s: HW Init fail %d\n", __func__, rc);
166 return -EIO;
167 }
168 } else {
169 dev_info(dev, "%s: No HW INIT function\n", __func__);
170 }
171 rc = cyttsp5_i2c_read_default(&client->dev, buf, 16);
172 if (rc < 0) {
173 dev_err(dev, "%s, read_default rc=%d\n", __func__, rc);
174 return -ENODEV;
175 }
176 }
177 rc = cyttsp5_probe(&cyttsp5_i2c_bus_ops, &client->dev, client->irq,
178 CY_I2C_DATA_SIZE);
179
180 #ifdef CONFIG_TOUCHSCREEN_CYPRESS_CYTTSP5_DEVICETREE_SUPPORT
181 if (rc && match)
182 cyttsp5_devtree_clean_pdata(dev);
183 #endif
184 return rc;
185 }
186
cyttsp5_i2c_remove(struct i2c_client * client)187 static int cyttsp5_i2c_remove(struct i2c_client *client)
188 {
189 #ifdef CONFIG_TOUCHSCREEN_CYPRESS_CYTTSP5_DEVICETREE_SUPPORT
190 struct device *dev = &client->dev;
191 const struct of_device_id *match;
192 #endif
193 struct cyttsp5_core_data *cd = i2c_get_clientdata(client);
194
195 cyttsp5_release(cd);
196
197 #ifdef CONFIG_TOUCHSCREEN_CYPRESS_CYTTSP5_DEVICETREE_SUPPORT
198 match = of_match_device(of_match_ptr(cyttsp5_i2c_of_match), dev);
199 if (match)
200 cyttsp5_devtree_clean_pdata(dev);
201 #endif
202
203 return 0;
204 }
205
206 static const struct i2c_device_id cyttsp5_i2c_id[] = {
207 { CYTTSP5_I2C_NAME, 0, },
208 { }
209 };
210 MODULE_DEVICE_TABLE(i2c, cyttsp5_i2c_id);
211
212 static struct i2c_driver cyttsp5_i2c_driver = {
213 .driver = {
214 .name = CYTTSP5_I2C_NAME,
215 .owner = THIS_MODULE,
216 .pm = &cyttsp5_pm_ops,
217 #ifdef CONFIG_TOUCHSCREEN_CYPRESS_CYTTSP5_DEVICETREE_SUPPORT
218 .of_match_table = cyttsp5_i2c_of_match,
219 #endif
220 },
221 .probe = cyttsp5_i2c_probe,
222 .remove = cyttsp5_i2c_remove,
223 .id_table = cyttsp5_i2c_id,
224 };
225
226 #if (KERNEL_VERSION(3, 3, 0) <= LINUX_VERSION_CODE)
227 module_i2c_driver(cyttsp5_i2c_driver);
228 #else
cyttsp5_i2c_init(void)229 static int __init cyttsp5_i2c_init(void)
230 {
231 int rc = i2c_add_driver(&cyttsp5_i2c_driver);
232
233 pr_info("%s: Parade TTSP I2C Driver (Built %s) rc=%d\n",
234 __func__, CY_DRIVER_VERSION, rc);
235 return rc;
236 }
237 late_initcall(cyttsp5_i2c_init);
238
cyttsp5_i2c_exit(void)239 static void __exit cyttsp5_i2c_exit(void)
240 {
241 i2c_del_driver(&cyttsp5_i2c_driver);
242 }
243 module_exit(cyttsp5_i2c_exit);
244 #endif
245
246 MODULE_LICENSE("GPL");
247 MODULE_DESCRIPTION("Parade TrueTouch(R) Standard Product I2C driver");
248 MODULE_AUTHOR("Parade Technologies <ttdrivers@paradetech.com>");
249