summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2026-04-24 13:23:50 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2026-04-24 13:23:50 -0700
commitcb4eb6771c0f8fd1c52a8f6fdec7762fb087380a (patch)
treec50311c87c0d464bfbba34e5c3b8699897fb1b65
parentb2680ba4a2ad259c7bbd856ed830b459e11d88ba (diff)
parent1c0220a61508d67a09a6e71eb09593a8aea61822 (diff)
downloadlwn-cb4eb6771c0f8fd1c52a8f6fdec7762fb087380a.tar.gz
lwn-cb4eb6771c0f8fd1c52a8f6fdec7762fb087380a.zip
Merge tag 'char-misc-7.1-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc
Pull char / misc / IIO / and others driver updates from Greg KH: "Here is the char/misc/iio and other smaller driver subsystem updates for 7.1-rc1. Lots of stuff in here, all tiny, but relevant for the different drivers they touch. Major points in here is: - the usual large set of new IIO drivers and updates for that subsystem (the large majority of this diffstat) - lots of comedi driver updates and bugfixes - coresight driver updates - interconnect driver updates and additions - mei driver updates - binder (both rust and C versions) updates and fixes - lots of other smaller driver subsystem updates and additions All of these have been in linux-next for a while with no reported issues" * tag 'char-misc-7.1-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc: (405 commits) coresight: tpdm: fix invalid MMIO access issue mei: me: add nova lake point H DID mei: lb: add late binding version 2 mei: bus: add mei_cldev_uuid w1: ds2490: drop redundant device reference bus: mhi: host: pci_generic: Add Telit FE912C04 modem support mei: csc: wake device while reading firmware status mei: csc: support controller with separate PCI device mei: convert PCI error to common errno mei: trace: print return value of pci_cfg_read mei: me: move trace into firmware status read mei: fix idle print specifiers mei: me: use PCI_DEVICE_DATA macro sonypi: Convert ACPI driver to a platform one misc: apds990x: fix all kernel-doc warnings most: usb: Use kzalloc_objs for endpoint address array hpet: Convert ACPI driver to a platform one misc: vmw_vmci: Fix spelling mistakes in comments parport: Remove completed item from to-do list char: remove unnecessary module_init/exit functions ...
-rw-r--r--.mailmap1
-rw-r--r--Documentation/ABI/stable/sysfs-driver-speakup4
-rw-r--r--Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm10
-rw-r--r--Documentation/ABI/testing/sysfs-bus-iio2
-rw-r--r--Documentation/devicetree/bindings/extcon/extcon-ptn5150.yaml3
-rw-r--r--Documentation/devicetree/bindings/iio/accel/adi,adxl372.yaml9
-rw-r--r--Documentation/devicetree/bindings/iio/accel/bosch,bma255.yaml40
-rw-r--r--Documentation/devicetree/bindings/iio/adc/adi,ad4030.yaml64
-rw-r--r--Documentation/devicetree/bindings/iio/adc/adi,ad4080.yaml3
-rw-r--r--Documentation/devicetree/bindings/iio/adc/adi,ad7380.yaml23
-rw-r--r--Documentation/devicetree/bindings/iio/adc/amlogic,meson-saradc.yaml4
-rw-r--r--Documentation/devicetree/bindings/iio/adc/lltc,ltc2497.yaml7
-rw-r--r--Documentation/devicetree/bindings/iio/adc/motorola,cpcap-adc.yaml1
-rw-r--r--Documentation/devicetree/bindings/iio/adc/qcom,spmi-adc5-gen3.yaml151
-rw-r--r--Documentation/devicetree/bindings/iio/adc/qcom,spmi-vadc-common.yaml84
-rw-r--r--Documentation/devicetree/bindings/iio/adc/qcom,spmi-vadc.yaml78
-rw-r--r--Documentation/devicetree/bindings/iio/amplifiers/adi,ad8366.yaml101
-rw-r--r--Documentation/devicetree/bindings/iio/dac/lltc,ltc2632.yaml57
-rw-r--r--Documentation/devicetree/bindings/iio/dac/maxim,ds4424.yaml42
-rw-r--r--Documentation/devicetree/bindings/iio/dac/ti,dac7612.yaml2
-rw-r--r--Documentation/devicetree/bindings/iio/gyroscope/bosch,bmg160.yaml12
-rw-r--r--Documentation/devicetree/bindings/iio/light/vishay,vcnl4000.yaml31
-rw-r--r--Documentation/devicetree/bindings/iio/magnetometer/bosch,bmc150_magn.yaml14
-rw-r--r--Documentation/devicetree/bindings/iio/proximity/st,vl53l0x.yaml22
-rw-r--r--Documentation/devicetree/bindings/iio/proximity/tyhx,hx9023s.yaml4
-rw-r--r--Documentation/devicetree/bindings/interconnect/qcom,glymur-rpmh.yaml136
-rw-r--r--Documentation/devicetree/bindings/interconnect/qcom,msm8974.yaml28
-rw-r--r--Documentation/devicetree/bindings/interconnect/qcom,osm-l3.yaml1
-rw-r--r--Documentation/devicetree/bindings/interconnect/qcom,qcs615-rpmh.yaml23
-rw-r--r--Documentation/devicetree/bindings/interconnect/qcom,qcs8300-rpmh.yaml63
-rw-r--r--Documentation/devicetree/bindings/mfd/qcom,spmi-pmic.yaml1
-rw-r--r--Documentation/devicetree/bindings/misc/qcom,fastrpc.yaml11
-rw-r--r--Documentation/devicetree/bindings/misc/ti,fpc202.yaml21
-rw-r--r--Documentation/devicetree/bindings/nvmem/layouts/kontron,sl28-vpd.yaml7
-rw-r--r--Documentation/devicetree/bindings/nvmem/qcom,qfprom.yaml1
-rw-r--r--Documentation/devicetree/bindings/nvmem/rockchip,otp.yaml83
-rw-r--r--Documentation/iio/ad4030.rst39
-rw-r--r--Documentation/iio/ad7191.rst6
-rw-r--r--Documentation/iio/adxl345.rst81
-rw-r--r--MAINTAINERS44
-rw-r--r--drivers/android/binder.c2
-rw-r--r--drivers/android/binder/allocation.rs33
-rw-r--r--drivers/android/binder/context.rs11
-rw-r--r--drivers/android/binder/error.rs10
-rw-r--r--drivers/android/binder/process.rs29
-rw-r--r--drivers/android/binder/rust_binder.h5
-rw-r--r--drivers/android/binder/rust_binder_events.h121
-rw-r--r--drivers/android/binder/rust_binder_main.rs3
-rw-r--r--drivers/android/binder/thread.rs211
-rw-r--r--drivers/android/binder/trace.rs78
-rw-r--r--drivers/android/binder/transaction.rs89
-rw-r--r--drivers/bus/mhi/ep/main.c10
-rw-r--r--drivers/bus/mhi/ep/ring.c6
-rw-r--r--drivers/bus/mhi/host/boot.c22
-rw-r--r--drivers/bus/mhi/host/pci_generic.c40
-rw-r--r--drivers/char/agp/backend.c16
-rw-r--r--drivers/char/hpet.c18
-rw-r--r--drivers/char/nsc_gpio.c14
-rw-r--r--drivers/char/sonypi.c25
-rw-r--r--drivers/comedi/Kconfig10
-rw-r--r--drivers/comedi/comedi_pci.c11
-rw-r--r--drivers/comedi/comedi_pcmcia.c11
-rw-r--r--drivers/comedi/comedi_usb.c11
-rw-r--r--drivers/comedi/drivers.c46
-rw-r--r--drivers/comedi/drivers/8255.c10
-rw-r--r--drivers/comedi/drivers/addi_watchdog.c11
-rw-r--r--drivers/comedi/drivers/adq12b.c3
-rw-r--r--drivers/comedi/drivers/aio_aio12_8.c15
-rw-r--r--drivers/comedi/drivers/aio_iiro_16.c11
-rw-r--r--drivers/comedi/drivers/amplc_dio200.c3
-rw-r--r--drivers/comedi/drivers/amplc_dio200_common.c11
-rw-r--r--drivers/comedi/drivers/amplc_pc236.c3
-rw-r--r--drivers/comedi/drivers/amplc_pc236_common.c11
-rw-r--r--drivers/comedi/drivers/amplc_pc263.c3
-rw-r--r--drivers/comedi/drivers/c6xdigio.c4
-rw-r--r--drivers/comedi/drivers/comedi_8254.c11
-rw-r--r--drivers/comedi/drivers/comedi_8255.c11
-rw-r--r--drivers/comedi/drivers/comedi_isadma.c32
-rw-r--r--drivers/comedi/drivers/comedi_parport.c4
-rw-r--r--drivers/comedi/drivers/dac02.c3
-rw-r--r--drivers/comedi/drivers/das08.c11
-rw-r--r--drivers/comedi/drivers/das08_isa.c3
-rw-r--r--drivers/comedi/drivers/das16.c31
-rw-r--r--drivers/comedi/drivers/das16m1.c3
-rw-r--r--drivers/comedi/drivers/das1800.c3
-rw-r--r--drivers/comedi/drivers/das6402.c3
-rw-r--r--drivers/comedi/drivers/das800.c3
-rw-r--r--drivers/comedi/drivers/dmm32at.c22
-rw-r--r--drivers/comedi/drivers/dt2801.c3
-rw-r--r--drivers/comedi/drivers/dt2811.c3
-rw-r--r--drivers/comedi/drivers/dt2814.c3
-rw-r--r--drivers/comedi/drivers/dt2815.c3
-rw-r--r--drivers/comedi/drivers/dt2817.c3
-rw-r--r--drivers/comedi/drivers/dt282x.c7
-rw-r--r--drivers/comedi/drivers/fl512.c8
-rw-r--r--drivers/comedi/drivers/mite.c11
-rw-r--r--drivers/comedi/drivers/mpc624.c3
-rw-r--r--drivers/comedi/drivers/multiq3.c3
-rw-r--r--drivers/comedi/drivers/ni_at_a2150.c3
-rw-r--r--drivers/comedi/drivers/ni_at_ao.c3
-rw-r--r--drivers/comedi/drivers/ni_atmio.c3
-rw-r--r--drivers/comedi/drivers/ni_atmio16d.c3
-rw-r--r--drivers/comedi/drivers/ni_labpc.c3
-rw-r--r--drivers/comedi/drivers/ni_labpc_common.c11
-rw-r--r--drivers/comedi/drivers/ni_labpc_isadma.c11
-rw-r--r--drivers/comedi/drivers/ni_tio.c11
-rw-r--r--drivers/comedi/drivers/ni_tiocmd.c11
-rw-r--r--drivers/comedi/drivers/ni_usb6501.c23
-rw-r--r--drivers/comedi/drivers/pcl711.c6
-rw-r--r--drivers/comedi/drivers/pcl724.c22
-rw-r--r--drivers/comedi/drivers/pcl726.c12
-rw-r--r--drivers/comedi/drivers/pcl730.c49
-rw-r--r--drivers/comedi/drivers/pcl812.c22
-rw-r--r--drivers/comedi/drivers/pcl816.c3
-rw-r--r--drivers/comedi/drivers/pcl818.c27
-rw-r--r--drivers/comedi/drivers/pcm3724.c3
-rw-r--r--drivers/comedi/drivers/pcmad.c3
-rw-r--r--drivers/comedi/drivers/pcmda12.c9
-rw-r--r--drivers/comedi/drivers/pcmmio.c3
-rw-r--r--drivers/comedi/drivers/pcmuio.c5
-rw-r--r--drivers/comedi/drivers/rti800.c3
-rw-r--r--drivers/comedi/drivers/rti802.c3
-rw-r--r--drivers/comedi/drivers/s526.c3
-rw-r--r--drivers/comedi/kcomedilib/kcomedilib_main.c12
-rw-r--r--drivers/counter/counter-sysfs.c2
-rw-r--r--drivers/extcon/Kconfig1
-rw-r--r--drivers/extcon/extcon-intel-int3496.c4
-rw-r--r--drivers/extcon/extcon-ptn5150.c56
-rw-r--r--drivers/extcon/extcon-usbc-tusb320.c24
-rw-r--r--drivers/extcon/extcon.c4
-rw-r--r--drivers/fpga/fpga-bridge.c2
-rw-r--r--drivers/fpga/intel-m10-bmc-sec-update.c2
-rw-r--r--drivers/gpib/agilent_82357a/agilent_82357a.c5
-rw-r--r--drivers/gpib/common/gpib_os.c17
-rw-r--r--drivers/gpib/lpvo_usb_gpib/lpvo_usb_gpib.c206
-rw-r--r--drivers/gpib/nec7210/nec7210.c12
-rw-r--r--drivers/gpib/ni_usb/ni_usb_gpib.c4
-rw-r--r--drivers/gpib/tms9914/tms9914.c13
-rw-r--r--drivers/greybus/es2.c11
-rw-r--r--drivers/greybus/gb-beagleplay.c164
-rw-r--r--drivers/greybus/svc.c5
-rw-r--r--drivers/hwtracing/coresight/coresight-catu.c4
-rw-r--r--drivers/hwtracing/coresight/coresight-core.c214
-rw-r--r--drivers/hwtracing/coresight/coresight-ctcu-core.c5
-rw-r--r--drivers/hwtracing/coresight/coresight-cti-core.c321
-rw-r--r--drivers/hwtracing/coresight/coresight-cti-sysfs.c174
-rw-r--r--drivers/hwtracing/coresight/coresight-cti.h15
-rw-r--r--drivers/hwtracing/coresight/coresight-dummy.c7
-rw-r--r--drivers/hwtracing/coresight/coresight-etb10.c4
-rw-r--r--drivers/hwtracing/coresight/coresight-etm-perf.c5
-rw-r--r--drivers/hwtracing/coresight/coresight-funnel.c4
-rw-r--r--drivers/hwtracing/coresight/coresight-platform.c4
-rw-r--r--drivers/hwtracing/coresight/coresight-priv.h3
-rw-r--r--drivers/hwtracing/coresight/coresight-replicator.c4
-rw-r--r--drivers/hwtracing/coresight/coresight-stm.c4
-rw-r--r--drivers/hwtracing/coresight/coresight-tmc-core.c15
-rw-r--r--drivers/hwtracing/coresight/coresight-tnoc.c4
-rw-r--r--drivers/hwtracing/coresight/coresight-tpda.c4
-rw-r--r--drivers/hwtracing/coresight/coresight-tpdm.c40
-rw-r--r--drivers/hwtracing/coresight/coresight-tpdm.h2
-rw-r--r--drivers/hwtracing/coresight/coresight-tpiu.c4
-rw-r--r--drivers/hwtracing/coresight/ultrasoc-smb.c4
-rw-r--r--drivers/iio/accel/Kconfig12
-rw-r--r--drivers/iio/accel/adis16201.c2
-rw-r--r--drivers/iio/accel/adis16209.c2
-rw-r--r--drivers/iio/accel/adxl313_core.c11
-rw-r--r--drivers/iio/accel/adxl345_core.c32
-rw-r--r--drivers/iio/accel/adxl372.c314
-rw-r--r--drivers/iio/accel/adxl372.h20
-rw-r--r--drivers/iio/accel/adxl372_i2c.c17
-rw-r--r--drivers/iio/accel/adxl372_spi.c17
-rw-r--r--drivers/iio/accel/adxl380.c4
-rw-r--r--drivers/iio/accel/bmc150-accel-core.c4
-rw-r--r--drivers/iio/accel/sca3000.c215
-rw-r--r--drivers/iio/adc/Kconfig33
-rw-r--r--drivers/iio/adc/Makefile1
-rw-r--r--drivers/iio/adc/ad4030.c618
-rw-r--r--drivers/iio/adc/ad4062.c12
-rw-r--r--drivers/iio/adc/ad4080.c46
-rw-r--r--drivers/iio/adc/ad4170-4.c6
-rw-r--r--drivers/iio/adc/ad7173.c3
-rw-r--r--drivers/iio/adc/ad7192.c3
-rw-r--r--drivers/iio/adc/ad7266.c6
-rw-r--r--drivers/iio/adc/ad7380.c53
-rw-r--r--drivers/iio/adc/ad7768-1.c221
-rw-r--r--drivers/iio/adc/ad7793.c3
-rw-r--r--drivers/iio/adc/ad7887.c2
-rw-r--r--drivers/iio/adc/ad7923.c4
-rw-r--r--drivers/iio/adc/ad9467.c95
-rw-r--r--drivers/iio/adc/ad_sigma_delta.c6
-rw-r--r--drivers/iio/adc/ade9000.c13
-rw-r--r--drivers/iio/adc/adi-axi-adc.c5
-rw-r--r--drivers/iio/adc/aspeed_adc.c72
-rw-r--r--drivers/iio/adc/at91-sama5d2_adc.c5
-rw-r--r--drivers/iio/adc/at91_adc.c12
-rw-r--r--drivers/iio/adc/cpcap-adc.c15
-rw-r--r--drivers/iio/adc/fsl-imx25-gcq.c2
-rw-r--r--drivers/iio/adc/ina2xx-adc.c65
-rw-r--r--drivers/iio/adc/ltc2309.c81
-rw-r--r--drivers/iio/adc/max11410.c4
-rw-r--r--drivers/iio/adc/max1363.c87
-rw-r--r--drivers/iio/adc/mcp3564.c2
-rw-r--r--drivers/iio/adc/men_z188_adc.c2
-rw-r--r--drivers/iio/adc/meson_saradc.c21
-rw-r--r--drivers/iio/adc/mt6359-auxadc.c2
-rw-r--r--drivers/iio/adc/nau7802.c3
-rw-r--r--drivers/iio/adc/npcm_adc.c2
-rw-r--r--drivers/iio/adc/nxp-sar-adc.c3
-rw-r--r--drivers/iio/adc/pac1921.c2
-rw-r--r--drivers/iio/adc/pac1934.c2
-rw-r--r--drivers/iio/adc/palmas_gpadc.c8
-rw-r--r--drivers/iio/adc/qcom-spmi-adc5-gen3.c860
-rw-r--r--drivers/iio/adc/rohm-bd79124.c4
-rw-r--r--drivers/iio/adc/sd_adc_modulator.c1
-rw-r--r--drivers/iio/adc/spear_adc.c2
-rw-r--r--drivers/iio/adc/stm32-adc-core.c2
-rw-r--r--drivers/iio/adc/stm32-adc.c2
-rw-r--r--drivers/iio/adc/sun20i-gpadc-iio.c2
-rw-r--r--drivers/iio/adc/ti-ads1015.c1
-rw-r--r--drivers/iio/adc/ti-ads1119.c3
-rw-r--r--drivers/iio/adc/ti-ads7950.c183
-rw-r--r--drivers/iio/adc/ti_am335x_adc.c6
-rw-r--r--drivers/iio/adc/twl4030-madc.c2
-rw-r--r--drivers/iio/adc/twl6030-gpadc.c2
-rw-r--r--drivers/iio/addac/ad74413r.c9
-rw-r--r--drivers/iio/amplifiers/Kconfig8
-rw-r--r--drivers/iio/amplifiers/ad8366.c405
-rw-r--r--drivers/iio/amplifiers/ada4250.c2
-rw-r--r--drivers/iio/buffer/industrialio-hw-consumer.c11
-rw-r--r--drivers/iio/buffer/kfifo_buf.c41
-rw-r--r--drivers/iio/cdc/ad7150.c2
-rw-r--r--drivers/iio/cdc/ad7746.c2
-rw-r--r--drivers/iio/chemical/bme680_core.c2
-rw-r--r--drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c2
-rw-r--r--drivers/iio/common/hid-sensors/hid-sensor-attributes.c2
-rw-r--r--drivers/iio/common/inv_sensors/inv_sensors_timestamp.c4
-rw-r--r--drivers/iio/common/ms_sensors/ms_sensors_i2c.c2
-rw-r--r--drivers/iio/common/st_sensors/st_sensors_core.c11
-rw-r--r--drivers/iio/dac/Kconfig1
-rw-r--r--drivers/iio/dac/ad5360.c29
-rw-r--r--drivers/iio/dac/ad7293.c31
-rw-r--r--drivers/iio/dac/adi-axi-dac.c3
-rw-r--r--drivers/iio/dac/ds4424.c373
-rw-r--r--drivers/iio/dac/ltc2632.c353
-rw-r--r--drivers/iio/dac/max5522.c22
-rw-r--r--drivers/iio/dac/ti-dac5571.c1
-rw-r--r--drivers/iio/filter/admv8818.c60
-rw-r--r--drivers/iio/frequency/ad9523.c110
-rw-r--r--drivers/iio/frequency/adf4350.c10
-rw-r--r--drivers/iio/frequency/adf4377.c56
-rw-r--r--drivers/iio/frequency/admv1013.c104
-rw-r--r--drivers/iio/frequency/admv1014.c89
-rw-r--r--drivers/iio/frequency/admv4420.c37
-rw-r--r--drivers/iio/frequency/adrf6780.c60
-rw-r--r--drivers/iio/gyro/hid-sensor-gyro-3d.c6
-rw-r--r--drivers/iio/humidity/hdc2010.c1
-rw-r--r--drivers/iio/imu/bmi323/bmi323_core.c1
-rw-r--r--drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c2
-rw-r--r--drivers/iio/imu/inv_mpu6050/inv_mpu_magn.c2
-rw-r--r--drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_i2c.c1
-rw-r--r--drivers/iio/industrialio-backend.c22
-rw-r--r--drivers/iio/industrialio-event.c1
-rw-r--r--drivers/iio/industrialio-trigger.c33
-rw-r--r--drivers/iio/light/Kconfig2
-rw-r--r--drivers/iio/light/acpi-als.c42
-rw-r--r--drivers/iio/light/apds9160.c2
-rw-r--r--drivers/iio/light/apds9306.c4
-rw-r--r--drivers/iio/light/as73211.c3
-rw-r--r--drivers/iio/light/gp2ap020a00f.c310
-rw-r--r--drivers/iio/light/ltr390.c2
-rw-r--r--drivers/iio/light/ltr501.c6
-rw-r--r--drivers/iio/light/opt3001.c2
-rw-r--r--drivers/iio/light/tsl2772.c2
-rw-r--r--drivers/iio/light/vcnl4000.c131
-rw-r--r--drivers/iio/light/zopt2201.c45
-rw-r--r--drivers/iio/magnetometer/ak8974.c2
-rw-r--r--drivers/iio/magnetometer/ak8975.c6
-rw-r--r--drivers/iio/magnetometer/bmc150_magn.c145
-rw-r--r--drivers/iio/magnetometer/si7210.c21
-rw-r--r--drivers/iio/magnetometer/yamaha-yas530.c2
-rw-r--r--drivers/iio/pressure/bmp280-spi.c2
-rw-r--r--drivers/iio/pressure/hsc030pa.c2
-rw-r--r--drivers/iio/pressure/hsc030pa_i2c.c7
-rw-r--r--drivers/iio/pressure/rohm-bm1390.c2
-rw-r--r--drivers/iio/pressure/zpa2326.c2
-rw-r--r--drivers/iio/proximity/Kconfig15
-rw-r--r--drivers/iio/proximity/Makefile1
-rw-r--r--drivers/iio/proximity/hx9023s.c5
-rw-r--r--drivers/iio/proximity/sx9324.c2
-rw-r--r--drivers/iio/proximity/vl53l1x-i2c.c756
-rw-r--r--drivers/iio/resolver/ad2s1210.c6
-rw-r--r--drivers/iio/temperature/ltc2983.c4
-rw-r--r--drivers/iio/test/iio-test-gts.c2
-rw-r--r--drivers/interconnect/debugfs-client.c9
-rw-r--r--drivers/interconnect/qcom/Kconfig13
-rw-r--r--drivers/interconnect/qcom/Makefile2
-rw-r--r--drivers/interconnect/qcom/eliza.c1585
-rw-r--r--drivers/interconnect/qcom/glymur.c40
-rw-r--r--drivers/interconnect/qcom/icc-rpm-clocks.c6
-rw-r--r--drivers/interconnect/qcom/icc-rpm.c18
-rw-r--r--drivers/interconnect/qcom/icc-rpm.h7
-rw-r--r--drivers/interconnect/qcom/msm8974.c1637
-rw-r--r--drivers/interconnect/qcom/qcs615.c247
-rw-r--r--drivers/interconnect/qcom/qcs8300.c375
-rw-r--r--drivers/misc/Kconfig3
-rw-r--r--drivers/misc/amd-sbi/rmi-core.c4
-rw-r--r--drivers/misc/amd-sbi/rmi-i2c.c14
-rw-r--r--drivers/misc/ibmasm/ibmasmfs.c7
-rw-r--r--drivers/misc/ibmasm/lowlevel.c12
-rw-r--r--drivers/misc/ibmasm/remote.c5
-rw-r--r--drivers/misc/mei/Kconfig11
-rw-r--r--drivers/misc/mei/Makefile3
-rw-r--r--drivers/misc/mei/bus-fixup.c6
-rw-r--r--drivers/misc/mei/bus.c13
-rw-r--r--drivers/misc/mei/gsc-me.c3
-rw-r--r--drivers/misc/mei/hw-me-regs.h166
-rw-r--r--drivers/misc/mei/hw-me.c53
-rw-r--r--drivers/misc/mei/hw-me.h10
-rw-r--r--drivers/misc/mei/hw-txe.c4
-rw-r--r--drivers/misc/mei/init.c4
-rw-r--r--drivers/misc/mei/main.c18
-rw-r--r--drivers/misc/mei/mei-trace.h10
-rw-r--r--drivers/misc/mei/mei_dev.h5
-rw-r--r--drivers/misc/mei/mei_lb.c252
-rw-r--r--drivers/misc/mei/pci-csc.c261
-rw-r--r--drivers/misc/mei/pci-me.c217
-rw-r--r--drivers/misc/ti_fpc202.c349
-rw-r--r--drivers/misc/vmw_vmci/vmci_queue_pair.c4
-rw-r--r--drivers/most/most_cdev.c20
-rw-r--r--drivers/most/most_usb.c6
-rw-r--r--drivers/mux/mmio.c8
-rw-r--r--drivers/nvmem/qnap-mcu-eeprom.c8
-rw-r--r--drivers/nvmem/rockchip-otp.c161
-rw-r--r--drivers/parport/TODO-parport2
-rw-r--r--drivers/pps/generators/pps_gen.c22
-rw-r--r--drivers/pps/pps.c24
-rw-r--r--drivers/staging/iio/adc/ad7816.c16
-rw-r--r--drivers/staging/iio/frequency/ad9834.c20
-rw-r--r--drivers/staging/iio/impedance-analyzer/ad5933.c28
-rw-r--r--drivers/w1/masters/ds2490.c11
-rw-r--r--include/drm/intel/intel_lb_mei_interface.h51
-rw-r--r--include/linux/comedi/comedi_isadma.h2
-rw-r--r--include/linux/comedi/comedidev.h53
-rw-r--r--include/linux/coresight.h14
-rw-r--r--include/linux/iio/adc/qcom-adc5-gen3-common.h211
-rw-r--r--include/linux/iio/backend.h24
-rw-r--r--include/linux/iio/common/st_sensors.h11
-rw-r--r--include/linux/iio/types.h1
-rw-r--r--include/linux/mei_cl_bus.h1
-rw-r--r--include/linux/mhi.h34
-rw-r--r--include/linux/platform_data/apds990x.h4
-rw-r--r--include/linux/platform_data/tsl2772.h4
-rw-r--r--rust/kernel/alloc/kvec.rs216
-rw-r--r--rust/kernel/sync/aref.rs22
-rw-r--r--rust/kernel/task.rs9
-rw-r--r--rust/kernel/uaccess.rs2
356 files changed, 12801 insertions, 4299 deletions
diff --git a/.mailmap b/.mailmap
index 28eedfaa2d0d..34acd34bbf9b 100644
--- a/.mailmap
+++ b/.mailmap
@@ -587,6 +587,7 @@ Michel Lespinasse <michel@lespinasse.org> <walken@google.com>
Michel Lespinasse <michel@lespinasse.org> <walken@zoy.org>
Mickaël Salaün <mic@digikod.net> <mic@linux.microsoft.com>
Miguel Ojeda <ojeda@kernel.org> <miguel.ojeda.sandonis@gmail.com>
+Mike Leach <mike.leach@arm.com> <mike.leach@linaro.org>
Mike Rapoport <rppt@kernel.org> <mike@compulab.co.il>
Mike Rapoport <rppt@kernel.org> <mike.rapoport@gmail.com>
Mike Rapoport <rppt@kernel.org> <rppt@linux.ibm.com>
diff --git a/Documentation/ABI/stable/sysfs-driver-speakup b/Documentation/ABI/stable/sysfs-driver-speakup
index 8b508b4a7a00..69c26b911fe3 100644
--- a/Documentation/ABI/stable/sysfs-driver-speakup
+++ b/Documentation/ABI/stable/sysfs-driver-speakup
@@ -16,8 +16,8 @@ What: /sys/accessibility/speakup/bleeps
KernelVersion: 2.6
Contact: speakup@linux-speakup.org
Description: This controls whether one hears beeps through the PC speaker
- when using speakup's review commands.
- TODO: what values does it accept?
+ when using speakup's review commands. Range: 0-3. 0 = off, 1 = beeps
+ only, 2 = announcements only, 3 = beeps and announcements (default).
What: /sys/accessibility/speakup/bleep_time
KernelVersion: 2.6
diff --git a/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm b/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm
index f8016df64532..bc36ba32c900 100644
--- a/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm
+++ b/Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm
@@ -278,3 +278,13 @@ Date: Aug 2025
KernelVersion 6.18
Contact: Mao Jinlong <quic_jinlmao@quicinc.com>
Description: (Read) Show hardware context information of device.
+
+What: /sys/bus/coresight/devices/<tpdm-name>/traceid
+Date: March 2026
+KernelVersion: 7.1
+Contact: Jie Gan <jie.gan@oss.qualcomm.com>
+Description:
+ (R) Show the trace ID that will appear in the trace stream
+ coming from this TPDM. The trace ID is inherited from the
+ connected TPDA device and is fixed for the lifetime of the
+ device. Returns -EINVAL if the device has not been enabled yet.
diff --git a/Documentation/ABI/testing/sysfs-bus-iio b/Documentation/ABI/testing/sysfs-bus-iio
index 5f87dcee78f7..4fc9f6bd4281 100644
--- a/Documentation/ABI/testing/sysfs-bus-iio
+++ b/Documentation/ABI/testing/sysfs-bus-iio
@@ -1428,7 +1428,7 @@ KernelVersion: 2.6.35
Contact: linux-iio@vger.kernel.org
Description:
The name of the trigger source being used, as per string given
- in /sys/class/iio/triggerY/name.
+ in /sys/bus/iio/devices/triggerY/name.
What: /sys/bus/iio/devices/iio:deviceX/bufferY/length
KernelVersion: 5.11
diff --git a/Documentation/devicetree/bindings/extcon/extcon-ptn5150.yaml b/Documentation/devicetree/bindings/extcon/extcon-ptn5150.yaml
index 072b3c0c5fd0..79f88b5f4e5c 100644
--- a/Documentation/devicetree/bindings/extcon/extcon-ptn5150.yaml
+++ b/Documentation/devicetree/bindings/extcon/extcon-ptn5150.yaml
@@ -42,6 +42,9 @@ properties:
description:
A port node to link the usb controller for the dual role switch.
+ connector:
+ $ref: /schemas/connector/usb-connector.yaml#
+
required:
- compatible
- interrupts
diff --git a/Documentation/devicetree/bindings/iio/accel/adi,adxl372.yaml b/Documentation/devicetree/bindings/iio/accel/adi,adxl372.yaml
index 0ba0df46c3a9..02e734946f44 100644
--- a/Documentation/devicetree/bindings/iio/accel/adi,adxl372.yaml
+++ b/Documentation/devicetree/bindings/iio/accel/adi,adxl372.yaml
@@ -4,20 +4,23 @@
$id: http://devicetree.org/schemas/iio/accel/adi,adxl372.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
-title: Analog Devices ADXL372 3-Axis, +/-(200g) Digital Accelerometer
+title: Analog Devices ADXL371/ADXL372 3-Axis, +/-(200g) Digital Accelerometer
maintainers:
- Marcelo Schmitt <marcelo.schmitt@analog.com>
- Nuno Sá <nuno.sa@analog.com>
+ - Antoniu Miclaus <antoniu.miclaus@analog.com>
description: |
- Analog Devices ADXL372 3-Axis, +/-(200g) Digital Accelerometer that supports
- both I2C & SPI interfaces
+ Analog Devices ADXL371/ADXL372 3-Axis, +/-(200g) Digital Accelerometer that
+ supports both I2C & SPI interfaces
+ https://www.analog.com/en/products/adxl371.html
https://www.analog.com/en/products/adxl372.html
properties:
compatible:
enum:
+ - adi,adxl371
- adi,adxl372
reg:
diff --git a/Documentation/devicetree/bindings/iio/accel/bosch,bma255.yaml b/Documentation/devicetree/bindings/iio/accel/bosch,bma255.yaml
index c1387e02eb82..7f9c5eec35dd 100644
--- a/Documentation/devicetree/bindings/iio/accel/bosch,bma255.yaml
+++ b/Documentation/devicetree/bindings/iio/accel/bosch,bma255.yaml
@@ -16,25 +16,27 @@ description:
properties:
compatible:
- enum:
- # bmc150-accel driver in Linux
- - bosch,bma222
- - bosch,bma222e
- - bosch,bma250e
- - bosch,bma253
- - bosch,bma254
- - bosch,bma255
- - bosch,bma280
- - bosch,bmc150_accel
- - bosch,bmc156_accel
- - bosch,bmi055_accel
-
- # bma180 driver in Linux
- - bosch,bma023
- - bosch,bma150
- - bosch,bma180
- - bosch,bma250
- - bosch,smb380
+ oneOf:
+ - enum:
+ - bosch,bma222
+ - bosch,bma222e
+ - bosch,bma250e
+ - bosch,bma253
+ - bosch,bma254
+ - bosch,bma255
+ - bosch,bma280
+ - bosch,bmc150_accel
+ - bosch,bmc156_accel
+ - bosch,bmi055_accel
+
+ - bosch,bma023
+ - bosch,bma150
+ - bosch,bma180
+ - bosch,bma250
+ - bosch,smb380
+ - items:
+ - const: bosch,bmx055-accel
+ - const: bosch,bmc150_accel
reg:
maxItems: 1
diff --git a/Documentation/devicetree/bindings/iio/adc/adi,ad4030.yaml b/Documentation/devicetree/bindings/iio/adc/adi,ad4030.yaml
index e22d518135f2..08b1f9d75f89 100644
--- a/Documentation/devicetree/bindings/iio/adc/adi,ad4030.yaml
+++ b/Documentation/devicetree/bindings/iio/adc/adi,ad4030.yaml
@@ -19,6 +19,10 @@ description: |
* https://www.analog.com/media/en/technical-documentation/data-sheets/ad4030-24-4032-24.pdf
* https://www.analog.com/media/en/technical-documentation/data-sheets/ad4630-24_ad4632-24.pdf
* https://www.analog.com/media/en/technical-documentation/data-sheets/ad4630-16-4632-16.pdf
+ * https://www.analog.com/media/en/technical-documentation/data-sheets/adaq4216.pdf
+ * https://www.analog.com/media/en/technical-documentation/data-sheets/adaq4224.pdf
+
+$ref: /schemas/spi/spi-peripheral-props.yaml#
properties:
compatible:
@@ -29,6 +33,8 @@ properties:
- adi,ad4630-24
- adi,ad4632-16
- adi,ad4632-24
+ - adi,adaq4216
+ - adi,adaq4224
reg:
maxItems: 1
@@ -60,6 +66,14 @@ properties:
description:
Internal buffered Reference. Used when ref-supply is not connected.
+ vddh-supply:
+ description:
+ PGIA Positive Power Supply.
+
+ vdd-fda-supply:
+ description:
+ FDA Positive Power Supply.
+
cnv-gpios:
description:
The Convert Input (CNV). It initiates the sampling conversions.
@@ -70,6 +84,17 @@ properties:
The Reset Input (/RST). Used for asynchronous device reset.
maxItems: 1
+ pga-gpios:
+ description:
+ A0 and A1 pins for gain selection. For devices that have PGA configuration
+ input pins, pga-gpios should be defined.
+ minItems: 2
+ maxItems: 2
+
+ pwms:
+ description: PWM signal connected to the CNV pin.
+ maxItems: 1
+
interrupts:
description:
The BUSY pin is used to signal that the conversions results are available
@@ -107,6 +132,22 @@ allOf:
properties:
spi-rx-bus-width:
maxItems: 1
+ # ADAQ devices require a gain property to indicate how hardware PGA is set
+ - if:
+ properties:
+ compatible:
+ contains:
+ pattern: ^adi,adaq
+ then:
+ required:
+ - vddh-supply
+ - vdd-fda-supply
+ - pga-gpios
+ properties:
+ ref-supply: false
+ else:
+ properties:
+ pga-gpios: false
examples:
- |
@@ -148,3 +189,26 @@ examples:
reset-gpios = <&gpio0 1 GPIO_ACTIVE_LOW>;
};
};
+ - |
+ #include <dt-bindings/gpio/gpio.h>
+
+ spi {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ adc@0 {
+ compatible = "adi,adaq4216";
+ reg = <0>;
+ spi-max-frequency = <80000000>;
+ vdd-5v-supply = <&supply_5V>;
+ vdd-1v8-supply = <&supply_1_8V>;
+ vio-supply = <&supply_1_8V>;
+ refin-supply = <&refin_sup>;
+ vddh-supply = <&vddh>;
+ vdd-fda-supply = <&vdd_fda>;
+ cnv-gpios = <&gpio0 0 GPIO_ACTIVE_HIGH>;
+ reset-gpios = <&gpio0 1 GPIO_ACTIVE_LOW>;
+ pga-gpios = <&gpio0 2 GPIO_ACTIVE_HIGH>,
+ <&gpio0 3 GPIO_ACTIVE_HIGH>;
+ };
+ };
diff --git a/Documentation/devicetree/bindings/iio/adc/adi,ad4080.yaml b/Documentation/devicetree/bindings/iio/adc/adi,ad4080.yaml
index ccd6a0ac1539..79df2696ef24 100644
--- a/Documentation/devicetree/bindings/iio/adc/adi,ad4080.yaml
+++ b/Documentation/devicetree/bindings/iio/adc/adi,ad4080.yaml
@@ -27,10 +27,13 @@ properties:
enum:
- adi,ad4080
- adi,ad4081
+ - adi,ad4082
- adi,ad4083
- adi,ad4084
+ - adi,ad4085
- adi,ad4086
- adi,ad4087
+ - adi,ad4088
reg:
maxItems: 1
diff --git a/Documentation/devicetree/bindings/iio/adc/adi,ad7380.yaml b/Documentation/devicetree/bindings/iio/adc/adi,ad7380.yaml
index b91bfb16ed6b..396e1a1aa805 100644
--- a/Documentation/devicetree/bindings/iio/adc/adi,ad7380.yaml
+++ b/Documentation/devicetree/bindings/iio/adc/adi,ad7380.yaml
@@ -62,6 +62,11 @@ properties:
spi-cpol: true
spi-cpha: true
+ spi-rx-bus-width:
+ maxItems: 4
+ items:
+ maximum: 1
+
vcc-supply:
description: A 3V to 3.6V supply that powers the chip.
@@ -160,6 +165,23 @@ patternProperties:
unevaluatedProperties: false
allOf:
+ # 2-channel chips only have two SDO lines
+ - if:
+ properties:
+ compatible:
+ enum:
+ - adi,ad7380
+ - adi,ad7381
+ - adi,ad7383
+ - adi,ad7384
+ - adi,ad7386
+ - adi,ad7387
+ - adi,ad7388
+ then:
+ properties:
+ spi-rx-bus-width:
+ maxItems: 2
+
# pseudo-differential chips require common mode voltage supplies,
# true differential chips don't use them
- if:
@@ -284,6 +306,7 @@ examples:
spi-cpol;
spi-cpha;
spi-max-frequency = <80000000>;
+ spi-rx-bus-width = <1>, <1>, <1>, <1>;
interrupts = <27 IRQ_TYPE_EDGE_FALLING>;
interrupt-parent = <&gpio0>;
diff --git a/Documentation/devicetree/bindings/iio/adc/amlogic,meson-saradc.yaml b/Documentation/devicetree/bindings/iio/adc/amlogic,meson-saradc.yaml
index bb9825e7346d..70ab4e140e71 100644
--- a/Documentation/devicetree/bindings/iio/adc/amlogic,meson-saradc.yaml
+++ b/Documentation/devicetree/bindings/iio/adc/amlogic,meson-saradc.yaml
@@ -27,7 +27,11 @@ properties:
- amlogic,meson-gxm-saradc
- amlogic,meson-axg-saradc
- amlogic,meson-g12a-saradc
+ # Usage of this generic fallback is not allowed for new devices
- const: amlogic,meson-saradc
+ - items:
+ - const: amlogic,meson-s4-saradc
+ - const: amlogic,meson-g12a-saradc
reg:
maxItems: 1
diff --git a/Documentation/devicetree/bindings/iio/adc/lltc,ltc2497.yaml b/Documentation/devicetree/bindings/iio/adc/lltc,ltc2497.yaml
index 5cc6a9684077..c884b6e03767 100644
--- a/Documentation/devicetree/bindings/iio/adc/lltc,ltc2497.yaml
+++ b/Documentation/devicetree/bindings/iio/adc/lltc,ltc2497.yaml
@@ -11,6 +11,12 @@ maintainers:
- Liam Beguin <liambeguin@gmail.com>
description: |
+ LTC2305:
+ low noise, low power, 2-channel, 12-bit successive approximation ADC with an
+ I2C compatible serial interface.
+
+ https://www.analog.com/media/en/technical-documentation/data-sheets/23015fb.pdf
+
LTC2309:
low noise, low power, 8-channel, 12-bit successive approximation ADC with an
I2C compatible serial interface.
@@ -28,6 +34,7 @@ description: |
properties:
compatible:
enum:
+ - lltc,ltc2305
- lltc,ltc2309
- lltc,ltc2497
- lltc,ltc2499
diff --git a/Documentation/devicetree/bindings/iio/adc/motorola,cpcap-adc.yaml b/Documentation/devicetree/bindings/iio/adc/motorola,cpcap-adc.yaml
index 9ceb6f18c854..1f77da7f8e06 100644
--- a/Documentation/devicetree/bindings/iio/adc/motorola,cpcap-adc.yaml
+++ b/Documentation/devicetree/bindings/iio/adc/motorola,cpcap-adc.yaml
@@ -19,6 +19,7 @@ properties:
enum:
- motorola,cpcap-adc
- motorola,mapphone-cpcap-adc
+ - motorola,mot-cpcap-adc
interrupts:
maxItems: 1
diff --git a/Documentation/devicetree/bindings/iio/adc/qcom,spmi-adc5-gen3.yaml b/Documentation/devicetree/bindings/iio/adc/qcom,spmi-adc5-gen3.yaml
new file mode 100644
index 000000000000..149f4af8f4b8
--- /dev/null
+++ b/Documentation/devicetree/bindings/iio/adc/qcom,spmi-adc5-gen3.yaml
@@ -0,0 +1,151 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/iio/adc/qcom,spmi-adc5-gen3.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm's SPMI PMIC ADC5 Gen3
+
+maintainers:
+ - Jishnu Prakash <jishnu.prakash@oss.qualcomm.com>
+
+description: |
+ SPMI PMIC5 Gen3 voltage ADC (ADC) provides interface to clients to read
+ voltage. It is a 16-bit sigma-delta ADC. It also performs the same thermal
+ monitoring function as the existing ADC_TM devices.
+
+ The interface is implemented on SDAM (Shared Direct Access Memory) peripherals
+ on the master PMIC rather than a dedicated ADC peripheral. The number of PMIC
+ SDAM peripherals allocated for ADC is not correlated with the PMIC used, it is
+ programmed in FW (PBS) and is fixed per SOC, based on the SOC requirements.
+ All boards using a particular (SOC + master PMIC) combination will have the
+ same number of ADC SDAMs supported on that PMIC.
+
+properties:
+ compatible:
+ const: qcom,spmi-adc5-gen3
+
+ reg:
+ items:
+ - description: SDAM0 base address in the SPMI PMIC register map
+ - description: SDAM1 base address
+ minItems: 1
+
+ "#address-cells":
+ const: 1
+
+ "#size-cells":
+ const: 0
+
+ "#io-channel-cells":
+ const: 1
+
+ "#thermal-sensor-cells":
+ const: 1
+
+ interrupts:
+ items:
+ - description: SDAM0 end of conversion (EOC) interrupt
+ - description: SDAM1 EOC interrupt
+ minItems: 1
+
+patternProperties:
+ "^channel@[0-9a-f]+$":
+ type: object
+ unevaluatedProperties: false
+ $ref: /schemas/iio/adc/qcom,spmi-vadc-common.yaml
+ description:
+ Represents the external channels which are connected to the ADC.
+
+ properties:
+ qcom,decimation:
+ enum: [ 85, 340, 1360 ]
+ default: 1360
+
+ qcom,hw-settle-time:
+ enum: [ 15, 100, 200, 300, 400, 500, 600, 700,
+ 1000, 2000, 4000, 8000, 16000, 32000, 64000, 128000 ]
+ default: 15
+
+ qcom,avg-samples:
+ enum: [ 1, 2, 4, 8, 16 ]
+ default: 1
+
+ qcom,adc-tm:
+ description:
+ ADC_TM is a threshold monitoring feature in HW which can be enabled
+ on any ADC channel, to trigger an IRQ for threshold violation. In
+ earlier ADC generations, it was implemented in a separate device
+ (documented in Documentation/devicetree/bindings/thermal/qcom-spmi-adc-tm5.yaml.)
+ In Gen3, this feature can be enabled in the same ADC device for any
+ channel and threshold monitoring and IRQ triggering are handled in FW
+ (PBS) instead of another dedicated HW block.
+ This property indicates ADC_TM monitoring is done on this channel.
+ type: boolean
+
+required:
+ - compatible
+ - reg
+ - "#address-cells"
+ - "#size-cells"
+ - "#io-channel-cells"
+ - interrupts
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/irq.h>
+
+ pmic {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ adc@9000 {
+ compatible = "qcom,spmi-adc5-gen3";
+ reg = <0x9000>, <0x9100>;
+ interrupts = <0x0 0x90 0x1 IRQ_TYPE_EDGE_RISING>,
+ <0x0 0x91 0x1 IRQ_TYPE_EDGE_RISING>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ #io-channel-cells = <1>;
+ #thermal-sensor-cells = <1>;
+
+ /* PMK8550 Channel nodes */
+ channel@3 {
+ reg = <0x3>;
+ label = "pmk8550_die_temp";
+ qcom,pre-scaling = <1 1>;
+ };
+
+ channel@44 {
+ reg = <0x44>;
+ label = "pmk8550_xo_therm";
+ qcom,pre-scaling = <1 1>;
+ qcom,ratiometric;
+ qcom,hw-settle-time = <200>;
+ qcom,adc-tm;
+ };
+
+ /* PM8550 Channel nodes */
+ channel@103 {
+ reg = <0x103>;
+ label = "pm8550_die_temp";
+ qcom,pre-scaling = <1 1>;
+ };
+
+ /* PM8550B Channel nodes */
+ channel@78f {
+ reg = <0x78f>;
+ label = "pm8550b_vbat_sns_qbg";
+ qcom,pre-scaling = <1 3>;
+ };
+
+ /* PM8550VS_C Channel nodes */
+ channel@203 {
+ reg = <0x203>;
+ label = "pm8550vs_c_die_temp";
+ qcom,pre-scaling = <1 1>;
+ };
+ };
+ };
diff --git a/Documentation/devicetree/bindings/iio/adc/qcom,spmi-vadc-common.yaml b/Documentation/devicetree/bindings/iio/adc/qcom,spmi-vadc-common.yaml
new file mode 100644
index 000000000000..3ae252c17b91
--- /dev/null
+++ b/Documentation/devicetree/bindings/iio/adc/qcom,spmi-vadc-common.yaml
@@ -0,0 +1,84 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/iio/adc/qcom,spmi-vadc-common.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm Technologies, Inc. SPMI PMIC ADC channels
+
+maintainers:
+ - Jishnu Prakash <jishnu.prakash@oss.qualcomm.com>
+
+description:
+ This defines the common properties used to define Qualcomm VADC channels.
+
+properties:
+ reg:
+ description:
+ ADC channel number (PMIC-specific for versions after PMIC5 ADC).
+ maxItems: 1
+
+ label:
+ description:
+ ADC input of the platform as seen in the schematics.
+ For thermistor inputs connected to generic AMUX or GPIO inputs
+ these can vary across platform for the same pins. Hence select
+ the platform schematics name for this channel.
+
+ qcom,decimation:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ description:
+ This parameter is used to decrease ADC sampling rate.
+ Quicker measurements can be made by reducing decimation ratio.
+
+ qcom,pre-scaling:
+ $ref: /schemas/types.yaml#/definitions/uint32-array
+ description:
+ Used for scaling the channel input signal before the signal is
+ fed to VADC. The configuration for this node is to know the
+ pre-determined ratio and use it for post scaling. It is a pair of
+ integers, denoting the numerator and denominator of the fraction by which
+ input signal is multiplied. For example, <1 3> indicates the signal is scaled
+ down to 1/3 of its value before ADC measurement.
+ If property is not found default value depending on chip will be used.
+ oneOf:
+ - items:
+ - const: 1
+ - enum: [ 1, 3, 4, 6, 20, 8, 10, 16 ]
+ - items:
+ - const: 10
+ - const: 81
+
+ qcom,ratiometric:
+ type: boolean
+ description: |
+ Channel calibration type.
+ - For compatible property "qcom,spmi-vadc", if this property is
+ specified VADC will use the VDD reference (1.8V) and GND for
+ channel calibration. If property is not found, channel will be
+ calibrated with 0.625V and 1.25V reference channels, also
+ known as absolute calibration.
+ - For other compatible properties, if this property is specified
+ VADC will use the VDD reference (1.875V) and GND for channel
+ calibration. If property is not found, channel will be calibrated
+ with 0V and 1.25V reference channels, also known as absolute calibration.
+
+ qcom,hw-settle-time:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ description: |
+ Time between AMUX getting configured and the ADC starting
+ conversion. The 'hw_settle_time' is an index used from valid values
+ and programmed in hardware to achieve the hardware settling delay.
+
+ qcom,avg-samples:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ description: |
+ Number of samples to be used for measurement.
+ Averaging provides the option to obtain a single measurement
+ from the ADC that is an average of multiple samples. The value
+ selected is 2^(value).
+
+required:
+ - reg
+
+additionalProperties: true
diff --git a/Documentation/devicetree/bindings/iio/adc/qcom,spmi-vadc.yaml b/Documentation/devicetree/bindings/iio/adc/qcom,spmi-vadc.yaml
index b9dc04b0d307..72188041e8b5 100644
--- a/Documentation/devicetree/bindings/iio/adc/qcom,spmi-vadc.yaml
+++ b/Documentation/devicetree/bindings/iio/adc/qcom,spmi-vadc.yaml
@@ -15,6 +15,8 @@ description: |
voltage. The VADC is a 15-bit sigma-delta ADC.
SPMI PMIC5/PMIC7 voltage ADC (ADC) provides interface to clients to read
voltage. The VADC is a 16-bit sigma-delta ADC.
+ Note that PMIC7 ADC is the generation between PMIC5 and PMIC5 Gen3 ADC,
+ it can be considered like PMIC5 Gen2.
properties:
compatible:
@@ -56,7 +58,7 @@ required:
patternProperties:
"^channel@[0-9a-f]+$":
type: object
- additionalProperties: false
+ unevaluatedProperties: false
description: |
Represents the external channels which are connected to the ADC.
For compatible property "qcom,spmi-vadc" following channels, also known as
@@ -64,79 +66,7 @@ patternProperties:
configuration nodes should be defined:
VADC_REF_625MV and/or VADC_SPARE1(based on PMIC version) VADC_REF_1250MV,
VADC_GND_REF and VADC_VDD_VADC.
-
- properties:
- reg:
- maxItems: 1
- description: |
- ADC channel number.
- See include/dt-bindings/iio/qcom,spmi-vadc.h
- For PMIC7 ADC, the channel numbers are specified separately per PMIC
- in the PMIC-specific files in include/dt-bindings/iio/.
-
- label:
- description: |
- ADC input of the platform as seen in the schematics.
- For thermistor inputs connected to generic AMUX or GPIO inputs
- these can vary across platform for the same pins. Hence select
- the platform schematics name for this channel.
-
- qcom,decimation:
- $ref: /schemas/types.yaml#/definitions/uint32
- description: |
- This parameter is used to decrease ADC sampling rate.
- Quicker measurements can be made by reducing decimation ratio.
-
- qcom,pre-scaling:
- description: |
- Used for scaling the channel input signal before the signal is
- fed to VADC. The configuration for this node is to know the
- pre-determined ratio and use it for post scaling. It is a pair of
- integers, denoting the numerator and denominator of the fraction by which
- input signal is multiplied. For example, <1 3> indicates the signal is scaled
- down to 1/3 of its value before ADC measurement.
- If property is not found default value depending on chip will be used.
- $ref: /schemas/types.yaml#/definitions/uint32-array
- oneOf:
- - items:
- - const: 1
- - enum: [ 1, 3, 4, 6, 20, 8, 10, 16 ]
- - items:
- - const: 10
- - const: 81
-
- qcom,ratiometric:
- description: |
- Channel calibration type.
- - For compatible property "qcom,spmi-vadc", if this property is
- specified VADC will use the VDD reference (1.8V) and GND for
- channel calibration. If property is not found, channel will be
- calibrated with 0.625V and 1.25V reference channels, also
- known as absolute calibration.
- - For compatible property "qcom,spmi-adc5", "qcom,spmi-adc7" and
- "qcom,spmi-adc-rev2", if this property is specified VADC will use
- the VDD reference (1.875V) and GND for channel calibration. If
- property is not found, channel will be calibrated with 0V and 1.25V
- reference channels, also known as absolute calibration.
- type: boolean
-
- qcom,hw-settle-time:
- $ref: /schemas/types.yaml#/definitions/uint32
- description: |
- Time between AMUX getting configured and the ADC starting
- conversion. The 'hw_settle_time' is an index used from valid values
- and programmed in hardware to achieve the hardware settling delay.
-
- qcom,avg-samples:
- $ref: /schemas/types.yaml#/definitions/uint32
- description: |
- Number of samples to be used for measurement.
- Averaging provides the option to obtain a single measurement
- from the ADC that is an average of multiple samples. The value
- selected is 2^(value).
-
- required:
- - reg
+ $ref: /schemas/iio/adc/qcom,spmi-vadc-common.yaml
allOf:
- if:
diff --git a/Documentation/devicetree/bindings/iio/amplifiers/adi,ad8366.yaml b/Documentation/devicetree/bindings/iio/amplifiers/adi,ad8366.yaml
new file mode 100644
index 000000000000..065637ce33a5
--- /dev/null
+++ b/Documentation/devicetree/bindings/iio/amplifiers/adi,ad8366.yaml
@@ -0,0 +1,101 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/iio/amplifiers/adi,ad8366.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: AD8366 and similar Gain Amplifiers and Digital Attenuators
+
+maintainers:
+ - Michael Hennerich <michael.hennerich@analog.com>
+ - Rodrigo Alencar <rodrigo.alencar@analog.com>
+
+description:
+ Digital Variable Gain Amplifiers (VGAs) and Digital Attenuators with
+ SPI interface.
+
+properties:
+ compatible:
+ enum:
+ - adi,ad8366
+ - adi,ada4961
+ - adi,adl5240
+ - adi,adrf5702
+ - adi,adrf5703
+ - adi,adrf5720
+ - adi,adrf5730
+ - adi,adrf5731
+ - adi,hmc271a
+ - adi,hmc792a
+ - adi,hmc1018a
+ - adi,hmc1019a
+ - adi,hmc1119
+
+ reg:
+ maxItems: 1
+
+ vcc-supply:
+ description: Regulator that provides power to the device.
+
+ reset-gpios:
+ maxItems: 1
+
+ enable-gpios:
+ maxItems: 1
+ description: Power-up or Serial Mode Enable GPIO.
+
+required:
+ - compatible
+ - reg
+ - vcc-supply
+
+allOf:
+ - $ref: /schemas/spi/spi-peripheral-props.yaml#
+ - if:
+ not:
+ properties:
+ compatible:
+ contains:
+ const: adi,hmc271a
+ then:
+ properties:
+ reset-gpios: false
+ - if:
+ not:
+ properties:
+ compatible:
+ contains:
+ anyOf:
+ - const: adi,ad8366
+ - const: adi,ada4961
+ - const: adi,adrf5702
+ - const: adi,adrf5703
+ - const: adi,adrf5720
+ - const: adi,adrf5730
+ - const: adi,adrf5731
+ - const: adi,hmc792a
+ - const: adi,hmc1018a
+ - const: adi,hmc1019a
+ - const: adi,hmc1119
+ then:
+ properties:
+ enable-gpios: false
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/gpio/gpio.h>
+ spi {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ amplifier@0 {
+ compatible = "adi,ad8366";
+ reg = <0>;
+ spi-max-frequency = <1000000>;
+ vcc-supply = <&vcc_3v3>;
+ enable-gpios = <&gpio 0 GPIO_ACTIVE_HIGH>;
+ };
+ };
+...
diff --git a/Documentation/devicetree/bindings/iio/dac/lltc,ltc2632.yaml b/Documentation/devicetree/bindings/iio/dac/lltc,ltc2632.yaml
index 733edc7d6d17..50a9cbb44e36 100644
--- a/Documentation/devicetree/bindings/iio/dac/lltc,ltc2632.yaml
+++ b/Documentation/devicetree/bindings/iio/dac/lltc,ltc2632.yaml
@@ -4,36 +4,49 @@
$id: http://devicetree.org/schemas/iio/dac/lltc,ltc2632.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
-title: Linear Technology LTC263x 12-/10-/8-Bit Rail-to-Rail DAC
+title: Linear Technology LTC263x and LTC2654 Rail-to-Rail DAC
maintainers:
- Michael Hennerich <michael.hennerich@analog.com>
description: |
- Bindings for the Linear Technology LTC2632/2634/2636 DAC
- Datasheet can be found here: https://www.analog.com/media/en/technical-documentation/data-sheets/LTC263[246].pdf
+ Bindings for the Linear Technology LTC2632/2634/2636/2654 DAC
+ Datasheet can be found here:
+ https://www.analog.com/media/en/technical-documentation/data-sheets/LTC263[246].pdf
+ https://www.analog.com/media/en/technical-documentation/data-sheets/2654f.pdf
properties:
compatible:
- enum:
- - lltc,ltc2632-l12
- - lltc,ltc2632-l10
- - lltc,ltc2632-l8
- - lltc,ltc2632-h12
- - lltc,ltc2632-h10
- - lltc,ltc2632-h8
- - lltc,ltc2634-l12
- - lltc,ltc2634-l10
- - lltc,ltc2634-l8
- - lltc,ltc2634-h12
- - lltc,ltc2634-h10
- - lltc,ltc2634-h8
- - lltc,ltc2636-l12
- - lltc,ltc2636-l10
- - lltc,ltc2636-l8
- - lltc,ltc2636-h12
- - lltc,ltc2636-h10
- - lltc,ltc2636-h8
+ oneOf:
+ - enum:
+ - lltc,ltc2632-l12
+ - lltc,ltc2632-l10
+ - lltc,ltc2632-l8
+ - lltc,ltc2632-h12
+ - lltc,ltc2632-h10
+ - lltc,ltc2632-h8
+ - lltc,ltc2634-l12
+ - lltc,ltc2634-l10
+ - lltc,ltc2634-l8
+ - lltc,ltc2634-h12
+ - lltc,ltc2634-h10
+ - lltc,ltc2634-h8
+ - lltc,ltc2636-l12
+ - lltc,ltc2636-l10
+ - lltc,ltc2636-l8
+ - lltc,ltc2636-h12
+ - lltc,ltc2636-h10
+ - lltc,ltc2636-h8
+ - lltc,ltc2654-l16
+ - lltc,ltc2654-h16
+ - items:
+ - enum:
+ - lltc,ltc2654-l12
+ - const: lltc,ltc2634-l12
+ - items:
+ - enum:
+ - lltc,ltc2654-h12
+ - const: lltc,ltc2634-h12
reg:
maxItems: 1
diff --git a/Documentation/devicetree/bindings/iio/dac/maxim,ds4424.yaml b/Documentation/devicetree/bindings/iio/dac/maxim,ds4424.yaml
index 264fa7c5fe3a..4323df2036ac 100644
--- a/Documentation/devicetree/bindings/iio/dac/maxim,ds4424.yaml
+++ b/Documentation/devicetree/bindings/iio/dac/maxim,ds4424.yaml
@@ -4,18 +4,21 @@
$id: http://devicetree.org/schemas/iio/dac/maxim,ds4424.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
-title: Maxim Integrated DS4422/DS4424 7-bit Sink/Source Current DAC
+title: Maxim Integrated DS4402/DS4404 and DS4422/DS4424 Current DACs
maintainers:
- Ismail Kose <ihkose@gmail.com>
description: |
- Datasheet publicly available at:
+ Datasheets publicly available at:
+ https://datasheets.maximintegrated.com/en/ds/DS4402-DS4404.pdf
https://datasheets.maximintegrated.com/en/ds/DS4422-DS4424.pdf
properties:
compatible:
enum:
+ - maxim,ds4402
+ - maxim,ds4404
- maxim,ds4422
- maxim,ds4424
@@ -24,9 +27,43 @@ properties:
vcc-supply: true
+ maxim,rfs-ohms:
+ description: |
+ Array of resistance values in Ohms for the external Rfs resistors
+ connected to the FS pins. These values determine the full-scale
+ output current. The actual resistance depends on the chip variant
+ and specific hardware design requirements.
+ minItems: 2
+ maxItems: 4
+
required:
- compatible
- reg
+ - maxim,rfs-ohms
+
+allOf:
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - maxim,ds4402
+ - maxim,ds4422
+ then:
+ properties:
+ maxim,rfs-ohms:
+ maxItems: 2
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - maxim,ds4404
+ - maxim,ds4424
+ then:
+ properties:
+ maxim,rfs-ohms:
+ minItems: 4
additionalProperties: false
@@ -40,6 +77,7 @@ examples:
compatible = "maxim,ds4424";
reg = <0x10>; /* When A0, A1 pins are ground */
vcc-supply = <&vcc_3v3>;
+ maxim,rfs-ohms = <40000>, <40000>, <40000>, <40000>;
};
};
...
diff --git a/Documentation/devicetree/bindings/iio/dac/ti,dac7612.yaml b/Documentation/devicetree/bindings/iio/dac/ti,dac7612.yaml
index 20dd1370660d..624c640be4c8 100644
--- a/Documentation/devicetree/bindings/iio/dac/ti,dac7612.yaml
+++ b/Documentation/devicetree/bindings/iio/dac/ti,dac7612.yaml
@@ -9,7 +9,7 @@ title: Texas Instruments DAC7612 family of DACs
description:
The DAC7612 is a dual, 12-bit digital-to-analog converter (DAC) with
guaranteed 12-bit monotonicity performance over the industrial temperature
- range. Is is programmable through an SPI interface.
+ range. It is programmable through an SPI interface.
maintainers:
- Ricardo Ribalda Delgado <ricardo@ribalda.com>
diff --git a/Documentation/devicetree/bindings/iio/gyroscope/bosch,bmg160.yaml b/Documentation/devicetree/bindings/iio/gyroscope/bosch,bmg160.yaml
index 3c6fe74af0b8..fcbd4b430e48 100644
--- a/Documentation/devicetree/bindings/iio/gyroscope/bosch,bmg160.yaml
+++ b/Documentation/devicetree/bindings/iio/gyroscope/bosch,bmg160.yaml
@@ -11,10 +11,14 @@ maintainers:
properties:
compatible:
- enum:
- - bosch,bmg160
- - bosch,bmi055_gyro
- - bosch,bmi088_gyro
+ oneOf:
+ - enum:
+ - bosch,bmg160
+ - bosch,bmi055_gyro
+ - bosch,bmi088_gyro
+ - items:
+ - const: bosch,bmx055-gyro
+ - const: bosch,bmg160
reg:
maxItems: 1
diff --git a/Documentation/devicetree/bindings/iio/light/vishay,vcnl4000.yaml b/Documentation/devicetree/bindings/iio/light/vishay,vcnl4000.yaml
index 4d1a225e8868..516afef7a545 100644
--- a/Documentation/devicetree/bindings/iio/light/vishay,vcnl4000.yaml
+++ b/Documentation/devicetree/bindings/iio/light/vishay,vcnl4000.yaml
@@ -18,16 +18,32 @@ allOf:
properties:
compatible:
- enum:
- - vishay,vcnl4000
- - vishay,vcnl4010
- - vishay,vcnl4020
- - vishay,vcnl4040
- - vishay,vcnl4200
+ oneOf:
+ - enum:
+ - capella,cm36672p
+ - vishay,vcnl4000
+ - vishay,vcnl4010
+ - vishay,vcnl4020
+ - vishay,vcnl4040
+ - vishay,vcnl4200
+ - items:
+ - const: capella,cm36686
+ - const: vishay,vcnl4040
interrupts:
maxItems: 1
+ vdd-supply:
+ description: Regulator providing power to the "VDD" pin.
+
+ vio-supply:
+ description: Regulator providing power for pull-up of the I/O lines.
+ Does not connect to the sensor directly, but is needed for the
+ correct operation of the I2C and interrupt lines.
+
+ vled-supply:
+ description: Regulator providing power to the IR anode pin.
+
reg:
maxItems: 1
@@ -49,6 +65,9 @@ examples:
compatible = "vishay,vcnl4200";
reg = <0x51>;
proximity-near-level = <220>;
+ vdd-supply = <&reg_vdd>;
+ vio-supply = <&reg_vio>;
+ vled-supply = <&reg_vled>;
};
};
...
diff --git a/Documentation/devicetree/bindings/iio/magnetometer/bosch,bmc150_magn.yaml b/Documentation/devicetree/bindings/iio/magnetometer/bosch,bmc150_magn.yaml
index a3838ab0c524..c1a6892b0194 100644
--- a/Documentation/devicetree/bindings/iio/magnetometer/bosch,bmc150_magn.yaml
+++ b/Documentation/devicetree/bindings/iio/magnetometer/bosch,bmc150_magn.yaml
@@ -21,11 +21,15 @@ properties:
description:
Note the bmm150_magn is a deprecated compatible as this part contains only
a magnetometer.
- enum:
- - bosch,bmc150_magn
- - bosch,bmc156_magn
- - bosch,bmm150
- - bosch,bmm150_magn
+ oneOf:
+ - enum:
+ - bosch,bmc150_magn
+ - bosch,bmc156_magn
+ - bosch,bmm150
+ - bosch,bmm150_magn
+ - items:
+ - const: bosch,bmx055-magn
+ - const: bosch,bmc150_magn
reg:
maxItems: 1
diff --git a/Documentation/devicetree/bindings/iio/proximity/st,vl53l0x.yaml b/Documentation/devicetree/bindings/iio/proximity/st,vl53l0x.yaml
index 322befc41de6..f7f8be1e379d 100644
--- a/Documentation/devicetree/bindings/iio/proximity/st,vl53l0x.yaml
+++ b/Documentation/devicetree/bindings/iio/proximity/st,vl53l0x.yaml
@@ -4,14 +4,17 @@
$id: http://devicetree.org/schemas/iio/proximity/st,vl53l0x.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
-title: ST VL53L0X ToF ranging sensor
+title: ST VL53L0X/VL53L1X ToF ranging sensor
maintainers:
- Song Qiang <songqiang1304521@gmail.com>
+ - Siratul Islam <email@sirat.me>
properties:
compatible:
- const: st,vl53l0x
+ enum:
+ - st,vl53l0x
+ - st,vl53l1x
reg:
maxItems: 1
@@ -21,6 +24,8 @@ properties:
reset-gpios:
maxItems: 1
+ description:
+ Phandle to the XSHUT GPIO. Used for hardware reset.
vdd-supply: true
@@ -28,6 +33,16 @@ required:
- compatible
- reg
+allOf:
+ - if:
+ properties:
+ compatible:
+ contains:
+ const: st,vl53l1x
+ then:
+ required:
+ - vdd-supply
+
additionalProperties: false
examples:
@@ -38,8 +53,9 @@ examples:
#size-cells = <0>;
proximity@29 {
- compatible = "st,vl53l0x";
+ compatible = "st,vl53l1x";
reg = <0x29>;
+ vdd-supply = <&reg_3v3>;
interrupt-parent = <&gpio>;
interrupts = <23 IRQ_TYPE_EDGE_FALLING>;
};
diff --git a/Documentation/devicetree/bindings/iio/proximity/tyhx,hx9023s.yaml b/Documentation/devicetree/bindings/iio/proximity/tyhx,hx9023s.yaml
index 64ce8bc8bd36..cc5b5284c267 100644
--- a/Documentation/devicetree/bindings/iio/proximity/tyhx,hx9023s.yaml
+++ b/Documentation/devicetree/bindings/iio/proximity/tyhx,hx9023s.yaml
@@ -28,6 +28,9 @@ properties:
vdd-supply: true
+ firmware-name:
+ maxItems: 1
+
"#address-cells":
const: 1
@@ -65,6 +68,7 @@ examples:
interrupt-parent = <&pio>;
interrupts = <16 IRQ_TYPE_EDGE_FALLING>;
vdd-supply = <&pp1800_prox>;
+ firmware-name = "hx9023s.bin";
#address-cells = <1>;
#size-cells = <0>;
diff --git a/Documentation/devicetree/bindings/interconnect/qcom,glymur-rpmh.yaml b/Documentation/devicetree/bindings/interconnect/qcom,glymur-rpmh.yaml
index d55a7bcf5591..f69b2facb658 100644
--- a/Documentation/devicetree/bindings/interconnect/qcom,glymur-rpmh.yaml
+++ b/Documentation/devicetree/bindings/interconnect/qcom,glymur-rpmh.yaml
@@ -4,7 +4,7 @@
$id: http://devicetree.org/schemas/interconnect/qcom,glymur-rpmh.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
-title: Qualcomm RPMh Network-On-Chip Interconnect on GLYMUR
+title: Qualcomm RPMh Network-On-Chip Interconnect on Glymur and Mahua SoCs
maintainers:
- Raviteja Laggyshetty <raviteja.laggyshetty@oss.qualcomm.com>
@@ -21,28 +21,98 @@ description: |
properties:
compatible:
- enum:
- - qcom,glymur-aggre1-noc
- - qcom,glymur-aggre2-noc
- - qcom,glymur-aggre3-noc
- - qcom,glymur-aggre4-noc
- - qcom,glymur-clk-virt
- - qcom,glymur-cnoc-cfg
- - qcom,glymur-cnoc-main
- - qcom,glymur-hscnoc
- - qcom,glymur-lpass-ag-noc
- - qcom,glymur-lpass-lpiaon-noc
- - qcom,glymur-lpass-lpicx-noc
- - qcom,glymur-mc-virt
- - qcom,glymur-mmss-noc
- - qcom,glymur-nsinoc
- - qcom,glymur-nsp-noc
- - qcom,glymur-oobm-ss-noc
- - qcom,glymur-pcie-east-anoc
- - qcom,glymur-pcie-east-slv-noc
- - qcom,glymur-pcie-west-anoc
- - qcom,glymur-pcie-west-slv-noc
- - qcom,glymur-system-noc
+ oneOf:
+ - items:
+ - enum:
+ - qcom,mahua-aggre1-noc
+ - const: qcom,glymur-aggre1-noc
+ - items:
+ - enum:
+ - qcom,mahua-aggre2-noc
+ - const: qcom,glymur-aggre2-noc
+ - items:
+ - enum:
+ - qcom,mahua-aggre3-noc
+ - const: qcom,glymur-aggre3-noc
+ - items:
+ - enum:
+ - qcom,mahua-aggre4-noc
+ - const: qcom,glymur-aggre4-noc
+ - items:
+ - enum:
+ - qcom,mahua-clk-virt
+ - const: qcom,glymur-clk-virt
+ - items:
+ - enum:
+ - qcom,mahua-cnoc-main
+ - const: qcom,glymur-cnoc-main
+ - items:
+ - enum:
+ - qcom,mahua-lpass-ag-noc
+ - const: qcom,glymur-lpass-ag-noc
+ - items:
+ - enum:
+ - qcom,mahua-lpass-lpiaon-noc
+ - const: qcom,glymur-lpass-lpiaon-noc
+ - items:
+ - enum:
+ - qcom,mahua-lpass-lpicx-noc
+ - const: qcom,glymur-lpass-lpicx-noc
+ - items:
+ - enum:
+ - qcom,mahua-mmss-noc
+ - const: qcom,glymur-mmss-noc
+ - items:
+ - enum:
+ - qcom,mahua-nsinoc
+ - const: qcom,glymur-nsinoc
+ - items:
+ - enum:
+ - qcom,mahua-nsp-noc
+ - const: qcom,glymur-nsp-noc
+ - items:
+ - enum:
+ - qcom,mahua-oobm-ss-noc
+ - const: qcom,glymur-oobm-ss-noc
+ - items:
+ - enum:
+ - qcom,mahua-pcie-east-anoc
+ - const: qcom,glymur-pcie-east-anoc
+ - items:
+ - enum:
+ - qcom,mahua-pcie-east-slv-noc
+ - const: qcom,glymur-pcie-east-slv-noc
+ - items:
+ - enum:
+ - qcom,mahua-system-noc
+ - const: qcom,glymur-system-noc
+ - enum:
+ - qcom,glymur-aggre1-noc
+ - qcom,glymur-aggre2-noc
+ - qcom,glymur-aggre3-noc
+ - qcom,glymur-aggre4-noc
+ - qcom,glymur-clk-virt
+ - qcom,glymur-cnoc-cfg
+ - qcom,glymur-cnoc-main
+ - qcom,glymur-hscnoc
+ - qcom,glymur-lpass-ag-noc
+ - qcom,glymur-lpass-lpiaon-noc
+ - qcom,glymur-lpass-lpicx-noc
+ - qcom,glymur-mc-virt
+ - qcom,glymur-mmss-noc
+ - qcom,glymur-nsinoc
+ - qcom,glymur-nsp-noc
+ - qcom,glymur-oobm-ss-noc
+ - qcom,glymur-pcie-east-anoc
+ - qcom,glymur-pcie-east-slv-noc
+ - qcom,glymur-pcie-west-anoc
+ - qcom,glymur-pcie-west-slv-noc
+ - qcom,glymur-system-noc
+ - qcom,mahua-cnoc-cfg
+ - qcom,mahua-hscnoc
+ - qcom,mahua-mc-virt
+ - qcom,mahua-pcie-west-anoc
+ - qcom,mahua-pcie-west-slv-noc
reg:
maxItems: 1
@@ -63,6 +133,7 @@ allOf:
enum:
- qcom,glymur-clk-virt
- qcom,glymur-mc-virt
+ - qcom,mahua-mc-virt
then:
properties:
reg: false
@@ -90,6 +161,20 @@ allOf:
compatible:
contains:
enum:
+ - qcom,mahua-pcie-west-anoc
+ then:
+ properties:
+ clocks:
+ items:
+ - description: aggre PCIE_3B WEST AXI clock
+ - description: aggre PCIE_4 WEST AXI clock
+ - description: aggre PCIE_6 WEST AXI clock
+
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
- qcom,glymur-pcie-east-anoc
then:
properties:
@@ -131,10 +216,11 @@ allOf:
compatible:
contains:
enum:
- - qcom,glymur-pcie-west-anoc
- - qcom,glymur-pcie-east-anoc
- qcom,glymur-aggre2-noc
- qcom,glymur-aggre4-noc
+ - qcom,glymur-pcie-east-anoc
+ - qcom,glymur-pcie-west-anoc
+ - qcom,mahua-pcie-west-anoc
then:
required:
- clocks
diff --git a/Documentation/devicetree/bindings/interconnect/qcom,msm8974.yaml b/Documentation/devicetree/bindings/interconnect/qcom,msm8974.yaml
index 95ce25ce1f7d..b35f6dd11c71 100644
--- a/Documentation/devicetree/bindings/interconnect/qcom,msm8974.yaml
+++ b/Documentation/devicetree/bindings/interconnect/qcom,msm8974.yaml
@@ -26,27 +26,34 @@ properties:
- qcom,msm8974-pnoc
- qcom,msm8974-snoc
- '#interconnect-cells':
- const: 1
-
clock-names:
items:
- const: bus
- - const: bus_a
clocks:
items:
- description: Bus Clock
- - description: Bus A Clock
required:
- compatible
- reg
- - '#interconnect-cells'
- - clock-names
- - clocks
-additionalProperties: false
+unevaluatedProperties: false
+
+allOf:
+ - $ref: qcom,rpm-common.yaml#
+ - if:
+ properties:
+ compatible:
+ const: qcom,msm8974-mmssnoc
+ then:
+ required:
+ - clocks
+ - clock-names
+ else:
+ properties:
+ clocks: false
+ clock-names: false
examples:
- |
@@ -56,7 +63,4 @@ examples:
reg = <0xfc380000 0x6a000>;
compatible = "qcom,msm8974-bimc";
#interconnect-cells = <1>;
- clock-names = "bus", "bus_a";
- clocks = <&rpmcc RPM_SMD_BIMC_CLK>,
- <&rpmcc RPM_SMD_BIMC_A_CLK>;
};
diff --git a/Documentation/devicetree/bindings/interconnect/qcom,osm-l3.yaml b/Documentation/devicetree/bindings/interconnect/qcom,osm-l3.yaml
index 6182599eb3c1..41b9f758bf8b 100644
--- a/Documentation/devicetree/bindings/interconnect/qcom,osm-l3.yaml
+++ b/Documentation/devicetree/bindings/interconnect/qcom,osm-l3.yaml
@@ -35,6 +35,7 @@ properties:
- qcom,sm6375-cpucp-l3
- qcom,sm8250-epss-l3
- qcom,sm8350-epss-l3
+ - qcom,sm8550-epss-l3
- qcom,sm8650-epss-l3
- const: qcom,epss-l3
- items:
diff --git a/Documentation/devicetree/bindings/interconnect/qcom,qcs615-rpmh.yaml b/Documentation/devicetree/bindings/interconnect/qcom,qcs615-rpmh.yaml
index e06404828824..a9cd49bbe247 100644
--- a/Documentation/devicetree/bindings/interconnect/qcom,qcs615-rpmh.yaml
+++ b/Documentation/devicetree/bindings/interconnect/qcom,qcs615-rpmh.yaml
@@ -34,6 +34,13 @@ properties:
reg:
maxItems: 1
+ clocks:
+ items:
+ - description: aggre UFS PHY AXI clock
+ - description: aggre USB2 SEC AXI clock
+ - description: aggre USB3 PRIM AXI clock
+ - description: RPMH CC IPA clock
+
required:
- compatible
@@ -53,6 +60,22 @@ allOf:
required:
- reg
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - qcom,qcs615-camnoc-virt
+ - qcom,qcs615-config-noc
+ - qcom,qcs615-dc-noc
+ - qcom,qcs615-gem-noc
+ - qcom,qcs615-mc-virt
+ - qcom,qcs615-mmss-noc
+ - qcom,qcs615-system-noc
+ then:
+ properties:
+ clocks: false
+
unevaluatedProperties: false
examples:
diff --git a/Documentation/devicetree/bindings/interconnect/qcom,qcs8300-rpmh.yaml b/Documentation/devicetree/bindings/interconnect/qcom,qcs8300-rpmh.yaml
index e9f528d6d9a8..88fe17277110 100644
--- a/Documentation/devicetree/bindings/interconnect/qcom,qcs8300-rpmh.yaml
+++ b/Documentation/devicetree/bindings/interconnect/qcom,qcs8300-rpmh.yaml
@@ -35,6 +35,10 @@ properties:
reg:
maxItems: 1
+ clocks:
+ minItems: 1
+ maxItems: 4
+
required:
- compatible
@@ -54,6 +58,64 @@ allOf:
required:
- reg
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - qcom,qcs8300-aggre1-noc
+ then:
+ properties:
+ clocks:
+ items:
+ - description: aggre UFS PHY AXI clock
+ - description: aggre QUP PRIM AXI clock
+ - description: aggre USB2 PRIM AXI clock
+ - description: aggre USB3 PRIM AXI clock
+
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - qcom,qcs8300-aggre2-noc
+ then:
+ properties:
+ clocks:
+ items:
+ - description: RPMH CC IPA clock
+
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - qcom,qcs8300-gem-noc
+ then:
+ properties:
+ clocks:
+ items:
+ - description: GCC DDRSS GPU AXI clock
+
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - qcom,qcs8300-clk-virt
+ - qcom,qcs8300-config-noc
+ - qcom,qcs8300-dc-noc
+ - qcom,qcs8300-gpdsp-anoc
+ - qcom,qcs8300-lpass-ag-noc
+ - qcom,qcs8300-mc-virt
+ - qcom,qcs8300-mmss-noc
+ - qcom,qcs8300-nspa-noc
+ - qcom,qcs8300-pcie-anoc
+ - qcom,qcs8300-system-noc
+ then:
+ properties:
+ clocks: false
+
unevaluatedProperties: false
examples:
@@ -63,6 +125,7 @@ examples:
reg = <0x9100000 0xf7080>;
#interconnect-cells = <2>;
qcom,bcm-voters = <&apps_bcm_voter>;
+ clocks = <&gcc_ddrss_gpu_axi_clk>;
};
clk_virt: interconnect-0 {
diff --git a/Documentation/devicetree/bindings/mfd/qcom,spmi-pmic.yaml b/Documentation/devicetree/bindings/mfd/qcom,spmi-pmic.yaml
index e5931d18d998..644c42b5e2e5 100644
--- a/Documentation/devicetree/bindings/mfd/qcom,spmi-pmic.yaml
+++ b/Documentation/devicetree/bindings/mfd/qcom,spmi-pmic.yaml
@@ -135,6 +135,7 @@ patternProperties:
"^adc@[0-9a-f]+$":
type: object
oneOf:
+ - $ref: /schemas/iio/adc/qcom,spmi-adc5-gen3.yaml#
- $ref: /schemas/iio/adc/qcom,spmi-iadc.yaml#
- $ref: /schemas/iio/adc/qcom,spmi-rradc.yaml#
- $ref: /schemas/iio/adc/qcom,spmi-vadc.yaml#
diff --git a/Documentation/devicetree/bindings/misc/qcom,fastrpc.yaml b/Documentation/devicetree/bindings/misc/qcom,fastrpc.yaml
index d8e47db677cc..ca830dd06de2 100644
--- a/Documentation/devicetree/bindings/misc/qcom,fastrpc.yaml
+++ b/Documentation/devicetree/bindings/misc/qcom,fastrpc.yaml
@@ -18,9 +18,14 @@ description: |
properties:
compatible:
- enum:
- - qcom,kaanapali-fastrpc
- - qcom,fastrpc
+ oneOf:
+ - enum:
+ - qcom,kaanapali-fastrpc
+ - qcom,fastrpc
+ - items:
+ - enum:
+ - qcom,glymur-fastrpc
+ - const: qcom,kaanapali-fastrpc
label:
enum:
diff --git a/Documentation/devicetree/bindings/misc/ti,fpc202.yaml b/Documentation/devicetree/bindings/misc/ti,fpc202.yaml
index a8cb10f2d0df..71c5859d2e13 100644
--- a/Documentation/devicetree/bindings/misc/ti,fpc202.yaml
+++ b/Documentation/devicetree/bindings/misc/ti,fpc202.yaml
@@ -53,6 +53,22 @@ patternProperties:
unevaluatedProperties: false
+ "^led@1[4-b]$":
+ $ref: /schemas/leds/common.yaml#
+ description: Output GPIO line with advanced LED features enabled.
+
+ properties:
+ reg:
+ minimum: 0x14
+ maximum: 0x1b
+ description:
+ GPIO line ID
+
+ required:
+ - reg
+
+ unevaluatedProperties: false
+
required:
- compatible
- reg
@@ -89,6 +105,11 @@ examples:
#size-cells = <0>;
reg = <1>;
};
+
+ led@14 {
+ reg = <0x14>;
+ label = "phy0:green:indicator";
+ };
};
};
...
diff --git a/Documentation/devicetree/bindings/nvmem/layouts/kontron,sl28-vpd.yaml b/Documentation/devicetree/bindings/nvmem/layouts/kontron,sl28-vpd.yaml
index afd1919c6b1c..c713e23819f1 100644
--- a/Documentation/devicetree/bindings/nvmem/layouts/kontron,sl28-vpd.yaml
+++ b/Documentation/devicetree/bindings/nvmem/layouts/kontron,sl28-vpd.yaml
@@ -19,12 +19,7 @@ select: false
properties:
compatible:
- oneOf:
- - items:
- - enum:
- - kontron,sa67-vpd
- - const: kontron,sl28-vpd
- - const: kontron,sl28-vpd
+ const: kontron,sl28-vpd
serial-number:
type: object
diff --git a/Documentation/devicetree/bindings/nvmem/qcom,qfprom.yaml b/Documentation/devicetree/bindings/nvmem/qcom,qfprom.yaml
index 839513d4b499..2ab047f2bb69 100644
--- a/Documentation/devicetree/bindings/nvmem/qcom,qfprom.yaml
+++ b/Documentation/devicetree/bindings/nvmem/qcom,qfprom.yaml
@@ -26,6 +26,7 @@ properties:
- qcom,ipq8064-qfprom
- qcom,ipq8074-qfprom
- qcom,ipq9574-qfprom
+ - qcom,kaanapali-qfprom
- qcom,msm8226-qfprom
- qcom,msm8916-qfprom
- qcom,msm8917-qfprom
diff --git a/Documentation/devicetree/bindings/nvmem/rockchip,otp.yaml b/Documentation/devicetree/bindings/nvmem/rockchip,otp.yaml
index dc89020b0950..7e4d5e1c4ced 100644
--- a/Documentation/devicetree/bindings/nvmem/rockchip,otp.yaml
+++ b/Documentation/devicetree/bindings/nvmem/rockchip,otp.yaml
@@ -14,6 +14,9 @@ properties:
enum:
- rockchip,px30-otp
- rockchip,rk3308-otp
+ - rockchip,rk3528-otp
+ - rockchip,rk3562-otp
+ - rockchip,rk3568-otp
- rockchip,rk3576-otp
- rockchip,rk3588-otp
@@ -26,19 +29,15 @@ properties:
clock-names:
minItems: 3
- items:
- - const: otp
- - const: apb_pclk
- - const: phy
- - const: arb
+ maxItems: 4
resets:
minItems: 1
- maxItems: 3
+ maxItems: 4
reset-names:
minItems: 1
- maxItems: 3
+ maxItems: 4
required:
- compatible
@@ -64,7 +63,10 @@ allOf:
clocks:
maxItems: 3
clock-names:
- maxItems: 3
+ items:
+ - const: otp
+ - const: apb_pclk
+ - const: phy
resets:
maxItems: 1
reset-names:
@@ -76,13 +78,68 @@ allOf:
compatible:
contains:
enum:
- - rockchip,rk3576-otp
+ - rockchip,rk3528-otp
then:
properties:
clocks:
maxItems: 3
clock-names:
+ items:
+ - const: otp
+ - const: apb_pclk
+ - const: sbpi
+ resets:
+ minItems: 3
+ maxItems: 3
+ reset-names:
+ items:
+ - const: otp
+ - const: apb
+ - const: sbpi
+
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - rockchip,rk3562-otp
+ - rockchip,rk3568-otp
+ then:
+ properties:
+ clocks:
+ minItems: 4
+ maxItems: 4
+ clock-names:
+ items:
+ - const: otp
+ - const: apb_pclk
+ - const: phy
+ - const: sbpi
+ resets:
+ minItems: 4
+ maxItems: 4
+ reset-names:
+ items:
+ - const: otp
+ - const: apb
+ - const: phy
+ - const: sbpi
+
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - rockchip,rk3576-otp
+ then:
+ properties:
+ clocks:
maxItems: 3
+ clock-names:
+ items:
+ - const: otp
+ - const: apb_pclk
+ - const: phy
resets:
minItems: 2
maxItems: 2
@@ -101,10 +158,16 @@ allOf:
properties:
clocks:
minItems: 4
+ maxItems: 4
clock-names:
- minItems: 4
+ items:
+ - const: otp
+ - const: apb_pclk
+ - const: phy
+ - const: arb
resets:
minItems: 3
+ maxItems: 3
reset-names:
items:
- const: otp
diff --git a/Documentation/iio/ad4030.rst b/Documentation/iio/ad4030.rst
index b57424b650a8..9caafa4148b0 100644
--- a/Documentation/iio/ad4030.rst
+++ b/Documentation/iio/ad4030.rst
@@ -92,6 +92,45 @@ Interleaved mode
In this mode, both channels conversion results are bit interleaved one SDO line.
As such the wiring is the same as `One lane mode`_.
+SPI offload wiring
+^^^^^^^^^^^^^^^^^^
+
+.. code-block::
+
+ +-------------+ +-------------+
+ | CNV |<-----+--| GPIO |
+ | | +--| PWM0 |
+ | | | |
+ | | +--| PWM1 |
+ | | | +-------------+
+ | | +->| TRIGGER |
+ | CS |<--------| CS |
+ | | | |
+ | ADC | | SPI |
+ | | | |
+ | SDI |<--------| SDO |
+ | SDO |-------->| SDI |
+ | SCLK |<--------| SCLK |
+ +-------------+ +-------------+
+
+In this mode, both the ``cnv-gpios`` and a ``pwms`` properties are required.
+The ``pwms`` property specifies the PWM that is connected to the ADC CNV pin.
+The SPI offload will have a ``trigger-sources`` property to indicate the SPI
+offload (PWM) trigger source. For AD4030 and similar ADCs, there are two
+possible data transfer zones for sample N. One of them (zone 1) starts after the
+data conversion for sample N is complete while the other one (zone 2) starts 9.8
+nanoseconds after the rising edge of CNV for sample N + 1.
+
+The configuration depicted in the above diagram is intended to perform data
+transfer in zone 2. To achieve high sample rates while meeting ADC timing
+requirements, an offset is added between the rising edges of PWM0 and PWM1 to
+delay the SPI transfer until 9.8 nanoseconds after CNV rising edge. This
+requires a specialized PWM controller that can provide such an offset.
+The `AD4630-FMC HDL project`_, for example, can be configured to sample AD4030
+data during zone 2 data read window.
+
+.. _AD4630-FMC HDL project: https://analogdevicesinc.github.io/hdl/projects/ad4630_fmc/index.html
+
SPI Clock mode
--------------
diff --git a/Documentation/iio/ad7191.rst b/Documentation/iio/ad7191.rst
index 977d4fea14b0..fd6a23ad44fd 100644
--- a/Documentation/iio/ad7191.rst
+++ b/Documentation/iio/ad7191.rst
@@ -63,11 +63,11 @@ Clock Configuration
The AD7191 supports both internal and external clock sources:
-- When CLKSEL pin is tied LOW: Uses internal 4.92MHz clock (no clock property
+- When CLKSEL pin is ACTIVE: Uses internal 4.92MHz clock (no clock property
needed)
-- When CLKSEL pin is tied HIGH: Requires external clock source
+- When CLKSEL pin is INACTIVE: Requires external clock source
- Can be a crystal between MCLK1 and MCLK2 pins
- - Or a CMOS-compatible clock driving MCLK2 pin
+ - Or a CMOS-compatible clock driving MCLK1 pin and MCLK2 left unconnected
- Must specify the "clocks" property in device tree when using external clock
SPI Interface Requirements
diff --git a/Documentation/iio/adxl345.rst b/Documentation/iio/adxl345.rst
index bb19d64f67c3..978f746a8198 100644
--- a/Documentation/iio/adxl345.rst
+++ b/Documentation/iio/adxl345.rst
@@ -12,16 +12,21 @@ This driver supports Analog Device's ADXL345/375 on SPI/I2C bus.
* `ADXL345 <https://www.analog.com/ADXL345>`_
* `ADXL375 <https://www.analog.com/ADXL375>`_
-The ADXL345 is a generic purpose low power, 3-axis accelerometer with selectable
-measurement ranges. The ADXL345 supports the ±2 g, ±4 g, ±8 g, and ±16 g ranges.
+The ADXL345 is a general-purpose, low-power, 3-axis accelerometer with selectable
+measurement ranges. The ADXL345 supports the following ranges:
+
+- ±2g (approx. ±19.61 m/s^2)
+- ±4g (approx. ±39.23 m/s^2)
+- ±8g (approx. ±78.45 m/s^2)
+- ±16g (approx. ±156.91 m/s^2)
2. Device Attributes
====================
-Each IIO device, has a device folder under ``/sys/bus/iio/devices/iio:deviceX``,
+Each IIO device has a device folder under ``/sys/bus/iio/devices/iio:deviceX``,
where X is the IIO index of the device. Under these folders reside a set of
device files, depending on the characteristics and features of the hardware
-device in questions. These files are consistently generalized and documented in
+device in question. These files are consistently generalized and documented in
the IIO ABI documentation.
The following table shows the ADXL345 related device files, found in the
@@ -42,7 +47,7 @@ specific device folder path ``/sys/bus/iio/devices/iio:deviceX``.
+-------------------------------------------+----------------------------------------------------------+
| in_accel_x_raw | Raw X-axis accelerometer channel value. |
+-------------------------------------------+----------------------------------------------------------+
-| in_accel_y_calibbias | y-axis acceleration offset correction |
+| in_accel_y_calibbias | Y-axis acceleration offset correction |
+-------------------------------------------+----------------------------------------------------------+
| in_accel_y_raw | Raw Y-axis accelerometer channel value. |
+-------------------------------------------+----------------------------------------------------------+
@@ -68,7 +73,7 @@ present, simply assume its value is 0.
+-------------------------------------+---------------------------+
| Channel type | Measurement unit |
+-------------------------------------+---------------------------+
-| Acceleration on X, Y, and Z axis | Meters per second squared |
+| Acceleration on X, Y, and Z axes | Meters per second squared |
+-------------------------------------+---------------------------+
Sensor Events
@@ -78,8 +83,8 @@ Specific IIO events are triggered by their corresponding interrupts. The sensor
driver supports either none or a single active interrupt (INT) line, selectable
from the two available options: INT1 or INT2. The active INT line should be
specified in the device tree. If no INT line is configured, the sensor defaults
-to FIFO bypass mode, where event detection is disabled and only X, Y, and Z axis
-measurements are available.
+to FIFO bypass mode, where event detection is disabled and only individual
+X, Y, and Z axis measurements are available.
The table below lists the ADXL345-related device files located in the
device-specific path: ``/sys/bus/iio/devices/iio:deviceX/events``.
@@ -90,37 +95,51 @@ listed.
+---------------------------------------------+---------------------------------------------+
| Event handle | Description |
+---------------------------------------------+---------------------------------------------+
-| in_accel_gesture_doubletap_en | Enable double tap detection on all axis |
+| in_accel_gesture_doubletap_en | Enable double tap detection on all axes |
+---------------------------------------------+---------------------------------------------+
| in_accel_gesture_doubletap_reset_timeout | Double tap window in [us] |
+---------------------------------------------+---------------------------------------------+
-| in_accel_gesture_doubletap_tap2_min_delay | Double tap latent in [us] |
+| in_accel_gesture_doubletap_scale | Double tap gesture threshold scale. |
++---------------------------------------------+---------------------------------------------+
+| in_accel_gesture_doubletap_tap2_min_delay | Double tap latency in [us] |
++---------------------------------------------+---------------------------------------------+
+| in_accel_gesture_doubletap_value | Double tap threshold value |
++---------------------------------------------+---------------------------------------------+
+| in_accel_gesture_singletap_scale | Single tap gesture threshold scale. |
+---------------------------------------------+---------------------------------------------+
| in_accel_gesture_singletap_timeout | Single tap duration in [us] |
+---------------------------------------------+---------------------------------------------+
-| in_accel_gesture_singletap_value | Single tap threshold value in 62.5/LSB |
+| in_accel_gesture_singletap_value | Single tap threshold value |
+---------------------------------------------+---------------------------------------------+
-| in_accel_mag_falling_period | Inactivity time in seconds |
+| in_accel_mag_adaptive_falling_period | AC coupled inactivity time in seconds |
+---------------------------------------------+---------------------------------------------+
-| in_accel_mag_falling_value | Inactivity threshold value in 62.5/LSB |
+| in_accel_mag_adaptive_falling_scale | AC coupled inactivity threshold scale. |
++---------------------------------------------+---------------------------------------------+
+| in_accel_mag_adaptive_falling_value | AC coupled inactivity threshold |
+---------------------------------------------+---------------------------------------------+
| in_accel_mag_adaptive_rising_en | Enable AC coupled activity on X axis |
+---------------------------------------------+---------------------------------------------+
-| in_accel_mag_adaptive_falling_period | AC coupled inactivity time in seconds |
+| in_accel_mag_adaptive_rising_scale | AC coupled activity threshold scale. |
+---------------------------------------------+---------------------------------------------+
-| in_accel_mag_adaptive_falling_value | AC coupled inactivity threshold in 62.5/LSB |
+| in_accel_mag_adaptive_rising_value | AC coupled activity threshold |
+---------------------------------------------+---------------------------------------------+
-| in_accel_mag_adaptive_rising_value | AC coupled activity threshold in 62.5/LSB |
+| in_accel_mag_falling_period | Inactivity time in seconds |
++---------------------------------------------+---------------------------------------------+
+| in_accel_mag_falling_scale | DC coupled inactivity threshold scale. |
++---------------------------------------------+---------------------------------------------+
+| in_accel_mag_falling_value | Inactivity threshold value |
+---------------------------------------------+---------------------------------------------+
| in_accel_mag_rising_en | Enable activity detection on X axis |
+---------------------------------------------+---------------------------------------------+
-| in_accel_mag_rising_value | Activity threshold value in 62.5/LSB |
+| in_accel_mag_rising_scale | DC coupled activity threshold scale. |
+---------------------------------------------+---------------------------------------------+
-| in_accel_x_gesture_singletap_en | Enable single tap detection on X axis |
+| in_accel_mag_rising_value | Activity threshold value |
+---------------------------------------------+---------------------------------------------+
-| in_accel_x&y&z_mag_falling_en | Enable inactivity detection on all axis |
+| in_accel_x&y&z_mag_adaptive_falling_en | Enable AC coupled inactivity on all axes |
+---------------------------------------------+---------------------------------------------+
-| in_accel_x&y&z_mag_adaptive_falling_en | Enable AC coupled inactivity on all axis |
+| in_accel_x&y&z_mag_falling_en | Enable inactivity detection on all axes |
++---------------------------------------------+---------------------------------------------+
+| in_accel_x_gesture_singletap_en | Enable single tap detection on X axis |
+---------------------------------------------+---------------------------------------------+
| in_accel_y_gesture_singletap_en | Enable single tap detection on Y axis |
+---------------------------------------------+---------------------------------------------+
@@ -140,8 +159,8 @@ When changing the **g range** configuration, the driver attempts to estimate
appropriate activity and inactivity thresholds by scaling the default values
based on the ratio of the previous range to the new one. The resulting threshold
will never be zero and will always fall between 1 and 255, corresponding to up
-to 62.5 g/LSB as specified in the datasheet. However, you can override these
-estimated thresholds by setting explicit values.
+to 62.5 mg/LSB (0.612915 m/s^2/LSB) as specified in the datasheet. However,
+you can override these estimated thresholds by setting explicit values.
When **activity** and **inactivity** events are enabled, the driver
automatically manages hysteresis behavior by setting the **link** and
@@ -270,13 +289,13 @@ Scale range configuration:
.. code-block:: bash
root:/sys/bus/iio/devices/iio:device0> cat ./in_accel_scale
- 0.478899
+ 0.004789
root:/sys/bus/iio/devices/iio:device0> cat ./in_accel_scale_available
- 0.478899 0.957798 1.915595 3.831190
+ 0.004789 0.009578 0.019156 0.038312
- root:/sys/bus/iio/devices/iio:device0> echo 1.915595 > ./in_accel_scale
+ root:/sys/bus/iio/devices/iio:device0> echo 0.019156 > ./in_accel_scale
root:/sys/bus/iio/devices/iio:device0> cat ./in_accel_scale
- 1.915595
+ 0.019156
Set output data rate (ODR):
@@ -312,10 +331,14 @@ Configure one or several events:
root:/sys/bus/iio/devices/iio:device0> echo 24 > ./buffer0/length
- ## AC coupled activity, threshold [62.5/LSB]
+ ## Check the event scale factor (0.0625 * 9.80665)
+ root:/sys/bus/iio/devices/iio:device0> cat ./events/in_accel_gesture_doubletap_scale
+ 0.612915
+
+ ## AC coupled activity, threshold [0.612915 m/s^2/LSB]
root:/sys/bus/iio/devices/iio:device0> echo 6 > ./events/in_accel_mag_adaptive_rising_value
- ## AC coupled inactivity, threshold, [62.5/LSB]
+ ## AC coupled inactivity, threshold, [0.612915 m/s^2/LSB]
root:/sys/bus/iio/devices/iio:device0> echo 4 > ./events/in_accel_mag_adaptive_falling_value
## AC coupled inactivity, time [s]
@@ -330,7 +353,7 @@ Configure one or several events:
## doubletap, window [us]
root:/sys/bus/iio/devices/iio:device0> echo 0.025 > ./events/in_accel_gesture_doubletap_reset_timeout
- ## doubletap, latent [us]
+ ## doubletap, latency [us]
root:/sys/bus/iio/devices/iio:device0> echo 0.025 > ./events/in_accel_gesture_doubletap_tap2_min_delay
## AC coupled activity, enable
diff --git a/MAINTAINERS b/MAINTAINERS
index 9922adc1f493..2fb1c75afd16 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -640,8 +640,11 @@ W: https://ez.analog.com/linux-software-drivers
F: Documentation/devicetree/bindings/iio/accel/adi,adxl367.yaml
F: drivers/iio/accel/adxl367*
-ADXL372 THREE-AXIS DIGITAL ACCELEROMETER DRIVER
+ADXL371/ADXL372 THREE-AXIS DIGITAL ACCELEROMETER DRIVER
M: Michael Hennerich <michael.hennerich@analog.com>
+M: Marcelo Schmitt <marcelo.schmitt@analog.com>
+M: Nuno Sá <nuno.sa@analog.com>
+M: Antoniu Miclaus <antoniu.miclaus@analog.com>
S: Supported
W: https://ez.analog.com/linux-software-drivers
F: Documentation/devicetree/bindings/iio/accel/adi,adxl372.yaml
@@ -1582,6 +1585,15 @@ W: https://ez.analog.com/linux-software-drivers
F: Documentation/devicetree/bindings/iio/adc/adi,ad7780.yaml
F: drivers/iio/adc/ad7780.c
+ANALOG DEVICES INC AD8366 DRIVER
+M: Michael Hennerich <Michael.Hennerich@analog.com>
+M: Rodrigo Alencar <rodrigo.alencar@analog.com>
+L: linux-iio@vger.kernel.org
+S: Supported
+W: https://ez.analog.com/linux-software-drivers
+F: Documentation/devicetree/bindings/iio/amplifiers/adi,ad8366.yaml
+F: drivers/iio/amplifiers/ad8366.c
+
ANALOG DEVICES INC AD9467 DRIVER
M: Michael Hennerich <Michael.Hennerich@analog.com>
M: Nuno Sa <nuno.sa@analog.com>
@@ -1690,6 +1702,14 @@ S: Supported
W: https://ez.analog.com/linux-software-drivers
F: Documentation/devicetree/bindings/iio/imu/adi,adis16550.yaml
+ANALOG DEVICES INC ADL8113 DRIVER
+M: Antoniu Miclaus <antoniu.miclaus@analog.com>
+L: linux-iio@vger.kernel.org
+S: Supported
+W: https://ez.analog.com/linux-software-drivers
+F: Documentation/devicetree/bindings/iio/amplifiers/adi,adl8113.yaml
+F: drivers/iio/amplifiers/adl8113.c
+
ANALOG DEVICES INC ADM1177 DRIVER
M: Michael Hennerich <Michael.Hennerich@analog.com>
L: linux-hwmon@vger.kernel.org
@@ -2700,8 +2720,9 @@ N: digicolor
ARM/CORESIGHT FRAMEWORK AND DRIVERS
M: Suzuki K Poulose <suzuki.poulose@arm.com>
-R: Mike Leach <mike.leach@linaro.org>
+R: Mike Leach <mike.leach@arm.com>
R: James Clark <james.clark@linaro.org>
+R: Leo Yan <leo.yan@arm.com>
L: coresight@lists.linaro.org (moderated for non-subscribers)
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
S: Maintained
@@ -13380,6 +13401,12 @@ F: include/linux/interconnect-clk.h
F: include/linux/interconnect-provider.h
F: include/linux/interconnect.h
+INTERCONNECT KUNIT TESTS
+M: Kuan-Wei Chiu <visitorckw@gmail.com>
+L: linux-pm@vger.kernel.org
+S: Maintained
+F: drivers/interconnect/icc-kunit.c
+
INTERRUPT COUNTER DRIVER
M: Oleksij Rempel <o.rempel@pengutronix.de>
R: Pengutronix Kernel Team <kernel@pengutronix.de>
@@ -19373,8 +19400,8 @@ F: drivers/net/dsa/ocelot/ocelot_ext.c
F: include/linux/mfd/ocelot.h
OCXL (Open Coherent Accelerator Processor Interface OpenCAPI) DRIVER
-M: Frederic Barrat <fbarrat@linux.ibm.com>
-M: Andrew Donnellan <ajd@linux.ibm.com>
+M: Mahesh J Salgaonkar <mahesh@linux.ibm.com>
+R: Andrew Donnellan <andrew+kernel@donnellan.id.au>
L: linuxppc-dev@lists.ozlabs.org
S: Odd Fixes
F: Documentation/userspace-api/accelerators/ocxl.rst
@@ -20859,7 +20886,7 @@ PERFORMANCE EVENTS TOOLING ARM64
R: John Garry <john.g.garry@oracle.com>
R: Will Deacon <will@kernel.org>
R: James Clark <james.clark@linaro.org>
-R: Mike Leach <mike.leach@linaro.org>
+R: Mike Leach <mike.leach@arm.com>
R: Leo Yan <leo.yan@linux.dev>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
S: Supported
@@ -25294,6 +25321,13 @@ S: Maintained
F: Documentation/devicetree/bindings/iio/proximity/st,vl53l0x.yaml
F: drivers/iio/proximity/vl53l0x-i2c.c
+ST VL53L1X ToF RANGER(I2C) IIO DRIVER
+M: Siratul Islam <email@sirat.me>
+L: linux-iio@vger.kernel.org
+S: Maintained
+F: Documentation/devicetree/bindings/iio/proximity/st,vl53l0x.yaml
+F: drivers/iio/proximity/vl53l1x-i2c.c
+
STABLE BRANCH
M: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
M: Sasha Levin <sashal@kernel.org>
diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index 21f91d9f2fbc..9e6194224593 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -3117,7 +3117,7 @@ static void binder_transaction(struct binder_proc *proc,
t->start_time = t_start_time;
t->from_pid = proc->pid;
t->from_tid = thread->pid;
- t->sender_euid = task_euid(proc->tsk);
+ t->sender_euid = current_euid();
t->code = tr->code;
t->flags = tr->flags;
t->priority = task_nice(current);
diff --git a/drivers/android/binder/allocation.rs b/drivers/android/binder/allocation.rs
index 7f65a9c3a0e5..0cab959e4b7e 100644
--- a/drivers/android/binder/allocation.rs
+++ b/drivers/android/binder/allocation.rs
@@ -56,7 +56,6 @@ pub(crate) struct Allocation {
pub(crate) process: Arc<Process>,
allocation_info: Option<AllocationInfo>,
free_on_drop: bool,
- pub(crate) oneway_spam_detected: bool,
#[allow(dead_code)]
pub(crate) debug_id: usize,
}
@@ -68,7 +67,6 @@ impl Allocation {
offset: usize,
size: usize,
ptr: usize,
- oneway_spam_detected: bool,
) -> Self {
Self {
process,
@@ -76,7 +74,6 @@ impl Allocation {
size,
ptr,
debug_id,
- oneway_spam_detected,
allocation_info: None,
free_on_drop: true,
}
@@ -208,6 +205,7 @@ impl Allocation {
let res = FileDescriptorReservation::get_unused_fd_flags(bindings::O_CLOEXEC)?;
let fd = res.reserved_fd();
self.write::<u32>(file_info.buffer_offset, &fd)?;
+ crate::trace::trace_transaction_fd_recv(self.debug_id, fd, file_info.buffer_offset);
reservations.push(
Reservation {
@@ -260,19 +258,22 @@ impl Drop for Allocation {
}
}
- for &fd in &info.file_list.close_on_free {
- let closer = match DeferredFdCloser::new(GFP_KERNEL) {
- Ok(closer) => closer,
- Err(kernel::alloc::AllocError) => {
- // Ignore allocation failures.
- break;
- }
- };
-
- // Here, we ignore errors. The operation can fail if the fd is not valid, or if the
- // method is called from a kthread. However, this is always called from a syscall,
- // so the latter case cannot happen, and we don't care about the first case.
- let _ = closer.close_fd(fd);
+ if self.process.task == kernel::current!().group_leader() {
+ for &fd in &info.file_list.close_on_free {
+ let closer = match DeferredFdCloser::new(GFP_KERNEL) {
+ Ok(closer) => closer,
+ Err(kernel::alloc::AllocError) => {
+ // Ignore allocation failures.
+ break;
+ }
+ };
+
+ // Here, we ignore errors. The operation can fail if the fd is not valid, or if
+ // the method is called from a kthread. However, this is always called from a
+ // syscall, so the latter case cannot happen, and we don't care about the first
+ // case.
+ let _ = closer.close_fd(fd);
+ }
}
if info.clear_on_free {
diff --git a/drivers/android/binder/context.rs b/drivers/android/binder/context.rs
index 9cf437c025a2..ddddb66b3557 100644
--- a/drivers/android/binder/context.rs
+++ b/drivers/android/binder/context.rs
@@ -94,6 +94,17 @@ impl Context {
}
let mut manager = self.manager.lock();
manager.all_procs.retain(|p| !Arc::ptr_eq(p, proc));
+
+ // Shrink the vector if it has significant unused capacity to avoid memory waste,
+ // but use a conservative strategy to prevent shrink-then-regrow oscillation.
+ // Only shrink when length drops below 1/4 of capacity, and shrink to twice the length.
+ let len = manager.all_procs.len();
+ let cap = manager.all_procs.capacity();
+ if len < cap / 4 {
+ // Shrink to twice the current length. Ignore allocation failures since this
+ // is just an optimization; the vector remains valid even if shrinking fails.
+ let _ = manager.all_procs.shrink_to(len * 2, GFP_KERNEL);
+ }
}
pub(crate) fn set_manager_node(&self, node_ref: NodeRef) -> Result {
diff --git a/drivers/android/binder/error.rs b/drivers/android/binder/error.rs
index b24497cfa292..45d85d4c2815 100644
--- a/drivers/android/binder/error.rs
+++ b/drivers/android/binder/error.rs
@@ -13,7 +13,7 @@ pub(crate) type BinderResult<T = ()> = core::result::Result<T, BinderError>;
/// errno.
pub(crate) struct BinderError {
pub(crate) reply: u32,
- source: Option<Error>,
+ pub(crate) source: Option<Error>,
}
impl BinderError {
@@ -41,14 +41,6 @@ impl BinderError {
pub(crate) fn is_dead(&self) -> bool {
self.reply == BR_DEAD_REPLY
}
-
- pub(crate) fn as_errno(&self) -> kernel::ffi::c_int {
- self.source.unwrap_or(EINVAL).to_errno()
- }
-
- pub(crate) fn should_pr_warn(&self) -> bool {
- self.source.is_some()
- }
}
/// Convert an errno into a `BinderError` and store the errno used to construct it. The errno
diff --git a/drivers/android/binder/process.rs b/drivers/android/binder/process.rs
index f06498129aa9..820cbd541435 100644
--- a/drivers/android/binder/process.rs
+++ b/drivers/android/binder/process.rs
@@ -48,6 +48,7 @@ use crate::{
range_alloc::{RangeAllocator, ReserveNew, ReserveNewArgs},
stats::BinderStats,
thread::{PushWorkRes, Thread},
+ transaction::TransactionInfo,
BinderfsProcFile, DArc, DLArc, DTRWrap, DeliverToRead,
};
@@ -681,7 +682,7 @@ impl Process {
fn get_current_thread(self: ArcBorrow<'_, Self>) -> Result<Arc<Thread>> {
let id = {
let current = kernel::current!();
- if !core::ptr::eq(current.group_leader(), &*self.task) {
+ if self.task != current.group_leader() {
pr_err!("get_current_thread was called from the wrong process.");
return Err(EINVAL);
}
@@ -1003,16 +1004,15 @@ impl Process {
self: &Arc<Self>,
debug_id: usize,
size: usize,
- is_oneway: bool,
- from_pid: i32,
+ info: &mut TransactionInfo,
) -> BinderResult<NewAllocation> {
use kernel::page::PAGE_SIZE;
let mut reserve_new_args = ReserveNewArgs {
debug_id,
size,
- is_oneway,
- pid: from_pid,
+ is_oneway: info.is_oneway(),
+ pid: info.from_pid,
..ReserveNewArgs::default()
};
@@ -1028,13 +1028,13 @@ impl Process {
reserve_new_args = alloc_request.make_alloc()?;
};
+ info.oneway_spam_suspect = new_alloc.oneway_spam_detected;
let res = Allocation::new(
self.clone(),
debug_id,
new_alloc.offset,
size,
addr + new_alloc.offset,
- new_alloc.oneway_spam_detected,
);
// This allocation will be marked as in use until the `Allocation` is used to free it.
@@ -1066,7 +1066,7 @@ impl Process {
let mapping = inner.mapping.as_mut()?;
let offset = ptr.checked_sub(mapping.address)?;
let (size, debug_id, odata) = mapping.alloc.reserve_existing(offset).ok()?;
- let mut alloc = Allocation::new(self.clone(), debug_id, offset, size, ptr, false);
+ let mut alloc = Allocation::new(self.clone(), debug_id, offset, size, ptr);
if let Some(data) = odata {
alloc.set_info(data);
}
@@ -1414,8 +1414,7 @@ impl Process {
.alloc
.take_for_each(|offset, size, debug_id, odata| {
let ptr = offset + address;
- let mut alloc =
- Allocation::new(self.clone(), debug_id, offset, size, ptr, false);
+ let mut alloc = Allocation::new(self.clone(), debug_id, offset, size, ptr);
if let Some(data) = odata {
alloc.set_info(data);
}
@@ -1443,6 +1442,9 @@ impl Process {
}
}
+ // #[export_name] is a temporary workaround so that ps output does not become unreadable from
+ // mangled symbol names.
+ #[export_name = "rust_binder_freeze"]
pub(crate) fn ioctl_freeze(&self, info: &BinderFreezeInfo) -> Result {
if info.enable == 0 {
let msgs = self.prepare_freeze_messages()?;
@@ -1657,11 +1659,14 @@ impl Process {
const _IOC_READ_WRITE: u32 = _IOC_READ | _IOC_WRITE;
- match _IOC_DIR(cmd) {
+ let res = match _IOC_DIR(cmd) {
_IOC_WRITE => Self::ioctl_write_only(this, file, cmd, &mut user_slice.reader()),
_IOC_READ_WRITE => Self::ioctl_write_read(this, file, cmd, user_slice),
_ => Err(EINVAL),
- }
+ };
+
+ crate::trace::trace_ioctl_done(res);
+ res
}
pub(crate) fn mmap(
@@ -1670,7 +1675,7 @@ impl Process {
vma: &mm::virt::VmaNew,
) -> Result {
// We don't allow mmap to be used in a different process.
- if !core::ptr::eq(kernel::current!().group_leader(), &*this.task) {
+ if this.task != kernel::current!().group_leader() {
return Err(EINVAL);
}
if vma.start() == 0 {
diff --git a/drivers/android/binder/rust_binder.h b/drivers/android/binder/rust_binder.h
index d2284726c025..3936b9d0b8cd 100644
--- a/drivers/android/binder/rust_binder.h
+++ b/drivers/android/binder/rust_binder.h
@@ -99,4 +99,9 @@ static inline size_t rust_binder_node_debug_id(rust_binder_node t)
return *(size_t *) (t + RUST_BINDER_LAYOUT.n.debug_id);
}
+static inline binder_uintptr_t rust_binder_node_ptr(rust_binder_node t)
+{
+ return *(binder_uintptr_t *) (t + RUST_BINDER_LAYOUT.n.ptr);
+}
+
#endif
diff --git a/drivers/android/binder/rust_binder_events.h b/drivers/android/binder/rust_binder_events.h
index 8ad785c6bd0f..1a446787c8b3 100644
--- a/drivers/android/binder/rust_binder_events.h
+++ b/drivers/android/binder/rust_binder_events.h
@@ -15,7 +15,7 @@
#include <linux/tracepoint.h>
-TRACE_EVENT(rust_binder_ioctl,
+TRACE_EVENT(binder_ioctl,
TP_PROTO(unsigned int cmd, unsigned long arg),
TP_ARGS(cmd, arg),
@@ -30,7 +30,46 @@ TRACE_EVENT(rust_binder_ioctl,
TP_printk("cmd=0x%x arg=0x%lx", __entry->cmd, __entry->arg)
);
-TRACE_EVENT(rust_binder_transaction,
+DECLARE_EVENT_CLASS(binder_function_return_class,
+ TP_PROTO(int ret),
+ TP_ARGS(ret),
+ TP_STRUCT__entry(
+ __field(int, ret)
+ ),
+ TP_fast_assign(
+ __entry->ret = ret;
+ ),
+ TP_printk("ret=%d", __entry->ret)
+);
+
+#define DEFINE_RBINDER_FUNCTION_RETURN_EVENT(name) \
+DEFINE_EVENT(binder_function_return_class, name, \
+ TP_PROTO(int ret), \
+ TP_ARGS(ret))
+
+DEFINE_RBINDER_FUNCTION_RETURN_EVENT(binder_ioctl_done);
+DEFINE_RBINDER_FUNCTION_RETURN_EVENT(binder_read_done);
+DEFINE_RBINDER_FUNCTION_RETURN_EVENT(binder_write_done);
+
+TRACE_EVENT(binder_wait_for_work,
+ TP_PROTO(bool proc_work, bool transaction_stack, bool thread_todo),
+ TP_ARGS(proc_work, transaction_stack, thread_todo),
+ TP_STRUCT__entry(
+ __field(bool, proc_work)
+ __field(bool, transaction_stack)
+ __field(bool, thread_todo)
+ ),
+ TP_fast_assign(
+ __entry->proc_work = proc_work;
+ __entry->transaction_stack = transaction_stack;
+ __entry->thread_todo = thread_todo;
+ ),
+ TP_printk("proc_work=%d transaction_stack=%d thread_todo=%d",
+ __entry->proc_work, __entry->transaction_stack,
+ __entry->thread_todo)
+);
+
+TRACE_EVENT(binder_transaction,
TP_PROTO(bool reply, rust_binder_transaction t, struct task_struct *thread),
TP_ARGS(reply, t, thread),
TP_STRUCT__entry(
@@ -60,6 +99,84 @@ TRACE_EVENT(rust_binder_transaction,
__entry->reply, __entry->flags, __entry->code)
);
+TRACE_EVENT(binder_transaction_received,
+ TP_PROTO(rust_binder_transaction t),
+ TP_ARGS(t),
+ TP_STRUCT__entry(
+ __field(int, debug_id)
+ ),
+ TP_fast_assign(
+ __entry->debug_id = rust_binder_transaction_debug_id(t);
+ ),
+ TP_printk("transaction=%d", __entry->debug_id)
+);
+
+TRACE_EVENT(binder_transaction_fd_send,
+ TP_PROTO(int t_debug_id, int fd, size_t offset),
+ TP_ARGS(t_debug_id, fd, offset),
+ TP_STRUCT__entry(
+ __field(int, debug_id)
+ __field(int, fd)
+ __field(size_t, offset)
+ ),
+ TP_fast_assign(
+ __entry->debug_id = t_debug_id;
+ __entry->fd = fd;
+ __entry->offset = offset;
+ ),
+ TP_printk("transaction=%d src_fd=%d offset=%zu",
+ __entry->debug_id, __entry->fd, __entry->offset)
+);
+
+TRACE_EVENT(binder_transaction_fd_recv,
+ TP_PROTO(int t_debug_id, int fd, size_t offset),
+ TP_ARGS(t_debug_id, fd, offset),
+ TP_STRUCT__entry(
+ __field(int, debug_id)
+ __field(int, fd)
+ __field(size_t, offset)
+ ),
+ TP_fast_assign(
+ __entry->debug_id = t_debug_id;
+ __entry->fd = fd;
+ __entry->offset = offset;
+ ),
+ TP_printk("transaction=%d dest_fd=%d offset=%zu",
+ __entry->debug_id, __entry->fd, __entry->offset)
+);
+
+TRACE_EVENT(binder_command,
+ TP_PROTO(uint32_t cmd),
+ TP_ARGS(cmd),
+ TP_STRUCT__entry(
+ __field(uint32_t, cmd)
+ ),
+ TP_fast_assign(
+ __entry->cmd = cmd;
+ ),
+ TP_printk("cmd=0x%x %s",
+ __entry->cmd,
+ _IOC_NR(__entry->cmd) < ARRAY_SIZE(binder_command_strings) ?
+ binder_command_strings[_IOC_NR(__entry->cmd)] :
+ "unknown")
+);
+
+TRACE_EVENT(binder_return,
+ TP_PROTO(uint32_t cmd),
+ TP_ARGS(cmd),
+ TP_STRUCT__entry(
+ __field(uint32_t, cmd)
+ ),
+ TP_fast_assign(
+ __entry->cmd = cmd;
+ ),
+ TP_printk("cmd=0x%x %s",
+ __entry->cmd,
+ _IOC_NR(__entry->cmd) < ARRAY_SIZE(binder_return_strings) ?
+ binder_return_strings[_IOC_NR(__entry->cmd)] :
+ "unknown")
+);
+
#endif /* _RUST_BINDER_TRACE_H */
/* This part must be outside protection */
diff --git a/drivers/android/binder/rust_binder_main.rs b/drivers/android/binder/rust_binder_main.rs
index 632b54714e44..dc1941cd2407 100644
--- a/drivers/android/binder/rust_binder_main.rs
+++ b/drivers/android/binder/rust_binder_main.rs
@@ -118,6 +118,7 @@ impl<'a> BinderReturnWriter<'a> {
/// Write a return code back to user space.
/// Should be a `BR_` constant from [`defs`] e.g. [`defs::BR_TRANSACTION_COMPLETE`].
fn write_code(&mut self, code: u32) -> Result {
+ crate::trace::trace_return(code);
stats::GLOBAL_STATS.inc_br(code);
self.thread.process.stats.inc_br(code);
self.writer.write(&code)
@@ -294,8 +295,6 @@ impl kernel::Module for BinderModule {
// SAFETY: The module initializer never runs twice, so we only call this once.
unsafe { crate::context::CONTEXTS.init() };
- pr_warn!("Loaded Rust Binder.");
-
BINDER_SHRINKER.register(c"android-binder")?;
// SAFETY: The module is being loaded, so we can initialize binderfs.
diff --git a/drivers/android/binder/thread.rs b/drivers/android/binder/thread.rs
index c004214b1662..97d5f31e8fe3 100644
--- a/drivers/android/binder/thread.rs
+++ b/drivers/android/binder/thread.rs
@@ -19,7 +19,7 @@ use kernel::{
sync::poll::{PollCondVar, PollTable},
sync::{aref::ARef, Arc, SpinLock},
task::Task,
- uaccess::UserSlice,
+ uaccess::{UserPtr, UserSlice, UserSliceReader},
uapi,
};
@@ -30,7 +30,7 @@ use crate::{
process::{GetWorkOrRegister, Process},
ptr_align,
stats::GLOBAL_STATS,
- transaction::Transaction,
+ transaction::{Transaction, TransactionInfo},
BinderReturnWriter, DArc, DLArc, DTRWrap, DeliverCode, DeliverToRead,
};
@@ -513,6 +513,9 @@ impl Thread {
/// Attempts to fetch a work item from the thread-local queue. The behaviour if the queue is
/// empty depends on `wait`: if it is true, the function waits for some work to be queued (or a
/// signal); otherwise it returns indicating that none is available.
+ // #[export_name] is a temporary workaround so that ps output does not become unreadable from
+ // mangled symbol names.
+ #[export_name = "rust_binder_waitlcl"]
fn get_work_local(self: &Arc<Self>, wait: bool) -> Result<Option<DLArc<dyn DeliverToRead>>> {
{
let mut inner = self.inner.lock();
@@ -551,6 +554,9 @@ impl Thread {
///
/// This must only be called when the thread is not participating in a transaction chain. If it
/// is, the local version (`get_work_local`) should be used instead.
+ // #[export_name] is a temporary workaround so that ps output does not become unreadable from
+ // mangled symbol names.
+ #[export_name = "rust_binder_wait"]
fn get_work(self: &Arc<Self>, wait: bool) -> Result<Option<DLArc<dyn DeliverToRead>>> {
// Try to get work from the thread's work queue, using only a local lock.
{
@@ -706,6 +712,7 @@ impl Thread {
core::mem::offset_of!(uapi::binder_fd_object, __bindgen_anon_1.fd);
let field_offset = offset + FD_FIELD_OFFSET;
+ crate::trace::trace_transaction_fd_send(view.alloc.debug_id, fd, field_offset);
view.alloc.info_add_fd(file, field_offset, false)?;
}
@@ -945,13 +952,11 @@ impl Thread {
pub(crate) fn copy_transaction_data(
&self,
to_process: Arc<Process>,
- tr: &BinderTransactionDataSg,
+ info: &mut TransactionInfo,
debug_id: usize,
allow_fds: bool,
txn_security_ctx_offset: Option<&mut usize>,
) -> BinderResult<NewAllocation> {
- let trd = &tr.transaction_data;
- let is_oneway = trd.flags & TF_ONE_WAY != 0;
let mut secctx = if let Some(offset) = txn_security_ctx_offset {
let secid = self.process.cred.get_secid();
let ctx = match security::SecurityCtx::from_secid(secid) {
@@ -966,10 +971,10 @@ impl Thread {
None
};
- let data_size = trd.data_size.try_into().map_err(|_| EINVAL)?;
+ let data_size = info.data_size;
let aligned_data_size = ptr_align(data_size).ok_or(EINVAL)?;
- let offsets_size: usize = trd.offsets_size.try_into().map_err(|_| EINVAL)?;
- let buffers_size: usize = tr.buffers_size.try_into().map_err(|_| EINVAL)?;
+ let offsets_size = info.offsets_size;
+ let buffers_size = info.buffers_size;
let aligned_secctx_size = match secctx.as_ref() {
Some((_offset, ctx)) => ptr_align(ctx.len()).ok_or(EINVAL)?,
None => 0,
@@ -992,32 +997,25 @@ impl Thread {
size_of::<u64>(),
);
let secctx_off = aligned_data_size + offsets_size + buffers_size;
- let mut alloc =
- match to_process.buffer_alloc(debug_id, len, is_oneway, self.process.task.pid()) {
- Ok(alloc) => alloc,
- Err(err) => {
- pr_warn!(
- "Failed to allocate buffer. len:{}, is_oneway:{}",
- len,
- is_oneway
- );
- return Err(err);
- }
- };
+ let mut alloc = match to_process.buffer_alloc(debug_id, len, info) {
+ Ok(alloc) => alloc,
+ Err(err) => {
+ pr_warn!(
+ "Failed to allocate buffer. len:{}, is_oneway:{}",
+ len,
+ info.is_oneway(),
+ );
+ return Err(err);
+ }
+ };
- // SAFETY: This accesses a union field, but it's okay because the field's type is valid for
- // all bit-patterns.
- let trd_data_ptr = unsafe { &trd.data.ptr };
- let mut buffer_reader =
- UserSlice::new(UserPtr::from_addr(trd_data_ptr.buffer as _), data_size).reader();
+ let mut buffer_reader = UserSlice::new(info.data_ptr, data_size).reader();
let mut end_of_previous_object = 0;
let mut sg_state = None;
// Copy offsets if there are any.
if offsets_size > 0 {
- let mut offsets_reader =
- UserSlice::new(UserPtr::from_addr(trd_data_ptr.offsets as _), offsets_size)
- .reader();
+ let mut offsets_reader = UserSlice::new(info.offsets_ptr, offsets_size).reader();
let offsets_start = aligned_data_size;
let offsets_end = aligned_data_size + offsets_size;
@@ -1192,37 +1190,92 @@ impl Thread {
}
}
- fn transaction<T>(self: &Arc<Self>, tr: &BinderTransactionDataSg, inner: T)
- where
- T: FnOnce(&Arc<Self>, &BinderTransactionDataSg) -> BinderResult,
- {
- if let Err(err) = inner(self, tr) {
- if err.should_pr_warn() {
- let mut ee = self.inner.lock().extended_error;
- ee.command = err.reply;
- ee.param = err.as_errno();
- pr_warn!(
- "Transaction failed: {:?} my_pid:{}",
- err,
- self.process.pid_in_current_ns()
- );
+ // No inlining avoids allocating stack space for `BinderTransactionData` for the entire
+ // duration of `transaction()`.
+ #[inline(never)]
+ fn read_transaction_info(
+ &self,
+ cmd: u32,
+ reader: &mut UserSliceReader,
+ info: &mut TransactionInfo,
+ ) -> Result<()> {
+ let td = match cmd {
+ BC_TRANSACTION | BC_REPLY => {
+ reader.read::<BinderTransactionData>()?.with_buffers_size(0)
+ }
+ BC_TRANSACTION_SG | BC_REPLY_SG => reader.read::<BinderTransactionDataSg>()?,
+ _ => return Err(EINVAL),
+ };
+
+ // SAFETY: Above `read` call initializes all bytes, so this union read is ok.
+ let trd_data_ptr = unsafe { &td.transaction_data.data.ptr };
+
+ info.is_reply = matches!(cmd, BC_REPLY | BC_REPLY_SG);
+ info.from_pid = self.process.task.pid();
+ info.from_tid = self.id;
+ info.code = td.transaction_data.code;
+ info.flags = td.transaction_data.flags;
+ info.data_ptr = UserPtr::from_addr(trd_data_ptr.buffer as usize);
+ info.data_size = td.transaction_data.data_size as usize;
+ info.offsets_ptr = UserPtr::from_addr(trd_data_ptr.offsets as usize);
+ info.offsets_size = td.transaction_data.offsets_size as usize;
+ info.buffers_size = td.buffers_size as usize;
+ // SAFETY: Above `read` call initializes all bytes, so this union read is ok.
+ info.target_handle = unsafe { td.transaction_data.target.handle };
+ Ok(())
+ }
+
+ #[inline(never)]
+ fn transaction(self: &Arc<Self>, cmd: u32, reader: &mut UserSliceReader) -> Result<()> {
+ let mut info = TransactionInfo::zeroed();
+ self.read_transaction_info(cmd, reader, &mut info)?;
+
+ let ret = if info.is_reply {
+ self.reply_inner(&mut info)
+ } else if info.is_oneway() {
+ self.oneway_transaction_inner(&mut info)
+ } else {
+ self.transaction_inner(&mut info)
+ };
+
+ if let Err(err) = ret {
+ if err.reply != BR_TRANSACTION_COMPLETE {
+ info.reply = err.reply;
}
self.push_return_work(err.reply);
+ if let Some(source) = &err.source {
+ info.errno = source.to_errno();
+ info.reply = err.reply;
+
+ {
+ let mut ee = self.inner.lock().extended_error;
+ ee.command = err.reply;
+ ee.param = source.to_errno();
+ }
+
+ pr_warn!(
+ "{}:{} transaction to {} failed: {source:?}",
+ info.from_pid,
+ info.from_tid,
+ info.to_pid
+ );
+ }
}
+
+ Ok(())
}
- fn transaction_inner(self: &Arc<Self>, tr: &BinderTransactionDataSg) -> BinderResult {
- // SAFETY: Handle's type has no invalid bit patterns.
- let handle = unsafe { tr.transaction_data.target.handle };
- let node_ref = self.process.get_transaction_node(handle)?;
+ fn transaction_inner(self: &Arc<Self>, info: &mut TransactionInfo) -> BinderResult {
+ let node_ref = self.process.get_transaction_node(info.target_handle)?;
+ info.to_pid = node_ref.node.owner.task.pid();
security::binder_transaction(&self.process.cred, &node_ref.node.owner.cred)?;
// TODO: We need to ensure that there isn't a pending transaction in the work queue. How
// could this happen?
let top = self.top_of_transaction_stack()?;
let list_completion = DTRWrap::arc_try_new(DeliverCode::new(BR_TRANSACTION_COMPLETE))?;
let completion = list_completion.clone_arc();
- let transaction = Transaction::new(node_ref, top, self, tr)?;
+ let transaction = Transaction::new(node_ref, top, self, info)?;
// Check that the transaction stack hasn't changed while the lock was released, then update
// it with the new transaction.
@@ -1238,7 +1291,7 @@ impl Thread {
inner.push_work_deferred(list_completion);
}
- if let Err(e) = transaction.submit() {
+ if let Err(e) = transaction.submit(info) {
completion.skip();
// Define `transaction` first to drop it after `inner`.
let transaction;
@@ -1251,18 +1304,21 @@ impl Thread {
}
}
- fn reply_inner(self: &Arc<Self>, tr: &BinderTransactionDataSg) -> BinderResult {
+ fn reply_inner(self: &Arc<Self>, info: &mut TransactionInfo) -> BinderResult {
let orig = self.inner.lock().pop_transaction_to_reply(self)?;
if !orig.from.is_current_transaction(&orig) {
return Err(EINVAL.into());
}
+ info.to_tid = orig.from.id;
+ info.to_pid = orig.from.process.task.pid();
+
// We need to complete the transaction even if we cannot complete building the reply.
let out = (|| -> BinderResult<_> {
let completion = DTRWrap::arc_try_new(DeliverCode::new(BR_TRANSACTION_COMPLETE))?;
let process = orig.from.process.clone();
let allow_fds = orig.flags & TF_ACCEPT_FDS != 0;
- let reply = Transaction::new_reply(self, process, tr, allow_fds)?;
+ let reply = Transaction::new_reply(self, process, info, allow_fds)?;
self.inner.lock().push_work(completion);
orig.from.deliver_reply(Ok(reply), &orig);
Ok(())
@@ -1283,16 +1339,12 @@ impl Thread {
out
}
- fn oneway_transaction_inner(self: &Arc<Self>, tr: &BinderTransactionDataSg) -> BinderResult {
- // SAFETY: The `handle` field is valid for all possible byte values, so reading from the
- // union is okay.
- let handle = unsafe { tr.transaction_data.target.handle };
- let node_ref = self.process.get_transaction_node(handle)?;
+ fn oneway_transaction_inner(self: &Arc<Self>, info: &mut TransactionInfo) -> BinderResult {
+ let node_ref = self.process.get_transaction_node(info.target_handle)?;
+ info.to_pid = node_ref.node.owner.task.pid();
security::binder_transaction(&self.process.cred, &node_ref.node.owner.cred)?;
- let transaction = Transaction::new(node_ref, None, self, tr)?;
- let code = if self.process.is_oneway_spam_detection_enabled()
- && transaction.oneway_spam_detected
- {
+ let transaction = Transaction::new(node_ref, None, self, info)?;
+ let code = if self.process.is_oneway_spam_detection_enabled() && info.oneway_spam_suspect {
BR_ONEWAY_SPAM_SUSPECT
} else {
BR_TRANSACTION_COMPLETE
@@ -1300,7 +1352,7 @@ impl Thread {
let list_completion = DTRWrap::arc_try_new(DeliverCode::new(code))?;
let completion = list_completion.clone_arc();
self.inner.lock().push_work(list_completion);
- match transaction.submit() {
+ match transaction.submit(info) {
Ok(()) => Ok(()),
Err(err) => {
completion.skip();
@@ -1318,32 +1370,12 @@ impl Thread {
while reader.len() >= size_of::<u32>() && self.inner.lock().return_work.is_unused() {
let before = reader.len();
let cmd = reader.read::<u32>()?;
+ crate::trace::trace_command(cmd);
GLOBAL_STATS.inc_bc(cmd);
self.process.stats.inc_bc(cmd);
match cmd {
- BC_TRANSACTION => {
- let tr = reader.read::<BinderTransactionData>()?.with_buffers_size(0);
- if tr.transaction_data.flags & TF_ONE_WAY != 0 {
- self.transaction(&tr, Self::oneway_transaction_inner);
- } else {
- self.transaction(&tr, Self::transaction_inner);
- }
- }
- BC_TRANSACTION_SG => {
- let tr = reader.read::<BinderTransactionDataSg>()?;
- if tr.transaction_data.flags & TF_ONE_WAY != 0 {
- self.transaction(&tr, Self::oneway_transaction_inner);
- } else {
- self.transaction(&tr, Self::transaction_inner);
- }
- }
- BC_REPLY => {
- let tr = reader.read::<BinderTransactionData>()?.with_buffers_size(0);
- self.transaction(&tr, Self::reply_inner)
- }
- BC_REPLY_SG => {
- let tr = reader.read::<BinderTransactionDataSg>()?;
- self.transaction(&tr, Self::reply_inner)
+ BC_TRANSACTION | BC_TRANSACTION_SG | BC_REPLY | BC_REPLY_SG => {
+ self.transaction(cmd, &mut reader)?;
}
BC_FREE_BUFFER => {
let buffer = self.process.buffer_get(reader.read()?);
@@ -1407,11 +1439,18 @@ impl Thread {
UserSlice::new(UserPtr::from_addr(read_start as _), read_len as _).writer(),
self,
);
- let (in_pool, use_proc_queue) = {
+ let (in_pool, has_transaction, thread_todo, use_proc_queue) = {
let inner = self.inner.lock();
- (inner.is_looper(), inner.should_use_process_work_queue())
+ (
+ inner.is_looper(),
+ inner.current_transaction.is_some(),
+ !inner.work_list.is_empty(),
+ inner.should_use_process_work_queue(),
+ )
};
+ crate::trace::trace_wait_for_work(use_proc_queue, has_transaction, thread_todo);
+
let getter = if use_proc_queue {
Self::get_work
} else {
@@ -1477,6 +1516,7 @@ impl Thread {
let mut ret = Ok(());
if req.write_size > 0 {
ret = self.write(&mut req);
+ crate::trace::trace_write_done(ret);
if let Err(err) = ret {
pr_warn!(
"Write failure {:?} in pid:{}",
@@ -1493,6 +1533,7 @@ impl Thread {
// Go through the work queue.
if req.read_size > 0 {
ret = self.read(&mut req, wait);
+ crate::trace::trace_read_done(ret);
if ret.is_err() && ret != Err(EINTR) {
pr_warn!(
"Read failure {:?} in pid:{}",
diff --git a/drivers/android/binder/trace.rs b/drivers/android/binder/trace.rs
index 9839901c7151..5539672d7285 100644
--- a/drivers/android/binder/trace.rs
+++ b/drivers/android/binder/trace.rs
@@ -5,13 +5,23 @@
use crate::transaction::Transaction;
use kernel::bindings::{rust_binder_transaction, task_struct};
-use kernel::ffi::{c_uint, c_ulong};
+use kernel::error::Result;
+use kernel::ffi::{c_int, c_uint, c_ulong};
use kernel::task::Task;
use kernel::tracepoint::declare_trace;
declare_trace! {
- unsafe fn rust_binder_ioctl(cmd: c_uint, arg: c_ulong);
- unsafe fn rust_binder_transaction(reply: bool, t: rust_binder_transaction, thread: *mut task_struct);
+ unsafe fn binder_ioctl(cmd: c_uint, arg: c_ulong);
+ unsafe fn binder_ioctl_done(ret: c_int);
+ unsafe fn binder_read_done(ret: c_int);
+ unsafe fn binder_write_done(ret: c_int);
+ unsafe fn binder_wait_for_work(proc_work: bool, transaction_stack: bool, thread_todo: bool);
+ unsafe fn binder_transaction(reply: bool, t: rust_binder_transaction, thread: *mut task_struct);
+ unsafe fn binder_transaction_received(t: rust_binder_transaction);
+ unsafe fn binder_transaction_fd_send(t_debug_id: c_int, fd: c_int, offset: usize);
+ unsafe fn binder_transaction_fd_recv(t_debug_id: c_int, fd: c_int, offset: usize);
+ unsafe fn binder_command(cmd: u32);
+ unsafe fn binder_return(ret: u32);
}
#[inline]
@@ -20,9 +30,39 @@ fn raw_transaction(t: &Transaction) -> rust_binder_transaction {
}
#[inline]
+fn to_errno(ret: Result) -> i32 {
+ match ret {
+ Ok(()) => 0,
+ Err(err) => err.to_errno(),
+ }
+}
+
+#[inline]
pub(crate) fn trace_ioctl(cmd: u32, arg: usize) {
// SAFETY: Always safe to call.
- unsafe { rust_binder_ioctl(cmd, arg as c_ulong) }
+ unsafe { binder_ioctl(cmd, arg as c_ulong) }
+}
+
+#[inline]
+pub(crate) fn trace_ioctl_done(ret: Result) {
+ // SAFETY: Always safe to call.
+ unsafe { binder_ioctl_done(to_errno(ret)) }
+}
+#[inline]
+pub(crate) fn trace_read_done(ret: Result) {
+ // SAFETY: Always safe to call.
+ unsafe { binder_read_done(to_errno(ret)) }
+}
+#[inline]
+pub(crate) fn trace_write_done(ret: Result) {
+ // SAFETY: Always safe to call.
+ unsafe { binder_write_done(to_errno(ret)) }
+}
+
+#[inline]
+pub(crate) fn trace_wait_for_work(proc_work: bool, transaction_stack: bool, thread_todo: bool) {
+ // SAFETY: Always safe to call.
+ unsafe { binder_wait_for_work(proc_work, transaction_stack, thread_todo) }
}
#[inline]
@@ -33,5 +73,33 @@ pub(crate) fn trace_transaction(reply: bool, t: &Transaction, thread: Option<&Ta
};
// SAFETY: The raw transaction is valid for the duration of this call. The thread pointer is
// valid or null.
- unsafe { rust_binder_transaction(reply, raw_transaction(t), thread) }
+ unsafe { binder_transaction(reply, raw_transaction(t), thread) }
+}
+
+#[inline]
+pub(crate) fn trace_transaction_received(t: &Transaction) {
+ // SAFETY: The raw transaction is valid for the duration of this call.
+ unsafe { binder_transaction_received(raw_transaction(t)) }
+}
+
+#[inline]
+pub(crate) fn trace_transaction_fd_send(t_debug_id: usize, fd: u32, offset: usize) {
+ // SAFETY: This function is always safe to call.
+ unsafe { binder_transaction_fd_send(t_debug_id as c_int, fd as c_int, offset) }
+}
+#[inline]
+pub(crate) fn trace_transaction_fd_recv(t_debug_id: usize, fd: u32, offset: usize) {
+ // SAFETY: This function is always safe to call.
+ unsafe { binder_transaction_fd_recv(t_debug_id as c_int, fd as c_int, offset) }
+}
+
+#[inline]
+pub(crate) fn trace_command(cmd: u32) {
+ // SAFETY: This function is always safe to call.
+ unsafe { binder_command(cmd) }
+}
+#[inline]
+pub(crate) fn trace_return(ret: u32) {
+ // SAFETY: This function is always safe to call.
+ unsafe { binder_return(ret) }
}
diff --git a/drivers/android/binder/transaction.rs b/drivers/android/binder/transaction.rs
index 75e6f5fbaaae..47d5e4d88b07 100644
--- a/drivers/android/binder/transaction.rs
+++ b/drivers/android/binder/transaction.rs
@@ -8,7 +8,7 @@ use kernel::{
seq_print,
sync::atomic::{ordering::Relaxed, Atomic},
sync::{Arc, SpinLock},
- task::Kuid,
+ task::{Kuid, Pid},
time::{Instant, Monotonic},
types::ScopeGuard,
};
@@ -24,6 +24,33 @@ use crate::{
BinderReturnWriter, DArc, DLArc, DTRWrap, DeliverToRead,
};
+#[derive(Zeroable)]
+pub(crate) struct TransactionInfo {
+ pub(crate) from_pid: Pid,
+ pub(crate) from_tid: Pid,
+ pub(crate) to_pid: Pid,
+ pub(crate) to_tid: Pid,
+ pub(crate) code: u32,
+ pub(crate) flags: u32,
+ pub(crate) data_ptr: UserPtr,
+ pub(crate) data_size: usize,
+ pub(crate) offsets_ptr: UserPtr,
+ pub(crate) offsets_size: usize,
+ pub(crate) buffers_size: usize,
+ pub(crate) target_handle: u32,
+ pub(crate) errno: i32,
+ pub(crate) reply: u32,
+ pub(crate) oneway_spam_suspect: bool,
+ pub(crate) is_reply: bool,
+}
+
+impl TransactionInfo {
+ #[inline]
+ pub(crate) fn is_oneway(&self) -> bool {
+ self.flags & TF_ONE_WAY != 0
+ }
+}
+
use core::mem::offset_of;
use kernel::bindings::rb_transaction_layout;
pub(crate) const TRANSACTION_LAYOUT: rb_transaction_layout = rb_transaction_layout {
@@ -52,7 +79,6 @@ pub(crate) struct Transaction {
data_address: usize,
sender_euid: Kuid,
txn_security_ctx_off: Option<usize>,
- pub(crate) oneway_spam_detected: bool,
start_time: Instant<Monotonic>,
}
@@ -65,17 +91,16 @@ impl Transaction {
node_ref: NodeRef,
from_parent: Option<DArc<Transaction>>,
from: &Arc<Thread>,
- tr: &BinderTransactionDataSg,
+ info: &mut TransactionInfo,
) -> BinderResult<DLArc<Self>> {
let debug_id = super::next_debug_id();
- let trd = &tr.transaction_data;
let allow_fds = node_ref.node.flags & FLAT_BINDER_FLAG_ACCEPTS_FDS != 0;
let txn_security_ctx = node_ref.node.flags & FLAT_BINDER_FLAG_TXN_SECURITY_CTX != 0;
let mut txn_security_ctx_off = if txn_security_ctx { Some(0) } else { None };
let to = node_ref.node.owner.clone();
let mut alloc = match from.copy_transaction_data(
to.clone(),
- tr,
+ info,
debug_id,
allow_fds,
txn_security_ctx_off.as_mut(),
@@ -88,15 +113,14 @@ impl Transaction {
return Err(err);
}
};
- let oneway_spam_detected = alloc.oneway_spam_detected;
- if trd.flags & TF_ONE_WAY != 0 {
+ if info.is_oneway() {
if from_parent.is_some() {
pr_warn!("Oneway transaction should not be in a transaction stack.");
return Err(EINVAL.into());
}
alloc.set_info_oneway_node(node_ref.node.clone());
}
- if trd.flags & TF_CLEAR_BUF != 0 {
+ if info.flags & TF_CLEAR_BUF != 0 {
alloc.set_info_clear_on_drop();
}
let target_node = node_ref.node.clone();
@@ -107,18 +131,17 @@ impl Transaction {
debug_id,
target_node: Some(target_node),
from_parent,
- sender_euid: from.process.task.euid(),
+ sender_euid: Kuid::current_euid(),
from: from.clone(),
to,
- code: trd.code,
- flags: trd.flags,
- data_size: trd.data_size as _,
- offsets_size: trd.offsets_size as _,
+ code: info.code,
+ flags: info.flags,
+ data_size: info.data_size,
+ offsets_size: info.offsets_size,
data_address,
allocation <- kernel::new_spinlock!(Some(alloc.success()), "Transaction::new"),
is_outstanding: Atomic::new(false),
txn_security_ctx_off,
- oneway_spam_detected,
start_time: Instant::now(),
}))?)
}
@@ -126,39 +149,36 @@ impl Transaction {
pub(crate) fn new_reply(
from: &Arc<Thread>,
to: Arc<Process>,
- tr: &BinderTransactionDataSg,
+ info: &mut TransactionInfo,
allow_fds: bool,
) -> BinderResult<DLArc<Self>> {
let debug_id = super::next_debug_id();
- let trd = &tr.transaction_data;
- let mut alloc = match from.copy_transaction_data(to.clone(), tr, debug_id, allow_fds, None)
- {
- Ok(alloc) => alloc,
- Err(err) => {
- pr_warn!("Failure in copy_transaction_data: {:?}", err);
- return Err(err);
- }
- };
- let oneway_spam_detected = alloc.oneway_spam_detected;
- if trd.flags & TF_CLEAR_BUF != 0 {
+ let mut alloc =
+ match from.copy_transaction_data(to.clone(), info, debug_id, allow_fds, None) {
+ Ok(alloc) => alloc,
+ Err(err) => {
+ pr_warn!("Failure in copy_transaction_data: {:?}", err);
+ return Err(err);
+ }
+ };
+ if info.flags & TF_CLEAR_BUF != 0 {
alloc.set_info_clear_on_drop();
}
Ok(DTRWrap::arc_pin_init(pin_init!(Transaction {
debug_id,
target_node: None,
from_parent: None,
- sender_euid: from.process.task.euid(),
+ sender_euid: Kuid::current_euid(),
from: from.clone(),
to,
- code: trd.code,
- flags: trd.flags,
- data_size: trd.data_size as _,
- offsets_size: trd.offsets_size as _,
+ code: info.code,
+ flags: info.flags,
+ data_size: info.data_size,
+ offsets_size: info.offsets_size,
data_address: alloc.ptr,
allocation <- kernel::new_spinlock!(Some(alloc.success()), "Transaction::new"),
is_outstanding: Atomic::new(false),
txn_security_ctx_off: None,
- oneway_spam_detected,
start_time: Instant::now(),
}))?)
}
@@ -248,7 +268,7 @@ impl Transaction {
/// stack, otherwise uses the destination process.
///
/// Not used for replies.
- pub(crate) fn submit(self: DLArc<Self>) -> BinderResult {
+ pub(crate) fn submit(self: DLArc<Self>, info: &mut TransactionInfo) -> BinderResult {
// Defined before `process_inner` so that the destructor runs after releasing the lock.
let mut _t_outdated;
@@ -298,6 +318,7 @@ impl Transaction {
}
let res = if let Some(thread) = self.find_target_thread() {
+ info.to_tid = thread.id;
crate::trace::trace_transaction(false, &self, Some(&thread.task));
match thread.push_work(self) {
PushWorkRes::Ok => Ok(()),
@@ -430,6 +451,8 @@ impl DeliverToRead for Transaction {
self.drop_outstanding_txn();
+ crate::trace::trace_transaction_received(&self);
+
// When this is not a reply and not a oneway transaction, update `current_transaction`. If
// it's a reply, `current_transaction` has already been updated appropriately.
if self.target_node.is_some() && tr_sec.transaction_data.flags & TF_ONE_WAY == 0 {
diff --git a/drivers/bus/mhi/ep/main.c b/drivers/bus/mhi/ep/main.c
index e3d0a3cbaf94..0277e1ab1198 100644
--- a/drivers/bus/mhi/ep/main.c
+++ b/drivers/bus/mhi/ep/main.c
@@ -367,7 +367,7 @@ static void mhi_ep_read_completion(struct mhi_ep_buf_info *buf_info)
ret = mhi_ep_send_completion_event(mhi_cntrl, ring, el,
MHI_TRE_DATA_GET_LEN(el),
MHI_EV_CC_EOB);
- if (ret < 0) {
+ if (ret) {
dev_err(&mhi_chan->mhi_dev->dev,
"Error sending transfer compl. event\n");
goto err_free_tre_buf;
@@ -383,7 +383,7 @@ static void mhi_ep_read_completion(struct mhi_ep_buf_info *buf_info)
ret = mhi_ep_send_completion_event(mhi_cntrl, ring, el,
MHI_TRE_DATA_GET_LEN(el),
MHI_EV_CC_EOT);
- if (ret < 0) {
+ if (ret) {
dev_err(&mhi_chan->mhi_dev->dev,
"Error sending transfer compl. event\n");
goto err_free_tre_buf;
@@ -449,7 +449,7 @@ static int mhi_ep_read_channel(struct mhi_ep_cntrl *mhi_cntrl,
dev_dbg(dev, "Reading %zd bytes from channel (%u)\n", tr_len, ring->ch_id);
ret = mhi_cntrl->read_async(mhi_cntrl, &buf_info);
- if (ret < 0) {
+ if (ret) {
dev_err(&mhi_chan->mhi_dev->dev, "Error reading from channel\n");
goto err_free_buf_addr;
}
@@ -494,7 +494,7 @@ static int mhi_ep_process_ch_ring(struct mhi_ep_ring *ring)
} else {
/* UL channel */
ret = mhi_ep_read_channel(mhi_cntrl, ring);
- if (ret < 0) {
+ if (ret) {
dev_err(&mhi_chan->mhi_dev->dev, "Failed to read channel\n");
return ret;
}
@@ -591,7 +591,7 @@ int mhi_ep_queue_skb(struct mhi_ep_device *mhi_dev, struct sk_buff *skb)
dev_dbg(dev, "Writing %zd bytes to channel (%u)\n", tr_len, ring->ch_id);
ret = mhi_cntrl->write_async(mhi_cntrl, &buf_info);
- if (ret < 0) {
+ if (ret) {
dev_err(dev, "Error writing to the channel\n");
goto err_exit;
}
diff --git a/drivers/bus/mhi/ep/ring.c b/drivers/bus/mhi/ep/ring.c
index 9375b16ff2a5..405ce16c02a8 100644
--- a/drivers/bus/mhi/ep/ring.c
+++ b/drivers/bus/mhi/ep/ring.c
@@ -49,7 +49,7 @@ static int __mhi_ep_cache_ring(struct mhi_ep_ring *ring, size_t end)
buf_info.dev_addr = &ring->ring_cache[start];
ret = mhi_cntrl->read_sync(mhi_cntrl, &buf_info);
- if (ret < 0)
+ if (ret)
return ret;
} else {
buf_info.size = (ring->ring_size - start) * sizeof(struct mhi_ring_element);
@@ -57,7 +57,7 @@ static int __mhi_ep_cache_ring(struct mhi_ep_ring *ring, size_t end)
buf_info.dev_addr = &ring->ring_cache[start];
ret = mhi_cntrl->read_sync(mhi_cntrl, &buf_info);
- if (ret < 0)
+ if (ret)
return ret;
if (end) {
@@ -66,7 +66,7 @@ static int __mhi_ep_cache_ring(struct mhi_ep_ring *ring, size_t end)
buf_info.size = end * sizeof(struct mhi_ring_element);
ret = mhi_cntrl->read_sync(mhi_cntrl, &buf_info);
- if (ret < 0)
+ if (ret)
return ret;
}
}
diff --git a/drivers/bus/mhi/host/boot.c b/drivers/bus/mhi/host/boot.c
index f16a1e67a667..19c84913cfb9 100644
--- a/drivers/bus/mhi/host/boot.c
+++ b/drivers/bus/mhi/host/boot.c
@@ -308,7 +308,6 @@ static void mhi_free_bhi_buffer(struct mhi_controller *mhi_cntrl,
struct mhi_buf *mhi_buf = image_info->mhi_buf;
dma_free_coherent(mhi_cntrl->cntrl_dev, mhi_buf->len, mhi_buf->buf, mhi_buf->dma_addr);
- kfree(image_info->mhi_buf);
kfree(image_info);
}
@@ -322,7 +321,6 @@ void mhi_free_bhie_table(struct mhi_controller *mhi_cntrl,
dma_free_coherent(mhi_cntrl->cntrl_dev, mhi_buf->len,
mhi_buf->buf, mhi_buf->dma_addr);
- kfree(image_info->mhi_buf);
kfree(image_info);
}
@@ -333,15 +331,10 @@ static int mhi_alloc_bhi_buffer(struct mhi_controller *mhi_cntrl,
struct image_info *img_info;
struct mhi_buf *mhi_buf;
- img_info = kzalloc_obj(*img_info);
+ img_info = kzalloc_flex(*img_info, mhi_buf, 1);
if (!img_info)
return -ENOMEM;
- /* Allocate memory for entry */
- img_info->mhi_buf = kzalloc_obj(*img_info->mhi_buf);
- if (!img_info->mhi_buf)
- goto error_alloc_mhi_buf;
-
/* Allocate and populate vector table */
mhi_buf = img_info->mhi_buf;
@@ -358,8 +351,6 @@ static int mhi_alloc_bhi_buffer(struct mhi_controller *mhi_cntrl,
return 0;
error_alloc_segment:
- kfree(mhi_buf);
-error_alloc_mhi_buf:
kfree(img_info);
return -ENOMEM;
@@ -375,14 +366,11 @@ int mhi_alloc_bhie_table(struct mhi_controller *mhi_cntrl,
struct image_info *img_info;
struct mhi_buf *mhi_buf;
- img_info = kzalloc_obj(*img_info);
+ img_info = kzalloc_flex(*img_info, mhi_buf, segments);
if (!img_info)
return -ENOMEM;
- /* Allocate memory for entries */
- img_info->mhi_buf = kzalloc_objs(*img_info->mhi_buf, segments);
- if (!img_info->mhi_buf)
- goto error_alloc_mhi_buf;
+ img_info->entries = segments;
/* Allocate and populate vector table */
mhi_buf = img_info->mhi_buf;
@@ -402,7 +390,6 @@ int mhi_alloc_bhie_table(struct mhi_controller *mhi_cntrl,
}
img_info->bhi_vec = img_info->mhi_buf[segments - 1].buf;
- img_info->entries = segments;
*image_info = img_info;
return 0;
@@ -411,9 +398,6 @@ error_alloc_segment:
for (--i, --mhi_buf; i >= 0; i--, mhi_buf--)
dma_free_coherent(mhi_cntrl->cntrl_dev, mhi_buf->len,
mhi_buf->buf, mhi_buf->dma_addr);
- kfree(img_info->mhi_buf);
-
-error_alloc_mhi_buf:
kfree(img_info);
return -ENOMEM;
diff --git a/drivers/bus/mhi/host/pci_generic.c b/drivers/bus/mhi/host/pci_generic.c
index 0884a384b77f..750da3dbb4c6 100644
--- a/drivers/bus/mhi/host/pci_generic.c
+++ b/drivers/bus/mhi/host/pci_generic.c
@@ -253,6 +253,13 @@ static const struct mhi_channel_config mhi_qcom_qdu100_channels[] = {
MHI_CHANNEL_CONFIG_DL(41, "MHI_PHC", 32, 4),
MHI_CHANNEL_CONFIG_UL(46, "IP_SW0", 256, 5),
MHI_CHANNEL_CONFIG_DL(47, "IP_SW0", 256, 5),
+ MHI_CHANNEL_CONFIG_UL(48, "IP_SW1", 256, 6),
+ MHI_CHANNEL_CONFIG_DL(49, "IP_SW1", 256, 6),
+ MHI_CHANNEL_CONFIG_UL(50, "IP_ETH0", 256, 7),
+ MHI_CHANNEL_CONFIG_DL(51, "IP_ETH0", 256, 7),
+ MHI_CHANNEL_CONFIG_UL(52, "IP_ETH1", 256, 8),
+ MHI_CHANNEL_CONFIG_DL(53, "IP_ETH1", 256, 8),
+
};
static struct mhi_event_config mhi_qcom_qdu100_events[] = {
@@ -268,6 +275,7 @@ static struct mhi_event_config mhi_qcom_qdu100_events[] = {
MHI_EVENT_CONFIG_SW_DATA(5, 512),
MHI_EVENT_CONFIG_SW_DATA(6, 512),
MHI_EVENT_CONFIG_SW_DATA(7, 512),
+ MHI_EVENT_CONFIG_SW_DATA(8, 512),
};
static const struct mhi_controller_config mhi_qcom_qdu100_config = {
@@ -407,6 +415,16 @@ static const struct mhi_pci_dev_info mhi_qcom_sdx55_info = {
.sideband_wake = false,
};
+static const struct mhi_pci_dev_info mhi_qcom_sdx35_info = {
+ .name = "qcom-sdx35m",
+ .config = &modem_qcom_v2_mhiv_config,
+ .bar_num = MHI_PCI_DEFAULT_BAR_NUM,
+ .dma_data_width = 32,
+ .mru_default = 32768,
+ .sideband_wake = false,
+ .edl_trigger = true,
+};
+
static const struct mhi_pci_dev_info mhi_qcom_sdx24_info = {
.name = "qcom-sdx24",
.edl = "qcom/prog_firehose_sdx24.mbn",
@@ -788,6 +806,8 @@ static const struct mhi_channel_config mhi_telit_fn990_channels[] = {
MHI_CHANNEL_CONFIG_DL(33, "DUN", 32, 0),
MHI_CHANNEL_CONFIG_UL(92, "DUN2", 32, 1),
MHI_CHANNEL_CONFIG_DL(93, "DUN2", 32, 1),
+ MHI_CHANNEL_CONFIG_UL(94, "NMEA", 32, 1),
+ MHI_CHANNEL_CONFIG_DL(95, "NMEA", 32, 1),
MHI_CHANNEL_CONFIG_HW_UL(100, "IP_HW0_MBIM", 128, 2),
MHI_CHANNEL_CONFIG_HW_DL(101, "IP_HW0_MBIM", 128, 3),
};
@@ -839,6 +859,8 @@ static const struct mhi_channel_config mhi_telit_fn920c04_channels[] = {
MHI_CHANNEL_CONFIG_DL_FP(35, "FIREHOSE", 32, 0),
MHI_CHANNEL_CONFIG_UL(92, "DUN2", 32, 1),
MHI_CHANNEL_CONFIG_DL(93, "DUN2", 32, 1),
+ MHI_CHANNEL_CONFIG_UL(94, "NMEA", 32, 1),
+ MHI_CHANNEL_CONFIG_DL(95, "NMEA", 32, 1),
MHI_CHANNEL_CONFIG_HW_UL(100, "IP_HW0", 128, 2),
MHI_CHANNEL_CONFIG_HW_DL(101, "IP_HW0", 128, 3),
};
@@ -882,6 +904,16 @@ static const struct mhi_pci_dev_info mhi_telit_fe990b40_info = {
.edl_trigger = true,
};
+static const struct mhi_pci_dev_info mhi_telit_fe912c04_info = {
+ .name = "telit-fe912c04",
+ .config = &modem_telit_fn920c04_config,
+ .bar_num = MHI_PCI_DEFAULT_BAR_NUM,
+ .dma_data_width = 32,
+ .sideband_wake = false,
+ .mru_default = 32768,
+ .edl_trigger = true,
+};
+
static const struct mhi_pci_dev_info mhi_netprisma_lcur57_info = {
.name = "netprisma-lcur57",
.edl = "qcom/prog_firehose_sdx24.mbn",
@@ -909,6 +941,11 @@ static const struct pci_device_id mhi_pci_id_table[] = {
/* Telit FN920C04 (sdx35) */
{PCI_DEVICE_SUB(PCI_VENDOR_ID_QCOM, 0x011a, 0x1c5d, 0x2020),
.driver_data = (kernel_ulong_t) &mhi_telit_fn920c04_info },
+ /* Telit FE912C04 (sdx35) */
+ { PCI_DEVICE_SUB(PCI_VENDOR_ID_QCOM, 0x011a, 0x1c5d, 0x2045),
+ .driver_data = (kernel_ulong_t) &mhi_telit_fe912c04_info },
+ { PCI_DEVICE(PCI_VENDOR_ID_QCOM, 0x011a),
+ .driver_data = (kernel_ulong_t) &mhi_qcom_sdx35_info },
{ PCI_DEVICE(PCI_VENDOR_ID_QCOM, 0x0304),
.driver_data = (kernel_ulong_t) &mhi_qcom_sdx24_info },
{ PCI_DEVICE_SUB(PCI_VENDOR_ID_QCOM, 0x0306, PCI_VENDOR_ID_QCOM, 0x010c),
@@ -1393,7 +1430,7 @@ static int mhi_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
goto err_unregister;
}
- err = mhi_sync_power_up(mhi_cntrl);
+ err = mhi_async_power_up(mhi_cntrl);
if (err) {
dev_err(&pdev->dev, "failed to power up MHI controller\n");
goto err_unprepare;
@@ -1428,6 +1465,7 @@ static void mhi_pci_remove(struct pci_dev *pdev)
struct mhi_pci_device *mhi_pdev = pci_get_drvdata(pdev);
struct mhi_controller *mhi_cntrl = &mhi_pdev->mhi_cntrl;
+ pm_runtime_forbid(&pdev->dev);
pci_disable_sriov(pdev);
if (pdev->is_physfn)
diff --git a/drivers/char/agp/backend.c b/drivers/char/agp/backend.c
index 4d920ca534a4..8983addca695 100644
--- a/drivers/char/agp/backend.c
+++ b/drivers/char/agp/backend.c
@@ -323,18 +323,6 @@ int agp_try_unsupported_boot;
EXPORT_SYMBOL(agp_off);
EXPORT_SYMBOL(agp_try_unsupported_boot);
-static int __init agp_init(void)
-{
- if (!agp_off)
- printk(KERN_INFO "Linux agpgart interface v%d.%d\n",
- AGPGART_VERSION_MAJOR, AGPGART_VERSION_MINOR);
- return 0;
-}
-
-static void __exit agp_exit(void)
-{
-}
-
#ifndef MODULE
static __init int agp_setup(char *s)
{
@@ -351,7 +339,3 @@ MODULE_AUTHOR("Dave Jones, Jeff Hartmann");
MODULE_DESCRIPTION("AGP GART driver");
MODULE_LICENSE("GPL and additional rights");
MODULE_ALIAS_MISCDEV(AGPGART_MINOR);
-
-module_init(agp_init);
-module_exit(agp_exit);
-
diff --git a/drivers/char/hpet.c b/drivers/char/hpet.c
index 8f128cc40147..46c84e5df00f 100644
--- a/drivers/char/hpet.c
+++ b/drivers/char/hpet.c
@@ -34,6 +34,7 @@
#include <linux/io.h>
#include <linux/acpi.h>
#include <linux/hpet.h>
+#include <linux/platform_device.h>
#include <asm/current.h>
#include <asm/irq.h>
#include <asm/div64.h>
@@ -973,8 +974,9 @@ static acpi_status hpet_resources(struct acpi_resource *res, void *data)
return AE_OK;
}
-static int hpet_acpi_add(struct acpi_device *device)
+static int hpet_acpi_probe(struct platform_device *pdev)
{
+ struct acpi_device *device = ACPI_COMPANION(&pdev->dev);
acpi_status result;
struct hpet_data data;
@@ -1002,12 +1004,12 @@ static const struct acpi_device_id hpet_device_ids[] = {
{"", 0},
};
-static struct acpi_driver hpet_acpi_driver = {
- .name = "hpet",
- .ids = hpet_device_ids,
- .ops = {
- .add = hpet_acpi_add,
- },
+static struct platform_driver hpet_acpi_driver = {
+ .probe = hpet_acpi_probe,
+ .driver = {
+ .name = "hpet_acpi",
+ .acpi_match_table = hpet_device_ids,
+ },
};
static struct miscdevice hpet_misc = { HPET_MINOR, "hpet", &hpet_fops };
@@ -1022,7 +1024,7 @@ static int __init hpet_init(void)
sysctl_header = register_sysctl("dev/hpet", hpet_table);
- result = acpi_bus_register_driver(&hpet_acpi_driver);
+ result = platform_driver_register(&hpet_acpi_driver);
if (result < 0) {
unregister_sysctl_table(sysctl_header);
misc_deregister(&hpet_misc);
diff --git a/drivers/char/nsc_gpio.c b/drivers/char/nsc_gpio.c
index da930c72bc74..2c9b12b85435 100644
--- a/drivers/char/nsc_gpio.c
+++ b/drivers/char/nsc_gpio.c
@@ -121,20 +121,6 @@ EXPORT_SYMBOL(nsc_gpio_write);
EXPORT_SYMBOL(nsc_gpio_read);
EXPORT_SYMBOL(nsc_gpio_dump);
-static int __init nsc_gpio_init(void)
-{
- printk(KERN_DEBUG NAME " initializing\n");
- return 0;
-}
-
-static void __exit nsc_gpio_cleanup(void)
-{
- printk(KERN_DEBUG NAME " cleanup\n");
-}
-
-module_init(nsc_gpio_init);
-module_exit(nsc_gpio_cleanup);
-
MODULE_AUTHOR("Jim Cromie <jim.cromie@gmail.com>");
MODULE_DESCRIPTION("NatSemi GPIO Common Methods");
MODULE_LICENSE("GPL");
diff --git a/drivers/char/sonypi.c b/drivers/char/sonypi.c
index 677bb5ac950a..ccda997a9098 100644
--- a/drivers/char/sonypi.c
+++ b/drivers/char/sonypi.c
@@ -1115,15 +1115,17 @@ static int sonypi_disable(void)
}
#ifdef CONFIG_ACPI
-static int sonypi_acpi_add(struct acpi_device *device)
+static int sonypi_acpi_probe(struct platform_device *pdev)
{
+ struct acpi_device *device = ACPI_COMPANION(&pdev->dev);
+
sonypi_acpi_device = device;
strcpy(acpi_device_name(device), "Sony laptop hotkeys");
strcpy(acpi_device_class(device), "sony/hotkey");
return 0;
}
-static void sonypi_acpi_remove(struct acpi_device *device)
+static void sonypi_acpi_remove(struct platform_device *pdev)
{
sonypi_acpi_device = NULL;
}
@@ -1133,13 +1135,12 @@ static const struct acpi_device_id sonypi_device_ids[] = {
{"", 0},
};
-static struct acpi_driver sonypi_acpi_driver = {
- .name = "sonypi",
- .class = "hkey",
- .ids = sonypi_device_ids,
- .ops = {
- .add = sonypi_acpi_add,
- .remove = sonypi_acpi_remove,
+static struct platform_driver sonypi_acpi_driver = {
+ .probe = sonypi_acpi_probe,
+ .remove = sonypi_acpi_remove,
+ .driver = {
+ .name = "sonypi_acpi",
+ .acpi_match_table = sonypi_device_ids,
},
};
#endif
@@ -1518,8 +1519,8 @@ static int __init sonypi_init(void)
goto err_free_device;
#ifdef CONFIG_ACPI
- if (acpi_bus_register_driver(&sonypi_acpi_driver) >= 0)
- acpi_driver_registered = 1;
+ error = platform_driver_register(&sonypi_acpi_driver);
+ acpi_driver_registered = !error;
#endif
return 0;
@@ -1535,7 +1536,7 @@ static void __exit sonypi_exit(void)
{
#ifdef CONFIG_ACPI
if (acpi_driver_registered)
- acpi_bus_unregister_driver(&sonypi_acpi_driver);
+ platform_driver_unregister(&sonypi_acpi_driver);
#endif
platform_device_unregister(sonypi_platform_device);
platform_driver_unregister(&sonypi_driver);
diff --git a/drivers/comedi/Kconfig b/drivers/comedi/Kconfig
index 6dcc2567de6d..c34a8d68547b 100644
--- a/drivers/comedi/Kconfig
+++ b/drivers/comedi/Kconfig
@@ -405,20 +405,20 @@ config COMEDI_FL512
called fl512.
config COMEDI_AIO_AIO12_8
- tristate "I/O Products PC/104 AIO12-8 Analog I/O Board support"
+ tristate "ACCES I/O Products PC/104 AIO12-8 Analog I/O Board support"
select COMEDI_8254
select COMEDI_8255
help
- Enable support for I/O Products PC/104 AIO12-8 Analog I/O Board
+ Enable support for ACCES I/O Products PC/104 AIO12-8 Analog I/O Board
To compile this driver as a module, choose M here: the module will be
called aio_aio12_8.
config COMEDI_AIO_IIRO_16
- tristate "I/O Products PC/104 IIRO16 Board support"
+ tristate "ACCES I/O Products PC/104 IIRO16 Board support"
help
- Enable support for I/O Products PC/104 IIRO16 Relay And Isolated
- Input Board
+ Enable support for ACCES I/O Products PC/104 IIRO16 Relay And
+ Isolated Input Board
To compile this driver as a module, choose M here: the module will be
called aio_iiro_16.
diff --git a/drivers/comedi/comedi_pci.c b/drivers/comedi/comedi_pci.c
index cc2581902195..da618f5e3a4d 100644
--- a/drivers/comedi/comedi_pci.c
+++ b/drivers/comedi/comedi_pci.c
@@ -211,17 +211,6 @@ void comedi_pci_driver_unregister(struct comedi_driver *comedi_driver,
}
EXPORT_SYMBOL_GPL(comedi_pci_driver_unregister);
-static int __init comedi_pci_init(void)
-{
- return 0;
-}
-module_init(comedi_pci_init);
-
-static void __exit comedi_pci_exit(void)
-{
-}
-module_exit(comedi_pci_exit);
-
MODULE_AUTHOR("https://www.comedi.org");
MODULE_DESCRIPTION("Comedi PCI interface module");
MODULE_LICENSE("GPL");
diff --git a/drivers/comedi/comedi_pcmcia.c b/drivers/comedi/comedi_pcmcia.c
index c53aad0fc2ce..17962bf66892 100644
--- a/drivers/comedi/comedi_pcmcia.c
+++ b/drivers/comedi/comedi_pcmcia.c
@@ -192,17 +192,6 @@ void comedi_pcmcia_driver_unregister(struct comedi_driver *comedi_driver,
}
EXPORT_SYMBOL_GPL(comedi_pcmcia_driver_unregister);
-static int __init comedi_pcmcia_init(void)
-{
- return 0;
-}
-module_init(comedi_pcmcia_init);
-
-static void __exit comedi_pcmcia_exit(void)
-{
-}
-module_exit(comedi_pcmcia_exit);
-
MODULE_AUTHOR("https://www.comedi.org");
MODULE_DESCRIPTION("Comedi PCMCIA interface module");
MODULE_LICENSE("GPL");
diff --git a/drivers/comedi/comedi_usb.c b/drivers/comedi/comedi_usb.c
index d11ea148ebf8..75d65171c76d 100644
--- a/drivers/comedi/comedi_usb.c
+++ b/drivers/comedi/comedi_usb.c
@@ -134,17 +134,6 @@ void comedi_usb_driver_unregister(struct comedi_driver *comedi_driver,
}
EXPORT_SYMBOL_GPL(comedi_usb_driver_unregister);
-static int __init comedi_usb_init(void)
-{
- return 0;
-}
-module_init(comedi_usb_init);
-
-static void __exit comedi_usb_exit(void)
-{
-}
-module_exit(comedi_usb_exit);
-
MODULE_AUTHOR("https://www.comedi.org");
MODULE_DESCRIPTION("Comedi USB interface module");
MODULE_LICENSE("GPL");
diff --git a/drivers/comedi/drivers.c b/drivers/comedi/drivers.c
index 5ab96b5eefd1..e78ad565f8f3 100644
--- a/drivers/comedi/drivers.c
+++ b/drivers/comedi/drivers.c
@@ -933,19 +933,24 @@ int comedi_load_firmware(struct comedi_device *dev,
EXPORT_SYMBOL_GPL(comedi_load_firmware);
/**
- * __comedi_request_region() - Request an I/O region for a legacy driver
+ * __comedi_check_request_region() - Request an I/O region for a legacy driver
* @dev: COMEDI device.
* @start: Base address of the I/O region.
* @len: Length of the I/O region.
+ * @minstart: Minimum allowed start address of region.
+ * @maxend: Maximum allowed region end address of region.
+ * @minalign: Required alignment for base address.
*
* Requests the specified I/O port region which must start at a non-zero
- * address.
+ * address, must fall within specified bounds, and must be correctly aligned.
*
* Returns 0 on success, -EINVAL if @start is 0, or -EIO if the request
* fails.
*/
-int __comedi_request_region(struct comedi_device *dev,
- unsigned long start, unsigned long len)
+int __comedi_check_request_region(struct comedi_device *dev,
+ unsigned long start, unsigned long len,
+ unsigned long minstart, unsigned long maxend,
+ unsigned long minalign)
{
if (!start) {
dev_warn(dev->class_dev,
@@ -954,6 +959,19 @@ int __comedi_request_region(struct comedi_device *dev,
return -EINVAL;
}
+ if (start < minstart || start > maxend || maxend - start < len - 1) {
+ dev_warn(dev->class_dev,
+ "%s: I/O base address or length out of range\n",
+ dev->board_name);
+ return -EINVAL;
+ }
+ if (!IS_ALIGNED(start, minalign)) {
+ dev_warn(dev->class_dev,
+ "%s: I/O base address not correctly aligned\n",
+ dev->board_name);
+ return -EINVAL;
+ }
+
if (!request_region(start, len, dev->board_name)) {
dev_warn(dev->class_dev, "%s: I/O port conflict (%#lx,%lu)\n",
dev->board_name, start, len);
@@ -962,16 +980,19 @@ int __comedi_request_region(struct comedi_device *dev,
return 0;
}
-EXPORT_SYMBOL_GPL(__comedi_request_region);
+EXPORT_SYMBOL_GPL(__comedi_check_request_region);
/**
- * comedi_request_region() - Request an I/O region for a legacy driver
+ * comedi_check_request_region() - Request an I/O region for a legacy driver
* @dev: COMEDI device.
* @start: Base address of the I/O region.
* @len: Length of the I/O region.
+ * @minstart: Minimum allowed start address of region.
+ * @maxend: Maximum allowed region end address of region.
+ * @minalign: Required alignment for base address.
*
* Requests the specified I/O port region which must start at a non-zero
- * address.
+ * address, must fall within specified bounds, and must be correctly aligned.
*
* On success, @dev->iobase is set to the base address of the region and
* @dev->iolen is set to its length.
@@ -979,12 +1000,15 @@ EXPORT_SYMBOL_GPL(__comedi_request_region);
* Returns 0 on success, -EINVAL if @start is 0, or -EIO if the request
* fails.
*/
-int comedi_request_region(struct comedi_device *dev,
- unsigned long start, unsigned long len)
+int comedi_check_request_region(struct comedi_device *dev,
+ unsigned long start, unsigned long len,
+ unsigned long minstart, unsigned long maxend,
+ unsigned long minalign)
{
int ret;
- ret = __comedi_request_region(dev, start, len);
+ ret = __comedi_check_request_region(dev, start, len, minstart, maxend,
+ minalign);
if (ret == 0) {
dev->iobase = start;
dev->iolen = len;
@@ -992,7 +1016,7 @@ int comedi_request_region(struct comedi_device *dev,
return ret;
}
-EXPORT_SYMBOL_GPL(comedi_request_region);
+EXPORT_SYMBOL_GPL(comedi_check_request_region);
/**
* comedi_legacy_detach() - A generic (*detach) function for legacy drivers
diff --git a/drivers/comedi/drivers/8255.c b/drivers/comedi/drivers/8255.c
index 5f70938b4477..ff45248ebb29 100644
--- a/drivers/comedi/drivers/8255.c
+++ b/drivers/comedi/drivers/8255.c
@@ -47,7 +47,7 @@ static int dev_8255_attach(struct comedi_device *dev,
struct comedi_devconfig *it)
{
struct comedi_subdevice *s;
- unsigned long iobase;
+ unsigned int iobase;
int ret;
int i;
@@ -70,13 +70,15 @@ static int dev_8255_attach(struct comedi_device *dev,
iobase = it->options[i];
/*
- * __comedi_request_region() does not set dev->iobase.
+ * __comedi_check_request_region() does not set dev->iobase.
*
* For 8255 devices that are manually attached using
* comedi_config, the 'iobase' is the actual I/O port
- * base address of the chip.
+ * base address of the chip. It should be aligned on
+ * a 4-byte boundary.
*/
- ret = __comedi_request_region(dev, iobase, I8255_SIZE);
+ ret = __comedi_check_request_region(dev, iobase, I8255_SIZE,
+ 0, UINT_MAX, 4);
if (ret)
return ret;
ret = subdev_8255_io_init(dev, s, iobase);
diff --git a/drivers/comedi/drivers/addi_watchdog.c b/drivers/comedi/drivers/addi_watchdog.c
index ed87ab432020..b778c88d4c11 100644
--- a/drivers/comedi/drivers/addi_watchdog.c
+++ b/drivers/comedi/drivers/addi_watchdog.c
@@ -124,17 +124,6 @@ int addi_watchdog_init(struct comedi_subdevice *s, unsigned long iobase)
}
EXPORT_SYMBOL_GPL(addi_watchdog_init);
-static int __init addi_watchdog_module_init(void)
-{
- return 0;
-}
-module_init(addi_watchdog_module_init);
-
-static void __exit addi_watchdog_module_exit(void)
-{
-}
-module_exit(addi_watchdog_module_exit);
-
MODULE_DESCRIPTION("ADDI-DATA Watchdog subdevice");
MODULE_AUTHOR("H Hartley Sweeten <hsweeten@visionengravers.com>");
MODULE_LICENSE("GPL");
diff --git a/drivers/comedi/drivers/adq12b.c b/drivers/comedi/drivers/adq12b.c
index 19d765182006..f8fa5c6ecdff 100644
--- a/drivers/comedi/drivers/adq12b.c
+++ b/drivers/comedi/drivers/adq12b.c
@@ -179,7 +179,8 @@ static int adq12b_attach(struct comedi_device *dev, struct comedi_devconfig *it)
struct comedi_subdevice *s;
int ret;
- ret = comedi_request_region(dev, it->options[0], 0x10);
+ ret = comedi_check_request_region(dev, it->options[0], 0x10,
+ 0x300, 0x3af, 0x20);
if (ret)
return ret;
diff --git a/drivers/comedi/drivers/aio_aio12_8.c b/drivers/comedi/drivers/aio_aio12_8.c
index 227a86a3a760..e0cbc2ec7c4d 100644
--- a/drivers/comedi/drivers/aio_aio12_8.c
+++ b/drivers/comedi/drivers/aio_aio12_8.c
@@ -1,17 +1,17 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* aio_aio12_8.c
- * Driver for Access I/O Products PC-104 AIO12-8 Analog I/O Board
+ * Driver for ACCES I/O Products PC-104 AIO12-8 Analog I/O Board
* Copyright (C) 2006 C&C Technologies, Inc.
*/
/*
* Driver: aio_aio12_8
- * Description: Access I/O Products PC-104 AIO12-8 Analog I/O Board
+ * Description: ACCES I/O Products PC-104 AIO12-8 Analog I/O Board
* Author: Pablo Mejia <pablo.mejia@cctechnol.com>
- * Devices: [Access I/O] PC-104 AIO12-8 (aio_aio12_8),
- * [Access I/O] PC-104 AI12-8 (aio_ai12_8),
- * [Access I/O] PC-104 AO12-4 (aio_ao12_4)
+ * Devices: [ACCES I/O] PC-104 AIO12-8 (aio_aio12_8),
+ * [ACCES I/O] PC-104 AI12-8 (aio_ai12_8),
+ * [ACCES I/O] PC-104 AO12-4 (aio_ao12_4)
* Status: experimental
*
* Configuration Options:
@@ -202,7 +202,8 @@ static int aio_aio12_8_attach(struct comedi_device *dev,
struct comedi_subdevice *s;
int ret;
- ret = comedi_request_region(dev, it->options[0], 32);
+ ret = comedi_check_request_region(dev, it->options[0], 32,
+ 0x100, 0x3ff, 32);
if (ret)
return ret;
@@ -272,5 +273,5 @@ static struct comedi_driver aio_aio12_8_driver = {
module_comedi_driver(aio_aio12_8_driver);
MODULE_AUTHOR("Comedi https://www.comedi.org");
-MODULE_DESCRIPTION("Comedi driver for Access I/O AIO12-8 Analog I/O Board");
+MODULE_DESCRIPTION("Comedi driver for ACCES I/O AIO12-8 Analog I/O Board");
MODULE_LICENSE("GPL");
diff --git a/drivers/comedi/drivers/aio_iiro_16.c b/drivers/comedi/drivers/aio_iiro_16.c
index 739cc4db52ac..d5d18fa2c638 100644
--- a/drivers/comedi/drivers/aio_iiro_16.c
+++ b/drivers/comedi/drivers/aio_iiro_16.c
@@ -1,15 +1,15 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* aio_iiro_16.c
- * Comedi driver for Access I/O Products 104-IIRO-16 board
+ * Comedi driver for ACCES I/O Products 104-IIRO-16 board
* Copyright (C) 2006 C&C Technologies, Inc.
*/
/*
* Driver: aio_iiro_16
- * Description: Access I/O Products PC/104 Isolated Input/Relay Output Board
+ * Description: ACCES I/O Products PC/104 Isolated Input/Relay Output Board
* Author: Zachary Ware <zach.ware@cctechnol.com>
- * Devices: [Access I/O] 104-IIRO-16 (aio_iiro_16)
+ * Devices: [ACCES I/O] 104-IIRO-16 (aio_iiro_16)
* Status: experimental
*
* Configuration Options:
@@ -167,7 +167,8 @@ static int aio_iiro_16_attach(struct comedi_device *dev,
struct comedi_subdevice *s;
int ret;
- ret = comedi_request_region(dev, it->options[0], 0x8);
+ ret = comedi_check_request_region(dev, it->options[0], 0x8,
+ 0x100, 0x3ff, 0x8);
if (ret)
return ret;
@@ -231,5 +232,5 @@ static struct comedi_driver aio_iiro_16_driver = {
module_comedi_driver(aio_iiro_16_driver);
MODULE_AUTHOR("Comedi https://www.comedi.org");
-MODULE_DESCRIPTION("Comedi driver for Access I/O Products 104-IIRO-16 board");
+MODULE_DESCRIPTION("Comedi driver for ACCES I/O Products 104-IIRO-16 board");
MODULE_LICENSE("GPL");
diff --git a/drivers/comedi/drivers/amplc_dio200.c b/drivers/comedi/drivers/amplc_dio200.c
index 4544bcdd8a70..8b1cbc3d24e5 100644
--- a/drivers/comedi/drivers/amplc_dio200.c
+++ b/drivers/comedi/drivers/amplc_dio200.c
@@ -242,7 +242,8 @@ static int dio200_attach(struct comedi_device *dev, struct comedi_devconfig *it)
{
int ret;
- ret = comedi_request_region(dev, it->options[0], 0x20);
+ ret = comedi_check_request_region(dev, it->options[0], 0x20,
+ 0, 0xfff, 0x20);
if (ret)
return ret;
diff --git a/drivers/comedi/drivers/amplc_dio200_common.c b/drivers/comedi/drivers/amplc_dio200_common.c
index b1a9b4c4a185..d61f51900976 100644
--- a/drivers/comedi/drivers/amplc_dio200_common.c
+++ b/drivers/comedi/drivers/amplc_dio200_common.c
@@ -901,17 +901,6 @@ int amplc_dio200_common_attach(struct comedi_device *dev, unsigned int irq,
}
EXPORT_SYMBOL_GPL(amplc_dio200_common_attach);
-static int __init amplc_dio200_common_init(void)
-{
- return 0;
-}
-module_init(amplc_dio200_common_init);
-
-static void __exit amplc_dio200_common_exit(void)
-{
-}
-module_exit(amplc_dio200_common_exit);
-
MODULE_AUTHOR("Comedi https://www.comedi.org");
MODULE_DESCRIPTION("Comedi helper for amplc_dio200 and amplc_dio200_pci");
MODULE_LICENSE("GPL");
diff --git a/drivers/comedi/drivers/amplc_pc236.c b/drivers/comedi/drivers/amplc_pc236.c
index b21e0c906aab..eadee10983bf 100644
--- a/drivers/comedi/drivers/amplc_pc236.c
+++ b/drivers/comedi/drivers/amplc_pc236.c
@@ -45,7 +45,8 @@ static int pc236_attach(struct comedi_device *dev, struct comedi_devconfig *it)
if (!devpriv)
return -ENOMEM;
- ret = comedi_request_region(dev, it->options[0], 0x4);
+ ret = comedi_check_request_region(dev, it->options[0], 0x4,
+ 0, 0xfff, 4);
if (ret)
return ret;
diff --git a/drivers/comedi/drivers/amplc_pc236_common.c b/drivers/comedi/drivers/amplc_pc236_common.c
index 326ca72c24ec..c3692f50bdb9 100644
--- a/drivers/comedi/drivers/amplc_pc236_common.c
+++ b/drivers/comedi/drivers/amplc_pc236_common.c
@@ -176,17 +176,6 @@ int amplc_pc236_common_attach(struct comedi_device *dev, unsigned long iobase,
}
EXPORT_SYMBOL_GPL(amplc_pc236_common_attach);
-static int __init amplc_pc236_common_init(void)
-{
- return 0;
-}
-module_init(amplc_pc236_common_init);
-
-static void __exit amplc_pc236_common_exit(void)
-{
-}
-module_exit(amplc_pc236_common_exit);
-
MODULE_AUTHOR("Comedi https://www.comedi.org");
MODULE_DESCRIPTION("Comedi helper for amplc_pc236 and amplc_pci236");
MODULE_LICENSE("GPL");
diff --git a/drivers/comedi/drivers/amplc_pc263.c b/drivers/comedi/drivers/amplc_pc263.c
index d7f088a8a5e3..e2196dc9d426 100644
--- a/drivers/comedi/drivers/amplc_pc263.c
+++ b/drivers/comedi/drivers/amplc_pc263.c
@@ -61,7 +61,8 @@ static int pc263_attach(struct comedi_device *dev, struct comedi_devconfig *it)
struct comedi_subdevice *s;
int ret;
- ret = comedi_request_region(dev, it->options[0], 0x2);
+ ret = comedi_check_request_region(dev, it->options[0], 0x2,
+ 0, 0x7ff, 2);
if (ret)
return ret;
diff --git a/drivers/comedi/drivers/c6xdigio.c b/drivers/comedi/drivers/c6xdigio.c
index 8a38d97d463b..b6563a48ada6 100644
--- a/drivers/comedi/drivers/c6xdigio.c
+++ b/drivers/comedi/drivers/c6xdigio.c
@@ -239,9 +239,11 @@ static int c6xdigio_attach(struct comedi_device *dev,
struct comedi_devconfig *it)
{
struct comedi_subdevice *s;
+ unsigned int iobase = it->options[0];
int ret;
- ret = comedi_request_region(dev, it->options[0], 0x03);
+ ret = comedi_check_request_region(dev, iobase, 0x03,
+ 0, UINT_MAX, 4);
if (ret)
return ret;
diff --git a/drivers/comedi/drivers/comedi_8254.c b/drivers/comedi/drivers/comedi_8254.c
index a297dd650dab..158e8b4108a8 100644
--- a/drivers/comedi/drivers/comedi_8254.c
+++ b/drivers/comedi/drivers/comedi_8254.c
@@ -724,17 +724,6 @@ struct comedi_8254 *comedi_8254_mm_alloc(void __iomem *mmio,
}
EXPORT_SYMBOL_GPL(comedi_8254_mm_alloc);
-static int __init comedi_8254_module_init(void)
-{
- return 0;
-}
-module_init(comedi_8254_module_init);
-
-static void __exit comedi_8254_module_exit(void)
-{
-}
-module_exit(comedi_8254_module_exit);
-
MODULE_AUTHOR("H Hartley Sweeten <hsweeten@visionengravers.com>");
MODULE_DESCRIPTION("Comedi: Generic 8254 timer/counter support");
MODULE_LICENSE("GPL");
diff --git a/drivers/comedi/drivers/comedi_8255.c b/drivers/comedi/drivers/comedi_8255.c
index a933ef53845a..fd6b1cf621a7 100644
--- a/drivers/comedi/drivers/comedi_8255.c
+++ b/drivers/comedi/drivers/comedi_8255.c
@@ -259,17 +259,6 @@ unsigned long subdev_8255_regbase(struct comedi_subdevice *s)
}
EXPORT_SYMBOL_GPL(subdev_8255_regbase);
-static int __init comedi_8255_module_init(void)
-{
- return 0;
-}
-module_init(comedi_8255_module_init);
-
-static void __exit comedi_8255_module_exit(void)
-{
-}
-module_exit(comedi_8255_module_exit);
-
MODULE_AUTHOR("Comedi https://www.comedi.org");
MODULE_DESCRIPTION("Comedi: Generic 8255 digital I/O support");
MODULE_LICENSE("GPL");
diff --git a/drivers/comedi/drivers/comedi_isadma.c b/drivers/comedi/drivers/comedi_isadma.c
index 04ce3eb9ae4f..b346079b9b6b 100644
--- a/drivers/comedi/drivers/comedi_isadma.c
+++ b/drivers/comedi/drivers/comedi_isadma.c
@@ -161,14 +161,10 @@ struct comedi_isadma *comedi_isadma_alloc(struct comedi_device *dev,
if (n_desc < 1 || n_desc > 2)
goto no_dma;
- dma = kzalloc_obj(*dma);
+ dma = kzalloc_flex(*dma, desc, n_desc);
if (!dma)
goto no_dma;
- desc = kzalloc_objs(*desc, n_desc);
- if (!desc)
- goto no_dma;
- dma->desc = desc;
dma->n_desc = n_desc;
if (dev->hw_dev) {
dma->dev = dev->hw_dev;
@@ -231,15 +227,12 @@ void comedi_isadma_free(struct comedi_isadma *dma)
if (!dma)
return;
- if (dma->desc) {
- for (i = 0; i < dma->n_desc; i++) {
- desc = &dma->desc[i];
- if (desc->virt_addr)
- dma_free_coherent(dma->dev, desc->maxsize,
- desc->virt_addr,
- desc->hw_addr);
- }
- kfree(dma->desc);
+ for (i = 0; i < dma->n_desc; i++) {
+ desc = &dma->desc[i];
+ if (desc->virt_addr)
+ dma_free_coherent(dma->dev, desc->maxsize,
+ desc->virt_addr,
+ desc->hw_addr);
}
if (dma->chan2 && dma->chan2 != dma->chan)
free_dma(dma->chan2);
@@ -249,17 +242,6 @@ void comedi_isadma_free(struct comedi_isadma *dma)
}
EXPORT_SYMBOL_GPL(comedi_isadma_free);
-static int __init comedi_isadma_init(void)
-{
- return 0;
-}
-module_init(comedi_isadma_init);
-
-static void __exit comedi_isadma_exit(void)
-{
-}
-module_exit(comedi_isadma_exit);
-
MODULE_AUTHOR("H Hartley Sweeten <hsweeten@visionengravers.com>");
MODULE_DESCRIPTION("Comedi ISA DMA support");
MODULE_LICENSE("GPL");
diff --git a/drivers/comedi/drivers/comedi_parport.c b/drivers/comedi/drivers/comedi_parport.c
index 098738a688fe..2604680d86c4 100644
--- a/drivers/comedi/drivers/comedi_parport.c
+++ b/drivers/comedi/drivers/comedi_parport.c
@@ -225,9 +225,11 @@ static int parport_attach(struct comedi_device *dev,
struct comedi_devconfig *it)
{
struct comedi_subdevice *s;
+ unsigned int iobase = it->options[0];
int ret;
- ret = comedi_request_region(dev, it->options[0], 0x03);
+ ret = comedi_check_request_region(dev, iobase, 0x03,
+ 0, UINT_MAX, 4);
if (ret)
return ret;
diff --git a/drivers/comedi/drivers/dac02.c b/drivers/comedi/drivers/dac02.c
index 4b011d66d7b0..2c04472c5078 100644
--- a/drivers/comedi/drivers/dac02.c
+++ b/drivers/comedi/drivers/dac02.c
@@ -103,7 +103,8 @@ static int dac02_attach(struct comedi_device *dev, struct comedi_devconfig *it)
struct comedi_subdevice *s;
int ret;
- ret = comedi_request_region(dev, it->options[0], 0x08);
+ ret = comedi_check_request_region(dev, it->options[0], 0x08,
+ 0x200, 0x3ff, 8);
if (ret)
return ret;
diff --git a/drivers/comedi/drivers/das08.c b/drivers/comedi/drivers/das08.c
index 49944ce1f813..a3298a3238e7 100644
--- a/drivers/comedi/drivers/das08.c
+++ b/drivers/comedi/drivers/das08.c
@@ -453,17 +453,6 @@ int das08_common_attach(struct comedi_device *dev, unsigned long iobase)
}
EXPORT_SYMBOL_GPL(das08_common_attach);
-static int __init das08_init(void)
-{
- return 0;
-}
-module_init(das08_init);
-
-static void __exit das08_exit(void)
-{
-}
-module_exit(das08_exit);
-
MODULE_AUTHOR("Comedi https://www.comedi.org");
MODULE_DESCRIPTION("Comedi common DAS08 support module");
MODULE_LICENSE("GPL");
diff --git a/drivers/comedi/drivers/das08_isa.c b/drivers/comedi/drivers/das08_isa.c
index 3d43b77cc9f4..1b022dc10b78 100644
--- a/drivers/comedi/drivers/das08_isa.c
+++ b/drivers/comedi/drivers/das08_isa.c
@@ -167,7 +167,8 @@ static int das08_isa_attach(struct comedi_device *dev,
if (!devpriv)
return -ENOMEM;
- ret = comedi_request_region(dev, it->options[0], board->iosize);
+ ret = comedi_check_request_region(dev, it->options[0], board->iosize,
+ 0, 0x3ff, board->iosize);
if (ret)
return ret;
diff --git a/drivers/comedi/drivers/das16.c b/drivers/comedi/drivers/das16.c
index 1f85572c21b4..6eebfda2cb53 100644
--- a/drivers/comedi/drivers/das16.c
+++ b/drivers/comedi/drivers/das16.c
@@ -1018,6 +1018,7 @@ static int das16_attach(struct comedi_device *dev, struct comedi_devconfig *it)
const struct das16_board *board = dev->board_ptr;
struct das16_private_struct *devpriv;
struct comedi_subdevice *s;
+ unsigned int iobase = it->options[0];
unsigned int osc_base;
unsigned int status;
int ret;
@@ -1037,11 +1038,25 @@ static int das16_attach(struct comedi_device *dev, struct comedi_devconfig *it)
devpriv->dev = dev;
if (board->size < 0x400) {
- ret = comedi_request_region(dev, it->options[0], board->size);
+ unsigned int size = board->size;
+
+ if (size > 0x10 && (iobase & 0x10) != 0) {
+ /*
+ * The board has more than 0x10 registers and is
+ * being placed on an odd 16-byte boundary. The
+ * board has some jumpers to configure this mode,
+ * disabling the 8255 at offset 0x10, so only 0x10
+ * registers will need to be mapped in this mode.
+ */
+ size = 0x10;
+ }
+ ret = comedi_check_request_region(dev, iobase, size,
+ 0, 0x3ff, 16);
if (ret)
return ret;
} else {
- ret = comedi_request_region(dev, it->options[0], 0x10);
+ ret = comedi_check_request_region(dev, iobase, 0x10,
+ 0, 0x3ff, 16);
if (ret)
return ret;
/* Request an additional region for the 8255 */
@@ -1146,9 +1161,15 @@ static int das16_attach(struct comedi_device *dev, struct comedi_devconfig *it)
/* 8255 Digital I/O subdevice */
if (board->has_8255) {
s = &dev->subdevices[4];
- ret = subdev_8255_io_init(dev, s, board->i8255_offset);
- if (ret)
- return ret;
+ if (board->i8255_offset == 0x10 && (dev->iobase & 0x10) != 0) {
+ dev_info(dev->class_dev,
+ "Disabling 8255 subdevice on unsupported base address\n");
+ s->type = COMEDI_SUBD_UNUSED;
+ } else {
+ ret = subdev_8255_io_init(dev, s, board->i8255_offset);
+ if (ret)
+ return ret;
+ }
}
das16_reset(dev);
diff --git a/drivers/comedi/drivers/das16m1.c b/drivers/comedi/drivers/das16m1.c
index 1b638f5b5a4f..9f531ba593b4 100644
--- a/drivers/comedi/drivers/das16m1.c
+++ b/drivers/comedi/drivers/das16m1.c
@@ -511,7 +511,8 @@ static int das16m1_attach(struct comedi_device *dev,
if (!devpriv)
return -ENOMEM;
- ret = comedi_request_region(dev, it->options[0], 0x10);
+ ret = comedi_check_request_region(dev, it->options[0], 0x10,
+ 0, 0x3ff, 16);
if (ret)
return ret;
/* Request an additional region for the 8255 and 3rd 8254 */
diff --git a/drivers/comedi/drivers/das1800.c b/drivers/comedi/drivers/das1800.c
index 7117c67aee7e..7d7ea99a81aa 100644
--- a/drivers/comedi/drivers/das1800.c
+++ b/drivers/comedi/drivers/das1800.c
@@ -1172,7 +1172,8 @@ static int das1800_attach(struct comedi_device *dev,
if (!devpriv)
return -ENOMEM;
- ret = comedi_request_region(dev, it->options[0], DAS1800_SIZE);
+ ret = comedi_check_request_region(dev, it->options[0], DAS1800_SIZE,
+ 0, 0x3ff, 16);
if (ret)
return ret;
diff --git a/drivers/comedi/drivers/das6402.c b/drivers/comedi/drivers/das6402.c
index 7660487e563c..516a5d5a2840 100644
--- a/drivers/comedi/drivers/das6402.c
+++ b/drivers/comedi/drivers/das6402.c
@@ -560,7 +560,8 @@ static int das6402_attach(struct comedi_device *dev,
if (!devpriv)
return -ENOMEM;
- ret = comedi_request_region(dev, it->options[0], 0x10);
+ ret = comedi_check_request_region(dev, it->options[0], 0x10,
+ 0, 0x3ff, 16);
if (ret)
return ret;
diff --git a/drivers/comedi/drivers/das800.c b/drivers/comedi/drivers/das800.c
index 300775523031..7563f40a4023 100644
--- a/drivers/comedi/drivers/das800.c
+++ b/drivers/comedi/drivers/das800.c
@@ -655,7 +655,8 @@ static int das800_attach(struct comedi_device *dev, struct comedi_devconfig *it)
if (!devpriv)
return -ENOMEM;
- ret = comedi_request_region(dev, it->options[0], 0x8);
+ ret = comedi_check_request_region(dev, it->options[0], 0x8,
+ 0, 0x3ff, 8);
if (ret)
return ret;
diff --git a/drivers/comedi/drivers/dmm32at.c b/drivers/comedi/drivers/dmm32at.c
index 910cd24b1bed..d1d9f75e168f 100644
--- a/drivers/comedi/drivers/dmm32at.c
+++ b/drivers/comedi/drivers/dmm32at.c
@@ -572,11 +572,27 @@ static int dmm32at_attach(struct comedi_device *dev,
struct comedi_devconfig *it)
{
struct comedi_subdevice *s;
+ unsigned int iobase = it->options[0];
int ret;
- ret = comedi_request_region(dev, it->options[0], 0x10);
- if (ret)
- return ret;
+ switch (iobase) {
+ case 0x100:
+ case 0x140:
+ case 0x180:
+ case 0x200:
+ case 0x280:
+ case 0x300:
+ case 0x340:
+ case 0x380:
+ ret = comedi_request_region(dev, iobase, 0x10);
+ if (ret)
+ return ret;
+ break;
+ default:
+ dev_err(dev->class_dev, "unsupported base address %#x\n",
+ iobase);
+ return -EINVAL;
+ }
ret = dmm32at_reset(dev);
if (ret) {
diff --git a/drivers/comedi/drivers/dt2801.c b/drivers/comedi/drivers/dt2801.c
index 230d25010f58..d790e69f98a0 100644
--- a/drivers/comedi/drivers/dt2801.c
+++ b/drivers/comedi/drivers/dt2801.c
@@ -540,7 +540,8 @@ static int dt2801_attach(struct comedi_device *dev, struct comedi_devconfig *it)
int ret = 0;
int n_ai_chans;
- ret = comedi_request_region(dev, it->options[0], 0x2);
+ ret = comedi_check_request_region(dev, it->options[0], 0x2,
+ 0x200, 0x3ff, 2);
if (ret)
return ret;
diff --git a/drivers/comedi/drivers/dt2811.c b/drivers/comedi/drivers/dt2811.c
index dbb9f38da289..bcc4b5ef48e8 100644
--- a/drivers/comedi/drivers/dt2811.c
+++ b/drivers/comedi/drivers/dt2811.c
@@ -556,7 +556,8 @@ static int dt2811_attach(struct comedi_device *dev, struct comedi_devconfig *it)
if (!devpriv)
return -ENOMEM;
- ret = comedi_request_region(dev, it->options[0], 0x8);
+ ret = comedi_check_request_region(dev, it->options[0], 0x8,
+ 0x200, 0x3ff, 8);
if (ret)
return ret;
diff --git a/drivers/comedi/drivers/dt2814.c b/drivers/comedi/drivers/dt2814.c
index c98a5a4a7aec..caec16482afb 100644
--- a/drivers/comedi/drivers/dt2814.c
+++ b/drivers/comedi/drivers/dt2814.c
@@ -305,7 +305,8 @@ static int dt2814_attach(struct comedi_device *dev, struct comedi_devconfig *it)
struct comedi_subdevice *s;
int ret;
- ret = comedi_request_region(dev, it->options[0], 0x2);
+ ret = comedi_check_request_region(dev, it->options[0], 0x2,
+ 0x200, 0x3ff, 2);
if (ret)
return ret;
diff --git a/drivers/comedi/drivers/dt2815.c b/drivers/comedi/drivers/dt2815.c
index d066dc303520..8832ecef2ab6 100644
--- a/drivers/comedi/drivers/dt2815.c
+++ b/drivers/comedi/drivers/dt2815.c
@@ -144,7 +144,8 @@ static int dt2815_attach(struct comedi_device *dev, struct comedi_devconfig *it)
const struct comedi_lrange *current_range_type, *voltage_range_type;
int ret;
- ret = comedi_request_region(dev, it->options[0], 0x2);
+ ret = comedi_check_request_region(dev, it->options[0], 0x2,
+ 0x200, 0x3ff, 2);
if (ret)
return ret;
diff --git a/drivers/comedi/drivers/dt2817.c b/drivers/comedi/drivers/dt2817.c
index 6738045c7531..9fd5b47c7fa7 100644
--- a/drivers/comedi/drivers/dt2817.c
+++ b/drivers/comedi/drivers/dt2817.c
@@ -103,7 +103,8 @@ static int dt2817_attach(struct comedi_device *dev, struct comedi_devconfig *it)
int ret;
struct comedi_subdevice *s;
- ret = comedi_request_region(dev, it->options[0], 0x5);
+ ret = comedi_check_request_region(dev, it->options[0], 0x5,
+ 0x200, 0x3ff, 8);
if (ret)
return ret;
diff --git a/drivers/comedi/drivers/dt282x.c b/drivers/comedi/drivers/dt282x.c
index 4ae80e6c7266..29832e1f062d 100644
--- a/drivers/comedi/drivers/dt282x.c
+++ b/drivers/comedi/drivers/dt282x.c
@@ -1064,7 +1064,12 @@ static int dt282x_attach(struct comedi_device *dev, struct comedi_devconfig *it)
struct comedi_subdevice *s;
int ret;
- ret = comedi_request_region(dev, it->options[0], 0x10);
+ /*
+ * Although it has only 16 bytes (8 16-bit registers), it needs to
+ * start on a 32-byte boundary in range 0x200 to 0x3E0.
+ */
+ ret = comedi_check_request_region(dev, it->options[0], 0x10,
+ 0x200, 0x3ff, 32);
if (ret)
return ret;
diff --git a/drivers/comedi/drivers/fl512.c b/drivers/comedi/drivers/fl512.c
index 139e801fc358..d9e6007556ac 100644
--- a/drivers/comedi/drivers/fl512.c
+++ b/drivers/comedi/drivers/fl512.c
@@ -98,9 +98,15 @@ static int fl512_ao_insn_write(struct comedi_device *dev,
static int fl512_attach(struct comedi_device *dev, struct comedi_devconfig *it)
{
struct comedi_subdevice *s;
+ unsigned int iobase = it->options[0];
int ret;
- ret = comedi_request_region(dev, it->options[0], 0x10);
+ /*
+ * FIXME: Don't know the allowed range, but assume it needs to be
+ * on a 16-byte boundary - Ian Abbott
+ */
+ ret = comedi_check_request_region(dev, iobase, 0x10,
+ 0, UINT_MAX, 16);
if (ret)
return ret;
diff --git a/drivers/comedi/drivers/mite.c b/drivers/comedi/drivers/mite.c
index e93150d6dc57..9098616900f7 100644
--- a/drivers/comedi/drivers/mite.c
+++ b/drivers/comedi/drivers/mite.c
@@ -921,17 +921,6 @@ void mite_detach(struct mite *mite)
}
EXPORT_SYMBOL_GPL(mite_detach);
-static int __init mite_module_init(void)
-{
- return 0;
-}
-module_init(mite_module_init);
-
-static void __exit mite_module_exit(void)
-{
-}
-module_exit(mite_module_exit);
-
MODULE_AUTHOR("Comedi https://www.comedi.org");
MODULE_DESCRIPTION("Comedi helper for NI Mite PCI interface chip");
MODULE_LICENSE("GPL");
diff --git a/drivers/comedi/drivers/mpc624.c b/drivers/comedi/drivers/mpc624.c
index 9e51ff528ed1..e6343f4267c1 100644
--- a/drivers/comedi/drivers/mpc624.c
+++ b/drivers/comedi/drivers/mpc624.c
@@ -237,7 +237,8 @@ static int mpc624_attach(struct comedi_device *dev, struct comedi_devconfig *it)
struct comedi_subdevice *s;
int ret;
- ret = comedi_request_region(dev, it->options[0], 0x10);
+ ret = comedi_check_request_region(dev, it->options[0], 0x10,
+ 0, 0x3ff, 16);
if (ret)
return ret;
diff --git a/drivers/comedi/drivers/multiq3.c b/drivers/comedi/drivers/multiq3.c
index ac369e9a262d..3dde3a1876d7 100644
--- a/drivers/comedi/drivers/multiq3.c
+++ b/drivers/comedi/drivers/multiq3.c
@@ -259,7 +259,8 @@ static int multiq3_attach(struct comedi_device *dev,
int ret;
int i;
- ret = comedi_request_region(dev, it->options[0], 0x10);
+ ret = comedi_check_request_region(dev, it->options[0], 0x10,
+ 0, 0x3ff, 16);
if (ret)
return ret;
diff --git a/drivers/comedi/drivers/ni_at_a2150.c b/drivers/comedi/drivers/ni_at_a2150.c
index e4e5a0ebd195..44221c928e32 100644
--- a/drivers/comedi/drivers/ni_at_a2150.c
+++ b/drivers/comedi/drivers/ni_at_a2150.c
@@ -694,7 +694,8 @@ static int a2150_attach(struct comedi_device *dev, struct comedi_devconfig *it)
if (!devpriv)
return -ENOMEM;
- ret = comedi_request_region(dev, it->options[0], 0x1c);
+ ret = comedi_check_request_region(dev, it->options[0], 0x1c,
+ 0, 0x3ff, 32);
if (ret)
return ret;
diff --git a/drivers/comedi/drivers/ni_at_ao.c b/drivers/comedi/drivers/ni_at_ao.c
index 9cf6b4ff6b65..31fd64bf8206 100644
--- a/drivers/comedi/drivers/ni_at_ao.c
+++ b/drivers/comedi/drivers/ni_at_ao.c
@@ -295,7 +295,8 @@ static int atao_attach(struct comedi_device *dev, struct comedi_devconfig *it)
struct comedi_subdevice *s;
int ret;
- ret = comedi_request_region(dev, it->options[0], 0x20);
+ ret = comedi_check_request_region(dev, it->options[0], 0x20,
+ 0, 0x3ff, 32);
if (ret)
return ret;
diff --git a/drivers/comedi/drivers/ni_atmio.c b/drivers/comedi/drivers/ni_atmio.c
index b4e759e5703f..7bc336333ace 100644
--- a/drivers/comedi/drivers/ni_atmio.c
+++ b/drivers/comedi/drivers/ni_atmio.c
@@ -311,7 +311,8 @@ static int ni_atmio_attach(struct comedi_device *dev,
comedi_set_hw_dev(dev, &isapnp_dev->dev);
}
- ret = comedi_request_region(dev, iobase, 0x20);
+ ret = comedi_check_request_region(dev, iobase, 0x20,
+ 0x20, 0xffff, 32);
if (ret)
return ret;
diff --git a/drivers/comedi/drivers/ni_atmio16d.c b/drivers/comedi/drivers/ni_atmio16d.c
index b057b3b3582e..b2772d909896 100644
--- a/drivers/comedi/drivers/ni_atmio16d.c
+++ b/drivers/comedi/drivers/ni_atmio16d.c
@@ -574,7 +574,8 @@ static int atmio16d_attach(struct comedi_device *dev,
struct comedi_subdevice *s;
int ret;
- ret = comedi_request_region(dev, it->options[0], 0x20);
+ ret = comedi_check_request_region(dev, it->options[0], 0x20,
+ 0, 0x3ff, 32);
if (ret)
return ret;
diff --git a/drivers/comedi/drivers/ni_labpc.c b/drivers/comedi/drivers/ni_labpc.c
index b25a8e117072..93b5333a99b5 100644
--- a/drivers/comedi/drivers/ni_labpc.c
+++ b/drivers/comedi/drivers/ni_labpc.c
@@ -78,7 +78,8 @@ static int labpc_attach(struct comedi_device *dev, struct comedi_devconfig *it)
unsigned int dma_chan = it->options[2];
int ret;
- ret = comedi_request_region(dev, it->options[0], 0x20);
+ ret = comedi_check_request_region(dev, it->options[0], 0x20,
+ 0, 0x3ff, 32);
if (ret)
return ret;
diff --git a/drivers/comedi/drivers/ni_labpc_common.c b/drivers/comedi/drivers/ni_labpc_common.c
index 7e0ce0ce0adf..21b838a9d9ec 100644
--- a/drivers/comedi/drivers/ni_labpc_common.c
+++ b/drivers/comedi/drivers/ni_labpc_common.c
@@ -1357,17 +1357,6 @@ void labpc_common_detach(struct comedi_device *dev)
}
EXPORT_SYMBOL_GPL(labpc_common_detach);
-static int __init labpc_common_init(void)
-{
- return 0;
-}
-module_init(labpc_common_init);
-
-static void __exit labpc_common_exit(void)
-{
-}
-module_exit(labpc_common_exit);
-
MODULE_AUTHOR("Comedi https://www.comedi.org");
MODULE_DESCRIPTION("Comedi helper for ni_labpc, ni_labpc_pci, ni_labpc_cs");
MODULE_LICENSE("GPL");
diff --git a/drivers/comedi/drivers/ni_labpc_isadma.c b/drivers/comedi/drivers/ni_labpc_isadma.c
index 0652ca8345b6..125797f655f2 100644
--- a/drivers/comedi/drivers/ni_labpc_isadma.c
+++ b/drivers/comedi/drivers/ni_labpc_isadma.c
@@ -164,17 +164,6 @@ void labpc_free_dma_chan(struct comedi_device *dev)
}
EXPORT_SYMBOL_GPL(labpc_free_dma_chan);
-static int __init ni_labpc_isadma_init_module(void)
-{
- return 0;
-}
-module_init(ni_labpc_isadma_init_module);
-
-static void __exit ni_labpc_isadma_cleanup_module(void)
-{
-}
-module_exit(ni_labpc_isadma_cleanup_module);
-
MODULE_AUTHOR("Comedi https://www.comedi.org");
MODULE_DESCRIPTION("Comedi NI Lab-PC ISA DMA support");
MODULE_LICENSE("GPL");
diff --git a/drivers/comedi/drivers/ni_tio.c b/drivers/comedi/drivers/ni_tio.c
index 519359a870a7..c3a909abcfa7 100644
--- a/drivers/comedi/drivers/ni_tio.c
+++ b/drivers/comedi/drivers/ni_tio.c
@@ -1825,17 +1825,6 @@ void ni_gpct_device_destroy(struct ni_gpct_device *counter_dev)
}
EXPORT_SYMBOL_GPL(ni_gpct_device_destroy);
-static int __init ni_tio_init_module(void)
-{
- return 0;
-}
-module_init(ni_tio_init_module);
-
-static void __exit ni_tio_cleanup_module(void)
-{
-}
-module_exit(ni_tio_cleanup_module);
-
MODULE_AUTHOR("Comedi <comedi@comedi.org>");
MODULE_DESCRIPTION("Comedi support for NI general-purpose counters");
MODULE_LICENSE("GPL");
diff --git a/drivers/comedi/drivers/ni_tiocmd.c b/drivers/comedi/drivers/ni_tiocmd.c
index ab6d9e8269f3..9c166703626b 100644
--- a/drivers/comedi/drivers/ni_tiocmd.c
+++ b/drivers/comedi/drivers/ni_tiocmd.c
@@ -494,17 +494,6 @@ void ni_tio_set_mite_channel(struct ni_gpct *counter,
}
EXPORT_SYMBOL_GPL(ni_tio_set_mite_channel);
-static int __init ni_tiocmd_init_module(void)
-{
- return 0;
-}
-module_init(ni_tiocmd_init_module);
-
-static void __exit ni_tiocmd_cleanup_module(void)
-{
-}
-module_exit(ni_tiocmd_cleanup_module);
-
MODULE_AUTHOR("Comedi <comedi@comedi.org>");
MODULE_DESCRIPTION("Comedi command support for NI general-purpose counters");
MODULE_LICENSE("GPL");
diff --git a/drivers/comedi/drivers/ni_usb6501.c b/drivers/comedi/drivers/ni_usb6501.c
index 0dd9edf7bced..7afc5661a5ec 100644
--- a/drivers/comedi/drivers/ni_usb6501.c
+++ b/drivers/comedi/drivers/ni_usb6501.c
@@ -477,31 +477,16 @@ static int ni6501_find_endpoints(struct comedi_device *dev)
struct usb_interface *intf = comedi_to_usb_interface(dev);
struct ni6501_private *devpriv = dev->private;
struct usb_host_interface *iface_desc = intf->cur_altsetting;
- struct usb_endpoint_descriptor *ep_desc;
- int i;
+ int ret;
if (iface_desc->desc.bNumEndpoints != 2) {
dev_err(dev->class_dev, "Wrong number of endpoints\n");
return -ENODEV;
}
- for (i = 0; i < iface_desc->desc.bNumEndpoints; i++) {
- ep_desc = &iface_desc->endpoint[i].desc;
-
- if (usb_endpoint_is_bulk_in(ep_desc)) {
- if (!devpriv->ep_rx)
- devpriv->ep_rx = ep_desc;
- continue;
- }
-
- if (usb_endpoint_is_bulk_out(ep_desc)) {
- if (!devpriv->ep_tx)
- devpriv->ep_tx = ep_desc;
- continue;
- }
- }
-
- if (!devpriv->ep_rx || !devpriv->ep_tx)
+ ret = usb_find_common_endpoints(iface_desc, &devpriv->ep_rx,
+ &devpriv->ep_tx, NULL, NULL);
+ if (ret)
return -ENODEV;
if (usb_endpoint_maxp(devpriv->ep_rx) < RX_MAX_SIZE)
diff --git a/drivers/comedi/drivers/pcl711.c b/drivers/comedi/drivers/pcl711.c
index 0cf3917defe7..5d2c4b2aa3bb 100644
--- a/drivers/comedi/drivers/pcl711.c
+++ b/drivers/comedi/drivers/pcl711.c
@@ -112,6 +112,7 @@ struct pcl711_board {
int n_aichan;
int n_aochan;
int maxirq;
+ unsigned int min_io_start;
const struct comedi_lrange *ai_range_type;
};
@@ -132,12 +133,14 @@ static const struct pcl711_board boardtypes[] = {
.n_aichan = 16,
.n_aochan = 2,
.maxirq = 15,
+ .min_io_start = 0x200,
.ai_range_type = &range_acl8112hg_ai,
}, {
.name = "acl8112dg",
.n_aichan = 16,
.n_aochan = 2,
.maxirq = 15,
+ .min_io_start = 0x200,
.ai_range_type = &range_acl8112dg_ai,
},
};
@@ -418,7 +421,8 @@ static int pcl711_attach(struct comedi_device *dev, struct comedi_devconfig *it)
struct comedi_subdevice *s;
int ret;
- ret = comedi_request_region(dev, it->options[0], 0x10);
+ ret = comedi_check_request_region(dev, it->options[0], 0x10,
+ board->min_io_start, 0x3ff, 16);
if (ret)
return ret;
diff --git a/drivers/comedi/drivers/pcl724.c b/drivers/comedi/drivers/pcl724.c
index 00474710b81f..9707d0c89304 100644
--- a/drivers/comedi/drivers/pcl724.c
+++ b/drivers/comedi/drivers/pcl724.c
@@ -31,6 +31,8 @@
struct pcl724_board {
const char *name;
unsigned int io_range;
+ unsigned int min_io_start;
+ unsigned int max_io_end;
unsigned int can_have96:1;
unsigned int is_pet48:1;
int numofports;
@@ -40,37 +42,53 @@ static const struct pcl724_board boardtypes[] = {
{
.name = "pcl724",
.io_range = 0x04,
+ .min_io_start = 0x200,
+ .max_io_end = 0x3ff,
.numofports = 1, /* 24 DIO channels */
}, {
.name = "pcl722",
.io_range = 0x20,
+ .min_io_start = 0x200,
+ .max_io_end = 0x3ff,
.can_have96 = 1,
.numofports = 6, /* 144 (or 96) DIO channels */
}, {
.name = "pcl731",
.io_range = 0x08,
+ .min_io_start = 0,
+ .max_io_end = 0x3ff,
.numofports = 2, /* 48 DIO channels */
}, {
.name = "acl7122",
.io_range = 0x20,
+ .min_io_start = 0x200,
+ .max_io_end = 0x3ff,
.can_have96 = 1,
.numofports = 6, /* 144 (or 96) DIO channels */
}, {
.name = "acl7124",
.io_range = 0x04,
+ .min_io_start = 0x200,
+ .max_io_end = 0x3ff,
.numofports = 1, /* 24 DIO channels */
}, {
.name = "pet48dio",
.io_range = 0x02,
+ .min_io_start = 0,
+ .max_io_end = 0x3ff,
.is_pet48 = 1,
.numofports = 2, /* 48 DIO channels */
}, {
.name = "pcmio48",
.io_range = 0x08,
+ .min_io_start = 0x100,
+ .max_io_end = 0x17f,
.numofports = 2, /* 48 DIO channels */
}, {
.name = "onyx-mm-dio",
.io_range = 0x10,
+ .min_io_start = 0,
+ .max_io_end = 0x3ff,
.numofports = 2, /* 48 DIO channels */
},
};
@@ -112,7 +130,9 @@ static int pcl724_attach(struct comedi_device *dev,
n_subdevices = 4;
}
- ret = comedi_request_region(dev, it->options[0], iorange);
+ ret = comedi_check_request_region(dev, it->options[0], iorange,
+ board->min_io_start,
+ board->max_io_end, iorange);
if (ret)
return ret;
diff --git a/drivers/comedi/drivers/pcl726.c b/drivers/comedi/drivers/pcl726.c
index b542896fa0e4..d3b1f4388643 100644
--- a/drivers/comedi/drivers/pcl726.c
+++ b/drivers/comedi/drivers/pcl726.c
@@ -91,7 +91,8 @@ static const struct comedi_lrange *const rangelist_728[] = {
struct pcl726_board {
const char *name;
- unsigned long io_len;
+ unsigned int io_len;
+ unsigned int min_io_start;
unsigned int irq_mask;
const struct comedi_lrange *const *ao_ranges;
int ao_num_ranges;
@@ -104,6 +105,7 @@ static const struct pcl726_board pcl726_boards[] = {
{
.name = "pcl726",
.io_len = 0x10,
+ .min_io_start = 0x200,
.ao_ranges = &rangelist_726[0],
.ao_num_ranges = ARRAY_SIZE(rangelist_726),
.ao_nchan = 6,
@@ -111,6 +113,7 @@ static const struct pcl726_board pcl726_boards[] = {
}, {
.name = "pcl727",
.io_len = 0x20,
+ .min_io_start = 0x200,
.ao_ranges = &rangelist_727[0],
.ao_num_ranges = ARRAY_SIZE(rangelist_727),
.ao_nchan = 12,
@@ -119,12 +122,14 @@ static const struct pcl726_board pcl726_boards[] = {
}, {
.name = "pcl728",
.io_len = 0x08,
+ .min_io_start = 0,
.ao_num_ranges = ARRAY_SIZE(rangelist_728),
.ao_ranges = &rangelist_728[0],
.ao_nchan = 2,
}, {
.name = "acl6126",
.io_len = 0x10,
+ .min_io_start = 0x200,
.irq_mask = 0x96e8,
.ao_num_ranges = ARRAY_SIZE(rangelist_726),
.ao_ranges = &rangelist_726[0],
@@ -133,6 +138,7 @@ static const struct pcl726_board pcl726_boards[] = {
}, {
.name = "acl6128",
.io_len = 0x08,
+ .min_io_start = 0,
.ao_num_ranges = ARRAY_SIZE(rangelist_728),
.ao_ranges = &rangelist_728[0],
.ao_nchan = 2,
@@ -316,7 +322,9 @@ static int pcl726_attach(struct comedi_device *dev,
int ret;
int i;
- ret = comedi_request_region(dev, it->options[0], board->io_len);
+ ret = comedi_check_request_region(dev, it->options[0], board->io_len,
+ board->min_io_start, 0x3ff,
+ board->io_len);
if (ret)
return ret;
diff --git a/drivers/comedi/drivers/pcl730.c b/drivers/comedi/drivers/pcl730.c
index d2733cd5383d..cf0f97b6e2c0 100644
--- a/drivers/comedi/drivers/pcl730.c
+++ b/drivers/comedi/drivers/pcl730.c
@@ -101,7 +101,9 @@
struct pcl730_board {
const char *name;
- unsigned int io_range;
+ unsigned short io_range;
+ unsigned short min_io_start;
+ unsigned short align_io_start;
unsigned is_pcl725:1;
unsigned is_acl7225b:1;
unsigned is_ir104:1;
@@ -117,6 +119,8 @@ static const struct pcl730_board pcl730_boards[] = {
{
.name = "pcl730",
.io_range = 0x04,
+ .min_io_start = 0,
+ .align_io_start = 0x04,
.has_ttl_io = 1,
.n_subdevs = 4,
.n_iso_out_chan = 16,
@@ -125,6 +129,8 @@ static const struct pcl730_board pcl730_boards[] = {
}, {
.name = "iso730",
.io_range = 0x04,
+ .min_io_start = 0,
+ .align_io_start = 0x04,
.n_subdevs = 4,
.n_iso_out_chan = 16,
.n_iso_in_chan = 16,
@@ -132,6 +138,8 @@ static const struct pcl730_board pcl730_boards[] = {
}, {
.name = "acl7130",
.io_range = 0x08,
+ .min_io_start = 0x200,
+ .align_io_start = 0x08,
.has_ttl_io = 1,
.n_subdevs = 4,
.n_iso_out_chan = 16,
@@ -140,6 +148,8 @@ static const struct pcl730_board pcl730_boards[] = {
}, {
.name = "pcm3730",
.io_range = 0x04,
+ .min_io_start = 0,
+ .align_io_start = 0x04,
.has_ttl_io = 1,
.n_subdevs = 4,
.n_iso_out_chan = 8,
@@ -148,6 +158,8 @@ static const struct pcl730_board pcl730_boards[] = {
}, {
.name = "pcl725",
.io_range = 0x02,
+ .min_io_start = 0x200,
+ .align_io_start = 0x02,
.is_pcl725 = 1,
.n_subdevs = 2,
.n_iso_out_chan = 8,
@@ -155,6 +167,8 @@ static const struct pcl730_board pcl730_boards[] = {
}, {
.name = "p8r8dio",
.io_range = 0x02,
+ .min_io_start = 0,
+ .align_io_start = 0x10,
.is_pcl725 = 1,
.has_readback = 1,
.n_subdevs = 2,
@@ -163,6 +177,8 @@ static const struct pcl730_board pcl730_boards[] = {
}, {
.name = "acl7225b",
.io_range = 0x08, /* only 4 are used */
+ .min_io_start = 0x200,
+ .align_io_start = 0x08,
.is_acl7225b = 1,
.has_readback = 1,
.n_subdevs = 2,
@@ -171,6 +187,8 @@ static const struct pcl730_board pcl730_boards[] = {
}, {
.name = "p16r16dio",
.io_range = 0x04,
+ .min_io_start = 0,
+ .align_io_start = 0x08,
.is_acl7225b = 1,
.has_readback = 1,
.n_subdevs = 2,
@@ -179,16 +197,22 @@ static const struct pcl730_board pcl730_boards[] = {
}, {
.name = "pcl733",
.io_range = 0x04,
+ .min_io_start = 0,
+ .align_io_start = 0x04,
.n_subdevs = 1,
.n_iso_in_chan = 32,
}, {
.name = "pcl734",
.io_range = 0x04,
+ .min_io_start = 0,
+ .align_io_start = 0x04,
.n_subdevs = 1,
.n_iso_out_chan = 32,
}, {
.name = "opmm-1616-xt",
.io_range = 0x10,
+ .min_io_start = 0x100,
+ .align_io_start = 0x10,
.is_acl7225b = 1,
.has_readback = 1,
.n_subdevs = 2,
@@ -197,11 +221,15 @@ static const struct pcl730_board pcl730_boards[] = {
}, {
.name = "pearl-mm-p",
.io_range = 0x02,
+ .min_io_start = 0x240,
+ .align_io_start = 0x40,
.n_subdevs = 1,
.n_iso_out_chan = 16,
}, {
.name = "ir104-pbf",
.io_range = 0x08,
+ .min_io_start = 0x240,
+ .align_io_start = 0x20,
.is_ir104 = 1,
.has_readback = 1,
.n_iso_out_chan = 20,
@@ -266,10 +294,27 @@ static int pcl730_attach(struct comedi_device *dev,
{
const struct pcl730_board *board = dev->board_ptr;
struct comedi_subdevice *s;
+ unsigned int iobase = it->options[0];
int subdev;
int ret;
- ret = comedi_request_region(dev, it->options[0], board->io_range);
+ if (board->is_ir104) {
+ switch (iobase) {
+ case 0x240:
+ case 0x260:
+ case 0x280:
+ case 0x300:
+ break;
+ default:
+ dev_warn(dev->class_dev,
+ "%s: unsupported I/O base address %#x\n",
+ dev->board_name, iobase);
+ return -EINVAL;
+ }
+ }
+ ret = comedi_check_request_region(dev, iobase, board->io_range,
+ board->min_io_start, 0x3ff,
+ board->align_io_start);
if (ret)
return ret;
diff --git a/drivers/comedi/drivers/pcl812.c b/drivers/comedi/drivers/pcl812.c
index abca61a72cf7..98b75792c09b 100644
--- a/drivers/comedi/drivers/pcl812.c
+++ b/drivers/comedi/drivers/pcl812.c
@@ -331,6 +331,7 @@ enum pcl812_boardtype {
struct pcl812_board {
const char *name;
enum pcl812_boardtype board_type;
+ unsigned short min_io_start;
int n_aichan;
int n_aochan;
unsigned int ai_ns_min;
@@ -346,6 +347,7 @@ static const struct pcl812_board boardtypes[] = {
{
.name = "pcl812",
.board_type = BOARD_PCL812,
+ .min_io_start = 0,
.n_aichan = 16,
.n_aochan = 2,
.ai_ns_min = 33000,
@@ -355,6 +357,7 @@ static const struct pcl812_board boardtypes[] = {
.has_dio = 1,
}, {
.name = "pcl812pg",
+ .min_io_start = 0,
.board_type = BOARD_PCL812PG,
.n_aichan = 16,
.n_aochan = 2,
@@ -366,6 +369,7 @@ static const struct pcl812_board boardtypes[] = {
}, {
.name = "acl8112pg",
.board_type = BOARD_PCL812PG,
+ .min_io_start = 0x200,
.n_aichan = 16,
.n_aochan = 2,
.ai_ns_min = 10000,
@@ -376,6 +380,7 @@ static const struct pcl812_board boardtypes[] = {
}, {
.name = "acl8112dg",
.board_type = BOARD_ACL8112,
+ .min_io_start = 0x200,
.n_aichan = 16, /* 8 differential */
.n_aochan = 2,
.ai_ns_min = 10000,
@@ -387,6 +392,7 @@ static const struct pcl812_board boardtypes[] = {
}, {
.name = "acl8112hg",
.board_type = BOARD_ACL8112,
+ .min_io_start = 0x200,
.n_aichan = 16, /* 8 differential */
.n_aochan = 2,
.ai_ns_min = 10000,
@@ -398,6 +404,7 @@ static const struct pcl812_board boardtypes[] = {
}, {
.name = "a821pgl",
.board_type = BOARD_A821,
+ .min_io_start = 0,
.n_aichan = 16, /* 8 differential */
.n_aochan = 1,
.ai_ns_min = 10000,
@@ -407,6 +414,7 @@ static const struct pcl812_board boardtypes[] = {
}, {
.name = "a821pglnda",
.board_type = BOARD_A821,
+ .min_io_start = 0,
.n_aichan = 16, /* 8 differential */
.ai_ns_min = 10000,
.rangelist_ai = &range_pcl813b_ai,
@@ -414,6 +422,7 @@ static const struct pcl812_board boardtypes[] = {
}, {
.name = "a821pgh",
.board_type = BOARD_A821,
+ .min_io_start = 0,
.n_aichan = 16, /* 8 differential */
.n_aochan = 1,
.ai_ns_min = 10000,
@@ -423,6 +432,7 @@ static const struct pcl812_board boardtypes[] = {
}, {
.name = "a822pgl",
.board_type = BOARD_ACL8112,
+ .min_io_start = 0,
.n_aichan = 16, /* 8 differential */
.n_aochan = 2,
.ai_ns_min = 10000,
@@ -433,6 +443,7 @@ static const struct pcl812_board boardtypes[] = {
}, {
.name = "a822pgh",
.board_type = BOARD_ACL8112,
+ .min_io_start = 0,
.n_aichan = 16, /* 8 differential */
.n_aochan = 2,
.ai_ns_min = 10000,
@@ -443,6 +454,7 @@ static const struct pcl812_board boardtypes[] = {
}, {
.name = "a823pgl",
.board_type = BOARD_ACL8112,
+ .min_io_start = 0,
.n_aichan = 16, /* 8 differential */
.n_aochan = 2,
.ai_ns_min = 8000,
@@ -453,6 +465,7 @@ static const struct pcl812_board boardtypes[] = {
}, {
.name = "a823pgh",
.board_type = BOARD_ACL8112,
+ .min_io_start = 0,
.n_aichan = 16, /* 8 differential */
.n_aochan = 2,
.ai_ns_min = 8000,
@@ -463,26 +476,31 @@ static const struct pcl812_board boardtypes[] = {
}, {
.name = "pcl813",
.board_type = BOARD_PCL813,
+ .min_io_start = 0,
.n_aichan = 32,
.rangelist_ai = &range_pcl813b_ai,
}, {
.name = "pcl813b",
.board_type = BOARD_PCL813B,
+ .min_io_start = 0,
.n_aichan = 32,
.rangelist_ai = &range_pcl813b_ai,
}, {
.name = "acl8113",
.board_type = BOARD_ACL8113,
+ .min_io_start = 0x200,
.n_aichan = 32,
.rangelist_ai = &range_acl8113_1_ai,
}, {
.name = "iso813",
.board_type = BOARD_ISO813,
+ .min_io_start = 0,
.n_aichan = 32,
.rangelist_ai = &range_iso813_1_ai,
}, {
.name = "acl8216",
.board_type = BOARD_ACL8216,
+ .min_io_start = 0x200,
.n_aichan = 16, /* 8 differential */
.n_aochan = 2,
.ai_ns_min = 10000,
@@ -495,6 +513,7 @@ static const struct pcl812_board boardtypes[] = {
}, {
.name = "a826pg",
.board_type = BOARD_ACL8216,
+ .min_io_start = 0,
.n_aichan = 16, /* 8 differential */
.n_aochan = 2,
.ai_ns_min = 10000,
@@ -1138,7 +1157,8 @@ static int pcl812_attach(struct comedi_device *dev, struct comedi_devconfig *it)
if (!devpriv)
return -ENOMEM;
- ret = comedi_request_region(dev, it->options[0], 0x10);
+ ret = comedi_check_request_region(dev, it->options[0], 0x10,
+ board->min_io_start, 0x3ff, 16);
if (ret)
return ret;
diff --git a/drivers/comedi/drivers/pcl816.c b/drivers/comedi/drivers/pcl816.c
index 28d1a88c50f6..1fcb2f798c7a 100644
--- a/drivers/comedi/drivers/pcl816.c
+++ b/drivers/comedi/drivers/pcl816.c
@@ -608,7 +608,8 @@ static int pcl816_attach(struct comedi_device *dev, struct comedi_devconfig *it)
if (!devpriv)
return -ENOMEM;
- ret = comedi_request_region(dev, it->options[0], 0x10);
+ ret = comedi_check_request_region(dev, it->options[0], 0x10,
+ 0, 0x3ff, 16);
if (ret)
return ret;
diff --git a/drivers/comedi/drivers/pcl818.c b/drivers/comedi/drivers/pcl818.c
index 06fe06396f23..aa775a024fc7 100644
--- a/drivers/comedi/drivers/pcl818.c
+++ b/drivers/comedi/drivers/pcl818.c
@@ -981,6 +981,10 @@ static int pcl818_attach(struct comedi_device *dev, struct comedi_devconfig *it)
const struct pcl818_board *board = dev->board_ptr;
struct pcl818_private *devpriv;
struct comedi_subdevice *s;
+ unsigned int io_base = it->options[0];
+ bool fifo_is_supported = board->has_fifo && !(io_base & 0x10);
+ bool fifo_is_wanted = board->has_fifo && it->options[2] == -1;
+ unsigned int io_len = fifo_is_supported ? 0x20 : 0x10;
unsigned int osc_base;
int ret;
@@ -988,11 +992,28 @@ static int pcl818_attach(struct comedi_device *dev, struct comedi_devconfig *it)
if (!devpriv)
return -ENOMEM;
- ret = comedi_request_region(dev, it->options[0],
- board->has_fifo ? 0x20 : 0x10);
+ ret = comedi_check_request_region(dev, io_base, io_len,
+ 0, 0x3ff, io_len);
if (ret)
return ret;
+ if (board->has_fifo) {
+ /* let user know about any required JP6 setting */
+ if (fifo_is_supported) {
+ if (fifo_is_wanted) {
+ dev_info(dev->class_dev,
+ "Assuming JP6 is in \"Enabled\" (default) position to use the FIFO.\n");
+ }
+ } else {
+ dev_info(dev->class_dev,
+ "JP6 needs to be in \"Disabled\" position for correct operation at this base address\n");
+ if (fifo_is_wanted) {
+ dev_warn(dev->class_dev,
+ "FIFO cannot be used at this base address\n");
+ }
+ }
+ }
+
/* we can use IRQ 2-7 for async command support */
if (it->options[1] >= 2 && it->options[1] <= 7) {
ret = request_irq(it->options[1], pcl818_interrupt, 0,
@@ -1002,7 +1023,7 @@ static int pcl818_attach(struct comedi_device *dev, struct comedi_devconfig *it)
}
/* should we use the FIFO? */
- if (dev->irq && board->has_fifo && it->options[2] == -1)
+ if (dev->irq && fifo_is_supported && fifo_is_wanted)
devpriv->usefifo = 1;
/* we need an IRQ to do DMA on channel 3 or 1 */
diff --git a/drivers/comedi/drivers/pcm3724.c b/drivers/comedi/drivers/pcm3724.c
index fb41de3baef8..867bb5b3860a 100644
--- a/drivers/comedi/drivers/pcm3724.c
+++ b/drivers/comedi/drivers/pcm3724.c
@@ -194,7 +194,8 @@ static int pcm3724_attach(struct comedi_device *dev,
if (!priv)
return -ENOMEM;
- ret = comedi_request_region(dev, it->options[0], 0x10);
+ ret = comedi_check_request_region(dev, it->options[0], 0x10,
+ 0, 0x3ff, 16);
if (ret)
return ret;
diff --git a/drivers/comedi/drivers/pcmad.c b/drivers/comedi/drivers/pcmad.c
index 976eda43881b..fd26b1eed1db 100644
--- a/drivers/comedi/drivers/pcmad.c
+++ b/drivers/comedi/drivers/pcmad.c
@@ -106,7 +106,8 @@ static int pcmad_attach(struct comedi_device *dev, struct comedi_devconfig *it)
struct comedi_subdevice *s;
int ret;
- ret = comedi_request_region(dev, it->options[0], 0x04);
+ ret = comedi_check_request_region(dev, it->options[0], 0x04,
+ 0, 0x3ff, 4);
if (ret)
return ret;
diff --git a/drivers/comedi/drivers/pcmda12.c b/drivers/comedi/drivers/pcmda12.c
index 611f13bedca0..6efd1ae6271a 100644
--- a/drivers/comedi/drivers/pcmda12.c
+++ b/drivers/comedi/drivers/pcmda12.c
@@ -120,7 +120,14 @@ static int pcmda12_attach(struct comedi_device *dev,
struct comedi_subdevice *s;
int ret;
- ret = comedi_request_region(dev, it->options[0], 0x10);
+ /*
+ * The datasheet says it requires 16 contiguous addresses and is
+ * "configurable on any even sixteen port boundary". So require
+ * a 32-byte boundary and assume it uses 10-bit addresses like
+ * similar boards.
+ */
+ ret = comedi_check_request_region(dev, it->options[0], 0x10,
+ 0, 0x3ff, 32);
if (ret)
return ret;
diff --git a/drivers/comedi/drivers/pcmmio.c b/drivers/comedi/drivers/pcmmio.c
index c2402239d551..d38202c8a12b 100644
--- a/drivers/comedi/drivers/pcmmio.c
+++ b/drivers/comedi/drivers/pcmmio.c
@@ -667,7 +667,8 @@ static int pcmmio_attach(struct comedi_device *dev, struct comedi_devconfig *it)
struct comedi_subdevice *s;
int ret;
- ret = comedi_request_region(dev, it->options[0], 32);
+ ret = comedi_check_request_region(dev, it->options[0], 32,
+ 0, 0xffff, 32);
if (ret)
return ret;
diff --git a/drivers/comedi/drivers/pcmuio.c b/drivers/comedi/drivers/pcmuio.c
index 33b24dbbb919..0995911a3ea3 100644
--- a/drivers/comedi/drivers/pcmuio.c
+++ b/drivers/comedi/drivers/pcmuio.c
@@ -521,11 +521,12 @@ static int pcmuio_attach(struct comedi_device *dev, struct comedi_devconfig *it)
const struct pcmuio_board *board = dev->board_ptr;
struct comedi_subdevice *s;
struct pcmuio_private *devpriv;
+ unsigned int io_len = board->num_asics * PCMUIO_ASIC_IOSIZE;
int ret;
int i;
- ret = comedi_request_region(dev, it->options[0],
- board->num_asics * PCMUIO_ASIC_IOSIZE);
+ ret = comedi_check_request_region(dev, it->options[0], io_len,
+ 0, 0xffff, io_len);
if (ret)
return ret;
diff --git a/drivers/comedi/drivers/rti800.c b/drivers/comedi/drivers/rti800.c
index 1b02e47bdb4c..fa3965cf92f2 100644
--- a/drivers/comedi/drivers/rti800.c
+++ b/drivers/comedi/drivers/rti800.c
@@ -257,7 +257,8 @@ static int rti800_attach(struct comedi_device *dev, struct comedi_devconfig *it)
struct comedi_subdevice *s;
int ret;
- ret = comedi_request_region(dev, it->options[0], 0x10);
+ ret = comedi_check_request_region(dev, it->options[0], 0x10,
+ 0, 0x3ff, 16);
if (ret)
return ret;
diff --git a/drivers/comedi/drivers/rti802.c b/drivers/comedi/drivers/rti802.c
index d66762a22258..af990881c27a 100644
--- a/drivers/comedi/drivers/rti802.c
+++ b/drivers/comedi/drivers/rti802.c
@@ -72,7 +72,8 @@ static int rti802_attach(struct comedi_device *dev, struct comedi_devconfig *it)
int i;
int ret;
- ret = comedi_request_region(dev, it->options[0], 0x04);
+ ret = comedi_check_request_region(dev, it->options[0], 0x04,
+ 0, 0x3ff, 4);
if (ret)
return ret;
diff --git a/drivers/comedi/drivers/s526.c b/drivers/comedi/drivers/s526.c
index 9245c679a3c4..dd27c754dea4 100644
--- a/drivers/comedi/drivers/s526.c
+++ b/drivers/comedi/drivers/s526.c
@@ -553,7 +553,8 @@ static int s526_attach(struct comedi_device *dev, struct comedi_devconfig *it)
struct comedi_subdevice *s;
int ret;
- ret = comedi_request_region(dev, it->options[0], 0x40);
+ ret = comedi_check_request_region(dev, it->options[0], 0x40,
+ 0, 0xffc0, 64);
if (ret)
return ret;
diff --git a/drivers/comedi/kcomedilib/kcomedilib_main.c b/drivers/comedi/kcomedilib/kcomedilib_main.c
index baa9eaaf97d4..517e60ffd81b 100644
--- a/drivers/comedi/kcomedilib/kcomedilib_main.c
+++ b/drivers/comedi/kcomedilib/kcomedilib_main.c
@@ -351,15 +351,3 @@ int comedi_get_n_channels(struct comedi_device *dev, unsigned int subdevice)
return n;
}
EXPORT_SYMBOL_GPL(comedi_get_n_channels);
-
-static int __init kcomedilib_module_init(void)
-{
- return 0;
-}
-
-static void __exit kcomedilib_module_exit(void)
-{
-}
-
-module_init(kcomedilib_module_init);
-module_exit(kcomedilib_module_exit);
diff --git a/drivers/counter/counter-sysfs.c b/drivers/counter/counter-sysfs.c
index 42c523343d32..ed85da907982 100644
--- a/drivers/counter/counter-sysfs.c
+++ b/drivers/counter/counter-sysfs.c
@@ -1101,8 +1101,6 @@ static int counter_sysfs_attr_add(struct counter_device *const counter,
/* Add device extensions */
return counter_sysfs_exts_add(dev, cattr_group, counter->ext,
counter->num_ext, scope, NULL);
-
- return 0;
}
/**
diff --git a/drivers/extcon/Kconfig b/drivers/extcon/Kconfig
index aec46bf03302..68d9df7d2dae 100644
--- a/drivers/extcon/Kconfig
+++ b/drivers/extcon/Kconfig
@@ -158,6 +158,7 @@ config EXTCON_PTN5150
tristate "NXP PTN5150 CC LOGIC USB EXTCON support"
depends on I2C && (GPIOLIB || COMPILE_TEST)
depends on USB_ROLE_SWITCH || !USB_ROLE_SWITCH
+ depends on TYPEC || !TYPEC
select REGMAP_I2C
help
Say Y here to enable support for USB peripheral and USB host
diff --git a/drivers/extcon/extcon-intel-int3496.c b/drivers/extcon/extcon-intel-int3496.c
index ded1a85a5549..7d16d5b7d58f 100644
--- a/drivers/extcon/extcon-intel-int3496.c
+++ b/drivers/extcon/extcon-intel-int3496.c
@@ -106,7 +106,7 @@ static irqreturn_t int3496_thread_isr(int irq, void *priv)
struct int3496_data *data = priv;
/* Let the pin settle before processing it */
- mod_delayed_work(system_wq, &data->work, DEBOUNCE_TIME);
+ mod_delayed_work(system_percpu_wq, &data->work, DEBOUNCE_TIME);
return IRQ_HANDLED;
}
@@ -181,7 +181,7 @@ static int int3496_probe(struct platform_device *pdev)
}
/* process id-pin so that we start with the right status */
- queue_delayed_work(system_wq, &data->work, 0);
+ queue_delayed_work(system_percpu_wq, &data->work, 0);
flush_delayed_work(&data->work);
platform_set_drvdata(pdev, data);
diff --git a/drivers/extcon/extcon-ptn5150.c b/drivers/extcon/extcon-ptn5150.c
index 78ad86c4a3be..eca1b140aeb0 100644
--- a/drivers/extcon/extcon-ptn5150.c
+++ b/drivers/extcon/extcon-ptn5150.c
@@ -18,6 +18,7 @@
#include <linux/extcon-provider.h>
#include <linux/gpio/consumer.h>
#include <linux/usb/role.h>
+#include <linux/usb/typec_mux.h>
/* PTN5150 registers */
#define PTN5150_REG_DEVICE_ID 0x01
@@ -38,7 +39,11 @@
#define PTN5150_REG_DEVICE_ID_VERSION GENMASK(7, 3)
#define PTN5150_REG_DEVICE_ID_VENDOR GENMASK(2, 0)
+#define PTN5150_POLARITY_CC1 0x1
+#define PTN5150_POLARITY_CC2 0x2
+
#define PTN5150_REG_CC_PORT_ATTACHMENT GENMASK(4, 2)
+#define PTN5150_REG_CC_POLARITY GENMASK(1, 0)
#define PTN5150_REG_CC_VBUS_DETECTION BIT(7)
#define PTN5150_REG_INT_CABLE_ATTACH_MASK BIT(0)
#define PTN5150_REG_INT_CABLE_DETACH_MASK BIT(1)
@@ -53,6 +58,7 @@ struct ptn5150_info {
int irq;
struct work_struct irq_work;
struct mutex mutex;
+ struct typec_switch *orient_sw;
struct usb_role_switch *role_sw;
};
@@ -71,6 +77,7 @@ static const struct regmap_config ptn5150_regmap_config = {
static void ptn5150_check_state(struct ptn5150_info *info)
{
+ enum typec_orientation orient = TYPEC_ORIENTATION_NONE;
unsigned int port_status, reg_data, vbus;
enum usb_role usb_role = USB_ROLE_NONE;
int ret;
@@ -81,6 +88,23 @@ static void ptn5150_check_state(struct ptn5150_info *info)
return;
}
+ orient = FIELD_GET(PTN5150_REG_CC_POLARITY, reg_data);
+ switch (orient) {
+ case PTN5150_POLARITY_CC1:
+ orient = TYPEC_ORIENTATION_NORMAL;
+ break;
+ case PTN5150_POLARITY_CC2:
+ orient = TYPEC_ORIENTATION_REVERSE;
+ break;
+ default:
+ orient = TYPEC_ORIENTATION_NONE;
+ break;
+ }
+
+ ret = typec_switch_set(info->orient_sw, orient);
+ if (ret)
+ dev_err(info->dev, "failed to set orientation: %d\n", ret);
+
port_status = FIELD_GET(PTN5150_REG_CC_PORT_ATTACHMENT, reg_data);
switch (port_status) {
@@ -152,6 +176,12 @@ static void ptn5150_irq_work(struct work_struct *work)
dev_err(info->dev,
"failed to set none role: %d\n",
ret);
+
+ ret = typec_switch_set(info->orient_sw,
+ TYPEC_ORIENTATION_NONE);
+ if (ret)
+ dev_err(info->dev,
+ "failed to set orientation: %d\n", ret);
}
}
@@ -219,12 +249,14 @@ static void ptn5150_work_sync_and_put(void *data)
cancel_work_sync(&info->irq_work);
usb_role_switch_put(info->role_sw);
+ typec_switch_put(info->orient_sw);
}
static int ptn5150_i2c_probe(struct i2c_client *i2c)
{
struct device *dev = &i2c->dev;
struct device_node *np = i2c->dev.of_node;
+ struct fwnode_handle *connector;
struct ptn5150_info *info;
int ret;
@@ -311,7 +343,17 @@ static int ptn5150_i2c_probe(struct i2c_client *i2c)
if (ret)
return -EINVAL;
+ connector = device_get_named_child_node(dev, "connector");
+ if (connector) {
+ info->orient_sw = fwnode_typec_switch_get(connector);
+ if (IS_ERR(info->orient_sw))
+ return dev_err_probe(info->dev, PTR_ERR(info->orient_sw),
+ "failed to get orientation switch\n");
+ }
+
info->role_sw = usb_role_switch_get(info->dev);
+ if (!info->role_sw && connector)
+ info->role_sw = fwnode_usb_role_switch_get(connector);
if (IS_ERR(info->role_sw))
return dev_err_probe(info->dev, PTR_ERR(info->role_sw),
"failed to get role switch\n");
@@ -331,6 +373,19 @@ static int ptn5150_i2c_probe(struct i2c_client *i2c)
return 0;
}
+static int ptn5150_resume(struct device *dev)
+{
+ struct i2c_client *i2c = to_i2c_client(dev);
+ struct ptn5150_info *info = i2c_get_clientdata(i2c);
+
+ /* Need to check possible pending interrupt events */
+ schedule_work(&info->irq_work);
+
+ return 0;
+}
+
+static DEFINE_SIMPLE_DEV_PM_OPS(ptn5150_pm_ops, NULL, ptn5150_resume);
+
static const struct of_device_id ptn5150_dt_match[] = {
{ .compatible = "nxp,ptn5150" },
{ },
@@ -346,6 +401,7 @@ MODULE_DEVICE_TABLE(i2c, ptn5150_i2c_id);
static struct i2c_driver ptn5150_i2c_driver = {
.driver = {
.name = "ptn5150",
+ .pm = pm_sleep_ptr(&ptn5150_pm_ops),
.of_match_table = ptn5150_dt_match,
},
.probe = ptn5150_i2c_probe,
diff --git a/drivers/extcon/extcon-usbc-tusb320.c b/drivers/extcon/extcon-usbc-tusb320.c
index 2eab341de6b7..920b03421850 100644
--- a/drivers/extcon/extcon-usbc-tusb320.c
+++ b/drivers/extcon/extcon-usbc-tusb320.c
@@ -454,20 +454,18 @@ static int tusb320_typec_probe(struct i2c_client *client,
priv->port_type = priv->cap.type;
/* This goes into register 0x8 field CURRENT_MODE_ADVERTISE */
- ret = fwnode_property_read_string(connector, "typec-power-opmode", &cap_str);
- if (ret)
- goto err_put;
-
- ret = typec_find_pwr_opmode(cap_str);
- if (ret < 0)
- goto err_put;
-
- priv->pwr_opmode = ret;
+ if (!fwnode_property_read_string(connector, "typec-power-opmode",
+ &cap_str)) {
+ ret = typec_find_pwr_opmode(cap_str);
+ if (ret < 0)
+ goto err_put;
+ priv->pwr_opmode = ret;
- /* Initialize the hardware with the devicetree settings. */
- ret = tusb320_set_adv_pwr_mode(priv);
- if (ret)
- goto err_put;
+ /* Initialize the hardware with the devicetree settings. */
+ ret = tusb320_set_adv_pwr_mode(priv);
+ if (ret)
+ goto err_put;
+ }
priv->cap.revision = USB_TYPEC_REV_1_1;
priv->cap.accessory[0] = TYPEC_ACCESSORY_AUDIO;
diff --git a/drivers/extcon/extcon.c b/drivers/extcon/extcon.c
index d9e9815a5f96..98d85cc114a7 100644
--- a/drivers/extcon/extcon.c
+++ b/drivers/extcon/extcon.c
@@ -1366,10 +1366,10 @@ void extcon_dev_unregister(struct extcon_dev *edev)
return;
}
- ida_free(&extcon_dev_ids, edev->id);
-
device_unregister(&edev->dev);
+ ida_free(&extcon_dev_ids, edev->id);
+
if (edev->mutually_exclusive && edev->max_supported) {
for (index = 0; edev->mutually_exclusive[index];
index++)
diff --git a/drivers/fpga/fpga-bridge.c b/drivers/fpga/fpga-bridge.c
index ca68c38aa4a1..8c275bd48a0d 100644
--- a/drivers/fpga/fpga-bridge.c
+++ b/drivers/fpga/fpga-bridge.c
@@ -290,7 +290,7 @@ static ssize_t name_show(struct device *dev,
{
struct fpga_bridge *bridge = to_fpga_bridge(dev);
- return sprintf(buf, "%s\n", bridge->name);
+ return sysfs_emit(buf, "%s\n", bridge->name);
}
static ssize_t state_show(struct device *dev,
diff --git a/drivers/fpga/intel-m10-bmc-sec-update.c b/drivers/fpga/intel-m10-bmc-sec-update.c
index 10f678b9ed36..b15dab6a39a3 100644
--- a/drivers/fpga/intel-m10-bmc-sec-update.c
+++ b/drivers/fpga/intel-m10-bmc-sec-update.c
@@ -183,7 +183,7 @@ show_canceled_csk(struct device *dev, u32 addr, char *buf)
bitmap_from_arr32(csk_map, csk32, CSK_BIT_LEN);
bitmap_complement(csk_map, csk_map, CSK_BIT_LEN);
- return bitmap_print_to_pagebuf(1, buf, csk_map, CSK_BIT_LEN);
+ return sysfs_emit(buf, "%*pbl\n", CSK_BIT_LEN, csk_map);
}
#define DEVICE_ATTR_SEC_CSK_RO(_name) \
diff --git a/drivers/gpib/agilent_82357a/agilent_82357a.c b/drivers/gpib/agilent_82357a/agilent_82357a.c
index e1349afbf933..770ba6eb40d1 100644
--- a/drivers/gpib/agilent_82357a/agilent_82357a.c
+++ b/drivers/gpib/agilent_82357a/agilent_82357a.c
@@ -1479,7 +1479,7 @@ static int agilent_82357a_driver_probe(struct usb_interface *interface,
if (mutex_lock_interruptible(&agilent_82357a_hotplug_lock))
return -ERESTARTSYS;
- usb_dev = usb_get_dev(interface_to_usbdev(interface));
+ usb_dev = interface_to_usbdev(interface);
for (i = 0; i < MAX_NUM_82357A_INTERFACES; ++i) {
if (!agilent_82357a_driver_interfaces[i]) {
agilent_82357a_driver_interfaces[i] = interface;
@@ -1490,14 +1490,12 @@ static int agilent_82357a_driver_probe(struct usb_interface *interface,
}
}
if (i == MAX_NUM_82357A_INTERFACES) {
- usb_put_dev(usb_dev);
mutex_unlock(&agilent_82357a_hotplug_lock);
dev_err(&usb_dev->dev, "out of space in agilent_82357a_driver_interfaces[]\n");
return -1;
}
path = kmalloc(path_length, GFP_KERNEL);
if (!path) {
- usb_put_dev(usb_dev);
mutex_unlock(&agilent_82357a_hotplug_lock);
return -ENOMEM;
}
@@ -1539,7 +1537,6 @@ static void agilent_82357a_driver_disconnect(struct usb_interface *interface)
}
if (i == MAX_NUM_82357A_INTERFACES)
dev_err(&usb_dev->dev, "unable to find interface - bug?\n");
- usb_put_dev(usb_dev);
mutex_unlock(&agilent_82357a_hotplug_lock);
}
diff --git a/drivers/gpib/common/gpib_os.c b/drivers/gpib/common/gpib_os.c
index 97c98f0a7a43..5909274ddc12 100644
--- a/drivers/gpib/common/gpib_os.c
+++ b/drivers/gpib/common/gpib_os.c
@@ -2219,10 +2219,13 @@ void init_gpib_status_queue(struct gpib_status_queue *device)
device->dropped_byte = 0;
}
-static struct class *gpib_class;
+static const struct class gpib_class = {
+ .name = "gpib_common",
+};
static int __init gpib_common_init_module(void)
{
+ int err;
int i;
pr_info("GPIB core driver\n");
@@ -2231,14 +2234,14 @@ static int __init gpib_common_init_module(void)
pr_err("gpib: can't get major %d\n", GPIB_CODE);
return -EIO;
}
- gpib_class = class_create("gpib_common");
- if (IS_ERR(gpib_class)) {
+ err = class_register(&gpib_class);
+ if (err) {
pr_err("gpib: failed to create gpib class\n");
unregister_chrdev(GPIB_CODE, "gpib");
- return PTR_ERR(gpib_class);
+ return err;
}
for (i = 0; i < GPIB_MAX_NUM_BOARDS; ++i)
- board_array[i].gpib_dev = device_create(gpib_class, NULL,
+ board_array[i].gpib_dev = device_create(&gpib_class, NULL,
MKDEV(GPIB_CODE, i), NULL, "gpib%i", i);
return 0;
@@ -2249,9 +2252,9 @@ static void __exit gpib_common_exit_module(void)
int i;
for (i = 0; i < GPIB_MAX_NUM_BOARDS; ++i)
- device_destroy(gpib_class, MKDEV(GPIB_CODE, i));
+ device_destroy(&gpib_class, MKDEV(GPIB_CODE, i));
- class_destroy(gpib_class);
+ class_unregister(&gpib_class);
unregister_chrdev(GPIB_CODE, "gpib");
}
diff --git a/drivers/gpib/lpvo_usb_gpib/lpvo_usb_gpib.c b/drivers/gpib/lpvo_usb_gpib/lpvo_usb_gpib.c
index 0f9d385bc50b..e6ea9422d6f2 100644
--- a/drivers/gpib/lpvo_usb_gpib/lpvo_usb_gpib.c
+++ b/drivers/gpib/lpvo_usb_gpib/lpvo_usb_gpib.c
@@ -51,10 +51,10 @@ MODULE_DESCRIPTION("GPIB driver for LPVO usb devices");
*
*/
-static const struct usb_device_id skel_table[] = {
+static const struct usb_device_id lpvo_table[] = {
{ } /* Terminating entry */
};
-MODULE_DEVICE_TABLE(usb, skel_table);
+MODULE_DEVICE_TABLE(usb, lpvo_table);
/*
* *** Diagnostics and Debug ***
@@ -182,15 +182,11 @@ static int usb_minors[MAX_DEV]; /* usb minors */
static int assigned_usb_minors; /* mask of filled slots */
static struct mutex minors_lock; /* operations on usb_minors are to be protected */
-/*
- * usb-skeleton prototypes
- */
-
-struct usb_skel;
-static ssize_t skel_do_write(struct usb_skel *, const char *, size_t);
-static ssize_t skel_do_read(struct usb_skel *, char *, size_t);
-static int skel_do_open(struct gpib_board *, int);
-static int skel_do_release(struct gpib_board *);
+struct lpvo;
+static ssize_t lpvo_do_write(struct lpvo *, const char *, size_t);
+static ssize_t lpvo_do_read(struct lpvo *, char *, size_t);
+static int lpvo_do_open(struct gpib_board *, int);
+static int lpvo_do_release(struct gpib_board *);
/*
* usec_diff : take difference in MICROsec between two 'timespec'
@@ -218,7 +214,7 @@ static inline int usec_diff(struct timespec64 *a, struct timespec64 *b)
static int write_loop(void *dev, char *msg, int leng)
{
- return skel_do_write(dev, msg, leng);
+ return lpvo_do_write(dev, msg, leng);
}
/**
@@ -246,7 +242,7 @@ static int send_command(struct gpib_board *board, char *msg, int leng)
if (retval < 0)
return retval;
- nchar = skel_do_read(GPIB_DEV, buffer, 64);
+ nchar = lpvo_do_read(GPIB_DEV, buffer, 64);
if (nchar < 0) {
dev_err(board->gpib_dev, " return from read: %d\n", nchar);
@@ -310,7 +306,7 @@ static int one_char(struct gpib_board *board, struct char_buf *b)
return b->inbuf[b->last - b->nchar--];
}
ktime_get_real_ts64 (&before);
- b->nchar = skel_do_read(GPIB_DEV, b->inbuf, INBUF_SIZE);
+ b->nchar = lpvo_do_read(GPIB_DEV, b->inbuf, INBUF_SIZE);
b->last = b->nchar;
ktime_get_real_ts64 (&after);
@@ -445,12 +441,12 @@ static int usb_gpib_attach(struct gpib_board *board, const struct gpib_board_con
if (!board->private_data)
return -ENOMEM;
- retval = skel_do_open(board, usb_minors[j]);
+ retval = lpvo_do_open(board, usb_minors[j]);
- DIA_LOG(1, "Skel open: %d\n", retval);
+ DIA_LOG(1, "lpvo open: %d\n", retval);
if (retval) {
- dev_err(board->gpib_dev, "skel open failed.\n");
+ dev_err(board->gpib_dev, "lpvo open failed.\n");
kfree(board->private_data);
board->private_data = NULL;
return -ENODEV;
@@ -517,8 +513,8 @@ static void usb_gpib_detach(struct gpib_board *board)
write_loop(GPIB_DEV, USB_GPIB_OFF, strlen(USB_GPIB_OFF));
msleep(100);
DIA_LOG(1, "%s", "GPIB off\n");
- retval = skel_do_release(board);
- DIA_LOG(1, "skel release -> %d\n", retval);
+ retval = lpvo_do_release(board);
+ DIA_LOG(1, "lpvo release -> %d\n", retval);
}
kfree(board->private_data);
board->private_data = NULL;
@@ -772,8 +768,8 @@ static int usb_gpib_read(struct gpib_board *board,
if (retval < 0)
return retval;
- retval = skel_do_read(GPIB_DEV, inbuf, 1);
- retval += skel_do_read(GPIB_DEV, inbuf + 1, 1);
+ retval = lpvo_do_read(GPIB_DEV, inbuf, 1);
+ retval += lpvo_do_read(GPIB_DEV, inbuf + 1, 1);
ktime_get_real_ts64 (&after);
@@ -1197,12 +1193,12 @@ static int write_latency_timer(struct usb_device *udev)
* written by Greg Kroah-Hartman and available in the kernel tree. *
* *
* Functions skel_open() and skel_release() have been rewritten and named *
- * skel_do_open() and skel_do_release() to process the attach and detach *
+ * lpvo_do_open() and lpvo_do_release() to process the attach and detach *
* requests coming from gpib_config. *
* *
- * Functions skel_read() and skel_write() have been split into a *
- * skel_do_read() and skel_do_write(), that cover the kernel stuff of read *
- * and write operations, and the original skel_read() and skel_write(), *
+ * Functions lpvo_read() and lpvo_write() have been split into a *
+ * lpvo_do_read() and lpvo_do_write(), that cover the kernel stuff of read *
+ * and write operations, and the original lpvo_read() and lpvo_write(), *
* that handle communication with user space and call their _do_ companion. *
* *
* Only the _do_ versions are used by the lpvo_usb_gpib driver; other ones *
@@ -1230,7 +1226,7 @@ static int write_latency_timer(struct usb_device *udev)
#include <linux/mutex.h>
/* Get a minor range for your devices from the usb maintainer */
-#define USB_SKEL_MINOR_BASE 192
+#define USB_LPVO_MINOR_BASE 192
/* private defines */
@@ -1245,7 +1241,7 @@ static int write_latency_timer(struct usb_device *udev)
#define USER_DEVICE 1 /* compile for device(s) in user space */
/* Structure to hold all of our device specific stuff */
-struct usb_skel {
+struct lpvo {
struct usb_device *udev; /* the usb device for this device */
struct usb_interface *interface; /* the interface for this device */
struct semaphore limit_sem; /* limiting the number of writes in progress */
@@ -1265,14 +1261,14 @@ struct usb_skel {
wait_queue_head_t bulk_in_wait; /* to wait for an ongoing read */
};
-#define to_skel_dev(d) container_of(d, struct usb_skel, kref)
+#define to_lpvo_dev(d) container_of(d, struct lpvo, kref)
-static struct usb_driver skel_driver;
-static void skel_draw_down(struct usb_skel *dev);
+static struct usb_driver lpvo_driver;
+static void lpvo_draw_down(struct lpvo *dev);
-static void skel_delete(struct kref *kref)
+static void lpvo_delete(struct kref *kref)
{
- struct usb_skel *dev = to_skel_dev(kref);
+ struct lpvo *dev = to_lpvo_dev(kref);
usb_free_urb(dev->bulk_in_urb);
usb_put_dev(dev->udev);
@@ -1281,16 +1277,16 @@ static void skel_delete(struct kref *kref)
}
/*
- * skel_do_open() - to be called by usb_gpib_attach
+ * lpvo_do_open() - to be called by usb_gpib_attach
*/
-static int skel_do_open(struct gpib_board *board, int subminor)
+static int lpvo_do_open(struct gpib_board *board, int subminor)
{
- struct usb_skel *dev;
+ struct lpvo *dev;
struct usb_interface *interface;
int retval = 0;
- interface = usb_find_interface(&skel_driver, subminor);
+ interface = usb_find_interface(&lpvo_driver, subminor);
if (!interface) {
dev_err(board->gpib_dev, "can't find device for minor %d\n", subminor);
retval = -ENODEV;
@@ -1318,12 +1314,12 @@ exit:
}
/*
- * skel_do_release() - to be called by usb_gpib_detach
+ * lpvo_do_release() - to be called by usb_gpib_detach
*/
-static int skel_do_release(struct gpib_board *board)
+static int lpvo_do_release(struct gpib_board *board)
{
- struct usb_skel *dev;
+ struct lpvo *dev;
dev = GPIB_DEV;
if (!dev)
@@ -1336,7 +1332,7 @@ static int skel_do_release(struct gpib_board *board)
mutex_unlock(&dev->io_mutex);
/* decrement the count on our device */
- kref_put(&dev->kref, skel_delete);
+ kref_put(&dev->kref, lpvo_delete);
return 0;
}
@@ -1344,9 +1340,9 @@ static int skel_do_release(struct gpib_board *board)
* read functions
*/
-static void skel_read_bulk_callback(struct urb *urb)
+static void lpvo_read_bulk_callback(struct urb *urb)
{
- struct usb_skel *dev;
+ struct lpvo *dev;
unsigned long flags;
dev = urb->context;
@@ -1370,7 +1366,7 @@ static void skel_read_bulk_callback(struct urb *urb)
wake_up_interruptible(&dev->bulk_in_wait);
}
-static int skel_do_read_io(struct usb_skel *dev, size_t count)
+static int lpvo_do_read_io(struct lpvo *dev, size_t count)
{
int rv;
@@ -1381,7 +1377,7 @@ static int skel_do_read_io(struct usb_skel *dev, size_t count)
dev->bulk_in_endpoint_addr),
dev->bulk_in_buffer,
min(dev->bulk_in_size, count),
- skel_read_bulk_callback,
+ lpvo_read_bulk_callback,
dev);
/* tell everybody to leave the URB alone */
spin_lock_irq(&dev->err_lock);
@@ -1406,10 +1402,10 @@ static int skel_do_read_io(struct usb_skel *dev, size_t count)
}
/*
- * skel_do_read() - read operations from lpvo_usb_gpib
+ * lpvo_do_read() - read operations from lpvo_usb_gpib
*/
-static ssize_t skel_do_read(struct usb_skel *dev, char *buffer, size_t count)
+static ssize_t lpvo_do_read(struct lpvo *dev, char *buffer, size_t count)
{
int rv;
bool ongoing_io;
@@ -1487,7 +1483,7 @@ retry:
* it seems that requests for less than dev->bulk_in_size
* are not accepted
*/
- rv = skel_do_read_io(dev, dev->bulk_in_size);
+ rv = lpvo_do_read_io(dev, dev->bulk_in_size);
if (rv < 0)
goto exit;
else
@@ -1534,10 +1530,10 @@ retry:
* asked for by the lpvo_usb_gpib layer.
*/
// if (available < count)
-// skel_do_read_io(dev, dev->bulk_in_size);
+// lpvo_do_read_io(dev, dev->bulk_in_size);
} else {
/* no data in the buffer */
- rv = skel_do_read_io(dev, dev->bulk_in_size);
+ rv = lpvo_do_read_io(dev, dev->bulk_in_size);
if (rv < 0)
goto exit;
else
@@ -1557,9 +1553,9 @@ exit:
* write functions
*/
-static void skel_write_bulk_callback(struct urb *urb)
+static void lpvo_write_bulk_callback(struct urb *urb)
{
- struct usb_skel *dev;
+ struct lpvo *dev;
unsigned long flags;
dev = urb->context;
@@ -1584,10 +1580,10 @@ static void skel_write_bulk_callback(struct urb *urb)
}
/*
- * skel_do_write() - write operations from lpvo_usb_gpib
+ * lpvo_do_write() - write operations from lpvo_usb_gpib
*/
-static ssize_t skel_do_write(struct usb_skel *dev, const char *buffer, size_t count)
+static ssize_t lpvo_do_write(struct lpvo *dev, const char *buffer, size_t count)
{
int retval = 0;
struct urb *urb = NULL;
@@ -1655,7 +1651,7 @@ static ssize_t skel_do_write(struct usb_skel *dev, const char *buffer, size_t co
/* initialize the urb properly */
usb_fill_bulk_urb(urb, dev->udev,
usb_sndbulkpipe(dev->udev, dev->bulk_out_endpoint_addr),
- buf, writesize, skel_write_bulk_callback, dev);
+ buf, writesize, lpvo_write_bulk_callback, dev);
urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
usb_anchor_urb(urb, &dev->submitted);
@@ -1694,9 +1690,9 @@ exit:
#if USER_DEVICE /* conditional compilation of user space device */
-static int skel_flush(struct file *file, fl_owner_t id)
+static int lpvo_flush(struct file *file, fl_owner_t id)
{
- struct usb_skel *dev;
+ struct lpvo *dev;
int res;
dev = file->private_data;
@@ -1705,7 +1701,7 @@ static int skel_flush(struct file *file, fl_owner_t id)
/* wait for io to stop */
mutex_lock(&dev->io_mutex);
- skel_draw_down(dev);
+ lpvo_draw_down(dev);
/* read out errors, leave subsequent opens a clean slate */
spin_lock_irq(&dev->err_lock);
@@ -1718,16 +1714,16 @@ static int skel_flush(struct file *file, fl_owner_t id)
return res;
}
-static int skel_open(struct inode *inode, struct file *file)
+static int lpvo_open(struct inode *inode, struct file *file)
{
- struct usb_skel *dev;
+ struct lpvo *dev;
struct usb_interface *interface;
int subminor;
int retval = 0;
subminor = iminor(inode);
- interface = usb_find_interface(&skel_driver, subminor);
+ interface = usb_find_interface(&lpvo_driver, subminor);
if (!interface) {
pr_err("can't find device for minor %d\n", subminor);
retval = -ENODEV;
@@ -1754,9 +1750,9 @@ exit:
return retval;
}
-static int skel_release(struct inode *inode, struct file *file)
+static int lpvo_release(struct inode *inode, struct file *file)
{
- struct usb_skel *dev;
+ struct lpvo *dev;
dev = file->private_data;
if (!dev)
@@ -1769,7 +1765,7 @@ static int skel_release(struct inode *inode, struct file *file)
mutex_unlock(&dev->io_mutex);
/* decrement the count on our device */
- kref_put(&dev->kref, skel_delete);
+ kref_put(&dev->kref, lpvo_delete);
return 0;
}
@@ -1777,10 +1773,10 @@ static int skel_release(struct inode *inode, struct file *file)
* user space access to read function
*/
-static ssize_t skel_read(struct file *file, char __user *buffer, size_t count,
+static ssize_t lpvo_read(struct file *file, char __user *buffer, size_t count,
loff_t *ppos)
{
- struct usb_skel *dev;
+ struct lpvo *dev;
char *buf;
ssize_t rv;
@@ -1790,7 +1786,7 @@ static ssize_t skel_read(struct file *file, char __user *buffer, size_t count,
if (!buf)
return -ENOMEM;
- rv = skel_do_read(dev, buf, count);
+ rv = lpvo_do_read(dev, buf, count);
if (rv > 0) {
if (copy_to_user(buffer, buf, rv)) {
@@ -1806,10 +1802,10 @@ static ssize_t skel_read(struct file *file, char __user *buffer, size_t count,
* user space access to write function
*/
-static ssize_t skel_write(struct file *file, const char __user *user_buffer,
+static ssize_t lpvo_write(struct file *file, const char __user *user_buffer,
size_t count, loff_t *ppos)
{
- struct usb_skel *dev;
+ struct lpvo *dev;
char *buf;
ssize_t rv;
@@ -1824,20 +1820,20 @@ static ssize_t skel_write(struct file *file, const char __user *user_buffer,
return -EFAULT;
}
- rv = skel_do_write(dev, buf, count);
+ rv = lpvo_do_write(dev, buf, count);
kfree(buf);
return rv;
}
#endif
-static const struct file_operations skel_fops = {
+static const struct file_operations lpvo_fops = {
.owner = THIS_MODULE,
#if USER_DEVICE
- .read = skel_read,
- .write = skel_write,
- .open = skel_open,
- .release = skel_release,
- .flush = skel_flush,
+ .read = lpvo_read,
+ .write = lpvo_write,
+ .open = lpvo_open,
+ .release = lpvo_release,
+ .flush = lpvo_flush,
.llseek = noop_llseek,
#endif
};
@@ -1847,17 +1843,17 @@ static const struct file_operations skel_fops = {
* and to have the device registered with the driver core
*/
#if USER_DEVICE
-static struct usb_class_driver skel_class = {
+static struct usb_class_driver lpvo_class = {
.name = "lpvo_raw%d",
- .fops = &skel_fops,
- .minor_base = USB_SKEL_MINOR_BASE,
+ .fops = &lpvo_fops,
+ .minor_base = USB_LPVO_MINOR_BASE,
};
#endif
-static int skel_probe(struct usb_interface *interface,
+static int lpvo_probe(struct usb_interface *interface,
const struct usb_device_id *id)
{
- struct usb_skel *dev;
+ struct lpvo *dev;
struct usb_endpoint_descriptor *bulk_in, *bulk_out;
int retval;
char *device_path;
@@ -1916,7 +1912,7 @@ static int skel_probe(struct usb_interface *interface,
#if USER_DEVICE
/* we can register the device now, as it is ready */
- retval = usb_register_dev(interface, &skel_class);
+ retval = usb_register_dev(interface, &lpvo_class);
if (retval) {
/* something prevented us from registering this driver */
dev_err(&interface->dev,
@@ -1934,14 +1930,14 @@ static int skel_probe(struct usb_interface *interface,
error:
/* this frees allocated memory */
- kref_put(&dev->kref, skel_delete);
+ kref_put(&dev->kref, lpvo_delete);
return retval;
}
-static void skel_disconnect(struct usb_interface *interface)
+static void lpvo_disconnect(struct usb_interface *interface)
{
- struct usb_skel *dev;
+ struct lpvo *dev;
int minor = interface->minor;
usb_gpib_exit_module(minor); /* first, disactivate the lpvo */
@@ -1951,7 +1947,7 @@ static void skel_disconnect(struct usb_interface *interface)
#if USER_DEVICE
/* give back our minor */
- usb_deregister_dev(interface, &skel_class);
+ usb_deregister_dev(interface, &lpvo_class);
#endif
/* prevent more I/O from starting */
@@ -1962,10 +1958,10 @@ static void skel_disconnect(struct usb_interface *interface)
usb_kill_anchored_urbs(&dev->submitted);
/* decrement our usage count */
- kref_put(&dev->kref, skel_delete);
+ kref_put(&dev->kref, lpvo_delete);
}
-static void skel_draw_down(struct usb_skel *dev)
+static void lpvo_draw_down(struct lpvo *dev)
{
int time;
@@ -1975,34 +1971,34 @@ static void skel_draw_down(struct usb_skel *dev)
usb_kill_urb(dev->bulk_in_urb);
}
-static int skel_suspend(struct usb_interface *intf, pm_message_t message)
+static int lpvo_suspend(struct usb_interface *intf, pm_message_t message)
{
- struct usb_skel *dev = usb_get_intfdata(intf);
+ struct lpvo *dev = usb_get_intfdata(intf);
if (!dev)
return 0;
- skel_draw_down(dev);
+ lpvo_draw_down(dev);
return 0;
}
-static int skel_resume(struct usb_interface *intf)
+static int lpvo_resume(struct usb_interface *intf)
{
return 0;
}
-static int skel_pre_reset(struct usb_interface *intf)
+static int lpvo_pre_reset(struct usb_interface *intf)
{
- struct usb_skel *dev = usb_get_intfdata(intf);
+ struct lpvo *dev = usb_get_intfdata(intf);
mutex_lock(&dev->io_mutex);
- skel_draw_down(dev);
+ lpvo_draw_down(dev);
return 0;
}
-static int skel_post_reset(struct usb_interface *intf)
+static int lpvo_post_reset(struct usb_interface *intf)
{
- struct usb_skel *dev = usb_get_intfdata(intf);
+ struct lpvo *dev = usb_get_intfdata(intf);
/* we are sure no URBs are active - no locking needed */
dev->errors = -EPIPE;
@@ -2011,16 +2007,16 @@ static int skel_post_reset(struct usb_interface *intf)
return 0;
}
-static struct usb_driver skel_driver = {
+static struct usb_driver lpvo_driver = {
.name = NAME,
- .probe = skel_probe,
- .disconnect = skel_disconnect,
- .suspend = skel_suspend,
- .resume = skel_resume,
- .pre_reset = skel_pre_reset,
- .post_reset = skel_post_reset,
- .id_table = skel_table,
+ .probe = lpvo_probe,
+ .disconnect = lpvo_disconnect,
+ .suspend = lpvo_suspend,
+ .resume = lpvo_resume,
+ .pre_reset = lpvo_pre_reset,
+ .post_reset = lpvo_post_reset,
+ .id_table = lpvo_table,
.supports_autosuspend = 1,
};
-module_usb_driver(skel_driver);
+module_usb_driver(lpvo_driver);
diff --git a/drivers/gpib/nec7210/nec7210.c b/drivers/gpib/nec7210/nec7210.c
index bbf39367f5e4..f15d38dfa4cc 100644
--- a/drivers/gpib/nec7210/nec7210.c
+++ b/drivers/gpib/nec7210/nec7210.c
@@ -1107,15 +1107,3 @@ void nec7210_locking_iomem_write_byte(struct nec7210_priv *priv, u8 data,
spin_unlock_irqrestore(&priv->register_page_lock, flags);
}
EXPORT_SYMBOL(nec7210_locking_iomem_write_byte);
-
-static int __init nec7210_init_module(void)
-{
- return 0;
-}
-
-static void __exit nec7210_exit_module(void)
-{
-}
-
-module_init(nec7210_init_module);
-module_exit(nec7210_exit_module);
diff --git a/drivers/gpib/ni_usb/ni_usb_gpib.c b/drivers/gpib/ni_usb/ni_usb_gpib.c
index a24cd6521362..0bbc13ecebf9 100644
--- a/drivers/gpib/ni_usb/ni_usb_gpib.c
+++ b/drivers/gpib/ni_usb/ni_usb_gpib.c
@@ -2431,7 +2431,6 @@ static int ni_usb_driver_probe(struct usb_interface *interface, const struct usb
static const int path_length = 1024;
mutex_lock(&ni_usb_hotplug_lock);
- usb_get_dev(usb_dev);
for (i = 0; i < MAX_NUM_NI_USB_INTERFACES; i++) {
if (!ni_usb_driver_interfaces[i]) {
ni_usb_driver_interfaces[i] = interface;
@@ -2440,14 +2439,12 @@ static int ni_usb_driver_probe(struct usb_interface *interface, const struct usb
}
}
if (i == MAX_NUM_NI_USB_INTERFACES) {
- usb_put_dev(usb_dev);
mutex_unlock(&ni_usb_hotplug_lock);
dev_err(&usb_dev->dev, "ni_usb_driver_interfaces[] full\n");
return -1;
}
path = kmalloc(path_length, GFP_KERNEL);
if (!path) {
- usb_put_dev(usb_dev);
mutex_unlock(&ni_usb_hotplug_lock);
return -ENOMEM;
}
@@ -2488,7 +2485,6 @@ static void ni_usb_driver_disconnect(struct usb_interface *interface)
}
if (i == MAX_NUM_NI_USB_INTERFACES)
dev_err(&usb_dev->dev, "unable to find interface bug?\n");
- usb_put_dev(usb_dev);
mutex_unlock(&ni_usb_hotplug_lock);
}
diff --git a/drivers/gpib/tms9914/tms9914.c b/drivers/gpib/tms9914/tms9914.c
index 72a11596a35e..1411297e6217 100644
--- a/drivers/gpib/tms9914/tms9914.c
+++ b/drivers/gpib/tms9914/tms9914.c
@@ -899,16 +899,3 @@ void tms9914_iomem_write_byte(struct tms9914_priv *priv, u8 data, unsigned int r
udelay(1);
}
EXPORT_SYMBOL_GPL(tms9914_iomem_write_byte);
-
-static int __init tms9914_init_module(void)
-{
- return 0;
-}
-
-static void __exit tms9914_exit_module(void)
-{
-}
-
-module_init(tms9914_init_module);
-module_exit(tms9914_exit_module);
-
diff --git a/drivers/greybus/es2.c b/drivers/greybus/es2.c
index 6ae0ac828afa..75b889fa21b4 100644
--- a/drivers/greybus/es2.c
+++ b/drivers/greybus/es2.c
@@ -772,7 +772,6 @@ static int check_urb_status(struct urb *urb)
static void es2_destroy(struct es2_ap_dev *es2)
{
- struct usb_device *udev;
struct urb *urb;
int i;
@@ -804,10 +803,7 @@ static void es2_destroy(struct es2_ap_dev *es2)
gb_hd_cport_release_reserved(es2->hd, ES2_CPORT_CDSI1);
gb_hd_cport_release_reserved(es2->hd, ES2_CPORT_CDSI0);
- udev = es2->usb_dev;
gb_hd_put(es2->hd);
-
- usb_put_dev(udev);
}
static void cport_in_callback(struct urb *urb)
@@ -1257,11 +1253,10 @@ static int ap_probe(struct usb_interface *interface,
bool bulk_in_found = false;
bool arpc_in_found = false;
- udev = usb_get_dev(interface_to_usbdev(interface));
+ udev = interface_to_usbdev(interface);
num_cports = apb_get_cport_count(udev);
if (num_cports < 0) {
- usb_put_dev(udev);
dev_err(&udev->dev, "Cannot retrieve CPort count: %d\n",
num_cports);
return num_cports;
@@ -1269,10 +1264,8 @@ static int ap_probe(struct usb_interface *interface,
hd = gb_hd_create(&es2_driver, &udev->dev, ES2_GBUF_MSG_SIZE_MAX,
num_cports);
- if (IS_ERR(hd)) {
- usb_put_dev(udev);
+ if (IS_ERR(hd))
return PTR_ERR(hd);
- }
es2 = hd_to_es2(hd);
es2->hd = hd;
diff --git a/drivers/greybus/gb-beagleplay.c b/drivers/greybus/gb-beagleplay.c
index 87186f891a6a..244966d56c9b 100644
--- a/drivers/greybus/gb-beagleplay.c
+++ b/drivers/greybus/gb-beagleplay.c
@@ -242,30 +242,26 @@ static void hdlc_write(struct gb_beagleplay *bg)
}
/**
- * hdlc_append() - Queue HDLC data for sending.
+ * hdlc_append() - Queue a single HDLC byte for sending.
* @bg: beagleplay greybus driver
* @value: hdlc byte to transmit
*
- * Assumes that producer lock as been acquired.
+ * Caller must hold tx_producer_lock and must have ensured sufficient
+ * space in the circular buffer before calling (see hdlc_tx_frames()).
*/
static void hdlc_append(struct gb_beagleplay *bg, u8 value)
{
- int tail, head = bg->tx_circ_buf.head;
+ int head = bg->tx_circ_buf.head;
+ int tail = READ_ONCE(bg->tx_circ_buf.tail);
- while (true) {
- tail = READ_ONCE(bg->tx_circ_buf.tail);
-
- if (CIRC_SPACE(head, tail, TX_CIRC_BUF_SIZE) >= 1) {
- bg->tx_circ_buf.buf[head] = value;
+ lockdep_assert_held(&bg->tx_producer_lock);
+ if (WARN_ON_ONCE(CIRC_SPACE(head, tail, TX_CIRC_BUF_SIZE) < 1))
+ return;
- /* Finish producing HDLC byte */
- smp_store_release(&bg->tx_circ_buf.head,
- (head + 1) & (TX_CIRC_BUF_SIZE - 1));
- return;
- }
- dev_warn(&bg->sd->dev, "Tx circ buf full");
- usleep_range(3000, 5000);
- }
+ bg->tx_circ_buf.buf[head] = value;
+ /* Ensure buffer write is visible before advancing head. */
+ smp_store_release(&bg->tx_circ_buf.head,
+ (head + 1) & (TX_CIRC_BUF_SIZE - 1));
}
static void hdlc_append_escaped(struct gb_beagleplay *bg, u8 value)
@@ -313,13 +309,94 @@ static void hdlc_transmit(struct work_struct *work)
spin_unlock_bh(&bg->tx_consumer_lock);
}
-static void hdlc_tx_frames(struct gb_beagleplay *bg, u8 address, u8 control,
+/**
+ * hdlc_encoded_length() - Calculate worst-case encoded length of an HDLC frame.
+ * @payloads: array of payload buffers
+ * @count: number of payloads
+ *
+ * Every data byte may need HDLC escaping (doubling its size).
+ * Frame layout: flag(1) + address(1-2) + control(1-2) + payload + CRC(2-4) + flag(1).
+ *
+ * Returns the maximum number of bytes needed in the circular buffer.
+ */
+static size_t hdlc_encoded_length(const struct hdlc_payload payloads[],
+ size_t count)
+{
+ size_t i, payload_len = 0;
+
+ for (i = 0; i < count; i++)
+ payload_len += payloads[i].len;
+
+ /*
+ * Worst case: every data byte needs escaping (doubles in size).
+ * data bytes = address(1) + control(1) + payload + crc(2)
+ * framing = opening flag(1) + closing flag(1)
+ */
+ return 2 + (1 + 1 + payload_len + 2) * 2;
+}
+
+#define HDLC_TX_BUF_WAIT_RETRIES 500
+#define HDLC_TX_BUF_WAIT_US_MIN 3000
+#define HDLC_TX_BUF_WAIT_US_MAX 5000
+
+/**
+ * hdlc_tx_frames() - Encode and queue an HDLC frame for transmission.
+ * @bg: beagleplay greybus driver
+ * @address: HDLC address field
+ * @control: HDLC control field
+ * @payloads: array of payload buffers
+ * @count: number of payloads
+ *
+ * Sleeps outside the spinlock until enough circular-buffer space is
+ * available, then verifies space under the lock and writes the entire
+ * frame atomically. Either a complete frame is enqueued or nothing is
+ * written, avoiding both sleeping in atomic context and partial frames.
+ *
+ * Returns 0 on success, -EAGAIN if the buffer remains full after retries.
+ */
+static int hdlc_tx_frames(struct gb_beagleplay *bg, u8 address, u8 control,
const struct hdlc_payload payloads[], size_t count)
{
+ size_t needed = hdlc_encoded_length(payloads, count);
+ int retries = HDLC_TX_BUF_WAIT_RETRIES;
size_t i;
+ int head, tail;
+
+ /* Wait outside the lock for sufficient buffer space. */
+ while (retries--) {
+ /* Pairs with smp_store_release() in hdlc_append(). */
+ head = smp_load_acquire(&bg->tx_circ_buf.head);
+ tail = READ_ONCE(bg->tx_circ_buf.tail);
+
+ if (CIRC_SPACE(head, tail, TX_CIRC_BUF_SIZE) >= needed)
+ break;
+
+ /* Kick the consumer and sleep — no lock held. */
+ schedule_work(&bg->tx_work);
+ usleep_range(HDLC_TX_BUF_WAIT_US_MIN, HDLC_TX_BUF_WAIT_US_MAX);
+ }
+
+ if (retries < 0) {
+ dev_warn_ratelimited(&bg->sd->dev, "Tx circ buf full, dropping frame\n");
+ return -EAGAIN;
+ }
spin_lock(&bg->tx_producer_lock);
+ /*
+ * Re-check space under the lock to close the TOCTOU window.
+ * This should be rare since tx_producer_lock serialises all
+ * producers and the consumer only frees space. If it fires,
+ * the caller is expected to handle -EAGAIN (retry or report).
+ */
+ head = bg->tx_circ_buf.head;
+ tail = READ_ONCE(bg->tx_circ_buf.tail);
+ if (unlikely(CIRC_SPACE(head, tail, TX_CIRC_BUF_SIZE) < needed)) {
+ spin_unlock(&bg->tx_producer_lock);
+ dev_warn_ratelimited(&bg->sd->dev, "Tx circ buf space lost, dropping frame\n");
+ return -EAGAIN;
+ }
+
hdlc_append_tx_frame(bg);
hdlc_append_tx_u8(bg, address);
hdlc_append_tx_u8(bg, control);
@@ -333,11 +410,16 @@ static void hdlc_tx_frames(struct gb_beagleplay *bg, u8 address, u8 control,
spin_unlock(&bg->tx_producer_lock);
schedule_work(&bg->tx_work);
+ return 0;
}
static void hdlc_tx_s_frame_ack(struct gb_beagleplay *bg)
{
- hdlc_tx_frames(bg, bg->rx_buffer[0], (bg->rx_buffer[1] >> 1) & 0x7, NULL, 0);
+ int ret;
+
+ ret = hdlc_tx_frames(bg, bg->rx_buffer[0], (bg->rx_buffer[1] >> 1) & 0x7, NULL, 0);
+ if (ret)
+ dev_warn_ratelimited(&bg->sd->dev, "Failed to send HDLC ACK: %d\n", ret);
}
static void hdlc_rx_frame(struct gb_beagleplay *bg)
@@ -535,6 +617,19 @@ static size_t cc1352_bootloader_rx(struct gb_beagleplay *bg, const u8 *data,
int ret;
size_t off = 0;
+ if (count > sizeof(bg->rx_buffer) - bg->rx_buffer_len) {
+ dev_err_ratelimited(&bg->sd->dev, "Bootloader RX buffer overflow");
+ bg->rx_buffer_len = 0;
+ return count;
+ }
+
+ if (count > sizeof(bg->rx_buffer) - bg->rx_buffer_len) {
+ dev_warn(&bg->sd->dev,
+ "dropping oversized bootloader receive chunk");
+ bg->rx_buffer_len = 0;
+ return count;
+ }
+
memcpy(bg->rx_buffer + bg->rx_buffer_len, data, count);
bg->rx_buffer_len += count;
@@ -595,6 +690,7 @@ static int gb_message_send(struct gb_host_device *hd, u16 cport, struct gb_messa
struct gb_beagleplay *bg = dev_get_drvdata(&hd->dev);
struct hdlc_payload payloads[3];
__le16 cport_id = cpu_to_le16(cport);
+ int ret;
dev_dbg(&hd->dev, "Sending greybus message with Operation %u, Type: %X on Cport %u",
msg->header->operation_id, msg->header->type, cport);
@@ -609,7 +705,10 @@ static int gb_message_send(struct gb_host_device *hd, u16 cport, struct gb_messa
payloads[2].buf = msg->payload;
payloads[2].len = msg->payload_size;
- hdlc_tx_frames(bg, ADDRESS_GREYBUS, 0x03, payloads, 3);
+ ret = hdlc_tx_frames(bg, ADDRESS_GREYBUS, 0x03, payloads, 3);
+ if (ret)
+ return ret;
+
greybus_message_sent(bg->gb_hd, msg, 0);
return 0;
@@ -622,20 +721,20 @@ static void gb_message_cancel(struct gb_message *message)
static struct gb_hd_driver gb_hdlc_driver = { .message_send = gb_message_send,
.message_cancel = gb_message_cancel };
-static void gb_beagleplay_start_svc(struct gb_beagleplay *bg)
+static int gb_beagleplay_start_svc(struct gb_beagleplay *bg)
{
const u8 command = CONTROL_SVC_START;
const struct hdlc_payload payload = { .len = 1, .buf = (void *)&command };
- hdlc_tx_frames(bg, ADDRESS_CONTROL, 0x03, &payload, 1);
+ return hdlc_tx_frames(bg, ADDRESS_CONTROL, 0x03, &payload, 1);
}
-static void gb_beagleplay_stop_svc(struct gb_beagleplay *bg)
+static int gb_beagleplay_stop_svc(struct gb_beagleplay *bg)
{
const u8 command = CONTROL_SVC_STOP;
const struct hdlc_payload payload = { .len = 1, .buf = (void *)&command };
- hdlc_tx_frames(bg, ADDRESS_CONTROL, 0x03, &payload, 1);
+ return hdlc_tx_frames(bg, ADDRESS_CONTROL, 0x03, &payload, 1);
}
static int cc1352_bootloader_wait_for_ack(struct gb_beagleplay *bg)
@@ -873,7 +972,9 @@ static enum fw_upload_err cc1352_prepare(struct fw_upload *fw_upload,
gb_greybus_deinit(bg);
msleep(5 * MSEC_PER_SEC);
- gb_beagleplay_stop_svc(bg);
+ /* Best effort — device is entering bootloader mode regardless. */
+ if (gb_beagleplay_stop_svc(bg))
+ dev_warn(&bg->sd->dev, "Failed to send SVC stop before flashing\n");
msleep(200);
flush_work(&bg->tx_work);
@@ -915,7 +1016,9 @@ static enum fw_upload_err cc1352_prepare(struct fw_upload *fw_upload,
if (gb_greybus_init(bg) < 0)
return dev_err_probe(&bg->sd->dev, FW_UPLOAD_ERR_RW_ERROR,
"Failed to initialize greybus");
- gb_beagleplay_start_svc(bg);
+ if (gb_beagleplay_start_svc(bg))
+ return dev_err_probe(&bg->sd->dev, FW_UPLOAD_ERR_RW_ERROR,
+ "Failed to restart SVC after skip");
return FW_UPLOAD_ERR_FW_INVALID;
}
@@ -996,7 +1099,9 @@ static enum fw_upload_err cc1352_poll_complete(struct fw_upload *fw_upload)
return dev_err_probe(&bg->sd->dev, FW_UPLOAD_ERR_RW_ERROR,
"Failed to initialize greybus");
- gb_beagleplay_start_svc(bg);
+ if (gb_beagleplay_start_svc(bg) < 0)
+ return dev_err_probe(&bg->sd->dev, FW_UPLOAD_ERR_RW_ERROR,
+ "Failed to start SVC");
return FW_UPLOAD_ERR_NONE;
}
@@ -1107,10 +1212,14 @@ static int gb_beagleplay_probe(struct serdev_device *serdev)
if (ret)
goto free_fw;
- gb_beagleplay_start_svc(bg);
+ ret = gb_beagleplay_start_svc(bg);
+ if (ret)
+ goto free_greybus;
return 0;
+free_greybus:
+ gb_greybus_deinit(bg);
free_fw:
gb_fw_deinit(bg);
free_hdlc:
@@ -1126,6 +1235,7 @@ static void gb_beagleplay_remove(struct serdev_device *serdev)
gb_fw_deinit(bg);
gb_greybus_deinit(bg);
+ /* Best effort — device is being removed. */
gb_beagleplay_stop_svc(bg);
hdlc_deinit(bg);
gb_serdev_deinit(bg);
diff --git a/drivers/greybus/svc.c b/drivers/greybus/svc.c
index 1b854f53f21e..490577731a19 100644
--- a/drivers/greybus/svc.c
+++ b/drivers/greybus/svc.c
@@ -775,10 +775,9 @@ static void gb_svc_pwrmon_debugfs_init(struct gb_svc *svc)
if (!rail_count || rail_count > GB_SVC_PWRMON_MAX_RAIL_COUNT)
goto err_pwrmon_debugfs;
- bufsize = sizeof(*rail_names) +
- GB_SVC_PWRMON_RAIL_NAME_BUFSIZE * rail_count;
+ bufsize = struct_size(rail_names, name, rail_count);
- rail_names = kzalloc(bufsize, GFP_KERNEL);
+ rail_names = kzalloc_flex(*rail_names, name, rail_count);
if (!rail_names)
goto err_pwrmon_debugfs;
diff --git a/drivers/hwtracing/coresight/coresight-catu.c b/drivers/hwtracing/coresight/coresight-catu.c
index dfd035852b12..ce71dcddfca2 100644
--- a/drivers/hwtracing/coresight/coresight-catu.c
+++ b/drivers/hwtracing/coresight/coresight-catu.c
@@ -30,8 +30,6 @@
#define catu_dbg(x, ...) do {} while (0)
#endif
-DEFINE_CORESIGHT_DEVLIST(catu_devs, "catu");
-
struct catu_etr_buf {
struct tmc_sg_table *catu_table;
dma_addr_t sladdr;
@@ -530,7 +528,7 @@ static int __catu_probe(struct device *dev, struct resource *res)
if (ret)
return ret;
- catu_desc.name = coresight_alloc_device_name(&catu_devs, dev);
+ catu_desc.name = coresight_alloc_device_name("catu", dev);
if (!catu_desc.name)
return -ENOMEM;
diff --git a/drivers/hwtracing/coresight/coresight-core.c b/drivers/hwtracing/coresight/coresight-core.c
index 80e26396ad0a..46f247f73cf6 100644
--- a/drivers/hwtracing/coresight/coresight-core.c
+++ b/drivers/hwtracing/coresight/coresight-core.c
@@ -53,6 +53,9 @@ struct coresight_node {
const u32 coresight_barrier_pkt[4] = {0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff};
EXPORT_SYMBOL_GPL(coresight_barrier_pkt);
+/* List maintains the device index */
+static LIST_HEAD(coresight_dev_idx_list);
+
static const struct cti_assoc_op *cti_assoc_ops;
void coresight_set_cti_ops(const struct cti_assoc_op *cti_op)
@@ -1149,7 +1152,6 @@ static int coresight_clear_filter_source(struct device *dev, void *data)
return 0;
}
-/* coresight_remove_conns - Remove other device's references to this device */
static void coresight_remove_conns(struct coresight_device *csdev)
{
int i, j;
@@ -1159,10 +1161,6 @@ static void coresight_remove_conns(struct coresight_device *csdev)
bus_for_each_dev(&coresight_bustype, NULL, csdev,
coresight_clear_filter_source);
- /*
- * Remove the input connection references from the destination device
- * for each output connection.
- */
for (i = 0; i < csdev->pdata->nr_outconns; i++) {
conn = csdev->pdata->out_conns[i];
if (conn->filter_src_fwnode) {
@@ -1173,6 +1171,13 @@ static void coresight_remove_conns(struct coresight_device *csdev)
if (!conn->dest_dev)
continue;
+ /* Remove sysfs links for the output connection */
+ coresight_remove_links(csdev, conn);
+
+ /*
+ * Remove the input connection references from the destination
+ * device for each output connection.
+ */
for (j = 0; j < conn->dest_dev->pdata->nr_inconns; ++j)
if (conn->dest_dev->pdata->in_conns[j] == conn) {
conn->dest_dev->pdata->in_conns[j] = NULL;
@@ -1195,6 +1200,8 @@ static void coresight_remove_conns(struct coresight_device *csdev)
coresight_remove_links(conn->src_dev, conn);
conn->dest_dev = NULL;
}
+
+ coresight_remove_conns_sysfs_group(csdev);
}
/**
@@ -1295,17 +1302,13 @@ void coresight_write64(struct coresight_device *csdev, u64 val, u32 offset)
* coresight_release_platform_data: Release references to the devices connected
* to the output port of this device.
*/
-void coresight_release_platform_data(struct coresight_device *csdev,
- struct device *dev,
+void coresight_release_platform_data(struct device *dev,
struct coresight_platform_data *pdata)
{
int i;
struct coresight_connection **conns = pdata->out_conns;
for (i = 0; i < pdata->nr_outconns; i++) {
- /* If we have made the links, remove them now */
- if (csdev && conns[i]->dest_dev)
- coresight_remove_links(csdev, conns[i]);
/*
* Drop the refcount and clear the handle as this device
* is going away
@@ -1317,8 +1320,6 @@ void coresight_release_platform_data(struct coresight_device *csdev,
devm_kfree(dev, pdata->out_conns);
devm_kfree(dev, pdata->in_conns);
devm_kfree(dev, pdata);
- if (csdev)
- coresight_remove_conns_sysfs_group(csdev);
}
struct coresight_device *coresight_register(struct coresight_desc *desc)
@@ -1346,12 +1347,6 @@ struct coresight_device *coresight_register(struct coresight_desc *desc)
csdev->dev.parent = desc->dev;
csdev->dev.release = coresight_device_release;
csdev->dev.bus = &coresight_bustype;
- /*
- * Hold the reference to our parent device. This will be
- * dropped only in coresight_device_release().
- */
- csdev->dev.fwnode = fwnode_handle_get(dev_fwnode(desc->dev));
- dev_set_name(&csdev->dev, "%s", desc->name);
if (csdev->type == CORESIGHT_DEV_TYPE_SINK ||
csdev->type == CORESIGHT_DEV_TYPE_LINKSINK) {
@@ -1363,6 +1358,14 @@ struct coresight_device *coresight_register(struct coresight_desc *desc)
goto err_out;
}
}
+
+ /*
+ * Hold the reference to our parent device. This will be
+ * dropped only in coresight_device_release().
+ */
+ csdev->dev.fwnode = fwnode_handle_get(dev_fwnode(desc->dev));
+ dev_set_name(&csdev->dev, "%s", desc->name);
+
/*
* Make sure the device registration and the connection fixup
* are synchronised, so that we don't see uninitialised devices
@@ -1380,37 +1383,30 @@ struct coresight_device *coresight_register(struct coresight_desc *desc)
goto out_unlock;
}
- if ((csdev->type == CORESIGHT_DEV_TYPE_SINK ||
- csdev->type == CORESIGHT_DEV_TYPE_LINKSINK) &&
- sink_ops(csdev)->alloc_buffer) {
- ret = etm_perf_add_symlink_sink(csdev);
-
- if (ret) {
- device_unregister(&csdev->dev);
- /*
- * As with the above, all resources are free'd
- * explicitly via coresight_device_release() triggered
- * from put_device(), which is in turn called from
- * function device_unregister().
- */
- goto out_unlock;
- }
- }
/* Device is now registered */
registered = true;
+ ret = etm_perf_add_symlink_sink(csdev);
+ if (ret && ret != -EOPNOTSUPP)
+ goto out_unlock;
+
ret = coresight_create_conns_sysfs_group(csdev);
- if (!ret)
- ret = coresight_fixup_orphan_conns(csdev);
+ if (ret)
+ goto out_unlock;
+
+ ret = coresight_fixup_orphan_conns(csdev);
+ if (ret)
+ goto out_unlock;
+
+ mutex_unlock(&coresight_mutex);
+
+ if (cti_assoc_ops && cti_assoc_ops->add)
+ cti_assoc_ops->add(csdev);
+
+ return csdev;
out_unlock:
mutex_unlock(&coresight_mutex);
- /* Success */
- if (!ret) {
- if (cti_assoc_ops && cti_assoc_ops->add)
- cti_assoc_ops->add(csdev);
- return csdev;
- }
/* Unregister the device if needed */
if (registered) {
@@ -1419,41 +1415,76 @@ out_unlock:
}
err_out:
- /* Cleanup the connection information */
- coresight_release_platform_data(NULL, desc->dev, desc->pdata);
+ coresight_release_platform_data(desc->dev, desc->pdata);
return ERR_PTR(ret);
}
EXPORT_SYMBOL_GPL(coresight_register);
void coresight_unregister(struct coresight_device *csdev)
{
- etm_perf_del_symlink_sink(csdev);
/* Remove references of that device in the topology */
if (cti_assoc_ops && cti_assoc_ops->remove)
cti_assoc_ops->remove(csdev);
+
+ mutex_lock(&coresight_mutex);
+ etm_perf_del_symlink_sink(csdev);
coresight_remove_conns(csdev);
coresight_clear_default_sink(csdev);
- coresight_release_platform_data(csdev, csdev->dev.parent, csdev->pdata);
+ coresight_release_platform_data(csdev->dev.parent, csdev->pdata);
device_unregister(&csdev->dev);
+ mutex_unlock(&coresight_mutex);
}
EXPORT_SYMBOL_GPL(coresight_unregister);
+static struct coresight_dev_list *
+coresight_allocate_device_list(const char *prefix)
+{
+ struct coresight_dev_list *list;
+
+ /* Check if have already allocated */
+ list_for_each_entry(list, &coresight_dev_idx_list, node) {
+ if (!strcmp(list->pfx, prefix))
+ return list;
+ }
-/*
- * coresight_search_device_idx - Search the fwnode handle of a device
- * in the given dev_idx list. Must be called with the coresight_mutex held.
- *
- * Returns the index of the entry, when found. Otherwise, -ENOENT.
- */
-static int coresight_search_device_idx(struct coresight_dev_list *dict,
- struct fwnode_handle *fwnode)
+ list = kzalloc(sizeof(*list), GFP_KERNEL);
+ if (!list)
+ return NULL;
+
+ list->pfx = kstrdup(prefix, GFP_KERNEL);
+ if (!list->pfx) {
+ kfree(list);
+ return NULL;
+ }
+
+ list_add(&list->node, &coresight_dev_idx_list);
+ return list;
+}
+
+static int coresight_allocate_device_idx(struct coresight_dev_list *list,
+ struct device *dev)
{
- int i;
+ struct fwnode_handle **fwnode_list;
+ struct fwnode_handle *fwnode = dev_fwnode(dev);
+ int idx;
+
+ for (idx = 0; idx < list->nr_idx; idx++)
+ if (list->fwnode_list[idx] == fwnode)
+ return idx;
- for (i = 0; i < dict->nr_idx; i++)
- if (dict->fwnode_list[i] == fwnode)
- return i;
- return -ENOENT;
+ /* Make space for the new entry */
+ idx = list->nr_idx;
+ fwnode_list = krealloc_array(list->fwnode_list,
+ idx + 1, sizeof(*list->fwnode_list),
+ GFP_KERNEL);
+ if (!fwnode_list)
+ return -ENOMEM;
+
+ fwnode_list[idx] = fwnode;
+ list->fwnode_list = fwnode_list;
+ list->nr_idx = idx + 1;
+
+ return idx;
}
static bool coresight_compare_type(enum coresight_dev_type type_a,
@@ -1527,45 +1558,63 @@ bool coresight_loses_context_with_cpu(struct device *dev)
EXPORT_SYMBOL_GPL(coresight_loses_context_with_cpu);
/*
- * coresight_alloc_device_name - Get an index for a given device in the
- * device index list specific to a driver. An index is allocated for a
- * device and is tracked with the fwnode_handle to prevent allocating
+ * coresight_alloc_device_name - Get an index for a given device in the list
+ * specific to a driver (presented by the prefix string). An index is allocated
+ * for a device and is tracked with the fwnode_handle to prevent allocating
* duplicate indices for the same device (e.g, if we defer probing of
* a device due to dependencies), in case the index is requested again.
*/
-char *coresight_alloc_device_name(struct coresight_dev_list *dict,
- struct device *dev)
+char *coresight_alloc_device_name(const char *prefix, struct device *dev)
{
- int idx;
+ struct coresight_dev_list *list;
char *name = NULL;
- struct fwnode_handle **list;
+ int idx;
mutex_lock(&coresight_mutex);
- idx = coresight_search_device_idx(dict, dev_fwnode(dev));
- if (idx < 0) {
- /* Make space for the new entry */
- idx = dict->nr_idx;
- list = krealloc_array(dict->fwnode_list,
- idx + 1, sizeof(*dict->fwnode_list),
- GFP_KERNEL);
- if (ZERO_OR_NULL_PTR(list)) {
- idx = -ENOMEM;
- goto done;
- }
+ list = coresight_allocate_device_list(prefix);
+ if (!list)
+ goto done;
- list[idx] = dev_fwnode(dev);
- dict->fwnode_list = list;
- dict->nr_idx = idx + 1;
- }
+ idx = coresight_allocate_device_idx(list, dev);
+
+ /*
+ * If index allocation fails, the device list is not released here;
+ * it is instead freed later by coresight_release_device_list() when
+ * the coresight_core module is unloaded.
+ */
+ if (idx < 0)
+ goto done;
- name = devm_kasprintf(dev, GFP_KERNEL, "%s%d", dict->pfx, idx);
+ name = devm_kasprintf(dev, GFP_KERNEL, "%s%d", list->pfx, idx);
done:
mutex_unlock(&coresight_mutex);
return name;
}
EXPORT_SYMBOL_GPL(coresight_alloc_device_name);
+static void coresight_release_device_list(void)
+{
+ struct coresight_dev_list *list, *next;
+ int i;
+
+ /*
+ * Here is no need to take coresight_mutex; this is during core module
+ * unloading, no race condition with other modules.
+ */
+
+ list_for_each_entry_safe(list, next, &coresight_dev_idx_list, node) {
+ for (i = 0; i < list->nr_idx; i++)
+ list->fwnode_list[i] = NULL;
+ list->nr_idx = 0;
+ list_del(&list->node);
+
+ kfree(list->pfx);
+ kfree(list->fwnode_list);
+ kfree(list);
+ }
+}
+
const struct bus_type coresight_bustype = {
.name = "coresight",
};
@@ -1639,6 +1688,7 @@ static void __exit coresight_exit(void)
&coresight_notifier);
etm_perf_exit();
bus_unregister(&coresight_bustype);
+ coresight_release_device_list();
}
module_init(coresight_init);
diff --git a/drivers/hwtracing/coresight/coresight-ctcu-core.c b/drivers/hwtracing/coresight/coresight-ctcu-core.c
index abed15eb72b4..9043cad42f01 100644
--- a/drivers/hwtracing/coresight/coresight-ctcu-core.c
+++ b/drivers/hwtracing/coresight/coresight-ctcu-core.c
@@ -19,8 +19,6 @@
#include "coresight-ctcu.h"
#include "coresight-priv.h"
-DEFINE_CORESIGHT_DEVLIST(ctcu_devs, "ctcu");
-
#define ctcu_writel(drvdata, val, offset) __raw_writel((val), drvdata->base + offset)
#define ctcu_readl(drvdata, offset) __raw_readl(drvdata->base + offset)
@@ -187,7 +185,7 @@ static int ctcu_probe(struct platform_device *pdev)
void __iomem *base;
int i, ret;
- desc.name = coresight_alloc_device_name(&ctcu_devs, dev);
+ desc.name = coresight_alloc_device_name("ctcu", dev);
if (!desc.name)
return -ENOMEM;
@@ -228,6 +226,7 @@ static int ctcu_probe(struct platform_device *pdev)
desc.dev = dev;
desc.ops = &ctcu_ops;
desc.access = CSDEV_ACCESS_IOMEM(base);
+ raw_spin_lock_init(&drvdata->spin_lock);
drvdata->csdev = coresight_register(&desc);
if (IS_ERR(drvdata->csdev))
diff --git a/drivers/hwtracing/coresight/coresight-cti-core.c b/drivers/hwtracing/coresight/coresight-cti-core.c
index bfbc365bb2ef..2f4c9362709a 100644
--- a/drivers/hwtracing/coresight/coresight-cti-core.c
+++ b/drivers/hwtracing/coresight/coresight-cti-core.c
@@ -42,21 +42,6 @@ static DEFINE_MUTEX(ect_mutex);
#define csdev_to_cti_drvdata(csdev) \
dev_get_drvdata(csdev->dev.parent)
-/* power management handling */
-static int nr_cti_cpu;
-
-/* quick lookup list for CPU bound CTIs when power handling */
-static struct cti_drvdata *cti_cpu_drvdata[NR_CPUS];
-
-/*
- * CTI naming. CTI bound to cores will have the name cti_cpu<N> where
- * N is the CPU ID. System CTIs will have the name cti_sys<I> where I
- * is an index allocated by order of discovery.
- *
- * CTI device name list - for CTI not bound to cores.
- */
-DEFINE_CORESIGHT_DEVLIST(cti_sys_devs, "cti_sys");
-
/* write set of regs to hardware - call with spinlock claimed */
void cti_write_all_hw_regs(struct cti_drvdata *drvdata)
{
@@ -77,7 +62,8 @@ void cti_write_all_hw_regs(struct cti_drvdata *drvdata)
/* other regs */
writel_relaxed(config->ctigate, drvdata->base + CTIGATE);
- writel_relaxed(config->asicctl, drvdata->base + ASICCTL);
+ if (config->asicctl_impl)
+ writel_relaxed(config->asicctl, drvdata->base + ASICCTL);
writel_relaxed(config->ctiappset, drvdata->base + CTIAPPSET);
/* re-enable CTI */
@@ -90,60 +76,24 @@ void cti_write_all_hw_regs(struct cti_drvdata *drvdata)
static int cti_enable_hw(struct cti_drvdata *drvdata)
{
struct cti_config *config = &drvdata->config;
- unsigned long flags;
- int rc = 0;
+ int rc;
- raw_spin_lock_irqsave(&drvdata->spinlock, flags);
+ guard(raw_spinlock_irqsave)(&drvdata->spinlock);
- /* no need to do anything if enabled or unpowered*/
- if (config->hw_enabled || !config->hw_powered)
+ /* no need to do anything if enabled */
+ if (cti_is_active(config))
goto cti_state_unchanged;
/* claim the device */
rc = coresight_claim_device(drvdata->csdev);
if (rc)
- goto cti_err_not_enabled;
+ return rc;
cti_write_all_hw_regs(drvdata);
- config->hw_enabled = true;
- drvdata->config.enable_req_count++;
- raw_spin_unlock_irqrestore(&drvdata->spinlock, flags);
- return rc;
-
cti_state_unchanged:
drvdata->config.enable_req_count++;
-
- /* cannot enable due to error */
-cti_err_not_enabled:
- raw_spin_unlock_irqrestore(&drvdata->spinlock, flags);
- return rc;
-}
-
-/* re-enable CTI on CPU when using CPU hotplug */
-static void cti_cpuhp_enable_hw(struct cti_drvdata *drvdata)
-{
- struct cti_config *config = &drvdata->config;
-
- raw_spin_lock(&drvdata->spinlock);
- config->hw_powered = true;
-
- /* no need to do anything if no enable request */
- if (!drvdata->config.enable_req_count)
- goto cti_hp_not_enabled;
-
- /* try to claim the device */
- if (coresight_claim_device(drvdata->csdev))
- goto cti_hp_not_enabled;
-
- cti_write_all_hw_regs(drvdata);
- config->hw_enabled = true;
- raw_spin_unlock(&drvdata->spinlock);
- return;
-
- /* did not re-enable due to no claim / no request */
-cti_hp_not_enabled:
- raw_spin_unlock(&drvdata->spinlock);
+ return 0;
}
/* disable hardware */
@@ -151,39 +101,36 @@ static int cti_disable_hw(struct cti_drvdata *drvdata)
{
struct cti_config *config = &drvdata->config;
struct coresight_device *csdev = drvdata->csdev;
- int ret = 0;
- raw_spin_lock(&drvdata->spinlock);
+ guard(raw_spinlock_irqsave)(&drvdata->spinlock);
/* don't allow negative refcounts, return an error */
- if (!drvdata->config.enable_req_count) {
- ret = -EINVAL;
- goto cti_not_disabled;
- }
+ if (!cti_is_active(config))
+ return -EINVAL;
/* check refcount - disable on 0 */
if (--drvdata->config.enable_req_count > 0)
- goto cti_not_disabled;
-
- /* no need to do anything if disabled or cpu unpowered */
- if (!config->hw_enabled || !config->hw_powered)
- goto cti_not_disabled;
+ return 0;
CS_UNLOCK(drvdata->base);
/* disable CTI */
writel_relaxed(0, drvdata->base + CTICONTROL);
- config->hw_enabled = false;
coresight_disclaim_device_unlocked(csdev);
CS_LOCK(drvdata->base);
- raw_spin_unlock(&drvdata->spinlock);
- return ret;
+ return 0;
+}
- /* not disabled this call */
-cti_not_disabled:
- raw_spin_unlock(&drvdata->spinlock);
- return ret;
+u32 cti_read_single_reg(struct cti_drvdata *drvdata, int offset)
+{
+ int val;
+
+ CS_UNLOCK(drvdata->base);
+ val = readl_relaxed(drvdata->base + offset);
+ CS_LOCK(drvdata->base);
+
+ return val;
}
void cti_write_single_reg(struct cti_drvdata *drvdata, int offset, u32 value)
@@ -198,11 +145,11 @@ void cti_write_intack(struct device *dev, u32 ackval)
struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);
struct cti_config *config = &drvdata->config;
- raw_spin_lock(&drvdata->spinlock);
+ guard(raw_spinlock_irqsave)(&drvdata->spinlock);
+
/* write if enabled */
- if (cti_active(config))
+ if (cti_is_active(config))
cti_write_single_reg(drvdata, CTIINTACK, ackval);
- raw_spin_unlock(&drvdata->spinlock);
}
/*
@@ -240,6 +187,8 @@ static void cti_set_default_config(struct device *dev,
config->trig_filter_enable = true;
config->ctigate = GENMASK(config->nr_ctm_channels - 1, 0);
config->enable_req_count = 0;
+
+ config->asicctl_impl = !!FIELD_GET(GENMASK(4, 0), devid);
}
/*
@@ -369,7 +318,7 @@ int cti_channel_trig_op(struct device *dev, enum cti_chan_op op,
reg_offset = (direction == CTI_TRIG_IN ? CTIINEN(trigger_idx) :
CTIOUTEN(trigger_idx));
- raw_spin_lock(&drvdata->spinlock);
+ guard(raw_spinlock_irqsave)(&drvdata->spinlock);
/* read - modify write - the trigger / channel enable value */
reg_value = direction == CTI_TRIG_IN ? config->ctiinen[trigger_idx] :
@@ -386,9 +335,9 @@ int cti_channel_trig_op(struct device *dev, enum cti_chan_op op,
config->ctiouten[trigger_idx] = reg_value;
/* write through if enabled */
- if (cti_active(config))
+ if (cti_is_active(config))
cti_write_single_reg(drvdata, reg_offset, reg_value);
- raw_spin_unlock(&drvdata->spinlock);
+
return 0;
}
@@ -406,7 +355,8 @@ int cti_channel_gate_op(struct device *dev, enum cti_chan_gate_op op,
chan_bitmask = BIT(channel_idx);
- raw_spin_lock(&drvdata->spinlock);
+ guard(raw_spinlock_irqsave)(&drvdata->spinlock);
+
reg_value = config->ctigate;
switch (op) {
case CTI_GATE_CHAN_ENABLE:
@@ -423,10 +373,10 @@ int cti_channel_gate_op(struct device *dev, enum cti_chan_gate_op op,
}
if (err == 0) {
config->ctigate = reg_value;
- if (cti_active(config))
+ if (cti_is_active(config))
cti_write_single_reg(drvdata, CTIGATE, reg_value);
}
- raw_spin_unlock(&drvdata->spinlock);
+
return err;
}
@@ -445,7 +395,8 @@ int cti_channel_setop(struct device *dev, enum cti_chan_set_op op,
chan_bitmask = BIT(channel_idx);
- raw_spin_lock(&drvdata->spinlock);
+ guard(raw_spinlock_irqsave)(&drvdata->spinlock);
+
reg_value = config->ctiappset;
switch (op) {
case CTI_CHAN_SET:
@@ -471,9 +422,8 @@ int cti_channel_setop(struct device *dev, enum cti_chan_set_op op,
break;
}
- if ((err == 0) && cti_active(config))
+ if ((err == 0) && cti_is_active(config))
cti_write_single_reg(drvdata, reg_offset, reg_value);
- raw_spin_unlock(&drvdata->spinlock);
return err;
}
@@ -658,146 +608,6 @@ static void cti_remove_conn_xrefs(struct cti_drvdata *drvdata)
}
}
-/** cti PM callbacks **/
-static int cti_cpu_pm_notify(struct notifier_block *nb, unsigned long cmd,
- void *v)
-{
- struct cti_drvdata *drvdata;
- struct coresight_device *csdev;
- unsigned int cpu = smp_processor_id();
- int notify_res = NOTIFY_OK;
-
- if (!cti_cpu_drvdata[cpu])
- return NOTIFY_OK;
-
- drvdata = cti_cpu_drvdata[cpu];
- csdev = drvdata->csdev;
-
- if (WARN_ON_ONCE(drvdata->ctidev.cpu != cpu))
- return NOTIFY_BAD;
-
- raw_spin_lock(&drvdata->spinlock);
-
- switch (cmd) {
- case CPU_PM_ENTER:
- /* CTI regs all static - we have a copy & nothing to save */
- drvdata->config.hw_powered = false;
- if (drvdata->config.hw_enabled)
- coresight_disclaim_device(csdev);
- break;
-
- case CPU_PM_ENTER_FAILED:
- drvdata->config.hw_powered = true;
- if (drvdata->config.hw_enabled) {
- if (coresight_claim_device(csdev))
- drvdata->config.hw_enabled = false;
- }
- break;
-
- case CPU_PM_EXIT:
- /* write hardware registers to re-enable. */
- drvdata->config.hw_powered = true;
- drvdata->config.hw_enabled = false;
-
- /* check enable reference count to enable HW */
- if (drvdata->config.enable_req_count) {
- /* check we can claim the device as we re-power */
- if (coresight_claim_device(csdev))
- goto cti_notify_exit;
-
- drvdata->config.hw_enabled = true;
- cti_write_all_hw_regs(drvdata);
- }
- break;
-
- default:
- notify_res = NOTIFY_DONE;
- break;
- }
-
-cti_notify_exit:
- raw_spin_unlock(&drvdata->spinlock);
- return notify_res;
-}
-
-static struct notifier_block cti_cpu_pm_nb = {
- .notifier_call = cti_cpu_pm_notify,
-};
-
-/* CPU HP handlers */
-static int cti_starting_cpu(unsigned int cpu)
-{
- struct cti_drvdata *drvdata = cti_cpu_drvdata[cpu];
-
- if (!drvdata)
- return 0;
-
- cti_cpuhp_enable_hw(drvdata);
- return 0;
-}
-
-static int cti_dying_cpu(unsigned int cpu)
-{
- struct cti_drvdata *drvdata = cti_cpu_drvdata[cpu];
-
- if (!drvdata)
- return 0;
-
- raw_spin_lock(&drvdata->spinlock);
- drvdata->config.hw_powered = false;
- if (drvdata->config.hw_enabled)
- coresight_disclaim_device(drvdata->csdev);
- raw_spin_unlock(&drvdata->spinlock);
- return 0;
-}
-
-static int cti_pm_setup(struct cti_drvdata *drvdata)
-{
- int ret;
-
- if (drvdata->ctidev.cpu == -1)
- return 0;
-
- if (nr_cti_cpu)
- goto done;
-
- cpus_read_lock();
- ret = cpuhp_setup_state_nocalls_cpuslocked(
- CPUHP_AP_ARM_CORESIGHT_CTI_STARTING,
- "arm/coresight_cti:starting",
- cti_starting_cpu, cti_dying_cpu);
- if (ret) {
- cpus_read_unlock();
- return ret;
- }
-
- ret = cpu_pm_register_notifier(&cti_cpu_pm_nb);
- cpus_read_unlock();
- if (ret) {
- cpuhp_remove_state_nocalls(CPUHP_AP_ARM_CORESIGHT_CTI_STARTING);
- return ret;
- }
-
-done:
- nr_cti_cpu++;
- cti_cpu_drvdata[drvdata->ctidev.cpu] = drvdata;
-
- return 0;
-}
-
-/* release PM registrations */
-static void cti_pm_release(struct cti_drvdata *drvdata)
-{
- if (drvdata->ctidev.cpu == -1)
- return;
-
- cti_cpu_drvdata[drvdata->ctidev.cpu] = NULL;
- if (--nr_cti_cpu == 0) {
- cpu_pm_unregister_notifier(&cti_cpu_pm_nb);
- cpuhp_remove_state_nocalls(CPUHP_AP_ARM_CORESIGHT_CTI_STARTING);
- }
-}
-
/** cti ect operations **/
int cti_enable(struct coresight_device *csdev, enum cs_mode mode,
struct coresight_path *path)
@@ -823,17 +633,13 @@ static const struct coresight_ops cti_ops = {
.helper_ops = &cti_ops_ect,
};
-/*
- * Free up CTI specific resources
- * called by dev->release, need to call down to underlying csdev release.
- */
-static void cti_device_release(struct device *dev)
+static void cti_remove(struct amba_device *adev)
{
- struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);
+ struct cti_drvdata *drvdata = dev_get_drvdata(&adev->dev);
struct cti_drvdata *ect_item, *ect_tmp;
mutex_lock(&ect_mutex);
- cti_pm_release(drvdata);
+ cti_remove_conn_xrefs(drvdata);
/* remove from the list */
list_for_each_entry_safe(ect_item, ect_tmp, &ect_net, node) {
@@ -844,17 +650,6 @@ static void cti_device_release(struct device *dev)
}
mutex_unlock(&ect_mutex);
- if (drvdata->csdev_release)
- drvdata->csdev_release(dev);
-}
-static void cti_remove(struct amba_device *adev)
-{
- struct cti_drvdata *drvdata = dev_get_drvdata(&adev->dev);
-
- mutex_lock(&ect_mutex);
- cti_remove_conn_xrefs(drvdata);
- mutex_unlock(&ect_mutex);
-
coresight_unregister(drvdata->csdev);
}
@@ -900,29 +695,27 @@ static int cti_probe(struct amba_device *adev, const struct amba_id *id)
return PTR_ERR(pdata);
}
- /* default to powered - could change on PM notifications */
- drvdata->config.hw_powered = true;
-
- /* set up device name - will depend if cpu bound or otherwise */
+ /*
+ * Set up device name - will depend if cpu bound or otherwise.
+ *
+ * CTI bound to cores will have the name cti_cpu<N> where N is th
+ * eCPU ID. System CTIs will have the name cti_sys<I> where I is an
+ * index allocated by order of discovery.
+ */
if (drvdata->ctidev.cpu >= 0)
cti_desc.name = devm_kasprintf(dev, GFP_KERNEL, "cti_cpu%d",
drvdata->ctidev.cpu);
else
- cti_desc.name = coresight_alloc_device_name(&cti_sys_devs, dev);
+ cti_desc.name = coresight_alloc_device_name("cti_sys", dev);
if (!cti_desc.name)
return -ENOMEM;
- /* setup CPU power management handling for CPU bound CTI devices. */
- ret = cti_pm_setup(drvdata);
- if (ret)
- return ret;
-
/* create dynamic attributes for connections */
ret = cti_create_cons_sysfs(dev, drvdata);
if (ret) {
dev_err(dev, "%s: create dynamic sysfs entries failed\n",
cti_desc.name);
- goto pm_release;
+ return ret;
}
/* set up coresight component description */
@@ -935,10 +728,8 @@ static int cti_probe(struct amba_device *adev, const struct amba_id *id)
coresight_clear_self_claim_tag(&cti_desc.access);
drvdata->csdev = coresight_register(&cti_desc);
- if (IS_ERR(drvdata->csdev)) {
- ret = PTR_ERR(drvdata->csdev);
- goto pm_release;
- }
+ if (IS_ERR(drvdata->csdev))
+ return PTR_ERR(drvdata->csdev);
/* add to list of CTI devices */
mutex_lock(&ect_mutex);
@@ -947,18 +738,10 @@ static int cti_probe(struct amba_device *adev, const struct amba_id *id)
cti_update_conn_xrefs(drvdata);
mutex_unlock(&ect_mutex);
- /* set up release chain */
- drvdata->csdev_release = drvdata->csdev->dev.release;
- drvdata->csdev->dev.release = cti_device_release;
-
/* all done - dec pm refcount */
pm_runtime_put(&adev->dev);
dev_info(&drvdata->csdev->dev, "CTI initialized\n");
return 0;
-
-pm_release:
- cti_pm_release(drvdata);
- return ret;
}
static struct amba_cs_uci_id uci_id_cti[] = {
diff --git a/drivers/hwtracing/coresight/coresight-cti-sysfs.c b/drivers/hwtracing/coresight/coresight-cti-sysfs.c
index 26ec0d8ed181..3fe2c916d228 100644
--- a/drivers/hwtracing/coresight/coresight-cti-sysfs.c
+++ b/drivers/hwtracing/coresight/coresight-cti-sysfs.c
@@ -81,19 +81,12 @@ static ssize_t enable_show(struct device *dev,
char *buf)
{
int enable_req;
- bool enabled, powered;
struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);
- raw_spin_lock(&drvdata->spinlock);
- enable_req = drvdata->config.enable_req_count;
- powered = drvdata->config.hw_powered;
- enabled = drvdata->config.hw_enabled;
- raw_spin_unlock(&drvdata->spinlock);
+ scoped_guard(raw_spinlock_irqsave, &drvdata->spinlock)
+ enable_req = cti_is_active(&drvdata->config);
- if (powered)
- return sprintf(buf, "%d\n", enabled);
- else
- return sprintf(buf, "%d\n", !!enable_req);
+ return sprintf(buf, "%d\n", !!enable_req);
}
static ssize_t enable_store(struct device *dev,
@@ -131,12 +124,7 @@ static ssize_t powered_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- bool powered;
- struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);
-
- raw_spin_lock(&drvdata->spinlock);
- powered = drvdata->config.hw_powered;
- raw_spin_unlock(&drvdata->spinlock);
+ bool powered = pm_runtime_active(dev->parent);
return sprintf(buf, "%d\n", powered);
}
@@ -181,10 +169,10 @@ static ssize_t coresight_cti_reg_show(struct device *dev,
u32 val = 0;
pm_runtime_get_sync(dev->parent);
- raw_spin_lock(&drvdata->spinlock);
- if (drvdata->config.hw_powered)
- val = readl_relaxed(drvdata->base + cti_attr->off);
- raw_spin_unlock(&drvdata->spinlock);
+
+ scoped_guard(raw_spinlock_irqsave, &drvdata->spinlock)
+ val = cti_read_single_reg(drvdata, cti_attr->off);
+
pm_runtime_put_sync(dev->parent);
return sysfs_emit(buf, "0x%x\n", val);
}
@@ -202,10 +190,10 @@ static __maybe_unused ssize_t coresight_cti_reg_store(struct device *dev,
return -EINVAL;
pm_runtime_get_sync(dev->parent);
- raw_spin_lock(&drvdata->spinlock);
- if (drvdata->config.hw_powered)
+
+ scoped_guard(raw_spinlock_irqsave, &drvdata->spinlock)
cti_write_single_reg(drvdata, cti_attr->off, val);
- raw_spin_unlock(&drvdata->spinlock);
+
pm_runtime_put_sync(dev->parent);
return size;
}
@@ -264,17 +252,19 @@ static ssize_t cti_reg32_show(struct device *dev, char *buf,
struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);
struct cti_config *config = &drvdata->config;
- raw_spin_lock(&drvdata->spinlock);
- if ((reg_offset >= 0) && cti_active(config)) {
- CS_UNLOCK(drvdata->base);
- val = readl_relaxed(drvdata->base + reg_offset);
- if (pcached_val)
- *pcached_val = val;
- CS_LOCK(drvdata->base);
- } else if (pcached_val) {
- val = *pcached_val;
+ if (reg_offset < 0)
+ return -EINVAL;
+
+ scoped_guard(raw_spinlock_irqsave, &drvdata->spinlock) {
+ if (cti_is_active(config)) {
+ val = cti_read_single_reg(drvdata, reg_offset);
+ if (pcached_val)
+ *pcached_val = val;
+ } else if (pcached_val) {
+ val = *pcached_val;
+ }
}
- raw_spin_unlock(&drvdata->spinlock);
+
return sprintf(buf, "%#x\n", val);
}
@@ -293,15 +283,19 @@ static ssize_t cti_reg32_store(struct device *dev, const char *buf,
if (kstrtoul(buf, 0, &val))
return -EINVAL;
- raw_spin_lock(&drvdata->spinlock);
- /* local store */
- if (pcached_val)
- *pcached_val = (u32)val;
+ if (reg_offset < 0)
+ return -EINVAL;
+
+ scoped_guard(raw_spinlock_irqsave, &drvdata->spinlock) {
+ /* local store */
+ if (pcached_val)
+ *pcached_val = (u32)val;
+
+ /* write through if offset and enabled */
+ if (cti_is_active(config))
+ cti_write_single_reg(drvdata, reg_offset, val);
+ }
- /* write through if offset and enabled */
- if ((reg_offset >= 0) && cti_active(config))
- cti_write_single_reg(drvdata, reg_offset, val);
- raw_spin_unlock(&drvdata->spinlock);
return size;
}
@@ -343,15 +337,16 @@ static ssize_t inout_sel_store(struct device *dev,
{
unsigned long val;
struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);
+ struct cti_config *config = &drvdata->config;
if (kstrtoul(buf, 0, &val))
return -EINVAL;
- if (val > (CTIINOUTEN_MAX - 1))
+ if (val >= config->nr_trig_max)
return -EINVAL;
- raw_spin_lock(&drvdata->spinlock);
+ guard(raw_spinlock_irqsave)(&drvdata->spinlock);
+
drvdata->config.ctiinout_sel = val;
- raw_spin_unlock(&drvdata->spinlock);
return size;
}
static DEVICE_ATTR_RW(inout_sel);
@@ -364,10 +359,11 @@ static ssize_t inen_show(struct device *dev,
int index;
struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);
- raw_spin_lock(&drvdata->spinlock);
- index = drvdata->config.ctiinout_sel;
- val = drvdata->config.ctiinen[index];
- raw_spin_unlock(&drvdata->spinlock);
+ scoped_guard(raw_spinlock_irqsave, &drvdata->spinlock) {
+ index = drvdata->config.ctiinout_sel;
+ val = drvdata->config.ctiinen[index];
+ }
+
return sprintf(buf, "%#lx\n", val);
}
@@ -383,14 +379,15 @@ static ssize_t inen_store(struct device *dev,
if (kstrtoul(buf, 0, &val))
return -EINVAL;
- raw_spin_lock(&drvdata->spinlock);
+ guard(raw_spinlock_irqsave)(&drvdata->spinlock);
+
index = config->ctiinout_sel;
config->ctiinen[index] = val;
/* write through if enabled */
- if (cti_active(config))
+ if (cti_is_active(config))
cti_write_single_reg(drvdata, CTIINEN(index), val);
- raw_spin_unlock(&drvdata->spinlock);
+
return size;
}
static DEVICE_ATTR_RW(inen);
@@ -403,10 +400,11 @@ static ssize_t outen_show(struct device *dev,
int index;
struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);
- raw_spin_lock(&drvdata->spinlock);
- index = drvdata->config.ctiinout_sel;
- val = drvdata->config.ctiouten[index];
- raw_spin_unlock(&drvdata->spinlock);
+ scoped_guard(raw_spinlock_irqsave, &drvdata->spinlock) {
+ index = drvdata->config.ctiinout_sel;
+ val = drvdata->config.ctiouten[index];
+ }
+
return sprintf(buf, "%#lx\n", val);
}
@@ -422,14 +420,15 @@ static ssize_t outen_store(struct device *dev,
if (kstrtoul(buf, 0, &val))
return -EINVAL;
- raw_spin_lock(&drvdata->spinlock);
+ guard(raw_spinlock_irqsave)(&drvdata->spinlock);
+
index = config->ctiinout_sel;
config->ctiouten[index] = val;
/* write through if enabled */
- if (cti_active(config))
+ if (cti_is_active(config))
cti_write_single_reg(drvdata, CTIOUTEN(index), val);
- raw_spin_unlock(&drvdata->spinlock);
+
return size;
}
static DEVICE_ATTR_RW(outen);
@@ -463,15 +462,15 @@ static ssize_t appclear_store(struct device *dev,
if (kstrtoul(buf, 0, &val))
return -EINVAL;
- raw_spin_lock(&drvdata->spinlock);
+ guard(raw_spinlock_irqsave)(&drvdata->spinlock);
/* a 1'b1 in appclr clears down the same bit in appset*/
config->ctiappset &= ~val;
/* write through if enabled */
- if (cti_active(config))
+ if (cti_is_active(config))
cti_write_single_reg(drvdata, CTIAPPCLEAR, val);
- raw_spin_unlock(&drvdata->spinlock);
+
return size;
}
static DEVICE_ATTR_WO(appclear);
@@ -487,12 +486,12 @@ static ssize_t apppulse_store(struct device *dev,
if (kstrtoul(buf, 0, &val))
return -EINVAL;
- raw_spin_lock(&drvdata->spinlock);
+ guard(raw_spinlock_irqsave)(&drvdata->spinlock);
/* write through if enabled */
- if (cti_active(config))
+ if (cti_is_active(config))
cti_write_single_reg(drvdata, CTIAPPPULSE, val);
- raw_spin_unlock(&drvdata->spinlock);
+
return size;
}
static DEVICE_ATTR_WO(apppulse);
@@ -530,6 +529,18 @@ static struct attribute *coresight_cti_regs_attrs[] = {
NULL,
};
+static umode_t coresight_cti_regs_is_visible(struct kobject *kobj,
+ struct attribute *attr, int idx)
+{
+ struct device *dev = kobj_to_dev(kobj);
+ struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);
+
+ if (attr == &dev_attr_asicctl.attr && !drvdata->config.asicctl_impl)
+ return 0;
+
+ return attr->mode;
+}
+
/* CTI channel x-trigger programming */
static int
cti_trig_op_parse(struct device *dev, enum cti_chan_op op,
@@ -678,9 +689,9 @@ static ssize_t trig_filter_enable_show(struct device *dev,
u32 val;
struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);
- raw_spin_lock(&drvdata->spinlock);
- val = drvdata->config.trig_filter_enable;
- raw_spin_unlock(&drvdata->spinlock);
+ scoped_guard(raw_spinlock_irqsave, &drvdata->spinlock)
+ val = drvdata->config.trig_filter_enable;
+
return sprintf(buf, "%d\n", val);
}
@@ -694,9 +705,9 @@ static ssize_t trig_filter_enable_store(struct device *dev,
if (kstrtoul(buf, 0, &val))
return -EINVAL;
- raw_spin_lock(&drvdata->spinlock);
+ guard(raw_spinlock_irqsave)(&drvdata->spinlock);
+
drvdata->config.trig_filter_enable = !!val;
- raw_spin_unlock(&drvdata->spinlock);
return size;
}
static DEVICE_ATTR_RW(trig_filter_enable);
@@ -726,7 +737,7 @@ static ssize_t chan_xtrigs_reset_store(struct device *dev,
struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);
struct cti_config *config = &drvdata->config;
- raw_spin_lock(&drvdata->spinlock);
+ guard(raw_spinlock_irqsave)(&drvdata->spinlock);
/* clear the CTI trigger / channel programming registers */
for (i = 0; i < config->nr_trig_max; i++) {
@@ -742,10 +753,9 @@ static ssize_t chan_xtrigs_reset_store(struct device *dev,
config->xtrig_rchan_sel = 0;
/* if enabled then write through */
- if (cti_active(config))
+ if (cti_is_active(config))
cti_write_all_hw_regs(drvdata);
- raw_spin_unlock(&drvdata->spinlock);
return size;
}
static DEVICE_ATTR_WO(chan_xtrigs_reset);
@@ -766,9 +776,9 @@ static ssize_t chan_xtrigs_sel_store(struct device *dev,
if (val > (drvdata->config.nr_ctm_channels - 1))
return -EINVAL;
- raw_spin_lock(&drvdata->spinlock);
+ guard(raw_spinlock_irqsave)(&drvdata->spinlock);
+
drvdata->config.xtrig_rchan_sel = val;
- raw_spin_unlock(&drvdata->spinlock);
return size;
}
@@ -779,9 +789,8 @@ static ssize_t chan_xtrigs_sel_show(struct device *dev,
unsigned long val;
struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);
- raw_spin_lock(&drvdata->spinlock);
- val = drvdata->config.xtrig_rchan_sel;
- raw_spin_unlock(&drvdata->spinlock);
+ scoped_guard(raw_spinlock_irqsave, &drvdata->spinlock)
+ val = drvdata->config.xtrig_rchan_sel;
return sprintf(buf, "%ld\n", val);
}
@@ -836,12 +845,12 @@ static ssize_t print_chan_list(struct device *dev,
unsigned long inuse_bits = 0, chan_mask;
/* scan regs to get bitmap of channels in use. */
- raw_spin_lock(&drvdata->spinlock);
- for (i = 0; i < config->nr_trig_max; i++) {
- inuse_bits |= config->ctiinen[i];
- inuse_bits |= config->ctiouten[i];
+ scoped_guard(raw_spinlock_irqsave, &drvdata->spinlock) {
+ for (i = 0; i < config->nr_trig_max; i++) {
+ inuse_bits |= config->ctiinen[i];
+ inuse_bits |= config->ctiouten[i];
+ }
}
- raw_spin_unlock(&drvdata->spinlock);
/* inverse bits if printing free channels */
if (!inuse)
@@ -1165,6 +1174,7 @@ static const struct attribute_group coresight_cti_mgmt_group = {
static const struct attribute_group coresight_cti_regs_group = {
.attrs = coresight_cti_regs_attrs,
+ .is_visible = coresight_cti_regs_is_visible,
.name = "regs",
};
diff --git a/drivers/hwtracing/coresight/coresight-cti.h b/drivers/hwtracing/coresight/coresight-cti.h
index 4f89091ee93f..c5f9e79fabc6 100644
--- a/drivers/hwtracing/coresight/coresight-cti.h
+++ b/drivers/hwtracing/coresight/coresight-cti.h
@@ -119,9 +119,8 @@ struct cti_device {
* @nr_trig_max: Max number of trigger signals implemented on device.
* (max of trig_in or trig_out) - from ID register.
* @nr_ctm_channels: number of available CTM channels - from ID register.
+ * @asicctl_impl: true if asicctl is implemented.
* @enable_req_count: CTI is enabled alongside >=1 associated devices.
- * @hw_enabled: true if hw is currently enabled.
- * @hw_powered: true if associated cpu powered on, or no cpu.
* @trig_in_use: bitfield of in triggers registered as in use.
* @trig_out_use: bitfield of out triggers registered as in use.
* @trig_out_filter: bitfield of out triggers that are blocked if filter
@@ -140,11 +139,10 @@ struct cti_config {
/* hardware description */
int nr_ctm_channels;
int nr_trig_max;
+ bool asicctl_impl;
/* cti enable control */
int enable_req_count;
- bool hw_enabled;
- bool hw_powered;
/* registered triggers and filtering */
u32 trig_in_use;
@@ -170,7 +168,6 @@ struct cti_config {
* @spinlock: Control data access to one at a time.
* @config: Configuration data for this CTI device.
* @node: List entry of this device in the list of CTI devices.
- * @csdev_release: release function for underlying coresight_device.
*/
struct cti_drvdata {
void __iomem *base;
@@ -179,7 +176,6 @@ struct cti_drvdata {
raw_spinlock_t spinlock;
struct cti_config config;
struct list_head node;
- void (*csdev_release)(struct device *dev);
};
/*
@@ -222,6 +218,7 @@ int cti_disable(struct coresight_device *csdev, struct coresight_path *path);
void cti_write_all_hw_regs(struct cti_drvdata *drvdata);
void cti_write_intack(struct device *dev, u32 ackval);
void cti_write_single_reg(struct cti_drvdata *drvdata, int offset, u32 value);
+u32 cti_read_single_reg(struct cti_drvdata *drvdata, int offset);
int cti_channel_trig_op(struct device *dev, enum cti_chan_op op,
enum cti_trig_dir direction, u32 channel_idx,
u32 trigger_idx);
@@ -234,10 +231,10 @@ struct coresight_platform_data *
coresight_cti_get_platform_data(struct device *dev);
const char *cti_plat_get_node_name(struct fwnode_handle *fwnode);
-/* cti powered and enabled */
-static inline bool cti_active(struct cti_config *cfg)
+/* Check if a cti device is enabled */
+static inline bool cti_is_active(struct cti_config *cfg)
{
- return cfg->hw_powered && cfg->hw_enabled;
+ return !!cfg->enable_req_count;
}
#endif /* _CORESIGHT_CORESIGHT_CTI_H */
diff --git a/drivers/hwtracing/coresight/coresight-dummy.c b/drivers/hwtracing/coresight/coresight-dummy.c
index 14322c99e29d..c176a2f57300 100644
--- a/drivers/hwtracing/coresight/coresight-dummy.c
+++ b/drivers/hwtracing/coresight/coresight-dummy.c
@@ -19,9 +19,6 @@ struct dummy_drvdata {
u8 traceid;
};
-DEFINE_CORESIGHT_DEVLIST(source_devs, "dummy_source");
-DEFINE_CORESIGHT_DEVLIST(sink_devs, "dummy_sink");
-
static int dummy_source_enable(struct coresight_device *csdev,
struct perf_event *event, enum cs_mode mode,
__maybe_unused struct coresight_path *path)
@@ -126,7 +123,7 @@ static int dummy_probe(struct platform_device *pdev)
if (of_device_is_compatible(node, "arm,coresight-dummy-source")) {
- desc.name = coresight_alloc_device_name(&source_devs, dev);
+ desc.name = coresight_alloc_device_name("dummy_source", dev);
if (!desc.name)
return -ENOMEM;
@@ -155,7 +152,7 @@ static int dummy_probe(struct platform_device *pdev)
drvdata->traceid = (u8)trace_id;
} else if (of_device_is_compatible(node, "arm,coresight-dummy-sink")) {
- desc.name = coresight_alloc_device_name(&sink_devs, dev);
+ desc.name = coresight_alloc_device_name("dummy_sink", dev);
if (!desc.name)
return -ENOMEM;
diff --git a/drivers/hwtracing/coresight/coresight-etb10.c b/drivers/hwtracing/coresight/coresight-etb10.c
index 6657602d8f2e..b952a1d47f12 100644
--- a/drivers/hwtracing/coresight/coresight-etb10.c
+++ b/drivers/hwtracing/coresight/coresight-etb10.c
@@ -63,8 +63,6 @@
#define ETB_FFSR_BIT 1
#define ETB_FRAME_SIZE_WORDS 4
-DEFINE_CORESIGHT_DEVLIST(etb_devs, "etb");
-
/**
* struct etb_drvdata - specifics associated to an ETB component
* @base: memory mapped base address for this component.
@@ -722,7 +720,7 @@ static int etb_probe(struct amba_device *adev, const struct amba_id *id)
struct resource *res = &adev->res;
struct coresight_desc desc = { 0 };
- desc.name = coresight_alloc_device_name(&etb_devs, dev);
+ desc.name = coresight_alloc_device_name("etb", dev);
if (!desc.name)
return -ENOMEM;
diff --git a/drivers/hwtracing/coresight/coresight-etm-perf.c b/drivers/hwtracing/coresight/coresight-etm-perf.c
index 72017dcc3b7f..f85dedf89a3f 100644
--- a/drivers/hwtracing/coresight/coresight-etm-perf.c
+++ b/drivers/hwtracing/coresight/coresight-etm-perf.c
@@ -902,7 +902,10 @@ int etm_perf_add_symlink_sink(struct coresight_device *csdev)
if (csdev->type != CORESIGHT_DEV_TYPE_SINK &&
csdev->type != CORESIGHT_DEV_TYPE_LINKSINK)
- return -EINVAL;
+ return -EOPNOTSUPP;
+
+ if (!sink_ops(csdev)->alloc_buffer)
+ return -EOPNOTSUPP;
if (csdev->ea != NULL)
return -EINVAL;
diff --git a/drivers/hwtracing/coresight/coresight-funnel.c b/drivers/hwtracing/coresight/coresight-funnel.c
index 3b248e54471a..3f56ceccd8c9 100644
--- a/drivers/hwtracing/coresight/coresight-funnel.c
+++ b/drivers/hwtracing/coresight/coresight-funnel.c
@@ -30,8 +30,6 @@
#define FUNNEL_HOLDTIME (0x7 << FUNNEL_HOLDTIME_SHFT)
#define FUNNEL_ENSx_MASK 0xff
-DEFINE_CORESIGHT_DEVLIST(funnel_devs, "funnel");
-
/**
* struct funnel_drvdata - specifics associated to a funnel component
* @base: memory mapped base address for this component.
@@ -223,7 +221,7 @@ static int funnel_probe(struct device *dev, struct resource *res)
of_device_is_compatible(dev->of_node, "arm,coresight-funnel"))
dev_warn_once(dev, "Uses OBSOLETE CoreSight funnel binding\n");
- desc.name = coresight_alloc_device_name(&funnel_devs, dev);
+ desc.name = coresight_alloc_device_name("funnel", dev);
if (!desc.name)
return -ENOMEM;
diff --git a/drivers/hwtracing/coresight/coresight-platform.c b/drivers/hwtracing/coresight/coresight-platform.c
index 0db64c5f4995..e337b6e2bf32 100644
--- a/drivers/hwtracing/coresight/coresight-platform.c
+++ b/drivers/hwtracing/coresight/coresight-platform.c
@@ -220,6 +220,8 @@ static int of_coresight_parse_endpoint(struct device *dev,
rparent = of_coresight_get_port_parent(rep);
if (!rparent)
break;
+ if (!of_device_is_available(rparent))
+ break;
if (of_graph_parse_endpoint(rep, &rendpoint))
break;
@@ -849,7 +851,7 @@ coresight_get_platform_data(struct device *dev)
error:
if (!IS_ERR_OR_NULL(pdata))
/* Cleanup the connection information */
- coresight_release_platform_data(NULL, dev, pdata);
+ coresight_release_platform_data(dev, pdata);
return ERR_PTR(ret);
}
EXPORT_SYMBOL_GPL(coresight_get_platform_data);
diff --git a/drivers/hwtracing/coresight/coresight-priv.h b/drivers/hwtracing/coresight/coresight-priv.h
index fd896ac07942..1ea882dffd70 100644
--- a/drivers/hwtracing/coresight/coresight-priv.h
+++ b/drivers/hwtracing/coresight/coresight-priv.h
@@ -239,8 +239,7 @@ static inline void *coresight_get_uci_data_from_amba(const struct amba_id *table
return NULL;
}
-void coresight_release_platform_data(struct coresight_device *csdev,
- struct device *dev,
+void coresight_release_platform_data(struct device *dev,
struct coresight_platform_data *pdata);
struct coresight_device *
coresight_find_csdev_by_fwnode(struct fwnode_handle *r_fwnode);
diff --git a/drivers/hwtracing/coresight/coresight-replicator.c b/drivers/hwtracing/coresight/coresight-replicator.c
index e6472658235d..07fc04f53b88 100644
--- a/drivers/hwtracing/coresight/coresight-replicator.c
+++ b/drivers/hwtracing/coresight/coresight-replicator.c
@@ -24,8 +24,6 @@
#define REPLICATOR_IDFILTER0 0x000
#define REPLICATOR_IDFILTER1 0x004
-DEFINE_CORESIGHT_DEVLIST(replicator_devs, "replicator");
-
/**
* struct replicator_drvdata - specifics associated to a replicator component
* @base: memory mapped base address for this component. Also indicates
@@ -230,7 +228,7 @@ static int replicator_probe(struct device *dev, struct resource *res)
dev_warn_once(dev,
"Uses OBSOLETE CoreSight replicator binding\n");
- desc.name = coresight_alloc_device_name(&replicator_devs, dev);
+ desc.name = coresight_alloc_device_name("replicator", dev);
if (!desc.name)
return -ENOMEM;
diff --git a/drivers/hwtracing/coresight/coresight-stm.c b/drivers/hwtracing/coresight/coresight-stm.c
index e68529bf89c9..aca6cec7885a 100644
--- a/drivers/hwtracing/coresight/coresight-stm.c
+++ b/drivers/hwtracing/coresight/coresight-stm.c
@@ -110,8 +110,6 @@ struct channel_space {
unsigned long *guaranteed;
};
-DEFINE_CORESIGHT_DEVLIST(stm_devs, "stm");
-
/**
* struct stm_drvdata - specifics associated to an STM component
* @base: memory mapped base address for this component.
@@ -834,7 +832,7 @@ static int __stm_probe(struct device *dev, struct resource *res)
struct resource ch_res;
struct coresight_desc desc = { 0 };
- desc.name = coresight_alloc_device_name(&stm_devs, dev);
+ desc.name = coresight_alloc_device_name("stm", dev);
if (!desc.name)
return -ENOMEM;
diff --git a/drivers/hwtracing/coresight/coresight-tmc-core.c b/drivers/hwtracing/coresight/coresight-tmc-core.c
index 36599c431be6..c89fe996af23 100644
--- a/drivers/hwtracing/coresight/coresight-tmc-core.c
+++ b/drivers/hwtracing/coresight/coresight-tmc-core.c
@@ -32,10 +32,6 @@
#include "coresight-priv.h"
#include "coresight-tmc.h"
-DEFINE_CORESIGHT_DEVLIST(etb_devs, "tmc_etb");
-DEFINE_CORESIGHT_DEVLIST(etf_devs, "tmc_etf");
-DEFINE_CORESIGHT_DEVLIST(etr_devs, "tmc_etr");
-
int tmc_wait_for_tmcready(struct tmc_drvdata *drvdata)
{
struct coresight_device *csdev = drvdata->csdev;
@@ -401,7 +397,6 @@ static ssize_t tmc_crashdata_read(struct file *file, char __user *data,
static int tmc_crashdata_release(struct inode *inode, struct file *file)
{
- int ret = 0;
unsigned long flags;
struct tmc_resrv_buf *rbuf;
struct tmc_drvdata *drvdata = container_of(file->private_data,
@@ -414,7 +409,7 @@ static int tmc_crashdata_release(struct inode *inode, struct file *file)
raw_spin_unlock_irqrestore(&drvdata->spinlock, flags);
dev_dbg(&drvdata->csdev->dev, "%s: released\n", __func__);
- return ret;
+ return 0;
}
static const struct file_operations tmc_crashdata_fops = {
@@ -777,7 +772,7 @@ static int __tmc_probe(struct device *dev, struct resource *res)
struct coresight_platform_data *pdata = NULL;
struct tmc_drvdata *drvdata;
struct coresight_desc desc = { 0 };
- struct coresight_dev_list *dev_list = NULL;
+ const char *dev_list = NULL;
drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
if (!drvdata)
@@ -827,7 +822,7 @@ static int __tmc_probe(struct device *dev, struct resource *res)
desc.type = CORESIGHT_DEV_TYPE_SINK;
desc.subtype.sink_subtype = CORESIGHT_DEV_SUBTYPE_SINK_BUFFER;
desc.ops = &tmc_etb_cs_ops;
- dev_list = &etb_devs;
+ dev_list = "tmc_etb";
break;
case TMC_CONFIG_TYPE_ETR:
desc.groups = coresight_etr_groups;
@@ -839,7 +834,7 @@ static int __tmc_probe(struct device *dev, struct resource *res)
goto out;
idr_init(&drvdata->idr);
mutex_init(&drvdata->idr_mutex);
- dev_list = &etr_devs;
+ dev_list = "tmc_etr";
break;
case TMC_CONFIG_TYPE_ETF:
desc.groups = coresight_etf_groups;
@@ -847,7 +842,7 @@ static int __tmc_probe(struct device *dev, struct resource *res)
desc.subtype.sink_subtype = CORESIGHT_DEV_SUBTYPE_SINK_BUFFER;
desc.subtype.link_subtype = CORESIGHT_DEV_SUBTYPE_LINK_FIFO;
desc.ops = &tmc_etf_cs_ops;
- dev_list = &etf_devs;
+ dev_list = "tmc_etf";
break;
default:
pr_err("%s: Unsupported TMC config\n", desc.name);
diff --git a/drivers/hwtracing/coresight/coresight-tnoc.c b/drivers/hwtracing/coresight/coresight-tnoc.c
index 1128612e70a7..96a25877b824 100644
--- a/drivers/hwtracing/coresight/coresight-tnoc.c
+++ b/drivers/hwtracing/coresight/coresight-tnoc.c
@@ -47,8 +47,6 @@ struct trace_noc_drvdata {
int atid;
};
-DEFINE_CORESIGHT_DEVLIST(trace_noc_devs, "traceNoc");
-
static void trace_noc_enable_hw(struct trace_noc_drvdata *drvdata)
{
u32 val;
@@ -191,7 +189,7 @@ static int _tnoc_probe(struct device *dev, struct resource *res)
struct coresight_desc desc = { 0 };
int ret;
- desc.name = coresight_alloc_device_name(&trace_noc_devs, dev);
+ desc.name = coresight_alloc_device_name("traceNoc", dev);
if (!desc.name)
return -ENOMEM;
diff --git a/drivers/hwtracing/coresight/coresight-tpda.c b/drivers/hwtracing/coresight/coresight-tpda.c
index 7055f8f13427..89c8f71f0aff 100644
--- a/drivers/hwtracing/coresight/coresight-tpda.c
+++ b/drivers/hwtracing/coresight/coresight-tpda.c
@@ -20,8 +20,6 @@
#include "coresight-trace-id.h"
#include "coresight-tpdm.h"
-DEFINE_CORESIGHT_DEVLIST(tpda_devs, "tpda");
-
static void tpda_clear_element_size(struct coresight_device *csdev)
{
struct tpda_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
@@ -585,7 +583,7 @@ static int tpda_probe(struct amba_device *adev, const struct amba_id *id)
if (ret)
return ret;
- desc.name = coresight_alloc_device_name(&tpda_devs, dev);
+ desc.name = coresight_alloc_device_name("tpda", dev);
if (!desc.name)
return -ENOMEM;
desc.type = CORESIGHT_DEV_TYPE_LINK;
diff --git a/drivers/hwtracing/coresight/coresight-tpdm.c b/drivers/hwtracing/coresight/coresight-tpdm.c
index 06e0a905a67d..eaf7210af648 100644
--- a/drivers/hwtracing/coresight/coresight-tpdm.c
+++ b/drivers/hwtracing/coresight/coresight-tpdm.c
@@ -19,8 +19,6 @@
#include "coresight-priv.h"
#include "coresight-tpdm.h"
-DEFINE_CORESIGHT_DEVLIST(tpdm_devs, "tpdm");
-
static bool tpdm_has_dsb_dataset(struct tpdm_drvdata *drvdata)
{
return (drvdata->datasets & TPDM_PIDR0_DS_DSB);
@@ -483,7 +481,7 @@ static void __tpdm_enable(struct tpdm_drvdata *drvdata)
static int tpdm_enable(struct coresight_device *csdev, struct perf_event *event,
enum cs_mode mode,
- __maybe_unused struct coresight_path *path)
+ struct coresight_path *path)
{
struct tpdm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
@@ -499,6 +497,7 @@ static int tpdm_enable(struct coresight_device *csdev, struct perf_event *event,
}
__tpdm_enable(drvdata);
+ drvdata->traceid = path->trace_id;
drvdata->enable = true;
spin_unlock(&drvdata->spinlock);
@@ -695,6 +694,29 @@ static struct attribute_group tpdm_attr_grp = {
.attrs = tpdm_attrs,
};
+static ssize_t traceid_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ unsigned long val;
+ struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+
+ val = drvdata->traceid;
+ if (!val)
+ return -EINVAL;
+
+ return sysfs_emit(buf, "%#lx\n", val);
+}
+static DEVICE_ATTR_RO(traceid);
+
+static struct attribute *traceid_attrs[] = {
+ &dev_attr_traceid.attr,
+ NULL,
+};
+
+static struct attribute_group traceid_attr_grp = {
+ .attrs = traceid_attrs,
+};
+
static ssize_t dsb_mode_show(struct device *dev,
struct device_attribute *attr,
char *buf)
@@ -1369,6 +1391,12 @@ static const struct attribute_group *tpdm_attr_grps[] = {
&tpdm_cmb_patt_grp,
&tpdm_cmb_msr_grp,
&tpdm_mcmb_attr_grp,
+ &traceid_attr_grp,
+ NULL,
+};
+
+static const struct attribute_group *static_tpdm_attr_grps[] = {
+ &traceid_attr_grp,
NULL,
};
@@ -1402,6 +1430,7 @@ static int tpdm_probe(struct device *dev, struct resource *res)
if (ret)
return ret;
+ desc.access = CSDEV_ACCESS_IOMEM(base);
if (tpdm_has_dsb_dataset(drvdata))
of_property_read_u32(drvdata->dev->of_node,
"qcom,dsb-msrs-num", &drvdata->dsb_msr_num);
@@ -1416,7 +1445,7 @@ static int tpdm_probe(struct device *dev, struct resource *res)
}
/* Set up coresight component description */
- desc.name = coresight_alloc_device_name(&tpdm_devs, dev);
+ desc.name = coresight_alloc_device_name("tpdm", dev);
if (!desc.name)
return -ENOMEM;
desc.type = CORESIGHT_DEV_TYPE_SOURCE;
@@ -1424,9 +1453,10 @@ static int tpdm_probe(struct device *dev, struct resource *res)
desc.ops = &tpdm_cs_ops;
desc.pdata = dev->platform_data;
desc.dev = dev;
- desc.access = CSDEV_ACCESS_IOMEM(base);
if (res)
desc.groups = tpdm_attr_grps;
+ else
+ desc.groups = static_tpdm_attr_grps;
drvdata->csdev = coresight_register(&desc);
if (IS_ERR(drvdata->csdev))
return PTR_ERR(drvdata->csdev);
diff --git a/drivers/hwtracing/coresight/coresight-tpdm.h b/drivers/hwtracing/coresight/coresight-tpdm.h
index 2867f3ab8186..11da64e1ade8 100644
--- a/drivers/hwtracing/coresight/coresight-tpdm.h
+++ b/drivers/hwtracing/coresight/coresight-tpdm.h
@@ -300,6 +300,7 @@ struct cmb_dataset {
* @cmb Specifics associated to TPDM CMB.
* @dsb_msr_num Number of MSR supported by DSB TPDM
* @cmb_msr_num Number of MSR supported by CMB TPDM
+ * @traceid Trace ID of the path.
*/
struct tpdm_drvdata {
@@ -313,6 +314,7 @@ struct tpdm_drvdata {
struct cmb_dataset *cmb;
u32 dsb_msr_num;
u32 cmb_msr_num;
+ u8 traceid;
};
/* Enumerate members of various datasets */
diff --git a/drivers/hwtracing/coresight/coresight-tpiu.c b/drivers/hwtracing/coresight/coresight-tpiu.c
index aaa44bc521c3..b8560b140e0f 100644
--- a/drivers/hwtracing/coresight/coresight-tpiu.c
+++ b/drivers/hwtracing/coresight/coresight-tpiu.c
@@ -49,8 +49,6 @@
#define FFCR_FON_MAN BIT(6)
#define FFCR_STOP_FI BIT(12)
-DEFINE_CORESIGHT_DEVLIST(tpiu_devs, "tpiu");
-
/*
* @base: memory mapped base address for this component.
* @atclk: optional clock for the core parts of the TPIU.
@@ -134,7 +132,7 @@ static int __tpiu_probe(struct device *dev, struct resource *res)
struct coresight_desc desc = { 0 };
int ret;
- desc.name = coresight_alloc_device_name(&tpiu_devs, dev);
+ desc.name = coresight_alloc_device_name("tpiu", dev);
if (!desc.name)
return -ENOMEM;
diff --git a/drivers/hwtracing/coresight/ultrasoc-smb.c b/drivers/hwtracing/coresight/ultrasoc-smb.c
index 8f7922a5e534..5776f63468fa 100644
--- a/drivers/hwtracing/coresight/ultrasoc-smb.c
+++ b/drivers/hwtracing/coresight/ultrasoc-smb.c
@@ -17,8 +17,6 @@
#include "coresight-priv.h"
#include "ultrasoc-smb.h"
-DEFINE_CORESIGHT_DEVLIST(sink_devs, "ultra_smb");
-
#define ULTRASOC_SMB_DSM_UUID "82ae1283-7f6a-4cbe-aa06-53e8fb24db18"
static bool smb_buffer_not_empty(struct smb_drv_data *drvdata)
@@ -478,7 +476,7 @@ static int smb_register_sink(struct platform_device *pdev,
desc.pdata = pdata;
desc.dev = &pdev->dev;
desc.groups = smb_sink_groups;
- desc.name = coresight_alloc_device_name(&sink_devs, &pdev->dev);
+ desc.name = coresight_alloc_device_name("ultra_smb", &pdev->dev);
if (!desc.name) {
dev_err(&pdev->dev, "Failed to alloc coresight device name");
return -ENOMEM;
diff --git a/drivers/iio/accel/Kconfig b/drivers/iio/accel/Kconfig
index 3d3f8d8673dd..4094299e2ed8 100644
--- a/drivers/iio/accel/Kconfig
+++ b/drivers/iio/accel/Kconfig
@@ -158,24 +158,24 @@ config ADXL372
select IIO_TRIGGERED_BUFFER
config ADXL372_SPI
- tristate "Analog Devices ADXL372 3-Axis Accelerometer SPI Driver"
+ tristate "Analog Devices ADXL371/ADXL372 3-Axis Accelerometer SPI Driver"
depends on SPI
select ADXL372
select REGMAP_SPI
help
- Say yes here to add support for the Analog Devices ADXL372 triaxial
- acceleration sensor.
+ Say yes here to add support for the Analog Devices ADXL371/ADXL372
+ triaxial acceleration sensor.
To compile this driver as a module, choose M here: the
module will be called adxl372_spi.
config ADXL372_I2C
- tristate "Analog Devices ADXL372 3-Axis Accelerometer I2C Driver"
+ tristate "Analog Devices ADXL371/ADXL372 3-Axis Accelerometer I2C Driver"
depends on I2C
select ADXL372
select REGMAP_I2C
help
- Say yes here to add support for the Analog Devices ADXL372 triaxial
- acceleration sensor.
+ Say yes here to add support for the Analog Devices ADXL371/ADXL372
+ triaxial acceleration sensor.
To compile this driver as a module, choose M here: the
module will be called adxl372_i2c.
diff --git a/drivers/iio/accel/adis16201.c b/drivers/iio/accel/adis16201.c
index 5127e58eebc7..ba0f97944c6d 100644
--- a/drivers/iio/accel/adis16201.c
+++ b/drivers/iio/accel/adis16201.c
@@ -147,7 +147,7 @@ static int adis16201_read_raw(struct iio_dev *indio_dev,
/*
* The raw ADC value is 1278 when the temperature
* is 25 degrees and the scale factor per milli
- * degree celcius is -470.
+ * degree Celsius is -470.
*/
*val = 25000 / -470 - 1278;
return IIO_VAL_INT;
diff --git a/drivers/iio/accel/adis16209.c b/drivers/iio/accel/adis16209.c
index 41ffd92f27fd..04e169f221c4 100644
--- a/drivers/iio/accel/adis16209.c
+++ b/drivers/iio/accel/adis16209.c
@@ -186,7 +186,7 @@ static int adis16209_read_raw(struct iio_dev *indio_dev,
/*
* The raw ADC value is 0x4FE when the temperature
* is 45 degrees and the scale factor per milli
- * degree celcius is -470.
+ * degree Celsius is -470.
*/
*val = 25000 / -470 - 0x4FE;
return IIO_VAL_INT;
diff --git a/drivers/iio/accel/adxl313_core.c b/drivers/iio/accel/adxl313_core.c
index 83dcac17a042..bcc11dabdf22 100644
--- a/drivers/iio/accel/adxl313_core.c
+++ b/drivers/iio/accel/adxl313_core.c
@@ -8,6 +8,7 @@
*/
#include <linux/bitfield.h>
+#include <linux/cleanup.h>
#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/overflow.h>
@@ -356,19 +357,15 @@ static int adxl313_read_axis(struct adxl313_data *data,
{
int ret;
- mutex_lock(&data->lock);
+ guard(mutex)(&data->lock);
ret = regmap_bulk_read(data->regmap,
ADXL313_REG_DATA_AXIS(chan->address),
&data->transf_buf, sizeof(data->transf_buf));
if (ret)
- goto unlock_ret;
-
- ret = le16_to_cpu(data->transf_buf);
+ return ret;
-unlock_ret:
- mutex_unlock(&data->lock);
- return ret;
+ return le16_to_cpu(data->transf_buf);
}
static int adxl313_read_freq_avail(struct iio_dev *indio_dev,
diff --git a/drivers/iio/accel/adxl345_core.c b/drivers/iio/accel/adxl345_core.c
index 78e3f799ecc1..6c9080d88c60 100644
--- a/drivers/iio/accel/adxl345_core.c
+++ b/drivers/iio/accel/adxl345_core.c
@@ -213,6 +213,7 @@ static const struct iio_event_spec adxl345_events[] = {
.dir = IIO_EV_DIR_RISING,
.mask_shared_by_type =
BIT(IIO_EV_INFO_ENABLE) |
+ BIT(IIO_EV_INFO_SCALE) |
BIT(IIO_EV_INFO_VALUE),
},
{
@@ -221,6 +222,7 @@ static const struct iio_event_spec adxl345_events[] = {
.dir = IIO_EV_DIR_RISING,
.mask_shared_by_type =
BIT(IIO_EV_INFO_ENABLE) |
+ BIT(IIO_EV_INFO_SCALE) |
BIT(IIO_EV_INFO_VALUE),
},
{
@@ -228,14 +230,19 @@ static const struct iio_event_spec adxl345_events[] = {
.type = IIO_EV_TYPE_GESTURE,
.dir = IIO_EV_DIR_SINGLETAP,
.mask_separate = BIT(IIO_EV_INFO_ENABLE),
- .mask_shared_by_type = BIT(IIO_EV_INFO_VALUE) |
+ .mask_shared_by_type =
+ BIT(IIO_EV_INFO_SCALE) |
+ BIT(IIO_EV_INFO_VALUE) |
BIT(IIO_EV_INFO_TIMEOUT),
},
{
/* double tap */
.type = IIO_EV_TYPE_GESTURE,
.dir = IIO_EV_DIR_DOUBLETAP,
- .mask_shared_by_type = BIT(IIO_EV_INFO_ENABLE) |
+ .mask_shared_by_type =
+ BIT(IIO_EV_INFO_ENABLE) |
+ BIT(IIO_EV_INFO_SCALE) |
+ BIT(IIO_EV_INFO_VALUE) |
BIT(IIO_EV_INFO_RESET_TIMEOUT) |
BIT(IIO_EV_INFO_TAP2_MIN_DELAY),
},
@@ -274,6 +281,7 @@ static const struct iio_event_spec adxl345_fake_chan_events[] = {
.dir = IIO_EV_DIR_FALLING,
.mask_separate = BIT(IIO_EV_INFO_ENABLE),
.mask_shared_by_type =
+ BIT(IIO_EV_INFO_SCALE) |
BIT(IIO_EV_INFO_VALUE) |
BIT(IIO_EV_INFO_PERIOD),
},
@@ -283,6 +291,7 @@ static const struct iio_event_spec adxl345_fake_chan_events[] = {
.dir = IIO_EV_DIR_FALLING,
.mask_separate = BIT(IIO_EV_INFO_ENABLE),
.mask_shared_by_type =
+ BIT(IIO_EV_INFO_SCALE) |
BIT(IIO_EV_INFO_VALUE) |
BIT(IIO_EV_INFO_PERIOD),
},
@@ -1341,6 +1350,16 @@ static int adxl345_read_event_value(struct iio_dev *indio_dev,
unsigned int tap_threshold;
int ret;
+ /*
+ * The event threshold LSB is fixed at 62.5 mg/LSB
+ * 0.0625 * 9.80665 = 0.612915625 m/s^2
+ */
+ if (info == IIO_EV_INFO_SCALE) {
+ *val = 0;
+ *val2 = 612915;
+ return IIO_VAL_INT_PLUS_MICRO;
+ }
+
switch (type) {
case IIO_EV_TYPE_MAG:
return adxl345_read_mag_value(st, dir, info,
@@ -1355,12 +1374,6 @@ static int adxl345_read_event_value(struct iio_dev *indio_dev,
case IIO_EV_TYPE_GESTURE:
switch (info) {
case IIO_EV_INFO_VALUE:
- /*
- * The scale factor would be 62.5mg/LSB (i.e. 0xFF = 16g) but
- * not applied here. In context of this general purpose sensor,
- * what imports is rather signal intensity than the absolute
- * measured g value.
- */
ret = regmap_read(st->regmap, ADXL345_REG_THRESH_TAP,
&tap_threshold);
if (ret)
@@ -1401,6 +1414,9 @@ static int adxl345_write_event_value(struct iio_dev *indio_dev,
if (ret)
return ret;
+ if (info == IIO_EV_INFO_SCALE)
+ return -EINVAL;
+
switch (type) {
case IIO_EV_TYPE_MAG:
ret = adxl345_write_mag_value(st, dir, info,
diff --git a/drivers/iio/accel/adxl372.c b/drivers/iio/accel/adxl372.c
index 28a8793a53b6..545a21e5a308 100644
--- a/drivers/iio/accel/adxl372.c
+++ b/drivers/iio/accel/adxl372.c
@@ -1,12 +1,13 @@
// SPDX-License-Identifier: GPL-2.0+
/*
- * ADXL372 3-Axis Digital Accelerometer core driver
+ * ADXL371/ADXL372 3-Axis Digital Accelerometer core driver
*
* Copyright 2018 Analog Devices Inc.
*/
#include <linux/bitfield.h>
#include <linux/bitops.h>
+#include <linux/cleanup.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/module.h>
@@ -180,6 +181,16 @@ enum adxl372_odr {
ADXL372_ODR_1600HZ,
ADXL372_ODR_3200HZ,
ADXL372_ODR_6400HZ,
+ ADXL372_ODR_NUM
+};
+
+enum adxl371_odr {
+ ADXL371_ODR_320HZ,
+ ADXL371_ODR_640HZ,
+ ADXL371_ODR_1280HZ,
+ ADXL371_ODR_2560HZ,
+ ADXL371_ODR_5120HZ,
+ ADXL371_ODR_NUM
};
enum adxl372_bandwidth {
@@ -214,14 +225,67 @@ enum adxl372_fifo_mode {
ADXL372_FIFO_OLD_SAVED
};
-static const int adxl372_samp_freq_tbl[5] = {
- 400, 800, 1600, 3200, 6400,
+static const int adxl372_samp_freq_tbl[ADXL372_ODR_NUM] = {
+ [ADXL372_ODR_400HZ] = 400,
+ [ADXL372_ODR_800HZ] = 800,
+ [ADXL372_ODR_1600HZ] = 1600,
+ [ADXL372_ODR_3200HZ] = 3200,
+ [ADXL372_ODR_6400HZ] = 6400,
+};
+
+static const int adxl372_bw_freq_tbl[ADXL372_ODR_NUM] = {
+ [ADXL372_BW_200HZ] = 200,
+ [ADXL372_BW_400HZ] = 400,
+ [ADXL372_BW_800HZ] = 800,
+ [ADXL372_BW_1600HZ] = 1600,
+ [ADXL372_BW_3200HZ] = 3200,
+};
+
+static const int adxl371_samp_freq_tbl[ADXL371_ODR_NUM] = {
+ [ADXL371_ODR_320HZ] = 320,
+ [ADXL371_ODR_640HZ] = 640,
+ [ADXL371_ODR_1280HZ] = 1280,
+ [ADXL371_ODR_2560HZ] = 2560,
+ [ADXL371_ODR_5120HZ] = 5120,
};
-static const int adxl372_bw_freq_tbl[5] = {
- 200, 400, 800, 1600, 3200,
+static const int adxl371_bw_freq_tbl[ADXL371_ODR_NUM] = {
+ [ADXL371_ODR_320HZ] = 160,
+ [ADXL371_ODR_640HZ] = 320,
+ [ADXL371_ODR_1280HZ] = 640,
+ [ADXL371_ODR_2560HZ] = 1280,
+ [ADXL371_ODR_5120HZ] = 2560,
};
+const struct adxl372_chip_info adxl371_chip_info = {
+ .name = "adxl371",
+ .samp_freq_tbl = adxl371_samp_freq_tbl,
+ .bw_freq_tbl = adxl371_bw_freq_tbl,
+ .num_freqs = ARRAY_SIZE(adxl371_samp_freq_tbl),
+ .act_time_scale_us = 4125,
+ .act_time_scale_low_us = 8250,
+ .inact_time_scale_ms = 16,
+ .inact_time_scale_low_ms = 32,
+ .max_odr = ADXL371_ODR_5120HZ,
+ /* Silicon erratum (er001) causes FIFO data misalignment on ADXL371 */
+ .fifo_supported = false,
+};
+EXPORT_SYMBOL_NS_GPL(adxl371_chip_info, "IIO_ADXL372");
+
+const struct adxl372_chip_info adxl372_chip_info = {
+ .name = "adxl372",
+ .samp_freq_tbl = adxl372_samp_freq_tbl,
+ .bw_freq_tbl = adxl372_bw_freq_tbl,
+ .num_freqs = ARRAY_SIZE(adxl372_samp_freq_tbl),
+ .act_time_scale_us = 3300,
+ .act_time_scale_low_us = 6600,
+ .inact_time_scale_ms = 13,
+ .inact_time_scale_low_ms = 26,
+ .max_odr = ADXL372_ODR_6400HZ,
+ .fifo_supported = true,
+};
+EXPORT_SYMBOL_NS_GPL(adxl372_chip_info, "IIO_ADXL372");
+
struct adxl372_axis_lookup {
unsigned int bits;
enum adxl372_fifo_format fifo_format;
@@ -257,8 +321,12 @@ static const struct iio_event_spec adxl372_events[] = {
.modified = 1, \
.channel2 = IIO_MOD_##axis, \
.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 = \
+ BIT(IIO_CHAN_INFO_SCALE) | \
+ BIT(IIO_CHAN_INFO_SAMP_FREQ) | \
+ BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY), \
+ .info_mask_shared_by_type_available = \
+ BIT(IIO_CHAN_INFO_SAMP_FREQ) | \
BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY), \
.scan_index = index, \
.scan_type = { \
@@ -279,6 +347,7 @@ static const struct iio_chan_spec adxl372_channels[] = {
};
struct adxl372_state {
+ const struct adxl372_chip_info *chip_info;
int irq;
struct device *dev;
struct regmap *regmap;
@@ -336,18 +405,14 @@ static ssize_t adxl372_write_threshold_value(struct iio_dev *indio_dev, unsigned
struct adxl372_state *st = iio_priv(indio_dev);
int ret;
- mutex_lock(&st->threshold_m);
+ guard(mutex)(&st->threshold_m);
+
ret = regmap_write(st->regmap, addr, ADXL372_THRESH_VAL_H_SEL(threshold));
if (ret < 0)
- goto unlock;
-
- ret = regmap_update_bits(st->regmap, addr + 1, GENMASK(7, 5),
- ADXL372_THRESH_VAL_L_SEL(threshold) << 5);
-
-unlock:
- mutex_unlock(&st->threshold_m);
+ return ret;
- return ret;
+ return regmap_update_bits(st->regmap, addr + 1, GENMASK(7, 5),
+ ADXL372_THRESH_VAL_L_SEL(threshold) << 5);
}
static int adxl372_read_axis(struct adxl372_state *st, u8 addr)
@@ -471,13 +536,14 @@ static int adxl372_set_activity_time_ms(struct adxl372_state *st,
int ret;
/*
- * 3.3 ms per code is the scale factor of the TIME_ACT register for
- * ODR = 6400 Hz. It is 6.6 ms per code for ODR = 3200 Hz and below.
+ * The scale factor of the TIME_ACT register depends on the ODR.
+ * A higher scale factor is used at the maximum ODR and a lower
+ * one at all other rates.
*/
- if (st->odr == ADXL372_ODR_6400HZ)
- scale_factor = 3300;
+ if (st->odr == st->chip_info->max_odr)
+ scale_factor = st->chip_info->act_time_scale_us;
else
- scale_factor = 6600;
+ scale_factor = st->chip_info->act_time_scale_low_us;
reg_val = DIV_ROUND_CLOSEST(act_time_ms * 1000, scale_factor);
@@ -501,13 +567,14 @@ static int adxl372_set_inactivity_time_ms(struct adxl372_state *st,
int ret;
/*
- * 13 ms per code is the scale factor of the TIME_INACT register for
- * ODR = 6400 Hz. It is 26 ms per code for ODR = 3200 Hz and below.
+ * The scale factor of the TIME_INACT register depends on the ODR.
+ * A higher scale factor is used at the maximum ODR and a lower
+ * one at all other rates.
*/
- if (st->odr == ADXL372_ODR_6400HZ)
- scale_factor = 13;
+ if (st->odr == st->chip_info->max_odr)
+ scale_factor = st->chip_info->inact_time_scale_ms;
else
- scale_factor = 26;
+ scale_factor = st->chip_info->inact_time_scale_low_ms;
res = DIV_ROUND_CLOSEST(inact_time_ms, scale_factor);
reg_val_h = (res >> 8) & 0xFF;
@@ -717,7 +784,7 @@ static int adxl372_setup(struct adxl372_state *st)
if (ret < 0)
return ret;
- ret = adxl372_set_odr(st, ADXL372_ODR_6400HZ);
+ ret = adxl372_set_odr(st, st->chip_info->max_odr);
if (ret < 0)
return ret;
@@ -777,10 +844,10 @@ static int adxl372_read_raw(struct iio_dev *indio_dev,
*val2 = ADXL372_USCALE;
return IIO_VAL_INT_PLUS_MICRO;
case IIO_CHAN_INFO_SAMP_FREQ:
- *val = adxl372_samp_freq_tbl[st->odr];
+ *val = st->chip_info->samp_freq_tbl[st->odr];
return IIO_VAL_INT;
case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
- *val = adxl372_bw_freq_tbl[st->bw];
+ *val = st->chip_info->bw_freq_tbl[st->bw];
return IIO_VAL_INT;
}
@@ -796,23 +863,17 @@ static int adxl372_write_raw(struct iio_dev *indio_dev,
switch (info) {
case IIO_CHAN_INFO_SAMP_FREQ:
- odr_index = adxl372_find_closest_match(adxl372_samp_freq_tbl,
- ARRAY_SIZE(adxl372_samp_freq_tbl),
- val);
+ odr_index = adxl372_find_closest_match(st->chip_info->samp_freq_tbl,
+ st->chip_info->num_freqs,
+ val);
ret = adxl372_set_odr(st, odr_index);
if (ret < 0)
return ret;
- /*
- * The timer period depends on the ODR selected.
- * At 3200 Hz and below, it is 6.6 ms; at 6400 Hz, it is 3.3 ms
- */
+ /* Recalculate activity time as the timer period depends on ODR */
ret = adxl372_set_activity_time_ms(st, st->act_time_ms);
if (ret < 0)
return ret;
- /*
- * The timer period depends on the ODR selected.
- * At 3200 Hz and below, it is 26 ms; at 6400 Hz, it is 13 ms
- */
+ /* Recalculate inactivity time as the timer period depends on ODR */
ret = adxl372_set_inactivity_time_ms(st, st->inact_time_ms);
if (ret < 0)
return ret;
@@ -825,9 +886,9 @@ static int adxl372_write_raw(struct iio_dev *indio_dev,
return ret;
case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
- bw_index = adxl372_find_closest_match(adxl372_bw_freq_tbl,
- ARRAY_SIZE(adxl372_bw_freq_tbl),
- val);
+ bw_index = adxl372_find_closest_match(st->chip_info->bw_freq_tbl,
+ st->chip_info->num_freqs,
+ val);
return adxl372_set_bandwidth(st, bw_index);
default:
return -EINVAL;
@@ -957,24 +1018,6 @@ static int adxl372_write_event_config(struct iio_dev *indio_dev, const struct ii
return adxl372_set_interrupts(st, st->int1_bitmask, 0);
}
-static ssize_t adxl372_show_filter_freq_avail(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- struct iio_dev *indio_dev = dev_to_iio_dev(dev);
- struct adxl372_state *st = iio_priv(indio_dev);
- int i;
- size_t len = 0;
-
- for (i = 0; i <= st->odr; i++)
- len += scnprintf(buf + len, PAGE_SIZE - len,
- "%d ", adxl372_bw_freq_tbl[i]);
-
- buf[len - 1] = '\n';
-
- return len;
-}
-
static ssize_t adxl372_get_fifo_enabled(struct device *dev,
struct device_attribute *attr,
char *buf)
@@ -1142,25 +1185,38 @@ static const struct iio_trigger_ops adxl372_peak_data_trigger_ops = {
.set_trigger_state = adxl372_peak_dready_trig_set_state,
};
-static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("400 800 1600 3200 6400");
-static IIO_DEVICE_ATTR(in_accel_filter_low_pass_3db_frequency_available,
- 0444, adxl372_show_filter_freq_avail, NULL, 0);
-
-static struct attribute *adxl372_attributes[] = {
- &iio_const_attr_sampling_frequency_available.dev_attr.attr,
- &iio_dev_attr_in_accel_filter_low_pass_3db_frequency_available.dev_attr.attr,
- NULL,
-};
+static int adxl372_read_avail(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ const int **vals, int *type, int *length,
+ long mask)
+{
+ struct adxl372_state *st = iio_priv(indio_dev);
-static const struct attribute_group adxl372_attrs_group = {
- .attrs = adxl372_attributes,
-};
+ switch (mask) {
+ case IIO_CHAN_INFO_SAMP_FREQ:
+ *vals = st->chip_info->samp_freq_tbl;
+ *type = IIO_VAL_INT;
+ *length = st->chip_info->num_freqs;
+ return IIO_AVAIL_LIST;
+ case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
+ *vals = st->chip_info->bw_freq_tbl;
+ *type = IIO_VAL_INT;
+ /*
+ * Bandwidth cannot exceed half the sampling frequency
+ * (Nyquist), so limit available values based on current ODR.
+ */
+ *length = st->odr + 1;
+ return IIO_AVAIL_LIST;
+ default:
+ return -EINVAL;
+ }
+}
static const struct iio_info adxl372_info = {
.validate_trigger = &adxl372_validate_trigger,
- .attrs = &adxl372_attrs_group,
.read_raw = adxl372_read_raw,
.write_raw = adxl372_write_raw,
+ .read_avail = adxl372_read_avail,
.read_event_config = adxl372_read_event_config,
.write_event_config = adxl372_write_event_config,
.read_event_value = adxl372_read_event_value,
@@ -1175,8 +1231,57 @@ bool adxl372_readable_noinc_reg(struct device *dev, unsigned int reg)
}
EXPORT_SYMBOL_NS_GPL(adxl372_readable_noinc_reg, "IIO_ADXL372");
+static int adxl372_buffer_setup(struct iio_dev *indio_dev)
+{
+ struct adxl372_state *st = iio_priv(indio_dev);
+ struct device *dev = st->dev;
+ int ret;
+
+ ret = devm_iio_triggered_buffer_setup_ext(dev, indio_dev, NULL,
+ adxl372_trigger_handler,
+ IIO_BUFFER_DIRECTION_IN,
+ &adxl372_buffer_ops,
+ adxl372_fifo_attributes);
+ if (ret)
+ return ret;
+
+ if (!st->irq)
+ return 0;
+
+ st->dready_trig = devm_iio_trigger_alloc(dev, "%s-dev%d",
+ indio_dev->name,
+ iio_device_id(indio_dev));
+ if (!st->dready_trig)
+ return -ENOMEM;
+
+ st->peak_datardy_trig = devm_iio_trigger_alloc(dev, "%s-dev%d-peak",
+ indio_dev->name,
+ iio_device_id(indio_dev));
+ if (!st->peak_datardy_trig)
+ return -ENOMEM;
+
+ st->dready_trig->ops = &adxl372_trigger_ops;
+ st->peak_datardy_trig->ops = &adxl372_peak_data_trigger_ops;
+ iio_trigger_set_drvdata(st->dready_trig, indio_dev);
+ iio_trigger_set_drvdata(st->peak_datardy_trig, indio_dev);
+ ret = devm_iio_trigger_register(dev, st->dready_trig);
+ if (ret)
+ return ret;
+
+ ret = devm_iio_trigger_register(dev, st->peak_datardy_trig);
+ if (ret)
+ return ret;
+
+ indio_dev->trig = iio_trigger_get(st->dready_trig);
+
+ return devm_request_irq(dev, st->irq,
+ iio_trigger_generic_data_rdy_poll,
+ IRQF_TRIGGER_RISING | IRQF_NO_THREAD,
+ indio_dev->name, st->dready_trig);
+}
+
int adxl372_probe(struct device *dev, struct regmap *regmap,
- int irq, const char *name)
+ int irq, const struct adxl372_chip_info *chip_info)
{
struct iio_dev *indio_dev;
struct adxl372_state *st;
@@ -1192,15 +1297,21 @@ int adxl372_probe(struct device *dev, struct regmap *regmap,
st->dev = dev;
st->regmap = regmap;
st->irq = irq;
+ st->chip_info = chip_info;
mutex_init(&st->threshold_m);
indio_dev->channels = adxl372_channels;
indio_dev->num_channels = ARRAY_SIZE(adxl372_channels);
- indio_dev->available_scan_masks = adxl372_channel_masks;
- indio_dev->name = name;
+ indio_dev->name = chip_info->name;
indio_dev->info = &adxl372_info;
- indio_dev->modes = INDIO_DIRECT_MODE | INDIO_BUFFER_SOFTWARE;
+
+ if (chip_info->fifo_supported) {
+ indio_dev->modes = INDIO_DIRECT_MODE | INDIO_BUFFER_SOFTWARE;
+ indio_dev->available_scan_masks = adxl372_channel_masks;
+ } else {
+ indio_dev->modes = INDIO_DIRECT_MODE;
+ }
ret = adxl372_setup(st);
if (ret < 0) {
@@ -1208,48 +1319,8 @@ int adxl372_probe(struct device *dev, struct regmap *regmap,
return ret;
}
- ret = devm_iio_triggered_buffer_setup_ext(dev,
- indio_dev, NULL,
- adxl372_trigger_handler,
- IIO_BUFFER_DIRECTION_IN,
- &adxl372_buffer_ops,
- adxl372_fifo_attributes);
- if (ret < 0)
- return ret;
-
- if (st->irq) {
- st->dready_trig = devm_iio_trigger_alloc(dev,
- "%s-dev%d",
- indio_dev->name,
- iio_device_id(indio_dev));
- if (st->dready_trig == NULL)
- return -ENOMEM;
-
- st->peak_datardy_trig = devm_iio_trigger_alloc(dev,
- "%s-dev%d-peak",
- indio_dev->name,
- iio_device_id(indio_dev));
- if (!st->peak_datardy_trig)
- return -ENOMEM;
-
- st->dready_trig->ops = &adxl372_trigger_ops;
- st->peak_datardy_trig->ops = &adxl372_peak_data_trigger_ops;
- iio_trigger_set_drvdata(st->dready_trig, indio_dev);
- iio_trigger_set_drvdata(st->peak_datardy_trig, indio_dev);
- ret = devm_iio_trigger_register(dev, st->dready_trig);
- if (ret < 0)
- return ret;
-
- ret = devm_iio_trigger_register(dev, st->peak_datardy_trig);
- if (ret < 0)
- return ret;
-
- indio_dev->trig = iio_trigger_get(st->dready_trig);
-
- ret = devm_request_irq(dev, st->irq,
- iio_trigger_generic_data_rdy_poll,
- IRQF_TRIGGER_RISING | IRQF_NO_THREAD,
- indio_dev->name, st->dready_trig);
+ if (chip_info->fifo_supported) {
+ ret = adxl372_buffer_setup(indio_dev);
if (ret < 0)
return ret;
}
@@ -1259,5 +1330,6 @@ int adxl372_probe(struct device *dev, struct regmap *regmap,
EXPORT_SYMBOL_NS_GPL(adxl372_probe, "IIO_ADXL372");
MODULE_AUTHOR("Stefan Popa <stefan.popa@analog.com>");
-MODULE_DESCRIPTION("Analog Devices ADXL372 3-axis accelerometer driver");
+MODULE_AUTHOR("Antoniu Miclaus <antoniu.miclaus@analog.com>");
+MODULE_DESCRIPTION("Analog Devices ADXL371/ADXL372 3-axis accelerometer driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/iio/accel/adxl372.h b/drivers/iio/accel/adxl372.h
index 80a0aa9714fc..353a8b3a9d76 100644
--- a/drivers/iio/accel/adxl372.h
+++ b/drivers/iio/accel/adxl372.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0+ */
/*
- * ADXL372 3-Axis Digital Accelerometer
+ * ADXL371/ADXL372 3-Axis Digital Accelerometer
*
* Copyright 2018 Analog Devices Inc.
*/
@@ -10,8 +10,24 @@
#define ADXL372_REVID 0x03
+struct adxl372_chip_info {
+ const char *name;
+ const int *samp_freq_tbl;
+ const int *bw_freq_tbl;
+ unsigned int num_freqs;
+ unsigned int act_time_scale_us;
+ unsigned int act_time_scale_low_us;
+ unsigned int inact_time_scale_ms;
+ unsigned int inact_time_scale_low_ms;
+ unsigned int max_odr;
+ bool fifo_supported;
+};
+
+extern const struct adxl372_chip_info adxl371_chip_info;
+extern const struct adxl372_chip_info adxl372_chip_info;
+
int adxl372_probe(struct device *dev, struct regmap *regmap,
- int irq, const char *name);
+ int irq, const struct adxl372_chip_info *chip_info);
bool adxl372_readable_noinc_reg(struct device *dev, unsigned int reg);
#endif /* _ADXL372_H_ */
diff --git a/drivers/iio/accel/adxl372_i2c.c b/drivers/iio/accel/adxl372_i2c.c
index 186d4fe9a556..ca2cabf24938 100644
--- a/drivers/iio/accel/adxl372_i2c.c
+++ b/drivers/iio/accel/adxl372_i2c.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0+
/*
- * ADXL372 3-Axis Digital Accelerometer I2C driver
+ * ADXL371/ADXL372 3-Axis Digital Accelerometer I2C driver
*
* Copyright 2018 Analog Devices Inc.
*/
@@ -20,11 +20,13 @@ static const struct regmap_config adxl372_regmap_config = {
static int adxl372_i2c_probe(struct i2c_client *client)
{
- const struct i2c_device_id *id = i2c_client_get_device_id(client);
+ const struct adxl372_chip_info *chip_info;
struct regmap *regmap;
unsigned int regval;
int ret;
+ chip_info = i2c_get_match_data(client);
+
regmap = devm_regmap_init_i2c(client, &adxl372_regmap_config);
if (IS_ERR(regmap))
return PTR_ERR(regmap);
@@ -38,17 +40,19 @@ static int adxl372_i2c_probe(struct i2c_client *client)
dev_warn(&client->dev,
"I2C might not work properly with other devices on the bus");
- return adxl372_probe(&client->dev, regmap, client->irq, id->name);
+ return adxl372_probe(&client->dev, regmap, client->irq, chip_info);
}
static const struct i2c_device_id adxl372_i2c_id[] = {
- { "adxl372" },
+ { "adxl371", (kernel_ulong_t)&adxl371_chip_info },
+ { "adxl372", (kernel_ulong_t)&adxl372_chip_info },
{ }
};
MODULE_DEVICE_TABLE(i2c, adxl372_i2c_id);
static const struct of_device_id adxl372_of_match[] = {
- { .compatible = "adi,adxl372" },
+ { .compatible = "adi,adxl371", .data = &adxl371_chip_info },
+ { .compatible = "adi,adxl372", .data = &adxl372_chip_info },
{ }
};
MODULE_DEVICE_TABLE(of, adxl372_of_match);
@@ -65,6 +69,7 @@ static struct i2c_driver adxl372_i2c_driver = {
module_i2c_driver(adxl372_i2c_driver);
MODULE_AUTHOR("Stefan Popa <stefan.popa@analog.com>");
-MODULE_DESCRIPTION("Analog Devices ADXL372 3-axis accelerometer I2C driver");
+MODULE_AUTHOR("Antoniu Miclaus <antoniu.miclaus@analog.com>");
+MODULE_DESCRIPTION("Analog Devices ADXL371/ADXL372 3-axis accelerometer I2C driver");
MODULE_LICENSE("GPL");
MODULE_IMPORT_NS("IIO_ADXL372");
diff --git a/drivers/iio/accel/adxl372_spi.c b/drivers/iio/accel/adxl372_spi.c
index 39941b519c3b..1f9c1544e547 100644
--- a/drivers/iio/accel/adxl372_spi.c
+++ b/drivers/iio/accel/adxl372_spi.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0+
/*
- * ADXL372 3-Axis Digital Accelerometer SPI driver
+ * ADXL371/ADXL372 3-Axis Digital Accelerometer SPI driver
*
* Copyright 2018 Analog Devices Inc.
*/
@@ -22,24 +22,28 @@ static const struct regmap_config adxl372_spi_regmap_config = {
static int adxl372_spi_probe(struct spi_device *spi)
{
- const struct spi_device_id *id = spi_get_device_id(spi);
+ const struct adxl372_chip_info *chip_info;
struct regmap *regmap;
+ chip_info = spi_get_device_match_data(spi);
+
regmap = devm_regmap_init_spi(spi, &adxl372_spi_regmap_config);
if (IS_ERR(regmap))
return PTR_ERR(regmap);
- return adxl372_probe(&spi->dev, regmap, spi->irq, id->name);
+ return adxl372_probe(&spi->dev, regmap, spi->irq, chip_info);
}
static const struct spi_device_id adxl372_spi_id[] = {
- { "adxl372", 0 },
+ { "adxl371", (kernel_ulong_t)&adxl371_chip_info },
+ { "adxl372", (kernel_ulong_t)&adxl372_chip_info },
{ }
};
MODULE_DEVICE_TABLE(spi, adxl372_spi_id);
static const struct of_device_id adxl372_of_match[] = {
- { .compatible = "adi,adxl372" },
+ { .compatible = "adi,adxl371", .data = &adxl371_chip_info },
+ { .compatible = "adi,adxl372", .data = &adxl372_chip_info },
{ }
};
MODULE_DEVICE_TABLE(of, adxl372_of_match);
@@ -56,6 +60,7 @@ static struct spi_driver adxl372_spi_driver = {
module_spi_driver(adxl372_spi_driver);
MODULE_AUTHOR("Stefan Popa <stefan.popa@analog.com>");
-MODULE_DESCRIPTION("Analog Devices ADXL372 3-axis accelerometer SPI driver");
+MODULE_AUTHOR("Antoniu Miclaus <antoniu.miclaus@analog.com>");
+MODULE_DESCRIPTION("Analog Devices ADXL371/ADXL372 3-axis accelerometer SPI driver");
MODULE_LICENSE("GPL");
MODULE_IMPORT_NS("IIO_ADXL372");
diff --git a/drivers/iio/accel/adxl380.c b/drivers/iio/accel/adxl380.c
index a51d1d61c412..e7bb32fbc475 100644
--- a/drivers/iio/accel/adxl380.c
+++ b/drivers/iio/accel/adxl380.c
@@ -31,7 +31,7 @@
#define ADXL319_ID_VAL 382
#define ADXL380_DEVID_AD_REG 0x00
-#define ADLX380_PART_ID_REG 0x02
+#define ADXL380_PART_ID_REG 0x02
#define ADXL380_X_DATA_H_REG 0x15
#define ADXL380_Y_DATA_H_REG 0x17
@@ -1878,7 +1878,7 @@ static int adxl380_setup(struct iio_dev *indio_dev)
if (reg_val != ADXL380_DEVID_AD_VAL)
dev_warn(st->dev, "Unknown chip id %x\n", reg_val);
- ret = regmap_bulk_read(st->regmap, ADLX380_PART_ID_REG,
+ ret = regmap_bulk_read(st->regmap, ADXL380_PART_ID_REG,
&st->transf_buf, 2);
if (ret)
return ret;
diff --git a/drivers/iio/accel/bmc150-accel-core.c b/drivers/iio/accel/bmc150-accel-core.c
index 42ccf0316ce5..2398eb7e12cd 100644
--- a/drivers/iio/accel/bmc150-accel-core.c
+++ b/drivers/iio/accel/bmc150-accel-core.c
@@ -851,7 +851,7 @@ static ssize_t bmc150_accel_get_fifo_watermark(struct device *dev,
wm = data->watermark;
mutex_unlock(&data->mutex);
- return sprintf(buf, "%d\n", wm);
+ return sysfs_emit(buf, "%d\n", wm);
}
static ssize_t bmc150_accel_get_fifo_state(struct device *dev,
@@ -866,7 +866,7 @@ static ssize_t bmc150_accel_get_fifo_state(struct device *dev,
state = data->fifo_mode;
mutex_unlock(&data->mutex);
- return sprintf(buf, "%d\n", state);
+ return sysfs_emit(buf, "%d\n", state);
}
static const struct iio_mount_matrix *
diff --git a/drivers/iio/accel/sca3000.c b/drivers/iio/accel/sca3000.c
index 4a827be439a2..573831199bba 100644
--- a/drivers/iio/accel/sca3000.c
+++ b/drivers/iio/accel/sca3000.c
@@ -7,6 +7,7 @@
* See industrialio/accels/sca3000.h for comments.
*/
+#include <linux/cleanup.h>
#include <linux/interrupt.h>
#include <linux/fs.h>
#include <linux/device.h>
@@ -171,6 +172,7 @@ struct sca3000_state {
/**
* struct sca3000_chip_info - model dependent parameters
+ * @name: name of the chip
* @scale: scale * 10^-6
* @temp_output: some devices have temperature sensors.
* @measurement_mode_freq: normal mode sampling frequency
@@ -193,6 +195,7 @@ struct sca3000_state {
* sca3000 variant.
**/
struct sca3000_chip_info {
+ const char *name;
unsigned int scale;
bool temp_output;
int measurement_mode_freq;
@@ -207,69 +210,59 @@ struct sca3000_chip_info {
int mot_det_mult_y[7];
};
-enum sca3000_variant {
- d01,
- e02,
- e04,
- e05,
+static const struct sca3000_chip_info sca3000_chip_info_d01 = {
+ .name = "sca3000_d01",
+ .scale = 7357,
+ .temp_output = true,
+ .measurement_mode_freq = 250,
+ .measurement_mode_3db_freq = 45,
+ .option_mode_1 = SCA3000_OP_MODE_BYPASS,
+ .option_mode_1_freq = 250,
+ .option_mode_1_3db_freq = 70,
+ .mot_det_mult_xz = { 50, 100, 200, 350, 650, 1300 },
+ .mot_det_mult_y = { 50, 100, 150, 250, 450, 850, 1750 },
};
-/*
- * Note where option modes are not defined, the chip simply does not
- * support any.
- * Other chips in the sca3000 series use i2c and are not included here.
- *
- * Some of these devices are only listed in the family data sheet and
- * do not actually appear to be available.
- */
-static const struct sca3000_chip_info sca3000_spi_chip_info_tbl[] = {
- [d01] = {
- .scale = 7357,
- .temp_output = true,
- .measurement_mode_freq = 250,
- .measurement_mode_3db_freq = 45,
- .option_mode_1 = SCA3000_OP_MODE_BYPASS,
- .option_mode_1_freq = 250,
- .option_mode_1_3db_freq = 70,
- .mot_det_mult_xz = {50, 100, 200, 350, 650, 1300},
- .mot_det_mult_y = {50, 100, 150, 250, 450, 850, 1750},
- },
- [e02] = {
- .scale = 9810,
- .measurement_mode_freq = 125,
- .measurement_mode_3db_freq = 40,
- .option_mode_1 = SCA3000_OP_MODE_NARROW,
- .option_mode_1_freq = 63,
- .option_mode_1_3db_freq = 11,
- .mot_det_mult_xz = {100, 150, 300, 550, 1050, 2050},
- .mot_det_mult_y = {50, 100, 200, 350, 700, 1350, 2700},
- },
- [e04] = {
- .scale = 19620,
- .measurement_mode_freq = 100,
- .measurement_mode_3db_freq = 38,
- .option_mode_1 = SCA3000_OP_MODE_NARROW,
- .option_mode_1_freq = 50,
- .option_mode_1_3db_freq = 9,
- .option_mode_2 = SCA3000_OP_MODE_WIDE,
- .option_mode_2_freq = 400,
- .option_mode_2_3db_freq = 70,
- .mot_det_mult_xz = {200, 300, 600, 1100, 2100, 4100},
- .mot_det_mult_y = {100, 200, 400, 7000, 1400, 2700, 54000},
- },
- [e05] = {
- .scale = 61313,
- .measurement_mode_freq = 200,
- .measurement_mode_3db_freq = 60,
- .option_mode_1 = SCA3000_OP_MODE_NARROW,
- .option_mode_1_freq = 50,
- .option_mode_1_3db_freq = 9,
- .option_mode_2 = SCA3000_OP_MODE_WIDE,
- .option_mode_2_freq = 400,
- .option_mode_2_3db_freq = 75,
- .mot_det_mult_xz = {600, 900, 1700, 3200, 6100, 11900},
- .mot_det_mult_y = {300, 600, 1200, 2000, 4100, 7800, 15600},
- },
+static const struct sca3000_chip_info sca3000_chip_info_e02 = {
+ .name = "sca3000_e02",
+ .scale = 9810,
+ .measurement_mode_freq = 125,
+ .measurement_mode_3db_freq = 40,
+ .option_mode_1 = SCA3000_OP_MODE_NARROW,
+ .option_mode_1_freq = 63,
+ .option_mode_1_3db_freq = 11,
+ .mot_det_mult_xz = { 100, 150, 300, 550, 1050, 2050 },
+ .mot_det_mult_y = { 50, 100, 200, 350, 700, 1350, 2700 },
+};
+
+static const struct sca3000_chip_info sca3000_chip_info_e04 = {
+ .name = "sca3000_e04",
+ .scale = 19620,
+ .measurement_mode_freq = 100,
+ .measurement_mode_3db_freq = 38,
+ .option_mode_1 = SCA3000_OP_MODE_NARROW,
+ .option_mode_1_freq = 50,
+ .option_mode_1_3db_freq = 9,
+ .option_mode_2 = SCA3000_OP_MODE_WIDE,
+ .option_mode_2_freq = 400,
+ .option_mode_2_3db_freq = 70,
+ .mot_det_mult_xz = { 200, 300, 600, 1100, 2100, 4100 },
+ .mot_det_mult_y = { 100, 200, 400, 7000, 1400, 2700, 54000 },
+};
+
+static const struct sca3000_chip_info sca3000_chip_info_e05 = {
+ .name = "sca3000_e05",
+ .scale = 61313,
+ .measurement_mode_freq = 200,
+ .measurement_mode_3db_freq = 60,
+ .option_mode_1 = SCA3000_OP_MODE_NARROW,
+ .option_mode_1_freq = 50,
+ .option_mode_1_3db_freq = 9,
+ .option_mode_2 = SCA3000_OP_MODE_WIDE,
+ .option_mode_2_freq = 400,
+ .option_mode_2_3db_freq = 75,
+ .mot_det_mult_xz = { 600, 900, 1700, 3200, 6100, 11900 },
+ .mot_det_mult_y = { 300, 600, 1200, 2000, 4100, 7800, 15600 },
};
static int sca3000_write_reg(struct sca3000_state *st, u8 address, u8 val)
@@ -1435,24 +1428,42 @@ static const struct iio_info sca3000_info = {
.write_event_config = &sca3000_write_event_config,
};
-static int sca3000_probe(struct spi_device *spi)
+static void sca3000_stop_all_interrupts(void *data)
{
+ struct iio_dev *indio_dev = data;
+ struct sca3000_state *st = iio_priv(indio_dev);
int ret;
+
+ guard(mutex)(&st->lock);
+
+ ret = sca3000_read_data_short(st, SCA3000_REG_INT_MASK_ADDR, 1);
+ if (ret)
+ return;
+
+ sca3000_write_reg(st, SCA3000_REG_INT_MASK_ADDR,
+ (st->rx[0] &
+ ~(SCA3000_REG_INT_MASK_RING_THREE_QUARTER |
+ SCA3000_REG_INT_MASK_RING_HALF |
+ SCA3000_REG_INT_MASK_ALL_INTS)));
+}
+
+static int sca3000_probe(struct spi_device *spi)
+{
+ struct device *dev = &spi->dev;
struct sca3000_state *st;
struct iio_dev *indio_dev;
+ int ret;
- indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
+ indio_dev = devm_iio_device_alloc(dev, sizeof(*st));
if (!indio_dev)
return -ENOMEM;
st = iio_priv(indio_dev);
- spi_set_drvdata(spi, indio_dev);
st->us = spi;
mutex_init(&st->lock);
- st->info = &sca3000_spi_chip_info_tbl[spi_get_device_id(spi)
- ->driver_data];
+ st->info = spi_get_device_match_data(spi);
- indio_dev->name = spi_get_device_id(spi)->name;
+ indio_dev->name = st->info->name;
indio_dev->info = &sca3000_info;
if (st->info->temp_output) {
indio_dev->channels = sca3000_channels_with_temp;
@@ -1464,78 +1475,39 @@ static int sca3000_probe(struct spi_device *spi)
}
indio_dev->modes = INDIO_DIRECT_MODE;
- ret = devm_iio_kfifo_buffer_setup(&spi->dev, indio_dev,
- &sca3000_ring_setup_ops);
+ ret = devm_iio_kfifo_buffer_setup(dev, indio_dev, &sca3000_ring_setup_ops);
if (ret)
return ret;
if (spi->irq) {
- ret = request_threaded_irq(spi->irq,
- NULL,
- &sca3000_event_handler,
- IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
- "sca3000",
- indio_dev);
+ ret = devm_request_threaded_irq(dev, spi->irq, NULL,
+ &sca3000_event_handler,
+ IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
+ "sca3000",
+ indio_dev);
if (ret)
return ret;
}
ret = sca3000_clean_setup(st);
if (ret)
- goto error_free_irq;
+ return ret;
ret = sca3000_print_rev(indio_dev);
if (ret)
- goto error_free_irq;
-
- ret = iio_device_register(indio_dev);
- if (ret)
- goto error_free_irq;
-
- return 0;
-
-error_free_irq:
- if (spi->irq)
- free_irq(spi->irq, indio_dev);
-
- return ret;
-}
-
-static int sca3000_stop_all_interrupts(struct sca3000_state *st)
-{
- int ret;
+ return ret;
- mutex_lock(&st->lock);
- ret = sca3000_read_data_short(st, SCA3000_REG_INT_MASK_ADDR, 1);
+ ret = devm_add_action_or_reset(dev, sca3000_stop_all_interrupts, indio_dev);
if (ret)
- goto error_ret;
- ret = sca3000_write_reg(st, SCA3000_REG_INT_MASK_ADDR,
- (st->rx[0] &
- ~(SCA3000_REG_INT_MASK_RING_THREE_QUARTER |
- SCA3000_REG_INT_MASK_RING_HALF |
- SCA3000_REG_INT_MASK_ALL_INTS)));
-error_ret:
- mutex_unlock(&st->lock);
- return ret;
-}
-
-static void sca3000_remove(struct spi_device *spi)
-{
- struct iio_dev *indio_dev = spi_get_drvdata(spi);
- struct sca3000_state *st = iio_priv(indio_dev);
-
- iio_device_unregister(indio_dev);
+ return ret;
- /* Must ensure no interrupts can be generated after this! */
- sca3000_stop_all_interrupts(st);
- if (spi->irq)
- free_irq(spi->irq, indio_dev);
+ return devm_iio_device_register(dev, indio_dev);
}
static const struct spi_device_id sca3000_id[] = {
- {"sca3000_d01", d01},
- {"sca3000_e02", e02},
- {"sca3000_e04", e04},
- {"sca3000_e05", e05},
+ { "sca3000_d01", (kernel_ulong_t)&sca3000_chip_info_d01 },
+ { "sca3000_e02", (kernel_ulong_t)&sca3000_chip_info_e02 },
+ { "sca3000_e04", (kernel_ulong_t)&sca3000_chip_info_e04 },
+ { "sca3000_e05", (kernel_ulong_t)&sca3000_chip_info_e05 },
{ }
};
MODULE_DEVICE_TABLE(spi, sca3000_id);
@@ -1545,7 +1517,6 @@ static struct spi_driver sca3000_driver = {
.name = "sca3000",
},
.probe = sca3000_probe,
- .remove = sca3000_remove,
.id_table = sca3000_id,
};
module_spi_driver(sca3000_driver);
diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
index 60038ae8dfc4..a9dedbb8eb46 100644
--- a/drivers/iio/adc/Kconfig
+++ b/drivers/iio/adc/Kconfig
@@ -60,9 +60,14 @@ config AD4030
tristate "Analog Devices AD4030 ADC Driver"
depends on SPI
depends on GPIOLIB
+ depends on PWM
select REGMAP
select IIO_BUFFER
+ select IIO_BUFFER_DMA
+ select IIO_BUFFER_DMAENGINE
select IIO_TRIGGERED_BUFFER
+ select SPI_OFFLOAD
+ select SPI_OFFLOAD_TRIGGER_PWM
help
Say yes here to build support for Analog Devices AD4030 and AD4630 high speed
SPI analog to digital converters (ADC).
@@ -413,8 +418,10 @@ config AD7768_1
select REGMAP_SPI
select RATIONAL
select IIO_BUFFER
+ select IIO_BUFFER_DMAENGINE
select IIO_TRIGGER
select IIO_TRIGGERED_BUFFER
+ select SPI_OFFLOAD
help
Say yes here to build support for Analog Devices AD7768-1 SPI
simultaneously sampling sigma-delta analog to digital converter (ADC).
@@ -1366,6 +1373,32 @@ config QCOM_SPMI_ADC5
To compile this driver as a module, choose M here: the module will
be called qcom-spmi-adc5.
+config QCOM_SPMI_ADC5_GEN3
+ tristate "Qualcomm Technologies Inc. SPMI PMIC5 GEN3 ADC"
+ depends on SPMI && THERMAL
+ select REGMAP_SPMI
+ select QCOM_VADC_COMMON
+ select AUXILIARY_BUS
+ help
+ IIO Voltage PMIC5 Gen3 ADC driver for Qualcomm Technologies Inc.
+
+ The driver supports reading multiple channels. The ADC is a 16-bit
+ sigma-delta ADC. The hardware supports calibrated results for
+ conversion requests and clients include reading phone power supply
+ voltage, on board system thermistors connected to the PMIC ADC,
+ PMIC die temperature, charger temperature, battery current, USB
+ voltage input and voltage signals connected to supported PMIC GPIO
+ pins. The hardware supports internal pull-up for thermistors and can
+ choose between a 30k, 100k or 400k ohm pull up using the ADC channels.
+
+ In addition, the same driver supports ADC thermal monitoring devices
+ too. They appear as thermal zones with multiple trip points. A thermal
+ client sets threshold temperature for both warm and cool trips and
+ gets updated when a threshold is reached.
+
+ To compile this driver as a module, choose M here: the module will
+ be called qcom-spmi-adc5-gen3.
+
config RCAR_GYRO_ADC
tristate "Renesas R-Car GyroADC driver"
depends on ARCH_RCAR_GEN2 || COMPILE_TEST
diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile
index c76550415ff1..097357d146ba 100644
--- a/drivers/iio/adc/Makefile
+++ b/drivers/iio/adc/Makefile
@@ -116,6 +116,7 @@ obj-$(CONFIG_PAC1934) += pac1934.o
obj-$(CONFIG_PALMAS_GPADC) += palmas_gpadc.o
obj-$(CONFIG_QCOM_PM8XXX_XOADC) += qcom-pm8xxx-xoadc.o
obj-$(CONFIG_QCOM_SPMI_ADC5) += qcom-spmi-adc5.o
+obj-$(CONFIG_QCOM_SPMI_ADC5_GEN3) += qcom-spmi-adc5-gen3.o
obj-$(CONFIG_QCOM_SPMI_IADC) += qcom-spmi-iadc.o
obj-$(CONFIG_QCOM_SPMI_RRADC) += qcom-spmi-rradc.o
obj-$(CONFIG_QCOM_SPMI_VADC) += qcom-spmi-vadc.o
diff --git a/drivers/iio/adc/ad4030.c b/drivers/iio/adc/ad4030.c
index 68446db9bef1..9c5f19321e3b 100644
--- a/drivers/iio/adc/ad4030.c
+++ b/drivers/iio/adc/ad4030.c
@@ -14,15 +14,26 @@
*/
#include <linux/bitfield.h>
+#include <linux/cleanup.h>
#include <linux/clk.h>
-#include <linux/iio/iio.h>
-#include <linux/iio/trigger_consumer.h>
-#include <linux/iio/triggered_buffer.h>
+#include <linux/dmaengine.h>
+#include <linux/limits.h>
+#include <linux/log2.h>
+#include <linux/math64.h>
+#include <linux/minmax.h>
+#include <linux/pwm.h>
#include <linux/regmap.h>
#include <linux/regulator/consumer.h>
+#include <linux/spi/offload/consumer.h>
#include <linux/spi/spi.h>
#include <linux/unaligned.h>
#include <linux/units.h>
+#include <linux/types.h>
+
+#include <linux/iio/buffer-dmaengine.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/trigger_consumer.h>
+#include <linux/iio/triggered_buffer.h>
#define AD4030_REG_INTERFACE_CONFIG_A 0x00
#define AD4030_REG_INTERFACE_CONFIG_A_SW_RESET (BIT(0) | BIT(7))
@@ -37,6 +48,8 @@
#define AD4030_REG_CHIP_GRADE_AD4630_24_GRADE 0x00
#define AD4030_REG_CHIP_GRADE_AD4632_16_GRADE 0x05
#define AD4030_REG_CHIP_GRADE_AD4632_24_GRADE 0x02
+#define AD4030_REG_CHIP_GRADE_ADAQ4216_GRADE 0x1E
+#define AD4030_REG_CHIP_GRADE_ADAQ4224_GRADE 0x1C
#define AD4030_REG_CHIP_GRADE_MASK_CHIP_GRADE GENMASK(7, 3)
#define AD4030_REG_SCRATCH_PAD 0x0A
#define AD4030_REG_SPI_REVISION 0x0B
@@ -111,6 +124,12 @@
#define AD4632_TCYC_NS 2000
#define AD4632_TCYC_ADJUSTED_NS (AD4632_TCYC_NS - AD4030_TCNVL_NS)
#define AD4030_TRESET_COM_DELAY_MS 750
+/* Datasheet says 9.8ns, so use the closest integer value */
+#define AD4030_TQUIET_CNV_DELAY_NS 10
+
+/* HARDWARE_GAIN */
+#define ADAQ4616_PGA_PINS 2
+#define ADAQ4616_PGA_GAIN_MAX_NANO (NANO * 2 / 3)
enum ad4030_out_mode {
AD4030_OUT_DATA_MD_DIFF,
@@ -132,15 +151,35 @@ enum {
AD4030_SCAN_TYPE_AVG,
};
+/*
+ * Gains computed as fractions of 1000 so they can be expressed by integers.
+ */
+static const int adaq4216_hw_gains_vpv[] = {
+ 1 * MILLI / 3, /* 0.333 */
+ 5 * MILLI / 9, /* 0.555 */
+ 20 * MILLI / 9, /* 0.2222 */
+ 20 * MILLI / 3, /* 0.6666 */
+};
+
+static const int adaq4216_hw_gains_frac[][2] = {
+ { 1, 3 }, /* 1/3 V/V gain */
+ { 5, 9 }, /* 5/9 V/V gain */
+ { 20, 9 }, /* 20/9 V/V gain */
+ { 20, 3 }, /* 20/3 V/V gain */
+};
+
struct ad4030_chip_info {
const char *name;
const unsigned long *available_masks;
const struct iio_chan_spec channels[AD4030_MAX_IIO_CHANNEL_NB];
+ const struct iio_chan_spec offload_channels[AD4030_MAX_IIO_CHANNEL_NB];
u8 grade;
u8 precision_bits;
+ bool has_pga;
/* Number of hardware channels */
int num_voltage_inputs;
unsigned int tcyc_ns;
+ unsigned int max_sample_rate_hz;
};
struct ad4030_state {
@@ -153,6 +192,18 @@ struct ad4030_state {
int offset_avail[3];
unsigned int avg_log2;
enum ad4030_out_mode mode;
+ /* Offload sampling */
+ struct spi_transfer offload_xfer;
+ struct spi_message offload_msg;
+ struct spi_offload *offload;
+ struct spi_offload_trigger *offload_trigger;
+ struct spi_offload_trigger_config offload_trigger_config;
+ struct pwm_device *cnv_trigger;
+ size_t scale_avail_size;
+ struct pwm_waveform cnv_wf;
+ unsigned int scale_avail[ARRAY_SIZE(adaq4216_hw_gains_vpv)][2];
+ struct gpio_descs *pga_gpios;
+ unsigned int pga_index;
/*
* DMA (thus cache coherency maintenance) requires the transfer buffers
@@ -209,8 +260,9 @@ struct ad4030_state {
* - voltage0-voltage1
* - voltage2-voltage3
*/
-#define AD4030_CHAN_DIFF(_idx, _scan_type) { \
+#define __AD4030_CHAN_DIFF(_idx, _scan_type, _offload, _pga) { \
.info_mask_shared_by_all = \
+ (_offload ? BIT(IIO_CHAN_INFO_SAMP_FREQ) : 0) | \
BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), \
.info_mask_shared_by_all_available = \
BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), \
@@ -219,6 +271,7 @@ struct ad4030_state {
BIT(IIO_CHAN_INFO_CALIBBIAS) | \
BIT(IIO_CHAN_INFO_RAW), \
.info_mask_separate_available = BIT(IIO_CHAN_INFO_CALIBBIAS) | \
+ (_pga ? BIT(IIO_CHAN_INFO_SCALE) : 0) | \
BIT(IIO_CHAN_INFO_CALIBSCALE), \
.type = IIO_VOLTAGE, \
.indexed = 1, \
@@ -232,10 +285,33 @@ struct ad4030_state {
.num_ext_scan_type = ARRAY_SIZE(_scan_type), \
}
+#define AD4030_CHAN_DIFF(_idx, _scan_type) \
+ __AD4030_CHAN_DIFF(_idx, _scan_type, 0, 0)
+
+#define AD4030_OFFLOAD_CHAN_DIFF(_idx, _scan_type) \
+ __AD4030_CHAN_DIFF(_idx, _scan_type, 1, 0)
+
+#define ADAQ4216_CHAN_DIFF(_idx, _scan_type) \
+ __AD4030_CHAN_DIFF(_idx, _scan_type, 0, 1)
+
+#define ADAQ4216_OFFLOAD_CHAN_DIFF(_idx, _scan_type) \
+ __AD4030_CHAN_DIFF(_idx, _scan_type, 1, 1)
+
+/*
+ * AD4030 can average over 2^N samples, where N = 1, 2, 3, ..., 16.
+ * We use N = 0 to mean no sample averaging.
+ */
static const int ad4030_average_modes[] = {
- 1, 2, 4, 8, 16, 32, 64, 128,
- 256, 512, 1024, 2048, 4096, 8192, 16384, 32768,
- 65536,
+ BIT(0), /* No sampling average */
+ BIT(1), BIT(2), BIT(3), BIT(4),
+ BIT(5), BIT(6), BIT(7), BIT(8),
+ BIT(9), BIT(10), BIT(11), BIT(12),
+ BIT(13), BIT(14), BIT(15), BIT(16),
+};
+
+static const struct spi_offload_config ad4030_offload_config = {
+ .capability_flags = SPI_OFFLOAD_CAP_TRIGGER |
+ SPI_OFFLOAD_CAP_RX_STREAM_DMA,
};
static int ad4030_enter_config_mode(struct ad4030_state *st)
@@ -377,6 +453,65 @@ static const struct regmap_config ad4030_regmap_config = {
.max_register = AD4030_REG_DIG_ERR,
};
+static void ad4030_fill_scale_avail(struct ad4030_state *st)
+{
+ unsigned int mag_bits, int_part, fract_part;
+ u64 range;
+
+ /*
+ * The maximum precision of differential channels is retrieved from the
+ * chip properties. The output code of differential channels is in two's
+ * complement format (i.e. signed), so the MSB is the sign bit and only
+ * (precision_bits - 1) bits express voltage magnitude.
+ */
+ mag_bits = st->chip->precision_bits - 1;
+
+ for (unsigned int i = 0; i < ARRAY_SIZE(adaq4216_hw_gains_frac); i++) {
+ range = mult_frac(st->vref_uv, adaq4216_hw_gains_frac[i][1],
+ adaq4216_hw_gains_frac[i][0]);
+ /*
+ * If range were in mV, we would multiply it by NANO below.
+ * Though, range is in µV so multiply it by MICRO only so the
+ * result after right shift and division scales output codes to
+ * millivolts.
+ */
+ int_part = div_u64_rem((range * MICRO) >> mag_bits, NANO, &fract_part);
+ st->scale_avail[i][0] = int_part;
+ st->scale_avail[i][1] = fract_part;
+ }
+}
+
+static int ad4030_set_pga_gain(struct ad4030_state *st)
+{
+ DECLARE_BITMAP(bitmap, ADAQ4616_PGA_PINS) = { };
+
+ bitmap_write(bitmap, st->pga_index, 0, ADAQ4616_PGA_PINS);
+
+ return gpiod_multi_set_value_cansleep(st->pga_gpios, bitmap);
+}
+
+static int ad4030_set_pga(struct iio_dev *indio_dev, int gain_int, int gain_fract)
+{
+ struct ad4030_state *st = iio_priv(indio_dev);
+ unsigned int mag_bits = st->chip->precision_bits - 1;
+ unsigned int tmp;
+ u64 gain_nano;
+
+ if (!st->pga_gpios)
+ return -EINVAL;
+
+ gain_nano = gain_int * NANO + gain_fract;
+ if (!in_range(gain_nano, 1, ADAQ4616_PGA_GAIN_MAX_NANO))
+ return -EINVAL;
+
+ tmp = DIV_ROUND_CLOSEST_ULL(gain_nano << mag_bits, NANO);
+ gain_nano = DIV_ROUND_CLOSEST(st->vref_uv, tmp);
+ st->pga_index = find_closest(gain_nano, adaq4216_hw_gains_vpv,
+ ARRAY_SIZE(adaq4216_hw_gains_vpv));
+
+ return ad4030_set_pga_gain(st);
+}
+
static int ad4030_get_chan_scale(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int *val,
@@ -389,6 +524,13 @@ static int ad4030_get_chan_scale(struct iio_dev *indio_dev,
if (IS_ERR(scan_type))
return PTR_ERR(scan_type);
+ /* The LSB of the 8-bit common-mode data is always vref/256. */
+ if (st->chip->has_pga && scan_type->realbits != 8) {
+ *val = st->scale_avail[st->pga_index][0];
+ *val2 = st->scale_avail[st->pga_index][1];
+ return IIO_VAL_INT_PLUS_NANO;
+ }
+
if (chan->differential)
*val = (st->vref_uv * 2) / MILLI;
else
@@ -451,6 +593,102 @@ static int ad4030_get_chan_calibbias(struct iio_dev *indio_dev,
}
}
+static void ad4030_get_sampling_freq(struct ad4030_state *st, int *freq)
+{
+ struct spi_offload_trigger_config *config = &st->offload_trigger_config;
+
+ /*
+ * Conversion data is fetched from the device when the offload transfer
+ * is triggered. Thus, provide the SPI offload trigger frequency as the
+ * sampling frequency.
+ */
+ *freq = config->periodic.frequency_hz;
+}
+
+static int ad4030_update_conversion_rate(struct ad4030_state *st,
+ unsigned int freq_hz, unsigned int avg_log2)
+{
+ struct spi_offload_trigger_config *config = &st->offload_trigger_config;
+ unsigned int offload_period_ns, cnv_rate_hz;
+ struct pwm_waveform cnv_wf = { };
+ u64 target = AD4030_TCNVH_NS;
+ u64 offload_offset_ns;
+ int ret;
+
+ /*
+ * When averaging/oversampling over N samples, we fire the offload
+ * trigger once at every N pulses of the CNV signal. Conversely, the CNV
+ * signal needs to be N times faster than the offload trigger. Take that
+ * into account to correctly re-evaluate both the PWM waveform connected
+ * to CNV and the SPI offload trigger.
+ */
+ cnv_rate_hz = freq_hz << avg_log2;
+
+ cnv_wf.period_length_ns = DIV_ROUND_CLOSEST(NSEC_PER_SEC, cnv_rate_hz);
+ /*
+ * The datasheet lists a minimum time of 9.8 ns, but no maximum. If the
+ * rounded PWM's value is less than 10, increase the target value by 10
+ * and attempt to round the waveform again, until the value is at least
+ * 10 ns. Use a separate variable to represent the target in case the
+ * rounding is severe enough to keep putting the first few results under
+ * the minimum 10ns condition checked by the while loop.
+ */
+ do {
+ cnv_wf.duty_length_ns = target;
+ ret = pwm_round_waveform_might_sleep(st->cnv_trigger, &cnv_wf);
+ if (ret)
+ return ret;
+ target += AD4030_TCNVH_NS;
+ } while (cnv_wf.duty_length_ns < AD4030_TCNVH_NS);
+
+ /*
+ * The CNV waveform period (period_length_ns) might get rounded down by
+ * pwm_round_waveform_might_sleep(). Check the resultant PWM period
+ * is not smaller than the minimum data conversion cycle time.
+ */
+ if (!in_range(cnv_wf.period_length_ns, AD4030_TCYC_NS, INT_MAX))
+ return -EINVAL;
+
+ offload_period_ns = DIV_ROUND_CLOSEST(NSEC_PER_SEC, freq_hz);
+
+ config->periodic.frequency_hz = DIV_ROUND_UP(HZ_PER_GHZ, offload_period_ns);
+
+ /*
+ * The hardware does the capture on zone 2 (when SPI trigger PWM
+ * is used). This means that the SPI trigger signal should happen at
+ * tsync + tquiet_con_delay being tsync the conversion signal period
+ * and tquiet_con_delay 9.8ns. Hence set the PWM phase accordingly.
+ *
+ * The PWM waveform API only supports nanosecond resolution right now,
+ * so round this setting to the closest available value.
+ */
+ offload_offset_ns = AD4030_TQUIET_CNV_DELAY_NS;
+ do {
+ config->periodic.offset_ns = offload_offset_ns;
+ ret = spi_offload_trigger_validate(st->offload_trigger, config);
+ if (ret)
+ return ret;
+ offload_offset_ns += AD4030_TQUIET_CNV_DELAY_NS;
+ } while (config->periodic.offset_ns < AD4030_TQUIET_CNV_DELAY_NS);
+
+ st->cnv_wf = cnv_wf;
+
+ return 0;
+}
+
+static int ad4030_set_sampling_freq(struct iio_dev *indio_dev, int freq_hz)
+{
+ struct ad4030_state *st = iio_priv(indio_dev);
+
+ if (freq_hz == 0)
+ return -EINVAL;
+
+ if (!in_range(freq_hz, 0, st->chip->max_sample_rate_hz))
+ return -ERANGE;
+
+ return ad4030_update_conversion_rate(st, freq_hz, st->avg_log2);
+}
+
static int ad4030_set_chan_calibscale(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int gain_int,
@@ -510,11 +748,30 @@ static int ad4030_set_avg_frame_len(struct iio_dev *dev, int avg_val)
struct ad4030_state *st = iio_priv(dev);
unsigned int avg_log2 = ilog2(avg_val);
unsigned int last_avg_idx = ARRAY_SIZE(ad4030_average_modes) - 1;
+ int freq_hz;
int ret;
if (avg_val < 0 || avg_val > ad4030_average_modes[last_avg_idx])
return -EINVAL;
+ if (st->offload_trigger) {
+ /*
+ * The sample averaging and sampling frequency configurations
+ * are mutually dependent on each other. That's because the
+ * effective data sample rate is fCNV / 2^N, where N is the
+ * number of samples being averaged.
+ *
+ * When SPI offload is supported and we have control over the
+ * sample rate, the conversion start signal (CNV) and the SPI
+ * offload trigger frequencies must be re-evaluated so data is
+ * fetched only after 'avg_val' conversions.
+ */
+ ad4030_get_sampling_freq(st, &freq_hz);
+ ret = ad4030_update_conversion_rate(st, freq_hz, avg_log2);
+ if (ret)
+ return ret;
+ }
+
ret = regmap_write(st->regmap, AD4030_REG_AVG,
AD4030_REG_AVG_MASK_AVG_SYNC |
FIELD_PREP(AD4030_REG_AVG_MASK_AVG_VAL, avg_log2));
@@ -623,7 +880,7 @@ static int ad4030_conversion(struct iio_dev *indio_dev)
/* Add one byte if we are using a differential + common byte mode */
bytes_to_read += (st->mode == AD4030_OUT_DATA_MD_24_DIFF_8_COM ||
st->mode == AD4030_OUT_DATA_MD_16_DIFF_8_COM) ? 1 : 0;
- /* Mulitiply by the number of hardware channels */
+ /* Multiply by the number of hardware channels */
bytes_to_read *= st->chip->num_voltage_inputs;
for (i = 0; i < cnv_nb; i++) {
@@ -742,6 +999,15 @@ static int ad4030_read_avail(struct iio_dev *indio_dev,
*length = ARRAY_SIZE(ad4030_average_modes);
return IIO_AVAIL_LIST;
+ case IIO_CHAN_INFO_SCALE:
+ if (st->scale_avail_size == 1)
+ *vals = (int *)st->scale_avail[st->pga_index];
+ else
+ *vals = (int *)st->scale_avail;
+ *length = st->scale_avail_size * 2; /* print int and nano part */
+ *type = IIO_VAL_INT_PLUS_NANO;
+ return IIO_AVAIL_LIST;
+
default:
return -EINVAL;
}
@@ -767,6 +1033,10 @@ static int ad4030_read_raw_dispatch(struct iio_dev *indio_dev,
*val = BIT(st->avg_log2);
return IIO_VAL_INT;
+ case IIO_CHAN_INFO_SAMP_FREQ:
+ ad4030_get_sampling_freq(st, val);
+ return IIO_VAL_INT;
+
default:
return -EINVAL;
}
@@ -807,6 +1077,12 @@ static int ad4030_write_raw_dispatch(struct iio_dev *indio_dev,
case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
return ad4030_set_avg_frame_len(indio_dev, val);
+ case IIO_CHAN_INFO_SAMP_FREQ:
+ return ad4030_set_sampling_freq(indio_dev, val);
+
+ case IIO_CHAN_INFO_SCALE:
+ return ad4030_set_pga(indio_dev, val, val2);
+
default:
return -EINVAL;
}
@@ -828,6 +1104,17 @@ static int ad4030_write_raw(struct iio_dev *indio_dev,
return ret;
}
+static int ad4030_write_raw_get_fmt(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan, long mask)
+{
+ switch (mask) {
+ case IIO_CHAN_INFO_SCALE:
+ return IIO_VAL_INT_PLUS_NANO;
+ default:
+ return IIO_VAL_INT_PLUS_MICRO;
+ }
+}
+
static int ad4030_reg_access(struct iio_dev *indio_dev, unsigned int reg,
unsigned int writeval, unsigned int *readval)
{
@@ -874,6 +1161,7 @@ static const struct iio_info ad4030_iio_info = {
.read_avail = ad4030_read_avail,
.read_raw = ad4030_read_raw,
.write_raw = ad4030_write_raw,
+ .write_raw_get_fmt = &ad4030_write_raw_get_fmt,
.debugfs_reg_access = ad4030_reg_access,
.read_label = ad4030_read_label,
.get_current_scan_type = ad4030_get_current_scan_type,
@@ -896,6 +1184,86 @@ static const struct iio_buffer_setup_ops ad4030_buffer_setup_ops = {
.validate_scan_mask = ad4030_validate_scan_mask,
};
+static void ad4030_prepare_offload_msg(struct iio_dev *indio_dev)
+{
+ struct ad4030_state *st = iio_priv(indio_dev);
+ u8 offload_bpw;
+
+ if (st->mode == AD4030_OUT_DATA_MD_30_AVERAGED_DIFF)
+ offload_bpw = 32;
+ else
+ offload_bpw = st->chip->precision_bits;
+
+ st->offload_xfer.bits_per_word = offload_bpw;
+ st->offload_xfer.len = spi_bpw_to_bytes(offload_bpw);
+ st->offload_xfer.offload_flags = SPI_OFFLOAD_XFER_RX_STREAM;
+ spi_message_init_with_transfers(&st->offload_msg, &st->offload_xfer, 1);
+}
+
+static int ad4030_offload_buffer_postenable(struct iio_dev *indio_dev)
+{
+ struct ad4030_state *st = iio_priv(indio_dev);
+ unsigned int reg_modes;
+ int ret;
+
+ /*
+ * When data from 2 analog input channels is output through a single
+ * bus line (interleaved mode (LANE_MD == 0b11)) and gets pushed through
+ * DMA, extra hardware is required to do the de-interleaving. While we
+ * don't support such hardware configurations, disallow interleaved mode
+ * when using SPI offload.
+ */
+ ret = regmap_read(st->regmap, AD4030_REG_MODES, &reg_modes);
+ if (ret)
+ return ret;
+
+ if (st->chip->num_voltage_inputs > 1 &&
+ FIELD_GET(AD4030_REG_MODES_MASK_LANE_MODE, reg_modes) == AD4030_LANE_MD_INTERLEAVED)
+ return -EINVAL;
+
+ ad4030_prepare_offload_msg(indio_dev);
+ st->offload_msg.offload = st->offload;
+ ret = spi_optimize_message(st->spi, &st->offload_msg);
+ if (ret)
+ return ret;
+
+ ret = pwm_set_waveform_might_sleep(st->cnv_trigger, &st->cnv_wf, false);
+ if (ret)
+ goto out_unoptimize;
+
+ ret = spi_offload_trigger_enable(st->offload, st->offload_trigger,
+ &st->offload_trigger_config);
+ if (ret)
+ goto out_pwm_disable;
+
+ return 0;
+
+out_pwm_disable:
+ pwm_disable(st->cnv_trigger);
+out_unoptimize:
+ spi_unoptimize_message(&st->offload_msg);
+
+ return ret;
+}
+
+static int ad4030_offload_buffer_predisable(struct iio_dev *indio_dev)
+{
+ struct ad4030_state *st = iio_priv(indio_dev);
+
+ spi_offload_trigger_disable(st->offload, st->offload_trigger);
+
+ pwm_disable(st->cnv_trigger);
+
+ spi_unoptimize_message(&st->offload_msg);
+
+ return 0;
+}
+
+static const struct iio_buffer_setup_ops ad4030_offload_buffer_setup_ops = {
+ .postenable = &ad4030_offload_buffer_postenable,
+ .predisable = &ad4030_offload_buffer_predisable,
+};
+
static int ad4030_regulators_get(struct ad4030_state *st)
{
struct device *dev = &st->spi->dev;
@@ -965,6 +1333,24 @@ static int ad4030_detect_chip_info(const struct ad4030_state *st)
return 0;
}
+static int ad4030_pwm_get(struct ad4030_state *st)
+{
+ struct device *dev = &st->spi->dev;
+
+ st->cnv_trigger = devm_pwm_get(dev, NULL);
+ if (IS_ERR(st->cnv_trigger))
+ return dev_err_probe(dev, PTR_ERR(st->cnv_trigger),
+ "Failed to get CNV PWM\n");
+
+ /*
+ * Preemptively disable the PWM, since we only want to enable it with
+ * the buffer.
+ */
+ pwm_disable(st->cnv_trigger);
+
+ return 0;
+}
+
static int ad4030_config(struct ad4030_state *st)
{
int ret;
@@ -992,6 +1378,51 @@ static int ad4030_config(struct ad4030_state *st)
return 0;
}
+static int ad4030_spi_offload_setup(struct iio_dev *indio_dev,
+ struct ad4030_state *st)
+{
+ struct device *dev = &st->spi->dev;
+ struct dma_chan *rx_dma;
+
+ indio_dev->setup_ops = &ad4030_offload_buffer_setup_ops;
+
+ st->offload_trigger = devm_spi_offload_trigger_get(dev, st->offload,
+ SPI_OFFLOAD_TRIGGER_PERIODIC);
+ if (IS_ERR(st->offload_trigger))
+ return dev_err_probe(dev, PTR_ERR(st->offload_trigger),
+ "failed to get offload trigger\n");
+
+ st->offload_trigger_config.type = SPI_OFFLOAD_TRIGGER_PERIODIC;
+
+ rx_dma = devm_spi_offload_rx_stream_request_dma_chan(dev, st->offload);
+ if (IS_ERR(rx_dma))
+ return dev_err_probe(dev, PTR_ERR(rx_dma),
+ "failed to get offload RX DMA\n");
+
+ return devm_iio_dmaengine_buffer_setup_with_handle(dev, indio_dev, rx_dma,
+ IIO_BUFFER_DIRECTION_IN);
+}
+
+static int ad4030_setup_pga(struct device *dev, struct iio_dev *indio_dev,
+ struct ad4030_state *st)
+{
+ /* Setup GPIOs for PGA control */
+ st->pga_gpios = devm_gpiod_get_array(dev, "pga", GPIOD_OUT_LOW);
+ if (IS_ERR(st->pga_gpios))
+ return dev_err_probe(dev, PTR_ERR(st->pga_gpios),
+ "Failed to get PGA gpios.\n");
+
+ if (st->pga_gpios->ndescs != ADAQ4616_PGA_PINS)
+ return dev_err_probe(dev, -EINVAL,
+ "Expected %d GPIOs for PGA control.\n",
+ ADAQ4616_PGA_PINS);
+
+ st->scale_avail_size = ARRAY_SIZE(adaq4216_hw_gains_vpv);
+ st->pga_index = 0;
+
+ return 0;
+}
+
static int ad4030_probe(struct spi_device *spi)
{
struct device *dev = &spi->dev;
@@ -1034,6 +1465,14 @@ static int ad4030_probe(struct spi_device *spi)
if (ret)
return ret;
+ if (st->chip->has_pga) {
+ ret = ad4030_setup_pga(dev, indio_dev, st);
+ if (ret)
+ return ret;
+
+ ad4030_fill_scale_avail(st);
+ }
+
ret = ad4030_config(st);
if (ret)
return ret;
@@ -1043,24 +1482,58 @@ static int ad4030_probe(struct spi_device *spi)
return dev_err_probe(dev, PTR_ERR(st->cnv_gpio),
"Failed to get cnv gpio\n");
- /*
- * One hardware channel is split in two software channels when using
- * common byte mode. Add one more channel for the timestamp.
- */
- indio_dev->num_channels = 2 * st->chip->num_voltage_inputs + 1;
indio_dev->name = st->chip->name;
indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->info = &ad4030_iio_info;
- indio_dev->channels = st->chip->channels;
indio_dev->available_scan_masks = st->chip->available_masks;
- ret = devm_iio_triggered_buffer_setup(dev, indio_dev,
- iio_pollfunc_store_time,
- ad4030_trigger_handler,
- &ad4030_buffer_setup_ops);
- if (ret)
- return dev_err_probe(dev, ret,
- "Failed to setup triggered buffer\n");
+ st->offload = devm_spi_offload_get(dev, spi, &ad4030_offload_config);
+ ret = PTR_ERR_OR_ZERO(st->offload);
+ /* Fall back to low speed usage when no SPI offload is available. */
+ if (ret == -ENODEV) {
+ /*
+ * One hardware channel is split in two software channels when
+ * using common byte mode. Add one more channel for the timestamp.
+ */
+ indio_dev->num_channels = 2 * st->chip->num_voltage_inputs + 1;
+ indio_dev->channels = st->chip->channels;
+
+ ret = devm_iio_triggered_buffer_setup(dev, indio_dev,
+ iio_pollfunc_store_time,
+ ad4030_trigger_handler,
+ &ad4030_buffer_setup_ops);
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "Failed to setup triggered buffer\n");
+ } else if (ret) {
+ return dev_err_probe(dev, ret, "failed to get offload\n");
+ } else {
+ /*
+ * Offloaded SPI transfers can't support software timestamp so
+ * no additional timestamp channel is added.
+ */
+ indio_dev->num_channels = st->chip->num_voltage_inputs;
+ indio_dev->channels = st->chip->offload_channels;
+ ret = ad4030_spi_offload_setup(indio_dev, st);
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "Failed to setup SPI offload\n");
+
+ ret = ad4030_pwm_get(st);
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to get PWM\n");
+
+ /*
+ * Start with a slower sampling rate so there is some room for
+ * adjusting the sample averaging and the sampling frequency
+ * without hitting the maximum conversion rate.
+ */
+ ret = ad4030_update_conversion_rate(st, st->chip->max_sample_rate_hz >> 4,
+ st->avg_log2);
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "Failed to set offload samp freq\n");
+ }
return devm_iio_device_register(dev, indio_dev);
}
@@ -1098,11 +1571,28 @@ static const struct iio_scan_type ad4030_24_scan_types[] = {
},
};
-static const struct iio_scan_type ad4030_16_scan_types[] = {
+static const struct iio_scan_type ad4030_24_offload_scan_types[] = {
[AD4030_SCAN_TYPE_NORMAL] = {
.sign = 's',
+ .realbits = 24,
.storagebits = 32,
+ .shift = 0,
+ .endianness = IIO_CPU,
+ },
+ [AD4030_SCAN_TYPE_AVG] = {
+ .sign = 's',
+ .realbits = 30,
+ .storagebits = 32,
+ .shift = 2,
+ .endianness = IIO_CPU,
+ },
+};
+
+static const struct iio_scan_type ad4030_16_scan_types[] = {
+ [AD4030_SCAN_TYPE_NORMAL] = {
+ .sign = 's',
.realbits = 16,
+ .storagebits = 32,
.shift = 16,
.endianness = IIO_BE,
},
@@ -1115,6 +1605,23 @@ static const struct iio_scan_type ad4030_16_scan_types[] = {
}
};
+static const struct iio_scan_type ad4030_16_offload_scan_types[] = {
+ [AD4030_SCAN_TYPE_NORMAL] = {
+ .sign = 's',
+ .realbits = 16,
+ .storagebits = 32,
+ .shift = 0,
+ .endianness = IIO_CPU,
+ },
+ [AD4030_SCAN_TYPE_AVG] = {
+ .sign = 's',
+ .realbits = 30,
+ .storagebits = 32,
+ .shift = 2,
+ .endianness = IIO_CPU,
+ },
+};
+
static const struct ad4030_chip_info ad4030_24_chip_info = {
.name = "ad4030-24",
.available_masks = ad4030_channel_masks,
@@ -1123,10 +1630,14 @@ static const struct ad4030_chip_info ad4030_24_chip_info = {
AD4030_CHAN_CMO(1, 0),
IIO_CHAN_SOFT_TIMESTAMP(2),
},
+ .offload_channels = {
+ AD4030_OFFLOAD_CHAN_DIFF(0, ad4030_24_offload_scan_types),
+ },
.grade = AD4030_REG_CHIP_GRADE_AD4030_24_GRADE,
.precision_bits = 24,
.num_voltage_inputs = 1,
.tcyc_ns = AD4030_TCYC_ADJUSTED_NS,
+ .max_sample_rate_hz = 2 * HZ_PER_MHZ,
};
static const struct ad4030_chip_info ad4630_16_chip_info = {
@@ -1139,10 +1650,15 @@ static const struct ad4030_chip_info ad4630_16_chip_info = {
AD4030_CHAN_CMO(3, 1),
IIO_CHAN_SOFT_TIMESTAMP(4),
},
+ .offload_channels = {
+ AD4030_OFFLOAD_CHAN_DIFF(0, ad4030_16_offload_scan_types),
+ AD4030_OFFLOAD_CHAN_DIFF(1, ad4030_16_offload_scan_types),
+ },
.grade = AD4030_REG_CHIP_GRADE_AD4630_16_GRADE,
.precision_bits = 16,
.num_voltage_inputs = 2,
.tcyc_ns = AD4030_TCYC_ADJUSTED_NS,
+ .max_sample_rate_hz = 2 * HZ_PER_MHZ,
};
static const struct ad4030_chip_info ad4630_24_chip_info = {
@@ -1155,10 +1671,15 @@ static const struct ad4030_chip_info ad4630_24_chip_info = {
AD4030_CHAN_CMO(3, 1),
IIO_CHAN_SOFT_TIMESTAMP(4),
},
+ .offload_channels = {
+ AD4030_OFFLOAD_CHAN_DIFF(0, ad4030_24_offload_scan_types),
+ AD4030_OFFLOAD_CHAN_DIFF(1, ad4030_24_offload_scan_types),
+ },
.grade = AD4030_REG_CHIP_GRADE_AD4630_24_GRADE,
.precision_bits = 24,
.num_voltage_inputs = 2,
.tcyc_ns = AD4030_TCYC_ADJUSTED_NS,
+ .max_sample_rate_hz = 2 * HZ_PER_MHZ,
};
static const struct ad4030_chip_info ad4632_16_chip_info = {
@@ -1171,10 +1692,15 @@ static const struct ad4030_chip_info ad4632_16_chip_info = {
AD4030_CHAN_CMO(3, 1),
IIO_CHAN_SOFT_TIMESTAMP(4),
},
+ .offload_channels = {
+ AD4030_OFFLOAD_CHAN_DIFF(0, ad4030_16_offload_scan_types),
+ AD4030_OFFLOAD_CHAN_DIFF(1, ad4030_16_offload_scan_types),
+ },
.grade = AD4030_REG_CHIP_GRADE_AD4632_16_GRADE,
.precision_bits = 16,
.num_voltage_inputs = 2,
.tcyc_ns = AD4632_TCYC_ADJUSTED_NS,
+ .max_sample_rate_hz = 500 * HZ_PER_KHZ,
};
static const struct ad4030_chip_info ad4632_24_chip_info = {
@@ -1187,10 +1713,53 @@ static const struct ad4030_chip_info ad4632_24_chip_info = {
AD4030_CHAN_CMO(3, 1),
IIO_CHAN_SOFT_TIMESTAMP(4),
},
+ .offload_channels = {
+ AD4030_OFFLOAD_CHAN_DIFF(0, ad4030_24_offload_scan_types),
+ AD4030_OFFLOAD_CHAN_DIFF(1, ad4030_24_offload_scan_types),
+ },
.grade = AD4030_REG_CHIP_GRADE_AD4632_24_GRADE,
.precision_bits = 24,
.num_voltage_inputs = 2,
.tcyc_ns = AD4632_TCYC_ADJUSTED_NS,
+ .max_sample_rate_hz = 500 * HZ_PER_KHZ,
+};
+
+static const struct ad4030_chip_info adaq4216_chip_info = {
+ .name = "adaq4216",
+ .available_masks = ad4030_channel_masks,
+ .channels = {
+ ADAQ4216_CHAN_DIFF(0, ad4030_16_scan_types),
+ AD4030_CHAN_CMO(1, 0),
+ IIO_CHAN_SOFT_TIMESTAMP(2),
+ },
+ .offload_channels = {
+ ADAQ4216_OFFLOAD_CHAN_DIFF(0, ad4030_16_offload_scan_types),
+ },
+ .grade = AD4030_REG_CHIP_GRADE_ADAQ4216_GRADE,
+ .precision_bits = 16,
+ .has_pga = true,
+ .num_voltage_inputs = 1,
+ .tcyc_ns = AD4030_TCYC_ADJUSTED_NS,
+ .max_sample_rate_hz = 2 * HZ_PER_MHZ,
+};
+
+static const struct ad4030_chip_info adaq4224_chip_info = {
+ .name = "adaq4224",
+ .available_masks = ad4030_channel_masks,
+ .channels = {
+ ADAQ4216_CHAN_DIFF(0, ad4030_24_scan_types),
+ AD4030_CHAN_CMO(1, 0),
+ IIO_CHAN_SOFT_TIMESTAMP(2),
+ },
+ .offload_channels = {
+ ADAQ4216_OFFLOAD_CHAN_DIFF(0, ad4030_24_offload_scan_types),
+ },
+ .grade = AD4030_REG_CHIP_GRADE_ADAQ4224_GRADE,
+ .precision_bits = 24,
+ .has_pga = true,
+ .num_voltage_inputs = 1,
+ .tcyc_ns = AD4030_TCYC_ADJUSTED_NS,
+ .max_sample_rate_hz = 2 * HZ_PER_MHZ,
};
static const struct spi_device_id ad4030_id_table[] = {
@@ -1199,6 +1768,8 @@ static const struct spi_device_id ad4030_id_table[] = {
{ "ad4630-24", (kernel_ulong_t)&ad4630_24_chip_info },
{ "ad4632-16", (kernel_ulong_t)&ad4632_16_chip_info },
{ "ad4632-24", (kernel_ulong_t)&ad4632_24_chip_info },
+ { "adaq4216", (kernel_ulong_t)&adaq4216_chip_info },
+ { "adaq4224", (kernel_ulong_t)&adaq4224_chip_info },
{ }
};
MODULE_DEVICE_TABLE(spi, ad4030_id_table);
@@ -1209,6 +1780,8 @@ static const struct of_device_id ad4030_of_match[] = {
{ .compatible = "adi,ad4630-24", .data = &ad4630_24_chip_info },
{ .compatible = "adi,ad4632-16", .data = &ad4632_16_chip_info },
{ .compatible = "adi,ad4632-24", .data = &ad4632_24_chip_info },
+ { .compatible = "adi,adaq4216", .data = &adaq4216_chip_info },
+ { .compatible = "adi,adaq4224", .data = &adaq4224_chip_info },
{ }
};
MODULE_DEVICE_TABLE(of, ad4030_of_match);
@@ -1226,3 +1799,4 @@ module_spi_driver(ad4030_driver);
MODULE_AUTHOR("Esteban Blanc <eblanc@baylibre.com>");
MODULE_DESCRIPTION("Analog Devices AD4630 ADC family driver");
MODULE_LICENSE("GPL");
+MODULE_IMPORT_NS("IIO_DMAENGINE_BUFFER");
diff --git a/drivers/iio/adc/ad4062.c b/drivers/iio/adc/ad4062.c
index 8b03736d55fc..222499a45b9b 100644
--- a/drivers/iio/adc/ad4062.c
+++ b/drivers/iio/adc/ad4062.c
@@ -1197,11 +1197,14 @@ static int ad4062_write_event_value(struct iio_dev *indio_dev,
* The AD4062 in burst averaging mode increases realbits from 16-bits to
* 20-bits, increasing the storagebits from 16-bits to 32-bits.
*/
-static inline size_t ad4062_sizeof_storagebits(struct ad4062_state *st)
+static inline int ad4062_sizeof_storagebits(struct ad4062_state *st)
{
const struct iio_scan_type *scan_type =
iio_get_current_scan_type(st->indio_dev, st->chip->channels);
+ if (IS_ERR(scan_type))
+ return PTR_ERR(scan_type);
+
return BITS_TO_BYTES(scan_type->storagebits);
}
@@ -1231,7 +1234,12 @@ static int pm_ad4062_triggered_buffer_postenable(struct ad4062_state *st)
if (ret)
return ret;
- st->conv_sizeof = ad4062_sizeof_storagebits(st);
+ ret = ad4062_sizeof_storagebits(st);
+ if (ret < 0)
+ return ret;
+
+ st->conv_sizeof = ret;
+
st->conv_addr = ad4062_get_conv_addr(st, st->conv_sizeof);
/* CONV_READ requires read to trigger first sample. */
struct i3c_xfer xfer_sample[2] = {
diff --git a/drivers/iio/adc/ad4080.c b/drivers/iio/adc/ad4080.c
index 7cf3b6ed7940..204ad198342b 100644
--- a/drivers/iio/adc/ad4080.c
+++ b/drivers/iio/adc/ad4080.c
@@ -127,10 +127,13 @@
#define AD4080_SPI_READ BIT(7)
#define AD4080_CHIP_ID 0x0050
#define AD4081_CHIP_ID 0x0051
+#define AD4082_CHIP_ID 0x0052
#define AD4083_CHIP_ID 0x0053
#define AD4084_CHIP_ID 0x0054
+#define AD4085_CHIP_ID 0x0055
#define AD4086_CHIP_ID 0x0056
#define AD4087_CHIP_ID 0x0057
+#define AD4088_CHIP_ID 0x0058
#define AD4080_LVDS_CNV_CLK_CNT_MAX 7
@@ -185,7 +188,6 @@ struct ad4080_state {
*/
struct mutex lock;
unsigned int num_lanes;
- unsigned int dec_rate;
unsigned long clk_rate;
enum ad4080_filter_type filter_type;
bool lvds_cnv_en;
@@ -442,14 +444,20 @@ static const struct iio_chan_spec ad4080_channel = AD4080_CHANNEL_DEFINE(20, 32)
static const struct iio_chan_spec ad4081_channel = AD4080_CHANNEL_DEFINE(20, 32);
+static const struct iio_chan_spec ad4082_channel = AD4080_CHANNEL_DEFINE(20, 32);
+
static const struct iio_chan_spec ad4083_channel = AD4080_CHANNEL_DEFINE(16, 16);
static const struct iio_chan_spec ad4084_channel = AD4080_CHANNEL_DEFINE(16, 16);
+static const struct iio_chan_spec ad4085_channel = AD4080_CHANNEL_DEFINE(16, 16);
+
static const struct iio_chan_spec ad4086_channel = AD4080_CHANNEL_DEFINE(14, 16);
static const struct iio_chan_spec ad4087_channel = AD4080_CHANNEL_DEFINE(14, 16);
+static const struct iio_chan_spec ad4088_channel = AD4080_CHANNEL_DEFINE(14, 16);
+
static const struct ad4080_chip_info ad4080_chip_info = {
.name = "ad4080",
.product_id = AD4080_CHIP_ID,
@@ -470,6 +478,16 @@ static const struct ad4080_chip_info ad4081_chip_info = {
.lvds_cnv_clk_cnt_max = 2,
};
+static const struct ad4080_chip_info ad4082_chip_info = {
+ .name = "ad4082",
+ .product_id = AD4082_CHIP_ID,
+ .scale_table = ad4080_scale_table,
+ .num_scales = ARRAY_SIZE(ad4080_scale_table),
+ .num_channels = 1,
+ .channels = &ad4082_channel,
+ .lvds_cnv_clk_cnt_max = 8,
+};
+
static const struct ad4080_chip_info ad4083_chip_info = {
.name = "ad4083",
.product_id = AD4083_CHIP_ID,
@@ -490,6 +508,16 @@ static const struct ad4080_chip_info ad4084_chip_info = {
.lvds_cnv_clk_cnt_max = 2,
};
+static const struct ad4080_chip_info ad4085_chip_info = {
+ .name = "ad4085",
+ .product_id = AD4085_CHIP_ID,
+ .scale_table = ad4080_scale_table,
+ .num_scales = ARRAY_SIZE(ad4080_scale_table),
+ .num_channels = 1,
+ .channels = &ad4085_channel,
+ .lvds_cnv_clk_cnt_max = 8,
+};
+
static const struct ad4080_chip_info ad4086_chip_info = {
.name = "ad4086",
.product_id = AD4086_CHIP_ID,
@@ -510,6 +538,16 @@ static const struct ad4080_chip_info ad4087_chip_info = {
.lvds_cnv_clk_cnt_max = 1,
};
+static const struct ad4080_chip_info ad4088_chip_info = {
+ .name = "ad4088",
+ .product_id = AD4088_CHIP_ID,
+ .scale_table = ad4080_scale_table,
+ .num_scales = ARRAY_SIZE(ad4080_scale_table),
+ .num_channels = 1,
+ .channels = &ad4088_channel,
+ .lvds_cnv_clk_cnt_max = 8,
+};
+
static int ad4080_setup(struct iio_dev *indio_dev)
{
struct ad4080_state *st = iio_priv(indio_dev);
@@ -666,10 +704,13 @@ static int ad4080_probe(struct spi_device *spi)
static const struct spi_device_id ad4080_id[] = {
{ "ad4080", (kernel_ulong_t)&ad4080_chip_info },
{ "ad4081", (kernel_ulong_t)&ad4081_chip_info },
+ { "ad4082", (kernel_ulong_t)&ad4082_chip_info },
{ "ad4083", (kernel_ulong_t)&ad4083_chip_info },
{ "ad4084", (kernel_ulong_t)&ad4084_chip_info },
+ { "ad4085", (kernel_ulong_t)&ad4085_chip_info },
{ "ad4086", (kernel_ulong_t)&ad4086_chip_info },
{ "ad4087", (kernel_ulong_t)&ad4087_chip_info },
+ { "ad4088", (kernel_ulong_t)&ad4088_chip_info },
{ }
};
MODULE_DEVICE_TABLE(spi, ad4080_id);
@@ -677,10 +718,13 @@ MODULE_DEVICE_TABLE(spi, ad4080_id);
static const struct of_device_id ad4080_of_match[] = {
{ .compatible = "adi,ad4080", &ad4080_chip_info },
{ .compatible = "adi,ad4081", &ad4081_chip_info },
+ { .compatible = "adi,ad4082", &ad4082_chip_info },
{ .compatible = "adi,ad4083", &ad4083_chip_info },
{ .compatible = "adi,ad4084", &ad4084_chip_info },
+ { .compatible = "adi,ad4085", &ad4085_chip_info },
{ .compatible = "adi,ad4086", &ad4086_chip_info },
{ .compatible = "adi,ad4087", &ad4087_chip_info },
+ { .compatible = "adi,ad4088", &ad4088_chip_info },
{ }
};
MODULE_DEVICE_TABLE(of, ad4080_of_match);
diff --git a/drivers/iio/adc/ad4170-4.c b/drivers/iio/adc/ad4170-4.c
index 82205bfae531..77af0e6b2c59 100644
--- a/drivers/iio/adc/ad4170-4.c
+++ b/drivers/iio/adc/ad4170-4.c
@@ -275,9 +275,9 @@ static const unsigned int ad4170_reg_size[] = {
};
enum ad4170_ref_buf {
- AD4170_REF_BUF_PRE, /* Pre-charge referrence buffer */
- AD4170_REF_BUF_FULL, /* Full referrence buffering */
- AD4170_REF_BUF_BYPASS, /* Bypass referrence buffering */
+ AD4170_REF_BUF_PRE, /* Pre-charge reference buffer */
+ AD4170_REF_BUF_FULL, /* Full reference buffering */
+ AD4170_REF_BUF_BYPASS, /* Bypass reference buffering */
};
/* maps adi,positive/negative-reference-buffer property values to enum */
diff --git a/drivers/iio/adc/ad7173.c b/drivers/iio/adc/ad7173.c
index d36612352b44..f76a9e08f39e 100644
--- a/drivers/iio/adc/ad7173.c
+++ b/drivers/iio/adc/ad7173.c
@@ -1763,7 +1763,8 @@ static int ad7173_validate_openwire_ain_inputs(struct ad7173_state *st,
static unsigned int ad7173_calc_openwire_thrsh_raw(struct ad7173_state *st,
struct iio_chan_spec *chan,
struct ad7173_channel *chan_st_priv,
- unsigned int thrsh_mv) {
+ unsigned int thrsh_mv)
+{
unsigned int thrsh_raw;
thrsh_raw =
diff --git a/drivers/iio/adc/ad7192.c b/drivers/iio/adc/ad7192.c
index 530e1d307860..8b1664f6b102 100644
--- a/drivers/iio/adc/ad7192.c
+++ b/drivers/iio/adc/ad7192.c
@@ -1402,9 +1402,6 @@ static int ad7192_probe(struct spi_device *spi)
st->int_vref_mv = ret == -ENODEV ? avdd_mv : ret / MILLI;
st->chip_info = spi_get_device_match_data(spi);
- if (!st->chip_info)
- return -ENODEV;
-
indio_dev->name = st->chip_info->name;
indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->info = st->chip_info->info;
diff --git a/drivers/iio/adc/ad7266.c b/drivers/iio/adc/ad7266.c
index 3364ac6c4631..0ef36c249ab8 100644
--- a/drivers/iio/adc/ad7266.c
+++ b/drivers/iio/adc/ad7266.c
@@ -409,10 +409,8 @@ static int ad7266_probe(struct spi_device *spi)
st->gpios[i] = devm_gpiod_get(&spi->dev,
ad7266_gpio_labels[i],
GPIOD_OUT_LOW);
- if (IS_ERR(st->gpios[i])) {
- ret = PTR_ERR(st->gpios[i]);
- return ret;
- }
+ if (IS_ERR(st->gpios[i]))
+ return PTR_ERR(st->gpios[i]);
}
}
} else {
diff --git a/drivers/iio/adc/ad7380.c b/drivers/iio/adc/ad7380.c
index bfd908deefc0..9f77990a03f9 100644
--- a/drivers/iio/adc/ad7380.c
+++ b/drivers/iio/adc/ad7380.c
@@ -77,8 +77,7 @@
#define AD7380_CONFIG1_REFSEL BIT(1)
#define AD7380_CONFIG1_PMODE BIT(0)
-#define AD7380_CONFIG2_SDO2 GENMASK(9, 8)
-#define AD7380_CONFIG2_SDO BIT(8)
+#define AD7380_CONFIG2_SDO GENMASK(9, 8)
#define AD7380_CONFIG2_RESET GENMASK(7, 0)
#define AD7380_CONFIG2_RESET_SOFT 0x3C
@@ -92,11 +91,6 @@
#define T_CONVERT_X_NS 500 /* xth conversion start time (oversampling) */
#define T_POWERUP_US 5000 /* Power up */
-/*
- * AD738x support several SDO lines to increase throughput, but driver currently
- * supports only 1 SDO line (standard SPI transaction)
- */
-#define AD7380_NUM_SDO_LINES 1
#define AD7380_DEFAULT_GAIN_MILLI 1000
/*
@@ -888,6 +882,8 @@ struct ad7380_state {
bool resolution_boost_enabled;
unsigned int ch;
bool seq;
+ /* How many SDO lines are wired up. */
+ u8 num_sdo_lines;
unsigned int vref_mv;
unsigned int vcm_mv[MAX_NUM_CHANNELS];
unsigned int gain_milli[MAX_NUM_CHANNELS];
@@ -1084,7 +1080,7 @@ static int ad7380_set_ch(struct ad7380_state *st, unsigned int ch)
if (oversampling_ratio > 1)
xfer.delay.value = T_CONVERT_0_NS +
T_CONVERT_X_NS * (oversampling_ratio - 1) *
- st->chip_info->num_simult_channels / AD7380_NUM_SDO_LINES;
+ st->chip_info->num_simult_channels / st->num_sdo_lines;
return spi_sync_transfer(st->spi, &xfer, 1);
}
@@ -1113,7 +1109,7 @@ static int ad7380_update_xfers(struct ad7380_state *st,
if (oversampling_ratio > 1)
t_convert = T_CONVERT_0_NS + T_CONVERT_X_NS *
(oversampling_ratio - 1) *
- st->chip_info->num_simult_channels / AD7380_NUM_SDO_LINES;
+ st->chip_info->num_simult_channels / st->num_sdo_lines;
if (st->seq) {
xfer[0].delay.value = xfer[1].delay.value = t_convert;
@@ -1198,6 +1194,8 @@ static int ad7380_init_offload_msg(struct ad7380_state *st,
xfer->bits_per_word = scan_type->realbits;
xfer->offload_flags = SPI_OFFLOAD_XFER_RX_STREAM;
xfer->len = AD7380_SPI_BYTES(scan_type) * st->chip_info->num_simult_channels;
+ if (st->num_sdo_lines > 1)
+ xfer->multi_lane_mode = SPI_MULTI_LANE_MODE_STRIPE;
spi_message_init_with_transfers(&st->offload_msg, xfer, 1);
st->offload_msg.offload = st->offload;
@@ -1793,6 +1791,7 @@ static const struct iio_info ad7380_info = {
static int ad7380_init(struct ad7380_state *st, bool external_ref_en)
{
+ u32 sdo;
int ret;
/* perform hard reset */
@@ -1815,11 +1814,24 @@ static int ad7380_init(struct ad7380_state *st, bool external_ref_en)
st->ch = 0;
st->seq = false;
- /* SPI 1-wire mode */
+ /* SDO field has an irregular mapping. */
+ switch (st->num_sdo_lines) {
+ case 1:
+ sdo = 1;
+ break;
+ case 2:
+ sdo = 0;
+ break;
+ case 4:
+ sdo = 2;
+ break;
+ default:
+ return -EINVAL;
+ }
+
return regmap_update_bits(st->regmap, AD7380_REG_ADDR_CONFIG2,
AD7380_CONFIG2_SDO,
- FIELD_PREP(AD7380_CONFIG2_SDO,
- AD7380_NUM_SDO_LINES));
+ FIELD_PREP(AD7380_CONFIG2_SDO, sdo));
}
static int ad7380_probe_spi_offload(struct iio_dev *indio_dev,
@@ -1842,7 +1854,7 @@ static int ad7380_probe_spi_offload(struct iio_dev *indio_dev,
"failed to get offload trigger\n");
sample_rate = st->chip_info->max_conversion_rate_hz *
- AD7380_NUM_SDO_LINES / st->chip_info->num_simult_channels;
+ st->num_sdo_lines / st->chip_info->num_simult_channels;
st->sample_freq_range[0] = 1; /* min */
st->sample_freq_range[1] = 1; /* step */
@@ -1850,7 +1862,7 @@ static int ad7380_probe_spi_offload(struct iio_dev *indio_dev,
/*
* Starting with a quite low frequency, to allow oversampling x32,
- * user is then reponsible to adjust the frequency for the specific case.
+ * user is then responsible to adjust the frequency for the specific case.
*/
ret = ad7380_set_sample_freq(st, sample_rate / 32);
if (ret)
@@ -1887,6 +1899,13 @@ static int ad7380_probe(struct spi_device *spi)
if (!st->chip_info)
return dev_err_probe(dev, -EINVAL, "missing match data\n");
+ st->num_sdo_lines = spi->num_rx_lanes;
+
+ if (st->num_sdo_lines < 1 || st->num_sdo_lines > st->chip_info->num_simult_channels)
+ return dev_err_probe(dev, -EINVAL,
+ "invalid number of SDO lines (%d)\n",
+ st->num_sdo_lines);
+
ret = devm_regulator_bulk_get_enable(dev, st->chip_info->num_supplies,
st->chip_info->supplies);
@@ -2010,6 +2029,8 @@ static int ad7380_probe(struct spi_device *spi)
st->normal_xfer[0].cs_change_delay.value = st->chip_info->timing_specs->t_csh_ns;
st->normal_xfer[0].cs_change_delay.unit = SPI_DELAY_UNIT_NSECS;
st->normal_xfer[1].rx_buf = st->scan_data;
+ if (st->num_sdo_lines > 1)
+ st->normal_xfer[1].multi_lane_mode = SPI_MULTI_LANE_MODE_STRIPE;
spi_message_init_with_transfers(&st->normal_msg, st->normal_xfer,
ARRAY_SIZE(st->normal_xfer));
@@ -2031,6 +2052,10 @@ static int ad7380_probe(struct spi_device *spi)
st->seq_xfer[2].cs_change = 1;
st->seq_xfer[2].cs_change_delay.value = st->chip_info->timing_specs->t_csh_ns;
st->seq_xfer[2].cs_change_delay.unit = SPI_DELAY_UNIT_NSECS;
+ if (st->num_sdo_lines > 1) {
+ st->seq_xfer[2].multi_lane_mode = SPI_MULTI_LANE_MODE_STRIPE;
+ st->seq_xfer[3].multi_lane_mode = SPI_MULTI_LANE_MODE_STRIPE;
+ }
spi_message_init_with_transfers(&st->seq_msg, st->seq_xfer,
ARRAY_SIZE(st->seq_xfer));
diff --git a/drivers/iio/adc/ad7768-1.c b/drivers/iio/adc/ad7768-1.c
index e16dede687d3..73fb734d06b2 100644
--- a/drivers/iio/adc/ad7768-1.c
+++ b/drivers/iio/adc/ad7768-1.c
@@ -25,12 +25,15 @@
#include <linux/regulator/consumer.h>
#include <linux/regulator/driver.h>
#include <linux/sysfs.h>
+#include <linux/spi/offload/consumer.h>
+#include <linux/spi/offload/provider.h>
#include <linux/spi/spi.h>
#include <linux/unaligned.h>
#include <linux/units.h>
#include <linux/util_macros.h>
#include <linux/iio/buffer.h>
+#include <linux/iio/buffer-dmaengine.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
#include <linux/iio/trigger.h>
@@ -161,6 +164,8 @@ enum ad7768_filter_regval {
enum ad7768_scan_type {
AD7768_SCAN_TYPE_NORMAL,
AD7768_SCAN_TYPE_HIGH_SPEED,
+ AD7768_SCAN_TYPE_OFFLOAD_NORMAL,
+ AD7768_SCAN_TYPE_OFFLOAD_HIGH_SPEED,
};
enum {
@@ -266,6 +271,18 @@ static const struct iio_scan_type ad7768_scan_type[] = {
.storagebits = 16,
.endianness = IIO_BE,
},
+ [AD7768_SCAN_TYPE_OFFLOAD_NORMAL] = {
+ .sign = 's',
+ .realbits = 24,
+ .storagebits = 32,
+ .endianness = IIO_CPU,
+ },
+ [AD7768_SCAN_TYPE_OFFLOAD_HIGH_SPEED] = {
+ .sign = 's',
+ .realbits = 16,
+ .storagebits = 32,
+ .endianness = IIO_CPU,
+ },
};
struct ad7768_chip_info {
@@ -283,6 +300,8 @@ struct ad7768_chip_info {
struct ad7768_state {
struct spi_device *spi;
+ struct spi_offload *offload;
+ struct spi_offload_trigger *offload_trigger;
struct regmap *regmap;
struct regmap *regmap24;
int vref_uv;
@@ -290,7 +309,6 @@ struct ad7768_state {
unsigned int vcm_output_sel;
struct clk *mclk;
unsigned int mclk_freq;
- unsigned int mclk_div;
unsigned int oversampling_ratio;
enum ad7768_filter_type filter_type;
unsigned int samp_freq;
@@ -306,6 +324,8 @@ struct ad7768_state {
struct gpio_desc *gpio_reset;
const char *labels[AD7768_MAX_CHANNELS];
struct gpio_chip gpiochip;
+ struct spi_transfer offload_xfer;
+ struct spi_message offload_msg;
const struct ad7768_chip_info *chip;
bool en_spi_sync;
struct mutex pga_lock; /* protect device internal state (PGA) */
@@ -464,13 +484,11 @@ static int ad7768_scan_direct(struct iio_dev *indio_dev)
int readval, ret;
reinit_completion(&st->completion);
-
- ret = ad7768_set_mode(st, AD7768_ONE_SHOT);
- if (ret < 0)
- return ret;
+ enable_irq(st->spi->irq);
ret = wait_for_completion_timeout(&st->completion,
msecs_to_jiffies(1000));
+ disable_irq(st->spi->irq);
if (!ret)
return -ETIMEDOUT;
@@ -487,14 +505,6 @@ static int ad7768_scan_direct(struct iio_dev *indio_dev)
if (st->oversampling_ratio == 8)
readval >>= 8;
- /*
- * Any SPI configuration of the AD7768-1 can only be
- * performed in continuous conversion mode.
- */
- ret = ad7768_set_mode(st, AD7768_CONTINUOUS);
- if (ret < 0)
- return ret;
-
return readval;
}
@@ -1138,6 +1148,10 @@ static int ad7768_get_current_scan_type(const struct iio_dev *indio_dev,
{
struct ad7768_state *st = iio_priv(indio_dev);
+ if (st->offload)
+ return st->oversampling_ratio == 8 ?
+ AD7768_SCAN_TYPE_OFFLOAD_HIGH_SPEED : AD7768_SCAN_TYPE_OFFLOAD_NORMAL;
+
return st->oversampling_ratio == 8 ?
AD7768_SCAN_TYPE_HIGH_SPEED : AD7768_SCAN_TYPE_NORMAL;
}
@@ -1252,6 +1266,10 @@ static int ad7768_setup(struct iio_dev *indio_dev)
return ret;
}
+ ret = ad7768_set_mode(st, AD7768_CONTINUOUS);
+ if (ret)
+ return ret;
+
/* For backwards compatibility, try the adi,sync-in-gpios property */
st->gpio_sync_in = devm_gpiod_get_optional(&st->spi->dev, "adi,sync-in",
GPIOD_OUT_LOW);
@@ -1356,8 +1374,94 @@ static const struct iio_buffer_setup_ops ad7768_buffer_ops = {
.predisable = &ad7768_buffer_predisable,
};
+static int ad7768_offload_buffer_postenable(struct iio_dev *indio_dev)
+{
+ struct ad7768_state *st = iio_priv(indio_dev);
+ struct spi_offload_trigger_config config = {
+ .type = SPI_OFFLOAD_TRIGGER_DATA_READY,
+ };
+ const struct iio_scan_type *scan_type;
+ unsigned int unused;
+ int ret;
+
+ scan_type = iio_get_current_scan_type(indio_dev, &indio_dev->channels[0]);
+ if (IS_ERR(scan_type))
+ return PTR_ERR(scan_type);
+
+ st->offload_xfer.len = spi_bpw_to_bytes(scan_type->realbits);
+ st->offload_xfer.bits_per_word = scan_type->realbits;
+ st->offload_xfer.offload_flags = SPI_OFFLOAD_XFER_RX_STREAM;
+
+ spi_message_init_with_transfers(&st->offload_msg, &st->offload_xfer, 1);
+ st->offload_msg.offload = st->offload;
+
+ ret = spi_optimize_message(st->spi, &st->offload_msg);
+ if (ret) {
+ dev_err(&st->spi->dev, "failed to prepare offload, err: %d\n", ret);
+ return ret;
+ }
+
+ /*
+ * Write a 1 to the LSB of the INTERFACE_FORMAT register to enter
+ * continuous read mode. Subsequent data reads do not require an
+ * initial 8-bit write to query the ADC_DATA register.
+ */
+ ret = regmap_write(st->regmap, AD7768_REG_INTERFACE_FORMAT, 0x01);
+ if (ret)
+ goto err_unoptimize_message;
+
+ ret = spi_offload_trigger_enable(st->offload, st->offload_trigger,
+ &config);
+ if (ret)
+ goto err_exit_continuous_read_mode;
+
+ return 0;
+
+err_exit_continuous_read_mode:
+ regmap_read(st->regmap24, AD7768_REG24_ADC_DATA, &unused);
+
+err_unoptimize_message:
+ spi_unoptimize_message(&st->offload_msg);
+
+ return ret;
+}
+
+static int ad7768_offload_buffer_predisable(struct iio_dev *indio_dev)
+{
+ struct ad7768_state *st = iio_priv(indio_dev);
+ unsigned int unused;
+
+ spi_offload_trigger_disable(st->offload, st->offload_trigger);
+ spi_unoptimize_message(&st->offload_msg);
+
+ /*
+ * To exit continuous read mode, perform a single read of the ADC_DATA
+ * reg (0x2C), which allows further configuration of the device.
+ */
+ return regmap_read(st->regmap24, AD7768_REG24_ADC_DATA, &unused);
+}
+
+static const struct iio_buffer_setup_ops ad7768_offload_buffer_ops = {
+ .postenable = ad7768_offload_buffer_postenable,
+ .predisable = ad7768_offload_buffer_predisable,
+};
+
+static int ad7768_set_trigger_state(struct iio_trigger *trig, bool enable)
+{
+ struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig);
+ struct ad7768_state *st = iio_priv(indio_dev);
+
+ if (enable)
+ enable_irq(st->spi->irq);
+ else
+ disable_irq(st->spi->irq);
+
+ return 0;
+}
+
static const struct iio_trigger_ops ad7768_trigger_ops = {
.validate_device = iio_trigger_validate_own_device,
+ .set_trigger_state = ad7768_set_trigger_state,
};
static int ad7768_set_channel_label(struct iio_dev *indio_dev,
@@ -1590,6 +1694,36 @@ static int ad7768_parse_aaf_gain(struct device *dev, struct ad7768_state *st)
return 0;
}
+static bool ad7768_offload_trigger_match(struct spi_offload_trigger *trigger,
+ enum spi_offload_trigger_type type,
+ u64 *args, u32 nargs)
+{
+ if (type != SPI_OFFLOAD_TRIGGER_DATA_READY)
+ return false;
+
+ /* Up to 2 args are allowed, but only 1 is used */
+ if (nargs == 0 || nargs > 2 || args[0] != AD7768_TRIGGER_SOURCE_DRDY)
+ return false;
+
+ return true;
+}
+
+static int ad7768_offload_trigger_request(struct spi_offload_trigger *trigger,
+ enum spi_offload_trigger_type type,
+ u64 *args, u32 nargs)
+{
+ /* Should already be validated by match, but just in case */
+ if (nargs == 0 || nargs > 2)
+ return -EINVAL;
+
+ return 0;
+}
+
+static const struct spi_offload_trigger_ops ad7768_offload_trigger_ops = {
+ .match = ad7768_offload_trigger_match,
+ .request = ad7768_offload_trigger_request,
+};
+
static const struct ad7768_chip_info ad7768_chip_info = {
.name = "ad7768-1",
.channel_spec = ad7768_channels,
@@ -1627,10 +1761,51 @@ static const struct ad7768_chip_info adaq7769_chip_info = {
.has_variable_aaf = true,
};
+static const struct spi_offload_config ad7768_spi_offload_config = {
+ .capability_flags = SPI_OFFLOAD_CAP_TRIGGER | SPI_OFFLOAD_CAP_RX_STREAM_DMA,
+};
+
+static int ad7768_spi_offload_probe(struct iio_dev *indio_dev,
+ struct ad7768_state *st)
+{
+ struct device *dev = &st->spi->dev;
+ struct spi_offload_trigger_info trigger_info = {
+ .fwnode = dev_fwnode(dev),
+ .ops = &ad7768_offload_trigger_ops,
+ .priv = st,
+ };
+ struct dma_chan *rx_dma;
+ int ret;
+
+ ret = devm_spi_offload_trigger_register(dev, &trigger_info);
+ if (ret)
+ return dev_err_probe(dev, ret, "failed to register offload trigger\n");
+
+ st->offload_trigger = devm_spi_offload_trigger_get(dev, st->offload,
+ SPI_OFFLOAD_TRIGGER_DATA_READY);
+ if (IS_ERR(st->offload_trigger))
+ return dev_err_probe(dev, PTR_ERR(st->offload_trigger),
+ "failed to get offload trigger\n");
+
+ rx_dma = devm_spi_offload_rx_stream_request_dma_chan(dev, st->offload);
+ if (IS_ERR(rx_dma))
+ return dev_err_probe(dev, PTR_ERR(rx_dma), "failed to get offload RX DMA\n");
+
+ ret = devm_iio_dmaengine_buffer_setup_with_handle(dev, indio_dev, rx_dma,
+ IIO_BUFFER_DIRECTION_IN);
+ if (ret)
+ return dev_err_probe(dev, ret, "failed to setup offload RX DMA\n");
+
+ indio_dev->setup_ops = &ad7768_offload_buffer_ops;
+
+ return 0;
+}
+
static int ad7768_probe(struct spi_device *spi)
{
struct ad7768_state *st;
struct iio_dev *indio_dev;
+ struct device *dev = &spi->dev;
int ret;
indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
@@ -1721,14 +1896,25 @@ static int ad7768_probe(struct spi_device *spi)
return ret;
ret = devm_request_irq(&spi->dev, spi->irq, &ad7768_interrupt,
- IRQF_TRIGGER_RISING | IRQF_NO_THREAD,
+ IRQF_TRIGGER_RISING | IRQF_NO_THREAD | IRQF_NO_AUTOEN,
indio_dev->name, indio_dev);
if (ret)
return ret;
- ret = ad7768_triggered_buffer_alloc(indio_dev);
- if (ret)
- return ret;
+ st->offload = devm_spi_offload_get(dev, spi, &ad7768_spi_offload_config);
+ ret = PTR_ERR_OR_ZERO(st->offload);
+ if (ret == -ENODEV) {
+ /* If not using SPI offload, fall back to low speed usage */
+ ret = ad7768_triggered_buffer_alloc(indio_dev);
+ if (ret)
+ return ret;
+ } else if (ret) {
+ return dev_err_probe(dev, ret, "failed to get SPI offload\n");
+ } else {
+ ret = ad7768_spi_offload_probe(indio_dev, st);
+ if (ret)
+ return ret;
+ }
return devm_iio_device_register(&spi->dev, indio_dev);
}
@@ -1764,3 +1950,4 @@ module_spi_driver(ad7768_driver);
MODULE_AUTHOR("Stefan Popa <stefan.popa@analog.com>");
MODULE_DESCRIPTION("Analog Devices AD7768-1 ADC driver");
MODULE_LICENSE("GPL v2");
+MODULE_IMPORT_NS("IIO_DMAENGINE_BUFFER");
diff --git a/drivers/iio/adc/ad7793.c b/drivers/iio/adc/ad7793.c
index ccf18ce48e34..8ff7b70d6632 100644
--- a/drivers/iio/adc/ad7793.c
+++ b/drivers/iio/adc/ad7793.c
@@ -152,7 +152,6 @@ struct ad7793_chip_info {
struct ad7793_state {
const struct ad7793_chip_info *chip_info;
- u16 int_vref_mv;
u16 mode;
u16 conf;
u32 scale_avail[8][2];
@@ -805,7 +804,7 @@ static int ad7793_probe(struct spi_device *spi)
vref_mv = ret / 1000;
} else {
- vref_mv = 1170; /* Build-in ref */
+ vref_mv = 1170; /* Built-in ref */
}
st->chip_info =
diff --git a/drivers/iio/adc/ad7887.c b/drivers/iio/adc/ad7887.c
index 87ff95643794..068171d54596 100644
--- a/drivers/iio/adc/ad7887.c
+++ b/drivers/iio/adc/ad7887.c
@@ -104,7 +104,7 @@ static int ad7887_ring_postdisable(struct iio_dev *indio_dev)
{
struct ad7887_state *st = iio_priv(indio_dev);
- /* dummy read: restore default CH0 settin */
+ /* dummy read: restore default CH0 settings */
return spi_sync(st->spi, &st->msg[AD7887_CH0]);
}
diff --git a/drivers/iio/adc/ad7923.c b/drivers/iio/adc/ad7923.c
index 0369151c7db1..acc87d486aa4 100644
--- a/drivers/iio/adc/ad7923.c
+++ b/drivers/iio/adc/ad7923.c
@@ -30,7 +30,7 @@
#define AD7923_PM_MODE_AS (1) /* auto shutdown */
#define AD7923_PM_MODE_FS (2) /* full shutdown */
#define AD7923_PM_MODE_OPS (3) /* normal operation */
-#define AD7923_SEQUENCE_OFF (0) /* no sequence fonction */
+#define AD7923_SEQUENCE_OFF (0) /* no sequence function */
#define AD7923_SEQUENCE_PROTECT (2) /* no interrupt write cycle */
#define AD7923_SEQUENCE_ON (3) /* continuous sequence */
@@ -39,7 +39,7 @@
#define AD7923_CHANNEL_WRITE(channel) ((channel) << 6) /* write channel */
#define AD7923_SEQUENCE_WRITE(sequence) ((((sequence) & 1) << 3) \
+ (((sequence) & 2) << 9))
- /* write sequence fonction */
+ /* write sequence function */
/* left shift for CR : bit 11 transmit in first */
#define AD7923_SHIFT_REGISTER 4
diff --git a/drivers/iio/adc/ad9467.c b/drivers/iio/adc/ad9467.c
index 022888545580..0bf67437508f 100644
--- a/drivers/iio/adc/ad9467.c
+++ b/drivers/iio/adc/ad9467.c
@@ -176,7 +176,6 @@ struct ad9467_state {
struct clk *clk;
/* used for debugfs */
struct ad9467_chan_test_mode *chan_test;
- unsigned int output_mode;
unsigned int (*scales)[2];
/*
* Times 2 because we may also invert the signal polarity and run the
@@ -925,7 +924,11 @@ static int __ad9467_update_clock(struct ad9467_state *st, long r_clk)
return ret;
guard(mutex)(&st->lock);
- return ad9467_calibrate(st);
+
+ if (iio_backend_has_caps(st->back, IIO_BACKEND_CAP_CALIBRATION))
+ return ad9467_calibrate(st);
+
+ return 0;
}
static int ad9467_write_raw(struct iio_dev *indio_dev,
@@ -1131,12 +1134,15 @@ static ssize_t ad9467_chan_test_mode_read(struct file *file,
len = scnprintf(buf, sizeof(buf), "Running \"%s\" Test:\n\t",
ad9467_test_modes[chan->mode]);
- ret = iio_backend_debugfs_print_chan_status(st->back, chan->idx,
- buf + len,
- sizeof(buf) - len);
- if (ret < 0)
- return ret;
- len += ret;
+ if (iio_backend_has_caps(st->back, IIO_BACKEND_CAP_CALIBRATION)) {
+ ret = iio_backend_debugfs_print_chan_status(st->back,
+ chan->idx,
+ buf + len,
+ sizeof(buf) - len);
+ if (ret < 0)
+ return ret;
+ len += ret;
+ }
} else if (chan->mode == AN877_ADC_TESTMODE_OFF) {
len = scnprintf(buf, sizeof(buf), "No test Running...\n");
} else {
@@ -1175,11 +1181,13 @@ static ssize_t ad9467_chan_test_mode_write(struct file *file,
if (mode == AN877_ADC_TESTMODE_OFF) {
unsigned int out_mode;
- if (chan->mode == AN877_ADC_TESTMODE_PN9_SEQ ||
- chan->mode == AN877_ADC_TESTMODE_PN23_SEQ) {
- ret = ad9467_backend_testmode_off(st, chan->idx);
- if (ret)
- return ret;
+ if (iio_backend_has_caps(st->back, IIO_BACKEND_CAP_CALIBRATION)) {
+ if (chan->mode == AN877_ADC_TESTMODE_PN9_SEQ ||
+ chan->mode == AN877_ADC_TESTMODE_PN23_SEQ) {
+ ret = ad9467_backend_testmode_off(st, chan->idx);
+ if (ret)
+ return ret;
+ }
}
ret = ad9467_testmode_set(st, chan->idx, mode);
@@ -1205,16 +1213,18 @@ static ssize_t ad9467_chan_test_mode_write(struct file *file,
return ret;
/* some patterns have a backend matching monitoring block */
- if (mode == AN877_ADC_TESTMODE_PN9_SEQ) {
- ret = ad9467_backend_testmode_on(st, chan->idx,
+ if (iio_backend_has_caps(st->back, IIO_BACKEND_CAP_CALIBRATION)) {
+ if (mode == AN877_ADC_TESTMODE_PN9_SEQ) {
+ ret = ad9467_backend_testmode_on(st, chan->idx,
IIO_BACKEND_ADI_PRBS_9A);
- if (ret)
- return ret;
- } else if (mode == AN877_ADC_TESTMODE_PN23_SEQ) {
- ret = ad9467_backend_testmode_on(st, chan->idx,
+ if (ret)
+ return ret;
+ } else if (mode == AN877_ADC_TESTMODE_PN23_SEQ) {
+ ret = ad9467_backend_testmode_on(st, chan->idx,
IIO_BACKEND_ADI_PRBS_23A);
- if (ret)
- return ret;
+ if (ret)
+ return ret;
+ }
}
}
@@ -1280,8 +1290,9 @@ static void ad9467_debugfs_init(struct iio_dev *indio_dev)
if (!st->chan_test)
return;
- debugfs_create_file("calibration_table_dump", 0400, d, st,
- &ad9467_calib_table_fops);
+ if (iio_backend_has_caps(st->back, IIO_BACKEND_CAP_CALIBRATION))
+ debugfs_create_file("calibration_table_dump", 0400, d, st,
+ &ad9467_calib_table_fops);
for (chan = 0; chan < st->info->num_channels; chan++) {
snprintf(attr_name, sizeof(attr_name), "in_voltage%u_test_mode",
@@ -1300,12 +1311,13 @@ static void ad9467_debugfs_init(struct iio_dev *indio_dev)
static int ad9467_probe(struct spi_device *spi)
{
+ struct device *dev = &spi->dev;
struct iio_dev *indio_dev;
struct ad9467_state *st;
unsigned int id;
int ret;
- indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
+ indio_dev = devm_iio_device_alloc(dev, sizeof(*st));
if (!indio_dev)
return -ENOMEM;
@@ -1320,16 +1332,15 @@ static int ad9467_probe(struct spi_device *spi)
if (AD9467_CAN_INVERT(st))
st->calib_map_size *= 2;
- st->clk = devm_clk_get_enabled(&spi->dev, "adc-clk");
+ st->clk = devm_clk_get_enabled(dev, "adc-clk");
if (IS_ERR(st->clk))
return PTR_ERR(st->clk);
- st->pwrdown_gpio = devm_gpiod_get_optional(&spi->dev, "powerdown",
- GPIOD_OUT_LOW);
+ st->pwrdown_gpio = devm_gpiod_get_optional(dev, "powerdown", GPIOD_OUT_LOW);
if (IS_ERR(st->pwrdown_gpio))
return PTR_ERR(st->pwrdown_gpio);
- ret = ad9467_reset(&spi->dev);
+ ret = ad9467_reset(dev);
if (ret)
return ret;
@@ -1339,7 +1350,7 @@ static int ad9467_probe(struct spi_device *spi)
id = ad9467_spi_read(st, AN877_ADC_REG_CHIP_ID);
if (id != st->info->id) {
- dev_err(&spi->dev, "Mismatch CHIP_ID, got 0x%X, expected 0x%X\n",
+ dev_err(dev, "Mismatch CHIP_ID, got 0x%X, expected 0x%X\n",
id, st->info->id);
return -ENODEV;
}
@@ -1356,19 +1367,25 @@ static int ad9467_probe(struct spi_device *spi)
if (ret)
return ret;
- ret = devm_iio_backend_request_buffer(&spi->dev, st->back, indio_dev);
- if (ret)
- return ret;
+ if (iio_backend_has_caps(st->back, IIO_BACKEND_CAP_BUFFER)) {
+ ret = devm_iio_backend_request_buffer(dev, st->back, indio_dev);
+ if (ret)
+ return ret;
+ }
- ret = devm_iio_backend_enable(&spi->dev, st->back);
- if (ret)
- return ret;
+ if (iio_backend_has_caps(st->back, IIO_BACKEND_CAP_ENABLE)) {
+ ret = devm_iio_backend_enable(dev, st->back);
+ if (ret)
+ return ret;
+ }
- ret = ad9467_calibrate(st);
- if (ret)
- return ret;
+ if (iio_backend_has_caps(st->back, IIO_BACKEND_CAP_CALIBRATION)) {
+ ret = ad9467_calibrate(st);
+ if (ret)
+ return ret;
+ }
- ret = devm_iio_device_register(&spi->dev, indio_dev);
+ ret = devm_iio_device_register(dev, indio_dev);
if (ret)
return ret;
diff --git a/drivers/iio/adc/ad_sigma_delta.c b/drivers/iio/adc/ad_sigma_delta.c
index 7852884703b0..a955556f9ec8 100644
--- a/drivers/iio/adc/ad_sigma_delta.c
+++ b/drivers/iio/adc/ad_sigma_delta.c
@@ -51,8 +51,10 @@
*/
void ad_sd_set_comm(struct ad_sigma_delta *sigma_delta, u8 comm)
{
- /* Some variants use the lower two bits of the communications register
- * to select the channel */
+ /*
+ * Some variants use the lower two bits of the communications register
+ * to select the channel.
+ */
sigma_delta->comm = comm & AD_SD_COMM_CHAN_MASK;
}
EXPORT_SYMBOL_NS_GPL(ad_sd_set_comm, "IIO_AD_SIGMA_DELTA");
diff --git a/drivers/iio/adc/ade9000.c b/drivers/iio/adc/ade9000.c
index 1abbfdfcd554..c0a9babfa519 100644
--- a/drivers/iio/adc/ade9000.c
+++ b/drivers/iio/adc/ade9000.c
@@ -218,9 +218,6 @@
#define ADE9000_ST1_ERROR1_BIT BIT(29)
#define ADE9000_ST1_ERROR2_BIT BIT(30)
#define ADE9000_ST1_ERROR3_BIT BIT(31)
-#define ADE9000_ST_ERROR \
- (ADE9000_ST1_ERROR0 | ADE9000_ST1_ERROR1 | \
- ADE9000_ST1_ERROR2 | ADE9000_ST1_ERROR3)
#define ADE9000_ST1_CROSSING_FIRST 6
#define ADE9000_ST1_CROSSING_DEPTH 25
@@ -283,7 +280,6 @@ enum ade9000_wfb_cfg {
#define ADE9000_PHASE_C_POS_BIT BIT(6)
#define ADE9000_MAX_PHASE_NR 3
-#define AD9000_CHANNELS_PER_PHASE 10
/*
* Calculate register address for multi-phase device.
@@ -1549,7 +1545,7 @@ static int ade9000_buffer_postdisable(struct iio_dev *indio_dev)
ret = regmap_clear_bits(st->regmap, ADE9000_REG_MASK0, interrupts);
if (ret) {
- dev_err(dev, "Post-disable update maks0 fail\n");
+ dev_err(dev, "Post-disable update mask0 fail\n");
return ret;
}
@@ -1589,10 +1585,9 @@ static int ade9000_reset(struct ade9000_state *st)
/* Only wait for completion if IRQ1 is available to signal reset done */
if (fwnode_irq_get_byname(dev_fwnode(dev), "irq1") >= 0) {
if (!wait_for_completion_timeout(&st->reset_completion,
- msecs_to_jiffies(1000))) {
- dev_err(dev, "Reset timeout after 1s\n");
- return -ETIMEDOUT;
- }
+ msecs_to_jiffies(1000)))
+ return dev_err_probe(dev, -ETIMEDOUT,
+ "Reset timeout after 1s\n");
}
/* If no IRQ available, reset is already complete after the 50ms delay above */
diff --git a/drivers/iio/adc/adi-axi-adc.c b/drivers/iio/adc/adi-axi-adc.c
index 5f445e0de9ea..ced0a2321ecf 100644
--- a/drivers/iio/adc/adi-axi-adc.c
+++ b/drivers/iio/adc/adi-axi-adc.c
@@ -621,6 +621,8 @@ static const struct iio_backend_ops adi_axi_adc_ops = {
static const struct iio_backend_info adi_axi_adc_generic = {
.name = "axi-adc",
.ops = &adi_axi_adc_ops,
+ .caps = IIO_BACKEND_CAP_CALIBRATION | IIO_BACKEND_CAP_BUFFER |
+ IIO_BACKEND_CAP_ENABLE,
};
static const struct iio_backend_ops adi_ad485x_ops = {
@@ -645,6 +647,8 @@ static const struct iio_backend_ops adi_ad485x_ops = {
static const struct iio_backend_info axi_ad485x = {
.name = "axi-ad485x",
.ops = &adi_ad485x_ops,
+ .caps = IIO_BACKEND_CAP_CALIBRATION | IIO_BACKEND_CAP_BUFFER |
+ IIO_BACKEND_CAP_ENABLE,
};
static const struct iio_backend_ops adi_ad408x_ops = {
@@ -665,6 +669,7 @@ static const struct iio_backend_ops adi_ad408x_ops = {
static const struct iio_backend_info axi_ad408x = {
.name = "axi-ad408x",
.ops = &adi_ad408x_ops,
+ .caps = IIO_BACKEND_CAP_BUFFER | IIO_BACKEND_CAP_ENABLE,
};
static int adi_axi_adc_probe(struct platform_device *pdev)
diff --git a/drivers/iio/adc/aspeed_adc.c b/drivers/iio/adc/aspeed_adc.c
index 83a9885b9ae4..6169ce28261e 100644
--- a/drivers/iio/adc/aspeed_adc.c
+++ b/drivers/iio/adc/aspeed_adc.c
@@ -75,6 +75,8 @@
#define ASPEED_ADC_INIT_POLLING_TIME 500
#define ASPEED_ADC_INIT_TIMEOUT 500000
+/* Battery sensing is typically on the last channel */
+#define ASPEED_ADC_BATTERY_CHANNEL 7
/*
* 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
@@ -121,6 +123,31 @@ struct aspeed_adc_data {
struct adc_gain battery_mode_gain;
};
+/*
+ * Enable multiple consecutive channels starting from channel 0.
+ * This creates a bitmask for channels 0 to (num_channels - 1).
+ * For example: num_channels=3 creates mask 0x0007 (channels 0,1,2)
+ */
+static inline u32 aspeed_adc_channels_mask(unsigned int num_channels)
+{
+ if (num_channels > 16)
+ return GENMASK(15, 0);
+
+ return BIT(num_channels) - 1;
+}
+
+static inline unsigned int aspeed_adc_get_active_channels(const struct aspeed_adc_data *data)
+{
+ /*
+ * For controllers with battery sensing capability, the last channel
+ * is reserved for battery sensing and should not be included in
+ * normal channel operations.
+ */
+ if (data->model_data->bat_sense_sup)
+ return data->model_data->num_channels - 1;
+ return data->model_data->num_channels;
+}
+
#define ASPEED_CHAN(_idx, _data_reg_addr) { \
.type = IIO_VOLTAGE, \
.indexed = 1, \
@@ -236,10 +263,10 @@ static int aspeed_adc_compensation(struct iio_dev *indio_dev)
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.
+ * After enable compensating sensing mode need to wait some time for the
+ * ADC stablize. Experiment result is 1ms.
*/
- mdelay(1);
+ fsleep(1000);
for (index = 0; index < 16; index++) {
/*
@@ -285,31 +312,48 @@ static int aspeed_adc_read_raw(struct iio_dev *indio_dev,
switch (mask) {
case IIO_CHAN_INFO_RAW:
- if (data->battery_sensing && chan->channel == 7) {
- adc_engine_control_reg_val =
- readl(data->base + ASPEED_REG_ENGINE_CONTROL);
+ adc_engine_control_reg_val = readl(data->base + ASPEED_REG_ENGINE_CONTROL);
+ /*
+ * For battery sensing capable controllers, we need to enable
+ * the specific channel before reading. This is required because
+ * the battery channel may not be enabled by default.
+ */
+ if (data->model_data->bat_sense_sup &&
+ chan->channel == ASPEED_ADC_BATTERY_CHANNEL) {
+ u32 ctrl_reg = adc_engine_control_reg_val & ~ASPEED_ADC_CTRL_CHANNEL;
+
+ ctrl_reg |= ASPEED_ADC_CTRL_CHANNEL_ENABLE(chan->channel);
+ writel(ctrl_reg, data->base + ASPEED_REG_ENGINE_CONTROL);
+ /*
+ * After enable a new channel need to wait some time for ADC stable
+ * Experiment result is 1ms.
+ */
+ fsleep(1000);
+ }
+
+ if (data->battery_sensing && chan->channel == ASPEED_ADC_BATTERY_CHANNEL) {
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
+ * After enable battery sensing mode need to wait some time for ADC stable
* Experiment result is 1ms.
*/
- mdelay(1);
+ fsleep(1000);
*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);
+ /* Restore control register value */
+ writel(adc_engine_control_reg_val,
+ data->base + ASPEED_REG_ENGINE_CONTROL);
return IIO_VAL_INT;
case IIO_CHAN_INFO_OFFSET:
- if (data->battery_sensing && chan->channel == 7)
+ if (data->battery_sensing && chan->channel == ASPEED_ADC_BATTERY_CHANNEL)
*val = (data->cv * data->battery_mode_gain.mult) /
data->battery_mode_gain.div;
else
@@ -611,7 +655,9 @@ static int aspeed_adc_probe(struct platform_device *pdev)
/* Start all channels in normal mode. */
adc_engine_control_reg_val =
readl(data->base + ASPEED_REG_ENGINE_CONTROL);
- adc_engine_control_reg_val |= ASPEED_ADC_CTRL_CHANNEL;
+ FIELD_MODIFY(ASPEED_ADC_CTRL_CHANNEL, &adc_engine_control_reg_val,
+ aspeed_adc_channels_mask(aspeed_adc_get_active_channels(data)));
+
writel(adc_engine_control_reg_val,
data->base + ASPEED_REG_ENGINE_CONTROL);
diff --git a/drivers/iio/adc/at91-sama5d2_adc.c b/drivers/iio/adc/at91-sama5d2_adc.c
index aa4ba3f5a506..255970b2e747 100644
--- a/drivers/iio/adc/at91-sama5d2_adc.c
+++ b/drivers/iio/adc/at91-sama5d2_adc.c
@@ -2259,7 +2259,7 @@ static int at91_adc_temp_sensor_init(struct at91_adc_state *st,
return 0;
/* Get the calibration data from NVMEM. */
- temp_calib = devm_nvmem_cell_get(dev, "temperature_calib");
+ temp_calib = nvmem_cell_get(dev, "temperature_calib");
if (IS_ERR(temp_calib)) {
ret = PTR_ERR(temp_calib);
if (ret != -ENOENT)
@@ -2268,6 +2268,7 @@ static int at91_adc_temp_sensor_init(struct at91_adc_state *st,
}
buf = nvmem_cell_read(temp_calib, &len);
+ nvmem_cell_put(temp_calib);
if (IS_ERR(buf)) {
dev_err(dev, "Failed to read calibration data!\n");
return PTR_ERR(buf);
@@ -2507,7 +2508,7 @@ static int at91_adc_suspend(struct device *dev)
at91_adc_buffer_postdisable(indio_dev);
/*
- * Do a sofware reset of the ADC before we go to suspend.
+ * Do a software reset of the ADC before we go to suspend.
* this will ensure that all pins are free from being muxed by the ADC
* and can be used by for other devices.
* Otherwise, ADC will hog them and we can't go to suspend mode.
diff --git a/drivers/iio/adc/at91_adc.c b/drivers/iio/adc/at91_adc.c
index 920dd9ffd27a..6e1930f7c65d 100644
--- a/drivers/iio/adc/at91_adc.c
+++ b/drivers/iio/adc/at91_adc.c
@@ -171,7 +171,7 @@ struct at91_adc_trigger {
};
/**
- * struct at91_adc_reg_desc - Various informations relative to registers
+ * struct at91_adc_reg_desc - Various information relative to registers
* @channel_base: Base offset for the channel data registers
* @drdy_mask: Mask of the DRDY field in the relevant registers
* (Interruptions registers mostly)
@@ -231,7 +231,7 @@ struct at91_adc_state {
struct iio_trigger **trig;
bool use_external;
u32 vref_mv;
- u32 res; /* resolution used for convertions */
+ u32 res; /* resolution used for conversions */
wait_queue_head_t wq_data_avail;
const struct at91_adc_caps *caps;
@@ -304,7 +304,7 @@ static void handle_adc_eoc_trigger(int irq, struct iio_dev *idev)
}
}
-static int at91_ts_sample(struct iio_dev *idev)
+static void at91_ts_sample(struct iio_dev *idev)
{
struct at91_adc_state *st = iio_priv(idev);
unsigned int xscale, yscale, reg, z1, z2;
@@ -323,7 +323,7 @@ static int at91_ts_sample(struct iio_dev *idev)
xscale = (reg >> 16) & xyz_mask;
if (xscale == 0) {
dev_err(&idev->dev, "Error: xscale == 0!\n");
- return -1;
+ return;
}
x /= xscale;
@@ -334,7 +334,7 @@ static int at91_ts_sample(struct iio_dev *idev)
yscale = (reg >> 16) & xyz_mask;
if (yscale == 0) {
dev_err(&idev->dev, "Error: yscale == 0!\n");
- return -1;
+ return;
}
y /= yscale;
@@ -363,8 +363,6 @@ static int at91_ts_sample(struct iio_dev *idev)
} else {
dev_dbg(&idev->dev, "pressure too low: not reporting\n");
}
-
- return 0;
}
static irqreturn_t at91_adc_rl_interrupt(int irq, void *private)
diff --git a/drivers/iio/adc/cpcap-adc.c b/drivers/iio/adc/cpcap-adc.c
index d9ee2ea116a7..f6f72efcc6ed 100644
--- a/drivers/iio/adc/cpcap-adc.c
+++ b/drivers/iio/adc/cpcap-adc.c
@@ -934,6 +934,17 @@ static const struct cpcap_adc_ato mapphone_adc = {
.atox_ps_factor_out = 0,
};
+static const struct cpcap_adc_ato mot_adc = {
+ .ato_in = 0x0300,
+ .atox_in = 0,
+ .adc_ps_factor_in = 0x0200,
+ .atox_ps_factor_in = 0,
+ .ato_out = 0x0780,
+ .atox_out = 0,
+ .adc_ps_factor_out = 0x0600,
+ .atox_ps_factor_out = 0,
+};
+
static const struct of_device_id cpcap_adc_id_table[] = {
{
.compatible = "motorola,cpcap-adc",
@@ -942,6 +953,10 @@ static const struct of_device_id cpcap_adc_id_table[] = {
.compatible = "motorola,mapphone-cpcap-adc",
.data = &mapphone_adc,
},
+ {
+ .compatible = "motorola,mot-cpcap-adc",
+ .data = &mot_adc,
+ },
{ }
};
MODULE_DEVICE_TABLE(of, cpcap_adc_id_table);
diff --git a/drivers/iio/adc/fsl-imx25-gcq.c b/drivers/iio/adc/fsl-imx25-gcq.c
index f8c220f6a7b4..e6268f7ac400 100644
--- a/drivers/iio/adc/fsl-imx25-gcq.c
+++ b/drivers/iio/adc/fsl-imx25-gcq.c
@@ -47,7 +47,7 @@ struct mx25_gcq_priv {
* of register writes, then a wait for a completion callback,
* and finally a register read, during which userspace could issue
* another read request. This lock protects a read access from
- * ocurring before another one has finished.
+ * occurring before another one has finished.
*/
struct mutex lock;
};
diff --git a/drivers/iio/adc/ina2xx-adc.c b/drivers/iio/adc/ina2xx-adc.c
index c6cded508738..7c04e3ec1cbc 100644
--- a/drivers/iio/adc/ina2xx-adc.c
+++ b/drivers/iio/adc/ina2xx-adc.c
@@ -119,7 +119,7 @@ static const struct regmap_config ina2xx_regmap_config = {
.volatile_reg = ina2xx_is_volatile_reg,
};
-enum ina2xx_ids { ina219, ina226 };
+enum ina2xx_ids { ina219, ina226, ina236 };
struct ina2xx_config {
const char *name;
@@ -173,6 +173,16 @@ static const struct ina2xx_config ina2xx_config[] = {
.power_lsb_factor = 25,
.chip_id = ina226,
},
+ [ina236] = {
+ .name = "ina236",
+ .config_default = INA226_CONFIG_DEFAULT,
+ .calibration_value = 2048,
+ .shunt_voltage_lsb = 2500,
+ .bus_voltage_shift = 0,
+ .bus_voltage_lsb = 1600,
+ .power_lsb_factor = 32,
+ .chip_id = ina236,
+ },
};
static int ina2xx_read_raw(struct iio_dev *indio_dev,
@@ -497,20 +507,26 @@ static int ina2xx_write_raw(struct iio_dev *indio_dev,
break;
case IIO_CHAN_INFO_INT_TIME:
- if (chip->config->chip_id == ina226) {
+ switch (chip->config->chip_id) {
+ case ina226:
+ case ina236:
if (chan->address == INA2XX_SHUNT_VOLTAGE)
ret = ina226_set_int_time_vshunt(chip, val2,
&tmp);
else
ret = ina226_set_int_time_vbus(chip, val2,
&tmp);
- } else {
+ break;
+ case ina219:
if (chan->address == INA2XX_SHUNT_VOLTAGE)
ret = ina219_set_int_time_vshunt(chip, val2,
&tmp);
else
ret = ina219_set_int_time_vbus(chip, val2,
&tmp);
+ break;
+ default:
+ ret = -EINVAL;
}
break;
@@ -725,19 +741,27 @@ static int ina2xx_conversion_ready(struct iio_dev *indio_dev)
* For now, we do an extra read of the MASK_ENABLE register (INA226)
* resp. the BUS_VOLTAGE register (INA219).
*/
- if (chip->config->chip_id == ina226) {
+ switch (chip->config->chip_id) {
+ case ina226:
+ case ina236:
ret = regmap_read(chip->regmap,
INA226_MASK_ENABLE, &alert);
+ if (ret < 0)
+ return ret;
+
alert &= INA226_CVRF;
- } else {
+ break;
+ case ina219:
ret = regmap_read(chip->regmap,
INA2XX_BUS_VOLTAGE, &alert);
+ if (ret < 0)
+ return ret;
alert &= INA219_CNVR;
+ break;
+ default:
+ return -EINVAL;
}
- if (ret < 0)
- return ret;
-
return !!alert;
}
@@ -988,16 +1012,22 @@ static int ina2xx_probe(struct i2c_client *client)
/* Patch the current config register with default. */
val = chip->config->config_default;
- if (type == ina226) {
+ switch (type) {
+ case ina226:
+ case ina236:
ina226_set_average(chip, INA226_DEFAULT_AVG, &val);
ina226_set_int_time_vbus(chip, INA226_DEFAULT_IT, &val);
ina226_set_int_time_vshunt(chip, INA226_DEFAULT_IT, &val);
- } else {
+ break;
+ case ina219:
chip->avg = 1;
ina219_set_int_time_vbus(chip, INA219_DEFAULT_IT, &val);
ina219_set_int_time_vshunt(chip, INA219_DEFAULT_IT, &val);
ina219_set_vbus_range_denom(chip, INA219_DEFAULT_BRNG, &val);
ina219_set_vshunt_pga_gain(chip, INA219_DEFAULT_PGA, &val);
+ break;
+ default:
+ return -EINVAL;
}
ret = ina2xx_init(chip, val);
@@ -1007,14 +1037,20 @@ static int ina2xx_probe(struct i2c_client *client)
}
indio_dev->modes = INDIO_DIRECT_MODE;
- if (type == ina226) {
+ switch (type) {
+ case ina226:
+ case ina236:
indio_dev->channels = ina226_channels;
indio_dev->num_channels = ARRAY_SIZE(ina226_channels);
indio_dev->info = &ina226_info;
- } else {
+ break;
+ case ina219:
indio_dev->channels = ina219_channels;
indio_dev->num_channels = ARRAY_SIZE(ina219_channels);
indio_dev->info = &ina219_info;
+ break;
+ default:
+ return -EINVAL;
}
indio_dev->name = id ? id->name : chip->config->name;
@@ -1047,6 +1083,7 @@ static const struct i2c_device_id ina2xx_id[] = {
{ "ina226", ina226 },
{ "ina230", ina226 },
{ "ina231", ina226 },
+ { "ina236", ina236 },
{ }
};
MODULE_DEVICE_TABLE(i2c, ina2xx_id);
@@ -1072,6 +1109,10 @@ static const struct of_device_id ina2xx_of_match[] = {
.compatible = "ti,ina231",
.data = (void *)ina226
},
+ {
+ .compatible = "ti,ina236",
+ .data = (void *)ina236
+ },
{ }
};
MODULE_DEVICE_TABLE(of, ina2xx_of_match);
diff --git a/drivers/iio/adc/ltc2309.c b/drivers/iio/adc/ltc2309.c
index 5f0d947d0615..316256edf150 100644
--- a/drivers/iio/adc/ltc2309.c
+++ b/drivers/iio/adc/ltc2309.c
@@ -1,8 +1,10 @@
// SPDX-License-Identifier: GPL-2.0
/*
+ * The LTC2305 is a 2-Channel, 12-Bit SAR ADC with an I2C Interface.
* The LTC2309 is an 8-Channel, 12-Bit SAR ADC with an I2C Interface.
*
* Datasheet:
+ * https://www.analog.com/media/en/technical-documentation/data-sheets/23015fb.pdf
* https://www.analog.com/media/en/technical-documentation/data-sheets/2309fd.pdf
*
* Copyright (c) 2023, Liam Beguin <liambeguin@gmail.com>
@@ -41,23 +43,30 @@ struct ltc2309 {
};
/* Order matches expected channel address, See datasheet Table 1. */
+enum ltc2305_channels {
+ LTC2305_CH0_CH1 = 0x0,
+ LTC2305_CH1_CH0 = 0x4,
+ LTC2305_CH0 = 0x8,
+ LTC2305_CH1 = 0xc,
+};
+
enum ltc2309_channels {
- LTC2309_CH0_CH1 = 0,
- LTC2309_CH2_CH3,
- LTC2309_CH4_CH5,
- LTC2309_CH6_CH7,
- LTC2309_CH1_CH0,
- LTC2309_CH3_CH2,
- LTC2309_CH5_CH4,
- LTC2309_CH7_CH6,
- LTC2309_CH0,
- LTC2309_CH2,
- LTC2309_CH4,
- LTC2309_CH6,
- LTC2309_CH1,
- LTC2309_CH3,
- LTC2309_CH5,
- LTC2309_CH7,
+ LTC2309_CH0_CH1 = 0x0,
+ LTC2309_CH2_CH3 = 0x1,
+ LTC2309_CH4_CH5 = 0x2,
+ LTC2309_CH6_CH7 = 0x3,
+ LTC2309_CH1_CH0 = 0x4,
+ LTC2309_CH3_CH2 = 0x5,
+ LTC2309_CH5_CH4 = 0x6,
+ LTC2309_CH7_CH6 = 0x7,
+ LTC2309_CH0 = 0x8,
+ LTC2309_CH2 = 0x9,
+ LTC2309_CH4 = 0xa,
+ LTC2309_CH6 = 0xb,
+ LTC2309_CH1 = 0xc,
+ LTC2309_CH3 = 0xd,
+ LTC2309_CH5 = 0xe,
+ LTC2309_CH7 = 0xf,
};
#define LTC2309_CHAN(_chan, _addr) { \
@@ -80,6 +89,13 @@ enum ltc2309_channels {
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
}
+static const struct iio_chan_spec ltc2305_channels[] = {
+ LTC2309_CHAN(0, LTC2305_CH0),
+ LTC2309_CHAN(1, LTC2305_CH1),
+ LTC2309_DIFF_CHAN(0, 1, LTC2305_CH0_CH1),
+ LTC2309_DIFF_CHAN(1, 0, LTC2305_CH1_CH0),
+};
+
static const struct iio_chan_spec ltc2309_channels[] = {
LTC2309_CHAN(0, LTC2309_CH0),
LTC2309_CHAN(1, LTC2309_CH1),
@@ -99,6 +115,24 @@ static const struct iio_chan_spec ltc2309_channels[] = {
LTC2309_DIFF_CHAN(7, 6, LTC2309_CH7_CH6),
};
+struct ltc2309_chip_info {
+ const char *name;
+ const struct iio_chan_spec *channels;
+ int num_channels;
+};
+
+static const struct ltc2309_chip_info ltc2305_chip_info = {
+ .name = "ltc2305",
+ .channels = ltc2305_channels,
+ .num_channels = ARRAY_SIZE(ltc2305_channels),
+};
+
+static const struct ltc2309_chip_info ltc2309_chip_info = {
+ .name = "ltc2309",
+ .channels = ltc2309_channels,
+ .num_channels = ARRAY_SIZE(ltc2309_channels),
+};
+
static int ltc2309_read_raw_channel(struct ltc2309 *ltc2309,
unsigned long address, int *val)
{
@@ -158,6 +192,7 @@ static const struct iio_info ltc2309_info = {
static int ltc2309_probe(struct i2c_client *client)
{
+ const struct ltc2309_chip_info *chip_info;
struct iio_dev *indio_dev;
struct ltc2309 *ltc2309;
int ret;
@@ -167,13 +202,15 @@ static int ltc2309_probe(struct i2c_client *client)
return -ENOMEM;
ltc2309 = iio_priv(indio_dev);
+ chip_info = i2c_get_match_data(client);
+
ltc2309->dev = &indio_dev->dev;
ltc2309->client = client;
- indio_dev->name = "ltc2309";
+ indio_dev->name = chip_info->name;
indio_dev->modes = INDIO_DIRECT_MODE;
- indio_dev->channels = ltc2309_channels;
- indio_dev->num_channels = ARRAY_SIZE(ltc2309_channels);
+ indio_dev->channels = chip_info->channels;
+ indio_dev->num_channels = chip_info->num_channels;
indio_dev->info = &ltc2309_info;
ret = devm_regulator_get_enable_read_voltage(&client->dev, "vref");
@@ -189,13 +226,15 @@ static int ltc2309_probe(struct i2c_client *client)
}
static const struct of_device_id ltc2309_of_match[] = {
- { .compatible = "lltc,ltc2309" },
+ { .compatible = "lltc,ltc2305", .data = &ltc2305_chip_info },
+ { .compatible = "lltc,ltc2309", .data = &ltc2309_chip_info },
{ }
};
MODULE_DEVICE_TABLE(of, ltc2309_of_match);
static const struct i2c_device_id ltc2309_id[] = {
- { "ltc2309" },
+ { "ltc2305", (kernel_ulong_t)&ltc2305_chip_info },
+ { "ltc2309", (kernel_ulong_t)&ltc2309_chip_info },
{ }
};
MODULE_DEVICE_TABLE(i2c, ltc2309_id);
diff --git a/drivers/iio/adc/max11410.c b/drivers/iio/adc/max11410.c
index 511b2f14dfaf..69351f4f10bb 100644
--- a/drivers/iio/adc/max11410.c
+++ b/drivers/iio/adc/max11410.c
@@ -912,8 +912,8 @@ static int max11410_self_calibrate(struct max11410_state *st)
static int max11410_probe(struct spi_device *spi)
{
- const char *vrefp_regs[] = { "vref0p", "vref1p", "vref2p" };
- const char *vrefn_regs[] = { "vref0n", "vref1n", "vref2n" };
+ static const char * const vrefp_regs[] = { "vref0p", "vref1p", "vref2p" };
+ static const char * const vrefn_regs[] = { "vref0n", "vref1n", "vref2n" };
struct device *dev = &spi->dev;
struct max11410_state *st;
struct iio_dev *indio_dev;
diff --git a/drivers/iio/adc/max1363.c b/drivers/iio/adc/max1363.c
index 9dd547e62b6c..4d0b79cfeb27 100644
--- a/drivers/iio/adc/max1363.c
+++ b/drivers/iio/adc/max1363.c
@@ -121,7 +121,7 @@ enum max1363_modes {
};
/**
- * struct max1363_chip_info - chip specifc information
+ * struct max1363_chip_info - chip specific information
* @info: iio core function callbacks structure
* @channels: channel specification
* @num_channels: number of channels
@@ -149,7 +149,6 @@ struct max1363_chip_info {
* @configbyte: cache of current device config byte
* @chip_info: chip model specific constants, available modes, etc.
* @current_mode: the scan mode of this chip
- * @requestedmask: a valid requested set of channels
* @lock: lock to ensure state is consistent
* @monitor_on: whether monitor mode is enabled
* @monitor_speed: parameter corresponding to device monitor speed setting
@@ -169,7 +168,6 @@ struct max1363_state {
u8 configbyte;
const struct max1363_chip_info *chip_info;
const struct max1363_mode *current_mode;
- u32 requestedmask;
struct mutex lock;
/* Using monitor modes and buffer at the same time is
@@ -637,48 +635,51 @@ static const enum max1363_modes max11644_mode_list[] = {
static const struct iio_chan_spec max11646_channels[] = MAX1363_2X_CHANS(10);
static const struct iio_chan_spec max11644_channels[] = MAX1363_2X_CHANS(12);
-enum { max1361,
- max1362,
- max1363,
- max1364,
- max1036,
- max1037,
- max1038,
- max1039,
- max1136,
- max1137,
- max1138,
- max1139,
- max1236,
- max1237,
- max1238,
- max1239,
- max11600,
- max11601,
- max11602,
- max11603,
- max11604,
- max11605,
- max11606,
- max11607,
- max11608,
- max11609,
- max11610,
- max11611,
- max11612,
- max11613,
- max11614,
- max11615,
- max11616,
- max11617,
- max11644,
- max11645,
- max11646,
- max11647
+enum {
+ max1361,
+ max1362,
+ max1363,
+ max1364,
+ max1036,
+ max1037,
+ max1038,
+ max1039,
+ max1136,
+ max1137,
+ max1138,
+ max1139,
+ max1236,
+ max1237,
+ max1238,
+ max1239,
+ max11600,
+ max11601,
+ max11602,
+ max11603,
+ max11604,
+ max11605,
+ max11606,
+ max11607,
+ max11608,
+ max11609,
+ max11610,
+ max11611,
+ max11612,
+ max11613,
+ max11614,
+ max11615,
+ max11616,
+ max11617,
+ max11644,
+ max11645,
+ max11646,
+ max11647,
};
-static const int max1363_monitor_speeds[] = { 133000, 665000, 33300, 16600,
- 8300, 4200, 2000, 1000 };
+static const int max1363_monitor_speeds[] = {
+ 133000, 665000, 33300, 16600,
+ 8300, 4200, 2000, 1000,
+};
static ssize_t max1363_monitor_show_freq(struct device *dev,
struct device_attribute *attr,
diff --git a/drivers/iio/adc/mcp3564.c b/drivers/iio/adc/mcp3564.c
index fcdf13f49c48..36675563829e 100644
--- a/drivers/iio/adc/mcp3564.c
+++ b/drivers/iio/adc/mcp3564.c
@@ -349,7 +349,7 @@ struct mcp3564_chip_info {
* struct mcp3564_state - working data for a ADC device
* @chip_info: chip specific data
* @spi: SPI device structure
- * @vref_mv: voltage reference value in miliVolts
+ * @vref_mv: voltage reference value in millivolts
* @lock: synchronize access to driver's state members
* @dev_addr: hardware device address
* @oversampling: the index inside oversampling list of the ADC
diff --git a/drivers/iio/adc/men_z188_adc.c b/drivers/iio/adc/men_z188_adc.c
index 90919d282e7b..5bd334ec5655 100644
--- a/drivers/iio/adc/men_z188_adc.c
+++ b/drivers/iio/adc/men_z188_adc.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
- * MEN 16z188 Analog to Digial Converter
+ * MEN 16z188 Analog to Digital Converter
*
* Copyright (C) 2014 MEN Mikroelektronik GmbH (www.men.de)
* Author: Johannes Thumshirn <johannes.thumshirn@men.de>
diff --git a/drivers/iio/adc/meson_saradc.c b/drivers/iio/adc/meson_saradc.c
index 47cd350498a0..23991a3612bd 100644
--- a/drivers/iio/adc/meson_saradc.c
+++ b/drivers/iio/adc/meson_saradc.c
@@ -792,7 +792,7 @@ static int meson_sar_adc_temp_sensor_init(struct iio_dev *indio_dev)
size_t read_len;
int ret;
- temperature_calib = devm_nvmem_cell_get(dev, "temperature_calib");
+ temperature_calib = nvmem_cell_get(dev, "temperature_calib");
if (IS_ERR(temperature_calib)) {
ret = PTR_ERR(temperature_calib);
@@ -806,13 +806,9 @@ static int meson_sar_adc_temp_sensor_init(struct iio_dev *indio_dev)
return dev_err_probe(dev, ret, "failed to get temperature_calib cell\n");
}
- 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);
+ nvmem_cell_put(temperature_calib);
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) {
@@ -820,6 +816,11 @@ static int meson_sar_adc_temp_sensor_init(struct iio_dev *indio_dev)
return dev_err_probe(dev, -EINVAL, "invalid read size of temperature_calib cell\n");
}
+ 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");
+
trimming_bits = priv->param->temperature_trimming_bits;
trimming_mask = BIT(trimming_bits) - 1;
@@ -1313,6 +1314,11 @@ static const struct meson_sar_adc_data meson_sar_adc_g12a_data = {
.name = "meson-g12a-saradc",
};
+static const struct meson_sar_adc_data meson_sar_adc_s4_data = {
+ .param = &meson_sar_adc_g12a_param,
+ .name = "meson-s4-saradc",
+};
+
static const struct of_device_id meson_sar_adc_of_match[] = {
{
.compatible = "amlogic,meson8-saradc",
@@ -1341,6 +1347,9 @@ static const struct of_device_id meson_sar_adc_of_match[] = {
}, {
.compatible = "amlogic,meson-g12a-saradc",
.data = &meson_sar_adc_g12a_data,
+ }, {
+ .compatible = "amlogic,meson-s4-saradc",
+ .data = &meson_sar_adc_s4_data,
},
{ }
};
diff --git a/drivers/iio/adc/mt6359-auxadc.c b/drivers/iio/adc/mt6359-auxadc.c
index f426a289e867..6b9ed9b1fde2 100644
--- a/drivers/iio/adc/mt6359-auxadc.c
+++ b/drivers/iio/adc/mt6359-auxadc.c
@@ -322,7 +322,7 @@ static const struct mtk_pmic_auxadc_chan mt6359_auxadc_ch_desc[] = {
MTK_PMIC_ADC_CHAN(BATADC, PMIC_AUXADC_RQST0, 0, PMIC_AUXADC_IMP1, 15, 128, 7, 2),
MTK_PMIC_ADC_CHAN(BAT_TEMP, PMIC_AUXADC_RQST0, 3, PMIC_AUXADC_IMP1, 15, 8, 5, 2),
MTK_PMIC_ADC_CHAN(CHIP_TEMP, PMIC_AUXADC_RQST0, 4, PMIC_AUXADC_IMP1, 15, 8, 1, 1),
- MTK_PMIC_ADC_CHAN(ACCDET, PMIC_AUXADC_RQST0, 5, PMIC_AUXADC_IMP1, 15 ,8, 1, 1),
+ MTK_PMIC_ADC_CHAN(ACCDET, PMIC_AUXADC_RQST0, 5, PMIC_AUXADC_IMP1, 15, 8, 1, 1),
MTK_PMIC_ADC_CHAN(VDCXO, PMIC_AUXADC_RQST0, 6, PMIC_AUXADC_IMP1, 15, 8, 3, 2),
MTK_PMIC_ADC_CHAN(TSX_TEMP, PMIC_AUXADC_RQST0, 7, PMIC_AUXADC_IMP1, 15, 128, 1, 1),
MTK_PMIC_ADC_CHAN(HPOFS_CAL, PMIC_AUXADC_RQST0, 9, PMIC_AUXADC_IMP1, 15, 256, 1, 1),
diff --git a/drivers/iio/adc/nau7802.c b/drivers/iio/adc/nau7802.c
index 458544cb8ee4..970afb27b839 100644
--- a/drivers/iio/adc/nau7802.c
+++ b/drivers/iio/adc/nau7802.c
@@ -55,7 +55,6 @@ struct nau7802_state {
struct mutex data_lock;
u32 vref_mv;
u32 conversion_count;
- u32 min_conversions;
u8 sample_rate;
u32 scale_avail[8];
struct completion value_ok;
@@ -257,7 +256,7 @@ static int nau7802_read_poll(struct iio_dev *indio_dev,
/*
* Because there is actually only one ADC for both channels, we have to
* wait for enough conversions to happen before getting a significant
- * value when changing channels and the values are far appart.
+ * value when changing channels and the values are far apart.
*/
do {
ret = i2c_smbus_read_byte_data(st->client, NAU7802_REG_PUCTRL);
diff --git a/drivers/iio/adc/npcm_adc.c b/drivers/iio/adc/npcm_adc.c
index c8283873cdee..ddabb9600d46 100644
--- a/drivers/iio/adc/npcm_adc.c
+++ b/drivers/iio/adc/npcm_adc.c
@@ -38,7 +38,7 @@ struct npcm_adc {
* read access from userspace. Reading a raw value requires a sequence
* of register writes, then a wait for a event and finally a register
* read, during which userspace could issue another read request.
- * This lock protects a read access from ocurring before another one
+ * This lock protects a read access from occurring before another one
* has finished.
*/
struct mutex lock;
diff --git a/drivers/iio/adc/nxp-sar-adc.c b/drivers/iio/adc/nxp-sar-adc.c
index 58103bf16aff..9d9f2c76bed4 100644
--- a/drivers/iio/adc/nxp-sar-adc.c
+++ b/drivers/iio/adc/nxp-sar-adc.c
@@ -247,7 +247,8 @@ static inline void nxp_sar_adc_calibration_start(void __iomem *base)
static inline int nxp_sar_adc_calibration_wait(void __iomem *base)
{
- u32 msr, ret;
+ u32 msr;
+ int ret;
ret = readl_poll_timeout(NXP_SAR_ADC_MSR(base), msr,
!FIELD_GET(NXP_SAR_ADC_MSR_CALBUSY, msr),
diff --git a/drivers/iio/adc/pac1921.c b/drivers/iio/adc/pac1921.c
index a0227b57f238..bce7185953ec 100644
--- a/drivers/iio/adc/pac1921.c
+++ b/drivers/iio/adc/pac1921.c
@@ -856,7 +856,7 @@ static ssize_t pac1921_format_scale_avail(const int (*const scales_tbl)[2],
/*
* Read available scales for a specific channel
*
- * NOTE: using extended info insted of iio.read_avail() because access to
+ * NOTE: using extended info instead of iio.read_avail() because access to
* current scales must be locked as they depend on shunt resistor which may
* change runtime. Caller of iio.read_avail() would access the table unlocked
* instead.
diff --git a/drivers/iio/adc/pac1934.c b/drivers/iio/adc/pac1934.c
index 712b5e9caba6..23055405a6e0 100644
--- a/drivers/iio/adc/pac1934.c
+++ b/drivers/iio/adc/pac1934.c
@@ -1351,7 +1351,7 @@ static int pac1934_prep_iio_channels(struct pac1934_chip_info *info, struct iio_
dyn_ch_struct = devm_kzalloc(dev, channel_size, GFP_KERNEL);
if (!dyn_ch_struct)
- return -EINVAL;
+ return -ENOMEM;
tmp_data = dyn_ch_struct;
diff --git a/drivers/iio/adc/palmas_gpadc.c b/drivers/iio/adc/palmas_gpadc.c
index 3f433064618e..f777986a6aba 100644
--- a/drivers/iio/adc/palmas_gpadc.c
+++ b/drivers/iio/adc/palmas_gpadc.c
@@ -105,7 +105,7 @@ struct palmas_gpadc_thresholds {
* of register writes, then a wait for a completion callback,
* and finally a register read, during which userspace could issue
* another read request. This lock protects a read access from
- * ocurring before another one has finished.
+ * occurring before another one has finished.
*
* This is the palmas_gpadc structure to store run-time information
* and pointers for this driver instance.
@@ -521,16 +521,16 @@ static int palmas_gpadc_get_low_threshold_raw(struct palmas_gpadc *adc,
val = (val * 1000) / adc->adc_info[adc_chan].gain;
- if (adc->adc_info[adc_chan].is_uncalibrated) {
+ if (adc->adc_info[adc_chan].is_uncalibrated) {
/* 2% worse */
min_gain_error -= 20;
min_offset_error = -36;
- } else {
+ } else {
val = (val * adc->adc_info[adc_chan].gain_error -
adc->adc_info[adc_chan].offset) /
1000;
min_offset_error = -2;
- }
+ }
return palmas_gpadc_threshold_with_tolerance(val,
min_INL,
diff --git a/drivers/iio/adc/qcom-spmi-adc5-gen3.c b/drivers/iio/adc/qcom-spmi-adc5-gen3.c
new file mode 100644
index 000000000000..f8168a14b907
--- /dev/null
+++ b/drivers/iio/adc/qcom-spmi-adc5-gen3.c
@@ -0,0 +1,860 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
+ */
+
+#include <linux/auxiliary_bus.h>
+#include <linux/bitfield.h>
+#include <linux/bits.h>
+#include <linux/cleanup.h>
+#include <linux/completion.h>
+#include <linux/container_of.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/device/devres.h>
+#include <linux/dev_printk.h>
+#include <linux/err.h>
+#include <linux/export.h>
+#include <linux/iio/adc/qcom-adc5-gen3-common.h>
+#include <linux/iio/iio.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mod_devicetable.h>
+#include <linux/mutex.h>
+#include <linux/platform_device.h>
+#include <linux/property.h>
+#include <linux/regmap.h>
+#include <linux/types.h>
+#include <linux/unaligned.h>
+
+#define ADC5_GEN3_VADC_SDAM 0x0
+
+struct adc5_chip;
+
+/**
+ * struct adc5_channel_prop - ADC channel structure
+ * @common_props: structure with ADC channel properties (common to TM usage).
+ * @adc_tm: indicates TM type if the channel is used for TM measurements.
+ * @chip: pointer to top-level ADC device structure.
+ */
+struct adc5_channel_prop {
+ struct adc5_channel_common_prop common_props;
+ int adc_tm;
+ struct adc5_chip *chip;
+};
+
+/**
+ * struct adc5_chip - ADC private structure.
+ * @dev: SPMI ADC5 Gen3 device.
+ * @dev_data: Top-level ADC device data.
+ * @nchannels: number of ADC channels.
+ * @chan_props: array of ADC channel properties.
+ * @iio_chans: array of IIO channels specification.
+ * @complete: ADC result notification after interrupt is received.
+ * @lock: ADC lock for access to the peripheral, to prevent concurrent
+ * requests from multiple clients.
+ * @data: software configuration data.
+ * @n_tm_channels: number of ADC channels used for TM measurements.
+ * @handler: TM callback to be called for threshold violation interrupt
+ * on first SDAM.
+ * @tm_aux: pointer to auxiliary TM device.
+ */
+struct adc5_chip {
+ struct device *dev;
+ struct adc5_device_data dev_data;
+ unsigned int nchannels;
+ struct adc5_channel_prop *chan_props;
+ struct iio_chan_spec *iio_chans;
+ struct completion complete;
+ struct mutex lock;
+ const struct adc5_data *data;
+ unsigned int n_tm_channels;
+ void (*handler)(struct auxiliary_device *tm_aux);
+ struct auxiliary_device *tm_aux;
+};
+
+int adc5_gen3_read(struct adc5_device_data *adc, unsigned int sdam_index,
+ u16 offset, u8 *data, int len)
+{
+ return regmap_bulk_read(adc->regmap,
+ adc->base[sdam_index].base_addr + offset,
+ data, len);
+}
+EXPORT_SYMBOL_NS_GPL(adc5_gen3_read, "QCOM_SPMI_ADC5_GEN3");
+
+int adc5_gen3_write(struct adc5_device_data *adc, unsigned int sdam_index,
+ u16 offset, u8 *data, int len)
+{
+ return regmap_bulk_write(adc->regmap,
+ adc->base[sdam_index].base_addr + offset,
+ data, len);
+}
+EXPORT_SYMBOL_NS_GPL(adc5_gen3_write, "QCOM_SPMI_ADC5_GEN3");
+
+static int adc5_gen3_read_voltage_data(struct adc5_chip *adc, u16 *data)
+{
+ u8 rslt[2];
+ int ret;
+
+ ret = adc5_gen3_read(&adc->dev_data, ADC5_GEN3_VADC_SDAM,
+ ADC5_GEN3_CH_DATA0(0), rslt, sizeof(rslt));
+ if (ret)
+ return ret;
+
+ *data = get_unaligned_le16(rslt);
+
+ if (*data == ADC5_USR_DATA_CHECK) {
+ dev_err(adc->dev, "Invalid data:%#x\n", *data);
+ return -EINVAL;
+ }
+
+ dev_dbg(adc->dev, "voltage raw code:%#x\n", *data);
+
+ return 0;
+}
+
+void adc5_gen3_update_dig_param(struct adc5_channel_common_prop *prop, u8 *data)
+{
+ /* Update calibration select and decimation ratio select */
+ *data &= ~(ADC5_GEN3_DIG_PARAM_CAL_SEL_MASK | ADC5_GEN3_DIG_PARAM_DEC_RATIO_SEL_MASK);
+ *data |= FIELD_PREP(ADC5_GEN3_DIG_PARAM_CAL_SEL_MASK, prop->cal_method);
+ *data |= FIELD_PREP(ADC5_GEN3_DIG_PARAM_DEC_RATIO_SEL_MASK, prop->decimation);
+}
+EXPORT_SYMBOL_NS_GPL(adc5_gen3_update_dig_param, "QCOM_SPMI_ADC5_GEN3");
+
+#define ADC5_GEN3_READ_CONFIG_REGS 7
+
+static int adc5_gen3_configure(struct adc5_chip *adc,
+ struct adc5_channel_common_prop *prop)
+{
+ u8 buf[ADC5_GEN3_READ_CONFIG_REGS];
+ u8 conv_req = 0;
+ int ret;
+
+ ret = adc5_gen3_read(&adc->dev_data, ADC5_GEN3_VADC_SDAM, ADC5_GEN3_SID,
+ buf, sizeof(buf));
+ if (ret)
+ return ret;
+
+ /* Write SID */
+ buf[0] = FIELD_PREP(ADC5_GEN3_SID_MASK, prop->sid);
+
+ /*
+ * Use channel 0 by default for immediate conversion and to indicate
+ * there is an actual conversion request
+ */
+ buf[1] = ADC5_GEN3_CHAN_CONV_REQ | 0;
+
+ buf[2] = ADC5_GEN3_TIME_IMMEDIATE;
+
+ /* Digital param selection */
+ adc5_gen3_update_dig_param(prop, &buf[3]);
+
+ /* Update fast average sample value */
+ buf[4] = FIELD_PREP(ADC5_GEN3_FAST_AVG_CTL_SAMPLES_MASK,
+ prop->avg_samples) | ADC5_GEN3_FAST_AVG_CTL_EN;
+
+ /* Select ADC channel */
+ buf[5] = prop->channel;
+
+ /* Select HW settle delay for channel */
+ buf[6] = FIELD_PREP(ADC5_GEN3_HW_SETTLE_DELAY_MASK,
+ prop->hw_settle_time_us);
+
+ reinit_completion(&adc->complete);
+
+ ret = adc5_gen3_write(&adc->dev_data, ADC5_GEN3_VADC_SDAM, ADC5_GEN3_SID,
+ buf, sizeof(buf));
+ if (ret)
+ return ret;
+
+ conv_req = ADC5_GEN3_CONV_REQ_REQ;
+ return adc5_gen3_write(&adc->dev_data, ADC5_GEN3_VADC_SDAM,
+ ADC5_GEN3_CONV_REQ, &conv_req, sizeof(conv_req));
+}
+
+/*
+ * Worst case delay from PBS in readying handshake bit can be up to 15ms, when
+ * PBS is busy running other simultaneous transactions, while in the best case,
+ * it is already ready at this point. Assigning polling delay and retry count
+ * accordingly.
+ */
+
+#define ADC5_GEN3_HS_DELAY_US 100
+#define ADC5_GEN3_HS_RETRY_COUNT 150
+
+int adc5_gen3_poll_wait_hs(struct adc5_device_data *adc,
+ unsigned int sdam_index)
+{
+ u8 conv_req = ADC5_GEN3_CONV_REQ_REQ;
+ int ret, count;
+ u8 status = 0;
+
+ for (count = 0; count < ADC5_GEN3_HS_RETRY_COUNT; count++) {
+ ret = adc5_gen3_read(adc, sdam_index, ADC5_GEN3_HS, &status, sizeof(status));
+ if (ret)
+ return ret;
+
+ if (status == ADC5_GEN3_HS_READY) {
+ ret = adc5_gen3_read(adc, sdam_index, ADC5_GEN3_CONV_REQ,
+ &conv_req, sizeof(conv_req));
+ if (ret)
+ return ret;
+
+ if (!conv_req)
+ return 0;
+ }
+
+ fsleep(ADC5_GEN3_HS_DELAY_US);
+ }
+
+ pr_err("Setting HS ready bit timed out, sdam_index:%d, status:%#x\n",
+ sdam_index, status);
+ return -ETIMEDOUT;
+}
+EXPORT_SYMBOL_NS_GPL(adc5_gen3_poll_wait_hs, "QCOM_SPMI_ADC5_GEN3");
+
+int adc5_gen3_status_clear(struct adc5_device_data *adc,
+ int sdam_index, u16 offset, u8 *val, int len)
+{
+ u8 value;
+ int ret;
+
+ ret = adc5_gen3_write(adc, sdam_index, offset, val, len);
+ if (ret)
+ return ret;
+
+ /* To indicate conversion request is only to clear a status */
+ value = 0;
+ ret = adc5_gen3_write(adc, sdam_index, ADC5_GEN3_PERPH_CH, &value,
+ sizeof(value));
+ if (ret)
+ return ret;
+
+ value = ADC5_GEN3_CONV_REQ_REQ;
+ return adc5_gen3_write(adc, sdam_index, ADC5_GEN3_CONV_REQ, &value,
+ sizeof(value));
+}
+EXPORT_SYMBOL_NS_GPL(adc5_gen3_status_clear, "QCOM_SPMI_ADC5_GEN3");
+
+/*
+ * Worst case delay from PBS for conversion time can be up to 500ms, when PBS
+ * has timed out twice, once for the initial attempt and once for a retry of
+ * the same transaction.
+ */
+
+#define ADC5_GEN3_CONV_TIMEOUT_MS 501
+
+static int adc5_gen3_do_conversion(struct adc5_chip *adc,
+ struct adc5_channel_common_prop *prop,
+ u16 *data_volt)
+{
+ unsigned long rc;
+ int ret;
+ u8 val;
+
+ guard(mutex)(&adc->lock);
+ ret = adc5_gen3_poll_wait_hs(&adc->dev_data, ADC5_GEN3_VADC_SDAM);
+ if (ret)
+ return ret;
+
+ ret = adc5_gen3_configure(adc, prop);
+ if (ret) {
+ dev_err(adc->dev, "ADC configure failed with %d\n", ret);
+ return ret;
+ }
+
+ /* No support for polling mode at present */
+ rc = wait_for_completion_timeout(&adc->complete,
+ msecs_to_jiffies(ADC5_GEN3_CONV_TIMEOUT_MS));
+ if (!rc) {
+ dev_err(adc->dev, "Reading ADC channel %s timed out\n",
+ prop->label);
+ return -ETIMEDOUT;
+ }
+
+ ret = adc5_gen3_read_voltage_data(adc, data_volt);
+ if (ret)
+ return ret;
+
+ val = BIT(0);
+ return adc5_gen3_status_clear(&adc->dev_data, ADC5_GEN3_VADC_SDAM,
+ ADC5_GEN3_EOC_CLR, &val, 1);
+}
+
+static irqreturn_t adc5_gen3_isr(int irq, void *dev_id)
+{
+ struct adc5_chip *adc = dev_id;
+ struct device *dev = adc->dev;
+ struct auxiliary_device *adev;
+ u8 status, eoc_status, val;
+ u8 tm_status[2];
+ int ret;
+
+ ret = adc5_gen3_read(&adc->dev_data, ADC5_GEN3_VADC_SDAM,
+ ADC5_GEN3_STATUS1, &status, sizeof(status));
+ if (ret) {
+ dev_err(dev, "adc read status1 failed with %d\n", ret);
+ return IRQ_HANDLED;
+ }
+
+ ret = adc5_gen3_read(&adc->dev_data, ADC5_GEN3_VADC_SDAM,
+ ADC5_GEN3_EOC_STS, &eoc_status, sizeof(eoc_status));
+ if (ret) {
+ dev_err(dev, "adc read eoc status failed with %d\n", ret);
+ return IRQ_HANDLED;
+ }
+
+ if (status & ADC5_GEN3_STATUS1_CONV_FAULT) {
+ dev_err_ratelimited(dev,
+ "Unexpected conversion fault, status:%#x, eoc_status:%#x\n",
+ status, eoc_status);
+ val = ADC5_GEN3_CONV_ERR_CLR_REQ;
+ adc5_gen3_status_clear(&adc->dev_data, ADC5_GEN3_VADC_SDAM,
+ ADC5_GEN3_CONV_ERR_CLR, &val, 1);
+ return IRQ_HANDLED;
+ }
+
+ /* CHAN0 is the preconfigured channel for immediate conversion */
+ if (eoc_status & ADC5_GEN3_EOC_CHAN_0)
+ complete(&adc->complete);
+
+ ret = adc5_gen3_read(&adc->dev_data, ADC5_GEN3_VADC_SDAM,
+ ADC5_GEN3_TM_HIGH_STS, tm_status, sizeof(tm_status));
+ if (ret) {
+ dev_err(dev, "adc read TM status failed with %d\n", ret);
+ return IRQ_HANDLED;
+ }
+
+ dev_dbg(dev, "Interrupt status:%#x, EOC status:%#x, high:%#x, low:%#x\n",
+ status, eoc_status, tm_status[0], tm_status[1]);
+
+ if (tm_status[0] || tm_status[1]) {
+ adev = adc->tm_aux;
+ if (!adev || !adev->dev.driver) {
+ dev_err(dev, "adc_tm auxiliary device not initialized\n");
+ return IRQ_HANDLED;
+ }
+
+ adc->handler(adev);
+ }
+
+ return IRQ_HANDLED;
+}
+
+static int adc5_gen3_fwnode_xlate(struct iio_dev *indio_dev,
+ const struct fwnode_reference_args *iiospec)
+{
+ struct adc5_chip *adc = iio_priv(indio_dev);
+ int i, v_channel;
+
+ for (i = 0; i < adc->nchannels; i++) {
+ v_channel = ADC5_GEN3_V_CHAN(adc->chan_props[i].common_props);
+ if (v_channel == iiospec->args[0])
+ return i;
+ }
+
+ return -ENOENT;
+}
+
+static int adc5_gen3_read_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan, int *val,
+ int *val2, long mask)
+{
+ struct adc5_chip *adc = iio_priv(indio_dev);
+ struct adc5_channel_common_prop *prop;
+ u16 adc_code_volt;
+ int ret;
+
+ prop = &adc->chan_props[chan->address].common_props;
+
+ switch (mask) {
+ case IIO_CHAN_INFO_PROCESSED:
+ ret = adc5_gen3_do_conversion(adc, prop, &adc_code_volt);
+ if (ret)
+ return ret;
+
+ ret = qcom_adc5_hw_scale(prop->scale_fn_type, prop->prescale,
+ adc->data, adc_code_volt, val);
+ if (ret)
+ return ret;
+
+ return IIO_VAL_INT;
+ default:
+ return -EINVAL;
+ }
+}
+
+static int adc5_gen3_read_label(struct iio_dev *indio_dev,
+ const struct iio_chan_spec *chan, char *label)
+{
+ struct adc5_chip *adc = iio_priv(indio_dev);
+ struct adc5_channel_prop *prop;
+
+ prop = &adc->chan_props[chan->address];
+ return sprintf(label, "%s\n", prop->common_props.label);
+}
+
+static const struct iio_info adc5_gen3_info = {
+ .read_raw = adc5_gen3_read_raw,
+ .read_label = adc5_gen3_read_label,
+ .fwnode_xlate = adc5_gen3_fwnode_xlate,
+};
+
+struct adc5_channels {
+ unsigned int prescale_index;
+ enum iio_chan_type type;
+ long info_mask;
+ enum vadc_scale_fn_type scale_fn_type;
+};
+
+/* In these definitions, _pre refers to an index into adc5_prescale_ratios. */
+#define ADC5_CHAN(_type, _mask, _pre, _scale) \
+ { \
+ .prescale_index = _pre, \
+ .type = _type, \
+ .info_mask = _mask, \
+ .scale_fn_type = _scale, \
+ }, \
+
+#define ADC5_CHAN_TEMP(_pre, _scale) \
+ ADC5_CHAN(IIO_TEMP, BIT(IIO_CHAN_INFO_PROCESSED), _pre, _scale) \
+
+#define ADC5_CHAN_VOLT(_pre, _scale) \
+ ADC5_CHAN(IIO_VOLTAGE, BIT(IIO_CHAN_INFO_PROCESSED), _pre, _scale) \
+
+#define ADC5_CHAN_CUR(_pre, _scale) \
+ ADC5_CHAN(IIO_CURRENT, BIT(IIO_CHAN_INFO_PROCESSED), _pre, _scale) \
+
+static const struct adc5_channels adc5_gen3_chans_pmic[ADC5_MAX_CHANNEL] = {
+ [ADC5_GEN3_REF_GND] = ADC5_CHAN_VOLT(0, SCALE_HW_CALIB_DEFAULT)
+ [ADC5_GEN3_1P25VREF] = ADC5_CHAN_VOLT(0, SCALE_HW_CALIB_DEFAULT)
+ [ADC5_GEN3_VPH_PWR] = ADC5_CHAN_VOLT(1, SCALE_HW_CALIB_DEFAULT)
+ [ADC5_GEN3_VBAT_SNS_QBG] = ADC5_CHAN_VOLT(1, SCALE_HW_CALIB_DEFAULT)
+ [ADC5_GEN3_USB_SNS_V_16] = ADC5_CHAN_TEMP(8, SCALE_HW_CALIB_DEFAULT)
+ [ADC5_GEN3_VIN_DIV16_MUX] = ADC5_CHAN_TEMP(8, SCALE_HW_CALIB_DEFAULT)
+ [ADC5_GEN3_DIE_TEMP] = ADC5_CHAN_TEMP(0,
+ SCALE_HW_CALIB_PMIC_THERM_PM7)
+ [ADC5_GEN3_AMUX1_THM_100K_PU] = ADC5_CHAN_TEMP(0,
+ SCALE_HW_CALIB_THERM_100K_PU_PM7)
+ [ADC5_GEN3_AMUX2_THM_100K_PU] = ADC5_CHAN_TEMP(0,
+ SCALE_HW_CALIB_THERM_100K_PU_PM7)
+ [ADC5_GEN3_AMUX3_THM_100K_PU] = ADC5_CHAN_TEMP(0,
+ SCALE_HW_CALIB_THERM_100K_PU_PM7)
+ [ADC5_GEN3_AMUX4_THM_100K_PU] = ADC5_CHAN_TEMP(0,
+ SCALE_HW_CALIB_THERM_100K_PU_PM7)
+ [ADC5_GEN3_AMUX5_THM_100K_PU] = ADC5_CHAN_TEMP(0,
+ SCALE_HW_CALIB_THERM_100K_PU_PM7)
+ [ADC5_GEN3_AMUX6_THM_100K_PU] = ADC5_CHAN_TEMP(0,
+ SCALE_HW_CALIB_THERM_100K_PU_PM7)
+ [ADC5_GEN3_AMUX1_GPIO_100K_PU] = ADC5_CHAN_TEMP(0,
+ SCALE_HW_CALIB_THERM_100K_PU_PM7)
+ [ADC5_GEN3_AMUX2_GPIO_100K_PU] = ADC5_CHAN_TEMP(0,
+ SCALE_HW_CALIB_THERM_100K_PU_PM7)
+ [ADC5_GEN3_AMUX3_GPIO_100K_PU] = ADC5_CHAN_TEMP(0,
+ SCALE_HW_CALIB_THERM_100K_PU_PM7)
+ [ADC5_GEN3_AMUX4_GPIO_100K_PU] = ADC5_CHAN_TEMP(0,
+ SCALE_HW_CALIB_THERM_100K_PU_PM7)
+};
+
+static int adc5_gen3_get_fw_channel_data(struct adc5_chip *adc,
+ struct adc5_channel_prop *prop,
+ struct fwnode_handle *fwnode)
+{
+ const char *name = fwnode_get_name(fwnode);
+ const struct adc5_data *data = adc->data;
+ struct device *dev = adc->dev;
+ const char *channel_name;
+ u32 chan, value, sid;
+ u32 varr[2];
+ int ret;
+
+ ret = fwnode_property_read_u32(fwnode, "reg", &chan);
+ if (ret < 0)
+ return dev_err_probe(dev, ret, "invalid channel number %s\n",
+ name);
+
+ /*
+ * Value read from "reg" is virtual channel number
+ * virtual channel number = sid << 8 | channel number
+ */
+ sid = FIELD_GET(ADC5_GEN3_VIRTUAL_SID_MASK, chan);
+ chan = FIELD_GET(ADC5_GEN3_CHANNEL_MASK, chan);
+
+ if (chan > ADC5_MAX_CHANNEL)
+ return dev_err_probe(dev, -EINVAL,
+ "%s invalid channel number %d\n",
+ name, chan);
+
+ prop->common_props.channel = chan;
+ prop->common_props.sid = sid;
+
+ if (!adc->data->adc_chans[chan].info_mask)
+ return dev_err_probe(dev, -EINVAL, "Channel %#x not supported\n", chan);
+
+ channel_name = name;
+ fwnode_property_read_string(fwnode, "label", &channel_name);
+ prop->common_props.label = channel_name;
+
+ value = data->decimation[ADC5_DECIMATION_DEFAULT];
+ fwnode_property_read_u32(fwnode, "qcom,decimation", &value);
+ ret = qcom_adc5_decimation_from_dt(value, data->decimation);
+ if (ret < 0)
+ return dev_err_probe(dev, ret, "%#x invalid decimation %d\n",
+ chan, value);
+ prop->common_props.decimation = ret;
+
+ prop->common_props.prescale = adc->data->adc_chans[chan].prescale_index;
+ ret = fwnode_property_read_u32_array(fwnode, "qcom,pre-scaling", varr, 2);
+ if (!ret) {
+ ret = qcom_adc5_prescaling_from_dt(varr[0], varr[1]);
+ if (ret < 0)
+ return dev_err_probe(dev, ret,
+ "%#x invalid pre-scaling <%d %d>\n",
+ chan, varr[0], varr[1]);
+ prop->common_props.prescale = ret;
+ }
+
+ value = data->hw_settle_1[VADC_DEF_HW_SETTLE_TIME];
+ fwnode_property_read_u32(fwnode, "qcom,hw-settle-time", &value);
+ ret = qcom_adc5_hw_settle_time_from_dt(value, data->hw_settle_1);
+ if (ret < 0)
+ return dev_err_probe(dev, ret,
+ "%#x invalid hw-settle-time %d us\n",
+ chan, value);
+ prop->common_props.hw_settle_time_us = ret;
+
+ value = BIT(VADC_DEF_AVG_SAMPLES);
+ fwnode_property_read_u32(fwnode, "qcom,avg-samples", &value);
+ ret = qcom_adc5_avg_samples_from_dt(value);
+ if (ret < 0)
+ return dev_err_probe(dev, ret, "%#x invalid avg-samples %d\n",
+ chan, value);
+ prop->common_props.avg_samples = ret;
+
+ if (fwnode_property_read_bool(fwnode, "qcom,ratiometric"))
+ prop->common_props.cal_method = ADC5_RATIOMETRIC_CAL;
+ else
+ prop->common_props.cal_method = ADC5_ABSOLUTE_CAL;
+
+ prop->adc_tm = fwnode_property_read_bool(fwnode, "qcom,adc-tm");
+ if (prop->adc_tm) {
+ adc->n_tm_channels++;
+ if (adc->n_tm_channels > (adc->dev_data.num_sdams * 8 - 1))
+ return dev_err_probe(dev, -EINVAL,
+ "Number of TM nodes %u greater than channels supported:%u\n",
+ adc->n_tm_channels,
+ adc->dev_data.num_sdams * 8 - 1);
+ }
+
+ return 0;
+}
+
+static const struct adc5_data adc5_gen3_data_pmic = {
+ .full_scale_code_volt = 0x70e4,
+ .adc_chans = adc5_gen3_chans_pmic,
+ .info = &adc5_gen3_info,
+ .decimation = (unsigned int [ADC5_DECIMATION_SAMPLES_MAX])
+ { 85, 340, 1360 },
+ .hw_settle_1 = (unsigned int [VADC_HW_SETTLE_SAMPLES_MAX])
+ { 15, 100, 200, 300,
+ 400, 500, 600, 700,
+ 1000, 2000, 4000, 8000,
+ 16000, 32000, 64000, 128000 },
+};
+
+static const struct of_device_id adc5_match_table[] = {
+ {
+ .compatible = "qcom,spmi-adc5-gen3",
+ .data = &adc5_gen3_data_pmic,
+ },
+ { }
+};
+MODULE_DEVICE_TABLE(of, adc5_match_table);
+
+static int adc5_get_fw_data(struct adc5_chip *adc)
+{
+ const struct adc5_channels *adc_chan;
+ struct adc5_channel_prop *chan_props;
+ struct iio_chan_spec *iio_chan;
+ struct device *dev = adc->dev;
+ unsigned int index = 0;
+ int ret;
+
+ adc->nchannels = device_get_child_node_count(dev);
+ if (!adc->nchannels)
+ return dev_err_probe(dev, -EINVAL, "No ADC channels found\n");
+
+ adc->iio_chans = devm_kcalloc(dev, adc->nchannels,
+ sizeof(*adc->iio_chans), GFP_KERNEL);
+ if (!adc->iio_chans)
+ return -ENOMEM;
+
+ adc->chan_props = devm_kcalloc(dev, adc->nchannels,
+ sizeof(*adc->chan_props), GFP_KERNEL);
+ if (!adc->chan_props)
+ return -ENOMEM;
+
+ chan_props = adc->chan_props;
+ adc->n_tm_channels = 0;
+ iio_chan = adc->iio_chans;
+ adc->data = device_get_match_data(dev);
+
+ device_for_each_child_node_scoped(dev, child) {
+ ret = adc5_gen3_get_fw_channel_data(adc, chan_props, child);
+ if (ret)
+ return ret;
+
+ chan_props->chip = adc;
+ adc_chan = &adc->data->adc_chans[chan_props->common_props.channel];
+ chan_props->common_props.scale_fn_type = adc_chan->scale_fn_type;
+
+ iio_chan->channel = ADC5_GEN3_V_CHAN(chan_props->common_props);
+ iio_chan->info_mask_separate = adc_chan->info_mask;
+ iio_chan->type = adc_chan->type;
+ iio_chan->address = index;
+ iio_chan->indexed = 1;
+ iio_chan++;
+ chan_props++;
+ index++;
+ }
+
+ return 0;
+}
+
+static void adc5_gen3_uninit_aux(void *data)
+{
+ auxiliary_device_uninit(data);
+}
+
+static void adc5_gen3_delete_aux(void *data)
+{
+ auxiliary_device_delete(data);
+}
+
+static void adc5_gen3_aux_device_release(struct device *dev) {}
+
+static int adc5_gen3_add_aux_tm_device(struct adc5_chip *adc)
+{
+ struct tm5_aux_dev_wrapper *aux_device;
+ int i, ret, i_tm = 0;
+
+ aux_device = devm_kzalloc(adc->dev, sizeof(*aux_device), GFP_KERNEL);
+ if (!aux_device)
+ return -ENOMEM;
+
+ aux_device->aux_dev.name = "adc5_tm_gen3";
+ aux_device->aux_dev.dev.parent = adc->dev;
+ aux_device->aux_dev.dev.release = adc5_gen3_aux_device_release;
+
+ aux_device->tm_props = devm_kcalloc(adc->dev, adc->n_tm_channels,
+ sizeof(*aux_device->tm_props),
+ GFP_KERNEL);
+ if (!aux_device->tm_props)
+ return -ENOMEM;
+
+ aux_device->dev_data = &adc->dev_data;
+
+ for (i = 0; i < adc->nchannels; i++) {
+ if (!adc->chan_props[i].adc_tm)
+ continue;
+ aux_device->tm_props[i_tm] = adc->chan_props[i].common_props;
+ i_tm++;
+ }
+
+ device_set_of_node_from_dev(&aux_device->aux_dev.dev, adc->dev);
+
+ aux_device->n_tm_channels = adc->n_tm_channels;
+
+ ret = auxiliary_device_init(&aux_device->aux_dev);
+ if (ret)
+ return ret;
+
+ ret = devm_add_action_or_reset(adc->dev, adc5_gen3_uninit_aux,
+ &aux_device->aux_dev);
+ if (ret)
+ return ret;
+
+ ret = auxiliary_device_add(&aux_device->aux_dev);
+ if (ret)
+ return ret;
+ ret = devm_add_action_or_reset(adc->dev, adc5_gen3_delete_aux,
+ &aux_device->aux_dev);
+ if (ret)
+ return ret;
+
+ adc->tm_aux = &aux_device->aux_dev;
+
+ return 0;
+}
+
+void adc5_gen3_mutex_lock(struct device *dev)
+ __acquires(&adc->lock)
+{
+ struct iio_dev *indio_dev = dev_get_drvdata(dev->parent);
+ struct adc5_chip *adc = iio_priv(indio_dev);
+
+ mutex_lock(&adc->lock);
+}
+EXPORT_SYMBOL_NS_GPL(adc5_gen3_mutex_lock, "QCOM_SPMI_ADC5_GEN3");
+
+void adc5_gen3_mutex_unlock(struct device *dev)
+ __releases(&adc->lock)
+{
+ struct iio_dev *indio_dev = dev_get_drvdata(dev->parent);
+ struct adc5_chip *adc = iio_priv(indio_dev);
+
+ mutex_unlock(&adc->lock);
+}
+EXPORT_SYMBOL_NS_GPL(adc5_gen3_mutex_unlock, "QCOM_SPMI_ADC5_GEN3");
+
+int adc5_gen3_get_scaled_reading(struct device *dev,
+ struct adc5_channel_common_prop *common_props,
+ int *val)
+{
+ struct iio_dev *indio_dev = dev_get_drvdata(dev->parent);
+ struct adc5_chip *adc = iio_priv(indio_dev);
+ u16 adc_code_volt;
+ int ret;
+
+ ret = adc5_gen3_do_conversion(adc, common_props, &adc_code_volt);
+ if (ret)
+ return ret;
+
+ return qcom_adc5_hw_scale(common_props->scale_fn_type,
+ common_props->prescale,
+ adc->data, adc_code_volt, val);
+}
+EXPORT_SYMBOL_NS_GPL(adc5_gen3_get_scaled_reading, "QCOM_SPMI_ADC5_GEN3");
+
+int adc5_gen3_therm_code_to_temp(struct device *dev,
+ struct adc5_channel_common_prop *common_props,
+ u16 code, int *val)
+{
+ struct iio_dev *indio_dev = dev_get_drvdata(dev->parent);
+ struct adc5_chip *adc = iio_priv(indio_dev);
+
+ return qcom_adc5_hw_scale(common_props->scale_fn_type,
+ common_props->prescale,
+ adc->data, code, val);
+}
+EXPORT_SYMBOL_NS_GPL(adc5_gen3_therm_code_to_temp, "QCOM_SPMI_ADC5_GEN3");
+
+void adc5_gen3_register_tm_event_notifier(struct device *dev,
+ void (*handler)(struct auxiliary_device *))
+{
+ struct iio_dev *indio_dev = dev_get_drvdata(dev->parent);
+ struct adc5_chip *adc = iio_priv(indio_dev);
+
+ adc->handler = handler;
+}
+EXPORT_SYMBOL_NS_GPL(adc5_gen3_register_tm_event_notifier, "QCOM_SPMI_ADC5_GEN3");
+
+static int adc5_gen3_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct iio_dev *indio_dev;
+ struct adc5_chip *adc;
+ struct regmap *regmap;
+ int ret, i;
+ u32 *reg;
+
+ regmap = dev_get_regmap(dev->parent, NULL);
+ if (!regmap)
+ return -ENODEV;
+
+ indio_dev = devm_iio_device_alloc(dev, sizeof(*adc));
+ if (!indio_dev)
+ return -ENOMEM;
+
+ adc = iio_priv(indio_dev);
+ adc->dev_data.regmap = regmap;
+ adc->dev = dev;
+
+ ret = device_property_count_u32(dev, "reg");
+ if (ret < 0)
+ return ret;
+
+ adc->dev_data.num_sdams = ret;
+
+ reg = devm_kcalloc(dev, adc->dev_data.num_sdams, sizeof(u32),
+ GFP_KERNEL);
+ if (!reg)
+ return -ENOMEM;
+
+ ret = device_property_read_u32_array(dev, "reg", reg,
+ adc->dev_data.num_sdams);
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "Failed to read reg property\n");
+
+ adc->dev_data.base = devm_kcalloc(dev, adc->dev_data.num_sdams,
+ sizeof(*adc->dev_data.base),
+ GFP_KERNEL);
+ if (!adc->dev_data.base)
+ return -ENOMEM;
+
+ platform_set_drvdata(pdev, indio_dev);
+ init_completion(&adc->complete);
+ ret = devm_mutex_init(dev, &adc->lock);
+ if (ret)
+ return ret;
+
+ for (i = 0; i < adc->dev_data.num_sdams; i++) {
+ adc->dev_data.base[i].base_addr = reg[i];
+
+ ret = platform_get_irq(pdev, i);
+ if (ret < 0)
+ return dev_err_probe(dev, ret,
+ "Getting IRQ %d failed\n", i);
+
+ adc->dev_data.base[i].irq = ret;
+
+ adc->dev_data.base[i].irq_name = devm_kasprintf(dev, GFP_KERNEL,
+ "sdam%d", i);
+ if (!adc->dev_data.base[i].irq_name)
+ return -ENOMEM;
+ }
+
+ ret = devm_request_irq(dev, adc->dev_data.base[ADC5_GEN3_VADC_SDAM].irq,
+ adc5_gen3_isr, 0,
+ adc->dev_data.base[ADC5_GEN3_VADC_SDAM].irq_name,
+ adc);
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "Failed to request SDAM%d irq\n",
+ ADC5_GEN3_VADC_SDAM);
+
+ ret = adc5_get_fw_data(adc);
+ if (ret)
+ return ret;
+
+ if (adc->n_tm_channels > 0) {
+ ret = adc5_gen3_add_aux_tm_device(adc);
+ if (ret)
+ dev_err_probe(dev, ret,
+ "Failed to add auxiliary TM device\n");
+ }
+
+ indio_dev->name = "spmi-adc5-gen3";
+ indio_dev->modes = INDIO_DIRECT_MODE;
+ indio_dev->info = &adc5_gen3_info;
+ indio_dev->channels = adc->iio_chans;
+ indio_dev->num_channels = adc->nchannels;
+
+ return devm_iio_device_register(dev, indio_dev);
+}
+
+static struct platform_driver adc5_gen3_driver = {
+ .driver = {
+ .name = "qcom-spmi-adc5-gen3",
+ .of_match_table = adc5_match_table,
+ },
+ .probe = adc5_gen3_probe,
+};
+module_platform_driver(adc5_gen3_driver);
+
+MODULE_DESCRIPTION("Qualcomm Technologies Inc. PMIC5 Gen3 ADC driver");
+MODULE_LICENSE("GPL");
+MODULE_IMPORT_NS("QCOM_SPMI_ADC5_GEN3");
diff --git a/drivers/iio/adc/rohm-bd79124.c b/drivers/iio/adc/rohm-bd79124.c
index fc0452749b79..40d00bd0cc9d 100644
--- a/drivers/iio/adc/rohm-bd79124.c
+++ b/drivers/iio/adc/rohm-bd79124.c
@@ -75,7 +75,7 @@
/*
* The high limit, low limit and last measurement result are each stored in
- * 2 consequtive registers. 4 bits are in the high bits of the first register
+ * 2 consecutive registers. 4 bits are in the high bits of the first register
* and 8 bits in the next register.
*
* These macros return the address of the first reg for the given channel.
@@ -962,7 +962,7 @@ static int bd79124_hw_init(struct bd79124_data *data)
if (ret)
return ret;
- /* Enable writing the measured values to the regsters */
+ /* Enable writing the measured values to the registers */
ret = regmap_set_bits(data->map, BD79124_REG_GEN_CFG,
BD79124_MSK_STATS_EN);
if (ret)
diff --git a/drivers/iio/adc/sd_adc_modulator.c b/drivers/iio/adc/sd_adc_modulator.c
index 9f7a75168aac..218117c45ec8 100644
--- a/drivers/iio/adc/sd_adc_modulator.c
+++ b/drivers/iio/adc/sd_adc_modulator.c
@@ -77,6 +77,7 @@ static const struct iio_backend_ops sd_backend_ops = {
static const struct iio_backend_info sd_backend_info = {
.name = "sd-modulator",
.ops = &sd_backend_ops,
+ .caps = IIO_BACKEND_CAP_ENABLE,
};
static int iio_sd_mod_register(struct platform_device *pdev)
diff --git a/drivers/iio/adc/spear_adc.c b/drivers/iio/adc/spear_adc.c
index 50b0a607baeb..91995489bb1c 100644
--- a/drivers/iio/adc/spear_adc.c
+++ b/drivers/iio/adc/spear_adc.c
@@ -82,7 +82,7 @@ struct spear_adc_state {
* of register writes, then a wait for a completion callback,
* and finally a register read, during which userspace could issue
* another read request. This lock protects a read access from
- * ocurring before another one has finished.
+ * occurring before another one has finished.
*/
struct mutex lock;
u32 current_clk;
diff --git a/drivers/iio/adc/stm32-adc-core.c b/drivers/iio/adc/stm32-adc-core.c
index e39a4c0db25e..a42d82d61cb8 100644
--- a/drivers/iio/adc/stm32-adc-core.c
+++ b/drivers/iio/adc/stm32-adc-core.c
@@ -227,7 +227,7 @@ static int stm32h7_adc_clk_sel(struct platform_device *pdev,
if (priv->aclk) {
/*
* Asynchronous clock modes (e.g. ckmode == 0)
- * From spec: PLL output musn't exceed max rate
+ * From spec: PLL output mustn't exceed max rate
*/
rate = clk_get_rate(priv->aclk);
if (!rate) {
diff --git a/drivers/iio/adc/stm32-adc.c b/drivers/iio/adc/stm32-adc.c
index 2d7f88459c7c..46106200bb86 100644
--- a/drivers/iio/adc/stm32-adc.c
+++ b/drivers/iio/adc/stm32-adc.c
@@ -1662,7 +1662,7 @@ static irqreturn_t stm32_adc_threaded_isr(int irq, void *data)
/*
* Clear ovr bit to avoid subsequent calls to IRQ handler.
* This requires to stop ADC first. OVR bit state in ISR,
- * is propaged to CSR register by hardware.
+ * is propagated to CSR register by hardware.
*/
adc->cfg->stop_conv(indio_dev);
stm32_adc_irq_clear(indio_dev, regs->isr_ovr.mask);
diff --git a/drivers/iio/adc/sun20i-gpadc-iio.c b/drivers/iio/adc/sun20i-gpadc-iio.c
index e4dfe76e6362..861c14da75ad 100644
--- a/drivers/iio/adc/sun20i-gpadc-iio.c
+++ b/drivers/iio/adc/sun20i-gpadc-iio.c
@@ -55,7 +55,7 @@ struct sun20i_gpadc_iio {
* of register writes, then a wait for a completion callback,
* and finally a register read, during which userspace could issue
* another read request. This lock protects a read access from
- * ocurring before another one has finished.
+ * occurring before another one has finished.
*/
struct mutex lock;
};
diff --git a/drivers/iio/adc/ti-ads1015.c b/drivers/iio/adc/ti-ads1015.c
index f2a93c63ca14..c7ffe47449e2 100644
--- a/drivers/iio/adc/ti-ads1015.c
+++ b/drivers/iio/adc/ti-ads1015.c
@@ -231,7 +231,6 @@ static const struct iio_event_spec ads1015_events[] = {
}
struct ads1015_channel_data {
- bool enabled;
unsigned int pga;
unsigned int data_rate;
};
diff --git a/drivers/iio/adc/ti-ads1119.c b/drivers/iio/adc/ti-ads1119.c
index 79be71b4de96..2320be0efb50 100644
--- a/drivers/iio/adc/ti-ads1119.c
+++ b/drivers/iio/adc/ti-ads1119.c
@@ -741,8 +741,7 @@ static int ads1119_probe(struct i2c_client *client)
ret = devm_request_irq(dev, client->irq, ads1119_irq_handler,
IRQF_NO_THREAD, "ads1119", indio_dev);
if (ret)
- return dev_err_probe(dev, ret,
- "Failed to allocate irq\n");
+ return ret;
st->trig = devm_iio_trigger_alloc(dev, "%s-dev%d",
indio_dev->name,
diff --git a/drivers/iio/adc/ti-ads7950.c b/drivers/iio/adc/ti-ads7950.c
index cdc624889559..028acd42741f 100644
--- a/drivers/iio/adc/ti-ads7950.c
+++ b/drivers/iio/adc/ti-ads7950.c
@@ -47,8 +47,6 @@
#define TI_ADS7950_MAX_CHAN 16
#define TI_ADS7950_NUM_GPIOS 4
-#define TI_ADS7950_TIMESTAMP_SIZE (sizeof(int64_t) / sizeof(__be16))
-
/* val = value, dec = left shift, bits = number of bits of the mask */
#define TI_ADS7950_EXTRACT(val, dec, bits) \
(((val) >> (dec)) & ((1 << (bits)) - 1))
@@ -105,8 +103,7 @@ struct ti_ads7950_state {
* 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]
- __aligned(IIO_DMA_MINALIGN);
+ u16 rx_buf[TI_ADS7950_MAX_CHAN + 2] __aligned(IIO_DMA_MINALIGN);
u16 tx_buf[TI_ADS7950_MAX_CHAN + 2];
u16 single_tx;
u16 single_rx;
@@ -118,21 +115,6 @@ struct ti_ads7950_chip_info {
unsigned int num_channels;
};
-enum ti_ads7950_id {
- TI_ADS7950,
- TI_ADS7951,
- TI_ADS7952,
- TI_ADS7953,
- TI_ADS7954,
- TI_ADS7955,
- TI_ADS7956,
- TI_ADS7957,
- TI_ADS7958,
- TI_ADS7959,
- TI_ADS7960,
- TI_ADS7961,
-};
-
#define TI_ADS7950_V_CHAN(index, bits) \
{ \
.type = IIO_VOLTAGE, \
@@ -225,55 +207,64 @@ static DECLARE_TI_ADS7950_8_CHANNELS(ti_ads7959, 8);
static DECLARE_TI_ADS7950_12_CHANNELS(ti_ads7960, 8);
static DECLARE_TI_ADS7950_16_CHANNELS(ti_ads7961, 8);
-static const struct ti_ads7950_chip_info ti_ads7950_chip_info[] = {
- [TI_ADS7950] = {
- .channels = ti_ads7950_channels,
- .num_channels = ARRAY_SIZE(ti_ads7950_channels),
- },
- [TI_ADS7951] = {
- .channels = ti_ads7951_channels,
- .num_channels = ARRAY_SIZE(ti_ads7951_channels),
- },
- [TI_ADS7952] = {
- .channels = ti_ads7952_channels,
- .num_channels = ARRAY_SIZE(ti_ads7952_channels),
- },
- [TI_ADS7953] = {
- .channels = ti_ads7953_channels,
- .num_channels = ARRAY_SIZE(ti_ads7953_channels),
- },
- [TI_ADS7954] = {
- .channels = ti_ads7954_channels,
- .num_channels = ARRAY_SIZE(ti_ads7954_channels),
- },
- [TI_ADS7955] = {
- .channels = ti_ads7955_channels,
- .num_channels = ARRAY_SIZE(ti_ads7955_channels),
- },
- [TI_ADS7956] = {
- .channels = ti_ads7956_channels,
- .num_channels = ARRAY_SIZE(ti_ads7956_channels),
- },
- [TI_ADS7957] = {
- .channels = ti_ads7957_channels,
- .num_channels = ARRAY_SIZE(ti_ads7957_channels),
- },
- [TI_ADS7958] = {
- .channels = ti_ads7958_channels,
- .num_channels = ARRAY_SIZE(ti_ads7958_channels),
- },
- [TI_ADS7959] = {
- .channels = ti_ads7959_channels,
- .num_channels = ARRAY_SIZE(ti_ads7959_channels),
- },
- [TI_ADS7960] = {
- .channels = ti_ads7960_channels,
- .num_channels = ARRAY_SIZE(ti_ads7960_channels),
- },
- [TI_ADS7961] = {
- .channels = ti_ads7961_channels,
- .num_channels = ARRAY_SIZE(ti_ads7961_channels),
- },
+static const struct ti_ads7950_chip_info ti_ads7950_chip_info = {
+ .channels = ti_ads7950_channels,
+ .num_channels = ARRAY_SIZE(ti_ads7950_channels),
+};
+
+static const struct ti_ads7950_chip_info ti_ads7951_chip_info = {
+ .channels = ti_ads7951_channels,
+ .num_channels = ARRAY_SIZE(ti_ads7951_channels),
+};
+
+static const struct ti_ads7950_chip_info ti_ads7952_chip_info = {
+ .channels = ti_ads7952_channels,
+ .num_channels = ARRAY_SIZE(ti_ads7952_channels),
+};
+
+static const struct ti_ads7950_chip_info ti_ads7953_chip_info = {
+ .channels = ti_ads7953_channels,
+ .num_channels = ARRAY_SIZE(ti_ads7953_channels),
+};
+
+static const struct ti_ads7950_chip_info ti_ads7954_chip_info = {
+ .channels = ti_ads7954_channels,
+ .num_channels = ARRAY_SIZE(ti_ads7954_channels),
+};
+
+static const struct ti_ads7950_chip_info ti_ads7955_chip_info = {
+ .channels = ti_ads7955_channels,
+ .num_channels = ARRAY_SIZE(ti_ads7955_channels),
+};
+
+static const struct ti_ads7950_chip_info ti_ads7956_chip_info = {
+ .channels = ti_ads7956_channels,
+ .num_channels = ARRAY_SIZE(ti_ads7956_channels),
+};
+
+static const struct ti_ads7950_chip_info ti_ads7957_chip_info = {
+ .channels = ti_ads7957_channels,
+ .num_channels = ARRAY_SIZE(ti_ads7957_channels),
+};
+
+static const struct ti_ads7950_chip_info ti_ads7958_chip_info = {
+ .channels = ti_ads7958_channels,
+ .num_channels = ARRAY_SIZE(ti_ads7958_channels),
+};
+
+static const struct ti_ads7950_chip_info ti_ads7959_chip_info = {
+ .channels = ti_ads7959_channels,
+ .num_channels = ARRAY_SIZE(ti_ads7959_channels),
+};
+
+static const struct ti_ads7950_chip_info ti_ads7960_chip_info = {
+ .channels = ti_ads7960_channels,
+ .num_channels = ARRAY_SIZE(ti_ads7960_channels),
+};
+
+static const struct ti_ads7950_chip_info ti_ads7961_chip_info = {
+ .channels = ti_ads7961_channels,
+ .num_channels = ARRAY_SIZE(ti_ads7961_channels),
};
/*
@@ -313,8 +304,10 @@ static irqreturn_t ti_ads7950_trigger_handler(int irq, void *p)
if (ret < 0)
goto out;
- iio_push_to_buffers_with_timestamp(indio_dev, &st->rx_buf[2],
- iio_get_time_ns(indio_dev));
+ iio_push_to_buffers_with_ts_unaligned(indio_dev, &st->rx_buf[2],
+ sizeof(*st->rx_buf) *
+ TI_ADS7950_MAX_CHAN,
+ iio_get_time_ns(indio_dev));
out:
mutex_unlock(&st->slock);
@@ -563,7 +556,7 @@ static int ti_ads7950_probe(struct spi_device *spi)
st->spi = spi;
- info = &ti_ads7950_chip_info[spi_get_device_id(spi)->driver_data];
+ info = spi_get_device_match_data(spi);
indio_dev->name = spi_get_device_id(spi)->name;
indio_dev->modes = INDIO_DIRECT_MODE;
@@ -685,35 +678,35 @@ static void ti_ads7950_remove(struct spi_device *spi)
}
static const struct spi_device_id ti_ads7950_id[] = {
- { "ads7950", TI_ADS7950 },
- { "ads7951", TI_ADS7951 },
- { "ads7952", TI_ADS7952 },
- { "ads7953", TI_ADS7953 },
- { "ads7954", TI_ADS7954 },
- { "ads7955", TI_ADS7955 },
- { "ads7956", TI_ADS7956 },
- { "ads7957", TI_ADS7957 },
- { "ads7958", TI_ADS7958 },
- { "ads7959", TI_ADS7959 },
- { "ads7960", TI_ADS7960 },
- { "ads7961", TI_ADS7961 },
+ { "ads7950", (kernel_ulong_t)&ti_ads7950_chip_info },
+ { "ads7951", (kernel_ulong_t)&ti_ads7951_chip_info },
+ { "ads7952", (kernel_ulong_t)&ti_ads7952_chip_info },
+ { "ads7953", (kernel_ulong_t)&ti_ads7953_chip_info },
+ { "ads7954", (kernel_ulong_t)&ti_ads7954_chip_info },
+ { "ads7955", (kernel_ulong_t)&ti_ads7955_chip_info },
+ { "ads7956", (kernel_ulong_t)&ti_ads7956_chip_info },
+ { "ads7957", (kernel_ulong_t)&ti_ads7957_chip_info },
+ { "ads7958", (kernel_ulong_t)&ti_ads7958_chip_info },
+ { "ads7959", (kernel_ulong_t)&ti_ads7959_chip_info },
+ { "ads7960", (kernel_ulong_t)&ti_ads7960_chip_info },
+ { "ads7961", (kernel_ulong_t)&ti_ads7961_chip_info },
{ }
};
MODULE_DEVICE_TABLE(spi, ti_ads7950_id);
static const struct of_device_id ads7950_of_table[] = {
- { .compatible = "ti,ads7950", .data = &ti_ads7950_chip_info[TI_ADS7950] },
- { .compatible = "ti,ads7951", .data = &ti_ads7950_chip_info[TI_ADS7951] },
- { .compatible = "ti,ads7952", .data = &ti_ads7950_chip_info[TI_ADS7952] },
- { .compatible = "ti,ads7953", .data = &ti_ads7950_chip_info[TI_ADS7953] },
- { .compatible = "ti,ads7954", .data = &ti_ads7950_chip_info[TI_ADS7954] },
- { .compatible = "ti,ads7955", .data = &ti_ads7950_chip_info[TI_ADS7955] },
- { .compatible = "ti,ads7956", .data = &ti_ads7950_chip_info[TI_ADS7956] },
- { .compatible = "ti,ads7957", .data = &ti_ads7950_chip_info[TI_ADS7957] },
- { .compatible = "ti,ads7958", .data = &ti_ads7950_chip_info[TI_ADS7958] },
- { .compatible = "ti,ads7959", .data = &ti_ads7950_chip_info[TI_ADS7959] },
- { .compatible = "ti,ads7960", .data = &ti_ads7950_chip_info[TI_ADS7960] },
- { .compatible = "ti,ads7961", .data = &ti_ads7950_chip_info[TI_ADS7961] },
+ { .compatible = "ti,ads7950", .data = &ti_ads7950_chip_info },
+ { .compatible = "ti,ads7951", .data = &ti_ads7951_chip_info },
+ { .compatible = "ti,ads7952", .data = &ti_ads7952_chip_info },
+ { .compatible = "ti,ads7953", .data = &ti_ads7953_chip_info },
+ { .compatible = "ti,ads7954", .data = &ti_ads7954_chip_info },
+ { .compatible = "ti,ads7955", .data = &ti_ads7955_chip_info },
+ { .compatible = "ti,ads7956", .data = &ti_ads7956_chip_info },
+ { .compatible = "ti,ads7957", .data = &ti_ads7957_chip_info },
+ { .compatible = "ti,ads7958", .data = &ti_ads7958_chip_info },
+ { .compatible = "ti,ads7959", .data = &ti_ads7959_chip_info },
+ { .compatible = "ti,ads7960", .data = &ti_ads7960_chip_info },
+ { .compatible = "ti,ads7961", .data = &ti_ads7961_chip_info },
{ }
};
MODULE_DEVICE_TABLE(of, ads7950_of_table);
diff --git a/drivers/iio/adc/ti_am335x_adc.c b/drivers/iio/adc/ti_am335x_adc.c
index a1a28584de93..1516dd332f90 100644
--- a/drivers/iio/adc/ti_am335x_adc.c
+++ b/drivers/iio/adc/ti_am335x_adc.c
@@ -113,10 +113,10 @@ static void tiadc_step_config(struct iio_dev *indio_dev)
* There are 16 configurable steps and 8 analog input
* lines available which are shared between Touchscreen and ADC.
*
- * Steps forwards i.e. from 0 towards 16 are used by ADC
- * depending on number of input lines needed.
+ * Steps forward, i.e. from 0 towards 16, are used by ADC
+ * depending on the number of input lines needed.
* Channel would represent which analog input
- * needs to be given to ADC to digitalize data.
+ * needs to be given to ADC to digitize data.
*/
for (i = 0; i < adc_dev->channels; i++) {
int chan;
diff --git a/drivers/iio/adc/twl4030-madc.c b/drivers/iio/adc/twl4030-madc.c
index fe3b31ec976e..f0274cd74973 100644
--- a/drivers/iio/adc/twl4030-madc.c
+++ b/drivers/iio/adc/twl4030-madc.c
@@ -252,7 +252,7 @@ static const struct s16_fract twl4030_divider_ratios[16] = {
{5, 11}, /* CHANNEL 15 */
};
-/* Conversion table from -3 to 55 degrees Celcius */
+/* Conversion table from -3 to 55 degrees Celsius */
static int twl4030_therm_tbl[] = {
30800, 29500, 28300, 27100,
26000, 24900, 23900, 22900, 22000, 21100, 20300, 19400, 18700,
diff --git a/drivers/iio/adc/twl6030-gpadc.c b/drivers/iio/adc/twl6030-gpadc.c
index 3ac774ebf678..7810d6b2b668 100644
--- a/drivers/iio/adc/twl6030-gpadc.c
+++ b/drivers/iio/adc/twl6030-gpadc.c
@@ -416,7 +416,7 @@ static u8 twl6032_channel_to_reg(int channel)
{
/*
* for any prior chosen channel, when the conversion is ready
- * the result is avalable in GPCH0_LSB, GPCH0_MSB.
+ * the result is available in GPCH0_LSB, GPCH0_MSB.
*/
return TWL6032_GPADC_GPCH0_LSB;
diff --git a/drivers/iio/addac/ad74413r.c b/drivers/iio/addac/ad74413r.c
index a20b4d48c5f7..fe930ce5ee30 100644
--- a/drivers/iio/addac/ad74413r.c
+++ b/drivers/iio/addac/ad74413r.c
@@ -839,12 +839,9 @@ static int _ad74413r_get_single_adc_result(struct ad74413r_state *st,
if (ret)
return ret;
- ret = wait_for_completion_timeout(&st->adc_data_completion,
- msecs_to_jiffies(1000));
- if (!ret) {
- ret = -ETIMEDOUT;
- return ret;
- }
+ if (!wait_for_completion_timeout(&st->adc_data_completion,
+ msecs_to_jiffies(1000)))
+ return -ETIMEDOUT;
ret = regmap_read(st->regmap, AD74413R_REG_ADC_RESULT_X(channel),
&uval);
diff --git a/drivers/iio/amplifiers/Kconfig b/drivers/iio/amplifiers/Kconfig
index a8a604863eed..9e24421b5e97 100644
--- a/drivers/iio/amplifiers/Kconfig
+++ b/drivers/iio/amplifiers/Kconfig
@@ -18,7 +18,15 @@ config AD8366
AD8366 Dual-Digital Variable Gain Amplifier (VGA)
ADA4961 BiCMOS RF Digital Gain Amplifier (DGA)
ADL5240 Digitally controlled variable gain amplifier (VGA)
+ ADRF5702: 0.125 dB LSB, 8-Bit, Silicon Digital Attenuator
+ ADRF5703: 0.25 dB LSB, 7-Bit, Silicon Digital Attenuator
+ ADRF5720: 0.5 dB LSB, 6-Bit, Silicon Digital Attenuator
+ ADRF5730: 0.5 dB LSB, 6-Bit, Silicon Digital Attenuator
+ ADRF5731: 2 dB LSB, 4-Bit, Silicon Digital Attenuator
+ HMC271A: 1dB LSB 5-Bit Digital Attenuator SMT
HMC792A 0.25 dB LSB GaAs MMIC 6-Bit Digital Attenuator
+ HMC1018A: 1.0 dB LSB GaAs MMIC 5-BIT Digital Attenuator
+ HMC1019A: 0.5 dB LSB GaAs MMIC 5-BIT Digital Attenuator
HMC1119 0.25 dB LSB, 7-Bit, Silicon Digital Attenuator
To compile this driver as a module, choose M here: the
diff --git a/drivers/iio/amplifiers/ad8366.c b/drivers/iio/amplifiers/ad8366.c
index d06ac786501c..bbf41a1fb3a1 100644
--- a/drivers/iio/amplifiers/ad8366.c
+++ b/drivers/iio/amplifiers/ad8366.c
@@ -5,46 +5,52 @@
* AD8366 Dual-Digital Variable Gain Amplifier (VGA)
* ADA4961 BiCMOS RF Digital Gain Amplifier (DGA)
* ADL5240 Digitally controlled variable gain amplifier (VGA)
+ * ADRF5702: 0.125 dB LSB, 8-Bit, Silicon Digital Attenuator, 50 MHz to 20 GHz
+ * ADRF5703: 0.25 dB LSB, 7-Bit, Silicon Digital Attenuator, 9 kHz to 20 GHz
+ * ADRF5720: 0.5 dB LSB, 6-Bit, Silicon Digital Attenuator, 9 kHz to 40 GHz
+ * ADRF5730: 0.5 dB LSB, 6-Bit, Silicon Digital Attenuator, 100 MHz to 40 GHz
+ * ADRF5731: 2 dB LSB, 4-Bit, Silicon Digital Attenuator, 100 MHz to 40 GHz
+ * HMC271A: 1dB LSB 5-Bit Digital Attenuator SMT, 0.7 - 3.7 GHz
* HMC792A 0.25 dB LSB GaAs MMIC 6-Bit Digital Attenuator
+ * HMC1018A: 1.0 dB LSB GaAs MMIC 5-BIT DIGITAL ATTENUATOR, 0.1 - 30 GHz
+ * HMC1019A: 0.5 dB LSB GaAs MMIC 5-BIT DIGITAL ATTENUATOR, 0.1 - 30 GHz
* HMC1119 0.25 dB LSB, 7-Bit, Silicon Digital Attenuator
*
- * Copyright 2012-2019 Analog Devices Inc.
+ * Copyright 2012-2026 Analog Devices Inc.
*/
-#include <linux/device.h>
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/sysfs.h>
-#include <linux/spi/spi.h>
-#include <linux/regulator/consumer.h>
-#include <linux/gpio/consumer.h>
+#include <linux/bitrev.h>
+#include <linux/bits.h>
+#include <linux/dev_printk.h>
#include <linux/err.h>
+#include <linux/gpio/consumer.h>
+#include <linux/math.h>
+#include <linux/minmax.h>
+#include <linux/mod_devicetable.h>
#include <linux/module.h>
-#include <linux/bitrev.h>
+#include <linux/mutex.h>
+#include <linux/regulator/consumer.h>
+#include <linux/reset.h>
+#include <linux/spi/spi.h>
+#include <linux/types.h>
+#include <linux/unaligned.h>
#include <linux/iio/iio.h>
-#include <linux/iio/sysfs.h>
-
-enum ad8366_type {
- ID_AD8366,
- ID_ADA4961,
- ID_ADL5240,
- ID_HMC792,
- ID_HMC1119,
-};
struct ad8366_info {
+ const char *name;
int gain_min;
int gain_max;
+ int gain_step;
+ size_t num_channels;
+ size_t (*pack_code)(const unsigned char *code, size_t num_channels,
+ unsigned char *data);
};
struct ad8366_state {
struct spi_device *spi;
- struct regulator *reg;
struct mutex lock; /* protect sensor state */
- struct gpio_desc *reset_gpio;
unsigned char ch[2];
- enum ad8366_type type;
const struct ad8366_info *info;
/*
* DMA (thus cache coherency maintenance) may require the
@@ -53,60 +59,148 @@ struct ad8366_state {
unsigned char data[2] __aligned(IIO_DMA_MINALIGN);
};
-static const struct ad8366_info ad8366_infos[] = {
- [ID_AD8366] = {
- .gain_min = 4500,
- .gain_max = 20500,
- },
- [ID_ADA4961] = {
- .gain_min = -6000,
- .gain_max = 15000,
- },
- [ID_ADL5240] = {
- .gain_min = -11500,
- .gain_max = 20000,
- },
- [ID_HMC792] = {
- .gain_min = -15750,
- .gain_max = 0,
- },
- [ID_HMC1119] = {
- .gain_min = -31750,
- .gain_max = 0,
- },
-};
+static size_t ad8366_pack_code(const unsigned char *code, size_t num_channels,
+ unsigned char *data)
+{
+ u8 ch_a = bitrev8(code[0]) >> 2;
+ u8 ch_b = bitrev8(code[1]) >> 2;
+
+ put_unaligned_be16((ch_b << 6) | ch_a, &data[0]);
+ return sizeof(__be16);
+}
-static int ad8366_write(struct iio_dev *indio_dev,
- unsigned char ch_a, unsigned char ch_b)
+static size_t adrf5731_pack_code(const unsigned char *code, size_t num_channels,
+ unsigned char *data)
{
- struct ad8366_state *st = iio_priv(indio_dev);
- int ret;
+ data[0] = code[0] << 2;
+ return 1;
+}
- switch (st->type) {
- case ID_AD8366:
- ch_a = bitrev8(ch_a & 0x3F);
- ch_b = bitrev8(ch_b & 0x3F);
+static size_t hmc271_pack_code(const unsigned char *code, size_t num_channels,
+ unsigned char *data)
+{
+ data[0] = bitrev8(code[0]) >> 3;
+ return 1;
+}
- st->data[0] = ch_b >> 4;
- st->data[1] = (ch_b << 4) | (ch_a >> 2);
- break;
- case ID_ADA4961:
- st->data[0] = ch_a & 0x1F;
- break;
- case ID_ADL5240:
- st->data[0] = (ch_a & 0x3F);
- break;
- case ID_HMC792:
- case ID_HMC1119:
- st->data[0] = ch_a;
- break;
- }
+static const struct ad8366_info ad8366_chip_info = {
+ .name = "ad8366",
+ .gain_min = 4500,
+ .gain_max = 20500,
+ .gain_step = 253,
+ .num_channels = 2,
+ .pack_code = ad8366_pack_code,
+};
- ret = spi_write(st->spi, st->data, indio_dev->num_channels);
- if (ret < 0)
- dev_err(&indio_dev->dev, "write failed (%d)", ret);
+static const struct ad8366_info ada4961_chip_info = {
+ .name = "ada4961",
+ .gain_min = -6000,
+ .gain_max = 15000,
+ .gain_step = -1000,
+ .num_channels = 1,
+};
- return ret;
+static const struct ad8366_info adl5240_chip_info = {
+ .name = "adl5240",
+ .gain_min = -11500,
+ .gain_max = 20000,
+ .gain_step = 500,
+ .num_channels = 1,
+};
+
+static const struct ad8366_info adrf5702_chip_info = {
+ .name = "adrf5702",
+ .gain_min = -31875,
+ .gain_max = 0,
+ .gain_step = -125,
+ .num_channels = 1,
+};
+
+static const struct ad8366_info adrf5703_chip_info = {
+ .name = "adrf5703",
+ .gain_min = -31750,
+ .gain_max = 0,
+ .gain_step = -250,
+ .num_channels = 1,
+};
+
+static const struct ad8366_info adrf5720_chip_info = {
+ .name = "adrf5720",
+ .gain_min = -31500,
+ .gain_max = 0,
+ .gain_step = -500,
+ .num_channels = 1,
+};
+
+static const struct ad8366_info adrf5730_chip_info = {
+ .name = "adrf5730",
+ .gain_min = -31500,
+ .gain_max = 0,
+ .gain_step = -500,
+ .num_channels = 1,
+};
+
+static const struct ad8366_info adrf5731_chip_info = {
+ .name = "adrf5731",
+ .gain_min = -30000,
+ .gain_max = 0,
+ .gain_step = -2000,
+ .num_channels = 1,
+ .pack_code = adrf5731_pack_code,
+};
+
+static const struct ad8366_info hmc271_chip_info = {
+ .name = "hmc271a",
+ .gain_min = -31000,
+ .gain_max = 0,
+ .gain_step = 1000,
+ .num_channels = 1,
+ .pack_code = hmc271_pack_code,
+};
+
+static const struct ad8366_info hmc792_chip_info = {
+ .name = "hmc792a",
+ .gain_min = -15750,
+ .gain_max = 0,
+ .gain_step = 250,
+ .num_channels = 1,
+};
+
+static const struct ad8366_info hmc1018_chip_info = {
+ .name = "hmc1018a",
+ .gain_min = -31000,
+ .gain_max = 0,
+ .gain_step = 1000,
+ .num_channels = 1,
+};
+
+static const struct ad8366_info hmc1019_chip_info = {
+ .name = "hmc1019a",
+ .gain_min = -15500,
+ .gain_max = 0,
+ .gain_step = 500,
+ .num_channels = 1,
+};
+
+static const struct ad8366_info hmc1119_chip_info = {
+ .name = "hmc1119",
+ .gain_min = -31750,
+ .gain_max = 0,
+ .gain_step = -250,
+ .num_channels = 1,
+};
+
+static int ad8366_write_code(struct ad8366_state *st)
+{
+ const struct ad8366_info *inf = st->info;
+ size_t len = 1;
+
+ if (inf->pack_code)
+ len = inf->pack_code(st->ch, inf->num_channels, st->data);
+ else
+ st->data[0] = st->ch[0];
+
+ return spi_write(st->spi, st->data, len);
}
static int ad8366_read_raw(struct iio_dev *indio_dev,
@@ -116,6 +210,7 @@ static int ad8366_read_raw(struct iio_dev *indio_dev,
long m)
{
struct ad8366_state *st = iio_priv(indio_dev);
+ const struct ad8366_info *inf = st->info;
int ret;
int code, gain = 0;
@@ -123,25 +218,8 @@ static int ad8366_read_raw(struct iio_dev *indio_dev,
switch (m) {
case IIO_CHAN_INFO_HARDWAREGAIN:
code = st->ch[chan->channel];
-
- switch (st->type) {
- case ID_AD8366:
- gain = code * 253 + 4500;
- break;
- case ID_ADA4961:
- gain = 15000 - code * 1000;
- break;
- case ID_ADL5240:
- gain = 20000 - 31500 + code * 500;
- break;
- case ID_HMC792:
- gain = -1 * code * 500;
- break;
- case ID_HMC1119:
- gain = -1 * code * 250;
- break;
- }
-
+ gain = inf->gain_step > 0 ? inf->gain_min : inf->gain_max;
+ gain += inf->gain_step * code;
/* Values in dB */
*val = gain / 1000;
*val2 = (gain % 1000) * 1000;
@@ -176,29 +254,14 @@ static int ad8366_write_raw(struct iio_dev *indio_dev,
if (gain > inf->gain_max || gain < inf->gain_min)
return -EINVAL;
- switch (st->type) {
- case ID_AD8366:
- code = (gain - 4500) / 253;
- break;
- case ID_ADA4961:
- code = (15000 - gain) / 1000;
- break;
- case ID_ADL5240:
- code = ((gain - 500 - 20000) / 500) & 0x3F;
- break;
- case ID_HMC792:
- code = (abs(gain) / 500) & 0x3F;
- break;
- case ID_HMC1119:
- code = (abs(gain) / 250) & 0x7F;
- break;
- }
+ gain -= inf->gain_step > 0 ? inf->gain_min : inf->gain_max;
+ code = DIV_ROUND_CLOSEST(gain, inf->gain_step);
mutex_lock(&st->lock);
switch (mask) {
case IIO_CHAN_INFO_HARDWAREGAIN:
st->ch[chan->channel] = code;
- ret = ad8366_write(indio_dev, st->ch[0], st->ch[1]);
+ ret = ad8366_write_code(st);
break;
default:
ret = -EINVAL;
@@ -239,107 +302,97 @@ static const struct iio_chan_spec ad8366_channels[] = {
AD8366_CHAN(1),
};
-static const struct iio_chan_spec ada4961_channels[] = {
- AD8366_CHAN(0),
-};
-
static int ad8366_probe(struct spi_device *spi)
{
+ struct device *dev = &spi->dev;
+ struct gpio_desc *enable_gpio;
+ struct reset_control *rstc;
struct iio_dev *indio_dev;
struct ad8366_state *st;
int ret;
- indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
+ indio_dev = devm_iio_device_alloc(dev, sizeof(*st));
if (indio_dev == NULL)
return -ENOMEM;
st = iio_priv(indio_dev);
- st->reg = devm_regulator_get(&spi->dev, "vcc");
- if (!IS_ERR(st->reg)) {
- ret = regulator_enable(st->reg);
- if (ret)
- return ret;
- }
+ ret = devm_mutex_init(dev, &st->lock);
+ if (ret)
+ return ret;
+
+ ret = devm_regulator_get_enable(dev, "vcc");
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to get regulator\n");
- spi_set_drvdata(spi, indio_dev);
- mutex_init(&st->lock);
st->spi = spi;
- st->type = spi_get_device_id(spi)->driver_data;
+ st->info = spi_get_device_match_data(spi);
- switch (st->type) {
- case ID_AD8366:
- indio_dev->channels = ad8366_channels;
- indio_dev->num_channels = ARRAY_SIZE(ad8366_channels);
- break;
- case ID_ADA4961:
- case ID_ADL5240:
- case ID_HMC792:
- case ID_HMC1119:
- st->reset_gpio = devm_gpiod_get_optional(&spi->dev, "reset", GPIOD_OUT_HIGH);
- if (IS_ERR(st->reset_gpio)) {
- ret = PTR_ERR(st->reset_gpio);
- goto error_disable_reg;
- }
- indio_dev->channels = ada4961_channels;
- indio_dev->num_channels = ARRAY_SIZE(ada4961_channels);
- break;
- default:
- dev_err(&spi->dev, "Invalid device ID\n");
- ret = -EINVAL;
- goto error_disable_reg;
- }
+ enable_gpio = devm_gpiod_get_optional(dev, "enable", GPIOD_OUT_HIGH);
+ if (IS_ERR(enable_gpio))
+ return dev_err_probe(dev, PTR_ERR(enable_gpio),
+ "Failed to get enable GPIO\n");
+
+ rstc = devm_reset_control_get_optional_exclusive_deasserted(dev, NULL);
+ if (IS_ERR(rstc))
+ return dev_err_probe(dev, PTR_ERR(rstc),
+ "Failed to get reset controller\n");
- st->info = &ad8366_infos[st->type];
- indio_dev->name = spi_get_device_id(spi)->name;
+ indio_dev->name = st->info->name;
indio_dev->info = &ad8366_info;
indio_dev->modes = INDIO_DIRECT_MODE;
+ indio_dev->channels = ad8366_channels;
+ indio_dev->num_channels = st->info->num_channels;
- ret = ad8366_write(indio_dev, 0, 0);
+ ret = ad8366_write_code(st);
if (ret < 0)
- goto error_disable_reg;
-
- ret = iio_device_register(indio_dev);
- if (ret)
- goto error_disable_reg;
-
- return 0;
+ return dev_err_probe(dev, ret, "failed to write initial gain\n");
-error_disable_reg:
- if (!IS_ERR(st->reg))
- regulator_disable(st->reg);
-
- return ret;
-}
-
-static void ad8366_remove(struct spi_device *spi)
-{
- struct iio_dev *indio_dev = spi_get_drvdata(spi);
- struct ad8366_state *st = iio_priv(indio_dev);
- struct regulator *reg = st->reg;
-
- iio_device_unregister(indio_dev);
-
- if (!IS_ERR(reg))
- regulator_disable(reg);
+ return devm_iio_device_register(dev, indio_dev);
}
static const struct spi_device_id ad8366_id[] = {
- {"ad8366", ID_AD8366},
- {"ada4961", ID_ADA4961},
- {"adl5240", ID_ADL5240},
- {"hmc792a", ID_HMC792},
- {"hmc1119", ID_HMC1119},
+ { "ad8366", (kernel_ulong_t)&ad8366_chip_info },
+ { "ada4961", (kernel_ulong_t)&ada4961_chip_info },
+ { "adl5240", (kernel_ulong_t)&adl5240_chip_info },
+ { "adrf5702", (kernel_ulong_t)&adrf5702_chip_info },
+ { "adrf5703", (kernel_ulong_t)&adrf5703_chip_info },
+ { "adrf5720", (kernel_ulong_t)&adrf5720_chip_info },
+ { "adrf5730", (kernel_ulong_t)&adrf5730_chip_info },
+ { "adrf5731", (kernel_ulong_t)&adrf5731_chip_info },
+ { "hmc271a", (kernel_ulong_t)&hmc271_chip_info },
+ { "hmc792a", (kernel_ulong_t)&hmc792_chip_info },
+ { "hmc1018a", (kernel_ulong_t)&hmc1018_chip_info },
+ { "hmc1019a", (kernel_ulong_t)&hmc1019_chip_info },
+ { "hmc1119", (kernel_ulong_t)&hmc1119_chip_info },
{ }
};
MODULE_DEVICE_TABLE(spi, ad8366_id);
+static const struct of_device_id ad8366_of_match[] = {
+ { .compatible = "adi,ad8366", .data = &ad8366_chip_info },
+ { .compatible = "adi,ada4961", .data = &ada4961_chip_info },
+ { .compatible = "adi,adl5240", .data = &adl5240_chip_info },
+ { .compatible = "adi,adrf5702", .data = &adrf5702_chip_info },
+ { .compatible = "adi,adrf5703", .data = &adrf5703_chip_info },
+ { .compatible = "adi,adrf5720", .data = &adrf5720_chip_info },
+ { .compatible = "adi,adrf5730", .data = &adrf5730_chip_info },
+ { .compatible = "adi,adrf5731", .data = &adrf5731_chip_info },
+ { .compatible = "adi,hmc271a", .data = &hmc271_chip_info },
+ { .compatible = "adi,hmc792a", .data = &hmc792_chip_info },
+ { .compatible = "adi,hmc1018a", .data = &hmc1018_chip_info },
+ { .compatible = "adi,hmc1019a", .data = &hmc1019_chip_info },
+ { .compatible = "adi,hmc1119", .data = &hmc1119_chip_info },
+ { }
+};
+MODULE_DEVICE_TABLE(of, ad8366_of_match);
+
static struct spi_driver ad8366_driver = {
.driver = {
- .name = KBUILD_MODNAME,
+ .name = KBUILD_MODNAME,
+ .of_match_table = ad8366_of_match,
},
.probe = ad8366_probe,
- .remove = ad8366_remove,
.id_table = ad8366_id,
};
diff --git a/drivers/iio/amplifiers/ada4250.c b/drivers/iio/amplifiers/ada4250.c
index 40f396ea9069..71e361af2074 100644
--- a/drivers/iio/amplifiers/ada4250.c
+++ b/drivers/iio/amplifiers/ada4250.c
@@ -109,7 +109,7 @@ static int ada4250_set_offset_uv(struct iio_dev *indio_dev,
/*
* Compute Range and Voltage per LSB for the Sensor Offset Calibration
- * Example of computation for Range 1 and Range 2 (Curren Bias Set = AVDD):
+ * Example of computation for Range 1 and Range 2 (Current Bias Set = AVDD):
* Range 1 Range 2
* Gain | Max Vos(mV) | LSB(mV) | Max Vos(mV) | LSB(mV) |
* 2 | X1*127 | X1=0.126(AVDD-1) | X1*3*127 | X1*3 |
diff --git a/drivers/iio/buffer/industrialio-hw-consumer.c b/drivers/iio/buffer/industrialio-hw-consumer.c
index cb771ef8eeb3..24d7df603760 100644
--- a/drivers/iio/buffer/industrialio-hw-consumer.c
+++ b/drivers/iio/buffer/industrialio-hw-consumer.c
@@ -28,7 +28,6 @@ struct hw_consumer_buffer {
struct list_head head;
struct iio_dev *indio_dev;
struct iio_buffer buffer;
- long scan_mask[];
};
static struct hw_consumer_buffer *iio_buffer_to_hw_consumer_buffer(
@@ -52,7 +51,6 @@ static const struct iio_buffer_access_funcs iio_hw_buf_access = {
static struct hw_consumer_buffer *iio_hw_consumer_get_buffer(
struct iio_hw_consumer *hwc, struct iio_dev *indio_dev)
{
- unsigned int mask_longs = BITS_TO_LONGS(iio_get_masklength(indio_dev));
struct hw_consumer_buffer *buf;
list_for_each_entry(buf, &hwc->buffers, head) {
@@ -60,13 +58,18 @@ static struct hw_consumer_buffer *iio_hw_consumer_get_buffer(
return buf;
}
- buf = kzalloc_flex(*buf, scan_mask, mask_longs);
+ buf = kzalloc_obj(*buf);
if (!buf)
return NULL;
buf->buffer.access = &iio_hw_buf_access;
buf->indio_dev = indio_dev;
- buf->buffer.scan_mask = buf->scan_mask;
+ buf->buffer.scan_mask = bitmap_zalloc(iio_get_masklength(indio_dev),
+ GFP_KERNEL);
+ if (!buf->buffer.scan_mask) {
+ kfree(buf);
+ return NULL;
+ }
iio_buffer_init(&buf->buffer);
list_add_tail(&buf->head, &hwc->buffers);
diff --git a/drivers/iio/buffer/kfifo_buf.c b/drivers/iio/buffer/kfifo_buf.c
index a6ff9085b8a2..b67ea6468226 100644
--- a/drivers/iio/buffer/kfifo_buf.c
+++ b/drivers/iio/buffer/kfifo_buf.c
@@ -224,35 +224,9 @@ void iio_kfifo_free(struct iio_buffer *r)
}
EXPORT_SYMBOL(iio_kfifo_free);
-static void devm_iio_kfifo_release(struct device *dev, void *res)
+static void devm_iio_kfifo_release(void *buffer)
{
- iio_kfifo_free(*(struct iio_buffer **)res);
-}
-
-/**
- * devm_iio_kfifo_allocate - Resource-managed iio_kfifo_allocate()
- * @dev: Device to allocate kfifo buffer for
- *
- * RETURNS:
- * Pointer to allocated iio_buffer on success, NULL on failure.
- */
-static struct iio_buffer *devm_iio_kfifo_allocate(struct device *dev)
-{
- struct iio_buffer **ptr, *r;
-
- ptr = devres_alloc(devm_iio_kfifo_release, sizeof(*ptr), GFP_KERNEL);
- if (!ptr)
- return NULL;
-
- r = iio_kfifo_allocate();
- if (r) {
- *ptr = r;
- devres_add(dev, ptr);
- } else {
- devres_free(ptr);
- }
-
- return r;
+ iio_kfifo_free(buffer);
}
/**
@@ -262,10 +236,12 @@ static struct iio_buffer *devm_iio_kfifo_allocate(struct device *dev)
* @setup_ops: The setup_ops required to configure the HW part of the buffer (optional)
* @buffer_attrs: Extra sysfs buffer attributes for this IIO buffer
*
- * This function allocates a kfifo buffer via devm_iio_kfifo_allocate() and
+ * This function allocates a kfifo buffer via iio_kfifo_allocate() and
* attaches it to the IIO device via iio_device_attach_buffer().
* This is meant to be a bit of a short-hand/helper function as there are a few
* drivers that seem to do this.
+ *
+ * Return: 0 on success, negative error code on failure.
*/
int devm_iio_kfifo_buffer_setup_ext(struct device *dev,
struct iio_dev *indio_dev,
@@ -273,11 +249,16 @@ int devm_iio_kfifo_buffer_setup_ext(struct device *dev,
const struct iio_dev_attr **buffer_attrs)
{
struct iio_buffer *buffer;
+ int ret;
- buffer = devm_iio_kfifo_allocate(dev);
+ buffer = iio_kfifo_allocate();
if (!buffer)
return -ENOMEM;
+ ret = devm_add_action_or_reset(dev, devm_iio_kfifo_release, buffer);
+ if (ret)
+ return ret;
+
indio_dev->modes |= INDIO_BUFFER_SOFTWARE;
indio_dev->setup_ops = setup_ops;
diff --git a/drivers/iio/cdc/ad7150.c b/drivers/iio/cdc/ad7150.c
index 427d32e398b3..8106a6a83561 100644
--- a/drivers/iio/cdc/ad7150.c
+++ b/drivers/iio/cdc/ad7150.c
@@ -306,7 +306,7 @@ static int ad7150_write_event_config(struct iio_dev *indio_dev,
dir);
if (ret)
goto error_ret;
- /* reenable any irq's we disabled whilst changing mode */
+ /* re-enable any IRQs we disabled whilst changing mode */
enable_irq(chip->interrupts[0]);
enable_irq(chip->interrupts[1]);
}
diff --git a/drivers/iio/cdc/ad7746.c b/drivers/iio/cdc/ad7746.c
index 8a306d55c72a..cb97e3c978d8 100644
--- a/drivers/iio/cdc/ad7746.c
+++ b/drivers/iio/cdc/ad7746.c
@@ -606,7 +606,7 @@ static int ad7746_read_channel(struct iio_dev *indio_dev,
return ret;
/*
- * Offset applied internally becaue the _offset userspace interface is
+ * Offset applied internally because the _offset userspace interface is
* needed for the CAP DACs which apply a controllable offset.
*/
*val = get_unaligned_be24(data) - 0x800000;
diff --git a/drivers/iio/chemical/bme680_core.c b/drivers/iio/chemical/bme680_core.c
index 24e0b59e2fdf..6aeac132394c 100644
--- a/drivers/iio/chemical/bme680_core.c
+++ b/drivers/iio/chemical/bme680_core.c
@@ -807,7 +807,7 @@ static int bme680_read_gas(struct bme680_data *data, int *comp_gas_res)
adc_gas_res = FIELD_GET(BME680_ADC_GAS_RES, gas_regs_val);
/*
- * occurs if either the gas heating duration was insuffient
+ * This may occur if either the gas heating duration was insufficient
* to reach the target heater temperature or the target
* heater temperature was too high for the heater sink to
* reach.
diff --git a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c
index 82cef4a12442..f34e2bbba2d1 100644
--- a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c
+++ b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c
@@ -106,7 +106,7 @@ static int cros_ec_sensors_read(struct iio_dev *indio_dev,
switch (st->core.type) {
case MOTIONSENSE_TYPE_ACCEL:
/*
- * EC returns data in g, iio exepects m/s^2.
+ * EC returns data in g, IIO expects m/s^2.
* Do not use IIO_G_TO_M_S_2 to avoid precision loss.
*/
*val = div_s64(val64 * 980665, 10);
diff --git a/drivers/iio/common/hid-sensors/hid-sensor-attributes.c b/drivers/iio/common/hid-sensors/hid-sensor-attributes.c
index a61428bfdce3..c115a72832b2 100644
--- a/drivers/iio/common/hid-sensors/hid-sensor-attributes.c
+++ b/drivers/iio/common/hid-sensors/hid-sensor-attributes.c
@@ -346,7 +346,7 @@ int hid_sensor_write_raw_hyst_rel_value(struct hid_sensor_common *st,
EXPORT_SYMBOL_NS(hid_sensor_write_raw_hyst_rel_value, "IIO_HID");
/*
- * This fuction applies the unit exponent to the scale.
+ * This function applies the unit exponent to the scale.
* For example:
* 9.806650000 ->exp:2-> val0[980]val1[665000000]
* 9.000806000 ->exp:2-> val0[900]val1[80600000]
diff --git a/drivers/iio/common/inv_sensors/inv_sensors_timestamp.c b/drivers/iio/common/inv_sensors/inv_sensors_timestamp.c
index 97526ba87b93..e0b10366ed2b 100644
--- a/drivers/iio/common/inv_sensors/inv_sensors_timestamp.c
+++ b/drivers/iio/common/inv_sensors/inv_sensors_timestamp.c
@@ -154,7 +154,7 @@ void inv_sensors_timestamp_interrupt(struct inv_sensors_timestamp *ts,
valid = inv_update_chip_period(ts, period);
}
- /* no previous data, compute theoritical value from interrupt */
+ /* no previous data, compute theoretical value from interrupt */
if (ts->timestamp == 0) {
/* elapsed time: sensor period * sensor samples number */
interval = (int64_t)ts->period * (int64_t)sample_nb;
@@ -185,7 +185,7 @@ void inv_sensors_timestamp_apply_odr(struct inv_sensors_timestamp *ts,
/*
* After ODR change the time interval with the previous sample is
- * undertermined (depends when the change occures). So we compute the
+ * undertermined (depends when the change occurs). So we compute the
* timestamp from the current interrupt using the new FIFO period, the
* total number of samples and the current sample numero.
*/
diff --git a/drivers/iio/common/ms_sensors/ms_sensors_i2c.c b/drivers/iio/common/ms_sensors/ms_sensors_i2c.c
index 588470863681..1960a2ce82a8 100644
--- a/drivers/iio/common/ms_sensors/ms_sensors_i2c.c
+++ b/drivers/iio/common/ms_sensors/ms_sensors_i2c.c
@@ -96,7 +96,7 @@ EXPORT_SYMBOL_NS(ms_sensors_read_prom_word, "IIO_MEAS_SPEC_SENSORS");
*
* Generic ADC conversion & read function for Measurement Specialties
* devices.
- * The function will issue conversion command, sleep appopriate delay, and
+ * The function will issue conversion command, sleep appropriate delay, and
* issue command to read ADC.
*
* Return: 0 on success, negative errno otherwise.
diff --git a/drivers/iio/common/st_sensors/st_sensors_core.c b/drivers/iio/common/st_sensors/st_sensors_core.c
index dac593be5695..dbc5e16fbde4 100644
--- a/drivers/iio/common/st_sensors/st_sensors_core.c
+++ b/drivers/iio/common/st_sensors/st_sensors_core.c
@@ -501,14 +501,12 @@ static int st_sensors_read_axis_data(struct iio_dev *indio_dev,
byte_for_channel = DIV_ROUND_UP(ch->scan_type.realbits +
ch->scan_type.shift, 8);
- outdata = kmalloc(byte_for_channel, GFP_DMA | GFP_KERNEL);
- if (!outdata)
- return -ENOMEM;
+ outdata = sdata->buffer_data;
err = regmap_bulk_read(sdata->regmap, ch->address,
outdata, byte_for_channel);
if (err < 0)
- goto st_sensors_free_memory;
+ return err;
if (byte_for_channel == 1)
*data = (s8)*outdata;
@@ -517,10 +515,7 @@ static int st_sensors_read_axis_data(struct iio_dev *indio_dev,
else if (byte_for_channel == 3)
*data = (s32)sign_extend32(get_unaligned_le24(outdata), 23);
-st_sensors_free_memory:
- kfree(outdata);
-
- return err;
+ return 0;
}
int st_sensors_read_info_raw(struct iio_dev *indio_dev,
diff --git a/drivers/iio/dac/Kconfig b/drivers/iio/dac/Kconfig
index db9f5c711b3d..cd4870b65415 100644
--- a/drivers/iio/dac/Kconfig
+++ b/drivers/iio/dac/Kconfig
@@ -408,6 +408,7 @@ config DPOT_DAC
config DS4424
tristate "Maxim Integrated DS4422/DS4424 DAC driver"
depends on I2C
+ select REGMAP_I2C
help
If you say yes here you get support for Maxim chips DS4422, DS4424.
diff --git a/drivers/iio/dac/ad5360.c b/drivers/iio/dac/ad5360.c
index bd32fa57b1d7..20316fd568e6 100644
--- a/drivers/iio/dac/ad5360.c
+++ b/drivers/iio/dac/ad5360.c
@@ -206,14 +206,10 @@ static int ad5360_write_unlocked(struct iio_dev *indio_dev,
static int ad5360_write(struct iio_dev *indio_dev, unsigned int cmd,
unsigned int addr, unsigned int val, unsigned int shift)
{
- int ret;
struct ad5360_state *st = iio_priv(indio_dev);
- mutex_lock(&st->lock);
- ret = ad5360_write_unlocked(indio_dev, cmd, addr, val, shift);
- mutex_unlock(&st->lock);
-
- return ret;
+ guard(mutex)(&st->lock);
+ return ad5360_write_unlocked(indio_dev, cmd, addr, val, shift);
}
static int ad5360_read(struct iio_dev *indio_dev, unsigned int type,
@@ -232,7 +228,7 @@ static int ad5360_read(struct iio_dev *indio_dev, unsigned int type,
},
};
- mutex_lock(&st->lock);
+ guard(mutex)(&st->lock);
st->data[0].d32 = cpu_to_be32(AD5360_CMD(AD5360_CMD_SPECIAL_FUNCTION) |
AD5360_ADDR(AD5360_REG_SF_READBACK) |
@@ -240,12 +236,10 @@ static int ad5360_read(struct iio_dev *indio_dev, unsigned int type,
AD5360_READBACK_ADDR(addr));
ret = spi_sync_transfer(st->spi, t, ARRAY_SIZE(t));
- if (ret >= 0)
- ret = be32_to_cpu(st->data[1].d32) & 0xffff;
-
- mutex_unlock(&st->lock);
+ if (ret < 0)
+ return ret;
- return ret;
+ return be32_to_cpu(st->data[1].d32) & 0xffff;
}
static ssize_t ad5360_read_dac_powerdown(struct device *dev,
@@ -262,19 +256,14 @@ static int ad5360_update_ctrl(struct iio_dev *indio_dev, unsigned int set,
unsigned int clr)
{
struct ad5360_state *st = iio_priv(indio_dev);
- int ret;
- mutex_lock(&st->lock);
+ guard(mutex)(&st->lock);
st->ctrl |= set;
st->ctrl &= ~clr;
- ret = ad5360_write_unlocked(indio_dev, AD5360_CMD_SPECIAL_FUNCTION,
- AD5360_REG_SF_CTRL, st->ctrl, 0);
-
- mutex_unlock(&st->lock);
-
- return ret;
+ return ad5360_write_unlocked(indio_dev, AD5360_CMD_SPECIAL_FUNCTION,
+ AD5360_REG_SF_CTRL, st->ctrl, 0);
}
static ssize_t ad5360_write_dac_powerdown(struct device *dev,
diff --git a/drivers/iio/dac/ad7293.c b/drivers/iio/dac/ad7293.c
index c3797e40cdd9..df6f126abf05 100644
--- a/drivers/iio/dac/ad7293.c
+++ b/drivers/iio/dac/ad7293.c
@@ -776,27 +776,27 @@ static int ad7293_reset(struct ad7293_state *st)
static int ad7293_properties_parse(struct ad7293_state *st)
{
- struct spi_device *spi = st->spi;
+ struct device *dev = &st->spi->dev;
int ret;
- ret = devm_regulator_get_enable(&spi->dev, "avdd");
+ ret = devm_regulator_get_enable(dev, "avdd");
if (ret)
- return dev_err_probe(&spi->dev, ret, "failed to enable AVDD\n");
+ return dev_err_probe(dev, ret, "failed to enable AVDD\n");
- ret = devm_regulator_get_enable(&spi->dev, "vdrive");
+ ret = devm_regulator_get_enable(dev, "vdrive");
if (ret)
- return dev_err_probe(&spi->dev, ret, "failed to enable VDRIVE\n");
+ return dev_err_probe(dev, ret, "failed to enable VDRIVE\n");
- ret = devm_regulator_get_enable_optional(&spi->dev, "vrefin");
+ ret = devm_regulator_get_enable_optional(dev, "vrefin");
if (ret < 0 && ret != -ENODEV)
- return dev_err_probe(&spi->dev, ret, "failed to enable VREFIN\n");
+ return dev_err_probe(dev, ret, "failed to enable VREFIN\n");
st->vrefin_en = ret != -ENODEV;
- st->gpio_reset = devm_gpiod_get_optional(&st->spi->dev, "reset",
+ st->gpio_reset = devm_gpiod_get_optional(dev, "reset",
GPIOD_OUT_HIGH);
if (IS_ERR(st->gpio_reset))
- return dev_err_probe(&spi->dev, PTR_ERR(st->gpio_reset),
+ return dev_err_probe(dev, PTR_ERR(st->gpio_reset),
"failed to get the reset GPIO\n");
return 0;
@@ -806,7 +806,7 @@ static int ad7293_init(struct ad7293_state *st)
{
int ret;
u16 chip_id;
- struct spi_device *spi = st->spi;
+ struct device *dev = &st->spi->dev;
ret = ad7293_properties_parse(st);
if (ret)
@@ -821,10 +821,8 @@ static int ad7293_init(struct ad7293_state *st)
if (ret)
return ret;
- if (chip_id != AD7293_CHIP_ID) {
- dev_err(&spi->dev, "Invalid Chip ID.\n");
- return -EINVAL;
- }
+ if (chip_id != AD7293_CHIP_ID)
+ return dev_err_probe(dev, -EINVAL, "Invalid Chip ID.\n");
if (!st->vrefin_en)
return __ad7293_spi_update_bits(st, AD7293_REG_GENERAL,
@@ -845,9 +843,10 @@ static int ad7293_probe(struct spi_device *spi)
{
struct iio_dev *indio_dev;
struct ad7293_state *st;
+ struct device *dev = &spi->dev;
int ret;
- indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
+ indio_dev = devm_iio_device_alloc(dev, sizeof(*st));
if (!indio_dev)
return -ENOMEM;
@@ -867,7 +866,7 @@ static int ad7293_probe(struct spi_device *spi)
if (ret)
return ret;
- return devm_iio_device_register(&spi->dev, indio_dev);
+ return devm_iio_device_register(dev, indio_dev);
}
static const struct spi_device_id ad7293_id[] = {
diff --git a/drivers/iio/dac/adi-axi-dac.c b/drivers/iio/dac/adi-axi-dac.c
index 9cc895bbe51a..451fad34e7ee 100644
--- a/drivers/iio/dac/adi-axi-dac.c
+++ b/drivers/iio/dac/adi-axi-dac.c
@@ -114,7 +114,6 @@ struct axi_dac_state {
const struct axi_dac_info *info;
u64 dac_clk;
u32 reg_config;
- bool int_tone;
int dac_clk_rate;
};
@@ -869,11 +868,13 @@ static const struct iio_backend_ops axi_ad3552r_ops = {
static const struct iio_backend_info axi_dac_generic = {
.name = "axi-dac",
.ops = &axi_dac_generic_ops,
+ .caps = IIO_BACKEND_CAP_BUFFER | IIO_BACKEND_CAP_ENABLE,
};
static const struct iio_backend_info axi_ad3552r = {
.name = "axi-ad3552r",
.ops = &axi_ad3552r_ops,
+ .caps = IIO_BACKEND_CAP_BUFFER | IIO_BACKEND_CAP_ENABLE,
};
static const struct regmap_config axi_dac_regmap_config = {
diff --git a/drivers/iio/dac/ds4424.c b/drivers/iio/dac/ds4424.c
index c61868f2de31..085f73de3f02 100644
--- a/drivers/iio/dac/ds4424.c
+++ b/drivers/iio/dac/ds4424.c
@@ -5,22 +5,31 @@
* Copyright (C) 2017 Maxim Integrated
*/
+#include <linux/array_size.h>
+#include <linux/bits.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/i2c.h>
#include <linux/kernel.h>
#include <linux/module.h>
-#include <linux/i2c.h>
+#include <linux/property.h>
+#include <linux/regmap.h>
#include <linux/regulator/consumer.h>
-#include <linux/err.h>
-#include <linux/delay.h>
-#include <linux/iio/iio.h>
+#include <linux/time64.h>
+#include <linux/types.h>
+
#include <linux/iio/driver.h>
+#include <linux/iio/iio.h>
#include <linux/iio/machine.h>
#define DS4422_MAX_DAC_CHANNELS 2
#define DS4424_MAX_DAC_CHANNELS 4
+#define DS4424_DAC_MASK GENMASK(6, 0)
+#define DS4404_DAC_MASK GENMASK(4, 0)
+#define DS4424_DAC_SOURCE BIT(7)
+
#define DS4424_DAC_ADDR(chan) ((chan) + 0xf8)
-#define DS4424_SOURCE_I 1
-#define DS4424_SINK_I 0
#define DS4424_CHANNEL(chan) { \
.type = IIO_CURRENT, \
@@ -30,33 +39,61 @@
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
}
-/*
- * DS4424 DAC control register 8 bits
- * [7] 0: to sink; 1: to source
- * [6:0] steps to sink/source
- * bit[7] looks like a sign bit, but the value of the register is
- * not a two's complement code considering the bit[6:0] is a absolute
- * distance from the zero point.
- */
-union ds4424_raw_data {
- struct {
- u8 dx:7;
- u8 source_bit:1;
- };
- u8 bits;
+#define DS4424_CHANNEL_WITH_SCALE(chan) { \
+ .type = IIO_CURRENT, \
+ .indexed = 1, \
+ .output = 1, \
+ .channel = chan, \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
+ BIT(IIO_CHAN_INFO_SCALE), \
+}
+
+struct ds4424_chip_info {
+ const char *name;
+ int vref_mV;
+ int scale_denom;
+ u8 result_mask;
+ u8 num_channels;
+};
+
+static const struct ds4424_chip_info ds4402_info = {
+ .name = "ds4402",
+ .vref_mV = 1230,
+ .scale_denom = 4,
+ .result_mask = DS4404_DAC_MASK,
+ .num_channels = DS4422_MAX_DAC_CHANNELS,
+};
+
+static const struct ds4424_chip_info ds4404_info = {
+ .name = "ds4404",
+ .vref_mV = 1230,
+ .scale_denom = 4,
+ .result_mask = DS4404_DAC_MASK,
+ .num_channels = DS4424_MAX_DAC_CHANNELS,
+};
+
+static const struct ds4424_chip_info ds4422_info = {
+ .name = "ds4422",
+ .vref_mV = 976,
+ .scale_denom = 16,
+ .result_mask = DS4424_DAC_MASK,
+ .num_channels = DS4422_MAX_DAC_CHANNELS,
};
-enum ds4424_device_ids {
- ID_DS4422,
- ID_DS4424,
+static const struct ds4424_chip_info ds4424_info = {
+ .name = "ds4424",
+ .vref_mV = 976,
+ .scale_denom = 16,
+ .result_mask = DS4424_DAC_MASK,
+ .num_channels = DS4424_MAX_DAC_CHANNELS,
};
struct ds4424_data {
- struct i2c_client *client;
- struct mutex lock;
- uint8_t save[DS4424_MAX_DAC_CHANNELS];
+ struct regmap *regmap;
struct regulator *vcc_reg;
- uint8_t raw[DS4424_MAX_DAC_CHANNELS];
+ const struct ds4424_chip_info *chip_info;
+ u32 rfs_ohms[DS4424_MAX_DAC_CHANNELS];
+ bool has_rfs;
};
static const struct iio_chan_spec ds4424_channels[] = {
@@ -66,63 +103,114 @@ static const struct iio_chan_spec ds4424_channels[] = {
DS4424_CHANNEL(3),
};
-static int ds4424_get_value(struct iio_dev *indio_dev,
- int *val, int channel)
-{
- struct ds4424_data *data = iio_priv(indio_dev);
- int ret;
+static const struct iio_chan_spec ds4424_channels_with_scale[] = {
+ DS4424_CHANNEL_WITH_SCALE(0),
+ DS4424_CHANNEL_WITH_SCALE(1),
+ DS4424_CHANNEL_WITH_SCALE(2),
+ DS4424_CHANNEL_WITH_SCALE(3),
+};
- mutex_lock(&data->lock);
- ret = i2c_smbus_read_byte_data(data->client, DS4424_DAC_ADDR(channel));
- if (ret < 0)
- goto fail;
+static const struct regmap_range ds44x2_ranges[] = {
+ regmap_reg_range(DS4424_DAC_ADDR(0), DS4424_DAC_ADDR(1)),
+};
- *val = ret;
+static const struct regmap_range ds44x4_ranges[] = {
+ regmap_reg_range(DS4424_DAC_ADDR(0), DS4424_DAC_ADDR(3)),
+};
-fail:
- mutex_unlock(&data->lock);
- return ret;
-}
+static const struct regmap_access_table ds44x2_table = {
+ .yes_ranges = ds44x2_ranges,
+ .n_yes_ranges = ARRAY_SIZE(ds44x2_ranges),
+};
+
+static const struct regmap_access_table ds44x4_table = {
+ .yes_ranges = ds44x4_ranges,
+ .n_yes_ranges = ARRAY_SIZE(ds44x4_ranges),
+};
-static int ds4424_set_value(struct iio_dev *indio_dev,
- int val, struct iio_chan_spec const *chan)
+static const struct regmap_config ds44x2_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .cache_type = REGCACHE_MAPLE,
+ .max_register = DS4424_DAC_ADDR(1),
+ .rd_table = &ds44x2_table,
+ .wr_table = &ds44x2_table,
+};
+
+static const struct regmap_config ds44x4_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .cache_type = REGCACHE_MAPLE,
+ .max_register = DS4424_DAC_ADDR(3),
+ .rd_table = &ds44x4_table,
+ .wr_table = &ds44x4_table,
+};
+
+static int ds4424_init_regmap(struct i2c_client *client,
+ struct iio_dev *indio_dev)
{
struct ds4424_data *data = iio_priv(indio_dev);
+ const struct regmap_config *regmap_config;
+ u8 vals[DS4424_MAX_DAC_CHANNELS];
int ret;
- mutex_lock(&data->lock);
- ret = i2c_smbus_write_byte_data(data->client,
- DS4424_DAC_ADDR(chan->channel), val);
- if (ret < 0)
- goto fail;
-
- data->raw[chan->channel] = val;
-
-fail:
- mutex_unlock(&data->lock);
- return ret;
+ if (indio_dev->num_channels == DS4424_MAX_DAC_CHANNELS)
+ regmap_config = &ds44x4_regmap_config;
+ else
+ regmap_config = &ds44x2_regmap_config;
+
+ data->regmap = devm_regmap_init_i2c(client, regmap_config);
+ if (IS_ERR(data->regmap))
+ return dev_err_probe(&client->dev, PTR_ERR(data->regmap),
+ "Failed to init regmap.\n");
+
+ /*
+ * Prime the cache with the bootloader's configuration.
+ * regmap_bulk_read() will automatically populate the cache with
+ * the values read from the hardware.
+ */
+ ret = regmap_bulk_read(data->regmap, DS4424_DAC_ADDR(0), vals,
+ indio_dev->num_channels);
+ if (ret)
+ return dev_err_probe(&client->dev, ret,
+ "Failed to read hardware values\n");
+
+ return 0;
}
static int ds4424_read_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int *val, int *val2, long mask)
{
- union ds4424_raw_data raw;
+ struct ds4424_data *data = iio_priv(indio_dev);
+ unsigned int regval;
int ret;
switch (mask) {
case IIO_CHAN_INFO_RAW:
- ret = ds4424_get_value(indio_dev, val, chan->channel);
+ ret = regmap_read(data->regmap, DS4424_DAC_ADDR(chan->channel),
+ &regval);
if (ret < 0) {
- pr_err("%s : ds4424_get_value returned %d\n",
- __func__, ret);
+ dev_err_ratelimited(indio_dev->dev.parent,
+ "Failed to read channel %d: %pe\n",
+ chan->channel, ERR_PTR(ret));
return ret;
}
- raw.bits = *val;
- *val = raw.dx;
- if (raw.source_bit == DS4424_SINK_I)
+
+ *val = regval & data->chip_info->result_mask;
+ if (!(regval & DS4424_DAC_SOURCE))
*val = -*val;
+
return IIO_VAL_INT;
+ case IIO_CHAN_INFO_SCALE:
+ if (!data->has_rfs)
+ return -EINVAL;
+
+ /* SCALE is mA/step: mV / Ohm = mA. */
+ *val = data->chip_info->vref_mV;
+ *val2 = data->rfs_ohms[chan->channel] *
+ data->chip_info->scale_denom;
+ return IIO_VAL_FRACTIONAL;
default:
return -EINVAL;
@@ -133,107 +221,131 @@ static int ds4424_write_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int val, int val2, long mask)
{
- union ds4424_raw_data raw;
+ struct ds4424_data *data = iio_priv(indio_dev);
+ unsigned int abs_val;
if (val2 != 0)
return -EINVAL;
switch (mask) {
case IIO_CHAN_INFO_RAW:
- if (val <= S8_MIN || val > S8_MAX)
+ abs_val = abs(val);
+ if (abs_val > data->chip_info->result_mask)
return -EINVAL;
- if (val > 0) {
- raw.source_bit = DS4424_SOURCE_I;
- raw.dx = val;
- } else {
- raw.source_bit = DS4424_SINK_I;
- raw.dx = -val;
- }
+ /*
+ * Currents exiting the IC (Source) are positive. 0 is a valid
+ * value for no current flow; the direction bit (Source vs Sink)
+ * is treated as don't-care by the hardware at 0.
+ */
+ if (val > 0)
+ abs_val |= DS4424_DAC_SOURCE;
- return ds4424_set_value(indio_dev, raw.bits, chan);
+ return regmap_write(data->regmap, DS4424_DAC_ADDR(chan->channel),
+ abs_val);
default:
return -EINVAL;
}
}
-static int ds4424_verify_chip(struct iio_dev *indio_dev)
+static int ds4424_parse_rfs(struct i2c_client *client,
+ struct ds4424_data *data,
+ struct iio_dev *indio_dev)
{
- int ret, val;
+ struct device *dev = &client->dev;
+ int count, ret;
+
+ if (!device_property_present(dev, "maxim,rfs-ohms"))
+ return 0;
+
+ count = device_property_count_u32(dev, "maxim,rfs-ohms");
+ if (count < 0)
+ return dev_err_probe(dev, count, "Failed to count maxim,rfs-ohms entries\n");
+ if (count != indio_dev->num_channels)
+ return dev_err_probe(dev, -EINVAL, "maxim,rfs-ohms must have %u entries\n",
+ indio_dev->num_channels);
+
+ ret = device_property_read_u32_array(dev, "maxim,rfs-ohms",
+ data->rfs_ohms,
+ indio_dev->num_channels);
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to read maxim,rfs-ohms property\n");
+
+ for (unsigned int i = 0; i < indio_dev->num_channels; i++) {
+ if (!data->rfs_ohms[i])
+ return dev_err_probe(dev, -EINVAL, "maxim,rfs-ohms entry %u is zero\n", i);
+ }
- ret = ds4424_get_value(indio_dev, &val, 0);
- if (ret < 0)
- dev_err(&indio_dev->dev,
- "%s failed. ret: %d\n", __func__, ret);
+ data->has_rfs = true;
- return ret;
+ return 0;
}
static int ds4424_suspend(struct device *dev)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct iio_dev *indio_dev = i2c_get_clientdata(client);
+ struct iio_dev *indio_dev = dev_get_drvdata(dev);
struct ds4424_data *data = iio_priv(indio_dev);
- int ret = 0;
- int i;
-
- for (i = 0; i < indio_dev->num_channels; i++) {
- data->save[i] = data->raw[i];
- ret = ds4424_set_value(indio_dev, 0,
- &indio_dev->channels[i]);
- if (ret < 0)
- return ret;
+ u8 zero_buf[DS4424_MAX_DAC_CHANNELS] = { };
+ int ret;
+
+ /* Disable all outputs, bypass cache so the '0' isn't saved */
+ regcache_cache_bypass(data->regmap, true);
+ ret = regmap_bulk_write(data->regmap, DS4424_DAC_ADDR(0),
+ zero_buf, indio_dev->num_channels);
+ regcache_cache_bypass(data->regmap, false);
+ if (ret) {
+ dev_err(dev, "Failed to zero outputs: %pe\n", ERR_PTR(ret));
+ return ret;
}
- return ret;
+
+ regcache_cache_only(data->regmap, true);
+ regcache_mark_dirty(data->regmap);
+
+ return 0;
}
static int ds4424_resume(struct device *dev)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct iio_dev *indio_dev = i2c_get_clientdata(client);
+ struct iio_dev *indio_dev = dev_get_drvdata(dev);
struct ds4424_data *data = iio_priv(indio_dev);
- int ret = 0;
- int i;
- for (i = 0; i < indio_dev->num_channels; i++) {
- ret = ds4424_set_value(indio_dev, data->save[i],
- &indio_dev->channels[i]);
- if (ret < 0)
- return ret;
- }
- return ret;
+ regcache_cache_only(data->regmap, false);
+ return regcache_sync(data->regmap);
}
static DEFINE_SIMPLE_DEV_PM_OPS(ds4424_pm_ops, ds4424_suspend, ds4424_resume);
-static const struct iio_info ds4424_info = {
+static const struct iio_info ds4424_iio_info = {
.read_raw = ds4424_read_raw,
.write_raw = ds4424_write_raw,
};
static int ds4424_probe(struct i2c_client *client)
{
- const struct i2c_device_id *id = i2c_client_get_device_id(client);
+ const struct ds4424_chip_info *chip_info;
struct ds4424_data *data;
struct iio_dev *indio_dev;
int ret;
+ chip_info = i2c_get_match_data(client);
+ if (!chip_info)
+ return -ENODEV;
+
indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
if (!indio_dev)
return -ENOMEM;
data = iio_priv(indio_dev);
i2c_set_clientdata(client, indio_dev);
- data->client = client;
- indio_dev->name = id->name;
+ indio_dev->name = chip_info->name;
+ data->chip_info = chip_info;
data->vcc_reg = devm_regulator_get(&client->dev, "vcc");
if (IS_ERR(data->vcc_reg))
return dev_err_probe(&client->dev, PTR_ERR(data->vcc_reg),
"Failed to get vcc-supply regulator.\n");
- mutex_init(&data->lock);
ret = regulator_enable(data->vcc_reg);
if (ret < 0) {
dev_err(&client->dev,
@@ -241,28 +353,29 @@ static int ds4424_probe(struct i2c_client *client)
return ret;
}
- usleep_range(1000, 1200);
- ret = ds4424_verify_chip(indio_dev);
- if (ret < 0)
+ /*
+ * The datasheet does not specify a power-up to I2C ready time.
+ * Maintain the existing conservative 1ms delay to ensure the
+ * device is ready for communication.
+ */
+ fsleep(1 * USEC_PER_MSEC);
+
+ indio_dev->num_channels = chip_info->num_channels;
+ indio_dev->modes = INDIO_DIRECT_MODE;
+ indio_dev->info = &ds4424_iio_info;
+
+ ret = ds4424_init_regmap(client, indio_dev);
+ if (ret)
goto fail;
- switch (id->driver_data) {
- case ID_DS4422:
- indio_dev->num_channels = DS4422_MAX_DAC_CHANNELS;
- break;
- case ID_DS4424:
- indio_dev->num_channels = DS4424_MAX_DAC_CHANNELS;
- break;
- default:
- dev_err(&client->dev,
- "ds4424: Invalid chip id.\n");
- ret = -ENXIO;
+ ret = ds4424_parse_rfs(client, data, indio_dev);
+ if (ret)
goto fail;
- }
- indio_dev->channels = ds4424_channels;
- indio_dev->modes = INDIO_DIRECT_MODE;
- indio_dev->info = &ds4424_info;
+ if (data->has_rfs)
+ indio_dev->channels = ds4424_channels_with_scale;
+ else
+ indio_dev->channels = ds4424_channels;
ret = iio_device_register(indio_dev);
if (ret < 0) {
@@ -288,16 +401,20 @@ static void ds4424_remove(struct i2c_client *client)
}
static const struct i2c_device_id ds4424_id[] = {
- { "ds4422", ID_DS4422 },
- { "ds4424", ID_DS4424 },
+ { "ds4402", (kernel_ulong_t)&ds4402_info },
+ { "ds4404", (kernel_ulong_t)&ds4404_info },
+ { "ds4422", (kernel_ulong_t)&ds4422_info },
+ { "ds4424", (kernel_ulong_t)&ds4424_info },
{ }
};
MODULE_DEVICE_TABLE(i2c, ds4424_id);
static const struct of_device_id ds4424_of_match[] = {
- { .compatible = "maxim,ds4422" },
- { .compatible = "maxim,ds4424" },
+ { .compatible = "maxim,ds4402", .data = &ds4402_info },
+ { .compatible = "maxim,ds4404", .data = &ds4404_info },
+ { .compatible = "maxim,ds4422", .data = &ds4422_info },
+ { .compatible = "maxim,ds4424", .data = &ds4424_info },
{ }
};
diff --git a/drivers/iio/dac/ltc2632.c b/drivers/iio/dac/ltc2632.c
index 105f939f7e54..d6a3d290e7a8 100644
--- a/drivers/iio/dac/ltc2632.c
+++ b/drivers/iio/dac/ltc2632.c
@@ -48,27 +48,6 @@ struct ltc2632_state {
int vref_mv;
};
-enum ltc2632_supported_device_ids {
- ID_LTC2632L12,
- ID_LTC2632L10,
- ID_LTC2632L8,
- ID_LTC2632H12,
- ID_LTC2632H10,
- ID_LTC2632H8,
- ID_LTC2634L12,
- ID_LTC2634L10,
- ID_LTC2634L8,
- ID_LTC2634H12,
- ID_LTC2634H10,
- ID_LTC2634H8,
- ID_LTC2636L12,
- ID_LTC2636L10,
- ID_LTC2636L8,
- ID_LTC2636H12,
- ID_LTC2636H10,
- ID_LTC2636H8,
-};
-
static int ltc2632_spi_write(struct spi_device *spi,
u8 cmd, u8 addr, u16 val, u8 shift)
{
@@ -79,8 +58,9 @@ static int ltc2632_spi_write(struct spi_device *spi,
* The input shift register is 24 bits wide.
* The next four are the command bits, C3 to C0,
* followed by the 4-bit DAC address, A3 to A0, and then the
- * 12-, 10-, 8-bit data-word. The data-word comprises the 12-,
- * 10-, 8-bit input code followed by 4, 6, or 8 don't care bits.
+ * 16-, 12-, 10-, 8-bit data-word. The data-word comprises the
+ * 16-, 12-, 10-, 8-bit input code followed by 0, 4, 6, or 8
+ * don't care bits.
*/
data = (cmd << 20) | (addr << 16) | (val << shift);
put_unaligned_be24(data, &msg[0]);
@@ -206,101 +186,129 @@ static const struct iio_chan_spec_ext_info ltc2632_ext_info[] = {
LTC2632_CHANNEL(7, _bits), \
}
+static DECLARE_LTC2632_CHANNELS(ltc2632x16, 16);
static DECLARE_LTC2632_CHANNELS(ltc2632x12, 12);
static DECLARE_LTC2632_CHANNELS(ltc2632x10, 10);
static DECLARE_LTC2632_CHANNELS(ltc2632x8, 8);
-static const struct ltc2632_chip_info ltc2632_chip_info_tbl[] = {
- [ID_LTC2632L12] = {
- .channels = ltc2632x12_channels,
- .num_channels = 2,
- .vref_mv = 2500,
- },
- [ID_LTC2632L10] = {
- .channels = ltc2632x10_channels,
- .num_channels = 2,
- .vref_mv = 2500,
- },
- [ID_LTC2632L8] = {
- .channels = ltc2632x8_channels,
- .num_channels = 2,
- .vref_mv = 2500,
- },
- [ID_LTC2632H12] = {
- .channels = ltc2632x12_channels,
- .num_channels = 2,
- .vref_mv = 4096,
- },
- [ID_LTC2632H10] = {
- .channels = ltc2632x10_channels,
- .num_channels = 2,
- .vref_mv = 4096,
- },
- [ID_LTC2632H8] = {
- .channels = ltc2632x8_channels,
- .num_channels = 2,
- .vref_mv = 4096,
- },
- [ID_LTC2634L12] = {
- .channels = ltc2632x12_channels,
- .num_channels = 4,
- .vref_mv = 2500,
- },
- [ID_LTC2634L10] = {
- .channels = ltc2632x10_channels,
- .num_channels = 4,
- .vref_mv = 2500,
- },
- [ID_LTC2634L8] = {
- .channels = ltc2632x8_channels,
- .num_channels = 4,
- .vref_mv = 2500,
- },
- [ID_LTC2634H12] = {
- .channels = ltc2632x12_channels,
- .num_channels = 4,
- .vref_mv = 4096,
- },
- [ID_LTC2634H10] = {
- .channels = ltc2632x10_channels,
- .num_channels = 4,
- .vref_mv = 4096,
- },
- [ID_LTC2634H8] = {
- .channels = ltc2632x8_channels,
- .num_channels = 4,
- .vref_mv = 4096,
- },
- [ID_LTC2636L12] = {
- .channels = ltc2632x12_channels,
- .num_channels = 8,
- .vref_mv = 2500,
- },
- [ID_LTC2636L10] = {
- .channels = ltc2632x10_channels,
- .num_channels = 8,
- .vref_mv = 2500,
- },
- [ID_LTC2636L8] = {
- .channels = ltc2632x8_channels,
- .num_channels = 8,
- .vref_mv = 2500,
- },
- [ID_LTC2636H12] = {
- .channels = ltc2632x12_channels,
- .num_channels = 8,
- .vref_mv = 4096,
- },
- [ID_LTC2636H10] = {
- .channels = ltc2632x10_channels,
- .num_channels = 8,
- .vref_mv = 4096,
- },
- [ID_LTC2636H8] = {
- .channels = ltc2632x8_channels,
- .num_channels = 8,
- .vref_mv = 4096,
- },
+static const struct ltc2632_chip_info ltc2632l12_chip_info = {
+ .channels = ltc2632x12_channels,
+ .num_channels = 2,
+ .vref_mv = 2500,
+};
+
+static const struct ltc2632_chip_info ltc2632l10_chip_info = {
+ .channels = ltc2632x10_channels,
+ .num_channels = 2,
+ .vref_mv = 2500,
+};
+
+static const struct ltc2632_chip_info ltc2632l8_chip_info = {
+ .channels = ltc2632x8_channels,
+ .num_channels = 2,
+ .vref_mv = 2500,
+};
+
+static const struct ltc2632_chip_info ltc2632h12_chip_info = {
+ .channels = ltc2632x12_channels,
+ .num_channels = 2,
+ .vref_mv = 4096,
+};
+
+static const struct ltc2632_chip_info ltc2632h10_chip_info = {
+ .channels = ltc2632x10_channels,
+ .num_channels = 2,
+ .vref_mv = 4096,
+};
+
+static const struct ltc2632_chip_info ltc2632h8_chip_info = {
+ .channels = ltc2632x8_channels,
+ .num_channels = 2,
+ .vref_mv = 4096,
+};
+
+static const struct ltc2632_chip_info ltc2634l12_chip_info = {
+ .channels = ltc2632x12_channels,
+ .num_channels = 4,
+ .vref_mv = 2500,
+};
+
+static const struct ltc2632_chip_info ltc2634l10_chip_info = {
+ .channels = ltc2632x10_channels,
+ .num_channels = 4,
+ .vref_mv = 2500,
+};
+
+static const struct ltc2632_chip_info ltc2634l8_chip_info = {
+ .channels = ltc2632x8_channels,
+ .num_channels = 4,
+ .vref_mv = 2500,
+};
+
+static const struct ltc2632_chip_info ltc2634h12_chip_info = {
+ .channels = ltc2632x12_channels,
+ .num_channels = 4,
+ .vref_mv = 4096,
+};
+
+static const struct ltc2632_chip_info ltc2634h10_chip_info = {
+ .channels = ltc2632x10_channels,
+ .num_channels = 4,
+ .vref_mv = 4096,
+};
+
+static const struct ltc2632_chip_info ltc2634h8_chip_info = {
+ .channels = ltc2632x8_channels,
+ .num_channels = 4,
+ .vref_mv = 4096,
+};
+
+static const struct ltc2632_chip_info ltc2636l12_chip_info = {
+ .channels = ltc2632x12_channels,
+ .num_channels = 8,
+ .vref_mv = 2500,
+};
+
+static const struct ltc2632_chip_info ltc2636l10_chip_info = {
+ .channels = ltc2632x10_channels,
+ .num_channels = 8,
+ .vref_mv = 2500,
+};
+
+static const struct ltc2632_chip_info ltc2636l8_chip_info = {
+ .channels = ltc2632x8_channels,
+ .num_channels = 8,
+ .vref_mv = 2500,
+};
+
+static const struct ltc2632_chip_info ltc2636h12_chip_info = {
+ .channels = ltc2632x12_channels,
+ .num_channels = 8,
+ .vref_mv = 4096,
+};
+
+static const struct ltc2632_chip_info ltc2636h10_chip_info = {
+ .channels = ltc2632x10_channels,
+ .num_channels = 8,
+ .vref_mv = 4096,
+};
+
+static const struct ltc2632_chip_info ltc2636h8_chip_info = {
+ .channels = ltc2632x8_channels,
+ .num_channels = 8,
+ .vref_mv = 4096,
+};
+
+static const struct ltc2632_chip_info ltc2654l16_chip_info = {
+ .channels = ltc2632x16_channels,
+ .num_channels = 4,
+ .vref_mv = 2500,
+};
+
+static const struct ltc2632_chip_info ltc2654h16_chip_info = {
+ .channels = ltc2632x16_channels,
+ .num_channels = 4,
+ .vref_mv = 4096,
};
static int ltc2632_probe(struct spi_device *spi)
@@ -354,84 +362,53 @@ static int ltc2632_probe(struct spi_device *spi)
}
static const struct spi_device_id ltc2632_id[] = {
- { "ltc2632-l12", (kernel_ulong_t)&ltc2632_chip_info_tbl[ID_LTC2632L12] },
- { "ltc2632-l10", (kernel_ulong_t)&ltc2632_chip_info_tbl[ID_LTC2632L10] },
- { "ltc2632-l8", (kernel_ulong_t)&ltc2632_chip_info_tbl[ID_LTC2632L8] },
- { "ltc2632-h12", (kernel_ulong_t)&ltc2632_chip_info_tbl[ID_LTC2632H12] },
- { "ltc2632-h10", (kernel_ulong_t)&ltc2632_chip_info_tbl[ID_LTC2632H10] },
- { "ltc2632-h8", (kernel_ulong_t)&ltc2632_chip_info_tbl[ID_LTC2632H8] },
- { "ltc2634-l12", (kernel_ulong_t)&ltc2632_chip_info_tbl[ID_LTC2634L12] },
- { "ltc2634-l10", (kernel_ulong_t)&ltc2632_chip_info_tbl[ID_LTC2634L10] },
- { "ltc2634-l8", (kernel_ulong_t)&ltc2632_chip_info_tbl[ID_LTC2634L8] },
- { "ltc2634-h12", (kernel_ulong_t)&ltc2632_chip_info_tbl[ID_LTC2634H12] },
- { "ltc2634-h10", (kernel_ulong_t)&ltc2632_chip_info_tbl[ID_LTC2634H10] },
- { "ltc2634-h8", (kernel_ulong_t)&ltc2632_chip_info_tbl[ID_LTC2634H8] },
- { "ltc2636-l12", (kernel_ulong_t)&ltc2632_chip_info_tbl[ID_LTC2636L12] },
- { "ltc2636-l10", (kernel_ulong_t)&ltc2632_chip_info_tbl[ID_LTC2636L10] },
- { "ltc2636-l8", (kernel_ulong_t)&ltc2632_chip_info_tbl[ID_LTC2636L8] },
- { "ltc2636-h12", (kernel_ulong_t)&ltc2632_chip_info_tbl[ID_LTC2636H12] },
- { "ltc2636-h10", (kernel_ulong_t)&ltc2632_chip_info_tbl[ID_LTC2636H10] },
- { "ltc2636-h8", (kernel_ulong_t)&ltc2632_chip_info_tbl[ID_LTC2636H8] },
+ { "ltc2632-l12", (kernel_ulong_t)&ltc2632l12_chip_info },
+ { "ltc2632-l10", (kernel_ulong_t)&ltc2632l10_chip_info },
+ { "ltc2632-l8", (kernel_ulong_t)&ltc2632l8_chip_info },
+ { "ltc2632-h12", (kernel_ulong_t)&ltc2632h12_chip_info },
+ { "ltc2632-h10", (kernel_ulong_t)&ltc2632h10_chip_info },
+ { "ltc2632-h8", (kernel_ulong_t)&ltc2632h8_chip_info },
+ { "ltc2634-l12", (kernel_ulong_t)&ltc2634l12_chip_info },
+ { "ltc2634-l10", (kernel_ulong_t)&ltc2634l10_chip_info },
+ { "ltc2634-l8", (kernel_ulong_t)&ltc2634l8_chip_info },
+ { "ltc2634-h12", (kernel_ulong_t)&ltc2634h12_chip_info },
+ { "ltc2634-h10", (kernel_ulong_t)&ltc2634h10_chip_info },
+ { "ltc2634-h8", (kernel_ulong_t)&ltc2634h8_chip_info },
+ { "ltc2636-l12", (kernel_ulong_t)&ltc2636l12_chip_info },
+ { "ltc2636-l10", (kernel_ulong_t)&ltc2636l10_chip_info },
+ { "ltc2636-l8", (kernel_ulong_t)&ltc2636l8_chip_info },
+ { "ltc2636-h12", (kernel_ulong_t)&ltc2636h12_chip_info },
+ { "ltc2636-h10", (kernel_ulong_t)&ltc2636h10_chip_info },
+ { "ltc2636-h8", (kernel_ulong_t)&ltc2636h8_chip_info },
+ { "ltc2654-l16", (kernel_ulong_t)&ltc2654l16_chip_info },
+ { "ltc2654-l12", (kernel_ulong_t)&ltc2634l12_chip_info },
+ { "ltc2654-h16", (kernel_ulong_t)&ltc2654h16_chip_info },
+ { "ltc2654-h12", (kernel_ulong_t)&ltc2634h12_chip_info },
{ }
};
MODULE_DEVICE_TABLE(spi, ltc2632_id);
static const struct of_device_id ltc2632_of_match[] = {
- {
- .compatible = "lltc,ltc2632-l12",
- .data = &ltc2632_chip_info_tbl[ID_LTC2632L12]
- }, {
- .compatible = "lltc,ltc2632-l10",
- .data = &ltc2632_chip_info_tbl[ID_LTC2632L10]
- }, {
- .compatible = "lltc,ltc2632-l8",
- .data = &ltc2632_chip_info_tbl[ID_LTC2632L8]
- }, {
- .compatible = "lltc,ltc2632-h12",
- .data = &ltc2632_chip_info_tbl[ID_LTC2632H12]
- }, {
- .compatible = "lltc,ltc2632-h10",
- .data = &ltc2632_chip_info_tbl[ID_LTC2632H10]
- }, {
- .compatible = "lltc,ltc2632-h8",
- .data = &ltc2632_chip_info_tbl[ID_LTC2632H8]
- }, {
- .compatible = "lltc,ltc2634-l12",
- .data = &ltc2632_chip_info_tbl[ID_LTC2634L12]
- }, {
- .compatible = "lltc,ltc2634-l10",
- .data = &ltc2632_chip_info_tbl[ID_LTC2634L10]
- }, {
- .compatible = "lltc,ltc2634-l8",
- .data = &ltc2632_chip_info_tbl[ID_LTC2634L8]
- }, {
- .compatible = "lltc,ltc2634-h12",
- .data = &ltc2632_chip_info_tbl[ID_LTC2634H12]
- }, {
- .compatible = "lltc,ltc2634-h10",
- .data = &ltc2632_chip_info_tbl[ID_LTC2634H10]
- }, {
- .compatible = "lltc,ltc2634-h8",
- .data = &ltc2632_chip_info_tbl[ID_LTC2634H8]
- }, {
- .compatible = "lltc,ltc2636-l12",
- .data = &ltc2632_chip_info_tbl[ID_LTC2636L12]
- }, {
- .compatible = "lltc,ltc2636-l10",
- .data = &ltc2632_chip_info_tbl[ID_LTC2636L10]
- }, {
- .compatible = "lltc,ltc2636-l8",
- .data = &ltc2632_chip_info_tbl[ID_LTC2636L8]
- }, {
- .compatible = "lltc,ltc2636-h12",
- .data = &ltc2632_chip_info_tbl[ID_LTC2636H12]
- }, {
- .compatible = "lltc,ltc2636-h10",
- .data = &ltc2632_chip_info_tbl[ID_LTC2636H10]
- }, {
- .compatible = "lltc,ltc2636-h8",
- .data = &ltc2632_chip_info_tbl[ID_LTC2636H8]
- },
+ { .compatible = "lltc,ltc2632-l12", .data = &ltc2632l12_chip_info },
+ { .compatible = "lltc,ltc2632-l10", .data = &ltc2632l10_chip_info },
+ { .compatible = "lltc,ltc2632-l8", .data = &ltc2632l8_chip_info },
+ { .compatible = "lltc,ltc2632-h12", .data = &ltc2632h12_chip_info },
+ { .compatible = "lltc,ltc2632-h10", .data = &ltc2632h10_chip_info },
+ { .compatible = "lltc,ltc2632-h8", .data = &ltc2632h8_chip_info },
+ { .compatible = "lltc,ltc2634-l12", .data = &ltc2634l12_chip_info },
+ { .compatible = "lltc,ltc2634-l10", .data = &ltc2634l10_chip_info },
+ { .compatible = "lltc,ltc2634-l8", .data = &ltc2634l8_chip_info },
+ { .compatible = "lltc,ltc2634-h12", .data = &ltc2634h12_chip_info },
+ { .compatible = "lltc,ltc2634-h10", .data = &ltc2634h10_chip_info },
+ { .compatible = "lltc,ltc2634-h8", .data = &ltc2634h8_chip_info },
+ { .compatible = "lltc,ltc2636-l12", .data = &ltc2636l12_chip_info },
+ { .compatible = "lltc,ltc2636-l10", .data = &ltc2636l10_chip_info },
+ { .compatible = "lltc,ltc2636-l8", .data = &ltc2636l8_chip_info },
+ { .compatible = "lltc,ltc2636-h12", .data = &ltc2636h12_chip_info },
+ { .compatible = "lltc,ltc2636-h10", .data = &ltc2636h10_chip_info },
+ { .compatible = "lltc,ltc2636-h8", .data = &ltc2636h8_chip_info },
+ { .compatible = "lltc,ltc2654-l16", .data = &ltc2654l16_chip_info },
+ { .compatible = "lltc,ltc2654-h16", .data = &ltc2654h16_chip_info },
{ }
};
MODULE_DEVICE_TABLE(of, ltc2632_of_match);
@@ -447,5 +424,5 @@ static struct spi_driver ltc2632_driver = {
module_spi_driver(ltc2632_driver);
MODULE_AUTHOR("Maxime Roussin-Belanger <maxime.roussinbelanger@gmail.com>");
-MODULE_DESCRIPTION("LTC2632 DAC SPI driver");
+MODULE_DESCRIPTION("LTC2632 and similar DAC SPI driver");
MODULE_LICENSE("GPL v2");
diff --git a/drivers/iio/dac/max5522.c b/drivers/iio/dac/max5522.c
index 1b8fe6b8d26e..b52a9cc1da79 100644
--- a/drivers/iio/dac/max5522.c
+++ b/drivers/iio/dac/max5522.c
@@ -14,6 +14,7 @@
#include <linux/regulator/consumer.h>
#include <linux/slab.h>
#include <linux/spi/spi.h>
+#include <linux/units.h>
#include <linux/iio/iio.h>
@@ -34,7 +35,7 @@ struct max5522_state {
struct regmap *regmap;
const struct max5522_chip_info *chip_info;
unsigned short dac_cache[2];
- struct regulator *vrefin_reg;
+ int vref_mV;
};
#define MAX5522_CHANNEL(chan) { \
@@ -79,17 +80,13 @@ static int max5522_read_raw(struct iio_dev *indio_dev,
int *val, int *val2, long info)
{
struct max5522_state *state = iio_priv(indio_dev);
- int ret;
switch (info) {
case IIO_CHAN_INFO_RAW:
*val = state->dac_cache[chan->channel];
return IIO_VAL_INT;
case IIO_CHAN_INFO_SCALE:
- ret = regulator_get_voltage(state->vrefin_reg);
- if (ret < 0)
- return -EINVAL;
- *val = ret / 1000;
+ *val = state->vref_mV;
*val2 = 10;
return IIO_VAL_FRACTIONAL_LOG2;
default:
@@ -147,16 +144,11 @@ static int max5522_spi_probe(struct spi_device *spi)
if (!state->chip_info)
return -EINVAL;
- state->vrefin_reg = devm_regulator_get(&spi->dev, "vrefin");
- if (IS_ERR(state->vrefin_reg))
- return dev_err_probe(&spi->dev, PTR_ERR(state->vrefin_reg),
- "Vrefin regulator not specified\n");
-
- ret = regulator_enable(state->vrefin_reg);
- if (ret) {
+ ret = devm_regulator_get_enable_read_voltage(&spi->dev, "vrefin");
+ if (ret < 0)
return dev_err_probe(&spi->dev, ret,
- "Failed to enable vref regulators\n");
- }
+ "Failed to get vrefin regulator\n");
+ state->vref_mV = ret / (MICRO / MILLI);
state->regmap = devm_regmap_init_spi(spi, &max5522_regmap_config);
diff --git a/drivers/iio/dac/ti-dac5571.c b/drivers/iio/dac/ti-dac5571.c
index bdc3f94aef98..455d61fc3f13 100644
--- a/drivers/iio/dac/ti-dac5571.c
+++ b/drivers/iio/dac/ti-dac5571.c
@@ -45,7 +45,6 @@ static const struct dac5571_spec dac5571_spec[] = {
struct dac5571_data {
struct i2c_client *client;
- int id;
struct mutex lock;
struct regulator *vref;
u16 val[4];
diff --git a/drivers/iio/filter/admv8818.c b/drivers/iio/filter/admv8818.c
index 19f823446cda..a4984b867248 100644
--- a/drivers/iio/filter/admv8818.c
+++ b/drivers/iio/filter/admv8818.c
@@ -657,56 +657,49 @@ static void admv8818_clk_disable(void *data)
static int admv8818_init(struct admv8818_state *st)
{
int ret;
- struct spi_device *spi = st->spi;
+ struct device *dev = &st->spi->dev;
unsigned int chip_id;
ret = regmap_write(st->regmap, ADMV8818_REG_SPI_CONFIG_A,
ADMV8818_SOFTRESET_N_MSK | ADMV8818_SOFTRESET_MSK);
- if (ret) {
- dev_err(&spi->dev, "ADMV8818 Soft Reset failed.\n");
- return ret;
- }
+ if (ret)
+ return dev_err_probe(dev, ret, "ADMV8818 Soft Reset failed.\n");
ret = regmap_write(st->regmap, ADMV8818_REG_SPI_CONFIG_A,
ADMV8818_SDOACTIVE_N_MSK | ADMV8818_SDOACTIVE_MSK);
- if (ret) {
- dev_err(&spi->dev, "ADMV8818 SDO Enable failed.\n");
- return ret;
- }
+ if (ret)
+ return dev_err_probe(dev, ret, "ADMV8818 SDO Enable failed.\n");
ret = regmap_read(st->regmap, ADMV8818_REG_CHIPTYPE, &chip_id);
- if (ret) {
- dev_err(&spi->dev, "ADMV8818 Chip ID read failed.\n");
- return ret;
- }
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "ADMV8818 Chip ID read failed.\n");
- if (chip_id != 0x1) {
- dev_err(&spi->dev, "ADMV8818 Invalid Chip ID.\n");
- return -EINVAL;
- }
+ if (chip_id != 0x1)
+ return dev_err_probe(dev, -EINVAL,
+ "ADMV8818 Invalid Chip ID.\n");
ret = regmap_update_bits(st->regmap, ADMV8818_REG_SPI_CONFIG_B,
ADMV8818_SINGLE_INSTRUCTION_MSK,
FIELD_PREP(ADMV8818_SINGLE_INSTRUCTION_MSK, 1));
- if (ret) {
- dev_err(&spi->dev, "ADMV8818 Single Instruction failed.\n");
- return ret;
- }
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "ADMV8818 Single Instruction failed.\n");
if (st->clkin)
return admv8818_rfin_band_select(st);
- else
- return 0;
+
+ return 0;
}
static int admv8818_clk_setup(struct admv8818_state *st)
{
- struct spi_device *spi = st->spi;
+ struct device *dev = &st->spi->dev;
int ret;
- st->clkin = devm_clk_get_optional(&spi->dev, "rf_in");
+ st->clkin = devm_clk_get_optional(dev, "rf_in");
if (IS_ERR(st->clkin))
- return dev_err_probe(&spi->dev, PTR_ERR(st->clkin),
+ return dev_err_probe(dev, PTR_ERR(st->clkin),
"failed to get the input clock\n");
else if (!st->clkin)
return 0;
@@ -715,7 +708,7 @@ static int admv8818_clk_setup(struct admv8818_state *st)
if (ret)
return ret;
- ret = devm_add_action_or_reset(&spi->dev, admv8818_clk_disable, st);
+ ret = devm_add_action_or_reset(dev, admv8818_clk_disable, st);
if (ret)
return ret;
@@ -724,16 +717,16 @@ static int admv8818_clk_setup(struct admv8818_state *st)
if (ret < 0)
return ret;
- return devm_add_action_or_reset(&spi->dev, admv8818_clk_notifier_unreg, st);
+ return devm_add_action_or_reset(dev, admv8818_clk_notifier_unreg, st);
}
static int admv8818_read_properties(struct admv8818_state *st)
{
- struct spi_device *spi = st->spi;
+ struct device *dev = &st->spi->dev;
u32 mhz;
int ret;
- ret = device_property_read_u32(&spi->dev, "adi,lpf-margin-mhz", &mhz);
+ ret = device_property_read_u32(dev, "adi,lpf-margin-mhz", &mhz);
if (ret == 0)
st->lpf_margin_hz = (u64)mhz * HZ_PER_MHZ;
else if (ret == -EINVAL)
@@ -742,7 +735,7 @@ static int admv8818_read_properties(struct admv8818_state *st)
return ret;
- ret = device_property_read_u32(&spi->dev, "adi,hpf-margin-mhz", &mhz);
+ ret = device_property_read_u32(dev, "adi,hpf-margin-mhz", &mhz);
if (ret == 0)
st->hpf_margin_hz = (u64)mhz * HZ_PER_MHZ;
else if (ret == -EINVAL)
@@ -758,9 +751,10 @@ static int admv8818_probe(struct spi_device *spi)
struct iio_dev *indio_dev;
struct regmap *regmap;
struct admv8818_state *st;
+ struct device *dev = &spi->dev;
int ret;
- indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
+ indio_dev = devm_iio_device_alloc(dev, sizeof(*st));
if (!indio_dev)
return -ENOMEM;
@@ -792,7 +786,7 @@ static int admv8818_probe(struct spi_device *spi)
if (ret)
return ret;
- return devm_iio_device_register(&spi->dev, indio_dev);
+ return devm_iio_device_register(dev, indio_dev);
}
static const struct spi_device_id admv8818_id[] = {
diff --git a/drivers/iio/frequency/ad9523.c b/drivers/iio/frequency/ad9523.c
index 63c485e9e44c..ea4d2763564a 100644
--- a/drivers/iio/frequency/ad9523.c
+++ b/drivers/iio/frequency/ad9523.c
@@ -167,9 +167,9 @@
/* AD9523_CHANNEL_CLOCK_DIST */
#define AD9523_CLK_DIST_DIV_PHASE(x) (((x) & 0x3F) << 18)
-#define AD9523_CLK_DIST_DIV_PHASE_REV(x) ((ret >> 18) & 0x3F)
+#define AD9523_CLK_DIST_DIV_PHASE_REV(x) (((x) >> 18) & 0x3F)
#define AD9523_CLK_DIST_DIV(x) ((((x) - 1) & 0x3FF) << 8)
-#define AD9523_CLK_DIST_DIV_REV(x) (((ret >> 8) & 0x3FF) + 1)
+#define AD9523_CLK_DIST_DIV_REV(x) ((((x) >> 8) & 0x3FF) + 1)
#define AD9523_CLK_DIST_INV_DIV_OUTPUT_EN (1 << 7)
#define AD9523_CLK_DIST_IGNORE_SYNC_EN (1 << 6)
#define AD9523_CLK_DIST_PWR_DOWN_EN (1 << 5)
@@ -558,55 +558,35 @@ static ssize_t ad9523_show(struct device *dev,
return ret;
}
-static IIO_DEVICE_ATTR(pll1_locked, S_IRUGO,
- ad9523_show,
- NULL,
- AD9523_STAT_PLL1_LD);
-
-static IIO_DEVICE_ATTR(pll2_locked, S_IRUGO,
- ad9523_show,
- NULL,
- AD9523_STAT_PLL2_LD);
-
-static IIO_DEVICE_ATTR(pll1_reference_clk_a_present, S_IRUGO,
- ad9523_show,
- NULL,
- AD9523_STAT_REFA);
-
-static IIO_DEVICE_ATTR(pll1_reference_clk_b_present, S_IRUGO,
- ad9523_show,
- NULL,
- AD9523_STAT_REFB);
-
-static IIO_DEVICE_ATTR(pll1_reference_clk_test_present, S_IRUGO,
- ad9523_show,
- NULL,
- AD9523_STAT_REF_TEST);
-
-static IIO_DEVICE_ATTR(vcxo_clk_present, S_IRUGO,
- ad9523_show,
- NULL,
- AD9523_STAT_VCXO);
-
-static IIO_DEVICE_ATTR(pll2_feedback_clk_present, S_IRUGO,
- ad9523_show,
- NULL,
- AD9523_STAT_PLL2_FB_CLK);
-
-static IIO_DEVICE_ATTR(pll2_reference_clk_present, S_IRUGO,
- ad9523_show,
- NULL,
- AD9523_STAT_PLL2_REF_CLK);
-
-static IIO_DEVICE_ATTR(sync_dividers, S_IWUSR,
- NULL,
- ad9523_store,
- AD9523_SYNC);
-
-static IIO_DEVICE_ATTR(store_eeprom, S_IWUSR,
- NULL,
- ad9523_store,
- AD9523_EEPROM);
+static IIO_DEVICE_ATTR(pll1_locked, 0444, ad9523_show, NULL,
+ AD9523_STAT_PLL1_LD);
+
+static IIO_DEVICE_ATTR(pll2_locked, 0444, ad9523_show, NULL,
+ AD9523_STAT_PLL2_LD);
+
+static IIO_DEVICE_ATTR(pll1_reference_clk_a_present, 0444, ad9523_show, NULL,
+ AD9523_STAT_REFA);
+
+static IIO_DEVICE_ATTR(pll1_reference_clk_b_present, 0444, ad9523_show, NULL,
+ AD9523_STAT_REFB);
+
+static IIO_DEVICE_ATTR(pll1_reference_clk_test_present, 0444, ad9523_show, NULL,
+ AD9523_STAT_REF_TEST);
+
+static IIO_DEVICE_ATTR(vcxo_clk_present, 0444, ad9523_show, NULL,
+ AD9523_STAT_VCXO);
+
+static IIO_DEVICE_ATTR(pll2_feedback_clk_present, 0444, ad9523_show, NULL,
+ AD9523_STAT_PLL2_FB_CLK);
+
+static IIO_DEVICE_ATTR(pll2_reference_clk_present, 0444, ad9523_show, NULL,
+ AD9523_STAT_PLL2_REF_CLK);
+
+static IIO_DEVICE_ATTR(sync_dividers, 0200, NULL, ad9523_store,
+ AD9523_SYNC);
+
+static IIO_DEVICE_ATTR(store_eeprom, 0200, NULL, ad9523_store,
+ AD9523_EEPROM);
static struct attribute *ad9523_attributes[] = {
&iio_dev_attr_sync_dividers.dev_attr.attr,
@@ -797,8 +777,7 @@ static int ad9523_setup(struct iio_dev *indio_dev)
return ret;
ret = ad9523_write(indio_dev, AD9523_PLL1_CHARGE_PUMP_CTRL,
- AD9523_PLL1_CHARGE_PUMP_CURRENT_nA(pdata->
- pll1_charge_pump_current_nA) |
+ AD9523_PLL1_CHARGE_PUMP_CURRENT_nA(pdata->pll1_charge_pump_current_nA) |
AD9523_PLL1_CHARGE_PUMP_MODE_NORMAL |
AD9523_PLL1_BACKLASH_PW_MIN);
if (ret < 0)
@@ -842,8 +821,7 @@ static int ad9523_setup(struct iio_dev *indio_dev)
*/
ret = ad9523_write(indio_dev, AD9523_PLL2_CHARGE_PUMP,
- AD9523_PLL2_CHARGE_PUMP_CURRENT_nA(pdata->
- pll2_charge_pump_current_nA));
+ AD9523_PLL2_CHARGE_PUMP_CURRENT_nA(pdata->pll2_charge_pump_current_nA));
if (ret < 0)
return ret;
@@ -970,17 +948,17 @@ static int ad9523_setup(struct iio_dev *indio_dev)
static int ad9523_probe(struct spi_device *spi)
{
- struct ad9523_platform_data *pdata = dev_get_platdata(&spi->dev);
+ struct device *dev = &spi->dev;
+ struct ad9523_platform_data *pdata;
struct iio_dev *indio_dev;
struct ad9523_state *st;
int ret;
- if (!pdata) {
- dev_err(&spi->dev, "no platform data?\n");
- return -EINVAL;
- }
+ pdata = dev_get_platdata(dev);
+ if (!pdata)
+ return dev_err_probe(dev, -EINVAL, "no platform data?\n");
- indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
+ indio_dev = devm_iio_device_alloc(dev, sizeof(*st));
if (indio_dev == NULL)
return -ENOMEM;
@@ -988,16 +966,16 @@ static int ad9523_probe(struct spi_device *spi)
mutex_init(&st->lock);
- ret = devm_regulator_get_enable(&spi->dev, "vcc");
+ ret = devm_regulator_get_enable(dev, "vcc");
if (ret)
return ret;
- st->pwrdown_gpio = devm_gpiod_get_optional(&spi->dev, "powerdown",
+ st->pwrdown_gpio = devm_gpiod_get_optional(dev, "powerdown",
GPIOD_OUT_HIGH);
if (IS_ERR(st->pwrdown_gpio))
return PTR_ERR(st->pwrdown_gpio);
- st->reset_gpio = devm_gpiod_get_optional(&spi->dev, "reset",
+ st->reset_gpio = devm_gpiod_get_optional(dev, "reset",
GPIOD_OUT_LOW);
if (IS_ERR(st->reset_gpio))
return PTR_ERR(st->reset_gpio);
@@ -1007,7 +985,7 @@ static int ad9523_probe(struct spi_device *spi)
gpiod_direction_output(st->reset_gpio, 1);
}
- st->sync_gpio = devm_gpiod_get_optional(&spi->dev, "sync",
+ st->sync_gpio = devm_gpiod_get_optional(dev, "sync",
GPIOD_OUT_HIGH);
if (IS_ERR(st->sync_gpio))
return PTR_ERR(st->sync_gpio);
@@ -1027,7 +1005,7 @@ static int ad9523_probe(struct spi_device *spi)
if (ret < 0)
return ret;
- return devm_iio_device_register(&spi->dev, indio_dev);
+ return devm_iio_device_register(dev, indio_dev);
}
static const struct spi_device_id ad9523_id[] = {
diff --git a/drivers/iio/frequency/adf4350.c b/drivers/iio/frequency/adf4350.c
index ed1741165f55..6bbb6a8dd9d0 100644
--- a/drivers/iio/frequency/adf4350.c
+++ b/drivers/iio/frequency/adf4350.c
@@ -152,10 +152,10 @@ static int adf4350_set_freq(struct adf4350_state *st, unsigned long long freq)
st->r4_rf_div_sel = 0;
/*
- * !\TODO: The below computation is making sure we get a power of 2
- * shift (st->r4_rf_div_sel) so that freq becomes higher or equal to
- * ADF4350_MIN_VCO_FREQ. This might be simplified with fls()/fls_long()
- * and friends.
+ * NOTE: This iteratively shifts freq by a power of 2
+ * (st->r4_rf_div_sel) to meet or exceed ADF4350_MIN_VCO_FREQ.
+ * A constant-time approach using fls_long() was attempted but
+ * deemed more complex without meaningful benefit for init code.
*/
while (freq < ADF4350_MIN_VCO_FREQ) {
freq <<= 1;
@@ -607,7 +607,7 @@ static int adf4350_probe(struct spi_device *spi)
if (dev_fwnode(&spi->dev)) {
pdata = adf4350_parse_dt(&spi->dev);
if (pdata == NULL)
- return -EINVAL;
+ return -ENOMEM;
} else {
pdata = dev_get_platdata(&spi->dev);
}
diff --git a/drivers/iio/frequency/adf4377.c b/drivers/iio/frequency/adf4377.c
index 8e2da218d48a..ff6077e29c73 100644
--- a/drivers/iio/frequency/adf4377.c
+++ b/drivers/iio/frequency/adf4377.c
@@ -706,23 +706,20 @@ static void adf4377_gpio_init(struct adf4377_state *st)
static int adf4377_init(struct adf4377_state *st)
{
- struct spi_device *spi = st->spi;
+ struct device *dev = &st->spi->dev;
int ret;
adf4377_gpio_init(st);
ret = adf4377_soft_reset(st);
- if (ret) {
- dev_err(&spi->dev, "Failed to soft reset.\n");
- return ret;
- }
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to soft reset.\n");
ret = regmap_multi_reg_write(st->regmap, adf4377_reg_defaults,
ARRAY_SIZE(adf4377_reg_defaults));
- if (ret) {
- dev_err(&spi->dev, "Failed to set default registers.\n");
- return ret;
- }
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "Failed to set default registers.\n");
ret = regmap_update_bits(st->regmap, 0x00,
ADF4377_0000_SDO_ACTIVE_MSK | ADF4377_0000_SDO_ACTIVE_R_MSK,
@@ -730,10 +727,9 @@ static int adf4377_init(struct adf4377_state *st)
ADF4377_0000_SDO_ACTIVE_SPI_4W) |
FIELD_PREP(ADF4377_0000_SDO_ACTIVE_R_MSK,
ADF4377_0000_SDO_ACTIVE_SPI_4W));
- if (ret) {
- dev_err(&spi->dev, "Failed to set 4-Wire Operation.\n");
- return ret;
- }
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "Failed to set 4-Wire Operation.\n");
st->clkin_freq = clk_get_rate(st->clkin);
@@ -747,10 +743,9 @@ static int adf4377_init(struct adf4377_state *st)
FIELD_PREP(ADF4377_001A_PD_PFDCP_MSK, 0) |
FIELD_PREP(ADF4377_001A_PD_CLKOUT1_MSK, 0) |
FIELD_PREP(ADF4377_001A_PD_CLKOUT2_MSK, 0));
- if (ret) {
- dev_err(&spi->dev, "Failed to set power down registers.\n");
- return ret;
- }
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "Failed to set power down registers.\n");
/* Set Mux Output */
ret = regmap_update_bits(st->regmap, 0x1D,
@@ -882,35 +877,35 @@ static const struct iio_chan_spec adf4377_channels[] = {
static int adf4377_properties_parse(struct adf4377_state *st)
{
- struct spi_device *spi = st->spi;
+ struct device *dev = &st->spi->dev;
int ret;
- st->clkin = devm_clk_get_enabled(&spi->dev, "ref_in");
+ st->clkin = devm_clk_get_enabled(dev, "ref_in");
if (IS_ERR(st->clkin))
- return dev_err_probe(&spi->dev, PTR_ERR(st->clkin),
+ return dev_err_probe(dev, PTR_ERR(st->clkin),
"failed to get the reference input clock\n");
- st->gpio_ce = devm_gpiod_get_optional(&st->spi->dev, "chip-enable",
+ st->gpio_ce = devm_gpiod_get_optional(dev, "chip-enable",
GPIOD_OUT_LOW);
if (IS_ERR(st->gpio_ce))
- return dev_err_probe(&spi->dev, PTR_ERR(st->gpio_ce),
+ return dev_err_probe(dev, PTR_ERR(st->gpio_ce),
"failed to get the CE GPIO\n");
- st->gpio_enclk1 = devm_gpiod_get_optional(&st->spi->dev, "clk1-enable",
+ st->gpio_enclk1 = devm_gpiod_get_optional(dev, "clk1-enable",
GPIOD_OUT_LOW);
if (IS_ERR(st->gpio_enclk1))
- return dev_err_probe(&spi->dev, PTR_ERR(st->gpio_enclk1),
+ return dev_err_probe(dev, PTR_ERR(st->gpio_enclk1),
"failed to get the CE GPIO\n");
if (st->chip_info->has_gpio_enclk2) {
- st->gpio_enclk2 = devm_gpiod_get_optional(&st->spi->dev, "clk2-enable",
+ st->gpio_enclk2 = devm_gpiod_get_optional(dev, "clk2-enable",
GPIOD_OUT_LOW);
if (IS_ERR(st->gpio_enclk2))
- return dev_err_probe(&spi->dev, PTR_ERR(st->gpio_enclk2),
+ return dev_err_probe(dev, PTR_ERR(st->gpio_enclk2),
"failed to get the CE GPIO\n");
}
- ret = device_property_match_property_string(&spi->dev, "adi,muxout-select",
+ ret = device_property_match_property_string(dev, "adi,muxout-select",
adf4377_muxout_modes,
ARRAY_SIZE(adf4377_muxout_modes));
if (ret >= 0)
@@ -1055,9 +1050,10 @@ static int adf4377_probe(struct spi_device *spi)
struct iio_dev *indio_dev;
struct regmap *regmap;
struct adf4377_state *st;
+ struct device *dev = &spi->dev;
int ret;
- indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
+ indio_dev = devm_iio_device_alloc(dev, sizeof(*st));
if (!indio_dev)
return -ENOMEM;
@@ -1080,7 +1076,7 @@ static int adf4377_probe(struct spi_device *spi)
return ret;
st->nb.notifier_call = adf4377_freq_change;
- ret = devm_clk_notifier_register(&spi->dev, st->clkin, &st->nb);
+ ret = devm_clk_notifier_register(dev, st->clkin, &st->nb);
if (ret)
return ret;
@@ -1097,7 +1093,7 @@ static int adf4377_probe(struct spi_device *spi)
indio_dev->num_channels = ARRAY_SIZE(adf4377_channels);
}
- return devm_iio_device_register(&spi->dev, indio_dev);
+ return devm_iio_device_register(dev, indio_dev);
}
static const struct spi_device_id adf4377_id[] = {
diff --git a/drivers/iio/frequency/admv1013.c b/drivers/iio/frequency/admv1013.c
index d8e8d541990f..b852378b3f68 100644
--- a/drivers/iio/frequency/admv1013.c
+++ b/drivers/iio/frequency/admv1013.c
@@ -85,9 +85,9 @@ enum {
};
enum {
- ADMV1013_SE_MODE_POS = 6,
- ADMV1013_SE_MODE_NEG = 9,
- ADMV1013_SE_MODE_DIFF = 12
+ ADMV1013_SE_MODE_POS,
+ ADMV1013_SE_MODE_NEG,
+ ADMV1013_SE_MODE_DIFF,
};
struct admv1013_state {
@@ -441,7 +441,7 @@ static int admv1013_init(struct admv1013_state *st, int vcm_uv)
{
int ret;
unsigned int data;
- struct spi_device *spi = st->spi;
+ struct device *dev = &st->spi->dev;
/* Perform a software reset */
ret = __admv1013_spi_update_bits(st, ADMV1013_REG_SPI_CONTROL,
@@ -461,19 +461,30 @@ static int admv1013_init(struct admv1013_state *st, int vcm_uv)
return ret;
data = FIELD_GET(ADMV1013_CHIP_ID_MSK, data);
- if (data != ADMV1013_CHIP_ID) {
- dev_err(&spi->dev, "Invalid Chip ID.\n");
- return -EINVAL;
- }
+ if (data != ADMV1013_CHIP_ID)
+ return dev_err_probe(dev, -EINVAL, "Invalid Chip ID.\n");
ret = __admv1013_spi_write(st, ADMV1013_REG_VVA_TEMP_COMP, 0xE700);
if (ret)
return ret;
- data = FIELD_PREP(ADMV1013_QUAD_SE_MODE_MSK, st->quad_se_mode);
+ switch (st->quad_se_mode) {
+ case ADMV1013_SE_MODE_POS:
+ data = 6;
+ break;
+ case ADMV1013_SE_MODE_NEG:
+ data = 9;
+ break;
+ case ADMV1013_SE_MODE_DIFF:
+ data = 12;
+ break;
+ default:
+ return -EINVAL;
+ }
ret = __admv1013_spi_update_bits(st, ADMV1013_REG_QUAD,
- ADMV1013_QUAD_SE_MODE_MSK, data);
+ ADMV1013_QUAD_SE_MODE_MSK,
+ FIELD_PREP(ADMV1013_QUAD_SE_MODE_MSK, data));
if (ret)
return ret;
@@ -514,43 +525,39 @@ static void admv1013_powerdown(void *data)
admv1013_spi_update_bits(data, ADMV1013_REG_ENABLE, enable_reg_msk, enable_reg);
}
+static const char * const admv1013_input_modes[] = {
+ [ADMV1013_IQ_MODE] = "iq",
+ [ADMV1013_IF_MODE] = "if",
+};
+
+static const char * const admv1013_quad_se_modes[] = {
+ [ADMV1013_SE_MODE_POS] = "se-pos",
+ [ADMV1013_SE_MODE_NEG] = "se-neg",
+ [ADMV1013_SE_MODE_DIFF] = "diff",
+};
+
static int admv1013_properties_parse(struct admv1013_state *st)
{
int ret;
- const char *str;
- struct spi_device *spi = st->spi;
+ struct device *dev = &st->spi->dev;
- st->det_en = device_property_read_bool(&spi->dev, "adi,detector-enable");
+ st->det_en = device_property_read_bool(dev, "adi,detector-enable");
- ret = device_property_read_string(&spi->dev, "adi,input-mode", &str);
- if (ret)
- st->input_mode = ADMV1013_IQ_MODE;
+ ret = device_property_match_property_string(dev, "adi,input-mode",
+ admv1013_input_modes,
+ ARRAY_SIZE(admv1013_input_modes));
+ st->input_mode = ret >= 0 ? ret : ADMV1013_IQ_MODE;
- if (!strcmp(str, "iq"))
- st->input_mode = ADMV1013_IQ_MODE;
- else if (!strcmp(str, "if"))
- st->input_mode = ADMV1013_IF_MODE;
- else
- return -EINVAL;
+ ret = device_property_match_property_string(dev, "adi,quad-se-mode",
+ admv1013_quad_se_modes,
+ ARRAY_SIZE(admv1013_quad_se_modes));
+ st->quad_se_mode = ret >= 0 ? ret : ADMV1013_SE_MODE_DIFF;
- ret = device_property_read_string(&spi->dev, "adi,quad-se-mode", &str);
- if (ret)
- st->quad_se_mode = ADMV1013_SE_MODE_DIFF;
-
- if (!strcmp(str, "diff"))
- st->quad_se_mode = ADMV1013_SE_MODE_DIFF;
- else if (!strcmp(str, "se-pos"))
- st->quad_se_mode = ADMV1013_SE_MODE_POS;
- else if (!strcmp(str, "se-neg"))
- st->quad_se_mode = ADMV1013_SE_MODE_NEG;
- else
- return -EINVAL;
-
- ret = devm_regulator_bulk_get_enable(&st->spi->dev,
+ ret = devm_regulator_bulk_get_enable(dev,
ARRAY_SIZE(admv1013_vcc_regs),
admv1013_vcc_regs);
if (ret) {
- dev_err_probe(&spi->dev, ret,
+ dev_err_probe(dev, ret,
"Failed to request VCC regulators\n");
return ret;
}
@@ -562,9 +569,10 @@ static int admv1013_probe(struct spi_device *spi)
{
struct iio_dev *indio_dev;
struct admv1013_state *st;
+ struct device *dev = &spi->dev;
int ret, vcm_uv;
- indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
+ indio_dev = devm_iio_device_alloc(dev, sizeof(*st));
if (!indio_dev)
return -ENOMEM;
@@ -581,36 +589,34 @@ static int admv1013_probe(struct spi_device *spi)
if (ret)
return ret;
- ret = devm_regulator_get_enable_read_voltage(&spi->dev, "vcm");
+ ret = devm_regulator_get_enable_read_voltage(dev, "vcm");
if (ret < 0)
- return dev_err_probe(&spi->dev, ret,
+ return dev_err_probe(dev, ret,
"failed to get the common-mode voltage\n");
vcm_uv = ret;
- st->clkin = devm_clk_get_enabled(&spi->dev, "lo_in");
+ st->clkin = devm_clk_get_enabled(dev, "lo_in");
if (IS_ERR(st->clkin))
- return dev_err_probe(&spi->dev, PTR_ERR(st->clkin),
+ return dev_err_probe(dev, PTR_ERR(st->clkin),
"failed to get the LO input clock\n");
st->nb.notifier_call = admv1013_freq_change;
- ret = devm_clk_notifier_register(&spi->dev, st->clkin, &st->nb);
+ ret = devm_clk_notifier_register(dev, st->clkin, &st->nb);
if (ret)
return ret;
mutex_init(&st->lock);
ret = admv1013_init(st, vcm_uv);
- if (ret) {
- dev_err(&spi->dev, "admv1013 init failed\n");
- return ret;
- }
+ if (ret)
+ return dev_err_probe(dev, ret, "admv1013 init failed\n");
- ret = devm_add_action_or_reset(&spi->dev, admv1013_powerdown, st);
+ ret = devm_add_action_or_reset(dev, admv1013_powerdown, st);
if (ret)
return ret;
- return devm_iio_device_register(&spi->dev, indio_dev);
+ return devm_iio_device_register(dev, indio_dev);
}
static const struct spi_device_id admv1013_id[] = {
diff --git a/drivers/iio/frequency/admv1014.c b/drivers/iio/frequency/admv1014.c
index 7a8f92ec80a2..25e8cd8135ad 100644
--- a/drivers/iio/frequency/admv1014.c
+++ b/drivers/iio/frequency/admv1014.c
@@ -610,15 +610,14 @@ static int admv1014_init(struct admv1014_state *st)
{
unsigned int chip_id, enable_reg, enable_reg_msk;
struct spi_device *spi = st->spi;
+ struct device *dev = &spi->dev;
int ret;
ret = regulator_bulk_enable(ADMV1014_NUM_REGULATORS, st->regulators);
- if (ret) {
- dev_err(&spi->dev, "Failed to enable regulators");
- return ret;
- }
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to enable regulators");
- ret = devm_add_action_or_reset(&spi->dev, admv1014_reg_disable, st->regulators);
+ ret = devm_add_action_or_reset(dev, admv1014_reg_disable, st->regulators);
if (ret)
return ret;
@@ -626,16 +625,16 @@ static int admv1014_init(struct admv1014_state *st)
if (ret)
return ret;
- ret = devm_add_action_or_reset(&spi->dev, admv1014_clk_disable, st->clkin);
+ ret = devm_add_action_or_reset(dev, admv1014_clk_disable, st->clkin);
if (ret)
return ret;
st->nb.notifier_call = admv1014_freq_change;
- ret = devm_clk_notifier_register(&spi->dev, st->clkin, &st->nb);
+ ret = devm_clk_notifier_register(dev, st->clkin, &st->nb);
if (ret)
return ret;
- ret = devm_add_action_or_reset(&spi->dev, admv1014_powerdown, st);
+ ret = devm_add_action_or_reset(dev, admv1014_powerdown, st);
if (ret)
return ret;
@@ -643,55 +642,47 @@ static int admv1014_init(struct admv1014_state *st)
ret = __admv1014_spi_update_bits(st, ADMV1014_REG_SPI_CONTROL,
ADMV1014_SPI_SOFT_RESET_MSK,
FIELD_PREP(ADMV1014_SPI_SOFT_RESET_MSK, 1));
- if (ret) {
- dev_err(&spi->dev, "ADMV1014 SPI software reset failed.\n");
- return ret;
- }
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "ADMV1014 SPI software reset failed.\n");
ret = __admv1014_spi_update_bits(st, ADMV1014_REG_SPI_CONTROL,
ADMV1014_SPI_SOFT_RESET_MSK,
FIELD_PREP(ADMV1014_SPI_SOFT_RESET_MSK, 0));
- if (ret) {
- dev_err(&spi->dev, "ADMV1014 SPI software reset disable failed.\n");
- return ret;
- }
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "ADMV1014 SPI software reset disable failed.\n");
ret = __admv1014_spi_write(st, ADMV1014_REG_VVA_TEMP_COMP, 0x727C);
- if (ret) {
- dev_err(&spi->dev, "Writing default Temperature Compensation value failed.\n");
- return ret;
- }
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "Writing default Temperature Compensation value failed.\n");
ret = __admv1014_spi_read(st, ADMV1014_REG_SPI_CONTROL, &chip_id);
if (ret)
return ret;
chip_id = FIELD_GET(ADMV1014_CHIP_ID_MSK, chip_id);
- if (chip_id != ADMV1014_CHIP_ID) {
- dev_err(&spi->dev, "Invalid Chip ID.\n");
- return -EINVAL;
- }
+ if (chip_id != ADMV1014_CHIP_ID)
+ return dev_err_probe(dev, -EINVAL, "Invalid Chip ID.\n");
ret = __admv1014_spi_update_bits(st, ADMV1014_REG_QUAD,
ADMV1014_QUAD_SE_MODE_MSK,
FIELD_PREP(ADMV1014_QUAD_SE_MODE_MSK,
st->quad_se_mode));
- if (ret) {
- dev_err(&spi->dev, "Writing Quad SE Mode failed.\n");
- return ret;
- }
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "Writing Quad SE Mode failed.\n");
ret = admv1014_update_quad_filters(st);
- if (ret) {
- dev_err(&spi->dev, "Update Quad Filters failed.\n");
- return ret;
- }
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "Update Quad Filters failed.\n");
ret = admv1014_update_vcm_settings(st);
- if (ret) {
- dev_err(&spi->dev, "Update VCM Settings failed.\n");
- return ret;
- }
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "Update VCM Settings failed.\n");
enable_reg_msk = ADMV1014_P1DB_COMPENSATION_MSK |
ADMV1014_IF_AMP_PD_MSK |
@@ -712,13 +703,14 @@ static int admv1014_properties_parse(struct admv1014_state *st)
{
unsigned int i;
struct spi_device *spi = st->spi;
+ struct device *dev = &spi->dev;
int ret;
- st->det_en = device_property_read_bool(&spi->dev, "adi,detector-enable");
+ st->det_en = device_property_read_bool(dev, "adi,detector-enable");
- st->p1db_comp = device_property_read_bool(&spi->dev, "adi,p1db-compensation-enable");
+ st->p1db_comp = device_property_read_bool(dev, "adi,p1db-compensation-enable");
- ret = device_property_match_property_string(&spi->dev, "adi,input-mode",
+ ret = device_property_match_property_string(dev, "adi,input-mode",
input_mode_names,
ARRAY_SIZE(input_mode_names));
if (ret >= 0)
@@ -726,7 +718,7 @@ static int admv1014_properties_parse(struct admv1014_state *st)
else
st->input_mode = ADMV1014_IQ_MODE;
- ret = device_property_match_property_string(&spi->dev, "adi,quad-se-mode",
+ ret = device_property_match_property_string(dev, "adi,quad-se-mode",
quad_se_mode_names,
ARRAY_SIZE(quad_se_mode_names));
if (ret >= 0)
@@ -737,16 +729,14 @@ static int admv1014_properties_parse(struct admv1014_state *st)
for (i = 0; i < ADMV1014_NUM_REGULATORS; ++i)
st->regulators[i].supply = admv1014_reg_name[i];
- ret = devm_regulator_bulk_get(&st->spi->dev, ADMV1014_NUM_REGULATORS,
+ ret = devm_regulator_bulk_get(dev, ADMV1014_NUM_REGULATORS,
st->regulators);
- if (ret) {
- dev_err(&spi->dev, "Failed to request regulators");
- return ret;
- }
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to request regulators");
- st->clkin = devm_clk_get(&spi->dev, "lo_in");
+ st->clkin = devm_clk_get(dev, "lo_in");
if (IS_ERR(st->clkin))
- return dev_err_probe(&spi->dev, PTR_ERR(st->clkin),
+ return dev_err_probe(dev, PTR_ERR(st->clkin),
"failed to get the LO input clock\n");
return 0;
@@ -756,9 +746,10 @@ static int admv1014_probe(struct spi_device *spi)
{
struct iio_dev *indio_dev;
struct admv1014_state *st;
+ struct device *dev = &spi->dev;
int ret;
- indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
+ indio_dev = devm_iio_device_alloc(dev, sizeof(*st));
if (!indio_dev)
return -ENOMEM;
@@ -787,7 +778,7 @@ static int admv1014_probe(struct spi_device *spi)
if (ret)
return ret;
- return devm_iio_device_register(&spi->dev, indio_dev);
+ return devm_iio_device_register(dev, indio_dev);
}
static const struct spi_device_id admv1014_id[] = {
diff --git a/drivers/iio/frequency/admv4420.c b/drivers/iio/frequency/admv4420.c
index 3ae462b4f5c9..618511eddfb1 100644
--- a/drivers/iio/frequency/admv4420.c
+++ b/drivers/iio/frequency/admv4420.c
@@ -243,7 +243,7 @@ static int admv4420_calc_parameters(struct admv4420_state *st)
st->n_counter.n_counter = 1;
}
if (!sol_found)
- return -1;
+ return -EINVAL;
st->n_counter.int_val = div_u64_rem(st->n_counter.n_counter, 10, &st->n_counter.frac_val);
st->n_counter.mod_val = 10;
@@ -279,10 +279,9 @@ static int admv4420_setup(struct iio_dev *indio_dev)
if (ret)
return ret;
- if (val != ADMV4420_SCRATCH_PAD_VAL_1) {
- dev_err(dev, "Failed ADMV4420 to read/write scratchpad %x ", val);
- return -EIO;
- }
+ if (val != ADMV4420_SCRATCH_PAD_VAL_1)
+ return dev_err_probe(dev, -EIO,
+ "Failed ADMV4420 to read/write scratchpad %x\n", val);
ret = regmap_write(st->regmap,
ADMV4420_SCRATCHPAD,
@@ -294,10 +293,9 @@ static int admv4420_setup(struct iio_dev *indio_dev)
if (ret)
return ret;
- if (val != ADMV4420_SCRATCH_PAD_VAL_2) {
- dev_err(dev, "Failed to read/write scratchpad %x ", val);
- return -EIO;
- }
+ if (val != ADMV4420_SCRATCH_PAD_VAL_2)
+ return dev_err_probe(dev, -EIO,
+ "Failed to read/write scratchpad %x\n", val);
st->mux_sel = ADMV4420_LOCK_DTCT;
st->lo_freq_hz = ADMV4420_DEFAULT_LO_FREQ_HZ;
@@ -305,10 +303,10 @@ static int admv4420_setup(struct iio_dev *indio_dev)
admv4420_fw_parse(st);
ret = admv4420_calc_parameters(st);
- if (ret) {
- dev_err(dev, "Failed calc parameters for %lld ", st->vco_freq_hz);
- return ret;
- }
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "Failed calc parameters for %llu\n",
+ st->vco_freq_hz);
ret = regmap_write(st->regmap, ADMV4420_R_DIV_L,
FIELD_GET(0xFF, st->ref_block.divider));
@@ -344,18 +342,19 @@ static int admv4420_setup(struct iio_dev *indio_dev)
static int admv4420_probe(struct spi_device *spi)
{
+ struct device *dev = &spi->dev;
struct iio_dev *indio_dev;
struct admv4420_state *st;
struct regmap *regmap;
int ret;
- indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
+ indio_dev = devm_iio_device_alloc(dev, sizeof(*st));
if (!indio_dev)
return -ENOMEM;
regmap = devm_regmap_init_spi(spi, &admv4420_regmap_config);
if (IS_ERR(regmap))
- return dev_err_probe(&spi->dev, PTR_ERR(regmap),
+ return dev_err_probe(dev, PTR_ERR(regmap),
"Failed to initializing spi regmap\n");
st = iio_priv(indio_dev);
@@ -368,12 +367,10 @@ static int admv4420_probe(struct spi_device *spi)
indio_dev->num_channels = ARRAY_SIZE(admv4420_channels);
ret = admv4420_setup(indio_dev);
- if (ret) {
- dev_err(&spi->dev, "Setup ADMV4420 failed (%d)\n", ret);
- return ret;
- }
+ if (ret)
+ return dev_err_probe(dev, ret, "Setup ADMV4420 failed\n");
- return devm_iio_device_register(&spi->dev, indio_dev);
+ return devm_iio_device_register(dev, indio_dev);
}
static const struct of_device_id admv4420_of_match[] = {
diff --git a/drivers/iio/frequency/adrf6780.c b/drivers/iio/frequency/adrf6780.c
index a7a21f929970..257fd31a0b0e 100644
--- a/drivers/iio/frequency/adrf6780.c
+++ b/drivers/iio/frequency/adrf6780.c
@@ -346,23 +346,21 @@ static const struct iio_chan_spec adrf6780_channels[] = {
static int adrf6780_reset(struct adrf6780_state *st)
{
int ret;
- struct spi_device *spi = st->spi;
+ struct device *dev = &st->spi->dev;
ret = __adrf6780_spi_update_bits(st, ADRF6780_REG_CONTROL,
ADRF6780_SOFT_RESET_MSK,
FIELD_PREP(ADRF6780_SOFT_RESET_MSK, 1));
- if (ret) {
- dev_err(&spi->dev, "ADRF6780 SPI software reset failed.\n");
- return ret;
- }
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "ADRF6780 SPI software reset failed.\n");
ret = __adrf6780_spi_update_bits(st, ADRF6780_REG_CONTROL,
ADRF6780_SOFT_RESET_MSK,
FIELD_PREP(ADRF6780_SOFT_RESET_MSK, 0));
- if (ret) {
- dev_err(&spi->dev, "ADRF6780 SPI software reset disable failed.\n");
- return ret;
- }
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "ADRF6780 SPI software reset disable failed.\n");
return 0;
}
@@ -371,7 +369,7 @@ static int adrf6780_init(struct adrf6780_state *st)
{
int ret;
unsigned int chip_id, enable_reg, enable_reg_msk;
- struct spi_device *spi = st->spi;
+ struct device *dev = &st->spi->dev;
/* Perform a software reset */
ret = adrf6780_reset(st);
@@ -383,10 +381,9 @@ static int adrf6780_init(struct adrf6780_state *st)
return ret;
chip_id = FIELD_GET(ADRF6780_CHIP_ID_MSK, chip_id);
- if (chip_id != ADRF6780_CHIP_ID) {
- dev_err(&spi->dev, "ADRF6780 Invalid Chip ID.\n");
- return -EINVAL;
- }
+ if (chip_id != ADRF6780_CHIP_ID)
+ return dev_err_probe(dev, -EINVAL,
+ "ADRF6780 Invalid Chip ID.\n");
enable_reg_msk = ADRF6780_VGA_BUFFER_EN_MSK |
ADRF6780_DETECTOR_EN_MSK |
@@ -426,18 +423,18 @@ static int adrf6780_init(struct adrf6780_state *st)
static void adrf6780_properties_parse(struct adrf6780_state *st)
{
- struct spi_device *spi = st->spi;
-
- st->vga_buff_en = device_property_read_bool(&spi->dev, "adi,vga-buff-en");
- st->lo_buff_en = device_property_read_bool(&spi->dev, "adi,lo-buff-en");
- st->if_mode_en = device_property_read_bool(&spi->dev, "adi,if-mode-en");
- st->iq_mode_en = device_property_read_bool(&spi->dev, "adi,iq-mode-en");
- st->lo_x2_en = device_property_read_bool(&spi->dev, "adi,lo-x2-en");
- st->lo_ppf_en = device_property_read_bool(&spi->dev, "adi,lo-ppf-en");
- st->lo_en = device_property_read_bool(&spi->dev, "adi,lo-en");
- st->uc_bias_en = device_property_read_bool(&spi->dev, "adi,uc-bias-en");
- st->lo_sideband = device_property_read_bool(&spi->dev, "adi,lo-sideband");
- st->vdet_out_en = device_property_read_bool(&spi->dev, "adi,vdet-out-en");
+ struct device *dev = &st->spi->dev;
+
+ st->vga_buff_en = device_property_read_bool(dev, "adi,vga-buff-en");
+ st->lo_buff_en = device_property_read_bool(dev, "adi,lo-buff-en");
+ st->if_mode_en = device_property_read_bool(dev, "adi,if-mode-en");
+ st->iq_mode_en = device_property_read_bool(dev, "adi,iq-mode-en");
+ st->lo_x2_en = device_property_read_bool(dev, "adi,lo-x2-en");
+ st->lo_ppf_en = device_property_read_bool(dev, "adi,lo-ppf-en");
+ st->lo_en = device_property_read_bool(dev, "adi,lo-en");
+ st->uc_bias_en = device_property_read_bool(dev, "adi,uc-bias-en");
+ st->lo_sideband = device_property_read_bool(dev, "adi,lo-sideband");
+ st->vdet_out_en = device_property_read_bool(dev, "adi,vdet-out-en");
}
static void adrf6780_powerdown(void *data)
@@ -450,9 +447,10 @@ static int adrf6780_probe(struct spi_device *spi)
{
struct iio_dev *indio_dev;
struct adrf6780_state *st;
+ struct device *dev = &spi->dev;
int ret;
- indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
+ indio_dev = devm_iio_device_alloc(dev, sizeof(*st));
if (!indio_dev)
return -ENOMEM;
@@ -467,9 +465,9 @@ static int adrf6780_probe(struct spi_device *spi)
adrf6780_properties_parse(st);
- st->clkin = devm_clk_get_enabled(&spi->dev, "lo_in");
+ st->clkin = devm_clk_get_enabled(dev, "lo_in");
if (IS_ERR(st->clkin))
- return dev_err_probe(&spi->dev, PTR_ERR(st->clkin),
+ return dev_err_probe(dev, PTR_ERR(st->clkin),
"failed to get the LO input clock\n");
mutex_init(&st->lock);
@@ -478,11 +476,11 @@ static int adrf6780_probe(struct spi_device *spi)
if (ret)
return ret;
- ret = devm_add_action_or_reset(&spi->dev, adrf6780_powerdown, st);
+ ret = devm_add_action_or_reset(dev, adrf6780_powerdown, st);
if (ret)
return ret;
- return devm_iio_device_register(&spi->dev, indio_dev);
+ return devm_iio_device_register(dev, indio_dev);
}
static const struct spi_device_id adrf6780_id[] = {
diff --git a/drivers/iio/gyro/hid-sensor-gyro-3d.c b/drivers/iio/gyro/hid-sensor-gyro-3d.c
index c43990c518f7..c340cc899a7c 100644
--- a/drivers/iio/gyro/hid-sensor-gyro-3d.c
+++ b/drivers/iio/gyro/hid-sensor-gyro-3d.c
@@ -42,7 +42,7 @@ static const u32 gyro_3d_addresses[GYRO_3D_CHANNEL_MAX] = {
HID_USAGE_SENSOR_ANGL_VELOCITY_Z_AXIS
};
-static const u32 gryo_3d_sensitivity_addresses[] = {
+static const u32 gyro_3d_sensitivity_addresses[] = {
HID_USAGE_SENSOR_DATA_ANGL_VELOCITY,
};
@@ -297,8 +297,8 @@ static int hid_gyro_3d_probe(struct platform_device *pdev)
ret = hid_sensor_parse_common_attributes(hsdev,
HID_USAGE_SENSOR_GYRO_3D,
&gyro_state->common_attributes,
- gryo_3d_sensitivity_addresses,
- ARRAY_SIZE(gryo_3d_sensitivity_addresses));
+ gyro_3d_sensitivity_addresses,
+ ARRAY_SIZE(gyro_3d_sensitivity_addresses));
if (ret) {
dev_err(&pdev->dev, "failed to setup common attributes\n");
return ret;
diff --git a/drivers/iio/humidity/hdc2010.c b/drivers/iio/humidity/hdc2010.c
index 894a8b4ab193..1a0f18251381 100644
--- a/drivers/iio/humidity/hdc2010.c
+++ b/drivers/iio/humidity/hdc2010.c
@@ -44,7 +44,6 @@ struct hdc2010_data {
struct i2c_client *client;
struct mutex lock;
u8 measurement_config;
- u8 interrupt_config;
u8 drdy_config;
};
diff --git a/drivers/iio/imu/bmi323/bmi323_core.c b/drivers/iio/imu/bmi323/bmi323_core.c
index 6bcb9a436581..f3d499423399 100644
--- a/drivers/iio/imu/bmi323/bmi323_core.c
+++ b/drivers/iio/imu/bmi323/bmi323_core.c
@@ -156,7 +156,6 @@ struct bmi323_data {
struct iio_mount_matrix orientation;
enum bmi323_irq_pin irq_pin;
struct iio_trigger *trig;
- bool drdy_trigger_enabled;
enum bmi323_state state;
s64 fifo_tstamp, old_fifo_tstamp;
u32 odrns[BMI323_SENSORS_CNT];
diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c b/drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c
index 0ab6eddf0543..532d5fdffaf8 100644
--- a/drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c
+++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c
@@ -1211,7 +1211,7 @@ int inv_icm42600_accel_parse_fifo(struct iio_dev *indio_dev)
ssize_t i, size;
unsigned int no;
const void *accel, *gyro, *timestamp;
- const int8_t *temp;
+ const s8 *temp;
unsigned int odr;
int64_t ts_val;
/* buffer is copied to userspace, zeroing it to avoid any data leak */
diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_magn.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_magn.c
index 6aee6c989485..47394594d17a 100644
--- a/drivers/iio/imu/inv_mpu6050/inv_mpu_magn.c
+++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_magn.c
@@ -125,7 +125,7 @@ static int inv_magn_init(struct inv_mpu6050_state *st)
}
/*
- * Sensitivity adjustement and scale to Gauss
+ * Sensitivity adjustment and scale to Gauss
*
* Hadj = H * (((ASA - 128) * 0.5 / 128) + 1)
* Factor simplification:
diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_i2c.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_i2c.c
index 7c933218036b..b2a7c2eaf50d 100644
--- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_i2c.c
+++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_i2c.c
@@ -144,6 +144,7 @@ MODULE_DEVICE_TABLE(of, st_lsm6dsx_i2c_of_match);
static const struct acpi_device_id st_lsm6dsx_i2c_acpi_match[] = {
{ "SMO8B30", ST_LSM6DS3TRC_ID, },
+ { "SMOCF00", ST_LSM6DSO_ID, },
{ }
};
MODULE_DEVICE_TABLE(acpi, st_lsm6dsx_i2c_acpi_match);
diff --git a/drivers/iio/industrialio-backend.c b/drivers/iio/industrialio-backend.c
index 447b694d6d5f..10e689f49441 100644
--- a/drivers/iio/industrialio-backend.c
+++ b/drivers/iio/industrialio-backend.c
@@ -56,6 +56,7 @@ struct iio_backend {
void *priv;
const char *name;
unsigned int cached_reg_addr;
+ u32 caps;
/*
* This index is relative to the frontend. Meaning that for
* frontends with multiple backends, this will be the index of this
@@ -774,6 +775,20 @@ int iio_backend_extend_chan_spec(struct iio_backend *back,
}
EXPORT_SYMBOL_NS_GPL(iio_backend_extend_chan_spec, "IIO_BACKEND");
+/**
+ * iio_backend_has_caps - Check if backend has specific capabilities
+ * @back: Backend device
+ * @caps: Capabilities to check
+ *
+ * RETURNS:
+ * True if backend has all the requested capabilities, false otherwise.
+ */
+bool iio_backend_has_caps(struct iio_backend *back, u32 caps)
+{
+ return (back->caps & caps) == caps;
+}
+EXPORT_SYMBOL_NS_GPL(iio_backend_has_caps, "IIO_BACKEND");
+
static void iio_backend_release(void *arg)
{
struct iio_backend *back = arg;
@@ -952,7 +967,6 @@ EXPORT_SYMBOL_NS_GPL(iio_backend_data_transfer_addr, "IIO_BACKEND");
static struct iio_backend *__devm_iio_backend_fwnode_get(struct device *dev, const char *name,
struct fwnode_handle *fwnode)
{
- struct fwnode_handle *fwnode_back;
struct iio_backend *back;
unsigned int index;
int ret;
@@ -967,7 +981,8 @@ static struct iio_backend *__devm_iio_backend_fwnode_get(struct device *dev, con
index = 0;
}
- fwnode_back = fwnode_find_reference(fwnode, "io-backends", index);
+ struct fwnode_handle *fwnode_back __free(fwnode_handle) =
+ fwnode_find_reference(fwnode, "io-backends", index);
if (IS_ERR(fwnode_back))
return dev_err_cast_probe(dev, fwnode_back,
"Cannot get Firmware reference\n");
@@ -977,7 +992,6 @@ static struct iio_backend *__devm_iio_backend_fwnode_get(struct device *dev, con
if (!device_match_fwnode(back->dev, fwnode_back))
continue;
- fwnode_handle_put(fwnode_back);
ret = __devm_iio_backend_get(dev, back);
if (ret)
return ERR_PTR(ret);
@@ -988,7 +1002,6 @@ static struct iio_backend *__devm_iio_backend_fwnode_get(struct device *dev, con
return back;
}
- fwnode_handle_put(fwnode_back);
return ERR_PTR(-EPROBE_DEFER);
}
@@ -1114,6 +1127,7 @@ int devm_iio_backend_register(struct device *dev,
back->ops = info->ops;
back->name = info->name;
+ back->caps = info->caps;
back->owner = dev->driver->owner;
back->dev = dev;
back->priv = priv;
diff --git a/drivers/iio/industrialio-event.c b/drivers/iio/industrialio-event.c
index 4149efcd5539..a0d6fcf2a9c9 100644
--- a/drivers/iio/industrialio-event.c
+++ b/drivers/iio/industrialio-event.c
@@ -256,6 +256,7 @@ static const char * const iio_ev_info_text[] = {
[IIO_EV_INFO_TAP2_MIN_DELAY] = "tap2_min_delay",
[IIO_EV_INFO_RUNNING_PERIOD] = "runningperiod",
[IIO_EV_INFO_RUNNING_COUNT] = "runningcount",
+ [IIO_EV_INFO_SCALE] = "scale",
};
static enum iio_event_direction iio_ev_attr_dir(struct iio_dev_attr *attr)
diff --git a/drivers/iio/industrialio-trigger.c b/drivers/iio/industrialio-trigger.c
index 7f34fe7bad07..17781c12bc85 100644
--- a/drivers/iio/industrialio-trigger.c
+++ b/drivers/iio/industrialio-trigger.c
@@ -561,10 +561,6 @@ struct iio_trigger *viio_trigger_alloc(struct device *parent,
if (!trig)
return NULL;
- trig->dev.parent = parent;
- trig->dev.type = &iio_trig_type;
- trig->dev.bus = &iio_bus_type;
- device_initialize(&trig->dev);
INIT_WORK(&trig->reenable_work, iio_reenable_work_fn);
mutex_init(&trig->pool_lock);
@@ -592,6 +588,11 @@ struct iio_trigger *viio_trigger_alloc(struct device *parent,
IRQ_NOREQUEST | IRQ_NOAUTOEN, IRQ_NOPROBE);
}
+ trig->dev.parent = parent;
+ trig->dev.type = &iio_trig_type;
+ trig->dev.bus = &iio_bus_type;
+ device_initialize(&trig->dev);
+
return trig;
free_descs:
@@ -634,9 +635,9 @@ void iio_trigger_free(struct iio_trigger *trig)
}
EXPORT_SYMBOL(iio_trigger_free);
-static void devm_iio_trigger_release(struct device *dev, void *res)
+static void devm_iio_trigger_release(void *trig)
{
- iio_trigger_free(*(struct iio_trigger **)res);
+ iio_trigger_free(trig);
}
/**
@@ -658,24 +659,20 @@ struct iio_trigger *__devm_iio_trigger_alloc(struct device *parent,
struct module *this_mod,
const char *fmt, ...)
{
- struct iio_trigger **ptr, *trig;
+ struct iio_trigger *trig;
va_list vargs;
-
- ptr = devres_alloc(devm_iio_trigger_release, sizeof(*ptr),
- GFP_KERNEL);
- if (!ptr)
- return NULL;
+ int ret;
/* use raw alloc_dr for kmalloc caller tracing */
va_start(vargs, fmt);
trig = viio_trigger_alloc(parent, this_mod, fmt, vargs);
va_end(vargs);
- if (trig) {
- *ptr = trig;
- devres_add(parent, ptr);
- } else {
- devres_free(ptr);
- }
+ if (!trig)
+ return NULL;
+
+ ret = devm_add_action_or_reset(parent, devm_iio_trigger_release, trig);
+ if (ret)
+ return NULL;
return trig;
}
diff --git a/drivers/iio/light/Kconfig b/drivers/iio/light/Kconfig
index ac1408d374c9..eff33e456c70 100644
--- a/drivers/iio/light/Kconfig
+++ b/drivers/iio/light/Kconfig
@@ -359,7 +359,7 @@ config ROHM_BU27034
select IIO_KFIFO_BUF
help
Enable support for the ROHM BU27034 ambient light sensor. ROHM BU27034
- is an ambient light sesnor with 3 channels and 3 photo diodes capable
+ is an ambient light sensor with 3 channels and 3 photo diodes capable
of detecting a very wide range of illuminance.
Typical application is adjusting LCD and backlight power of TVs and
mobile phones.
diff --git a/drivers/iio/light/acpi-als.c b/drivers/iio/light/acpi-als.c
index d5d1a8b9c035..ab229318dce9 100644
--- a/drivers/iio/light/acpi-als.c
+++ b/drivers/iio/light/acpi-als.c
@@ -18,6 +18,7 @@
#include <linux/err.h>
#include <linux/irq.h>
#include <linux/mutex.h>
+#include <linux/platform_device.h>
#include <linux/iio/iio.h>
#include <linux/iio/buffer.h>
@@ -90,9 +91,9 @@ static int acpi_als_read_value(struct acpi_als *als, char *prop, s32 *val)
return 0;
}
-static void acpi_als_notify(struct acpi_device *device, u32 event)
+static void acpi_als_notify(acpi_handle handle, u32 event, void *data)
{
- struct iio_dev *indio_dev = acpi_driver_data(device);
+ struct iio_dev *indio_dev = data;
struct acpi_als *als = iio_priv(indio_dev);
if (iio_buffer_enabled(indio_dev) && iio_trigger_using_own(indio_dev)) {
@@ -102,7 +103,7 @@ static void acpi_als_notify(struct acpi_device *device, u32 event)
break;
default:
/* Unhandled event */
- dev_dbg(&device->dev,
+ dev_dbg(&als->device->dev,
"Unhandled ACPI ALS event (%08x)!\n",
event);
}
@@ -175,9 +176,10 @@ out:
return IRQ_HANDLED;
}
-static int acpi_als_add(struct acpi_device *device)
+static int acpi_als_probe(struct platform_device *pdev)
{
- struct device *dev = &device->dev;
+ struct device *dev = &pdev->dev;
+ struct acpi_device *device = ACPI_COMPANION(dev);
struct iio_dev *indio_dev;
struct acpi_als *als;
int ret;
@@ -188,7 +190,6 @@ static int acpi_als_add(struct acpi_device *device)
als = iio_priv(indio_dev);
- device->driver_data = indio_dev;
als->device = device;
mutex_init(&als->lock);
@@ -218,7 +219,18 @@ static int acpi_als_add(struct acpi_device *device)
if (ret)
return ret;
- return devm_iio_device_register(dev, indio_dev);
+ ret = devm_iio_device_register(dev, indio_dev);
+ if (ret)
+ return ret;
+
+ return acpi_dev_install_notify_handler(device, ACPI_DEVICE_NOTIFY,
+ acpi_als_notify, indio_dev);
+}
+
+static void acpi_als_remove(struct platform_device *pdev)
+{
+ acpi_dev_remove_notify_handler(ACPI_COMPANION(&pdev->dev),
+ ACPI_DEVICE_NOTIFY, acpi_als_notify);
}
static const struct acpi_device_id acpi_als_device_ids[] = {
@@ -228,17 +240,15 @@ static const struct acpi_device_id acpi_als_device_ids[] = {
MODULE_DEVICE_TABLE(acpi, acpi_als_device_ids);
-static struct acpi_driver acpi_als_driver = {
- .name = "acpi_als",
- .class = ACPI_ALS_CLASS,
- .ids = acpi_als_device_ids,
- .ops = {
- .add = acpi_als_add,
- .notify = acpi_als_notify,
+static struct platform_driver acpi_als_driver = {
+ .probe = acpi_als_probe,
+ .remove = acpi_als_remove,
+ .driver = {
+ .name = "acpi_als",
+ .acpi_match_table = acpi_als_device_ids,
},
};
-
-module_acpi_driver(acpi_als_driver);
+module_platform_driver(acpi_als_driver);
MODULE_AUTHOR("Zhang Rui <rui.zhang@intel.com>");
MODULE_AUTHOR("Martin Liska <marxin.liska@gmail.com>");
diff --git a/drivers/iio/light/apds9160.c b/drivers/iio/light/apds9160.c
index 9b8af11b7b67..3da0bdac04cf 100644
--- a/drivers/iio/light/apds9160.c
+++ b/drivers/iio/light/apds9160.c
@@ -620,7 +620,7 @@ static int apds9160_set_ps_gain(struct apds9160_chip *data, int val)
/*
* The PS intelligent cancellation level register allows
- * for an on-chip substraction of the ADC count caused by
+ * for an on-chip subtraction of the ADC count caused by
* unwanted reflected light from PS ADC output.
*/
static int apds9160_set_ps_cancellation_level(struct apds9160_chip *data,
diff --git a/drivers/iio/light/apds9306.c b/drivers/iio/light/apds9306.c
index 7e68cca0edfa..5ca4c87524fe 100644
--- a/drivers/iio/light/apds9306.c
+++ b/drivers/iio/light/apds9306.c
@@ -168,7 +168,6 @@ struct apds9306_regfields {
* respectively.
* @regmap: Regmap structure pointer
* @rf: Regmap register fields structure
- * @nlux_per_count: Nano lux per ADC count for a particular model
* @read_data_available: Flag set by IRQ handler for ADC data available
*/
struct apds9306_data {
@@ -180,7 +179,6 @@ struct apds9306_data {
struct regmap *regmap;
struct apds9306_regfields rf;
- int nlux_per_count;
int read_data_available;
};
@@ -1176,7 +1174,7 @@ static int apds9306_init_iio_gts(struct apds9306_data *data)
static void apds9306_powerdown(void *ptr)
{
- struct apds9306_data *data = (struct apds9306_data *)ptr;
+ struct apds9306_data *data = ptr;
struct apds9306_regfields *rf = &data->rf;
int ret;
diff --git a/drivers/iio/light/as73211.c b/drivers/iio/light/as73211.c
index 32719f584c47..9fe830dac679 100644
--- a/drivers/iio/light/as73211.c
+++ b/drivers/iio/light/as73211.c
@@ -677,9 +677,6 @@ static irqreturn_t as73211_trigger_handler(int irq __always_unused, void *p)
(char *)&scan.chan[0], 3 * sizeof(scan.chan[0]));
if (ret < 0)
goto done;
-
- /* Avoid pushing uninitialized data */
- scan.chan[3] = 0;
}
if (data_result) {
diff --git a/drivers/iio/light/gp2ap020a00f.c b/drivers/iio/light/gp2ap020a00f.c
index c7df4b258e2c..7e388319ee2e 100644
--- a/drivers/iio/light/gp2ap020a00f.c
+++ b/drivers/iio/light/gp2ap020a00f.c
@@ -31,12 +31,14 @@
* the other one.
*/
+#include <linux/cleanup.h>
#include <linux/debugfs.h>
#include <linux/delay.h>
#include <linux/i2c.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/irq_work.h>
+#include <linux/minmax.h>
#include <linux/module.h>
#include <linux/mod_devicetable.h>
#include <linux/mutex.h>
@@ -44,6 +46,7 @@
#include <linux/regulator/consumer.h>
#include <linux/slab.h>
#include <linux/unaligned.h>
+
#include <linux/iio/buffer.h>
#include <linux/iio/events.h>
#include <linux/iio/iio.h>
@@ -52,8 +55,6 @@
#include <linux/iio/trigger_consumer.h>
#include <linux/iio/triggered_buffer.h>
-#define GP2A_I2C_NAME "gp2ap020a00f"
-
/* Registers */
#define GP2AP020A00F_OP_REG 0x00 /* Basic operations */
#define GP2AP020A00F_ALS_REG 0x01 /* ALS related settings */
@@ -174,10 +175,8 @@
#define GP2AP020A00F_CHAN_TIMESTAMP 3
#define GP2AP020A00F_DATA_READY_TIMEOUT msecs_to_jiffies(1000)
-#define GP2AP020A00F_DATA_REG(chan) (GP2AP020A00F_D0_L_REG + \
- (chan) * 2)
-#define GP2AP020A00F_THRESH_REG(th_val_id) (GP2AP020A00F_TL_L_REG + \
- (th_val_id) * 2)
+#define GP2AP020A00F_DATA_REG(chan) (GP2AP020A00F_D0_L_REG + (chan) * 2)
+#define GP2AP020A00F_THRESH_REG(th_val_id) (GP2AP020A00F_TL_L_REG + (th_val_id) * 2)
#define GP2AP020A00F_THRESH_VAL_ID(reg_addr) ((reg_addr - 4) / 2)
#define GP2AP020A00F_SUBTRACT_MODE 0
@@ -194,7 +193,7 @@ enum gp2ap020a00f_opmode {
GP2AP020A00F_OPMODE_ALS_AND_PS,
GP2AP020A00F_OPMODE_PROX_DETECT,
GP2AP020A00F_OPMODE_SHUTDOWN,
- GP2AP020A00F_NUM_OPMODES,
+ GP2AP020A00F_NUM_OPMODES
};
enum gp2ap020a00f_cmd {
@@ -246,7 +245,6 @@ struct gp2ap020a00f_data {
struct iio_trigger *trig;
struct regmap *regmap;
unsigned int thresh_val[4];
- u8 debug_reg_addr;
struct irq_work work;
wait_queue_head_t data_ready_queue;
};
@@ -389,20 +387,17 @@ static int gp2ap020a00f_set_operation_mode(struct gp2ap020a00f_data *data,
}
err = regmap_update_bits(data->regmap, GP2AP020A00F_ALS_REG,
- GP2AP020A00F_PRST_MASK, opmode_regs_settings[op]
- .als_reg);
+ GP2AP020A00F_PRST_MASK, opmode_regs_settings[op].als_reg);
if (err < 0)
return err;
err = regmap_update_bits(data->regmap, GP2AP020A00F_PS_REG,
- GP2AP020A00F_INTTYPE_MASK, opmode_regs_settings[op]
- .ps_reg);
+ GP2AP020A00F_INTTYPE_MASK, opmode_regs_settings[op].ps_reg);
if (err < 0)
return err;
err = regmap_update_bits(data->regmap, GP2AP020A00F_LED_REG,
- GP2AP020A00F_PIN_MASK, opmode_regs_settings[op]
- .led_reg);
+ GP2AP020A00F_PIN_MASK, opmode_regs_settings[op].led_reg);
if (err < 0)
return err;
}
@@ -453,15 +448,13 @@ static int gp2ap020a00f_write_event_threshold(struct gp2ap020a00f_data *data,
*/
thresh_reg_val = data->thresh_val[th_val_id] / 16;
else
- thresh_reg_val = data->thresh_val[th_val_id] > 16000 ?
- 16000 :
- data->thresh_val[th_val_id];
+ thresh_reg_val = min(data->thresh_val[th_val_id], 16000U);
thresh_buf = cpu_to_le16(thresh_reg_val);
return regmap_bulk_write(data->regmap,
GP2AP020A00F_THRESH_REG(th_val_id),
- (u8 *)&thresh_buf, 2);
+ &thresh_buf, sizeof(thresh_buf));
}
static int gp2ap020a00f_alter_opmode(struct gp2ap020a00f_data *data,
@@ -493,27 +486,24 @@ static int gp2ap020a00f_alter_opmode(struct gp2ap020a00f_data *data,
static int gp2ap020a00f_exec_cmd(struct gp2ap020a00f_data *data,
enum gp2ap020a00f_cmd cmd)
{
- int err = 0;
+ int err;
switch (cmd) {
case GP2AP020A00F_CMD_READ_RAW_CLEAR:
if (data->cur_opmode != GP2AP020A00F_OPMODE_SHUTDOWN)
return -EBUSY;
- err = gp2ap020a00f_set_operation_mode(data,
+ return gp2ap020a00f_set_operation_mode(data,
GP2AP020A00F_OPMODE_READ_RAW_CLEAR);
- break;
case GP2AP020A00F_CMD_READ_RAW_IR:
if (data->cur_opmode != GP2AP020A00F_OPMODE_SHUTDOWN)
return -EBUSY;
- err = gp2ap020a00f_set_operation_mode(data,
+ return gp2ap020a00f_set_operation_mode(data,
GP2AP020A00F_OPMODE_READ_RAW_IR);
- break;
case GP2AP020A00F_CMD_READ_RAW_PROXIMITY:
if (data->cur_opmode != GP2AP020A00F_OPMODE_SHUTDOWN)
return -EBUSY;
- err = gp2ap020a00f_set_operation_mode(data,
+ return gp2ap020a00f_set_operation_mode(data,
GP2AP020A00F_OPMODE_READ_RAW_PROXIMITY);
- break;
case GP2AP020A00F_CMD_TRIGGER_CLEAR_EN:
if (data->cur_opmode == GP2AP020A00F_OPMODE_PROX_DETECT)
return -EBUSY;
@@ -521,16 +511,17 @@ static int gp2ap020a00f_exec_cmd(struct gp2ap020a00f_data *data,
err = gp2ap020a00f_alter_opmode(data,
GP2AP020A00F_OPMODE_ALS,
GP2AP020A00F_ADD_MODE);
+ else
+ err = 0;
set_bit(GP2AP020A00F_FLAG_ALS_CLEAR_TRIGGER, &data->flags);
- break;
+ return err;
case GP2AP020A00F_CMD_TRIGGER_CLEAR_DIS:
clear_bit(GP2AP020A00F_FLAG_ALS_CLEAR_TRIGGER, &data->flags);
if (gp2ap020a00f_als_enabled(data))
break;
- err = gp2ap020a00f_alter_opmode(data,
+ return gp2ap020a00f_alter_opmode(data,
GP2AP020A00F_OPMODE_ALS,
GP2AP020A00F_SUBTRACT_MODE);
- break;
case GP2AP020A00F_CMD_TRIGGER_IR_EN:
if (data->cur_opmode == GP2AP020A00F_OPMODE_PROX_DETECT)
return -EBUSY;
@@ -538,16 +529,17 @@ static int gp2ap020a00f_exec_cmd(struct gp2ap020a00f_data *data,
err = gp2ap020a00f_alter_opmode(data,
GP2AP020A00F_OPMODE_ALS,
GP2AP020A00F_ADD_MODE);
+ else
+ err = 0;
set_bit(GP2AP020A00F_FLAG_ALS_IR_TRIGGER, &data->flags);
- break;
+ return err;
case GP2AP020A00F_CMD_TRIGGER_IR_DIS:
clear_bit(GP2AP020A00F_FLAG_ALS_IR_TRIGGER, &data->flags);
if (gp2ap020a00f_als_enabled(data))
break;
- err = gp2ap020a00f_alter_opmode(data,
+ return gp2ap020a00f_alter_opmode(data,
GP2AP020A00F_OPMODE_ALS,
GP2AP020A00F_SUBTRACT_MODE);
- break;
case GP2AP020A00F_CMD_TRIGGER_PROX_EN:
if (data->cur_opmode == GP2AP020A00F_OPMODE_PROX_DETECT)
return -EBUSY;
@@ -555,13 +547,12 @@ static int gp2ap020a00f_exec_cmd(struct gp2ap020a00f_data *data,
GP2AP020A00F_OPMODE_PS,
GP2AP020A00F_ADD_MODE);
set_bit(GP2AP020A00F_FLAG_PROX_TRIGGER, &data->flags);
- break;
+ return err;
case GP2AP020A00F_CMD_TRIGGER_PROX_DIS:
clear_bit(GP2AP020A00F_FLAG_PROX_TRIGGER, &data->flags);
- err = gp2ap020a00f_alter_opmode(data,
+ return gp2ap020a00f_alter_opmode(data,
GP2AP020A00F_OPMODE_PS,
GP2AP020A00F_SUBTRACT_MODE);
- break;
case GP2AP020A00F_CMD_ALS_HIGH_EV_EN:
if (test_bit(GP2AP020A00F_FLAG_ALS_RISING_EV, &data->flags))
return 0;
@@ -575,9 +566,8 @@ static int gp2ap020a00f_exec_cmd(struct gp2ap020a00f_data *data,
return err;
}
set_bit(GP2AP020A00F_FLAG_ALS_RISING_EV, &data->flags);
- err = gp2ap020a00f_write_event_threshold(data,
+ return gp2ap020a00f_write_event_threshold(data,
GP2AP020A00F_THRESH_TH, true);
- break;
case GP2AP020A00F_CMD_ALS_HIGH_EV_DIS:
if (!test_bit(GP2AP020A00F_FLAG_ALS_RISING_EV, &data->flags))
return 0;
@@ -589,9 +579,8 @@ static int gp2ap020a00f_exec_cmd(struct gp2ap020a00f_data *data,
if (err < 0)
return err;
}
- err = gp2ap020a00f_write_event_threshold(data,
+ return gp2ap020a00f_write_event_threshold(data,
GP2AP020A00F_THRESH_TH, false);
- break;
case GP2AP020A00F_CMD_ALS_LOW_EV_EN:
if (test_bit(GP2AP020A00F_FLAG_ALS_FALLING_EV, &data->flags))
return 0;
@@ -605,9 +594,8 @@ static int gp2ap020a00f_exec_cmd(struct gp2ap020a00f_data *data,
return err;
}
set_bit(GP2AP020A00F_FLAG_ALS_FALLING_EV, &data->flags);
- err = gp2ap020a00f_write_event_threshold(data,
+ return gp2ap020a00f_write_event_threshold(data,
GP2AP020A00F_THRESH_TL, true);
- break;
case GP2AP020A00F_CMD_ALS_LOW_EV_DIS:
if (!test_bit(GP2AP020A00F_FLAG_ALS_FALLING_EV, &data->flags))
return 0;
@@ -619,9 +607,8 @@ static int gp2ap020a00f_exec_cmd(struct gp2ap020a00f_data *data,
if (err < 0)
return err;
}
- err = gp2ap020a00f_write_event_threshold(data,
+ return gp2ap020a00f_write_event_threshold(data,
GP2AP020A00F_THRESH_TL, false);
- break;
case GP2AP020A00F_CMD_PROX_HIGH_EV_EN:
if (test_bit(GP2AP020A00F_FLAG_PROX_RISING_EV, &data->flags))
return 0;
@@ -635,9 +622,8 @@ static int gp2ap020a00f_exec_cmd(struct gp2ap020a00f_data *data,
return err;
}
set_bit(GP2AP020A00F_FLAG_PROX_RISING_EV, &data->flags);
- err = gp2ap020a00f_write_event_threshold(data,
+ return gp2ap020a00f_write_event_threshold(data,
GP2AP020A00F_THRESH_PH, true);
- break;
case GP2AP020A00F_CMD_PROX_HIGH_EV_DIS:
if (!test_bit(GP2AP020A00F_FLAG_PROX_RISING_EV, &data->flags))
return 0;
@@ -646,9 +632,8 @@ static int gp2ap020a00f_exec_cmd(struct gp2ap020a00f_data *data,
GP2AP020A00F_OPMODE_SHUTDOWN);
if (err < 0)
return err;
- err = gp2ap020a00f_write_event_threshold(data,
+ return gp2ap020a00f_write_event_threshold(data,
GP2AP020A00F_THRESH_PH, false);
- break;
case GP2AP020A00F_CMD_PROX_LOW_EV_EN:
if (test_bit(GP2AP020A00F_FLAG_PROX_FALLING_EV, &data->flags))
return 0;
@@ -662,9 +647,8 @@ static int gp2ap020a00f_exec_cmd(struct gp2ap020a00f_data *data,
return err;
}
set_bit(GP2AP020A00F_FLAG_PROX_FALLING_EV, &data->flags);
- err = gp2ap020a00f_write_event_threshold(data,
+ return gp2ap020a00f_write_event_threshold(data,
GP2AP020A00F_THRESH_PL, true);
- break;
case GP2AP020A00F_CMD_PROX_LOW_EV_DIS:
if (!test_bit(GP2AP020A00F_FLAG_PROX_FALLING_EV, &data->flags))
return 0;
@@ -673,12 +657,11 @@ static int gp2ap020a00f_exec_cmd(struct gp2ap020a00f_data *data,
GP2AP020A00F_OPMODE_SHUTDOWN);
if (err < 0)
return err;
- err = gp2ap020a00f_write_event_threshold(data,
+ return gp2ap020a00f_write_event_threshold(data,
GP2AP020A00F_THRESH_PL, false);
- break;
}
- return err;
+ return 0;
}
static int wait_conversion_complete_irq(struct gp2ap020a00f_data *data)
@@ -697,18 +680,18 @@ static int wait_conversion_complete_irq(struct gp2ap020a00f_data *data)
static int gp2ap020a00f_read_output(struct gp2ap020a00f_data *data,
unsigned int output_reg, int *val)
{
- u8 reg_buf[2];
+ __le16 reg_buf;
int err;
err = wait_conversion_complete_irq(data);
if (err < 0)
dev_dbg(&data->client->dev, "data ready timeout\n");
- err = regmap_bulk_read(data->regmap, output_reg, reg_buf, 2);
+ err = regmap_bulk_read(data->regmap, output_reg, &reg_buf, sizeof(reg_buf));
if (err < 0)
return err;
- *val = le16_to_cpup((__le16 *)reg_buf);
+ *val = le16_to_cpu(reg_buf);
return err;
}
@@ -866,13 +849,13 @@ static irqreturn_t gp2ap020a00f_thresh_event_handler(int irq, void *data)
{
struct iio_dev *indio_dev = data;
struct gp2ap020a00f_data *priv = iio_priv(indio_dev);
- u8 op_reg_flags, d0_reg_buf[2];
unsigned int output_val, op_reg_val;
+ __le16 d0_reg_buf;
+ u8 op_reg_flags;
int thresh_val_id, ret;
/* Read interrupt flags */
- ret = regmap_read(priv->regmap, GP2AP020A00F_OP_REG,
- &op_reg_val);
+ ret = regmap_read(priv->regmap, GP2AP020A00F_OP_REG, &op_reg_val);
if (ret < 0)
goto done;
@@ -884,8 +867,7 @@ static irqreturn_t gp2ap020a00f_thresh_event_handler(int irq, void *data)
/* Clear interrupt flags (if not in INTTYPE_PULSE mode) */
if (priv->cur_opmode != GP2AP020A00F_OPMODE_PROX_DETECT) {
- ret = regmap_write(priv->regmap, GP2AP020A00F_OP_REG,
- op_reg_val);
+ ret = regmap_write(priv->regmap, GP2AP020A00F_OP_REG, op_reg_val);
if (ret < 0)
goto done;
}
@@ -895,11 +877,11 @@ static irqreturn_t gp2ap020a00f_thresh_event_handler(int irq, void *data)
* transition is required.
*/
ret = regmap_bulk_read(priv->regmap, GP2AP020A00F_D0_L_REG,
- d0_reg_buf, 2);
+ &d0_reg_buf, sizeof(d0_reg_buf));
if (ret < 0)
goto done;
- output_val = le16_to_cpup((__le16 *)d0_reg_buf);
+ output_val = le16_to_cpu(d0_reg_buf);
if (gp2ap020a00f_adjust_lux_mode(priv, output_val))
goto done;
@@ -966,17 +948,15 @@ static irqreturn_t gp2ap020a00f_trigger_handler(int irq, void *data)
int i, out_val, ret;
iio_for_each_active_channel(indio_dev, i) {
- ret = regmap_bulk_read(priv->regmap,
- GP2AP020A00F_DATA_REG(i),
- &priv->buffer[d_size], 2);
+ ret = regmap_bulk_read(priv->regmap, GP2AP020A00F_DATA_REG(i),
+ &priv->buffer[d_size], 2);
if (ret < 0)
goto done;
if (i == GP2AP020A00F_SCAN_MODE_LIGHT_CLEAR ||
i == GP2AP020A00F_SCAN_MODE_LIGHT_IR) {
- out_val = le16_to_cpup((__le16 *)&priv->buffer[d_size]);
+ out_val = get_unaligned_le16(&priv->buffer[d_size]);
gp2ap020a00f_output_to_lux(priv, &out_val);
-
put_unaligned_le32(out_val, &priv->buffer[d_size]);
d_size += 4;
} else {
@@ -984,16 +964,15 @@ static irqreturn_t gp2ap020a00f_trigger_handler(int irq, void *data)
}
}
- iio_push_to_buffers_with_timestamp(indio_dev, priv->buffer,
- pf->timestamp);
+ iio_push_to_buffers_with_timestamp(indio_dev, priv->buffer, pf->timestamp);
done:
iio_trigger_notify_done(indio_dev->trig);
return IRQ_HANDLED;
}
-static u8 gp2ap020a00f_get_thresh_reg(const struct iio_chan_spec *chan,
- enum iio_event_direction event_dir)
+static int gp2ap020a00f_get_thresh_reg(const struct iio_chan_spec *chan,
+ enum iio_event_direction event_dir)
{
switch (chan->type) {
case IIO_PROXIMITY:
@@ -1007,10 +986,8 @@ static u8 gp2ap020a00f_get_thresh_reg(const struct iio_chan_spec *chan,
else
return GP2AP020A00F_TL_L_REG;
default:
- break;
+ return -EINVAL;
}
-
- return -EINVAL;
}
static int gp2ap020a00f_write_event_val(struct iio_dev *indio_dev,
@@ -1023,53 +1000,41 @@ static int gp2ap020a00f_write_event_val(struct iio_dev *indio_dev,
struct gp2ap020a00f_data *data = iio_priv(indio_dev);
bool event_en = false;
u8 thresh_val_id;
- u8 thresh_reg_l;
- int err = 0;
+ int thresh_reg_l;
- mutex_lock(&data->lock);
+ guard(mutex)(&data->lock);
thresh_reg_l = gp2ap020a00f_get_thresh_reg(chan, dir);
- thresh_val_id = GP2AP020A00F_THRESH_VAL_ID(thresh_reg_l);
+ if (thresh_reg_l < 0)
+ return thresh_reg_l;
- if (thresh_val_id > GP2AP020A00F_THRESH_PH) {
- err = -EINVAL;
- goto error_unlock;
- }
+ thresh_val_id = GP2AP020A00F_THRESH_VAL_ID(thresh_reg_l);
+ if (thresh_val_id > GP2AP020A00F_THRESH_PH)
+ return -EINVAL;
switch (thresh_reg_l) {
case GP2AP020A00F_TH_L_REG:
- event_en = test_bit(GP2AP020A00F_FLAG_ALS_RISING_EV,
- &data->flags);
+ event_en = test_bit(GP2AP020A00F_FLAG_ALS_RISING_EV, &data->flags);
break;
case GP2AP020A00F_TL_L_REG:
- event_en = test_bit(GP2AP020A00F_FLAG_ALS_FALLING_EV,
- &data->flags);
+ event_en = test_bit(GP2AP020A00F_FLAG_ALS_FALLING_EV, &data->flags);
break;
case GP2AP020A00F_PH_L_REG:
- if (val == 0) {
- err = -EINVAL;
- goto error_unlock;
- }
- event_en = test_bit(GP2AP020A00F_FLAG_PROX_RISING_EV,
- &data->flags);
+ if (val == 0)
+ return -EINVAL;
+
+ event_en = test_bit(GP2AP020A00F_FLAG_PROX_RISING_EV, &data->flags);
break;
case GP2AP020A00F_PL_L_REG:
- if (val == 0) {
- err = -EINVAL;
- goto error_unlock;
- }
- event_en = test_bit(GP2AP020A00F_FLAG_PROX_FALLING_EV,
- &data->flags);
+ if (val == 0)
+ return -EINVAL;
+
+ event_en = test_bit(GP2AP020A00F_FLAG_PROX_FALLING_EV, &data->flags);
break;
}
data->thresh_val[thresh_val_id] = val;
- err = gp2ap020a00f_write_event_threshold(data, thresh_val_id,
- event_en);
-error_unlock:
- mutex_unlock(&data->lock);
-
- return err;
+ return gp2ap020a00f_write_event_threshold(data, thresh_val_id, event_en);
}
static int gp2ap020a00f_read_event_val(struct iio_dev *indio_dev,
@@ -1080,24 +1045,19 @@ static int gp2ap020a00f_read_event_val(struct iio_dev *indio_dev,
int *val, int *val2)
{
struct gp2ap020a00f_data *data = iio_priv(indio_dev);
- u8 thresh_reg_l;
- int err = IIO_VAL_INT;
+ int thresh_reg_l;
- mutex_lock(&data->lock);
+ guard(mutex)(&data->lock);
thresh_reg_l = gp2ap020a00f_get_thresh_reg(chan, dir);
-
- if (thresh_reg_l > GP2AP020A00F_PH_L_REG) {
- err = -EINVAL;
- goto error_unlock;
- }
+ if (thresh_reg_l < 0)
+ return thresh_reg_l;
+ if (thresh_reg_l > GP2AP020A00F_PH_L_REG)
+ return -EINVAL;
*val = data->thresh_val[GP2AP020A00F_THRESH_VAL_ID(thresh_reg_l)];
-error_unlock:
- mutex_unlock(&data->lock);
-
- return err;
+ return IIO_VAL_INT;
}
static int gp2ap020a00f_write_prox_event_config(struct iio_dev *indio_dev,
@@ -1163,32 +1123,25 @@ static int gp2ap020a00f_write_event_config(struct iio_dev *indio_dev,
{
struct gp2ap020a00f_data *data = iio_priv(indio_dev);
enum gp2ap020a00f_cmd cmd;
- int err;
- mutex_lock(&data->lock);
+ guard(mutex)(&data->lock);
switch (chan->type) {
case IIO_PROXIMITY:
- err = gp2ap020a00f_write_prox_event_config(indio_dev, state);
- break;
+ return gp2ap020a00f_write_prox_event_config(indio_dev, state);
case IIO_LIGHT:
if (dir == IIO_EV_DIR_RISING) {
cmd = state ? GP2AP020A00F_CMD_ALS_HIGH_EV_EN :
GP2AP020A00F_CMD_ALS_HIGH_EV_DIS;
- err = gp2ap020a00f_exec_cmd(data, cmd);
+ return gp2ap020a00f_exec_cmd(data, cmd);
} else {
cmd = state ? GP2AP020A00F_CMD_ALS_LOW_EV_EN :
GP2AP020A00F_CMD_ALS_LOW_EV_DIS;
- err = gp2ap020a00f_exec_cmd(data, cmd);
+ return gp2ap020a00f_exec_cmd(data, cmd);
}
- break;
default:
- err = -EINVAL;
+ return -EINVAL;
}
-
- mutex_unlock(&data->lock);
-
- return err;
}
static int gp2ap020a00f_read_event_config(struct iio_dev *indio_dev,
@@ -1197,40 +1150,29 @@ static int gp2ap020a00f_read_event_config(struct iio_dev *indio_dev,
enum iio_event_direction dir)
{
struct gp2ap020a00f_data *data = iio_priv(indio_dev);
- int event_en = 0;
- mutex_lock(&data->lock);
+ guard(mutex)(&data->lock);
switch (chan->type) {
case IIO_PROXIMITY:
if (dir == IIO_EV_DIR_RISING)
- event_en = test_bit(GP2AP020A00F_FLAG_PROX_RISING_EV,
- &data->flags);
+ return test_bit(GP2AP020A00F_FLAG_PROX_RISING_EV, &data->flags);
else
- event_en = test_bit(GP2AP020A00F_FLAG_PROX_FALLING_EV,
- &data->flags);
- break;
+ return test_bit(GP2AP020A00F_FLAG_PROX_FALLING_EV, &data->flags);
case IIO_LIGHT:
if (dir == IIO_EV_DIR_RISING)
- event_en = test_bit(GP2AP020A00F_FLAG_ALS_RISING_EV,
- &data->flags);
+ return test_bit(GP2AP020A00F_FLAG_ALS_RISING_EV, &data->flags);
else
- event_en = test_bit(GP2AP020A00F_FLAG_ALS_FALLING_EV,
- &data->flags);
- break;
+ return test_bit(GP2AP020A00F_FLAG_ALS_FALLING_EV, &data->flags);
default:
- event_en = -EINVAL;
- break;
+ return -EINVAL;
}
-
- mutex_unlock(&data->lock);
-
- return event_en;
}
static int gp2ap020a00f_read_channel(struct gp2ap020a00f_data *data,
struct iio_chan_spec const *chan, int *val)
{
+ struct device *dev = &data->client->dev;
enum gp2ap020a00f_cmd cmd;
int err;
@@ -1250,27 +1192,23 @@ static int gp2ap020a00f_read_channel(struct gp2ap020a00f_data *data,
err = gp2ap020a00f_exec_cmd(data, cmd);
if (err < 0) {
- dev_err(&data->client->dev,
- "gp2ap020a00f_exec_cmd failed\n");
- goto error_ret;
+ dev_err(dev, "gp2ap020a00f_exec_cmd failed\n");
+ return err;
}
err = gp2ap020a00f_read_output(data, chan->address, val);
if (err < 0)
- dev_err(&data->client->dev,
- "gp2ap020a00f_read_output failed\n");
+ dev_err(dev, "gp2ap020a00f_read_output failed\n");
err = gp2ap020a00f_set_operation_mode(data,
GP2AP020A00F_OPMODE_SHUTDOWN);
if (err < 0)
- dev_err(&data->client->dev,
- "Failed to shut down the device.\n");
+ dev_err(dev, "Failed to shut down the device.\n");
if (cmd == GP2AP020A00F_CMD_READ_RAW_CLEAR ||
cmd == GP2AP020A00F_CMD_READ_RAW_IR)
gp2ap020a00f_output_to_lux(data, val);
-error_ret:
return err;
}
@@ -1383,9 +1321,9 @@ static const struct iio_info gp2ap020a00f_info = {
static int gp2ap020a00f_buffer_postenable(struct iio_dev *indio_dev)
{
struct gp2ap020a00f_data *data = iio_priv(indio_dev);
- int i, err = 0;
+ int i, err;
- mutex_lock(&data->lock);
+ guard(mutex)(&data->lock);
/*
* Enable triggers according to the scan_mask. Enabling either
@@ -1409,28 +1347,27 @@ static int gp2ap020a00f_buffer_postenable(struct iio_dev *indio_dev)
err = gp2ap020a00f_exec_cmd(data,
GP2AP020A00F_CMD_TRIGGER_PROX_EN);
break;
+ default:
+ err = -EINVAL;
+ break;
}
+ if (err)
+ return err;
}
- if (err < 0)
- goto error_unlock;
-
data->buffer = kmalloc(indio_dev->scan_bytes, GFP_KERNEL);
if (!data->buffer)
- err = -ENOMEM;
-
-error_unlock:
- mutex_unlock(&data->lock);
+ return -ENOMEM;
- return err;
+ return 0;
}
static int gp2ap020a00f_buffer_predisable(struct iio_dev *indio_dev)
{
struct gp2ap020a00f_data *data = iio_priv(indio_dev);
- int i, err = 0;
+ int i, err;
- mutex_lock(&data->lock);
+ guard(mutex)(&data->lock);
iio_for_each_active_channel(indio_dev, i) {
switch (i) {
@@ -1446,15 +1383,16 @@ static int gp2ap020a00f_buffer_predisable(struct iio_dev *indio_dev)
err = gp2ap020a00f_exec_cmd(data,
GP2AP020A00F_CMD_TRIGGER_PROX_DIS);
break;
+ default:
+ err = -EINVAL;
+ break;
}
+ if (err)
+ return err;
}
- if (err == 0)
- kfree(data->buffer);
-
- mutex_unlock(&data->lock);
-
- return err;
+ kfree(data->buffer);
+ return 0;
}
static const struct iio_buffer_setup_ops gp2ap020a00f_buffer_setup_ops = {
@@ -1465,18 +1403,19 @@ static const struct iio_buffer_setup_ops gp2ap020a00f_buffer_setup_ops = {
static int gp2ap020a00f_probe(struct i2c_client *client)
{
const struct i2c_device_id *id = i2c_client_get_device_id(client);
+ struct device *dev = &client->dev;
struct gp2ap020a00f_data *data;
struct iio_dev *indio_dev;
struct regmap *regmap;
int err;
- indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
+ indio_dev = devm_iio_device_alloc(dev, sizeof(*data));
if (!indio_dev)
return -ENOMEM;
data = iio_priv(indio_dev);
- data->vled_reg = devm_regulator_get(&client->dev, "vled");
+ data->vled_reg = devm_regulator_get(dev, "vled");
if (IS_ERR(data->vled_reg))
return PTR_ERR(data->vled_reg);
@@ -1486,7 +1425,7 @@ static int gp2ap020a00f_probe(struct i2c_client *client)
regmap = devm_regmap_init_i2c(client, &gp2ap020a00f_regmap_config);
if (IS_ERR(regmap)) {
- dev_err(&client->dev, "Regmap initialization failed.\n");
+ dev_err(dev, "Regmap initialization failed.\n");
err = PTR_ERR(regmap);
goto error_regulator_disable;
}
@@ -1497,7 +1436,7 @@ static int gp2ap020a00f_probe(struct i2c_client *client)
ARRAY_SIZE(gp2ap020a00f_reg_init_tab));
if (err < 0) {
- dev_err(&client->dev, "Device initialization failed.\n");
+ dev_err(dev, "Device initialization failed.\n");
goto error_regulator_disable;
}
@@ -1522,11 +1461,10 @@ static int gp2ap020a00f_probe(struct i2c_client *client)
goto error_regulator_disable;
/* Allocate trigger */
- data->trig = devm_iio_trigger_alloc(&client->dev, "%s-trigger",
- indio_dev->name);
+ data->trig = devm_iio_trigger_alloc(dev, "%s-trigger", indio_dev->name);
if (data->trig == NULL) {
err = -ENOMEM;
- dev_err(&indio_dev->dev, "Failed to allocate iio trigger.\n");
+ dev_err(dev, "Failed to allocate iio trigger.\n");
goto error_uninit_buffer;
}
@@ -1538,7 +1476,7 @@ static int gp2ap020a00f_probe(struct i2c_client *client)
"gp2ap020a00f_als_event",
indio_dev);
if (err < 0) {
- dev_err(&client->dev, "Irq request failed.\n");
+ dev_err(dev, "Irq request failed.\n");
goto error_uninit_buffer;
}
@@ -1546,7 +1484,7 @@ static int gp2ap020a00f_probe(struct i2c_client *client)
err = iio_trigger_register(data->trig);
if (err < 0) {
- dev_err(&client->dev, "Failed to register iio trigger.\n");
+ dev_err(dev, "Failed to register iio trigger.\n");
goto error_free_irq;
}
@@ -1572,12 +1510,12 @@ static void gp2ap020a00f_remove(struct i2c_client *client)
{
struct iio_dev *indio_dev = i2c_get_clientdata(client);
struct gp2ap020a00f_data *data = iio_priv(indio_dev);
+ struct device *dev = &client->dev;
int err;
- err = gp2ap020a00f_set_operation_mode(data,
- GP2AP020A00F_OPMODE_SHUTDOWN);
+ err = gp2ap020a00f_set_operation_mode(data, GP2AP020A00F_OPMODE_SHUTDOWN);
if (err < 0)
- dev_err(&indio_dev->dev, "Failed to power off the device.\n");
+ dev_err(dev, "Failed to power off the device.\n");
iio_device_unregister(indio_dev);
iio_trigger_unregister(data->trig);
@@ -1587,10 +1525,9 @@ static void gp2ap020a00f_remove(struct i2c_client *client)
}
static const struct i2c_device_id gp2ap020a00f_id[] = {
- { GP2A_I2C_NAME },
+ { "gp2ap020a00f" },
{ }
};
-
MODULE_DEVICE_TABLE(i2c, gp2ap020a00f_id);
static const struct of_device_id gp2ap020a00f_of_match[] = {
@@ -1601,14 +1538,13 @@ MODULE_DEVICE_TABLE(of, gp2ap020a00f_of_match);
static struct i2c_driver gp2ap020a00f_driver = {
.driver = {
- .name = GP2A_I2C_NAME,
+ .name = "gp2ap020a00f",
.of_match_table = gp2ap020a00f_of_match,
},
.probe = gp2ap020a00f_probe,
.remove = gp2ap020a00f_remove,
.id_table = gp2ap020a00f_id,
};
-
module_i2c_driver(gp2ap020a00f_driver);
MODULE_AUTHOR("Jacek Anaszewski <j.anaszewski@samsung.com>");
diff --git a/drivers/iio/light/ltr390.c b/drivers/iio/light/ltr390.c
index fc387426fa87..f1702aca582d 100644
--- a/drivers/iio/light/ltr390.c
+++ b/drivers/iio/light/ltr390.c
@@ -101,7 +101,7 @@ enum ltr390_meas_rate {
struct ltr390_data {
struct regmap *regmap;
struct i2c_client *client;
- /* Protects device from simulataneous reads */
+ /* Protects device from simultaneous reads */
struct mutex lock;
enum ltr390_mode mode;
int gain;
diff --git a/drivers/iio/light/ltr501.c b/drivers/iio/light/ltr501.c
index 022e0693983b..4d99ae336f61 100644
--- a/drivers/iio/light/ltr501.c
+++ b/drivers/iio/light/ltr501.c
@@ -754,7 +754,7 @@ static int ltr501_get_gain_index(const struct ltr501_gain *gain, int size,
if (val == gain[i].scale && val2 == gain[i].uscale)
return i;
- return -1;
+ return -EINVAL;
}
static int __ltr501_write_raw(struct iio_dev *indio_dev,
@@ -773,7 +773,7 @@ static int __ltr501_write_raw(struct iio_dev *indio_dev,
info->als_gain_tbl_size,
val, val2);
if (i < 0)
- return -EINVAL;
+ return i;
data->als_contr &= ~info->als_gain_mask;
data->als_contr |= i << info->als_gain_shift;
@@ -785,7 +785,7 @@ static int __ltr501_write_raw(struct iio_dev *indio_dev,
info->ps_gain_tbl_size,
val, val2);
if (i < 0)
- return -EINVAL;
+ return i;
data->ps_contr &= ~LTR501_CONTR_PS_GAIN_MASK;
data->ps_contr |= i << LTR501_CONTR_PS_GAIN_SHIFT;
diff --git a/drivers/iio/light/opt3001.c b/drivers/iio/light/opt3001.c
index 393a3d2fbe1d..53bc455b7bad 100644
--- a/drivers/iio/light/opt3001.c
+++ b/drivers/iio/light/opt3001.c
@@ -91,7 +91,7 @@ struct opt3001_chip_info {
*/
int factor_integer;
/*
- * Factor used to align decimal part of proccessed value to six decimal
+ * Factor used to align decimal part of processed value to six decimal
* places.
*/
int factor_decimal;
diff --git a/drivers/iio/light/tsl2772.c b/drivers/iio/light/tsl2772.c
index 0b171106441a..c8f15ba95267 100644
--- a/drivers/iio/light/tsl2772.c
+++ b/drivers/iio/light/tsl2772.c
@@ -190,7 +190,7 @@ struct tsl2772_chip {
};
/*
- * Different devices require different coefficents, and these numbers were
+ * Different devices require different coefficients, and these numbers were
* derived from the 'Lux Equation' section of the various device datasheets.
* All of these coefficients assume a Glass Attenuation (GA) factor of 1.
* The coefficients are multiplied by 1000 to avoid floating point operations.
diff --git a/drivers/iio/light/vcnl4000.c b/drivers/iio/light/vcnl4000.c
index a36c23813679..9650dbc41f2b 100644
--- a/drivers/iio/light/vcnl4000.c
+++ b/drivers/iio/light/vcnl4000.c
@@ -18,12 +18,13 @@
*/
#include <linux/bitfield.h>
-#include <linux/module.h>
-#include <linux/i2c.h>
-#include <linux/err.h>
#include <linux/delay.h>
-#include <linux/pm_runtime.h>
+#include <linux/err.h>
+#include <linux/i2c.h>
#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/pm_runtime.h>
+#include <linux/regulator/consumer.h>
#include <linux/units.h>
#include <linux/iio/buffer.h>
@@ -185,6 +186,7 @@ static const int vcnl4040_ps_oversampling_ratio[] = {1, 2, 4, 8};
#define VCNL4000_SLEEP_DELAY_MS 2000 /* before we enter pm_runtime_suspend */
enum vcnl4000_device_ids {
+ CM36672P,
VCNL4000,
VCNL4010,
VCNL4040,
@@ -235,6 +237,8 @@ struct vcnl4000_chip_spec {
};
static const struct i2c_device_id vcnl4000_id[] = {
+ { "cm36672p", CM36672P },
+ { "cm36686", VCNL4040 },
{ "vcnl4000", VCNL4000 },
{ "vcnl4010", VCNL4010 },
{ "vcnl4020", VCNL4010 },
@@ -277,7 +281,7 @@ static int vcnl4000_init(struct vcnl4000_data *data)
data->rev = ret & 0xf;
data->al_scale = 250000;
- return data->chip_spec->set_power_state(data, true);
+ return 0;
};
static ssize_t vcnl4000_write_als_enable(struct vcnl4000_data *data, bool en)
@@ -353,17 +357,19 @@ static int vcnl4200_set_power_state(struct vcnl4000_data *data, bool on)
static int vcnl4200_init(struct vcnl4000_data *data)
{
+ struct i2c_client *client = data->client;
+ struct device *dev = &client->dev;
int ret, id;
u16 regval;
- ret = i2c_smbus_read_word_data(data->client, VCNL4200_DEV_ID);
+ ret = i2c_smbus_read_word_data(client, VCNL4200_DEV_ID);
if (ret < 0)
return ret;
id = ret & 0xff;
if (id != VCNL4200_PROD_ID) {
- ret = i2c_smbus_read_word_data(data->client, VCNL4040_DEV_ID);
+ ret = i2c_smbus_read_word_data(client, VCNL4040_DEV_ID);
if (ret < 0)
return ret;
@@ -373,7 +379,7 @@ static int vcnl4200_init(struct vcnl4000_data *data)
return -ENODEV;
}
- dev_dbg(&data->client->dev, "device id 0x%x", id);
+ dev_dbg(dev, "device id 0x%x", id);
data->rev = (ret >> 8) & 0xf;
data->ps_int = 0;
@@ -397,32 +403,32 @@ static int vcnl4200_init(struct vcnl4000_data *data)
}
data->al_scale = data->chip_spec->ulux_step;
data->ps_scale = 16;
- mutex_init(&data->vcnl4200_al.lock);
- mutex_init(&data->vcnl4200_ps.lock);
+
+ ret = devm_mutex_init(dev, &data->vcnl4200_al.lock);
+ if (ret)
+ return ret;
+
+ ret = devm_mutex_init(dev, &data->vcnl4200_ps.lock);
+ if (ret)
+ return ret;
/* Use 16 bits proximity sensor readings */
- ret = i2c_smbus_read_word_data(data->client, VCNL4200_PS_CONF1);
+ ret = i2c_smbus_read_word_data(client, VCNL4200_PS_CONF1);
if (ret < 0)
return ret;
regval = ret | VCNL4040_PS_CONF2_PS_HD;
- ret = i2c_smbus_write_word_data(data->client, VCNL4200_PS_CONF1,
- regval);
+ ret = i2c_smbus_write_word_data(client, VCNL4200_PS_CONF1, regval);
if (ret < 0)
return ret;
/* Align proximity sensor sample rate to 16 bits data width */
- ret = i2c_smbus_read_word_data(data->client, VCNL4200_PS_CONF3);
+ ret = i2c_smbus_read_word_data(client, VCNL4200_PS_CONF3);
if (ret < 0)
return ret;
regval = ret | VCNL4040_CONF3_PS_SAMPLE_16BITS;
- ret = i2c_smbus_write_word_data(data->client, VCNL4200_PS_CONF3,
- regval);
- if (ret < 0)
- return ret;
-
- ret = data->chip_spec->set_power_state(data, true);
+ ret = i2c_smbus_write_word_data(client, VCNL4200_PS_CONF3, regval);
if (ret < 0)
return ret;
@@ -1842,6 +1848,22 @@ static const struct iio_chan_spec vcnl4040_channels[] = {
}
};
+static const struct iio_chan_spec cm36672p_channels[] = {
+ {
+ .type = IIO_PROXIMITY,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+ BIT(IIO_CHAN_INFO_INT_TIME) |
+ BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO) |
+ BIT(IIO_CHAN_INFO_CALIBBIAS),
+ .info_mask_separate_available = BIT(IIO_CHAN_INFO_INT_TIME) |
+ BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO) |
+ BIT(IIO_CHAN_INFO_CALIBBIAS),
+ .ext_info = vcnl4000_ext_info,
+ .event_spec = vcnl4040_event_spec,
+ .num_event_specs = ARRAY_SIZE(vcnl4040_event_spec),
+ },
+};
+
static const struct iio_info vcnl4000_info = {
.read_raw = vcnl4000_read_raw,
};
@@ -1867,6 +1889,19 @@ static const struct iio_info vcnl4040_info = {
};
static const struct vcnl4000_chip_spec vcnl4000_chip_spec_cfg[] = {
+ [CM36672P] = {
+ .prod = "CM36672P",
+ .init = vcnl4200_init,
+ .measure_proximity = vcnl4200_measure_proximity,
+ .set_power_state = vcnl4200_set_power_state,
+ .channels = cm36672p_channels,
+ .num_channels = ARRAY_SIZE(cm36672p_channels),
+ .info = &vcnl4040_info,
+ .irq_thread = vcnl4040_irq_thread,
+ .int_reg = VCNL4040_INT_FLAGS,
+ .ps_it_times = &vcnl4040_ps_it_times,
+ .num_ps_it_times = ARRAY_SIZE(vcnl4040_ps_it_times),
+ },
[VCNL4000] = {
.prod = "VCNL4000",
.init = vcnl4000_init,
@@ -1951,11 +1986,13 @@ static int vcnl4010_probe_trigger(struct iio_dev *indio_dev)
static int vcnl4000_probe(struct i2c_client *client)
{
const struct i2c_device_id *id = i2c_client_get_device_id(client);
+ const char * const regulator_names[] = { "vdd", "vio", "vled" };
+ struct device *dev = &client->dev;
struct vcnl4000_data *data;
struct iio_dev *indio_dev;
int ret;
- indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
+ indio_dev = devm_iio_device_alloc(dev, sizeof(*data));
if (!indio_dev)
return -ENOMEM;
@@ -1965,18 +2002,27 @@ static int vcnl4000_probe(struct i2c_client *client)
data->id = id->driver_data;
data->chip_spec = &vcnl4000_chip_spec_cfg[data->id];
- mutex_init(&data->vcnl4000_lock);
+ ret = devm_regulator_bulk_get_enable(dev, ARRAY_SIZE(regulator_names),
+ regulator_names);
+ if (ret)
+ return ret;
+
+ ret = devm_mutex_init(dev, &data->vcnl4000_lock);
+ if (ret)
+ return ret;
ret = data->chip_spec->init(data);
if (ret < 0)
return ret;
- dev_dbg(&client->dev, "%s Ambient light/proximity sensor, Rev: %02x\n",
+ ret = data->chip_spec->set_power_state(data, true);
+ if (ret)
+ return ret;
+
+ dev_dbg(dev, "%s Ambient light/proximity sensor, Rev: %02x\n",
data->chip_spec->prod, data->rev);
- if (device_property_read_u32(&client->dev, "proximity-near-level",
- &data->near_level))
- data->near_level = 0;
+ device_property_read_u32(dev, "proximity-near-level", &data->near_level);
indio_dev->info = data->chip_spec->info;
indio_dev->channels = data->chip_spec->channels;
@@ -1986,35 +2032,29 @@ static int vcnl4000_probe(struct i2c_client *client)
if (data->chip_spec->trig_buffer_func &&
data->chip_spec->buffer_setup_ops) {
- ret = devm_iio_triggered_buffer_setup(&client->dev, indio_dev,
- NULL,
+ ret = devm_iio_triggered_buffer_setup(dev, indio_dev, NULL,
data->chip_spec->trig_buffer_func,
data->chip_spec->buffer_setup_ops);
- if (ret < 0) {
- dev_err(&client->dev,
- "unable to setup iio triggered buffer\n");
+ if (ret < 0)
return ret;
- }
}
if (client->irq && data->chip_spec->irq_thread) {
- ret = devm_request_threaded_irq(&client->dev, client->irq,
- NULL, data->chip_spec->irq_thread,
+ ret = devm_request_threaded_irq(dev, client->irq, NULL,
+ data->chip_spec->irq_thread,
IRQF_TRIGGER_FALLING |
IRQF_ONESHOT,
"vcnl4000_irq",
indio_dev);
- if (ret < 0) {
- dev_err(&client->dev, "irq request failed\n");
+ if (ret < 0)
return ret;
- }
ret = vcnl4010_probe_trigger(indio_dev);
if (ret < 0)
return ret;
}
- ret = pm_runtime_set_active(&client->dev);
+ ret = pm_runtime_set_active(dev);
if (ret < 0)
goto fail_poweroff;
@@ -2022,9 +2062,9 @@ static int vcnl4000_probe(struct i2c_client *client)
if (ret < 0)
goto fail_poweroff;
- pm_runtime_enable(&client->dev);
- pm_runtime_set_autosuspend_delay(&client->dev, VCNL4000_SLEEP_DELAY_MS);
- pm_runtime_use_autosuspend(&client->dev);
+ pm_runtime_enable(dev);
+ pm_runtime_set_autosuspend_delay(dev, VCNL4000_SLEEP_DELAY_MS);
+ pm_runtime_use_autosuspend(dev);
return 0;
fail_poweroff:
@@ -2034,6 +2074,15 @@ fail_poweroff:
static const struct of_device_id vcnl_4000_of_match[] = {
{
+ .compatible = "capella,cm36672p",
+ .data = (void *)CM36672P,
+ },
+ /* Capella CM36686 is fully compatible with Vishay VCNL4040 */
+ {
+ .compatible = "capella,cm36686",
+ .data = (void *)VCNL4040,
+ },
+ {
.compatible = "vishay,vcnl4000",
.data = (void *)VCNL4000,
},
diff --git a/drivers/iio/light/zopt2201.c b/drivers/iio/light/zopt2201.c
index 1dba1b949cc3..0990e4d266eb 100644
--- a/drivers/iio/light/zopt2201.c
+++ b/drivers/iio/light/zopt2201.c
@@ -10,17 +10,17 @@
* TODO: interrupt support, ALS/UVB raw mode
*/
-#include <linux/module.h>
+#include <linux/cleanup.h>
+#include <linux/delay.h>
+#include <linux/err.h>
#include <linux/i2c.h>
+#include <linux/module.h>
#include <linux/mutex.h>
-#include <linux/err.h>
-#include <linux/delay.h>
+#include <linux/unaligned.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
-#include <linux/unaligned.h>
-
#define ZOPT2201_DRV_NAME "zopt2201"
/* Registers */
@@ -186,10 +186,10 @@ static int zopt2201_read(struct zopt2201_data *data, u8 reg)
u8 buf[3];
int ret;
- mutex_lock(&data->lock);
+ guard(mutex)(&data->lock);
ret = zopt2201_enable_mode(data, reg == ZOPT2201_UVB_DATA);
if (ret < 0)
- goto fail;
+ return ret;
while (tries--) {
unsigned long t = zopt2201_resolution[data->res].us;
@@ -200,30 +200,25 @@ static int zopt2201_read(struct zopt2201_data *data, u8 reg)
msleep(t / 1000);
ret = i2c_smbus_read_byte_data(client, ZOPT2201_MAIN_STATUS);
if (ret < 0)
- goto fail;
+ return ret;
if (ret & ZOPT2201_MAIN_STATUS_DRDY)
break;
}
if (tries < 0) {
ret = -ETIMEDOUT;
- goto fail;
+ return ret;
}
ret = i2c_smbus_read_i2c_block_data(client, reg, sizeof(buf), buf);
if (ret < 0)
- goto fail;
+ return ret;
ret = i2c_smbus_write_byte_data(client, ZOPT2201_MAIN_CTRL, 0x00);
if (ret < 0)
- goto fail;
- mutex_unlock(&data->lock);
+ return ret;
return get_unaligned_le24(&buf[0]);
-
-fail:
- mutex_unlock(&data->lock);
- return ret;
}
static const struct iio_chan_spec zopt2201_channels[] = {
@@ -317,17 +312,15 @@ static int zopt2201_set_resolution(struct zopt2201_data *data, u8 res)
static int zopt2201_write_resolution(struct zopt2201_data *data,
int val, int val2)
{
- int i, ret;
+ int i;
if (val != 0)
return -EINVAL;
for (i = 0; i < ARRAY_SIZE(zopt2201_resolution); i++)
if (val2 == zopt2201_resolution[i].us) {
- mutex_lock(&data->lock);
- ret = zopt2201_set_resolution(data, i);
- mutex_unlock(&data->lock);
- return ret;
+ guard(mutex)(&data->lock);
+ return zopt2201_set_resolution(data, i);
}
return -EINVAL;
@@ -351,16 +344,12 @@ static int zopt2201_write_scale_by_idx(struct zopt2201_data *data, int idx,
{
int ret;
- mutex_lock(&data->lock);
+ guard(mutex)(&data->lock);
ret = zopt2201_set_resolution(data, zopt2201_scale_array[idx].res);
if (ret < 0)
- goto unlock;
-
- ret = zopt2201_set_gain(data, zopt2201_scale_array[idx].gain);
+ return ret;
-unlock:
- mutex_unlock(&data->lock);
- return ret;
+ return zopt2201_set_gain(data, zopt2201_scale_array[idx].gain);
}
static int zopt2201_write_scale_als(struct zopt2201_data *data,
diff --git a/drivers/iio/magnetometer/ak8974.c b/drivers/iio/magnetometer/ak8974.c
index 68ece700c7ce..817b18257608 100644
--- a/drivers/iio/magnetometer/ak8974.c
+++ b/drivers/iio/magnetometer/ak8974.c
@@ -577,7 +577,7 @@ static int ak8974_measure_channel(struct ak8974 *ak8974, unsigned long address,
/*
* This explicit cast to (s16) is necessary as the measurement
* is done in 2's complement with positive and negative values.
- * The follwing assignment to *val will then convert the signed
+ * The following assignment to *val will then convert the signed
* s16 value to a signed int value.
*/
*val = (s16)le16_to_cpu(hw_values[address]);
diff --git a/drivers/iio/magnetometer/ak8975.c b/drivers/iio/magnetometer/ak8975.c
index d30315ad85de..b648b0afa573 100644
--- a/drivers/iio/magnetometer/ak8975.c
+++ b/drivers/iio/magnetometer/ak8975.c
@@ -545,7 +545,7 @@ static int ak8975_set_mode(struct ak8975_data *data, enum ak_ctrl_mode mode)
return ret;
}
data->cntl_cache = regval;
- /* After mode change wait atleast 100us */
+ /* After mode change wait at least 100us */
usleep_range(100, 500);
return 0;
@@ -697,7 +697,7 @@ static int wait_conversion_complete_polled(struct ak8975_data *data)
return read_status;
}
-/* Returns 0 if the end of conversion interrupt occured or -ETIME otherwise */
+/* Returns 0 if the end of conversion interrupt occurred or -ETIME otherwise */
static int wait_conversion_complete_interrupt(struct ak8975_data *data)
{
int ret;
@@ -759,7 +759,7 @@ static int ak8975_read_axis(struct iio_dev *indio_dev, int index, int *val)
if (ret < 0)
goto exit;
- /* Read out ST2 for release lock on measurment data. */
+ /* Read out ST2 for release lock on measurement data. */
ret = i2c_smbus_read_byte_data(client, data->def->ctrl_regs[ST2]);
if (ret < 0) {
dev_err(&client->dev, "Error in reading ST2\n");
diff --git a/drivers/iio/magnetometer/bmc150_magn.c b/drivers/iio/magnetometer/bmc150_magn.c
index a022e1805dff..bf2551988008 100644
--- a/drivers/iio/magnetometer/bmc150_magn.c
+++ b/drivers/iio/magnetometer/bmc150_magn.c
@@ -12,6 +12,7 @@
#include <linux/module.h>
#include <linux/i2c.h>
#include <linux/interrupt.h>
+#include <linux/cleanup.h>
#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/pm.h>
@@ -148,14 +149,16 @@ struct bmc150_magn_data {
static const struct {
int freq;
u8 reg_val;
-} bmc150_magn_samp_freq_table[] = { {2, 0x01},
- {6, 0x02},
- {8, 0x03},
- {10, 0x00},
- {15, 0x04},
- {20, 0x05},
- {25, 0x06},
- {30, 0x07} };
+} bmc150_magn_samp_freq_table[] = {
+ { 2, 0x01 },
+ { 6, 0x02 },
+ { 8, 0x03 },
+ { 10, 0x00 },
+ { 15, 0x04 },
+ { 20, 0x05 },
+ { 25, 0x06 },
+ { 30, 0x07 },
+};
enum bmc150_magn_presets {
LOW_POWER_PRESET,
@@ -169,10 +172,10 @@ static const struct bmc150_magn_preset {
u8 rep_z;
u8 odr;
} bmc150_magn_presets_table[] = {
- [LOW_POWER_PRESET] = {3, 3, 10},
- [REGULAR_PRESET] = {9, 15, 10},
- [ENHANCED_REGULAR_PRESET] = {15, 27, 10},
- [HIGH_ACCURACY_PRESET] = {47, 83, 20},
+ [LOW_POWER_PRESET] = { 3, 3, 10 },
+ [REGULAR_PRESET] = { 9, 15, 10 },
+ [ENHANCED_REGULAR_PRESET] = { 15, 27, 10 },
+ [HIGH_ACCURACY_PRESET] = { 47, 83, 20 },
};
#define BMC150_MAGN_DEFAULT_PRESET REGULAR_PRESET
@@ -255,6 +258,13 @@ static int bmc150_magn_set_power_mode(struct bmc150_magn_data *data,
return -EINVAL;
}
+static int bmc150_magn_set_power_mode_locked(struct bmc150_magn_data *data,
+ enum bmc150_magn_power_modes mode)
+{
+ guard(mutex)(&data->mutex);
+ return bmc150_magn_set_power_mode(data, mode, true);
+}
+
static int bmc150_magn_set_power_state(struct bmc150_magn_data *data, bool on)
{
int ret = 0;
@@ -453,33 +463,29 @@ static int bmc150_magn_read_raw(struct iio_dev *indio_dev,
s32 values[AXIS_XYZ_MAX];
switch (mask) {
- case IIO_CHAN_INFO_RAW:
+ case IIO_CHAN_INFO_RAW: {
if (iio_buffer_enabled(indio_dev))
return -EBUSY;
- mutex_lock(&data->mutex);
+
+ guard(mutex)(&data->mutex);
ret = bmc150_magn_set_power_state(data, true);
- if (ret < 0) {
- mutex_unlock(&data->mutex);
+ if (ret < 0)
return ret;
- }
ret = bmc150_magn_read_xyz(data, values);
if (ret < 0) {
bmc150_magn_set_power_state(data, false);
- mutex_unlock(&data->mutex);
return ret;
}
*val = values[chan->scan_index];
ret = bmc150_magn_set_power_state(data, false);
- if (ret < 0) {
- mutex_unlock(&data->mutex);
+ if (ret < 0)
return ret;
- }
- mutex_unlock(&data->mutex);
return IIO_VAL_INT;
+ }
case IIO_CHAN_INFO_SCALE:
/*
* The API/driver performs an off-chip temperature
@@ -527,48 +533,39 @@ static int bmc150_magn_write_raw(struct iio_dev *indio_dev,
int ret;
switch (mask) {
- case IIO_CHAN_INFO_SAMP_FREQ:
+ case IIO_CHAN_INFO_SAMP_FREQ: {
if (val > data->max_odr)
return -EINVAL;
- mutex_lock(&data->mutex);
- ret = bmc150_magn_set_odr(data, val);
- mutex_unlock(&data->mutex);
- return ret;
+ guard(mutex)(&data->mutex);
+ return bmc150_magn_set_odr(data, val);
+ }
case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
switch (chan->channel2) {
case IIO_MOD_X:
- case IIO_MOD_Y:
+ case IIO_MOD_Y: {
if (val < 1 || val > 511)
return -EINVAL;
- mutex_lock(&data->mutex);
+ guard(mutex)(&data->mutex);
ret = bmc150_magn_set_max_odr(data, val, 0, 0);
- if (ret < 0) {
- mutex_unlock(&data->mutex);
+ if (ret < 0)
return ret;
- }
- ret = regmap_update_bits(data->regmap,
+ return regmap_update_bits(data->regmap,
BMC150_MAGN_REG_REP_XY,
BMC150_MAGN_REG_REP_DATAMASK,
- BMC150_MAGN_REPXY_TO_REGVAL
- (val));
- mutex_unlock(&data->mutex);
- return ret;
- case IIO_MOD_Z:
+ BMC150_MAGN_REPXY_TO_REGVAL(val));
+ }
+ case IIO_MOD_Z: {
if (val < 1 || val > 256)
return -EINVAL;
- mutex_lock(&data->mutex);
+ guard(mutex)(&data->mutex);
ret = bmc150_magn_set_max_odr(data, 0, val, 0);
- if (ret < 0) {
- mutex_unlock(&data->mutex);
+ if (ret < 0)
return ret;
- }
- ret = regmap_update_bits(data->regmap,
+ return regmap_update_bits(data->regmap,
BMC150_MAGN_REG_REP_Z,
BMC150_MAGN_REG_REP_DATAMASK,
- BMC150_MAGN_REPZ_TO_REGVAL
- (val));
- mutex_unlock(&data->mutex);
- return ret;
+ BMC150_MAGN_REPZ_TO_REGVAL(val));
+ }
default:
return -EINVAL;
}
@@ -655,8 +652,9 @@ static const struct iio_info bmc150_magn_info = {
};
static const unsigned long bmc150_magn_scan_masks[] = {
- BIT(AXIS_X) | BIT(AXIS_Y) | BIT(AXIS_Z),
- 0};
+ BIT(AXIS_X) | BIT(AXIS_Y) | BIT(AXIS_Z),
+ 0
+};
static irqreturn_t bmc150_magn_trigger_handler(int irq, void *p)
{
@@ -695,7 +693,7 @@ static int bmc150_magn_init(struct bmc150_magn_data *data)
* 3ms power-on time according to datasheet, let's better
* be safe than sorry and set this delay to 5ms.
*/
- msleep(5);
+ fsleep(5 * USEC_PER_MSEC);
ret = bmc150_magn_set_power_mode(data, BMC150_MAGN_POWER_MODE_SUSPEND,
false);
@@ -782,9 +780,8 @@ static void bmc150_magn_trig_reen(struct iio_trigger *trig)
if (!data->dready_trigger_on)
return;
- mutex_lock(&data->mutex);
+ guard(mutex)(&data->mutex);
ret = bmc150_magn_reset_intr(data);
- mutex_unlock(&data->mutex);
if (ret)
dev_err(data->dev, "Failed to reset interrupt\n");
}
@@ -794,32 +791,28 @@ static int bmc150_magn_data_rdy_trigger_set_state(struct iio_trigger *trig,
{
struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig);
struct bmc150_magn_data *data = iio_priv(indio_dev);
- int ret = 0;
+ int ret;
+
+ guard(mutex)(&data->mutex);
- mutex_lock(&data->mutex);
if (state == data->dready_trigger_on)
- goto err_unlock;
+ return 0;
ret = regmap_update_bits(data->regmap, BMC150_MAGN_REG_INT_DRDY,
BMC150_MAGN_MASK_DRDY_EN,
state << BMC150_MAGN_SHIFT_DRDY_EN);
if (ret < 0)
- goto err_unlock;
+ return ret;
data->dready_trigger_on = state;
if (state) {
ret = bmc150_magn_reset_intr(data);
if (ret < 0)
- goto err_unlock;
+ return ret;
}
- mutex_unlock(&data->mutex);
return 0;
-
-err_unlock:
- mutex_unlock(&data->mutex);
- return ret;
}
static const struct iio_trigger_ops bmc150_magn_trigger_ops = {
@@ -977,9 +970,7 @@ void bmc150_magn_remove(struct device *dev)
if (data->dready_trig)
iio_trigger_unregister(data->dready_trig);
- mutex_lock(&data->mutex);
- bmc150_magn_set_power_mode(data, BMC150_MAGN_POWER_MODE_SUSPEND, true);
- mutex_unlock(&data->mutex);
+ bmc150_magn_set_power_mode_locked(data, BMC150_MAGN_POWER_MODE_SUSPEND);
regulator_bulk_disable(ARRAY_SIZE(data->regulators), data->regulators);
}
@@ -992,10 +983,8 @@ static int bmc150_magn_runtime_suspend(struct device *dev)
struct bmc150_magn_data *data = iio_priv(indio_dev);
int ret;
- mutex_lock(&data->mutex);
- ret = bmc150_magn_set_power_mode(data, BMC150_MAGN_POWER_MODE_SLEEP,
- true);
- mutex_unlock(&data->mutex);
+ ret = bmc150_magn_set_power_mode_locked(data,
+ BMC150_MAGN_POWER_MODE_SLEEP);
if (ret < 0) {
dev_err(dev, "powering off device failed\n");
return ret;
@@ -1021,28 +1010,18 @@ static int bmc150_magn_suspend(struct device *dev)
{
struct iio_dev *indio_dev = dev_get_drvdata(dev);
struct bmc150_magn_data *data = iio_priv(indio_dev);
- int ret;
- mutex_lock(&data->mutex);
- ret = bmc150_magn_set_power_mode(data, BMC150_MAGN_POWER_MODE_SLEEP,
- true);
- mutex_unlock(&data->mutex);
-
- return ret;
+ return bmc150_magn_set_power_mode_locked(data,
+ BMC150_MAGN_POWER_MODE_SLEEP);
}
static int bmc150_magn_resume(struct device *dev)
{
struct iio_dev *indio_dev = dev_get_drvdata(dev);
struct bmc150_magn_data *data = iio_priv(indio_dev);
- int ret;
- mutex_lock(&data->mutex);
- ret = bmc150_magn_set_power_mode(data, BMC150_MAGN_POWER_MODE_NORMAL,
- true);
- mutex_unlock(&data->mutex);
-
- return ret;
+ return bmc150_magn_set_power_mode_locked(data,
+ BMC150_MAGN_POWER_MODE_NORMAL);
}
#endif
diff --git a/drivers/iio/magnetometer/si7210.c b/drivers/iio/magnetometer/si7210.c
index 27e3feba7a0f..2a36abd1c99d 100644
--- a/drivers/iio/magnetometer/si7210.c
+++ b/drivers/iio/magnetometer/si7210.c
@@ -128,8 +128,8 @@ static const struct regmap_config si7210_regmap_conf = {
struct si7210_data {
struct regmap *regmap;
struct i2c_client *client;
- struct regulator *vdd;
struct mutex fetch_lock; /* lock for a single measurement fetch */
+ unsigned int vdd_uV;
s8 temp_offset;
s8 temp_gain;
s8 scale_20_a[A_REGS_COUNT];
@@ -221,12 +221,8 @@ static int si7210_read_raw(struct iio_dev *indio_dev,
temp *= (1 + (data->temp_gain / 2048));
temp += (int)(MICRO / 16) * data->temp_offset;
- ret = regulator_get_voltage(data->vdd);
- if (ret < 0)
- return ret;
-
/* temp -= 0.222 * VDD */
- temp -= 222 * div_s64(ret, MILLI);
+ temp -= 222 * (data->vdd_uV / MILLI);
*val = div_s64(temp, MILLI);
@@ -396,14 +392,11 @@ static int si7210_probe(struct i2c_client *client)
return dev_err_probe(&client->dev, PTR_ERR(data->regmap),
"failed to register regmap\n");
- data->vdd = devm_regulator_get(&client->dev, "vdd");
- if (IS_ERR(data->vdd))
- return dev_err_probe(&client->dev, PTR_ERR(data->vdd),
- "failed to get VDD regulator\n");
-
- ret = regulator_enable(data->vdd);
- if (ret)
- return ret;
+ ret = devm_regulator_get_enable_read_voltage(&client->dev, "vdd");
+ if (ret < 0)
+ return dev_err_probe(&client->dev, ret,
+ "Failed to get vdd regulator\n");
+ data->vdd_uV = ret;
indio_dev->name = dev_name(&client->dev);
indio_dev->modes = INDIO_DIRECT_MODE;
diff --git a/drivers/iio/magnetometer/yamaha-yas530.c b/drivers/iio/magnetometer/yamaha-yas530.c
index d49e37edcbed..140c422773f6 100644
--- a/drivers/iio/magnetometer/yamaha-yas530.c
+++ b/drivers/iio/magnetometer/yamaha-yas530.c
@@ -1223,7 +1223,7 @@ static int yas530_measure_offsets(struct yas5xx *yas5xx)
* as the values for [x, y1, y2]. The value is +/-31
* but the effect on the raw values is much larger.
* The effect of the offset is to bring the measure
- * rougly to the center.
+ * roughly to the center.
*/
ox = 0;
oy1 = 0;
diff --git a/drivers/iio/pressure/bmp280-spi.c b/drivers/iio/pressure/bmp280-spi.c
index 3b90384f17d7..04bf2f5be5b1 100644
--- a/drivers/iio/pressure/bmp280-spi.c
+++ b/drivers/iio/pressure/bmp280-spi.c
@@ -47,7 +47,7 @@ static int bmp380_regmap_spi_read(void *context, const void *reg,
return -EINVAL;
/*
- * According to the BMP3xx datasheets, for a basic SPI read opertion,
+ * According to the BMP3xx datasheets, for a basic SPI read operation,
* the first byte needs to be dropped and the rest are the requested
* data.
*/
diff --git a/drivers/iio/pressure/hsc030pa.c b/drivers/iio/pressure/hsc030pa.c
index 2d00c0656259..d6b18a84f0ab 100644
--- a/drivers/iio/pressure/hsc030pa.c
+++ b/drivers/iio/pressure/hsc030pa.c
@@ -273,7 +273,7 @@ static const struct hsc_range_config hsc_range_config[HSC_VARIANTS_MAX] = {
* @data: structure containing instantiated sensor data
* Return: true only if both status bits are zero
*
- * the two MSB from the first transfered byte contain a status code
+ * The two MSB from the first transferred byte contain a status code
* 00 - normal operation, valid data
* 01 - device in factory programming mode
* 10 - stale data
diff --git a/drivers/iio/pressure/hsc030pa_i2c.c b/drivers/iio/pressure/hsc030pa_i2c.c
index a34ef4653f34..3500bda03d75 100644
--- a/drivers/iio/pressure/hsc030pa_i2c.c
+++ b/drivers/iio/pressure/hsc030pa_i2c.c
@@ -34,8 +34,13 @@ static int hsc_i2c_recv(struct hsc_data *data)
msg.buf = data->buffer;
ret = i2c_transfer(client->adapter, &msg, 1);
+ if (ret < 0)
+ return ret;
- return (ret == 2) ? 0 : ret;
+ if (ret != 1)
+ return -EIO;
+
+ return 0;
}
static int hsc_i2c_probe(struct i2c_client *client)
diff --git a/drivers/iio/pressure/rohm-bm1390.c b/drivers/iio/pressure/rohm-bm1390.c
index dac27fd359ad..08146ca0f91d 100644
--- a/drivers/iio/pressure/rohm-bm1390.c
+++ b/drivers/iio/pressure/rohm-bm1390.c
@@ -440,7 +440,7 @@ static int bm1390_fifo_flush(struct iio_dev *idev, unsigned int samples)
* the timestamps. If we are ran from IRQ, then the
* IRQF_ONESHOT has us covered - but if we are ran by the
* user-space read we need to disable the IRQ to be on a safe
- * side. We do this usng synchronous disable so that if the
+ * side. We do this using synchronous disable so that if the
* IRQ thread is being ran on other CPU we wait for it to be
* finished.
*/
diff --git a/drivers/iio/pressure/zpa2326.c b/drivers/iio/pressure/zpa2326.c
index 4923a558a26a..2c68fdf2744e 100644
--- a/drivers/iio/pressure/zpa2326.c
+++ b/drivers/iio/pressure/zpa2326.c
@@ -840,7 +840,7 @@ static irqreturn_t zpa2326_handle_threaded_irq(int irq, void *data)
complete:
/*
- * Wake up direct or externaly triggered buffer mode waiters: see
+ * Wake up direct or externally triggered buffer mode waiters: see
* zpa2326_sample_oneshot() and zpa2326_trigger_handler().
*/
complete(&priv->data_ready);
diff --git a/drivers/iio/proximity/Kconfig b/drivers/iio/proximity/Kconfig
index 6070974c2c85..bb77fad2a1b3 100644
--- a/drivers/iio/proximity/Kconfig
+++ b/drivers/iio/proximity/Kconfig
@@ -244,6 +244,21 @@ config VL53L0X_I2C
To compile this driver as a module, choose M here: the
module will be called vl53l0x-i2c.
+config VL53L1X_I2C
+ tristate "STMicroelectronics VL53L1X ToF ranger sensor (I2C)"
+ depends on I2C
+ select IIO_BUFFER
+ select IIO_TRIGGERED_BUFFER
+ select REGMAP_I2C
+ select RESET_CONTROLLER
+ help
+ Say Y here to build a driver for STMicroelectronics VL53L1X
+ ToF ranger sensors with i2c interface.
+ This driver can be used to measure the distance of objects.
+
+ To compile this driver as a module, choose M here: the
+ module will be called vl53l1x-i2c.
+
config AW96103
tristate "AW96103/AW96105 Awinic proximity sensor"
select REGMAP_I2C
diff --git a/drivers/iio/proximity/Makefile b/drivers/iio/proximity/Makefile
index 152034d38c49..4352833dd8a4 100644
--- a/drivers/iio/proximity/Makefile
+++ b/drivers/iio/proximity/Makefile
@@ -23,5 +23,6 @@ obj-$(CONFIG_SX_COMMON) += sx_common.o
obj-$(CONFIG_SX9500) += sx9500.o
obj-$(CONFIG_VCNL3020) += vcnl3020.o
obj-$(CONFIG_VL53L0X_I2C) += vl53l0x-i2c.o
+obj-$(CONFIG_VL53L1X_I2C) += vl53l1x-i2c.o
obj-$(CONFIG_AW96103) += aw96103.o
diff --git a/drivers/iio/proximity/hx9023s.c b/drivers/iio/proximity/hx9023s.c
index 17e00ee2b6f8..9efaa5b6b5bd 100644
--- a/drivers/iio/proximity/hx9023s.c
+++ b/drivers/iio/proximity/hx9023s.c
@@ -1088,6 +1088,7 @@ static int hx9023s_probe(struct i2c_client *client)
struct device *dev = &client->dev;
struct iio_dev *indio_dev;
struct hx9023s_data *data;
+ const char *fw_name;
int ret;
indio_dev = devm_iio_device_alloc(dev, sizeof(*data));
@@ -1125,7 +1126,9 @@ static int hx9023s_probe(struct i2c_client *client)
if (ret)
return dev_err_probe(dev, ret, "channel config failed\n");
- ret = request_firmware_nowait(THIS_MODULE, true, "hx9023s.bin", dev,
+ fw_name = "hx9023s.bin";
+ device_property_read_string(dev, "firmware-name", &fw_name);
+ ret = request_firmware_nowait(THIS_MODULE, true, fw_name, dev,
GFP_KERNEL, data, hx9023s_cfg_update);
if (ret)
return dev_err_probe(dev, ret, "reg config failed\n");
diff --git a/drivers/iio/proximity/sx9324.c b/drivers/iio/proximity/sx9324.c
index c7b2d03c23bc..f61eff39751d 100644
--- a/drivers/iio/proximity/sx9324.c
+++ b/drivers/iio/proximity/sx9324.c
@@ -821,7 +821,7 @@ static const struct sx_common_reg_default sx9324_default_regs[] = {
{ SX9324_REG_ADV_CTRL10, 0x00, "adv_ctrl10" },
{ SX9324_REG_ADV_CTRL11, 0x00, "adv_ctrl11" },
{ SX9324_REG_ADV_CTRL12, 0x00, "adv_ctrl12" },
- /* TODO(gwendal): SAR currenly disabled */
+ /* TODO(gwendal): SAR currently disabled */
{ SX9324_REG_ADV_CTRL13, 0x00, "adv_ctrl13" },
{ SX9324_REG_ADV_CTRL14, 0x00, "adv_ctrl14" },
{ SX9324_REG_ADV_CTRL15, 0x00, "adv_ctrl15" },
diff --git a/drivers/iio/proximity/vl53l1x-i2c.c b/drivers/iio/proximity/vl53l1x-i2c.c
new file mode 100644
index 000000000000..4d9cb3983dba
--- /dev/null
+++ b/drivers/iio/proximity/vl53l1x-i2c.c
@@ -0,0 +1,756 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
+/*
+ * Support for ST VL53L1X FlightSense ToF Ranging Sensor on a i2c bus.
+ *
+ * Copyright (C) 2026 Siratul Islam <email@sirat.me>
+ *
+ * Datasheet available at
+ * <https://www.st.com/resource/en/datasheet/vl53l1x.pdf>
+ *
+ * Default 7-bit i2c slave address 0x29.
+ *
+ * The VL53L1X requires a firmware configuration blob to be loaded at boot.
+ * Register values for the default configuration are taken from
+ * ST's VL53L1X Ultra Lite Driver (STSW-IMG009).
+ */
+
+#include <linux/array_size.h>
+#include <linux/bits.h>
+#include <linux/bitfield.h>
+#include <linux/completion.h>
+#include <linux/delay.h>
+#include <linux/dev_printk.h>
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/math.h>
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
+#include <linux/regmap.h>
+#include <linux/regulator/consumer.h>
+#include <linux/reset.h>
+#include <linux/time.h>
+#include <linux/types.h>
+
+#include <asm/byteorder.h>
+
+#include <linux/iio/buffer.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/trigger.h>
+#include <linux/iio/trigger_consumer.h>
+#include <linux/iio/triggered_buffer.h>
+
+#define VL53L1X_REG_SOFT_RESET 0x0000
+#define VL53L1X_REG_VHV_CONFIG__TIMEOUT_MACROP_LOOP_BOUND 0x0008
+#define VL53L1X_REG_VHV_CONFIG__INIT 0x000B
+#define VL53L1X_REG_GPIO_HV_MUX__CTRL 0x0030
+#define VL53L1X_REG_GPIO__TIO_HV_STATUS 0x0031
+#define VL53L1X_REG_SYSTEM__INTERRUPT_CONFIG_GPIO 0x0046
+#define VL53L1X_REG_PHASECAL_CONFIG__TIMEOUT_MACROP 0x004B
+#define VL53L1X_REG_RANGE_CONFIG__TIMEOUT_MACROP_A 0x005E
+#define VL53L1X_REG_RANGE_CONFIG__VCSEL_PERIOD_A 0x0060
+#define VL53L1X_REG_RANGE_CONFIG__TIMEOUT_MACROP_B 0x0061
+#define VL53L1X_REG_RANGE_CONFIG__VCSEL_PERIOD_B 0x0063
+#define VL53L1X_REG_RANGE_CONFIG__VALID_PHASE_HIGH 0x0069
+#define VL53L1X_REG_SYSTEM__INTERMEASUREMENT_PERIOD 0x006C
+#define VL53L1X_REG_SD_CONFIG__WOI_SD0 0x0078
+#define VL53L1X_REG_SD_CONFIG__WOI_SD1 0x0079
+#define VL53L1X_REG_SD_CONFIG__INITIAL_PHASE_SD0 0x007A
+#define VL53L1X_REG_SD_CONFIG__INITIAL_PHASE_SD1 0x007B
+#define VL53L1X_REG_SYSTEM__INTERRUPT_CLEAR 0x0086
+#define VL53L1X_REG_SYSTEM__MODE_START 0x0087
+#define VL53L1X_REG_RESULT__RANGE_STATUS 0x0089
+#define VL53L1X_REG_RESULT__FINAL_CROSSTALK_CORRECTED_RANGE_MM_SD0 0x0096
+#define VL53L1X_REG_RESULT__OSC_CALIBRATE_VAL 0x00DE
+#define VL53L1X_REG_FIRMWARE__SYSTEM_STATUS 0x00E5
+#define VL53L1X_REG_IDENTIFICATION__MODEL_ID 0x010F
+#define VL53L1X_REG_DEFAULT_CONFIG 0x002D
+
+#define VL53L1X_MODEL_ID_VAL 0xEACC
+
+#define VL53L1X_MODE_START_TIMED 0x40
+#define VL53L1X_MODE_START_STOP 0x00
+
+#define VL53L1X_INT_NEW_SAMPLE_READY 0x02
+
+#define VL53L1X_GPIO_HV_MUX_POLARITY BIT(4)
+
+#define VL53L1X_VHV_LOOP_BOUND_TWO 0x09
+
+#define VL53L1X_RANGE_STATUS_MASK GENMASK(4, 0)
+#define VL53L1X_RANGE_STATUS_VALID 9
+
+#define VL53L1X_OSC_CALIBRATE_MASK GENMASK(9, 0)
+
+/* Inter-measurement period uses PLL divider with 1.075 oscillator correction */
+static const struct u32_fract vl53l1x_osc_correction = {
+ .numerator = 1075,
+ .denominator = 1000,
+};
+
+enum vl53l1x_distance_mode {
+ VL53L1X_SHORT,
+ VL53L1X_LONG,
+};
+
+struct vl53l1x_data {
+ struct regmap *regmap;
+ struct completion completion;
+ struct reset_control *xshut_reset;
+ enum vl53l1x_distance_mode distance_mode;
+ u8 gpio_polarity;
+ int irq;
+};
+
+static const struct regmap_range vl53l1x_volatile_ranges[] = {
+ regmap_reg_range(VL53L1X_REG_GPIO__TIO_HV_STATUS,
+ VL53L1X_REG_GPIO__TIO_HV_STATUS),
+ regmap_reg_range(VL53L1X_REG_RESULT__RANGE_STATUS,
+ VL53L1X_REG_RESULT__RANGE_STATUS),
+ regmap_reg_range(VL53L1X_REG_RESULT__FINAL_CROSSTALK_CORRECTED_RANGE_MM_SD0,
+ VL53L1X_REG_RESULT__FINAL_CROSSTALK_CORRECTED_RANGE_MM_SD0 + 1),
+ regmap_reg_range(VL53L1X_REG_RESULT__OSC_CALIBRATE_VAL,
+ VL53L1X_REG_RESULT__OSC_CALIBRATE_VAL + 1),
+ regmap_reg_range(VL53L1X_REG_FIRMWARE__SYSTEM_STATUS,
+ VL53L1X_REG_FIRMWARE__SYSTEM_STATUS),
+};
+
+static const struct regmap_access_table vl53l1x_volatile_table = {
+ .yes_ranges = vl53l1x_volatile_ranges,
+ .n_yes_ranges = ARRAY_SIZE(vl53l1x_volatile_ranges),
+};
+
+static const struct regmap_range vl53l1x_write_only_ranges[] = {
+ regmap_reg_range(VL53L1X_REG_SOFT_RESET, VL53L1X_REG_SOFT_RESET),
+ regmap_reg_range(VL53L1X_REG_SYSTEM__INTERRUPT_CLEAR,
+ VL53L1X_REG_SYSTEM__MODE_START),
+};
+
+static const struct regmap_access_table vl53l1x_readable_table = {
+ .no_ranges = vl53l1x_write_only_ranges,
+ .n_no_ranges = ARRAY_SIZE(vl53l1x_write_only_ranges),
+};
+
+static const struct regmap_config vl53l1x_regmap_config = {
+ .reg_bits = 16,
+ .val_bits = 8,
+ /* MODEL_ID is 16-bit. +1 covers the second byte at 0x0110 */
+ .max_register = VL53L1X_REG_IDENTIFICATION__MODEL_ID + 1,
+ .cache_type = REGCACHE_MAPLE,
+ .volatile_table = &vl53l1x_volatile_table,
+ .rd_table = &vl53l1x_readable_table,
+};
+
+static int vl53l1x_read_u16(struct vl53l1x_data *data, u16 reg, u16 *val)
+{
+ __be16 buf;
+ int ret;
+
+ ret = regmap_bulk_read(data->regmap, reg, &buf, sizeof(buf));
+ if (ret)
+ return ret;
+
+ *val = be16_to_cpu(buf);
+ return 0;
+}
+
+static int vl53l1x_write_u16(struct vl53l1x_data *data, u16 reg, u16 val)
+{
+ __be16 buf = cpu_to_be16(val);
+
+ return regmap_bulk_write(data->regmap, reg, &buf, sizeof(buf));
+}
+
+static int vl53l1x_write_u32(struct vl53l1x_data *data, u16 reg, u32 val)
+{
+ __be32 buf = cpu_to_be32(val);
+
+ return regmap_bulk_write(data->regmap, reg, &buf, sizeof(buf));
+}
+
+static int vl53l1x_clear_irq(struct vl53l1x_data *data)
+{
+ return regmap_write(data->regmap, VL53L1X_REG_SYSTEM__INTERRUPT_CLEAR, 0x01);
+}
+
+static int vl53l1x_start_ranging(struct vl53l1x_data *data)
+{
+ int ret;
+
+ ret = vl53l1x_clear_irq(data);
+ if (ret)
+ return ret;
+
+ return regmap_write(data->regmap, VL53L1X_REG_SYSTEM__MODE_START,
+ VL53L1X_MODE_START_TIMED);
+}
+
+static int vl53l1x_stop_ranging(struct vl53l1x_data *data)
+{
+ return regmap_write(data->regmap, VL53L1X_REG_SYSTEM__MODE_START,
+ VL53L1X_MODE_START_STOP);
+}
+
+/*
+ * Default configuration blob from ST's VL53L1X Ultra Lite Driver
+ * (STSW-IMG009).
+ */
+static const u8 vl53l1x_default_config[] = {
+ 0x00, 0x00, 0x00, 0x01, 0x02, 0x00, 0x02, 0x08, /* reg 0x2d..0x34 */
+ 0x00, 0x08, 0x10, 0x01, 0x01, 0x00, 0x00, 0x00, /* reg 0x35..0x3c */
+ 0x00, 0xFF, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x00, /* reg 0x3d..0x44 */
+ 0x00, 0x20, 0x0B, 0x00, 0x00, 0x02, 0x0A, 0x21, /* reg 0x45..0x4c */
+ 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0xC8, /* reg 0x4d..0x54 */
+ 0x00, 0x00, 0x38, 0xFF, 0x01, 0x00, 0x08, 0x00, /* reg 0x55..0x5c */
+ 0x00, 0x01, 0xCC, 0x0F, 0x01, 0xF1, 0x0D, 0x01, /* reg 0x5d..0x64 */
+ 0x68, 0x00, 0x80, 0x08, 0xB8, 0x00, 0x00, 0x00, /* reg 0x65..0x6c */
+ 0x00, 0x0F, 0x89, 0x00, 0x00, 0x00, 0x00, 0x00, /* reg 0x6d..0x74 */
+ 0x00, 0x00, 0x01, 0x0F, 0x0D, 0x0E, 0x0E, 0x00, /* reg 0x75..0x7c */
+ 0x00, 0x02, 0xC7, 0xFF, 0x9B, 0x00, 0x00, 0x00, /* reg 0x7d..0x84 */
+ 0x01, 0x00, 0x00, /* reg 0x85..0x87 */
+};
+
+static int vl53l1x_chip_init(struct vl53l1x_data *data)
+{
+ struct device *dev = regmap_get_device(data->regmap);
+ unsigned int val;
+ u16 model_id;
+ int ret;
+
+ if (!data->xshut_reset) {
+ ret = regmap_write(data->regmap, VL53L1X_REG_SOFT_RESET, 0x00);
+ if (ret)
+ return ret;
+ fsleep(100); /* conservative reset pulse, no spec */
+
+ ret = regmap_write(data->regmap, VL53L1X_REG_SOFT_RESET, 0x01);
+ if (ret)
+ return ret;
+ fsleep(1000); /* conservative boot wait, no spec */
+ }
+
+ ret = regmap_read_poll_timeout(data->regmap,
+ VL53L1X_REG_FIRMWARE__SYSTEM_STATUS, val,
+ val & BIT(0),
+ 1 * USEC_PER_MSEC,
+ 100 * USEC_PER_MSEC);
+ if (ret)
+ return dev_err_probe(dev, ret, "firmware boot timeout\n");
+
+ ret = vl53l1x_read_u16(data, VL53L1X_REG_IDENTIFICATION__MODEL_ID,
+ &model_id);
+ if (ret)
+ return ret;
+
+ if (model_id != VL53L1X_MODEL_ID_VAL)
+ dev_info(dev, "unknown model id: 0x%04x, continuing\n", model_id);
+
+ ret = regmap_bulk_write(data->regmap, VL53L1X_REG_DEFAULT_CONFIG,
+ vl53l1x_default_config,
+ sizeof(vl53l1x_default_config));
+ if (ret)
+ return ret;
+
+ ret = regmap_read(data->regmap, VL53L1X_REG_GPIO_HV_MUX__CTRL, &val);
+ if (ret)
+ return ret;
+ data->gpio_polarity = !!(val & VL53L1X_GPIO_HV_MUX_POLARITY);
+
+ /* Initial ranging cycle for VHV calibration */
+ ret = vl53l1x_start_ranging(data);
+ if (ret)
+ return ret;
+
+ /* 1ms poll, 1s timeout covers max timing budgets (per ST Ultra Lite Driver) */
+ ret = regmap_read_poll_timeout(data->regmap,
+ VL53L1X_REG_GPIO__TIO_HV_STATUS, val,
+ (val & 1) != data->gpio_polarity,
+ 1 * USEC_PER_MSEC,
+ 1000 * USEC_PER_MSEC);
+ if (ret)
+ return ret;
+
+ ret = vl53l1x_clear_irq(data);
+ if (ret)
+ return ret;
+
+ ret = vl53l1x_stop_ranging(data);
+ if (ret)
+ return ret;
+
+ ret = regmap_write(data->regmap,
+ VL53L1X_REG_VHV_CONFIG__TIMEOUT_MACROP_LOOP_BOUND,
+ VL53L1X_VHV_LOOP_BOUND_TWO);
+ if (ret)
+ return ret;
+
+ return regmap_write(data->regmap, VL53L1X_REG_VHV_CONFIG__INIT, 0x00);
+}
+
+static const struct reg_sequence vl53l1x_mode_short[] = {
+ { VL53L1X_REG_PHASECAL_CONFIG__TIMEOUT_MACROP, 0x14 },
+ { VL53L1X_REG_RANGE_CONFIG__VCSEL_PERIOD_A, 0x07 },
+ { VL53L1X_REG_RANGE_CONFIG__VCSEL_PERIOD_B, 0x05 },
+ { VL53L1X_REG_RANGE_CONFIG__VALID_PHASE_HIGH, 0x38 },
+ { VL53L1X_REG_SD_CONFIG__WOI_SD0, 0x07 },
+ { VL53L1X_REG_SD_CONFIG__WOI_SD1, 0x05 },
+ { VL53L1X_REG_SD_CONFIG__INITIAL_PHASE_SD0, 0x06 },
+ { VL53L1X_REG_SD_CONFIG__INITIAL_PHASE_SD1, 0x06 },
+};
+
+static const struct reg_sequence vl53l1x_mode_long[] = {
+ { VL53L1X_REG_PHASECAL_CONFIG__TIMEOUT_MACROP, 0x0A },
+ { VL53L1X_REG_RANGE_CONFIG__VCSEL_PERIOD_A, 0x0F },
+ { VL53L1X_REG_RANGE_CONFIG__VCSEL_PERIOD_B, 0x0D },
+ { VL53L1X_REG_RANGE_CONFIG__VALID_PHASE_HIGH, 0xB8 },
+ { VL53L1X_REG_SD_CONFIG__WOI_SD0, 0x0F },
+ { VL53L1X_REG_SD_CONFIG__WOI_SD1, 0x0D },
+ { VL53L1X_REG_SD_CONFIG__INITIAL_PHASE_SD0, 0x0E },
+ { VL53L1X_REG_SD_CONFIG__INITIAL_PHASE_SD1, 0x0E },
+};
+
+static const struct {
+ const struct reg_sequence *regs;
+ size_t num_regs;
+} vl53l1x_mode_configs[] = {
+ [VL53L1X_SHORT] = { vl53l1x_mode_short, ARRAY_SIZE(vl53l1x_mode_short) },
+ [VL53L1X_LONG] = { vl53l1x_mode_long, ARRAY_SIZE(vl53l1x_mode_long) },
+};
+
+static int vl53l1x_set_distance_mode(struct vl53l1x_data *data,
+ enum vl53l1x_distance_mode mode)
+{
+ int ret;
+
+ if (mode >= ARRAY_SIZE(vl53l1x_mode_configs))
+ return -EINVAL;
+
+ ret = regmap_multi_reg_write(data->regmap,
+ vl53l1x_mode_configs[mode].regs,
+ vl53l1x_mode_configs[mode].num_regs);
+ if (ret)
+ return ret;
+
+ data->distance_mode = mode;
+ return 0;
+}
+
+/*
+ * The timing budget controls how long the sensor spends collecting
+ * a single range measurement. Pre-computed TIMEOUT_MACROP register
+ * values from ST's VL53L1X Ultra Lite Driver.
+ */
+static int vl53l1x_set_timing_budget(struct vl53l1x_data *data, u16 budget_ms)
+{
+ u16 timeout_a, timeout_b;
+ int ret;
+
+ switch (data->distance_mode) {
+ case VL53L1X_SHORT:
+ switch (budget_ms) {
+ case 15:
+ timeout_a = 0x001D;
+ timeout_b = 0x0027;
+ break;
+ case 20:
+ timeout_a = 0x0051;
+ timeout_b = 0x006E;
+ break;
+ case 33:
+ timeout_a = 0x00D6;
+ timeout_b = 0x006E;
+ break;
+ case 50:
+ timeout_a = 0x01AE;
+ timeout_b = 0x01E8;
+ break;
+ case 100:
+ timeout_a = 0x02E1;
+ timeout_b = 0x0388;
+ break;
+ case 200:
+ timeout_a = 0x03E1;
+ timeout_b = 0x0496;
+ break;
+ case 500:
+ timeout_a = 0x0591;
+ timeout_b = 0x05C1;
+ break;
+ default:
+ return -EINVAL;
+ }
+ break;
+ case VL53L1X_LONG:
+ switch (budget_ms) {
+ case 20:
+ timeout_a = 0x001E;
+ timeout_b = 0x0022;
+ break;
+ case 33:
+ timeout_a = 0x0060;
+ timeout_b = 0x006E;
+ break;
+ case 50:
+ timeout_a = 0x00AD;
+ timeout_b = 0x00C6;
+ break;
+ case 100:
+ timeout_a = 0x01CC;
+ timeout_b = 0x01EA;
+ break;
+ case 200:
+ timeout_a = 0x02D9;
+ timeout_b = 0x02F8;
+ break;
+ case 500:
+ timeout_a = 0x048F;
+ timeout_b = 0x04A4;
+ break;
+ default:
+ return -EINVAL;
+ }
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ ret = vl53l1x_write_u16(data, VL53L1X_REG_RANGE_CONFIG__TIMEOUT_MACROP_A,
+ timeout_a);
+ if (ret)
+ return ret;
+
+ return vl53l1x_write_u16(data, VL53L1X_REG_RANGE_CONFIG__TIMEOUT_MACROP_B,
+ timeout_b);
+}
+
+static int vl53l1x_set_inter_measurement_ms(struct vl53l1x_data *data,
+ u16 period_ms)
+{
+ u16 osc_calibrate_val;
+ u16 clock_pll;
+ u32 inter_meas;
+ int ret;
+
+ ret = vl53l1x_read_u16(data, VL53L1X_REG_RESULT__OSC_CALIBRATE_VAL,
+ &osc_calibrate_val);
+ if (ret)
+ return ret;
+
+ clock_pll = osc_calibrate_val & VL53L1X_OSC_CALIBRATE_MASK;
+ inter_meas = (clock_pll * period_ms * vl53l1x_osc_correction.numerator) /
+ vl53l1x_osc_correction.denominator;
+
+ return vl53l1x_write_u32(data,
+ VL53L1X_REG_SYSTEM__INTERMEASUREMENT_PERIOD,
+ inter_meas);
+}
+
+static int vl53l1x_read_proximity(struct vl53l1x_data *data, int *val)
+{
+ unsigned int range_status;
+ u16 distance;
+ int ret;
+
+ if (data->irq) {
+ reinit_completion(&data->completion);
+
+ ret = vl53l1x_clear_irq(data);
+ if (ret)
+ return ret;
+
+ if (!wait_for_completion_timeout(&data->completion, HZ))
+ return -ETIMEDOUT;
+ } else {
+ unsigned int rdy;
+
+ /* 1ms poll, 1s timeout covers max timing budgets (per ST Ultra Lite Driver) */
+ ret = regmap_read_poll_timeout(data->regmap,
+ VL53L1X_REG_GPIO__TIO_HV_STATUS, rdy,
+ (rdy & 1) != data->gpio_polarity,
+ 1 * USEC_PER_MSEC,
+ 1000 * USEC_PER_MSEC);
+ if (ret)
+ return ret;
+ }
+
+ ret = regmap_read(data->regmap, VL53L1X_REG_RESULT__RANGE_STATUS,
+ &range_status);
+ if (ret)
+ goto clear_irq;
+
+ if (FIELD_GET(VL53L1X_RANGE_STATUS_MASK, range_status) !=
+ VL53L1X_RANGE_STATUS_VALID) {
+ ret = -EIO;
+ goto clear_irq;
+ }
+
+ ret = vl53l1x_read_u16(data,
+ VL53L1X_REG_RESULT__FINAL_CROSSTALK_CORRECTED_RANGE_MM_SD0,
+ &distance);
+ if (ret)
+ goto clear_irq;
+
+ *val = distance;
+
+clear_irq:
+ vl53l1x_clear_irq(data);
+ return ret;
+}
+
+static const struct iio_chan_spec vl53l1x_channels[] = {
+ {
+ .type = IIO_DISTANCE,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+ BIT(IIO_CHAN_INFO_SCALE),
+ .scan_index = 0,
+ .scan_type = {
+ .sign = 'u',
+ .realbits = 16,
+ .storagebits = 16,
+ },
+ },
+ IIO_CHAN_SOFT_TIMESTAMP(1),
+};
+
+static int vl53l1x_read_raw(struct iio_dev *indio_dev,
+ const struct iio_chan_spec *chan,
+ int *val, int *val2, long mask)
+{
+ struct vl53l1x_data *data = iio_priv(indio_dev);
+ int ret;
+
+ if (chan->type != IIO_DISTANCE)
+ return -EINVAL;
+
+ switch (mask) {
+ case IIO_CHAN_INFO_RAW:
+ if (!iio_device_claim_direct(indio_dev))
+ return -EBUSY;
+ ret = vl53l1x_read_proximity(data, val);
+ iio_device_release_direct(indio_dev);
+ if (ret)
+ return ret;
+ return IIO_VAL_INT;
+ case IIO_CHAN_INFO_SCALE:
+ *val = 0;
+ *val2 = 1000;
+ return IIO_VAL_INT_PLUS_MICRO;
+ default:
+ return -EINVAL;
+ }
+}
+
+static const struct iio_info vl53l1x_info = {
+ .read_raw = vl53l1x_read_raw,
+ .validate_trigger = iio_validate_own_trigger,
+};
+
+static irqreturn_t vl53l1x_trigger_handler(int irq, void *priv)
+{
+ struct iio_poll_func *pf = priv;
+ struct iio_dev *indio_dev = pf->indio_dev;
+ struct vl53l1x_data *data = iio_priv(indio_dev);
+ struct {
+ u16 distance;
+ aligned_s64 timestamp;
+ } scan = { };
+ unsigned int range_status;
+ int ret;
+
+ ret = regmap_read(data->regmap, VL53L1X_REG_RESULT__RANGE_STATUS,
+ &range_status);
+ if (ret)
+ goto notify_and_clear_irq;
+ if (FIELD_GET(VL53L1X_RANGE_STATUS_MASK, range_status) !=
+ VL53L1X_RANGE_STATUS_VALID)
+ goto notify_and_clear_irq;
+
+ ret = vl53l1x_read_u16(data,
+ VL53L1X_REG_RESULT__FINAL_CROSSTALK_CORRECTED_RANGE_MM_SD0,
+ &scan.distance);
+ if (ret)
+ goto notify_and_clear_irq;
+
+ iio_push_to_buffers_with_ts(indio_dev, &scan, sizeof(scan),
+ iio_get_time_ns(indio_dev));
+
+notify_and_clear_irq:
+ iio_trigger_notify_done(indio_dev->trig);
+ vl53l1x_clear_irq(data);
+
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t vl53l1x_irq_handler(int irq, void *priv)
+{
+ struct iio_dev *indio_dev = priv;
+ struct vl53l1x_data *data = iio_priv(indio_dev);
+
+ if (iio_buffer_enabled(indio_dev))
+ iio_trigger_poll(indio_dev->trig);
+ else
+ complete(&data->completion);
+
+ return IRQ_HANDLED;
+}
+
+static const struct iio_trigger_ops vl53l1x_trigger_ops = {
+ .validate_device = iio_trigger_validate_own_device,
+};
+
+static void vl53l1x_stop_ranging_action(void *priv)
+{
+ vl53l1x_stop_ranging(priv);
+}
+
+static int vl53l1x_configure_irq(struct device *dev, int irq,
+ struct iio_dev *indio_dev)
+{
+ struct vl53l1x_data *data = iio_priv(indio_dev);
+ int ret;
+
+ ret = devm_request_irq(dev, irq, vl53l1x_irq_handler, IRQF_NO_THREAD,
+ indio_dev->name, indio_dev);
+ if (ret)
+ return ret;
+
+ ret = regmap_write(data->regmap, VL53L1X_REG_SYSTEM__INTERRUPT_CONFIG_GPIO,
+ VL53L1X_INT_NEW_SAMPLE_READY);
+ if (ret)
+ return dev_err_probe(dev, ret, "failed to configure IRQ\n");
+
+ return 0;
+}
+
+static int vl53l1x_probe(struct i2c_client *client)
+{
+ struct device *dev = &client->dev;
+ struct vl53l1x_data *data;
+ struct iio_dev *indio_dev;
+ int ret;
+
+ indio_dev = devm_iio_device_alloc(dev, sizeof(*data));
+ if (!indio_dev)
+ return -ENOMEM;
+
+ data = iio_priv(indio_dev);
+ data->irq = client->irq;
+
+ data->regmap = devm_regmap_init_i2c(client, &vl53l1x_regmap_config);
+ if (IS_ERR(data->regmap))
+ return dev_err_probe(dev, PTR_ERR(data->regmap),
+ "regmap initialization failed\n");
+
+ ret = devm_regulator_get_enable(dev, "vdd");
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to enable VDD regulator\n");
+
+ /*
+ * XSHUT held low puts the chip in hardware standby. All register
+ * state is lost on de-assert so this is functionally a reset.
+ */
+ data->xshut_reset = devm_reset_control_get_optional_exclusive_deasserted(dev, NULL);
+ if (IS_ERR(data->xshut_reset))
+ return dev_err_probe(dev, PTR_ERR(data->xshut_reset),
+ "Cannot get reset control\n");
+
+ /*
+ * 1.2 ms max boot duration.
+ * Datasheet Section 3.6 "Power up and boot sequence".
+ */
+ fsleep(1200);
+
+ ret = vl53l1x_chip_init(data);
+ if (ret)
+ return ret;
+
+ ret = vl53l1x_set_distance_mode(data, VL53L1X_LONG);
+ if (ret)
+ return ret;
+
+ /* 50 ms timing budget (per ST Ultra Lite Driver) */
+ ret = vl53l1x_set_timing_budget(data, 50);
+ if (ret)
+ return ret;
+
+ /* 50 ms inter-measurement period (per ST Ultra Lite Driver) */
+ ret = vl53l1x_set_inter_measurement_ms(data, 50);
+ if (ret)
+ return ret;
+
+ /*
+ * The hardware only supports "autonomous" continuous ranging mode.
+ * Start ranging here and leave it running for the lifetime of
+ * the device. Both direct reads and the buffer path rely on this.
+ */
+ ret = vl53l1x_start_ranging(data);
+ if (ret)
+ return ret;
+
+ ret = devm_add_action_or_reset(dev, vl53l1x_stop_ranging_action, data);
+ if (ret)
+ return ret;
+
+ indio_dev->name = "vl53l1x";
+ indio_dev->info = &vl53l1x_info;
+ indio_dev->channels = vl53l1x_channels;
+ indio_dev->num_channels = ARRAY_SIZE(vl53l1x_channels);
+ indio_dev->modes = INDIO_DIRECT_MODE;
+
+ if (client->irq) {
+ struct iio_trigger *trig;
+
+ init_completion(&data->completion);
+
+ trig = devm_iio_trigger_alloc(dev, "%s-dev%d", indio_dev->name,
+ iio_device_id(indio_dev));
+ if (!trig)
+ return -ENOMEM;
+
+ trig->ops = &vl53l1x_trigger_ops;
+ iio_trigger_set_drvdata(trig, indio_dev);
+ ret = devm_iio_trigger_register(dev, trig);
+ if (ret)
+ return ret;
+
+ indio_dev->trig = iio_trigger_get(trig);
+
+ ret = vl53l1x_configure_irq(dev, client->irq, indio_dev);
+ if (ret)
+ return ret;
+
+ ret = devm_iio_triggered_buffer_setup(dev, indio_dev, NULL,
+ &vl53l1x_trigger_handler,
+ NULL);
+ if (ret)
+ return ret;
+ }
+
+ return devm_iio_device_register(dev, indio_dev);
+}
+
+static const struct i2c_device_id vl53l1x_id[] = {
+ { "vl53l1x" },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, vl53l1x_id);
+
+static const struct of_device_id st_vl53l1x_dt_match[] = {
+ { .compatible = "st,vl53l1x" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, st_vl53l1x_dt_match);
+
+static struct i2c_driver vl53l1x_driver = {
+ .driver = {
+ .name = "vl53l1x-i2c",
+ .of_match_table = st_vl53l1x_dt_match,
+ },
+ .probe = vl53l1x_probe,
+ .id_table = vl53l1x_id,
+};
+module_i2c_driver(vl53l1x_driver);
+
+MODULE_AUTHOR("Siratul Islam <email@sirat.me>");
+MODULE_DESCRIPTION("ST VL53L1X ToF ranging sensor driver");
+MODULE_LICENSE("Dual BSD/GPL");
diff --git a/drivers/iio/resolver/ad2s1210.c b/drivers/iio/resolver/ad2s1210.c
index 06d9c784f93e..774728c804c0 100644
--- a/drivers/iio/resolver/ad2s1210.c
+++ b/drivers/iio/resolver/ad2s1210.c
@@ -896,14 +896,14 @@ static const struct iio_event_spec ad2s1210_monitor_signal_event_spec[] = {
.mask_separate = BIT(IIO_EV_INFO_VALUE),
},
{
- /* Sine/cosine DOS overrange fault.*/
+ /* Sine/cosine DOS overrange fault. */
.type = IIO_EV_TYPE_THRESH,
.dir = IIO_EV_DIR_RISING,
- /* Degredation of signal overrange threshold. */
+ /* Degradation of signal overrange threshold. */
.mask_separate = BIT(IIO_EV_INFO_VALUE),
},
{
- /* Sine/cosine DOS mismatch fault.*/
+ /* Sine/cosine DOS mismatch fault. */
.type = IIO_EV_TYPE_MAG,
.dir = IIO_EV_DIR_RISING,
.mask_separate = BIT(IIO_EV_INFO_VALUE),
diff --git a/drivers/iio/temperature/ltc2983.c b/drivers/iio/temperature/ltc2983.c
index 7dd40d69cce6..38e6f8dfd3b8 100644
--- a/drivers/iio/temperature/ltc2983.c
+++ b/drivers/iio/temperature/ltc2983.c
@@ -709,7 +709,7 @@ ltc2983_thermocouple_new(const struct fwnode_handle *child, struct ltc2983_data
ret = fwnode_property_read_u32(ref, "reg", &thermo->cold_junction_chan);
if (ret)
/*
- * This would be catched later but we can just return
+ * This would be caught later but we can just return
* the error right away.
*/
return dev_err_ptr_probe(&st->spi->dev, ret,
@@ -798,7 +798,7 @@ ltc2983_rtd_new(const struct fwnode_handle *child, struct ltc2983_data *st,
* For 4wire RTD with rotation, the channel selection cannot be
* >=19 since the chann + 1 is used in this configuration.
* For 4wire RTDs with kelvin rsense, the rsense channel cannot be
- * <=1 since chanel - 1 and channel - 2 are used.
+ * <=1 since channel - 1 and channel - 2 are used.
*/
if (rtd->sensor_config & LTC2983_RTD_4_WIRE_MASK) {
/* 4-wire */
diff --git a/drivers/iio/test/iio-test-gts.c b/drivers/iio/test/iio-test-gts.c
index 11250bc905c9..6ffff85ba853 100644
--- a/drivers/iio/test/iio-test-gts.c
+++ b/drivers/iio/test/iio-test-gts.c
@@ -20,7 +20,7 @@
*
* If yes, then adding a test is probably a good idea but please stop for a
* moment and consider the effort of changing all the tests when code gets
- * refactored. Eventually it neeeds to be.
+ * refactored. Eventually it needs to be.
*/
#define TEST_TSEL_50 1
diff --git a/drivers/interconnect/debugfs-client.c b/drivers/interconnect/debugfs-client.c
index 5107bff53173..08df9188ef94 100644
--- a/drivers/interconnect/debugfs-client.c
+++ b/drivers/interconnect/debugfs-client.c
@@ -150,10 +150,13 @@ int icc_debugfs_client_init(struct dentry *icc_dir)
return ret;
}
- src_node = devm_kstrdup(&pdev->dev, "", GFP_KERNEL);
- dst_node = devm_kstrdup(&pdev->dev, "", GFP_KERNEL);
- if (!src_node || !dst_node)
+ src_node = kstrdup("", GFP_KERNEL);
+ dst_node = kstrdup("", GFP_KERNEL);
+ if (!src_node || !dst_node) {
+ kfree(dst_node);
+ kfree(src_node);
return -ENOMEM;
+ }
client_dir = debugfs_create_dir("test_client", icc_dir);
diff --git a/drivers/interconnect/qcom/Kconfig b/drivers/interconnect/qcom/Kconfig
index bb1cb8a640c1..786b4eda44b4 100644
--- a/drivers/interconnect/qcom/Kconfig
+++ b/drivers/interconnect/qcom/Kconfig
@@ -8,8 +8,17 @@ config INTERCONNECT_QCOM
config INTERCONNECT_QCOM_BCM_VOTER
tristate
+config INTERCONNECT_QCOM_ELIZA
+ tristate "Qualcomm Eliza interconnect driver"
+ depends on INTERCONNECT_QCOM_RPMH_POSSIBLE
+ select INTERCONNECT_QCOM_RPMH
+ select INTERCONNECT_QCOM_BCM_VOTER
+ help
+ This is a driver for the Qualcomm Network-on-Chip on Eliza-based
+ platforms.
+
config INTERCONNECT_QCOM_GLYMUR
- tristate "Qualcomm GLYMUR interconnect driver"
+ tristate "Qualcomm Glymur interconnect driver"
depends on INTERCONNECT_QCOM_RPMH_POSSIBLE
select INTERCONNECT_QCOM_RPMH
select INTERCONNECT_QCOM_BCM_VOTER
@@ -18,7 +27,7 @@ config INTERCONNECT_QCOM_GLYMUR
platforms.
config INTERCONNECT_QCOM_KAANAPALI
- tristate "Qualcomm KAANAPALI interconnect driver"
+ tristate "Qualcomm Kaanapali interconnect driver"
depends on INTERCONNECT_QCOM_RPMH_POSSIBLE
select INTERCONNECT_QCOM_RPMH
select INTERCONNECT_QCOM_BCM_VOTER
diff --git a/drivers/interconnect/qcom/Makefile b/drivers/interconnect/qcom/Makefile
index 6eedff043b41..cdf2c6c9fbf3 100644
--- a/drivers/interconnect/qcom/Makefile
+++ b/drivers/interconnect/qcom/Makefile
@@ -4,6 +4,7 @@ obj-$(CONFIG_INTERCONNECT_QCOM) += interconnect_qcom.o
interconnect_qcom-y := icc-common.o
icc-bcm-voter-objs := bcm-voter.o
+qnoc-eliza-objs := eliza.o
qnoc-glymur-objs := glymur.o
qnoc-kaanapali-objs := kaanapali.o
qnoc-milos-objs := milos.o
@@ -48,6 +49,7 @@ qnoc-x1e80100-objs := x1e80100.o
icc-smd-rpm-objs := smd-rpm.o icc-rpm.o icc-rpm-clocks.o
obj-$(CONFIG_INTERCONNECT_QCOM_BCM_VOTER) += icc-bcm-voter.o
+obj-$(CONFIG_INTERCONNECT_QCOM_ELIZA) += qnoc-eliza.o
obj-$(CONFIG_INTERCONNECT_QCOM_GLYMUR) += qnoc-glymur.o
obj-$(CONFIG_INTERCONNECT_QCOM_KAANAPALI) += qnoc-kaanapali.o
obj-$(CONFIG_INTERCONNECT_QCOM_MILOS) += qnoc-milos.o
diff --git a/drivers/interconnect/qcom/eliza.c b/drivers/interconnect/qcom/eliza.c
new file mode 100644
index 000000000000..a4f7903f0524
--- /dev/null
+++ b/drivers/interconnect/qcom/eliza.c
@@ -0,0 +1,1585 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
+ */
+
+#include <linux/device.h>
+#include <linux/interconnect.h>
+#include <linux/interconnect-provider.h>
+#include <linux/module.h>
+#include <linux/of_platform.h>
+#include <dt-bindings/interconnect/qcom,eliza-rpmh.h>
+
+#include "bcm-voter.h"
+#include "icc-rpmh.h"
+
+static struct qcom_icc_node qup1_core_slave = {
+ .name = "qup1_core_slave",
+ .channels = 1,
+ .buswidth = 4,
+};
+
+static struct qcom_icc_node qup2_core_slave = {
+ .name = "qup2_core_slave",
+ .channels = 1,
+ .buswidth = 4,
+};
+
+static struct qcom_icc_node qhs_ahb2phy0 = {
+ .name = "qhs_ahb2phy0",
+ .channels = 1,
+ .buswidth = 4,
+};
+
+static struct qcom_icc_node qhs_ahb2phy1 = {
+ .name = "qhs_ahb2phy1",
+ .channels = 1,
+ .buswidth = 4,
+};
+
+static struct qcom_icc_node qhs_camera_cfg = {
+ .name = "qhs_camera_cfg",
+ .channels = 1,
+ .buswidth = 4,
+};
+
+static struct qcom_icc_node qhs_clk_ctl = {
+ .name = "qhs_clk_ctl",
+ .channels = 1,
+ .buswidth = 4,
+};
+
+static struct qcom_icc_node qhs_crypto0_cfg = {
+ .name = "qhs_crypto0_cfg",
+ .channels = 1,
+ .buswidth = 4,
+};
+
+static struct qcom_icc_node qhs_display_cfg = {
+ .name = "qhs_display_cfg",
+ .channels = 1,
+ .buswidth = 4,
+};
+
+static struct qcom_icc_node qhs_gpuss_cfg = {
+ .name = "qhs_gpuss_cfg",
+ .channels = 1,
+ .buswidth = 8,
+};
+
+static struct qcom_icc_node qhs_i3c_ibi0_cfg = {
+ .name = "qhs_i3c_ibi0_cfg",
+ .channels = 1,
+ .buswidth = 4,
+};
+
+static struct qcom_icc_node qhs_i3c_ibi1_cfg = {
+ .name = "qhs_i3c_ibi1_cfg",
+ .channels = 1,
+ .buswidth = 4,
+};
+
+static struct qcom_icc_node qhs_imem_cfg = {
+ .name = "qhs_imem_cfg",
+ .channels = 1,
+ .buswidth = 4,
+};
+
+static struct qcom_icc_node qhs_mss_cfg = {
+ .name = "qhs_mss_cfg",
+ .channels = 1,
+ .buswidth = 4,
+};
+
+static struct qcom_icc_node qhs_pcie_0_cfg = {
+ .name = "qhs_pcie_0_cfg",
+ .channels = 1,
+ .buswidth = 4,
+};
+
+static struct qcom_icc_node qhs_prng = {
+ .name = "qhs_prng",
+ .channels = 1,
+ .buswidth = 4,
+};
+
+static struct qcom_icc_node qhs_qdss_cfg = {
+ .name = "qhs_qdss_cfg",
+ .channels = 1,
+ .buswidth = 4,
+};
+
+static struct qcom_icc_node qhs_qspi = {
+ .name = "qhs_qspi",
+ .channels = 1,
+ .buswidth = 4,
+};
+
+static struct qcom_icc_node qhs_qup1 = {
+ .name = "qhs_qup1",
+ .channels = 1,
+ .buswidth = 4,
+};
+
+static struct qcom_icc_node qhs_qup2 = {
+ .name = "qhs_qup2",
+ .channels = 1,
+ .buswidth = 4,
+};
+
+static struct qcom_icc_node qhs_sdc2 = {
+ .name = "qhs_sdc2",
+ .channels = 1,
+ .buswidth = 4,
+};
+
+static struct qcom_icc_node qhs_tcsr = {
+ .name = "qhs_tcsr",
+ .channels = 1,
+ .buswidth = 4,
+};
+
+static struct qcom_icc_node qhs_tlmm = {
+ .name = "qhs_tlmm",
+ .channels = 1,
+ .buswidth = 4,
+};
+
+static struct qcom_icc_node qhs_ufs_mem_cfg = {
+ .name = "qhs_ufs_mem_cfg",
+ .channels = 1,
+ .buswidth = 4,
+};
+
+static struct qcom_icc_node qhs_usb3_0 = {
+ .name = "qhs_usb3_0",
+ .channels = 1,
+ .buswidth = 4,
+};
+
+static struct qcom_icc_node qhs_venus_cfg = {
+ .name = "qhs_venus_cfg",
+ .channels = 1,
+ .buswidth = 4,
+};
+
+static struct qcom_icc_node qhs_vsense_ctrl_cfg = {
+ .name = "qhs_vsense_ctrl_cfg",
+ .channels = 1,
+ .buswidth = 4,
+};
+
+static struct qcom_icc_node xs_qdss_stm = {
+ .name = "xs_qdss_stm",
+ .channels = 1,
+ .buswidth = 4,
+};
+
+static struct qcom_icc_node xs_sys_tcu_cfg = {
+ .name = "xs_sys_tcu_cfg",
+ .channels = 1,
+ .buswidth = 8,
+};
+
+static struct qcom_icc_node qhs_aoss = {
+ .name = "qhs_aoss",
+ .channels = 1,
+ .buswidth = 4,
+};
+
+static struct qcom_icc_node qhs_ipa = {
+ .name = "qhs_ipa",
+ .channels = 1,
+ .buswidth = 4,
+};
+
+static struct qcom_icc_node qhs_ipc_router = {
+ .name = "qhs_ipc_router",
+ .channels = 1,
+ .buswidth = 4,
+};
+
+static struct qcom_icc_node qhs_soccp = {
+ .name = "qhs_soccp",
+ .channels = 1,
+ .buswidth = 4,
+};
+
+static struct qcom_icc_node qhs_tme_cfg = {
+ .name = "qhs_tme_cfg",
+ .channels = 1,
+ .buswidth = 4,
+};
+
+static struct qcom_icc_node qss_apss = {
+ .name = "qss_apss",
+ .channels = 1,
+ .buswidth = 4,
+};
+
+static struct qcom_icc_node qss_ddrss_cfg = {
+ .name = "qss_ddrss_cfg",
+ .channels = 1,
+ .buswidth = 4,
+};
+
+static struct qcom_icc_node qxs_boot_imem = {
+ .name = "qxs_boot_imem",
+ .channels = 1,
+ .buswidth = 16,
+};
+
+static struct qcom_icc_node qxs_imem = {
+ .name = "qxs_imem",
+ .channels = 1,
+ .buswidth = 8,
+};
+
+static struct qcom_icc_node qxs_modem_boot_imem = {
+ .name = "qxs_modem_boot_imem",
+ .channels = 1,
+ .buswidth = 8,
+};
+
+static struct qcom_icc_node srvc_cnoc_main = {
+ .name = "srvc_cnoc_main",
+ .channels = 1,
+ .buswidth = 4,
+};
+
+static struct qcom_icc_node xs_pcie_0 = {
+ .name = "xs_pcie_0",
+ .channels = 1,
+ .buswidth = 8,
+};
+
+static struct qcom_icc_node xs_pcie_1 = {
+ .name = "xs_pcie_1",
+ .channels = 1,
+ .buswidth = 8,
+};
+
+static struct qcom_icc_node ebi = {
+ .name = "ebi",
+ .channels = 4,
+ .buswidth = 4,
+};
+
+static struct qcom_icc_node srvc_mnoc_sf = {
+ .name = "srvc_mnoc_sf",
+ .channels = 1,
+ .buswidth = 4,
+};
+
+static struct qcom_icc_node srvc_mnoc_hf = {
+ .name = "srvc_mnoc_hf",
+ .channels = 1,
+ .buswidth = 4,
+};
+
+static struct qcom_icc_node srvc_pcie_aggre_noc = {
+ .name = "srvc_pcie_aggre_noc",
+ .channels = 1,
+ .buswidth = 4,
+};
+
+static struct qcom_icc_node qup1_core_master = {
+ .name = "qup1_core_master",
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 1,
+ .link_nodes = { &qup1_core_slave },
+};
+
+static struct qcom_icc_node qup2_core_master = {
+ .name = "qup2_core_master",
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 1,
+ .link_nodes = { &qup2_core_slave },
+};
+
+static struct qcom_icc_node qnm_gemnoc_pcie = {
+ .name = "qnm_gemnoc_pcie",
+ .channels = 1,
+ .buswidth = 16,
+ .num_links = 2,
+ .link_nodes = { &xs_pcie_0, &xs_pcie_1 },
+};
+
+static struct qcom_icc_node llcc_mc = {
+ .name = "llcc_mc",
+ .channels = 4,
+ .buswidth = 4,
+ .num_links = 1,
+ .link_nodes = { &ebi },
+};
+
+static struct qcom_icc_node qsm_sf_mnoc_cfg = {
+ .name = "qsm_sf_mnoc_cfg",
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 1,
+ .link_nodes = { &srvc_mnoc_sf },
+};
+
+static struct qcom_icc_node qsm_hf_mnoc_cfg = {
+ .name = "qsm_hf_mnoc_cfg",
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 1,
+ .link_nodes = { &srvc_mnoc_hf },
+};
+
+static struct qcom_icc_node qsm_pcie_anoc_cfg = {
+ .name = "qsm_pcie_anoc_cfg",
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 1,
+ .link_nodes = { &srvc_pcie_aggre_noc },
+};
+
+static struct qcom_icc_node qss_mnoc_hf_cfg = {
+ .name = "qss_mnoc_hf_cfg",
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 1,
+ .link_nodes = { &qsm_hf_mnoc_cfg },
+};
+
+static struct qcom_icc_node qss_mnoc_sf_cfg = {
+ .name = "qss_mnoc_sf_cfg",
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 1,
+ .link_nodes = { &qsm_sf_mnoc_cfg },
+};
+
+static struct qcom_icc_node qss_pcie_anoc_cfg = {
+ .name = "qss_pcie_anoc_cfg",
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 1,
+ .link_nodes = { &qsm_pcie_anoc_cfg },
+};
+
+static struct qcom_icc_node qns_llcc = {
+ .name = "qns_llcc",
+ .channels = 2,
+ .buswidth = 16,
+ .num_links = 1,
+ .link_nodes = { &llcc_mc },
+};
+
+static struct qcom_icc_node qns_pcie = {
+ .name = "qns_pcie",
+ .channels = 1,
+ .buswidth = 16,
+ .num_links = 1,
+ .link_nodes = { &qnm_gemnoc_pcie },
+};
+
+static struct qcom_icc_node qsm_cfg = {
+ .name = "qsm_cfg",
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 29,
+ .link_nodes = { &qhs_ahb2phy0, &qhs_ahb2phy1,
+ &qhs_camera_cfg, &qhs_clk_ctl,
+ &qhs_crypto0_cfg, &qhs_display_cfg,
+ &qhs_gpuss_cfg, &qhs_i3c_ibi0_cfg,
+ &qhs_i3c_ibi1_cfg, &qhs_imem_cfg,
+ &qhs_mss_cfg, &qhs_pcie_0_cfg,
+ &qhs_prng, &qhs_qdss_cfg,
+ &qhs_qspi, &qhs_qup1,
+ &qhs_qup2, &qhs_sdc2,
+ &qhs_tcsr, &qhs_tlmm,
+ &qhs_ufs_mem_cfg, &qhs_usb3_0,
+ &qhs_venus_cfg, &qhs_vsense_ctrl_cfg,
+ &qss_mnoc_hf_cfg, &qss_mnoc_sf_cfg,
+ &qss_pcie_anoc_cfg, &xs_qdss_stm,
+ &xs_sys_tcu_cfg },
+};
+
+static struct qcom_icc_node xm_gic = {
+ .name = "xm_gic",
+ .channels = 1,
+ .buswidth = 8,
+ .qosbox = &(const struct qcom_icc_qosbox) {
+ .num_ports = 1,
+ .port_offsets = { 0x15d000 },
+ .prio = 4,
+ .urg_fwd = 0,
+ .prio_fwd_disable = 1,
+ },
+ .num_links = 1,
+ .link_nodes = { &qns_llcc },
+};
+
+static struct qcom_icc_node qss_cfg = {
+ .name = "qss_cfg",
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 1,
+ .link_nodes = { &qsm_cfg },
+};
+
+static struct qcom_icc_node qnm_gemnoc_cnoc = {
+ .name = "qnm_gemnoc_cnoc",
+ .channels = 1,
+ .buswidth = 16,
+ .num_links = 12,
+ .link_nodes = { &qhs_aoss, &qhs_ipa,
+ &qhs_ipc_router, &qhs_soccp,
+ &qhs_tme_cfg, &qss_apss,
+ &qss_cfg, &qss_ddrss_cfg,
+ &qxs_boot_imem, &qxs_imem,
+ &qxs_modem_boot_imem, &srvc_cnoc_main },
+};
+
+static struct qcom_icc_node qns_gem_noc_cnoc = {
+ .name = "qns_gem_noc_cnoc",
+ .channels = 1,
+ .buswidth = 16,
+ .num_links = 1,
+ .link_nodes = { &qnm_gemnoc_cnoc },
+};
+
+static struct qcom_icc_qosbox alm_gpu_tcu_qos = {
+ .num_ports = 1,
+ .port_offsets = { 0x155000 },
+ .prio = 1,
+ .urg_fwd = 0,
+ .prio_fwd_disable = 1,
+};
+
+static struct qcom_icc_node alm_gpu_tcu = {
+ .name = "alm_gpu_tcu",
+ .channels = 1,
+ .buswidth = 8,
+ .qosbox = &alm_gpu_tcu_qos,
+ .num_links = 2,
+ .link_nodes = { &qns_gem_noc_cnoc, &qns_llcc },
+};
+
+static struct qcom_icc_qosbox alm_sys_tcu_qos = {
+ .num_ports = 1,
+ .port_offsets = { 0x157000 },
+ .prio = 6,
+ .urg_fwd = 0,
+ .prio_fwd_disable = 1,
+};
+
+static struct qcom_icc_node alm_sys_tcu = {
+ .name = "alm_sys_tcu",
+ .channels = 1,
+ .buswidth = 8,
+ .qosbox = &alm_sys_tcu_qos,
+ .num_links = 2,
+ .link_nodes = { &qns_gem_noc_cnoc, &qns_llcc },
+};
+
+static struct qcom_icc_node chm_apps = {
+ .name = "chm_apps",
+ .channels = 3,
+ .buswidth = 32,
+ .num_links = 3,
+ .link_nodes = { &qns_gem_noc_cnoc, &qns_llcc,
+ &qns_pcie },
+};
+
+static struct qcom_icc_qosbox qnm_gpu_qos = {
+ .num_ports = 2,
+ .port_offsets = { 0x31000, 0xb1000 },
+ .prio = 0,
+ .urg_fwd = 1,
+ .prio_fwd_disable = 1,
+};
+
+static struct qcom_icc_node qnm_gpu = {
+ .name = "qnm_gpu",
+ .channels = 2,
+ .buswidth = 32,
+ .qosbox = &qnm_gpu_qos,
+ .num_links = 2,
+ .link_nodes = { &qns_gem_noc_cnoc, &qns_llcc },
+};
+
+static struct qcom_icc_qosbox qnm_lpass_gemnoc_qos = {
+ .num_ports = 1,
+ .port_offsets = { 0x159000 },
+ .prio = 0,
+ .urg_fwd = 1,
+ .prio_fwd_disable = 0,
+};
+
+static struct qcom_icc_node qnm_lpass_gemnoc = {
+ .name = "qnm_lpass_gemnoc",
+ .channels = 1,
+ .buswidth = 16,
+ .qosbox = &qnm_lpass_gemnoc_qos,
+ .num_links = 3,
+ .link_nodes = { &qns_gem_noc_cnoc, &qns_llcc,
+ &qns_pcie },
+};
+
+static struct qcom_icc_node qnm_mdsp = {
+ .name = "qnm_mdsp",
+ .channels = 1,
+ .buswidth = 16,
+ .num_links = 3,
+ .link_nodes = { &qns_gem_noc_cnoc, &qns_llcc,
+ &qns_pcie },
+};
+
+static struct qcom_icc_qosbox qnm_mnoc_hf_qos = {
+ .num_ports = 2,
+ .port_offsets = { 0x33000, 0xb3000 },
+ .prio = 0,
+ .urg_fwd = 1,
+ .prio_fwd_disable = 0,
+};
+
+static struct qcom_icc_node qnm_mnoc_hf = {
+ .name = "qnm_mnoc_hf",
+ .channels = 2,
+ .buswidth = 32,
+ .qosbox = &qnm_mnoc_hf_qos,
+ .num_links = 2,
+ .link_nodes = { &qns_gem_noc_cnoc, &qns_llcc },
+};
+
+static struct qcom_icc_qosbox qnm_mnoc_sf_qos = {
+ .num_ports = 2,
+ .port_offsets = { 0x35000, 0xb5000 },
+ .prio = 0,
+ .urg_fwd = 0,
+ .prio_fwd_disable = 0,
+};
+
+static struct qcom_icc_node qnm_mnoc_sf = {
+ .name = "qnm_mnoc_sf",
+ .channels = 2,
+ .buswidth = 32,
+ .qosbox = &qnm_mnoc_sf_qos,
+ .num_links = 2,
+ .link_nodes = { &qns_gem_noc_cnoc, &qns_llcc },
+};
+
+static struct qcom_icc_qosbox qnm_nsp_gemnoc_qos = {
+ .num_ports = 2,
+ .port_offsets = { 0x37000, 0xb7000 },
+ .prio = 0,
+ .urg_fwd = 1,
+ .prio_fwd_disable = 1,
+};
+
+static struct qcom_icc_node qnm_nsp_gemnoc = {
+ .name = "qnm_nsp_gemnoc",
+ .channels = 2,
+ .buswidth = 32,
+ .qosbox = &qnm_nsp_gemnoc_qos,
+ .num_links = 3,
+ .link_nodes = { &qns_gem_noc_cnoc, &qns_llcc,
+ &qns_pcie },
+};
+
+static struct qcom_icc_qosbox qnm_pcie_qos = {
+ .num_ports = 1,
+ .port_offsets = { 0x15b000 },
+ .prio = 2,
+ .urg_fwd = 1,
+ .prio_fwd_disable = 0,
+};
+
+static struct qcom_icc_node qnm_pcie = {
+ .name = "qnm_pcie",
+ .channels = 1,
+ .buswidth = 16,
+ .qosbox = &qnm_pcie_qos,
+ .num_links = 2,
+ .link_nodes = { &qns_gem_noc_cnoc, &qns_llcc },
+};
+
+static struct qcom_icc_node qnm_snoc_sf = {
+ .name = "qnm_snoc_sf",
+ .channels = 1,
+ .buswidth = 16,
+ .qosbox = &(const struct qcom_icc_qosbox) {
+ .num_ports = 1,
+ .port_offsets = { 0x15f000 },
+ .prio = 0,
+ .urg_fwd = 1,
+ .prio_fwd_disable = 0,
+ },
+ .num_links = 3,
+ .link_nodes = { &qns_gem_noc_cnoc, &qns_llcc,
+ &qns_pcie },
+};
+
+static struct qcom_icc_node qxm_wlan_q6 = {
+ .name = "qxm_wlan_q6",
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 3,
+ .link_nodes = { &qns_gem_noc_cnoc, &qns_llcc,
+ &qns_pcie },
+};
+
+static struct qcom_icc_node qns_lpass_ag_noc_gemnoc = {
+ .name = "qns_lpass_ag_noc_gemnoc",
+ .channels = 1,
+ .buswidth = 16,
+ .num_links = 1,
+ .link_nodes = { &qnm_lpass_gemnoc },
+};
+
+static struct qcom_icc_node qns_mem_noc_sf = {
+ .name = "qns_mem_noc_sf",
+ .channels = 2,
+ .buswidth = 32,
+ .num_links = 1,
+ .link_nodes = { &qnm_mnoc_sf },
+};
+
+static struct qcom_icc_node qns_mem_noc_hf = {
+ .name = "qns_mem_noc_hf",
+ .channels = 2,
+ .buswidth = 32,
+ .num_links = 1,
+ .link_nodes = { &qnm_mnoc_hf },
+};
+
+static struct qcom_icc_node qns_nsp_gemnoc = {
+ .name = "qns_nsp_gemnoc",
+ .channels = 2,
+ .buswidth = 32,
+ .num_links = 1,
+ .link_nodes = { &qnm_nsp_gemnoc },
+};
+
+static struct qcom_icc_node qns_pcie_mem_noc = {
+ .name = "qns_pcie_mem_noc",
+ .channels = 1,
+ .buswidth = 16,
+ .num_links = 1,
+ .link_nodes = { &qnm_pcie },
+};
+
+static struct qcom_icc_node qns_gemnoc_sf = {
+ .name = "qns_gemnoc_sf",
+ .channels = 1,
+ .buswidth = 16,
+ .num_links = 1,
+ .link_nodes = { &qnm_snoc_sf },
+};
+
+static struct qcom_icc_node qnm_lpiaon_noc = {
+ .name = "qnm_lpiaon_noc",
+ .channels = 1,
+ .buswidth = 16,
+ .num_links = 1,
+ .link_nodes = { &qns_lpass_ag_noc_gemnoc },
+};
+
+static struct qcom_icc_qosbox qnm_camnoc_nrt_icp_sf_qos = {
+ .num_ports = 1,
+ .port_offsets = { 0x25000 },
+ .prio = 4,
+ .urg_fwd = 0,
+ .prio_fwd_disable = 1,
+};
+
+static struct qcom_icc_node qnm_camnoc_nrt_icp_sf = {
+ .name = "qnm_camnoc_nrt_icp_sf",
+ .channels = 1,
+ .buswidth = 8,
+ .qosbox = &qnm_camnoc_nrt_icp_sf_qos,
+ .num_links = 1,
+ .link_nodes = { &qns_mem_noc_sf },
+};
+
+static struct qcom_icc_node qnm_camnoc_rt_cdm_sf = {
+ .name = "qnm_camnoc_rt_cdm_sf",
+ .channels = 1,
+ .buswidth = 8,
+ .qosbox = &(const struct qcom_icc_qosbox) {
+ .num_ports = 1,
+ .port_offsets = { 0x2c000 },
+ .prio = 2,
+ .urg_fwd = 0,
+ .prio_fwd_disable = 1,
+ },
+ .num_links = 1,
+ .link_nodes = { &qns_mem_noc_sf },
+};
+
+static struct qcom_icc_node qnm_camnoc_sf = {
+ .name = "qnm_camnoc_sf",
+ .channels = 2,
+ .buswidth = 32,
+ .qosbox = &(const struct qcom_icc_qosbox) {
+ .num_ports = 2,
+ .port_offsets = { 0x26000, 0x27000 },
+ .prio = 0,
+ .urg_fwd = 1,
+ .prio_fwd_disable = 0,
+ },
+ .num_links = 1,
+ .link_nodes = { &qns_mem_noc_sf },
+};
+
+static struct qcom_icc_node qnm_video_mvp = {
+ .name = "qnm_video_mvp",
+ .channels = 1,
+ .buswidth = 32,
+ .qosbox = &(const struct qcom_icc_qosbox) {
+ .num_ports = 1,
+ .port_offsets = { 0x28000 },
+ .prio = 0,
+ .urg_fwd = 1,
+ .prio_fwd_disable = 0,
+ },
+ .num_links = 1,
+ .link_nodes = { &qns_mem_noc_sf },
+};
+
+static struct qcom_icc_node qnm_video_v_cpu = {
+ .name = "qnm_video_v_cpu",
+ .channels = 1,
+ .buswidth = 8,
+ .qosbox = &(const struct qcom_icc_qosbox) {
+ .num_ports = 1,
+ .port_offsets = { 0x2b000 },
+ .prio = 4,
+ .urg_fwd = 0,
+ .prio_fwd_disable = 1,
+ },
+ .num_links = 1,
+ .link_nodes = { &qns_mem_noc_sf },
+};
+
+static struct qcom_icc_node qnm_camnoc_hf = {
+ .name = "qnm_camnoc_hf",
+ .channels = 2,
+ .buswidth = 32,
+ .qosbox = &(const struct qcom_icc_qosbox) {
+ .num_ports = 2,
+ .port_offsets = { 0x64000, 0x65000 },
+ .prio = 0,
+ .urg_fwd = 1,
+ .prio_fwd_disable = 0,
+ },
+ .num_links = 1,
+ .link_nodes = { &qns_mem_noc_hf },
+};
+
+static struct qcom_icc_node qnm_mdp = {
+ .name = "qnm_mdp",
+ .channels = 2,
+ .buswidth = 32,
+ .qosbox = &(const struct qcom_icc_qosbox) {
+ .num_ports = 2,
+ .port_offsets = { 0x66000, 0x67000 },
+ .prio = 0,
+ .urg_fwd = 1,
+ .prio_fwd_disable = 0,
+ },
+ .num_links = 1,
+ .link_nodes = { &qns_mem_noc_hf },
+};
+
+static struct qcom_icc_node qxm_nsp = {
+ .name = "qxm_nsp",
+ .channels = 2,
+ .buswidth = 32,
+ .num_links = 1,
+ .link_nodes = { &qns_nsp_gemnoc },
+};
+
+static struct qcom_icc_node xm_pcie3_0 = {
+ .name = "xm_pcie3_0",
+ .channels = 1,
+ .buswidth = 8,
+ .qosbox = &(const struct qcom_icc_qosbox) {
+ .num_ports = 1,
+ .port_offsets = { 0xb000 },
+ .prio = 3,
+ .urg_fwd = 0,
+ .prio_fwd_disable = 1,
+ },
+ .num_links = 1,
+ .link_nodes = { &qns_pcie_mem_noc },
+};
+
+static struct qcom_icc_node xm_pcie3_1 = {
+ .name = "xm_pcie3_1",
+ .channels = 1,
+ .buswidth = 8,
+ .qosbox = &(const struct qcom_icc_qosbox) {
+ .num_ports = 1,
+ .port_offsets = { 0xc000 },
+ .prio = 3,
+ .urg_fwd = 0,
+ .prio_fwd_disable = 1,
+ },
+ .num_links = 1,
+ .link_nodes = { &qns_pcie_mem_noc },
+};
+
+static struct qcom_icc_node qnm_aggre1_noc = {
+ .name = "qnm_aggre1_noc",
+ .channels = 1,
+ .buswidth = 16,
+ .num_links = 1,
+ .link_nodes = { &qns_gemnoc_sf },
+};
+
+static struct qcom_icc_node qnm_aggre2_noc = {
+ .name = "qnm_aggre2_noc",
+ .channels = 1,
+ .buswidth = 16,
+ .num_links = 1,
+ .link_nodes = { &qns_gemnoc_sf },
+};
+
+static struct qcom_icc_node qnm_cnoc_data = {
+ .name = "qnm_cnoc_data",
+ .channels = 1,
+ .buswidth = 8,
+ .qosbox = &(const struct qcom_icc_qosbox) {
+ .num_ports = 1,
+ .port_offsets = { 0x1d000 },
+ .prio = 2,
+ .urg_fwd = 0,
+ .prio_fwd_disable = 1,
+ },
+ .num_links = 1,
+ .link_nodes = { &qns_gemnoc_sf },
+};
+
+static struct qcom_icc_node qnm_nsinoc_snoc = {
+ .name = "qnm_nsinoc_snoc",
+ .channels = 1,
+ .buswidth = 8,
+ .qosbox = &(const struct qcom_icc_qosbox) {
+ .num_ports = 1,
+ .port_offsets = { 0x1c000 },
+ .prio = 2,
+ .urg_fwd = 0,
+ .prio_fwd_disable = 1,
+ },
+ .num_links = 1,
+ .link_nodes = { &qns_gemnoc_sf },
+};
+
+static struct qcom_icc_node qns_a1noc_snoc = {
+ .name = "qns_a1noc_snoc",
+ .channels = 1,
+ .buswidth = 16,
+ .num_links = 1,
+ .link_nodes = { &qnm_aggre1_noc },
+};
+
+static struct qcom_icc_node qns_a2noc_snoc = {
+ .name = "qns_a2noc_snoc",
+ .channels = 1,
+ .buswidth = 16,
+ .num_links = 1,
+ .link_nodes = { &qnm_aggre2_noc },
+};
+
+static struct qcom_icc_node qns_lpass_aggnoc = {
+ .name = "qns_lpass_aggnoc",
+ .channels = 1,
+ .buswidth = 16,
+ .num_links = 1,
+ .link_nodes = { &qnm_lpiaon_noc },
+};
+
+static struct qcom_icc_node qhm_qspi = {
+ .name = "qhm_qspi",
+ .channels = 1,
+ .buswidth = 4,
+ .qosbox = &(const struct qcom_icc_qosbox) {
+ .num_ports = 1,
+ .port_offsets = { 0xc000 },
+ .prio = 2,
+ .urg_fwd = 0,
+ .prio_fwd_disable = 1,
+ },
+ .num_links = 1,
+ .link_nodes = { &qns_a1noc_snoc },
+};
+
+static struct qcom_icc_node qhm_qup1 = {
+ .name = "qhm_qup1",
+ .channels = 1,
+ .buswidth = 4,
+ .qosbox = &(const struct qcom_icc_qosbox) {
+ .num_ports = 1,
+ .port_offsets = { 0xd000 },
+ .prio = 2,
+ .urg_fwd = 0,
+ .prio_fwd_disable = 1,
+ },
+ .num_links = 1,
+ .link_nodes = { &qns_a1noc_snoc },
+};
+
+static struct qcom_icc_node xm_ufs_mem = {
+ .name = "xm_ufs_mem",
+ .channels = 1,
+ .buswidth = 16,
+ .qosbox = &(const struct qcom_icc_qosbox) {
+ .num_ports = 1,
+ .port_offsets = { 0xf000 },
+ .prio = 2,
+ .urg_fwd = 0,
+ .prio_fwd_disable = 1,
+ },
+ .num_links = 1,
+ .link_nodes = { &qns_a1noc_snoc },
+};
+
+static struct qcom_icc_node xm_usb3_0 = {
+ .name = "xm_usb3_0",
+ .channels = 1,
+ .buswidth = 8,
+ .qosbox = &(const struct qcom_icc_qosbox) {
+ .num_ports = 1,
+ .port_offsets = { 0x10000 },
+ .prio = 2,
+ .urg_fwd = 0,
+ .prio_fwd_disable = 1,
+ },
+ .num_links = 1,
+ .link_nodes = { &qns_a1noc_snoc },
+};
+
+static struct qcom_icc_node qhm_qup2 = {
+ .name = "qhm_qup2",
+ .channels = 1,
+ .buswidth = 4,
+ .qosbox = &(const struct qcom_icc_qosbox) {
+ .num_ports = 1,
+ .port_offsets = { 0x14000 },
+ .prio = 2,
+ .urg_fwd = 0,
+ .prio_fwd_disable = 1,
+ },
+ .num_links = 1,
+ .link_nodes = { &qns_a2noc_snoc },
+};
+
+static struct qcom_icc_node qxm_crypto = {
+ .name = "qxm_crypto",
+ .channels = 1,
+ .buswidth = 8,
+ .qosbox = &(const struct qcom_icc_qosbox) {
+ .num_ports = 1,
+ .port_offsets = { 0x15000 },
+ .prio = 2,
+ .urg_fwd = 0,
+ .prio_fwd_disable = 1,
+ },
+ .num_links = 1,
+ .link_nodes = { &qns_a2noc_snoc },
+};
+
+static struct qcom_icc_node qxm_ipa = {
+ .name = "qxm_ipa",
+ .channels = 1,
+ .buswidth = 8,
+ .qosbox = &(const struct qcom_icc_qosbox) {
+ .num_ports = 1,
+ .port_offsets = { 0x16000 },
+ .prio = 2,
+ .urg_fwd = 0,
+ .prio_fwd_disable = 1,
+ },
+ .num_links = 1,
+ .link_nodes = { &qns_a2noc_snoc },
+};
+
+static struct qcom_icc_node qxm_soccp = {
+ .name = "qxm_soccp",
+ .channels = 1,
+ .buswidth = 8,
+ .qosbox = &(const struct qcom_icc_qosbox) {
+ .num_ports = 1,
+ .port_offsets = { 0x1a000 },
+ .prio = 2,
+ .urg_fwd = 0,
+ .prio_fwd_disable = 1,
+ },
+ .num_links = 1,
+ .link_nodes = { &qns_a2noc_snoc },
+};
+
+static struct qcom_icc_node xm_qdss_etr_0 = {
+ .name = "xm_qdss_etr_0",
+ .channels = 1,
+ .buswidth = 8,
+ .qosbox = &(const struct qcom_icc_qosbox) {
+ .num_ports = 1,
+ .port_offsets = { 0x17000 },
+ .prio = 2,
+ .urg_fwd = 0,
+ .prio_fwd_disable = 1,
+ },
+ .num_links = 1,
+ .link_nodes = { &qns_a2noc_snoc },
+};
+
+static struct qcom_icc_node xm_qdss_etr_1 = {
+ .name = "xm_qdss_etr_1",
+ .channels = 1,
+ .buswidth = 8,
+ .qosbox = &(const struct qcom_icc_qosbox) {
+ .num_ports = 1,
+ .port_offsets = { 0x18000 },
+ .prio = 2,
+ .urg_fwd = 0,
+ .prio_fwd_disable = 1,
+ },
+ .num_links = 1,
+ .link_nodes = { &qns_a2noc_snoc },
+};
+
+static struct qcom_icc_node xm_sdc1 = {
+ .name = "xm_sdc1",
+ .channels = 1,
+ .buswidth = 8,
+ .qosbox = &(const struct qcom_icc_qosbox) {
+ .num_ports = 1,
+ .port_offsets = { 0x13000 },
+ .prio = 2,
+ .urg_fwd = 0,
+ .prio_fwd_disable = 1,
+ },
+ .num_links = 1,
+ .link_nodes = { &qns_a2noc_snoc },
+};
+
+static struct qcom_icc_node xm_sdc2 = {
+ .name = "xm_sdc2",
+ .channels = 1,
+ .buswidth = 8,
+ .qosbox = &(const struct qcom_icc_qosbox) {
+ .num_ports = 1,
+ .port_offsets = { 0x19000 },
+ .prio = 2,
+ .urg_fwd = 0,
+ .prio_fwd_disable = 1,
+ },
+ .num_links = 1,
+ .link_nodes = { &qns_a2noc_snoc },
+};
+
+static struct qcom_icc_node qnm_lpass_lpinoc = {
+ .name = "qnm_lpass_lpinoc",
+ .channels = 1,
+ .buswidth = 16,
+ .num_links = 1,
+ .link_nodes = { &qns_lpass_aggnoc },
+};
+
+static struct qcom_icc_node qns_lpi_aon_noc = {
+ .name = "qns_lpi_aon_noc",
+ .channels = 1,
+ .buswidth = 16,
+ .num_links = 1,
+ .link_nodes = { &qnm_lpass_lpinoc },
+};
+
+static struct qcom_icc_node qxm_lpinoc_dsp_axim = {
+ .name = "qxm_lpinoc_dsp_axim",
+ .channels = 1,
+ .buswidth = 16,
+ .num_links = 1,
+ .link_nodes = { &qns_lpi_aon_noc },
+};
+
+static struct qcom_icc_bcm bcm_ce0 = {
+ .name = "CE0",
+ .num_nodes = 1,
+ .nodes = { &qxm_crypto },
+};
+
+static struct qcom_icc_bcm bcm_cn0 = {
+ .name = "CN0",
+ .enable_mask = BIT(0),
+ .keepalive = true,
+ .num_nodes = 43,
+ .nodes = { &qsm_cfg, &qhs_ahb2phy0,
+ &qhs_ahb2phy1, &qhs_camera_cfg,
+ &qhs_clk_ctl, &qhs_crypto0_cfg,
+ &qhs_gpuss_cfg, &qhs_i3c_ibi0_cfg,
+ &qhs_i3c_ibi1_cfg, &qhs_imem_cfg,
+ &qhs_mss_cfg, &qhs_pcie_0_cfg,
+ &qhs_prng, &qhs_qdss_cfg,
+ &qhs_qspi, &qhs_sdc2,
+ &qhs_tcsr, &qhs_tlmm,
+ &qhs_ufs_mem_cfg, &qhs_usb3_0,
+ &qhs_venus_cfg, &qhs_vsense_ctrl_cfg,
+ &qss_mnoc_hf_cfg, &qss_mnoc_sf_cfg,
+ &qss_pcie_anoc_cfg, &xs_qdss_stm,
+ &xs_sys_tcu_cfg, &qnm_gemnoc_cnoc,
+ &qnm_gemnoc_pcie, &qhs_aoss,
+ &qhs_ipa, &qhs_ipc_router,
+ &qhs_soccp, &qhs_tme_cfg,
+ &qss_apss, &qss_cfg,
+ &qss_ddrss_cfg, &qxs_boot_imem,
+ &qxs_imem, &qxs_modem_boot_imem,
+ &srvc_cnoc_main, &xs_pcie_0,
+ &xs_pcie_1 },
+};
+
+static struct qcom_icc_bcm bcm_cn1 = {
+ .name = "CN1",
+ .num_nodes = 3,
+ .nodes = { &qhs_display_cfg, &qhs_qup1,
+ &qhs_qup2 },
+};
+
+static struct qcom_icc_bcm bcm_co0 = {
+ .name = "CO0",
+ .enable_mask = BIT(0),
+ .num_nodes = 2,
+ .nodes = { &qxm_nsp, &qns_nsp_gemnoc },
+};
+
+static struct qcom_icc_bcm bcm_lp0 = {
+ .name = "LP0",
+ .num_nodes = 2,
+ .nodes = { &qnm_lpass_lpinoc, &qns_lpass_aggnoc },
+};
+
+static struct qcom_icc_bcm bcm_mc0 = {
+ .name = "MC0",
+ .keepalive = true,
+ .num_nodes = 1,
+ .nodes = { &ebi },
+};
+
+static struct qcom_icc_bcm bcm_mm0 = {
+ .name = "MM0",
+ .num_nodes = 1,
+ .nodes = { &qns_mem_noc_hf },
+};
+
+static struct qcom_icc_bcm bcm_mm1 = {
+ .name = "MM1",
+ .enable_mask = BIT(0),
+ .num_nodes = 7,
+ .nodes = { &qnm_camnoc_nrt_icp_sf, &qnm_camnoc_rt_cdm_sf,
+ &qnm_camnoc_sf, &qnm_video_mvp,
+ &qnm_video_v_cpu, &qnm_camnoc_hf,
+ &qns_mem_noc_sf },
+};
+
+static struct qcom_icc_bcm bcm_qup1 = {
+ .name = "QUP1",
+ .vote_scale = 1,
+ .keepalive = true,
+ .num_nodes = 1,
+ .nodes = { &qup1_core_slave },
+};
+
+static struct qcom_icc_bcm bcm_qup2 = {
+ .name = "QUP2",
+ .vote_scale = 1,
+ .keepalive = true,
+ .num_nodes = 1,
+ .nodes = { &qup2_core_slave },
+};
+
+static struct qcom_icc_bcm bcm_sh0 = {
+ .name = "SH0",
+ .keepalive = true,
+ .num_nodes = 1,
+ .nodes = { &qns_llcc },
+};
+
+static struct qcom_icc_bcm bcm_sh1 = {
+ .name = "SH1",
+ .enable_mask = BIT(0),
+ .num_nodes = 14,
+ .nodes = { &alm_gpu_tcu, &alm_sys_tcu,
+ &chm_apps, &qnm_gpu,
+ &qnm_mdsp, &qnm_mnoc_hf,
+ &qnm_mnoc_sf, &qnm_nsp_gemnoc,
+ &qnm_pcie, &qnm_snoc_sf,
+ &qxm_wlan_q6, &xm_gic,
+ &qns_gem_noc_cnoc, &qns_pcie },
+};
+
+static struct qcom_icc_bcm bcm_sn0 = {
+ .name = "SN0",
+ .keepalive = true,
+ .num_nodes = 1,
+ .nodes = { &qns_gemnoc_sf },
+};
+
+static struct qcom_icc_bcm bcm_sn2 = {
+ .name = "SN2",
+ .num_nodes = 1,
+ .nodes = { &qnm_aggre1_noc },
+};
+
+static struct qcom_icc_bcm bcm_sn3 = {
+ .name = "SN3",
+ .num_nodes = 1,
+ .nodes = { &qnm_aggre2_noc },
+};
+
+static struct qcom_icc_bcm bcm_sn4 = {
+ .name = "SN4",
+ .num_nodes = 1,
+ .nodes = { &qns_pcie_mem_noc },
+};
+
+static struct qcom_icc_node * const aggre1_noc_nodes[] = {
+ [MASTER_QSPI_0] = &qhm_qspi,
+ [MASTER_QUP_1] = &qhm_qup1,
+ [MASTER_UFS_MEM] = &xm_ufs_mem,
+ [MASTER_USB3_0] = &xm_usb3_0,
+ [SLAVE_A1NOC_SNOC] = &qns_a1noc_snoc,
+};
+
+static const struct qcom_icc_desc eliza_aggre1_noc = {
+ .nodes = aggre1_noc_nodes,
+ .num_nodes = ARRAY_SIZE(aggre1_noc_nodes),
+ .qos_requires_clocks = true,
+};
+
+static struct qcom_icc_bcm * const aggre2_noc_bcms[] = {
+ &bcm_ce0,
+};
+
+static struct qcom_icc_node * const aggre2_noc_nodes[] = {
+ [MASTER_QUP_2] = &qhm_qup2,
+ [MASTER_CRYPTO] = &qxm_crypto,
+ [MASTER_IPA] = &qxm_ipa,
+ [MASTER_SOCCP_AGGR_NOC] = &qxm_soccp,
+ [MASTER_QDSS_ETR] = &xm_qdss_etr_0,
+ [MASTER_QDSS_ETR_1] = &xm_qdss_etr_1,
+ [MASTER_SDCC_1] = &xm_sdc1,
+ [MASTER_SDCC_2] = &xm_sdc2,
+ [SLAVE_A2NOC_SNOC] = &qns_a2noc_snoc,
+};
+
+static const struct qcom_icc_desc eliza_aggre2_noc = {
+ .nodes = aggre2_noc_nodes,
+ .num_nodes = ARRAY_SIZE(aggre2_noc_nodes),
+ .bcms = aggre2_noc_bcms,
+ .num_bcms = ARRAY_SIZE(aggre2_noc_bcms),
+ .qos_requires_clocks = true,
+};
+
+static struct qcom_icc_bcm * const clk_virt_bcms[] = {
+ &bcm_qup1,
+ &bcm_qup2,
+};
+
+static struct qcom_icc_node * const clk_virt_nodes[] = {
+ [MASTER_QUP_CORE_1] = &qup1_core_master,
+ [MASTER_QUP_CORE_2] = &qup2_core_master,
+ [SLAVE_QUP_CORE_1] = &qup1_core_slave,
+ [SLAVE_QUP_CORE_2] = &qup2_core_slave,
+};
+
+static const struct qcom_icc_desc eliza_clk_virt = {
+ .nodes = clk_virt_nodes,
+ .num_nodes = ARRAY_SIZE(clk_virt_nodes),
+ .bcms = clk_virt_bcms,
+ .num_bcms = ARRAY_SIZE(clk_virt_bcms),
+};
+
+static struct qcom_icc_bcm * const cnoc_cfg_bcms[] = {
+ &bcm_cn0,
+ &bcm_cn1,
+};
+
+static struct qcom_icc_node * const cnoc_cfg_nodes[] = {
+ [MASTER_CNOC_CFG] = &qsm_cfg,
+ [SLAVE_AHB2PHY_SOUTH] = &qhs_ahb2phy0,
+ [SLAVE_AHB2PHY_NORTH] = &qhs_ahb2phy1,
+ [SLAVE_CAMERA_CFG] = &qhs_camera_cfg,
+ [SLAVE_CLK_CTL] = &qhs_clk_ctl,
+ [SLAVE_CRYPTO_0_CFG] = &qhs_crypto0_cfg,
+ [SLAVE_DISPLAY_CFG] = &qhs_display_cfg,
+ [SLAVE_GFX3D_CFG] = &qhs_gpuss_cfg,
+ [SLAVE_I3C_IBI0_CFG] = &qhs_i3c_ibi0_cfg,
+ [SLAVE_I3C_IBI1_CFG] = &qhs_i3c_ibi1_cfg,
+ [SLAVE_IMEM_CFG] = &qhs_imem_cfg,
+ [SLAVE_CNOC_MSS] = &qhs_mss_cfg,
+ [SLAVE_PCIE_0_CFG] = &qhs_pcie_0_cfg,
+ [SLAVE_PRNG] = &qhs_prng,
+ [SLAVE_QDSS_CFG] = &qhs_qdss_cfg,
+ [SLAVE_QSPI_0] = &qhs_qspi,
+ [SLAVE_QUP_1] = &qhs_qup1,
+ [SLAVE_QUP_2] = &qhs_qup2,
+ [SLAVE_SDCC_2] = &qhs_sdc2,
+ [SLAVE_TCSR] = &qhs_tcsr,
+ [SLAVE_TLMM] = &qhs_tlmm,
+ [SLAVE_UFS_MEM_CFG] = &qhs_ufs_mem_cfg,
+ [SLAVE_USB3_0] = &qhs_usb3_0,
+ [SLAVE_VENUS_CFG] = &qhs_venus_cfg,
+ [SLAVE_VSENSE_CTRL_CFG] = &qhs_vsense_ctrl_cfg,
+ [SLAVE_CNOC_MNOC_HF_CFG] = &qss_mnoc_hf_cfg,
+ [SLAVE_CNOC_MNOC_SF_CFG] = &qss_mnoc_sf_cfg,
+ [SLAVE_PCIE_ANOC_CFG] = &qss_pcie_anoc_cfg,
+ [SLAVE_QDSS_STM] = &xs_qdss_stm,
+ [SLAVE_TCU] = &xs_sys_tcu_cfg,
+};
+
+static const struct qcom_icc_desc eliza_cnoc_cfg = {
+ .nodes = cnoc_cfg_nodes,
+ .num_nodes = ARRAY_SIZE(cnoc_cfg_nodes),
+ .bcms = cnoc_cfg_bcms,
+ .num_bcms = ARRAY_SIZE(cnoc_cfg_bcms),
+};
+
+static struct qcom_icc_bcm * const cnoc_main_bcms[] = {
+ &bcm_cn0,
+};
+
+static struct qcom_icc_node * const cnoc_main_nodes[] = {
+ [MASTER_GEM_NOC_CNOC] = &qnm_gemnoc_cnoc,
+ [MASTER_GEM_NOC_PCIE_SNOC] = &qnm_gemnoc_pcie,
+ [SLAVE_AOSS] = &qhs_aoss,
+ [SLAVE_IPA_CFG] = &qhs_ipa,
+ [SLAVE_IPC_ROUTER_CFG] = &qhs_ipc_router,
+ [SLAVE_SOCCP] = &qhs_soccp,
+ [SLAVE_TME_CFG] = &qhs_tme_cfg,
+ [SLAVE_APPSS] = &qss_apss,
+ [SLAVE_CNOC_CFG] = &qss_cfg,
+ [SLAVE_DDRSS_CFG] = &qss_ddrss_cfg,
+ [SLAVE_BOOT_IMEM] = &qxs_boot_imem,
+ [SLAVE_IMEM] = &qxs_imem,
+ [SLAVE_BOOT_IMEM_2] = &qxs_modem_boot_imem,
+ [SLAVE_SERVICE_CNOC] = &srvc_cnoc_main,
+ [SLAVE_PCIE_0] = &xs_pcie_0,
+ [SLAVE_PCIE_1] = &xs_pcie_1,
+};
+
+static const struct qcom_icc_desc eliza_cnoc_main = {
+ .nodes = cnoc_main_nodes,
+ .num_nodes = ARRAY_SIZE(cnoc_main_nodes),
+ .bcms = cnoc_main_bcms,
+ .num_bcms = ARRAY_SIZE(cnoc_main_bcms),
+};
+
+static struct qcom_icc_bcm * const gem_noc_bcms[] = {
+ &bcm_sh0,
+ &bcm_sh1,
+};
+
+static struct qcom_icc_node * const gem_noc_nodes[] = {
+ [MASTER_GPU_TCU] = &alm_gpu_tcu,
+ [MASTER_SYS_TCU] = &alm_sys_tcu,
+ [MASTER_APPSS_PROC] = &chm_apps,
+ [MASTER_GFX3D] = &qnm_gpu,
+ [MASTER_LPASS_GEM_NOC] = &qnm_lpass_gemnoc,
+ [MASTER_MSS_PROC] = &qnm_mdsp,
+ [MASTER_MNOC_HF_MEM_NOC] = &qnm_mnoc_hf,
+ [MASTER_MNOC_SF_MEM_NOC] = &qnm_mnoc_sf,
+ [MASTER_COMPUTE_NOC] = &qnm_nsp_gemnoc,
+ [MASTER_ANOC_PCIE_GEM_NOC] = &qnm_pcie,
+ [MASTER_SNOC_SF_MEM_NOC] = &qnm_snoc_sf,
+ [MASTER_WLAN_Q6] = &qxm_wlan_q6,
+ [MASTER_GIC] = &xm_gic,
+ [SLAVE_GEM_NOC_CNOC] = &qns_gem_noc_cnoc,
+ [SLAVE_LLCC] = &qns_llcc,
+ [SLAVE_MEM_NOC_PCIE_SNOC] = &qns_pcie,
+};
+
+static const struct qcom_icc_desc eliza_gem_noc = {
+ .nodes = gem_noc_nodes,
+ .num_nodes = ARRAY_SIZE(gem_noc_nodes),
+ .bcms = gem_noc_bcms,
+ .num_bcms = ARRAY_SIZE(gem_noc_bcms),
+};
+
+static struct qcom_icc_node * const lpass_ag_noc_nodes[] = {
+ [MASTER_LPIAON_NOC] = &qnm_lpiaon_noc,
+ [SLAVE_LPASS_GEM_NOC] = &qns_lpass_ag_noc_gemnoc,
+};
+
+static const struct qcom_icc_desc eliza_lpass_ag_noc = {
+ .nodes = lpass_ag_noc_nodes,
+ .num_nodes = ARRAY_SIZE(lpass_ag_noc_nodes),
+};
+
+static struct qcom_icc_bcm * const lpass_lpiaon_noc_bcms[] = {
+ &bcm_lp0,
+};
+
+static struct qcom_icc_node * const lpass_lpiaon_noc_nodes[] = {
+ [MASTER_LPASS_LPINOC] = &qnm_lpass_lpinoc,
+ [SLAVE_LPIAON_NOC_LPASS_AG_NOC] = &qns_lpass_aggnoc,
+};
+
+static const struct qcom_icc_desc eliza_lpass_lpiaon_noc = {
+ .nodes = lpass_lpiaon_noc_nodes,
+ .num_nodes = ARRAY_SIZE(lpass_lpiaon_noc_nodes),
+ .bcms = lpass_lpiaon_noc_bcms,
+ .num_bcms = ARRAY_SIZE(lpass_lpiaon_noc_bcms),
+};
+
+static struct qcom_icc_node * const lpass_lpicx_noc_nodes[] = {
+ [MASTER_LPASS_PROC] = &qxm_lpinoc_dsp_axim,
+ [SLAVE_LPICX_NOC_LPIAON_NOC] = &qns_lpi_aon_noc,
+};
+
+static const struct qcom_icc_desc eliza_lpass_lpicx_noc = {
+ .nodes = lpass_lpicx_noc_nodes,
+ .num_nodes = ARRAY_SIZE(lpass_lpicx_noc_nodes),
+};
+
+static struct qcom_icc_bcm * const mc_virt_bcms[] = {
+ &bcm_mc0,
+};
+
+static struct qcom_icc_node * const mc_virt_nodes[] = {
+ [MASTER_LLCC] = &llcc_mc,
+ [SLAVE_EBI1] = &ebi,
+};
+
+static const struct qcom_icc_desc eliza_mc_virt = {
+ .nodes = mc_virt_nodes,
+ .num_nodes = ARRAY_SIZE(mc_virt_nodes),
+ .bcms = mc_virt_bcms,
+ .num_bcms = ARRAY_SIZE(mc_virt_bcms),
+};
+
+static struct qcom_icc_bcm * const mmss_noc_bcms[] = {
+ &bcm_mm0,
+ &bcm_mm1,
+};
+
+static struct qcom_icc_node * const mmss_noc_nodes[] = {
+ [MASTER_CAMNOC_NRT_ICP_SF] = &qnm_camnoc_nrt_icp_sf,
+ [MASTER_CAMNOC_RT_CDM_SF] = &qnm_camnoc_rt_cdm_sf,
+ [MASTER_CAMNOC_SF] = &qnm_camnoc_sf,
+ [MASTER_VIDEO_MVP] = &qnm_video_mvp,
+ [MASTER_VIDEO_V_PROC] = &qnm_video_v_cpu,
+ [MASTER_CNOC_MNOC_SF_CFG] = &qsm_sf_mnoc_cfg,
+ [MASTER_CAMNOC_HF] = &qnm_camnoc_hf,
+ [MASTER_MDP] = &qnm_mdp,
+ [MASTER_CNOC_MNOC_HF_CFG] = &qsm_hf_mnoc_cfg,
+ [SLAVE_MNOC_SF_MEM_NOC] = &qns_mem_noc_sf,
+ [SLAVE_SERVICE_MNOC_SF] = &srvc_mnoc_sf,
+ [SLAVE_MNOC_HF_MEM_NOC] = &qns_mem_noc_hf,
+ [SLAVE_SERVICE_MNOC_HF] = &srvc_mnoc_hf,
+};
+
+static const struct qcom_icc_desc eliza_mmss_noc = {
+ .nodes = mmss_noc_nodes,
+ .num_nodes = ARRAY_SIZE(mmss_noc_nodes),
+ .bcms = mmss_noc_bcms,
+ .num_bcms = ARRAY_SIZE(mmss_noc_bcms),
+};
+
+static struct qcom_icc_bcm * const nsp_noc_bcms[] = {
+ &bcm_co0,
+};
+
+static struct qcom_icc_node * const nsp_noc_nodes[] = {
+ [MASTER_CDSP_PROC] = &qxm_nsp,
+ [SLAVE_CDSP_MEM_NOC] = &qns_nsp_gemnoc,
+};
+
+static const struct qcom_icc_desc eliza_nsp_noc = {
+ .nodes = nsp_noc_nodes,
+ .num_nodes = ARRAY_SIZE(nsp_noc_nodes),
+ .bcms = nsp_noc_bcms,
+ .num_bcms = ARRAY_SIZE(nsp_noc_bcms),
+};
+
+static struct qcom_icc_bcm * const pcie_anoc_bcms[] = {
+ &bcm_sn4,
+};
+
+static struct qcom_icc_node * const pcie_anoc_nodes[] = {
+ [MASTER_PCIE_ANOC_CFG] = &qsm_pcie_anoc_cfg,
+ [MASTER_PCIE_0] = &xm_pcie3_0,
+ [MASTER_PCIE_1] = &xm_pcie3_1,
+ [SLAVE_ANOC_PCIE_GEM_NOC] = &qns_pcie_mem_noc,
+ [SLAVE_SERVICE_PCIE_ANOC] = &srvc_pcie_aggre_noc,
+};
+
+static const struct qcom_icc_desc eliza_pcie_anoc = {
+ .nodes = pcie_anoc_nodes,
+ .num_nodes = ARRAY_SIZE(pcie_anoc_nodes),
+ .bcms = pcie_anoc_bcms,
+ .num_bcms = ARRAY_SIZE(pcie_anoc_bcms),
+ .qos_requires_clocks = true,
+};
+
+static struct qcom_icc_bcm * const system_noc_bcms[] = {
+ &bcm_sn0,
+ &bcm_sn2,
+ &bcm_sn3,
+};
+
+static struct qcom_icc_node * const system_noc_nodes[] = {
+ [MASTER_A1NOC_SNOC] = &qnm_aggre1_noc,
+ [MASTER_A2NOC_SNOC] = &qnm_aggre2_noc,
+ [MASTER_CNOC_SNOC] = &qnm_cnoc_data,
+ [MASTER_NSINOC_SNOC] = &qnm_nsinoc_snoc,
+ [SLAVE_SNOC_GEM_NOC_SF] = &qns_gemnoc_sf,
+};
+
+static const struct qcom_icc_desc eliza_system_noc = {
+ .nodes = system_noc_nodes,
+ .num_nodes = ARRAY_SIZE(system_noc_nodes),
+ .bcms = system_noc_bcms,
+ .num_bcms = ARRAY_SIZE(system_noc_bcms),
+};
+
+static const struct of_device_id qnoc_of_match[] = {
+ { .compatible = "qcom,eliza-aggre1-noc", .data = &eliza_aggre1_noc },
+ { .compatible = "qcom,eliza-aggre2-noc", .data = &eliza_aggre2_noc },
+ { .compatible = "qcom,eliza-clk-virt", .data = &eliza_clk_virt },
+ { .compatible = "qcom,eliza-cnoc-cfg", .data = &eliza_cnoc_cfg },
+ { .compatible = "qcom,eliza-cnoc-main", .data = &eliza_cnoc_main },
+ { .compatible = "qcom,eliza-gem-noc", .data = &eliza_gem_noc },
+ { .compatible = "qcom,eliza-lpass-ag-noc", .data = &eliza_lpass_ag_noc },
+ { .compatible = "qcom,eliza-lpass-lpiaon-noc", .data = &eliza_lpass_lpiaon_noc },
+ { .compatible = "qcom,eliza-lpass-lpicx-noc", .data = &eliza_lpass_lpicx_noc },
+ { .compatible = "qcom,eliza-mc-virt", .data = &eliza_mc_virt },
+ { .compatible = "qcom,eliza-mmss-noc", .data = &eliza_mmss_noc },
+ { .compatible = "qcom,eliza-nsp-noc", .data = &eliza_nsp_noc },
+ { .compatible = "qcom,eliza-pcie-anoc", .data = &eliza_pcie_anoc },
+ { .compatible = "qcom,eliza-system-noc", .data = &eliza_system_noc },
+ { }
+};
+MODULE_DEVICE_TABLE(of, qnoc_of_match);
+
+static struct platform_driver qnoc_driver = {
+ .probe = qcom_icc_rpmh_probe,
+ .remove = qcom_icc_rpmh_remove,
+ .driver = {
+ .name = "qnoc-eliza",
+ .of_match_table = qnoc_of_match,
+ .sync_state = icc_sync_state,
+ },
+};
+
+static int __init qnoc_driver_init(void)
+{
+ return platform_driver_register(&qnoc_driver);
+}
+core_initcall(qnoc_driver_init);
+
+static void __exit qnoc_driver_exit(void)
+{
+ platform_driver_unregister(&qnoc_driver);
+}
+module_exit(qnoc_driver_exit);
+
+MODULE_DESCRIPTION(" Qualcomm Eliza NoC driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/interconnect/qcom/glymur.c b/drivers/interconnect/qcom/glymur.c
index e5c07795a6c6..9b9ed99ef242 100644
--- a/drivers/interconnect/qcom/glymur.c
+++ b/drivers/interconnect/qcom/glymur.c
@@ -9,6 +9,7 @@
#include <linux/interconnect-provider.h>
#include <linux/module.h>
#include <linux/of_platform.h>
+#include <linux/property.h>
#include <dt-bindings/interconnect/qcom,glymur-rpmh.h>
#include "bcm-voter.h"
@@ -1985,7 +1986,7 @@ static struct qcom_icc_bcm * const cnoc_cfg_bcms[] = {
&bcm_cn1,
};
-static struct qcom_icc_node * const cnoc_cfg_nodes[] = {
+static struct qcom_icc_node *cnoc_cfg_nodes[] = {
[MASTER_CNOC_CFG] = &qsm_cfg,
[SLAVE_AHB2PHY_SOUTH] = &qhs_ahb2phy0,
[SLAVE_AHB2PHY_NORTH] = &qhs_ahb2phy1,
@@ -2093,7 +2094,7 @@ static struct qcom_icc_bcm * const hscnoc_bcms[] = {
&bcm_sh1,
};
-static struct qcom_icc_node * const hscnoc_nodes[] = {
+static struct qcom_icc_node *hscnoc_nodes[] = {
[MASTER_GPU_TCU] = &alm_gpu_tcu,
[MASTER_PCIE_TCU] = &alm_pcie_qtc,
[MASTER_SYS_TCU] = &alm_sys_tcu,
@@ -2377,7 +2378,7 @@ static struct qcom_icc_bcm * const pcie_west_anoc_bcms[] = {
&bcm_sn6,
};
-static struct qcom_icc_node * const pcie_west_anoc_nodes[] = {
+static struct qcom_icc_node *pcie_west_anoc_nodes[] = {
[MASTER_PCIE_WEST_ANOC_CFG] = &qsm_pcie_west_anoc_cfg,
[MASTER_PCIE_2] = &xm_pcie_2,
[MASTER_PCIE_3A] = &xm_pcie_3a,
@@ -2409,7 +2410,7 @@ static struct qcom_icc_bcm * const pcie_west_slv_noc_bcms[] = {
&bcm_sn6,
};
-static struct qcom_icc_node * const pcie_west_slv_noc_nodes[] = {
+static struct qcom_icc_node *pcie_west_slv_noc_nodes[] = {
[MASTER_HSCNOC_PCIE_WEST] = &qnm_hscnoc_pcie_west,
[MASTER_CNOC_PCIE_WEST_SLAVE_CFG] = &qsm_cnoc_pcie_west_slave_cfg,
[SLAVE_HSCNOC_PCIE_WEST_MS_MPU_CFG] = &qhs_hscnoc_pcie_west_ms_mpu_cfg,
@@ -2470,6 +2471,28 @@ static const struct qcom_icc_desc glymur_system_noc = {
.num_bcms = ARRAY_SIZE(system_noc_bcms),
};
+static int glymur_qnoc_probe(struct platform_device *pdev)
+{
+ if (device_is_compatible(&pdev->dev, "qcom,mahua-mc-virt")) {
+ llcc_mc.channels = 8;
+ ebi.channels = 8;
+ } else if (device_is_compatible(&pdev->dev, "qcom,mahua-hscnoc")) {
+ qns_llcc.channels = 8;
+ chm_apps.channels = 4;
+ qnm_pcie_west.buswidth = 32;
+ hscnoc_nodes[MASTER_WLAN_Q6] = NULL;
+ } else if (device_is_compatible(&pdev->dev, "qcom,mahua-pcie-west-anoc")) {
+ qns_pcie_west_mem_noc.buswidth = 32;
+ pcie_west_anoc_nodes[MASTER_PCIE_3A] = NULL;
+ } else if (device_is_compatible(&pdev->dev, "qcom,mahua-cnoc-cfg")) {
+ cnoc_cfg_nodes[SLAVE_PCIE_3A_CFG] = NULL;
+ } else if (device_is_compatible(&pdev->dev, "qcom,mahua-pcie-west-slv-noc")) {
+ pcie_west_slv_noc_nodes[SLAVE_PCIE_3A] = NULL;
+ }
+
+ return qcom_icc_rpmh_probe(pdev);
+}
+
static const struct of_device_id qnoc_of_match[] = {
{ .compatible = "qcom,glymur-aggre1-noc", .data = &glymur_aggre1_noc},
{ .compatible = "qcom,glymur-aggre2-noc", .data = &glymur_aggre2_noc},
@@ -2477,12 +2500,15 @@ static const struct of_device_id qnoc_of_match[] = {
{ .compatible = "qcom,glymur-aggre4-noc", .data = &glymur_aggre4_noc},
{ .compatible = "qcom,glymur-clk-virt", .data = &glymur_clk_virt},
{ .compatible = "qcom,glymur-cnoc-cfg", .data = &glymur_cnoc_cfg},
+ { .compatible = "qcom,mahua-cnoc-cfg", .data = &glymur_cnoc_cfg},
{ .compatible = "qcom,glymur-cnoc-main", .data = &glymur_cnoc_main},
{ .compatible = "qcom,glymur-hscnoc", .data = &glymur_hscnoc},
+ { .compatible = "qcom,mahua-hscnoc", .data = &glymur_hscnoc},
{ .compatible = "qcom,glymur-lpass-ag-noc", .data = &glymur_lpass_ag_noc},
{ .compatible = "qcom,glymur-lpass-lpiaon-noc", .data = &glymur_lpass_lpiaon_noc},
{ .compatible = "qcom,glymur-lpass-lpicx-noc", .data = &glymur_lpass_lpicx_noc},
{ .compatible = "qcom,glymur-mc-virt", .data = &glymur_mc_virt},
+ { .compatible = "qcom,mahua-mc-virt", .data = &glymur_mc_virt},
{ .compatible = "qcom,glymur-mmss-noc", .data = &glymur_mmss_noc},
{ .compatible = "qcom,glymur-nsinoc", .data = &glymur_nsinoc},
{ .compatible = "qcom,glymur-nsp-noc", .data = &glymur_nsp_noc},
@@ -2490,14 +2516,16 @@ static const struct of_device_id qnoc_of_match[] = {
{ .compatible = "qcom,glymur-pcie-east-anoc", .data = &glymur_pcie_east_anoc},
{ .compatible = "qcom,glymur-pcie-east-slv-noc", .data = &glymur_pcie_east_slv_noc},
{ .compatible = "qcom,glymur-pcie-west-anoc", .data = &glymur_pcie_west_anoc},
+ { .compatible = "qcom,mahua-pcie-west-anoc", .data = &glymur_pcie_west_anoc},
{ .compatible = "qcom,glymur-pcie-west-slv-noc", .data = &glymur_pcie_west_slv_noc},
+ { .compatible = "qcom,mahua-pcie-west-slv-noc", .data = &glymur_pcie_west_slv_noc},
{ .compatible = "qcom,glymur-system-noc", .data = &glymur_system_noc},
{ }
};
MODULE_DEVICE_TABLE(of, qnoc_of_match);
static struct platform_driver qnoc_driver = {
- .probe = qcom_icc_rpmh_probe,
+ .probe = glymur_qnoc_probe,
.remove = qcom_icc_rpmh_remove,
.driver = {
.name = "qnoc-glymur",
@@ -2518,5 +2546,5 @@ static void __exit qnoc_driver_exit(void)
}
module_exit(qnoc_driver_exit);
-MODULE_DESCRIPTION("GLYMUR NoC driver");
+MODULE_DESCRIPTION("Glymur NoC driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/interconnect/qcom/icc-rpm-clocks.c b/drivers/interconnect/qcom/icc-rpm-clocks.c
index ac1677de7dfd..69846e26f46a 100644
--- a/drivers/interconnect/qcom/icc-rpm-clocks.c
+++ b/drivers/interconnect/qcom/icc-rpm-clocks.c
@@ -31,6 +31,12 @@ const struct rpm_clk_resource mem_1_clk = {
};
EXPORT_SYMBOL_GPL(mem_1_clk);
+const struct rpm_clk_resource gpu_mem_2_clk = {
+ .resource_type = QCOM_SMD_RPM_MEM_CLK,
+ .clock_id = 2,
+};
+EXPORT_SYMBOL_GPL(gpu_mem_2_clk);
+
const struct rpm_clk_resource bus_0_clk = {
.resource_type = QCOM_SMD_RPM_BUS_CLK,
.clock_id = 0,
diff --git a/drivers/interconnect/qcom/icc-rpm.c b/drivers/interconnect/qcom/icc-rpm.c
index ea1042d38128..23a1d116e79a 100644
--- a/drivers/interconnect/qcom/icc-rpm.c
+++ b/drivers/interconnect/qcom/icc-rpm.c
@@ -204,7 +204,7 @@ static int qcom_icc_qos_set(struct icc_node *node)
}
}
-static int qcom_icc_rpm_set(struct qcom_icc_node *qn, u64 *bw)
+static int qcom_icc_rpm_set(struct qcom_icc_node *qn, u64 *bw, bool ignore_enxio)
{
int ret, rpm_ctx = 0;
u64 bw_bps;
@@ -222,8 +222,9 @@ static int qcom_icc_rpm_set(struct qcom_icc_node *qn, u64 *bw)
bw_bps);
if (ret) {
pr_err("qcom_icc_rpm_smd_send mas %d error %d\n",
- qn->mas_rpm_id, ret);
- return ret;
+ qn->mas_rpm_id, ret);
+ if (ret != -ENXIO || !ignore_enxio)
+ return ret;
}
}
@@ -234,8 +235,9 @@ static int qcom_icc_rpm_set(struct qcom_icc_node *qn, u64 *bw)
bw_bps);
if (ret) {
pr_err("qcom_icc_rpm_smd_send slv %d error %d\n",
- qn->slv_rpm_id, ret);
- return ret;
+ qn->slv_rpm_id, ret);
+ if (ret != -ENXIO || !ignore_enxio)
+ return ret;
}
}
}
@@ -361,12 +363,12 @@ static int qcom_icc_set(struct icc_node *src, struct icc_node *dst)
active_rate = agg_clk_rate[QCOM_SMD_RPM_ACTIVE_STATE];
sleep_rate = agg_clk_rate[QCOM_SMD_RPM_SLEEP_STATE];
- ret = qcom_icc_rpm_set(src_qn, src_qn->sum_avg);
+ ret = qcom_icc_rpm_set(src_qn, src_qn->sum_avg, qp->ignore_enxio);
if (ret)
return ret;
if (dst_qn) {
- ret = qcom_icc_rpm_set(dst_qn, dst_qn->sum_avg);
+ ret = qcom_icc_rpm_set(dst_qn, dst_qn->sum_avg, qp->ignore_enxio);
if (ret)
return ret;
}
@@ -509,6 +511,7 @@ int qnoc_probe(struct platform_device *pdev)
for (i = 0; i < cd_num; i++)
qp->intf_clks[i].id = cds[i];
+ qp->ignore_enxio = desc->ignore_enxio;
qp->keep_alive = desc->keep_alive;
qp->type = desc->type;
qp->qos_offset = desc->qos_offset;
@@ -553,6 +556,7 @@ regmap_done:
provider->aggregate = qcom_icc_bw_aggregate;
provider->xlate_extended = qcom_icc_xlate_extended;
provider->data = data;
+ provider->get_bw = desc->get_bw;
icc_provider_init(provider);
diff --git a/drivers/interconnect/qcom/icc-rpm.h b/drivers/interconnect/qcom/icc-rpm.h
index f4883d43eae4..7d1cb2efa9ee 100644
--- a/drivers/interconnect/qcom/icc-rpm.h
+++ b/drivers/interconnect/qcom/icc-rpm.h
@@ -51,7 +51,7 @@ struct rpm_clk_resource {
* @bus_clk: a pointer to a HLOS-owned bus clock
* @intf_clks: a clk_bulk_data array of interface clocks
* @keep_alive: whether to always keep a minimum vote on the bus clocks
- * @is_on: whether the bus is powered on
+ * @ignore_enxio: whether to ignore ENXIO errors (for MSM8974)
*/
struct qcom_icc_provider {
struct icc_provider provider;
@@ -66,7 +66,7 @@ struct qcom_icc_provider {
struct clk *bus_clk;
struct clk_bulk_data *intf_clks;
bool keep_alive;
- bool is_on;
+ bool ignore_enxio;
};
/**
@@ -137,6 +137,8 @@ struct qcom_icc_desc {
unsigned int qos_offset;
u16 ab_coeff;
u16 ib_coeff;
+ int (*get_bw)(struct icc_node *node, u32 *avg, u32 *peak);
+ bool ignore_enxio;
};
/* Valid for all bus types */
@@ -152,6 +154,7 @@ extern const struct rpm_clk_resource bimc_clk;
extern const struct rpm_clk_resource bus_0_clk;
extern const struct rpm_clk_resource bus_1_clk;
extern const struct rpm_clk_resource bus_2_clk;
+extern const struct rpm_clk_resource gpu_mem_2_clk;
extern const struct rpm_clk_resource mem_1_clk;
extern const struct rpm_clk_resource mmaxi_0_clk;
extern const struct rpm_clk_resource mmaxi_1_clk;
diff --git a/drivers/interconnect/qcom/msm8974.c b/drivers/interconnect/qcom/msm8974.c
index 3239edc37f02..c020c61126ca 100644
--- a/drivers/interconnect/qcom/msm8974.c
+++ b/drivers/interconnect/qcom/msm8974.c
@@ -173,76 +173,85 @@ enum {
MSM8974_SNOC_SLV_QDSS_STM,
};
-#define to_msm8974_icc_provider(_provider) \
- container_of(_provider, struct msm8974_icc_provider, provider)
+static int msm8974_get_bw(struct icc_node *node, u32 *avg, u32 *peak)
+{
+ *avg = 0;
+ *peak = 0;
-static const struct clk_bulk_data msm8974_icc_bus_clocks[] = {
- { .id = "bus" },
- { .id = "bus_a" },
+ return 0;
};
-/**
- * struct msm8974_icc_provider - Qualcomm specific interconnect provider
- * @provider: generic interconnect provider
- * @bus_clks: the clk_bulk_data table of bus clocks
- * @num_clks: the total number of clk_bulk_data entries
- */
-struct msm8974_icc_provider {
- struct icc_provider provider;
- struct clk_bulk_data *bus_clks;
- int num_clks;
-};
-
-#define MSM8974_ICC_MAX_LINKS 3
-
-/**
- * struct msm8974_icc_node - Qualcomm specific interconnect nodes
- * @name: the node name used in debugfs
- * @id: a unique node identifier
- * @links: an array of nodes where we can go next while traversing
- * @num_links: the total number of @links
- * @buswidth: width of the interconnect between a node and the bus (bytes)
- * @mas_rpm_id: RPM ID for devices that are bus masters
- * @slv_rpm_id: RPM ID for devices that are bus slaves
- * @rate: current bus clock rate in Hz
- */
-struct msm8974_icc_node {
- unsigned char *name;
- u16 id;
- u16 links[MSM8974_ICC_MAX_LINKS];
- u16 num_links;
- u16 buswidth;
- int mas_rpm_id;
- int slv_rpm_id;
- u64 rate;
-};
-
-struct msm8974_icc_desc {
- struct msm8974_icc_node * const *nodes;
- size_t num_nodes;
-};
-
-#define DEFINE_QNODE(_name, _id, _buswidth, _mas_rpm_id, _slv_rpm_id, \
- ...) \
- static struct msm8974_icc_node _name = { \
- .name = #_name, \
- .id = _id, \
- .buswidth = _buswidth, \
- .mas_rpm_id = _mas_rpm_id, \
- .slv_rpm_id = _slv_rpm_id, \
- .num_links = COUNT_ARGS(__VA_ARGS__), \
- .links = { __VA_ARGS__ }, \
- }
-
-DEFINE_QNODE(mas_ampss_m0, MSM8974_BIMC_MAS_AMPSS_M0, 8, 0, -1);
-DEFINE_QNODE(mas_ampss_m1, MSM8974_BIMC_MAS_AMPSS_M1, 8, 0, -1);
-DEFINE_QNODE(mas_mss_proc, MSM8974_BIMC_MAS_MSS_PROC, 8, 1, -1);
-DEFINE_QNODE(bimc_to_mnoc, MSM8974_BIMC_TO_MNOC, 8, 2, -1, MSM8974_BIMC_SLV_EBI_CH0);
-DEFINE_QNODE(bimc_to_snoc, MSM8974_BIMC_TO_SNOC, 8, 3, 2, MSM8974_SNOC_TO_BIMC, MSM8974_BIMC_SLV_EBI_CH0, MSM8974_BIMC_MAS_AMPSS_M0);
-DEFINE_QNODE(slv_ebi_ch0, MSM8974_BIMC_SLV_EBI_CH0, 8, -1, 0);
-DEFINE_QNODE(slv_ampss_l2, MSM8974_BIMC_SLV_AMPSS_L2, 8, -1, 1);
-
-static struct msm8974_icc_node * const msm8974_bimc_nodes[] = {
+static struct qcom_icc_node mas_ampss_m0 = {
+ .name = "mas_ampss_m0",
+ .id = MSM8974_BIMC_MAS_AMPSS_M0,
+ .buswidth = 8,
+ .mas_rpm_id = 0,
+ .slv_rpm_id = -1,
+};
+
+static struct qcom_icc_node mas_ampss_m1 = {
+ .name = "mas_ampss_m1",
+ .id = MSM8974_BIMC_MAS_AMPSS_M1,
+ .buswidth = 8,
+ .mas_rpm_id = 0,
+ .slv_rpm_id = -1,
+};
+
+static struct qcom_icc_node mas_mss_proc = {
+ .name = "mas_mss_proc",
+ .id = MSM8974_BIMC_MAS_MSS_PROC,
+ .buswidth = 8,
+ .mas_rpm_id = 1,
+ .slv_rpm_id = -1,
+};
+
+static const u16 bimc_to_mnoc_links[] = {
+ MSM8974_BIMC_SLV_EBI_CH0
+};
+
+static struct qcom_icc_node bimc_to_mnoc = {
+ .name = "bimc_to_mnoc",
+ .id = MSM8974_BIMC_TO_MNOC,
+ .buswidth = 8,
+ .mas_rpm_id = 2,
+ .slv_rpm_id = -1,
+ .num_links = ARRAY_SIZE(bimc_to_mnoc_links),
+ .links = bimc_to_mnoc_links,
+};
+
+static const u16 bimc_to_snoc_links[] = {
+ MSM8974_SNOC_TO_BIMC,
+ MSM8974_BIMC_SLV_EBI_CH0,
+ MSM8974_BIMC_MAS_AMPSS_M0
+};
+
+static struct qcom_icc_node bimc_to_snoc = {
+ .name = "bimc_to_snoc",
+ .id = MSM8974_BIMC_TO_SNOC,
+ .buswidth = 8,
+ .mas_rpm_id = 3,
+ .slv_rpm_id = 2,
+ .num_links = ARRAY_SIZE(bimc_to_snoc_links),
+ .links = bimc_to_snoc_links,
+};
+
+static struct qcom_icc_node slv_ebi_ch0 = {
+ .name = "slv_ebi_ch0",
+ .id = MSM8974_BIMC_SLV_EBI_CH0,
+ .buswidth = 8,
+ .mas_rpm_id = -1,
+ .slv_rpm_id = 0,
+};
+
+static struct qcom_icc_node slv_ampss_l2 = {
+ .name = "slv_ampss_l2",
+ .id = MSM8974_BIMC_SLV_AMPSS_L2,
+ .buswidth = 8,
+ .mas_rpm_id = -1,
+ .slv_rpm_id = 1,
+};
+
+static struct qcom_icc_node * const msm8974_bimc_nodes[] = {
[BIMC_MAS_AMPSS_M0] = &mas_ampss_m0,
[BIMC_MAS_AMPSS_M1] = &mas_ampss_m1,
[BIMC_MAS_MSS_PROC] = &mas_mss_proc,
@@ -252,50 +261,311 @@ static struct msm8974_icc_node * const msm8974_bimc_nodes[] = {
[BIMC_SLV_AMPSS_L2] = &slv_ampss_l2,
};
-static const struct msm8974_icc_desc msm8974_bimc = {
+static const struct qcom_icc_desc msm8974_bimc = {
.nodes = msm8974_bimc_nodes,
.num_nodes = ARRAY_SIZE(msm8974_bimc_nodes),
+ .bus_clk_desc = &bimc_clk,
+ .get_bw = msm8974_get_bw,
+ .ignore_enxio = true,
+};
+
+static struct qcom_icc_node mas_rpm_inst = {
+ .name = "mas_rpm_inst",
+ .id = MSM8974_CNOC_MAS_RPM_INST,
+ .buswidth = 8,
+ .mas_rpm_id = 45,
+ .slv_rpm_id = -1,
+};
+
+static struct qcom_icc_node mas_rpm_data = {
+ .name = "mas_rpm_data",
+ .id = MSM8974_CNOC_MAS_RPM_DATA,
+ .buswidth = 8,
+ .mas_rpm_id = 46,
+ .slv_rpm_id = -1,
+};
+
+static struct qcom_icc_node mas_rpm_sys = {
+ .name = "mas_rpm_sys",
+ .id = MSM8974_CNOC_MAS_RPM_SYS,
+ .buswidth = 8,
+ .mas_rpm_id = 47,
+ .slv_rpm_id = -1,
+};
+
+static struct qcom_icc_node mas_dehr = {
+ .name = "mas_dehr",
+ .id = MSM8974_CNOC_MAS_DEHR,
+ .buswidth = 8,
+ .mas_rpm_id = 48,
+ .slv_rpm_id = -1,
+};
+
+static struct qcom_icc_node mas_qdss_dap = {
+ .name = "mas_qdss_dap",
+ .id = MSM8974_CNOC_MAS_QDSS_DAP,
+ .buswidth = 8,
+ .mas_rpm_id = 49,
+ .slv_rpm_id = -1,
+};
+
+static struct qcom_icc_node mas_spdm = {
+ .name = "mas_spdm",
+ .id = MSM8974_CNOC_MAS_SPDM,
+ .buswidth = 8,
+ .mas_rpm_id = 50,
+ .slv_rpm_id = -1,
+};
+
+static struct qcom_icc_node mas_tic = {
+ .name = "mas_tic",
+ .id = MSM8974_CNOC_MAS_TIC,
+ .buswidth = 8,
+ .mas_rpm_id = 51,
+ .slv_rpm_id = -1,
+};
+
+static struct qcom_icc_node slv_clk_ctl = {
+ .name = "slv_clk_ctl",
+ .id = MSM8974_CNOC_SLV_CLK_CTL,
+ .buswidth = 8,
+ .mas_rpm_id = -1,
+ .slv_rpm_id = 47,
+};
+
+static struct qcom_icc_node slv_cnoc_mss = {
+ .name = "slv_cnoc_mss",
+ .id = MSM8974_CNOC_SLV_CNOC_MSS,
+ .buswidth = 8,
+ .mas_rpm_id = -1,
+ .slv_rpm_id = 48,
+};
+
+static struct qcom_icc_node slv_security = {
+ .name = "slv_security",
+ .id = MSM8974_CNOC_SLV_SECURITY,
+ .buswidth = 8,
+ .mas_rpm_id = -1,
+ .slv_rpm_id = 49,
+};
+
+static struct qcom_icc_node slv_tcsr = {
+ .name = "slv_tcsr",
+ .id = MSM8974_CNOC_SLV_TCSR,
+ .buswidth = 8,
+ .mas_rpm_id = -1,
+ .slv_rpm_id = 50,
+};
+
+static struct qcom_icc_node slv_tlmm = {
+ .name = "slv_tlmm",
+ .id = MSM8974_CNOC_SLV_TLMM,
+ .buswidth = 8,
+ .mas_rpm_id = -1,
+ .slv_rpm_id = 51,
+};
+
+static struct qcom_icc_node slv_crypto_0_cfg = {
+ .name = "slv_crypto_0_cfg",
+ .id = MSM8974_CNOC_SLV_CRYPTO_0_CFG,
+ .buswidth = 8,
+ .mas_rpm_id = -1,
+ .slv_rpm_id = 52,
+};
+
+static struct qcom_icc_node slv_crypto_1_cfg = {
+ .name = "slv_crypto_1_cfg",
+ .id = MSM8974_CNOC_SLV_CRYPTO_1_CFG,
+ .buswidth = 8,
+ .mas_rpm_id = -1,
+ .slv_rpm_id = 53,
+};
+
+static struct qcom_icc_node slv_imem_cfg = {
+ .name = "slv_imem_cfg",
+ .id = MSM8974_CNOC_SLV_IMEM_CFG,
+ .buswidth = 8,
+ .mas_rpm_id = -1,
+ .slv_rpm_id = 54,
+};
+
+static struct qcom_icc_node slv_message_ram = {
+ .name = "slv_message_ram",
+ .id = MSM8974_CNOC_SLV_MESSAGE_RAM,
+ .buswidth = 8,
+ .mas_rpm_id = -1,
+ .slv_rpm_id = 55,
+};
+
+static struct qcom_icc_node slv_bimc_cfg = {
+ .name = "slv_bimc_cfg",
+ .id = MSM8974_CNOC_SLV_BIMC_CFG,
+ .buswidth = 8,
+ .mas_rpm_id = -1,
+ .slv_rpm_id = 56,
+};
+
+static struct qcom_icc_node slv_boot_rom = {
+ .name = "slv_boot_rom",
+ .id = MSM8974_CNOC_SLV_BOOT_ROM,
+ .buswidth = 8,
+ .mas_rpm_id = -1,
+ .slv_rpm_id = 57,
+};
+
+static struct qcom_icc_node slv_pmic_arb = {
+ .name = "slv_pmic_arb",
+ .id = MSM8974_CNOC_SLV_PMIC_ARB,
+ .buswidth = 8,
+ .mas_rpm_id = -1,
+ .slv_rpm_id = 59,
+};
+
+static struct qcom_icc_node slv_spdm_wrapper = {
+ .name = "slv_spdm_wrapper",
+ .id = MSM8974_CNOC_SLV_SPDM_WRAPPER,
+ .buswidth = 8,
+ .mas_rpm_id = -1,
+ .slv_rpm_id = 60,
+};
+
+static struct qcom_icc_node slv_dehr_cfg = {
+ .name = "slv_dehr_cfg",
+ .id = MSM8974_CNOC_SLV_DEHR_CFG,
+ .buswidth = 8,
+ .mas_rpm_id = -1,
+ .slv_rpm_id = 61,
+};
+
+static struct qcom_icc_node slv_mpm = {
+ .name = "slv_mpm",
+ .id = MSM8974_CNOC_SLV_MPM,
+ .buswidth = 8,
+ .mas_rpm_id = -1,
+ .slv_rpm_id = 62,
+};
+
+static struct qcom_icc_node slv_qdss_cfg = {
+ .name = "slv_qdss_cfg",
+ .id = MSM8974_CNOC_SLV_QDSS_CFG,
+ .buswidth = 8,
+ .mas_rpm_id = -1,
+ .slv_rpm_id = 63,
+};
+
+static struct qcom_icc_node slv_rbcpr_cfg = {
+ .name = "slv_rbcpr_cfg",
+ .id = MSM8974_CNOC_SLV_RBCPR_CFG,
+ .buswidth = 8,
+ .mas_rpm_id = -1,
+ .slv_rpm_id = 64,
+};
+
+static struct qcom_icc_node slv_rbcpr_qdss_apu_cfg = {
+ .name = "slv_rbcpr_qdss_apu_cfg",
+ .id = MSM8974_CNOC_SLV_RBCPR_QDSS_APU_CFG,
+ .buswidth = 8,
+ .mas_rpm_id = -1,
+ .slv_rpm_id = 65,
+};
+
+static struct qcom_icc_node cnoc_to_snoc = {
+ .name = "cnoc_to_snoc",
+ .id = MSM8974_CNOC_TO_SNOC,
+ .buswidth = 8,
+ .mas_rpm_id = 52,
+ .slv_rpm_id = 75,
+};
+
+static struct qcom_icc_node slv_cnoc_onoc_cfg = {
+ .name = "slv_cnoc_onoc_cfg",
+ .id = MSM8974_CNOC_SLV_CNOC_ONOC_CFG,
+ .buswidth = 8,
+ .mas_rpm_id = -1,
+ .slv_rpm_id = 68,
+};
+
+static struct qcom_icc_node slv_cnoc_mnoc_mmss_cfg = {
+ .name = "slv_cnoc_mnoc_mmss_cfg",
+ .id = MSM8974_CNOC_SLV_CNOC_MNOC_MMSS_CFG,
+ .buswidth = 8,
+ .mas_rpm_id = -1,
+ .slv_rpm_id = 58,
+};
+
+static struct qcom_icc_node slv_cnoc_mnoc_cfg = {
+ .name = "slv_cnoc_mnoc_cfg",
+ .id = MSM8974_CNOC_SLV_CNOC_MNOC_CFG,
+ .buswidth = 8,
+ .mas_rpm_id = -1,
+ .slv_rpm_id = 66,
+};
+
+static struct qcom_icc_node slv_pnoc_cfg = {
+ .name = "slv_pnoc_cfg",
+ .id = MSM8974_CNOC_SLV_PNOC_CFG,
+ .buswidth = 8,
+ .mas_rpm_id = -1,
+ .slv_rpm_id = 69,
+};
+
+static struct qcom_icc_node slv_snoc_mpu_cfg = {
+ .name = "slv_snoc_mpu_cfg",
+ .id = MSM8974_CNOC_SLV_SNOC_MPU_CFG,
+ .buswidth = 8,
+ .mas_rpm_id = -1,
+ .slv_rpm_id = 67,
};
-DEFINE_QNODE(mas_rpm_inst, MSM8974_CNOC_MAS_RPM_INST, 8, 45, -1);
-DEFINE_QNODE(mas_rpm_data, MSM8974_CNOC_MAS_RPM_DATA, 8, 46, -1);
-DEFINE_QNODE(mas_rpm_sys, MSM8974_CNOC_MAS_RPM_SYS, 8, 47, -1);
-DEFINE_QNODE(mas_dehr, MSM8974_CNOC_MAS_DEHR, 8, 48, -1);
-DEFINE_QNODE(mas_qdss_dap, MSM8974_CNOC_MAS_QDSS_DAP, 8, 49, -1);
-DEFINE_QNODE(mas_spdm, MSM8974_CNOC_MAS_SPDM, 8, 50, -1);
-DEFINE_QNODE(mas_tic, MSM8974_CNOC_MAS_TIC, 8, 51, -1);
-DEFINE_QNODE(slv_clk_ctl, MSM8974_CNOC_SLV_CLK_CTL, 8, -1, 47);
-DEFINE_QNODE(slv_cnoc_mss, MSM8974_CNOC_SLV_CNOC_MSS, 8, -1, 48);
-DEFINE_QNODE(slv_security, MSM8974_CNOC_SLV_SECURITY, 8, -1, 49);
-DEFINE_QNODE(slv_tcsr, MSM8974_CNOC_SLV_TCSR, 8, -1, 50);
-DEFINE_QNODE(slv_tlmm, MSM8974_CNOC_SLV_TLMM, 8, -1, 51);
-DEFINE_QNODE(slv_crypto_0_cfg, MSM8974_CNOC_SLV_CRYPTO_0_CFG, 8, -1, 52);
-DEFINE_QNODE(slv_crypto_1_cfg, MSM8974_CNOC_SLV_CRYPTO_1_CFG, 8, -1, 53);
-DEFINE_QNODE(slv_imem_cfg, MSM8974_CNOC_SLV_IMEM_CFG, 8, -1, 54);
-DEFINE_QNODE(slv_message_ram, MSM8974_CNOC_SLV_MESSAGE_RAM, 8, -1, 55);
-DEFINE_QNODE(slv_bimc_cfg, MSM8974_CNOC_SLV_BIMC_CFG, 8, -1, 56);
-DEFINE_QNODE(slv_boot_rom, MSM8974_CNOC_SLV_BOOT_ROM, 8, -1, 57);
-DEFINE_QNODE(slv_pmic_arb, MSM8974_CNOC_SLV_PMIC_ARB, 8, -1, 59);
-DEFINE_QNODE(slv_spdm_wrapper, MSM8974_CNOC_SLV_SPDM_WRAPPER, 8, -1, 60);
-DEFINE_QNODE(slv_dehr_cfg, MSM8974_CNOC_SLV_DEHR_CFG, 8, -1, 61);
-DEFINE_QNODE(slv_mpm, MSM8974_CNOC_SLV_MPM, 8, -1, 62);
-DEFINE_QNODE(slv_qdss_cfg, MSM8974_CNOC_SLV_QDSS_CFG, 8, -1, 63);
-DEFINE_QNODE(slv_rbcpr_cfg, MSM8974_CNOC_SLV_RBCPR_CFG, 8, -1, 64);
-DEFINE_QNODE(slv_rbcpr_qdss_apu_cfg, MSM8974_CNOC_SLV_RBCPR_QDSS_APU_CFG, 8, -1, 65);
-DEFINE_QNODE(cnoc_to_snoc, MSM8974_CNOC_TO_SNOC, 8, 52, 75);
-DEFINE_QNODE(slv_cnoc_onoc_cfg, MSM8974_CNOC_SLV_CNOC_ONOC_CFG, 8, -1, 68);
-DEFINE_QNODE(slv_cnoc_mnoc_mmss_cfg, MSM8974_CNOC_SLV_CNOC_MNOC_MMSS_CFG, 8, -1, 58);
-DEFINE_QNODE(slv_cnoc_mnoc_cfg, MSM8974_CNOC_SLV_CNOC_MNOC_CFG, 8, -1, 66);
-DEFINE_QNODE(slv_pnoc_cfg, MSM8974_CNOC_SLV_PNOC_CFG, 8, -1, 69);
-DEFINE_QNODE(slv_snoc_mpu_cfg, MSM8974_CNOC_SLV_SNOC_MPU_CFG, 8, -1, 67);
-DEFINE_QNODE(slv_snoc_cfg, MSM8974_CNOC_SLV_SNOC_CFG, 8, -1, 70);
-DEFINE_QNODE(slv_ebi1_dll_cfg, MSM8974_CNOC_SLV_EBI1_DLL_CFG, 8, -1, 71);
-DEFINE_QNODE(slv_phy_apu_cfg, MSM8974_CNOC_SLV_PHY_APU_CFG, 8, -1, 72);
-DEFINE_QNODE(slv_ebi1_phy_cfg, MSM8974_CNOC_SLV_EBI1_PHY_CFG, 8, -1, 73);
-DEFINE_QNODE(slv_rpm, MSM8974_CNOC_SLV_RPM, 8, -1, 74);
-DEFINE_QNODE(slv_service_cnoc, MSM8974_CNOC_SLV_SERVICE_CNOC, 8, -1, 76);
-
-static struct msm8974_icc_node * const msm8974_cnoc_nodes[] = {
+static struct qcom_icc_node slv_snoc_cfg = {
+ .name = "slv_snoc_cfg",
+ .id = MSM8974_CNOC_SLV_SNOC_CFG,
+ .buswidth = 8,
+ .mas_rpm_id = -1,
+ .slv_rpm_id = 70,
+};
+
+static struct qcom_icc_node slv_ebi1_dll_cfg = {
+ .name = "slv_ebi1_dll_cfg",
+ .id = MSM8974_CNOC_SLV_EBI1_DLL_CFG,
+ .buswidth = 8,
+ .mas_rpm_id = -1,
+ .slv_rpm_id = 71,
+};
+
+static struct qcom_icc_node slv_phy_apu_cfg = {
+ .name = "slv_phy_apu_cfg",
+ .id = MSM8974_CNOC_SLV_PHY_APU_CFG,
+ .buswidth = 8,
+ .mas_rpm_id = -1,
+ .slv_rpm_id = 72,
+};
+
+static struct qcom_icc_node slv_ebi1_phy_cfg = {
+ .name = "slv_ebi1_phy_cfg",
+ .id = MSM8974_CNOC_SLV_EBI1_PHY_CFG,
+ .buswidth = 8,
+ .mas_rpm_id = -1,
+ .slv_rpm_id = 73,
+};
+
+static struct qcom_icc_node slv_rpm = {
+ .name = "slv_rpm",
+ .id = MSM8974_CNOC_SLV_RPM,
+ .buswidth = 8,
+ .mas_rpm_id = -1,
+ .slv_rpm_id = 74,
+};
+
+static struct qcom_icc_node slv_service_cnoc = {
+ .name = "slv_service_cnoc",
+ .id = MSM8974_CNOC_SLV_SERVICE_CNOC,
+ .buswidth = 8,
+ .mas_rpm_id = -1,
+ .slv_rpm_id = 76,
+};
+
+static struct qcom_icc_node * const msm8974_cnoc_nodes[] = {
[CNOC_MAS_RPM_INST] = &mas_rpm_inst,
[CNOC_MAS_RPM_DATA] = &mas_rpm_data,
[CNOC_MAS_RPM_SYS] = &mas_rpm_sys,
@@ -335,35 +605,221 @@ static struct msm8974_icc_node * const msm8974_cnoc_nodes[] = {
[CNOC_SLV_SERVICE_CNOC] = &slv_service_cnoc,
};
-static const struct msm8974_icc_desc msm8974_cnoc = {
+static const struct qcom_icc_desc msm8974_cnoc = {
.nodes = msm8974_cnoc_nodes,
.num_nodes = ARRAY_SIZE(msm8974_cnoc_nodes),
+ .bus_clk_desc = &bus_2_clk,
+ .get_bw = msm8974_get_bw,
+ .ignore_enxio = true,
};
-DEFINE_QNODE(mas_graphics_3d, MSM8974_MNOC_MAS_GRAPHICS_3D, 16, 6, -1, MSM8974_MNOC_TO_BIMC);
-DEFINE_QNODE(mas_jpeg, MSM8974_MNOC_MAS_JPEG, 16, 7, -1, MSM8974_MNOC_TO_BIMC);
-DEFINE_QNODE(mas_mdp_port0, MSM8974_MNOC_MAS_MDP_PORT0, 16, 8, -1, MSM8974_MNOC_TO_BIMC);
-DEFINE_QNODE(mas_video_p0, MSM8974_MNOC_MAS_VIDEO_P0, 16, 9, -1);
-DEFINE_QNODE(mas_video_p1, MSM8974_MNOC_MAS_VIDEO_P1, 16, 10, -1);
-DEFINE_QNODE(mas_vfe, MSM8974_MNOC_MAS_VFE, 16, 11, -1, MSM8974_MNOC_TO_BIMC);
-DEFINE_QNODE(mnoc_to_cnoc, MSM8974_MNOC_TO_CNOC, 16, 4, -1);
-DEFINE_QNODE(mnoc_to_bimc, MSM8974_MNOC_TO_BIMC, 16, -1, 16, MSM8974_BIMC_TO_MNOC);
-DEFINE_QNODE(slv_camera_cfg, MSM8974_MNOC_SLV_CAMERA_CFG, 16, -1, 3);
-DEFINE_QNODE(slv_display_cfg, MSM8974_MNOC_SLV_DISPLAY_CFG, 16, -1, 4);
-DEFINE_QNODE(slv_ocmem_cfg, MSM8974_MNOC_SLV_OCMEM_CFG, 16, -1, 5);
-DEFINE_QNODE(slv_cpr_cfg, MSM8974_MNOC_SLV_CPR_CFG, 16, -1, 6);
-DEFINE_QNODE(slv_cpr_xpu_cfg, MSM8974_MNOC_SLV_CPR_XPU_CFG, 16, -1, 7);
-DEFINE_QNODE(slv_misc_cfg, MSM8974_MNOC_SLV_MISC_CFG, 16, -1, 8);
-DEFINE_QNODE(slv_misc_xpu_cfg, MSM8974_MNOC_SLV_MISC_XPU_CFG, 16, -1, 9);
-DEFINE_QNODE(slv_venus_cfg, MSM8974_MNOC_SLV_VENUS_CFG, 16, -1, 10);
-DEFINE_QNODE(slv_graphics_3d_cfg, MSM8974_MNOC_SLV_GRAPHICS_3D_CFG, 16, -1, 11);
-DEFINE_QNODE(slv_mmss_clk_cfg, MSM8974_MNOC_SLV_MMSS_CLK_CFG, 16, -1, 12);
-DEFINE_QNODE(slv_mmss_clk_xpu_cfg, MSM8974_MNOC_SLV_MMSS_CLK_XPU_CFG, 16, -1, 13);
-DEFINE_QNODE(slv_mnoc_mpu_cfg, MSM8974_MNOC_SLV_MNOC_MPU_CFG, 16, -1, 14);
-DEFINE_QNODE(slv_onoc_mpu_cfg, MSM8974_MNOC_SLV_ONOC_MPU_CFG, 16, -1, 15);
-DEFINE_QNODE(slv_service_mnoc, MSM8974_MNOC_SLV_SERVICE_MNOC, 16, -1, 17);
-
-static struct msm8974_icc_node * const msm8974_mnoc_nodes[] = {
+static const u16 mas_graphics_3d_links[] = {
+ MSM8974_MNOC_TO_BIMC
+};
+
+static struct qcom_icc_node mas_graphics_3d = {
+ .name = "mas_graphics_3d",
+ .id = MSM8974_MNOC_MAS_GRAPHICS_3D,
+ .buswidth = 16,
+ .mas_rpm_id = 6,
+ .slv_rpm_id = -1,
+ .num_links = ARRAY_SIZE(mas_graphics_3d_links),
+ .links = mas_graphics_3d_links,
+};
+
+static const u16 mas_jpeg_links[] = {
+ MSM8974_MNOC_TO_BIMC
+};
+
+static struct qcom_icc_node mas_jpeg = {
+ .name = "mas_jpeg",
+ .id = MSM8974_MNOC_MAS_JPEG,
+ .buswidth = 16,
+ .mas_rpm_id = 7,
+ .slv_rpm_id = -1,
+ .num_links = ARRAY_SIZE(mas_jpeg_links),
+ .links = mas_jpeg_links,
+};
+
+static const u16 mas_mdp_port0_links[] = {
+ MSM8974_MNOC_TO_BIMC
+};
+
+static struct qcom_icc_node mas_mdp_port0 = {
+ .name = "mas_mdp_port0",
+ .id = MSM8974_MNOC_MAS_MDP_PORT0,
+ .buswidth = 16,
+ .mas_rpm_id = 8,
+ .slv_rpm_id = -1,
+ .num_links = ARRAY_SIZE(mas_mdp_port0_links),
+ .links = mas_mdp_port0_links,
+};
+
+static struct qcom_icc_node mas_video_p0 = {
+ .name = "mas_video_p0",
+ .id = MSM8974_MNOC_MAS_VIDEO_P0,
+ .buswidth = 16,
+ .mas_rpm_id = 9,
+ .slv_rpm_id = -1,
+};
+
+static struct qcom_icc_node mas_video_p1 = {
+ .name = "mas_video_p1",
+ .id = MSM8974_MNOC_MAS_VIDEO_P1,
+ .buswidth = 16,
+ .mas_rpm_id = 10,
+ .slv_rpm_id = -1,
+};
+
+static const u16 mas_vfe_links[] = {
+ MSM8974_MNOC_TO_BIMC
+};
+
+static struct qcom_icc_node mas_vfe = {
+ .name = "mas_vfe",
+ .id = MSM8974_MNOC_MAS_VFE,
+ .buswidth = 16,
+ .mas_rpm_id = 11,
+ .slv_rpm_id = -1,
+ .num_links = ARRAY_SIZE(mas_vfe_links),
+ .links = mas_vfe_links,
+};
+
+static struct qcom_icc_node mnoc_to_cnoc = {
+ .name = "mnoc_to_cnoc",
+ .id = MSM8974_MNOC_TO_CNOC,
+ .buswidth = 16,
+ .mas_rpm_id = 4,
+ .slv_rpm_id = -1,
+};
+
+static const u16 mnoc_to_bimc_links[] = {
+ MSM8974_BIMC_TO_MNOC
+};
+
+static struct qcom_icc_node mnoc_to_bimc = {
+ .name = "mnoc_to_bimc",
+ .id = MSM8974_MNOC_TO_BIMC,
+ .buswidth = 16,
+ .mas_rpm_id = -1,
+ .slv_rpm_id = 16,
+ .num_links = ARRAY_SIZE(mnoc_to_bimc_links),
+ .links = mnoc_to_bimc_links,
+};
+
+static struct qcom_icc_node slv_camera_cfg = {
+ .name = "slv_camera_cfg",
+ .id = MSM8974_MNOC_SLV_CAMERA_CFG,
+ .buswidth = 16,
+ .mas_rpm_id = -1,
+ .slv_rpm_id = 3,
+};
+
+static struct qcom_icc_node slv_display_cfg = {
+ .name = "slv_display_cfg",
+ .id = MSM8974_MNOC_SLV_DISPLAY_CFG,
+ .buswidth = 16,
+ .mas_rpm_id = -1,
+ .slv_rpm_id = 4,
+};
+
+static struct qcom_icc_node slv_ocmem_cfg = {
+ .name = "slv_ocmem_cfg",
+ .id = MSM8974_MNOC_SLV_OCMEM_CFG,
+ .buswidth = 16,
+ .mas_rpm_id = -1,
+ .slv_rpm_id = 5,
+};
+
+static struct qcom_icc_node slv_cpr_cfg = {
+ .name = "slv_cpr_cfg",
+ .id = MSM8974_MNOC_SLV_CPR_CFG,
+ .buswidth = 16,
+ .mas_rpm_id = -1,
+ .slv_rpm_id = 6,
+};
+
+static struct qcom_icc_node slv_cpr_xpu_cfg = {
+ .name = "slv_cpr_xpu_cfg",
+ .id = MSM8974_MNOC_SLV_CPR_XPU_CFG,
+ .buswidth = 16,
+ .mas_rpm_id = -1,
+ .slv_rpm_id = 7,
+};
+
+static struct qcom_icc_node slv_misc_cfg = {
+ .name = "slv_misc_cfg",
+ .id = MSM8974_MNOC_SLV_MISC_CFG,
+ .buswidth = 16,
+ .mas_rpm_id = -1,
+ .slv_rpm_id = 8,
+};
+
+static struct qcom_icc_node slv_misc_xpu_cfg = {
+ .name = "slv_misc_xpu_cfg",
+ .id = MSM8974_MNOC_SLV_MISC_XPU_CFG,
+ .buswidth = 16,
+ .mas_rpm_id = -1,
+ .slv_rpm_id = 9,
+};
+
+static struct qcom_icc_node slv_venus_cfg = {
+ .name = "slv_venus_cfg",
+ .id = MSM8974_MNOC_SLV_VENUS_CFG,
+ .buswidth = 16,
+ .mas_rpm_id = -1,
+ .slv_rpm_id = 10,
+};
+
+static struct qcom_icc_node slv_graphics_3d_cfg = {
+ .name = "slv_graphics_3d_cfg",
+ .id = MSM8974_MNOC_SLV_GRAPHICS_3D_CFG,
+ .buswidth = 16,
+ .mas_rpm_id = -1,
+ .slv_rpm_id = 11,
+};
+
+static struct qcom_icc_node slv_mmss_clk_cfg = {
+ .name = "slv_mmss_clk_cfg",
+ .id = MSM8974_MNOC_SLV_MMSS_CLK_CFG,
+ .buswidth = 16,
+ .mas_rpm_id = -1,
+ .slv_rpm_id = 12,
+};
+
+static struct qcom_icc_node slv_mmss_clk_xpu_cfg = {
+ .name = "slv_mmss_clk_xpu_cfg",
+ .id = MSM8974_MNOC_SLV_MMSS_CLK_XPU_CFG,
+ .buswidth = 16,
+ .mas_rpm_id = -1,
+ .slv_rpm_id = 13,
+};
+
+static struct qcom_icc_node slv_mnoc_mpu_cfg = {
+ .name = "slv_mnoc_mpu_cfg",
+ .id = MSM8974_MNOC_SLV_MNOC_MPU_CFG,
+ .buswidth = 16,
+ .mas_rpm_id = -1,
+ .slv_rpm_id = 14,
+};
+
+static struct qcom_icc_node slv_onoc_mpu_cfg = {
+ .name = "slv_onoc_mpu_cfg",
+ .id = MSM8974_MNOC_SLV_ONOC_MPU_CFG,
+ .buswidth = 16,
+ .mas_rpm_id = -1,
+ .slv_rpm_id = 15,
+};
+
+static struct qcom_icc_node slv_service_mnoc = {
+ .name = "slv_service_mnoc",
+ .id = MSM8974_MNOC_SLV_SERVICE_MNOC,
+ .buswidth = 16,
+ .mas_rpm_id = -1,
+ .slv_rpm_id = 17,
+};
+
+static struct qcom_icc_node * const msm8974_mnoc_nodes[] = {
[MNOC_MAS_GRAPHICS_3D] = &mas_graphics_3d,
[MNOC_MAS_JPEG] = &mas_jpeg,
[MNOC_MAS_MDP_PORT0] = &mas_mdp_port0,
@@ -388,27 +844,130 @@ static struct msm8974_icc_node * const msm8974_mnoc_nodes[] = {
[MNOC_SLV_SERVICE_MNOC] = &slv_service_mnoc,
};
-static const struct msm8974_icc_desc msm8974_mnoc = {
+static const struct qcom_icc_desc msm8974_mnoc = {
.nodes = msm8974_mnoc_nodes,
.num_nodes = ARRAY_SIZE(msm8974_mnoc_nodes),
+ .get_bw = msm8974_get_bw,
+ .ignore_enxio = true,
+};
+
+static const u16 ocmem_noc_to_ocmem_vnoc_links[] = {
+ MSM8974_OCMEM_SLV_OCMEM
+};
+
+static struct qcom_icc_node ocmem_noc_to_ocmem_vnoc = {
+ .name = "ocmem_noc_to_ocmem_vnoc",
+ .id = MSM8974_OCMEM_NOC_TO_OCMEM_VNOC,
+ .buswidth = 16,
+ .mas_rpm_id = 54,
+ .slv_rpm_id = 78,
+ .num_links = ARRAY_SIZE(ocmem_noc_to_ocmem_vnoc_links),
+ .links = ocmem_noc_to_ocmem_vnoc_links,
+};
+
+static struct qcom_icc_node mas_jpeg_ocmem = {
+ .name = "mas_jpeg_ocmem",
+ .id = MSM8974_OCMEM_MAS_JPEG_OCMEM,
+ .buswidth = 16,
+ .mas_rpm_id = 13,
+ .slv_rpm_id = -1,
+};
+
+static struct qcom_icc_node mas_mdp_ocmem = {
+ .name = "mas_mdp_ocmem",
+ .id = MSM8974_OCMEM_MAS_MDP_OCMEM,
+ .buswidth = 16,
+ .mas_rpm_id = 14,
+ .slv_rpm_id = -1,
+};
+
+static struct qcom_icc_node mas_video_p0_ocmem = {
+ .name = "mas_video_p0_ocmem",
+ .id = MSM8974_OCMEM_MAS_VIDEO_P0_OCMEM,
+ .buswidth = 16,
+ .mas_rpm_id = 15,
+ .slv_rpm_id = -1,
+};
+
+static struct qcom_icc_node mas_video_p1_ocmem = {
+ .name = "mas_video_p1_ocmem",
+ .id = MSM8974_OCMEM_MAS_VIDEO_P1_OCMEM,
+ .buswidth = 16,
+ .mas_rpm_id = 16,
+ .slv_rpm_id = -1,
};
-DEFINE_QNODE(ocmem_noc_to_ocmem_vnoc, MSM8974_OCMEM_NOC_TO_OCMEM_VNOC, 16, 54, 78, MSM8974_OCMEM_SLV_OCMEM);
-DEFINE_QNODE(mas_jpeg_ocmem, MSM8974_OCMEM_MAS_JPEG_OCMEM, 16, 13, -1);
-DEFINE_QNODE(mas_mdp_ocmem, MSM8974_OCMEM_MAS_MDP_OCMEM, 16, 14, -1);
-DEFINE_QNODE(mas_video_p0_ocmem, MSM8974_OCMEM_MAS_VIDEO_P0_OCMEM, 16, 15, -1);
-DEFINE_QNODE(mas_video_p1_ocmem, MSM8974_OCMEM_MAS_VIDEO_P1_OCMEM, 16, 16, -1);
-DEFINE_QNODE(mas_vfe_ocmem, MSM8974_OCMEM_MAS_VFE_OCMEM, 16, 17, -1);
-DEFINE_QNODE(mas_cnoc_onoc_cfg, MSM8974_OCMEM_MAS_CNOC_ONOC_CFG, 16, 12, -1);
-DEFINE_QNODE(slv_service_onoc, MSM8974_OCMEM_SLV_SERVICE_ONOC, 16, -1, 19);
-DEFINE_QNODE(slv_ocmem, MSM8974_OCMEM_SLV_OCMEM, 16, -1, 18);
+static struct qcom_icc_node mas_vfe_ocmem = {
+ .name = "mas_vfe_ocmem",
+ .id = MSM8974_OCMEM_MAS_VFE_OCMEM,
+ .buswidth = 16,
+ .mas_rpm_id = 17,
+ .slv_rpm_id = -1,
+};
+
+static struct qcom_icc_node mas_cnoc_onoc_cfg = {
+ .name = "mas_cnoc_onoc_cfg",
+ .id = MSM8974_OCMEM_MAS_CNOC_ONOC_CFG,
+ .buswidth = 16,
+ .mas_rpm_id = 12,
+ .slv_rpm_id = -1,
+};
+
+static struct qcom_icc_node slv_service_onoc = {
+ .name = "slv_service_onoc",
+ .id = MSM8974_OCMEM_SLV_SERVICE_ONOC,
+ .buswidth = 16,
+ .mas_rpm_id = -1,
+ .slv_rpm_id = 19,
+};
+
+static struct qcom_icc_node slv_ocmem = {
+ .name = "slv_ocmem",
+ .id = MSM8974_OCMEM_SLV_OCMEM,
+ .buswidth = 16,
+ .mas_rpm_id = -1,
+ .slv_rpm_id = 18,
+};
/* Virtual NoC is needed for connection to OCMEM */
-DEFINE_QNODE(ocmem_vnoc_to_onoc, MSM8974_OCMEM_VNOC_TO_OCMEM_NOC, 16, 56, 79, MSM8974_OCMEM_NOC_TO_OCMEM_VNOC);
-DEFINE_QNODE(ocmem_vnoc_to_snoc, MSM8974_OCMEM_VNOC_TO_SNOC, 8, 57, 80);
-DEFINE_QNODE(mas_v_ocmem_gfx3d, MSM8974_OCMEM_VNOC_MAS_GFX3D, 8, 55, -1, MSM8974_OCMEM_VNOC_TO_OCMEM_NOC);
+static const u16 ocmem_vnoc_to_onoc_links[] = {
+ MSM8974_OCMEM_NOC_TO_OCMEM_VNOC
+};
-static struct msm8974_icc_node * const msm8974_onoc_nodes[] = {
+static struct qcom_icc_node ocmem_vnoc_to_onoc = {
+ .name = "ocmem_vnoc_to_onoc",
+ .id = MSM8974_OCMEM_VNOC_TO_OCMEM_NOC,
+ .buswidth = 16,
+ .mas_rpm_id = 56,
+ .slv_rpm_id = 79,
+ .num_links = ARRAY_SIZE(ocmem_vnoc_to_onoc_links),
+ .links = ocmem_vnoc_to_onoc_links,
+};
+
+static struct qcom_icc_node ocmem_vnoc_to_snoc = {
+ .name = "ocmem_vnoc_to_snoc",
+ .id = MSM8974_OCMEM_VNOC_TO_SNOC,
+ .buswidth = 8,
+ .mas_rpm_id = 57,
+ .slv_rpm_id = 80,
+};
+
+static const u16 mas_v_ocmem_gfx3d_links[] = {
+ MSM8974_OCMEM_VNOC_TO_OCMEM_NOC
+};
+
+static struct qcom_icc_node mas_v_ocmem_gfx3d = {
+ .name = "mas_v_ocmem_gfx3d",
+ .id = MSM8974_OCMEM_VNOC_MAS_GFX3D,
+ .buswidth = 8,
+ .mas_rpm_id = 55,
+ .slv_rpm_id = -1,
+ .num_links = ARRAY_SIZE(mas_v_ocmem_gfx3d_links),
+ .links = mas_v_ocmem_gfx3d_links,
+};
+
+
+static struct qcom_icc_node * const msm8974_onoc_nodes[] = {
[OCMEM_NOC_TO_OCMEM_VNOC] = &ocmem_noc_to_ocmem_vnoc,
[OCMEM_MAS_JPEG_OCMEM] = &mas_jpeg_ocmem,
[OCMEM_MAS_MDP_OCMEM] = &mas_mdp_ocmem,
@@ -423,40 +982,298 @@ static struct msm8974_icc_node * const msm8974_onoc_nodes[] = {
[OCMEM_SLV_OCMEM] = &slv_ocmem,
};
-static const struct msm8974_icc_desc msm8974_onoc = {
+static const struct qcom_icc_desc msm8974_onoc = {
.nodes = msm8974_onoc_nodes,
.num_nodes = ARRAY_SIZE(msm8974_onoc_nodes),
+ .bus_clk_desc = &gpu_mem_2_clk,
+ .get_bw = msm8974_get_bw,
+ .ignore_enxio = true,
+};
+
+static struct qcom_icc_node mas_pnoc_cfg = {
+ .name = "mas_pnoc_cfg",
+ .id = MSM8974_PNOC_MAS_PNOC_CFG,
+ .buswidth = 8,
+ .mas_rpm_id = 43,
+ .slv_rpm_id = -1,
+};
+
+static const u16 mas_sdcc_1_links[] = {
+ MSM8974_PNOC_TO_SNOC
+};
+
+static struct qcom_icc_node mas_sdcc_1 = {
+ .name = "mas_sdcc_1",
+ .id = MSM8974_PNOC_MAS_SDCC_1,
+ .buswidth = 8,
+ .mas_rpm_id = 33,
+ .slv_rpm_id = -1,
+ .num_links = ARRAY_SIZE(mas_sdcc_1_links),
+ .links = mas_sdcc_1_links,
};
-DEFINE_QNODE(mas_pnoc_cfg, MSM8974_PNOC_MAS_PNOC_CFG, 8, 43, -1);
-DEFINE_QNODE(mas_sdcc_1, MSM8974_PNOC_MAS_SDCC_1, 8, 33, -1, MSM8974_PNOC_TO_SNOC);
-DEFINE_QNODE(mas_sdcc_3, MSM8974_PNOC_MAS_SDCC_3, 8, 34, -1, MSM8974_PNOC_TO_SNOC);
-DEFINE_QNODE(mas_sdcc_4, MSM8974_PNOC_MAS_SDCC_4, 8, 36, -1, MSM8974_PNOC_TO_SNOC);
-DEFINE_QNODE(mas_sdcc_2, MSM8974_PNOC_MAS_SDCC_2, 8, 35, -1, MSM8974_PNOC_TO_SNOC);
-DEFINE_QNODE(mas_tsif, MSM8974_PNOC_MAS_TSIF, 8, 37, -1, MSM8974_PNOC_TO_SNOC);
-DEFINE_QNODE(mas_bam_dma, MSM8974_PNOC_MAS_BAM_DMA, 8, 38, -1);
-DEFINE_QNODE(mas_blsp_2, MSM8974_PNOC_MAS_BLSP_2, 8, 39, -1, MSM8974_PNOC_TO_SNOC);
-DEFINE_QNODE(mas_usb_hsic, MSM8974_PNOC_MAS_USB_HSIC, 8, 40, -1, MSM8974_PNOC_TO_SNOC);
-DEFINE_QNODE(mas_blsp_1, MSM8974_PNOC_MAS_BLSP_1, 8, 41, -1, MSM8974_PNOC_TO_SNOC);
-DEFINE_QNODE(mas_usb_hs, MSM8974_PNOC_MAS_USB_HS, 8, 42, -1, MSM8974_PNOC_TO_SNOC);
-DEFINE_QNODE(pnoc_to_snoc, MSM8974_PNOC_TO_SNOC, 8, 44, 45, MSM8974_SNOC_TO_PNOC, MSM8974_PNOC_SLV_PRNG);
-DEFINE_QNODE(slv_sdcc_1, MSM8974_PNOC_SLV_SDCC_1, 8, -1, 31);
-DEFINE_QNODE(slv_sdcc_3, MSM8974_PNOC_SLV_SDCC_3, 8, -1, 32);
-DEFINE_QNODE(slv_sdcc_2, MSM8974_PNOC_SLV_SDCC_2, 8, -1, 33);
-DEFINE_QNODE(slv_sdcc_4, MSM8974_PNOC_SLV_SDCC_4, 8, -1, 34);
-DEFINE_QNODE(slv_tsif, MSM8974_PNOC_SLV_TSIF, 8, -1, 35);
-DEFINE_QNODE(slv_bam_dma, MSM8974_PNOC_SLV_BAM_DMA, 8, -1, 36);
-DEFINE_QNODE(slv_blsp_2, MSM8974_PNOC_SLV_BLSP_2, 8, -1, 37);
-DEFINE_QNODE(slv_usb_hsic, MSM8974_PNOC_SLV_USB_HSIC, 8, -1, 38);
-DEFINE_QNODE(slv_blsp_1, MSM8974_PNOC_SLV_BLSP_1, 8, -1, 39);
-DEFINE_QNODE(slv_usb_hs, MSM8974_PNOC_SLV_USB_HS, 8, -1, 40);
-DEFINE_QNODE(slv_pdm, MSM8974_PNOC_SLV_PDM, 8, -1, 41);
-DEFINE_QNODE(slv_periph_apu_cfg, MSM8974_PNOC_SLV_PERIPH_APU_CFG, 8, -1, 42);
-DEFINE_QNODE(slv_pnoc_mpu_cfg, MSM8974_PNOC_SLV_PNOC_MPU_CFG, 8, -1, 43);
-DEFINE_QNODE(slv_prng, MSM8974_PNOC_SLV_PRNG, 8, -1, 44, MSM8974_PNOC_TO_SNOC);
-DEFINE_QNODE(slv_service_pnoc, MSM8974_PNOC_SLV_SERVICE_PNOC, 8, -1, 46);
-
-static struct msm8974_icc_node * const msm8974_pnoc_nodes[] = {
+static const u16 mas_sdcc_3_links[] = {
+ MSM8974_PNOC_TO_SNOC
+};
+
+static struct qcom_icc_node mas_sdcc_3 = {
+ .name = "mas_sdcc_3",
+ .id = MSM8974_PNOC_MAS_SDCC_3,
+ .buswidth = 8,
+ .mas_rpm_id = 34,
+ .slv_rpm_id = -1,
+ .num_links = ARRAY_SIZE(mas_sdcc_3_links),
+ .links = mas_sdcc_3_links,
+};
+
+static const u16 mas_sdcc_4_links[] = {
+ MSM8974_PNOC_TO_SNOC
+};
+
+static struct qcom_icc_node mas_sdcc_4 = {
+ .name = "mas_sdcc_4",
+ .id = MSM8974_PNOC_MAS_SDCC_4,
+ .buswidth = 8,
+ .mas_rpm_id = 36,
+ .slv_rpm_id = -1,
+ .num_links = ARRAY_SIZE(mas_sdcc_4_links),
+ .links = mas_sdcc_4_links,
+};
+
+static const u16 mas_sdcc_2_links[] = {
+ MSM8974_PNOC_TO_SNOC
+};
+
+static struct qcom_icc_node mas_sdcc_2 = {
+ .name = "mas_sdcc_2",
+ .id = MSM8974_PNOC_MAS_SDCC_2,
+ .buswidth = 8,
+ .mas_rpm_id = 35,
+ .slv_rpm_id = -1,
+ .num_links = ARRAY_SIZE(mas_sdcc_2_links),
+ .links = mas_sdcc_2_links,
+};
+
+static const u16 mas_tsif_links[] = {
+ MSM8974_PNOC_TO_SNOC
+};
+
+static struct qcom_icc_node mas_tsif = {
+ .name = "mas_tsif",
+ .id = MSM8974_PNOC_MAS_TSIF,
+ .buswidth = 8,
+ .mas_rpm_id = 37,
+ .slv_rpm_id = -1,
+ .num_links = ARRAY_SIZE(mas_tsif_links),
+ .links = mas_tsif_links,
+};
+
+static struct qcom_icc_node mas_bam_dma = {
+ .name = "mas_bam_dma",
+ .id = MSM8974_PNOC_MAS_BAM_DMA,
+ .buswidth = 8,
+ .mas_rpm_id = 38,
+ .slv_rpm_id = -1,
+};
+
+static const u16 mas_blsp_2_links[] = {
+ MSM8974_PNOC_TO_SNOC
+};
+
+static struct qcom_icc_node mas_blsp_2 = {
+ .name = "mas_blsp_2",
+ .id = MSM8974_PNOC_MAS_BLSP_2,
+ .buswidth = 8,
+ .mas_rpm_id = 39,
+ .slv_rpm_id = -1,
+ .num_links = ARRAY_SIZE(mas_blsp_2_links),
+ .links = mas_blsp_2_links,
+};
+
+static const u16 mas_usb_hsic_links[] = {
+ MSM8974_PNOC_TO_SNOC
+};
+
+static struct qcom_icc_node mas_usb_hsic = {
+ .name = "mas_usb_hsic",
+ .id = MSM8974_PNOC_MAS_USB_HSIC,
+ .buswidth = 8,
+ .mas_rpm_id = 40,
+ .slv_rpm_id = -1,
+ .num_links = ARRAY_SIZE(mas_usb_hsic_links),
+ .links = mas_usb_hsic_links,
+};
+
+static const u16 mas_blsp_1_links[] = {
+ MSM8974_PNOC_TO_SNOC
+};
+
+static struct qcom_icc_node mas_blsp_1 = {
+ .name = "mas_blsp_1",
+ .id = MSM8974_PNOC_MAS_BLSP_1,
+ .buswidth = 8,
+ .mas_rpm_id = 41,
+ .slv_rpm_id = -1,
+ .num_links = ARRAY_SIZE(mas_blsp_1_links),
+ .links = mas_blsp_1_links,
+};
+
+static const u16 mas_usb_hs_links[] = {
+ MSM8974_PNOC_TO_SNOC
+};
+
+static struct qcom_icc_node mas_usb_hs = {
+ .name = "mas_usb_hs",
+ .id = MSM8974_PNOC_MAS_USB_HS,
+ .buswidth = 8,
+ .mas_rpm_id = 42,
+ .slv_rpm_id = -1,
+ .num_links = ARRAY_SIZE(mas_usb_hs_links),
+ .links = mas_usb_hs_links,
+};
+
+static const u16 pnoc_to_snoc_links[] = {
+ MSM8974_SNOC_TO_PNOC,
+ MSM8974_PNOC_SLV_PRNG
+};
+
+static struct qcom_icc_node pnoc_to_snoc = {
+ .name = "pnoc_to_snoc",
+ .id = MSM8974_PNOC_TO_SNOC,
+ .buswidth = 8,
+ .mas_rpm_id = 44,
+ .slv_rpm_id = 45,
+ .num_links = ARRAY_SIZE(pnoc_to_snoc_links),
+ .links = pnoc_to_snoc_links,
+};
+
+static struct qcom_icc_node slv_sdcc_1 = {
+ .name = "slv_sdcc_1",
+ .id = MSM8974_PNOC_SLV_SDCC_1,
+ .buswidth = 8,
+ .mas_rpm_id = -1,
+ .slv_rpm_id = 31,
+};
+
+static struct qcom_icc_node slv_sdcc_3 = {
+ .name = "slv_sdcc_3",
+ .id = MSM8974_PNOC_SLV_SDCC_3,
+ .buswidth = 8,
+ .mas_rpm_id = -1,
+ .slv_rpm_id = 32,
+};
+
+static struct qcom_icc_node slv_sdcc_2 = {
+ .name = "slv_sdcc_2",
+ .id = MSM8974_PNOC_SLV_SDCC_2,
+ .buswidth = 8,
+ .mas_rpm_id = -1,
+ .slv_rpm_id = 33,
+};
+
+static struct qcom_icc_node slv_sdcc_4 = {
+ .name = "slv_sdcc_4",
+ .id = MSM8974_PNOC_SLV_SDCC_4,
+ .buswidth = 8,
+ .mas_rpm_id = -1,
+ .slv_rpm_id = 34,
+};
+
+static struct qcom_icc_node slv_tsif = {
+ .name = "slv_tsif",
+ .id = MSM8974_PNOC_SLV_TSIF,
+ .buswidth = 8,
+ .mas_rpm_id = -1,
+ .slv_rpm_id = 35,
+};
+
+static struct qcom_icc_node slv_bam_dma = {
+ .name = "slv_bam_dma",
+ .id = MSM8974_PNOC_SLV_BAM_DMA,
+ .buswidth = 8,
+ .mas_rpm_id = -1,
+ .slv_rpm_id = 36,
+};
+
+static struct qcom_icc_node slv_blsp_2 = {
+ .name = "slv_blsp_2",
+ .id = MSM8974_PNOC_SLV_BLSP_2,
+ .buswidth = 8,
+ .mas_rpm_id = -1,
+ .slv_rpm_id = 37,
+};
+
+static struct qcom_icc_node slv_usb_hsic = {
+ .name = "slv_usb_hsic",
+ .id = MSM8974_PNOC_SLV_USB_HSIC,
+ .buswidth = 8,
+ .mas_rpm_id = -1,
+ .slv_rpm_id = 38,
+};
+
+static struct qcom_icc_node slv_blsp_1 = {
+ .name = "slv_blsp_1",
+ .id = MSM8974_PNOC_SLV_BLSP_1,
+ .buswidth = 8,
+ .mas_rpm_id = -1,
+ .slv_rpm_id = 39,
+};
+
+static struct qcom_icc_node slv_usb_hs = {
+ .name = "slv_usb_hs",
+ .id = MSM8974_PNOC_SLV_USB_HS,
+ .buswidth = 8,
+ .mas_rpm_id = -1,
+ .slv_rpm_id = 40,
+};
+
+static struct qcom_icc_node slv_pdm = {
+ .name = "slv_pdm",
+ .id = MSM8974_PNOC_SLV_PDM,
+ .buswidth = 8,
+ .mas_rpm_id = -1,
+ .slv_rpm_id = 41,
+};
+
+static struct qcom_icc_node slv_periph_apu_cfg = {
+ .name = "slv_periph_apu_cfg",
+ .id = MSM8974_PNOC_SLV_PERIPH_APU_CFG,
+ .buswidth = 8,
+ .mas_rpm_id = -1,
+ .slv_rpm_id = 42,
+};
+
+static struct qcom_icc_node slv_pnoc_mpu_cfg = {
+ .name = "slv_pnoc_mpu_cfg",
+ .id = MSM8974_PNOC_SLV_PNOC_MPU_CFG,
+ .buswidth = 8,
+ .mas_rpm_id = -1,
+ .slv_rpm_id = 43,
+};
+
+static const u16 slv_prng_links[] = {
+ MSM8974_PNOC_TO_SNOC
+};
+
+static struct qcom_icc_node slv_prng = {
+ .name = "slv_prng",
+ .id = MSM8974_PNOC_SLV_PRNG,
+ .buswidth = 8,
+ .mas_rpm_id = -1,
+ .slv_rpm_id = 44,
+ .num_links = ARRAY_SIZE(slv_prng_links),
+ .links = slv_prng_links,
+};
+
+static struct qcom_icc_node slv_service_pnoc = {
+ .name = "slv_service_pnoc",
+ .id = MSM8974_PNOC_SLV_SERVICE_PNOC,
+ .buswidth = 8,
+ .mas_rpm_id = -1,
+ .slv_rpm_id = 46,
+};
+
+static struct qcom_icc_node * const msm8974_pnoc_nodes[] = {
[PNOC_MAS_PNOC_CFG] = &mas_pnoc_cfg,
[PNOC_MAS_SDCC_1] = &mas_sdcc_1,
[PNOC_MAS_SDCC_3] = &mas_sdcc_3,
@@ -486,37 +1303,244 @@ static struct msm8974_icc_node * const msm8974_pnoc_nodes[] = {
[PNOC_SLV_SERVICE_PNOC] = &slv_service_pnoc,
};
-static const struct msm8974_icc_desc msm8974_pnoc = {
+static const struct qcom_icc_desc msm8974_pnoc = {
.nodes = msm8974_pnoc_nodes,
.num_nodes = ARRAY_SIZE(msm8974_pnoc_nodes),
+ .bus_clk_desc = &bus_0_clk,
+ .get_bw = msm8974_get_bw,
+ .keep_alive = true,
+ .ignore_enxio = true,
+};
+
+static struct qcom_icc_node mas_lpass_ahb = {
+ .name = "mas_lpass_ahb",
+ .id = MSM8974_SNOC_MAS_LPASS_AHB,
+ .buswidth = 8,
+ .mas_rpm_id = 18,
+ .slv_rpm_id = -1,
+};
+
+static struct qcom_icc_node mas_qdss_bam = {
+ .name = "mas_qdss_bam",
+ .id = MSM8974_SNOC_MAS_QDSS_BAM,
+ .buswidth = 8,
+ .mas_rpm_id = 19,
+ .slv_rpm_id = -1,
+};
+
+static struct qcom_icc_node mas_snoc_cfg = {
+ .name = "mas_snoc_cfg",
+ .id = MSM8974_SNOC_MAS_SNOC_CFG,
+ .buswidth = 8,
+ .mas_rpm_id = 20,
+ .slv_rpm_id = -1,
};
-DEFINE_QNODE(mas_lpass_ahb, MSM8974_SNOC_MAS_LPASS_AHB, 8, 18, -1);
-DEFINE_QNODE(mas_qdss_bam, MSM8974_SNOC_MAS_QDSS_BAM, 8, 19, -1);
-DEFINE_QNODE(mas_snoc_cfg, MSM8974_SNOC_MAS_SNOC_CFG, 8, 20, -1);
-DEFINE_QNODE(snoc_to_bimc, MSM8974_SNOC_TO_BIMC, 8, 21, 24, MSM8974_BIMC_TO_SNOC);
-DEFINE_QNODE(snoc_to_cnoc, MSM8974_SNOC_TO_CNOC, 8, 22, 25);
-DEFINE_QNODE(snoc_to_pnoc, MSM8974_SNOC_TO_PNOC, 8, 29, 28, MSM8974_PNOC_TO_SNOC);
-DEFINE_QNODE(snoc_to_ocmem_vnoc, MSM8974_SNOC_TO_OCMEM_VNOC, 8, 53, 77, MSM8974_OCMEM_VNOC_TO_OCMEM_NOC);
-DEFINE_QNODE(mas_crypto_core0, MSM8974_SNOC_MAS_CRYPTO_CORE0, 8, 23, -1, MSM8974_SNOC_TO_BIMC);
-DEFINE_QNODE(mas_crypto_core1, MSM8974_SNOC_MAS_CRYPTO_CORE1, 8, 24, -1);
-DEFINE_QNODE(mas_lpass_proc, MSM8974_SNOC_MAS_LPASS_PROC, 8, 25, -1, MSM8974_SNOC_TO_OCMEM_VNOC);
-DEFINE_QNODE(mas_mss, MSM8974_SNOC_MAS_MSS, 8, 26, -1);
-DEFINE_QNODE(mas_mss_nav, MSM8974_SNOC_MAS_MSS_NAV, 8, 27, -1);
-DEFINE_QNODE(mas_ocmem_dma, MSM8974_SNOC_MAS_OCMEM_DMA, 8, 28, -1);
-DEFINE_QNODE(mas_wcss, MSM8974_SNOC_MAS_WCSS, 8, 30, -1);
-DEFINE_QNODE(mas_qdss_etr, MSM8974_SNOC_MAS_QDSS_ETR, 8, 31, -1);
-DEFINE_QNODE(mas_usb3, MSM8974_SNOC_MAS_USB3, 8, 32, -1, MSM8974_SNOC_TO_BIMC);
-DEFINE_QNODE(slv_ampss, MSM8974_SNOC_SLV_AMPSS, 8, -1, 20);
-DEFINE_QNODE(slv_lpass, MSM8974_SNOC_SLV_LPASS, 8, -1, 21);
-DEFINE_QNODE(slv_usb3, MSM8974_SNOC_SLV_USB3, 8, -1, 22);
-DEFINE_QNODE(slv_wcss, MSM8974_SNOC_SLV_WCSS, 8, -1, 23);
-DEFINE_QNODE(slv_ocimem, MSM8974_SNOC_SLV_OCIMEM, 8, -1, 26);
-DEFINE_QNODE(slv_snoc_ocmem, MSM8974_SNOC_SLV_SNOC_OCMEM, 8, -1, 27);
-DEFINE_QNODE(slv_service_snoc, MSM8974_SNOC_SLV_SERVICE_SNOC, 8, -1, 29);
-DEFINE_QNODE(slv_qdss_stm, MSM8974_SNOC_SLV_QDSS_STM, 8, -1, 30);
-
-static struct msm8974_icc_node * const msm8974_snoc_nodes[] = {
+static const u16 snoc_to_bimc_links[] = {
+ MSM8974_BIMC_TO_SNOC
+};
+
+static struct qcom_icc_node snoc_to_bimc = {
+ .name = "snoc_to_bimc",
+ .id = MSM8974_SNOC_TO_BIMC,
+ .buswidth = 8,
+ .mas_rpm_id = 21,
+ .slv_rpm_id = 24,
+ .num_links = ARRAY_SIZE(snoc_to_bimc_links),
+ .links = snoc_to_bimc_links,
+};
+
+static struct qcom_icc_node snoc_to_cnoc = {
+ .name = "snoc_to_cnoc",
+ .id = MSM8974_SNOC_TO_CNOC,
+ .buswidth = 8,
+ .mas_rpm_id = 22,
+ .slv_rpm_id = 25,
+};
+
+static const u16 snoc_to_pnoc_links[] = {
+ MSM8974_PNOC_TO_SNOC
+};
+
+static struct qcom_icc_node snoc_to_pnoc = {
+ .name = "snoc_to_pnoc",
+ .id = MSM8974_SNOC_TO_PNOC,
+ .buswidth = 8,
+ .mas_rpm_id = 29,
+ .slv_rpm_id = 28,
+ .num_links = ARRAY_SIZE(snoc_to_pnoc_links),
+ .links = snoc_to_pnoc_links,
+};
+
+static const u16 snoc_to_ocmem_vnoc_links[] = {
+ MSM8974_OCMEM_VNOC_TO_OCMEM_NOC
+};
+
+static struct qcom_icc_node snoc_to_ocmem_vnoc = {
+ .name = "snoc_to_ocmem_vnoc",
+ .id = MSM8974_SNOC_TO_OCMEM_VNOC,
+ .buswidth = 8,
+ .mas_rpm_id = 53,
+ .slv_rpm_id = 77,
+ .num_links = ARRAY_SIZE(snoc_to_ocmem_vnoc_links),
+ .links = snoc_to_ocmem_vnoc_links,
+};
+
+static const u16 mas_crypto_core0_links[] = {
+ MSM8974_SNOC_TO_BIMC
+};
+
+static struct qcom_icc_node mas_crypto_core0 = {
+ .name = "mas_crypto_core0",
+ .id = MSM8974_SNOC_MAS_CRYPTO_CORE0,
+ .buswidth = 8,
+ .mas_rpm_id = 23,
+ .slv_rpm_id = -1,
+ .num_links = ARRAY_SIZE(mas_crypto_core0_links),
+ .links = mas_crypto_core0_links,
+};
+
+static struct qcom_icc_node mas_crypto_core1 = {
+ .name = "mas_crypto_core1",
+ .id = MSM8974_SNOC_MAS_CRYPTO_CORE1,
+ .buswidth = 8,
+ .mas_rpm_id = 24,
+ .slv_rpm_id = -1,
+};
+
+static const u16 mas_lpass_proc_links[] = {
+ MSM8974_SNOC_TO_OCMEM_VNOC
+};
+
+static struct qcom_icc_node mas_lpass_proc = {
+ .name = "mas_lpass_proc",
+ .id = MSM8974_SNOC_MAS_LPASS_PROC,
+ .buswidth = 8,
+ .mas_rpm_id = 25,
+ .slv_rpm_id = -1,
+ .num_links = ARRAY_SIZE(mas_lpass_proc_links),
+ .links = mas_lpass_proc_links,
+};
+
+static struct qcom_icc_node mas_mss = {
+ .name = "mas_mss",
+ .id = MSM8974_SNOC_MAS_MSS,
+ .buswidth = 8,
+ .mas_rpm_id = 26,
+ .slv_rpm_id = -1,
+};
+
+static struct qcom_icc_node mas_mss_nav = {
+ .name = "mas_mss_nav",
+ .id = MSM8974_SNOC_MAS_MSS_NAV,
+ .buswidth = 8,
+ .mas_rpm_id = 27,
+ .slv_rpm_id = -1,
+};
+
+static struct qcom_icc_node mas_ocmem_dma = {
+ .name = "mas_ocmem_dma",
+ .id = MSM8974_SNOC_MAS_OCMEM_DMA,
+ .buswidth = 8,
+ .mas_rpm_id = 28,
+ .slv_rpm_id = -1,
+};
+
+static struct qcom_icc_node mas_wcss = {
+ .name = "mas_wcss",
+ .id = MSM8974_SNOC_MAS_WCSS,
+ .buswidth = 8,
+ .mas_rpm_id = 30,
+ .slv_rpm_id = -1,
+};
+
+static struct qcom_icc_node mas_qdss_etr = {
+ .name = "mas_qdss_etr",
+ .id = MSM8974_SNOC_MAS_QDSS_ETR,
+ .buswidth = 8,
+ .mas_rpm_id = 31,
+ .slv_rpm_id = -1,
+};
+
+static const u16 mas_usb3_links[] = {
+ MSM8974_SNOC_TO_BIMC
+};
+
+static struct qcom_icc_node mas_usb3 = {
+ .name = "mas_usb3",
+ .id = MSM8974_SNOC_MAS_USB3,
+ .buswidth = 8,
+ .mas_rpm_id = 32,
+ .slv_rpm_id = -1,
+ .num_links = ARRAY_SIZE(mas_usb3_links),
+ .links = mas_usb3_links,
+};
+
+static struct qcom_icc_node slv_ampss = {
+ .name = "slv_ampss",
+ .id = MSM8974_SNOC_SLV_AMPSS,
+ .buswidth = 8,
+ .mas_rpm_id = -1,
+ .slv_rpm_id = 20,
+};
+
+static struct qcom_icc_node slv_lpass = {
+ .name = "slv_lpass",
+ .id = MSM8974_SNOC_SLV_LPASS,
+ .buswidth = 8,
+ .mas_rpm_id = -1,
+ .slv_rpm_id = 21,
+};
+
+static struct qcom_icc_node slv_usb3 = {
+ .name = "slv_usb3",
+ .id = MSM8974_SNOC_SLV_USB3,
+ .buswidth = 8,
+ .mas_rpm_id = -1,
+ .slv_rpm_id = 22,
+};
+
+static struct qcom_icc_node slv_wcss = {
+ .name = "slv_wcss",
+ .id = MSM8974_SNOC_SLV_WCSS,
+ .buswidth = 8,
+ .mas_rpm_id = -1,
+ .slv_rpm_id = 23,
+};
+
+static struct qcom_icc_node slv_ocimem = {
+ .name = "slv_ocimem",
+ .id = MSM8974_SNOC_SLV_OCIMEM,
+ .buswidth = 8,
+ .mas_rpm_id = -1,
+ .slv_rpm_id = 26,
+};
+
+static struct qcom_icc_node slv_snoc_ocmem = {
+ .name = "slv_snoc_ocmem",
+ .id = MSM8974_SNOC_SLV_SNOC_OCMEM,
+ .buswidth = 8,
+ .mas_rpm_id = -1,
+ .slv_rpm_id = 27,
+};
+
+static struct qcom_icc_node slv_service_snoc = {
+ .name = "slv_service_snoc",
+ .id = MSM8974_SNOC_SLV_SERVICE_SNOC,
+ .buswidth = 8,
+ .mas_rpm_id = -1,
+ .slv_rpm_id = 29,
+};
+
+static struct qcom_icc_node slv_qdss_stm = {
+ .name = "slv_qdss_stm",
+ .id = MSM8974_SNOC_SLV_QDSS_STM,
+ .buswidth = 8,
+ .mas_rpm_id = -1,
+ .slv_rpm_id = 30,
+};
+
+static struct qcom_icc_node * const msm8974_snoc_nodes[] = {
[SNOC_MAS_LPASS_AHB] = &mas_lpass_ahb,
[SNOC_MAS_QDSS_BAM] = &mas_qdss_bam,
[SNOC_MAS_SNOC_CFG] = &mas_snoc_cfg,
@@ -543,209 +1567,14 @@ static struct msm8974_icc_node * const msm8974_snoc_nodes[] = {
[SNOC_SLV_QDSS_STM] = &slv_qdss_stm,
};
-static const struct msm8974_icc_desc msm8974_snoc = {
+static const struct qcom_icc_desc msm8974_snoc = {
.nodes = msm8974_snoc_nodes,
.num_nodes = ARRAY_SIZE(msm8974_snoc_nodes),
+ .bus_clk_desc = &bus_1_clk,
+ .get_bw = msm8974_get_bw,
+ .ignore_enxio = true,
};
-static void msm8974_icc_rpm_smd_send(struct device *dev, int rsc_type,
- char *name, int id, u64 val)
-{
- int ret;
-
- if (id == -1)
- return;
-
- /*
- * Setting the bandwidth requests for some nodes fails and this same
- * behavior occurs on the downstream MSM 3.4 kernel sources based on
- * errors like this in that kernel:
- *
- * msm_rpm_get_error_from_ack(): RPM NACK Unsupported resource
- * AXI: msm_bus_rpm_req(): RPM: Ack failed
- * AXI: msm_bus_rpm_commit_arb(): RPM: Req fail: mas:32, bw:240000000
- *
- * Since there's no publicly available documentation for this hardware,
- * and the bandwidth for some nodes in the path can be set properly,
- * let's not return an error.
- */
- ret = qcom_icc_rpm_smd_send(QCOM_SMD_RPM_ACTIVE_STATE, rsc_type, id,
- val);
- if (ret)
- dev_dbg(dev, "Cannot set bandwidth for node %s (%d): %d\n",
- name, id, ret);
-}
-
-static int msm8974_icc_set(struct icc_node *src, struct icc_node *dst)
-{
- struct msm8974_icc_node *src_qn, *dst_qn;
- struct msm8974_icc_provider *qp;
- u64 sum_bw, max_peak_bw, rate;
- u32 agg_avg = 0, agg_peak = 0;
- struct icc_provider *provider;
- struct icc_node *n;
- int ret, i;
-
- src_qn = src->data;
- dst_qn = dst->data;
- provider = src->provider;
- qp = to_msm8974_icc_provider(provider);
-
- list_for_each_entry(n, &provider->nodes, node_list)
- provider->aggregate(n, 0, n->avg_bw, n->peak_bw,
- &agg_avg, &agg_peak);
-
- sum_bw = icc_units_to_bps(agg_avg);
- max_peak_bw = icc_units_to_bps(agg_peak);
-
- /* Set bandwidth on source node */
- msm8974_icc_rpm_smd_send(provider->dev, RPM_BUS_MASTER_REQ,
- src_qn->name, src_qn->mas_rpm_id, sum_bw);
-
- msm8974_icc_rpm_smd_send(provider->dev, RPM_BUS_SLAVE_REQ,
- src_qn->name, src_qn->slv_rpm_id, sum_bw);
-
- /* Set bandwidth on destination node */
- msm8974_icc_rpm_smd_send(provider->dev, RPM_BUS_MASTER_REQ,
- dst_qn->name, dst_qn->mas_rpm_id, sum_bw);
-
- msm8974_icc_rpm_smd_send(provider->dev, RPM_BUS_SLAVE_REQ,
- dst_qn->name, dst_qn->slv_rpm_id, sum_bw);
-
- rate = max(sum_bw, max_peak_bw);
-
- do_div(rate, src_qn->buswidth);
-
- rate = min_t(u32, rate, INT_MAX);
-
- if (src_qn->rate == rate)
- return 0;
-
- for (i = 0; i < qp->num_clks; i++) {
- ret = clk_set_rate(qp->bus_clks[i].clk, rate);
- if (ret) {
- dev_err(provider->dev, "%s clk_set_rate error: %d\n",
- qp->bus_clks[i].id, ret);
- ret = 0;
- }
- }
-
- src_qn->rate = rate;
-
- return 0;
-}
-
-static int msm8974_get_bw(struct icc_node *node, u32 *avg, u32 *peak)
-{
- *avg = 0;
- *peak = 0;
-
- return 0;
-}
-
-static int msm8974_icc_probe(struct platform_device *pdev)
-{
- const struct msm8974_icc_desc *desc;
- struct msm8974_icc_node * const *qnodes;
- struct msm8974_icc_provider *qp;
- struct device *dev = &pdev->dev;
- struct icc_onecell_data *data;
- struct icc_provider *provider;
- struct icc_node *node;
- size_t num_nodes, i;
- int ret;
-
- /* wait for the RPM proxy */
- if (!qcom_icc_rpm_smd_available())
- return -EPROBE_DEFER;
-
- desc = of_device_get_match_data(dev);
- if (!desc)
- return -EINVAL;
-
- qnodes = desc->nodes;
- num_nodes = desc->num_nodes;
-
- qp = devm_kzalloc(dev, sizeof(*qp), GFP_KERNEL);
- if (!qp)
- return -ENOMEM;
-
- data = devm_kzalloc(dev, struct_size(data, nodes, num_nodes),
- GFP_KERNEL);
- if (!data)
- return -ENOMEM;
- data->num_nodes = num_nodes;
-
- qp->bus_clks = devm_kmemdup(dev, msm8974_icc_bus_clocks,
- sizeof(msm8974_icc_bus_clocks), GFP_KERNEL);
- if (!qp->bus_clks)
- return -ENOMEM;
-
- qp->num_clks = ARRAY_SIZE(msm8974_icc_bus_clocks);
- ret = devm_clk_bulk_get(dev, qp->num_clks, qp->bus_clks);
- if (ret)
- return ret;
-
- ret = clk_bulk_prepare_enable(qp->num_clks, qp->bus_clks);
- if (ret)
- return ret;
-
- provider = &qp->provider;
- provider->dev = dev;
- provider->set = msm8974_icc_set;
- provider->aggregate = icc_std_aggregate;
- provider->xlate = of_icc_xlate_onecell;
- provider->data = data;
- provider->get_bw = msm8974_get_bw;
-
- icc_provider_init(provider);
-
- for (i = 0; i < num_nodes; i++) {
- size_t j;
-
- node = icc_node_create(qnodes[i]->id);
- if (IS_ERR(node)) {
- ret = PTR_ERR(node);
- goto err_remove_nodes;
- }
-
- node->name = qnodes[i]->name;
- node->data = qnodes[i];
- icc_node_add(node, provider);
-
- dev_dbg(dev, "registered node %s\n", node->name);
-
- /* populate links */
- for (j = 0; j < qnodes[i]->num_links; j++)
- icc_link_create(node, qnodes[i]->links[j]);
-
- data->nodes[i] = node;
- }
-
- ret = icc_provider_register(provider);
- if (ret)
- goto err_remove_nodes;
-
- platform_set_drvdata(pdev, qp);
-
- return 0;
-
-err_remove_nodes:
- icc_nodes_remove(provider);
- clk_bulk_disable_unprepare(qp->num_clks, qp->bus_clks);
-
- return ret;
-}
-
-static void msm8974_icc_remove(struct platform_device *pdev)
-{
- struct msm8974_icc_provider *qp = platform_get_drvdata(pdev);
-
- icc_provider_deregister(&qp->provider);
- icc_nodes_remove(&qp->provider);
- clk_bulk_disable_unprepare(qp->num_clks, qp->bus_clks);
-}
-
static const struct of_device_id msm8974_noc_of_match[] = {
{ .compatible = "qcom,msm8974-bimc", .data = &msm8974_bimc},
{ .compatible = "qcom,msm8974-cnoc", .data = &msm8974_cnoc},
@@ -758,8 +1587,8 @@ static const struct of_device_id msm8974_noc_of_match[] = {
MODULE_DEVICE_TABLE(of, msm8974_noc_of_match);
static struct platform_driver msm8974_noc_driver = {
- .probe = msm8974_icc_probe,
- .remove = msm8974_icc_remove,
+ .probe = qnoc_probe,
+ .remove = qnoc_remove,
.driver = {
.name = "qnoc-msm8974",
.of_match_table = msm8974_noc_of_match,
diff --git a/drivers/interconnect/qcom/qcs615.c b/drivers/interconnect/qcom/qcs615.c
index 797956eb6ff5..017a6017421f 100644
--- a/drivers/interconnect/qcom/qcs615.c
+++ b/drivers/interconnect/qcom/qcs615.c
@@ -142,6 +142,12 @@ static struct qcom_icc_node qhm_qdss_bam = {
.name = "qhm_qdss_bam",
.channels = 1,
.buswidth = 4,
+ .qosbox = &(const struct qcom_icc_qosbox) {
+ .num_ports = 1,
+ .port_offsets = { 0xc000 },
+ .prio = 2,
+ .urg_fwd = 0,
+ },
.num_links = 1,
.link_nodes = { &qns_a1noc_snoc },
};
@@ -150,6 +156,12 @@ static struct qcom_icc_node qhm_qspi = {
.name = "qhm_qspi",
.channels = 1,
.buswidth = 4,
+ .qosbox = &(const struct qcom_icc_qosbox) {
+ .num_ports = 1,
+ .port_offsets = { 0x17000 },
+ .prio = 2,
+ .urg_fwd = 0,
+ },
.num_links = 1,
.link_nodes = { &qns_a1noc_snoc },
};
@@ -158,6 +170,12 @@ static struct qcom_icc_node qhm_qup0 = {
.name = "qhm_qup0",
.channels = 1,
.buswidth = 4,
+ .qosbox = &(const struct qcom_icc_qosbox) {
+ .num_ports = 1,
+ .port_offsets = { 0x10000 },
+ .prio = 2,
+ .urg_fwd = 0,
+ },
.num_links = 1,
.link_nodes = { &qns_a1noc_snoc },
};
@@ -166,6 +184,12 @@ static struct qcom_icc_node qhm_qup1 = {
.name = "qhm_qup1",
.channels = 1,
.buswidth = 4,
+ .qosbox = &(const struct qcom_icc_qosbox) {
+ .num_ports = 1,
+ .port_offsets = { 0x12000 },
+ .prio = 2,
+ .urg_fwd = 0,
+ },
.num_links = 1,
.link_nodes = { &qns_a1noc_snoc },
};
@@ -174,6 +198,12 @@ static struct qcom_icc_node qnm_cnoc = {
.name = "qnm_cnoc",
.channels = 1,
.buswidth = 8,
+ .qosbox = &(const struct qcom_icc_qosbox) {
+ .num_ports = 1,
+ .port_offsets = { 0x4000 },
+ .prio = 2,
+ .urg_fwd = 1,
+ },
.num_links = 1,
.link_nodes = { &qns_a1noc_snoc },
};
@@ -182,6 +212,12 @@ static struct qcom_icc_node qxm_crypto = {
.name = "qxm_crypto",
.channels = 1,
.buswidth = 8,
+ .qosbox = &(const struct qcom_icc_qosbox) {
+ .num_ports = 1,
+ .port_offsets = { 0x5000 },
+ .prio = 2,
+ .urg_fwd = 1,
+ },
.num_links = 1,
.link_nodes = { &qns_a1noc_snoc },
};
@@ -190,6 +226,12 @@ static struct qcom_icc_node qxm_ipa = {
.name = "qxm_ipa",
.channels = 1,
.buswidth = 8,
+ .qosbox = &(const struct qcom_icc_qosbox) {
+ .num_ports = 1,
+ .port_offsets = { 0x6000 },
+ .prio = 2,
+ .urg_fwd = 1,
+ },
.num_links = 1,
.link_nodes = { &qns_lpass_snoc },
};
@@ -198,6 +240,12 @@ static struct qcom_icc_node xm_emac_avb = {
.name = "xm_emac_avb",
.channels = 1,
.buswidth = 8,
+ .qosbox = &(const struct qcom_icc_qosbox) {
+ .num_ports = 1,
+ .port_offsets = { 0xa000 },
+ .prio = 2,
+ .urg_fwd = 0,
+ },
.num_links = 1,
.link_nodes = { &qns_a1noc_snoc },
};
@@ -206,6 +254,12 @@ static struct qcom_icc_node xm_pcie = {
.name = "xm_pcie",
.channels = 1,
.buswidth = 8,
+ .qosbox = &(const struct qcom_icc_qosbox) {
+ .num_ports = 1,
+ .port_offsets = { 0x13000 },
+ .prio = 0,
+ .urg_fwd = 0,
+ },
.num_links = 1,
.link_nodes = { &qns_pcie_snoc },
};
@@ -214,6 +268,12 @@ static struct qcom_icc_node xm_qdss_etr = {
.name = "xm_qdss_etr",
.channels = 1,
.buswidth = 8,
+ .qosbox = &(const struct qcom_icc_qosbox) {
+ .num_ports = 1,
+ .port_offsets = { 0xb000 },
+ .prio = 2,
+ .urg_fwd = 0,
+ },
.num_links = 1,
.link_nodes = { &qns_a1noc_snoc },
};
@@ -222,6 +282,12 @@ static struct qcom_icc_node xm_sdc1 = {
.name = "xm_sdc1",
.channels = 1,
.buswidth = 8,
+ .qosbox = &(const struct qcom_icc_qosbox) {
+ .num_ports = 1,
+ .port_offsets = { 0xe000 },
+ .prio = 2,
+ .urg_fwd = 0,
+ },
.num_links = 1,
.link_nodes = { &qns_a1noc_snoc },
};
@@ -230,6 +296,12 @@ static struct qcom_icc_node xm_sdc2 = {
.name = "xm_sdc2",
.channels = 1,
.buswidth = 8,
+ .qosbox = &(const struct qcom_icc_qosbox) {
+ .num_ports = 1,
+ .port_offsets = { 0x16000 },
+ .prio = 2,
+ .urg_fwd = 0,
+ },
.num_links = 1,
.link_nodes = { &qns_a1noc_snoc },
};
@@ -238,6 +310,12 @@ static struct qcom_icc_node xm_ufs_mem = {
.name = "xm_ufs_mem",
.channels = 1,
.buswidth = 8,
+ .qosbox = &(const struct qcom_icc_qosbox) {
+ .num_ports = 1,
+ .port_offsets = { 0x11000 },
+ .prio = 2,
+ .urg_fwd = 0,
+ },
.num_links = 1,
.link_nodes = { &qns_a1noc_snoc },
};
@@ -246,6 +324,12 @@ static struct qcom_icc_node xm_usb2 = {
.name = "xm_usb2",
.channels = 1,
.buswidth = 8,
+ .qosbox = &(const struct qcom_icc_qosbox) {
+ .num_ports = 1,
+ .port_offsets = { 0x15000 },
+ .prio = 2,
+ .urg_fwd = 0,
+ },
.num_links = 1,
.link_nodes = { &qns_a1noc_snoc },
};
@@ -254,6 +338,12 @@ static struct qcom_icc_node xm_usb3_0 = {
.name = "xm_usb3_0",
.channels = 1,
.buswidth = 8,
+ .qosbox = &(const struct qcom_icc_qosbox) {
+ .num_ports = 1,
+ .port_offsets = { 0xd000 },
+ .prio = 2,
+ .urg_fwd = 0,
+ },
.num_links = 1,
.link_nodes = { &qns_a1noc_snoc },
};
@@ -356,6 +446,12 @@ static struct qcom_icc_node acm_apps = {
.name = "acm_apps",
.channels = 1,
.buswidth = 16,
+ .qosbox = &(const struct qcom_icc_qosbox) {
+ .num_ports = 2,
+ .port_offsets = { 0x2e000, 0x2e100 },
+ .prio = 0,
+ .urg_fwd = 1,
+ },
.num_links = 3,
.link_nodes = { &qns_gem_noc_snoc, &qns_llcc,
&qns_sys_pcie },
@@ -365,6 +461,12 @@ static struct qcom_icc_node acm_gpu_tcu = {
.name = "acm_gpu_tcu",
.channels = 1,
.buswidth = 8,
+ .qosbox = &(const struct qcom_icc_qosbox) {
+ .num_ports = 1,
+ .port_offsets = { 0x36000 },
+ .prio = 6,
+ .urg_fwd = 0,
+ },
.num_links = 2,
.link_nodes = { &qns_gem_noc_snoc, &qns_llcc },
};
@@ -373,6 +475,12 @@ static struct qcom_icc_node acm_sys_tcu = {
.name = "acm_sys_tcu",
.channels = 1,
.buswidth = 8,
+ .qosbox = &(const struct qcom_icc_qosbox) {
+ .num_ports = 1,
+ .port_offsets = { 0x37000 },
+ .prio = 6,
+ .urg_fwd = 0,
+ },
.num_links = 2,
.link_nodes = { &qns_gem_noc_snoc, &qns_llcc },
};
@@ -389,6 +497,12 @@ static struct qcom_icc_node qnm_gpu = {
.name = "qnm_gpu",
.channels = 2,
.buswidth = 32,
+ .qosbox = &(const struct qcom_icc_qosbox) {
+ .num_ports = 2,
+ .port_offsets = { 0x34000, 0x34080 },
+ .prio = 0,
+ .urg_fwd = 1,
+ },
.num_links = 2,
.link_nodes = { &qns_gem_noc_snoc, &qns_llcc },
};
@@ -397,6 +511,12 @@ static struct qcom_icc_node qnm_mnoc_hf = {
.name = "qnm_mnoc_hf",
.channels = 1,
.buswidth = 32,
+ .qosbox = &(const struct qcom_icc_qosbox) {
+ .num_ports = 1,
+ .port_offsets = { 0x2f000 },
+ .prio = 0,
+ .urg_fwd = 1,
+ },
.num_links = 1,
.link_nodes = { &qns_llcc },
};
@@ -405,6 +525,12 @@ static struct qcom_icc_node qnm_mnoc_sf = {
.name = "qnm_mnoc_sf",
.channels = 1,
.buswidth = 32,
+ .qosbox = &(const struct qcom_icc_qosbox) {
+ .num_ports = 1,
+ .port_offsets = { 0x35000 },
+ .prio = 0,
+ .urg_fwd = 1,
+ },
.num_links = 2,
.link_nodes = { &qns_gem_noc_snoc, &qns_llcc },
};
@@ -413,6 +539,12 @@ static struct qcom_icc_node qnm_snoc_gc = {
.name = "qnm_snoc_gc",
.channels = 1,
.buswidth = 8,
+ .qosbox = &(const struct qcom_icc_qosbox) {
+ .num_ports = 1,
+ .port_offsets = { 0x31000 },
+ .prio = 0,
+ .urg_fwd = 1,
+ },
.num_links = 1,
.link_nodes = { &qns_llcc },
};
@@ -421,6 +553,12 @@ static struct qcom_icc_node qnm_snoc_sf = {
.name = "qnm_snoc_sf",
.channels = 1,
.buswidth = 16,
+ .qosbox = &(const struct qcom_icc_qosbox) {
+ .num_ports = 1,
+ .port_offsets = { 0x30000 },
+ .prio = 0,
+ .urg_fwd = 1,
+ },
.num_links = 1,
.link_nodes = { &qns_llcc },
};
@@ -445,6 +583,12 @@ static struct qcom_icc_node qxm_camnoc_hf0 = {
.name = "qxm_camnoc_hf0",
.channels = 1,
.buswidth = 32,
+ .qosbox = &(const struct qcom_icc_qosbox) {
+ .num_ports = 1,
+ .port_offsets = { 0xa000 },
+ .prio = 0,
+ .urg_fwd = 1,
+ },
.num_links = 1,
.link_nodes = { &qns_mem_noc_hf },
};
@@ -453,6 +597,12 @@ static struct qcom_icc_node qxm_camnoc_hf1 = {
.name = "qxm_camnoc_hf1",
.channels = 1,
.buswidth = 32,
+ .qosbox = &(const struct qcom_icc_qosbox) {
+ .num_ports = 1,
+ .port_offsets = { 0xb000 },
+ .prio = 0,
+ .urg_fwd = 1,
+ },
.num_links = 1,
.link_nodes = { &qns_mem_noc_hf },
};
@@ -461,6 +611,12 @@ static struct qcom_icc_node qxm_camnoc_sf = {
.name = "qxm_camnoc_sf",
.channels = 1,
.buswidth = 32,
+ .qosbox = &(const struct qcom_icc_qosbox) {
+ .num_ports = 1,
+ .port_offsets = { 0x9000 },
+ .prio = 0,
+ .urg_fwd = 1,
+ },
.num_links = 1,
.link_nodes = { &qns2_mem_noc },
};
@@ -469,6 +625,12 @@ static struct qcom_icc_node qxm_mdp0 = {
.name = "qxm_mdp0",
.channels = 1,
.buswidth = 32,
+ .qosbox = &(const struct qcom_icc_qosbox) {
+ .num_ports = 1,
+ .port_offsets = { 0xc000 },
+ .prio = 0,
+ .urg_fwd = 1,
+ },
.num_links = 1,
.link_nodes = { &qns_mem_noc_hf },
};
@@ -477,6 +639,12 @@ static struct qcom_icc_node qxm_rot = {
.name = "qxm_rot",
.channels = 1,
.buswidth = 32,
+ .qosbox = &(const struct qcom_icc_qosbox) {
+ .num_ports = 1,
+ .port_offsets = { 0xe000 },
+ .prio = 0,
+ .urg_fwd = 1,
+ },
.num_links = 1,
.link_nodes = { &qns2_mem_noc },
};
@@ -485,6 +653,12 @@ static struct qcom_icc_node qxm_venus0 = {
.name = "qxm_venus0",
.channels = 1,
.buswidth = 32,
+ .qosbox = &(const struct qcom_icc_qosbox) {
+ .num_ports = 1,
+ .port_offsets = { 0xf000 },
+ .prio = 0,
+ .urg_fwd = 1,
+ },
.num_links = 1,
.link_nodes = { &qns2_mem_noc },
};
@@ -493,6 +667,12 @@ static struct qcom_icc_node qxm_venus_arm9 = {
.name = "qxm_venus_arm9",
.channels = 1,
.buswidth = 8,
+ .qosbox = &(const struct qcom_icc_qosbox) {
+ .num_ports = 1,
+ .port_offsets = { 0x11000 },
+ .prio = 0,
+ .urg_fwd = 1,
+ },
.num_links = 1,
.link_nodes = { &qns2_mem_noc },
};
@@ -559,6 +739,12 @@ static struct qcom_icc_node qxm_pimem = {
.name = "qxm_pimem",
.channels = 1,
.buswidth = 8,
+ .qosbox = &(const struct qcom_icc_qosbox) {
+ .num_ports = 1,
+ .port_offsets = { 0xc000 },
+ .prio = 2,
+ .urg_fwd = 1,
+ },
.num_links = 2,
.link_nodes = { &qns_memnoc_gc, &qxs_imem },
};
@@ -567,6 +753,12 @@ static struct qcom_icc_node xm_gic = {
.name = "xm_gic",
.channels = 1,
.buswidth = 8,
+ .qosbox = &(const struct qcom_icc_qosbox) {
+ .num_ports = 1,
+ .port_offsets = { 0xd000 },
+ .prio = 2,
+ .urg_fwd = 1,
+ },
.num_links = 2,
.link_nodes = { &qns_memnoc_gc, &qxs_imem },
};
@@ -1213,11 +1405,21 @@ static struct qcom_icc_node * const aggre1_noc_nodes[] = {
[SLAVE_SERVICE_A2NOC] = &srvc_aggre2_noc,
};
+static const struct regmap_config qcs615_aggre1_noc_regmap_config = {
+ .reg_bits = 32,
+ .reg_stride = 4,
+ .val_bits = 32,
+ .max_register = 0x3f200,
+ .fast_io = true,
+};
+
static const struct qcom_icc_desc qcs615_aggre1_noc = {
+ .config = &qcs615_aggre1_noc_regmap_config,
.nodes = aggre1_noc_nodes,
.num_nodes = ARRAY_SIZE(aggre1_noc_nodes),
.bcms = aggre1_noc_bcms,
.num_bcms = ARRAY_SIZE(aggre1_noc_bcms),
+ .qos_requires_clocks = true,
};
static struct qcom_icc_bcm * const camnoc_virt_bcms[] = {
@@ -1289,7 +1491,16 @@ static struct qcom_icc_node * const config_noc_nodes[] = {
[SLAVE_SERVICE_CNOC] = &srvc_cnoc,
};
+static const struct regmap_config qcs615_config_noc_regmap_config = {
+ .reg_bits = 32,
+ .reg_stride = 4,
+ .val_bits = 32,
+ .max_register = 0x5080,
+ .fast_io = true,
+};
+
static const struct qcom_icc_desc qcs615_config_noc = {
+ .config = &qcs615_config_noc_regmap_config,
.nodes = config_noc_nodes,
.num_nodes = ARRAY_SIZE(config_noc_nodes),
.bcms = config_noc_bcms,
@@ -1302,7 +1513,16 @@ static struct qcom_icc_node * const dc_noc_nodes[] = {
[SLAVE_LLCC_CFG] = &qhs_llcc,
};
+static const struct regmap_config qcs615_dc_noc_regmap_config = {
+ .reg_bits = 32,
+ .reg_stride = 4,
+ .val_bits = 32,
+ .max_register = 0x3200,
+ .fast_io = true,
+};
+
static const struct qcom_icc_desc qcs615_dc_noc = {
+ .config = &qcs615_dc_noc_regmap_config,
.nodes = dc_noc_nodes,
.num_nodes = ARRAY_SIZE(dc_noc_nodes),
};
@@ -1331,7 +1551,16 @@ static struct qcom_icc_node * const gem_noc_nodes[] = {
[SLAVE_SERVICE_GEM_NOC] = &srvc_gemnoc,
};
+static const struct regmap_config qcs615_gem_noc_regmap_config = {
+ .reg_bits = 32,
+ .reg_stride = 4,
+ .val_bits = 32,
+ .max_register = 0x3e200,
+ .fast_io = true,
+};
+
static const struct qcom_icc_desc qcs615_gem_noc = {
+ .config = &qcs615_gem_noc_regmap_config,
.nodes = gem_noc_nodes,
.num_nodes = ARRAY_SIZE(gem_noc_nodes),
.bcms = gem_noc_bcms,
@@ -1376,7 +1605,16 @@ static struct qcom_icc_node * const mmss_noc_nodes[] = {
[SLAVE_SERVICE_MNOC] = &srvc_mnoc,
};
+static const struct regmap_config qcs615_mmss_noc_regmap_config = {
+ .reg_bits = 32,
+ .reg_stride = 4,
+ .val_bits = 32,
+ .max_register = 0x1c100,
+ .fast_io = true,
+};
+
static const struct qcom_icc_desc qcs615_mmss_noc = {
+ .config = &qcs615_mmss_noc_regmap_config,
.nodes = mmss_noc_nodes,
.num_nodes = ARRAY_SIZE(mmss_noc_nodes),
.bcms = mmss_noc_bcms,
@@ -1418,7 +1656,16 @@ static struct qcom_icc_node * const system_noc_nodes[] = {
[SLAVE_TCU] = &xs_sys_tcu_cfg,
};
+static const struct regmap_config qcs615_system_noc_regmap_config = {
+ .reg_bits = 32,
+ .reg_stride = 4,
+ .val_bits = 32,
+ .max_register = 0x1f300,
+ .fast_io = true,
+};
+
static const struct qcom_icc_desc qcs615_system_noc = {
+ .config = &qcs615_system_noc_regmap_config,
.nodes = system_noc_nodes,
.num_nodes = ARRAY_SIZE(system_noc_nodes),
.bcms = system_noc_bcms,
diff --git a/drivers/interconnect/qcom/qcs8300.c b/drivers/interconnect/qcom/qcs8300.c
index bc403a9bf68c..ebf167182572 100644
--- a/drivers/interconnect/qcom/qcs8300.c
+++ b/drivers/interconnect/qcom/qcs8300.c
@@ -186,6 +186,13 @@ static struct qcom_icc_node qxm_qup3 = {
.name = "qxm_qup3",
.channels = 1,
.buswidth = 8,
+ .qosbox = &(const struct qcom_icc_qosbox) {
+ .num_ports = 1,
+ .port_offsets = { 0x11000 },
+ .prio_fwd_disable = 1,
+ .prio = 2,
+ .urg_fwd = 0,
+ },
.num_links = 1,
.link_nodes = { &qns_a1noc_snoc },
};
@@ -194,6 +201,13 @@ static struct qcom_icc_node xm_emac_0 = {
.name = "xm_emac_0",
.channels = 1,
.buswidth = 8,
+ .qosbox = &(const struct qcom_icc_qosbox) {
+ .num_ports = 1,
+ .port_offsets = { 0x12000 },
+ .prio_fwd_disable = 1,
+ .prio = 2,
+ .urg_fwd = 0,
+ },
.num_links = 1,
.link_nodes = { &qns_a1noc_snoc },
};
@@ -202,6 +216,13 @@ static struct qcom_icc_node xm_sdc1 = {
.name = "xm_sdc1",
.channels = 1,
.buswidth = 8,
+ .qosbox = &(const struct qcom_icc_qosbox) {
+ .num_ports = 1,
+ .port_offsets = { 0x14000 },
+ .prio_fwd_disable = 1,
+ .prio = 2,
+ .urg_fwd = 0,
+ },
.num_links = 1,
.link_nodes = { &qns_a1noc_snoc },
};
@@ -210,6 +231,13 @@ static struct qcom_icc_node xm_ufs_mem = {
.name = "xm_ufs_mem",
.channels = 1,
.buswidth = 8,
+ .qosbox = &(const struct qcom_icc_qosbox) {
+ .num_ports = 1,
+ .port_offsets = { 0x15000 },
+ .prio_fwd_disable = 1,
+ .prio = 2,
+ .urg_fwd = 0,
+ },
.num_links = 1,
.link_nodes = { &qns_a1noc_snoc },
};
@@ -218,6 +246,13 @@ static struct qcom_icc_node xm_usb2_2 = {
.name = "xm_usb2_2",
.channels = 1,
.buswidth = 8,
+ .qosbox = &(const struct qcom_icc_qosbox) {
+ .num_ports = 1,
+ .port_offsets = { 0x16000 },
+ .prio_fwd_disable = 1,
+ .prio = 2,
+ .urg_fwd = 0,
+ },
.num_links = 1,
.link_nodes = { &qns_a1noc_snoc },
};
@@ -226,6 +261,13 @@ static struct qcom_icc_node xm_usb3_0 = {
.name = "xm_usb3_0",
.channels = 1,
.buswidth = 8,
+ .qosbox = &(const struct qcom_icc_qosbox) {
+ .num_ports = 1,
+ .port_offsets = { 0x17000 },
+ .prio_fwd_disable = 1,
+ .prio = 2,
+ .urg_fwd = 0,
+ },
.num_links = 1,
.link_nodes = { &qns_a1noc_snoc },
};
@@ -234,6 +276,13 @@ static struct qcom_icc_node qhm_qdss_bam = {
.name = "qhm_qdss_bam",
.channels = 1,
.buswidth = 4,
+ .qosbox = &(const struct qcom_icc_qosbox) {
+ .num_ports = 1,
+ .port_offsets = { 0x14000 },
+ .prio_fwd_disable = 1,
+ .prio = 2,
+ .urg_fwd = 0,
+ },
.num_links = 1,
.link_nodes = { &qns_a2noc_snoc },
};
@@ -242,6 +291,13 @@ static struct qcom_icc_node qhm_qup0 = {
.name = "qhm_qup0",
.channels = 1,
.buswidth = 4,
+ .qosbox = &(const struct qcom_icc_qosbox) {
+ .num_ports = 1,
+ .port_offsets = { 0x17000 },
+ .prio_fwd_disable = 1,
+ .prio = 2,
+ .urg_fwd = 0,
+ },
.num_links = 1,
.link_nodes = { &qns_a2noc_snoc },
};
@@ -250,6 +306,13 @@ static struct qcom_icc_node qhm_qup1 = {
.name = "qhm_qup1",
.channels = 1,
.buswidth = 4,
+ .qosbox = &(const struct qcom_icc_qosbox) {
+ .num_ports = 1,
+ .port_offsets = { 0x12000 },
+ .prio_fwd_disable = 1,
+ .prio = 2,
+ .urg_fwd = 0,
+ },
.num_links = 1,
.link_nodes = { &qns_a2noc_snoc },
};
@@ -258,6 +321,13 @@ static struct qcom_icc_node qnm_cnoc_datapath = {
.name = "qnm_cnoc_datapath",
.channels = 1,
.buswidth = 8,
+ .qosbox = &(const struct qcom_icc_qosbox) {
+ .num_ports = 1,
+ .port_offsets = { 0x16000 },
+ .prio_fwd_disable = 1,
+ .prio = 2,
+ .urg_fwd = 0,
+ },
.num_links = 1,
.link_nodes = { &qns_a2noc_snoc },
};
@@ -266,6 +336,13 @@ static struct qcom_icc_node qxm_crypto_0 = {
.name = "qxm_crypto_0",
.channels = 1,
.buswidth = 8,
+ .qosbox = &(const struct qcom_icc_qosbox) {
+ .num_ports = 1,
+ .port_offsets = { 0x18000 },
+ .prio_fwd_disable = 1,
+ .prio = 2,
+ .urg_fwd = 0,
+ },
.num_links = 1,
.link_nodes = { &qns_a2noc_snoc },
};
@@ -274,6 +351,13 @@ static struct qcom_icc_node qxm_crypto_1 = {
.name = "qxm_crypto_1",
.channels = 1,
.buswidth = 8,
+ .qosbox = &(const struct qcom_icc_qosbox) {
+ .num_ports = 1,
+ .port_offsets = { 0x1a000 },
+ .prio_fwd_disable = 1,
+ .prio = 2,
+ .urg_fwd = 0,
+ },
.num_links = 1,
.link_nodes = { &qns_a2noc_snoc },
};
@@ -282,6 +366,13 @@ static struct qcom_icc_node qxm_ipa = {
.name = "qxm_ipa",
.channels = 1,
.buswidth = 8,
+ .qosbox = &(const struct qcom_icc_qosbox) {
+ .num_ports = 1,
+ .port_offsets = { 0x11000 },
+ .prio_fwd_disable = 1,
+ .prio = 2,
+ .urg_fwd = 0,
+ },
.num_links = 1,
.link_nodes = { &qns_a2noc_snoc },
};
@@ -290,6 +381,13 @@ static struct qcom_icc_node xm_qdss_etr_0 = {
.name = "xm_qdss_etr_0",
.channels = 1,
.buswidth = 8,
+ .qosbox = &(const struct qcom_icc_qosbox) {
+ .num_ports = 1,
+ .port_offsets = { 0x13000 },
+ .prio_fwd_disable = 1,
+ .prio = 2,
+ .urg_fwd = 0,
+ },
.num_links = 1,
.link_nodes = { &qns_a2noc_snoc },
};
@@ -298,6 +396,13 @@ static struct qcom_icc_node xm_qdss_etr_1 = {
.name = "xm_qdss_etr_1",
.channels = 1,
.buswidth = 8,
+ .qosbox = &(const struct qcom_icc_qosbox) {
+ .num_ports = 1,
+ .port_offsets = { 0x19000 },
+ .prio_fwd_disable = 1,
+ .prio = 2,
+ .urg_fwd = 0,
+ },
.num_links = 1,
.link_nodes = { &qns_a2noc_snoc },
};
@@ -390,6 +495,13 @@ static struct qcom_icc_node alm_gpu_tcu = {
.name = "alm_gpu_tcu",
.channels = 1,
.buswidth = 8,
+ .qosbox = &(const struct qcom_icc_qosbox) {
+ .num_ports = 1,
+ .port_offsets = { 0xaf000 },
+ .prio_fwd_disable = 1,
+ .prio = 1,
+ .urg_fwd = 0,
+ },
.num_links = 2,
.link_nodes = { &qns_gem_noc_cnoc, &qns_llcc },
};
@@ -398,6 +510,13 @@ static struct qcom_icc_node alm_pcie_tcu = {
.name = "alm_pcie_tcu",
.channels = 1,
.buswidth = 8,
+ .qosbox = &(const struct qcom_icc_qosbox) {
+ .num_ports = 1,
+ .port_offsets = { 0xb0000 },
+ .prio_fwd_disable = 1,
+ .prio = 3,
+ .urg_fwd = 0,
+ },
.num_links = 2,
.link_nodes = { &qns_gem_noc_cnoc, &qns_llcc },
};
@@ -406,6 +525,13 @@ static struct qcom_icc_node alm_sys_tcu = {
.name = "alm_sys_tcu",
.channels = 1,
.buswidth = 8,
+ .qosbox = &(const struct qcom_icc_qosbox) {
+ .num_ports = 1,
+ .port_offsets = { 0xb1000 },
+ .prio_fwd_disable = 1,
+ .prio = 6,
+ .urg_fwd = 0,
+ },
.num_links = 2,
.link_nodes = { &qns_gem_noc_cnoc, &qns_llcc },
};
@@ -423,6 +549,13 @@ static struct qcom_icc_node qnm_cmpnoc0 = {
.name = "qnm_cmpnoc0",
.channels = 2,
.buswidth = 32,
+ .qosbox = &(const struct qcom_icc_qosbox) {
+ .num_ports = 2,
+ .port_offsets = { 0xf6000, 0xf7000 },
+ .prio_fwd_disable = 1,
+ .prio = 0,
+ .urg_fwd = 0,
+ },
.num_links = 2,
.link_nodes = { &qns_gem_noc_cnoc, &qns_llcc },
};
@@ -448,6 +581,13 @@ static struct qcom_icc_node qnm_gpu = {
.name = "qnm_gpu",
.channels = 2,
.buswidth = 32,
+ .qosbox = &(const struct qcom_icc_qosbox) {
+ .num_ports = 2,
+ .port_offsets = { 0xf0000, 0xf1000 },
+ .prio_fwd_disable = 1,
+ .prio = 0,
+ .urg_fwd = 0,
+ },
.num_links = 2,
.link_nodes = { &qns_gem_noc_cnoc, &qns_llcc },
};
@@ -456,6 +596,13 @@ static struct qcom_icc_node qnm_mnoc_hf = {
.name = "qnm_mnoc_hf",
.channels = 2,
.buswidth = 32,
+ .qosbox = &(const struct qcom_icc_qosbox) {
+ .num_ports = 2,
+ .port_offsets = { 0xf2000, 0xf3000 },
+ .prio_fwd_disable = 0,
+ .prio = 0,
+ .urg_fwd = 1,
+ },
.num_links = 2,
.link_nodes = { &qns_llcc, &qns_pcie },
};
@@ -464,6 +611,13 @@ static struct qcom_icc_node qnm_mnoc_sf = {
.name = "qnm_mnoc_sf",
.channels = 2,
.buswidth = 32,
+ .qosbox = &(const struct qcom_icc_qosbox) {
+ .num_ports = 2,
+ .port_offsets = { 0xf4000, 0xf5000 },
+ .prio_fwd_disable = 0,
+ .prio = 0,
+ .urg_fwd = 1,
+ },
.num_links = 3,
.link_nodes = { &qns_gem_noc_cnoc, &qns_llcc,
&qns_pcie },
@@ -473,6 +627,13 @@ static struct qcom_icc_node qnm_pcie = {
.name = "qnm_pcie",
.channels = 1,
.buswidth = 32,
+ .qosbox = &(const struct qcom_icc_qosbox) {
+ .num_ports = 1,
+ .port_offsets = { 0xb3000 },
+ .prio_fwd_disable = 1,
+ .prio = 2,
+ .urg_fwd = 0,
+ },
.num_links = 2,
.link_nodes = { &qns_gem_noc_cnoc, &qns_llcc },
};
@@ -481,6 +642,13 @@ static struct qcom_icc_node qnm_snoc_gc = {
.name = "qnm_snoc_gc",
.channels = 1,
.buswidth = 8,
+ .qosbox = &(const struct qcom_icc_qosbox) {
+ .num_ports = 1,
+ .port_offsets = { 0xb4000 },
+ .prio_fwd_disable = 0,
+ .prio = 0,
+ .urg_fwd = 1,
+ },
.num_links = 1,
.link_nodes = { &qns_llcc },
};
@@ -489,6 +657,13 @@ static struct qcom_icc_node qnm_snoc_sf = {
.name = "qnm_snoc_sf",
.channels = 1,
.buswidth = 16,
+ .qosbox = &(const struct qcom_icc_qosbox) {
+ .num_ports = 1,
+ .port_offsets = { 0xb5000 },
+ .prio_fwd_disable = 0,
+ .prio = 0,
+ .urg_fwd = 1,
+ },
.num_links = 3,
.link_nodes = { &qns_gem_noc_cnoc, &qns_llcc,
&qns_pcie },
@@ -541,6 +716,13 @@ static struct qcom_icc_node qnm_camnoc_hf = {
.name = "qnm_camnoc_hf",
.channels = 1,
.buswidth = 32,
+ .qosbox = &(const struct qcom_icc_qosbox) {
+ .num_ports = 1,
+ .port_offsets = { 0xa000 },
+ .prio_fwd_disable = 0,
+ .prio = 0,
+ .urg_fwd = 1,
+ },
.num_links = 1,
.link_nodes = { &qns_mem_noc_hf },
};
@@ -549,6 +731,13 @@ static struct qcom_icc_node qnm_camnoc_icp = {
.name = "qnm_camnoc_icp",
.channels = 1,
.buswidth = 8,
+ .qosbox = &(const struct qcom_icc_qosbox) {
+ .num_ports = 1,
+ .port_offsets = { 0x2a000 },
+ .prio_fwd_disable = 0,
+ .prio = 0,
+ .urg_fwd = 1,
+ },
.num_links = 1,
.link_nodes = { &qns_mem_noc_sf },
};
@@ -557,6 +746,13 @@ static struct qcom_icc_node qnm_camnoc_sf = {
.name = "qnm_camnoc_sf",
.channels = 1,
.buswidth = 32,
+ .qosbox = &(const struct qcom_icc_qosbox) {
+ .num_ports = 1,
+ .port_offsets = { 0x2a080 },
+ .prio_fwd_disable = 0,
+ .prio = 0,
+ .urg_fwd = 1,
+ },
.num_links = 1,
.link_nodes = { &qns_mem_noc_sf },
};
@@ -565,6 +761,13 @@ static struct qcom_icc_node qnm_mdp0_0 = {
.name = "qnm_mdp0_0",
.channels = 1,
.buswidth = 32,
+ .qosbox = &(const struct qcom_icc_qosbox) {
+ .num_ports = 1,
+ .port_offsets = { 0xa080 },
+ .prio_fwd_disable = 0,
+ .prio = 0,
+ .urg_fwd = 1,
+ },
.num_links = 1,
.link_nodes = { &qns_mem_noc_hf },
};
@@ -573,6 +776,13 @@ static struct qcom_icc_node qnm_mdp0_1 = {
.name = "qnm_mdp0_1",
.channels = 1,
.buswidth = 32,
+ .qosbox = &(const struct qcom_icc_qosbox) {
+ .num_ports = 1,
+ .port_offsets = { 0xa180 },
+ .prio_fwd_disable = 0,
+ .prio = 0,
+ .urg_fwd = 1,
+ },
.num_links = 1,
.link_nodes = { &qns_mem_noc_hf },
};
@@ -597,6 +807,13 @@ static struct qcom_icc_node qnm_video0 = {
.name = "qnm_video0",
.channels = 1,
.buswidth = 32,
+ .qosbox = &(const struct qcom_icc_qosbox) {
+ .num_ports = 1,
+ .port_offsets = { 0x2a100 },
+ .prio_fwd_disable = 0,
+ .prio = 0,
+ .urg_fwd = 1,
+ },
.num_links = 1,
.link_nodes = { &qns_mem_noc_sf },
};
@@ -605,6 +822,13 @@ static struct qcom_icc_node qnm_video_cvp = {
.name = "qnm_video_cvp",
.channels = 1,
.buswidth = 32,
+ .qosbox = &(const struct qcom_icc_qosbox) {
+ .num_ports = 1,
+ .port_offsets = { 0x2a200 },
+ .prio_fwd_disable = 0,
+ .prio = 0,
+ .urg_fwd = 1,
+ },
.num_links = 1,
.link_nodes = { &qns_mem_noc_sf },
};
@@ -613,6 +837,13 @@ static struct qcom_icc_node qnm_video_v_cpu = {
.name = "qnm_video_v_cpu",
.channels = 1,
.buswidth = 8,
+ .qosbox = &(const struct qcom_icc_qosbox) {
+ .num_ports = 1,
+ .port_offsets = { 0x2a280 },
+ .prio_fwd_disable = 0,
+ .prio = 0,
+ .urg_fwd = 1,
+ },
.num_links = 1,
.link_nodes = { &qns_mem_noc_sf },
};
@@ -637,6 +868,13 @@ static struct qcom_icc_node xm_pcie3_0 = {
.name = "xm_pcie3_0",
.channels = 1,
.buswidth = 16,
+ .qosbox = &(const struct qcom_icc_qosbox) {
+ .num_ports = 1,
+ .port_offsets = { 0xb000 },
+ .prio_fwd_disable = 1,
+ .prio = 2,
+ .urg_fwd = 0,
+ },
.num_links = 1,
.link_nodes = { &qns_pcie_mem_noc },
};
@@ -645,6 +883,13 @@ static struct qcom_icc_node xm_pcie3_1 = {
.name = "xm_pcie3_1",
.channels = 1,
.buswidth = 32,
+ .qosbox = &(const struct qcom_icc_qosbox) {
+ .num_ports = 1,
+ .port_offsets = { 0xc000 },
+ .prio_fwd_disable = 1,
+ .prio = 2,
+ .urg_fwd = 0,
+ },
.num_links = 1,
.link_nodes = { &qns_pcie_mem_noc },
};
@@ -653,6 +898,13 @@ static struct qcom_icc_node qhm_gic = {
.name = "qhm_gic",
.channels = 1,
.buswidth = 4,
+ .qosbox = &(const struct qcom_icc_qosbox) {
+ .num_ports = 1,
+ .port_offsets = { 0x14000 },
+ .prio_fwd_disable = 1,
+ .prio = 2,
+ .urg_fwd = 0,
+ },
.num_links = 1,
.link_nodes = { &qns_gemnoc_sf },
};
@@ -677,6 +929,13 @@ static struct qcom_icc_node qnm_lpass_noc = {
.name = "qnm_lpass_noc",
.channels = 1,
.buswidth = 16,
+ .qosbox = &(const struct qcom_icc_qosbox) {
+ .num_ports = 1,
+ .port_offsets = { 0x12000 },
+ .prio_fwd_disable = 0,
+ .prio = 0,
+ .urg_fwd = 1,
+ },
.num_links = 1,
.link_nodes = { &qns_gemnoc_sf },
};
@@ -693,6 +952,13 @@ static struct qcom_icc_node qxm_pimem = {
.name = "qxm_pimem",
.channels = 1,
.buswidth = 8,
+ .qosbox = &(const struct qcom_icc_qosbox) {
+ .num_ports = 1,
+ .port_offsets = { 0x13000 },
+ .prio_fwd_disable = 1,
+ .prio = 2,
+ .urg_fwd = 0,
+ },
.num_links = 1,
.link_nodes = { &qns_gemnoc_gc },
};
@@ -701,6 +967,13 @@ static struct qcom_icc_node xm_gic = {
.name = "xm_gic",
.channels = 1,
.buswidth = 8,
+ .qosbox = &(const struct qcom_icc_qosbox) {
+ .num_ports = 1,
+ .port_offsets = { 0x15000 },
+ .prio_fwd_disable = 1,
+ .prio = 2,
+ .urg_fwd = 0,
+ },
.num_links = 1,
.link_nodes = { &qns_gemnoc_gc },
};
@@ -1599,11 +1872,21 @@ static struct qcom_icc_node * const aggre1_noc_nodes[] = {
[SLAVE_A1NOC_SNOC] = &qns_a1noc_snoc,
};
+static const struct regmap_config qcs8300_aggre1_noc_regmap_config = {
+ .reg_bits = 32,
+ .reg_stride = 4,
+ .val_bits = 32,
+ .max_register = 0x17080,
+ .fast_io = true,
+};
+
static const struct qcom_icc_desc qcs8300_aggre1_noc = {
+ .config = &qcs8300_aggre1_noc_regmap_config,
.nodes = aggre1_noc_nodes,
.num_nodes = ARRAY_SIZE(aggre1_noc_nodes),
.bcms = aggre1_noc_bcms,
.num_bcms = ARRAY_SIZE(aggre1_noc_bcms),
+ .qos_requires_clocks = true,
};
static struct qcom_icc_bcm * const aggre2_noc_bcms[] = {
@@ -1624,11 +1907,21 @@ static struct qcom_icc_node * const aggre2_noc_nodes[] = {
[SLAVE_A2NOC_SNOC] = &qns_a2noc_snoc,
};
+static const struct regmap_config qcs8300_aggre2_noc_regmap_config = {
+ .reg_bits = 32,
+ .reg_stride = 4,
+ .val_bits = 32,
+ .max_register = 0x1a080,
+ .fast_io = true,
+};
+
static const struct qcom_icc_desc qcs8300_aggre2_noc = {
+ .config = &qcs8300_aggre2_noc_regmap_config,
.nodes = aggre2_noc_nodes,
.num_nodes = ARRAY_SIZE(aggre2_noc_nodes),
.bcms = aggre2_noc_bcms,
.num_bcms = ARRAY_SIZE(aggre2_noc_bcms),
+ .qos_requires_clocks = true,
};
static struct qcom_icc_bcm * const clk_virt_bcms[] = {
@@ -1740,7 +2033,16 @@ static struct qcom_icc_node * const config_noc_nodes[] = {
[SLAVE_TCU] = &xs_sys_tcu_cfg,
};
+static const struct regmap_config qcs8300_config_noc_regmap_config = {
+ .reg_bits = 32,
+ .reg_stride = 4,
+ .val_bits = 32,
+ .max_register = 0x13080,
+ .fast_io = true,
+};
+
static const struct qcom_icc_desc qcs8300_config_noc = {
+ .config = &qcs8300_config_noc_regmap_config,
.nodes = config_noc_nodes,
.num_nodes = ARRAY_SIZE(config_noc_nodes),
.bcms = config_noc_bcms,
@@ -1753,7 +2055,16 @@ static struct qcom_icc_node * const dc_noc_nodes[] = {
[SLAVE_GEM_NOC_CFG] = &qns_gemnoc,
};
+static const struct regmap_config qcs8300_dc_noc_regmap_config = {
+ .reg_bits = 32,
+ .reg_stride = 4,
+ .val_bits = 32,
+ .max_register = 0x5080,
+ .fast_io = true,
+};
+
static const struct qcom_icc_desc qcs8300_dc_noc = {
+ .config = &qcs8300_dc_noc_regmap_config,
.nodes = dc_noc_nodes,
.num_nodes = ARRAY_SIZE(dc_noc_nodes),
};
@@ -1786,11 +2097,21 @@ static struct qcom_icc_node * const gem_noc_nodes[] = {
[SLAVE_SERVICE_GEM_NOC2] = &srvc_sys_gemnoc_2,
};
+static const struct regmap_config qcs8300_gem_noc_regmap_config = {
+ .reg_bits = 32,
+ .reg_stride = 4,
+ .val_bits = 32,
+ .max_register = 0xf7080,
+ .fast_io = true,
+};
+
static const struct qcom_icc_desc qcs8300_gem_noc = {
+ .config = &qcs8300_gem_noc_regmap_config,
.nodes = gem_noc_nodes,
.num_nodes = ARRAY_SIZE(gem_noc_nodes),
.bcms = gem_noc_bcms,
.num_bcms = ARRAY_SIZE(gem_noc_bcms),
+ .qos_requires_clocks = true,
};
static struct qcom_icc_bcm * const gpdsp_anoc_bcms[] = {
@@ -1803,7 +2124,16 @@ static struct qcom_icc_node * const gpdsp_anoc_nodes[] = {
[SLAVE_GP_DSP_SAIL_NOC] = &qns_gp_dsp_sail_noc,
};
+static const struct regmap_config qcs8300_gpdsp_anoc_regmap_config = {
+ .reg_bits = 32,
+ .reg_stride = 4,
+ .val_bits = 32,
+ .max_register = 0xd080,
+ .fast_io = true,
+};
+
static const struct qcom_icc_desc qcs8300_gpdsp_anoc = {
+ .config = &qcs8300_gpdsp_anoc_regmap_config,
.nodes = gpdsp_anoc_nodes,
.num_nodes = ARRAY_SIZE(gpdsp_anoc_nodes),
.bcms = gpdsp_anoc_bcms,
@@ -1826,7 +2156,16 @@ static struct qcom_icc_node * const lpass_ag_noc_nodes[] = {
[SLAVE_SERVICE_LPASS_AG_NOC] = &srvc_niu_lpass_agnoc,
};
+static const struct regmap_config qcs8300_lpass_ag_noc_regmap_config = {
+ .reg_bits = 32,
+ .reg_stride = 4,
+ .val_bits = 32,
+ .max_register = 0x17200,
+ .fast_io = true,
+};
+
static const struct qcom_icc_desc qcs8300_lpass_ag_noc = {
+ .config = &qcs8300_lpass_ag_noc_regmap_config,
.nodes = lpass_ag_noc_nodes,
.num_nodes = ARRAY_SIZE(lpass_ag_noc_nodes),
.bcms = lpass_ag_noc_bcms,
@@ -1872,7 +2211,16 @@ static struct qcom_icc_node * const mmss_noc_nodes[] = {
[SLAVE_SERVICE_MNOC_SF] = &srvc_mnoc_sf,
};
+static const struct regmap_config qcs8300_mmss_noc_regmap_config = {
+ .reg_bits = 32,
+ .reg_stride = 4,
+ .val_bits = 32,
+ .max_register = 0x40000,
+ .fast_io = true,
+};
+
static const struct qcom_icc_desc qcs8300_mmss_noc = {
+ .config = &qcs8300_mmss_noc_regmap_config,
.nodes = mmss_noc_nodes,
.num_nodes = ARRAY_SIZE(mmss_noc_nodes),
.bcms = mmss_noc_bcms,
@@ -1892,7 +2240,16 @@ static struct qcom_icc_node * const nspa_noc_nodes[] = {
[SLAVE_SERVICE_NSP_NOC] = &service_nsp_noc,
};
+static const struct regmap_config qcs8300_nspa_noc_regmap_config = {
+ .reg_bits = 32,
+ .reg_stride = 4,
+ .val_bits = 32,
+ .max_register = 0x16080,
+ .fast_io = true,
+};
+
static const struct qcom_icc_desc qcs8300_nspa_noc = {
+ .config = &qcs8300_nspa_noc_regmap_config,
.nodes = nspa_noc_nodes,
.num_nodes = ARRAY_SIZE(nspa_noc_nodes),
.bcms = nspa_noc_bcms,
@@ -1909,7 +2266,16 @@ static struct qcom_icc_node * const pcie_anoc_nodes[] = {
[SLAVE_ANOC_PCIE_GEM_NOC] = &qns_pcie_mem_noc,
};
+static const struct regmap_config qcs8300_pcie_anoc_regmap_config = {
+ .reg_bits = 32,
+ .reg_stride = 4,
+ .val_bits = 32,
+ .max_register = 0xc080,
+ .fast_io = true,
+};
+
static const struct qcom_icc_desc qcs8300_pcie_anoc = {
+ .config = &qcs8300_pcie_anoc_regmap_config,
.nodes = pcie_anoc_nodes,
.num_nodes = ARRAY_SIZE(pcie_anoc_nodes),
.bcms = pcie_anoc_bcms,
@@ -1937,7 +2303,16 @@ static struct qcom_icc_node * const system_noc_nodes[] = {
[SLAVE_SERVICE_SNOC] = &srvc_snoc,
};
+static const struct regmap_config qcs8300_system_noc_regmap_config = {
+ .reg_bits = 32,
+ .reg_stride = 4,
+ .val_bits = 32,
+ .max_register = 0x15080,
+ .fast_io = true,
+};
+
static const struct qcom_icc_desc qcs8300_system_noc = {
+ .config = &qcs8300_system_noc_regmap_config,
.nodes = system_noc_nodes,
.num_nodes = ARRAY_SIZE(system_noc_nodes),
.bcms = system_noc_bcms,
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index 5cc79d1517af..00683bf06258 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -116,7 +116,8 @@ config RPMB
config TI_FPC202
tristate "TI FPC202 Dual Port Controller"
depends on I2C
- select GPIOLIB
+ depends on GPIOLIB
+ depends on LEDS_CLASS
select I2C_ATR
help
If you say yes here you get support for the Texas Instruments FPC202
diff --git a/drivers/misc/amd-sbi/rmi-core.c b/drivers/misc/amd-sbi/rmi-core.c
index c3a58912d6db..d4238ebad3c6 100644
--- a/drivers/misc/amd-sbi/rmi-core.c
+++ b/drivers/misc/amd-sbi/rmi-core.c
@@ -48,7 +48,7 @@
/* CPUID MCAMSR mask & index */
#define CPUID_MCA_THRD_INDEX 32
#define CPUID_MCA_FUNC_MASK GENMASK(31, 0)
-#define CPUID_EXT_FUNC_INDEX 56
+#define CPUID_EXT_FUNC_INDEX 48
/* input for bulk write to CPUID protocol */
struct cpu_msr_indata {
@@ -214,6 +214,7 @@ static int rmi_cpuid_read(struct sbrmi_data *data,
goto exit_unlock;
break;
case 0x21:
+ case 0x31:
ret = rmi_cpuid_input_ext(data, msg, thread);
if (ret)
goto exit_unlock;
@@ -327,6 +328,7 @@ static int rmi_mca_msr_read(struct sbrmi_data *data,
goto exit_unlock;
break;
case 0x21:
+ case 0x31:
ret = rmi_mcamsr_input_ext(data, msg, thread);
if (ret)
goto exit_unlock;
diff --git a/drivers/misc/amd-sbi/rmi-i2c.c b/drivers/misc/amd-sbi/rmi-i2c.c
index f0cc99000b69..37e5ea83bf97 100644
--- a/drivers/misc/amd-sbi/rmi-i2c.c
+++ b/drivers/misc/amd-sbi/rmi-i2c.c
@@ -170,6 +170,16 @@ static int sbrmi_i3c_probe(struct i3c_device *i3cdev)
struct regmap *regmap;
int rev, ret;
+ /*
+ * AMD OOB devices are distinguished by their Instance ID.
+ * For SBRMI, the Instance ID is 1. Since the device ID match
+ * does not account for the Instance ID, the following check
+ * ensures that only the SBRMI device is probed, excluding
+ * other OOB devices.
+ */
+ if (I3C_PID_INSTANCE_ID(i3cdev->desc->info.pid) != 1)
+ return -ENXIO;
+
regmap = devm_regmap_init_i3c(i3cdev, &sbrmi_regmap_config);
if (IS_ERR(regmap))
return PTR_ERR(regmap);
@@ -212,6 +222,10 @@ static void sbrmi_i3c_remove(struct i3c_device *i3cdev)
static const struct i3c_device_id sbrmi_i3c_id[] = {
/* PID for AMD SBRMI device */
I3C_DEVICE_EXTRA_INFO(0x112, 0x0, 0x2, NULL),
+ I3C_DEVICE_EXTRA_INFO(0x0, 0x0, 0x118, NULL), /* Socket:0, Venice */
+ I3C_DEVICE_EXTRA_INFO(0x0, 0x100, 0x118, NULL), /* Socket:1, Venice */
+ I3C_DEVICE_EXTRA_INFO(0x112, 0x0, 0x119, NULL), /* Socket:0, Venice */
+ I3C_DEVICE_EXTRA_INFO(0x112, 0x100, 0x119, NULL), /* Socket:1, Venice */
{}
};
MODULE_DEVICE_TABLE(i3c, sbrmi_i3c_id);
diff --git a/drivers/misc/ibmasm/ibmasmfs.c b/drivers/misc/ibmasm/ibmasmfs.c
index f68a8957b98f..dfdfa9ba4747 100644
--- a/drivers/misc/ibmasm/ibmasmfs.c
+++ b/drivers/misc/ibmasm/ibmasmfs.c
@@ -303,6 +303,8 @@ static ssize_t command_file_write(struct file *file, const char __user *ubuff, s
return -EINVAL;
if (count == 0 || count > IBMASM_CMD_MAX_BUFFER_SIZE)
return 0;
+ if (count < sizeof(struct dot_command_header))
+ return -EINVAL;
if (*offset != 0)
return 0;
@@ -319,6 +321,11 @@ static ssize_t command_file_write(struct file *file, const char __user *ubuff, s
return -EFAULT;
}
+ if (count < get_dot_command_size(cmd->buffer)) {
+ command_put(cmd);
+ return -EINVAL;
+ }
+
spin_lock_irqsave(&command_data->sp->lock, flags);
if (command_data->command) {
spin_unlock_irqrestore(&command_data->sp->lock, flags);
diff --git a/drivers/misc/ibmasm/lowlevel.c b/drivers/misc/ibmasm/lowlevel.c
index 6922dc6c10db..5313230f36ad 100644
--- a/drivers/misc/ibmasm/lowlevel.c
+++ b/drivers/misc/ibmasm/lowlevel.c
@@ -19,17 +19,21 @@ static struct i2o_header header = I2O_HEADER_TEMPLATE;
int ibmasm_send_i2o_message(struct service_processor *sp)
{
u32 mfa;
- unsigned int command_size;
+ size_t command_size;
struct i2o_message *message;
struct command *command = sp->current_command;
+ command_size = get_dot_command_size(command->buffer);
+ if (command_size > command->buffer_size)
+ return 1;
+ if (command_size > I2O_COMMAND_SIZE)
+ command_size = I2O_COMMAND_SIZE;
+
mfa = get_mfa_inbound(sp->base_address);
if (!mfa)
return 1;
- command_size = get_dot_command_size(command->buffer);
- header.message_size = outgoing_message_size(command_size);
-
+ header.message_size = outgoing_message_size((unsigned int)command_size);
message = get_i2o_message(sp->base_address, mfa);
memcpy_toio(&message->header, &header, sizeof(struct i2o_header));
diff --git a/drivers/misc/ibmasm/remote.c b/drivers/misc/ibmasm/remote.c
index ec816d3b38cb..521531738c9a 100644
--- a/drivers/misc/ibmasm/remote.c
+++ b/drivers/misc/ibmasm/remote.c
@@ -177,6 +177,11 @@ void ibmasm_handle_mouse_interrupt(struct service_processor *sp)
writer = get_queue_writer(sp);
while (reader != writer) {
+ if (reader >= REMOTE_QUEUE_SIZE || writer >= REMOTE_QUEUE_SIZE) {
+ set_queue_reader(sp, 0);
+ break;
+ }
+
memcpy_fromio(&input, get_queue_entry(sp, reader),
sizeof(struct remote_input));
diff --git a/drivers/misc/mei/Kconfig b/drivers/misc/mei/Kconfig
index 094fb1dde0fe..2d1bc5b4d11b 100644
--- a/drivers/misc/mei/Kconfig
+++ b/drivers/misc/mei/Kconfig
@@ -59,6 +59,17 @@ config INTEL_MEI_GSC
tasks such as graphics card firmware update and security
tasks.
+config INTEL_MEI_CSC
+ tristate "Intel MEI CSC embedded device"
+ depends on INTEL_MEI_ME
+ help
+ Intel PCI driver for the chassis controller embedded in Intel graphics devices.
+
+ An MEI device here called CSC can be embedded in discrete
+ Intel graphics devices, to support a range of chassis
+ tasks such as graphics card firmware update and security
+ tasks.
+
config INTEL_MEI_VSC_HW
tristate "Intel visual sensing controller device transport driver"
depends on ACPI && SPI
diff --git a/drivers/misc/mei/Makefile b/drivers/misc/mei/Makefile
index a203ed766b33..9a6aa335921e 100644
--- a/drivers/misc/mei/Makefile
+++ b/drivers/misc/mei/Makefile
@@ -21,6 +21,9 @@ mei-me-objs += hw-me.o
obj-$(CONFIG_INTEL_MEI_GSC) += mei-gsc.o
mei-gsc-objs := gsc-me.o
+obj-$(CONFIG_INTEL_MEI_CSC) += mei-csc.o
+mei-csc-objs := pci-csc.o
+
obj-$(CONFIG_INTEL_MEI_TXE) += mei-txe.o
mei-txe-objs := pci-txe.o
mei-txe-objs += hw-txe.o
diff --git a/drivers/misc/mei/bus-fixup.c b/drivers/misc/mei/bus-fixup.c
index e6a1d3534663..bea7a47d216e 100644
--- a/drivers/misc/mei/bus-fixup.c
+++ b/drivers/misc/mei/bus-fixup.c
@@ -303,9 +303,9 @@ static void mei_wd(struct mei_cl_device *cldev)
{
struct pci_dev *pdev = to_pci_dev(cldev->dev.parent);
- if (pdev->device == MEI_DEV_ID_WPT_LP ||
- pdev->device == MEI_DEV_ID_SPT ||
- pdev->device == MEI_DEV_ID_SPT_H)
+ if (pdev->device == PCI_DEVICE_ID_INTEL_MEI_WPT_LP ||
+ pdev->device == PCI_DEVICE_ID_INTEL_MEI_SPT ||
+ pdev->device == PCI_DEVICE_ID_INTEL_MEI_SPT_H)
cldev->me_cl->props.protocol_version = 0x2;
cldev->do_match = 1;
diff --git a/drivers/misc/mei/bus.c b/drivers/misc/mei/bus.c
index f739dbcdb04c..fcde082eb5e3 100644
--- a/drivers/misc/mei/bus.c
+++ b/drivers/misc/mei/bus.c
@@ -602,6 +602,19 @@ void mei_cldev_set_drvdata(struct mei_cl_device *cldev, void *data)
EXPORT_SYMBOL_GPL(mei_cldev_set_drvdata);
/**
+ * mei_cldev_uuid - return uuid of the underlying me client
+ *
+ * @cldev: mei client device
+ *
+ * Return: me client uuid
+ */
+const uuid_le *mei_cldev_uuid(const struct mei_cl_device *cldev)
+{
+ return mei_me_cl_uuid(cldev->me_cl);
+}
+EXPORT_SYMBOL_GPL(mei_cldev_uuid);
+
+/**
* mei_cldev_ver - return protocol version of the underlying me client
*
* @cldev: mei client device
diff --git a/drivers/misc/mei/gsc-me.c b/drivers/misc/mei/gsc-me.c
index 93cba090ea08..73d5beeb9c34 100644
--- a/drivers/misc/mei/gsc-me.c
+++ b/drivers/misc/mei/gsc-me.c
@@ -23,11 +23,12 @@
#define MEI_GSC_RPM_TIMEOUT 500
-static int mei_gsc_read_hfs(const struct mei_device *dev, int where, u32 *val)
+static int mei_gsc_read_hfs(const struct mei_device *dev, int where, const char *name, u32 *val)
{
struct mei_me_hw *hw = to_me_hw(dev);
*val = ioread32(hw->mem_addr + where + 0xC00);
+ trace_mei_reg_read(&dev->dev, name, where, *val);
return 0;
}
diff --git a/drivers/misc/mei/hw-me-regs.h b/drivers/misc/mei/hw-me-regs.h
index fa30899a5fa2..f145e8e36cb3 100644
--- a/drivers/misc/mei/hw-me-regs.h
+++ b/drivers/misc/mei/hw-me-regs.h
@@ -9,120 +9,123 @@
/*
* MEI device IDs
*/
-#define MEI_DEV_ID_82946GZ 0x2974 /* 82946GZ/GL */
-#define MEI_DEV_ID_82G35 0x2984 /* 82G35 Express */
-#define MEI_DEV_ID_82Q965 0x2994 /* 82Q963/Q965 */
-#define MEI_DEV_ID_82G965 0x29A4 /* 82P965/G965 */
+#define PCI_DEVICE_ID_INTEL_MEI_82946GZ 0x2974 /* 82946GZ/GL */
+#define PCI_DEVICE_ID_INTEL_MEI_82G35 0x2984 /* 82G35 Express */
+#define PCI_DEVICE_ID_INTEL_MEI_82Q965 0x2994 /* 82Q963/Q965 */
+#define PCI_DEVICE_ID_INTEL_MEI_82G965 0x29A4 /* 82P965/G965 */
-#define MEI_DEV_ID_82GM965 0x2A04 /* Mobile PM965/GM965 */
-#define MEI_DEV_ID_82GME965 0x2A14 /* Mobile GME965/GLE960 */
+#define PCI_DEVICE_ID_INTEL_MEI_82GM965 0x2A04 /* Mobile PM965/GM965 */
+#define PCI_DEVICE_ID_INTEL_MEI_82GME965 0x2A14 /* Mobile GME965/GLE960 */
-#define MEI_DEV_ID_ICH9_82Q35 0x29B4 /* 82Q35 Express */
-#define MEI_DEV_ID_ICH9_82G33 0x29C4 /* 82G33/G31/P35/P31 Express */
-#define MEI_DEV_ID_ICH9_82Q33 0x29D4 /* 82Q33 Express */
-#define MEI_DEV_ID_ICH9_82X38 0x29E4 /* 82X38/X48 Express */
-#define MEI_DEV_ID_ICH9_3200 0x29F4 /* 3200/3210 Server */
+#define PCI_DEVICE_ID_INTEL_MEI_ICH9_82Q35 0x29B4 /* 82Q35 Express */
+#define PCI_DEVICE_ID_INTEL_MEI_ICH9_82G33 0x29C4 /* 82G33/G31/P35/P31 Express */
+#define PCI_DEVICE_ID_INTEL_MEI_ICH9_82Q33 0x29D4 /* 82Q33 Express */
+#define PCI_DEVICE_ID_INTEL_MEI_ICH9_82X38 0x29E4 /* 82X38/X48 Express */
+#define PCI_DEVICE_ID_INTEL_MEI_ICH9_3200 0x29F4 /* 3200/3210 Server */
-#define MEI_DEV_ID_ICH9_6 0x28B4 /* Bearlake */
-#define MEI_DEV_ID_ICH9_7 0x28C4 /* Bearlake */
-#define MEI_DEV_ID_ICH9_8 0x28D4 /* Bearlake */
-#define MEI_DEV_ID_ICH9_9 0x28E4 /* Bearlake */
-#define MEI_DEV_ID_ICH9_10 0x28F4 /* Bearlake */
+#define PCI_DEVICE_ID_INTEL_MEI_ICH9_6 0x28B4 /* Bearlake */
+#define PCI_DEVICE_ID_INTEL_MEI_ICH9_7 0x28C4 /* Bearlake */
+#define PCI_DEVICE_ID_INTEL_MEI_ICH9_8 0x28D4 /* Bearlake */
+#define PCI_DEVICE_ID_INTEL_MEI_ICH9_9 0x28E4 /* Bearlake */
+#define PCI_DEVICE_ID_INTEL_MEI_ICH9_10 0x28F4 /* Bearlake */
-#define MEI_DEV_ID_ICH9M_1 0x2A44 /* Cantiga */
-#define MEI_DEV_ID_ICH9M_2 0x2A54 /* Cantiga */
-#define MEI_DEV_ID_ICH9M_3 0x2A64 /* Cantiga */
-#define MEI_DEV_ID_ICH9M_4 0x2A74 /* Cantiga */
+#define PCI_DEVICE_ID_INTEL_MEI_ICH9M_1 0x2A44 /* Cantiga */
+#define PCI_DEVICE_ID_INTEL_MEI_ICH9M_2 0x2A54 /* Cantiga */
+#define PCI_DEVICE_ID_INTEL_MEI_ICH9M_3 0x2A64 /* Cantiga */
+#define PCI_DEVICE_ID_INTEL_MEI_ICH9M_4 0x2A74 /* Cantiga */
-#define MEI_DEV_ID_ICH10_1 0x2E04 /* Eaglelake */
-#define MEI_DEV_ID_ICH10_2 0x2E14 /* Eaglelake */
-#define MEI_DEV_ID_ICH10_3 0x2E24 /* Eaglelake */
-#define MEI_DEV_ID_ICH10_4 0x2E34 /* Eaglelake */
+#define PCI_DEVICE_ID_INTEL_MEI_ICH10_1 0x2E04 /* Eaglelake */
+#define PCI_DEVICE_ID_INTEL_MEI_ICH10_2 0x2E14 /* Eaglelake */
+#define PCI_DEVICE_ID_INTEL_MEI_ICH10_3 0x2E24 /* Eaglelake */
+#define PCI_DEVICE_ID_INTEL_MEI_ICH10_4 0x2E34 /* Eaglelake */
-#define MEI_DEV_ID_IBXPK_1 0x3B64 /* Calpella */
-#define MEI_DEV_ID_IBXPK_2 0x3B65 /* Calpella */
+#define PCI_DEVICE_ID_INTEL_MEI_IBXPK_1 0x3B64 /* Calpella */
+#define PCI_DEVICE_ID_INTEL_MEI_IBXPK_2 0x3B65 /* Calpella */
-#define MEI_DEV_ID_CPT_1 0x1C3A /* Couger Point */
-#define MEI_DEV_ID_PBG_1 0x1D3A /* C600/X79 Patsburg */
+#define PCI_DEVICE_ID_INTEL_MEI_CPT_1 0x1C3A /* Couger Point */
+#define PCI_DEVICE_ID_INTEL_MEI_PBG_1 0x1D3A /* C600/X79 Patsburg */
-#define MEI_DEV_ID_PPT_1 0x1E3A /* Panther Point */
-#define MEI_DEV_ID_PPT_2 0x1CBA /* Panther Point */
-#define MEI_DEV_ID_PPT_3 0x1DBA /* Panther Point */
+#define PCI_DEVICE_ID_INTEL_MEI_PPT_1 0x1E3A /* Panther Point */
+#define PCI_DEVICE_ID_INTEL_MEI_PPT_2 0x1CBA /* Panther Point */
+#define PCI_DEVICE_ID_INTEL_MEI_PPT_3 0x1DBA /* Panther Point */
-#define MEI_DEV_ID_LPT_H 0x8C3A /* Lynx Point H */
-#define MEI_DEV_ID_LPT_W 0x8D3A /* Lynx Point - Wellsburg */
-#define MEI_DEV_ID_LPT_LP 0x9C3A /* Lynx Point LP */
-#define MEI_DEV_ID_LPT_HR 0x8CBA /* Lynx Point H Refresh */
+#define PCI_DEVICE_ID_INTEL_MEI_LPT_H 0x8C3A /* Lynx Point H */
+#define PCI_DEVICE_ID_INTEL_MEI_LPT_W 0x8D3A /* Lynx Point - Wellsburg */
+#define PCI_DEVICE_ID_INTEL_MEI_LPT_LP 0x9C3A /* Lynx Point LP */
+#define PCI_DEVICE_ID_INTEL_MEI_LPT_HR 0x8CBA /* Lynx Point H Refresh */
-#define MEI_DEV_ID_WPT_LP 0x9CBA /* Wildcat Point LP */
-#define MEI_DEV_ID_WPT_LP_2 0x9CBB /* Wildcat Point LP 2 */
+#define PCI_DEVICE_ID_INTEL_MEI_WPT_LP 0x9CBA /* Wildcat Point LP */
+#define PCI_DEVICE_ID_INTEL_MEI_WPT_LP_2 0x9CBB /* Wildcat Point LP 2 */
-#define MEI_DEV_ID_SPT 0x9D3A /* Sunrise Point */
-#define MEI_DEV_ID_SPT_2 0x9D3B /* Sunrise Point 2 */
-#define MEI_DEV_ID_SPT_3 0x9D3E /* Sunrise Point 3 (iToutch) */
-#define MEI_DEV_ID_SPT_H 0xA13A /* Sunrise Point H */
-#define MEI_DEV_ID_SPT_H_2 0xA13B /* Sunrise Point H 2 */
+#define PCI_DEVICE_ID_INTEL_MEI_SPT 0x9D3A /* Sunrise Point */
+#define PCI_DEVICE_ID_INTEL_MEI_SPT_2 0x9D3B /* Sunrise Point 2 */
+#define PCI_DEVICE_ID_INTEL_MEI_SPT_3 0x9D3E /* Sunrise Point 3 (iToutch) */
+#define PCI_DEVICE_ID_INTEL_MEI_SPT_H 0xA13A /* Sunrise Point H */
+#define PCI_DEVICE_ID_INTEL_MEI_SPT_H_2 0xA13B /* Sunrise Point H 2 */
-#define MEI_DEV_ID_LBG 0xA1BA /* Lewisburg (SPT) */
+#define PCI_DEVICE_ID_INTEL_MEI_LBG 0xA1BA /* Lewisburg (SPT) */
-#define MEI_DEV_ID_BXT_M 0x1A9A /* Broxton M */
-#define MEI_DEV_ID_APL_I 0x5A9A /* Apollo Lake I */
+#define PCI_DEVICE_ID_INTEL_MEI_BXT_M 0x1A9A /* Broxton M */
+#define PCI_DEVICE_ID_INTEL_MEI_APL_I 0x5A9A /* Apollo Lake I */
-#define MEI_DEV_ID_DNV_IE 0x19E5 /* Denverton IE */
+#define PCI_DEVICE_ID_INTEL_MEI_DNV_IE 0x19E5 /* Denverton IE */
-#define MEI_DEV_ID_GLK 0x319A /* Gemini Lake */
+#define PCI_DEVICE_ID_INTEL_MEI_GLK 0x319A /* Gemini Lake */
-#define MEI_DEV_ID_KBP 0xA2BA /* Kaby Point */
-#define MEI_DEV_ID_KBP_2 0xA2BB /* Kaby Point 2 */
-#define MEI_DEV_ID_KBP_3 0xA2BE /* Kaby Point 3 (iTouch) */
+#define PCI_DEVICE_ID_INTEL_MEI_KBP 0xA2BA /* Kaby Point */
+#define PCI_DEVICE_ID_INTEL_MEI_KBP_2 0xA2BB /* Kaby Point 2 */
+#define PCI_DEVICE_ID_INTEL_MEI_KBP_3 0xA2BE /* Kaby Point 3 (iTouch) */
-#define MEI_DEV_ID_CNP_LP 0x9DE0 /* Cannon Point LP */
-#define MEI_DEV_ID_CNP_LP_3 0x9DE4 /* Cannon Point LP 3 (iTouch) */
-#define MEI_DEV_ID_CNP_H 0xA360 /* Cannon Point H */
-#define MEI_DEV_ID_CNP_H_3 0xA364 /* Cannon Point H 3 (iTouch) */
+#define PCI_DEVICE_ID_INTEL_MEI_CNP_LP 0x9DE0 /* Cannon Point LP */
+#define PCI_DEVICE_ID_INTEL_MEI_CNP_LP_3 0x9DE4 /* Cannon Point LP 3 (iTouch) */
+#define PCI_DEVICE_ID_INTEL_MEI_CNP_H 0xA360 /* Cannon Point H */
+#define PCI_DEVICE_ID_INTEL_MEI_CNP_H_3 0xA364 /* Cannon Point H 3 (iTouch) */
-#define MEI_DEV_ID_CMP_LP 0x02e0 /* Comet Point LP */
-#define MEI_DEV_ID_CMP_LP_3 0x02e4 /* Comet Point LP 3 (iTouch) */
+#define PCI_DEVICE_ID_INTEL_MEI_CMP_LP 0x02e0 /* Comet Point LP */
+#define PCI_DEVICE_ID_INTEL_MEI_CMP_LP_3 0x02e4 /* Comet Point LP 3 (iTouch) */
-#define MEI_DEV_ID_CMP_V 0xA3BA /* Comet Point Lake V */
+#define PCI_DEVICE_ID_INTEL_MEI_CMP_V 0xA3BA /* Comet Point Lake V */
-#define MEI_DEV_ID_CMP_H 0x06e0 /* Comet Lake H */
-#define MEI_DEV_ID_CMP_H_3 0x06e4 /* Comet Lake H 3 (iTouch) */
+#define PCI_DEVICE_ID_INTEL_MEI_CMP_H 0x06e0 /* Comet Lake H */
+#define PCI_DEVICE_ID_INTEL_MEI_CMP_H_3 0x06e4 /* Comet Lake H 3 (iTouch) */
-#define MEI_DEV_ID_CDF 0x18D3 /* Cedar Fork */
+#define PCI_DEVICE_ID_INTEL_MEI_CDF 0x18D3 /* Cedar Fork */
-#define MEI_DEV_ID_ICP_LP 0x34E0 /* Ice Lake Point LP */
-#define MEI_DEV_ID_ICP_N 0x38E0 /* Ice Lake Point N */
+#define PCI_DEVICE_ID_INTEL_MEI_ICP_LP 0x34E0 /* Ice Lake Point LP */
+#define PCI_DEVICE_ID_INTEL_MEI_ICP_N 0x38E0 /* Ice Lake Point N */
-#define MEI_DEV_ID_JSP_N 0x4DE0 /* Jasper Lake Point N */
+#define PCI_DEVICE_ID_INTEL_MEI_JSP_N 0x4DE0 /* Jasper Lake Point N */
-#define MEI_DEV_ID_TGP_LP 0xA0E0 /* Tiger Lake Point LP */
-#define MEI_DEV_ID_TGP_H 0x43E0 /* Tiger Lake Point H */
+#define PCI_DEVICE_ID_INTEL_MEI_TGP_LP 0xA0E0 /* Tiger Lake Point LP */
+#define PCI_DEVICE_ID_INTEL_MEI_TGP_H 0x43E0 /* Tiger Lake Point H */
-#define MEI_DEV_ID_MCC 0x4B70 /* Mule Creek Canyon (EHL) */
-#define MEI_DEV_ID_MCC_4 0x4B75 /* Mule Creek Canyon 4 (EHL) */
+#define PCI_DEVICE_ID_INTEL_MEI_MCC 0x4B70 /* Mule Creek Canyon (EHL) */
+#define PCI_DEVICE_ID_INTEL_MEI_MCC_4 0x4B75 /* Mule Creek Canyon 4 (EHL) */
-#define MEI_DEV_ID_EBG 0x1BE0 /* Emmitsburg WS */
+#define PCI_DEVICE_ID_INTEL_MEI_EBG 0x1BE0 /* Emmitsburg WS */
-#define MEI_DEV_ID_ADP_S 0x7AE8 /* Alder Lake Point S */
-#define MEI_DEV_ID_ADP_LP 0x7A60 /* Alder Lake Point LP */
-#define MEI_DEV_ID_ADP_P 0x51E0 /* Alder Lake Point P */
-#define MEI_DEV_ID_ADP_N 0x54E0 /* Alder Lake Point N */
+#define PCI_DEVICE_ID_INTEL_MEI_ADP_S 0x7AE8 /* Alder Lake Point S */
+#define PCI_DEVICE_ID_INTEL_MEI_ADP_LP 0x7A60 /* Alder Lake Point LP */
+#define PCI_DEVICE_ID_INTEL_MEI_ADP_P 0x51E0 /* Alder Lake Point P */
+#define PCI_DEVICE_ID_INTEL_MEI_ADP_N 0x54E0 /* Alder Lake Point N */
-#define MEI_DEV_ID_RPL_S 0x7A68 /* Raptor Lake Point S */
+#define PCI_DEVICE_ID_INTEL_MEI_RPL_S 0x7A68 /* Raptor Lake Point S */
-#define MEI_DEV_ID_MTL_M 0x7E70 /* Meteor Lake Point M */
-#define MEI_DEV_ID_ARL_S 0x7F68 /* Arrow Lake Point S */
-#define MEI_DEV_ID_ARL_H 0x7770 /* Arrow Lake Point H */
+#define PCI_DEVICE_ID_INTEL_MEI_MTL_M 0x7E70 /* Meteor Lake Point M */
+#define PCI_DEVICE_ID_INTEL_MEI_ARL_S 0x7F68 /* Arrow Lake Point S */
+#define PCI_DEVICE_ID_INTEL_MEI_ARL_H 0x7770 /* Arrow Lake Point H */
-#define MEI_DEV_ID_LNL_M 0xA870 /* Lunar Lake Point M */
+#define PCI_DEVICE_ID_INTEL_MEI_LNL_M 0xA870 /* Lunar Lake Point M */
-#define MEI_DEV_ID_PTL_H 0xE370 /* Panther Lake H */
-#define MEI_DEV_ID_PTL_P 0xE470 /* Panther Lake P */
+#define PCI_DEVICE_ID_INTEL_MEI_PTL_H 0xE370 /* Panther Lake H */
+#define PCI_DEVICE_ID_INTEL_MEI_PTL_P 0xE470 /* Panther Lake P */
-#define MEI_DEV_ID_WCL_P 0x4D70 /* Wildcat Lake P */
+#define PCI_DEVICE_ID_INTEL_MEI_WCL_P 0x4D70 /* Wildcat Lake P */
-#define MEI_DEV_ID_NVL_S 0x6E68 /* Nova Lake Point S */
+#define PCI_DEVICE_ID_INTEL_MEI_NVL_S 0x6E68 /* Nova Lake Point S */
+#define PCI_DEVICE_ID_INTEL_MEI_NVL_H 0xD370 /* Nova Lake Point H */
+
+#define PCI_DEVICE_ID_INTEL_MEI_CRI 0x6766 /* Crescent Island */
/*
* MEI HW Section
@@ -134,6 +137,7 @@
# define PCI_CFG_HFS_1_OPMODE_MSK 0xf0000 /* OP MODE Mask: SPS <= 4.0 */
# define PCI_CFG_HFS_1_OPMODE_SPS 0xf0000 /* SPS SKU : SPS <= 4.0 */
#define PCI_CFG_HFS_2 0x48
+# define PCI_CFG_HFS_2_D3_BLOCK BIT(7)
# define PCI_CFG_HFS_2_PM_CMOFF_TO_CMX_ERROR 0x1000000 /* CMoff->CMx wake after an error */
# define PCI_CFG_HFS_2_PM_CM_RESET_ERROR 0x5000000 /* CME reset due to exception */
# define PCI_CFG_HFS_2_PM_EVENT_MASK 0xf000000
diff --git a/drivers/misc/mei/hw-me.c b/drivers/misc/mei/hw-me.c
index 1e4a41ac428f..e286763b52ec 100644
--- a/drivers/misc/mei/hw-me.c
+++ b/drivers/misc/mei/hw-me.c
@@ -215,11 +215,8 @@ static int mei_me_fw_status(struct mei_device *dev,
fw_status->count = fw_src->count;
for (i = 0; i < fw_src->count && i < MEI_FW_STATUS_MAX; i++) {
- ret = hw->read_fws(dev, fw_src->status[i],
+ ret = hw->read_fws(dev, fw_src->status[i], "PCI_CFG_HFS_X",
&fw_status->status[i]);
- trace_mei_pci_cfg_read(&dev->dev, "PCI_CFG_HFS_X",
- fw_src->status[i],
- fw_status->status[i]);
if (ret)
return ret;
}
@@ -227,6 +224,15 @@ static int mei_me_fw_status(struct mei_device *dev,
return 0;
}
+static bool mei_csc_pg_blocked(struct mei_device *dev)
+{
+ struct mei_me_hw *hw = to_me_hw(dev);
+ u32 reg = 0;
+
+ hw->read_fws(dev, PCI_CFG_HFS_2, "PCI_CFG_HFS_2", &reg);
+ return (reg & PCI_CFG_HFS_2_D3_BLOCK) == PCI_CFG_HFS_2_D3_BLOCK;
+}
+
/**
* mei_me_hw_config - configure hw dependent settings
*
@@ -250,8 +256,7 @@ static int mei_me_hw_config(struct mei_device *dev)
hw->hbuf_depth = (hcsr & H_CBD) >> 24;
reg = 0;
- hw->read_fws(dev, PCI_CFG_HFS_1, &reg);
- trace_mei_pci_cfg_read(&dev->dev, "PCI_CFG_HFS_1", PCI_CFG_HFS_1, reg);
+ hw->read_fws(dev, PCI_CFG_HFS_1, "PCI_CFG_HFS_1", &reg);
hw->d0i3_supported =
((reg & PCI_CFG_HFS_1_D0I3_MSK) == PCI_CFG_HFS_1_D0I3_MSK);
@@ -446,8 +451,7 @@ static void mei_gsc_pxp_check(struct mei_device *dev)
if (!kind_is_gsc(dev) && !kind_is_gscfi(dev))
return;
- hw->read_fws(dev, PCI_CFG_HFS_5, &fwsts5);
- trace_mei_pci_cfg_read(&dev->dev, "PCI_CFG_HFS_5", PCI_CFG_HFS_5, fwsts5);
+ hw->read_fws(dev, PCI_CFG_HFS_5, "PCI_CFG_HFS_5", &fwsts5);
if ((fwsts5 & GSC_CFG_HFS_5_BOOT_TYPE_MSK) == GSC_CFG_HFS_5_BOOT_TYPE_PXP) {
if (dev->gsc_reset_to_pxp == MEI_DEV_RESET_TO_PXP_DEFAULT)
@@ -1211,6 +1215,7 @@ static int mei_me_hw_reset(struct mei_device *dev, bool intr_enable)
return ret;
} else {
hw->pg_state = MEI_PG_OFF;
+ dev->pg_blocked = mei_csc_pg_blocked(dev);
}
}
@@ -1299,6 +1304,7 @@ irqreturn_t mei_me_irq_thread_handler(int irq, void *dev_id)
{
struct mei_device *dev = (struct mei_device *) dev_id;
struct list_head cmpl_list;
+ bool pg_blocked;
s32 slots;
u32 hcsr;
int rets = 0;
@@ -1350,6 +1356,14 @@ irqreturn_t mei_me_irq_thread_handler(int irq, void *dev_id)
}
goto end;
}
+
+ pg_blocked = mei_csc_pg_blocked(dev);
+ if (pg_blocked && !dev->pg_blocked) /* PG block requested */
+ pm_request_resume(&dev->dev);
+ else if (!pg_blocked && dev->pg_blocked) /* PG block lifted */
+ pm_request_autosuspend(&dev->dev);
+ dev->pg_blocked = pg_blocked;
+
/* check slots available for reading */
slots = mei_count_full_read_slots(dev);
while (slots > 0) {
@@ -1504,10 +1518,11 @@ static bool mei_me_fw_type_nm(const struct pci_dev *pdev)
{
u32 reg;
unsigned int devfn;
+ int ret;
devfn = PCI_DEVFN(PCI_SLOT(pdev->devfn), 0);
- pci_bus_read_config_dword(pdev->bus, devfn, PCI_CFG_HFS_2, &reg);
- trace_mei_pci_cfg_read(&pdev->dev, "PCI_CFG_HFS_2", PCI_CFG_HFS_2, reg);
+ ret = pci_bus_read_config_dword(pdev->bus, devfn, PCI_CFG_HFS_2, &reg);
+ trace_mei_pci_cfg_read(&pdev->dev, "PCI_CFG_HFS_2", PCI_CFG_HFS_2, reg, ret);
/* make sure that bit 9 (NM) is up and bit 10 (DM) is down */
return (reg & 0x600) == 0x200;
}
@@ -1530,10 +1545,11 @@ static bool mei_me_fw_type_sps_4(const struct pci_dev *pdev)
{
u32 reg;
unsigned int devfn;
+ int ret;
devfn = PCI_DEVFN(PCI_SLOT(pdev->devfn), 0);
- pci_bus_read_config_dword(pdev->bus, devfn, PCI_CFG_HFS_1, &reg);
- trace_mei_pci_cfg_read(&pdev->dev, "PCI_CFG_HFS_1", PCI_CFG_HFS_1, reg);
+ ret = pci_bus_read_config_dword(pdev->bus, devfn, PCI_CFG_HFS_1, &reg);
+ trace_mei_pci_cfg_read(&pdev->dev, "PCI_CFG_HFS_1", PCI_CFG_HFS_1, reg, ret);
return (reg & PCI_CFG_HFS_1_OPMODE_MSK) == PCI_CFG_HFS_1_OPMODE_SPS;
}
@@ -1555,10 +1571,11 @@ static bool mei_me_fw_type_sps_ign(const struct pci_dev *pdev)
u32 reg;
u32 fw_type;
unsigned int devfn;
+ int ret;
devfn = PCI_DEVFN(PCI_SLOT(pdev->devfn), 0);
- pci_bus_read_config_dword(pdev->bus, devfn, PCI_CFG_HFS_3, &reg);
- trace_mei_pci_cfg_read(&pdev->dev, "PCI_CFG_HFS_3", PCI_CFG_HFS_3, reg);
+ ret = pci_bus_read_config_dword(pdev->bus, devfn, PCI_CFG_HFS_3, &reg);
+ trace_mei_pci_cfg_read(&pdev->dev, "PCI_CFG_HFS_3", PCI_CFG_HFS_3, reg, ret);
fw_type = (reg & PCI_CFG_HFS_3_FW_SKU_MSK);
dev_dbg(&pdev->dev, "fw type is %d\n", fw_type);
@@ -1722,6 +1739,13 @@ static const struct mei_cfg mei_me_gscfi_cfg = {
MEI_CFG_FW_VER_SUPP,
};
+/* Chassis System Controller Firmware Interface */
+static const struct mei_cfg mei_me_csc_cfg = {
+ MEI_CFG_TYPE_GSCFI,
+ MEI_CFG_PCH8_HFS,
+ MEI_CFG_FW_VER_SUPP,
+};
+
/*
* mei_cfg_list - A list of platform platform specific configurations.
* Note: has to be synchronized with enum mei_cfg_idx.
@@ -1744,6 +1768,7 @@ static const struct mei_cfg *const mei_cfg_list[] = {
[MEI_ME_PCH15_SPS_CFG] = &mei_me_pch15_sps_cfg,
[MEI_ME_GSC_CFG] = &mei_me_gsc_cfg,
[MEI_ME_GSCFI_CFG] = &mei_me_gscfi_cfg,
+ [MEI_ME_CSC_CFG] = &mei_me_csc_cfg,
};
const struct mei_cfg *mei_me_get_cfg(kernel_ulong_t idx)
diff --git a/drivers/misc/mei/hw-me.h b/drivers/misc/mei/hw-me.h
index 204b92af6c47..8da8662a9d61 100644
--- a/drivers/misc/mei/hw-me.h
+++ b/drivers/misc/mei/hw-me.h
@@ -33,12 +33,6 @@ struct mei_cfg {
u32 hw_trc_supported:1;
};
-
-#define MEI_PCI_DEVICE(dev, cfg) \
- .vendor = PCI_VENDOR_ID_INTEL, .device = (dev), \
- .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID, \
- .driver_data = (kernel_ulong_t)(cfg),
-
#define MEI_ME_RPM_TIMEOUT 500 /* ms */
/**
@@ -62,7 +56,7 @@ struct mei_me_hw {
enum mei_pg_state pg_state;
bool d0i3_supported;
u8 hbuf_depth;
- int (*read_fws)(const struct mei_device *dev, int where, u32 *val);
+ int (*read_fws)(const struct mei_device *dev, int where, const char *name, u32 *val);
/* polling */
struct task_struct *polling_thread;
wait_queue_head_t wait_active;
@@ -110,6 +104,7 @@ static inline bool mei_me_hw_use_polling(const struct mei_me_hw *hw)
* SPS firmware exclusion.
* @MEI_ME_GSC_CFG: Graphics System Controller
* @MEI_ME_GSCFI_CFG: Graphics System Controller Firmware Interface
+ * @MEI_ME_CSC_CFG: Chassis System Controller Firmware Interface
* @MEI_ME_NUM_CFG: Upper Sentinel.
*/
enum mei_cfg_idx {
@@ -130,6 +125,7 @@ enum mei_cfg_idx {
MEI_ME_PCH15_SPS_CFG,
MEI_ME_GSC_CFG,
MEI_ME_GSCFI_CFG,
+ MEI_ME_CSC_CFG,
MEI_ME_NUM_CFG,
};
diff --git a/drivers/misc/mei/hw-txe.c b/drivers/misc/mei/hw-txe.c
index e4688c391027..a83de653c603 100644
--- a/drivers/misc/mei/hw-txe.c
+++ b/drivers/misc/mei/hw-txe.c
@@ -651,9 +651,9 @@ static int mei_txe_fw_status(struct mei_device *dev,
&fw_status->status[i]);
trace_mei_pci_cfg_read(&dev->dev, "PCI_CFG_HSF_X",
fw_src->status[i],
- fw_status->status[i]);
+ fw_status->status[i], ret);
if (ret)
- return ret;
+ return pcibios_err_to_errno(ret);
}
return 0;
diff --git a/drivers/misc/mei/init.c b/drivers/misc/mei/init.c
index b789c4d9c709..766f119f7ed0 100644
--- a/drivers/misc/mei/init.c
+++ b/drivers/misc/mei/init.c
@@ -344,13 +344,15 @@ EXPORT_SYMBOL_GPL(mei_stop);
bool mei_write_is_idle(struct mei_device *dev)
{
bool idle = (dev->dev_state == MEI_DEV_ENABLED &&
+ !dev->pg_blocked &&
list_empty(&dev->ctrl_wr_list) &&
list_empty(&dev->write_list) &&
list_empty(&dev->write_waiting_list));
- dev_dbg(&dev->dev, "write pg: is idle[%d] state=%s ctrl=%01d write=%01d wwait=%01d\n",
+ dev_dbg(&dev->dev, "write pg: is idle[%d] state=%s blocked=%d ctrl=%d write=%d wwait=%d\n",
idle,
mei_dev_state_str(dev->dev_state),
+ dev->pg_blocked,
list_empty(&dev->ctrl_wr_list),
list_empty(&dev->write_list),
list_empty(&dev->write_waiting_list));
diff --git a/drivers/misc/mei/main.c b/drivers/misc/mei/main.c
index 6f26d5160788..54f70f513482 100644
--- a/drivers/misc/mei/main.c
+++ b/drivers/misc/mei/main.c
@@ -4,6 +4,7 @@
* Intel Management Engine Interface (Intel MEI) Linux driver
*/
+#include <linux/cleanup.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/kernel.h>
@@ -13,6 +14,7 @@
#include <linux/errno.h>
#include <linux/types.h>
#include <linux/fcntl.h>
+#include <linux/pm_runtime.h>
#include <linux/poll.h>
#include <linux/init.h>
#include <linux/ioctl.h>
@@ -982,14 +984,22 @@ static DEVICE_ATTR_RO(trc);
static ssize_t fw_status_show(struct device *device,
struct device_attribute *attr, char *buf)
{
- struct mei_device *dev = dev_get_drvdata(device);
+ struct mei_device *mdev = dev_get_drvdata(device);
struct mei_fw_status fw_status;
int err, i;
ssize_t cnt = 0;
- mutex_lock(&dev->device_lock);
- err = mei_fw_status(dev, &fw_status);
- mutex_unlock(&dev->device_lock);
+ if (mdev->read_fws_need_resume) {
+ err = pm_runtime_resume_and_get(mdev->parent);
+ if (err) {
+ dev_err(device, "read fw_status resume error = %d\n", err);
+ return err;
+ }
+ }
+ scoped_guard(mutex, &mdev->device_lock)
+ err = mei_fw_status(mdev, &fw_status);
+ if (mdev->read_fws_need_resume)
+ pm_runtime_put_autosuspend(mdev->parent);
if (err) {
dev_err(device, "read fw_status error = %d\n", err);
return err;
diff --git a/drivers/misc/mei/mei-trace.h b/drivers/misc/mei/mei-trace.h
index 24fa321d88bd..fa5224e5353a 100644
--- a/drivers/misc/mei/mei-trace.h
+++ b/drivers/misc/mei/mei-trace.h
@@ -55,22 +55,24 @@ TRACE_EVENT(mei_reg_write,
);
TRACE_EVENT(mei_pci_cfg_read,
- TP_PROTO(const struct device *dev, const char *reg, u32 offs, u32 val),
- TP_ARGS(dev, reg, offs, val),
+ TP_PROTO(const struct device *dev, const char *reg, u32 offs, u32 val, int ret),
+ TP_ARGS(dev, reg, offs, val, ret),
TP_STRUCT__entry(
__string(dev, dev_name(dev))
__string(reg, reg)
__field(u32, offs)
__field(u32, val)
+ __field(int, ret)
),
TP_fast_assign(
__assign_str(dev);
__assign_str(reg);
__entry->offs = offs;
__entry->val = val;
+ __entry->ret = ret;
),
- TP_printk("[%s] pci cfg read %s:[%#x] = %#x",
- __get_str(dev), __get_str(reg), __entry->offs, __entry->val)
+ TP_printk("[%s] pci cfg read %s:[%#x] = %#x, ret = %d",
+ __get_str(dev), __get_str(reg), __entry->offs, __entry->val, __entry->ret)
);
#endif /* _MEI_TRACE_H_ */
diff --git a/drivers/misc/mei/mei_dev.h b/drivers/misc/mei/mei_dev.h
index 0bf8d552c3ea..d8634a726990 100644
--- a/drivers/misc/mei/mei_dev.h
+++ b/drivers/misc/mei/mei_dev.h
@@ -490,6 +490,8 @@ struct mei_dev_timeouts {
* @timer_work : MEI timer delayed work (timeouts)
*
* @recvd_hw_ready : hw ready message received flag
+ * @pg_blocked : low power mode is not allowed
+ * @read_fws_need_resume: the FW status handler needs HW woken from sleep
*
* @wait_hw_ready : wait queue for receive HW ready message form FW
* @wait_pg : wait queue for receive PG message from FW
@@ -575,6 +577,9 @@ struct mei_device {
struct delayed_work timer_work;
bool recvd_hw_ready;
+ bool pg_blocked;
+ bool read_fws_need_resume;
+
/*
* waiting queue for receive message from FW
*/
diff --git a/drivers/misc/mei/mei_lb.c b/drivers/misc/mei/mei_lb.c
index 78717ee8ac9a..f6a258c2b838 100644
--- a/drivers/misc/mei/mei_lb.c
+++ b/drivers/misc/mei/mei_lb.c
@@ -59,12 +59,17 @@
* 5. Status is returned back to the host via MEI.
*/
+/* Late Binding version 1 */
+
#define INTEL_LB_CMD 0x12
#define INTEL_LB_RSP (INTEL_LB_CMD | 0x80)
#define INTEL_LB_SEND_TIMEOUT_MSEC 3000
#define INTEL_LB_RECV_TIMEOUT_MSEC 3000
+#define MEI_GUID_MKHI UUID_LE(0xe2c2afa2, 0x3817, 0x4d19, \
+ 0x9d, 0x95, 0x6, 0xb1, 0x6b, 0x58, 0x8a, 0x5d)
+
/**
* struct mei_lb_req - Late Binding request structure
* @header: MKHI message header (see struct mkhi_msg_hdr)
@@ -97,8 +102,74 @@ struct mei_lb_rsp {
__le32 status;
} __packed;
-static bool mei_lb_check_response(const struct device *dev, ssize_t bytes,
- struct mei_lb_rsp *rsp)
+/* Late Binding version 2 */
+
+#define MEI_LB2_CMD 0x01
+
+#define MEI_LB2_HDR_FLAG_RSP 0x01
+
+#define MEI_GUID_LB UUID_LE(0x4ed87243, 0x3980, 0x4d8e, \
+ 0xb1, 0xf9, 0x6f, 0xb7, 0xc0, 0x14, 0x8c, 0x4d)
+
+/**
+ * struct mei_lb2_header - Late Binding2 header
+ * @command_id:
+ * @flags: Flags for transport layer (e.g. MEI_LB2_HDR_FLAG_RSP)
+ * @reserved: Reserved for future use by authentication firmware, must be set to 0
+ */
+struct mei_lb2_header {
+ __le32 command_id;
+ u8 flags;
+ u8 reserved[3];
+};
+
+/**
+ * struct mei_lb2_rsp_header - Late Binding2 response header
+ * @header: Common command header
+ * @status: Status returned by authentication firmware (see &enum intel_lb_status)
+ */
+struct mei_lb2_rsp_header {
+ struct mei_lb2_header header;
+ __le32 status;
+};
+
+#define MEI_LB2_FLAG_FST_CHUNK 0x02
+#define MEI_LB2_FLAG_LST_CHUNK 0x04
+
+/**
+ * struct mei_lb2_req - Late Binding2 request
+ * @header: Common command header
+ * @type: Type of the Late Binding payload (see &enum intel_lb_type)
+ * @flags: Flags to be passed to the authentication firmware (MEI_LB2_FLAG_*)
+ * @reserved: Reserved for future use by authentication firmware, must be set to 0
+ * @total_payload_size: Size of whole Late Binding package in bytes
+ * @payload_size: Size of the payload chunk in bytes
+ * @payload: Data chunk to be sent to the authentication firmware
+ */
+struct mei_lb2_req {
+ struct mei_lb2_header header;
+ __le32 type;
+ __le32 flags;
+ __le32 reserved;
+ __le32 total_payload_size;
+ __le32 payload_size;
+ u8 payload[] __counted_by(payload_size);
+};
+
+/**
+ * struct mei_lb2_rsp - Late Binding2 response
+ * @rheader: Common response header
+ * @type: Type of the Late Binding payload (see &enum intel_lb_type)
+ * @reserved: Reserved for future use by authentication firmware, must be set to 0
+ */
+struct mei_lb2_rsp {
+ struct mei_lb2_rsp_header rheader;
+ __le32 type;
+ __le32 reserved[2];
+};
+
+static bool mei_lb_check_response_v1(const struct device *dev, ssize_t bytes,
+ struct mei_lb_rsp *rsp)
{
/*
* Received message size may be smaller than the full message size when
@@ -134,24 +205,15 @@ static bool mei_lb_check_response(const struct device *dev, ssize_t bytes,
return true;
}
-static int mei_lb_push_payload(struct device *dev, u32 type, u32 flags,
- const void *payload, size_t payload_size)
+static int mei_lb_push_payload_v1(struct device *dev, struct mei_cl_device *cldev,
+ u32 type, u32 flags, const void *payload, size_t payload_size)
{
- struct mei_cl_device *cldev;
struct mei_lb_req *req = NULL;
struct mei_lb_rsp rsp;
size_t req_size;
ssize_t bytes;
int ret;
- cldev = to_mei_cl_device(dev);
-
- ret = mei_cldev_enable(cldev);
- if (ret) {
- dev_dbg(dev, "Failed to enable firmware client. %d\n", ret);
- return ret;
- }
-
req_size = struct_size(req, payload, payload_size);
if (req_size > mei_cldev_mtu(cldev)) {
dev_err(dev, "Payload is too big: %zu\n", payload_size);
@@ -190,7 +252,7 @@ static int mei_lb_push_payload(struct device *dev, u32 type, u32 flags,
ret = bytes;
goto end;
}
- if (!mei_lb_check_response(dev, bytes, &rsp)) {
+ if (!mei_lb_check_response_v1(dev, bytes, &rsp)) {
dev_err(dev, "Bad response from the firmware. header: %02x %02x %02x %02x\n",
rsp.header.group_id, rsp.header.command,
rsp.header.reserved, rsp.header.result);
@@ -201,11 +263,130 @@ static int mei_lb_push_payload(struct device *dev, u32 type, u32 flags,
dev_dbg(dev, "status = %u\n", le32_to_cpu(rsp.status));
ret = (int)le32_to_cpu(rsp.status);
end:
- mei_cldev_disable(cldev);
kfree(req);
return ret;
}
+static int mei_lb_check_response_v2(const struct device *dev, ssize_t bytes,
+ struct mei_lb2_rsp *rsp)
+{
+ /*
+ * Received message size may be smaller than the full message size when
+ * reply contains only header with status field set to the error code.
+ * Check the header size and content first to output exact error, if needed,
+ * and then process to the whole message.
+ */
+ if (bytes < sizeof(rsp->rheader)) {
+ dev_err(dev, "Received less than header size from the firmware: %zd < %zu\n",
+ bytes, sizeof(rsp->rheader));
+ return -ENOMSG;
+ }
+ if (rsp->rheader.header.command_id != MEI_LB2_CMD) {
+ dev_err(dev, "Mismatch command: 0x%x instead of 0x%x\n",
+ rsp->rheader.header.command_id, MEI_LB2_CMD);
+ return -EPROTO;
+ }
+ if (!(rsp->rheader.header.flags & MEI_LB2_HDR_FLAG_RSP)) {
+ dev_err(dev, "Not a response: 0x%x\n", rsp->rheader.header.flags);
+ return -EBADMSG;
+ }
+ if (rsp->rheader.status) {
+ dev_err(dev, "Error in result: 0x%x\n", rsp->rheader.status);
+ return (int)le32_to_cpu(rsp->rheader.status);
+ }
+ if (bytes < sizeof(*rsp)) {
+ dev_err(dev, "Received less than message size from the firmware: %zd < %zu\n",
+ bytes, sizeof(*rsp));
+ return -ENODATA;
+ }
+
+ return 0;
+}
+
+static int mei_lb_push_payload_v2(struct device *dev, struct mei_cl_device *cldev,
+ u32 type, u32 flags, const void *payload, size_t payload_size)
+{
+ u32 first_chunk, last_chunk;
+ struct mei_lb2_rsp rsp;
+ size_t sent_data = 0;
+ size_t chunk_size;
+ size_t req_size;
+ ssize_t bytes;
+ int ret;
+
+ struct mei_lb2_req *req __free(kfree) = kzalloc(mei_cldev_mtu(cldev), GFP_KERNEL);
+ if (!req)
+ return -ENOMEM;
+
+ first_chunk = MEI_LB2_FLAG_FST_CHUNK;
+ last_chunk = 0;
+ do {
+ chunk_size = min(payload_size - sent_data, mei_cldev_mtu(cldev) - sizeof(*req));
+
+ req_size = struct_size(req, payload, chunk_size);
+ if (sent_data + chunk_size == payload_size)
+ last_chunk = MEI_LB2_FLAG_LST_CHUNK;
+
+ req->header.command_id = MEI_LB2_CMD;
+ req->type = cpu_to_le32(type);
+ req->flags = cpu_to_le32(flags | first_chunk | last_chunk);
+ req->reserved = 0;
+ req->total_payload_size = cpu_to_le32(payload_size);
+ req->payload_size = cpu_to_le32(chunk_size);
+ memcpy(req->payload, payload + sent_data, chunk_size);
+
+ dev_dbg(dev, "Sending %zu bytes from offset %zu of %zu%s%s\n",
+ chunk_size, sent_data, payload_size,
+ first_chunk ? " first" : "", last_chunk ? " last" : "");
+
+ bytes = mei_cldev_send_timeout(cldev, (u8 *)req, req_size,
+ INTEL_LB_SEND_TIMEOUT_MSEC);
+ if (bytes < 0) {
+ dev_err(dev, "Failed to send late binding request to firmware. %zd\n",
+ bytes);
+ return bytes;
+ }
+
+ bytes = mei_cldev_recv_timeout(cldev, (u8 *)&rsp, sizeof(rsp),
+ INTEL_LB_RECV_TIMEOUT_MSEC);
+ if (bytes < 0) {
+ dev_err(dev, "Failed to receive late binding reply from firmware. %zd\n",
+ bytes);
+ return bytes;
+ }
+ ret = mei_lb_check_response_v2(dev, bytes, &rsp);
+ if (ret)
+ return ret;
+
+ /* prepare for the next chunk */
+ sent_data += chunk_size;
+ first_chunk = 0;
+ } while (!last_chunk);
+
+ return 0;
+}
+
+static int mei_lb_push_payload(struct device *dev, u32 type, u32 flags,
+ const void *payload, size_t payload_size)
+{
+ struct mei_cl_device *cldev = to_mei_cl_device(dev);
+ int ret;
+
+ ret = mei_cldev_enable(cldev);
+ if (ret) {
+ dev_dbg(dev, "Failed to enable firmware client. %d\n", ret);
+ return ret;
+ }
+
+ if (memcmp(&MEI_GUID_LB, mei_cldev_uuid(cldev), sizeof(uuid_le)) == 0)
+ ret = mei_lb_push_payload_v2(dev, cldev, type, flags, payload, payload_size);
+ else
+ ret = mei_lb_push_payload_v1(dev, cldev, type, flags, payload, payload_size);
+
+ mei_cldev_disable(cldev);
+ return ret;
+}
+
static const struct intel_lb_component_ops mei_lb_ops = {
.push_payload = mei_lb_push_payload,
};
@@ -229,11 +410,16 @@ static int mei_lb_component_match(struct device *dev, int subcomponent,
void *data)
{
/*
- * This function checks if requester is Intel %PCI_CLASS_DISPLAY_VGA or
- * %PCI_CLASS_DISPLAY_OTHER device, and checks if the requester is the
- * grand parent of mei_if i.e. late bind MEI device
+ * This function checks if requester is Intel vendor,
+ * determines if MEI is standalone PCI device or the auxiliary one
+ * and checks the following:
+ * 0) PCI parent: (e.g. /sys/class/mei/mei0/device -> ../../../0000:15:00.0)
+ * the requester and MEI device has the same grand parent
+ * 1) Auxiliary parent: (e.g. /sys/class/mei/mei1/device -> ../../../xe.mei-gscfi.768)
+ * the requester is the parent of MEI device
*/
struct device *base = data;
+ struct device *basep = dev;
struct pci_dev *pdev;
if (!dev)
@@ -247,20 +433,30 @@ static int mei_lb_component_match(struct device *dev, int subcomponent,
if (pdev->vendor != PCI_VENDOR_ID_INTEL)
return 0;
- if (pdev->class != (PCI_CLASS_DISPLAY_VGA << 8) &&
- pdev->class != (PCI_CLASS_DISPLAY_OTHER << 8))
- return 0;
-
if (subcomponent != INTEL_COMPONENT_LB)
return 0;
base = base->parent;
- if (!base) /* mei device */
+ if (!base) /* MEI device */
return 0;
- base = base->parent; /* pci device */
+ if (dev_is_pci(base)) {
+ /* case 0) PCI parent */
+ base = base->parent; /* bridge 1 */
+ if (!base)
+ return 0;
+ base = base->parent; /* bridge 2 */
+
+ basep = basep->parent; /* bridge 1 */
+ if (!basep)
+ return 0;
+ basep = basep->parent; /* bridge 2 */
+ } else {
+ /* case 1) Auxiliary parent */
+ base = base->parent; /* PCI device */
+ }
- return !!base && dev == base;
+ return !!base && !!basep && base == basep;
}
static int mei_lb_probe(struct mei_cl_device *cldev,
@@ -288,11 +484,9 @@ static void mei_lb_remove(struct mei_cl_device *cldev)
component_master_del(&cldev->dev, &mei_lb_component_master_ops);
}
-#define MEI_GUID_MKHI UUID_LE(0xe2c2afa2, 0x3817, 0x4d19, \
- 0x9d, 0x95, 0x6, 0xb1, 0x6b, 0x58, 0x8a, 0x5d)
-
static const struct mei_cl_device_id mei_lb_tbl[] = {
- { .uuid = MEI_GUID_MKHI, .version = MEI_CL_VERSION_ANY },
+ { .uuid = MEI_GUID_MKHI, .version = 1 },
+ { .uuid = MEI_GUID_LB, .version = MEI_CL_VERSION_ANY },
{ }
};
MODULE_DEVICE_TABLE(mei, mei_lb_tbl);
diff --git a/drivers/misc/mei/pci-csc.c b/drivers/misc/mei/pci-csc.c
new file mode 100644
index 000000000000..70792bf9b3c0
--- /dev/null
+++ b/drivers/misc/mei/pci-csc.c
@@ -0,0 +1,261 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2025-2026, Intel Corporation. All rights reserved.
+ * Intel Management Engine Interface (Intel MEI) Linux driver
+ * for CSC platforms.
+ */
+
+#include <linux/cleanup.h>
+#include <linux/device.h>
+#include <linux/dma-mapping.h>
+#include <linux/err.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/pci.h>
+#include <linux/pm_runtime.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+
+#include "client.h"
+#include "hw-me-regs.h"
+#include "hw-me.h"
+#include "mei_dev.h"
+#include "mei-trace.h"
+
+#define MEI_CSC_HECI2_OFFSET 0x1000
+
+static int mei_csc_read_fws(const struct mei_device *mdev, int where, const char *name, u32 *val)
+{
+ struct mei_me_hw *hw = to_me_hw(mdev);
+
+ *val = ioread32(hw->mem_addr + where + 0xC00);
+ trace_mei_reg_read(&mdev->dev, name, where, *val);
+ return 0;
+}
+
+static int mei_csc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+ struct device *dev = &pdev->dev;
+ const struct mei_cfg *cfg;
+ char __iomem *registers;
+ struct mei_device *mdev;
+ struct mei_me_hw *hw;
+ int err;
+
+ cfg = mei_me_get_cfg(ent->driver_data);
+ if (!cfg)
+ return -ENODEV;
+
+ err = pcim_enable_device(pdev);
+ if (err)
+ return dev_err_probe(dev, err, "Failed to enable PCI device.\n");
+
+ pci_set_master(pdev);
+
+ registers = pcim_iomap_region(pdev, 0, KBUILD_MODNAME);
+ if (IS_ERR(registers))
+ return dev_err_probe(dev, PTR_ERR(registers), "Failed to get PCI region.\n");
+
+ err = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64));
+ if (err)
+ return dev_err_probe(dev, err, "No usable DMA configuration.\n");
+
+ /* allocates and initializes the mei dev structure */
+ mdev = mei_me_dev_init(dev, cfg, false);
+ if (!mdev)
+ return -ENOMEM;
+
+ mdev->read_fws_need_resume = true;
+
+ hw = to_me_hw(mdev);
+
+ /*
+ * Both HECI1 and HECI2 are on this device, but only HECI2 is supported.
+ */
+ hw->mem_addr = registers + MEI_CSC_HECI2_OFFSET;
+ hw->read_fws = mei_csc_read_fws;
+
+ /*
+ * mei_register() assumes ownership of mdev.
+ * No need to release it explicitly in error path.
+ */
+ err = mei_register(mdev, dev);
+ if (err)
+ return err;
+
+ pci_set_drvdata(pdev, mdev);
+
+ err = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_INTX | PCI_IRQ_MSI);
+ if (err < 0) {
+ dev_err_probe(dev, err, "Failed to allocate IRQ.\n");
+ goto err_mei_unreg;
+ }
+
+ hw->irq = pci_irq_vector(pdev, 0);
+
+ /* request and enable interrupt */
+ err = request_threaded_irq(hw->irq,
+ mei_me_irq_quick_handler, mei_me_irq_thread_handler,
+ IRQF_SHARED | IRQF_ONESHOT, KBUILD_MODNAME, mdev);
+ if (err)
+ goto err_free_irq_vectors;
+
+ /*
+ * Continue to char device setup in spite of firmware handshake failure.
+ * In order to provide access to the firmware status registers to the user
+ * space via sysfs. The firmware status registers required to understand
+ * firmware error state and possible recovery flow.
+ */
+ if (mei_start(mdev))
+ dev_warn(dev, "Failed to initialize HECI hardware.\n");
+
+ pm_runtime_set_autosuspend_delay(dev, MEI_ME_RPM_TIMEOUT);
+ pm_runtime_use_autosuspend(dev);
+
+ /*
+ * MEI requires to resume from runtime suspend mode
+ * in order to perform link reset flow upon system suspend.
+ */
+ dev_pm_set_driver_flags(dev, DPM_FLAG_NO_DIRECT_COMPLETE);
+
+ pm_runtime_allow(dev);
+ pm_runtime_put_noidle(dev);
+
+ return 0;
+
+err_free_irq_vectors:
+ pci_free_irq_vectors(pdev);
+err_mei_unreg:
+ mei_deregister(mdev);
+ return err;
+}
+
+static void mei_csc_shutdown(struct pci_dev *pdev)
+{
+ struct mei_device *mdev = pci_get_drvdata(pdev);
+ struct mei_me_hw *hw = to_me_hw(mdev);
+
+ pm_runtime_get_noresume(&pdev->dev);
+
+ mei_stop(mdev);
+
+ mei_disable_interrupts(mdev);
+ free_irq(hw->irq, mdev);
+ pci_free_irq_vectors(pdev);
+}
+
+static void mei_csc_remove(struct pci_dev *pdev)
+{
+ struct mei_device *mdev = pci_get_drvdata(pdev);
+
+ mei_csc_shutdown(pdev);
+
+ mei_deregister(mdev);
+}
+
+static int mei_csc_pci_prepare(struct device *dev)
+{
+ pm_runtime_resume(dev);
+ return 0;
+}
+
+static int mei_csc_pci_suspend(struct device *dev)
+{
+ struct mei_device *mdev = dev_get_drvdata(dev);
+
+ mei_stop(mdev);
+
+ mei_disable_interrupts(mdev);
+
+ return 0;
+}
+
+static int mei_csc_pci_resume(struct device *dev)
+{
+ struct mei_device *mdev = dev_get_drvdata(dev);
+ int err;
+
+ err = mei_restart(mdev);
+ if (err)
+ return err;
+
+ /* Start timer if stopped in suspend */
+ schedule_delayed_work(&mdev->timer_work, HZ);
+
+ return 0;
+}
+
+static void mei_csc_pci_complete(struct device *dev)
+{
+ pm_runtime_suspend(dev);
+}
+
+static int mei_csc_pm_runtime_idle(struct device *dev)
+{
+ struct mei_device *mdev = dev_get_drvdata(dev);
+
+ return mei_write_is_idle(mdev) ? 0 : -EBUSY;
+}
+
+static int mei_csc_pm_runtime_suspend(struct device *dev)
+{
+ struct mei_device *mdev = dev_get_drvdata(dev);
+ struct mei_me_hw *hw = to_me_hw(mdev);
+
+ guard(mutex)(&mdev->device_lock);
+
+ if (!mei_write_is_idle(mdev))
+ return -EAGAIN;
+
+ hw->pg_state = MEI_PG_ON;
+ return 0;
+}
+
+static int mei_csc_pm_runtime_resume(struct device *dev)
+{
+ struct mei_device *mdev = dev_get_drvdata(dev);
+ struct mei_me_hw *hw = to_me_hw(mdev);
+ irqreturn_t irq_ret;
+
+ scoped_guard(mutex, &mdev->device_lock)
+ hw->pg_state = MEI_PG_OFF;
+
+ /* Process all queues that wait for resume */
+ irq_ret = mei_me_irq_thread_handler(1, mdev);
+ if (irq_ret != IRQ_HANDLED)
+ dev_err(dev, "thread handler fail %d\n", irq_ret);
+
+ return 0;
+}
+
+static const struct dev_pm_ops mei_csc_pm_ops = {
+ .prepare = pm_sleep_ptr(mei_csc_pci_prepare),
+ .complete = pm_sleep_ptr(mei_csc_pci_complete),
+ SYSTEM_SLEEP_PM_OPS(mei_csc_pci_suspend, mei_csc_pci_resume)
+ RUNTIME_PM_OPS(mei_csc_pm_runtime_suspend,
+ mei_csc_pm_runtime_resume, mei_csc_pm_runtime_idle)
+};
+
+static const struct pci_device_id mei_csc_pci_tbl[] = {
+ { PCI_DEVICE_DATA(INTEL, MEI_CRI, MEI_ME_CSC_CFG) },
+ {}
+};
+MODULE_DEVICE_TABLE(pci, mei_csc_pci_tbl);
+
+static struct pci_driver mei_csc_driver = {
+ .name = KBUILD_MODNAME,
+ .id_table = mei_csc_pci_tbl,
+ .probe = mei_csc_probe,
+ .remove = mei_csc_remove,
+ .shutdown = mei_csc_shutdown,
+ .driver = {
+ .pm = &mei_csc_pm_ops,
+ .probe_type = PROBE_PREFER_ASYNCHRONOUS,
+ }
+};
+module_pci_driver(mei_csc_driver);
+
+MODULE_DESCRIPTION("Intel(R) Management Engine Interface for discrete graphics (CSC)");
+MODULE_LICENSE("GPL");
diff --git a/drivers/misc/mei/pci-me.c b/drivers/misc/mei/pci-me.c
index 2a6e569558b9..9efeafa8f1ca 100644
--- a/drivers/misc/mei/pci-me.c
+++ b/drivers/misc/mei/pci-me.c
@@ -23,113 +23,115 @@
#include "client.h"
#include "hw-me-regs.h"
#include "hw-me.h"
+#include "mei-trace.h"
/* mei_pci_tbl - PCI Device ID Table */
static const struct pci_device_id mei_me_pci_tbl[] = {
- {MEI_PCI_DEVICE(MEI_DEV_ID_82946GZ, MEI_ME_ICH_CFG)},
- {MEI_PCI_DEVICE(MEI_DEV_ID_82G35, MEI_ME_ICH_CFG)},
- {MEI_PCI_DEVICE(MEI_DEV_ID_82Q965, MEI_ME_ICH_CFG)},
- {MEI_PCI_DEVICE(MEI_DEV_ID_82G965, MEI_ME_ICH_CFG)},
- {MEI_PCI_DEVICE(MEI_DEV_ID_82GM965, MEI_ME_ICH_CFG)},
- {MEI_PCI_DEVICE(MEI_DEV_ID_82GME965, MEI_ME_ICH_CFG)},
- {MEI_PCI_DEVICE(MEI_DEV_ID_ICH9_82Q35, MEI_ME_ICH_CFG)},
- {MEI_PCI_DEVICE(MEI_DEV_ID_ICH9_82G33, MEI_ME_ICH_CFG)},
- {MEI_PCI_DEVICE(MEI_DEV_ID_ICH9_82Q33, MEI_ME_ICH_CFG)},
- {MEI_PCI_DEVICE(MEI_DEV_ID_ICH9_82X38, MEI_ME_ICH_CFG)},
- {MEI_PCI_DEVICE(MEI_DEV_ID_ICH9_3200, MEI_ME_ICH_CFG)},
-
- {MEI_PCI_DEVICE(MEI_DEV_ID_ICH9_6, MEI_ME_ICH_CFG)},
- {MEI_PCI_DEVICE(MEI_DEV_ID_ICH9_7, MEI_ME_ICH_CFG)},
- {MEI_PCI_DEVICE(MEI_DEV_ID_ICH9_8, MEI_ME_ICH_CFG)},
- {MEI_PCI_DEVICE(MEI_DEV_ID_ICH9_9, MEI_ME_ICH_CFG)},
- {MEI_PCI_DEVICE(MEI_DEV_ID_ICH9_10, MEI_ME_ICH_CFG)},
- {MEI_PCI_DEVICE(MEI_DEV_ID_ICH9M_1, MEI_ME_ICH_CFG)},
- {MEI_PCI_DEVICE(MEI_DEV_ID_ICH9M_2, MEI_ME_ICH_CFG)},
- {MEI_PCI_DEVICE(MEI_DEV_ID_ICH9M_3, MEI_ME_ICH_CFG)},
- {MEI_PCI_DEVICE(MEI_DEV_ID_ICH9M_4, MEI_ME_ICH_CFG)},
-
- {MEI_PCI_DEVICE(MEI_DEV_ID_ICH10_1, MEI_ME_ICH10_CFG)},
- {MEI_PCI_DEVICE(MEI_DEV_ID_ICH10_2, MEI_ME_ICH10_CFG)},
- {MEI_PCI_DEVICE(MEI_DEV_ID_ICH10_3, MEI_ME_ICH10_CFG)},
- {MEI_PCI_DEVICE(MEI_DEV_ID_ICH10_4, MEI_ME_ICH10_CFG)},
-
- {MEI_PCI_DEVICE(MEI_DEV_ID_IBXPK_1, MEI_ME_PCH6_CFG)},
- {MEI_PCI_DEVICE(MEI_DEV_ID_IBXPK_2, MEI_ME_PCH6_CFG)},
- {MEI_PCI_DEVICE(MEI_DEV_ID_CPT_1, MEI_ME_PCH_CPT_PBG_CFG)},
- {MEI_PCI_DEVICE(MEI_DEV_ID_PBG_1, MEI_ME_PCH_CPT_PBG_CFG)},
- {MEI_PCI_DEVICE(MEI_DEV_ID_PPT_1, MEI_ME_PCH7_CFG)},
- {MEI_PCI_DEVICE(MEI_DEV_ID_PPT_2, MEI_ME_PCH7_CFG)},
- {MEI_PCI_DEVICE(MEI_DEV_ID_PPT_3, MEI_ME_PCH7_CFG)},
- {MEI_PCI_DEVICE(MEI_DEV_ID_LPT_H, MEI_ME_PCH8_SPS_4_CFG)},
- {MEI_PCI_DEVICE(MEI_DEV_ID_LPT_W, MEI_ME_PCH8_SPS_4_CFG)},
- {MEI_PCI_DEVICE(MEI_DEV_ID_LPT_LP, MEI_ME_PCH8_CFG)},
- {MEI_PCI_DEVICE(MEI_DEV_ID_LPT_HR, MEI_ME_PCH8_SPS_4_CFG)},
- {MEI_PCI_DEVICE(MEI_DEV_ID_WPT_LP, MEI_ME_PCH8_CFG)},
- {MEI_PCI_DEVICE(MEI_DEV_ID_WPT_LP_2, MEI_ME_PCH8_CFG)},
-
- {MEI_PCI_DEVICE(MEI_DEV_ID_SPT, MEI_ME_PCH8_CFG)},
- {MEI_PCI_DEVICE(MEI_DEV_ID_SPT_2, MEI_ME_PCH8_CFG)},
- {MEI_PCI_DEVICE(MEI_DEV_ID_SPT_3, MEI_ME_PCH8_ITOUCH_CFG)},
- {MEI_PCI_DEVICE(MEI_DEV_ID_SPT_H, MEI_ME_PCH8_SPS_4_CFG)},
- {MEI_PCI_DEVICE(MEI_DEV_ID_SPT_H_2, MEI_ME_PCH8_SPS_4_CFG)},
- {MEI_PCI_DEVICE(MEI_DEV_ID_LBG, MEI_ME_PCH12_SPS_4_CFG)},
-
- {MEI_PCI_DEVICE(MEI_DEV_ID_BXT_M, MEI_ME_PCH8_CFG)},
- {MEI_PCI_DEVICE(MEI_DEV_ID_APL_I, MEI_ME_PCH8_CFG)},
-
- {MEI_PCI_DEVICE(MEI_DEV_ID_DNV_IE, MEI_ME_PCH8_CFG)},
-
- {MEI_PCI_DEVICE(MEI_DEV_ID_GLK, MEI_ME_PCH8_CFG)},
-
- {MEI_PCI_DEVICE(MEI_DEV_ID_KBP, MEI_ME_PCH8_CFG)},
- {MEI_PCI_DEVICE(MEI_DEV_ID_KBP_2, MEI_ME_PCH8_CFG)},
- {MEI_PCI_DEVICE(MEI_DEV_ID_KBP_3, MEI_ME_PCH8_CFG)},
-
- {MEI_PCI_DEVICE(MEI_DEV_ID_CNP_LP, MEI_ME_PCH12_CFG)},
- {MEI_PCI_DEVICE(MEI_DEV_ID_CNP_LP_3, MEI_ME_PCH8_ITOUCH_CFG)},
- {MEI_PCI_DEVICE(MEI_DEV_ID_CNP_H, MEI_ME_PCH12_SPS_CFG)},
- {MEI_PCI_DEVICE(MEI_DEV_ID_CNP_H_3, MEI_ME_PCH12_SPS_ITOUCH_CFG)},
-
- {MEI_PCI_DEVICE(MEI_DEV_ID_CMP_LP, MEI_ME_PCH12_CFG)},
- {MEI_PCI_DEVICE(MEI_DEV_ID_CMP_LP_3, MEI_ME_PCH8_ITOUCH_CFG)},
- {MEI_PCI_DEVICE(MEI_DEV_ID_CMP_V, MEI_ME_PCH12_CFG)},
- {MEI_PCI_DEVICE(MEI_DEV_ID_CMP_H, MEI_ME_PCH12_CFG)},
- {MEI_PCI_DEVICE(MEI_DEV_ID_CMP_H_3, MEI_ME_PCH8_ITOUCH_CFG)},
-
- {MEI_PCI_DEVICE(MEI_DEV_ID_ICP_LP, MEI_ME_PCH12_CFG)},
- {MEI_PCI_DEVICE(MEI_DEV_ID_ICP_N, MEI_ME_PCH12_CFG)},
-
- {MEI_PCI_DEVICE(MEI_DEV_ID_TGP_LP, MEI_ME_PCH15_CFG)},
- {MEI_PCI_DEVICE(MEI_DEV_ID_TGP_H, MEI_ME_PCH15_SPS_CFG)},
-
- {MEI_PCI_DEVICE(MEI_DEV_ID_JSP_N, MEI_ME_PCH15_CFG)},
-
- {MEI_PCI_DEVICE(MEI_DEV_ID_MCC, MEI_ME_PCH15_CFG)},
- {MEI_PCI_DEVICE(MEI_DEV_ID_MCC_4, MEI_ME_PCH8_CFG)},
-
- {MEI_PCI_DEVICE(MEI_DEV_ID_CDF, MEI_ME_PCH8_CFG)},
-
- {MEI_PCI_DEVICE(MEI_DEV_ID_EBG, MEI_ME_PCH15_SPS_CFG)},
-
- {MEI_PCI_DEVICE(MEI_DEV_ID_ADP_S, MEI_ME_PCH15_CFG)},
- {MEI_PCI_DEVICE(MEI_DEV_ID_ADP_LP, MEI_ME_PCH15_CFG)},
- {MEI_PCI_DEVICE(MEI_DEV_ID_ADP_P, MEI_ME_PCH15_CFG)},
- {MEI_PCI_DEVICE(MEI_DEV_ID_ADP_N, MEI_ME_PCH15_CFG)},
-
- {MEI_PCI_DEVICE(MEI_DEV_ID_RPL_S, MEI_ME_PCH15_SPS_CFG)},
-
- {MEI_PCI_DEVICE(MEI_DEV_ID_MTL_M, MEI_ME_PCH15_CFG)},
- {MEI_PCI_DEVICE(MEI_DEV_ID_ARL_S, MEI_ME_PCH15_CFG)},
- {MEI_PCI_DEVICE(MEI_DEV_ID_ARL_H, MEI_ME_PCH15_CFG)},
-
- {MEI_PCI_DEVICE(MEI_DEV_ID_LNL_M, MEI_ME_PCH15_CFG)},
-
- {MEI_PCI_DEVICE(MEI_DEV_ID_PTL_H, MEI_ME_PCH15_CFG)},
- {MEI_PCI_DEVICE(MEI_DEV_ID_PTL_P, MEI_ME_PCH15_CFG)},
-
- {MEI_PCI_DEVICE(MEI_DEV_ID_WCL_P, MEI_ME_PCH15_CFG)},
-
- {MEI_PCI_DEVICE(MEI_DEV_ID_NVL_S, MEI_ME_PCH15_CFG)},
+ {PCI_DEVICE_DATA(INTEL, MEI_82946GZ, MEI_ME_ICH_CFG)},
+ {PCI_DEVICE_DATA(INTEL, MEI_82G35, MEI_ME_ICH_CFG)},
+ {PCI_DEVICE_DATA(INTEL, MEI_82Q965, MEI_ME_ICH_CFG)},
+ {PCI_DEVICE_DATA(INTEL, MEI_82G965, MEI_ME_ICH_CFG)},
+ {PCI_DEVICE_DATA(INTEL, MEI_82GM965, MEI_ME_ICH_CFG)},
+ {PCI_DEVICE_DATA(INTEL, MEI_82GME965, MEI_ME_ICH_CFG)},
+ {PCI_DEVICE_DATA(INTEL, MEI_ICH9_82Q35, MEI_ME_ICH_CFG)},
+ {PCI_DEVICE_DATA(INTEL, MEI_ICH9_82G33, MEI_ME_ICH_CFG)},
+ {PCI_DEVICE_DATA(INTEL, MEI_ICH9_82Q33, MEI_ME_ICH_CFG)},
+ {PCI_DEVICE_DATA(INTEL, MEI_ICH9_82X38, MEI_ME_ICH_CFG)},
+ {PCI_DEVICE_DATA(INTEL, MEI_ICH9_3200, MEI_ME_ICH_CFG)},
+
+ {PCI_DEVICE_DATA(INTEL, MEI_ICH9_6, MEI_ME_ICH_CFG)},
+ {PCI_DEVICE_DATA(INTEL, MEI_ICH9_7, MEI_ME_ICH_CFG)},
+ {PCI_DEVICE_DATA(INTEL, MEI_ICH9_8, MEI_ME_ICH_CFG)},
+ {PCI_DEVICE_DATA(INTEL, MEI_ICH9_9, MEI_ME_ICH_CFG)},
+ {PCI_DEVICE_DATA(INTEL, MEI_ICH9_10, MEI_ME_ICH_CFG)},
+ {PCI_DEVICE_DATA(INTEL, MEI_ICH9M_1, MEI_ME_ICH_CFG)},
+ {PCI_DEVICE_DATA(INTEL, MEI_ICH9M_2, MEI_ME_ICH_CFG)},
+ {PCI_DEVICE_DATA(INTEL, MEI_ICH9M_3, MEI_ME_ICH_CFG)},
+ {PCI_DEVICE_DATA(INTEL, MEI_ICH9M_4, MEI_ME_ICH_CFG)},
+
+ {PCI_DEVICE_DATA(INTEL, MEI_ICH10_1, MEI_ME_ICH10_CFG)},
+ {PCI_DEVICE_DATA(INTEL, MEI_ICH10_2, MEI_ME_ICH10_CFG)},
+ {PCI_DEVICE_DATA(INTEL, MEI_ICH10_3, MEI_ME_ICH10_CFG)},
+ {PCI_DEVICE_DATA(INTEL, MEI_ICH10_4, MEI_ME_ICH10_CFG)},
+
+ {PCI_DEVICE_DATA(INTEL, MEI_IBXPK_1, MEI_ME_PCH6_CFG)},
+ {PCI_DEVICE_DATA(INTEL, MEI_IBXPK_2, MEI_ME_PCH6_CFG)},
+ {PCI_DEVICE_DATA(INTEL, MEI_CPT_1, MEI_ME_PCH_CPT_PBG_CFG)},
+ {PCI_DEVICE_DATA(INTEL, MEI_PBG_1, MEI_ME_PCH_CPT_PBG_CFG)},
+ {PCI_DEVICE_DATA(INTEL, MEI_PPT_1, MEI_ME_PCH7_CFG)},
+ {PCI_DEVICE_DATA(INTEL, MEI_PPT_2, MEI_ME_PCH7_CFG)},
+ {PCI_DEVICE_DATA(INTEL, MEI_PPT_3, MEI_ME_PCH7_CFG)},
+ {PCI_DEVICE_DATA(INTEL, MEI_LPT_H, MEI_ME_PCH8_SPS_4_CFG)},
+ {PCI_DEVICE_DATA(INTEL, MEI_LPT_W, MEI_ME_PCH8_SPS_4_CFG)},
+ {PCI_DEVICE_DATA(INTEL, MEI_LPT_LP, MEI_ME_PCH8_CFG)},
+ {PCI_DEVICE_DATA(INTEL, MEI_LPT_HR, MEI_ME_PCH8_SPS_4_CFG)},
+ {PCI_DEVICE_DATA(INTEL, MEI_WPT_LP, MEI_ME_PCH8_CFG)},
+ {PCI_DEVICE_DATA(INTEL, MEI_WPT_LP_2, MEI_ME_PCH8_CFG)},
+
+ {PCI_DEVICE_DATA(INTEL, MEI_SPT, MEI_ME_PCH8_CFG)},
+ {PCI_DEVICE_DATA(INTEL, MEI_SPT_2, MEI_ME_PCH8_CFG)},
+ {PCI_DEVICE_DATA(INTEL, MEI_SPT_3, MEI_ME_PCH8_ITOUCH_CFG)},
+ {PCI_DEVICE_DATA(INTEL, MEI_SPT_H, MEI_ME_PCH8_SPS_4_CFG)},
+ {PCI_DEVICE_DATA(INTEL, MEI_SPT_H_2, MEI_ME_PCH8_SPS_4_CFG)},
+ {PCI_DEVICE_DATA(INTEL, MEI_LBG, MEI_ME_PCH12_SPS_4_CFG)},
+
+ {PCI_DEVICE_DATA(INTEL, MEI_BXT_M, MEI_ME_PCH8_CFG)},
+ {PCI_DEVICE_DATA(INTEL, MEI_APL_I, MEI_ME_PCH8_CFG)},
+
+ {PCI_DEVICE_DATA(INTEL, MEI_DNV_IE, MEI_ME_PCH8_CFG)},
+
+ {PCI_DEVICE_DATA(INTEL, MEI_GLK, MEI_ME_PCH8_CFG)},
+
+ {PCI_DEVICE_DATA(INTEL, MEI_KBP, MEI_ME_PCH8_CFG)},
+ {PCI_DEVICE_DATA(INTEL, MEI_KBP_2, MEI_ME_PCH8_CFG)},
+ {PCI_DEVICE_DATA(INTEL, MEI_KBP_3, MEI_ME_PCH8_CFG)},
+
+ {PCI_DEVICE_DATA(INTEL, MEI_CNP_LP, MEI_ME_PCH12_CFG)},
+ {PCI_DEVICE_DATA(INTEL, MEI_CNP_LP_3, MEI_ME_PCH8_ITOUCH_CFG)},
+ {PCI_DEVICE_DATA(INTEL, MEI_CNP_H, MEI_ME_PCH12_SPS_CFG)},
+ {PCI_DEVICE_DATA(INTEL, MEI_CNP_H_3, MEI_ME_PCH12_SPS_ITOUCH_CFG)},
+
+ {PCI_DEVICE_DATA(INTEL, MEI_CMP_LP, MEI_ME_PCH12_CFG)},
+ {PCI_DEVICE_DATA(INTEL, MEI_CMP_LP_3, MEI_ME_PCH8_ITOUCH_CFG)},
+ {PCI_DEVICE_DATA(INTEL, MEI_CMP_V, MEI_ME_PCH12_CFG)},
+ {PCI_DEVICE_DATA(INTEL, MEI_CMP_H, MEI_ME_PCH12_CFG)},
+ {PCI_DEVICE_DATA(INTEL, MEI_CMP_H_3, MEI_ME_PCH8_ITOUCH_CFG)},
+
+ {PCI_DEVICE_DATA(INTEL, MEI_ICP_LP, MEI_ME_PCH12_CFG)},
+ {PCI_DEVICE_DATA(INTEL, MEI_ICP_N, MEI_ME_PCH12_CFG)},
+
+ {PCI_DEVICE_DATA(INTEL, MEI_TGP_LP, MEI_ME_PCH15_CFG)},
+ {PCI_DEVICE_DATA(INTEL, MEI_TGP_H, MEI_ME_PCH15_SPS_CFG)},
+
+ {PCI_DEVICE_DATA(INTEL, MEI_JSP_N, MEI_ME_PCH15_CFG)},
+
+ {PCI_DEVICE_DATA(INTEL, MEI_MCC, MEI_ME_PCH15_CFG)},
+ {PCI_DEVICE_DATA(INTEL, MEI_MCC_4, MEI_ME_PCH8_CFG)},
+
+ {PCI_DEVICE_DATA(INTEL, MEI_CDF, MEI_ME_PCH8_CFG)},
+
+ {PCI_DEVICE_DATA(INTEL, MEI_EBG, MEI_ME_PCH15_SPS_CFG)},
+
+ {PCI_DEVICE_DATA(INTEL, MEI_ADP_S, MEI_ME_PCH15_CFG)},
+ {PCI_DEVICE_DATA(INTEL, MEI_ADP_LP, MEI_ME_PCH15_CFG)},
+ {PCI_DEVICE_DATA(INTEL, MEI_ADP_P, MEI_ME_PCH15_CFG)},
+ {PCI_DEVICE_DATA(INTEL, MEI_ADP_N, MEI_ME_PCH15_CFG)},
+
+ {PCI_DEVICE_DATA(INTEL, MEI_RPL_S, MEI_ME_PCH15_SPS_CFG)},
+
+ {PCI_DEVICE_DATA(INTEL, MEI_MTL_M, MEI_ME_PCH15_CFG)},
+ {PCI_DEVICE_DATA(INTEL, MEI_ARL_S, MEI_ME_PCH15_CFG)},
+ {PCI_DEVICE_DATA(INTEL, MEI_ARL_H, MEI_ME_PCH15_CFG)},
+
+ {PCI_DEVICE_DATA(INTEL, MEI_LNL_M, MEI_ME_PCH15_CFG)},
+
+ {PCI_DEVICE_DATA(INTEL, MEI_PTL_H, MEI_ME_PCH15_CFG)},
+ {PCI_DEVICE_DATA(INTEL, MEI_PTL_P, MEI_ME_PCH15_CFG)},
+
+ {PCI_DEVICE_DATA(INTEL, MEI_WCL_P, MEI_ME_PCH15_CFG)},
+
+ {PCI_DEVICE_DATA(INTEL, MEI_NVL_S, MEI_ME_PCH15_CFG)},
+ {PCI_DEVICE_DATA(INTEL, MEI_NVL_H, MEI_ME_PCH15_CFG)},
/* required last entry */
{0, }
@@ -145,11 +147,14 @@ static inline void mei_me_set_pm_domain(struct mei_device *dev) {}
static inline void mei_me_unset_pm_domain(struct mei_device *dev) {}
#endif /* CONFIG_PM */
-static int mei_me_read_fws(const struct mei_device *dev, int where, u32 *val)
+static int mei_me_read_fws(const struct mei_device *dev, int where, const char *name, u32 *val)
{
struct pci_dev *pdev = to_pci_dev(dev->parent);
+ int ret;
- return pci_read_config_dword(pdev, where, val);
+ ret = pci_read_config_dword(pdev, where, val);
+ trace_mei_pci_cfg_read(&dev->dev, name, where, *val, ret);
+ return pcibios_err_to_errno(ret);
}
/**
diff --git a/drivers/misc/ti_fpc202.c b/drivers/misc/ti_fpc202.c
index 8eb2b5ac9850..2aac83ec4a39 100644
--- a/drivers/misc/ti_fpc202.c
+++ b/drivers/misc/ti_fpc202.c
@@ -7,12 +7,17 @@
*/
#include <linux/cleanup.h>
+#include <linux/device/devres.h>
#include <linux/err.h>
#include <linux/i2c.h>
#include <linux/i2c-atr.h>
#include <linux/gpio/consumer.h>
#include <linux/gpio/driver.h>
+#include <linux/gpio/machine.h>
+#include <linux/leds.h>
#include <linux/module.h>
+#include <linux/math.h>
+#include <linux/types.h>
#define FPC202_NUM_PORTS 2
#define FPC202_ALIASES_PER_PORT 2
@@ -34,18 +39,55 @@
* ...
* 19: P1_S1_OUT_B
*
+ * Ports with optional LED control:
+ *
+ * 20: P0_S0_OUT_C (P0_S0_LED1)
+ * ...
+ * 23: P1_S1_OUT_C (P1_S1_LED1)
+ * 24: P0_S0_OUT_D (P0_S0_LED2
+ * ...
+ * 27: P1_S1_OUT_D (P1_S1_LED2)
+ *
*/
-#define FPC202_GPIO_COUNT 20
+#define FPC202_GPIO_COUNT 28
#define FPC202_GPIO_P0_S0_IN_B 4
#define FPC202_GPIO_P0_S0_OUT_A 12
+#define FPC202_GPIO_P0_S0_OUT_C 20
+#define FPC202_GPIO_P0_S0_OUT_D 24
#define FPC202_REG_IN_A_INT 0x6
#define FPC202_REG_IN_C_IN_B 0x7
#define FPC202_REG_OUT_A_OUT_B 0x8
+#define FPC202_REG_OUT_C_OUT_D 0x9
#define FPC202_REG_OUT_A_OUT_B_VAL 0xa
+#define FPC202_LED_COUNT 8
+
+/* There are four LED GPIO mode registers which manage two GPIOs each. */
+#define FPC202_REG_LED_MODE(offset) (0x1a + 0x20 * ((offset) % 4))
+
+/* LED1 GPIOs (*_OUT_C) are configured in bits 1:0, LED2 GPIOs (*_OUT_D) in bits 3:2. */
+#define FPC202_LED_MODE_SHIFT(offset) ((offset) < FPC202_GPIO_P0_S0_OUT_D ? 0 : 2)
+#define FPC202_LED_MODE_MASK(offset) (GENMASK(1, 0) << FPC202_LED_MODE_SHIFT(offset))
+
+/* There is one PWM control register for each GPIO LED */
+#define FPC202_REG_LED_PWM(offset) \
+ (((offset) < FPC202_GPIO_P0_S0_OUT_D ? 0x14 : 0x15) + 0x20 * ((offset) % 4))
+
+/* There are two blink delay registers (on/off time) for each GPIO LED */
+#define FPC202_REG_LED_BLINK_ON(offset) \
+ (((offset) < FPC202_GPIO_P0_S0_OUT_D ? 0x16 : 0x18) + 0x20 * ((offset) % 4))
+#define FPC202_REG_LED_BLINK_OFF(offset) (FPC202_REG_LED_BLINK_ON(offset) + 1)
+
+/* The actual hardware precision is 2.5ms but since the LED API doesn't handle sub-millisecond
+ * timesteps this is rounded up to 5ms
+ */
+#define FPC202_LED_BLINK_PRECISION 5UL
+
+#define FPC202_LED_MAX_BRIGHTNESS 255
+
#define FPC202_REG_MOD_DEV(port, dev) (0xb4 + ((port) * 4) + (dev))
#define FPC202_REG_AUX_DEV(port, dev) (0xb6 + ((port) * 4) + (dev))
@@ -59,15 +101,34 @@
/* Even aliases are assigned to device 0 and odd aliases to device 1 */
#define fpc202_dev_num_from_alias(alias) ((alias) % 2)
+enum fpc202_led_mode {
+ FPC202_LED_MODE_OFF = 0,
+ FPC202_LED_MODE_ON = 1,
+ FPC202_LED_MODE_PWM = 2,
+ FPC202_LED_MODE_BLINK = 3,
+};
+
+struct fpc202_led {
+ int offset;
+ struct led_classdev led_cdev;
+ struct fpc202_priv *priv;
+ struct gpio_desc *gpio;
+ enum fpc202_led_mode mode;
+};
+
struct fpc202_priv {
struct i2c_client *client;
struct i2c_atr *atr;
struct gpio_desc *en_gpio;
struct gpio_chip gpio;
+ struct fpc202_led leds[FPC202_LED_COUNT];
/* Lock REG_MOD/AUX_DEV and addr_caches during attach/detach */
struct mutex reg_dev_lock;
+ /* Lock LED mode select register during accesses */
+ struct mutex led_mode_lock;
+
/* Cached device addresses for both ports and their devices */
u8 addr_caches[2][2];
@@ -97,6 +158,11 @@ static int fpc202_gpio_get_dir(int offset)
return offset < FPC202_GPIO_P0_S0_OUT_A ? GPIO_LINE_DIRECTION_IN : GPIO_LINE_DIRECTION_OUT;
}
+static int fpc202_gpio_has_led_caps(int offset)
+{
+ return offset >= FPC202_GPIO_P0_S0_OUT_C;
+}
+
static int fpc202_read(struct fpc202_priv *priv, u8 reg)
{
int val;
@@ -118,6 +184,37 @@ static void fpc202_set_enable(struct fpc202_priv *priv, int enable)
gpiod_set_value(priv->en_gpio, enable);
}
+static int fpc202_led_mode_write(struct fpc202_priv *priv,
+ int offset,
+ enum fpc202_led_mode mode)
+{
+ u8 val, reg = FPC202_REG_LED_MODE(offset);
+ int ret;
+
+ guard(mutex)(&priv->led_mode_lock);
+
+ ret = fpc202_read(priv, reg);
+ if (ret < 0) {
+ dev_err(&priv->client->dev, "failed to read LED mode %d! err %d\n",
+ offset, ret);
+ return ret;
+ }
+
+ val = (u8)ret & ~FPC202_LED_MODE_MASK(offset);
+ val |= mode << FPC202_LED_MODE_SHIFT(offset);
+
+ return fpc202_write(priv, reg, val);
+}
+
+static int fpc202_led_mode_set(struct fpc202_led *led, enum fpc202_led_mode mode)
+{
+ struct fpc202_priv *priv = led->priv;
+
+ led->mode = mode;
+
+ return fpc202_led_mode_write(priv, led->offset, mode);
+}
+
static int fpc202_gpio_set(struct gpio_chip *chip, unsigned int offset,
int value)
{
@@ -125,6 +222,16 @@ static int fpc202_gpio_set(struct gpio_chip *chip, unsigned int offset,
int ret;
u8 val;
+ if (fpc202_gpio_has_led_caps(offset)) {
+ ret = fpc202_led_mode_write(priv, offset,
+ value ? FPC202_LED_MODE_ON : FPC202_LED_MODE_OFF);
+ if (ret < 0)
+ dev_err(&priv->client->dev, "Failed to set GPIO %d LED mode! err %d\n",
+ offset, ret);
+
+ return ret;
+ }
+
ret = fpc202_read(priv, FPC202_REG_OUT_A_OUT_B_VAL);
if (ret < 0) {
dev_err(&priv->client->dev, "Failed to set GPIO %d value! err %d\n", offset, ret);
@@ -153,9 +260,11 @@ static int fpc202_gpio_get(struct gpio_chip *chip, unsigned int offset)
} else if (offset < FPC202_GPIO_P0_S0_OUT_A) {
reg = FPC202_REG_IN_C_IN_B;
bit = BIT(offset - FPC202_GPIO_P0_S0_IN_B);
- } else {
+ } else if (!fpc202_gpio_has_led_caps(offset)) {
reg = FPC202_REG_OUT_A_OUT_B_VAL;
bit = BIT(offset - FPC202_GPIO_P0_S0_OUT_A);
+ } else {
+ return -EOPNOTSUPP;
}
ret = fpc202_read(priv, reg);
@@ -177,21 +286,29 @@ static int fpc202_gpio_direction_output(struct gpio_chip *chip, unsigned int off
int value)
{
struct fpc202_priv *priv = gpiochip_get_data(chip);
+ u8 reg, val, bit;
int ret;
- u8 val;
if (fpc202_gpio_get_dir(offset) == GPIO_LINE_DIRECTION_IN)
return -EINVAL;
fpc202_gpio_set(chip, offset, value);
- ret = fpc202_read(priv, FPC202_REG_OUT_A_OUT_B);
+ if (fpc202_gpio_has_led_caps(offset)) {
+ reg = FPC202_REG_OUT_C_OUT_D;
+ bit = BIT(offset - FPC202_GPIO_P0_S0_OUT_C);
+ } else {
+ reg = FPC202_REG_OUT_A_OUT_B;
+ bit = BIT(offset - FPC202_GPIO_P0_S0_OUT_A);
+ }
+
+ ret = fpc202_read(priv, reg);
if (ret < 0)
return ret;
- val = (u8)ret | BIT(offset - FPC202_GPIO_P0_S0_OUT_A);
+ val = (u8)ret | bit;
- return fpc202_write(priv, FPC202_REG_OUT_A_OUT_B, val);
+ return fpc202_write(priv, reg, val);
}
/*
@@ -243,23 +360,15 @@ static void fpc202_detach_addr(struct i2c_atr *atr, u32 chan_id,
u16 addr)
{
struct fpc202_priv *priv = i2c_atr_get_driver_data(atr);
- int dev_num, reg_mod, val;
+ int dev_num, val;
for (dev_num = 0; dev_num < 2; dev_num++) {
- reg_mod = FPC202_REG_MOD_DEV(chan_id, dev_num);
-
mutex_lock(&priv->reg_dev_lock);
val = priv->addr_caches[chan_id][dev_num];
mutex_unlock(&priv->reg_dev_lock);
- if (val < 0) {
- dev_err(&priv->client->dev, "failed to read register 0x%x while detaching address 0x%02x\n",
- reg_mod, addr);
- return;
- }
-
if (val == (addr & 0x7f)) {
fpc202_write_dev_addr(priv, chan_id, dev_num, FPC202_REG_DEV_INVALID);
return;
@@ -272,6 +381,183 @@ static const struct i2c_atr_ops fpc202_atr_ops = {
.detach_addr = fpc202_detach_addr,
};
+static struct fpc202_led *fpc202_cdev_to_led(struct led_classdev *cdev)
+{
+ return container_of(cdev, struct fpc202_led, led_cdev);
+}
+
+static struct fpc202_led *fpc202_led_get(struct fpc202_priv *priv, int offset)
+{
+ return &priv->leds[offset - FPC202_GPIO_P0_S0_OUT_C];
+}
+
+static int fpc202_led_blink_set(struct led_classdev *cdev,
+ unsigned long *delay_on,
+ unsigned long *delay_off)
+{
+ struct fpc202_led *led = fpc202_cdev_to_led(cdev);
+ struct fpc202_priv *priv = led->priv;
+ unsigned long val;
+ int ret;
+
+ if (*delay_on == 0 && *delay_off == 0) {
+ *delay_on = 250;
+ *delay_off = 250;
+ } else {
+ if (*delay_on % FPC202_LED_BLINK_PRECISION)
+ *delay_on = roundup(*delay_on, FPC202_LED_BLINK_PRECISION);
+
+ if (*delay_off % FPC202_LED_BLINK_PRECISION)
+ *delay_off = roundup(*delay_off, FPC202_LED_BLINK_PRECISION);
+ }
+
+ /* Multiply the duration by two, since the actual precision is 2.5ms not 5ms*/
+ val = 2 * (*delay_on / FPC202_LED_BLINK_PRECISION);
+ if (val > 255) {
+ val = 255;
+ *delay_on = (val / 2) * FPC202_LED_BLINK_PRECISION;
+ }
+
+ ret = fpc202_write(priv, FPC202_REG_LED_BLINK_ON(led->offset), val);
+ if (ret) {
+ dev_err(&priv->client->dev,
+ "Failed to set blink on duration for LED %d, err %d\n",
+ led->offset, ret);
+ return ret;
+ }
+
+ val = 2 * (*delay_off / FPC202_LED_BLINK_PRECISION);
+ if (val > 255) {
+ val = 255;
+ *delay_off = (val / 2) * FPC202_LED_BLINK_PRECISION;
+ }
+
+ ret = fpc202_write(priv, FPC202_REG_LED_BLINK_OFF(led->offset), val);
+ if (ret) {
+ dev_err(&priv->client->dev,
+ "Failed to set blink off duration for LED %d, err %d\n",
+ led->offset, ret);
+ return ret;
+ }
+
+ return fpc202_led_mode_set(led, FPC202_LED_MODE_BLINK);
+}
+
+static enum led_brightness fpc202_led_brightness_get(struct led_classdev *cdev)
+{
+ struct fpc202_led *led = fpc202_cdev_to_led(cdev);
+
+ if (led->mode == FPC202_LED_MODE_OFF)
+ return LED_OFF;
+
+ return LED_ON;
+}
+
+static int fpc202_led_brightness_set(struct led_classdev *cdev,
+ enum led_brightness brightness)
+{
+ struct fpc202_led *led = fpc202_cdev_to_led(cdev);
+ struct fpc202_priv *priv = led->priv;
+ int ret;
+
+ if (!brightness)
+ return fpc202_led_mode_set(led, FPC202_LED_MODE_OFF);
+
+ if (led->mode != FPC202_LED_MODE_BLINK) {
+ if (brightness == FPC202_LED_MAX_BRIGHTNESS)
+ return fpc202_led_mode_set(led, FPC202_LED_MODE_ON);
+
+ ret = fpc202_led_mode_set(led, FPC202_LED_MODE_PWM);
+ if (ret) {
+ dev_err(&priv->client->dev, "Failed to set LED %d mode, err %d\n",
+ led->offset, ret);
+ return ret;
+ }
+ }
+
+ return fpc202_write(priv, FPC202_REG_LED_PWM(led->offset), brightness);
+}
+
+static int fpc202_register_led(struct fpc202_priv *priv, int offset,
+ struct device_node *led_handle)
+{
+ struct fpc202_led *led = fpc202_led_get(priv, offset);
+ struct device *dev = &priv->client->dev;
+ struct led_init_data init_data = { };
+ int ret = 0;
+
+ led->priv = priv;
+ led->offset = offset;
+ led->led_cdev.max_brightness = FPC202_LED_MAX_BRIGHTNESS;
+ led->led_cdev.brightness_set_blocking = fpc202_led_brightness_set;
+ led->led_cdev.brightness_get = fpc202_led_brightness_get;
+ led->led_cdev.blink_set = fpc202_led_blink_set;
+
+ init_data.fwnode = of_fwnode_handle(led_handle);
+ init_data.default_label = NULL;
+ init_data.devicename = NULL;
+ init_data.devname_mandatory = false;
+
+ ret = fpc202_led_mode_set(led, FPC202_LED_MODE_OFF);
+ if (ret) {
+ dev_err(dev, "Failed to set LED %d mode, err %d\n", offset, ret);
+ return ret;
+ }
+
+ ret = devm_led_classdev_register_ext(dev, &led->led_cdev, &init_data);
+ if (ret) {
+ dev_err(dev, "Failed to register LED %d cdev, err %d\n", offset, ret);
+ return ret;
+ }
+
+ /* Claim corresponding GPIO line so that it cannot be interfered with */
+ led->gpio = gpiochip_request_own_desc(&priv->gpio, offset, led->led_cdev.name,
+ GPIO_ACTIVE_HIGH, GPIOD_ASIS);
+ if (IS_ERR(led->gpio)) {
+ ret = PTR_ERR(led->gpio);
+ dev_err(dev, "Failed to register LED %d cdev, err %d\n", offset, ret);
+ }
+
+ return ret;
+}
+
+static int fpc202_register_leds(struct fpc202_priv *priv)
+{
+ struct device *dev = &priv->client->dev;
+ int offset, ret = 0;
+
+ if (!devres_open_group(dev, fpc202_register_leds, GFP_KERNEL))
+ return -ENOMEM;
+
+ for_each_child_of_node_scoped(dev->of_node, led_handle) {
+ ret = of_property_read_u32(led_handle, "reg", &offset);
+ if (ret) {
+ dev_err(dev, "Failed to read 'reg' property of child node, err %d\n", ret);
+ return ret;
+ }
+
+ if (offset < FPC202_GPIO_P0_S0_OUT_C || offset > FPC202_GPIO_COUNT)
+ continue;
+
+ ret = fpc202_register_led(priv, offset, led_handle);
+ if (ret) {
+ dev_err(dev, "Failed to register LED %d, err %d\n", offset,
+ ret);
+ goto free_own_gpios;
+ }
+ }
+
+ devres_close_group(dev, fpc202_register_leds);
+
+ return 0;
+
+free_own_gpios:
+ for (offset = 0; offset < FPC202_LED_COUNT; offset++)
+ if (priv->leds[offset].gpio)
+ gpiochip_free_own_desc(priv->leds[offset].gpio);
+ return ret;
+}
+
static int fpc202_probe_port(struct fpc202_priv *priv, struct device_node *i2c_handle, int port_id)
{
u16 aliases[FPC202_ALIASES_PER_PORT] = { };
@@ -310,13 +596,14 @@ static int fpc202_probe(struct i2c_client *client)
{
struct device *dev = &client->dev;
struct fpc202_priv *priv;
- int ret, port_id;
+ int ret, port_id, led_id;
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
if (!priv)
return -ENOMEM;
mutex_init(&priv->reg_dev_lock);
+ mutex_init(&priv->led_mode_lock);
priv->client = client;
i2c_set_clientdata(client, priv);
@@ -354,6 +641,12 @@ static int fpc202_probe(struct i2c_client *client)
i2c_atr_set_driver_data(priv->atr, priv);
+ ret = fpc202_register_leds(priv);
+ if (ret) {
+ dev_err(dev, "Failed to register LEDs, err %d\n", ret);
+ goto delete_atr;
+ }
+
bitmap_zero(priv->probed_ports, FPC202_NUM_PORTS);
for_each_child_of_node_scoped(dev->of_node, i2c_handle) {
@@ -366,11 +659,8 @@ static int fpc202_probe(struct i2c_client *client)
goto unregister_chans;
}
- if (port_id > FPC202_NUM_PORTS) {
- dev_err(dev, "port ID %d is out of range!\n", port_id);
- ret = -EINVAL;
- goto unregister_chans;
- }
+ if (port_id >= FPC202_NUM_PORTS)
+ continue;
ret = fpc202_probe_port(priv, i2c_handle, port_id);
if (ret) {
@@ -385,11 +675,18 @@ unregister_chans:
for_each_set_bit(port_id, priv->probed_ports, FPC202_NUM_PORTS)
fpc202_remove_port(priv, port_id);
+ for (led_id = 0; led_id < FPC202_LED_COUNT; led_id++)
+ if (priv->leds[led_id].gpio)
+ gpiochip_free_own_desc(priv->leds[led_id].gpio);
+
+ devres_release_group(&client->dev, fpc202_register_leds);
+delete_atr:
i2c_atr_delete(priv->atr);
disable_gpio:
fpc202_set_enable(priv, 0);
gpiochip_remove(&priv->gpio);
destroy_mutex:
+ mutex_destroy(&priv->led_mode_lock);
mutex_destroy(&priv->reg_dev_lock);
out:
return ret;
@@ -398,11 +695,19 @@ out:
static void fpc202_remove(struct i2c_client *client)
{
struct fpc202_priv *priv = i2c_get_clientdata(client);
- int port_id;
+ int port_id, led_id;
for_each_set_bit(port_id, priv->probed_ports, FPC202_NUM_PORTS)
fpc202_remove_port(priv, port_id);
+ for (led_id = 0; led_id < FPC202_LED_COUNT; led_id++)
+ if (priv->leds[led_id].gpio)
+ gpiochip_free_own_desc(priv->leds[led_id].gpio);
+
+ /* Release led devices early so that blink handlers don't trigger. */
+ devres_release_group(&client->dev, fpc202_register_leds);
+
+ mutex_destroy(&priv->led_mode_lock);
mutex_destroy(&priv->reg_dev_lock);
i2c_atr_delete(priv->atr);
diff --git a/drivers/misc/vmw_vmci/vmci_queue_pair.c b/drivers/misc/vmw_vmci/vmci_queue_pair.c
index 872aad355dbe..b777bc3fdde2 100644
--- a/drivers/misc/vmw_vmci/vmci_queue_pair.c
+++ b/drivers/misc/vmw_vmci/vmci_queue_pair.c
@@ -2532,7 +2532,7 @@ static bool qp_wait_for_ready_queue(struct vmci_qp *qpair)
* VMCI_ERROR_QUEUEPAIR_NOSPACE if no space was available to enqueue
* data, VMCI_ERROR_INVALID_SIZE, if any queue pointer is outside the
* queue (as defined by the queue size), VMCI_ERROR_INVALID_ARGS, if
- * an error occured when accessing the buffer,
+ * an error occurred when accessing the buffer,
* VMCI_ERROR_QUEUEPAIR_NOTATTACHED, if the queue pair pages aren't
* available. Otherwise, the number of bytes written to the queue is
* returned. Updates the tail pointer of the produce queue.
@@ -2598,7 +2598,7 @@ static ssize_t qp_enqueue_locked(struct vmci_queue *produce_q,
* VMCI_ERROR_QUEUEPAIR_NODATA if no data was available to dequeue.
* VMCI_ERROR_INVALID_SIZE, if any queue pointer is outside the queue
* (as defined by the queue size).
- * VMCI_ERROR_INVALID_ARGS, if an error occured when accessing the buffer.
+ * VMCI_ERROR_INVALID_ARGS, if an error occurred when accessing the buffer.
* Otherwise the number of bytes dequeued is returned.
* Side effects:
* Updates the head pointer of the consume queue.
diff --git a/drivers/most/most_cdev.c b/drivers/most/most_cdev.c
index b31dc824466f..5df508d8d60a 100644
--- a/drivers/most/most_cdev.c
+++ b/drivers/most/most_cdev.c
@@ -19,11 +19,14 @@
#define CHRDEV_REGION_SIZE 50
+static const struct class most_cdev_class = {
+ .name = "most_cdev"
+};
+
static struct cdev_component {
dev_t devno;
struct ida minor_id;
unsigned int major;
- struct class *class;
struct most_component cc;
} comp;
@@ -91,7 +94,7 @@ static void destroy_cdev(struct comp_channel *c)
{
unsigned long flags;
- device_destroy(comp.class, c->devno);
+ device_destroy(&most_cdev_class, c->devno);
cdev_del(&c->cdev);
spin_lock_irqsave(&ch_list_lock, flags);
list_del(&c->list);
@@ -455,7 +458,7 @@ static int comp_probe(struct most_interface *iface, int channel_id,
spin_lock_irqsave(&ch_list_lock, cl_flags);
list_add_tail(&c->list, &channel_list);
spin_unlock_irqrestore(&ch_list_lock, cl_flags);
- c->dev = device_create(comp.class, NULL, c->devno, NULL, "%s", name);
+ c->dev = device_create(&most_cdev_class, NULL, c->devno, NULL, "%s", name);
if (IS_ERR(c->dev)) {
retval = PTR_ERR(c->dev);
@@ -487,13 +490,14 @@ static struct cdev_component comp = {
},
};
+
static int __init most_cdev_init(void)
{
int err;
- comp.class = class_create("most_cdev");
- if (IS_ERR(comp.class))
- return PTR_ERR(comp.class);
+ err = class_register(&most_cdev_class);
+ if (err)
+ return err;
ida_init(&comp.minor_id);
@@ -515,7 +519,7 @@ free_cdev:
unregister_chrdev_region(comp.devno, CHRDEV_REGION_SIZE);
dest_ida:
ida_destroy(&comp.minor_id);
- class_destroy(comp.class);
+ class_unregister(&most_cdev_class);
return err;
}
@@ -532,7 +536,7 @@ static void __exit most_cdev_exit(void)
}
unregister_chrdev_region(comp.devno, CHRDEV_REGION_SIZE);
ida_destroy(&comp.minor_id);
- class_destroy(comp.class);
+ class_unregister(&most_cdev_class);
}
module_init(most_cdev_init);
diff --git a/drivers/most/most_usb.c b/drivers/most/most_usb.c
index d2c0875727a3..6437733afee0 100644
--- a/drivers/most/most_usb.c
+++ b/drivers/most/most_usb.c
@@ -1009,13 +1009,11 @@ hdm_probe(struct usb_interface *interface, const struct usb_device_id *id)
goto err_free_conf;
mdev->iface.channel_vector = mdev->cap;
- mdev->ep_address =
- kcalloc(num_endpoints, sizeof(*mdev->ep_address), GFP_KERNEL);
+ mdev->ep_address = kzalloc_objs(*mdev->ep_address, num_endpoints);
if (!mdev->ep_address)
goto err_free_cap;
- mdev->busy_urbs =
- kzalloc_objs(*mdev->busy_urbs, num_endpoints);
+ mdev->busy_urbs = kzalloc_objs(*mdev->busy_urbs, num_endpoints);
if (!mdev->busy_urbs)
goto err_free_ep_address;
diff --git a/drivers/mux/mmio.c b/drivers/mux/mmio.c
index 0611ef28bb69..b61e590f2ac9 100644
--- a/drivers/mux/mmio.c
+++ b/drivers/mux/mmio.c
@@ -100,12 +100,14 @@ static int mux_mmio_probe(struct platform_device *pdev)
mux_mmio = mux_chip_priv(mux_chip);
- mux_mmio->fields = devm_kmalloc(dev, num_fields * sizeof(*mux_mmio->fields), GFP_KERNEL);
+ mux_mmio->fields = devm_kcalloc(dev, num_fields, sizeof(*mux_mmio->fields),
+ GFP_KERNEL);
if (!mux_mmio->fields)
return -ENOMEM;
- mux_mmio->hardware_states = devm_kmalloc(dev, num_fields *
- sizeof(*mux_mmio->hardware_states), GFP_KERNEL);
+ mux_mmio->hardware_states = devm_kcalloc(dev, num_fields,
+ sizeof(*mux_mmio->hardware_states),
+ GFP_KERNEL);
if (!mux_mmio->hardware_states)
return -ENOMEM;
diff --git a/drivers/nvmem/qnap-mcu-eeprom.c b/drivers/nvmem/qnap-mcu-eeprom.c
index 0b919895b3b2..07bdaa2a33fa 100644
--- a/drivers/nvmem/qnap-mcu-eeprom.c
+++ b/drivers/nvmem/qnap-mcu-eeprom.c
@@ -86,10 +86,10 @@ static int qnap_mcu_eeprom_probe(struct platform_device *pdev)
nvcfg.read_only = true;
nvcfg.root_only = false;
nvcfg.reg_read = qnap_mcu_eeprom_read;
- nvcfg.size = QNAP_MCU_EEPROM_SIZE,
- nvcfg.word_size = 1,
- nvcfg.stride = 1,
- nvcfg.priv = mcu,
+ nvcfg.size = QNAP_MCU_EEPROM_SIZE;
+ nvcfg.word_size = 1;
+ nvcfg.stride = 1;
+ nvcfg.priv = mcu;
ndev = devm_nvmem_register(&pdev->dev, &nvcfg);
if (IS_ERR(ndev))
diff --git a/drivers/nvmem/rockchip-otp.c b/drivers/nvmem/rockchip-otp.c
index d88f12c53242..0ec78b5e19e7 100644
--- a/drivers/nvmem/rockchip-otp.c
+++ b/drivers/nvmem/rockchip-otp.c
@@ -27,6 +27,7 @@
#define OTPC_USER_CTRL 0x0100
#define OTPC_USER_ADDR 0x0104
#define OTPC_USER_ENABLE 0x0108
+#define OTPC_USER_QP 0x0120
#define OTPC_USER_Q 0x0124
#define OTPC_INT_STATUS 0x0304
#define OTPC_SBPI_CMD0_OFFSET 0x1000
@@ -59,7 +60,6 @@
#define RK3588_OTPC_AUTO_EN 0x08
#define RK3588_OTPC_INT_ST 0x84
#define RK3588_OTPC_DOUT0 0x20
-#define RK3588_NBYTES 4
#define RK3588_BURST_NUM 1
#define RK3588_BURST_SHIFT 8
#define RK3588_ADDR_SHIFT 16
@@ -69,6 +69,7 @@
struct rockchip_data {
int size;
int read_offset;
+ int word_size;
const char * const *clks;
int num_clks;
nvmem_reg_read_t reg_read;
@@ -184,49 +185,81 @@ read_end:
return ret;
}
+static int rk3568_otp_read(void *context, unsigned int offset, void *val,
+ size_t count)
+{
+ struct rockchip_otp *otp = context;
+ u16 *buf = val;
+ u32 otp_qp;
+ int ret;
+
+ ret = rockchip_otp_reset(otp);
+ if (ret) {
+ dev_err(otp->dev, "failed to reset otp phy\n");
+ return ret;
+ }
+
+ ret = rockchip_otp_ecc_enable(otp, true);
+ if (ret) {
+ dev_err(otp->dev, "rockchip_otp_ecc_enable err\n");
+ return ret;
+ }
+
+ writel(OTPC_USE_USER | OTPC_USE_USER_MASK, otp->base + OTPC_USER_CTRL);
+ udelay(5);
+
+ while (count--) {
+ writel(offset++ | OTPC_USER_ADDR_MASK,
+ otp->base + OTPC_USER_ADDR);
+ writel(OTPC_USER_FSM_ENABLE | OTPC_USER_FSM_ENABLE_MASK,
+ otp->base + OTPC_USER_ENABLE);
+
+ ret = rockchip_otp_wait_status(otp, OTPC_INT_STATUS,
+ OTPC_USER_DONE);
+ if (ret) {
+ dev_err(otp->dev, "timeout during read setup\n");
+ goto read_end;
+ }
+
+ otp_qp = readl(otp->base + OTPC_USER_QP);
+ if (((otp_qp & 0xc0) == 0xc0) || (otp_qp & 0x20)) {
+ ret = -EIO;
+ dev_err(otp->dev, "ecc check error during read setup\n");
+ goto read_end;
+ }
+
+ *buf++ = readl(otp->base + OTPC_USER_Q);
+ }
+
+read_end:
+ writel(0x0 | OTPC_USE_USER_MASK, otp->base + OTPC_USER_CTRL);
+
+ return ret;
+}
+
static int rk3588_otp_read(void *context, unsigned int offset,
- void *val, size_t bytes)
+ void *val, size_t count)
{
struct rockchip_otp *otp = context;
- unsigned int addr_start, addr_end, addr_len;
- int ret, i = 0;
- u32 data;
- u8 *buf;
-
- addr_start = round_down(offset, RK3588_NBYTES) / RK3588_NBYTES;
- addr_end = round_up(offset + bytes, RK3588_NBYTES) / RK3588_NBYTES;
- addr_len = addr_end - addr_start;
- addr_start += otp->data->read_offset / RK3588_NBYTES;
-
- buf = kzalloc(array_size(addr_len, RK3588_NBYTES), GFP_KERNEL);
- if (!buf)
- return -ENOMEM;
+ u32 *buf = val;
+ int ret;
- while (addr_len--) {
- writel((addr_start << RK3588_ADDR_SHIFT) |
+ while (count--) {
+ writel((offset++ << RK3588_ADDR_SHIFT) |
(RK3588_BURST_NUM << RK3588_BURST_SHIFT),
otp->base + RK3588_OTPC_AUTO_CTRL);
writel(RK3588_AUTO_EN, otp->base + RK3588_OTPC_AUTO_EN);
ret = rockchip_otp_wait_status(otp, RK3588_OTPC_INT_ST,
RK3588_RD_DONE);
- if (ret < 0) {
+ if (ret) {
dev_err(otp->dev, "timeout during read setup\n");
- goto read_end;
+ return ret;
}
- data = readl(otp->base + RK3588_OTPC_DOUT0);
- memcpy(&buf[i], &data, RK3588_NBYTES);
-
- i += RK3588_NBYTES;
- addr_start++;
+ *buf++ = readl(otp->base + RK3588_OTPC_DOUT0);
}
- memcpy(val, buf + offset % RK3588_NBYTES, bytes);
-
-read_end:
- kfree(buf);
-
return ret;
}
@@ -234,7 +267,7 @@ static int rockchip_otp_read(void *context, unsigned int offset,
void *val, size_t bytes)
{
struct rockchip_otp *otp = context;
- int ret;
+ int ret, word_size;
if (!otp->data || !otp->data->reg_read)
return -EINVAL;
@@ -245,8 +278,34 @@ static int rockchip_otp_read(void *context, unsigned int offset,
return ret;
}
- ret = otp->data->reg_read(context, offset, val, bytes);
+ offset += otp->data->read_offset;
+ word_size = otp->data->word_size;
+
+ if (word_size > 1) {
+ unsigned int addr_start, addr_end;
+ size_t count;
+ u8 *buf;
+
+ addr_start = offset / word_size;
+ addr_end = DIV_ROUND_UP(offset + bytes, word_size);
+ count = addr_end - addr_start;
+
+ buf = kzalloc(array_size(count, word_size), GFP_KERNEL);
+ if (!buf) {
+ ret = -ENOMEM;
+ goto err;
+ }
+
+ ret = otp->data->reg_read(context, addr_start, buf, count);
+ if (!ret)
+ memcpy(val, buf + (offset % word_size), bytes);
+
+ kfree(buf);
+ } else {
+ ret = otp->data->reg_read(context, offset, val, bytes);
+ }
+err:
clk_bulk_disable_unprepare(otp->data->num_clks, otp->clks);
return ret;
@@ -259,7 +318,7 @@ static struct nvmem_config otp_config = {
.type = NVMEM_TYPE_OTP,
.read_only = true,
.stride = 1,
- .word_size = 1,
+ .word_size = sizeof(u8),
.reg_read = rockchip_otp_read,
};
@@ -274,9 +333,34 @@ static const struct rockchip_data px30_data = {
.reg_read = px30_otp_read,
};
+static const char * const rk3528_otp_clocks[] = {
+ "otp", "apb_pclk", "sbpi",
+};
+
+static const struct rockchip_data rk3528_data = {
+ .size = 0x80,
+ .word_size = sizeof(u16),
+ .clks = rk3528_otp_clocks,
+ .num_clks = ARRAY_SIZE(rk3528_otp_clocks),
+ .reg_read = rk3568_otp_read,
+};
+
+static const char * const rk3568_otp_clocks[] = {
+ "otp", "apb_pclk", "phy", "sbpi",
+};
+
+static const struct rockchip_data rk3568_data = {
+ .size = 0x80,
+ .word_size = sizeof(u16),
+ .clks = rk3568_otp_clocks,
+ .num_clks = ARRAY_SIZE(rk3568_otp_clocks),
+ .reg_read = rk3568_otp_read,
+};
+
static const struct rockchip_data rk3576_data = {
.size = 0x100,
.read_offset = 0x700,
+ .word_size = sizeof(u32),
.clks = px30_otp_clocks,
.num_clks = ARRAY_SIZE(px30_otp_clocks),
.reg_read = rk3588_otp_read,
@@ -289,6 +373,7 @@ static const char * const rk3588_otp_clocks[] = {
static const struct rockchip_data rk3588_data = {
.size = 0x400,
.read_offset = 0xc00,
+ .word_size = sizeof(u32),
.clks = rk3588_otp_clocks,
.num_clks = ARRAY_SIZE(rk3588_otp_clocks),
.reg_read = rk3588_otp_read,
@@ -304,6 +389,18 @@ static const struct of_device_id rockchip_otp_match[] = {
.data = &px30_data,
},
{
+ .compatible = "rockchip,rk3528-otp",
+ .data = &rk3528_data,
+ },
+ {
+ .compatible = "rockchip,rk3562-otp",
+ .data = &rk3568_data,
+ },
+ {
+ .compatible = "rockchip,rk3568-otp",
+ .data = &rk3568_data,
+ },
+ {
.compatible = "rockchip,rk3576-otp",
.data = &rk3576_data,
},
diff --git a/drivers/parport/TODO-parport b/drivers/parport/TODO-parport
index 089b14ee446f..661a5ab91c0a 100644
--- a/drivers/parport/TODO-parport
+++ b/drivers/parport/TODO-parport
@@ -13,7 +13,7 @@ Things to be done.
bits when they have something to say. We should read out and deal
with (maybe just log) whatever the printer wants to tell the world.
-3. Support more hardware (eg m68k, Sun bpp).
+3. Support more hardware (eg m68k).
4. A better PLIP (make use of bidirectional/ECP/EPP ports).
diff --git a/drivers/pps/generators/pps_gen.c b/drivers/pps/generators/pps_gen.c
index 7143c003366c..5e207c75e340 100644
--- a/drivers/pps/generators/pps_gen.c
+++ b/drivers/pps/generators/pps_gen.c
@@ -26,7 +26,10 @@
*/
static dev_t pps_gen_devt;
-static struct class *pps_gen_class;
+static const struct class pps_gen_class = {
+ .name = "pps-gen",
+ .dev_groups = pps_gen_groups
+};
static DEFINE_IDA(pps_gen_ida);
@@ -183,7 +186,7 @@ static int pps_gen_register_cdev(struct pps_gen_device *pps_gen)
MAJOR(pps_gen_devt), pps_gen->id);
goto free_ida;
}
- pps_gen->dev = device_create(pps_gen_class, pps_gen->info->parent, devt,
+ pps_gen->dev = device_create(&pps_gen_class, pps_gen->info->parent, devt,
pps_gen, "pps-gen%d", pps_gen->id);
if (IS_ERR(pps_gen->dev)) {
err = PTR_ERR(pps_gen->dev);
@@ -207,7 +210,7 @@ free_ida:
static void pps_gen_unregister_cdev(struct pps_gen_device *pps_gen)
{
pr_debug("unregistering pps-gen%d\n", pps_gen->id);
- device_destroy(pps_gen_class, pps_gen->dev->devt);
+ device_destroy(&pps_gen_class, pps_gen->dev->devt);
}
/*
@@ -307,7 +310,7 @@ EXPORT_SYMBOL(pps_gen_event);
static void __exit pps_gen_exit(void)
{
- class_destroy(pps_gen_class);
+ class_unregister(&pps_gen_class);
unregister_chrdev_region(pps_gen_devt, PPS_GEN_MAX_SOURCES);
}
@@ -315,12 +318,11 @@ static int __init pps_gen_init(void)
{
int err;
- pps_gen_class = class_create("pps-gen");
- if (IS_ERR(pps_gen_class)) {
- pr_err("failed to allocate class\n");
- return PTR_ERR(pps_gen_class);
+ err = class_register(&pps_gen_class);
+ if (err) {
+ pr_err("failed to register class\n");
+ return err;
}
- pps_gen_class->dev_groups = pps_gen_groups;
err = alloc_chrdev_region(&pps_gen_devt, 0,
PPS_GEN_MAX_SOURCES, "pps-gen");
@@ -332,7 +334,7 @@ static int __init pps_gen_init(void)
return 0;
remove_class:
- class_destroy(pps_gen_class);
+ class_unregister(&pps_gen_class);
return err;
}
diff --git a/drivers/pps/pps.c b/drivers/pps/pps.c
index c6b8b6478276..de1122bb69ea 100644
--- a/drivers/pps/pps.c
+++ b/drivers/pps/pps.c
@@ -26,7 +26,10 @@
*/
static int pps_major;
-static struct class *pps_class;
+static const struct class pps_class = {
+ .name = "pps",
+ .dev_groups = pps_groups
+};
static DEFINE_MUTEX(pps_idr_lock);
static DEFINE_IDR(pps_idr);
@@ -379,7 +382,7 @@ int pps_register_cdev(struct pps_device *pps)
}
pps->id = err;
- pps->dev.class = pps_class;
+ pps->dev.class = &pps_class;
pps->dev.parent = pps->info.dev;
pps->dev.devt = MKDEV(pps_major, pps->id);
dev_set_drvdata(&pps->dev, pps);
@@ -408,7 +411,7 @@ void pps_unregister_cdev(struct pps_device *pps)
{
pr_debug("unregistering pps%d\n", pps->id);
pps->lookup_cookie = NULL;
- device_destroy(pps_class, pps->dev.devt);
+ device_destroy(&pps_class, pps->dev.devt);
/* Now we can release the ID for re-use */
mutex_lock(&pps_idr_lock);
@@ -460,18 +463,19 @@ EXPORT_SYMBOL(pps_lookup_dev);
static void __exit pps_exit(void)
{
- class_destroy(pps_class);
+ class_unregister(&pps_class);
__unregister_chrdev(pps_major, 0, PPS_MAX_SOURCES, "pps");
}
static int __init pps_init(void)
{
- pps_class = class_create("pps");
- if (IS_ERR(pps_class)) {
- pr_err("failed to allocate class\n");
- return PTR_ERR(pps_class);
+ int err;
+
+ err = class_register(&pps_class);
+ if (err) {
+ pr_err("failed to register class\n");
+ return err;
}
- pps_class->dev_groups = pps_groups;
pps_major = __register_chrdev(0, 0, PPS_MAX_SOURCES, "pps",
&pps_cdev_fops);
@@ -487,7 +491,7 @@ static int __init pps_init(void)
return 0;
remove_class:
- class_destroy(pps_class);
+ class_unregister(&pps_class);
return pps_major;
}
diff --git a/drivers/staging/iio/adc/ad7816.c b/drivers/staging/iio/adc/ad7816.c
index 172acf135f3b..0e32a2295990 100644
--- a/drivers/staging/iio/adc/ad7816.c
+++ b/drivers/staging/iio/adc/ad7816.c
@@ -124,8 +124,8 @@ static ssize_t ad7816_show_mode(struct device *dev,
struct ad7816_chip_info *chip = iio_priv(indio_dev);
if (chip->mode)
- return sprintf(buf, "power-save\n");
- return sprintf(buf, "full\n");
+ return sysfs_emit(buf, "power-save\n");
+ return sysfs_emit(buf, "full\n");
}
static ssize_t ad7816_store_mode(struct device *dev,
@@ -156,7 +156,7 @@ static ssize_t ad7816_show_available_modes(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- return sprintf(buf, "full\npower-save\n");
+ return sysfs_emit(buf, "full\npower-save\n");
}
static IIO_DEVICE_ATTR(available_modes, 0444, ad7816_show_available_modes,
@@ -169,7 +169,7 @@ static ssize_t ad7816_show_channel(struct device *dev,
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ad7816_chip_info *chip = iio_priv(indio_dev);
- return sprintf(buf, "%d\n", chip->channel_id);
+ return sysfs_emit(buf, "%d\n", chip->channel_id);
}
static ssize_t ad7816_store_channel(struct device *dev,
@@ -231,9 +231,9 @@ static ssize_t ad7816_show_value(struct device *dev,
data &= AD7816_TEMP_FLOAT_MASK;
if (value < 0)
data = BIT(AD7816_TEMP_FLOAT_OFFSET) - data;
- return sprintf(buf, "%d.%.2d\n", value, data * 25);
+ return sysfs_emit(buf, "%d.%.2d\n", value, data * 25);
}
- return sprintf(buf, "%u\n", data);
+ return sysfs_emit(buf, "%u\n", data);
}
static IIO_DEVICE_ATTR(value, 0444, ad7816_show_value, NULL, 0);
@@ -281,9 +281,9 @@ static ssize_t ad7816_show_oti(struct device *dev,
value = AD7816_BOUND_VALUE_MIN +
(chip->oti_data[chip->channel_id] -
AD7816_BOUND_VALUE_BASE);
- return sprintf(buf, "%d\n", value);
+ return sysfs_emit(buf, "%d\n", value);
}
- return sprintf(buf, "%u\n", chip->oti_data[chip->channel_id]);
+ return sysfs_emit(buf, "%u\n", chip->oti_data[chip->channel_id]);
}
static inline ssize_t ad7816_set_oti(struct device *dev,
diff --git a/drivers/staging/iio/frequency/ad9834.c b/drivers/staging/iio/frequency/ad9834.c
index d339d5e8e043..bdb2580e29bf 100644
--- a/drivers/staging/iio/frequency/ad9834.c
+++ b/drivers/staging/iio/frequency/ad9834.c
@@ -281,16 +281,12 @@ ssize_t ad9834_show_out0_wavetype_available(struct device *dev,
{
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ad9834_state *st = iio_priv(indio_dev);
- char *str;
if (st->devid == ID_AD9833 || st->devid == ID_AD9837)
- str = "sine triangle square";
- else if (st->control & AD9834_OPBITEN)
- str = "sine";
- else
- str = "sine triangle";
-
- return sprintf(buf, "%s\n", str);
+ return sysfs_emit(buf, "sine triangle square\n");
+ if (st->control & AD9834_OPBITEN)
+ return sysfs_emit(buf, "sine\n");
+ return sysfs_emit(buf, "sine triangle\n");
}
static IIO_DEVICE_ATTR(out_altvoltage0_out0_wavetype_available, 0444,
@@ -303,14 +299,10 @@ ssize_t ad9834_show_out1_wavetype_available(struct device *dev,
{
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ad9834_state *st = iio_priv(indio_dev);
- char *str;
if (st->control & AD9834_MODE)
- str = "";
- else
- str = "square";
-
- return sprintf(buf, "%s\n", str);
+ return sysfs_emit(buf, "\n");
+ return sysfs_emit(buf, "square\n");
}
static IIO_DEVICE_ATTR(out_altvoltage0_out1_wavetype_available, 0444,
diff --git a/drivers/staging/iio/impedance-analyzer/ad5933.c b/drivers/staging/iio/impedance-analyzer/ad5933.c
index 85a4223295cd..dde2ec9d1f6a 100644
--- a/drivers/staging/iio/impedance-analyzer/ad5933.c
+++ b/drivers/staging/iio/impedance-analyzer/ad5933.c
@@ -5,6 +5,7 @@
* Copyright 2011 Analog Devices Inc.
*/
+#include <linux/bits.h>
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/device.h>
@@ -194,8 +195,7 @@ static int ad5933_set_freq(struct ad5933_state *st,
u8 d8[4];
} dat;
- freqreg = (u64)freq * (u64)(1 << 27);
- do_div(freqreg, st->mclk_hz / 4);
+ freqreg = div64_ul(BIT_ULL(27) * freq, st->mclk_hz / 4);
switch (reg) {
case AD5933_REG_FREQ_START:
@@ -285,7 +285,7 @@ static ssize_t ad5933_show_frequency(struct device *dev,
freqreg = (u64)freqreg * (u64)(st->mclk_hz / 4);
do_div(freqreg, BIT(27));
- return sprintf(buf, "%d\n", (int)freqreg);
+ return sysfs_emit(buf, "%llu\n", freqreg);
}
static ssize_t ad5933_store_frequency(struct device *dev,
@@ -338,27 +338,27 @@ static ssize_t ad5933_show(struct device *dev,
mutex_lock(&st->lock);
switch ((u32)this_attr->address) {
case AD5933_OUT_RANGE:
- len = sprintf(buf, "%u\n",
- st->range_avail[(st->ctrl_hb >> 1) & 0x3]);
+ len = sysfs_emit(buf, "%u\n",
+ st->range_avail[(st->ctrl_hb >> 1) & 0x3]);
break;
case AD5933_OUT_RANGE_AVAIL:
- len = sprintf(buf, "%u %u %u %u\n", st->range_avail[0],
- st->range_avail[3], st->range_avail[2],
- st->range_avail[1]);
+ len = sysfs_emit(buf, "%u %u %u %u\n", st->range_avail[0],
+ st->range_avail[3], st->range_avail[2],
+ st->range_avail[1]);
break;
case AD5933_OUT_SETTLING_CYCLES:
- len = sprintf(buf, "%d\n", st->settling_cycles);
+ len = sysfs_emit(buf, "%d\n", st->settling_cycles);
break;
case AD5933_IN_PGA_GAIN:
- len = sprintf(buf, "%s\n",
- (st->ctrl_hb & AD5933_CTRL_PGA_GAIN_1) ?
- "1" : "0.2");
+ len = sysfs_emit(buf, "%s\n",
+ (st->ctrl_hb & AD5933_CTRL_PGA_GAIN_1) ?
+ "1" : "0.2");
break;
case AD5933_IN_PGA_GAIN_AVAIL:
- len = sprintf(buf, "1 0.2\n");
+ len = sysfs_emit(buf, "1 0.2\n");
break;
case AD5933_FREQ_POINTS:
- len = sprintf(buf, "%d\n", st->freq_points);
+ len = sysfs_emit(buf, "%d\n", st->freq_points);
break;
default:
ret = -EINVAL;
diff --git a/drivers/w1/masters/ds2490.c b/drivers/w1/masters/ds2490.c
index 35e75d07ef5d..aa1f57f74397 100644
--- a/drivers/w1/masters/ds2490.c
+++ b/drivers/w1/masters/ds2490.c
@@ -1022,11 +1022,8 @@ static int ds_probe(struct usb_interface *intf,
if (!dev)
return -ENOMEM;
- dev->udev = usb_get_dev(udev);
- if (!dev->udev) {
- err = -ENOMEM;
- goto err_out_free;
- }
+ dev->udev = udev;
+
memset(dev->ep, 0, sizeof(dev->ep));
usb_set_intfdata(intf, dev);
@@ -1085,9 +1082,8 @@ static int ds_probe(struct usb_interface *intf,
err_out_clear:
usb_set_intfdata(intf, NULL);
- usb_put_dev(dev->udev);
-err_out_free:
kfree(dev);
+
return err;
}
@@ -1107,7 +1103,6 @@ static void ds_disconnect(struct usb_interface *intf)
usb_set_intfdata(intf, NULL);
- usb_put_dev(dev->udev);
kfree(dev);
}
diff --git a/include/drm/intel/intel_lb_mei_interface.h b/include/drm/intel/intel_lb_mei_interface.h
index 0850738a30fc..7f533ac7cc10 100644
--- a/include/drm/intel/intel_lb_mei_interface.h
+++ b/include/drm/intel/intel_lb_mei_interface.h
@@ -6,6 +6,7 @@
#ifndef _INTEL_LB_MEI_INTERFACE_H_
#define _INTEL_LB_MEI_INTERFACE_H_
+#include <linux/bits.h>
#include <linux/types.h>
struct device;
@@ -21,9 +22,11 @@ struct device;
/**
* enum intel_lb_type - enum to determine late binding payload type
* @INTEL_LB_TYPE_FAN_CONTROL: Fan controller configuration
+ * @INTEL_LB_TYPE_OCODE: Ocode firmware
*/
enum intel_lb_type {
INTEL_LB_TYPE_FAN_CONTROL = 1,
+ INTEL_LB_TYPE_OCODE = 3,
};
/**
@@ -36,16 +39,46 @@ enum intel_lb_type {
* @INTEL_LB_STATUS_INVALID_SIGNATURE: Payload has an invalid or untrusted signature
* @INTEL_LB_STATUS_INVALID_PAYLOAD: Payload contents are not accepted by firmware
* @INTEL_LB_STATUS_TIMEOUT: Operation timed out before completion
+ * @INTEL_LB_STATUS_BUFFER_TOO_SMALL: Buffer provided is smaller when expected
+ * @INTEL_LB_STATUS_INTERNAL_ERROR: Internal firmware error
+ * @INTEL_LB_STATUS_INVALID_FPT_TABLE: Invalid firmware format table
+ * @INTEL_LB_STATUS_SIGNED_PAYLOAD_VERIFICATION_ERROR: Error in signature verification
+ * @INTEL_LB_STATUS_SIGNED_PAYLOAD_INVALID_CPD: Invalid CPD
+ * @INTEL_LB_STATUS_SIGNED_PAYLOAD_FW_VERSION_MISMATCH: Firmware version mismatch
+ * @INTEL_LB_STATUS_SIGNED_PAYLOAD_INVALID_MANIFEST: Invalid firmware manifest
+ * @INTEL_LB_STATUS_SIGNED_PAYLOAD_INVALID_HASH: Wrong hash in signature
+ * @INTEL_LB_STATUS_SIGNED_PAYLOAD_BINDING_TYPE_MISMATCH: Wrong firmware type provided
+ * @INTEL_LB_STATUS_SIGNED_PAYLOAD_HANDLE_SVN_FAILED: SVN check failed
+ * @INTEL_LB_STATUS_DESTINATION_MBOX_FAILURE: Failed to send datat to destination
+ * @INTEL_LB_STATUS_MISSING_LOADING_PATCH: No loading patch found
+ * @INTEL_LB_STATUS_INVALID_COMMAND: Invalid command number
+ * @INTEL_LB_STATUS_INVALID_HECI_HEADER: Invalid transport header
+ * @INTEL_LB_STATUS_IP_ERROR_START: Base for internal errors
*/
enum intel_lb_status {
- INTEL_LB_STATUS_SUCCESS = 0,
- INTEL_LB_STATUS_4ID_MISMATCH = 1,
- INTEL_LB_STATUS_ARB_FAILURE = 2,
- INTEL_LB_STATUS_GENERAL_ERROR = 3,
- INTEL_LB_STATUS_INVALID_PARAMS = 4,
- INTEL_LB_STATUS_INVALID_SIGNATURE = 5,
- INTEL_LB_STATUS_INVALID_PAYLOAD = 6,
- INTEL_LB_STATUS_TIMEOUT = 7,
+ INTEL_LB_STATUS_SUCCESS = 0,
+ INTEL_LB_STATUS_4ID_MISMATCH = 1,
+ INTEL_LB_STATUS_ARB_FAILURE = 2,
+ INTEL_LB_STATUS_GENERAL_ERROR = 3,
+ INTEL_LB_STATUS_INVALID_PARAMS = 4,
+ INTEL_LB_STATUS_INVALID_SIGNATURE = 5,
+ INTEL_LB_STATUS_INVALID_PAYLOAD = 6,
+ INTEL_LB_STATUS_TIMEOUT = 7,
+ INTEL_LB_STATUS_BUFFER_TOO_SMALL = 8,
+ INTEL_LB_STATUS_INTERNAL_ERROR = 9,
+ INTEL_LB_STATUS_INVALID_FPT_TABLE = 10,
+ INTEL_LB_STATUS_SIGNED_PAYLOAD_VERIFICATION_ERROR = 11,
+ INTEL_LB_STATUS_SIGNED_PAYLOAD_INVALID_CPD = 12,
+ INTEL_LB_STATUS_SIGNED_PAYLOAD_FW_VERSION_MISMATCH = 13,
+ INTEL_LB_STATUS_SIGNED_PAYLOAD_INVALID_MANIFEST = 14,
+ INTEL_LB_STATUS_SIGNED_PAYLOAD_INVALID_HASH = 15,
+ INTEL_LB_STATUS_SIGNED_PAYLOAD_BINDING_TYPE_MISMATCH = 16,
+ INTEL_LB_STATUS_SIGNED_PAYLOAD_HANDLE_SVN_FAILED = 17,
+ INTEL_LB_STATUS_DESTINATION_MBOX_FAILURE = 18,
+ INTEL_LB_STATUS_MISSING_LOADING_PATCH = 19,
+ INTEL_LB_STATUS_INVALID_COMMAND = 20,
+ INTEL_LB_STATUS_INVALID_HECI_HEADER = 21,
+ INTEL_LB_STATUS_IP_ERROR_START = BIT(31),
};
/**
@@ -62,7 +95,7 @@ struct intel_lb_component_ops {
* @payload_size: Payload buffer size in bytes
*
* Return: 0 success, negative errno value on transport failure,
- * positive status returned by firmware
+ * positive error status returned by firmware
*/
int (*push_payload)(struct device *dev, u32 type, u32 flags,
const void *payload, size_t payload_size);
diff --git a/include/linux/comedi/comedi_isadma.h b/include/linux/comedi/comedi_isadma.h
index 9d2b12db7e6e..7514ce222fa6 100644
--- a/include/linux/comedi/comedi_isadma.h
+++ b/include/linux/comedi/comedi_isadma.h
@@ -48,11 +48,11 @@ struct comedi_isadma_desc {
*/
struct comedi_isadma {
struct device *dev;
- struct comedi_isadma_desc *desc;
int n_desc;
int cur_dma;
unsigned int chan;
unsigned int chan2;
+ struct comedi_isadma_desc desc[] __counted_by(n_desc);
};
#if IS_ENABLED(CONFIG_ISA_DMA_API)
diff --git a/include/linux/comedi/comedidev.h b/include/linux/comedi/comedidev.h
index 35fdc41845ce..577a08f37aee 100644
--- a/include/linux/comedi/comedidev.h
+++ b/include/linux/comedi/comedidev.h
@@ -1026,10 +1026,55 @@ int comedi_load_firmware(struct comedi_device *dev, struct device *hw_dev,
unsigned long context),
unsigned long context);
-int __comedi_request_region(struct comedi_device *dev,
- unsigned long start, unsigned long len);
-int comedi_request_region(struct comedi_device *dev,
- unsigned long start, unsigned long len);
+int __comedi_check_request_region(struct comedi_device *dev,
+ unsigned long start, unsigned long len,
+ unsigned long minstart, unsigned long maxend,
+ unsigned long minalign);
+int comedi_check_request_region(struct comedi_device *dev,
+ unsigned long start, unsigned long len,
+ unsigned long minstart, unsigned long maxend,
+ unsigned long minalign);
+
+/**
+ * __comedi_request_region() - Request an I/O region for a legacy driver
+ * @dev: COMEDI device.
+ * @start: Base address of the I/O region.
+ * @len: Length of the I/O region.
+ *
+ * Requests the specified I/O port region which must start at a non-zero
+ * address.
+ *
+ * Returns 0 on success, -EINVAL if @start is 0, or -EIO if the request
+ * fails.
+ */
+static inline int __comedi_request_region(struct comedi_device *dev,
+ unsigned long start,
+ unsigned long len)
+{
+ return __comedi_check_request_region(dev, start, len, 0, ~0ul, 1);
+}
+
+/**
+ * comedi_request_region() - Request an I/O region for a legacy driver
+ * @dev: COMEDI device.
+ * @start: Base address of the I/O region.
+ * @len: Length of the I/O region.
+ *
+ * Requests the specified I/O port region which must start at a non-zero
+ * address.
+ *
+ * On success, @dev->iobase is set to the base address of the region and
+ * @dev->iolen is set to its length.
+ *
+ * Returns 0 on success, -EINVAL if @start is 0, or -EIO if the request
+ * fails.
+ */
+static inline int comedi_request_region(struct comedi_device *dev,
+ unsigned long start, unsigned long len)
+{
+ return comedi_check_request_region(dev, start, len, 0, ~0ul, 1);
+}
+
void comedi_legacy_detach(struct comedi_device *dev);
int comedi_auto_config(struct device *hardware_device,
diff --git a/include/linux/coresight.h b/include/linux/coresight.h
index 2b48be97fcd0..2131febebee9 100644
--- a/include/linux/coresight.h
+++ b/include/linux/coresight.h
@@ -306,24 +306,19 @@ struct coresight_device {
* coresight_dev_list - Mapping for devices to "name" index for device
* names.
*
+ * @node: Node on the global device index list.
* @nr_idx: Number of entries already allocated.
* @pfx: Prefix pattern for device name.
* @fwnode_list: Array of fwnode_handles associated with each allocated
* index, upto nr_idx entries.
*/
struct coresight_dev_list {
+ struct list_head node;
int nr_idx;
- const char *pfx;
+ char *pfx;
struct fwnode_handle **fwnode_list;
};
-#define DEFINE_CORESIGHT_DEVLIST(var, dev_pfx) \
-static struct coresight_dev_list (var) = { \
- .pfx = dev_pfx, \
- .nr_idx = 0, \
- .fwnode_list = NULL, \
-}
-
#define to_coresight_device(d) container_of(d, struct coresight_device, dev)
/**
@@ -663,8 +658,7 @@ void coresight_clear_self_claim_tag(struct csdev_access *csa);
void coresight_clear_self_claim_tag_unlocked(struct csdev_access *csa);
void coresight_disclaim_device(struct coresight_device *csdev);
void coresight_disclaim_device_unlocked(struct coresight_device *csdev);
-char *coresight_alloc_device_name(struct coresight_dev_list *devs,
- struct device *dev);
+char *coresight_alloc_device_name(const char *prefix, struct device *dev);
bool coresight_loses_context_with_cpu(struct device *dev);
diff --git a/include/linux/iio/adc/qcom-adc5-gen3-common.h b/include/linux/iio/adc/qcom-adc5-gen3-common.h
new file mode 100644
index 000000000000..6303eaa6640b
--- /dev/null
+++ b/include/linux/iio/adc/qcom-adc5-gen3-common.h
@@ -0,0 +1,211 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
+ *
+ * Code used in the main and auxiliary Qualcomm PMIC voltage ADCs
+ * of type ADC5 Gen3.
+ */
+
+#ifndef QCOM_ADC5_GEN3_COMMON_H
+#define QCOM_ADC5_GEN3_COMMON_H
+
+#include <linux/auxiliary_bus.h>
+#include <linux/bitfield.h>
+#include <linux/bits.h>
+#include <linux/device.h>
+#include <linux/iio/adc/qcom-vadc-common.h>
+#include <linux/regmap.h>
+#include <linux/types.h>
+
+#define ADC5_GEN3_HS 0x45
+#define ADC5_GEN3_HS_BUSY BIT(7)
+#define ADC5_GEN3_HS_READY BIT(0)
+
+#define ADC5_GEN3_STATUS1 0x46
+#define ADC5_GEN3_STATUS1_CONV_FAULT BIT(7)
+#define ADC5_GEN3_STATUS1_THR_CROSS BIT(6)
+#define ADC5_GEN3_STATUS1_EOC BIT(0)
+
+#define ADC5_GEN3_TM_EN_STS 0x47
+#define ADC5_GEN3_TM_HIGH_STS 0x48
+#define ADC5_GEN3_TM_LOW_STS 0x49
+
+#define ADC5_GEN3_EOC_STS 0x4a
+#define ADC5_GEN3_EOC_CHAN_0 BIT(0)
+
+#define ADC5_GEN3_EOC_CLR 0x4b
+#define ADC5_GEN3_TM_HIGH_STS_CLR 0x4c
+#define ADC5_GEN3_TM_LOW_STS_CLR 0x4d
+#define ADC5_GEN3_CONV_ERR_CLR 0x4e
+#define ADC5_GEN3_CONV_ERR_CLR_REQ BIT(0)
+
+#define ADC5_GEN3_SID 0x4f
+#define ADC5_GEN3_SID_MASK GENMASK(3, 0)
+
+#define ADC5_GEN3_PERPH_CH 0x50
+#define ADC5_GEN3_CHAN_CONV_REQ BIT(7)
+
+#define ADC5_GEN3_TIMER_SEL 0x51
+#define ADC5_GEN3_TIME_IMMEDIATE 0x1
+
+#define ADC5_GEN3_DIG_PARAM 0x52
+#define ADC5_GEN3_DIG_PARAM_CAL_SEL_MASK GENMASK(5, 4)
+#define ADC5_GEN3_DIG_PARAM_DEC_RATIO_SEL_MASK GENMASK(3, 2)
+
+#define ADC5_GEN3_FAST_AVG 0x53
+#define ADC5_GEN3_FAST_AVG_CTL_EN BIT(7)
+#define ADC5_GEN3_FAST_AVG_CTL_SAMPLES_MASK GENMASK(2, 0)
+
+#define ADC5_GEN3_ADC_CH_SEL_CTL 0x54
+#define ADC5_GEN3_DELAY_CTL 0x55
+#define ADC5_GEN3_HW_SETTLE_DELAY_MASK GENMASK(3, 0)
+
+#define ADC5_GEN3_CH_EN 0x56
+#define ADC5_GEN3_HIGH_THR_INT_EN BIT(1)
+#define ADC5_GEN3_LOW_THR_INT_EN BIT(0)
+
+#define ADC5_GEN3_LOW_THR0 0x57
+#define ADC5_GEN3_LOW_THR1 0x58
+#define ADC5_GEN3_HIGH_THR0 0x59
+#define ADC5_GEN3_HIGH_THR1 0x5a
+
+#define ADC5_GEN3_CH_DATA0(channel) (0x5c + (channel) * 2)
+#define ADC5_GEN3_CH_DATA1(channel) (0x5d + (channel) * 2)
+
+#define ADC5_GEN3_CONV_REQ 0xe5
+#define ADC5_GEN3_CONV_REQ_REQ BIT(0)
+
+#define ADC5_GEN3_VIRTUAL_SID_MASK GENMASK(15, 8)
+#define ADC5_GEN3_CHANNEL_MASK GENMASK(7, 0)
+#define ADC5_GEN3_V_CHAN(x) \
+ (FIELD_PREP(ADC5_GEN3_VIRTUAL_SID_MASK, (x).sid) | (x).channel)
+
+/* ADC channels for PMIC5 Gen3 */
+#define ADC5_GEN3_REF_GND 0x00
+#define ADC5_GEN3_1P25VREF 0x01
+#define ADC5_GEN3_DIE_TEMP 0x03
+#define ADC5_GEN3_USB_SNS_V_16 0x11
+#define ADC5_GEN3_VIN_DIV16_MUX 0x12
+#define ADC5_GEN3_VPH_PWR 0x8e
+#define ADC5_GEN3_VBAT_SNS_QBG 0x8f
+/* 100k pull-up channels */
+#define ADC5_GEN3_AMUX1_THM_100K_PU 0x44
+#define ADC5_GEN3_AMUX2_THM_100K_PU 0x45
+#define ADC5_GEN3_AMUX3_THM_100K_PU 0x46
+#define ADC5_GEN3_AMUX4_THM_100K_PU 0x47
+#define ADC5_GEN3_AMUX5_THM_100K_PU 0x48
+#define ADC5_GEN3_AMUX6_THM_100K_PU 0x49
+#define ADC5_GEN3_AMUX1_GPIO_100K_PU 0x4a
+#define ADC5_GEN3_AMUX2_GPIO_100K_PU 0x4b
+#define ADC5_GEN3_AMUX3_GPIO_100K_PU 0x4c
+#define ADC5_GEN3_AMUX4_GPIO_100K_PU 0x4d
+
+#define ADC5_MAX_CHANNEL 0xc0
+
+enum adc5_cal_method {
+ ADC5_NO_CAL = 0,
+ ADC5_RATIOMETRIC_CAL,
+ ADC5_ABSOLUTE_CAL,
+};
+
+enum adc5_time_select {
+ MEAS_INT_DISABLE = 0,
+ MEAS_INT_IMMEDIATE,
+ MEAS_INT_50MS,
+ MEAS_INT_100MS,
+ MEAS_INT_1S,
+ MEAS_INT_NONE,
+};
+
+/**
+ * struct adc5_sdam_data - data per SDAM allocated for adc usage
+ * @base_addr: base address for the ADC SDAM peripheral.
+ * @irq_name: ADC IRQ name.
+ * @irq: ADC IRQ number.
+ */
+struct adc5_sdam_data {
+ u16 base_addr;
+ const char *irq_name;
+ int irq;
+};
+
+/**
+ * struct adc5_device_data - Top-level ADC device data
+ * @regmap: ADC peripheral register map field.
+ * @base: array of SDAM data.
+ * @num_sdams: number of ADC SDAM peripherals.
+ */
+struct adc5_device_data {
+ struct regmap *regmap;
+ struct adc5_sdam_data *base;
+ int num_sdams;
+};
+
+/**
+ * struct adc5_channel_common_prop - ADC channel properties (common to ADC and TM).
+ * @channel: channel number, refer to the channel list.
+ * @cal_method: calibration method.
+ * @decimation: sampling rate supported for the channel.
+ * @sid: ID of PMIC owning the channel.
+ * @label: Channel name used in device tree.
+ * @prescale: channel scaling performed on the input signal.
+ * @hw_settle_time_us: the time between AMUX being configured and the
+ * start of conversion in uS.
+ * @avg_samples: ability to provide single result from the ADC
+ * that is an average of multiple measurements.
+ * @scale_fn_type: Represents the scaling function to convert voltage
+ * physical units desired by the client for the channel.
+ */
+struct adc5_channel_common_prop {
+ unsigned int channel;
+ enum adc5_cal_method cal_method;
+ unsigned int decimation;
+ unsigned int sid;
+ const char *label;
+ unsigned int prescale;
+ unsigned int hw_settle_time_us;
+ unsigned int avg_samples;
+ enum vadc_scale_fn_type scale_fn_type;
+};
+
+/**
+ * struct tm5_aux_dev_wrapper - wrapper structure around TM auxiliary device
+ * @aux_dev: TM auxiliary device structure.
+ * @dev_data: Top-level ADC device data.
+ * @tm_props: Array of common ADC channel properties for TM channels.
+ * @n_tm_channels: number of TM channels.
+ */
+struct tm5_aux_dev_wrapper {
+ struct auxiliary_device aux_dev;
+ struct adc5_device_data *dev_data;
+ struct adc5_channel_common_prop *tm_props;
+ unsigned int n_tm_channels;
+};
+
+int adc5_gen3_read(struct adc5_device_data *adc, unsigned int sdam_index,
+ u16 offset, u8 *data, int len);
+
+int adc5_gen3_write(struct adc5_device_data *adc, unsigned int sdam_index,
+ u16 offset, u8 *data, int len);
+
+int adc5_gen3_poll_wait_hs(struct adc5_device_data *adc,
+ unsigned int sdam_index);
+
+void adc5_gen3_update_dig_param(struct adc5_channel_common_prop *prop,
+ u8 *data);
+
+int adc5_gen3_status_clear(struct adc5_device_data *adc,
+ int sdam_index, u16 offset, u8 *val, int len);
+
+void adc5_gen3_mutex_lock(struct device *dev);
+void adc5_gen3_mutex_unlock(struct device *dev);
+int adc5_gen3_get_scaled_reading(struct device *dev,
+ struct adc5_channel_common_prop *common_props,
+ int *val);
+int adc5_gen3_therm_code_to_temp(struct device *dev,
+ struct adc5_channel_common_prop *common_props,
+ u16 code, int *val);
+void adc5_gen3_register_tm_event_notifier(struct device *dev,
+ void (*handler)(struct auxiliary_device *));
+
+#endif /* QCOM_ADC5_GEN3_COMMON_H */
diff --git a/include/linux/iio/backend.h b/include/linux/iio/backend.h
index 7f815f3fed6a..4d15c2a9802c 100644
--- a/include/linux/iio/backend.h
+++ b/include/linux/iio/backend.h
@@ -85,6 +85,27 @@ enum iio_backend_filter_type {
};
/**
+ * enum iio_backend_capabilities - Backend capabilities
+ * Backend capabilities can be used by frontends to check if a given
+ * functionality is supported by the backend. This is useful for frontend
+ * devices which are expected to work with alternative backend
+ * implementations. Capabilities are loosely coupled with operations,
+ * meaning that a capability requires certain operations to be implemented
+ * by the backend. A capability might be mapped to a single operation or
+ * multiple operations.
+ *
+ * @IIO_BACKEND_CAP_CALIBRATION: Backend supports digital interface
+ * calibration. Calibration procedure is device specific.
+ * @IIO_BACKEND_CAP_BUFFER: Support for IIO buffer interface.
+ * @IIO_BACKEND_CAP_ENABLE: Backend can be explicitly enabled/disabled.
+ */
+enum iio_backend_capabilities {
+ IIO_BACKEND_CAP_CALIBRATION = BIT(0),
+ IIO_BACKEND_CAP_BUFFER = BIT(1),
+ IIO_BACKEND_CAP_ENABLE = BIT(2),
+};
+
+/**
* struct iio_backend_ops - operations structure for an iio_backend
* @enable: Enable backend.
* @disable: Disable backend.
@@ -179,10 +200,12 @@ struct iio_backend_ops {
* struct iio_backend_info - info structure for an iio_backend
* @name: Backend name.
* @ops: Backend operations.
+ * @caps: Backend capabilities. (bitmask of enum iio_backend_capabilities).
*/
struct iio_backend_info {
const char *name;
const struct iio_backend_ops *ops;
+ u32 caps;
};
int iio_backend_chan_enable(struct iio_backend *back, unsigned int chan);
@@ -235,6 +258,7 @@ int iio_backend_read_raw(struct iio_backend *back,
long mask);
int iio_backend_extend_chan_spec(struct iio_backend *back,
struct iio_chan_spec *chan);
+bool iio_backend_has_caps(struct iio_backend *back, u32 caps);
void *iio_backend_get_priv(const struct iio_backend *conv);
struct iio_backend *devm_iio_backend_get(struct device *dev, const char *name);
struct iio_backend *devm_iio_backend_fwnode_get(struct device *dev,
diff --git a/include/linux/iio/common/st_sensors.h b/include/linux/iio/common/st_sensors.h
index f9ae5cdd884f..1ba496f0fea5 100644
--- a/include/linux/iio/common/st_sensors.h
+++ b/include/linux/iio/common/st_sensors.h
@@ -160,12 +160,12 @@ struct st_sensor_int_drdy {
/**
* struct st_sensor_data_ready_irq - ST sensor device data-ready interrupt
- * struct int1 - data-ready configuration register for INT1 pin.
- * struct int2 - data-ready configuration register for INT2 pin.
+ * @int1: data-ready configuration register for INT1 pin.
+ * @int2: data-ready configuration register for INT2 pin.
* @addr_ihl: address to enable/disable active low on the INT lines.
* @mask_ihl: mask to enable/disable active low on the INT lines.
- * struct stat_drdy - status register of DRDY (data ready) interrupt.
- * struct ig1 - represents the Interrupt Generator 1 of sensors.
+ * @stat_drdy: status register of DRDY (data ready) interrupt.
+ * @ig1: represents the Interrupt Generator 1 of sensors.
* @en_addr: address of the enable ig1 register.
* @en_mask: mask to write the on/off value for enable.
*/
@@ -190,6 +190,7 @@ struct st_sensor_data_ready_irq {
* @wai_addr: The address of WhoAmI register.
* @sensors_supported: List of supported sensors by struct itself.
* @ch: IIO channels for the sensor.
+ * @num_ch: Number of IIO channels in @ch
* @odr: Output data rate register and ODR list available.
* @pw: Power register of the sensor.
* @enable_axis: Enable one or more axis of the sensor.
@@ -228,7 +229,7 @@ struct st_sensor_settings {
* @regmap: Pointer to specific sensor regmap configuration.
* @enabled: Status of the sensor (false->off, true->on).
* @odr: Output data rate of the sensor [Hz].
- * num_data_channels: Number of data channels used in buffer.
+ * @num_data_channels: Number of data channels used in buffer.
* @drdy_int_pin: Redirect DRDY on pin 1 (1) or pin 2 (2).
* @int_pin_open_drain: Set the interrupt/DRDY to open drain.
* @irq: the IRQ number.
diff --git a/include/linux/iio/types.h b/include/linux/iio/types.h
index 34eebad12d2c..4e3099defc1d 100644
--- a/include/linux/iio/types.h
+++ b/include/linux/iio/types.h
@@ -21,6 +21,7 @@ enum iio_event_info {
IIO_EV_INFO_TAP2_MIN_DELAY,
IIO_EV_INFO_RUNNING_PERIOD,
IIO_EV_INFO_RUNNING_COUNT,
+ IIO_EV_INFO_SCALE,
};
#define IIO_VAL_INT 1
diff --git a/include/linux/mei_cl_bus.h b/include/linux/mei_cl_bus.h
index a82755e1fc40..5bdbd9e1d460 100644
--- a/include/linux/mei_cl_bus.h
+++ b/include/linux/mei_cl_bus.h
@@ -112,6 +112,7 @@ int mei_cldev_register_rx_cb(struct mei_cl_device *cldev, mei_cldev_cb_t rx_cb);
int mei_cldev_register_notif_cb(struct mei_cl_device *cldev,
mei_cldev_cb_t notif_cb);
+const uuid_le *mei_cldev_uuid(const struct mei_cl_device *cldev);
u8 mei_cldev_ver(const struct mei_cl_device *cldev);
size_t mei_cldev_mtu(const struct mei_cl_device *cldev);
diff --git a/include/linux/mhi.h b/include/linux/mhi.h
index 88ccb3e14f48..fb3ba639f4f8 100644
--- a/include/linux/mhi.h
+++ b/include/linux/mhi.h
@@ -86,16 +86,32 @@ enum mhi_ch_type {
};
/**
+ * struct mhi_buf - MHI Buffer description
+ * @buf: Virtual address of the buffer
+ * @name: Buffer label. For offload channel, configurations name must be:
+ * ECA - Event context array data
+ * CCA - Channel context array data
+ * @dma_addr: IOMMU address of the buffer
+ * @len: # of bytes
+ */
+struct mhi_buf {
+ void *buf;
+ const char *name;
+ dma_addr_t dma_addr;
+ size_t len;
+};
+
+/**
* struct image_info - Firmware and RDDM table
* @mhi_buf: Buffer for firmware and RDDM table
* @entries: # of entries in table
*/
struct image_info {
- struct mhi_buf *mhi_buf;
/* private: from internal.h */
struct bhi_vec_entry *bhi_vec;
/* public: */
u32 entries;
+ struct mhi_buf mhi_buf[] __counted_by(entries);
};
/**
@@ -489,22 +505,6 @@ struct mhi_result {
};
/**
- * struct mhi_buf - MHI Buffer description
- * @buf: Virtual address of the buffer
- * @name: Buffer label. For offload channel, configurations name must be:
- * ECA - Event context array data
- * CCA - Channel context array data
- * @dma_addr: IOMMU address of the buffer
- * @len: # of bytes
- */
-struct mhi_buf {
- void *buf;
- const char *name;
- dma_addr_t dma_addr;
- size_t len;
-};
-
-/**
* struct mhi_driver - Structure representing a MHI client driver
* @probe: CB function for client driver probe function
* @remove: CB function for client driver remove function
diff --git a/include/linux/platform_data/apds990x.h b/include/linux/platform_data/apds990x.h
index 94dfbaa365e1..37684f68c04f 100644
--- a/include/linux/platform_data/apds990x.h
+++ b/include/linux/platform_data/apds990x.h
@@ -31,7 +31,6 @@
* itself. If the GA is zero, driver will use uncovered sensor default values
* format: decimal value * APDS_PARAM_SCALE except df which is plain integer.
*/
-#define APDS_PARAM_SCALE 4096
struct apds990x_chip_factors {
int ga;
int cf1;
@@ -40,11 +39,12 @@ struct apds990x_chip_factors {
int irf2;
int df;
};
+#define APDS_PARAM_SCALE 4096
/**
* struct apds990x_platform_data - platform data for apsd990x.c driver
* @cf: chip factor data
- * @pddrive: IR-led driving current
+ * @pdrive: IR-led driving current
* @ppcount: number of IR pulses used for proximity estimation
* @setup_resources: interrupt line setup call back function
* @release_resources: interrupt line release call back function
diff --git a/include/linux/platform_data/tsl2772.h b/include/linux/platform_data/tsl2772.h
index f8ade15a35e2..f042e82b39c3 100644
--- a/include/linux/platform_data/tsl2772.h
+++ b/include/linux/platform_data/tsl2772.h
@@ -61,9 +61,9 @@ struct tsl2772_lux {
* @prox_pulse_count: Number if proximity emitter pulses.
* @prox_max_samples_cal: The number of samples that are taken when performing
* a proximity calibration.
- * @prox_diode Which diode(s) to use for driving the external
+ * @prox_diode: Which diode(s) to use for driving the external
* LED(s) for proximity sensing.
- * @prox_power The amount of power to use for the external LED(s).
+ * @prox_power: The amount of power to use for the external LED(s).
*/
struct tsl2772_settings {
int als_time;
diff --git a/rust/kernel/alloc/kvec.rs b/rust/kernel/alloc/kvec.rs
index ac8d6f763ae8..6438385e4322 100644
--- a/rust/kernel/alloc/kvec.rs
+++ b/rust/kernel/alloc/kvec.rs
@@ -9,7 +9,10 @@ use super::{
};
use crate::{
fmt,
- page::AsPageIter, //
+ page::{
+ AsPageIter,
+ PAGE_SIZE, //
+ },
};
use core::{
borrow::{Borrow, BorrowMut},
@@ -734,6 +737,115 @@ where
self.truncate(num_kept);
}
}
+// TODO: This is a temporary KVVec-specific implementation. It should be replaced with a generic
+// `shrink_to()` for `impl<T, A: Allocator> Vec<T, A>` that uses `A::realloc()` once the
+// underlying allocators properly support shrinking via realloc.
+impl<T> Vec<T, KVmalloc> {
+ /// Shrinks the capacity of the vector with a lower bound.
+ ///
+ /// The capacity will remain at least as large as both the length and the supplied value.
+ /// If the current capacity is less than the lower limit, this is a no-op.
+ ///
+ /// For `kmalloc` allocations, this delegates to `realloc()`, which decides whether
+ /// shrinking is worthwhile. For `vmalloc` allocations, shrinking only occurs if the
+ /// operation would free at least one page of memory, and performs a deep copy since
+ /// `vrealloc` does not yet support in-place shrinking.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// // Allocate enough capacity to span multiple pages.
+ /// let elements_per_page = kernel::page::PAGE_SIZE / core::mem::size_of::<u32>();
+ /// let mut v = KVVec::with_capacity(elements_per_page * 4, GFP_KERNEL)?;
+ /// v.push(1, GFP_KERNEL)?;
+ /// v.push(2, GFP_KERNEL)?;
+ ///
+ /// v.shrink_to(0, GFP_KERNEL)?;
+ /// # Ok::<(), Error>(())
+ /// ```
+ pub fn shrink_to(&mut self, min_capacity: usize, flags: Flags) -> Result<(), AllocError> {
+ let target_cap = core::cmp::max(self.len(), min_capacity);
+
+ if self.capacity() <= target_cap {
+ return Ok(());
+ }
+
+ if Self::is_zst() {
+ return Ok(());
+ }
+
+ // For kmalloc allocations, delegate to realloc() and let the allocator decide
+ // whether shrinking is worthwhile.
+ //
+ // SAFETY: `self.ptr` points to a valid `KVmalloc` allocation.
+ if !unsafe { bindings::is_vmalloc_addr(self.ptr.as_ptr().cast()) } {
+ let new_layout = ArrayLayout::<T>::new(target_cap).map_err(|_| AllocError)?;
+
+ // SAFETY:
+ // - `self.ptr` is valid and was previously allocated with `KVmalloc`.
+ // - `self.layout` matches the `ArrayLayout` of the preceding allocation.
+ let ptr = unsafe {
+ KVmalloc::realloc(
+ Some(self.ptr.cast()),
+ new_layout.into(),
+ self.layout.into(),
+ flags,
+ NumaNode::NO_NODE,
+ )?
+ };
+
+ self.ptr = ptr.cast();
+ self.layout = new_layout;
+ return Ok(());
+ }
+
+ // Only shrink if we would free at least one page.
+ let current_size = self.capacity() * core::mem::size_of::<T>();
+ let target_size = target_cap * core::mem::size_of::<T>();
+ let current_pages = current_size.div_ceil(PAGE_SIZE);
+ let target_pages = target_size.div_ceil(PAGE_SIZE);
+
+ if current_pages <= target_pages {
+ return Ok(());
+ }
+
+ if target_cap == 0 {
+ if !self.layout.is_empty() {
+ // SAFETY:
+ // - `self.ptr` was previously allocated with `KVmalloc`.
+ // - `self.layout` matches the `ArrayLayout` of the preceding allocation.
+ unsafe { KVmalloc::free(self.ptr.cast(), self.layout.into()) };
+ }
+ self.ptr = NonNull::dangling();
+ self.layout = ArrayLayout::empty();
+ return Ok(());
+ }
+
+ // SAFETY: `target_cap <= self.capacity()` and original capacity was valid.
+ let new_layout = unsafe { ArrayLayout::<T>::new_unchecked(target_cap) };
+
+ let new_ptr = KVmalloc::alloc(new_layout.into(), flags, NumaNode::NO_NODE)?;
+
+ // SAFETY:
+ // - `self.as_ptr()` is valid for reads of `self.len()` elements of `T`.
+ // - `new_ptr` is valid for writes of at least `target_cap >= self.len()` elements.
+ // - The two allocations do not overlap since `new_ptr` is freshly allocated.
+ // - Both pointers are properly aligned for `T`.
+ unsafe {
+ ptr::copy_nonoverlapping(self.as_ptr(), new_ptr.as_ptr().cast::<T>(), self.len())
+ };
+
+ // SAFETY:
+ // - `self.ptr` was previously allocated with `KVmalloc`.
+ // - `self.layout` matches the `ArrayLayout` of the preceding allocation.
+ unsafe { KVmalloc::free(self.ptr.cast(), self.layout.into()) };
+
+ self.ptr = new_ptr.cast::<T>();
+ self.layout = new_layout;
+
+ Ok(())
+ }
+}
impl<T: Clone, A: Allocator> Vec<T, A> {
/// Extend the vector by `n` clones of `value`.
@@ -1398,4 +1510,106 @@ mod tests {
func.push_within_capacity(false).unwrap();
}
}
+
+ #[test]
+ fn test_kvvec_shrink_to() {
+ use crate::page::PAGE_SIZE;
+
+ // Create a vector with capacity spanning multiple pages.
+ let mut v = KVVec::<u8>::with_capacity(PAGE_SIZE * 4, GFP_KERNEL).unwrap();
+
+ // Add a few elements.
+ v.push(1, GFP_KERNEL).unwrap();
+ v.push(2, GFP_KERNEL).unwrap();
+ v.push(3, GFP_KERNEL).unwrap();
+
+ let initial_capacity = v.capacity();
+ assert!(initial_capacity >= PAGE_SIZE * 4);
+
+ // Shrink to a capacity that would free at least one page.
+ v.shrink_to(PAGE_SIZE, GFP_KERNEL).unwrap();
+
+ // Capacity should have been reduced.
+ assert!(v.capacity() < initial_capacity);
+ assert!(v.capacity() >= PAGE_SIZE);
+
+ // Elements should be preserved.
+ assert_eq!(v.len(), 3);
+ assert_eq!(v[0], 1);
+ assert_eq!(v[1], 2);
+ assert_eq!(v[2], 3);
+
+ // Shrink to zero (should shrink to len).
+ v.shrink_to(0, GFP_KERNEL).unwrap();
+
+ // Capacity should be at least the length.
+ assert!(v.capacity() >= v.len());
+
+ // Elements should still be preserved.
+ assert_eq!(v.len(), 3);
+ assert_eq!(v[0], 1);
+ assert_eq!(v[1], 2);
+ assert_eq!(v[2], 3);
+ }
+
+ #[test]
+ fn test_kvvec_shrink_to_empty() {
+ use crate::page::PAGE_SIZE;
+
+ // Create a vector with large capacity but no elements.
+ let mut v = KVVec::<u8>::with_capacity(PAGE_SIZE * 4, GFP_KERNEL).unwrap();
+
+ assert!(v.is_empty());
+
+ // Shrink empty vector to zero.
+ v.shrink_to(0, GFP_KERNEL).unwrap();
+
+ // Should have freed the allocation.
+ assert_eq!(v.capacity(), 0);
+ assert!(v.is_empty());
+ }
+
+ #[test]
+ fn test_kvvec_shrink_to_no_op() {
+ use crate::page::PAGE_SIZE;
+
+ // Create a small vector.
+ let mut v = KVVec::<u8>::with_capacity(PAGE_SIZE, GFP_KERNEL).unwrap();
+ v.push(1, GFP_KERNEL).unwrap();
+
+ let capacity_before = v.capacity();
+
+ // Try to shrink to a capacity larger than current - should be no-op.
+ v.shrink_to(capacity_before + 100, GFP_KERNEL).unwrap();
+
+ assert_eq!(v.capacity(), capacity_before);
+ assert_eq!(v.len(), 1);
+ assert_eq!(v[0], 1);
+ }
+
+ #[test]
+ fn test_kvvec_shrink_to_respects_min_capacity() {
+ use crate::page::PAGE_SIZE;
+
+ // Create a vector with large capacity.
+ let mut v = KVVec::<u8>::with_capacity(PAGE_SIZE * 4, GFP_KERNEL).unwrap();
+
+ // Add some elements.
+ for i in 0..10u8 {
+ v.push(i, GFP_KERNEL).unwrap();
+ }
+
+ // Shrink to a min_capacity larger than length.
+ let min_cap = PAGE_SIZE * 2;
+ v.shrink_to(min_cap, GFP_KERNEL).unwrap();
+
+ // Capacity should be at least min_capacity.
+ assert!(v.capacity() >= min_cap);
+
+ // All elements preserved.
+ assert_eq!(v.len(), 10);
+ for i in 0..10u8 {
+ assert_eq!(v[i as usize], i);
+ }
+ }
}
diff --git a/rust/kernel/sync/aref.rs b/rust/kernel/sync/aref.rs
index 0616c0353c2b..9989f56d0605 100644
--- a/rust/kernel/sync/aref.rs
+++ b/rust/kernel/sync/aref.rs
@@ -170,3 +170,25 @@ impl<T: AlwaysRefCounted> Drop for ARef<T> {
unsafe { T::dec_ref(self.ptr) };
}
}
+
+impl<T, U> PartialEq<ARef<U>> for ARef<T>
+where
+ T: AlwaysRefCounted + PartialEq<U>,
+ U: AlwaysRefCounted,
+{
+ #[inline]
+ fn eq(&self, other: &ARef<U>) -> bool {
+ T::eq(&**self, &**other)
+ }
+}
+impl<T: AlwaysRefCounted + Eq> Eq for ARef<T> {}
+
+impl<T, U> PartialEq<&'_ U> for ARef<T>
+where
+ T: AlwaysRefCounted + PartialEq<U>,
+{
+ #[inline]
+ fn eq(&self, other: &&U) -> bool {
+ T::eq(&**self, other)
+ }
+}
diff --git a/rust/kernel/task.rs b/rust/kernel/task.rs
index 049c8a4d45d8..38273f4eedb5 100644
--- a/rust/kernel/task.rs
+++ b/rust/kernel/task.rs
@@ -361,6 +361,15 @@ unsafe impl crate::sync::aref::AlwaysRefCounted for Task {
}
}
+impl PartialEq for Task {
+ #[inline]
+ fn eq(&self, other: &Self) -> bool {
+ ptr::eq(self.as_ptr(), other.as_ptr())
+ }
+}
+
+impl Eq for Task {}
+
impl Kuid {
/// Get the current euid.
#[inline]
diff --git a/rust/kernel/uaccess.rs b/rust/kernel/uaccess.rs
index 6c9c1cce3c63..5f6c4d7a1a51 100644
--- a/rust/kernel/uaccess.rs
+++ b/rust/kernel/uaccess.rs
@@ -21,7 +21,7 @@ use core::mem::{size_of, MaybeUninit};
///
/// This is the Rust equivalent to C pointers tagged with `__user`.
#[repr(transparent)]
-#[derive(Copy, Clone)]
+#[derive(Copy, Clone, Zeroable)]
pub struct UserPtr(*mut c_void);
impl UserPtr {