diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/input/mouse/cyapa.c | 179 |
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 | |||
232 | static const struct cyapa_cmd_len cyapa_i2c_cmds[] = { | 287 | static 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 | ||
303 | static 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 | |||
248 | static ssize_t cyapa_i2c_reg_read_block(struct cyapa *cyapa, u8 reg, size_t len, | 319 | static 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 | */ | ||
344 | static 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 | |||
373 | out: | ||
374 | return ret > 0 ? len : ret; | ||
375 | } | ||
376 | |||
260 | static s32 cyapa_read_byte(struct cyapa *cyapa, u8 cmd_idx) | 377 | static 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 | ||
267 | static s32 cyapa_write_byte(struct cyapa *cyapa, u8 cmd_idx, u8 value) | 390 | static 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 | ||
274 | static ssize_t cyapa_read_block(struct cyapa *cyapa, u8 cmd_idx, u8 *values) | 403 | static 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 | ||
743 | static 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 | |||
597 | static int cyapa_create_input_dev(struct cyapa *cyapa) | 756 | static 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) { |