1 | /* |
2 | * Copyright (c) 2015 - 2016 Red Hat, Inc |
3 | * Copyright (c) 2011, 2012 Synaptics Incorporated |
4 | * Copyright (c) 2011 Unixphere |
5 | * |
6 | * This program is free software; you can redistribute it and/or modify it |
7 | * under the terms of the GNU General Public License version 2 as published by |
8 | * the Free Software Foundation. |
9 | */ |
10 | |
11 | #include <linux/kernel.h> |
12 | #include <linux/delay.h> |
13 | #include <linux/i2c.h> |
14 | #include <linux/interrupt.h> |
15 | #include <linux/kconfig.h> |
16 | #include <linux/lockdep.h> |
17 | #include <linux/module.h> |
18 | #include <linux/pm.h> |
19 | #include <linux/rmi.h> |
20 | #include <linux/slab.h> |
21 | #include "rmi_driver.h" |
22 | |
23 | #define SMB_PROTOCOL_VERSION_ADDRESS 0xfd |
24 | #define SMB_MAX_COUNT 32 |
25 | #define RMI_SMB2_MAP_SIZE 8 /* 8 entry of 4 bytes each */ |
26 | #define RMI_SMB2_MAP_FLAGS_WE 0x01 |
27 | |
28 | struct mapping_table_entry { |
29 | __le16 rmiaddr; |
30 | u8 readcount; |
31 | u8 flags; |
32 | }; |
33 | |
34 | struct rmi_smb_xport { |
35 | struct rmi_transport_dev xport; |
36 | struct i2c_client *client; |
37 | |
38 | struct mutex page_mutex; |
39 | int page; |
40 | u8 table_index; |
41 | struct mutex mappingtable_mutex; |
42 | struct mapping_table_entry mapping_table[RMI_SMB2_MAP_SIZE]; |
43 | }; |
44 | |
45 | static int rmi_smb_get_version(struct rmi_smb_xport *rmi_smb) |
46 | { |
47 | struct i2c_client *client = rmi_smb->client; |
48 | int retval; |
49 | |
50 | /* Check if for SMBus new version device by reading version byte. */ |
51 | retval = i2c_smbus_read_byte_data(client, SMB_PROTOCOL_VERSION_ADDRESS); |
52 | if (retval < 0) { |
53 | dev_err(&client->dev, "failed to get SMBus version number!\n" ); |
54 | return retval; |
55 | } |
56 | |
57 | return retval + 1; |
58 | } |
59 | |
60 | /* SMB block write - wrapper over ic2_smb_write_block */ |
61 | static int smb_block_write(struct rmi_transport_dev *xport, |
62 | u8 commandcode, const void *buf, size_t len) |
63 | { |
64 | struct rmi_smb_xport *rmi_smb = |
65 | container_of(xport, struct rmi_smb_xport, xport); |
66 | struct i2c_client *client = rmi_smb->client; |
67 | int retval; |
68 | |
69 | retval = i2c_smbus_write_block_data(client, commandcode, len, buf); |
70 | |
71 | rmi_dbg(RMI_DEBUG_XPORT, &client->dev, |
72 | "wrote %zd bytes at %#04x: %d (%*ph)\n" , |
73 | len, commandcode, retval, (int)len, buf); |
74 | |
75 | return retval; |
76 | } |
77 | |
78 | /* |
79 | * The function to get command code for smbus operations and keeps |
80 | * records to the driver mapping table |
81 | */ |
82 | static int rmi_smb_get_command_code(struct rmi_transport_dev *xport, |
83 | u16 rmiaddr, int bytecount, bool isread, u8 *commandcode) |
84 | { |
85 | struct rmi_smb_xport *rmi_smb = |
86 | container_of(xport, struct rmi_smb_xport, xport); |
87 | struct mapping_table_entry new_map; |
88 | int i; |
89 | int retval = 0; |
90 | |
91 | mutex_lock(&rmi_smb->mappingtable_mutex); |
92 | |
93 | for (i = 0; i < RMI_SMB2_MAP_SIZE; i++) { |
94 | struct mapping_table_entry *entry = &rmi_smb->mapping_table[i]; |
95 | |
96 | if (le16_to_cpu(entry->rmiaddr) == rmiaddr) { |
97 | if (isread) { |
98 | if (entry->readcount == bytecount) |
99 | goto exit; |
100 | } else { |
101 | if (entry->flags & RMI_SMB2_MAP_FLAGS_WE) { |
102 | goto exit; |
103 | } |
104 | } |
105 | } |
106 | } |
107 | |
108 | i = rmi_smb->table_index; |
109 | rmi_smb->table_index = (i + 1) % RMI_SMB2_MAP_SIZE; |
110 | |
111 | /* constructs mapping table data entry. 4 bytes each entry */ |
112 | memset(&new_map, 0, sizeof(new_map)); |
113 | new_map.rmiaddr = cpu_to_le16(rmiaddr); |
114 | new_map.readcount = bytecount; |
115 | new_map.flags = !isread ? RMI_SMB2_MAP_FLAGS_WE : 0; |
116 | |
117 | retval = smb_block_write(xport, i + 0x80, &new_map, sizeof(new_map)); |
118 | if (retval < 0) { |
119 | /* |
120 | * if not written to device mapping table |
121 | * clear the driver mapping table records |
122 | */ |
123 | memset(&new_map, 0, sizeof(new_map)); |
124 | } |
125 | |
126 | /* save to the driver level mapping table */ |
127 | rmi_smb->mapping_table[i] = new_map; |
128 | |
129 | exit: |
130 | mutex_unlock(&rmi_smb->mappingtable_mutex); |
131 | |
132 | if (retval < 0) |
133 | return retval; |
134 | |
135 | *commandcode = i; |
136 | return 0; |
137 | } |
138 | |
139 | static int rmi_smb_write_block(struct rmi_transport_dev *xport, u16 rmiaddr, |
140 | const void *databuff, size_t len) |
141 | { |
142 | int retval = 0; |
143 | u8 commandcode; |
144 | struct rmi_smb_xport *rmi_smb = |
145 | container_of(xport, struct rmi_smb_xport, xport); |
146 | int cur_len = (int)len; |
147 | |
148 | mutex_lock(&rmi_smb->page_mutex); |
149 | |
150 | while (cur_len > 0) { |
151 | /* |
152 | * break into 32 bytes chunks to write get command code |
153 | */ |
154 | int block_len = min_t(int, len, SMB_MAX_COUNT); |
155 | |
156 | retval = rmi_smb_get_command_code(xport, rmiaddr, block_len, |
157 | false, &commandcode); |
158 | if (retval < 0) |
159 | goto exit; |
160 | |
161 | retval = smb_block_write(xport, commandcode, |
162 | databuff, block_len); |
163 | if (retval < 0) |
164 | goto exit; |
165 | |
166 | /* prepare to write next block of bytes */ |
167 | cur_len -= SMB_MAX_COUNT; |
168 | databuff += SMB_MAX_COUNT; |
169 | rmiaddr += SMB_MAX_COUNT; |
170 | } |
171 | exit: |
172 | mutex_unlock(&rmi_smb->page_mutex); |
173 | return retval; |
174 | } |
175 | |
176 | /* SMB block read - wrapper over ic2_smb_read_block */ |
177 | static int smb_block_read(struct rmi_transport_dev *xport, |
178 | u8 commandcode, void *buf, size_t len) |
179 | { |
180 | struct rmi_smb_xport *rmi_smb = |
181 | container_of(xport, struct rmi_smb_xport, xport); |
182 | struct i2c_client *client = rmi_smb->client; |
183 | int retval; |
184 | |
185 | retval = i2c_smbus_read_block_data(client, commandcode, buf); |
186 | if (retval < 0) |
187 | return retval; |
188 | |
189 | return retval; |
190 | } |
191 | |
192 | static int rmi_smb_read_block(struct rmi_transport_dev *xport, u16 rmiaddr, |
193 | void *databuff, size_t len) |
194 | { |
195 | struct rmi_smb_xport *rmi_smb = |
196 | container_of(xport, struct rmi_smb_xport, xport); |
197 | int retval; |
198 | u8 commandcode; |
199 | int cur_len = (int)len; |
200 | |
201 | mutex_lock(&rmi_smb->page_mutex); |
202 | memset(databuff, 0, len); |
203 | |
204 | while (cur_len > 0) { |
205 | /* break into 32 bytes chunks to write get command code */ |
206 | int block_len = min_t(int, cur_len, SMB_MAX_COUNT); |
207 | |
208 | retval = rmi_smb_get_command_code(xport, rmiaddr, block_len, |
209 | true, &commandcode); |
210 | if (retval < 0) |
211 | goto exit; |
212 | |
213 | retval = smb_block_read(xport, commandcode, |
214 | databuff, block_len); |
215 | if (retval < 0) |
216 | goto exit; |
217 | |
218 | /* prepare to read next block of bytes */ |
219 | cur_len -= SMB_MAX_COUNT; |
220 | databuff += SMB_MAX_COUNT; |
221 | rmiaddr += SMB_MAX_COUNT; |
222 | } |
223 | |
224 | retval = 0; |
225 | |
226 | exit: |
227 | mutex_unlock(&rmi_smb->page_mutex); |
228 | return retval; |
229 | } |
230 | |
231 | static void rmi_smb_clear_state(struct rmi_smb_xport *rmi_smb) |
232 | { |
233 | /* the mapping table has been flushed, discard the current one */ |
234 | mutex_lock(&rmi_smb->mappingtable_mutex); |
235 | memset(rmi_smb->mapping_table, 0, sizeof(rmi_smb->mapping_table)); |
236 | mutex_unlock(&rmi_smb->mappingtable_mutex); |
237 | } |
238 | |
239 | static int rmi_smb_enable_smbus_mode(struct rmi_smb_xport *rmi_smb) |
240 | { |
241 | int retval; |
242 | |
243 | /* we need to get the smbus version to activate the touchpad */ |
244 | retval = rmi_smb_get_version(rmi_smb); |
245 | if (retval < 0) |
246 | return retval; |
247 | |
248 | return 0; |
249 | } |
250 | |
251 | static int rmi_smb_reset(struct rmi_transport_dev *xport, u16 reset_addr) |
252 | { |
253 | struct rmi_smb_xport *rmi_smb = |
254 | container_of(xport, struct rmi_smb_xport, xport); |
255 | |
256 | rmi_smb_clear_state(rmi_smb); |
257 | |
258 | /* |
259 | * we do not call the actual reset command, it has to be handled in |
260 | * PS/2 or there will be races between PS/2 and SMBus. |
261 | * PS/2 should ensure that a psmouse_reset is called before |
262 | * intializing the device and after it has been removed to be in a known |
263 | * state. |
264 | */ |
265 | return rmi_smb_enable_smbus_mode(rmi_smb); |
266 | } |
267 | |
268 | static const struct rmi_transport_ops rmi_smb_ops = { |
269 | .write_block = rmi_smb_write_block, |
270 | .read_block = rmi_smb_read_block, |
271 | .reset = rmi_smb_reset, |
272 | }; |
273 | |
274 | static int rmi_smb_probe(struct i2c_client *client, |
275 | const struct i2c_device_id *id) |
276 | { |
277 | struct rmi_device_platform_data *pdata = dev_get_platdata(&client->dev); |
278 | struct rmi_smb_xport *rmi_smb; |
279 | int smbus_version; |
280 | int error; |
281 | |
282 | if (!pdata) { |
283 | dev_err(&client->dev, "no platform data, aborting\n" ); |
284 | return -ENOMEM; |
285 | } |
286 | |
287 | if (!i2c_check_functionality(client->adapter, |
288 | I2C_FUNC_SMBUS_READ_BLOCK_DATA | |
289 | I2C_FUNC_SMBUS_HOST_NOTIFY)) { |
290 | dev_err(&client->dev, |
291 | "adapter does not support required functionality\n" ); |
292 | return -ENODEV; |
293 | } |
294 | |
295 | if (client->irq <= 0) { |
296 | dev_err(&client->dev, "no IRQ provided, giving up\n" ); |
297 | return client->irq ? client->irq : -ENODEV; |
298 | } |
299 | |
300 | rmi_smb = devm_kzalloc(&client->dev, sizeof(struct rmi_smb_xport), |
301 | GFP_KERNEL); |
302 | if (!rmi_smb) |
303 | return -ENOMEM; |
304 | |
305 | rmi_dbg(RMI_DEBUG_XPORT, &client->dev, "Probing %s\n" , |
306 | dev_name(&client->dev)); |
307 | |
308 | rmi_smb->client = client; |
309 | mutex_init(&rmi_smb->page_mutex); |
310 | mutex_init(&rmi_smb->mappingtable_mutex); |
311 | |
312 | rmi_smb->xport.dev = &client->dev; |
313 | rmi_smb->xport.pdata = *pdata; |
314 | rmi_smb->xport.pdata.irq = client->irq; |
315 | rmi_smb->xport.proto_name = "smb" ; |
316 | rmi_smb->xport.ops = &rmi_smb_ops; |
317 | |
318 | smbus_version = rmi_smb_get_version(rmi_smb); |
319 | if (smbus_version < 0) |
320 | return smbus_version; |
321 | |
322 | rmi_dbg(RMI_DEBUG_XPORT, &client->dev, "Smbus version is %d" , |
323 | smbus_version); |
324 | |
325 | if (smbus_version != 2 && smbus_version != 3) { |
326 | dev_err(&client->dev, "Unrecognized SMB version %d\n" , |
327 | smbus_version); |
328 | return -ENODEV; |
329 | } |
330 | |
331 | i2c_set_clientdata(client, rmi_smb); |
332 | |
333 | dev_info(&client->dev, "registering SMbus-connected sensor\n" ); |
334 | |
335 | error = rmi_register_transport_device(&rmi_smb->xport); |
336 | if (error) { |
337 | dev_err(&client->dev, "failed to register sensor: %d\n" , error); |
338 | return error; |
339 | } |
340 | |
341 | return 0; |
342 | } |
343 | |
344 | static int rmi_smb_remove(struct i2c_client *client) |
345 | { |
346 | struct rmi_smb_xport *rmi_smb = i2c_get_clientdata(client); |
347 | |
348 | rmi_unregister_transport_device(&rmi_smb->xport); |
349 | |
350 | return 0; |
351 | } |
352 | |
353 | static int __maybe_unused rmi_smb_suspend(struct device *dev) |
354 | { |
355 | struct i2c_client *client = to_i2c_client(dev); |
356 | struct rmi_smb_xport *rmi_smb = i2c_get_clientdata(client); |
357 | int ret; |
358 | |
359 | ret = rmi_driver_suspend(rmi_smb->xport.rmi_dev, true); |
360 | if (ret) |
361 | dev_warn(dev, "Failed to suspend device: %d\n" , ret); |
362 | |
363 | return ret; |
364 | } |
365 | |
366 | static int __maybe_unused rmi_smb_runtime_suspend(struct device *dev) |
367 | { |
368 | struct i2c_client *client = to_i2c_client(dev); |
369 | struct rmi_smb_xport *rmi_smb = i2c_get_clientdata(client); |
370 | int ret; |
371 | |
372 | ret = rmi_driver_suspend(rmi_smb->xport.rmi_dev, false); |
373 | if (ret) |
374 | dev_warn(dev, "Failed to suspend device: %d\n" , ret); |
375 | |
376 | return ret; |
377 | } |
378 | |
379 | static int __maybe_unused rmi_smb_resume(struct device *dev) |
380 | { |
381 | struct i2c_client *client = container_of(dev, struct i2c_client, dev); |
382 | struct rmi_smb_xport *rmi_smb = i2c_get_clientdata(client); |
383 | struct rmi_device *rmi_dev = rmi_smb->xport.rmi_dev; |
384 | int ret; |
385 | |
386 | rmi_smb_reset(&rmi_smb->xport, 0); |
387 | |
388 | rmi_reset(rmi_dev); |
389 | |
390 | ret = rmi_driver_resume(rmi_smb->xport.rmi_dev, true); |
391 | if (ret) |
392 | dev_warn(dev, "Failed to resume device: %d\n" , ret); |
393 | |
394 | return 0; |
395 | } |
396 | |
397 | static int __maybe_unused rmi_smb_runtime_resume(struct device *dev) |
398 | { |
399 | struct i2c_client *client = to_i2c_client(dev); |
400 | struct rmi_smb_xport *rmi_smb = i2c_get_clientdata(client); |
401 | int ret; |
402 | |
403 | ret = rmi_driver_resume(rmi_smb->xport.rmi_dev, false); |
404 | if (ret) |
405 | dev_warn(dev, "Failed to resume device: %d\n" , ret); |
406 | |
407 | return 0; |
408 | } |
409 | |
410 | static const struct dev_pm_ops rmi_smb_pm = { |
411 | SET_SYSTEM_SLEEP_PM_OPS(rmi_smb_suspend, rmi_smb_resume) |
412 | SET_RUNTIME_PM_OPS(rmi_smb_runtime_suspend, rmi_smb_runtime_resume, |
413 | NULL) |
414 | }; |
415 | |
416 | static const struct i2c_device_id rmi_id[] = { |
417 | { "rmi4_smbus" , 0 }, |
418 | { } |
419 | }; |
420 | MODULE_DEVICE_TABLE(i2c, rmi_id); |
421 | |
422 | static struct i2c_driver rmi_smb_driver = { |
423 | .driver = { |
424 | .name = "rmi4_smbus" , |
425 | .pm = &rmi_smb_pm, |
426 | }, |
427 | .id_table = rmi_id, |
428 | .probe = rmi_smb_probe, |
429 | .remove = rmi_smb_remove, |
430 | }; |
431 | |
432 | module_i2c_driver(rmi_smb_driver); |
433 | |
434 | MODULE_AUTHOR("Andrew Duggan <aduggan@synaptics.com>" ); |
435 | MODULE_AUTHOR("Benjamin Tissoires <benjamin.tissoires@redhat.com>" ); |
436 | MODULE_DESCRIPTION("RMI4 SMBus driver" ); |
437 | MODULE_LICENSE("GPL" ); |
438 | |