2022-08-03 10:32:37

by Claudiu Beznea

[permalink] [raw]
Subject: [PATCH v3 00/19] iio: adc: at91-sama5d2_adc: add support for temperature sensor

Hi,

The following series add support for temperature sensor available on
SAMA7G5.

Temperature sensor available on SAMA7G5 provides 2 outputs VTEMP and VBG.
VTEMP is proportional to the absolute temperature voltage and VBG is a
quasi-temperature independent voltage. Both are necessary in computing
the temperature (for better accuracy). Also, for better accuracy the
following settings were imposed when measusing the temperature:
oversampling rate of 256, sampling frequency of 10MHz, a startup time of
512 ticks, MR.tracktim=0xf, EMR.trackx=0x3.

For computing the temperature measured by ADC calibration data is
necessary. This is provided via OTP memory available on SAMA7G5.

Patches 1/19-4/19 provides some fixes.
Patches 5/19-16/19 prepares for the addition of temperature sensor
support.
Patch 17/16 adds the temperature sensor support.

Along with temperature sensor support I took the chance and added
runtime PM support in this series, too (handled in patch 19/19).

The rest of patches in this series are minor cleanups.

Thank you,
Claudiu Beznea

Changes in v3:
- fixed compilation warning by adjusting patches 10/19, 11/19

Changes in v2:
- addressed review comments
- with this, new patches were intruced in this series: 2/19, 4/19,
8/19, 9,19
- runtime pm support has been adapted to work also when CONFIG_PM
is not enabled
- collected tags

Claudiu Beznea (19):
iio: adc: at91-sama5d2_adc: fix AT91_SAMA5D2_MR_TRACKTIM_MAX
iio: adc: at91-sama5d2_adc: check return status for pressure and touch
iio: adc: at91-sama5d2_adc: lock around oversampling and sample freq
iio: adc: at91-sama5d2_adc: disable/prepare buffer on suspend/resume
iio: adc: at91-sama5d2_adc: exit from write_raw() when buffers are
enabled
iio: adc: at91-sama5d2_adc: handle different EMR.OSR for different hw
versions
iio: adc: at91-sama5d2_adc: move the check of oversampling in its
function
iio: adc: at91-sama5d2_adc: drop AT91_OSR_XSAMPLES defines
iio: adc: at91-sama5d2_adc: add .read_avail() chan_info ops
iio: adc: at91-sama5d2_adc: adjust osr based on specific platform data
iio: adc: at91-sama5d2_adc: add 64 and 256 oversampling ratio
iio: adc: at91-sama5d2_adc: move oversampling storage in its function
iio: adc: at91-sama5d2_adc: update trackx on emr
iio: adc: at91-sama5d2_adc: add startup and tracktim as parameter for
at91_adc_setup_samp_freq()
iio: adc: at91-sama5d2_adc: lock around at91_adc_read_info_raw()
dt-bindings: iio: adc: at91-sama5d2_adc: add id for temperature
channel
iio: adc: at91-sama5d2_adc: add support for temperature sensor
iio: adc: at91-sama5d2_adc: add empty line after functions
iio: adc: at91-sama5d2_adc: add runtime pm support

drivers/iio/adc/at91-sama5d2_adc.c | 684 +++++++++++++++---
.../dt-bindings/iio/adc/at91-sama5d2_adc.h | 3 +
2 files changed, 568 insertions(+), 119 deletions(-)

--
2.34.1



2022-08-03 10:32:46

by Claudiu Beznea

[permalink] [raw]
Subject: [PATCH v3 06/19] iio: adc: at91-sama5d2_adc: handle different EMR.OSR for different hw versions

SAMA7G5 introduces 64 and 256 oversampling rates. Due to this EMR.OSR is 3
bits long. Change the code to reflect this. Commit prepares the code
for the addition of 64 and 256 oversampling rates.

Signed-off-by: Claudiu Beznea <[email protected]>
---
drivers/iio/adc/at91-sama5d2_adc.c | 31 +++++++++++++++++-------------
1 file changed, 18 insertions(+), 13 deletions(-)

diff --git a/drivers/iio/adc/at91-sama5d2_adc.c b/drivers/iio/adc/at91-sama5d2_adc.c
index 64943d8ea869..0283c8cc3168 100644
--- a/drivers/iio/adc/at91-sama5d2_adc.c
+++ b/drivers/iio/adc/at91-sama5d2_adc.c
@@ -138,8 +138,7 @@ struct at91_adc_reg_layout {
/* Extended Mode Register */
u16 EMR;
/* Extended Mode Register - Oversampling rate */
-#define AT91_SAMA5D2_EMR_OSR(V) ((V) << 16)
-#define AT91_SAMA5D2_EMR_OSR_MASK GENMASK(17, 16)
+#define AT91_SAMA5D2_EMR_OSR(V, M) (((V) << 16) & (M))
#define AT91_SAMA5D2_EMR_OSR_1SAMPLES 0
#define AT91_SAMA5D2_EMR_OSR_4SAMPLES 1
#define AT91_SAMA5D2_EMR_OSR_16SAMPLES 2
@@ -403,6 +402,7 @@ static const struct at91_adc_reg_layout sama7g5_layout = {
* @max_index: highest channel index (highest index may be higher
* than the total channel number)
* @hw_trig_cnt: number of possible hardware triggers
+ * @osr_mask: oversampling ratio bitmask on EMR register
*/
struct at91_adc_platform {
const struct at91_adc_reg_layout *layout;
@@ -414,6 +414,7 @@ struct at91_adc_platform {
unsigned int max_channels;
unsigned int max_index;
unsigned int hw_trig_cnt;
+ unsigned int osr_mask;
};

/**
@@ -612,6 +613,7 @@ static const struct at91_adc_platform sama5d2_platform = {
.max_index = AT91_SAMA5D2_MAX_CHAN_IDX,
#define AT91_SAMA5D2_HW_TRIG_CNT 3
.hw_trig_cnt = AT91_SAMA5D2_HW_TRIG_CNT,
+ .osr_mask = GENMASK(17, 16),
};

static const struct at91_adc_platform sama7g5_platform = {
@@ -627,6 +629,7 @@ static const struct at91_adc_platform sama7g5_platform = {
.max_index = AT91_SAMA7G5_MAX_CHAN_IDX,
#define AT91_SAMA7G5_HW_TRIG_CNT 3
.hw_trig_cnt = AT91_SAMA7G5_HW_TRIG_CNT,
+ .osr_mask = GENMASK(18, 16),
};

static int at91_adc_chan_xlate(struct iio_dev *indio_dev, int chan)
@@ -725,30 +728,32 @@ static void at91_adc_eoc_ena(struct at91_adc_state *st, unsigned int channel)
at91_adc_writel(st, EOC_IER, BIT(channel));
}

-static void at91_adc_config_emr(struct at91_adc_state *st)
+static void at91_adc_config_emr(struct at91_adc_state *st,
+ u32 oversampling_ratio)
{
/* configure the extended mode register */
unsigned int emr = at91_adc_readl(st, EMR);
+ unsigned int osr_mask = st->soc_info.platform->osr_mask;

/* select oversampling per single trigger event */
emr |= AT91_SAMA5D2_EMR_ASTE(1);

/* delete leftover content if it's the case */
- emr &= ~AT91_SAMA5D2_EMR_OSR_MASK;
+ emr &= ~osr_mask;

/* select oversampling ratio from configuration */
- switch (st->oversampling_ratio) {
+ switch (oversampling_ratio) {
case AT91_OSR_1SAMPLES:
- emr |= AT91_SAMA5D2_EMR_OSR(AT91_SAMA5D2_EMR_OSR_1SAMPLES) &
- AT91_SAMA5D2_EMR_OSR_MASK;
+ emr |= AT91_SAMA5D2_EMR_OSR(AT91_SAMA5D2_EMR_OSR_1SAMPLES,
+ osr_mask);
break;
case AT91_OSR_4SAMPLES:
- emr |= AT91_SAMA5D2_EMR_OSR(AT91_SAMA5D2_EMR_OSR_4SAMPLES) &
- AT91_SAMA5D2_EMR_OSR_MASK;
+ emr |= AT91_SAMA5D2_EMR_OSR(AT91_SAMA5D2_EMR_OSR_4SAMPLES,
+ osr_mask);
break;
case AT91_OSR_16SAMPLES:
- emr |= AT91_SAMA5D2_EMR_OSR(AT91_SAMA5D2_EMR_OSR_16SAMPLES) &
- AT91_SAMA5D2_EMR_OSR_MASK;
+ emr |= AT91_SAMA5D2_EMR_OSR(AT91_SAMA5D2_EMR_OSR_16SAMPLES,
+ osr_mask);
break;
}

@@ -1658,7 +1663,7 @@ static int at91_adc_write_raw(struct iio_dev *indio_dev,
mutex_lock(&st->lock);
st->oversampling_ratio = val;
/* update ratio */
- at91_adc_config_emr(st);
+ at91_adc_config_emr(st, val);
mutex_unlock(&st->lock);
iio_device_release_direct_mode(indio_dev);
return 0;
@@ -1838,7 +1843,7 @@ static void at91_adc_hw_init(struct iio_dev *indio_dev)
at91_adc_setup_samp_freq(indio_dev, st->soc_info.min_sample_rate);

/* configure extended mode register */
- at91_adc_config_emr(st);
+ at91_adc_config_emr(st, st->oversampling_ratio);
}

static ssize_t at91_adc_get_fifo_state(struct device *dev,
--
2.34.1


2022-08-03 10:32:57

by Claudiu Beznea

[permalink] [raw]
Subject: [PATCH v3 08/19] iio: adc: at91-sama5d2_adc: drop AT91_OSR_XSAMPLES defines

Drop AT91_OSR_1SAMPLES, AT91_OSR_4SAMPLES, AT91_OSR_16SAMPLES defines
and insted use their values inline.

Suggested-by: Jonathan Cameron <[email protected]>
Signed-off-by: Claudiu Beznea <[email protected]>
---
drivers/iio/adc/at91-sama5d2_adc.c | 23 +++++++++--------------
1 file changed, 9 insertions(+), 14 deletions(-)

diff --git a/drivers/iio/adc/at91-sama5d2_adc.c b/drivers/iio/adc/at91-sama5d2_adc.c
index ace4cc431a95..fe4bec03bea9 100644
--- a/drivers/iio/adc/at91-sama5d2_adc.c
+++ b/drivers/iio/adc/at91-sama5d2_adc.c
@@ -304,11 +304,6 @@ static const struct at91_adc_reg_layout sama7g5_layout = {
#define AT91_HWFIFO_MAX_SIZE_STR "128"
#define AT91_HWFIFO_MAX_SIZE 128

-/* Possible values for oversampling ratio */
-#define AT91_OSR_1SAMPLES 1
-#define AT91_OSR_4SAMPLES 4
-#define AT91_OSR_16SAMPLES 16
-
#define AT91_SAMA5D2_CHAN_SINGLE(index, num, addr) \
{ \
.type = IIO_VOLTAGE, \
@@ -743,15 +738,15 @@ static int at91_adc_config_emr(struct at91_adc_state *st,

/* select oversampling ratio from configuration */
switch (oversampling_ratio) {
- case AT91_OSR_1SAMPLES:
+ case 1:
emr |= AT91_SAMA5D2_EMR_OSR(AT91_SAMA5D2_EMR_OSR_1SAMPLES,
osr_mask);
break;
- case AT91_OSR_4SAMPLES:
+ case 4:
emr |= AT91_SAMA5D2_EMR_OSR(AT91_SAMA5D2_EMR_OSR_4SAMPLES,
osr_mask);
break;
- case AT91_OSR_16SAMPLES:
+ case 16:
emr |= AT91_SAMA5D2_EMR_OSR(AT91_SAMA5D2_EMR_OSR_16SAMPLES,
osr_mask);
break;
@@ -766,13 +761,13 @@ static int at91_adc_config_emr(struct at91_adc_state *st,

static int at91_adc_adjust_val_osr(struct at91_adc_state *st, int *val)
{
- if (st->oversampling_ratio == AT91_OSR_1SAMPLES) {
+ if (st->oversampling_ratio == 1) {
/*
* in this case we only have 12 bits of real data, but channel
* is registered as 14 bits, so shift left two bits
*/
*val <<= 2;
- } else if (st->oversampling_ratio == AT91_OSR_4SAMPLES) {
+ } else if (st->oversampling_ratio == 4) {
/*
* in this case we have 13 bits of real data, but channel
* is registered as 14 bits, so left shift one bit
@@ -1875,9 +1870,9 @@ static IIO_CONST_ATTR(hwfifo_watermark_min, "2");
static IIO_CONST_ATTR(hwfifo_watermark_max, AT91_HWFIFO_MAX_SIZE_STR);

static IIO_CONST_ATTR(oversampling_ratio_available,
- __stringify(AT91_OSR_1SAMPLES) " "
- __stringify(AT91_OSR_4SAMPLES) " "
- __stringify(AT91_OSR_16SAMPLES));
+ __stringify(1) " "
+ __stringify(4) " "
+ __stringify(16));

static struct attribute *at91_adc_attributes[] = {
&iio_const_attr_oversampling_ratio_available.dev_attr.attr,
@@ -1973,7 +1968,7 @@ static int at91_adc_probe(struct platform_device *pdev)
bitmap_set(&st->touch_st.channels_bitmask,
st->soc_info.platform->touch_chan_p, 1);

- st->oversampling_ratio = AT91_OSR_1SAMPLES;
+ st->oversampling_ratio = 1;

ret = of_property_read_u32(pdev->dev.of_node,
"atmel,min-sample-rate-hz",
--
2.34.1


2022-08-03 10:33:12

by Claudiu Beznea

[permalink] [raw]
Subject: [PATCH v3 11/19] iio: adc: at91-sama5d2_adc: add 64 and 256 oversampling ratio

Add 64 and 256 oversampling ratio support. It is necessary for temperature
sensor.

Signed-off-by: Claudiu Beznea <[email protected]>
---

Changes in v3:
- adapt to changes on patch 10/19

drivers/iio/adc/at91-sama5d2_adc.c | 31 +++++++++++++++++++++++++-----
1 file changed, 26 insertions(+), 5 deletions(-)

diff --git a/drivers/iio/adc/at91-sama5d2_adc.c b/drivers/iio/adc/at91-sama5d2_adc.c
index db9d77385149..d6a93aa7fbaf 100644
--- a/drivers/iio/adc/at91-sama5d2_adc.c
+++ b/drivers/iio/adc/at91-sama5d2_adc.c
@@ -142,6 +142,8 @@ struct at91_adc_reg_layout {
#define AT91_SAMA5D2_EMR_OSR_1SAMPLES 0
#define AT91_SAMA5D2_EMR_OSR_4SAMPLES 1
#define AT91_SAMA5D2_EMR_OSR_16SAMPLES 2
+#define AT91_SAMA5D2_EMR_OSR_64SAMPLES 3
+#define AT91_SAMA5D2_EMR_OSR_256SAMPLES 4

/* Extended Mode Register - Averaging on single trigger event */
#define AT91_SAMA5D2_EMR_ASTE(V) ((V) << 20)
@@ -421,7 +423,7 @@ struct at91_adc_platform {
unsigned int max_index;
unsigned int hw_trig_cnt;
unsigned int osr_mask;
- unsigned int oversampling_avail[3];
+ unsigned int oversampling_avail[5];
unsigned int oversampling_avail_no;
unsigned int chan_realbits;
};
@@ -642,8 +644,8 @@ static const struct at91_adc_platform sama7g5_platform = {
#define AT91_SAMA7G5_HW_TRIG_CNT 3
.hw_trig_cnt = AT91_SAMA7G5_HW_TRIG_CNT,
.osr_mask = GENMASK(18, 16),
- .oversampling_avail = { 1, 4, 16, },
- .oversampling_avail_no = 3,
+ .oversampling_avail = { 1, 4, 16, 64, 256, },
+ .oversampling_avail_no = 5,
.chan_realbits = 16,
};

@@ -749,6 +751,15 @@ static int at91_adc_config_emr(struct at91_adc_state *st,
/* configure the extended mode register */
unsigned int emr = at91_adc_readl(st, EMR);
unsigned int osr_mask = st->soc_info.platform->osr_mask;
+ int i;
+
+ /* Check against supported oversampling values. */
+ for (i = 0; i < st->soc_info.platform->oversampling_avail_no; i++) {
+ if (oversampling_ratio == st->soc_info.platform->oversampling_avail[i])
+ break;
+ }
+ if (i == st->soc_info.platform->oversampling_avail_no)
+ return -EINVAL;

/* select oversampling per single trigger event */
emr |= AT91_SAMA5D2_EMR_ASTE(1);
@@ -770,8 +781,14 @@ static int at91_adc_config_emr(struct at91_adc_state *st,
emr |= AT91_SAMA5D2_EMR_OSR(AT91_SAMA5D2_EMR_OSR_16SAMPLES,
osr_mask);
break;
- default:
- return -EINVAL;
+ case 64:
+ emr |= AT91_SAMA5D2_EMR_OSR(AT91_SAMA5D2_EMR_OSR_64SAMPLES,
+ osr_mask);
+ break;
+ case 256:
+ emr |= AT91_SAMA5D2_EMR_OSR(AT91_SAMA5D2_EMR_OSR_256SAMPLES,
+ osr_mask);
+ break;
}

at91_adc_writel(st, EMR, emr);
@@ -789,6 +806,10 @@ static int at91_adc_adjust_val_osr(struct at91_adc_state *st, int *val)
nbits = 13;
else if (st->oversampling_ratio == 16)
nbits = 14;
+ else if (st->oversampling_ratio == 64)
+ nbits = 15;
+ else if (st->oversampling_ratio == 256)
+ nbits = 16;
else
/* Should not happen. */
return -EINVAL;
--
2.34.1


2022-08-03 10:33:25

by Claudiu Beznea

[permalink] [raw]
Subject: [PATCH v3 12/19] iio: adc: at91-sama5d2_adc: move oversampling storage in its function

Move the storage of oversampling_ratio in at91_adc_config_emr().
This prepares for the next commits.

Signed-off-by: Claudiu Beznea <[email protected]>
---
drivers/iio/adc/at91-sama5d2_adc.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/iio/adc/at91-sama5d2_adc.c b/drivers/iio/adc/at91-sama5d2_adc.c
index d6a93aa7fbaf..a1df475a6f29 100644
--- a/drivers/iio/adc/at91-sama5d2_adc.c
+++ b/drivers/iio/adc/at91-sama5d2_adc.c
@@ -793,6 +793,8 @@ static int at91_adc_config_emr(struct at91_adc_state *st,

at91_adc_writel(st, EMR, emr);

+ st->oversampling_ratio = oversampling_ratio;
+
return 0;
}

@@ -1705,8 +1707,6 @@ static int at91_adc_write_raw(struct iio_dev *indio_dev,
mutex_lock(&st->lock);
/* update ratio */
ret = at91_adc_config_emr(st, val);
- if (!ret)
- st->oversampling_ratio = val;
mutex_unlock(&st->lock);
iio_device_release_direct_mode(indio_dev);
return ret;
--
2.34.1


2022-08-03 10:44:04

by Claudiu Beznea

[permalink] [raw]
Subject: [PATCH v3 17/19] iio: adc: at91-sama5d2_adc: add support for temperature sensor

The ADC on SAMA7G5 has a dedicated channel (channel 31) for measuring
in-SoC temperature. 2 inputs are multiplexed on channel 31, VTEMP and
VBG as follows:

`
| \ +-----+
VBG --->| | ch31 | |
Vtemp --->| |----->| ADC |
| / | |
| / +-----+
.

where:
- VTEMP is proportional to the absolute temperature voltage
- VBG is a quasi-temperature independent voltage

Both VBG and VTEMP are needed to determine the correct in-SoC
temperature. At a moment of time only one of these could be measured, the
selection being done with bit SRCLCH bit of ACR register. The formula to
calculate the temperature is as follows:

P1 + (Vref * (VTEMP - P6 - P4 * VBG)) / (VBG * VTEMP_DT)

where:
- P1, P4, P6 are calibration data retrieved from OTP memory
- Vref is the reference voltage for ADC
- VTEMP_DT is the voltage sensitivity to temperature and is constant
- VTEMP, VBG are the measured values from channel 31

For better resolution before reading the temperature certain settings
for oversampling ratio, sample frequency, EMR.TRACKX, MR.TRACKTIM are
applied. The initial settings are reapplied at the end of temperature
reading.

Current support is not integrated with trigger buffers channel 31 not
being enabled/disabled in functions at91_adc_buffer_prepare(),
at91_adc_buffer_postdisable() thus the conversion for channel 31 is not
done in case trigger buffers are enabled. In case of trigger buffers are
enabled and temperature requests are received in the driver though
at91_adc_read_temp() the at91_adc_read_temp() will return with an error
code.

Signed-off-by: Claudiu Beznea <[email protected]>
---
drivers/iio/adc/at91-sama5d2_adc.c | 256 ++++++++++++++++++++++++++++-
1 file changed, 249 insertions(+), 7 deletions(-)

diff --git a/drivers/iio/adc/at91-sama5d2_adc.c b/drivers/iio/adc/at91-sama5d2_adc.c
index 1a72e304fc3a..0a7b1680f158 100644
--- a/drivers/iio/adc/at91-sama5d2_adc.c
+++ b/drivers/iio/adc/at91-sama5d2_adc.c
@@ -19,6 +19,7 @@
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/sched.h>
+#include <linux/units.h>
#include <linux/wait.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
@@ -26,9 +27,12 @@
#include <linux/iio/trigger.h>
#include <linux/iio/trigger_consumer.h>
#include <linux/iio/triggered_buffer.h>
+#include <linux/nvmem-consumer.h>
#include <linux/pinctrl/consumer.h>
#include <linux/regulator/consumer.h>

+#include <dt-bindings/iio/adc/at91-sama5d2_adc.h>
+
struct at91_adc_reg_layout {
/* Control Register */
u16 CR;
@@ -73,10 +77,13 @@ struct at91_adc_reg_layout {
/* Startup Time */
#define AT91_SAMA5D2_MR_STARTUP(v) ((v) << 16)
#define AT91_SAMA5D2_MR_STARTUP_MASK GENMASK(19, 16)
+/* Minimum startup time for temperature sensor */
+#define AT91_SAMA5D2_MR_STARTUP_TS_MIN (50)
/* Analog Change */
#define AT91_SAMA5D2_MR_ANACH BIT(23)
/* Tracking Time */
#define AT91_SAMA5D2_MR_TRACKTIM(v) ((v) << 24)
+#define AT91_SAMA5D2_MR_TRACKTIM_TS 6
#define AT91_SAMA5D2_MR_TRACKTIM_MAX 0xf
/* Transfer Time */
#define AT91_SAMA5D2_MR_TRANSFER(v) ((v) << 28)
@@ -149,6 +156,9 @@ struct at91_adc_reg_layout {
#define AT91_SAMA5D2_TRACKX_MASK GENMASK(23, 22)
#define AT91_SAMA5D2_TRACKX(x) (((x) << 22) & \
AT91_SAMA5D2_TRACKX_MASK)
+/* TRACKX for temperature sensor. */
+#define AT91_SAMA5D2_TRACKX_TS (1)
+
/* Extended Mode Register - Averaging on single trigger event */
#define AT91_SAMA5D2_EMR_ASTE(V) ((V) << 20)

@@ -164,6 +174,8 @@ struct at91_adc_reg_layout {
u16 ACR;
/* Analog Control Register - Pen detect sensitivity mask */
#define AT91_SAMA5D2_ACR_PENDETSENS_MASK GENMASK(1, 0)
+/* Analog Control Register - Source last channel */
+#define AT91_SAMA5D2_ACR_SRCLCH BIT(16)

/* Touchscreen Mode Register */
u16 TSMR;
@@ -231,6 +243,10 @@ struct at91_adc_reg_layout {
u16 WPSR;
/* Version Register */
u16 VERSION;
+/* Temperature Sensor Mode Register */
+ u16 TEMPMR;
+/* Temperature Sensor Mode - Temperature sensor on */
+#define AT91_SAMA5D2_TEMPMR_TEMPON BIT(0)
};

static const struct at91_adc_reg_layout sama5d2_layout = {
@@ -285,6 +301,7 @@ static const struct at91_adc_reg_layout sama7g5_layout = {
.EOC_IDR = 0x38,
.EOC_IMR = 0x3c,
.EOC_ISR = 0x40,
+ .TEMPMR = 0x44,
.OVER = 0x4c,
.EMR = 0x50,
.CWR = 0x54,
@@ -391,6 +408,21 @@ static const struct at91_adc_reg_layout sama7g5_layout = {
.datasheet_name = name, \
}

+#define AT91_SAMA5D2_CHAN_TEMP(num, name, addr) \
+ { \
+ .type = IIO_TEMP, \
+ .channel = num, \
+ .address = addr, \
+ .scan_index = num, \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), \
+ .info_mask_shared_by_all = \
+ BIT(IIO_CHAN_INFO_PROCESSED) | \
+ BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), \
+ .info_mask_shared_by_all_available = \
+ BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), \
+ .datasheet_name = name, \
+ }
+
#define at91_adc_readl(st, reg) \
readl_relaxed((st)->base + (st)->soc_info.platform->layout->reg)
#define at91_adc_read_chan(st, reg) \
@@ -415,6 +447,8 @@ static const struct at91_adc_reg_layout sama7g5_layout = {
* @oversampling_avail: available oversampling values
* @oversampling_avail_no: number of available oversampling values
* @chan_realbits: realbits for registered channels
+ * @temp_chan: temperature channel index
+ * @temp_sensor: temperature sensor supported
*/
struct at91_adc_platform {
const struct at91_adc_reg_layout *layout;
@@ -430,20 +464,54 @@ struct at91_adc_platform {
unsigned int oversampling_avail[5];
unsigned int oversampling_avail_no;
unsigned int chan_realbits;
+ unsigned int temp_chan;
+ bool temp_sensor;
};

+/**
+ * struct at91_adc_temp_sensor_clb - at91-sama5d2 temperature sensor
+ * calibration data structure
+ * @p1: P1 calibration temperature
+ * @p4: P4 calibration voltage
+ * @p6: P6 calibration voltage
+ */
+struct at91_adc_temp_sensor_clb {
+ u32 p1;
+ u32 p4;
+ u32 p6;
+};
+
+/**
+ * enum at91_adc_ts_clb_idx - calibration indexes in NVMEM buffer
+ * @AT91_ADC_TS_CLB_IDX_P1: index for P1
+ * @AT91_ADC_TS_CLB_IDX_P4: index for P4
+ * @AT91_ADC_TS_CLB_IDX_P6: index for P6
+ * @AT91_ADC_TS_CLB_IDX_MAX: max index for temperature calibration packet in OTP
+ */
+enum at91_adc_ts_clb_idx {
+ AT91_ADC_TS_CLB_IDX_P1 = 2,
+ AT91_ADC_TS_CLB_IDX_P4 = 5,
+ AT91_ADC_TS_CLB_IDX_P6 = 7,
+ AT91_ADC_TS_CLB_IDX_MAX = 19,
+};
+
+/* Temperature sensor calibration - Vtemp voltage sensitivity to temperature. */
+#define AT91_ADC_TS_VTEMP_DT (2080U)
+
/**
* 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
+ * @temp_sensor_clb: temperature sensor calibration data 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_temp_sensor_clb temp_sensor_clb;
};

struct at91_adc_trigger {
@@ -491,6 +559,18 @@ struct at91_adc_touch {
struct work_struct workq;
};

+/**
+ * struct at91_adc_temp - at91-sama5d2 temperature information structure
+ * @sample_period_val: sample period value
+ * @saved_sample_rate: saved sample rate
+ * @saved_oversampling: saved oversampling
+ */
+struct at91_adc_temp {
+ u16 sample_period_val;
+ u16 saved_sample_rate;
+ u16 saved_oversampling;
+};
+
/*
* Buffer size requirements:
* No channels * bytes_per_channel(2) + timestamp bytes (8)
@@ -518,6 +598,7 @@ struct at91_adc_state {
wait_queue_head_t wq_data_available;
struct at91_adc_dma dma_st;
struct at91_adc_touch touch_st;
+ struct at91_adc_temp temp_st;
struct iio_dev *indio_dev;
/* Ensure naturally aligned timestamp */
u16 buffer[AT91_BUFFER_MAX_HWORDS] __aligned(8);
@@ -607,6 +688,7 @@ static const struct iio_chan_spec at91_sama7g5_adc_channels[] = {
AT91_SAMA5D2_CHAN_DIFF(22, 12, 13, 0x90),
AT91_SAMA5D2_CHAN_DIFF(23, 14, 15, 0x98),
IIO_CHAN_SOFT_TIMESTAMP(24),
+ AT91_SAMA5D2_CHAN_TEMP(AT91_SAMA7G5_ADC_TEMP_CHANNEL, "temp", 0xdc),
};

static const struct at91_adc_platform sama5d2_platform = {
@@ -639,10 +721,13 @@ static const struct at91_adc_platform sama7g5_platform = {
.adc_channels = &at91_sama7g5_adc_channels,
#define AT91_SAMA7G5_SINGLE_CHAN_CNT 16
#define AT91_SAMA7G5_DIFF_CHAN_CNT 8
+#define AT91_SAMA7G5_TEMP_CHAN_CNT 1
.nr_channels = AT91_SAMA7G5_SINGLE_CHAN_CNT +
- AT91_SAMA7G5_DIFF_CHAN_CNT,
+ AT91_SAMA7G5_DIFF_CHAN_CNT +
+ AT91_SAMA7G5_TEMP_CHAN_CNT,
#define AT91_SAMA7G5_MAX_CHAN_IDX (AT91_SAMA7G5_SINGLE_CHAN_CNT + \
- AT91_SAMA7G5_DIFF_CHAN_CNT)
+ AT91_SAMA7G5_DIFF_CHAN_CNT + \
+ AT91_SAMA7G5_TEMP_CHAN_CNT)
.max_channels = ARRAY_SIZE(at91_sama7g5_adc_channels),
.max_index = AT91_SAMA7G5_MAX_CHAN_IDX,
#define AT91_SAMA7G5_HW_TRIG_CNT 3
@@ -651,6 +736,8 @@ static const struct at91_adc_platform sama7g5_platform = {
.oversampling_avail = { 1, 4, 16, 64, 256, },
.oversampling_avail_no = 5,
.chan_realbits = 16,
+ .temp_sensor = true,
+ .temp_chan = AT91_SAMA7G5_ADC_TEMP_CHANNEL,
};

static int at91_adc_chan_xlate(struct iio_dev *indio_dev, int chan)
@@ -1193,7 +1280,8 @@ static int at91_adc_buffer_prepare(struct iio_dev *indio_dev)
continue;
/* these channel types cannot be handled by this trigger */
if (chan->type == IIO_POSITIONRELATIVE ||
- chan->type == IIO_PRESSURE)
+ chan->type == IIO_PRESSURE ||
+ chan->type == IIO_TEMP)
continue;

at91_adc_cor(st, chan);
@@ -1235,7 +1323,8 @@ static int at91_adc_buffer_postdisable(struct iio_dev *indio_dev)
continue;
/* these channel types are virtual, no need to do anything */
if (chan->type == IIO_POSITIONRELATIVE ||
- chan->type == IIO_PRESSURE)
+ chan->type == IIO_PRESSURE ||
+ chan->type == IIO_TEMP)
continue;

at91_adc_writel(st, CHDR, BIT(chan->channel));
@@ -1613,12 +1702,19 @@ static int at91_adc_read_info_raw(struct iio_dev *indio_dev,
return ret;
}

- /* in this case we have a voltage channel */
+ /* in this case we have a voltage or temperature channel */

st->chan = chan;

at91_adc_cor(st, chan);
at91_adc_writel(st, CHER, BIT(chan->channel));
+ /*
+ * TEMPMR.TEMPON needs to update after CHER otherwise if none
+ * of the channels are enabled and TEMPMR.TEMPON = 1 will
+ * trigger DRDY interruption while preparing for temperature read.
+ */
+ if (chan->type == IIO_TEMP)
+ at91_adc_writel(st, TEMPMR, AT91_SAMA5D2_TEMPMR_TEMPON);
at91_adc_eoc_ena(st, chan->channel);
at91_adc_writel(st, CR, AT91_SAMA5D2_CR_START);

@@ -1638,6 +1734,8 @@ static int at91_adc_read_info_raw(struct iio_dev *indio_dev,
}

at91_adc_eoc_dis(st, st->chan->channel);
+ if (chan->type == IIO_TEMP)
+ at91_adc_writel(st, TEMPMR, 0U);
at91_adc_writel(st, CHDR, BIT(chan->channel));

/* Needed to ACK the DRDY interruption */
@@ -1665,6 +1763,89 @@ static int at91_adc_read_info_locked(struct iio_dev *indio_dev,
return ret;
}

+static void at91_adc_temp_sensor_configure(struct at91_adc_state *st,
+ bool start)
+{
+ u32 sample_rate, oversampling_ratio;
+ u32 startup_time, tracktim, trackx;
+
+ if (start) {
+ /*
+ * Configure the sensor for best accuracy: 10MHz frequency,
+ * oversampling rate of 256, tracktim=0xf and trackx=1.
+ */
+ sample_rate = 10 * MEGA;
+ oversampling_ratio = 256;
+ startup_time = AT91_SAMA5D2_MR_STARTUP_TS_MIN;
+ tracktim = AT91_SAMA5D2_MR_TRACKTIM_TS;
+ trackx = AT91_SAMA5D2_TRACKX_TS;
+
+ st->temp_st.saved_sample_rate = st->current_sample_rate;
+ st->temp_st.saved_oversampling = st->oversampling_ratio;
+ } else {
+ /* Go back to previous settings. */
+ sample_rate = st->temp_st.saved_sample_rate;
+ oversampling_ratio = st->temp_st.saved_oversampling;
+ startup_time = st->soc_info.startup_time;
+ tracktim = 0;
+ trackx = 0;
+ }
+
+ at91_adc_setup_samp_freq(st->indio_dev, sample_rate, startup_time,
+ tracktim);
+ at91_adc_config_emr(st, oversampling_ratio, trackx);
+}
+
+static int at91_adc_read_temp(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan, int *val)
+{
+ struct at91_adc_state *st = iio_priv(indio_dev);
+ struct at91_adc_temp_sensor_clb *clb = &st->soc_info.temp_sensor_clb;
+ u64 div1, div2;
+ u32 tmp;
+ int ret, vbg, vtemp;
+
+ ret = iio_device_claim_direct_mode(indio_dev);
+ if (ret)
+ return ret;
+ mutex_lock(&st->lock);
+
+ at91_adc_temp_sensor_configure(st, true);
+
+ /* Read VBG. */
+ tmp = at91_adc_readl(st, ACR);
+ tmp |= AT91_SAMA5D2_ACR_SRCLCH;
+ at91_adc_writel(st, ACR, tmp);
+ ret = at91_adc_read_info_raw(indio_dev, chan, &vbg);
+ if (ret < 0)
+ goto restore_config;
+
+ /* Read VTEMP. */
+ tmp &= ~AT91_SAMA5D2_ACR_SRCLCH;
+ at91_adc_writel(st, ACR, tmp);
+ ret = at91_adc_read_info_raw(indio_dev, chan, &vtemp);
+
+restore_config:
+ /* Revert previous settings. */
+ at91_adc_temp_sensor_configure(st, false);
+ mutex_unlock(&st->lock);
+ iio_device_release_direct_mode(indio_dev);
+ if (ret < 0)
+ return ret;
+
+ /*
+ * Temp[milli] = p1[milli] + (vtemp * clb->p6 - clb->p4 * vbg)/
+ * (vbg * AT91_ADC_TS_VTEMP_DT)
+ */
+ div1 = DIV_ROUND_CLOSEST_ULL(((u64)vtemp * clb->p6), vbg);
+ div1 = DIV_ROUND_CLOSEST_ULL((div1 * 1000), AT91_ADC_TS_VTEMP_DT);
+ div2 = DIV_ROUND_CLOSEST_ULL((u64)clb->p4, AT91_ADC_TS_VTEMP_DT);
+ div2 *= 1000;
+ *val = clb->p1 + (int)div1 - (int)div2;
+
+ return ret;
+}
+
static int at91_adc_read_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int *val, int *val2, long mask)
@@ -1682,6 +1863,11 @@ static int at91_adc_read_raw(struct iio_dev *indio_dev,
*val2 = chan->scan_type.realbits;
return IIO_VAL_FRACTIONAL_LOG2;

+ case IIO_CHAN_INFO_PROCESSED:
+ if (chan->type != IIO_TEMP)
+ return -EINVAL;
+ return at91_adc_read_temp(indio_dev, chan, val);
+
case IIO_CHAN_INFO_SAMP_FREQ:
*val = at91_adc_get_sample_freq(st);
return IIO_VAL_INT;
@@ -1997,12 +2183,61 @@ static int at91_adc_buffer_and_trigger_init(struct device *dev,
return 0;
}

+static int at91_adc_temp_sensor_init(struct at91_adc_state *st,
+ struct device *dev)
+{
+ struct at91_adc_temp_sensor_clb *clb = &st->soc_info.temp_sensor_clb;
+ struct nvmem_cell *temp_calib;
+ u32 *buf;
+ size_t len;
+ int ret = 0;
+
+ if (!st->soc_info.platform->temp_sensor)
+ return 0;
+
+ /* Get the calibration data from NVMEM. */
+ temp_calib = devm_nvmem_cell_get(dev, "temperature_calib");
+ if (IS_ERR(temp_calib)) {
+ ret = PTR_ERR(temp_calib);
+ if (ret != -ENOENT)
+ dev_err(dev, "Failed to get temperature_calib cell!\n");
+ return ret;
+ }
+
+ buf = nvmem_cell_read(temp_calib, &len);
+ if (IS_ERR(buf)) {
+ dev_err(dev, "Failed to read calibration data!\n");
+ return PTR_ERR(buf);
+ }
+ if (len < AT91_ADC_TS_CLB_IDX_MAX * 4) {
+ dev_err(dev, "Invalid calibration data!\n");
+ ret = -EINVAL;
+ goto free_buf;
+ }
+
+ /* Store calibration data for later use. */
+ clb->p1 = buf[AT91_ADC_TS_CLB_IDX_P1];
+ clb->p4 = buf[AT91_ADC_TS_CLB_IDX_P4];
+ clb->p6 = buf[AT91_ADC_TS_CLB_IDX_P6];
+
+ /*
+ * We prepare here the conversion to milli and also add constant
+ * factor (5 degrees Celsius) to p1 here to avoid doing it on
+ * hotpath.
+ */
+ clb->p1 = clb->p1 * 1000 + 5000;
+
+free_buf:
+ kfree(buf);
+ return ret;
+}
+
static int at91_adc_probe(struct platform_device *pdev)
{
struct iio_dev *indio_dev;
struct at91_adc_state *st;
struct resource *res;
- int ret, i;
+ int ret, i, num_channels;
u32 edge_type = IRQ_TYPE_NONE;

indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*st));
@@ -2014,11 +2249,18 @@ static int at91_adc_probe(struct platform_device *pdev)

st->soc_info.platform = of_device_get_match_data(&pdev->dev);

+ ret = at91_adc_temp_sensor_init(st, &pdev->dev);
+ /* Don't register temperature channel if initialization failed. */
+ if (ret)
+ num_channels = st->soc_info.platform->max_channels - 1;
+ else
+ num_channels = st->soc_info.platform->max_channels;
+
indio_dev->name = dev_name(&pdev->dev);
indio_dev->modes = INDIO_DIRECT_MODE | INDIO_BUFFER_SOFTWARE;
indio_dev->info = &at91_adc_info;
indio_dev->channels = *st->soc_info.platform->adc_channels;
- indio_dev->num_channels = st->soc_info.platform->max_channels;
+ indio_dev->num_channels = num_channels;

bitmap_set(&st->touch_st.channels_bitmask,
st->soc_info.platform->touch_chan_x, 1);
--
2.34.1


2022-08-03 10:45:48

by Claudiu Beznea

[permalink] [raw]
Subject: [PATCH v3 16/19] dt-bindings: iio: adc: at91-sama5d2_adc: add id for temperature channel

Add ID for temperature channel of AT91 SAMA5D2 ADC.

Signed-off-by: Claudiu Beznea <[email protected]>
Acked-by: Rob Herring <[email protected]>
---
include/dt-bindings/iio/adc/at91-sama5d2_adc.h | 3 +++
1 file changed, 3 insertions(+)

diff --git a/include/dt-bindings/iio/adc/at91-sama5d2_adc.h b/include/dt-bindings/iio/adc/at91-sama5d2_adc.h
index 70f99dbdbb42..866d36530583 100644
--- a/include/dt-bindings/iio/adc/at91-sama5d2_adc.h
+++ b/include/dt-bindings/iio/adc/at91-sama5d2_adc.h
@@ -13,4 +13,7 @@
/* pressure channel index */
#define AT91_SAMA5D2_ADC_P_CHANNEL 26

+/* SAMA7G5 Temperature sensor channel index. */
+#define AT91_SAMA7G5_ADC_TEMP_CHANNEL 31
+
#endif
--
2.34.1


2022-08-03 10:48:11

by Claudiu Beznea

[permalink] [raw]
Subject: [PATCH v3 13/19] iio: adc: at91-sama5d2_adc: update trackx on emr

Add support for updating trackx bits of EMR register. Having different
values of EMR.TRACKX when measuring temperature give a better accuracy.

Signed-off-by: Claudiu Beznea <[email protected]>
---
drivers/iio/adc/at91-sama5d2_adc.c | 14 ++++++++++----
1 file changed, 10 insertions(+), 4 deletions(-)

diff --git a/drivers/iio/adc/at91-sama5d2_adc.c b/drivers/iio/adc/at91-sama5d2_adc.c
index a1df475a6f29..0209353cbfd7 100644
--- a/drivers/iio/adc/at91-sama5d2_adc.c
+++ b/drivers/iio/adc/at91-sama5d2_adc.c
@@ -145,6 +145,10 @@ struct at91_adc_reg_layout {
#define AT91_SAMA5D2_EMR_OSR_64SAMPLES 3
#define AT91_SAMA5D2_EMR_OSR_256SAMPLES 4

+/* Extended Mode Register - TRACKX */
+#define AT91_SAMA5D2_TRACKX_MASK GENMASK(23, 22)
+#define AT91_SAMA5D2_TRACKX(x) (((x) << 22) & \
+ AT91_SAMA5D2_TRACKX_MASK)
/* Extended Mode Register - Averaging on single trigger event */
#define AT91_SAMA5D2_EMR_ASTE(V) ((V) << 20)

@@ -746,7 +750,7 @@ static void at91_adc_eoc_ena(struct at91_adc_state *st, unsigned int channel)
}

static int at91_adc_config_emr(struct at91_adc_state *st,
- u32 oversampling_ratio)
+ u32 oversampling_ratio, u32 trackx)
{
/* configure the extended mode register */
unsigned int emr = at91_adc_readl(st, EMR);
@@ -765,7 +769,7 @@ static int at91_adc_config_emr(struct at91_adc_state *st,
emr |= AT91_SAMA5D2_EMR_ASTE(1);

/* delete leftover content if it's the case */
- emr &= ~osr_mask;
+ emr &= ~(osr_mask | AT91_SAMA5D2_TRACKX_MASK);

/* select oversampling ratio from configuration */
switch (oversampling_ratio) {
@@ -791,6 +795,8 @@ static int at91_adc_config_emr(struct at91_adc_state *st,
break;
}

+ /* Update trackx. */
+ emr |= AT91_SAMA5D2_TRACKX(trackx);
at91_adc_writel(st, EMR, emr);

st->oversampling_ratio = oversampling_ratio;
@@ -1706,7 +1712,7 @@ static int at91_adc_write_raw(struct iio_dev *indio_dev,
return ret;
mutex_lock(&st->lock);
/* update ratio */
- ret = at91_adc_config_emr(st, val);
+ ret = at91_adc_config_emr(st, val, 0);
mutex_unlock(&st->lock);
iio_device_release_direct_mode(indio_dev);
return ret;
@@ -1904,7 +1910,7 @@ static void at91_adc_hw_init(struct iio_dev *indio_dev)
at91_adc_setup_samp_freq(indio_dev, st->soc_info.min_sample_rate);

/* configure extended mode register */
- at91_adc_config_emr(st, st->oversampling_ratio);
+ at91_adc_config_emr(st, st->oversampling_ratio, 0);
}

static ssize_t at91_adc_get_fifo_state(struct device *dev,
--
2.34.1


2022-08-03 10:50:07

by Claudiu Beznea

[permalink] [raw]
Subject: [PATCH v3 14/19] iio: adc: at91-sama5d2_adc: add startup and tracktim as parameter for at91_adc_setup_samp_freq()

Add startup and tracktim as parameter for at91_adc_setup_samp_freq()
function. In case of temperature sensor being enabled these parameters
will be configured on temperature read request to improve the accuracy
of the read temperature.

Signed-off-by: Claudiu Beznea <[email protected]>
---
drivers/iio/adc/at91-sama5d2_adc.c | 18 +++++++++++-------
1 file changed, 11 insertions(+), 7 deletions(-)

diff --git a/drivers/iio/adc/at91-sama5d2_adc.c b/drivers/iio/adc/at91-sama5d2_adc.c
index 0209353cbfd7..fd02da9b26b2 100644
--- a/drivers/iio/adc/at91-sama5d2_adc.c
+++ b/drivers/iio/adc/at91-sama5d2_adc.c
@@ -1435,7 +1435,9 @@ static unsigned at91_adc_startup_time(unsigned startup_time_min,
return i;
}

-static void at91_adc_setup_samp_freq(struct iio_dev *indio_dev, unsigned freq)
+static void at91_adc_setup_samp_freq(struct iio_dev *indio_dev, unsigned freq,
+ unsigned int startup_time,
+ unsigned int tracktim)
{
struct at91_adc_state *st = iio_priv(indio_dev);
unsigned f_per, prescal, startup, mr;
@@ -1443,17 +1445,17 @@ static void at91_adc_setup_samp_freq(struct iio_dev *indio_dev, unsigned freq)
f_per = clk_get_rate(st->per_clk);
prescal = (f_per / (2 * freq)) - 1;

- startup = at91_adc_startup_time(st->soc_info.startup_time,
- freq / 1000);
+ startup = at91_adc_startup_time(startup_time, freq / 1000);

mr = at91_adc_readl(st, MR);
mr &= ~(AT91_SAMA5D2_MR_STARTUP_MASK | AT91_SAMA5D2_MR_PRESCAL_MASK);
mr |= AT91_SAMA5D2_MR_STARTUP(startup);
mr |= AT91_SAMA5D2_MR_PRESCAL(prescal);
+ mr |= AT91_SAMA5D2_MR_TRACKTIM(tracktim);
at91_adc_writel(st, MR, mr);

- dev_dbg(&indio_dev->dev, "freq: %u, startup: %u, prescal: %u\n",
- freq, startup, prescal);
+ dev_dbg(&indio_dev->dev, "freq: %u, startup: %u, prescal: %u, tracktim=%u\n",
+ freq, startup, prescal, tracktim);
st->current_sample_rate = freq;
}

@@ -1725,7 +1727,8 @@ static int at91_adc_write_raw(struct iio_dev *indio_dev,
if (ret)
return ret;
mutex_lock(&st->lock);
- at91_adc_setup_samp_freq(indio_dev, val);
+ at91_adc_setup_samp_freq(indio_dev, val,
+ st->soc_info.startup_time, 0);
mutex_unlock(&st->lock);
iio_device_release_direct_mode(indio_dev);
return 0;
@@ -1907,7 +1910,8 @@ static void at91_adc_hw_init(struct iio_dev *indio_dev)
at91_adc_writel(st, MR,
AT91_SAMA5D2_MR_TRANSFER(2) | AT91_SAMA5D2_MR_ANACH);

- at91_adc_setup_samp_freq(indio_dev, st->soc_info.min_sample_rate);
+ at91_adc_setup_samp_freq(indio_dev, st->soc_info.min_sample_rate,
+ st->soc_info.startup_time, 0);

/* configure extended mode register */
at91_adc_config_emr(st, st->oversampling_ratio, 0);
--
2.34.1


2022-08-03 11:08:14

by Claudiu Beznea

[permalink] [raw]
Subject: [PATCH v3 15/19] iio: adc: at91-sama5d2_adc: lock around at91_adc_read_info_raw()

Remove iio_device_{claim, release}_direct_mode() and lock/unlock to
&st->lock from at91_adc_read_info_raw(). Instead add a wrapper around
at91_adc_read_info_raw() and do there the lock/unlock. This will allow
using the at91_adc_read_info_raw() in patch that add support for
temperature sensor.

Signed-off-by: Claudiu Beznea <[email protected]>
---
drivers/iio/adc/at91-sama5d2_adc.c | 39 +++++++++++++++---------------
1 file changed, 19 insertions(+), 20 deletions(-)

diff --git a/drivers/iio/adc/at91-sama5d2_adc.c b/drivers/iio/adc/at91-sama5d2_adc.c
index fd02da9b26b2..1a72e304fc3a 100644
--- a/drivers/iio/adc/at91-sama5d2_adc.c
+++ b/drivers/iio/adc/at91-sama5d2_adc.c
@@ -1582,6 +1582,7 @@ static irqreturn_t at91_adc_interrupt(int irq, void *private)
return IRQ_HANDLED;
}

+/* This needs to be called with direct mode claimed and st->lock locked. */
static int at91_adc_read_info_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan, int *val)
{
@@ -1594,45 +1595,26 @@ static int at91_adc_read_info_raw(struct iio_dev *indio_dev,
* if external trigger is enabled
*/
if (chan->type == IIO_POSITIONRELATIVE) {
- ret = iio_device_claim_direct_mode(indio_dev);
- if (ret)
- return ret;
- mutex_lock(&st->lock);
-
ret = at91_adc_read_position(st, chan->channel,
&tmp_val);
*val = tmp_val;
if (ret > 0)
ret = at91_adc_adjust_val_osr(st, val);
- mutex_unlock(&st->lock);
- iio_device_release_direct_mode(indio_dev);

return ret;
}
if (chan->type == IIO_PRESSURE) {
- ret = iio_device_claim_direct_mode(indio_dev);
- if (ret)
- return ret;
- mutex_lock(&st->lock);
-
ret = at91_adc_read_pressure(st, chan->channel,
&tmp_val);
*val = tmp_val;
if (ret > 0)
ret = at91_adc_adjust_val_osr(st, val);
- mutex_unlock(&st->lock);
- iio_device_release_direct_mode(indio_dev);

return ret;
}

/* in this case we have a voltage channel */

- ret = iio_device_claim_direct_mode(indio_dev);
- if (ret)
- return ret;
- mutex_lock(&st->lock);
-
st->chan = chan;

at91_adc_cor(st, chan);
@@ -1661,9 +1643,25 @@ static int at91_adc_read_info_raw(struct iio_dev *indio_dev,
/* Needed to ACK the DRDY interruption */
at91_adc_readl(st, LCDR);

+ return ret;
+}
+
+static int at91_adc_read_info_locked(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan, int *val)
+{
+ struct at91_adc_state *st = iio_priv(indio_dev);
+ int ret;
+
+ ret = iio_device_claim_direct_mode(indio_dev);
+ if (ret)
+ return ret;
+
+ mutex_lock(&st->lock);
+ ret = at91_adc_read_info_raw(indio_dev, chan, val);
mutex_unlock(&st->lock);

iio_device_release_direct_mode(indio_dev);
+
return ret;
}

@@ -1675,7 +1673,8 @@ static int at91_adc_read_raw(struct iio_dev *indio_dev,

switch (mask) {
case IIO_CHAN_INFO_RAW:
- return at91_adc_read_info_raw(indio_dev, chan, val);
+ return at91_adc_read_info_locked(indio_dev, chan, val);
+
case IIO_CHAN_INFO_SCALE:
*val = st->vref_uv / 1000;
if (chan->differential)
--
2.34.1


2022-08-03 11:09:00

by Claudiu Beznea

[permalink] [raw]
Subject: [PATCH v3 18/19] iio: adc: at91-sama5d2_adc: add empty line after functions

Add empty line after function.

Signed-off-by: Claudiu Beznea <[email protected]>
---
drivers/iio/adc/at91-sama5d2_adc.c | 1 +
1 file changed, 1 insertion(+)

diff --git a/drivers/iio/adc/at91-sama5d2_adc.c b/drivers/iio/adc/at91-sama5d2_adc.c
index 0a7b1680f158..94cb96ccd2ee 100644
--- a/drivers/iio/adc/at91-sama5d2_adc.c
+++ b/drivers/iio/adc/at91-sama5d2_adc.c
@@ -1371,6 +1371,7 @@ static struct iio_trigger *at91_adc_allocate_trigger(struct iio_dev *indio,

return trig;
}
+
static void at91_adc_trigger_handler_nodma(struct iio_dev *indio_dev,
struct iio_poll_func *pf)
{
--
2.34.1


2022-08-03 11:09:43

by Claudiu Beznea

[permalink] [raw]
Subject: [PATCH v3 19/19] iio: adc: at91-sama5d2_adc: add runtime pm support

Add runtime PM support by disabling/enabling ADC's peripheral clock.
On simple conversion the ADC's clock is kept enabled just while the
conversion is in progress. This includes also temperature conversion.
For triggered buffers and touch conversions the ADC clock is kept enabled
while the triggered buffers or touch are enabled. Along with it removed
the __maybe_unused on suspend() and resume() ops as the dev_pm_ops
object members are now filled with SYSTEM_SLEEP_PM_OPS().

Signed-off-by: Claudiu Beznea <[email protected]>
---
drivers/iio/adc/at91-sama5d2_adc.c | 208 +++++++++++++++++++++++------
1 file changed, 166 insertions(+), 42 deletions(-)

diff --git a/drivers/iio/adc/at91-sama5d2_adc.c b/drivers/iio/adc/at91-sama5d2_adc.c
index 94cb96ccd2ee..8d8aa9691499 100644
--- a/drivers/iio/adc/at91-sama5d2_adc.c
+++ b/drivers/iio/adc/at91-sama5d2_adc.c
@@ -29,6 +29,7 @@
#include <linux/iio/triggered_buffer.h>
#include <linux/nvmem-consumer.h>
#include <linux/pinctrl/consumer.h>
+#include <linux/pm_runtime.h>
#include <linux/regulator/consumer.h>

#include <dt-bindings/iio/adc/at91-sama5d2_adc.h>
@@ -600,6 +601,7 @@ struct at91_adc_state {
struct at91_adc_touch touch_st;
struct at91_adc_temp temp_st;
struct iio_dev *indio_dev;
+ struct device *dev;
/* Ensure naturally aligned timestamp */
u16 buffer[AT91_BUFFER_MAX_HWORDS] __aligned(8);
/*
@@ -840,9 +842,9 @@ static int at91_adc_config_emr(struct at91_adc_state *st,
u32 oversampling_ratio, u32 trackx)
{
/* configure the extended mode register */
- unsigned int emr = at91_adc_readl(st, EMR);
+ unsigned int emr, osr;
unsigned int osr_mask = st->soc_info.platform->osr_mask;
- int i;
+ int i, ret;

/* Check against supported oversampling values. */
for (i = 0; i < st->soc_info.platform->oversampling_avail_no; i++) {
@@ -852,40 +854,46 @@ static int at91_adc_config_emr(struct at91_adc_state *st,
if (i == st->soc_info.platform->oversampling_avail_no)
return -EINVAL;

- /* select oversampling per single trigger event */
- emr |= AT91_SAMA5D2_EMR_ASTE(1);
-
- /* delete leftover content if it's the case */
- emr &= ~(osr_mask | AT91_SAMA5D2_TRACKX_MASK);
-
/* select oversampling ratio from configuration */
switch (oversampling_ratio) {
case 1:
- emr |= AT91_SAMA5D2_EMR_OSR(AT91_SAMA5D2_EMR_OSR_1SAMPLES,
- osr_mask);
+ osr = AT91_SAMA5D2_EMR_OSR(AT91_SAMA5D2_EMR_OSR_1SAMPLES,
+ osr_mask);
break;
case 4:
- emr |= AT91_SAMA5D2_EMR_OSR(AT91_SAMA5D2_EMR_OSR_4SAMPLES,
- osr_mask);
+ osr = AT91_SAMA5D2_EMR_OSR(AT91_SAMA5D2_EMR_OSR_4SAMPLES,
+ osr_mask);
break;
case 16:
- emr |= AT91_SAMA5D2_EMR_OSR(AT91_SAMA5D2_EMR_OSR_16SAMPLES,
- osr_mask);
+ osr = AT91_SAMA5D2_EMR_OSR(AT91_SAMA5D2_EMR_OSR_16SAMPLES,
+ osr_mask);
break;
case 64:
- emr |= AT91_SAMA5D2_EMR_OSR(AT91_SAMA5D2_EMR_OSR_64SAMPLES,
- osr_mask);
+ osr = AT91_SAMA5D2_EMR_OSR(AT91_SAMA5D2_EMR_OSR_64SAMPLES,
+ osr_mask);
break;
case 256:
- emr |= AT91_SAMA5D2_EMR_OSR(AT91_SAMA5D2_EMR_OSR_256SAMPLES,
- osr_mask);
+ osr = AT91_SAMA5D2_EMR_OSR(AT91_SAMA5D2_EMR_OSR_256SAMPLES,
+ osr_mask);
break;
}

- /* Update trackx. */
- emr |= AT91_SAMA5D2_TRACKX(trackx);
+ ret = pm_runtime_resume_and_get(st->dev);
+ if (ret < 0)
+ return ret;
+
+ emr = at91_adc_readl(st, EMR);
+ /* select oversampling per single trigger event */
+ emr |= AT91_SAMA5D2_EMR_ASTE(1);
+ /* delete leftover content if it's the case */
+ emr &= ~(osr_mask | AT91_SAMA5D2_TRACKX_MASK);
+ /* Update osr and trackx. */
+ emr |= osr | AT91_SAMA5D2_TRACKX(trackx);
at91_adc_writel(st, EMR, emr);

+ pm_runtime_mark_last_busy(st->dev);
+ pm_runtime_put_autosuspend(st->dev);
+
st->oversampling_ratio = oversampling_ratio;

return 0;
@@ -944,15 +952,22 @@ static void at91_adc_adjust_val_osr_array(struct at91_adc_state *st, void *buf,
static int at91_adc_configure_touch(struct at91_adc_state *st, bool state)
{
u32 clk_khz = st->current_sample_rate / 1000;
- int i = 0;
+ int i = 0, ret;
u16 pendbc;
u32 tsmr, acr;

- if (!state) {
+ if (state) {
+ ret = pm_runtime_resume_and_get(st->dev);
+ if (ret < 0)
+ return ret;
+ } else {
/* disabling touch IRQs and setting mode to no touch enabled */
at91_adc_writel(st, IDR,
AT91_SAMA5D2_IER_PEN | AT91_SAMA5D2_IER_NOPEN);
at91_adc_writel(st, TSMR, 0);
+
+ pm_runtime_mark_last_busy(st->dev);
+ pm_runtime_put_autosuspend(st->dev);
return 0;
}
/*
@@ -1093,10 +1108,9 @@ static int at91_adc_read_pressure(struct at91_adc_state *st, int chan, u16 *val)
return IIO_VAL_INT;
}

-static int at91_adc_configure_trigger(struct iio_trigger *trig, bool state)
+static void at91_adc_configure_trigger_registers(struct at91_adc_state *st,
+ bool state)
{
- struct iio_dev *indio = iio_trigger_get_drvdata(trig);
- struct at91_adc_state *st = iio_priv(indio);
u32 status = at91_adc_readl(st, TRGR);

/* clear TRGMOD */
@@ -1107,6 +1121,26 @@ static int at91_adc_configure_trigger(struct iio_trigger *trig, bool state)

/* set/unset hw trigger */
at91_adc_writel(st, TRGR, status);
+}
+
+static int at91_adc_configure_trigger(struct iio_trigger *trig, bool state)
+{
+ struct iio_dev *indio = iio_trigger_get_drvdata(trig);
+ struct at91_adc_state *st = iio_priv(indio);
+ int ret;
+
+ if (state) {
+ ret = pm_runtime_resume_and_get(st->dev);
+ if (ret < 0)
+ return ret;
+ }
+
+ at91_adc_configure_trigger_registers(st, state);
+
+ if (!state) {
+ pm_runtime_mark_last_busy(st->dev);
+ pm_runtime_put_autosuspend(st->dev);
+ }

return 0;
}
@@ -1265,11 +1299,15 @@ static int at91_adc_buffer_prepare(struct iio_dev *indio_dev)
if (!(iio_device_get_current_mode(indio_dev) & INDIO_ALL_TRIGGERED_MODES))
return -EINVAL;

+ ret = pm_runtime_resume_and_get(st->dev);
+ if (ret < 0)
+ return ret;
+
/* we continue with the triggered buffer */
ret = at91_adc_dma_start(indio_dev);
if (ret) {
dev_err(&indio_dev->dev, "buffer prepare failed\n");
- return ret;
+ goto pm_runtime_put;
}

for_each_set_bit(bit, indio_dev->active_scan_mask,
@@ -1292,12 +1330,16 @@ static int at91_adc_buffer_prepare(struct iio_dev *indio_dev)
if (at91_adc_buffer_check_use_irq(indio_dev, st))
at91_adc_writel(st, IER, AT91_SAMA5D2_IER_DRDY);

- return 0;
+pm_runtime_put:
+ pm_runtime_mark_last_busy(st->dev);
+ pm_runtime_put_autosuspend(st->dev);
+ return ret;
}

static int at91_adc_buffer_postdisable(struct iio_dev *indio_dev)
{
struct at91_adc_state *st = iio_priv(indio_dev);
+ int ret;
u8 bit;

/* check if we are disabling triggered buffer or the touchscreen */
@@ -1308,6 +1350,10 @@ static int at91_adc_buffer_postdisable(struct iio_dev *indio_dev)
if (!(iio_device_get_current_mode(indio_dev) & INDIO_ALL_TRIGGERED_MODES))
return -EINVAL;

+ ret = pm_runtime_resume_and_get(st->dev);
+ if (ret < 0)
+ return ret;
+
/*
* For each enable channel we must disable it in hardware.
* In the case of DMA, we must read the last converted value
@@ -1343,6 +1389,9 @@ static int at91_adc_buffer_postdisable(struct iio_dev *indio_dev)
if (st->dma_st.dma_chan)
dmaengine_terminate_sync(st->dma_st.dma_chan);

+ pm_runtime_mark_last_busy(st->dev);
+ pm_runtime_put_autosuspend(st->dev);
+
return 0;
}

@@ -1531,12 +1580,17 @@ static void at91_adc_setup_samp_freq(struct iio_dev *indio_dev, unsigned freq,
{
struct at91_adc_state *st = iio_priv(indio_dev);
unsigned f_per, prescal, startup, mr;
+ int ret;

f_per = clk_get_rate(st->per_clk);
prescal = (f_per / (2 * freq)) - 1;

startup = at91_adc_startup_time(startup_time, freq / 1000);

+ ret = pm_runtime_resume_and_get(st->dev);
+ if (ret < 0)
+ return;
+
mr = at91_adc_readl(st, MR);
mr &= ~(AT91_SAMA5D2_MR_STARTUP_MASK | AT91_SAMA5D2_MR_PRESCAL_MASK);
mr |= AT91_SAMA5D2_MR_STARTUP(startup);
@@ -1544,6 +1598,9 @@ static void at91_adc_setup_samp_freq(struct iio_dev *indio_dev, unsigned freq,
mr |= AT91_SAMA5D2_MR_TRACKTIM(tracktim);
at91_adc_writel(st, MR, mr);

+ pm_runtime_mark_last_busy(st->dev);
+ pm_runtime_put_autosuspend(st->dev);
+
dev_dbg(&indio_dev->dev, "freq: %u, startup: %u, prescal: %u, tracktim=%u\n",
freq, startup, prescal, tracktim);
st->current_sample_rate = freq;
@@ -1680,6 +1737,10 @@ static int at91_adc_read_info_raw(struct iio_dev *indio_dev,
u16 tmp_val;
int ret;

+ ret = pm_runtime_resume_and_get(st->dev);
+ if (ret < 0)
+ return ret;
+
/*
* Keep in mind that we cannot use software trigger or touchscreen
* if external trigger is enabled
@@ -1691,7 +1752,7 @@ static int at91_adc_read_info_raw(struct iio_dev *indio_dev,
if (ret > 0)
ret = at91_adc_adjust_val_osr(st, val);

- return ret;
+ goto pm_runtime_put;
}
if (chan->type == IIO_PRESSURE) {
ret = at91_adc_read_pressure(st, chan->channel,
@@ -1700,7 +1761,7 @@ static int at91_adc_read_info_raw(struct iio_dev *indio_dev,
if (ret > 0)
ret = at91_adc_adjust_val_osr(st, val);

- return ret;
+ goto pm_runtime_put;
}

/* in this case we have a voltage or temperature channel */
@@ -1742,6 +1803,9 @@ static int at91_adc_read_info_raw(struct iio_dev *indio_dev,
/* Needed to ACK the DRDY interruption */
at91_adc_readl(st, LCDR);

+pm_runtime_put:
+ pm_runtime_mark_last_busy(st->dev);
+ pm_runtime_put_autosuspend(st->dev);
return ret;
}

@@ -1811,6 +1875,10 @@ static int at91_adc_read_temp(struct iio_dev *indio_dev,
return ret;
mutex_lock(&st->lock);

+ ret = pm_runtime_resume_and_get(st->dev);
+ if (ret < 0)
+ goto unlock;
+
at91_adc_temp_sensor_configure(st, true);

/* Read VBG. */
@@ -1829,6 +1897,9 @@ static int at91_adc_read_temp(struct iio_dev *indio_dev,
restore_config:
/* Revert previous settings. */
at91_adc_temp_sensor_configure(st, false);
+ pm_runtime_mark_last_busy(st->dev);
+ pm_runtime_put_autosuspend(st->dev);
+unlock:
mutex_unlock(&st->lock);
iio_device_release_direct_mode(indio_dev);
if (ret < 0)
@@ -2373,13 +2444,19 @@ static int at91_adc_probe(struct platform_device *pdev)
if (ret)
goto vref_disable;

- at91_adc_hw_init(indio_dev);
-
platform_set_drvdata(pdev, indio_dev);
+ st->dev = &pdev->dev;
+ pm_runtime_set_autosuspend_delay(st->dev, 500);
+ pm_runtime_use_autosuspend(st->dev);
+ pm_runtime_set_active(st->dev);
+ pm_runtime_enable(st->dev);
+ pm_runtime_get_noresume(st->dev);
+
+ at91_adc_hw_init(indio_dev);

ret = at91_adc_buffer_and_trigger_init(&pdev->dev, indio_dev);
if (ret < 0)
- goto per_clk_disable_unprepare;
+ goto err_pm_disable;

if (dma_coerce_mask_and_coherent(&indio_dev->dev, DMA_BIT_MASK(32)))
dev_info(&pdev->dev, "cannot set DMA mask to 32-bit\n");
@@ -2395,11 +2472,18 @@ static int at91_adc_probe(struct platform_device *pdev)
dev_info(&pdev->dev, "version: %x\n",
readl_relaxed(st->base + st->soc_info.platform->layout->VERSION));

+ pm_runtime_mark_last_busy(st->dev);
+ pm_runtime_put_autosuspend(st->dev);
+
return 0;

dma_disable:
at91_adc_dma_disable(st);
-per_clk_disable_unprepare:
+err_pm_disable:
+ pm_runtime_put_noidle(st->dev);
+ pm_runtime_disable(st->dev);
+ pm_runtime_set_suspended(st->dev);
+ pm_runtime_dont_use_autosuspend(st->dev);
clk_disable_unprepare(st->per_clk);
vref_disable:
regulator_disable(st->vref);
@@ -2417,6 +2501,8 @@ static int at91_adc_remove(struct platform_device *pdev)

at91_adc_dma_disable(st);

+ pm_runtime_disable(st->dev);
+ pm_runtime_set_suspended(st->dev);
clk_disable_unprepare(st->per_clk);

regulator_disable(st->vref);
@@ -2429,6 +2515,11 @@ static int at91_adc_suspend(struct device *dev)
{
struct iio_dev *indio_dev = dev_get_drvdata(dev);
struct at91_adc_state *st = iio_priv(indio_dev);
+ int ret;
+
+ ret = pm_runtime_resume_and_get(st->dev);
+ if (ret < 0)
+ return ret;

if (iio_buffer_enabled(indio_dev))
at91_adc_buffer_postdisable(indio_dev);
@@ -2441,6 +2532,8 @@ static int at91_adc_suspend(struct device *dev)
*/
at91_adc_writel(st, CR, AT91_SAMA5D2_CR_SWRST);

+ pm_runtime_mark_last_busy(st->dev);
+ pm_runtime_put_noidle(st->dev);
clk_disable_unprepare(st->per_clk);
regulator_disable(st->vref);
regulator_disable(st->reg);
@@ -2470,18 +2563,28 @@ static int at91_adc_resume(struct device *dev)
if (ret)
goto vref_disable_resume;

+ pm_runtime_get_noresume(st->dev);
+
at91_adc_hw_init(indio_dev);

/* reconfiguring trigger hardware state */
- if (!iio_buffer_enabled(indio_dev))
- return 0;
+ if (iio_buffer_enabled(indio_dev)) {
+ ret = at91_adc_buffer_prepare(indio_dev);
+ if (ret)
+ goto pm_runtime_put;

- ret = at91_adc_buffer_prepare(indio_dev);
- if (ret)
- goto vref_disable_resume;
+ at91_adc_configure_trigger_registers(st, true);
+ }
+
+ pm_runtime_mark_last_busy(st->dev);
+ pm_runtime_put_autosuspend(st->dev);

- return at91_adc_configure_trigger(st->trig, true);
+ return 0;

+pm_runtime_put:
+ pm_runtime_mark_last_busy(st->dev);
+ pm_runtime_put_noidle(st->dev);
+ clk_disable_unprepare(st->per_clk);
vref_disable_resume:
regulator_disable(st->vref);
reg_disable_resume:
@@ -2491,8 +2594,29 @@ static int at91_adc_resume(struct device *dev)
return ret;
}

-static DEFINE_SIMPLE_DEV_PM_OPS(at91_adc_pm_ops, at91_adc_suspend,
- at91_adc_resume);
+static int at91_adc_runtime_suspend(struct device *dev)
+{
+ struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct at91_adc_state *st = iio_priv(indio_dev);
+
+ clk_disable(st->per_clk);
+
+ return 0;
+}
+
+static int at91_adc_runtime_resume(struct device *dev)
+{
+ struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct at91_adc_state *st = iio_priv(indio_dev);
+
+ return clk_enable(st->per_clk);
+}
+
+static const struct dev_pm_ops at91_adc_pm_ops = {
+ SYSTEM_SLEEP_PM_OPS(at91_adc_suspend, at91_adc_resume)
+ RUNTIME_PM_OPS(at91_adc_runtime_suspend, at91_adc_runtime_resume,
+ NULL)
+};

static const struct of_device_id at91_adc_dt_match[] = {
{
@@ -2513,7 +2637,7 @@ static struct platform_driver at91_adc_driver = {
.driver = {
.name = "at91-sama5d2_adc",
.of_match_table = at91_adc_dt_match,
- .pm = pm_sleep_ptr(&at91_adc_pm_ops),
+ .pm = pm_ptr(&at91_adc_pm_ops),
},
};
module_platform_driver(at91_adc_driver)
--
2.34.1


2022-08-06 14:13:40

by Jonathan Cameron

[permalink] [raw]
Subject: Re: [PATCH v3 00/19] iio: adc: at91-sama5d2_adc: add support for temperature sensor

On Wed, 3 Aug 2022 13:28:36 +0300
Claudiu Beznea <[email protected]> wrote:

> Hi,
>
> The following series add support for temperature sensor available on
> SAMA7G5.
>
> Temperature sensor available on SAMA7G5 provides 2 outputs VTEMP and VBG.
> VTEMP is proportional to the absolute temperature voltage and VBG is a
> quasi-temperature independent voltage. Both are necessary in computing
> the temperature (for better accuracy). Also, for better accuracy the
> following settings were imposed when measusing the temperature:
> oversampling rate of 256, sampling frequency of 10MHz, a startup time of
> 512 ticks, MR.tracktim=0xf, EMR.trackx=0x3.
>
> For computing the temperature measured by ADC calibration data is
> necessary. This is provided via OTP memory available on SAMA7G5.
>
> Patches 1/19-4/19 provides some fixes.
> Patches 5/19-16/19 prepares for the addition of temperature sensor
> support.
> Patch 17/16 adds the temperature sensor support.
>
> Along with temperature sensor support I took the chance and added
> runtime PM support in this series, too (handled in patch 19/19).
>
> The rest of patches in this series are minor cleanups.
Dropped v2 adn replaced with this one. For now just pushed out as
testing to let the autobuilders take another look at it.
I'll rebase when rc1 is out and then push this out for linux-next
to pick up.

Thanks,

Jonathan

>
> Thank you,
> Claudiu Beznea
>
> Changes in v3:
> - fixed compilation warning by adjusting patches 10/19, 11/19
>
> Changes in v2:
> - addressed review comments
> - with this, new patches were intruced in this series: 2/19, 4/19,
> 8/19, 9,19
> - runtime pm support has been adapted to work also when CONFIG_PM
> is not enabled
> - collected tags
>
> Claudiu Beznea (19):
> iio: adc: at91-sama5d2_adc: fix AT91_SAMA5D2_MR_TRACKTIM_MAX
> iio: adc: at91-sama5d2_adc: check return status for pressure and touch
> iio: adc: at91-sama5d2_adc: lock around oversampling and sample freq
> iio: adc: at91-sama5d2_adc: disable/prepare buffer on suspend/resume
> iio: adc: at91-sama5d2_adc: exit from write_raw() when buffers are
> enabled
> iio: adc: at91-sama5d2_adc: handle different EMR.OSR for different hw
> versions
> iio: adc: at91-sama5d2_adc: move the check of oversampling in its
> function
> iio: adc: at91-sama5d2_adc: drop AT91_OSR_XSAMPLES defines
> iio: adc: at91-sama5d2_adc: add .read_avail() chan_info ops
> iio: adc: at91-sama5d2_adc: adjust osr based on specific platform data
> iio: adc: at91-sama5d2_adc: add 64 and 256 oversampling ratio
> iio: adc: at91-sama5d2_adc: move oversampling storage in its function
> iio: adc: at91-sama5d2_adc: update trackx on emr
> iio: adc: at91-sama5d2_adc: add startup and tracktim as parameter for
> at91_adc_setup_samp_freq()
> iio: adc: at91-sama5d2_adc: lock around at91_adc_read_info_raw()
> dt-bindings: iio: adc: at91-sama5d2_adc: add id for temperature
> channel
> iio: adc: at91-sama5d2_adc: add support for temperature sensor
> iio: adc: at91-sama5d2_adc: add empty line after functions
> iio: adc: at91-sama5d2_adc: add runtime pm support
>
> drivers/iio/adc/at91-sama5d2_adc.c | 684 +++++++++++++++---
> .../dt-bindings/iio/adc/at91-sama5d2_adc.h | 3 +
> 2 files changed, 568 insertions(+), 119 deletions(-)
>