lkml.org 
[lkml]   [2021]   [Oct]   [14]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH v5 3/7] iio: adc: stm32-adc: split channel init into several routines
    Date
    Split stm32_adc_chan_of_init channel initialization function into
    several routines to increase readability and prepare channel
    generic binding handling.

    Signed-off-by: Olivier Moysan <olivier.moysan@foss.st.com>
    Reviewed-by: Fabrice Gasnier <fabrice.gasnier@foss.st.com>
    ---
    drivers/iio/adc/stm32-adc.c | 131 ++++++++++++++++++++++++------------
    1 file changed, 87 insertions(+), 44 deletions(-)

    diff --git a/drivers/iio/adc/stm32-adc.c b/drivers/iio/adc/stm32-adc.c
    index 5088de835bb1..2f137d14f141 100644
    --- a/drivers/iio/adc/stm32-adc.c
    +++ b/drivers/iio/adc/stm32-adc.c
    @@ -194,6 +194,7 @@ struct stm32_adc_cfg {
    * @smpr_val: sampling time settings (e.g. smpr1 / smpr2)
    * @cal: optional calibration data on some devices
    * @chan_name: channel name array
    + * @num_diff: number of differential channels
    */
    struct stm32_adc {
    struct stm32_adc_common *common;
    @@ -217,6 +218,7 @@ struct stm32_adc {
    u32 smpr_val[2];
    struct stm32_adc_calib cal;
    char chan_name[STM32_ADC_CH_MAX][STM32_ADC_CH_SZ];
    + u32 num_diff;
    };

    struct stm32_adc_diff_channel {
    @@ -1706,17 +1708,11 @@ static void stm32_adc_chan_init_one(struct iio_dev *indio_dev,
    }
    }

    -static int stm32_adc_chan_of_init(struct iio_dev *indio_dev, bool timestamping)
    +static int stm32_adc_get_legacy_chan_count(struct iio_dev *indio_dev, struct stm32_adc *adc)
    {
    struct device_node *node = indio_dev->dev.of_node;
    - struct stm32_adc *adc = iio_priv(indio_dev);
    const struct stm32_adc_info *adc_info = adc->cfg->adc_info;
    - struct stm32_adc_diff_channel diff[STM32_ADC_CH_MAX];
    - struct property *prop;
    - const __be32 *cur;
    - struct iio_chan_spec *channels;
    - int scan_index = 0, num_channels = 0, num_diff = 0, ret, i;
    - u32 val, smp = 0;
    + int num_channels = 0, ret;

    ret = of_property_count_u32_elems(node, "st,adc-channels");
    if (ret > adc_info->max_channels) {
    @@ -1727,41 +1723,54 @@ static int stm32_adc_chan_of_init(struct iio_dev *indio_dev, bool timestamping)
    }

    ret = of_property_count_elems_of_size(node, "st,adc-diff-channels",
    - sizeof(*diff));
    + sizeof(struct stm32_adc_diff_channel));
    if (ret > adc_info->max_channels) {
    dev_err(&indio_dev->dev, "Bad st,adc-diff-channels?\n");
    return -EINVAL;
    } else if (ret > 0) {
    - int size = ret * sizeof(*diff) / sizeof(u32);
    -
    - num_diff = ret;
    + adc->num_diff = ret;
    num_channels += ret;
    + }
    +
    + return num_channels;
    +}
    +
    +static int stm32_adc_legacy_chan_init(struct iio_dev *indio_dev,
    + struct stm32_adc *adc,
    + struct iio_chan_spec *channels)
    +{
    + struct device_node *node = indio_dev->dev.of_node;
    + const struct stm32_adc_info *adc_info = adc->cfg->adc_info;
    + struct stm32_adc_diff_channel diff[STM32_ADC_CH_MAX];
    + u32 num_diff = adc->num_diff;
    + int size = num_diff * sizeof(*diff) / sizeof(u32);
    + int scan_index = 0, val, ret, i;
    + struct property *prop;
    + const __be32 *cur;
    +
    + if (num_diff) {
    ret = of_property_read_u32_array(node, "st,adc-diff-channels",
    (u32 *)diff, size);
    - if (ret)
    + if (ret) {
    + dev_err(&indio_dev->dev, "Failed to get diff channels %d\n", ret);
    return ret;
    - }
    + }

    - if (!num_channels) {
    - dev_err(&indio_dev->dev, "No channels configured\n");
    - return -ENODATA;
    - }
    + for (i = 0; i < num_diff; i++) {
    + if (diff[i].vinp >= adc_info->max_channels ||
    + diff[i].vinn >= adc_info->max_channels) {
    + dev_err(&indio_dev->dev, "Invalid channel in%d-in%d\n",
    + diff[i].vinp, diff[i].vinn);
    + return -EINVAL;
    + }

    - /* Optional sample time is provided either for each, or all channels */
    - ret = of_property_count_u32_elems(node, "st,min-sample-time-nsecs");
    - if (ret > 1 && ret != num_channels) {
    - dev_err(&indio_dev->dev, "Invalid st,min-sample-time-nsecs\n");
    - return -EINVAL;
    + stm32_adc_chan_init_one(indio_dev, &channels[scan_index],
    + diff[i].vinp, diff[i].vinn,
    + scan_index, true);
    + scan_index++;
    + }
    }

    - if (timestamping)
    - num_channels++;
    -
    - channels = devm_kcalloc(&indio_dev->dev, num_channels,
    - sizeof(struct iio_chan_spec), GFP_KERNEL);
    - if (!channels)
    - return -ENOMEM;
    -
    of_property_for_each_u32(node, "st,adc-channels", prop, cur, val) {
    if (val >= adc_info->max_channels) {
    dev_err(&indio_dev->dev, "Invalid channel %d\n", val);
    @@ -1771,8 +1780,7 @@ static int stm32_adc_chan_of_init(struct iio_dev *indio_dev, bool timestamping)
    /* Channel can't be configured both as single-ended & diff */
    for (i = 0; i < num_diff; i++) {
    if (val == diff[i].vinp) {
    - dev_err(&indio_dev->dev,
    - "channel %d miss-configured\n", val);
    + dev_err(&indio_dev->dev, "channel %d misconfigured\n", val);
    return -EINVAL;
    }
    }
    @@ -1781,19 +1789,54 @@ static int stm32_adc_chan_of_init(struct iio_dev *indio_dev, bool timestamping)
    scan_index++;
    }

    - for (i = 0; i < num_diff; i++) {
    - if (diff[i].vinp >= adc_info->max_channels ||
    - diff[i].vinn >= adc_info->max_channels) {
    - dev_err(&indio_dev->dev, "Invalid channel in%d-in%d\n",
    - diff[i].vinp, diff[i].vinn);
    - return -EINVAL;
    - }
    - stm32_adc_chan_init_one(indio_dev, &channels[scan_index],
    - diff[i].vinp, diff[i].vinn, scan_index,
    - true);
    - scan_index++;
    + return scan_index;
    +}
    +
    +static int stm32_adc_chan_of_init(struct iio_dev *indio_dev, bool timestamping)
    +{
    + struct device_node *node = indio_dev->dev.of_node;
    + struct stm32_adc *adc = iio_priv(indio_dev);
    + const struct stm32_adc_info *adc_info = adc->cfg->adc_info;
    + struct iio_chan_spec *channels;
    + int scan_index = 0, num_channels = 0, ret, i;
    + u32 smp = 0;
    +
    + ret = stm32_adc_get_legacy_chan_count(indio_dev, adc);
    + if (ret < 0)
    + return ret;
    + num_channels = ret;
    +
    + if (!num_channels) {
    + dev_err(&indio_dev->dev, "No channels configured\n");
    + return -ENODATA;
    }

    + if (num_channels > adc_info->max_channels) {
    + dev_err(&indio_dev->dev, "Channel number [%d] exceeds %d\n",
    + num_channels, adc_info->max_channels);
    + return -EINVAL;
    + }
    +
    + /* Optional sample time is provided either for each, or all channels */
    + ret = of_property_count_u32_elems(node, "st,min-sample-time-nsecs");
    + if (ret > 1 && ret != num_channels) {
    + dev_err(&indio_dev->dev, "Invalid st,min-sample-time-nsecs\n");
    + return -EINVAL;
    + }
    +
    + if (timestamping)
    + num_channels++;
    +
    + channels = devm_kcalloc(&indio_dev->dev, num_channels,
    + sizeof(struct iio_chan_spec), GFP_KERNEL);
    + if (!channels)
    + return -ENOMEM;
    +
    + ret = stm32_adc_legacy_chan_init(indio_dev, adc, channels);
    + if (ret < 0)
    + return ret;
    + scan_index = ret;
    +
    for (i = 0; i < scan_index; i++) {
    /*
    * Using of_property_read_u32_index(), smp value will only be
    --
    2.17.1
    \
     
     \ /
      Last update: 2021-10-14 15:14    [W:8.377 / U:0.032 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site