Re: [PATCH v1 2/2] iio: adc: adding support for pac193x

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

 



On Sun, 2023-03-12 at 16:42 +0000, Jonathan Cameron wrote:
> EXTERNAL EMAIL: Do not click links or open attachments unless you
> know the content is safe
> 
> > 
> > > 
> > > 
> > > 
> > > > +
> > > > +     len += sprintf(buf, "%u\n", chip_info->shunts[target]);
> > > > +
> > > > +     return len;
> > > > +}
> > > > +
> > > > +static ssize_t channel_name_show(struct device *dev,
> > > 
> > > Looks like per channel label support provided by the read_label
> > > iio_info callback.
> > > 
> > 
> > I was trying to use the read_label iio_info callback but I end it
> > up
> > into a sysfs error related to duplicated labels.
> 
> That's interesting.  Can you provide more info on that. I'd like to
> understand why that's happening to you.
> 

I have add the ".read_label" and the function asociated with it to the
driver but here is the error:

root@sama5d27-wlsom1-ek-sd:~/work/pac193x# insmod pac1934.ko
pac193x 1-001c: :pac193x_prep_iio_channels: Channel 2 active
pac193x 1-001c: :pac193x_prep_iio_channels: Channel 3 active
pac193x 1-001c: :pac193x_prep_iio_channels: Channel 4 active
iio iio:device1: tried to double register : in_voltage2_label
pac193x 1-001c: Failed to register sysfs interfaces
iio iio:device1: error -EBUSY: Can't register IIO device
pac193x: probe of 1-001c failed with error -16



Here are the list of files in case I don't use read_label (only
physical channels 2 to 4 are available):

root@sama5d27-wlsom1-ek-sd:~/work/pac193x# ls
/sys/bus/iio/devices/iio\:device1/
channel_name_2        in_current4_mean_raw  in_power2_raw         
in_voltage2_scale     power
channel_name_3        in_current4_raw       in_power2_scale       
in_voltage3_mean_raw  reset_accumulators
channel_name_4        in_current4_scale     in_power3_raw         
in_voltage3_raw       sampling_frequency_available
in_current2_mean_raw  in_energy2_raw        in_power3_scale       
in_voltage3_scale     shunt_value_2
in_current2_raw       in_energy2_scale      in_power4_raw         
in_voltage4_mean_raw  shunt_value_3
in_current2_scale     in_energy3_raw        in_power4_scale       
in_voltage4_raw       shunt_value_4
in_current3_mean_raw  in_energy3_scale      in_sampling_frequency 
in_voltage4_scale     subsystem
in_current3_raw       in_energy4_raw        in_voltage2_mean_raw   name
uevent
in_current3_scale     in_energy4_scale      in_voltage2_raw       
of_node               waiting_for_supplier



> > 
> > Also I'm not sure if this read_label will help me in the end. What
> > I
> > was aiming to obtain here with the "channel_name_show" and the
> > custom
> > IIO attribute was to have "an umbrella" name/label for multiple IIO
> > channels. For example on physical "channel 1" we will measure the
> > voltage, the current and the power because all of those IIO
> > channels
> > will point to one board power supply (like VDD, VIO, V_GPU, V_DDR,
> > etc).
> 
> That should be possible with read_label as it's free form text.
> Perhaps I'm missing why that doesn't provide enough information for
> what
> you need.
> 
> > 

It seems it does more that I need. My concern is that the read_label
will do a label for all available channels (like _raw or scale_ will
do) and I want to  have just up to a maximum of 4 labels each one will
cover the multiple entries (e.g.: channel_name_2 will be a umbrela
"label" for:
in_power2_raw         in_voltage2_scale  in_power2_scale        
in_current2_mean_raw  in_energy2_raw     shunt_value_2
in_current2_raw       in_energy2_scale   in_current2_scale     
in_voltage2_mean_raw  in_voltage2_raw

> > 
> > 
> > 
> > 
> > > > +                              struct device_attribute *attr,
> > > > +                              char *buf)
> > > > +{
> > > > +     struct iio_dev *indio_dev = dev_to_iio_dev(dev);
> > > > +     struct pac193x_chip_info *chip_info =
> > > > iio_priv(indio_dev);
> > > > +     int len = 0;
> > > > +     int target = (int)(attr->attr.name[strlen(attr-
> > > > >attr.name) -
> > > > 1] - '0') - 1;
> > > > +
> > > > +     len += sprintf(buf, "%s\n", chip_info-
> > > > > channel_names[target]);
> > > > +
> > > > +     return len;
> > > > +}
> > > > +
> > > > +static ssize_t shunt_value_store(struct device *dev,
> > > 
> > > Shunt values aren't normally dynamic.  Why do you need to write
> > > it
> > > from
> > > userspace? I'd expect that to come from firmware.
> > > 
> > > If it's needed the ext_info framework might be a better fit than
> > > direct implementation of the attribute.
> > 
> > 
> > Yes, usually the shunt aren't normally dynamic, but what I'm aiming
> > to
> > get here is to let the user to overwrite the value after a
> > calibration
> > of the system. This will improve the accuracy of the reading even
> > in
> > the case the shunts are not of high precision ones.
> 
> I'll go with maybe on this.  Perhaps not a feature for the initial
> version of the driver, but one that is better to discuss in a follow
> up thread along with details of the expected calibration process etc.
> > 

Calibration process could be easly be done. Just think that we have a
linux board that measure some dinamic load that uses a connector. The
load could be easily changed by the user with a "calibrated" load, read
the measurement do the math expected versus read values and update the
shunt value. Those values needs to be stored by the user somewhere to
be reused after a reboot. After the board is calibrated a "normal" load
could pluged in (one example is to monitor the charge/discharge current
of a battery).


> > 
> > > 
> > 
> > > 
> > > > shunt_value_store, 0);
> > > > +static IIO_DEVICE_ATTR(shunt_value_2, 0644, shunt_value_show,
> > > > shunt_value_store, 0);
> > > > +static IIO_DEVICE_ATTR(shunt_value_3, 0644, shunt_value_show,
> > > > shunt_value_store, 0);
> > > > +static IIO_DEVICE_ATTR(shunt_value_4, 0644, shunt_value_show,
> > > > shunt_value_store, 0);
> > > > +
> > > > +static IIO_DEVICE_ATTR(channel_name_1, 0444,
> > > > channel_name_show,
> > > > NULL, 0);
> > > > +static IIO_DEVICE_ATTR(channel_name_2, 0444,
> > > > channel_name_show,
> > > > NULL, 0);
> > > > +static IIO_DEVICE_ATTR(channel_name_3, 0444,
> > > > channel_name_show,
> > > > NULL, 0);
> > > > +static IIO_DEVICE_ATTR(channel_name_4, 0444,
> > > > channel_name_show,
> > > > NULL, 0);
> > > > +
> > > > +static IIO_DEVICE_ATTR(reset_accumulators, 0200, NULL,
> > > > reset_accumulators_store, 0);
> > > > +
> > > > +static struct attribute *pac193x_all_attributes[] = {
> > > > +     PAC193X_DEV_ATTR(shunt_value_1),
> > > 
> > > These all need ABI documentation so that we can easily review
> > > what
> > > they do.
> > > Documenation/ABI/testing/sysfs-bus-iio-pac1931
> > > Note that if they overlap with ABI used elsewhere we may need to
> > > move
> > > it to a more
> > > generic place (there can't be two lots of docs for the same ABI
> > > element)
> > > 
> > 
> > I will add comments into the code. The "shunt_value_show" will
> > print
> > the shunt value used to calculate current and power.
> I'd prefer handling shut calibration as a future patch because it
> needs
> some thought and discussion + may delay the rest of the driver. 
> Without that
> ability to tweak it I'm not sure it provides value to be able to read
> it now.
> 
> > The "channel_name_show" is the name of the device channel used to
> > easily identify what we are measuring (V_DDR, V_GPU, V_IO, etc) and
> > it's an "umbrella" for multiple IIO measurements (voltage, current
> > and
> > power)
> 
> As above. I'd like to think a bit more on this one.
> 

OK.


> > 
> > "reset_accumulators" will help the user to reinitialize the power
> > on
> > all channels.
> 
> This sounds like the rare case where the ENABLE IIO ABI may fit.
> We use that for things like step counters that also accumulate over
> time.  If we can use that, I'd prefer it to custom ABI.
> 
> > 
> > 
> > > > +     if (!indio_dev) {
> > > > +             dev_err_probe(&indio_dev->dev,
> > > > PTR_ERR(indio_dev),
> > > > +                           "Can't allocate iio device\n");
> > > > +             return -ENOMEM;
> > > > +     }
> > > > +
> > > > +     chip_info = iio_priv(indio_dev);
> > > > +
> > > > +     i2c_set_clientdata(client, indio_dev);
> > > 
> > > Assuming you follow suggestion to go fully devm managed handling
> > > of
> > > remove, I don't htink
> > > you will need this.
> > > 
> > > > +     chip_info->client = client;
> > > > +
> > > > +     memset(&chip_info->chip_reg_data, 0, sizeof(chip_info-
> > > > > chip_reg_data));
> > > 
> > > The iio_priv space is allocated with kzalloc so no need to zero
> > > here.
> > > 
> > > > +
> > > > +     if (ACPI_HANDLE(&client->dev)) {
> > > > +             pac193x_get_variant(chip_info);
> > > 
> > > Why is this ACPI specific?
> > 
> > Not really. I will change it to work in both cases.
> > 
> > > 
> > > If you can query the variant from the hardware, that is the right
> > > thing to use
> > > for all registration types.  It can be helpful to call out if
> > > there
> > > is
> > > a mismatch though with a warning print, so comparing the result
> > > of
> > > the i2c call with the data is fine.
> > > 
> > > > +     } else {
> > > > +             dev_id = id->driver_data;
> > > > +
> > > > +             /* store the type of chip */
> > > > +             chip_info->chip_variant = dev_id;
> > > > +
> > > > +             /* get the maximum number of channels for the
> > > > given
> > > > chip id */
> > > > +             chip_info->phys_channels =
> > > > pac193x_chip_config[dev_id].phys_channels;
> > > > +     }
> > > > +
> > > > +     /*
> > > > +      * load default settings - all channels disabled,
> > > > +      * uni directional flow, default shunt values
> > > 
> > > The concept of a default shunt value bothers me a little if this
> > > is
> > > an external resistor.  How is there in any real sense a default?
> > > Can we just fail if it's not provided - or wrap the default up
> > > for
> > > just ACPI case where I guess there might be firmware that doesn't
> > > specify it?
> > 
> > I'm doing some math with that resistor later in code and I was just
> > making sure that I will not divide by 0, but indeed I could just
> > exit
> > in case the value is not correctly set.
> 
> Exit is best thing to do I think.
> 
> 
OK.


> > 
Thanks,
Marius




[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