xref: /OK3568_Linux_fs/kernel/drivers/input/touchscreen/focaltech_touch_ft5436/focaltech_i2c.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 /*
2  *
3  * FocalTech TouchScreen driver.
4  *
5  * Copyright (c) 2012-2019, FocalTech Systems, Ltd., all rights reserved.
6  *
7  * This software is licensed under the terms of the GNU General Public
8  * License version 2, as published by the Free Software Foundation, and
9  * may be copied, distributed, and modified under those terms.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  */
17 
18 /************************************************************************
19 *
20 * File Name: focaltech_i2c.c
21 *
22 * Author: Focaltech Driver Team
23 *
24 * Created: 2016-08-04
25 *
26 * Abstract: i2c communication with TP
27 *
28 * Version: v1.0
29 *
30 * Revision History:
31 *
32 ************************************************************************/
33 
34 /*****************************************************************************
35 * Included header files
36 *****************************************************************************/
37 #include "focaltech_core.h"
38 
39 /*****************************************************************************
40 * Private constant and macro definitions using #define
41 *****************************************************************************/
42 #define I2C_RETRY_NUMBER                    3
43 #define I2C_BUF_LENGTH                      256
44 
45 /*****************************************************************************
46 * Private enumerations, structures and unions using typedef
47 *****************************************************************************/
48 
49 /*****************************************************************************
50 * Static variables
51 *****************************************************************************/
52 
53 /*****************************************************************************
54 * Global variable or extern global variabls/functions
55 *****************************************************************************/
56 
57 /*****************************************************************************
58 * Static function prototypes
59 *****************************************************************************/
60 
61 /*****************************************************************************
62 * functions body
63 *****************************************************************************/
fts_read(u8 * cmd,u32 cmdlen,u8 * data,u32 datalen)64 int fts_read(u8 *cmd, u32 cmdlen, u8 *data, u32 datalen)
65 {
66     int ret = 0;
67     int i = 0;
68     struct fts_ts_data *ts_data = fts_data;
69     struct i2c_msg msg_list[2];
70     struct i2c_msg *msg = NULL;
71     int msg_num = 0;
72 
73     /* must have data when read */
74     if (!ts_data || !ts_data->client || !data || !datalen
75         || (datalen >= I2C_BUF_LENGTH) || (cmdlen >= I2C_BUF_LENGTH)) {
76         FTS_ERROR("fts_data/client/cmdlen(%d)/data/datalen(%d) is invalid",
77                   cmdlen, datalen);
78         return -EINVAL;
79     }
80 
81     mutex_lock(&ts_data->bus_lock);
82     memset(&msg_list[0], 0, sizeof(struct i2c_msg));
83     memset(&msg_list[1], 0, sizeof(struct i2c_msg));
84     memcpy(ts_data->bus_tx_buf, cmd, cmdlen);
85     msg_list[0].addr = ts_data->client->addr;
86     msg_list[0].flags = 0;
87     msg_list[0].len = cmdlen;
88     msg_list[0].buf = ts_data->bus_tx_buf;
89     msg_list[1].addr = ts_data->client->addr;
90     msg_list[1].flags = I2C_M_RD;
91     msg_list[1].len = datalen;
92     msg_list[1].buf = ts_data->bus_rx_buf;
93     if (cmd && cmdlen) {
94         msg = &msg_list[0];
95         msg_num = 2;
96     } else {
97         msg = &msg_list[1];
98         msg_num = 1;
99     }
100 
101     for (i = 0; i < I2C_RETRY_NUMBER; i++) {
102         ret = i2c_transfer(ts_data->client->adapter, msg, msg_num);
103         if (ret < 0) {
104             FTS_ERROR("i2c_transfer(read) fail,ret:%d", ret);
105         } else {
106             memcpy(data, ts_data->bus_rx_buf, datalen);
107             break;
108         }
109     }
110 
111     mutex_unlock(&ts_data->bus_lock);
112     return ret;
113 }
114 
fts_write(u8 * writebuf,u32 writelen)115 int fts_write(u8 *writebuf, u32 writelen)
116 {
117     int ret = 0;
118     int i = 0;
119     struct fts_ts_data *ts_data = fts_data;
120     struct i2c_msg msgs;
121 
122     if (!ts_data || !ts_data->client || !writebuf || !writelen
123         || (writelen >= I2C_BUF_LENGTH)) {
124         FTS_ERROR("fts_data/client/data/datalen(%d) is invalid", writelen);
125         return -EINVAL;
126     }
127 
128     mutex_lock(&ts_data->bus_lock);
129     memset(&msgs, 0, sizeof(struct i2c_msg));
130     memcpy(ts_data->bus_tx_buf, writebuf, writelen);
131     msgs.addr = ts_data->client->addr;
132     msgs.flags = 0;
133     msgs.len = writelen;
134     msgs.buf = ts_data->bus_tx_buf;
135     for (i = 0; i < I2C_RETRY_NUMBER; i++) {
136         ret = i2c_transfer(ts_data->client->adapter, &msgs, 1);
137         if (ret < 0) {
138             FTS_ERROR("i2c_transfer(write) fail,ret:%d", ret);
139         } else {
140             break;
141         }
142     }
143     mutex_unlock(&ts_data->bus_lock);
144     return ret;
145 }
146 
fts_read_reg(u8 addr,u8 * value)147 int fts_read_reg(u8 addr, u8 *value)
148 {
149     return fts_read(&addr, 1, value, 1);
150 }
151 
fts_write_reg(u8 addr,u8 value)152 int fts_write_reg(u8 addr, u8 value)
153 {
154     u8 buf[2] = { 0 };
155 
156     buf[0] = addr;
157     buf[1] = value;
158     return fts_write(buf, sizeof(buf));
159 }
160 
fts_bus_init(struct fts_ts_data * ts_data)161 int fts_bus_init(struct fts_ts_data *ts_data)
162 {
163     FTS_FUNC_ENTER();
164     ts_data->bus_tx_buf = kzalloc(I2C_BUF_LENGTH, GFP_KERNEL);
165     if (NULL == ts_data->bus_tx_buf) {
166         FTS_ERROR("failed to allocate memory for bus_tx_buf");
167         return -ENOMEM;
168     }
169 
170     ts_data->bus_rx_buf = kzalloc(I2C_BUF_LENGTH, GFP_KERNEL);
171     if (NULL == ts_data->bus_rx_buf) {
172         FTS_ERROR("failed to allocate memory for bus_rx_buf");
173         return -ENOMEM;
174     }
175     FTS_FUNC_EXIT();
176     return 0;
177 }
178 
fts_bus_exit(struct fts_ts_data * ts_data)179 int fts_bus_exit(struct fts_ts_data *ts_data)
180 {
181     FTS_FUNC_ENTER();
182     if (ts_data && ts_data->bus_tx_buf) {
183         kfree(ts_data->bus_tx_buf);
184         ts_data->bus_tx_buf = NULL;
185     }
186 
187     if (ts_data && ts_data->bus_rx_buf) {
188         kfree(ts_data->bus_rx_buf);
189         ts_data->bus_rx_buf = NULL;
190     }
191     FTS_FUNC_EXIT();
192     return 0;
193 }