Re: [PATCH v5 4/6] iio: adc: adi-axi-adc: set data format

David Lechner
2024-11-01T21:00:19Z

On 11/1/24 2:52 PM, David Lechner wrote:
> On 11/1/24 6:23 AM, Antoniu Miclaus wrote:
>> Add support for selecting the data format within the AXI ADC ip.
>>
>> Signed-off-by: Antoniu Miclaus <antoniu.miclaus@analog.com>
>> ---
>> no changes in v5.
>> drivers/iio/adc/adi-axi-adc.c | 22 ++++++++++++++++++++++
>> 1 file changed, 22 insertions(+)
>>
>> diff --git a/drivers/iio/adc/adi-axi-adc.c b/drivers/iio/adc/adi-axi-adc.c
>> index f6475bc93796..6f658d9b4c9d 100644
>> --- a/drivers/iio/adc/adi-axi-adc.c
>> +++ b/drivers/iio/adc/adi-axi-adc.c
>> @@ -45,6 +45,9 @@
>> #define ADI_AXI_ADC_REG_CTRL 0x0044
>> #define ADI_AXI_ADC_CTRL_DDR_EDGESEL_MASK BIT(1)
>>
>> +#define ADI_AXI_ADC_REG_CNTRL_3 0x004c
>> +#define ADI_AXI_ADC_CNTRL_3_CUSTOM_CTRL_MSK GENMASK(7, 0)
>> +
>> #define ADI_AXI_ADC_REG_DRP_STATUS 0x0074
>> #define ADI_AXI_ADC_DRP_LOCKED BIT(17)
>>
>> @@ -312,6 +315,24 @@ static int axi_adc_interface_type_get(struct iio_backend *back,
>> return 0;
>> }
>>
>> +static int axi_adc_data_size_set(struct iio_backend *back, ssize_t size)
>> +{
>> + struct adi_axi_adc_state *st = iio_backend_get_priv(back);
>> + unsigned int val;
>> +
>> + if (size <= 20)
>> + val = 0;
>> + else if (size <= 24)
>> + val = 1;
>> + else if (size <= 32)
>> + val = 3;
>
> Should these be exact matches instead of "<="?
>
> Also, what would val = 2 mean? Perhaps we need some macros to explain
> the meanings of these values. The docs linked below give the meaning
> for a different chip, but not AD485x.
>
>> + else
>> + return -EINVAL;
>> +
>> + return regmap_update_bits(st->regmap, ADI_AXI_ADC_REG_CNTRL_3,
>> + ADI_AXI_ADC_CNTRL_3_CUSTOM_CONTROL_MSK, val);
>

Answering my own question:

I did some digging in the HDL source code and found that there
are actually multiple field here.

So instead of ADI_AXI_ADC_CNTRL_3_CUSTOM_CTRL_MSK, we should have

#define AD485X_CNTRL_3_CUSTOM_CTRL_OVERSAMPLING_EN BIT(2)
#define AD485X_CNTRL_3_CUSTOM_CTRL_PACKET_FORMAT GENMASK(1, 0)

And the meaning of PACKET_FORMAT is different for 16-bit vs.
20-bit chips and in some cases if oversampling is enabled or not.

For 16-bit chips:
0 = 16-bit data and no status bits
1 = 16-bit data and 8 status bits

For 20-bit chips:
0 = 20-bit data and no status bits
1 = 20-bit data and 4 status bits OR
24-bit data and no status bits (oversampling)
2 = 20-bit data and 8 status bits and 4 bit padding OR
24-bit data and 8 status bits (oversampling)
3 = Same as 2

So this tells me that A) we probably need a separate oversampling
enable callback and B) we should be more clear about what "data
size" means. Do we mean just the sample data size (realbits) or
do we mean the sample data plus status bit (realbits + shift).

The implementation is fine for now (other than we should remove the
val = 3 case). But if we need to enable status bit in the future,
it won't be compatible with this function.

> My understanding is that the use of REG_CHAN_CNTRL_3 is different
> for every HDL project depending on what (frontend) chip is is being
> used with. In the AXI DAC, we added a new compatible string for this
> (and other reasons). Not sure if we need to go that far here, but I
> would at least put a comment here explaining that this use of the
> register is highly specific to the AXI AD485x variant [1] of the
> AXI ADC IP core.
>
> Ideally though, there should be an ID register that we can read
> to get this info or use a different DT compatible string.
>
> [1]: http://analogdevicesinc.github.io/hdl/library/axi_ad485x/index.html
>
>> +}
>> +
>> static struct iio_buffer *axi_adc_request_buffer(struct iio_backend *back,
>> struct iio_dev *indio_dev)
>> {
>> @@ -360,6 +381,7 @@ static const struct iio_backend_ops adi_axi_adc_ops = {
>> .test_pattern_set = axi_adc_test_pattern_set,
>> .chan_status = axi_adc_chan_status,
>> .interface_type_get = axi_adc_interface_type_get,
>> + .data_size_set = axi_adc_data_size_set,
>> .debugfs_reg_access = iio_backend_debugfs_ptr(axi_adc_reg_access),
>> .debugfs_print_chan_status = iio_backend_debugfs_ptr(axi_adc_debugfs_print_chan_status),
>> };
>