]> Git Repo - linux.git/commitdiff
Merge tag 'iio-for-5.16a-split-take4' of https://git.kernel.org/pub/scm/linux/kernel...
authorGreg Kroah-Hartman <[email protected]>
Tue, 19 Oct 2021 09:44:28 +0000 (11:44 +0200)
committerGreg Kroah-Hartman <[email protected]>
Tue, 19 Oct 2021 09:44:28 +0000 (11:44 +0200)
Jonathan writes:

First set of IIO new device and feature support for the 5.16 cycle

Counter subsystem changes now sent separately.

This has been a busy cycle, so lots here and a few more stragglers to
come next week.

Big new feature in this cycle is probably output buffer support.
This has been in the works for a very long time so it's great to see
Mihail pick up the challenge and build upon his predecessors work to finally
bring this feature to mainline.

New device support
------------------

* adi,adxl313
  - New driver and dt bindings for this low power accelerometer.
* adi,adxl355
  - New driver and dt bindings for this accelerometer.
  - Later series adds buffer support.
* asahi-kasei,ak8975
  - Minor additions to driver to support ak09916
* aspeed,aspeed-adc
  - Substantial rework plus feature additions to add support for the
    ast2600 including a new dt bindings doc.
* atmel,at91_sama5d2
  - Rework and support introduced for the sama7g5 parts.
* maxim,max31865
  - New driver and bindings for this RTD temperature sensor chip.
* nxp,imx8qxp
  - New driver and bindings for the ADC found on the i.MX 8QuadXPlus Soc.
* senseair,sunrise
  - New driver and bindings for this family of carbon dioxide gas sensors.
* sensiron,scd4x
  - New driver and bindings for this carbon dioxide gas sensor.

New features
------------

* Output buffer support.  Works in a similar fashion to input buffers, but
  in this case userspace pushes data into the kfifo which is then drained
  to the device when a trigger occurs.  Support added to the ad5766 DAC
  driver.
* Core, devm_iio_map_array_register() to avoid need for
  devm_add_action_or_reset() based cleanup in fully managed allocation
  drivers.
* Core iio_push_to_buffers_with_ts_unaligned() function to safely handle a
  few drivers where it really hard to ensure the correct data alignment in
  an iio_push_to_buffers_with_timestamp() call. Note this uses a bounce
  buffer so should be avoided whenever possible.  Used in the ti,adc108s102,
  invense,mpu3050 and adi,adis16400.  This closes the last   known set
  of drivers with alignment issues at this interface.
* maxim,max1027
  - Substantial rework to this driver main target of which was supporting
    use of other triggers than it's own EOC interrupt.
  - Transfer optimization.
* nxp,fxls8962af
  - Threshold even support including using it as a wakeup source.

Cleanups, minor fixes etc
-------------------------

Chances of a common type to multiple drivers:

* devm_ conversion and drop of .remove() callbacks in:
  - adi,ad5064
  - adi,ad7291
  - adi,ad7303
  - adi,ad7746
  - adi,ad9832
  - adi,adis16080
  - dialog,da9150-gpadc
  - intel,mrfld_adc
  - marvell,berlin2
  - maxim,max1363
  - maxim,max44000
  - nuvoton,nau7802
  - st_sensors (includes a lot of rework!)
  - ti,ads8344
  - ti,lp8788

* devm_platform_ioremap_resource() used to reduce boilerplate
  - cirrus,ep93xx
  - rockchip,saradc
  - stm,stm32-dac

* Use dev_err_probe() in more places to both not print on deferred probe and
  ensure a reason for the deferral is available for debug purposes.
  - adi,ad8801
  - capella,cm36651
  - linear,ltc1660
  - maxim,ds4424
  - maxim,max5821
  - microchip,mcp4922
  - nxp,lpc18xx
  - onnn,noa1305
  - st,lsm9ds0
  - st,st_sensors
  - st,stm32-dac
  - ti,afe4403
  - ti,afe4404
  - ti,dac7311

* Drop error returns in SPI and I2C remove() functions as they are ignored and
  long term plan is to change these all over to returning void. In some cases
  these patches just make it 'obvious' they always return 0 where it was the
  case before but not easy to tell.
  - adi,ad5380
  - adi,ad5446
  - adi,ad5686
  - adi,ad5592r
  - bosch,bma400
  - bosch,bmc150
  - fsl,mma7455
  - honeywell,hmc5843
  - kionix,kxsd9
  - maxim,max5487
  - meas,ms5611
  - ti,afe4403

Driver specific changes

* adi,ad5770r
  - Bring driver inline with documented bindings.
* adi,ad7746
  - Trivial style fix
* adi,ad7949
  - Express some magic values as the underlying parts via new #defines.
  - Make it work with SPI controllers that don't support 14 or 16 bit messages
  - Support selection of voltage reference from dt including expanding the
    dt-bindings to cover this new functionality.
* adi,ad799x
  - Implement selection of external reference voltage on AD7991, AD7995 and
    AD7999.
  - Add missing dt-bindings doc for devices supported by this driver.
* adi,adislib
  - Move interrupt startup to better location in startup flow.
  - Handle devices that cannot mask/unmask the drdy pin and must instead mask
    at the interrupt controller.  Applies to the adis16460 and adis16475 from
    which we then drop equivalent code.
* adi,ltc2983
  - Add support for optional reset pin.
  - Fail to probe if no channels specified in dt binding.
* asahi-kasei,ak8975
  - dt-binding additions of missing vid-supply regulator.
* aspeed,aspeed-adc
  - Typo fix.
* fsl,mma7660
  - Mark acpi_device_id table __maybe_unused to avoid build warning.
* fsl,imx25-gcq
  - Avoid initializing regulators that aren't used.
* invensense,mpu3050
  - Drop a dead protection against a clash with the old input driver.
* invensense,mpu6050
  - Rework code to not use strcpy() and hence avoid possibility of wrong sized
    buffers. Note this wasn't a bug, but the new code is a lot more readable.
  - Mark acpi_device_id table __maybe_unused to avoid build warning.
* kionix,kxcjk1013
  - dt-binding addition to note it supports interrupts.
* marvell,berlin2-adc
  - Enable COMPILE_TEST building.
* maxim,max1027
  - Avoid returning success in an error path.
* nxp,imx8qxp
  - Fix warning when runtime pm not enabled via __maybe_unused.
* ricoh,rn5t618
  - Use the new devm_iio_map_array_register() instead of open coding the same.
* samsung,exynos_adc
  - Improve kconfig help text.
* st,lsm6dsx
  - Move max_fifo_size into the fifo_ops structure where the other configuration
    parameters are found.
* st,st_sensors:
  - Reorder to ensure we turn the power off after removing userspace interfaces.
* senseair,sunrise
  - Add missing I2C dependency.
* ti,twl6030
  - Small code tidy up.

* tag 'iio-for-5.16a-split-take4' of https://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio: (148 commits)
  iio: imx8qxp-adc: mark PM functions as __maybe_unused
  iio: pressure: ms5611: Make ms5611_remove() return void
  iio: potentiometer: max5487: Don't return an error in .remove()
  iio: magn: hmc5843: Make hmc5843_common_remove() return void
  iio: health: afe4403: Don't return an error in .remove()
  iio: dac: ad5686: Make ad5686_remove() return void
  iio: dac: ad5592r: Make ad5592r_remove() return void
  iio: dac: ad5446: Make ad5446_remove() return void
  iio: dac: ad5380: Make ad5380_remove() return void
  iio: accel: mma7455: Make mma7455_core_remove() return void
  iio: accel: kxsd9: Make kxsd9_common_remove() return void
  iio: accel: bmi088: Make bmi088_accel_core_remove() return void
  iio: accel: bmc150: Make bmc150_accel_core_remove() return void
  iio: accel: bma400: Make bma400_remove() return void
  drivers:iio:dac:ad5766.c: Add trigger buffer
  iio: triggered-buffer: extend support to configure output buffers
  iio: kfifo-buffer: Add output buffer support
  iio: Add output buffer support
  iio: documentation: Document scd4x calibration use
  drivers: iio: chemical: Add support for Sensirion SCD4x CO2 sensor
  ...

1  2 
MAINTAINERS
drivers/iio/accel/fxls8962af-core.c
drivers/iio/adc/aspeed_adc.c
drivers/iio/adc/max1027.c
drivers/iio/imu/adis16475.c

diff --combined MAINTAINERS
index efa61ac936d3e9847f10fde929ce2e195622e28b,f925f304d33d9033d6870586092e549d4be08cc8..8f414775978aac4d83856977a41126d547d81863
@@@ -414,8 -414,7 +414,8 @@@ T: git git://git.kernel.org/pub/scm/lin
  F:    drivers/acpi/pmic/
  
  ACPI THERMAL DRIVER
 -M:    Zhang Rui <[email protected]>
 +M:    Rafael J. Wysocki <[email protected]>
 +R:    Zhang Rui <[email protected]>
  L:    [email protected]
  S:    Supported
  W:    https://01.org/linux-acpi
@@@ -591,6 -590,12 +591,12 @@@ L:       [email protected]
  S:    Maintained
  F:    drivers/platform/x86/adv_swbutton.c
  
+ ADXL313 THREE-AXIS DIGITAL ACCELEROMETER DRIVER
+ M:    Lucas Stankus <[email protected]>
+ S:    Supported
+ F:    Documentation/devicetree/bindings/iio/accel/adi,adxl313.yaml
+ F:    drivers/iio/accel/adxl313*
  ADXL34X THREE-AXIS DIGITAL ACCELEROMETER DRIVER (ADXL345/ADXL346)
  M:    Michael Hennerich <[email protected]>
  S:    Supported
@@@ -599,6 -604,16 +605,16 @@@ W:       http://ez.analog.com/community/linux
  F:    Documentation/devicetree/bindings/iio/accel/adi,adxl345.yaml
  F:    drivers/input/misc/adxl34x.c
  
+ ADXL355 THREE-AXIS DIGITAL ACCELEROMETER DRIVER
+ M:    Puranjay Mohan <[email protected]>
+ L:    [email protected]
+ S:    Supported
+ F:    Documentation/devicetree/bindings/iio/accel/adi,adxl355.yaml
+ F:    drivers/iio/accel/adxl355.h
+ F:    drivers/iio/accel/adxl355_core.c
+ F:    drivers/iio/accel/adxl355_i2c.c
+ F:    drivers/iio/accel/adxl355_spi.c
  ADXL372 THREE-AXIS DIGITAL ACCELEROMETER DRIVER
  M:    Michael Hennerich <[email protected]>
  S:    Supported
@@@ -811,7 -826,7 +827,7 @@@ F: Documentation/devicetree/bindings/dm
  F:    drivers/dma/altera-msgdma.c
  
  ALTERA PIO DRIVER
 -M:    Joyce Ooi <joyce.ooi@intel.com>
 +M:    Mun Yew Tham <mun.yew.tham@intel.com>
  L:    [email protected]
  S:    Maintained
  F:    drivers/gpio/gpio-altera.c
@@@ -978,12 -993,12 +994,12 @@@ L:      [email protected]
  S:    Maintained
  F:    drivers/platform/x86/amd-pmc.*
  
 -AMD POWERPLAY
 +AMD POWERPLAY AND SWSMU
  M:    Evan Quan <[email protected]>
  L:    [email protected]
  S:    Supported
  T:    git https://gitlab.freedesktop.org/agd5f/linux.git
 -F:    drivers/gpu/drm/amd/pm/powerplay/
 +F:    drivers/gpu/drm/amd/pm/
  
  AMD PTDMA DRIVER
  M:    Sanjay R Mehta <[email protected]>
@@@ -1276,7 -1291,6 +1292,7 @@@ F:      drivers/input/mouse/bcm5974.
  
  APPLE DART IOMMU DRIVER
  M:    Sven Peter <[email protected]>
 +R:    Alyssa Rosenzweig <[email protected]>
  L:    [email protected]
  S:    Maintained
  F:    Documentation/devicetree/bindings/iommu/apple,dart.yaml
@@@ -1713,8 -1727,6 +1729,8 @@@ F:      drivers/*/*alpine
  
  ARM/APPLE MACHINE SUPPORT
  M:    Hector Martin <[email protected]>
 +M:    Sven Peter <[email protected]>
 +R:    Alyssa Rosenzweig <[email protected]>
  L:    [email protected] (moderated for non-subscribers)
  S:    Maintained
  W:    https://asahilinux.org
@@@ -2240,7 -2252,6 +2256,7 @@@ F:      arch/arm/mach-pxa/mioa701.
  
  ARM/MStar/Sigmastar Armv7 SoC support
  M:    Daniel Palmer <[email protected]>
 +M:    Romain Perier <[email protected]>
  L:    [email protected] (moderated for non-subscribers)
  S:    Maintained
  W:    http://linux-chenxing.org/
@@@ -2717,7 -2728,6 +2733,7 @@@ F:      drivers/power/reset/keystone-reset.
  
  ARM/TEXAS INSTRUMENTS K3 ARCHITECTURE
  M:    Nishanth Menon <[email protected]>
 +M:    Vignesh Raghavendra <[email protected]>
  M:    Tero Kristo <[email protected]>
  L:    [email protected] (moderated for non-subscribers)
  S:    Supported
@@@ -2810,8 -2820,9 +2826,8 @@@ F:      arch/arm/mach-pxa/include/mach/vpac2
  F:    arch/arm/mach-pxa/vpac270.c
  
  ARM/VT8500 ARM ARCHITECTURE
 -M:    Tony Prisk <[email protected]>
  L:    [email protected] (moderated for non-subscribers)
 -S:    Maintained
 +S:    Orphan
  F:    Documentation/devicetree/bindings/i2c/i2c-wmt.txt
  F:    arch/arm/mach-vt8500/
  F:    drivers/clocksource/timer-vt8500.c
@@@ -2967,7 -2978,7 +2983,7 @@@ F:      crypto/async_tx
  F:    include/linux/async_tx.h
  
  AT24 EEPROM DRIVER
 -M:    Bartosz Golaszewski <b[email protected]>
 +M:    Bartosz Golaszewski <b[email protected]>
  L:    [email protected]
  S:    Maintained
  T:    git git://git.kernel.org/pub/scm/linux/kernel/git/brgl/linux.git
@@@ -3390,11 -3401,9 +3406,11 @@@ F:    Documentation/networking/filter.rs
  F:    Documentation/userspace-api/ebpf/
  F:    arch/*/net/*
  F:    include/linux/bpf*
 +F:    include/linux/btf*
  F:    include/linux/filter.h
  F:    include/trace/events/xdp.h
  F:    include/uapi/linux/bpf*
 +F:    include/uapi/linux/btf*
  F:    include/uapi/linux/filter.h
  F:    kernel/bpf/
  F:    kernel/trace/bpf_trace.c
@@@ -3828,6 -3837,7 +3844,6 @@@ F:      drivers/scsi/mpi3mr
  
  BROADCOM NETXTREME-E ROCE DRIVER
  M:    Selvin Xavier <[email protected]>
 -M:    Naresh Kumar PBS <[email protected]>
  L:    [email protected]
  S:    Supported
  W:    http://www.broadcom.com
@@@ -4662,7 -4672,7 +4678,7 @@@ W:      http://linux-cifs.samba.org
  T:    git git://git.samba.org/sfrench/cifs-2.6.git
  F:    Documentation/admin-guide/cifs/
  F:    fs/cifs/
 -F:    fs/cifs_common/
 +F:    fs/smbfs_common/
  
  COMPACTPCI HOTPLUG CORE
  M:    Scott Murray <[email protected]>
@@@ -4810,8 -4820,7 +4826,8 @@@ F:      Documentation/ABI/testing/sysfs-bus-
  F:    Documentation/driver-api/generic-counter.rst
  F:    drivers/counter/
  F:    include/linux/counter.h
 -F:    include/linux/counter_enum.h
 +F:    include/uapi/linux/counter.h
 +F:    tools/counter/
  
  CP2615 I2C DRIVER
  M:    Bence Csókás <[email protected]>
@@@ -7344,11 -7353,10 +7360,11 @@@ F:   include/uapi/linux/fpga-dfl.
  
  FPGA MANAGER FRAMEWORK
  M:    Moritz Fischer <[email protected]>
 +M:    Wu Hao <[email protected]>
 +M:    Xu Yilun <[email protected]>
  R:    Tom Rix <[email protected]>
  L:    [email protected]
  S:    Maintained
 -W:    http://www.rocketboards.org
  Q:    http://patchwork.kernel.org/project/linux-fpga/list/
  T:    git git://git.kernel.org/pub/scm/linux/kernel/git/mdf/linux-fpga.git
  F:    Documentation/devicetree/bindings/fpga/
@@@ -7442,7 -7450,7 +7458,7 @@@ FREESCALE IMX / MXC FEC DRIVE
  M:    Joakim Zhang <[email protected]>
  L:    [email protected]
  S:    Maintained
 -F:    Documentation/devicetree/bindings/net/fsl-fec.txt
 +F:    Documentation/devicetree/bindings/net/fsl,fec.yaml
  F:    drivers/net/ethernet/freescale/fec.h
  F:    drivers/net/ethernet/freescale/fec_main.c
  F:    drivers/net/ethernet/freescale/fec_ptp.c
@@@ -7994,7 -8002,7 +8010,7 @@@ F:      include/linux/gpio/regmap.
  
  GPIO SUBSYSTEM
  M:    Linus Walleij <[email protected]>
 -M:    Bartosz Golaszewski <b[email protected]>
 +M:    Bartosz Golaszewski <b[email protected]>
  L:    [email protected]
  S:    Maintained
  T:    git git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio.git
@@@ -8616,8 -8624,9 +8632,8 @@@ F:      Documentation/devicetree/bindings/ii
  F:    drivers/iio/humidity/hts221*
  
  HUAWEI ETHERNET DRIVER
 -M:    Bin Luo <[email protected]>
  L:    [email protected]
 -S:    Supported
 +S:    Orphan
  F:    Documentation/networking/device_drivers/ethernet/huawei/hinic.rst
  F:    drivers/net/ethernet/huawei/hinic/
  
@@@ -9309,7 -9318,7 +9325,7 @@@ S:      Maintaine
  F:    drivers/platform/x86/intel/atomisp2/led.c
  
  INTEL BIOS SAR INT1092 DRIVER
 -M:    Shravan S <[email protected]>
 +M:    Shravan Sudhakar <[email protected]>
  M:    Intel Corporation <[email protected]>
  L:    [email protected]
  S:    Maintained
@@@ -9631,7 -9640,7 +9647,7 @@@ F:      include/uapi/linux/isst_if.
  F:    tools/power/x86/intel-speed-select/
  
  INTEL STRATIX10 FIRMWARE DRIVERS
 -M:    Richard Gong <[email protected]>
 +M:    Dinh Nguyen <[email protected]>
  L:    [email protected]
  S:    Maintained
  F:    Documentation/ABI/testing/sysfs-devices-platform-stratix10-rsu
@@@ -10201,8 -10210,8 +10217,8 @@@ M:   Hyunchul Lee <[email protected]
  L:    [email protected]
  S:    Maintained
  T:    git git://git.samba.org/ksmbd.git
 -F:    fs/cifs_common/
  F:    fs/ksmbd/
 +F:    fs/smbfs_common/
  
  KERNEL UNIT TESTING FRAMEWORK (KUnit)
  M:    Brendan Higgins <[email protected]>
@@@ -10281,6 -10290,7 +10297,6 @@@ KERNEL VIRTUAL MACHINE for s390 (KVM/s3
  M:    Christian Borntraeger <[email protected]>
  M:    Janosch Frank <[email protected]>
  R:    David Hildenbrand <[email protected]>
 -R:    Cornelia Huck <[email protected]>
  R:    Claudio Imbrenda <[email protected]>
  L:    [email protected]
  S:    Supported
@@@ -11154,7 -11164,6 +11170,7 @@@ S:   Maintaine
  F:    Documentation/devicetree/bindings/net/dsa/marvell.txt
  F:    Documentation/networking/devlink/mv88e6xxx.rst
  F:    drivers/net/dsa/mv88e6xxx/
 +F:    include/linux/dsa/mv88e6xxx.h
  F:    include/linux/platform_data/mv88e6xxx.h
  
  MARVELL ARMADA 3700 PHY DRIVERS
@@@ -11374,7 -11383,7 +11390,7 @@@ F:   Documentation/devicetree/bindings/ii
  F:    drivers/iio/proximity/mb1232.c
  
  MAXIM MAX77650 PMIC MFD DRIVER
 -M:    Bartosz Golaszewski <b[email protected]>
 +M:    Bartosz Golaszewski <b[email protected]>
  L:    [email protected]
  S:    Maintained
  F:    Documentation/devicetree/bindings/*/*max77650.yaml
@@@ -13262,9 -13271,9 +13278,9 @@@ F:   Documentation/scsi/NinjaSCSI.rs
  F:    drivers/scsi/nsp32*
  
  NIOS2 ARCHITECTURE
 -M:    Ley Foon Tan <[email protected]>
 +M:    Dinh Nguyen <[email protected]>
  S:    Maintained
 -T:    git git://git.kernel.org/pub/scm/linux/kernel/git/lftan/nios2.git
 +T:    git git://git.kernel.org/pub/scm/linux/kernel/git/dinguyen/linux.git
  F:    arch/nios2/
  
  NITRO ENCLAVES (NE)
@@@ -13472,6 -13481,13 +13488,13 @@@ S: Maintaine
  F:    Documentation/devicetree/bindings/display/imx/nxp,imx8mq-dcss.yaml
  F:    drivers/gpu/drm/imx/dcss/
  
+ NXP i.MX 8QXP ADC DRIVER
+ M:    Cai Huoqing <[email protected]>
+ L:    [email protected]
+ S:    Supported
+ F:    Documentation/devicetree/bindings/iio/adc/nxp,imx8qxp-adc.yaml
+ F:    drivers/iio/adc/imx8qxp-adc.c
  NXP PF8100/PF8121A/PF8200 PMIC REGULATOR DEVICE DRIVER
  M:    Jagan Teki <[email protected]>
  S:    Maintained
@@@ -14349,8 -14365,7 +14372,8 @@@ F:   Documentation/devicetree/bindings/pc
  F:    drivers/pci/controller/pci-ixp4xx.c
  
  PCI DRIVER FOR INTEL VOLUME MANAGEMENT DEVICE (VMD)
 -M:    Jonathan Derrick <[email protected]>
 +M:    Nirmal Patel <[email protected]>
 +R:    Jonathan Derrick <[email protected]>
  L:    [email protected]
  S:    Supported
  F:    drivers/pci/controller/vmd.c
  M:    Heiko Carstens <[email protected]>
  M:    Vasily Gorbik <[email protected]>
  M:    Christian Borntraeger <[email protected]>
 +R:    Alexander Gordeev <[email protected]>
  L:    [email protected]
  S:    Supported
  W:    http://www.ibm.com/developerworks/linux/linux390/
@@@ -16382,6 -16396,7 +16405,6 @@@ F:   drivers/s390/crypto/vfio_ap_ops.
  F:    drivers/s390/crypto/vfio_ap_private.h
  
  S390 VFIO-CCW DRIVER
 -M:    Cornelia Huck <[email protected]>
  M:    Eric Farman <[email protected]>
  M:    Matthew Rosato <[email protected]>
  R:    Halil Pasic <[email protected]>
@@@ -16658,6 -16673,13 +16681,6 @@@ M:  Lubomir Rintel <[email protected]
  S:    Supported
  F:    drivers/char/pcmcia/scr24x_cs.c
  
 -SCSI CDROM DRIVER
 -M:    Jens Axboe <[email protected]>
 -L:    [email protected]
 -S:    Maintained
 -W:    http://www.kernel.dk
 -F:    drivers/scsi/sr*
 -
  SCSI RDMA PROTOCOL (SRP) INITIATOR
  M:    Bart Van Assche <[email protected]>
  L:    [email protected]
@@@ -16872,6 -16894,13 +16895,13 @@@ S: Maintaine
  F:    drivers/misc/phantom.c
  F:    include/uapi/linux/phantom.h
  
+ SENSEAIR SUNRISE 006-0-0007
+ M:    Jacopo Mondi <[email protected]>
+ S:    Maintained
+ F:    Documentation/ABI/testing/sysfs-bus-iio-chemical-sunrise-co2
+ F:    Documentation/devicetree/bindings/iio/chemical/senseair,sunrise.yaml
+ F:    drivers/iio/chemical/sunrise_co2.c
  SENSIRION SCD30 CARBON DIOXIDE SENSOR DRIVER
  M:    Tomasz Duszynski <[email protected]>
  S:    Maintained
@@@ -16881,6 -16910,12 +16911,12 @@@ F: drivers/iio/chemical/scd30_core.
  F:    drivers/iio/chemical/scd30_i2c.c
  F:    drivers/iio/chemical/scd30_serial.c
  
+ SENSIRION SCD4X CARBON DIOXIDE SENSOR DRIVER
+ M:    Roan van Dijk <[email protected]>
+ S:    Maintained
+ F:    Documentation/devicetree/bindings/iio/chemical/sensirion,scd4x.yaml
+ F:    drivers/iio/chemical/scd4x.c
  SENSIRION SGP40 GAS SENSOR DRIVER
  M:    Andreas Klinger <[email protected]>
  S:    Maintained
@@@ -16956,6 -16991,7 +16992,6 @@@ F:   drivers/misc/sgi-xp
  
  SHARED MEMORY COMMUNICATIONS (SMC) SOCKETS
  M:    Karsten Graul <[email protected]>
 -M:    Guvenc Gulce <[email protected]>
  L:    [email protected]
  S:    Supported
  W:    http://www.ibm.com/developerworks/linux/linux390/
@@@ -17800,6 -17836,7 +17836,6 @@@ F:   drivers/staging/nvec
  
  STAGING - OLPC SECONDARY DISPLAY CONTROLLER (DCON)
  M:    Jens Frederich <[email protected]>
 -M:    Daniel Drake <[email protected]>
  M:    Jon Nettleton <[email protected]>
  S:    Maintained
  W:    http://wiki.laptop.org/go/DCON
@@@ -17890,8 -17927,7 +17926,8 @@@ M:   Olivier Moysan <olivier.moysan@foss.
  M:    Arnaud Pouliquen <[email protected]>
  L:    [email protected] (moderated for non-subscribers)
  S:    Maintained
 -F:    Documentation/devicetree/bindings/iio/adc/st,stm32-*.yaml
 +F:    Documentation/devicetree/bindings/iio/adc/st,stm32-dfsdm-adc.yaml
 +F:    Documentation/devicetree/bindings/sound/st,stm32-*.yaml
  F:    sound/soc/stm/
  
  STM32 TIMER/LPTIMER DRIVERS
@@@ -17968,11 -18004,10 +18004,11 @@@ F:        Documentation/admin-guide/svga.rs
  F:    arch/x86/boot/video*
  
  SWIOTLB SUBSYSTEM
 -M:    Konrad Rzeszutek Wilk <[email protected]>
 +M:    Christoph Hellwig <[email protected]>
  L:    [email protected]
  S:    Supported
 -T:    git git://git.kernel.org/pub/scm/linux/kernel/git/konrad/swiotlb.git
 +W:    http://git.infradead.org/users/hch/dma-mapping.git
 +T:    git git://git.infradead.org/users/hch/dma-mapping.git
  F:    arch/*/kernel/pci-swiotlb.c
  F:    include/linux/swiotlb.h
  F:    kernel/dma/swiotlb.c
@@@ -17988,7 -18023,7 +18024,7 @@@ F:   net/switchdev
  SY8106A REGULATOR DRIVER
  M:    Icenowy Zheng <[email protected]>
  S:    Maintained
 -F:    Documentation/devicetree/bindings/regulator/sy8106a-regulator.txt
 +F:    Documentation/devicetree/bindings/regulator/silergy,sy8106a.yaml
  F:    drivers/regulator/sy8106a-regulator.c
  
  SYNC FILE FRAMEWORK
@@@ -18555,14 -18590,13 +18591,14 @@@ T:        git git://linuxtv.org/media_tree.gi
  F:    drivers/media/radio/radio-raremono.c
  
  THERMAL
 -M:    Zhang Rui <[email protected]>
 +M:    Rafael J. Wysocki <[email protected]>
  M:    Daniel Lezcano <[email protected]>
  R:    Amit Kucheria <[email protected]>
 +R:    Zhang Rui <[email protected]>
  L:    [email protected]
  S:    Supported
  Q:    https://patchwork.kernel.org/project/linux-pm/list/
 -T:    git git://git.kernel.org/pub/scm/linux/kernel/git/thermal/linux.git
 +T:    git git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm.git thermal
  F:    Documentation/devicetree/bindings/thermal/
  F:    drivers/thermal/
  F:    include/linux/cpu_cooling.h
@@@ -18691,7 -18725,7 +18727,7 @@@ F:   include/linux/clk/ti.
  
  TI DAVINCI MACHINE SUPPORT
  M:    Sekhar Nori <[email protected]>
 -R:    Bartosz Golaszewski <b[email protected]>
 +R:    Bartosz Golaszewski <b[email protected]>
  L:    [email protected] (moderated for non-subscribers)
  S:    Supported
  T:    git git://git.kernel.org/pub/scm/linux/kernel/git/nsekhar/linux-davinci.git
@@@ -19290,12 -19324,13 +19326,12 @@@ S:        Maintaine
  F:    drivers/usb/misc/chaoskey.c
  
  USB CYPRESS C67X00 DRIVER
 -M:    Peter Korsgaard <[email protected]>
  L:    [email protected]
 -S:    Maintained
 +S:    Orphan
  F:    drivers/usb/c67x00/
  
  USB DAVICOM DM9601 DRIVER
 -M:    Peter Korsgaard <[email protected]>
 +M:    Peter Korsgaard <[email protected]>
  L:    [email protected]
  S:    Maintained
  W:    http://www.linux-usb.org/usbnet
@@@ -20475,6 -20510,7 +20511,6 @@@ F:   samples/bpf/xdpsock
  F:    tools/lib/bpf/xsk*
  
  XEN BLOCK SUBSYSTEM
 -M:    Konrad Rzeszutek Wilk <[email protected]>
  M:    Roger Pau Monné <[email protected]>
  L:    [email protected] (moderated for non-subscribers)
  S:    Supported
@@@ -20522,7 -20558,7 +20558,7 @@@ S:   Supporte
  F:    drivers/net/xen-netback/*
  
  XEN PCI SUBSYSTEM
 -M:    Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
 +M:    Juergen Gross <jgross@suse.com>
  L:    [email protected] (moderated for non-subscribers)
  S:    Supported
  F:    arch/x86/pci/*xen*
@@@ -20545,8 -20581,7 +20581,8 @@@ S:   Supporte
  F:    sound/xen/*
  
  XEN SWIOTLB SUBSYSTEM
 -M:    Konrad Rzeszutek Wilk <[email protected]>
 +M:    Juergen Gross <[email protected]>
 +M:    Stefano Stabellini <[email protected]>
  L:    [email protected] (moderated for non-subscribers)
  L:    [email protected]
  S:    Supported
@@@ -20705,6 -20740,7 +20741,6 @@@ S:   Maintaine
  F:    mm/zbud.c
  
  ZD1211RW WIRELESS DRIVER
 -M:    Daniel Drake <[email protected]>
  M:    Ulrich Kunitz <[email protected]>
  L:    [email protected]
  L:    [email protected] (subscribers-only)
index f41db9e0249a71be2ea4f9a9fd29cc33d6a474ae,06b490c2a8cedeb4b7a42887109f2bdd23251389..32989d91b9829ebef7dcdc343cb874cd6c4dcaf1
@@@ -22,6 -22,7 +22,7 @@@
  #include <linux/regmap.h>
  
  #include <linux/iio/buffer.h>
+ #include <linux/iio/events.h>
  #include <linux/iio/iio.h>
  #include <linux/iio/kfifo_buf.h>
  #include <linux/iio/sysfs.h>
@@@ -30,6 -31,7 +31,7 @@@
  
  #define FXLS8962AF_INT_STATUS                 0x00
  #define FXLS8962AF_INT_STATUS_SRC_BOOT                BIT(0)
+ #define FXLS8962AF_INT_STATUS_SRC_SDCD_OT     BIT(4)
  #define FXLS8962AF_INT_STATUS_SRC_BUF         BIT(5)
  #define FXLS8962AF_INT_STATUS_SRC_DRDY                BIT(7)
  #define FXLS8962AF_TEMP_OUT                   0x01
@@@ -73,6 -75,7 +75,7 @@@
  #define FXLS8962AF_ASLP_COUNT_LSB             0x1e
  
  #define FXLS8962AF_INT_EN                     0x20
+ #define FXLS8962AF_INT_EN_SDCD_OT_EN          BIT(5)
  #define FXLS8962AF_INT_EN_BUF_EN              BIT(6)
  #define FXLS8962AF_INT_PIN_SEL                        0x21
  #define FXLS8962AF_INT_PIN_SEL_MASK           GENMASK(7, 0)
  #define FXLS8962AF_ORIENT_THS_REG             0x2c
  
  #define FXLS8962AF_SDCD_INT_SRC1              0x2d
+ #define FXLS8962AF_SDCD_INT_SRC1_X_OT         BIT(5)
+ #define FXLS8962AF_SDCD_INT_SRC1_X_POL                BIT(4)
+ #define FXLS8962AF_SDCD_INT_SRC1_Y_OT         BIT(3)
+ #define FXLS8962AF_SDCD_INT_SRC1_Y_POL                BIT(2)
+ #define FXLS8962AF_SDCD_INT_SRC1_Z_OT         BIT(1)
+ #define FXLS8962AF_SDCD_INT_SRC1_Z_POL                BIT(0)
  #define FXLS8962AF_SDCD_INT_SRC2              0x2e
  #define FXLS8962AF_SDCD_CONFIG1                       0x2f
+ #define FXLS8962AF_SDCD_CONFIG1_Z_OT_EN               BIT(3)
+ #define FXLS8962AF_SDCD_CONFIG1_Y_OT_EN               BIT(4)
+ #define FXLS8962AF_SDCD_CONFIG1_X_OT_EN               BIT(5)
+ #define FXLS8962AF_SDCD_CONFIG1_OT_ELE                BIT(7)
  #define FXLS8962AF_SDCD_CONFIG2                       0x30
+ #define FXLS8962AF_SDCD_CONFIG2_SDCD_EN               BIT(7)
+ #define FXLS8962AF_SC2_REF_UPDM_AC            GENMASK(6, 5)
  #define FXLS8962AF_SDCD_OT_DBCNT              0x31
  #define FXLS8962AF_SDCD_WT_DBCNT              0x32
  #define FXLS8962AF_SDCD_LTHS_LSB              0x33
@@@ -151,7 -166,11 +166,11 @@@ struct fxls8962af_data 
        } scan;
        int64_t timestamp, old_timestamp;       /* Only used in hw fifo mode. */
        struct iio_mount_matrix orientation;
+       int irq;
        u8 watermark;
+       u8 enable_event;
+       u16 lower_thres;
+       u16 upper_thres;
  };
  
  const struct regmap_config fxls8962af_regmap_conf = {
@@@ -238,7 -257,7 +257,7 @@@ static int fxls8962af_get_out(struct fx
        }
  
        ret = regmap_bulk_read(data->regmap, chan->address,
-                              &raw_val, (chan->scan_type.storagebits / 8));
+                              &raw_val, sizeof(data->lower_thres));
  
        if (!is_active)
                fxls8962af_power_off(data);
@@@ -451,6 -470,15 +470,15 @@@ static int fxls8962af_write_raw(struct 
        }
  }
  
+ static int fxls8962af_event_setup(struct fxls8962af_data *data, int state)
+ {
+       /* Enable wakeup interrupt */
+       int mask = FXLS8962AF_INT_EN_SDCD_OT_EN;
+       int value = state ? mask : 0;
+       return regmap_update_bits(data->regmap, FXLS8962AF_INT_EN, mask, value);
+ }
  static int fxls8962af_set_watermark(struct iio_dev *indio_dev, unsigned val)
  {
        struct fxls8962af_data *data = iio_priv(indio_dev);
        return 0;
  }
  
+ static int __fxls8962af_set_thresholds(struct fxls8962af_data *data,
+                                      const struct iio_chan_spec *chan,
+                                      enum iio_event_direction dir,
+                                      int val)
+ {
+       switch (dir) {
+       case IIO_EV_DIR_FALLING:
+               data->lower_thres = val;
+               return regmap_bulk_write(data->regmap, FXLS8962AF_SDCD_LTHS_LSB,
+                               &data->lower_thres, sizeof(data->lower_thres));
+       case IIO_EV_DIR_RISING:
+               data->upper_thres = val;
+               return regmap_bulk_write(data->regmap, FXLS8962AF_SDCD_UTHS_LSB,
+                               &data->upper_thres, sizeof(data->upper_thres));
+       default:
+               return -EINVAL;
+       }
+ }
+ static int fxls8962af_read_event(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 fxls8962af_data *data = iio_priv(indio_dev);
+       int ret;
+       if (type != IIO_EV_TYPE_THRESH)
+               return -EINVAL;
+       switch (dir) {
+       case IIO_EV_DIR_FALLING:
+               ret = regmap_bulk_read(data->regmap, FXLS8962AF_SDCD_LTHS_LSB,
+                                      &data->lower_thres, sizeof(data->lower_thres));
+               if (ret)
+                       return ret;
+               *val = sign_extend32(data->lower_thres, chan->scan_type.realbits - 1);
+               return IIO_VAL_INT;
+       case IIO_EV_DIR_RISING:
+               ret = regmap_bulk_read(data->regmap, FXLS8962AF_SDCD_UTHS_LSB,
+                                      &data->upper_thres, sizeof(data->upper_thres));
+               if (ret)
+                       return ret;
+               *val = sign_extend32(data->upper_thres, chan->scan_type.realbits - 1);
+               return IIO_VAL_INT;
+       default:
+               return -EINVAL;
+       }
+ }
+ static int fxls8962af_write_event(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 fxls8962af_data *data = iio_priv(indio_dev);
+       int ret, val_masked;
+       if (type != IIO_EV_TYPE_THRESH)
+               return -EINVAL;
+       if (val < -2048 || val > 2047)
+               return -EINVAL;
+       if (data->enable_event)
+               return -EBUSY;
+       val_masked = val & GENMASK(11, 0);
+       if (fxls8962af_is_active(data)) {
+               ret = fxls8962af_standby(data);
+               if (ret)
+                       return ret;
+               ret = __fxls8962af_set_thresholds(data, chan, dir, val_masked);
+               if (ret)
+                       return ret;
+               return fxls8962af_active(data);
+       } else {
+               return __fxls8962af_set_thresholds(data, chan, dir, val_masked);
+       }
+ }
+ static int
+ fxls8962af_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 fxls8962af_data *data = iio_priv(indio_dev);
+       if (type != IIO_EV_TYPE_THRESH)
+               return -EINVAL;
+       switch (chan->channel2) {
+       case IIO_MOD_X:
+               return !!(FXLS8962AF_SDCD_CONFIG1_X_OT_EN & data->enable_event);
+       case IIO_MOD_Y:
+               return !!(FXLS8962AF_SDCD_CONFIG1_Y_OT_EN & data->enable_event);
+       case IIO_MOD_Z:
+               return !!(FXLS8962AF_SDCD_CONFIG1_Z_OT_EN & data->enable_event);
+       default:
+               return -EINVAL;
+       }
+ }
+ static int
+ fxls8962af_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 fxls8962af_data *data = iio_priv(indio_dev);
+       u8 enable_event, enable_bits;
+       int ret, value;
+       if (type != IIO_EV_TYPE_THRESH)
+               return -EINVAL;
+       switch (chan->channel2) {
+       case IIO_MOD_X:
+               enable_bits = FXLS8962AF_SDCD_CONFIG1_X_OT_EN;
+               break;
+       case IIO_MOD_Y:
+               enable_bits = FXLS8962AF_SDCD_CONFIG1_Y_OT_EN;
+               break;
+       case IIO_MOD_Z:
+               enable_bits = FXLS8962AF_SDCD_CONFIG1_Z_OT_EN;
+               break;
+       default:
+               return -EINVAL;
+       }
+       if (state)
+               enable_event = data->enable_event | enable_bits;
+       else
+               enable_event = data->enable_event & ~enable_bits;
+       if (data->enable_event == enable_event)
+               return 0;
+       ret = fxls8962af_standby(data);
+       if (ret)
+               return ret;
+       /* Enable events */
+       value = enable_event | FXLS8962AF_SDCD_CONFIG1_OT_ELE;
+       ret = regmap_write(data->regmap, FXLS8962AF_SDCD_CONFIG1, value);
+       if (ret)
+               return ret;
+       /*
+        * Enable update of SDCD_REF_X/Y/Z values with the current decimated and
+        * trimmed X/Y/Z acceleration input data. This allows for acceleration
+        * slope detection with Data(n) to Data(n–1) always used as the input
+        * to the window comparator.
+        */
+       value = enable_event ?
+               FXLS8962AF_SDCD_CONFIG2_SDCD_EN | FXLS8962AF_SC2_REF_UPDM_AC :
+               0x00;
+       ret = regmap_write(data->regmap, FXLS8962AF_SDCD_CONFIG2, value);
+       if (ret)
+               return ret;
+       ret = fxls8962af_event_setup(data, state);
+       if (ret)
+               return ret;
+       data->enable_event = enable_event;
+       if (data->enable_event) {
+               fxls8962af_active(data);
+               ret = fxls8962af_power_on(data);
+       } else {
+               ret = iio_device_claim_direct_mode(indio_dev);
+               if (ret)
+                       return ret;
+               /* Not in buffered mode so disable power */
+               ret = fxls8962af_power_off(data);
+               iio_device_release_direct_mode(indio_dev);
+       }
+       return ret;
+ }
+ static const struct iio_event_spec fxls8962af_event[] = {
+       {
+               .type = IIO_EV_TYPE_THRESH,
+               .dir = IIO_EV_DIR_EITHER,
+               .mask_separate = BIT(IIO_EV_INFO_ENABLE),
+       },
+       {
+               .type = IIO_EV_TYPE_THRESH,
+               .dir = IIO_EV_DIR_FALLING,
+               .mask_separate = BIT(IIO_EV_INFO_VALUE),
+       },
+       {
+               .type = IIO_EV_TYPE_THRESH,
+               .dir = IIO_EV_DIR_RISING,
+               .mask_separate = BIT(IIO_EV_INFO_VALUE),
+       },
+ };
  #define FXLS8962AF_CHANNEL(axis, reg, idx) { \
        .type = IIO_ACCEL, \
        .address = reg, \
                .shift = 4, \
                .endianness = IIO_BE, \
        }, \
+       .event_spec = fxls8962af_event, \
+       .num_event_specs = ARRAY_SIZE(fxls8962af_event), \
  }
  
  #define FXLS8962AF_TEMP_CHANNEL { \
@@@ -522,6 -763,10 +763,10 @@@ static const struct iio_info fxls8962af
        .read_raw = &fxls8962af_read_raw,
        .write_raw = &fxls8962af_write_raw,
        .write_raw_get_fmt = fxls8962af_write_raw_get_fmt,
+       .read_event_value = fxls8962af_read_event,
+       .write_event_value = fxls8962af_write_event,
+       .read_event_config = fxls8962af_read_event_config,
+       .write_event_config = fxls8962af_write_event_config,
        .read_avail = fxls8962af_read_avail,
        .hwfifo_set_watermark = fxls8962af_set_watermark,
  };
@@@ -605,7 -850,8 +850,8 @@@ static int fxls8962af_buffer_predisable
  
        ret = __fxls8962af_fifo_set_mode(data, false);
  
-       fxls8962af_active(data);
+       if (data->enable_event)
+               fxls8962af_active(data);
  
        return ret;
  }
@@@ -614,7 -860,10 +860,10 @@@ static int fxls8962af_buffer_postdisabl
  {
        struct fxls8962af_data *data = iio_priv(indio_dev);
  
-       return fxls8962af_power_off(data);
+       if (!data->enable_event)
+               fxls8962af_power_off(data);
+       return 0;
  }
  
  static const struct iio_buffer_setup_ops fxls8962af_buffer_ops = {
@@@ -725,6 -974,45 +974,45 @@@ static int fxls8962af_fifo_flush(struc
        return count;
  }
  
+ static int fxls8962af_event_interrupt(struct iio_dev *indio_dev)
+ {
+       struct fxls8962af_data *data = iio_priv(indio_dev);
+       s64 ts = iio_get_time_ns(indio_dev);
+       unsigned int reg;
+       u64 ev_code;
+       int ret;
+       ret = regmap_read(data->regmap, FXLS8962AF_SDCD_INT_SRC1, &reg);
+       if (ret)
+               return ret;
+       if (reg & FXLS8962AF_SDCD_INT_SRC1_X_OT) {
+               ev_code = reg & FXLS8962AF_SDCD_INT_SRC1_X_POL ?
+                       IIO_EV_DIR_RISING : IIO_EV_DIR_FALLING;
+               iio_push_event(indio_dev,
+                               IIO_MOD_EVENT_CODE(IIO_ACCEL, 0, IIO_MOD_X,
+                                       IIO_EV_TYPE_THRESH, ev_code), ts);
+       }
+       if (reg & FXLS8962AF_SDCD_INT_SRC1_Y_OT) {
+               ev_code = reg & FXLS8962AF_SDCD_INT_SRC1_Y_POL ?
+                       IIO_EV_DIR_RISING : IIO_EV_DIR_FALLING;
+               iio_push_event(indio_dev,
+                               IIO_MOD_EVENT_CODE(IIO_ACCEL, 0, IIO_MOD_X,
+                                       IIO_EV_TYPE_THRESH, ev_code), ts);
+       }
+       if (reg & FXLS8962AF_SDCD_INT_SRC1_Z_OT) {
+               ev_code = reg & FXLS8962AF_SDCD_INT_SRC1_Z_POL ?
+                       IIO_EV_DIR_RISING : IIO_EV_DIR_FALLING;
+               iio_push_event(indio_dev,
+                               IIO_MOD_EVENT_CODE(IIO_ACCEL, 0, IIO_MOD_X,
+                                       IIO_EV_TYPE_THRESH, ev_code), ts);
+       }
+       return 0;
+ }
  static irqreturn_t fxls8962af_interrupt(int irq, void *p)
  {
        struct iio_dev *indio_dev = p;
  
        if (reg & FXLS8962AF_INT_STATUS_SRC_BUF) {
                ret = fxls8962af_fifo_flush(indio_dev);
 -              if (ret)
 +              if (ret < 0)
                        return IRQ_NONE;
  
                return IRQ_HANDLED;
        }
  
+       if (reg & FXLS8962AF_INT_STATUS_SRC_SDCD_OT) {
+               ret = fxls8962af_event_interrupt(indio_dev);
+               if (ret < 0)
+                       return IRQ_NONE;
+               return IRQ_HANDLED;
+       }
        return IRQ_NONE;
  }
  
@@@ -861,6 -1157,7 +1157,7 @@@ int fxls8962af_core_probe(struct devic
        data = iio_priv(indio_dev);
        dev_set_drvdata(dev, indio_dev);
        data->regmap = regmap;
+       data->irq = irq;
  
        ret = iio_read_mount_matrix(dev, &data->orientation);
        if (ret)
        if (ret)
                return ret;
  
+       if (device_property_read_bool(dev, "wakeup-source"))
+               device_init_wakeup(dev, true);
        return devm_iio_device_register(dev, indio_dev);
  }
  EXPORT_SYMBOL_GPL(fxls8962af_core_probe);
@@@ -955,9 -1255,46 +1255,46 @@@ static int __maybe_unused fxls8962af_ru
        return fxls8962af_active(data);
  }
  
+ static int __maybe_unused fxls8962af_suspend(struct device *dev)
+ {
+       struct iio_dev *indio_dev = dev_get_drvdata(dev);
+       struct fxls8962af_data *data = iio_priv(indio_dev);
+       if (device_may_wakeup(dev) && data->enable_event) {
+               enable_irq_wake(data->irq);
+               /*
+                * Disable buffer, as the buffer is so small the device will wake
+                * almost immediately.
+                */
+               if (iio_buffer_enabled(indio_dev))
+                       fxls8962af_buffer_predisable(indio_dev);
+       } else {
+               fxls8962af_runtime_suspend(dev);
+       }
+       return 0;
+ }
+ static int __maybe_unused fxls8962af_resume(struct device *dev)
+ {
+       struct iio_dev *indio_dev = dev_get_drvdata(dev);
+       struct fxls8962af_data *data = iio_priv(indio_dev);
+       if (device_may_wakeup(dev) && data->enable_event) {
+               disable_irq_wake(data->irq);
+               if (iio_buffer_enabled(indio_dev))
+                       fxls8962af_buffer_postenable(indio_dev);
+       } else {
+               fxls8962af_runtime_resume(dev);
+       }
+       return 0;
+ }
  const struct dev_pm_ops fxls8962af_pm_ops = {
-       SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
-                               pm_runtime_force_resume)
+       SET_SYSTEM_SLEEP_PM_OPS(fxls8962af_suspend, fxls8962af_resume)
        SET_RUNTIME_PM_OPS(fxls8962af_runtime_suspend,
                           fxls8962af_runtime_resume, NULL)
  };
index 34ec0c28b2dff6b145445e1aabf5fc89c20ac363,c2705f6124953c2b373857cdfd7cff7f515a9cc8..e939b84cbb561473303f68ed8525dbfeeb53b29d
@@@ -1,8 -1,15 +1,15 @@@
  // SPDX-License-Identifier: GPL-2.0-only
  /*
-  * Aspeed AST2400/2500 ADC
+  * Aspeed AST2400/2500/2600 ADC
   *
   * Copyright (C) 2017 Google, Inc.
+  * Copyright (C) 2021 Aspeed Technology Inc.
+  *
+  * ADC clock formula:
+  * Ast2400/Ast2500:
+  * clock period = period of PCLK * 2 * (ADC0C[31:17] + 1) * (ADC0C[9:0] + 1)
+  * Ast2600:
+  * clock period = period of PCLK * 2 * (ADC0C[15:0] + 1)
   */
  
  #include <linux/clk.h>
  #include <linux/module.h>
  #include <linux/of_platform.h>
  #include <linux/platform_device.h>
+ #include <linux/regulator/consumer.h>
  #include <linux/reset.h>
  #include <linux/spinlock.h>
  #include <linux/types.h>
+ #include <linux/bitfield.h>
+ #include <linux/regmap.h>
+ #include <linux/mfd/syscon.h>
  
  #include <linux/iio/iio.h>
  #include <linux/iio/driver.h>
  #define ASPEED_REG_INTERRUPT_CONTROL  0x04
  #define ASPEED_REG_VGA_DETECT_CONTROL 0x08
  #define ASPEED_REG_CLOCK_CONTROL      0x0C
- #define ASPEED_REG_MAX                        0xC0
- #define ASPEED_OPERATION_MODE_POWER_DOWN      (0x0 << 1)
- #define ASPEED_OPERATION_MODE_STANDBY         (0x1 << 1)
- #define ASPEED_OPERATION_MODE_NORMAL          (0x7 << 1)
- #define ASPEED_ENGINE_ENABLE          BIT(0)
- #define ASPEED_ADC_CTRL_INIT_RDY      BIT(8)
+ #define ASPEED_REG_COMPENSATION_TRIM  0xC4
+ /*
+  * The register offset between 0xC8~0xCC can be read and won't affect the
+  * hardware logic in each version of ADC.
+  */
+ #define ASPEED_REG_MAX                        0xD0
+ #define ASPEED_ADC_ENGINE_ENABLE              BIT(0)
+ #define ASPEED_ADC_OP_MODE                    GENMASK(3, 1)
+ #define ASPEED_ADC_OP_MODE_PWR_DOWN           0
+ #define ASPEED_ADC_OP_MODE_STANDBY            1
+ #define ASPEED_ADC_OP_MODE_NORMAL             7
+ #define ASPEED_ADC_CTRL_COMPENSATION          BIT(4)
+ #define ASPEED_ADC_AUTO_COMPENSATION          BIT(5)
+ /*
+  * Bit 6 determines not only the reference voltage range but also the dividing
+  * circuit for battery sensing.
+  */
+ #define ASPEED_ADC_REF_VOLTAGE                        GENMASK(7, 6)
+ #define ASPEED_ADC_REF_VOLTAGE_2500mV         0
+ #define ASPEED_ADC_REF_VOLTAGE_1200mV         1
+ #define ASPEED_ADC_REF_VOLTAGE_EXT_HIGH               2
+ #define ASPEED_ADC_REF_VOLTAGE_EXT_LOW                3
+ #define ASPEED_ADC_BAT_SENSING_DIV            BIT(6)
+ #define ASPEED_ADC_BAT_SENSING_DIV_2_3                0
+ #define ASPEED_ADC_BAT_SENSING_DIV_1_3                1
+ #define ASPEED_ADC_CTRL_INIT_RDY              BIT(8)
+ #define ASPEED_ADC_CH7_MODE                   BIT(12)
+ #define ASPEED_ADC_CH7_NORMAL                 0
+ #define ASPEED_ADC_CH7_BAT                    1
+ #define ASPEED_ADC_BAT_SENSING_ENABLE         BIT(13)
+ #define ASPEED_ADC_CTRL_CHANNEL                       GENMASK(31, 16)
+ #define ASPEED_ADC_CTRL_CHANNEL_ENABLE(ch)    FIELD_PREP(ASPEED_ADC_CTRL_CHANNEL, BIT(ch))
  
  #define ASPEED_ADC_INIT_POLLING_TIME  500
  #define ASPEED_ADC_INIT_TIMEOUT               500000
+ /*
+  * When the sampling rate is too high, the ADC may not have enough charging
+  * time, resulting in a low voltage value. Thus, the default uses a slow
+  * sampling rate for most use cases.
+  */
+ #define ASPEED_ADC_DEF_SAMPLING_RATE  65000
+ struct aspeed_adc_trim_locate {
+       const unsigned int offset;
+       const unsigned int field;
+ };
  
  struct aspeed_adc_model_data {
        const char *model_name;
        unsigned int min_sampling_rate; // Hz
        unsigned int max_sampling_rate; // Hz
-       unsigned int vref_voltage;      // mV
+       unsigned int vref_fixed_mv;
        bool wait_init_sequence;
+       bool need_prescaler;
+       bool bat_sense_sup;
+       u8 scaler_bit_width;
+       unsigned int num_channels;
+       const struct aspeed_adc_trim_locate *trim_locate;
+ };
+ struct adc_gain {
+       u8 mult;
+       u8 div;
  };
  
  struct aspeed_adc_data {
        struct device           *dev;
+       const struct aspeed_adc_model_data *model_data;
+       struct regulator        *regulator;
        void __iomem            *base;
        spinlock_t              clk_lock;
+       struct clk_hw           *fixed_div_clk;
        struct clk_hw           *clk_prescaler;
        struct clk_hw           *clk_scaler;
        struct reset_control    *rst;
+       int                     vref_mv;
+       u32                     sample_period_ns;
+       int                     cv;
+       bool                    battery_sensing;
+       struct adc_gain         battery_mode_gain;
  };
  
  #define ASPEED_CHAN(_idx, _data_reg_addr) {                   \
        .address = (_data_reg_addr),                            \
        .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),           \
        .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) |  \
-                               BIT(IIO_CHAN_INFO_SAMP_FREQ),   \
+                               BIT(IIO_CHAN_INFO_SAMP_FREQ) |  \
+                               BIT(IIO_CHAN_INFO_OFFSET),      \
  }
  
  static const struct iio_chan_spec aspeed_adc_iio_channels[] = {
        ASPEED_CHAN(15, 0x2E),
  };
  
+ #define ASPEED_BAT_CHAN(_idx, _data_reg_addr) {                                       \
+               .type = IIO_VOLTAGE,                                            \
+               .indexed = 1,                                                   \
+               .channel = (_idx),                                              \
+               .address = (_data_reg_addr),                                    \
+               .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |                  \
+                                     BIT(IIO_CHAN_INFO_OFFSET),                \
+               .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) |          \
+                                           BIT(IIO_CHAN_INFO_SAMP_FREQ),       \
+ }
+ static const struct iio_chan_spec aspeed_adc_iio_bat_channels[] = {
+       ASPEED_CHAN(0, 0x10),
+       ASPEED_CHAN(1, 0x12),
+       ASPEED_CHAN(2, 0x14),
+       ASPEED_CHAN(3, 0x16),
+       ASPEED_CHAN(4, 0x18),
+       ASPEED_CHAN(5, 0x1A),
+       ASPEED_CHAN(6, 0x1C),
+       ASPEED_BAT_CHAN(7, 0x1E),
+ };
+ static int aspeed_adc_set_trim_data(struct iio_dev *indio_dev)
+ {
+       struct device_node *syscon;
+       struct regmap *scu;
+       u32 scu_otp, trimming_val;
+       struct aspeed_adc_data *data = iio_priv(indio_dev);
+       syscon = of_find_node_by_name(NULL, "syscon");
+       if (syscon == NULL) {
+               dev_warn(data->dev, "Couldn't find syscon node\n");
+               return -EOPNOTSUPP;
+       }
+       scu = syscon_node_to_regmap(syscon);
+       if (IS_ERR(scu)) {
+               dev_warn(data->dev, "Failed to get syscon regmap\n");
+               return -EOPNOTSUPP;
+       }
+       if (data->model_data->trim_locate) {
+               if (regmap_read(scu, data->model_data->trim_locate->offset,
+                               &scu_otp)) {
+                       dev_warn(data->dev,
+                                "Failed to get adc trimming data\n");
+                       trimming_val = 0x8;
+               } else {
+                       trimming_val =
+                               ((scu_otp) &
+                                (data->model_data->trim_locate->field)) >>
+                               __ffs(data->model_data->trim_locate->field);
+               }
+               dev_dbg(data->dev,
+                       "trimming val = %d, offset = %08x, fields = %08x\n",
+                       trimming_val, data->model_data->trim_locate->offset,
+                       data->model_data->trim_locate->field);
+               writel(trimming_val, data->base + ASPEED_REG_COMPENSATION_TRIM);
+       }
+       return 0;
+ }
+ static int aspeed_adc_compensation(struct iio_dev *indio_dev)
+ {
+       struct aspeed_adc_data *data = iio_priv(indio_dev);
+       u32 index, adc_raw = 0;
+       u32 adc_engine_control_reg_val;
+       adc_engine_control_reg_val =
+               readl(data->base + ASPEED_REG_ENGINE_CONTROL);
+       adc_engine_control_reg_val &= ~ASPEED_ADC_OP_MODE;
+       adc_engine_control_reg_val |=
+               (FIELD_PREP(ASPEED_ADC_OP_MODE, ASPEED_ADC_OP_MODE_NORMAL) |
+                ASPEED_ADC_ENGINE_ENABLE);
+       /*
+        * Enable compensating sensing:
+        * After that, the input voltage of ADC will force to half of the reference
+        * voltage. So the expected reading raw data will become half of the max
+        * value. We can get compensating value = 0x200 - ADC read raw value.
+        * It is recommended to average at least 10 samples to get a final CV.
+        */
+       writel(adc_engine_control_reg_val | ASPEED_ADC_CTRL_COMPENSATION |
+                      ASPEED_ADC_CTRL_CHANNEL_ENABLE(0),
+              data->base + ASPEED_REG_ENGINE_CONTROL);
+       /*
+        * After enable compensating sensing mode need to wait some time for ADC stable
+        * Experiment result is 1ms.
+        */
+       mdelay(1);
+       for (index = 0; index < 16; index++) {
+               /*
+                * Waiting for the sampling period ensures that the value acquired
+                * is fresh each time.
+                */
+               ndelay(data->sample_period_ns);
+               adc_raw += readw(data->base + aspeed_adc_iio_channels[0].address);
+       }
+       adc_raw >>= 4;
+       data->cv = BIT(ASPEED_RESOLUTION_BITS - 1) - adc_raw;
+       writel(adc_engine_control_reg_val,
+              data->base + ASPEED_REG_ENGINE_CONTROL);
+       dev_dbg(data->dev, "Compensating value = %d\n", data->cv);
+       return 0;
+ }
+ static int aspeed_adc_set_sampling_rate(struct iio_dev *indio_dev, u32 rate)
+ {
+       struct aspeed_adc_data *data = iio_priv(indio_dev);
+       if (rate < data->model_data->min_sampling_rate ||
+           rate > data->model_data->max_sampling_rate)
+               return -EINVAL;
+       /* Each sampling needs 12 clocks to convert.*/
+       clk_set_rate(data->clk_scaler->clk, rate * ASPEED_CLOCKS_PER_SAMPLE);
+       rate = clk_get_rate(data->clk_scaler->clk);
+       data->sample_period_ns = DIV_ROUND_UP_ULL(
+               (u64)NSEC_PER_SEC * ASPEED_CLOCKS_PER_SAMPLE, rate);
+       dev_dbg(data->dev, "Adc clock = %d sample period = %d ns", rate,
+               data->sample_period_ns);
+       return 0;
+ }
  static int aspeed_adc_read_raw(struct iio_dev *indio_dev,
                               struct iio_chan_spec const *chan,
                               int *val, int *val2, long mask)
  {
        struct aspeed_adc_data *data = iio_priv(indio_dev);
-       const struct aspeed_adc_model_data *model_data =
-                       of_device_get_match_data(data->dev);
+       u32 adc_engine_control_reg_val;
  
        switch (mask) {
        case IIO_CHAN_INFO_RAW:
-               *val = readw(data->base + chan->address);
+               if (data->battery_sensing && chan->channel == 7) {
+                       adc_engine_control_reg_val =
+                               readl(data->base + ASPEED_REG_ENGINE_CONTROL);
+                       writel(adc_engine_control_reg_val |
+                                      FIELD_PREP(ASPEED_ADC_CH7_MODE,
+                                                 ASPEED_ADC_CH7_BAT) |
+                                      ASPEED_ADC_BAT_SENSING_ENABLE,
+                              data->base + ASPEED_REG_ENGINE_CONTROL);
+                       /*
+                        * After enable battery sensing mode need to wait some time for adc stable
+                        * Experiment result is 1ms.
+                        */
+                       mdelay(1);
+                       *val = readw(data->base + chan->address);
+                       *val = (*val * data->battery_mode_gain.mult) /
+                              data->battery_mode_gain.div;
+                       /* Restore control register value */
+                       writel(adc_engine_control_reg_val,
+                              data->base + ASPEED_REG_ENGINE_CONTROL);
+               } else
+                       *val = readw(data->base + chan->address);
+               return IIO_VAL_INT;
+       case IIO_CHAN_INFO_OFFSET:
+               if (data->battery_sensing && chan->channel == 7)
+                       *val = (data->cv * data->battery_mode_gain.mult) /
+                              data->battery_mode_gain.div;
+               else
+                       *val = data->cv;
                return IIO_VAL_INT;
  
        case IIO_CHAN_INFO_SCALE:
-               *val = model_data->vref_voltage;
+               *val = data->vref_mv;
                *val2 = ASPEED_RESOLUTION_BITS;
                return IIO_VAL_FRACTIONAL_LOG2;
  
@@@ -119,19 -333,9 +333,9 @@@ static int aspeed_adc_write_raw(struct 
                                struct iio_chan_spec const *chan,
                                int val, int val2, long mask)
  {
-       struct aspeed_adc_data *data = iio_priv(indio_dev);
-       const struct aspeed_adc_model_data *model_data =
-                       of_device_get_match_data(data->dev);
        switch (mask) {
        case IIO_CHAN_INFO_SAMP_FREQ:
-               if (val < model_data->min_sampling_rate ||
-                       val > model_data->max_sampling_rate)
-                       return -EINVAL;
-               clk_set_rate(data->clk_scaler->clk,
-                               val * ASPEED_CLOCKS_PER_SAMPLE);
-               return 0;
+               return aspeed_adc_set_sampling_rate(indio_dev, val);
  
        case IIO_CHAN_INFO_SCALE:
        case IIO_CHAN_INFO_RAW:
@@@ -168,14 -372,119 +372,119 @@@ static const struct iio_info aspeed_adc
        .debugfs_reg_access = aspeed_adc_reg_access,
  };
  
+ static void aspeed_adc_unregister_fixed_divider(void *data)
+ {
+       struct clk_hw *clk = data;
+       clk_hw_unregister_fixed_factor(clk);
+ }
+ static void aspeed_adc_reset_assert(void *data)
+ {
+       struct reset_control *rst = data;
+       reset_control_assert(rst);
+ }
+ static void aspeed_adc_clk_disable_unprepare(void *data)
+ {
+       struct clk *clk = data;
+       clk_disable_unprepare(clk);
+ }
+ static void aspeed_adc_power_down(void *data)
+ {
+       struct aspeed_adc_data *priv_data = data;
+       writel(FIELD_PREP(ASPEED_ADC_OP_MODE, ASPEED_ADC_OP_MODE_PWR_DOWN),
+              priv_data->base + ASPEED_REG_ENGINE_CONTROL);
+ }
+ static void aspeed_adc_reg_disable(void *data)
+ {
+       struct regulator *reg = data;
+       regulator_disable(reg);
+ }
+ static int aspeed_adc_vref_config(struct iio_dev *indio_dev)
+ {
+       struct aspeed_adc_data *data = iio_priv(indio_dev);
+       int ret;
+       u32 adc_engine_control_reg_val;
+       if (data->model_data->vref_fixed_mv) {
+               data->vref_mv = data->model_data->vref_fixed_mv;
+               return 0;
+       }
+       adc_engine_control_reg_val =
+               readl(data->base + ASPEED_REG_ENGINE_CONTROL);
+       data->regulator = devm_regulator_get_optional(data->dev, "vref");
+       if (!IS_ERR(data->regulator)) {
+               ret = regulator_enable(data->regulator);
+               if (ret)
+                       return ret;
+               ret = devm_add_action_or_reset(
+                       data->dev, aspeed_adc_reg_disable, data->regulator);
+               if (ret)
+                       return ret;
+               data->vref_mv = regulator_get_voltage(data->regulator);
+               /* Conversion from uV to mV */
+               data->vref_mv /= 1000;
+               if ((data->vref_mv >= 1550) && (data->vref_mv <= 2700))
+                       writel(adc_engine_control_reg_val |
+                               FIELD_PREP(
+                                       ASPEED_ADC_REF_VOLTAGE,
+                                       ASPEED_ADC_REF_VOLTAGE_EXT_HIGH),
+                       data->base + ASPEED_REG_ENGINE_CONTROL);
+               else if ((data->vref_mv >= 900) && (data->vref_mv <= 1650))
+                       writel(adc_engine_control_reg_val |
+                               FIELD_PREP(
+                                       ASPEED_ADC_REF_VOLTAGE,
+                                       ASPEED_ADC_REF_VOLTAGE_EXT_LOW),
+                       data->base + ASPEED_REG_ENGINE_CONTROL);
+               else {
+                       dev_err(data->dev, "Regulator voltage %d not support",
+                               data->vref_mv);
+                       return -EOPNOTSUPP;
+               }
+       } else {
+               if (PTR_ERR(data->regulator) != -ENODEV)
+                       return PTR_ERR(data->regulator);
+               data->vref_mv = 2500000;
+               of_property_read_u32(data->dev->of_node,
+                                    "aspeed,int-vref-microvolt",
+                                    &data->vref_mv);
+               /* Conversion from uV to mV */
+               data->vref_mv /= 1000;
+               if (data->vref_mv == 2500)
+                       writel(adc_engine_control_reg_val |
+                               FIELD_PREP(ASPEED_ADC_REF_VOLTAGE,
+                                               ASPEED_ADC_REF_VOLTAGE_2500mV),
+                       data->base + ASPEED_REG_ENGINE_CONTROL);
+               else if (data->vref_mv == 1200)
+                       writel(adc_engine_control_reg_val |
+                               FIELD_PREP(ASPEED_ADC_REF_VOLTAGE,
+                                               ASPEED_ADC_REF_VOLTAGE_1200mV),
+                       data->base + ASPEED_REG_ENGINE_CONTROL);
+               else {
+                       dev_err(data->dev, "Voltage %d not support", data->vref_mv);
+                       return -EOPNOTSUPP;
+               }
+       }
+       return 0;
+ }
  static int aspeed_adc_probe(struct platform_device *pdev)
  {
        struct iio_dev *indio_dev;
        struct aspeed_adc_data *data;
-       const struct aspeed_adc_model_data *model_data;
-       const char *clk_parent_name;
        int ret;
        u32 adc_engine_control_reg_val;
+       unsigned long scaler_flags = 0;
+       char clk_name[32], clk_parent_name[32];
  
        indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*data));
        if (!indio_dev)
  
        data = iio_priv(indio_dev);
        data->dev = &pdev->dev;
+       data->model_data = of_device_get_match_data(&pdev->dev);
 +      platform_set_drvdata(pdev, indio_dev);
  
        data->base = devm_platform_ioremap_resource(pdev, 0);
        if (IS_ERR(data->base))
  
        /* Register ADC clock prescaler with source specified by device tree. */
        spin_lock_init(&data->clk_lock);
-       clk_parent_name = of_clk_get_parent_name(pdev->dev.of_node, 0);
-       data->clk_prescaler = clk_hw_register_divider(
-                               &pdev->dev, "prescaler", clk_parent_name, 0,
-                               data->base + ASPEED_REG_CLOCK_CONTROL,
-                               17, 15, 0, &data->clk_lock);
-       if (IS_ERR(data->clk_prescaler))
-               return PTR_ERR(data->clk_prescaler);
+       snprintf(clk_parent_name, ARRAY_SIZE(clk_parent_name), "%s",
+                of_clk_get_parent_name(pdev->dev.of_node, 0));
+       snprintf(clk_name, ARRAY_SIZE(clk_name), "%s-fixed-div",
+                data->model_data->model_name);
+       data->fixed_div_clk = clk_hw_register_fixed_factor(
+               &pdev->dev, clk_name, clk_parent_name, 0, 1, 2);
+       if (IS_ERR(data->fixed_div_clk))
+               return PTR_ERR(data->fixed_div_clk);
+       ret = devm_add_action_or_reset(data->dev,
+                                      aspeed_adc_unregister_fixed_divider,
+                                      data->fixed_div_clk);
+       if (ret)
+               return ret;
+       snprintf(clk_parent_name, ARRAY_SIZE(clk_parent_name), clk_name);
+       if (data->model_data->need_prescaler) {
+               snprintf(clk_name, ARRAY_SIZE(clk_name), "%s-prescaler",
+                        data->model_data->model_name);
+               data->clk_prescaler = devm_clk_hw_register_divider(
+                       &pdev->dev, clk_name, clk_parent_name, 0,
+                       data->base + ASPEED_REG_CLOCK_CONTROL, 17, 15, 0,
+                       &data->clk_lock);
+               if (IS_ERR(data->clk_prescaler))
+                       return PTR_ERR(data->clk_prescaler);
+               snprintf(clk_parent_name, ARRAY_SIZE(clk_parent_name),
+                        clk_name);
+               scaler_flags = CLK_SET_RATE_PARENT;
+       }
        /*
         * Register ADC clock scaler downstream from the prescaler. Allow rate
         * setting to adjust the prescaler as well.
         */
-       data->clk_scaler = clk_hw_register_divider(
-                               &pdev->dev, "scaler", "prescaler",
-                               CLK_SET_RATE_PARENT,
-                               data->base + ASPEED_REG_CLOCK_CONTROL,
-                               0, 10, 0, &data->clk_lock);
-       if (IS_ERR(data->clk_scaler)) {
-               ret = PTR_ERR(data->clk_scaler);
-               goto scaler_error;
-       }
-       data->rst = devm_reset_control_get_exclusive(&pdev->dev, NULL);
+       snprintf(clk_name, ARRAY_SIZE(clk_name), "%s-scaler",
+                data->model_data->model_name);
+       data->clk_scaler = devm_clk_hw_register_divider(
+               &pdev->dev, clk_name, clk_parent_name, scaler_flags,
+               data->base + ASPEED_REG_CLOCK_CONTROL, 0,
+               data->model_data->scaler_bit_width, 0, &data->clk_lock);
+       if (IS_ERR(data->clk_scaler))
+               return PTR_ERR(data->clk_scaler);
+       data->rst = devm_reset_control_get_shared(&pdev->dev, NULL);
        if (IS_ERR(data->rst)) {
                dev_err(&pdev->dev,
                        "invalid or missing reset controller device tree entry");
-               ret = PTR_ERR(data->rst);
-               goto reset_error;
+               return PTR_ERR(data->rst);
        }
        reset_control_deassert(data->rst);
  
-       model_data = of_device_get_match_data(&pdev->dev);
+       ret = devm_add_action_or_reset(data->dev, aspeed_adc_reset_assert,
+                                      data->rst);
+       if (ret)
+               return ret;
  
-       if (model_data->wait_init_sequence) {
-               /* Enable engine in normal mode. */
-               writel(ASPEED_OPERATION_MODE_NORMAL | ASPEED_ENGINE_ENABLE,
-                      data->base + ASPEED_REG_ENGINE_CONTROL);
+       ret = aspeed_adc_vref_config(indio_dev);
+       if (ret)
+               return ret;
  
+       if (of_find_property(data->dev->of_node, "aspeed,trim-data-valid",
+                            NULL)) {
+               ret = aspeed_adc_set_trim_data(indio_dev);
+               if (ret)
+                       return ret;
+       }
+       if (of_find_property(data->dev->of_node, "aspeed,battery-sensing",
+                            NULL)) {
+               if (data->model_data->bat_sense_sup) {
+                       data->battery_sensing = 1;
+                       if (readl(data->base + ASPEED_REG_ENGINE_CONTROL) &
+                           ASPEED_ADC_BAT_SENSING_DIV) {
+                               data->battery_mode_gain.mult = 3;
+                               data->battery_mode_gain.div = 1;
+                       } else {
+                               data->battery_mode_gain.mult = 3;
+                               data->battery_mode_gain.div = 2;
+                       }
+               } else
+                       dev_warn(&pdev->dev,
+                                "Failed to enable battery-sensing mode\n");
+       }
+       ret = clk_prepare_enable(data->clk_scaler->clk);
+       if (ret)
+               return ret;
+       ret = devm_add_action_or_reset(data->dev,
+                                      aspeed_adc_clk_disable_unprepare,
+                                      data->clk_scaler->clk);
+       if (ret)
+               return ret;
+       ret = aspeed_adc_set_sampling_rate(indio_dev,
+                                          ASPEED_ADC_DEF_SAMPLING_RATE);
+       if (ret)
+               return ret;
+       adc_engine_control_reg_val =
+               readl(data->base + ASPEED_REG_ENGINE_CONTROL);
+       adc_engine_control_reg_val |=
+               FIELD_PREP(ASPEED_ADC_OP_MODE, ASPEED_ADC_OP_MODE_NORMAL) |
+               ASPEED_ADC_ENGINE_ENABLE;
+       /* Enable engine in normal mode. */
+       writel(adc_engine_control_reg_val,
+              data->base + ASPEED_REG_ENGINE_CONTROL);
+       ret = devm_add_action_or_reset(data->dev, aspeed_adc_power_down,
+                                       data);
+       if (ret)
+               return ret;
+       if (data->model_data->wait_init_sequence) {
                /* Wait for initial sequence complete. */
                ret = readl_poll_timeout(data->base + ASPEED_REG_ENGINE_CONTROL,
                                         adc_engine_control_reg_val,
                                         ASPEED_ADC_INIT_POLLING_TIME,
                                         ASPEED_ADC_INIT_TIMEOUT);
                if (ret)
-                       goto poll_timeout_error;
+                       return ret;
        }
  
+       aspeed_adc_compensation(indio_dev);
        /* Start all channels in normal mode. */
-       ret = clk_prepare_enable(data->clk_scaler->clk);
-       if (ret)
-               goto clk_enable_error;
-       adc_engine_control_reg_val = GENMASK(31, 16) |
-               ASPEED_OPERATION_MODE_NORMAL | ASPEED_ENGINE_ENABLE;
+       adc_engine_control_reg_val =
+               readl(data->base + ASPEED_REG_ENGINE_CONTROL);
+       adc_engine_control_reg_val |= ASPEED_ADC_CTRL_CHANNEL;
        writel(adc_engine_control_reg_val,
-               data->base + ASPEED_REG_ENGINE_CONTROL);
+              data->base + ASPEED_REG_ENGINE_CONTROL);
  
-       model_data = of_device_get_match_data(&pdev->dev);
-       indio_dev->name = model_data->model_name;
+       indio_dev->name = data->model_data->model_name;
        indio_dev->info = &aspeed_adc_iio_info;
        indio_dev->modes = INDIO_DIRECT_MODE;
-       indio_dev->channels = aspeed_adc_iio_channels;
-       indio_dev->num_channels = ARRAY_SIZE(aspeed_adc_iio_channels);
-       ret = iio_device_register(indio_dev);
-       if (ret)
-               goto iio_register_error;
-       return 0;
+       indio_dev->channels = data->battery_sensing ?
+                                           aspeed_adc_iio_bat_channels :
+                                           aspeed_adc_iio_channels;
+       indio_dev->num_channels = data->model_data->num_channels;
  
- iio_register_error:
-       writel(ASPEED_OPERATION_MODE_POWER_DOWN,
-               data->base + ASPEED_REG_ENGINE_CONTROL);
-       clk_disable_unprepare(data->clk_scaler->clk);
- clk_enable_error:
- poll_timeout_error:
-       reset_control_assert(data->rst);
- reset_error:
-       clk_hw_unregister_divider(data->clk_scaler);
- scaler_error:
-       clk_hw_unregister_divider(data->clk_prescaler);
+       ret = devm_iio_device_register(data->dev, indio_dev);
        return ret;
  }
  
- static int aspeed_adc_remove(struct platform_device *pdev)
- {
-       struct iio_dev *indio_dev = platform_get_drvdata(pdev);
      struct aspeed_adc_data *data = iio_priv(indio_dev);
+ static const struct aspeed_adc_trim_locate ast2500_adc_trim = {
+       .offset = 0x154,
+       .field = GENMASK(31, 28),
};
  
-       iio_device_unregister(indio_dev);
-       writel(ASPEED_OPERATION_MODE_POWER_DOWN,
-               data->base + ASPEED_REG_ENGINE_CONTROL);
-       clk_disable_unprepare(data->clk_scaler->clk);
-       reset_control_assert(data->rst);
-       clk_hw_unregister_divider(data->clk_scaler);
-       clk_hw_unregister_divider(data->clk_prescaler);
+ static const struct aspeed_adc_trim_locate ast2600_adc0_trim = {
+       .offset = 0x5d0,
+       .field = GENMASK(3, 0),
+ };
  
-       return 0;
- }
+ static const struct aspeed_adc_trim_locate ast2600_adc1_trim = {
+       .offset = 0x5d0,
+       .field = GENMASK(7, 4),
+ };
  
  static const struct aspeed_adc_model_data ast2400_model_data = {
        .model_name = "ast2400-adc",
-       .vref_voltage = 2500, // mV
+       .vref_fixed_mv = 2500,
        .min_sampling_rate = 10000,
        .max_sampling_rate = 500000,
+       .need_prescaler = true,
+       .scaler_bit_width = 10,
+       .num_channels = 16,
  };
  
  static const struct aspeed_adc_model_data ast2500_model_data = {
        .model_name = "ast2500-adc",
-       .vref_voltage = 1800, // mV
+       .vref_fixed_mv = 1800,
        .min_sampling_rate = 1,
        .max_sampling_rate = 1000000,
        .wait_init_sequence = true,
+       .need_prescaler = true,
+       .scaler_bit_width = 10,
+       .num_channels = 16,
+       .trim_locate = &ast2500_adc_trim,
+ };
+ static const struct aspeed_adc_model_data ast2600_adc0_model_data = {
+       .model_name = "ast2600-adc0",
+       .min_sampling_rate = 10000,
+       .max_sampling_rate = 500000,
+       .wait_init_sequence = true,
+       .bat_sense_sup = true,
+       .scaler_bit_width = 16,
+       .num_channels = 8,
+       .trim_locate = &ast2600_adc0_trim,
+ };
+ static const struct aspeed_adc_model_data ast2600_adc1_model_data = {
+       .model_name = "ast2600-adc1",
+       .min_sampling_rate = 10000,
+       .max_sampling_rate = 500000,
+       .wait_init_sequence = true,
+       .bat_sense_sup = true,
+       .scaler_bit_width = 16,
+       .num_channels = 8,
+       .trim_locate = &ast2600_adc1_trim,
  };
  
  static const struct of_device_id aspeed_adc_matches[] = {
        { .compatible = "aspeed,ast2400-adc", .data = &ast2400_model_data },
        { .compatible = "aspeed,ast2500-adc", .data = &ast2500_model_data },
+       { .compatible = "aspeed,ast2600-adc0", .data = &ast2600_adc0_model_data },
+       { .compatible = "aspeed,ast2600-adc1", .data = &ast2600_adc1_model_data },
        {},
  };
  MODULE_DEVICE_TABLE(of, aspeed_adc_matches);
  
  static struct platform_driver aspeed_adc_driver = {
        .probe = aspeed_adc_probe,
-       .remove = aspeed_adc_remove,
        .driver = {
                .name = KBUILD_MODNAME,
                .of_match_table = aspeed_adc_matches,
  module_platform_driver(aspeed_adc_driver);
  
  MODULE_AUTHOR("Rick Altherr <[email protected]>");
- MODULE_DESCRIPTION("Aspeed AST2400/2500 ADC Driver");
+ MODULE_DESCRIPTION("Aspeed AST2400/2500/2600 ADC Driver");
  MODULE_LICENSE("GPL");
index b753658bb41ec0f6d5ecb58f9955607cfaae4b58,cb60b76a4d3aa64e0515a8e7fd5a41e81b39fcf8..4daf1d576c4eed6cc190b30b4f5b73461c4f9b15
@@@ -60,6 -60,9 +60,9 @@@
  #define MAX1027_NAVG_32   (0x03 << 2)
  #define MAX1027_AVG_EN    BIT(4)
  
+ /* Device can achieve 300ksps so we assume a 3.33us conversion delay */
+ #define MAX1027_CONVERSION_UDELAY 4
  enum max1027_id {
        max1027,
        max1029,
@@@ -103,7 -106,7 +106,7 @@@ MODULE_DEVICE_TABLE(of, max1027_adc_dt_
                        .sign = 'u',                                    \
                        .realbits = depth,                              \
                        .storagebits = 16,                              \
 -                      .shift = 2,                                     \
 +                      .shift = (depth == 10) ? 2 : 0,                 \
                        .endianness = IIO_BE,                           \
                },                                                      \
        }
        MAX1027_V_CHAN(11, depth)
  
  #define MAX1X31_CHANNELS(depth)                       \
 -      MAX1X27_CHANNELS(depth),                \
        MAX1X29_CHANNELS(depth),                \
        MAX1027_V_CHAN(12, depth),              \
        MAX1027_V_CHAN(13, depth),              \
@@@ -172,18 -176,53 +175,53 @@@ static const struct iio_chan_spec max12
        MAX1X31_CHANNELS(12),
  };
  
+ /*
+  * These devices are able to scan from 0 to N, N being the highest voltage
+  * channel requested by the user. The temperature can be included or not,
+  * but cannot be retrieved alone. Based on the below
+  * ->available_scan_masks, the core will select the most appropriate
+  * ->active_scan_mask and the "minimum" number of channels will be
+  * scanned and pushed to the buffers.
+  *
+  * For example, if the user wants channels 1, 4 and 5, all channels from
+  * 0 to 5 will be scanned and pushed to the IIO buffers. The core will then
+  * filter out the unneeded samples based on the ->active_scan_mask that has
+  * been selected and only channels 1, 4 and 5 will be available to the user
+  * in the shared buffer.
+  */
+ #define MAX1X27_SCAN_MASK_TEMP BIT(0)
+ #define MAX1X27_SCAN_MASKS(temp)                                      \
+       GENMASK(1, 1 - (temp)), GENMASK(2, 1 - (temp)),                 \
+       GENMASK(3, 1 - (temp)), GENMASK(4, 1 - (temp)),                 \
+       GENMASK(5, 1 - (temp)), GENMASK(6, 1 - (temp)),                 \
+       GENMASK(7, 1 - (temp)), GENMASK(8, 1 - (temp))
+ #define MAX1X29_SCAN_MASKS(temp)                                      \
+       MAX1X27_SCAN_MASKS(temp),                                       \
+       GENMASK(9, 1 - (temp)), GENMASK(10, 1 - (temp)),                \
+       GENMASK(11, 1 - (temp)), GENMASK(12, 1 - (temp))
+ #define MAX1X31_SCAN_MASKS(temp)                                      \
+       MAX1X29_SCAN_MASKS(temp),                                       \
+       GENMASK(13, 1 - (temp)), GENMASK(14, 1 - (temp)),               \
+       GENMASK(15, 1 - (temp)), GENMASK(16, 1 - (temp))
  static const unsigned long max1027_available_scan_masks[] = {
-       0x000001ff,
+       MAX1X27_SCAN_MASKS(0),
+       MAX1X27_SCAN_MASKS(1),
        0x00000000,
  };
  
  static const unsigned long max1029_available_scan_masks[] = {
-       0x00001fff,
+       MAX1X29_SCAN_MASKS(0),
+       MAX1X29_SCAN_MASKS(1),
        0x00000000,
  };
  
  static const unsigned long max1031_available_scan_masks[] = {
-       0x0001ffff,
+       MAX1X31_SCAN_MASKS(0),
+       MAX1X31_SCAN_MASKS(1),
        0x00000000,
  };
  
@@@ -232,10 -271,65 +270,65 @@@ struct max1027_state 
        struct iio_trigger              *trig;
        __be16                          *buffer;
        struct mutex                    lock;
+       struct completion               complete;
  
        u8                              reg ____cacheline_aligned;
  };
  
+ static int max1027_wait_eoc(struct iio_dev *indio_dev)
+ {
+       struct max1027_state *st = iio_priv(indio_dev);
+       unsigned int conversion_time = MAX1027_CONVERSION_UDELAY;
+       int ret;
+       if (st->spi->irq) {
+               ret = wait_for_completion_timeout(&st->complete,
+                                                 msecs_to_jiffies(1000));
+               reinit_completion(&st->complete);
+               if (!ret)
+                       return -ETIMEDOUT;
+       } else {
+               if (indio_dev->active_scan_mask)
+                       conversion_time *= hweight32(*indio_dev->active_scan_mask);
+               usleep_range(conversion_time, conversion_time * 2);
+       }
+       return 0;
+ }
+ /* Scan from chan 0 to the highest requested channel. Include temperature on demand. */
+ static int max1027_configure_chans_and_start(struct iio_dev *indio_dev)
+ {
+       struct max1027_state *st = iio_priv(indio_dev);
+       st->reg = MAX1027_CONV_REG | MAX1027_SCAN_0_N;
+       st->reg |= MAX1027_CHAN(fls(*indio_dev->active_scan_mask) - 2);
+       if (*indio_dev->active_scan_mask & MAX1X27_SCAN_MASK_TEMP)
+               st->reg |= MAX1027_TEMP;
+       return spi_write(st->spi, &st->reg, 1);
+ }
+ static int max1027_enable_trigger(struct iio_dev *indio_dev, bool enable)
+ {
+       struct max1027_state *st = iio_priv(indio_dev);
+       st->reg = MAX1027_SETUP_REG | MAX1027_REF_MODE2;
+       /*
+        * Start acquisition on:
+        * MODE0: external hardware trigger wired to the cnvst input pin
+        * MODE2: conversion register write
+        */
+       if (enable)
+               st->reg |= MAX1027_CKS_MODE0;
+       else
+               st->reg |= MAX1027_CKS_MODE2;
+       return spi_write(st->spi, &st->reg, 1);
+ }
  static int max1027_read_single_value(struct iio_dev *indio_dev,
                                     struct iio_chan_spec const *chan,
                                     int *val)
        int ret;
        struct max1027_state *st = iio_priv(indio_dev);
  
-       if (iio_buffer_enabled(indio_dev)) {
-               dev_warn(&indio_dev->dev, "trigger mode already enabled");
-               return -EBUSY;
-       }
-       /* Start acquisition on conversion register write */
-       st->reg = MAX1027_SETUP_REG | MAX1027_REF_MODE2 | MAX1027_CKS_MODE2;
-       ret = spi_write(st->spi, &st->reg, 1);
-       if (ret < 0) {
-               dev_err(&indio_dev->dev,
-                       "Failed to configure setup register\n");
+       ret = iio_device_claim_direct_mode(indio_dev);
+       if (ret)
                return ret;
-       }
  
        /* Configure conversion register with the requested chan */
        st->reg = MAX1027_CONV_REG | MAX1027_CHAN(chan->channel) |
        if (ret < 0) {
                dev_err(&indio_dev->dev,
                        "Failed to configure conversion register\n");
+               iio_device_release_direct_mode(indio_dev);
                return ret;
        }
  
        /*
         * For an unknown reason, when we use the mode "10" (write
         * conversion register), the interrupt doesn't occur every time.
-        * So we just wait 1 ms.
+        * So we just wait the maximum conversion time and deliver the value.
         */
-       mdelay(1);
+       ret = max1027_wait_eoc(indio_dev);
+       if (ret)
+               return ret;
  
        /* Read result */
        ret = spi_read(st->spi, st->buffer, (chan->type == IIO_TEMP) ? 4 : 2);
+       iio_device_release_direct_mode(indio_dev);
        if (ret < 0)
                return ret;
  
@@@ -327,8 -417,8 +416,8 @@@ static int max1027_read_raw(struct iio_
  }
  
  static int max1027_debugfs_reg_access(struct iio_dev *indio_dev,
-                                     unsigned reg, unsigned writeval,
-                                     unsigned *readval)
+                                     unsigned int reg, unsigned int writeval,
+                                     unsigned int *readval)
  {
        struct max1027_state *st = iio_priv(indio_dev);
        u8 *val = (u8 *)st->buffer;
        return spi_write(st->spi, val, 1);
  }
  
- static int max1027_validate_trigger(struct iio_dev *indio_dev,
-                                   struct iio_trigger *trig)
+ static int max1027_set_cnvst_trigger_state(struct iio_trigger *trig, bool state)
  {
-       struct max1027_state *st = iio_priv(indio_dev);
+       struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig);
+       int ret;
+       /*
+        * In order to disable the convst trigger, start acquisition on
+        * conversion register write, which basically disables triggering
+        * conversions upon cnvst changes and thus has the effect of disabling
+        * the external hardware trigger.
+        */
+       ret = max1027_enable_trigger(indio_dev, state);
+       if (ret)
+               return ret;
  
-       if (st->trig != trig)
-               return -EINVAL;
+       if (state) {
+               ret = max1027_configure_chans_and_start(indio_dev);
+               if (ret)
+                       return ret;
+       }
  
        return 0;
  }
  
- static int max1027_set_trigger_state(struct iio_trigger *trig, bool state)
+ static int max1027_read_scan(struct iio_dev *indio_dev)
  {
-       struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig);
        struct max1027_state *st = iio_priv(indio_dev);
+       unsigned int scanned_chans;
        int ret;
  
-       if (state) {
-               /* Start acquisition on cnvst */
-               st->reg = MAX1027_SETUP_REG | MAX1027_CKS_MODE0 |
-                         MAX1027_REF_MODE2;
-               ret = spi_write(st->spi, &st->reg, 1);
-               if (ret < 0)
-                       return ret;
+       scanned_chans = fls(*indio_dev->active_scan_mask) - 1;
+       if (*indio_dev->active_scan_mask & MAX1X27_SCAN_MASK_TEMP)
+               scanned_chans++;
  
-               /* Scan from 0 to max */
-               st->reg = MAX1027_CONV_REG | MAX1027_CHAN(0) |
-                         MAX1027_SCAN_N_M | MAX1027_TEMP;
-               ret = spi_write(st->spi, &st->reg, 1);
-               if (ret < 0)
-                       return ret;
-       } else {
-               /* Start acquisition on conversion register write */
-               st->reg = MAX1027_SETUP_REG | MAX1027_CKS_MODE2 |
-                         MAX1027_REF_MODE2;
-               ret = spi_write(st->spi, &st->reg, 1);
-               if (ret < 0)
-                       return ret;
-       }
+       /* fill buffer with all channel */
+       ret = spi_read(st->spi, st->buffer, scanned_chans * 2);
+       if (ret < 0)
+               return ret;
+       iio_push_to_buffers(indio_dev, st->buffer);
  
        return 0;
  }
  
+ static irqreturn_t max1027_handler(int irq, void *private)
+ {
+       struct iio_dev *indio_dev = private;
+       struct max1027_state *st = iio_priv(indio_dev);
+       /*
+        * If buffers are disabled (raw read) or when using external triggers,
+        * we just need to unlock the waiters which will then handle the data.
+        *
+        * When using the internal trigger, we must hand-off the choice of the
+        * handler to the core which will then lookup through the interrupt tree
+        * for the right handler registered with iio_triggered_buffer_setup()
+        * to execute, as this trigger might very well be used in conjunction
+        * with another device. The core will then call the relevant handler to
+        * perform the data processing step.
+        */
+       if (!iio_buffer_enabled(indio_dev))
+               complete(&st->complete);
+       else
+               iio_trigger_poll(indio_dev->trig);
+       return IRQ_HANDLED;
+ }
  static irqreturn_t max1027_trigger_handler(int irq, void *private)
  {
        struct iio_poll_func *pf = private;
        struct iio_dev *indio_dev = pf->indio_dev;
-       struct max1027_state *st = iio_priv(indio_dev);
+       int ret;
  
-       pr_debug("%s(irq=%d, private=0x%p)\n", __func__, irq, private);
+       if (!iio_trigger_using_own(indio_dev)) {
+               ret = max1027_configure_chans_and_start(indio_dev);
+               if (ret)
+                       goto out;
  
-       /* fill buffer with all channel */
-       spi_read(st->spi, st->buffer, indio_dev->masklength * 2);
+               /* This is a threaded handler, it is fine to wait for an IRQ */
+               ret = max1027_wait_eoc(indio_dev);
+               if (ret)
+                       goto out;
+       }
  
-       iio_push_to_buffers(indio_dev, st->buffer);
+       ret = max1027_read_scan(indio_dev);
+ out:
+       if (ret)
+               dev_err(&indio_dev->dev,
+                       "Cannot read scanned values (%d)\n", ret);
  
        iio_trigger_notify_done(indio_dev->trig);
  
  
  static const struct iio_trigger_ops max1027_trigger_ops = {
        .validate_device = &iio_trigger_validate_own_device,
-       .set_trigger_state = &max1027_set_trigger_state,
+       .set_trigger_state = &max1027_set_cnvst_trigger_state,
  };
  
  static const struct iio_info max1027_info = {
        .read_raw = &max1027_read_raw,
-       .validate_trigger = &max1027_validate_trigger,
        .debugfs_reg_access = &max1027_debugfs_reg_access,
  };
  
@@@ -421,10 -545,8 +544,8 @@@ static int max1027_probe(struct spi_dev
        struct iio_dev *indio_dev;
        struct max1027_state *st;
  
-       pr_debug("%s: probe(spi = 0x%p)\n", __func__, spi);
        indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
-       if (indio_dev == NULL) {
+       if (!indio_dev) {
                pr_err("Can't allocate iio device\n");
                return -ENOMEM;
        }
        st->info = &max1027_chip_info_tbl[spi_get_device_id(spi)->driver_data];
  
        mutex_init(&st->lock);
+       init_completion(&st->complete);
  
        indio_dev->name = spi_get_device_id(spi)->name;
        indio_dev->info = &max1027_info;
        indio_dev->available_scan_masks = st->info->available_scan_masks;
  
        st->buffer = devm_kmalloc_array(&indio_dev->dev,
-                                 indio_dev->num_channels, 2,
-                                 GFP_KERNEL);
-       if (st->buffer == NULL) {
-               dev_err(&indio_dev->dev, "Can't allocate buffer\n");
+                                       indio_dev->num_channels, 2,
+                                       GFP_KERNEL);
+       if (!st->buffer)
                return -ENOMEM;
+       /* Enable triggered buffers */
+       ret = devm_iio_triggered_buffer_setup(&spi->dev, indio_dev,
+                                             &iio_pollfunc_store_time,
+                                             &max1027_trigger_handler,
+                                             NULL);
+       if (ret < 0) {
+               dev_err(&indio_dev->dev, "Failed to setup buffer\n");
+               return ret;
        }
  
+       /* If there is an EOC interrupt, register the cnvst hardware trigger */
        if (spi->irq) {
-               ret = devm_iio_triggered_buffer_setup(&spi->dev, indio_dev,
-                                                     &iio_pollfunc_store_time,
-                                                     &max1027_trigger_handler,
-                                                     NULL);
-               if (ret < 0) {
-                       dev_err(&indio_dev->dev, "Failed to setup buffer\n");
-                       return ret;
-               }
                st->trig = devm_iio_trigger_alloc(&spi->dev, "%s-trigger",
                                                  indio_dev->name);
-               if (st->trig == NULL) {
+               if (!st->trig) {
                        ret = -ENOMEM;
                        dev_err(&indio_dev->dev,
                                "Failed to allocate iio trigger\n");
                        return ret;
                }
  
-               ret = devm_request_threaded_irq(&spi->dev, spi->irq,
-                                               iio_trigger_generic_data_rdy_poll,
-                                               NULL,
-                                               IRQF_TRIGGER_FALLING,
-                                               spi->dev.driver->name,
-                                               st->trig);
+               ret = devm_request_irq(&spi->dev, spi->irq, max1027_handler,
+                                      IRQF_TRIGGER_FALLING,
+                                      spi->dev.driver->name, indio_dev);
                if (ret < 0) {
                        dev_err(&indio_dev->dev, "Failed to allocate IRQ.\n");
                        return ret;
                return ret;
        }
  
+       /* Assume conversion on register write for now */
+       ret = max1027_enable_trigger(indio_dev, false);
+       if (ret)
+               return ret;
        return devm_iio_device_register(&spi->dev, indio_dev);
  }
  
index 287fff39a927aacf6a043627c4e0cb78f0ba850a,b76d8482bbd5c5de71f322ffa9c5d7862ccb5c3b..ea91d127077df77562e2ee722ff4a7ba0f83381a
@@@ -353,11 -353,10 +353,11 @@@ static int adis16475_set_freq(struct ad
        if (dec > st->info->max_dec)
                dec = st->info->max_dec;
  
 -      ret = adis_write_reg_16(&st->adis, ADIS16475_REG_DEC_RATE, dec);
 +      ret = __adis_write_reg_16(&st->adis, ADIS16475_REG_DEC_RATE, dec);
        if (ret)
                goto error;
  
 +      adis_dev_unlock(&st->adis);
        /*
         * If decimation is used, then gyro and accel data will have meaningful
         * bits on the LSB registers. This info is used on the trigger handler.
@@@ -607,20 -606,6 +607,6 @@@ static const char * const adis16475_sta
        [ADIS16475_DIAG_STAT_CLK] = "Clock error",
  };
  
- static int adis16475_enable_irq(struct adis *adis, bool enable)
- {
-       /*
-        * There is no way to gate the data-ready signal internally inside the
-        * ADIS16475. We can only control it's polarity...
-        */
-       if (enable)
-               enable_irq(adis->spi->irq);
-       else
-               disable_irq(adis->spi->irq);
-       return 0;
- }
  #define ADIS16475_DATA(_prod_id, _timeouts)                           \
  {                                                                     \
        .msc_ctrl_reg = ADIS16475_REG_MSG_CTRL,                         \
                BIT(ADIS16475_DIAG_STAT_SENSOR) |                       \
                BIT(ADIS16475_DIAG_STAT_MEMORY) |                       \
                BIT(ADIS16475_DIAG_STAT_CLK),                           \
-       .enable_irq = adis16475_enable_irq,                             \
+       .unmasked_drdy = true,                                          \
        .timeouts = (_timeouts),                                        \
        .burst_reg_cmd = ADIS16475_REG_GLOB_CMD,                        \
        .burst_len = ADIS16475_BURST_MAX_DATA,                          \
@@@ -1255,9 -1240,6 +1241,6 @@@ static int adis16475_config_irq_pin(str
                return -EINVAL;
        }
  
-       /* We cannot mask the interrupt so ensure it's not enabled at request */
-       st->adis.irq_flag |= IRQF_NO_AUTOEN;
        val = ADIS16475_MSG_CTRL_DR_POL(polarity);
        ret = __adis_update_bits(&st->adis, ADIS16475_REG_MSG_CTRL,
                                 ADIS16475_MSG_CTRL_DR_POL_MASK, val);
This page took 0.246688 seconds and 4 git commands to generate.