[POC] iio: ad74413: allow channel configuration to be given via module parameters

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Just to see how it would look, I tried doing the below. Since a board
may have more than one ad74412/ad74413, one needs to be able to
differentiate between them. So for now each module parameter channelX
(X=0,1,2,3) accepts a space-separated list of <label>:<function>,
where label is matched against the label property in device tree, but
also allowing * to match any, which is more convenient when one knows
there is only one device.

Aside from the missing documentation (MODULE_PARM_DESC), there are of
course various details to hash out. E.g., should the function be
specified with a raw integer as here, or should we take a text string
"voltage-output", "current-input-ext-power" etc. and translate those?
Should we use space or comma or semicolon as separator? And so on.

I also considered whether instead of the label one should instead
match on the OF_FULLNAME,
e.g. /soc@0/bus@30800000/spi@30840000/ad74412r@0, but that's a lot
more complicated, and I assume that anybody that has more than one of
these chips would anyway assign a label so that they can distinguish
their /sys/bus/iio/... directories.

I should also note that it is not unprecedented for modules to take
parameters that do some sort of (ad hoc) parsing to apply settings
per-device. For example:

- ignore_wake in drivers/gpio/gpiolib-acpi.c
- mtdparts in drivers/mtd/parsers/cmdlinepart.c
- pci_devs_to_hide in drivers/xen/xen-pciback/pci_stub.c
- quirks in drivers/hid/usbhid/hid-core.c

So the question is, is there any chance that anything like this could
be accepted? If so, I'll of course spin this into a real patch with
proper MODULE_PARM_DESC and commit log etc.

This has been tested doing

  insmod ad74413r.ko 'channel0=*:1' 'channel1=*:3' 'channel2=*:2' 'channel3=*:4'

and seeing that the channels did indeed come up as expected, where the
device tree specified CH_FUNC_HIGH_IMPEDANCE for all of them.

---
 drivers/iio/addac/ad74413r.c | 37 ++++++++++++++++++++++++++++++++++--
 1 file changed, 35 insertions(+), 2 deletions(-)

diff --git a/drivers/iio/addac/ad74413r.c b/drivers/iio/addac/ad74413r.c
index ef873737c33a..284bdb358dec 100644
--- a/drivers/iio/addac/ad74413r.c
+++ b/drivers/iio/addac/ad74413r.c
@@ -1146,6 +1146,35 @@ static const struct ad74413r_channels ad74413r_channels_map[] = {
 	[CH_FUNC_CURRENT_INPUT_LOOP_POWER_HART] = AD74413R_CHANNELS(current_input),
 };
 
+static char *channel_function[AD74413R_CHANNEL_MAX];
+
+static int ad74413r_get_channel_function(struct ad74413r_state *st, u32 index,
+					 struct fwnode_handle *channel_node)
+{
+	const char *s, *c, *label;
+	u32 func, label_len;
+
+	if (device_property_read_string(st->dev, "label", &label))
+		label = "";
+
+	label_len = strlen(label);
+	for (s = channel_function[index]; s; s = strchr(s, ' ')) {
+		s = skip_spaces(s);
+		c = strchr(s, ':');
+		if (!c)
+			break;
+
+		if ((c - s == label_len && !memcmp(s, label, label_len)) ||
+		    (c - s == 1 && *s == '*'))
+			return simple_strtol(c + 1, NULL, 10);
+	}
+
+	func = CH_FUNC_HIGH_IMPEDANCE;
+	fwnode_property_read_u32(channel_node, "adi,ch-func", &func);
+
+	return func;
+}
+
 static int ad74413r_parse_channel_config(struct iio_dev *indio_dev,
 					 struct fwnode_handle *channel_node)
 {
@@ -1171,8 +1200,7 @@ static int ad74413r_parse_channel_config(struct iio_dev *indio_dev,
 		return -EINVAL;
 	}
 
-	config->func = CH_FUNC_HIGH_IMPEDANCE;
-	fwnode_property_read_u32(channel_node, "adi,ch-func", &config->func);
+	config->func = ad74413r_get_channel_function(st, index, channel_node);
 
 	if (config->func < CH_FUNC_MIN || config->func > CH_FUNC_MAX) {
 		dev_err(st->dev, "Invalid channel function %u\n", config->func);
@@ -1494,6 +1522,11 @@ static struct spi_driver ad74413r_driver = {
 	.id_table = ad74413r_spi_id,
 };
 
+module_param_named(channel0, channel_function[0], charp, 0444);
+module_param_named(channel1, channel_function[1], charp, 0444);
+module_param_named(channel2, channel_function[2], charp, 0444);
+module_param_named(channel3, channel_function[3], charp, 0444);
+
 module_driver(ad74413r_driver,
 	      ad74413r_register_driver,
 	      ad74413r_unregister_driver);
-- 
2.37.2




[Index of Archives]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Input]     [Linux Kernel]     [Linux SCSI]     [X.org]

  Powered by Linux