5
votes

I have an i2c device (touch controller). Usually I would add it to the .dts file like this when it is connected to the SoC i2c master (a tegra chip in my case):

    i2c@7000c000 {
            st1332: touchscreen@55 {
                    compatible = "sitronix,st1232";
                    reg = <0x55>;
                    interrupt-parent = <&gpio>;
                    interrupts = <189 IRQ_TYPE_EDGE_FALLING>;
            };       
    };

With the i2c controler i2c@7000c000 being defined in the SoC's .dtsi file:

    i2c1: i2c@7000c000 {
            #address-cells = <1>;
            #size-cells = <0>;
            compatible = "nvidia,tegra124-i2c";
            reg = <0x0 0x7000c000 0x0 0x100>;
            interrupts = <0 38 0x04>;
            scl-gpio = <&gpio 20 0>; /* gpio PC4 */
            sda-gpio = <&gpio 21 0>; /* gpio PC5 */
            nvidia,memory-clients = <14>;
            status = "okay";
            clock-frequency = <400000>;
    };

However, I don't want to connect the touch controller to one of the i2c masters from the SoC. Instead I have it connected to a cp2112 USB to i2c bridge.

The cp2112 driver works fine: I can use commands such as i2cget to access it from the command line. But how do I add it to the .dts file so that the touch controller driver will talk to it?

Because USB devices are enumerated automatically, I don't have a node in my .dts file that I can use as parent for the touch controller node. I would assume that I need to create a placeholder node in the .dts file under the usb controller (xusb@70090000 in my case), that is then associated with the enumerated USB device by the kernel, and move the touch controller into this node, but I don't know how to do that. What would such a node for a USB device look like? Or is there a completely different solution to the problem?

I am running Linux 3.10.40 with a backported version of hid-cp2112 from Linux v4.1.0-rc5.

2

2 Answers

3
votes

As the hid-cp2112 driver is probed by the USB device enumeration, it does not even try to find itself in the device tree. I have created the following patch to hid-cp2112.c that links the found cp2112 device to a /i2c@cp2112 node in the devie tree. (This of course only works for situations where there is only one cp2112 chip on the USB.)

diff --git a/drivers/hid/hid-cp2112.c b/drivers/hid/hid-cp2112.c
index 2bd7f97..fa88590 100644
--- a/drivers/hid/hid-cp2112.c
+++ b/drivers/hid/hid-cp2112.c
@@ -31,6 +31,8 @@
 #include <linux/module.h>
 #include <linux/nls.h>
 #include <linux/usb/ch9.h>
+#include <linux/of.h>
+#include <linux/of_i2c.h>
 #include "hid-ids.h"

 enum {
@@ -1014,6 +1016,7 @@ static int cp2112_probe(struct hid_device *hdev, const struct hid_device_id *id)
    dev->adap.algo      = &smbus_algorithm;
    dev->adap.algo_data = dev;
    dev->adap.dev.parent    = &hdev->dev;
+   dev->adap.dev.of_node   = of_find_node_by_path("/i2c@cp2112");
    snprintf(dev->adap.name, sizeof(dev->adap.name),
         "CP2112 SMBus Bridge on hiddev%d", hdev->minor);
    init_waitqueue_head(&dev->wait);
@@ -1029,6 +1032,8 @@ static int cp2112_probe(struct hid_device *hdev, const struct hid_device_id *id)

    hid_dbg(hdev, "adapter registered\n");

+   of_i2c_register_devices(&dev->adap);
+
    dev->gc.label           = "cp2112_gpio";
    dev->gc.direction_input     = cp2112_gpio_direction_input;
    dev->gc.direction_output    = cp2112_gpio_direction_output;

The entry in the .dts file for the touch controller looks like this:

    i2c@cp2112 {
            #address-cells = <1>;
            #size-cells = <0>;
            st1332: touchscreen@55 {
                    compatible = "sitronix,st1232";
                    reg = <0x55>;
                    interrupt-parent = <&gpio>;
                    interrupts = <189 IRQ_TYPE_EDGE_FALLING>;
            };
    };
2
votes

As a reference for those who may encounter similar problems notice that Clifford was backporting the cp2112 driver from Linux 4+ back to v3.10.40.

If you look at the kernel source for i2c busses it seems that they had to register themselves by using of_i2c_register_devices, but this need was removed from kernel v3.12 onwards. This is why the cp2112 driver does not call of_i2c_register_devices.