diff mbox series

iio: imu: bmi270: add temperature channel

Message ID 20250111-bmi270-temp-v1-1-76ee38211bf2@gmail.com (mailing list archive)
State New
Headers show
Series iio: imu: bmi270: add temperature channel | expand

Commit Message

Gustavo Silva Jan. 11, 2025, 5:26 p.m. UTC
The BMI270 IMU includes a temperature sensor. Add a channel for reading
the temperature.

Signed-off-by: Gustavo Silva <gustavograzs@gmail.com>
---
 drivers/iio/imu/bmi270/bmi270_core.c | 49 ++++++++++++++++++++++++++++++++----
 1 file changed, 44 insertions(+), 5 deletions(-)


---
base-commit: 577a66e2e634f712384c57a98f504c44ea4b47da
change-id: 20250111-bmi270-temp-e9d253619180

Best regards,

Comments

Jonathan Cameron Jan. 12, 2025, 4:27 p.m. UTC | #1
On Sat, 11 Jan 2025 14:26:18 -0300
Gustavo Silva <gustavograzs@gmail.com> wrote:

> The BMI270 IMU includes a temperature sensor. Add a channel for reading
> the temperature.
> 
> Signed-off-by: Gustavo Silva <gustavograzs@gmail.com>
Hi Gustavo,

A few minor comments inline,

Thanks,

Jonathan

> ---
>  drivers/iio/imu/bmi270/bmi270_core.c | 49 ++++++++++++++++++++++++++++++++----
>  1 file changed, 44 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/iio/imu/bmi270/bmi270_core.c b/drivers/iio/imu/bmi270/bmi270_core.c
> index 7fec52e0b48624f07031b63a9caf6c318f33f5dc..c7853923aa69f83a829a71979135f1f7a7ef29ec 100644
> --- a/drivers/iio/imu/bmi270/bmi270_core.c
> +++ b/drivers/iio/imu/bmi270/bmi270_core.c
> @@ -5,6 +5,7 @@
>  #include <linux/i2c.h>
>  #include <linux/module.h>
>  #include <linux/regmap.h>
> +#include <linux/units.h>
>  
>  #include <linux/iio/iio.h>
>  #include <linux/iio/sysfs.h>
> @@ -28,10 +29,11 @@
>  #define BMI270_INTERNAL_STATUS_REG			0x21
>  #define BMI270_INTERNAL_STATUS_MSG_MSK			GENMASK(3, 0)
>  #define BMI270_INTERNAL_STATUS_MSG_INIT_OK		0x01
> -
>  #define BMI270_INTERNAL_STATUS_AXES_REMAP_ERR_MSK	BIT(5)
>  #define BMI270_INTERNAL_STATUS_ODR_50HZ_ERR_MSK		BIT(6)
>  
> +#define BMI270_TEMPERATURE_0_REG			0x22
> +
>  #define BMI270_ACC_CONF_REG				0x40
>  #define BMI270_ACC_CONF_ODR_MSK				GENMASK(3, 0)
>  #define BMI270_ACC_CONF_ODR_100HZ			0x08
> @@ -69,6 +71,10 @@
>  #define BMI270_PWR_CTRL_ACCEL_EN_MSK			BIT(2)
>  #define BMI270_PWR_CTRL_TEMP_EN_MSK			BIT(3)
>  
> +/* See datasheet section 4.6.14, Temperature Sensor */
> +#define BMI270_TEMP_OFFSET				11776
> +#define BMI270_TEMP_SCALE				1953125
> +
>  #define BMI260_INIT_DATA_FILE "bmi260-init-data.fw"
>  #define BMI270_INIT_DATA_FILE "bmi270-init-data.fw"
>  
> @@ -109,6 +115,7 @@ EXPORT_SYMBOL_NS_GPL(bmi270_chip_info, "IIO_BMI270");
>  enum bmi270_sensor_type {
>  	BMI270_ACCEL	= 0,
>  	BMI270_GYRO,
> +	BMI270_TEMP,
>  };
>  
>  struct bmi270_scale {
> @@ -136,6 +143,10 @@ static const struct bmi270_scale bmi270_gyro_scale[] = {
>  	{ 0, 66 },
>  };
>  
> +static const struct bmi270_scale bmi270_temp_scale[] = {
> +	{BMI270_TEMP_SCALE / MEGA, BMI270_TEMP_SCALE % MEGA},

	{ BMI270_TEMP_SCALE / MEGA, BMI270_TEMP_SCALE % MEGA },

Maybe MICRO is the better choice (and same value).

 
> +};
> +
>  struct bmi270_scale_item {
>  	const struct bmi270_scale *tbl;
>  	int num;
> @@ -150,6 +161,10 @@ static const struct bmi270_scale_item bmi270_scale_table[] = {
>  		.tbl	= bmi270_gyro_scale,
>  		.num	= ARRAY_SIZE(bmi270_gyro_scale),
>  	},
> +	[BMI270_TEMP] = {
> +		.tbl	= bmi270_temp_scale,
> +		.num	= ARRAY_SIZE(bmi270_temp_scale),
> +	},
>  };
>  
>  static const struct bmi270_odr bmi270_accel_odr[] = {
> @@ -255,7 +270,7 @@ static int bmi270_set_scale(struct bmi270_data *data, int chan_type, int uscale)
>  }
>  
>  static int bmi270_get_scale(struct bmi270_data *bmi270_device, int chan_type,
> -			    int *uscale)
> +			    int *scale, int *uscale)
>  {
>  	int ret;
>  	unsigned int val;
> @@ -280,6 +295,10 @@ static int bmi270_get_scale(struct bmi270_data *bmi270_device, int chan_type,
>  		val = FIELD_GET(BMI270_GYR_CONF_RANGE_MSK, val);
>  		bmi270_scale_item = bmi270_scale_table[BMI270_GYRO];
>  		break;
> +	case IIO_TEMP:
> +		val = 0;
> +		bmi270_scale_item = bmi270_scale_table[BMI270_TEMP];
> +		break;
>  	default:
>  		return -EINVAL;
>  	}
> @@ -287,6 +306,7 @@ static int bmi270_get_scale(struct bmi270_data *bmi270_device, int chan_type,
>  	if (val >= bmi270_scale_item.num)
>  		return -EINVAL;
>  
> +	*scale = bmi270_scale_item.tbl[val].scale;
>  	*uscale = bmi270_scale_item.tbl[val].uscale;
>  	return 0;
>  }
> @@ -399,6 +419,9 @@ static int bmi270_get_data(struct bmi270_data *bmi270_device,
>  	case IIO_ANGL_VEL:
>  		reg = BMI270_ANG_VEL_X_REG + (axis - IIO_MOD_X) * 2;
>  		break;
> +	case IIO_TEMP:
> +		reg = BMI270_TEMPERATURE_0_REG;
> +		break;
>  	default:
>  		return -EINVAL;
>  	}
> @@ -427,12 +450,20 @@ static int bmi270_read_raw(struct iio_dev *indio_dev,
>  
>  		return IIO_VAL_INT;
>  	case IIO_CHAN_INFO_SCALE:
> -		*val = 0;
> -		ret = bmi270_get_scale(bmi270_device, chan->type, val2);
> +		ret = bmi270_get_scale(bmi270_device, chan->type, val, val2);
>  		return ret ? ret : IIO_VAL_INT_PLUS_MICRO;
> +	case IIO_CHAN_INFO_OFFSET:
> +		switch (chan->type) {
> +		case IIO_TEMP:
> +			*val = BMI270_TEMP_OFFSET;
> +			return IIO_VAL_INT;
> +		default:
> +			return -EINVAL;
> +		}
>  	case IIO_CHAN_INFO_SAMP_FREQ:
>  		ret = bmi270_get_odr(bmi270_device, chan->type, val, val2);
>  		return ret ? ret : IIO_VAL_INT_PLUS_MICRO;
> +

Unrelated change.  Good to remove these before posting a patch as it
just adds noise.  If you want to tidy up white space that is fine but
not in the same patch as anything making functional changes.

>  	default:
>  		return -EINVAL;
>  	}
> @@ -544,6 +575,13 @@ static const struct iio_chan_spec bmi270_channels[] = {
>  	BMI270_ANG_VEL_CHANNEL(X),
>  	BMI270_ANG_VEL_CHANNEL(Y),
>  	BMI270_ANG_VEL_CHANNEL(Z),
> +	{
> +		.type = IIO_TEMP,
> +		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
> +				      BIT(IIO_CHAN_INFO_SCALE) |
> +				      BIT(IIO_CHAN_INFO_OFFSET),
> +		.scan_index = -1, /* No buffer support */
> +	},
>  	IIO_CHAN_SOFT_TIMESTAMP(BMI270_SCAN_TIMESTAMP),
>  };
>  
> @@ -646,7 +684,8 @@ static int bmi270_configure_imu(struct bmi270_data *bmi270_device)
>  	ret = regmap_set_bits(regmap, BMI270_PWR_CTRL_REG,
>  			      BMI270_PWR_CTRL_AUX_EN_MSK |
>  			      BMI270_PWR_CTRL_GYR_EN_MSK |
> -			      BMI270_PWR_CTRL_ACCEL_EN_MSK);
> +			      BMI270_PWR_CTRL_ACCEL_EN_MSK |
> +			      BMI270_PWR_CTRL_TEMP_EN_MSK);
>  	if (ret)
>  		return dev_err_probe(dev, ret, "Failed to enable accelerometer and gyroscope");
>  
> 
> ---
> base-commit: 577a66e2e634f712384c57a98f504c44ea4b47da
> change-id: 20250111-bmi270-temp-e9d253619180
> 
> Best regards,
diff mbox series

Patch

diff --git a/drivers/iio/imu/bmi270/bmi270_core.c b/drivers/iio/imu/bmi270/bmi270_core.c
index 7fec52e0b48624f07031b63a9caf6c318f33f5dc..c7853923aa69f83a829a71979135f1f7a7ef29ec 100644
--- a/drivers/iio/imu/bmi270/bmi270_core.c
+++ b/drivers/iio/imu/bmi270/bmi270_core.c
@@ -5,6 +5,7 @@ 
 #include <linux/i2c.h>
 #include <linux/module.h>
 #include <linux/regmap.h>
+#include <linux/units.h>
 
 #include <linux/iio/iio.h>
 #include <linux/iio/sysfs.h>
@@ -28,10 +29,11 @@ 
 #define BMI270_INTERNAL_STATUS_REG			0x21
 #define BMI270_INTERNAL_STATUS_MSG_MSK			GENMASK(3, 0)
 #define BMI270_INTERNAL_STATUS_MSG_INIT_OK		0x01
-
 #define BMI270_INTERNAL_STATUS_AXES_REMAP_ERR_MSK	BIT(5)
 #define BMI270_INTERNAL_STATUS_ODR_50HZ_ERR_MSK		BIT(6)
 
+#define BMI270_TEMPERATURE_0_REG			0x22
+
 #define BMI270_ACC_CONF_REG				0x40
 #define BMI270_ACC_CONF_ODR_MSK				GENMASK(3, 0)
 #define BMI270_ACC_CONF_ODR_100HZ			0x08
@@ -69,6 +71,10 @@ 
 #define BMI270_PWR_CTRL_ACCEL_EN_MSK			BIT(2)
 #define BMI270_PWR_CTRL_TEMP_EN_MSK			BIT(3)
 
+/* See datasheet section 4.6.14, Temperature Sensor */
+#define BMI270_TEMP_OFFSET				11776
+#define BMI270_TEMP_SCALE				1953125
+
 #define BMI260_INIT_DATA_FILE "bmi260-init-data.fw"
 #define BMI270_INIT_DATA_FILE "bmi270-init-data.fw"
 
@@ -109,6 +115,7 @@  EXPORT_SYMBOL_NS_GPL(bmi270_chip_info, "IIO_BMI270");
 enum bmi270_sensor_type {
 	BMI270_ACCEL	= 0,
 	BMI270_GYRO,
+	BMI270_TEMP,
 };
 
 struct bmi270_scale {
@@ -136,6 +143,10 @@  static const struct bmi270_scale bmi270_gyro_scale[] = {
 	{ 0, 66 },
 };
 
+static const struct bmi270_scale bmi270_temp_scale[] = {
+	{BMI270_TEMP_SCALE / MEGA, BMI270_TEMP_SCALE % MEGA},
+};
+
 struct bmi270_scale_item {
 	const struct bmi270_scale *tbl;
 	int num;
@@ -150,6 +161,10 @@  static const struct bmi270_scale_item bmi270_scale_table[] = {
 		.tbl	= bmi270_gyro_scale,
 		.num	= ARRAY_SIZE(bmi270_gyro_scale),
 	},
+	[BMI270_TEMP] = {
+		.tbl	= bmi270_temp_scale,
+		.num	= ARRAY_SIZE(bmi270_temp_scale),
+	},
 };
 
 static const struct bmi270_odr bmi270_accel_odr[] = {
@@ -255,7 +270,7 @@  static int bmi270_set_scale(struct bmi270_data *data, int chan_type, int uscale)
 }
 
 static int bmi270_get_scale(struct bmi270_data *bmi270_device, int chan_type,
-			    int *uscale)
+			    int *scale, int *uscale)
 {
 	int ret;
 	unsigned int val;
@@ -280,6 +295,10 @@  static int bmi270_get_scale(struct bmi270_data *bmi270_device, int chan_type,
 		val = FIELD_GET(BMI270_GYR_CONF_RANGE_MSK, val);
 		bmi270_scale_item = bmi270_scale_table[BMI270_GYRO];
 		break;
+	case IIO_TEMP:
+		val = 0;
+		bmi270_scale_item = bmi270_scale_table[BMI270_TEMP];
+		break;
 	default:
 		return -EINVAL;
 	}
@@ -287,6 +306,7 @@  static int bmi270_get_scale(struct bmi270_data *bmi270_device, int chan_type,
 	if (val >= bmi270_scale_item.num)
 		return -EINVAL;
 
+	*scale = bmi270_scale_item.tbl[val].scale;
 	*uscale = bmi270_scale_item.tbl[val].uscale;
 	return 0;
 }
@@ -399,6 +419,9 @@  static int bmi270_get_data(struct bmi270_data *bmi270_device,
 	case IIO_ANGL_VEL:
 		reg = BMI270_ANG_VEL_X_REG + (axis - IIO_MOD_X) * 2;
 		break;
+	case IIO_TEMP:
+		reg = BMI270_TEMPERATURE_0_REG;
+		break;
 	default:
 		return -EINVAL;
 	}
@@ -427,12 +450,20 @@  static int bmi270_read_raw(struct iio_dev *indio_dev,
 
 		return IIO_VAL_INT;
 	case IIO_CHAN_INFO_SCALE:
-		*val = 0;
-		ret = bmi270_get_scale(bmi270_device, chan->type, val2);
+		ret = bmi270_get_scale(bmi270_device, chan->type, val, val2);
 		return ret ? ret : IIO_VAL_INT_PLUS_MICRO;
+	case IIO_CHAN_INFO_OFFSET:
+		switch (chan->type) {
+		case IIO_TEMP:
+			*val = BMI270_TEMP_OFFSET;
+			return IIO_VAL_INT;
+		default:
+			return -EINVAL;
+		}
 	case IIO_CHAN_INFO_SAMP_FREQ:
 		ret = bmi270_get_odr(bmi270_device, chan->type, val, val2);
 		return ret ? ret : IIO_VAL_INT_PLUS_MICRO;
+
 	default:
 		return -EINVAL;
 	}
@@ -544,6 +575,13 @@  static const struct iio_chan_spec bmi270_channels[] = {
 	BMI270_ANG_VEL_CHANNEL(X),
 	BMI270_ANG_VEL_CHANNEL(Y),
 	BMI270_ANG_VEL_CHANNEL(Z),
+	{
+		.type = IIO_TEMP,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+				      BIT(IIO_CHAN_INFO_SCALE) |
+				      BIT(IIO_CHAN_INFO_OFFSET),
+		.scan_index = -1, /* No buffer support */
+	},
 	IIO_CHAN_SOFT_TIMESTAMP(BMI270_SCAN_TIMESTAMP),
 };
 
@@ -646,7 +684,8 @@  static int bmi270_configure_imu(struct bmi270_data *bmi270_device)
 	ret = regmap_set_bits(regmap, BMI270_PWR_CTRL_REG,
 			      BMI270_PWR_CTRL_AUX_EN_MSK |
 			      BMI270_PWR_CTRL_GYR_EN_MSK |
-			      BMI270_PWR_CTRL_ACCEL_EN_MSK);
+			      BMI270_PWR_CTRL_ACCEL_EN_MSK |
+			      BMI270_PWR_CTRL_TEMP_EN_MSK);
 	if (ret)
 		return dev_err_probe(dev, ret, "Failed to enable accelerometer and gyroscope");