Skip to content

Commit

Permalink
Input: synaptics-rmi4 - add device tree support for RMI4 I2C devices
Browse files Browse the repository at this point in the history
Add devicetree binding for I2C devices and add bindings for optional
parameters in the function drivers. Parameters for function drivers are
defined in child nodes for each of the functions.

Signed-off-by: Andrew Duggan <aduggan@synaptics.com>
Acked-by: Rob Herring <robh@kernel.org>
Tested-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
Tested-by: Linus Walleij <linus.walleij@linaro.org>
Tested-by: Bjorn Andersson <bjorn.andersson@linaro.org>
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
  • Loading branch information
Andrew Duggan authored and Dmitry Torokhov committed Mar 11, 2016
1 parent fdf5160 commit d8a8b3e
Show file tree
Hide file tree
Showing 8 changed files with 217 additions and 5 deletions.
39 changes: 39 additions & 0 deletions Documentation/devicetree/bindings/input/rmi4/rmi_f01.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
Synaptics RMI4 F01 Device Binding

The Synaptics RMI4 core is able to support RMI4 devices using different
transports and different functions. This file describes the device tree
bindings for devices which contain Function 1. Complete documentation
for transports and other functions can be found in:
Documentation/devicetree/bindings/input/rmi4.

Additional documentation for F01 can be found at:
http://www.synaptics.com/sites/default/files/511-000136-01-Rev-E-RMI4-Interfacing-Guide.pdf

Optional Properties:
- syna,nosleep-mode: If set the device will run at full power without sleeping.
nosleep has 3 modes, 0 will not change the default
setting, 1 will disable nosleep (allow sleeping),
and 2 will enable nosleep (disabling sleep).
- syna,wakeup-threshold: Defines the amplitude of the disturbance to the
background capacitance that will cause the
device to wake from dozing.
- syna,doze-holdoff-ms: The delay to wait after the last finger lift and the
first doze cycle.
- syna,doze-interval-ms: The time period that the device sleeps between finger
activity.


Example of a RMI4 I2C device with F01:
Example:
&i2c1 {
rmi4-i2c-dev@2c {
compatible = "syna,rmi4-i2c";

...

rmi4-f01@1 {
reg = <0x1>;
syna,nosleep-mode = <1>;
};
};
};
53 changes: 53 additions & 0 deletions Documentation/devicetree/bindings/input/rmi4/rmi_i2c.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
Synaptics RMI4 I2C Device Binding

The Synaptics RMI4 core is able to support RMI4 devices using different
transports and different functions. This file describes the device tree
bindings for devices using the I2C transport driver. Complete documentation
for other transports and functions can be found in
Documentation/devicetree/bindings/input/rmi4.

Required Properties:
- compatible: syna,rmi4-i2c
- reg: I2C address
- #address-cells: Set to 1 to indicate that the function child nodes
consist of only on uint32 value.
- #size-cells: Set to 0 to indicate that the function child nodes do not
have a size property.

Optional Properties:
- interrupts: interrupt which the rmi device is connected to.
- interrupt-parent: The interrupt controller.
See Documentation/devicetree/bindings/interrupt-controller/interrupts.txt

- syna,reset-delay-ms: The number of milliseconds to wait after resetting the
device.

Function Parameters:
Parameters specific to RMI functions are contained in child nodes of the rmi device
node. Documentation for the parameters of each function can be found in:
Documentation/devicetree/bindings/input/rmi4/rmi_f*.txt.



Example:
&i2c1 {
rmi4-i2c-dev@2c {
compatible = "syna,rmi4-i2c";
reg = <0x2c>;
#address-cells = <1>;
#size-cells = <0>;
interrupt-parent = <&gpio>;
interrupts = <4 2>;

rmi4-f01@1 {
reg = <0x1>;
syna,nosleep-mode = <1>;
};

rmi4-f11@11 {
reg = <0x11>;
touchscreen-inverted-y;
syna,sensor-type = <2>;
};
};
};
1 change: 1 addition & 0 deletions Documentation/devicetree/bindings/vendor-prefixes.txt
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,7 @@ sprd Spreadtrum Communications Inc.
st STMicroelectronics
ste ST-Ericsson
stericsson ST-Ericsson
syna Synaptics Inc.
synology Synology, Inc.
tbs TBS Technologies
tcl Toby Churchill Ltd.
Expand Down
35 changes: 35 additions & 0 deletions drivers/input/rmi4/rmi_bus.c
Original file line number Diff line number Diff line change
Expand Up @@ -153,13 +153,30 @@ static int rmi_function_match(struct device *dev, struct device_driver *drv)
return fn->fd.function_number == handler->func;
}

#ifdef CONFIG_OF
static void rmi_function_of_probe(struct rmi_function *fn)
{
char of_name[9];

snprintf(of_name, sizeof(of_name), "rmi4-f%02x",
fn->fd.function_number);
fn->dev.of_node = of_find_node_by_name(
fn->rmi_dev->xport->dev->of_node, of_name);
}
#else
static inline void rmi_function_of_probe(struct rmi_function *fn)
{}
#endif

static int rmi_function_probe(struct device *dev)
{
struct rmi_function *fn = to_rmi_function(dev);
struct rmi_function_handler *handler =
to_rmi_function_handler(dev->driver);
int error;

rmi_function_of_probe(fn);

if (handler->probe) {
error = handler->probe(fn);
return error;
Expand Down Expand Up @@ -325,6 +342,24 @@ static int rmi_register_function_handlers(void)
return ret;
}

int rmi_of_property_read_u32(struct device *dev, u32 *result,
const char *prop, bool optional)
{
int retval;
u32 val = 0;

retval = of_property_read_u32(dev->of_node, prop, &val);
if (retval && (!optional && retval == -EINVAL)) {
dev_err(dev, "Failed to get %s value: %d\n",
prop, retval);
return retval;
}
*result = val;

return 0;
}
EXPORT_SYMBOL_GPL(rmi_of_property_read_u32);

static int __init rmi_bus_init(void)
{
int error;
Expand Down
4 changes: 0 additions & 4 deletions drivers/input/rmi4/rmi_bus.h
Original file line number Diff line number Diff line change
Expand Up @@ -172,10 +172,6 @@ extern struct bus_type rmi_bus_type;

int rmi_of_property_read_u32(struct device *dev, u32 *result,
const char *prop, bool optional);
int rmi_of_property_read_u16(struct device *dev, u16 *result,
const char *prop, bool optional);
int rmi_of_property_read_u8(struct device *dev, u8 *result,
const char *prop, bool optional);

#define RMI_DEBUG_CORE BIT(0)
#define RMI_DEBUG_XPORT BIT(1)
Expand Down
28 changes: 28 additions & 0 deletions drivers/input/rmi4/rmi_driver.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include <linux/kconfig.h>
#include <linux/pm.h>
#include <linux/slab.h>
#include <linux/of.h>
#include <uapi/linux/input.h>
#include <linux/rmi.h>
#include "rmi_bus.h"
Expand Down Expand Up @@ -821,6 +822,27 @@ static int rmi_driver_remove(struct device *dev)
return 0;
}

#ifdef CONFIG_OF
static int rmi_driver_of_probe(struct device *dev,
struct rmi_device_platform_data *pdata)
{
int retval;

retval = rmi_of_property_read_u32(dev, &pdata->reset_delay_ms,
"syna,reset-delay-ms", 1);
if (retval)
return retval;

return 0;
}
#else
static inline int rmi_driver_of_probe(struct device *dev,
struct rmi_device_platform_data *pdata)
{
return -ENODEV;
}
#endif

static int rmi_driver_probe(struct device *dev)
{
struct rmi_driver *rmi_driver;
Expand All @@ -846,6 +868,12 @@ static int rmi_driver_probe(struct device *dev)

pdata = rmi_get_platform_data(rmi_dev);

if (rmi_dev->xport->dev->of_node) {
retval = rmi_driver_of_probe(rmi_dev->xport->dev, pdata);
if (retval)
return retval;
}

data = devm_kzalloc(dev, sizeof(struct rmi_driver_data), GFP_KERNEL);
if (!data)
return -ENOMEM;
Expand Down
50 changes: 50 additions & 0 deletions drivers/input/rmi4/rmi_f01.c
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,50 @@ char *rmi_f01_get_product_ID(struct rmi_function *fn)
return f01->properties.product_id;
}

#ifdef CONFIG_OF
static int rmi_f01_of_probe(struct device *dev,
struct rmi_device_platform_data *pdata)
{
int retval;
u32 val;

retval = rmi_of_property_read_u32(dev,
(u32 *)&pdata->power_management.nosleep,
"syna,nosleep-mode", 1);
if (retval)
return retval;

retval = rmi_of_property_read_u32(dev, &val,
"syna,wakeup-threshold", 1);
if (retval)
return retval;

pdata->power_management.wakeup_threshold = val;

retval = rmi_of_property_read_u32(dev, &val,
"syna,doze-holdoff-ms", 1);
if (retval)
return retval;

pdata->power_management.doze_holdoff = val * 100;

retval = rmi_of_property_read_u32(dev, &val,
"syna,doze-interval-ms", 1);
if (retval)
return retval;

pdata->power_management.doze_interval = val / 10;

return 0;
}
#else
static inline int rmi_f01_of_probe(struct device *dev,
struct rmi_device_platform_data *pdata)
{
return -ENODEV;
}
#endif

static int rmi_f01_probe(struct rmi_function *fn)
{
struct rmi_device *rmi_dev = fn->rmi_dev;
Expand All @@ -258,6 +302,12 @@ static int rmi_f01_probe(struct rmi_function *fn)
u8 device_status;
u8 temp;

if (fn->dev.of_node) {
error = rmi_f01_of_probe(&fn->dev, pdata);
if (error)
return error;
}

f01 = devm_kzalloc(&fn->dev, sizeof(struct f01_data), GFP_KERNEL);
if (!f01)
return -ENOMEM;
Expand Down
12 changes: 11 additions & 1 deletion drivers/input/rmi4/rmi_i2c.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include <linux/i2c.h>
#include <linux/rmi.h>
#include <linux/irq.h>
#include <linux/of.h>
#include "rmi_driver.h"

#define BUFFER_SIZE_INCREMENT 32
Expand Down Expand Up @@ -207,6 +208,14 @@ static int rmi_i2c_init_irq(struct i2c_client *client)
return 0;
}

#ifdef CONFIG_OF
static const struct of_device_id rmi_i2c_of_match[] = {
{ .compatible = "syna,rmi4-i2c" },
{},
};
MODULE_DEVICE_TABLE(of, rmi_i2c_of_match);
#endif

static int rmi_i2c_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
Expand All @@ -223,7 +232,7 @@ static int rmi_i2c_probe(struct i2c_client *client,

pdata = &rmi_i2c->xport.pdata;

if (client_pdata)
if (!client->dev.of_node && client_pdata)
*pdata = *client_pdata;

if (client->irq > 0)
Expand Down Expand Up @@ -372,6 +381,7 @@ static struct i2c_driver rmi_i2c_driver = {
.driver = {
.name = "rmi4_i2c",
.pm = &rmi_i2c_pm,
.of_match_table = of_match_ptr(rmi_i2c_of_match),
},
.id_table = rmi_id,
.probe = rmi_i2c_probe,
Expand Down

0 comments on commit d8a8b3e

Please sign in to comment.