input: misc: add DT support to Invensense MPU
Daniel Fu [Thu, 12 Sep 2013 07:27:35 +0000 (15:27 +0800)]
Add device tree support to Invensense MPU drivers.

Bug 1363572

Change-Id: I65012d8ab52b6405ce033db4307885256c16c2a6
Signed-off-by: Daniel Fu <danifu@nvidia.com>
Reviewed-on: http://git-master/r/274074
Reviewed-by: Automatic_Commit_Validation_User
GVS: Gerrit_Virtual_Submit
Reviewed-by: Robert Collins <rcollins@nvidia.com>
Reviewed-by: Nitin Kumbhar <nkumbhar@nvidia.com>

Documentation/devicetree/bindings/input/inv-mpu-sensors.txt [new file with mode: 0644]
drivers/input/misc/mpu/inv_gyro.c

diff --git a/Documentation/devicetree/bindings/input/inv-mpu-sensors.txt b/Documentation/devicetree/bindings/input/inv-mpu-sensors.txt
new file mode 100644 (file)
index 0000000..f29d202
--- /dev/null
@@ -0,0 +1,42 @@
+* Invensense MPU6xxx Gyro + Accelerometer
+* Invensense MPU9xxx Gyro + Accelerometer + Compass
+
+Required properties:
+- compatible: The driver is compatible with
+  "invensense,itg3500"
+  "invensense,mpu3050"
+  "invensense,mpu6050"
+  "invensense,mpu9150"
+  "invensense,mpu6500"
+  "invensense,mpu9250"
+  "invensense,mpu6xxx"
+- reg: the I2C address
+- interrupt-parent: the interrupt controller that it is attached to.
+- interrupts: The intterrupt property of device node.
+- invensense,int_config: Bits [7:3] of the int config register.
+- invensense,level_shifter: 0: VLogic, 1: VDD
+- invensense,orientation: the orientation matricies are 3x3 rotation matricies
+  that are applied to the data to rotate from the mounting orientation to the
+  platform orientation. The values must be one of 0, 1, or -1(0xff in byte
+  array) and each row and column should have exactly 1 non-zero value.
+- invensense,sec_slave_type: secondary slave device type
+  0: SECONDARY_SLAVE_TYPE_NONE
+  1: SECONDARY_SLAVE_TYPE_ACCEL
+  2: SECONDARY_SLAVE_TYPE_COMPASS
+  3: SECONDARY_SLAVE_TYPE_PRESSURE
+- invensense,key: key for MPL library.
+
+Example:
+
+mpu9250@69 {
+       compatible = "invensense,mpu9250";
+       reg = <0x69>;
+       interrupt-parent = <&gpio>;
+       interrupts = <144 0x01>;
+       invensense,int_config = <0x10>;
+       invensense,level_shifter = <0>;
+       invensense,orientation = [01 00 00 00 01 00 00 00 01];
+       invensense,sec_slave_type = <0>;
+       invensense,key = [4e cc 7e eb f6 1e 35 22 00 34 0d 65 32 e9 94 89];
+};
+
index 47faa6b..0d5428b 100644 (file)
@@ -4332,6 +4332,51 @@ static int nvi_remove(struct i2c_client *client)
        return 0;
 }
 
+static int of_nvi_parse_platform_data(struct i2c_client *client,
+                               struct mpu_platform_data *pdata)
+{
+       struct device_node *np = client->dev.of_node;
+       char const *pchar;
+       u32 tmp;
+       int len;
+
+       if (!pdata) {
+               dev_err(&client->dev, "Platform data hasn't been allocated\n");
+               return -EINVAL;
+       }
+
+       if (!of_property_read_u32_array(np, "invensense,int_config", &tmp, 1))
+               pdata->int_config = (u8)tmp;
+       else
+               dev_err(&client->dev, "Can't read int_config property\n");
+
+       if (!of_property_read_u32_array(np, "invensense,level_shifter",
+                                                       &tmp, 1))
+               pdata->level_shifter = (u8)tmp;
+       else
+               dev_err(&client->dev, "Can't read level_shifter property\n");
+
+       pchar = of_get_property(np, "invensense,orientation", &len);
+       if (pchar && len == sizeof(pdata->orientation))
+               memcpy(pdata->orientation, pchar, len);
+       else
+               dev_err(&client->dev, "Can't read orientation property\n");
+
+       if (!of_property_read_u32_array(np, "invensense,sec_slave_type",
+                                                       &tmp, 1))
+               pdata->sec_slave_type = (enum secondary_slave_type)tmp;
+       else
+               dev_err(&client->dev, "Can't read sec_slave_type property\n");
+
+       pchar = of_get_property(np, "invensense,key", &len);
+       if (pchar && len == sizeof(pdata->key))
+               memcpy(pdata->key, pchar, len);
+       else
+               dev_err(&client->dev, "Can't read key property\n");
+
+       return 0;
+}
+
 static int nvi_probe(struct i2c_client *client,
                     const struct i2c_device_id *id)
 {
@@ -4357,7 +4402,13 @@ static int nvi_probe(struct i2c_client *client,
        st->reg = (struct inv_reg_map_s *)&chip_reg ;
        st->hw_s = (struct inv_hw_s *)hw_info;
        st->i2c_addr = client->addr;
-       st->plat_data =
+
+       if (client->dev.of_node) {
+               result = of_nvi_parse_platform_data(client, &st->plat_data);
+               if (result)
+                       goto out_free;
+       } else
+               st->plat_data =
                   *(struct mpu_platform_data *)dev_get_platdata(&client->dev);
 
        result = nvi_dev_init(st, id);
@@ -4426,6 +4477,21 @@ static struct i2c_device_id nvi_mpu_id[] = {
 
 MODULE_DEVICE_TABLE(i2c, nvi_mpu_id);
 
+#ifdef CONFIG_OF
+static const struct of_device_id nvi_mpu_of_match[] = {
+       { .compatible = "invensense,itg3500", },
+       { .compatible = "invensense,mpu3050", },
+       { .compatible = "invensense,mpu6050", },
+       { .compatible = "invensense,mpu9150", },
+       { .compatible = "invensense,mpu6500", },
+       { .compatible = "invensense,mpu9250", },
+       { .compatible = "invensense,mpu6xxx", },
+       {}
+};
+
+MODULE_DEVICE_TABLE(of, nvi_mpu_of_match);
+#endif
+
 static struct i2c_driver inv_mod_driver = {
        .class = I2C_CLASS_HWMON,
        .probe          =       nvi_probe,
@@ -4434,6 +4500,7 @@ static struct i2c_driver inv_mod_driver = {
        .driver = {
                .owner  =       THIS_MODULE,
                .name   =       "inv_dev",
+               .of_match_table = of_match_ptr(nvi_mpu_of_match),
 #ifdef CONFIG_PM
                .pm     =       &nvi_pm_ops,
 #endif