struct sun20i_gpadc_iio { void __iomem *regs; struct completion completion; int last_channel; /* * Lock to protect the device state during a potential concurrent * read access from userspace. Reading a raw value requires a sequence * of register writes, then a wait for a completion callback, * and finally a register read, during which userspace could issue * another read request. This lock protects a read access from * ocurring before another one has finished.
*/ struct mutex lock;
};
staticint sun20i_gpadc_adc_read(struct sun20i_gpadc_iio *info, struct iio_chan_spec const *chan, int *val)
{
u32 ctrl; int ret = IIO_VAL_INT;
mutex_lock(&info->lock);
reinit_completion(&info->completion);
if (info->last_channel != chan->channel) {
info->last_channel = chan->channel;
/* enable the analog input channel */
writel(SUN20I_GPADC_CS_EN_ADC_CH(chan->channel),
info->regs + SUN20I_GPADC_CS_EN);
/* enable the data irq for input channel */
writel(SUN20I_GPADC_DATA_INTC_CH_DATA_IRQ_EN(chan->channel),
info->regs + SUN20I_GPADC_DATA_INTC);
}
/* enable the ADC function */
ctrl = readl(info->regs + SUN20I_GPADC_CTRL);
ctrl |= FIELD_PREP(SUN20I_GPADC_CTRL_ADC_EN_MASK, 1);
writel(ctrl, info->regs + SUN20I_GPADC_CTRL);
/* * According to the datasheet maximum acquire time(TACQ) can be * (65535+1)/24Mhz and conversion time(CONV_TIME) is always constant * and equal to 14/24Mhz, so (TACQ+CONV_TIME) <= 2.73125ms. * A 10ms delay should be enough to make sure an interrupt occurs in * normal conditions. If it doesn't occur, then there is a timeout.
*/ if (!wait_for_completion_timeout(&info->completion, msecs_to_jiffies(10))) {
ret = -ETIMEDOUT; goto err_unlock;
}
/* read the ADC data */
*val = readl(info->regs + SUN20I_GPADC_CH_DATA(chan->channel));
err_unlock:
mutex_unlock(&info->lock);
return ret;
}
staticint sun20i_gpadc_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int *val, int *val2, long mask)
{ struct sun20i_gpadc_iio *info = iio_priv(indio_dev);
switch (mask) { case IIO_CHAN_INFO_RAW: return sun20i_gpadc_adc_read(info, chan, val); case IIO_CHAN_INFO_SCALE: /* value in mv = 1800mV / 4096 raw */
*val = 1800;
*val2 = 12; return IIO_VAL_FRACTIONAL_LOG2; default: return -EINVAL;
}
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.