Support ROHM BD79124 ADC
Subsystems (14)
Matti Vaittinen
maintainerv7 cover Support ROHM BD79124 ADC
Support ROHM BD79124 ADC.
This series adds also couple of IIO ADC helper functions for parsing the channel information from the device tree. There are also new helpers included for iterating and counting firmware child nodes with a specific name.
Series does also convert couple of drivers to use these helpers. The rzg2l_adc and the sun20i-gpadc are converted to use the new ADC helper.
The gianfar driver under net and the thp7312 under media/i2c are added as first users of the newly added "named child node" -helpers.
There has been some discussion about how useful these ADC helpers are, and whether they should support also differential and single ended channel configurations. This version does not include support for those - with the benefit of reduced complexity and easier to use API.
NOTE: Patches 4,5,9 and 10 are untested as I lack of relevant HW. They have been compile tested only.
The ROHM BD79124 ADC itself is quite usual stuff. 12-bit, 8-channel ADC with threshold monitoring.
Except that:
- each ADC input pin can be configured as a general purpose output.
- manually starting an ADC conversion and reading the result would require the I2C _master_ to do clock stretching(!) for the duration of the conversion... Let's just say this is not well supported.
- IC supports 'autonomous measurement mode' and storing latest results to the result registers. This mode is used by the driver due to the "peculiar" I2C when doing manual reads.
Furthermore, the ADC uses this continuous autonomous measuring, and the IC keeps producing new 'out of window' IRQs if measurements are out of window - the driver disables the event for 1 seconds when sending it to user. This prevents generating storm of events
Revision history:
v6 => v7:
- Inline device_get_named_child_node_count()
- Fix kernel-doc for fwnode_get_named_child_node_count()
- Minor styling fixes
More accurate changelog in individual patches.
v5 => v6:
- Drop applied patch
- Add *_for_each_named_child_* iterators
- Add a patch converting the thp7312 driver to use the new helper
- Styling and minor things pointed by reviewers
v4 => v5: Fixes as per various review comments. Most notably:
- Drop the patch making the TI's ADC driver to respect device tree.
- Add (RFC) patch converting gianfar driver to use new name child-node counting API as suggested by Andy.
- Add fwnode_get_child_node_count_named() as suggested by Rob.
- rebase to v6.14-rc5
More accurate changelog in individual patches.
v3 => v4:
- Drop the ADC helper support for differential channels
- Drop the ADC helper for getting only channel IDs by fwnode.
- "Promote" the function counting the number of child nodes with a specific name to the property.h (As suggested by Jonathan).
- Add ADC helpers to a namespace.
- Rebase on v6.14-rc3
- More minor changes described in individual patches.
v2 => v3:
- Restrict BD79124 channel numbers as suggested by Conor and add Conor's Reviewed-by tag.
- Support differential and single-ended inputs
- Convert couple of existing drivers to use the added ADC helpers
- Minor fixes based on reviews
Link to v2:
https://lore.kernel.org/all/[email protected]/
RFC v1 => v2:
- Drop MFD and pinmux.
- Automatically re-enable events after 1 second.
- Export fwnode parsing helpers for finding the ADC channels.
---
Matti Vaittinen (10):
dt-bindings: ROHM BD79124 ADC/GPO
property: Add functions to iterate named child
iio: adc: add helpers for parsing ADC nodes
iio: adc: rzg2l_adc: Use adc-helpers
iio: adc: sun20i-gpadc: Use adc-helpers
iio: adc: Support ROHM BD79124 ADC
MAINTAINERS: Add IIO ADC helpers
MAINTAINERS: Add ROHM BD79124 ADC/GPO
net: gianfar: Use device_get_child_node_count_named()
media: thp7312: Use helper for iterating named child nodes
.../bindings/iio/adc/rohm,bd79124.yaml | 114 ++ MAINTAINERS | 12 + drivers/base/property.c | 27 + drivers/iio/adc/Kconfig | 17 + drivers/iio/adc/Makefile | 3 + drivers/iio/adc/industrialio-adc.c | 79 ++ drivers/iio/adc/rohm-bd79124.c | 1107 +++++++++++++++++ drivers/iio/adc/rzg2l_adc.c | 38 +- drivers/iio/adc/sun20i-gpadc-iio.c | 38 +- drivers/media/i2c/thp7312.c | 8 +- drivers/net/ethernet/freescale/gianfar.c | 17 +- include/linux/iio/adc-helpers.h | 27 + include/linux/property.h | 24 + 13 files changed, 1449 insertions(+), 62 deletions(-) create mode 100644 Documentation/devicetree/bindings/iio/adc/rohm,bd79124.yaml create mode 100644 drivers/iio/adc/industrialio-adc.c create mode 100644 drivers/iio/adc/rohm-bd79124.c create mode 100644 include/linux/iio/adc-helpers.h
base-commit: 7eb172143d5508b4da468ed59ee857c6e5e01da6
Signature · 1 line
2.48.1
Matti Vaittinen
maintainerPATCH v7 1/10 dt-bindings: ROHM BD79124 ADC/GPO
Add binding document for the ROHM BD79124 ADC / GPO.
ROHM BD79124 is a 8-channel, 12-bit ADC. The input pins can also be used as general purpose outputs.
---
Revision history:
v3 =>
- No changes
v2 => v3:
- Restrict channel numbers to 0-7 as suggested by Conor
RFC v1 => v2:
- drop MFD and represent directly as ADC
- drop pinmux and treat all non ADC channel pins as GPOs
--- .../bindings/iio/adc/rohm,bd79124.yaml | 114 ++++++++++++++++++ 1 file changed, 114 insertions(+) create mode 100644 Documentation/devicetree/bindings/iio/adc/rohm,bd79124.yaml
Documentation/devicetree/bindings/iio/adc/rohm,bd79124.yaml new file +114 -0
@@ -0,0 +1,114 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/iio/adc/rohm,bd79124.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: ROHM BD79124 ADC/GPO + +maintainers: + - Matti Vaittinen <[email protected]> + +description: | + The ROHM BD79124 is a 12-bit, 8-channel, SAR ADC. The ADC supports + an automatic measurement mode, with an alarm interrupt for out-of-window + measurements. ADC input pins can be also configured as general purpose + outputs. + +properties: + compatible: + const: rohm,bd79124 + + reg: + description: + I2C slave address. + maxItems: 1 + + interrupts: + maxItems: 1 + + gpio-controller: true + + "#gpio-cells": + const: 1 + description: + The pin number. + + vdd-supply: true + + iovdd-supply: true + + "#address-cells": + const: 1 + + "#size-cells": + const: 0 + +patternProperties: + "^channel@[0-7]+$": + type: object + $ref: /schemas/iio/adc/adc.yaml# + description: Represents ADC channel. + + properties: + reg: + description: AIN pin number + minimum: 0 + maximum: 7 + + required: + - reg + + additionalProperties: false + +required: + - compatible + - reg + - iovdd-supply + - vdd-supply + +additionalProperties: false + +examples: + - | + #include <dt-bindings/interrupt-controller/irq.h> + #include <dt-bindings/leds/common.h> + i2c { + #address-cells = <1>; + #size-cells = <0>; + adc: adc@10 { + compatible = "rohm,bd79124"; + reg = <0x10>; + + interrupt-parent = <&gpio1>; + interrupts = <29 8>; + + vdd-supply = <&dummyreg>; + iovdd-supply = <&dummyreg>; + + #address-cells = <1>; + #size-cells = <0>; + + channel@0 { + reg = <0>; + }; + channel@1 { + reg = <1>; + }; + channel@2 { + reg = <2>; + }; + channel@3 { + reg = <3>; + }; + channel@4 { + reg = <4>; + }; + channel@5 { + reg = <5>; + }; + channel@6 { + reg = <6>; + }; + }; + };
Signature · 1 line
2.48.1
Matti Vaittinen
maintainerPATCH v7 2/10 property: Add functions to iterate named child
In reply to Matti VaittinenThere are a few use-cases where child nodes with a specific name need to be parsed. Code like:
fwnode_for_each_child_node()
if (fwnode_name_eq()) ...
can be found from a various drivers/subsystems. Adding a macro for this can simplify things a bit.
In a few cases the data from the found nodes is later added to an array, which is allocated based on the number of found nodes. One example of such use is the IIO subsystem's ADC channel nodes, where the relevant nodes are named as channel[@N].
Add helpers for iterating and counting device's sub-nodes with certain name instead of open-coding this in every user.
---
Revision history:
v6 => v7:
- Improve kerneldoc
- Inline device_get_named_child_node_count() and change it to call fwnode_get_named_child_node_count() inside
- Fix indentiation of the new macros
v5 => v6:
- Add helpers to also iterate through the nodes.
v4 => v5:
- Use given name instead of string 'channel' when counting the nodes
- Add also fwnode_get_child_node_count_named() as suggested by Rob.
v3 => v4:
- New patch as suggested by Jonathan, see discussion in:
https://lore.kernel.org/lkml/20250223161338.5c896280@jic23-huawei/
--- drivers/base/property.c | 27 +++++++++++++++++++++++++++ include/linux/property.h | 24 ++++++++++++++++++++++++ 2 files changed, 51 insertions(+)
drivers/base/property.c +27 -0
@@ -945,6 +945,33 @@ unsigned int device_get_child_node_count(const struct device *dev) }EXPORT_SYMBOL_GPL (device_get_child_node_count); +/** +* fwnode_get_named_child_node_count - number of child nodes with given name +* @fwnode: Node which child nodes are counted. +* @name: String to match child node name against. +* +* Scan child nodes and count all the nodes with a specific name. Potential +* 'number' -ending after the 'at sign' for scanned names is ignored. +* E.g.:: +* device_get_named_child_node_count(dev, "channel"); +* would match all the nodes:: +* channel { }, channel@0 {}, channel@0xabba {}... +* +* Return: the number of child nodes with a matching name for a given device. +*/ +unsigned int fwnode_get_named_child_node_count (const struct fwnode_handle *fwnode, +const char *name) +{ +struct fwnode_handle *child; +unsigned int count =0 ; + +fwnode_for_each_named_child_node (fwnode, child, name) + count++; + +return count; +} +EXPORT_SYMBOL_GPL (fwnode_get_named_child_node_count); +bool device_dma_supported (const struct device *dev) {return fwnode_call_bool_op (dev_fwnode (dev), device_dma_supported);
include/linux/property.h +24 -0
@@ -167,10 +167,18 @@ struct fwnode_handle *fwnode_get_next_available_child_node(for (child =fwnode_get_next_child_node (fwnode,NULL ); child; \ child = fwnode_get_next_child_node(fwnode, child)) +#define fwnode_for_each_named_child_node (fwnode, child, name) \ + fwnode_for_each_child_node(fwnode, child) \ + if (!fwnode_name_eq(child, name)) { } else +#define fwnode_for_each_available_child_node (fwnode, child) \ for (child = fwnode_get_next_available_child_node(fwnode, NULL); child;\ child = fwnode_get_next_available_child_node(fwnode, child)) +#define fwnode_for_each_available_named_child_node (fwnode, child, name) \ + fwnode_for_each_available_child_node(fwnode, child) \ + if (!fwnode_name_eq(child, name)) { } else +struct fwnode_handle *device_get_next_child_node (const struct device *dev,struct fwnode_handle *child);
@@ -178,11 +186,19 @@ struct fwnode_handle *device_get_next_child_node(const struct device *dev,for (child =device_get_next_child_node (dev,NULL ); child; \ child = device_get_next_child_node(dev, child)) +#define device_for_each_named_child_node (dev, child, name) \ + device_for_each_child_node(dev, child) \ + if (!fwnode_name_eq(child, name)) { } else +#define device_for_each_child_node_scoped (dev, child) \ for (struct fwnode_handle *child __free(fwnode_handle) = \ device_get_next_child_node(dev, NULL); \ child; child = device_get_next_child_node(dev, child)) +#define device_for_each_named_child_node_scoped (dev, child, name) \ + device_for_each_child_node_scoped(dev, child) \ + if (!fwnode_name_eq(child, name)) { } else +struct fwnode_handle *fwnode_get_named_child_node (const struct fwnode_handle *fwnode,const char *childname); struct fwnode_handle *device_get_named_child_node(const struct device *dev,
@@ -210,6 +226,14 @@ int fwnode_irq_get_byname(const struct fwnode_handle *fwnode, const char *name);unsigned int device_get_child_node_count (const struct device *dev); +unsigned int fwnode_get_named_child_node_count (const struct fwnode_handle *fwnode, +const char *name); +static inline unsigned int device_get_named_child_node_count (const struct device *dev, +const char *name) +{ +return fwnode_get_named_child_node_count (dev_fwnode (dev), name); +} +static inline int device_property_read_u8 (const struct device *dev,const char *propname,u8 *val) {
Signature · 1 line
2.48.1
Re: [PATCH v7 02/10] property: Add functions to iterate named child
Quoted 10 lines · Matti Vaittinen
There are a few use-cases where child nodes with a specific name need to be parsed. Code like:
fwnode_for_each_child_node()if (fwnode_name_eq()) ...can be found from a various
drivers/subsystems. Adding a macro for this can simplify things a bit.
Quoted 7 lines
In a few cases the data from the found nodes is later added to an array, which is allocated based on the number of found nodes. One example of such use is the IIO subsystem's ADC channel nodes, where the relevant nodes are named as channel[@N].
Add helpers for iterating and counting device's sub-nodes with certain name instead of open-coding this in every user.
LGTM,
I haven't checked the rendered kernel-doc, though.
Signature · 2 lines
With Best Regards, Andy Shevchenko
Re: [PATCH v7 02/10] property: Add functions to iterate named child
In reply to Matti VaittinenHello,
LGTM, few minor comments inline.
With those sorted
Quoted 21 lines · Matti Vaittinen
There are a few use-cases where child nodes with a specific name need to be parsed. Code like:
fwnode_for_each_child_node()if (fwnode_name_eq()) ...can be found from a various
drivers/subsystems. Adding a macro for this can simplify things a bit.In a few cases the data from the found nodes is later added to an array, which is allocated based on the number of found nodes. One example of such use is the IIO subsystem's ADC channel nodes, where the relevant nodes are named as channel[@N].
Add helpers for iterating and counting device's sub-nodes with certain name instead of open-coding this in every user.
Suggested-by Jonathan Cameron <[email protected]>Signed-off-by Matti Vaittinen <[email protected]>---
...
Quoted 9 lines
+/**
+ *fwnode_get_named_child_node_count- number of child nodes with given name
+ * @fwnode: Node which child nodes are counted.
+ * @name: String to match child node name against.
+ *
+ * Scan child nodes and count all the nodes with a specific name. Potential
+ * 'number' -ending after the 'at sign' for scanned names is ignored.
+ * E.g.::
+ *device_get_named_child_node_count(dev, "channel");
The function being documented is fwnode_get_named_child_node_count(). Shouldn't the example be
fwnode_get_named_child_node_count(fwnode, "channel");
?
Quoted 5 lines
+ * would match all the nodes::
+ * channel { }, channel@0 {}, channel@0xabba {}...
+ *
+ * Return: the number of child nodes with a matching name for a given device.
+ */
...
include/linux/property.h struct fwnode_handle *device_get_next_child_node(const struct device *dev, · line 191
Quoted 3 lines
include/linux/property.h +3
-0+#define device_for_each_named_child_node (dev, child, name) \ + device_for_each_child_node(dev, child) \ + if (!fwnode_name_eq(child, name)) { } else
nitpicking: add only one tab for each indentation level.
device_for_each_child_node(dev, child) \
if (!fwnode_name_eq(child, name)) { } elseinclude/linux/property.h struct fwnode_handle *device_get_next_child_node(const struct device *dev, · line 201
Quoted 10 lines
include/linux/property.h +5
-0+#define device_for_each_child_node_scoped (dev, child) \ for (struct fwnode_handle *child __free(fwnode_handle) = \ device_get_next_child_node(dev, NULL); \ child; child = device_get_next_child_node(dev, child)) +#define device_for_each_named_child_node_scoped (dev, child, name) \ + device_for_each_child_node_scoped(dev, child) \ + if (!fwnode_name_eq(child, name)) { } else +
nitpicking: instead of two tabs, only one tab before device_for_..._scoped().
device_for_each_child_node_scoped(dev, child) \
if (!fwnode_name_eq(child, name)) { } elseRegards,
Marcelo
Matti Vaittinen
maintainerPATCH v7 3/10 iio: adc: add helpers for parsing ADC nodes
In reply to Matti VaittinenThere are ADC ICs which may have some of the AIN pins usable for other functions. These ICs may have some of the AIN pins wired so that they should not be used for ADC.
(Preferred?) way for marking pins which can be used as ADC inputs is to add corresponding channels@N nodes in the device tree as described in the ADC binding yaml.
Add couple of helper functions which can be used to retrieve the channel information from the device node.
---
Revision history:
v6 =>
- No changes
v5 => v6:
- Adapt to changed fwnode helper names
- Fix spelling
v4 => v5:
- Inline iio_adc_device_num_channels()
- Fix Indenting function parameters
- Combine the max channel ID checks.
v3 => v4:
- Drop diff-channel support
- Drop iio_adc_device_channels_by_property()
- Add IIO_DEVICE namespace
- Move industrialio-adc.o to top of the Makefile
- Some styling as suggested by Andy
- Re-consider included headers
v2 => v3: Mostly based on review comments by Jonathan
- Support differential and single-ended channels
- Rename iio_adc_device_get_channels() as iio_adc_device_channels_by_property()
- Improve spelling
- Drop support for cases where DT comes from parent device's node
- Decrease loop indent by reverting node name check conditions
- Don't set 'chan->indexed' by number of channels to keep the interface consistent no matter how many channels are connected.
- Fix ID range check and related comment
RFC v1 => v2:
- New patch
--- drivers/iio/adc/Kconfig | 3 ++ drivers/iio/adc/Makefile | 2 + drivers/iio/adc/industrialio-adc.c | 79 ++++++++++++++++++++++++++++++ include/linux/iio/adc-helpers.h | 27 ++++++++++ 4 files changed, 111 insertions(+) create mode 100644 drivers/iio/adc/industrialio-adc.c create mode 100644 include/linux/iio/adc-helpers.h
drivers/iio/adc/Kconfig +3 -0
@@ -6,6 +6,9 @@ menu "Analog to digital converters" +config IIO_ADC_HELPER + tristate + config AB8500_GPADC bool "ST-Ericsson AB8500 GPADC driver" depends on AB8500_CORE && REGULATOR_AB8500
drivers/iio/adc/Makefile +2 -0
@@ -3,6 +3,8 @@ # Makefile for IIO ADC drivers # +obj-$(CONFIG_IIO_ADC_HELPER) += industrialio-adc.o + # When adding new entries keep the list in alphabetical order obj-$(CONFIG_AB8500_GPADC) += ab8500-gpadc.o obj-$(CONFIG_AD_SIGMA_DELTA) += ad_sigma_delta.o
drivers/iio/adc/industrialio-adc.c new file +79 -0
79 lines not on this page · raw message
include/linux/iio/adc-helpers.h new file +27 -0
@@ -0,0 +1,27 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +/* +* The industrial I/O ADC firmware property parsing helpers +* +* Copyright (c) 2025 Matti Vaittinen <[email protected]> +*/ + +#ifndef _INDUSTRIAL_IO_ADC_HELPERS_H_ +#define _INDUSTRIAL_IO_ADC_HELPERS_H_ + +#include <linux/property.h> + +struct device ; +struct iio_chan_spec ; + +static inline int iio_adc_device_num_channels (struct device *dev) +{ +return device_get_named_child_node_count (dev,"channel" ); +} + +int devm_iio_adc_device_alloc_chaninfo_se (struct device *dev, +const struct iio_chan_spec *template, +int max_chan_id, +struct iio_chan_spec **cs); + +#endif /* _INDUSTRIAL_IO_ADC_HELPERS_H_ */
Signature · 1 line
2.48.1
Andy Shevchenko
reviewerRe: [PATCH v7 03/10] iio: adc: add helpers for parsing ADC nodes
Quoted 10 lines · Matti Vaittinen
There are ADC ICs which may have some of the AIN pins usable for other functions. These ICs may have some of the AIN pins wired so that they should not be used for ADC.
(Preferred?) way for marking pins which can be used as ADC inputs is to add corresponding channels@N nodes in the device tree as described in the ADC binding yaml.
Add couple of helper functions which can be used to retrieve the channel information from the device node.
...
drivers/iio/adc/industrialio-adc.c line 43
Quoted 7 lines
drivers/iio/adc/industrialio-adc.c new file +7
-0+int devm_iio_adc_device_alloc_chaninfo_se (struct device *dev, +const struct iio_chan_spec *template, +int max_chan_id, +struct iio_chan_spec **cs) +{ +struct iio_chan_spec *chan_array, *chan; +int num_chan =0 , ret;
Unneeded assignment.
drivers/iio/adc/industrialio-adc.c line 47
Quoted 3 lines
drivers/iio/adc/industrialio-adc.c new file +3
-0+ num_chan =iio_adc_device_num_channels (dev); +if (num_chan <1 ) +return num_chan;
This is really interesting code. So, if the above returns negative error code, we return it, if it returns 0, we return success (but 0 channels)?
Shouldn't we do *cs = NULL; at the case of 0 channels if it's a success? (Under success I assume that returned values are okay to go with, and cs in your case will be left uninitialised or contain something we don't control.
Quoted 6 lines
drivers/iio/adc/industrialio-adc.c new file +6
-0+ chan_array =devm_kcalloc (dev, num_chan,sizeof (*chan_array), +GFP_KERNEL ); +if (!chan_array) +return -ENOMEM ; + + chan = &chan_array[0 ];
drivers/iio/adc/industrialio-adc.c line 64
Quoted 10 lines
drivers/iio/adc/industrialio-adc.c new file +9
-0+ +device_for_each_named_child_node_scoped (dev, child,"channel" ) { +u32 ch; + + ret =fwnode_property_read_u32 (child,"reg" , &ch); +if (ret) +return ret; +if (max_chan_id !=-1 && ch > max_chan_id) +return -ERANGE ;
Hmm... What if max_chan_id is equal to an error code? Or in other words, why -1 is special and not all negative numbers?
Also note, you used unsigned type and compare it to int which, in case of being negative will give promotion. The ch will not be big enough in most cases (unless it's great than (INT_MAX + 1).
TL;DR: you have a potential integer overflow here.
Quoted 9 lines
drivers/iio/adc/industrialio-adc.c new file +9
-0+ *chan = *template; + chan->channel = ch; + chan++; + } + + *cs = chan_array; + +return num_chan; +}
Signature · 2 lines
With Best Regards, Andy Shevchenko
Matti Vaittinen
maintainerRe: [PATCH v7 03/10] iio: adc: add helpers for parsing ADC nodes
Quoted 14 lines · Andy Shevchenko
Quoted 10 lines · Matti Vaittinen
There are ADC ICs which may have some of the AIN pins usable for other functions. These ICs may have some of the AIN pins wired so that they should not be used for ADC.
(Preferred?) way for marking pins which can be used as ADC inputs is to add corresponding channels@N nodes in the device tree as described in the ADC binding yaml.
Add couple of helper functions which can be used to retrieve the channel information from the device node.
...
Quoted 9 lines
drivers/iio/adc/industrialio-adc.c line 43
Quoted 7 lines
drivers/iio/adc/industrialio-adc.c new file +7
-0+int devm_iio_adc_device_alloc_chaninfo_se (struct device *dev, +const struct iio_chan_spec *template, +int max_chan_id, +struct iio_chan_spec **cs) +{ +struct iio_chan_spec *chan_array, *chan; +int num_chan =0 , ret;Unneeded assignment.
Hmm. I have a deja-vu. Thanks for the reminder.
Quoted 7 lines
drivers/iio/adc/industrialio-adc.c line 47
Quoted 4 lines
drivers/iio/adc/industrialio-adc.c new file +3
-0+ num_chan =iio_adc_device_num_channels (dev); +if (num_chan <1 ) +return num_chan;This is really interesting code. So, if the above returns negative error code, we return it, if it returns 0, we return success (but 0 channels)?
Yes. I don't think it's that interesting though. Checking the devicetree succeeded while no channels were found. I think returning 0 is very much aligned with this.
Quoted 1 line
Shouldn't we do *cs = NULL; at the case of 0 channels if it's a success?
I suppose you're right.
But, as you pointed out in review of the 05/10:
Quoted 3 lines
Usually in other similar APIs we return
-ENOENT. And user won't need to have an additional check in case of 0 being considered as an error case too.
I don't know whether to agree with you here. For majority of the ADC drivers, having no channels in devicetree is indeed just another error, which I think is not in any ways special.
However, for 33,3333% of the users added in this patch, the "no channels found" is not really an error condition ;) The BD79124 could have all channels used for GPO - although this would probably be very very unusual. (Why buying an ADC chip if you need just a GPO?). Still, this wouldn't be an error. (And I need to handle this better in BD79124 probe - so thanks).
Quoted 2 lines
(Under success I assume that returned values are okay to go with, and cs in your case will be left uninitialised or contain something we don't control.
I see your point although I wouldn't be concerned with cs not being NULL for as long as number of channels is zero.
Anyway, I think it makes sense to simplify ~67% of callers by returning -ENODEV if there is no channels. The remaining ~33% can then check for the -ENODEV and handle it separately from other returned errors. So, thanks.
Quoted 14 lines
Quoted 13 lines
drivers/iio/adc/industrialio-adc.c new file +13
-0+ chan_array =devm_kcalloc (dev, num_chan,sizeof (*chan_array), +GFP_KERNEL ); +if (!chan_array) +return -ENOMEM ; + + chan = &chan_array[0 ]; + +device_for_each_named_child_node_scoped (dev, child,"channel" ) { +u32 ch; + + ret =fwnode_property_read_u32 (child,"reg" , &ch); +if (ret) +return ret;
Quoted 5 lines
drivers/iio/adc/industrialio-adc.c line 64
Quoted 2 lines
drivers/iio/adc/industrialio-adc.c new file +2
-0+if (max_chan_id !=-1 && ch > max_chan_id) +return -ERANGE ;Hmm... What if
max_chan_idis equal to an error code? Or in other words, why -1 is special and not all negative numbers?
-1 was just picked to represent a 'don't care' value. Old habit. In the old days I handled lots of code where -1 was defined as 'invalid' for APIs with unsigned ints as well. It works nicely on systems where it turns out to be maximum positive value - leaving most of the number space for valid values.
I suppose saying any negative means "don't care" works well here. And, dropping all negatives here will also make the check below just work with unsigned comparison.
Quoted 2 lines
Also note, you used unsigned type and compare it to int which, in case of being negative will give promotion.
Right. I didn't thin negative IDs would make sense and trusted users to pass only positive ones. Treating all negatives as "don't care" is indeed better than trusting this.
Thanks.
Quoted 15 lines
The ch will not be
big enough in most cases (unless it's great than (INT_MAX+ 1).TL;DR: you have a potential integer overflow here.
Quoted 9 lines
drivers/iio/adc/industrialio-adc.c new file +9
-0+ *chan = *template; + chan->channel = ch; + chan++; + } + + *cs = chan_array; + +return num_chan; +}
Andy Shevchenko
reviewerRe: [PATCH v7 03/10] iio: adc: add helpers for parsing ADC nodes
Quoted 2 lines · Matti Vaittinen
Quoted 1 line · Andy Shevchenko
On Thu, Mar 13, 2025 at 09:18:18AM +0200, Matti Vaittinen wrote:
...
Quoted 10 lines
Quoted 6 lines
drivers/iio/adc/industrialio-adc.c line 47
Quoted 3 lines
drivers/iio/adc/industrialio-adc.c new file +3
-0+ num_chan =iio_adc_device_num_channels (dev); +if (num_chan <1 ) +return num_chan;This is really interesting code. So, if the above returns negative error code, we return it, if it returns 0, we return success (but 0 channels)?
Yes. I don't think it's that interesting though. Checking the devicetree succeeded while no channels were found. I think returning 0 is very much aligned with this.
Right, but as I suggested, let's follow already established APIs that return -ENOENT and never 0 in similar cases.
Quoted 4 lines
Quoted 1 line
Shouldn't we do *cs = NULL; at the case of 0 channels if it's a success?
I suppose you're right.
Quoted 8 lines
But, as you pointed out in review of the 05/10:
Quoted 3 lines
Usually in other similar APIs we return
-ENOENT. And user won't need to have an additional check in case of 0 being considered as an error case too.I don't know whether to agree with you here. For majority of the ADC drivers, having no channels in devicetree is indeed just another error, which I think is not in any ways special.
So...? (I see below your answer :-)
Quoted 5 lines
However, for 33,3333% of the users added in this patch, the "no channels found" is not really an error condition ;) The BD79124 could have all channels used for GPO - although this would probably be very very unusual. (Why buying an ADC chip if you need just a GPO?). Still, this wouldn't be an error. (And I need to handle this better in BD79124 probe - so thanks).
ENOENT check is again established for optional/not_found cases.
Review
Quoted 9 lines
Quoted 2 lines
(Under success I assume that returned values are okay to go with, and cs in your case will be left uninitialised or contain something we don't control.
I see your point although I wouldn't be concerned with cs not being NULL for as long as number of channels is zero.
Anyway, I think it makes sense to simplify ~67% of callers by returning
(quoted diff) +0
-2-ENODEV if there is no channels. The remaining ~33% can then check for the -ENODEV and handle it separately from other returned errors. So, thanks.
Not at all!
Signature · 2 lines
With Best Regards, Andy Shevchenko
Jonathan Cameron
maintainerRe: [PATCH v7 03/10] iio: adc: add helpers for parsing ADC nodes
In reply to Matti VaittinenQuoted 10 lines · On Thu, 13 Mar 2025 09:18:18 +0200 Matti Vaittinen <[email protected]>…
There are ADC ICs which may have some of the AIN pins usable for other functions. These ICs may have some of the AIN pins wired so that they should not be used for ADC.
(Preferred?) way for marking pins which can be used as ADC inputs is to add corresponding channels@N nodes in the device tree as described in the ADC binding yaml.
Add couple of helper functions which can be used to retrieve the channel information from the device node.
I suspect we'll need the addition of an optional trailing timestamp channel at somepoint. But we can add that when we need it as only matters for drivers doing iio_push_to_buffers_with_timestamp()
Otherwise no additional comments from me.
Matti Vaittinen
maintainerRe: [PATCH v7 03/10] iio: adc: add helpers for parsing ADC nodes
Quoted 11 lines · Jonathan Cameron
Quoted 8 lines · On Thu, 13 Mar 2025 09:18:18 +0200 Matti Vaittinen <[email protected]>…
There are ADC ICs which may have some of the AIN pins usable for other functions. These ICs may have some of the AIN pins wired so that they should not be used for ADC.
(Preferred?) way for marking pins which can be used as ADC inputs is to add corresponding channels@N nodes in the device tree as described in the ADC binding yaml.
Quoted 5 lines
Quoted 2 lines
Add couple of helper functions which can be used to retrieve the channel information from the device node.
I suspect we'll need the addition of an optional trailing timestamp channel at somepoint. But we can add that when we need it as only matters for drivers doing
iio_push_to_buffers_with_timestamp()
This is true. That'll enable using this for devices with buffers - which is not possible right now as most buffer users do timestamps. I'll leave adding the parameter to first buffered user though, but I think it's good to say out loud this is doable :) Thanks!
Quoted 1 line
Otherwise no additional comments from me.
Yours,
-- Matti
Matti Vaittinen
maintainerPATCH v7 4/10 iio: adc: rzg2l_adc: Use adc-helpers
In reply to Matti VaittinenThe new devm_iio_adc_device_alloc_chaninfo_se() -helper is intended to help drivers avoid open-coding the for_each_node -loop for getting the channel IDs. The helper provides standard way to detect the ADC channel nodes (by the node name), and a standard way to convert the "reg" -properties to channel identification numbers, used in the struct iio_chan_spec. Furthermore, the helper can optionally check the found channel IDs are smaller than given maximum. This is useful for callers which later use the IDs for example for indexing a channel data array.
The original driver treated all found child nodes as channel nodes. The new helper requires channel nodes to be named channel[@N]. This should help avoid problems with devices which may contain also other but ADC child nodes. Quick grep from arch/* with the rzg2l_adc's compatible string didn't reveal any in-tree .dts with channel nodes named otherwise. Also, same grep shows all the .dts seem to have channel IDs between 0..num of channels.
Use the new helper.
---
Revision history:
v6 => v7:
- Fix function name in the commit message
v5 => v6:
- Commit message typofix
v4 => v5:
- Drop the diff-channel stuff from the commit message
v3 => v4:
- Adapt to 'drop diff-channel support' changes to ADC-helpers
- select ADC helpers in the Kconfig
- Rebased to 6.14-rc3 => channel type can no longer come from the template.
v2 => v3:
- New patch
The change is compile tested only!! Testing before applying is highly appreciated (as always!).
--- drivers/iio/adc/Kconfig | 1 + drivers/iio/adc/rzg2l_adc.c | 38 +++++++++++++++++-------------------- 2 files changed, 18 insertions(+), 21 deletions(-)
drivers/iio/adc/Kconfig +1 -0
@@ -1222,6 +1222,7 @@ config RICHTEK_RTQ6056 config RZG2L_ADC tristate "Renesas RZ/G2L ADC driver" depends on ARCH_RZG2L || COMPILE_TEST + select IIO_ADC_HELPER help Say yes here to build support for the ADC found in Renesas RZ/G2L family.
drivers/iio/adc/rzg2l_adc.c +17 -21
@@ -11,6 +11,7 @@#include <linux/cleanup.h> #include <linux/completion.h> #include <linux/delay.h> +#include <linux/iio/adc-helpers.h> #include <linux/iio/iio.h> #include <linux/interrupt.h> #include <linux/io.h>
@@ -324,21 +325,30 @@ static irqreturn_t rzg2l_adc_isr(int irq, void *dev_id)return IRQ_HANDLED ; } +static const struct iio_chan_spec rzg2l_adc_chan_template = { + .indexed =1 , + .info_mask_separate =BIT (IIO_CHAN_INFO_RAW ), +}; +static int rzg2l_adc_parse_properties (struct platform_device *pdev,struct rzg2l_adc *adc) {const struct rzg2l_adc_hw_params *hw_params = adc->hw_params;struct iio_chan_spec *chan_array;struct rzg2l_adc_data *data; -unsigned int channel;int num_channels; -int ret;u8 i; data =devm_kzalloc (&pdev->dev,sizeof (*data),GFP_KERNEL );if (!data)return -ENOMEM ; - num_channels =device_get_child_node_count (&pdev->dev); + num_channels =devm_iio_adc_device_alloc_chaninfo_se (&pdev->dev, + &rzg2l_adc_chan_template, + hw_params->num_channels -1 , + &chan_array); +if (num_channels <0 ) +return num_channels; +if (!num_channels)return dev_err_probe (&pdev->dev, -ENODEV ,"no channel children\n" );
@@ -346,26 +356,11 @@ static int rzg2l_adc_parse_properties(struct platform_device *pdev, struct rzg2lreturn dev_err_probe (&pdev->dev, -EINVAL ,"num of channel children out of range\n" ); - chan_array =devm_kcalloc (&pdev->dev, num_channels,sizeof (*chan_array), -GFP_KERNEL ); -if (!chan_array) -return -ENOMEM ; - - i =0 ; -device_for_each_child_node_scoped (&pdev->dev, fwnode) { - ret =fwnode_property_read_u32 (fwnode,"reg" , &channel); -if (ret) -return ret; - -if (channel >= hw_params->num_channels) -return -EINVAL ; +for (i =0 ; i < num_channels; i++) { +int channel = chan_array[i].channel; - chan_array[i].type = rzg2l_adc_channels[channel].type; - chan_array[i].indexed =1 ; - chan_array[i].channel = channel; - chan_array[i].info_mask_separate =BIT (IIO_CHAN_INFO_RAW ); chan_array[i].datasheet_name = rzg2l_adc_channels[channel].name; - i++; + chan_array[i].type = rzg2l_adc_channels[channel].type; } data->num_channels = num_channels;
@@ -626,3 +621,4 @@ module_platform_driver(rzg2l_adc_driver);MODULE_AUTHOR ("Lad Prabhakar <[email protected]>" );MODULE_DESCRIPTION ("Renesas RZ/G2L ADC driver" );MODULE_LICENSE ("GPL v2" ); +MODULE_IMPORT_NS ("IIO_DRIVER" );
Signature · 1 line
2.48.1
Matti Vaittinen
maintainerPATCH v7 5/10 iio: adc: sun20i-gpadc: Use adc-helpers
In reply to Matti VaittinenThe new devm_iio_adc_device_alloc_chaninfo_se() -helper is intended to help drivers avoid open-coding the for_each_node -loop for getting the channel IDs. The helper provides standard way to detect the ADC channel nodes (by the node name), and a standard way to convert the "reg" -properties to channel identification numbers, used in the struct iio_chan_spec. Furthermore, the helper can optionally check the found channel IDs are smaller than given maximum. This is useful for callers which later use the IDs for example for indexing a channel data array.
The original driver treated all found child nodes as channel nodes. The new helper requires channel nodes to be named channel[@N]. This should help avoid problems with devices which may contain also other but ADC child nodes. Quick grep from arch/* with the sun20i-gpadc's compatible string didn't reveal any in-tree .dts with channel nodes named otherwise. Also, same grep shows all the in-tree .dts seem to have channel IDs between 0..num of channels.
Use the new helper.
---
Revision history:
v6 => v7:
- Fix function name in the commit message
v5 => v6:
- Commit message typofix
v4 => v5:
- Drop the diff-channel stuff from the commit message
v3 => v4:
- Adapt to 'drop diff-channel support' changes to ADC-helpers
- select ADC helpers in the Kconfig
v2 => v3:
- New patch
I picked the sun20i-gpadc in this series because it has a straightforward approach for populating the struct iio_chan_spec. Everything else except the .channel can use 'template'-data.
This makes the sun20i-gpadc well suited to be an example user of this new helper. I hope this patch helps to evaluate whether these helpers are worth the hassle.
The change is compile tested only!! Testing before applying is highly appreciated (as always!). Also, even though I tried to audit the dts files for the reg-properties in the channel nodes, use of references didn't make it easy. I can't guarantee I didn't miss anything.
--- drivers/iio/adc/Kconfig | 1 + drivers/iio/adc/sun20i-gpadc-iio.c | 38 ++++++++++++------------------ 2 files changed, 16 insertions(+), 23 deletions(-)
drivers/iio/adc/Kconfig +1 -0
@@ -1357,6 +1357,7 @@ config SUN4I_GPADC config SUN20I_GPADC tristate "Allwinner D1/T113s/T507/R329 and similar GPADCs driver" depends on ARCH_SUNXI || COMPILE_TEST + select IIO_ADC_HELPER help Say yes here to build support for Allwinner (D1, T113, T507 and R329) SoCs GPADC. This ADC provides up to 16 channels.
drivers/iio/adc/sun20i-gpadc-iio.c +15 -23
@@ -15,6 +15,7 @@#include <linux/property.h> #include <linux/reset.h> +#include <linux/iio/adc-helpers.h> #include <linux/iio/iio.h> #define SUN20I_GPADC_DRIVER_NAME "sun20i-gpadc"
@@ -149,37 +150,27 @@ static void sun20i_gpadc_reset_assert(void *data)reset_control_assert (rst); } +static const struct iio_chan_spec sun20i_gpadc_chan_template = { + .type =IIO_VOLTAGE , + .indexed =1 , + .info_mask_separate =BIT (IIO_CHAN_INFO_RAW ), + .info_mask_shared_by_type =BIT (IIO_CHAN_INFO_SCALE ), +}; +static int sun20i_gpadc_alloc_channels (struct iio_dev *indio_dev,struct device *dev) { -unsigned int channel; -int num_channels, i, ret; +int num_channels;struct iio_chan_spec *channels; - num_channels =device_get_child_node_count (dev); + num_channels =devm_iio_adc_device_alloc_chaninfo_se (dev, + &sun20i_gpadc_chan_template,-1 , &channels); +if (num_channels <0 ) +return num_channels; +if (num_channels ==0 )return dev_err_probe (dev, -ENODEV ,"no channel children\n" ); - channels =devm_kcalloc (dev, num_channels,sizeof (*channels), -GFP_KERNEL ); -if (!channels) -return -ENOMEM ; - - i =0 ; -device_for_each_child_node_scoped (dev, node) { - ret =fwnode_property_read_u32 (node,"reg" , &channel); -if (ret) -return dev_err_probe (dev, ret,"invalid channel number\n" ); - - channels[i].type =IIO_VOLTAGE ; - channels[i].indexed =1 ; - channels[i].channel = channel; - channels[i].info_mask_separate =BIT (IIO_CHAN_INFO_RAW ); - channels[i].info_mask_shared_by_type =BIT (IIO_CHAN_INFO_SCALE ); - - i++; - } - indio_dev->channels = channels; indio_dev->num_channels = num_channels;
@@ -271,3 +262,4 @@ module_platform_driver(sun20i_gpadc_driver);MODULE_DESCRIPTION ("ADC driver for sunxi platforms" );MODULE_AUTHOR ("Maksim Kiselev <[email protected]>" );MODULE_LICENSE ("GPL" ); +MODULE_IMPORT_NS ("IIO_DRIVER" );
Signature · 1 line
2.48.1
Andy Shevchenko
reviewerRe: [PATCH v7 05/10] iio: adc: sun20i-gpadc: Use adc-helpers
Quoted 18 lines · Matti Vaittinen
The new
devm_iio_adc_device_alloc_chaninfo_se()-helper is intended to help drivers avoid open-coding thefor_each_node-loop for getting the channel IDs. The helper provides standard way to detect the ADC channel nodes (by the node name), and a standard way to convert the "reg" -properties to channel identification numbers, used in the structiio_chan_spec. Furthermore, the helper can optionally check the found channel IDs are smaller than given maximum. This is useful for callers which later use the IDs for example for indexing a channel data array.The original driver treated all found child nodes as channel nodes. The new helper requires channel nodes to be named channel[@N]. This should help avoid problems with devices which may contain also other but ADC child nodes. Quick grep from
arch/*with the sun20i-gpadc's compatible string didn't reveal any in-tree .dts with channel nodes named otherwise. Also, same grep shows all the in-tree .dts seem to have channel IDs between 0..num of channels.Use the new helper.
...
drivers/iio/adc/sun20i-gpadc-iio.c static void sun20i_gpadc_reset_assert(void *data) · line 172
Quoted 7 lines
drivers/iio/adc/sun20i-gpadc-iio.c +5
-0+ num_channels =devm_iio_adc_device_alloc_chaninfo_se (dev, + &sun20i_gpadc_chan_template,-1 , &channels); +if (num_channels <0 ) +return num_channels; +if (num_channels ==0 )return dev_err_probe (dev, -ENODEV ,"no channel children\n" );
Note, this what I would expected in your helper to see, i.e. separated cases for < 0 (error code) and == 0, no channels.
Also, are all users going to have this check? Usually in other similar APIs we return -ENOENT. And user won't need to have an additional check in case of 0 being considered as an error case too.
Signature · 2 lines
With Best Regards, Andy Shevchenko
Jonathan Cameron
maintainerRe: [PATCH v7 05/10] iio: adc: sun20i-gpadc: Use adc-helpers
Quoted 33 lines · On Thu, 13 Mar 2025 14:34:24 +0200 Andy Shevchenko…
Quoted 18 lines · Matti Vaittinen
The new
devm_iio_adc_device_alloc_chaninfo_se()-helper is intended to help drivers avoid open-coding thefor_each_node-loop for getting the channel IDs. The helper provides standard way to detect the ADC channel nodes (by the node name), and a standard way to convert the "reg" -properties to channel identification numbers, used in the structiio_chan_spec. Furthermore, the helper can optionally check the found channel IDs are smaller than given maximum. This is useful for callers which later use the IDs for example for indexing a channel data array.The original driver treated all found child nodes as channel nodes. The new helper requires channel nodes to be named channel[@N]. This should help avoid problems with devices which may contain also other but ADC child nodes. Quick grep from
arch/*with the sun20i-gpadc's compatible string didn't reveal any in-tree .dts with channel nodes named otherwise. Also, same grep shows all the in-tree .dts seem to have channel IDs between 0..num of channels.Use the new helper.
...
drivers/iio/adc/sun20i-gpadc-iio.c static void sun20i_gpadc_reset_assert(void *data) · line 172
Quoted 7 lines
drivers/iio/adc/sun20i-gpadc-iio.c +5
-0+ num_channels =devm_iio_adc_device_alloc_chaninfo_se (dev, + &sun20i_gpadc_chan_template,-1 , &channels); +if (num_channels <0 ) +return num_channels; +if (num_channels ==0 )return dev_err_probe (dev, -ENODEV ,"no channel children\n" );Note, this what I would expected in your helper to see, i.e. separated cases for < 0 (error code) and == 0, no channels.
Quoted 3 lines
Also, are all users going to have this check? Usually in other similar APIs we return
-ENOENT. And user won't need to have an additional check in case of 0 being considered as an error case too.
In a few cases we'll need to do the dance the other way in the caller. So specifically check for -ENOENT and not treat it as an error.
That stems from channel nodes being optionally added to drivers after they have been around a while (usually to add more specific configuration) and needing to maintain old behaviour of presenting all channels with default settings.
I agree that returning -ENOENT is a reasonable way to handle this.
Jonathan
Quoted 4 lines
Matti Vaittinen
maintainerRe: [PATCH v7 05/10] iio: adc: sun20i-gpadc: Use adc-helpers
Quoted 42 lines · Jonathan Cameron
Quoted 33 lines · On Thu, 13 Mar 2025 14:34:24 +0200 Andy Shevchenko…
Quoted 18 lines · Matti Vaittinen
The new
devm_iio_adc_device_alloc_chaninfo_se()-helper is intended to help drivers avoid open-coding thefor_each_node-loop for getting the channel IDs. The helper provides standard way to detect the ADC channel nodes (by the node name), and a standard way to convert the "reg" -properties to channel identification numbers, used in the structiio_chan_spec. Furthermore, the helper can optionally check the found channel IDs are smaller than given maximum. This is useful for callers which later use the IDs for example for indexing a channel data array.The original driver treated all found child nodes as channel nodes. The new helper requires channel nodes to be named channel[@N]. This should help avoid problems with devices which may contain also other but ADC child nodes. Quick grep from
arch/*with the sun20i-gpadc's compatible string didn't reveal any in-tree .dts with channel nodes named otherwise. Also, same grep shows all the in-tree .dts seem to have channel IDs between 0..num of channels.Use the new helper.
...
drivers/iio/adc/sun20i-gpadc-iio.c static void sun20i_gpadc_reset_assert(void *data) · line 172
Quoted 7 lines
drivers/iio/adc/sun20i-gpadc-iio.c +5
-0+ num_channels =devm_iio_adc_device_alloc_chaninfo_se (dev, + &sun20i_gpadc_chan_template,-1 , &channels); +if (num_channels <0 ) +return num_channels; +if (num_channels ==0 )return dev_err_probe (dev, -ENODEV ,"no channel children\n" );Note, this what I would expected in your helper to see, i.e. separated cases for < 0 (error code) and == 0, no channels.
Quoted 3 lines
Also, are all users going to have this check? Usually in other similar APIs we return
-ENOENT. And user won't need to have an additional check in case of 0 being considered as an error case too.In a few cases we'll need to do the dance the other way in the caller. So specifically check for
-ENOENTand not treat it as an error.
Quoted 6 lines
That stems from channel nodes being optionally added to drivers after they have been around a while (usually to add more specific configuration) and needing to maintain old behaviour of presenting all channels with default settings.
I agree that returning
-ENOENTis a reasonable way to handle this.
I agree - but I'm going to use -ENODEV instead of -ENOENT because that's what the current callers return if they find no channels. That way the drivers can return the value directly without converting -ENOENT to -ENODEV.
Yours,
-- Matti
Andy Shevchenko
reviewerRe: [PATCH v7 05/10] iio: adc: sun20i-gpadc: Use adc-helpers
Quoted 4 lines · Matti Vaittinen
Quoted 3 lines · Jonathan Cameron
Quoted 1 line · On Thu, 13 Mar 2025 14:34:24 +0200 Andy Shevchenko…
On Thu, Mar 13, 2025 at 09:18:49AM +0200, Matti Vaittinen wrote:
...
Quoted 22 lines
Quoted 22 lines
Quoted 11 lines
drivers/iio/adc/sun20i-gpadc-iio.c static void sun20i_gpadc_reset_assert(void *data) · line 172
Quoted 7 lines
drivers/iio/adc/sun20i-gpadc-iio.c +5
-0+ num_channels =devm_iio_adc_device_alloc_chaninfo_se (dev, + &sun20i_gpadc_chan_template,-1 , &channels); +if (num_channels <0 ) +return num_channels; +if (num_channels ==0 )return dev_err_probe (dev, -ENODEV ,"no channel children\n" );Note, this what I would expected in your helper to see, i.e. separated cases for < 0 (error code) and == 0, no channels.
Quoted 3 lines
Also, are all users going to have this check? Usually in other similar APIs we return
-ENOENT. And user won't need to have an additional check in case of 0 being considered as an error case too.In a few cases we'll need to do the dance the other way in the caller. So specifically check for
-ENOENTand not treat it as an error.That stems from channel nodes being optionally added to drivers after they have been around a while (usually to add more specific configuration) and needing to maintain old behaviour of presenting all channels with default settings.
Quoted 5 lines
Quoted 1 line
I agree that returning
-ENOENTis a reasonable way to handle this.I agree - but I'm going to use
-ENODEVinstead of-ENOENTbecause that's what the current callers return if they find no channels. That way the drivers can return the value directly without converting-ENOENTto-ENODEV.
ENODEV can be easily clashed with other irrelevant cases, ENOENT is the correct error code. If drivers return this instead of another error code, nothing bad happen, it's not an ABI path, correct?
Signature · 2 lines
With Best Regards, Andy Shevchenko
Matti Vaittinen
maintainerRe: [PATCH v7 05/10] iio: adc: sun20i-gpadc: Use adc-helpers
Quoted 30 lines · Andy Shevchenko
Quoted 4 lines · Matti Vaittinen
Quoted 3 lines · Jonathan Cameron
Quoted 1 line · On Thu, 13 Mar 2025 14:34:24 +0200 Andy Shevchenko…
On Thu, Mar 13, 2025 at 09:18:49AM +0200, Matti Vaittinen wrote:
...
Quoted 22 lines
Quoted 22 lines
Quoted 11 lines
drivers/iio/adc/sun20i-gpadc-iio.c static void sun20i_gpadc_reset_assert(void *data) · line 172
Quoted 7 lines
drivers/iio/adc/sun20i-gpadc-iio.c +5
-0+ num_channels =devm_iio_adc_device_alloc_chaninfo_se (dev, + &sun20i_gpadc_chan_template,-1 , &channels); +if (num_channels <0 ) +return num_channels; +if (num_channels ==0 )return dev_err_probe (dev, -ENODEV ,"no channel children\n" );Note, this what I would expected in your helper to see, i.e. separated cases for < 0 (error code) and == 0, no channels.
Quoted 3 lines
Also, are all users going to have this check? Usually in other similar APIs we return
-ENOENT. And user won't need to have an additional check in case of 0 being considered as an error case too.In a few cases we'll need to do the dance the other way in the caller. So specifically check for
-ENOENTand not treat it as an error.That stems from channel nodes being optionally added to drivers after they have been around a while (usually to add more specific configuration) and needing to maintain old behaviour of presenting all channels with default settings.
Quoted 7 lines
Quoted 5 lines
Quoted 1 line
I agree that returning
-ENOENTis a reasonable way to handle this.I agree - but I'm going to use
-ENODEVinstead of-ENOENTbecause that's what the current callers return if they find no channels. That way the drivers can return the value directly without converting-ENOENTto-ENODEV.ENODEV can be easily clashed with other irrelevant cases,
Can you please explain what cases?
Quoted 2 lines
ENOENT is the correct
error code.
I kind of agree if we look this from the fwnode perspective. But, when we look this from the intended user's perspective, I can very well understand the -ENODEV. Returning -ENODEV from ADC driver's probe which can't find any of the channels feels correct to me.
Quoted 2 lines
If drivers return this instead of another error code, nothing bad happen, it's not an ABI path, correct?
I don't know if failure returned from a probe is an ABI. I still feel -ENODEV is correct value, and I don't want to change it for existing users - and I think also new ADC drivers should use -ENODEV if they find no channels at all.
Besides that I think -ENODEV to be right, changing it to -ENOENT for existing callers requires a buy-in from Jonathan (and/or) the driver maintainers.
Yours,
-- Matti
Andy Shevchenko
reviewerRe: [PATCH v7 05/10] iio: adc: sun20i-gpadc: Use adc-helpers
Quoted 6 lines · Matti Vaittinen
Quoted 5 lines · Andy Shevchenko
Quoted 4 lines · Matti Vaittinen
Quoted 3 lines · Jonathan Cameron
Quoted 1 line · On Thu, 13 Mar 2025 14:34:24 +0200 Andy Shevchenko…
On Thu, Mar 13, 2025 at 09:18:49AM +0200, Matti Vaittinen wrote:
...
Quoted 24 lines
Quoted 24 lines
Quoted 24 lines
Quoted 23 lines
Quoted 11 lines
drivers/iio/adc/sun20i-gpadc-iio.c static void sun20i_gpadc_reset_assert(void *data) · line 172
Quoted 7 lines
drivers/iio/adc/sun20i-gpadc-iio.c +5
-0+ num_channels =devm_iio_adc_device_alloc_chaninfo_se (dev, + &sun20i_gpadc_chan_template,-1 , &channels); +if (num_channels <0 ) +return num_channels; +if (num_channels ==0 )return dev_err_probe (dev, -ENODEV ,"no channel children\n" );Note, this what I would expected in your helper to see, i.e. separated cases for < 0 (error code) and == 0, no channels.
Quoted 3 lines
Also, are all users going to have this check? Usually in other similar APIs we return
-ENOENT. And user won't need to have an additional check in case of 0 being considered as an error case too.In a few cases we'll need to do the dance the other way in the caller. So specifically check for
-ENOENTand not treat it as an error.That stems from channel nodes being optionally added to drivers after they have been around a while (usually to add more specific configuration) and needing to maintain old behaviour of presenting all channels with default settings.
I agree that returning
-ENOENTis a reasonable way to handle this.
Quoted 7 lines
Quoted 5 lines
Quoted 3 lines
I agree - but I'm going to use
-ENODEVinstead of-ENOENTbecause that's what the current callers return if they find no channels. That way the drivers can return the value directly without converting-ENOENTto-ENODEV.ENODEV can be easily clashed with other irrelevant cases,
Can you please explain what cases?
When it's a code path that returns the same error code for something different.
Quoted 7 lines
Quoted 2 lines
ENOENT is the correct
error code.I kind of agree if we look this from the fwnode perspective. But, when we look this from the intended user's perspective, I can very well understand the
-ENODEV. Returning-ENODEVfrom ADC driver's probe which can't find any of the channels feels correct to me.
Okay, it seems we have got yet another disagreement as I think this has to be ENOENT. Because this is related to the firmware description and not real hardware discovery path. If it is the latter, I may fully agree on ENODEV choice. But AFAICS it's not the case here.
Quoted 5 lines
Quoted 2 lines
If drivers return this instead of another error code, nothing bad happen, it's not an ABI path, correct?
I don't know if failure returned from a probe is an ABI. I still feel
-ENODEVis correct value,
And I have the opposite opinion. I think ENODEV is _incorrect_ choice in this case.
Quoted 3 lines
and I don't want to change it for existing users -
and I think also new ADC drivers should use-ENODEVif they find no channels at all.
Again, the problem is that you are trying to apply the error code for HW to the information that comes from FW.
Quoted 3 lines
Besides that I think
-ENODEVto be right, changing it to-ENOENTfor existing callers requires a buy-in from Jonathan (and/or) the driver maintainers.
Yeah, will wait for Jonathan to judge, but I think you can find rationale above.
Signature · 2 lines
With Best Regards, Andy Shevchenko
Jonathan Cameron
maintainerRe: [PATCH v7 05/10] iio: adc: sun20i-gpadc: Use adc-helpers
Quoted 52 lines · On Mon, 17 Mar 2025 11:27:37 +0200 Andy Shevchenko…
Quoted 6 lines · Matti Vaittinen
Quoted 5 lines · Andy Shevchenko
Quoted 4 lines · Matti Vaittinen
Quoted 3 lines · Jonathan Cameron
Quoted 1 line · On Thu, 13 Mar 2025 14:34:24 +0200 Andy Shevchenko…
On Thu, Mar 13, 2025 at 09:18:49AM +0200, Matti Vaittinen wrote:
...
Quoted 24 lines
Quoted 24 lines
Quoted 24 lines
Quoted 23 lines
Quoted 11 lines
Review
Quoted 7 lines
(quoted diff) +5
-0+ num_channels = devm_iio_adc_device_alloc_chaninfo_se(dev, + &sun20i_gpadc_chan_template, -1, &channels); + if (num_channels < 0) + return num_channels; + if (num_channels == 0) return dev_err_probe(dev, -ENODEV, "no channel children\n");Note, this what I would expected in your helper to see, i.e. separated cases for < 0 (error code) and == 0, no channels.
Quoted 3 lines
Also, are all users going to have this check? Usually in other similar APIs we return
-ENOENT. And user won't need to have an additional check in case of 0 being considered as an error case too.In a few cases we'll need to do the dance the other way in the caller. So specifically check for
-ENOENTand not treat it as an error.That stems from channel nodes being optionally added to drivers after they have been around a while (usually to add more specific configuration) and needing to maintain old behaviour of presenting all channels with default settings.
I agree that returning
-ENOENTis a reasonable way to handle this.Quoted 7 lines
Quoted 5 lines
Quoted 3 lines
I agree - but I'm going to use
-ENODEVinstead of-ENOENTbecause that's what the current callers return if they find no channels. That way the drivers can return the value directly without converting-ENOENTto-ENODEV.ENODEV can be easily clashed with other irrelevant cases,
Can you please explain what cases?
When it's a code path that returns the same error code for something different.
Quoted 7 lines
Quoted 2 lines
ENOENT is the correct
error code.I kind of agree if we look this from the fwnode perspective. But, when we look this from the intended user's perspective, I can very well understand the
-ENODEV. Returning-ENODEVfrom ADC driver's probe which can't find any of the channels feels correct to me.
Quoted 4 lines
Okay, it seems we have got yet another disagreement as I think this has to be ENOENT. Because this is related to the firmware description and not real hardware discovery path. If it is the latter, I may fully agree on ENODEV choice. But AFAICS it's not the case here.
I'd not rule so strongly but -ENOENT is fine and there should be no fall out from standardizing around that.
Quoted 14 lines
Quoted 6 lines
Quoted 3 lines
If drivers return this instead of another error code, nothing bad happen, it's not an ABI path, correct?
I don't know if failure returned from a probe is an ABI. I still feel
-ENODEVis correct value,And I have the opposite opinion. I think ENODEV is _incorrect_ choice in this case.
Quoted 3 lines
and I don't want to change it for existing users -
and I think also new ADC drivers should use-ENODEVif they find no channels at all.
Quoted 8 lines
Again, the problem is that you are trying to apply the error code for HW to the information that comes from FW.
Quoted 3 lines
Besides that I think
-ENODEVto be right, changing it to-ENOENTfor existing callers requires a buy-in from Jonathan (and/or) the driver maintainers.Yeah, will wait for Jonathan to judge, but I think you can find rationale above.
The distinction between hardware not there (-ENODEV) and missing stuff in FW (-ENOENT) seems reasonable to make. If anyone is relying on capturing a specific error code and doing anything much with it beyond logging for debug then they are very optimistic as this stuff is often not particularly stable over kernel versions. That sort of error code specific handling only makes sense very locally, not in probe() return values.
Hence my preference here is switch to -ENOENT and we'll go with that for
new code in general that hits this sort of problem. I'd not consider
older code returning -ENODEV buggy as such, just slightly less than ideal. So any changes for now probably belong in series touching the code for other reasons rather than a mass cleanup.
Jonathan
Matti Vaittinen
maintainerPATCH v7 6/10 iio: adc: Support ROHM BD79124 ADC
In reply to Matti VaittinenThe ROHM BD79124 is a 12-bit, 8-channel, SAR ADC. The ADC supports an automatic measurement mode, with an alarm interrupt for out-of-window measurements. The window is configurable for each channel.
The I2C protocol for manual start of the measurement and data reading is somewhat peculiar. It requires the master to do clock stretching after sending the I2C slave-address until the slave has captured the data. Needless to say this is not well suopported by the I2C controllers.
Thus the driver does not support the BD79124's manual measurement mode but implements the measurements using automatic measurement mode relying on the BD79124's ability of storing latest measurements into register.
The driver does also support configuring the threshold events for detecting the out-of-window events.
The BD79124 keeps asserting IRQ for as long as the measured voltage is out of the configured window. Thus the driver masks the received event for a fixed duration (1 second) when an event is handled. This prevents the user-space from choking on the events
The ADC input pins can be also configured as general purpose outputs. Those pins which don't have corresponding ADC channel node in the device-tree will be controllable as GPO.
---
Revision history:
v6 => v7:
- Styling
v5 => v6:
- Styling as suggested by Jonathan
v4 => v5:
- Drop unused interval defines
- Append unit to interval define and drop a comment
- Drop parenthesis around bitwise negation operation ~
- Use proper block comment style
- Improve the documentation of the re-enabling the events by moving comment explaining early return to the point of the return, and by adding own comment for the reason of locking before calling the re-enabling
- Indenting
- Drop unused struct bd79124_reg_init
- Drop bd79124_init_mux() wrapper and call the regmap_write() directly
v3 => v4:
- Adapt to 'drop diff-channel support' changes to ADC-helpers
- Don't parse fwnode in GPIO valid-mask callback but use pin config cached at probe()
- Drop use of iio_adc_device_channels_by_property()
- Open code the bd79124_reg_init loop (as suggested by Jonathan)
- Use devm variant of mutex_init()
- Styling
v2 => v3:
- Fix uninitialized return value reported by the kernel test robot
- Fix indent
- Adapt to adc-helper changes supporting also single-ended and differential channels
RFC v1 => v2:
- Add event throttling (constant delay of 1 sec)
- rename variable 'd' to 'data'
- Use ADC helpers to detect pins used for ADC
- bd79124 drop MFD and pinmux && handle GPO in this driver
- Drop adc suffix from the IIO file name
drivers/iio/adc/rohm-bd79124.c styling
--- drivers/iio/adc/Kconfig | 12 + drivers/iio/adc/Makefile | 1 + drivers/iio/adc/rohm-bd79124.c | 1107 ++++++++++++++++++++++++++++++++ 3 files changed, 1120 insertions(+) create mode 100644 drivers/iio/adc/rohm-bd79124.c
drivers/iio/adc/Kconfig +12 -0
@@ -1191,6 +1191,18 @@ config RN5T618_ADC This driver can also be built as a module. If so, the module will be called rn5t618-adc. +config ROHM_BD79124 + tristate "Rohm BD79124 ADC driver" + depends on I2C + select REGMAP_I2C + select IIO_ADC_HELPER + help + Say yes here to build support for the ROHM BD79124 ADC. The + ROHM BD79124 is a 12-bit, 8-channel, SAR ADC. The ADC supports + also an automatic measurement mode, with an alarm interrupt for + out-of-window measurements. The window is configurable for each + channel. + config ROCKCHIP_SARADC tristate "Rockchip SARADC driver" depends on ARCH_ROCKCHIP || COMPILE_TEST
drivers/iio/adc/Makefile +1 -0
@@ -109,6 +109,7 @@ obj-$(CONFIG_QCOM_VADC_COMMON) += qcom-vadc-common.o obj-$(CONFIG_RCAR_GYRO_ADC) += rcar-gyroadc.o obj-$(CONFIG_RICHTEK_RTQ6056) += rtq6056.o obj-$(CONFIG_RN5T618_ADC) += rn5t618-adc.o +obj-$(CONFIG_ROHM_BD79124) += rohm-bd79124.o obj-$(CONFIG_ROCKCHIP_SARADC) += rockchip_saradc.o obj-$(CONFIG_RZG2L_ADC) += rzg2l_adc.o obj-$(CONFIG_SC27XX_ADC) += sc27xx_adc.o
drivers/iio/adc/rohm-bd79124.c new file +1107 -0
1,107 lines not on this page · raw message
Signature · 1 line
2.48.1
Andy Shevchenko
reviewerRe: [PATCH v7 06/10] iio: adc: Support ROHM BD79124 ADC
Quoted 24 lines · Matti Vaittinen
The ROHM BD79124 is a 12-bit, 8-channel, SAR ADC. The ADC supports an automatic measurement mode, with an alarm interrupt for out-of-window measurements. The window is configurable for each channel.
The I2C protocol for manual start of the measurement and data reading is somewhat peculiar. It requires the master to do clock stretching after sending the I2C slave-address until the slave has captured the data. Needless to say this is not well suopported by the I2C controllers.
Thus the driver does not support the BD79124's manual measurement mode but implements the measurements using automatic measurement mode relying on the BD79124's ability of storing latest measurements into register.
The driver does also support configuring the threshold events for detecting the out-of-window events.
The BD79124 keeps asserting IRQ for as long as the measured voltage is out of the configured window. Thus the driver masks the received event for a fixed duration (1 second) when an event is handled. This prevents the user-space from choking on the events
The ADC input pins can be also configured as general purpose outputs. Those pins which don't have corresponding ADC channel node in the device-tree will be controllable as GPO.
...
Quoted 1 line
+#define
BD79124_REG_SYSTEM_STATUS0x0
I would expect to see 0x00
Quoted 5 lines
drivers/iio/adc/rohm-bd79124.c new file +5
-0+#define BD79124_REG_GEN_CFG 0x01 +#define BD79124_REG_OPMODE_CFG 0x04 +#define BD79124_REG_PINCFG 0x05 +#define BD79124_REG_GPO_VAL 0x0B +#define BD79124_REG_SEQUENCE_CFG 0x10
drivers/iio/adc/rohm-bd79124.c line 49
Quoted 10 lines
drivers/iio/adc/rohm-bd79124.c new file +10
-0+#define BD79124_REG_MANUAL_CHANNELS 0x11 +#define BD79124_REG_AUTO_CHANNELS 0x12 +#define BD79124_REG_ALERT_CH_SEL 0x14 +#define BD79124_REG_EVENT_FLAG 0x18 +#define BD79124_REG_EVENT_FLAG_HI 0x1a +#define BD79124_REG_EVENT_FLAG_LO 0x1c +#define BD79124_REG_HYSTERESIS_CH0 0x20 +#define BD79124_REG_EVENTCOUNT_CH0 0x22 +#define BD79124_REG_RECENT_CH0_LSB 0xa0 +#define BD79124_REG_RECENT_CH7_MSB 0xaf
...
Wouldn't be better...
drivers/iio/adc/rohm-bd79124.c line 56
Quoted 5 lines
drivers/iio/adc/rohm-bd79124.c new file +5
-0+#define BD79124_MASK_CONV_MODE GENMASK(6, 5) +#define BD79124_MASK_AUTO_INTERVAL GENMASK(1, 0) +#define BD79124_CONV_MODE_MANSEQ 0 +#define BD79124_CONV_MODE_AUTO 1 +#define BD79124_INTERVAL_750_US 0
To group masks and values of the same bitfields?
#define BD79124_MASK_CONV_MODE GENMASK(6, 5)
#define BD79124_CONV_MODE_MANSEQ 0
#define BD79124_CONV_MODE_AUTO 1
#define BD79124_MASK_AUTO_INTERVAL GENMASK(1, 0)
#define BD79124_INTERVAL_750_US 0
drivers/iio/adc/rohm-bd79124.c line 67
Quoted 10 lines
drivers/iio/adc/rohm-bd79124.c new file +10
-0+#define BD79124_MASK_DWC_EN BIT(4) +#define BD79124_MASK_STATS_EN BIT(5) +#define BD79124_MASK_SEQ_START BIT(4) +#define BD79124_MASK_SEQ_MODE GENMASK(1, 0) +#define BD79124_MASK_SEQ_MANUAL 0 +#define BD79124_MASK_SEQ_SEQ 1 + +#define BD79124_MASK_HYSTERESIS GENMASK(3, 0) +#define BD79124_LOW_LIMIT_MIN 0 +#define BD79124_HIGH_LIMIT_MAX GENMASK(11, 0)
These masks are not named after registers (or I don't see it clearly), it's hard to understand which one relates to which register. Also, why not using bitfield.h?
...
Quoted 1 line
+ * These macros return the address of the 1.st reg for the given channel
first
(and missing period at the end).
drivers/iio/adc/rohm-bd79124.c line 80
Quoted 5 lines
drivers/iio/adc/rohm-bd79124.c new file +5
-0+#define BD79124_GET_HIGH_LIMIT_REG (ch) (BD79124_REG_HYSTERESIS_CH0 + (ch) * 4) +#define BD79124_GET_LOW_LIMIT_REG (ch) (BD79124_REG_EVENTCOUNT_CH0 + (ch) * 4) +#define BD79124_GET_LIMIT_REG (ch, dir) ((dir) == IIO_EV_DIR_RISING ? \ + BD79124_GET_HIGH_LIMIT_REG(ch) : BD79124_GET_LOW_LIMIT_REG(ch)) +#define BD79124_GET_RECENT_RES_REG (ch) (BD79124_REG_RECENT_CH0_LSB + (ch) * 2)
Don't we want to have something in bitfield.h for arrays in the register, i.e. when register(s) is(are) split to 2+ bits per an element in an array of the same semantics. Would be nice to eliminate such a boilerplate here and in many other drivers.
Quoted 38 lines
drivers/iio/adc/rohm-bd79124.c new file +38
-0+/* +* The hysteresis for a channel is stored in the same register where the +* 4 bits of high limit reside. +*/ +#define BD79124_GET_HYSTERESIS_REG (ch) BD79124_GET_HIGH_LIMIT_REG(ch) + +#define BD79124_MAX_NUM_CHANNELS 8 + +struct bd79124_data { +s64 timestamp; +struct regmap *map; +struct device *dev; +int vmax; +/* +* Keep measurement status so read_raw() knows if the measurement needs +* to be started. +*/ +int alarm_monitored[BD79124_MAX_NUM_CHANNELS ]; +/* +* The BD79124 does not allow disabling/enabling limit separately for +* one direction only. Hence, we do the disabling by changing the limit +* to maximum/minimum measurable value. This means we need to cache +* the limit in order to maintain it over the time limit is disabled. +*/ +u16 alarm_r_limit[BD79124_MAX_NUM_CHANNELS ]; +u16 alarm_f_limit[BD79124_MAX_NUM_CHANNELS ]; +/* Bitmask of disabled events (for rate limiting) for each channel. */ +int alarm_suppressed[BD79124_MAX_NUM_CHANNELS ]; +/* +* The BD79124 is configured to run the measurements in the background. +* This is done for the event monitoring as well as for the read_raw(). +* Protect the measurement starting/stopping using a mutex. +*/ +struct mutex mutex; +struct delayed_work alm_enable_work; +struct gpio_chip gc; +u8 gpio_valid_mask; +};
...
Quoted 1 line
+static void
bd79124gpo_set(struct gpio_chip *gc, unsigned int offset, int value)
You should use .set_rv()
...
drivers/iio/adc/rohm-bd79124.c line 203
Quoted 2 lines
drivers/iio/adc/rohm-bd79124.c new file +2
-0+static void bd79124gpo_set_multiple (struct gpio_chip *gc,unsigned long *mask, +unsigned long *bits)
Ditto, .set_multiple_rv().
Review
Quoted 2 lines
(quoted diff) +2
-0+{ + int ret, val;
Here and everywhere else, the returned value by regmap is unsigned int.
Quoted 15 lines
drivers/iio/adc/rohm-bd79124.c new file +15
-0+struct bd79124_data *data =gpiochip_get_data (gc); + +/* Ensure all GPIOs in 'mask' are set to be GPIOs */ + ret =regmap_read (data->map,BD79124_REG_PINCFG , &val); +if (ret) +return ; + +if ((val & *mask) != *mask) { +dev_dbg (data->dev,"Invalid mux config. Can't set value.\n" ); +/* Do not set value for pins configured as ADC inputs */ + *mask &= val; + } + +regmap_update_bits (data->map,BD79124_REG_GPO_VAL , *mask, *bits); +}
...
drivers/iio/adc/rohm-bd79124.c line 249
Quoted 5 lines
drivers/iio/adc/rohm-bd79124.c new file +5
-0+struct bd79124_raw { +u8 bit0_3;/* Is set in high bits of the byte */ +u8 bit4_11; +}; +#define BD79124_RAW_TO_INT (r) ((r.bit4_11 << 4) | (r.bit0_3 >> 4))
And how this is different from treating it as __le16? Needs a good comment about bit layout.
...
drivers/iio/adc/rohm-bd79124.c line 294
Quoted 8 lines
drivers/iio/adc/rohm-bd79124.c new file +7
-0+static int bd79124_write_int_to_reg (struct bd79124_data *data,int reg, +unsigned int val) +{ +struct bd79124_raw raw; +int ret, tmp; + raw.bit4_11 = (u8)(val >>4 ); + raw.bit0_3 = (u8)(val <<4 );
Why casting?
Make sense to have a symmetrical macro instead of hiding it in the code.
drivers/iio/adc/rohm-bd79124.c line 300
Quoted 5 lines
drivers/iio/adc/rohm-bd79124.c new file +5
-0+ ret =regmap_read (data->map, reg, &tmp); +if (ret) +return ret; + + raw.bit0_3 |= (0xf & tmp);
GENMASK() ?
Quoted 2 lines
drivers/iio/adc/rohm-bd79124.c new file +2
-0+return regmap_bulk_write (data->map, reg, &raw,sizeof (raw)); +}
...
drivers/iio/adc/rohm-bd79124.c line 374
Quoted 3 lines
drivers/iio/adc/rohm-bd79124.c new file +3
-0+/* +* The data-sheet says the hysteresis register value needs to be +* sifted left by 3
Missing period.
Quoted 1 line
(quoted diff) +1
-0+ */
...
drivers/iio/adc/rohm-bd79124.c line 468
Quoted 1 line
drivers/iio/adc/rohm-bd79124.c new file +1
-0+return (data->alarm_monitored[chan->channel] &BIT (dir));
Unneeded parentheses.
...
drivers/iio/adc/rohm-bd79124.c line 616
Quoted 3 lines
drivers/iio/adc/rohm-bd79124.c new file +3
-0+case IIO_EV_INFO_HYSTERESIS : + reg =BD79124_GET_HYSTERESIS_REG (chan->channel); + val >>=3 ;
Second time I see this. Perhaps you need a macro to explain this right shift?
drivers/iio/adc/rohm-bd79124.c line 619
Quoted 2 lines
drivers/iio/adc/rohm-bd79124.c new file +2
-0+return regmap_update_bits (data->map, reg,BD79124_MASK_HYSTERESIS , + val);
Can be one line.
...
Quoted 10 lines
drivers/iio/adc/rohm-bd79124.c new file +10
-0+static irqreturn_t bd79124_event_handler (int irq,void *priv) +{ +int ret, i_hi, i_lo, i; +struct iio_dev *iio_dev = priv; +struct bd79124_data *data =iio_priv (iio_dev); + +/* +* Return IRQ_NONE if bailing-out without acking. This allows the IRQ +* subsystem to disable the offending IRQ line if we get a hardware +* problem. This behaviour has saved my poor bottom a few times in the
drivers/iio/adc/rohm-bd79124.c line 862
Quoted 10 lines
drivers/iio/adc/rohm-bd79124.c new file +10
-0+* past as, instead of getting unusably unresponsive, the system has +* spilled out the magic words "...nobody cared". +*/ + ret =regmap_read (data->map,BD79124_REG_EVENT_FLAG_HI , &i_hi); +if (ret) +return IRQ_NONE ; + + ret =regmap_read (data->map,BD79124_REG_EVENT_FLAG_LO , &i_lo); +if (ret) +return IRQ_NONE ;
Only I don't get why you can't use bulk read here. The registers seem to be sequential.
Quoted 34 lines
drivers/iio/adc/rohm-bd79124.c new file +34
-0+if (!i_lo && !i_hi) +return IRQ_NONE ; + +for (i =0 ; i <BD79124_MAX_NUM_CHANNELS ; i++) { +u64 ecode; + +if (BIT (i) & i_hi) { + ecode =IIO_UNMOD_EVENT_CODE (IIO_VOLTAGE , i, +IIO_EV_TYPE_THRESH , +IIO_EV_DIR_RISING ); + +iio_push_event (iio_dev, ecode, data->timestamp); +/* +* The BD79124 keeps the IRQ asserted for as long as +* the voltage exceeds the threshold. It causes the IRQ +* to keep firing. +* +* Disable the event for the channel and schedule the +* re-enabling the event later to prevent storm of +* events. +*/ + ret =bd79124_event_ratelimit_hi (data, i); +if (ret) +return IRQ_NONE ; + } +if (BIT (i) & i_lo) { + ecode =IIO_UNMOD_EVENT_CODE (IIO_VOLTAGE , i, +IIO_EV_TYPE_THRESH , +IIO_EV_DIR_FALLING ); + +iio_push_event (iio_dev, ecode, data->timestamp); + ret =bd79124_event_ratelimit_lo (data, i); +if (ret) +return IRQ_NONE ;
drivers/iio/adc/rohm-bd79124.c line 907
Quoted 10 lines
drivers/iio/adc/rohm-bd79124.c new file +10
-0+ } + } + + ret =regmap_write (data->map,BD79124_REG_EVENT_FLAG_HI , i_hi); +if (ret) +return IRQ_NONE ; + + ret =regmap_write (data->map,BD79124_REG_EVENT_FLAG_LO , i_lo); +if (ret) +return IRQ_NONE ;
In the similar way bulk write.
Quoted 2 lines
drivers/iio/adc/rohm-bd79124.c new file +2
-0+return IRQ_HANDLED ; +}
...
drivers/iio/adc/rohm-bd79124.c line 926
Quoted 5 lines
drivers/iio/adc/rohm-bd79124.c new file +5
-0+static int bd79124_chan_init (struct bd79124_data *data,int channel) +{ +int ret; + + ret =regmap_write (data->map,BD79124_GET_HIGH_LIMIT_REG (channel),4095 );
BD79124_HIGH_LIMIT_MAX ?
drivers/iio/adc/rohm-bd79124.c line 930
Quoted 4 lines
drivers/iio/adc/rohm-bd79124.c new file +4
-0+if (ret) +return ret; + +return regmap_write (data->map,BD79124_GET_LOW_LIMIT_REG (channel),0 );
BD79124_HIGH_LIMIT_MIN ?
Quoted 1 line
+}
...
drivers/iio/adc/rohm-bd79124.c line 961
Quoted 5 lines
drivers/iio/adc/rohm-bd79124.c new file +5
-0+for (i =0 ; i <BD79124_MAX_NUM_CHANNELS ; i++) { + ret =bd79124_chan_init (data, i); +if (ret) +return ret; + data->alarm_r_limit[i] =4095 ;
As per above?
Quoted 1 line
(quoted diff) +1
-0+ }
...
drivers/iio/adc/rohm-bd79124.c line 1056
Quoted 2 lines
drivers/iio/adc/rohm-bd79124.c new file +2
-0+ gpio_pins =bd79124_get_gpio_pins (iio_dev->channels, + iio_dev->num_channels);
It may be a single line (84 characters).
...
drivers/iio/adc/rohm-bd79124.c line 1089
Quoted 2 lines
drivers/iio/adc/rohm-bd79124.c new file +2
-0+static const struct i2c_device_id bd79124_id[] = { + {"bd79124" , },
Redundant inner comma.
Quoted 2 lines
(quoted diff) +2
-0+ { } +};
Signature · 2 lines
With Best Regards, Andy Shevchenko
Matti Vaittinen
maintainerRe: [PATCH v7 06/10] iio: adc: Support ROHM BD79124 ADC
Quoted 26 lines · Andy Shevchenko
Quoted 16 lines · Matti Vaittinen
The ROHM BD79124 is a 12-bit, 8-channel, SAR ADC. The ADC supports an automatic measurement mode, with an alarm interrupt for out-of-window measurements. The window is configurable for each channel.
The I2C protocol for manual start of the measurement and data reading is somewhat peculiar. It requires the master to do clock stretching after sending the I2C slave-address until the slave has captured the data. Needless to say this is not well suopported by the I2C controllers.
Thus the driver does not support the BD79124's manual measurement mode but implements the measurements using automatic measurement mode relying on the BD79124's ability of storing latest measurements into register.
The driver does also support configuring the threshold events for detecting the out-of-window events.
Quoted 8 lines
The BD79124 keeps asserting IRQ for as long as the measured voltage is out of the configured window. Thus the driver masks the received event for a fixed duration (1 second) when an event is handled. This prevents the user-space from choking on the events
The ADC input pins can be also configured as general purpose outputs. Those pins which don't have corresponding ADC channel node in the device-tree will be controllable as GPO.
Quoted 5 lines
...
Quoted 1 line
+#define
BD79124_REG_SYSTEM_STATUS0x0I would expect to see
0x00
ok.
Quoted 29 lines
Quoted 6 lines
drivers/iio/adc/rohm-bd79124.c new file +5
-0+#define BD79124_REG_GEN_CFG 0x01 +#define BD79124_REG_OPMODE_CFG 0x04 +#define BD79124_REG_PINCFG 0x05 +#define BD79124_REG_GPO_VAL 0x0B +#define BD79124_REG_SEQUENCE_CFG 0x10drivers/iio/adc/rohm-bd79124.c line 49
Quoted 10 lines
drivers/iio/adc/rohm-bd79124.c new file +10
-0+#define BD79124_REG_MANUAL_CHANNELS 0x11 +#define BD79124_REG_AUTO_CHANNELS 0x12 +#define BD79124_REG_ALERT_CH_SEL 0x14 +#define BD79124_REG_EVENT_FLAG 0x18 +#define BD79124_REG_EVENT_FLAG_HI 0x1a +#define BD79124_REG_EVENT_FLAG_LO 0x1c +#define BD79124_REG_HYSTERESIS_CH0 0x20 +#define BD79124_REG_EVENTCOUNT_CH0 0x22 +#define BD79124_REG_RECENT_CH0_LSB 0xa0 +#define BD79124_REG_RECENT_CH7_MSB 0xaf...
Wouldn't be better...
drivers/iio/adc/rohm-bd79124.c line 56
Quoted 5 lines
drivers/iio/adc/rohm-bd79124.c new file +5
-0+#define BD79124_MASK_CONV_MODE GENMASK(6, 5) +#define BD79124_MASK_AUTO_INTERVAL GENMASK(1, 0) +#define BD79124_CONV_MODE_MANSEQ 0 +#define BD79124_CONV_MODE_AUTO 1 +#define BD79124_INTERVAL_750_US 0To group masks and values of the same bitfields?
Quoted 5 lines
#define
BD79124_MASK_CONV_MODEGENMASK(6, 5)
#defineBD79124_CONV_MODE_MANSEQ0
#defineBD79124_CONV_MODE_AUTO1
#defineBD79124_MASK_AUTO_INTERVALGENMASK(1, 0)
#defineBD79124_INTERVAL_750_US0
ok.
Quoted 13 lines
drivers/iio/adc/rohm-bd79124.c line 67
Quoted 11 lines
drivers/iio/adc/rohm-bd79124.c new file +10
-0+#define BD79124_MASK_DWC_EN BIT(4) +#define BD79124_MASK_STATS_EN BIT(5) +#define BD79124_MASK_SEQ_START BIT(4) +#define BD79124_MASK_SEQ_MODE GENMASK(1, 0) +#define BD79124_MASK_SEQ_MANUAL 0 +#define BD79124_MASK_SEQ_SEQ 1 + +#define BD79124_MASK_HYSTERESIS GENMASK(3, 0) +#define BD79124_LOW_LIMIT_MIN 0 +#define BD79124_HIGH_LIMIT_MAX GENMASK(11, 0)These masks are not named after registers (or I don't see it clearly),
Naming is hard. I usually try to make a balance between:
1) using names which explain the purpose when seen in the code (at call site)
2) keeping names short enough
3) following the naming convention in the data sheet
4) maintain relation to the register.
I put most emphasis to the 1, while 2 is important to me as well. 3 is _very_ nice to have, but it is often somehow contradicting with 1 and 2. 4 is IMO just nice to have. The register is usually clearly visible at call site, and if someone adds new functionality (or checks the correctness of the masks/registers), then 3 is way more important.
I am open to any concrete suggestions though.
Quoted 3 lines
it's
hard to understand which one relates to which register. Also, why not usingbitfield.h?
I saw no need for it?
Quoted 5 lines
...
Quoted 1 line
+ * These macros return the address of the 1.st reg for the given channel
first
Huh?
Quoted 1 line
(and missing period at the end).
Ok.
Quoted 10 lines
drivers/iio/adc/rohm-bd79124.c line 80
Quoted 5 lines
drivers/iio/adc/rohm-bd79124.c new file +5
-0+#define BD79124_GET_HIGH_LIMIT_REG (ch) (BD79124_REG_HYSTERESIS_CH0 + (ch) * 4) +#define BD79124_GET_LOW_LIMIT_REG (ch) (BD79124_REG_EVENTCOUNT_CH0 + (ch) * 4) +#define BD79124_GET_LIMIT_REG (ch, dir) ((dir) == IIO_EV_DIR_RISING ? \ + BD79124_GET_HIGH_LIMIT_REG(ch) : BD79124_GET_LOW_LIMIT_REG(ch)) +#define BD79124_GET_RECENT_RES_REG (ch) (BD79124_REG_RECENT_CH0_LSB + (ch) * 2)Don't we want to have something in
bitfield.hfor arrays in the register, i.e. when register(s) is(are) split to 2+ bits per an element in an array of the same semantics. Would be nice to eliminate such a boilerplate here and in many other drivers.
Not necessarily a bad idea. Still, I am not willing to expand this series any more - currently there is 10 patches, 2 of which are directly related to the BD79124. I don't want to delay this driver for another cycle due to added helpers.
Quoted 43 lines
Quoted 38 lines
drivers/iio/adc/rohm-bd79124.c new file +38
-0+/* +* The hysteresis for a channel is stored in the same register where the +* 4 bits of high limit reside. +*/ +#define BD79124_GET_HYSTERESIS_REG (ch) BD79124_GET_HIGH_LIMIT_REG(ch) + +#define BD79124_MAX_NUM_CHANNELS 8 + +struct bd79124_data { +s64 timestamp; +struct regmap *map; +struct device *dev; +int vmax; +/* +* Keep measurement status so read_raw() knows if the measurement needs +* to be started. +*/ +int alarm_monitored[BD79124_MAX_NUM_CHANNELS ]; +/* +* The BD79124 does not allow disabling/enabling limit separately for +* one direction only. Hence, we do the disabling by changing the limit +* to maximum/minimum measurable value. This means we need to cache +* the limit in order to maintain it over the time limit is disabled. +*/ +u16 alarm_r_limit[BD79124_MAX_NUM_CHANNELS ]; +u16 alarm_f_limit[BD79124_MAX_NUM_CHANNELS ]; +/* Bitmask of disabled events (for rate limiting) for each channel. */ +int alarm_suppressed[BD79124_MAX_NUM_CHANNELS ]; +/* +* The BD79124 is configured to run the measurements in the background. +* This is done for the event monitoring as well as for the read_raw(). +* Protect the measurement starting/stopping using a mutex. +*/ +struct mutex mutex; +struct delayed_work alm_enable_work; +struct gpio_chip gc; +u8 gpio_valid_mask; +};...
Quoted 1 line
+static void
bd79124gpo_set(struct gpio_chip *gc, unsigned int offset, int value)
Quoted 8 lines
You should use .set_rv()
...
drivers/iio/adc/rohm-bd79124.c line 203
Quoted 2 lines
drivers/iio/adc/rohm-bd79124.c new file +2
-0+static void bd79124gpo_set_multiple (struct gpio_chip *gc,unsigned long *mask, +unsigned long *bits)Ditto, .set_multiple_rv().
As you know, this started at v6.14 cycle which is still ongoing. I don't think .set_rv() and .set_multiple_rv() are available?
Quoted 5 lines
Review
Quoted 3 lines
(quoted diff) +2
-0+{ + int ret, val;Here and everywhere else, the returned value by regmap is unsigned int.
Ack.
Quoted 19 lines
Quoted 16 lines
drivers/iio/adc/rohm-bd79124.c new file +15
-0+struct bd79124_data *data =gpiochip_get_data (gc); + +/* Ensure all GPIOs in 'mask' are set to be GPIOs */ + ret =regmap_read (data->map,BD79124_REG_PINCFG , &val); +if (ret) +return ; + +if ((val & *mask) != *mask) { +dev_dbg (data->dev,"Invalid mux config. Can't set value.\n" ); +/* Do not set value for pins configured as ADC inputs */ + *mask &= val; + } + +regmap_update_bits (data->map,BD79124_REG_GPO_VAL , *mask, *bits); +}...
Quoted 8 lines
drivers/iio/adc/rohm-bd79124.c line 249
Quoted 5 lines
drivers/iio/adc/rohm-bd79124.c new file +5
-0+struct bd79124_raw { +u8 bit0_3;/* Is set in high bits of the byte */ +u8 bit4_11; +}; +#define BD79124_RAW_TO_INT (r) ((r.bit4_11 << 4) | (r.bit0_3 >> 4))And how this is different from treating it as
__le16? Needs a good comment about bit layout.
You don't think:
Quoted 4 lines
drivers/iio/adc/rohm-bd79124.c line 248
Quoted 4 lines
drivers/iio/adc/rohm-bd79124.c new file +4
-0+struct bd79124_raw { +u8 bit0_3;/* Is set in high bits of the byte */ +u8 bit4_11; +};
suffices? It's hard for me to think how to explain bit layout more explicitly.
This was discussed during the RFC review. I explained the rationale why I rather represent this as two 8 bit variables than le16 with (mysterious to me) shift. As a result, Jonathan told me he's not feeling (too) strong about this (but also warned we may see follow-up patches converting this to le and shift - which, by the way, is harder for me to understand).
Quoted 9 lines
...
Quoted 5 lines
drivers/iio/adc/rohm-bd79124.c new file +5
-0+static int bd79124_write_int_to_reg (struct bd79124_data *data,int reg, +unsigned int val) +{ +struct bd79124_raw raw; +int ret, tmp;
Quoted 4 lines
drivers/iio/adc/rohm-bd79124.c line 294
Quoted 2 lines
drivers/iio/adc/rohm-bd79124.c new file +2
-0+ raw.bit4_11 = (u8)(val >>4 ); + raw.bit0_3 = (u8)(val <<4 );Why casting?
To make it clear storing unsigned int to u8 is considered to be Ok. I can drop it though if you feel strong about it.
Quoted 2 lines
Make sense to have a symmetrical macro instead of hiding it in the code.
Ok.
Quoted 7 lines
drivers/iio/adc/rohm-bd79124.c line 300
Quoted 5 lines
drivers/iio/adc/rohm-bd79124.c new file +5
-0+ ret =regmap_read (data->map, reg, &tmp); +if (ret) +return ret; + + raw.bit0_3 |= (0xf & tmp);
GENMASK()?
For me 0xf is both shorter and clearer. (For me 0xf - or, 0x0f if you like, 0xf0 and 0xff are clear by a glance).
I can go for GENMASK() if it is absolutely required, but for me it is in this case just making this harder to read. I like GENMASK() for something like 0xe or 0x60 though.
Quoted 8 lines
Quoted 2 lines
drivers/iio/adc/rohm-bd79124.c new file +2
-0+return regmap_bulk_write (data->map, reg, &raw,sizeof (raw)); +}...
drivers/iio/adc/rohm-bd79124.c line 468
Quoted 1 line
drivers/iio/adc/rohm-bd79124.c new file +1
-0+return (data->alarm_monitored[chan->channel] &BIT (dir));Unneeded parentheses.
ok
Quoted 7 lines
...
drivers/iio/adc/rohm-bd79124.c line 616
Quoted 3 lines
drivers/iio/adc/rohm-bd79124.c new file +3
-0+case IIO_EV_INFO_HYSTERESIS : + reg =BD79124_GET_HYSTERESIS_REG (chan->channel); + val >>=3 ;Second time I see this. Perhaps you need a macro to explain this right shift?
Not really sure about this. I think it's kind of obvious why this is shifted - and in case it's not, there is a comment explaining it.
I could have a macro like REGVAL2HYSTERESIS() - but I don't think it is a great idea, because then anyone interested in understanding the value read from register would need to dig out the macro to find how value needs to be converted. Doing the shift here shows the register format to a reader right away - and honestly, it should be pretty obvious to the reader that this shift converts register value to proper format.
Quoted 5 lines
drivers/iio/adc/rohm-bd79124.c line 619
Quoted 3 lines
drivers/iio/adc/rohm-bd79124.c new file +2
-0+return regmap_update_bits (data->map, reg,BD79124_MASK_HYSTERESIS , + val);Can be one line.
I still prefer to have lines < 80 to make them fit my terminal.
I think we have discussed this before. I don't think we will agree on this as I have a very real reason for short lines. It does directly impact on my daily work. I don't think you're going to like it no matter how I explain this.
Quoted 17 lines
...
Quoted 15 lines
drivers/iio/adc/rohm-bd79124.c new file +15
-0+static irqreturn_t bd79124_event_handler (int irq,void *priv) +{ +int ret, i_hi, i_lo, i; +struct iio_dev *iio_dev = priv; +struct bd79124_data *data =iio_priv (iio_dev); + +/* +* Return IRQ_NONE if bailing-out without acking. This allows the IRQ +* subsystem to disable the offending IRQ line if we get a hardware +* problem. This behaviour has saved my poor bottom a few times in the +* past as, instead of getting unusably unresponsive, the system has +* spilled out the magic words "...nobody cared". +*/ + ret =regmap_read (data->map,BD79124_REG_EVENT_FLAG_HI , &i_hi); +if (ret)
Quoted 8 lines
drivers/iio/adc/rohm-bd79124.c line 862
Quoted 5 lines
drivers/iio/adc/rohm-bd79124.c new file +5
-0+return IRQ_NONE ; + + ret =regmap_read (data->map,BD79124_REG_EVENT_FLAG_LO , &i_lo); +if (ret) +return IRQ_NONE ;Only I don't get why you can't use bulk read here. The registers seem to be sequential.
I think using bulk_read is a good idea. Thanks.
Quoted 39 lines
Quoted 39 lines
drivers/iio/adc/rohm-bd79124.c new file +38
-0+if (!i_lo && !i_hi) +return IRQ_NONE ; + +for (i =0 ; i <BD79124_MAX_NUM_CHANNELS ; i++) { +u64 ecode; + +if (BIT (i) & i_hi) { + ecode =IIO_UNMOD_EVENT_CODE (IIO_VOLTAGE , i, +IIO_EV_TYPE_THRESH , +IIO_EV_DIR_RISING ); + +iio_push_event (iio_dev, ecode, data->timestamp); +/* +* The BD79124 keeps the IRQ asserted for as long as +* the voltage exceeds the threshold. It causes the IRQ +* to keep firing. +* +* Disable the event for the channel and schedule the +* re-enabling the event later to prevent storm of +* events. +*/ + ret =bd79124_event_ratelimit_hi (data, i); +if (ret) +return IRQ_NONE ; + } +if (BIT (i) & i_lo) { + ecode =IIO_UNMOD_EVENT_CODE (IIO_VOLTAGE , i, +IIO_EV_TYPE_THRESH , +IIO_EV_DIR_FALLING ); + +iio_push_event (iio_dev, ecode, data->timestamp); + ret =bd79124_event_ratelimit_lo (data, i); +if (ret) +return IRQ_NONE ; + } + } + + ret =regmap_write (data->map,BD79124_REG_EVENT_FLAG_HI , i_hi);
Quoted 8 lines
drivers/iio/adc/rohm-bd79124.c line 907
Quoted 6 lines
drivers/iio/adc/rohm-bd79124.c new file +6
-0+if (ret) +return IRQ_NONE ; + + ret =regmap_write (data->map,BD79124_REG_EVENT_FLAG_LO , i_lo); +if (ret) +return IRQ_NONE ;In the similar way bulk write.
agree.
Quoted 14 lines
Quoted 3 lines
drivers/iio/adc/rohm-bd79124.c new file +2
-0+return IRQ_HANDLED ; +}...
drivers/iio/adc/rohm-bd79124.c line 926
Quoted 5 lines
drivers/iio/adc/rohm-bd79124.c new file +5
-0+static int bd79124_chan_init (struct bd79124_data *data,int channel) +{ +int ret; + + ret =regmap_write (data->map,BD79124_GET_HIGH_LIMIT_REG (channel),4095 );
BD79124_HIGH_LIMIT_MAX?
Quoted 6 lines
drivers/iio/adc/rohm-bd79124.c line 930
Quoted 4 lines
drivers/iio/adc/rohm-bd79124.c new file +4
-0+if (ret) +return ret; + +return regmap_write (data->map,BD79124_GET_LOW_LIMIT_REG (channel),0 );
BD79124_HIGH_LIMIT_MIN?
I think I originally had these defines but I was probably asked to drop the defines and use raw values instead.
Quoted 7 lines
Quoted 1 line
+}
...
drivers/iio/adc/rohm-bd79124.c line 1089
Quoted 2 lines
drivers/iio/adc/rohm-bd79124.c new file +2
-0+static const struct i2c_device_id bd79124_id[] = { + {"bd79124" , },Redundant inner comma.
ok.
Matti Vaittinen
maintainerRe: [PATCH v7 06/10] iio: adc: Support ROHM BD79124 ADC
Quoted 18 lines · Matti Vaittinen
Quoted 17 lines · Andy Shevchenko
Quoted 6 lines · Matti Vaittinen
drivers/iio/adc/rohm-bd79124.c new file +5
-0+static int bd79124_chan_init (struct bd79124_data *data,int channel) +{ + int ret; + + ret = regmap_write(data->map,
BD79124_GET_HIGH_LIMIT_REG(channel), 4095);
BD79124_HIGH_LIMIT_MAX?Quoted 5 lines
+ if (ret)
+ return ret;
+
+ return regmap_write(data->map,BD79124_GET_LOW_LIMIT_REG(channel), 0);
Quoted 3 lines
Quoted 1 line
BD79124_HIGH_LIMIT_MIN?I think I originally had these defines but I was probably asked to drop the defines and use raw values instead.
Please ignore my reply here! It seems I still have the defines in other places of the code so they haven't been dropped after all. I'll replace the raw values as you suggested.
Thanks.
Yours,
-- Matti
Andy Shevchenko
reviewerRe: [PATCH v7 06/10] iio: adc: Support ROHM BD79124 ADC
In reply to Matti VaittinenQuoted 2 lines · Matti Vaittinen
Quoted 1 line · Andy Shevchenko
On Thu, Mar 13, 2025 at 09:19:03AM +0200, Matti Vaittinen wrote:
...
Quoted 14 lines
Quoted 5 lines
drivers/iio/adc/rohm-bd79124.c line 67
Quoted 3 lines
drivers/iio/adc/rohm-bd79124.c new file +3
-0+#define BD79124_MASK_HYSTERESIS GENMASK(3, 0) +#define BD79124_LOW_LIMIT_MIN 0 +#define BD79124_HIGH_LIMIT_MAX GENMASK(11, 0)These masks are not named after registers (or I don't see it clearly),
Naming is hard. I usually try to make a balance between:
1) using names which explain the purpose when seen in the code (at call site)
2) keeping names short enough
3) following the naming convention in the data sheet
4) maintain relation to the register.
Quoted 7 lines
I put most emphasis to the 1, while 2 is important to me as well. 3 is _very_ nice to have, but it is often somehow contradicting with 1 and 2. 4 is IMO just nice to have. The register is usually clearly visible at call site, and if someone adds new functionality (or checks the correctness of the masks/registers), then 3 is way more important.
I am open to any concrete suggestions though.
From my point of view the starting point is 3, then one may apply 2 and 4, the 1 may mangle the name so much that register data field name becomes quite abstract.
Quoted 5 lines
Quoted 3 lines
it's
hard to understand which one relates to which register. Also, why not usingbitfield.h?I saw no need for it?
Hmm... Okay, I think Jonathan will ask that if really needed.
...
Quoted 5 lines
Quoted 3 lines
Quoted 1 line
+ * These macros return the address of the 1.st reg for the given channel
first
Huh?
Replace "1.st" (which seems not a standard representation of it) by "first".
Quoted 3 lines
Quoted 1 line
(and missing period at the end).
Ok.
...
Quoted 11 lines
Quoted 10 lines
drivers/iio/adc/rohm-bd79124.c line 80
Quoted 5 lines
drivers/iio/adc/rohm-bd79124.c new file +5
-0+#define BD79124_GET_HIGH_LIMIT_REG (ch) (BD79124_REG_HYSTERESIS_CH0 + (ch) * 4) +#define BD79124_GET_LOW_LIMIT_REG (ch) (BD79124_REG_EVENTCOUNT_CH0 + (ch) * 4) +#define BD79124_GET_LIMIT_REG (ch, dir) ((dir) == IIO_EV_DIR_RISING ? \ + BD79124_GET_HIGH_LIMIT_REG(ch) : BD79124_GET_LOW_LIMIT_REG(ch)) +#define BD79124_GET_RECENT_RES_REG (ch) (BD79124_REG_RECENT_CH0_LSB + (ch) * 2)Don't we want to have something in
bitfield.hfor arrays in the register, i.e. when register(s) is(are) split to 2+ bits per an element in an array of the same semantics. Would be nice to eliminate such a boilerplate here and in many other drivers.
Quoted 4 lines
Not necessarily a bad idea. Still, I am not willing to expand this series any more - currently there is 10 patches, 2 of which are directly related to the BD79124. I don't want to delay this driver for another cycle due to added helpers.
It was just a side note. Consider as a poll for opinions.
...
Quoted 3 lines
Quoted 3 lines
Quoted 1 line
+static void
bd79124gpo_set(struct gpio_chip *gc, unsigned int offset, int value)You should use .set_rv()
...
Quoted 7 lines
Quoted 4 lines
drivers/iio/adc/rohm-bd79124.c line 203
Quoted 2 lines
drivers/iio/adc/rohm-bd79124.c new file +2
-0+static void bd79124gpo_set_multiple (struct gpio_chip *gc,unsigned long *mask, +unsigned long *bits)Ditto, .set_multiple_rv().
As you know, this started at v6.14 cycle which is still ongoing. I don't think .set_rv() and .set_multiple_rv() are available?
You mean that you are still hope to have this series to be squeezed for v6.15-rc1? That's not me who decides, but if not, those APIs will be part of the v6.15-rc1 (at least they are pending in GPIO subsystem).
...
Quoted 9 lines
Quoted 8 lines
drivers/iio/adc/rohm-bd79124.c line 249
Quoted 5 lines
drivers/iio/adc/rohm-bd79124.c new file +5
-0+struct bd79124_raw { +u8 bit0_3;/* Is set in high bits of the byte */ +u8 bit4_11; +}; +#define BD79124_RAW_TO_INT (r) ((r.bit4_11 << 4) | (r.bit0_3 >> 4))And how this is different from treating it as
__le16? Needs a good comment about bit layout.
Quoted 7 lines
You don't think:
Quoted 4 lines
drivers/iio/adc/rohm-bd79124.c line 248
Quoted 4 lines
drivers/iio/adc/rohm-bd79124.c new file +4
-0+struct bd79124_raw { +u8 bit0_3;/* Is set in high bits of the byte */ +u8 bit4_11; +};suffices? It's hard for me to think how to explain bit layout more explicitly.
I do not think it suffices. It's hard to decode what you meant by the naming and the comment. Actually it even confuses me.
Quoted 5 lines
This was discussed during the RFC review. I explained the rationale why I rather represent this as two 8 bit variables than le16 with (mysterious to me) shift. As a result, Jonathan told me he's not feeling (too) strong about this (but also warned we may see follow-up patches converting this to le and shift - which, by the way, is harder for me to understand).
If you want to leave them, the good comment needs to be added for both
1) explaining bit layouts;
2) why __le16 is not being used.
...
Quoted 6 lines
Quoted 6 lines
Quoted 5 lines
drivers/iio/adc/rohm-bd79124.c new file +5
-0+static int bd79124_write_int_to_reg (struct bd79124_data *data,int reg, +unsigned int val) +{ +struct bd79124_raw raw; +int ret, tmp;
Quoted 7 lines
Quoted 4 lines
drivers/iio/adc/rohm-bd79124.c line 294
Quoted 2 lines
drivers/iio/adc/rohm-bd79124.c new file +2
-0+ raw.bit4_11 = (u8)(val >>4 ); + raw.bit0_3 = (u8)(val <<4 );Why casting?
To make it clear storing unsigned int to u8 is considered to be Ok. I can drop it though if you feel strong about it.
In C (not C++) explicit casting is a point to stumble over and check if there is any problems or call for asking the question "Whu?!"
...
Quoted 8 lines
Quoted 7 lines
drivers/iio/adc/rohm-bd79124.c line 300
Quoted 5 lines
drivers/iio/adc/rohm-bd79124.c new file +5
-0+ ret =regmap_read (data->map, reg, &tmp); +if (ret) +return ret; + + raw.bit0_3 |= (0xf & tmp);
GENMASK()?
Quoted 6 lines
For me
0xfis both shorter and clearer. (For me0xf- or,0x0fif you like,0xf0and0xffare clear by a glance).I can go for
GENMASK()if it is absolutely required, but for me it is in this case just making this harder to read. I likeGENMASK()for something like0xeor0x60though.
It makes code inconsistent and one letter is not so visible. Ideally it should be a definition with self-explanatory name.
Quoted 2 lines
Quoted 2 lines
Quoted 2 lines
drivers/iio/adc/rohm-bd79124.c new file +2
-0+return regmap_bulk_write (data->map, reg, &raw,sizeof (raw)); +}
...
Quoted 9 lines
Quoted 5 lines
drivers/iio/adc/rohm-bd79124.c line 616
Quoted 3 lines
drivers/iio/adc/rohm-bd79124.c new file +3
-0+case IIO_EV_INFO_HYSTERESIS : + reg =BD79124_GET_HYSTERESIS_REG (chan->channel); + val >>=3 ;Second time I see this. Perhaps you need a macro to explain this right shift?
Not really sure about this. I think it's kind of obvious why this is shifted
- and in case it's not, there is a comment explaining it.
Quoted 6 lines
I could have a macro like
REGVAL2HYSTERESIS()- but I don't think it is a great idea, because then anyone interested in understanding the value read from register would need to dig out the macro to find how value needs to be converted. Doing the shift here shows the register format to a reader right away - and honestly, it should be pretty obvious to the reader that this shift converts register value to proper format.
These shifts are not a big issue, so whatever you choose / chose.
Quoted 10 lines
Quoted 4 lines
drivers/iio/adc/rohm-bd79124.c line 619
Quoted 2 lines
drivers/iio/adc/rohm-bd79124.c new file +2
-0+return regmap_update_bits (data->map, reg,BD79124_MASK_HYSTERESIS , + val);Can be one line.
I still prefer to have lines < 80 to make them fit my terminal. I think we have discussed this before. I don't think we will agree on this as I have a very real reason for short lines. It does directly impact on my daily work. I don't think you're going to like it no matter how I explain this.
IIRC this takes 82 characters.
Yes, we discussed and I see no issues to avoid uglifying / adding unnecessary lines to the code. We can continue arguing, but this what I think and I don't know what argument may change my opinion. Apparently this is on maintainer's field now to decide.
Signature · 2 lines
With Best Regards, Andy Shevchenko
Jonathan Cameron
maintainerRe: [PATCH v7 06/10] iio: adc: Support ROHM BD79124 ADC
Quoted 5 lines · On Fri, 14 Mar 2025 16:33:13 +0200 Andy Shevchenko…
Quoted 2 lines · Matti Vaittinen
Quoted 1 line · Andy Shevchenko
On Thu, Mar 13, 2025 at 09:19:03AM +0200, Matti Vaittinen wrote:
...
Picking out a few things to comment on...
Quoted 27 lines
Quoted 15 lines
Quoted 6 lines
drivers/iio/adc/rohm-bd79124.c line 67
Quoted 4 lines
drivers/iio/adc/rohm-bd79124.c new file +3
-0+#define BD79124_MASK_HYSTERESIS GENMASK(3, 0) +#define BD79124_LOW_LIMIT_MIN 0 +#define BD79124_HIGH_LIMIT_MAX GENMASK(11, 0)These masks are not named after registers (or I don't see it clearly),
Naming is hard. I usually try to make a balance between:
1) using names which explain the purpose when seen in the code (at call site)
2) keeping names short enough
3) following the naming convention in the data sheet
4) maintain relation to the register.Quoted 7 lines
I put most emphasis to the 1, while 2 is important to me as well. 3 is _very_ nice to have, but it is often somehow contradicting with 1 and 2. 4 is IMO just nice to have. The register is usually clearly visible at call site, and if someone adds new functionality (or checks the correctness of the masks/registers), then 3 is way more important.
I am open to any concrete suggestions though.
From my point of view the starting point is 3, then one may apply 2 and 4, the 1 may mangle the name so much that register data field name becomes quite abstract.
Quoted 8 lines
Quoted 5 lines
Quoted 3 lines
it's
hard to understand which one relates to which register. Also, why not usingbitfield.h?I saw no need for it?
Hmm... Okay, I think Jonathan will ask that if really needed.
I won't as I'm not a huge fan of bitfield.h. In many cases they bloat the code and increase the writes that go over the bus. Don't get me wrong, there are good usecases, but it's not a universal thing (unlike PREP_FIELD() etc which I love :)
I do favour burning a few characters to make field / register relationship clear though. A few things can help I think.
Structuring defines and naming:
I like using whitespace in subtle ways for this.
#define PREFIX_REGNAME_REG 0x00
#define PREFIX_REGNAME_FIELDNAME_MSK GENMASK(X, Y)
#define PREFIX_REGNAME_FIELDNAME_FILEVALNAME 0x3
etc
Makes it easy to see if we have a mismatch going on
However, I don't insist on this in all cases as it is one of those "don't let perfect be the enemy of good" cases I think.
So Matti, good to have one last look at the defines and see if they can be wrangled into a slightly better form.
.
Quoted 7 lines
...
Quoted 5 lines
Quoted 4 lines
drivers/iio/adc/rohm-bd79124.c line 203
Quoted 2 lines
drivers/iio/adc/rohm-bd79124.c new file +2
-0+static void bd79124gpo_set_multiple (struct gpio_chip *gc,unsigned long *mask, +unsigned long *bits)Ditto, .set_multiple_rv().
Quoted 7 lines
Quoted 2 lines
As you know, this started at v6.14 cycle which is still ongoing. I don't think .set_rv() and .set_multiple_rv() are available?
You mean that you are still hope to have this series to be squeezed for v6.15-rc1? That's not me who decides, but if not, those APIs will be part of the v6.15-rc1 (at least they are pending in GPIO subsystem).
I'd vote for a rebase on rc1 that should be really easy to for me to pick
up. I'd accept a follow up series though. Ultimately won't affect
when this series lands as very unlikely Linus will delay the release long enough for me to do another pull request this cycle,
Jonathan
Jonathan Cameron
maintainerRe: [PATCH v7 06/10] iio: adc: Support ROHM BD79124 ADC
Quoted 40 lines · On Sun, 16 Mar 2025 09:52:33 +0000 Jonathan Cameron <[email protected]> wrote:
Quoted 5 lines · On Fri, 14 Mar 2025 16:33:13 +0200 Andy Shevchenko…
Quoted 2 lines · Matti Vaittinen
Quoted 1 line · Andy Shevchenko
On Thu, Mar 13, 2025 at 09:19:03AM +0200, Matti Vaittinen wrote:
...
Picking out a few things to comment on...
Quoted 31 lines
Quoted 15 lines
Quoted 6 lines
drivers/iio/adc/rohm-bd79124.c line 67
Quoted 4 lines
drivers/iio/adc/rohm-bd79124.c new file +3
-0+#define BD79124_MASK_HYSTERESIS GENMASK(3, 0) +#define BD79124_LOW_LIMIT_MIN 0 +#define BD79124_HIGH_LIMIT_MAX GENMASK(11, 0)These masks are not named after registers (or I don't see it clearly),
Naming is hard. I usually try to make a balance between:
1) using names which explain the purpose when seen in the code (at call site)
2) keeping names short enough
3) following the naming convention in the data sheet
4) maintain relation to the register.Quoted 7 lines
I put most emphasis to the 1, while 2 is important to me as well. 3 is _very_ nice to have, but it is often somehow contradicting with 1 and 2. 4 is IMO just nice to have. The register is usually clearly visible at call site, and if someone adds new functionality (or checks the correctness of the masks/registers), then 3 is way more important.
I am open to any concrete suggestions though.
From my point of view the starting point is 3, then one may apply 2 and 4, the 1 may mangle the name so much that register data field name becomes quite abstract.
Quoted 4 lines
Quoted 3 lines
it's
hard to understand which one relates to which register. Also, why not usingbitfield.h?
Quoted 6 lines
Quoted 4 lines
Quoted 1 line
I saw no need for it?
Hmm... Okay, I think Jonathan will ask that if really needed.
I won't as I'm not a huge fan of
bitfield.h. In many cases they bloat the code
Oops. You weren't talking about the regmap bitfields. Ignore this. This driver is using FIELD_PREP / FIELD_GET. Maybe should be more extensive?
Quoted 45 lines
and increase the writes that go over the bus. Don't get me wrong, there are good usecases, but it's not a universal thing (unlike
PREP_FIELD()etc which I love :)I do favour burning a few characters to make field / register relationship clear though. A few things can help I think.
Structuring defines and naming:
I like using whitespace in subtle ways for this.#define
PREFIX_REGNAME_REG0x00
#definePREFIX_REGNAME_FIELDNAME_MSKGENMASK(X, Y)
#definePREFIX_REGNAME_FIELDNAME_FILEVALNAME0x3
etcMakes it easy to see if we have a mismatch going on
However, I don't insist on this in all cases as it is one of those "don't let perfect be the enemy of good" cases I think.
So Matti, good to have one last look at the defines and see if they can be wrangled into a slightly better form.
.
Quoted 7 lines
...
Quoted 5 lines
Quoted 4 lines
drivers/iio/adc/rohm-bd79124.c line 203
Quoted 2 lines
drivers/iio/adc/rohm-bd79124.c new file +2
-0+static void bd79124gpo_set_multiple (struct gpio_chip *gc,unsigned long *mask, +unsigned long *bits)Ditto, .set_multiple_rv().
Quoted 7 lines
Quoted 2 lines
As you know, this started at v6.14 cycle which is still ongoing. I don't think .set_rv() and .set_multiple_rv() are available?
You mean that you are still hope to have this series to be squeezed for v6.15-rc1? That's not me who decides, but if not, those APIs will be part of the v6.15-rc1 (at least they are pending in GPIO subsystem).
I'd vote for a rebase on rc1 that should be really easy to for me to pick
up. I'd accept a follow up series though. Ultimately won't affect
when this series lands as very unlikely Linus will delay the release long enough for me to do another pull request this cycle,Jonathan
Matti Vaittinen
maintainerRe: [PATCH v7 06/10] iio: adc: Support ROHM BD79124 ADC
In reply to Jonathan CameronQuoted 53 lines · Jonathan Cameron
Quoted 5 lines · On Fri, 14 Mar 2025 16:33:13 +0200 Andy Shevchenko…
Quoted 2 lines · Matti Vaittinen
Quoted 1 line · Andy Shevchenko
On Thu, Mar 13, 2025 at 09:19:03AM +0200, Matti Vaittinen wrote:
...
Picking out a few things to comment on...
Quoted 27 lines
Quoted 15 lines
Quoted 6 lines
drivers/iio/adc/rohm-bd79124.c line 67
Quoted 4 lines
drivers/iio/adc/rohm-bd79124.c new file +3
-0+#define BD79124_MASK_HYSTERESIS GENMASK(3, 0) +#define BD79124_LOW_LIMIT_MIN 0 +#define BD79124_HIGH_LIMIT_MAX GENMASK(11, 0)These masks are not named after registers (or I don't see it clearly),
Naming is hard. I usually try to make a balance between:
1) using names which explain the purpose when seen in the code (at call site)
2) keeping names short enough
3) following the naming convention in the data sheet
4) maintain relation to the register.Quoted 7 lines
I put most emphasis to the 1, while 2 is important to me as well. 3 is _very_ nice to have, but it is often somehow contradicting with 1 and 2. 4 is IMO just nice to have. The register is usually clearly visible at call site, and if someone adds new functionality (or checks the correctness of the masks/registers), then 3 is way more important.
I am open to any concrete suggestions though.
From my point of view the starting point is 3, then one may apply 2 and 4,
the 1 may mangle the name so much that register data field name becomes quite abstract.Quoted 8 lines
Quoted 5 lines
Quoted 3 lines
it's
hard to understand which one relates to which register. Also, why not usingbitfield.h?I saw no need for it?
Hmm... Okay, I think Jonathan will ask that if really needed.
I won't as I'm not a huge fan of
bitfield.h. In many cases they bloat the code and increase the writes that go over the bus. Don't get me wrong, there are good usecases, but it's not a universal thing (unlikePREP_FIELD()etc which I love :)I do favour burning a few characters to make field / register relationship clear though. A few things can help I think.
Quoted 7 lines
Structuring defines and naming:
I like using whitespace in subtle ways for this.#define
PREFIX_REGNAME_REG0x00
#definePREFIX_REGNAME_FIELDNAME_MSKGENMASK(X, Y)
#definePREFIX_REGNAME_FIELDNAME_FILEVALNAME0x3
etc
This is close to my usual way, but not quite. I most often do:
PREFIX_REG_REGNAMEPREFIX_MASK_FIELDNAMEPREFIX_FIELDNAME_FIELDVALUE.
Problem withPREFIX_REGNAME_FIELDNAME_MSK
compared toPREFIX_MASK_FIELDNAME
tends to be the length of the define. Also, sometimes registers contain field(s) which have nothing to do with the register name. Sometimes it results confusing definitions. (Confusing meaning that seeing the actual read/write makes one to wonder what the register field is supposed to do).
Quoted 7 lines
Makes it easy to see if we have a mismatch going on
However, I don't insist on this in all cases as it is one of those "don't let perfect be the enemy of good" cases I think.
So Matti, good to have one last look at the defines and see if they can be wrangled into a slightly better form.
I can at least change the MASK to MSK and save one letter :) What comes to the ordering, I see you prefer having MSK / REG suffix at the end - while I like having it right after the prefix (just because it makes the MSK / REG to stay aligned - which in my eyes looks a little bit better). So, I'm not sure if I change it to your preference (which may end up being more common in IIO if it's what you prefer), or if I keep it the way I am used to.
Quoted 10 lines
Quoted 10 lines
...
Quoted 7 lines
Quoted 4 lines
drivers/iio/adc/rohm-bd79124.c line 203
Quoted 2 lines
drivers/iio/adc/rohm-bd79124.c new file +2
-0+static void bd79124gpo_set_multiple (struct gpio_chip *gc,unsigned long *mask, +unsigned long *bits)Ditto, .set_multiple_rv().
As you know, this started at v6.14 cycle which is still ongoing. I don't think .set_rv() and .set_multiple_rv() are available?
Quoted 6 lines
Quoted 4 lines
You mean that you are still hope to have this series to be squeezed for v6.15-rc1? That's not me who decides, but if not, those APIs will be part of the v6.15-rc1 (at least they are pending in GPIO subsystem).
I'd vote for a rebase on rc1 that should be really easy to for me to pick up.
I sure can rebase if the series is not merged before the rc1 is out. I, however, rather not delay versions (unless explicitly asked to).
Sometimes postponing things to wait dependencies to get merged backfires due to some 'last minute' delays. Hence, I don't usually adapt to new APIs until they are in the rc1 or target subsystem's 'for-next' (or other suitable) -branch.
Quoted 3 lines
I'd accept a follow up series though. Ultimately won't affect
when this series lands as very unlikely Linus will delay the release long enough for me to do another pull request this cycle,
No problem. You'll pick this when you think it's ready - and I'll rebase if new rc1 is out before that (and convert to set_rv() and set_multiple_rv() if they are included in the rc1).
If you merge before the set_rv() and set_multiple_rv() are in your tree, then a follow-up will be done when they emerge. :)
Yours,
-- Matti
Jonathan Cameron
maintainerRe: [PATCH v7 06/10] iio: adc: Support ROHM BD79124 ADC
Quoted 73 lines · On Mon, 17 Mar 2025 08:52:09 +0200 Matti Vaittinen <[email protected]>…
Quoted 53 lines · Jonathan Cameron
Quoted 5 lines · On Fri, 14 Mar 2025 16:33:13 +0200 Andy Shevchenko…
Quoted 2 lines · Matti Vaittinen
Quoted 1 line · Andy Shevchenko
On Thu, Mar 13, 2025 at 09:19:03AM +0200, Matti Vaittinen wrote:
...
Picking out a few things to comment on...
Quoted 27 lines
Quoted 15 lines
Quoted 6 lines
drivers/iio/adc/rohm-bd79124.c line 67
Quoted 4 lines
drivers/iio/adc/rohm-bd79124.c new file +3
-0+#define BD79124_MASK_HYSTERESIS GENMASK(3, 0) +#define BD79124_LOW_LIMIT_MIN 0 +#define BD79124_HIGH_LIMIT_MAX GENMASK(11, 0)These masks are not named after registers (or I don't see it clearly),
Naming is hard. I usually try to make a balance between:
1) using names which explain the purpose when seen in the code (at call site)
2) keeping names short enough
3) following the naming convention in the data sheet
4) maintain relation to the register.Quoted 7 lines
I put most emphasis to the 1, while 2 is important to me as well. 3 is _very_ nice to have, but it is often somehow contradicting with 1 and 2. 4 is IMO just nice to have. The register is usually clearly visible at call site, and if someone adds new functionality (or checks the correctness of the masks/registers), then 3 is way more important.
I am open to any concrete suggestions though.
From my point of view the starting point is 3, then one may apply 2 and 4,
the 1 may mangle the name so much that register data field name becomes quite abstract.Quoted 8 lines
Quoted 5 lines
Quoted 3 lines
it's
hard to understand which one relates to which register. Also, why not usingbitfield.h?I saw no need for it?
Hmm... Okay, I think Jonathan will ask that if really needed.
I won't as I'm not a huge fan of
bitfield.h. In many cases they bloat the code and increase the writes that go over the bus. Don't get me wrong, there are good usecases, but it's not a universal thing (unlikePREP_FIELD()etc which I love :)I do favour burning a few characters to make field / register relationship clear though. A few things can help I think.
Quoted 7 lines
Structuring defines and naming:
I like using whitespace in subtle ways for this.#define
PREFIX_REGNAME_REG0x00
#definePREFIX_REGNAME_FIELDNAME_MSKGENMASK(X, Y)
#definePREFIX_REGNAME_FIELDNAME_FILEVALNAME0x3
etcThis is close to my usual way, but not quite. I most often do:
PREFIX_REG_REGNAMEPREFIX_MASK_FIELDNAMEPREFIX_FIELDNAME_FIELDVALUE.Problem with
PREFIX_REGNAME_FIELDNAME_MSK
compared toPREFIX_MASK_FIELDNAME
Quoted 4 lines
tends to be the length of the define. Also, sometimes registers contain field(s) which have nothing to do with the register name. Sometimes it results confusing definitions. (Confusing meaning that seeing the actual read/write makes one to wonder what the register field is supposed to do).
The key reason to keep that regname in there is it lets the reader scan the register defines for oddities then, having done that read the code without having to go look to see if the field is infact in this register. So having the name in there in a fixed location tends to help with whole case of fields shoved in corners of unconnected registers.
Quoted 9 lines
Quoted 8 lines
Makes it easy to see if we have a mismatch going on
However, I don't insist on this in all cases as it is one of those "don't let perfect be the enemy of good" cases I think.
So Matti, good to have one last look at the defines and see if they can be wrangled into a slightly better form.
Quoted 7 lines
I can at least change the MASK to MSK and save one letter :) What comes to the ordering, I see you prefer having MSK / REG suffix at the end - while I like having it right after the prefix (just because it makes the MSK / REG to stay aligned - which in my eyes looks a little bit better). So, I'm not sure if I change it to your preference (which may end up being more common in IIO if it's what you prefer), or if I keep it the way I am used to.
That choice is up to you. If the clarity is there, I'm not fussed on ordering.
Quoted 18 lines
Quoted 11 lines
Quoted 11 lines
...
Quoted 7 lines
Quoted 4 lines
drivers/iio/adc/rohm-bd79124.c line 203
Quoted 2 lines
drivers/iio/adc/rohm-bd79124.c new file +2
-0+static void bd79124gpo_set_multiple (struct gpio_chip *gc,unsigned long *mask, +unsigned long *bits)Ditto, .set_multiple_rv().
As you know, this started at v6.14 cycle which is still ongoing. I don't think .set_rv() and .set_multiple_rv() are available?
Quoted 6 lines
Quoted 4 lines
You mean that you are still hope to have this series to be squeezed for v6.15-rc1? That's not me who decides, but if not, those APIs will be part of the v6.15-rc1 (at least they are pending in GPIO subsystem).
I'd vote for a rebase on rc1 that should be really easy to for me to pick up.
Quoted 7 lines
I sure can rebase if the series is not merged before the rc1 is out. I, however, rather not delay versions (unless explicitly asked to).
Sometimes postponing things to wait dependencies to get merged backfires due to some 'last minute' delays. Hence, I don't usually adapt to new APIs until they are in the rc1 or target subsystem's 'for-next' (or other suitable) -branch.
If we were a little later in the coming cycle I'd agree, but risk factor for a rebase around rc1/2 is very low.
That often needs doing anyway because of in kernel ABI changes etc.
Quoted 11 lines
Quoted 4 lines
I'd accept a follow up series though. Ultimately won't affect
when this series lands as very unlikely Linus will delay the release long enough for me to do another pull request this cycle,No problem. You'll pick this when you think it's ready - and I'll rebase if new rc1 is out before that (and convert to
set_rv()andset_multiple_rv()if they are included in the rc1).If you merge before the
set_rv()andset_multiple_rv()are in your tree, then a follow-up will be done when they emerge. :)
Either path is fine for me. Let's see where we end up! Even fine to not wait for the rc1 rebase, but just mention the dependency. That way your code can be on list for final reviews and ready to pick up after rc1 is there.
Jonathan
Quoted 3 lines
Yours,
-- Matti
Matti Vaittinen
maintainerRe: [PATCH v7 06/10] iio: adc: Support ROHM BD79124 ADC
In reply to Andy ShevchenkoQuoted 11 lines · Andy Shevchenko
Quoted 9 lines · Matti Vaittinen
drivers/iio/adc/rohm-bd79124.c new file +9
-0+/* +* Return IRQ_NONE if bailing-out without acking. This allows the IRQ +* subsystem to disable the offending IRQ line if we get a hardware +* problem. This behaviour has saved my poor bottom a few times in the +* past as, instead of getting unusably unresponsive, the system has +* spilled out the magic words "...nobody cared". +*/ + ret =regmap_read (data->map,BD79124_REG_EVENT_FLAG_HI , &i_hi); +if (ret)
Quoted 8 lines
drivers/iio/adc/rohm-bd79124.c line 862
Quoted 5 lines
drivers/iio/adc/rohm-bd79124.c new file +5
-0+return IRQ_NONE ; + + ret =regmap_read (data->map,BD79124_REG_EVENT_FLAG_LO , &i_lo); +if (ret) +return IRQ_NONE ;Only I don't get why you can't use bulk read here. The registers seem to be sequential.
After taking another look - there seems to be undocumented register (0x1b) between the BD79124_REG_EVENT_FLAG_HI (0x1a) and the BD79124_REG_EVENT_FLAG_LO (0x1c).
I won't touch it unless there is a real verified performance problem.
Quoted 39 lines
Quoted 39 lines
drivers/iio/adc/rohm-bd79124.c new file +38
-0+if (!i_lo && !i_hi) +return IRQ_NONE ; + +for (i =0 ; i <BD79124_MAX_NUM_CHANNELS ; i++) { +u64 ecode; + +if (BIT (i) & i_hi) { + ecode =IIO_UNMOD_EVENT_CODE (IIO_VOLTAGE , i, +IIO_EV_TYPE_THRESH , +IIO_EV_DIR_RISING ); + +iio_push_event (iio_dev, ecode, data->timestamp); +/* +* The BD79124 keeps the IRQ asserted for as long as +* the voltage exceeds the threshold. It causes the IRQ +* to keep firing. +* +* Disable the event for the channel and schedule the +* re-enabling the event later to prevent storm of +* events. +*/ + ret =bd79124_event_ratelimit_hi (data, i); +if (ret) +return IRQ_NONE ; + } +if (BIT (i) & i_lo) { + ecode =IIO_UNMOD_EVENT_CODE (IIO_VOLTAGE , i, +IIO_EV_TYPE_THRESH , +IIO_EV_DIR_FALLING ); + +iio_push_event (iio_dev, ecode, data->timestamp); + ret =bd79124_event_ratelimit_lo (data, i); +if (ret) +return IRQ_NONE ; + } + } + + ret =regmap_write (data->map,BD79124_REG_EVENT_FLAG_HI , i_hi);
Quoted 8 lines
drivers/iio/adc/rohm-bd79124.c line 907
Quoted 6 lines
drivers/iio/adc/rohm-bd79124.c new file +6
-0+if (ret) +return IRQ_NONE ; + + ret =regmap_write (data->map,BD79124_REG_EVENT_FLAG_LO , i_lo); +if (ret) +return IRQ_NONE ;In the similar way bulk write.
definitely not due to the 0x1b.
Quoted 2 lines
Quoted 2 lines
drivers/iio/adc/rohm-bd79124.c new file +2
-0+return IRQ_HANDLED ; +}
Andy Shevchenko
reviewerRe: [PATCH v7 06/10] iio: adc: Support ROHM BD79124 ADC
Quoted 2 lines · Matti Vaittinen
Quoted 1 line · Andy Shevchenko
On Thu, Mar 13, 2025 at 09:19:03AM +0200, Matti Vaittinen wrote:
...
Quoted 16 lines
Quoted 10 lines
drivers/iio/adc/rohm-bd79124.c line 862
Quoted 7 lines
drivers/iio/adc/rohm-bd79124.c new file +7
-0+ ret =regmap_read (data->map,BD79124_REG_EVENT_FLAG_HI , &i_hi); +if (ret) +return IRQ_NONE ; + + ret =regmap_read (data->map,BD79124_REG_EVENT_FLAG_LO , &i_lo); +if (ret) +return IRQ_NONE ;Only I don't get why you can't use bulk read here. The registers seem to be sequential.
After taking another look - there seems to be undocumented register (
0x1b) between theBD79124_REG_EVENT_FLAG_HI(0x1a) and theBD79124_REG_EVENT_FLAG_LO(0x1c).I won't touch it unless there is a real verified performance problem.
...
Quoted 3 lines
Quoted 1 line
In the similar way bulk write.
definitely not due to the
0x1b.
Okay, it seems I misinterpreted the values you have in regmap configuration, I was under the impression that regmap is 16-bit data, but it is about address.
So, we need to know why the heck HW has sparse registers for what is supposed to be sequential. This needs a good comment.
Signature · 2 lines
With Best Regards, Andy Shevchenko
Matti Vaittinen
maintainerRe: [PATCH v7 06/10] iio: adc: Support ROHM BD79124 ADC
Quoted 25 lines · Andy Shevchenko
Quoted 2 lines · Matti Vaittinen
Quoted 1 line · Andy Shevchenko
On Thu, Mar 13, 2025 at 09:19:03AM +0200, Matti Vaittinen wrote:
...
Quoted 16 lines
Quoted 10 lines
drivers/iio/adc/rohm-bd79124.c line 862
Quoted 7 lines
drivers/iio/adc/rohm-bd79124.c new file +7
-0+ ret =regmap_read (data->map,BD79124_REG_EVENT_FLAG_HI , &i_hi); +if (ret) +return IRQ_NONE ; + + ret =regmap_read (data->map,BD79124_REG_EVENT_FLAG_LO , &i_lo); +if (ret) +return IRQ_NONE ;Only I don't get why you can't use bulk read here. The registers seem to be sequential.
After taking another look - there seems to be undocumented register (
0x1b) between theBD79124_REG_EVENT_FLAG_HI(0x1a) and theBD79124_REG_EVENT_FLAG_LO(0x1c).I won't touch it unless there is a real verified performance problem.
...
Quoted 8 lines
Quoted 3 lines
Quoted 1 line
In the similar way bulk write.
definitely not due to the
0x1b.Okay, it seems I misinterpreted the values you have in regmap configuration, I was under the impression that regmap is 16-bit data, but it is about address.
So, we need to know why the heck HW has sparse registers
We don't know. And we really don't even need to know it. We can just use this device knowing there are some.
Quoted 2 lines
for what is supposed
to be sequential. This needs a good comment.
I think it is quite usual that devices contain undocumented registers. Not sure having a comment that this device also has some, adds much of value? I suppose I can add a comment that we can't use bulk_write because registers aren't in subsequent addresses - but having just removed bunch of unnecessary comments from the code (as requested), I'm not sure adding this one really improves situation... When one sees separate reads/writes for data spread to multiple registers, he is likely to assume addresses aren't subsequent.
Yours,
-- Matti
Andy Shevchenko
reviewerRe: [PATCH v7 06/10] iio: adc: Support ROHM BD79124 ADC
Quoted 2 lines · Matti Vaittinen
Quoted 1 line · Andy Shevchenko
On Fri, Mar 14, 2025 at 11:22:37AM +0200, Matti Vaittinen wrote:
...
Quoted 7 lines
Quoted 4 lines
Okay, it seems I misinterpreted the values you have in regmap configuration, I was under the impression that regmap is 16-bit data, but it is about address.
So, we need to know why the heck HW has sparse registers
We don't know. And we really don't even need to know it. We can just use this device knowing there are some.
Don't you have a channel to ask HW engineers about this?
Quoted 11 lines
Quoted 2 lines
for what is supposed
to be sequential. This needs a good comment.I think it is quite usual that devices contain undocumented registers. Not sure having a comment that this device also has some, adds much of value? I suppose I can add a comment that we can't use
bulk_writebecause registers aren't in subsequent addresses - but having just removed bunch of unnecessary comments from the code (as requested), I'm not sure adding this one really improves situation... When one sees separate reads/writes for data spread to multiple registers, he is likely to assume addresses aren't subsequent.
From HW design perspective it's silly to sparse hi and lo part of the semantically same entity. So, either the (undocumented) register is also part of the soup, or the registers have different semantics.
This what needs to be commented in my opinion.
Signature · 2 lines
With Best Regards, Andy Shevchenko
Matti Vaittinen
maintainerRe: [PATCH v7 06/10] iio: adc: Support ROHM BD79124 ADC
Quoted 9 lines · Andy Shevchenko
Quoted 2 lines · Matti Vaittinen
Quoted 1 line · Andy Shevchenko
On Fri, Mar 14, 2025 at 11:22:37AM +0200, Matti Vaittinen wrote:
...
Quoted 3 lines
Quoted 3 lines
Okay, it seems I misinterpreted the values you have in regmap configuration, I was under the impression that regmap is 16-bit data, but it is about address.
Quoted 6 lines
Quoted 4 lines
Quoted 1 line
So, we need to know why the heck HW has sparse registers
We don't know. And we really don't even need to know it. We can just use this device knowing there are some.
Don't you have a channel to ask HW engineers about this?
Let's just say that ROHM is, while not huge, still rather large company. I'm located far away from the HQ, I speak different language and I am from very different cultural background. So, while there are some channels, it is not always easy, clever of possible to ask (not to mention getting answers to) "why this way" - questions :)
Quoted 12 lines
Quoted 11 lines
Quoted 2 lines
for what is supposed
to be sequential. This needs a good comment.I think it is quite usual that devices contain undocumented registers. Not sure having a comment that this device also has some, adds much of value? I suppose I can add a comment that we can't use
bulk_writebecause registers aren't in subsequent addresses - but having just removed bunch of unnecessary comments from the code (as requested), I'm not sure adding this one really improves situation... When one sees separate reads/writes for data spread to multiple registers, he is likely to assume addresses aren't subsequent.
Quoted 3 lines
From HW design perspective it's silly to sparse hi and lo part of
the semantically same entity. So, either the (undocumented) register is also part of the soup, or the registers have different semantics.
Or, the designer has not thought how software would be doing the reads. Or, this design has originated from a design done for a very specific purpose, which, we don't know of.
Quoted 1 line
This what needs to be commented in my opinion.
Yours,
-- Matti
Jonathan Cameron
maintainerRe: [PATCH v7 06/10] iio: adc: Support ROHM BD79124 ADC
In reply to Matti VaittinenQuoted 10 lines · On Thu, 13 Mar 2025 09:19:03 +0200 Matti Vaittinen <[email protected]>…
The ROHM BD79124 is a 12-bit, 8-channel, SAR ADC. The ADC supports an automatic measurement mode, with an alarm interrupt for out-of-window measurements. The window is configurable for each channel.
The I2C protocol for manual start of the measurement and data reading is somewhat peculiar. It requires the master to do clock stretching after sending the I2C slave-address until the slave has captured the data. Needless to say this is not well suopported by the I2C controllers.
Thus the driver does not support the BD79124's manual measurement mode
Given you are going to be doing a v8 and I'm bored on a train, so utterly trivial comments that you get as a frequent contributor as things to consider for future patches. (I'm sure it's just what you always wanted :)
In theory should be imperative though I don't care as much as some.
Hence, do not support the....
Quoted 5 lines
but implements the measurements using automatic measurement mode relying on the BD79124's ability of storing latest measurements into register.
The driver does also support configuring the threshold events for detecting the out-of-window events.
Trivial editorial comment: that 'does' is not providing anything use in modern English (might have done in the past, no idea!)
"Also support configure the threshold..."
Quoted 11 lines
The BD79124 keeps asserting IRQ for as long as the measured voltage is out of the configured window. Thus the driver masks the received event for a fixed duration (1 second) when an event is handled. This prevents the user-space from choking on the events
The ADC input pins can be also configured as general purpose outputs. Those pins which don't have corresponding ADC channel node in the device-tree will be controllable as GPO.
Signed-off-by Matti Vaittinen <[email protected]>
A few trivial things inline.
Jonathan
Quoted 8 lines
+/*
+ * The high and low limits as well as the recent result values are stored in
+ * the same way in 2 consequent registers. The first register contains 4 bits
+ * of the value. These bits are stored in the high bits [7:4] of register, but
+ * they represent the low bits [3:0] of the value.
+ * The value bits [11:4] are stored in the next regoster.
+ *
+ * Conver the integer to register format and write it using rmw cycle.
Convert?
Quoted 3 lines
+ */
drivers/iio/adc/rohm-bd79124.c new file +2
-0+static int bd79124_write_int_to_reg (struct bd79124_data *data,int reg, +unsigned int val)
..
drivers/iio/adc/rohm-bd79124.c line 468
Quoted 11 lines
drivers/iio/adc/rohm-bd79124.c new file +11
-0+static int bd79124_read_event_config (struct iio_dev *iio_dev, +const struct iio_chan_spec *chan, +enum iio_event_type type, +enum iio_event_direction dir) +{ +struct bd79124_data *data =iio_priv (iio_dev); + +if (chan->channel >=BD79124_MAX_NUM_CHANNELS ) +return -EINVAL ; + +return (data->alarm_monitored[chan->channel] &BIT (dir));
Drop the outer brackets as not adding anything.
Quoted 6 lines
drivers/iio/adc/rohm-bd79124.c new file +3
-0+} +static int bd79124_probe (struct i2c_client *i2c) +{
...
drivers/iio/adc/rohm-bd79124.c line 1064
Quoted 4 lines
drivers/iio/adc/rohm-bd79124.c new file +4
-0+ data->gpio_valid_mask = gpio_pins; + data->gc = bd79124gpo_chip; + data->gc.parent = dev; +devm_mutex_init (dev, &data->mutex);
ret = devm_mutex_init(dev, &data->mutex);
if (ret)
return ret;
It is very unlikely to fail so no point in papering over failing to register the cleanup.
Quoted 16 lines
drivers/iio/adc/rohm-bd79124.c new file +16
-0+ + ret =devm_gpiochip_add_data (dev, &data->gc, data); +if (ret) +return dev_err_probe (dev, ret,"gpio init Failed\n" ); + +if (i2c->irq >0 ) { + ret =devm_request_threaded_irq (dev, i2c->irq, + bd79124_irq_handler, &bd79124_event_handler, +IRQF_ONESHOT ,"adc-thresh-alert" , iio_dev); +if (ret) +return dev_err_probe (data->dev, ret, +"Failed to register IRQ\n" ); + } + +return devm_iio_device_register (data->dev, iio_dev); +}
Matti Vaittinen
maintainerRe: [PATCH v7 06/10] iio: adc: Support ROHM BD79124 ADC
Quoted 12 lines · Jonathan Cameron
Quoted 9 lines · On Thu, 13 Mar 2025 09:19:03 +0200 Matti Vaittinen <[email protected]>…
The ROHM BD79124 is a 12-bit, 8-channel, SAR ADC. The ADC supports an automatic measurement mode, with an alarm interrupt for out-of-window measurements. The window is configurable for each channel.
The I2C protocol for manual start of the measurement and data reading is somewhat peculiar. It requires the master to do clock stretching after sending the I2C slave-address until the slave has captured the data. Needless to say this is not well suopported by the I2C controllers.
Quoted 5 lines
Quoted 1 line
Thus the driver does not support the BD79124's manual measurement mode
Given you are going to be doing a v8 and I'm bored on a train, so utterly trivial comments that you get as a frequent contributor as things to consider for future patches. (I'm sure it's just what you always wanted :)
I don't mind these! :)
I can admit (and I have admitted it), sometimes I get irritated by comments. Maybe that's just natural. Still, in many occasions I am not irritated/annoyed at all, but I am actually genuinely glad I've learnt a thing or 2. Maybe it is also connected to the tone of voice when comments are given?
Quoted 11 lines
In theory should be imperative though I don't care as much as some.
Hence, do not support the....
Quoted 5 lines
but implements the measurements using automatic measurement mode relying on the BD79124's ability of storing latest measurements into register.
The driver does also support configuring the threshold events for detecting the out-of-window events.
Trivial editorial comment: that 'does' is not providing anything use in modern English (might have done in the past, no idea!)
I have learned my English back in the 90's. Back then they told us we were taught British English. My teacher had probably been taught somewhere in the 70's. So, what I've learned is likely not modern English - besides, I liked girls and sports more than school, so I never was an A-class student ... ;)
I suppose you might know better than I (do) ;)
Well, I rarely get feedback from what I write - so this kind of things are valuable. I think I've developed a habit of adding this 'do' to the places where it's not necessary. Sometimes just out of a habit, and sometimes (in my ears) it strengthens the meaning. And I have no idea how correct the usage is unless I (do) get the feedback.
So, thanks.
Quoted 26 lines
"Also support configure the threshold..."
Quoted 11 lines
The BD79124 keeps asserting IRQ for as long as the measured voltage is out of the configured window. Thus the driver masks the received event for a fixed duration (1 second) when an event is handled. This prevents the user-space from choking on the events
The ADC input pins can be also configured as general purpose outputs. Those pins which don't have corresponding ADC channel node in the device-tree will be controllable as GPO.
Signed-off-by Matti Vaittinen <[email protected]>A few trivial things inline.
Jonathan
Quoted 8 lines
+/*
+ * The high and low limits as well as the recent result values are stored in
+ * the same way in 2 consequent registers. The first register contains 4 bits
+ * of the value. These bits are stored in the high bits [7:4] of register, but
+ * they represent the low bits [3:0] of the value.
+ * The value bits [11:4] are stored in the next regoster.
+ *
+ * Conver the integer to register format and write it using rmw cycle.
Quoted 1 line
Convert?
Right. As a note to self, also register, not regoster.
Thanks!
Yours,
-- Matti
Matti Vaittinen
maintainerRe: [PATCH v7 06/10] iio: adc: Support ROHM BD79124 ADC
In reply to Jonathan CameronQuoted 2 lines · Jonathan Cameron
On Thu, 13 Mar 2025 09:19:03 +0200
Matti Vaittinen <[email protected]> wrote:
...
Quoted 16 lines
Quoted 2 lines
drivers/iio/adc/rohm-bd79124.c new file +2
-0+static int bd79124_write_int_to_reg (struct bd79124_data *data,int reg, +unsigned int val)..
drivers/iio/adc/rohm-bd79124.c line 468
Quoted 11 lines
drivers/iio/adc/rohm-bd79124.c new file +11
-0+static int bd79124_read_event_config (struct iio_dev *iio_dev, +const struct iio_chan_spec *chan, +enum iio_event_type type, +enum iio_event_direction dir) +{ +struct bd79124_data *data =iio_priv (iio_dev); + +if (chan->channel >=BD79124_MAX_NUM_CHANNELS ) +return -EINVAL ; + +return (data->alarm_monitored[chan->channel] &BIT (dir));Drop the outer brackets as not adding anything.
I just noticed that the integer returned from here is directly provided to the user-space. I don't know the history, but it feels a bit off to me. I mean, I would expect the read from sysfs file "*_en" to return '1' or '0' - not 0x04.
Oh well, I suppose it's too late to change this in the IIO core - but I'll do:
return !!(data->alarm_monitored[chan->channel] & BIT(dir));
in v8.
Yours,
-- Matti
Jonathan Cameron
maintainerRe: [PATCH v7 06/10] iio: adc: Support ROHM BD79124 ADC
Quoted 23 lines · On Mon, 17 Mar 2025 13:24:07 +0200 Matti Vaittinen <[email protected]>…
Quoted 2 lines · Jonathan Cameron
On Thu, 13 Mar 2025 09:19:03 +0200
Matti Vaittinen <[email protected]> wrote:...
Quoted 16 lines
Quoted 2 lines
drivers/iio/adc/rohm-bd79124.c new file +2
-0+static int bd79124_write_int_to_reg (struct bd79124_data *data,int reg, +unsigned int val)..
drivers/iio/adc/rohm-bd79124.c line 468
Quoted 11 lines
drivers/iio/adc/rohm-bd79124.c new file +11
-0+static int bd79124_read_event_config (struct iio_dev *iio_dev, +const struct iio_chan_spec *chan, +enum iio_event_type type, +enum iio_event_direction dir) +{ +struct bd79124_data *data =iio_priv (iio_dev); + +if (chan->channel >=BD79124_MAX_NUM_CHANNELS ) +return -EINVAL ; + +return (data->alarm_monitored[chan->channel] &BIT (dir));Drop the outer brackets as not adding anything.
Quoted 8 lines
I just noticed that the integer returned from here is directly provided to the user-space. I don't know the history, but it feels a bit off to me. I mean, I would expect the read from sysfs file "
*_en" to return '1' or '0' - not0x04.Oh well, I suppose it's too late to change this in the IIO core - but I'll do:
return !!(data->alarm_monitored[chan->channel] & BIT(dir));
Agreed it should be returning 1 or 0.
This stuff is a little bit messy. I'd not be against that ABI cleanup if we squashed the values to 0,1 in the core as a follow up.
I doubt anyone relies on getting 0x4 as that would be very driver specific userspace code!
Jonathan
Quoted 6 lines
in v8.
Yours,
-- Matti
Andy Shevchenko
reviewerRe: [PATCH v7 06/10] iio: adc: Support ROHM BD79124 ADC
Quoted 5 lines · Jonathan Cameron
Quoted 3 lines · On Mon, 17 Mar 2025 13:24:07 +0200 Matti Vaittinen <[email protected]>…
Quoted 2 lines · Jonathan Cameron
On Thu, 13 Mar 2025 09:19:03 +0200
Matti Vaittinen <[email protected]> wrote:
...
Quoted 13 lines
Quoted 4 lines
Quoted 3 lines
drivers/iio/adc/rohm-bd79124.c line 468
Quoted 1 line
drivers/iio/adc/rohm-bd79124.c new file +1
-0+return (data->alarm_monitored[chan->channel] &BIT (dir));Drop the outer brackets as not adding anything.
Quoted 8 lines
I just noticed that the integer returned from here is directly provided to the user-space. I don't know the history, but it feels a bit off to me. I mean, I would expect the read from sysfs file "
*_en" to return '1' or '0' - not0x04.Oh well, I suppose it's too late to change this in the IIO core - but I'll do:
return !!(data->alarm_monitored[chan->channel] & BIT(dir));
Quoted 7 lines
Agreed it should be returning 1 or 0.
This stuff is a little bit messy. I'd not be against that ABI cleanup if we squashed the values to 0,1 in the core as a follow up.
I doubt anyone relies on getting
0x4as that would be very driver specific userspace code!
FWIW, the time this discussion was held, I looked at the code and it seems we have such drivers. I doubt we can change it without potential breakage of (some) user space tools.
Signature · 2 lines
With Best Regards, Andy Shevchenko
Matti Vaittinen
maintainerRe: [PATCH v7 06/10] iio: adc: Support ROHM BD79124 ADC
Quoted 27 lines · Andy Shevchenko
Quoted 5 lines · Jonathan Cameron
Quoted 3 lines · On Mon, 17 Mar 2025 13:24:07 +0200 Matti Vaittinen <[email protected]>…
Quoted 2 lines · Jonathan Cameron
On Thu, 13 Mar 2025 09:19:03 +0200
Matti Vaittinen <[email protected]> wrote:...
Quoted 18 lines
Quoted 4 lines
Quoted 3 lines
drivers/iio/adc/rohm-bd79124.c line 468
Quoted 1 line
drivers/iio/adc/rohm-bd79124.c new file +1
-0+return (data->alarm_monitored[chan->channel] &BIT (dir));Drop the outer brackets as not adding anything.
Quoted 8 lines
I just noticed that the integer returned from here is directly provided to the user-space. I don't know the history, but it feels a bit off to me. I mean, I would expect the read from sysfs file "
*_en" to return '1' or '0' - not0x04.Oh well, I suppose it's too late to change this in the IIO core - but I'll do:
return !!(data->alarm_monitored[chan->channel] & BIT(dir));Agreed it should be returning 1 or 0.
This stuff is a little bit messy. I'd not be against that ABI cleanup if we squashed the values to 0,1 in the core as a follow up.
Quoted 6 lines
Quoted 2 lines
I doubt anyone relies on getting
0x4as that would be very driver specific userspace code!FWIW, the time this discussion was held, I looked at the code and it seems we have such drivers. I doubt we can change it without potential breakage of (some) user space tools.
Thanks for the check, and for sharing the results Andy.
I was considering this for a while but eventually I didn't want to take a chance of breaking things. I have a feeling that majority of application writers, who happen to be writing something using a specific sensor, would just make their code to match what-ever they see kernel retuning via sysfs.
I know younger me would in the early 2000s. If I got a board where I was able to read values from sysfs, I would have just written the code which matches whatever I saw in sysfs when testing out things. I would have tried reading the file and then making my application to expect exactly the value "0x4" - assuming other values may have some other, unknown to me, meaning. I wouldn't have gone after a documentation, much less to send a question or a patch upstream :)
So, I wouldn't be surprized if someone else had done just this same, and they might be upset if we break their app(s).
Yours,
-- Matti
Matti Vaittinen
maintainerPATCH v7 7/10 MAINTAINERS: Add IIO ADC helpers
In reply to Matti VaittinenAdd undersigned as a maintainer for the IIO ADC helpers.
---
Revision history:
v2 =>
- No changes
RFC v1 => v2:
- New patch
--- MAINTAINERS | 7 +++++++ 1 file changed, 7 insertions(+)
MAINTAINERS +7 -0
@@ -11208,6 +11208,13 @@ L: [email protected] S: Maintained F: drivers/media/rc/iguanair.c +IIO ADC HELPERS +M: Matti Vaittinen <[email protected]> +L: [email protected] +S: Maintained +F: drivers/iio/adc/industrialio-adc.c +F: include/linux/iio/adc-helpers.h + IIO BACKEND FRAMEWORK M: Nuno Sa <[email protected]> R: Olivier Moysan <[email protected]>
Signature · 1 line
2.48.1
Matti Vaittinen
maintainerPATCH v7 8/10 MAINTAINERS: Add ROHM BD79124 ADC/GPO
In reply to Matti VaittinenAdd undersigned as a maintainer for the ROHM BD79124 ADC/GPO driver.
---
Revision history:
v2 =>
- No changes
RFC v1 => v2:
- Drop MFD and pinmux drivers
--- MAINTAINERS | 5 +++++ 1 file changed, 5 insertions(+)
MAINTAINERS +5 -0
@@ -20547,6 +20547,11 @@ S: Supported F: drivers/power/supply/bd99954-charger.c F: drivers/power/supply/bd99954-charger.h +ROHM BD79124 ADC / GPO IC +M: Matti Vaittinen <[email protected]> +S: Supported +F: drivers/iio/adc/rohm-bd79124.c + ROHM BH1745 COLOUR SENSOR M: Mudit Sharma <[email protected]> L: [email protected]
Signature · 1 line
2.48.1
Matti Vaittinen
maintainerPATCH v7 9/10 net: gianfar: Use device_get_child_node_count_named()
In reply to Matti VaittinenWe can avoid open-coding the loop construct which counts firmware child nodes with a specific name by using the newly added device_get_child_node_count_named().
The gianfar driver has such open-coded loop. Replace it with the device_get_child_node_count_named().
---
Revision history:
v6 =>:
- No changes
v5 (RFC) => v6:
- Drop RFC
- Adapt to changed function name.
It's fair to tell the pros and cons of this patch.
The simplification is there, but it's not a big one. It comes with a cost of getting the property.h included in this driver which currently uses exclusively the of_* APIs.
NOTE: This patch depends on the patch:
[2/10] "property: Add functions to iterate named child"
Compile-tested only!
--- drivers/net/ethernet/freescale/gianfar.c | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-)
drivers/net/ethernet/freescale/gianfar.c +4 -13
@@ -97,6 +97,7 @@#include <linux/phy_fixed.h> #include <linux/of.h> #include <linux/of_net.h> +#include <linux/property.h> #include "gianfar.h"
@@ -571,18 +572,6 @@ static int gfar_parse_group(struct device_node *np,return 0 ; } -static int gfar_of_group_count (struct device_node *np) -{ -struct device_node *child; -int num =0 ; - -for_each_available_child_of_node (np, child) -if (of_node_name_eq (child,"queue-group" )) - num++; - -return num; -} -/* Reads the controller's registers to determine what interface * connects it to the PHY. */
@@ -654,8 +643,10 @@ static int gfar_of_init(struct platform_device *ofdev, struct net_device **pdev) num_rx_qs =1 ; }else {/* MQ_MG_MODE */ /* get the actual number of supported groups */ -unsigned int num_grps =gfar_of_group_count (np); +unsigned int num_grps; + num_grps =device_get_named_child_node_count (&ofdev->dev, +"queue-group" );if (num_grps ==0 || num_grps >MAXGROUPS ) {dev_err (&ofdev->dev,"Invalid # of int groups(%d)\n" , num_grps);
Signature · 1 line
2.48.1
Re: [PATCH v7 net-next 09/10] net: gianfar: Use device_get_child_node_count_named()
Quoted 6 lines · Matti Vaittinen
We can avoid open-coding the loop construct which counts firmware child nodes with a specific name by using the newly added
device_get_child_node_count_named().The gianfar driver has such open-coded loop. Replace it with the
device_get_child_node_count_named().
FWIW,
Signature · 2 lines
With Best Regards, Andy Shevchenko
Matti Vaittinen
maintainerPATCH v7 10/10 media: thp7312: Use helper for iterating named child nodes
In reply to Matti VaittinenSlightly simplify code iterating the child nodes with specific names using the new fwnode_for_each_available_named_child_node().
---
Revision history:
v6 =>:
- No changes
v5 => v6:
- New patch
NOTE: This patch depends on the patch:
[2/10] "property: Add functions to iterate named child"
Compile-tested only!
--- drivers/media/i2c/thp7312.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-)
drivers/media/i2c/thp7312.c +3 -5
@@ -2067,11 +2067,9 @@ static int thp7312_parse_dt(struct thp7312_device *thp7312)return -EINVAL ; } -fwnode_for_each_available_child_node (sensors, node) { -if (fwnode_name_eq (node,"sensor" )) { -if (!thp7312_sensor_parse_dt (thp7312, node)) - num_sensors++; - } +fwnode_for_each_available_named_child_node (sensors, node,"sensor" ) { +if (!thp7312_sensor_parse_dt (thp7312, node)) + num_sensors++; }fwnode_handle_put (sensors);
Signature · 1 line
2.48.1