IIO new device support, features and minor fixes for 5.20
Several on-running cleanup efforts dominate this time, plus the DMA safety alignment issue identified due to improved understanding of the restrictions as a result of Catalin Marinas' efforts in that area. One immutable branch in here due to MFD and SPMI elements needed for the qcom-rradc driver. Device support * bmi088 - Add support for bmi085 (accelerometer part of IMU) - Add support for bmi090l (accelerometer part of IMU) * mcp4922 - Add support for single channel device MCP4921 * rzg2l-adc - Add compatible and minor tweaks to support RZ/G2UL ADC * sca3300 - Add support for scl3300 including refactoring driver to support multiple device types and cleanup noticed whilst working on driver. * spmi-rradc - New driver for Qualcomm SPMI Round Robin ADC including necessary additional utility functions in SPMI core and related MFD driver. * ti-dac55781 - Add compatible for DAC121C081 which is very similar to existing parts. Features * core - Warn on iio_trigger_get() on an unregistered IIO trigger. * bma400 - Triggered buffer support - Activity and step counting - Misc driver improvements such as devm and header ordering * cm32181 - Add PM support. * cros_ec - Sensor location support * sx9324 - Add precharge resistor setting - Add internal compensation resistor setting - Add CS idle/sleep mode. * sx9360 - Add precharge resistor setting * vl53l0x - Handle reset GPIO, regulator and relax handling of irq type. Cleanup and minor fixes: Treewide changes - Cleanup of error handling in remove functions in many drivers. - Update dt-binding maintainers for a number of ADI bindings. - Several sets of conversion of drivers from device tree specific to generic device properties. Includes fixing up various related header and Kconfig issues. - Drop include of of.h from iio.h and fix up drivers that need to include it directly. - More moves of clusters of drivers into appropriate IIO_XXX namespaces. - Tree wide fix of a long running bug around DMA safety requirements. IIO was using __cacheline_aligned to pad iio_priv() structures. This worked for a long time by coincidence, but correct alignment is ARCH_KMALLOC_MINALIGN. As there is activity around this area, introduce an IIO local IIO_DMA_MINALIGN to allow for changing it in one place rather than every driver in future. Note, there have been no reports of this bug in the wild, and it may not happen on any platforms supported by upstream, so no rush to backport these fixes. Other cleanup * core - Switch to ida_alloc()/free() - Drop unused iio_get_time_res() - Octal permissions and DEVICE_ATTR_* macros. - Cleanup bared unsigned usage. * MAINTAINERS - Add include/dt-bindings/iio/ to the main IIO entry. * ad5380 - Comment syntax fix. * ad74413r - Call to for_each_set_bit_from(), with from value as 0 replaced. * ad7768-1 - Drop explicit setting of INDIO_BUFFER_TRIGGERED as now done by the core. * adxl345 - Fix wrong address in dt-binding example. * adxl367 - Drop extra update of FIFO watermark. * at91-sama5d2 - Limit requested watermark to the hwfifo size. * bmg160, bme680 - Typos * cio-dac - Switch to iomap rather than direct use of ioports * kxsd9 - Replace CONFIG_PM guards with new PM macros that let the compiler cleanly remove the unused code and structures when !CONFIG_PM * lsm6dsx - Use new pm_sleep_ptr() and EXPORT_SIMPLE_DEV_PM_OPS(). Then move to Namespace. * meson_saradc - general cleanup. - Avoid attaching resources to iio_dev->dev - Use same struct device for all error messages - Convert to dev_err_probe() and use local struct device *dev to reduce code complexity. - Use devm_clk_get_optional() instead of hand rolling. - Use regmap_read_poll_timeout() instead of hand rolling. * mma7660 - Drop ACPI_PTR() use that is unhelpful. * mpu3050 - Stop exporting symbols not used outside of module - Switch to new DEFINE_RUNTIME_DEV_PM_OPS() macro and move to Namespace. * ping - Typo fix * qcom-spmi-rradc - Typo fix * sc27xx - Convert to generic struct u32_fract * srf08 - Drop a redundant check on !val * st_lsm6dsx - Limit the requested watermark to the hwfifo size. * stm32-adc - Use generic_handle_domain_irq() instead of opencoding. - Fix handling of ADC disable. * stm32-dac - Use str_enabled_disable() instead of open coding. * stx104 - Switch to iomap rather than direct use of ioports * tsc2046 - Drop explicit setting of INDIO_BUFFER_TRIGGERED as now done by the core. * tsl2563 - Replace flush_scheduled_work() with cancel_delayed_work_sync() - Replace cancel_delayed_work() with cancel_delayed_work_sync() * vl53l0x - Make the VDD regulator optional by allowing a dummy regulator. -----BEGIN PGP SIGNATURE----- iQJFBAABCAAvFiEEbilms4eEBlKRJoGxVIU0mcT0FogFAmLQBwARHGppYzIzQGtl cm5lbC5vcmcACgkQVIU0mcT0FohMHRAAi3nPM3IchXe886olumRgX5ke75vU+FNT sqQjqlpl6X7j5yNLU+HF6lC7zg3QzDnfWJ3Uo4C7s2sW7zO0997lkFx4jvF3yW9y 0nLDgYm1Y1te/qR84BE355pMEsYEJVZyPI/Z8UfuBh6IfnSDeTE5ZwCvlRMAchtp AX+j1114FQvZ8yfdIlFjlN4vYSxCGgEZzfWYhpch/Jv1y2Q0L17bpv/KWGt1AYaF VugmKoNTM3WzIABBNGWQ4l4ZVVuVpuiVUL90AKv6Qf+yDSqw94tuIM0NZpJ1rqLr 7tH568m7Eewh7zBp88PRB9XDiZVERvzdVQaT22+wlX+Vhn/SKeoK8PPpdLWD1YyG hXB0p+FGKncoKKgK1w9L7qRRNmsQDHowNHYMSjnzeBuyGQyEqwAXzNvvbiCqHh8y 7b8GW+CYo7//wIarg74Xl+/4LwdCGcMUJNuTm1efEgC7yGToY7JD63DNo3sylaII bfoT06/yogaay/rVLZs5n+MvDONaDt4AbTTErG48s0TzqD/O8Ys85AF0IvKwQ80N WMxe4y+gdJ6VuU+ww9+6WdUzxnx+5gt+ZA2iLxZFekOIUi3Tj+q47F+17Jvwyt7U 2wQzdtvNhHPwD5CqYpxD4iH/z5YFCtIHKjmUsVyAWGVbeuSS/QvFzpf39YWxBWO+ W1w6RStUbXo= =IcsE -----END PGP SIGNATURE----- Merge tag 'iio-for-5.20a' of https://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio into char-misc-next Jonathan writes: IIO new device support, features and minor fixes for 5.20 Several on-running cleanup efforts dominate this time, plus the DMA safety alignment issue identified due to improved understanding of the restrictions as a result of Catalin Marinas' efforts in that area. One immutable branch in here due to MFD and SPMI elements needed for the qcom-rradc driver. Device support * bmi088 - Add support for bmi085 (accelerometer part of IMU) - Add support for bmi090l (accelerometer part of IMU) * mcp4922 - Add support for single channel device MCP4921 * rzg2l-adc - Add compatible and minor tweaks to support RZ/G2UL ADC * sca3300 - Add support for scl3300 including refactoring driver to support multiple device types and cleanup noticed whilst working on driver. * spmi-rradc - New driver for Qualcomm SPMI Round Robin ADC including necessary additional utility functions in SPMI core and related MFD driver. * ti-dac55781 - Add compatible for DAC121C081 which is very similar to existing parts. Features * core - Warn on iio_trigger_get() on an unregistered IIO trigger. * bma400 - Triggered buffer support - Activity and step counting - Misc driver improvements such as devm and header ordering * cm32181 - Add PM support. * cros_ec - Sensor location support * sx9324 - Add precharge resistor setting - Add internal compensation resistor setting - Add CS idle/sleep mode. * sx9360 - Add precharge resistor setting * vl53l0x - Handle reset GPIO, regulator and relax handling of irq type. Cleanup and minor fixes: Treewide changes - Cleanup of error handling in remove functions in many drivers. - Update dt-binding maintainers for a number of ADI bindings. - Several sets of conversion of drivers from device tree specific to generic device properties. Includes fixing up various related header and Kconfig issues. - Drop include of of.h from iio.h and fix up drivers that need to include it directly. - More moves of clusters of drivers into appropriate IIO_XXX namespaces. - Tree wide fix of a long running bug around DMA safety requirements. IIO was using __cacheline_aligned to pad iio_priv() structures. This worked for a long time by coincidence, but correct alignment is ARCH_KMALLOC_MINALIGN. As there is activity around this area, introduce an IIO local IIO_DMA_MINALIGN to allow for changing it in one place rather than every driver in future. Note, there have been no reports of this bug in the wild, and it may not happen on any platforms supported by upstream, so no rush to backport these fixes. Other cleanup * core - Switch to ida_alloc()/free() - Drop unused iio_get_time_res() - Octal permissions and DEVICE_ATTR_* macros. - Cleanup bared unsigned usage. * MAINTAINERS - Add include/dt-bindings/iio/ to the main IIO entry. * ad5380 - Comment syntax fix. * ad74413r - Call to for_each_set_bit_from(), with from value as 0 replaced. * ad7768-1 - Drop explicit setting of INDIO_BUFFER_TRIGGERED as now done by the core. * adxl345 - Fix wrong address in dt-binding example. * adxl367 - Drop extra update of FIFO watermark. * at91-sama5d2 - Limit requested watermark to the hwfifo size. * bmg160, bme680 - Typos * cio-dac - Switch to iomap rather than direct use of ioports * kxsd9 - Replace CONFIG_PM guards with new PM macros that let the compiler cleanly remove the unused code and structures when !CONFIG_PM * lsm6dsx - Use new pm_sleep_ptr() and EXPORT_SIMPLE_DEV_PM_OPS(). Then move to Namespace. * meson_saradc - general cleanup. - Avoid attaching resources to iio_dev->dev - Use same struct device for all error messages - Convert to dev_err_probe() and use local struct device *dev to reduce code complexity. - Use devm_clk_get_optional() instead of hand rolling. - Use regmap_read_poll_timeout() instead of hand rolling. * mma7660 - Drop ACPI_PTR() use that is unhelpful. * mpu3050 - Stop exporting symbols not used outside of module - Switch to new DEFINE_RUNTIME_DEV_PM_OPS() macro and move to Namespace. * ping - Typo fix * qcom-spmi-rradc - Typo fix * sc27xx - Convert to generic struct u32_fract * srf08 - Drop a redundant check on !val * st_lsm6dsx - Limit the requested watermark to the hwfifo size. * stm32-adc - Use generic_handle_domain_irq() instead of opencoding. - Fix handling of ADC disable. * stm32-dac - Use str_enabled_disable() instead of open coding. * stx104 - Switch to iomap rather than direct use of ioports * tsc2046 - Drop explicit setting of INDIO_BUFFER_TRIGGERED as now done by the core. * tsl2563 - Replace flush_scheduled_work() with cancel_delayed_work_sync() - Replace cancel_delayed_work() with cancel_delayed_work_sync() * vl53l0x - Make the VDD regulator optional by allowing a dummy regulator. * tag 'iio-for-5.20a' of https://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio: (244 commits) iio: adc: xilinx-xadc: Drop duplicate NULL check in xadc_parse_dt() iio: adc: xilinx-xadc: Make use of device properties iio: light: cm32181: Add PM support iio: adc: ad778-1: do not explicity set INDIO_BUFFER_TRIGGERED mode iio: adc: ti-tsc2046: do not explicity set INDIO_BUFFER_TRIGGERED mode iio: adc: stm32-adc: disable adc before calibration iio: adc: stm32-adc: make safe adc disable iio: dac: ad5380: align '*' each line and drop unneeded blank line iio: adc: qcom-spmi-rradc: Fix spelling mistake "coherrency" -> "coherency" iio: Don't use bare "unsigned" dt-bindings: iio: dac: mcp4922: expand for mcp4921 support iio: dac: mcp4922: add support to mcp4921 iio: chemical: sps30: Move symbol exports into IIO_SPS30 namespace iio: pressure: bmp280: Move symbol exports to IIO_BMP280 namespace iio: imu: bmi160: Move exported symbols to IIO_BMI160 namespace iio: adc: stm32-adc: Use generic_handle_domain_irq() proximity: vl53l0x: Make VDD regulator actually optional MAINTAINERS: add include/dt-bindings/iio to IIO SUBSYSTEM AND DRIVERS dt-bindings: iio/accel: Fix adi,adxl345/6 example I2C address iio: gyro: bmg160: Fix typo in comment ...
This commit is contained in:
Коммит
2a3c8f8a44
|
@ -79,6 +79,11 @@ Description:
|
|||
* "accel-base"
|
||||
* "accel-display"
|
||||
|
||||
For devices where an accelerometer is housed in the swivel camera subassembly
|
||||
(for AR application), the following standardized label is used:
|
||||
|
||||
* "accel-camera"
|
||||
|
||||
What: /sys/bus/iio/devices/iio:deviceX/current_timestamp_clock
|
||||
KernelVersion: 4.5
|
||||
Contact: linux-iio@vger.kernel.org
|
||||
|
|
|
@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
|
|||
title: ADIS16240 Programmable Impact Sensor and Recorder driver
|
||||
|
||||
maintainers:
|
||||
- Alexandru Ardelean <alexandru.ardelean@analog.com>
|
||||
- Alexandru Tachici <alexandru.tachici@analog.com>
|
||||
|
||||
description: |
|
||||
ADIS16240 Programmable Impact Sensor and Recorder driver that supports
|
||||
|
|
|
@ -55,7 +55,7 @@ examples:
|
|||
/* Example for a I2C device node */
|
||||
accelerometer@2a {
|
||||
compatible = "adi,adxl345";
|
||||
reg = <0x53>;
|
||||
reg = <0x2a>;
|
||||
interrupt-parent = <&gpio0>;
|
||||
interrupts = <0 IRQ_TYPE_LEVEL_HIGH>;
|
||||
};
|
||||
|
|
|
@ -17,7 +17,9 @@ description: |
|
|||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- bosch,bmi085-accel
|
||||
- bosch,bmi088-accel
|
||||
- bosch,bmi090l-accel
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
|
|
@ -17,6 +17,7 @@ properties:
|
|||
compatible:
|
||||
enum:
|
||||
- murata,sca3300
|
||||
- murata,scl3300
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
|
|
@ -8,7 +8,6 @@ title: Analog Devices AD9467 and similar High-Speed ADCs
|
|||
|
||||
maintainers:
|
||||
- Michael Hennerich <michael.hennerich@analog.com>
|
||||
- Alexandru Ardelean <alexandru.ardelean@analog.com>
|
||||
|
||||
description: |
|
||||
The AD9467 and the parts similar with it, are high-speed analog-to-digital
|
||||
|
|
|
@ -8,7 +8,6 @@ title: Analog Devices AXI ADC IP core
|
|||
|
||||
maintainers:
|
||||
- Michael Hennerich <michael.hennerich@analog.com>
|
||||
- Alexandru Ardelean <alexandru.ardelean@analog.com>
|
||||
|
||||
description: |
|
||||
Analog Devices Generic AXI ADC IP core for interfacing an ADC device
|
||||
|
|
|
@ -0,0 +1,51 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/iio/adc/qcom,spmi-rradc.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Qualcomm's SPMI PMIC Round Robin ADC
|
||||
|
||||
maintainers:
|
||||
- Caleb Connolly <caleb.connolly@linaro.org>
|
||||
|
||||
description: |
|
||||
The Qualcomm SPMI Round Robin ADC (RRADC) provides interface to clients to
|
||||
read the voltage, current and temperature for supported peripherals such as
|
||||
the battery thermistor die temperature, charger temperature, USB and DC input
|
||||
voltage / current and battery ID resistor.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- qcom,pmi8998-rradc
|
||||
- qcom,pm660-rradc
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
qcom,batt-id-delay-ms:
|
||||
description: Sets the hardware settling time for the battery ID resistor.
|
||||
enum: [0, 1, 4, 12, 20, 40, 60, 80]
|
||||
|
||||
"#io-channel-cells":
|
||||
const: 1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
pmic {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
pmic_rradc: adc@4500 {
|
||||
compatible = "qcom,pmi8998-rradc";
|
||||
reg = <0x4500>;
|
||||
#io-channel-cells = <1>;
|
||||
};
|
||||
};
|
|
@ -19,6 +19,7 @@ properties:
|
|||
compatible:
|
||||
items:
|
||||
- enum:
|
||||
- renesas,r9a07g043-adc # RZ/G2UL
|
||||
- renesas,r9a07g044-adc # RZ/G2L
|
||||
- renesas,r9a07g054-adc # RZ/V2L
|
||||
- const: renesas,rzg2l-adc
|
||||
|
@ -76,16 +77,35 @@ patternProperties:
|
|||
properties:
|
||||
reg:
|
||||
description: |
|
||||
The channel number. It can have up to 8 channels numbered from 0 to 7.
|
||||
items:
|
||||
- minimum: 0
|
||||
maximum: 7
|
||||
The channel number.
|
||||
|
||||
required:
|
||||
- reg
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
allOf:
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
const: renesas,r9a07g043-adc
|
||||
then:
|
||||
patternProperties:
|
||||
"^channel@[2-7]$": false
|
||||
"^channel@[0-1]$":
|
||||
properties:
|
||||
reg:
|
||||
minimum: 0
|
||||
maximum: 1
|
||||
else:
|
||||
patternProperties:
|
||||
"^channel@[0-7]$":
|
||||
properties:
|
||||
reg:
|
||||
minimum: 0
|
||||
maximum: 7
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
|
|
|
@ -8,7 +8,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
|
|||
title: Analog Devices AD5770R DAC device driver
|
||||
|
||||
maintainers:
|
||||
- Mircea Caprioru <mircea.caprioru@analog.com>
|
||||
- Alexandru Tachici <alexandru.tachici@analog.com>
|
||||
|
||||
description: |
|
||||
Bindings for the Analog Devices AD5770R current DAC device. Datasheet can be
|
||||
|
|
|
@ -15,6 +15,7 @@ properties:
|
|||
enum:
|
||||
- microchip,mcp4902
|
||||
- microchip,mcp4912
|
||||
- microchip,mcp4921
|
||||
- microchip,mcp4922
|
||||
|
||||
reg:
|
||||
|
|
|
@ -21,6 +21,7 @@ properties:
|
|||
- ti,dac5573
|
||||
- ti,dac6573
|
||||
- ti,dac7573
|
||||
- ti,dac121c081
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
|
|
@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
|
|||
title: Analog Devices ADIS16480 and similar IMUs
|
||||
|
||||
maintainers:
|
||||
- Alexandru Ardelean <alexandru.ardelean@analog.com>
|
||||
- Alexandru Tachici <alexandru.tachici@analog.com>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
|
|
|
@ -126,6 +126,42 @@ properties:
|
|||
UINT_MAX (4294967295) represents infinite. Other values
|
||||
represent 1-1/N.
|
||||
|
||||
semtech,cs-idle-sleep:
|
||||
description:
|
||||
State of CS pins during sleep mode and idle time.
|
||||
enum:
|
||||
- hi-z
|
||||
- gnd
|
||||
- vdd
|
||||
|
||||
semtech,int-comp-resistor:
|
||||
description:
|
||||
Internal resistor setting for compensation.
|
||||
enum:
|
||||
- lowest
|
||||
- low
|
||||
- high
|
||||
- highest
|
||||
|
||||
semtech,input-precharge-resistor-ohms:
|
||||
default: 4000
|
||||
multipleOf: 2000
|
||||
minimum: 0
|
||||
maximum: 30000
|
||||
description:
|
||||
Pre-charge input resistance in Ohm.
|
||||
|
||||
semtech,input-analog-gain:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
minimum: 0
|
||||
maximum: 3
|
||||
description: |
|
||||
Defines the input antenna analog gain
|
||||
0: x1.247
|
||||
1: x1 (default)
|
||||
2: x0.768
|
||||
3: x0.552
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
@ -157,5 +193,8 @@ examples:
|
|||
semtech,ph01-proxraw-strength = <2>;
|
||||
semtech,ph23-proxraw-strength = <2>;
|
||||
semtech,avg-pos-strength = <64>;
|
||||
semtech,int-comp-resistor = "lowest";
|
||||
semtech,input-precharge-resistor-ohms = <2000>;
|
||||
semtech,cs-idle-sleep = "gnd";
|
||||
};
|
||||
};
|
||||
|
|
|
@ -61,6 +61,14 @@ properties:
|
|||
UINT_MAX (4294967295) represents infinite. Other values
|
||||
represent 1-1/N.
|
||||
|
||||
semtech,input-precharge-resistor-ohms:
|
||||
default: 0
|
||||
multipleOf: 2000
|
||||
minimum: 0
|
||||
maximum: 30000
|
||||
description:
|
||||
Pre-charge input resistance in Ohm.
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
@ -85,5 +93,6 @@ examples:
|
|||
semtech,resolution = <256>;
|
||||
semtech,proxraw-strength = <2>;
|
||||
semtech,avg-pos-strength = <64>;
|
||||
semtech,input-precharge-resistor-ohms = <4000>;
|
||||
};
|
||||
};
|
||||
|
|
|
@ -19,6 +19,11 @@ properties:
|
|||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
reset-gpios:
|
||||
maxItems: 1
|
||||
|
||||
vdd-supply: true
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
|
|
@ -9724,6 +9724,7 @@ F: Documentation/ABI/testing/sysfs-bus-iio*
|
|||
F: Documentation/devicetree/bindings/iio/
|
||||
F: drivers/iio/
|
||||
F: drivers/staging/iio/
|
||||
F: include/dt-bindings/iio/
|
||||
F: include/linux/iio/
|
||||
F: tools/iio/
|
||||
|
||||
|
|
|
@ -204,6 +204,8 @@ config BMA220
|
|||
config BMA400
|
||||
tristate "Bosch BMA400 3-Axis Accelerometer Driver"
|
||||
select REGMAP
|
||||
select IIO_BUFFER
|
||||
select IIO_TRIGGERED_BUFFER
|
||||
select BMA400_I2C if I2C
|
||||
select BMA400_SPI if SPI
|
||||
help
|
||||
|
|
|
@ -46,7 +46,7 @@ EXPORT_SYMBOL_NS_GPL(adxl313_writable_regs_table, IIO_ADXL313);
|
|||
struct adxl313_data {
|
||||
struct regmap *regmap;
|
||||
struct mutex lock; /* lock to protect transf_buf */
|
||||
__le16 transf_buf ____cacheline_aligned;
|
||||
__le16 transf_buf __aligned(IIO_DMA_MINALIGN);
|
||||
};
|
||||
|
||||
static const int adxl313_odr_freqs[][2] = {
|
||||
|
|
|
@ -177,7 +177,7 @@ struct adxl355_data {
|
|||
u8 buf[14];
|
||||
s64 ts;
|
||||
} buffer;
|
||||
} ____cacheline_aligned;
|
||||
} __aligned(IIO_DMA_MINALIGN);
|
||||
};
|
||||
|
||||
static int adxl355_set_op_mode(struct adxl355_data *data,
|
||||
|
|
|
@ -179,7 +179,7 @@ struct adxl367_state {
|
|||
unsigned int fifo_set_size;
|
||||
unsigned int fifo_watermark;
|
||||
|
||||
__be16 fifo_buf[ADXL367_FIFO_SIZE] ____cacheline_aligned;
|
||||
__be16 fifo_buf[ADXL367_FIFO_SIZE] __aligned(IIO_DMA_MINALIGN);
|
||||
__be16 sample_buf;
|
||||
u8 act_threshold_buf[2];
|
||||
u8 inact_time_buf[2];
|
||||
|
@ -447,21 +447,17 @@ static int adxl367_set_fifo_format(struct adxl367_state *st,
|
|||
fifo_format));
|
||||
}
|
||||
|
||||
static int adxl367_set_fifo_samples(struct adxl367_state *st,
|
||||
unsigned int fifo_watermark,
|
||||
unsigned int fifo_set_size)
|
||||
static int adxl367_set_fifo_watermark(struct adxl367_state *st,
|
||||
unsigned int fifo_watermark)
|
||||
{
|
||||
unsigned int fifo_samples = fifo_watermark * fifo_set_size;
|
||||
unsigned int fifo_samples = fifo_watermark * st->fifo_set_size;
|
||||
unsigned int fifo_samples_h, fifo_samples_l;
|
||||
int ret;
|
||||
|
||||
if (fifo_samples > ADXL367_FIFO_MAX_WATERMARK)
|
||||
fifo_samples = ADXL367_FIFO_MAX_WATERMARK;
|
||||
|
||||
if (fifo_set_size == 0)
|
||||
return 0;
|
||||
|
||||
fifo_samples /= fifo_set_size;
|
||||
fifo_samples /= st->fifo_set_size;
|
||||
|
||||
fifo_samples_h = FIELD_PREP(ADXL367_SAMPLES_H_MASK,
|
||||
FIELD_GET(ADXL367_SAMPLES_VAL_H_MASK,
|
||||
|
@ -475,30 +471,8 @@ static int adxl367_set_fifo_samples(struct adxl367_state *st,
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
return regmap_update_bits(st->regmap, ADXL367_REG_FIFO_SAMPLES,
|
||||
ADXL367_SAMPLES_L_MASK, fifo_samples_l);
|
||||
}
|
||||
|
||||
static int adxl367_set_fifo_set_size(struct adxl367_state *st,
|
||||
unsigned int fifo_set_size)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = adxl367_set_fifo_samples(st, st->fifo_watermark, fifo_set_size);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
st->fifo_set_size = fifo_set_size;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int adxl367_set_fifo_watermark(struct adxl367_state *st,
|
||||
unsigned int fifo_watermark)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = adxl367_set_fifo_samples(st, fifo_watermark, st->fifo_set_size);
|
||||
ret = regmap_update_bits(st->regmap, ADXL367_REG_FIFO_SAMPLES,
|
||||
ADXL367_SAMPLES_L_MASK, fifo_samples_l);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
@ -1276,14 +1250,11 @@ static int adxl367_update_scan_mode(struct iio_dev *indio_dev,
|
|||
{
|
||||
struct adxl367_state *st = iio_priv(indio_dev);
|
||||
enum adxl367_fifo_format fifo_format;
|
||||
unsigned int fifo_set_size;
|
||||
int ret;
|
||||
|
||||
if (!adxl367_find_mask_fifo_format(active_scan_mask, &fifo_format))
|
||||
return -EINVAL;
|
||||
|
||||
fifo_set_size = bitmap_weight(active_scan_mask, indio_dev->masklength);
|
||||
|
||||
mutex_lock(&st->lock);
|
||||
|
||||
ret = adxl367_set_measure_en(st, false);
|
||||
|
@ -1294,11 +1265,12 @@ static int adxl367_update_scan_mode(struct iio_dev *indio_dev,
|
|||
if (ret)
|
||||
goto out;
|
||||
|
||||
ret = adxl367_set_fifo_set_size(st, fifo_set_size);
|
||||
ret = adxl367_set_measure_en(st, true);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
ret = adxl367_set_measure_en(st, true);
|
||||
st->fifo_set_size = bitmap_weight(active_scan_mask,
|
||||
indio_dev->masklength);
|
||||
|
||||
out:
|
||||
mutex_unlock(&st->lock);
|
||||
|
|
|
@ -9,6 +9,8 @@
|
|||
#include <linux/regmap.h>
|
||||
#include <linux/spi/spi.h>
|
||||
|
||||
#include <linux/iio/iio.h>
|
||||
|
||||
#include "adxl367.h"
|
||||
|
||||
#define ADXL367_SPI_WRITE_COMMAND 0x0A
|
||||
|
@ -28,10 +30,10 @@ struct adxl367_spi_state {
|
|||
struct spi_transfer fifo_xfer[2];
|
||||
|
||||
/*
|
||||
* DMA (thus cache coherency maintenance) requires the
|
||||
* transfer buffers to live in their own cache lines.
|
||||
* DMA (thus cache coherency maintenance) may require the
|
||||
* transfer buffers live in their own cache lines.
|
||||
*/
|
||||
u8 reg_write_tx_buf[1] ____cacheline_aligned;
|
||||
u8 reg_write_tx_buf[1] __aligned(IIO_DMA_MINALIGN);
|
||||
u8 reg_read_tx_buf[2];
|
||||
u8 fifo_tx_buf[1];
|
||||
};
|
||||
|
|
|
@ -67,7 +67,7 @@ struct bma220_data {
|
|||
/* Ensure timestamp is naturally aligned. */
|
||||
s64 timestamp __aligned(8);
|
||||
} scan;
|
||||
u8 tx_buf[2] ____cacheline_aligned;
|
||||
u8 tx_buf[2] __aligned(IIO_DMA_MINALIGN);
|
||||
};
|
||||
|
||||
static const struct iio_chan_spec bma220_channels[] = {
|
||||
|
|
|
@ -39,6 +39,7 @@
|
|||
#define BMA400_INT_STAT0_REG 0x0e
|
||||
#define BMA400_INT_STAT1_REG 0x0f
|
||||
#define BMA400_INT_STAT2_REG 0x10
|
||||
#define BMA400_INT12_MAP_REG 0x23
|
||||
|
||||
/* Temperature register */
|
||||
#define BMA400_TEMP_DATA_REG 0x11
|
||||
|
@ -53,6 +54,9 @@
|
|||
#define BMA400_STEP_CNT1_REG 0x16
|
||||
#define BMA400_STEP_CNT3_REG 0x17
|
||||
#define BMA400_STEP_STAT_REG 0x18
|
||||
#define BMA400_STEP_INT_MSK BIT(0)
|
||||
#define BMA400_STEP_RAW_LEN 0x03
|
||||
#define BMA400_STEP_STAT_MASK GENMASK(9, 8)
|
||||
|
||||
/*
|
||||
* Read-write configuration registers
|
||||
|
@ -62,6 +66,13 @@
|
|||
#define BMA400_ACC_CONFIG2_REG 0x1b
|
||||
#define BMA400_CMD_REG 0x7e
|
||||
|
||||
/* Interrupt registers */
|
||||
#define BMA400_INT_CONFIG0_REG 0x1f
|
||||
#define BMA400_INT_CONFIG1_REG 0x20
|
||||
#define BMA400_INT1_MAP_REG 0x21
|
||||
#define BMA400_INT_IO_CTRL_REG 0x24
|
||||
#define BMA400_INT_DRDY_MSK BIT(7)
|
||||
|
||||
/* Chip ID of BMA 400 devices found in the chip ID register. */
|
||||
#define BMA400_ID_REG_VAL 0x90
|
||||
|
||||
|
@ -83,8 +94,38 @@
|
|||
#define BMA400_ACC_ODR_MIN_WHOLE_HZ 25
|
||||
#define BMA400_ACC_ODR_MIN_HZ 12
|
||||
|
||||
#define BMA400_SCALE_MIN 38357
|
||||
#define BMA400_SCALE_MAX 306864
|
||||
/* Generic interrupts register */
|
||||
#define BMA400_GEN1INT_CONFIG0 0x3f
|
||||
#define BMA400_GEN2INT_CONFIG0 0x4A
|
||||
#define BMA400_GEN_CONFIG1_OFF 0x01
|
||||
#define BMA400_GEN_CONFIG2_OFF 0x02
|
||||
#define BMA400_GEN_CONFIG3_OFF 0x03
|
||||
#define BMA400_GEN_CONFIG31_OFF 0x04
|
||||
#define BMA400_INT_GEN1_MSK BIT(2)
|
||||
#define BMA400_INT_GEN2_MSK BIT(3)
|
||||
#define BMA400_GEN_HYST_MSK GENMASK(1, 0)
|
||||
|
||||
/*
|
||||
* BMA400_SCALE_MIN macro value represents m/s^2 for 1 LSB before
|
||||
* converting to micro values for +-2g range.
|
||||
*
|
||||
* For +-2g - 1 LSB = 0.976562 milli g = 0.009576 m/s^2
|
||||
* For +-4g - 1 LSB = 1.953125 milli g = 0.019153 m/s^2
|
||||
* For +-16g - 1 LSB = 7.8125 milli g = 0.076614 m/s^2
|
||||
*
|
||||
* The raw value which is used to select the different ranges is determined
|
||||
* by the first bit set position from the scale value, so BMA400_SCALE_MIN
|
||||
* should be odd.
|
||||
*
|
||||
* Scale values for +-2g, +-4g, +-8g and +-16g are populated into bma400_scales
|
||||
* array by left shifting BMA400_SCALE_MIN.
|
||||
* e.g.:
|
||||
* To select +-2g = 9577 << 0 = raw value to write is 0.
|
||||
* To select +-8g = 9577 << 2 = raw value to write is 2.
|
||||
* To select +-16g = 9577 << 3 = raw value to write is 3.
|
||||
*/
|
||||
#define BMA400_SCALE_MIN 9577
|
||||
#define BMA400_SCALE_MAX 76617
|
||||
|
||||
#define BMA400_NUM_REGULATORS 2
|
||||
#define BMA400_VDD_REGULATOR 0
|
||||
|
@ -92,8 +133,7 @@
|
|||
|
||||
extern const struct regmap_config bma400_regmap_config;
|
||||
|
||||
int bma400_probe(struct device *dev, struct regmap *regmap, const char *name);
|
||||
|
||||
void bma400_remove(struct device *dev);
|
||||
int bma400_probe(struct device *dev, struct regmap *regmap, int irq,
|
||||
const char *name);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -11,15 +11,24 @@
|
|||
* - Create channel for sensor time
|
||||
*/
|
||||
|
||||
#include <linux/bitfield.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/iio/iio.h>
|
||||
#include <linux/iio/sysfs.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include <asm/unaligned.h>
|
||||
|
||||
#include <linux/iio/iio.h>
|
||||
#include <linux/iio/buffer.h>
|
||||
#include <linux/iio/events.h>
|
||||
#include <linux/iio/trigger.h>
|
||||
#include <linux/iio/trigger_consumer.h>
|
||||
#include <linux/iio/triggered_buffer.h>
|
||||
|
||||
#include "bma400.h"
|
||||
|
||||
|
@ -46,11 +55,24 @@ enum bma400_power_mode {
|
|||
POWER_MODE_INVALID = 0x03,
|
||||
};
|
||||
|
||||
enum bma400_scan {
|
||||
BMA400_ACCL_X,
|
||||
BMA400_ACCL_Y,
|
||||
BMA400_ACCL_Z,
|
||||
BMA400_TEMP,
|
||||
};
|
||||
|
||||
struct bma400_sample_freq {
|
||||
int hz;
|
||||
int uhz;
|
||||
};
|
||||
|
||||
enum bma400_activity {
|
||||
BMA400_STILL,
|
||||
BMA400_WALKING,
|
||||
BMA400_RUNNING,
|
||||
};
|
||||
|
||||
struct bma400_data {
|
||||
struct device *dev;
|
||||
struct regmap *regmap;
|
||||
|
@ -61,6 +83,19 @@ struct bma400_data {
|
|||
struct bma400_sample_freq sample_freq;
|
||||
int oversampling_ratio;
|
||||
int scale;
|
||||
struct iio_trigger *trig;
|
||||
int steps_enabled;
|
||||
bool step_event_en;
|
||||
bool activity_event_en;
|
||||
unsigned int generic_event_en;
|
||||
/* Correct time stamp alignment */
|
||||
struct {
|
||||
__le16 buff[3];
|
||||
u8 temperature;
|
||||
s64 ts __aligned(8);
|
||||
} buffer __aligned(IIO_DMA_MINALIGN);
|
||||
__le16 status;
|
||||
__be16 duration;
|
||||
};
|
||||
|
||||
static bool bma400_is_writable_reg(struct device *dev, unsigned int reg)
|
||||
|
@ -152,7 +187,38 @@ static const struct iio_chan_spec_ext_info bma400_ext_info[] = {
|
|||
{ }
|
||||
};
|
||||
|
||||
#define BMA400_ACC_CHANNEL(_axis) { \
|
||||
static const struct iio_event_spec bma400_step_detect_event = {
|
||||
.type = IIO_EV_TYPE_CHANGE,
|
||||
.dir = IIO_EV_DIR_NONE,
|
||||
.mask_separate = BIT(IIO_EV_INFO_ENABLE),
|
||||
};
|
||||
|
||||
static const struct iio_event_spec bma400_activity_event = {
|
||||
.type = IIO_EV_TYPE_CHANGE,
|
||||
.dir = IIO_EV_DIR_NONE,
|
||||
.mask_shared_by_type = BIT(IIO_EV_INFO_ENABLE),
|
||||
};
|
||||
|
||||
static const struct iio_event_spec bma400_accel_event[] = {
|
||||
{
|
||||
.type = IIO_EV_TYPE_MAG,
|
||||
.dir = IIO_EV_DIR_FALLING,
|
||||
.mask_shared_by_type = BIT(IIO_EV_INFO_VALUE) |
|
||||
BIT(IIO_EV_INFO_PERIOD) |
|
||||
BIT(IIO_EV_INFO_HYSTERESIS) |
|
||||
BIT(IIO_EV_INFO_ENABLE),
|
||||
},
|
||||
{
|
||||
.type = IIO_EV_TYPE_MAG,
|
||||
.dir = IIO_EV_DIR_RISING,
|
||||
.mask_shared_by_type = BIT(IIO_EV_INFO_VALUE) |
|
||||
BIT(IIO_EV_INFO_PERIOD) |
|
||||
BIT(IIO_EV_INFO_HYSTERESIS) |
|
||||
BIT(IIO_EV_INFO_ENABLE),
|
||||
},
|
||||
};
|
||||
|
||||
#define BMA400_ACC_CHANNEL(_index, _axis) { \
|
||||
.type = IIO_ACCEL, \
|
||||
.modified = 1, \
|
||||
.channel2 = IIO_MOD_##_axis, \
|
||||
|
@ -164,17 +230,55 @@ static const struct iio_chan_spec_ext_info bma400_ext_info[] = {
|
|||
BIT(IIO_CHAN_INFO_SCALE) | \
|
||||
BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), \
|
||||
.ext_info = bma400_ext_info, \
|
||||
.scan_index = _index, \
|
||||
.scan_type = { \
|
||||
.sign = 's', \
|
||||
.realbits = 12, \
|
||||
.storagebits = 16, \
|
||||
.endianness = IIO_LE, \
|
||||
}, \
|
||||
.event_spec = bma400_accel_event, \
|
||||
.num_event_specs = ARRAY_SIZE(bma400_accel_event) \
|
||||
}
|
||||
|
||||
#define BMA400_ACTIVITY_CHANNEL(_chan2) { \
|
||||
.type = IIO_ACTIVITY, \
|
||||
.modified = 1, \
|
||||
.channel2 = _chan2, \
|
||||
.info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), \
|
||||
.scan_index = -1, /* No buffer support */ \
|
||||
.event_spec = &bma400_activity_event, \
|
||||
.num_event_specs = 1, \
|
||||
}
|
||||
|
||||
static const struct iio_chan_spec bma400_channels[] = {
|
||||
BMA400_ACC_CHANNEL(X),
|
||||
BMA400_ACC_CHANNEL(Y),
|
||||
BMA400_ACC_CHANNEL(Z),
|
||||
BMA400_ACC_CHANNEL(0, X),
|
||||
BMA400_ACC_CHANNEL(1, Y),
|
||||
BMA400_ACC_CHANNEL(2, Z),
|
||||
{
|
||||
.type = IIO_TEMP,
|
||||
.info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED),
|
||||
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SAMP_FREQ),
|
||||
.scan_index = 3,
|
||||
.scan_type = {
|
||||
.sign = 's',
|
||||
.realbits = 8,
|
||||
.storagebits = 8,
|
||||
.endianness = IIO_LE,
|
||||
},
|
||||
},
|
||||
{
|
||||
.type = IIO_STEPS,
|
||||
.info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED) |
|
||||
BIT(IIO_CHAN_INFO_ENABLE),
|
||||
.scan_index = -1, /* No buffer support */
|
||||
.event_spec = &bma400_step_detect_event,
|
||||
.num_event_specs = 1,
|
||||
},
|
||||
BMA400_ACTIVITY_CHANNEL(IIO_MOD_STILL),
|
||||
BMA400_ACTIVITY_CHANNEL(IIO_MOD_WALKING),
|
||||
BMA400_ACTIVITY_CHANNEL(IIO_MOD_RUNNING),
|
||||
IIO_CHAN_SOFT_TIMESTAMP(4),
|
||||
};
|
||||
|
||||
static int bma400_get_temp_reg(struct bma400_data *data, int *val, int *val2)
|
||||
|
@ -542,6 +646,40 @@ static int bma400_set_power_mode(struct bma400_data *data,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int bma400_enable_steps(struct bma400_data *data, int val)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (data->steps_enabled == val)
|
||||
return 0;
|
||||
|
||||
ret = regmap_update_bits(data->regmap, BMA400_INT_CONFIG1_REG,
|
||||
BMA400_STEP_INT_MSK,
|
||||
FIELD_PREP(BMA400_STEP_INT_MSK, val ? 1 : 0));
|
||||
if (ret)
|
||||
return ret;
|
||||
data->steps_enabled = val;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int bma400_get_steps_reg(struct bma400_data *data, int *val)
|
||||
{
|
||||
u8 *steps_raw;
|
||||
int ret;
|
||||
|
||||
steps_raw = kmalloc(BMA400_STEP_RAW_LEN, GFP_KERNEL);
|
||||
if (!steps_raw)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = regmap_bulk_read(data->regmap, BMA400_STEP_CNT0_REG,
|
||||
steps_raw, BMA400_STEP_RAW_LEN);
|
||||
if (ret)
|
||||
return ret;
|
||||
*val = get_unaligned_le24(steps_raw);
|
||||
kfree(steps_raw);
|
||||
return IIO_VAL_INT;
|
||||
}
|
||||
|
||||
static void bma400_init_tables(void)
|
||||
{
|
||||
int raw;
|
||||
|
@ -560,6 +698,40 @@ static void bma400_init_tables(void)
|
|||
}
|
||||
}
|
||||
|
||||
static void bma400_regulators_disable(void *data_ptr)
|
||||
{
|
||||
struct bma400_data *data = data_ptr;
|
||||
|
||||
regulator_bulk_disable(ARRAY_SIZE(data->regulators), data->regulators);
|
||||
}
|
||||
|
||||
static void bma400_power_disable(void *data_ptr)
|
||||
{
|
||||
struct bma400_data *data = data_ptr;
|
||||
int ret;
|
||||
|
||||
mutex_lock(&data->mutex);
|
||||
ret = bma400_set_power_mode(data, POWER_MODE_SLEEP);
|
||||
mutex_unlock(&data->mutex);
|
||||
if (ret)
|
||||
dev_warn(data->dev, "Failed to put device into sleep mode (%pe)\n",
|
||||
ERR_PTR(ret));
|
||||
}
|
||||
|
||||
static enum iio_modifier bma400_act_to_mod(enum bma400_activity activity)
|
||||
{
|
||||
switch (activity) {
|
||||
case BMA400_STILL:
|
||||
return IIO_MOD_STILL;
|
||||
case BMA400_WALKING:
|
||||
return IIO_MOD_WALKING;
|
||||
case BMA400_RUNNING:
|
||||
return IIO_MOD_RUNNING;
|
||||
default:
|
||||
return IIO_NO_MOD;
|
||||
}
|
||||
}
|
||||
|
||||
static int bma400_init(struct bma400_data *data)
|
||||
{
|
||||
unsigned int val;
|
||||
|
@ -569,13 +741,12 @@ static int bma400_init(struct bma400_data *data)
|
|||
ret = regmap_read(data->regmap, BMA400_CHIP_ID_REG, &val);
|
||||
if (ret) {
|
||||
dev_err(data->dev, "Failed to read chip id register\n");
|
||||
goto out;
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (val != BMA400_ID_REG_VAL) {
|
||||
dev_err(data->dev, "Chip ID mismatch\n");
|
||||
ret = -ENODEV;
|
||||
goto out;
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
data->regulators[BMA400_VDD_REGULATOR].supply = "vdd";
|
||||
|
@ -589,27 +760,31 @@ static int bma400_init(struct bma400_data *data)
|
|||
"Failed to get regulators: %d\n",
|
||||
ret);
|
||||
|
||||
goto out;
|
||||
return ret;
|
||||
}
|
||||
ret = regulator_bulk_enable(ARRAY_SIZE(data->regulators),
|
||||
data->regulators);
|
||||
if (ret) {
|
||||
dev_err(data->dev, "Failed to enable regulators: %d\n",
|
||||
ret);
|
||||
goto out;
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = devm_add_action_or_reset(data->dev, bma400_regulators_disable, data);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = bma400_get_power_mode(data);
|
||||
if (ret) {
|
||||
dev_err(data->dev, "Failed to get the initial power-mode\n");
|
||||
goto err_reg_disable;
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (data->power_mode != POWER_MODE_NORMAL) {
|
||||
ret = bma400_set_power_mode(data, POWER_MODE_NORMAL);
|
||||
if (ret) {
|
||||
dev_err(data->dev, "Failed to wake up the device\n");
|
||||
goto err_reg_disable;
|
||||
return ret;
|
||||
}
|
||||
/*
|
||||
* TODO: The datasheet waits 1500us here in the example, but
|
||||
|
@ -618,20 +793,28 @@ static int bma400_init(struct bma400_data *data)
|
|||
usleep_range(1500, 2000);
|
||||
}
|
||||
|
||||
ret = devm_add_action_or_reset(data->dev, bma400_power_disable, data);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
bma400_init_tables();
|
||||
|
||||
ret = bma400_get_accel_output_data_rate(data);
|
||||
if (ret)
|
||||
goto err_reg_disable;
|
||||
return ret;
|
||||
|
||||
ret = bma400_get_accel_oversampling_ratio(data);
|
||||
if (ret)
|
||||
goto err_reg_disable;
|
||||
return ret;
|
||||
|
||||
ret = bma400_get_accel_scale(data);
|
||||
if (ret)
|
||||
goto err_reg_disable;
|
||||
return ret;
|
||||
|
||||
/* Configure INT1 pin to open drain */
|
||||
ret = regmap_write(data->regmap, BMA400_INT_IO_CTRL_REG, 0x06);
|
||||
if (ret)
|
||||
return ret;
|
||||
/*
|
||||
* Once the interrupt engine is supported we might use the
|
||||
* data_src_reg, but for now ensure this is set to the
|
||||
|
@ -639,12 +822,6 @@ static int bma400_init(struct bma400_data *data)
|
|||
* channel.
|
||||
*/
|
||||
return regmap_write(data->regmap, BMA400_ACC_CONFIG2_REG, 0x00);
|
||||
|
||||
err_reg_disable:
|
||||
regulator_bulk_disable(ARRAY_SIZE(data->regulators),
|
||||
data->regulators);
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int bma400_read_raw(struct iio_dev *indio_dev,
|
||||
|
@ -652,14 +829,37 @@ static int bma400_read_raw(struct iio_dev *indio_dev,
|
|||
int *val2, long mask)
|
||||
{
|
||||
struct bma400_data *data = iio_priv(indio_dev);
|
||||
unsigned int activity;
|
||||
int ret;
|
||||
|
||||
switch (mask) {
|
||||
case IIO_CHAN_INFO_PROCESSED:
|
||||
mutex_lock(&data->mutex);
|
||||
ret = bma400_get_temp_reg(data, val, val2);
|
||||
mutex_unlock(&data->mutex);
|
||||
return ret;
|
||||
switch (chan->type) {
|
||||
case IIO_TEMP:
|
||||
mutex_lock(&data->mutex);
|
||||
ret = bma400_get_temp_reg(data, val, val2);
|
||||
mutex_unlock(&data->mutex);
|
||||
return ret;
|
||||
case IIO_STEPS:
|
||||
return bma400_get_steps_reg(data, val);
|
||||
case IIO_ACTIVITY:
|
||||
ret = regmap_read(data->regmap, BMA400_STEP_STAT_REG,
|
||||
&activity);
|
||||
if (ret)
|
||||
return ret;
|
||||
/*
|
||||
* The device does not support confidence value levels,
|
||||
* so we will always have 100% for current activity and
|
||||
* 0% for the others.
|
||||
*/
|
||||
if (chan->channel2 == bma400_act_to_mod(activity))
|
||||
*val = 100;
|
||||
else
|
||||
*val = 0;
|
||||
return IIO_VAL_INT;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
case IIO_CHAN_INFO_RAW:
|
||||
mutex_lock(&data->mutex);
|
||||
ret = bma400_get_accel_reg(data, chan, val);
|
||||
|
@ -700,6 +900,9 @@ static int bma400_read_raw(struct iio_dev *indio_dev,
|
|||
|
||||
*val = data->oversampling_ratio;
|
||||
return IIO_VAL_INT;
|
||||
case IIO_CHAN_INFO_ENABLE:
|
||||
*val = data->steps_enabled;
|
||||
return IIO_VAL_INT;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
@ -765,6 +968,11 @@ static int bma400_write_raw(struct iio_dev *indio_dev,
|
|||
ret = bma400_set_accel_oversampling_ratio(data, val);
|
||||
mutex_unlock(&data->mutex);
|
||||
return ret;
|
||||
case IIO_CHAN_INFO_ENABLE:
|
||||
mutex_lock(&data->mutex);
|
||||
ret = bma400_enable_steps(data, val);
|
||||
mutex_unlock(&data->mutex);
|
||||
return ret;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
@ -781,19 +989,419 @@ static int bma400_write_raw_get_fmt(struct iio_dev *indio_dev,
|
|||
return IIO_VAL_INT_PLUS_MICRO;
|
||||
case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
|
||||
return IIO_VAL_INT;
|
||||
case IIO_CHAN_INFO_ENABLE:
|
||||
return IIO_VAL_INT;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
static int bma400_read_event_config(struct iio_dev *indio_dev,
|
||||
const struct iio_chan_spec *chan,
|
||||
enum iio_event_type type,
|
||||
enum iio_event_direction dir)
|
||||
{
|
||||
struct bma400_data *data = iio_priv(indio_dev);
|
||||
|
||||
switch (chan->type) {
|
||||
case IIO_ACCEL:
|
||||
switch (dir) {
|
||||
case IIO_EV_DIR_RISING:
|
||||
return FIELD_GET(BMA400_INT_GEN1_MSK,
|
||||
data->generic_event_en);
|
||||
case IIO_EV_DIR_FALLING:
|
||||
return FIELD_GET(BMA400_INT_GEN2_MSK,
|
||||
data->generic_event_en);
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
case IIO_STEPS:
|
||||
return data->step_event_en;
|
||||
case IIO_ACTIVITY:
|
||||
return data->activity_event_en;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
static int bma400_steps_event_enable(struct bma400_data *data, int state)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = bma400_enable_steps(data, 1);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = regmap_update_bits(data->regmap, BMA400_INT12_MAP_REG,
|
||||
BMA400_STEP_INT_MSK,
|
||||
FIELD_PREP(BMA400_STEP_INT_MSK,
|
||||
state));
|
||||
if (ret)
|
||||
return ret;
|
||||
data->step_event_en = state;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bma400_activity_event_en(struct bma400_data *data,
|
||||
enum iio_event_direction dir,
|
||||
int state)
|
||||
{
|
||||
int ret, reg, msk, value, field_value;
|
||||
|
||||
switch (dir) {
|
||||
case IIO_EV_DIR_RISING:
|
||||
reg = BMA400_GEN1INT_CONFIG0;
|
||||
msk = BMA400_INT_GEN1_MSK;
|
||||
value = 2;
|
||||
set_mask_bits(&field_value, BMA400_INT_GEN1_MSK,
|
||||
FIELD_PREP(BMA400_INT_GEN1_MSK, state));
|
||||
break;
|
||||
case IIO_EV_DIR_FALLING:
|
||||
reg = BMA400_GEN2INT_CONFIG0;
|
||||
msk = BMA400_INT_GEN2_MSK;
|
||||
value = 0;
|
||||
set_mask_bits(&field_value, BMA400_INT_GEN2_MSK,
|
||||
FIELD_PREP(BMA400_INT_GEN2_MSK, state));
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Enabling all axis for interrupt evaluation */
|
||||
ret = regmap_write(data->regmap, reg, 0xF8);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* OR combination of all axis for interrupt evaluation */
|
||||
ret = regmap_write(data->regmap, reg + BMA400_GEN_CONFIG1_OFF, value);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Initial value to avoid interrupts while enabling*/
|
||||
ret = regmap_write(data->regmap, reg + BMA400_GEN_CONFIG2_OFF, 0x0A);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Initial duration value to avoid interrupts while enabling*/
|
||||
ret = regmap_write(data->regmap, reg + BMA400_GEN_CONFIG31_OFF, 0x0F);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = regmap_update_bits(data->regmap, BMA400_INT1_MAP_REG, msk,
|
||||
field_value);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = regmap_update_bits(data->regmap, BMA400_INT_CONFIG0_REG, msk,
|
||||
field_value);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
set_mask_bits(&data->generic_event_en, msk, field_value);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bma400_write_event_config(struct iio_dev *indio_dev,
|
||||
const struct iio_chan_spec *chan,
|
||||
enum iio_event_type type,
|
||||
enum iio_event_direction dir, int state)
|
||||
{
|
||||
struct bma400_data *data = iio_priv(indio_dev);
|
||||
int ret;
|
||||
|
||||
switch (chan->type) {
|
||||
case IIO_ACCEL:
|
||||
mutex_lock(&data->mutex);
|
||||
ret = bma400_activity_event_en(data, dir, state);
|
||||
mutex_unlock(&data->mutex);
|
||||
return ret;
|
||||
case IIO_STEPS:
|
||||
mutex_lock(&data->mutex);
|
||||
ret = bma400_steps_event_enable(data, state);
|
||||
mutex_unlock(&data->mutex);
|
||||
return ret;
|
||||
case IIO_ACTIVITY:
|
||||
mutex_lock(&data->mutex);
|
||||
if (!data->step_event_en) {
|
||||
ret = bma400_steps_event_enable(data, true);
|
||||
if (ret) {
|
||||
mutex_unlock(&data->mutex);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
data->activity_event_en = state;
|
||||
mutex_unlock(&data->mutex);
|
||||
return 0;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
static int get_gen_config_reg(enum iio_event_direction dir)
|
||||
{
|
||||
switch (dir) {
|
||||
case IIO_EV_DIR_FALLING:
|
||||
return BMA400_GEN2INT_CONFIG0;
|
||||
case IIO_EV_DIR_RISING:
|
||||
return BMA400_GEN1INT_CONFIG0;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
static int bma400_read_event_value(struct iio_dev *indio_dev,
|
||||
const struct iio_chan_spec *chan,
|
||||
enum iio_event_type type,
|
||||
enum iio_event_direction dir,
|
||||
enum iio_event_info info,
|
||||
int *val, int *val2)
|
||||
{
|
||||
struct bma400_data *data = iio_priv(indio_dev);
|
||||
int ret, reg;
|
||||
|
||||
switch (chan->type) {
|
||||
case IIO_ACCEL:
|
||||
reg = get_gen_config_reg(dir);
|
||||
if (reg < 0)
|
||||
return -EINVAL;
|
||||
|
||||
*val2 = 0;
|
||||
switch (info) {
|
||||
case IIO_EV_INFO_VALUE:
|
||||
ret = regmap_read(data->regmap,
|
||||
reg + BMA400_GEN_CONFIG2_OFF,
|
||||
val);
|
||||
if (ret)
|
||||
return ret;
|
||||
return IIO_VAL_INT;
|
||||
case IIO_EV_INFO_PERIOD:
|
||||
mutex_lock(&data->mutex);
|
||||
ret = regmap_bulk_read(data->regmap,
|
||||
reg + BMA400_GEN_CONFIG3_OFF,
|
||||
&data->duration,
|
||||
sizeof(data->duration));
|
||||
if (ret) {
|
||||
mutex_unlock(&data->mutex);
|
||||
return ret;
|
||||
}
|
||||
*val = be16_to_cpu(data->duration);
|
||||
mutex_unlock(&data->mutex);
|
||||
return IIO_VAL_INT;
|
||||
case IIO_EV_INFO_HYSTERESIS:
|
||||
ret = regmap_read(data->regmap, reg, val);
|
||||
if (ret)
|
||||
return ret;
|
||||
*val = FIELD_GET(BMA400_GEN_HYST_MSK, *val);
|
||||
return IIO_VAL_INT;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
static int bma400_write_event_value(struct iio_dev *indio_dev,
|
||||
const struct iio_chan_spec *chan,
|
||||
enum iio_event_type type,
|
||||
enum iio_event_direction dir,
|
||||
enum iio_event_info info,
|
||||
int val, int val2)
|
||||
{
|
||||
struct bma400_data *data = iio_priv(indio_dev);
|
||||
int reg, ret;
|
||||
|
||||
switch (chan->type) {
|
||||
case IIO_ACCEL:
|
||||
reg = get_gen_config_reg(dir);
|
||||
if (reg < 0)
|
||||
return -EINVAL;
|
||||
|
||||
switch (info) {
|
||||
case IIO_EV_INFO_VALUE:
|
||||
if (val < 1 || val > 255)
|
||||
return -EINVAL;
|
||||
|
||||
return regmap_write(data->regmap,
|
||||
reg + BMA400_GEN_CONFIG2_OFF,
|
||||
val);
|
||||
case IIO_EV_INFO_PERIOD:
|
||||
if (val < 1 || val > 65535)
|
||||
return -EINVAL;
|
||||
|
||||
mutex_lock(&data->mutex);
|
||||
put_unaligned_be16(val, &data->duration);
|
||||
ret = regmap_bulk_write(data->regmap,
|
||||
reg + BMA400_GEN_CONFIG3_OFF,
|
||||
&data->duration,
|
||||
sizeof(data->duration));
|
||||
mutex_unlock(&data->mutex);
|
||||
return ret;
|
||||
case IIO_EV_INFO_HYSTERESIS:
|
||||
if (val < 0 || val > 3)
|
||||
return -EINVAL;
|
||||
|
||||
return regmap_update_bits(data->regmap, reg,
|
||||
BMA400_GEN_HYST_MSK,
|
||||
FIELD_PREP(BMA400_GEN_HYST_MSK,
|
||||
val));
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
static int bma400_data_rdy_trigger_set_state(struct iio_trigger *trig,
|
||||
bool state)
|
||||
{
|
||||
struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig);
|
||||
struct bma400_data *data = iio_priv(indio_dev);
|
||||
int ret;
|
||||
|
||||
ret = regmap_update_bits(data->regmap, BMA400_INT_CONFIG0_REG,
|
||||
BMA400_INT_DRDY_MSK,
|
||||
FIELD_PREP(BMA400_INT_DRDY_MSK, state));
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return regmap_update_bits(data->regmap, BMA400_INT1_MAP_REG,
|
||||
BMA400_INT_DRDY_MSK,
|
||||
FIELD_PREP(BMA400_INT_DRDY_MSK, state));
|
||||
}
|
||||
|
||||
static const unsigned long bma400_avail_scan_masks[] = {
|
||||
BIT(BMA400_ACCL_X) | BIT(BMA400_ACCL_Y) | BIT(BMA400_ACCL_Z),
|
||||
BIT(BMA400_ACCL_X) | BIT(BMA400_ACCL_Y) | BIT(BMA400_ACCL_Z)
|
||||
| BIT(BMA400_TEMP),
|
||||
0
|
||||
};
|
||||
|
||||
static const struct iio_info bma400_info = {
|
||||
.read_raw = bma400_read_raw,
|
||||
.read_avail = bma400_read_avail,
|
||||
.write_raw = bma400_write_raw,
|
||||
.write_raw_get_fmt = bma400_write_raw_get_fmt,
|
||||
.read_event_config = bma400_read_event_config,
|
||||
.write_event_config = bma400_write_event_config,
|
||||
.write_event_value = bma400_write_event_value,
|
||||
.read_event_value = bma400_read_event_value,
|
||||
};
|
||||
|
||||
int bma400_probe(struct device *dev, struct regmap *regmap, const char *name)
|
||||
static const struct iio_trigger_ops bma400_trigger_ops = {
|
||||
.set_trigger_state = &bma400_data_rdy_trigger_set_state,
|
||||
.validate_device = &iio_trigger_validate_own_device,
|
||||
};
|
||||
|
||||
static irqreturn_t bma400_trigger_handler(int irq, void *p)
|
||||
{
|
||||
struct iio_poll_func *pf = p;
|
||||
struct iio_dev *indio_dev = pf->indio_dev;
|
||||
struct bma400_data *data = iio_priv(indio_dev);
|
||||
int ret, temp;
|
||||
|
||||
/* Lock to protect the data->buffer */
|
||||
mutex_lock(&data->mutex);
|
||||
|
||||
/* bulk read six registers, with the base being the LSB register */
|
||||
ret = regmap_bulk_read(data->regmap, BMA400_X_AXIS_LSB_REG,
|
||||
&data->buffer.buff, sizeof(data->buffer.buff));
|
||||
if (ret)
|
||||
goto unlock_err;
|
||||
|
||||
if (test_bit(BMA400_TEMP, indio_dev->active_scan_mask)) {
|
||||
ret = regmap_read(data->regmap, BMA400_TEMP_DATA_REG, &temp);
|
||||
if (ret)
|
||||
goto unlock_err;
|
||||
|
||||
data->buffer.temperature = temp;
|
||||
}
|
||||
|
||||
iio_push_to_buffers_with_timestamp(indio_dev, &data->buffer,
|
||||
iio_get_time_ns(indio_dev));
|
||||
|
||||
mutex_unlock(&data->mutex);
|
||||
iio_trigger_notify_done(indio_dev->trig);
|
||||
return IRQ_HANDLED;
|
||||
|
||||
unlock_err:
|
||||
mutex_unlock(&data->mutex);
|
||||
return IRQ_NONE;
|
||||
}
|
||||
|
||||
static irqreturn_t bma400_interrupt(int irq, void *private)
|
||||
{
|
||||
struct iio_dev *indio_dev = private;
|
||||
struct bma400_data *data = iio_priv(indio_dev);
|
||||
s64 timestamp = iio_get_time_ns(indio_dev);
|
||||
unsigned int act, ev_dir = IIO_EV_DIR_NONE;
|
||||
int ret;
|
||||
|
||||
/* Lock to protect the data->status */
|
||||
mutex_lock(&data->mutex);
|
||||
ret = regmap_bulk_read(data->regmap, BMA400_INT_STAT0_REG,
|
||||
&data->status,
|
||||
sizeof(data->status));
|
||||
/*
|
||||
* if none of the bit is set in the status register then it is
|
||||
* spurious interrupt.
|
||||
*/
|
||||
if (ret || !data->status)
|
||||
goto unlock_err;
|
||||
|
||||
if (FIELD_GET(BMA400_INT_GEN1_MSK, le16_to_cpu(data->status)))
|
||||
ev_dir = IIO_EV_DIR_RISING;
|
||||
|
||||
if (FIELD_GET(BMA400_INT_GEN2_MSK, le16_to_cpu(data->status)))
|
||||
ev_dir = IIO_EV_DIR_FALLING;
|
||||
|
||||
if (ev_dir != IIO_EV_DIR_NONE) {
|
||||
iio_push_event(indio_dev,
|
||||
IIO_MOD_EVENT_CODE(IIO_ACCEL, 0,
|
||||
IIO_MOD_X_OR_Y_OR_Z,
|
||||
IIO_EV_TYPE_MAG, ev_dir),
|
||||
timestamp);
|
||||
}
|
||||
|
||||
if (FIELD_GET(BMA400_STEP_STAT_MASK, le16_to_cpu(data->status))) {
|
||||
iio_push_event(indio_dev,
|
||||
IIO_MOD_EVENT_CODE(IIO_STEPS, 0, IIO_NO_MOD,
|
||||
IIO_EV_TYPE_CHANGE,
|
||||
IIO_EV_DIR_NONE),
|
||||
timestamp);
|
||||
|
||||
if (data->activity_event_en) {
|
||||
ret = regmap_read(data->regmap, BMA400_STEP_STAT_REG,
|
||||
&act);
|
||||
if (ret)
|
||||
goto unlock_err;
|
||||
|
||||
iio_push_event(indio_dev,
|
||||
IIO_MOD_EVENT_CODE(IIO_ACTIVITY, 0,
|
||||
bma400_act_to_mod(act),
|
||||
IIO_EV_TYPE_CHANGE,
|
||||
IIO_EV_DIR_NONE),
|
||||
timestamp);
|
||||
}
|
||||
}
|
||||
|
||||
if (FIELD_GET(BMA400_INT_DRDY_MSK, le16_to_cpu(data->status))) {
|
||||
mutex_unlock(&data->mutex);
|
||||
iio_trigger_poll_chained(data->trig);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
mutex_unlock(&data->mutex);
|
||||
return IRQ_HANDLED;
|
||||
|
||||
unlock_err:
|
||||
mutex_unlock(&data->mutex);
|
||||
return IRQ_NONE;
|
||||
}
|
||||
|
||||
int bma400_probe(struct device *dev, struct regmap *regmap, int irq,
|
||||
const char *name)
|
||||
{
|
||||
struct iio_dev *indio_dev;
|
||||
struct bma400_data *data;
|
||||
|
@ -820,34 +1428,44 @@ int bma400_probe(struct device *dev, struct regmap *regmap, const char *name)
|
|||
indio_dev->info = &bma400_info;
|
||||
indio_dev->channels = bma400_channels;
|
||||
indio_dev->num_channels = ARRAY_SIZE(bma400_channels);
|
||||
indio_dev->available_scan_masks = bma400_avail_scan_masks;
|
||||
indio_dev->modes = INDIO_DIRECT_MODE;
|
||||
|
||||
dev_set_drvdata(dev, indio_dev);
|
||||
if (irq > 0) {
|
||||
data->trig = devm_iio_trigger_alloc(dev, "%s-dev%d",
|
||||
indio_dev->name,
|
||||
iio_device_id(indio_dev));
|
||||
if (!data->trig)
|
||||
return -ENOMEM;
|
||||
|
||||
return iio_device_register(indio_dev);
|
||||
data->trig->ops = &bma400_trigger_ops;
|
||||
iio_trigger_set_drvdata(data->trig, indio_dev);
|
||||
|
||||
ret = devm_iio_trigger_register(data->dev, data->trig);
|
||||
if (ret)
|
||||
return dev_err_probe(data->dev, ret,
|
||||
"iio trigger register fail\n");
|
||||
|
||||
indio_dev->trig = iio_trigger_get(data->trig);
|
||||
ret = devm_request_threaded_irq(dev, irq, NULL,
|
||||
&bma400_interrupt,
|
||||
IRQF_TRIGGER_RISING | IRQF_ONESHOT,
|
||||
indio_dev->name, indio_dev);
|
||||
if (ret)
|
||||
return dev_err_probe(data->dev, ret,
|
||||
"request irq %d failed\n", irq);
|
||||
}
|
||||
|
||||
ret = devm_iio_triggered_buffer_setup(dev, indio_dev, NULL,
|
||||
&bma400_trigger_handler, NULL);
|
||||
if (ret)
|
||||
return dev_err_probe(data->dev, ret,
|
||||
"iio triggered buffer setup failed\n");
|
||||
|
||||
return devm_iio_device_register(dev, indio_dev);
|
||||
}
|
||||
EXPORT_SYMBOL_NS(bma400_probe, IIO_BMA400);
|
||||
|
||||
void bma400_remove(struct device *dev)
|
||||
{
|
||||
struct iio_dev *indio_dev = dev_get_drvdata(dev);
|
||||
struct bma400_data *data = iio_priv(indio_dev);
|
||||
int ret;
|
||||
|
||||
mutex_lock(&data->mutex);
|
||||
ret = bma400_set_power_mode(data, POWER_MODE_SLEEP);
|
||||
mutex_unlock(&data->mutex);
|
||||
|
||||
if (ret)
|
||||
dev_warn(dev, "Failed to put device into sleep mode (%pe)\n", ERR_PTR(ret));
|
||||
|
||||
regulator_bulk_disable(ARRAY_SIZE(data->regulators),
|
||||
data->regulators);
|
||||
|
||||
iio_device_unregister(indio_dev);
|
||||
}
|
||||
EXPORT_SYMBOL_NS(bma400_remove, IIO_BMA400);
|
||||
|
||||
MODULE_AUTHOR("Dan Robertson <dan@dlrobertson.com>");
|
||||
MODULE_DESCRIPTION("Bosch BMA400 triaxial acceleration sensor core");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
|
|
@ -24,14 +24,7 @@ static int bma400_i2c_probe(struct i2c_client *client,
|
|||
return PTR_ERR(regmap);
|
||||
}
|
||||
|
||||
return bma400_probe(&client->dev, regmap, id->name);
|
||||
}
|
||||
|
||||
static int bma400_i2c_remove(struct i2c_client *client)
|
||||
{
|
||||
bma400_remove(&client->dev);
|
||||
|
||||
return 0;
|
||||
return bma400_probe(&client->dev, regmap, client->irq, id->name);
|
||||
}
|
||||
|
||||
static const struct i2c_device_id bma400_i2c_ids[] = {
|
||||
|
@ -52,7 +45,6 @@ static struct i2c_driver bma400_i2c_driver = {
|
|||
.of_match_table = bma400_of_i2c_match,
|
||||
},
|
||||
.probe = bma400_i2c_probe,
|
||||
.remove = bma400_i2c_remove,
|
||||
.id_table = bma400_i2c_ids,
|
||||
};
|
||||
|
||||
|
|
|
@ -84,12 +84,7 @@ static int bma400_spi_probe(struct spi_device *spi)
|
|||
if (ret)
|
||||
dev_err(&spi->dev, "Failed to read chip id register\n");
|
||||
|
||||
return bma400_probe(&spi->dev, regmap, id->name);
|
||||
}
|
||||
|
||||
static void bma400_spi_remove(struct spi_device *spi)
|
||||
{
|
||||
bma400_remove(&spi->dev);
|
||||
return bma400_probe(&spi->dev, regmap, spi->irq, id->name);
|
||||
}
|
||||
|
||||
static const struct spi_device_id bma400_spi_ids[] = {
|
||||
|
@ -110,7 +105,6 @@ static struct spi_driver bma400_spi_driver = {
|
|||
.of_match_table = bma400_of_spi_match,
|
||||
},
|
||||
.probe = bma400_spi_probe,
|
||||
.remove = bma400_spi_remove,
|
||||
.id_table = bma400_spi_ids,
|
||||
};
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
* Copyright (c) 2018-2021, Topic Embedded Products
|
||||
*/
|
||||
|
||||
#include <linux/bitfield.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/iio/iio.h>
|
||||
#include <linux/iio/sysfs.h>
|
||||
|
@ -73,6 +74,8 @@
|
|||
#define BMI088_ACCEL_FIFO_MODE_FIFO 0x40
|
||||
#define BMI088_ACCEL_FIFO_MODE_STREAM 0x80
|
||||
|
||||
#define BMIO088_ACCEL_ACC_RANGE_MSK GENMASK(1, 0)
|
||||
|
||||
enum bmi088_accel_axis {
|
||||
AXIS_X,
|
||||
AXIS_Y,
|
||||
|
@ -119,12 +122,13 @@ struct bmi088_accel_chip_info {
|
|||
u8 chip_id;
|
||||
const struct iio_chan_spec *channels;
|
||||
int num_channels;
|
||||
const int scale_table[4][2];
|
||||
};
|
||||
|
||||
struct bmi088_accel_data {
|
||||
struct regmap *regmap;
|
||||
const struct bmi088_accel_chip_info *chip_info;
|
||||
u8 buffer[2] ____cacheline_aligned; /* shared DMA safe buffer */
|
||||
u8 buffer[2] __aligned(IIO_DMA_MINALIGN); /* shared DMA safe buffer */
|
||||
};
|
||||
|
||||
static const struct regmap_range bmi088_volatile_ranges[] = {
|
||||
|
@ -236,6 +240,21 @@ static int bmi088_accel_set_sample_freq(struct bmi088_accel_data *data, int val)
|
|||
BMI088_ACCEL_MODE_ODR_MASK, regval);
|
||||
}
|
||||
|
||||
static int bmi088_accel_set_scale(struct bmi088_accel_data *data, int val, int val2)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
if (val == data->chip_info->scale_table[i][0] &&
|
||||
val2 == data->chip_info->scale_table[i][1])
|
||||
break;
|
||||
|
||||
if (i == 4)
|
||||
return -EINVAL;
|
||||
|
||||
return regmap_write(data->regmap, BMI088_ACCEL_REG_ACC_RANGE, i);
|
||||
}
|
||||
|
||||
static int bmi088_accel_get_temp(struct bmi088_accel_data *data, int *val)
|
||||
{
|
||||
int ret;
|
||||
|
@ -280,6 +299,7 @@ static int bmi088_accel_read_raw(struct iio_dev *indio_dev,
|
|||
struct bmi088_accel_data *data = iio_priv(indio_dev);
|
||||
struct device *dev = regmap_get_device(data->regmap);
|
||||
int ret;
|
||||
int reg;
|
||||
|
||||
switch (mask) {
|
||||
case IIO_CHAN_INFO_RAW:
|
||||
|
@ -330,13 +350,14 @@ static int bmi088_accel_read_raw(struct iio_dev *indio_dev,
|
|||
return ret;
|
||||
|
||||
ret = regmap_read(data->regmap,
|
||||
BMI088_ACCEL_REG_ACC_RANGE, val);
|
||||
BMI088_ACCEL_REG_ACC_RANGE, ®);
|
||||
if (ret)
|
||||
goto out_read_raw_pm_put;
|
||||
|
||||
*val2 = 15 - (*val & 0x3);
|
||||
*val = 3 * 980;
|
||||
ret = IIO_VAL_FRACTIONAL_LOG2;
|
||||
reg = FIELD_GET(BMIO088_ACCEL_ACC_RANGE_MSK, reg);
|
||||
*val = data->chip_info->scale_table[reg][0];
|
||||
*val2 = data->chip_info->scale_table[reg][1];
|
||||
ret = IIO_VAL_INT_PLUS_MICRO;
|
||||
|
||||
goto out_read_raw_pm_put;
|
||||
default:
|
||||
|
@ -367,7 +388,14 @@ static int bmi088_accel_read_avail(struct iio_dev *indio_dev,
|
|||
const int **vals, int *type, int *length,
|
||||
long mask)
|
||||
{
|
||||
struct bmi088_accel_data *data = iio_priv(indio_dev);
|
||||
|
||||
switch (mask) {
|
||||
case IIO_CHAN_INFO_SCALE:
|
||||
*vals = (const int *)data->chip_info->scale_table;
|
||||
*length = 8;
|
||||
*type = IIO_VAL_INT_PLUS_MICRO;
|
||||
return IIO_AVAIL_LIST;
|
||||
case IIO_CHAN_INFO_SAMP_FREQ:
|
||||
*type = IIO_VAL_INT_PLUS_MICRO;
|
||||
*vals = bmi088_sample_freqs;
|
||||
|
@ -387,6 +415,15 @@ static int bmi088_accel_write_raw(struct iio_dev *indio_dev,
|
|||
int ret;
|
||||
|
||||
switch (mask) {
|
||||
case IIO_CHAN_INFO_SCALE:
|
||||
ret = pm_runtime_resume_and_get(dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = bmi088_accel_set_scale(data, val, val2);
|
||||
pm_runtime_mark_last_busy(dev);
|
||||
pm_runtime_put_autosuspend(dev);
|
||||
return ret;
|
||||
case IIO_CHAN_INFO_SAMP_FREQ:
|
||||
ret = pm_runtime_resume_and_get(dev);
|
||||
if (ret)
|
||||
|
@ -408,7 +445,8 @@ static int bmi088_accel_write_raw(struct iio_dev *indio_dev,
|
|||
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
|
||||
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \
|
||||
BIT(IIO_CHAN_INFO_SAMP_FREQ), \
|
||||
.info_mask_shared_by_type_available = BIT(IIO_CHAN_INFO_SAMP_FREQ), \
|
||||
.info_mask_shared_by_type_available = BIT(IIO_CHAN_INFO_SAMP_FREQ) | \
|
||||
BIT(IIO_CHAN_INFO_SCALE), \
|
||||
.scan_index = AXIS_##_axis, \
|
||||
}
|
||||
|
||||
|
@ -427,11 +465,26 @@ static const struct iio_chan_spec bmi088_accel_channels[] = {
|
|||
};
|
||||
|
||||
static const struct bmi088_accel_chip_info bmi088_accel_chip_info_tbl[] = {
|
||||
[0] = {
|
||||
.name = "bmi088a",
|
||||
[BOSCH_BMI085] = {
|
||||
.name = "bmi085-accel",
|
||||
.chip_id = 0x1F,
|
||||
.channels = bmi088_accel_channels,
|
||||
.num_channels = ARRAY_SIZE(bmi088_accel_channels),
|
||||
.scale_table = {{0, 598}, {0, 1196}, {0, 2393}, {0, 4785}},
|
||||
},
|
||||
[BOSCH_BMI088] = {
|
||||
.name = "bmi088-accel",
|
||||
.chip_id = 0x1E,
|
||||
.channels = bmi088_accel_channels,
|
||||
.num_channels = ARRAY_SIZE(bmi088_accel_channels),
|
||||
.scale_table = {{0, 897}, {0, 1794}, {0, 3589}, {0, 7178}},
|
||||
},
|
||||
[BOSCH_BMI090L] = {
|
||||
.name = "bmi090l-accel",
|
||||
.chip_id = 0x1A,
|
||||
.channels = bmi088_accel_channels,
|
||||
.num_channels = ARRAY_SIZE(bmi088_accel_channels),
|
||||
.scale_table = {{0, 897}, {0, 1794}, {0, 3589}, {0, 7178}},
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -446,12 +499,15 @@ static const unsigned long bmi088_accel_scan_masks[] = {
|
|||
0
|
||||
};
|
||||
|
||||
static int bmi088_accel_chip_init(struct bmi088_accel_data *data)
|
||||
static int bmi088_accel_chip_init(struct bmi088_accel_data *data, enum bmi_device_type type)
|
||||
{
|
||||
struct device *dev = regmap_get_device(data->regmap);
|
||||
int ret, i;
|
||||
unsigned int val;
|
||||
|
||||
if (type >= BOSCH_UNKNOWN)
|
||||
return -ENODEV;
|
||||
|
||||
/* Do a dummy read to enable SPI interface, won't harm I2C */
|
||||
regmap_read(data->regmap, BMI088_ACCEL_REG_INT_STATUS, &val);
|
||||
|
||||
|
@ -477,22 +533,23 @@ static int bmi088_accel_chip_init(struct bmi088_accel_data *data)
|
|||
}
|
||||
|
||||
/* Validate chip ID */
|
||||
for (i = 0; i < ARRAY_SIZE(bmi088_accel_chip_info_tbl); i++) {
|
||||
if (bmi088_accel_chip_info_tbl[i].chip_id == val) {
|
||||
data->chip_info = &bmi088_accel_chip_info_tbl[i];
|
||||
for (i = 0; i < ARRAY_SIZE(bmi088_accel_chip_info_tbl); i++)
|
||||
if (bmi088_accel_chip_info_tbl[i].chip_id == val)
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i == ARRAY_SIZE(bmi088_accel_chip_info_tbl)) {
|
||||
dev_err(dev, "Invalid chip %x\n", val);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (i == ARRAY_SIZE(bmi088_accel_chip_info_tbl))
|
||||
data->chip_info = &bmi088_accel_chip_info_tbl[type];
|
||||
else
|
||||
data->chip_info = &bmi088_accel_chip_info_tbl[i];
|
||||
|
||||
if (i != type)
|
||||
dev_warn(dev, "unexpected chip id 0x%X\n", val);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bmi088_accel_core_probe(struct device *dev, struct regmap *regmap,
|
||||
int irq, const char *name, bool block_supported)
|
||||
int irq, enum bmi_device_type type)
|
||||
{
|
||||
struct bmi088_accel_data *data;
|
||||
struct iio_dev *indio_dev;
|
||||
|
@ -507,13 +564,13 @@ int bmi088_accel_core_probe(struct device *dev, struct regmap *regmap,
|
|||
|
||||
data->regmap = regmap;
|
||||
|
||||
ret = bmi088_accel_chip_init(data);
|
||||
ret = bmi088_accel_chip_init(data, type);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
indio_dev->channels = data->chip_info->channels;
|
||||
indio_dev->num_channels = data->chip_info->num_channels;
|
||||
indio_dev->name = name ? name : data->chip_info->name;
|
||||
indio_dev->name = data->chip_info->name;
|
||||
indio_dev->available_scan_masks = bmi088_accel_scan_masks;
|
||||
indio_dev->modes = INDIO_DIRECT_MODE;
|
||||
indio_dev->info = &bmi088_accel_info;
|
||||
|
|
|
@ -52,8 +52,8 @@ static int bmi088_accel_probe(struct spi_device *spi)
|
|||
return PTR_ERR(regmap);
|
||||
}
|
||||
|
||||
return bmi088_accel_core_probe(&spi->dev, regmap, spi->irq, id->name,
|
||||
true);
|
||||
return bmi088_accel_core_probe(&spi->dev, regmap, spi->irq,
|
||||
id->driver_data);
|
||||
}
|
||||
|
||||
static void bmi088_accel_remove(struct spi_device *spi)
|
||||
|
@ -61,8 +61,18 @@ static void bmi088_accel_remove(struct spi_device *spi)
|
|||
bmi088_accel_core_remove(&spi->dev);
|
||||
}
|
||||
|
||||
static const struct of_device_id bmi088_of_match[] = {
|
||||
{ .compatible = "bosch,bmi085-accel" },
|
||||
{ .compatible = "bosch,bmi088-accel" },
|
||||
{ .compatible = "bosch,bmi090l-accel" },
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, bmi088_of_match);
|
||||
|
||||
static const struct spi_device_id bmi088_accel_id[] = {
|
||||
{"bmi088-accel", },
|
||||
{"bmi085-accel", BOSCH_BMI085},
|
||||
{"bmi088-accel", BOSCH_BMI088},
|
||||
{"bmi090l-accel", BOSCH_BMI090L},
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(spi, bmi088_accel_id);
|
||||
|
@ -71,6 +81,7 @@ static struct spi_driver bmi088_accel_driver = {
|
|||
.driver = {
|
||||
.name = "bmi088_accel_spi",
|
||||
.pm = &bmi088_accel_pm_ops,
|
||||
.of_match_table = bmi088_of_match,
|
||||
},
|
||||
.probe = bmi088_accel_probe,
|
||||
.remove = bmi088_accel_remove,
|
||||
|
|
|
@ -8,11 +8,18 @@
|
|||
|
||||
struct device;
|
||||
|
||||
enum bmi_device_type {
|
||||
BOSCH_BMI085,
|
||||
BOSCH_BMI088,
|
||||
BOSCH_BMI090L,
|
||||
BOSCH_UNKNOWN,
|
||||
};
|
||||
|
||||
extern const struct regmap_config bmi088_regmap_conf;
|
||||
extern const struct dev_pm_ops bmi088_accel_pm_ops;
|
||||
|
||||
int bmi088_accel_core_probe(struct device *dev, struct regmap *regmap, int irq,
|
||||
const char *name, bool block_supported);
|
||||
enum bmi_device_type type);
|
||||
void bmi088_accel_core_remove(struct device *dev);
|
||||
|
||||
#endif /* BMI088_ACCEL_H */
|
||||
|
|
|
@ -230,7 +230,7 @@ static int cros_ec_accel_legacy_probe(struct platform_device *pdev)
|
|||
indio_dev->channels = cros_ec_accel_legacy_channels;
|
||||
indio_dev->num_channels = ARRAY_SIZE(cros_ec_accel_legacy_channels);
|
||||
/* The lid sensor needs to be presented inverted. */
|
||||
if (state->loc == MOTIONSENSE_LOC_LID) {
|
||||
if (!strcmp(indio_dev->label, "accel-display")) {
|
||||
state->sign[CROS_EC_SENSOR_X] = -1;
|
||||
state->sign[CROS_EC_SENSOR_Z] = -1;
|
||||
}
|
||||
|
|
|
@ -55,7 +55,7 @@ static struct i2c_driver kxsd9_i2c_driver = {
|
|||
.driver = {
|
||||
.name = "kxsd9",
|
||||
.of_match_table = kxsd9_of_match,
|
||||
.pm = &kxsd9_dev_pm_ops,
|
||||
.pm = pm_ptr(&kxsd9_dev_pm_ops),
|
||||
},
|
||||
.probe = kxsd9_i2c_probe,
|
||||
.remove = kxsd9_i2c_remove,
|
||||
|
|
|
@ -52,7 +52,7 @@ MODULE_DEVICE_TABLE(of, kxsd9_of_match);
|
|||
static struct spi_driver kxsd9_spi_driver = {
|
||||
.driver = {
|
||||
.name = "kxsd9",
|
||||
.pm = &kxsd9_dev_pm_ops,
|
||||
.pm = pm_ptr(&kxsd9_dev_pm_ops),
|
||||
.of_match_table = kxsd9_of_match,
|
||||
},
|
||||
.probe = kxsd9_spi_probe,
|
||||
|
|
|
@ -492,7 +492,6 @@ void kxsd9_common_remove(struct device *dev)
|
|||
}
|
||||
EXPORT_SYMBOL_NS(kxsd9_common_remove, IIO_KXSD9);
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
static int kxsd9_runtime_suspend(struct device *dev)
|
||||
{
|
||||
struct iio_dev *indio_dev = dev_get_drvdata(dev);
|
||||
|
@ -508,15 +507,9 @@ static int kxsd9_runtime_resume(struct device *dev)
|
|||
|
||||
return kxsd9_power_up(st);
|
||||
}
|
||||
#endif /* CONFIG_PM */
|
||||
|
||||
const struct dev_pm_ops kxsd9_dev_pm_ops = {
|
||||
SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
|
||||
pm_runtime_force_resume)
|
||||
SET_RUNTIME_PM_OPS(kxsd9_runtime_suspend,
|
||||
kxsd9_runtime_resume, NULL)
|
||||
};
|
||||
EXPORT_SYMBOL_NS(kxsd9_dev_pm_ops, IIO_KXSD9);
|
||||
EXPORT_NS_RUNTIME_DEV_PM_OPS(kxsd9_dev_pm_ops, kxsd9_runtime_suspend,
|
||||
kxsd9_runtime_resume, NULL, IIO_KXSD9);
|
||||
|
||||
MODULE_AUTHOR("Jonathan Cameron <jic23@kernel.org>");
|
||||
MODULE_DESCRIPTION("Kionix KXSD9 driver");
|
||||
|
|
|
@ -157,7 +157,9 @@ static int mc3230_remove(struct i2c_client *client)
|
|||
|
||||
iio_device_unregister(indio_dev);
|
||||
|
||||
return mc3230_set_opcon(iio_priv(indio_dev), MC3230_MODE_OPCON_STANDBY);
|
||||
mc3230_set_opcon(iio_priv(indio_dev), MC3230_MODE_OPCON_STANDBY);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mc3230_suspend(struct device *dev)
|
||||
|
|
|
@ -7,8 +7,8 @@
|
|||
* IIO driver for Freescale MMA7660FC; 7-bit I2C address: 0x4c.
|
||||
*/
|
||||
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/mod_devicetable.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/iio/iio.h>
|
||||
#include <linux/iio/sysfs.h>
|
||||
|
@ -255,7 +255,7 @@ static const struct of_device_id mma7660_of_match[] = {
|
|||
};
|
||||
MODULE_DEVICE_TABLE(of, mma7660_of_match);
|
||||
|
||||
static const struct acpi_device_id __maybe_unused mma7660_acpi_id[] = {
|
||||
static const struct acpi_device_id mma7660_acpi_id[] = {
|
||||
{"MMA7660", 0},
|
||||
{}
|
||||
};
|
||||
|
@ -267,7 +267,7 @@ static struct i2c_driver mma7660_driver = {
|
|||
.name = "mma7660",
|
||||
.pm = pm_sleep_ptr(&mma7660_pm_ops),
|
||||
.of_match_table = mma7660_of_match,
|
||||
.acpi_match_table = ACPI_PTR(mma7660_acpi_id),
|
||||
.acpi_match_table = mma7660_acpi_id,
|
||||
},
|
||||
.probe = mma7660_probe,
|
||||
.remove = mma7660_remove,
|
||||
|
|
|
@ -167,8 +167,8 @@ struct sca3000_state {
|
|||
int mo_det_use_count;
|
||||
struct mutex lock;
|
||||
/* Can these share a cacheline ? */
|
||||
u8 rx[384] ____cacheline_aligned;
|
||||
u8 tx[6] ____cacheline_aligned;
|
||||
u8 rx[384] __aligned(IIO_DMA_MINALIGN);
|
||||
u8 tx[6] __aligned(IIO_DMA_MINALIGN);
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -424,7 +424,7 @@ error_ret:
|
|||
* sca3000_print_rev() - sysfs interface to read the chip revision number
|
||||
* @indio_dev: Device instance specific generic IIO data.
|
||||
* Driver specific device instance data can be obtained via
|
||||
* via iio_priv(indio_dev)
|
||||
* iio_priv(indio_dev)
|
||||
*/
|
||||
static int sca3000_print_rev(struct iio_dev *indio_dev)
|
||||
{
|
||||
|
|
|
@ -38,17 +38,24 @@
|
|||
/* Device ID */
|
||||
#define SCA3300_REG_WHOAMI 0x10
|
||||
#define SCA3300_WHOAMI_ID 0x51
|
||||
#define SCL3300_WHOAMI_ID 0xC1
|
||||
|
||||
/* Device return status and mask */
|
||||
#define SCA3300_VALUE_RS_ERROR 0x3
|
||||
#define SCA3300_MASK_RS_STATUS GENMASK(1, 0)
|
||||
|
||||
#define SCL3300_REG_ANG_CTRL 0x0C
|
||||
#define SCL3300_ANG_ENABLE 0x1F
|
||||
|
||||
enum sca3300_scan_indexes {
|
||||
SCA3300_ACC_X = 0,
|
||||
SCA3300_ACC_Y,
|
||||
SCA3300_ACC_Z,
|
||||
SCA3300_TEMP,
|
||||
SCA3300_TIMESTAMP,
|
||||
SCA3300_INCLI_X,
|
||||
SCA3300_INCLI_Y,
|
||||
SCA3300_INCLI_Z,
|
||||
};
|
||||
|
||||
#define SCA3300_ACCEL_CHANNEL(index, reg, axis) { \
|
||||
|
@ -72,27 +79,72 @@ enum sca3300_scan_indexes {
|
|||
}, \
|
||||
}
|
||||
|
||||
#define SCA3300_INCLI_CHANNEL(index, reg, axis) { \
|
||||
.type = IIO_INCLI, \
|
||||
.address = reg, \
|
||||
.modified = 1, \
|
||||
.channel2 = IIO_MOD_##axis, \
|
||||
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
|
||||
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
|
||||
.info_mask_shared_by_type_available = BIT(IIO_CHAN_INFO_SCALE), \
|
||||
.scan_index = index, \
|
||||
.scan_type = { \
|
||||
.sign = 's', \
|
||||
.realbits = 16, \
|
||||
.storagebits = 16, \
|
||||
.endianness = IIO_CPU, \
|
||||
}, \
|
||||
}
|
||||
|
||||
#define SCA3300_TEMP_CHANNEL(index, reg) { \
|
||||
.type = IIO_TEMP, \
|
||||
.address = reg, \
|
||||
.scan_index = index, \
|
||||
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
|
||||
.scan_type = { \
|
||||
.sign = 's', \
|
||||
.realbits = 16, \
|
||||
.storagebits = 16, \
|
||||
.endianness = IIO_CPU, \
|
||||
}, \
|
||||
}
|
||||
|
||||
static const struct iio_chan_spec sca3300_channels[] = {
|
||||
SCA3300_ACCEL_CHANNEL(SCA3300_ACC_X, 0x1, X),
|
||||
SCA3300_ACCEL_CHANNEL(SCA3300_ACC_Y, 0x2, Y),
|
||||
SCA3300_ACCEL_CHANNEL(SCA3300_ACC_Z, 0x3, Z),
|
||||
{
|
||||
.type = IIO_TEMP,
|
||||
.address = 0x5,
|
||||
.scan_index = SCA3300_TEMP,
|
||||
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
|
||||
.scan_type = {
|
||||
.sign = 's',
|
||||
.realbits = 16,
|
||||
.storagebits = 16,
|
||||
.endianness = IIO_CPU,
|
||||
},
|
||||
},
|
||||
SCA3300_TEMP_CHANNEL(SCA3300_TEMP, 0x05),
|
||||
IIO_CHAN_SOFT_TIMESTAMP(4),
|
||||
};
|
||||
|
||||
static const int sca3300_lp_freq[] = {70, 70, 70, 10};
|
||||
static const int sca3300_accel_scale[][2] = {{0, 370}, {0, 741}, {0, 185}, {0, 185}};
|
||||
static const int sca3300_lp_freq[] = {70, 10};
|
||||
static const int sca3300_lp_freq_map[] = {0, 0, 0, 1};
|
||||
|
||||
static const int scl3300_lp_freq[] = {40, 70, 10};
|
||||
static const int scl3300_lp_freq_map[] = {0, 1, 2};
|
||||
|
||||
static const int sca3300_accel_scale[][2] = {{0, 370}, {0, 741}, {0, 185}};
|
||||
static const int sca3300_accel_scale_map[] = {0, 1, 2, 2};
|
||||
|
||||
static const int scl3300_accel_scale[][2] = {{0, 167}, {0, 333}, {0, 83}};
|
||||
static const int scl3300_accel_scale_map[] = {0, 1, 2};
|
||||
|
||||
static const int scl3300_incli_scale[][2] = {{0, 5495}};
|
||||
static const int scl3300_incli_scale_map[] = {0, 0, 0};
|
||||
|
||||
static const int sca3300_avail_modes_map[] = {0, 1, 2, 3};
|
||||
static const int scl3300_avail_modes_map[] = {0, 1, 3};
|
||||
|
||||
static const struct iio_chan_spec scl3300_channels[] = {
|
||||
SCA3300_ACCEL_CHANNEL(SCA3300_ACC_X, 0x1, X),
|
||||
SCA3300_ACCEL_CHANNEL(SCA3300_ACC_Y, 0x2, Y),
|
||||
SCA3300_ACCEL_CHANNEL(SCA3300_ACC_Z, 0x3, Z),
|
||||
SCA3300_TEMP_CHANNEL(SCA3300_TEMP, 0x05),
|
||||
IIO_CHAN_SOFT_TIMESTAMP(4),
|
||||
SCA3300_INCLI_CHANNEL(SCA3300_INCLI_X, 0x09, X),
|
||||
SCA3300_INCLI_CHANNEL(SCA3300_INCLI_Y, 0x0A, Y),
|
||||
SCA3300_INCLI_CHANNEL(SCA3300_INCLI_Z, 0x0B, Z),
|
||||
};
|
||||
|
||||
static const unsigned long sca3300_scan_masks[] = {
|
||||
BIT(SCA3300_ACC_X) | BIT(SCA3300_ACC_Y) | BIT(SCA3300_ACC_Z) |
|
||||
|
@ -100,10 +152,38 @@ static const unsigned long sca3300_scan_masks[] = {
|
|||
0
|
||||
};
|
||||
|
||||
static const unsigned long scl3300_scan_masks[] = {
|
||||
BIT(SCA3300_ACC_X) | BIT(SCA3300_ACC_Y) | BIT(SCA3300_ACC_Z) |
|
||||
BIT(SCA3300_TEMP) |
|
||||
BIT(SCA3300_INCLI_X) | BIT(SCA3300_INCLI_Y) | BIT(SCA3300_INCLI_Z),
|
||||
0
|
||||
};
|
||||
|
||||
struct sca3300_chip_info {
|
||||
const char *name;
|
||||
const unsigned long *scan_masks;
|
||||
const struct iio_chan_spec *channels;
|
||||
u8 num_channels;
|
||||
u8 num_accel_scales;
|
||||
const int (*accel_scale)[2];
|
||||
const int *accel_scale_map;
|
||||
const int (*incli_scale)[2];
|
||||
const int *incli_scale_map;
|
||||
u8 num_incli_scales;
|
||||
u8 num_freqs;
|
||||
const int *freq_table;
|
||||
const int *freq_map;
|
||||
const int *avail_modes_table;
|
||||
u8 num_avail_modes;
|
||||
u8 chip_id;
|
||||
bool angle_supported;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct sca3300_data - device data
|
||||
* @spi: SPI device structure
|
||||
* @lock: Data buffer lock
|
||||
* @chip: Sensor chip specific information
|
||||
* @scan: Triggered buffer. Four channel 16-bit data + 64-bit timestamp
|
||||
* @txbuf: Transmit buffer
|
||||
* @rxbuf: Receive buffer
|
||||
|
@ -111,14 +191,53 @@ static const unsigned long sca3300_scan_masks[] = {
|
|||
struct sca3300_data {
|
||||
struct spi_device *spi;
|
||||
struct mutex lock;
|
||||
const struct sca3300_chip_info *chip;
|
||||
struct {
|
||||
s16 channels[4];
|
||||
s64 ts __aligned(sizeof(s64));
|
||||
} scan;
|
||||
u8 txbuf[4] ____cacheline_aligned;
|
||||
u8 txbuf[4] __aligned(IIO_DMA_MINALIGN);
|
||||
u8 rxbuf[4];
|
||||
};
|
||||
|
||||
static const struct sca3300_chip_info sca3300_chip_tbl[] = {
|
||||
{
|
||||
.name = "sca3300",
|
||||
.scan_masks = sca3300_scan_masks,
|
||||
.channels = sca3300_channels,
|
||||
.num_channels = ARRAY_SIZE(sca3300_channels),
|
||||
.num_accel_scales = ARRAY_SIZE(sca3300_accel_scale)*2,
|
||||
.accel_scale = sca3300_accel_scale,
|
||||
.accel_scale_map = sca3300_accel_scale_map,
|
||||
.num_freqs = ARRAY_SIZE(sca3300_lp_freq),
|
||||
.freq_table = sca3300_lp_freq,
|
||||
.freq_map = sca3300_lp_freq_map,
|
||||
.avail_modes_table = sca3300_avail_modes_map,
|
||||
.num_avail_modes = 4,
|
||||
.chip_id = SCA3300_WHOAMI_ID,
|
||||
.angle_supported = false,
|
||||
},
|
||||
{
|
||||
.name = "scl3300",
|
||||
.scan_masks = scl3300_scan_masks,
|
||||
.channels = scl3300_channels,
|
||||
.num_channels = ARRAY_SIZE(scl3300_channels),
|
||||
.num_accel_scales = ARRAY_SIZE(scl3300_accel_scale)*2,
|
||||
.accel_scale = scl3300_accel_scale,
|
||||
.accel_scale_map = scl3300_accel_scale_map,
|
||||
.incli_scale = scl3300_incli_scale,
|
||||
.incli_scale_map = scl3300_incli_scale_map,
|
||||
.num_incli_scales = ARRAY_SIZE(scl3300_incli_scale)*2,
|
||||
.num_freqs = ARRAY_SIZE(scl3300_lp_freq),
|
||||
.freq_table = scl3300_lp_freq,
|
||||
.freq_map = scl3300_lp_freq_map,
|
||||
.avail_modes_table = scl3300_avail_modes_map,
|
||||
.num_avail_modes = 3,
|
||||
.chip_id = SCL3300_WHOAMI_ID,
|
||||
.angle_supported = true,
|
||||
},
|
||||
};
|
||||
|
||||
DECLARE_CRC8_TABLE(sca3300_crc_table);
|
||||
|
||||
static int sca3300_transfer(struct sca3300_data *sca_data, int *val)
|
||||
|
@ -225,36 +344,91 @@ static int sca3300_write_reg(struct sca3300_data *sca_data, u8 reg, int val)
|
|||
return sca3300_error_handler(sca_data);
|
||||
}
|
||||
|
||||
static int sca3300_set_op_mode(struct sca3300_data *sca_data, int index)
|
||||
{
|
||||
if ((index < 0) || (index >= sca_data->chip->num_avail_modes))
|
||||
return -EINVAL;
|
||||
|
||||
return sca3300_write_reg(sca_data, SCA3300_REG_MODE,
|
||||
sca_data->chip->avail_modes_table[index]);
|
||||
}
|
||||
|
||||
static int sca3300_get_op_mode(struct sca3300_data *sca_data, int *index)
|
||||
{
|
||||
int reg_val;
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
ret = sca3300_read_reg(sca_data, SCA3300_REG_MODE, ®_val);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
for (i = 0; i < sca_data->chip->num_avail_modes; i++) {
|
||||
if (sca_data->chip->avail_modes_table[i] == reg_val)
|
||||
break;
|
||||
}
|
||||
if (i == sca_data->chip->num_avail_modes)
|
||||
return -EINVAL;
|
||||
|
||||
*index = i;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sca3300_set_frequency(struct sca3300_data *data, int val)
|
||||
{
|
||||
const struct sca3300_chip_info *chip = data->chip;
|
||||
unsigned int index;
|
||||
int *opmode_scale;
|
||||
int *new_scale;
|
||||
unsigned int i;
|
||||
|
||||
if (sca3300_get_op_mode(data, &index))
|
||||
return -EINVAL;
|
||||
|
||||
/*
|
||||
* Find a mode in which the requested sampling frequency is available
|
||||
* and the scaling currently set is retained.
|
||||
*/
|
||||
opmode_scale = (int *)chip->accel_scale[chip->accel_scale_map[index]];
|
||||
for (i = 0; i < chip->num_avail_modes; i++) {
|
||||
new_scale = (int *)chip->accel_scale[chip->accel_scale_map[i]];
|
||||
if ((val == chip->freq_table[chip->freq_map[i]]) &&
|
||||
(opmode_scale[1] == new_scale[1]) &&
|
||||
(opmode_scale[0] == new_scale[0]))
|
||||
break;
|
||||
}
|
||||
if (i == chip->num_avail_modes)
|
||||
return -EINVAL;
|
||||
|
||||
return sca3300_set_op_mode(data, i);
|
||||
}
|
||||
|
||||
static int sca3300_write_raw(struct iio_dev *indio_dev,
|
||||
struct iio_chan_spec const *chan,
|
||||
int val, int val2, long mask)
|
||||
{
|
||||
struct sca3300_data *data = iio_priv(indio_dev);
|
||||
int reg_val;
|
||||
int ret;
|
||||
int index;
|
||||
int i;
|
||||
|
||||
switch (mask) {
|
||||
case IIO_CHAN_INFO_SCALE:
|
||||
if (val)
|
||||
if (chan->type != IIO_ACCEL)
|
||||
return -EINVAL;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(sca3300_accel_scale); i++) {
|
||||
if (val2 == sca3300_accel_scale[i][1])
|
||||
return sca3300_write_reg(data, SCA3300_REG_MODE, i);
|
||||
/*
|
||||
* Letting scale take priority over sampling frequency.
|
||||
* That makes sense given we can only ever end up increasing
|
||||
* the sampling frequency which is unlikely to be a problem.
|
||||
*/
|
||||
for (i = 0; i < data->chip->num_avail_modes; i++) {
|
||||
index = data->chip->accel_scale_map[i];
|
||||
if ((val == data->chip->accel_scale[index][0]) &&
|
||||
(val2 == data->chip->accel_scale[index][1]))
|
||||
return sca3300_set_op_mode(data, i);
|
||||
}
|
||||
return -EINVAL;
|
||||
|
||||
case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
|
||||
ret = sca3300_read_reg(data, SCA3300_REG_MODE, ®_val);
|
||||
if (ret)
|
||||
return ret;
|
||||
/* freq. change is possible only for mode 3 and 4 */
|
||||
if (reg_val == 2 && val == sca3300_lp_freq[3])
|
||||
return sca3300_write_reg(data, SCA3300_REG_MODE, 3);
|
||||
if (reg_val == 3 && val == sca3300_lp_freq[2])
|
||||
return sca3300_write_reg(data, SCA3300_REG_MODE, 2);
|
||||
return -EINVAL;
|
||||
return sca3300_set_frequency(data, val);
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
@ -265,8 +439,8 @@ static int sca3300_read_raw(struct iio_dev *indio_dev,
|
|||
int *val, int *val2, long mask)
|
||||
{
|
||||
struct sca3300_data *data = iio_priv(indio_dev);
|
||||
int index;
|
||||
int ret;
|
||||
int reg_val;
|
||||
|
||||
switch (mask) {
|
||||
case IIO_CHAN_INFO_RAW:
|
||||
|
@ -275,17 +449,29 @@ static int sca3300_read_raw(struct iio_dev *indio_dev,
|
|||
return ret;
|
||||
return IIO_VAL_INT;
|
||||
case IIO_CHAN_INFO_SCALE:
|
||||
ret = sca3300_read_reg(data, SCA3300_REG_MODE, ®_val);
|
||||
ret = sca3300_get_op_mode(data, &index);
|
||||
if (ret)
|
||||
return ret;
|
||||
*val = 0;
|
||||
*val2 = sca3300_accel_scale[reg_val][1];
|
||||
return IIO_VAL_INT_PLUS_MICRO;
|
||||
switch (chan->type) {
|
||||
case IIO_INCLI:
|
||||
index = data->chip->incli_scale_map[index];
|
||||
*val = data->chip->incli_scale[index][0];
|
||||
*val2 = data->chip->incli_scale[index][1];
|
||||
return IIO_VAL_INT_PLUS_MICRO;
|
||||
case IIO_ACCEL:
|
||||
index = data->chip->accel_scale_map[index];
|
||||
*val = data->chip->accel_scale[index][0];
|
||||
*val2 = data->chip->accel_scale[index][1];
|
||||
return IIO_VAL_INT_PLUS_MICRO;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
|
||||
ret = sca3300_read_reg(data, SCA3300_REG_MODE, ®_val);
|
||||
ret = sca3300_get_op_mode(data, &index);
|
||||
if (ret)
|
||||
return ret;
|
||||
*val = sca3300_lp_freq[reg_val];
|
||||
index = data->chip->freq_map[index];
|
||||
*val = data->chip->freq_table[index];
|
||||
return IIO_VAL_INT;
|
||||
default:
|
||||
return -EINVAL;
|
||||
|
@ -329,6 +515,7 @@ static int sca3300_init(struct sca3300_data *sca_data,
|
|||
{
|
||||
int value = 0;
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
ret = sca3300_write_reg(sca_data, SCA3300_REG_MODE,
|
||||
SCA3300_MODE_SW_RESET);
|
||||
|
@ -337,20 +524,33 @@ static int sca3300_init(struct sca3300_data *sca_data,
|
|||
|
||||
/*
|
||||
* Wait 1ms after SW-reset command.
|
||||
* Wait 15ms for settling of signal paths.
|
||||
* Wait for the settling of signal paths,
|
||||
* 15ms for SCA3300 and 25ms for SCL3300,
|
||||
*/
|
||||
usleep_range(16e3, 50e3);
|
||||
usleep_range(26e3, 50e3);
|
||||
|
||||
ret = sca3300_read_reg(sca_data, SCA3300_REG_WHOAMI, &value);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (value != SCA3300_WHOAMI_ID) {
|
||||
dev_err(&sca_data->spi->dev,
|
||||
"device id not expected value, %d != %u\n",
|
||||
value, SCA3300_WHOAMI_ID);
|
||||
for (i = 0; i < ARRAY_SIZE(sca3300_chip_tbl); i++) {
|
||||
if (sca3300_chip_tbl[i].chip_id == value)
|
||||
break;
|
||||
}
|
||||
if (i == ARRAY_SIZE(sca3300_chip_tbl)) {
|
||||
dev_err(&sca_data->spi->dev, "unknown chip id %x\n", value);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
sca_data->chip = &sca3300_chip_tbl[i];
|
||||
|
||||
if (sca_data->chip->angle_supported) {
|
||||
ret = sca3300_write_reg(sca_data, SCL3300_REG_ANG_CTRL,
|
||||
SCL3300_ANG_ENABLE);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -382,15 +582,26 @@ static int sca3300_read_avail(struct iio_dev *indio_dev,
|
|||
const int **vals, int *type, int *length,
|
||||
long mask)
|
||||
{
|
||||
struct sca3300_data *data = iio_priv(indio_dev);
|
||||
switch (mask) {
|
||||
case IIO_CHAN_INFO_SCALE:
|
||||
*vals = (const int *)sca3300_accel_scale;
|
||||
*length = ARRAY_SIZE(sca3300_accel_scale) * 2 - 2;
|
||||
*type = IIO_VAL_INT_PLUS_MICRO;
|
||||
return IIO_AVAIL_LIST;
|
||||
switch (chan->type) {
|
||||
case IIO_INCLI:
|
||||
*vals = (const int *)data->chip->incli_scale;
|
||||
*length = data->chip->num_incli_scales;
|
||||
*type = IIO_VAL_INT_PLUS_MICRO;
|
||||
return IIO_AVAIL_LIST;
|
||||
case IIO_ACCEL:
|
||||
*vals = (const int *)data->chip->accel_scale;
|
||||
*length = data->chip->num_accel_scales;
|
||||
*type = IIO_VAL_INT_PLUS_MICRO;
|
||||
return IIO_AVAIL_LIST;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
|
||||
*vals = &sca3300_lp_freq[2];
|
||||
*length = 2;
|
||||
*vals = (const int *)data->chip->freq_table;
|
||||
*length = data->chip->num_freqs;
|
||||
*type = IIO_VAL_INT;
|
||||
return IIO_AVAIL_LIST;
|
||||
default:
|
||||
|
@ -422,11 +633,6 @@ static int sca3300_probe(struct spi_device *spi)
|
|||
crc8_populate_msb(sca3300_crc_table, SCA3300_CRC8_POLYNOMIAL);
|
||||
|
||||
indio_dev->info = &sca3300_info;
|
||||
indio_dev->name = SCA3300_ALIAS;
|
||||
indio_dev->modes = INDIO_DIRECT_MODE;
|
||||
indio_dev->channels = sca3300_channels;
|
||||
indio_dev->num_channels = ARRAY_SIZE(sca3300_channels);
|
||||
indio_dev->available_scan_masks = sca3300_scan_masks;
|
||||
|
||||
ret = sca3300_init(sca_data, indio_dev);
|
||||
if (ret) {
|
||||
|
@ -434,6 +640,12 @@ static int sca3300_probe(struct spi_device *spi)
|
|||
return ret;
|
||||
}
|
||||
|
||||
indio_dev->name = sca_data->chip->name;
|
||||
indio_dev->modes = INDIO_DIRECT_MODE;
|
||||
indio_dev->channels = sca_data->chip->channels;
|
||||
indio_dev->num_channels = sca_data->chip->num_channels;
|
||||
indio_dev->available_scan_masks = sca_data->chip->scan_masks;
|
||||
|
||||
ret = devm_iio_triggered_buffer_setup(&spi->dev, indio_dev,
|
||||
iio_pollfunc_store_time,
|
||||
sca3300_trigger_handler, NULL);
|
||||
|
@ -454,6 +666,7 @@ static int sca3300_probe(struct spi_device *spi)
|
|||
|
||||
static const struct of_device_id sca3300_dt_ids[] = {
|
||||
{ .compatible = "murata,sca3300"},
|
||||
{ .compatible = "murata,scl3300"},
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, sca3300_dt_ids);
|
||||
|
|
|
@ -608,7 +608,9 @@ static int stk8312_remove(struct i2c_client *client)
|
|||
if (data->dready_trig)
|
||||
iio_trigger_unregister(data->dready_trig);
|
||||
|
||||
return stk8312_set_mode(data, STK8312_MODE_STANDBY);
|
||||
stk8312_set_mode(data, STK8312_MODE_STANDBY);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int stk8312_suspend(struct device *dev)
|
||||
|
|
|
@ -501,7 +501,9 @@ static int stk8ba50_remove(struct i2c_client *client)
|
|||
if (data->dready_trig)
|
||||
iio_trigger_unregister(data->dready_trig);
|
||||
|
||||
return stk8ba50_set_power(data, STK8BA50_MODE_SUSPEND);
|
||||
stk8ba50_set_power(data, STK8BA50_MODE_SUSPEND);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int stk8ba50_suspend(struct device *dev)
|
||||
|
|
|
@ -417,7 +417,6 @@ config DLN2_ADC
|
|||
|
||||
config ENVELOPE_DETECTOR
|
||||
tristate "Envelope detector using a DAC and a comparator"
|
||||
depends on OF
|
||||
help
|
||||
Say yes here to build support for an envelope detector using a DAC
|
||||
and a comparator.
|
||||
|
@ -563,7 +562,7 @@ config LP8788_ADC
|
|||
config LPC18XX_ADC
|
||||
tristate "NXP LPC18xx ADC driver"
|
||||
depends on ARCH_LPC18XX || COMPILE_TEST
|
||||
depends on OF && HAS_IOMEM
|
||||
depends on HAS_IOMEM
|
||||
help
|
||||
Say yes here to build support for NXP LPC18XX ADC.
|
||||
|
||||
|
@ -823,6 +822,18 @@ config QCOM_PM8XXX_XOADC
|
|||
To compile this driver as a module, choose M here: the module
|
||||
will be called qcom-pm8xxx-xoadc.
|
||||
|
||||
config QCOM_SPMI_RRADC
|
||||
tristate "Qualcomm SPMI RRADC"
|
||||
depends on MFD_SPMI_PMIC
|
||||
help
|
||||
This is for the PMIC Round Robin ADC driver.
|
||||
|
||||
This driver exposes the battery ID resistor, battery thermal, PMIC die
|
||||
temperature, charger USB in and DC in voltage and current.
|
||||
|
||||
To compile this driver as a module, choose M here: the module will
|
||||
be called qcom-qpmi-rradc.
|
||||
|
||||
config QCOM_SPMI_IADC
|
||||
tristate "Qualcomm SPMI PMIC current ADC"
|
||||
depends on SPMI
|
||||
|
@ -941,7 +952,6 @@ config SPEAR_ADC
|
|||
|
||||
config SD_ADC_MODULATOR
|
||||
tristate "Generic sigma delta modulator"
|
||||
depends on OF
|
||||
select IIO_BUFFER
|
||||
select IIO_TRIGGERED_BUFFER
|
||||
help
|
||||
|
@ -1259,7 +1269,6 @@ config TWL6030_GPADC
|
|||
|
||||
config VF610_ADC
|
||||
tristate "Freescale vf610 ADC driver"
|
||||
depends on OF
|
||||
depends on HAS_IOMEM
|
||||
select IIO_BUFFER
|
||||
select IIO_TRIGGERED_BUFFER
|
||||
|
|
|
@ -78,6 +78,7 @@ obj-$(CONFIG_NPCM_ADC) += npcm_adc.o
|
|||
obj-$(CONFIG_PALMAS_GPADC) += palmas_gpadc.o
|
||||
obj-$(CONFIG_QCOM_SPMI_ADC5) += qcom-spmi-adc5.o
|
||||
obj-$(CONFIG_QCOM_SPMI_IADC) += qcom-spmi-iadc.o
|
||||
obj-$(CONFIG_QCOM_SPMI_RRADC) += qcom-spmi-rradc.o
|
||||
obj-$(CONFIG_QCOM_VADC_COMMON) += qcom-vadc-common.o
|
||||
obj-$(CONFIG_QCOM_SPMI_VADC) += qcom-spmi-vadc.o
|
||||
obj-$(CONFIG_QCOM_PM8XXX_XOADC) += qcom-pm8xxx-xoadc.o
|
||||
|
|
|
@ -37,7 +37,7 @@ struct ad7266_state {
|
|||
struct gpio_desc *gpios[3];
|
||||
|
||||
/*
|
||||
* DMA (thus cache coherency maintenance) requires the
|
||||
* DMA (thus cache coherency maintenance) may require the
|
||||
* transfer buffers to live in their own cache lines.
|
||||
* The buffer needs to be large enough to hold two samples (4 bytes) and
|
||||
* the naturally aligned timestamp (8 bytes).
|
||||
|
@ -45,7 +45,7 @@ struct ad7266_state {
|
|||
struct {
|
||||
__be16 sample[2];
|
||||
s64 timestamp;
|
||||
} data ____cacheline_aligned;
|
||||
} data __aligned(IIO_DMA_MINALIGN);
|
||||
};
|
||||
|
||||
static int ad7266_wakeup(struct ad7266_state *st)
|
||||
|
|
|
@ -183,7 +183,7 @@ struct ad7280_state {
|
|||
unsigned char cb_mask[AD7280A_MAX_CHAIN];
|
||||
struct mutex lock; /* protect sensor state */
|
||||
|
||||
__be32 tx ____cacheline_aligned;
|
||||
__be32 tx __aligned(IIO_DMA_MINALIGN);
|
||||
__be32 rx;
|
||||
};
|
||||
|
||||
|
|
|
@ -80,7 +80,7 @@ struct ad7292_state {
|
|||
struct regulator *reg;
|
||||
unsigned short vref_mv;
|
||||
|
||||
__be16 d16 ____cacheline_aligned;
|
||||
__be16 d16 __aligned(IIO_DMA_MINALIGN);
|
||||
u8 d8[2];
|
||||
};
|
||||
|
||||
|
|
|
@ -49,7 +49,7 @@ struct ad7298_state {
|
|||
* DMA (thus cache coherency maintenance) requires the
|
||||
* transfer buffers to live in their own cache lines.
|
||||
*/
|
||||
__be16 rx_buf[12] ____cacheline_aligned;
|
||||
__be16 rx_buf[12] __aligned(IIO_DMA_MINALIGN);
|
||||
__be16 tx_buf[2];
|
||||
};
|
||||
|
||||
|
|
|
@ -44,13 +44,12 @@ struct ad7476_state {
|
|||
struct spi_transfer xfer;
|
||||
struct spi_message msg;
|
||||
/*
|
||||
* DMA (thus cache coherency maintenance) requires the
|
||||
* DMA (thus cache coherency maintenance) may require the
|
||||
* transfer buffers to live in their own cache lines.
|
||||
* Make the buffer large enough for one 16 bit sample and one 64 bit
|
||||
* aligned 64 bit timestamp.
|
||||
*/
|
||||
unsigned char data[ALIGN(2, sizeof(s64)) + sizeof(s64)]
|
||||
____cacheline_aligned;
|
||||
unsigned char data[ALIGN(2, sizeof(s64)) + sizeof(s64)] __aligned(IIO_DMA_MINALIGN);
|
||||
};
|
||||
|
||||
enum ad7476_supported_device_ids {
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include <linux/interrupt.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/property.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/slab.h>
|
||||
|
|
|
@ -116,11 +116,11 @@ struct ad7606_state {
|
|||
struct completion completion;
|
||||
|
||||
/*
|
||||
* DMA (thus cache coherency maintenance) requires the
|
||||
* DMA (thus cache coherency maintenance) may require the
|
||||
* transfer buffers to live in their own cache lines.
|
||||
* 16 * 16-bit samples + 64-bit timestamp
|
||||
*/
|
||||
unsigned short data[20] ____cacheline_aligned;
|
||||
unsigned short data[20] __aligned(IIO_DMA_MINALIGN);
|
||||
__be16 d16[2];
|
||||
};
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
* Copyright 2011 Analog Devices Inc.
|
||||
*/
|
||||
|
||||
#include <linux/mod_devicetable.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/types.h>
|
||||
|
|
|
@ -45,13 +45,12 @@ struct ad7766 {
|
|||
struct spi_message msg;
|
||||
|
||||
/*
|
||||
* DMA (thus cache coherency maintenance) requires the
|
||||
* DMA (thus cache coherency maintenance) may require the
|
||||
* transfer buffers to live in their own cache lines.
|
||||
* Make the buffer large enough for one 24 bit sample and one 64 bit
|
||||
* aligned 64 bit timestamp.
|
||||
*/
|
||||
unsigned char data[ALIGN(3, sizeof(s64)) + sizeof(s64)]
|
||||
____cacheline_aligned;
|
||||
unsigned char data[ALIGN(3, sizeof(s64)) + sizeof(s64)] __aligned(IIO_DMA_MINALIGN);
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
|
@ -163,7 +163,7 @@ struct ad7768_state {
|
|||
struct gpio_desc *gpio_sync_in;
|
||||
const char *labels[ARRAY_SIZE(ad7768_channels)];
|
||||
/*
|
||||
* DMA (thus cache coherency maintenance) requires the
|
||||
* DMA (thus cache coherency maintenance) may require the
|
||||
* transfer buffers to live in their own cache lines.
|
||||
*/
|
||||
union {
|
||||
|
@ -173,7 +173,7 @@ struct ad7768_state {
|
|||
} scan;
|
||||
__be32 d32;
|
||||
u8 d8[2];
|
||||
} data ____cacheline_aligned;
|
||||
} data __aligned(IIO_DMA_MINALIGN);
|
||||
};
|
||||
|
||||
static int ad7768_spi_reg_read(struct ad7768_state *st, unsigned int addr,
|
||||
|
@ -620,7 +620,7 @@ static int ad7768_probe(struct spi_device *spi)
|
|||
indio_dev->num_channels = ARRAY_SIZE(ad7768_channels);
|
||||
indio_dev->name = spi_get_device_id(spi)->name;
|
||||
indio_dev->info = &ad7768_info;
|
||||
indio_dev->modes = INDIO_DIRECT_MODE | INDIO_BUFFER_TRIGGERED;
|
||||
indio_dev->modes = INDIO_DIRECT_MODE;
|
||||
|
||||
ret = ad7768_setup(st);
|
||||
if (ret < 0) {
|
||||
|
|
|
@ -66,13 +66,12 @@ struct ad7887_state {
|
|||
unsigned char tx_cmd_buf[4];
|
||||
|
||||
/*
|
||||
* DMA (thus cache coherency maintenance) requires the
|
||||
* DMA (thus cache coherency maintenance) may require the
|
||||
* transfer buffers to live in their own cache lines.
|
||||
* Buffer needs to be large enough to hold two 16 bit samples and a
|
||||
* 64 bit aligned 64 bit timestamp.
|
||||
*/
|
||||
unsigned char data[ALIGN(4, sizeof(s64)) + sizeof(s64)]
|
||||
____cacheline_aligned;
|
||||
unsigned char data[ALIGN(4, sizeof(s64)) + sizeof(s64)] __aligned(IIO_DMA_MINALIGN);
|
||||
};
|
||||
|
||||
enum ad7887_supported_device_ids {
|
||||
|
|
|
@ -57,12 +57,12 @@ struct ad7923_state {
|
|||
unsigned int settings;
|
||||
|
||||
/*
|
||||
* DMA (thus cache coherency maintenance) requires the
|
||||
* DMA (thus cache coherency maintenance) may require the
|
||||
* transfer buffers to live in their own cache lines.
|
||||
* Ensure rx_buf can be directly used in iio_push_to_buffers_with_timetamp
|
||||
* Length = 8 channels + 4 extra for 8 byte timestamp
|
||||
*/
|
||||
__be16 rx_buf[12] ____cacheline_aligned;
|
||||
__be16 rx_buf[12] __aligned(IIO_DMA_MINALIGN);
|
||||
__be16 tx_buf[4];
|
||||
};
|
||||
|
||||
|
|
|
@ -86,7 +86,7 @@ struct ad7949_adc_chip {
|
|||
u8 resolution;
|
||||
u16 cfg;
|
||||
unsigned int current_channel;
|
||||
u16 buffer ____cacheline_aligned;
|
||||
u16 buffer __aligned(IIO_DMA_MINALIGN);
|
||||
__be16 buf8b;
|
||||
};
|
||||
|
||||
|
|
|
@ -474,3 +474,4 @@ module_spi_driver(ad9467_driver);
|
|||
MODULE_AUTHOR("Michael Hennerich <michael.hennerich@analog.com>");
|
||||
MODULE_DESCRIPTION("Analog Devices AD9467 ADC driver");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
MODULE_IMPORT_NS(IIO_ADI_AXI);
|
||||
|
|
|
@ -84,9 +84,10 @@ void *adi_axi_adc_conv_priv(struct adi_axi_adc_conv *conv)
|
|||
{
|
||||
struct adi_axi_adc_client *cl = conv_to_client(conv);
|
||||
|
||||
return (char *)cl + ALIGN(sizeof(struct adi_axi_adc_client), IIO_ALIGN);
|
||||
return (char *)cl + ALIGN(sizeof(struct adi_axi_adc_client),
|
||||
IIO_DMA_MINALIGN);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(adi_axi_adc_conv_priv);
|
||||
EXPORT_SYMBOL_NS_GPL(adi_axi_adc_conv_priv, IIO_ADI_AXI);
|
||||
|
||||
static void adi_axi_adc_write(struct adi_axi_adc_state *st,
|
||||
unsigned int reg,
|
||||
|
@ -169,9 +170,9 @@ static struct adi_axi_adc_conv *adi_axi_adc_conv_register(struct device *dev,
|
|||
struct adi_axi_adc_client *cl;
|
||||
size_t alloc_size;
|
||||
|
||||
alloc_size = ALIGN(sizeof(struct adi_axi_adc_client), IIO_ALIGN);
|
||||
alloc_size = ALIGN(sizeof(struct adi_axi_adc_client), IIO_DMA_MINALIGN);
|
||||
if (sizeof_priv)
|
||||
alloc_size += ALIGN(sizeof_priv, IIO_ALIGN);
|
||||
alloc_size += ALIGN(sizeof_priv, IIO_DMA_MINALIGN);
|
||||
|
||||
cl = kzalloc(alloc_size, GFP_KERNEL);
|
||||
if (!cl)
|
||||
|
@ -224,7 +225,7 @@ struct adi_axi_adc_conv *devm_adi_axi_adc_conv_register(struct device *dev,
|
|||
|
||||
return conv;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(devm_adi_axi_adc_conv_register);
|
||||
EXPORT_SYMBOL_NS_GPL(devm_adi_axi_adc_conv_register, IIO_ADI_AXI);
|
||||
|
||||
static ssize_t in_voltage_scale_available_show(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
|
|
|
@ -1752,7 +1752,7 @@ static int at91_adc_set_watermark(struct iio_dev *indio_dev, unsigned int val)
|
|||
int ret;
|
||||
|
||||
if (val > AT91_HWFIFO_MAX_SIZE)
|
||||
return -EINVAL;
|
||||
val = AT91_HWFIFO_MAX_SIZE;
|
||||
|
||||
if (!st->selected_trig->hw_trig) {
|
||||
dev_dbg(&indio_dev->dev, "we need hw trigger for DMA\n");
|
||||
|
|
|
@ -15,7 +15,9 @@
|
|||
#include <linux/iio/machine.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/mod_devicetable.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/mfd/syscon.h>
|
||||
|
|
|
@ -49,7 +49,7 @@ struct hi8435_priv {
|
|||
|
||||
unsigned threshold_lo[2]; /* GND-Open and Supply-Open thresholds */
|
||||
unsigned threshold_hi[2]; /* GND-Open and Supply-Open thresholds */
|
||||
u8 reg_buffer[3] ____cacheline_aligned;
|
||||
u8 reg_buffer[3] __aligned(IIO_DMA_MINALIGN);
|
||||
};
|
||||
|
||||
static int hi8435_readb(struct hi8435_priv *priv, u8 reg, u8 *val)
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include <linux/interrupt.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/mod_devicetable.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include <linux/interrupt.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/mod_devicetable.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
|
|
|
@ -1038,12 +1038,18 @@ static int ina2xx_remove(struct i2c_client *client)
|
|||
{
|
||||
struct iio_dev *indio_dev = i2c_get_clientdata(client);
|
||||
struct ina2xx_chip_info *chip = iio_priv(indio_dev);
|
||||
int ret;
|
||||
|
||||
iio_device_unregister(indio_dev);
|
||||
|
||||
/* Powerdown */
|
||||
return regmap_update_bits(chip->regmap, INA2XX_CONFIG,
|
||||
INA2XX_MODE_MASK, 0);
|
||||
ret = regmap_update_bits(chip->regmap, INA2XX_CONFIG,
|
||||
INA2XX_MODE_MASK, 0);
|
||||
if (ret)
|
||||
dev_warn(&client->dev, "Failed to power down device (%pe)\n",
|
||||
ERR_PTR(ret));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct i2c_device_id ina2xx_id[] = {
|
||||
|
|
|
@ -17,7 +17,9 @@
|
|||
#include <linux/module.h>
|
||||
#include <linux/mod_devicetable.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/property.h>
|
||||
|
||||
#define JZ_ADC_REG_ENABLE 0x00
|
||||
#define JZ_ADC_REG_CFG 0x04
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include <linux/interrupt.h>
|
||||
#include <linux/mfd/intel_soc_pmic.h>
|
||||
#include <linux/mfd/intel_soc_pmic_mrfld.h>
|
||||
#include <linux/mod_devicetable.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
|
|
@ -17,10 +17,9 @@
|
|||
#include <linux/iio/driver.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/iopoll.h>
|
||||
#include <linux/mod_devicetable.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
|
||||
|
|
|
@ -24,10 +24,10 @@ struct ltc2496_driverdata {
|
|||
struct spi_device *spi;
|
||||
|
||||
/*
|
||||
* DMA (thus cache coherency maintenance) requires the
|
||||
* DMA (thus cache coherency maintenance) may require the
|
||||
* transfer buffers to live in their own cache lines.
|
||||
*/
|
||||
unsigned char rxbuf[3] ____cacheline_aligned;
|
||||
unsigned char rxbuf[3] __aligned(IIO_DMA_MINALIGN);
|
||||
unsigned char txbuf[3];
|
||||
};
|
||||
|
||||
|
|
|
@ -20,10 +20,10 @@ struct ltc2497_driverdata {
|
|||
struct ltc2497core_driverdata common_ddata;
|
||||
struct i2c_client *client;
|
||||
/*
|
||||
* DMA (thus cache coherency maintenance) requires the
|
||||
* DMA (thus cache coherency maintenance) may require the
|
||||
* transfer buffers to live in their own cache lines.
|
||||
*/
|
||||
__be32 buf ____cacheline_aligned;
|
||||
__be32 buf __aligned(IIO_DMA_MINALIGN);
|
||||
};
|
||||
|
||||
static int ltc2497_result_and_measure(struct ltc2497core_driverdata *ddata,
|
||||
|
|
|
@ -272,7 +272,7 @@ struct max1027_state {
|
|||
struct mutex lock;
|
||||
struct completion complete;
|
||||
|
||||
u8 reg ____cacheline_aligned;
|
||||
u8 reg __aligned(IIO_DMA_MINALIGN);
|
||||
};
|
||||
|
||||
static int max1027_wait_eoc(struct iio_dev *indio_dev)
|
||||
|
|
|
@ -33,10 +33,10 @@ struct max11100_state {
|
|||
struct spi_device *spi;
|
||||
|
||||
/*
|
||||
* DMA (thus cache coherency maintenance) requires the
|
||||
* DMA (thus cache coherency maintenance) may require the
|
||||
* transfer buffers to live in their own cache lines.
|
||||
*/
|
||||
u8 buffer[3] ____cacheline_aligned;
|
||||
u8 buffer[3] __aligned(IIO_DMA_MINALIGN);
|
||||
};
|
||||
|
||||
static const struct iio_chan_spec max11100_channels[] = {
|
||||
|
|
|
@ -42,7 +42,7 @@ struct max1118 {
|
|||
s64 ts __aligned(8);
|
||||
} scan;
|
||||
|
||||
u8 data ____cacheline_aligned;
|
||||
u8 data __aligned(IIO_DMA_MINALIGN);
|
||||
};
|
||||
|
||||
#define MAX1118_CHANNEL(ch) \
|
||||
|
|
|
@ -26,7 +26,7 @@ struct max1241 {
|
|||
struct regulator *vref;
|
||||
struct gpio_desc *shutdown;
|
||||
|
||||
__be16 data ____cacheline_aligned;
|
||||
__be16 data __aligned(IIO_DMA_MINALIGN);
|
||||
};
|
||||
|
||||
static const struct iio_chan_spec max1241_channels[] = {
|
||||
|
|
|
@ -92,7 +92,7 @@ struct mcp320x {
|
|||
struct mutex lock;
|
||||
const struct mcp320x_chip_info *chip_info;
|
||||
|
||||
u8 tx_buf ____cacheline_aligned;
|
||||
u8 tx_buf __aligned(IIO_DMA_MINALIGN);
|
||||
u8 rx_buf[4];
|
||||
};
|
||||
|
||||
|
|
|
@ -322,22 +322,17 @@ static int meson_sar_adc_calib_val(struct iio_dev *indio_dev, int val)
|
|||
static int meson_sar_adc_wait_busy_clear(struct iio_dev *indio_dev)
|
||||
{
|
||||
struct meson_sar_adc_priv *priv = iio_priv(indio_dev);
|
||||
int regval, timeout = 10000;
|
||||
int val;
|
||||
|
||||
/*
|
||||
* NOTE: we need a small delay before reading the status, otherwise
|
||||
* the sample engine may not have started internally (which would
|
||||
* seem to us that sampling is already finished).
|
||||
*/
|
||||
do {
|
||||
udelay(1);
|
||||
regmap_read(priv->regmap, MESON_SAR_ADC_REG0, ®val);
|
||||
} while (FIELD_GET(MESON_SAR_ADC_REG0_BUSY_MASK, regval) && timeout--);
|
||||
|
||||
if (timeout < 0)
|
||||
return -ETIMEDOUT;
|
||||
|
||||
return 0;
|
||||
udelay(1);
|
||||
return regmap_read_poll_timeout_atomic(priv->regmap, MESON_SAR_ADC_REG0, val,
|
||||
!FIELD_GET(MESON_SAR_ADC_REG0_BUSY_MASK, val),
|
||||
1, 10000);
|
||||
}
|
||||
|
||||
static int meson_sar_adc_read_raw_sample(struct iio_dev *indio_dev,
|
||||
|
@ -345,6 +340,7 @@ static int meson_sar_adc_read_raw_sample(struct iio_dev *indio_dev,
|
|||
int *val)
|
||||
{
|
||||
struct meson_sar_adc_priv *priv = iio_priv(indio_dev);
|
||||
struct device *dev = indio_dev->dev.parent;
|
||||
int regval, fifo_chan, fifo_val, count;
|
||||
|
||||
if (!wait_for_completion_timeout(&priv->done,
|
||||
|
@ -353,16 +349,14 @@ static int meson_sar_adc_read_raw_sample(struct iio_dev *indio_dev,
|
|||
|
||||
count = meson_sar_adc_get_fifo_count(indio_dev);
|
||||
if (count != 1) {
|
||||
dev_err(&indio_dev->dev,
|
||||
"ADC FIFO has %d element(s) instead of one\n", count);
|
||||
dev_err(dev, "ADC FIFO has %d element(s) instead of one\n", count);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
regmap_read(priv->regmap, MESON_SAR_ADC_FIFO_RD, ®val);
|
||||
fifo_chan = FIELD_GET(MESON_SAR_ADC_FIFO_RD_CHAN_ID_MASK, regval);
|
||||
if (fifo_chan != chan->address) {
|
||||
dev_err(&indio_dev->dev,
|
||||
"ADC FIFO entry belongs to channel %d instead of %lu\n",
|
||||
dev_err(dev, "ADC FIFO entry belongs to channel %d instead of %lu\n",
|
||||
fifo_chan, chan->address);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
@ -490,7 +484,7 @@ static void meson_sar_adc_stop_sample_engine(struct iio_dev *indio_dev)
|
|||
static int meson_sar_adc_lock(struct iio_dev *indio_dev)
|
||||
{
|
||||
struct meson_sar_adc_priv *priv = iio_priv(indio_dev);
|
||||
int val, timeout = 10000;
|
||||
int val, ret;
|
||||
|
||||
mutex_lock(&indio_dev->mlock);
|
||||
|
||||
|
@ -500,18 +494,18 @@ static int meson_sar_adc_lock(struct iio_dev *indio_dev)
|
|||
MESON_SAR_ADC_DELAY_KERNEL_BUSY,
|
||||
MESON_SAR_ADC_DELAY_KERNEL_BUSY);
|
||||
|
||||
udelay(1);
|
||||
|
||||
/*
|
||||
* wait until BL30 releases it's lock (so we can use the SAR
|
||||
* ADC)
|
||||
*/
|
||||
do {
|
||||
udelay(1);
|
||||
regmap_read(priv->regmap, MESON_SAR_ADC_DELAY, &val);
|
||||
} while (val & MESON_SAR_ADC_DELAY_BL30_BUSY && timeout--);
|
||||
|
||||
if (timeout < 0) {
|
||||
ret = regmap_read_poll_timeout_atomic(priv->regmap, MESON_SAR_ADC_DELAY, val,
|
||||
!(val & MESON_SAR_ADC_DELAY_BL30_BUSY),
|
||||
1, 10000);
|
||||
if (ret) {
|
||||
mutex_unlock(&indio_dev->mlock);
|
||||
return -ETIMEDOUT;
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -550,6 +544,7 @@ static int meson_sar_adc_get_sample(struct iio_dev *indio_dev,
|
|||
int *val)
|
||||
{
|
||||
struct meson_sar_adc_priv *priv = iio_priv(indio_dev);
|
||||
struct device *dev = indio_dev->dev.parent;
|
||||
int ret;
|
||||
|
||||
if (chan->type == IIO_TEMP && !priv->temperature_sensor_calibrated)
|
||||
|
@ -573,8 +568,7 @@ static int meson_sar_adc_get_sample(struct iio_dev *indio_dev,
|
|||
meson_sar_adc_unlock(indio_dev);
|
||||
|
||||
if (ret) {
|
||||
dev_warn(indio_dev->dev.parent,
|
||||
"failed to read sample for channel %lu: %d\n",
|
||||
dev_warn(dev, "failed to read sample for channel %lu: %d\n",
|
||||
chan->address, ret);
|
||||
return ret;
|
||||
}
|
||||
|
@ -587,6 +581,7 @@ static int meson_sar_adc_iio_info_read_raw(struct iio_dev *indio_dev,
|
|||
int *val, int *val2, long mask)
|
||||
{
|
||||
struct meson_sar_adc_priv *priv = iio_priv(indio_dev);
|
||||
struct device *dev = indio_dev->dev.parent;
|
||||
int ret;
|
||||
|
||||
switch (mask) {
|
||||
|
@ -603,9 +598,7 @@ static int meson_sar_adc_iio_info_read_raw(struct iio_dev *indio_dev,
|
|||
if (chan->type == IIO_VOLTAGE) {
|
||||
ret = regulator_get_voltage(priv->vref);
|
||||
if (ret < 0) {
|
||||
dev_err(indio_dev->dev.parent,
|
||||
"failed to get vref voltage: %d\n",
|
||||
ret);
|
||||
dev_err(dev, "failed to get vref voltage: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -650,11 +643,11 @@ static int meson_sar_adc_clk_init(struct iio_dev *indio_dev,
|
|||
void __iomem *base)
|
||||
{
|
||||
struct meson_sar_adc_priv *priv = iio_priv(indio_dev);
|
||||
struct device *dev = indio_dev->dev.parent;
|
||||
struct clk_init_data init;
|
||||
const char *clk_parents[1];
|
||||
|
||||
init.name = devm_kasprintf(&indio_dev->dev, GFP_KERNEL, "%s#adc_div",
|
||||
dev_name(indio_dev->dev.parent));
|
||||
init.name = devm_kasprintf(dev, GFP_KERNEL, "%s#adc_div", dev_name(dev));
|
||||
if (!init.name)
|
||||
return -ENOMEM;
|
||||
|
||||
|
@ -670,13 +663,11 @@ static int meson_sar_adc_clk_init(struct iio_dev *indio_dev,
|
|||
priv->clk_div.hw.init = &init;
|
||||
priv->clk_div.flags = 0;
|
||||
|
||||
priv->adc_div_clk = devm_clk_register(&indio_dev->dev,
|
||||
&priv->clk_div.hw);
|
||||
priv->adc_div_clk = devm_clk_register(dev, &priv->clk_div.hw);
|
||||
if (WARN_ON(IS_ERR(priv->adc_div_clk)))
|
||||
return PTR_ERR(priv->adc_div_clk);
|
||||
|
||||
init.name = devm_kasprintf(&indio_dev->dev, GFP_KERNEL, "%s#adc_en",
|
||||
dev_name(indio_dev->dev.parent));
|
||||
init.name = devm_kasprintf(dev, GFP_KERNEL, "%s#adc_en", dev_name(dev));
|
||||
if (!init.name)
|
||||
return -ENOMEM;
|
||||
|
||||
|
@ -690,7 +681,7 @@ static int meson_sar_adc_clk_init(struct iio_dev *indio_dev,
|
|||
priv->clk_gate.bit_idx = __ffs(MESON_SAR_ADC_REG3_CLK_EN);
|
||||
priv->clk_gate.hw.init = &init;
|
||||
|
||||
priv->adc_clk = devm_clk_register(&indio_dev->dev, &priv->clk_gate.hw);
|
||||
priv->adc_clk = devm_clk_register(dev, &priv->clk_gate.hw);
|
||||
if (WARN_ON(IS_ERR(priv->adc_clk)))
|
||||
return PTR_ERR(priv->adc_clk);
|
||||
|
||||
|
@ -701,12 +692,12 @@ static int meson_sar_adc_temp_sensor_init(struct iio_dev *indio_dev)
|
|||
{
|
||||
struct meson_sar_adc_priv *priv = iio_priv(indio_dev);
|
||||
u8 *buf, trimming_bits, trimming_mask, upper_adc_val;
|
||||
struct device *dev = indio_dev->dev.parent;
|
||||
struct nvmem_cell *temperature_calib;
|
||||
size_t read_len;
|
||||
int ret;
|
||||
|
||||
temperature_calib = devm_nvmem_cell_get(indio_dev->dev.parent,
|
||||
"temperature_calib");
|
||||
temperature_calib = devm_nvmem_cell_get(dev, "temperature_calib");
|
||||
if (IS_ERR(temperature_calib)) {
|
||||
ret = PTR_ERR(temperature_calib);
|
||||
|
||||
|
@ -717,30 +708,21 @@ static int meson_sar_adc_temp_sensor_init(struct iio_dev *indio_dev)
|
|||
if (ret == -ENODEV)
|
||||
return 0;
|
||||
|
||||
return dev_err_probe(indio_dev->dev.parent, ret,
|
||||
"failed to get temperature_calib cell\n");
|
||||
return dev_err_probe(dev, ret, "failed to get temperature_calib cell\n");
|
||||
}
|
||||
|
||||
priv->tsc_regmap =
|
||||
syscon_regmap_lookup_by_phandle(indio_dev->dev.parent->of_node,
|
||||
"amlogic,hhi-sysctrl");
|
||||
if (IS_ERR(priv->tsc_regmap)) {
|
||||
dev_err(indio_dev->dev.parent,
|
||||
"failed to get amlogic,hhi-sysctrl regmap\n");
|
||||
return PTR_ERR(priv->tsc_regmap);
|
||||
}
|
||||
priv->tsc_regmap = syscon_regmap_lookup_by_phandle(dev->of_node, "amlogic,hhi-sysctrl");
|
||||
if (IS_ERR(priv->tsc_regmap))
|
||||
return dev_err_probe(dev, PTR_ERR(priv->tsc_regmap),
|
||||
"failed to get amlogic,hhi-sysctrl regmap\n");
|
||||
|
||||
read_len = MESON_SAR_ADC_EFUSE_BYTES;
|
||||
buf = nvmem_cell_read(temperature_calib, &read_len);
|
||||
if (IS_ERR(buf)) {
|
||||
dev_err(indio_dev->dev.parent,
|
||||
"failed to read temperature_calib cell\n");
|
||||
return PTR_ERR(buf);
|
||||
} else if (read_len != MESON_SAR_ADC_EFUSE_BYTES) {
|
||||
if (IS_ERR(buf))
|
||||
return dev_err_probe(dev, PTR_ERR(buf), "failed to read temperature_calib cell\n");
|
||||
if (read_len != MESON_SAR_ADC_EFUSE_BYTES) {
|
||||
kfree(buf);
|
||||
dev_err(indio_dev->dev.parent,
|
||||
"invalid read size of temperature_calib cell\n");
|
||||
return -EINVAL;
|
||||
return dev_err_probe(dev, -EINVAL, "invalid read size of temperature_calib cell\n");
|
||||
}
|
||||
|
||||
trimming_bits = priv->param->temperature_trimming_bits;
|
||||
|
@ -765,6 +747,7 @@ static int meson_sar_adc_temp_sensor_init(struct iio_dev *indio_dev)
|
|||
static int meson_sar_adc_init(struct iio_dev *indio_dev)
|
||||
{
|
||||
struct meson_sar_adc_priv *priv = iio_priv(indio_dev);
|
||||
struct device *dev = indio_dev->dev.parent;
|
||||
int regval, i, ret;
|
||||
|
||||
/*
|
||||
|
@ -888,18 +871,12 @@ static int meson_sar_adc_init(struct iio_dev *indio_dev)
|
|||
}
|
||||
|
||||
ret = clk_set_parent(priv->adc_sel_clk, priv->clkin);
|
||||
if (ret) {
|
||||
dev_err(indio_dev->dev.parent,
|
||||
"failed to set adc parent to clkin\n");
|
||||
return ret;
|
||||
}
|
||||
if (ret)
|
||||
return dev_err_probe(dev, ret, "failed to set adc parent to clkin\n");
|
||||
|
||||
ret = clk_set_rate(priv->adc_clk, priv->param->clock_rate);
|
||||
if (ret) {
|
||||
dev_err(indio_dev->dev.parent,
|
||||
"failed to set adc clock rate\n");
|
||||
return ret;
|
||||
}
|
||||
if (ret)
|
||||
return dev_err_probe(dev, ret, "failed to set adc clock rate\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -922,6 +899,7 @@ static void meson_sar_adc_set_bandgap(struct iio_dev *indio_dev, bool on_off)
|
|||
static int meson_sar_adc_hw_enable(struct iio_dev *indio_dev)
|
||||
{
|
||||
struct meson_sar_adc_priv *priv = iio_priv(indio_dev);
|
||||
struct device *dev = indio_dev->dev.parent;
|
||||
int ret;
|
||||
u32 regval;
|
||||
|
||||
|
@ -931,14 +909,13 @@ static int meson_sar_adc_hw_enable(struct iio_dev *indio_dev)
|
|||
|
||||
ret = regulator_enable(priv->vref);
|
||||
if (ret < 0) {
|
||||
dev_err(indio_dev->dev.parent,
|
||||
"failed to enable vref regulator\n");
|
||||
dev_err(dev, "failed to enable vref regulator\n");
|
||||
goto err_vref;
|
||||
}
|
||||
|
||||
ret = clk_prepare_enable(priv->core_clk);
|
||||
if (ret) {
|
||||
dev_err(indio_dev->dev.parent, "failed to enable core clk\n");
|
||||
dev_err(dev, "failed to enable core clk\n");
|
||||
goto err_core_clk;
|
||||
}
|
||||
|
||||
|
@ -956,7 +933,7 @@ static int meson_sar_adc_hw_enable(struct iio_dev *indio_dev)
|
|||
|
||||
ret = clk_prepare_enable(priv->adc_clk);
|
||||
if (ret) {
|
||||
dev_err(indio_dev->dev.parent, "failed to enable adc clk\n");
|
||||
dev_err(dev, "failed to enable adc clk\n");
|
||||
goto err_adc_clk;
|
||||
}
|
||||
|
||||
|
@ -1186,24 +1163,21 @@ static int meson_sar_adc_probe(struct platform_device *pdev)
|
|||
{
|
||||
const struct meson_sar_adc_data *match_data;
|
||||
struct meson_sar_adc_priv *priv;
|
||||
struct device *dev = &pdev->dev;
|
||||
struct iio_dev *indio_dev;
|
||||
void __iomem *base;
|
||||
int irq, ret;
|
||||
|
||||
indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*priv));
|
||||
if (!indio_dev) {
|
||||
dev_err(&pdev->dev, "failed allocating iio device\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
indio_dev = devm_iio_device_alloc(dev, sizeof(*priv));
|
||||
if (!indio_dev)
|
||||
return dev_err_probe(dev, -ENOMEM, "failed allocating iio device\n");
|
||||
|
||||
priv = iio_priv(indio_dev);
|
||||
init_completion(&priv->done);
|
||||
|
||||
match_data = of_device_get_match_data(&pdev->dev);
|
||||
if (!match_data) {
|
||||
dev_err(&pdev->dev, "failed to get match data\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
match_data = of_device_get_match_data(dev);
|
||||
if (!match_data)
|
||||
return dev_err_probe(dev, -ENODEV, "failed to get match data\n");
|
||||
|
||||
priv->param = match_data->param;
|
||||
|
||||
|
@ -1215,47 +1189,33 @@ static int meson_sar_adc_probe(struct platform_device *pdev)
|
|||
if (IS_ERR(base))
|
||||
return PTR_ERR(base);
|
||||
|
||||
priv->regmap = devm_regmap_init_mmio(&pdev->dev, base,
|
||||
priv->param->regmap_config);
|
||||
priv->regmap = devm_regmap_init_mmio(dev, base, priv->param->regmap_config);
|
||||
if (IS_ERR(priv->regmap))
|
||||
return PTR_ERR(priv->regmap);
|
||||
|
||||
irq = irq_of_parse_and_map(pdev->dev.of_node, 0);
|
||||
irq = irq_of_parse_and_map(dev->of_node, 0);
|
||||
if (!irq)
|
||||
return -EINVAL;
|
||||
|
||||
ret = devm_request_irq(&pdev->dev, irq, meson_sar_adc_irq, IRQF_SHARED,
|
||||
dev_name(&pdev->dev), indio_dev);
|
||||
ret = devm_request_irq(dev, irq, meson_sar_adc_irq, IRQF_SHARED, dev_name(dev), indio_dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
priv->clkin = devm_clk_get(&pdev->dev, "clkin");
|
||||
priv->clkin = devm_clk_get(dev, "clkin");
|
||||
if (IS_ERR(priv->clkin))
|
||||
return dev_err_probe(&pdev->dev, PTR_ERR(priv->clkin),
|
||||
"failed to get clkin\n");
|
||||
return dev_err_probe(dev, PTR_ERR(priv->clkin), "failed to get clkin\n");
|
||||
|
||||
priv->core_clk = devm_clk_get(&pdev->dev, "core");
|
||||
priv->core_clk = devm_clk_get(dev, "core");
|
||||
if (IS_ERR(priv->core_clk))
|
||||
return dev_err_probe(&pdev->dev, PTR_ERR(priv->core_clk),
|
||||
"failed to get core clk\n");
|
||||
return dev_err_probe(dev, PTR_ERR(priv->core_clk), "failed to get core clk\n");
|
||||
|
||||
priv->adc_clk = devm_clk_get(&pdev->dev, "adc_clk");
|
||||
if (IS_ERR(priv->adc_clk)) {
|
||||
if (PTR_ERR(priv->adc_clk) == -ENOENT)
|
||||
priv->adc_clk = NULL;
|
||||
else
|
||||
return dev_err_probe(&pdev->dev, PTR_ERR(priv->adc_clk),
|
||||
"failed to get adc clk\n");
|
||||
}
|
||||
priv->adc_clk = devm_clk_get_optional(dev, "adc_clk");
|
||||
if (IS_ERR(priv->adc_clk))
|
||||
return dev_err_probe(dev, PTR_ERR(priv->adc_clk), "failed to get adc clk\n");
|
||||
|
||||
priv->adc_sel_clk = devm_clk_get(&pdev->dev, "adc_sel");
|
||||
if (IS_ERR(priv->adc_sel_clk)) {
|
||||
if (PTR_ERR(priv->adc_sel_clk) == -ENOENT)
|
||||
priv->adc_sel_clk = NULL;
|
||||
else
|
||||
return dev_err_probe(&pdev->dev, PTR_ERR(priv->adc_sel_clk),
|
||||
"failed to get adc_sel clk\n");
|
||||
}
|
||||
priv->adc_sel_clk = devm_clk_get_optional(dev, "adc_sel");
|
||||
if (IS_ERR(priv->adc_sel_clk))
|
||||
return dev_err_probe(dev, PTR_ERR(priv->adc_sel_clk), "failed to get adc_sel clk\n");
|
||||
|
||||
/* on pre-GXBB SoCs the SAR ADC itself provides the ADC clock: */
|
||||
if (!priv->adc_clk) {
|
||||
|
@ -1264,10 +1224,9 @@ static int meson_sar_adc_probe(struct platform_device *pdev)
|
|||
return ret;
|
||||
}
|
||||
|
||||
priv->vref = devm_regulator_get(&pdev->dev, "vref");
|
||||
priv->vref = devm_regulator_get(dev, "vref");
|
||||
if (IS_ERR(priv->vref))
|
||||
return dev_err_probe(&pdev->dev, PTR_ERR(priv->vref),
|
||||
"failed to get vref regulator\n");
|
||||
return dev_err_probe(dev, PTR_ERR(priv->vref), "failed to get vref regulator\n");
|
||||
|
||||
priv->calibscale = MILLION;
|
||||
|
||||
|
@ -1297,7 +1256,7 @@ static int meson_sar_adc_probe(struct platform_device *pdev)
|
|||
|
||||
ret = meson_sar_adc_calib(indio_dev);
|
||||
if (ret)
|
||||
dev_warn(&pdev->dev, "calibration failed\n");
|
||||
dev_warn(dev, "calibration failed\n");
|
||||
|
||||
platform_set_drvdata(pdev, indio_dev);
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include <linux/iio/iio.h>
|
||||
#include <linux/iio/machine.h>
|
||||
#include <linux/mfd/mp2629.h>
|
||||
#include <linux/mod_devicetable.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include <linux/irq.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/ktime.h>
|
||||
#include <linux/mod_devicetable.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
|
|
@ -8,10 +8,11 @@
|
|||
#include <linux/delay.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/mod_devicetable.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/property.h>
|
||||
#include <linux/wait.h>
|
||||
#include <linux/log2.h>
|
||||
#include <linux/of.h>
|
||||
|
||||
#include <linux/iio/iio.h>
|
||||
#include <linux/iio/sysfs.h>
|
||||
|
@ -407,21 +408,14 @@ static const struct iio_info nau7802_info = {
|
|||
.attrs = &nau7802_attribute_group,
|
||||
};
|
||||
|
||||
static int nau7802_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
static int nau7802_probe(struct i2c_client *client)
|
||||
{
|
||||
struct iio_dev *indio_dev;
|
||||
struct nau7802_state *st;
|
||||
struct device_node *np = client->dev.of_node;
|
||||
int i, ret;
|
||||
u8 data;
|
||||
u32 tmp = 0;
|
||||
|
||||
if (!client->dev.of_node) {
|
||||
dev_err(&client->dev, "No device tree node available.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*st));
|
||||
if (indio_dev == NULL)
|
||||
return -ENOMEM;
|
||||
|
@ -457,7 +451,7 @@ static int nau7802_probe(struct i2c_client *client,
|
|||
if (!(ret & NAU7802_PUCTRL_PUR_BIT))
|
||||
return ret;
|
||||
|
||||
of_property_read_u32(np, "nuvoton,vldo", &tmp);
|
||||
device_property_read_u32(&client->dev, "nuvoton,vldo", &tmp);
|
||||
st->vref_mv = tmp;
|
||||
|
||||
data = NAU7802_PUCTRL_PUD_BIT | NAU7802_PUCTRL_PUA_BIT |
|
||||
|
@ -550,7 +544,7 @@ static const struct of_device_id nau7802_dt_ids[] = {
|
|||
MODULE_DEVICE_TABLE(of, nau7802_dt_ids);
|
||||
|
||||
static struct i2c_driver nau7802_driver = {
|
||||
.probe = nau7802_probe,
|
||||
.probe_new = nau7802_probe,
|
||||
.id_table = nau7802_i2c_id,
|
||||
.driver = {
|
||||
.name = "nau7802",
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include <linux/iio/iio.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/mod_devicetable.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/regmap.h>
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -18,6 +18,7 @@
|
|||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/property.h>
|
||||
#include <linux/reset.h>
|
||||
|
||||
#define DRIVER_NAME "rzg2l-adc"
|
||||
|
@ -260,9 +261,6 @@ static int rzg2l_adc_read_label(struct iio_dev *iio_dev,
|
|||
const struct iio_chan_spec *chan,
|
||||
char *label)
|
||||
{
|
||||
if (chan->channel >= RZG2L_ADC_MAX_CHANNELS)
|
||||
return -EINVAL;
|
||||
|
||||
return sysfs_emit(label, "%s\n", rzg2l_adc_channel_name[chan->channel]);
|
||||
}
|
||||
|
||||
|
|
|
@ -579,15 +579,14 @@ unlock_adc:
|
|||
return ret;
|
||||
}
|
||||
|
||||
static void sc27xx_adc_volt_ratio(struct sc27xx_adc_data *data,
|
||||
int channel, int scale,
|
||||
u32 *div_numerator, u32 *div_denominator)
|
||||
static void sc27xx_adc_volt_ratio(struct sc27xx_adc_data *data, int channel, int scale,
|
||||
struct u32_fract *fract)
|
||||
{
|
||||
u32 ratio;
|
||||
|
||||
ratio = data->var_data->get_ratio(channel, scale);
|
||||
*div_numerator = ratio >> SC27XX_RATIO_NUMERATOR_OFFSET;
|
||||
*div_denominator = ratio & SC27XX_RATIO_DENOMINATOR_MASK;
|
||||
fract->numerator = ratio >> SC27XX_RATIO_NUMERATOR_OFFSET;
|
||||
fract->denominator = ratio & SC27XX_RATIO_DENOMINATOR_MASK;
|
||||
}
|
||||
|
||||
static int adc_to_volt(struct sc27xx_adc_linear_graph *graph,
|
||||
|
@ -615,7 +614,7 @@ static int sc27xx_adc_to_volt(struct sc27xx_adc_linear_graph *graph,
|
|||
static int sc27xx_adc_convert_volt(struct sc27xx_adc_data *data, int channel,
|
||||
int scale, int raw_adc)
|
||||
{
|
||||
u32 numerator, denominator;
|
||||
struct u32_fract fract;
|
||||
u32 volt;
|
||||
|
||||
/*
|
||||
|
@ -637,9 +636,9 @@ static int sc27xx_adc_convert_volt(struct sc27xx_adc_data *data, int channel,
|
|||
break;
|
||||
}
|
||||
|
||||
sc27xx_adc_volt_ratio(data, channel, scale, &numerator, &denominator);
|
||||
sc27xx_adc_volt_ratio(data, channel, scale, &fract);
|
||||
|
||||
return DIV_ROUND_CLOSEST(volt * denominator, numerator);
|
||||
return DIV_ROUND_CLOSEST(volt * fract.denominator, fract.numerator);
|
||||
}
|
||||
|
||||
static int sc27xx_adc_read_processed(struct sc27xx_adc_data *data,
|
||||
|
|
|
@ -358,7 +358,7 @@ static void stm32_adc_irq_handler(struct irq_desc *desc)
|
|||
if ((status & priv->cfg->regs->eoc_msk[i] &&
|
||||
stm32_adc_eoc_enabled(priv, i)) ||
|
||||
(status & priv->cfg->regs->ovr_msk[i]))
|
||||
generic_handle_irq(irq_find_mapping(priv->domain, i));
|
||||
generic_handle_domain_irq(priv->domain, i);
|
||||
}
|
||||
|
||||
chained_irq_exit(chip, desc);
|
||||
|
|
|
@ -876,6 +876,9 @@ static void stm32h7_adc_disable(struct iio_dev *indio_dev)
|
|||
int ret;
|
||||
u32 val;
|
||||
|
||||
if (!(stm32_adc_readl(adc, STM32H7_ADC_CR) & STM32H7_ADEN))
|
||||
return;
|
||||
|
||||
/* Disable ADC and wait until it's effectively disabled */
|
||||
stm32_adc_set_bits(adc, STM32H7_ADC_CR, STM32H7_ADDIS);
|
||||
ret = stm32_adc_readl_poll_timeout(STM32H7_ADC_CR, val,
|
||||
|
@ -1016,6 +1019,9 @@ static int stm32h7_adc_selfcalib(struct iio_dev *indio_dev)
|
|||
if (adc->cal.calibrated)
|
||||
return true;
|
||||
|
||||
/* ADC must be disabled for calibration */
|
||||
stm32h7_adc_disable(indio_dev);
|
||||
|
||||
/*
|
||||
* Select calibration mode:
|
||||
* - Offset calibration for single ended inputs
|
||||
|
|
|
@ -51,7 +51,7 @@ MODULE_PARM_DESC(base, "Apex Embedded Systems STX104 base addresses");
|
|||
*/
|
||||
struct stx104_iio {
|
||||
unsigned int chan_out_states[STX104_NUM_OUT_CHAN];
|
||||
unsigned int base;
|
||||
void __iomem *base;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -64,7 +64,7 @@ struct stx104_iio {
|
|||
struct stx104_gpio {
|
||||
struct gpio_chip chip;
|
||||
spinlock_t lock;
|
||||
unsigned int base;
|
||||
void __iomem *base;
|
||||
unsigned int out_state;
|
||||
};
|
||||
|
||||
|
@ -79,7 +79,7 @@ static int stx104_read_raw(struct iio_dev *indio_dev,
|
|||
switch (mask) {
|
||||
case IIO_CHAN_INFO_HARDWAREGAIN:
|
||||
/* get gain configuration */
|
||||
adc_config = inb(priv->base + 11);
|
||||
adc_config = ioread8(priv->base + 11);
|
||||
gain = adc_config & 0x3;
|
||||
|
||||
*val = 1 << gain;
|
||||
|
@ -91,24 +91,24 @@ static int stx104_read_raw(struct iio_dev *indio_dev,
|
|||
}
|
||||
|
||||
/* select ADC channel */
|
||||
outb(chan->channel | (chan->channel << 4), priv->base + 2);
|
||||
iowrite8(chan->channel | (chan->channel << 4), priv->base + 2);
|
||||
|
||||
/* trigger ADC sample capture and wait for completion */
|
||||
outb(0, priv->base);
|
||||
while (inb(priv->base + 8) & BIT(7));
|
||||
iowrite8(0, priv->base);
|
||||
while (ioread8(priv->base + 8) & BIT(7));
|
||||
|
||||
*val = inw(priv->base);
|
||||
*val = ioread16(priv->base);
|
||||
return IIO_VAL_INT;
|
||||
case IIO_CHAN_INFO_OFFSET:
|
||||
/* get ADC bipolar/unipolar configuration */
|
||||
adc_config = inb(priv->base + 11);
|
||||
adc_config = ioread8(priv->base + 11);
|
||||
adbu = !(adc_config & BIT(2));
|
||||
|
||||
*val = -32768 * adbu;
|
||||
return IIO_VAL_INT;
|
||||
case IIO_CHAN_INFO_SCALE:
|
||||
/* get ADC bipolar/unipolar and gain configuration */
|
||||
adc_config = inb(priv->base + 11);
|
||||
adc_config = ioread8(priv->base + 11);
|
||||
adbu = !(adc_config & BIT(2));
|
||||
gain = adc_config & 0x3;
|
||||
|
||||
|
@ -130,16 +130,16 @@ static int stx104_write_raw(struct iio_dev *indio_dev,
|
|||
/* Only four gain states (x1, x2, x4, x8) */
|
||||
switch (val) {
|
||||
case 1:
|
||||
outb(0, priv->base + 11);
|
||||
iowrite8(0, priv->base + 11);
|
||||
break;
|
||||
case 2:
|
||||
outb(1, priv->base + 11);
|
||||
iowrite8(1, priv->base + 11);
|
||||
break;
|
||||
case 4:
|
||||
outb(2, priv->base + 11);
|
||||
iowrite8(2, priv->base + 11);
|
||||
break;
|
||||
case 8:
|
||||
outb(3, priv->base + 11);
|
||||
iowrite8(3, priv->base + 11);
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
|
@ -153,7 +153,7 @@ static int stx104_write_raw(struct iio_dev *indio_dev,
|
|||
return -EINVAL;
|
||||
|
||||
priv->chan_out_states[chan->channel] = val;
|
||||
outw(val, priv->base + 4 + 2 * chan->channel);
|
||||
iowrite16(val, priv->base + 4 + 2 * chan->channel);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -222,7 +222,7 @@ static int stx104_gpio_get(struct gpio_chip *chip, unsigned int offset)
|
|||
if (offset >= 4)
|
||||
return -EINVAL;
|
||||
|
||||
return !!(inb(stx104gpio->base) & BIT(offset));
|
||||
return !!(ioread8(stx104gpio->base) & BIT(offset));
|
||||
}
|
||||
|
||||
static int stx104_gpio_get_multiple(struct gpio_chip *chip, unsigned long *mask,
|
||||
|
@ -230,7 +230,7 @@ static int stx104_gpio_get_multiple(struct gpio_chip *chip, unsigned long *mask,
|
|||
{
|
||||
struct stx104_gpio *const stx104gpio = gpiochip_get_data(chip);
|
||||
|
||||
*bits = inb(stx104gpio->base);
|
||||
*bits = ioread8(stx104gpio->base);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -252,7 +252,7 @@ static void stx104_gpio_set(struct gpio_chip *chip, unsigned int offset,
|
|||
else
|
||||
stx104gpio->out_state &= ~mask;
|
||||
|
||||
outb(stx104gpio->out_state, stx104gpio->base);
|
||||
iowrite8(stx104gpio->out_state, stx104gpio->base);
|
||||
|
||||
spin_unlock_irqrestore(&stx104gpio->lock, flags);
|
||||
}
|
||||
|
@ -279,7 +279,7 @@ static void stx104_gpio_set_multiple(struct gpio_chip *chip,
|
|||
|
||||
stx104gpio->out_state &= ~*mask;
|
||||
stx104gpio->out_state |= *mask & *bits;
|
||||
outb(stx104gpio->out_state, stx104gpio->base);
|
||||
iowrite8(stx104gpio->out_state, stx104gpio->base);
|
||||
|
||||
spin_unlock_irqrestore(&stx104gpio->lock, flags);
|
||||
}
|
||||
|
@ -306,11 +306,16 @@ static int stx104_probe(struct device *dev, unsigned int id)
|
|||
return -EBUSY;
|
||||
}
|
||||
|
||||
priv = iio_priv(indio_dev);
|
||||
priv->base = devm_ioport_map(dev, base[id], STX104_EXTENT);
|
||||
if (!priv->base)
|
||||
return -ENOMEM;
|
||||
|
||||
indio_dev->info = &stx104_info;
|
||||
indio_dev->modes = INDIO_DIRECT_MODE;
|
||||
|
||||
/* determine if differential inputs */
|
||||
if (inb(base[id] + 8) & BIT(5)) {
|
||||
if (ioread8(priv->base + 8) & BIT(5)) {
|
||||
indio_dev->num_channels = ARRAY_SIZE(stx104_channels_diff);
|
||||
indio_dev->channels = stx104_channels_diff;
|
||||
} else {
|
||||
|
@ -320,18 +325,15 @@ static int stx104_probe(struct device *dev, unsigned int id)
|
|||
|
||||
indio_dev->name = dev_name(dev);
|
||||
|
||||
priv = iio_priv(indio_dev);
|
||||
priv->base = base[id];
|
||||
|
||||
/* configure device for software trigger operation */
|
||||
outb(0, base[id] + 9);
|
||||
iowrite8(0, priv->base + 9);
|
||||
|
||||
/* initialize gain setting to x1 */
|
||||
outb(0, base[id] + 11);
|
||||
iowrite8(0, priv->base + 11);
|
||||
|
||||
/* initialize DAC output to 0V */
|
||||
outw(0, base[id] + 4);
|
||||
outw(0, base[id] + 6);
|
||||
iowrite16(0, priv->base + 4);
|
||||
iowrite16(0, priv->base + 6);
|
||||
|
||||
stx104gpio->chip.label = dev_name(dev);
|
||||
stx104gpio->chip.parent = dev;
|
||||
|
@ -346,7 +348,7 @@ static int stx104_probe(struct device *dev, unsigned int id)
|
|||
stx104gpio->chip.get_multiple = stx104_gpio_get_multiple;
|
||||
stx104gpio->chip.set = stx104_gpio_set;
|
||||
stx104gpio->chip.set_multiple = stx104_gpio_set_multiple;
|
||||
stx104gpio->base = base[id] + 3;
|
||||
stx104gpio->base = priv->base + 3;
|
||||
stx104gpio->out_state = 0x0;
|
||||
|
||||
spin_lock_init(&stx104gpio->lock);
|
||||
|
|
|
@ -36,7 +36,7 @@ struct adc0832 {
|
|||
*/
|
||||
u8 data[24] __aligned(8);
|
||||
|
||||
u8 tx_buf[2] ____cacheline_aligned;
|
||||
u8 tx_buf[2] __aligned(IIO_DMA_MINALIGN);
|
||||
u8 rx_buf[2];
|
||||
};
|
||||
|
||||
|
|
|
@ -32,10 +32,10 @@ struct adc084s021 {
|
|||
s64 ts __aligned(8);
|
||||
} scan;
|
||||
/*
|
||||
* DMA (thus cache coherency maintenance) requires the
|
||||
* DMA (thus cache coherency maintenance) may require the
|
||||
* transfer buffers to live in their own cache line.
|
||||
*/
|
||||
u16 tx_buf[4] ____cacheline_aligned;
|
||||
u16 tx_buf[4] __aligned(IIO_DMA_MINALIGN);
|
||||
__be16 rx_buf[5]; /* First 16-bits are trash */
|
||||
};
|
||||
|
||||
|
|
|
@ -77,8 +77,8 @@ struct adc108s102_state {
|
|||
* tx_buf: 8 channel read commands, plus 1 dummy command
|
||||
* rx_buf: 1 dummy response, 8 channel responses
|
||||
*/
|
||||
__be16 rx_buf[9] ____cacheline_aligned;
|
||||
__be16 tx_buf[9] ____cacheline_aligned;
|
||||
__be16 rx_buf[9] __aligned(IIO_DMA_MINALIGN);
|
||||
__be16 tx_buf[9] __aligned(IIO_DMA_MINALIGN);
|
||||
};
|
||||
|
||||
#define ADC108S102_V_CHAN(index) \
|
||||
|
|
|
@ -55,7 +55,7 @@ struct adc12138 {
|
|||
*/
|
||||
__be16 data[20] __aligned(8);
|
||||
|
||||
u8 tx_buf[2] ____cacheline_aligned;
|
||||
u8 tx_buf[2] __aligned(IIO_DMA_MINALIGN);
|
||||
u8 rx_buf[2];
|
||||
};
|
||||
|
||||
|
|
|
@ -29,7 +29,7 @@ struct adc128 {
|
|||
struct regulator *reg;
|
||||
struct mutex lock;
|
||||
|
||||
u8 buffer[2] ____cacheline_aligned;
|
||||
u8 buffer[2] __aligned(IIO_DMA_MINALIGN);
|
||||
};
|
||||
|
||||
static int adc128_adc_conversion(struct adc128 *adc, u8 channel)
|
||||
|
|
|
@ -71,7 +71,7 @@ struct ti_adc_data {
|
|||
u8 read_size;
|
||||
u8 shift;
|
||||
|
||||
u8 buffer[16] ____cacheline_aligned;
|
||||
u8 buffer[16] __aligned(IIO_DMA_MINALIGN);
|
||||
};
|
||||
|
||||
static int ti_adc_read_measurement(struct ti_adc_data *data,
|
||||
|
|
|
@ -1098,6 +1098,7 @@ static int ads1015_remove(struct i2c_client *client)
|
|||
{
|
||||
struct iio_dev *indio_dev = i2c_get_clientdata(client);
|
||||
struct ads1015_data *data = iio_priv(indio_dev);
|
||||
int ret;
|
||||
|
||||
iio_device_unregister(indio_dev);
|
||||
|
||||
|
@ -1105,7 +1106,12 @@ static int ads1015_remove(struct i2c_client *client)
|
|||
pm_runtime_set_suspended(&client->dev);
|
||||
|
||||
/* power down single shot mode */
|
||||
return ads1015_set_conv_mode(data, ADS1015_SINGLESHOT);
|
||||
ret = ads1015_set_conv_mode(data, ADS1015_SINGLESHOT);
|
||||
if (ret)
|
||||
dev_warn(&client->dev, "Failed to power down (%pe)\n",
|
||||
ERR_PTR(ret));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
|
|
|
@ -106,7 +106,7 @@ struct ads124s_private {
|
|||
* timestamp is maintained.
|
||||
*/
|
||||
u32 buffer[ADS124S08_MAX_CHANNELS + sizeof(s64)/sizeof(u32)] __aligned(8);
|
||||
u8 data[5] ____cacheline_aligned;
|
||||
u8 data[5] __aligned(IIO_DMA_MINALIGN);
|
||||
};
|
||||
|
||||
#define ADS124S08_CHAN(index) \
|
||||
|
|
|
@ -105,7 +105,7 @@ struct ads131e08_state {
|
|||
s64 ts __aligned(8);
|
||||
} tmp_buf;
|
||||
|
||||
u8 tx_buf[3] ____cacheline_aligned;
|
||||
u8 tx_buf[3] __aligned(IIO_DMA_MINALIGN);
|
||||
/*
|
||||
* Add extra one padding byte to be able to access the last channel
|
||||
* value using u32 pointer
|
||||
|
|
|
@ -102,11 +102,11 @@ struct ti_ads7950_state {
|
|||
unsigned int gpio_cmd_settings_bitmask;
|
||||
|
||||
/*
|
||||
* DMA (thus cache coherency maintenance) requires the
|
||||
* DMA (thus cache coherency maintenance) may require the
|
||||
* transfer buffers to live in their own cache lines.
|
||||
*/
|
||||
u16 rx_buf[TI_ADS7950_MAX_CHAN + 2 + TI_ADS7950_TIMESTAMP_SIZE]
|
||||
____cacheline_aligned;
|
||||
__aligned(IIO_DMA_MINALIGN);
|
||||
u16 tx_buf[TI_ADS7950_MAX_CHAN + 2];
|
||||
u16 single_tx;
|
||||
u16 single_rx;
|
||||
|
|
|
@ -28,7 +28,7 @@ struct ads8344 {
|
|||
*/
|
||||
struct mutex lock;
|
||||
|
||||
u8 tx_buf ____cacheline_aligned;
|
||||
u8 tx_buf __aligned(IIO_DMA_MINALIGN);
|
||||
u8 rx_buf[3];
|
||||
};
|
||||
|
||||
|
|
|
@ -71,7 +71,7 @@ struct ads8688_state {
|
|||
union {
|
||||
__be32 d32;
|
||||
u8 d8[4];
|
||||
} data[2] ____cacheline_aligned;
|
||||
} data[2] __aligned(IIO_DMA_MINALIGN);
|
||||
};
|
||||
|
||||
enum ads8688_id {
|
||||
|
|
|
@ -37,12 +37,12 @@ struct tlc4541_state {
|
|||
struct spi_message scan_single_msg;
|
||||
|
||||
/*
|
||||
* DMA (thus cache coherency maintenance) requires the
|
||||
* DMA (thus cache coherency maintenance) may require the
|
||||
* transfer buffers to live in their own cache lines.
|
||||
* 2 bytes data + 6 bytes padding + 8 bytes timestamp when
|
||||
* call iio_push_to_buffers_with_timestamp.
|
||||
*/
|
||||
__be16 rx_buf[8] ____cacheline_aligned;
|
||||
__be16 rx_buf[8] __aligned(IIO_DMA_MINALIGN);
|
||||
};
|
||||
|
||||
struct tlc4541_chip_info {
|
||||
|
|
|
@ -776,7 +776,7 @@ static int tsc2046_adc_probe(struct spi_device *spi)
|
|||
priv->spi = spi;
|
||||
|
||||
indio_dev->name = TI_TSC2046_NAME;
|
||||
indio_dev->modes = INDIO_DIRECT_MODE | INDIO_BUFFER_TRIGGERED;
|
||||
indio_dev->modes = INDIO_DIRECT_MODE;
|
||||
indio_dev->channels = dcfg->channels;
|
||||
indio_dev->num_channels = dcfg->num_channels;
|
||||
indio_dev->info = &tsc2046_adc_info;
|
||||
|
|
|
@ -5,7 +5,9 @@
|
|||
* Copyright 2013 Freescale Semiconductor, Inc.
|
||||
*/
|
||||
|
||||
#include <linux/mod_devicetable.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/property.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/delay.h>
|
||||
|
@ -14,10 +16,7 @@
|
|||
#include <linux/io.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/completion.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_irq.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/err.h>
|
||||
|
||||
#include <linux/iio/iio.h>
|
||||
|
@ -799,6 +798,7 @@ MODULE_DEVICE_TABLE(of, vf610_adc_match);
|
|||
|
||||
static int vf610_adc_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct vf610_adc *info;
|
||||
struct iio_dev *indio_dev;
|
||||
int irq;
|
||||
|
@ -846,13 +846,10 @@ static int vf610_adc_probe(struct platform_device *pdev)
|
|||
|
||||
info->vref_uv = regulator_get_voltage(info->vref);
|
||||
|
||||
of_property_read_u32_array(pdev->dev.of_node, "fsl,adck-max-frequency",
|
||||
info->max_adck_rate, 3);
|
||||
device_property_read_u32_array(dev, "fsl,adck-max-frequency", info->max_adck_rate, 3);
|
||||
|
||||
ret = of_property_read_u32(pdev->dev.of_node, "min-sample-time",
|
||||
&info->adc_feature.default_sample_time);
|
||||
if (ret)
|
||||
info->adc_feature.default_sample_time = DEFAULT_SAMPLE_TIME;
|
||||
info->adc_feature.default_sample_time = DEFAULT_SAMPLE_TIME;
|
||||
device_property_read_u32(dev, "min-sample-time", &info->adc_feature.default_sample_time);
|
||||
|
||||
platform_set_drvdata(pdev, indio_dev);
|
||||
|
||||
|
|
|
@ -17,10 +17,11 @@
|
|||
#include <linux/interrupt.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/mod_devicetable.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/overflow.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/property.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/sysfs.h>
|
||||
|
||||
|
@ -1182,14 +1183,13 @@ static const struct of_device_id xadc_of_match_table[] = {
|
|||
};
|
||||
MODULE_DEVICE_TABLE(of, xadc_of_match_table);
|
||||
|
||||
static int xadc_parse_dt(struct iio_dev *indio_dev, struct device_node *np,
|
||||
unsigned int *conf, int irq)
|
||||
static int xadc_parse_dt(struct iio_dev *indio_dev, unsigned int *conf, int irq)
|
||||
{
|
||||
struct device *dev = indio_dev->dev.parent;
|
||||
struct xadc *xadc = iio_priv(indio_dev);
|
||||
const struct iio_chan_spec *channel_templates;
|
||||
struct iio_chan_spec *channels, *chan;
|
||||
struct device_node *chan_node, *child;
|
||||
struct fwnode_handle *chan_node, *child;
|
||||
unsigned int max_channels;
|
||||
unsigned int num_channels;
|
||||
const char *external_mux;
|
||||
|
@ -1200,7 +1200,7 @@ static int xadc_parse_dt(struct iio_dev *indio_dev, struct device_node *np,
|
|||
|
||||
*conf = 0;
|
||||
|
||||
ret = of_property_read_string(np, "xlnx,external-mux", &external_mux);
|
||||
ret = device_property_read_string(dev, "xlnx,external-mux", &external_mux);
|
||||
if (ret < 0 || strcasecmp(external_mux, "none") == 0)
|
||||
xadc->external_mux_mode = XADC_EXTERNAL_MUX_NONE;
|
||||
else if (strcasecmp(external_mux, "single") == 0)
|
||||
|
@ -1211,8 +1211,7 @@ static int xadc_parse_dt(struct iio_dev *indio_dev, struct device_node *np,
|
|||
return -EINVAL;
|
||||
|
||||
if (xadc->external_mux_mode != XADC_EXTERNAL_MUX_NONE) {
|
||||
ret = of_property_read_u32(np, "xlnx,external-mux-channel",
|
||||
&ext_mux_chan);
|
||||
ret = device_property_read_u32(dev, "xlnx,external-mux-channel", &ext_mux_chan);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
|
@ -1247,33 +1246,31 @@ static int xadc_parse_dt(struct iio_dev *indio_dev, struct device_node *np,
|
|||
num_channels = 9;
|
||||
chan = &channels[9];
|
||||
|
||||
chan_node = of_get_child_by_name(np, "xlnx,channels");
|
||||
if (chan_node) {
|
||||
for_each_child_of_node(chan_node, child) {
|
||||
if (num_channels >= max_channels) {
|
||||
of_node_put(child);
|
||||
break;
|
||||
}
|
||||
|
||||
ret = of_property_read_u32(child, "reg", ®);
|
||||
if (ret || reg > 16)
|
||||
continue;
|
||||
|
||||
if (of_property_read_bool(child, "xlnx,bipolar"))
|
||||
chan->scan_type.sign = 's';
|
||||
|
||||
if (reg == 0) {
|
||||
chan->scan_index = 11;
|
||||
chan->address = XADC_REG_VPVN;
|
||||
} else {
|
||||
chan->scan_index = 15 + reg;
|
||||
chan->address = XADC_REG_VAUX(reg - 1);
|
||||
}
|
||||
num_channels++;
|
||||
chan++;
|
||||
chan_node = device_get_named_child_node(dev, "xlnx,channels");
|
||||
fwnode_for_each_child_node(chan_node, child) {
|
||||
if (num_channels >= max_channels) {
|
||||
fwnode_handle_put(child);
|
||||
break;
|
||||
}
|
||||
|
||||
ret = fwnode_property_read_u32(child, "reg", ®);
|
||||
if (ret || reg > 16)
|
||||
continue;
|
||||
|
||||
if (fwnode_property_read_bool(child, "xlnx,bipolar"))
|
||||
chan->scan_type.sign = 's';
|
||||
|
||||
if (reg == 0) {
|
||||
chan->scan_index = 11;
|
||||
chan->address = XADC_REG_VPVN;
|
||||
} else {
|
||||
chan->scan_index = 15 + reg;
|
||||
chan->address = XADC_REG_VAUX(reg - 1);
|
||||
}
|
||||
num_channels++;
|
||||
chan++;
|
||||
}
|
||||
of_node_put(chan_node);
|
||||
fwnode_handle_put(chan_node);
|
||||
|
||||
/* No IRQ => no events */
|
||||
if (irq <= 0) {
|
||||
|
@ -1316,7 +1313,6 @@ static void xadc_cancel_delayed_work(void *data)
|
|||
static int xadc_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
const struct of_device_id *id;
|
||||
const struct xadc_ops *ops;
|
||||
struct iio_dev *indio_dev;
|
||||
unsigned int bipolar_mask;
|
||||
|
@ -1326,15 +1322,10 @@ static int xadc_probe(struct platform_device *pdev)
|
|||
int irq;
|
||||
int i;
|
||||
|
||||
if (!dev->of_node)
|
||||
return -ENODEV;
|
||||
|
||||
id = of_match_node(xadc_of_match_table, dev->of_node);
|
||||
if (!id)
|
||||
ops = device_get_match_data(dev);
|
||||
if (!ops)
|
||||
return -EINVAL;
|
||||
|
||||
ops = id->data;
|
||||
|
||||
irq = platform_get_irq_optional(pdev, 0);
|
||||
if (irq < 0 &&
|
||||
(irq != -ENXIO || !(ops->flags & XADC_FLAGS_IRQ_OPTIONAL)))
|
||||
|
@ -1345,7 +1336,7 @@ static int xadc_probe(struct platform_device *pdev)
|
|||
return -ENOMEM;
|
||||
|
||||
xadc = iio_priv(indio_dev);
|
||||
xadc->ops = id->data;
|
||||
xadc->ops = ops;
|
||||
init_completion(&xadc->completion);
|
||||
mutex_init(&xadc->mutex);
|
||||
spin_lock_init(&xadc->lock);
|
||||
|
@ -1359,7 +1350,7 @@ static int xadc_probe(struct platform_device *pdev)
|
|||
indio_dev->modes = INDIO_DIRECT_MODE;
|
||||
indio_dev->info = &xadc_info;
|
||||
|
||||
ret = xadc_parse_dt(indio_dev, dev->of_node, &conf0, irq);
|
||||
ret = xadc_parse_dt(indio_dev, &conf0, irq);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче