aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/iio/adc
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2022-03-28 12:27:35 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2022-03-28 12:27:35 -0700
commit02e2af20f4f9f2aa0c84e9a30a35c02f0fbb7daa (patch)
treed126449a7d2ea2270627183f7cebd726fbe56a9d /drivers/iio/adc
parentMerge tag 'pinctrl-v5.18-1' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-pinctrl (diff)
parentfirmware: google: Properly state IOMEM dependency (diff)
downloadlinux-dev-02e2af20f4f9f2aa0c84e9a30a35c02f0fbb7daa.tar.xz
linux-dev-02e2af20f4f9f2aa0c84e9a30a35c02f0fbb7daa.zip
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')
-rw-r--r--drivers/iio/adc/Kconfig11
-rw-r--r--drivers/iio/adc/Makefile1
-rw-r--r--drivers/iio/adc/ab8500-gpadc.c14
-rw-r--r--drivers/iio/adc/ad7091r-base.c4
-rw-r--r--drivers/iio/adc/ad7091r5.c1
-rw-r--r--drivers/iio/adc/ad7124.c1
-rw-r--r--drivers/iio/adc/ad7192.c5
-rw-r--r--drivers/iio/adc/ad7280a.c1111
-rw-r--r--drivers/iio/adc/ad7606.c4
-rw-r--r--drivers/iio/adc/ad7606_par.c1
-rw-r--r--drivers/iio/adc/ad7606_spi.c1
-rw-r--r--drivers/iio/adc/ad7780.c1
-rw-r--r--drivers/iio/adc/ad7791.c1
-rw-r--r--drivers/iio/adc/ad7793.c1
-rw-r--r--drivers/iio/adc/ad_sigma_delta.c20
-rw-r--r--drivers/iio/adc/aspeed_adc.c4
-rw-r--r--drivers/iio/adc/at91_adc.c7
-rw-r--r--drivers/iio/adc/cpcap-adc.c2
-rw-r--r--drivers/iio/adc/exynos_adc.c9
-rw-r--r--drivers/iio/adc/hi8435.c2
-rw-r--r--drivers/iio/adc/ina2xx-adc.c2
-rw-r--r--drivers/iio/adc/max9611.c2
-rw-r--r--drivers/iio/adc/mt6577_auxadc.c16
-rw-r--r--drivers/iio/adc/palmas_gpadc.c10
-rw-r--r--drivers/iio/adc/qcom-pm8xxx-xoadc.c15
-rw-r--r--drivers/iio/adc/qcom-spmi-vadc.c24
-rw-r--r--drivers/iio/adc/qcom-vadc-common.c92
-rw-r--r--drivers/iio/adc/rcar-gyroadc.c6
-rw-r--r--drivers/iio/adc/rn5t618-adc.c7
-rw-r--r--drivers/iio/adc/rockchip_saradc.c9
-rw-r--r--drivers/iio/adc/rzg2l_adc.c4
-rw-r--r--drivers/iio/adc/stm32-adc-core.c17
-rw-r--r--drivers/iio/adc/stm32-adc.c12
-rw-r--r--drivers/iio/adc/stm32-dfsdm-adc.c11
-rw-r--r--drivers/iio/adc/stm32-dfsdm-core.c19
-rw-r--r--drivers/iio/adc/ti-adc084s021.c2
-rw-r--r--drivers/iio/adc/ti-tsc2046.c269
-rw-r--r--drivers/iio/adc/twl4030-madc.c9
-rw-r--r--drivers/iio/adc/twl6030-gpadc.c10
-rw-r--r--drivers/iio/adc/vf610_adc.c7
-rw-r--r--drivers/iio/adc/xilinx-ams.c26
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;