Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Input: synaptics-rmi4 - add SMBus support

Code obtained from https://raw.githubusercontent.com/mightybigcar/synaptics-rmi4/jf/drivers/input/rmi4/rmi_smbus.c
and updated to match upstream. And fixed to make it work.

Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
Signed-off-by: Andrew Duggan <aduggan@synaptics.com>
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>

authored by

Benjamin Tissoires and committed by
Dmitry Torokhov
82264d0c 332c3988

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