Commit a7a1c60b authored by George Mois's avatar George Mois Committed by Jonathan Cameron

drivers: iio: accel: adxl312 and adxl314 support

ADXL312 and ADXL314 are small, thin, low power, 3-axis accelerometers
with high resolution (13-bit) measurement up to +/-12 g and +/- 200 g
respectively.

Implement support for ADXL312 and ADXL314 by extending the ADXL313
driver.

Datasheet: https://www.analog.com/media/en/technical-documentation/data-sheets/ADXL312.pdf
Datasheet: https://www.analog.com/media/en/technical-documentation/data-sheets/ADXL314.pdfSigned-off-by: default avatarGeorge Mois <george.mois@analog.com>
Link: https://lore.kernel.org/r/20220905132018.364900-2-george.mois@analog.comSigned-off-by: default avatarJonathan Cameron <Jonathan.Cameron@huawei.com>
parent abf90541
...@@ -8,6 +8,8 @@ ...@@ -8,6 +8,8 @@
#ifndef _ADXL313_H_ #ifndef _ADXL313_H_
#define _ADXL313_H_ #define _ADXL313_H_
#include <linux/iio/iio.h>
/* ADXL313 register definitions */ /* ADXL313 register definitions */
#define ADXL313_REG_DEVID0 0x00 #define ADXL313_REG_DEVID0 0x00
#define ADXL313_REG_DEVID1 0x01 #define ADXL313_REG_DEVID1 0x01
...@@ -26,6 +28,7 @@ ...@@ -26,6 +28,7 @@
#define ADXL313_REG_FIFO_STATUS 0x39 #define ADXL313_REG_FIFO_STATUS 0x39
#define ADXL313_DEVID0 0xAD #define ADXL313_DEVID0 0xAD
#define ADXL313_DEVID0_ADXL312_314 0xE5
#define ADXL313_DEVID1 0x1D #define ADXL313_DEVID1 0x1D
#define ADXL313_PARTID 0xCB #define ADXL313_PARTID 0xCB
#define ADXL313_SOFT_RESET 0x52 #define ADXL313_SOFT_RESET 0x52
...@@ -37,18 +40,46 @@ ...@@ -37,18 +40,46 @@
#define ADXL313_MEASUREMENT_MODE BIT(3) #define ADXL313_MEASUREMENT_MODE BIT(3)
#define ADXL313_RANGE_MSK GENMASK(1, 0) #define ADXL313_RANGE_MSK GENMASK(1, 0)
#define ADXL313_RANGE_4G 3 #define ADXL313_RANGE_MAX 3
#define ADXL313_FULL_RES BIT(3) #define ADXL313_FULL_RES BIT(3)
#define ADXL313_SPI_3WIRE BIT(6) #define ADXL313_SPI_3WIRE BIT(6)
#define ADXL313_I2C_DISABLE BIT(6) #define ADXL313_I2C_DISABLE BIT(6)
extern const struct regmap_access_table adxl312_readable_regs_table;
extern const struct regmap_access_table adxl313_readable_regs_table; extern const struct regmap_access_table adxl313_readable_regs_table;
extern const struct regmap_access_table adxl314_readable_regs_table;
extern const struct regmap_access_table adxl312_writable_regs_table;
extern const struct regmap_access_table adxl313_writable_regs_table; extern const struct regmap_access_table adxl313_writable_regs_table;
extern const struct regmap_access_table adxl314_writable_regs_table;
enum adxl313_device_type {
ADXL312,
ADXL313,
ADXL314,
};
struct adxl313_data {
struct regmap *regmap;
const struct adxl313_chip_info *chip_info;
struct mutex lock; /* lock to protect transf_buf */
__le16 transf_buf __aligned(IIO_DMA_MINALIGN);
};
struct adxl313_chip_info {
const char *name;
enum adxl313_device_type type;
int scale_factor;
bool variable_range;
bool soft_reset;
int (*check_id)(struct device *dev, struct adxl313_data *data);
};
extern const struct adxl313_chip_info adxl31x_chip_info[];
int adxl313_core_probe(struct device *dev, int adxl313_core_probe(struct device *dev,
struct regmap *regmap, struct regmap *regmap,
const char *name, const struct adxl313_chip_info *chip_info,
int (*setup)(struct device *, struct regmap *)); int (*setup)(struct device *, struct regmap *));
#endif /* _ADXL313_H_ */ #endif /* _ADXL313_H_ */
...@@ -8,12 +8,18 @@ ...@@ -8,12 +8,18 @@
*/ */
#include <linux/bitfield.h> #include <linux/bitfield.h>
#include <linux/iio/iio.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/regmap.h> #include <linux/regmap.h>
#include "adxl313.h" #include "adxl313.h"
static const struct regmap_range adxl312_readable_reg_range[] = {
regmap_reg_range(ADXL313_REG_DEVID0, ADXL313_REG_DEVID0),
regmap_reg_range(ADXL313_REG_OFS_AXIS(0), ADXL313_REG_OFS_AXIS(2)),
regmap_reg_range(ADXL313_REG_THRESH_ACT, ADXL313_REG_ACT_INACT_CTL),
regmap_reg_range(ADXL313_REG_BW_RATE, ADXL313_REG_FIFO_STATUS),
};
static const struct regmap_range adxl313_readable_reg_range[] = { static const struct regmap_range adxl313_readable_reg_range[] = {
regmap_reg_range(ADXL313_REG_DEVID0, ADXL313_REG_XID), regmap_reg_range(ADXL313_REG_DEVID0, ADXL313_REG_XID),
regmap_reg_range(ADXL313_REG_SOFT_RESET, ADXL313_REG_SOFT_RESET), regmap_reg_range(ADXL313_REG_SOFT_RESET, ADXL313_REG_SOFT_RESET),
...@@ -22,12 +28,109 @@ static const struct regmap_range adxl313_readable_reg_range[] = { ...@@ -22,12 +28,109 @@ static const struct regmap_range adxl313_readable_reg_range[] = {
regmap_reg_range(ADXL313_REG_BW_RATE, ADXL313_REG_FIFO_STATUS), regmap_reg_range(ADXL313_REG_BW_RATE, ADXL313_REG_FIFO_STATUS),
}; };
const struct regmap_access_table adxl312_readable_regs_table = {
.yes_ranges = adxl312_readable_reg_range,
.n_yes_ranges = ARRAY_SIZE(adxl312_readable_reg_range),
};
EXPORT_SYMBOL_NS_GPL(adxl312_readable_regs_table, IIO_ADXL313);
const struct regmap_access_table adxl313_readable_regs_table = { const struct regmap_access_table adxl313_readable_regs_table = {
.yes_ranges = adxl313_readable_reg_range, .yes_ranges = adxl313_readable_reg_range,
.n_yes_ranges = ARRAY_SIZE(adxl313_readable_reg_range), .n_yes_ranges = ARRAY_SIZE(adxl313_readable_reg_range),
}; };
EXPORT_SYMBOL_NS_GPL(adxl313_readable_regs_table, IIO_ADXL313); EXPORT_SYMBOL_NS_GPL(adxl313_readable_regs_table, IIO_ADXL313);
const struct regmap_access_table adxl314_readable_regs_table = {
.yes_ranges = adxl312_readable_reg_range,
.n_yes_ranges = ARRAY_SIZE(adxl312_readable_reg_range),
};
EXPORT_SYMBOL_NS_GPL(adxl314_readable_regs_table, IIO_ADXL313);
static int adxl312_check_id(struct device *dev,
struct adxl313_data *data)
{
unsigned int regval;
int ret;
ret = regmap_read(data->regmap, ADXL313_REG_DEVID0, &regval);
if (ret)
return ret;
if (regval != ADXL313_DEVID0_ADXL312_314)
dev_warn(dev, "Invalid manufacturer ID: %#02x\n", regval);
return 0;
}
static int adxl313_check_id(struct device *dev,
struct adxl313_data *data)
{
unsigned int regval;
int ret;
ret = regmap_read(data->regmap, ADXL313_REG_DEVID0, &regval);
if (ret)
return ret;
if (regval != ADXL313_DEVID0)
dev_warn(dev, "Invalid manufacturer ID: 0x%02x\n", regval);
/* Check DEVID1 and PARTID */
if (regval == ADXL313_DEVID0) {
ret = regmap_read(data->regmap, ADXL313_REG_DEVID1, &regval);
if (ret)
return ret;
if (regval != ADXL313_DEVID1)
dev_warn(dev, "Invalid mems ID: 0x%02x\n", regval);
ret = regmap_read(data->regmap, ADXL313_REG_PARTID, &regval);
if (ret)
return ret;
if (regval != ADXL313_PARTID)
dev_warn(dev, "Invalid device ID: 0x%02x\n", regval);
}
return 0;
}
const struct adxl313_chip_info adxl31x_chip_info[] = {
[ADXL312] = {
.name = "adxl312",
.type = ADXL312,
.scale_factor = 28425072,
.variable_range = true,
.soft_reset = false,
.check_id = &adxl312_check_id,
},
[ADXL313] = {
.name = "adxl313",
.type = ADXL313,
.scale_factor = 9576806,
.variable_range = true,
.soft_reset = true,
.check_id = &adxl313_check_id,
},
[ADXL314] = {
.name = "adxl314",
.type = ADXL314,
.scale_factor = 478858719,
.variable_range = false,
.soft_reset = false,
.check_id = &adxl312_check_id,
},
};
EXPORT_SYMBOL_NS_GPL(adxl31x_chip_info, IIO_ADXL313);
static const struct regmap_range adxl312_writable_reg_range[] = {
regmap_reg_range(ADXL313_REG_OFS_AXIS(0), ADXL313_REG_OFS_AXIS(2)),
regmap_reg_range(ADXL313_REG_THRESH_ACT, ADXL313_REG_ACT_INACT_CTL),
regmap_reg_range(ADXL313_REG_BW_RATE, ADXL313_REG_INT_MAP),
regmap_reg_range(ADXL313_REG_DATA_FORMAT, ADXL313_REG_DATA_FORMAT),
regmap_reg_range(ADXL313_REG_FIFO_CTL, ADXL313_REG_FIFO_CTL),
};
static const struct regmap_range adxl313_writable_reg_range[] = { static const struct regmap_range adxl313_writable_reg_range[] = {
regmap_reg_range(ADXL313_REG_SOFT_RESET, ADXL313_REG_SOFT_RESET), regmap_reg_range(ADXL313_REG_SOFT_RESET, ADXL313_REG_SOFT_RESET),
regmap_reg_range(ADXL313_REG_OFS_AXIS(0), ADXL313_REG_OFS_AXIS(2)), regmap_reg_range(ADXL313_REG_OFS_AXIS(0), ADXL313_REG_OFS_AXIS(2)),
...@@ -37,17 +140,23 @@ static const struct regmap_range adxl313_writable_reg_range[] = { ...@@ -37,17 +140,23 @@ static const struct regmap_range adxl313_writable_reg_range[] = {
regmap_reg_range(ADXL313_REG_FIFO_CTL, ADXL313_REG_FIFO_CTL), regmap_reg_range(ADXL313_REG_FIFO_CTL, ADXL313_REG_FIFO_CTL),
}; };
const struct regmap_access_table adxl312_writable_regs_table = {
.yes_ranges = adxl312_writable_reg_range,
.n_yes_ranges = ARRAY_SIZE(adxl312_writable_reg_range),
};
EXPORT_SYMBOL_NS_GPL(adxl312_writable_regs_table, IIO_ADXL313);
const struct regmap_access_table adxl313_writable_regs_table = { const struct regmap_access_table adxl313_writable_regs_table = {
.yes_ranges = adxl313_writable_reg_range, .yes_ranges = adxl313_writable_reg_range,
.n_yes_ranges = ARRAY_SIZE(adxl313_writable_reg_range), .n_yes_ranges = ARRAY_SIZE(adxl313_writable_reg_range),
}; };
EXPORT_SYMBOL_NS_GPL(adxl313_writable_regs_table, IIO_ADXL313); EXPORT_SYMBOL_NS_GPL(adxl313_writable_regs_table, IIO_ADXL313);
struct adxl313_data { const struct regmap_access_table adxl314_writable_regs_table = {
struct regmap *regmap; .yes_ranges = adxl312_writable_reg_range,
struct mutex lock; /* lock to protect transf_buf */ .n_yes_ranges = ARRAY_SIZE(adxl312_writable_reg_range),
__le16 transf_buf __aligned(IIO_DMA_MINALIGN);
}; };
EXPORT_SYMBOL_NS_GPL(adxl314_writable_regs_table, IIO_ADXL313);
static const int adxl313_odr_freqs[][2] = { static const int adxl313_odr_freqs[][2] = {
[0] = { 6, 250000 }, [0] = { 6, 250000 },
...@@ -156,12 +265,10 @@ static int adxl313_read_raw(struct iio_dev *indio_dev, ...@@ -156,12 +265,10 @@ static int adxl313_read_raw(struct iio_dev *indio_dev,
*val = sign_extend32(ret, chan->scan_type.realbits - 1); *val = sign_extend32(ret, chan->scan_type.realbits - 1);
return IIO_VAL_INT; return IIO_VAL_INT;
case IIO_CHAN_INFO_SCALE: case IIO_CHAN_INFO_SCALE:
/*
* Scale for any g range is given in datasheet as
* 1024 LSB/g = 0.0009765625 * 9.80665 = 0.009576806640625 m/s^2
*/
*val = 0; *val = 0;
*val2 = 9576806;
*val2 = data->chip_info->scale_factor;
return IIO_VAL_INT_PLUS_NANO; return IIO_VAL_INT_PLUS_NANO;
case IIO_CHAN_INFO_CALIBBIAS: case IIO_CHAN_INFO_CALIBBIAS:
ret = regmap_read(data->regmap, ret = regmap_read(data->regmap,
...@@ -170,7 +277,7 @@ static int adxl313_read_raw(struct iio_dev *indio_dev, ...@@ -170,7 +277,7 @@ static int adxl313_read_raw(struct iio_dev *indio_dev,
return ret; return ret;
/* /*
* 8-bit resolution at +/- 0.5g, that is 4x accel data scale * 8-bit resolution at minimum range, that is 4x accel data scale
* factor at full resolution * factor at full resolution
*/ */
*val = sign_extend32(regval, 7) * 4; *val = sign_extend32(regval, 7) * 4;
...@@ -198,7 +305,7 @@ static int adxl313_write_raw(struct iio_dev *indio_dev, ...@@ -198,7 +305,7 @@ static int adxl313_write_raw(struct iio_dev *indio_dev,
switch (mask) { switch (mask) {
case IIO_CHAN_INFO_CALIBBIAS: case IIO_CHAN_INFO_CALIBBIAS:
/* /*
* 8-bit resolution at +/- 0.5g, that is 4x accel data scale * 8-bit resolution at minimum range, that is 4x accel data scale
* factor at full resolution * factor at full resolution
*/ */
if (clamp_val(val, -128 * 4, 127 * 4) != val) if (clamp_val(val, -128 * 4, 127 * 4) != val)
...@@ -223,14 +330,18 @@ static const struct iio_info adxl313_info = { ...@@ -223,14 +330,18 @@ static const struct iio_info adxl313_info = {
static int adxl313_setup(struct device *dev, struct adxl313_data *data, static int adxl313_setup(struct device *dev, struct adxl313_data *data,
int (*setup)(struct device *, struct regmap *)) int (*setup)(struct device *, struct regmap *))
{ {
unsigned int regval;
int ret; int ret;
/* Ensures the device is in a consistent state after start up */ /*
ret = regmap_write(data->regmap, ADXL313_REG_SOFT_RESET, * If sw reset available, ensures the device is in a consistent
ADXL313_SOFT_RESET); * state after start up
if (ret) */
return ret; if (data->chip_info->soft_reset) {
ret = regmap_write(data->regmap, ADXL313_REG_SOFT_RESET,
ADXL313_SOFT_RESET);
if (ret)
return ret;
}
if (setup) { if (setup) {
ret = setup(dev, data->regmap); ret = setup(dev, data->regmap);
...@@ -238,46 +349,25 @@ static int adxl313_setup(struct device *dev, struct adxl313_data *data, ...@@ -238,46 +349,25 @@ static int adxl313_setup(struct device *dev, struct adxl313_data *data,
return ret; return ret;
} }
ret = regmap_read(data->regmap, ADXL313_REG_DEVID0, &regval); ret = data->chip_info->check_id(dev, data);
if (ret) if (ret)
return ret; return ret;
if (regval != ADXL313_DEVID0) { /* Sets the range to maximum, full resolution, if applicable */
dev_err(dev, "Invalid manufacturer ID: 0x%02x\n", regval); if (data->chip_info->variable_range) {
return -ENODEV; ret = regmap_update_bits(data->regmap, ADXL313_REG_DATA_FORMAT,
} ADXL313_RANGE_MSK,
FIELD_PREP(ADXL313_RANGE_MSK, ADXL313_RANGE_MAX));
ret = regmap_read(data->regmap, ADXL313_REG_DEVID1, &regval); if (ret)
if (ret) return ret;
return ret;
if (regval != ADXL313_DEVID1) {
dev_err(dev, "Invalid mems ID: 0x%02x\n", regval);
return -ENODEV;
}
ret = regmap_read(data->regmap, ADXL313_REG_PARTID, &regval);
if (ret)
return ret;
if (regval != ADXL313_PARTID) { /* Enables full resolution */
dev_err(dev, "Invalid device ID: 0x%02x\n", regval); ret = regmap_update_bits(data->regmap, ADXL313_REG_DATA_FORMAT,
return -ENODEV; ADXL313_FULL_RES, ADXL313_FULL_RES);
if (ret)
return ret;
} }
/* Sets the range to +/- 4g */
ret = regmap_update_bits(data->regmap, ADXL313_REG_DATA_FORMAT,
ADXL313_RANGE_MSK,
FIELD_PREP(ADXL313_RANGE_MSK, ADXL313_RANGE_4G));
if (ret)
return ret;
/* Enables full resolution */
ret = regmap_update_bits(data->regmap, ADXL313_REG_DATA_FORMAT,
ADXL313_FULL_RES, ADXL313_FULL_RES);
if (ret)
return ret;
/* Enables measurement mode */ /* Enables measurement mode */
return regmap_update_bits(data->regmap, ADXL313_REG_POWER_CTL, return regmap_update_bits(data->regmap, ADXL313_REG_POWER_CTL,
ADXL313_POWER_CTL_MSK, ADXL313_POWER_CTL_MSK,
...@@ -288,7 +378,7 @@ static int adxl313_setup(struct device *dev, struct adxl313_data *data, ...@@ -288,7 +378,7 @@ static int adxl313_setup(struct device *dev, struct adxl313_data *data,
* adxl313_core_probe() - probe and setup for adxl313 accelerometer * adxl313_core_probe() - probe and setup for adxl313 accelerometer
* @dev: Driver model representation of the device * @dev: Driver model representation of the device
* @regmap: Register map of the device * @regmap: Register map of the device
* @name: Device name buffer reference * @chip_info: Structure containing device specific data
* @setup: Setup routine to be executed right before the standard device * @setup: Setup routine to be executed right before the standard device
* setup, can also be set to NULL if not required * setup, can also be set to NULL if not required
* *
...@@ -296,7 +386,7 @@ static int adxl313_setup(struct device *dev, struct adxl313_data *data, ...@@ -296,7 +386,7 @@ static int adxl313_setup(struct device *dev, struct adxl313_data *data,
*/ */
int adxl313_core_probe(struct device *dev, int adxl313_core_probe(struct device *dev,
struct regmap *regmap, struct regmap *regmap,
const char *name, const struct adxl313_chip_info *chip_info,
int (*setup)(struct device *, struct regmap *)) int (*setup)(struct device *, struct regmap *))
{ {
struct adxl313_data *data; struct adxl313_data *data;
...@@ -309,9 +399,11 @@ int adxl313_core_probe(struct device *dev, ...@@ -309,9 +399,11 @@ int adxl313_core_probe(struct device *dev,
data = iio_priv(indio_dev); data = iio_priv(indio_dev);
data->regmap = regmap; data->regmap = regmap;
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 = &adxl313_info; indio_dev->info = &adxl313_info;
indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->channels = adxl313_channels; indio_dev->channels = adxl313_channels;
......
...@@ -14,42 +14,72 @@ ...@@ -14,42 +14,72 @@
#include "adxl313.h" #include "adxl313.h"
static const struct regmap_config adxl313_i2c_regmap_config = { static const struct regmap_config adxl31x_i2c_regmap_config[] = {
.reg_bits = 8, [ADXL312] = {
.val_bits = 8, .reg_bits = 8,
.rd_table = &adxl313_readable_regs_table, .val_bits = 8,
.wr_table = &adxl313_writable_regs_table, .rd_table = &adxl312_readable_regs_table,
.max_register = 0x39, .wr_table = &adxl312_writable_regs_table,
.max_register = 0x39,
},
[ADXL313] = {
.reg_bits = 8,
.val_bits = 8,
.rd_table = &adxl313_readable_regs_table,
.wr_table = &adxl313_writable_regs_table,
.max_register = 0x39,
},
[ADXL314] = {
.reg_bits = 8,
.val_bits = 8,
.rd_table = &adxl314_readable_regs_table,
.wr_table = &adxl314_writable_regs_table,
.max_register = 0x39,
},
}; };
static int adxl313_i2c_probe(struct i2c_client *client)
{
struct regmap *regmap;
regmap = devm_regmap_init_i2c(client, &adxl313_i2c_regmap_config);
if (IS_ERR(regmap)) {
dev_err(&client->dev, "Error initializing i2c regmap: %ld\n",
PTR_ERR(regmap));
return PTR_ERR(regmap);
}
return adxl313_core_probe(&client->dev, regmap, client->name, NULL);
}
static const struct i2c_device_id adxl313_i2c_id[] = { static const struct i2c_device_id adxl313_i2c_id[] = {
{ "adxl313" }, { .name = "adxl312", .driver_data = (kernel_ulong_t)&adxl31x_chip_info[ADXL312] },
{ .name = "adxl313", .driver_data = (kernel_ulong_t)&adxl31x_chip_info[ADXL312] },
{ .name = "adxl314", .driver_data = (kernel_ulong_t)&adxl31x_chip_info[ADXL312] },
{ } { }
}; };
MODULE_DEVICE_TABLE(i2c, adxl313_i2c_id); MODULE_DEVICE_TABLE(i2c, adxl313_i2c_id);
static const struct of_device_id adxl313_of_match[] = { static const struct of_device_id adxl313_of_match[] = {
{ .compatible = "adi,adxl313" }, { .compatible = "adi,adxl312", .data = &adxl31x_chip_info[ADXL312] },
{ .compatible = "adi,adxl313", .data = &adxl31x_chip_info[ADXL313] },
{ .compatible = "adi,adxl314", .data = &adxl31x_chip_info[ADXL314] },
{ } { }
}; };
MODULE_DEVICE_TABLE(of, adxl313_of_match); MODULE_DEVICE_TABLE(of, adxl313_of_match);
static int adxl313_i2c_probe(struct i2c_client *client)
{
const struct adxl313_chip_info *chip_data;
struct regmap *regmap;
/*
* Retrieves device specific data as a pointer to a
* adxl313_chip_info structure
*/
chip_data = device_get_match_data(&client->dev);
if (!chip_data)
chip_data = (const struct adxl313_chip_info *)i2c_match_id(adxl313_i2c_id, client)->driver_data;
regmap = devm_regmap_init_i2c(client,
&adxl31x_i2c_regmap_config[chip_data->type]);
if (IS_ERR(regmap)) {
dev_err(&client->dev, "Error initializing i2c regmap: %ld\n",
PTR_ERR(regmap));
return PTR_ERR(regmap);
}
return adxl313_core_probe(&client->dev, regmap, chip_data, NULL);
}
static struct i2c_driver adxl313_i2c_driver = { static struct i2c_driver adxl313_i2c_driver = {
.driver = { .driver = {
.name = "adxl313_i2c", .name = "adxl313_i2c",
......
...@@ -11,17 +11,38 @@ ...@@ -11,17 +11,38 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/regmap.h> #include <linux/regmap.h>
#include <linux/spi/spi.h> #include <linux/spi/spi.h>
#include <linux/property.h>
#include "adxl313.h" #include "adxl313.h"
static const struct regmap_config adxl313_spi_regmap_config = { static const struct regmap_config adxl31x_spi_regmap_config[] = {
.reg_bits = 8, [ADXL312] = {
.val_bits = 8, .reg_bits = 8,
.rd_table = &adxl313_readable_regs_table, .val_bits = 8,
.wr_table = &adxl313_writable_regs_table, .rd_table = &adxl312_readable_regs_table,
.max_register = 0x39, .wr_table = &adxl312_writable_regs_table,
/* Setting bits 7 and 6 enables multiple-byte read */ .max_register = 0x39,
.read_flag_mask = BIT(7) | BIT(6), /* Setting bits 7 and 6 enables multiple-byte read */
.read_flag_mask = BIT(7) | BIT(6),
},
[ADXL313] = {
.reg_bits = 8,
.val_bits = 8,
.rd_table = &adxl313_readable_regs_table,
.wr_table = &adxl313_writable_regs_table,
.max_register = 0x39,
/* Setting bits 7 and 6 enables multiple-byte read */
.read_flag_mask = BIT(7) | BIT(6),
},
[ADXL314] = {
.reg_bits = 8,
.val_bits = 8,
.rd_table = &adxl314_readable_regs_table,
.wr_table = &adxl314_writable_regs_table,
.max_register = 0x39,
/* Setting bits 7 and 6 enables multiple-byte read */
.read_flag_mask = BIT(7) | BIT(6),
},
}; };
static int adxl313_spi_setup(struct device *dev, struct regmap *regmap) static int adxl313_spi_setup(struct device *dev, struct regmap *regmap)
...@@ -42,7 +63,7 @@ static int adxl313_spi_setup(struct device *dev, struct regmap *regmap) ...@@ -42,7 +63,7 @@ static int adxl313_spi_setup(struct device *dev, struct regmap *regmap)
static int adxl313_spi_probe(struct spi_device *spi) static int adxl313_spi_probe(struct spi_device *spi)
{ {
const struct spi_device_id *id = spi_get_device_id(spi); const struct adxl313_chip_info *chip_data;
struct regmap *regmap; struct regmap *regmap;
int ret; int ret;
...@@ -51,26 +72,40 @@ static int adxl313_spi_probe(struct spi_device *spi) ...@@ -51,26 +72,40 @@ static int adxl313_spi_probe(struct spi_device *spi)
if (ret) if (ret)
return ret; return ret;
regmap = devm_regmap_init_spi(spi, &adxl313_spi_regmap_config); /*
* Retrieves device specific data as a pointer to a
* adxl313_chip_info structure
*/
chip_data = device_get_match_data(&spi->dev);
if (!chip_data)
chip_data = (const struct adxl313_chip_info *)spi_get_device_id(spi)->driver_data;
regmap = devm_regmap_init_spi(spi,
&adxl31x_spi_regmap_config[chip_data->type]);
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",
PTR_ERR(regmap)); PTR_ERR(regmap));
return PTR_ERR(regmap); return PTR_ERR(regmap);
} }
return adxl313_core_probe(&spi->dev, regmap, id->name, return adxl313_core_probe(&spi->dev, regmap,
&adxl313_spi_setup); chip_data, &adxl313_spi_setup);
} }
static const struct spi_device_id adxl313_spi_id[] = { static const struct spi_device_id adxl313_spi_id[] = {
{ "adxl313" }, { .name = "adxl312", .driver_data = (kernel_ulong_t)&adxl31x_chip_info[ADXL312] },
{ .name = "adxl313", .driver_data = (kernel_ulong_t)&adxl31x_chip_info[ADXL313] },
{ .name = "adxl314", .driver_data = (kernel_ulong_t)&adxl31x_chip_info[ADXL314] },
{ } { }
}; };
MODULE_DEVICE_TABLE(spi, adxl313_spi_id); MODULE_DEVICE_TABLE(spi, adxl313_spi_id);
static const struct of_device_id adxl313_of_match[] = { static const struct of_device_id adxl313_of_match[] = {
{ .compatible = "adi,adxl313" }, { .compatible = "adi,adxl312", .data = &adxl31x_chip_info[ADXL312] },
{ .compatible = "adi,adxl313", .data = &adxl31x_chip_info[ADXL313] },
{ .compatible = "adi,adxl314", .data = &adxl31x_chip_info[ADXL314] },
{ } { }
}; };
......
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