summaryrefslogtreecommitdiff
path: root/drivers/iio/adc/stm32-adc.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/iio/adc/stm32-adc.c')
-rw-r--r--drivers/iio/adc/stm32-adc.c325
1 files changed, 228 insertions, 97 deletions
diff --git a/drivers/iio/adc/stm32-adc.c b/drivers/iio/adc/stm32-adc.c
index 1aadb2ad2cab..2d7f88459c7c 100644
--- a/drivers/iio/adc/stm32-adc.c
+++ b/drivers/iio/adc/stm32-adc.c
@@ -6,6 +6,7 @@
* Author: Fabrice Gasnier <fabrice.gasnier@st.com>.
*/
+#include <linux/array_size.h>
#include <linux/clk.h>
#include <linux/debugfs.h>
#include <linux/delay.h>
@@ -202,28 +203,32 @@ struct stm32_adc;
* @has_boostmode: boost mode support flag
* @has_linearcal: linear calibration support flag
* @has_presel: channel preselection support flag
+ * @has_oversampling: oversampling support flag
* @prepare: optional prepare routine (power-up, enable)
* @start_conv: routine to start conversions
* @stop_conv: routine to stop conversions
* @unprepare: optional unprepare routine (disable, power-down)
* @irq_clear: routine to clear irqs
+ * @set_ovs: routine to set oversampling configuration
* @smp_cycles: programmable sampling time (ADC clock cycles)
* @ts_int_ch: pointer to array of internal channels minimum sampling time in ns
*/
struct stm32_adc_cfg {
const struct stm32_adc_regspec *regs;
const struct stm32_adc_info *adc_info;
- struct stm32_adc_trig_info *trigs;
+ const struct stm32_adc_trig_info *trigs;
bool clk_required;
bool has_vregready;
bool has_boostmode;
bool has_linearcal;
bool has_presel;
+ bool has_oversampling;
int (*prepare)(struct iio_dev *);
void (*start_conv)(struct iio_dev *, bool dma);
void (*stop_conv)(struct iio_dev *);
void (*unprepare)(struct iio_dev *);
void (*irq_clear)(struct iio_dev *indio_dev, u32 msk);
+ void (*set_ovs)(struct iio_dev *indio_dev, u32 ovs_idx);
const unsigned int *smp_cycles;
const unsigned int *ts_int_ch;
};
@@ -255,6 +260,7 @@ struct stm32_adc_cfg {
* @num_diff: number of differential channels
* @int_ch: internal channel indexes array
* @nsmps: number of channels with optional sample time
+ * @ovs_idx: current oversampling ratio index (in oversampling array)
*/
struct stm32_adc {
struct stm32_adc_common *common;
@@ -282,6 +288,7 @@ struct stm32_adc {
u32 num_diff;
int int_ch[STM32_ADC_INT_CH_NB];
int nsmps;
+ int ovs_idx;
};
struct stm32_adc_diff_channel {
@@ -293,12 +300,24 @@ struct stm32_adc_diff_channel {
* struct stm32_adc_info - stm32 ADC, per instance config data
* @max_channels: Number of channels
* @resolutions: available resolutions
+ * @oversampling: available oversampling ratios
* @num_res: number of available resolutions
+ * @num_ovs: number of available oversampling ratios
*/
struct stm32_adc_info {
int max_channels;
const unsigned int *resolutions;
+ const unsigned int *oversampling;
const unsigned int num_res;
+ const unsigned int num_ovs;
+};
+
+static const unsigned int stm32h7_adc_oversampling_avail[] = {
+ 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024,
+};
+
+static const unsigned int stm32mp13_adc_oversampling_avail[] = {
+ 1, 2, 4, 8, 16, 32, 64, 128, 256,
};
static const unsigned int stm32f4_adc_resolutions[] = {
@@ -322,14 +341,18 @@ static const unsigned int stm32h7_adc_resolutions[] = {
static const struct stm32_adc_info stm32h7_adc_info = {
.max_channels = STM32_ADC_CH_MAX,
.resolutions = stm32h7_adc_resolutions,
+ .oversampling = stm32h7_adc_oversampling_avail,
.num_res = ARRAY_SIZE(stm32h7_adc_resolutions),
+ .num_ovs = ARRAY_SIZE(stm32h7_adc_oversampling_avail),
};
/* stm32mp13 can have up to 19 channels */
static const struct stm32_adc_info stm32mp13_adc_info = {
.max_channels = 19,
.resolutions = stm32f4_adc_resolutions,
+ .oversampling = stm32mp13_adc_oversampling_avail,
.num_res = ARRAY_SIZE(stm32f4_adc_resolutions),
+ .num_ovs = ARRAY_SIZE(stm32mp13_adc_oversampling_avail),
};
/*
@@ -360,7 +383,7 @@ static const struct stm32_adc_regs stm32f4_sq[STM32_ADC_MAX_SQ + 1] = {
};
/* STM32F4 external trigger sources for all instances */
-static struct stm32_adc_trig_info stm32f4_adc_trigs[] = {
+static const struct stm32_adc_trig_info stm32f4_adc_trigs[] = {
{ TIM1_CH1, STM32_EXT0 },
{ TIM1_CH2, STM32_EXT1 },
{ TIM1_CH3, STM32_EXT2 },
@@ -450,7 +473,7 @@ static const struct stm32_adc_regs stm32h7_sq[STM32_ADC_MAX_SQ + 1] = {
};
/* STM32H7 external trigger sources for all instances */
-static struct stm32_adc_trig_info stm32h7_adc_trigs[] = {
+static const struct stm32_adc_trig_info stm32h7_adc_trigs[] = {
{ TIM1_CH1, STM32_EXT0 },
{ TIM1_CH2, STM32_EXT1 },
{ TIM1_CH3, STM32_EXT2 },
@@ -469,7 +492,7 @@ static struct stm32_adc_trig_info stm32h7_adc_trigs[] = {
{ LPTIM1_OUT, STM32_EXT18 },
{ LPTIM2_OUT, STM32_EXT19 },
{ LPTIM3_OUT, STM32_EXT20 },
- {},
+ { }
};
/*
@@ -889,6 +912,56 @@ static void stm32mp13_adc_start_conv(struct iio_dev *indio_dev, bool dma)
stm32_adc_set_bits(adc, STM32H7_ADC_CR, STM32H7_ADSTART);
}
+static void stm32h7_adc_set_ovs(struct iio_dev *indio_dev, u32 ovs_idx)
+{
+ struct stm32_adc *adc = iio_priv(indio_dev);
+ u32 ovsr_bits, bits, msk;
+
+ msk = STM32H7_ROVSE | STM32H7_OVSR_MASK | STM32H7_OVSS_MASK;
+ stm32_adc_clr_bits(adc, STM32H7_ADC_CFGR2, msk);
+
+ if (!ovs_idx)
+ return;
+
+ /*
+ * Only the oversampling ratios corresponding to 2^ovs_idx are exposed in sysfs.
+ * Oversampling ratios [2,3,...,1024] are mapped on OVSR register values [1,2,...,1023].
+ * OVSR = 2^ovs_idx - 1
+ * These ratio increase the resolution by ovs_idx bits. Apply a right shift to keep initial
+ * resolution given by "assigned-resolution-bits" property.
+ * OVSS = ovs_idx
+ */
+ ovsr_bits = GENMASK(ovs_idx - 1, 0);
+ bits = STM32H7_ROVSE | STM32H7_OVSS(ovs_idx) | STM32H7_OVSR(ovsr_bits);
+
+ stm32_adc_set_bits(adc, STM32H7_ADC_CFGR2, bits & msk);
+}
+
+static void stm32mp13_adc_set_ovs(struct iio_dev *indio_dev, u32 ovs_idx)
+{
+ struct stm32_adc *adc = iio_priv(indio_dev);
+ u32 bits, msk;
+
+ msk = STM32H7_ROVSE | STM32MP13_OVSR_MASK | STM32MP13_OVSS_MASK;
+ stm32_adc_clr_bits(adc, STM32H7_ADC_CFGR2, msk);
+
+ if (!ovs_idx)
+ return;
+
+ /*
+ * The oversampling ratios [2,4,8,..,256] are mapped on OVSR register values [0,1,...,7].
+ * OVSR = ovs_idx - 1
+ * These ratio increase the resolution by ovs_idx bits. Apply a right shift to keep initial
+ * resolution given by "assigned-resolution-bits" property.
+ * OVSS = ovs_idx
+ */
+ bits = STM32H7_ROVSE | STM32MP13_OVSS(ovs_idx);
+ if (ovs_idx - 1)
+ bits |= STM32MP13_OVSR(ovs_idx - 1);
+
+ stm32_adc_set_bits(adc, STM32H7_ADC_CFGR2, bits & msk);
+}
+
static int stm32h7_adc_exit_pwr_down(struct iio_dev *indio_dev)
{
struct stm32_adc *adc = iio_priv(indio_dev);
@@ -1261,7 +1334,7 @@ static int stm32_adc_conf_scan_seq(struct iio_dev *indio_dev,
stm32_adc_writel(adc, adc->cfg->regs->smpr[0], adc->smpr_val[0]);
stm32_adc_writel(adc, adc->cfg->regs->smpr[1], adc->smpr_val[1]);
- for_each_set_bit(bit, scan_mask, indio_dev->masklength) {
+ for_each_set_bit(bit, scan_mask, iio_get_masklength(indio_dev)) {
chan = indio_dev->channels + bit;
/*
* Assign one channel per SQ entry in regular
@@ -1408,7 +1481,7 @@ static int stm32_adc_single_conv(struct iio_dev *indio_dev,
struct stm32_adc *adc = iio_priv(indio_dev);
struct device *dev = indio_dev->dev.parent;
const struct stm32_adc_regspec *regs = adc->cfg->regs;
- long timeout;
+ long time_left;
u32 val;
int ret;
@@ -1440,12 +1513,12 @@ static int stm32_adc_single_conv(struct iio_dev *indio_dev,
adc->cfg->start_conv(indio_dev, false);
- timeout = wait_for_completion_interruptible_timeout(
+ time_left = wait_for_completion_interruptible_timeout(
&adc->completion, STM32_ADC_TIMEOUT);
- if (timeout == 0) {
+ if (time_left == 0) {
ret = -ETIMEDOUT;
- } else if (timeout < 0) {
- ret = timeout;
+ } else if (time_left < 0) {
+ ret = time_left;
} else {
*res = adc->buffer[0];
ret = IIO_VAL_INT;
@@ -1455,12 +1528,71 @@ static int stm32_adc_single_conv(struct iio_dev *indio_dev,
stm32_adc_conv_irq_disable(adc);
- pm_runtime_mark_last_busy(dev);
pm_runtime_put_autosuspend(dev);
return ret;
}
+static int stm32_adc_write_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int val, int val2, long mask)
+{
+ struct stm32_adc *adc = iio_priv(indio_dev);
+ struct device *dev = indio_dev->dev.parent;
+ int nb = adc->cfg->adc_info->num_ovs;
+ unsigned int idx;
+ int ret;
+
+ switch (mask) {
+ case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
+ if (val2)
+ return -EINVAL;
+
+ for (idx = 0; idx < nb; idx++)
+ if (adc->cfg->adc_info->oversampling[idx] == val)
+ break;
+ if (idx >= nb)
+ return -EINVAL;
+
+ if (!iio_device_claim_direct(indio_dev))
+ return -EBUSY;
+
+ ret = pm_runtime_resume_and_get(dev);
+ if (ret < 0)
+ goto err;
+
+ adc->cfg->set_ovs(indio_dev, idx);
+
+ pm_runtime_put_autosuspend(dev);
+
+ adc->ovs_idx = idx;
+
+err:
+ iio_device_release_direct(indio_dev);
+
+ return ret;
+ default:
+ return -EINVAL;
+ }
+}
+
+static int stm32_adc_read_avail(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ const int **vals, int *type, int *length, long m)
+{
+ struct stm32_adc *adc = iio_priv(indio_dev);
+
+ switch (m) {
+ case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
+ *type = IIO_VAL_INT;
+ *length = adc->cfg->adc_info->num_ovs;
+ *vals = adc->cfg->adc_info->oversampling;
+ return IIO_AVAIL_LIST;
+ default:
+ return -EINVAL;
+ }
+}
+
static int stm32_adc_read_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int *val, int *val2, long mask)
@@ -1471,9 +1603,8 @@ static int stm32_adc_read_raw(struct iio_dev *indio_dev,
switch (mask) {
case IIO_CHAN_INFO_RAW:
case IIO_CHAN_INFO_PROCESSED:
- ret = iio_device_claim_direct_mode(indio_dev);
- if (ret)
- return ret;
+ if (!iio_device_claim_direct(indio_dev))
+ return -EBUSY;
if (chan->type == IIO_VOLTAGE)
ret = stm32_adc_single_conv(indio_dev, chan, val);
else
@@ -1482,7 +1613,7 @@ static int stm32_adc_read_raw(struct iio_dev *indio_dev,
if (mask == IIO_CHAN_INFO_PROCESSED)
*val = STM32_ADC_VREFINT_VOLTAGE * adc->vrefint.vrefint_cal / *val;
- iio_device_release_direct_mode(indio_dev);
+ iio_device_release_direct(indio_dev);
return ret;
case IIO_CHAN_INFO_SCALE:
@@ -1503,6 +1634,10 @@ static int stm32_adc_read_raw(struct iio_dev *indio_dev,
*val = 0;
return IIO_VAL_INT;
+ case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
+ *val = adc->cfg->adc_info->oversampling[adc->ovs_idx];
+ return IIO_VAL_INT;
+
default:
return -EINVAL;
}
@@ -1619,10 +1754,9 @@ static int stm32_adc_update_scan_mode(struct iio_dev *indio_dev,
if (ret < 0)
return ret;
- adc->num_conv = bitmap_weight(scan_mask, indio_dev->masklength);
+ adc->num_conv = bitmap_weight(scan_mask, iio_get_masklength(indio_dev));
ret = stm32_adc_conf_scan_seq(indio_dev, scan_mask);
- pm_runtime_mark_last_busy(dev);
pm_runtime_put_autosuspend(dev);
return ret;
@@ -1671,7 +1805,6 @@ static int stm32_adc_debugfs_reg_access(struct iio_dev *indio_dev,
else
*readval = stm32_adc_readl(adc, reg);
- pm_runtime_mark_last_busy(dev);
pm_runtime_put_autosuspend(dev);
return 0;
@@ -1679,6 +1812,8 @@ static int stm32_adc_debugfs_reg_access(struct iio_dev *indio_dev,
static const struct iio_info stm32_adc_iio_info = {
.read_raw = stm32_adc_read_raw,
+ .write_raw = stm32_adc_write_raw,
+ .read_avail = stm32_adc_read_avail,
.validate_trigger = stm32_adc_validate_trigger,
.hwfifo_set_watermark = stm32_adc_set_watermark,
.update_scan_mode = stm32_adc_update_scan_mode,
@@ -1815,7 +1950,6 @@ static int stm32_adc_buffer_postenable(struct iio_dev *indio_dev)
err_clr_trig:
stm32_adc_set_trig(indio_dev, NULL);
err_pm_put:
- pm_runtime_mark_last_busy(dev);
pm_runtime_put_autosuspend(dev);
return ret;
@@ -1838,7 +1972,6 @@ static int stm32_adc_buffer_predisable(struct iio_dev *indio_dev)
if (stm32_adc_set_trig(indio_dev, NULL))
dev_err(&indio_dev->dev, "Can't clear trigger\n");
- pm_runtime_mark_last_busy(dev);
pm_runtime_put_autosuspend(dev);
return 0;
@@ -1859,8 +1992,8 @@ static irqreturn_t stm32_adc_trigger_handler(int irq, void *p)
/* reset buffer index */
adc->bufi = 0;
- iio_push_to_buffers_with_timestamp(indio_dev, adc->buffer,
- pf->timestamp);
+ iio_push_to_buffers_with_ts(indio_dev, adc->buffer, sizeof(adc->buffer),
+ pf->timestamp);
iio_trigger_notify_done(indio_dev->trig);
/* re-enable eoc irq */
@@ -1877,7 +2010,7 @@ static const struct iio_chan_spec_ext_info stm32_adc_ext_info[] = {
.read = iio_enum_available_read,
.private = (uintptr_t)&stm32_adc_trig_pol,
},
- {},
+ { }
};
static void stm32_adc_debugfs_init(struct iio_dev *indio_dev)
@@ -1972,6 +2105,10 @@ static void stm32_adc_chan_init_one(struct iio_dev *indio_dev,
chan->info_mask_separate = BIT(IIO_CHAN_INFO_RAW);
chan->info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) |
BIT(IIO_CHAN_INFO_OFFSET);
+ if (adc->cfg->has_oversampling) {
+ chan->info_mask_shared_by_all |= BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO);
+ chan->info_mask_shared_by_all_available = BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO);
+ }
chan->scan_type.sign = 'u';
chan->scan_type.realbits = adc->cfg->adc_info->resolutions[adc->res];
chan->scan_type.storagebits = 16;
@@ -1993,6 +2130,8 @@ static int stm32_adc_get_legacy_chan_count(struct iio_dev *indio_dev, struct stm
const struct stm32_adc_info *adc_info = adc->cfg->adc_info;
int num_channels = 0, ret;
+ dev_dbg(&indio_dev->dev, "using legacy channel config\n");
+
ret = device_property_count_u32(dev, "st,adc-channels");
if (ret > adc_info->max_channels) {
dev_err(&indio_dev->dev, "Bad st,adc-channels?\n");
@@ -2006,16 +2145,15 @@ static int stm32_adc_get_legacy_chan_count(struct iio_dev *indio_dev, struct stm
* to get the *real* number of channels.
*/
ret = device_property_count_u32(dev, "st,adc-diff-channels");
- if (ret < 0)
- return ret;
-
- ret /= (int)(sizeof(struct stm32_adc_diff_channel) / sizeof(u32));
- if (ret > adc_info->max_channels) {
- dev_err(&indio_dev->dev, "Bad st,adc-diff-channels?\n");
- return -EINVAL;
- } else if (ret > 0) {
- adc->num_diff = ret;
- num_channels += ret;
+ if (ret > 0) {
+ ret /= (int)(sizeof(struct stm32_adc_diff_channel) / sizeof(u32));
+ if (ret > adc_info->max_channels) {
+ dev_err(&indio_dev->dev, "Bad st,adc-diff-channels?\n");
+ return -EINVAL;
+ } else if (ret > 0) {
+ adc->num_diff = ret;
+ num_channels += ret;
+ }
}
/* Optional sample time is provided either for each, or all channels */
@@ -2037,6 +2175,7 @@ static int stm32_adc_legacy_chan_init(struct iio_dev *indio_dev,
struct stm32_adc_diff_channel diff[STM32_ADC_CH_MAX];
struct device *dev = &indio_dev->dev;
u32 num_diff = adc->num_diff;
+ int num_se = nchans - num_diff;
int size = num_diff * sizeof(*diff) / sizeof(u32);
int scan_index = 0, ret, i, c;
u32 smp = 0, smps[STM32_ADC_CH_MAX], chans[STM32_ADC_CH_MAX];
@@ -2063,29 +2202,32 @@ static int stm32_adc_legacy_chan_init(struct iio_dev *indio_dev,
scan_index++;
}
}
-
- ret = device_property_read_u32_array(dev, "st,adc-channels", chans,
- nchans);
- if (ret)
- return ret;
-
- for (c = 0; c < nchans; c++) {
- if (chans[c] >= adc_info->max_channels) {
- dev_err(&indio_dev->dev, "Invalid channel %d\n",
- chans[c]);
- return -EINVAL;
+ if (num_se > 0) {
+ ret = device_property_read_u32_array(dev, "st,adc-channels", chans, num_se);
+ if (ret) {
+ dev_err(&indio_dev->dev, "Failed to get st,adc-channels %d\n", ret);
+ return ret;
}
- /* Channel can't be configured both as single-ended & diff */
- for (i = 0; i < num_diff; i++) {
- if (chans[c] == diff[i].vinp) {
- dev_err(&indio_dev->dev, "channel %d misconfigured\n", chans[c]);
+ for (c = 0; c < num_se; c++) {
+ if (chans[c] >= adc_info->max_channels) {
+ dev_err(&indio_dev->dev, "Invalid channel %d\n",
+ chans[c]);
return -EINVAL;
}
+
+ /* Channel can't be configured both as single-ended & diff */
+ for (i = 0; i < num_diff; i++) {
+ if (chans[c] == diff[i].vinp) {
+ dev_err(&indio_dev->dev, "channel %d misconfigured\n",
+ chans[c]);
+ return -EINVAL;
+ }
+ }
+ stm32_adc_chan_init_one(indio_dev, &channels[scan_index],
+ chans[c], 0, scan_index, false);
+ scan_index++;
}
- stm32_adc_chan_init_one(indio_dev, &channels[scan_index],
- chans[c], 0, scan_index, false);
- scan_index++;
}
if (adc->nsmps > 0) {
@@ -2182,58 +2324,52 @@ static int stm32_adc_generic_chan_init(struct iio_dev *indio_dev,
struct iio_chan_spec *channels)
{
const struct stm32_adc_info *adc_info = adc->cfg->adc_info;
- struct fwnode_handle *child;
+ struct device *dev = &indio_dev->dev;
const char *name;
int val, scan_index = 0, ret;
bool differential;
u32 vin[2];
- device_for_each_child_node(&indio_dev->dev, child) {
+ device_for_each_child_node_scoped(dev, child) {
ret = fwnode_property_read_u32(child, "reg", &val);
- if (ret) {
- dev_err(&indio_dev->dev, "Missing channel index %d\n", ret);
- goto err;
- }
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "Missing channel index\n");
ret = fwnode_property_read_string(child, "label", &name);
/* label is optional */
if (!ret) {
- if (strlen(name) >= STM32_ADC_CH_SZ) {
- dev_err(&indio_dev->dev, "Label %s exceeds %d characters\n",
- name, STM32_ADC_CH_SZ);
- ret = -EINVAL;
- goto err;
- }
- strncpy(adc->chan_name[val], name, STM32_ADC_CH_SZ);
+ if (strlen(name) >= STM32_ADC_CH_SZ)
+ return dev_err_probe(dev, -EINVAL,
+ "Label %s exceeds %d characters\n",
+ name, STM32_ADC_CH_SZ);
+
+ strscpy(adc->chan_name[val], name, STM32_ADC_CH_SZ);
ret = stm32_adc_populate_int_ch(indio_dev, name, val);
if (ret == -ENOENT)
continue;
else if (ret)
- goto err;
+ return ret;
} else if (ret != -EINVAL) {
- dev_err(&indio_dev->dev, "Invalid label %d\n", ret);
- goto err;
+ return dev_err_probe(dev, ret, "Invalid label\n");
}
- if (val >= adc_info->max_channels) {
- dev_err(&indio_dev->dev, "Invalid channel %d\n", val);
- ret = -EINVAL;
- goto err;
- }
+ if (val >= adc_info->max_channels)
+ return dev_err_probe(dev, -EINVAL,
+ "Invalid channel %d\n", val);
differential = false;
ret = fwnode_property_read_u32_array(child, "diff-channels", vin, 2);
/* diff-channels is optional */
if (!ret) {
differential = true;
- if (vin[0] != val || vin[1] >= adc_info->max_channels) {
- dev_err(&indio_dev->dev, "Invalid channel in%d-in%d\n",
- vin[0], vin[1]);
- goto err;
- }
+ if (vin[0] != val || vin[1] >= adc_info->max_channels)
+ return dev_err_probe(dev, -EINVAL,
+ "Invalid channel in%d-in%d\n",
+ vin[0], vin[1]);
} else if (ret != -EINVAL) {
- dev_err(&indio_dev->dev, "Invalid diff-channels property %d\n", ret);
- goto err;
+ return dev_err_probe(dev, ret,
+ "Invalid diff-channels property\n");
}
stm32_adc_chan_init_one(indio_dev, &channels[scan_index], val,
@@ -2242,11 +2378,9 @@ static int stm32_adc_generic_chan_init(struct iio_dev *indio_dev,
val = 0;
ret = fwnode_property_read_u32(child, "st,min-sample-time-ns", &val);
/* st,min-sample-time-ns is optional */
- if (ret && ret != -EINVAL) {
- dev_err(&indio_dev->dev, "Invalid st,min-sample-time-ns property %d\n",
- ret);
- goto err;
- }
+ if (ret && ret != -EINVAL)
+ return dev_err_probe(dev, ret,
+ "Invalid st,min-sample-time-ns property\n");
stm32_adc_smpr_init(adc, channels[scan_index].channel, val);
if (differential)
@@ -2256,11 +2390,6 @@ static int stm32_adc_generic_chan_init(struct iio_dev *indio_dev,
}
return scan_index;
-
-err:
- fwnode_handle_put(child);
-
- return ret;
}
static int stm32_adc_chan_fw_init(struct iio_dev *indio_dev, bool timestamping)
@@ -2306,7 +2435,7 @@ static int stm32_adc_chan_fw_init(struct iio_dev *indio_dev, bool timestamping)
if (legacy)
ret = stm32_adc_legacy_chan_init(indio_dev, adc, channels,
- num_channels);
+ timestamping ? num_channels - 1 : num_channels);
else
ret = stm32_adc_generic_chan_init(indio_dev, adc, channels);
if (ret < 0)
@@ -2335,7 +2464,7 @@ static int stm32_adc_chan_fw_init(struct iio_dev *indio_dev, bool timestamping)
static int stm32_adc_dma_request(struct device *dev, struct iio_dev *indio_dev)
{
struct stm32_adc *adc = iio_priv(indio_dev);
- struct dma_slave_config config;
+ struct dma_slave_config config = { };
int ret;
adc->dma_chan = dma_request_chan(dev, "rx");
@@ -2359,7 +2488,6 @@ static int stm32_adc_dma_request(struct device *dev, struct iio_dev *indio_dev)
}
/* Configure DMA channel to read data register */
- memset(&config, 0, sizeof(config));
config.src_addr = (dma_addr_t)adc->common->phys_base;
config.src_addr += adc->offset + adc->cfg->regs->dr;
config.src_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
@@ -2480,7 +2608,6 @@ static int stm32_adc_probe(struct platform_device *pdev)
goto err_hw_stop;
}
- pm_runtime_mark_last_busy(dev);
pm_runtime_put_autosuspend(dev);
if (IS_ENABLED(CONFIG_DEBUG_FS))
@@ -2508,7 +2635,7 @@ err_dma_disable:
return ret;
}
-static int stm32_adc_remove(struct platform_device *pdev)
+static void stm32_adc_remove(struct platform_device *pdev)
{
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
struct stm32_adc *adc = iio_priv(indio_dev);
@@ -2527,8 +2654,6 @@ static int stm32_adc_remove(struct platform_device *pdev)
adc->rx_buf, adc->rx_dma_buf);
dma_release_channel(adc->dma_chan);
}
-
- return 0;
}
static int stm32_adc_suspend(struct device *dev)
@@ -2598,6 +2723,7 @@ static const struct stm32_adc_cfg stm32h7_adc_cfg = {
.has_boostmode = true,
.has_linearcal = true,
.has_presel = true,
+ .has_oversampling = true,
.start_conv = stm32h7_adc_start_conv,
.stop_conv = stm32h7_adc_stop_conv,
.prepare = stm32h7_adc_prepare,
@@ -2605,6 +2731,7 @@ static const struct stm32_adc_cfg stm32h7_adc_cfg = {
.smp_cycles = stm32h7_adc_smp_cycles,
.irq_clear = stm32h7_adc_irq_clear,
.ts_int_ch = stm32_adc_min_ts_h7,
+ .set_ovs = stm32h7_adc_set_ovs,
};
static const unsigned int stm32_adc_min_ts_mp1[] = { 100, 100, 100, 4300, 9800 };
@@ -2618,6 +2745,7 @@ static const struct stm32_adc_cfg stm32mp1_adc_cfg = {
.has_boostmode = true,
.has_linearcal = true,
.has_presel = true,
+ .has_oversampling = true,
.start_conv = stm32h7_adc_start_conv,
.stop_conv = stm32h7_adc_stop_conv,
.prepare = stm32h7_adc_prepare,
@@ -2625,6 +2753,7 @@ static const struct stm32_adc_cfg stm32mp1_adc_cfg = {
.smp_cycles = stm32h7_adc_smp_cycles,
.irq_clear = stm32h7_adc_irq_clear,
.ts_int_ch = stm32_adc_min_ts_mp1,
+ .set_ovs = stm32h7_adc_set_ovs,
};
static const unsigned int stm32_adc_min_ts_mp13[] = { 100, 0, 0, 4300, 9800 };
@@ -2634,6 +2763,7 @@ static const struct stm32_adc_cfg stm32mp13_adc_cfg = {
.regs = &stm32mp13_adc_regspec,
.adc_info = &stm32mp13_adc_info,
.trigs = stm32h7_adc_trigs,
+ .has_oversampling = true,
.start_conv = stm32mp13_adc_start_conv,
.stop_conv = stm32h7_adc_stop_conv,
.prepare = stm32h7_adc_prepare,
@@ -2641,6 +2771,7 @@ static const struct stm32_adc_cfg stm32mp13_adc_cfg = {
.smp_cycles = stm32mp13_adc_smp_cycles,
.irq_clear = stm32h7_adc_irq_clear,
.ts_int_ch = stm32_adc_min_ts_mp13,
+ .set_ovs = stm32mp13_adc_set_ovs,
};
static const struct of_device_id stm32_adc_of_match[] = {
@@ -2648,7 +2779,7 @@ static const struct of_device_id stm32_adc_of_match[] = {
{ .compatible = "st,stm32h7-adc", .data = (void *)&stm32h7_adc_cfg },
{ .compatible = "st,stm32mp1-adc", .data = (void *)&stm32mp1_adc_cfg },
{ .compatible = "st,stm32mp13-adc", .data = (void *)&stm32mp13_adc_cfg },
- {},
+ { }
};
MODULE_DEVICE_TABLE(of, stm32_adc_of_match);