Commit d3532d69 authored by Ramona Bolboaca's avatar Ramona Bolboaca Committed by Jonathan Cameron

drivers: iio: accel: Add support for ADXL359 device

Add support for ADXL359 device in already existing ADXL355 driver.

Datasheet: https://www.analog.com/media/en/technical-documentation/data-sheets/adxl359.pdfSigned-off-by: default avatarRamona Bolboaca <ramona.bolboaca@analog.com>
Link: https://lore.kernel.org/r/20221031105129.47740-4-ramona.bolboaca@analog.comSigned-off-by: default avatarJonathan Cameron <Jonathan.Cameron@huawei.com>
parent b311d2e1
...@@ -10,12 +10,30 @@ ...@@ -10,12 +10,30 @@
#include <linux/regmap.h> #include <linux/regmap.h>
enum adxl355_device_type {
ADXL355,
ADXL359,
};
struct adxl355_fractional_type {
int integer;
int decimal;
};
struct device; 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_readable_regs_tbl;
extern const struct regmap_access_table adxl355_writeable_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, int adxl355_core_probe(struct device *dev, struct regmap *regmap,
const char *name); const struct adxl355_chip_info *chip_info);
#endif /* _ADXL355_H_ */ #endif /* _ADXL355_H_ */
...@@ -60,6 +60,7 @@ ...@@ -60,6 +60,7 @@
#define ADXL355_DEVID_AD_VAL 0xAD #define ADXL355_DEVID_AD_VAL 0xAD
#define ADXL355_DEVID_MST_VAL 0x1D #define ADXL355_DEVID_MST_VAL 0x1D
#define ADXL355_PARTID_VAL 0xED #define ADXL355_PARTID_VAL 0xED
#define ADXL359_PARTID_VAL 0xE9
#define ADXL355_RESET_CODE 0x52 #define ADXL355_RESET_CODE 0x52
static const struct regmap_range adxl355_read_reg_range[] = { static const struct regmap_range adxl355_read_reg_range[] = {
...@@ -83,6 +84,60 @@ const struct regmap_access_table adxl355_writeable_regs_tbl = { ...@@ -83,6 +84,60 @@ const struct regmap_access_table adxl355_writeable_regs_tbl = {
}; };
EXPORT_SYMBOL_NS_GPL(adxl355_writeable_regs_tbl, IIO_ADXL355); 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 { enum adxl355_op_mode {
ADXL355_MEASUREMENT, ADXL355_MEASUREMENT,
ADXL355_STANDBY, ADXL355_STANDBY,
...@@ -162,6 +217,7 @@ static const struct adxl355_chan_info adxl355_chans[] = { ...@@ -162,6 +217,7 @@ static const struct adxl355_chan_info adxl355_chans[] = {
}; };
struct adxl355_data { struct adxl355_data {
const struct adxl355_chip_info *chip_info;
struct regmap *regmap; struct regmap *regmap;
struct device *dev; struct device *dev;
struct mutex lock; /* lock to protect op_mode */ struct mutex lock; /* lock to protect op_mode */
...@@ -456,33 +512,25 @@ static int adxl355_read_raw(struct iio_dev *indio_dev, ...@@ -456,33 +512,25 @@ static int adxl355_read_raw(struct iio_dev *indio_dev,
case IIO_CHAN_INFO_SCALE: case IIO_CHAN_INFO_SCALE:
switch (chan->type) { 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: case IIO_TEMP:
/*
* Temperature scale is -110.497238.
* See the detailed explanation in adxl35x_chip_info
* definition above.
*/
*val = -110; *val = -110;
*val2 = 497238; *val2 = 497238;
return IIO_VAL_INT_PLUS_MICRO; 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: case IIO_ACCEL:
*val = 0; *val = data->chip_info->accel_scale.integer;
*val2 = 38245; *val2 = data->chip_info->accel_scale.decimal;
return IIO_VAL_INT_PLUS_NANO; return IIO_VAL_INT_PLUS_NANO;
default: default:
return -EINVAL; return -EINVAL;
} }
case IIO_CHAN_INFO_OFFSET: case IIO_CHAN_INFO_OFFSET:
*val = -2111; *val = data->chip_info->temp_offset.integer;
*val2 = 250000; *val2 = data->chip_info->temp_offset.decimal;
return IIO_VAL_INT_PLUS_MICRO; return IIO_VAL_INT_PLUS_MICRO;
case IIO_CHAN_INFO_CALIBBIAS: case IIO_CHAN_INFO_CALIBBIAS:
*val = sign_extend32(data->calibbias[chan->address], 15); *val = sign_extend32(data->calibbias[chan->address], 15);
...@@ -705,7 +753,7 @@ static int adxl355_probe_trigger(struct iio_dev *indio_dev, int irq) ...@@ -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, 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 adxl355_data *data;
struct iio_dev *indio_dev; struct iio_dev *indio_dev;
...@@ -720,9 +768,10 @@ int adxl355_core_probe(struct device *dev, struct regmap *regmap, ...@@ -720,9 +768,10 @@ int adxl355_core_probe(struct device *dev, struct regmap *regmap,
data->regmap = regmap; data->regmap = regmap;
data->dev = dev; data->dev = dev;
data->op_mode = ADXL355_STANDBY; data->op_mode = ADXL355_STANDBY;
data->chip_info = chip_info;
mutex_init(&data->lock); mutex_init(&data->lock);
indio_dev->name = name; indio_dev->name = chip_info->name;
indio_dev->info = &adxl355_info; indio_dev->info = &adxl355_info;
indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->channels = adxl355_channels; indio_dev->channels = adxl355_channels;
......
...@@ -23,6 +23,20 @@ static const struct regmap_config adxl355_i2c_regmap_config = { ...@@ -23,6 +23,20 @@ static const struct regmap_config adxl355_i2c_regmap_config = {
static int adxl355_i2c_probe(struct i2c_client *client) static int adxl355_i2c_probe(struct i2c_client *client)
{ {
struct regmap *regmap; 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); regmap = devm_regmap_init_i2c(client, &adxl355_i2c_regmap_config);
if (IS_ERR(regmap)) { if (IS_ERR(regmap)) {
...@@ -32,17 +46,19 @@ static int adxl355_i2c_probe(struct i2c_client *client) ...@@ -32,17 +46,19 @@ static int adxl355_i2c_probe(struct i2c_client *client)
return PTR_ERR(regmap); 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[] = { 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); MODULE_DEVICE_TABLE(i2c, adxl355_i2c_id);
static const struct of_device_id adxl355_of_match[] = { 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); MODULE_DEVICE_TABLE(of, adxl355_of_match);
......
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#include <linux/mod_devicetable.h> #include <linux/mod_devicetable.h>
#include <linux/regmap.h> #include <linux/regmap.h>
#include <linux/spi/spi.h> #include <linux/spi/spi.h>
#include <linux/property.h>
#include "adxl355.h" #include "adxl355.h"
...@@ -24,9 +25,17 @@ static const struct regmap_config adxl355_spi_regmap_config = { ...@@ -24,9 +25,17 @@ static const struct regmap_config adxl355_spi_regmap_config = {
static int adxl355_spi_probe(struct spi_device *spi) 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; 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); regmap = devm_regmap_init_spi(spi, &adxl355_spi_regmap_config);
if (IS_ERR(regmap)) { if (IS_ERR(regmap)) {
dev_err(&spi->dev, "Error initializing spi regmap: %ld\n", dev_err(&spi->dev, "Error initializing spi regmap: %ld\n",
...@@ -35,17 +44,19 @@ static int adxl355_spi_probe(struct spi_device *spi) ...@@ -35,17 +44,19 @@ static int adxl355_spi_probe(struct spi_device *spi)
return PTR_ERR(regmap); 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[] = { 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); MODULE_DEVICE_TABLE(spi, adxl355_spi_id);
static const struct of_device_id adxl355_of_match[] = { 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); MODULE_DEVICE_TABLE(of, adxl355_of_match);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment