Skip to content

Commit

Permalink
Input: synaptics-rmi4 - add support for F34 V7 bootloader
Browse files Browse the repository at this point in the history
Port firmware update code from Samsung Galaxy S7 driver into
mainline framework.

This patch has been tested on Synaptics S7813.

Signed-off-by: Nick Dyer <[email protected]>
Tested-by: Chris Healy <[email protected]>
Signed-off-by: Dmitry Torokhov <[email protected]>
  • Loading branch information
ndyer authored and dtor committed Dec 12, 2016
1 parent 5d244f7 commit 5191d88
Show file tree
Hide file tree
Showing 6 changed files with 1,688 additions and 34 deletions.
2 changes: 1 addition & 1 deletion drivers/input/rmi4/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ rmi_core-$(CONFIG_RMI4_F03) += rmi_f03.o
rmi_core-$(CONFIG_RMI4_F11) += rmi_f11.o
rmi_core-$(CONFIG_RMI4_F12) += rmi_f12.o
rmi_core-$(CONFIG_RMI4_F30) += rmi_f30.o
rmi_core-$(CONFIG_RMI4_F34) += rmi_f34.o
rmi_core-$(CONFIG_RMI4_F34) += rmi_f34.o rmi_f34v7.o
rmi_core-$(CONFIG_RMI4_F54) += rmi_f54.o
rmi_core-$(CONFIG_RMI4_F55) += rmi_f55.o

Expand Down
56 changes: 33 additions & 23 deletions drivers/input/rmi4/rmi_driver.c
Original file line number Diff line number Diff line change
Expand Up @@ -544,7 +544,7 @@ static int rmi_scan_pdt_page(struct rmi_device *rmi_dev,
else
*empty_pages = 0;

return (data->f01_bootloader_mode || *empty_pages >= 2) ?
return (data->bootloader_mode || *empty_pages >= 2) ?
RMI_SCAN_DONE : RMI_SCAN_CONTINUE;
}

Expand Down Expand Up @@ -749,41 +749,49 @@ bool rmi_register_desc_has_subpacket(const struct rmi_register_desc_item *item,
subpacket) == subpacket;
}

/* Indicates that flash programming is enabled (bootloader mode). */
#define RMI_F01_STATUS_BOOTLOADER(status) (!!((status) & 0x40))

/*
* Given the PDT entry for F01, read the device status register to determine
* if we're stuck in bootloader mode or not.
*
*/
static int rmi_check_bootloader_mode(struct rmi_device *rmi_dev,
const struct pdt_entry *pdt)
{
int error;
u8 device_status;
struct rmi_driver_data *data = dev_get_drvdata(&rmi_dev->dev);
int ret;
u8 status;

error = rmi_read(rmi_dev, pdt->data_base_addr + pdt->page_start,
&device_status);
if (error) {
dev_err(&rmi_dev->dev,
"Failed to read device status: %d.\n", error);
return error;
if (pdt->function_number == 0x34 && pdt->function_version > 1) {
ret = rmi_read(rmi_dev, pdt->data_base_addr, &status);
if (ret) {
dev_err(&rmi_dev->dev,
"Failed to read F34 status: %d.\n", ret);
return ret;
}

if (status & BIT(7))
data->bootloader_mode = true;
} else if (pdt->function_number == 0x01) {
ret = rmi_read(rmi_dev, pdt->data_base_addr, &status);
if (ret) {
dev_err(&rmi_dev->dev,
"Failed to read F01 status: %d.\n", ret);
return ret;
}

if (status & BIT(6))
data->bootloader_mode = true;
}

return RMI_F01_STATUS_BOOTLOADER(device_status);
return 0;
}

static int rmi_count_irqs(struct rmi_device *rmi_dev,
void *ctx, const struct pdt_entry *pdt)
{
struct rmi_driver_data *data = dev_get_drvdata(&rmi_dev->dev);
int *irq_count = ctx;
int ret;

*irq_count += pdt->interrupt_source_count;
if (pdt->function_number == 0x01)
data->f01_bootloader_mode =
rmi_check_bootloader_mode(rmi_dev, pdt);

ret = rmi_check_bootloader_mode(rmi_dev, pdt);
if (ret < 0)
return ret;

return RMI_SCAN_CONTINUE;
}
Expand Down Expand Up @@ -1024,13 +1032,15 @@ int rmi_probe_interrupts(struct rmi_driver_data *data)
*/
rmi_dbg(RMI_DEBUG_CORE, dev, "%s: Counting IRQs.\n", __func__);
irq_count = 0;
data->bootloader_mode = false;

retval = rmi_scan_pdt(rmi_dev, &irq_count, rmi_count_irqs);
if (retval < 0) {
dev_err(dev, "IRQ counting failed with code %d.\n", retval);
return retval;
}

if (data->f01_bootloader_mode)
if (data->bootloader_mode)
dev_warn(&rmi_dev->dev, "Device in bootloader mode.\n");

data->irq_count = irq_count;
Expand Down
40 changes: 33 additions & 7 deletions drivers/input/rmi4/rmi_f34.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include <linux/firmware.h>
#include <asm/unaligned.h>
#include <asm/unaligned.h>
#include <linux/bitops.h>

#include "rmi_driver.h"
#include "rmi_f34.h"
Expand Down Expand Up @@ -105,6 +106,9 @@ static int rmi_f34_attention(struct rmi_function *fn, unsigned long *irq_bits)
struct f34_data *f34 = dev_get_drvdata(&fn->dev);
int ret;

if (f34->bl_version != 5)
return 0;

ret = rmi_read(f34->fn->rmi_dev, f34->v5.ctrl_address, &f34->v5.status);
rmi_dbg(RMI_DEBUG_FN, &fn->dev, "%s: status: %#02x, ret: %d\n",
__func__, f34->v5.status, ret);
Expand Down Expand Up @@ -292,17 +296,24 @@ static int rmi_firmware_update(struct rmi_driver_data *data,
return -EINVAL;
}

/* Only version 0 currently supported */
if (data->f34_container->fd.function_version != 0) {
f34 = dev_get_drvdata(&data->f34_container->dev);

if (f34->bl_version == 7) {
if (data->pdt_props & HAS_BSR) {
dev_err(dev, "%s: LTS not supported\n", __func__);
return -ENODEV;
}
} else if (f34->bl_version != 5) {
dev_warn(dev, "F34 V%d not supported!\n",
data->f34_container->fd.function_version);
return -ENODEV;
}

f34 = dev_get_drvdata(&data->f34_container->dev);

/* Enter flash mode */
ret = rmi_f34_enable_flash(f34);
if (f34->bl_version == 7)
ret = rmi_f34v7_start_reflash(f34, fw);
else
ret = rmi_f34_enable_flash(f34);
if (ret)
return ret;

Expand All @@ -319,7 +330,7 @@ static int rmi_firmware_update(struct rmi_driver_data *data,
if (ret)
return ret;

if (!data->f01_bootloader_mode || !data->f34_container) {
if (!data->bootloader_mode || !data->f34_container) {
dev_warn(dev, "%s: No F34 present or not in bootloader!\n",
__func__);
return -EINVAL;
Expand All @@ -330,7 +341,10 @@ static int rmi_firmware_update(struct rmi_driver_data *data,
f34 = dev_get_drvdata(&data->f34_container->dev);

/* Perform firmware update */
ret = rmi_f34_update_firmware(f34, fw);
if (f34->bl_version == 7)
ret = rmi_f34v7_do_reflash(f34, fw);
else
ret = rmi_f34_update_firmware(f34, fw);

dev_info(&f34->fn->dev, "Firmware update complete, status:%d\n", ret);

Expand Down Expand Up @@ -363,6 +377,9 @@ static int rmi_firmware_update(struct rmi_driver_data *data,
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,
struct device_attribute *dattr,
const char *buf, size_t count)
Expand Down Expand Up @@ -411,6 +428,7 @@ static int rmi_f34_probe(struct rmi_function *fn)
struct f34_data *f34;
unsigned char f34_queries[9];
bool has_config_id;
u8 version = fn->fd.function_version;
int ret;

f34 = devm_kzalloc(&fn->dev, sizeof(struct f34_data), GFP_KERNEL);
Expand All @@ -420,6 +438,14 @@ static int rmi_f34_probe(struct rmi_function *fn)
f34->fn = fn;
dev_set_drvdata(&fn->dev, f34);

/* v5 code only supported version 0, try V7 probe */
if (version > 0)
return rmi_f34v7_probe(f34);
else if (version != 0)
return -ENODEV;

f34->bl_version = 5;

ret = rmi_read_block(fn->rmi_dev, fn->fd.query_base_addr,
f34_queries, sizeof(f34_queries));
if (ret) {
Expand Down
Loading

0 comments on commit 5191d88

Please sign in to comment.