Input: synaptics-rmi4 - add support for F34 device reflash

Add support for updating firmware, triggered by a sysfs attribute.

This patch has been tested on Synaptics S7300.

Signed-off-by: Nick Dyer <nick@shmanahar.org>
Tested-by: Chris Healy <cphealy@gmail.com>
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
diff --git a/drivers/input/rmi4/rmi_driver.c b/drivers/input/rmi4/rmi_driver.c
index 4f8d197..2b17d8c 100644
--- a/drivers/input/rmi4/rmi_driver.c
+++ b/drivers/input/rmi4/rmi_driver.c
@@ -35,14 +35,24 @@
 #define RMI_DEVICE_RESET_CMD	0x01
 #define DEFAULT_RESET_DELAY_MS	100
 
-static void rmi_free_function_list(struct rmi_device *rmi_dev)
+void rmi_free_function_list(struct rmi_device *rmi_dev)
 {
 	struct rmi_function *fn, *tmp;
 	struct rmi_driver_data *data = dev_get_drvdata(&rmi_dev->dev);
 
 	rmi_dbg(RMI_DEBUG_CORE, &rmi_dev->dev, "Freeing function list\n");
 
+	mutex_lock(&data->irq_mutex);
+
+	devm_kfree(&rmi_dev->dev, data->irq_memory);
+	data->irq_memory = NULL;
+	data->irq_status = NULL;
+	data->fn_irq_bits = NULL;
+	data->current_irq_mask = NULL;
+	data->new_irq_mask = NULL;
+
 	data->f01_container = NULL;
+	data->f34_container = NULL;
 
 	/* Doing it in the reverse order so F01 will be removed last */
 	list_for_each_entry_safe_reverse(fn, tmp,
@@ -50,7 +60,10 @@
 		list_del(&fn->node);
 		rmi_unregister_function(fn);
 	}
+
+	mutex_unlock(&data->irq_mutex);
 }
+EXPORT_SYMBOL_GPL(rmi_free_function_list);
 
 static int reset_one_function(struct rmi_function *fn)
 {
@@ -147,24 +160,25 @@
 	if (!data)
 		return 0;
 
+	mutex_lock(&data->irq_mutex);
+	if (!data->irq_status || !data->f01_container) {
+		mutex_unlock(&data->irq_mutex);
+		return 0;
+	}
+
 	if (!rmi_dev->xport->attn_data) {
 		error = rmi_read_block(rmi_dev,
 				data->f01_container->fd.data_base_addr + 1,
 				data->irq_status, data->num_of_irq_regs);
 		if (error < 0) {
 			dev_err(dev, "Failed to read irqs, code=%d\n", error);
+			mutex_unlock(&data->irq_mutex);
 			return error;
 		}
 	}
 
-	mutex_lock(&data->irq_mutex);
 	bitmap_and(data->irq_status, data->irq_status, data->current_irq_mask,
 	       data->irq_count);
-	/*
-	 * At this point, irq_status has all bits that are set in the
-	 * interrupt status register and are enabled.
-	 */
-	mutex_unlock(&data->irq_mutex);
 
 	/*
 	 * It would be nice to be able to use irq_chip to handle these
@@ -180,6 +194,8 @@
 	if (data->input)
 		input_sync(data->input);
 
+	mutex_unlock(&data->irq_mutex);
+
 	return 0;
 }
 
@@ -244,12 +260,18 @@
 	struct rmi_function *entry;
 	int retval;
 
+	mutex_lock(&data->irq_mutex);
+
 	list_for_each_entry(entry, &data->function_list, node) {
 		retval = suspend_one_function(entry);
-		if (retval < 0)
+		if (retval < 0) {
+			mutex_unlock(&data->irq_mutex);
 			return retval;
+		}
 	}
 
+	mutex_unlock(&data->irq_mutex);
+
 	return 0;
 }
 
@@ -278,16 +300,22 @@
 	struct rmi_function *entry;
 	int retval;
 
+	mutex_lock(&data->irq_mutex);
+
 	list_for_each_entry(entry, &data->function_list, node) {
 		retval = resume_one_function(entry);
-		if (retval < 0)
+		if (retval < 0) {
+			mutex_unlock(&data->irq_mutex);
 			return retval;
+		}
 	}
 
+	mutex_unlock(&data->irq_mutex);
+
 	return 0;
 }
 
-static int enable_sensor(struct rmi_device *rmi_dev)
+int rmi_enable_sensor(struct rmi_device *rmi_dev)
 {
 	int retval = 0;
 
@@ -297,6 +325,7 @@
 
 	return rmi_process_interrupt_requests(rmi_dev);
 }
+EXPORT_SYMBOL_GPL(rmi_enable_sensor);
 
 /**
  * rmi_driver_set_input_params - set input device id and other data.
@@ -502,10 +531,9 @@
 					RMI_SCAN_DONE : RMI_SCAN_CONTINUE;
 }
 
-static int rmi_scan_pdt(struct rmi_device *rmi_dev, void *ctx,
-			int (*callback)(struct rmi_device *rmi_dev,
-					void *ctx,
-					const struct pdt_entry *entry))
+int rmi_scan_pdt(struct rmi_device *rmi_dev, void *ctx,
+		 int (*callback)(struct rmi_device *rmi_dev,
+		 void *ctx, const struct pdt_entry *entry))
 {
 	int page;
 	int empty_pages = 0;
@@ -520,6 +548,7 @@
 
 	return retval < 0 ? retval : 0;
 }
+EXPORT_SYMBOL_GPL(rmi_scan_pdt);
 
 int rmi_read_register_desc(struct rmi_device *d, u16 addr,
 				struct rmi_register_descriptor *rdesc)
@@ -740,19 +769,15 @@
 	int *irq_count = ctx;
 
 	*irq_count += pdt->interrupt_source_count;
-	if (pdt->function_number == 0x01) {
+	if (pdt->function_number == 0x01)
 		data->f01_bootloader_mode =
 			rmi_check_bootloader_mode(rmi_dev, pdt);
-		if (data->f01_bootloader_mode)
-			dev_warn(&rmi_dev->dev,
-				"WARNING: RMI4 device is in bootloader mode!\n");
-	}
 
 	return RMI_SCAN_CONTINUE;
 }
 
-static int rmi_initial_reset(struct rmi_device *rmi_dev,
-			     void *ctx, const struct pdt_entry *pdt)
+int rmi_initial_reset(struct rmi_device *rmi_dev, void *ctx,
+		      const struct pdt_entry *pdt)
 {
 	int error;
 
@@ -787,6 +812,7 @@
 	/* F01 should always be on page 0. If we don't find it there, fail. */
 	return pdt->page_start == 0 ? RMI_SCAN_CONTINUE : -ENODEV;
 }
+EXPORT_SYMBOL_GPL(rmi_initial_reset);
 
 static int rmi_create_function(struct rmi_device *rmi_dev,
 			       void *ctx, const struct pdt_entry *pdt)
@@ -828,6 +854,8 @@
 
 	if (pdt->function_number == 0x01)
 		data->f01_container = fn;
+	else if (pdt->function_number == 0x34)
+		data->f34_container = fn;
 
 	list_add_tail(&fn->node, &data->function_list);
 
@@ -893,6 +921,7 @@
 
 	disable_irq(irq);
 
+	rmi_f34_remove_sysfs(rmi_dev);
 	rmi_free_function_list(rmi_dev);
 
 	return 0;
@@ -919,13 +948,12 @@
 }
 #endif
 
-static int rmi_probe_interrupts(struct rmi_driver_data *data)
+int rmi_probe_interrupts(struct rmi_driver_data *data)
 {
 	struct rmi_device *rmi_dev = data->rmi_dev;
 	struct device *dev = &rmi_dev->dev;
 	int irq_count;
 	size_t size;
-	void *irq_memory;
 	int retval;
 
 	/*
@@ -941,31 +969,38 @@
 		dev_err(dev, "IRQ counting failed with code %d.\n", retval);
 		return retval;
 	}
+
+	if (data->f01_bootloader_mode)
+		dev_warn(&rmi_dev->dev, "Device in bootloader mode.\n");
+
 	data->irq_count = irq_count;
 	data->num_of_irq_regs = (data->irq_count + 7) / 8;
 
 	size = BITS_TO_LONGS(data->irq_count) * sizeof(unsigned long);
-	irq_memory = devm_kzalloc(dev, size * 4, GFP_KERNEL);
-	if (!irq_memory) {
+	data->irq_memory = devm_kzalloc(dev, size * 4, GFP_KERNEL);
+	if (!data->irq_memory) {
 		dev_err(dev, "Failed to allocate memory for irq masks.\n");
 		return retval;
 	}
 
-	data->irq_status	= irq_memory + size * 0;
-	data->fn_irq_bits	= irq_memory + size * 1;
-	data->current_irq_mask	= irq_memory + size * 2;
-	data->new_irq_mask	= irq_memory + size * 3;
+	data->irq_status	= data->irq_memory + size * 0;
+	data->fn_irq_bits	= data->irq_memory + size * 1;
+	data->current_irq_mask	= data->irq_memory + size * 2;
+	data->new_irq_mask	= data->irq_memory + size * 3;
 
 	return retval;
 }
+EXPORT_SYMBOL_GPL(rmi_probe_interrupts);
 
-static int rmi_init_functions(struct rmi_driver_data *data)
+int rmi_init_functions(struct rmi_driver_data *data)
 {
 	struct rmi_device *rmi_dev = data->rmi_dev;
 	struct device *dev = &rmi_dev->dev;
 	int irq_count;
 	int retval;
 
+	mutex_lock(&data->irq_mutex);
+
 	irq_count = 0;
 	rmi_dbg(RMI_DEBUG_CORE, dev, "%s: Creating functions.\n", __func__);
 	retval = rmi_scan_pdt(rmi_dev, &irq_count, rmi_create_function);
@@ -990,12 +1025,16 @@
 		goto err_destroy_functions;
 	}
 
+	mutex_unlock(&data->irq_mutex);
+
 	return 0;
 
 err_destroy_functions:
 	rmi_free_function_list(rmi_dev);
+	mutex_unlock(&data->irq_mutex);
 	return retval;
 }
+EXPORT_SYMBOL_GPL(rmi_init_functions);
 
 static int rmi_driver_probe(struct device *dev)
 {
@@ -1100,6 +1139,10 @@
 	if (retval)
 		goto err;
 
+	retval = rmi_f34_create_sysfs(rmi_dev);
+	if (retval)
+		goto err;
+
 	if (data->input) {
 		rmi_driver_set_input_name(rmi_dev, data->input);
 		if (!rmi_dev->xport->input) {
@@ -1117,7 +1160,7 @@
 
 	if (data->f01_container->dev.driver)
 		/* Driver already bound, so enable ATTN now. */
-		return enable_sensor(rmi_dev);
+		return rmi_enable_sensor(rmi_dev);
 
 	return 0;