aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrew Duggan <aduggan@synaptics.com>2016-03-10 18:46:32 -0500
committerDmitry Torokhov <dmitry.torokhov@gmail.com>2016-03-10 19:02:41 -0500
commitd8a8b3edfd922e3886684a3434bd2b752167ff29 (patch)
tree7a43bd47dfdab7f209bf6aa68698401db679241d
parentfdf51604f104f95bbb828019e6b8f17e7a0f834a (diff)
Input: synaptics-rmi4 - add device tree support for RMI4 I2C devices
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>
-rw-r--r--Documentation/devicetree/bindings/input/rmi4/rmi_f01.txt39
-rw-r--r--Documentation/devicetree/bindings/input/rmi4/rmi_i2c.txt53
-rw-r--r--Documentation/devicetree/bindings/vendor-prefixes.txt1
-rw-r--r--drivers/input/rmi4/rmi_bus.c35
-rw-r--r--drivers/input/rmi4/rmi_bus.h4
-rw-r--r--drivers/input/rmi4/rmi_driver.c28
-rw-r--r--drivers/input/rmi4/rmi_f01.c50
-rw-r--r--drivers/input/rmi4/rmi_i2c.c12
8 files changed, 217 insertions, 5 deletions
diff --git a/Documentation/devicetree/bindings/input/rmi4/rmi_f01.txt b/Documentation/devicetree/bindings/input/rmi4/rmi_f01.txt
new file mode 100644
index 000000000000..079cad2b6843
--- /dev/null
+++ b/Documentation/devicetree/bindings/input/rmi4/rmi_f01.txt
@@ -0,0 +1,39 @@
1Synaptics RMI4 F01 Device Binding
2
3The Synaptics RMI4 core is able to support RMI4 devices using different
4transports and different functions. This file describes the device tree
5bindings for devices which contain Function 1. Complete documentation
6for transports and other functions can be found in:
7Documentation/devicetree/bindings/input/rmi4.
8
9Additional documentation for F01 can be found at:
10http://www.synaptics.com/sites/default/files/511-000136-01-Rev-E-RMI4-Interfacing-Guide.pdf
11
12Optional Properties:
13- syna,nosleep-mode: If set the device will run at full power without sleeping.
14 nosleep has 3 modes, 0 will not change the default
15 setting, 1 will disable nosleep (allow sleeping),
16 and 2 will enable nosleep (disabling sleep).
17- syna,wakeup-threshold: Defines the amplitude of the disturbance to the
18 background capacitance that will cause the
19 device to wake from dozing.
20- syna,doze-holdoff-ms: The delay to wait after the last finger lift and the
21 first doze cycle.
22- syna,doze-interval-ms: The time period that the device sleeps between finger
23 activity.
24
25
26Example of a RMI4 I2C device with F01:
27 Example:
28 &i2c1 {
29 rmi4-i2c-dev@2c {
30 compatible = "syna,rmi4-i2c";
31
32 ...
33
34 rmi4-f01@1 {
35 reg = <0x1>;
36 syna,nosleep-mode = <1>;
37 };
38 };
39 };
diff --git a/Documentation/devicetree/bindings/input/rmi4/rmi_i2c.txt b/Documentation/devicetree/bindings/input/rmi4/rmi_i2c.txt
new file mode 100644
index 000000000000..95fa715c6046
--- /dev/null
+++ b/Documentation/devicetree/bindings/input/rmi4/rmi_i2c.txt
@@ -0,0 +1,53 @@
1Synaptics RMI4 I2C Device Binding
2
3The Synaptics RMI4 core is able to support RMI4 devices using different
4transports and different functions. This file describes the device tree
5bindings for devices using the I2C transport driver. Complete documentation
6for other transports and functions can be found in
7Documentation/devicetree/bindings/input/rmi4.
8
9Required Properties:
10- compatible: syna,rmi4-i2c
11- reg: I2C address
12- #address-cells: Set to 1 to indicate that the function child nodes
13 consist of only on uint32 value.
14- #size-cells: Set to 0 to indicate that the function child nodes do not
15 have a size property.
16
17Optional Properties:
18- interrupts: interrupt which the rmi device is connected to.
19- interrupt-parent: The interrupt controller.
20See Documentation/devicetree/bindings/interrupt-controller/interrupts.txt
21
22- syna,reset-delay-ms: The number of milliseconds to wait after resetting the
23 device.
24
25Function Parameters:
26Parameters specific to RMI functions are contained in child nodes of the rmi device
27 node. Documentation for the parameters of each function can be found in:
28Documentation/devicetree/bindings/input/rmi4/rmi_f*.txt.
29
30
31
32Example:
33 &i2c1 {
34 rmi4-i2c-dev@2c {
35 compatible = "syna,rmi4-i2c";
36 reg = <0x2c>;
37 #address-cells = <1>;
38 #size-cells = <0>;
39 interrupt-parent = <&gpio>;
40 interrupts = <4 2>;
41
42 rmi4-f01@1 {
43 reg = <0x1>;
44 syna,nosleep-mode = <1>;
45 };
46
47 rmi4-f11@11 {
48 reg = <0x11>;
49 touchscreen-inverted-y;
50 syna,sensor-type = <2>;
51 };
52 };
53 };
diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt
index 55df1d444e9f..7a1bf68a70fa 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.txt
+++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
@@ -220,6 +220,7 @@ sprd Spreadtrum Communications Inc.
220st STMicroelectronics 220st STMicroelectronics
221ste ST-Ericsson 221ste ST-Ericsson
222stericsson ST-Ericsson 222stericsson ST-Ericsson
223syna Synaptics Inc.
223synology Synology, Inc. 224synology Synology, Inc.
224tbs TBS Technologies 225tbs TBS Technologies
225tcl Toby Churchill Ltd. 226tcl Toby Churchill Ltd.
diff --git a/drivers/input/rmi4/rmi_bus.c b/drivers/input/rmi4/rmi_bus.c
index 0a2bd5a0f2b7..434477ea0c4e 100644
--- a/drivers/input/rmi4/rmi_bus.c
+++ b/drivers/input/rmi4/rmi_bus.c
@@ -153,6 +153,21 @@ static int rmi_function_match(struct device *dev, struct device_driver *drv)
153 return fn->fd.function_number == handler->func; 153 return fn->fd.function_number == handler->func;
154} 154}
155 155
156#ifdef CONFIG_OF
157static void rmi_function_of_probe(struct rmi_function *fn)
158{
159 char of_name[9];
160
161 snprintf(of_name, sizeof(of_name), "rmi4-f%02x",
162 fn->fd.function_number);
163 fn->dev.of_node = of_find_node_by_name(
164 fn->rmi_dev->xport->dev->of_node, of_name);
165}
166#else
167static inline void rmi_function_of_probe(struct rmi_function *fn)
168{}
169#endif
170
156static int rmi_function_probe(struct device *dev) 171static int rmi_function_probe(struct device *dev)
157{ 172{
158 struct rmi_function *fn = to_rmi_function(dev); 173 struct rmi_function *fn = to_rmi_function(dev);
@@ -160,6 +175,8 @@ static int rmi_function_probe(struct device *dev)
160 to_rmi_function_handler(dev->driver); 175 to_rmi_function_handler(dev->driver);
161 int error; 176 int error;
162 177
178 rmi_function_of_probe(fn);
179
163 if (handler->probe) { 180 if (handler->probe) {
164 error = handler->probe(fn); 181 error = handler->probe(fn);
165 return error; 182 return error;
@@ -325,6 +342,24 @@ err_unregister_function_handlers:
325 return ret; 342 return ret;
326} 343}
327 344
345int rmi_of_property_read_u32(struct device *dev, u32 *result,
346 const char *prop, bool optional)
347{
348 int retval;
349 u32 val = 0;
350
351 retval = of_property_read_u32(dev->of_node, prop, &val);
352 if (retval && (!optional && retval == -EINVAL)) {
353 dev_err(dev, "Failed to get %s value: %d\n",
354 prop, retval);
355 return retval;
356 }
357 *result = val;
358
359 return 0;
360}
361EXPORT_SYMBOL_GPL(rmi_of_property_read_u32);
362
328static int __init rmi_bus_init(void) 363static int __init rmi_bus_init(void)
329{ 364{
330 int error; 365 int error;
diff --git a/drivers/input/rmi4/rmi_bus.h b/drivers/input/rmi4/rmi_bus.h
index 13b148d44b37..899579830536 100644
--- a/drivers/input/rmi4/rmi_bus.h
+++ b/drivers/input/rmi4/rmi_bus.h
@@ -172,10 +172,6 @@ extern struct bus_type rmi_bus_type;
172 172
173int rmi_of_property_read_u32(struct device *dev, u32 *result, 173int rmi_of_property_read_u32(struct device *dev, u32 *result,
174 const char *prop, bool optional); 174 const char *prop, bool optional);
175int rmi_of_property_read_u16(struct device *dev, u16 *result,
176 const char *prop, bool optional);
177int rmi_of_property_read_u8(struct device *dev, u8 *result,
178 const char *prop, bool optional);
179 175
180#define RMI_DEBUG_CORE BIT(0) 176#define RMI_DEBUG_CORE BIT(0)
181#define RMI_DEBUG_XPORT BIT(1) 177#define RMI_DEBUG_XPORT BIT(1)
diff --git a/drivers/input/rmi4/rmi_driver.c b/drivers/input/rmi4/rmi_driver.c
index b0f34b57a126..da38f0ad80ed 100644
--- a/drivers/input/rmi4/rmi_driver.c
+++ b/drivers/input/rmi4/rmi_driver.c
@@ -20,6 +20,7 @@
20#include <linux/kconfig.h> 20#include <linux/kconfig.h>
21#include <linux/pm.h> 21#include <linux/pm.h>
22#include <linux/slab.h> 22#include <linux/slab.h>
23#include <linux/of.h>
23#include <uapi/linux/input.h> 24#include <uapi/linux/input.h>
24#include <linux/rmi.h> 25#include <linux/rmi.h>
25#include "rmi_bus.h" 26#include "rmi_bus.h"
@@ -821,6 +822,27 @@ static int rmi_driver_remove(struct device *dev)
821 return 0; 822 return 0;
822} 823}
823 824
825#ifdef CONFIG_OF
826static int rmi_driver_of_probe(struct device *dev,
827 struct rmi_device_platform_data *pdata)
828{
829 int retval;
830
831 retval = rmi_of_property_read_u32(dev, &pdata->reset_delay_ms,
832 "syna,reset-delay-ms", 1);
833 if (retval)
834 return retval;
835
836 return 0;
837}
838#else
839static inline int rmi_driver_of_probe(struct device *dev,
840 struct rmi_device_platform_data *pdata)
841{
842 return -ENODEV;
843}
844#endif
845
824static int rmi_driver_probe(struct device *dev) 846static int rmi_driver_probe(struct device *dev)
825{ 847{
826 struct rmi_driver *rmi_driver; 848 struct rmi_driver *rmi_driver;
@@ -846,6 +868,12 @@ static int rmi_driver_probe(struct device *dev)
846 868
847 pdata = rmi_get_platform_data(rmi_dev); 869 pdata = rmi_get_platform_data(rmi_dev);
848 870
871 if (rmi_dev->xport->dev->of_node) {
872 retval = rmi_driver_of_probe(rmi_dev->xport->dev, pdata);
873 if (retval)
874 return retval;
875 }
876
849 data = devm_kzalloc(dev, sizeof(struct rmi_driver_data), GFP_KERNEL); 877 data = devm_kzalloc(dev, sizeof(struct rmi_driver_data), GFP_KERNEL);
850 if (!data) 878 if (!data)
851 return -ENOMEM; 879 return -ENOMEM;
diff --git a/drivers/input/rmi4/rmi_f01.c b/drivers/input/rmi4/rmi_f01.c
index e50ecc6699e7..eb362bc71a4c 100644
--- a/drivers/input/rmi4/rmi_f01.c
+++ b/drivers/input/rmi4/rmi_f01.c
@@ -247,6 +247,50 @@ char *rmi_f01_get_product_ID(struct rmi_function *fn)
247 return f01->properties.product_id; 247 return f01->properties.product_id;
248} 248}
249 249
250#ifdef CONFIG_OF
251static int rmi_f01_of_probe(struct device *dev,
252 struct rmi_device_platform_data *pdata)
253{
254 int retval;
255 u32 val;
256
257 retval = rmi_of_property_read_u32(dev,
258 (u32 *)&pdata->power_management.nosleep,
259 "syna,nosleep-mode", 1);
260 if (retval)
261 return retval;
262
263 retval = rmi_of_property_read_u32(dev, &val,
264 "syna,wakeup-threshold", 1);
265 if (retval)
266 return retval;
267
268 pdata->power_management.wakeup_threshold = val;
269
270 retval = rmi_of_property_read_u32(dev, &val,
271 "syna,doze-holdoff-ms", 1);
272 if (retval)
273 return retval;
274
275 pdata->power_management.doze_holdoff = val * 100;
276
277 retval = rmi_of_property_read_u32(dev, &val,
278 "syna,doze-interval-ms", 1);
279 if (retval)
280 return retval;
281
282 pdata->power_management.doze_interval = val / 10;
283
284 return 0;
285}
286#else
287static inline int rmi_f01_of_probe(struct device *dev,
288 struct rmi_device_platform_data *pdata)
289{
290 return -ENODEV;
291}
292#endif
293
250static int rmi_f01_probe(struct rmi_function *fn) 294static int rmi_f01_probe(struct rmi_function *fn)
251{ 295{
252 struct rmi_device *rmi_dev = fn->rmi_dev; 296 struct rmi_device *rmi_dev = fn->rmi_dev;
@@ -258,6 +302,12 @@ static int rmi_f01_probe(struct rmi_function *fn)
258 u8 device_status; 302 u8 device_status;
259 u8 temp; 303 u8 temp;
260 304
305 if (fn->dev.of_node) {
306 error = rmi_f01_of_probe(&fn->dev, pdata);
307 if (error)
308 return error;
309 }
310
261 f01 = devm_kzalloc(&fn->dev, sizeof(struct f01_data), GFP_KERNEL); 311 f01 = devm_kzalloc(&fn->dev, sizeof(struct f01_data), GFP_KERNEL);
262 if (!f01) 312 if (!f01)
263 return -ENOMEM; 313 return -ENOMEM;
diff --git a/drivers/input/rmi4/rmi_i2c.c b/drivers/input/rmi4/rmi_i2c.c
index f93742b6537e..a96a326b53bd 100644
--- a/drivers/input/rmi4/rmi_i2c.c
+++ b/drivers/input/rmi4/rmi_i2c.c
@@ -10,6 +10,7 @@
10#include <linux/i2c.h> 10#include <linux/i2c.h>
11#include <linux/rmi.h> 11#include <linux/rmi.h>
12#include <linux/irq.h> 12#include <linux/irq.h>
13#include <linux/of.h>
13#include "rmi_driver.h" 14#include "rmi_driver.h"
14 15
15#define BUFFER_SIZE_INCREMENT 32 16#define BUFFER_SIZE_INCREMENT 32
@@ -207,6 +208,14 @@ static int rmi_i2c_init_irq(struct i2c_client *client)
207 return 0; 208 return 0;
208} 209}
209 210
211#ifdef CONFIG_OF
212static const struct of_device_id rmi_i2c_of_match[] = {
213 { .compatible = "syna,rmi4-i2c" },
214 {},
215};
216MODULE_DEVICE_TABLE(of, rmi_i2c_of_match);
217#endif
218
210static int rmi_i2c_probe(struct i2c_client *client, 219static int rmi_i2c_probe(struct i2c_client *client,
211 const struct i2c_device_id *id) 220 const struct i2c_device_id *id)
212{ 221{
@@ -223,7 +232,7 @@ static int rmi_i2c_probe(struct i2c_client *client,
223 232
224 pdata = &rmi_i2c->xport.pdata; 233 pdata = &rmi_i2c->xport.pdata;
225 234
226 if (client_pdata) 235 if (!client->dev.of_node && client_pdata)
227 *pdata = *client_pdata; 236 *pdata = *client_pdata;
228 237
229 if (client->irq > 0) 238 if (client->irq > 0)
@@ -372,6 +381,7 @@ static struct i2c_driver rmi_i2c_driver = {
372 .driver = { 381 .driver = {
373 .name = "rmi4_i2c", 382 .name = "rmi4_i2c",
374 .pm = &rmi_i2c_pm, 383 .pm = &rmi_i2c_pm,
384 .of_match_table = of_match_ptr(rmi_i2c_of_match),
375 }, 385 },
376 .id_table = rmi_id, 386 .id_table = rmi_id,
377 .probe = rmi_i2c_probe, 387 .probe = rmi_i2c_probe,