Commit d5e6e0fa authored by Dmitry Torokhov's avatar Dmitry Torokhov

Merge branch 'synaptics-rmi4' into next

Bring in latest RMI4 support in preparation to the merge window.
parents 57b8443d f32361b7
...@@ -9,9 +9,11 @@ config RMI4_CORE ...@@ -9,9 +9,11 @@ config RMI4_CORE
If unsure, say Y. If unsure, say Y.
if RMI4_CORE
config RMI4_I2C config RMI4_I2C
tristate "RMI4 I2C Support" tristate "RMI4 I2C Support"
depends on RMI4_CORE && I2C depends on I2C
help help
Say Y here if you want to support RMI4 devices connected to an I2C Say Y here if you want to support RMI4 devices connected to an I2C
bus. bus.
...@@ -20,7 +22,7 @@ config RMI4_I2C ...@@ -20,7 +22,7 @@ config RMI4_I2C
config RMI4_SPI config RMI4_SPI
tristate "RMI4 SPI Support" tristate "RMI4 SPI Support"
depends on RMI4_CORE && SPI depends on SPI
help help
Say Y here if you want to support RMI4 devices connected to a SPI Say Y here if you want to support RMI4 devices connected to a SPI
bus. bus.
...@@ -29,7 +31,7 @@ config RMI4_SPI ...@@ -29,7 +31,7 @@ config RMI4_SPI
config RMI4_SMB config RMI4_SMB
tristate "RMI4 SMB Support" tristate "RMI4 SMB Support"
depends on RMI4_CORE && I2C depends on I2C
help help
Say Y here if you want to support RMI4 devices connected to an SMB Say Y here if you want to support RMI4 devices connected to an SMB
bus. bus.
...@@ -40,23 +42,20 @@ config RMI4_SMB ...@@ -40,23 +42,20 @@ config RMI4_SMB
called rmi_smbus. called rmi_smbus.
config RMI4_F03 config RMI4_F03
bool "RMI4 Function 03 (PS2 Guest)" bool "RMI4 Function 03 (PS2 Guest)"
depends on RMI4_CORE
depends on SERIO=y || RMI4_CORE=SERIO depends on SERIO=y || RMI4_CORE=SERIO
help help
Say Y here if you want to add support for RMI4 function 03. Say Y here if you want to add support for RMI4 function 03.
Function 03 provides PS2 guest support for RMI4 devices. This Function 03 provides PS2 guest support for RMI4 devices. This
includes support for TrackPoints on TouchPads. includes support for TrackPoints on TouchPads.
config RMI4_2D_SENSOR config RMI4_2D_SENSOR
bool bool
depends on RMI4_CORE
config RMI4_F11 config RMI4_F11
bool "RMI4 Function 11 (2D pointing)" bool "RMI4 Function 11 (2D pointing)"
select RMI4_2D_SENSOR select RMI4_2D_SENSOR
depends on RMI4_CORE
help help
Say Y here if you want to add support for RMI4 function 11. Say Y here if you want to add support for RMI4 function 11.
...@@ -67,7 +66,6 @@ config RMI4_F11 ...@@ -67,7 +66,6 @@ config RMI4_F11
config RMI4_F12 config RMI4_F12
bool "RMI4 Function 12 (2D pointing)" bool "RMI4 Function 12 (2D pointing)"
select RMI4_2D_SENSOR select RMI4_2D_SENSOR
depends on RMI4_CORE
help help
Say Y here if you want to add support for RMI4 function 12. Say Y here if you want to add support for RMI4 function 12.
...@@ -77,7 +75,6 @@ config RMI4_F12 ...@@ -77,7 +75,6 @@ config RMI4_F12
config RMI4_F30 config RMI4_F30
bool "RMI4 Function 30 (GPIO LED)" bool "RMI4 Function 30 (GPIO LED)"
depends on RMI4_CORE
help help
Say Y here if you want to add support for RMI4 function 30. Say Y here if you want to add support for RMI4 function 30.
...@@ -86,7 +83,6 @@ config RMI4_F30 ...@@ -86,7 +83,6 @@ config RMI4_F30
config RMI4_F34 config RMI4_F34
bool "RMI4 Function 34 (Device reflash)" bool "RMI4 Function 34 (Device reflash)"
depends on RMI4_CORE
select FW_LOADER select FW_LOADER
help help
Say Y here if you want to add support for RMI4 function 34. Say Y here if you want to add support for RMI4 function 34.
...@@ -97,7 +93,6 @@ config RMI4_F34 ...@@ -97,7 +93,6 @@ config RMI4_F34
config RMI4_F54 config RMI4_F54
bool "RMI4 Function 54 (Analog diagnostics)" bool "RMI4 Function 54 (Analog diagnostics)"
depends on RMI4_CORE
depends on VIDEO_V4L2=y || (RMI4_CORE=m && VIDEO_V4L2=m) depends on VIDEO_V4L2=y || (RMI4_CORE=m && VIDEO_V4L2=m)
select VIDEOBUF2_VMALLOC select VIDEOBUF2_VMALLOC
select RMI4_F55 select RMI4_F55
...@@ -109,9 +104,10 @@ config RMI4_F54 ...@@ -109,9 +104,10 @@ config RMI4_F54
config RMI4_F55 config RMI4_F55
bool "RMI4 Function 55 (Sensor tuning)" bool "RMI4 Function 55 (Sensor tuning)"
depends on RMI4_CORE
help help
Say Y here if you want to add support for RMI4 function 55 Say Y here if you want to add support for RMI4 function 55
Function 55 provides access to the RMI4 touch sensor tuning Function 55 provides access to the RMI4 touch sensor tuning
mechanism. mechanism.
endif # RMI_CORE
...@@ -144,8 +144,13 @@ static void rmi_2d_sensor_set_input_params(struct rmi_2d_sensor *sensor) ...@@ -144,8 +144,13 @@ static void rmi_2d_sensor_set_input_params(struct rmi_2d_sensor *sensor)
int input_flags = 0; int input_flags = 0;
if (sensor->report_abs) { if (sensor->report_abs) {
if (sensor->axis_align.swap_axes) if (sensor->axis_align.swap_axes) {
swap(sensor->max_x, sensor->max_y); swap(sensor->max_x, sensor->max_y);
swap(sensor->axis_align.clip_x_low,
sensor->axis_align.clip_y_low);
swap(sensor->axis_align.clip_x_high,
sensor->axis_align.clip_y_high);
}
sensor->min_x = sensor->axis_align.clip_x_low; sensor->min_x = sensor->axis_align.clip_x_low;
if (sensor->axis_align.clip_x_high) if (sensor->axis_align.clip_x_high)
......
...@@ -261,10 +261,10 @@ int __rmi_register_function_handler(struct rmi_function_handler *handler, ...@@ -261,10 +261,10 @@ int __rmi_register_function_handler(struct rmi_function_handler *handler,
driver->probe = rmi_function_probe; driver->probe = rmi_function_probe;
driver->remove = rmi_function_remove; driver->remove = rmi_function_remove;
error = driver_register(&handler->driver); error = driver_register(driver);
if (error) { if (error) {
pr_err("driver_register() failed for %s, error: %d\n", pr_err("driver_register() failed for %s, error: %d\n",
handler->driver.name, error); driver->name, error);
return error; return error;
} }
......
...@@ -265,6 +265,19 @@ static int rmi_irq_init(struct rmi_device *rmi_dev) ...@@ -265,6 +265,19 @@ static int rmi_irq_init(struct rmi_device *rmi_dev)
return 0; return 0;
} }
struct rmi_function *rmi_find_function(struct rmi_device *rmi_dev, u8 number)
{
struct rmi_driver_data *data = dev_get_drvdata(&rmi_dev->dev);
struct rmi_function *entry;
list_for_each_entry(entry, &data->function_list, node) {
if (entry->fd.function_number == number)
return entry;
}
return NULL;
}
static int suspend_one_function(struct rmi_function *fn) static int suspend_one_function(struct rmi_function *fn)
{ {
struct rmi_function_handler *fh; struct rmi_function_handler *fh;
...@@ -364,7 +377,7 @@ static void rmi_driver_set_input_name(struct rmi_device *rmi_dev, ...@@ -364,7 +377,7 @@ static void rmi_driver_set_input_name(struct rmi_device *rmi_dev,
struct input_dev *input) struct input_dev *input)
{ {
struct rmi_driver_data *data = dev_get_drvdata(&rmi_dev->dev); struct rmi_driver_data *data = dev_get_drvdata(&rmi_dev->dev);
char *device_name = rmi_f01_get_product_ID(data->f01_container); const char *device_name = rmi_f01_get_product_ID(data->f01_container);
char *name; char *name;
name = devm_kasprintf(&rmi_dev->dev, GFP_KERNEL, name = devm_kasprintf(&rmi_dev->dev, GFP_KERNEL,
...@@ -836,7 +849,7 @@ static int rmi_create_function(struct rmi_device *rmi_dev, ...@@ -836,7 +849,7 @@ static int rmi_create_function(struct rmi_device *rmi_dev,
void *ctx, const struct pdt_entry *pdt) void *ctx, const struct pdt_entry *pdt)
{ {
struct device *dev = &rmi_dev->dev; struct device *dev = &rmi_dev->dev;
struct rmi_driver_data *data = dev_get_drvdata(&rmi_dev->dev); struct rmi_driver_data *data = dev_get_drvdata(dev);
int *current_irq_count = ctx; int *current_irq_count = ctx;
struct rmi_function *fn; struct rmi_function *fn;
int i; int i;
...@@ -1040,7 +1053,7 @@ int rmi_probe_interrupts(struct rmi_driver_data *data) ...@@ -1040,7 +1053,7 @@ int rmi_probe_interrupts(struct rmi_driver_data *data)
} }
if (data->bootloader_mode) if (data->bootloader_mode)
dev_warn(&rmi_dev->dev, "Device in bootloader mode.\n"); dev_warn(dev, "Device in bootloader mode.\n");
data->irq_count = irq_count; data->irq_count = irq_count;
data->num_of_irq_regs = (data->irq_count + 7) / 8; data->num_of_irq_regs = (data->irq_count + 7) / 8;
......
...@@ -93,6 +93,7 @@ bool rmi_is_physical_driver(struct device_driver *); ...@@ -93,6 +93,7 @@ bool rmi_is_physical_driver(struct device_driver *);
int rmi_register_physical_driver(void); int rmi_register_physical_driver(void);
void rmi_unregister_physical_driver(void); void rmi_unregister_physical_driver(void);
void rmi_free_function_list(struct rmi_device *rmi_dev); void rmi_free_function_list(struct rmi_device *rmi_dev);
struct rmi_function *rmi_find_function(struct rmi_device *rmi_dev, u8 number);
int rmi_enable_sensor(struct rmi_device *rmi_dev); int rmi_enable_sensor(struct rmi_device *rmi_dev);
int rmi_scan_pdt(struct rmi_device *rmi_dev, void *ctx, int rmi_scan_pdt(struct rmi_device *rmi_dev, void *ctx,
int (*callback)(struct rmi_device *rmi_dev, void *ctx, int (*callback)(struct rmi_device *rmi_dev, void *ctx,
...@@ -104,7 +105,7 @@ int rmi_init_functions(struct rmi_driver_data *data); ...@@ -104,7 +105,7 @@ int rmi_init_functions(struct rmi_driver_data *data);
int rmi_initial_reset(struct rmi_device *rmi_dev, void *ctx, int rmi_initial_reset(struct rmi_device *rmi_dev, void *ctx,
const struct pdt_entry *pdt); const struct pdt_entry *pdt);
char *rmi_f01_get_product_ID(struct rmi_function *fn); const char *rmi_f01_get_product_ID(struct rmi_function *fn);
#ifdef CONFIG_RMI4_F34 #ifdef CONFIG_RMI4_F34
int rmi_f34_create_sysfs(struct rmi_device *rmi_dev); int rmi_f34_create_sysfs(struct rmi_device *rmi_dev);
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/uaccess.h> #include <linux/uaccess.h>
#include <linux/of.h> #include <linux/of.h>
#include <asm/unaligned.h>
#include "rmi_driver.h" #include "rmi_driver.h"
#define RMI_PRODUCT_ID_LENGTH 10 #define RMI_PRODUCT_ID_LENGTH 10
...@@ -54,6 +55,7 @@ struct f01_basic_properties { ...@@ -54,6 +55,7 @@ struct f01_basic_properties {
u8 product_id[RMI_PRODUCT_ID_LENGTH + 1]; u8 product_id[RMI_PRODUCT_ID_LENGTH + 1];
u16 productinfo; u16 productinfo;
u32 firmware_id; u32 firmware_id;
u32 package_id;
}; };
/* F01 device status bits */ /* F01 device status bits */
...@@ -220,8 +222,19 @@ static int rmi_f01_read_properties(struct rmi_device *rmi_dev, ...@@ -220,8 +222,19 @@ static int rmi_f01_read_properties(struct rmi_device *rmi_dev,
has_build_id_query = !!(queries[0] & BIT(1)); has_build_id_query = !!(queries[0] & BIT(1));
} }
if (has_package_id_query) if (has_package_id_query) {
ret = rmi_read_block(rmi_dev, prod_info_addr,
queries, sizeof(__le64));
if (ret) {
dev_err(&rmi_dev->dev,
"Failed to read package info: %d\n",
ret);
return ret;
}
props->package_id = get_unaligned_le64(queries);
prod_info_addr++; prod_info_addr++;
}
if (has_build_id_query) { if (has_build_id_query) {
ret = rmi_read_block(rmi_dev, prod_info_addr, queries, ret = rmi_read_block(rmi_dev, prod_info_addr, queries,
...@@ -241,13 +254,90 @@ static int rmi_f01_read_properties(struct rmi_device *rmi_dev, ...@@ -241,13 +254,90 @@ static int rmi_f01_read_properties(struct rmi_device *rmi_dev,
return 0; return 0;
} }
char *rmi_f01_get_product_ID(struct rmi_function *fn) const char *rmi_f01_get_product_ID(struct rmi_function *fn)
{ {
struct f01_data *f01 = dev_get_drvdata(&fn->dev); struct f01_data *f01 = dev_get_drvdata(&fn->dev);
return f01->properties.product_id; return f01->properties.product_id;
} }
static ssize_t rmi_driver_manufacturer_id_show(struct device *dev,
struct device_attribute *dattr,
char *buf)
{
struct rmi_driver_data *data = dev_get_drvdata(dev);
struct f01_data *f01 = dev_get_drvdata(&data->f01_container->dev);
return scnprintf(buf, PAGE_SIZE, "%d\n",
f01->properties.manufacturer_id);
}
static DEVICE_ATTR(manufacturer_id, 0444,
rmi_driver_manufacturer_id_show, NULL);
static ssize_t rmi_driver_dom_show(struct device *dev,
struct device_attribute *dattr, char *buf)
{
struct rmi_driver_data *data = dev_get_drvdata(dev);
struct f01_data *f01 = dev_get_drvdata(&data->f01_container->dev);
return scnprintf(buf, PAGE_SIZE, "%s\n", f01->properties.dom);
}
static DEVICE_ATTR(date_of_manufacture, 0444, rmi_driver_dom_show, NULL);
static ssize_t rmi_driver_product_id_show(struct device *dev,
struct device_attribute *dattr,
char *buf)
{
struct rmi_driver_data *data = dev_get_drvdata(dev);
struct f01_data *f01 = dev_get_drvdata(&data->f01_container->dev);
return scnprintf(buf, PAGE_SIZE, "%s\n", f01->properties.product_id);
}
static DEVICE_ATTR(product_id, 0444, rmi_driver_product_id_show, NULL);
static ssize_t rmi_driver_firmware_id_show(struct device *dev,
struct device_attribute *dattr,
char *buf)
{
struct rmi_driver_data *data = dev_get_drvdata(dev);
struct f01_data *f01 = dev_get_drvdata(&data->f01_container->dev);
return scnprintf(buf, PAGE_SIZE, "%d\n", f01->properties.firmware_id);
}
static DEVICE_ATTR(firmware_id, 0444, rmi_driver_firmware_id_show, NULL);
static ssize_t rmi_driver_package_id_show(struct device *dev,
struct device_attribute *dattr,
char *buf)
{
struct rmi_driver_data *data = dev_get_drvdata(dev);
struct f01_data *f01 = dev_get_drvdata(&data->f01_container->dev);
u32 package_id = f01->properties.package_id;
return scnprintf(buf, PAGE_SIZE, "%04x.%04x\n",
package_id & 0xffff, (package_id >> 16) & 0xffff);
}
static DEVICE_ATTR(package_id, 0444, rmi_driver_package_id_show, NULL);
static struct attribute *rmi_f01_attrs[] = {
&dev_attr_manufacturer_id.attr,
&dev_attr_date_of_manufacture.attr,
&dev_attr_product_id.attr,
&dev_attr_firmware_id.attr,
&dev_attr_package_id.attr,
NULL
};
static struct attribute_group rmi_f01_attr_group = {
.attrs = rmi_f01_attrs,
};
#ifdef CONFIG_OF #ifdef CONFIG_OF
static int rmi_f01_of_probe(struct device *dev, static int rmi_f01_of_probe(struct device *dev,
struct rmi_device_platform_data *pdata) struct rmi_device_platform_data *pdata)
...@@ -480,9 +570,18 @@ static int rmi_f01_probe(struct rmi_function *fn) ...@@ -480,9 +570,18 @@ static int rmi_f01_probe(struct rmi_function *fn)
dev_set_drvdata(&fn->dev, f01); dev_set_drvdata(&fn->dev, f01);
error = sysfs_create_group(&fn->rmi_dev->dev.kobj, &rmi_f01_attr_group);
if (error)
dev_warn(&fn->dev, "Failed to create sysfs group: %d\n", error);
return 0; return 0;
} }
static void rmi_f01_remove(struct rmi_function *fn)
{
sysfs_remove_group(&fn->rmi_dev->dev.kobj, &rmi_f01_attr_group);
}
static int rmi_f01_config(struct rmi_function *fn) static int rmi_f01_config(struct rmi_function *fn)
{ {
struct f01_data *f01 = dev_get_drvdata(&fn->dev); struct f01_data *f01 = dev_get_drvdata(&fn->dev);
...@@ -622,6 +721,7 @@ struct rmi_function_handler rmi_f01_handler = { ...@@ -622,6 +721,7 @@ struct rmi_function_handler rmi_f01_handler = {
}, },
.func = 0x01, .func = 0x01,
.probe = rmi_f01_probe, .probe = rmi_f01_probe,
.remove = rmi_f01_remove,
.config = rmi_f01_config, .config = rmi_f01_config,
.attention = rmi_f01_attention, .attention = rmi_f01_attention,
.suspend = rmi_f01_suspend, .suspend = rmi_f01_suspend,
......
...@@ -175,9 +175,6 @@ static int rmi_f03_attention(struct rmi_function *fn, unsigned long *irq_bits) ...@@ -175,9 +175,6 @@ static int rmi_f03_attention(struct rmi_function *fn, unsigned long *irq_bits)
int i; int i;
int error; int error;
if (!rmi_dev)
return -ENODEV;
if (drvdata->attn_data.data) { if (drvdata->attn_data.data) {
/* First grab the data passed by the transport device */ /* First grab the data passed by the transport device */
if (drvdata->attn_data.size < ob_len) { if (drvdata->attn_data.size < ob_len) {
......
...@@ -157,6 +157,9 @@ static int rmi_f34_write_blocks(struct f34_data *f34, const void *data, ...@@ -157,6 +157,9 @@ static int rmi_f34_write_blocks(struct f34_data *f34, const void *data,
i + 1, block_count); i + 1, block_count);
data += f34->v5.block_size; data += f34->v5.block_size;
f34->update_progress += f34->v5.block_size;
f34->update_status = (f34->update_progress * 100) /
f34->update_size;
} }
return 0; return 0;
...@@ -174,7 +177,7 @@ static int rmi_f34_write_config(struct f34_data *f34, const void *data) ...@@ -174,7 +177,7 @@ static int rmi_f34_write_config(struct f34_data *f34, const void *data)
F34_WRITE_CONFIG_BLOCK); F34_WRITE_CONFIG_BLOCK);
} }
int rmi_f34_enable_flash(struct f34_data *f34) static int rmi_f34_enable_flash(struct f34_data *f34)
{ {
return rmi_f34_command(f34, F34_ENABLE_FLASH_PROG, return rmi_f34_command(f34, F34_ENABLE_FLASH_PROG,
F34_ENABLE_WAIT_MS, true); F34_ENABLE_WAIT_MS, true);
...@@ -184,9 +187,14 @@ static int rmi_f34_flash_firmware(struct f34_data *f34, ...@@ -184,9 +187,14 @@ static int rmi_f34_flash_firmware(struct f34_data *f34,
const struct rmi_f34_firmware *syn_fw) const struct rmi_f34_firmware *syn_fw)
{ {
struct rmi_function *fn = f34->fn; struct rmi_function *fn = f34->fn;
u32 image_size = le32_to_cpu(syn_fw->image_size);
u32 config_size = le32_to_cpu(syn_fw->config_size);
int ret; int ret;
if (syn_fw->image_size) { f34->update_progress = 0;
f34->update_size = image_size + config_size;
if (image_size) {
dev_info(&fn->dev, "Erasing firmware...\n"); dev_info(&fn->dev, "Erasing firmware...\n");
ret = rmi_f34_command(f34, F34_ERASE_ALL, ret = rmi_f34_command(f34, F34_ERASE_ALL,
F34_ERASE_WAIT_MS, true); F34_ERASE_WAIT_MS, true);
...@@ -194,18 +202,18 @@ static int rmi_f34_flash_firmware(struct f34_data *f34, ...@@ -194,18 +202,18 @@ static int rmi_f34_flash_firmware(struct f34_data *f34,
return ret; return ret;
dev_info(&fn->dev, "Writing firmware (%d bytes)...\n", dev_info(&fn->dev, "Writing firmware (%d bytes)...\n",
syn_fw->image_size); image_size);
ret = rmi_f34_write_firmware(f34, syn_fw->data); ret = rmi_f34_write_firmware(f34, syn_fw->data);
if (ret) if (ret)
return ret; return ret;
} }
if (syn_fw->config_size) { if (config_size) {
/* /*
* We only need to erase config if we haven't updated * We only need to erase config if we haven't updated
* firmware. * firmware.
*/ */
if (!syn_fw->image_size) { if (!image_size) {
dev_info(&fn->dev, "Erasing config...\n"); dev_info(&fn->dev, "Erasing config...\n");
ret = rmi_f34_command(f34, F34_ERASE_CONFIG, ret = rmi_f34_command(f34, F34_ERASE_CONFIG,
F34_ERASE_WAIT_MS, true); F34_ERASE_WAIT_MS, true);
...@@ -214,9 +222,8 @@ static int rmi_f34_flash_firmware(struct f34_data *f34, ...@@ -214,9 +222,8 @@ static int rmi_f34_flash_firmware(struct f34_data *f34,
} }
dev_info(&fn->dev, "Writing config (%d bytes)...\n", dev_info(&fn->dev, "Writing config (%d bytes)...\n",
syn_fw->config_size); config_size);
ret = rmi_f34_write_config(f34, ret = rmi_f34_write_config(f34, &syn_fw->data[image_size]);
&syn_fw->data[syn_fw->image_size]);
if (ret) if (ret)
return ret; return ret;
} }
...@@ -224,21 +231,23 @@ static int rmi_f34_flash_firmware(struct f34_data *f34, ...@@ -224,21 +231,23 @@ static int rmi_f34_flash_firmware(struct f34_data *f34,
return 0; return 0;
} }
int rmi_f34_update_firmware(struct f34_data *f34, const struct firmware *fw) static int rmi_f34_update_firmware(struct f34_data *f34,
const struct firmware *fw)
{ {
const struct rmi_f34_firmware *syn_fw; const struct rmi_f34_firmware *syn_fw =
(const struct rmi_f34_firmware *)fw->data;
u32 image_size = le32_to_cpu(syn_fw->image_size);
u32 config_size = le32_to_cpu(syn_fw->config_size);
int ret; int ret;
syn_fw = (const struct rmi_f34_firmware *)fw->data;
BUILD_BUG_ON(offsetof(struct rmi_f34_firmware, data) != BUILD_BUG_ON(offsetof(struct rmi_f34_firmware, data) !=
F34_FW_IMAGE_OFFSET); F34_FW_IMAGE_OFFSET);
rmi_dbg(RMI_DEBUG_FN, &f34->fn->dev, rmi_dbg(RMI_DEBUG_FN, &f34->fn->dev,
"FW size:%d, checksum:%08x, image_size:%d, config_size:%d\n", "FW size:%zd, checksum:%08x, image_size:%d, config_size:%d\n",
(int)fw->size, fw->size,
le32_to_cpu(syn_fw->checksum), le32_to_cpu(syn_fw->checksum),
le32_to_cpu(syn_fw->image_size), image_size, config_size);
le32_to_cpu(syn_fw->config_size));
rmi_dbg(RMI_DEBUG_FN, &f34->fn->dev, rmi_dbg(RMI_DEBUG_FN, &f34->fn->dev,
"FW bootloader_id:%02x, product_id:%.*s, info: %02x%02x\n", "FW bootloader_id:%02x, product_id:%.*s, info: %02x%02x\n",
...@@ -246,27 +255,25 @@ int rmi_f34_update_firmware(struct f34_data *f34, const struct firmware *fw) ...@@ -246,27 +255,25 @@ int rmi_f34_update_firmware(struct f34_data *f34, const struct firmware *fw)
(int)sizeof(syn_fw->product_id), syn_fw->product_id, (int)sizeof(syn_fw->product_id), syn_fw->product_id,
syn_fw->product_info[0], syn_fw->product_info[1]); syn_fw->product_info[0], syn_fw->product_info[1]);
if (syn_fw->image_size && if (image_size && image_size != f34->v5.fw_blocks * f34->v5.block_size) {
syn_fw->image_size != f34->v5.fw_blocks * f34->v5.block_size) {
dev_err(&f34->fn->dev, dev_err(&f34->fn->dev,
"Bad firmware image: fw size %d, expected %d\n", "Bad firmware image: fw size %d, expected %d\n",
syn_fw->image_size, image_size, f34->v5.fw_blocks * f34->v5.block_size);
f34->v5.fw_blocks * f34->v5.block_size);
ret = -EILSEQ; ret = -EILSEQ;
goto out; goto out;
} }
if (syn_fw->config_size && if (config_size &&
syn_fw->config_size != f34->v5.config_blocks * f34->v5.block_size) { config_size != f34->v5.config_blocks * f34->v5.block_size) {
dev_err(&f34->fn->dev, dev_err(&f34->fn->dev,
"Bad firmware image: config size %d, expected %d\n", "Bad firmware image: config size %d, expected %d\n",
syn_fw->config_size, config_size,
f34->v5.config_blocks * f34->v5.block_size); f34->v5.config_blocks * f34->v5.block_size);
ret = -EILSEQ; ret = -EILSEQ;
goto out; goto out;
} }
if (syn_fw->image_size && !syn_fw->config_size) { if (image_size && !config_size) {
dev_err(&f34->fn->dev, "Bad firmware image: no config data\n"); dev_err(&f34->fn->dev, "Bad firmware image: no config data\n");
ret = -EILSEQ; ret = -EILSEQ;
goto out; goto out;
...@@ -283,6 +290,63 @@ int rmi_f34_update_firmware(struct f34_data *f34, const struct firmware *fw) ...@@ -283,6 +290,63 @@ int rmi_f34_update_firmware(struct f34_data *f34, const struct firmware *fw)
return ret; return ret;
} }
static int rmi_f34_status(struct rmi_function *fn)
{
struct f34_data *f34 = dev_get_drvdata(&fn->dev);
/*
* The status is the percentage complete, or once complete,
* zero for success or a negative return code.
*/
return f34->update_status;
}
static ssize_t rmi_driver_bootloader_id_show(struct device *dev,
struct device_attribute *dattr,
char *buf)
{
struct rmi_driver_data *data = dev_get_drvdata(dev);
struct rmi_function *fn = data->f34_container;
struct f34_data *f34;
if (fn) {
f34 = dev_get_drvdata(&fn->dev);
if (f34->bl_version == 5)
return scnprintf(buf, PAGE_SIZE, "%c%c\n",
f34->bootloader_id[0],
f34->bootloader_id[1]);
else
return scnprintf(buf, PAGE_SIZE, "V%d.%d\n",
f34->bootloader_id[1],
f34->bootloader_id[0]);
}
return 0;
}
static DEVICE_ATTR(bootloader_id, 0444, rmi_driver_bootloader_id_show, NULL);
static ssize_t rmi_driver_configuration_id_show(struct device *dev,
struct device_attribute *dattr,
char *buf)
{
struct rmi_driver_data *data = dev_get_drvdata(dev);
struct rmi_function *fn = data->f34_container;
struct f34_data *f34;
if (fn) {
f34 = dev_get_drvdata(&fn->dev);
return scnprintf(buf, PAGE_SIZE, "%s\n", f34->configuration_id);
}
return 0;
}
static DEVICE_ATTR(configuration_id, 0444,
rmi_driver_configuration_id_show, NULL);
static int rmi_firmware_update(struct rmi_driver_data *data, static int rmi_firmware_update(struct rmi_driver_data *data,
const struct firmware *fw) const struct firmware *fw)
{ {
...@@ -346,7 +410,13 @@ static int rmi_firmware_update(struct rmi_driver_data *data, ...@@ -346,7 +410,13 @@ static int rmi_firmware_update(struct rmi_driver_data *data,
else else
ret = rmi_f34_update_firmware(f34, fw); ret = rmi_f34_update_firmware(f34, fw);
dev_info(&f34->fn->dev, "Firmware update complete, status:%d\n", ret); if (ret) {
f34->update_status = ret;
dev_err(&f34->fn->dev,
"Firmware update failed, status: %d\n", ret);
} else {
dev_info(&f34->fn->dev, "Firmware update complete\n");
}
rmi_disable_irq(rmi_dev, false); rmi_disable_irq(rmi_dev, false);
...@@ -377,9 +447,6 @@ static int rmi_firmware_update(struct rmi_driver_data *data, ...@@ -377,9 +447,6 @@ static int rmi_firmware_update(struct rmi_driver_data *data,
return ret; return ret;
} }
static int rmi_firmware_update(struct rmi_driver_data *data,
const struct firmware *fw);
static ssize_t rmi_driver_update_fw_store(struct device *dev, static ssize_t rmi_driver_update_fw_store(struct device *dev,
struct device_attribute *dattr, struct device_attribute *dattr,
const char *buf, size_t count) const char *buf, size_t count)
...@@ -414,8 +481,27 @@ static ssize_t rmi_driver_update_fw_store(struct device *dev, ...@@ -414,8 +481,27 @@ static ssize_t rmi_driver_update_fw_store(struct device *dev,
static DEVICE_ATTR(update_fw, 0200, NULL, rmi_driver_update_fw_store); static DEVICE_ATTR(update_fw, 0200, NULL, rmi_driver_update_fw_store);
static ssize_t rmi_driver_update_fw_status_show(struct device *dev,
struct device_attribute *dattr,
char *buf)
{
struct rmi_driver_data *data = dev_get_drvdata(dev);
int update_status = 0;
if (data->f34_container)
update_status = rmi_f34_status(data->f34_container);
return scnprintf(buf, PAGE_SIZE, "%d\n", update_status);
}
static DEVICE_ATTR(update_fw_status, 0444,
rmi_driver_update_fw_status_show, NULL);
static struct attribute *rmi_firmware_attrs[] = { static struct attribute *rmi_firmware_attrs[] = {
&dev_attr_bootloader_id.attr,
&dev_attr_configuration_id.attr,
&dev_attr_update_fw.attr, &dev_attr_update_fw.attr,
&dev_attr_update_fw_status.attr,
NULL NULL
}; };
...@@ -441,8 +527,6 @@ static int rmi_f34_probe(struct rmi_function *fn) ...@@ -441,8 +527,6 @@ static int rmi_f34_probe(struct rmi_function *fn)
/* v5 code only supported version 0, try V7 probe */ /* v5 code only supported version 0, try V7 probe */
if (version > 0) if (version > 0)
return rmi_f34v7_probe(f34); return rmi_f34v7_probe(f34);
else if (version != 0)
return -ENODEV;
f34->bl_version = 5; f34->bl_version = 5;
......
...@@ -301,6 +301,10 @@ struct f34_data { ...@@ -301,6 +301,10 @@ struct f34_data {
unsigned char bootloader_id[5]; unsigned char bootloader_id[5];
unsigned char configuration_id[CONFIG_ID_SIZE*2 + 1]; unsigned char configuration_id[CONFIG_ID_SIZE*2 + 1];
int update_status;
int update_progress;
int update_size;
union { union {
struct f34v5_data v5; struct f34v5_data v5;
struct f34v7_data v7; struct f34v7_data v7;
......
...@@ -588,6 +588,7 @@ static int rmi_f34v7_check_ui_firmware_size(struct f34_data *f34) ...@@ -588,6 +588,7 @@ static int rmi_f34v7_check_ui_firmware_size(struct f34_data *f34)
u16 block_count; u16 block_count;
block_count = f34->v7.img.ui_firmware.size / f34->v7.block_size; block_count = f34->v7.img.ui_firmware.size / f34->v7.block_size;
f34->update_size += block_count;
if (block_count != f34->v7.blkcount.ui_firmware) { if (block_count != f34->v7.blkcount.ui_firmware) {
dev_err(&f34->fn->dev, dev_err(&f34->fn->dev,
...@@ -604,6 +605,7 @@ static int rmi_f34v7_check_ui_config_size(struct f34_data *f34) ...@@ -604,6 +605,7 @@ static int rmi_f34v7_check_ui_config_size(struct f34_data *f34)
u16 block_count; u16 block_count;
block_count = f34->v7.img.ui_config.size / f34->v7.block_size; block_count = f34->v7.img.ui_config.size / f34->v7.block_size;
f34->update_size += block_count;
if (block_count != f34->v7.blkcount.ui_config) { if (block_count != f34->v7.blkcount.ui_config) {
dev_err(&f34->fn->dev, "UI config size mismatch\n"); dev_err(&f34->fn->dev, "UI config size mismatch\n");
...@@ -618,6 +620,7 @@ static int rmi_f34v7_check_dp_config_size(struct f34_data *f34) ...@@ -618,6 +620,7 @@ static int rmi_f34v7_check_dp_config_size(struct f34_data *f34)
u16 block_count; u16 block_count;
block_count = f34->v7.img.dp_config.size / f34->v7.block_size; block_count = f34->v7.img.dp_config.size / f34->v7.block_size;
f34->update_size += block_count;
if (block_count != f34->v7.blkcount.dp_config) { if (block_count != f34->v7.blkcount.dp_config) {
dev_err(&f34->fn->dev, "Display config size mismatch\n"); dev_err(&f34->fn->dev, "Display config size mismatch\n");
...@@ -632,6 +635,8 @@ static int rmi_f34v7_check_guest_code_size(struct f34_data *f34) ...@@ -632,6 +635,8 @@ static int rmi_f34v7_check_guest_code_size(struct f34_data *f34)
u16 block_count; u16 block_count;
block_count = f34->v7.img.guest_code.size / f34->v7.block_size; block_count = f34->v7.img.guest_code.size / f34->v7.block_size;
f34->update_size += block_count;
if (block_count != f34->v7.blkcount.guest_code) { if (block_count != f34->v7.blkcount.guest_code) {
dev_err(&f34->fn->dev, "Guest code size mismatch\n"); dev_err(&f34->fn->dev, "Guest code size mismatch\n");
return -EINVAL; return -EINVAL;
...@@ -645,6 +650,7 @@ static int rmi_f34v7_check_bl_config_size(struct f34_data *f34) ...@@ -645,6 +650,7 @@ static int rmi_f34v7_check_bl_config_size(struct f34_data *f34)
u16 block_count; u16 block_count;
block_count = f34->v7.img.bl_config.size / f34->v7.block_size; block_count = f34->v7.img.bl_config.size / f34->v7.block_size;
f34->update_size += block_count;
if (block_count != f34->v7.blkcount.bl_config) { if (block_count != f34->v7.blkcount.bl_config) {
dev_err(&f34->fn->dev, "Bootloader config size mismatch\n"); dev_err(&f34->fn->dev, "Bootloader config size mismatch\n");
...@@ -881,6 +887,9 @@ static int rmi_f34v7_write_f34v7_blocks(struct f34_data *f34, ...@@ -881,6 +887,9 @@ static int rmi_f34v7_write_f34v7_blocks(struct f34_data *f34,
block_ptr += (transfer * f34->v7.block_size); block_ptr += (transfer * f34->v7.block_size);
remaining -= transfer; remaining -= transfer;
f34->update_progress += transfer;
f34->update_status = (f34->update_progress * 100) /
f34->update_size;
} while (remaining); } while (remaining);
return 0; return 0;
...@@ -1191,6 +1200,8 @@ int rmi_f34v7_do_reflash(struct f34_data *f34, const struct firmware *fw) ...@@ -1191,6 +1200,8 @@ int rmi_f34v7_do_reflash(struct f34_data *f34, const struct firmware *fw)
rmi_f34v7_read_queries_bl_version(f34); rmi_f34v7_read_queries_bl_version(f34);
f34->v7.image = fw->data; f34->v7.image = fw->data;
f34->update_progress = 0;
f34->update_size = 0;
ret = rmi_f34v7_parse_image_info(f34); ret = rmi_f34v7_parse_image_info(f34);
if (ret < 0) if (ret < 0)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment