All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/4] dt-bindings: iio/adc: Add a compatible string for JZ4770 SoC ADC
@ 2019-06-23 18:47 Artur Rojek
  2019-06-23 18:47 ` [PATCH 2/4] dt-bindings: iio/adc: Add AUX2 channel idx " Artur Rojek
                   ` (3 more replies)
  0 siblings, 4 replies; 10+ messages in thread
From: Artur Rojek @ 2019-06-23 18:47 UTC (permalink / raw)
  To: Jonathan Cameron, Rob Herring, Mark Rutland
  Cc: linux-iio, devicetree, linux-kernel, Maarten ter Huurne,
	Paul Cercueil, Artur Rojek

Add a compatible string for the ADC controller present on
Ingenic JZ4770 SoC.

Signed-off-by: Artur Rojek <contact@artur-rojek.eu>
---
 Documentation/devicetree/bindings/iio/adc/ingenic,adc.txt | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/iio/adc/ingenic,adc.txt b/Documentation/devicetree/bindings/iio/adc/ingenic,adc.txt
index f01159f20d87..cd9048cf9dcf 100644
--- a/Documentation/devicetree/bindings/iio/adc/ingenic,adc.txt
+++ b/Documentation/devicetree/bindings/iio/adc/ingenic,adc.txt
@@ -5,6 +5,7 @@ Required properties:
 - compatible: Should be one of:
   * ingenic,jz4725b-adc
   * ingenic,jz4740-adc
+  * ingenic,jz4770-adc
 - reg: ADC controller registers location and length.
 - clocks: phandle to the SoC's ADC clock.
 - clock-names: Must be set to "adc".
-- 
2.22.0


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 2/4] dt-bindings: iio/adc: Add AUX2 channel idx for JZ4770 SoC ADC
  2019-06-23 18:47 [PATCH 1/4] dt-bindings: iio/adc: Add a compatible string for JZ4770 SoC ADC Artur Rojek
@ 2019-06-23 18:47 ` Artur Rojek
  2019-07-10 13:53     ` Rob Herring
  2019-06-23 18:47 ` [PATCH 3/4] IIO: Ingenic JZ47xx: Set clock divider on probe Artur Rojek
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 10+ messages in thread
From: Artur Rojek @ 2019-06-23 18:47 UTC (permalink / raw)
  To: Jonathan Cameron, Rob Herring, Mark Rutland
  Cc: linux-iio, devicetree, linux-kernel, Maarten ter Huurne,
	Paul Cercueil, Artur Rojek

Introduce support for AUX2 channel found in ADC hardware present on
Ingenic JZ4770 SoC.

Signed-off-by: Artur Rojek <contact@artur-rojek.eu>
---
 include/dt-bindings/iio/adc/ingenic,adc.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/include/dt-bindings/iio/adc/ingenic,adc.h b/include/dt-bindings/iio/adc/ingenic,adc.h
index 82706b2706ac..42f871ab3272 100644
--- a/include/dt-bindings/iio/adc/ingenic,adc.h
+++ b/include/dt-bindings/iio/adc/ingenic,adc.h
@@ -6,5 +6,6 @@
 /* ADC channel idx. */
 #define INGENIC_ADC_AUX		0
 #define INGENIC_ADC_BATTERY	1
+#define INGENIC_ADC_AUX2	2
 
 #endif
-- 
2.22.0


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 3/4] IIO: Ingenic JZ47xx: Set clock divider on probe
  2019-06-23 18:47 [PATCH 1/4] dt-bindings: iio/adc: Add a compatible string for JZ4770 SoC ADC Artur Rojek
  2019-06-23 18:47 ` [PATCH 2/4] dt-bindings: iio/adc: Add AUX2 channel idx " Artur Rojek
@ 2019-06-23 18:47 ` Artur Rojek
  2019-06-26 20:00   ` Jonathan Cameron
  2019-06-23 18:47 ` [PATCH 4/4] IIO: Ingenic JZ47xx: Add support for JZ4770 SoC ADC Artur Rojek
  2019-07-10 13:52   ` Rob Herring
  3 siblings, 1 reply; 10+ messages in thread
From: Artur Rojek @ 2019-06-23 18:47 UTC (permalink / raw)
  To: Jonathan Cameron, Rob Herring, Mark Rutland
  Cc: linux-iio, devicetree, linux-kernel, Maarten ter Huurne,
	Paul Cercueil, Artur Rojek

From: Maarten ter Huurne <maarten@treewalker.org>

The SADC component can run at up to 8 MHz on JZ4725B, but is fed
a 12 MHz input clock (EXT). Divide it by two to get 6 MHz, then
set up another divider to match, to produce a 10us clock.

If the clock dividers are left on their power-on defaults (a divider
of 1), the SADC mostly works, but will occasionally produce erroneous
readings. This led to button presses being detected out of nowhere on
the RS90 every few minutes. With this change, no ghost button presses
were logged in almost a day worth of testing.

The ADCLK register for configuring clock dividers doesn't exist on
JZ4740, so avoid writing it there.

A function has been introduced rather than a flag because there is a lot
of variation between the ADCLK registers on JZ47xx SoCs, both in
the internal layout of the register and in the frequency range
supported by the SADC. So this solution should make it easier
to add support for other JZ47xx SoCs later.

Signed-off-by: Maarten ter Huurne <maarten@treewalker.org>
Signed-off-by: Artur Rojek <contact@artur-rojek.eu>
---
 drivers/iio/adc/ingenic-adc.c | 54 +++++++++++++++++++++++++++++++++++
 1 file changed, 54 insertions(+)

diff --git a/drivers/iio/adc/ingenic-adc.c b/drivers/iio/adc/ingenic-adc.c
index 92b1d5037ac9..e234970b7150 100644
--- a/drivers/iio/adc/ingenic-adc.c
+++ b/drivers/iio/adc/ingenic-adc.c
@@ -11,6 +11,7 @@
 #include <linux/iio/iio.h>
 #include <linux/io.h>
 #include <linux/iopoll.h>
+#include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/mutex.h>
 #include <linux/platform_device.h>
@@ -22,8 +23,11 @@
 #define JZ_ADC_REG_ADTCH		0x18
 #define JZ_ADC_REG_ADBDAT		0x1c
 #define JZ_ADC_REG_ADSDAT		0x20
+#define JZ_ADC_REG_ADCLK		0x28
 
 #define JZ_ADC_REG_CFG_BAT_MD		BIT(4)
+#define JZ_ADC_REG_ADCLK_CLKDIV_LSB	0
+#define JZ_ADC_REG_ADCLK_CLKDIV10US_LSB	16
 
 #define JZ_ADC_AUX_VREF				3300
 #define JZ_ADC_AUX_VREF_BITS			12
@@ -34,6 +38,8 @@
 #define JZ4740_ADC_BATTERY_HIGH_VREF		(7500 * 0.986)
 #define JZ4740_ADC_BATTERY_HIGH_VREF_BITS	12
 
+struct ingenic_adc;
+
 struct ingenic_adc_soc_data {
 	unsigned int battery_high_vref;
 	unsigned int battery_high_vref_bits;
@@ -41,6 +47,7 @@ struct ingenic_adc_soc_data {
 	size_t battery_raw_avail_size;
 	const int *battery_scale_avail;
 	size_t battery_scale_avail_size;
+	int (*init_clk_div)(struct device *dev, struct ingenic_adc *adc);
 };
 
 struct ingenic_adc {
@@ -151,6 +158,42 @@ static const int jz4740_adc_battery_scale_avail[] = {
 	JZ_ADC_BATTERY_LOW_VREF, JZ_ADC_BATTERY_LOW_VREF_BITS,
 };
 
+static int jz4725b_adc_init_clk_div(struct device *dev, struct ingenic_adc *adc)
+{
+	struct clk *parent_clk;
+	unsigned long parent_rate, rate;
+	unsigned int div_main, div_10us;
+
+	parent_clk = clk_get_parent(adc->clk);
+	if (!parent_clk) {
+		dev_err(dev, "ADC clock has no parent\n");
+		return -ENODEV;
+	}
+	parent_rate = clk_get_rate(parent_clk);
+
+	/*
+	 * The JZ4725B ADC works at 500 kHz to 8 MHz.
+	 * We pick the highest rate possible.
+	 * In practice we typically get 6 MHz, half of the 12 MHz EXT clock.
+	 */
+	div_main = DIV_ROUND_UP(parent_rate, 8000000);
+	div_main = clamp(div_main, 1u, 64u);
+	rate = parent_rate / div_main;
+	if (rate < 500000 || rate > 8000000) {
+		dev_err(dev, "No valid divider for ADC main clock\n");
+		return -EINVAL;
+	}
+
+	/* We also need a divider that produces a 10us clock. */
+	div_10us = DIV_ROUND_UP(rate, 100000);
+
+	writel(((div_10us - 1) << JZ_ADC_REG_ADCLK_CLKDIV10US_LSB) |
+	       (div_main - 1) << JZ_ADC_REG_ADCLK_CLKDIV_LSB,
+	       adc->base + JZ_ADC_REG_ADCLK);
+
+	return 0;
+}
+
 static const struct ingenic_adc_soc_data jz4725b_adc_soc_data = {
 	.battery_high_vref = JZ4725B_ADC_BATTERY_HIGH_VREF,
 	.battery_high_vref_bits = JZ4725B_ADC_BATTERY_HIGH_VREF_BITS,
@@ -158,6 +201,7 @@ static const struct ingenic_adc_soc_data jz4725b_adc_soc_data = {
 	.battery_raw_avail_size = ARRAY_SIZE(jz4725b_adc_battery_raw_avail),
 	.battery_scale_avail = jz4725b_adc_battery_scale_avail,
 	.battery_scale_avail_size = ARRAY_SIZE(jz4725b_adc_battery_scale_avail),
+	.init_clk_div = jz4725b_adc_init_clk_div,
 };
 
 static const struct ingenic_adc_soc_data jz4740_adc_soc_data = {
@@ -167,6 +211,7 @@ static const struct ingenic_adc_soc_data jz4740_adc_soc_data = {
 	.battery_raw_avail_size = ARRAY_SIZE(jz4740_adc_battery_raw_avail),
 	.battery_scale_avail = jz4740_adc_battery_scale_avail,
 	.battery_scale_avail_size = ARRAY_SIZE(jz4740_adc_battery_scale_avail),
+	.init_clk_div = NULL, /* no ADCLK register on JZ4740 */
 };
 
 static int ingenic_adc_read_avail(struct iio_dev *iio_dev,
@@ -317,6 +362,15 @@ static int ingenic_adc_probe(struct platform_device *pdev)
 		return ret;
 	}
 
+	/* Set clock dividers. */
+	if (soc_data->init_clk_div) {
+		ret = soc_data->init_clk_div(dev, adc);
+		if (ret) {
+			clk_disable_unprepare(adc->clk);
+			return ret;
+		}
+	}
+
 	/* Put hardware in a known passive state. */
 	writeb(0x00, adc->base + JZ_ADC_REG_ENABLE);
 	writeb(0xff, adc->base + JZ_ADC_REG_CTRL);
-- 
2.22.0


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 4/4] IIO: Ingenic JZ47xx: Add support for JZ4770 SoC ADC.
  2019-06-23 18:47 [PATCH 1/4] dt-bindings: iio/adc: Add a compatible string for JZ4770 SoC ADC Artur Rojek
  2019-06-23 18:47 ` [PATCH 2/4] dt-bindings: iio/adc: Add AUX2 channel idx " Artur Rojek
  2019-06-23 18:47 ` [PATCH 3/4] IIO: Ingenic JZ47xx: Set clock divider on probe Artur Rojek
@ 2019-06-23 18:47 ` Artur Rojek
  2019-06-26 19:59   ` Jonathan Cameron
  2019-07-10 13:52   ` Rob Herring
  3 siblings, 1 reply; 10+ messages in thread
From: Artur Rojek @ 2019-06-23 18:47 UTC (permalink / raw)
  To: Jonathan Cameron, Rob Herring, Mark Rutland
  Cc: linux-iio, devicetree, linux-kernel, Maarten ter Huurne,
	Paul Cercueil, Artur Rojek

Add support for the ADC hardware present on Ingenic JZ4770 SoC.

Signed-off-by: Artur Rojek <contact@artur-rojek.eu>
Tested-by: Paul Cercueil <paul@crapouillou.net>
---
 drivers/iio/adc/ingenic-adc.c | 134 +++++++++++++++++++++++++++++++---
 1 file changed, 123 insertions(+), 11 deletions(-)

diff --git a/drivers/iio/adc/ingenic-adc.c b/drivers/iio/adc/ingenic-adc.c
index e234970b7150..68d1c3280d1a 100644
--- a/drivers/iio/adc/ingenic-adc.c
+++ b/drivers/iio/adc/ingenic-adc.c
@@ -25,9 +25,13 @@
 #define JZ_ADC_REG_ADSDAT		0x20
 #define JZ_ADC_REG_ADCLK		0x28
 
+#define JZ_ADC_REG_ENABLE_PD		BIT(7)
+#define JZ_ADC_REG_CFG_AUX_MD		(BIT(0) | BIT(1))
 #define JZ_ADC_REG_CFG_BAT_MD		BIT(4)
 #define JZ_ADC_REG_ADCLK_CLKDIV_LSB	0
-#define JZ_ADC_REG_ADCLK_CLKDIV10US_LSB	16
+#define JZ4725B_ADC_REG_ADCLK_CLKDIV10US_LSB	16
+#define JZ4770_ADC_REG_ADCLK_CLKDIV10US_LSB	8
+#define JZ4770_ADC_REG_ADCLK_CLKDIVMS_LSB	16
 
 #define JZ_ADC_AUX_VREF				3300
 #define JZ_ADC_AUX_VREF_BITS			12
@@ -37,6 +41,8 @@
 #define JZ4725B_ADC_BATTERY_HIGH_VREF_BITS	10
 #define JZ4740_ADC_BATTERY_HIGH_VREF		(7500 * 0.986)
 #define JZ4740_ADC_BATTERY_HIGH_VREF_BITS	12
+#define JZ4770_ADC_BATTERY_VREF			6600
+#define JZ4770_ADC_BATTERY_VREF_BITS		12
 
 struct ingenic_adc;
 
@@ -47,6 +53,8 @@ struct ingenic_adc_soc_data {
 	size_t battery_raw_avail_size;
 	const int *battery_scale_avail;
 	size_t battery_scale_avail_size;
+	unsigned int battery_vref_mode: 1;
+	unsigned int has_aux2: 1;
 	int (*init_clk_div)(struct device *dev, struct ingenic_adc *adc);
 };
 
@@ -54,6 +62,7 @@ struct ingenic_adc {
 	void __iomem *base;
 	struct clk *clk;
 	struct mutex lock;
+	struct mutex aux_lock;
 	const struct ingenic_adc_soc_data *soc_data;
 	bool low_vref_mode;
 };
@@ -120,6 +129,8 @@ static int ingenic_adc_write_raw(struct iio_dev *iio_dev,
 	case IIO_CHAN_INFO_SCALE:
 		switch (chan->channel) {
 		case INGENIC_ADC_BATTERY:
+			if (!adc->soc_data->battery_vref_mode)
+				return -EINVAL;
 			if (val > JZ_ADC_BATTERY_LOW_VREF) {
 				ingenic_adc_set_config(adc,
 						       JZ_ADC_REG_CFG_BAT_MD,
@@ -158,6 +169,14 @@ static const int jz4740_adc_battery_scale_avail[] = {
 	JZ_ADC_BATTERY_LOW_VREF, JZ_ADC_BATTERY_LOW_VREF_BITS,
 };
 
+static const int jz4770_adc_battery_raw_avail[] = {
+	0, 1, (1 << JZ4770_ADC_BATTERY_VREF_BITS) - 1,
+};
+
+static const int jz4770_adc_battery_scale_avail[] = {
+	JZ4770_ADC_BATTERY_VREF, JZ4770_ADC_BATTERY_VREF_BITS,
+};
+
 static int jz4725b_adc_init_clk_div(struct device *dev, struct ingenic_adc *adc)
 {
 	struct clk *parent_clk;
@@ -187,7 +206,45 @@ static int jz4725b_adc_init_clk_div(struct device *dev, struct ingenic_adc *adc)
 	/* We also need a divider that produces a 10us clock. */
 	div_10us = DIV_ROUND_UP(rate, 100000);
 
-	writel(((div_10us - 1) << JZ_ADC_REG_ADCLK_CLKDIV10US_LSB) |
+	writel(((div_10us - 1) << JZ4725B_ADC_REG_ADCLK_CLKDIV10US_LSB) |
+	       (div_main - 1) << JZ_ADC_REG_ADCLK_CLKDIV_LSB,
+	       adc->base + JZ_ADC_REG_ADCLK);
+
+	return 0;
+}
+
+static int jz4770_adc_init_clk_div(struct device *dev, struct ingenic_adc *adc)
+{
+	struct clk *parent_clk;
+	unsigned long parent_rate, rate;
+	unsigned int div_main, div_ms, div_10us;
+
+	parent_clk = clk_get_parent(adc->clk);
+	if (!parent_clk) {
+		dev_err(dev, "ADC clock has no parent\n");
+		return -ENODEV;
+	}
+	parent_rate = clk_get_rate(parent_clk);
+
+	/*
+	 * The JZ4770 ADC works at 20 kHz to 200 kHz.
+	 * We pick the highest rate possible.
+	 */
+	div_main = DIV_ROUND_UP(parent_rate, 200000);
+	div_main = clamp(div_main, 1u, 256u);
+	rate = parent_rate / div_main;
+	if (rate < 20000 || rate > 200000) {
+		dev_err(dev, "No valid divider for ADC main clock\n");
+		return -EINVAL;
+	}
+
+	/* We also need a divider that produces a 10us clock. */
+	div_10us = DIV_ROUND_UP(rate, 10000);
+	/* And another, which produces a 1ms clock. */
+	div_ms = DIV_ROUND_UP(rate, 1000);
+
+	writel(((div_ms - 1) << JZ4770_ADC_REG_ADCLK_CLKDIVMS_LSB) |
+	       ((div_10us - 1) << JZ4770_ADC_REG_ADCLK_CLKDIV10US_LSB) |
 	       (div_main - 1) << JZ_ADC_REG_ADCLK_CLKDIV_LSB,
 	       adc->base + JZ_ADC_REG_ADCLK);
 
@@ -201,6 +258,8 @@ static const struct ingenic_adc_soc_data jz4725b_adc_soc_data = {
 	.battery_raw_avail_size = ARRAY_SIZE(jz4725b_adc_battery_raw_avail),
 	.battery_scale_avail = jz4725b_adc_battery_scale_avail,
 	.battery_scale_avail_size = ARRAY_SIZE(jz4725b_adc_battery_scale_avail),
+	.battery_vref_mode = true,
+	.has_aux2 = false,
 	.init_clk_div = jz4725b_adc_init_clk_div,
 };
 
@@ -211,9 +270,23 @@ static const struct ingenic_adc_soc_data jz4740_adc_soc_data = {
 	.battery_raw_avail_size = ARRAY_SIZE(jz4740_adc_battery_raw_avail),
 	.battery_scale_avail = jz4740_adc_battery_scale_avail,
 	.battery_scale_avail_size = ARRAY_SIZE(jz4740_adc_battery_scale_avail),
+	.battery_vref_mode = true,
+	.has_aux2 = false,
 	.init_clk_div = NULL, /* no ADCLK register on JZ4740 */
 };
 
+static const struct ingenic_adc_soc_data jz4770_adc_soc_data = {
+	.battery_high_vref = JZ4770_ADC_BATTERY_VREF,
+	.battery_high_vref_bits = JZ4770_ADC_BATTERY_VREF_BITS,
+	.battery_raw_avail = jz4770_adc_battery_raw_avail,
+	.battery_raw_avail_size = ARRAY_SIZE(jz4770_adc_battery_raw_avail),
+	.battery_scale_avail = jz4770_adc_battery_scale_avail,
+	.battery_scale_avail_size = ARRAY_SIZE(jz4770_adc_battery_scale_avail),
+	.battery_vref_mode = false,
+	.has_aux2 = true,
+	.init_clk_div = jz4770_adc_init_clk_div,
+};
+
 static int ingenic_adc_read_avail(struct iio_dev *iio_dev,
 				  struct iio_chan_spec const *chan,
 				  const int **vals,
@@ -246,19 +319,37 @@ static int ingenic_adc_read_raw(struct iio_dev *iio_dev,
 				long m)
 {
 	struct ingenic_adc *adc = iio_priv(iio_dev);
-	int ret;
+	struct mutex *lock = NULL;
+	int bit, ret, engine = 0;
 
 	switch (m) {
 	case IIO_CHAN_INFO_RAW:
-		clk_enable(adc->clk);
-		ret = ingenic_adc_capture(adc, chan->channel);
-		if (ret) {
-			clk_disable(adc->clk);
-			return ret;
+		switch (chan->channel) {
+		case INGENIC_ADC_AUX:
+		case INGENIC_ADC_AUX2:
+			if (adc->soc_data->has_aux2)
+				lock = &adc->aux_lock;
+			break;
+		case INGENIC_ADC_BATTERY:
+			engine = 1;
+			break;
 		}
 
+		if (lock) /* We cannot sample AUX/AUX2 in parallel. */
+			mutex_lock(lock);
+		if (adc->soc_data->has_aux2 && engine == 0) {
+			bit = BIT(chan->channel == INGENIC_ADC_AUX2);
+			ingenic_adc_set_config(adc, JZ_ADC_REG_CFG_AUX_MD, bit);
+		}
+
+		clk_enable(adc->clk);
+		ret = ingenic_adc_capture(adc, engine);
+		if (ret)
+			goto out;
+
 		switch (chan->channel) {
 		case INGENIC_ADC_AUX:
+		case INGENIC_ADC_AUX2:
 			*val = readw(adc->base + JZ_ADC_REG_ADSDAT);
 			break;
 		case INGENIC_ADC_BATTERY:
@@ -266,12 +357,12 @@ static int ingenic_adc_read_raw(struct iio_dev *iio_dev,
 			break;
 		}
 
-		clk_disable(adc->clk);
-
-		return IIO_VAL_INT;
+		ret = IIO_VAL_INT;
+		goto out;
 	case IIO_CHAN_INFO_SCALE:
 		switch (chan->channel) {
 		case INGENIC_ADC_AUX:
+		case INGENIC_ADC_AUX2:
 			*val = JZ_ADC_AUX_VREF;
 			*val2 = JZ_ADC_AUX_VREF_BITS;
 			break;
@@ -290,6 +381,13 @@ static int ingenic_adc_read_raw(struct iio_dev *iio_dev,
 	default:
 		return -EINVAL;
 	}
+
+out:
+	clk_disable(adc->clk);
+	if (lock)
+		mutex_unlock(lock);
+
+	return ret;
 }
 
 static void ingenic_adc_clk_cleanup(void *data)
@@ -322,6 +420,14 @@ static const struct iio_chan_spec ingenic_channels[] = {
 		.indexed = 1,
 		.channel = INGENIC_ADC_BATTERY,
 	},
+	{ /* Must always be last in the array. */
+		.extend_name = "aux2",
+		.type = IIO_VOLTAGE,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+				      BIT(IIO_CHAN_INFO_SCALE),
+		.indexed = 1,
+		.channel = INGENIC_ADC_AUX2,
+	},
 };
 
 static int ingenic_adc_probe(struct platform_device *pdev)
@@ -343,6 +449,7 @@ static int ingenic_adc_probe(struct platform_device *pdev)
 
 	adc = iio_priv(iio_dev);
 	mutex_init(&adc->lock);
+	mutex_init(&adc->aux_lock);
 	adc->soc_data = soc_data;
 
 	mem_base = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -374,6 +481,7 @@ static int ingenic_adc_probe(struct platform_device *pdev)
 	/* Put hardware in a known passive state. */
 	writeb(0x00, adc->base + JZ_ADC_REG_ENABLE);
 	writeb(0xff, adc->base + JZ_ADC_REG_CTRL);
+	usleep_range(2000, 3000); /* Must wait at least 2ms. */
 	clk_disable(adc->clk);
 
 	ret = devm_add_action_or_reset(dev, ingenic_adc_clk_cleanup, adc->clk);
@@ -387,6 +495,9 @@ static int ingenic_adc_probe(struct platform_device *pdev)
 	iio_dev->modes = INDIO_DIRECT_MODE;
 	iio_dev->channels = ingenic_channels;
 	iio_dev->num_channels = ARRAY_SIZE(ingenic_channels);
+	/* Remove AUX2 from the list of supported channels. */
+	if (!adc->soc_data->has_aux2)
+		iio_dev->num_channels -= 1;
 	iio_dev->info = &ingenic_adc_info;
 
 	ret = devm_iio_device_register(dev, iio_dev);
@@ -400,6 +511,7 @@ static int ingenic_adc_probe(struct platform_device *pdev)
 static const struct of_device_id ingenic_adc_of_match[] = {
 	{ .compatible = "ingenic,jz4725b-adc", .data = &jz4725b_adc_soc_data, },
 	{ .compatible = "ingenic,jz4740-adc", .data = &jz4740_adc_soc_data, },
+	{ .compatible = "ingenic,jz4770-adc", .data = &jz4770_adc_soc_data, },
 	{ },
 };
 MODULE_DEVICE_TABLE(of, ingenic_adc_of_match);
-- 
2.22.0


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* Re: [PATCH 4/4] IIO: Ingenic JZ47xx: Add support for JZ4770 SoC ADC.
  2019-06-23 18:47 ` [PATCH 4/4] IIO: Ingenic JZ47xx: Add support for JZ4770 SoC ADC Artur Rojek
@ 2019-06-26 19:59   ` Jonathan Cameron
  0 siblings, 0 replies; 10+ messages in thread
From: Jonathan Cameron @ 2019-06-26 19:59 UTC (permalink / raw)
  To: Artur Rojek
  Cc: Rob Herring, Mark Rutland, linux-iio, devicetree, linux-kernel,
	Maarten ter Huurne, Paul Cercueil

On Sun, 23 Jun 2019 20:47:32 +0200
Artur Rojek <contact@artur-rojek.eu> wrote:

> Add support for the ADC hardware present on Ingenic JZ4770 SoC.
> 
> Signed-off-by: Artur Rojek <contact@artur-rojek.eu>
> Tested-by: Paul Cercueil <paul@crapouillou.net>
Hi

A few minor comments inline.  Main one is that I'd like some numbers
to justify the added complexity in avoiding he uncontended mutex in
the cases where we don't 'need' it.  That makes the code more
complex, and I would like to have evidence that it is worth it.

Thanks,

Jonathan

> ---
>  drivers/iio/adc/ingenic-adc.c | 134 +++++++++++++++++++++++++++++++---
>  1 file changed, 123 insertions(+), 11 deletions(-)
> 
> diff --git a/drivers/iio/adc/ingenic-adc.c b/drivers/iio/adc/ingenic-adc.c
> index e234970b7150..68d1c3280d1a 100644
> --- a/drivers/iio/adc/ingenic-adc.c
> +++ b/drivers/iio/adc/ingenic-adc.c
> @@ -25,9 +25,13 @@
>  #define JZ_ADC_REG_ADSDAT		0x20
>  #define JZ_ADC_REG_ADCLK		0x28
>  
> +#define JZ_ADC_REG_ENABLE_PD		BIT(7)
> +#define JZ_ADC_REG_CFG_AUX_MD		(BIT(0) | BIT(1))
>  #define JZ_ADC_REG_CFG_BAT_MD		BIT(4)
>  #define JZ_ADC_REG_ADCLK_CLKDIV_LSB	0
> -#define JZ_ADC_REG_ADCLK_CLKDIV10US_LSB	16
> +#define JZ4725B_ADC_REG_ADCLK_CLKDIV10US_LSB	16
> +#define JZ4770_ADC_REG_ADCLK_CLKDIV10US_LSB	8
> +#define JZ4770_ADC_REG_ADCLK_CLKDIVMS_LSB	16
>  
>  #define JZ_ADC_AUX_VREF				3300
>  #define JZ_ADC_AUX_VREF_BITS			12
> @@ -37,6 +41,8 @@
>  #define JZ4725B_ADC_BATTERY_HIGH_VREF_BITS	10
>  #define JZ4740_ADC_BATTERY_HIGH_VREF		(7500 * 0.986)
>  #define JZ4740_ADC_BATTERY_HIGH_VREF_BITS	12
> +#define JZ4770_ADC_BATTERY_VREF			6600
> +#define JZ4770_ADC_BATTERY_VREF_BITS		12
>  
>  struct ingenic_adc;
>  
> @@ -47,6 +53,8 @@ struct ingenic_adc_soc_data {
>  	size_t battery_raw_avail_size;
>  	const int *battery_scale_avail;
>  	size_t battery_scale_avail_size;
> +	unsigned int battery_vref_mode: 1;
> +	unsigned int has_aux2: 1;
>  	int (*init_clk_div)(struct device *dev, struct ingenic_adc *adc);
>  };
>  
> @@ -54,6 +62,7 @@ struct ingenic_adc {
>  	void __iomem *base;
>  	struct clk *clk;
>  	struct mutex lock;
> +	struct mutex aux_lock;
>  	const struct ingenic_adc_soc_data *soc_data;
>  	bool low_vref_mode;
>  };
> @@ -120,6 +129,8 @@ static int ingenic_adc_write_raw(struct iio_dev *iio_dev,
>  	case IIO_CHAN_INFO_SCALE:
>  		switch (chan->channel) {
>  		case INGENIC_ADC_BATTERY:
> +			if (!adc->soc_data->battery_vref_mode)
> +				return -EINVAL;
>  			if (val > JZ_ADC_BATTERY_LOW_VREF) {
>  				ingenic_adc_set_config(adc,
>  						       JZ_ADC_REG_CFG_BAT_MD,
> @@ -158,6 +169,14 @@ static const int jz4740_adc_battery_scale_avail[] = {
>  	JZ_ADC_BATTERY_LOW_VREF, JZ_ADC_BATTERY_LOW_VREF_BITS,
>  };
>  
> +static const int jz4770_adc_battery_raw_avail[] = {
> +	0, 1, (1 << JZ4770_ADC_BATTERY_VREF_BITS) - 1,
> +};
> +
> +static const int jz4770_adc_battery_scale_avail[] = {
> +	JZ4770_ADC_BATTERY_VREF, JZ4770_ADC_BATTERY_VREF_BITS,
> +};
> +
>  static int jz4725b_adc_init_clk_div(struct device *dev, struct ingenic_adc *adc)
>  {
>  	struct clk *parent_clk;
> @@ -187,7 +206,45 @@ static int jz4725b_adc_init_clk_div(struct device *dev, struct ingenic_adc *adc)
>  	/* We also need a divider that produces a 10us clock. */
>  	div_10us = DIV_ROUND_UP(rate, 100000);
>  
> -	writel(((div_10us - 1) << JZ_ADC_REG_ADCLK_CLKDIV10US_LSB) |
> +	writel(((div_10us - 1) << JZ4725B_ADC_REG_ADCLK_CLKDIV10US_LSB) |
> +	       (div_main - 1) << JZ_ADC_REG_ADCLK_CLKDIV_LSB,
> +	       adc->base + JZ_ADC_REG_ADCLK);
> +
> +	return 0;
> +}
> +
> +static int jz4770_adc_init_clk_div(struct device *dev, struct ingenic_adc *adc)
> +{
> +	struct clk *parent_clk;
> +	unsigned long parent_rate, rate;
> +	unsigned int div_main, div_ms, div_10us;
> +
> +	parent_clk = clk_get_parent(adc->clk);
> +	if (!parent_clk) {
> +		dev_err(dev, "ADC clock has no parent\n");
> +		return -ENODEV;
> +	}
> +	parent_rate = clk_get_rate(parent_clk);
> +
> +	/*
> +	 * The JZ4770 ADC works at 20 kHz to 200 kHz.
> +	 * We pick the highest rate possible.
> +	 */
> +	div_main = DIV_ROUND_UP(parent_rate, 200000);
> +	div_main = clamp(div_main, 1u, 256u);
> +	rate = parent_rate / div_main;
> +	if (rate < 20000 || rate > 200000) {
> +		dev_err(dev, "No valid divider for ADC main clock\n");
> +		return -EINVAL;
> +	}
> +
> +	/* We also need a divider that produces a 10us clock. */
> +	div_10us = DIV_ROUND_UP(rate, 10000);
> +	/* And another, which produces a 1ms clock. */
> +	div_ms = DIV_ROUND_UP(rate, 1000);
> +
> +	writel(((div_ms - 1) << JZ4770_ADC_REG_ADCLK_CLKDIVMS_LSB) |
> +	       ((div_10us - 1) << JZ4770_ADC_REG_ADCLK_CLKDIV10US_LSB) |
>  	       (div_main - 1) << JZ_ADC_REG_ADCLK_CLKDIV_LSB,
>  	       adc->base + JZ_ADC_REG_ADCLK);
>  
> @@ -201,6 +258,8 @@ static const struct ingenic_adc_soc_data jz4725b_adc_soc_data = {
>  	.battery_raw_avail_size = ARRAY_SIZE(jz4725b_adc_battery_raw_avail),
>  	.battery_scale_avail = jz4725b_adc_battery_scale_avail,
>  	.battery_scale_avail_size = ARRAY_SIZE(jz4725b_adc_battery_scale_avail),
> +	.battery_vref_mode = true,
> +	.has_aux2 = false,
>  	.init_clk_div = jz4725b_adc_init_clk_div,
>  };
>  
> @@ -211,9 +270,23 @@ static const struct ingenic_adc_soc_data jz4740_adc_soc_data = {
>  	.battery_raw_avail_size = ARRAY_SIZE(jz4740_adc_battery_raw_avail),
>  	.battery_scale_avail = jz4740_adc_battery_scale_avail,
>  	.battery_scale_avail_size = ARRAY_SIZE(jz4740_adc_battery_scale_avail),
> +	.battery_vref_mode = true,
> +	.has_aux2 = false,
>  	.init_clk_div = NULL, /* no ADCLK register on JZ4740 */
>  };
>  
> +static const struct ingenic_adc_soc_data jz4770_adc_soc_data = {
> +	.battery_high_vref = JZ4770_ADC_BATTERY_VREF,
> +	.battery_high_vref_bits = JZ4770_ADC_BATTERY_VREF_BITS,
> +	.battery_raw_avail = jz4770_adc_battery_raw_avail,
> +	.battery_raw_avail_size = ARRAY_SIZE(jz4770_adc_battery_raw_avail),
> +	.battery_scale_avail = jz4770_adc_battery_scale_avail,
> +	.battery_scale_avail_size = ARRAY_SIZE(jz4770_adc_battery_scale_avail),
> +	.battery_vref_mode = false,
> +	.has_aux2 = true,
> +	.init_clk_div = jz4770_adc_init_clk_div,
> +};
> +
>  static int ingenic_adc_read_avail(struct iio_dev *iio_dev,
>  				  struct iio_chan_spec const *chan,
>  				  const int **vals,
> @@ -246,19 +319,37 @@ static int ingenic_adc_read_raw(struct iio_dev *iio_dev,
>  				long m)
>  {
>  	struct ingenic_adc *adc = iio_priv(iio_dev);
> -	int ret;
> +	struct mutex *lock = NULL;

The cost of a lock when not contended should be pretty low.
If we are going to do the optimization of not having the lock for
the single channel case, then I'd like some performance numbers
to justify the complexity.  What difference is it making?

> +	int bit, ret, engine = 0;
>  
>  	switch (m) {
>  	case IIO_CHAN_INFO_RAW:
> -		clk_enable(adc->clk);
> -		ret = ingenic_adc_capture(adc, chan->channel);
> -		if (ret) {
> -			clk_disable(adc->clk);
> -			return ret;
> +		switch (chan->channel) {
> +		case INGENIC_ADC_AUX:
> +		case INGENIC_ADC_AUX2:
> +			if (adc->soc_data->has_aux2)
> +				lock = &adc->aux_lock;
> +			break;
> +		case INGENIC_ADC_BATTERY:
> +			engine = 1;
> +			break;
>  		}
>  
> +		if (lock) /* We cannot sample AUX/AUX2 in parallel. */
> +			mutex_lock(lock);
> +		if (adc->soc_data->has_aux2 && engine == 0) {
> +			bit = BIT(chan->channel == INGENIC_ADC_AUX2);
> +			ingenic_adc_set_config(adc, JZ_ADC_REG_CFG_AUX_MD, bit);
> +		}
> +
> +		clk_enable(adc->clk);
> +		ret = ingenic_adc_capture(adc, engine);
> +		if (ret)
> +			goto out;
> +
>  		switch (chan->channel) {
>  		case INGENIC_ADC_AUX:
> +		case INGENIC_ADC_AUX2:
>  			*val = readw(adc->base + JZ_ADC_REG_ADSDAT);
>  			break;
>  		case INGENIC_ADC_BATTERY:
> @@ -266,12 +357,12 @@ static int ingenic_adc_read_raw(struct iio_dev *iio_dev,
>  			break;
>  		}
>  
> -		clk_disable(adc->clk);
> -
> -		return IIO_VAL_INT;
> +		ret = IIO_VAL_INT;
> +		goto out;
>  	case IIO_CHAN_INFO_SCALE:
>  		switch (chan->channel) {
>  		case INGENIC_ADC_AUX:
> +		case INGENIC_ADC_AUX2:
>  			*val = JZ_ADC_AUX_VREF;
>  			*val2 = JZ_ADC_AUX_VREF_BITS;
>  			break;
> @@ -290,6 +381,13 @@ static int ingenic_adc_read_raw(struct iio_dev *iio_dev,
>  	default:
>  		return -EINVAL;
>  	}
> +
> +out:
> +	clk_disable(adc->clk);

A bit tricky to follow with this code structure. I'd suggest factoring
out the _RAW block as a utility function so we can avoid the
breaking out of deeply nested code to the handler like this.

> +	if (lock)
> +		mutex_unlock(lock);
> +
> +	return ret;
>  }
>  
>  static void ingenic_adc_clk_cleanup(void *data)
> @@ -322,6 +420,14 @@ static const struct iio_chan_spec ingenic_channels[] = {
>  		.indexed = 1,
>  		.channel = INGENIC_ADC_BATTERY,
>  	},
> +	{ /* Must always be last in the array. */
> +		.extend_name = "aux2",
> +		.type = IIO_VOLTAGE,
> +		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
> +				      BIT(IIO_CHAN_INFO_SCALE),
> +		.indexed = 1,
> +		.channel = INGENIC_ADC_AUX2,
> +	},
>  };
>  
>  static int ingenic_adc_probe(struct platform_device *pdev)
> @@ -343,6 +449,7 @@ static int ingenic_adc_probe(struct platform_device *pdev)
>  
>  	adc = iio_priv(iio_dev);
>  	mutex_init(&adc->lock);
> +	mutex_init(&adc->aux_lock);
>  	adc->soc_data = soc_data;
>  
>  	mem_base = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> @@ -374,6 +481,7 @@ static int ingenic_adc_probe(struct platform_device *pdev)
>  	/* Put hardware in a known passive state. */
>  	writeb(0x00, adc->base + JZ_ADC_REG_ENABLE);
>  	writeb(0xff, adc->base + JZ_ADC_REG_CTRL);
> +	usleep_range(2000, 3000); /* Must wait at least 2ms. */
>  	clk_disable(adc->clk);
>  
>  	ret = devm_add_action_or_reset(dev, ingenic_adc_clk_cleanup, adc->clk);
> @@ -387,6 +495,9 @@ static int ingenic_adc_probe(struct platform_device *pdev)
>  	iio_dev->modes = INDIO_DIRECT_MODE;
>  	iio_dev->channels = ingenic_channels;
>  	iio_dev->num_channels = ARRAY_SIZE(ingenic_channels);
> +	/* Remove AUX2 from the list of supported channels. */
> +	if (!adc->soc_data->has_aux2)
> +		iio_dev->num_channels -= 1;
>  	iio_dev->info = &ingenic_adc_info;
>  
>  	ret = devm_iio_device_register(dev, iio_dev);
> @@ -400,6 +511,7 @@ static int ingenic_adc_probe(struct platform_device *pdev)
>  static const struct of_device_id ingenic_adc_of_match[] = {
>  	{ .compatible = "ingenic,jz4725b-adc", .data = &jz4725b_adc_soc_data, },
>  	{ .compatible = "ingenic,jz4740-adc", .data = &jz4740_adc_soc_data, },
> +	{ .compatible = "ingenic,jz4770-adc", .data = &jz4770_adc_soc_data, },
>  	{ },
>  };
>  MODULE_DEVICE_TABLE(of, ingenic_adc_of_match);


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 3/4] IIO: Ingenic JZ47xx: Set clock divider on probe
  2019-06-23 18:47 ` [PATCH 3/4] IIO: Ingenic JZ47xx: Set clock divider on probe Artur Rojek
@ 2019-06-26 20:00   ` Jonathan Cameron
  0 siblings, 0 replies; 10+ messages in thread
From: Jonathan Cameron @ 2019-06-26 20:00 UTC (permalink / raw)
  To: Artur Rojek
  Cc: Rob Herring, Mark Rutland, linux-iio, devicetree, linux-kernel,
	Maarten ter Huurne, Paul Cercueil

On Sun, 23 Jun 2019 20:47:31 +0200
Artur Rojek <contact@artur-rojek.eu> wrote:

> From: Maarten ter Huurne <maarten@treewalker.org>
> 
> The SADC component can run at up to 8 MHz on JZ4725B, but is fed
> a 12 MHz input clock (EXT). Divide it by two to get 6 MHz, then
> set up another divider to match, to produce a 10us clock.
> 
> If the clock dividers are left on their power-on defaults (a divider
> of 1), the SADC mostly works, but will occasionally produce erroneous
> readings. This led to button presses being detected out of nowhere on
> the RS90 every few minutes. With this change, no ghost button presses
> were logged in almost a day worth of testing.
> 
> The ADCLK register for configuring clock dividers doesn't exist on
> JZ4740, so avoid writing it there.
> 
> A function has been introduced rather than a flag because there is a lot
> of variation between the ADCLK registers on JZ47xx SoCs, both in
> the internal layout of the register and in the frequency range
> supported by the SADC. So this solution should make it easier
> to add support for other JZ47xx SoCs later.
> 
> Signed-off-by: Maarten ter Huurne <maarten@treewalker.org>
> Signed-off-by: Artur Rojek <contact@artur-rojek.eu>
This sounds like it perhaps should be marked as a fix and have appropriate
fixes tag?  Otherwise, looks fine to me.

Jonathan

> ---
>  drivers/iio/adc/ingenic-adc.c | 54 +++++++++++++++++++++++++++++++++++
>  1 file changed, 54 insertions(+)
> 
> diff --git a/drivers/iio/adc/ingenic-adc.c b/drivers/iio/adc/ingenic-adc.c
> index 92b1d5037ac9..e234970b7150 100644
> --- a/drivers/iio/adc/ingenic-adc.c
> +++ b/drivers/iio/adc/ingenic-adc.c
> @@ -11,6 +11,7 @@
>  #include <linux/iio/iio.h>
>  #include <linux/io.h>
>  #include <linux/iopoll.h>
> +#include <linux/kernel.h>
>  #include <linux/module.h>
>  #include <linux/mutex.h>
>  #include <linux/platform_device.h>
> @@ -22,8 +23,11 @@
>  #define JZ_ADC_REG_ADTCH		0x18
>  #define JZ_ADC_REG_ADBDAT		0x1c
>  #define JZ_ADC_REG_ADSDAT		0x20
> +#define JZ_ADC_REG_ADCLK		0x28
>  
>  #define JZ_ADC_REG_CFG_BAT_MD		BIT(4)
> +#define JZ_ADC_REG_ADCLK_CLKDIV_LSB	0
> +#define JZ_ADC_REG_ADCLK_CLKDIV10US_LSB	16
>  
>  #define JZ_ADC_AUX_VREF				3300
>  #define JZ_ADC_AUX_VREF_BITS			12
> @@ -34,6 +38,8 @@
>  #define JZ4740_ADC_BATTERY_HIGH_VREF		(7500 * 0.986)
>  #define JZ4740_ADC_BATTERY_HIGH_VREF_BITS	12
>  
> +struct ingenic_adc;
> +
>  struct ingenic_adc_soc_data {
>  	unsigned int battery_high_vref;
>  	unsigned int battery_high_vref_bits;
> @@ -41,6 +47,7 @@ struct ingenic_adc_soc_data {
>  	size_t battery_raw_avail_size;
>  	const int *battery_scale_avail;
>  	size_t battery_scale_avail_size;
> +	int (*init_clk_div)(struct device *dev, struct ingenic_adc *adc);
>  };
>  
>  struct ingenic_adc {
> @@ -151,6 +158,42 @@ static const int jz4740_adc_battery_scale_avail[] = {
>  	JZ_ADC_BATTERY_LOW_VREF, JZ_ADC_BATTERY_LOW_VREF_BITS,
>  };
>  
> +static int jz4725b_adc_init_clk_div(struct device *dev, struct ingenic_adc *adc)
> +{
> +	struct clk *parent_clk;
> +	unsigned long parent_rate, rate;
> +	unsigned int div_main, div_10us;
> +
> +	parent_clk = clk_get_parent(adc->clk);
> +	if (!parent_clk) {
> +		dev_err(dev, "ADC clock has no parent\n");
> +		return -ENODEV;
> +	}
> +	parent_rate = clk_get_rate(parent_clk);
> +
> +	/*
> +	 * The JZ4725B ADC works at 500 kHz to 8 MHz.
> +	 * We pick the highest rate possible.
> +	 * In practice we typically get 6 MHz, half of the 12 MHz EXT clock.
> +	 */
> +	div_main = DIV_ROUND_UP(parent_rate, 8000000);
> +	div_main = clamp(div_main, 1u, 64u);
> +	rate = parent_rate / div_main;
> +	if (rate < 500000 || rate > 8000000) {
> +		dev_err(dev, "No valid divider for ADC main clock\n");
> +		return -EINVAL;
> +	}
> +
> +	/* We also need a divider that produces a 10us clock. */
> +	div_10us = DIV_ROUND_UP(rate, 100000);
> +
> +	writel(((div_10us - 1) << JZ_ADC_REG_ADCLK_CLKDIV10US_LSB) |
> +	       (div_main - 1) << JZ_ADC_REG_ADCLK_CLKDIV_LSB,
> +	       adc->base + JZ_ADC_REG_ADCLK);
> +
> +	return 0;
> +}
> +
>  static const struct ingenic_adc_soc_data jz4725b_adc_soc_data = {
>  	.battery_high_vref = JZ4725B_ADC_BATTERY_HIGH_VREF,
>  	.battery_high_vref_bits = JZ4725B_ADC_BATTERY_HIGH_VREF_BITS,
> @@ -158,6 +201,7 @@ static const struct ingenic_adc_soc_data jz4725b_adc_soc_data = {
>  	.battery_raw_avail_size = ARRAY_SIZE(jz4725b_adc_battery_raw_avail),
>  	.battery_scale_avail = jz4725b_adc_battery_scale_avail,
>  	.battery_scale_avail_size = ARRAY_SIZE(jz4725b_adc_battery_scale_avail),
> +	.init_clk_div = jz4725b_adc_init_clk_div,
>  };
>  
>  static const struct ingenic_adc_soc_data jz4740_adc_soc_data = {
> @@ -167,6 +211,7 @@ static const struct ingenic_adc_soc_data jz4740_adc_soc_data = {
>  	.battery_raw_avail_size = ARRAY_SIZE(jz4740_adc_battery_raw_avail),
>  	.battery_scale_avail = jz4740_adc_battery_scale_avail,
>  	.battery_scale_avail_size = ARRAY_SIZE(jz4740_adc_battery_scale_avail),
> +	.init_clk_div = NULL, /* no ADCLK register on JZ4740 */
>  };
>  
>  static int ingenic_adc_read_avail(struct iio_dev *iio_dev,
> @@ -317,6 +362,15 @@ static int ingenic_adc_probe(struct platform_device *pdev)
>  		return ret;
>  	}
>  
> +	/* Set clock dividers. */
> +	if (soc_data->init_clk_div) {
> +		ret = soc_data->init_clk_div(dev, adc);
> +		if (ret) {
> +			clk_disable_unprepare(adc->clk);
> +			return ret;
> +		}
> +	}
> +
>  	/* Put hardware in a known passive state. */
>  	writeb(0x00, adc->base + JZ_ADC_REG_ENABLE);
>  	writeb(0xff, adc->base + JZ_ADC_REG_CTRL);


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 1/4] dt-bindings: iio/adc: Add a compatible string for JZ4770 SoC ADC
  2019-06-23 18:47 [PATCH 1/4] dt-bindings: iio/adc: Add a compatible string for JZ4770 SoC ADC Artur Rojek
@ 2019-07-10 13:52   ` Rob Herring
  2019-06-23 18:47 ` [PATCH 3/4] IIO: Ingenic JZ47xx: Set clock divider on probe Artur Rojek
                     ` (2 subsequent siblings)
  3 siblings, 0 replies; 10+ messages in thread
From: Rob Herring @ 2019-07-10 13:52 UTC (permalink / raw)
  To: Artur Rojek
  Cc: Jonathan Cameron, Mark Rutland, linux-iio, devicetree,
	linux-kernel, Maarten ter Huurne, Paul Cercueil, Artur Rojek

On Sun, 23 Jun 2019 20:47:29 +0200, Artur Rojek wrote:
> Add a compatible string for the ADC controller present on
> Ingenic JZ4770 SoC.
> 
> Signed-off-by: Artur Rojek <contact@artur-rojek.eu>
> ---
>  Documentation/devicetree/bindings/iio/adc/ingenic,adc.txt | 1 +
>  1 file changed, 1 insertion(+)
> 

Reviewed-by: Rob Herring <robh@kernel.org>

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 1/4] dt-bindings: iio/adc: Add a compatible string for JZ4770 SoC ADC
@ 2019-07-10 13:52   ` Rob Herring
  0 siblings, 0 replies; 10+ messages in thread
From: Rob Herring @ 2019-07-10 13:52 UTC (permalink / raw)
  Cc: Jonathan Cameron, Mark Rutland, linux-iio, devicetree,
	linux-kernel, Maarten ter Huurne, Paul Cercueil, Artur Rojek

On Sun, 23 Jun 2019 20:47:29 +0200, Artur Rojek wrote:
> Add a compatible string for the ADC controller present on
> Ingenic JZ4770 SoC.
> 
> Signed-off-by: Artur Rojek <contact@artur-rojek.eu>
> ---
>  Documentation/devicetree/bindings/iio/adc/ingenic,adc.txt | 1 +
>  1 file changed, 1 insertion(+)
> 

Reviewed-by: Rob Herring <robh@kernel.org>

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 2/4] dt-bindings: iio/adc: Add AUX2 channel idx for JZ4770 SoC ADC
  2019-06-23 18:47 ` [PATCH 2/4] dt-bindings: iio/adc: Add AUX2 channel idx " Artur Rojek
@ 2019-07-10 13:53     ` Rob Herring
  0 siblings, 0 replies; 10+ messages in thread
From: Rob Herring @ 2019-07-10 13:53 UTC (permalink / raw)
  To: Artur Rojek
  Cc: Jonathan Cameron, Mark Rutland, linux-iio, devicetree,
	linux-kernel, Maarten ter Huurne, Paul Cercueil, Artur Rojek

On Sun, 23 Jun 2019 20:47:30 +0200, Artur Rojek wrote:
> Introduce support for AUX2 channel found in ADC hardware present on
> Ingenic JZ4770 SoC.
> 
> Signed-off-by: Artur Rojek <contact@artur-rojek.eu>
> ---
>  include/dt-bindings/iio/adc/ingenic,adc.h | 1 +
>  1 file changed, 1 insertion(+)
> 

Reviewed-by: Rob Herring <robh@kernel.org>

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 2/4] dt-bindings: iio/adc: Add AUX2 channel idx for JZ4770 SoC ADC
@ 2019-07-10 13:53     ` Rob Herring
  0 siblings, 0 replies; 10+ messages in thread
From: Rob Herring @ 2019-07-10 13:53 UTC (permalink / raw)
  Cc: Jonathan Cameron, Mark Rutland, linux-iio, devicetree,
	linux-kernel, Maarten ter Huurne, Paul Cercueil, Artur Rojek

On Sun, 23 Jun 2019 20:47:30 +0200, Artur Rojek wrote:
> Introduce support for AUX2 channel found in ADC hardware present on
> Ingenic JZ4770 SoC.
> 
> Signed-off-by: Artur Rojek <contact@artur-rojek.eu>
> ---
>  include/dt-bindings/iio/adc/ingenic,adc.h | 1 +
>  1 file changed, 1 insertion(+)
> 

Reviewed-by: Rob Herring <robh@kernel.org>

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2019-07-10 13:53 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-06-23 18:47 [PATCH 1/4] dt-bindings: iio/adc: Add a compatible string for JZ4770 SoC ADC Artur Rojek
2019-06-23 18:47 ` [PATCH 2/4] dt-bindings: iio/adc: Add AUX2 channel idx " Artur Rojek
2019-07-10 13:53   ` Rob Herring
2019-07-10 13:53     ` Rob Herring
2019-06-23 18:47 ` [PATCH 3/4] IIO: Ingenic JZ47xx: Set clock divider on probe Artur Rojek
2019-06-26 20:00   ` Jonathan Cameron
2019-06-23 18:47 ` [PATCH 4/4] IIO: Ingenic JZ47xx: Add support for JZ4770 SoC ADC Artur Rojek
2019-06-26 19:59   ` Jonathan Cameron
2019-07-10 13:52 ` [PATCH 1/4] dt-bindings: iio/adc: Add a compatible string " Rob Herring
2019-07-10 13:52   ` Rob Herring

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.