Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit dce5bdfe authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman
Browse files

Merge tag 'iio-fixes-for-4.0d' of...

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.
parents 3d8bbe24 4ce7ca89
Loading
Loading
Loading
Loading
+2 −1
Original line number Original line Diff line number Diff line
@@ -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
+61 −30
Original line number Original line Diff line number Diff line
@@ -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)
{
	unsigned long adck_rate, ipg_rate = clk_get_rate(info->clk);
	int i;

	/*
	/*
 * ADC sample frequency, unit is ADCK cycles.
	 * Calculate ADC sample frequencies
 * ADC clk source is ipg clock, which is the same as bus clock.
	 * Sample time unit is ADCK cycles. ADCK clk source is ipg clock,
	 * which is the same as bus clock.
	 *
	 *
	 * ADC conversion time = SFCAdder + AverageNum x (BCT + LSTAdder)
	 * ADC conversion time = SFCAdder + AverageNum x (BCT + LSTAdder)
	 * SFCAdder: fixed to 6 ADCK cycles
	 * SFCAdder: fixed to 6 ADCK cycles
	 * AverageNum: 1, 4, 8, 16, 32 samples for hardware average.
	 * AverageNum: 1, 4, 8, 16, 32 samples for hardware average.
	 * BCT (Base Conversion Time): fixed to 25 ADCK cycles for 12 bit mode
	 * BCT (Base Conversion Time): fixed to 25 ADCK cycles for 12 bit mode
	 * LSTAdder(Long Sample Time): fixed to 3 ADCK cycles
	 * LSTAdder(Long Sample Time): fixed to 3 ADCK cycles
 *
 * By default, enable 12 bit resolution mode, clock source
 * set to ipg clock, So get below frequency group:
	 */
	 */
static const u32 vf610_sample_freq_avail[5] =
	adck_rate = ipg_rate / info->adc_feature.clk_div;
{1941176, 559332, 286957, 145374, 73171};
	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;
+1 −1
Original line number Original line Diff line number Diff line
@@ -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;