mirror of
https://github.com/edk2-porting/linux-next.git
synced 2024-12-25 05:34:00 +08:00
Input: elan_i2c - add support for multi IC type and iap format
In order to support multiple IC types for i2c/smbus protocol, add get ic type command and use this data when checking firmware page count and signature address. Signed-off-by: Duson Lin <dusonlin@emc.com.tw> Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
This commit is contained in:
parent
85919a00e5
commit
12018ac3d6
@ -33,9 +33,7 @@
|
|||||||
#define ETP_FW_IAP_PAGE_ERR (1 << 5)
|
#define ETP_FW_IAP_PAGE_ERR (1 << 5)
|
||||||
#define ETP_FW_IAP_INTF_ERR (1 << 4)
|
#define ETP_FW_IAP_INTF_ERR (1 << 4)
|
||||||
#define ETP_FW_PAGE_SIZE 64
|
#define ETP_FW_PAGE_SIZE 64
|
||||||
#define ETP_FW_VAILDPAGE_COUNT 768
|
|
||||||
#define ETP_FW_SIGNATURE_SIZE 6
|
#define ETP_FW_SIGNATURE_SIZE 6
|
||||||
#define ETP_FW_SIGNATURE_ADDRESS 0xBFFA
|
|
||||||
|
|
||||||
struct i2c_client;
|
struct i2c_client;
|
||||||
struct completion;
|
struct completion;
|
||||||
@ -58,7 +56,8 @@ struct elan_transport_ops {
|
|||||||
bool max_baseliune, u8 *value);
|
bool max_baseliune, u8 *value);
|
||||||
|
|
||||||
int (*get_version)(struct i2c_client *client, bool iap, u8 *version);
|
int (*get_version)(struct i2c_client *client, bool iap, u8 *version);
|
||||||
int (*get_sm_version)(struct i2c_client *client, u8 *version);
|
int (*get_sm_version)(struct i2c_client *client,
|
||||||
|
u8* ic_type, u8 *version);
|
||||||
int (*get_checksum)(struct i2c_client *client, bool iap, u16 *csum);
|
int (*get_checksum)(struct i2c_client *client, bool iap, u16 *csum);
|
||||||
int (*get_product_id)(struct i2c_client *client, u8 *id);
|
int (*get_product_id)(struct i2c_client *client, u8 *id);
|
||||||
|
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
* Copyright (c) 2013 ELAN Microelectronics Corp.
|
* Copyright (c) 2013 ELAN Microelectronics Corp.
|
||||||
*
|
*
|
||||||
* Author: 林政維 (Duson Lin) <dusonlin@emc.com.tw>
|
* Author: 林政維 (Duson Lin) <dusonlin@emc.com.tw>
|
||||||
* Version: 1.5.7
|
* Version: 1.5.8
|
||||||
*
|
*
|
||||||
* Based on cyapa driver:
|
* Based on cyapa driver:
|
||||||
* copyright (c) 2011-2012 Cypress Semiconductor, Inc.
|
* copyright (c) 2011-2012 Cypress Semiconductor, Inc.
|
||||||
@ -40,7 +40,7 @@
|
|||||||
#include "elan_i2c.h"
|
#include "elan_i2c.h"
|
||||||
|
|
||||||
#define DRIVER_NAME "elan_i2c"
|
#define DRIVER_NAME "elan_i2c"
|
||||||
#define ELAN_DRIVER_VERSION "1.5.7"
|
#define ELAN_DRIVER_VERSION "1.5.8"
|
||||||
#define ETP_MAX_PRESSURE 255
|
#define ETP_MAX_PRESSURE 255
|
||||||
#define ETP_FWIDTH_REDUCE 90
|
#define ETP_FWIDTH_REDUCE 90
|
||||||
#define ETP_FINGER_WIDTH 15
|
#define ETP_FINGER_WIDTH 15
|
||||||
@ -83,6 +83,9 @@ struct elan_tp_data {
|
|||||||
u16 fw_checksum;
|
u16 fw_checksum;
|
||||||
int pressure_adjustment;
|
int pressure_adjustment;
|
||||||
u8 mode;
|
u8 mode;
|
||||||
|
u8 ic_type;
|
||||||
|
u16 fw_vaildpage_count;
|
||||||
|
u16 fw_signature_address;
|
||||||
|
|
||||||
bool irq_wake;
|
bool irq_wake;
|
||||||
|
|
||||||
@ -91,6 +94,29 @@ struct elan_tp_data {
|
|||||||
bool baseline_ready;
|
bool baseline_ready;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static int elan_get_fwinfo(u8 ic_type, u16 *vaildpage_count,
|
||||||
|
u16 *signature_address)
|
||||||
|
{
|
||||||
|
switch(ic_type) {
|
||||||
|
case 0x09:
|
||||||
|
*vaildpage_count = 768;
|
||||||
|
break;
|
||||||
|
case 0x0D:
|
||||||
|
*vaildpage_count = 896;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
/* unknown ic type clear value */
|
||||||
|
*vaildpage_count = 0;
|
||||||
|
*signature_address = 0;
|
||||||
|
return -ENXIO;
|
||||||
|
}
|
||||||
|
|
||||||
|
*signature_address =
|
||||||
|
(*vaildpage_count * ETP_FW_PAGE_SIZE) - ETP_FW_SIGNATURE_SIZE;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int elan_enable_power(struct elan_tp_data *data)
|
static int elan_enable_power(struct elan_tp_data *data)
|
||||||
{
|
{
|
||||||
int repeat = ETP_RETRY_COUNT;
|
int repeat = ETP_RETRY_COUNT;
|
||||||
@ -221,7 +247,8 @@ static int elan_query_device_info(struct elan_tp_data *data)
|
|||||||
if (error)
|
if (error)
|
||||||
return error;
|
return error;
|
||||||
|
|
||||||
error = data->ops->get_sm_version(data->client, &data->sm_version);
|
error = data->ops->get_sm_version(data->client, &data->ic_type,
|
||||||
|
&data->sm_version);
|
||||||
if (error)
|
if (error)
|
||||||
return error;
|
return error;
|
||||||
|
|
||||||
@ -234,6 +261,14 @@ static int elan_query_device_info(struct elan_tp_data *data)
|
|||||||
if (error)
|
if (error)
|
||||||
return error;
|
return error;
|
||||||
|
|
||||||
|
error = elan_get_fwinfo(data->ic_type, &data->fw_vaildpage_count,
|
||||||
|
&data->fw_signature_address);
|
||||||
|
if (error) {
|
||||||
|
dev_err(&data->client->dev,
|
||||||
|
"unknown ic type %d\n", data->ic_type);
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -318,7 +353,7 @@ static int __elan_update_firmware(struct elan_tp_data *data,
|
|||||||
iap_start_addr = get_unaligned_le16(&fw->data[ETP_IAP_START_ADDR * 2]);
|
iap_start_addr = get_unaligned_le16(&fw->data[ETP_IAP_START_ADDR * 2]);
|
||||||
|
|
||||||
boot_page_count = (iap_start_addr * 2) / ETP_FW_PAGE_SIZE;
|
boot_page_count = (iap_start_addr * 2) / ETP_FW_PAGE_SIZE;
|
||||||
for (i = boot_page_count; i < ETP_FW_VAILDPAGE_COUNT; i++) {
|
for (i = boot_page_count; i < data->fw_vaildpage_count; i++) {
|
||||||
u16 checksum = 0;
|
u16 checksum = 0;
|
||||||
const u8 *page = &fw->data[i * ETP_FW_PAGE_SIZE];
|
const u8 *page = &fw->data[i * ETP_FW_PAGE_SIZE];
|
||||||
|
|
||||||
@ -454,7 +489,7 @@ static ssize_t elan_sysfs_update_fw(struct device *dev,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Firmware file must match signature data */
|
/* Firmware file must match signature data */
|
||||||
fw_signature = &fw->data[ETP_FW_SIGNATURE_ADDRESS];
|
fw_signature = &fw->data[data->fw_signature_address];
|
||||||
if (memcmp(fw_signature, signature, sizeof(signature)) != 0) {
|
if (memcmp(fw_signature, signature, sizeof(signature)) != 0) {
|
||||||
dev_err(dev, "signature mismatch (expected %*ph, got %*ph)\n",
|
dev_err(dev, "signature mismatch (expected %*ph, got %*ph)\n",
|
||||||
(int)sizeof(signature), signature,
|
(int)sizeof(signature), signature,
|
||||||
|
@ -259,7 +259,8 @@ static int elan_i2c_get_version(struct i2c_client *client,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int elan_i2c_get_sm_version(struct i2c_client *client, u8 *version)
|
static int elan_i2c_get_sm_version(struct i2c_client *client,
|
||||||
|
u8 *ic_type, u8 *version)
|
||||||
{
|
{
|
||||||
int error;
|
int error;
|
||||||
u8 val[3];
|
u8 val[3];
|
||||||
@ -271,6 +272,7 @@ static int elan_i2c_get_sm_version(struct i2c_client *client, u8 *version)
|
|||||||
}
|
}
|
||||||
|
|
||||||
*version = val[0];
|
*version = val[0];
|
||||||
|
*ic_type = val[1];
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -165,7 +165,8 @@ static int elan_smbus_get_version(struct i2c_client *client,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int elan_smbus_get_sm_version(struct i2c_client *client, u8 *version)
|
static int elan_smbus_get_sm_version(struct i2c_client *client,
|
||||||
|
u8 *ic_type, u8 *version)
|
||||||
{
|
{
|
||||||
int error;
|
int error;
|
||||||
u8 val[3];
|
u8 val[3];
|
||||||
@ -177,7 +178,8 @@ static int elan_smbus_get_sm_version(struct i2c_client *client, u8 *version)
|
|||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
*version = val[0]; /* XXX Why 0 and not 2 as in IAP/FW versions? */
|
*version = val[0];
|
||||||
|
*ic_type = val[1];
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user