Hi Christopher,
On Tue, Jan 07, 2014 at 12:33:41PM -0800, Christopher Heiny wrote:
> Eliminates copy-paste code that handled scans of the Page Descriptor Table,
> replacing it with a single PDT scan routine that invokes a callback function.
> The scan routine is not static so that it can be used by the firmware update
> code (under development, not yet submitted).
>
> Updated the copyright dates while we were at it.
>
> Signed-off-by: Christopher Heiny <[email protected]>
> Cc: Dmitry Torokhov <[email protected]>
> Cc: Benjamin Tissoires <[email protected]>
>
> ---
>
> drivers/input/rmi4/rmi_driver.c | 155
> ++++++++++++++++++++--------------------
> drivers/input/rmi4/rmi_driver.h | 6 +-
> 2 files changed, 83 insertions(+), 78 deletions(-)
>
> diff --git a/drivers/input/rmi4/rmi_driver.c b/drivers/input/rmi4/rmi_driver.c
> index eb790ff..cbd6485 100644
> --- a/drivers/input/rmi4/rmi_driver.c
> +++ b/drivers/input/rmi4/rmi_driver.c
> @@ -1,5 +1,5 @@
> /*
> - * Copyright (c) 2011-2013 Synaptics Incorporated
> + * Copyright (c) 2011-2014 Synaptics Incorporated
> * Copyright (c) 2011 Unixphere
> *
> * This driver provides the core support for a single RMI4-based device.
> @@ -566,85 +566,80 @@ err_free_mem:
> return error;
> }
>
> -/*
> - * Scan the PDT for F01 so we can force a reset before anything else
> - * is done. This forces the sensor into a known state, and also
> - * forces application of any pending updates from reflashing the
> - * firmware or configuration.
> - *
> - * We have to do this before actually building the PDT because the reflash
> - * updates (if any) might cause various registers to move around.
> - */
> -static int rmi_initial_reset(struct rmi_device *rmi_dev)
> +
> +#define RMI_SCAN_CONTINUE 0
> +#define RMI_SCAN_DONE 1
Can we add RMI_SCAN_ERROR here and use it instead of -EXXXX errors: I'd
rather not mix the 2 namespaces.
> +
> +static int rmi_initial_reset(struct rmi_device *rmi_dev,
> + void *clbk_ctx, struct pdt_entry *pdt_entry, int page)
> {
> - struct pdt_entry pdt_entry;
> - int page;
> - struct device *dev = &rmi_dev->dev;
> - bool done = false;
> - bool has_f01 = false;
> - int i;
> int retval;
> - const struct rmi_device_platform_data *pdata =
> - to_rmi_platform_data(rmi_dev);
>
> - dev_dbg(dev, "Initial reset.\n");
> + if (pdt_entry->function_number == 0x01) {
> + u16 cmd_addr = page + pdt_entry->command_base_addr;
> + u8 cmd_buf = RMI_DEVICE_RESET_CMD;
> + const struct rmi_device_platform_data *pdata =
> + to_rmi_platform_data(rmi_dev);
>
> - for (page = 0; (page <= RMI4_MAX_PAGE) && !done; page++) {
> - u16 page_start = RMI4_PAGE_SIZE * page;
> - u16 pdt_start = page_start + PDT_START_SCAN_LOCATION;
> - u16 pdt_end = page_start + PDT_END_SCAN_LOCATION;
> + retval = rmi_write_block(rmi_dev, cmd_addr, &cmd_buf, 1);
> + if (retval < 0) {
> + dev_err(&rmi_dev->dev,
> + "Initial reset failed. Code = %d.\n", retval);
> + return retval;
> + }
> + mdelay(pdata->reset_delay_ms);
>
> - done = true;
> - for (i = pdt_start; i >= pdt_end; i -= RMI_PDT_ENTRY_SIZE) {
> - retval = rmi_read_pdt_entry(rmi_dev, &pdt_entry, i);
> - if (retval < 0)
> - return retval;
> + return RMI_SCAN_DONE;
> + }
>
> - if (RMI4_END_OF_PDT(pdt_entry.function_number))
> - break;
> - done = false;
> + /* F01 should always be on page 0. If we don't find it there, fail. */
> + return (!page) ? RMI_SCAN_CONTINUE : -ENODEV;
> +}
>
> - if (pdt_entry.function_number == 0x01) {
> - u16 cmd_addr = page_start +
> - pdt_entry.command_base_addr;
> - u8 cmd_buf = RMI_DEVICE_RESET_CMD;
> - retval = rmi_write_block(rmi_dev, cmd_addr,
> - &cmd_buf, 1);
> - if (retval < 0) {
> - dev_err(dev, "Initial reset failed.
> Code = %d.\n",
> - retval);
> - return retval;
> - }
> - mdelay(pdata->reset_delay_ms);
> - done = true;
> - has_f01 = true;
> - break;
> - }
> - }
> - }
> +static int rmi_create_functions_clbk(struct rmi_device *rmi_dev,
> + void *clbk_ctx, struct pdt_entry *entry, int page)
> +{
> + int *irq_count = (int *)clbk_ctx;
>
> - if (!has_f01) {
> - dev_warn(dev, "WARNING: Failed to find F01 for initial
> reset.\n");
> - return -ENODEV;
> - }
> + return create_function(rmi_dev, entry, irq_count,
> + RMI4_PAGE_SIZE * page);
> +}
> +
> +static int rmi_create_functions(struct rmi_device *rmi_dev)
> +{
> + struct rmi_driver_data *data = dev_get_drvdata(&rmi_dev->dev);
> + struct device *dev = &rmi_dev->dev;
> + int irq_count = 0;
> + int retval;
> +
> + // XXX need to make sure we create F01 first...
> + // XXX or do we? It might not be required in the updated structure.
Prefer not add more C99-style comments.
> + retval = rmi_scan_pdt(rmi_dev, &irq_count, rmi_create_functions_clbk);
> +
> + if (retval)
> + return retval;
> +
> + // TODO: I think we need to count the IRQs before creating the
> + // functions.
Same here.
> + data->irq_count = irq_count;
> + data->num_of_irq_regs = (irq_count + 7) / 8;
>
> return 0;
> }
>
> -static int rmi_scan_pdt(struct rmi_device *rmi_dev)
> +int rmi_scan_pdt(struct rmi_device *rmi_dev, void *ctx,
> + int (*rmi_pdt_scan_clbk)(struct rmi_device *rmi_dev,
> + void *clbk_ctx, struct pdt_entry *entry, int page))
> {
> - struct rmi_driver_data *data;
> + struct rmi_driver_data *data = dev_get_drvdata(&rmi_dev->dev);
> struct pdt_entry pdt_entry;
> int page;
> - struct device *dev = &rmi_dev->dev;
> - int irq_count = 0;
> - bool done = false;
> int i;
> - int retval;
> -
> - dev_dbg(dev, "Scanning PDT...\n");
> + bool done = false;
> + int retval = 0;
>
> - data = dev_get_drvdata(&rmi_dev->dev);
> + // TODO: With F01 and reflash as part of the core now, is this
> + // lock still required?
> mutex_lock(&data->pdt_mutex);
>
> for (page = 0; (page <= RMI4_MAX_PAGE) && !done; page++) {
> @@ -656,27 +651,27 @@ static int rmi_scan_pdt(struct rmi_device *rmi_dev)
> for (i = pdt_start; i >= pdt_end; i -= RMI_PDT_ENTRY_SIZE) {
> retval = rmi_read_pdt_entry(rmi_dev, &pdt_entry, i);
> if (retval < 0)
> - goto error_exit;
> + return retval;
>
> if (RMI4_END_OF_PDT(pdt_entry.function_number))
> break;
>
> - dev_dbg(dev, "Found F%02X on page %#04x\n",
> + dev_dbg(&rmi_dev->dev, "Found F%02X on page %#04x\n",
> pdt_entry.function_number, page);
> done = false;
>
> - // XXX need to make sure we create F01 first...
> - retval = create_function(rmi_dev,
> - &pdt_entry, &irq_count, page_start);
> -
> - if (retval)
> + retval = rmi_pdt_scan_clbk(rmi_dev, ctx,
> + &pdt_entry, page);
> + if (retval < 0) {
> goto error_exit;
> + } else if (retval == RMI_SCAN_DONE) {
> + done = true;
> + break;
> + }
> }
> done = done || data->f01_bootloader_mode;
This should be simplified even more: the callback should return
RMI_SCAN_DONE if device is in bootloader mode.
> }
> - data->irq_count = irq_count;
> - data->num_of_irq_regs = (irq_count + 7) / 8;
> - dev_dbg(dev, "%s: Done with PDT scan.\n", __func__);
> +
> retval = 0;
>
> error_exit:
> @@ -684,6 +679,7 @@ error_exit:
> return retval;
> }
>
> +
> #ifdef CONFIG_PM_SLEEP
> static int rmi_driver_suspend(struct device *dev)
> {
> @@ -797,10 +793,15 @@ static int rmi_driver_probe(struct device *dev)
>
> /*
> * Right before a warm boot, the sensor might be in some unusual state,
> - * such as F54 diagnostics, or F34 bootloader mode. In order to clear
> - * the sensor to a known state, we issue a initial reset to clear any
> + * such as F54 diagnostics, or F34 bootloader mode after a firmware
> + * or configuration update. In order to clear the sensor to a known
> + * state and/or apply any updates, we issue a initial reset to clear any
> * previous settings and force it into normal operation.
> *
> + * We have to do this before actually building the PDT because
> + * the reflash updates (if any) might cause various registers to move
> + * around.
> + *
> * For a number of reasons, this initial reset may fail to return
> * within the specified time, but we'll still be able to bring up the
> * driver normally after that failure. This occurs most commonly in
> @@ -813,11 +814,11 @@ static int rmi_driver_probe(struct device *dev)
> */
> if (!pdata->reset_delay_ms)
> pdata->reset_delay_ms = DEFAULT_RESET_DELAY_MS;
> - retval = rmi_initial_reset(rmi_dev);
> + retval = rmi_scan_pdt(rmi_dev, NULL, rmi_initial_reset);
> if (retval)
> dev_warn(dev, "RMI initial reset failed! Continuing in spite of
> this.\n");
>
> - retval = rmi_scan_pdt(rmi_dev);
> + retval = rmi_create_functions(rmi_dev);
> if (retval) {
> dev_err(dev, "PDT scan for %s failed with code %d.\n",
> pdata->sensor_name, retval);
> diff --git a/drivers/input/rmi4/rmi_driver.h b/drivers/input/rmi4/rmi_driver.h
> index df9ddd8..f73be73 100644
> --- a/drivers/input/rmi4/rmi_driver.h
> +++ b/drivers/input/rmi4/rmi_driver.h
> @@ -1,5 +1,5 @@
> /*
> - * Copyright (c) 2011-2013 Synaptics Incorporated
> + * Copyright (c) 2011-2014 Synaptics Incorporated
> * Copyright (c) 2011 Unixphere
> *
> * This program is free software; you can redistribute it and/or modify it
> @@ -108,6 +108,10 @@ struct pdt_entry {
> int rmi_read_pdt_entry(struct rmi_device *rmi_dev, struct pdt_entry *entry,
> u16 pdt_address);
>
> +int rmi_scan_pdt(struct rmi_device *rmi_dev, void *ctx,
> + int (*rmi_pdt_scan_clbk)(struct rmi_device *rmi_dev,
> + void *clbk_ctx, struct pdt_entry *entry, int page));
> +
> bool rmi_is_physical_driver(struct device_driver *);
> int rmi_register_physical_driver(void);
> void rmi_unregister_physical_driver(void);
Thanks.
--
Dmitry
--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html