Re: [PATCH v2 04/10] iio: adc: at91-sama5d2_adc: convert to platform specific data structures

Eugen.Hristev
2021-08-31T11:53:03Z

On 8/30/21 5:44 PM, Jonathan Cameron wrote:
> On Mon, 30 Aug 2021 12:31:46 +0000
> <Eugen.Hristev@microchip.com> wrote:
>
>> On 8/24/21 2:54 PM, Eugen Hristev wrote:
>>> Convert the driver to platform specific structures. This means:
>>> - create a register layout struct that will hold offsets for registers
>>> - create a platform struct that will hold platform information (number of
>>> channels, indexes for different channels and pointer to layout struct)
>>> - convert specific macros that are platform dependent into platform variables
>>>
>>> This step is in fact a no-op, but allows the driver to be more flexible
>>> and for future enhancement including adding new platforms that are partly
>>> compatible with the current driver and differ slightly in register layout
>>> or capabilities for example.
>>>
>>> Signed-off-by: Eugen Hristev <eugen.hristev@microchip.com>
>>> ---
>>> drivers/iio/adc/at91-sama5d2_adc.c | 410 +++++++++++++++++------------
>>> 1 file changed, 247 insertions(+), 163 deletions(-)
>>>
>>> diff --git a/drivers/iio/adc/at91-sama5d2_adc.c b/drivers/iio/adc/at91-sama5d2_adc.c
>>> index 9d71dcffcf93..8ede18b8d789 100644
>>> --- a/drivers/iio/adc/at91-sama5d2_adc.c
>>> +++ b/drivers/iio/adc/at91-sama5d2_adc.c
>>> @@ -27,8 +27,9 @@
>>> #include <linux/pinctrl/consumer.h>
>>> #include <linux/regulator/consumer.h>
>>>
>>> +struct at91_adc_reg_layout {
>>> /* Control Register */
>>> -#define AT91_SAMA5D2_CR 0x00
>>> + u16 CR;
>>> /* Software Reset */
>>> #define AT91_SAMA5D2_CR_SWRST BIT(0)
>>> /* Start Conversion */
>>> @@ -39,7 +40,7 @@
>>> #define AT91_SAMA5D2_CR_CMPRST BIT(4)
>>>
>>> /* Mode Register */
>>> -#define AT91_SAMA5D2_MR 0x04
>>> + u16 MR;
>>> /* Trigger Selection */
>>> #define AT91_SAMA5D2_MR_TRGSEL(v) ((v) << 1)
>>> /* ADTRG */
>>> @@ -82,19 +83,19 @@
>>> #define AT91_SAMA5D2_MR_USEQ BIT(31)
>>>
>>> /* Channel Sequence Register 1 */
>>> -#define AT91_SAMA5D2_SEQR1 0x08
>>> + u16 SEQR1;
>>> /* Channel Sequence Register 2 */
>>> -#define AT91_SAMA5D2_SEQR2 0x0c
>>> + u16 SEQR2;
>>> /* Channel Enable Register */
>>> -#define AT91_SAMA5D2_CHER 0x10
>>> + u16 CHER;
>>> /* Channel Disable Register */
>>> -#define AT91_SAMA5D2_CHDR 0x14
>>> + u16 CHDR;
>>> /* Channel Status Register */
>>> -#define AT91_SAMA5D2_CHSR 0x18
>>> + u16 CHSR;
>>> /* Last Converted Data Register */
>>> -#define AT91_SAMA5D2_LCDR 0x20
>>> + u16 LCDR;
>>> /* Interrupt Enable Register */
>>> -#define AT91_SAMA5D2_IER 0x24
>>> + u16 IER;
>>> /* Interrupt Enable Register - TS X measurement ready */
>>> #define AT91_SAMA5D2_IER_XRDY BIT(20)
>>> /* Interrupt Enable Register - TS Y measurement ready */
>>> @@ -109,22 +110,23 @@
>>> #define AT91_SAMA5D2_IER_PEN BIT(29)
>>> /* Interrupt Enable Register - No pen detect */
>>> #define AT91_SAMA5D2_IER_NOPEN BIT(30)
>>> +
>>> /* Interrupt Disable Register */
>>> -#define AT91_SAMA5D2_IDR 0x28
>>> + u16 IDR;
>>> /* Interrupt Mask Register */
>>> -#define AT91_SAMA5D2_IMR 0x2c
>>> + u16 IMR;
>>> /* Interrupt Status Register */
>>> -#define AT91_SAMA5D2_ISR 0x30
>>> + u16 ISR;
>>> /* Interrupt Status Register - Pen touching sense status */
>>> #define AT91_SAMA5D2_ISR_PENS BIT(31)
>>> /* Last Channel Trigger Mode Register */
>>> -#define AT91_SAMA5D2_LCTMR 0x34
>>> + u16 LCTMR;
>>> /* Last Channel Compare Window Register */
>>> -#define AT91_SAMA5D2_LCCWR 0x38
>>> + u16 LCCWR;
>>> /* Overrun Status Register */
>>> -#define AT91_SAMA5D2_OVER 0x3c
>>> + u16 OVER;
>>> /* Extended Mode Register */
>>> -#define AT91_SAMA5D2_EMR 0x40
>>> + u16 EMR;
>>> /* Extended Mode Register - Oversampling rate */
>>> #define AT91_SAMA5D2_EMR_OSR(V) ((V) << 16)
>>> #define AT91_SAMA5D2_EMR_OSR_MASK GENMASK(17, 16)
>>> @@ -134,22 +136,22 @@
>>>
>>> /* Extended Mode Register - Averaging on single trigger event */
>>> #define AT91_SAMA5D2_EMR_ASTE(V) ((V) << 20)
>>> +
>>> /* Compare Window Register */
>>> -#define AT91_SAMA5D2_CWR 0x44
>>> + u16 CWR;
>>> /* Channel Gain Register */
>>> -#define AT91_SAMA5D2_CGR 0x48
>>> -
>>> + u16 CGR;
>>> /* Channel Offset Register */
>>> -#define AT91_SAMA5D2_COR 0x4c
>>> + u16 COR;
>>> #define AT91_SAMA5D2_COR_DIFF_OFFSET 16
>>>
>>> /* Analog Control Register */
>>> -#define AT91_SAMA5D2_ACR 0x94
>>> + u16 ACR;
>>> /* Analog Control Register - Pen detect sensitivity mask */
>>> #define AT91_SAMA5D2_ACR_PENDETSENS_MASK GENMASK(1, 0)
>>>
>>> /* Touchscreen Mode Register */
>>> -#define AT91_SAMA5D2_TSMR 0xb0
>>> + u16 TSMR;
>>> /* Touchscreen Mode Register - No touch mode */
>>> #define AT91_SAMA5D2_TSMR_TSMODE_NONE 0
>>> /* Touchscreen Mode Register - 4 wire screen, no pressure measurement */
>>> @@ -178,13 +180,13 @@
>>> #define AT91_SAMA5D2_TSMR_PENDET_ENA BIT(24)
>>>
>>> /* Touchscreen X Position Register */
>>> -#define AT91_SAMA5D2_XPOSR 0xb4
>>> + u16 XPOSR;
>>> /* Touchscreen Y Position Register */
>>> -#define AT91_SAMA5D2_YPOSR 0xb8
>>> + u16 YPOSR;
>>> /* Touchscreen Pressure Register */
>>> -#define AT91_SAMA5D2_PRESSR 0xbc
>>> + u16 PRESSR;
>>> /* Trigger Register */
>>> -#define AT91_SAMA5D2_TRGR 0xc0
>>> + u16 TRGR;
>>> /* Mask for TRGMOD field of TRGR register */
>>> #define AT91_SAMA5D2_TRGR_TRGMOD_MASK GENMASK(2, 0)
>>> /* No trigger, only software trigger can start conversions */
>>> @@ -203,30 +205,52 @@
>>> #define AT91_SAMA5D2_TRGR_TRGPER(x) ((x) << 16)
>>>
>>> /* Correction Select Register */
>>> -#define AT91_SAMA5D2_COSR 0xd0
>>> + u16 COSR;
>>> /* Correction Value Register */
>>> -#define AT91_SAMA5D2_CVR 0xd4
>>> + u16 CVR;
>>> /* Channel Error Correction Register */
>>> -#define AT91_SAMA5D2_CECR 0xd8
>>> + u16 CECR;
>>> /* Write Protection Mode Register */
>>> -#define AT91_SAMA5D2_WPMR 0xe4
>>> + u16 WPMR;
>>> /* Write Protection Status Register */
>>> -#define AT91_SAMA5D2_WPSR 0xe8
>>> + u16 WPSR;
>>> /* Version Register */
>>> -#define AT91_SAMA5D2_VERSION 0xfc
>>> -
>>> -#define AT91_SAMA5D2_HW_TRIG_CNT 3
>>> -#define AT91_SAMA5D2_SINGLE_CHAN_CNT 12
>>> -#define AT91_SAMA5D2_DIFF_CHAN_CNT 6
>>> -
>>> -#define AT91_SAMA5D2_TIMESTAMP_CHAN_IDX (AT91_SAMA5D2_SINGLE_CHAN_CNT + \
>>> - AT91_SAMA5D2_DIFF_CHAN_CNT + 1)
>>> + u16 VERSION;
>>> +};
>>>
>>> -#define AT91_SAMA5D2_TOUCH_X_CHAN_IDX (AT91_SAMA5D2_SINGLE_CHAN_CNT + \
>>> - AT91_SAMA5D2_DIFF_CHAN_CNT * 2)
>>
>> Hi Jonathan,
>>
>> While we are here, regarding the above line, I cannot tell why did I
>> multiply by two the differential channel count. This makes some gaps in
>> the number of channels when we put them all in the same table.
>>
>> I did not change this as it would break the ABI regarding the bindings
>> for the touchscreen #adc-cells phandle references.
>
> Really? Xlate is based off scan_index, not these values I think...

I figured it out.

We have 12 single channels [0..11] then 6 differential [12, 14, 16, 18,
20, 22] spaced by two, a timestamp [23], then we have the X channel
index at 24, Y at 25 and pressure are 26.

These are reflected in this file :

https://elixir.bootlin.com/linux/latest/source/include/dt-bindings/iio/adc/at91-sama5d2_adc.h

And the resistive touchscreen connects to the adc with these indexes.

And I realised why we have the padding/spaces.
It was the original design of the driver, in the line which I
highlighted now below in the patch : (and I never changed this since
working on this driver, because it was a break of the ABI in channel
numbers ...)

>
>>
>> However, I am thinking if there was a reason for it or it was a slip
>> when I initially wrote this.
>
> I've no idea :) I can't immediately see why we'd need the padding.
>
>>
>> Do you think there is any reason to change it and tighten the holes in
>> the indexes list ?
>
> I don't think it matters. As far as I can tell they are used mostly (possibly
> entirely) for internal management and not exposed to any of the ABIs etc.
>
> Jonathan
>
>>
>>
>> Eugen
>>
>>> -#define AT91_SAMA5D2_TOUCH_Y_CHAN_IDX (AT91_SAMA5D2_TOUCH_X_CHAN_IDX + 1)
>>> -#define AT91_SAMA5D2_TOUCH_P_CHAN_IDX (AT91_SAMA5D2_TOUCH_Y_CHAN_IDX + 1)
>>> -#define AT91_SAMA5D2_MAX_CHAN_IDX AT91_SAMA5D2_TOUCH_P_CHAN_IDX
>>> +static const struct at91_adc_reg_layout sama5d2_layout = {
>>> + .CR = 0x00,
>>> + .MR = 0x04,
>>> + .SEQR1 = 0x08,
>>> + .SEQR2 = 0x0c,
>>> + .CHER = 0x10,
>>> + .CHDR = 0x14,
>>> + .CHSR = 0x18,
>>> + .LCDR = 0x20,
>>> + .IER = 0x24,
>>> + .IDR = 0x28,
>>> + .IMR = 0x2c,
>>> + .ISR = 0x30,
>>> + .LCTMR = 0x34,
>>> + .LCCWR = 0x38,
>>> + .OVER = 0x3c,
>>> + .EMR = 0x40,
>>> + .CWR = 0x44,
>>> + .CGR = 0x48,
>>> + .COR = 0x4c,
>>> + .ACR = 0x94,
>>> + .TSMR = 0xb0,
>>> + .XPOSR = 0xb4,
>>> + .YPOSR = 0xb8,
>>> + .PRESSR = 0xbc,
>>> + .TRGR = 0xc0,
>>> + .COSR = 0xd0,
>>> + .CVR = 0xd4,
>>> + .CECR = 0xd8,
>>> + .WPMR = 0xe4,
>>> + .WPSR = 0xe8,
>>> + .VERSION = 0xfc,
>>> +};
>>>
>>> #define AT91_SAMA5D2_TOUCH_SAMPLE_PERIOD_US 2000 /* 2ms */
>>> #define AT91_SAMA5D2_TOUCH_PEN_DETECT_DEBOUNCE_US 200
>>> @@ -235,18 +259,6 @@
>>>
>>> #define AT91_SAMA5D2_MAX_POS_BITS 12
>>>
>>> -/*
>>> - * Maximum number of bytes to hold conversion from all channels
>>> - * without the timestamp.
>>> - */
>>> -#define AT91_BUFFER_MAX_CONVERSION_BYTES ((AT91_SAMA5D2_SINGLE_CHAN_CNT + \
>>> - AT91_SAMA5D2_DIFF_CHAN_CNT) * 2)
>>> -
>>> -/* This total must also include the timestamp */
>>> -#define AT91_BUFFER_MAX_BYTES (AT91_BUFFER_MAX_CONVERSION_BYTES + 8)
>>> -
>>> -#define AT91_BUFFER_MAX_HWORDS (AT91_BUFFER_MAX_BYTES / 2)
>>> -
>>> #define AT91_HWFIFO_MAX_SIZE_STR "128"
>>> #define AT91_HWFIFO_MAX_SIZE 128
>>>
>>> @@ -255,12 +267,12 @@
>>> #define AT91_OSR_4SAMPLES 4
>>> #define AT91_OSR_16SAMPLES 16
>>>
>>> -#define AT91_SAMA5D2_CHAN_SINGLE(num, addr) \
>>> +#define AT91_SAMA5D2_CHAN_SINGLE(index, num, addr) \
>>> { \
>>> .type = IIO_VOLTAGE, \
>>> .channel = num, \
>>> .address = addr, \
>>> - .scan_index = num, \
>>> + .scan_index = index, \
>>> .scan_type = { \
>>> .sign = 'u', \
>>> .realbits = 14, \
>>> @@ -274,14 +286,14 @@
>>> .indexed = 1, \
>>> }
>>>
>>> -#define AT91_SAMA5D2_CHAN_DIFF(num, num2, addr) \
>>> +#define AT91_SAMA5D2_CHAN_DIFF(index, num, num2, addr) \
>>> { \
>>> .type = IIO_VOLTAGE, \
>>> .differential = 1, \
>>> .channel = num, \
>>> .channel2 = num2, \
>>> .address = addr, \
>>> - .scan_index = num + AT91_SAMA5D2_SINGLE_CHAN_CNT, \

Here it is: we always added num to the single channel count, but num
goes incrementally in steps of two : 0, 2, 4, 6, 8, 10

>>> + .scan_index = index, \
>>> .scan_type = { \
>>> .sign = 's', \
>>> .realbits = 14, \
>>> @@ -328,13 +340,48 @@
>>> .datasheet_name = name, \
>>> }
>>>
>>> -#define at91_adc_readl(st, reg) readl_relaxed(st->base + reg)
>>> -#define at91_adc_writel(st, reg, val) writel_relaxed(val, st->base + reg)
>>> +#define at91_adc_readl(st, reg) \
>>> + readl_relaxed((st)->base + (st)->soc_info.platform->layout->reg)
>>> +#define at91_adc_read_chan(st, reg) \
>>> + readl_relaxed((st)->base + reg)
>>> +#define at91_adc_writel(st, reg, val) \
>>> + writel_relaxed(val, (st)->base + (st)->soc_info.platform->layout->reg)
>>> +
>>> +/**
>>> + * struct at91_adc_platform - at91-sama5d2 platform information struct
>>> + * @layout: pointer to the reg layout struct
>>> + * @adc_channels: pointer to an array of channels for registering in
>>> + * the iio subsystem
>>> + * @nr_channels: number of physical channels available
>>> + * @touch_chan_x: index of the touchscreen X channel
>>> + * @touch_chan_y: index of the touchscreen Y channel
>>> + * @touch_chan_p: index of the touchscreen P channel
>>> + * @max_channels: number of total channels
>>> + * @hw_trig_cnt: number of possible hardware triggers
>>> + */
>>> +struct at91_adc_platform {
>>> + const struct at91_adc_reg_layout *layout;
>>> + const struct iio_chan_spec (*adc_channels)[];
>>> + unsigned int nr_channels;
>>> + unsigned int touch_chan_x;
>>> + unsigned int touch_chan_y;
>>> + unsigned int touch_chan_p;
>>> + unsigned int max_channels;
>>> + unsigned int hw_trig_cnt;
>>> +};
>>>
>>> +/**
>>> + * struct at91_adc_soc_info - at91-sama5d2 soc information struct
>>> + * @startup_time: device startup time
>>> + * @min_sample_rate: minimum sample rate in Hz
>>> + * @max_sample_rate: maximum sample rate in Hz
>>> + * @platform: pointer to the platform structure
>>> + */
>>> struct at91_adc_soc_info {
>>> unsigned startup_time;
>>> unsigned min_sample_rate;
>>> unsigned max_sample_rate;
>>> + const struct at91_adc_platform *platform;
>>> };
>>>
>>> struct at91_adc_trigger {
>>> @@ -382,6 +429,15 @@ struct at91_adc_touch {
>>> struct work_struct workq;
>>> };
>>>
>>> +/*
>>> + * Buffer size requirements:
>>> + * No channels * bytes_per_channel(2) + timestamp bytes (8)
>>> + * Divided by 2 because we need half words.
>>> + * We assume 32 channels for now, has to be increased if needed.
>>> + * Nobody minds a buffer being too big.
>>> + */
>>> +#define AT91_BUFFER_MAX_HWORDS ((32 * 2 + 8) / 2)
>>> +
>>> struct at91_adc_state {
>>> void __iomem *base;
>>> int irq;
>>> @@ -437,29 +493,49 @@ static const struct at91_adc_trigger at91_adc_trigger_list[] = {
>>> },
>>> };
>>>
>>> -static const struct iio_chan_spec at91_adc_channels[] = {
>>> - AT91_SAMA5D2_CHAN_SINGLE(0, 0x50),
>>> - AT91_SAMA5D2_CHAN_SINGLE(1, 0x54),
>>> - AT91_SAMA5D2_CHAN_SINGLE(2, 0x58),
>>> - AT91_SAMA5D2_CHAN_SINGLE(3, 0x5c),
>>> - AT91_SAMA5D2_CHAN_SINGLE(4, 0x60),
>>> - AT91_SAMA5D2_CHAN_SINGLE(5, 0x64),
>>> - AT91_SAMA5D2_CHAN_SINGLE(6, 0x68),
>>> - AT91_SAMA5D2_CHAN_SINGLE(7, 0x6c),
>>> - AT91_SAMA5D2_CHAN_SINGLE(8, 0x70),
>>> - AT91_SAMA5D2_CHAN_SINGLE(9, 0x74),
>>> - AT91_SAMA5D2_CHAN_SINGLE(10, 0x78),
>>> - AT91_SAMA5D2_CHAN_SINGLE(11, 0x7c),
>>> - AT91_SAMA5D2_CHAN_DIFF(0, 1, 0x50),
>>> - AT91_SAMA5D2_CHAN_DIFF(2, 3, 0x58),
>>> - AT91_SAMA5D2_CHAN_DIFF(4, 5, 0x60),
>>> - AT91_SAMA5D2_CHAN_DIFF(6, 7, 0x68),
>>> - AT91_SAMA5D2_CHAN_DIFF(8, 9, 0x70),
>>> - AT91_SAMA5D2_CHAN_DIFF(10, 11, 0x78),

you can see it here,

>>> - IIO_CHAN_SOFT_TIMESTAMP(AT91_SAMA5D2_TIMESTAMP_CHAN_IDX),
>>> - AT91_SAMA5D2_CHAN_TOUCH(AT91_SAMA5D2_TOUCH_X_CHAN_IDX, "x", IIO_MOD_X),
>>> - AT91_SAMA5D2_CHAN_TOUCH(AT91_SAMA5D2_TOUCH_Y_CHAN_IDX, "y", IIO_MOD_Y),
>>> - AT91_SAMA5D2_CHAN_PRESSURE(AT91_SAMA5D2_TOUCH_P_CHAN_IDX, "pressure"),
>>> +static const struct iio_chan_spec at91_sama5d2_adc_channels[] = {
>>> + AT91_SAMA5D2_CHAN_SINGLE(0, 0, 0x50),
>>> + AT91_SAMA5D2_CHAN_SINGLE(1, 1, 0x54),
>>> + AT91_SAMA5D2_CHAN_SINGLE(2, 2, 0x58),
>>> + AT91_SAMA5D2_CHAN_SINGLE(3, 3, 0x5c),
>>> + AT91_SAMA5D2_CHAN_SINGLE(4, 4, 0x60),
>>> + AT91_SAMA5D2_CHAN_SINGLE(5, 5, 0x64),
>>> + AT91_SAMA5D2_CHAN_SINGLE(6, 6, 0x68),
>>> + AT91_SAMA5D2_CHAN_SINGLE(7, 7, 0x6c),
>>> + AT91_SAMA5D2_CHAN_SINGLE(8, 8, 0x70),
>>> + AT91_SAMA5D2_CHAN_SINGLE(9, 9, 0x74),
>>> + AT91_SAMA5D2_CHAN_SINGLE(10, 10, 0x78),
>>> + AT91_SAMA5D2_CHAN_SINGLE(11, 11, 0x7c),
>>> + AT91_SAMA5D2_CHAN_DIFF(12, 0, 1, 0x50),
>>> + AT91_SAMA5D2_CHAN_DIFF(13, 2, 3, 0x58),
>>> + AT91_SAMA5D2_CHAN_DIFF(14, 4, 5, 0x60),
>>> + AT91_SAMA5D2_CHAN_DIFF(15, 6, 7, 0x68),
>>> + AT91_SAMA5D2_CHAN_DIFF(16, 8, 9, 0x70),
>>> + AT91_SAMA5D2_CHAN_DIFF(17, 10, 11, 0x78),
>>> + IIO_CHAN_SOFT_TIMESTAMP(18),
>>> + AT91_SAMA5D2_CHAN_TOUCH(19, "x", IIO_MOD_X),
>>> + AT91_SAMA5D2_CHAN_TOUCH(20, "y", IIO_MOD_Y),
>>> + AT91_SAMA5D2_CHAN_PRESSURE(21, "pressure"),

And I have to come up with a new version of the patch to fix this.

It should be like this:

>>> + AT91_SAMA5D2_CHAN_SINGLE(11, 11, 0x7c),
>>> + AT91_SAMA5D2_CHAN_DIFF(12, 0, 1, 0x50),
>>> + AT91_SAMA5D2_CHAN_DIFF(14, 2, 3, 0x58),
>>> + AT91_SAMA5D2_CHAN_DIFF(16, 4, 5, 0x60),
>>> + AT91_SAMA5D2_CHAN_DIFF(18, 6, 7, 0x68),
>>> + AT91_SAMA5D2_CHAN_DIFF(20, 8, 9, 0x70),
>>> + AT91_SAMA5D2_CHAN_DIFF(22, 10, 11, 0x78),
>>> + IIO_CHAN_SOFT_TIMESTAMP(23),
>>> + AT91_SAMA5D2_CHAN_TOUCH(24, "x", IIO_MOD_X),
>>> + AT91_SAMA5D2_CHAN_TOUCH(25, "y", IIO_MOD_Y),
>>> + AT91_SAMA5D2_CHAN_PRESSURE(26, "pressure"),

Sorry about this. Do you want me to resend the whole series together
with the fixes found by robots ?

I can redo the series, retest it, and send it tomorrow as a v3.

Thanks,
Eugen

>>> +};
>>> +
[snip]