Skip to content

Commit

Permalink
HID: i2c-hid: add DT bindings
Browse files Browse the repository at this point in the history
Add device tree based support for HID over I2C devices.

Tested on an Odroid-X board with a Synaptics touchpad.

Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
  • Loading branch information
bentiss authored and Jiri Kosina committed Jul 31, 2013
1 parent 3366dd9 commit 3d7d248
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 2 deletions.
28 changes: 28 additions & 0 deletions Documentation/devicetree/bindings/hid/hid-over-i2c.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
* HID over I2C Device-Tree bindings

HID over I2C provides support for various Human Interface Devices over the
I2C bus. These devices can be for example touchpads, keyboards, touch screens
or sensors.

The specification has been written by Microsoft and is currently available here:
http://msdn.microsoft.com/en-us/library/windows/hardware/hh852380.aspx

If this binding is used, the kernel module i2c-hid will handle the communication
with the device and the generic hid core layer will handle the protocol.

Required properties:
- compatible: must be "hid-over-i2c"
- reg: i2c slave address
- hid-descr-addr: HID descriptor address
- interrupt-parent: the phandle for the interrupt controller
- interrupts: interrupt line

Example:

i2c-hid-dev@2c {
compatible = "hid-over-i2c";
reg = <0x2c>;
hid-descr-addr = <0x0020>;
interrupt-parent = <&gpx3>;
interrupts = <3 2>;
};
44 changes: 43 additions & 1 deletion drivers/hid/i2c-hid/i2c-hid.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
#include <linux/hid.h>
#include <linux/mutex.h>
#include <linux/acpi.h>
#include <linux/of.h>

#include <linux/i2c/i2c-hid.h>

Expand Down Expand Up @@ -933,6 +934,42 @@ static inline int i2c_hid_acpi_pdata(struct i2c_client *client,
}
#endif

#ifdef CONFIG_OF
static int i2c_hid_of_probe(struct i2c_client *client,
struct i2c_hid_platform_data *pdata)
{
struct device *dev = &client->dev;
u32 val;
int ret;

ret = of_property_read_u32(dev->of_node, "hid-descr-addr", &val);
if (ret) {
dev_err(&client->dev, "HID register address not provided\n");
return -ENODEV;
}
if (val >> 16) {
dev_err(&client->dev, "Bad HID register address: 0x%08x\n",
val);
return -EINVAL;
}
pdata->hid_descriptor_address = val;

return 0;
}

static const struct of_device_id i2c_hid_of_match[] = {
{ .compatible = "hid-over-i2c" },
{},
};
MODULE_DEVICE_TABLE(of, i2c_hid_of_match);
#else
static inline int i2c_hid_of_probe(struct i2c_client *client,
struct i2c_hid_platform_data *pdata)
{
return -ENODEV;
}
#endif

static int i2c_hid_probe(struct i2c_client *client,
const struct i2c_device_id *dev_id)
{
Expand All @@ -954,7 +991,11 @@ static int i2c_hid_probe(struct i2c_client *client,
if (!ihid)
return -ENOMEM;

if (!platform_data) {
if (client->dev.of_node) {
ret = i2c_hid_of_probe(client, &ihid->pdata);
if (ret)
goto err;
} else if (!platform_data) {
ret = i2c_hid_acpi_pdata(client, &ihid->pdata);
if (ret) {
dev_err(&client->dev,
Expand Down Expand Up @@ -1095,6 +1136,7 @@ static struct i2c_driver i2c_hid_driver = {
.owner = THIS_MODULE,
.pm = &i2c_hid_pm,
.acpi_match_table = ACPI_PTR(i2c_hid_acpi_match),
.of_match_table = of_match_ptr(i2c_hid_of_match),
},

.probe = i2c_hid_probe,
Expand Down
3 changes: 2 additions & 1 deletion include/linux/i2c/i2c-hid.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@
* @hid_descriptor_address: i2c register where the HID descriptor is stored.
*
* Note that it is the responsibility of the platform driver (or the acpi 5.0
* driver) to setup the irq related to the gpio in the struct i2c_board_info.
* driver, or the flattened device tree) to setup the irq related to the gpio in
* the struct i2c_board_info.
* The platform driver should also setup the gpio according to the device:
*
* A typical example is the following:
Expand Down

0 comments on commit 3d7d248

Please sign in to comment.