* [PATCH v3 1/2] bindings: iio: accel: extend adxl313 documentation file
@ 2022-08-31 14:35 George Mois
2022-08-31 14:35 ` [PATCH v3 2/2] drivers: iio: accel: adxl312 and adxl314 support George Mois
2022-09-04 15:13 ` [PATCH v3 1/2] bindings: iio: accel: extend adxl313 documentation file Jonathan Cameron
0 siblings, 2 replies; 4+ messages in thread
From: George Mois @ 2022-08-31 14:35 UTC (permalink / raw)
To: jic23, robh+dt, krzysztof.kozlowski+dt, linux-iio, devicetree,
linux-kernel
Cc: lucas.p.stankus, George Mois
Extend the adi,adxl313.yaml file with information regrding the
ADXL312 and ADXL314 devices.
Signed-off-by: George Mois <george.mois@analog.com>
Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
---
no changes in v3.
.../devicetree/bindings/iio/accel/adi,adxl313.yaml | 10 +++++++---
1 file changed, 7 insertions(+), 3 deletions(-)
diff --git a/Documentation/devicetree/bindings/iio/accel/adi,adxl313.yaml b/Documentation/devicetree/bindings/iio/accel/adi,adxl313.yaml
index d6afc1b8c272..59d48ff1a16c 100644
--- a/Documentation/devicetree/bindings/iio/accel/adi,adxl313.yaml
+++ b/Documentation/devicetree/bindings/iio/accel/adi,adxl313.yaml
@@ -4,20 +4,24 @@
$id: http://devicetree.org/schemas/iio/accel/adi,adxl313.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
-title: Analog Devices ADXL313 3-Axis Digital Accelerometer
+title: Analog Devices ADXL312, ADXL313, and ADXL314 3-Axis Digital Accelerometers
maintainers:
- Lucas Stankus <lucas.p.stankus@gmail.com>
description: |
- Analog Devices ADXL313 3-Axis Digital Accelerometer that supports
- both I2C & SPI interfaces.
+ Analog Devices ADXL312, ADXL313, and ADXL314 3-Axis Digital Accelerometer that
+ support both I2C & SPI interfaces.
+ https://www.analog.com/en/products/adxl312.html
https://www.analog.com/en/products/adxl313.html
+ https://www.analog.com/en/products/adxl314.html
properties:
compatible:
enum:
+ - adi,adxl312
- adi,adxl313
+ - adi,adxl314
reg:
maxItems: 1
--
2.30.2
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [PATCH v3 2/2] drivers: iio: accel: adxl312 and adxl314 support
2022-08-31 14:35 [PATCH v3 1/2] bindings: iio: accel: extend adxl313 documentation file George Mois
@ 2022-08-31 14:35 ` George Mois
2022-09-04 15:28 ` Jonathan Cameron
2022-09-04 15:13 ` [PATCH v3 1/2] bindings: iio: accel: extend adxl313 documentation file Jonathan Cameron
1 sibling, 1 reply; 4+ messages in thread
From: George Mois @ 2022-08-31 14:35 UTC (permalink / raw)
To: jic23, robh+dt, krzysztof.kozlowski+dt, linux-iio, devicetree,
linux-kernel
Cc: lucas.p.stankus, George Mois
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>
---
changes in v3:
- move MODULE_DEVICE_TABLE adxl313_of_match to i2c and spi drivers
- correct multiline comment style
- create separate functions for checking device ID registers
- use of spi_get_device_id() path when device_get_match_data() fails
drivers/iio/accel/adxl313.h | 25 +++-
drivers/iio/accel/adxl313_core.c | 193 ++++++++++++++++++++++++-------
drivers/iio/accel/adxl313_i2c.c | 82 +++++++++----
drivers/iio/accel/adxl313_spi.c | 71 +++++++++---
4 files changed, 288 insertions(+), 83 deletions(-)
diff --git a/drivers/iio/accel/adxl313.h b/drivers/iio/accel/adxl313.h
index 4415f2fc07e1..0feb1d44c265 100644
--- a/drivers/iio/accel/adxl313.h
+++ b/drivers/iio/accel/adxl313.h
@@ -26,6 +26,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 +38,38 @@
#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_chip_info {
+ const char *name;
+ enum adxl313_device_type type;
+ int scale_factor;
+ bool variable_range;
+ bool soft_reset;
+};
+
+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_ */
diff --git a/drivers/iio/accel/adxl313_core.c b/drivers/iio/accel/adxl313_core.c
index afeef779e1d0..9c93e71c94f1 100644
--- a/drivers/iio/accel/adxl313_core.c
+++ b/drivers/iio/accel/adxl313_core.c
@@ -14,6 +14,13 @@
#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 +29,57 @@ 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);
+
+const struct adxl313_chip_info adxl31x_chip_info[] = {
+ [ADXL312] = {
+ .name = "adxl312",
+ .type = ADXL312,
+ .scale_factor = 28425072,
+ .variable_range = true,
+ .soft_reset = false,
+ },
+ [ADXL313] = {
+ .name = "adxl313",
+ .type = ADXL313,
+ .scale_factor = 9576806,
+ .variable_range = true,
+ .soft_reset = true,
+ },
+ [ADXL314] = {
+ .name = "adxl314",
+ .type = ADXL314,
+ .scale_factor = 478858719,
+ .variable_range = false,
+ .soft_reset = false,
+ }
+};
+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,14 +89,27 @@ 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);
+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);
+
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);
};
@@ -156,12 +221,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 +233,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 +261,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)
@@ -220,64 +283,102 @@ static const struct iio_info adxl313_info = {
.read_avail = adxl313_read_freq_avail,
};
-static int adxl313_setup(struct device *dev, struct adxl313_data *data,
- int (*setup)(struct device *, struct regmap *))
+static int adxl312_adxl314_check_id(struct device *dev,
+ struct adxl313_data *data)
{
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);
+ ret = regmap_read(data->regmap, ADXL313_REG_DEVID0, ®val);
if (ret)
return ret;
- if (setup) {
- ret = setup(dev, data->regmap);
- 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_err(dev, "Invalid manufacturer ID: 0x%02x\n", regval);
- return -ENODEV;
- }
+ if (regval != ADXL313_DEVID0)
+ dev_warn(dev, "Invalid manufacturer ID: 0x%02x\n", regval);
- ret = regmap_read(data->regmap, ADXL313_REG_DEVID1, ®val);
- if (ret)
- return ret;
+ /* 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);
- 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_warn(dev, "Invalid device ID: 0x%02x\n", regval);
}
- ret = regmap_read(data->regmap, ADXL313_REG_PARTID, ®val);
- if (ret)
- return ret;
+ return 0;
+}
+
+static int adxl313_setup(struct device *dev, struct adxl313_data *data,
+ int (*setup)(struct device *, struct regmap *))
+{
+ int ret;
- if (regval != ADXL313_PARTID) {
- dev_err(dev, "Invalid device ID: 0x%02x\n", regval);
- return -ENODEV;
+ /*
+ * 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;
}
- /* 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;
+ if (setup) {
+ ret = setup(dev, data->regmap);
+ if (ret)
+ return ret;
+ }
+
+ if (data->chip_info->type == ADXL313)
+ /* ADXL313 */
+ ret = adxl313_check_id(dev, data);
+ else
+ /* ADXL312 or ADXL314 */
+ ret = adxl312_adxl314_check_id(dev, data);
- /* Enables full resolution */
- ret = regmap_update_bits(data->regmap, ADXL313_REG_DATA_FORMAT,
- ADXL313_FULL_RES, ADXL313_FULL_RES);
if (ret)
return ret;
+ /* 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;
+ }
+
/* Enables measurement mode */
return regmap_update_bits(data->regmap, ADXL313_REG_POWER_CTL,
ADXL313_POWER_CTL_MSK,
@@ -288,7 +389,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 +397,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 +410,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;
diff --git a/drivers/iio/accel/adxl313_i2c.c b/drivers/iio/accel/adxl313_i2c.c
index c329765dbf60..0665f2945a27 100644
--- a/drivers/iio/accel/adxl313_i2c.c
+++ b/drivers/iio/accel/adxl313_i2c.c
@@ -14,42 +14,80 @@
#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 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);
+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,
}
-
- return adxl313_core_probe(&client->dev, regmap, client->name, NULL);
-}
+};
static const struct i2c_device_id adxl313_i2c_id[] = {
- { "adxl313" },
+ { "adxl312", ADXL312 },
+ { "adxl313", ADXL313 },
+ { "adxl314", ADXL314 },
{ }
};
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;
+ enum adxl313_device_type chip_type;
+ struct regmap *regmap;
+
+ chip_data = device_get_match_data(&client->dev);
+ if (chip_data)
+ chip_type = chip_data->type;
+ else
+ chip_type = i2c_match_id(adxl313_i2c_id, client)->driver_data;
+
+ regmap = devm_regmap_init_i2c(client,
+ &adxl31x_i2c_regmap_config[chip_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, &adxl31x_chip_info[chip_type], NULL);
+}
+
static struct i2c_driver adxl313_i2c_driver = {
.driver = {
.name = "adxl313_i2c",
diff --git a/drivers/iio/accel/adxl313_spi.c b/drivers/iio/accel/adxl313_spi.c
index a3c6d553462d..2c3b094ef465 100644
--- a/drivers/iio/accel/adxl313_spi.c
+++ b/drivers/iio/accel/adxl313_spi.c
@@ -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,8 @@ 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;
+ enum adxl313_device_type chip_type;
struct regmap *regmap;
int ret;
@@ -51,26 +73,47 @@ static int adxl313_spi_probe(struct spi_device *spi)
if (ret)
return ret;
- regmap = devm_regmap_init_spi(spi, &adxl313_spi_regmap_config);
+ chip_data = device_get_match_data(&spi->dev);
+ if (chip_data)
+ chip_type = chip_data->type;
+ else
+ chip_type = spi_get_device_id(spi)->driver_data;
+
+ regmap = devm_regmap_init_spi(spi,
+ &adxl31x_spi_regmap_config[chip_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,
+ &adxl31x_chip_info[chip_type], &adxl313_spi_setup);
}
static const struct spi_device_id adxl313_spi_id[] = {
- { "adxl313" },
+ { "adxl312", ADXL312 },
+ { "adxl313", ADXL313 },
+ { "adxl314", 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],
+ },
{ }
};
--
2.30.2
^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: [PATCH v3 1/2] bindings: iio: accel: extend adxl313 documentation file
2022-08-31 14:35 [PATCH v3 1/2] bindings: iio: accel: extend adxl313 documentation file George Mois
2022-08-31 14:35 ` [PATCH v3 2/2] drivers: iio: accel: adxl312 and adxl314 support George Mois
@ 2022-09-04 15:13 ` Jonathan Cameron
1 sibling, 0 replies; 4+ messages in thread
From: Jonathan Cameron @ 2022-09-04 15:13 UTC (permalink / raw)
To: George Mois
Cc: robh+dt, krzysztof.kozlowski+dt, linux-iio, devicetree,
linux-kernel, lucas.p.stankus
On Wed, 31 Aug 2022 17:35:37 +0300
George Mois <george.mois@analog.com> wrote:
> Extend the adi,adxl313.yaml file with information regrding the
> ADXL312 and ADXL314 devices.
>
> Signed-off-by: George Mois <george.mois@analog.com>
> Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
Content is fine, but dt-bindings patches have a particular patch
title format. Something like:
dt-bindings: iio: accel: adxl313: Add compatibles for adxl312 and adxl314
> ---
> no changes in v3.
> .../devicetree/bindings/iio/accel/adi,adxl313.yaml | 10 +++++++---
> 1 file changed, 7 insertions(+), 3 deletions(-)
>
> diff --git a/Documentation/devicetree/bindings/iio/accel/adi,adxl313.yaml b/Documentation/devicetree/bindings/iio/accel/adi,adxl313.yaml
> index d6afc1b8c272..59d48ff1a16c 100644
> --- a/Documentation/devicetree/bindings/iio/accel/adi,adxl313.yaml
> +++ b/Documentation/devicetree/bindings/iio/accel/adi,adxl313.yaml
> @@ -4,20 +4,24 @@
> $id: http://devicetree.org/schemas/iio/accel/adi,adxl313.yaml#
> $schema: http://devicetree.org/meta-schemas/core.yaml#
>
> -title: Analog Devices ADXL313 3-Axis Digital Accelerometer
> +title: Analog Devices ADXL312, ADXL313, and ADXL314 3-Axis Digital Accelerometers
>
> maintainers:
> - Lucas Stankus <lucas.p.stankus@gmail.com>
>
> description: |
> - Analog Devices ADXL313 3-Axis Digital Accelerometer that supports
> - both I2C & SPI interfaces.
> + Analog Devices ADXL312, ADXL313, and ADXL314 3-Axis Digital Accelerometer that
> + support both I2C & SPI interfaces.
> + https://www.analog.com/en/products/adxl312.html
> https://www.analog.com/en/products/adxl313.html
> + https://www.analog.com/en/products/adxl314.html
>
> properties:
> compatible:
> enum:
> + - adi,adxl312
> - adi,adxl313
> + - adi,adxl314
>
> reg:
> maxItems: 1
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH v3 2/2] drivers: iio: accel: adxl312 and adxl314 support
2022-08-31 14:35 ` [PATCH v3 2/2] drivers: iio: accel: adxl312 and adxl314 support George Mois
@ 2022-09-04 15:28 ` Jonathan Cameron
0 siblings, 0 replies; 4+ messages in thread
From: Jonathan Cameron @ 2022-09-04 15:28 UTC (permalink / raw)
To: George Mois
Cc: robh+dt, krzysztof.kozlowski+dt, linux-iio, devicetree,
linux-kernel, lucas.p.stankus
On Wed, 31 Aug 2022 17:35:38 +0300
George Mois <george.mois@analog.com> wrote:
> 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
Whilst there is some discussion of this going on in a different thread
my opinion is that Datasheet is a formal tag so there should be no blank line
here.
A few other minor comments inline.
>
> Signed-off-by: George Mois <george.mois@analog.com>
> ---
> diff --git a/drivers/iio/accel/adxl313_core.c b/drivers/iio/accel/adxl313_core.c
> index afeef779e1d0..9c93e71c94f1 100644
> --- a/drivers/iio/accel/adxl313_core.c
> +++ b/drivers/iio/accel/adxl313_core.c
...
> -static int adxl313_setup(struct device *dev, struct adxl313_data *data,
> - int (*setup)(struct device *, struct regmap *))
> +static int adxl312_adxl314_check_id(struct device *dev,
Naming a function after multiple supported parts has a history of
going wrong over the longer term as that list of parts keeps getting longer.
Just name it after the first one supported.
> + struct adxl313_data *data)
> {
> unsigned int regval;
> int ret;
>
> +
> +static int adxl313_setup(struct device *dev, struct adxl313_data *data,
> + int (*setup)(struct device *, struct regmap *))
> +{
> + int ret;
>
> - if (regval != ADXL313_PARTID) {
> - dev_err(dev, "Invalid device ID: 0x%02x\n", regval);
> - return -ENODEV;
> + /*
> + * 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;
> }
>
> - /* 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;
> + if (setup) {
> + ret = setup(dev, data->regmap);
> + if (ret)
> + return ret;
> + }
> +
> + if (data->chip_info->type == ADXL313)
> + /* ADXL313 */
> + ret = adxl313_check_id(dev, data);
I'd prefer these handled via a callback rather than checking on type.
That leads to the driver being easier to extend for future supported parts
as changes are focused in one place (the chip_info structures).
Otherwise this new approach seems much cleaner.
> + else
> + /* ADXL312 or ADXL314 */
> + ret = adxl312_adxl314_check_id(dev, data);
>
> diff --git a/drivers/iio/accel/adxl313_i2c.c b/drivers/iio/accel/adxl313_i2c.c
> index c329765dbf60..0665f2945a27 100644
> --- a/drivers/iio/accel/adxl313_i2c.c
> +++ b/drivers/iio/accel/adxl313_i2c.c
> @@ -14,42 +14,80 @@
>
> static const struct i2c_device_id adxl313_i2c_id[] = {
> - { "adxl313" },
> + { "adxl312", ADXL312 },
As for SPI case, it would be cleaner to put a pointer
in here as then the two paths will be more similar.
> + { "adxl313", ADXL313 },
> + { "adxl314", ADXL314 },
> { }
> };
>
> 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;
> + enum adxl313_device_type chip_type;
> + struct regmap *regmap;
> +
> + chip_data = device_get_match_data(&client->dev);
> + if (chip_data)
> + chip_type = chip_data->type;
> + else
> + chip_type = i2c_match_id(adxl313_i2c_id, client)->driver_data;
> +
> + regmap = devm_regmap_init_i2c(client,
> + &adxl31x_i2c_regmap_config[chip_type]);
As below: I think it is cleaner to get chip_data for either registration
path and extract chip_type from that. Aim being to avoid going backwards
and forwards between the structure and the enum.
> + 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, &adxl31x_chip_info[chip_type], NULL);
> +}
> +
> static struct i2c_driver adxl313_i2c_driver = {
> .driver = {
> .name = "adxl313_i2c",
> diff --git a/drivers/iio/accel/adxl313_spi.c b/drivers/iio/accel/adxl313_spi.c
> index a3c6d553462d..2c3b094ef465 100644
> --- a/drivers/iio/accel/adxl313_spi.c
> +++ b/drivers/iio/accel/adxl313_spi.c
> @@ -11,17 +11,38 @@
>
> static int adxl313_spi_setup(struct device *dev, struct regmap *regmap)
> @@ -42,7 +63,8 @@ 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;
> + enum adxl313_device_type chip_type;
> struct regmap *regmap;
> int ret;
>
> @@ -51,26 +73,47 @@ static int adxl313_spi_probe(struct spi_device *spi)
> if (ret)
> return ret;
>
> - regmap = devm_regmap_init_spi(spi, &adxl313_spi_regmap_config);
> + chip_data = device_get_match_data(&spi->dev);
> + if (chip_data)
> + chip_type = chip_data->type;
> + else
> + chip_type = spi_get_device_id(spi)->driver_data;
I'd rather see you set chip_data here for either path then use that
directly in the core_probe() call below. Note comment on storing
a pointer in spi_device_id->driver_data (it is carefully sized to allow
that to be done)
You will need to pull chip_type out for the regmap config, but at least
we are only going one way rather than
chip_data->chip_type->chip_data.
> +
> + regmap = devm_regmap_init_spi(spi,
> + &adxl31x_spi_regmap_config[chip_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,
> + &adxl31x_chip_info[chip_type], &adxl313_spi_setup);
> }
>
> static const struct spi_device_id adxl313_spi_id[] = {
> - { "adxl313" },
> + { "adxl312", ADXL312 },
It's fine to store a pointer in the data field of this (will need casting appropriately)
and that will simplify handling in probe() as both sources will be of the same type.
> + { "adxl313", ADXL313 },
> + { "adxl314", 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],
Not particularly important but it's fairly common practice to have these
on one line.
{ .compatible = "adi,adxl312", .data = &adxl31x_chip_info[ADXL312] },
> + },
> + {
> + .compatible = "adi,adxl313",
> + .data = &adxl31x_chip_info[ADXL313],
> + },
> + {
> + .compatible = "adi,adxl314",
> + .data = &adxl31x_chip_info[ADXL314],
> + },
> { }
> };
>
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2022-09-04 16:03 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2022-08-31 14:35 [PATCH v3 1/2] bindings: iio: accel: extend adxl313 documentation file George Mois
2022-08-31 14:35 ` [PATCH v3 2/2] drivers: iio: accel: adxl312 and adxl314 support George Mois
2022-09-04 15:28 ` Jonathan Cameron
2022-09-04 15:13 ` [PATCH v3 1/2] bindings: iio: accel: extend adxl313 documentation file Jonathan Cameron
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).