OSDN Git Service

drivers: iio: accel: Add support for ADXL359 device
authorRamona Bolboaca <ramona.bolboaca@analog.com>
Mon, 31 Oct 2022 10:51:29 +0000 (12:51 +0200)
committerJonathan Cameron <Jonathan.Cameron@huawei.com>
Wed, 23 Nov 2022 19:44:04 +0000 (19:44 +0000)
Add support for ADXL359 device in already existing ADXL355 driver.

Datasheet: https://www.analog.com/media/en/technical-documentation/data-sheets/adxl359.pdf
Signed-off-by: Ramona Bolboaca <ramona.bolboaca@analog.com>
Link: https://lore.kernel.org/r/20221031105129.47740-4-ramona.bolboaca@analog.com
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
drivers/iio/accel/adxl355.h
drivers/iio/accel/adxl355_core.c
drivers/iio/accel/adxl355_i2c.c
drivers/iio/accel/adxl355_spi.c

index 6dd49b1..061e66d 100644 (file)
 
 #include <linux/regmap.h>
 
+enum adxl355_device_type {
+       ADXL355,
+       ADXL359,
+};
+
+struct adxl355_fractional_type {
+       int integer;
+       int decimal;
+};
+
 struct device;
 
+struct adxl355_chip_info {
+       const char                      *name;
+       u8                              part_id;
+       struct adxl355_fractional_type  accel_scale;
+       struct adxl355_fractional_type  temp_offset;
+};
+
 extern const struct regmap_access_table adxl355_readable_regs_tbl;
 extern const struct regmap_access_table adxl355_writeable_regs_tbl;
+extern const struct adxl355_chip_info adxl35x_chip_info[];
 
 int adxl355_core_probe(struct device *dev, struct regmap *regmap,
-                      const char *name);
+                      const struct adxl355_chip_info *chip_info);
 
 #endif /* _ADXL355_H_ */
index dd08253..0c9225d 100644 (file)
@@ -60,6 +60,7 @@
 #define ADXL355_DEVID_AD_VAL           0xAD
 #define ADXL355_DEVID_MST_VAL          0x1D
 #define ADXL355_PARTID_VAL             0xED
+#define ADXL359_PARTID_VAL             0xE9
 #define ADXL355_RESET_CODE             0x52
 
 static const struct regmap_range adxl355_read_reg_range[] = {
@@ -83,6 +84,60 @@ const struct regmap_access_table adxl355_writeable_regs_tbl = {
 };
 EXPORT_SYMBOL_NS_GPL(adxl355_writeable_regs_tbl, IIO_ADXL355);
 
+const struct adxl355_chip_info adxl35x_chip_info[] = {
+       [ADXL355] = {
+               .name = "adxl355",
+               .part_id = ADXL355_PARTID_VAL,
+               /*
+                * At +/- 2g with 20-bit resolution, scale is given in datasheet
+                * as 3.9ug/LSB = 0.0000039 * 9.80665 = 0.00003824593 m/s^2.
+                */
+               .accel_scale = {
+                       .integer = 0,
+                       .decimal = 38245,
+               },
+               /*
+                * The datasheet defines an intercept of 1885 LSB at 25 degC
+                * and a slope of -9.05 LSB/C. The following formula can be used
+                * to find the temperature:
+                * Temp = ((RAW - 1885)/(-9.05)) + 25 but this doesn't follow
+                * the format of the IIO which is Temp = (RAW + OFFSET) * SCALE.
+                * Hence using some rearranging we get the scale as -110.497238
+                * and offset as -2111.25.
+                */
+               .temp_offset = {
+                       .integer =  -2111,
+                       .decimal = 250000,
+               },
+       },
+       [ADXL359] = {
+               .name = "adxl359",
+               .part_id = ADXL359_PARTID_VAL,
+               /*
+                * At +/- 10g with 20-bit resolution, scale is given in datasheet
+                * as 19.5ug/LSB = 0.0000195 * 9.80665 = 0.0.00019122967 m/s^2.
+                */
+               .accel_scale = {
+                       .integer = 0,
+                       .decimal = 191229,
+               },
+               /*
+                * The datasheet defines an intercept of 1852 LSB at 25 degC
+                * and a slope of -9.05 LSB/C. The following formula can be used
+                * to find the temperature:
+                * Temp = ((RAW - 1852)/(-9.05)) + 25 but this doesn't follow
+                * the format of the IIO which is Temp = (RAW + OFFSET) * SCALE.
+                * Hence using some rearranging we get the scale as -110.497238
+                * and offset as -2079.25.
+                */
+               .temp_offset = {
+                       .integer = -2079,
+                       .decimal = 250000,
+               },
+       },
+};
+EXPORT_SYMBOL_NS_GPL(adxl35x_chip_info, IIO_ADXL355);
+
 enum adxl355_op_mode {
        ADXL355_MEASUREMENT,
        ADXL355_STANDBY,
@@ -162,6 +217,7 @@ static const struct adxl355_chan_info adxl355_chans[] = {
 };
 
 struct adxl355_data {
+       const struct adxl355_chip_info *chip_info;
        struct regmap *regmap;
        struct device *dev;
        struct mutex lock; /* lock to protect op_mode */
@@ -456,33 +512,25 @@ static int adxl355_read_raw(struct iio_dev *indio_dev,
 
        case IIO_CHAN_INFO_SCALE:
                switch (chan->type) {
-               /*
-                * The datasheet defines an intercept of 1885 LSB at 25 degC
-                * and a slope of -9.05 LSB/C. The following formula can be used
-                * to find the temperature:
-                * Temp = ((RAW - 1885)/(-9.05)) + 25 but this doesn't follow
-                * the format of the IIO which is Temp = (RAW + OFFSET) * SCALE.
-                * Hence using some rearranging we get the scale as -110.497238
-                * and offset as -2111.25.
-                */
                case IIO_TEMP:
+                       /*
+                        * Temperature scale is -110.497238.
+                        * See the detailed explanation in adxl35x_chip_info
+                        * definition above.
+                        */
                        *val = -110;
                        *val2 = 497238;
                        return IIO_VAL_INT_PLUS_MICRO;
-               /*
-                * At +/- 2g with 20-bit resolution, scale is given in datasheet
-                * as 3.9ug/LSB = 0.0000039 * 9.80665 = 0.00003824593 m/s^2.
-                */
                case IIO_ACCEL:
-                       *val = 0;
-                       *val2 = 38245;
+                       *val = data->chip_info->accel_scale.integer;
+                       *val2 = data->chip_info->accel_scale.decimal;
                        return IIO_VAL_INT_PLUS_NANO;
                default:
                        return -EINVAL;
                }
        case IIO_CHAN_INFO_OFFSET:
-               *val = -2111;
-               *val2 = 250000;
+               *val = data->chip_info->temp_offset.integer;
+               *val2 = data->chip_info->temp_offset.decimal;
                return IIO_VAL_INT_PLUS_MICRO;
        case IIO_CHAN_INFO_CALIBBIAS:
                *val = sign_extend32(data->calibbias[chan->address], 15);
@@ -705,7 +753,7 @@ static int adxl355_probe_trigger(struct iio_dev *indio_dev, int irq)
 }
 
 int adxl355_core_probe(struct device *dev, struct regmap *regmap,
-                      const char *name)
+                      const struct adxl355_chip_info *chip_info)
 {
        struct adxl355_data *data;
        struct iio_dev *indio_dev;
@@ -720,9 +768,10 @@ int adxl355_core_probe(struct device *dev, struct regmap *regmap,
        data->regmap = regmap;
        data->dev = dev;
        data->op_mode = ADXL355_STANDBY;
+       data->chip_info = chip_info;
        mutex_init(&data->lock);
 
-       indio_dev->name = name;
+       indio_dev->name = chip_info->name;
        indio_dev->info = &adxl355_info;
        indio_dev->modes = INDIO_DIRECT_MODE;
        indio_dev->channels = adxl355_channels;
index f67d579..6cde5cc 100644 (file)
@@ -23,6 +23,20 @@ static const struct regmap_config adxl355_i2c_regmap_config = {
 static int adxl355_i2c_probe(struct i2c_client *client)
 {
        struct regmap *regmap;
+       const struct adxl355_chip_info *chip_data;
+       const struct i2c_device_id *adxl355;
+
+       chip_data = device_get_match_data(&client->dev);
+       if (!chip_data) {
+               adxl355 = to_i2c_driver(client->dev.driver)->id_table;
+               if (!adxl355)
+                       return -EINVAL;
+
+               chip_data = (void *)i2c_match_id(adxl355, client)->driver_data;
+
+               if (!chip_data)
+                       return -EINVAL;
+       }
 
        regmap = devm_regmap_init_i2c(client, &adxl355_i2c_regmap_config);
        if (IS_ERR(regmap)) {
@@ -32,17 +46,19 @@ static int adxl355_i2c_probe(struct i2c_client *client)
                return PTR_ERR(regmap);
        }
 
-       return adxl355_core_probe(&client->dev, regmap, client->name);
+       return adxl355_core_probe(&client->dev, regmap, chip_data);
 }
 
 static const struct i2c_device_id adxl355_i2c_id[] = {
-       { "adxl355", 0 },
+       { "adxl355", (kernel_ulong_t)&adxl35x_chip_info[ADXL355] },
+       { "adxl359", (kernel_ulong_t)&adxl35x_chip_info[ADXL359] },
        { }
 };
 MODULE_DEVICE_TABLE(i2c, adxl355_i2c_id);
 
 static const struct of_device_id adxl355_of_match[] = {
-       { .compatible = "adi,adxl355" },
+       { .compatible = "adi,adxl355", .data = &adxl35x_chip_info[ADXL355] },
+       { .compatible = "adi,adxl359", .data = &adxl35x_chip_info[ADXL359] },
        { }
 };
 MODULE_DEVICE_TABLE(of, adxl355_of_match);
index 5fe986a..fc99534 100644 (file)
@@ -9,6 +9,7 @@
 #include <linux/mod_devicetable.h>
 #include <linux/regmap.h>
 #include <linux/spi/spi.h>
+#include <linux/property.h>
 
 #include "adxl355.h"
 
@@ -24,9 +25,17 @@ static const struct regmap_config adxl355_spi_regmap_config = {
 
 static int adxl355_spi_probe(struct spi_device *spi)
 {
-       const struct spi_device_id *id = spi_get_device_id(spi);
+       const struct adxl355_chip_info *chip_data;
        struct regmap *regmap;
 
+       chip_data = device_get_match_data(&spi->dev);
+       if (!chip_data) {
+               chip_data = (void *)spi_get_device_id(spi)->driver_data;
+
+               if (!chip_data)
+                       return -EINVAL;
+       }
+
        regmap = devm_regmap_init_spi(spi, &adxl355_spi_regmap_config);
        if (IS_ERR(regmap)) {
                dev_err(&spi->dev, "Error initializing spi regmap: %ld\n",
@@ -35,17 +44,19 @@ static int adxl355_spi_probe(struct spi_device *spi)
                return PTR_ERR(regmap);
        }
 
-       return adxl355_core_probe(&spi->dev, regmap, id->name);
+       return adxl355_core_probe(&spi->dev, regmap, chip_data);
 }
 
 static const struct spi_device_id adxl355_spi_id[] = {
-       { "adxl355", 0 },
+       { "adxl355", (kernel_ulong_t)&adxl35x_chip_info[ADXL355] },
+       { "adxl359", (kernel_ulong_t)&adxl35x_chip_info[ADXL359] },
        { }
 };
 MODULE_DEVICE_TABLE(spi, adxl355_spi_id);
 
 static const struct of_device_id adxl355_of_match[] = {
-       { .compatible = "adi,adxl355" },
+       { .compatible = "adi,adxl355", .data = &adxl35x_chip_info[ADXL355] },
+       { .compatible = "adi,adxl359", .data = &adxl35x_chip_info[ADXL359] },
        { }
 };
 MODULE_DEVICE_TABLE(of, adxl355_of_match);