linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH V8 0/5] iio: accel: sca3300: add compatible for scl3300
@ 2022-05-23  6:23 LI Qingwu
  2022-05-23  6:23 ` [PATCH V8 1/5] dt-bindings: iio: accel: sca3300: Document murata,scl3300 LI Qingwu
                   ` (4 more replies)
  0 siblings, 5 replies; 9+ messages in thread
From: LI Qingwu @ 2022-05-23  6:23 UTC (permalink / raw)
  To: jic23, lars, robh+dt, tomas.melin, andy.shevchenko, devicetree,
	linux-kernel, Qing-wu.Li
  Cc: thomas.haemmerle, linux-iio

The current driver support sca3300 only, modified to support SCL3300.
Verified with SCL3300 on IMX8MM.

SCL3300 is a three-axis accelerometer sensor with angle output, 
the change adds the support of scl3300 and inclination data output.


Changes in v8: 
 - Modified comments for the wait time of settling of signal paths.
 - Arrange the line wrap of CA3300_INCLI_CHANNEL.
 - Fix the whitespace issue.
 - Add "bool angle" in chip info for enable the angle output.


LI Qingwu (5):
  dt-bindings: iio: accel: sca3300: Document murata,scl3300
  iio: accel: sca3300: add define for temp channel for reuse.
  iio: accel: sca3300: modified to support multi chips
  iio: accel: sca3300: Add support for SCL3300
  iio: accel: sca3300: Add inclination channels

 .../bindings/iio/accel/murata,sca3300.yaml    |   1 +
 drivers/iio/accel/sca3300.c                   | 325 +++++++++++++++---
 2 files changed, 271 insertions(+), 55 deletions(-)

-- 
2.25.1


^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH V8 1/5] dt-bindings: iio: accel: sca3300: Document murata,scl3300
  2022-05-23  6:23 [PATCH V8 0/5] iio: accel: sca3300: add compatible for scl3300 LI Qingwu
@ 2022-05-23  6:23 ` LI Qingwu
  2022-05-23  6:23 ` [PATCH V8 2/5] iio: accel: sca3300: add define for temp channel for reuse LI Qingwu
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 9+ messages in thread
From: LI Qingwu @ 2022-05-23  6:23 UTC (permalink / raw)
  To: jic23, lars, robh+dt, tomas.melin, andy.shevchenko, devicetree,
	linux-kernel, Qing-wu.Li
  Cc: thomas.haemmerle, linux-iio, Rob Herring

Add DT bindings for Murata scl3300 inclinometer.

Reviewed-by: Rob Herring <robh@kernel.org>
Signed-off-by: LI Qingwu <Qing-wu.Li@leica-geosystems.com.cn>
---
 Documentation/devicetree/bindings/iio/accel/murata,sca3300.yaml | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/iio/accel/murata,sca3300.yaml b/Documentation/devicetree/bindings/iio/accel/murata,sca3300.yaml
index 55fd3548e3b6..f6e2a16a710b 100644
--- a/Documentation/devicetree/bindings/iio/accel/murata,sca3300.yaml
+++ b/Documentation/devicetree/bindings/iio/accel/murata,sca3300.yaml
@@ -17,6 +17,7 @@ properties:
   compatible:
     enum:
       - murata,sca3300
+      - murata,scl3300
 
   reg:
     maxItems: 1
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH V8 2/5] iio: accel: sca3300: add define for temp channel for reuse.
  2022-05-23  6:23 [PATCH V8 0/5] iio: accel: sca3300: add compatible for scl3300 LI Qingwu
  2022-05-23  6:23 ` [PATCH V8 1/5] dt-bindings: iio: accel: sca3300: Document murata,scl3300 LI Qingwu
@ 2022-05-23  6:23 ` LI Qingwu
  2022-05-23  6:23 ` [PATCH V8 3/5] iio: accel: sca3300: modified to support multi chips LI Qingwu
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 9+ messages in thread
From: LI Qingwu @ 2022-05-23  6:23 UTC (permalink / raw)
  To: jic23, lars, robh+dt, tomas.melin, andy.shevchenko, devicetree,
	linux-kernel, Qing-wu.Li
  Cc: thomas.haemmerle, linux-iio

Add define of SCA3300_TEMP_CHANNEL for reuse.

Signed-off-by: LI Qingwu <Qing-wu.Li@leica-geosystems.com.cn>
---
 drivers/iio/accel/sca3300.c | 26 ++++++++++++++------------
 1 file changed, 14 insertions(+), 12 deletions(-)

diff --git a/drivers/iio/accel/sca3300.c b/drivers/iio/accel/sca3300.c
index f7ef8ecfd34a..ff16d2cc8c70 100644
--- a/drivers/iio/accel/sca3300.c
+++ b/drivers/iio/accel/sca3300.c
@@ -72,22 +72,24 @@ enum sca3300_scan_indexes {
 	},								\
 }
 
+#define SCA3300_TEMP_CHANNEL(index, reg) {				\
+		.type = IIO_TEMP,					\
+		.address = reg,						\
+		.scan_index = index,					\
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),		\
+		.scan_type = {						\
+			.sign = 's',					\
+			.realbits = 16,					\
+			.storagebits = 16,				\
+			.endianness = IIO_CPU,				\
+		},							\
+}
+
 static const struct iio_chan_spec sca3300_channels[] = {
 	SCA3300_ACCEL_CHANNEL(SCA3300_ACC_X, 0x1, X),
 	SCA3300_ACCEL_CHANNEL(SCA3300_ACC_Y, 0x2, Y),
 	SCA3300_ACCEL_CHANNEL(SCA3300_ACC_Z, 0x3, Z),
-	{
-		.type = IIO_TEMP,
-		.address = 0x5,
-		.scan_index = SCA3300_TEMP,
-		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
-		.scan_type = {
-			.sign = 's',
-			.realbits = 16,
-			.storagebits = 16,
-			.endianness = IIO_CPU,
-		},
-	},
+	SCA3300_TEMP_CHANNEL(SCA3300_TEMP, 0x05),
 	IIO_CHAN_SOFT_TIMESTAMP(4),
 };
 
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH V8 3/5] iio: accel: sca3300: modified to support multi chips
  2022-05-23  6:23 [PATCH V8 0/5] iio: accel: sca3300: add compatible for scl3300 LI Qingwu
  2022-05-23  6:23 ` [PATCH V8 1/5] dt-bindings: iio: accel: sca3300: Document murata,scl3300 LI Qingwu
  2022-05-23  6:23 ` [PATCH V8 2/5] iio: accel: sca3300: add define for temp channel for reuse LI Qingwu
@ 2022-05-23  6:23 ` LI Qingwu
  2022-05-25  9:59   ` Tomas Melin
  2022-05-23  6:23 ` [PATCH V8 4/5] iio: accel: sca3300: Add support for SCL3300 LI Qingwu
  2022-05-23  6:23 ` [PATCH V8 5/5] iio: accel: sca3300: Add inclination channels LI Qingwu
  4 siblings, 1 reply; 9+ messages in thread
From: LI Qingwu @ 2022-05-23  6:23 UTC (permalink / raw)
  To: jic23, lars, robh+dt, tomas.melin, andy.shevchenko, devicetree,
	linux-kernel, Qing-wu.Li
  Cc: thomas.haemmerle, linux-iio

Prepare the way for multiple chips and additional channels:
- Modify the driver to read the device ID and load the corresponding
  sensor information from the table to support multiple chips
- Add prepares for the addition of extra channels
- Prepare for handling the operation modes for multiple chips

Signed-off-by: LI Qingwu <Qing-wu.Li@leica-geosystems.com.cn>
---
 drivers/iio/accel/sca3300.c | 198 ++++++++++++++++++++++++++++--------
 1 file changed, 157 insertions(+), 41 deletions(-)

diff --git a/drivers/iio/accel/sca3300.c b/drivers/iio/accel/sca3300.c
index ff16d2cc8c70..6463d12a9ab9 100644
--- a/drivers/iio/accel/sca3300.c
+++ b/drivers/iio/accel/sca3300.c
@@ -93,19 +93,40 @@ static const struct iio_chan_spec sca3300_channels[] = {
 	IIO_CHAN_SOFT_TIMESTAMP(4),
 };
 
-static const int sca3300_lp_freq[] = {70, 70, 70, 10};
-static const int sca3300_accel_scale[][2] = {{0, 370}, {0, 741}, {0, 185}, {0, 185}};
+static const int sca3300_lp_freq[] = {70, 10};
+static const int sca3300_lp_freq_map[] = {0, 0, 0, 1};
 
+static const int sca3300_accel_scale[][2] = {{0, 370}, {0, 741}, {0, 185}};
+static const int sca3300_accel_scale_map[] = {0, 1, 2, 2};
+
+static const int sca3300_avail_modes_map[] = {0, 1, 2, 3};
 static const unsigned long sca3300_scan_masks[] = {
 	BIT(SCA3300_ACC_X) | BIT(SCA3300_ACC_Y) | BIT(SCA3300_ACC_Z) |
 	BIT(SCA3300_TEMP),
 	0
 };
 
+struct sca3300_chip_info {
+	const char *name;
+	const unsigned long *scan_masks;
+	const struct iio_chan_spec *channels;
+	u8 num_channels;
+	u8 num_accel_scales;
+	const int (*accel_scale)[2];
+	const int *accel_scale_map;
+	u8 num_freqs;
+	const int *freq_table;
+	const int *freq_map;
+	const int *avail_modes_table;
+	u8 num_avail_modes;
+	u8 chip_id;
+};
+
 /**
  * struct sca3300_data - device data
  * @spi: SPI device structure
  * @lock: Data buffer lock
+ * @chip: Sensor chip specific information
  * @scan: Triggered buffer. Four channel 16-bit data + 64-bit timestamp
  * @txbuf: Transmit buffer
  * @rxbuf: Receive buffer
@@ -113,6 +134,7 @@ static const unsigned long sca3300_scan_masks[] = {
 struct sca3300_data {
 	struct spi_device *spi;
 	struct mutex lock;
+	const struct sca3300_chip_info *chip;
 	struct {
 		s16 channels[4];
 		s64 ts __aligned(sizeof(s64));
@@ -121,6 +143,24 @@ struct sca3300_data {
 	u8 rxbuf[4];
 };
 
+static const struct sca3300_chip_info sca3300_chip_tbl[] = {
+	{
+		.name = "sca3300",
+		.scan_masks = sca3300_scan_masks,
+		.channels = sca3300_channels,
+		.num_channels = ARRAY_SIZE(sca3300_channels),
+		.num_accel_scales = ARRAY_SIZE(sca3300_accel_scale)*2,
+		.accel_scale = sca3300_accel_scale,
+		.accel_scale_map = sca3300_accel_scale_map,
+		.num_freqs = ARRAY_SIZE(sca3300_lp_freq),
+		.freq_table = sca3300_lp_freq,
+		.freq_map = sca3300_lp_freq_map,
+		.avail_modes_table = sca3300_avail_modes_map,
+		.num_avail_modes = 4,
+		.chip_id = SCA3300_WHOAMI_ID,
+	},
+};
+
 DECLARE_CRC8_TABLE(sca3300_crc_table);
 
 static int sca3300_transfer(struct sca3300_data *sca_data, int *val)
@@ -227,36 +267,92 @@ static int sca3300_write_reg(struct sca3300_data *sca_data, u8 reg, int val)
 	return sca3300_error_handler(sca_data);
 }
 
+static int sca3300_set_op_mode(struct sca3300_data *sca_data, int index)
+{
+	if ((index < 0) || (index >= sca_data->chip->num_avail_modes))
+		return -EINVAL;
+
+	return sca3300_write_reg(sca_data, SCA3300_REG_MODE,
+				 sca_data->chip->avail_modes_table[index]);
+}
+
+static int sca3300_get_op_mode(struct sca3300_data *sca_data, int *index)
+{
+	int reg_val;
+	int ret;
+	int i;
+
+	ret = sca3300_read_reg(sca_data, SCA3300_REG_MODE, &reg_val);
+	if (ret)
+		return ret;
+
+	reg_val &= GENMASK(1, 0);
+	for (i = 0; i < sca_data->chip->num_avail_modes; i++) {
+		if (sca_data->chip->avail_modes_table[i] == reg_val)
+			break;
+	}
+	if (i == sca_data->chip->num_avail_modes)
+		return -EINVAL;
+
+	*index = i;
+	return 0;
+}
+
+static int sca3300_set_frequency(struct sca3300_data *data, int val)
+{
+	const struct sca3300_chip_info *chip = data->chip;
+	unsigned int index;
+	int *opmode_scale;
+	int *new_scale;
+	unsigned int i;
+
+	if (sca3300_get_op_mode(data, &index))
+		return -EINVAL;
+
+	/*
+	 * Find a mode in which the requested sampling frequency is available
+	 * and the scaling currently set is retained.
+	 */
+	opmode_scale = (int *)chip->accel_scale[chip->accel_scale_map[index]];
+	for (i = 0; i < chip->num_avail_modes; i++) {
+		new_scale = (int *)chip->accel_scale[chip->accel_scale_map[i]];
+		if ((val == chip->freq_table[chip->freq_map[i]]) &&
+		    (opmode_scale[1] == new_scale[1]) &&
+		    (opmode_scale[0] == new_scale[0]))
+			break;
+	}
+	if (i == chip->num_avail_modes)
+		return -EINVAL;
+
+	return sca3300_set_op_mode(data, i);
+}
+
 static int sca3300_write_raw(struct iio_dev *indio_dev,
 			     struct iio_chan_spec const *chan,
 			     int val, int val2, long mask)
 {
 	struct sca3300_data *data = iio_priv(indio_dev);
-	int reg_val;
-	int ret;
+	int index;
 	int i;
 
 	switch (mask) {
 	case IIO_CHAN_INFO_SCALE:
-		if (val)
+		if (chan->type != IIO_ACCEL)
 			return -EINVAL;
-
-		for (i = 0; i < ARRAY_SIZE(sca3300_accel_scale); i++) {
-			if (val2 == sca3300_accel_scale[i][1])
-				return sca3300_write_reg(data, SCA3300_REG_MODE, i);
+		/*
+		 * Letting scale take priority over sampling frequency.
+		 * That makes sense given we can only ever end up increasing
+		 * the sampling frequency which is unlikely to be a problem.
+		 */
+		for (i = 0; i < data->chip->num_avail_modes; i++) {
+			index = data->chip->accel_scale_map[i];
+			if ((val  == data->chip->accel_scale[index][0]) &&
+			    (val2 == data->chip->accel_scale[index][1]))
+				return sca3300_set_op_mode(data, i);
 		}
 		return -EINVAL;
-
 	case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
-		ret = sca3300_read_reg(data, SCA3300_REG_MODE, &reg_val);
-		if (ret)
-			return ret;
-		/* freq. change is possible only for mode 3 and 4 */
-		if (reg_val == 2 && val == sca3300_lp_freq[3])
-			return sca3300_write_reg(data, SCA3300_REG_MODE, 3);
-		if (reg_val == 3 && val == sca3300_lp_freq[2])
-			return sca3300_write_reg(data, SCA3300_REG_MODE, 2);
-		return -EINVAL;
+		return sca3300_set_frequency(data, val);
 	default:
 		return -EINVAL;
 	}
@@ -267,8 +363,8 @@ static int sca3300_read_raw(struct iio_dev *indio_dev,
 			    int *val, int *val2, long mask)
 {
 	struct sca3300_data *data = iio_priv(indio_dev);
+	int index;
 	int ret;
-	int reg_val;
 
 	switch (mask) {
 	case IIO_CHAN_INFO_RAW:
@@ -277,17 +373,24 @@ static int sca3300_read_raw(struct iio_dev *indio_dev,
 			return ret;
 		return IIO_VAL_INT;
 	case IIO_CHAN_INFO_SCALE:
-		ret = sca3300_read_reg(data, SCA3300_REG_MODE, &reg_val);
+		ret = sca3300_get_op_mode(data, &index);
 		if (ret)
 			return ret;
-		*val = 0;
-		*val2 = sca3300_accel_scale[reg_val][1];
-		return IIO_VAL_INT_PLUS_MICRO;
+		switch (chan->type) {
+		case IIO_ACCEL:
+			index = data->chip->accel_scale_map[index];
+			*val  = data->chip->accel_scale[index][0];
+			*val2 = data->chip->accel_scale[index][1];
+			return IIO_VAL_INT_PLUS_MICRO;
+		default:
+			return -EINVAL;
+		}
 	case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
-		ret = sca3300_read_reg(data, SCA3300_REG_MODE, &reg_val);
+		ret = sca3300_get_op_mode(data, &index);
 		if (ret)
 			return ret;
-		*val = sca3300_lp_freq[reg_val];
+		index = data->chip->freq_map[index];
+		*val = data->chip->freq_table[index];
 		return IIO_VAL_INT;
 	default:
 		return -EINVAL;
@@ -331,6 +434,7 @@ static int sca3300_init(struct sca3300_data *sca_data,
 {
 	int value = 0;
 	int ret;
+	int i;
 
 	ret = sca3300_write_reg(sca_data, SCA3300_REG_MODE,
 				SCA3300_MODE_SW_RESET);
@@ -347,12 +451,17 @@ static int sca3300_init(struct sca3300_data *sca_data,
 	if (ret)
 		return ret;
 
-	if (value != SCA3300_WHOAMI_ID) {
-		dev_err(&sca_data->spi->dev,
-			"device id not expected value, %d != %u\n",
-			value, SCA3300_WHOAMI_ID);
+	for (i = 0; i < ARRAY_SIZE(sca3300_chip_tbl); i++) {
+		if (sca3300_chip_tbl[i].chip_id == value)
+			break;
+	}
+	if (i == ARRAY_SIZE(sca3300_chip_tbl)) {
+		dev_err(&sca_data->spi->dev, "unknown chip id %x\n", value);
 		return -ENODEV;
 	}
+
+	sca_data->chip = &sca3300_chip_tbl[i];
+
 	return 0;
 }
 
@@ -384,15 +493,21 @@ static int sca3300_read_avail(struct iio_dev *indio_dev,
 			      const int **vals, int *type, int *length,
 			      long mask)
 {
+	struct sca3300_data *data = iio_priv(indio_dev);
 	switch (mask) {
 	case IIO_CHAN_INFO_SCALE:
-		*vals = (const int *)sca3300_accel_scale;
-		*length = ARRAY_SIZE(sca3300_accel_scale) * 2 - 2;
-		*type = IIO_VAL_INT_PLUS_MICRO;
-		return IIO_AVAIL_LIST;
+		switch (chan->type) {
+		case IIO_ACCEL:
+			*vals = (const int *)data->chip->accel_scale;
+			*length = data->chip->num_accel_scales;
+			*type = IIO_VAL_INT_PLUS_MICRO;
+			return IIO_AVAIL_LIST;
+		default:
+			return -EINVAL;
+		}
 	case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
-		*vals = &sca3300_lp_freq[2];
-		*length = 2;
+		*vals = (const int *)data->chip->freq_table;
+		*length = data->chip->num_freqs;
 		*type = IIO_VAL_INT;
 		return IIO_AVAIL_LIST;
 	default:
@@ -424,11 +539,6 @@ static int sca3300_probe(struct spi_device *spi)
 	crc8_populate_msb(sca3300_crc_table, SCA3300_CRC8_POLYNOMIAL);
 
 	indio_dev->info = &sca3300_info;
-	indio_dev->name = SCA3300_ALIAS;
-	indio_dev->modes = INDIO_DIRECT_MODE;
-	indio_dev->channels = sca3300_channels;
-	indio_dev->num_channels = ARRAY_SIZE(sca3300_channels);
-	indio_dev->available_scan_masks = sca3300_scan_masks;
 
 	ret = sca3300_init(sca_data, indio_dev);
 	if (ret) {
@@ -436,6 +546,12 @@ static int sca3300_probe(struct spi_device *spi)
 		return ret;
 	}
 
+	indio_dev->name = sca_data->chip->name;
+	indio_dev->modes = INDIO_DIRECT_MODE;
+	indio_dev->channels = sca_data->chip->channels;
+	indio_dev->num_channels = sca_data->chip->num_channels;
+	indio_dev->available_scan_masks = sca_data->chip->scan_masks;
+
 	ret = devm_iio_triggered_buffer_setup(&spi->dev, indio_dev,
 					      iio_pollfunc_store_time,
 					      sca3300_trigger_handler, NULL);
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH V8 4/5] iio: accel: sca3300: Add support for SCL3300
  2022-05-23  6:23 [PATCH V8 0/5] iio: accel: sca3300: add compatible for scl3300 LI Qingwu
                   ` (2 preceding siblings ...)
  2022-05-23  6:23 ` [PATCH V8 3/5] iio: accel: sca3300: modified to support multi chips LI Qingwu
@ 2022-05-23  6:23 ` LI Qingwu
  2022-05-25 10:08   ` Tomas Melin
  2022-05-23  6:23 ` [PATCH V8 5/5] iio: accel: sca3300: Add inclination channels LI Qingwu
  4 siblings, 1 reply; 9+ messages in thread
From: LI Qingwu @ 2022-05-23  6:23 UTC (permalink / raw)
  To: jic23, lars, robh+dt, tomas.melin, andy.shevchenko, devicetree,
	linux-kernel, Qing-wu.Li
  Cc: thomas.haemmerle, linux-iio

Add support for Murata SCL3300, a 3-axis MEMS accelerometer.
Same as SCA3300, it has the accelerometer and temperature output.

Datasheet: www.murata.com/en-us/products/sensor/inclinometer/overview/lineup/scl3300
Signed-off-by: LI Qingwu <Qing-wu.Li@leica-geosystems.com.cn>
---
 drivers/iio/accel/sca3300.c | 31 +++++++++++++++++++++++++++++--
 1 file changed, 29 insertions(+), 2 deletions(-)

diff --git a/drivers/iio/accel/sca3300.c b/drivers/iio/accel/sca3300.c
index 6463d12a9ab9..74e780a7ffcd 100644
--- a/drivers/iio/accel/sca3300.c
+++ b/drivers/iio/accel/sca3300.c
@@ -38,6 +38,7 @@
 /* Device ID */
 #define SCA3300_REG_WHOAMI	0x10
 #define SCA3300_WHOAMI_ID	0x51
+#define SCL3300_WHOAMI_ID	0xC1
 
 /* Device return status and mask */
 #define SCA3300_VALUE_RS_ERROR	0x3
@@ -96,10 +97,18 @@ static const struct iio_chan_spec sca3300_channels[] = {
 static const int sca3300_lp_freq[] = {70, 10};
 static const int sca3300_lp_freq_map[] = {0, 0, 0, 1};
 
+static const int scl3300_lp_freq[] = {40, 70, 10};
+static const int scl3300_lp_freq_map[] = {0, 1, 2};
+
 static const int sca3300_accel_scale[][2] = {{0, 370}, {0, 741}, {0, 185}};
 static const int sca3300_accel_scale_map[] = {0, 1, 2, 2};
 
+static const int scl3300_accel_scale[][2] = {{0, 167}, {0, 333}, {0, 83}};
+static const int scl3300_accel_scale_map[] = {0, 1, 2};
+
 static const int sca3300_avail_modes_map[] = {0, 1, 2, 3};
+static const int scl3300_avail_modes_map[] = {0, 1, 3};
+
 static const unsigned long sca3300_scan_masks[] = {
 	BIT(SCA3300_ACC_X) | BIT(SCA3300_ACC_Y) | BIT(SCA3300_ACC_Z) |
 	BIT(SCA3300_TEMP),
@@ -159,6 +168,21 @@ static const struct sca3300_chip_info sca3300_chip_tbl[] = {
 		.num_avail_modes = 4,
 		.chip_id = SCA3300_WHOAMI_ID,
 	},
+	{
+		.name = "scl3300",
+		.scan_masks = sca3300_scan_masks,
+		.channels = sca3300_channels,
+		.num_channels = ARRAY_SIZE(sca3300_channels),
+		.num_accel_scales = ARRAY_SIZE(scl3300_accel_scale)*2,
+		.accel_scale = scl3300_accel_scale,
+		.accel_scale_map = scl3300_accel_scale_map,
+		.num_freqs = ARRAY_SIZE(scl3300_lp_freq),
+		.freq_table = scl3300_lp_freq,
+		.freq_map = scl3300_lp_freq_map,
+		.avail_modes_table = scl3300_avail_modes_map,
+		.num_avail_modes = 3,
+		.chip_id = SCL3300_WHOAMI_ID,
+	},
 };
 
 DECLARE_CRC8_TABLE(sca3300_crc_table);
@@ -443,9 +467,11 @@ static int sca3300_init(struct sca3300_data *sca_data,
 
 	/*
 	 * Wait 1ms after SW-reset command.
-	 * Wait 15ms for settling of signal paths.
+	 * Wait for the settling of signal paths,
+	 * 15ms for SCA3300 and 25ms for SCL3300,
+	 * take the max of the then.
 	 */
-	usleep_range(16e3, 50e3);
+	usleep_range(26e3, 50e3);
 
 	ret = sca3300_read_reg(sca_data, SCA3300_REG_WHOAMI, &value);
 	if (ret)
@@ -572,6 +598,7 @@ static int sca3300_probe(struct spi_device *spi)
 
 static const struct of_device_id sca3300_dt_ids[] = {
 	{ .compatible = "murata,sca3300"},
+	{ .compatible = "murata,scl3300"},
 	{}
 };
 MODULE_DEVICE_TABLE(of, sca3300_dt_ids);
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH V8 5/5] iio: accel: sca3300: Add inclination channels
  2022-05-23  6:23 [PATCH V8 0/5] iio: accel: sca3300: add compatible for scl3300 LI Qingwu
                   ` (3 preceding siblings ...)
  2022-05-23  6:23 ` [PATCH V8 4/5] iio: accel: sca3300: Add support for SCL3300 LI Qingwu
@ 2022-05-23  6:23 ` LI Qingwu
  2022-05-28 17:23   ` Jonathan Cameron
  4 siblings, 1 reply; 9+ messages in thread
From: LI Qingwu @ 2022-05-23  6:23 UTC (permalink / raw)
  To: jic23, lars, robh+dt, tomas.melin, andy.shevchenko, devicetree,
	linux-kernel, Qing-wu.Li
  Cc: thomas.haemmerle, linux-iio

Different from SCA3300, SCL3300 can output inclination angles.
Angles are formed from acceleration with following equations:
ANG_X = atan2(accx , sqrt(pow(accy , 2) + pow(accz , 2)))
ANG_Y = atan2(accy , sqrt(pow(accx , 2) + pow(accz , 2)))
ANG_Z = atan2(accz , sqrt(pow(accx , 2) + pow(accy , 2)))

The commit adds the output of the raw value, scale
and scale_available of angles.

New interfaces:
  in_incli_scale
  in_incli_scale_available
  in_incli_x_raw
  in_incli_y_raw
  in_incli_z_raw
Data converted by application of scale to degrees.

Signed-off-by: LI Qingwu <Qing-wu.Li@leica-geosystems.com.cn>
---
 drivers/iio/accel/sca3300.c | 76 +++++++++++++++++++++++++++++++++++--
 1 file changed, 73 insertions(+), 3 deletions(-)

diff --git a/drivers/iio/accel/sca3300.c b/drivers/iio/accel/sca3300.c
index 74e780a7ffcd..c7fcb0de5462 100644
--- a/drivers/iio/accel/sca3300.c
+++ b/drivers/iio/accel/sca3300.c
@@ -44,12 +44,18 @@
 #define SCA3300_VALUE_RS_ERROR	0x3
 #define SCA3300_MASK_RS_STATUS	GENMASK(1, 0)
 
+#define SCL3300_REG_ANG_CTRL 0x0C
+#define SCL3300_ANG_ENABLE   0x1F
+
 enum sca3300_scan_indexes {
 	SCA3300_ACC_X = 0,
 	SCA3300_ACC_Y,
 	SCA3300_ACC_Z,
 	SCA3300_TEMP,
 	SCA3300_TIMESTAMP,
+	SCA3300_INCLI_X,
+	SCA3300_INCLI_Y,
+	SCA3300_INCLI_Z,
 };
 
 #define SCA3300_ACCEL_CHANNEL(index, reg, axis) {			\
@@ -73,6 +79,23 @@ enum sca3300_scan_indexes {
 	},								\
 }
 
+#define SCA3300_INCLI_CHANNEL(index, reg, axis) {			\
+	.type = IIO_INCLI,						\
+	.address = reg,							\
+	.modified = 1,							\
+	.channel2 = IIO_MOD_##axis,					\
+	.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),		\
+	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),			\
+	.info_mask_shared_by_type_available = BIT(IIO_CHAN_INFO_SCALE), \
+	.scan_index = index,						\
+	.scan_type = {							\
+		.sign = 's',						\
+		.realbits = 16,						\
+		.storagebits = 16,					\
+		.endianness = IIO_CPU,					\
+	},								\
+}
+
 #define SCA3300_TEMP_CHANNEL(index, reg) {				\
 		.type = IIO_TEMP,					\
 		.address = reg,						\
@@ -106,15 +129,36 @@ static const int sca3300_accel_scale_map[] = {0, 1, 2, 2};
 static const int scl3300_accel_scale[][2] = {{0, 167}, {0, 333}, {0, 83}};
 static const int scl3300_accel_scale_map[] = {0, 1, 2};
 
+static const int scl3300_incli_scale[][2] = {{0, 5495}};
+static const int scl3300_incli_scale_map[] = {0, 0, 0};
+
 static const int sca3300_avail_modes_map[] = {0, 1, 2, 3};
 static const int scl3300_avail_modes_map[] = {0, 1, 3};
 
+static const struct iio_chan_spec scl3300_channels[] = {
+	SCA3300_ACCEL_CHANNEL(SCA3300_ACC_X, 0x1, X),
+	SCA3300_ACCEL_CHANNEL(SCA3300_ACC_Y, 0x2, Y),
+	SCA3300_ACCEL_CHANNEL(SCA3300_ACC_Z, 0x3, Z),
+	SCA3300_TEMP_CHANNEL(SCA3300_TEMP, 0x05),
+	IIO_CHAN_SOFT_TIMESTAMP(4),
+	SCA3300_INCLI_CHANNEL(SCA3300_INCLI_X, 0x09, X),
+	SCA3300_INCLI_CHANNEL(SCA3300_INCLI_Y, 0x0A, Y),
+	SCA3300_INCLI_CHANNEL(SCA3300_INCLI_Z, 0x0B, Z),
+};
+
 static const unsigned long sca3300_scan_masks[] = {
 	BIT(SCA3300_ACC_X) | BIT(SCA3300_ACC_Y) | BIT(SCA3300_ACC_Z) |
 	BIT(SCA3300_TEMP),
 	0
 };
 
+static const unsigned long scl3300_scan_masks[] = {
+	BIT(SCA3300_ACC_X) | BIT(SCA3300_ACC_Y) | BIT(SCA3300_ACC_Z) |
+	BIT(SCA3300_TEMP) |
+	BIT(SCA3300_INCLI_X) | BIT(SCA3300_INCLI_Y) | BIT(SCA3300_INCLI_Z),
+	0
+};
+
 struct sca3300_chip_info {
 	const char *name;
 	const unsigned long *scan_masks;
@@ -123,12 +167,16 @@ struct sca3300_chip_info {
 	u8 num_accel_scales;
 	const int (*accel_scale)[2];
 	const int *accel_scale_map;
+	const int (*incli_scale)[2];
+	const int *incli_scale_map;
+	u8 num_incli_scales;
 	u8 num_freqs;
 	const int *freq_table;
 	const int *freq_map;
 	const int *avail_modes_table;
 	u8 num_avail_modes;
 	u8 chip_id;
+	bool angle;
 };
 
 /**
@@ -167,21 +215,26 @@ static const struct sca3300_chip_info sca3300_chip_tbl[] = {
 		.avail_modes_table = sca3300_avail_modes_map,
 		.num_avail_modes = 4,
 		.chip_id = SCA3300_WHOAMI_ID,
+		.angle = false,
 	},
 	{
 		.name = "scl3300",
-		.scan_masks = sca3300_scan_masks,
-		.channels = sca3300_channels,
-		.num_channels = ARRAY_SIZE(sca3300_channels),
+		.scan_masks = scl3300_scan_masks,
+		.channels = scl3300_channels,
+		.num_channels = ARRAY_SIZE(scl3300_channels),
 		.num_accel_scales = ARRAY_SIZE(scl3300_accel_scale)*2,
 		.accel_scale = scl3300_accel_scale,
 		.accel_scale_map = scl3300_accel_scale_map,
+		.incli_scale = scl3300_incli_scale,
+		.incli_scale_map = scl3300_incli_scale_map,
+		.num_incli_scales =  ARRAY_SIZE(scl3300_incli_scale)*2,
 		.num_freqs = ARRAY_SIZE(scl3300_lp_freq),
 		.freq_table = scl3300_lp_freq,
 		.freq_map = scl3300_lp_freq_map,
 		.avail_modes_table = scl3300_avail_modes_map,
 		.num_avail_modes = 3,
 		.chip_id = SCL3300_WHOAMI_ID,
+		.angle = true,
 	},
 };
 
@@ -401,6 +454,11 @@ static int sca3300_read_raw(struct iio_dev *indio_dev,
 		if (ret)
 			return ret;
 		switch (chan->type) {
+		case IIO_INCLI:
+			index = data->chip->incli_scale_map[index];
+			*val  = data->chip->incli_scale[index][0];
+			*val2 = data->chip->incli_scale[index][1];
+			return IIO_VAL_INT_PLUS_MICRO;
 		case IIO_ACCEL:
 			index = data->chip->accel_scale_map[index];
 			*val  = data->chip->accel_scale[index][0];
@@ -488,6 +546,13 @@ static int sca3300_init(struct sca3300_data *sca_data,
 
 	sca_data->chip = &sca3300_chip_tbl[i];
 
+	if (sca_data->chip->angle) {
+		ret = sca3300_write_reg(sca_data, SCL3300_REG_ANG_CTRL,
+					SCL3300_ANG_ENABLE);
+		if (ret)
+			return ret;
+	}
+
 	return 0;
 }
 
@@ -523,6 +588,11 @@ static int sca3300_read_avail(struct iio_dev *indio_dev,
 	switch (mask) {
 	case IIO_CHAN_INFO_SCALE:
 		switch (chan->type) {
+		case IIO_INCLI:
+			*vals = (const int *)data->chip->incli_scale;
+			*length = data->chip->num_incli_scales;
+			*type = IIO_VAL_INT_PLUS_MICRO;
+			return IIO_AVAIL_LIST;
 		case IIO_ACCEL:
 			*vals = (const int *)data->chip->accel_scale;
 			*length = data->chip->num_accel_scales;
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* Re: [PATCH V8 3/5] iio: accel: sca3300: modified to support multi chips
  2022-05-23  6:23 ` [PATCH V8 3/5] iio: accel: sca3300: modified to support multi chips LI Qingwu
@ 2022-05-25  9:59   ` Tomas Melin
  0 siblings, 0 replies; 9+ messages in thread
From: Tomas Melin @ 2022-05-25  9:59 UTC (permalink / raw)
  To: LI Qingwu, jic23, lars, robh+dt, andy.shevchenko, devicetree,
	linux-kernel
  Cc: thomas.haemmerle, linux-iio

Hi,

this is looking quite good now. A few small comments below still.

On 23/05/2022 09:23, LI Qingwu wrote:
> Prepare the way for multiple chips and additional channels:
> - Modify the driver to read the device ID and load the corresponding
>   sensor information from the table to support multiple chips
> - Add prepares for the addition of extra channels
> - Prepare for handling the operation modes for multiple chips
> 
> Signed-off-by: LI Qingwu <Qing-wu.Li@leica-geosystems.com.cn>
> ---
>  drivers/iio/accel/sca3300.c | 198 ++++++++++++++++++++++++++++--------
>  1 file changed, 157 insertions(+), 41 deletions(-)
> 
> diff --git a/drivers/iio/accel/sca3300.c b/drivers/iio/accel/sca3300.c
> index ff16d2cc8c70..6463d12a9ab9 100644
> --- a/drivers/iio/accel/sca3300.c
> +++ b/drivers/iio/accel/sca3300.c
> @@ -93,19 +93,40 @@ static const struct iio_chan_spec sca3300_channels[] = {
>  	IIO_CHAN_SOFT_TIMESTAMP(4),
>  };
>  
> -static const int sca3300_lp_freq[] = {70, 70, 70, 10};
> -static const int sca3300_accel_scale[][2] = {{0, 370}, {0, 741}, {0, 185}, {0, 185}};
> +static const int sca3300_lp_freq[] = {70, 10};
> +static const int sca3300_lp_freq_map[] = {0, 0, 0, 1};
>  
> +static const int sca3300_accel_scale[][2] = {{0, 370}, {0, 741}, {0, 185}};
> +static const int sca3300_accel_scale_map[] = {0, 1, 2, 2};
> +
> +static const int sca3300_avail_modes_map[] = {0, 1, 2, 3};
>  static const unsigned long sca3300_scan_masks[] = {
>  	BIT(SCA3300_ACC_X) | BIT(SCA3300_ACC_Y) | BIT(SCA3300_ACC_Z) |
>  	BIT(SCA3300_TEMP),
>  	0
>  };
>  
> +struct sca3300_chip_info {
> +	const char *name;
> +	const unsigned long *scan_masks;
> +	const struct iio_chan_spec *channels;
> +	u8 num_channels;
> +	u8 num_accel_scales;
> +	const int (*accel_scale)[2];
> +	const int *accel_scale_map;
> +	u8 num_freqs;
> +	const int *freq_table;
> +	const int *freq_map;
> +	const int *avail_modes_table;
> +	u8 num_avail_modes;
> +	u8 chip_id;
> +};
> +
>  /**
>   * struct sca3300_data - device data
>   * @spi: SPI device structure
>   * @lock: Data buffer lock
> + * @chip: Sensor chip specific information
>   * @scan: Triggered buffer. Four channel 16-bit data + 64-bit timestamp
>   * @txbuf: Transmit buffer
>   * @rxbuf: Receive buffer
> @@ -113,6 +134,7 @@ static const unsigned long sca3300_scan_masks[] = {
>  struct sca3300_data {
>  	struct spi_device *spi;
>  	struct mutex lock;
> +	const struct sca3300_chip_info *chip;
>  	struct {
>  		s16 channels[4];
>  		s64 ts __aligned(sizeof(s64));
> @@ -121,6 +143,24 @@ struct sca3300_data {
>  	u8 rxbuf[4];
>  };
>  
> +static const struct sca3300_chip_info sca3300_chip_tbl[] = {
> +	{
> +		.name = "sca3300",
> +		.scan_masks = sca3300_scan_masks,
> +		.channels = sca3300_channels,
> +		.num_channels = ARRAY_SIZE(sca3300_channels),
> +		.num_accel_scales = ARRAY_SIZE(sca3300_accel_scale)*2,
> +		.accel_scale = sca3300_accel_scale,
> +		.accel_scale_map = sca3300_accel_scale_map,
> +		.num_freqs = ARRAY_SIZE(sca3300_lp_freq),
> +		.freq_table = sca3300_lp_freq,
> +		.freq_map = sca3300_lp_freq_map,
> +		.avail_modes_table = sca3300_avail_modes_map,
> +		.num_avail_modes = 4,
> +		.chip_id = SCA3300_WHOAMI_ID,
> +	},
> +};
> +
>  DECLARE_CRC8_TABLE(sca3300_crc_table);
>  
>  static int sca3300_transfer(struct sca3300_data *sca_data, int *val)
> @@ -227,36 +267,92 @@ static int sca3300_write_reg(struct sca3300_data *sca_data, u8 reg, int val)
>  	return sca3300_error_handler(sca_data);
>  }
>  
> +static int sca3300_set_op_mode(struct sca3300_data *sca_data, int index)
> +{
> +	if ((index < 0) || (index >= sca_data->chip->num_avail_modes))
> +		return -EINVAL;
> +
> +	return sca3300_write_reg(sca_data, SCA3300_REG_MODE,
> +				 sca_data->chip->avail_modes_table[index]);
> +}
> +
> +static int sca3300_get_op_mode(struct sca3300_data *sca_data, int *index)
> +{
> +	int reg_val;
> +	int ret;
> +	int i;
> +
> +	ret = sca3300_read_reg(sca_data, SCA3300_REG_MODE, &reg_val);
> +	if (ret)
> +		return ret;
> +
> +	reg_val &= GENMASK(1, 0);

This silently assumes that mode register has always max 4 modes, yet
there is a parameter for this in chip_info (num_avail_modes).
Wondering why this masking was added, I cannot see mention about this in
datasheet that register REG_MODE would contain other bits that the
actual mode number.
Was there some specific case in mind for adding this masking?


> +	for (i = 0; i < sca_data->chip->num_avail_modes; i++) {
> +		if (sca_data->chip->avail_modes_table[i] == reg_val)
> +			break;
> +	}
> +	if (i == sca_data->chip->num_avail_modes)
> +		return -EINVAL;
> +
> +	*index = i;
> +	return 0;
> +}
> +
> +static int sca3300_set_frequency(struct sca3300_data *data, int val)
> +{
> +	const struct sca3300_chip_info *chip = data->chip;
> +	unsigned int index;
> +	int *opmode_scale;
> +	int *new_scale;
> +	unsigned int i;
> +
> +	if (sca3300_get_op_mode(data, &index))
> +		return -EINVAL;
Suggest not hiding return code from get_op_mode() here, instead use

    ret = sca3300_get_op_mode(data, &index)
    if (ret)
        return ret;

Thanks,
Tomas


> +
> +	/*
> +	 * Find a mode in which the requested sampling frequency is available
> +	 * and the scaling currently set is retained.
> +	 */
> +	opmode_scale = (int *)chip->accel_scale[chip->accel_scale_map[index]];
> +	for (i = 0; i < chip->num_avail_modes; i++) {
> +		new_scale = (int *)chip->accel_scale[chip->accel_scale_map[i]];
> +		if ((val == chip->freq_table[chip->freq_map[i]]) &&
> +		    (opmode_scale[1] == new_scale[1]) &&
> +		    (opmode_scale[0] == new_scale[0]))
> +			break;
> +	}
> +	if (i == chip->num_avail_modes)
> +		return -EINVAL;
> +
> +	return sca3300_set_op_mode(data, i);
> +}
> +
>  static int sca3300_write_raw(struct iio_dev *indio_dev,
>  			     struct iio_chan_spec const *chan,
>  			     int val, int val2, long mask)
>  {
>  	struct sca3300_data *data = iio_priv(indio_dev);
> -	int reg_val;
> -	int ret;
> +	int index;
>  	int i;
>  
>  	switch (mask) {
>  	case IIO_CHAN_INFO_SCALE:
> -		if (val)
> +		if (chan->type != IIO_ACCEL)
>  			return -EINVAL;
> -
> -		for (i = 0; i < ARRAY_SIZE(sca3300_accel_scale); i++) {
> -			if (val2 == sca3300_accel_scale[i][1])
> -				return sca3300_write_reg(data, SCA3300_REG_MODE, i);
> +		/*
> +		 * Letting scale take priority over sampling frequency.
> +		 * That makes sense given we can only ever end up increasing
> +		 * the sampling frequency which is unlikely to be a problem.
> +		 */
> +		for (i = 0; i < data->chip->num_avail_modes; i++) {
> +			index = data->chip->accel_scale_map[i];
> +			if ((val  == data->chip->accel_scale[index][0]) &&
> +			    (val2 == data->chip->accel_scale[index][1]))
> +				return sca3300_set_op_mode(data, i);
>  		}
>  		return -EINVAL;
> -
>  	case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
> -		ret = sca3300_read_reg(data, SCA3300_REG_MODE, &reg_val);
> -		if (ret)
> -			return ret;
> -		/* freq. change is possible only for mode 3 and 4 */
> -		if (reg_val == 2 && val == sca3300_lp_freq[3])
> -			return sca3300_write_reg(data, SCA3300_REG_MODE, 3);
> -		if (reg_val == 3 && val == sca3300_lp_freq[2])
> -			return sca3300_write_reg(data, SCA3300_REG_MODE, 2);
> -		return -EINVAL;
> +		return sca3300_set_frequency(data, val);
>  	default:
>  		return -EINVAL;
>  	}
> @@ -267,8 +363,8 @@ static int sca3300_read_raw(struct iio_dev *indio_dev,
>  			    int *val, int *val2, long mask)
>  {
>  	struct sca3300_data *data = iio_priv(indio_dev);
> +	int index;
>  	int ret;
> -	int reg_val;
>  
>  	switch (mask) {
>  	case IIO_CHAN_INFO_RAW:
> @@ -277,17 +373,24 @@ static int sca3300_read_raw(struct iio_dev *indio_dev,
>  			return ret;
>  		return IIO_VAL_INT;
>  	case IIO_CHAN_INFO_SCALE:
> -		ret = sca3300_read_reg(data, SCA3300_REG_MODE, &reg_val);
> +		ret = sca3300_get_op_mode(data, &index);
>  		if (ret)
>  			return ret;
> -		*val = 0;
> -		*val2 = sca3300_accel_scale[reg_val][1];
> -		return IIO_VAL_INT_PLUS_MICRO;
> +		switch (chan->type) {
> +		case IIO_ACCEL:
> +			index = data->chip->accel_scale_map[index];
> +			*val  = data->chip->accel_scale[index][0];
> +			*val2 = data->chip->accel_scale[index][1];
> +			return IIO_VAL_INT_PLUS_MICRO;
> +		default:
> +			return -EINVAL;
> +		}
>  	case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
> -		ret = sca3300_read_reg(data, SCA3300_REG_MODE, &reg_val);
> +		ret = sca3300_get_op_mode(data, &index);
>  		if (ret)
>  			return ret;
> -		*val = sca3300_lp_freq[reg_val];
> +		index = data->chip->freq_map[index];
> +		*val = data->chip->freq_table[index];
>  		return IIO_VAL_INT;
>  	default:
>  		return -EINVAL;
> @@ -331,6 +434,7 @@ static int sca3300_init(struct sca3300_data *sca_data,
>  {
>  	int value = 0;
>  	int ret;
> +	int i;
>  
>  	ret = sca3300_write_reg(sca_data, SCA3300_REG_MODE,
>  				SCA3300_MODE_SW_RESET);
> @@ -347,12 +451,17 @@ static int sca3300_init(struct sca3300_data *sca_data,
>  	if (ret)
>  		return ret;
>  
> -	if (value != SCA3300_WHOAMI_ID) {
> -		dev_err(&sca_data->spi->dev,
> -			"device id not expected value, %d != %u\n",
> -			value, SCA3300_WHOAMI_ID);
> +	for (i = 0; i < ARRAY_SIZE(sca3300_chip_tbl); i++) {
> +		if (sca3300_chip_tbl[i].chip_id == value)
> +			break;
> +	}
> +	if (i == ARRAY_SIZE(sca3300_chip_tbl)) {
> +		dev_err(&sca_data->spi->dev, "unknown chip id %x\n", value);
>  		return -ENODEV;
>  	}
> +
> +	sca_data->chip = &sca3300_chip_tbl[i];
> +
>  	return 0;
>  }
>  
> @@ -384,15 +493,21 @@ static int sca3300_read_avail(struct iio_dev *indio_dev,
>  			      const int **vals, int *type, int *length,
>  			      long mask)
>  {
> +	struct sca3300_data *data = iio_priv(indio_dev);
>  	switch (mask) {
>  	case IIO_CHAN_INFO_SCALE:
> -		*vals = (const int *)sca3300_accel_scale;
> -		*length = ARRAY_SIZE(sca3300_accel_scale) * 2 - 2;
> -		*type = IIO_VAL_INT_PLUS_MICRO;
> -		return IIO_AVAIL_LIST;
> +		switch (chan->type) {
> +		case IIO_ACCEL:
> +			*vals = (const int *)data->chip->accel_scale;
> +			*length = data->chip->num_accel_scales;
> +			*type = IIO_VAL_INT_PLUS_MICRO;
> +			return IIO_AVAIL_LIST;
> +		default:
> +			return -EINVAL;
> +		}
>  	case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
> -		*vals = &sca3300_lp_freq[2];
> -		*length = 2;
> +		*vals = (const int *)data->chip->freq_table;
> +		*length = data->chip->num_freqs;
>  		*type = IIO_VAL_INT;
>  		return IIO_AVAIL_LIST;
>  	default:
> @@ -424,11 +539,6 @@ static int sca3300_probe(struct spi_device *spi)
>  	crc8_populate_msb(sca3300_crc_table, SCA3300_CRC8_POLYNOMIAL);
>  
>  	indio_dev->info = &sca3300_info;
> -	indio_dev->name = SCA3300_ALIAS;
> -	indio_dev->modes = INDIO_DIRECT_MODE;
> -	indio_dev->channels = sca3300_channels;
> -	indio_dev->num_channels = ARRAY_SIZE(sca3300_channels);
> -	indio_dev->available_scan_masks = sca3300_scan_masks;
>  
>  	ret = sca3300_init(sca_data, indio_dev);
>  	if (ret) {
> @@ -436,6 +546,12 @@ static int sca3300_probe(struct spi_device *spi)
>  		return ret;
>  	}
>  
> +	indio_dev->name = sca_data->chip->name;
> +	indio_dev->modes = INDIO_DIRECT_MODE;
> +	indio_dev->channels = sca_data->chip->channels;
> +	indio_dev->num_channels = sca_data->chip->num_channels;
> +	indio_dev->available_scan_masks = sca_data->chip->scan_masks;
> +
>  	ret = devm_iio_triggered_buffer_setup(&spi->dev, indio_dev,
>  					      iio_pollfunc_store_time,
>  					      sca3300_trigger_handler, NULL);

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH V8 4/5] iio: accel: sca3300: Add support for SCL3300
  2022-05-23  6:23 ` [PATCH V8 4/5] iio: accel: sca3300: Add support for SCL3300 LI Qingwu
@ 2022-05-25 10:08   ` Tomas Melin
  0 siblings, 0 replies; 9+ messages in thread
From: Tomas Melin @ 2022-05-25 10:08 UTC (permalink / raw)
  To: LI Qingwu, jic23, lars, robh+dt, andy.shevchenko, devicetree,
	linux-kernel
  Cc: thomas.haemmerle, linux-iio



On 23/05/2022 09:23, LI Qingwu wrote:
> Add support for Murata SCL3300, a 3-axis MEMS accelerometer.
> Same as SCA3300, it has the accelerometer and temperature output.
> 
> Datasheet: www.murata.com/en-us/products/sensor/inclinometer/overview/lineup/scl3300
> Signed-off-by: LI Qingwu <Qing-wu.Li@leica-geosystems.com.cn>
> ---
>  drivers/iio/accel/sca3300.c | 31 +++++++++++++++++++++++++++++--
>  1 file changed, 29 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/iio/accel/sca3300.c b/drivers/iio/accel/sca3300.c
> index 6463d12a9ab9..74e780a7ffcd 100644
> --- a/drivers/iio/accel/sca3300.c
> +++ b/drivers/iio/accel/sca3300.c
> @@ -38,6 +38,7 @@
>  /* Device ID */
>  #define SCA3300_REG_WHOAMI	0x10
>  #define SCA3300_WHOAMI_ID	0x51
> +#define SCL3300_WHOAMI_ID	0xC1
>  
>  /* Device return status and mask */
>  #define SCA3300_VALUE_RS_ERROR	0x3
> @@ -96,10 +97,18 @@ static const struct iio_chan_spec sca3300_channels[] = {
>  static const int sca3300_lp_freq[] = {70, 10};
>  static const int sca3300_lp_freq_map[] = {0, 0, 0, 1};
>  
> +static const int scl3300_lp_freq[] = {40, 70, 10};
> +static const int scl3300_lp_freq_map[] = {0, 1, 2};
> +
>  static const int sca3300_accel_scale[][2] = {{0, 370}, {0, 741}, {0, 185}};
>  static const int sca3300_accel_scale_map[] = {0, 1, 2, 2};
>  
> +static const int scl3300_accel_scale[][2] = {{0, 167}, {0, 333}, {0, 83}};
> +static const int scl3300_accel_scale_map[] = {0, 1, 2};
> +
>  static const int sca3300_avail_modes_map[] = {0, 1, 2, 3};
> +static const int scl3300_avail_modes_map[] = {0, 1, 3};
> +
>  static const unsigned long sca3300_scan_masks[] = {
>  	BIT(SCA3300_ACC_X) | BIT(SCA3300_ACC_Y) | BIT(SCA3300_ACC_Z) |
>  	BIT(SCA3300_TEMP),
> @@ -159,6 +168,21 @@ static const struct sca3300_chip_info sca3300_chip_tbl[] = {
>  		.num_avail_modes = 4,
>  		.chip_id = SCA3300_WHOAMI_ID,
>  	},
> +	{
> +		.name = "scl3300",
> +		.scan_masks = sca3300_scan_masks,
> +		.channels = sca3300_channels,
> +		.num_channels = ARRAY_SIZE(sca3300_channels),
> +		.num_accel_scales = ARRAY_SIZE(scl3300_accel_scale)*2,
> +		.accel_scale = scl3300_accel_scale,
> +		.accel_scale_map = scl3300_accel_scale_map,
> +		.num_freqs = ARRAY_SIZE(scl3300_lp_freq),
> +		.freq_table = scl3300_lp_freq,
> +		.freq_map = scl3300_lp_freq_map,
> +		.avail_modes_table = scl3300_avail_modes_map,
> +		.num_avail_modes = 3,
> +		.chip_id = SCL3300_WHOAMI_ID,
> +	},
>  };
>  
>  DECLARE_CRC8_TABLE(sca3300_crc_table);
> @@ -443,9 +467,11 @@ static int sca3300_init(struct sca3300_data *sca_data,
>  
>  	/*
>  	 * Wait 1ms after SW-reset command.
> -	 * Wait 15ms for settling of signal paths.
> +	 * Wait for the settling of signal paths,
> +	 * 15ms for SCA3300 and 25ms for SCL3300,

> +	 * take the max of the then.
There is now a typo here, but I think this line could be left out
altogether. i.e.

> +	 * Wait for the settling of signal paths,
> +	 * 15ms for SCA3300 and 25ms for SCL3300.


Thanks,
Tomas

>  	 */
> -	usleep_range(16e3, 50e3);
> +	usleep_range(26e3, 50e3);
>  
>  	ret = sca3300_read_reg(sca_data, SCA3300_REG_WHOAMI, &value);
>  	if (ret)
> @@ -572,6 +598,7 @@ static int sca3300_probe(struct spi_device *spi)
>  
>  static const struct of_device_id sca3300_dt_ids[] = {
>  	{ .compatible = "murata,sca3300"},
> +	{ .compatible = "murata,scl3300"},
>  	{}
>  };
>  MODULE_DEVICE_TABLE(of, sca3300_dt_ids);

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH V8 5/5] iio: accel: sca3300: Add inclination channels
  2022-05-23  6:23 ` [PATCH V8 5/5] iio: accel: sca3300: Add inclination channels LI Qingwu
@ 2022-05-28 17:23   ` Jonathan Cameron
  0 siblings, 0 replies; 9+ messages in thread
From: Jonathan Cameron @ 2022-05-28 17:23 UTC (permalink / raw)
  To: LI Qingwu
  Cc: lars, robh+dt, tomas.melin, andy.shevchenko, devicetree,
	linux-kernel, thomas.haemmerle, linux-iio

On Mon, 23 May 2022 06:23:12 +0000
LI Qingwu <Qing-wu.Li@leica-geosystems.com.cn> wrote:

> Different from SCA3300, SCL3300 can output inclination angles.
> Angles are formed from acceleration with following equations:
> ANG_X = atan2(accx , sqrt(pow(accy , 2) + pow(accz , 2)))
> ANG_Y = atan2(accy , sqrt(pow(accx , 2) + pow(accz , 2)))
> ANG_Z = atan2(accz , sqrt(pow(accx , 2) + pow(accy , 2)))
> 
> The commit adds the output of the raw value, scale
> and scale_available of angles.
> 
> New interfaces:
>   in_incli_scale
>   in_incli_scale_available
>   in_incli_x_raw
>   in_incli_y_raw
>   in_incli_z_raw
> Data converted by application of scale to degrees.
> 
> Signed-off-by: LI Qingwu <Qing-wu.Li@leica-geosystems.com.cn>
> ---

Hi,

One comment inline.

>  struct sca3300_chip_info {
>  	const char *name;
>  	const unsigned long *scan_masks;
> @@ -123,12 +167,16 @@ struct sca3300_chip_info {
>  	u8 num_accel_scales;
>  	const int (*accel_scale)[2];
>  	const int *accel_scale_map;
> +	const int (*incli_scale)[2];
> +	const int *incli_scale_map;
> +	u8 num_incli_scales;
>  	u8 num_freqs;
>  	const int *freq_table;
>  	const int *freq_map;
>  	const int *avail_modes_table;
>  	u8 num_avail_modes;
>  	u8 chip_id;
> +	bool angle;

"angle" is a bit vague.  Perhaps "angle_supported"?

Otherwise this looks good to me.

Thanks,

Jonathan


^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2022-05-28 17:14 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-05-23  6:23 [PATCH V8 0/5] iio: accel: sca3300: add compatible for scl3300 LI Qingwu
2022-05-23  6:23 ` [PATCH V8 1/5] dt-bindings: iio: accel: sca3300: Document murata,scl3300 LI Qingwu
2022-05-23  6:23 ` [PATCH V8 2/5] iio: accel: sca3300: add define for temp channel for reuse LI Qingwu
2022-05-23  6:23 ` [PATCH V8 3/5] iio: accel: sca3300: modified to support multi chips LI Qingwu
2022-05-25  9:59   ` Tomas Melin
2022-05-23  6:23 ` [PATCH V8 4/5] iio: accel: sca3300: Add support for SCL3300 LI Qingwu
2022-05-25 10:08   ` Tomas Melin
2022-05-23  6:23 ` [PATCH V8 5/5] iio: accel: sca3300: Add inclination channels LI Qingwu
2022-05-28 17:23   ` 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).