From 43d33f7458383ff6ce9838fca7b78b9b64fb988a Mon Sep 17 00:00:00 2001
From: Ludovic Desroches <ludovic.desroches@atmel.com>
Date: Thu, 3 Mar 2016 17:09:13 +0100
Subject: iio:adc:at91-sama5d2: fix typo

Fix typo in the name of a macro.

Signed-off-by: Ludovic Desroches <ludovic.desroches@atmel.com>
Signed-off-by: Jonathan Cameron <jic23@kernel.org>
---
 drivers/iio/adc/at91-sama5d2_adc.c | 26 +++++++++++++-------------
 1 file changed, 13 insertions(+), 13 deletions(-)

(limited to 'drivers/iio/adc')

diff --git a/drivers/iio/adc/at91-sama5d2_adc.c b/drivers/iio/adc/at91-sama5d2_adc.c
index dbee13ad33a3..33bacece325c 100644
--- a/drivers/iio/adc/at91-sama5d2_adc.c
+++ b/drivers/iio/adc/at91-sama5d2_adc.c
@@ -140,7 +140,7 @@
 /* Version Register */
 #define AT91_SAMA5D2_VERSION	0xfc
 
-#define AT91_AT91_SAMA5D2_CHAN(num, addr)				\
+#define AT91_SAMA5D2_CHAN(num, addr)					\
 	{								\
 		.type = IIO_VOLTAGE,					\
 		.channel = num,						\
@@ -185,18 +185,18 @@ struct at91_adc_state {
 };
 
 static const struct iio_chan_spec at91_adc_channels[] = {
-	AT91_AT91_SAMA5D2_CHAN(0, 0x50),
-	AT91_AT91_SAMA5D2_CHAN(1, 0x54),
-	AT91_AT91_SAMA5D2_CHAN(2, 0x58),
-	AT91_AT91_SAMA5D2_CHAN(3, 0x5c),
-	AT91_AT91_SAMA5D2_CHAN(4, 0x60),
-	AT91_AT91_SAMA5D2_CHAN(5, 0x64),
-	AT91_AT91_SAMA5D2_CHAN(6, 0x68),
-	AT91_AT91_SAMA5D2_CHAN(7, 0x6c),
-	AT91_AT91_SAMA5D2_CHAN(8, 0x70),
-	AT91_AT91_SAMA5D2_CHAN(9, 0x74),
-	AT91_AT91_SAMA5D2_CHAN(10, 0x78),
-	AT91_AT91_SAMA5D2_CHAN(11, 0x7c),
+	AT91_SAMA5D2_CHAN(0, 0x50),
+	AT91_SAMA5D2_CHAN(1, 0x54),
+	AT91_SAMA5D2_CHAN(2, 0x58),
+	AT91_SAMA5D2_CHAN(3, 0x5c),
+	AT91_SAMA5D2_CHAN(4, 0x60),
+	AT91_SAMA5D2_CHAN(5, 0x64),
+	AT91_SAMA5D2_CHAN(6, 0x68),
+	AT91_SAMA5D2_CHAN(7, 0x6c),
+	AT91_SAMA5D2_CHAN(8, 0x70),
+	AT91_SAMA5D2_CHAN(9, 0x74),
+	AT91_SAMA5D2_CHAN(10, 0x78),
+	AT91_SAMA5D2_CHAN(11, 0x7c),
 };
 
 static unsigned at91_adc_startup_time(unsigned startup_time_min,
-- 
cgit v1.2.3


From f0fa15cce13d5987c50907eb98846d13e2b4d9ca Mon Sep 17 00:00:00 2001
From: Ludovic Desroches <ludovic.desroches@atmel.com>
Date: Thu, 3 Mar 2016 17:09:14 +0100
Subject: iio:adc:at91-sama5d2: fix identation

Remove some extra tabs.

Signed-off-by: Ludovic Desroches <ludovic.desroches@atmel.com>
Signed-off-by: Jonathan Cameron <jic23@kernel.org>
---
 drivers/iio/adc/at91-sama5d2_adc.c | 20 ++++++++++----------
 1 file changed, 10 insertions(+), 10 deletions(-)

(limited to 'drivers/iio/adc')

diff --git a/drivers/iio/adc/at91-sama5d2_adc.c b/drivers/iio/adc/at91-sama5d2_adc.c
index 33bacece325c..5bc038f23609 100644
--- a/drivers/iio/adc/at91-sama5d2_adc.c
+++ b/drivers/iio/adc/at91-sama5d2_adc.c
@@ -92,13 +92,13 @@
 /* Last Converted Data Register */
 #define AT91_SAMA5D2_LCDR	0x20
 /* Interrupt Enable Register */
-#define AT91_SAMA5D2_IER		0x24
+#define AT91_SAMA5D2_IER	0x24
 /* Interrupt Disable Register */
-#define AT91_SAMA5D2_IDR		0x28
+#define AT91_SAMA5D2_IDR	0x28
 /* Interrupt Mask Register */
-#define AT91_SAMA5D2_IMR		0x2c
+#define AT91_SAMA5D2_IMR	0x2c
 /* Interrupt Status Register */
-#define AT91_SAMA5D2_ISR		0x30
+#define AT91_SAMA5D2_ISR	0x30
 /* Last Channel Trigger Mode Register */
 #define AT91_SAMA5D2_LCTMR	0x34
 /* Last Channel Compare Window Register */
@@ -106,17 +106,17 @@
 /* Overrun Status Register */
 #define AT91_SAMA5D2_OVER	0x3c
 /* Extended Mode Register */
-#define AT91_SAMA5D2_EMR		0x40
+#define AT91_SAMA5D2_EMR	0x40
 /* Compare Window Register */
-#define AT91_SAMA5D2_CWR		0x44
+#define AT91_SAMA5D2_CWR	0x44
 /* Channel Gain Register */
-#define AT91_SAMA5D2_CGR		0x48
+#define AT91_SAMA5D2_CGR	0x48
 /* Channel Offset Register */
-#define AT91_SAMA5D2_COR		0x4c
+#define AT91_SAMA5D2_COR	0x4c
 /* Channel Data Register 0 */
 #define AT91_SAMA5D2_CDR0	0x50
 /* Analog Control Register */
-#define AT91_SAMA5D2_ACR		0x94
+#define AT91_SAMA5D2_ACR	0x94
 /* Touchscreen Mode Register */
 #define AT91_SAMA5D2_TSMR	0xb0
 /* Touchscreen X Position Register */
@@ -130,7 +130,7 @@
 /* Correction Select Register */
 #define AT91_SAMA5D2_COSR	0xd0
 /* Correction Value Register */
-#define AT91_SAMA5D2_CVR		0xd4
+#define AT91_SAMA5D2_CVR	0xd4
 /* Channel Error Correction Register */
 #define AT91_SAMA5D2_CECR	0xd8
 /* Write Protection Mode Register */
-- 
cgit v1.2.3


From e84a41d5db891eab6f1f4a2625bb97f3c6415eee Mon Sep 17 00:00:00 2001
From: Krzysztof Kozlowski <k.kozlowski@samsung.com>
Date: Fri, 4 Mar 2016 10:05:26 +0900
Subject: iio: adc: Fix build error of missing devm_ioremap_resource on UM

The devres.o gets linked if HAS_IOMEM is present so on ARCH=um
allyesconfig (COMPILE_TEST) failed with:

drivers/built-in.o: In function `at91_adc_probe':
at91-sama5d2_adc.c:(.text+0x48f548): undefined reference to `devm_ioremap_resource'

Signed-off-by: Krzysztof Kozlowski <k.kozlowski@samsung.com>
Signed-off-by: Jonathan Cameron <jic23@kernel.org>
---
 drivers/iio/adc/Kconfig | 1 +
 1 file changed, 1 insertion(+)

(limited to 'drivers/iio/adc')

diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
index 932de1f9d1e7..a8819a08a828 100644
--- a/drivers/iio/adc/Kconfig
+++ b/drivers/iio/adc/Kconfig
@@ -134,6 +134,7 @@ config AT91_ADC
 config AT91_SAMA5D2_ADC
 	tristate "Atmel AT91 SAMA5D2 ADC"
 	depends on ARCH_AT91 || COMPILE_TEST
+	depends on HAS_IOMEM
 	help
 	  Say yes here to build support for Atmel SAMA5D2 ADC which is
 	  available on SAMA5D2 SoC family.
-- 
cgit v1.2.3


From a583c24deefdaaaf5bd96a1117b850904a294804 Mon Sep 17 00:00:00 2001
From: Joachim Eastwood <manabian@gmail.com>
Date: Sat, 12 Mar 2016 13:30:14 +0100
Subject: iio: adc: add NXP LPC18xx ADC driver

Add base support for the 10-bit SAR ADC peripheral found
on NXP LPC18xx/43xx SoCs.

This is a minimal driver that does not support burst mode,
interrupts, DMA or hardware triggers.

User manual with register description can be found on:
LPC18xx: www.nxp.com/documents/user_manual/UM10430.pdf
LPC43xx: www.nxp.com/documents/user_manual/UM10503.pdf

Signed-off-by: Joachim Eastwood <manabian@gmail.com>
Signed-off-by: Jonathan Cameron <jic23@kernel.org>
---
 drivers/iio/adc/Kconfig       |  10 ++
 drivers/iio/adc/Makefile      |   1 +
 drivers/iio/adc/lpc18xx_adc.c | 231 ++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 242 insertions(+)
 create mode 100644 drivers/iio/adc/lpc18xx_adc.c

(limited to 'drivers/iio/adc')

diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
index a8819a08a828..9ddcd5db039b 100644
--- a/drivers/iio/adc/Kconfig
+++ b/drivers/iio/adc/Kconfig
@@ -235,6 +235,16 @@ config LP8788_ADC
 	  To compile this driver as a module, choose M here: the module will be
 	  called lp8788_adc.
 
+config LPC18XX_ADC
+	tristate "NXP LPC18xx ADC driver"
+	depends on ARCH_LPC18XX || COMPILE_TEST
+	depends on OF && HAS_IOMEM
+	help
+	  Say yes here to build support for NXP LPC18XX ADC.
+
+	  To compile this driver as a module, choose M here: the module will be
+	  called lpc18xx_adc.
+
 config MAX1027
 	tristate "Maxim max1027 ADC driver"
 	depends on SPI
diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile
index b1aa456e6af3..1a4ac4590857 100644
--- a/drivers/iio/adc/Makefile
+++ b/drivers/iio/adc/Makefile
@@ -24,6 +24,7 @@ obj-$(CONFIG_HI8435) += hi8435.o
 obj-$(CONFIG_IMX7D_ADC) += imx7d_adc.o
 obj-$(CONFIG_INA2XX_ADC) += ina2xx-adc.o
 obj-$(CONFIG_LP8788_ADC) += lp8788_adc.o
+obj-$(CONFIG_LPC18XX_ADC) += lpc18xx_adc.o
 obj-$(CONFIG_MAX1027) += max1027.o
 obj-$(CONFIG_MAX1363) += max1363.o
 obj-$(CONFIG_MCP320X) += mcp320x.o
diff --git a/drivers/iio/adc/lpc18xx_adc.c b/drivers/iio/adc/lpc18xx_adc.c
new file mode 100644
index 000000000000..3ef18f4b27f0
--- /dev/null
+++ b/drivers/iio/adc/lpc18xx_adc.c
@@ -0,0 +1,231 @@
+/*
+ * IIO ADC driver for NXP LPC18xx ADC
+ *
+ * Copyright (C) 2016 Joachim Eastwood <manabian@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * UNSUPPORTED hardware features:
+ *  - Hardware triggers
+ *  - Burst mode
+ *  - Interrupts
+ *  - DMA
+ */
+
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/driver.h>
+#include <linux/io.h>
+#include <linux/iopoll.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
+
+/* LPC18XX ADC registers and bits */
+#define LPC18XX_ADC_CR			0x000
+#define  LPC18XX_ADC_CR_CLKDIV_SHIFT	8
+#define  LPC18XX_ADC_CR_PDN		BIT(21)
+#define  LPC18XX_ADC_CR_START_NOW	(0x1 << 24)
+#define LPC18XX_ADC_GDR			0x004
+
+/* Data register bits */
+#define LPC18XX_ADC_SAMPLE_SHIFT	6
+#define LPC18XX_ADC_SAMPLE_MASK		0x3ff
+#define LPC18XX_ADC_CONV_DONE		BIT(31)
+
+/* Clock should be 4.5 MHz or less */
+#define LPC18XX_ADC_CLK_TARGET		4500000
+
+struct lpc18xx_adc {
+	struct regulator *vref;
+	void __iomem *base;
+	struct device *dev;
+	struct mutex lock;
+	struct clk *clk;
+	u32 cr_reg;
+};
+
+#define LPC18XX_ADC_CHAN(_idx) {				\
+	.type = IIO_VOLTAGE,					\
+	.indexed = 1,						\
+	.channel = _idx,					\
+	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),		\
+	.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),	\
+}
+
+static const struct iio_chan_spec lpc18xx_adc_iio_channels[] = {
+	LPC18XX_ADC_CHAN(0),
+	LPC18XX_ADC_CHAN(1),
+	LPC18XX_ADC_CHAN(2),
+	LPC18XX_ADC_CHAN(3),
+	LPC18XX_ADC_CHAN(4),
+	LPC18XX_ADC_CHAN(5),
+	LPC18XX_ADC_CHAN(6),
+	LPC18XX_ADC_CHAN(7),
+};
+
+static int lpc18xx_adc_read_chan(struct lpc18xx_adc *adc, unsigned int ch)
+{
+	int ret;
+	u32 reg;
+
+	reg = adc->cr_reg | BIT(ch) | LPC18XX_ADC_CR_START_NOW;
+	writel(reg, adc->base + LPC18XX_ADC_CR);
+
+	ret = readl_poll_timeout(adc->base + LPC18XX_ADC_GDR, reg,
+				 reg & LPC18XX_ADC_CONV_DONE, 3, 9);
+	if (ret) {
+		dev_warn(adc->dev, "adc read timed out\n");
+		return ret;
+	}
+
+	return (reg >> LPC18XX_ADC_SAMPLE_SHIFT) & LPC18XX_ADC_SAMPLE_MASK;
+}
+
+static int lpc18xx_adc_read_raw(struct iio_dev *indio_dev,
+				struct iio_chan_spec const *chan,
+				int *val, int *val2, long mask)
+{
+	struct lpc18xx_adc *adc = iio_priv(indio_dev);
+
+	switch (mask) {
+	case IIO_CHAN_INFO_RAW:
+		mutex_lock(&adc->lock);
+		*val = lpc18xx_adc_read_chan(adc, chan->channel);
+		mutex_unlock(&adc->lock);
+		if (*val < 0)
+			return *val;
+
+		return IIO_VAL_INT;
+
+	case IIO_CHAN_INFO_SCALE:
+		*val = regulator_get_voltage(adc->vref) / 1000;
+		*val2 = 10;
+
+		return IIO_VAL_FRACTIONAL_LOG2;
+	}
+
+	return -EINVAL;
+}
+
+static const struct iio_info lpc18xx_adc_info = {
+	.read_raw = lpc18xx_adc_read_raw,
+	.driver_module = THIS_MODULE,
+};
+
+static int lpc18xx_adc_probe(struct platform_device *pdev)
+{
+	struct iio_dev *indio_dev;
+	struct lpc18xx_adc *adc;
+	struct resource *res;
+	unsigned int clkdiv;
+	unsigned long rate;
+	int ret;
+
+	indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*adc));
+	if (!indio_dev)
+		return -ENOMEM;
+
+	platform_set_drvdata(pdev, indio_dev);
+	adc = iio_priv(indio_dev);
+	adc->dev = &pdev->dev;
+	mutex_init(&adc->lock);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	adc->base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(adc->base))
+		return PTR_ERR(adc->base);
+
+	adc->clk = devm_clk_get(&pdev->dev, NULL);
+	if (IS_ERR(adc->clk)) {
+		dev_err(&pdev->dev, "error getting clock\n");
+		return PTR_ERR(adc->clk);
+	}
+
+	rate = clk_get_rate(adc->clk);
+	clkdiv = DIV_ROUND_UP(rate, LPC18XX_ADC_CLK_TARGET);
+
+	adc->vref = devm_regulator_get(&pdev->dev, "vref");
+	if (IS_ERR(adc->vref)) {
+		dev_err(&pdev->dev, "error getting regulator\n");
+		return PTR_ERR(adc->vref);
+	}
+
+	indio_dev->name = dev_name(&pdev->dev);
+	indio_dev->dev.parent = &pdev->dev;
+	indio_dev->info = &lpc18xx_adc_info;
+	indio_dev->modes = INDIO_DIRECT_MODE;
+	indio_dev->channels = lpc18xx_adc_iio_channels;
+	indio_dev->num_channels = ARRAY_SIZE(lpc18xx_adc_iio_channels);
+
+	ret = regulator_enable(adc->vref);
+	if (ret) {
+		dev_err(&pdev->dev, "unable to enable regulator\n");
+		return ret;
+	}
+
+	ret = clk_prepare_enable(adc->clk);
+	if (ret) {
+		dev_err(&pdev->dev, "unable to enable clock\n");
+		goto dis_reg;
+	}
+
+	adc->cr_reg = (clkdiv << LPC18XX_ADC_CR_CLKDIV_SHIFT) |
+			LPC18XX_ADC_CR_PDN;
+	writel(adc->cr_reg, adc->base + LPC18XX_ADC_CR);
+
+	ret = iio_device_register(indio_dev);
+	if (ret) {
+		dev_err(&pdev->dev, "unable to register device\n");
+		goto dis_clk;
+	}
+
+	return 0;
+
+dis_clk:
+	writel(0, adc->base + LPC18XX_ADC_CR);
+	clk_disable_unprepare(adc->clk);
+dis_reg:
+	regulator_disable(adc->vref);
+	return ret;
+}
+
+static int lpc18xx_adc_remove(struct platform_device *pdev)
+{
+	struct iio_dev *indio_dev = platform_get_drvdata(pdev);
+	struct lpc18xx_adc *adc = iio_priv(indio_dev);
+
+	iio_device_unregister(indio_dev);
+
+	writel(0, adc->base + LPC18XX_ADC_CR);
+	clk_disable_unprepare(adc->clk);
+	regulator_disable(adc->vref);
+
+	return 0;
+}
+
+static const struct of_device_id lpc18xx_adc_match[] = {
+	{ .compatible = "nxp,lpc1850-adc" },
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, lpc18xx_adc_match);
+
+static struct platform_driver lpc18xx_adc_driver = {
+	.probe	= lpc18xx_adc_probe,
+	.remove	= lpc18xx_adc_remove,
+	.driver	= {
+		.name = "lpc18xx-adc",
+		.of_match_table = lpc18xx_adc_match,
+	},
+};
+module_platform_driver(lpc18xx_adc_driver);
+
+MODULE_DESCRIPTION("LPC18xx ADC driver");
+MODULE_AUTHOR("Joachim Eastwood <manabian@gmail.com>");
+MODULE_LICENSE("GPL v2");
-- 
cgit v1.2.3


From ae549a72212c94c757fa3ecbcaa986cc9d2e2b96 Mon Sep 17 00:00:00 2001
From: David Wu <david.wu@rock-chips.com>
Date: Wed, 16 Mar 2016 01:44:15 +0800
Subject: iio: adc: rockchip_saradc: add saradc support for rk3399

The ADC is a 6-channel signal-ended 10-bit Successive
Approximation Register (SAR) A/D Converter.

Signed-off-by: David Wu <david.wu@rock-chips.com>
Signed-off-by: Jonathan Cameron <jic23@kernel.org>
---
 .../devicetree/bindings/iio/adc/rockchip-saradc.txt   |  6 +++++-
 drivers/iio/adc/rockchip_saradc.c                     | 19 +++++++++++++++++++
 2 files changed, 24 insertions(+), 1 deletion(-)

(limited to 'drivers/iio/adc')

diff --git a/Documentation/devicetree/bindings/iio/adc/rockchip-saradc.txt b/Documentation/devicetree/bindings/iio/adc/rockchip-saradc.txt
index a9a5fe19ff2a..bf99e2f24788 100644
--- a/Documentation/devicetree/bindings/iio/adc/rockchip-saradc.txt
+++ b/Documentation/devicetree/bindings/iio/adc/rockchip-saradc.txt
@@ -1,7 +1,11 @@
 Rockchip Successive Approximation Register (SAR) A/D Converter bindings
 
 Required properties:
-- compatible: Should be "rockchip,saradc" or "rockchip,rk3066-tsadc"
+- compatible: should be "rockchip,<name>-saradc" or "rockchip,rk3066-tsadc"
+   - "rockchip,saradc": for rk3188, rk3288
+   - "rockchip,rk3066-tsadc": for rk3036
+   - "rockchip,rk3399-saradc": for rk3399
+
 - reg: physical base address of the controller and length of memory mapped
        region.
 - interrupts: The interrupt number to the cpu. The interrupt specifier format
diff --git a/drivers/iio/adc/rockchip_saradc.c b/drivers/iio/adc/rockchip_saradc.c
index 9c311c1e1ac7..f9ad6c2d6821 100644
--- a/drivers/iio/adc/rockchip_saradc.c
+++ b/drivers/iio/adc/rockchip_saradc.c
@@ -159,6 +159,22 @@ static const struct rockchip_saradc_data rk3066_tsadc_data = {
 	.clk_rate = 50000,
 };
 
+static const struct iio_chan_spec rockchip_rk3399_saradc_iio_channels[] = {
+	ADC_CHANNEL(0, "adc0"),
+	ADC_CHANNEL(1, "adc1"),
+	ADC_CHANNEL(2, "adc2"),
+	ADC_CHANNEL(3, "adc3"),
+	ADC_CHANNEL(4, "adc4"),
+	ADC_CHANNEL(5, "adc5"),
+};
+
+static const struct rockchip_saradc_data rk3399_saradc_data = {
+	.num_bits = 10,
+	.channels = rockchip_rk3399_saradc_iio_channels,
+	.num_channels = ARRAY_SIZE(rockchip_rk3399_saradc_iio_channels),
+	.clk_rate = 1000000,
+};
+
 static const struct of_device_id rockchip_saradc_match[] = {
 	{
 		.compatible = "rockchip,saradc",
@@ -166,6 +182,9 @@ static const struct of_device_id rockchip_saradc_match[] = {
 	}, {
 		.compatible = "rockchip,rk3066-tsadc",
 		.data = &rk3066_tsadc_data,
+	}, {
+		.compatible = "rockchip,rk3399-saradc",
+		.data = &rk3399_saradc_data,
 	},
 	{},
 };
-- 
cgit v1.2.3


From d1ef4f2cae6705925088047554e89c34048f926a Mon Sep 17 00:00:00 2001
From: Marc Titinger <mtitinger@baylibre.com>
Date: Mon, 14 Mar 2016 11:20:44 +0100
Subject: iio: ina2xx-adc: update the CALIB. register when RShunt changes

The user (or an init script) may setup RShunt via sysfs after the
driver was initialized, for instance based on the EEPROM contents
of a modular probe. The calibration register must be set accordingly.

Signed-off-by: Marc Titinger <marc.titinger@baylibre.com>
Signed-off-by: Jonathan Cameron <jic23@kernel.org>
---
 drivers/iio/adc/ina2xx-adc.c | 39 ++++++++++++++++++++++++---------------
 1 file changed, 24 insertions(+), 15 deletions(-)

(limited to 'drivers/iio/adc')

diff --git a/drivers/iio/adc/ina2xx-adc.c b/drivers/iio/adc/ina2xx-adc.c
index 65909d5858b1..4e56fe3580bf 100644
--- a/drivers/iio/adc/ina2xx-adc.c
+++ b/drivers/iio/adc/ina2xx-adc.c
@@ -350,6 +350,23 @@ static ssize_t ina2xx_allow_async_readout_store(struct device *dev,
 	return len;
 }
 
+/*
+ * Set current LSB to 1mA, shunt is in uOhms
+ * (equation 13 in datasheet). We hardcode a Current_LSB
+ * of 1.0 x10-6. The only remaining parameter is RShunt.
+ * There is no need to expose the CALIBRATION register
+ * to the user for now. But we need to reset this register
+ * if the user updates RShunt after driver init, e.g upon
+ * reading an EEPROM/Probe-type value.
+ */
+static int ina2xx_set_calibration(struct ina2xx_chip_info *chip)
+{
+	u16 regval = DIV_ROUND_CLOSEST(chip->config->calibration_factor,
+				   chip->shunt_resistor);
+
+	return regmap_write(chip->regmap, INA2XX_CALIBRATION, regval);
+}
+
 static int set_shunt_resistor(struct ina2xx_chip_info *chip, unsigned int val)
 {
 	if (val <= 0 || val > chip->config->calibration_factor)
@@ -385,6 +402,11 @@ static ssize_t ina2xx_shunt_resistor_store(struct device *dev,
 	if (ret)
 		return ret;
 
+	/* Update the Calibration register */
+	ret = ina2xx_set_calibration(chip);
+	if (ret)
+		return ret;
+
 	return len;
 }
 
@@ -602,24 +624,11 @@ static const struct iio_info ina2xx_info = {
 /* Initialize the configuration and calibration registers. */
 static int ina2xx_init(struct ina2xx_chip_info *chip, unsigned int config)
 {
-	u16 regval;
-	int ret;
-
-	ret = regmap_write(chip->regmap, INA2XX_CONFIG, config);
+	int ret = regmap_write(chip->regmap, INA2XX_CONFIG, config);
 	if (ret)
 		return ret;
 
-	/*
-	 * Set current LSB to 1mA, shunt is in uOhms
-	 * (equation 13 in datasheet). We hardcode a Current_LSB
-	 * of 1.0 x10-6. The only remaining parameter is RShunt.
-	 * There is no need to expose the CALIBRATION register
-	 * to the user for now.
-	 */
-	regval = DIV_ROUND_CLOSEST(chip->config->calibration_factor,
-				   chip->shunt_resistor);
-
-	return regmap_write(chip->regmap, INA2XX_CALIBRATION, regval);
+	return ina2xx_set_calibration(chip);
 }
 
 static int ina2xx_probe(struct i2c_client *client,
-- 
cgit v1.2.3


From 94b24230196da3cd6bd58235137f9a7438983c73 Mon Sep 17 00:00:00 2001
From: Ludovic Desroches <ludovic.desroches@atmel.com>
Date: Tue, 22 Mar 2016 17:08:45 +0100
Subject: iio:adc:at91-sama5d2: cleanup mode register use

Do not erase previous configuration of the mode register when setting
the sampling frequency.

Signed-off-by: Ludovic Desroches <ludovic.desroches@atmel.com>
Signed-off-by: Jonathan Cameron <jic23@kernel.org>
---
 drivers/iio/adc/at91-sama5d2_adc.c | 15 ++++++++++-----
 1 file changed, 10 insertions(+), 5 deletions(-)

(limited to 'drivers/iio/adc')

diff --git a/drivers/iio/adc/at91-sama5d2_adc.c b/drivers/iio/adc/at91-sama5d2_adc.c
index 5bc038f23609..01ba1068613e 100644
--- a/drivers/iio/adc/at91-sama5d2_adc.c
+++ b/drivers/iio/adc/at91-sama5d2_adc.c
@@ -66,8 +66,10 @@
 #define	AT91_SAMA5D2_MR_PRESCAL(v)	((v) << AT91_SAMA5D2_MR_PRESCAL_OFFSET)
 #define	AT91_SAMA5D2_MR_PRESCAL_OFFSET	8
 #define	AT91_SAMA5D2_MR_PRESCAL_MAX	0xff
+#define AT91_SAMA5D2_MR_PRESCAL_MASK	GENMASK(15, 8)
 /* Startup Time */
 #define	AT91_SAMA5D2_MR_STARTUP(v)	((v) << 16)
+#define AT91_SAMA5D2_MR_STARTUP_MASK	GENMASK(19, 16)
 /* Analog Change */
 #define	AT91_SAMA5D2_MR_ANACH		BIT(23)
 /* Tracking Time */
@@ -226,7 +228,7 @@ static unsigned at91_adc_startup_time(unsigned startup_time_min,
 static void at91_adc_setup_samp_freq(struct at91_adc_state *st, unsigned freq)
 {
 	struct iio_dev *indio_dev = iio_priv_to_dev(st);
-	unsigned f_per, prescal, startup;
+	unsigned f_per, prescal, startup, mr;
 
 	f_per = clk_get_rate(st->per_clk);
 	prescal = (f_per / (2 * freq)) - 1;
@@ -234,10 +236,11 @@ static void at91_adc_setup_samp_freq(struct at91_adc_state *st, unsigned freq)
 	startup = at91_adc_startup_time(st->soc_info.startup_time,
 					freq / 1000);
 
-	at91_adc_writel(st, AT91_SAMA5D2_MR,
-			AT91_SAMA5D2_MR_TRANSFER(2)
-			| AT91_SAMA5D2_MR_STARTUP(startup)
-			| AT91_SAMA5D2_MR_PRESCAL(prescal));
+	mr = at91_adc_readl(st, AT91_SAMA5D2_MR);
+	mr &= ~(AT91_SAMA5D2_MR_STARTUP_MASK | AT91_SAMA5D2_MR_PRESCAL_MASK);
+	mr |= AT91_SAMA5D2_MR_STARTUP(startup);
+	mr |= AT91_SAMA5D2_MR_PRESCAL(prescal);
+	at91_adc_writel(st, AT91_SAMA5D2_MR, mr);
 
 	dev_dbg(&indio_dev->dev, "freq: %u, startup: %u, prescal: %u\n",
 		freq, startup, prescal);
@@ -444,6 +447,8 @@ static int at91_adc_probe(struct platform_device *pdev)
 
 	at91_adc_writel(st, AT91_SAMA5D2_CR, AT91_SAMA5D2_CR_SWRST);
 	at91_adc_writel(st, AT91_SAMA5D2_IDR, 0xffffffff);
+	/* Transfer field must be set to 2 according to the datasheet. */
+	at91_adc_writel(st, AT91_SAMA5D2_MR, AT91_SAMA5D2_MR_TRANSFER(2));
 
 	at91_adc_setup_samp_freq(st, st->soc_info.min_sample_rate);
 
-- 
cgit v1.2.3


From d65113222c27e2ca0b292a5163ea294428d481b2 Mon Sep 17 00:00:00 2001
From: Ludovic Desroches <ludovic.desroches@atmel.com>
Date: Tue, 22 Mar 2016 17:08:46 +0100
Subject: iio:adc:at91-sama5d2: add support for differential conversions

Add signed differential channels and update the voltage scale for
differential conversions.

Signed-off-by: Ludovic Desroches <ludovic.desroches@atmel.com>
Signed-off-by: Jonathan Cameron <jic23@kernel.org>
---
 drivers/iio/adc/at91-sama5d2_adc.c | 71 ++++++++++++++++++++++++++++++--------
 1 file changed, 56 insertions(+), 15 deletions(-)

(limited to 'drivers/iio/adc')

diff --git a/drivers/iio/adc/at91-sama5d2_adc.c b/drivers/iio/adc/at91-sama5d2_adc.c
index 01ba1068613e..07adb1070fc2 100644
--- a/drivers/iio/adc/at91-sama5d2_adc.c
+++ b/drivers/iio/adc/at91-sama5d2_adc.c
@@ -113,8 +113,11 @@
 #define AT91_SAMA5D2_CWR	0x44
 /* Channel Gain Register */
 #define AT91_SAMA5D2_CGR	0x48
+
 /* Channel Offset Register */
 #define AT91_SAMA5D2_COR	0x4c
+#define AT91_SAMA5D2_COR_DIFF_OFFSET	16
+
 /* Channel Data Register 0 */
 #define AT91_SAMA5D2_CDR0	0x50
 /* Analog Control Register */
@@ -142,7 +145,7 @@
 /* Version Register */
 #define AT91_SAMA5D2_VERSION	0xfc
 
-#define AT91_SAMA5D2_CHAN(num, addr)					\
+#define AT91_SAMA5D2_CHAN_SINGLE(num, addr)				\
 	{								\
 		.type = IIO_VOLTAGE,					\
 		.channel = num,						\
@@ -158,6 +161,24 @@
 		.indexed = 1,						\
 	}
 
+#define AT91_SAMA5D2_CHAN_DIFF(num, num2, addr)				\
+	{								\
+		.type = IIO_VOLTAGE,					\
+		.differential = 1,					\
+		.channel = num,						\
+		.channel2 = num2,					\
+		.address = addr,					\
+		.scan_type = {						\
+			.sign = 's',					\
+			.realbits = 12,					\
+		},							\
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),		\
+		.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),	\
+		.info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ),\
+		.datasheet_name = "CH"#num"-CH"#num2,			\
+		.indexed = 1,						\
+	}
+
 #define at91_adc_readl(st, reg)		readl_relaxed(st->base + reg)
 #define at91_adc_writel(st, reg, val)	writel_relaxed(val, st->base + reg)
 
@@ -187,18 +208,24 @@ struct at91_adc_state {
 };
 
 static const struct iio_chan_spec at91_adc_channels[] = {
-	AT91_SAMA5D2_CHAN(0, 0x50),
-	AT91_SAMA5D2_CHAN(1, 0x54),
-	AT91_SAMA5D2_CHAN(2, 0x58),
-	AT91_SAMA5D2_CHAN(3, 0x5c),
-	AT91_SAMA5D2_CHAN(4, 0x60),
-	AT91_SAMA5D2_CHAN(5, 0x64),
-	AT91_SAMA5D2_CHAN(6, 0x68),
-	AT91_SAMA5D2_CHAN(7, 0x6c),
-	AT91_SAMA5D2_CHAN(8, 0x70),
-	AT91_SAMA5D2_CHAN(9, 0x74),
-	AT91_SAMA5D2_CHAN(10, 0x78),
-	AT91_SAMA5D2_CHAN(11, 0x7c),
+	AT91_SAMA5D2_CHAN_SINGLE(0, 0x50),
+	AT91_SAMA5D2_CHAN_SINGLE(1, 0x54),
+	AT91_SAMA5D2_CHAN_SINGLE(2, 0x58),
+	AT91_SAMA5D2_CHAN_SINGLE(3, 0x5c),
+	AT91_SAMA5D2_CHAN_SINGLE(4, 0x60),
+	AT91_SAMA5D2_CHAN_SINGLE(5, 0x64),
+	AT91_SAMA5D2_CHAN_SINGLE(6, 0x68),
+	AT91_SAMA5D2_CHAN_SINGLE(7, 0x6c),
+	AT91_SAMA5D2_CHAN_SINGLE(8, 0x70),
+	AT91_SAMA5D2_CHAN_SINGLE(9, 0x74),
+	AT91_SAMA5D2_CHAN_SINGLE(10, 0x78),
+	AT91_SAMA5D2_CHAN_SINGLE(11, 0x7c),
+	AT91_SAMA5D2_CHAN_DIFF(0, 1, 0x50),
+	AT91_SAMA5D2_CHAN_DIFF(2, 3, 0x58),
+	AT91_SAMA5D2_CHAN_DIFF(4, 5, 0x60),
+	AT91_SAMA5D2_CHAN_DIFF(6, 7, 0x68),
+	AT91_SAMA5D2_CHAN_DIFF(8, 9, 0x70),
+	AT91_SAMA5D2_CHAN_DIFF(10, 11, 0x78),
 };
 
 static unsigned at91_adc_startup_time(unsigned startup_time_min,
@@ -281,6 +308,7 @@ static int at91_adc_read_raw(struct iio_dev *indio_dev,
 			     int *val, int *val2, long mask)
 {
 	struct at91_adc_state *st = iio_priv(indio_dev);
+	u32 cor = 0;
 	int ret;
 
 	switch (mask) {
@@ -289,6 +317,11 @@ static int at91_adc_read_raw(struct iio_dev *indio_dev,
 
 		st->chan = chan;
 
+		if (chan->differential)
+			cor = (BIT(chan->channel) | BIT(chan->channel2)) <<
+			      AT91_SAMA5D2_COR_DIFF_OFFSET;
+
+		at91_adc_writel(st, AT91_SAMA5D2_COR, cor);
 		at91_adc_writel(st, AT91_SAMA5D2_CHER, BIT(chan->channel));
 		at91_adc_writel(st, AT91_SAMA5D2_IER, BIT(chan->channel));
 		at91_adc_writel(st, AT91_SAMA5D2_CR, AT91_SAMA5D2_CR_START);
@@ -301,6 +334,8 @@ static int at91_adc_read_raw(struct iio_dev *indio_dev,
 
 		if (ret > 0) {
 			*val = st->conversion_value;
+			if (chan->scan_type.sign == 's')
+				*val = sign_extend32(*val, 11);
 			ret = IIO_VAL_INT;
 			st->conversion_done = false;
 		}
@@ -313,6 +348,8 @@ static int at91_adc_read_raw(struct iio_dev *indio_dev,
 
 	case IIO_CHAN_INFO_SCALE:
 		*val = st->vref_uv / 1000;
+		if (chan->differential)
+			*val *= 2;
 		*val2 = chan->scan_type.realbits;
 		return IIO_VAL_FRACTIONAL_LOG2;
 
@@ -447,8 +484,12 @@ static int at91_adc_probe(struct platform_device *pdev)
 
 	at91_adc_writel(st, AT91_SAMA5D2_CR, AT91_SAMA5D2_CR_SWRST);
 	at91_adc_writel(st, AT91_SAMA5D2_IDR, 0xffffffff);
-	/* Transfer field must be set to 2 according to the datasheet. */
-	at91_adc_writel(st, AT91_SAMA5D2_MR, AT91_SAMA5D2_MR_TRANSFER(2));
+	/*
+	 * Transfer field must be set to 2 according to the datasheet and
+	 * allows different analog settings for each channel.
+	 */
+	at91_adc_writel(st, AT91_SAMA5D2_MR,
+			AT91_SAMA5D2_MR_TRANSFER(2) | AT91_SAMA5D2_MR_ANACH);
 
 	at91_adc_setup_samp_freq(st, st->soc_info.min_sample_rate);
 
-- 
cgit v1.2.3


From eaa3476a7ee27c9927531781c8b25365d77e3030 Mon Sep 17 00:00:00 2001
From: Marc Titinger <mtitinger@baylibre.com>
Date: Fri, 11 Mar 2016 15:52:30 +0100
Subject: iio: ina2xx-adc: fix scale for VShunt

The scale would result in uV instead of expected mV.
Mostly cosmetic, since the value of 'Power' was computed OK.

Signed-off-by: Marc Titinger <marc.titinger@baylibre.com>
Signed-off-by: Jonathan Cameron <jic23@kernel.org>
---
 drivers/iio/adc/ina2xx-adc.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

(limited to 'drivers/iio/adc')

diff --git a/drivers/iio/adc/ina2xx-adc.c b/drivers/iio/adc/ina2xx-adc.c
index 4e56fe3580bf..502f2fbe8aef 100644
--- a/drivers/iio/adc/ina2xx-adc.c
+++ b/drivers/iio/adc/ina2xx-adc.c
@@ -185,9 +185,9 @@ static int ina2xx_read_raw(struct iio_dev *indio_dev,
 	case IIO_CHAN_INFO_SCALE:
 		switch (chan->address) {
 		case INA2XX_SHUNT_VOLTAGE:
-			/* processed (mV) = raw*1000/shunt_div */
+			/* processed (mV) = raw/shunt_div */
 			*val2 = chip->config->shunt_div;
-			*val = 1000;
+			*val = 1;
 			return IIO_VAL_FRACTIONAL;
 
 		case INA2XX_BUS_VOLTAGE:
-- 
cgit v1.2.3