Commit edf17b28 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'staging-5.7-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging

Pull staging/IIO driver fixes from Greg KH:
 "Here are some small staging and IIO driver fixes for 5.7-rc3

  Lots of tiny things for reported issues in staging and IIO drivers,
  including a counter driver fix as well (the iio drivers seem to be
  tied to those). Full details of the fixes are in the shortlog.

  All of these have been in linux-next for a while with no reported
  issues"

* tag 'staging-5.7-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging: (27 commits)
  staging: vt6656: Fix calling conditions of vnt_set_bss_mode
  staging: comedi: Fix comedi_device refcnt leak in comedi_open
  staging: vt6656: Fix pairwise key entry save.
  staging: vt6656: Fix drivers TBTT timing counter.
  staging: vt6656: Don't set RCR_MULTICAST or RCR_BROADCAST by default.
  MAINTAINERS: remove Stefan Popa's email
  iio: adc: ad7192: fix null pointer de-reference crash during probe
  iio: core: remove extra semi-colon from devm_iio_device_register() macro
  iio: adc: ti-ads8344: properly byte swap value
  iio: imu: inv_mpu6050: fix suspend/resume with runtime power
  iio: st_sensors: rely on odr mask to know if odr can be set
  iio: xilinx-xadc: Make sure not exceed maximum samplerate
  iio: xilinx-xadc: Fix sequencer configuration for aux channels in simultaneous mode
  iio: xilinx-xadc: Fix clearing interrupt when enabling trigger
  iio: xilinx-xadc: Fix ADC-B powerdown
  iio: dac: ad5770r: fix off-by-one check on maximum number of channels
  iio: imu: st_lsm6dsx: flush hw FIFO before resetting the device
  iio: core: Fix handling of 'dB'
  dt-bindings: iio: adc: stm32-adc: fix id relative path
  counter: 104-quad-8: Add lock guards - generic interface
  ...
parents a8a0e2a9 664ba518
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) # SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
%YAML 1.2 %YAML 1.2
--- ---
$id: "http://devicetree.org/schemas/bindings/iio/adc/st,stm32-adc.yaml#" $id: "http://devicetree.org/schemas/iio/adc/st,stm32-adc.yaml#"
$schema: "http://devicetree.org/meta-schemas/core.yaml#" $schema: "http://devicetree.org/meta-schemas/core.yaml#"
title: STMicroelectronics STM32 ADC bindings title: STMicroelectronics STM32 ADC bindings
......
...@@ -570,7 +570,7 @@ F: Documentation/devicetree/bindings/iio/accel/adi,adxl345.yaml ...@@ -570,7 +570,7 @@ F: Documentation/devicetree/bindings/iio/accel/adi,adxl345.yaml
F: drivers/input/misc/adxl34x.c F: drivers/input/misc/adxl34x.c
ADXL372 THREE-AXIS DIGITAL ACCELEROMETER DRIVER ADXL372 THREE-AXIS DIGITAL ACCELEROMETER DRIVER
M: Stefan Popa <stefan.popa@analog.com> M: Michael Hennerich <michael.hennerich@analog.com>
S: Supported S: Supported
W: http://ez.analog.com/community/linux-device-drivers W: http://ez.analog.com/community/linux-device-drivers
F: Documentation/devicetree/bindings/iio/accel/adi,adxl372.yaml F: Documentation/devicetree/bindings/iio/accel/adi,adxl372.yaml
...@@ -922,7 +922,7 @@ F: arch/arm64/boot/dts/amd/amd-seattle-xgbe*.dtsi ...@@ -922,7 +922,7 @@ F: arch/arm64/boot/dts/amd/amd-seattle-xgbe*.dtsi
F: drivers/net/ethernet/amd/xgbe/ F: drivers/net/ethernet/amd/xgbe/
ANALOG DEVICES INC AD5686 DRIVER ANALOG DEVICES INC AD5686 DRIVER
M: Stefan Popa <stefan.popa@analog.com> M: Michael Hennerich <Michael.Hennerich@analog.com>
L: linux-pm@vger.kernel.org L: linux-pm@vger.kernel.org
S: Supported S: Supported
W: http://ez.analog.com/community/linux-device-drivers W: http://ez.analog.com/community/linux-device-drivers
...@@ -930,7 +930,7 @@ F: drivers/iio/dac/ad5686* ...@@ -930,7 +930,7 @@ F: drivers/iio/dac/ad5686*
F: drivers/iio/dac/ad5696* F: drivers/iio/dac/ad5696*
ANALOG DEVICES INC AD5758 DRIVER ANALOG DEVICES INC AD5758 DRIVER
M: Stefan Popa <stefan.popa@analog.com> M: Michael Hennerich <Michael.Hennerich@analog.com>
L: linux-iio@vger.kernel.org L: linux-iio@vger.kernel.org
S: Supported S: Supported
W: http://ez.analog.com/community/linux-device-drivers W: http://ez.analog.com/community/linux-device-drivers
...@@ -946,7 +946,7 @@ F: Documentation/devicetree/bindings/iio/adc/adi,ad7091r5.yaml ...@@ -946,7 +946,7 @@ F: Documentation/devicetree/bindings/iio/adc/adi,ad7091r5.yaml
F: drivers/iio/adc/ad7091r5.c F: drivers/iio/adc/ad7091r5.c
ANALOG DEVICES INC AD7124 DRIVER ANALOG DEVICES INC AD7124 DRIVER
M: Stefan Popa <stefan.popa@analog.com> M: Michael Hennerich <Michael.Hennerich@analog.com>
L: linux-iio@vger.kernel.org L: linux-iio@vger.kernel.org
S: Supported S: Supported
W: http://ez.analog.com/community/linux-device-drivers W: http://ez.analog.com/community/linux-device-drivers
...@@ -970,7 +970,7 @@ F: Documentation/devicetree/bindings/iio/adc/adi,ad7292.yaml ...@@ -970,7 +970,7 @@ F: Documentation/devicetree/bindings/iio/adc/adi,ad7292.yaml
F: drivers/iio/adc/ad7292.c F: drivers/iio/adc/ad7292.c
ANALOG DEVICES INC AD7606 DRIVER ANALOG DEVICES INC AD7606 DRIVER
M: Stefan Popa <stefan.popa@analog.com> M: Michael Hennerich <Michael.Hennerich@analog.com>
M: Beniamin Bia <beniamin.bia@analog.com> M: Beniamin Bia <beniamin.bia@analog.com>
L: linux-iio@vger.kernel.org L: linux-iio@vger.kernel.org
S: Supported S: Supported
...@@ -979,7 +979,7 @@ F: Documentation/devicetree/bindings/iio/adc/adi,ad7606.yaml ...@@ -979,7 +979,7 @@ F: Documentation/devicetree/bindings/iio/adc/adi,ad7606.yaml
F: drivers/iio/adc/ad7606.c F: drivers/iio/adc/ad7606.c
ANALOG DEVICES INC AD7768-1 DRIVER ANALOG DEVICES INC AD7768-1 DRIVER
M: Stefan Popa <stefan.popa@analog.com> M: Michael Hennerich <Michael.Hennerich@analog.com>
L: linux-iio@vger.kernel.org L: linux-iio@vger.kernel.org
S: Supported S: Supported
W: http://ez.analog.com/community/linux-device-drivers W: http://ez.analog.com/community/linux-device-drivers
...@@ -1040,7 +1040,7 @@ F: Documentation/devicetree/bindings/hwmon/adi,adm1177.yaml ...@@ -1040,7 +1040,7 @@ F: Documentation/devicetree/bindings/hwmon/adi,adm1177.yaml
F: drivers/hwmon/adm1177.c F: drivers/hwmon/adm1177.c
ANALOG DEVICES INC ADP5061 DRIVER ANALOG DEVICES INC ADP5061 DRIVER
M: Stefan Popa <stefan.popa@analog.com> M: Michael Hennerich <Michael.Hennerich@analog.com>
L: linux-pm@vger.kernel.org L: linux-pm@vger.kernel.org
S: Supported S: Supported
W: http://ez.analog.com/community/linux-device-drivers W: http://ez.analog.com/community/linux-device-drivers
...@@ -1109,7 +1109,6 @@ F: drivers/iio/amplifiers/hmc425a.c ...@@ -1109,7 +1109,6 @@ F: drivers/iio/amplifiers/hmc425a.c
ANALOG DEVICES INC IIO DRIVERS ANALOG DEVICES INC IIO DRIVERS
M: Lars-Peter Clausen <lars@metafoo.de> M: Lars-Peter Clausen <lars@metafoo.de>
M: Michael Hennerich <Michael.Hennerich@analog.com> M: Michael Hennerich <Michael.Hennerich@analog.com>
M: Stefan Popa <stefan.popa@analog.com>
S: Supported S: Supported
W: http://wiki.analog.com/ W: http://wiki.analog.com/
W: http://ez.analog.com/community/linux-device-drivers W: http://ez.analog.com/community/linux-device-drivers
......
...@@ -44,6 +44,7 @@ MODULE_PARM_DESC(base, "ACCES 104-QUAD-8 base addresses"); ...@@ -44,6 +44,7 @@ MODULE_PARM_DESC(base, "ACCES 104-QUAD-8 base addresses");
* @base: base port address of the IIO device * @base: base port address of the IIO device
*/ */
struct quad8_iio { struct quad8_iio {
struct mutex lock;
struct counter_device counter; struct counter_device counter;
unsigned int fck_prescaler[QUAD8_NUM_COUNTERS]; unsigned int fck_prescaler[QUAD8_NUM_COUNTERS];
unsigned int preset[QUAD8_NUM_COUNTERS]; unsigned int preset[QUAD8_NUM_COUNTERS];
...@@ -123,6 +124,8 @@ static int quad8_read_raw(struct iio_dev *indio_dev, ...@@ -123,6 +124,8 @@ static int quad8_read_raw(struct iio_dev *indio_dev,
/* Borrow XOR Carry effectively doubles count range */ /* Borrow XOR Carry effectively doubles count range */
*val = (borrow ^ carry) << 24; *val = (borrow ^ carry) << 24;
mutex_lock(&priv->lock);
/* Reset Byte Pointer; transfer Counter to Output Latch */ /* Reset Byte Pointer; transfer Counter to Output Latch */
outb(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP | QUAD8_RLD_CNTR_OUT, outb(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP | QUAD8_RLD_CNTR_OUT,
base_offset + 1); base_offset + 1);
...@@ -130,6 +133,8 @@ static int quad8_read_raw(struct iio_dev *indio_dev, ...@@ -130,6 +133,8 @@ static int quad8_read_raw(struct iio_dev *indio_dev,
for (i = 0; i < 3; i++) for (i = 0; i < 3; i++)
*val |= (unsigned int)inb(base_offset) << (8 * i); *val |= (unsigned int)inb(base_offset) << (8 * i);
mutex_unlock(&priv->lock);
return IIO_VAL_INT; return IIO_VAL_INT;
case IIO_CHAN_INFO_ENABLE: case IIO_CHAN_INFO_ENABLE:
*val = priv->ab_enable[chan->channel]; *val = priv->ab_enable[chan->channel];
...@@ -160,6 +165,8 @@ static int quad8_write_raw(struct iio_dev *indio_dev, ...@@ -160,6 +165,8 @@ static int quad8_write_raw(struct iio_dev *indio_dev,
if ((unsigned int)val > 0xFFFFFF) if ((unsigned int)val > 0xFFFFFF)
return -EINVAL; return -EINVAL;
mutex_lock(&priv->lock);
/* Reset Byte Pointer */ /* Reset Byte Pointer */
outb(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, base_offset + 1); outb(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, base_offset + 1);
...@@ -183,12 +190,16 @@ static int quad8_write_raw(struct iio_dev *indio_dev, ...@@ -183,12 +190,16 @@ static int quad8_write_raw(struct iio_dev *indio_dev,
/* Reset Error flag */ /* Reset Error flag */
outb(QUAD8_CTR_RLD | QUAD8_RLD_RESET_E, base_offset + 1); outb(QUAD8_CTR_RLD | QUAD8_RLD_RESET_E, base_offset + 1);
mutex_unlock(&priv->lock);
return 0; return 0;
case IIO_CHAN_INFO_ENABLE: case IIO_CHAN_INFO_ENABLE:
/* only boolean values accepted */ /* only boolean values accepted */
if (val < 0 || val > 1) if (val < 0 || val > 1)
return -EINVAL; return -EINVAL;
mutex_lock(&priv->lock);
priv->ab_enable[chan->channel] = val; priv->ab_enable[chan->channel] = val;
ior_cfg = val | priv->preset_enable[chan->channel] << 1; ior_cfg = val | priv->preset_enable[chan->channel] << 1;
...@@ -196,11 +207,18 @@ static int quad8_write_raw(struct iio_dev *indio_dev, ...@@ -196,11 +207,18 @@ static int quad8_write_raw(struct iio_dev *indio_dev,
/* Load I/O control configuration */ /* Load I/O control configuration */
outb(QUAD8_CTR_IOR | ior_cfg, base_offset + 1); outb(QUAD8_CTR_IOR | ior_cfg, base_offset + 1);
mutex_unlock(&priv->lock);
return 0; return 0;
case IIO_CHAN_INFO_SCALE: case IIO_CHAN_INFO_SCALE:
mutex_lock(&priv->lock);
/* Quadrature scaling only available in quadrature mode */ /* Quadrature scaling only available in quadrature mode */
if (!priv->quadrature_mode[chan->channel] && (val2 || val != 1)) if (!priv->quadrature_mode[chan->channel] &&
(val2 || val != 1)) {
mutex_unlock(&priv->lock);
return -EINVAL; return -EINVAL;
}
/* Only three gain states (1, 0.5, 0.25) */ /* Only three gain states (1, 0.5, 0.25) */
if (val == 1 && !val2) if (val == 1 && !val2)
...@@ -214,11 +232,15 @@ static int quad8_write_raw(struct iio_dev *indio_dev, ...@@ -214,11 +232,15 @@ static int quad8_write_raw(struct iio_dev *indio_dev,
priv->quadrature_scale[chan->channel] = 2; priv->quadrature_scale[chan->channel] = 2;
break; break;
default: default:
mutex_unlock(&priv->lock);
return -EINVAL; return -EINVAL;
} }
else else {
mutex_unlock(&priv->lock);
return -EINVAL; return -EINVAL;
}
mutex_unlock(&priv->lock);
return 0; return 0;
} }
...@@ -255,6 +277,8 @@ static ssize_t quad8_write_preset(struct iio_dev *indio_dev, uintptr_t private, ...@@ -255,6 +277,8 @@ static ssize_t quad8_write_preset(struct iio_dev *indio_dev, uintptr_t private,
if (preset > 0xFFFFFF) if (preset > 0xFFFFFF)
return -EINVAL; return -EINVAL;
mutex_lock(&priv->lock);
priv->preset[chan->channel] = preset; priv->preset[chan->channel] = preset;
/* Reset Byte Pointer */ /* Reset Byte Pointer */
...@@ -264,6 +288,8 @@ static ssize_t quad8_write_preset(struct iio_dev *indio_dev, uintptr_t private, ...@@ -264,6 +288,8 @@ static ssize_t quad8_write_preset(struct iio_dev *indio_dev, uintptr_t private,
for (i = 0; i < 3; i++) for (i = 0; i < 3; i++)
outb(preset >> (8 * i), base_offset); outb(preset >> (8 * i), base_offset);
mutex_unlock(&priv->lock);
return len; return len;
} }
...@@ -293,6 +319,8 @@ static ssize_t quad8_write_set_to_preset_on_index(struct iio_dev *indio_dev, ...@@ -293,6 +319,8 @@ static ssize_t quad8_write_set_to_preset_on_index(struct iio_dev *indio_dev,
/* Preset enable is active low in Input/Output Control register */ /* Preset enable is active low in Input/Output Control register */
preset_enable = !preset_enable; preset_enable = !preset_enable;
mutex_lock(&priv->lock);
priv->preset_enable[chan->channel] = preset_enable; priv->preset_enable[chan->channel] = preset_enable;
ior_cfg = priv->ab_enable[chan->channel] | ior_cfg = priv->ab_enable[chan->channel] |
...@@ -301,6 +329,8 @@ static ssize_t quad8_write_set_to_preset_on_index(struct iio_dev *indio_dev, ...@@ -301,6 +329,8 @@ static ssize_t quad8_write_set_to_preset_on_index(struct iio_dev *indio_dev,
/* Load I/O control configuration to Input / Output Control Register */ /* Load I/O control configuration to Input / Output Control Register */
outb(QUAD8_CTR_IOR | ior_cfg, base_offset); outb(QUAD8_CTR_IOR | ior_cfg, base_offset);
mutex_unlock(&priv->lock);
return len; return len;
} }
...@@ -358,6 +388,8 @@ static int quad8_set_count_mode(struct iio_dev *indio_dev, ...@@ -358,6 +388,8 @@ static int quad8_set_count_mode(struct iio_dev *indio_dev,
unsigned int mode_cfg = cnt_mode << 1; unsigned int mode_cfg = cnt_mode << 1;
const int base_offset = priv->base + 2 * chan->channel + 1; const int base_offset = priv->base + 2 * chan->channel + 1;
mutex_lock(&priv->lock);
priv->count_mode[chan->channel] = cnt_mode; priv->count_mode[chan->channel] = cnt_mode;
/* Add quadrature mode configuration */ /* Add quadrature mode configuration */
...@@ -367,6 +399,8 @@ static int quad8_set_count_mode(struct iio_dev *indio_dev, ...@@ -367,6 +399,8 @@ static int quad8_set_count_mode(struct iio_dev *indio_dev,
/* Load mode configuration to Counter Mode Register */ /* Load mode configuration to Counter Mode Register */
outb(QUAD8_CTR_CMR | mode_cfg, base_offset); outb(QUAD8_CTR_CMR | mode_cfg, base_offset);
mutex_unlock(&priv->lock);
return 0; return 0;
} }
...@@ -394,19 +428,26 @@ static int quad8_set_synchronous_mode(struct iio_dev *indio_dev, ...@@ -394,19 +428,26 @@ static int quad8_set_synchronous_mode(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan, unsigned int synchronous_mode) const struct iio_chan_spec *chan, unsigned int synchronous_mode)
{ {
struct quad8_iio *const priv = iio_priv(indio_dev); struct quad8_iio *const priv = iio_priv(indio_dev);
const unsigned int idr_cfg = synchronous_mode |
priv->index_polarity[chan->channel] << 1;
const int base_offset = priv->base + 2 * chan->channel + 1; const int base_offset = priv->base + 2 * chan->channel + 1;
unsigned int idr_cfg = synchronous_mode;
mutex_lock(&priv->lock);
idr_cfg |= priv->index_polarity[chan->channel] << 1;
/* Index function must be non-synchronous in non-quadrature mode */ /* Index function must be non-synchronous in non-quadrature mode */
if (synchronous_mode && !priv->quadrature_mode[chan->channel]) if (synchronous_mode && !priv->quadrature_mode[chan->channel]) {
mutex_unlock(&priv->lock);
return -EINVAL; return -EINVAL;
}
priv->synchronous_mode[chan->channel] = synchronous_mode; priv->synchronous_mode[chan->channel] = synchronous_mode;
/* Load Index Control configuration to Index Control Register */ /* Load Index Control configuration to Index Control Register */
outb(QUAD8_CTR_IDR | idr_cfg, base_offset); outb(QUAD8_CTR_IDR | idr_cfg, base_offset);
mutex_unlock(&priv->lock);
return 0; return 0;
} }
...@@ -434,8 +475,12 @@ static int quad8_set_quadrature_mode(struct iio_dev *indio_dev, ...@@ -434,8 +475,12 @@ static int quad8_set_quadrature_mode(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan, unsigned int quadrature_mode) const struct iio_chan_spec *chan, unsigned int quadrature_mode)
{ {
struct quad8_iio *const priv = iio_priv(indio_dev); struct quad8_iio *const priv = iio_priv(indio_dev);
unsigned int mode_cfg = priv->count_mode[chan->channel] << 1;
const int base_offset = priv->base + 2 * chan->channel + 1; const int base_offset = priv->base + 2 * chan->channel + 1;
unsigned int mode_cfg;
mutex_lock(&priv->lock);
mode_cfg = priv->count_mode[chan->channel] << 1;
if (quadrature_mode) if (quadrature_mode)
mode_cfg |= (priv->quadrature_scale[chan->channel] + 1) << 3; mode_cfg |= (priv->quadrature_scale[chan->channel] + 1) << 3;
...@@ -453,6 +498,8 @@ static int quad8_set_quadrature_mode(struct iio_dev *indio_dev, ...@@ -453,6 +498,8 @@ static int quad8_set_quadrature_mode(struct iio_dev *indio_dev,
/* Load mode configuration to Counter Mode Register */ /* Load mode configuration to Counter Mode Register */
outb(QUAD8_CTR_CMR | mode_cfg, base_offset); outb(QUAD8_CTR_CMR | mode_cfg, base_offset);
mutex_unlock(&priv->lock);
return 0; return 0;
} }
...@@ -480,15 +527,20 @@ static int quad8_set_index_polarity(struct iio_dev *indio_dev, ...@@ -480,15 +527,20 @@ static int quad8_set_index_polarity(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan, unsigned int index_polarity) const struct iio_chan_spec *chan, unsigned int index_polarity)
{ {
struct quad8_iio *const priv = iio_priv(indio_dev); struct quad8_iio *const priv = iio_priv(indio_dev);
const unsigned int idr_cfg = priv->synchronous_mode[chan->channel] |
index_polarity << 1;
const int base_offset = priv->base + 2 * chan->channel + 1; const int base_offset = priv->base + 2 * chan->channel + 1;
unsigned int idr_cfg = index_polarity << 1;
mutex_lock(&priv->lock);
idr_cfg |= priv->synchronous_mode[chan->channel];
priv->index_polarity[chan->channel] = index_polarity; priv->index_polarity[chan->channel] = index_polarity;
/* Load Index Control configuration to Index Control Register */ /* Load Index Control configuration to Index Control Register */
outb(QUAD8_CTR_IDR | idr_cfg, base_offset); outb(QUAD8_CTR_IDR | idr_cfg, base_offset);
mutex_unlock(&priv->lock);
return 0; return 0;
} }
...@@ -589,7 +641,7 @@ static int quad8_signal_read(struct counter_device *counter, ...@@ -589,7 +641,7 @@ static int quad8_signal_read(struct counter_device *counter,
static int quad8_count_read(struct counter_device *counter, static int quad8_count_read(struct counter_device *counter,
struct counter_count *count, unsigned long *val) struct counter_count *count, unsigned long *val)
{ {
const struct quad8_iio *const priv = counter->priv; struct quad8_iio *const priv = counter->priv;
const int base_offset = priv->base + 2 * count->id; const int base_offset = priv->base + 2 * count->id;
unsigned int flags; unsigned int flags;
unsigned int borrow; unsigned int borrow;
...@@ -603,6 +655,8 @@ static int quad8_count_read(struct counter_device *counter, ...@@ -603,6 +655,8 @@ static int quad8_count_read(struct counter_device *counter,
/* Borrow XOR Carry effectively doubles count range */ /* Borrow XOR Carry effectively doubles count range */
*val = (unsigned long)(borrow ^ carry) << 24; *val = (unsigned long)(borrow ^ carry) << 24;
mutex_lock(&priv->lock);
/* Reset Byte Pointer; transfer Counter to Output Latch */ /* Reset Byte Pointer; transfer Counter to Output Latch */
outb(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP | QUAD8_RLD_CNTR_OUT, outb(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP | QUAD8_RLD_CNTR_OUT,
base_offset + 1); base_offset + 1);
...@@ -610,13 +664,15 @@ static int quad8_count_read(struct counter_device *counter, ...@@ -610,13 +664,15 @@ static int quad8_count_read(struct counter_device *counter,
for (i = 0; i < 3; i++) for (i = 0; i < 3; i++)
*val |= (unsigned long)inb(base_offset) << (8 * i); *val |= (unsigned long)inb(base_offset) << (8 * i);
mutex_unlock(&priv->lock);
return 0; return 0;
} }
static int quad8_count_write(struct counter_device *counter, static int quad8_count_write(struct counter_device *counter,
struct counter_count *count, unsigned long val) struct counter_count *count, unsigned long val)
{ {
const struct quad8_iio *const priv = counter->priv; struct quad8_iio *const priv = counter->priv;
const int base_offset = priv->base + 2 * count->id; const int base_offset = priv->base + 2 * count->id;
int i; int i;
...@@ -624,6 +680,8 @@ static int quad8_count_write(struct counter_device *counter, ...@@ -624,6 +680,8 @@ static int quad8_count_write(struct counter_device *counter,
if (val > 0xFFFFFF) if (val > 0xFFFFFF)
return -EINVAL; return -EINVAL;
mutex_lock(&priv->lock);
/* Reset Byte Pointer */ /* Reset Byte Pointer */
outb(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, base_offset + 1); outb(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, base_offset + 1);
...@@ -647,6 +705,8 @@ static int quad8_count_write(struct counter_device *counter, ...@@ -647,6 +705,8 @@ static int quad8_count_write(struct counter_device *counter,
/* Reset Error flag */ /* Reset Error flag */
outb(QUAD8_CTR_RLD | QUAD8_RLD_RESET_E, base_offset + 1); outb(QUAD8_CTR_RLD | QUAD8_RLD_RESET_E, base_offset + 1);
mutex_unlock(&priv->lock);
return 0; return 0;
} }
...@@ -667,13 +727,13 @@ static enum counter_count_function quad8_count_functions_list[] = { ...@@ -667,13 +727,13 @@ static enum counter_count_function quad8_count_functions_list[] = {
static int quad8_function_get(struct counter_device *counter, static int quad8_function_get(struct counter_device *counter,
struct counter_count *count, size_t *function) struct counter_count *count, size_t *function)
{ {
const struct quad8_iio *const priv = counter->priv; struct quad8_iio *const priv = counter->priv;
const int id = count->id; const int id = count->id;
const unsigned int quadrature_mode = priv->quadrature_mode[id];
const unsigned int scale = priv->quadrature_scale[id];
if (quadrature_mode) mutex_lock(&priv->lock);
switch (scale) {
if (priv->quadrature_mode[id])
switch (priv->quadrature_scale[id]) {
case 0: case 0:
*function = QUAD8_COUNT_FUNCTION_QUADRATURE_X1; *function = QUAD8_COUNT_FUNCTION_QUADRATURE_X1;
break; break;
...@@ -687,6 +747,8 @@ static int quad8_function_get(struct counter_device *counter, ...@@ -687,6 +747,8 @@ static int quad8_function_get(struct counter_device *counter,
else else
*function = QUAD8_COUNT_FUNCTION_PULSE_DIRECTION; *function = QUAD8_COUNT_FUNCTION_PULSE_DIRECTION;
mutex_unlock(&priv->lock);
return 0; return 0;
} }
...@@ -697,10 +759,15 @@ static int quad8_function_set(struct counter_device *counter, ...@@ -697,10 +759,15 @@ static int quad8_function_set(struct counter_device *counter,
const int id = count->id; const int id = count->id;
unsigned int *const quadrature_mode = priv->quadrature_mode + id; unsigned int *const quadrature_mode = priv->quadrature_mode + id;
unsigned int *const scale = priv->quadrature_scale + id; unsigned int *const scale = priv->quadrature_scale + id;
unsigned int mode_cfg = priv->count_mode[id] << 1;
unsigned int *const synchronous_mode = priv->synchronous_mode + id; unsigned int *const synchronous_mode = priv->synchronous_mode + id;
const unsigned int idr_cfg = priv->index_polarity[id] << 1;
const int base_offset = priv->base + 2 * id + 1; const int base_offset = priv->base + 2 * id + 1;
unsigned int mode_cfg;
unsigned int idr_cfg;
mutex_lock(&priv->lock);
mode_cfg = priv->count_mode[id] << 1;
idr_cfg = priv->index_polarity[id] << 1;
if (function == QUAD8_COUNT_FUNCTION_PULSE_DIRECTION) { if (function == QUAD8_COUNT_FUNCTION_PULSE_DIRECTION) {
*quadrature_mode = 0; *quadrature_mode = 0;
...@@ -736,6 +803,8 @@ static int quad8_function_set(struct counter_device *counter, ...@@ -736,6 +803,8 @@ static int quad8_function_set(struct counter_device *counter,
/* Load mode configuration to Counter Mode Register */ /* Load mode configuration to Counter Mode Register */
outb(QUAD8_CTR_CMR | mode_cfg, base_offset); outb(QUAD8_CTR_CMR | mode_cfg, base_offset);
mutex_unlock(&priv->lock);
return 0; return 0;
} }
...@@ -852,15 +921,20 @@ static int quad8_index_polarity_set(struct counter_device *counter, ...@@ -852,15 +921,20 @@ static int quad8_index_polarity_set(struct counter_device *counter,
{ {
struct quad8_iio *const priv = counter->priv; struct quad8_iio *const priv = counter->priv;
const size_t channel_id = signal->id - 16; const size_t channel_id = signal->id - 16;
const unsigned int idr_cfg = priv->synchronous_mode[channel_id] |
index_polarity << 1;
const int base_offset = priv->base + 2 * channel_id + 1; const int base_offset = priv->base + 2 * channel_id + 1;
unsigned int idr_cfg = index_polarity << 1;
mutex_lock(&priv->lock);
idr_cfg |= priv->synchronous_mode[channel_id];
priv->index_polarity[channel_id] = index_polarity; priv->index_polarity[channel_id] = index_polarity;
/* Load Index Control configuration to Index Control Register */ /* Load Index Control configuration to Index Control Register */
outb(QUAD8_CTR_IDR | idr_cfg, base_offset); outb(QUAD8_CTR_IDR | idr_cfg, base_offset);
mutex_unlock(&priv->lock);
return 0; return 0;
} }
...@@ -887,19 +961,26 @@ static int quad8_synchronous_mode_set(struct counter_device *counter, ...@@ -887,19 +961,26 @@ static int quad8_synchronous_mode_set(struct counter_device *counter,
{ {
struct quad8_iio *const priv = counter->priv; struct quad8_iio *const priv = counter->priv;
const size_t channel_id = signal->id - 16; const size_t channel_id = signal->id - 16;
const unsigned int idr_cfg = synchronous_mode |
priv->index_polarity[channel_id] << 1;
const int base_offset = priv->base + 2 * channel_id + 1; const int base_offset = priv->base + 2 * channel_id + 1;
unsigned int idr_cfg = synchronous_mode;
mutex_lock(&priv->lock);
idr_cfg |= priv->index_polarity[channel_id] << 1;
/* Index function must be non-synchronous in non-quadrature mode */ /* Index function must be non-synchronous in non-quadrature mode */
if (synchronous_mode && !priv->quadrature_mode[channel_id]) if (synchronous_mode && !priv->quadrature_mode[channel_id]) {
mutex_unlock(&priv->lock);
return -EINVAL; return -EINVAL;
}
priv->synchronous_mode[channel_id] = synchronous_mode; priv->synchronous_mode[channel_id] = synchronous_mode;
/* Load Index Control configuration to Index Control Register */ /* Load Index Control configuration to Index Control Register */
outb(QUAD8_CTR_IDR | idr_cfg, base_offset); outb(QUAD8_CTR_IDR | idr_cfg, base_offset);
mutex_unlock(&priv->lock);
return 0; return 0;
} }
...@@ -964,6 +1045,8 @@ static int quad8_count_mode_set(struct counter_device *counter, ...@@ -964,6 +1045,8 @@ static int quad8_count_mode_set(struct counter_device *counter,
break; break;
} }
mutex_lock(&priv->lock);
priv->count_mode[count->id] = cnt_mode; priv->count_mode[count->id] = cnt_mode;
/* Set count mode configuration value */ /* Set count mode configuration value */
...@@ -976,6 +1059,8 @@ static int quad8_count_mode_set(struct counter_device *counter, ...@@ -976,6 +1059,8 @@ static int quad8_count_mode_set(struct counter_device *counter,
/* Load mode configuration to Counter Mode Register */ /* Load mode configuration to Counter Mode Register */
outb(QUAD8_CTR_CMR | mode_cfg, base_offset); outb(QUAD8_CTR_CMR | mode_cfg, base_offset);
mutex_unlock(&priv->lock);
return 0; return 0;
} }
...@@ -1017,6 +1102,8 @@ static ssize_t quad8_count_enable_write(struct counter_device *counter, ...@@ -1017,6 +1102,8 @@ static ssize_t quad8_count_enable_write(struct counter_device *counter,
if (err) if (err)
return err; return err;
mutex_lock(&priv->lock);
priv->ab_enable[count->id] = ab_enable; priv->ab_enable[count->id] = ab_enable;
ior_cfg = ab_enable | priv->preset_enable[count->id] << 1; ior_cfg = ab_enable | priv->preset_enable[count->id] << 1;
...@@ -1024,6 +1111,8 @@ static ssize_t quad8_count_enable_write(struct counter_device *counter, ...@@ -1024,6 +1111,8 @@ static ssize_t quad8_count_enable_write(struct counter_device *counter,
/* Load I/O control configuration */ /* Load I/O control configuration */
outb(QUAD8_CTR_IOR | ior_cfg, base_offset + 1); outb(QUAD8_CTR_IOR | ior_cfg, base_offset + 1);
mutex_unlock(&priv->lock);
return len; return len;
} }
...@@ -1052,14 +1141,28 @@ static ssize_t quad8_count_preset_read(struct counter_device *counter, ...@@ -1052,14 +1141,28 @@ static ssize_t quad8_count_preset_read(struct counter_device *counter,
return sprintf(buf, "%u\n", priv->preset[count->id]); return sprintf(buf, "%u\n", priv->preset[count->id]);
} }
static void quad8_preset_register_set(struct quad8_iio *quad8iio, int id,
unsigned int preset)
{
const unsigned int base_offset = quad8iio->base + 2 * id;
int i;
quad8iio->preset[id] = preset;
/* Reset Byte Pointer */
outb(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, base_offset + 1);
/* Set Preset Register */
for (i = 0; i < 3; i++)
outb(preset >> (8 * i), base_offset);
}
static ssize_t quad8_count_preset_write(struct counter_device *counter, static ssize_t quad8_count_preset_write(struct counter_device *counter,
struct counter_count *count, void *private, const char *buf, size_t len) struct counter_count *count, void *private, const char *buf, size_t len)
{ {
struct quad8_iio *const priv = counter->priv; struct quad8_iio *const priv = counter->priv;
const int base_offset = priv->base + 2 * count->id;
unsigned int preset; unsigned int preset;
int ret; int ret;
int i;
ret = kstrtouint(buf, 0, &preset); ret = kstrtouint(buf, 0, &preset);
if (ret) if (ret)
...@@ -1069,14 +1172,11 @@ static ssize_t quad8_count_preset_write(struct counter_device *counter, ...@@ -1069,14 +1172,11 @@ static ssize_t quad8_count_preset_write(struct counter_device *counter,
if (preset > 0xFFFFFF) if (preset > 0xFFFFFF)
return -EINVAL; return -EINVAL;
priv->preset[count->id] = preset; mutex_lock(&priv->lock);
/* Reset Byte Pointer */ quad8_preset_register_set(priv, count->id, preset);
outb(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, base_offset + 1);
/* Set Preset Register */ mutex_unlock(&priv->lock);
for (i = 0; i < 3; i++)
outb(preset >> (8 * i), base_offset);
return len; return len;
} }
...@@ -1084,15 +1184,20 @@ static ssize_t quad8_count_preset_write(struct counter_device *counter, ...@@ -1084,15 +1184,20 @@ static ssize_t quad8_count_preset_write(struct counter_device *counter,
static ssize_t quad8_count_ceiling_read(struct counter_device *counter, static ssize_t quad8_count_ceiling_read(struct counter_device *counter,
struct counter_count *count, void *private, char *buf) struct counter_count *count, void *private, char *buf)
{ {
const struct quad8_iio *const priv = counter->priv; struct quad8_iio *const priv = counter->priv;
mutex_lock(&priv->lock);
/* Range Limit and Modulo-N count modes use preset value as ceiling */ /* Range Limit and Modulo-N count modes use preset value as ceiling */
switch (priv->count_mode[count->id]) { switch (priv->count_mode[count->id]) {
case 1: case 1:
case 3: case 3:
return quad8_count_preset_read(counter, count, private, buf); mutex_unlock(&priv->lock);
return sprintf(buf, "%u\n", priv->preset[count->id]);
} }
mutex_unlock(&priv->lock);
/* By default 0x1FFFFFF (25 bits unsigned) is maximum count */ /* By default 0x1FFFFFF (25 bits unsigned) is maximum count */
return sprintf(buf, "33554431\n"); return sprintf(buf, "33554431\n");
} }
...@@ -1101,15 +1206,29 @@ static ssize_t quad8_count_ceiling_write(struct counter_device *counter, ...@@ -1101,15 +1206,29 @@ static ssize_t quad8_count_ceiling_write(struct counter_device *counter,
struct counter_count *count, void *private, const char *buf, size_t len) struct counter_count *count, void *private, const char *buf, size_t len)
{ {
struct quad8_iio *const priv = counter->priv; struct quad8_iio *const priv = counter->priv;
unsigned int ceiling;
int ret;
ret = kstrtouint(buf, 0, &ceiling);
if (ret)
return ret;
/* Only 24-bit values are supported */
if (ceiling > 0xFFFFFF)
return -EINVAL;
mutex_lock(&priv->lock);
/* Range Limit and Modulo-N count modes use preset value as ceiling */ /* Range Limit and Modulo-N count modes use preset value as ceiling */
switch (priv->count_mode[count->id]) { switch (priv->count_mode[count->id]) {
case 1: case 1:
case 3: case 3:
return quad8_count_preset_write(counter, count, private, buf, quad8_preset_register_set(priv, count->id, ceiling);
len); break;
} }
mutex_unlock(&priv->lock);
return len; return len;
} }
...@@ -1137,6 +1256,8 @@ static ssize_t quad8_count_preset_enable_write(struct counter_device *counter, ...@@ -1137,6 +1256,8 @@ static ssize_t quad8_count_preset_enable_write(struct counter_device *counter,
/* Preset enable is active low in Input/Output Control register */ /* Preset enable is active low in Input/Output Control register */
preset_enable = !preset_enable; preset_enable = !preset_enable;
mutex_lock(&priv->lock);
priv->preset_enable[count->id] = preset_enable; priv->preset_enable[count->id] = preset_enable;
ior_cfg = priv->ab_enable[count->id] | (unsigned int)preset_enable << 1; ior_cfg = priv->ab_enable[count->id] | (unsigned int)preset_enable << 1;
...@@ -1144,6 +1265,8 @@ static ssize_t quad8_count_preset_enable_write(struct counter_device *counter, ...@@ -1144,6 +1265,8 @@ static ssize_t quad8_count_preset_enable_write(struct counter_device *counter,
/* Load I/O control configuration to Input / Output Control Register */ /* Load I/O control configuration to Input / Output Control Register */
outb(QUAD8_CTR_IOR | ior_cfg, base_offset); outb(QUAD8_CTR_IOR | ior_cfg, base_offset);
mutex_unlock(&priv->lock);
return len; return len;
} }
...@@ -1429,6 +1552,9 @@ static int quad8_probe(struct device *dev, unsigned int id) ...@@ -1429,6 +1552,9 @@ static int quad8_probe(struct device *dev, unsigned int id)
quad8iio->counter.priv = quad8iio; quad8iio->counter.priv = quad8iio;
quad8iio->base = base[id]; quad8iio->base = base[id];
/* Initialize mutex */
mutex_init(&quad8iio->lock);
/* Reset all counters and disable interrupt function */ /* Reset all counters and disable interrupt function */
outb(QUAD8_CHAN_OP_RESET_COUNTERS, base[id] + QUAD8_REG_CHAN_OP); outb(QUAD8_CHAN_OP_RESET_COUNTERS, base[id] + QUAD8_REG_CHAN_OP);
/* Set initial configuration for all counters */ /* Set initial configuration for all counters */
......
...@@ -125,10 +125,10 @@ ...@@ -125,10 +125,10 @@
#define AD7193_CH_AINCOM 0x600 /* AINCOM - AINCOM */ #define AD7193_CH_AINCOM 0x600 /* AINCOM - AINCOM */
/* ID Register Bit Designations (AD7192_REG_ID) */ /* ID Register Bit Designations (AD7192_REG_ID) */
#define ID_AD7190 0x4 #define CHIPID_AD7190 0x4
#define ID_AD7192 0x0 #define CHIPID_AD7192 0x0
#define ID_AD7193 0x2 #define CHIPID_AD7193 0x2
#define ID_AD7195 0x6 #define CHIPID_AD7195 0x6
#define AD7192_ID_MASK 0x0F #define AD7192_ID_MASK 0x0F
/* GPOCON Register Bit Designations (AD7192_REG_GPOCON) */ /* GPOCON Register Bit Designations (AD7192_REG_GPOCON) */
...@@ -161,7 +161,20 @@ enum { ...@@ -161,7 +161,20 @@ enum {
AD7192_SYSCALIB_FULL_SCALE, AD7192_SYSCALIB_FULL_SCALE,
}; };
enum {
ID_AD7190,
ID_AD7192,
ID_AD7193,
ID_AD7195,
};
struct ad7192_chip_info {
unsigned int chip_id;
const char *name;
};
struct ad7192_state { struct ad7192_state {
const struct ad7192_chip_info *chip_info;
struct regulator *avdd; struct regulator *avdd;
struct regulator *dvdd; struct regulator *dvdd;
struct clk *mclk; struct clk *mclk;
...@@ -172,7 +185,6 @@ struct ad7192_state { ...@@ -172,7 +185,6 @@ struct ad7192_state {
u32 conf; u32 conf;
u32 scale_avail[8][2]; u32 scale_avail[8][2];
u8 gpocon; u8 gpocon;
u8 devid;
u8 clock_sel; u8 clock_sel;
struct mutex lock; /* protect sensor state */ struct mutex lock; /* protect sensor state */
u8 syscalib_mode[8]; u8 syscalib_mode[8];
...@@ -348,7 +360,7 @@ static int ad7192_setup(struct ad7192_state *st, struct device_node *np) ...@@ -348,7 +360,7 @@ static int ad7192_setup(struct ad7192_state *st, struct device_node *np)
id &= AD7192_ID_MASK; id &= AD7192_ID_MASK;
if (id != st->devid) if (id != st->chip_info->chip_id)
dev_warn(&st->sd.spi->dev, "device ID query failed (0x%X)\n", dev_warn(&st->sd.spi->dev, "device ID query failed (0x%X)\n",
id); id);
...@@ -363,7 +375,7 @@ static int ad7192_setup(struct ad7192_state *st, struct device_node *np) ...@@ -363,7 +375,7 @@ static int ad7192_setup(struct ad7192_state *st, struct device_node *np)
st->mode |= AD7192_MODE_REJ60; st->mode |= AD7192_MODE_REJ60;
refin2_en = of_property_read_bool(np, "adi,refin2-pins-enable"); refin2_en = of_property_read_bool(np, "adi,refin2-pins-enable");
if (refin2_en && st->devid != ID_AD7195) if (refin2_en && st->chip_info->chip_id != CHIPID_AD7195)
st->conf |= AD7192_CONF_REFSEL; st->conf |= AD7192_CONF_REFSEL;
st->conf &= ~AD7192_CONF_CHOP; st->conf &= ~AD7192_CONF_CHOP;
...@@ -859,12 +871,31 @@ static const struct iio_chan_spec ad7193_channels[] = { ...@@ -859,12 +871,31 @@ static const struct iio_chan_spec ad7193_channels[] = {
IIO_CHAN_SOFT_TIMESTAMP(14), IIO_CHAN_SOFT_TIMESTAMP(14),
}; };
static const struct ad7192_chip_info ad7192_chip_info_tbl[] = {
[ID_AD7190] = {
.chip_id = CHIPID_AD7190,
.name = "ad7190",
},
[ID_AD7192] = {
.chip_id = CHIPID_AD7192,
.name = "ad7192",
},
[ID_AD7193] = {
.chip_id = CHIPID_AD7193,
.name = "ad7193",
},
[ID_AD7195] = {
.chip_id = CHIPID_AD7195,
.name = "ad7195",
},
};
static int ad7192_channels_config(struct iio_dev *indio_dev) static int ad7192_channels_config(struct iio_dev *indio_dev)
{ {
struct ad7192_state *st = iio_priv(indio_dev); struct ad7192_state *st = iio_priv(indio_dev);
switch (st->devid) { switch (st->chip_info->chip_id) {
case ID_AD7193: case CHIPID_AD7193:
indio_dev->channels = ad7193_channels; indio_dev->channels = ad7193_channels;
indio_dev->num_channels = ARRAY_SIZE(ad7193_channels); indio_dev->num_channels = ARRAY_SIZE(ad7193_channels);
break; break;
...@@ -878,10 +909,10 @@ static int ad7192_channels_config(struct iio_dev *indio_dev) ...@@ -878,10 +909,10 @@ static int ad7192_channels_config(struct iio_dev *indio_dev)
} }
static const struct of_device_id ad7192_of_match[] = { static const struct of_device_id ad7192_of_match[] = {
{ .compatible = "adi,ad7190", .data = (void *)ID_AD7190 }, { .compatible = "adi,ad7190", .data = &ad7192_chip_info_tbl[ID_AD7190] },
{ .compatible = "adi,ad7192", .data = (void *)ID_AD7192 }, { .compatible = "adi,ad7192", .data = &ad7192_chip_info_tbl[ID_AD7192] },
{ .compatible = "adi,ad7193", .data = (void *)ID_AD7193 }, { .compatible = "adi,ad7193", .data = &ad7192_chip_info_tbl[ID_AD7193] },
{ .compatible = "adi,ad7195", .data = (void *)ID_AD7195 }, { .compatible = "adi,ad7195", .data = &ad7192_chip_info_tbl[ID_AD7195] },
{} {}
}; };
MODULE_DEVICE_TABLE(of, ad7192_of_match); MODULE_DEVICE_TABLE(of, ad7192_of_match);
...@@ -938,16 +969,16 @@ static int ad7192_probe(struct spi_device *spi) ...@@ -938,16 +969,16 @@ static int ad7192_probe(struct spi_device *spi)
} }
spi_set_drvdata(spi, indio_dev); spi_set_drvdata(spi, indio_dev);
st->devid = (unsigned long)of_device_get_match_data(&spi->dev); st->chip_info = of_device_get_match_data(&spi->dev);
indio_dev->dev.parent = &spi->dev; indio_dev->dev.parent = &spi->dev;
indio_dev->name = spi_get_device_id(spi)->name; indio_dev->name = st->chip_info->name;
indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->modes = INDIO_DIRECT_MODE;
ret = ad7192_channels_config(indio_dev); ret = ad7192_channels_config(indio_dev);
if (ret < 0) if (ret < 0)
goto error_disable_dvdd; goto error_disable_dvdd;
if (st->devid == ID_AD7195) if (st->chip_info->chip_id == CHIPID_AD7195)
indio_dev->info = &ad7195_info; indio_dev->info = &ad7195_info;
else else
indio_dev->info = &ad7192_info; indio_dev->info = &ad7192_info;
......
...@@ -542,7 +542,7 @@ static const struct iio_info ad7797_info = { ...@@ -542,7 +542,7 @@ static const struct iio_info ad7797_info = {
.read_raw = &ad7793_read_raw, .read_raw = &ad7793_read_raw,
.write_raw = &ad7793_write_raw, .write_raw = &ad7793_write_raw,
.write_raw_get_fmt = &ad7793_write_raw_get_fmt, .write_raw_get_fmt = &ad7793_write_raw_get_fmt,
.attrs = &ad7793_attribute_group, .attrs = &ad7797_attribute_group,
.validate_trigger = ad_sd_validate_trigger, .validate_trigger = ad_sd_validate_trigger,
}; };
......
...@@ -1418,8 +1418,30 @@ static unsigned int stm32_adc_dma_residue(struct stm32_adc *adc) ...@@ -1418,8 +1418,30 @@ static unsigned int stm32_adc_dma_residue(struct stm32_adc *adc)
static void stm32_adc_dma_buffer_done(void *data) static void stm32_adc_dma_buffer_done(void *data)
{ {
struct iio_dev *indio_dev = data; struct iio_dev *indio_dev = data;
struct stm32_adc *adc = iio_priv(indio_dev);
int residue = stm32_adc_dma_residue(adc);
/*
* In DMA mode the trigger services of IIO are not used
* (e.g. no call to iio_trigger_poll).
* Calling irq handler associated to the hardware trigger is not
* relevant as the conversions have already been done. Data
* transfers are performed directly in DMA callback instead.
* This implementation avoids to call trigger irq handler that
* may sleep, in an atomic context (DMA irq handler context).
*/
dev_dbg(&indio_dev->dev, "%s bufi=%d\n", __func__, adc->bufi);
iio_trigger_poll_chained(indio_dev->trig); while (residue >= indio_dev->scan_bytes) {
u16 *buffer = (u16 *)&adc->rx_buf[adc->bufi];
iio_push_to_buffers(indio_dev, buffer);
residue -= indio_dev->scan_bytes;
adc->bufi += indio_dev->scan_bytes;
if (adc->bufi >= adc->rx_buf_sz)
adc->bufi = 0;
}
} }
static int stm32_adc_dma_start(struct iio_dev *indio_dev) static int stm32_adc_dma_start(struct iio_dev *indio_dev)
...@@ -1845,6 +1867,7 @@ static int stm32_adc_probe(struct platform_device *pdev) ...@@ -1845,6 +1867,7 @@ static int stm32_adc_probe(struct platform_device *pdev)
{ {
struct iio_dev *indio_dev; struct iio_dev *indio_dev;
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
irqreturn_t (*handler)(int irq, void *p) = NULL;
struct stm32_adc *adc; struct stm32_adc *adc;
int ret; int ret;
...@@ -1911,9 +1934,11 @@ static int stm32_adc_probe(struct platform_device *pdev) ...@@ -1911,9 +1934,11 @@ static int stm32_adc_probe(struct platform_device *pdev)
if (ret < 0) if (ret < 0)
return ret; return ret;
if (!adc->dma_chan)
handler = &stm32_adc_trigger_handler;
ret = iio_triggered_buffer_setup(indio_dev, ret = iio_triggered_buffer_setup(indio_dev,
&iio_pollfunc_store_time, &iio_pollfunc_store_time, handler,
&stm32_adc_trigger_handler,
&stm32_adc_buffer_setup_ops); &stm32_adc_buffer_setup_ops);
if (ret) { if (ret) {
dev_err(&pdev->dev, "buffer setup failed\n"); dev_err(&pdev->dev, "buffer setup failed\n");
......
...@@ -29,7 +29,7 @@ struct ads8344 { ...@@ -29,7 +29,7 @@ struct ads8344 {
struct mutex lock; struct mutex lock;
u8 tx_buf ____cacheline_aligned; u8 tx_buf ____cacheline_aligned;
u16 rx_buf; u8 rx_buf[3];
}; };
#define ADS8344_VOLTAGE_CHANNEL(chan, si) \ #define ADS8344_VOLTAGE_CHANNEL(chan, si) \
...@@ -89,11 +89,11 @@ static int ads8344_adc_conversion(struct ads8344 *adc, int channel, ...@@ -89,11 +89,11 @@ static int ads8344_adc_conversion(struct ads8344 *adc, int channel,
udelay(9); udelay(9);
ret = spi_read(spi, &adc->rx_buf, 2); ret = spi_read(spi, adc->rx_buf, sizeof(adc->rx_buf));
if (ret) if (ret)
return ret; return ret;
return adc->rx_buf; return adc->rx_buf[0] << 9 | adc->rx_buf[1] << 1 | adc->rx_buf[2] >> 7;
} }
static int ads8344_read_raw(struct iio_dev *iio, static int ads8344_read_raw(struct iio_dev *iio,
......
...@@ -102,6 +102,16 @@ static const unsigned int XADC_ZYNQ_UNMASK_TIMEOUT = 500; ...@@ -102,6 +102,16 @@ static const unsigned int XADC_ZYNQ_UNMASK_TIMEOUT = 500;
#define XADC_FLAGS_BUFFERED BIT(0) #define XADC_FLAGS_BUFFERED BIT(0)
/*
* The XADC hardware supports a samplerate of up to 1MSPS. Unfortunately it does
* not have a hardware FIFO. Which means an interrupt is generated for each
* conversion sequence. At 1MSPS sample rate the CPU in ZYNQ7000 is completely
* overloaded by the interrupts that it soft-lockups. For this reason the driver
* limits the maximum samplerate 150kSPS. At this rate the CPU is fairly busy,
* but still responsive.
*/
#define XADC_MAX_SAMPLERATE 150000
static void xadc_write_reg(struct xadc *xadc, unsigned int reg, static void xadc_write_reg(struct xadc *xadc, unsigned int reg,
uint32_t val) uint32_t val)
{ {
...@@ -674,7 +684,7 @@ static int xadc_trigger_set_state(struct iio_trigger *trigger, bool state) ...@@ -674,7 +684,7 @@ static int xadc_trigger_set_state(struct iio_trigger *trigger, bool state)
spin_lock_irqsave(&xadc->lock, flags); spin_lock_irqsave(&xadc->lock, flags);
xadc_read_reg(xadc, XADC_AXI_REG_IPIER, &val); xadc_read_reg(xadc, XADC_AXI_REG_IPIER, &val);
xadc_write_reg(xadc, XADC_AXI_REG_IPISR, val & XADC_AXI_INT_EOS); xadc_write_reg(xadc, XADC_AXI_REG_IPISR, XADC_AXI_INT_EOS);
if (state) if (state)
val |= XADC_AXI_INT_EOS; val |= XADC_AXI_INT_EOS;
else else
...@@ -722,13 +732,14 @@ static int xadc_power_adc_b(struct xadc *xadc, unsigned int seq_mode) ...@@ -722,13 +732,14 @@ static int xadc_power_adc_b(struct xadc *xadc, unsigned int seq_mode)
{ {
uint16_t val; uint16_t val;
/* Powerdown the ADC-B when it is not needed. */
switch (seq_mode) { switch (seq_mode) {
case XADC_CONF1_SEQ_SIMULTANEOUS: case XADC_CONF1_SEQ_SIMULTANEOUS:
case XADC_CONF1_SEQ_INDEPENDENT: case XADC_CONF1_SEQ_INDEPENDENT:
val = XADC_CONF2_PD_ADC_B; val = 0;
break; break;
default: default:
val = 0; val = XADC_CONF2_PD_ADC_B;
break; break;
} }
...@@ -797,6 +808,16 @@ static int xadc_preenable(struct iio_dev *indio_dev) ...@@ -797,6 +808,16 @@ static int xadc_preenable(struct iio_dev *indio_dev)
if (ret) if (ret)
goto err; goto err;
/*
* In simultaneous mode the upper and lower aux channels are samples at
* the same time. In this mode the upper 8 bits in the sequencer
* register are don't care and the lower 8 bits control two channels
* each. As such we must set the bit if either the channel in the lower
* group or the upper group is enabled.
*/
if (seq_mode == XADC_CONF1_SEQ_SIMULTANEOUS)
scan_mask = ((scan_mask >> 8) | scan_mask) & 0xff0000;
ret = xadc_write_adc_reg(xadc, XADC_REG_SEQ(1), scan_mask >> 16); ret = xadc_write_adc_reg(xadc, XADC_REG_SEQ(1), scan_mask >> 16);
if (ret) if (ret)
goto err; goto err;
...@@ -823,11 +844,27 @@ static const struct iio_buffer_setup_ops xadc_buffer_ops = { ...@@ -823,11 +844,27 @@ static const struct iio_buffer_setup_ops xadc_buffer_ops = {
.postdisable = &xadc_postdisable, .postdisable = &xadc_postdisable,
}; };
static int xadc_read_samplerate(struct xadc *xadc)
{
unsigned int div;
uint16_t val16;
int ret;
ret = xadc_read_adc_reg(xadc, XADC_REG_CONF2, &val16);
if (ret)
return ret;
div = (val16 & XADC_CONF2_DIV_MASK) >> XADC_CONF2_DIV_OFFSET;
if (div < 2)
div = 2;
return xadc_get_dclk_rate(xadc) / div / 26;
}
static int xadc_read_raw(struct iio_dev *indio_dev, static int xadc_read_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan, int *val, int *val2, long info) struct iio_chan_spec const *chan, int *val, int *val2, long info)
{ {
struct xadc *xadc = iio_priv(indio_dev); struct xadc *xadc = iio_priv(indio_dev);
unsigned int div;
uint16_t val16; uint16_t val16;
int ret; int ret;
...@@ -880,41 +917,31 @@ static int xadc_read_raw(struct iio_dev *indio_dev, ...@@ -880,41 +917,31 @@ static int xadc_read_raw(struct iio_dev *indio_dev,
*val = -((273150 << 12) / 503975); *val = -((273150 << 12) / 503975);
return IIO_VAL_INT; return IIO_VAL_INT;
case IIO_CHAN_INFO_SAMP_FREQ: case IIO_CHAN_INFO_SAMP_FREQ:
ret = xadc_read_adc_reg(xadc, XADC_REG_CONF2, &val16); ret = xadc_read_samplerate(xadc);
if (ret) if (ret < 0)
return ret; return ret;
div = (val16 & XADC_CONF2_DIV_MASK) >> XADC_CONF2_DIV_OFFSET; *val = ret;
if (div < 2)
div = 2;
*val = xadc_get_dclk_rate(xadc) / div / 26;
return IIO_VAL_INT; return IIO_VAL_INT;
default: default:
return -EINVAL; return -EINVAL;
} }
} }
static int xadc_write_raw(struct iio_dev *indio_dev, static int xadc_write_samplerate(struct xadc *xadc, int val)
struct iio_chan_spec const *chan, int val, int val2, long info)
{ {
struct xadc *xadc = iio_priv(indio_dev);
unsigned long clk_rate = xadc_get_dclk_rate(xadc); unsigned long clk_rate = xadc_get_dclk_rate(xadc);
unsigned int div; unsigned int div;
if (!clk_rate) if (!clk_rate)
return -EINVAL; return -EINVAL;
if (info != IIO_CHAN_INFO_SAMP_FREQ)
return -EINVAL;
if (val <= 0) if (val <= 0)
return -EINVAL; return -EINVAL;
/* Max. 150 kSPS */ /* Max. 150 kSPS */
if (val > 150000) if (val > XADC_MAX_SAMPLERATE)
val = 150000; val = XADC_MAX_SAMPLERATE;
val *= 26; val *= 26;
...@@ -927,7 +954,7 @@ static int xadc_write_raw(struct iio_dev *indio_dev, ...@@ -927,7 +954,7 @@ static int xadc_write_raw(struct iio_dev *indio_dev,
* limit. * limit.
*/ */
div = clk_rate / val; div = clk_rate / val;
if (clk_rate / div / 26 > 150000) if (clk_rate / div / 26 > XADC_MAX_SAMPLERATE)
div++; div++;
if (div < 2) if (div < 2)
div = 2; div = 2;
...@@ -938,6 +965,17 @@ static int xadc_write_raw(struct iio_dev *indio_dev, ...@@ -938,6 +965,17 @@ static int xadc_write_raw(struct iio_dev *indio_dev,
div << XADC_CONF2_DIV_OFFSET); div << XADC_CONF2_DIV_OFFSET);
} }
static int xadc_write_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan, int val, int val2, long info)
{
struct xadc *xadc = iio_priv(indio_dev);
if (info != IIO_CHAN_INFO_SAMP_FREQ)
return -EINVAL;
return xadc_write_samplerate(xadc, val);
}
static const struct iio_event_spec xadc_temp_events[] = { static const struct iio_event_spec xadc_temp_events[] = {
{ {
.type = IIO_EV_TYPE_THRESH, .type = IIO_EV_TYPE_THRESH,
...@@ -1223,6 +1261,21 @@ static int xadc_probe(struct platform_device *pdev) ...@@ -1223,6 +1261,21 @@ static int xadc_probe(struct platform_device *pdev)
if (ret) if (ret)
goto err_free_samplerate_trigger; goto err_free_samplerate_trigger;
/*
* Make sure not to exceed the maximum samplerate since otherwise the
* resulting interrupt storm will soft-lock the system.
*/
if (xadc->ops->flags & XADC_FLAGS_BUFFERED) {
ret = xadc_read_samplerate(xadc);
if (ret < 0)
goto err_free_samplerate_trigger;
if (ret > XADC_MAX_SAMPLERATE) {
ret = xadc_write_samplerate(xadc, XADC_MAX_SAMPLERATE);
if (ret < 0)
goto err_free_samplerate_trigger;
}
}
ret = request_irq(xadc->irq, xadc->ops->interrupt_handler, 0, ret = request_irq(xadc->irq, xadc->ops->interrupt_handler, 0,
dev_name(&pdev->dev), indio_dev); dev_name(&pdev->dev), indio_dev);
if (ret) if (ret)
......
...@@ -79,7 +79,7 @@ int st_sensors_set_odr(struct iio_dev *indio_dev, unsigned int odr) ...@@ -79,7 +79,7 @@ int st_sensors_set_odr(struct iio_dev *indio_dev, unsigned int odr)
struct st_sensor_odr_avl odr_out = {0, 0}; struct st_sensor_odr_avl odr_out = {0, 0};
struct st_sensor_data *sdata = iio_priv(indio_dev); struct st_sensor_data *sdata = iio_priv(indio_dev);
if (!sdata->sensor_settings->odr.addr) if (!sdata->sensor_settings->odr.mask)
return 0; return 0;
err = st_sensors_match_odr(sdata->sensor_settings, odr, &odr_out); err = st_sensors_match_odr(sdata->sensor_settings, odr, &odr_out);
......
...@@ -525,7 +525,7 @@ static int ad5770r_channel_config(struct ad5770r_state *st) ...@@ -525,7 +525,7 @@ static int ad5770r_channel_config(struct ad5770r_state *st)
ret = fwnode_property_read_u32(child, "num", &num); ret = fwnode_property_read_u32(child, "num", &num);
if (ret) if (ret)
return ret; return ret;
if (num > AD5770R_MAX_CHANNELS) if (num >= AD5770R_MAX_CHANNELS)
return -EINVAL; return -EINVAL;
ret = fwnode_property_read_u32_array(child, ret = fwnode_property_read_u32_array(child,
......
...@@ -1617,6 +1617,10 @@ static int __maybe_unused inv_mpu_resume(struct device *dev) ...@@ -1617,6 +1617,10 @@ static int __maybe_unused inv_mpu_resume(struct device *dev)
if (result) if (result)
goto out_unlock; goto out_unlock;
pm_runtime_disable(dev);
pm_runtime_set_active(dev);
pm_runtime_enable(dev);
result = inv_mpu6050_switch_engine(st, true, st->suspended_sensors); result = inv_mpu6050_switch_engine(st, true, st->suspended_sensors);
if (result) if (result)
goto out_unlock; goto out_unlock;
...@@ -1638,13 +1642,18 @@ static int __maybe_unused inv_mpu_suspend(struct device *dev) ...@@ -1638,13 +1642,18 @@ static int __maybe_unused inv_mpu_suspend(struct device *dev)
mutex_lock(&st->lock); mutex_lock(&st->lock);
st->suspended_sensors = 0;
if (pm_runtime_suspended(dev)) {
result = 0;
goto out_unlock;
}
if (iio_buffer_enabled(indio_dev)) { if (iio_buffer_enabled(indio_dev)) {
result = inv_mpu6050_prepare_fifo(st, false); result = inv_mpu6050_prepare_fifo(st, false);
if (result) if (result)
goto out_unlock; goto out_unlock;
} }
st->suspended_sensors = 0;
if (st->chip_config.accl_en) if (st->chip_config.accl_en)
st->suspended_sensors |= INV_MPU6050_SENSOR_ACCL; st->suspended_sensors |= INV_MPU6050_SENSOR_ACCL;
if (st->chip_config.gyro_en) if (st->chip_config.gyro_en)
......
...@@ -337,6 +337,7 @@ enum st_lsm6dsx_fifo_mode { ...@@ -337,6 +337,7 @@ enum st_lsm6dsx_fifo_mode {
* @gain: Configured sensor sensitivity. * @gain: Configured sensor sensitivity.
* @odr: Output data rate of the sensor [Hz]. * @odr: Output data rate of the sensor [Hz].
* @watermark: Sensor watermark level. * @watermark: Sensor watermark level.
* @decimator: Sensor decimation factor.
* @sip: Number of samples in a given pattern. * @sip: Number of samples in a given pattern.
* @ts_ref: Sensor timestamp reference for hw one. * @ts_ref: Sensor timestamp reference for hw one.
* @ext_info: Sensor settings if it is connected to i2c controller * @ext_info: Sensor settings if it is connected to i2c controller
...@@ -350,11 +351,13 @@ struct st_lsm6dsx_sensor { ...@@ -350,11 +351,13 @@ struct st_lsm6dsx_sensor {
u32 odr; u32 odr;
u16 watermark; u16 watermark;
u8 decimator;
u8 sip; u8 sip;
s64 ts_ref; s64 ts_ref;
struct { struct {
const struct st_lsm6dsx_ext_dev_settings *settings; const struct st_lsm6dsx_ext_dev_settings *settings;
u32 slv_odr;
u8 addr; u8 addr;
} ext_info; } ext_info;
}; };
......
...@@ -93,6 +93,7 @@ st_lsm6dsx_get_decimator_val(struct st_lsm6dsx_sensor *sensor, u32 max_odr) ...@@ -93,6 +93,7 @@ st_lsm6dsx_get_decimator_val(struct st_lsm6dsx_sensor *sensor, u32 max_odr)
break; break;
} }
sensor->decimator = decimator;
return i == max_size ? 0 : st_lsm6dsx_decimator_table[i].val; return i == max_size ? 0 : st_lsm6dsx_decimator_table[i].val;
} }
...@@ -337,7 +338,7 @@ static inline int st_lsm6dsx_read_block(struct st_lsm6dsx_hw *hw, u8 addr, ...@@ -337,7 +338,7 @@ static inline int st_lsm6dsx_read_block(struct st_lsm6dsx_hw *hw, u8 addr,
int st_lsm6dsx_read_fifo(struct st_lsm6dsx_hw *hw) int st_lsm6dsx_read_fifo(struct st_lsm6dsx_hw *hw)
{ {
struct st_lsm6dsx_sensor *acc_sensor, *gyro_sensor, *ext_sensor = NULL; struct st_lsm6dsx_sensor *acc_sensor, *gyro_sensor, *ext_sensor = NULL;
int err, acc_sip, gyro_sip, ts_sip, ext_sip, read_len, offset; int err, sip, acc_sip, gyro_sip, ts_sip, ext_sip, read_len, offset;
u16 fifo_len, pattern_len = hw->sip * ST_LSM6DSX_SAMPLE_SIZE; u16 fifo_len, pattern_len = hw->sip * ST_LSM6DSX_SAMPLE_SIZE;
u16 fifo_diff_mask = hw->settings->fifo_ops.fifo_diff.mask; u16 fifo_diff_mask = hw->settings->fifo_ops.fifo_diff.mask;
u8 gyro_buff[ST_LSM6DSX_IIO_BUFF_SIZE]; u8 gyro_buff[ST_LSM6DSX_IIO_BUFF_SIZE];
...@@ -399,19 +400,20 @@ int st_lsm6dsx_read_fifo(struct st_lsm6dsx_hw *hw) ...@@ -399,19 +400,20 @@ int st_lsm6dsx_read_fifo(struct st_lsm6dsx_hw *hw)
acc_sip = acc_sensor->sip; acc_sip = acc_sensor->sip;
ts_sip = hw->ts_sip; ts_sip = hw->ts_sip;
offset = 0; offset = 0;
sip = 0;
while (acc_sip > 0 || gyro_sip > 0 || ext_sip > 0) { while (acc_sip > 0 || gyro_sip > 0 || ext_sip > 0) {
if (gyro_sip > 0) { if (gyro_sip > 0 && !(sip % gyro_sensor->decimator)) {
memcpy(gyro_buff, &hw->buff[offset], memcpy(gyro_buff, &hw->buff[offset],
ST_LSM6DSX_SAMPLE_SIZE); ST_LSM6DSX_SAMPLE_SIZE);
offset += ST_LSM6DSX_SAMPLE_SIZE; offset += ST_LSM6DSX_SAMPLE_SIZE;
} }
if (acc_sip > 0) { if (acc_sip > 0 && !(sip % acc_sensor->decimator)) {
memcpy(acc_buff, &hw->buff[offset], memcpy(acc_buff, &hw->buff[offset],
ST_LSM6DSX_SAMPLE_SIZE); ST_LSM6DSX_SAMPLE_SIZE);
offset += ST_LSM6DSX_SAMPLE_SIZE; offset += ST_LSM6DSX_SAMPLE_SIZE;
} }
if (ext_sip > 0) { if (ext_sip > 0 && !(sip % ext_sensor->decimator)) {
memcpy(ext_buff, &hw->buff[offset], memcpy(ext_buff, &hw->buff[offset],
ST_LSM6DSX_SAMPLE_SIZE); ST_LSM6DSX_SAMPLE_SIZE);
offset += ST_LSM6DSX_SAMPLE_SIZE; offset += ST_LSM6DSX_SAMPLE_SIZE;
...@@ -441,18 +443,25 @@ int st_lsm6dsx_read_fifo(struct st_lsm6dsx_hw *hw) ...@@ -441,18 +443,25 @@ int st_lsm6dsx_read_fifo(struct st_lsm6dsx_hw *hw)
offset += ST_LSM6DSX_SAMPLE_SIZE; offset += ST_LSM6DSX_SAMPLE_SIZE;
} }
if (gyro_sip-- > 0) if (gyro_sip > 0 && !(sip % gyro_sensor->decimator)) {
iio_push_to_buffers_with_timestamp( iio_push_to_buffers_with_timestamp(
hw->iio_devs[ST_LSM6DSX_ID_GYRO], hw->iio_devs[ST_LSM6DSX_ID_GYRO],
gyro_buff, gyro_sensor->ts_ref + ts); gyro_buff, gyro_sensor->ts_ref + ts);
if (acc_sip-- > 0) gyro_sip--;
}
if (acc_sip > 0 && !(sip % acc_sensor->decimator)) {
iio_push_to_buffers_with_timestamp( iio_push_to_buffers_with_timestamp(
hw->iio_devs[ST_LSM6DSX_ID_ACC], hw->iio_devs[ST_LSM6DSX_ID_ACC],
acc_buff, acc_sensor->ts_ref + ts); acc_buff, acc_sensor->ts_ref + ts);
if (ext_sip-- > 0) acc_sip--;
}
if (ext_sip > 0 && !(sip % ext_sensor->decimator)) {
iio_push_to_buffers_with_timestamp( iio_push_to_buffers_with_timestamp(
hw->iio_devs[ST_LSM6DSX_ID_EXT0], hw->iio_devs[ST_LSM6DSX_ID_EXT0],
ext_buff, ext_sensor->ts_ref + ts); ext_buff, ext_sensor->ts_ref + ts);
ext_sip--;
}
sip++;
} }
} }
......
...@@ -2036,11 +2036,21 @@ static int st_lsm6dsx_init_hw_timer(struct st_lsm6dsx_hw *hw) ...@@ -2036,11 +2036,21 @@ static int st_lsm6dsx_init_hw_timer(struct st_lsm6dsx_hw *hw)
return 0; return 0;
} }
static int st_lsm6dsx_init_device(struct st_lsm6dsx_hw *hw) static int st_lsm6dsx_reset_device(struct st_lsm6dsx_hw *hw)
{ {
const struct st_lsm6dsx_reg *reg; const struct st_lsm6dsx_reg *reg;
int err; int err;
/*
* flush hw FIFO before device reset in order to avoid
* possible races on interrupt line 1. If the first interrupt
* line is asserted during hw reset the device will work in
* I3C-only mode (if it is supported)
*/
err = st_lsm6dsx_flush_fifo(hw);
if (err < 0 && err != -ENOTSUPP)
return err;
/* device sw reset */ /* device sw reset */
reg = &hw->settings->reset; reg = &hw->settings->reset;
err = regmap_update_bits(hw->regmap, reg->addr, reg->mask, err = regmap_update_bits(hw->regmap, reg->addr, reg->mask,
...@@ -2059,6 +2069,18 @@ static int st_lsm6dsx_init_device(struct st_lsm6dsx_hw *hw) ...@@ -2059,6 +2069,18 @@ static int st_lsm6dsx_init_device(struct st_lsm6dsx_hw *hw)
msleep(50); msleep(50);
return 0;
}
static int st_lsm6dsx_init_device(struct st_lsm6dsx_hw *hw)
{
const struct st_lsm6dsx_reg *reg;
int err;
err = st_lsm6dsx_reset_device(hw);
if (err < 0)
return err;
/* enable Block Data Update */ /* enable Block Data Update */
reg = &hw->settings->bdu; reg = &hw->settings->bdu;
err = regmap_update_bits(hw->regmap, reg->addr, reg->mask, err = regmap_update_bits(hw->regmap, reg->addr, reg->mask,
......
...@@ -421,7 +421,8 @@ int st_lsm6dsx_shub_set_enable(struct st_lsm6dsx_sensor *sensor, bool enable) ...@@ -421,7 +421,8 @@ int st_lsm6dsx_shub_set_enable(struct st_lsm6dsx_sensor *sensor, bool enable)
settings = sensor->ext_info.settings; settings = sensor->ext_info.settings;
if (enable) { if (enable) {
err = st_lsm6dsx_shub_set_odr(sensor, sensor->odr); err = st_lsm6dsx_shub_set_odr(sensor,
sensor->ext_info.slv_odr);
if (err < 0) if (err < 0)
return err; return err;
} else { } else {
...@@ -459,7 +460,7 @@ st_lsm6dsx_shub_read_oneshot(struct st_lsm6dsx_sensor *sensor, ...@@ -459,7 +460,7 @@ st_lsm6dsx_shub_read_oneshot(struct st_lsm6dsx_sensor *sensor,
if (err < 0) if (err < 0)
return err; return err;
delay = 1000000000 / sensor->odr; delay = 1000000000 / sensor->ext_info.slv_odr;
usleep_range(delay, 2 * delay); usleep_range(delay, 2 * delay);
len = min_t(int, sizeof(data), ch->scan_type.realbits >> 3); len = min_t(int, sizeof(data), ch->scan_type.realbits >> 3);
...@@ -500,8 +501,8 @@ st_lsm6dsx_shub_read_raw(struct iio_dev *iio_dev, ...@@ -500,8 +501,8 @@ st_lsm6dsx_shub_read_raw(struct iio_dev *iio_dev,
iio_device_release_direct_mode(iio_dev); iio_device_release_direct_mode(iio_dev);
break; break;
case IIO_CHAN_INFO_SAMP_FREQ: case IIO_CHAN_INFO_SAMP_FREQ:
*val = sensor->odr / 1000; *val = sensor->ext_info.slv_odr / 1000;
*val2 = (sensor->odr % 1000) * 1000; *val2 = (sensor->ext_info.slv_odr % 1000) * 1000;
ret = IIO_VAL_INT_PLUS_MICRO; ret = IIO_VAL_INT_PLUS_MICRO;
break; break;
case IIO_CHAN_INFO_SCALE: case IIO_CHAN_INFO_SCALE:
...@@ -535,8 +536,20 @@ st_lsm6dsx_shub_write_raw(struct iio_dev *iio_dev, ...@@ -535,8 +536,20 @@ st_lsm6dsx_shub_write_raw(struct iio_dev *iio_dev,
val = val * 1000 + val2 / 1000; val = val * 1000 + val2 / 1000;
err = st_lsm6dsx_shub_get_odr_val(sensor, val, &data); err = st_lsm6dsx_shub_get_odr_val(sensor, val, &data);
if (!err) if (!err) {
sensor->odr = val; struct st_lsm6dsx_hw *hw = sensor->hw;
struct st_lsm6dsx_sensor *ref_sensor;
u8 odr_val;
int odr;
ref_sensor = iio_priv(hw->iio_devs[ST_LSM6DSX_ID_ACC]);
odr = st_lsm6dsx_check_odr(ref_sensor, val, &odr_val);
if (odr < 0)
return odr;
sensor->ext_info.slv_odr = val;
sensor->odr = odr;
}
break; break;
} }
default: default:
...@@ -613,6 +626,7 @@ st_lsm6dsx_shub_alloc_iiodev(struct st_lsm6dsx_hw *hw, ...@@ -613,6 +626,7 @@ st_lsm6dsx_shub_alloc_iiodev(struct st_lsm6dsx_hw *hw,
const struct st_lsm6dsx_ext_dev_settings *info, const struct st_lsm6dsx_ext_dev_settings *info,
u8 i2c_addr, const char *name) u8 i2c_addr, const char *name)
{ {
enum st_lsm6dsx_sensor_id ref_id = ST_LSM6DSX_ID_ACC;
struct iio_chan_spec *ext_channels; struct iio_chan_spec *ext_channels;
struct st_lsm6dsx_sensor *sensor; struct st_lsm6dsx_sensor *sensor;
struct iio_dev *iio_dev; struct iio_dev *iio_dev;
...@@ -628,7 +642,8 @@ st_lsm6dsx_shub_alloc_iiodev(struct st_lsm6dsx_hw *hw, ...@@ -628,7 +642,8 @@ st_lsm6dsx_shub_alloc_iiodev(struct st_lsm6dsx_hw *hw,
sensor = iio_priv(iio_dev); sensor = iio_priv(iio_dev);
sensor->id = id; sensor->id = id;
sensor->hw = hw; sensor->hw = hw;
sensor->odr = info->odr_table.odr_avl[0].milli_hz; sensor->odr = hw->settings->odr_table[ref_id].odr_avl[0].milli_hz;
sensor->ext_info.slv_odr = info->odr_table.odr_avl[0].milli_hz;
sensor->gain = info->fs_table.fs_avl[0].gain; sensor->gain = info->fs_table.fs_avl[0].gain;
sensor->ext_info.settings = info; sensor->ext_info.settings = info;
sensor->ext_info.addr = i2c_addr; sensor->ext_info.addr = i2c_addr;
......
...@@ -915,14 +915,11 @@ static ssize_t iio_write_channel_info(struct device *dev, ...@@ -915,14 +915,11 @@ static ssize_t iio_write_channel_info(struct device *dev,
return -EINVAL; return -EINVAL;
integer = ch; integer = ch;
} else { } else {
ret = iio_str_to_fixpoint(buf, fract_mult, &integer, &fract); ret = __iio_str_to_fixpoint(buf, fract_mult, &integer, &fract,
scale_db);
if (ret) if (ret)
return ret; return ret;
} }
ret = __iio_str_to_fixpoint(buf, fract_mult, &integer, &fract,
scale_db);
if (ret)
return ret;
ret = indio_dev->info->write_raw(indio_dev, this_attr->c, ret = indio_dev->info->write_raw(indio_dev, this_attr->c,
integer, fract, this_attr->address); integer, fract, this_attr->address);
......
...@@ -2725,8 +2725,10 @@ static int comedi_open(struct inode *inode, struct file *file) ...@@ -2725,8 +2725,10 @@ static int comedi_open(struct inode *inode, struct file *file)
} }
cfp = kzalloc(sizeof(*cfp), GFP_KERNEL); cfp = kzalloc(sizeof(*cfp), GFP_KERNEL);
if (!cfp) if (!cfp) {
comedi_dev_put(dev);
return -ENOMEM; return -ENOMEM;
}
cfp->dev = dev; cfp->dev = dev;
......
...@@ -92,6 +92,7 @@ static int dt2815_ao_insn(struct comedi_device *dev, struct comedi_subdevice *s, ...@@ -92,6 +92,7 @@ static int dt2815_ao_insn(struct comedi_device *dev, struct comedi_subdevice *s,
int ret; int ret;
for (i = 0; i < insn->n; i++) { for (i = 0; i < insn->n; i++) {
/* FIXME: lo bit 0 chooses voltage output or current output */
lo = ((data[i] & 0x0f) << 4) | (chan << 1) | 0x01; lo = ((data[i] & 0x0f) << 4) | (chan << 1) | 0x01;
hi = (data[i] & 0xff0) >> 4; hi = (data[i] & 0xff0) >> 4;
...@@ -105,6 +106,8 @@ static int dt2815_ao_insn(struct comedi_device *dev, struct comedi_subdevice *s, ...@@ -105,6 +106,8 @@ static int dt2815_ao_insn(struct comedi_device *dev, struct comedi_subdevice *s,
if (ret) if (ret)
return ret; return ret;
outb(hi, dev->iobase + DT2815_DATA);
devpriv->ao_readback[chan] = data[i]; devpriv->ao_readback[chan] = data[i];
} }
return i; return i;
......
...@@ -228,8 +228,7 @@ int gasket_sysfs_create_entries(struct device *device, ...@@ -228,8 +228,7 @@ int gasket_sysfs_create_entries(struct device *device,
} }
mutex_lock(&mapping->mutex); mutex_lock(&mapping->mutex);
for (i = 0; strcmp(attrs[i].attr.attr.name, GASKET_ARRAY_END_MARKER); for (i = 0; attrs[i].attr.attr.name != NULL; i++) {
i++) {
if (mapping->attribute_count == GASKET_SYSFS_MAX_NODES) { if (mapping->attribute_count == GASKET_SYSFS_MAX_NODES) {
dev_err(device, dev_err(device,
"Maximum number of sysfs nodes reached for device\n"); "Maximum number of sysfs nodes reached for device\n");
......
...@@ -30,10 +30,6 @@ ...@@ -30,10 +30,6 @@
*/ */
#define GASKET_SYSFS_MAX_NODES 196 #define GASKET_SYSFS_MAX_NODES 196
/* End markers for sysfs struct arrays. */
#define GASKET_ARRAY_END_TOKEN GASKET_RESERVED_ARRAY_END
#define GASKET_ARRAY_END_MARKER __stringify(GASKET_ARRAY_END_TOKEN)
/* /*
* Terminator struct for a gasket_sysfs_attr array. Must be at the end of * Terminator struct for a gasket_sysfs_attr array. Must be at the end of
* all gasket_sysfs_attribute arrays. * all gasket_sysfs_attribute arrays.
......
...@@ -83,9 +83,6 @@ static int vnt_set_keymode(struct ieee80211_hw *hw, u8 *mac_addr, ...@@ -83,9 +83,6 @@ static int vnt_set_keymode(struct ieee80211_hw *hw, u8 *mac_addr,
case VNT_KEY_PAIRWISE: case VNT_KEY_PAIRWISE:
key_mode |= mode; key_mode |= mode;
key_inx = 4; key_inx = 4;
/* Don't save entry for pairwise key for station mode */
if (priv->op_mode == NL80211_IFTYPE_STATION)
clear_bit(entry, &priv->key_entry_inuse);
break; break;
default: default:
return -EINVAL; return -EINVAL;
...@@ -109,7 +106,6 @@ static int vnt_set_keymode(struct ieee80211_hw *hw, u8 *mac_addr, ...@@ -109,7 +106,6 @@ static int vnt_set_keymode(struct ieee80211_hw *hw, u8 *mac_addr,
int vnt_set_keys(struct ieee80211_hw *hw, struct ieee80211_sta *sta, int vnt_set_keys(struct ieee80211_hw *hw, struct ieee80211_sta *sta,
struct ieee80211_vif *vif, struct ieee80211_key_conf *key) struct ieee80211_vif *vif, struct ieee80211_key_conf *key)
{ {
struct ieee80211_bss_conf *conf = &vif->bss_conf;
struct vnt_private *priv = hw->priv; struct vnt_private *priv = hw->priv;
u8 *mac_addr = NULL; u8 *mac_addr = NULL;
u8 key_dec_mode = 0; u8 key_dec_mode = 0;
...@@ -154,16 +150,12 @@ int vnt_set_keys(struct ieee80211_hw *hw, struct ieee80211_sta *sta, ...@@ -154,16 +150,12 @@ int vnt_set_keys(struct ieee80211_hw *hw, struct ieee80211_sta *sta,
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE) { if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE)
vnt_set_keymode(hw, mac_addr, key, VNT_KEY_PAIRWISE, vnt_set_keymode(hw, mac_addr, key, VNT_KEY_PAIRWISE,
key_dec_mode, true); key_dec_mode, true);
} else { else
vnt_set_keymode(hw, mac_addr, key, VNT_KEY_DEFAULTKEY, vnt_set_keymode(hw, mac_addr, key, VNT_KEY_GROUP_ADDRESS,
key_dec_mode, true); key_dec_mode, true);
vnt_set_keymode(hw, (u8 *)conf->bssid, key,
VNT_KEY_GROUP_ADDRESS, key_dec_mode, true);
}
return 0; return 0;
} }
...@@ -625,8 +625,6 @@ static int vnt_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) ...@@ -625,8 +625,6 @@ static int vnt_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
priv->op_mode = vif->type; priv->op_mode = vif->type;
vnt_set_bss_mode(priv);
/* LED blink on TX */ /* LED blink on TX */
vnt_mac_set_led(priv, LEDSTS_STS, LEDSTS_INTER); vnt_mac_set_led(priv, LEDSTS_STS, LEDSTS_INTER);
...@@ -713,7 +711,6 @@ static void vnt_bss_info_changed(struct ieee80211_hw *hw, ...@@ -713,7 +711,6 @@ static void vnt_bss_info_changed(struct ieee80211_hw *hw,
priv->basic_rates = conf->basic_rates; priv->basic_rates = conf->basic_rates;
vnt_update_top_rates(priv); vnt_update_top_rates(priv);
vnt_set_bss_mode(priv);
dev_dbg(&priv->usb->dev, "basic rates %x\n", conf->basic_rates); dev_dbg(&priv->usb->dev, "basic rates %x\n", conf->basic_rates);
} }
...@@ -742,11 +739,14 @@ static void vnt_bss_info_changed(struct ieee80211_hw *hw, ...@@ -742,11 +739,14 @@ static void vnt_bss_info_changed(struct ieee80211_hw *hw,
priv->short_slot_time = false; priv->short_slot_time = false;
vnt_set_short_slot_time(priv); vnt_set_short_slot_time(priv);
vnt_update_ifs(priv);
vnt_set_vga_gain_offset(priv, priv->bb_vga[0]); vnt_set_vga_gain_offset(priv, priv->bb_vga[0]);
vnt_update_pre_ed_threshold(priv, false); vnt_update_pre_ed_threshold(priv, false);
} }
if (changed & (BSS_CHANGED_BASIC_RATES | BSS_CHANGED_ERP_PREAMBLE |
BSS_CHANGED_ERP_SLOT))
vnt_set_bss_mode(priv);
if (changed & BSS_CHANGED_TXPOWER) if (changed & BSS_CHANGED_TXPOWER)
vnt_rf_setpower(priv, priv->current_rate, vnt_rf_setpower(priv, priv->current_rate,
conf->chandef.chan->hw_value); conf->chandef.chan->hw_value);
...@@ -770,12 +770,15 @@ static void vnt_bss_info_changed(struct ieee80211_hw *hw, ...@@ -770,12 +770,15 @@ static void vnt_bss_info_changed(struct ieee80211_hw *hw,
vnt_mac_reg_bits_on(priv, MAC_REG_TFTCTL, vnt_mac_reg_bits_on(priv, MAC_REG_TFTCTL,
TFTCTL_TSFCNTREN); TFTCTL_TSFCNTREN);
vnt_adjust_tsf(priv, conf->beacon_rate->hw_value,
conf->sync_tsf, priv->current_tsf);
vnt_mac_set_beacon_interval(priv, conf->beacon_int); vnt_mac_set_beacon_interval(priv, conf->beacon_int);
vnt_reset_next_tbtt(priv, conf->beacon_int); vnt_reset_next_tbtt(priv, conf->beacon_int);
vnt_adjust_tsf(priv, conf->beacon_rate->hw_value,
conf->sync_tsf, priv->current_tsf);
vnt_update_next_tbtt(priv,
conf->sync_tsf, conf->beacon_int);
} else { } else {
vnt_clear_current_tsf(priv); vnt_clear_current_tsf(priv);
...@@ -809,15 +812,11 @@ static void vnt_configure(struct ieee80211_hw *hw, ...@@ -809,15 +812,11 @@ static void vnt_configure(struct ieee80211_hw *hw,
{ {
struct vnt_private *priv = hw->priv; struct vnt_private *priv = hw->priv;
u8 rx_mode = 0; u8 rx_mode = 0;
int rc;
*total_flags &= FIF_ALLMULTI | FIF_OTHER_BSS | FIF_BCN_PRBRESP_PROMISC; *total_flags &= FIF_ALLMULTI | FIF_OTHER_BSS | FIF_BCN_PRBRESP_PROMISC;
rc = vnt_control_in(priv, MESSAGE_TYPE_READ, MAC_REG_RCR, vnt_control_in(priv, MESSAGE_TYPE_READ, MAC_REG_RCR,
MESSAGE_REQUEST_MACREG, sizeof(u8), &rx_mode); MESSAGE_REQUEST_MACREG, sizeof(u8), &rx_mode);
if (!rc)
rx_mode = RCR_MULTICAST | RCR_BROADCAST;
dev_dbg(&priv->usb->dev, "rx mode in = %x\n", rx_mode); dev_dbg(&priv->usb->dev, "rx mode in = %x\n", rx_mode);
...@@ -856,8 +855,12 @@ static int vnt_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, ...@@ -856,8 +855,12 @@ static int vnt_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
case SET_KEY: case SET_KEY:
return vnt_set_keys(hw, sta, vif, key); return vnt_set_keys(hw, sta, vif, key);
case DISABLE_KEY: case DISABLE_KEY:
if (test_bit(key->hw_key_idx, &priv->key_entry_inuse)) if (test_bit(key->hw_key_idx, &priv->key_entry_inuse)) {
clear_bit(key->hw_key_idx, &priv->key_entry_inuse); clear_bit(key->hw_key_idx, &priv->key_entry_inuse);
vnt_mac_disable_keyentry(priv, key->hw_key_idx);
}
default: default:
break; break;
} }
......
...@@ -207,7 +207,8 @@ static void vnt_int_process_data(struct vnt_private *priv) ...@@ -207,7 +207,8 @@ static void vnt_int_process_data(struct vnt_private *priv)
priv->wake_up_count = priv->wake_up_count =
priv->hw->conf.listen_interval; priv->hw->conf.listen_interval;
--priv->wake_up_count; if (priv->wake_up_count)
--priv->wake_up_count;
/* Turn on wake up to listen next beacon */ /* Turn on wake up to listen next beacon */
if (priv->wake_up_count == 1) if (priv->wake_up_count == 1)
......
...@@ -600,7 +600,7 @@ void iio_device_unregister(struct iio_dev *indio_dev); ...@@ -600,7 +600,7 @@ void iio_device_unregister(struct iio_dev *indio_dev);
* 0 on success, negative error number on failure. * 0 on success, negative error number on failure.
*/ */
#define devm_iio_device_register(dev, indio_dev) \ #define devm_iio_device_register(dev, indio_dev) \
__devm_iio_device_register((dev), (indio_dev), THIS_MODULE); __devm_iio_device_register((dev), (indio_dev), THIS_MODULE)
int __devm_iio_device_register(struct device *dev, struct iio_dev *indio_dev, int __devm_iio_device_register(struct device *dev, struct iio_dev *indio_dev,
struct module *this_mod); struct module *this_mod);
void devm_iio_device_unregister(struct device *dev, struct iio_dev *indio_dev); void devm_iio_device_unregister(struct device *dev, struct iio_dev *indio_dev);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment