diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2022-03-28 12:27:35 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2022-03-28 12:27:35 -0700 |
commit | 02e2af20f4f9f2aa0c84e9a30a35c02f0fbb7daa (patch) | |
tree | d126449a7d2ea2270627183f7cebd726fbe56a9d /drivers/iio/adc | |
parent | ff61bc81b3feebcef4d0431a92e2e40e8d4fe8b3 (diff) | |
parent | 37fd83916da2e4cae03d350015c82a67b1b334c4 (diff) | |
download | linux-02e2af20f4f9f2aa0c84e9a30a35c02f0fbb7daa.tar.bz2 |
Merge tag 'char-misc-5.18-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc
Pull char/misc and other driver updates from Greg KH:
"Here is the big set of char/misc and other small driver subsystem
updates for 5.18-rc1.
Included in here are merges from driver subsystems which contain:
- iio driver updates and new drivers
- fsi driver updates
- fpga driver updates
- habanalabs driver updates and support for new hardware
- soundwire driver updates and new drivers
- phy driver updates and new drivers
- coresight driver updates
- icc driver updates
Individual changes include:
- mei driver updates
- interconnect driver updates
- new PECI driver subsystem added
- vmci driver updates
- lots of tiny misc/char driver updates
All of these have been in linux-next for a while with no reported
problems"
* tag 'char-misc-5.18-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc: (556 commits)
firmware: google: Properly state IOMEM dependency
kgdbts: fix return value of __setup handler
firmware: sysfb: fix platform-device leak in error path
firmware: stratix10-svc: add missing callback parameter on RSU
arm64: dts: qcom: add non-secure domain property to fastrpc nodes
misc: fastrpc: Add dma handle implementation
misc: fastrpc: Add fdlist implementation
misc: fastrpc: Add helper function to get list and page
misc: fastrpc: Add support to secure memory map
dt-bindings: misc: add fastrpc domain vmid property
misc: fastrpc: check before loading process to the DSP
misc: fastrpc: add secure domain support
dt-bindings: misc: add property to support non-secure DSP
misc: fastrpc: Add support to get DSP capabilities
misc: fastrpc: add support for FASTRPC_IOCTL_MEM_MAP/UNMAP
misc: fastrpc: separate fastrpc device from channel context
dt-bindings: nvmem: brcm,nvram: add basic NVMEM cells
dt-bindings: nvmem: make "reg" property optional
nvmem: brcm_nvram: parse NVRAM content into NVMEM cells
nvmem: dt-bindings: Fix the error of dt-bindings check
...
Diffstat (limited to 'drivers/iio/adc')
41 files changed, 1504 insertions, 266 deletions
diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig index 4fdc8bfbb407..71ab0a06aa82 100644 --- a/drivers/iio/adc/Kconfig +++ b/drivers/iio/adc/Kconfig @@ -64,6 +64,17 @@ config AD7266 To compile this driver as a module, choose M here: the module will be called ad7266. +config AD7280 + tristate "Analog Devices AD7280A Lithium Ion Battery Monitoring System" + depends on SPI + select CRC8 + help + Say yes here to build support for Analog Devices AD7280A + Lithium Ion Battery Monitoring System. + + To compile this driver as a module, choose M here: the + module will be called ad7280a + config AD7291 tristate "Analog Devices AD7291 ADC driver" depends on I2C diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile index 4a8f1833993b..39d806f6d457 100644 --- a/drivers/iio/adc/Makefile +++ b/drivers/iio/adc/Makefile @@ -10,6 +10,7 @@ obj-$(CONFIG_AD7091R5) += ad7091r5.o ad7091r-base.o obj-$(CONFIG_AD7124) += ad7124.o obj-$(CONFIG_AD7192) += ad7192.o obj-$(CONFIG_AD7266) += ad7266.o +obj-$(CONFIG_AD7280) += ad7280a.o obj-$(CONFIG_AD7291) += ad7291.o obj-$(CONFIG_AD7292) += ad7292.o obj-$(CONFIG_AD7298) += ad7298.o diff --git a/drivers/iio/adc/ab8500-gpadc.c b/drivers/iio/adc/ab8500-gpadc.c index 4c46a201d4ef..930ce96e6ff5 100644 --- a/drivers/iio/adc/ab8500-gpadc.c +++ b/drivers/iio/adc/ab8500-gpadc.c @@ -942,7 +942,6 @@ static const struct iio_info ab8500_gpadc_info = { .read_raw = ab8500_gpadc_read_raw, }; -#ifdef CONFIG_PM static int ab8500_gpadc_runtime_suspend(struct device *dev) { struct iio_dev *indio_dev = dev_get_drvdata(dev); @@ -965,7 +964,6 @@ static int ab8500_gpadc_runtime_resume(struct device *dev) return ret; } -#endif /** * ab8500_gpadc_parse_channel() - process devicetree channel configuration @@ -1199,20 +1197,16 @@ static int ab8500_gpadc_remove(struct platform_device *pdev) return 0; } -static const struct dev_pm_ops ab8500_gpadc_pm_ops = { - SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, - pm_runtime_force_resume) - SET_RUNTIME_PM_OPS(ab8500_gpadc_runtime_suspend, - ab8500_gpadc_runtime_resume, - NULL) -}; +static DEFINE_RUNTIME_DEV_PM_OPS(ab8500_gpadc_pm_ops, + ab8500_gpadc_runtime_suspend, + ab8500_gpadc_runtime_resume, NULL); static struct platform_driver ab8500_gpadc_driver = { .probe = ab8500_gpadc_probe, .remove = ab8500_gpadc_remove, .driver = { .name = "ab8500-gpadc", - .pm = &ab8500_gpadc_pm_ops, + .pm = pm_ptr(&ab8500_gpadc_pm_ops), }, }; builtin_platform_driver(ab8500_gpadc_driver); diff --git a/drivers/iio/adc/ad7091r-base.c b/drivers/iio/adc/ad7091r-base.c index 63b4d6ea4566..8e252cde735b 100644 --- a/drivers/iio/adc/ad7091r-base.c +++ b/drivers/iio/adc/ad7091r-base.c @@ -260,7 +260,7 @@ int ad7091r_probe(struct device *dev, const char *name, return devm_iio_device_register(dev, iio_dev); } -EXPORT_SYMBOL_GPL(ad7091r_probe); +EXPORT_SYMBOL_NS_GPL(ad7091r_probe, IIO_AD7091R); static bool ad7091r_writeable_reg(struct device *dev, unsigned int reg) { @@ -290,7 +290,7 @@ const struct regmap_config ad7091r_regmap_config = { .writeable_reg = ad7091r_writeable_reg, .volatile_reg = ad7091r_volatile_reg, }; -EXPORT_SYMBOL_GPL(ad7091r_regmap_config); +EXPORT_SYMBOL_NS_GPL(ad7091r_regmap_config, IIO_AD7091R); MODULE_AUTHOR("Beniamin Bia <beniamin.bia@analog.com>"); MODULE_DESCRIPTION("Analog Devices AD7091Rx multi-channel converters"); diff --git a/drivers/iio/adc/ad7091r5.c b/drivers/iio/adc/ad7091r5.c index 9665679c3ea6..47f5763023a4 100644 --- a/drivers/iio/adc/ad7091r5.c +++ b/drivers/iio/adc/ad7091r5.c @@ -111,3 +111,4 @@ module_i2c_driver(ad7091r5_driver); MODULE_AUTHOR("Beniamin Bia <beniamin.bia@analog.com>"); MODULE_DESCRIPTION("Analog Devices AD7091R5 multi-channel ADC driver"); MODULE_LICENSE("GPL v2"); +MODULE_IMPORT_NS(IIO_AD7091R); diff --git a/drivers/iio/adc/ad7124.c b/drivers/iio/adc/ad7124.c index b400bbe291aa..c47ead15f6e5 100644 --- a/drivers/iio/adc/ad7124.c +++ b/drivers/iio/adc/ad7124.c @@ -970,3 +970,4 @@ module_spi_driver(ad71124_driver); MODULE_AUTHOR("Stefan Popa <stefan.popa@analog.com>"); MODULE_DESCRIPTION("Analog Devices AD7124 SPI driver"); MODULE_LICENSE("GPL"); +MODULE_IMPORT_NS(IIO_AD_SIGMA_DELTA); diff --git a/drivers/iio/adc/ad7192.c b/drivers/iio/adc/ad7192.c index cc990205f306..770b4e59238f 100644 --- a/drivers/iio/adc/ad7192.c +++ b/drivers/iio/adc/ad7192.c @@ -433,7 +433,7 @@ static ssize_t ad7192_show_ac_excitation(struct device *dev, struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ad7192_state *st = iio_priv(indio_dev); - return sprintf(buf, "%d\n", !!(st->mode & AD7192_MODE_ACX)); + return sysfs_emit(buf, "%d\n", !!(st->mode & AD7192_MODE_ACX)); } static ssize_t ad7192_show_bridge_switch(struct device *dev, @@ -443,7 +443,7 @@ static ssize_t ad7192_show_bridge_switch(struct device *dev, struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct ad7192_state *st = iio_priv(indio_dev); - return sprintf(buf, "%d\n", !!(st->gpocon & AD7192_GPOCON_BPDSW)); + return sysfs_emit(buf, "%d\n", !!(st->gpocon & AD7192_GPOCON_BPDSW)); } static ssize_t ad7192_set(struct device *dev, @@ -1048,3 +1048,4 @@ module_spi_driver(ad7192_driver); MODULE_AUTHOR("Michael Hennerich <michael.hennerich@analog.com>"); MODULE_DESCRIPTION("Analog Devices AD7190, AD7192, AD7193, AD7195 ADC"); MODULE_LICENSE("GPL v2"); +MODULE_IMPORT_NS(IIO_AD_SIGMA_DELTA); diff --git a/drivers/iio/adc/ad7280a.c b/drivers/iio/adc/ad7280a.c new file mode 100644 index 000000000000..ef9d27759961 --- /dev/null +++ b/drivers/iio/adc/ad7280a.c @@ -0,0 +1,1111 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * AD7280A Lithium Ion Battery Monitoring System + * + * Copyright 2011 Analog Devices Inc. + */ + +#include <linux/bitfield.h> +#include <linux/bits.h> +#include <linux/crc8.h> +#include <linux/delay.h> +#include <linux/device.h> +#include <linux/err.h> +#include <linux/interrupt.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/mod_devicetable.h> +#include <linux/mutex.h> +#include <linux/slab.h> +#include <linux/sysfs.h> +#include <linux/spi/spi.h> + +#include <linux/iio/events.h> +#include <linux/iio/iio.h> + +/* Registers */ + +#define AD7280A_CELL_VOLTAGE_1_REG 0x0 /* D11 to D0, Read only */ +#define AD7280A_CELL_VOLTAGE_2_REG 0x1 /* D11 to D0, Read only */ +#define AD7280A_CELL_VOLTAGE_3_REG 0x2 /* D11 to D0, Read only */ +#define AD7280A_CELL_VOLTAGE_4_REG 0x3 /* D11 to D0, Read only */ +#define AD7280A_CELL_VOLTAGE_5_REG 0x4 /* D11 to D0, Read only */ +#define AD7280A_CELL_VOLTAGE_6_REG 0x5 /* D11 to D0, Read only */ +#define AD7280A_AUX_ADC_1_REG 0x6 /* D11 to D0, Read only */ +#define AD7280A_AUX_ADC_2_REG 0x7 /* D11 to D0, Read only */ +#define AD7280A_AUX_ADC_3_REG 0x8 /* D11 to D0, Read only */ +#define AD7280A_AUX_ADC_4_REG 0x9 /* D11 to D0, Read only */ +#define AD7280A_AUX_ADC_5_REG 0xA /* D11 to D0, Read only */ +#define AD7280A_AUX_ADC_6_REG 0xB /* D11 to D0, Read only */ +#define AD7280A_SELF_TEST_REG 0xC /* D11 to D0, Read only */ + +#define AD7280A_CTRL_HB_REG 0xD /* D15 to D8, Read/write */ +#define AD7280A_CTRL_HB_CONV_INPUT_MSK GENMASK(7, 6) +#define AD7280A_CTRL_HB_CONV_INPUT_ALL 0 +#define AD7280A_CTRL_HB_CONV_INPUT_6CELL_AUX1_3_5 1 +#define AD7280A_CTRL_HB_CONV_INPUT_6CELL 2 +#define AD7280A_CTRL_HB_CONV_INPUT_SELF_TEST 3 +#define AD7280A_CTRL_HB_CONV_RREAD_MSK GENMASK(5, 4) +#define AD7280A_CTRL_HB_CONV_RREAD_ALL 0 +#define AD7280A_CTRL_HB_CONV_RREAD_6CELL_AUX1_3_5 1 +#define AD7280A_CTRL_HB_CONV_RREAD_6CELL 2 +#define AD7280A_CTRL_HB_CONV_RREAD_NO 3 +#define AD7280A_CTRL_HB_CONV_START_MSK BIT(3) +#define AD7280A_CTRL_HB_CONV_START_CNVST 0 +#define AD7280A_CTRL_HB_CONV_START_CS 1 +#define AD7280A_CTRL_HB_CONV_AVG_MSK GENMASK(2, 1) +#define AD7280A_CTRL_HB_CONV_AVG_DIS 0 +#define AD7280A_CTRL_HB_CONV_AVG_2 1 +#define AD7280A_CTRL_HB_CONV_AVG_4 2 +#define AD7280A_CTRL_HB_CONV_AVG_8 3 +#define AD7280A_CTRL_HB_PWRDN_SW BIT(0) + +#define AD7280A_CTRL_LB_REG 0xE /* D7 to D0, Read/write */ +#define AD7280A_CTRL_LB_SWRST_MSK BIT(7) +#define AD7280A_CTRL_LB_ACQ_TIME_MSK GENMASK(6, 5) +#define AD7280A_CTRL_LB_ACQ_TIME_400ns 0 +#define AD7280A_CTRL_LB_ACQ_TIME_800ns 1 +#define AD7280A_CTRL_LB_ACQ_TIME_1200ns 2 +#define AD7280A_CTRL_LB_ACQ_TIME_1600ns 3 +#define AD7280A_CTRL_LB_MUST_SET BIT(4) +#define AD7280A_CTRL_LB_THERMISTOR_MSK BIT(3) +#define AD7280A_CTRL_LB_LOCK_DEV_ADDR_MSK BIT(2) +#define AD7280A_CTRL_LB_INC_DEV_ADDR_MSK BIT(1) +#define AD7280A_CTRL_LB_DAISY_CHAIN_RB_MSK BIT(0) + +#define AD7280A_CELL_OVERVOLTAGE_REG 0xF /* D7 to D0, Read/write */ +#define AD7280A_CELL_UNDERVOLTAGE_REG 0x10 /* D7 to D0, Read/write */ +#define AD7280A_AUX_ADC_OVERVOLTAGE_REG 0x11 /* D7 to D0, Read/write */ +#define AD7280A_AUX_ADC_UNDERVOLTAGE_REG 0x12 /* D7 to D0, Read/write */ + +#define AD7280A_ALERT_REG 0x13 /* D7 to D0, Read/write */ +#define AD7280A_ALERT_REMOVE_MSK GENMASK(3, 0) +#define AD7280A_ALERT_REMOVE_AUX5 BIT(0) +#define AD7280A_ALERT_REMOVE_AUX3_AUX5 BIT(1) +#define AD7280A_ALERT_REMOVE_VIN5 BIT(2) +#define AD7280A_ALERT_REMOVE_VIN4_VIN5 BIT(3) +#define AD7280A_ALERT_GEN_STATIC_HIGH BIT(6) +#define AD7280A_ALERT_RELAY_SIG_CHAIN_DOWN (BIT(7) | BIT(6)) + +#define AD7280A_CELL_BALANCE_REG 0x14 /* D7 to D0, Read/write */ +#define AD7280A_CELL_BALANCE_CHAN_BITMAP_MSK GENMASK(7, 2) +#define AD7280A_CB1_TIMER_REG 0x15 /* D7 to D0, Read/write */ +#define AD7280A_CB_TIMER_VAL_MSK GENMASK(7, 3) +#define AD7280A_CB2_TIMER_REG 0x16 /* D7 to D0, Read/write */ +#define AD7280A_CB3_TIMER_REG 0x17 /* D7 to D0, Read/write */ +#define AD7280A_CB4_TIMER_REG 0x18 /* D7 to D0, Read/write */ +#define AD7280A_CB5_TIMER_REG 0x19 /* D7 to D0, Read/write */ +#define AD7280A_CB6_TIMER_REG 0x1A /* D7 to D0, Read/write */ +#define AD7280A_PD_TIMER_REG 0x1B /* D7 to D0, Read/write */ +#define AD7280A_READ_REG 0x1C /* D7 to D0, Read/write */ +#define AD7280A_READ_ADDR_MSK GENMASK(7, 2) +#define AD7280A_CNVST_CTRL_REG 0x1D /* D7 to D0, Read/write */ + +/* Transfer fields */ +#define AD7280A_TRANS_WRITE_DEVADDR_MSK GENMASK(31, 27) +#define AD7280A_TRANS_WRITE_ADDR_MSK GENMASK(26, 21) +#define AD7280A_TRANS_WRITE_VAL_MSK GENMASK(20, 13) +#define AD7280A_TRANS_WRITE_ALL_MSK BIT(12) +#define AD7280A_TRANS_WRITE_CRC_MSK GENMASK(10, 3) +#define AD7280A_TRANS_WRITE_RES_PATTERN 0x2 + +/* Layouts differ for channel vs other registers */ +#define AD7280A_TRANS_READ_DEVADDR_MSK GENMASK(31, 27) +#define AD7280A_TRANS_READ_CONV_CHANADDR_MSK GENMASK(26, 23) +#define AD7280A_TRANS_READ_CONV_DATA_MSK GENMASK(22, 11) +#define AD7280A_TRANS_READ_REG_REGADDR_MSK GENMASK(26, 21) +#define AD7280A_TRANS_READ_REG_DATA_MSK GENMASK(20, 13) +#define AD7280A_TRANS_READ_WRITE_ACK_MSK BIT(10) +#define AD7280A_TRANS_READ_CRC_MSK GENMASK(9, 2) + +/* Magic value used to indicate this special case */ +#define AD7280A_ALL_CELLS (0xAD << 16) + +#define AD7280A_MAX_SPI_CLK_HZ 700000 /* < 1MHz */ +#define AD7280A_MAX_CHAIN 8 +#define AD7280A_CELLS_PER_DEV 6 +#define AD7280A_BITS 12 +#define AD7280A_NUM_CH (AD7280A_AUX_ADC_6_REG - \ + AD7280A_CELL_VOLTAGE_1_REG + 1) + +#define AD7280A_CALC_VOLTAGE_CHAN_NUM(d, c) (((d) * AD7280A_CELLS_PER_DEV) + \ + (c)) +#define AD7280A_CALC_TEMP_CHAN_NUM(d, c) (((d) * AD7280A_CELLS_PER_DEV) + \ + (c) - AD7280A_CELLS_PER_DEV) + +#define AD7280A_DEVADDR_MASTER 0 +#define AD7280A_DEVADDR_ALL 0x1F + +static const unsigned short ad7280a_n_avg[4] = {1, 2, 4, 8}; +static const unsigned short ad7280a_t_acq_ns[4] = {470, 1030, 1510, 1945}; + +/* 5-bit device address is sent LSB first */ +static unsigned int ad7280a_devaddr(unsigned int addr) +{ + return ((addr & 0x1) << 4) | + ((addr & 0x2) << 2) | + (addr & 0x4) | + ((addr & 0x8) >> 2) | + ((addr & 0x10) >> 4); +} + +/* + * During a read a valid write is mandatory. + * So writing to the highest available address (Address 0x1F) and setting the + * address all parts bit to 0 is recommended. + * So the TXVAL is AD7280A_DEVADDR_ALL + CRC + */ +#define AD7280A_READ_TXVAL 0xF800030A + +/* + * AD7280 CRC + * + * P(x) = x^8 + x^5 + x^3 + x^2 + x^1 + x^0 = 0b100101111 => 0x2F + */ +#define POLYNOM 0x2F + +struct ad7280_state { + struct spi_device *spi; + struct iio_chan_spec *channels; + unsigned int chain_last_alert_ignore; + bool thermistor_term_en; + int slave_num; + int scan_cnt; + int readback_delay_us; + unsigned char crc_tab[CRC8_TABLE_SIZE]; + u8 oversampling_ratio; + u8 acquisition_time; + unsigned char ctrl_lb; + unsigned char cell_threshhigh; + unsigned char cell_threshlow; + unsigned char aux_threshhigh; + unsigned char aux_threshlow; + unsigned char cb_mask[AD7280A_MAX_CHAIN]; + struct mutex lock; /* protect sensor state */ + + __be32 tx ____cacheline_aligned; + __be32 rx; +}; + +static unsigned char ad7280_calc_crc8(unsigned char *crc_tab, unsigned int val) +{ + unsigned char crc; + + crc = crc_tab[val >> 16 & 0xFF]; + crc = crc_tab[crc ^ (val >> 8 & 0xFF)]; + + return crc ^ (val & 0xFF); +} + +static int ad7280_check_crc(struct ad7280_state *st, unsigned int val) +{ + unsigned char crc = ad7280_calc_crc8(st->crc_tab, val >> 10); + + if (crc != ((val >> 2) & 0xFF)) + return -EIO; + + return 0; +} + +/* + * After initiating a conversion sequence we need to wait until the conversion + * is done. The delay is typically in the range of 15..30us however depending on + * the number of devices in the daisy chain, the number of averages taken, + * conversion delays and acquisition time options it may take up to 250us, in + * this case we better sleep instead of busy wait. + */ + +static void ad7280_delay(struct ad7280_state *st) +{ + if (st->readback_delay_us < 50) + udelay(st->readback_delay_us); + else + usleep_range(250, 500); +} + +static int __ad7280_read32(struct ad7280_state *st, unsigned int *val) +{ + int ret; + struct spi_transfer t = { + .tx_buf = &st->tx, + .rx_buf = &st->rx, + .len = sizeof(st->tx), + }; + + st->tx = cpu_to_be32(AD7280A_READ_TXVAL); + + ret = spi_sync_transfer(st->spi, &t, 1); + if (ret) + return ret; + + *val = be32_to_cpu(st->rx); + + return 0; +} + +static int ad7280_write(struct ad7280_state *st, unsigned int devaddr, + unsigned int addr, bool all, unsigned int val) +{ + unsigned int reg = FIELD_PREP(AD7280A_TRANS_WRITE_DEVADDR_MSK, devaddr) | + FIELD_PREP(AD7280A_TRANS_WRITE_ADDR_MSK, addr) | + FIELD_PREP(AD7280A_TRANS_WRITE_VAL_MSK, val) | + FIELD_PREP(AD7280A_TRANS_WRITE_ALL_MSK, all); + + reg |= FIELD_PREP(AD7280A_TRANS_WRITE_CRC_MSK, + ad7280_calc_crc8(st->crc_tab, reg >> 11)); + /* Reserved b010 pattern not included crc calc */ + reg |= AD7280A_TRANS_WRITE_RES_PATTERN; + + st->tx = cpu_to_be32(reg); + + return spi_write(st->spi, &st->tx, sizeof(st->tx)); +} + +static int ad7280_read_reg(struct ad7280_state *st, unsigned int devaddr, + unsigned int addr) +{ + int ret; + unsigned int tmp; + + /* turns off the read operation on all parts */ + ret = ad7280_write(st, AD7280A_DEVADDR_MASTER, AD7280A_CTRL_HB_REG, 1, + FIELD_PREP(AD7280A_CTRL_HB_CONV_INPUT_MSK, + AD7280A_CTRL_HB_CONV_INPUT_ALL) | + FIELD_PREP(AD7280A_CTRL_HB_CONV_RREAD_MSK, + AD7280A_CTRL_HB_CONV_RREAD_NO) | + FIELD_PREP(AD7280A_CTRL_HB_CONV_AVG_MSK, + st->oversampling_ratio)); + if (ret) + return ret; + + /* turns on the read operation on the addressed part */ + ret = ad7280_write(st, devaddr, AD7280A_CTRL_HB_REG, 0, + FIELD_PREP(AD7280A_CTRL_HB_CONV_INPUT_MSK, + AD7280A_CTRL_HB_CONV_INPUT_ALL) | + FIELD_PREP(AD7280A_CTRL_HB_CONV_RREAD_MSK, + AD7280A_CTRL_HB_CONV_RREAD_ALL) | + FIELD_PREP(AD7280A_CTRL_HB_CONV_AVG_MSK, + st->oversampling_ratio)); + if (ret) + return ret; + + /* Set register address on the part to be read from */ + ret = ad7280_write(st, devaddr, AD7280A_READ_REG, 0, + FIELD_PREP(AD7280A_READ_ADDR_MSK, addr)); + if (ret) + return ret; + + ret = __ad7280_read32(st, &tmp); + if (ret) + return ret; + + if (ad7280_check_crc(st, tmp)) + return -EIO; + + if ((FIELD_GET(AD7280A_TRANS_READ_DEVADDR_MSK, tmp) != devaddr) || + (FIELD_GET(AD7280A_TRANS_READ_REG_REGADDR_MSK, tmp) != addr)) + return -EFAULT; + + return FIELD_GET(AD7280A_TRANS_READ_REG_DATA_MSK, tmp); +} + +static int ad7280_read_channel(struct ad7280_state *st, unsigned int devaddr, + unsigned int addr) +{ + int ret; + unsigned int tmp; + + ret = ad7280_write(st, devaddr, AD7280A_READ_REG, 0, + FIELD_PREP(AD7280A_READ_ADDR_MSK, addr)); + if (ret) + return ret; + + ret = ad7280_write(st, AD7280A_DEVADDR_MASTER, AD7280A_CTRL_HB_REG, 1, + FIELD_PREP(AD7280A_CTRL_HB_CONV_INPUT_MSK, + AD7280A_CTRL_HB_CONV_INPUT_ALL) | + FIELD_PREP(AD7280A_CTRL_HB_CONV_RREAD_MSK, + AD7280A_CTRL_HB_CONV_RREAD_NO) | + FIELD_PREP(AD7280A_CTRL_HB_CONV_AVG_MSK, + st->oversampling_ratio)); + if (ret) + return ret; + + ret = ad7280_write(st, devaddr, AD7280A_CTRL_HB_REG, 0, + FIELD_PREP(AD7280A_CTRL_HB_CONV_INPUT_MSK, + AD7280A_CTRL_HB_CONV_INPUT_ALL) | + FIELD_PREP(AD7280A_CTRL_HB_CONV_RREAD_MSK, + AD7280A_CTRL_HB_CONV_RREAD_ALL) | + FIELD_PREP(AD7280A_CTRL_HB_CONV_START_MSK, + AD7280A_CTRL_HB_CONV_START_CS) | + FIELD_PREP(AD7280A_CTRL_HB_CONV_AVG_MSK, + st->oversampling_ratio)); + if (ret) + return ret; + + ad7280_delay(st); + + ret = __ad7280_read32(st, &tmp); + if (ret) + return ret; + + if (ad7280_check_crc(st, tmp)) + return -EIO; + + if ((FIELD_GET(AD7280A_TRANS_READ_DEVADDR_MSK, tmp) != devaddr) || + (FIELD_GET(AD7280A_TRANS_READ_CONV_CHANADDR_MSK, tmp) != addr)) + return -EFAULT; + + return FIELD_GET(AD7280A_TRANS_READ_CONV_DATA_MSK, tmp); +} + +static int ad7280_read_all_channels(struct ad7280_state *st, unsigned int cnt, + unsigned int *array) +{ + int i, ret; + unsigned int tmp, sum = 0; + + ret = ad7280_write(st, AD7280A_DEVADDR_MASTER, AD7280A_READ_REG, 1, + AD7280A_CELL_VOLTAGE_1_REG << 2); + if (ret) + return ret; + + ret = ad7280_write(st, AD7280A_DEVADDR_MASTER, AD7280A_CTRL_HB_REG, 1, + FIELD_PREP(AD7280A_CTRL_HB_CONV_INPUT_MSK, + AD7280A_CTRL_HB_CONV_INPUT_ALL) | + FIELD_PREP(AD7280A_CTRL_HB_CONV_RREAD_MSK, + AD7280A_CTRL_HB_CONV_RREAD_ALL) | + FIELD_PREP(AD7280A_CTRL_HB_CONV_START_MSK, + AD7280A_CTRL_HB_CONV_START_CS) | + FIELD_PREP(AD7280A_CTRL_HB_CONV_AVG_MSK, + st->oversampling_ratio)); + if (ret) + return ret; + + ad7280_delay(st); + + for (i = 0; i < cnt; i++) { + ret = __ad7280_read32(st, &tmp); + if (ret) + return ret; + + if (ad7280_check_crc(st, tmp)) + return -EIO; + + if (array) + array[i] = tmp; + /* only sum cell voltages */ + if (FIELD_GET(AD7280A_TRANS_READ_CONV_CHANADDR_MSK, tmp) <= + AD7280A_CELL_VOLTAGE_6_REG) + sum += FIELD_GET(AD7280A_TRANS_READ_CONV_DATA_MSK, tmp); + } + + return sum; +} + +static void ad7280_sw_power_down(void *data) +{ + struct ad7280_state *st = data; + + ad7280_write(st, AD7280A_DEVADDR_MASTER, AD7280A_CTRL_HB_REG, 1, + AD7280A_CTRL_HB_PWRDN_SW | + FIELD_PREP(AD7280A_CTRL_HB_CONV_AVG_MSK, st->oversampling_ratio)); +} + +static int ad7280_chain_setup(struct ad7280_state *st) +{ + unsigned int val, n; + int ret; + + ret = ad7280_write(st, AD7280A_DEVADDR_MASTER, AD7280A_CTRL_LB_REG, 1, + FIELD_PREP(AD7280A_CTRL_LB_DAISY_CHAIN_RB_MSK, 1) | + FIELD_PREP(AD7280A_CTRL_LB_LOCK_DEV_ADDR_MSK, 1) | + AD7280A_CTRL_LB_MUST_SET | + FIELD_PREP(AD7280A_CTRL_LB_SWRST_MSK, 1) | + st->ctrl_lb); + if (ret) + return ret; + + ret = ad7280_write(st, AD7280A_DEVADDR_MASTER, AD7280A_CTRL_LB_REG, 1, + FIELD_PREP(AD7280A_CTRL_LB_DAISY_CHAIN_RB_MSK, 1) | + FIELD_PREP(AD7280A_CTRL_LB_LOCK_DEV_ADDR_MSK, 1) | + AD7280A_CTRL_LB_MUST_SET | + FIELD_PREP(AD7280A_CTRL_LB_SWRST_MSK, 0) | + st->ctrl_lb); + if (ret) + goto error_power_down; + + ret = ad7280_write(st, AD7280A_DEVADDR_MASTER, AD7280A_READ_REG, 1, + FIELD_PREP(AD7280A_READ_ADDR_MSK, AD7280A_CTRL_LB_REG)); + if (ret) + goto error_power_down; + + for (n = 0; n <= AD7280A_MAX_CHAIN; n++) { + ret = __ad7280_read32(st, &val); + if (ret) + goto error_power_down; + + if (val == 0) + return n - 1; + + if (ad7280_check_crc(st, val)) { + ret = -EIO; + goto error_power_down; + } + + if (n != ad7280a_devaddr(FIELD_GET(AD7280A_TRANS_READ_DEVADDR_MSK, val))) { + ret = -EIO; + goto error_power_down; + } + } + ret = -EFAULT; + +error_power_down: + ad7280_write(st, AD7280A_DEVADDR_MASTER, AD7280A_CTRL_HB_REG, 1, + AD7280A_CTRL_HB_PWRDN_SW | + FIELD_PREP(AD7280A_CTRL_HB_CONV_AVG_MSK, st->oversampling_ratio)); + + return ret; +} + +static ssize_t ad7280_show_balance_sw(struct iio_dev *indio_dev, + uintptr_t private, + const struct iio_chan_spec *chan, char *buf) +{ + struct ad7280_state *st = iio_priv(indio_dev); + + return sysfs_emit(buf, "%d\n", + !!(st->cb_mask[chan->address >> 8] & + BIT(chan->address & 0xFF))); +} + +static ssize_t ad7280_store_balance_sw(struct iio_dev *indio_dev, + uintptr_t private, + const struct iio_chan_spec *chan, + const char *buf, size_t len) +{ + struct ad7280_state *st = iio_priv(indio_dev); + unsigned int devaddr, ch; + bool readin; + int ret; + + ret = strtobool(buf, &readin); + if (ret) + return ret; + + devaddr = chan->address >> 8; + ch = chan->address & 0xFF; + + mutex_lock(&st->lock); + if (readin) + st->cb_mask[devaddr] |= BIT(ch); + else + st->cb_mask[devaddr] &= ~BIT(ch); + + ret = ad7280_write(st, devaddr, AD7280A_CELL_BALANCE_REG, 0, + FIELD_PREP(AD7280A_CELL_BALANCE_CHAN_BITMAP_MSK, + st->cb_mask[devaddr])); + mutex_unlock(&st->lock); + + return ret ? ret : len; +} + +static ssize_t ad7280_show_balance_timer(struct iio_dev *indio_dev, + uintptr_t private, + const struct iio_chan_spec *chan, + char *buf) +{ + struct ad7280_state *st = iio_priv(indio_dev); + unsigned int msecs; + int ret; + + mutex_lock(&st->lock); + ret = ad7280_read_reg(st, chan->address >> 8, + (chan->address & 0xFF) + AD7280A_CB1_TIMER_REG); + mutex_unlock(&st->lock); + + if (ret < 0) + return ret; + + msecs = FIELD_GET(AD7280A_CB_TIMER_VAL_MSK, ret) * 71500; + + return sysfs_emit(buf, "%u.%u\n", msecs / 1000, msecs % 1000); +} + +static ssize_t ad7280_store_balance_timer(struct iio_dev *indio_dev, + uintptr_t private, + const struct iio_chan_spec *chan, + const char *buf, size_t len) +{ + struct ad7280_state *st = iio_priv(indio_dev); + int val, val2; + int ret; + + ret = iio_str_to_fixpoint(buf, 1000, &val, &val2); + if (ret) + return ret; + + val = val * 1000 + val2; + val /= 71500; + + if (val > 31) + return -EINVAL; + + mutex_lock(&st->lock); + ret = ad7280_write(st, chan->address >> 8, + (chan->address & 0xFF) + AD7280A_CB1_TIMER_REG, 0, + FIELD_PREP(AD7280A_CB_TIMER_VAL_MSK, val)); + mutex_unlock(&st->lock); + + return ret ? ret : len; +} + +static const struct iio_chan_spec_ext_info ad7280_cell_ext_info[] = { + { + .name = "balance_switch_en", + .read = ad7280_show_balance_sw, + .write = ad7280_store_balance_sw, + .shared = IIO_SEPARATE, + }, { + .name = "balance_switch_timer", + .read = ad7280_show_balance_timer, + .write = ad7280_store_balance_timer, + .shared = IIO_SEPARATE, + }, + {} +}; + +static const struct iio_event_spec ad7280_events[] = { + { + .type = IIO_EV_TYPE_THRESH, + .dir = IIO_EV_DIR_RISING, + .mask_shared_by_type = BIT(IIO_EV_INFO_VALUE), + }, { + .type = IIO_EV_TYPE_THRESH, + .dir = IIO_EV_DIR_FALLING, + .mask_shared_by_type = BIT(IIO_EV_INFO_VALUE), + }, +}; + +static void ad7280_voltage_channel_init(struct iio_chan_spec *chan, int i, + bool irq_present) +{ + chan->type = IIO_VOLTAGE; + chan->differential = 1; + chan->channel = i; + chan->channel2 = chan->channel + 1; + if (irq_present) { + chan->event_spec = ad7280_events; + chan->num_event_specs = ARRAY_SIZE(ad7280_events); + } + chan->ext_info = ad7280_cell_ext_info; +} + +static void ad7280_temp_channel_init(struct iio_chan_spec *chan, int i, + bool irq_present) +{ + chan->type = IIO_TEMP; + chan->channel = i; + if (irq_present) { + chan->event_spec = ad7280_events; + chan->num_event_specs = ARRAY_SIZE(ad7280_events); + } +} + +static void ad7280_common_fields_init(struct iio_chan_spec *chan, int addr, + int cnt) +{ + chan->indexed = 1; + chan->info_mask_separate = BIT(IIO_CHAN_INFO_RAW); + chan->info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE); + chan->info_mask_shared_by_all = BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO); + chan->address = addr; + chan->scan_index = cnt; + chan->scan_type.sign = 'u'; + chan->scan_type.realbits = 12; + chan->scan_type.storagebits = 32; +} + +static void ad7280_total_voltage_channel_init(struct iio_chan_spec *chan, + int cnt, int dev) +{ + chan->type = IIO_VOLTAGE; + chan->differential = 1; + chan->channel = 0; + chan->channel2 = dev * AD7280A_CELLS_PER_DEV; + chan->address = AD7280A_ALL_CELLS; + chan->indexed = 1; + chan->info_mask_separate = BIT(IIO_CHAN_INFO_RAW); + chan->info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE); + chan->scan_index = cnt; + chan->scan_type.sign = 'u'; + chan->scan_type.realbits = 32; + chan->scan_type.storagebits = 32; +} + +static void ad7280_init_dev_channels(struct ad7280_state *st, int dev, int *cnt, + bool irq_present) +{ + int addr, ch, i; + struct iio_chan_spec *chan; + + for (ch = AD7280A_CELL_VOLTAGE_1_REG; ch <= AD7280A_AUX_ADC_6_REG; ch++) { + chan = &st->channels[*cnt]; + + if (ch < AD7280A_AUX_ADC_1_REG) { + i = AD7280A_CALC_VOLTAGE_CHAN_NUM(dev, ch); + ad7280_voltage_channel_init(chan, i, irq_present); + } else { + i = AD7280A_CALC_TEMP_CHAN_NUM(dev, ch); + ad7280_temp_channel_init(chan, i, irq_present); + } + + addr = ad7280a_devaddr(dev) << 8 | ch; + ad7280_common_fields_init(chan, addr, *cnt); + + (*cnt)++; + } +} + +static int ad7280_channel_init(struct ad7280_state *st, bool irq_present) +{ + int dev, cnt = 0; + + st->channels = devm_kcalloc(&st->spi->dev, (st->slave_num + 1) * 12 + 1, + sizeof(*st->channels), GFP_KERNEL); + if (!st->channels) + return -ENOMEM; + + for (dev = 0; dev <= st->slave_num; dev++) + ad7280_init_dev_channels(st, dev, &cnt, irq_present); + + ad7280_total_voltage_channel_init(&st->channels[cnt], cnt, dev); + + return cnt + 1; +} + +static int ad7280a_read_thresh(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, + enum iio_event_type type, + enum iio_event_direction dir, + enum iio_event_info info, int *val, int *val2) +{ + struct ad7280_state *st = iio_priv(indio_dev); + + switch (chan->type) { + case IIO_VOLTAGE: + switch (dir) { + case IIO_EV_DIR_RISING: + *val = 1000 + (st->cell_threshhigh * 1568L) / 100; + return IIO_VAL_INT; + case IIO_EV_DIR_FALLING: + *val = 1000 + (st->cell_threshlow * 1568L) / 100; + return IIO_VAL_INT; + default: + return -EINVAL; + } + break; + case IIO_TEMP: + switch (dir) { + case IIO_EV_DIR_RISING: + *val = ((st->aux_threshhigh) * 196L) / 10; + return IIO_VAL_INT; + case IIO_EV_DIR_FALLING: + *val = (st->aux_threshlow * 196L) / 10; + return IIO_VAL_INT; + default: + return -EINVAL; + } + break; + default: + return -EINVAL; + } +} + +static int ad7280a_write_thresh(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, + enum iio_event_type type, + enum iio_event_direction dir, + enum iio_event_info info, + int val, int val2) +{ + struct ad7280_state *st = iio_priv(indio_dev); + unsigned int addr; + long value; + int ret; + + if (val2 != 0) + return -EINVAL; + + mutex_lock(&st->lock); + switch (chan->type) { + case IIO_VOLTAGE: + value = ((val - 1000) * 100) / 1568; /* LSB 15.68mV */ + value = clamp(value, 0L, 0xFFL); + switch (dir) { + case IIO_EV_DIR_RISING: + addr = AD7280A_CELL_OVERVOLTAGE_REG; + ret = ad7280_write(st, AD7280A_DEVADDR_MASTER, addr, + 1, val); + if (ret) + break; + st->cell_threshhigh = value; + break; + case IIO_EV_DIR_FALLING: + addr = AD7280A_CELL_UNDERVOLTAGE_REG; + ret = ad7280_write(st, AD7280A_DEVADDR_MASTER, addr, + 1, val); + if (ret) + break; + st->cell_threshlow = value; + break; + default: + ret = -EINVAL; + goto err_unlock; + } + break; + case IIO_TEMP: + value = (val * 10) / 196; /* LSB 19.6mV */ + value = clamp(value, 0L, 0xFFL); + switch (dir) { + case IIO_EV_DIR_RISING: + addr = AD7280A_AUX_ADC_OVERVOLTAGE_REG; + ret = ad7280_write(st, AD7280A_DEVADDR_MASTER, addr, + 1, val); + if (ret) + break; + st->aux_threshhigh = val; + break; + case IIO_EV_DIR_FALLING: + addr = AD7280A_AUX_ADC_UNDERVOLTAGE_REG; + ret = ad7280_write(st, AD7280A_DEVADDR_MASTER, addr, + 1, val); + if (ret) + break; + st->aux_threshlow = val; + break; + default: + ret = -EINVAL; + goto err_unlock; + } + break; + default: + ret = -EINVAL; + goto err_unlock; + } + +err_unlock: + mutex_unlock(&st->lock); + + return ret; +} + +static irqreturn_t ad7280_event_handler(int irq, void *private) +{ + struct iio_dev *indio_dev = private; + struct ad7280_state *st = iio_priv(indio_dev); + unsigned int *channels; + int i, ret; + + channels = kcalloc(st->scan_cnt, sizeof(*channels), GFP_KERNEL); + if (!channels) + return IRQ_HANDLED; + + ret = ad7280_read_all_channels(st, st->scan_cnt, channels); + if (ret < 0) + goto out; + + for (i = 0; i < st->scan_cnt; i++) { + unsigned int val; + + val = FIELD_GET(AD7280A_TRANS_READ_CONV_DATA_MSK, channels[i]); + if (FIELD_GET(AD7280A_TRANS_READ_CONV_CHANADDR_MSK, channels[i]) <= + AD7280A_CELL_VOLTAGE_6_REG) { + if (val >= st->cell_threshhigh) { + u64 tmp = IIO_EVENT_CODE(IIO_VOLTAGE, 1, 0, + IIO_EV_DIR_RISING, + IIO_EV_TYPE_THRESH, + 0, 0, 0); + iio_push_event(indio_dev, tmp, + iio_get_time_ns(indio_dev)); + } else if (val <= st->cell_threshlow) { + u64 tmp = IIO_EVENT_CODE(IIO_VOLTAGE, 1, 0, + IIO_EV_DIR_FALLING, + IIO_EV_TYPE_THRESH, + 0, 0, 0); + iio_push_event(indio_dev, tmp, + iio_get_time_ns(indio_dev)); + } + } else { + if (val >= st->aux_threshhigh) { + u64 tmp = IIO_UNMOD_EVENT_CODE(IIO_TEMP, 0, + IIO_EV_TYPE_THRESH, + IIO_EV_DIR_RISING); + iio_push_event(indio_dev, tmp, + iio_get_time_ns(indio_dev)); + } else if (val <= st->aux_threshlow) { + u64 tmp = IIO_UNMOD_EVENT_CODE(IIO_TEMP, 0, + IIO_EV_TYPE_THRESH, + IIO_EV_DIR_FALLING); + iio_push_event(indio_dev, tmp, + iio_get_time_ns(indio_dev)); + } + } + } + +out: + kfree(channels); + + return IRQ_HANDLED; +} + +static void ad7280_update_delay(struct ad7280_state *st) +{ + /* + * Total Conversion Time = ((tACQ + tCONV) * + * (Number of Conversions per Part)) − + * tACQ + ((N - 1) * tDELAY) + * + * Readback Delay = Total Conversion Time + tWAIT + */ + + st->readback_delay_us = + ((ad7280a_t_acq_ns[st->acquisition_time & 0x3] + 720) * + (AD7280A_NUM_CH * ad7280a_n_avg[st->oversampling_ratio & 0x3])) - + ad7280a_t_acq_ns[st->acquisition_time & 0x3] + st->slave_num * 250; + + /* Convert to usecs */ + st->readback_delay_us = DIV_ROUND_UP(st->readback_delay_us, 1000); + st->readback_delay_us += 5; /* Add tWAIT */ +} + +static int ad7280_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, + int *val2, + long m) +{ + struct ad7280_state *st = iio_priv(indio_dev); + int ret; + + switch (m) { + case IIO_CHAN_INFO_RAW: + mutex_lock(&st->lock); + if (chan->address == AD7280A_ALL_CELLS) + ret = ad7280_read_all_channels(st, st->scan_cnt, NULL); + else + ret = ad7280_read_channel(st, chan->address >> 8, + chan->address & 0xFF); + mutex_unlock(&st->lock); + + if (ret < 0) + return ret; + + *val = ret; + + return IIO_VAL_INT; + case IIO_CHAN_INFO_SCALE: + if ((chan->address & 0xFF) <= AD7280A_CELL_VOLTAGE_6_REG) + *val = 4000; + else + *val = 5000; + + *val2 = AD7280A_BITS; + return IIO_VAL_FRACTIONAL_LOG2; + case IIO_CHAN_INFO_OVERSAMPLING_RATIO: + *val = ad7280a_n_avg[st->oversampling_ratio]; + return IIO_VAL_INT; + } + return -EINVAL; +} + +static int ad7280_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int val, int val2, long mask) +{ + struct ad7280_state *st = iio_priv(indio_dev); + int i; + + switch (mask) { + case IIO_CHAN_INFO_OVERSAMPLING_RATIO: + if (val2 != 0) + return -EINVAL; + for (i = 0; i < ARRAY_SIZE(ad7280a_n_avg); i++) { + if (val == ad7280a_n_avg[i]) { + st->oversampling_ratio = i; + ad7280_update_delay(st); + return 0; + } + } + return -EINVAL; + default: + return -EINVAL; + } +} + +static const struct iio_info ad7280_info = { + .read_raw = ad7280_read_raw, + .write_raw = ad7280_write_raw, + .read_event_value = &ad7280a_read_thresh, + .write_event_value = &ad7280a_write_thresh, +}; + +static const struct iio_info ad7280_info_no_irq = { + .read_raw = ad7280_read_raw, + .write_raw = ad7280_write_raw, +}; + +static int ad7280_probe(struct spi_device *spi) +{ + struct device *dev = &spi->dev; + struct ad7280_state *st; + int ret; + struct iio_dev *indio_dev; + + 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->spi = spi; + mutex_init(&st->lock); + + st->thermistor_term_en = + device_property_read_bool(dev, "adi,thermistor-termination"); + + if (device_property_present(dev, "adi,acquisition-time-ns")) { + u32 val; + + ret = device_property_read_u32(dev, "adi,acquisition-time-ns", &val); + if (ret) + return ret; + + switch (val) { + case 400: + st->acquisition_time = AD7280A_CTRL_LB_ACQ_TIME_400ns; + break; + case 800: + st->acquisition_time = AD7280A_CTRL_LB_ACQ_TIME_800ns; + break; + case 1200: + st->acquisition_time = AD7280A_CTRL_LB_ACQ_TIME_1200ns; + break; + case 1600: + st->acquisition_time = AD7280A_CTRL_LB_ACQ_TIME_1600ns; + break; + default: + dev_err(dev, "Firmware provided acquisition time is invalid\n"); + return -EINVAL; + } + } else { + st->acquisition_time = AD7280A_CTRL_LB_ACQ_TIME_400ns; + } + + /* Alert masks are intended for when particular inputs are not wired up */ + if (device_property_present(dev, "adi,voltage-alert-last-chan")) { + u32 val; + + ret = device_property_read_u32(dev, "adi,voltage-alert-last-chan", &val); + if (ret) + return ret; + + switch (val) { + case 3: + st->chain_last_alert_ignore |= AD7280A_ALERT_REMOVE_VIN4_VIN5; + break; + case 4: + st->chain_last_alert_ignore |= AD7280A_ALERT_REMOVE_VIN5; + break; + case 5: + break; + default: + dev_err(dev, + "Firmware provided last voltage alert channel invalid\n"); + break; + } + } + crc8_populate_msb(st->crc_tab, POLYNOM); + + st->spi->max_speed_hz = AD7280A_MAX_SPI_CLK_HZ; + st->spi->mode = SPI_MODE_1; + spi_setup(st->spi); + + st->ctrl_lb = FIELD_PREP(AD7280A_CTRL_LB_ACQ_TIME_MSK, st->acquisition_time) | + FIELD_PREP(AD7280A_CTRL_LB_THERMISTOR_MSK, st->thermistor_term_en); + st->oversampling_ratio = 0; /* No oversampling */ + + ret = ad7280_chain_setup(st); + if (ret < 0) + return ret; + + st->slave_num = ret; + st->scan_cnt = (st->slave_num + 1) * AD7280A_NUM_CH; + st->cell_threshhigh = 0xFF; + st->aux_threshhigh = 0xFF; + + ret = devm_add_action_or_reset(dev, ad7280_sw_power_down, st); + if (ret) + return ret; + + ad7280_update_delay(st); + + indio_dev->name = spi_get_device_id(spi)->name; + indio_dev->modes = INDIO_DIRECT_MODE; + + ret = ad7280_channel_init(st, spi->irq > 0); + if (ret < 0) + return ret; + + indio_dev->num_channels = ret; + indio_dev->channels = st->channels; + if (spi->irq > 0) { + ret = ad7280_write(st, AD7280A_DEVADDR_MASTER, + AD7280A_ALERT_REG, 1, + AD7280A_ALERT_RELAY_SIG_CHAIN_DOWN); + if (ret) + return ret; + + ret = ad7280_write(st, ad7280a_devaddr(st->slave_num), + AD7280A_ALERT_REG, 0, + AD7280A_ALERT_GEN_STATIC_HIGH | + FIELD_PREP(AD7280A_ALERT_REMOVE_MSK, + st->chain_last_alert_ignore)); + if (ret) + return ret; + + ret = devm_request_threaded_irq(dev, spi->irq, + NULL, + ad7280_event_handler, + IRQF_TRIGGER_FALLING | + IRQF_ONESHOT, + indio_dev->name, + indio_dev); + if (ret) + return ret; + + indio_dev->info = &ad7280_info; + } else { + indio_dev->info = &ad7280_info_no_irq; + } + + return devm_iio_device_register(dev, indio_dev); +} + +static const struct spi_device_id ad7280_id[] = { + {"ad7280a", 0}, + {} +}; +MODULE_DEVICE_TABLE(spi, ad7280_id); + +static struct spi_driver ad7280_driver = { + .driver = { + .name = "ad7280", + }, + .probe = ad7280_probe, + .id_table = ad7280_id, +}; +module_spi_driver(ad7280_driver); + +MODULE_AUTHOR("Michael Hennerich <michael.hennerich@analog.com>"); +MODULE_DESCRIPTION("Analog Devices AD7280A"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/iio/adc/ad7606.c b/drivers/iio/adc/ad7606.c index 0a60ecc69d38..3b193dc26438 100644 --- a/drivers/iio/adc/ad7606.c +++ b/drivers/iio/adc/ad7606.c @@ -693,7 +693,7 @@ int ad7606_probe(struct device *dev, int irq, void __iomem *base_address, return devm_iio_device_register(dev, indio_dev); } -EXPORT_SYMBOL_GPL(ad7606_probe); +EXPORT_SYMBOL_NS_GPL(ad7606_probe, IIO_AD7606); #ifdef CONFIG_PM_SLEEP @@ -725,7 +725,7 @@ static int ad7606_resume(struct device *dev) } SIMPLE_DEV_PM_OPS(ad7606_pm_ops, ad7606_suspend, ad7606_resume); -EXPORT_SYMBOL_GPL(ad7606_pm_ops); +EXPORT_SYMBOL_NS_GPL(ad7606_pm_ops, IIO_AD7606); #endif diff --git a/drivers/iio/adc/ad7606_par.c b/drivers/iio/adc/ad7606_par.c index f732b3ac7878..8888e56b5e90 100644 --- a/drivers/iio/adc/ad7606_par.c +++ b/drivers/iio/adc/ad7606_par.c @@ -101,3 +101,4 @@ module_platform_driver(ad7606_driver); MODULE_AUTHOR("Michael Hennerich <michael.hennerich@analog.com>"); MODULE_DESCRIPTION("Analog Devices AD7606 ADC"); MODULE_LICENSE("GPL v2"); +MODULE_IMPORT_NS(IIO_AD7606); diff --git a/drivers/iio/adc/ad7606_spi.c b/drivers/iio/adc/ad7606_spi.c index 29945ad07dca..263a778bcf25 100644 --- a/drivers/iio/adc/ad7606_spi.c +++ b/drivers/iio/adc/ad7606_spi.c @@ -362,3 +362,4 @@ module_spi_driver(ad7606_driver); MODULE_AUTHOR("Michael Hennerich <michael.hennerich@analog.com>"); MODULE_DESCRIPTION("Analog Devices AD7606 ADC"); MODULE_LICENSE("GPL v2"); +MODULE_IMPORT_NS(IIO_AD7606); diff --git a/drivers/iio/adc/ad7780.c b/drivers/iio/adc/ad7780.c index b6e8c8abf6f4..a813fe04787c 100644 --- a/drivers/iio/adc/ad7780.c +++ b/drivers/iio/adc/ad7780.c @@ -375,3 +375,4 @@ module_spi_driver(ad7780_driver); MODULE_AUTHOR("Michael Hennerich <michael.hennerich@analog.com>"); MODULE_DESCRIPTION("Analog Devices AD7780 and similar ADCs"); MODULE_LICENSE("GPL v2"); +MODULE_IMPORT_NS(IIO_AD_SIGMA_DELTA); diff --git a/drivers/iio/adc/ad7791.c b/drivers/iio/adc/ad7791.c index cb579aa89f39..fee8d129a5f0 100644 --- a/drivers/iio/adc/ad7791.c +++ b/drivers/iio/adc/ad7791.c @@ -474,3 +474,4 @@ module_spi_driver(ad7791_driver); MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>"); MODULE_DESCRIPTION("Analog Devices AD7787/AD7788/AD7789/AD7790/AD7791 ADC driver"); MODULE_LICENSE("GPL v2"); +MODULE_IMPORT_NS(IIO_AD_SIGMA_DELTA); diff --git a/drivers/iio/adc/ad7793.c b/drivers/iio/adc/ad7793.c index 0e7ab3fb072a..5f8cb9aaac70 100644 --- a/drivers/iio/adc/ad7793.c +++ b/drivers/iio/adc/ad7793.c @@ -867,3 +867,4 @@ module_spi_driver(ad7793_driver); MODULE_AUTHOR("Michael Hennerich <michael.hennerich@analog.com>"); MODULE_DESCRIPTION("Analog Devices AD7793 and similar ADCs"); MODULE_LICENSE("GPL v2"); +MODULE_IMPORT_NS(IIO_AD_SIGMA_DELTA); diff --git a/drivers/iio/adc/ad_sigma_delta.c b/drivers/iio/adc/ad_sigma_delta.c index cd418bd8bd87..ebcd52526cac 100644 --- a/drivers/iio/adc/ad_sigma_delta.c +++ b/drivers/iio/adc/ad_sigma_delta.c @@ -42,7 +42,7 @@ void ad_sd_set_comm(struct ad_sigma_delta *sigma_delta, uint8_t comm) * to select the channel */ sigma_delta->comm = comm & AD_SD_COMM_CHAN_MASK; } -EXPORT_SYMBOL_GPL(ad_sd_set_comm); +EXPORT_SYMBOL_NS_GPL(ad_sd_set_comm, IIO_AD_SIGMA_DELTA); /** * ad_sd_write_reg() - Write a register @@ -94,7 +94,7 @@ int ad_sd_write_reg(struct ad_sigma_delta *sigma_delta, unsigned int reg, return ret; } -EXPORT_SYMBOL_GPL(ad_sd_write_reg); +EXPORT_SYMBOL_NS_GPL(ad_sd_write_reg, IIO_AD_SIGMA_DELTA); static int ad_sd_read_reg_raw(struct ad_sigma_delta *sigma_delta, unsigned int reg, unsigned int size, uint8_t *val) @@ -171,7 +171,7 @@ int ad_sd_read_reg(struct ad_sigma_delta *sigma_delta, out: return ret; } -EXPORT_SYMBOL_GPL(ad_sd_read_reg); +EXPORT_SYMBOL_NS_GPL(ad_sd_read_reg, IIO_AD_SIGMA_DELTA); /** * ad_sd_reset() - Reset the serial interface @@ -199,7 +199,7 @@ int ad_sd_reset(struct ad_sigma_delta *sigma_delta, return ret; } -EXPORT_SYMBOL_GPL(ad_sd_reset); +EXPORT_SYMBOL_NS_GPL(ad_sd_reset, IIO_AD_SIGMA_DELTA); int ad_sd_calibrate(struct ad_sigma_delta *sigma_delta, unsigned int mode, unsigned int channel) @@ -238,7 +238,7 @@ out: return ret; } -EXPORT_SYMBOL_GPL(ad_sd_calibrate); +EXPORT_SYMBOL_NS_GPL(ad_sd_calibrate, IIO_AD_SIGMA_DELTA); /** * ad_sd_calibrate_all() - Performs channel calibration @@ -262,7 +262,7 @@ int ad_sd_calibrate_all(struct ad_sigma_delta *sigma_delta, return 0; } -EXPORT_SYMBOL_GPL(ad_sd_calibrate_all); +EXPORT_SYMBOL_NS_GPL(ad_sd_calibrate_all, IIO_AD_SIGMA_DELTA); /** * ad_sigma_delta_single_conversion() - Performs a single data conversion @@ -337,7 +337,7 @@ out: return IIO_VAL_INT; } -EXPORT_SYMBOL_GPL(ad_sigma_delta_single_conversion); +EXPORT_SYMBOL_NS_GPL(ad_sigma_delta_single_conversion, IIO_AD_SIGMA_DELTA); static int ad_sd_buffer_postenable(struct iio_dev *indio_dev) { @@ -465,7 +465,7 @@ int ad_sd_validate_trigger(struct iio_dev *indio_dev, struct iio_trigger *trig) return 0; } -EXPORT_SYMBOL_GPL(ad_sd_validate_trigger); +EXPORT_SYMBOL_NS_GPL(ad_sd_validate_trigger, IIO_AD_SIGMA_DELTA); static int devm_ad_sd_probe_trigger(struct device *dev, struct iio_dev *indio_dev) { @@ -524,7 +524,7 @@ int devm_ad_sd_setup_buffer_and_trigger(struct device *dev, struct iio_dev *indi return devm_ad_sd_probe_trigger(dev, indio_dev); } -EXPORT_SYMBOL_GPL(devm_ad_sd_setup_buffer_and_trigger); +EXPORT_SYMBOL_NS_GPL(devm_ad_sd_setup_buffer_and_trigger, IIO_AD_SIGMA_DELTA); /** * ad_sd_init() - Initializes a ad_sigma_delta struct @@ -545,7 +545,7 @@ int ad_sd_init(struct ad_sigma_delta *sigma_delta, struct iio_dev *indio_dev, return 0; } -EXPORT_SYMBOL_GPL(ad_sd_init); +EXPORT_SYMBOL_NS_GPL(ad_sd_init, IIO_AD_SIGMA_DELTA); MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>"); MODULE_DESCRIPTION("Analog Devices Sigma-Delta ADCs"); diff --git a/drivers/iio/adc/aspeed_adc.c b/drivers/iio/adc/aspeed_adc.c index e939b84cbb56..0793d2474cdc 100644 --- a/drivers/iio/adc/aspeed_adc.c +++ b/drivers/iio/adc/aspeed_adc.c @@ -539,7 +539,9 @@ static int aspeed_adc_probe(struct platform_device *pdev) data->clk_scaler = devm_clk_hw_register_divider( &pdev->dev, clk_name, clk_parent_name, scaler_flags, data->base + ASPEED_REG_CLOCK_CONTROL, 0, - data->model_data->scaler_bit_width, 0, &data->clk_lock); + data->model_data->scaler_bit_width, + data->model_data->need_prescaler ? CLK_DIVIDER_ONE_BASED : 0, + &data->clk_lock); if (IS_ERR(data->clk_scaler)) return PTR_ERR(data->clk_scaler); diff --git a/drivers/iio/adc/at91_adc.c b/drivers/iio/adc/at91_adc.c index 5a7d3a3a5fa8..532daaa6f943 100644 --- a/drivers/iio/adc/at91_adc.c +++ b/drivers/iio/adc/at91_adc.c @@ -1234,7 +1234,6 @@ static int at91_adc_remove(struct platform_device *pdev) return 0; } -#ifdef CONFIG_PM_SLEEP static int at91_adc_suspend(struct device *dev) { struct iio_dev *idev = dev_get_drvdata(dev); @@ -1256,9 +1255,9 @@ static int at91_adc_resume(struct device *dev) return 0; } -#endif -static SIMPLE_DEV_PM_OPS(at91_adc_pm_ops, at91_adc_suspend, at91_adc_resume); +static DEFINE_SIMPLE_DEV_PM_OPS(at91_adc_pm_ops, at91_adc_suspend, + at91_adc_resume); static const struct at91_adc_trigger at91sam9260_triggers[] = { { .name = "timer-counter-0", .value = 0x1 }, @@ -1386,7 +1385,7 @@ static struct platform_driver at91_adc_driver = { .driver = { .name = DRIVER_NAME, .of_match_table = at91_adc_dt_ids, - .pm = &at91_adc_pm_ops, + .pm = pm_sleep_ptr(&at91_adc_pm_ops), }, }; diff --git a/drivers/iio/adc/cpcap-adc.c b/drivers/iio/adc/cpcap-adc.c index 40e59f4c95bc..b6c4ef70484e 100644 --- a/drivers/iio/adc/cpcap-adc.c +++ b/drivers/iio/adc/cpcap-adc.c @@ -474,7 +474,7 @@ static int cpcap_adc_calibrate_one(struct cpcap_adc *ddata, for (i = 0; i < CPCAP_ADC_MAX_RETRIES; i++) { calibration_data[0] = 0; calibration_data[1] = 0; - cal_data_diff = 0; + cpcap_adc_setup_calibrate(ddata, channel); error = regmap_read(ddata->reg, calibration_register, &calibration_data[0]); diff --git a/drivers/iio/adc/exynos_adc.c b/drivers/iio/adc/exynos_adc.c index 3b3868aa2533..cff1ba57fb16 100644 --- a/drivers/iio/adc/exynos_adc.c +++ b/drivers/iio/adc/exynos_adc.c @@ -968,7 +968,6 @@ static int exynos_adc_remove(struct platform_device *pdev) return 0; } -#ifdef CONFIG_PM_SLEEP static int exynos_adc_suspend(struct device *dev) { struct iio_dev *indio_dev = dev_get_drvdata(dev); @@ -1001,11 +1000,9 @@ static int exynos_adc_resume(struct device *dev) return 0; } -#endif -static SIMPLE_DEV_PM_OPS(exynos_adc_pm_ops, - exynos_adc_suspend, - exynos_adc_resume); +static DEFINE_SIMPLE_DEV_PM_OPS(exynos_adc_pm_ops, exynos_adc_suspend, + exynos_adc_resume); static struct platform_driver exynos_adc_driver = { .probe = exynos_adc_probe, @@ -1013,7 +1010,7 @@ static struct platform_driver exynos_adc_driver = { .driver = { .name = "exynos-adc", .of_match_table = exynos_adc_match, - .pm = &exynos_adc_pm_ops, + .pm = pm_sleep_ptr(&exynos_adc_pm_ops), }, }; diff --git a/drivers/iio/adc/hi8435.c b/drivers/iio/adc/hi8435.c index e665e14c6e54..8eb0140df133 100644 --- a/drivers/iio/adc/hi8435.c +++ b/drivers/iio/adc/hi8435.c @@ -529,7 +529,7 @@ static const struct of_device_id hi8435_dt_ids[] = { MODULE_DEVICE_TABLE(of, hi8435_dt_ids); static const struct spi_device_id hi8435_id[] = { - { "hi8435", 0}, + { "hi8435", 0 }, { } }; MODULE_DEVICE_TABLE(spi, hi8435_id); diff --git a/drivers/iio/adc/ina2xx-adc.c b/drivers/iio/adc/ina2xx-adc.c index 4f9992a51e64..8d902a32a0fd 100644 --- a/drivers/iio/adc/ina2xx-adc.c +++ b/drivers/iio/adc/ina2xx-adc.c @@ -539,7 +539,7 @@ static ssize_t ina2xx_allow_async_readout_show(struct device *dev, { struct ina2xx_chip_info *chip = iio_priv(dev_to_iio_dev(dev)); - return sprintf(buf, "%d\n", chip->allow_async_readout); + return sysfs_emit(buf, "%d\n", chip->allow_async_readout); } static ssize_t ina2xx_allow_async_readout_store(struct device *dev, diff --git a/drivers/iio/adc/max9611.c b/drivers/iio/adc/max9611.c index 01a4275e9c46..f982f00303dc 100644 --- a/drivers/iio/adc/max9611.c +++ b/drivers/iio/adc/max9611.c @@ -429,7 +429,7 @@ static ssize_t max9611_shunt_resistor_show(struct device *dev, i = max9611->shunt_resistor_uohm / 1000000; r = max9611->shunt_resistor_uohm % 1000000; - return sprintf(buf, "%u.%06u\n", i, r); + return sysfs_emit(buf, "%u.%06u\n", i, r); } static IIO_DEVICE_ATTR(in_power_shunt_resistor, 0444, diff --git a/drivers/iio/adc/mt6577_auxadc.c b/drivers/iio/adc/mt6577_auxadc.c index d4fccd52ef08..e78c96a185db 100644 --- a/drivers/iio/adc/mt6577_auxadc.c +++ b/drivers/iio/adc/mt6577_auxadc.c @@ -46,6 +46,11 @@ struct mt6577_auxadc_device { const struct mtk_auxadc_compatible *dev_comp; }; +static const struct mtk_auxadc_compatible mt8186_compat = { + .sample_data_cali = false, + .check_global_idle = false, +}; + static const struct mtk_auxadc_compatible mt8173_compat = { .sample_data_cali = false, .check_global_idle = true, @@ -330,11 +335,12 @@ static SIMPLE_DEV_PM_OPS(mt6577_auxadc_pm_ops, mt6577_auxadc_resume); static const struct of_device_id mt6577_auxadc_of_match[] = { - { .compatible = "mediatek,mt2701-auxadc", .data = &mt8173_compat}, - { .compatible = "mediatek,mt2712-auxadc", .data = &mt8173_compat}, - { .compatible = "mediatek,mt7622-auxadc", .data = &mt8173_compat}, - { .compatible = "mediatek,mt8173-auxadc", .data = &mt8173_compat}, - { .compatible = "mediatek,mt6765-auxadc", .data = &mt6765_compat}, + { .compatible = "mediatek,mt2701-auxadc", .data = &mt8173_compat }, + { .compatible = "mediatek,mt2712-auxadc", .data = &mt8173_compat }, + { .compatible = "mediatek,mt7622-auxadc", .data = &mt8173_compat }, + { .compatible = "mediatek,mt8173-auxadc", .data = &mt8173_compat }, + { .compatible = "mediatek,mt8186-auxadc", .data = &mt8186_compat }, + { .compatible = "mediatek,mt6765-auxadc", .data = &mt6765_compat }, { } }; MODULE_DEVICE_TABLE(of, mt6577_auxadc_of_match); diff --git a/drivers/iio/adc/palmas_gpadc.c b/drivers/iio/adc/palmas_gpadc.c index f9c8385c72d3..61e80bf3d05e 100644 --- a/drivers/iio/adc/palmas_gpadc.c +++ b/drivers/iio/adc/palmas_gpadc.c @@ -653,7 +653,6 @@ static int palmas_gpadc_remove(struct platform_device *pdev) return 0; } -#ifdef CONFIG_PM_SLEEP static int palmas_adc_wakeup_configure(struct palmas_gpadc *adc) { int adc_period, conv; @@ -822,12 +821,9 @@ static int palmas_gpadc_resume(struct device *dev) return 0; }; -#endif -static const struct dev_pm_ops palmas_pm_ops = { - SET_SYSTEM_SLEEP_PM_OPS(palmas_gpadc_suspend, - palmas_gpadc_resume) -}; +static DEFINE_SIMPLE_DEV_PM_OPS(palmas_pm_ops, palmas_gpadc_suspend, + palmas_gpadc_resume); static const struct of_device_id of_palmas_gpadc_match_tbl[] = { { .compatible = "ti,palmas-gpadc", }, @@ -840,7 +836,7 @@ static struct platform_driver palmas_gpadc_driver = { .remove = palmas_gpadc_remove, .driver = { .name = MOD_NAME, - .pm = &palmas_pm_ops, + .pm = pm_sleep_ptr(&palmas_pm_ops), .of_match_table = of_palmas_gpadc_match_tbl, }, }; diff --git a/drivers/iio/adc/qcom-pm8xxx-xoadc.c b/drivers/iio/adc/qcom-pm8xxx-xoadc.c index 21d7eff645c3..5e9e56821075 100644 --- a/drivers/iio/adc/qcom-pm8xxx-xoadc.c +++ b/drivers/iio/adc/qcom-pm8xxx-xoadc.c @@ -175,7 +175,7 @@ struct xoadc_channel { const char *datasheet_name; u8 pre_scale_mux:2; u8 amux_channel:4; - const struct vadc_prescale_ratio prescale; + const struct u32_fract prescale; enum iio_chan_type type; enum vadc_scale_fn_type scale_fn_type; u8 amux_ip_rsv:3; @@ -218,7 +218,9 @@ struct xoadc_variant { .datasheet_name = __stringify(_dname), \ .pre_scale_mux = _presmux, \ .amux_channel = _amux, \ - .prescale = { .num = _prenum, .den = _preden }, \ + .prescale = { \ + .numerator = _prenum, .denominator = _preden, \ + }, \ .type = _type, \ .scale_fn_type = _scale, \ .amux_ip_rsv = _amip, \ @@ -809,12 +811,11 @@ static int pm8xxx_xoadc_parse_channel(struct device *dev, BIT(IIO_CHAN_INFO_PROCESSED); iio_chan->indexed = 1; - dev_dbg(dev, "channel [PRESCALE/MUX: %02x AMUX: %02x] \"%s\" " - "ref voltage: %d, decimation %d " - "prescale %d/%d, scale function %d\n", + dev_dbg(dev, + "channel [PRESCALE/MUX: %02x AMUX: %02x] \"%s\" ref voltage: %d, decimation %d prescale %d/%d, scale function %d\n", hwchan->pre_scale_mux, hwchan->amux_channel, ch->name, - ch->amux_ip_rsv, ch->decimation, hwchan->prescale.num, - hwchan->prescale.den, hwchan->scale_fn_type); + ch->amux_ip_rsv, ch->decimation, hwchan->prescale.numerator, + hwchan->prescale.denominator, hwchan->scale_fn_type); return 0; } diff --git a/drivers/iio/adc/qcom-spmi-vadc.c b/drivers/iio/adc/qcom-spmi-vadc.c index 07b1a99381d9..34202ba52469 100644 --- a/drivers/iio/adc/qcom-spmi-vadc.c +++ b/drivers/iio/adc/qcom-spmi-vadc.c @@ -122,15 +122,15 @@ struct vadc_priv { struct mutex lock; }; -static const struct vadc_prescale_ratio vadc_prescale_ratios[] = { - {.num = 1, .den = 1}, - {.num = 1, .den = 3}, - {.num = 1, .den = 4}, - {.num = 1, .den = 6}, - {.num = 1, .den = 20}, - {.num = 1, .den = 8}, - {.num = 10, .den = 81}, - {.num = 1, .den = 10} +static const struct u32_fract vadc_prescale_ratios[] = { + { .numerator = 1, .denominator = 1 }, + { .numerator = 1, .denominator = 3 }, + { .numerator = 1, .denominator = 4 }, + { .numerator = 1, .denominator = 6 }, + { .numerator = 1, .denominator = 20 }, + { .numerator = 1, .denominator = 8 }, + { .numerator = 10, .denominator = 81 }, + { .numerator = 1, .denominator = 10 }, }; static int vadc_read(struct vadc_priv *vadc, u16 offset, u8 *data) @@ -404,13 +404,13 @@ err: return ret; } -static int vadc_prescaling_from_dt(u32 num, u32 den) +static int vadc_prescaling_from_dt(u32 numerator, u32 denominator) { unsigned int pre; for (pre = 0; pre < ARRAY_SIZE(vadc_prescale_ratios); pre++) - if (vadc_prescale_ratios[pre].num == num && - vadc_prescale_ratios[pre].den == den) + if (vadc_prescale_ratios[pre].numerator == numerator && + vadc_prescale_ratios[pre].denominator == denominator) break; if (pre == ARRAY_SIZE(vadc_prescale_ratios)) diff --git a/drivers/iio/adc/qcom-vadc-common.c b/drivers/iio/adc/qcom-vadc-common.c index 14723896aab2..6c6aec848f98 100644 --- a/drivers/iio/adc/qcom-vadc-common.c +++ b/drivers/iio/adc/qcom-vadc-common.c @@ -289,44 +289,44 @@ static const struct vadc_map_pt adcmap7_100k[] = { { 2420, 130048 } }; -static const struct vadc_prescale_ratio adc5_prescale_ratios[] = { - {.num = 1, .den = 1}, - {.num = 1, .den = 3}, - {.num = 1, .den = 4}, - {.num = 1, .den = 6}, - {.num = 1, .den = 20}, - {.num = 1, .den = 8}, - {.num = 10, .den = 81}, - {.num = 1, .den = 10}, - {.num = 1, .den = 16} +static const struct u32_fract adc5_prescale_ratios[] = { + { .numerator = 1, .denominator = 1 }, + { .numerator = 1, .denominator = 3 }, + { .numerator = 1, .denominator = 4 }, + { .numerator = 1, .denominator = 6 }, + { .numerator = 1, .denominator = 20 }, + { .numerator = 1, .denominator = 8 }, + { .numerator = 10, .denominator = 81 }, + { .numerator = 1, .denominator = 10 }, + { .numerator = 1, .denominator = 16 }, }; static int qcom_vadc_scale_hw_calib_volt( - const struct vadc_prescale_ratio *prescale, + const struct u32_fract *prescale, const struct adc5_data *data, u16 adc_code, int *result_uv); static int qcom_vadc_scale_hw_calib_therm( - const struct vadc_prescale_ratio *prescale, + const struct u32_fract *prescale, const struct adc5_data *data, u16 adc_code, int *result_mdec); static int qcom_vadc7_scale_hw_calib_therm( - const struct vadc_prescale_ratio *prescale, + const struct u32_fract *prescale, const struct adc5_data *data, u16 adc_code, int *result_mdec); static int qcom_vadc_scale_hw_smb_temp( - const struct vadc_prescale_ratio *prescale, + const struct u32_fract *prescale, const struct adc5_data *data, u16 adc_code, int *result_mdec); static int qcom_vadc_scale_hw_chg5_temp( - const struct vadc_prescale_ratio *prescale, + const struct u32_fract *prescale, const struct adc5_data *data, u16 adc_code, int *result_mdec); static int qcom_vadc_scale_hw_calib_die_temp( - const struct vadc_prescale_ratio *prescale, + const struct u32_fract *prescale, const struct adc5_data *data, u16 adc_code, int *result_mdec); static int qcom_vadc7_scale_hw_calib_die_temp( - const struct vadc_prescale_ratio *prescale, + const struct u32_fract *prescale, const struct adc5_data *data, u16 adc_code, int *result_mdec); @@ -406,7 +406,7 @@ static void qcom_vadc_scale_calib(const struct vadc_linear_graph *calib_graph, } static int qcom_vadc_scale_volt(const struct vadc_linear_graph *calib_graph, - const struct vadc_prescale_ratio *prescale, + const struct u32_fract *prescale, bool absolute, u16 adc_code, int *result_uv) { @@ -414,15 +414,15 @@ static int qcom_vadc_scale_volt(const struct vadc_linear_graph *calib_graph, qcom_vadc_scale_calib(calib_graph, adc_code, absolute, &voltage); - voltage = voltage * prescale->den; - result = div64_s64(voltage, prescale->num); + voltage *= prescale->denominator; + result = div64_s64(voltage, prescale->numerator); *result_uv = result; return 0; } static int qcom_vadc_scale_therm(const struct vadc_linear_graph *calib_graph, - const struct vadc_prescale_ratio *prescale, + const struct u32_fract *prescale, bool absolute, u16 adc_code, int *result_mdec) { @@ -444,7 +444,7 @@ static int qcom_vadc_scale_therm(const struct vadc_linear_graph *calib_graph, } static int qcom_vadc_scale_die_temp(const struct vadc_linear_graph *calib_graph, - const struct vadc_prescale_ratio *prescale, + const struct u32_fract *prescale, bool absolute, u16 adc_code, int *result_mdec) { @@ -454,8 +454,8 @@ static int qcom_vadc_scale_die_temp(const struct vadc_linear_graph *calib_graph, qcom_vadc_scale_calib(calib_graph, adc_code, absolute, &voltage); if (voltage > 0) { - temp = voltage * prescale->den; - do_div(temp, prescale->num * 2); + temp = voltage * prescale->denominator; + do_div(temp, prescale->numerator * 2); voltage = temp; } else { voltage = 0; @@ -467,7 +467,7 @@ static int qcom_vadc_scale_die_temp(const struct vadc_linear_graph *calib_graph, } static int qcom_vadc_scale_chg_temp(const struct vadc_linear_graph *calib_graph, - const struct vadc_prescale_ratio *prescale, + const struct u32_fract *prescale, bool absolute, u16 adc_code, int *result_mdec) { @@ -475,8 +475,8 @@ static int qcom_vadc_scale_chg_temp(const struct vadc_linear_graph *calib_graph, qcom_vadc_scale_calib(calib_graph, adc_code, absolute, &voltage); - voltage = voltage * prescale->den; - voltage = div64_s64(voltage, prescale->num); + voltage *= prescale->denominator; + voltage = div64_s64(voltage, prescale->numerator); voltage = ((PMI_CHG_SCALE_1) * (voltage * 2)); voltage = (voltage + PMI_CHG_SCALE_2); result = div64_s64(voltage, 1000000); @@ -487,21 +487,21 @@ static int qcom_vadc_scale_chg_temp(const struct vadc_linear_graph *calib_graph, /* convert voltage to ADC code, using 1.875V reference */ static u16 qcom_vadc_scale_voltage_code(s32 voltage, - const struct vadc_prescale_ratio *prescale, + const struct u32_fract *prescale, const u32 full_scale_code_volt, unsigned int factor) { s64 volt = voltage; s64 adc_vdd_ref_mv = 1875; /* reference voltage */ - volt *= prescale->num * factor * full_scale_code_volt; - volt = div64_s64(volt, (s64)prescale->den * adc_vdd_ref_mv * 1000); + volt *= prescale->numerator * factor * full_scale_code_volt; + volt = div64_s64(volt, (s64)prescale->denominator * adc_vdd_ref_mv * 1000); return volt; } static int qcom_vadc_scale_code_voltage_factor(u16 adc_code, - const struct vadc_prescale_ratio *prescale, + const struct u32_fract *prescale, const struct adc5_data *data, unsigned int factor) { @@ -520,8 +520,8 @@ static int qcom_vadc_scale_code_voltage_factor(u16 adc_code, voltage = (s64) adc_code * adc_vdd_ref_mv * 1000; voltage = div64_s64(voltage, data->full_scale_code_volt); if (voltage > 0) { - voltage *= prescale->den; - temp = prescale->num * factor; + voltage *= prescale->denominator; + temp = prescale->numerator * factor; voltage = div64_s64(voltage, temp); } else { voltage = 0; @@ -531,7 +531,7 @@ static int qcom_vadc_scale_code_voltage_factor(u16 adc_code, } static int qcom_vadc7_scale_hw_calib_therm( - const struct vadc_prescale_ratio *prescale, + const struct u32_fract *prescale, const struct adc5_data *data, u16 adc_code, int *result_mdec) { @@ -557,7 +557,7 @@ static int qcom_vadc7_scale_hw_calib_therm( } static int qcom_vadc_scale_hw_calib_volt( - const struct vadc_prescale_ratio *prescale, + const struct u32_fract *prescale, const struct adc5_data *data, u16 adc_code, int *result_uv) { @@ -568,7 +568,7 @@ static int qcom_vadc_scale_hw_calib_volt( } static int qcom_vadc_scale_hw_calib_therm( - const struct vadc_prescale_ratio *prescale, + const struct u32_fract *prescale, const struct adc5_data *data, u16 adc_code, int *result_mdec) { @@ -584,7 +584,7 @@ static int qcom_vadc_scale_hw_calib_therm( } static int qcom_vadc_scale_hw_calib_die_temp( - const struct vadc_prescale_ratio *prescale, + const struct u32_fract *prescale, const struct adc5_data *data, u16 adc_code, int *result_mdec) { @@ -596,7 +596,7 @@ static int qcom_vadc_scale_hw_calib_die_temp( } static int qcom_vadc7_scale_hw_calib_die_temp( - const struct vadc_prescale_ratio *prescale, + const struct u32_fract *prescale, const struct adc5_data *data, u16 adc_code, int *result_mdec) { @@ -611,7 +611,7 @@ static int qcom_vadc7_scale_hw_calib_die_temp( } static int qcom_vadc_scale_hw_smb_temp( - const struct vadc_prescale_ratio *prescale, + const struct u32_fract *prescale, const struct adc5_data *data, u16 adc_code, int *result_mdec) { @@ -623,7 +623,7 @@ static int qcom_vadc_scale_hw_smb_temp( } static int qcom_vadc_scale_hw_chg5_temp( - const struct vadc_prescale_ratio *prescale, + const struct u32_fract *prescale, const struct adc5_data *data, u16 adc_code, int *result_mdec) { @@ -636,7 +636,7 @@ static int qcom_vadc_scale_hw_chg5_temp( int qcom_vadc_scale(enum vadc_scale_fn_type scaletype, const struct vadc_linear_graph *calib_graph, - const struct vadc_prescale_ratio *prescale, + const struct u32_fract *prescale, bool absolute, u16 adc_code, int *result) { @@ -667,7 +667,7 @@ EXPORT_SYMBOL(qcom_vadc_scale); u16 qcom_adc_tm5_temp_volt_scale(unsigned int prescale_ratio, u32 full_scale_code_volt, int temp) { - const struct vadc_prescale_ratio *prescale = &adc5_prescale_ratios[prescale_ratio]; + const struct u32_fract *prescale = &adc5_prescale_ratios[prescale_ratio]; s32 voltage; voltage = qcom_vadc_map_temp_voltage(adcmap_100k_104ef_104fb_1875_vref, @@ -682,7 +682,7 @@ int qcom_adc5_hw_scale(enum vadc_scale_fn_type scaletype, const struct adc5_data *data, u16 adc_code, int *result) { - const struct vadc_prescale_ratio *prescale = &adc5_prescale_ratios[prescale_ratio]; + const struct u32_fract *prescale = &adc5_prescale_ratios[prescale_ratio]; if (!(scaletype >= SCALE_HW_CALIB_DEFAULT && scaletype < SCALE_HW_CALIB_INVALID)) { @@ -695,13 +695,13 @@ int qcom_adc5_hw_scale(enum vadc_scale_fn_type scaletype, } EXPORT_SYMBOL(qcom_adc5_hw_scale); -int qcom_adc5_prescaling_from_dt(u32 num, u32 den) +int qcom_adc5_prescaling_from_dt(u32 numerator, u32 denominator) { unsigned int pre; for (pre = 0; pre < ARRAY_SIZE(adc5_prescale_ratios); pre++) - if (adc5_prescale_ratios[pre].num == num && - adc5_prescale_ratios[pre].den == den) + if (adc5_prescale_ratios[pre].numerator == numerator && + adc5_prescale_ratios[pre].denominator == denominator) break; if (pre == ARRAY_SIZE(adc5_prescale_ratios)) diff --git a/drivers/iio/adc/rcar-gyroadc.c b/drivers/iio/adc/rcar-gyroadc.c index 727ea6c68049..27d9e147b4b7 100644 --- a/drivers/iio/adc/rcar-gyroadc.c +++ b/drivers/iio/adc/rcar-gyroadc.c @@ -577,7 +577,6 @@ static int rcar_gyroadc_remove(struct platform_device *pdev) return 0; } -#if defined(CONFIG_PM) static int rcar_gyroadc_suspend(struct device *dev) { struct iio_dev *indio_dev = dev_get_drvdata(dev); @@ -597,10 +596,9 @@ static int rcar_gyroadc_resume(struct device *dev) return 0; } -#endif static const struct dev_pm_ops rcar_gyroadc_pm_ops = { - SET_RUNTIME_PM_OPS(rcar_gyroadc_suspend, rcar_gyroadc_resume, NULL) + RUNTIME_PM_OPS(rcar_gyroadc_suspend, rcar_gyroadc_resume, NULL) }; static struct platform_driver rcar_gyroadc_driver = { @@ -609,7 +607,7 @@ static struct platform_driver rcar_gyroadc_driver = { .driver = { .name = DRIVER_NAME, .of_match_table = rcar_gyroadc_match, - .pm = &rcar_gyroadc_pm_ops, + .pm = pm_ptr(&rcar_gyroadc_pm_ops), }, }; diff --git a/drivers/iio/adc/rn5t618-adc.c b/drivers/iio/adc/rn5t618-adc.c index 7d891b4ea461..6bf32907f01d 100644 --- a/drivers/iio/adc/rn5t618-adc.c +++ b/drivers/iio/adc/rn5t618-adc.c @@ -42,11 +42,6 @@ struct rn5t618_adc_data { int irq; }; -struct rn5t618_channel_ratios { - u16 numerator; - u16 denominator; -}; - enum rn5t618_channels { LIMMON = 0, VBAT, @@ -58,7 +53,7 @@ enum rn5t618_channels { AIN0 }; -static const struct rn5t618_channel_ratios rn5t618_ratios[8] = { +static const struct u16_fract rn5t618_ratios[8] = { [LIMMON] = {50, 32}, /* measured across 20mOhm, amplified by 32 */ [VBAT] = {2, 1}, [VADP] = {3, 1}, diff --git a/drivers/iio/adc/rockchip_saradc.c b/drivers/iio/adc/rockchip_saradc.c index 14b8df4ca9c8..b87ea7148b58 100644 --- a/drivers/iio/adc/rockchip_saradc.c +++ b/drivers/iio/adc/rockchip_saradc.c @@ -481,7 +481,6 @@ static int rockchip_saradc_probe(struct platform_device *pdev) return devm_iio_device_register(&pdev->dev, indio_dev); } -#ifdef CONFIG_PM_SLEEP static int rockchip_saradc_suspend(struct device *dev) { struct iio_dev *indio_dev = dev_get_drvdata(dev); @@ -514,17 +513,17 @@ static int rockchip_saradc_resume(struct device *dev) return ret; } -#endif -static SIMPLE_DEV_PM_OPS(rockchip_saradc_pm_ops, - rockchip_saradc_suspend, rockchip_saradc_resume); +static DEFINE_SIMPLE_DEV_PM_OPS(rockchip_saradc_pm_ops, + rockchip_saradc_suspend, + rockchip_saradc_resume); static struct platform_driver rockchip_saradc_driver = { .probe = rockchip_saradc_probe, .driver = { .name = "rockchip-saradc", .of_match_table = rockchip_saradc_match, - .pm = &rockchip_saradc_pm_ops, + .pm = pm_sleep_ptr(&rockchip_saradc_pm_ops), }, }; diff --git a/drivers/iio/adc/rzg2l_adc.c b/drivers/iio/adc/rzg2l_adc.c index 9d5be52bd948..7585144b9715 100644 --- a/drivers/iio/adc/rzg2l_adc.c +++ b/drivers/iio/adc/rzg2l_adc.c @@ -55,7 +55,7 @@ #define RZG2L_ADCR(n) (0x30 + ((n) * 0x4)) #define RZG2L_ADCR_AD_MASK GENMASK(11, 0) -#define RZG2L_ADSMP_DEFUALT_SAMPLING 0x578 +#define RZG2L_ADSMP_DEFAULT_SAMPLING 0x578 #define RZG2L_ADC_MAX_CHANNELS 8 #define RZG2L_ADC_CHN_MASK 0x7 @@ -395,7 +395,7 @@ static int rzg2l_adc_hw_init(struct rzg2l_adc *adc) reg &= ~RZG2L_ADM3_ADIL_MASK; reg &= ~RZG2L_ADM3_ADCMP_MASK; reg &= ~RZG2L_ADM3_ADSMP_MASK; - reg |= (RZG2L_ADM3_ADCMP_E | RZG2L_ADSMP_DEFUALT_SAMPLING); + reg |= (RZG2L_ADM3_ADCMP_E | RZG2L_ADSMP_DEFAULT_SAMPLING); rzg2l_adc_writel(adc, RZG2L_ADM(3), reg); exit_hw_init: diff --git a/drivers/iio/adc/stm32-adc-core.c b/drivers/iio/adc/stm32-adc-core.c index b6e18eb101f7..142656232157 100644 --- a/drivers/iio/adc/stm32-adc-core.c +++ b/drivers/iio/adc/stm32-adc-core.c @@ -763,7 +763,6 @@ static int stm32_adc_remove(struct platform_device *pdev) return 0; } -#if defined(CONFIG_PM) static int stm32_adc_core_runtime_suspend(struct device *dev) { stm32_adc_core_hw_stop(dev); @@ -782,15 +781,11 @@ static int stm32_adc_core_runtime_idle(struct device *dev) return 0; } -#endif - -static const struct dev_pm_ops stm32_adc_core_pm_ops = { - SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, - pm_runtime_force_resume) - SET_RUNTIME_PM_OPS(stm32_adc_core_runtime_suspend, - stm32_adc_core_runtime_resume, - stm32_adc_core_runtime_idle) -}; + +static DEFINE_RUNTIME_DEV_PM_OPS(stm32_adc_core_pm_ops, + stm32_adc_core_runtime_suspend, + stm32_adc_core_runtime_resume, + stm32_adc_core_runtime_idle); static const struct stm32_adc_priv_cfg stm32f4_adc_priv_cfg = { .regs = &stm32f4_adc_common_regs, @@ -836,7 +831,7 @@ static struct platform_driver stm32_adc_driver = { .driver = { .name = "stm32-adc-core", .of_match_table = stm32_adc_of_match, - .pm = &stm32_adc_core_pm_ops, + .pm = pm_ptr(&stm32_adc_core_pm_ops), }, }; module_platform_driver(stm32_adc_driver); diff --git a/drivers/iio/adc/stm32-adc.c b/drivers/iio/adc/stm32-adc.c index 897166d9e45c..a68ecbda6480 100644 --- a/drivers/iio/adc/stm32-adc.c +++ b/drivers/iio/adc/stm32-adc.c @@ -2352,7 +2352,6 @@ static int stm32_adc_remove(struct platform_device *pdev) return 0; } -#if defined(CONFIG_PM_SLEEP) static int stm32_adc_suspend(struct device *dev) { struct iio_dev *indio_dev = dev_get_drvdata(dev); @@ -2382,9 +2381,7 @@ static int stm32_adc_resume(struct device *dev) return stm32_adc_buffer_postenable(indio_dev); } -#endif -#if defined(CONFIG_PM) static int stm32_adc_runtime_suspend(struct device *dev) { return stm32_adc_hw_stop(dev); @@ -2394,12 +2391,11 @@ static int stm32_adc_runtime_resume(struct device *dev) { return stm32_adc_hw_start(dev); } -#endif static const struct dev_pm_ops stm32_adc_pm_ops = { - SET_SYSTEM_SLEEP_PM_OPS(stm32_adc_suspend, stm32_adc_resume) - SET_RUNTIME_PM_OPS(stm32_adc_runtime_suspend, stm32_adc_runtime_resume, - NULL) + SYSTEM_SLEEP_PM_OPS(stm32_adc_suspend, stm32_adc_resume) + RUNTIME_PM_OPS(stm32_adc_runtime_suspend, stm32_adc_runtime_resume, + NULL) }; static const struct stm32_adc_cfg stm32f4_adc_cfg = { @@ -2453,7 +2449,7 @@ static struct platform_driver stm32_adc_driver = { .driver = { .name = "stm32-adc", .of_match_table = stm32_adc_of_match, - .pm = &stm32_adc_pm_ops, + .pm = pm_ptr(&stm32_adc_pm_ops), }, }; module_platform_driver(stm32_adc_driver); diff --git a/drivers/iio/adc/stm32-dfsdm-adc.c b/drivers/iio/adc/stm32-dfsdm-adc.c index 1cfefb3b5e56..9704cf0b9753 100644 --- a/drivers/iio/adc/stm32-dfsdm-adc.c +++ b/drivers/iio/adc/stm32-dfsdm-adc.c @@ -1632,7 +1632,7 @@ static int stm32_dfsdm_adc_remove(struct platform_device *pdev) return 0; } -static int __maybe_unused stm32_dfsdm_adc_suspend(struct device *dev) +static int stm32_dfsdm_adc_suspend(struct device *dev) { struct iio_dev *indio_dev = dev_get_drvdata(dev); @@ -1642,7 +1642,7 @@ static int __maybe_unused stm32_dfsdm_adc_suspend(struct device *dev) return 0; } -static int __maybe_unused stm32_dfsdm_adc_resume(struct device *dev) +static int stm32_dfsdm_adc_resume(struct device *dev) { struct iio_dev *indio_dev = dev_get_drvdata(dev); struct stm32_dfsdm_adc *adc = iio_priv(indio_dev); @@ -1665,14 +1665,15 @@ static int __maybe_unused stm32_dfsdm_adc_resume(struct device *dev) return 0; } -static SIMPLE_DEV_PM_OPS(stm32_dfsdm_adc_pm_ops, - stm32_dfsdm_adc_suspend, stm32_dfsdm_adc_resume); +static DEFINE_SIMPLE_DEV_PM_OPS(stm32_dfsdm_adc_pm_ops, + stm32_dfsdm_adc_suspend, + stm32_dfsdm_adc_resume); static struct platform_driver stm32_dfsdm_adc_driver = { .driver = { .name = "stm32-dfsdm-adc", .of_match_table = stm32_dfsdm_adc_match, - .pm = &stm32_dfsdm_adc_pm_ops, + .pm = pm_sleep_ptr(&stm32_dfsdm_adc_pm_ops), }, .probe = stm32_dfsdm_adc_probe, .remove = stm32_dfsdm_adc_remove, diff --git a/drivers/iio/adc/stm32-dfsdm-core.c b/drivers/iio/adc/stm32-dfsdm-core.c index a627af9a825e..a3d4de6ba4c2 100644 --- a/drivers/iio/adc/stm32-dfsdm-core.c +++ b/drivers/iio/adc/stm32-dfsdm-core.c @@ -381,7 +381,7 @@ static int stm32_dfsdm_core_remove(struct platform_device *pdev) return 0; } -static int __maybe_unused stm32_dfsdm_core_suspend(struct device *dev) +static int stm32_dfsdm_core_suspend(struct device *dev) { struct stm32_dfsdm *dfsdm = dev_get_drvdata(dev); struct dfsdm_priv *priv = to_stm32_dfsdm_priv(dfsdm); @@ -397,7 +397,7 @@ static int __maybe_unused stm32_dfsdm_core_suspend(struct device *dev) return pinctrl_pm_select_sleep_state(dev); } -static int __maybe_unused stm32_dfsdm_core_resume(struct device *dev) +static int stm32_dfsdm_core_resume(struct device *dev) { struct stm32_dfsdm *dfsdm = dev_get_drvdata(dev); struct dfsdm_priv *priv = to_stm32_dfsdm_priv(dfsdm); @@ -414,7 +414,7 @@ static int __maybe_unused stm32_dfsdm_core_resume(struct device *dev) return pm_runtime_force_resume(dev); } -static int __maybe_unused stm32_dfsdm_core_runtime_suspend(struct device *dev) +static int stm32_dfsdm_core_runtime_suspend(struct device *dev) { struct stm32_dfsdm *dfsdm = dev_get_drvdata(dev); @@ -423,7 +423,7 @@ static int __maybe_unused stm32_dfsdm_core_runtime_suspend(struct device *dev) return 0; } -static int __maybe_unused stm32_dfsdm_core_runtime_resume(struct device *dev) +static int stm32_dfsdm_core_runtime_resume(struct device *dev) { struct stm32_dfsdm *dfsdm = dev_get_drvdata(dev); @@ -431,11 +431,10 @@ static int __maybe_unused stm32_dfsdm_core_runtime_resume(struct device *dev) } static const struct dev_pm_ops stm32_dfsdm_core_pm_ops = { - SET_SYSTEM_SLEEP_PM_OPS(stm32_dfsdm_core_suspend, - stm32_dfsdm_core_resume) - SET_RUNTIME_PM_OPS(stm32_dfsdm_core_runtime_suspend, - stm32_dfsdm_core_runtime_resume, - NULL) + SYSTEM_SLEEP_PM_OPS(stm32_dfsdm_core_suspend, stm32_dfsdm_core_resume) + RUNTIME_PM_OPS(stm32_dfsdm_core_runtime_suspend, + stm32_dfsdm_core_runtime_resume, + NULL) }; static struct platform_driver stm32_dfsdm_driver = { @@ -444,7 +443,7 @@ static struct platform_driver stm32_dfsdm_driver = { .driver = { .name = "stm32-dfsdm", .of_match_table = stm32_dfsdm_of_match, - .pm = &stm32_dfsdm_core_pm_ops, + .pm = pm_ptr(&stm32_dfsdm_core_pm_ops), }, }; diff --git a/drivers/iio/adc/ti-adc084s021.c b/drivers/iio/adc/ti-adc084s021.c index ce3f5a3814f9..c9b5d9aec3dc 100644 --- a/drivers/iio/adc/ti-adc084s021.c +++ b/drivers/iio/adc/ti-adc084s021.c @@ -248,7 +248,7 @@ static const struct of_device_id adc084s021_of_match[] = { MODULE_DEVICE_TABLE(of, adc084s021_of_match); static const struct spi_device_id adc084s021_id[] = { - { ADC084S021_DRIVER_NAME, 0}, + { ADC084S021_DRIVER_NAME, 0 }, {} }; MODULE_DEVICE_TABLE(spi, adc084s021_id); diff --git a/drivers/iio/adc/ti-tsc2046.c b/drivers/iio/adc/ti-tsc2046.c index e8fc4d01f30b..55b35570ad8b 100644 --- a/drivers/iio/adc/ti-tsc2046.c +++ b/drivers/iio/adc/ti-tsc2046.c @@ -82,6 +82,11 @@ #define TI_TSC2046_DATA_12BIT GENMASK(14, 3) #define TI_TSC2046_MAX_CHAN 8 +#define TI_TSC2046_MIN_POLL_CNT 3 +#define TI_TSC2046_EXT_POLL_CNT 3 +#define TI_TSC2046_POLL_CNT \ + (TI_TSC2046_MIN_POLL_CNT + TI_TSC2046_EXT_POLL_CNT) +#define TI_TSC2046_INT_VREF 2500 /* Represents a HW sample */ struct tsc2046_adc_atom { @@ -123,14 +128,23 @@ struct tsc2046_adc_ch_cfg { unsigned int oversampling_ratio; }; +enum tsc2046_state { + TSC2046_STATE_SHUTDOWN, + TSC2046_STATE_STANDBY, + TSC2046_STATE_POLL, + TSC2046_STATE_POLL_IRQ_DISABLE, + TSC2046_STATE_ENABLE_IRQ, +}; + struct tsc2046_adc_priv { struct spi_device *spi; const struct tsc2046_adc_dcfg *dcfg; struct iio_trigger *trig; struct hrtimer trig_timer; - spinlock_t trig_lock; - unsigned int trig_more_count; + enum tsc2046_state state; + int poll_cnt; + spinlock_t state_lock; struct spi_transfer xfer; struct spi_message msg; @@ -153,9 +167,6 @@ struct tsc2046_adc_priv { struct tsc2046_adc_atom *rx; struct tsc2046_adc_atom *tx; - struct tsc2046_adc_atom *rx_one; - struct tsc2046_adc_atom *tx_one; - unsigned int count; unsigned int groups; u32 effective_speed_hz; @@ -171,6 +182,8 @@ struct tsc2046_adc_priv { .type = IIO_VOLTAGE, \ .indexed = 1, \ .channel = index, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ .datasheet_name = "#name", \ .scan_index = index, \ .scan_type = { \ @@ -234,6 +247,14 @@ static u8 tsc2046_adc_get_cmd(struct tsc2046_adc_priv *priv, int ch_idx, else pd = 0; + switch (ch_idx) { + case TI_TSC2046_ADDR_TEMP1: + case TI_TSC2046_ADDR_AUX: + case TI_TSC2046_ADDR_VBAT: + case TI_TSC2046_ADDR_TEMP0: + pd |= TI_TSC2046_SER | TI_TSC2046_PD1_VREF_ON; + } + return TI_TSC2046_START | FIELD_PREP(TI_TSC2046_ADDR, ch_idx) | pd; } @@ -245,16 +266,50 @@ static u16 tsc2046_adc_get_value(struct tsc2046_adc_atom *buf) static int tsc2046_adc_read_one(struct tsc2046_adc_priv *priv, int ch_idx, u32 *effective_speed_hz) { + struct tsc2046_adc_ch_cfg *ch = &priv->ch_cfg[ch_idx]; + struct tsc2046_adc_atom *rx_buf, *tx_buf; + unsigned int val, val_normalized = 0; + int ret, i, count_skip = 0, max_count; struct spi_transfer xfer; struct spi_message msg; - int ret; + u8 cmd; + + if (!effective_speed_hz) { + count_skip = tsc2046_adc_time_to_count(priv, ch->settling_time_us); + max_count = count_skip + ch->oversampling_ratio; + } else { + max_count = 1; + } + + if (sizeof(*tx_buf) * max_count > PAGE_SIZE) + return -ENOSPC; + + tx_buf = kcalloc(max_count, sizeof(*tx_buf), GFP_KERNEL); + if (!tx_buf) + return -ENOMEM; + + rx_buf = kcalloc(max_count, sizeof(*rx_buf), GFP_KERNEL); + if (!rx_buf) { + ret = -ENOMEM; + goto free_tx; + } + + /* + * Do not enable automatic power down on working samples. Otherwise the + * plates will never be completely charged. + */ + cmd = tsc2046_adc_get_cmd(priv, ch_idx, true); + + for (i = 0; i < max_count - 1; i++) + tx_buf[i].cmd = cmd; + + /* automatically power down on last sample */ + tx_buf[i].cmd = tsc2046_adc_get_cmd(priv, ch_idx, false); memset(&xfer, 0, sizeof(xfer)); - priv->tx_one->cmd = tsc2046_adc_get_cmd(priv, ch_idx, false); - priv->tx_one->data = 0; - xfer.tx_buf = priv->tx_one; - xfer.rx_buf = priv->rx_one; - xfer.len = sizeof(*priv->tx_one); + xfer.tx_buf = tx_buf; + xfer.rx_buf = rx_buf; + xfer.len = sizeof(*tx_buf) * max_count; spi_message_init_with_transfers(&msg, &xfer, 1); /* @@ -265,13 +320,25 @@ static int tsc2046_adc_read_one(struct tsc2046_adc_priv *priv, int ch_idx, if (ret) { dev_err_ratelimited(&priv->spi->dev, "SPI transfer failed %pe\n", ERR_PTR(ret)); - return ret; + goto free_bufs; } if (effective_speed_hz) *effective_speed_hz = xfer.effective_speed_hz; - return tsc2046_adc_get_value(priv->rx_one); + for (i = 0; i < max_count - count_skip; i++) { + val = tsc2046_adc_get_value(&rx_buf[count_skip + i]); + val_normalized += val; + } + + ret = DIV_ROUND_UP(val_normalized, max_count - count_skip); + +free_bufs: + kfree(rx_buf); +free_tx: + kfree(tx_buf); + + return ret; } static size_t tsc2046_adc_group_set_layout(struct tsc2046_adc_priv *priv, @@ -378,6 +445,37 @@ static irqreturn_t tsc2046_adc_trigger_handler(int irq, void *p) return IRQ_HANDLED; } +static int tsc2046_adc_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, int *val2, long m) +{ + struct tsc2046_adc_priv *priv = iio_priv(indio_dev); + int ret; + + switch (m) { + case IIO_CHAN_INFO_RAW: + ret = tsc2046_adc_read_one(priv, chan->channel, NULL); + if (ret < 0) + return ret; + + *val = ret; + + return IIO_VAL_INT; + case IIO_CHAN_INFO_SCALE: + /* + * Note: the TSC2046 has internal voltage divider on the VBAT + * line. This divider can be influenced by external divider. + * So, it is better to use external voltage-divider driver + * instead, which is calculating complete chain. + */ + *val = TI_TSC2046_INT_VREF; + *val2 = chan->scan_type.realbits; + return IIO_VAL_FRACTIONAL_LOG2; + } + + return -EINVAL; +} + static int tsc2046_adc_update_scan_mode(struct iio_dev *indio_dev, const unsigned long *active_scan_mask) { @@ -408,24 +506,67 @@ static int tsc2046_adc_update_scan_mode(struct iio_dev *indio_dev, } static const struct iio_info tsc2046_adc_info = { + .read_raw = tsc2046_adc_read_raw, .update_scan_mode = tsc2046_adc_update_scan_mode, }; -static enum hrtimer_restart tsc2046_adc_trig_more(struct hrtimer *hrtimer) +static enum hrtimer_restart tsc2046_adc_timer(struct hrtimer *hrtimer) { struct tsc2046_adc_priv *priv = container_of(hrtimer, struct tsc2046_adc_priv, trig_timer); unsigned long flags; - spin_lock_irqsave(&priv->trig_lock, flags); - - disable_irq_nosync(priv->spi->irq); - - priv->trig_more_count++; - iio_trigger_poll(priv->trig); + /* + * This state machine should address following challenges : + * - the interrupt source is based on level shifter attached to the X + * channel of ADC. It will change the state every time we switch + * between channels. So, we need to disable IRQ if we do + * iio_trigger_poll(). + * - we should do iio_trigger_poll() at some reduced sample rate + * - we should still trigger for some amount of time after last + * interrupt with enabled IRQ was processed. + */ - spin_unlock_irqrestore(&priv->trig_lock, flags); + spin_lock_irqsave(&priv->state_lock, flags); + switch (priv->state) { + case TSC2046_STATE_ENABLE_IRQ: + if (priv->poll_cnt < TI_TSC2046_POLL_CNT) { + priv->poll_cnt++; + hrtimer_start(&priv->trig_timer, + ns_to_ktime(priv->scan_interval_us * + NSEC_PER_USEC), + HRTIMER_MODE_REL_SOFT); + + if (priv->poll_cnt >= TI_TSC2046_MIN_POLL_CNT) { + priv->state = TSC2046_STATE_POLL_IRQ_DISABLE; + enable_irq(priv->spi->irq); + } else { + priv->state = TSC2046_STATE_POLL; + } + } else { + priv->state = TSC2046_STATE_STANDBY; + enable_irq(priv->spi->irq); + } + break; + case TSC2046_STATE_POLL_IRQ_DISABLE: + disable_irq_nosync(priv->spi->irq); + fallthrough; + case TSC2046_STATE_POLL: + priv->state = TSC2046_STATE_ENABLE_IRQ; + /* iio_trigger_poll() starts hrtimer */ + iio_trigger_poll(priv->trig); + break; + case TSC2046_STATE_SHUTDOWN: + break; + case TSC2046_STATE_STANDBY: + fallthrough; + default: + dev_warn(&priv->spi->dev, "Got unexpected state: %i\n", + priv->state); + break; + } + spin_unlock_irqrestore(&priv->state_lock, flags); return HRTIMER_NORESTART; } @@ -434,16 +575,20 @@ static irqreturn_t tsc2046_adc_irq(int irq, void *dev_id) { struct iio_dev *indio_dev = dev_id; struct tsc2046_adc_priv *priv = iio_priv(indio_dev); - - spin_lock(&priv->trig_lock); + unsigned long flags; hrtimer_try_to_cancel(&priv->trig_timer); - priv->trig_more_count = 0; - disable_irq_nosync(priv->spi->irq); - iio_trigger_poll(priv->trig); + spin_lock_irqsave(&priv->state_lock, flags); + if (priv->state != TSC2046_STATE_SHUTDOWN) { + priv->state = TSC2046_STATE_ENABLE_IRQ; + priv->poll_cnt = 0; - spin_unlock(&priv->trig_lock); + /* iio_trigger_poll() starts hrtimer */ + disable_irq_nosync(priv->spi->irq); + iio_trigger_poll(priv->trig); + } + spin_unlock_irqrestore(&priv->state_lock, flags); return IRQ_HANDLED; } @@ -452,49 +597,42 @@ static void tsc2046_adc_reenable_trigger(struct iio_trigger *trig) { struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig); struct tsc2046_adc_priv *priv = iio_priv(indio_dev); - unsigned long flags; - int delta; + ktime_t tim; /* * We can sample it as fast as we can, but usually we do not need so * many samples. Reduce the sample rate for default (touchscreen) use * case. - * Currently we do not need a highly precise sample rate. It is enough - * to have calculated numbers. - */ - delta = priv->scan_interval_us - priv->time_per_scan_us; - if (delta > 0) - fsleep(delta); - - spin_lock_irqsave(&priv->trig_lock, flags); - - /* - * We need to trigger at least one extra sample to detect state - * difference on ADC side. */ - if (!priv->trig_more_count) { - int timeout_ms = DIV_ROUND_UP(priv->scan_interval_us, - USEC_PER_MSEC); - - hrtimer_start(&priv->trig_timer, ms_to_ktime(timeout_ms), - HRTIMER_MODE_REL_SOFT); - } - - enable_irq(priv->spi->irq); - - spin_unlock_irqrestore(&priv->trig_lock, flags); + tim = ns_to_ktime((priv->scan_interval_us - priv->time_per_scan_us) * + NSEC_PER_USEC); + hrtimer_start(&priv->trig_timer, tim, HRTIMER_MODE_REL_SOFT); } static int tsc2046_adc_set_trigger_state(struct iio_trigger *trig, bool enable) { struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig); struct tsc2046_adc_priv *priv = iio_priv(indio_dev); + unsigned long flags; if (enable) { - enable_irq(priv->spi->irq); + spin_lock_irqsave(&priv->state_lock, flags); + if (priv->state == TSC2046_STATE_SHUTDOWN) { + priv->state = TSC2046_STATE_STANDBY; + enable_irq(priv->spi->irq); + } + spin_unlock_irqrestore(&priv->state_lock, flags); } else { - disable_irq(priv->spi->irq); - hrtimer_try_to_cancel(&priv->trig_timer); + spin_lock_irqsave(&priv->state_lock, flags); + + if (priv->state == TSC2046_STATE_STANDBY || + priv->state == TSC2046_STATE_POLL_IRQ_DISABLE) + disable_irq_nosync(priv->spi->irq); + + priv->state = TSC2046_STATE_SHUTDOWN; + spin_unlock_irqrestore(&priv->state_lock, flags); + + hrtimer_cancel(&priv->trig_timer); } return 0; @@ -511,16 +649,6 @@ static int tsc2046_adc_setup_spi_msg(struct tsc2046_adc_priv *priv) size_t size; int ret; - priv->tx_one = devm_kzalloc(&priv->spi->dev, sizeof(*priv->tx_one), - GFP_KERNEL); - if (!priv->tx_one) - return -ENOMEM; - - priv->rx_one = devm_kzalloc(&priv->spi->dev, sizeof(*priv->rx_one), - GFP_KERNEL); - if (!priv->rx_one) - return -ENOMEM; - /* * Make dummy read to set initial power state and get real SPI clock * freq. It seems to be not important which channel is used for this @@ -551,6 +679,12 @@ static int tsc2046_adc_setup_spi_msg(struct tsc2046_adc_priv *priv) for (ch_idx = 0; ch_idx < ARRAY_SIZE(priv->l); ch_idx++) size += tsc2046_adc_group_set_layout(priv, ch_idx, ch_idx); + if (size > PAGE_SIZE) { + dev_err(&priv->spi->dev, + "Calculated scan buffer is too big. Try to reduce spi-max-frequency, settling-time-us or oversampling-ratio\n"); + return -ENOSPC; + } + priv->tx = devm_kzalloc(&priv->spi->dev, size, GFP_KERNEL); if (!priv->tx) return -ENOMEM; @@ -668,10 +802,11 @@ static int tsc2046_adc_probe(struct spi_device *spi) iio_trigger_set_drvdata(trig, indio_dev); trig->ops = &tsc2046_adc_trigger_ops; - spin_lock_init(&priv->trig_lock); + spin_lock_init(&priv->state_lock); + priv->state = TSC2046_STATE_SHUTDOWN; hrtimer_init(&priv->trig_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL_SOFT); - priv->trig_timer.function = tsc2046_adc_trig_more; + priv->trig_timer.function = tsc2046_adc_timer; ret = devm_iio_trigger_register(dev, trig); if (ret) { diff --git a/drivers/iio/adc/twl4030-madc.c b/drivers/iio/adc/twl4030-madc.c index 6ce40cc4568a..f8f8aea15612 100644 --- a/drivers/iio/adc/twl4030-madc.c +++ b/drivers/iio/adc/twl4030-madc.c @@ -231,13 +231,7 @@ static const struct iio_chan_spec twl4030_madc_iio_channels[] = { static struct twl4030_madc_data *twl4030_madc; -struct twl4030_prescale_divider_ratios { - s16 numerator; - s16 denominator; -}; - -static const struct twl4030_prescale_divider_ratios -twl4030_divider_ratios[16] = { +static const struct s16_fract twl4030_divider_ratios[16] = { {1, 1}, /* CHANNEL 0 No Prescaler */ {1, 1}, /* CHANNEL 1 No Prescaler */ {6, 10}, /* CHANNEL 2 */ @@ -256,7 +250,6 @@ twl4030_divider_ratios[16] = { {5, 11}, /* CHANNEL 15 */ }; - /* Conversion table from -3 to 55 degrees Celcius */ static int twl4030_therm_tbl[] = { 30800, 29500, 28300, 27100, diff --git a/drivers/iio/adc/twl6030-gpadc.c b/drivers/iio/adc/twl6030-gpadc.c index afdb59e0b526..f53e8558b560 100644 --- a/drivers/iio/adc/twl6030-gpadc.c +++ b/drivers/iio/adc/twl6030-gpadc.c @@ -911,6 +911,8 @@ static int twl6030_gpadc_probe(struct platform_device *pdev) ret = devm_request_threaded_irq(dev, irq, NULL, twl6030_gpadc_irq_handler, IRQF_ONESHOT, "twl6030_gpadc", indio_dev); + if (ret) + return ret; ret = twl6030_gpadc_enable_irq(TWL6030_GPADC_RT_SW1_EOC_MASK); if (ret < 0) { @@ -944,7 +946,6 @@ static int twl6030_gpadc_remove(struct platform_device *pdev) return 0; } -#ifdef CONFIG_PM_SLEEP static int twl6030_gpadc_suspend(struct device *pdev) { int ret; @@ -968,17 +969,16 @@ static int twl6030_gpadc_resume(struct device *pdev) return 0; }; -#endif -static SIMPLE_DEV_PM_OPS(twl6030_gpadc_pm_ops, twl6030_gpadc_suspend, - twl6030_gpadc_resume); +static DEFINE_SIMPLE_DEV_PM_OPS(twl6030_gpadc_pm_ops, twl6030_gpadc_suspend, + twl6030_gpadc_resume); static struct platform_driver twl6030_gpadc_driver = { .probe = twl6030_gpadc_probe, .remove = twl6030_gpadc_remove, .driver = { .name = DRIVER_NAME, - .pm = &twl6030_gpadc_pm_ops, + .pm = pm_sleep_ptr(&twl6030_gpadc_pm_ops), .of_match_table = of_twl6030_match_tbl, }, }; diff --git a/drivers/iio/adc/vf610_adc.c b/drivers/iio/adc/vf610_adc.c index fd57fc43e8e5..c84293efc129 100644 --- a/drivers/iio/adc/vf610_adc.c +++ b/drivers/iio/adc/vf610_adc.c @@ -912,7 +912,6 @@ static int vf610_adc_remove(struct platform_device *pdev) return 0; } -#ifdef CONFIG_PM_SLEEP static int vf610_adc_suspend(struct device *dev) { struct iio_dev *indio_dev = dev_get_drvdata(dev); @@ -952,9 +951,9 @@ disable_reg: regulator_disable(info->vref); return ret; } -#endif -static SIMPLE_DEV_PM_OPS(vf610_adc_pm_ops, vf610_adc_suspend, vf610_adc_resume); +static DEFINE_SIMPLE_DEV_PM_OPS(vf610_adc_pm_ops, vf610_adc_suspend, + vf610_adc_resume); static struct platform_driver vf610_adc_driver = { .probe = vf610_adc_probe, @@ -962,7 +961,7 @@ static struct platform_driver vf610_adc_driver = { .driver = { .name = DRIVER_NAME, .of_match_table = vf610_adc_match, - .pm = &vf610_adc_pm_ops, + .pm = pm_sleep_ptr(&vf610_adc_pm_ops), }, }; diff --git a/drivers/iio/adc/xilinx-ams.c b/drivers/iio/adc/xilinx-ams.c index 8343c5f74121..a55396c1f8b2 100644 --- a/drivers/iio/adc/xilinx-ams.c +++ b/drivers/iio/adc/xilinx-ams.c @@ -12,6 +12,7 @@ #include <linux/bitfield.h> #include <linux/clk.h> #include <linux/delay.h> +#include <linux/devm-helpers.h> #include <linux/interrupt.h> #include <linux/io.h> #include <linux/iopoll.h> @@ -91,8 +92,8 @@ #define AMS_CONF1_SEQ_MASK GENMASK(15, 12) #define AMS_CONF1_SEQ_DEFAULT FIELD_PREP(AMS_CONF1_SEQ_MASK, 0) -#define AMS_CONF1_SEQ_CONTINUOUS FIELD_PREP(AMS_CONF1_SEQ_MASK, 1) -#define AMS_CONF1_SEQ_SINGLE_CHANNEL FIELD_PREP(AMS_CONF1_SEQ_MASK, 2) +#define AMS_CONF1_SEQ_CONTINUOUS FIELD_PREP(AMS_CONF1_SEQ_MASK, 2) +#define AMS_CONF1_SEQ_SINGLE_CHANNEL FIELD_PREP(AMS_CONF1_SEQ_MASK, 3) #define AMS_REG_SEQ0_MASK GENMASK(15, 0) #define AMS_REG_SEQ2_MASK GENMASK(21, 16) @@ -530,14 +531,18 @@ static int ams_enable_single_channel(struct ams *ams, unsigned int offset) return -EINVAL; } - /* set single channel, sequencer off mode */ + /* put sysmon in a soft reset to change the sequence */ ams_ps_update_reg(ams, AMS_REG_CONFIG1, AMS_CONF1_SEQ_MASK, - AMS_CONF1_SEQ_SINGLE_CHANNEL); + AMS_CONF1_SEQ_DEFAULT); /* write the channel number */ ams_ps_update_reg(ams, AMS_REG_CONFIG0, AMS_CONF0_CHANNEL_NUM_MASK, channel_num); + /* set single channel, sequencer off mode */ + ams_ps_update_reg(ams, AMS_REG_CONFIG1, AMS_CONF1_SEQ_MASK, + AMS_CONF1_SEQ_SINGLE_CHANNEL); + return 0; } @@ -551,6 +556,8 @@ static int ams_read_vcc_reg(struct ams *ams, unsigned int offset, u32 *data) if (ret) return ret; + /* clear end-of-conversion flag, wait for next conversion to complete */ + writel(expect, ams->base + AMS_ISR_1); ret = readl_poll_timeout(ams->base + AMS_ISR_1, reg, (reg & expect), AMS_INIT_POLL_TIME_US, AMS_INIT_TIMEOUT_US); if (ret) @@ -1224,6 +1231,7 @@ static int ams_init_module(struct iio_dev *indio_dev, /* add PS channels to iio device channels */ memcpy(channels, ams_ps_channels, sizeof(ams_ps_channels)); + num_channels = ARRAY_SIZE(ams_ps_channels); } else if (fwnode_property_match_string(fwnode, "compatible", "xlnx,zynqmp-ams-pl") == 0) { ams->pl_base = fwnode_iomap(fwnode, 0); @@ -1348,11 +1356,6 @@ static void ams_clk_disable_unprepare(void *data) clk_disable_unprepare(data); } -static void ams_cancel_delayed_work(void *data) -{ - cancel_delayed_work(data); -} - static int ams_probe(struct platform_device *pdev) { struct iio_dev *indio_dev; @@ -1389,9 +1392,8 @@ static int ams_probe(struct platform_device *pdev) if (ret < 0) return ret; - INIT_DELAYED_WORK(&ams->ams_unmask_work, ams_unmask_worker); - ret = devm_add_action_or_reset(&pdev->dev, ams_cancel_delayed_work, - &ams->ams_unmask_work); + ret = devm_delayed_work_autocancel(&pdev->dev, &ams->ams_unmask_work, + ams_unmask_worker); if (ret < 0) return ret; |