[PATCH v4 3/3] iio: adc: mt6360: Add ADC driver for MT6360
Jonathan Cameron
jic23 at kernel.org
Sat Sep 19 09:20:05 EDT 2020
On Fri, 18 Sep 2020 16:04:43 +0800
Gene Chen <gene.chen.richtek at gmail.com> wrote:
> Jonathan Cameron <jic23 at kernel.org> 於 2020年9月18日 週五 上午1:53寫道:
> >
> > On Wed, 16 Sep 2020 01:36:09 +0800
> > Gene Chen <gene.chen.richtek at gmail.com> wrote:
> >
> > > From: Gene Chen <gene_chen at richtek.com>
> > >
> > > Add MT6360 ADC driver include Charger Current, Voltage, and
> > > Temperature.
> > >
> > > Signed-off-by: Gene Chen <gene_chen at richtek.com>
> > Comments inline.
...
> > > + if (ret)
> > > + goto out_adc_lock;
> > > +
> > > + start_t = ktime_get();
> > > + predict_end_t = ktime_add_ms(mad->last_off_timestamps[channel], 2 * ADC_WAIT_TIME_MS);
> > > +
> > > + if (ktime_after(start_t, predict_end_t))
> > > + pre_wait_time = ADC_WAIT_TIME_MS;
> > > + else
> > > + pre_wait_time = 3 * ADC_WAIT_TIME_MS;
> > > +
> > > + msleep(pre_wait_time);
> > > +
> > > + while (true) {
> > > + ret = regmap_raw_read(mad->regmap, MT6360_REG_PMUADCRPT1, rpt, sizeof(rpt));
> > > + if (ret)
> > > + goto out_adc_conv;
> > > +
> > > + /*
> > > + * There are two functions, ZCV and TypeC OTP, running ADC VBAT and TS in
> > > + * background, and ADC samples are taken on a fixed frequency no matter read the
> > > + * previous one or not.
> > > + * To avoid conflict, We set minimum time threshold after enable ADC and
> > > + * check report channel is the same.
> > > + * The worst case is run the same ADC twice and background function is also running,
> > > + * ADC conversion sequence is desire channel before start ADC, background ADC,
> > > + * desire channel after start ADC.
> > > + * So the minimum correct data is three times of typical conversion time.
> > > + */
> > > + if ((rpt[0] & MT6360_RPTCH_MASK) == channel)
> > > + break;
> > > +
> > > + msleep(ADC_WAIT_TIME_MS);
> > > + }
> > > +
> > > + /* rpt[1]: ADC_HI_BYTE, rpt[2]: ADC_LOW_BYTE */
> > > + *val = be16_to_cpup((__be16 *)(rpt + 1));
> >
> > To be entirely safe, probably need that to be an unaligned read?
> >
>
> Maybe I can change to "*val = rpt[1] << 8 | rpt[2];".
> It's more abvious.
That would definitely be safe so do that.
>
> > > + ret = IIO_VAL_INT;
> > > +
> > > +out_adc_conv:
> > > + /* Only keep ADC enable */
> > > + adc_enable = cpu_to_be16(MT6360_ADCEN_MASK);
> > > + regmap_raw_write(mad->regmap, MT6360_REG_PMUADCCFG, (void *)&adc_enable, sizeof(__be16));
> >
> > sizeof(adc_enable)
> >
>
> ACK
>
> > > + mad->last_off_timestamps[channel] = ktime_get();
> > > + /* Config prefer channel to NO_PREFER */
> > > + regmap_update_bits(mad->regmap, MT6360_REG_PMUADCRPT1, MT6360_PREFERCH_MASK,
> > > + MT6360_NO_PREFER << MT6360_PREFERCH_SHFT);
> > > +out_adc_lock:
> > > + mutex_unlock(&mad->adc_lock);
> > > +
> > > + return ret;
> > > +}
> > > +
> > > +static int mt6360_adc_read_scale(struct mt6360_adc_data *mad, int channel, int *val, int *val2)
> > > +{
> > > + unsigned int regval;
> > > + int ret;
> > > +
> > > + switch (channel) {
> > > + case MT6360_CHAN_USBID:
> > > + fallthrough;
> >
> > I don't think we need fallthrough for cases
> > with nothing in them.
> >
>
> Every channel needs set " *val = 2500" for scale.
> Do you mean change as below?
>
> switch (channel) {
> case MT6360_CHAN_USBID:
> case MT6360_CHAN_VSYS:
> case MT6360_CHAN_VBAT:
> case MT6360_CHAN_CHG_VDDP:
> case MT6360_CHAN_VREF_TS:
> fallthrough;
Don't need this fallthrough.
fallthrough is only needed if something is done in the
case statement. I believe the checker is clever enough to
assume that a set of case statements with nothing inbetween
them are deliberate.
> case MT6360_CHAN_TS:
> *val = 1250;
> return IIO_VAL_INT;
>
...
> > > +
> > > +static irqreturn_t mt6360_adc_trigger_handler(int irq, void *p)
> > > +{
> > > + struct iio_poll_func *pf = p;
> > > + struct iio_dev *indio_dev = pf->indio_dev;
> > > + struct mt6360_adc_data *mad = iio_priv(indio_dev);
> > > + struct {
> > > + u16 values[MT6360_CHAN_MAX];
> >
> > There is a hole in here I think? (MT6360_CHAN_MAX is 11?)
> > If so we need to explicitly memset the structure to avoid any
> > risk of kernel data leakage to userspace.
Make sure you deal with this in v5!
> >
> > > + int64_t timestamp;
> > > + } data;
> >
> > I guess we know this is on a platform with 64bit alignment for int64_t's
> > (unlike x86_64 for example)
> >
>
> Do you mean change as below?
> struct {
> u16 values[MT6360_CHAN_MAX];
> int64_t timestamp; __aligned(8)
> } data;
You can do that, or we can rely on the fact this part is never used
on a platform where that isn't guaranteed anyway.
>
> > > + int i = 0, bit, val, ret;
...
More information about the Linux-mediatek
mailing list