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.pdf Signed-off-by: George Mois <george.mois@analog.com> Link: https://lore.kernel.org/r/20220905132018.364900-2-george.mois@analog.com Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
This commit is contained in:
Родитель
abf90541d1
Коммит
a7a1c60bc4
|
@ -8,6 +8,8 @@
|
|||
#ifndef _ADXL313_H_
|
||||
#define _ADXL313_H_
|
||||
|
||||
#include <linux/iio/iio.h>
|
||||
|
||||
/* ADXL313 register definitions */
|
||||
#define ADXL313_REG_DEVID0 0x00
|
||||
#define ADXL313_REG_DEVID1 0x01
|
||||
|
@ -26,6 +28,7 @@
|
|||
#define ADXL313_REG_FIFO_STATUS 0x39
|
||||
|
||||
#define ADXL313_DEVID0 0xAD
|
||||
#define ADXL313_DEVID0_ADXL312_314 0xE5
|
||||
#define ADXL313_DEVID1 0x1D
|
||||
#define ADXL313_PARTID 0xCB
|
||||
#define ADXL313_SOFT_RESET 0x52
|
||||
|
@ -37,18 +40,46 @@
|
|||
#define ADXL313_MEASUREMENT_MODE BIT(3)
|
||||
|
||||
#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_SPI_3WIRE 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 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 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,
|
||||
struct regmap *regmap,
|
||||
const char *name,
|
||||
const struct adxl313_chip_info *chip_info,
|
||||
int (*setup)(struct device *, struct regmap *));
|
||||
#endif /* _ADXL313_H_ */
|
||||
|
|
|
@ -8,12 +8,18 @@
|
|||
*/
|
||||
|
||||
#include <linux/bitfield.h>
|
||||
#include <linux/iio/iio.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/regmap.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[] = {
|
||||
regmap_reg_range(ADXL313_REG_DEVID0, ADXL313_REG_XID),
|
||||
regmap_reg_range(ADXL313_REG_SOFT_RESET, ADXL313_REG_SOFT_RESET),
|
||||
|
@ -22,12 +28,109 @@ static const struct regmap_range adxl313_readable_reg_range[] = {
|
|||
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 = {
|
||||
.yes_ranges = adxl313_readable_reg_range,
|
||||
.n_yes_ranges = ARRAY_SIZE(adxl313_readable_reg_range),
|
||||
};
|
||||
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, ®val);
|
||||
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, ®val);
|
||||
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, ®val);
|
||||
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, ®val);
|
||||
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[] = {
|
||||
regmap_reg_range(ADXL313_REG_SOFT_RESET, ADXL313_REG_SOFT_RESET),
|
||||
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[] = {
|
|||
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 = {
|
||||
.yes_ranges = adxl313_writable_reg_range,
|
||||
.n_yes_ranges = ARRAY_SIZE(adxl313_writable_reg_range),
|
||||
};
|
||||
EXPORT_SYMBOL_NS_GPL(adxl313_writable_regs_table, IIO_ADXL313);
|
||||
|
||||
struct adxl313_data {
|
||||
struct regmap *regmap;
|
||||
struct mutex lock; /* lock to protect transf_buf */
|
||||
__le16 transf_buf __aligned(IIO_DMA_MINALIGN);
|
||||
const struct regmap_access_table adxl314_writable_regs_table = {
|
||||
.yes_ranges = adxl312_writable_reg_range,
|
||||
.n_yes_ranges = ARRAY_SIZE(adxl312_writable_reg_range),
|
||||
};
|
||||
EXPORT_SYMBOL_NS_GPL(adxl314_writable_regs_table, IIO_ADXL313);
|
||||
|
||||
static const int adxl313_odr_freqs[][2] = {
|
||||
[0] = { 6, 250000 },
|
||||
|
@ -156,12 +265,10 @@ static int adxl313_read_raw(struct iio_dev *indio_dev,
|
|||
*val = sign_extend32(ret, chan->scan_type.realbits - 1);
|
||||
return IIO_VAL_INT;
|
||||
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;
|
||||
*val2 = 9576806;
|
||||
|
||||
*val2 = data->chip_info->scale_factor;
|
||||
|
||||
return IIO_VAL_INT_PLUS_NANO;
|
||||
case IIO_CHAN_INFO_CALIBBIAS:
|
||||
ret = regmap_read(data->regmap,
|
||||
|
@ -170,7 +277,7 @@ static int adxl313_read_raw(struct iio_dev *indio_dev,
|
|||
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
|
||||
*/
|
||||
*val = sign_extend32(regval, 7) * 4;
|
||||
|
@ -198,7 +305,7 @@ static int adxl313_write_raw(struct iio_dev *indio_dev,
|
|||
switch (mask) {
|
||||
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
|
||||
*/
|
||||
if (clamp_val(val, -128 * 4, 127 * 4) != val)
|
||||
|
@ -223,14 +330,18 @@ static const struct iio_info adxl313_info = {
|
|||
static int adxl313_setup(struct device *dev, struct adxl313_data *data,
|
||||
int (*setup)(struct device *, struct regmap *))
|
||||
{
|
||||
unsigned int regval;
|
||||
int ret;
|
||||
|
||||
/* Ensures the device is in a consistent state after start up */
|
||||
ret = regmap_write(data->regmap, ADXL313_REG_SOFT_RESET,
|
||||
ADXL313_SOFT_RESET);
|
||||
if (ret)
|
||||
return ret;
|
||||
/*
|
||||
* If sw reset available, ensures the device is in a consistent
|
||||
* state after start up
|
||||
*/
|
||||
if (data->chip_info->soft_reset) {
|
||||
ret = regmap_write(data->regmap, ADXL313_REG_SOFT_RESET,
|
||||
ADXL313_SOFT_RESET);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (setup) {
|
||||
ret = setup(dev, data->regmap);
|
||||
|
@ -238,46 +349,25 @@ static int adxl313_setup(struct device *dev, struct adxl313_data *data,
|
|||
return ret;
|
||||
}
|
||||
|
||||
ret = regmap_read(data->regmap, ADXL313_REG_DEVID0, ®val);
|
||||
ret = data->chip_info->check_id(dev, data);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (regval != ADXL313_DEVID0) {
|
||||
dev_err(dev, "Invalid manufacturer ID: 0x%02x\n", regval);
|
||||
return -ENODEV;
|
||||
/* Sets the range to maximum, full resolution, if applicable */
|
||||
if (data->chip_info->variable_range) {
|
||||
ret = regmap_update_bits(data->regmap, ADXL313_REG_DATA_FORMAT,
|
||||
ADXL313_RANGE_MSK,
|
||||
FIELD_PREP(ADXL313_RANGE_MSK, ADXL313_RANGE_MAX));
|
||||
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;
|
||||
}
|
||||
|
||||
ret = regmap_read(data->regmap, ADXL313_REG_DEVID1, ®val);
|
||||
if (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, ®val);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (regval != ADXL313_PARTID) {
|
||||
dev_err(dev, "Invalid device ID: 0x%02x\n", regval);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
/* 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 */
|
||||
return regmap_update_bits(data->regmap, ADXL313_REG_POWER_CTL,
|
||||
ADXL313_POWER_CTL_MSK,
|
||||
|
@ -288,7 +378,7 @@ static int adxl313_setup(struct device *dev, struct adxl313_data *data,
|
|||
* adxl313_core_probe() - probe and setup for adxl313 accelerometer
|
||||
* @dev: Driver model representation 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, can also be set to NULL if not required
|
||||
*
|
||||
|
@ -296,7 +386,7 @@ static int adxl313_setup(struct device *dev, struct adxl313_data *data,
|
|||
*/
|
||||
int adxl313_core_probe(struct device *dev,
|
||||
struct regmap *regmap,
|
||||
const char *name,
|
||||
const struct adxl313_chip_info *chip_info,
|
||||
int (*setup)(struct device *, struct regmap *))
|
||||
{
|
||||
struct adxl313_data *data;
|
||||
|
@ -309,9 +399,11 @@ int adxl313_core_probe(struct device *dev,
|
|||
|
||||
data = iio_priv(indio_dev);
|
||||
data->regmap = regmap;
|
||||
data->chip_info = chip_info;
|
||||
|
||||
mutex_init(&data->lock);
|
||||
|
||||
indio_dev->name = name;
|
||||
indio_dev->name = chip_info->name;
|
||||
indio_dev->info = &adxl313_info;
|
||||
indio_dev->modes = INDIO_DIRECT_MODE;
|
||||
indio_dev->channels = adxl313_channels;
|
||||
|
|
|
@ -14,42 +14,72 @@
|
|||
|
||||
#include "adxl313.h"
|
||||
|
||||
static const struct regmap_config adxl313_i2c_regmap_config = {
|
||||
.reg_bits = 8,
|
||||
.val_bits = 8,
|
||||
.rd_table = &adxl313_readable_regs_table,
|
||||
.wr_table = &adxl313_writable_regs_table,
|
||||
.max_register = 0x39,
|
||||
static const struct regmap_config adxl31x_i2c_regmap_config[] = {
|
||||
[ADXL312] = {
|
||||
.reg_bits = 8,
|
||||
.val_bits = 8,
|
||||
.rd_table = &adxl312_readable_regs_table,
|
||||
.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[] = {
|
||||
{ "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);
|
||||
|
||||
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);
|
||||
|
||||
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 = {
|
||||
.driver = {
|
||||
.name = "adxl313_i2c",
|
||||
|
|
|
@ -11,17 +11,38 @@
|
|||
#include <linux/module.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/spi/spi.h>
|
||||
#include <linux/property.h>
|
||||
|
||||
#include "adxl313.h"
|
||||
|
||||
static const struct regmap_config adxl313_spi_regmap_config = {
|
||||
.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),
|
||||
static const struct regmap_config adxl31x_spi_regmap_config[] = {
|
||||
[ADXL312] = {
|
||||
.reg_bits = 8,
|
||||
.val_bits = 8,
|
||||
.rd_table = &adxl312_readable_regs_table,
|
||||
.wr_table = &adxl312_writable_regs_table,
|
||||
.max_register = 0x39,
|
||||
/* 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)
|
||||
|
@ -42,7 +63,7 @@ static int adxl313_spi_setup(struct device *dev, struct regmap *regmap)
|
|||
|
||||
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;
|
||||
int ret;
|
||||
|
||||
|
@ -51,26 +72,40 @@ static int adxl313_spi_probe(struct spi_device *spi)
|
|||
if (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)) {
|
||||
dev_err(&spi->dev, "Error initializing spi regmap: %ld\n",
|
||||
PTR_ERR(regmap));
|
||||
return PTR_ERR(regmap);
|
||||
}
|
||||
|
||||
return adxl313_core_probe(&spi->dev, regmap, id->name,
|
||||
&adxl313_spi_setup);
|
||||
return adxl313_core_probe(&spi->dev, regmap,
|
||||
chip_data, &adxl313_spi_setup);
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
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] },
|
||||
{ }
|
||||
};
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче