diff --git a/Documentation/devicetree/bindings/input/touchscreen/ti-tsc-adc.txt b/Documentation/devicetree/bindings/input/touchscreen/ti-tsc-adc.txt index 6c4fb34823d3..b1163bf97146 100644 --- a/Documentation/devicetree/bindings/input/touchscreen/ti-tsc-adc.txt +++ b/Documentation/devicetree/bindings/input/touchscreen/ti-tsc-adc.txt @@ -42,6 +42,27 @@ Optional properties: hardware knob for adjusting the amount of "settling time". +- child "adc" + ti,chan-step-opendelay: List of open delays for each channel of + ADC in the order of ti,adc-channels. The + value corresponds to the number of ADC + clock cycles to wait after applying the + step configuration registers and before + sending the start of ADC conversion. + Maximum value is 0x3FFFF. + ti,chan-step-sampledelay: List of sample delays for each channel + of ADC in the order of ti,adc-channels. + The value corresponds to the number of + ADC clock cycles to sample (to hold + start of conversion high). + Maximum value is 0xFF. + ti,chan-step-avg: Number of averages to be performed for each + channel of ADC. If average is 16 then input + is sampled 16 times and averaged to get more + accurate value. This increases the time taken + by ADC to generate a sample. Valid range is 0 + average to 16 averages. Maximum value is 16. + Example: tscadc: tscadc@44e0d000 { compatible = "ti,am3359-tscadc"; @@ -55,5 +76,8 @@ Example: adc { ti,adc-channels = <4 5 6 7>; + ti,chan-step-opendelay = <0x098 0x3ffff 0x098 0x0>; + ti,chan-step-sampledelay = <0xff 0x0 0xf 0x0>; + ti,chan-step-avg = <16 2 4 8>; }; } diff --git a/drivers/iio/adc/ti_am335x_adc.c b/drivers/iio/adc/ti_am335x_adc.c index 42e444044ea5..942320e32753 100644 --- a/drivers/iio/adc/ti_am335x_adc.c +++ b/drivers/iio/adc/ti_am335x_adc.c @@ -37,6 +37,7 @@ struct tiadc_device { u8 channel_step[8]; int buffer_en_ch_steps; u16 data[8]; + u32 open_delay[8], sample_delay[8], step_avg[8]; }; static unsigned int tiadc_readl(struct tiadc_device *adc, unsigned int reg) @@ -85,6 +86,7 @@ static u32 get_adc_step_bit(struct tiadc_device *adc_dev, int chan) static void tiadc_step_config(struct iio_dev *indio_dev) { struct tiadc_device *adc_dev = iio_priv(indio_dev); + struct device *dev = adc_dev->mfd_tscadc->dev; unsigned int stepconfig; int i, steps = 0; @@ -98,20 +100,47 @@ static void tiadc_step_config(struct iio_dev *indio_dev) * needs to be given to ADC to digitalize data. */ - if (iio_buffer_enabled(indio_dev)) - stepconfig = STEPCONFIG_AVG_16 | STEPCONFIG_FIFO1 - | STEPCONFIG_MODE_SWCNT; - else - stepconfig = STEPCONFIG_AVG_16 | STEPCONFIG_FIFO1; for (i = 0; i < adc_dev->channels; i++) { int chan; chan = adc_dev->channel_line[i]; + + if (adc_dev->step_avg[i] > STEPCONFIG_AVG_16) { + dev_warn(dev, "chan %d step_avg truncating to %d\n", + chan, STEPCONFIG_AVG_16); + adc_dev->step_avg[i] = STEPCONFIG_AVG_16; + } + + if (adc_dev->step_avg[i]) + stepconfig = + STEPCONFIG_AVG(ffs(adc_dev->step_avg[i]) - 1) | + STEPCONFIG_FIFO1; + else + stepconfig = STEPCONFIG_FIFO1; + + if (iio_buffer_enabled(indio_dev)) + stepconfig |= STEPCONFIG_MODE_SWCNT; + tiadc_writel(adc_dev, REG_STEPCONFIG(steps), stepconfig | STEPCONFIG_INP(chan)); + + if (adc_dev->open_delay[i] > STEPDELAY_OPEN_MASK) { + dev_warn(dev, "chan %d open delay truncating to 0x3FFFF\n", + chan); + adc_dev->open_delay[i] = STEPDELAY_OPEN_MASK; + } + + if (adc_dev->sample_delay[i] > 0xFF) { + dev_warn(dev, "chan %d sample delay truncating to 0xFF\n", + chan); + adc_dev->sample_delay[i] = 0xFF; + } + tiadc_writel(adc_dev, REG_STEPDELAY(steps), - STEPCONFIG_OPENDLY); + STEPDELAY_OPEN(adc_dev->open_delay[i]) | + STEPDELAY_SAMPLE(adc_dev->sample_delay[i])); + adc_dev->channel_step[i] = steps; steps++; } @@ -406,9 +435,22 @@ static int tiadc_parse_dt(struct platform_device *pdev, of_property_for_each_u32(node, "ti,adc-channels", prop, cur, val) { adc_dev->channel_line[channels] = val; + + /* Set Default values for optional DT parameters */ + adc_dev->open_delay[channels] = STEPCONFIG_OPENDLY; + adc_dev->sample_delay[channels] = STEPCONFIG_SAMPLEDLY; + adc_dev->step_avg[channels] = 16; + channels++; } + of_property_read_u32_array(node, "ti,chan-step-avg", + adc_dev->step_avg, channels); + of_property_read_u32_array(node, "ti,chan-step-opendelay", + adc_dev->open_delay, channels); + of_property_read_u32_array(node, "ti,chan-step-sampledelay", + adc_dev->sample_delay, channels); + adc_dev->channels = channels; return 0; }