[PATCH v2] hwmon: Driver for Maxim MAX6697 and compatibles
Guenter Roeck
linux at roeck-us.net
Tue Jan 15 17:02:28 EST 2013
On Mon, Jan 14, 2013 at 10:24:04PM +0100, Jean Delvare wrote:
> Hi Guenter,
>
> Sorry for the late review, originally I planned to do a quick review
> but apparently I am simply unable to do that. So here comes a complete
> review. As usual, pick what you agree with and feel free to ignore the
> rest :)
>
Hi Jean,
as always an excellent and thorough review.
Couple of comments inline.
> On Sun, 16 Dec 2012 21:33:09 -0800, Guenter Roeck wrote:
> > Add support for MAX6581, MAX6602, MAX6622, MAX6636, MAX6689, MAX6693,
> > MAX6694, MAX6697, MAX6698, and MAX6699 temperature sensors
> >
> > Signed-off-by: Guenter Roeck <linux at roeck-us.net>
> > ---
> > v2:
> > - Add suppport for platform data and devicetree based chip initialization
> > - Drop S_IRUGOWU macro: s/S_IRUGOWU/S_IRUGO | S_IWUSR/
> >
> > Documentation/devicetree/bindings/i2c/max6697.txt | 45 ++
> > Documentation/hwmon/max6697 | 57 ++
> > drivers/hwmon/Kconfig | 11 +
> > drivers/hwmon/Makefile | 1 +
> > drivers/hwmon/max6697.c | 634 +++++++++++++++++++++
> > include/linux/platform_data/max6697.h | 25 +
> > 6 files changed, 773 insertions(+)
> > create mode 100644 Documentation/devicetree/bindings/i2c/max6697.txt
> > create mode 100644 Documentation/hwmon/max6697
> > create mode 100644 drivers/hwmon/max6697.c
> > create mode 100644 include/linux/platform_data/max6697.h
> >
> > diff --git a/Documentation/devicetree/bindings/i2c/max6697.txt b/Documentation/devicetree/bindings/i2c/max6697.txt
> > new file mode 100644
> > index 0000000..3e867e2
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/i2c/max6697.txt
> > @@ -0,0 +1,45 @@
> > +max6697 properties
> > +
> > +Required properties:
> > +- compatible:
> > + Should be one of
> > + maxim,max6581
> > + maxim,max6602
> > + maxim,max6622
> > + maxim,max6636
> > + maxim,max6689
> > + maxim,max6693
> > + maxim,max6694
> > + maxim,max6697
> > + maxim,max6698
> > + maxim,max6699
> > +- reg: I2C address
> > +
> > +Optional properties:
>
> Your definition of "optional" is questionable. Setting _any_ of these
> properties will cause _all_ others to be considered as 0 and the chip
> will be reprogrammed with these settings. I'd say this is unexpected and
Actually, not just "any", but the values have to be specified if OF data is
present and a non-default configuration is wanted. I clarified that in the
text.
> confusing. I'd expect struct max6697_platform_data to be able to store
> "don't change" for every setting, so that only the properties actually
> provided are written to the chip.
>
> If you really don't want to do that, then you should make it prominently
> visible both here and in max6697.h that one should either set all
> properties or none. Beware though that this may still cause trouble if
> you ever have to add one property to the set in the future.
>
I tried to find a better wording. I do want to set all values, so that part is
on purpose.
> > +- smbus-timeout-disable
> > + Set to enable SMBus timeout
s/enable/disable/
> > +- extended-range-enable
> > + Only valid for MAX6581. Set to enable extended temperature range.
> > +- alert-mask
> > + Alert bit mask. Alert disabled for bits set.
> > +- over-temperature-mask
> > + Over temperature bit mask. Over temperature reporting disabled for
> > + bits set.
> > +- resistance-cancellation
> > + Boolean for all chips other than MAX6581. Enabled if set.
> > + For MAX6581, resistance cancellation enabled for all channels if
> > + specified as boolean, otherwise as per bit mask specified.
> > +- transistor-ideality
> > + For MAX6581 only. Two values; first is bit mask, second is ideality
> > + select value as per MAX6581 data sheet.
>
> I'm not familiar with OF properties... Is there any standard for the
> properties above? If not, and other drivers implement similar
> properties, did you make sure to follow existing common practice?
>
No, not for the optional properties; I did not find anything for those.
I had tried to submit a generic means to configure i2c chips via OF,
but that was rejected even though a similar approach is used for some
PHY chips.
[ ... ]
> > +
> > +static ssize_t show_temp11(struct device *dev,
> > + struct device_attribute *devattr, char *buf)
> > +{
> > + int nr = to_sensor_dev_attr_2(devattr)->nr;
> > + int index = to_sensor_dev_attr_2(devattr)->index;
> > + struct max6697_data *data = max6697_update_device(dev);
> > +
> > + if (IS_ERR(data))
> > + return PTR_ERR(data);
> > +
> > + return sprintf(buf, "%d\n",
> > + ((data->temp[nr][index] << 3) |
> > + (data->temp[nr][index + 1] >> 5)) * 125);
>
> I can't see this code dealing properly with the negative temperature
> values supported by the MAX6581, nor with its extended format... nor
> with its normal format BTW, as it turns out to be completely different
> from the other chips.
>
Actually, the data sheet is wrong for the normal format; actual values
are the same as for other chips in that case. I now added explicit support
for the extended data format, by subtracting 64 from the returned value if
enabled. AFAICS that is correct.
> Did you have a formal request to support the MAX6581? It is different
> enough from the other support chips that I wouldn't mind dropping
> support for it from this driver, and only add support for it if someone
> needs it.
>
MAX6581 is one of the chips used by Juniper (besides MAX6697), so I need
to have support for it.
[ ... ]
> > +
> > +static SENSOR_DEVICE_ATTR(temp1_fault, S_IRUGO, show_alarm, NULL, 0);
>
> This one will never be used, as temp1 is local and can't be faulty.
>
It was there to have 6 sensors per group in the single-dimensional array
(which I needed for the initialization). I changed the array to two-dimensional,
so this is now gone.
[ ... ]
> > + if (!pdata && !client->dev.of_node)
> > + return 0;
> > +
> > + if (!pdata || client->dev.of_node) {
>
> A comment of what you're testing here would be helpful. Does platform
> take precedence over OF data, or the other way around? In fact the test
> seems wrong, as the second half will always be true if evaluated.
>
The idea was for OF data to take precedence. So
if (client->dev.of_node) {
serves the purpose.
[ ... ]
> > +
> > + ret = i2c_smbus_write_byte_data(client, MAX6697_REG_CONFIG, reg);
> > + if (ret < 0)
> > + return ret;
>
> You should never do this. If you want to modify specific bits of a
> register, read it first, modify and write back. Don't arbitrarily set
> the other bits to 0.
>
That is on purpose. I want to set all other bits to 0.
Other problems I found:
- Bit masks were not well specified. While temp1 is local and temp2..8 are
remote, bit masks were as per chip specifications. I changed the bit masks to
follow temp1..8, ie bit 0=local, bit 1..7=remote.
- If neither platform data nor OF data is available, chip configuration was not
read. Didn't make much of a difference in the old code, but since I now
support the extended temperature on MAX6581 and a chip/config specific
update interval, I had to add code to read the configuration in that case.
I'll do some more testing and resubmit later this week.
Thanks,
Guenter
More information about the devicetree-discuss
mailing list