aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/input/mouse
diff options
context:
space:
mode:
authorBenson Leung <bleung@chromium.org>2013-02-13 16:56:03 -0500
committerDmitry Torokhov <dmitry.torokhov@gmail.com>2013-02-13 23:21:17 -0500
commit6ddaf744c9f6dd08aaec05bc9536173317b913a3 (patch)
tree8c9c25b65c0c9343188eda94bfeca0768765b9ac /drivers/input/mouse
parent48064bdcd6d1c27ad0a35103eb8cee2d087940d9 (diff)
Input: cyapa - add support for smbus protocol
This patch adds support for the Cypress APA Smbus Trackpad type, which uses a modified register map that fits within the limitations of the smbus protocol. Devices that use this protocol include: CYTRA-116001-00 - Samsung Series 5 550 Chromebook trackpad CYTRA-103002-00 - Acer C7 Chromebook trackpad CYTRA-101003-00 - HP Pavilion 14 Chromebook trackpad Signed-off-by: Dudley Du <dudl@cypress.com> Signed-off-by: Benson Leung <bleung@chromium.org> Reviewed-by: Daniel Kurtz <djkurtz@chromium.org> Reviewed-by: Henrik Rydberg <rydberg@euromail.se> Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Diffstat (limited to 'drivers/input/mouse')
-rw-r--r--drivers/input/mouse/cyapa.c179
1 files changed, 174 insertions, 5 deletions
diff --git a/drivers/input/mouse/cyapa.c b/drivers/input/mouse/cyapa.c
index 1a14688329be..b409c3d7d4fb 100644
--- a/drivers/input/mouse/cyapa.c
+++ b/drivers/input/mouse/cyapa.c
@@ -208,6 +208,7 @@ struct cyapa {
208 char phys[32]; /* device physical location */ 208 char phys[32]; /* device physical location */
209 int irq; 209 int irq;
210 bool irq_wake; /* irq wake is enabled */ 210 bool irq_wake; /* irq wake is enabled */
211 bool smbus;
211 212
212 /* read from query data region. */ 213 /* read from query data region. */
213 char product_id[16]; 214 char product_id[16];
@@ -229,6 +230,60 @@ struct cyapa_cmd_len {
229 u8 len; 230 u8 len;
230}; 231};
231 232
233#define CYAPA_ADAPTER_FUNC_NONE 0
234#define CYAPA_ADAPTER_FUNC_I2C 1
235#define CYAPA_ADAPTER_FUNC_SMBUS 2
236#define CYAPA_ADAPTER_FUNC_BOTH 3
237
238/*
239 * macros for SMBus communication
240 */
241#define SMBUS_READ 0x01
242#define SMBUS_WRITE 0x00
243#define SMBUS_ENCODE_IDX(cmd, idx) ((cmd) | (((idx) & 0x03) << 1))
244#define SMBUS_ENCODE_RW(cmd, rw) ((cmd) | ((rw) & 0x01))
245#define SMBUS_BYTE_BLOCK_CMD_MASK 0x80
246#define SMBUS_GROUP_BLOCK_CMD_MASK 0x40
247
248 /* for byte read/write command */
249#define CMD_RESET 0
250#define CMD_POWER_MODE 1
251#define CMD_DEV_STATUS 2
252#define SMBUS_BYTE_CMD(cmd) (((cmd) & 0x3f) << 1)
253#define CYAPA_SMBUS_RESET SMBUS_BYTE_CMD(CMD_RESET)
254#define CYAPA_SMBUS_POWER_MODE SMBUS_BYTE_CMD(CMD_POWER_MODE)
255#define CYAPA_SMBUS_DEV_STATUS SMBUS_BYTE_CMD(CMD_DEV_STATUS)
256
257 /* for group registers read/write command */
258#define REG_GROUP_DATA 0
259#define REG_GROUP_CMD 2
260#define REG_GROUP_QUERY 3
261#define SMBUS_GROUP_CMD(grp) (0x80 | (((grp) & 0x07) << 3))
262#define CYAPA_SMBUS_GROUP_DATA SMBUS_GROUP_CMD(REG_GROUP_DATA)
263#define CYAPA_SMBUS_GROUP_CMD SMBUS_GROUP_CMD(REG_GROUP_CMD)
264#define CYAPA_SMBUS_GROUP_QUERY SMBUS_GROUP_CMD(REG_GROUP_QUERY)
265
266 /* for register block read/write command */
267#define CMD_BL_STATUS 0
268#define CMD_BL_HEAD 1
269#define CMD_BL_CMD 2
270#define CMD_BL_DATA 3
271#define CMD_BL_ALL 4
272#define CMD_BLK_PRODUCT_ID 5
273#define CMD_BLK_HEAD 6
274#define SMBUS_BLOCK_CMD(cmd) (0xc0 | (((cmd) & 0x1f) << 1))
275
276/* register block read/write command in bootloader mode */
277#define CYAPA_SMBUS_BL_STATUS SMBUS_BLOCK_CMD(CMD_BL_STATUS)
278#define CYAPA_SMBUS_BL_HEAD SMBUS_BLOCK_CMD(CMD_BL_HEAD)
279#define CYAPA_SMBUS_BL_CMD SMBUS_BLOCK_CMD(CMD_BL_CMD)
280#define CYAPA_SMBUS_BL_DATA SMBUS_BLOCK_CMD(CMD_BL_DATA)
281#define CYAPA_SMBUS_BL_ALL SMBUS_BLOCK_CMD(CMD_BL_ALL)
282
283/* register block read/write command in operational mode */
284#define CYAPA_SMBUS_BLK_PRODUCT_ID SMBUS_BLOCK_CMD(CMD_BLK_PRODUCT_ID)
285#define CYAPA_SMBUS_BLK_HEAD SMBUS_BLOCK_CMD(CMD_BLK_HEAD)
286
232static const struct cyapa_cmd_len cyapa_i2c_cmds[] = { 287static const struct cyapa_cmd_len cyapa_i2c_cmds[] = {
233 { CYAPA_OFFSET_SOFT_RESET, 1 }, 288 { CYAPA_OFFSET_SOFT_RESET, 1 },
234 { REG_OFFSET_COMMAND_BASE + 1, 1 }, 289 { REG_OFFSET_COMMAND_BASE + 1, 1 },
@@ -245,6 +300,22 @@ static const struct cyapa_cmd_len cyapa_i2c_cmds[] = {
245 { REG_OFFSET_DATA_BASE, 32 } 300 { REG_OFFSET_DATA_BASE, 32 }
246}; 301};
247 302
303static const struct cyapa_cmd_len cyapa_smbus_cmds[] = {
304 { CYAPA_SMBUS_RESET, 1 },
305 { CYAPA_SMBUS_POWER_MODE, 1 },
306 { CYAPA_SMBUS_DEV_STATUS, 1 },
307 { CYAPA_SMBUS_GROUP_DATA, sizeof(struct cyapa_reg_data) },
308 { CYAPA_SMBUS_GROUP_CMD, 2 },
309 { CYAPA_SMBUS_GROUP_QUERY, QUERY_DATA_SIZE },
310 { CYAPA_SMBUS_BL_STATUS, 3 },
311 { CYAPA_SMBUS_BL_HEAD, 16 },
312 { CYAPA_SMBUS_BL_CMD, 16 },
313 { CYAPA_SMBUS_BL_DATA, 16 },
314 { CYAPA_SMBUS_BL_ALL, 32 },
315 { CYAPA_SMBUS_BLK_PRODUCT_ID, PRODUCT_ID_SIZE },
316 { CYAPA_SMBUS_BLK_HEAD, 16 },
317};
318
248static ssize_t cyapa_i2c_reg_read_block(struct cyapa *cyapa, u8 reg, size_t len, 319static ssize_t cyapa_i2c_reg_read_block(struct cyapa *cyapa, u8 reg, size_t len,
249 u8 *values) 320 u8 *values)
250{ 321{
@@ -257,26 +328,92 @@ static ssize_t cyapa_i2c_reg_write_block(struct cyapa *cyapa, u8 reg,
257 return i2c_smbus_write_i2c_block_data(cyapa->client, reg, len, values); 328 return i2c_smbus_write_i2c_block_data(cyapa->client, reg, len, values);
258} 329}
259 330
331/*
332 * cyapa_smbus_read_block - perform smbus block read command
333 * @cyapa - private data structure of the driver
334 * @cmd - the properly encoded smbus command
335 * @len - expected length of smbus command result
336 * @values - buffer to store smbus command result
337 *
338 * Returns negative errno, else the number of bytes written.
339 *
340 * Note:
341 * In trackpad device, the memory block allocated for I2C register map
342 * is 256 bytes, so the max read block for I2C bus is 256 bytes.
343 */
344static ssize_t cyapa_smbus_read_block(struct cyapa *cyapa, u8 cmd, size_t len,
345 u8 *values)
346{
347 ssize_t ret;
348 u8 index;
349 u8 smbus_cmd;
350 u8 *buf;
351 struct i2c_client *client = cyapa->client;
352
353 if (!(SMBUS_BYTE_BLOCK_CMD_MASK & cmd))
354 return -EINVAL;
355
356 if (SMBUS_GROUP_BLOCK_CMD_MASK & cmd) {
357 /* read specific block registers command. */
358 smbus_cmd = SMBUS_ENCODE_RW(cmd, SMBUS_READ);
359 ret = i2c_smbus_read_block_data(client, smbus_cmd, values);
360 goto out;
361 }
362
363 ret = 0;
364 for (index = 0; index * I2C_SMBUS_BLOCK_MAX < len; index++) {
365 smbus_cmd = SMBUS_ENCODE_IDX(cmd, index);
366 smbus_cmd = SMBUS_ENCODE_RW(smbus_cmd, SMBUS_READ);
367 buf = values + I2C_SMBUS_BLOCK_MAX * index;
368 ret = i2c_smbus_read_block_data(client, smbus_cmd, buf);
369 if (ret < 0)
370 goto out;
371 }
372
373out:
374 return ret > 0 ? len : ret;
375}
376
260static s32 cyapa_read_byte(struct cyapa *cyapa, u8 cmd_idx) 377static s32 cyapa_read_byte(struct cyapa *cyapa, u8 cmd_idx)
261{ 378{
262 u8 cmd = cyapa_i2c_cmds[cmd_idx].cmd; 379 u8 cmd;
263 380
381 if (cyapa->smbus) {
382 cmd = cyapa_smbus_cmds[cmd_idx].cmd;
383 cmd = SMBUS_ENCODE_RW(cmd, SMBUS_READ);
384 } else {
385 cmd = cyapa_i2c_cmds[cmd_idx].cmd;
386 }
264 return i2c_smbus_read_byte_data(cyapa->client, cmd); 387 return i2c_smbus_read_byte_data(cyapa->client, cmd);
265} 388}
266 389
267static s32 cyapa_write_byte(struct cyapa *cyapa, u8 cmd_idx, u8 value) 390static s32 cyapa_write_byte(struct cyapa *cyapa, u8 cmd_idx, u8 value)
268{ 391{
269 u8 cmd = cyapa_i2c_cmds[cmd_idx].cmd; 392 u8 cmd;
270 393
394 if (cyapa->smbus) {
395 cmd = cyapa_smbus_cmds[cmd_idx].cmd;
396 cmd = SMBUS_ENCODE_RW(cmd, SMBUS_WRITE);
397 } else {
398 cmd = cyapa_i2c_cmds[cmd_idx].cmd;
399 }
271 return i2c_smbus_write_byte_data(cyapa->client, cmd, value); 400 return i2c_smbus_write_byte_data(cyapa->client, cmd, value);
272} 401}
273 402
274static ssize_t cyapa_read_block(struct cyapa *cyapa, u8 cmd_idx, u8 *values) 403static ssize_t cyapa_read_block(struct cyapa *cyapa, u8 cmd_idx, u8 *values)
275{ 404{
276 u8 cmd = cyapa_i2c_cmds[cmd_idx].cmd; 405 u8 cmd;
277 size_t len = cyapa_i2c_cmds[cmd_idx].len; 406 size_t len;
278 407
279 return cyapa_i2c_reg_read_block(cyapa, cmd, len, values); 408 if (cyapa->smbus) {
409 cmd = cyapa_smbus_cmds[cmd_idx].cmd;
410 len = cyapa_smbus_cmds[cmd_idx].len;
411 return cyapa_smbus_read_block(cyapa, cmd, len, values);
412 } else {
413 cmd = cyapa_i2c_cmds[cmd_idx].cmd;
414 len = cyapa_i2c_cmds[cmd_idx].len;
415 return cyapa_i2c_reg_read_block(cyapa, cmd, len, values);
416 }
280} 417}
281 418
282/* 419/*
@@ -298,6 +435,15 @@ static int cyapa_get_state(struct cyapa *cyapa)
298 */ 435 */
299 ret = cyapa_i2c_reg_read_block(cyapa, BL_HEAD_OFFSET, BL_STATUS_SIZE, 436 ret = cyapa_i2c_reg_read_block(cyapa, BL_HEAD_OFFSET, BL_STATUS_SIZE,
300 status); 437 status);
438
439 /*
440 * On smbus systems in OP mode, the i2c_reg_read will fail with
441 * -ETIMEDOUT. In this case, try again using the smbus equivalent
442 * command. This should return a BL_HEAD indicating CYAPA_STATE_OP.
443 */
444 if (cyapa->smbus && (ret == -ETIMEDOUT || ret == -ENXIO))
445 ret = cyapa_read_block(cyapa, CYAPA_CMD_BL_STATUS, status);
446
301 if (ret != BL_STATUS_SIZE) 447 if (ret != BL_STATUS_SIZE)
302 goto error; 448 goto error;
303 449
@@ -594,6 +740,19 @@ out:
594 return IRQ_HANDLED; 740 return IRQ_HANDLED;
595} 741}
596 742
743static u8 cyapa_check_adapter_functionality(struct i2c_client *client)
744{
745 u8 ret = CYAPA_ADAPTER_FUNC_NONE;
746
747 if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
748 ret |= CYAPA_ADAPTER_FUNC_I2C;
749 if (i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA |
750 I2C_FUNC_SMBUS_BLOCK_DATA |
751 I2C_FUNC_SMBUS_I2C_BLOCK))
752 ret |= CYAPA_ADAPTER_FUNC_SMBUS;
753 return ret;
754}
755
597static int cyapa_create_input_dev(struct cyapa *cyapa) 756static int cyapa_create_input_dev(struct cyapa *cyapa)
598{ 757{
599 struct device *dev = &cyapa->client->dev; 758 struct device *dev = &cyapa->client->dev;
@@ -668,9 +827,16 @@ static int cyapa_probe(struct i2c_client *client,
668 const struct i2c_device_id *dev_id) 827 const struct i2c_device_id *dev_id)
669{ 828{
670 int ret; 829 int ret;
830 u8 adapter_func;
671 struct cyapa *cyapa; 831 struct cyapa *cyapa;
672 struct device *dev = &client->dev; 832 struct device *dev = &client->dev;
673 833
834 adapter_func = cyapa_check_adapter_functionality(client);
835 if (adapter_func == CYAPA_ADAPTER_FUNC_NONE) {
836 dev_err(dev, "not a supported I2C/SMBus adapter\n");
837 return -EIO;
838 }
839
674 cyapa = kzalloc(sizeof(struct cyapa), GFP_KERNEL); 840 cyapa = kzalloc(sizeof(struct cyapa), GFP_KERNEL);
675 if (!cyapa) { 841 if (!cyapa) {
676 dev_err(dev, "allocate memory for cyapa failed\n"); 842 dev_err(dev, "allocate memory for cyapa failed\n");
@@ -683,6 +849,9 @@ static int cyapa_probe(struct i2c_client *client,
683 sprintf(cyapa->phys, "i2c-%d-%04x/input0", client->adapter->nr, 849 sprintf(cyapa->phys, "i2c-%d-%04x/input0", client->adapter->nr,
684 client->addr); 850 client->addr);
685 851
852 /* i2c isn't supported, use smbus */
853 if (adapter_func == CYAPA_ADAPTER_FUNC_SMBUS)
854 cyapa->smbus = true;
686 cyapa->state = CYAPA_STATE_NO_DEVICE; 855 cyapa->state = CYAPA_STATE_NO_DEVICE;
687 ret = cyapa_check_is_operational(cyapa); 856 ret = cyapa_check_is_operational(cyapa);
688 if (ret) { 857 if (ret) {