| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * Elan I2C/SMBus Touchpad driver - I2C interface |
|---|
| 3 | 4 | * |
|---|
| .. | .. |
|---|
| 9 | 10 | * copyright (c) 2011-2012 Cypress Semiconductor, Inc. |
|---|
| 10 | 11 | * copyright (c) 2011-2012 Google, Inc. |
|---|
| 11 | 12 | * |
|---|
| 12 | | - * This program is free software; you can redistribute it and/or modify it |
|---|
| 13 | | - * under the terms of the GNU General Public License version 2 as published |
|---|
| 14 | | - * by the Free Software Foundation. |
|---|
| 15 | | - * |
|---|
| 16 | 13 | * Trademarks are the property of their respective owners. |
|---|
| 17 | 14 | */ |
|---|
| 18 | 15 | |
|---|
| .. | .. |
|---|
| 22 | 19 | #include <linux/interrupt.h> |
|---|
| 23 | 20 | #include <linux/jiffies.h> |
|---|
| 24 | 21 | #include <linux/kernel.h> |
|---|
| 22 | +#include <linux/slab.h> |
|---|
| 25 | 23 | #include <linux/sched.h> |
|---|
| 26 | 24 | #include <asm/unaligned.h> |
|---|
| 27 | 25 | |
|---|
| .. | .. |
|---|
| 46 | 44 | #define ETP_I2C_RESOLUTION_CMD 0x0108 |
|---|
| 47 | 45 | #define ETP_I2C_PRESSURE_CMD 0x010A |
|---|
| 48 | 46 | #define ETP_I2C_IAP_VERSION_CMD 0x0110 |
|---|
| 47 | +#define ETP_I2C_IC_TYPE_P0_CMD 0x0110 |
|---|
| 48 | +#define ETP_I2C_IAP_VERSION_P0_CMD 0x0111 |
|---|
| 49 | 49 | #define ETP_I2C_SET_CMD 0x0300 |
|---|
| 50 | 50 | #define ETP_I2C_POWER_CMD 0x0307 |
|---|
| 51 | 51 | #define ETP_I2C_FW_CHECKSUM_CMD 0x030F |
|---|
| .. | .. |
|---|
| 56 | 56 | #define ETP_I2C_CALIBRATE_CMD 0x0316 |
|---|
| 57 | 57 | #define ETP_I2C_MAX_BASELINE_CMD 0x0317 |
|---|
| 58 | 58 | #define ETP_I2C_MIN_BASELINE_CMD 0x0318 |
|---|
| 59 | +#define ETP_I2C_IAP_TYPE_REG 0x0040 |
|---|
| 60 | +#define ETP_I2C_IAP_TYPE_CMD 0x0304 |
|---|
| 59 | 61 | |
|---|
| 60 | 62 | #define ETP_I2C_REPORT_LEN 34 |
|---|
| 63 | +#define ETP_I2C_REPORT_LEN_ID2 39 |
|---|
| 64 | +#define ETP_I2C_REPORT_MAX_LEN 39 |
|---|
| 61 | 65 | #define ETP_I2C_DESC_LENGTH 30 |
|---|
| 62 | 66 | #define ETP_I2C_REPORT_DESC_LENGTH 158 |
|---|
| 63 | 67 | #define ETP_I2C_INF_LENGTH 2 |
|---|
| .. | .. |
|---|
| 252 | 256 | dev_err(&client->dev, "failed to get pattern: %d\n", error); |
|---|
| 253 | 257 | return error; |
|---|
| 254 | 258 | } |
|---|
| 255 | | - *pattern = val[1]; |
|---|
| 259 | + |
|---|
| 260 | + /* |
|---|
| 261 | + * Not all versions of firmware implement "get pattern" command. |
|---|
| 262 | + * When this command is not implemented the device will respond |
|---|
| 263 | + * with 0xFF 0xFF, which we will treat as "old" pattern 0. |
|---|
| 264 | + */ |
|---|
| 265 | + *pattern = val[0] == 0xFF && val[1] == 0xFF ? 0 : val[1]; |
|---|
| 256 | 266 | |
|---|
| 257 | 267 | return 0; |
|---|
| 258 | 268 | } |
|---|
| 259 | 269 | |
|---|
| 260 | 270 | static int elan_i2c_get_version(struct i2c_client *client, |
|---|
| 261 | | - bool iap, u8 *version) |
|---|
| 271 | + u8 pattern, bool iap, u8 *version) |
|---|
| 262 | 272 | { |
|---|
| 263 | 273 | int error; |
|---|
| 264 | | - u8 pattern_ver; |
|---|
| 274 | + u16 cmd; |
|---|
| 265 | 275 | u8 val[3]; |
|---|
| 266 | 276 | |
|---|
| 267 | | - error = elan_i2c_get_pattern(client, &pattern_ver); |
|---|
| 268 | | - if (error) { |
|---|
| 269 | | - dev_err(&client->dev, "failed to get pattern version\n"); |
|---|
| 270 | | - return error; |
|---|
| 271 | | - } |
|---|
| 277 | + if (!iap) |
|---|
| 278 | + cmd = ETP_I2C_FW_VERSION_CMD; |
|---|
| 279 | + else if (pattern == 0) |
|---|
| 280 | + cmd = ETP_I2C_IAP_VERSION_P0_CMD; |
|---|
| 281 | + else |
|---|
| 282 | + cmd = ETP_I2C_IAP_VERSION_CMD; |
|---|
| 272 | 283 | |
|---|
| 273 | | - error = elan_i2c_read_cmd(client, |
|---|
| 274 | | - iap ? ETP_I2C_IAP_VERSION_CMD : |
|---|
| 275 | | - ETP_I2C_FW_VERSION_CMD, |
|---|
| 276 | | - val); |
|---|
| 284 | + error = elan_i2c_read_cmd(client, cmd, val); |
|---|
| 277 | 285 | if (error) { |
|---|
| 278 | 286 | dev_err(&client->dev, "failed to get %s version: %d\n", |
|---|
| 279 | 287 | iap ? "IAP" : "FW", error); |
|---|
| 280 | 288 | return error; |
|---|
| 281 | 289 | } |
|---|
| 282 | 290 | |
|---|
| 283 | | - if (pattern_ver == 0x01) |
|---|
| 291 | + if (pattern >= 0x01) |
|---|
| 284 | 292 | *version = iap ? val[1] : val[0]; |
|---|
| 285 | 293 | else |
|---|
| 286 | 294 | *version = val[0]; |
|---|
| 287 | 295 | return 0; |
|---|
| 288 | 296 | } |
|---|
| 289 | 297 | |
|---|
| 290 | | -static int elan_i2c_get_sm_version(struct i2c_client *client, |
|---|
| 291 | | - u16 *ic_type, u8 *version, |
|---|
| 292 | | - u8 *clickpad) |
|---|
| 298 | +static int elan_i2c_get_sm_version(struct i2c_client *client, u8 pattern, |
|---|
| 299 | + u16 *ic_type, u8 *version, u8 *clickpad) |
|---|
| 293 | 300 | { |
|---|
| 294 | 301 | int error; |
|---|
| 295 | | - u8 pattern_ver; |
|---|
| 296 | 302 | u8 val[3]; |
|---|
| 297 | 303 | |
|---|
| 298 | | - error = elan_i2c_get_pattern(client, &pattern_ver); |
|---|
| 299 | | - if (error) { |
|---|
| 300 | | - dev_err(&client->dev, "failed to get pattern version\n"); |
|---|
| 301 | | - return error; |
|---|
| 302 | | - } |
|---|
| 303 | | - |
|---|
| 304 | | - if (pattern_ver == 0x01) { |
|---|
| 304 | + if (pattern >= 0x01) { |
|---|
| 305 | 305 | error = elan_i2c_read_cmd(client, ETP_I2C_IC_TYPE_CMD, val); |
|---|
| 306 | 306 | if (error) { |
|---|
| 307 | 307 | dev_err(&client->dev, "failed to get ic type: %d\n", |
|---|
| .. | .. |
|---|
| 327 | 327 | return error; |
|---|
| 328 | 328 | } |
|---|
| 329 | 329 | *version = val[0]; |
|---|
| 330 | | - *ic_type = val[1]; |
|---|
| 330 | + |
|---|
| 331 | + error = elan_i2c_read_cmd(client, ETP_I2C_IC_TYPE_P0_CMD, val); |
|---|
| 332 | + if (error) { |
|---|
| 333 | + dev_err(&client->dev, "failed to get ic type: %d\n", |
|---|
| 334 | + error); |
|---|
| 335 | + return error; |
|---|
| 336 | + } |
|---|
| 337 | + *ic_type = val[0]; |
|---|
| 331 | 338 | |
|---|
| 332 | 339 | error = elan_i2c_read_cmd(client, ETP_I2C_NSM_VERSION_CMD, |
|---|
| 333 | 340 | val); |
|---|
| .. | .. |
|---|
| 389 | 396 | return error; |
|---|
| 390 | 397 | } |
|---|
| 391 | 398 | |
|---|
| 392 | | - *max_x = le16_to_cpup((__le16 *)val) & 0x0fff; |
|---|
| 399 | + *max_x = le16_to_cpup((__le16 *)val); |
|---|
| 393 | 400 | |
|---|
| 394 | 401 | error = elan_i2c_read_cmd(client, ETP_I2C_MAX_Y_AXIS_CMD, val); |
|---|
| 395 | 402 | if (error) { |
|---|
| .. | .. |
|---|
| 397 | 404 | return error; |
|---|
| 398 | 405 | } |
|---|
| 399 | 406 | |
|---|
| 400 | | - *max_y = le16_to_cpup((__le16 *)val) & 0x0fff; |
|---|
| 407 | + *max_y = le16_to_cpup((__le16 *)val); |
|---|
| 401 | 408 | |
|---|
| 402 | 409 | return 0; |
|---|
| 403 | 410 | } |
|---|
| .. | .. |
|---|
| 510 | 517 | return 0; |
|---|
| 511 | 518 | } |
|---|
| 512 | 519 | |
|---|
| 513 | | -static int elan_i2c_prepare_fw_update(struct i2c_client *client) |
|---|
| 520 | +static int elan_read_write_iap_type(struct i2c_client *client, u16 fw_page_size) |
|---|
| 521 | +{ |
|---|
| 522 | + int error; |
|---|
| 523 | + u16 constant; |
|---|
| 524 | + u8 val[3]; |
|---|
| 525 | + int retry = 3; |
|---|
| 526 | + |
|---|
| 527 | + do { |
|---|
| 528 | + error = elan_i2c_write_cmd(client, ETP_I2C_IAP_TYPE_CMD, |
|---|
| 529 | + fw_page_size / 2); |
|---|
| 530 | + if (error) { |
|---|
| 531 | + dev_err(&client->dev, |
|---|
| 532 | + "cannot write iap type: %d\n", error); |
|---|
| 533 | + return error; |
|---|
| 534 | + } |
|---|
| 535 | + |
|---|
| 536 | + error = elan_i2c_read_cmd(client, ETP_I2C_IAP_TYPE_CMD, val); |
|---|
| 537 | + if (error) { |
|---|
| 538 | + dev_err(&client->dev, |
|---|
| 539 | + "failed to read iap type register: %d\n", |
|---|
| 540 | + error); |
|---|
| 541 | + return error; |
|---|
| 542 | + } |
|---|
| 543 | + constant = le16_to_cpup((__le16 *)val); |
|---|
| 544 | + dev_dbg(&client->dev, "iap type reg: 0x%04x\n", constant); |
|---|
| 545 | + |
|---|
| 546 | + if (constant == fw_page_size / 2) |
|---|
| 547 | + return 0; |
|---|
| 548 | + |
|---|
| 549 | + } while (--retry > 0); |
|---|
| 550 | + |
|---|
| 551 | + dev_err(&client->dev, "cannot set iap type\n"); |
|---|
| 552 | + return -EIO; |
|---|
| 553 | +} |
|---|
| 554 | + |
|---|
| 555 | +static int elan_i2c_prepare_fw_update(struct i2c_client *client, u16 ic_type, |
|---|
| 556 | + u8 iap_version, u16 fw_page_size) |
|---|
| 514 | 557 | { |
|---|
| 515 | 558 | struct device *dev = &client->dev; |
|---|
| 516 | 559 | int error; |
|---|
| .. | .. |
|---|
| 550 | 593 | return -EIO; |
|---|
| 551 | 594 | } |
|---|
| 552 | 595 | |
|---|
| 596 | + if (ic_type >= 0x0D && iap_version >= 1) { |
|---|
| 597 | + error = elan_read_write_iap_type(client, fw_page_size); |
|---|
| 598 | + if (error) |
|---|
| 599 | + return error; |
|---|
| 600 | + } |
|---|
| 601 | + |
|---|
| 553 | 602 | /* Set flash key again */ |
|---|
| 554 | 603 | error = elan_i2c_set_flash_key(client); |
|---|
| 555 | 604 | if (error) |
|---|
| .. | .. |
|---|
| 575 | 624 | return 0; |
|---|
| 576 | 625 | } |
|---|
| 577 | 626 | |
|---|
| 578 | | -static int elan_i2c_write_fw_block(struct i2c_client *client, |
|---|
| 627 | +static int elan_i2c_write_fw_block(struct i2c_client *client, u16 fw_page_size, |
|---|
| 579 | 628 | const u8 *page, u16 checksum, int idx) |
|---|
| 580 | 629 | { |
|---|
| 581 | 630 | struct device *dev = &client->dev; |
|---|
| 582 | | - u8 page_store[ETP_FW_PAGE_SIZE + 4]; |
|---|
| 631 | + u8 *page_store; |
|---|
| 583 | 632 | u8 val[3]; |
|---|
| 584 | 633 | u16 result; |
|---|
| 585 | 634 | int ret, error; |
|---|
| 586 | 635 | |
|---|
| 636 | + page_store = kmalloc(fw_page_size + 4, GFP_KERNEL); |
|---|
| 637 | + if (!page_store) |
|---|
| 638 | + return -ENOMEM; |
|---|
| 639 | + |
|---|
| 587 | 640 | page_store[0] = ETP_I2C_IAP_REG_L; |
|---|
| 588 | 641 | page_store[1] = ETP_I2C_IAP_REG_H; |
|---|
| 589 | | - memcpy(&page_store[2], page, ETP_FW_PAGE_SIZE); |
|---|
| 642 | + memcpy(&page_store[2], page, fw_page_size); |
|---|
| 590 | 643 | /* recode checksum at last two bytes */ |
|---|
| 591 | | - put_unaligned_le16(checksum, &page_store[ETP_FW_PAGE_SIZE + 2]); |
|---|
| 644 | + put_unaligned_le16(checksum, &page_store[fw_page_size + 2]); |
|---|
| 592 | 645 | |
|---|
| 593 | | - ret = i2c_master_send(client, page_store, sizeof(page_store)); |
|---|
| 594 | | - if (ret != sizeof(page_store)) { |
|---|
| 646 | + ret = i2c_master_send(client, page_store, fw_page_size + 4); |
|---|
| 647 | + if (ret != fw_page_size + 4) { |
|---|
| 595 | 648 | error = ret < 0 ? ret : -EIO; |
|---|
| 596 | 649 | dev_err(dev, "Failed to write page %d: %d\n", idx, error); |
|---|
| 597 | | - return error; |
|---|
| 650 | + goto exit; |
|---|
| 598 | 651 | } |
|---|
| 599 | 652 | |
|---|
| 600 | 653 | /* Wait for F/W to update one page ROM data. */ |
|---|
| 601 | | - msleep(35); |
|---|
| 654 | + msleep(fw_page_size == ETP_FW_PAGE_SIZE_512 ? 50 : 35); |
|---|
| 602 | 655 | |
|---|
| 603 | 656 | error = elan_i2c_read_cmd(client, ETP_I2C_IAP_CTRL_CMD, val); |
|---|
| 604 | 657 | if (error) { |
|---|
| 605 | 658 | dev_err(dev, "Failed to read IAP write result: %d\n", error); |
|---|
| 606 | | - return error; |
|---|
| 659 | + goto exit; |
|---|
| 607 | 660 | } |
|---|
| 608 | 661 | |
|---|
| 609 | 662 | result = le16_to_cpup((__le16 *)val); |
|---|
| 610 | 663 | if (result & (ETP_FW_IAP_PAGE_ERR | ETP_FW_IAP_INTF_ERR)) { |
|---|
| 611 | 664 | dev_err(dev, "IAP reports failed write: %04hx\n", |
|---|
| 612 | 665 | result); |
|---|
| 613 | | - return -EIO; |
|---|
| 666 | + error = -EIO; |
|---|
| 667 | + goto exit; |
|---|
| 614 | 668 | } |
|---|
| 615 | 669 | |
|---|
| 616 | | - return 0; |
|---|
| 670 | +exit: |
|---|
| 671 | + kfree(page_store); |
|---|
| 672 | + return error; |
|---|
| 617 | 673 | } |
|---|
| 618 | 674 | |
|---|
| 619 | 675 | static int elan_i2c_finish_fw_update(struct i2c_client *client, |
|---|
| 620 | 676 | struct completion *completion) |
|---|
| 621 | 677 | { |
|---|
| 622 | 678 | struct device *dev = &client->dev; |
|---|
| 623 | | - int error; |
|---|
| 679 | + int error = 0; |
|---|
| 624 | 680 | int len; |
|---|
| 625 | | - u8 buffer[ETP_I2C_REPORT_LEN]; |
|---|
| 681 | + u8 buffer[ETP_I2C_REPORT_MAX_LEN]; |
|---|
| 626 | 682 | |
|---|
| 627 | | - len = i2c_master_recv(client, buffer, ETP_I2C_REPORT_LEN); |
|---|
| 628 | | - if (len != ETP_I2C_REPORT_LEN) { |
|---|
| 683 | + len = i2c_master_recv(client, buffer, ETP_I2C_REPORT_MAX_LEN); |
|---|
| 684 | + if (len <= 0) { |
|---|
| 629 | 685 | error = len < 0 ? len : -EIO; |
|---|
| 630 | 686 | dev_warn(dev, "failed to read I2C data after FW WDT reset: %d (%d)\n", |
|---|
| 631 | 687 | error, len); |
|---|
| .. | .. |
|---|
| 659 | 715 | return 0; |
|---|
| 660 | 716 | } |
|---|
| 661 | 717 | |
|---|
| 662 | | -static int elan_i2c_get_report(struct i2c_client *client, u8 *report) |
|---|
| 718 | +static int elan_i2c_get_report_features(struct i2c_client *client, u8 pattern, |
|---|
| 719 | + unsigned int *features, |
|---|
| 720 | + unsigned int *report_len) |
|---|
| 721 | +{ |
|---|
| 722 | + *features = ETP_FEATURE_REPORT_MK; |
|---|
| 723 | + *report_len = pattern <= 0x01 ? |
|---|
| 724 | + ETP_I2C_REPORT_LEN : ETP_I2C_REPORT_LEN_ID2; |
|---|
| 725 | + return 0; |
|---|
| 726 | +} |
|---|
| 727 | + |
|---|
| 728 | +static int elan_i2c_get_report(struct i2c_client *client, |
|---|
| 729 | + u8 *report, unsigned int report_len) |
|---|
| 663 | 730 | { |
|---|
| 664 | 731 | int len; |
|---|
| 665 | 732 | |
|---|
| 666 | | - len = i2c_master_recv(client, report, ETP_I2C_REPORT_LEN); |
|---|
| 733 | + len = i2c_master_recv(client, report, report_len); |
|---|
| 667 | 734 | if (len < 0) { |
|---|
| 668 | 735 | dev_err(&client->dev, "failed to read report data: %d\n", len); |
|---|
| 669 | 736 | return len; |
|---|
| 670 | 737 | } |
|---|
| 671 | 738 | |
|---|
| 672 | | - if (len != ETP_I2C_REPORT_LEN) { |
|---|
| 739 | + if (len != report_len) { |
|---|
| 673 | 740 | dev_err(&client->dev, |
|---|
| 674 | 741 | "wrong report length (%d vs %d expected)\n", |
|---|
| 675 | | - len, ETP_I2C_REPORT_LEN); |
|---|
| 742 | + len, report_len); |
|---|
| 676 | 743 | return -EIO; |
|---|
| 677 | 744 | } |
|---|
| 678 | 745 | |
|---|
| .. | .. |
|---|
| 709 | 776 | |
|---|
| 710 | 777 | .get_pattern = elan_i2c_get_pattern, |
|---|
| 711 | 778 | |
|---|
| 779 | + .get_report_features = elan_i2c_get_report_features, |
|---|
| 712 | 780 | .get_report = elan_i2c_get_report, |
|---|
| 713 | 781 | }; |
|---|