1d2912cb1SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only 26696777cSDuson Lin /* 36696777cSDuson Lin * Elan I2C/SMBus Touchpad driver - I2C interface 46696777cSDuson Lin * 56696777cSDuson Lin * Copyright (c) 2013 ELAN Microelectronics Corp. 66696777cSDuson Lin * 76696777cSDuson Lin * Author: 林政維 (Duson Lin) <dusonlin@emc.com.tw> 86696777cSDuson Lin * 96696777cSDuson Lin * Based on cyapa driver: 106696777cSDuson Lin * copyright (c) 2011-2012 Cypress Semiconductor, Inc. 116696777cSDuson Lin * copyright (c) 2011-2012 Google, Inc. 126696777cSDuson Lin * 136696777cSDuson Lin * Trademarks are the property of their respective owners. 146696777cSDuson Lin */ 156696777cSDuson Lin 166696777cSDuson Lin #include <linux/completion.h> 176696777cSDuson Lin #include <linux/delay.h> 186696777cSDuson Lin #include <linux/i2c.h> 196696777cSDuson Lin #include <linux/interrupt.h> 206696777cSDuson Lin #include <linux/jiffies.h> 216696777cSDuson Lin #include <linux/kernel.h> 226696777cSDuson Lin #include <linux/sched.h> 236696777cSDuson Lin #include <asm/unaligned.h> 246696777cSDuson Lin 256696777cSDuson Lin #include "elan_i2c.h" 266696777cSDuson Lin 276696777cSDuson Lin /* Elan i2c commands */ 286696777cSDuson Lin #define ETP_I2C_RESET 0x0100 296696777cSDuson Lin #define ETP_I2C_WAKE_UP 0x0800 306696777cSDuson Lin #define ETP_I2C_SLEEP 0x0801 316696777cSDuson Lin #define ETP_I2C_DESC_CMD 0x0001 326696777cSDuson Lin #define ETP_I2C_REPORT_DESC_CMD 0x0002 336696777cSDuson Lin #define ETP_I2C_STAND_CMD 0x0005 34a2eaf299SKT Liao #define ETP_I2C_PATTERN_CMD 0x0100 356696777cSDuson Lin #define ETP_I2C_UNIQUEID_CMD 0x0101 366696777cSDuson Lin #define ETP_I2C_FW_VERSION_CMD 0x0102 37a2eaf299SKT Liao #define ETP_I2C_IC_TYPE_CMD 0x0103 38a2eaf299SKT Liao #define ETP_I2C_OSM_VERSION_CMD 0x0103 39a2eaf299SKT Liao #define ETP_I2C_NSM_VERSION_CMD 0x0104 406696777cSDuson Lin #define ETP_I2C_XY_TRACENUM_CMD 0x0105 416696777cSDuson Lin #define ETP_I2C_MAX_X_AXIS_CMD 0x0106 426696777cSDuson Lin #define ETP_I2C_MAX_Y_AXIS_CMD 0x0107 436696777cSDuson Lin #define ETP_I2C_RESOLUTION_CMD 0x0108 44b9bced0eSduson #define ETP_I2C_PRESSURE_CMD 0x010A 456696777cSDuson Lin #define ETP_I2C_IAP_VERSION_CMD 0x0110 46*fc7c882aSJingle Wu #define ETP_I2C_IC_TYPE_P0_CMD 0x0110 476696777cSDuson Lin #define ETP_I2C_SET_CMD 0x0300 486696777cSDuson Lin #define ETP_I2C_POWER_CMD 0x0307 496696777cSDuson Lin #define ETP_I2C_FW_CHECKSUM_CMD 0x030F 506696777cSDuson Lin #define ETP_I2C_IAP_CTRL_CMD 0x0310 516696777cSDuson Lin #define ETP_I2C_IAP_CMD 0x0311 526696777cSDuson Lin #define ETP_I2C_IAP_RESET_CMD 0x0314 536696777cSDuson Lin #define ETP_I2C_IAP_CHECKSUM_CMD 0x0315 546696777cSDuson Lin #define ETP_I2C_CALIBRATE_CMD 0x0316 556696777cSDuson Lin #define ETP_I2C_MAX_BASELINE_CMD 0x0317 566696777cSDuson Lin #define ETP_I2C_MIN_BASELINE_CMD 0x0318 576696777cSDuson Lin 586696777cSDuson Lin #define ETP_I2C_REPORT_LEN 34 596696777cSDuson Lin #define ETP_I2C_DESC_LENGTH 30 606696777cSDuson Lin #define ETP_I2C_REPORT_DESC_LENGTH 158 616696777cSDuson Lin #define ETP_I2C_INF_LENGTH 2 626696777cSDuson Lin #define ETP_I2C_IAP_PASSWORD 0x1EA5 636696777cSDuson Lin #define ETP_I2C_IAP_RESET 0xF0F0 646696777cSDuson Lin #define ETP_I2C_MAIN_MODE_ON (1 << 9) 656696777cSDuson Lin #define ETP_I2C_IAP_REG_L 0x01 666696777cSDuson Lin #define ETP_I2C_IAP_REG_H 0x06 676696777cSDuson Lin 686696777cSDuson Lin static int elan_i2c_read_block(struct i2c_client *client, 696696777cSDuson Lin u16 reg, u8 *val, u16 len) 706696777cSDuson Lin { 716696777cSDuson Lin __le16 buf[] = { 726696777cSDuson Lin cpu_to_le16(reg), 736696777cSDuson Lin }; 746696777cSDuson Lin struct i2c_msg msgs[] = { 756696777cSDuson Lin { 766696777cSDuson Lin .addr = client->addr, 776696777cSDuson Lin .flags = client->flags & I2C_M_TEN, 786696777cSDuson Lin .len = sizeof(buf), 796696777cSDuson Lin .buf = (u8 *)buf, 806696777cSDuson Lin }, 816696777cSDuson Lin { 826696777cSDuson Lin .addr = client->addr, 836696777cSDuson Lin .flags = (client->flags & I2C_M_TEN) | I2C_M_RD, 846696777cSDuson Lin .len = len, 856696777cSDuson Lin .buf = val, 866696777cSDuson Lin } 876696777cSDuson Lin }; 886696777cSDuson Lin int ret; 896696777cSDuson Lin 906696777cSDuson Lin ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); 916696777cSDuson Lin return ret == ARRAY_SIZE(msgs) ? 0 : (ret < 0 ? ret : -EIO); 926696777cSDuson Lin } 936696777cSDuson Lin 946696777cSDuson Lin static int elan_i2c_read_cmd(struct i2c_client *client, u16 reg, u8 *val) 956696777cSDuson Lin { 966696777cSDuson Lin int retval; 976696777cSDuson Lin 986696777cSDuson Lin retval = elan_i2c_read_block(client, reg, val, ETP_I2C_INF_LENGTH); 996696777cSDuson Lin if (retval < 0) { 1006696777cSDuson Lin dev_err(&client->dev, "reading cmd (0x%04x) fail.\n", reg); 1016696777cSDuson Lin return retval; 1026696777cSDuson Lin } 1036696777cSDuson Lin 1046696777cSDuson Lin return 0; 1056696777cSDuson Lin } 1066696777cSDuson Lin 1076696777cSDuson Lin static int elan_i2c_write_cmd(struct i2c_client *client, u16 reg, u16 cmd) 1086696777cSDuson Lin { 1096696777cSDuson Lin __le16 buf[] = { 1106696777cSDuson Lin cpu_to_le16(reg), 1116696777cSDuson Lin cpu_to_le16(cmd), 1126696777cSDuson Lin }; 1136696777cSDuson Lin struct i2c_msg msg = { 1146696777cSDuson Lin .addr = client->addr, 1156696777cSDuson Lin .flags = client->flags & I2C_M_TEN, 1166696777cSDuson Lin .len = sizeof(buf), 1176696777cSDuson Lin .buf = (u8 *)buf, 1186696777cSDuson Lin }; 1196696777cSDuson Lin int ret; 1206696777cSDuson Lin 1216696777cSDuson Lin ret = i2c_transfer(client->adapter, &msg, 1); 122b3beed7fSDuson Lin if (ret != 1) { 123b3beed7fSDuson Lin if (ret >= 0) 124b3beed7fSDuson Lin ret = -EIO; 125b3beed7fSDuson Lin dev_err(&client->dev, "writing cmd (0x%04x) failed: %d\n", 126b3beed7fSDuson Lin reg, ret); 127b3beed7fSDuson Lin return ret; 128b3beed7fSDuson Lin } 129b3beed7fSDuson Lin 130b3beed7fSDuson Lin return 0; 1316696777cSDuson Lin } 1326696777cSDuson Lin 1336696777cSDuson Lin static int elan_i2c_initialize(struct i2c_client *client) 1346696777cSDuson Lin { 1356696777cSDuson Lin struct device *dev = &client->dev; 1366696777cSDuson Lin int error; 1376696777cSDuson Lin u8 val[256]; 1386696777cSDuson Lin 1396696777cSDuson Lin error = elan_i2c_write_cmd(client, ETP_I2C_STAND_CMD, ETP_I2C_RESET); 1406696777cSDuson Lin if (error) { 1416696777cSDuson Lin dev_err(dev, "device reset failed: %d\n", error); 1426696777cSDuson Lin return error; 1436696777cSDuson Lin } 1446696777cSDuson Lin 1456696777cSDuson Lin /* Wait for the device to reset */ 1466696777cSDuson Lin msleep(100); 1476696777cSDuson Lin 1486696777cSDuson Lin /* get reset acknowledgement 0000 */ 1496696777cSDuson Lin error = i2c_master_recv(client, val, ETP_I2C_INF_LENGTH); 1506696777cSDuson Lin if (error < 0) { 1516696777cSDuson Lin dev_err(dev, "failed to read reset response: %d\n", error); 1526696777cSDuson Lin return error; 1536696777cSDuson Lin } 1546696777cSDuson Lin 1556696777cSDuson Lin error = elan_i2c_read_block(client, ETP_I2C_DESC_CMD, 1566696777cSDuson Lin val, ETP_I2C_DESC_LENGTH); 1576696777cSDuson Lin if (error) { 1586696777cSDuson Lin dev_err(dev, "cannot get device descriptor: %d\n", error); 1596696777cSDuson Lin return error; 1606696777cSDuson Lin } 1616696777cSDuson Lin 1626696777cSDuson Lin error = elan_i2c_read_block(client, ETP_I2C_REPORT_DESC_CMD, 1636696777cSDuson Lin val, ETP_I2C_REPORT_DESC_LENGTH); 1646696777cSDuson Lin if (error) { 1656696777cSDuson Lin dev_err(dev, "fetching report descriptor failed.: %d\n", error); 1666696777cSDuson Lin return error; 1676696777cSDuson Lin } 1686696777cSDuson Lin 1696696777cSDuson Lin return 0; 1706696777cSDuson Lin } 1716696777cSDuson Lin 1726696777cSDuson Lin static int elan_i2c_sleep_control(struct i2c_client *client, bool sleep) 1736696777cSDuson Lin { 1746696777cSDuson Lin return elan_i2c_write_cmd(client, ETP_I2C_STAND_CMD, 1756696777cSDuson Lin sleep ? ETP_I2C_SLEEP : ETP_I2C_WAKE_UP); 1766696777cSDuson Lin } 1776696777cSDuson Lin 1786696777cSDuson Lin static int elan_i2c_power_control(struct i2c_client *client, bool enable) 1796696777cSDuson Lin { 1806696777cSDuson Lin u8 val[2]; 1816696777cSDuson Lin u16 reg; 1826696777cSDuson Lin int error; 1836696777cSDuson Lin 1846696777cSDuson Lin error = elan_i2c_read_cmd(client, ETP_I2C_POWER_CMD, val); 1856696777cSDuson Lin if (error) { 1866696777cSDuson Lin dev_err(&client->dev, 1876696777cSDuson Lin "failed to read current power state: %d\n", 1886696777cSDuson Lin error); 1896696777cSDuson Lin return error; 1906696777cSDuson Lin } 1916696777cSDuson Lin 1926696777cSDuson Lin reg = le16_to_cpup((__le16 *)val); 1936696777cSDuson Lin if (enable) 1946696777cSDuson Lin reg &= ~ETP_DISABLE_POWER; 1956696777cSDuson Lin else 1966696777cSDuson Lin reg |= ETP_DISABLE_POWER; 1976696777cSDuson Lin 1986696777cSDuson Lin error = elan_i2c_write_cmd(client, ETP_I2C_POWER_CMD, reg); 1996696777cSDuson Lin if (error) { 2006696777cSDuson Lin dev_err(&client->dev, 2016696777cSDuson Lin "failed to write current power state: %d\n", 2026696777cSDuson Lin error); 2036696777cSDuson Lin return error; 2046696777cSDuson Lin } 2056696777cSDuson Lin 2066696777cSDuson Lin return 0; 2076696777cSDuson Lin } 2086696777cSDuson Lin 2096696777cSDuson Lin static int elan_i2c_set_mode(struct i2c_client *client, u8 mode) 2106696777cSDuson Lin { 2116696777cSDuson Lin return elan_i2c_write_cmd(client, ETP_I2C_SET_CMD, mode); 2126696777cSDuson Lin } 2136696777cSDuson Lin 2146696777cSDuson Lin 2156696777cSDuson Lin static int elan_i2c_calibrate(struct i2c_client *client) 2166696777cSDuson Lin { 2176696777cSDuson Lin return elan_i2c_write_cmd(client, ETP_I2C_CALIBRATE_CMD, 1); 2186696777cSDuson Lin } 2196696777cSDuson Lin 2206696777cSDuson Lin static int elan_i2c_calibrate_result(struct i2c_client *client, u8 *val) 2216696777cSDuson Lin { 2226696777cSDuson Lin return elan_i2c_read_block(client, ETP_I2C_CALIBRATE_CMD, val, 1); 2236696777cSDuson Lin } 2246696777cSDuson Lin 2256696777cSDuson Lin static int elan_i2c_get_baseline_data(struct i2c_client *client, 2266696777cSDuson Lin bool max_baseline, u8 *value) 2276696777cSDuson Lin { 2286696777cSDuson Lin int error; 2296696777cSDuson Lin u8 val[3]; 2306696777cSDuson Lin 2316696777cSDuson Lin error = elan_i2c_read_cmd(client, 2326696777cSDuson Lin max_baseline ? ETP_I2C_MAX_BASELINE_CMD : 2336696777cSDuson Lin ETP_I2C_MIN_BASELINE_CMD, 2346696777cSDuson Lin val); 2356696777cSDuson Lin if (error) 2366696777cSDuson Lin return error; 2376696777cSDuson Lin 2386696777cSDuson Lin *value = le16_to_cpup((__le16 *)val); 2396696777cSDuson Lin 2406696777cSDuson Lin return 0; 2416696777cSDuson Lin } 2426696777cSDuson Lin 243a2eaf299SKT Liao static int elan_i2c_get_pattern(struct i2c_client *client, u8 *pattern) 244a2eaf299SKT Liao { 245a2eaf299SKT Liao int error; 246a2eaf299SKT Liao u8 val[3]; 247a2eaf299SKT Liao 248a2eaf299SKT Liao error = elan_i2c_read_cmd(client, ETP_I2C_PATTERN_CMD, val); 249a2eaf299SKT Liao if (error) { 250a2eaf299SKT Liao dev_err(&client->dev, "failed to get pattern: %d\n", error); 251a2eaf299SKT Liao return error; 252a2eaf299SKT Liao } 25377da21c5SJingle Wu 25477da21c5SJingle Wu /* 25577da21c5SJingle Wu * Not all versions of firmware implement "get pattern" command. 25677da21c5SJingle Wu * When this command is not implemented the device will respond 25777da21c5SJingle Wu * with 0xFF 0xFF, which we will treat as "old" pattern 0. 25877da21c5SJingle Wu */ 25977da21c5SJingle Wu *pattern = val[0] == 0xFF && val[1] == 0xFF ? 0 : val[1]; 260a2eaf299SKT Liao 261a2eaf299SKT Liao return 0; 262a2eaf299SKT Liao } 263a2eaf299SKT Liao 2646696777cSDuson Lin static int elan_i2c_get_version(struct i2c_client *client, 2656696777cSDuson Lin bool iap, u8 *version) 2666696777cSDuson Lin { 2676696777cSDuson Lin int error; 268a2eaf299SKT Liao u8 pattern_ver; 2696696777cSDuson Lin u8 val[3]; 2706696777cSDuson Lin 271a2eaf299SKT Liao error = elan_i2c_get_pattern(client, &pattern_ver); 272a2eaf299SKT Liao if (error) { 273a2eaf299SKT Liao dev_err(&client->dev, "failed to get pattern version\n"); 274a2eaf299SKT Liao return error; 275a2eaf299SKT Liao } 276a2eaf299SKT Liao 2776696777cSDuson Lin error = elan_i2c_read_cmd(client, 2786696777cSDuson Lin iap ? ETP_I2C_IAP_VERSION_CMD : 2796696777cSDuson Lin ETP_I2C_FW_VERSION_CMD, 2806696777cSDuson Lin val); 2816696777cSDuson Lin if (error) { 2826696777cSDuson Lin dev_err(&client->dev, "failed to get %s version: %d\n", 2836696777cSDuson Lin iap ? "IAP" : "FW", error); 2846696777cSDuson Lin return error; 2856696777cSDuson Lin } 2866696777cSDuson Lin 287a2eaf299SKT Liao if (pattern_ver == 0x01) 288a2eaf299SKT Liao *version = iap ? val[1] : val[0]; 289a2eaf299SKT Liao else 2906696777cSDuson Lin *version = val[0]; 2916696777cSDuson Lin return 0; 2926696777cSDuson Lin } 2936696777cSDuson Lin 29412018ac3SDuson Lin static int elan_i2c_get_sm_version(struct i2c_client *client, 29599136881SKT Liao u16 *ic_type, u8 *version, 29699136881SKT Liao u8 *clickpad) 2976696777cSDuson Lin { 2986696777cSDuson Lin int error; 299a2eaf299SKT Liao u8 pattern_ver; 3006696777cSDuson Lin u8 val[3]; 3016696777cSDuson Lin 302a2eaf299SKT Liao error = elan_i2c_get_pattern(client, &pattern_ver); 3036696777cSDuson Lin if (error) { 304a2eaf299SKT Liao dev_err(&client->dev, "failed to get pattern version\n"); 3056696777cSDuson Lin return error; 3066696777cSDuson Lin } 3076696777cSDuson Lin 308a2eaf299SKT Liao if (pattern_ver == 0x01) { 309a2eaf299SKT Liao error = elan_i2c_read_cmd(client, ETP_I2C_IC_TYPE_CMD, val); 310a2eaf299SKT Liao if (error) { 311a2eaf299SKT Liao dev_err(&client->dev, "failed to get ic type: %d\n", 312a2eaf299SKT Liao error); 313a2eaf299SKT Liao return error; 314a2eaf299SKT Liao } 315a2eaf299SKT Liao *ic_type = be16_to_cpup((__be16 *)val); 316a2eaf299SKT Liao 317a2eaf299SKT Liao error = elan_i2c_read_cmd(client, ETP_I2C_NSM_VERSION_CMD, 318a2eaf299SKT Liao val); 319a2eaf299SKT Liao if (error) { 320a2eaf299SKT Liao dev_err(&client->dev, "failed to get SM version: %d\n", 321a2eaf299SKT Liao error); 322a2eaf299SKT Liao return error; 323a2eaf299SKT Liao } 324a2eaf299SKT Liao *version = val[1]; 32599136881SKT Liao *clickpad = val[0] & 0x10; 326a2eaf299SKT Liao } else { 327a2eaf299SKT Liao error = elan_i2c_read_cmd(client, ETP_I2C_OSM_VERSION_CMD, val); 328a2eaf299SKT Liao if (error) { 329a2eaf299SKT Liao dev_err(&client->dev, "failed to get SM version: %d\n", 330a2eaf299SKT Liao error); 331a2eaf299SKT Liao return error; 332a2eaf299SKT Liao } 3336696777cSDuson Lin *version = val[0]; 334*fc7c882aSJingle Wu 335*fc7c882aSJingle Wu error = elan_i2c_read_cmd(client, ETP_I2C_IC_TYPE_P0_CMD, val); 336*fc7c882aSJingle Wu if (error) { 337*fc7c882aSJingle Wu dev_err(&client->dev, "failed to get ic type: %d\n", 338*fc7c882aSJingle Wu error); 339*fc7c882aSJingle Wu return error; 340*fc7c882aSJingle Wu } 341*fc7c882aSJingle Wu *ic_type = val[0]; 34299136881SKT Liao 34399136881SKT Liao error = elan_i2c_read_cmd(client, ETP_I2C_NSM_VERSION_CMD, 34499136881SKT Liao val); 34599136881SKT Liao if (error) { 34699136881SKT Liao dev_err(&client->dev, "failed to get SM version: %d\n", 34799136881SKT Liao error); 34899136881SKT Liao return error; 34999136881SKT Liao } 35099136881SKT Liao *clickpad = val[0] & 0x10; 351a2eaf299SKT Liao } 352a2eaf299SKT Liao 3536696777cSDuson Lin return 0; 3546696777cSDuson Lin } 3556696777cSDuson Lin 356ed75a14eSDuson Lin static int elan_i2c_get_product_id(struct i2c_client *client, u16 *id) 3576696777cSDuson Lin { 3586696777cSDuson Lin int error; 3596696777cSDuson Lin u8 val[3]; 3606696777cSDuson Lin 3616696777cSDuson Lin error = elan_i2c_read_cmd(client, ETP_I2C_UNIQUEID_CMD, val); 3626696777cSDuson Lin if (error) { 3636696777cSDuson Lin dev_err(&client->dev, "failed to get product ID: %d\n", error); 3646696777cSDuson Lin return error; 3656696777cSDuson Lin } 3666696777cSDuson Lin 367ed75a14eSDuson Lin *id = le16_to_cpup((__le16 *)val); 3686696777cSDuson Lin return 0; 3696696777cSDuson Lin } 3706696777cSDuson Lin 3716696777cSDuson Lin static int elan_i2c_get_checksum(struct i2c_client *client, 3726696777cSDuson Lin bool iap, u16 *csum) 3736696777cSDuson Lin { 3746696777cSDuson Lin int error; 3756696777cSDuson Lin u8 val[3]; 3766696777cSDuson Lin 3776696777cSDuson Lin error = elan_i2c_read_cmd(client, 3786696777cSDuson Lin iap ? ETP_I2C_IAP_CHECKSUM_CMD : 3796696777cSDuson Lin ETP_I2C_FW_CHECKSUM_CMD, 3806696777cSDuson Lin val); 3816696777cSDuson Lin if (error) { 3826696777cSDuson Lin dev_err(&client->dev, "failed to get %s checksum: %d\n", 3836696777cSDuson Lin iap ? "IAP" : "FW", error); 3846696777cSDuson Lin return error; 3856696777cSDuson Lin } 3866696777cSDuson Lin 3876696777cSDuson Lin *csum = le16_to_cpup((__le16 *)val); 3886696777cSDuson Lin return 0; 3896696777cSDuson Lin } 3906696777cSDuson Lin 3916696777cSDuson Lin static int elan_i2c_get_max(struct i2c_client *client, 3926696777cSDuson Lin unsigned int *max_x, unsigned int *max_y) 3936696777cSDuson Lin { 3946696777cSDuson Lin int error; 3956696777cSDuson Lin u8 val[3]; 3966696777cSDuson Lin 3976696777cSDuson Lin error = elan_i2c_read_cmd(client, ETP_I2C_MAX_X_AXIS_CMD, val); 3986696777cSDuson Lin if (error) { 3996696777cSDuson Lin dev_err(&client->dev, "failed to get X dimension: %d\n", error); 4006696777cSDuson Lin return error; 4016696777cSDuson Lin } 4026696777cSDuson Lin 4036696777cSDuson Lin *max_x = le16_to_cpup((__le16 *)val) & 0x0fff; 4046696777cSDuson Lin 4056696777cSDuson Lin error = elan_i2c_read_cmd(client, ETP_I2C_MAX_Y_AXIS_CMD, val); 4066696777cSDuson Lin if (error) { 4076696777cSDuson Lin dev_err(&client->dev, "failed to get Y dimension: %d\n", error); 4086696777cSDuson Lin return error; 4096696777cSDuson Lin } 4106696777cSDuson Lin 4116696777cSDuson Lin *max_y = le16_to_cpup((__le16 *)val) & 0x0fff; 4126696777cSDuson Lin 4136696777cSDuson Lin return 0; 4146696777cSDuson Lin } 4156696777cSDuson Lin 4166696777cSDuson Lin static int elan_i2c_get_resolution(struct i2c_client *client, 4176696777cSDuson Lin u8 *hw_res_x, u8 *hw_res_y) 4186696777cSDuson Lin { 4196696777cSDuson Lin int error; 4206696777cSDuson Lin u8 val[3]; 4216696777cSDuson Lin 4226696777cSDuson Lin error = elan_i2c_read_cmd(client, ETP_I2C_RESOLUTION_CMD, val); 4236696777cSDuson Lin if (error) { 4246696777cSDuson Lin dev_err(&client->dev, "failed to get resolution: %d\n", error); 4256696777cSDuson Lin return error; 4266696777cSDuson Lin } 4276696777cSDuson Lin 4286696777cSDuson Lin *hw_res_x = val[0]; 4296696777cSDuson Lin *hw_res_y = val[1]; 4306696777cSDuson Lin 4316696777cSDuson Lin return 0; 4326696777cSDuson Lin } 4336696777cSDuson Lin 4346696777cSDuson Lin static int elan_i2c_get_num_traces(struct i2c_client *client, 4356696777cSDuson Lin unsigned int *x_traces, 4366696777cSDuson Lin unsigned int *y_traces) 4376696777cSDuson Lin { 4386696777cSDuson Lin int error; 4396696777cSDuson Lin u8 val[3]; 4406696777cSDuson Lin 4416696777cSDuson Lin error = elan_i2c_read_cmd(client, ETP_I2C_XY_TRACENUM_CMD, val); 4426696777cSDuson Lin if (error) { 4436696777cSDuson Lin dev_err(&client->dev, "failed to get trace info: %d\n", error); 4446696777cSDuson Lin return error; 4456696777cSDuson Lin } 4466696777cSDuson Lin 4479f423801SDuson Lin *x_traces = val[0]; 4489f423801SDuson Lin *y_traces = val[1]; 4496696777cSDuson Lin 4506696777cSDuson Lin return 0; 4516696777cSDuson Lin } 4526696777cSDuson Lin 453b9bced0eSduson static int elan_i2c_get_pressure_adjustment(struct i2c_client *client, 454b9bced0eSduson int *adjustment) 455b9bced0eSduson { 456b9bced0eSduson int error; 457b9bced0eSduson u8 val[3]; 458b9bced0eSduson 459b9bced0eSduson error = elan_i2c_read_cmd(client, ETP_I2C_PRESSURE_CMD, val); 460b9bced0eSduson if (error) { 461b9bced0eSduson dev_err(&client->dev, "failed to get pressure format: %d\n", 462b9bced0eSduson error); 463b9bced0eSduson return error; 464b9bced0eSduson } 465b9bced0eSduson 466b9bced0eSduson if ((val[0] >> 4) & 0x1) 467b9bced0eSduson *adjustment = 0; 468b9bced0eSduson else 469b9bced0eSduson *adjustment = ETP_PRESSURE_OFFSET; 470b9bced0eSduson 471b9bced0eSduson return 0; 472b9bced0eSduson } 473b9bced0eSduson 4746696777cSDuson Lin static int elan_i2c_iap_get_mode(struct i2c_client *client, enum tp_mode *mode) 4756696777cSDuson Lin { 4766696777cSDuson Lin int error; 4776696777cSDuson Lin u16 constant; 4786696777cSDuson Lin u8 val[3]; 4796696777cSDuson Lin 4806696777cSDuson Lin error = elan_i2c_read_cmd(client, ETP_I2C_IAP_CTRL_CMD, val); 4816696777cSDuson Lin if (error) { 4826696777cSDuson Lin dev_err(&client->dev, 4836696777cSDuson Lin "failed to read iap control register: %d\n", 4846696777cSDuson Lin error); 4856696777cSDuson Lin return error; 4866696777cSDuson Lin } 4876696777cSDuson Lin 4886696777cSDuson Lin constant = le16_to_cpup((__le16 *)val); 4896696777cSDuson Lin dev_dbg(&client->dev, "iap control reg: 0x%04x.\n", constant); 4906696777cSDuson Lin 4916696777cSDuson Lin *mode = (constant & ETP_I2C_MAIN_MODE_ON) ? MAIN_MODE : IAP_MODE; 4926696777cSDuson Lin 4936696777cSDuson Lin return 0; 4946696777cSDuson Lin } 4956696777cSDuson Lin 4966696777cSDuson Lin static int elan_i2c_iap_reset(struct i2c_client *client) 4976696777cSDuson Lin { 4986696777cSDuson Lin int error; 4996696777cSDuson Lin 5006696777cSDuson Lin error = elan_i2c_write_cmd(client, ETP_I2C_IAP_RESET_CMD, 5016696777cSDuson Lin ETP_I2C_IAP_RESET); 5026696777cSDuson Lin if (error) { 5036696777cSDuson Lin dev_err(&client->dev, "cannot reset IC: %d\n", error); 5046696777cSDuson Lin return error; 5056696777cSDuson Lin } 5066696777cSDuson Lin 5076696777cSDuson Lin return 0; 5086696777cSDuson Lin } 5096696777cSDuson Lin 5106696777cSDuson Lin static int elan_i2c_set_flash_key(struct i2c_client *client) 5116696777cSDuson Lin { 5126696777cSDuson Lin int error; 5136696777cSDuson Lin 5146696777cSDuson Lin error = elan_i2c_write_cmd(client, ETP_I2C_IAP_CMD, 5156696777cSDuson Lin ETP_I2C_IAP_PASSWORD); 5166696777cSDuson Lin if (error) { 5176696777cSDuson Lin dev_err(&client->dev, "cannot set flash key: %d\n", error); 5186696777cSDuson Lin return error; 5196696777cSDuson Lin } 5206696777cSDuson Lin 5216696777cSDuson Lin return 0; 5226696777cSDuson Lin } 5236696777cSDuson Lin 5246696777cSDuson Lin static int elan_i2c_prepare_fw_update(struct i2c_client *client) 5256696777cSDuson Lin { 5266696777cSDuson Lin struct device *dev = &client->dev; 5276696777cSDuson Lin int error; 5286696777cSDuson Lin enum tp_mode mode; 5296696777cSDuson Lin u8 val[3]; 5306696777cSDuson Lin u16 password; 5316696777cSDuson Lin 5326696777cSDuson Lin /* Get FW in which mode (IAP_MODE/MAIN_MODE) */ 5336696777cSDuson Lin error = elan_i2c_iap_get_mode(client, &mode); 5346696777cSDuson Lin if (error) 5356696777cSDuson Lin return error; 5366696777cSDuson Lin 5376696777cSDuson Lin if (mode == IAP_MODE) { 5386696777cSDuson Lin /* Reset IC */ 5396696777cSDuson Lin error = elan_i2c_iap_reset(client); 5406696777cSDuson Lin if (error) 5416696777cSDuson Lin return error; 5426696777cSDuson Lin 5436696777cSDuson Lin msleep(30); 5446696777cSDuson Lin } 5456696777cSDuson Lin 5466696777cSDuson Lin /* Set flash key*/ 5476696777cSDuson Lin error = elan_i2c_set_flash_key(client); 5486696777cSDuson Lin if (error) 5496696777cSDuson Lin return error; 5506696777cSDuson Lin 5516696777cSDuson Lin /* Wait for F/W IAP initialization */ 5526696777cSDuson Lin msleep(mode == MAIN_MODE ? 100 : 30); 5536696777cSDuson Lin 5546696777cSDuson Lin /* Check if we are in IAP mode or not */ 5556696777cSDuson Lin error = elan_i2c_iap_get_mode(client, &mode); 5566696777cSDuson Lin if (error) 5576696777cSDuson Lin return error; 5586696777cSDuson Lin 5596696777cSDuson Lin if (mode == MAIN_MODE) { 5606696777cSDuson Lin dev_err(dev, "wrong mode: %d\n", mode); 5616696777cSDuson Lin return -EIO; 5626696777cSDuson Lin } 5636696777cSDuson Lin 5646696777cSDuson Lin /* Set flash key again */ 5656696777cSDuson Lin error = elan_i2c_set_flash_key(client); 5666696777cSDuson Lin if (error) 5676696777cSDuson Lin return error; 5686696777cSDuson Lin 5696696777cSDuson Lin /* Wait for F/W IAP initialization */ 5706696777cSDuson Lin msleep(30); 5716696777cSDuson Lin 5726696777cSDuson Lin /* read back to check we actually enabled successfully. */ 5736696777cSDuson Lin error = elan_i2c_read_cmd(client, ETP_I2C_IAP_CMD, val); 5746696777cSDuson Lin if (error) { 5756696777cSDuson Lin dev_err(dev, "cannot read iap password: %d\n", 5766696777cSDuson Lin error); 5776696777cSDuson Lin return error; 5786696777cSDuson Lin } 5796696777cSDuson Lin 5806696777cSDuson Lin password = le16_to_cpup((__le16 *)val); 5816696777cSDuson Lin if (password != ETP_I2C_IAP_PASSWORD) { 5826696777cSDuson Lin dev_err(dev, "wrong iap password: 0x%X\n", password); 5836696777cSDuson Lin return -EIO; 5846696777cSDuson Lin } 5856696777cSDuson Lin 5866696777cSDuson Lin return 0; 5876696777cSDuson Lin } 5886696777cSDuson Lin 5896696777cSDuson Lin static int elan_i2c_write_fw_block(struct i2c_client *client, 5906696777cSDuson Lin const u8 *page, u16 checksum, int idx) 5916696777cSDuson Lin { 5926696777cSDuson Lin struct device *dev = &client->dev; 5936696777cSDuson Lin u8 page_store[ETP_FW_PAGE_SIZE + 4]; 5946696777cSDuson Lin u8 val[3]; 5956696777cSDuson Lin u16 result; 5966696777cSDuson Lin int ret, error; 5976696777cSDuson Lin 5986696777cSDuson Lin page_store[0] = ETP_I2C_IAP_REG_L; 5996696777cSDuson Lin page_store[1] = ETP_I2C_IAP_REG_H; 6006696777cSDuson Lin memcpy(&page_store[2], page, ETP_FW_PAGE_SIZE); 6016696777cSDuson Lin /* recode checksum at last two bytes */ 6026696777cSDuson Lin put_unaligned_le16(checksum, &page_store[ETP_FW_PAGE_SIZE + 2]); 6036696777cSDuson Lin 6046696777cSDuson Lin ret = i2c_master_send(client, page_store, sizeof(page_store)); 6056696777cSDuson Lin if (ret != sizeof(page_store)) { 6066696777cSDuson Lin error = ret < 0 ? ret : -EIO; 6076696777cSDuson Lin dev_err(dev, "Failed to write page %d: %d\n", idx, error); 6086696777cSDuson Lin return error; 6096696777cSDuson Lin } 6106696777cSDuson Lin 6116696777cSDuson Lin /* Wait for F/W to update one page ROM data. */ 61205f5c385SKT Liao msleep(35); 6136696777cSDuson Lin 6146696777cSDuson Lin error = elan_i2c_read_cmd(client, ETP_I2C_IAP_CTRL_CMD, val); 6156696777cSDuson Lin if (error) { 6166696777cSDuson Lin dev_err(dev, "Failed to read IAP write result: %d\n", error); 6176696777cSDuson Lin return error; 6186696777cSDuson Lin } 6196696777cSDuson Lin 6206696777cSDuson Lin result = le16_to_cpup((__le16 *)val); 6216696777cSDuson Lin if (result & (ETP_FW_IAP_PAGE_ERR | ETP_FW_IAP_INTF_ERR)) { 6226696777cSDuson Lin dev_err(dev, "IAP reports failed write: %04hx\n", 6236696777cSDuson Lin result); 6246696777cSDuson Lin return -EIO; 6256696777cSDuson Lin } 6266696777cSDuson Lin 6276696777cSDuson Lin return 0; 6286696777cSDuson Lin } 6296696777cSDuson Lin 6306696777cSDuson Lin static int elan_i2c_finish_fw_update(struct i2c_client *client, 6316696777cSDuson Lin struct completion *completion) 6326696777cSDuson Lin { 6336696777cSDuson Lin struct device *dev = &client->dev; 6346696777cSDuson Lin int error; 6356696777cSDuson Lin int len; 6364b3c7dbbSKT Liao u8 buffer[ETP_I2C_REPORT_LEN]; 6374b3c7dbbSKT Liao 6384b3c7dbbSKT Liao len = i2c_master_recv(client, buffer, ETP_I2C_REPORT_LEN); 6394b3c7dbbSKT Liao if (len != ETP_I2C_REPORT_LEN) { 6404b3c7dbbSKT Liao error = len < 0 ? len : -EIO; 6414b3c7dbbSKT Liao dev_warn(dev, "failed to read I2C data after FW WDT reset: %d (%d)\n", 6424b3c7dbbSKT Liao error, len); 6434b3c7dbbSKT Liao } 6446696777cSDuson Lin 6456696777cSDuson Lin reinit_completion(completion); 6466696777cSDuson Lin enable_irq(client->irq); 6476696777cSDuson Lin 6486696777cSDuson Lin error = elan_i2c_write_cmd(client, ETP_I2C_STAND_CMD, ETP_I2C_RESET); 6496696777cSDuson Lin if (error) { 6506696777cSDuson Lin dev_err(dev, "device reset failed: %d\n", error); 651a04f1440SKT Liao } else if (!wait_for_completion_timeout(completion, 652a04f1440SKT Liao msecs_to_jiffies(300))) { 6536696777cSDuson Lin dev_err(dev, "timeout waiting for device reset\n"); 654a04f1440SKT Liao error = -ETIMEDOUT; 6556696777cSDuson Lin } 6566696777cSDuson Lin 657a04f1440SKT Liao disable_irq(client->irq); 658a04f1440SKT Liao 659a04f1440SKT Liao if (error) 660a04f1440SKT Liao return error; 661a04f1440SKT Liao 6626696777cSDuson Lin len = i2c_master_recv(client, buffer, ETP_I2C_INF_LENGTH); 6636696777cSDuson Lin if (len != ETP_I2C_INF_LENGTH) { 6646696777cSDuson Lin error = len < 0 ? len : -EIO; 6656696777cSDuson Lin dev_err(dev, "failed to read INT signal: %d (%d)\n", 6666696777cSDuson Lin error, len); 6676696777cSDuson Lin return error; 6686696777cSDuson Lin } 6696696777cSDuson Lin 6706696777cSDuson Lin return 0; 6716696777cSDuson Lin } 6726696777cSDuson Lin 6736696777cSDuson Lin static int elan_i2c_get_report(struct i2c_client *client, u8 *report) 6746696777cSDuson Lin { 6756696777cSDuson Lin int len; 6766696777cSDuson Lin 6776696777cSDuson Lin len = i2c_master_recv(client, report, ETP_I2C_REPORT_LEN); 6786696777cSDuson Lin if (len < 0) { 6796696777cSDuson Lin dev_err(&client->dev, "failed to read report data: %d\n", len); 6806696777cSDuson Lin return len; 6816696777cSDuson Lin } 6826696777cSDuson Lin 6836696777cSDuson Lin if (len != ETP_I2C_REPORT_LEN) { 6846696777cSDuson Lin dev_err(&client->dev, 6856696777cSDuson Lin "wrong report length (%d vs %d expected)\n", 6866696777cSDuson Lin len, ETP_I2C_REPORT_LEN); 6876696777cSDuson Lin return -EIO; 6886696777cSDuson Lin } 6896696777cSDuson Lin 6906696777cSDuson Lin return 0; 6916696777cSDuson Lin } 6926696777cSDuson Lin 6936696777cSDuson Lin const struct elan_transport_ops elan_i2c_ops = { 6946696777cSDuson Lin .initialize = elan_i2c_initialize, 6956696777cSDuson Lin .sleep_control = elan_i2c_sleep_control, 6966696777cSDuson Lin .power_control = elan_i2c_power_control, 6976696777cSDuson Lin .set_mode = elan_i2c_set_mode, 6986696777cSDuson Lin 6996696777cSDuson Lin .calibrate = elan_i2c_calibrate, 7006696777cSDuson Lin .calibrate_result = elan_i2c_calibrate_result, 7016696777cSDuson Lin 7026696777cSDuson Lin .get_baseline_data = elan_i2c_get_baseline_data, 7036696777cSDuson Lin 7046696777cSDuson Lin .get_version = elan_i2c_get_version, 7056696777cSDuson Lin .get_sm_version = elan_i2c_get_sm_version, 7066696777cSDuson Lin .get_product_id = elan_i2c_get_product_id, 7076696777cSDuson Lin .get_checksum = elan_i2c_get_checksum, 708b9bced0eSduson .get_pressure_adjustment = elan_i2c_get_pressure_adjustment, 7096696777cSDuson Lin 7106696777cSDuson Lin .get_max = elan_i2c_get_max, 7116696777cSDuson Lin .get_resolution = elan_i2c_get_resolution, 7126696777cSDuson Lin .get_num_traces = elan_i2c_get_num_traces, 7136696777cSDuson Lin 7146696777cSDuson Lin .iap_get_mode = elan_i2c_iap_get_mode, 7156696777cSDuson Lin .iap_reset = elan_i2c_iap_reset, 7166696777cSDuson Lin 7176696777cSDuson Lin .prepare_fw_update = elan_i2c_prepare_fw_update, 7186696777cSDuson Lin .write_fw_block = elan_i2c_write_fw_block, 7196696777cSDuson Lin .finish_fw_update = elan_i2c_finish_fw_update, 7206696777cSDuson Lin 721a2eaf299SKT Liao .get_pattern = elan_i2c_get_pattern, 722a2eaf299SKT Liao 7236696777cSDuson Lin .get_report = elan_i2c_get_report, 7246696777cSDuson Lin }; 725