linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 00/05] input: RMI4 Synaptics RMI4 Touchscreen Driver
@ 2013-01-19  1:12 Christopher Heiny
  2013-01-19  1:12 ` [PATCH 01/05] input: RMI4 public header file Christopher Heiny
                   ` (5 more replies)
  0 siblings, 6 replies; 11+ messages in thread
From: Christopher Heiny @ 2013-01-19  1:12 UTC (permalink / raw)
  To: Dmitry Torokhov
  Cc: Jean Delvare, Linux Kernel, Linux Input, Christopher Heiny,
	Allie Xiong, Vivian Ly, Daniel Rosenberg, Alexandra Chin,
	Joerie de Gram, Wolfram Sang, Mathieu Poirier, Linus Walleij

This patchset implements changes based on the synaptics-rmi4 branch of
Dmitry's input tree.  The base for the patchset is Dmitry's commit
0af25383d395fb5ece54b79d12d06138bf8b9836 from 2012-11-28.  It supersedes
our previous patch submission from 2012-12-18.

Overall this patchset implements the following changes with respect to
the Dmitry's 2012-11-28 commit:

* updates to Dmitry's RMI4_CORE structure from his 2012-11-28 patches.
This tries to maintain the same approach as Dmitry's implementation, but
we had to move away from using the bus probe() routine, since it wasn't
possible for that routine to readily determine if it had a struct driver() for
an RMI4 sensor or an RMI4 device.  Otherwise, we've stuck close to Dmitry's
work, which has tidied things up nicely.

* We've renamed the structures rmi_function_handler to rmi_function_driver and
rmi_device to rmi_function_dev, mainly because they actually were being treated
as drivers and devices for individual RMI4 functions, and the previous
terminology was somewhat confusing.

* Changed a bunch of bools to u32 to support standard debugfs macros.  Moved
almost all the debugfs and sysfs handling out of these files into their own
modules, simplifying the core functionality of the driver.  Once the core is
stable, we can look into adding modules to support the debug/control
features.

* Many other bools were changed to u8, per Dmitry's request.

* Trivial - file copyright header is updated to be more in line with the rest
of the files under ./input.


We've broken this patch into 6 parts, as follows:
    01 - public header file
    02 - core sensor and bus implementation
    03 - I2C physical layer driver
    04.05 - drivers for individual RMI functions


Hopefully this is the last time we'll have wide-ranging structural changes in
the driver code, and future patchsets can be much smaller and confined to
one or two areas of interest.


Comments and other feedback on this driver are welcomed.

Christopher Heiny and the Synaptics RMI4 driver team

Signed-off-by: Christopher Heiny <cheiny@synaptics.com>
Cc: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Cc: Jean Delvare <khali@linux-fr.org>
Cc: Linus Walleij <linus.walleij@stericsson.com>
Cc: Joeri de Gram <j.de.gram@gmail.com>

---

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCH 01/05] input: RMI4 public header file
  2013-01-19  1:12 [PATCH 00/05] input: RMI4 Synaptics RMI4 Touchscreen Driver Christopher Heiny
@ 2013-01-19  1:12 ` Christopher Heiny
  2013-01-19  1:12 ` [PATCH 02/05] input: RMI4 core files Christopher Heiny
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 11+ messages in thread
From: Christopher Heiny @ 2013-01-19  1:12 UTC (permalink / raw)
  To: Dmitry Torokhov
  Cc: Jean Delvare, Linux Kernel, Linux Input, Christopher Heiny,
	Allie Xiong, Vivian Ly, Daniel Rosenberg, Alexandra Chin,
	Joerie de Gram, Wolfram Sang, Mathieu Poirier, Linus Walleij

In addition to the changes described in part 0/5, this fixes some cut&paste
issues in the comments for module_rmi_function_driver.

Signed-off-by: Christopher Heiny <cheiny@synaptics.com>
Cc: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Cc: Linus Walleij <linus.walleij@stericsson.com>
Cc: Joeri de Gram <j.de.gram@gmail.com>
Acked-by: Jean Delvare <khali@linux-fr.org>

---

 include/linux/rmi.h |   95 +++++++++++++++++++++++----------------------------
 1 files changed, 43 insertions(+), 52 deletions(-)

diff --git a/include/linux/rmi.h b/include/linux/rmi.h
index daca41b..eec926f 100644
--- a/include/linux/rmi.h
+++ b/include/linux/rmi.h
@@ -2,25 +2,16 @@
  * Copyright (c) 2011, 2012 Synaptics Incorporated
  * Copyright (c) 2011 Unixphere
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
  */
 
 #ifndef _RMI_H
 #define _RMI_H
 #include <linux/kernel.h>
 #include <linux/cdev.h>
+#include <linux/debugfs.h>
 #include <linux/device.h>
 #include <linux/interrupt.h>
 #include <linux/input.h>
@@ -31,7 +22,6 @@
 #include <linux/stat.h>
 #include <linux/types.h>
 #include <linux/wait.h>
-#include <linux/debugfs.h>
 
 extern struct bus_type rmi_bus_type;
 
@@ -73,7 +63,7 @@ enum rmi_attn_polarity {
  *               automatically enabled for this sensor.
  */
 struct rmi_f11_2d_axis_alignment {
-	bool swap_axes;
+	u32 swap_axes;
 	bool flip_x;
 	bool flip_y;
 	int clip_X_low;
@@ -82,7 +72,6 @@ struct rmi_f11_2d_axis_alignment {
 	int clip_Y_high;
 	int offset_X;
 	int offset_Y;
-	int rel_report_enabled;
 	u8 delta_x_threshold;
 	u8 delta_y_threshold;
 };
@@ -105,6 +94,7 @@ enum rmi_f11_sensor_type {
 
 /**
  * struct rmi_f11_sensor_data - overrides defaults for a single F11 2D sensor.
+ *
  * @axis_align - provides axis alignment overrides (see above).
  * @type_a - all modern RMI F11 firmwares implement Multifinger Type B
  * protocol.  Set this to true to force MF Type A behavior, in case you find
@@ -338,13 +328,14 @@ struct rmi_function_descriptor {
 	u8 function_version;
 };
 
-struct rmi_function;
+struct rmi_function_dev;
 struct rmi_device;
 
 /**
- * struct rmi_function_handler - driver routines for a particular RMI function.
+ * struct rmi_function_driver - driver routines for a particular RMI function.
  *
  * @func: The RMI function number
+ * @probe: Called when the handler is successfully matched to a function device.
  * @reset: Called when a reset of the touch sensor is detected.  The routine
  * should perform any out-of-the-ordinary reset handling that might be
  * necessary.  Restoring of touch sensor configuration registers should be
@@ -361,37 +352,31 @@ struct rmi_device;
  *
  * All callbacks are expected to return 0 on success, error code on failure.
  */
-struct rmi_function_handler {
+struct rmi_function_driver {
 	struct device_driver driver;
 
 	u8 func;
-	int (*probe)(struct rmi_function *fn);
-	void (*remove)(struct rmi_function *fn);
-	int (*config)(struct rmi_function *fn);
-	int (*reset)(struct rmi_function *fn);
-	int (*attention)(struct rmi_function *fn, unsigned long *irq_bits);
+	int (*probe)(struct rmi_function_dev *fc);
+	int (*remove)(struct rmi_function_dev *fc);
+	int (*config)(struct rmi_function_dev *fc);
+	int (*reset)(struct rmi_function_dev *fc);
+	int (*attention)(struct rmi_function_dev *fc,
+				unsigned long *irq_bits);
 #ifdef CONFIG_PM
-	int (*suspend)(struct rmi_function *fn);
-	int (*resume)(struct rmi_function *fn);
+	int (*suspend)(struct rmi_function_dev *fc);
+	int (*resume)(struct rmi_function_dev *fc);
 #endif
 };
 
-#define to_rmi_function_handler(d) \
-		container_of(d, struct rmi_function_handler, driver)
-
-int __must_check __rmi_register_function_handler(struct rmi_function_handler *,
-						 struct module *, const char *);
-#define rmi_register_function_handler(handler) \
-	__rmi_register_function_handler(handler, THIS_MODULE, KBUILD_MODNAME)
-
-void rmi_unregister_function_handler(struct rmi_function_handler *);
+#define to_rmi_function_driver(d) \
+		container_of(d, struct rmi_function_driver, driver);
 
 /**
- * struct rmi_function - represents the implementation of an RMI4
- * function for a particular device (basically, a driver for that RMI4 function)
+ * struct rmi_function_dev - represents an a particular RMI4 function on a given
+ * RMI4 sensor.
  *
  * @fd: The function descriptor of the RMI function
- * @rmi_dev: Pointer to the RMI device associated with this function container
+ * @rmi_dev: Pointer to the RMI device associated with this function device
  * @dev: The device associated with this particular function.
  *
  * @num_of_irqs: The number of irqs needed by this function
@@ -400,11 +385,12 @@ void rmi_unregister_function_handler(struct rmi_function_handler *);
  * interrupt handling.
  * @data: Private data pointer
  *
- * @list: Used to create a list of function containers.
+ * @list: Used to create a list of function devices.
  * @debugfs_root: used during debugging
  *
  */
-struct rmi_function {
+struct rmi_function_dev {
+
 	struct rmi_function_descriptor fd;
 	struct rmi_device *rmi_dev;
 	struct device dev;
@@ -414,13 +400,19 @@ struct rmi_function {
 	void *data;
 	struct list_head list;
 
-#ifdef CONFIG_RMI4_DEBUG
 	struct dentry *debugfs_root;
-#endif
 };
 
-#define to_rmi_function(d) \
-		container_of(d, struct rmi_function, dev)
+#define to_rmi_function_dev(d) \
+		container_of(d, struct rmi_function_dev, dev);
+
+
+int __must_check __rmi_register_function_driver(struct rmi_function_driver *,
+						 struct module *, const char *);
+#define rmi_register_function_driver(handler) \
+	__rmi_register_function_driver(handler, THIS_MODULE, KBUILD_MODNAME)
+
+void rmi_unregister_function_driver(struct rmi_function_driver *);
 
 /**
  * struct rmi_driver - driver for an RMI4 sensor on the RMI bus.
@@ -446,6 +438,7 @@ struct rmi_driver {
 	int (*store_productid)(struct rmi_device *rmi_dev);
 	int (*set_input_params)(struct rmi_device *rmi_dev,
 			struct input_dev *input);
+	int (*remove)(struct rmi_device *rmi_dev);
 	void *data;
 };
 
@@ -528,9 +521,7 @@ struct rmi_device {
 	struct rmi_driver *driver;
 	struct rmi_phys_device *phys;
 
-#ifdef CONFIG_RMI4_DEBUG
 	struct dentry *debugfs_root;
-#endif
 };
 
 #define to_rmi_device(d) container_of(d, struct rmi_device, dev);
@@ -601,17 +592,17 @@ void rmi_unregister_phys_device(struct rmi_phys_device *phys);
 int rmi_for_each_dev(void *data, int (*func)(struct device *dev, void *data));
 
 /**
- * module_serio_driver() - Helper macro for registering a serio driver
- * @__serio_driver: serio_driver struct
+ * module_rmi_function_driver() - Helper macro for registering a function driver
+ * @__rmi_driver: rmi_function_driver struct
  *
- * Helper macro for serio drivers which do not do anything special in
+ * Helper macro for RMI4 function drivers which do not do anything special in
  * module init/exit. This eliminates a lot of boilerplate. Each module
  * may only use this macro once, and calling it replaces module_init()
  * and module_exit().
  */
-#define module_rmi_driver(__rmi_driver)			\
+#define module_rmi_function_driver(__rmi_driver)	\
 	module_driver(__rmi_driver,			\
-		      rmi_register_function_handler,	\
-		      rmi_unregister_function_handler)
+		      rmi_register_function_driver,	\
+		      rmi_unregister_function_driver)
 
 #endif

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 02/05] input: RMI4 core files
  2013-01-19  1:12 [PATCH 00/05] input: RMI4 Synaptics RMI4 Touchscreen Driver Christopher Heiny
  2013-01-19  1:12 ` [PATCH 01/05] input: RMI4 public header file Christopher Heiny
@ 2013-01-19  1:12 ` Christopher Heiny
  2013-01-19  1:12 ` [PATCH 03/05] input: RMI4 I2C physical layer Christopher Heiny
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 11+ messages in thread
From: Christopher Heiny @ 2013-01-19  1:12 UTC (permalink / raw)
  To: Dmitry Torokhov
  Cc: Jean Delvare, Linux Kernel, Linux Input, Christopher Heiny,
	Allie Xiong, Vivian Ly, Daniel Rosenberg, Alexandra Chin,
	Joerie de Gram, Wolfram Sang, Mathieu Poirier, Linus Walleij

In addition to the changes described in 0/5 of this patch set, these files
are updated as follows:

* initialization sequence rearranged to support the merging of rmi_f01 and
rmi_driver into the RMI4 core.

* the initial reset and firmware update PDT scans are split into their own
functions in order to account for the fact that the PDT may change after
the initial reset.

* Problems with release_rmidev_device() identified by Greg KH are fixed and
tested.

* EXPORT_SYMBOL() changed to EXPORT_SYMBOL_GPL(), per Greg KH input.


Signed-off-by: Christopher Heiny <cheiny@synaptics.com>
Cc: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Cc: Linus Walleij <linus.walleij@stericsson.com>
Cc: Joeri de Gram <j.de.gram@gmail.com>
Acked-by: Jean Delvare <khali@linux-fr.org>

---

 drivers/input/rmi4/rmi_bus.c    |  232 +++++-----
 drivers/input/rmi4/rmi_driver.c |  988 ++++++++++++---------------------------
 drivers/input/rmi4/rmi_driver.h |   32 +-
 3 files changed, 446 insertions(+), 806 deletions(-)

diff --git a/drivers/input/rmi4/rmi_bus.c b/drivers/input/rmi4/rmi_bus.c
index acbfd3d..71bc201 100644
--- a/drivers/input/rmi4/rmi_bus.c
+++ b/drivers/input/rmi4/rmi_bus.c
@@ -2,19 +2,9 @@
  * Copyright (c) 2011, 2012 Synaptics Incorporated
  * Copyright (c) 2011 Unixphere
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
  */
 
 #include <linux/kernel.h>
@@ -75,7 +65,8 @@ static struct dentry *rmi_debugfs_root;
 
 static void release_rmidev_device(struct device *dev)
 {
-	device_unregister(dev);
+	struct rmi_device *rmi_dev = to_rmi_device(dev);
+	kfree(rmi_dev);
 }
 
 /**
@@ -110,17 +101,19 @@ int rmi_register_phys_device(struct rmi_phys_device *phys)
 	dev_dbg(phys->dev, "%s: Registered %s as %s.\n", __func__,
 		pdata->sensor_name, dev_name(&rmi_dev->dev));
 
-	if (IS_ENABLED(CONFIG_RMI4_DEBUG) && rmi_debugfs_root) {
+#ifdef	CONFIG_RMI4_DEBUG
+	if (rmi_debugfs_root) {
 		rmi_dev->debugfs_root = debugfs_create_dir(
 			dev_name(&rmi_dev->dev), rmi_debugfs_root);
 		if (!rmi_dev->debugfs_root)
 			dev_err(&rmi_dev->dev, "Failed to create debugfs root.\n");
 	}
+#endif
 
 	phys->rmi_dev = rmi_dev;
 	return device_register(&rmi_dev->dev);
 }
-EXPORT_SYMBOL(rmi_register_phys_device);
+EXPORT_SYMBOL_GPL(rmi_register_phys_device);
 
 /**
  * rmi_unregister_phys_device - unregister a physical device connection
@@ -131,102 +124,84 @@ void rmi_unregister_phys_device(struct rmi_phys_device *phys)
 {
 	struct rmi_device *rmi_dev = phys->rmi_dev;
 
-	if (IS_ENABLED(CONFIG_RMI4_DEBUG) && rmi_dev->debugfs_root)
+#ifdef	CONFIG_RMI4_DEBUG
+	if (rmi_dev->debugfs_root)
 		debugfs_remove(rmi_dev->debugfs_root);
+#endif
 
-	kfree(rmi_dev);
+	device_unregister(&rmi_dev->dev);
 }
-EXPORT_SYMBOL(rmi_unregister_phys_device);
+EXPORT_SYMBOL_GPL(rmi_unregister_phys_device);
 
-/**
- * rmi_register_function_handler - register a handler for an RMI function
- * @handler: RMI handler that should be registered.
- * @module: pointer to module that implements the handler
- * @mod_name: name of the module implementing the handler
- *
- * This function performs additional setup of RMI function handler and
- * registers it with the RMI core so that it can be bound to
- * RMI function devices.
- */
-int __rmi_register_function_handler(struct rmi_function_handler *handler,
-				     struct module *owner,
-				     const char *mod_name)
+static int rmi_bus_match(struct device *dev, struct device_driver *drv)
 {
-	int error;
+	struct rmi_function_driver *fn_drv;
+	struct rmi_function_dev *fn;
 
-	handler->driver.bus = &rmi_bus_type;
-	handler->driver.owner = owner;
-	handler->driver.mod_name = mod_name;
+	/*
+	 * This seems a little broken to me.  It  means a system can only ever
+	 * have one kind of sensor driver.  It'll work for now, but I think in
+	 * the long run we need to revisit this.
+	 */
+	if (dev->type == &rmi_sensor_type && drv == &rmi_sensor_driver.driver)
+		return 1;
 
-	error = driver_register(&handler->driver);
-	if (error) {
-		pr_err("driver_register() failed for %s, error: %d\n",
-			handler->driver.name, error);
-		return error;
-	}
+	if (dev->type != &rmi_function_type)
+		return 0;
 
-	return 0;
-}
-EXPORT_SYMBOL(__rmi_register_function_handler);
+	fn = to_rmi_function_dev(dev);
+	fn_drv = to_rmi_function_driver(drv);
 
-/**
- * rmi_unregister_function_handler - unregister given RMI function handler
- * @handler: RMI handler that should be unregistered.
- *
- * This function unregisters given function handler from RMI core which
- * causes it to be unbound from the function devices.
- */
-void rmi_unregister_function_handler(struct rmi_function_handler *handler)
-{
-	driver_unregister(&handler->driver);
+	return fn->fd.function_number == fn_drv->func;
 }
-EXPORT_SYMBOL(rmi_unregister_function_handler);
 
-
-static int rmi_function_match(struct device *dev, struct device_driver *drv)
+static int rmi_function_probe(struct device *dev)
 {
-	struct rmi_function_handler *handler;
-	struct rmi_function *fn;
+	struct rmi_function_driver *fn_drv;
+	struct rmi_function_dev *fn = to_rmi_function_dev(dev);
 
-	if (dev->type != &rmi_function_type)
-		return 0;
+	fn_drv = to_rmi_function_driver(dev->driver);
 
-	if (drv == &rmi_sensor_driver.driver)
-		return 0;
+	if (fn_drv->probe)
+		return fn_drv->probe(fn);
 
-	fn = to_rmi_function(dev);
-	handler = to_rmi_function_handler(drv);
-
-	return fn->fd.function_number == handler->func;
+	return 0;
 }
 
-static int rmi_function_probe(struct device *dev)
+static int rmi_function_remove(struct device *dev)
 {
-	struct rmi_function *fn = to_rmi_function(dev);
-	struct rmi_function_handler *handler =
-					to_rmi_function_handler(dev->driver);
-	int error;
+	struct rmi_function_driver *fn_drv;
+	struct rmi_function_dev *fn = to_rmi_function_dev(dev);
 
-	if (handler->probe) {
-		error = handler->probe(fn);
-		return error;
-	}
+	fn_drv = to_rmi_function_driver(dev->driver);
+
+	if (fn_drv->remove)
+		return fn_drv->remove(fn);
 
 	return 0;
 }
 
-static int rmi_function_remove(struct device *dev)
+static int rmi_sensor_remove(struct device *dev)
 {
-	struct rmi_function *fn = to_rmi_function(dev);
-	struct rmi_function_handler *handler =
-					to_rmi_function_handler(dev->driver);
+	struct rmi_driver *driver;
+	struct rmi_device *rmi_dev = to_rmi_device(dev);
 
-	if (handler->remove)
-		handler->remove(fn);
+	driver = to_rmi_driver(dev->driver);
 
+	if (!driver->remove)
+		return driver->remove(rmi_dev);
 	return 0;
 }
 
+static int rmi_bus_remove(struct device *dev)
+{
+	if (dev->type == &rmi_function_type)
+		return rmi_function_remove(dev);
+	else if (dev->type == &rmi_sensor_type)
+		return rmi_sensor_remove(dev);
+	return -EINVAL;
+}
+
 #ifdef CONFIG_PM
 static int rmi_bus_suspend(struct device *dev)
 {
@@ -267,12 +242,58 @@ static SIMPLE_DEV_PM_OPS(rmi_bus_pm_ops,
 			 rmi_bus_suspend, rmi_bus_resume);
 
 struct bus_type rmi_bus_type = {
-	.match		= rmi_function_match,
-	.probe		= rmi_function_probe,
-	.remove		= rmi_function_remove,
 	.name		= "rmi",
+	.match		= rmi_bus_match,
+	.remove		= rmi_bus_remove,
 	.pm		= &rmi_bus_pm_ops,
 };
+EXPORT_SYMBOL_GPL(rmi_bus_type);
+
+/**
+ * rmi_register_function_driver - register a driver for an RMI function
+ * @fn_drv: RMI driver that should be registered.
+ * @module: pointer to module that implements the driver
+ * @mod_name: name of the module implementing the driver
+ *
+ * This function performs additional setup of RMI function driver and
+ * registers it with the RMI core so that it can be bound to
+ * RMI function devices.
+ */
+int __rmi_register_function_driver(struct rmi_function_driver *fn_drv,
+				     struct module *owner,
+				     const char *mod_name)
+{
+	int error;
+
+	fn_drv->driver.bus = &rmi_bus_type;
+	fn_drv->driver.owner = owner;
+	if (!fn_drv->driver.probe)
+		fn_drv->driver.probe = rmi_function_probe;
+	fn_drv->driver.mod_name = mod_name;
+
+	error = driver_register(&fn_drv->driver);
+	if (error) {
+		pr_err("driver_register() failed for %s, error: %d\n",
+			fn_drv->driver.name, error);
+		return error;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(__rmi_register_function_driver);
+
+/**
+ * rmi_unregister_function_driver - unregister given RMI function driver
+ * @fn_drv: RMI driver that should be unregistered.
+ *
+ * This function unregisters given function driver from RMI core which
+ * causes it to be unbound from the function devices.
+ */
+void rmi_unregister_function_driver(struct rmi_function_driver *fn_drv)
+{
+	driver_unregister(&fn_drv->driver);
+}
+EXPORT_SYMBOL_GPL(rmi_unregister_function_driver);
 
 /**
  * rmi_for_each_dev - provides a way for other parts of the system to enumerate
@@ -289,7 +310,7 @@ int rmi_for_each_dev(void *data, int (*func)(struct device *dev, void *data))
 	mutex_unlock(&rmi_bus_mutex);
 	return retval;
 }
-EXPORT_SYMBOL(rmi_for_each_dev);
+EXPORT_SYMBOL_GPL(rmi_for_each_dev);
 
 static int __init rmi_bus_init(void)
 {
@@ -304,9 +325,21 @@ static int __init rmi_bus_init(void)
 		return error;
 	}
 
-	error = rmi_register_function_handler(&rmi_f01_handler);
+#ifdef CONFIG_RMI4_DEBUG
+	rmi_debugfs_root = debugfs_create_dir(rmi_bus_type.name, NULL);
+	if (!rmi_debugfs_root)
+		pr_err("%s: Failed to create debugfs root.\n",
+			__func__);
+	else if (IS_ERR(rmi_debugfs_root)) {
+		pr_err("%s: Kernel may not contain debugfs support, code=%ld\n",
+			__func__, PTR_ERR(rmi_debugfs_root));
+		rmi_debugfs_root = NULL;
+	}
+#endif
+
+	error = rmi_register_function_driver(&rmi_f01_driver);
 	if (error) {
-		pr_err("%s: error registering the RMI F01 handler: %d\n",
+		pr_err("%s: error registering the RMI F01 driver: %d\n",
 			__func__, error);
 		goto err_unregister_bus;
 	}
@@ -318,22 +351,10 @@ static int __init rmi_bus_init(void)
 		goto err_unregister_f01;
 	}
 
-	if (IS_ENABLED(CONFIG_RMI4_DEBUG)) {
-		rmi_debugfs_root = debugfs_create_dir(rmi_bus_type.name, NULL);
-		if (!rmi_debugfs_root)
-			pr_err("%s: Failed to create debugfs root.\n",
-			       __func__);
-		else if (IS_ERR(rmi_debugfs_root)) {
-			pr_err("%s: Kernel may not contain debugfs support, code=%ld\n",
-				__func__, PTR_ERR(rmi_debugfs_root));
-			rmi_debugfs_root = NULL;
-		}
-	}
-
 	return 0;
 
 err_unregister_f01:
-	rmi_unregister_function_handler(&rmi_f01_handler);
+	rmi_unregister_function_driver(&rmi_f01_driver);
 err_unregister_bus:
 	bus_unregister(&rmi_bus_type);
 	return error;
@@ -345,11 +366,12 @@ static void __exit rmi_bus_exit(void)
 	 * We should only ever get here if all drivers are unloaded, so
 	 * all we have to do at this point is unregister ourselves.
 	 */
-	if (IS_ENABLED(CONFIG_RMI4_DEBUG) && rmi_debugfs_root)
+#ifdef CONFIG_RMI4_DEBUG
+	if (rmi_debugfs_root)
 		debugfs_remove(rmi_debugfs_root);
-
+#endif
 	rmi_unregister_sensor_driver();
-	rmi_unregister_function_handler(&rmi_f01_handler);
+	rmi_unregister_function_driver(&rmi_f01_driver);
 	bus_unregister(&rmi_bus_type);
 }
 
diff --git a/drivers/input/rmi4/rmi_driver.c b/drivers/input/rmi4/rmi_driver.c
index bbd23f9..8f6a585 100644
--- a/drivers/input/rmi4/rmi_driver.c
+++ b/drivers/input/rmi4/rmi_driver.c
@@ -1,29 +1,17 @@
 /*
- * Copyright (c) 2011, 2012 Synaptics Incorporated
+ * Copyright (c) 2011-2013 Synaptics Incorporated
  * Copyright (c) 2011 Unixphere
  *
- * This driver adds support for generic RMI4 devices from Synpatics. It
- * implements the mandatory f01 RMI register and depends on the presence of
- * other required RMI functions.
+ * This driver provides the core support for a single RMI4-based device.
  *
  * The RMI4 specification can be found here (URL split after files/ for
  * style reasons):
  * http://www.synaptics.com/sites/default/files/
  *           511-000136-01-Rev-E-RMI4%20Intrfacing%20Guide.pdf
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
  */
 
 #include <linux/kernel.h>
@@ -40,7 +28,6 @@
 #include <linux/rmi.h>
 #include <linux/slab.h>
 #include <linux/uaccess.h>
-#include <uapi/linux/input.h>
 #include "rmi_driver.h"
 #include "rmi_f01.h"
 
@@ -55,311 +42,6 @@
 
 #define IRQ_DEBUG(data) (IS_ENABLED(CONFIG_RMI4_DEBUG) && data->irq_debug)
 
-#ifdef	CONFIG_RMI4_DEBUG
-struct driver_debugfs_data {
-	bool done;
-	struct rmi_device *rmi_dev;
-};
-
-static int debug_open(struct inode *inodep, struct file *filp)
-{
-	struct driver_debugfs_data *data;
-	struct rmi_device *rmi_dev;
-
-	rmi_dev = inodep->i_private;
-	data = kzalloc(sizeof(struct driver_debugfs_data),
-				GFP_KERNEL);
-	if (!data)
-		return -ENOMEM;
-
-	data->rmi_dev = inodep->i_private;
-	filp->private_data = data;
-	return 0;
-}
-
-static int debug_release(struct inode *inodep, struct file *filp)
-{
-	kfree(filp->private_data);
-	return 0;
-}
-
-static ssize_t delay_read(struct file *filp, char __user *buffer, size_t size,
-		    loff_t *offset) {
-	struct driver_debugfs_data *data = filp->private_data;
-	struct rmi_device_platform_data *pdata =
-			data->rmi_dev->phys->dev->platform_data;
-	int retval;
-	char *local_buf;
-
-	if (data->done)
-		return 0;
-
-	data->done = 1;
-
-	local_buf = kcalloc(size, sizeof(u8), GFP_KERNEL);
-	if (!local_buf)
-		return -ENOMEM;
-
-	retval = snprintf(local_buf, size, "%d %d %d %d %d\n",
-		pdata->spi_data.read_delay_us, pdata->spi_data.write_delay_us,
-		pdata->spi_data.block_delay_us,
-		pdata->spi_data.pre_delay_us, pdata->spi_data.post_delay_us);
-
-	if (retval <= 0 || copy_to_user(buffer, local_buf, retval))
-		retval = -EFAULT;
-	kfree(local_buf);
-
-	return retval;
-}
-
-static ssize_t delay_write(struct file *filp, const char __user *buffer,
-			   size_t size, loff_t *offset) {
-	struct driver_debugfs_data *data = filp->private_data;
-	struct rmi_device_platform_data *pdata =
-			data->rmi_dev->phys->dev->platform_data;
-	int retval;
-	char *local_buf;
-	unsigned int new_read_delay;
-	unsigned int new_write_delay;
-	unsigned int new_block_delay;
-	unsigned int new_pre_delay;
-	unsigned int new_post_delay;
-
-	local_buf = kcalloc(size, sizeof(u8), GFP_KERNEL);
-	if (!local_buf)
-		return -ENOMEM;
-
-	retval = copy_from_user(local_buf, buffer, size);
-	if (retval) {
-		kfree(local_buf);
-		return -EFAULT;
-	}
-
-	retval = sscanf(local_buf, "%u %u %u %u %u", &new_read_delay,
-			&new_write_delay, &new_block_delay,
-			&new_pre_delay, &new_post_delay);
-	kfree(local_buf);
-
-	if (retval != 5) {
-		dev_err(&data->rmi_dev->dev,
-			"Incorrect number of values provided for delay.");
-		return -EINVAL;
-	}
-	dev_dbg(&data->rmi_dev->dev,
-		 "Setting delays to %u %u %u %u %u.\n", new_read_delay,
-		 new_write_delay, new_block_delay, new_pre_delay,
-		 new_post_delay);
-	pdata->spi_data.read_delay_us = new_read_delay;
-	pdata->spi_data.write_delay_us = new_write_delay;
-	pdata->spi_data.block_delay_us = new_block_delay;
-	pdata->spi_data.pre_delay_us = new_pre_delay;
-	pdata->spi_data.post_delay_us = new_post_delay;
-
-	return size;
-}
-
-static const struct file_operations delay_fops = {
-	.owner = THIS_MODULE,
-	.open = debug_open,
-	.release = debug_release,
-	.read = delay_read,
-	.write = delay_write,
-};
-
-#define PHYS_NAME "phys"
-
-static ssize_t phys_read(struct file *filp, char __user *buffer, size_t size,
-		    loff_t *offset) {
-	struct driver_debugfs_data *data = filp->private_data;
-	struct rmi_phys_info *info = &data->rmi_dev->phys->info;
-	int retval;
-	char *local_buf;
-
-	if (data->done)
-		return 0;
-
-	local_buf = kcalloc(size, sizeof(u8), GFP_KERNEL);
-	if (!local_buf)
-		return -ENOMEM;
-
-	data->done = 1;
-
-	retval = snprintf(local_buf, size,
-		"%-5s %ld %ld %ld %ld %ld %ld\n",
-		 info->proto ? info->proto : "unk",
-		 info->tx_count, info->tx_bytes, info->tx_errs,
-		 info->rx_count, info->rx_bytes, info->rx_errs);
-	if (retval <= 0 || copy_to_user(buffer, local_buf, retval))
-		retval = -EFAULT;
-	kfree(local_buf);
-
-	return retval;
-}
-
-static const struct file_operations phys_fops = {
-	.owner = THIS_MODULE,
-	.open = debug_open,
-	.release = debug_release,
-	.read = phys_read,
-};
-
-static ssize_t attn_count_read(struct file *filp, char __user *buffer,
-		size_t size, loff_t *offset) {
-	struct driver_debugfs_data *data = filp->private_data;
-	struct rmi_driver_data *rmi_data = dev_get_drvdata(&data->rmi_dev->dev);
-	int retval;
-	char *local_buf;
-
-	if (data->done)
-		return 0;
-
-	local_buf = kcalloc(size, sizeof(u8), GFP_KERNEL);
-	if (!local_buf)
-		return -ENOMEM;
-
-	data->done = 1;
-
-	retval = snprintf(local_buf, size, "%d\n",
-			  rmi_data->attn_count.counter);
-	if (retval <= 0 || copy_to_user(buffer, local_buf, retval))
-		retval = -EFAULT;
-	kfree(local_buf);
-
-	return retval;
-}
-
-static const struct file_operations attn_count_fops = {
-	.owner = THIS_MODULE,
-	.open = debug_open,
-	.release = debug_release,
-	.read = attn_count_read,
-};
-
-static ssize_t irq_debug_read(struct file *filp, char __user *buffer,
-			size_t size, loff_t *offset) {
-	int retval;
-	char *local_buf;
-	struct driver_debugfs_data *data = filp->private_data;
-	struct rmi_driver_data *rmi_data = dev_get_drvdata(&data->rmi_dev->dev);
-
-	if (data->done)
-		return 0;
-
-	local_buf = kcalloc(size, sizeof(u8), GFP_KERNEL);
-	if (!local_buf)
-		return -ENOMEM;
-
-	data->done = 1;
-
-	retval = snprintf(local_buf, size, "%u\n", rmi_data->irq_debug);
-
-	if (retval <= 0 || copy_to_user(buffer, local_buf, retval))
-		retval = -EFAULT;
-	kfree(local_buf);
-
-	return retval;
-}
-
-static ssize_t irq_debug_write(struct file *filp, const char __user *buffer,
-			   size_t size, loff_t *offset) {
-	int retval;
-	char *local_buf;
-	unsigned int new_value;
-	struct driver_debugfs_data *data = filp->private_data;
-	struct rmi_driver_data *rmi_data = dev_get_drvdata(&data->rmi_dev->dev);
-
-
-	local_buf = kcalloc(size, sizeof(u8), GFP_KERNEL);
-	if (!local_buf)
-		return -ENOMEM;
-	retval = copy_from_user(local_buf, buffer, size);
-	if (retval) {
-		kfree(local_buf);
-		return -EFAULT;
-	}
-
-	retval = sscanf(local_buf, "%u", &new_value);
-	if (retval != 1 || new_value > 1)
-		retval = -EINVAL;
-	kfree(local_buf);
-	rmi_data->irq_debug = new_value;
-
-	return size;
-}
-
-static const struct file_operations irq_debug_fops = {
-	.owner = THIS_MODULE,
-	.open = debug_open,
-	.release = debug_release,
-	.read = irq_debug_read,
-	.write = irq_debug_write,
-};
-
-static int setup_debugfs(struct rmi_device *rmi_dev)
-{
-	struct rmi_driver_data *data = dev_get_drvdata(&rmi_dev->dev);
-	struct rmi_phys_info *info = &rmi_dev->phys->info;
-	int retval = 0;
-
-	if (!rmi_dev->debugfs_root)
-		return -ENODEV;
-
-	if (IS_ENABLED(CONFIG_RMI4_SPI) && !strncmp("spi", info->proto, 3)) {
-		data->debugfs_delay = debugfs_create_file("delay",
-				RMI_RW_ATTR, rmi_dev->debugfs_root, rmi_dev,
-				&delay_fops);
-		if (!data->debugfs_delay || IS_ERR(data->debugfs_delay)) {
-			dev_warn(&rmi_dev->dev, "Failed to create debugfs delay.\n");
-			data->debugfs_delay = NULL;
-		}
-	}
-
-	data->debugfs_phys = debugfs_create_file(PHYS_NAME, RMI_RO_ATTR,
-				rmi_dev->debugfs_root, rmi_dev, &phys_fops);
-	if (!data->debugfs_phys || IS_ERR(data->debugfs_phys)) {
-		dev_warn(&rmi_dev->dev, "Failed to create debugfs phys.\n");
-		data->debugfs_phys = NULL;
-	}
-
-	data->debugfs_irq = debugfs_create_file("irq_debug",
-			RMI_RW_ATTR,
-			rmi_dev->debugfs_root,
-			rmi_dev, &irq_debug_fops);
-	if (!data->debugfs_irq || IS_ERR(data->debugfs_irq)) {
-		dev_warn(&rmi_dev->dev, "Failed to create debugfs irq_debug.\n");
-		data->debugfs_irq = NULL;
-	}
-
-	data->debugfs_attn_count = debugfs_create_file("attn_count",
-				RMI_RO_ATTR,
-				rmi_dev->debugfs_root,
-				rmi_dev, &attn_count_fops);
-	if (!data->debugfs_phys || IS_ERR(data->debugfs_attn_count)) {
-		dev_warn(&rmi_dev->dev, "Failed to create debugfs attn_count.\n");
-		data->debugfs_attn_count = NULL;
-	}
-
-	return retval;
-}
-
-static void teardown_debugfs(struct rmi_device *rmi_dev)
-{
-	struct rmi_driver_data *data = dev_get_drvdata(&rmi_dev->dev);
-
-	if (IS_ENABLED(CONFIG_RMI4_SPI) && data->debugfs_delay)
-		debugfs_remove(data->debugfs_delay);
-	if (data->debugfs_phys)
-		debugfs_remove(data->debugfs_phys);
-	if (data->debugfs_irq)
-		debugfs_remove(data->debugfs_irq);
-	if (data->debugfs_attn_count)
-		debugfs_remove(data->debugfs_attn_count);
-}
-#else
-#define teardown_debugfs(rmi_dev)
-#define setup_debugfs(rmi_dev) 0
-#endif
-
 static irqreturn_t rmi_irq_thread(int irq, void *p)
 {
 	struct rmi_phys_device *phys = p;
@@ -431,7 +113,7 @@ static void disable_polling(struct rmi_device *rmi_dev)
 	cancel_work_sync(&data->poll_work);
 }
 
-static void disable_sensor(struct rmi_device *rmi_dev)
+void disable_sensor(struct rmi_device *rmi_dev)
 {
 	struct rmi_driver_data *data = dev_get_drvdata(&rmi_dev->dev);
 
@@ -452,7 +134,7 @@ static void disable_sensor(struct rmi_device *rmi_dev)
 	data->enabled = false;
 }
 
-static int enable_sensor(struct rmi_device *rmi_dev)
+int enable_sensor(struct rmi_device *rmi_dev)
 {
 	struct rmi_driver_data *data = dev_get_drvdata(&rmi_dev->dev);
 	struct rmi_phys_device *rmi_phys;
@@ -493,108 +175,9 @@ static int enable_sensor(struct rmi_device *rmi_dev)
 	return retval;
 }
 
-/* sysfs show and store fns for driver attributes */
-
-static ssize_t rmi_driver_bsr_show(struct device *dev,
-				   struct device_attribute *attr, char *buf)
-{
-	struct rmi_device *rmi_dev;
-	struct rmi_driver_data *data;
-	rmi_dev = to_rmi_device(dev);
-	data = dev_get_drvdata(&rmi_dev->dev);
-
-	return snprintf(buf, PAGE_SIZE, "%u\n", data->bsr);
-}
-
-static ssize_t rmi_driver_bsr_store(struct device *dev,
-				    struct device_attribute *attr,
-				    const char *buf, size_t count)
-{
-	int retval;
-	unsigned long val;
-	struct rmi_device *rmi_dev;
-	struct rmi_driver_data *data;
-
-	rmi_dev = to_rmi_device(dev);
-	data = dev_get_drvdata(&rmi_dev->dev);
-
-	/* need to convert the string data to an actual value */
-	retval = strict_strtoul(buf, 10, &val);
-	if (retval < 0 || val > 255) {
-		dev_err(dev, "Invalid value '%s' written to BSR.\n", buf);
-		return -EINVAL;
-	}
-
-	retval = rmi_write(rmi_dev, BSR_LOCATION, (u8)val);
-	if (retval < 0) {
-		dev_err(dev, "%s : failed to write bsr %lu to %#06x\n",
-			__func__, val, BSR_LOCATION);
-		return retval;
-	}
-
-	data->bsr = val;
-
-	return count;
-}
-
-static ssize_t rmi_driver_enabled_show(struct device *dev,
-				       struct device_attribute *attr, char *buf)
-{
-	struct rmi_device *rmi_dev;
-	struct rmi_driver_data *data;
-
-	rmi_dev = to_rmi_device(dev);
-	data = dev_get_drvdata(&rmi_dev->dev);
-
-	return snprintf(buf, PAGE_SIZE, "%u\n", data->enabled);
-}
-
-static ssize_t rmi_driver_enabled_store(struct device *dev,
-					struct device_attribute *attr,
-					const char *buf, size_t count)
-{
-	int retval;
-	int new_value;
-	struct rmi_device *rmi_dev;
-	struct rmi_driver_data *data;
-
-	rmi_dev = to_rmi_device(dev);
-	data = dev_get_drvdata(&rmi_dev->dev);
-
-	if (sysfs_streq(buf, "0"))
-		new_value = false;
-	else if (sysfs_streq(buf, "1"))
-		new_value = true;
-	else
-		return -EINVAL;
-
-	if (new_value) {
-		retval = enable_sensor(rmi_dev);
-		if (retval) {
-			dev_err(dev, "Failed to enable sensor, code=%d.\n",
-				retval);
-			return -EIO;
-		}
-	} else {
-		disable_sensor(rmi_dev);
-	}
-
-	return count;
-}
-
-/** This sysfs attribute is deprecated, and will be removed in a future release.
- */
-static struct device_attribute attrs[] = {
-	__ATTR(enabled, RMI_RW_ATTR,
-	       rmi_driver_enabled_show, rmi_driver_enabled_store),
-};
-
-static struct device_attribute bsr_attribute = __ATTR(bsr, RMI_RW_ATTR,
-	       rmi_driver_bsr_show, rmi_driver_bsr_store);
-
 static void rmi_free_function_list(struct rmi_device *rmi_dev)
 {
-	struct rmi_function *entry, *n;
+	struct rmi_function_dev *entry, *n;
 	struct rmi_driver_data *data = dev_get_drvdata(&rmi_dev->dev);
 
 	if (!data) {
@@ -602,7 +185,7 @@ static void rmi_free_function_list(struct rmi_device *rmi_dev)
 		return;
 	}
 
-	data->f01_container = NULL;
+	data->f01_dev = NULL;
 
 	if (list_empty(&data->rmi_functions.list))
 		return;
@@ -613,44 +196,43 @@ static void rmi_free_function_list(struct rmi_device *rmi_dev)
 	}
 }
 
-static void release_function_device(struct device *dev)
+static void release_fndev_device(struct device *dev)
 {
-	dev_dbg(dev, "REMOVING KOBJ!");
 	kobject_put(&dev->kobj);
 }
 
-static int reset_one_function(struct rmi_function *fn)
+static int reset_one_function(struct rmi_function_dev *fn_dev)
 {
-	struct rmi_function_handler *fh;
+	struct rmi_function_driver *fn_drv;
 	int retval = 0;
 
-	if (!fn || !fn->dev.driver)
+	if (!fn_dev || !fn_dev->dev.driver)
 		return 0;
 
-	fh = to_rmi_function_handler(fn->dev.driver);
-	if (fh->reset) {
-		retval = fh->reset(fn);
+	fn_drv = to_rmi_function_driver(fn_dev->dev.driver);
+	if (fn_drv->reset) {
+		retval = fn_drv->reset(fn_dev);
 		if (retval < 0)
-			dev_err(&fn->dev, "Reset failed with code %d.\n",
+			dev_err(&fn_dev->dev, "Reset failed with code %d.\n",
 				retval);
 	}
 
 	return retval;
 }
 
-static int configure_one_function(struct rmi_function *fn)
+static int configure_one_function(struct rmi_function_dev *fn_dev)
 {
-	struct rmi_function_handler *fh;
+	struct rmi_function_driver *fn_drv;
 	int retval = 0;
 
-	if (!fn || !fn->dev.driver)
+	if (!fn_dev || !fn_dev->dev.driver)
 		return 0;
 
-	fh = to_rmi_function_handler(fn->dev.driver);
-	if (fh->config) {
-		retval = fh->config(fn);
+	fn_drv = to_rmi_function_driver(fn_dev->dev.driver);
+	if (fn_drv->config) {
+		retval = fn_drv->config(fn_dev);
 		if (retval < 0)
-			dev_err(&fn->dev, "Config failed with code %d.\n",
+			dev_err(&fn_dev->dev, "Config failed with code %d.\n",
 				retval);
 	}
 
@@ -660,7 +242,7 @@ static int configure_one_function(struct rmi_function *fn)
 static int rmi_driver_process_reset_requests(struct rmi_device *rmi_dev)
 {
 	struct rmi_driver_data *data = dev_get_drvdata(&rmi_dev->dev);
-	struct rmi_function *entry;
+	struct rmi_function_dev *entry;
 	int retval;
 
 	if (list_empty(&data->rmi_functions.list))
@@ -678,7 +260,7 @@ static int rmi_driver_process_reset_requests(struct rmi_device *rmi_dev)
 static int rmi_driver_process_config_requests(struct rmi_device *rmi_dev)
 {
 	struct rmi_driver_data *data = dev_get_drvdata(&rmi_dev->dev);
-	struct rmi_function *entry;
+	struct rmi_function_dev *entry;
 	int retval;
 
 	if (list_empty(&data->rmi_functions.list))
@@ -693,21 +275,21 @@ static int rmi_driver_process_config_requests(struct rmi_device *rmi_dev)
 	return 0;
 }
 
-static void process_one_interrupt(struct rmi_function *fn,
+static void process_one_interrupt(struct rmi_function_dev *fn_dev,
 		unsigned long *irq_status, struct rmi_driver_data *data)
 {
-	struct rmi_function_handler *fh;
+	struct rmi_function_driver *fn_drv;
 	DECLARE_BITMAP(irq_bits, data->num_of_irq_regs);
 
-	if (!fn || !fn->dev.driver)
+	if (!fn_dev || !fn_dev->dev.driver)
 		return;
 
-	fh = to_rmi_function_handler(fn->dev.driver);
-	if (fn->irq_mask && fh->attention) {
-		bitmap_and(irq_bits, irq_status, fn->irq_mask,
+	fn_drv = to_rmi_function_driver(fn_dev->dev.driver);
+	if (fn_dev->irq_mask && fn_drv->attention) {
+		bitmap_and(irq_bits, irq_status, fn_dev->irq_mask,
 				data->irq_count);
 		if (!bitmap_empty(irq_bits, data->irq_count))
-			fh->attention(fn, irq_bits);
+			fn_drv->attention(fn_dev, irq_bits);
 	}
 }
 
@@ -715,11 +297,11 @@ static int process_interrupt_requests(struct rmi_device *rmi_dev)
 {
 	struct rmi_driver_data *data = dev_get_drvdata(&rmi_dev->dev);
 	struct device *dev = &rmi_dev->dev;
-	struct rmi_function *entry;
+	struct rmi_function_dev *entry;
 	int error;
 
 	error = rmi_read_block(rmi_dev,
-				data->f01_container->fd.data_base_addr + 1,
+				data->f01_dev->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);
@@ -743,8 +325,7 @@ static int process_interrupt_requests(struct rmi_device *rmi_dev)
 	 */
 	list_for_each_entry(entry, &data->rmi_functions.list, list) {
 		if (entry->irq_mask)
-			process_one_interrupt(entry, data->irq_status,
-					      data);
+			process_one_interrupt(entry, data->irq_status, data);
 	}
 
 	return 0;
@@ -786,7 +367,7 @@ static int rmi_driver_irq_save(struct rmi_device *rmi_dev,
 	if (!data->irq_stored) {
 		/* Save current enabled interrupts */
 		retval = rmi_read_block(rmi_dev,
-				data->f01_container->fd.control_base_addr+1,
+				data->f01_dev->fd.control_base_addr+1,
 				data->irq_mask_store, data->num_of_irq_regs);
 		if (retval < 0) {
 			dev_err(dev, "%s: Failed to read enabled interrupts!",
@@ -800,7 +381,7 @@ static int rmi_driver_irq_save(struct rmi_device *rmi_dev,
 		 * to identify them.
 		 */
 		retval = rmi_write_block(rmi_dev,
-				data->f01_container->fd.control_base_addr+1,
+				data->f01_dev->fd.control_base_addr+1,
 				new_ints, data->num_of_irq_regs);
 		if (retval < 0) {
 			dev_err(dev, "%s: Failed to change enabled interrupts!",
@@ -829,7 +410,7 @@ static int rmi_driver_irq_restore(struct rmi_device *rmi_dev)
 
 	if (data->irq_stored) {
 		retval = rmi_write_block(rmi_dev,
-				data->f01_container->fd.control_base_addr+1,
+				data->f01_dev->fd.control_base_addr+1,
 				data->irq_mask_store, data->num_of_irq_regs);
 		if (retval < 0) {
 			dev_err(dev, "%s: Failed to write enabled interupts!",
@@ -858,7 +439,7 @@ static int rmi_driver_irq_handler(struct rmi_device *rmi_dev, int irq)
 	/* Can get called before the driver is fully ready to deal with
 	 * interrupts.
 	 */
-	if (!data || !data->f01_container) {
+	if (!data || !data->f01_dev) {
 		dev_dbg(&rmi_dev->dev,
 			 "Not ready to handle interrupts yet!\n");
 		return 0;
@@ -875,7 +456,7 @@ static int rmi_driver_reset_handler(struct rmi_device *rmi_dev)
 	/* Can get called before the driver is fully ready to deal with
 	 * this situation.
 	 */
-	if (!data || !data->f01_container) {
+	if (!data || !data->f01_dev) {
 		dev_warn(&rmi_dev->dev,
 			 "Not ready to handle reset yet!\n");
 		return 0;
@@ -903,65 +484,66 @@ static int rmi_driver_reset_handler(struct rmi_device *rmi_dev)
  * Construct a function's IRQ mask. This should be called once and stored.
  */
 int rmi_driver_irq_get_mask(struct rmi_device *rmi_dev,
-		struct rmi_function *fn) {
+		struct rmi_function_dev *fn_dev) {
 	int i;
 	struct rmi_driver_data *data = dev_get_drvdata(&rmi_dev->dev);
 
 	/* call devm_kcalloc when it will be defined in kernel in future */
-	fn->irq_mask = devm_kzalloc(&rmi_dev->dev,
+	fn_dev->irq_mask = devm_kzalloc(&rmi_dev->dev,
 			BITS_TO_LONGS(data->irq_count)*sizeof(unsigned long),
 			GFP_KERNEL);
 
-	if (fn->irq_mask) {
-		for (i = 0; i < fn->num_of_irqs; i++)
-			set_bit(fn->irq_pos+i, fn->irq_mask);
-		return 0;
-	} else
+	if (!fn_dev->irq_mask)
 		return -ENOMEM;
+
+	for (i = 0; i < fn_dev->num_of_irqs; i++)
+		set_bit(fn_dev->irq_pos+i, fn_dev->irq_mask);
+	return 0;
 }
 
 static int init_function_device(struct rmi_device *rmi_dev,
-			     struct rmi_function *fn)
+			     struct rmi_function_dev *fn_dev)
 {
 	int retval;
 
 	/* This memset might not be what we want to do... */
-	memset(&fn->dev, 0, sizeof(struct device));
-	dev_set_name(&fn->dev, "%s.fn%02x", dev_name(&rmi_dev->dev),
-			fn->fd.function_number);
-	fn->dev.release = release_function_device;
-
-	fn->dev.parent = &rmi_dev->dev;
-	fn->dev.type = &rmi_function_type;
-	fn->dev.bus = &rmi_bus_type;
-	dev_dbg(&rmi_dev->dev, "Register F%02X.\n", fn->fd.function_number);
-	retval = device_register(&fn->dev);
-	if (retval) {
-		dev_err(&rmi_dev->dev, "Failed device_register for F%02X.\n",
-			fn->fd.function_number);
-		return retval;
-	}
+	memset(&(fn_dev->dev), 0, sizeof(struct device));
+	dev_set_name(&(fn_dev->dev), "%s.fn%02x", dev_name(&rmi_dev->dev),
+			fn_dev->fd.function_number);
+	fn_dev->dev.release = release_fndev_device;
+
+	fn_dev->dev.parent = &rmi_dev->dev;
+	fn_dev->dev.type = &rmi_function_type;
+	fn_dev->dev.bus = &rmi_bus_type;
 
 	if (IS_ENABLED(CONFIG_RMI4_DEBUG)) {
 		char dirname[12];
 
-		snprintf(dirname, 12, "F%02X", fn->fd.function_number);
-		fn->debugfs_root = debugfs_create_dir(dirname,
+		snprintf(dirname, 12, "F%02X", fn_dev->fd.function_number);
+		fn_dev->debugfs_root = debugfs_create_dir(dirname,
 						      rmi_dev->debugfs_root);
-		if (!fn->debugfs_root)
-			dev_warn(&fn->dev, "Failed to create debugfs dir.\n");
+		if (!fn_dev->debugfs_root)
+			dev_warn(&fn_dev->dev, "Failed to create debugfs dir.\n");
+	}
+
+	dev_dbg(&rmi_dev->dev, "Register F%02X.\n", fn_dev->fd.function_number);
+	retval = device_register(&fn_dev->dev);
+	if (retval) {
+		dev_err(&rmi_dev->dev, "Failed device_register for F%02X.\n",
+			fn_dev->fd.function_number);
+		return retval;
 	}
 
 	return 0;
 }
 
-static int create_function(struct rmi_device *rmi_dev,
+static int create_function_dev(struct rmi_device *rmi_dev,
 				     struct pdt_entry *pdt_ptr,
 				     int *current_irq_count,
 				     u16 page_start)
 {
 	struct rmi_driver_data *data = dev_get_drvdata(&rmi_dev->dev);
-	struct rmi_function *fn = NULL;
+	struct rmi_function_dev *fn_dev = NULL;
 	int retval = 0;
 	struct device *dev = &rmi_dev->dev;
 	struct rmi_device_platform_data *pdata;
@@ -971,41 +553,45 @@ static int create_function(struct rmi_device *rmi_dev,
 	dev_dbg(dev, "Initializing F%02X for %s.\n", pdt_ptr->function_number,
 		pdata->sensor_name);
 
-	fn = devm_kzalloc(dev, sizeof(struct rmi_function),
+	fn_dev = devm_kzalloc(dev, sizeof(struct rmi_function_dev),
 			GFP_KERNEL);
-	if (!fn) {
-		dev_err(dev, "Failed to allocate F%02X container.\n",
+	if (!fn_dev) {
+		dev_err(dev, "Failed to allocate F%02X device.\n",
 			pdt_ptr->function_number);
 		return -ENOMEM;
 	}
 
-	copy_pdt_entry_to_fd(pdt_ptr, &fn->fd, page_start);
+	copy_pdt_entry_to_fd(pdt_ptr, &fn_dev->fd, page_start);
 
-	fn->rmi_dev = rmi_dev;
-	fn->num_of_irqs = pdt_ptr->interrupt_source_count;
+	fn_dev->rmi_dev = rmi_dev;
+	fn_dev->num_of_irqs = pdt_ptr->interrupt_source_count;
+	fn_dev->irq_pos = *current_irq_count;
+	*current_irq_count += fn_dev->num_of_irqs;
 
-	fn->irq_pos = *current_irq_count;
-	*current_irq_count += fn->num_of_irqs;
+	retval = rmi_driver_irq_get_mask(rmi_dev, fn_dev);
+	if (retval < 0) {
+		dev_err(dev, "%s: Failed to create irq_mask for F%02X.\n",
+			__func__, pdt_ptr->function_number);
+		return retval;
+	}
 
-	retval = init_function_device(rmi_dev, fn);
+	retval = init_function_device(rmi_dev, fn_dev);
 	if (retval < 0) {
 		dev_err(dev, "Failed to initialize F%02X device.\n",
 			pdt_ptr->function_number);
-		goto error_free_data;
+		return retval;
 	}
 
-	INIT_LIST_HEAD(&fn->list);
+	INIT_LIST_HEAD(&fn_dev->list);
 	/* we need to ensure that F01 is at the head of the list.
 	 */
 	if (pdt_ptr->function_number == 0x01) {
-		list_add(&fn->list, &data->rmi_functions.list);
-		data->f01_container = fn;
+		list_add(&fn_dev->list, &data->rmi_functions.list);
+		data->f01_dev = fn_dev;
 	} else
-		list_add_tail(&fn->list, &data->rmi_functions.list);
-	return 0;
+		list_add_tail(&fn_dev->list, &data->rmi_functions.list);
 
-error_free_data:
-	return retval;
+	return 0;
 }
 
 /*
@@ -1031,41 +617,107 @@ static void check_bootloader_mode(struct rmi_device *rmi_dev,
 	if (device_status.flash_prog)
 		dev_warn(&rmi_dev->dev,
 			 "WARNING: RMI4 device is in bootloader mode!\n");
+
 }
 
 /*
- * 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.
- *
- * At this time, we also reflash the device if (a) in kernel reflashing is
+ * We also reflash the device if (a) in kernel reflashing is
  * enabled, and (b) the reflash module decides it requires reflashing.
  *
  * We have to do this before actually building the PDT because the reflash
  * might cause various registers to move around.
  */
-static int reset_and_reflash(struct rmi_device *rmi_dev)
+static int rmi_device_reflash(struct rmi_device *rmi_dev)
 {
 	struct pdt_entry pdt_entry;
 	int page;
 	struct device *dev = &rmi_dev->dev;
-	bool done = false;
+	bool done;
 	bool has_f01 = false;
 	bool has_f34 = false;
 	struct pdt_entry f34_pdt, f01_pdt;
 	int i;
 	int retval;
 	struct rmi_device_platform_data *pdata;
+	struct rmi_driver_data *data = dev_get_drvdata(&rmi_dev->dev);
 
-	dev_dbg(dev, "Initial reset.\n");
+	dev_dbg(dev, "Initial reflash.\n");
 	pdata = to_rmi_platform_data(rmi_dev);
-	for (page = 0; (page <= RMI4_MAX_PAGE) && !done; page++) {
+	data->f01_bootloader_mode = false;
+	for (page = 0; (page <= RMI4_MAX_PAGE); 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;
+		done = true;
+		for (i = pdt_start; i >= pdt_end ; i -= sizeof(pdt_entry)) {
+			retval = rmi_read_block(rmi_dev, i, &pdt_entry,
+					       sizeof(pdt_entry));
+			if (retval != sizeof(pdt_entry)) {
+				dev_err(dev, "Read PDT entry at %#06x failed, code = %d.\n",
+						i, retval);
+				return retval;
+			}
+
+			if (RMI4_END_OF_PDT(pdt_entry.function_number))
+				break;
+			done = false;
+			if (pdt_entry.function_number == 0x01) {
+				memcpy(&f01_pdt, &pdt_entry, sizeof(pdt_entry));
+				has_f01 = true;
+				check_bootloader_mode(rmi_dev, &pdt_entry,
+						      page_start);
+			} else if (pdt_entry.function_number == 0x34) {
+				memcpy(&f34_pdt, &pdt_entry, sizeof(pdt_entry));
+				has_f34 = true;
+			}
+
+			if (has_f01 && has_f34) {
+				done = true;
+				break;
+			}
+		}
+
+		if (data->f01_bootloader_mode || done)
+			break;
+	}
+
+	if (!has_f01) {
+		dev_warn(dev, "WARNING: Failed to find F01 for initial reflash.\n");
+		return -ENODEV;
+	}
+
+	if (has_f34)
+		rmi4_fw_update(rmi_dev, &f01_pdt, &f34_pdt);
+	else
+		dev_warn(dev, "WARNING: No F34 , firmware update will not be done.\n");
+	return 0;
+}
 
+/*
+ * 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.
+ *
+ */
+static int rmi_device_reset(struct rmi_device *rmi_dev)
+{
+	struct pdt_entry pdt_entry;
+	int page;
+	struct device *dev = &rmi_dev->dev;
+	int i;
+	int retval;
+	bool done = false;
+	struct rmi_device_platform_data *pdata;
+
+	dev_dbg(dev, "Initial reset.\n");
+	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;
 		done = true;
+
 		for (i = pdt_start; i >= pdt_end; i -= sizeof(pdt_entry)) {
 			retval = rmi_read_block(rmi_dev, i, &pdt_entry,
 					       sizeof(pdt_entry));
@@ -1091,39 +743,16 @@ static int reset_and_reflash(struct rmi_device *rmi_dev)
 					return retval;
 				}
 				mdelay(pdata->reset_delay_ms);
-				if (IS_ENABLED(CONFIG_RMI4_FWLIB))
-					memcpy(&f01_pdt, &pdt_entry,
-							sizeof(pdt_entry));
-				else
-					done = true;
-				has_f01 = true;
-				break;
-			} else if (IS_ENABLED(CONFIG_RMI4_FWLIB) &&
-					pdt_entry.function_number == 0x34) {
-				memcpy(&f34_pdt, &pdt_entry, sizeof(pdt_entry));
-				has_f34 = true;
+				return 0;
 			}
 		}
 	}
 
-	if (!has_f01) {
-		dev_warn(dev, "WARNING: Failed to find F01 for initial reset.\n");
-		return -ENODEV;
-	}
-
-	if (IS_ENABLED(CONFIG_RMI4_FWLIB)) {
-		if (has_f34)
-			rmi4_fw_update(rmi_dev, &f01_pdt, &f34_pdt);
-		else
-			dev_warn(dev, "WARNING: No F34, firmware update will not be done.\n");
-	}
-
-	return 0;
+	return -ENODEV;
 }
 
-
-/* extract product ID */
-void get_prod_id(struct rmi_device *rmi_dev, struct rmi_driver_data *drvdata)
+static void get_prod_id(struct rmi_device *rmi_dev,
+			struct rmi_driver_data *drvdata)
 {
 	struct device *dev = &rmi_dev->dev;
 	int retval;
@@ -1134,7 +763,7 @@ void get_prod_id(struct rmi_device *rmi_dev, struct rmi_driver_data *drvdata)
 	u8 product_id[RMI_PRODUCT_ID_LENGTH+1];
 
 	retval = rmi_read_block(rmi_dev,
-		drvdata->f01_container->fd.query_base_addr+
+		drvdata->f01_dev->fd.query_base_addr+
 		sizeof(struct f01_basic_queries),
 		product_id, RMI_PRODUCT_ID_LENGTH);
 	if (retval < 0) {
@@ -1146,7 +775,7 @@ void get_prod_id(struct rmi_device *rmi_dev, struct rmi_driver_data *drvdata)
 	for (i = 0; i < sizeof(product_id); i++)
 		product_id[i] = tolower(product_id[i]);
 
-	for (i = 0; i < sizeof(pattern); i++) {
+	for (i = 0; i < ARRAY_SIZE(pattern); i++) {
 		retval = sscanf(product_id, pattern[i], &board, &rev);
 		if (retval)
 			break;
@@ -1158,6 +787,55 @@ void get_prod_id(struct rmi_device *rmi_dev, struct rmi_driver_data *drvdata)
 		drvdata->board, drvdata->rev);
 }
 
+static int rmi_count_irqs(struct rmi_device *rmi_dev)
+{
+	struct rmi_driver_data *data;
+	struct pdt_entry pdt_entry;
+	int page;
+	struct device *dev = &rmi_dev->dev;
+	int irq_count = 0;
+	bool done = false;
+	int i;
+	int retval;
+
+	data = dev_get_drvdata(&rmi_dev->dev);
+	mutex_lock(&data->pdt_mutex);
+
+	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;
+
+		done = true;
+		for (i = pdt_start; i >= pdt_end; i -= sizeof(pdt_entry)) {
+			retval = rmi_read_block(rmi_dev, i, &pdt_entry,
+					       sizeof(pdt_entry));
+			if (retval != sizeof(pdt_entry)) {
+				dev_err(dev, "Read of PDT entry at %#06x failed.\n",
+					i);
+				goto error_exit;
+			}
+
+			if (RMI4_END_OF_PDT(pdt_entry.function_number))
+				break;
+			irq_count += pdt_entry.interrupt_source_count;
+			done = false;
+
+			if (pdt_entry.function_number == 0x01)
+				check_bootloader_mode(rmi_dev, &pdt_entry,
+						      page_start);
+		}
+		done = done || data->f01_bootloader_mode;
+	}
+	data->irq_count = irq_count;
+	data->num_of_irq_regs = (irq_count + 7) / 8;
+	retval = 0;
+
+error_exit:
+	mutex_unlock(&data->pdt_mutex);
+	return retval;
+}
+
 static int rmi_scan_pdt(struct rmi_device *rmi_dev)
 {
 	struct rmi_driver_data *data;
@@ -1201,7 +879,7 @@ static int rmi_scan_pdt(struct rmi_device *rmi_dev)
 						      page_start);
 
 
-			retval = create_function(rmi_dev,
+			retval = create_function_dev(rmi_dev,
 					&pdt_entry, &irq_count, page_start);
 
 			if (retval)
@@ -1212,8 +890,6 @@ static int rmi_scan_pdt(struct rmi_device *rmi_dev)
 		}
 		done = done || data->f01_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;
 
@@ -1226,23 +902,21 @@ static int f01_notifier_call(struct notifier_block *nb,
 				unsigned long action, void *data)
 {
 	struct device *dev = data;
-	struct rmi_function *fn;
+	struct rmi_function_dev *fn_dev;
 
 	if (dev->type != &rmi_function_type)
 		return 0;
 
-	fn = to_rmi_function(dev);
-	if (fn->fd.function_number != 0x01)
+	fn_dev = to_rmi_function_dev(dev);
+	if (fn_dev->fd.function_number != 0x01)
 		return 0;
 
 	switch (action) {
 	case BUS_NOTIFY_BOUND_DRIVER:
-		dev_dbg(dev, "%s: F01 driver bound.\n", __func__);
-		enable_sensor(fn->rmi_dev);
+		enable_sensor(fn_dev->rmi_dev);
 		break;
 	case BUS_NOTIFY_UNBIND_DRIVER:
-		dev_dbg(dev, "%s: F01 driver going away.\n", __func__);
-		disable_sensor(fn->rmi_dev);
+		disable_sensor(fn_dev->rmi_dev);
 		break;
 	}
 	return 0;
@@ -1253,20 +927,20 @@ static struct notifier_block rmi_bus_notifier = {
 };
 
 #ifdef CONFIG_PM
-static int suspend_one_device(struct rmi_function *fn)
+static int suspend_one_device(struct rmi_function_dev *fn_dev)
 {
-	struct rmi_function_handler *fh;
+	struct rmi_function_driver *fn_drv;
 	int retval = 0;
 
-	if (!fn->dev.driver)
+	if (!fn_dev->dev.driver)
 		return 0;
 
-	fh = to_rmi_function_handler(fn->dev.driver);
+	fn_drv = to_rmi_function_driver(fn_dev->dev.driver);
 
-	if (fh->suspend) {
-		retval = fh->suspend(fn);
+	if (fn_drv->suspend) {
+		retval = fn_drv->suspend(fn_dev);
 		if (retval < 0)
-			dev_err(&fn->dev, "Suspend failed, code: %d",
+			dev_err(&fn_dev->dev, "Suspend failed, code: %d",
 				retval);
 	}
 
@@ -1276,7 +950,7 @@ static int suspend_one_device(struct rmi_function *fn)
 static int rmi_driver_suspend(struct device *dev)
 {
 	struct rmi_driver_data *data;
-	struct rmi_function *entry;
+	struct rmi_function_dev *entry;
 	int retval = 0;
 	struct rmi_device *rmi_dev = to_rmi_device(dev);
 
@@ -1309,20 +983,20 @@ exit:
 	return retval;
 }
 
-static int resume_one_device(struct rmi_function *fn)
+static int resume_one_device(struct rmi_function_dev *fn_dev)
 {
-	struct rmi_function_handler *fh;
+	struct rmi_function_driver *fn_drv;
 	int retval = 0;
 
-	if (!fn->dev.driver)
+	if (!fn_dev->dev.driver)
 		return 0;
 
-	fh = to_rmi_function_handler(fn->dev.driver);
+	fn_drv = to_rmi_function_driver(fn_dev->dev.driver);
 
-	if (fh->resume) {
-		retval = fh->resume(fn);
+	if (fn_drv->resume) {
+		retval = fn_drv->resume(fn_dev);
 		if (retval < 0)
-			dev_err(&fn->dev, "Resume failed, code: %d",
+			dev_err(&fn_dev->dev, "Resume failed, code: %d",
 				retval);
 	}
 
@@ -1332,7 +1006,7 @@ static int resume_one_device(struct rmi_function *fn)
 static int rmi_driver_resume(struct device *dev)
 {
 	struct rmi_driver_data *data;
-	struct rmi_function *entry;
+	struct rmi_function_dev *entry;
 	int retval = 0;
 	struct rmi_device *rmi_dev = to_rmi_device(dev);
 
@@ -1357,7 +1031,6 @@ static int rmi_driver_resume(struct device *dev)
 	if (retval)
 		goto exit;
 
-
 	if (data->post_resume) {
 		retval = data->post_resume(data->pm_data);
 		if (retval)
@@ -1372,24 +1045,12 @@ exit:
 
 #endif /* CONFIG_PM */
 
-static int __devexit rmi_driver_remove(struct device *dev)
+static int rmi_driver_remove(struct rmi_device *rmi_dev)
 {
-	struct rmi_driver_data *data;
-	int i;
-	struct rmi_device *rmi_dev = to_rmi_device(dev);
-
-	data = dev_get_drvdata(&rmi_dev->dev);
-
 	disable_sensor(rmi_dev);
 
-	if (IS_ENABLED(CONFIG_RMI4_DEBUG))
-		teardown_debugfs(rmi_dev);
 
 	rmi_free_function_list(rmi_dev);
-	for (i = 0; i < ARRAY_SIZE(attrs); i++)
-		device_remove_file(&rmi_dev->dev, &attrs[i]);
-	if (data->pdt_props.has_bsr)
-		device_remove_file(&rmi_dev->dev, &bsr_attribute);
 	return 0;
 }
 
@@ -1397,22 +1058,17 @@ static int __devinit rmi_driver_probe(struct device *dev)
 {
 	struct rmi_driver *rmi_driver;
 	struct rmi_driver_data *data = NULL;
-	struct rmi_function *fn;
 	struct rmi_device_platform_data *pdata;
 	int retval = 0;
-	int attr_count = 0;
 	struct rmi_device *rmi_dev;
 
-	dev_dbg(dev, "%s: Starting probe.\n", __func__);
 	if (!dev->driver) {
 		dev_err(dev, "No driver for RMI4 device during probe!\n");
 		return -ENODEV;
 	}
 
-	if (dev->type != &rmi_sensor_type) {
-		dev_dbg(dev, "Not a sensor device.\n");
-		return 1;
-	}
+	if (dev->type != &rmi_sensor_type)
+		return -ENODEV;
 
 	rmi_dev = to_rmi_device(dev);
 	rmi_driver = to_rmi_driver(dev->driver);
@@ -1447,32 +1103,13 @@ static int __devinit rmi_driver_probe(struct device *dev)
 	 */
 	if (!pdata->reset_delay_ms)
 		pdata->reset_delay_ms = DEFAULT_RESET_DELAY_MS;
-	retval = reset_and_reflash(rmi_dev);
+	retval = rmi_device_reset(rmi_dev);
 	if (retval)
 		dev_warn(dev, "RMI initial reset failed! Continuing in spite of this.\n");
 
-
-	retval = rmi_scan_pdt(rmi_dev);
-	if (retval) {
-		dev_err(dev, "PDT scan for %s failed with code %d.\n",
-			pdata->sensor_name, retval);
-		goto err_free_data;
-	}
-
-	if (!data->f01_container) {
-		dev_err(dev, "missing F01 container!\n");
-		retval = -EINVAL;
-		goto err_free_data;
-	}
-
-	list_for_each_entry(fn, &data->rmi_functions.list, list) {
-		retval = rmi_driver_irq_get_mask(rmi_dev, fn);
-		if (retval < 0) {
-			dev_err(dev, "%s: Failed to create irq_mask.\n",
-				__func__);
-			goto err_free_data;
-		}
-	}
+	retval = rmi_device_reflash(rmi_dev);
+	if (retval)
+		dev_warn(dev, "RMI reflash failed! Continuing in spite of this.\n");
 
 	retval = rmi_read(rmi_dev, PDT_PROPERTIES_LOCATION, &data->pdt_props);
 	if (retval < 0) {
@@ -1483,22 +1120,29 @@ static int __devinit rmi_driver_probe(struct device *dev)
 			 PDT_PROPERTIES_LOCATION);
 	}
 
-	dev_dbg(dev, "%s: Creating sysfs files.", __func__);
-	for (attr_count = 0; attr_count < ARRAY_SIZE(attrs); attr_count++) {
-		retval = device_create_file(dev, &attrs[attr_count]);
-		if (retval < 0) {
-			dev_err(dev, "%s: Failed to create sysfs file %s.\n",
-				__func__, attrs[attr_count].attr.name);
-			goto err_free_data;
-		}
-	}
-	if (data->pdt_props.has_bsr) {
-		retval = device_create_file(dev, &bsr_attribute);
-		if (retval < 0) {
-			dev_err(dev, "%s: Failed to create sysfs file bsr.\n",
-				__func__);
-			goto err_free_data;
+	if (pdata->attn_gpio) {
+		data->irq = gpio_to_irq(pdata->attn_gpio);
+		if (pdata->level_triggered) {
+			data->irq_flags = IRQF_ONESHOT |
+				((pdata->attn_polarity == RMI_ATTN_ACTIVE_HIGH)
+				? IRQF_TRIGGER_HIGH : IRQF_TRIGGER_LOW);
+		} else {
+			data->irq_flags =
+				(pdata->attn_polarity == RMI_ATTN_ACTIVE_HIGH)
+				? IRQF_TRIGGER_RISING : IRQF_TRIGGER_FALLING;
 		}
+		dev_dbg(dev, "Mapped IRQ %d for GPIO %d.\n",
+			data->irq, pdata->attn_gpio);
+	} else
+		data->poll_interval = ktime_set(0,
+			(pdata->poll_interval_ms ? pdata->poll_interval_ms :
+			DEFAULT_POLL_INTERVAL_MS) * 1000);
+
+	retval = rmi_count_irqs(rmi_dev);
+	if (retval) {
+		dev_err(dev, "IRQ counting for %s failed with code %d.\n",
+			pdata->sensor_name, retval);
+		goto err_free_data;
 	}
 
 	mutex_init(&data->irq_mutex);
@@ -1511,8 +1155,7 @@ static int __devinit rmi_driver_probe(struct device *dev)
 		goto err_free_data;
 	}
 
-	data->current_irq_mask = devm_kzalloc(dev,
-				data->num_of_irq_regs,
+	data->current_irq_mask = devm_kzalloc(dev, data->num_of_irq_regs,
 				GFP_KERNEL);
 	if (!data->current_irq_mask) {
 		dev_err(dev, "Failed to allocate current_irq_mask.\n");
@@ -1520,15 +1163,6 @@ static int __devinit rmi_driver_probe(struct device *dev)
 		goto err_free_data;
 	}
 
-	retval = rmi_read_block(rmi_dev,
-				data->f01_container->fd.control_base_addr+1,
-				data->current_irq_mask, data->num_of_irq_regs);
-	if (retval < 0) {
-		dev_err(dev, "%s: Failed to read current IRQ mask.\n",
-			__func__);
-		goto err_free_data;
-	}
-
 	data->irq_mask_store = devm_kzalloc(dev,
 		BITS_TO_LONGS(data->irq_count)*sizeof(unsigned long),
 		GFP_KERNEL);
@@ -1537,6 +1171,29 @@ static int __devinit rmi_driver_probe(struct device *dev)
 		retval = -ENOMEM;
 		goto err_free_data;
 	}
+
+	retval = rmi_scan_pdt(rmi_dev);
+	if (retval) {
+		dev_err(dev, "PDT scan for %s failed with code %d.\n",
+			pdata->sensor_name, retval);
+		goto err_free_data;
+	}
+
+	if (!data->f01_dev) {
+		dev_err(dev, "missing F01 device!\n");
+		retval = -EINVAL;
+		goto err_free_data;
+	}
+
+	retval = rmi_read_block(rmi_dev,
+				data->f01_dev->fd.control_base_addr+1,
+				data->current_irq_mask, data->num_of_irq_regs);
+	if (retval < 0) {
+		dev_err(dev, "%s: Failed to read current IRQ mask.\n",
+			__func__);
+		goto err_free_data;
+	}
+
 	if (IS_ENABLED(CONFIG_PM)) {
 		data->pm_data = pdata->pm_data;
 		data->pre_suspend = pdata->pre_suspend;
@@ -1547,34 +1204,11 @@ static int __devinit rmi_driver_probe(struct device *dev)
 		mutex_init(&data->suspend_mutex);
 	}
 
-	if (pdata->attn_gpio) {
-		data->irq = gpio_to_irq(pdata->attn_gpio);
-		if (pdata->level_triggered) {
-			data->irq_flags = IRQF_ONESHOT |
-				((pdata->attn_polarity == RMI_ATTN_ACTIVE_HIGH)
-				? IRQF_TRIGGER_HIGH : IRQF_TRIGGER_LOW);
-		} else {
-			data->irq_flags =
-				(pdata->attn_polarity == RMI_ATTN_ACTIVE_HIGH)
-				? IRQF_TRIGGER_RISING : IRQF_TRIGGER_FALLING;
-		}
-	} else
-		data->poll_interval = ktime_set(0,
-			(pdata->poll_interval_ms ? pdata->poll_interval_ms :
-			DEFAULT_POLL_INTERVAL_MS) * 1000);
-
-	if (data->f01_container->dev.driver) {
+	if (data->f01_dev->dev.driver) {
 		/* Driver already bound, so enable ATTN now. */
 		enable_sensor(rmi_dev);
 	}
 
-	if (IS_ENABLED(CONFIG_RMI4_DEBUG)) {
-		retval = setup_debugfs(rmi_dev);
-		if (retval < 0)
-			dev_warn(&fn->dev, "Failed to setup debugfs. Code: %d.\n",
-				retval);
-	}
-
 	if (IS_ENABLED(CONFIG_RMI4_DEV) && pdata->attn_gpio) {
 		retval = gpio_export(pdata->attn_gpio, false);
 		if (retval) {
@@ -1598,10 +1232,6 @@ static int __devinit rmi_driver_probe(struct device *dev)
 
  err_free_data:
 	rmi_free_function_list(rmi_dev);
-	for (attr_count--; attr_count >= 0; attr_count--)
-		device_remove_file(dev, &attrs[attr_count]);
-	if (data->pdt_props.has_bsr)
-		device_remove_file(dev, &bsr_attribute);
 	return retval;
 }
 
@@ -1615,32 +1245,32 @@ struct rmi_driver rmi_sensor_driver = {
 		.bus = &rmi_bus_type,
 		.pm = &rmi_driver_pm,
 		.probe = rmi_driver_probe,
-		.remove = __devexit_p(rmi_driver_remove),
 	},
 	.irq_handler = rmi_driver_irq_handler,
 	.reset_handler = rmi_driver_reset_handler,
 	.store_irq_mask = rmi_driver_irq_save,
 	.restore_irq_mask = rmi_driver_irq_restore,
 	.set_input_params = rmi_driver_set_input_params,
+	.remove = rmi_driver_remove,
 };
 
 int __init rmi_register_sensor_driver(void)
 {
-	int error;
+	int retval;
 
-	error = driver_register(&rmi_sensor_driver.driver);
-	if (error) {
+	retval = driver_register(&rmi_sensor_driver.driver);
+	if (retval) {
 		pr_err("%s: driver register failed, code=%d.\n", __func__,
-		       error);
-		return error;
+		       retval);
+		return retval;
 	}
 
 	/* Ask the bus to let us know when drivers are bound to devices. */
-	error = bus_register_notifier(&rmi_bus_type, &rmi_bus_notifier);
-	if (error) {
+	retval = bus_register_notifier(&rmi_bus_type, &rmi_bus_notifier);
+	if (retval) {
 		pr_err("%s: failed to register bus notifier, code=%d.\n",
-		       __func__, error);
-		return error;
+		       __func__, retval);
+		return retval;
 	}
 
 	return 0;
diff --git a/drivers/input/rmi4/rmi_driver.h b/drivers/input/rmi4/rmi_driver.h
index 2866f7d..e709a63 100644
--- a/drivers/input/rmi4/rmi_driver.h
+++ b/drivers/input/rmi4/rmi_driver.h
@@ -2,20 +2,11 @@
  * Copyright (c) 2011, 2012 Synaptics Incorporated
  * Copyright (c) 2011 Unixphere
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
  */
+
 #ifndef _RMI_DRIVER_H
 #define _RMI_DRIVER_H
 
@@ -23,7 +14,7 @@
 #include <linux/hrtimer.h>
 #include <linux/ktime.h>
 
-#define RMI_DRIVER_VERSION "1.6"
+#define RMI_DRIVER_VERSION "1.7"
 
 #define SYNAPTICS_INPUT_DEVICE_NAME "Synaptics RMI4 Touch Sensor"
 #define SYNAPTICS_VENDOR_ID 0x06cb
@@ -32,8 +23,6 @@
 	.attrs = _attrs,  \
 }
 
-#define attrify(nm) (&dev_attr_##nm.attr)
-
 #define PDT_PROPERTIES_LOCATION 0x00EF
 #define BSR_LOCATION 0x00FE
 
@@ -44,14 +33,14 @@ struct pdt_properties {
 } __attribute__((__packed__));
 
 struct rmi_driver_data {
-	struct rmi_function rmi_functions;
+	struct rmi_function_dev rmi_functions;
 	struct rmi_device *rmi_dev;
 
-	struct rmi_function *f01_container;
+	struct rmi_function_dev *f01_dev;
 	bool f01_bootloader_mode;
 
 	atomic_t attn_count;
-	bool irq_debug;
+	u32 irq_debug;
 	int irq;
 	int irq_flags;
 	int num_of_irq_regs;
@@ -66,7 +55,6 @@ struct rmi_driver_data {
 	struct hrtimer poll_timer;
 	struct work_struct poll_work;
 	ktime_t poll_interval;
-
 	struct mutex pdt_mutex;
 	struct pdt_properties pdt_props;
 	u8 bsr;
@@ -133,11 +121,11 @@ static inline void copy_pdt_entry_to_fd(struct pdt_entry *pdt,
 extern void rmi4_fw_update(struct rmi_device *rmi_dev,
 		struct pdt_entry *f01_pdt, struct pdt_entry *f34_pdt);
 #else
-#define rmi4_fw_update(rmi_dev, f01_pdt, f34_pdt)
+#define rmi4_fw_update(rmi_dev, f01_pdt, f34_pdt) 0
 #endif
 
 extern struct rmi_driver rmi_sensor_driver;
-extern struct rmi_function_handler rmi_f01_handler;
+extern struct rmi_function_driver rmi_f01_driver;
 
 int rmi_register_sensor_driver(void);
 void rmi_unregister_sensor_driver(void);

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 03/05] input: RMI4 I2C physical layer
  2013-01-19  1:12 [PATCH 00/05] input: RMI4 Synaptics RMI4 Touchscreen Driver Christopher Heiny
  2013-01-19  1:12 ` [PATCH 01/05] input: RMI4 public header file Christopher Heiny
  2013-01-19  1:12 ` [PATCH 02/05] input: RMI4 core files Christopher Heiny
@ 2013-01-19  1:12 ` Christopher Heiny
  2013-01-19  1:12 ` [PATCH 04/05] input: RMI4 F01 device control Christopher Heiny
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 11+ messages in thread
From: Christopher Heiny @ 2013-01-19  1:12 UTC (permalink / raw)
  To: Dmitry Torokhov
  Cc: Jean Delvare, Linux Kernel, Linux Input, Christopher Heiny,
	Allie Xiong, Vivian Ly, Daniel Rosenberg, Alexandra Chin,
	Joerie de Gram, Wolfram Sang, Mathieu Poirier, Linus Walleij

Changes here are limited to those described in the 0/5 of this patchset, plus
some tweaks to debugging output.

Signed-off-by: Christopher Heiny <cheiny@synaptics.com>
Cc: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Cc: Linus Walleij <linus.walleij@stericsson.com>
Cc: Joeri de Gram <j.de.gram@gmail.com>
Acked-by: Jean Delvare <khali@linux-fr.org>

---

 drivers/input/rmi4/rmi_i2c.c |  141 ++++++------------------------------------
 1 files changed, 20 insertions(+), 121 deletions(-)

diff --git a/drivers/input/rmi4/rmi_i2c.c b/drivers/input/rmi4/rmi_i2c.c
index ca32101..513791c 100644
--- a/drivers/input/rmi4/rmi_i2c.c
+++ b/drivers/input/rmi4/rmi_i2c.c
@@ -2,19 +2,9 @@
  * Copyright (c) 2011, 2012 Synaptics Incorporated
  * Copyright (c) 2011 Unixphere
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
  */
 
 #include <linux/kernel.h>
@@ -58,7 +48,7 @@ struct rmi_i2c_data {
 	u8 *debug_buf;
 	int debug_buf_size;
 
-	bool comms_debug;
+	u32 comms_debug;
 #ifdef CONFIG_RMI4_DEBUG
 	struct dentry *debugfs_comms;
 #endif
@@ -66,107 +56,13 @@ struct rmi_i2c_data {
 
 #ifdef CONFIG_RMI4_DEBUG
 
-
-/**
- * struct i2c_debugfs_data - stores information for debugfs
- *
- * @done: Indicates that we are done reading debug data. Subsequent reads
- * will return EOF.
- * @i2c_data: Pointer to the i2c data
- *
- */
-struct i2c_debugfs_data {
-	bool done;
-	struct rmi_i2c_data *i2c_data;
-};
-
-static int debug_open(struct inode *inodep, struct file *filp)
-{
-	struct i2c_debugfs_data *data;
-
-	data = kzalloc(sizeof(struct i2c_debugfs_data), GFP_KERNEL);
-	if (!data)
-		return -ENOMEM;
-
-	data->i2c_data = inodep->i_private;
-	filp->private_data = data;
-	return 0;
-}
-
-static int debug_release(struct inode *inodep, struct file *filp)
-{
-	kfree(filp->private_data);
-	return 0;
-}
-
-static ssize_t comms_debug_read(struct file *filp, char __user *buffer,
-		size_t size, loff_t *offset) {
-	int retval;
-	char *local_buf;
-	struct i2c_debugfs_data *dfs = filp->private_data;
-	struct rmi_i2c_data *data = dfs->i2c_data;
-
-	if (dfs->done)
-		return 0;
-
-	local_buf = kcalloc(size, sizeof(u8), GFP_KERNEL);
-	if (!local_buf)
-		return -ENOMEM;
-
-	dfs->done = 1;
-
-	retval = snprintf(local_buf, PAGE_SIZE, "%u\n", data->comms_debug);
-
-	if (retval <= 0 || copy_to_user(buffer, local_buf, retval))
-		retval = -EFAULT;
-	kfree(local_buf);
-
-	return retval;
-}
-
-static ssize_t comms_debug_write(struct file *filp, const char __user *buffer,
-			   size_t size, loff_t *offset) {
-	int retval;
-	char *local_buf;
-	unsigned int new_value;
-	struct i2c_debugfs_data *dfs = filp->private_data;
-	struct rmi_i2c_data *data = dfs->i2c_data;
-
-	local_buf = kcalloc(size, sizeof(u8), GFP_KERNEL);
-	if (!local_buf)
-		return -ENOMEM;
-	retval = copy_from_user(local_buf, buffer, size);
-	if (retval) {
-		kfree(local_buf);
-		return -EFAULT;
-	}
-
-	retval = sscanf(local_buf, "%u", &new_value);
-	kfree(local_buf);
-	if (retval != 1 || new_value > 1)
-		return -EINVAL;
-
-	data->comms_debug = new_value;
-
-	return size;
-}
-
-
-static const struct file_operations comms_debug_fops = {
-	.owner = THIS_MODULE,
-	.open = debug_open,
-	.release = debug_release,
-	.read = comms_debug_read,
-	.write = comms_debug_write,
-};
-
 static int setup_debugfs(struct rmi_device *rmi_dev, struct rmi_i2c_data *data)
 {
 	if (!rmi_dev->debugfs_root)
 		return -ENODEV;
 
-	data->debugfs_comms = debugfs_create_file("comms_debug", RMI_RW_ATTR,
-			rmi_dev->debugfs_root, data, &comms_debug_fops);
+	data->debugfs_comms = debugfs_create_bool("comms_debug", RMI_RW_ATTR,
+			rmi_dev->debugfs_root, &data->comms_debug);
 	if (!data->debugfs_comms || IS_ERR(data->debugfs_comms)) {
 		dev_warn(&rmi_dev->dev, "Failed to create debugfs comms_debug.\n");
 		data->debugfs_comms = NULL;
@@ -180,6 +76,9 @@ static void teardown_debugfs(struct rmi_i2c_data *data)
 	if (data->debugfs_comms)
 		debugfs_remove(data->debugfs_comms);
 }
+#else
+#define setup_debugfs(rmi_dev, data) 0
+#define teardown_debugfs(data)
 #endif
 
 #define COMMS_DEBUG(data) (IS_ENABLED(CONFIG_RMI4_DEBUG) && data->comms_debug)
@@ -286,8 +185,8 @@ static int rmi_i2c_write_block(struct rmi_phys_device *phys, u16 addr,
 	}
 
 	if (COMMS_DEBUG(data)) {
-		retval = copy_to_debug_buf(&client->dev, data, (u8 *) buf, len);
-		if (!retval)
+		int rc = copy_to_debug_buf(&client->dev, data, (u8 *) buf, len);
+		if (!rc)
 			dev_dbg(&client->dev, "writes %d bytes at %#06x:%s\n",
 				len, addr, data->debug_buf);
 	}
@@ -341,8 +240,8 @@ static int rmi_i2c_read_block(struct rmi_phys_device *phys, u16 addr,
 	if (retval < 0)
 		phys->info.rx_errs++;
 	else if (COMMS_DEBUG(data)) {
-		retval = copy_to_debug_buf(&client->dev, data, (u8 *) buf, len);
-		if (!retval)
+		int rc = copy_to_debug_buf(&client->dev, data, (u8 *) buf, len);
+		if (!rc)
 			dev_dbg(&client->dev, "read %d bytes at %#06x:%s\n",
 				len, addr, data->debug_buf);
 	}
@@ -369,7 +268,7 @@ static int __devinit rmi_i2c_probe(struct i2c_client *client,
 		client->addr, pdata->attn_gpio);
 
 	if (pdata->gpio_config) {
-		dev_info(&client->dev, "Configuring GPIOs.\n");
+		dev_dbg(&client->dev, "Configuring GPIOs.\n");
 		retval = pdata->gpio_config(pdata->gpio_data, true);
 		if (retval < 0) {
 			dev_err(&client->dev, "Failed to configure GPIOs, code: %d.\n",
@@ -419,15 +318,16 @@ static int __devinit rmi_i2c_probe(struct i2c_client *client,
 
 	retval = rmi_register_phys_device(rmi_phys);
 	if (retval) {
-		dev_err(&client->dev,
-			"failed to register physical driver at 0x%.2X.\n",
+		dev_err(&client->dev, "Failed to register physical driver at 0x%.2X.\n",
 			client->addr);
 		goto err_gpio;
 	}
 	i2c_set_clientdata(client, rmi_phys);
 
-	if (IS_ENABLED(CONFIG_RMI4_DEBUG))
-		retval = setup_debugfs(rmi_phys->rmi_dev, data);
+	retval = setup_debugfs(rmi_phys->rmi_dev, data);
+	if (retval < 0)
+		dev_warn(&client->dev, "Failed to setup debugfs. Code: %d.\n",
+			 retval);
 
 	dev_info(&client->dev, "registered rmi i2c driver at %#04x.\n",
 			client->addr);
@@ -444,8 +344,7 @@ static int __devexit rmi_i2c_remove(struct i2c_client *client)
 	struct rmi_phys_device *phys = i2c_get_clientdata(client);
 	struct rmi_device_platform_data *pd = client->dev.platform_data;
 
-	if (IS_ENABLED(CONFIG_RMI4_DEBUG))
-		teardown_debugfs(phys->data);
+	teardown_debugfs(phys->data);
 
 	rmi_unregister_phys_device(phys);
 

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 04/05] input: RMI4 F01 device control
  2013-01-19  1:12 [PATCH 00/05] input: RMI4 Synaptics RMI4 Touchscreen Driver Christopher Heiny
                   ` (2 preceding siblings ...)
  2013-01-19  1:12 ` [PATCH 03/05] input: RMI4 I2C physical layer Christopher Heiny
@ 2013-01-19  1:12 ` Christopher Heiny
  2013-01-31  8:08   ` Dmitry Torokhov
  2013-01-19  1:12 ` [PATCH 05/05] input: RMI4 F11 2D input Christopher Heiny
  2014-02-04  7:56 ` [PATCH 00/05] input: RMI4 Synaptics RMI4 Touchscreen Driver Linus Walleij
  5 siblings, 1 reply; 11+ messages in thread
From: Christopher Heiny @ 2013-01-19  1:12 UTC (permalink / raw)
  To: Dmitry Torokhov
  Cc: Jean Delvare, Linux Kernel, Linux Input, Christopher Heiny,
	Allie Xiong, Vivian Ly, Daniel Rosenberg, Alexandra Chin,
	Joerie de Gram, Wolfram Sang, Mathieu Poirier, Linus Walleij

In addition to the changes described in 0/0 of this patchset, this patch
includes device serialization updated to conform to the latest RMI4
specification.

Signed-off-by: Christopher Heiny <cheiny@synaptics.com>
Cc: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Cc: Linus Walleij <linus.walleij@stericsson.com>
Cc: Joeri de Gram <j.de.gram@gmail.com>
Acked-by: Jean Delvare <khali@linux-fr.org>

---

 drivers/input/rmi4/rmi_f01.c | 1113 ++++++------------------------------------
 drivers/input/rmi4/rmi_f01.h |  138 +++++-
 2 files changed, 250 insertions(+), 1001 deletions(-)

diff --git a/drivers/input/rmi4/rmi_f01.c b/drivers/input/rmi4/rmi_f01.c
index d7461d7..67afdeb 100644
--- a/drivers/input/rmi4/rmi_f01.c
+++ b/drivers/input/rmi4/rmi_f01.c
@@ -2,902 +2,64 @@
  * Copyright (c) 2011-2012 Synaptics Incorporated
  * Copyright (c) 2011 Unixphere
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
  */
 
 #include <linux/kernel.h>
-#include <linux/debugfs.h>
 #include <linux/kconfig.h>
 #include <linux/rmi.h>
 #include <linux/slab.h>
 #include <linux/uaccess.h>
+
 #include "rmi_driver.h"
 #include "rmi_f01.h"
 
-/**
- * @reset - set this bit to force a firmware reset of the sensor.
- */
-struct f01_device_commands {
-	u8 reset:1;
-	u8 reserved:7;
-};
-
-/**
- * @ctrl0 - see documentation in rmi_f01.h.
- * @interrupt_enable - A mask of per-function interrupts on the touch sensor.
- * @doze_interval - controls the interval between checks for finger presence
- * when the touch sensor is in doze mode, in units of 10ms.
- * @wakeup_threshold - controls the capacitance threshold at which the touch
- * sensor will decide to wake up from that low power state.
- * @doze_holdoff - controls how long the touch sensor waits after the last
- * finger lifts before entering the doze state, in units of 100ms.
- */
-struct f01_device_control {
-	struct f01_device_control_0 ctrl0;
-	u8 *interrupt_enable;
-	u8 doze_interval;
-	u8 wakeup_threshold;
-	u8 doze_holdoff;
-};
-
-/**
- * @has_ds4_queries - if true, the query registers relating to Design Studio 4
- * features are present.
- * @has_multi_phy - if true, multiple physical communications interfaces are
- * supported.
- * @has_guest - if true, a "guest" device is supported.
- */
-struct f01_query_42 {
-	u8 has_ds4_queries:1;
-	u8 has_multi_phy:1;
-	u8 has_guest:1;
-	u8 reserved:5;
-} __attribute__((__packed__));
-
-/**
- * @length - the length of the remaining Query43.* register block, not
- * including the first register.
- * @has_package_id_query -  the package ID query data will be accessible from
- * inside the ProductID query registers.
- * @has_packrat_query -  the packrat query data will be accessible from inside
- * the ProductID query registers.
- * @has_reset_query - the reset pin related registers are valid.
- * @has_maskrev_query - the silicon mask revision number will be reported.
- * @has_i2c_control - the register F01_RMI_Ctrl6 will exist.
- * @has_spi_control - the register F01_RMI_Ctrl7 will exist.
- * @has_attn_control - the register F01_RMI_Ctrl8 will exist.
- * @reset_enabled - the hardware reset pin functionality has been enabled
- * for this device.
- * @reset_polarity - If this bit reports as ‘0’, it means that the reset state
- * is active low. A ‘1’ means that the reset state is active high.
- * @pullup_enabled - If set, it indicates that a built-in weak pull up has
- * been enabled on the Reset pin; clear means that no pull-up is present.
- * @reset_pin_number - This field represents which GPIO pin number has been
- * assigned the reset functionality.
- */
-struct f01_ds4_queries {
-	u8 length:4;
-	u8 reserved_1:4;
-
-	u8 has_package_id_query:1;
-	u8 has_packrat_query:1;
-	u8 has_reset_query:1;
-	u8 has_maskrev_query:1;
-	u8 reserved_2:4;
-
-	u8 has_i2c_control:1;
-	u8 has_spi_control:1;
-	u8 has_attn_control:1;
-	u8 reserved_3:5;
-
-	u8 reset_enabled:1;
-	u8 reset_polarity:1;
-	u8 pullup_enabled:1;
-	u8 reserved_4:1;
-	u8 reset_pin_number:4;
-} __attribute__((__packed__));
-
-struct f01_data {
-	struct f01_device_control device_control;
-	struct f01_basic_queries basic_queries;
-	struct f01_device_status device_status;
-	u8 product_id[RMI_PRODUCT_ID_LENGTH + 1];
-
-	u16 interrupt_enable_addr;
-	u16 doze_interval_addr;
-	u16 wakeup_threshold_addr;
-	u16 doze_holdoff_addr;
-
-	int irq_count;
-	int num_of_irq_regs;
-
-#ifdef CONFIG_PM
-	bool suspended;
-	bool old_nosleep;
-#endif
-
-#ifdef CONFIG_RMI4_DEBUG
-	struct dentry *debugfs_interrupt_enable;
-#endif
-};
-
-#ifdef CONFIG_RMI4_DEBUG
-struct f01_debugfs_data {
-	bool done;
-	struct rmi_function *fn;
-};
-
-static int f01_debug_open(struct inode *inodep, struct file *filp)
-{
-	struct f01_debugfs_data *data;
-	struct rmi_function *fn = inodep->i_private;
-
-	data = kzalloc(sizeof(struct f01_debugfs_data), GFP_KERNEL);
-	if (!data)
-		return -ENOMEM;
-
-	data->fn = fn;
-	filp->private_data = data;
-	return 0;
-}
-
-static int f01_debug_release(struct inode *inodep, struct file *filp)
-{
-	kfree(filp->private_data);
-	return 0;
-}
-
-static ssize_t interrupt_enable_read(struct file *filp, char __user *buffer,
-				     size_t size, loff_t *offset) {
-	int i;
-	int len;
-	int total_len = 0;
-	char local_buf[size];
-	char *current_buf = local_buf;
-	struct f01_debugfs_data *data = filp->private_data;
-	struct f01_data *f01 = data->fn->data;
-
-	if (data->done)
-		return 0;
-
-	data->done = 1;
-
-	/* loop through each irq value and copy its
-	 * string representation into buf */
-	for (i = 0; i < f01->irq_count; i++) {
-		int irq_reg;
-		int irq_shift;
-		int interrupt_enable;
-
-		irq_reg = i / 8;
-		irq_shift = i % 8;
-		interrupt_enable =
-		    ((f01->device_control.interrupt_enable[irq_reg]
-			>> irq_shift) & 0x01);
-
-		/* get next irq value and write it to buf */
-		len = snprintf(current_buf, size - total_len,
-			"%u ", interrupt_enable);
-		/* bump up ptr to next location in buf if the
-		 * snprintf was valid.  Otherwise issue an error
-		 * and return. */
-		if (len > 0) {
-			current_buf += len;
-			total_len += len;
-		} else {
-			dev_err(&data->fn->dev, "Failed to build interrupt_enable buffer, code = %d.\n",
-						len);
-			return snprintf(local_buf, size, "unknown\n");
-		}
-	}
-	len = snprintf(current_buf, size - total_len, "\n");
-	if (len > 0)
-		total_len += len;
-	else
-		dev_warn(&data->fn->dev, "%s: Failed to append carriage return.\n",
-			 __func__);
-
-	if (copy_to_user(buffer, local_buf, total_len))
-		return -EFAULT;
-
-	return total_len;
-}
-
-static ssize_t interrupt_enable_write(struct file *filp,
-		const char __user *buffer, size_t size, loff_t *offset) {
-	int retval;
-	char buf[size];
-	char *local_buf = buf;
-	int i;
-	int irq_count = 0;
-	int irq_reg = 0;
-	struct f01_debugfs_data *data = filp->private_data;
-	struct f01_data *f01 = data->fn->data;
-
-	retval = copy_from_user(buf, buffer, size);
-	if (retval)
-		return -EFAULT;
-
-	for (i = 0; i < f01->irq_count && *local_buf != 0;
-	     i++, local_buf += 2) {
-		int irq_shift;
-		int interrupt_enable;
-		int result;
-
-		irq_reg = i / 8;
-		irq_shift = i % 8;
-
-		/* get next interrupt mapping value and store and bump up to
-		 * point to next item in local_buf */
-		result = sscanf(local_buf, "%u", &interrupt_enable);
-		if ((result != 1) ||
-			(interrupt_enable != 0 && interrupt_enable != 1)) {
-			dev_err(&data->fn->dev, "Interrupt enable[%d] is not a valid value 0x%x.\n",
-				i, interrupt_enable);
-			return -EINVAL;
-		}
-		if (interrupt_enable == 0) {
-			f01->device_control.interrupt_enable[irq_reg] &=
-				(1 << irq_shift) ^ 0xFF;
-		} else
-			f01->device_control.interrupt_enable[irq_reg] |=
-				(1 << irq_shift);
-		irq_count++;
-	}
-
-	/* Make sure the irq count matches */
-	if (irq_count != f01->irq_count) {
-		dev_err(&data->fn->dev, "Interrupt enable count of %d doesn't match device count of %d.\n",
-			 irq_count, f01->irq_count);
-		return -EINVAL;
-	}
-
-	/* write back to the control register */
-	retval = rmi_write_block(data->fn->rmi_dev, f01->interrupt_enable_addr,
-			f01->device_control.interrupt_enable,
-			f01->num_of_irq_regs);
-	if (retval < 0) {
-		dev_err(&data->fn->dev, "Could not write interrupt_enable mask to %#06x\n",
-			f01->interrupt_enable_addr);
-		return retval;
-	}
-
-	return size;
-}
-
-static const struct file_operations interrupt_enable_fops = {
-	.owner = THIS_MODULE,
-	.open = f01_debug_open,
-	.release = f01_debug_release,
-	.read = interrupt_enable_read,
-	.write = interrupt_enable_write,
-};
-
-static int setup_debugfs(struct rmi_function *fn)
-{
-	struct f01_data *data = fn->data;
-
-	if (!fn->debugfs_root)
-		return -ENODEV;
-
-	data->debugfs_interrupt_enable = debugfs_create_file("interrupt_enable",
-		RMI_RW_ATTR, fn->debugfs_root, fn, &interrupt_enable_fops);
-	if (!data->debugfs_interrupt_enable)
-		dev_warn(&fn->dev,
-			 "Failed to create debugfs interrupt_enable.\n");
-
-	return 0;
-}
-
-static void teardown_debugfs(struct f01_data *f01)
-{
-	if (f01->debugfs_interrupt_enable)
-		debugfs_remove(f01->debugfs_interrupt_enable);
-}
-
-#else
+#define FUNCTION_NUMBER 0x01
 
-static inline int setup_debugfs(struct rmi_function *fn)
-{
-	return 0;
-}
-
-static inline void teardown_debugfs(struct f01_data *f01)
-{
-}
-
-#endif
-
-static ssize_t rmi_fn_01_productinfo_show(struct device *dev,
-					  struct device_attribute *attr,
-					  char *buf)
-{
-	struct rmi_function *fn = to_rmi_function(dev);
-	struct f01_data *data = fn->data;
-
-	return snprintf(buf, PAGE_SIZE, "0x%02x 0x%02x\n",
-			data->basic_queries.productinfo_1,
-			data->basic_queries.productinfo_2);
-}
-
-static ssize_t rmi_fn_01_productid_show(struct device *dev,
-					struct device_attribute *attr,
-					char *buf)
-{
-	struct rmi_function *fn = to_rmi_function(dev);
-	struct f01_data *data = fn->data;
-
-	return snprintf(buf, PAGE_SIZE, "%s\n", data->product_id);
-}
-
-static ssize_t rmi_fn_01_manufacturer_show(struct device *dev,
-					   struct device_attribute *attr,
-					   char *buf)
-{
-	struct rmi_function *fn = to_rmi_function(dev);
-	struct f01_data *data = fn->data;
-
-	return snprintf(buf, PAGE_SIZE, "0x%02x\n",
-			data->basic_queries.manufacturer_id);
-}
-
-static ssize_t rmi_fn_01_datecode_show(struct device *dev,
-				       struct device_attribute *attr,
-				       char *buf)
-{
-	struct rmi_function *fn = to_rmi_function(dev);
-	struct f01_data *data = fn->data;
-
-	return snprintf(buf, PAGE_SIZE, "20%02u-%02u-%02u\n",
-			data->basic_queries.year,
-			data->basic_queries.month,
-			data->basic_queries.day);
-}
-
-static ssize_t rmi_fn_01_reset_store(struct device *dev,
-				     struct device_attribute *attr,
-				     const char *buf, size_t count)
-{
-	struct rmi_function *fn = to_rmi_function(dev);
-	unsigned int reset;
-	int retval = 0;
-
-
-	if (sscanf(buf, "%u", &reset) != 1)
-		return -EINVAL;
-	if (reset < 0 || reset > 1)
-		return -EINVAL;
-
-	/* Per spec, 0 has no effect, so we skip it entirely. */
-	if (reset) {
-		/* Command register always reads as 0, so just use a local. */
-		struct f01_device_commands commands = {
-			.reset = 1
-		};
-		retval = rmi_write_block(fn->rmi_dev, fn->fd.command_base_addr,
-				&commands, sizeof(commands));
-		if (retval < 0) {
-			dev_err(dev, "Failed to issue reset command, code = %d.",
-						retval);
-			return retval;
-		}
-	}
-
-	return count;
-}
-
-static ssize_t rmi_fn_01_sleepmode_show(struct device *dev,
-					struct device_attribute *attr,
-					char *buf)
-{
-	struct rmi_function *fn = to_rmi_function(dev);
-	struct f01_data *data = fn->data;
-
-	return snprintf(buf, PAGE_SIZE,
-			"%d\n", data->device_control.ctrl0.sleep_mode);
-}
-
-static ssize_t rmi_fn_01_sleepmode_store(struct device *dev,
-					 struct device_attribute *attr,
-					 const char *buf, size_t count)
-{
-	struct rmi_function *fn = to_rmi_function(dev);
-	struct f01_data *data = fn->data;
-	unsigned long new_value;
-	int retval;
-
-	retval = strict_strtoul(buf, 10, &new_value);
-	if (retval < 0 || !RMI_IS_VALID_SLEEPMODE(new_value)) {
-		dev_err(dev, "%s: Invalid sleep mode %s.", __func__, buf);
-		return -EINVAL;
-	}
-
-	dev_dbg(dev, "Setting sleep mode to %ld.", new_value);
-	data->device_control.ctrl0.sleep_mode = new_value;
-	retval = rmi_write_block(fn->rmi_dev, fn->fd.control_base_addr,
-			&data->device_control.ctrl0,
-			sizeof(data->device_control.ctrl0));
-	if (retval >= 0)
-		retval = count;
-	else
-		dev_err(dev, "Failed to write sleep mode, code %d.\n", retval);
-	return retval;
-}
-
-static ssize_t rmi_fn_01_nosleep_show(struct device *dev,
-				      struct device_attribute *attr, char *buf)
-{
-	struct rmi_function *fn = to_rmi_function(dev);
-	struct f01_data *data = fn->data;
-
-	return snprintf(buf, PAGE_SIZE, "%d\n",
-			data->device_control.ctrl0.nosleep);
-}
-
-static ssize_t rmi_fn_01_nosleep_store(struct device *dev,
-				       struct device_attribute *attr,
-				       const char *buf, size_t count)
-{
-	struct rmi_function *fn = to_rmi_function(dev);
-	struct f01_data *data = fn->data;
-	unsigned long new_value;
-	int retval;
-
-	retval = strict_strtoul(buf, 10, &new_value);
-	if (retval < 0 || new_value > 1) {
-		dev_err(dev, "%s: Invalid nosleep bit %s.", __func__, buf);
-		return -EINVAL;
-	}
-
-	data->device_control.ctrl0.nosleep = new_value;
-	retval = rmi_write_block(fn->rmi_dev, fn->fd.control_base_addr,
-			&data->device_control.ctrl0,
-			sizeof(data->device_control.ctrl0));
-	if (retval >= 0)
-		retval = count;
-	else
-		dev_err(dev, "Failed to write nosleep bit.\n");
-
-	return retval;
-}
-
-static ssize_t rmi_fn_01_chargerinput_show(struct device *dev,
-				      struct device_attribute *attr, char *buf)
-{
-	struct rmi_function *fn = to_rmi_function(dev);
-	struct f01_data *data = fn->data;
-
-	return snprintf(buf, PAGE_SIZE, "%d\n",
-			data->device_control.ctrl0.charger_input);
-}
-
-static ssize_t rmi_fn_01_chargerinput_store(struct device *dev,
-				       struct device_attribute *attr,
-				       const char *buf, size_t count)
-{
-	struct rmi_function *fn = to_rmi_function(dev);
-	struct f01_data *data = fn->data;
-	unsigned long new_value;
-	int retval;
-
-	retval = strict_strtoul(buf, 10, &new_value);
-	if (retval < 0 || new_value > 1) {
-		dev_err(dev, "%s: Invalid chargerinput bit %s.", __func__, buf);
-		return -EINVAL;
-	}
-
-	data->device_control.ctrl0.charger_input = new_value;
-	retval = rmi_write_block(fn->rmi_dev, fn->fd.control_base_addr,
-			&data->device_control.ctrl0,
-			sizeof(data->device_control.ctrl0));
-	if (retval >= 0)
-		retval = count;
-	else
-		dev_err(dev, "Failed to write chargerinput bit.\n");
-
-	return retval;
-}
-
-static ssize_t rmi_fn_01_reportrate_show(struct device *dev,
-				      struct device_attribute *attr, char *buf)
-{
-	struct rmi_function *fn = to_rmi_function(dev);
-	struct f01_data *data = fn->data;
-
-	return snprintf(buf, PAGE_SIZE, "%d\n",
-			data->device_control.ctrl0.report_rate);
-}
-
-static ssize_t rmi_fn_01_reportrate_store(struct device *dev,
-				       struct device_attribute *attr,
-				       const char *buf, size_t count)
-{
-	struct rmi_function *fn = to_rmi_function(dev);
-	struct f01_data *data = fn->data;
-	unsigned long new_value;
-	int retval;
-
-	retval = strict_strtoul(buf, 10, &new_value);
-	if (retval < 0 || new_value > 1) {
-		dev_err(dev, "%s: Invalid reportrate bit %s.", __func__, buf);
-		return -EINVAL;
-	}
-
-	data->device_control.ctrl0.report_rate = new_value;
-	retval = rmi_write_block(fn->rmi_dev, fn->fd.control_base_addr,
-			&data->device_control.ctrl0,
-			sizeof(data->device_control.ctrl0));
-	if (retval >= 0)
-		retval = count;
-	else
-		dev_err(dev, "Failed to write reportrate bit.\n");
-
-	return retval;
-}
-
-static ssize_t rmi_fn_01_interrupt_enable_show(struct device *dev,
-				struct device_attribute *attr, char *buf)
-{
-	struct rmi_function *fn = to_rmi_function(dev);
-	struct f01_data *data = fn->data;
-	int i, len, total_len = 0;
-	char *current_buf = buf;
-
-	/* loop through each irq value and copy its
-	 * string representation into buf */
-	for (i = 0; i < data->irq_count; i++) {
-		int irq_reg;
-		int irq_shift;
-		int interrupt_enable;
-
-		irq_reg = i / 8;
-		irq_shift = i % 8;
-		interrupt_enable =
-		    ((data->device_control.interrupt_enable[irq_reg]
-			>> irq_shift) & 0x01);
-
-		/* get next irq value and write it to buf */
-		len = snprintf(current_buf, PAGE_SIZE - total_len,
-			"%u ", interrupt_enable);
-		/* bump up ptr to next location in buf if the
-		 * snprintf was valid.  Otherwise issue an error
-		 * and return. */
-		if (len > 0) {
-			current_buf += len;
-			total_len += len;
-		} else {
-			dev_err(dev, "Failed to build interrupt_enable buffer, code = %d.\n",
-						len);
-			return snprintf(buf, PAGE_SIZE, "unknown\n");
-		}
-	}
-	len = snprintf(current_buf, PAGE_SIZE - total_len, "\n");
-	if (len > 0)
-		total_len += len;
-	else
-		dev_warn(dev, "%s: Failed to append carriage return.\n",
-			 __func__);
-	return total_len;
-
-}
-
-static ssize_t rmi_fn_01_doze_interval_show(struct device *dev,
-				struct device_attribute *attr, char *buf)
-{
-	struct rmi_function *fn = to_rmi_function(dev);
-	struct f01_data *data = fn->data;
-
-	return snprintf(buf, PAGE_SIZE, "%d\n",
-			data->device_control.doze_interval);
-
-}
-
-static ssize_t rmi_fn_01_doze_interval_store(struct device *dev,
-					  struct device_attribute *attr,
-					  const char *buf, size_t count)
-{
-	struct rmi_function *fn = to_rmi_function(dev);
-	struct f01_data *data = fn->data;
-	unsigned long new_value;
-	int retval;
-	u16 ctrl_base_addr;
-
-	retval = strict_strtoul(buf, 10, &new_value);
-	if (retval < 0 || new_value > 255) {
-		dev_err(dev, "%s: Invalid doze interval %s.", __func__, buf);
-		return -EINVAL;
-	}
-
-	data->device_control.doze_interval = new_value;
-	ctrl_base_addr = fn->fd.control_base_addr + sizeof(u8) +
-			(sizeof(u8)*(data->num_of_irq_regs));
-	dev_dbg(dev, "doze_interval store address %x, value %d",
-		ctrl_base_addr, data->device_control.doze_interval);
-
-	retval = rmi_write_block(fn->rmi_dev, data->doze_interval_addr,
-			&data->device_control.doze_interval,
-			sizeof(u8));
-	if (retval >= 0)
-		retval = count;
-	else
-		dev_err(dev, "Failed to write doze interval.\n");
-
-	return retval;
-
-}
-
-static ssize_t rmi_fn_01_wakeup_threshold_show(struct device *dev,
-					 struct device_attribute *attr,
-					 char *buf)
-{
-	struct rmi_function *fn = to_rmi_function(dev);
-	struct f01_data *data = fn->data;
-
-	return snprintf(buf, PAGE_SIZE, "%d\n",
-			data->device_control.wakeup_threshold);
-}
-
-static ssize_t rmi_fn_01_wakeup_threshold_store(struct device *dev,
-					  struct device_attribute *attr,
-					  const char *buf, size_t count)
-{
-	struct rmi_function *fn = to_rmi_function(dev);
-	struct f01_data *data = fn->data;
-	unsigned long new_value;
-	int retval;
-
-	retval = strict_strtoul(buf, 10, &new_value);
-	if (retval < 0 || new_value > 255) {
-		dev_err(dev, "%s: Invalid wakeup threshold %s.", __func__, buf);
-		return -EINVAL;
-	}
-
-	data->device_control.doze_interval = new_value;
-	retval = rmi_write_block(fn->rmi_dev, data->wakeup_threshold_addr,
-			&data->device_control.wakeup_threshold,
-			sizeof(u8));
-	if (retval >= 0)
-		retval = count;
-	else
-		dev_err(dev, "Failed to write wakeup threshold.\n");
-	return retval;
-
-}
-
-static ssize_t rmi_fn_01_doze_holdoff_show(struct device *dev,
-					 struct device_attribute *attr,
-					 char *buf)
-{
-	struct rmi_function *fn = to_rmi_function(dev);
-	struct f01_data *data = fn->data;
-
-	return snprintf(buf, PAGE_SIZE, "%d\n",
-			data->device_control.doze_holdoff);
-
-}
-
-
-static ssize_t rmi_fn_01_doze_holdoff_store(struct device *dev,
-					  struct device_attribute *attr,
-					  const char *buf, size_t count)
-{
-	struct rmi_function *fn = to_rmi_function(dev);
-	struct f01_data *data = fn->data;
-	unsigned long new_value;
-	int retval;
-
-	retval = strict_strtoul(buf, 10, &new_value);
-	if (retval < 0 || new_value > 255) {
-		dev_err(dev, "%s: Invalid doze holdoff %s.", __func__, buf);
-		return -EINVAL;
-	}
-
-	data->device_control.doze_interval = new_value;
-	retval = rmi_write_block(fn->rmi_dev, data->doze_holdoff_addr,
-			&data->device_control.doze_holdoff,
-			sizeof(u8));
-	if (retval >= 0)
-		retval = count;
-	else
-		dev_err(dev, "Failed to write doze holdoff.\n");
-
-	return retval;
-
-}
-
-static ssize_t rmi_fn_01_configured_show(struct device *dev,
-				      struct device_attribute *attr, char *buf)
-{
-	struct rmi_function *fn = to_rmi_function(dev);
-	struct f01_data *data = fn->data;
-
-	return snprintf(buf, PAGE_SIZE, "%d\n",
-			data->device_control.ctrl0.configured);
-}
-
-static ssize_t rmi_fn_01_unconfigured_show(struct device *dev,
-				      struct device_attribute *attr, char *buf)
-{
-	struct rmi_function *fn = to_rmi_function(dev);
-	struct f01_data *data = fn->data;
-
-	return snprintf(buf, PAGE_SIZE, "%d\n",
-			data->device_status.unconfigured);
-}
-
-static ssize_t rmi_fn_01_flashprog_show(struct device *dev,
-				      struct device_attribute *attr, char *buf)
-{
-	struct rmi_function *fn = to_rmi_function(dev);
-	struct f01_data *data = fn->data;
-
-	return snprintf(buf, PAGE_SIZE, "%d\n",
-			data->device_status.flash_prog);
-}
-
-static ssize_t rmi_fn_01_statuscode_show(struct device *dev,
-				      struct device_attribute *attr, char *buf)
-{
-	struct rmi_function *fn = to_rmi_function(dev);
-	struct f01_data *data = fn->data;
-
-	return snprintf(buf, PAGE_SIZE, "0x%02x\n",
-			data->device_status.status_code);
-}
-
-#define RMI_F01_ATTR(_name)			\
-	DEVICE_ATTR(_name, RMI_RW_ATTR,		\
-		    rmi_fn_01_##_name##_show,	\
-		    rmi_fn_01_##_name##_store)
-
-#define RMI_F01_RO_ATTR(_name)			\
-	DEVICE_ATTR(_name, RMI_RO_ATTR,		\
-		    rmi_fn_01_##_name##_show,	\
-		    NULL)
-
-#define RMI_F01_WO_ATTR(_name)			\
-	DEVICE_ATTR(_name, RMI_RO_ATTR,		\
-		    NULL,			\
-		    rmi_fn_01_##_name##_store)
-
-
-static RMI_F01_RO_ATTR(productinfo);
-static RMI_F01_RO_ATTR(productid);
-static RMI_F01_RO_ATTR(manufacturer);
-static RMI_F01_RO_ATTR(datecode);
-
-/* Control register access */
-static RMI_F01_ATTR(sleepmode);
-static RMI_F01_ATTR(nosleep);
-static RMI_F01_ATTR(chargerinput);
-static RMI_F01_ATTR(reportrate);
-
-/*
- * We don't want arbitrary callers changing the interrupt enable mask,
- * so it's read only.
- */
-static RMI_F01_RO_ATTR(interrupt_enable);
-static RMI_F01_ATTR(doze_interval);
-static RMI_F01_ATTR(wakeup_threshold);
-static RMI_F01_ATTR(doze_holdoff);
-
-/*
- * We make report rate RO, since the driver uses that to look for
- * resets.  We don't want someone faking us out by changing that
- * bit.
- */
-static RMI_F01_RO_ATTR(configured);
-
-/* Command register access. */
-static RMI_F01_WO_ATTR(reset);
-
-/* Status register access. */
-static RMI_F01_RO_ATTR(unconfigured);
-static RMI_F01_RO_ATTR(flashprog);
-static RMI_F01_RO_ATTR(statuscode);
-
-static struct attribute *rmi_fn_01_attrs[] = {
-	&dev_attr_productinfo.attr,
-	&dev_attr_productid.attr,
-	&dev_attr_manufacturer.attr,
-	&dev_attr_datecode.attr,
-	&dev_attr_sleepmode.attr,
-	&dev_attr_nosleep.attr,
-	&dev_attr_chargerinput.attr,
-	&dev_attr_reportrate.attr,
-	&dev_attr_interrupt_enable.attr,
-	&dev_attr_doze_interval.attr,
-	&dev_attr_wakeup_threshold.attr,
-	&dev_attr_doze_holdoff.attr,
-	&dev_attr_configured.attr,
-	&dev_attr_reset.attr,
-	&dev_attr_unconfigured.attr,
-	&dev_attr_flashprog.attr,
-	&dev_attr_statuscode.attr,
-	NULL
-};
-
-static umode_t rmi_fn_01_attr_visible(struct kobject *kobj,
-				      struct attribute *attr, int n)
-{
-	struct device *dev = kobj_to_dev(kobj); 
-	struct rmi_function *fn = to_rmi_function(dev);
-	struct f01_data *data = fn->data;
-	umode_t mode = attr->mode;
-
-	if (attr == &dev_attr_doze_interval.attr) {
-		if (!data->basic_queries.has_lts)
-			mode = 0;
-	} else if (attr == &dev_attr_wakeup_threshold.attr) {
-		if (!data->basic_queries.has_adjustable_doze)
-			mode = 0;
-	} else if (attr == &dev_attr_doze_holdoff.attr) {
-		if (!data->basic_queries.has_adjustable_doze_holdoff)
-			mode = 0;
-	}
-
-	return mode;
-}
-
-static struct attribute_group rmi_fn_01_attr_group = {
-	.is_visible	= rmi_fn_01_attr_visible,
-	.attrs		= rmi_fn_01_attrs,
-};
-
-static int rmi_f01_alloc_memory(struct rmi_function *fn,
-				int num_of_irq_regs)
+static int rmi_f01_alloc_memory(struct rmi_function_dev *fn_dev,
+	int num_of_irq_regs)
 {
 	struct f01_data *f01;
 
-	f01 = devm_kzalloc(&fn->dev, sizeof(struct f01_data), GFP_KERNEL);
+	f01 = devm_kzalloc(&fn_dev->dev, sizeof(struct f01_data), GFP_KERNEL);
 	if (!f01) {
-		dev_err(&fn->dev, "Failed to allocate fn_01_data.\n");
+		dev_err(&fn_dev->dev, "Failed to allocate fn_01_data.\n");
 		return -ENOMEM;
 	}
 
-	f01->device_control.interrupt_enable = devm_kzalloc(&fn->dev,
+	f01->device_control.interrupt_enable = devm_kzalloc(&fn_dev->dev,
 			sizeof(u8)*(num_of_irq_regs),
 			GFP_KERNEL);
 	if (!f01->device_control.interrupt_enable) {
-		dev_err(&fn->dev, "Failed to allocate interrupt enable.\n");
+		dev_err(&fn_dev->dev, "Failed to allocate interrupt enable.\n");
 		return -ENOMEM;
 	}
-	fn->data = f01;
+	fn_dev->data = f01;
 
 	return 0;
 }
 
-static int rmi_f01_initialize(struct rmi_function *fn)
+static int rmi_f01_initialize(struct rmi_function_dev *fn_dev)
 {
 	u8 temp;
-	int error;
-	u16 ctrl_base_addr;
-	struct rmi_device *rmi_dev = fn->rmi_dev;
+	int retval;
+	u16 query_addr = fn_dev->fd.query_base_addr;
+	u16 ctrl_addr = fn_dev->fd.control_base_addr;
+	struct rmi_device *rmi_dev = fn_dev->rmi_dev;
 	struct rmi_driver_data *driver_data = dev_get_drvdata(&rmi_dev->dev);
-	struct f01_data *data = fn->data;
+	struct f01_data *data = fn_dev->data;
 	struct rmi_device_platform_data *pdata = to_rmi_platform_data(rmi_dev);
 
 	/* Set the configured bit and (optionally) other important stuff
 	 * in the device control register. */
-	ctrl_base_addr = fn->fd.control_base_addr;
-	error = rmi_read_block(rmi_dev, fn->fd.control_base_addr,
+	retval = rmi_read_block(rmi_dev, fn_dev->fd.control_base_addr,
 			&data->device_control.ctrl0,
 			sizeof(data->device_control.ctrl0));
-	if (error < 0) {
-		dev_err(&fn->dev, "Failed to read F01 control.\n");
-		return error;
+	if (retval < 0) {
+		dev_err(&fn_dev->dev, "Failed to read F01 control.\n");
+		return retval;
 	}
 	switch (pdata->power_management.nosleep) {
 	case RMI_F01_NOSLEEP_DEFAULT:
@@ -914,242 +76,237 @@ static int rmi_f01_initialize(struct rmi_function *fn)
 	 * is certain to function.
 	 */
 	if (data->device_control.ctrl0.sleep_mode != RMI_SLEEP_MODE_NORMAL) {
-		dev_warn(&fn->dev,
+		dev_warn(&fn_dev->dev,
 			 "WARNING: Non-zero sleep mode found. Clearing...\n");
 		data->device_control.ctrl0.sleep_mode = RMI_SLEEP_MODE_NORMAL;
 	}
 
 	data->device_control.ctrl0.configured = 1;
-	error = rmi_write_block(rmi_dev, fn->fd.control_base_addr,
+	retval = rmi_write_block(rmi_dev, fn_dev->fd.control_base_addr,
 			&data->device_control.ctrl0,
 			sizeof(data->device_control.ctrl0));
-	if (error < 0) {
-		dev_err(&fn->dev, "Failed to write F01 control.\n");
-		return error;
+	if (retval < 0) {
+		dev_err(&fn_dev->dev, "Failed to write F01 control.\n");
+		return retval;
 	}
 
 	data->irq_count = driver_data->irq_count;
 	data->num_of_irq_regs = driver_data->num_of_irq_regs;
-	ctrl_base_addr += sizeof(struct f01_device_control_0);
+	ctrl_addr += sizeof(struct f01_device_control_0);
 
-	data->interrupt_enable_addr = ctrl_base_addr;
-	error = rmi_read_block(rmi_dev, ctrl_base_addr,
+	data->interrupt_enable_addr = ctrl_addr;
+	retval = rmi_read_block(rmi_dev, ctrl_addr,
 			data->device_control.interrupt_enable,
 			sizeof(u8)*(data->num_of_irq_regs));
-	if (error < 0) {
-		dev_err(&fn->dev, "Failed to read F01 control interrupt enable register.\n");
+	if (retval < 0) {
+		dev_err(&fn_dev->dev, "Failed to read F01 control interrupt enable register.\n");
 		goto error_exit;
 	}
-	ctrl_base_addr += data->num_of_irq_regs;
+	ctrl_addr += data->num_of_irq_regs;
 
 	/* dummy read in order to clear irqs */
-	error = rmi_read(rmi_dev, fn->fd.data_base_addr + 1, &temp);
-	if (error < 0) {
-		dev_err(&fn->dev, "Failed to read Interrupt Status.\n");
-		return error;
+	retval = rmi_read(rmi_dev, fn_dev->fd.data_base_addr + 1, &temp);
+	if (retval < 0) {
+		dev_err(&fn_dev->dev, "Failed to read Interrupt Status.\n");
+		return retval;
 	}
 
-	error = rmi_read_block(rmi_dev, fn->fd.query_base_addr,
-				&data->basic_queries,
+	/* read queries */
+	retval = rmi_read_block(rmi_dev, query_addr, &data->basic_queries,
 				sizeof(data->basic_queries));
-	if (error < 0) {
-		dev_err(&fn->dev, "Failed to read device query registers.\n");
-		return error;
+	if (retval < 0) {
+		dev_err(&fn_dev->dev, "Failed to read device query registers.\n");
+		return retval;
 	}
+	query_addr += sizeof(data->basic_queries);
 
-	error = rmi_read_block(rmi_dev,
-		fn->fd.query_base_addr + sizeof(data->basic_queries),
-		data->product_id, RMI_PRODUCT_ID_LENGTH);
-	if (error < 0) {
-		dev_err(&fn->dev, "Failed to read product ID.\n");
-		return error;
+	retval = rmi_read_block(rmi_dev, query_addr, data->serialization,
+				F01_SERIALIZATION_SIZE);
+	if (retval < 0) {
+		dev_err(&fn_dev->dev, "Failed to read device serialization.\n");
+		return retval;
+	}
+	query_addr += F01_SERIALIZATION_SIZE;
+
+	retval = rmi_read_block(rmi_dev, query_addr, data->product_id,
+				RMI_PRODUCT_ID_LENGTH);
+	if (retval < 0) {
+		dev_err(&fn_dev->dev, "Failed to read product ID.\n");
+		return retval;
 	}
 	data->product_id[RMI_PRODUCT_ID_LENGTH] = '\0';
-	dev_info(&fn->dev, "found RMI device, manufacturer: %s, product: %s\n",
+	dev_info(&fn_dev->dev, "found RMI device, manufacturer: %s, product: %s\n",
 		 data->basic_queries.manufacturer_id == 1 ?
 							"synaptics" : "unknown",
 		 data->product_id);
 
 	/* read control register */
 	if (data->basic_queries.has_adjustable_doze) {
-		data->doze_interval_addr = ctrl_base_addr;
-		ctrl_base_addr++;
+		data->doze_interval_addr = ctrl_addr;
+		ctrl_addr++;
 
 		if (pdata->power_management.doze_interval) {
 			data->device_control.doze_interval =
 				pdata->power_management.doze_interval;
-			error = rmi_write(rmi_dev, data->doze_interval_addr,
+			retval = rmi_write(rmi_dev, data->doze_interval_addr,
 					data->device_control.doze_interval);
-			if (error < 0) {
-				dev_err(&fn->dev, "Failed to configure F01 doze interval register.\n");
+			if (retval < 0) {
+				dev_err(&fn_dev->dev, "Failed to configure F01 doze interval register.\n");
 				goto error_exit;
 			}
 		} else {
-			error = rmi_read(rmi_dev, data->doze_interval_addr,
+			retval = rmi_read(rmi_dev, data->doze_interval_addr,
 					&data->device_control.doze_interval);
-			if (error < 0) {
-				dev_err(&fn->dev, "Failed to read F01 doze interval register.\n");
+			if (retval < 0) {
+				dev_err(&fn_dev->dev, "Failed to read F01 doze interval register.\n");
 				goto error_exit;
 			}
 		}
 
-		data->wakeup_threshold_addr = ctrl_base_addr;
-		ctrl_base_addr++;
+		data->wakeup_threshold_addr = ctrl_addr;
+		ctrl_addr++;
 
 		if (pdata->power_management.wakeup_threshold) {
 			data->device_control.wakeup_threshold =
 				pdata->power_management.wakeup_threshold;
-			error = rmi_write(rmi_dev, data->wakeup_threshold_addr,
+			retval = rmi_write(rmi_dev, data->wakeup_threshold_addr,
 					data->device_control.wakeup_threshold);
-			if (error < 0) {
-				dev_err(&fn->dev, "Failed to configure F01 wakeup threshold register.\n");
+			if (retval < 0) {
+				dev_err(&fn_dev->dev, "Failed to configure F01 wakeup threshold register.\n");
 				goto error_exit;
 			}
 		} else {
-			error = rmi_read(rmi_dev, data->wakeup_threshold_addr,
+			retval = rmi_read(rmi_dev, data->wakeup_threshold_addr,
 					&data->device_control.wakeup_threshold);
-			if (error < 0) {
-				dev_err(&fn->dev, "Failed to read F01 wakeup threshold register.\n");
+			if (retval < 0) {
+				dev_err(&fn_dev->dev, "Failed to read F01 wakeup threshold register.\n");
 				goto error_exit;
 			}
 		}
 	}
 
 	if (data->basic_queries.has_adjustable_doze_holdoff) {
-		data->doze_holdoff_addr = ctrl_base_addr;
-		ctrl_base_addr++;
+		data->doze_holdoff_addr = ctrl_addr;
+		ctrl_addr++;
 
 		if (pdata->power_management.doze_holdoff) {
 			data->device_control.doze_holdoff =
 				pdata->power_management.doze_holdoff;
-			error = rmi_write(rmi_dev, data->doze_holdoff_addr,
+			retval = rmi_write(rmi_dev, data->doze_holdoff_addr,
 					data->device_control.doze_holdoff);
-			if (error < 0) {
-				dev_err(&fn->dev, "Failed to configure F01 doze holdoff register.\n");
+			if (retval < 0) {
+				dev_err(&fn_dev->dev, "Failed to configure F01 doze holdoff register.\n");
 				goto error_exit;
 			}
 		} else {
-			error = rmi_read(rmi_dev, data->doze_holdoff_addr,
+			retval = rmi_read(rmi_dev, data->doze_holdoff_addr,
 					&data->device_control.doze_holdoff);
-			if (error < 0) {
-				dev_err(&fn->dev, "Failed to read F01 doze holdoff register.\n");
+			if (retval < 0) {
+				dev_err(&fn_dev->dev, "Failed to read F01 doze holdoff register.\n");
 				goto error_exit;
 			}
 		}
 	}
 
-	error = rmi_read_block(rmi_dev, fn->fd.data_base_addr,
+	retval = rmi_read_block(rmi_dev, fn_dev->fd.data_base_addr,
 		&data->device_status, sizeof(data->device_status));
-	if (error < 0) {
-		dev_err(&fn->dev, "Failed to read device status.\n");
+	if (retval < 0) {
+		dev_err(&fn_dev->dev, "Failed to read device status.\n");
 		goto error_exit;
 	}
 
 	if (data->device_status.unconfigured) {
-		dev_err(&fn->dev, "Device reset during configuration process, status: %#02x!\n",
+		dev_err(&fn_dev->dev, "Device reset during configuration process, status: %#02x!\n",
 				data->device_status.status_code);
-		error = -EINVAL;
+		retval = -EINVAL;
 		goto error_exit;
 	}
 
-	error = setup_debugfs(fn);
-	if (error)
-		dev_warn(&fn->dev, "Failed to setup debugfs, error: %d.\n",
-			 error);
-
-	return 0;
+	return retval;
 
  error_exit:
 	kfree(data);
-	return error;
+	return retval;
 }
 
-static int rmi_f01_config(struct rmi_function *fn)
+static int rmi_f01_config(struct rmi_function_dev *fn_dev)
 {
-	struct f01_data *data = fn->data;
+	struct f01_data *data = fn_dev->data;
 	int retval;
 
-	retval = rmi_write_block(fn->rmi_dev, fn->fd.control_base_addr,
+	retval = rmi_write_block(fn_dev->rmi_dev, fn_dev->fd.control_base_addr,
 			&data->device_control.ctrl0,
 			sizeof(data->device_control.ctrl0));
 	if (retval < 0) {
-		dev_err(&fn->dev, "Failed to write device_control.reg.\n");
+		dev_err(&fn_dev->dev, "Failed to write device_control.reg.\n");
 		return retval;
 	}
 
-	retval = rmi_write_block(fn->rmi_dev, data->interrupt_enable_addr,
+	retval = rmi_write_block(fn_dev->rmi_dev, data->interrupt_enable_addr,
 			data->device_control.interrupt_enable,
 			sizeof(u8)*(data->num_of_irq_regs));
 
 	if (retval < 0) {
-		dev_err(&fn->dev, "Failed to write interrupt enable.\n");
+		dev_err(&fn_dev->dev, "Failed to write interrupt enable.\n");
 		return retval;
 	}
 	if (data->basic_queries.has_lts) {
-		retval = rmi_write_block(fn->rmi_dev, data->doze_interval_addr,
-				&data->device_control.doze_interval,
-				sizeof(u8));
+		retval = rmi_write_block(fn_dev->rmi_dev,
+					data->doze_interval_addr,
+					&data->device_control.doze_interval,
+					sizeof(u8));
 		if (retval < 0) {
-			dev_err(&fn->dev, "Failed to write doze interval.\n");
+			dev_err(&fn_dev->dev, "Failed to write doze interval.\n");
 			return retval;
 		}
 	}
 
 	if (data->basic_queries.has_adjustable_doze) {
 		retval = rmi_write_block(
-				fn->rmi_dev, data->wakeup_threshold_addr,
+				fn_dev->rmi_dev, data->wakeup_threshold_addr,
 				&data->device_control.wakeup_threshold,
 				sizeof(u8));
 		if (retval < 0) {
-			dev_err(&fn->dev, "Failed to write wakeup threshold.\n");
+			dev_err(&fn_dev->dev, "Failed to write wakeup threshold.\n");
 			return retval;
 		}
 	}
 
 	if (data->basic_queries.has_adjustable_doze_holdoff) {
-		retval = rmi_write_block(fn->rmi_dev, data->doze_holdoff_addr,
-				&data->device_control.doze_holdoff,
-				sizeof(u8));
+		retval = rmi_write_block(fn_dev->rmi_dev,
+					data->doze_holdoff_addr,
+					&data->device_control.doze_holdoff,
+					sizeof(u8));
 		if (retval < 0) {
-			dev_err(&fn->dev, "Failed to write doze holdoff.\n");
+			dev_err(&fn_dev->dev, "Failed to write doze holdoff.\n");
 			return retval;
 		}
 	}
 	return 0;
 }
 
-static int rmi_f01_probe(struct rmi_function *fn)
+static int rmi_f01_probe(struct rmi_function_dev *fn_dev)
 {
 	struct rmi_driver_data *driver_data =
-			dev_get_drvdata(&fn->rmi_dev->dev);
+			dev_get_drvdata(&fn_dev->rmi_dev->dev);
 	int error;
 
-	error = rmi_f01_alloc_memory(fn, driver_data->num_of_irq_regs);
-	if (error)
-		return error;
-
-	error = rmi_f01_initialize(fn);
-	if (error)
+	error = rmi_f01_alloc_memory(fn_dev, driver_data->num_of_irq_regs);
+	if (error < 0)
 		return error;
 
-	error = sysfs_create_group(&fn->dev.kobj, &rmi_fn_01_attr_group);
-	if (error)
+	error = rmi_f01_initialize(fn_dev);
+	if (error < 0)
 		return error;
 
 	return 0;
 }
 
-static void rmi_f01_remove(struct rmi_function *fn)
-{
-	teardown_debugfs(fn->data);
-	sysfs_remove_group(&fn->dev.kobj, &rmi_fn_01_attr_group);
-}
-
 #ifdef CONFIG_PM
-static int rmi_f01_suspend(struct rmi_function *fn)
+static int rmi_f01_suspend(struct rmi_function_dev *fn_dev)
 {
-	struct rmi_device *rmi_dev = fn->rmi_dev;
-	struct f01_data *data = fn->data;
+	struct rmi_device *rmi_dev = fn_dev->rmi_dev;
+	struct f01_data *data = fn_dev->data;
 	int retval = 0;
 
 	if (data->suspended)
@@ -1160,11 +317,11 @@ static int rmi_f01_suspend(struct rmi_function *fn)
 	data->device_control.ctrl0.sleep_mode = RMI_SLEEP_MODE_SENSOR_SLEEP;
 
 	retval = rmi_write_block(rmi_dev,
-			fn->fd.control_base_addr,
+			fn_dev->fd.control_base_addr,
 			&data->device_control.ctrl0,
 			sizeof(data->device_control.ctrl0));
 	if (retval < 0) {
-		dev_err(&fn->dev, "Failed to write sleep mode. Code: %d.\n",
+		dev_err(&fn_dev->dev, "Failed to write sleep mode. Code: %d.\n",
 			retval);
 		data->device_control.ctrl0.nosleep = data->old_nosleep;
 		data->device_control.ctrl0.sleep_mode = RMI_SLEEP_MODE_NORMAL;
@@ -1176,10 +333,10 @@ static int rmi_f01_suspend(struct rmi_function *fn)
 	return retval;
 }
 
-static int rmi_f01_resume(struct rmi_function *fn)
+static int rmi_f01_resume(struct rmi_function_dev *fn_dev)
 {
-	struct rmi_device *rmi_dev = fn->rmi_dev;
-	struct f01_data *data = fn->data;
+	struct rmi_device *rmi_dev = fn_dev->rmi_dev;
+	struct f01_data *data = fn_dev->data;
 	int retval = 0;
 
 	if (!data->suspended)
@@ -1188,11 +345,11 @@ static int rmi_f01_resume(struct rmi_function *fn)
 	data->device_control.ctrl0.nosleep = data->old_nosleep;
 	data->device_control.ctrl0.sleep_mode = RMI_SLEEP_MODE_NORMAL;
 
-	retval = rmi_write_block(rmi_dev, fn->fd.control_base_addr,
+	retval = rmi_write_block(rmi_dev, fn_dev->fd.control_base_addr,
 			&data->device_control.ctrl0,
 			sizeof(data->device_control.ctrl0));
 	if (retval < 0)
-		dev_err(&fn->dev,
+		dev_err(&fn_dev->dev,
 			"Failed to restore normal operation. Code: %d.\n",
 			retval);
 	else {
@@ -1204,22 +361,27 @@ static int rmi_f01_resume(struct rmi_function *fn)
 }
 #endif /* CONFIG_PM */
 
-static int rmi_f01_attention(struct rmi_function *fn,
-			     unsigned long *irq_bits)
+static int rmi_f01_remove(struct rmi_function_dev *fn_dev)
 {
-	struct rmi_device *rmi_dev = fn->rmi_dev;
-	struct f01_data *data = fn->data;
+	return 0;
+}
+
+static int rmi_f01_attention(struct rmi_function_dev *fn_dev,
+						unsigned long *irq_bits)
+{
+	struct rmi_device *rmi_dev = fn_dev->rmi_dev;
+	struct f01_data *data = fn_dev->data;
 	int retval;
 
-	retval = rmi_read_block(rmi_dev, fn->fd.data_base_addr,
+	retval = rmi_read_block(rmi_dev, fn_dev->fd.data_base_addr,
 		&data->device_status, sizeof(data->device_status));
 	if (retval < 0) {
-		dev_err(&fn->dev, "Failed to read device status, code: %d.\n",
+		dev_err(&fn_dev->dev, "Failed to read device status, code: %d.\n",
 			retval);
 		return retval;
 	}
 	if (data->device_status.unconfigured) {
-		dev_warn(&fn->dev, "Device reset detected.\n");
+		dev_warn(&fn_dev->dev, "Device reset detected.\n");
 		retval = rmi_dev->driver->reset_handler(rmi_dev);
 		if (retval < 0)
 			return retval;
@@ -1227,16 +389,17 @@ static int rmi_f01_attention(struct rmi_function *fn,
 	return 0;
 }
 
-struct rmi_function_handler rmi_f01_handler = {
+struct rmi_function_driver rmi_f01_driver = {
 	.driver = {
 		.name = "rmi_f01",
 	},
-	.func = 0x01,
+	.func = FUNCTION_NUMBER,
 	.probe = rmi_f01_probe,
 	.remove = rmi_f01_remove,
 	.config = rmi_f01_config,
 	.attention = rmi_f01_attention,
-#ifdef CONFIG_PM
+
+#ifdef	CONFIG_PM
 	.suspend = rmi_f01_suspend,
 	.resume = rmi_f01_resume,
 #endif  /* CONFIG_PM */
diff --git a/drivers/input/rmi4/rmi_f01.h b/drivers/input/rmi4/rmi_f01.h
index 8092b7f..d388c63 100644
--- a/drivers/input/rmi4/rmi_f01.h
+++ b/drivers/input/rmi4/rmi_f01.h
@@ -30,6 +30,8 @@
 
 #define F01_RESET_MASK 0x01
 
+#define F01_SERIALIZATION_SIZE 7
+
 /**
  * @manufacturer_id - reports the identity of the manufacturer of the RMI
  * device. Synaptics RMI devices report a Manufacturer ID of $01.
@@ -49,19 +51,6 @@
  * product spec sheet.
  * @productinfo_2 - meaning varies from product to product, consult your
  * product spec sheet.
- * @year - year of manufacture MOD 2000.
- * @month - month of manufacture
- * @day - day of manufacture
- * @wafer_id1_lsb - The wafer-lot ID registers record the lot number of the
- * wafer from which the module’s touch controller was produced.
- * @wafer_id1_msb - The wafer-lot ID registers record the lot number of the
- * wafer from which the module’s touch controller was produced.
- * @wafer_id2_lsb - The wafer-lot ID registers record the lot number of the
- * wafer from which the module’s touch controller was produced.
- * @wafer_id2_msb - The wafer-lot ID registers record the lot number of the
- * wafer from which the module’s touch controller was produced.
- * @wafer_id3_lsb - The wafer-lot ID registers record the lot number of the
- * wafer from which the module’s touch controller was produced.
  */
 struct f01_basic_queries {
 	u8 manufacturer_id:8;
@@ -77,21 +66,9 @@ struct f01_basic_queries {
 
 	u8 productinfo_1:7;
 	u8 q2_bit_7:1;
-
 	u8 productinfo_2:7;
 	u8 q3_bit_7:1;
 
-	u8 year:5;
-	u8 month:4;
-	u8 day:5;
-	u8 cp1:1;
-	u8 cp2:1;
-
-	u8 wafer_id1_lsb:8;
-	u8 wafer_id1_msb:8;
-	u8 wafer_id2_lsb:8;
-	u8 wafer_id2_msb:8;
-	u8 wafer_id3_lsb:8;
 } __attribute__((__packed__));
 
 /** The status code field reports the most recent device status event.
@@ -120,7 +97,7 @@ enum rmi_device_status {
  * @unconfigured - the device has lost its configuration for some reason.
  */
 struct f01_device_status {
-	u8 status_code:4;
+	enum rmi_device_status status_code:4;
 	u8 reserved:2;
 	u8 flash_prog:1;
 	u8 unconfigured:1;
@@ -159,4 +136,113 @@ struct f01_device_control_0 {
 	u8 configured:1;
 } __attribute__((__packed__));
 
+/**
+ * @reset - set this bit to force a firmware reset of the sensor.
+ */
+struct f01_device_commands {
+	u8 reset:1;
+	u8 reserved:7;
+};
+
+/**
+ * @ctrl0 - see documentation in rmi_f01.h.
+ * @interrupt_enable - A mask of per-function interrupts on the touch sensor.
+ * @doze_interval - controls the interval between checks for finger presence
+ * when the touch sensor is in doze mode, in units of 10ms.
+ * @wakeup_threshold - controls the capacitance threshold at which the touch
+ * sensor will decide to wake up from that low power state.
+ * @doze_holdoff - controls how long the touch sensor waits after the last
+ * finger lifts before entering the doze state, in units of 100ms.
+ */
+struct f01_device_control {
+	struct f01_device_control_0 ctrl0;
+	u8 *interrupt_enable;
+	u8 doze_interval;
+	u8 wakeup_threshold;
+	u8 doze_holdoff;
+};
+
+/**
+ * @has_ds4_queries - if true, the query registers relating to Design Studio 4
+ * features are present.
+ * @has_multi_phy - if true, multiple physical communications interfaces are
+ * supported.
+ * @has_guest - if true, a "guest" device is supported.
+ */
+struct f01_query_42 {
+		u8 has_ds4_queries:1;
+		u8 has_multi_phy:1;
+		u8 has_guest:1;
+		u8 reserved:5;
+} __attribute__((__packed__));
+
+/**
+ * @length - the length of the remaining Query43.* register block, not
+ * including the first register.
+ * @has_package_id_query -  the package ID query data will be accessible from
+ * inside the ProductID query registers.
+ * @has_packrat_query -  the packrat query data will be accessible from inside
+ * the ProductID query registers.
+ * @has_reset_query - the reset pin related registers are valid.
+ * @has_maskrev_query - the silicon mask revision number will be reported.
+ * @has_i2c_control - the register F01_RMI_Ctrl6 will exist.
+ * @has_spi_control - the register F01_RMI_Ctrl7 will exist.
+ * @has_attn_control - the register F01_RMI_Ctrl8 will exist.
+ * @reset_enabled - the hardware reset pin functionality has been enabled
+ * for this device.
+ * @reset_polarity - If this bit reports as ‘0’, it means that the reset state
+ * is active low. A ‘1’ means that the reset state is active high.
+ * @pullup_enabled - If set, it indicates that a built-in weak pull up has
+ * been enabled on the Reset pin; clear means that no pull-up is present.
+ * @reset_pin_number - This field represents which GPIO pin number has been
+ * assigned the reset functionality.
+ */
+struct f01_ds4_queries {
+	u8 length:4;
+	u8 reserved_1:4;
+
+	u8 has_package_id_query:1;
+	u8 has_packrat_query:1;
+	u8 has_reset_query:1;
+	u8 has_maskrev_query:1;
+	u8 reserved_2:4;
+
+	u8 has_i2c_control:1;
+	u8 has_spi_control:1;
+	u8 has_attn_control:1;
+	u8 reserved_3:5;
+
+	u8 reset_enabled:1;
+	u8 reset_polarity:1;
+	u8 pullup_enabled:1;
+	u8 reserved_4:1;
+	u8 reset_pin_number:4;
+} __attribute__((__packed__));
+
+/*
+ *
+ * @serialization - 7 bytes of device serialization data.  The meaning of
+ * these bytes varies from product to product, consult your product spec sheet.
+ */
+struct f01_data {
+	struct f01_device_control device_control;
+	struct f01_basic_queries basic_queries;
+	struct f01_device_status device_status;
+	u8 serialization[F01_SERIALIZATION_SIZE];
+	u8 product_id[RMI_PRODUCT_ID_LENGTH+1];
+
+	u16 interrupt_enable_addr;
+	u16 doze_interval_addr;
+	u16 wakeup_threshold_addr;
+	u16 doze_holdoff_addr;
+
+	int irq_count;
+	int num_of_irq_regs;
+
+#ifdef	CONFIG_PM
+	bool suspended;
+	bool old_nosleep;
+#endif
+};
+
 #endif

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 05/05] input: RMI4 F11 2D input
  2013-01-19  1:12 [PATCH 00/05] input: RMI4 Synaptics RMI4 Touchscreen Driver Christopher Heiny
                   ` (3 preceding siblings ...)
  2013-01-19  1:12 ` [PATCH 04/05] input: RMI4 F01 device control Christopher Heiny
@ 2013-01-19  1:12 ` Christopher Heiny
  2014-02-04  7:56 ` [PATCH 00/05] input: RMI4 Synaptics RMI4 Touchscreen Driver Linus Walleij
  5 siblings, 0 replies; 11+ messages in thread
From: Christopher Heiny @ 2013-01-19  1:12 UTC (permalink / raw)
  To: Dmitry Torokhov
  Cc: Jean Delvare, Linux Kernel, Linux Input, Christopher Heiny,
	Allie Xiong, Vivian Ly, Daniel Rosenberg, Alexandra Chin,
	Joerie de Gram, Wolfram Sang, Mathieu Poirier, Linus Walleij

In addition to the changes described in 0/5 of this patchset, this patch
includes:

* some fixes to the input device parameters.

* removal of some stray Android stuff.

Signed-off-by: Christopher Heiny <cheiny@synaptics.com>
Cc: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Cc: Linus Walleij <linus.walleij@stericsson.com>
Cc: Joeri de Gram <j.de.gram@gmail.com>
Acked-by: Jean Delvare <khali@linux-fr.org>

---

 drivers/input/rmi4/rmi_f11.c | 2028 ++----------------------------------------
 drivers/input/rmi4/rmi_f11.h |  779 ++++++++++++++++
 2 files changed, 852 insertions(+), 1955 deletions(-)

diff --git a/drivers/input/rmi4/rmi_f11.c b/drivers/input/rmi4/rmi_f11.c
index 8457ab4..bd4cbe3 100644
--- a/drivers/input/rmi4/rmi_f11.c
+++ b/drivers/input/rmi4/rmi_f11.c
@@ -2,40 +2,28 @@
  * Copyright (c) 2011,2012 Synaptics Incorporated
  * Copyright (c) 2011 Unixphere
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
  */
 
 #define FUNCTION_DATA f11_data
+#define FUNCTION_NUMBER 0x11
 
 #include <linux/kernel.h>
 #include <linux/delay.h>
 #include <linux/device.h>
+#include <linux/fs.h>
 #include <linux/input.h>
 #include <linux/input/mt.h>
 #include <linux/kconfig.h>
 #include <linux/rmi.h>
 #include <linux/slab.h>
-#include "rmi_driver.h"
-
-#ifdef CONFIG_RMI4_DEBUG
-#include <linux/debugfs.h>
-#include <linux/fs.h>
 #include <linux/uaccess.h>
-#endif
 
-#define F11_MAX_NUM_OF_SENSORS		8
+#include "rmi_driver.h"
+#include "rmi_f11.h"
+
 #define F11_MAX_NUM_OF_FINGERS		10
 #define F11_MAX_NUM_OF_TOUCH_SHAPES	16
 
@@ -53,185 +41,6 @@
 #define DEFAULT_MAX_ABS_MT_ORIENTATION 1
 #define DEFAULT_MIN_ABS_MT_TRACKING_ID 1
 #define DEFAULT_MAX_ABS_MT_TRACKING_ID 10
-#define NAME_BUFFER_SIZE 256
-#define FUNCTION_NUMBER 0x11
-
-/** A note about RMI4 F11 register structure.
- *
- *  There may be one or more individual 2D touch surfaces associated with an
- * instance for F11.  For example, a handheld device might have a touchscreen
- * display on the front, and a touchpad on the back.  F11 represents these touch
- * surfaces as individual sensors, up to 7 on a given RMI4 device.
- *
- * The properties for
- * a given sensor are described by its query registers.  The number of query
- * registers and the layout of their contents are described by the F11 device
- * queries as well as the per-sensor query information.  The query registers
- * for sensor[n+1] immediately follow those for sensor[n], so the start address
- * of the sensor[n+1] queries can only be computed if you know the size of the
- * sensor[n] queries.  Because each of the sensors may have different
- * properties, the size of the query registers for each sensor must be
- * calculated on a sensor by sensor basis.
- *
- * Similarly, each sensor has control registers that govern its behavior.  The
- * size and layout of the control registers for a given sensor can be determined
- * by parsing that sensors query registers.  The control registers for
- * sensor[n+1] immediately follow those for sensor[n], so you can only know
- * the start address for the sensor[n+1] controls if you know the size (and
- * location) of the sensor[n] controls.
- *
- * And in a likewise fashion, each sensor has data registers where it reports
- * its touch data and other interesting stuff.  The size and layout of a
- * sensors data registers must be determined by parsing its query registers.
- * The data registers for sensor[n+1] immediately follow those for sensor[n],
- * so you can only know the start address for the sensor[n+1] controls if you
- * know the size (and location) of the sensor[n] controls.
- *
- * The short story is that we need to read and parse a lot of query
- * registers in order to determine the attributes of a sensor[0].  Then
- * we need to use that data to compute the size of the control and data
- * registers for sensor[0].  Once we have that figured out, we can then do
- * the same thing for each subsequent sensor.
- *
- * The end result is that we have a number of structs that aren't used to
- * directly generate the input events, but their size, location and contents
- * are critical to determining where the data we are interested in lives.
- *
- * At this time, the driver does not yet comprehend all possible F11
- * configuration options, but it should be sufficient to cover 99% of RMI4 F11
- * devices currently in the field.
- */
-
-/**
- * @rezero - writing 1 to this will cause the sensor to calibrate to the
- * current capacitive state.
- */
-struct f11_2d_commands {
-	u8 rezero:1;
-	u8 reserved:7;
-} __attribute__((__packed__));
-
-/** This query is always present, and is on a per device basis.  All other
- * queries are on a per-sensor basis.
- *
- * @nbr_of_sensors - the number of 2D sensors on the touch device.
- * @has_query9 - indicates the F11_2D_Query9 register exists.
- * @has_query11 - indicates the F11_2D_Query11 register exists.
- * @has_query12 - indicates the F11_2D_Query12 register exists.
- */
-struct f11_2d_device_query {
-	u8 nbr_of_sensors:3;
-	u8 has_query9:1;
-	u8 has_query11:1;
-	u8 has_query12:1;
-	u8 has_query27:1;
-	u8 has_query28:1;
-} __attribute__((__packed__));
-
-/** Query registers 1 through 4 are always present.
- * @number_of_fingers - describes the maximum number of fingers the 2-D sensor
- * supports.
- * @has_rel - the sensor supports relative motion reporting.
- * @has_abs - the sensor supports absolute poition reporting.
- * @has_gestures - the sensor supports gesture reporting.
- * @has_sensitivity_adjust - the sensor supports a global sensitivity
- * adjustment.
- * @configurable - the sensor supports various configuration options.
- * @num_of_x_electrodes -  the maximum number of electrodes the 2-D sensor
- * supports on the X axis.
- * @num_of_y_electrodes -  the maximum number of electrodes the 2-D sensor
- * supports on the Y axis.
- * @max_electrodes - the total number of X and Y electrodes that may be
- * configured.
- */
-struct f11_2d_sensor_info {
-	/* query1 */
-	u8 number_of_fingers:3;
-	u8 has_rel:1;
-	u8 has_abs:1;
-	u8 has_gestures:1;
-	u8 has_sensitivity_adjust:1;
-	u8 configurable:1;
-	/* query2 */
-	u8 num_of_x_electrodes:7;
-	u8 reserved_1:1;
-	/* query3 */
-	u8 num_of_y_electrodes:7;
-	u8 reserved_2:1;
-	/* query4 */
-	u8 max_electrodes:7;
-	u8 reserved_3:1;
-} __attribute__((__packed__));
-
-/** Query 5 - this is present if the has_abs bit is set.
- *
- * @abs_data_size - describes the format of data reported by the absolute
- * data source.  Only one format (the kind used here) is supported at this
- * time.
- * @has_anchored_finger - then the sensor supports the high-precision second
- * finger tracking provided by the manual tracking and motion sensitivity
- * options.
- * @has_adjust_hyst - the difference between the finger release threshold and
- * the touch threshold.
- * @has_dribble - the sensor supports the generation of dribble interrupts,
- * which may be enabled or disabled with the dribble control bit.
- * @has_bending_correction - Bending related data registers 28 and 36, and
- * control register 52..57 are present.
- * @has_large_object_suppression - control register 58 and data register 28
- * exist.
- * @has_jitter_filter - query 13 and control 73..76 exist.
- */
-struct f11_2d_abs_info {
-	u8 abs_data_size:2;
-	u8 has_anchored_finger:1;
-	u8 has_adj_hyst:1;
-	u8 has_dribble:1;
-	u8 has_bending_correction:1;
-	u8 has_large_object_suppression:1;
-	u8 has_jitter_filter:1;
-} __attribute__((__packed__));
-
-/** Gesture information queries 7 and 8 are present if has_gestures bit is set.
- *
- * @has_single_tap - a basic single-tap gesture is supported.
- * @has_tap_n_hold - tap-and-hold gesture is supported.
- * @has_double_tap - double-tap gesture is supported.
- * @has_early_tap - early tap is supported and reported as soon as the finger
- * lifts for any tap event that could be interpreted as either a single tap
- * or as the first tap of a double-tap or tap-and-hold gesture.
- * @has_flick - flick detection is supported.
- * @has_press - press gesture reporting is supported.
- * @has_pinch - pinch gesture detection is supported.
- * @has_palm_det - the 2-D sensor notifies the host whenever a large conductive
- * object such as a palm or a cheek touches the 2-D sensor.
- * @has_rotate - rotation gesture detection is supported.
- * @has_touch_shapes - TouchShapes are supported.  A TouchShape is a fixed
- * rectangular area on the sensor that behaves like a capacitive button.
- * @has_scroll_zones - scrolling areas near the sensor edges are supported.
- * @has_individual_scroll_zones - if 1, then 4 scroll zones are supported;
- * if 0, then only two are supported.
- * @has_multi_finger_scroll - the multifinger_scrolling bit will be set when
- * more than one finger is involved in a scrolling action.
- */
-struct f11_2d_gesture_info {
-	u8 has_single_tap:1;
-	u8 has_tap_n_hold:1;
-	u8 has_double_tap:1;
-	u8 has_early_tap:1;
-	u8 has_flick:1;
-	u8 has_press:1;
-	u8 has_pinch:1;
-	u8 has_chiral:1;
-
-	u8 has_palm_det:1;
-	u8 has_rotate:1;
-	u8 has_touch_shapes:1;
-	u8 has_scroll_zones:1;
-	u8 has_individual_scroll_zones:1;
-	u8 has_multi_finger_scroll:1;
-	u8 has_mf_edge_motion:1;
-	u8 has_mf_scroll_inertia:1;
-} __attribute__((__packed__));
 
 /** Utility for checking bytes in the gesture info registers.  This is done
  * often enough that we put it here to declutter the conditionals.
@@ -241,620 +50,6 @@ static bool has_gesture_bits(const struct f11_2d_gesture_info *info,
 	return ((u8 *) info)[byte] != 0;
 }
 
-/**
- * @has_pen - detection of a stylus is supported and registers F11_2D_Ctrl20
- * and F11_2D_Ctrl21 exist.
- * @has_proximity - detection of fingers near the sensor is supported and
- * registers F11_2D_Ctrl22 through F11_2D_Ctrl26 exist.
- * @has_palm_det_sensitivity -  the sensor supports the palm detect sensitivity
- * feature and register F11_2D_Ctrl27 exists.
- * @has_two_pen_thresholds - is has_pen is also set, then F11_2D_Ctrl35 exists.
- * @has_contact_geometry - the sensor supports the use of contact geometry to
- * map absolute X and Y target positions and registers F11_2D_Data18.* through
- * F11_2D_Data27 exist.
- */
-struct f11_2d_query9 {
-	u8 has_pen:1;
-	u8 has_proximity:1;
-	u8 has_palm_det_sensitivity:1;
-	u8 has_suppress_on_palm_detect:1;
-	u8 has_two_pen_thresholds:1;
-	u8 has_contact_geometry:1;
-	u8 has_pen_hover_discrimination:1;
-	u8 has_pen_filters:1;
-} __attribute__((__packed__));
-
-/** Touch shape info (query 10) is present if has_touch_shapes is set.
- *
- * @nbr_touch_shapes - the total number of touch shapes supported.
- */
-struct f11_2d_ts_info {
-	u8 nbr_touch_shapes:5;
-	u8 reserved:3;
-} __attribute__((__packed__));
-
-/** Query 11 is present if the has_query11 bit is set in query 0.
- *
- * @has_z_tuning - if set, the sensor supports Z tuning and registers
- * F11_2D_Ctrl29 through F11_2D_Ctrl33 exist.
- * @has_algorithm_selection - controls choice of noise suppression algorithm
- * @has_w_tuning - the sensor supports Wx and Wy scaling and registers
- * F11_2D_Ctrl36 through F11_2D_Ctrl39 exist.
- * @has_pitch_info - the X and Y pitches of the sensor electrodes can be
- * configured and registers F11_2D_Ctrl40 and F11_2D_Ctrl41 exist.
- * @has_finger_size -  the default finger width settings for the
- * sensor can be configured and registers F11_2D_Ctrl42 through F11_2D_Ctrl44
- * exist.
- * @has_segmentation_aggressiveness - the sensor’s ability to distinguish
- * multiple objects close together can be configured and register F11_2D_Ctrl45
- * exists.
- * @has_XY_clip -  the inactive outside borders of the sensor can be
- * configured and registers F11_2D_Ctrl46 through F11_2D_Ctrl49 exist.
- * @has_drumming_filter - the sensor can be configured to distinguish
- * between a fast flick and a quick drumming movement and registers
- * F11_2D_Ctrl50 and F11_2D_Ctrl51 exist.
- */
-struct f11_2d_query11 {
-	u8 has_z_tuning:1;
-	u8 has_algorithm_selection:1;
-	u8 has_w_tuning:1;
-	u8 has_pitch_info:1;
-	u8 has_finger_size:1;
-	u8 has_segmentation_aggressiveness:1;
-	u8 has_XY_clip:1;
-	u8 has_drumming_filter:1;
-} __attribute__((__packed__));
-
-/**
- * @has_gapless_finger - control registers relating to gapless finger are
- * present.
- * @has_gapless_finger_tuning - additional control and data registers relating
- * to gapless finger are present.
- * @has_8bit_w - larger W value reporting is supported.
- * @has_adjustable_mapping - TBD
- * @has_info2 - the general info query14 is present
- * @has_physical_props - additional queries describing the physical properties
- * of the sensor are present.
- * @has_finger_limit - indicates that F11 Ctrl 80 exists.
- * @has_linear_coeff - indicates that F11 Ctrl 81 exists.
- */
-struct f11_2d_query12 {
-	u8 has_gapless_finger:1;
-	u8 has_gapless_finger_tuning:1;
-	u8 has_8bit_w:1;
-	u8 has_adjustable_mapping:1;
-	u8 has_info2:1;
-	u8 has_physical_props:1;
-	u8 has_finger_limit:1;
-	u8 has_linear_coeff_2:1;
-} __attribute__((__packed__));
-
-/** This register is present if Query 5's has_jitter_filter bit is set.
- * @jitter_window_size - used by Design Studio 4.
- * @jitter_filter_type - used by Design Studio 4.
- */
-struct f11_2d_query13 {
-	u8 jtter_window_size:5;
-	u8 jitter_filter_type:2;
-	u8 reserved:1;
-} __attribute__((__packed__));
-
-/** This register is present if query 12's has_general_info2 flag is set.
- *
- * @light_control - Indicates what light/led control features are present, if
- * any.
- * @is_clear - if set, this is a clear sensor (indicating direct pointing
- * application), otherwise it's opaque (indicating indirect pointing).
- * @clickpad_props - specifies if this is a clickpad, and if so what sort of
- * mechanism it uses
- * @mouse_buttons - specifies the number of mouse buttons present (if any).
- * @has_advanced_gestures - advanced driver gestures are supported.
- */
-struct f11_2d_query14 {
-	u8 light_control:2;
-	u8 is_clear:1;
-	u8 clickpad_props:2;
-	u8 mouse_buttons:2;
-	u8 has_advanced_gestures:1;
-} __attribute__((__packed__));
-
-#define F11_LIGHT_CTL_NONE 0x00
-#define F11_LUXPAD	   0x01
-#define F11_DUAL_MODE      0x02
-
-#define F11_NOT_CLICKPAD     0x00
-#define F11_HINGED_CLICKPAD  0x01
-#define F11_UNIFORM_CLICKPAD 0x02
-
-/** See notes above for information about specific query register sets.
- */
-struct f11_2d_sensor_queries {
-	struct f11_2d_sensor_info info;
-	struct f11_2d_abs_info abs_info;
-	u8 f11_2d_query6;
-	struct f11_2d_gesture_info gesture_info;
-	struct f11_2d_query9 query9;
-	struct f11_2d_ts_info ts_info;
-	struct f11_2d_query11 features_1;
-	struct f11_2d_query12 features_2;
-	struct f11_2d_query13 jitter_filter;
-	struct f11_2d_query14 info_2;
-};
-
-/**
- * @reporting_mode - controls how often finger position data is reported.
- * @abs_pos_filt - when set, enables various noise and jitter filtering
- * algorithms for absolute reports.
- * @rel_pos_filt - when set, enables various noise and jitter filtering
- * algorithms for relative reports.
- * @rel_ballistics - enables ballistics processing for the relative finger
- * motion on the 2-D sensor.
- * @dribble - enables the dribbling feature.
- * @report_beyond_clip - when this is set, fingers outside the active area
- * specified by the x_clip and y_clip registers will be reported, but with
- * reported finger position clipped to the edge of the active area.
- * @palm_detect_thresh - the threshold at which a wide finger is considered a
- * palm. A value of 0 inhibits palm detection.
- * @motion_sensitivity - specifies the threshold an anchored finger must move
- * before it is considered no longer anchored.  High values mean more
- * sensitivity.
- * @man_track_en - for anchored finger tracking, whether the host (1) or the
- * device (0) determines which finger is the tracked finger.
- * @man_tracked_finger - when man_track_en is 1, specifies whether finger 0 or
- * finger 1 is the tracked finger.
- * @delta_x_threshold - 2-D position update interrupts are inhibited unless
- * the finger moves more than a certain threshold distance along the X axis.
- * @delta_y_threshold - 2-D position update interrupts are inhibited unless
- * the finger moves more than a certain threshold distance along the Y axis.
- * @velocity - When rel_ballistics is set, this register defines the
- * velocity ballistic parameter applied to all relative motion events.
- * @acceleration - When rel_ballistics is set, this register defines the
- * acceleration ballistic parameter applied to all relative motion events.
- * @sensor_max_x_pos - the maximum X coordinate reported by the sensor.
- * @sensor_max_y_pos - the maximum Y coordinate reported by the sensor.
- */
-struct f11_2d_ctrl0_9 {
-	/* F11_2D_Ctrl0 */
-	u8 reporting_mode:3;
-	u8 abs_pos_filt:1;
-	u8 rel_pos_filt:1;
-	u8 rel_ballistics:1;
-	u8 dribble:1;
-	u8 report_beyond_clip:1;
-	/* F11_2D_Ctrl1 */
-	u8 palm_detect_thres:4;
-	u8 motion_sensitivity:2;
-	u8 man_track_en:1;
-	u8 man_tracked_finger:1;
-	/* F11_2D_Ctrl2 and 3 */
-	u8 delta_x_threshold:8;
-	u8 delta_y_threshold:8;
-	/* F11_2D_Ctrl4 and 5 */
-	u8 velocity:8;
-	u8 acceleration:8;
-	/* F11_2D_Ctrl6 thru 9 */
-	u16 sensor_max_x_pos:12;
-	u8 ctrl7_reserved:4;
-	u16 sensor_max_y_pos:12;
-	u8 ctrl9_reserved:4;
-} __attribute__((__packed__));
-
-/**
- * @single_tap_int_enable - enable tap gesture recognition.
- * @tap_n_hold_int_enable - enable tap-and-hold gesture recognition.
- * @double_tap_int_enable - enable double-tap gesture recognition.
- * @early_tap_int_enable - enable early tap notification.
- * @flick_int_enable - enable flick detection.
- * @press_int_enable - enable press gesture recognition.
- * @pinch_int_enable - enable pinch detection.
- */
-struct f11_2d_ctrl10 {
-	u8 single_tap_int_enable:1;
-	u8 tap_n_hold_int_enable:1;
-	u8 double_tap_int_enable:1;
-	u8 early_tap_int_enable:1;
-	u8 flick_int_enable:1;
-	u8 press_int_enable:1;
-	u8 pinch_int_enable:1;
-	u8 reserved:1;
-} __attribute__((__packed__));
-
-/**
- * @palm_detect_int_enable - enable palm detection feature.
- * @rotate_int_enable - enable rotate gesture detection.
- * @touch_shape_int_enable - enable the TouchShape feature.
- * @scroll_zone_int_enable - enable scroll zone reporting.
- * @multi_finger_scroll_int_enable - enable the multfinger scroll feature.
- */
-struct f11_2d_ctrl11 {
-	u8 palm_detect_int_enable:1;
-	u8 rotate_int_enable:1;
-	u8 touch_shape_int_enable:1;
-	u8 scroll_zone_int_enable:1;
-	u8 multi_finger_scroll_int_enable:1;
-	u8 reserved:3;
-} __attribute__((__packed__));
-
-/**
- * @sens_adjustment - allows a host to alter the overall sensitivity of a
- * 2-D sensor. A positive value in this register will make the sensor more
- * sensitive than the factory defaults, and a negative value will make it
- * less sensitive.
- * @hyst_adjustment - increase the touch/no-touch hysteresis by 2 Z-units for
- * each one unit increment in this setting.
- */
-struct f11_2d_ctrl14 {
-	s8 sens_adjustment:5;
-	u8 hyst_adjustment:3;
-} __attribute__((__packed__));
-
-/**
- * @max_tap_time - the maximum duration of a tap, in 10-millisecond units.
- */
-struct f11_2d_ctrl15 {
-	u8 max_tap_time:8;
-} __attribute__((__packed__));
-
-/**
- * @min_press_time - The minimum duration required for stationary finger(s) to
- * generate a press gesture, in 10-millisecond units.
- */
-struct f11_2d_ctrl16 {
-	u8 min_press_time:8;
-} __attribute__((__packed__));
-
-/**
- * @max_tap_distance - Determines the maximum finger movement allowed during
- * a tap, in 0.1-millimeter units.
- */
-struct f11_2d_ctrl17 {
-	u8 max_tap_distance:8;
-} __attribute__((__packed__));
-
-/**
- * @min_flick_distance - the minimum finger movement for a flick gesture,
- * in 1-millimeter units.
- * @min_flick_speed - the minimum finger speed for a flick gesture, in
- * 10-millimeter/second units.
- */
-struct f11_2d_ctrl18_19 {
-	u8 min_flick_distance:8;
-	u8 min_flick_speed:8;
-} __attribute__((__packed__));
-
-/**
- * @pen_detect_enable - enable reporting of stylus activity.
- * @pen_jitter_filter_enable - Setting this enables the stylus anti-jitter
- * filter.
- * @pen_z_threshold - This is the stylus-detection lower threshold. Smaller
- * values result in higher sensitivity.
- */
-struct f11_2d_ctrl20_21 {
-	u8 pen_detect_enable:1;
-	u8 pen_jitter_filter_enable:1;
-	u8 ctrl20_reserved:6;
-	u8 pen_z_threshold:8;
-} __attribute__((__packed__));
-
-/**
- * These are not accessible through sysfs yet.
- *
- * @proximity_detect_int_en - enable proximity detection feature.
- * @proximity_jitter_filter_en - enables an anti-jitter filter on proximity
- * data.
- * @proximity_detection_z_threshold - the threshold for finger-proximity
- * detection.
- * @proximity_delta_x_threshold - In reduced-reporting modes, this is the
- * threshold for proximate-finger movement in the direction parallel to the
- * X-axis.
- * @proximity_delta_y_threshold - In reduced-reporting modes, this is the
- * threshold for proximate-finger movement in the direction parallel to the
- * Y-axis.
- * * @proximity_delta_Z_threshold - In reduced-reporting modes, this is the
- * threshold for proximate-finger movement in the direction parallel to the
- * Z-axis.
- */
-struct f11_2d_ctrl22_26 {
-	/* control 22 */
-	u8 proximity_detect_int_en:1;
-	u8 proximity_jitter_filter_en:1;
-	u8 f11_2d_ctrl6_b3__7:6;
-
-	/* control 23 */
-	u8 proximity_detection_z_threshold;
-
-	/* control 24 */
-	u8 proximity_delta_x_threshold;
-
-	/* control 25 */
-	u8 proximity_delta_y_threshold;
-
-	/* control 26 */
-	u8 proximity_delta_z_threshold;
-} __attribute__((__packed__));
-
-/**
- * @palm_detecy_sensitivity - When this value is small, smaller objects will
- * be identified as palms; when this value is large, only larger objects will
- * be identified as palms. 0 represents the factory default.
- * @suppress_on_palm_detect - when set, all F11 interrupts except palm_detect
- * are suppressed while a palm is detected.
- */
-struct f11_2d_ctrl27 {
-	s8 palm_detect_sensitivity:4;
-	u8 suppress_on_palm_detect:1;
-	u8 f11_2d_ctrl27_b5__7:3;
-} __attribute__((__packed__));
-
-/**
- * @multi_finger_scroll_mode - allows choice of multi-finger scroll mode and
- * determines whether and how X or Y displacements are reported.
- * @edge_motion_en - enables the edge_motion feature.
- * @multi_finger_scroll_momentum - controls the length of time that scrolling
- * continues after fingers have been lifted.
- */
-struct f11_2d_ctrl28 {
-	u8 multi_finger_scroll_mode:2;
-	u8 edge_motion_en:1;
-	u8 f11_2d_ctrl28b_3:1;
-	u8 multi_finger_scroll_momentum:4;
-} __attribute__((__packed__));
-
-/**
- * @z_touch_threshold - Specifies the finger-arrival Z threshold. Large values
- * may cause smaller fingers to be rejected.
- * @z_touch_hysteresis - Specifies the difference between the finger-arrival
- * Z threshold and the finger-departure Z threshold.
- */
-struct f11_2d_ctrl29_30 {
-	u8 z_touch_threshold;
-	u8 z_touch_hysteresis;
-} __attribute__((__packed__));
-
-
-struct f11_2d_ctrl {
-	struct f11_2d_ctrl0_9		 *ctrl0_9;
-	u16				ctrl0_9_address;
-	struct f11_2d_ctrl10		*ctrl10;
-	struct f11_2d_ctrl11		*ctrl11;
-	u8				ctrl12_size;
-	struct f11_2d_ctrl14		*ctrl14;
-	struct f11_2d_ctrl15		*ctrl15;
-	struct f11_2d_ctrl16		*ctrl16;
-	struct f11_2d_ctrl17		*ctrl17;
-	struct f11_2d_ctrl18_19		*ctrl18_19;
-	struct f11_2d_ctrl20_21		*ctrl20_21;
-	struct f11_2d_ctrl22_26		*ctrl22_26;
-	struct f11_2d_ctrl27		*ctrl27;
-	struct f11_2d_ctrl28		*ctrl28;
-	struct f11_2d_ctrl29_30		*ctrl29_30;
-};
-
-/**
- * @x_msb - top 8 bits of X finger position.
- * @y_msb - top 8 bits of Y finger position.
- * @x_lsb - bottom 4 bits of X finger position.
- * @y_lsb - bottom 4 bits of Y finger position.
- * @w_y - contact patch width along Y axis.
- * @w_x - contact patch width along X axis.
- * @z - finger Z value (proxy for pressure).
- */
-struct f11_2d_data_1_5 {
-	u8 x_msb;
-	u8 y_msb;
-	u8 x_lsb:4;
-	u8 y_lsb:4;
-	u8 w_y:4;
-	u8 w_x:4;
-	u8 z;
-} __attribute__((__packed__));
-
-/**
- * @delta_x - relative motion along X axis.
- * @delta_y - relative motion along Y axis.
- */
-struct f11_2d_data_6_7 {
-	s8 delta_x;
-	s8 delta_y;
-} __attribute__((__packed__));
-
-/**
- * @single_tap - a single tap was recognized.
- * @tap_and_hold - a tap-and-hold gesture was recognized.
- * @double_tap - a double tap gesture was recognized.
- * @early_tap - a tap gesture might be happening.
- * @flick - a flick gesture was detected.
- * @press - a press gesture was recognized.
- * @pinch - a pinch gesture was detected.
- */
-struct f11_2d_data_8 {
-	bool single_tap:1;
-	bool tap_and_hold:1;
-	bool double_tap:1;
-	bool early_tap:1;
-	bool flick:1;
-	bool press:1;
-	bool pinch:1;
-} __attribute__((__packed__));
-
-/**
- * @palm_detect - a palm or other large object is in contact with the sensor.
- * @rotate - a rotate gesture was detected.
- * @shape - a TouchShape has been activated.
- * @scrollzone - scrolling data is available.
- * @finger_count - number of fingers involved in the reported gesture.
- */
-struct f11_2d_data_9 {
-	bool palm_detect:1;
-	bool rotate:1;
-	bool shape:1;
-	bool scrollzone:1;
-	u8 finger_count:3;
-} __attribute__((__packed__));
-
-/**
- * @pinch_motion - when a pinch gesture is detected, this is the change in
- * distance between the two fingers since this register was last read.
- */
-struct f11_2d_data_10 {
-	s8 pinch_motion;
-} __attribute__((__packed__));
-
-/**
- * @x_flick_dist - when a flick gesture is detected,  the distance of flick
- * gesture in X direction.
- * @y_flick_dist - when a flick gesture is detected,  the distance of flick
- * gesture in Y direction.
- * @flick_time - the total time of the flick gesture, in 10ms units.
- */
-struct f11_2d_data_10_12 {
-	s8 x_flick_dist;
-	s8 y_flick_dist;
-	u8 flick_time;
-} __attribute__((__packed__));
-
-/**
- * @motion - when a rotate gesture is detected, the accumulated distance
- * of the rotate motion. Clockwise motion is positive and counterclockwise
- * motion is negative.
- * @finger_separation - when a rotate gesture is detected, the distance
- * between the fingers.
- */
-struct f11_2d_data_11_12 {
-	s8 motion;
-	u8 finger_separation;
-} __attribute__((__packed__));
-
-/**
- * @shape_n - a bitmask of the currently activate TouchShapes (if any).
- */
-struct f11_2d_data_13 {
-	u8 shape_n;
-} __attribute__((__packed__));
-
-/**
- * @horizontal - chiral scrolling distance in the X direction.
- * @vertical - chiral scrolling distance in the Y direction.
- */
-struct f11_2d_data_14_15 {
-	s8 horizontal;
-	s8 vertical;
-} __attribute__((__packed__));
-
-/**
- * @x_low - scroll zone motion along the lower edge of the sensor.
- * @y_right - scroll zone motion along the right edge of the sensor.
- * @x_upper - scroll zone motion along the upper edge of the sensor.
- * @y_left - scroll zone motion along the left edge of the sensor.
- */
-struct f11_2d_data_14_17 {
-	s8 x_low;
-	s8 y_right;
-	s8 x_upper;
-	s8 y_left;
-} __attribute__((__packed__));
-
-struct f11_2d_data {
-	u8				*f_state;
-	const struct f11_2d_data_1_5	*abs_pos;
-	const struct f11_2d_data_6_7	*rel_pos;
-	const struct f11_2d_data_8	*gest_1;
-	const struct f11_2d_data_9	*gest_2;
-	const struct f11_2d_data_10	*pinch;
-	const struct f11_2d_data_10_12	*flick;
-	const struct f11_2d_data_11_12	*rotate;
-	const struct f11_2d_data_13	*shapes;
-	const struct f11_2d_data_14_15	*multi_scroll;
-	const struct f11_2d_data_14_17	*scroll_zones;
-};
-
-/**
- * @axis_align - controls parameters that are useful in system prototyping
- * and bring up.
- * @sens_query - query registers for this particular sensor.
- * @data - the data reported by this sensor, mapped into a collection of
- * structs.
- * @max_x - The maximum X coordinate that will be reported by this sensor.
- * @max_y - The maximum Y coordinate that will be reported by this sensor.
- * @nbr_fingers - How many fingers can this sensor report?
- * @data_pkt - buffer for data reported by this sensor.
- * @pkt_size - number of bytes in that buffer.
- * @sensor_index - identifies this particular 2D touch sensor
- * @type_a - some early RMI4 2D sensors do not reliably track the finger
- * position when two fingers are on the device.  When this is true, we
- * assume we have one of those sensors and report events appropriately.
- * @sensor_type - indicates whether we're touchscreen or touchpad.
- * @input - input device for absolute pointing stream
- * @mouse_input - input device for relative pointing stream.
- * @input_phys - buffer for the absolute phys name for this sensor.
- * @input_mouse_phys - buffer for the relative phys name for this sensor.
- * @debugfs_flip - inverts one or both axes.  Useful in prototyping new
- * systems.
- * @debugfs_flip - coordinate clipping range for one or both axes.  Useful in
- * prototyping new systems.
- * @debugfs_delta_threshold - adjusts motion sensitivity for relative reports
- * and (in reduced reporting mode) absolute reports.  Useful in prototyping new
- * systems.
- * @debugfs_offset - offsets one or both axes.  Useful in prototyping new
- * systems.
- * @debugfs_swap - swaps X and Y axes.  Useful in prototyping new systems.
- * @debugfs_type_a - forces type A behavior.  Useful in bringing up old systems
- * when you're not sure if you've got a Type A or Type B sensor.
- */
-struct f11_2d_sensor {
-	struct rmi_f11_2d_axis_alignment axis_align;
-	struct f11_2d_sensor_queries sens_query;
-	struct f11_2d_data data;
-	u16 max_x;
-	u16 max_y;
-	u8 nbr_fingers;
-	u8 *data_pkt;
-	int pkt_size;
-	u8 sensor_index;
-	bool type_a;
-	enum rmi_f11_sensor_type sensor_type;
-	struct input_dev *input;
-	struct input_dev *mouse_input;
-	struct rmi_function *fn;
-	char input_phys[NAME_BUFFER_SIZE];
-	char input_phys_mouse[NAME_BUFFER_SIZE];
-
-#ifdef CONFIG_RMI4_DEBUG
-	struct dentry *debugfs_flip;
-	struct dentry *debugfs_clip;
-	struct dentry *debugfs_delta_threshold;
-	struct dentry *debugfs_offset;
-	struct dentry *debugfs_swap;
-	struct dentry *debugfs_type_a;
-#endif
-};
-
-/** Data pertaining to F11 in general.  For per-sensor data, see struct
- * f11_2d_sensor.
- *
- * @dev_query - F11 device specific query registers.
- * @dev_controls - F11 device specific control registers.
- * @dev_controls_mutex - lock for the control registers.
- * @rezero_wait_ms - if nonzero, upon resume we will wait this many
- * milliseconds before rezeroing the sensor(s).  This is useful in systems with
- * poor electrical behavior on resume, where the initial calibration of the
- * sensor(s) coming out of sleep state may be bogus.
- * @sensors - per sensor data structures.
- * @debugfs_rezero_wait - allows control of the rezero_wait value.  Useful
- * during system prototyping.
- */
-struct f11_data {
-	struct f11_2d_device_query dev_query;
-	struct f11_2d_ctrl dev_controls;
-	struct mutex dev_controls_mutex;
-	u16 rezero_wait_ms;
-	struct f11_2d_sensor sensors[F11_MAX_NUM_OF_SENSORS];
-
-#ifdef CONFIG_RMI4_DEBUG
-	struct dentry *debugfs_rezero_wait;
-#endif
-};
-
 enum finger_state_values {
 	F11_NO_FINGER	= 0x00,
 	F11_PRESENT	= 0x01,
@@ -862,705 +57,6 @@ enum finger_state_values {
 	F11_RESERVED	= 0x03
 };
 
-static ssize_t f11_maxPos_show(struct device *dev,
-				     struct device_attribute *attr,
-				     char *buf)
-{
-	struct rmi_function *fn;
-	struct f11_data *data;
-
-	fn = to_rmi_function(dev);
-	data = fn->data;
-
-	return snprintf(buf, PAGE_SIZE, "%u %u\n",
-			data->sensors[0].max_x, data->sensors[0].max_y);
-}
-
-static ssize_t f11_relreport_show(struct device *dev,
-					struct device_attribute *attr,
-					char *buf)
-{
-	struct rmi_function *fn;
-	struct f11_data *instance_data;
-
-	fn = to_rmi_function(dev);
-	instance_data = fn->data;
-
-	return snprintf(buf, PAGE_SIZE, "%u\n",
-			instance_data->
-			sensors[0].axis_align.rel_report_enabled);
-}
-
-static ssize_t f11_relreport_store(struct device *dev,
-					 struct device_attribute *attr,
-					 const char *buf,
-					 size_t count)
-{
-	struct rmi_function *fn;
-	struct f11_data *instance_data;
-	unsigned int new_value;
-
-	fn = to_rmi_function(dev);
-	instance_data = fn->data;
-
-
-	if (sscanf(buf, "%u", &new_value) != 1)
-		return -EINVAL;
-	if (new_value > 1)
-		return -EINVAL;
-	instance_data->sensors[0].axis_align.rel_report_enabled = new_value;
-
-	return count;
-}
-
-static ssize_t f11_rezero_store(struct device *dev,
-				     struct device_attribute *attr,
-				     const char *buf, size_t count)
-{
-	struct rmi_function *fn = NULL;
-	unsigned int rezero;
-	int retval = 0;
-
-	fn = to_rmi_function(dev);
-
-	if (sscanf(buf, "%u", &rezero) != 1)
-		return -EINVAL;
-	if (rezero > 1)
-		return -EINVAL;
-
-	/* Per spec, 0 has no effect, so we skip it entirely. */
-	if (rezero) {
-		/* Command register always reads as 0, so just use a local. */
-		struct f11_2d_commands commands = {
-			.rezero = true,
-		};
-
-		retval = rmi_write_block(fn->rmi_dev, fn->fd.command_base_addr,
-				&commands, sizeof(commands));
-		if (retval < 0) {
-			dev_err(dev, "%s: failed to issue rezero command, error = %d.",
-				__func__, retval);
-			return retval;
-		}
-	}
-
-	return count;
-}
-
-static struct device_attribute attrs[] = {
-	__ATTR(relreport, RMI_RW_ATTR, f11_relreport_show, f11_relreport_store),
-	__ATTR(maxPos, RMI_RO_ATTR, f11_maxPos_show, NULL),
-	__ATTR(rezero, RMI_WO_ATTR, NULL, f11_rezero_store)
-};
-
-#ifdef CONFIG_RMI4_DEBUG
-
-struct sensor_debugfs_data {
-	bool done;
-	struct f11_2d_sensor *sensor;
-};
-
-static int sensor_debug_open(struct inode *inodep, struct file *filp)
-{
-	struct sensor_debugfs_data *data;
-	struct f11_2d_sensor *sensor = inodep->i_private;
-
-	data = kzalloc(sizeof(struct sensor_debugfs_data), GFP_KERNEL);
-	if (!data)
-		return -ENOMEM;
-
-	data->sensor = sensor;
-	filp->private_data = data;
-	return 0;
-}
-
-static int sensor_debug_release(struct inode *inodep, struct file *filp)
-{
-	kfree(filp->private_data);
-	return 0;
-}
-
-static ssize_t flip_read(struct file *filp, char __user *buffer, size_t size,
-		    loff_t *offset) {
-	int retval;
-	char *local_buf;
-	struct sensor_debugfs_data *data = filp->private_data;
-
-	if (data->done)
-		return 0;
-
-	local_buf = kcalloc(size, sizeof(u8), GFP_KERNEL);
-	if (!local_buf)
-		return -ENOMEM;
-
-	data->done = 1;
-
-	retval = snprintf(local_buf, size, "%u %u\n",
-			data->sensor->axis_align.flip_x,
-			data->sensor->axis_align.flip_y);
-
-	if (retval <= 0 || copy_to_user(buffer, local_buf, retval))
-		retval = -EFAULT;
-	kfree(local_buf);
-
-	return retval;
-}
-
-static ssize_t flip_write(struct file *filp, const char __user *buffer,
-			   size_t size, loff_t *offset) {
-	int retval;
-	char *local_buf;
-	unsigned int new_X;
-	unsigned int new_Y;
-	struct sensor_debugfs_data *data = filp->private_data;
-
-	local_buf = kcalloc(size, sizeof(u8), GFP_KERNEL);
-	if (!local_buf)
-		return -ENOMEM;
-
-	retval = copy_from_user(local_buf, buffer, size);
-	if (retval) {
-		kfree(local_buf);
-		return -EFAULT;
-	}
-
-	retval = sscanf(local_buf, "%u %u", &new_X, &new_Y);
-	kfree(local_buf);
-	if (retval != 2 || new_X > 1 || new_Y > 1)
-		return -EINVAL;
-
-	data->sensor->axis_align.flip_x = new_X;
-	data->sensor->axis_align.flip_y = new_Y;
-
-	return size;
-}
-
-static const struct file_operations flip_fops = {
-	.owner = THIS_MODULE,
-	.open = sensor_debug_open,
-	.release = sensor_debug_release,
-	.read = flip_read,
-	.write = flip_write,
-};
-
-static ssize_t delta_threshold_read(struct file *filp, char __user *buffer,
-		size_t size, loff_t *offset) {
-	int retval;
-	char *local_buf;
-	struct sensor_debugfs_data *data = filp->private_data;
-	struct f11_data *f11 = data->sensor->fn->data;
-	struct f11_2d_ctrl *ctrl = &f11->dev_controls;
-
-	if (data->done)
-		return 0;
-
-	local_buf = kcalloc(size, sizeof(u8), GFP_KERNEL);
-	if (!local_buf)
-		return -ENOMEM;
-
-	data->done = 1;
-
-	retval = snprintf(local_buf, size, "%u %u\n",
-			ctrl->ctrl0_9->delta_x_threshold,
-			ctrl->ctrl0_9->delta_y_threshold);
-
-	if (retval <= 0 || copy_to_user(buffer, local_buf, retval))
-		retval = -EFAULT;
-	kfree(local_buf);
-
-	return retval;
-
-}
-
-static ssize_t delta_threshold_write(struct file *filp,
-		const char __user *buffer, size_t size, loff_t *offset) {
-	int retval;
-	char *local_buf;
-	unsigned int new_X, new_Y;
-	u8 save_X, save_Y;
-	int rc;
-	struct sensor_debugfs_data *data = filp->private_data;
-	struct f11_data *f11 = data->sensor->fn->data;
-	struct f11_2d_ctrl *ctrl = &f11->dev_controls;
-	struct rmi_device *rmi_dev =  data->sensor->fn->rmi_dev;
-
-	local_buf = kcalloc(size, sizeof(u8), GFP_KERNEL);
-	if (!local_buf)
-		return -ENOMEM;
-
-	retval = copy_from_user(local_buf, buffer, size);
-	if (retval) {
-		kfree(local_buf);
-		return -EFAULT;
-	}
-
-	retval = sscanf(local_buf, "%u %u", &new_X, &new_Y);
-	kfree(local_buf);
-	if (retval != 2 || new_X > 1 || new_Y > 1)
-		return -EINVAL;
-
-	save_X = ctrl->ctrl0_9->delta_x_threshold;
-	save_Y = ctrl->ctrl0_9->delta_y_threshold;
-
-	ctrl->ctrl0_9->delta_x_threshold = new_X;
-	ctrl->ctrl0_9->delta_y_threshold = new_Y;
-	rc = rmi_write_block(rmi_dev, ctrl->ctrl0_9_address,
-			ctrl->ctrl0_9, sizeof(*ctrl->ctrl0_9));
-	if (rc < 0) {
-		dev_warn(&data->sensor->fn->dev,
-			"Failed to write to delta_threshold. Code: %d.\n",
-			rc);
-		ctrl->ctrl0_9->delta_x_threshold = save_X;
-		ctrl->ctrl0_9->delta_y_threshold = save_Y;
-	}
-
-	return size;
-}
-
-static const struct file_operations delta_threshold_fops = {
-	.owner = THIS_MODULE,
-	.open = sensor_debug_open,
-	.release = sensor_debug_release,
-	.read = delta_threshold_read,
-	.write = delta_threshold_write,
-};
-
-static ssize_t offset_read(struct file *filp, char __user *buffer, size_t size,
-		    loff_t *offset) {
-	int retval;
-	char *local_buf;
-	struct sensor_debugfs_data *data = filp->private_data;
-
-	if (data->done)
-		return 0;
-
-	local_buf = kcalloc(size, sizeof(u8), GFP_KERNEL);
-	if (!local_buf)
-		return -ENOMEM;
-
-	data->done = 1;
-
-	retval = snprintf(local_buf, size, "%u %u\n",
-			data->sensor->axis_align.offset_X,
-			data->sensor->axis_align.offset_Y);
-
-	if (retval <= 0 || copy_to_user(buffer, local_buf, retval))
-		retval = -EFAULT;
-	kfree(local_buf);
-
-	return retval;
-}
-
-static ssize_t offset_write(struct file *filp, const char __user *buffer,
-			   size_t size, loff_t *offset)
-{
-	int retval;
-	char *local_buf;
-	int new_X;
-	int new_Y;
-	struct sensor_debugfs_data *data = filp->private_data;
-
-	local_buf = kcalloc(size, sizeof(u8), GFP_KERNEL);
-	if (!local_buf)
-		return -ENOMEM;
-
-	retval = copy_from_user(local_buf, buffer, size);
-	if (retval) {
-		kfree(local_buf);
-		return -EFAULT;
-	}
-	retval = sscanf(local_buf, "%u %u", &new_X, &new_Y);
-	kfree(local_buf);
-	if (retval != 2)
-		return -EINVAL;
-
-	data->sensor->axis_align.offset_X = new_X;
-	data->sensor->axis_align.offset_Y = new_Y;
-
-	return size;
-}
-
-static const struct file_operations offset_fops = {
-	.owner = THIS_MODULE,
-	.open = sensor_debug_open,
-	.release = sensor_debug_release,
-	.read = offset_read,
-	.write = offset_write,
-};
-
-static ssize_t clip_read(struct file *filp, char __user *buffer, size_t size,
-		    loff_t *offset) {
-	int retval;
-	char *local_buf;
-	struct sensor_debugfs_data *data = filp->private_data;
-
-	if (data->done)
-		return 0;
-
-	local_buf = kcalloc(size, sizeof(u8), GFP_KERNEL);
-	if (!local_buf)
-		return -ENOMEM;
-
-	data->done = 1;
-
-	retval = snprintf(local_buf, size, "%u %u %u %u\n",
-			data->sensor->axis_align.clip_X_low,
-			data->sensor->axis_align.clip_X_high,
-			data->sensor->axis_align.clip_Y_low,
-			data->sensor->axis_align.clip_Y_high);
-
-	if (retval <= 0 || copy_to_user(buffer, local_buf, retval))
-		retval = -EFAULT;
-	kfree(local_buf);
-
-	return retval;
-}
-
-static ssize_t clip_write(struct file *filp, const char __user *buffer,
-			   size_t size, loff_t *offset)
-{
-	int retval;
-	char *local_buf;
-	unsigned int new_X_low, new_X_high, new_Y_low, new_Y_high;
-	struct sensor_debugfs_data *data = filp->private_data;
-
-	local_buf = kcalloc(size, sizeof(u8), GFP_KERNEL);
-	if (!local_buf)
-		return -ENOMEM;
-
-	retval = copy_from_user(local_buf, buffer, size);
-	if (retval) {
-		kfree(local_buf);
-		return -EFAULT;
-	}
-
-	retval = sscanf(local_buf, "%u %u %u %u",
-		&new_X_low, &new_X_high, &new_Y_low, &new_Y_high);
-	kfree(local_buf);
-	if (retval != 4)
-		return -EINVAL;
-
-	if (new_X_low >= new_X_high || new_Y_low >= new_Y_high)
-		return -EINVAL;
-
-	data->sensor->axis_align.clip_X_low = new_X_low;
-	data->sensor->axis_align.clip_X_high = new_X_high;
-	data->sensor->axis_align.clip_Y_low = new_Y_low;
-	data->sensor->axis_align.clip_Y_high = new_Y_high;
-
-	return size;
-}
-
-static const struct file_operations clip_fops = {
-	.owner = THIS_MODULE,
-	.open = sensor_debug_open,
-	.release = sensor_debug_release,
-	.read = clip_read,
-	.write = clip_write,
-};
-
-static ssize_t swap_read(struct file *filp, char __user *buffer, size_t size,
-		    loff_t *offset) {
-	int retval;
-	char *local_buf;
-	struct sensor_debugfs_data *data = filp->private_data;
-
-	if (data->done)
-		return 0;
-
-	local_buf = kcalloc(size, sizeof(u8), GFP_KERNEL);
-	if (!local_buf)
-		return -ENOMEM;
-
-	data->done = 1;
-
-	retval = snprintf(local_buf, size, "%u\n",
-			data->sensor->axis_align.swap_axes);
-
-	if (retval <= 0 || copy_to_user(buffer, local_buf, retval))
-		retval = -EFAULT;
-	kfree(local_buf);
-
-	return retval;
-}
-
-static ssize_t swap_write(struct file *filp, const char __user *buffer,
-			   size_t size, loff_t *offset)
-{
-	int retval;
-	char *local_buf;
-	int new_value;
-	struct sensor_debugfs_data *data = filp->private_data;
-
-	local_buf = kcalloc(size, sizeof(u8), GFP_KERNEL);
-	if (!local_buf)
-		return -ENOMEM;
-
-	retval = copy_from_user(local_buf, buffer, size);
-	if (retval) {
-		kfree(local_buf);
-		return -EFAULT;
-	}
-	retval = sscanf(local_buf, "%u", &new_value);
-	kfree(local_buf);
-	if (retval != 1 || new_value > 1)
-		return -EINVAL;
-
-	data->sensor->axis_align.swap_axes = new_value;
-	return size;
-}
-
-static const struct file_operations swap_fops = {
-	.owner = THIS_MODULE,
-	.open = sensor_debug_open,
-	.release = sensor_debug_release,
-	.read = swap_read,
-	.write = swap_write,
-};
-
-static ssize_t type_a_read(struct file *filp, char __user *buffer, size_t size,
-		    loff_t *offset) {
-	int retval;
-	char *local_buf;
-	struct sensor_debugfs_data *data = filp->private_data;
-
-	if (data->done)
-		return 0;
-
-	local_buf = kcalloc(size, sizeof(u8), GFP_KERNEL);
-	if (!local_buf)
-		return -ENOMEM;
-
-	data->done = 1;
-
-	retval = snprintf(local_buf, size, "%u\n",
-			data->sensor->type_a);
-
-	if (retval <= 0 || copy_to_user(buffer, local_buf, retval))
-		retval = -EFAULT;
-	kfree(local_buf);
-
-	return retval;
-}
-
-static ssize_t type_a_write(struct file *filp, const char __user *buffer,
-			   size_t size, loff_t *offset)
-{
-	int retval;
-	char *local_buf;
-	int new_value;
-	struct sensor_debugfs_data *data = filp->private_data;
-
-	local_buf = kcalloc(size, sizeof(u8), GFP_KERNEL);
-	if (!local_buf)
-		return -ENOMEM;
-
-	retval = copy_from_user(local_buf, buffer, size);
-	if (retval) {
-		kfree(local_buf);
-		return -EFAULT;
-	}
-
-	retval = sscanf(local_buf, "%u", &new_value);
-	kfree(local_buf);
-	if (retval != 1 || new_value > 1)
-		return -EINVAL;
-
-	data->sensor->type_a = new_value;
-	return size;
-}
-
-static const struct file_operations type_a_fops = {
-	.owner = THIS_MODULE,
-	.open = sensor_debug_open,
-	.release = sensor_debug_release,
-	.read = type_a_read,
-	.write = type_a_write,
-};
-
-static int setup_sensor_debugfs(struct f11_2d_sensor *sensor)
-{
-	int retval = 0;
-	char fname[NAME_BUFFER_SIZE];
-	struct rmi_function *fn = sensor->fn;
-
-	if (!fn->debugfs_root)
-		return -ENODEV;
-
-	retval = snprintf(fname, NAME_BUFFER_SIZE, "flip.%d",
-			  sensor->sensor_index);
-	sensor->debugfs_flip = debugfs_create_file(fname, RMI_RW_ATTR,
-				fn->debugfs_root, sensor, &flip_fops);
-	if (!sensor->debugfs_flip)
-		dev_warn(&fn->dev, "Failed to create debugfs %s.\n",
-			 fname);
-
-	retval = snprintf(fname, NAME_BUFFER_SIZE, "clip.%d",
-			  sensor->sensor_index);
-	sensor->debugfs_clip = debugfs_create_file(fname, RMI_RW_ATTR,
-				fn->debugfs_root, sensor, &clip_fops);
-	if (!sensor->debugfs_clip)
-		dev_warn(&fn->dev, "Failed to create debugfs %s.\n",
-			 fname);
-
-	retval = snprintf(fname, NAME_BUFFER_SIZE, "delta_threshold.%d",
-			  sensor->sensor_index);
-	sensor->debugfs_clip = debugfs_create_file(fname, RMI_RW_ATTR,
-				fn->debugfs_root, sensor,
-				&delta_threshold_fops);
-	if (!sensor->debugfs_delta_threshold)
-		dev_warn(&fn->dev, "Failed to create debugfs %s.\n",
-			 fname);
-
-	retval = snprintf(fname, NAME_BUFFER_SIZE, "offset.%d",
-			  sensor->sensor_index);
-	sensor->debugfs_offset = debugfs_create_file(fname, RMI_RW_ATTR,
-				fn->debugfs_root, sensor, &offset_fops);
-	if (!sensor->debugfs_offset)
-		dev_warn(&fn->dev, "Failed to create debugfs %s.\n",
-			 fname);
-
-	retval = snprintf(fname, NAME_BUFFER_SIZE, "swap.%d",
-			  sensor->sensor_index);
-	sensor->debugfs_swap = debugfs_create_file(fname, RMI_RW_ATTR,
-				fn->debugfs_root, sensor, &swap_fops);
-	if (!sensor->debugfs_swap)
-		dev_warn(&fn->dev, "Failed to create debugfs %s.\n",
-			 fname);
-
-	retval = snprintf(fname, NAME_BUFFER_SIZE, "type_a.%d",
-			  sensor->sensor_index);
-	sensor->debugfs_type_a = debugfs_create_file(fname, RMI_RW_ATTR,
-				fn->debugfs_root, sensor, &type_a_fops);
-	if (!sensor->debugfs_type_a)
-		dev_warn(&fn->dev, "Failed to create debugfs %s.\n",
-			 fname);
-
-	return retval;
-}
-
-static void teardown_sensor_debugfs(struct f11_2d_sensor *sensor)
-{
-	if (sensor->debugfs_flip)
-		debugfs_remove(sensor->debugfs_flip);
-
-	if (sensor->debugfs_clip)
-		debugfs_remove(sensor->debugfs_clip);
-
-	if (sensor->debugfs_offset)
-		debugfs_remove(sensor->debugfs_offset);
-
-	if (sensor->debugfs_swap)
-		debugfs_remove(sensor->debugfs_swap);
-
-	if (sensor->debugfs_type_a)
-		debugfs_remove(sensor->debugfs_type_a);
-}
-
-struct f11_debugfs_data {
-	bool done;
-	struct rmi_function *fn;
-};
-
-static int f11_debug_open(struct inode *inodep, struct file *filp)
-{
-	struct f11_debugfs_data *data;
-	struct rmi_function *fn = inodep->i_private;
-
-	data = devm_kzalloc(&fn->dev, sizeof(struct f11_debugfs_data),
-		GFP_KERNEL);
-	if (!data)
-		return -ENOMEM;
-
-	data->fn = fn;
-	filp->private_data = data;
-	return 0;
-}
-
-static ssize_t rezero_wait_read(struct file *filp, char __user *buffer,
-		size_t size, loff_t *offset) {
-	int retval;
-	char *local_buf;
-	struct f11_debugfs_data *data = filp->private_data;
-	struct f11_data *f11 = data->fn->data;
-
-	if (data->done)
-		return 0;
-
-	local_buf = kcalloc(size, sizeof(u8), GFP_KERNEL);
-	if (!local_buf)
-		return -ENOMEM;
-
-	data->done = 1;
-
-	retval = snprintf(local_buf, size, "%u\n", f11->rezero_wait_ms);
-
-	if (retval <= 0 || copy_to_user(buffer, local_buf, retval))
-		retval = -EFAULT;
-	kfree(local_buf);
-
-	return retval;
-}
-
-static ssize_t rezero_wait_write(struct file *filp, const char __user *buffer,
-			   size_t size, loff_t *offset)
-{
-	int retval;
-	char *local_buf;
-	int new_value;
-	struct f11_debugfs_data *data = filp->private_data;
-	struct f11_data *f11 = data->fn->data;
-
-	local_buf = kcalloc(size, sizeof(u8), GFP_KERNEL);
-	if (!local_buf)
-		return -ENOMEM;
-
-	retval = copy_from_user(local_buf, buffer, size);
-	if (retval) {
-		kfree(local_buf);
-		return -EFAULT;
-	}
-
-	retval = sscanf(local_buf, "%u", &new_value);
-	kfree(local_buf);
-	if (retval != 1 || new_value > 65535)
-		return -EINVAL;
-
-	f11->rezero_wait_ms = new_value;
-	return size;
-}
-
-static const struct file_operations rezero_wait_fops = {
-	.owner = THIS_MODULE,
-	.open = f11_debug_open,
-	.read = rezero_wait_read,
-	.write = rezero_wait_write,
-};
-
-static int setup_f11_debugfs(struct rmi_function *fn)
-{
-	struct f11_data *f11 = fn->data;
-
-	if (!fn->debugfs_root)
-		return -ENODEV;
-
-	f11->debugfs_rezero_wait = debugfs_create_file("rezero_wait",
-		RMI_RW_ATTR, fn->debugfs_root, fn, &rezero_wait_fops);
-	if (!f11->debugfs_rezero_wait)
-		dev_warn(&fn->dev,
-			 "Failed to create debugfs rezero_wait.\n");
-
-	return 0;
-}
-
-static void teardown_f11_debugfs(struct f11_data *f11)
-{
-	if (f11->debugfs_rezero_wait)
-		debugfs_remove(f11->debugfs_rezero_wait);
-}
-#endif
-/* End adding debugfs */
-
 /** F11_INACCURATE state is overloaded to indicate pen present. */
 #define F11_PEN F11_INACCURATE
 
@@ -1688,7 +184,7 @@ static void rmi_f11_abs_pos_report(struct f11_data *f11,
 		input_report_abs(sensor->input, ABS_MT_ORIENTATION, orient);
 		input_report_abs(sensor->input, ABS_MT_POSITION_X, x);
 		input_report_abs(sensor->input, ABS_MT_POSITION_Y, y);
-		dev_dbg(&sensor->fn->dev,
+		dev_dbg(&sensor->fn_dev->dev,
 			"finger[%d]:%d - x:%d y:%d z:%d w_max:%d w_min:%d\n",
 			n_finger, finger_state, x, y, z, w_max, w_min);
 	}
@@ -1724,7 +220,7 @@ static void rmi_f11_finger_handler(struct f11_data *f11,
 		if (sensor->data.rel_pos)
 			rmi_f11_rel_pos_report(sensor, i);
 	}
-	input_mt_sync(sensor->input);
+	input_mt_sync_frame(sensor->input);
 	input_sync(sensor->input);
 }
 
@@ -1786,53 +282,12 @@ static int f11_2d_construct_data(struct f11_2d_sensor *sensor)
 		i += (sensor->nbr_fingers * 2);
 	}
 
-	if (has_gesture_bits(&query->gesture_info, 0)) {
-		data->gest_1 = (struct f11_2d_data_8 *)&sensor->data_pkt[i];
-		i++;
-	}
-
-	if (has_gesture_bits(&query->gesture_info, 0) ||
-				has_gesture_bits(&query->gesture_info, 1)) {
-		data->gest_2 = (struct f11_2d_data_9 *)&sensor->data_pkt[i];
-		i++;
-	}
-
-	if (query->gesture_info.has_pinch) {
-		data->pinch = (struct f11_2d_data_10 *)&sensor->data_pkt[i];
-		i++;
-	}
-
-	if (query->gesture_info.has_flick) {
-		if (query->gesture_info.has_pinch) {
-			data->flick = (struct f11_2d_data_10_12 *)data->pinch;
-			i += 2;
-		} else {
-			data->flick = (struct f11_2d_data_10_12 *)
-					&sensor->data_pkt[i];
-			i += 3;
-		}
-	}
-
-	if (query->gesture_info.has_rotate) {
-		if (query->gesture_info.has_flick) {
-			data->rotate = (struct f11_2d_data_11_12 *)
-					(data->flick + 1);
-		} else {
-			data->rotate = (struct f11_2d_data_11_12 *)
-					&sensor->data_pkt[i];
-			i += 2;
-		}
-	}
-
-	if (query->gesture_info.has_touch_shapes)
-		data->shapes = (struct f11_2d_data_13 *)&sensor->data_pkt[i];
-
 	return 0;
 }
 
-static int f11_read_control_regs(struct rmi_function *fn,
+static int f11_read_control_regs(struct rmi_function_dev *fn_dev,
 				struct f11_2d_ctrl *ctrl, u16 ctrl_base_addr) {
-	struct rmi_device *rmi_dev = fn->rmi_dev;
+	struct rmi_device *rmi_dev = fn_dev->rmi_dev;
 	u16 read_address = ctrl_base_addr;
 	int error = 0;
 
@@ -1840,216 +295,35 @@ static int f11_read_control_regs(struct rmi_function *fn,
 	error = rmi_read_block(rmi_dev, read_address, ctrl->ctrl0_9,
 		sizeof(*ctrl->ctrl0_9));
 	if (error < 0) {
-		dev_err(&fn->dev, "Failed to read ctrl0, code: %d.\n", error);
+		dev_err(&fn_dev->dev, "Failed to read ctrl0, code: %d.\n",
+			error);
 		return error;
 	}
 	read_address += sizeof(*ctrl->ctrl0_9);
 
-	if (ctrl->ctrl10) {
-		error = rmi_read_block(rmi_dev, read_address,
-			ctrl->ctrl10, sizeof(*ctrl->ctrl10));
-		if (error < 0) {
-			dev_err(&fn->dev,
-				"Failed to read ctrl10, code: %d.\n", error);
-			return error;
-		}
-		read_address += sizeof(*ctrl->ctrl10);
-	}
-
-	if (ctrl->ctrl11) {
-		error = rmi_read_block(rmi_dev, read_address,
-			ctrl->ctrl11, sizeof(*ctrl->ctrl11));
-		if (error < 0) {
-			dev_err(&fn->dev,
-				"Failed to read ctrl11, code: %d.\n", error);
-			return error;
-		}
-		read_address += sizeof(*ctrl->ctrl11);
-	}
-
-	if (ctrl->ctrl14) {
-		error = rmi_read_block(rmi_dev, read_address,
-			ctrl->ctrl14, sizeof(*ctrl->ctrl14));
-		if (error < 0) {
-			dev_err(&fn->dev,
-				"Failed to read ctrl14, code: %d.\n", error);
-			return error;
-		}
-		read_address += sizeof(*ctrl->ctrl14);
-	}
-
-	if (ctrl->ctrl15) {
-		error = rmi_read_block(rmi_dev, read_address,
-			ctrl->ctrl15, sizeof(*ctrl->ctrl15));
-		if (error < 0) {
-			dev_err(&fn->dev,
-				"Failed to read ctrl15, code: %d.\n", error);
-			return error;
-		}
-		read_address += sizeof(*ctrl->ctrl15);
-	}
-
-	if (ctrl->ctrl16) {
-		error = rmi_read_block(rmi_dev, read_address,
-			ctrl->ctrl16, sizeof(*ctrl->ctrl16));
-		if (error < 0) {
-			dev_err(&fn->dev,
-				"Failed to read ctrl16, code: %d.\n", error);
-			return error;
-		}
-		read_address += sizeof(*ctrl->ctrl16);
-	}
-
-	if (ctrl->ctrl17) {
-		error = rmi_read_block(rmi_dev, read_address,
-			ctrl->ctrl17, sizeof(*ctrl->ctrl17));
-		if (error < 0) {
-			dev_err(&fn->dev,
-				"Failed to read ctrl17, code: %d.\n", error);
-			return error;
-		}
-		read_address += sizeof(*ctrl->ctrl17);
-	}
-
-	if (ctrl->ctrl18_19) {
-		error = rmi_read_block(rmi_dev, read_address,
-			ctrl->ctrl18_19, sizeof(*ctrl->ctrl18_19));
-		if (error < 0) {
-			dev_err(&fn->dev,
-				"Failed to read ctrl18_19, code: %d.\n", error);
-			return error;
-		}
-		read_address += sizeof(*ctrl->ctrl18_19);
-	}
-
-	if (ctrl->ctrl20_21) {
-		error = rmi_read_block(rmi_dev, read_address,
-			ctrl->ctrl20_21, sizeof(*ctrl->ctrl20_21));
-		if (error < 0) {
-			dev_err(&fn->dev,
-				"Failed to read ctrl20_21, code: %d.\n", error);
-			return error;
-		}
-		read_address += sizeof(*ctrl->ctrl20_21);
-	}
-
-	if (ctrl->ctrl22_26) {
-		error = rmi_read_block(rmi_dev, read_address,
-			ctrl->ctrl22_26, sizeof(*ctrl->ctrl22_26));
-		if (error < 0) {
-			dev_err(&fn->dev,
-				"Failed to read ctrl22_26, code: %d.\n", error);
-			return error;
-		}
-		read_address += sizeof(*ctrl->ctrl22_26);
-	}
-
-	if (ctrl->ctrl27) {
-		error = rmi_read_block(rmi_dev, read_address,
-			ctrl->ctrl27, sizeof(*ctrl->ctrl27));
-		if (error < 0) {
-			dev_err(&fn->dev,
-				"Failed to read ctrl27, code: %d.\n", error);
-			return error;
-		}
-		read_address += sizeof(*ctrl->ctrl27);
-	}
-
-	if (ctrl->ctrl28) {
-		error = rmi_read_block(rmi_dev, read_address,
-			ctrl->ctrl28, sizeof(*ctrl->ctrl28));
-		if (error < 0) {
-			dev_err(&fn->dev,
-				"Failed to read ctrl28, code: %d.\n", error);
-			return error;
-		}
-		read_address += sizeof(*ctrl->ctrl28);
-	}
-
-	if (ctrl->ctrl29_30) {
-		error = rmi_read_block(rmi_dev, read_address,
-			ctrl->ctrl29_30, sizeof(*ctrl->ctrl29_30));
-		if (error < 0) {
-			dev_err(&fn->dev,
-				"Failed to read ctrl29_30, code: %d.\n", error);
-			return error;
-		}
-		read_address += sizeof(*ctrl->ctrl29_30);
-	}
 	return 0;
 }
 
-static int f11_allocate_control_regs(struct rmi_function *fn,
+static int f11_allocate_control_regs(struct rmi_function_dev *fn_dev,
 				struct f11_2d_device_query *device_query,
 				struct f11_2d_sensor_queries *sensor_query,
 				struct f11_2d_ctrl *ctrl,
 				u16 ctrl_base_addr) {
 
-	ctrl->ctrl0_9 = devm_kzalloc(&fn->dev, sizeof(struct f11_2d_ctrl0_9),
-				       GFP_KERNEL);
+	ctrl->ctrl0_9 = devm_kzalloc(&fn_dev->dev,
+				     sizeof(struct f11_2d_ctrl0_9), GFP_KERNEL);
 	if (!ctrl->ctrl0_9)
 		return -ENOMEM;
-	if (has_gesture_bits(&sensor_query->gesture_info, 0)) {
-		ctrl->ctrl10 = devm_kzalloc(&fn->dev,
-			sizeof(struct f11_2d_ctrl10), GFP_KERNEL);
-		if (!ctrl->ctrl10)
-			return -ENOMEM;
-	}
-
-	if (has_gesture_bits(&sensor_query->gesture_info, 1)) {
-		ctrl->ctrl11 = devm_kzalloc(&fn->dev,
-			sizeof(struct f11_2d_ctrl11), GFP_KERNEL);
-		if (!ctrl->ctrl11)
-			return -ENOMEM;
-	}
-
-	if (device_query->has_query9 && sensor_query->query9.has_pen) {
-		ctrl->ctrl20_21 = devm_kzalloc(&fn->dev,
-			sizeof(struct f11_2d_ctrl20_21), GFP_KERNEL);
-		if (!ctrl->ctrl20_21)
-			return -ENOMEM;
-	}
-
-	if (device_query->has_query9 && sensor_query->query9.has_proximity) {
-		ctrl->ctrl22_26 = devm_kzalloc(&fn->dev,
-			sizeof(struct f11_2d_ctrl22_26), GFP_KERNEL);
-		if (!ctrl->ctrl22_26)
-			return -ENOMEM;
-	}
-
-	if (device_query->has_query9 &&
-		(sensor_query->query9.has_palm_det_sensitivity ||
-		sensor_query->query9.has_suppress_on_palm_detect)) {
-		ctrl->ctrl27 = devm_kzalloc(&fn->dev,
-			sizeof(struct f11_2d_ctrl27), GFP_KERNEL);
-		if (!ctrl->ctrl27)
-			return -ENOMEM;
-	}
-
-	if (sensor_query->gesture_info.has_multi_finger_scroll) {
-		ctrl->ctrl28 = devm_kzalloc(&fn->dev,
-			sizeof(struct f11_2d_ctrl28), GFP_KERNEL);
-		if (!ctrl->ctrl28)
-			return -ENOMEM;
-	}
-
-	if (device_query->has_query11 &&
-			sensor_query->features_1.has_z_tuning) {
-		ctrl->ctrl29_30 = devm_kzalloc(&fn->dev,
-			sizeof(struct f11_2d_ctrl29_30), GFP_KERNEL);
-		if (!ctrl->ctrl29_30)
-			return -ENOMEM;
-	}
 
 	return 0;
 }
 
-static int f11_write_control_regs(struct rmi_function *fn,
+static int f11_write_control_regs(struct rmi_function_dev *fn_dev,
 					struct f11_2d_sensor_queries *query,
 					struct f11_2d_ctrl *ctrl,
 					u16 ctrl_base_addr)
 {
-	struct rmi_device *rmi_dev = fn->rmi_dev;
+	struct rmi_device *rmi_dev = fn_dev->rmi_dev;
 	u16 write_address = ctrl_base_addr;
 	int error;
 
@@ -2060,103 +334,6 @@ static int f11_write_control_regs(struct rmi_function *fn,
 		return error;
 	write_address += sizeof(ctrl->ctrl0_9);
 
-	if (ctrl->ctrl10) {
-		error = rmi_write_block(rmi_dev, write_address,
-					ctrl->ctrl10, sizeof(*ctrl->ctrl10));
-		if (error < 0)
-			return error;
-		write_address++;
-	}
-
-	if (ctrl->ctrl11) {
-		error = rmi_write_block(rmi_dev, write_address,
-					ctrl->ctrl11, sizeof(*ctrl->ctrl11));
-		if (error < 0)
-			return error;
-		write_address++;
-	}
-
-	if (ctrl->ctrl14) {
-		error = rmi_write_block(rmi_dev, write_address,
-				ctrl->ctrl14, sizeof(ctrl->ctrl14));
-		if (error < 0)
-			return error;
-		write_address += sizeof(*ctrl->ctrl15);
-	}
-
-	if (ctrl->ctrl15) {
-		error = rmi_write_block(rmi_dev, write_address,
-				ctrl->ctrl15, sizeof(*ctrl->ctrl15));
-		if (error < 0)
-			return error;
-		write_address += sizeof(*ctrl->ctrl15);
-	}
-
-	if (ctrl->ctrl16) {
-		error = rmi_write_block(rmi_dev, write_address,
-				ctrl->ctrl16, sizeof(*ctrl->ctrl16));
-		if (error < 0)
-			return error;
-		write_address += sizeof(*ctrl->ctrl16);
-	}
-
-	if (ctrl->ctrl17) {
-		error = rmi_write_block(rmi_dev, write_address,
-				ctrl->ctrl17, sizeof(*ctrl->ctrl17));
-		if (error < 0)
-			return error;
-		write_address += sizeof(*ctrl->ctrl17);
-	}
-
-	if (ctrl->ctrl18_19) {
-		error = rmi_write_block(rmi_dev, write_address,
-			ctrl->ctrl18_19, sizeof(*ctrl->ctrl18_19));
-		if (error < 0)
-			return error;
-		write_address += sizeof(*ctrl->ctrl18_19);
-	}
-
-	if (ctrl->ctrl20_21) {
-		error = rmi_write_block(rmi_dev, write_address,
-			ctrl->ctrl20_21, sizeof(*ctrl->ctrl20_21));
-		if (error < 0)
-			return error;
-		write_address += sizeof(*ctrl->ctrl20_21);
-	}
-
-	if (ctrl->ctrl22_26) {
-		error = rmi_write_block(rmi_dev, write_address,
-			ctrl->ctrl22_26, sizeof(*ctrl->ctrl22_26));
-		if (error < 0)
-			return error;
-		write_address += sizeof(*ctrl->ctrl22_26);
-	}
-
-	if (ctrl->ctrl27) {
-		error = rmi_write_block(rmi_dev, write_address,
-			ctrl->ctrl27, sizeof(*ctrl->ctrl27));
-		if (error < 0)
-			return error;
-		write_address += sizeof(*ctrl->ctrl27);
-	}
-
-	if (ctrl->ctrl28) {
-		error = rmi_write_block(rmi_dev, write_address,
-			ctrl->ctrl28, sizeof(*ctrl->ctrl28));
-		if (error < 0)
-			return error;
-		write_address += sizeof(*ctrl->ctrl28);
-	}
-
-	if (ctrl->ctrl29_30) {
-		error = rmi_write_block(rmi_dev, write_address,
-					ctrl->ctrl29_30,
-					sizeof(struct f11_2d_ctrl29_30));
-		if (error < 0)
-			return error;
-		write_address += sizeof(struct f11_2d_ctrl29_30);
-	}
-
 	return 0;
 }
 
@@ -2259,9 +436,9 @@ static int rmi_f11_get_query_parameters(struct rmi_device *rmi_dev,
 /* This operation is done in a number of places, so we have a handy routine
  * for it.
  */
-static void f11_set_abs_params(struct rmi_function *fn, int index)
+static void f11_set_abs_params(struct rmi_function_dev *fn_dev, int index)
 {
-	struct f11_data *f11 = fn->data;
+	struct f11_data *f11 = fn_dev->data;
 	struct f11_2d_sensor *sensor = &f11->sensors[index];
 	struct input_dev *input = sensor->input;
 	int device_x_max =
@@ -2304,7 +481,7 @@ static void f11_set_abs_params(struct rmi_function *fn, int index)
 	else
 		y_max = device_y_max;
 
-	dev_dbg(&fn->dev, "Set ranges X=[%d..%d] Y=[%d..%d].",
+	dev_dbg(&fn_dev->dev, "Set ranges X=[%d..%d] Y=[%d..%d].",
 			x_min, x_max, y_min, y_max);
 
 	input_set_abs_params(input, ABS_MT_PRESSURE, 0,
@@ -2334,9 +511,9 @@ static void f11_set_abs_params(struct rmi_function *fn, int index)
 				     0, MT_TOOL_FINGER, 0, 0);
 }
 
-static int rmi_f11_initialize(struct rmi_function *fn)
+static int rmi_f11_initialize(struct rmi_function_dev *fn_dev)
 {
-	struct rmi_device *rmi_dev = fn->rmi_dev;
+	struct rmi_device *rmi_dev = fn_dev->rmi_dev;
 	struct f11_data *f11;
 	struct f11_2d_ctrl *ctrl;
 	u8 query_offset;
@@ -2347,21 +524,15 @@ static int rmi_f11_initialize(struct rmi_function *fn)
 	int i;
 	struct rmi_device_platform_data *pdata = to_rmi_platform_data(rmi_dev);
 
-	dev_dbg(&fn->dev, "Initializing F11 values for %s.\n",
-		 pdata->sensor_name);
-
-	/*
-	** init instance data, fill in values and create any sysfs files
-	*/
-	f11 = devm_kzalloc(&fn->dev, sizeof(struct f11_data), GFP_KERNEL);
+	f11 = devm_kzalloc(&fn_dev->dev, sizeof(struct f11_data), GFP_KERNEL);
 	if (!f11)
 		return -ENOMEM;
 
-	fn->data = f11;
+	fn_dev->data = f11;
 	f11->rezero_wait_ms = pdata->f11_rezero_wait;
 
-	query_base_addr = fn->fd.query_base_addr;
-	control_base_addr = fn->fd.control_base_addr;
+	query_base_addr = fn_dev->fd.query_base_addr;
+	control_base_addr = fn_dev->fd.control_base_addr;
 
 	rc = rmi_read(rmi_dev, query_base_addr, &f11->dev_query);
 	if (rc < 0)
@@ -2372,7 +543,7 @@ static int rmi_f11_initialize(struct rmi_function *fn)
 	for (i = 0; i < (f11->dev_query.nbr_of_sensors + 1); i++) {
 		struct f11_2d_sensor *sensor = &f11->sensors[i];
 		sensor->sensor_index = i;
-		sensor->fn = fn;
+		sensor->fn_dev = fn_dev;
 
 		rc = rmi_f11_get_query_parameters(rmi_dev, &f11->dev_query,
 				&sensor->sens_query, query_offset);
@@ -2380,19 +551,19 @@ static int rmi_f11_initialize(struct rmi_function *fn)
 			return rc;
 		query_offset += rc;
 
-		rc = f11_allocate_control_regs(fn,
+		rc = f11_allocate_control_regs(fn_dev,
 				&f11->dev_query, &sensor->sens_query,
 				&f11->dev_controls, control_base_addr);
 		if (rc < 0) {
-			dev_err(&fn->dev,
+			dev_err(&fn_dev->dev,
 				"Failed to allocate F11 control params.\n");
 			return rc;
 		}
 
-		rc = f11_read_control_regs(fn, &f11->dev_controls,
+		rc = f11_read_control_regs(fn_dev, &f11->dev_controls,
 				control_base_addr);
 		if (rc < 0) {
-			dev_err(&fn->dev,
+			dev_err(&fn_dev->dev,
 				"Failed to read F11 control params.\n");
 			return rc;
 		}
@@ -2438,7 +609,7 @@ static int rmi_f11_initialize(struct rmi_function *fn)
 					ctrl->ctrl0_9,
 					sizeof(*ctrl->ctrl0_9));
 			if (rc < 0)
-				dev_warn(&fn->dev, "Failed to write to delta_x_threshold %d. Code: %d.\n",
+				dev_warn(&fn_dev->dev, "Failed to write to delta_x_threshold %d. Code: %d.\n",
 					i, rc);
 
 		}
@@ -2451,33 +622,22 @@ static int rmi_f11_initialize(struct rmi_function *fn)
 					ctrl->ctrl0_9,
 					sizeof(*ctrl->ctrl0_9));
 			if (rc < 0)
-				dev_warn(&fn->dev, "Failed to write to delta_y_threshold %d. Code: %d.\n",
+				dev_warn(&fn_dev->dev, "Failed to write to delta_y_threshold %d. Code: %d.\n",
 					i, rc);
 		}
 
-		if (IS_ENABLED(CONFIG_RMI4_DEBUG)) {
-			rc = setup_sensor_debugfs(sensor);
-			if (rc < 0)
-				dev_warn(&fn->dev, "Failed to setup debugfs for F11 sensor %d. Code: %d.\n",
-					i, rc);
-		}
-	}
 
-	if (IS_ENABLED(CONFIG_RMI4_DEBUG)) {
-		rc = setup_f11_debugfs(fn);
-		if (rc < 0)
-			dev_warn(&fn->dev, "Failed to setup debugfs for F11. Code: %d.\n",
-				rc);
 	}
 
-	mutex_init(&f11->dev_controls_mutex);
+
+
 	return 0;
 }
 
-static int rmi_f11_register_devices(struct rmi_function *fn)
+static int rmi_f11_register_devices(struct rmi_function_dev *fn_dev)
 {
-	struct rmi_device *rmi_dev = fn->rmi_dev;
-	struct f11_data *f11 = fn->data;
+	struct rmi_device *rmi_dev = fn_dev->rmi_dev;
+	struct f11_data *f11 = fn_dev->data;
 	struct input_dev *input_dev;
 	struct input_dev *input_dev_mouse;
 	struct rmi_driver_data *driver_data = dev_get_drvdata(&rmi_dev->dev);
@@ -2503,14 +663,14 @@ static int rmi_f11_register_devices(struct rmi_function *fn)
 		if (driver->set_input_params) {
 			rc = driver->set_input_params(rmi_dev, input_dev);
 			if (rc < 0) {
-				dev_err(&fn->dev,
+				dev_err(&fn_dev->dev,
 				"%s: Error in setting input device.\n",
 				__func__);
 				goto error_unregister;
 			}
 		}
 		sprintf(sensor->input_phys, "%s.abs%d/input0",
-			dev_name(&fn->dev), i);
+			dev_name(&fn_dev->dev), i);
 		input_dev->phys = sensor->input_phys;
 		input_dev->dev.parent = &rmi_dev->dev;
 		input_set_drvdata(input_dev, f11);
@@ -2519,7 +679,7 @@ static int rmi_f11_register_devices(struct rmi_function *fn)
 		set_bit(EV_ABS, input_dev->evbit);
 		input_set_capability(input_dev, EV_KEY, BTN_TOUCH);
 
-		f11_set_abs_params(fn, i);
+		f11_set_abs_params(fn_dev, i);
 
 		if (sensor->sens_query.info.has_rel) {
 			set_bit(EV_REL, input_dev->evbit);
@@ -2546,14 +706,14 @@ static int rmi_f11_register_devices(struct rmi_function *fn)
 				rc = driver->set_input_params(rmi_dev,
 					input_dev_mouse);
 				if (rc < 0) {
-					dev_err(&fn->dev,
+					dev_err(&fn_dev->dev,
 					"%s: Error in setting input device.\n",
 					__func__);
 					goto error_unregister;
 				}
 			}
 			sprintf(sensor->input_phys_mouse, "%s.rel%d/input0",
-				dev_name(&fn->dev), i);
+				dev_name(&fn_dev->dev), i);
 			set_bit(EV_REL, input_dev_mouse->evbit);
 			set_bit(REL_X, input_dev_mouse->relbit);
 			set_bit(REL_Y, input_dev_mouse->relbit);
@@ -2595,9 +755,9 @@ error_unregister:
 	return rc;
 }
 
-static void rmi_f11_free_devices(struct rmi_function *fn)
+static void rmi_f11_free_devices(struct rmi_function_dev *fn_dev)
 {
-	struct f11_data *f11 = fn->data;
+	struct f11_data *f11 = fn_dev->data;
 	int i;
 
 	for (i = 0; i < (f11->dev_query.nbr_of_sensors + 1); i++) {
@@ -2608,38 +768,15 @@ static void rmi_f11_free_devices(struct rmi_function *fn)
 	}
 }
 
-static int rmi_f11_create_sysfs(struct rmi_function *fn)
+static int rmi_f11_config(struct rmi_function_dev *fn_dev)
 {
-	int attr_count = 0;
-	int rc;
-
-	for (attr_count = 0; attr_count < ARRAY_SIZE(attrs); attr_count++) {
-		if (sysfs_create_file
-		    (&fn->dev.kobj, &attrs[attr_count].attr) < 0) {
-			dev_err(&fn->dev, "Failed to create sysfs file for %s.",
-				attrs[attr_count].attr.name);
-			rc = -ENODEV;
-			goto err_remove_sysfs;
-		}
-	}
-
-	return 0;
-
-err_remove_sysfs:
-	for (attr_count--; attr_count >= 0; attr_count--)
-		sysfs_remove_file(&fn->dev.kobj, &attrs[attr_count].attr);
-	return rc;
-}
-
-static int rmi_f11_config(struct rmi_function *fn)
-{
-	struct f11_data *f11 = fn->data;
+	struct f11_data *f11 = fn_dev->data;
 	int i;
 	int rc;
 
 	for (i = 0; i < (f11->dev_query.nbr_of_sensors + 1); i++) {
-		rc = f11_write_control_regs(fn, &f11->sensors[i].sens_query,
-				   &f11->dev_controls, fn->fd.query_base_addr);
+		rc = f11_write_control_regs(fn_dev, &f11->sensors[i].sens_query,
+				&f11->dev_controls, fn_dev->fd.query_base_addr);
 		if (rc < 0)
 			return rc;
 	}
@@ -2647,12 +784,12 @@ static int rmi_f11_config(struct rmi_function *fn)
 	return 0;
 }
 
-int rmi_f11_attention(struct rmi_function *fn,
+int rmi_f11_attention(struct rmi_function_dev *fn_dev,
 						unsigned long *irq_bits)
 {
-	struct rmi_device *rmi_dev = fn->rmi_dev;
-	struct f11_data *f11 = fn->data;
-	u16 data_base_addr = fn->fd.data_base_addr;
+	struct rmi_device *rmi_dev = fn_dev->rmi_dev;
+	struct f11_data *f11 = fn_dev->data;
+	u16 data_base_addr = fn_dev->fd.data_base_addr;
 	u16 data_base_addr_offset = 0;
 	int error;
 	int i;
@@ -2673,26 +810,26 @@ int rmi_f11_attention(struct rmi_function *fn,
 }
 
 #ifdef CONFIG_PM
-static int rmi_f11_resume(struct rmi_function *fn)
+static int rmi_f11_resume(struct rmi_function_dev *fn_dev)
 {
-	struct rmi_device *rmi_dev = fn->rmi_dev;
-	struct f11_data *data = fn->data;
+	struct rmi_device *rmi_dev = fn_dev->rmi_dev;
+	struct f11_data *data = fn_dev->data;
 	/* Command register always reads as 0, so we can just use a local. */
 	struct f11_2d_commands commands = {
 		.rezero = true,
 	};
 	int retval = 0;
 
-	dev_dbg(&fn->dev, "Resuming...\n");
+	dev_dbg(&fn_dev->dev, "Resuming...\n");
 	if (!data->rezero_wait_ms)
 		return 0;
 
 	mdelay(data->rezero_wait_ms);
 
-	retval = rmi_write_block(rmi_dev, fn->fd.command_base_addr,
+	retval = rmi_write_block(rmi_dev, fn_dev->fd.command_base_addr,
 			&commands, sizeof(commands));
 	if (retval < 0) {
-		dev_err(&fn->dev, "%s: failed to issue rezero command, error = %d.",
+		dev_err(&fn_dev->dev, "%s: failed to issue rezero command, error = %d.",
 			__func__, retval);
 		return retval;
 	}
@@ -2701,62 +838,43 @@ static int rmi_f11_resume(struct rmi_function *fn)
 }
 #endif /* CONFIG_PM */
 
-static int rmi_f11_probe(struct rmi_function *fn)
+static int rmi_f11_remove(struct rmi_function_dev *fn_dev)
+{
+	rmi_f11_free_devices(fn_dev);
+	return 0;
+}
+
+static int rmi_f11_probe(struct rmi_function_dev *fn_dev)
 {
 	int rc;
 
-	rc = rmi_f11_initialize(fn);
+	rc = rmi_f11_initialize(fn_dev);
 	if (rc < 0)
 		return rc;
 
-	rc = rmi_f11_register_devices(fn);
+	rc = rmi_f11_register_devices(fn_dev);
 	if (rc < 0)
 		return rc;
 
-	rc = rmi_f11_create_sysfs(fn);
 	if (rc < 0)
 		return rc;
 
 	return 0;
 }
 
-static void rmi_f11_remove(struct rmi_function *fn)
-{
-	struct f11_data *f11 = fn->data;
-	int attr_count = 0;
-
-	if (IS_ENABLED(CONFIG_RMI4_DEBUG)) {
-		int i;
-
-		for (i = 0; i < f11->dev_query.nbr_of_sensors + 1; i++)
-			teardown_sensor_debugfs(&f11->sensors[i]);
-		teardown_f11_debugfs(f11);
-	}
-
-	for (attr_count = 0; attr_count < ARRAY_SIZE(attrs); attr_count++)
-		sysfs_remove_file(&fn->dev.kobj, &attrs[attr_count].attr);
-
-	rmi_f11_free_devices(fn);
-}
-
-
-static struct rmi_function_handler rmi_f11_handler = {
+static struct rmi_function_driver function_driver = {
 	.driver = {
 		.name = "rmi_f11",
 	},
-	.func = 0x11,
+	.func = FUNCTION_NUMBER,
 	.probe = rmi_f11_probe,
 	.remove = rmi_f11_remove,
 	.config = rmi_f11_config,
 	.attention = rmi_f11_attention,
-#ifdef CONFIG_HAS_EARLYSUSPEND
-	.late_resume = rmi_f11_resume
-#elif defined(CONFIG_PM)
 	.resume = rmi_f11_resume
-#endif  /* defined(CONFIG_HAS_EARLYSUSPEND) */
 };
 
-module_rmi_driver(rmi_f11_handler);
+module_rmi_function_driver(function_driver);
 
 MODULE_AUTHOR("Christopher Heiny <cheiny@synaptics.com");
 MODULE_DESCRIPTION("RMI F11 module");
diff --git a/drivers/input/rmi4/rmi_f11.h b/drivers/input/rmi4/rmi_f11.h
new file mode 100644
index 0000000..f9e0574
--- /dev/null
+++ b/drivers/input/rmi4/rmi_f11.h
@@ -0,0 +1,779 @@
+/*
+ * Copyright (c) 2013 Synaptics Incorporated
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ */
+
+#ifndef RMI_F11_CONTROL_H
+#define RMI_F11_CONTROL_H
+
+#define F11_MAX_NUM_OF_SENSORS 8
+
+#define NAME_BUFFER_SIZE 256
+
+/** A note about RMI4 F11 register structure.
+ *
+ *  There may be one or more individual 2D touch surfaces associated with an
+ * instance for F11.  For example, a handheld device might have a touchscreen
+ * display on the front, and a touchpad on the back.  F11 represents these touch
+ * surfaces as individual sensors, up to 7 on a given RMI4 device.
+ *
+ * The properties for
+ * a given sensor are described by its query registers.  The number of query
+ * registers and the layout of their contents are described by the F11 device
+ * queries as well as the per-sensor query information.  The query registers
+ * for sensor[n+1] immediately follow those for sensor[n], so the start address
+ * of the sensor[n+1] queries can only be computed if you know the size of the
+ * sensor[n] queries.  Because each of the sensors may have different
+ * properties, the size of the query registers for each sensor must be
+ * calculated on a sensor by sensor basis.
+ *
+ * Similarly, each sensor has control registers that govern its behavior.  The
+ * size and layout of the control registers for a given sensor can be determined
+ * by parsing that sensors query registers.  The control registers for
+ * sensor[n+1] immediately follow those for sensor[n], so you can only know
+ * the start address for the sensor[n+1] controls if you know the size (and
+ * location) of the sensor[n] controls.
+ *
+ * And in a likewise fashion, each sensor has data registers where it reports
+ * its touch data and other interesting stuff.  The size and layout of a
+ * sensors data registers must be determined by parsing its query registers.
+ * The data registers for sensor[n+1] immediately follow those for sensor[n],
+ * so you can only know the start address for the sensor[n+1] controls if you
+ * know the size (and location) of the sensor[n] controls.
+ *
+ * The short story is that we need to read and parse a lot of query
+ * registers in order to determine the attributes of a sensor[0].  Then
+ * we need to use that data to compute the size of the control and data
+ * registers for sensor[0].  Once we have that figured out, we can then do
+ * the same thing for each subsequent sensor.
+ *
+ * The end result is that we have a number of structs that aren't used to
+ * directly generate the input events, but their size, location and contents
+ * are critical to determining where the data we are interested in lives.
+ *
+ * At this time, the driver does not yet comprehend all possible F11
+ * configuration options, but it should be sufficient to cover 99% of RMI4 F11
+ * devices currently in the field.
+ */
+
+/**
+ * @rezero - writing 1 to this will cause the sensor to calibrate to the
+ * current capacitive state.
+ */
+struct f11_2d_commands {
+	u8 rezero:1;
+	u8 reserved:7;
+} __attribute__((__packed__));
+
+/** This query is always present, and is on a per device basis.  All other
+ * queries are on a per-sensor basis.
+ *
+ * @nbr_of_sensors - the number of 2D sensors on the touch device.
+ * @has_query9 - indicates the F11_2D_Query9 register exists.
+ * @has_query11 - indicates the F11_2D_Query11 register exists.
+ * @has_query12 - indicates the F11_2D_Query12 register exists.
+ */
+struct f11_2d_device_query {
+	u8 nbr_of_sensors:3;
+	u8 has_query9:1;
+	u8 has_query11:1;
+	u8 has_query12:1;
+	u8 has_query27:1;
+	u8 has_query28:1;
+} __attribute__((__packed__));
+
+/** Query registers 1 through 4 are always present.
+ * @number_of_fingers - describes the maximum number of fingers the 2-D sensor
+ * supports.
+ * @has_rel - the sensor supports relative motion reporting.
+ * @has_abs - the sensor supports absolute poition reporting.
+ * @has_gestures - the sensor supports gesture reporting.
+ * @has_sensitivity_adjust - the sensor supports a global sensitivity
+ * adjustment.
+ * @configurable - the sensor supports various configuration options.
+ * @num_of_x_electrodes -  the maximum number of electrodes the 2-D sensor
+ * supports on the X axis.
+ * @num_of_y_electrodes -  the maximum number of electrodes the 2-D sensor
+ * supports on the Y axis.
+ * @max_electrodes - the total number of X and Y electrodes that may be
+ * configured.
+ */
+struct f11_2d_sensor_info {
+	/* query1 */
+	u8 number_of_fingers:3;
+	u8 has_rel:1;
+	u8 has_abs:1;
+	u8 has_gestures:1;
+	u8 has_sensitivity_adjust:1;
+	u8 configurable:1;
+	/* query2 */
+	u8 num_of_x_electrodes:7;
+	u8 reserved_1:1;
+	/* query3 */
+	u8 num_of_y_electrodes:7;
+	u8 reserved_2:1;
+	/* query4 */
+	u8 max_electrodes:7;
+	u8 reserved_3:1;
+} __attribute__((__packed__));
+
+/** Query 5 - this is present if the has_abs bit is set.
+ *
+ * @abs_data_size - describes the format of data reported by the absolute
+ * data source.  Only one format (the kind used here) is supported at this
+ * time.
+ * @has_anchored_finger - then the sensor supports the high-precision second
+ * finger tracking provided by the manual tracking and motion sensitivity
+ * options.
+ * @has_adjust_hyst - the difference between the finger release threshold and
+ * the touch threshold.
+ * @has_dribble - the sensor supports the generation of dribble interrupts,
+ * which may be enabled or disabled with the dribble control bit.
+ * @has_bending_correction - Bending related data registers 28 and 36, and
+ * control register 52..57 are present.
+ * @has_large_object_suppression - control register 58 and data register 28
+ * exist.
+ * @has_jitter_filter - query 13 and control 73..76 exist.
+ */
+struct f11_2d_abs_info {
+	u8 abs_data_size:2;
+	u8 has_anchored_finger:1;
+	u8 has_adj_hyst:1;
+	u8 has_dribble:1;
+	u8 has_bending_correction:1;
+	u8 has_large_object_suppression:1;
+	u8 has_jitter_filter:1;
+} __attribute__((__packed__));
+
+/** Gesture information queries 7 and 8 are present if has_gestures bit is set.
+ *
+ * @has_single_tap - a basic single-tap gesture is supported.
+ * @has_tap_n_hold - tap-and-hold gesture is supported.
+ * @has_double_tap - double-tap gesture is supported.
+ * @has_early_tap - early tap is supported and reported as soon as the finger
+ * lifts for any tap event that could be interpreted as either a single tap
+ * or as the first tap of a double-tap or tap-and-hold gesture.
+ * @has_flick - flick detection is supported.
+ * @has_press - press gesture reporting is supported.
+ * @has_pinch - pinch gesture detection is supported.
+ * @has_palm_det - the 2-D sensor notifies the host whenever a large conductive
+ * object such as a palm or a cheek touches the 2-D sensor.
+ * @has_rotate - rotation gesture detection is supported.
+ * @has_touch_shapes - TouchShapes are supported.  A TouchShape is a fixed
+ * rectangular area on the sensor that behaves like a capacitive button.
+ * @has_scroll_zones - scrolling areas near the sensor edges are supported.
+ * @has_individual_scroll_zones - if 1, then 4 scroll zones are supported;
+ * if 0, then only two are supported.
+ * @has_multi_finger_scroll - the multifinger_scrolling bit will be set when
+ * more than one finger is involved in a scrolling action.
+ */
+struct f11_2d_gesture_info {
+	u8 has_single_tap:1;
+	u8 has_tap_n_hold:1;
+	u8 has_double_tap:1;
+	u8 has_early_tap:1;
+	u8 has_flick:1;
+	u8 has_press:1;
+	u8 has_pinch:1;
+	u8 has_chiral:1;
+
+	u8 has_palm_det:1;
+	u8 has_rotate:1;
+	u8 has_touch_shapes:1;
+	u8 has_scroll_zones:1;
+	u8 has_individual_scroll_zones:1;
+	u8 has_multi_finger_scroll:1;
+	u8 has_mf_edge_motion:1;
+	u8 has_mf_scroll_inertia:1;
+} __attribute__((__packed__));
+
+/**
+ * @has_pen - detection of a stylus is supported and registers F11_2D_Ctrl20
+ * and F11_2D_Ctrl21 exist.
+ * @has_proximity - detection of fingers near the sensor is supported and
+ * registers F11_2D_Ctrl22 through F11_2D_Ctrl26 exist.
+ * @has_palm_det_sensitivity -  the sensor supports the palm detect sensitivity
+ * feature and register F11_2D_Ctrl27 exists.
+ * @has_two_pen_thresholds - is has_pen is also set, then F11_2D_Ctrl35 exists.
+ * @has_contact_geometry - the sensor supports the use of contact geometry to
+ * map absolute X and Y target positions and registers F11_2D_Data18.* through
+ * F11_2D_Data27 exist.
+ */
+struct f11_2d_query9 {
+	u8 has_pen:1;
+	u8 has_proximity:1;
+	u8 has_palm_det_sensitivity:1;
+	u8 has_suppress_on_palm_detect:1;
+	u8 has_two_pen_thresholds:1;
+	u8 has_contact_geometry:1;
+	u8 has_pen_hover_discrimination:1;
+	u8 has_pen_filters:1;
+} __attribute__((__packed__));
+
+/** Touch shape info (query 10) is present if has_touch_shapes is set.
+ *
+ * @nbr_touch_shapes - the total number of touch shapes supported.
+ */
+struct f11_2d_ts_info {
+	u8 nbr_touch_shapes:5;
+	u8 reserved:3;
+} __attribute__((__packed__));
+
+/** Query 11 is present if the has_query11 bit is set in query 0.
+ *
+ * @has_z_tuning - if set, the sensor supports Z tuning and registers
+ * F11_2D_Ctrl29 through F11_2D_Ctrl33 exist.
+ * @has_algorithm_selection - controls choice of noise suppression algorithm
+ * @has_w_tuning - the sensor supports Wx and Wy scaling and registers
+ * F11_2D_Ctrl36 through F11_2D_Ctrl39 exist.
+ * @has_pitch_info - the X and Y pitches of the sensor electrodes can be
+ * configured and registers F11_2D_Ctrl40 and F11_2D_Ctrl41 exist.
+ * @has_finger_size -  the default finger width settings for the
+ * sensor can be configured and registers F11_2D_Ctrl42 through F11_2D_Ctrl44
+ * exist.
+ * @has_segmentation_aggressiveness - the sensor’s ability to distinguish
+ * multiple objects close together can be configured and register F11_2D_Ctrl45
+ * exists.
+ * @has_XY_clip -  the inactive outside borders of the sensor can be
+ * configured and registers F11_2D_Ctrl46 through F11_2D_Ctrl49 exist.
+ * @has_drumming_filter - the sensor can be configured to distinguish
+ * between a fast flick and a quick drumming movement and registers
+ * F11_2D_Ctrl50 and F11_2D_Ctrl51 exist.
+ */
+struct f11_2d_query11 {
+	u8 has_z_tuning:1;
+	u8 has_algorithm_selection:1;
+	u8 has_w_tuning:1;
+	u8 has_pitch_info:1;
+	u8 has_finger_size:1;
+	u8 has_segmentation_aggressiveness:1;
+	u8 has_XY_clip:1;
+	u8 has_drumming_filter:1;
+} __attribute__((__packed__));
+
+/**
+ * @has_gapless_finger - control registers relating to gapless finger are
+ * present.
+ * @has_gapless_finger_tuning - additional control and data registers relating
+ * to gapless finger are present.
+ * @has_8bit_w - larger W value reporting is supported.
+ * @has_adjustable_mapping - TBD
+ * @has_info2 - the general info query14 is present
+ * @has_physical_props - additional queries describing the physical properties
+ * of the sensor are present.
+ * @has_finger_limit - indicates that F11 Ctrl 80 exists.
+ * @has_linear_coeff - indicates that F11 Ctrl 81 exists.
+ */
+struct f11_2d_query12 {
+	u8 has_gapless_finger:1;
+	u8 has_gapless_finger_tuning:1;
+	u8 has_8bit_w:1;
+	u8 has_adjustable_mapping:1;
+	u8 has_info2:1;
+	u8 has_physical_props:1;
+	u8 has_finger_limit:1;
+	u8 has_linear_coeff_2:1;
+} __attribute__((__packed__));
+
+/** This register is present if Query 5's has_jitter_filter bit is set.
+ * @jitter_window_size - used by Design Studio 4.
+ * @jitter_filter_type - used by Design Studio 4.
+ */
+struct f11_2d_query13 {
+	u8 jtter_window_size:5;
+	u8 jitter_filter_type:2;
+	u8 reserved:1;
+} __attribute__((__packed__));
+
+/** This register is present if query 12's has_general_info2 flag is set.
+ *
+ * @light_control - Indicates what light/led control features are present, if
+ * any.
+ * @is_clear - if set, this is a clear sensor (indicating direct pointing
+ * application), otherwise it's opaque (indicating indirect pointing).
+ * @clickpad_props - specifies if this is a clickpad, and if so what sort of
+ * mechanism it uses
+ * @mouse_buttons - specifies the number of mouse buttons present (if any).
+ * @has_advanced_gestures - advanced driver gestures are supported.
+ */
+struct f11_2d_query14 {
+	u8 light_control:2;
+	u8 is_clear:1;
+	u8 clickpad_props:2;
+	u8 mouse_buttons:2;
+	u8 has_advanced_gestures:1;
+} __attribute__((__packed__));
+
+#define F11_LIGHT_CTL_NONE 0x00
+#define F11_LUXPAD	   0x01
+#define F11_DUAL_MODE      0x02
+
+#define F11_NOT_CLICKPAD     0x00
+#define F11_HINGED_CLICKPAD  0x01
+#define F11_UNIFORM_CLICKPAD 0x02
+
+/** See notes above for information about specific query register sets.
+ */
+struct f11_2d_sensor_queries {
+	struct f11_2d_sensor_info info;
+	struct f11_2d_abs_info abs_info;
+	u8 f11_2d_query6;
+	struct f11_2d_gesture_info gesture_info;
+	struct f11_2d_query9 query9;
+	struct f11_2d_ts_info ts_info;
+	struct f11_2d_query11 features_1;
+	struct f11_2d_query12 features_2;
+	struct f11_2d_query13 jitter_filter;
+	struct f11_2d_query14 info_2;
+};
+
+/**
+ * @reporting_mode - controls how often finger position data is reported.
+ * @abs_pos_filt - when set, enables various noise and jitter filtering
+ * algorithms for absolute reports.
+ * @rel_pos_filt - when set, enables various noise and jitter filtering
+ * algorithms for relative reports.
+ * @rel_ballistics - enables ballistics processing for the relative finger
+ * motion on the 2-D sensor.
+ * @dribble - enables the dribbling feature.
+ * @report_beyond_clip - when this is set, fingers outside the active area
+ * specified by the x_clip and y_clip registers will be reported, but with
+ * reported finger position clipped to the edge of the active area.
+ * @palm_detect_thresh - the threshold at which a wide finger is considered a
+ * palm. A value of 0 inhibits palm detection.
+ * @motion_sensitivity - specifies the threshold an anchored finger must move
+ * before it is considered no longer anchored.  High values mean more
+ * sensitivity.
+ * @man_track_en - for anchored finger tracking, whether the host (1) or the
+ * device (0) determines which finger is the tracked finger.
+ * @man_tracked_finger - when man_track_en is 1, specifies whether finger 0 or
+ * finger 1 is the tracked finger.
+ * @delta_x_threshold - 2-D position update interrupts are inhibited unless
+ * the finger moves more than a certain threshold distance along the X axis.
+ * @delta_y_threshold - 2-D position update interrupts are inhibited unless
+ * the finger moves more than a certain threshold distance along the Y axis.
+ * @velocity - When rel_ballistics is set, this register defines the
+ * velocity ballistic parameter applied to all relative motion events.
+ * @acceleration - When rel_ballistics is set, this register defines the
+ * acceleration ballistic parameter applied to all relative motion events.
+ * @sensor_max_x_pos - the maximum X coordinate reported by the sensor.
+ * @sensor_max_y_pos - the maximum Y coordinate reported by the sensor.
+ */
+struct f11_2d_ctrl0_9 {
+	/* F11_2D_Ctrl0 */
+	u8 reporting_mode:3;
+	u8 abs_pos_filt:1;
+	u8 rel_pos_filt:1;
+	u8 rel_ballistics:1;
+	u8 dribble:1;
+	u8 report_beyond_clip:1;
+	/* F11_2D_Ctrl1 */
+	u8 palm_detect_thres:4;
+	u8 motion_sensitivity:2;
+	u8 man_track_en:1;
+	u8 man_tracked_finger:1;
+	/* F11_2D_Ctrl2 and 3 */
+	u8 delta_x_threshold:8;
+	u8 delta_y_threshold:8;
+	/* F11_2D_Ctrl4 and 5 */
+	u8 velocity:8;
+	u8 acceleration:8;
+	/* F11_2D_Ctrl6 thru 9 */
+	u16 sensor_max_x_pos:12;
+	u8 ctrl7_reserved:4;
+	u16 sensor_max_y_pos:12;
+	u8 ctrl9_reserved:4;
+} __attribute__((__packed__));
+
+/**
+ * @single_tap_int_enable - enable tap gesture recognition.
+ * @tap_n_hold_int_enable - enable tap-and-hold gesture recognition.
+ * @double_tap_int_enable - enable double-tap gesture recognition.
+ * @early_tap_int_enable - enable early tap notification.
+ * @flick_int_enable - enable flick detection.
+ * @press_int_enable - enable press gesture recognition.
+ * @pinch_int_enable - enable pinch detection.
+ */
+struct f11_2d_ctrl10 {
+	u8 single_tap_int_enable:1;
+	u8 tap_n_hold_int_enable:1;
+	u8 double_tap_int_enable:1;
+	u8 early_tap_int_enable:1;
+	u8 flick_int_enable:1;
+	u8 press_int_enable:1;
+	u8 pinch_int_enable:1;
+	u8 reserved:1;
+} __attribute__((__packed__));
+
+/**
+ * @palm_detect_int_enable - enable palm detection feature.
+ * @rotate_int_enable - enable rotate gesture detection.
+ * @touch_shape_int_enable - enable the TouchShape feature.
+ * @scroll_zone_int_enable - enable scroll zone reporting.
+ * @multi_finger_scroll_int_enable - enable the multfinger scroll feature.
+ */
+struct f11_2d_ctrl11 {
+	u8 palm_detect_int_enable:1;
+	u8 rotate_int_enable:1;
+	u8 touch_shape_int_enable:1;
+	u8 scroll_zone_int_enable:1;
+	u8 multi_finger_scroll_int_enable:1;
+	u8 reserved:3;
+} __attribute__((__packed__));
+
+/**
+ * @sens_adjustment - allows a host to alter the overall sensitivity of a
+ * 2-D sensor. A positive value in this register will make the sensor more
+ * sensitive than the factory defaults, and a negative value will make it
+ * less sensitive.
+ * @hyst_adjustment - increase the touch/no-touch hysteresis by 2 Z-units for
+ * each one unit increment in this setting.
+ */
+struct f11_2d_ctrl14 {
+	s8 sens_adjustment:5;
+	u8 hyst_adjustment:3;
+} __attribute__((__packed__));
+
+/**
+ * @max_tap_time - the maximum duration of a tap, in 10-millisecond units.
+ */
+struct f11_2d_ctrl15 {
+	u8 max_tap_time:8;
+} __attribute__((__packed__));
+
+/**
+ * @min_press_time - The minimum duration required for stationary finger(s) to
+ * generate a press gesture, in 10-millisecond units.
+ */
+struct f11_2d_ctrl16 {
+	u8 min_press_time:8;
+} __attribute__((__packed__));
+
+/**
+ * @max_tap_distance - Determines the maximum finger movement allowed during
+ * a tap, in 0.1-millimeter units.
+ */
+struct f11_2d_ctrl17 {
+	u8 max_tap_distance:8;
+} __attribute__((__packed__));
+
+/**
+ * @min_flick_distance - the minimum finger movement for a flick gesture,
+ * in 1-millimeter units.
+ * @min_flick_speed - the minimum finger speed for a flick gesture, in
+ * 10-millimeter/second units.
+ */
+struct f11_2d_ctrl18_19 {
+	u8 min_flick_distance:8;
+	u8 min_flick_speed:8;
+} __attribute__((__packed__));
+
+/**
+ * @pen_detect_enable - enable reporting of stylus activity.
+ * @pen_jitter_filter_enable - Setting this enables the stylus anti-jitter
+ * filter.
+ * @pen_z_threshold - This is the stylus-detection lower threshold. Smaller
+ * values result in higher sensitivity.
+ */
+struct f11_2d_ctrl20_21 {
+	u8 pen_detect_enable:1;
+	u8 pen_jitter_filter_enable:1;
+	u8 ctrl20_reserved:6;
+	u8 pen_z_threshold:8;
+} __attribute__((__packed__));
+
+/**
+ * These are not accessible through sysfs yet.
+ *
+ * @proximity_detect_int_en - enable proximity detection feature.
+ * @proximity_jitter_filter_en - enables an anti-jitter filter on proximity
+ * data.
+ * @proximity_detection_z_threshold - the threshold for finger-proximity
+ * detection.
+ * @proximity_delta_x_threshold - In reduced-reporting modes, this is the
+ * threshold for proximate-finger movement in the direction parallel to the
+ * X-axis.
+ * @proximity_delta_y_threshold - In reduced-reporting modes, this is the
+ * threshold for proximate-finger movement in the direction parallel to the
+ * Y-axis.
+ * * @proximity_delta_Z_threshold - In reduced-reporting modes, this is the
+ * threshold for proximate-finger movement in the direction parallel to the
+ * Z-axis.
+ */
+struct f11_2d_ctrl22_26 {
+	/* control 22 */
+	u8 proximity_detect_int_en:1;
+	u8 proximity_jitter_filter_en:1;
+	u8 f11_2d_ctrl6_b3__7:6;
+
+	/* control 23 */
+	u8 proximity_detection_z_threshold;
+
+	/* control 24 */
+	u8 proximity_delta_x_threshold;
+
+	/* control 25 */
+	u8 proximity_delta_y_threshold;
+
+	/* control 26 */
+	u8 proximity_delta_z_threshold;
+} __attribute__((__packed__));
+
+/**
+ * @palm_detecy_sensitivity - When this value is small, smaller objects will
+ * be identified as palms; when this value is large, only larger objects will
+ * be identified as palms. 0 represents the factory default.
+ * @suppress_on_palm_detect - when set, all F11 interrupts except palm_detect
+ * are suppressed while a palm is detected.
+ */
+struct f11_2d_ctrl27 {
+	s8 palm_detect_sensitivity:4;
+	u8 suppress_on_palm_detect:1;
+	u8 f11_2d_ctrl27_b5__7:3;
+} __attribute__((__packed__));
+
+/**
+ * @multi_finger_scroll_mode - allows choice of multi-finger scroll mode and
+ * determines whether and how X or Y displacements are reported.
+ * @edge_motion_en - enables the edge_motion feature.
+ * @multi_finger_scroll_momentum - controls the length of time that scrolling
+ * continues after fingers have been lifted.
+ */
+struct f11_2d_ctrl28 {
+	u8 multi_finger_scroll_mode:2;
+	u8 edge_motion_en:1;
+	u8 f11_2d_ctrl28b_3:1;
+	u8 multi_finger_scroll_momentum:4;
+} __attribute__((__packed__));
+
+/**
+ * @z_touch_threshold - Specifies the finger-arrival Z threshold. Large values
+ * may cause smaller fingers to be rejected.
+ * @z_touch_hysteresis - Specifies the difference between the finger-arrival
+ * Z threshold and the finger-departure Z threshold.
+ */
+struct f11_2d_ctrl29_30 {
+	u8 z_touch_threshold;
+	u8 z_touch_hysteresis;
+} __attribute__((__packed__));
+
+
+struct f11_2d_ctrl {
+	struct f11_2d_ctrl0_9		 *ctrl0_9;
+	u16				ctrl0_9_address;
+	struct f11_2d_ctrl10		*ctrl10;
+	struct f11_2d_ctrl11		*ctrl11;
+	u8				ctrl12_size;
+	struct f11_2d_ctrl14		*ctrl14;
+	struct f11_2d_ctrl15		*ctrl15;
+	struct f11_2d_ctrl16		*ctrl16;
+	struct f11_2d_ctrl17		*ctrl17;
+	struct f11_2d_ctrl18_19		*ctrl18_19;
+	struct f11_2d_ctrl20_21		*ctrl20_21;
+	struct f11_2d_ctrl22_26		*ctrl22_26;
+	struct f11_2d_ctrl27		*ctrl27;
+	struct f11_2d_ctrl28		*ctrl28;
+	struct f11_2d_ctrl29_30		*ctrl29_30;
+};
+
+/**
+ * @x_msb - top 8 bits of X finger position.
+ * @y_msb - top 8 bits of Y finger position.
+ * @x_lsb - bottom 4 bits of X finger position.
+ * @y_lsb - bottom 4 bits of Y finger position.
+ * @w_y - contact patch width along Y axis.
+ * @w_x - contact patch width along X axis.
+ * @z - finger Z value (proxy for pressure).
+ */
+struct f11_2d_data_1_5 {
+	u8 x_msb;
+	u8 y_msb;
+	u8 x_lsb:4;
+	u8 y_lsb:4;
+	u8 w_y:4;
+	u8 w_x:4;
+	u8 z;
+} __attribute__((__packed__));
+
+/**
+ * @delta_x - relative motion along X axis.
+ * @delta_y - relative motion along Y axis.
+ */
+struct f11_2d_data_6_7 {
+	s8 delta_x;
+	s8 delta_y;
+} __attribute__((__packed__));
+
+/**
+ * @single_tap - a single tap was recognized.
+ * @tap_and_hold - a tap-and-hold gesture was recognized.
+ * @double_tap - a double tap gesture was recognized.
+ * @early_tap - a tap gesture might be happening.
+ * @flick - a flick gesture was detected.
+ * @press - a press gesture was recognized.
+ * @pinch - a pinch gesture was detected.
+ */
+struct f11_2d_data_8 {
+	u8 single_tap:1;
+	u8 tap_and_hold:1;
+	u8 double_tap:1;
+	u8 early_tap:1;
+	u8 flick:1;
+	u8 press:1;
+	u8 pinch:1;
+} __attribute__((__packed__));
+
+/**
+ * @palm_detect - a palm or other large object is in contact with the sensor.
+ * @rotate - a rotate gesture was detected.
+ * @shape - a TouchShape has been activated.
+ * @scrollzone - scrolling data is available.
+ * @finger_count - number of fingers involved in the reported gesture.
+ */
+struct f11_2d_data_9 {
+	u8 palm_detect:1;
+	u8 rotate:1;
+	u8 shape:1;
+	u8 scrollzone:1;
+	u8 finger_count:3;
+} __attribute__((__packed__));
+
+/**
+ * @pinch_motion - when a pinch gesture is detected, this is the change in
+ * distance between the two fingers since this register was last read.
+ */
+struct f11_2d_data_10 {
+	s8 pinch_motion;
+} __attribute__((__packed__));
+
+/**
+ * @x_flick_dist - when a flick gesture is detected,  the distance of flick
+ * gesture in X direction.
+ * @y_flick_dist - when a flick gesture is detected,  the distance of flick
+ * gesture in Y direction.
+ * @flick_time - the total time of the flick gesture, in 10ms units.
+ */
+struct f11_2d_data_10_12 {
+	s8 x_flick_dist;
+	s8 y_flick_dist;
+	u8 flick_time;
+} __attribute__((__packed__));
+
+/**
+ * @motion - when a rotate gesture is detected, the accumulated distance
+ * of the rotate motion. Clockwise motion is positive and counterclockwise
+ * motion is negative.
+ * @finger_separation - when a rotate gesture is detected, the distance
+ * between the fingers.
+ */
+struct f11_2d_data_11_12 {
+	s8 motion;
+	u8 finger_separation;
+} __attribute__((__packed__));
+
+/**
+ * @shape_n - a bitmask of the currently activate TouchShapes (if any).
+ */
+struct f11_2d_data_13 {
+	u8 shape_n;
+} __attribute__((__packed__));
+
+/**
+ * @horizontal - chiral scrolling distance in the X direction.
+ * @vertical - chiral scrolling distance in the Y direction.
+ */
+struct f11_2d_data_14_15 {
+	s8 horizontal;
+	s8 vertical;
+} __attribute__((__packed__));
+
+/**
+ * @x_low - scroll zone motion along the lower edge of the sensor.
+ * @y_right - scroll zone motion along the right edge of the sensor.
+ * @x_upper - scroll zone motion along the upper edge of the sensor.
+ * @y_left - scroll zone motion along the left edge of the sensor.
+ */
+struct f11_2d_data_14_17 {
+	s8 x_low;
+	s8 y_right;
+	s8 x_upper;
+	s8 y_left;
+} __attribute__((__packed__));
+
+struct f11_2d_data {
+	u8				*f_state;
+	const struct f11_2d_data_1_5	*abs_pos;
+	const struct f11_2d_data_6_7	*rel_pos;
+	const struct f11_2d_data_8	*gest_1;
+	const struct f11_2d_data_9	*gest_2;
+	const struct f11_2d_data_10	*pinch;
+	const struct f11_2d_data_10_12	*flick;
+	const struct f11_2d_data_11_12	*rotate;
+	const struct f11_2d_data_13	*shapes;
+	const struct f11_2d_data_14_15	*multi_scroll;
+	const struct f11_2d_data_14_17	*scroll_zones;
+};
+
+/**
+ * @axis_align - controls parameters that are useful in system prototyping
+ * and bring up.
+ * @sens_query - query registers for this particular sensor.
+ * @data - the data reported by this sensor, mapped into a collection of
+ * structs.
+ * @max_x - The maximum X coordinate that will be reported by this sensor.
+ * @max_y - The maximum Y coordinate that will be reported by this sensor.
+ * @nbr_fingers - How many fingers can this sensor report?
+ * @data_pkt - buffer for data reported by this sensor.
+ * @pkt_size - number of bytes in that buffer.
+ * @sensor_index - identifies this particular 2D touch sensor
+ * @type_a - some early RMI4 2D sensors do not reliably track the finger
+ * position when two fingers are on the device.  When this is true, we
+ * assume we have one of those sensors and report events appropriately.
+ * @sensor_type - indicates whether we're touchscreen or touchpad.
+ * @input - input device for absolute pointing stream
+ * @mouse_input - input device for relative pointing stream.
+ * @input_phys - buffer for the absolute phys name for this sensor.
+ * @input_phys_mouse - buffer for the relative phys name for this sensor.
+ */
+struct f11_2d_sensor {
+	struct rmi_f11_2d_axis_alignment axis_align;
+	struct f11_2d_sensor_queries sens_query;
+	struct f11_2d_data data;
+	u16 max_x;
+	u16 max_y;
+	u8 nbr_fingers;
+	u8 *data_pkt;
+	int pkt_size;
+	u8 sensor_index;
+	u32 type_a;
+	enum rmi_f11_sensor_type sensor_type;
+	struct input_dev *input;
+	struct input_dev *mouse_input;
+	struct rmi_function_dev *fn_dev;
+	char input_phys[NAME_BUFFER_SIZE];
+	char input_phys_mouse[NAME_BUFFER_SIZE];
+};
+
+/** Data pertaining to F11 in general.  For per-sensor data, see struct
+ * f11_2d_sensor.
+ *
+ * @dev_query - F11 device specific query registers.
+ * @dev_controls - F11 device specific control registers.
+ * @dev_controls_mutex - lock for the control registers.
+ * @rezero_wait_ms - if nonzero, upon resume we will wait this many
+ * milliseconds before rezeroing the sensor(s).  This is useful in systems with
+ * poor electrical behavior on resume, where the initial calibration of the
+ * sensor(s) coming out of sleep state may be bogus.
+ * @sensors - per sensor data structures.
+ */
+struct f11_data {
+	struct f11_2d_device_query dev_query;
+	struct f11_2d_ctrl dev_controls;
+	struct mutex dev_controls_mutex;
+	u16 rezero_wait_ms;
+	struct f11_2d_sensor sensors[F11_MAX_NUM_OF_SENSORS];
+};
+#endif

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* Re: [PATCH 04/05] input: RMI4 F01 device control
  2013-01-19  1:12 ` [PATCH 04/05] input: RMI4 F01 device control Christopher Heiny
@ 2013-01-31  8:08   ` Dmitry Torokhov
  2013-01-31 21:14     ` Christopher Heiny
  0 siblings, 1 reply; 11+ messages in thread
From: Dmitry Torokhov @ 2013-01-31  8:08 UTC (permalink / raw)
  To: Christopher Heiny
  Cc: Jean Delvare, Linux Kernel, Linux Input, Allie Xiong, Vivian Ly,
	Daniel Rosenberg, Alexandra Chin, Joerie de Gram, Wolfram Sang,
	Mathieu Poirier, Linus Walleij

Hi Chris,

On Fri, Jan 18, 2013 at 05:12:44PM -0800, Christopher Heiny wrote:
> In addition to the changes described in 0/0 of this patchset, this patch
> includes device serialization updated to conform to the latest RMI4
> specification.

I was looking at the various aspects of the RMI4 patchset, trying to
fix the issues that I see, but there is one big issue that I simply do
not have time to tackle - the driver is completely broken on big endian
architectures due to reliance on bitfileds when exchanging the data with
the device.

Consider the following structures:

>  struct f01_device_status {
> -	u8 status_code:4;
> +	enum rmi_device_status status_code:4;
>  	u8 reserved:2;
>  	u8 flash_prog:1;
>  	u8 unconfigured:1;
> @@ -159,4 +136,113 @@ struct f01_device_control_0 {
>  	u8 configured:1;
>  } __attribute__((__packed__));
>  
> +/**
> + * @reset - set this bit to force a firmware reset of the sensor.
> + */
> +struct f01_device_commands {
> +	u8 reset:1;
> +	u8 reserved:7;
> +};
> +

To make this work on BE boxes you either need to add #ifdefs to the
structures reversing the order of fields or use bit shifts and masks to
get/set specific bits in bytes.

I tried converting F01 code (you can see the [likely broken as I can't
test] result in my tree), but I really do not have time for F11.

Thanks.

-- 
Dmitry

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH 04/05] input: RMI4 F01 device control
  2013-01-31  8:08   ` Dmitry Torokhov
@ 2013-01-31 21:14     ` Christopher Heiny
  2013-02-07 23:19       ` Christopher Heiny
  0 siblings, 1 reply; 11+ messages in thread
From: Christopher Heiny @ 2013-01-31 21:14 UTC (permalink / raw)
  To: Dmitry Torokhov
  Cc: Jean Delvare, Linux Kernel, Linux Input, Allie Xiong, Vivian Ly,
	Daniel Rosenberg, Alexandra Chin, Joerie de Gram, Wolfram Sang,
	Mathieu Poirier, Linus Walleij

On 01/31/2013 12:08 AM, Dmitry Torokhov wrote:
> Hi Chris,
>
> On Fri, Jan 18, 2013 at 05:12:44PM -0800, Christopher Heiny wrote:
>> In addition to the changes described in 0/0 of this patchset, this patch
>> includes device serialization updated to conform to the latest RMI4
>> specification.
>
> I was looking at the various aspects of the RMI4 patchset, trying to
> fix the issues that I see, but there is one big issue that I simply do
> not have time to tackle - the driver is completely broken on big endian
> architectures due to reliance on bitfileds when exchanging the data with
> the device.

Grumble.  I brought this up during the original development, but was 
assured that it would work fine per the C language spec.  I'll have to 
revisit that discussion and report back.

Also, I noticed you merged F01 header into F01.  That's going to have to 
be backed out, because F05, F34, and F54 are also interested in the F01 
stuff, as is the (proposed) F01 diagnostic module.  We just aren't 
submitting that code right now in order to keep the code down to a 
managable size.

> Consider the following structures:
>
>>   struct f01_device_status {
>> -	u8 status_code:4;
>> +	enum rmi_device_status status_code:4;
>>   	u8 reserved:2;
>>   	u8 flash_prog:1;
>>   	u8 unconfigured:1;
>> @@ -159,4 +136,113 @@ struct f01_device_control_0 {
>>   	u8 configured:1;
>>   } __attribute__((__packed__));
>>
>> +/**
>> + * @reset - set this bit to force a firmware reset of the sensor.
>> + */
>> +struct f01_device_commands {
>> +	u8 reset:1;
>> +	u8 reserved:7;
>> +};
>> +
>
> To make this work on BE boxes you either need to add #ifdefs to the
> structures reversing the order of fields or use bit shifts and masks to
> get/set specific bits in bytes.
>
> I tried converting F01 code (you can see the [likely broken as I can't
> test] result in my tree), but I really do not have time for F11.
>
> Thanks.
>


-- 

Christopher Heiny
Senior Staff Firmware Engineer
Synaptics Incorporated

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH 04/05] input: RMI4 F01 device control
  2013-01-31 21:14     ` Christopher Heiny
@ 2013-02-07 23:19       ` Christopher Heiny
  0 siblings, 0 replies; 11+ messages in thread
From: Christopher Heiny @ 2013-02-07 23:19 UTC (permalink / raw)
  To: Dmitry Torokhov
  Cc: Jean Delvare, Linux Kernel, Linux Input, Allie Xiong, Vivian Ly,
	Daniel Rosenberg, Alexandra Chin, Joerie de Gram, Wolfram Sang,
	Mathieu Poirier, Linus Walleij

On 01/31/2013 01:14 PM, Christopher Heiny wrote:
> On 01/31/2013 12:08 AM, Dmitry Torokhov wrote:
>> Hi Chris,
>>
>> On Fri, Jan 18, 2013 at 05:12:44PM -0800, Christopher Heiny wrote:
>>> In addition to the changes described in 0/0 of this patchset, this patch
>>> includes device serialization updated to conform to the latest RMI4
>>> specification.
>>
>> I was looking at the various aspects of the RMI4 patchset, trying to
>> fix the issues that I see, but there is one big issue that I simply do
>> not have time to tackle - the driver is completely broken on big endian
>> architectures due to reliance on bitfileds when exchanging the data with
>> the device.
>
> Grumble.  I brought this up during the original development, but was
> assured that it would work fine per the C language spec.  I'll have to
> revisit that discussion and report back.

OK, after some trivial research it turns out you're right, and I was 
right originally, but let myself be blindsided by bafflegab.  Doh!

As you mentioned, fixing the endian-ness problem is a pretty wide 
ranging change to the way things are done in the driver.  Fortunately 
it's not a structural change to the architecture of the driver.

But because it affects pretty much the whole code (which is actually a 
LOT more code than we're currently submitting - but that unsubmitted 
code will have to be updated concurrently with the submitted code to 
prevent a trainwreck), I'd like to isolate that fix to a single event.

So I propose we get all our other issues worked out, since a bunch of 
them are already in progress.  Once that stuff is stable, my team can do 
one big change to fix the endian bug.  If the code is stable, we can do 
the update on our end pretty quickly.

How does that sound?

					Chris

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH 00/05] input: RMI4 Synaptics RMI4 Touchscreen Driver
  2013-01-19  1:12 [PATCH 00/05] input: RMI4 Synaptics RMI4 Touchscreen Driver Christopher Heiny
                   ` (4 preceding siblings ...)
  2013-01-19  1:12 ` [PATCH 05/05] input: RMI4 F11 2D input Christopher Heiny
@ 2014-02-04  7:56 ` Linus Walleij
  2014-02-04 20:20   ` Christopher Heiny
  5 siblings, 1 reply; 11+ messages in thread
From: Linus Walleij @ 2014-02-04  7:56 UTC (permalink / raw)
  To: Christopher Heiny
  Cc: Dmitry Torokhov, Jean Delvare, Linux Kernel, Linux Input,
	Allie Xiong, Vivian Ly, Daniel Rosenberg, Alexandra Chin,
	Joerie de Gram, Wolfram Sang, Mathieu Poirier, Linus Walleij

On Sat, Jan 19, 2013 at 2:12 AM, Christopher Heiny <cheiny@synaptics.com> wrote:

> This patchset implements changes based on the synaptics-rmi4 branch of
> Dmitry's input tree.

What is happening to the RMI4 driver stuff?

Has this development stalled? The branch in Dmitry's git
seems to be maintained but not much is happening or is
there any progress?

Yours,
Linus Walleij

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH 00/05] input: RMI4 Synaptics RMI4 Touchscreen Driver
  2014-02-04  7:56 ` [PATCH 00/05] input: RMI4 Synaptics RMI4 Touchscreen Driver Linus Walleij
@ 2014-02-04 20:20   ` Christopher Heiny
  0 siblings, 0 replies; 11+ messages in thread
From: Christopher Heiny @ 2014-02-04 20:20 UTC (permalink / raw)
  To: Linus Walleij
  Cc: Dmitry Torokhov, Jean Delvare, Linux Kernel, Linux Input,
	Allie Xiong, Vivian Ly, Daniel Rosenberg, Alexandra Chin,
	Joerie de Gram, Wolfram Sang, Mathieu Poirier, Linus Walleij

On 02/03/2014 11:56 PM, Linus Walleij wrote:
> On Sat, Jan 19, 2013 at 2:12 AM, Christopher Heiny <cheiny@synaptics.com> wrote:
>
>> This patchset implements changes based on the synaptics-rmi4 branch of
>> Dmitry's input tree.
>
> What is happening to the RMI4 driver stuff?
>
> Has this development stalled? The branch in Dmitry's git
> seems to be maintained but not much is happening or is
> there any progress?

Hi Linus,

Development stalled for several months last year, but picked up again 
last fall.  We've been submitting patches against Dmitry's input tree, 
sending them to linux-input rather than linux-kernel.  If you check the 
linux-input archives on spinics, you can see what's been going on.

If you'd like, we'll make sure to cc you on upcoming patches.  I've got 
some due - hopefully later today.

					Chris


^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2014-02-04 20:20 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-01-19  1:12 [PATCH 00/05] input: RMI4 Synaptics RMI4 Touchscreen Driver Christopher Heiny
2013-01-19  1:12 ` [PATCH 01/05] input: RMI4 public header file Christopher Heiny
2013-01-19  1:12 ` [PATCH 02/05] input: RMI4 core files Christopher Heiny
2013-01-19  1:12 ` [PATCH 03/05] input: RMI4 I2C physical layer Christopher Heiny
2013-01-19  1:12 ` [PATCH 04/05] input: RMI4 F01 device control Christopher Heiny
2013-01-31  8:08   ` Dmitry Torokhov
2013-01-31 21:14     ` Christopher Heiny
2013-02-07 23:19       ` Christopher Heiny
2013-01-19  1:12 ` [PATCH 05/05] input: RMI4 F11 2D input Christopher Heiny
2014-02-04  7:56 ` [PATCH 00/05] input: RMI4 Synaptics RMI4 Touchscreen Driver Linus Walleij
2014-02-04 20:20   ` Christopher Heiny

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).