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 <cheiny@xxxxxxxxxxxxx> > Cc: Dmitry Torokhov <dmitry.torokhov@xxxxxxxxx> > Cc: Benjamin Tissoires <benjamin.tissoires@xxxxxxxxxx> > > --- > > 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 majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html