|
@@ -60,6 +60,24 @@ static u32 get_adc_step_mask(struct tiadc_device *adc_dev)
|
|
return step_en;
|
|
return step_en;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static u32 get_adc_chan_step_mask(struct tiadc_device *adc_dev,
|
|
|
|
+ struct iio_chan_spec const *chan)
|
|
|
|
+{
|
|
|
|
+ int i;
|
|
|
|
+
|
|
|
|
+ for (i = 0; i < ARRAY_SIZE(adc_dev->channel_step); i++) {
|
|
|
|
+ if (chan->channel == adc_dev->channel_line[i]) {
|
|
|
|
+ u32 step;
|
|
|
|
+
|
|
|
|
+ step = adc_dev->channel_step[i];
|
|
|
|
+ /* +1 for the charger */
|
|
|
|
+ return 1 << (step + 1);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ WARN_ON(1);
|
|
|
|
+ return 0;
|
|
|
|
+}
|
|
|
|
+
|
|
static u32 get_adc_step_bit(struct tiadc_device *adc_dev, int chan)
|
|
static u32 get_adc_step_bit(struct tiadc_device *adc_dev, int chan)
|
|
{
|
|
{
|
|
return 1 << adc_dev->channel_step[chan];
|
|
return 1 << adc_dev->channel_step[chan];
|
|
@@ -181,7 +199,7 @@ static int tiadc_buffer_postenable(struct iio_dev *indio_dev)
|
|
enb |= (get_adc_step_bit(adc_dev, bit) << 1);
|
|
enb |= (get_adc_step_bit(adc_dev, bit) << 1);
|
|
adc_dev->buffer_en_ch_steps = enb;
|
|
adc_dev->buffer_en_ch_steps = enb;
|
|
|
|
|
|
- am335x_tsc_se_set(adc_dev->mfd_tscadc, enb);
|
|
|
|
|
|
+ am335x_tsc_se_set_cache(adc_dev->mfd_tscadc, enb);
|
|
|
|
|
|
tiadc_writel(adc_dev, REG_IRQSTATUS, IRQENB_FIFO1THRES
|
|
tiadc_writel(adc_dev, REG_IRQSTATUS, IRQENB_FIFO1THRES
|
|
| IRQENB_FIFO1OVRRUN | IRQENB_FIFO1UNDRFLW);
|
|
| IRQENB_FIFO1OVRRUN | IRQENB_FIFO1UNDRFLW);
|
|
@@ -199,6 +217,7 @@ static int tiadc_buffer_predisable(struct iio_dev *indio_dev)
|
|
tiadc_writel(adc_dev, REG_IRQCLR, (IRQENB_FIFO1THRES |
|
|
tiadc_writel(adc_dev, REG_IRQCLR, (IRQENB_FIFO1THRES |
|
|
IRQENB_FIFO1OVRRUN | IRQENB_FIFO1UNDRFLW));
|
|
IRQENB_FIFO1OVRRUN | IRQENB_FIFO1UNDRFLW));
|
|
am335x_tsc_se_clr(adc_dev->mfd_tscadc, adc_dev->buffer_en_ch_steps);
|
|
am335x_tsc_se_clr(adc_dev->mfd_tscadc, adc_dev->buffer_en_ch_steps);
|
|
|
|
+ adc_dev->buffer_en_ch_steps = 0;
|
|
|
|
|
|
/* Flush FIFO of leftover data in the time it takes to disable adc */
|
|
/* Flush FIFO of leftover data in the time it takes to disable adc */
|
|
fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT);
|
|
fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT);
|
|
@@ -328,34 +347,43 @@ static int tiadc_read_raw(struct iio_dev *indio_dev,
|
|
unsigned int fifo1count, read, stepid;
|
|
unsigned int fifo1count, read, stepid;
|
|
bool found = false;
|
|
bool found = false;
|
|
u32 step_en;
|
|
u32 step_en;
|
|
- unsigned long timeout = jiffies + usecs_to_jiffies
|
|
|
|
- (IDLE_TIMEOUT * adc_dev->channels);
|
|
|
|
|
|
+ unsigned long timeout;
|
|
|
|
|
|
if (iio_buffer_enabled(indio_dev))
|
|
if (iio_buffer_enabled(indio_dev))
|
|
return -EBUSY;
|
|
return -EBUSY;
|
|
|
|
|
|
- step_en = get_adc_step_mask(adc_dev);
|
|
|
|
- am335x_tsc_se_set(adc_dev->mfd_tscadc, step_en);
|
|
|
|
|
|
+ step_en = get_adc_chan_step_mask(adc_dev, chan);
|
|
|
|
+ if (!step_en)
|
|
|
|
+ return -EINVAL;
|
|
|
|
+
|
|
|
|
+ fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT);
|
|
|
|
+ while (fifo1count--)
|
|
|
|
+ tiadc_readl(adc_dev, REG_FIFO1);
|
|
|
|
+
|
|
|
|
+ am335x_tsc_se_set_once(adc_dev->mfd_tscadc, step_en);
|
|
|
|
|
|
- /* Wait for ADC sequencer to complete sampling */
|
|
|
|
- while (tiadc_readl(adc_dev, REG_ADCFSM) & SEQ_STATUS) {
|
|
|
|
- if (time_after(jiffies, timeout))
|
|
|
|
|
|
+ timeout = jiffies + usecs_to_jiffies
|
|
|
|
+ (IDLE_TIMEOUT * adc_dev->channels);
|
|
|
|
+ /* Wait for Fifo threshold interrupt */
|
|
|
|
+ while (1) {
|
|
|
|
+ fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT);
|
|
|
|
+ if (fifo1count)
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ if (time_after(jiffies, timeout)) {
|
|
|
|
+ am335x_tsc_se_adc_done(adc_dev->mfd_tscadc);
|
|
return -EAGAIN;
|
|
return -EAGAIN;
|
|
}
|
|
}
|
|
|
|
+ }
|
|
map_val = chan->channel + TOTAL_CHANNELS;
|
|
map_val = chan->channel + TOTAL_CHANNELS;
|
|
|
|
|
|
/*
|
|
/*
|
|
- * When the sub-system is first enabled,
|
|
|
|
- * the sequencer will always start with the
|
|
|
|
- * lowest step (1) and continue until step (16).
|
|
|
|
- * For ex: If we have enabled 4 ADC channels and
|
|
|
|
- * currently use only 1 out of them, the
|
|
|
|
- * sequencer still configures all the 4 steps,
|
|
|
|
- * leading to 3 unwanted data.
|
|
|
|
- * Hence we need to flush out this data.
|
|
|
|
|
|
+ * We check the complete FIFO. We programmed just one entry but in case
|
|
|
|
+ * something went wrong we left empty handed (-EAGAIN previously) and
|
|
|
|
+ * then the value apeared somehow in the FIFO we would have two entries.
|
|
|
|
+ * Therefore we read every item and keep only the latest version of the
|
|
|
|
+ * requested channel.
|
|
*/
|
|
*/
|
|
-
|
|
|
|
- fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT);
|
|
|
|
for (i = 0; i < fifo1count; i++) {
|
|
for (i = 0; i < fifo1count; i++) {
|
|
read = tiadc_readl(adc_dev, REG_FIFO1);
|
|
read = tiadc_readl(adc_dev, REG_FIFO1);
|
|
stepid = read & FIFOREAD_CHNLID_MASK;
|
|
stepid = read & FIFOREAD_CHNLID_MASK;
|
|
@@ -367,6 +395,7 @@ static int tiadc_read_raw(struct iio_dev *indio_dev,
|
|
*val = (u16) read;
|
|
*val = (u16) read;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
+ am335x_tsc_se_adc_done(adc_dev->mfd_tscadc);
|
|
|
|
|
|
if (found == false)
|
|
if (found == false)
|
|
return -EBUSY;
|
|
return -EBUSY;
|
|
@@ -494,7 +523,8 @@ static int tiadc_resume(struct device *dev)
|
|
tiadc_writel(adc_dev, REG_CTRL, restore);
|
|
tiadc_writel(adc_dev, REG_CTRL, restore);
|
|
|
|
|
|
tiadc_step_config(indio_dev);
|
|
tiadc_step_config(indio_dev);
|
|
-
|
|
|
|
|
|
+ am335x_tsc_se_set_cache(adc_dev->mfd_tscadc,
|
|
|
|
+ adc_dev->buffer_en_ch_steps);
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|