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

Input: synaptics-rmi4 - add I2C transport driver

Add the transport driver for devices using RMI4 over I2C.

Signed-off-by: Andrew Duggan <aduggan@synaptics.com>
Signed-off-by: Christopher Heiny <cheiny@synaptics.com>
Tested-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
Tested-by: Linus Walleij <linus.walleij@linaro.org>
Tested-by: Bjorn Andersson <bjorn.andersson@linaro.org>
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>

authored by

Andrew Duggan and committed by
Dmitry Torokhov
fdf51604 2b6a321d

+399
+9
drivers/input/rmi4/Kconfig
··· 8 8 required for all RMI4 device support. 9 9 10 10 If unsure, say Y. 11 + 12 + config RMI4_I2C 13 + tristate "RMI4 I2C Support" 14 + depends on RMI4_CORE && I2C 15 + help 16 + Say Y here if you want to support RMI4 devices connected to an I2C 17 + bus. 18 + 19 + If unsure, say Y.
+3
drivers/input/rmi4/Makefile
··· 1 1 obj-$(CONFIG_RMI4_CORE) += rmi_core.o 2 2 rmi_core-y := rmi_bus.o rmi_driver.o rmi_f01.o 3 + 4 + # Transports 5 + obj-$(CONFIG_RMI4_I2C) += rmi_i2c.o
+387
drivers/input/rmi4/rmi_i2c.c
··· 1 + /* 2 + * Copyright (c) 2011-2016 Synaptics Incorporated 3 + * Copyright (c) 2011 Unixphere 4 + * 5 + * This program is free software; you can redistribute it and/or modify it 6 + * under the terms of the GNU General Public License version 2 as published by 7 + * the Free Software Foundation. 8 + */ 9 + 10 + #include <linux/i2c.h> 11 + #include <linux/rmi.h> 12 + #include <linux/irq.h> 13 + #include "rmi_driver.h" 14 + 15 + #define BUFFER_SIZE_INCREMENT 32 16 + 17 + /** 18 + * struct rmi_i2c_xport - stores information for i2c communication 19 + * 20 + * @xport: The transport interface structure 21 + * 22 + * @page_mutex: Locks current page to avoid changing pages in unexpected ways. 23 + * @page: Keeps track of the current virtual page 24 + * 25 + * @tx_buf: Buffer used for transmitting data to the sensor over i2c. 26 + * @tx_buf_size: Size of the buffer 27 + */ 28 + struct rmi_i2c_xport { 29 + struct rmi_transport_dev xport; 30 + struct i2c_client *client; 31 + 32 + struct mutex page_mutex; 33 + int page; 34 + 35 + int irq; 36 + 37 + u8 *tx_buf; 38 + size_t tx_buf_size; 39 + }; 40 + 41 + #define RMI_PAGE_SELECT_REGISTER 0xff 42 + #define RMI_I2C_PAGE(addr) (((addr) >> 8) & 0xff) 43 + 44 + /* 45 + * rmi_set_page - Set RMI page 46 + * @xport: The pointer to the rmi_transport_dev struct 47 + * @page: The new page address. 48 + * 49 + * RMI devices have 16-bit addressing, but some of the transport 50 + * implementations (like SMBus) only have 8-bit addressing. So RMI implements 51 + * a page address at 0xff of every page so we can reliable page addresses 52 + * every 256 registers. 53 + * 54 + * The page_mutex lock must be held when this function is entered. 55 + * 56 + * Returns zero on success, non-zero on failure. 57 + */ 58 + static int rmi_set_page(struct rmi_i2c_xport *rmi_i2c, u8 page) 59 + { 60 + struct i2c_client *client = rmi_i2c->client; 61 + u8 txbuf[2] = {RMI_PAGE_SELECT_REGISTER, page}; 62 + int retval; 63 + 64 + retval = i2c_master_send(client, txbuf, sizeof(txbuf)); 65 + if (retval != sizeof(txbuf)) { 66 + dev_err(&client->dev, 67 + "%s: set page failed: %d.", __func__, retval); 68 + return (retval < 0) ? retval : -EIO; 69 + } 70 + 71 + rmi_i2c->page = page; 72 + return 0; 73 + } 74 + 75 + static int rmi_i2c_write_block(struct rmi_transport_dev *xport, u16 addr, 76 + const void *buf, size_t len) 77 + { 78 + struct rmi_i2c_xport *rmi_i2c = 79 + container_of(xport, struct rmi_i2c_xport, xport); 80 + struct i2c_client *client = rmi_i2c->client; 81 + size_t tx_size = len + 1; 82 + int retval; 83 + 84 + mutex_lock(&rmi_i2c->page_mutex); 85 + 86 + if (!rmi_i2c->tx_buf || rmi_i2c->tx_buf_size < tx_size) { 87 + if (rmi_i2c->tx_buf) 88 + devm_kfree(&client->dev, rmi_i2c->tx_buf); 89 + rmi_i2c->tx_buf_size = tx_size + BUFFER_SIZE_INCREMENT; 90 + rmi_i2c->tx_buf = devm_kzalloc(&client->dev, 91 + rmi_i2c->tx_buf_size, 92 + GFP_KERNEL); 93 + if (!rmi_i2c->tx_buf) { 94 + rmi_i2c->tx_buf_size = 0; 95 + retval = -ENOMEM; 96 + goto exit; 97 + } 98 + } 99 + 100 + rmi_i2c->tx_buf[0] = addr & 0xff; 101 + memcpy(rmi_i2c->tx_buf + 1, buf, len); 102 + 103 + if (RMI_I2C_PAGE(addr) != rmi_i2c->page) { 104 + retval = rmi_set_page(rmi_i2c, RMI_I2C_PAGE(addr)); 105 + if (retval) 106 + goto exit; 107 + } 108 + 109 + retval = i2c_master_send(client, rmi_i2c->tx_buf, tx_size); 110 + if (retval == tx_size) 111 + retval = 0; 112 + else if (retval >= 0) 113 + retval = -EIO; 114 + 115 + exit: 116 + rmi_dbg(RMI_DEBUG_XPORT, &client->dev, 117 + "write %zd bytes at %#06x: %d (%*ph)\n", 118 + len, addr, retval, (int)len, buf); 119 + 120 + mutex_unlock(&rmi_i2c->page_mutex); 121 + return retval; 122 + } 123 + 124 + static int rmi_i2c_read_block(struct rmi_transport_dev *xport, u16 addr, 125 + void *buf, size_t len) 126 + { 127 + struct rmi_i2c_xport *rmi_i2c = 128 + container_of(xport, struct rmi_i2c_xport, xport); 129 + struct i2c_client *client = rmi_i2c->client; 130 + u8 addr_offset = addr & 0xff; 131 + int retval; 132 + struct i2c_msg msgs[] = { 133 + { 134 + .addr = client->addr, 135 + .len = sizeof(addr_offset), 136 + .buf = &addr_offset, 137 + }, 138 + { 139 + .addr = client->addr, 140 + .flags = I2C_M_RD, 141 + .len = len, 142 + .buf = buf, 143 + }, 144 + }; 145 + 146 + mutex_lock(&rmi_i2c->page_mutex); 147 + 148 + if (RMI_I2C_PAGE(addr) != rmi_i2c->page) { 149 + retval = rmi_set_page(rmi_i2c, RMI_I2C_PAGE(addr)); 150 + if (retval) 151 + goto exit; 152 + } 153 + 154 + retval = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); 155 + if (retval == ARRAY_SIZE(msgs)) 156 + retval = 0; /* success */ 157 + else if (retval >= 0) 158 + retval = -EIO; 159 + 160 + exit: 161 + rmi_dbg(RMI_DEBUG_XPORT, &client->dev, 162 + "read %zd bytes at %#06x: %d (%*ph)\n", 163 + len, addr, retval, (int)len, buf); 164 + 165 + mutex_unlock(&rmi_i2c->page_mutex); 166 + return retval; 167 + } 168 + 169 + static const struct rmi_transport_ops rmi_i2c_ops = { 170 + .write_block = rmi_i2c_write_block, 171 + .read_block = rmi_i2c_read_block, 172 + }; 173 + 174 + static irqreturn_t rmi_i2c_irq(int irq, void *dev_id) 175 + { 176 + struct rmi_i2c_xport *rmi_i2c = dev_id; 177 + struct rmi_device *rmi_dev = rmi_i2c->xport.rmi_dev; 178 + int ret; 179 + 180 + ret = rmi_process_interrupt_requests(rmi_dev); 181 + if (ret) 182 + rmi_dbg(RMI_DEBUG_XPORT, &rmi_dev->dev, 183 + "Failed to process interrupt request: %d\n", ret); 184 + 185 + return IRQ_HANDLED; 186 + } 187 + 188 + static int rmi_i2c_init_irq(struct i2c_client *client) 189 + { 190 + struct rmi_i2c_xport *rmi_i2c = i2c_get_clientdata(client); 191 + int irq_flags = irqd_get_trigger_type(irq_get_irq_data(rmi_i2c->irq)); 192 + int ret; 193 + 194 + if (!irq_flags) 195 + irq_flags = IRQF_TRIGGER_LOW; 196 + 197 + ret = devm_request_threaded_irq(&client->dev, rmi_i2c->irq, NULL, 198 + rmi_i2c_irq, irq_flags | IRQF_ONESHOT, client->name, 199 + rmi_i2c); 200 + if (ret < 0) { 201 + dev_warn(&client->dev, "Failed to register interrupt %d\n", 202 + rmi_i2c->irq); 203 + 204 + return ret; 205 + } 206 + 207 + return 0; 208 + } 209 + 210 + static int rmi_i2c_probe(struct i2c_client *client, 211 + const struct i2c_device_id *id) 212 + { 213 + struct rmi_device_platform_data *pdata; 214 + struct rmi_device_platform_data *client_pdata = 215 + dev_get_platdata(&client->dev); 216 + struct rmi_i2c_xport *rmi_i2c; 217 + int retval; 218 + 219 + rmi_i2c = devm_kzalloc(&client->dev, sizeof(struct rmi_i2c_xport), 220 + GFP_KERNEL); 221 + if (!rmi_i2c) 222 + return -ENOMEM; 223 + 224 + pdata = &rmi_i2c->xport.pdata; 225 + 226 + if (client_pdata) 227 + *pdata = *client_pdata; 228 + 229 + if (client->irq > 0) 230 + rmi_i2c->irq = client->irq; 231 + 232 + rmi_dbg(RMI_DEBUG_XPORT, &client->dev, "Probing %s.\n", 233 + dev_name(&client->dev)); 234 + if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { 235 + dev_err(&client->dev, 236 + "adapter does not support required functionality.\n"); 237 + return -ENODEV; 238 + } 239 + 240 + rmi_i2c->client = client; 241 + mutex_init(&rmi_i2c->page_mutex); 242 + 243 + rmi_i2c->xport.dev = &client->dev; 244 + rmi_i2c->xport.proto_name = "i2c"; 245 + rmi_i2c->xport.ops = &rmi_i2c_ops; 246 + 247 + i2c_set_clientdata(client, rmi_i2c); 248 + 249 + /* 250 + * Setting the page to zero will (a) make sure the PSR is in a 251 + * known state, and (b) make sure we can talk to the device. 252 + */ 253 + retval = rmi_set_page(rmi_i2c, 0); 254 + if (retval) { 255 + dev_err(&client->dev, "Failed to set page select to 0.\n"); 256 + return retval; 257 + } 258 + 259 + retval = rmi_register_transport_device(&rmi_i2c->xport); 260 + if (retval) { 261 + dev_err(&client->dev, "Failed to register transport driver at 0x%.2X.\n", 262 + client->addr); 263 + return retval; 264 + } 265 + 266 + retval = rmi_i2c_init_irq(client); 267 + if (retval < 0) 268 + return retval; 269 + 270 + dev_info(&client->dev, "registered rmi i2c driver at %#04x.\n", 271 + client->addr); 272 + return 0; 273 + } 274 + 275 + static int rmi_i2c_remove(struct i2c_client *client) 276 + { 277 + struct rmi_i2c_xport *rmi_i2c = i2c_get_clientdata(client); 278 + 279 + rmi_unregister_transport_device(&rmi_i2c->xport); 280 + 281 + return 0; 282 + } 283 + 284 + #ifdef CONFIG_PM_SLEEP 285 + static int rmi_i2c_suspend(struct device *dev) 286 + { 287 + struct i2c_client *client = to_i2c_client(dev); 288 + struct rmi_i2c_xport *rmi_i2c = i2c_get_clientdata(client); 289 + int ret; 290 + 291 + ret = rmi_driver_suspend(rmi_i2c->xport.rmi_dev); 292 + if (ret) 293 + dev_warn(dev, "Failed to resume device: %d\n", ret); 294 + 295 + disable_irq(rmi_i2c->irq); 296 + if (device_may_wakeup(&client->dev)) { 297 + ret = enable_irq_wake(rmi_i2c->irq); 298 + if (!ret) 299 + dev_warn(dev, "Failed to enable irq for wake: %d\n", 300 + ret); 301 + } 302 + return ret; 303 + } 304 + 305 + static int rmi_i2c_resume(struct device *dev) 306 + { 307 + struct i2c_client *client = to_i2c_client(dev); 308 + struct rmi_i2c_xport *rmi_i2c = i2c_get_clientdata(client); 309 + int ret; 310 + 311 + enable_irq(rmi_i2c->irq); 312 + if (device_may_wakeup(&client->dev)) { 313 + ret = disable_irq_wake(rmi_i2c->irq); 314 + if (!ret) 315 + dev_warn(dev, "Failed to disable irq for wake: %d\n", 316 + ret); 317 + } 318 + 319 + ret = rmi_driver_resume(rmi_i2c->xport.rmi_dev); 320 + if (ret) 321 + dev_warn(dev, "Failed to resume device: %d\n", ret); 322 + 323 + return ret; 324 + } 325 + #endif 326 + 327 + #ifdef CONFIG_PM 328 + static int rmi_i2c_runtime_suspend(struct device *dev) 329 + { 330 + struct i2c_client *client = to_i2c_client(dev); 331 + struct rmi_i2c_xport *rmi_i2c = i2c_get_clientdata(client); 332 + int ret; 333 + 334 + ret = rmi_driver_suspend(rmi_i2c->xport.rmi_dev); 335 + if (ret) 336 + dev_warn(dev, "Failed to resume device: %d\n", ret); 337 + 338 + disable_irq(rmi_i2c->irq); 339 + 340 + return 0; 341 + } 342 + 343 + static int rmi_i2c_runtime_resume(struct device *dev) 344 + { 345 + struct i2c_client *client = to_i2c_client(dev); 346 + struct rmi_i2c_xport *rmi_i2c = i2c_get_clientdata(client); 347 + int ret; 348 + 349 + enable_irq(rmi_i2c->irq); 350 + 351 + ret = rmi_driver_resume(rmi_i2c->xport.rmi_dev); 352 + if (ret) 353 + dev_warn(dev, "Failed to resume device: %d\n", ret); 354 + 355 + return 0; 356 + } 357 + #endif 358 + 359 + static const struct dev_pm_ops rmi_i2c_pm = { 360 + SET_SYSTEM_SLEEP_PM_OPS(rmi_i2c_suspend, rmi_i2c_resume) 361 + SET_RUNTIME_PM_OPS(rmi_i2c_runtime_suspend, rmi_i2c_runtime_resume, 362 + NULL) 363 + }; 364 + 365 + static const struct i2c_device_id rmi_id[] = { 366 + { "rmi4_i2c", 0 }, 367 + { } 368 + }; 369 + MODULE_DEVICE_TABLE(i2c, rmi_id); 370 + 371 + static struct i2c_driver rmi_i2c_driver = { 372 + .driver = { 373 + .name = "rmi4_i2c", 374 + .pm = &rmi_i2c_pm, 375 + }, 376 + .id_table = rmi_id, 377 + .probe = rmi_i2c_probe, 378 + .remove = rmi_i2c_remove, 379 + }; 380 + 381 + module_i2c_driver(rmi_i2c_driver); 382 + 383 + MODULE_AUTHOR("Christopher Heiny <cheiny@synaptics.com>"); 384 + MODULE_AUTHOR("Andrew Duggan <aduggan@synaptics.com>"); 385 + MODULE_DESCRIPTION("RMI I2C driver"); 386 + MODULE_LICENSE("GPL"); 387 + MODULE_VERSION(RMI_DRIVER_VERSION);