First set of IIO fixes for the 5.7 cycle.
Includes one MAINTAINERS update to avoid people getting a lot of bounce messages and complaining about it. * MAINTAINERS - Drop Stefan Popa's Analog Devices email address in favour of Michael Hennerich. * core - Fix handling of dB sysfs inputs. - Drop a stray semi colon in macro definition. * ad5770r - Fix an off by one in chec on maximum number of channels. * ad7192 - Fix a null pointer de-reference due to the name previously being retrieved from the spi_get_device_id call which no longer works as the relevant table was removed. * ad7797 - Use correct attribute group. * counter/104-quad-8 - Add locks to prevent some race conditions. * inv-mpu6050 - Fix issues around suspend / resume clashing with runtime PM. * stm32-adc - Fix sleep in invalid context - Fix id relative path error in device tree binding doc. * st_lsm6dsx - Fix a read alignment issue on an untagged FIFO. - Handle odr for slave to properly compute the FIFO data layout / pattern. - Flush the HW FIFO before resettting the device to avoid a race on interrupt line 1. * st_sensors - Rely on ODR mask not ODR address to identify if the ODR can be set. Some devices have an ODR address of 0. * ti-ads8344 - Byte ordering was wrong - fix it. * xilinx-xadc - Fix inverted logic in powering down the second ADC. - Fix clearing interrupt when enabling the trigger. - Fix configuration of sequencer when in simultaneous sampling mode. - Limit initial sampling rate as done for runtime configured ones. -----BEGIN PGP SIGNATURE----- iQJFBAABCAAvFiEEbilms4eEBlKRJoGxVIU0mcT0FogFAl6cgbkRHGppYzIzQGtl cm5lbC5vcmcACgkQVIU0mcT0Foj/qg//c1TF2fhXEuGNua2M9PzaO+UgEkymF5lD R9bQPOPLXesTxmIZDIPWuIYaoFOIBrB6Kc9DvE8+7apVc0I/JFYmuXSjY1LGoBj5 6WSrbtfAHYD5HBY/ZQq92iw+feFlctWtpp7H6Ngy2c7lQy8OKMhrHOA1NgbC++HH 5OA5uoMD7Fo0mvAGY7/74DiJFEKG/PUUrGWSbH792Mh0EmvXgyFkWyHEXCUrS6Qo gbaLk8mZsTac3iwYoLk7AdYyQpEdQD/tnCHpBzHHdTdDcQuKHbknP9t/zFuEkM/e hAH6H/cOr+IMOkMvYe1HDRQsOwkPQppz2GnxtWAUwCV8Shkn7khOExnV17zqUfJx NSzX60/iZWj53cAJkp4ZW4Uf6dqEEeCvV9jzWngXsCTRz96tpwJoLDilTEStSp1r 0d17OpFSkrPoJQR6miK+wCeoA4CcLLfGJXG1BcDpsT0qgHq/TNx7P7AX55Ip//IL uu7qCDzFHAct8C50r1725pthsX/69PI34F8wHQ+bSt8eBlEMc/+iDavXO7MPvNNi Xd/Je0c+6pV15X9lCN7RqujDjBb2yMzX9f3Omq0txc4ughYGYb3QLwAfBidjW6Wy fI6AgBXOdqUOlFgq0ncDUVmS73AMfb2ilvstfY+cfhLrtGIzZNwin1znSIxcesaS tUGD9Xk/bPc= =SmJy -----END PGP SIGNATURE----- Merge tag 'iio-fixes-for-5.7a' of git://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio into staging-linus Jonathan writes: First set of IIO fixes for the 5.7 cycle. Includes one MAINTAINERS update to avoid people getting a lot of bounce messages and complaining about it. * MAINTAINERS - Drop Stefan Popa's Analog Devices email address in favour of Michael Hennerich. * core - Fix handling of dB sysfs inputs. - Drop a stray semi colon in macro definition. * ad5770r - Fix an off by one in chec on maximum number of channels. * ad7192 - Fix a null pointer de-reference due to the name previously being retrieved from the spi_get_device_id call which no longer works as the relevant table was removed. * ad7797 - Use correct attribute group. * counter/104-quad-8 - Add locks to prevent some race conditions. * inv-mpu6050 - Fix issues around suspend / resume clashing with runtime PM. * stm32-adc - Fix sleep in invalid context - Fix id relative path error in device tree binding doc. * st_lsm6dsx - Fix a read alignment issue on an untagged FIFO. - Handle odr for slave to properly compute the FIFO data layout / pattern. - Flush the HW FIFO before resettting the device to avoid a race on interrupt line 1. * st_sensors - Rely on ODR mask not ODR address to identify if the ODR can be set. Some devices have an ODR address of 0. * ti-ads8344 - Byte ordering was wrong - fix it. * xilinx-xadc - Fix inverted logic in powering down the second ADC. - Fix clearing interrupt when enabling the trigger. - Fix configuration of sequencer when in simultaneous sampling mode. - Limit initial sampling rate as done for runtime configured ones. * tag 'iio-fixes-for-5.7a' of git://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio: 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 iio: imu: st_lsm6dsx: specify slave odr in slv_odr iio: imu: st_lsm6dsx: fix read misalignment on untagged FIFO iio: adc: stm32-adc: fix sleep in atomic context iio:ad7797: Use correct attribute_group
This commit is contained in:
commit
c532cc617e
|
@ -1,7 +1,7 @@
|
||||||
# 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
|
||||||
|
|
15
MAINTAINERS
15
MAINTAINERS
|
@ -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
|
||||||
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*
|
||||||
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
|
||||||
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
|
||||||
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
|
||||||
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
|
||||||
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
|
||||||
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");
|
||||||
* @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,
|
||||||
/* 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,
|
||||||
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,
|
||||||
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,
|
||||||
/* 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,
|
||||||
/* 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,
|
||||||
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,
|
||||||
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,
|
||||||
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,
|
||||||
/* 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,
|
||||||
/* 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,
|
||||||
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,
|
||||||
/* 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,
|
||||||
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,
|
||||||
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,
|
||||||
/* 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,
|
||||||
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,
|
||||||
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,
|
||||||
/* 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,
|
||||||
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,
|
||||||
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,
|
||||||
/* 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[] = {
|
||||||
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,
|
||||||
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,
|
||||||
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,
|
||||||
/* 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,
|
||||||
{
|
{
|
||||||
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,
|
||||||
{
|
{
|
||||||
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,
|
||||||
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,
|
||||||
/* 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,
|
||||||
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,
|
||||||
/* 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,
|
||||||
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,
|
||||||
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,
|
||||||
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,
|
||||||
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,
|
||||||
/* 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,
|
||||||
/* 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)
|
||||||
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 @@
|
||||||
#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 {
|
||||||
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 {
|
||||||
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)
|
||||||
|
|
||||||
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)
|
||||||
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[] = {
|
||||||
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)
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
||||||
}
|
}
|
||||||
|
|
||||||
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 = {
|
||||||
.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)
|
||||||
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);
|
||||||
|
|
||||||
iio_trigger_poll_chained(indio_dev->trig);
|
/*
|
||||||
|
* 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);
|
||||||
|
|
||||||
|
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)
|
||||||
{
|
{
|
||||||
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)
|
||||||
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 {
|
||||||
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,
|
||||||
|
|
||||||
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;
|
||||||
|
|
||||||
#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)
|
||||||
|
|
||||||
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)
|
||||||
{
|
{
|
||||||
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)
|
||||||
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 = {
|
||||||
.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,
|
||||||
*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,
|
||||||
* 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,
|
||||||
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)
|
||||||
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)
|
||||||
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)
|
||||||
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)
|
||||||
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)
|
||||||
|
|
||||||
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 {
|
||||||
* @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 {
|
||||||
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)
|
||||||
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,
|
||||||
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)
|
||||||
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)
|
||||||
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)
|
||||||
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)
|
||||||
|
|
||||||
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)
|
||||||
|
|
||||||
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,
|
||||||
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,
|
||||||
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,
|
||||||
|
|
||||||
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,
|
||||||
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,
|
||||||
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,
|
||||||
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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in New Issue