Commit 2d7768a872b73a7105d6355948dae0acff72f061

Authored by Linus Walleij
Committed by Jonathan Cameron
1 parent 3b1cae7c2c

iio: st_sensors: add devicetree probing support

The I2C devices that make up the STMicroelectronics MEMS sensors
may be sneakily enabled by cleverly giving the device node the same
name as a string match from the platform device ID table. However
the right method is to use the compatible string.

On detection, the ST sensors use the ID string to probe and
instatiate the right sensor driver, so pass the kernel-internal ID
string in the .data field of the OF match table, and set the I2C
client name to this name when a compatible match is used.

This avoids having misc Linux-specific strings floating around in
the device tree.

Cc: Lee Jones <lee.jones@linaro.org>
Cc: Denis CIOCCA <denis.ciocca@st.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Jonathan Cameron <jic23@kernel.org>

Showing 6 changed files with 177 additions and 0 deletions Side-by-side Diff

drivers/iio/accel/st_accel_i2c.c
... ... @@ -18,6 +18,55 @@
18 18 #include <linux/iio/common/st_sensors_i2c.h>
19 19 #include "st_accel.h"
20 20  
  21 +#ifdef CONFIG_OF
  22 +static const struct of_device_id st_accel_of_match[] = {
  23 + {
  24 + .compatible = "st,lsm303dlh-accel",
  25 + .data = LSM303DLH_ACCEL_DEV_NAME,
  26 + },
  27 + {
  28 + .compatible = "st,lsm303dlhc-accel",
  29 + .data = LSM303DLHC_ACCEL_DEV_NAME,
  30 + },
  31 + {
  32 + .compatible = "st,lis3dh-accel",
  33 + .data = LIS3DH_ACCEL_DEV_NAME,
  34 + },
  35 + {
  36 + .compatible = "st,lsm330d-accel",
  37 + .data = LSM330D_ACCEL_DEV_NAME,
  38 + },
  39 + {
  40 + .compatible = "st,lsm330dl-accel",
  41 + .data = LSM330DL_ACCEL_DEV_NAME,
  42 + },
  43 + {
  44 + .compatible = "st,lsm330dlc-accel",
  45 + .data = LSM330DLC_ACCEL_DEV_NAME,
  46 + },
  47 + {
  48 + .compatible = "st,lis331dlh-accel",
  49 + .data = LIS331DLH_ACCEL_DEV_NAME,
  50 + },
  51 + {
  52 + .compatible = "st,lsm303dl-accel",
  53 + .data = LSM303DL_ACCEL_DEV_NAME,
  54 + },
  55 + {
  56 + .compatible = "st,lsm303dlm-accel",
  57 + .data = LSM303DLM_ACCEL_DEV_NAME,
  58 + },
  59 + {
  60 + .compatible = "st,lsm330-accel",
  61 + .data = LSM330_ACCEL_DEV_NAME,
  62 + },
  63 + {},
  64 +};
  65 +MODULE_DEVICE_TABLE(of, st_accel_of_match);
  66 +#else
  67 +#define st_accel_of_match NULL
  68 +#endif
  69 +
21 70 static int st_accel_i2c_probe(struct i2c_client *client,
22 71 const struct i2c_device_id *id)
23 72 {
... ... @@ -31,6 +80,7 @@
31 80  
32 81 adata = iio_priv(indio_dev);
33 82 adata->dev = &client->dev;
  83 + st_sensors_of_i2c_probe(client, st_accel_of_match);
34 84  
35 85 st_sensors_i2c_configure(indio_dev, client, adata);
36 86  
... ... @@ -67,6 +117,7 @@
67 117 .driver = {
68 118 .owner = THIS_MODULE,
69 119 .name = "st-accel-i2c",
  120 + .of_match_table = of_match_ptr(st_accel_of_match),
70 121 },
71 122 .probe = st_accel_i2c_probe,
72 123 .remove = st_accel_i2c_remove,
drivers/iio/common/st_sensors/st_sensors_i2c.c
... ... @@ -12,6 +12,7 @@
12 12 #include <linux/module.h>
13 13 #include <linux/slab.h>
14 14 #include <linux/iio/iio.h>
  15 +#include <linux/of_device.h>
15 16  
16 17 #include <linux/iio/common/st_sensors_i2c.h>
17 18  
... ... @@ -75,6 +76,35 @@
75 76 sdata->get_irq_data_ready = st_sensors_i2c_get_irq;
76 77 }
77 78 EXPORT_SYMBOL(st_sensors_i2c_configure);
  79 +
  80 +#ifdef CONFIG_OF
  81 +/**
  82 + * st_sensors_of_i2c_probe() - device tree probe for ST I2C sensors
  83 + * @client: the I2C client device for the sensor
  84 + * @match: the OF match table for the device, containing compatible strings
  85 + * but also a .data field with the corresponding internal kernel name
  86 + * used by this sensor.
  87 + *
  88 + * In effect this function matches a compatible string to an internal kernel
  89 + * name for a certain sensor device, so that the rest of the autodetection can
  90 + * rely on that name from this point on. I2C client devices will be renamed
  91 + * to match the internal kernel convention.
  92 + */
  93 +void st_sensors_of_i2c_probe(struct i2c_client *client,
  94 + const struct of_device_id *match)
  95 +{
  96 + const struct of_device_id *of_id;
  97 +
  98 + of_id = of_match_device(match, &client->dev);
  99 + if (!of_id)
  100 + return;
  101 +
  102 + /* The name from the OF match takes precedence if present */
  103 + strncpy(client->name, of_id->data, sizeof(client->name));
  104 + client->name[sizeof(client->name) - 1] = '\0';
  105 +}
  106 +EXPORT_SYMBOL(st_sensors_of_i2c_probe);
  107 +#endif
78 108  
79 109 MODULE_AUTHOR("Denis Ciocca <denis.ciocca@st.com>");
80 110 MODULE_DESCRIPTION("STMicroelectronics ST-sensors i2c driver");
drivers/iio/gyro/st_gyro_i2c.c
... ... @@ -18,6 +18,43 @@
18 18 #include <linux/iio/common/st_sensors_i2c.h>
19 19 #include "st_gyro.h"
20 20  
  21 +#ifdef CONFIG_OF
  22 +static const struct of_device_id st_gyro_of_match[] = {
  23 + {
  24 + .compatible = "st,l3g4200d-gyro",
  25 + .data = L3G4200D_GYRO_DEV_NAME,
  26 + },
  27 + {
  28 + .compatible = "st,lsm330d-gyro",
  29 + .data = LSM330D_GYRO_DEV_NAME,
  30 + },
  31 + {
  32 + .compatible = "st,lsm330dl-gyro",
  33 + .data = LSM330DL_GYRO_DEV_NAME,
  34 + },
  35 + {
  36 + .compatible = "st,lsm330dlc-gyro",
  37 + .data = LSM330DLC_GYRO_DEV_NAME,
  38 + },
  39 + {
  40 + .compatible = "st,l3gd20-gyro",
  41 + .data = L3GD20_GYRO_DEV_NAME,
  42 + },
  43 + {
  44 + .compatible = "st,l3g4is-gyro",
  45 + .data = L3G4IS_GYRO_DEV_NAME,
  46 + },
  47 + {
  48 + .compatible = "st,lsm330-gyro",
  49 + .data = LSM330_GYRO_DEV_NAME,
  50 + },
  51 + {},
  52 +};
  53 +MODULE_DEVICE_TABLE(of, st_gyro_of_match);
  54 +#else
  55 +#define st_gyro_of_match NULL
  56 +#endif
  57 +
21 58 static int st_gyro_i2c_probe(struct i2c_client *client,
22 59 const struct i2c_device_id *id)
23 60 {
... ... @@ -31,6 +68,7 @@
31 68  
32 69 gdata = iio_priv(indio_dev);
33 70 gdata->dev = &client->dev;
  71 + st_sensors_of_i2c_probe(client, st_gyro_of_match);
34 72  
35 73 st_sensors_i2c_configure(indio_dev, client, gdata);
36 74  
... ... @@ -65,6 +103,7 @@
65 103 .driver = {
66 104 .owner = THIS_MODULE,
67 105 .name = "st-gyro-i2c",
  106 + .of_match_table = of_match_ptr(st_gyro_of_match),
68 107 },
69 108 .probe = st_gyro_i2c_probe,
70 109 .remove = st_gyro_i2c_remove,
drivers/iio/magnetometer/st_magn_i2c.c
... ... @@ -18,6 +18,27 @@
18 18 #include <linux/iio/common/st_sensors_i2c.h>
19 19 #include "st_magn.h"
20 20  
  21 +#ifdef CONFIG_OF
  22 +static const struct of_device_id st_magn_of_match[] = {
  23 + {
  24 + .compatible = "st,lsm303dlhc-magn",
  25 + .data = LSM303DLHC_MAGN_DEV_NAME,
  26 + },
  27 + {
  28 + .compatible = "st,lsm303dlm-magn",
  29 + .data = LSM303DLM_MAGN_DEV_NAME,
  30 + },
  31 + {
  32 + .compatible = "st,lis3mdl-magn",
  33 + .data = LIS3MDL_MAGN_DEV_NAME,
  34 + },
  35 + {},
  36 +};
  37 +MODULE_DEVICE_TABLE(of, st_magn_of_match);
  38 +#else
  39 +#define st_magn_of_match NULL
  40 +#endif
  41 +
21 42 static int st_magn_i2c_probe(struct i2c_client *client,
22 43 const struct i2c_device_id *id)
23 44 {
... ... @@ -31,6 +52,7 @@
31 52  
32 53 mdata = iio_priv(indio_dev);
33 54 mdata->dev = &client->dev;
  55 + st_sensors_of_i2c_probe(client, st_magn_of_match);
34 56  
35 57 st_sensors_i2c_configure(indio_dev, client, mdata);
36 58  
... ... @@ -61,6 +83,7 @@
61 83 .driver = {
62 84 .owner = THIS_MODULE,
63 85 .name = "st-magn-i2c",
  86 + .of_match_table = of_match_ptr(st_magn_of_match),
64 87 },
65 88 .probe = st_magn_i2c_probe,
66 89 .remove = st_magn_i2c_remove,
drivers/iio/pressure/st_pressure_i2c.c
... ... @@ -18,6 +18,27 @@
18 18 #include <linux/iio/common/st_sensors_i2c.h>
19 19 #include "st_pressure.h"
20 20  
  21 +#ifdef CONFIG_OF
  22 +static const struct of_device_id st_press_of_match[] = {
  23 + {
  24 + .compatible = "st,lps001wp-press",
  25 + .data = LPS001WP_PRESS_DEV_NAME,
  26 + },
  27 + {
  28 + .compatible = "st,lps25h-press",
  29 + .data = LPS25H_PRESS_DEV_NAME,
  30 + },
  31 + {
  32 + .compatible = "st,lps331ap-press",
  33 + .data = LPS331AP_PRESS_DEV_NAME,
  34 + },
  35 + {},
  36 +};
  37 +MODULE_DEVICE_TABLE(of, st_press_of_match);
  38 +#else
  39 +#define st_press_of_match NULL
  40 +#endif
  41 +
21 42 static int st_press_i2c_probe(struct i2c_client *client,
22 43 const struct i2c_device_id *id)
23 44 {
... ... @@ -31,6 +52,7 @@
31 52  
32 53 pdata = iio_priv(indio_dev);
33 54 pdata->dev = &client->dev;
  55 + st_sensors_of_i2c_probe(client, st_press_of_match);
34 56  
35 57 st_sensors_i2c_configure(indio_dev, client, pdata);
36 58  
... ... @@ -60,6 +82,7 @@
60 82 .driver = {
61 83 .owner = THIS_MODULE,
62 84 .name = "st-press-i2c",
  85 + .of_match_table = of_match_ptr(st_press_of_match),
63 86 },
64 87 .probe = st_press_i2c_probe,
65 88 .remove = st_press_i2c_remove,
include/linux/iio/common/st_sensors_i2c.h
... ... @@ -13,9 +13,20 @@
13 13  
14 14 #include <linux/i2c.h>
15 15 #include <linux/iio/common/st_sensors.h>
  16 +#include <linux/of.h>
16 17  
17 18 void st_sensors_i2c_configure(struct iio_dev *indio_dev,
18 19 struct i2c_client *client, struct st_sensor_data *sdata);
  20 +
  21 +#ifdef CONFIG_OF
  22 +void st_sensors_of_i2c_probe(struct i2c_client *client,
  23 + const struct of_device_id *match);
  24 +#else
  25 +static inline void st_sensors_of_i2c_probe(struct i2c_client *client,
  26 + const struct of_device_id *match)
  27 +{
  28 +}
  29 +#endif
19 30  
20 31 #endif /* ST_SENSORS_I2C_H */