diff mbox series

[v3,3/4] iio: temperature: tmp117: add TI TMP116 support

Message ID 20230217093711.1891564-4-m.felsch@pengutronix.de
State New
Headers show
Series [v3,1/4] dt-bindings: iio: ti,tmp117: fix documentation link | expand

Commit Message

Marco Felsch Feb. 17, 2023, 9:37 a.m. UTC
The TMP116 is the predecessor of the TMP117. The TMP116 don't support
custom offset calibration data, instead this register is used as generic
EEPROM storage as well.

Signed-off-by: Marco Felsch <m.felsch@pengutronix.de>
---
v3:
- use switch case within probe() as well
- don't hide smbus_read error within tmp117_identify()
- add dedicated compatible

v2:
- no changes

 drivers/iio/temperature/tmp117.c | 46 ++++++++++++++++++++++++--------
 1 file changed, 35 insertions(+), 11 deletions(-)

Comments

Jonathan Cameron Feb. 18, 2023, 5:04 p.m. UTC | #1
On Fri, 17 Feb 2023 10:37:10 +0100
Marco Felsch <m.felsch@pengutronix.de> wrote:

> The TMP116 is the predecessor of the TMP117. The TMP116 don't support
> custom offset calibration data, instead this register is used as generic
> EEPROM storage as well.
> 
> Signed-off-by: Marco Felsch <m.felsch@pengutronix.de>

I failed to notice that the handling of fallback compatibles (not
related to the fact we can't use them for the TMP116 as discussed)
is less than ideal in the original driver.

Given it already doesn't work, I'm fine with handling that in a
a separate patch though if you would prefer. If you don't get to
it I might eventually do so.  There are a lot of cases of this
in IIO, but mostly we don't bother fixing them unless we are touching
the driver for other reasons.

I can fix the trivial alphabetical order thing up whilst applying.

Thanks,

Jonathan


> ---
> v3:
> - use switch case within probe() as well
> - don't hide smbus_read error within tmp117_identify()
> - add dedicated compatible
> 
> v2:
> - no changes
> 
>  drivers/iio/temperature/tmp117.c | 46 ++++++++++++++++++++++++--------
>  1 file changed, 35 insertions(+), 11 deletions(-)
> 
> diff --git a/drivers/iio/temperature/tmp117.c b/drivers/iio/temperature/tmp117.c
> index f9b8f2b570f6b..728538fbaf9ba 100644
> --- a/drivers/iio/temperature/tmp117.c
> +++ b/drivers/iio/temperature/tmp117.c
> @@ -31,9 +31,11 @@
>  #define TMP117_REG_DEVICE_ID		0xF
>  
>  #define TMP117_RESOLUTION_10UC		78125
> -#define TMP117_DEVICE_ID		0x0117
>  #define MICRODEGREE_PER_10MILLIDEGREE	10000
>  
> +#define TMP116_DEVICE_ID		0x1116
> +#define TMP117_DEVICE_ID		0x0117
> +
>  struct tmp117_data {
>  	struct i2c_client *client;
>  	s16 calibbias;
> @@ -105,6 +107,13 @@ static const struct iio_chan_spec tmp117_channels[] = {
>  		.type = IIO_TEMP,
>  		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
>  			BIT(IIO_CHAN_INFO_CALIBBIAS) | BIT(IIO_CHAN_INFO_SCALE),
> +};
> +
> +static const struct iio_chan_spec tmp116_channels[] = {
> +	{
> +		.type = IIO_TEMP,
> +		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
> +				      BIT(IIO_CHAN_INFO_SCALE),
>  	},
>  };
>  
> @@ -120,25 +129,29 @@ static int tmp117_identify(struct i2c_client *client)
>  	dev_id = i2c_smbus_read_word_swapped(client, TMP117_REG_DEVICE_ID);
>  	if (dev_id < 0)
>  		return dev_id;
> -	if (dev_id != TMP117_DEVICE_ID) {
> -		dev_err(&client->dev, "TMP117 not found\n");
> +
> +	switch (dev_id) {
> +	case TMP116_DEVICE_ID:
> +	case TMP117_DEVICE_ID:
> +		return dev_id;
> +	default:
> +		dev_err(&client->dev, "TMP116/117 not found\n");

More a comment on the original code rather than your changes, but we should fix
if whilst here...

So this is always fun.  Ideally if we don't match a known device we should trust
the compatible provided.  The intent here is that if a new device turns up
with a different ID and does indeed have a valid fallback compatible then
the driver should work. It's fine to warn, but we shouldn't fail the probe.

As such a dance is needed.  First we need to associate some data with the
device IDs (see below)

>  		return -ENODEV;
>  	}
> -	return 0;
>  }
>  
>  static int tmp117_probe(struct i2c_client *client)
>  {
>  	struct tmp117_data *data;
>  	struct iio_dev *indio_dev;
> -	int ret;
> +	int dev_id;
>  
>  	if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_WORD_DATA))
>  		return -EOPNOTSUPP;
>  
> -	ret = tmp117_identify(client);
> -	if (ret < 0)
> -		return ret;
> +	dev_id = tmp117_identify(client);
> +	if (dev_id < 0)

Fallback ID related. See above. If this happens we should not error out,
but rather fallback on assumption that the provided compatible is correct
even though we don't know the new dev_id.  So look up the data here.
Prefer data from the device_property_get_match_data() and if that fails
fallback to i2c_client_get_device_id() and the data field from that.


> +		return dev_id;
>  
>  	indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
>  	if (!indio_dev)
> @@ -148,24 +161,35 @@ static int tmp117_probe(struct i2c_client *client)
>  	data->client = client;
>  	data->calibbias = 0;
>  
> -	indio_dev->name = "tmp117";
>  	indio_dev->modes = INDIO_DIRECT_MODE;
>  	indio_dev->info = &tmp117_info;
>  
> -	indio_dev->channels = tmp117_channels;
> -	indio_dev->num_channels = ARRAY_SIZE(tmp117_channels);
> +	switch (dev_id) {
> +	case TMP116_DEVICE_ID:
> +		indio_dev->channels = tmp116_channels;
> +		indio_dev->num_channels = ARRAY_SIZE(tmp116_channels);
> +		indio_dev->name = "tmp116";
> +		break;
> +	case TMP117_DEVICE_ID:
> +		indio_dev->channels = tmp117_channels;
> +		indio_dev->num_channels = ARRAY_SIZE(tmp117_channels);
> +		indio_dev->name = "tmp117";
> +		break;
> +	}
>  
>  	return devm_iio_device_register(&client->dev, indio_dev);
>  }
>  
>  static const struct of_device_id tmp117_of_match[] = {
>  	{ .compatible = "ti,tmp117", },
> +	{ .compatible = "ti,tmp116", },

Alphabetical order preferred.

Data here as below.

>  	{ }
>  };
>  MODULE_DEVICE_TABLE(of, tmp117_of_match);
>  
>  static const struct i2c_device_id tmp117_id[] = {
>  	{ "tmp117", 0 },
> +	{ "tmp116", 0 },
Follow on from above: This needs data to distinguish the two so we can
support future fallback compatibles to one of these.
>  	{ }
>  };
>  MODULE_DEVICE_TABLE(i2c, tmp117_id);
diff mbox series

Patch

diff --git a/drivers/iio/temperature/tmp117.c b/drivers/iio/temperature/tmp117.c
index f9b8f2b570f6b..728538fbaf9ba 100644
--- a/drivers/iio/temperature/tmp117.c
+++ b/drivers/iio/temperature/tmp117.c
@@ -31,9 +31,11 @@ 
 #define TMP117_REG_DEVICE_ID		0xF
 
 #define TMP117_RESOLUTION_10UC		78125
-#define TMP117_DEVICE_ID		0x0117
 #define MICRODEGREE_PER_10MILLIDEGREE	10000
 
+#define TMP116_DEVICE_ID		0x1116
+#define TMP117_DEVICE_ID		0x0117
+
 struct tmp117_data {
 	struct i2c_client *client;
 	s16 calibbias;
@@ -105,6 +107,13 @@  static const struct iio_chan_spec tmp117_channels[] = {
 		.type = IIO_TEMP,
 		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
 			BIT(IIO_CHAN_INFO_CALIBBIAS) | BIT(IIO_CHAN_INFO_SCALE),
+};
+
+static const struct iio_chan_spec tmp116_channels[] = {
+	{
+		.type = IIO_TEMP,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+				      BIT(IIO_CHAN_INFO_SCALE),
 	},
 };
 
@@ -120,25 +129,29 @@  static int tmp117_identify(struct i2c_client *client)
 	dev_id = i2c_smbus_read_word_swapped(client, TMP117_REG_DEVICE_ID);
 	if (dev_id < 0)
 		return dev_id;
-	if (dev_id != TMP117_DEVICE_ID) {
-		dev_err(&client->dev, "TMP117 not found\n");
+
+	switch (dev_id) {
+	case TMP116_DEVICE_ID:
+	case TMP117_DEVICE_ID:
+		return dev_id;
+	default:
+		dev_err(&client->dev, "TMP116/117 not found\n");
 		return -ENODEV;
 	}
-	return 0;
 }
 
 static int tmp117_probe(struct i2c_client *client)
 {
 	struct tmp117_data *data;
 	struct iio_dev *indio_dev;
-	int ret;
+	int dev_id;
 
 	if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_WORD_DATA))
 		return -EOPNOTSUPP;
 
-	ret = tmp117_identify(client);
-	if (ret < 0)
-		return ret;
+	dev_id = tmp117_identify(client);
+	if (dev_id < 0)
+		return dev_id;
 
 	indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
 	if (!indio_dev)
@@ -148,24 +161,35 @@  static int tmp117_probe(struct i2c_client *client)
 	data->client = client;
 	data->calibbias = 0;
 
-	indio_dev->name = "tmp117";
 	indio_dev->modes = INDIO_DIRECT_MODE;
 	indio_dev->info = &tmp117_info;
 
-	indio_dev->channels = tmp117_channels;
-	indio_dev->num_channels = ARRAY_SIZE(tmp117_channels);
+	switch (dev_id) {
+	case TMP116_DEVICE_ID:
+		indio_dev->channels = tmp116_channels;
+		indio_dev->num_channels = ARRAY_SIZE(tmp116_channels);
+		indio_dev->name = "tmp116";
+		break;
+	case TMP117_DEVICE_ID:
+		indio_dev->channels = tmp117_channels;
+		indio_dev->num_channels = ARRAY_SIZE(tmp117_channels);
+		indio_dev->name = "tmp117";
+		break;
+	}
 
 	return devm_iio_device_register(&client->dev, indio_dev);
 }
 
 static const struct of_device_id tmp117_of_match[] = {
 	{ .compatible = "ti,tmp117", },
+	{ .compatible = "ti,tmp116", },
 	{ }
 };
 MODULE_DEVICE_TABLE(of, tmp117_of_match);
 
 static const struct i2c_device_id tmp117_id[] = {
 	{ "tmp117", 0 },
+	{ "tmp116", 0 },
 	{ }
 };
 MODULE_DEVICE_TABLE(i2c, tmp117_id);