IIO fixes for 4.0 set 4

A couple more IIO fixes.
 
 * Fix check for HAS_IOMEM in the cc100001_adc driver to avoid build errors.
   Rather curiously it was ORed with Regulator and clock support.
 * vf610 driver was trying to use an ADC clock outside the possible
   spec on some boards.  The driver assumed a fixed clock speed previously
   across all boards, but that is not true.  This fix ensures that the
   reported frequency is correct on all boards.
 * The adis imu common code directly set the current trigger to the
   driver supplied one.  Unfortunately this didn't increase the use count
   leading to a double free via a particular path of changing the trigger
   then removing the driver.
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v2
 
 iQIcBAABCAAGBQJVGaWjAAoJEFSFNJnE9BaIWUwP/jtYsUsoILHo8vng+DoFyx5L
 nDEEJqDYM7AROuBFAhayqpWVLjsd88VLCtD/in1HjNYXilhFbEMjIKknc3mmBg37
 YRNS7roxmOM7BD/Emww0eTlnmmNIXJx6iNBPJYizhtlS9xUGYWUwGfWOX2MN/qzq
 5oWL9uC8UAbMU0/hAeQ2rwYer/L7JDykQFrirupSyHqBzhL80gJ2591Bp1f8jTQ6
 CJ+gQZq/7qV1TzCW9PQzbO4oToBAXcShuKT7KEEJWiBEeUyC1lHn0cQocePA4Xd6
 YnO5tARiIZgAFypGHIYRZ22D3bP5HrGNtW7MSGdC5m4UNVTn/JlEO+bMLwaWVQWq
 bufK5bGGU8sS4lvyJSrixWb6S5lVoyCnrnKUc8Azaogd77G3JlMEiZBwp+5Chisr
 2tWSIdrAcH+NW/cp0iDHYjVKnkbHNvlmNqU0CHqWBXqUaIeZnzmhfUQcMih8jIy4
 CdyuBw9qUuVROkGOAzxNxrs5eZy4RiZ/erVZR7iI618l1ZtZcBVhZjek9GGj8Mc7
 6U+gnxR+jq2YUMCZyX8iRkxvW0JIxPh3ePGzvoSdenQuZRdblG8icff3dYup7XkJ
 EtLf7DeHyi1yE6E3TE/0iyTDhBErzv/ayvHkse0BFu4eBps0w60WPmcwjf6r1SUv
 FiYj8KMn1BlKqggX/eX+
 =BbAz
 -----END PGP SIGNATURE-----

Merge tag 'iio-fixes-for-4.0d' of git://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio into staging-linus

Jonathan writes:

IIO fixes for 4.0 set 4

A couple more IIO fixes.

* Fix check for HAS_IOMEM in the cc100001_adc driver to avoid build errors.
  Rather curiously it was ORed with Regulator and clock support.
* vf610 driver was trying to use an ADC clock outside the possible
  spec on some boards.  The driver assumed a fixed clock speed previously
  across all boards, but that is not true.  This fix ensures that the
  reported frequency is correct on all boards.
* The adis imu common code directly set the current trigger to the
  driver supplied one.  Unfortunately this didn't increase the use count
  leading to a double free via a particular path of changing the trigger
  then removing the driver.
This commit is contained in:
Greg Kroah-Hartman 2015-04-01 13:51:02 +02:00
commit dce5bdfe8f
3 changed files with 64 additions and 32 deletions

View File

@ -137,7 +137,8 @@ config AXP288_ADC
config CC10001_ADC config CC10001_ADC
tristate "Cosmic Circuits 10001 ADC driver" tristate "Cosmic Circuits 10001 ADC driver"
depends on HAS_IOMEM || HAVE_CLK || REGULATOR depends on HAVE_CLK || REGULATOR
depends on HAS_IOMEM
select IIO_BUFFER select IIO_BUFFER
select IIO_TRIGGERED_BUFFER select IIO_TRIGGERED_BUFFER
help help

View File

@ -141,9 +141,13 @@ struct vf610_adc {
struct regulator *vref; struct regulator *vref;
struct vf610_adc_feature adc_feature; struct vf610_adc_feature adc_feature;
u32 sample_freq_avail[5];
struct completion completion; struct completion completion;
}; };
static const u32 vf610_hw_avgs[] = { 1, 4, 8, 16, 32 };
#define VF610_ADC_CHAN(_idx, _chan_type) { \ #define VF610_ADC_CHAN(_idx, _chan_type) { \
.type = (_chan_type), \ .type = (_chan_type), \
.indexed = 1, \ .indexed = 1, \
@ -180,35 +184,47 @@ static const struct iio_chan_spec vf610_adc_iio_channels[] = {
/* sentinel */ /* sentinel */
}; };
/* static inline void vf610_adc_calculate_rates(struct vf610_adc *info)
* ADC sample frequency, unit is ADCK cycles. {
* ADC clk source is ipg clock, which is the same as bus clock. unsigned long adck_rate, ipg_rate = clk_get_rate(info->clk);
* int i;
* ADC conversion time = SFCAdder + AverageNum x (BCT + LSTAdder)
* SFCAdder: fixed to 6 ADCK cycles /*
* AverageNum: 1, 4, 8, 16, 32 samples for hardware average. * Calculate ADC sample frequencies
* BCT (Base Conversion Time): fixed to 25 ADCK cycles for 12 bit mode * Sample time unit is ADCK cycles. ADCK clk source is ipg clock,
* LSTAdder(Long Sample Time): fixed to 3 ADCK cycles * which is the same as bus clock.
* *
* By default, enable 12 bit resolution mode, clock source * ADC conversion time = SFCAdder + AverageNum x (BCT + LSTAdder)
* set to ipg clock, So get below frequency group: * SFCAdder: fixed to 6 ADCK cycles
*/ * AverageNum: 1, 4, 8, 16, 32 samples for hardware average.
static const u32 vf610_sample_freq_avail[5] = * BCT (Base Conversion Time): fixed to 25 ADCK cycles for 12 bit mode
{1941176, 559332, 286957, 145374, 73171}; * LSTAdder(Long Sample Time): fixed to 3 ADCK cycles
*/
adck_rate = ipg_rate / info->adc_feature.clk_div;
for (i = 0; i < ARRAY_SIZE(vf610_hw_avgs); i++)
info->sample_freq_avail[i] =
adck_rate / (6 + vf610_hw_avgs[i] * (25 + 3));
}
static inline void vf610_adc_cfg_init(struct vf610_adc *info) static inline void vf610_adc_cfg_init(struct vf610_adc *info)
{ {
struct vf610_adc_feature *adc_feature = &info->adc_feature;
/* set default Configuration for ADC controller */ /* set default Configuration for ADC controller */
info->adc_feature.clk_sel = VF610_ADCIOC_BUSCLK_SET; adc_feature->clk_sel = VF610_ADCIOC_BUSCLK_SET;
info->adc_feature.vol_ref = VF610_ADCIOC_VR_VREF_SET; adc_feature->vol_ref = VF610_ADCIOC_VR_VREF_SET;
info->adc_feature.calibration = true; adc_feature->calibration = true;
info->adc_feature.ovwren = true; adc_feature->ovwren = true;
info->adc_feature.clk_div = 1; adc_feature->res_mode = 12;
info->adc_feature.res_mode = 12; adc_feature->sample_rate = 1;
info->adc_feature.sample_rate = 1; adc_feature->lpm = true;
info->adc_feature.lpm = true;
/* Use a save ADCK which is below 20MHz on all devices */
adc_feature->clk_div = 8;
vf610_adc_calculate_rates(info);
} }
static void vf610_adc_cfg_post_set(struct vf610_adc *info) static void vf610_adc_cfg_post_set(struct vf610_adc *info)
@ -290,12 +306,10 @@ static void vf610_adc_cfg_set(struct vf610_adc *info)
cfg_data = readl(info->regs + VF610_REG_ADC_CFG); cfg_data = readl(info->regs + VF610_REG_ADC_CFG);
/* low power configuration */
cfg_data &= ~VF610_ADC_ADLPC_EN; cfg_data &= ~VF610_ADC_ADLPC_EN;
if (adc_feature->lpm) if (adc_feature->lpm)
cfg_data |= VF610_ADC_ADLPC_EN; cfg_data |= VF610_ADC_ADLPC_EN;
/* disable high speed */
cfg_data &= ~VF610_ADC_ADHSC_EN; cfg_data &= ~VF610_ADC_ADHSC_EN;
writel(cfg_data, info->regs + VF610_REG_ADC_CFG); writel(cfg_data, info->regs + VF610_REG_ADC_CFG);
@ -435,10 +449,27 @@ static irqreturn_t vf610_adc_isr(int irq, void *dev_id)
return IRQ_HANDLED; return IRQ_HANDLED;
} }
static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("1941176, 559332, 286957, 145374, 73171"); static ssize_t vf610_show_samp_freq_avail(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct vf610_adc *info = iio_priv(dev_to_iio_dev(dev));
size_t len = 0;
int i;
for (i = 0; i < ARRAY_SIZE(info->sample_freq_avail); i++)
len += scnprintf(buf + len, PAGE_SIZE - len,
"%u ", info->sample_freq_avail[i]);
/* replace trailing space by newline */
buf[len - 1] = '\n';
return len;
}
static IIO_DEV_ATTR_SAMP_FREQ_AVAIL(vf610_show_samp_freq_avail);
static struct attribute *vf610_attributes[] = { static struct attribute *vf610_attributes[] = {
&iio_const_attr_sampling_frequency_available.dev_attr.attr, &iio_dev_attr_sampling_frequency_available.dev_attr.attr,
NULL NULL
}; };
@ -502,7 +533,7 @@ static int vf610_read_raw(struct iio_dev *indio_dev,
return IIO_VAL_FRACTIONAL_LOG2; return IIO_VAL_FRACTIONAL_LOG2;
case IIO_CHAN_INFO_SAMP_FREQ: case IIO_CHAN_INFO_SAMP_FREQ:
*val = vf610_sample_freq_avail[info->adc_feature.sample_rate]; *val = info->sample_freq_avail[info->adc_feature.sample_rate];
*val2 = 0; *val2 = 0;
return IIO_VAL_INT; return IIO_VAL_INT;
@ -525,9 +556,9 @@ static int vf610_write_raw(struct iio_dev *indio_dev,
switch (mask) { switch (mask) {
case IIO_CHAN_INFO_SAMP_FREQ: case IIO_CHAN_INFO_SAMP_FREQ:
for (i = 0; for (i = 0;
i < ARRAY_SIZE(vf610_sample_freq_avail); i < ARRAY_SIZE(info->sample_freq_avail);
i++) i++)
if (val == vf610_sample_freq_avail[i]) { if (val == info->sample_freq_avail[i]) {
info->adc_feature.sample_rate = i; info->adc_feature.sample_rate = i;
vf610_adc_sample_set(info); vf610_adc_sample_set(info);
return 0; return 0;

View File

@ -60,7 +60,7 @@ int adis_probe_trigger(struct adis *adis, struct iio_dev *indio_dev)
iio_trigger_set_drvdata(adis->trig, adis); iio_trigger_set_drvdata(adis->trig, adis);
ret = iio_trigger_register(adis->trig); ret = iio_trigger_register(adis->trig);
indio_dev->trig = adis->trig; indio_dev->trig = iio_trigger_get(adis->trig);
if (ret) if (ret)
goto error_free_irq; goto error_free_irq;