linux-iio.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/5] iio: Minor cleanups to spear ADC driver followed by staging graduation.
@ 2014-03-11 20:36 Jonathan Cameron
  2014-03-11 20:36 ` [PATCH 1/5] staging:iio:adc:spear adc - prefix defines to avoid namespace clashes Jonathan Cameron
                   ` (5 more replies)
  0 siblings, 6 replies; 11+ messages in thread
From: Jonathan Cameron @ 2014-03-11 20:36 UTC (permalink / raw)
  To: linux-iio; +Cc: sr, Jonathan Cameron

This driver has been reasonably clean since it was first merged within the
staging tree.  If it had been submitted after the IIO core was outside of
staging we might have taken it as is. I did a final review and the first 4
patches of this series rework various minor aspects of the driver.

Whilst it is a slow driver, the device tree matches at the lowest level seemed
a little unwise so the largest rework is concerned with centralising that
logic using a classic ops structure of function pointers.  The other large
change was to move to using the info_mask_shared_by_all approach to handle
sampling frequency.  This is something I am slowly propogating across the
whole tree, but might as well be done whilst we are looking at this driver.

I don't have hardware and whilst I think these are all changes that are
possible to easily verify by eye, a tested by would be most welcome!

Note this is the first driver I'm suggesting moving out of staging following
Greg's entirely reasonable question of 'What's wrong with the stuff that is
left?'  Any help with this sort of final cleanup and move would be most
welcome.

Jonathan

Jonathan Cameron (5):
  staging:iio:adc:spear adc - prefix defines to avoid namespace clashes.
  staging:iio:adc:spear adc rework so that device tree queries are all
    in probe
  staging:iio:adc:spear_adc drop initialization of unused scan_type
  staging:iio:adc:spear_adc use info_mask_shared_by_all for samp freq
  iio:adc:spear_adc move out of staging

 drivers/iio/adc/Kconfig             |   8 +
 drivers/iio/adc/Makefile            |   1 +
 drivers/iio/adc/spear_adc.c         | 429 +++++++++++++++++++++++++++++++++++
 drivers/staging/iio/adc/Kconfig     |   8 -
 drivers/staging/iio/adc/Makefile    |   1 -
 drivers/staging/iio/adc/spear_adc.c | 432 ------------------------------------
 6 files changed, 438 insertions(+), 441 deletions(-)
 create mode 100644 drivers/iio/adc/spear_adc.c
 delete mode 100644 drivers/staging/iio/adc/spear_adc.c

-- 
1.9.0


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

* [PATCH 1/5] staging:iio:adc:spear adc - prefix defines to avoid namespace clashes.
  2014-03-11 20:36 [PATCH 0/5] iio: Minor cleanups to spear ADC driver followed by staging graduation Jonathan Cameron
@ 2014-03-11 20:36 ` Jonathan Cameron
  2014-03-11 20:36 ` [PATCH 2/5] staging:iio:adc:spear adc rework so that device tree queries are all in probe Jonathan Cameron
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 11+ messages in thread
From: Jonathan Cameron @ 2014-03-11 20:36 UTC (permalink / raw)
  To: linux-iio; +Cc: sr, Jonathan Cameron

Signed-off-by: Jonathan Cameron <jic23@kernel.org>
---
 drivers/staging/iio/adc/spear_adc.c | 73 ++++++++++++++++++-------------------
 1 file changed, 36 insertions(+), 37 deletions(-)

diff --git a/drivers/staging/iio/adc/spear_adc.c b/drivers/staging/iio/adc/spear_adc.c
index 970d9ed..9234e05 100644
--- a/drivers/staging/iio/adc/spear_adc.c
+++ b/drivers/staging/iio/adc/spear_adc.c
@@ -22,39 +22,36 @@
 #include <linux/iio/iio.h>
 #include <linux/iio/sysfs.h>
 
-/*
- * SPEAR registers definitions
- */
-
-#define SCAN_RATE_LO(x)		((x) & 0xFFFF)
-#define SCAN_RATE_HI(x)		(((x) >> 0x10) & 0xFFFF)
-#define CLK_LOW(x)		(((x) & 0xf) << 0)
-#define CLK_HIGH(x)		(((x) & 0xf) << 4)
+/* SPEAR registers definitions */
+#define SPEAR600_ADC_SCAN_RATE_LO(x)	((x) & 0xFFFF)
+#define SPEAR600_ADC_SCAN_RATE_HI(x)	(((x) >> 0x10) & 0xFFFF)
+#define SPEAR_ADC_CLK_LOW(x)		(((x) & 0xf) << 0)
+#define SPEAR_ADC_CLK_HIGH(x)		(((x) & 0xf) << 4)
 
 /* Bit definitions for SPEAR_ADC_STATUS */
-#define START_CONVERSION	(1 << 0)
-#define CHANNEL_NUM(x)		((x) << 1)
-#define ADC_ENABLE		(1 << 4)
-#define AVG_SAMPLE(x)		((x) << 5)
-#define VREF_INTERNAL		(1 << 9)
+#define SPEAR_ADC_STATUS_START_CONVERSION	(1 << 0)
+#define SPEAR_ADC_STATUS_CHANNEL_NUM(x)		((x) << 1)
+#define SPEAR_ADC_STATUS_ADC_ENABLE		(1 << 4)
+#define SPEAR_ADC_STATUS_AVG_SAMPLE(x)		((x) << 5)
+#define SPEAR_ADC_STATUS_VREF_INTERNAL		(1 << 9)
 
-#define DATA_MASK		0x03ff
-#define DATA_BITS		10
+#define SPEAR_ADC_DATA_MASK		0x03ff
+#define SPEAR_ADC_DATA_BITS		10
 
-#define MOD_NAME "spear-adc"
+#define SPEAR_ADC_MOD_NAME "spear-adc"
 
-#define ADC_CHANNEL_NUM		8
+#define SPEAR_ADC_CHANNEL_NUM		8
 
-#define CLK_MIN			2500000
-#define CLK_MAX			20000000
+#define SPEAR_ADC_CLK_MIN			2500000
+#define SPEAR_ADC_CLK_MAX			20000000
 
 struct adc_regs_spear3xx {
 	u32 status;
 	u32 average;
 	u32 scan_rate;
 	u32 clk;	/* Not avail for 1340 & 1310 */
-	u32 ch_ctrl[ADC_CHANNEL_NUM];
-	u32 ch_data[ADC_CHANNEL_NUM];
+	u32 ch_ctrl[SPEAR_ADC_CHANNEL_NUM];
+	u32 ch_data[SPEAR_ADC_CHANNEL_NUM];
 };
 
 struct chan_data {
@@ -66,8 +63,8 @@ struct adc_regs_spear6xx {
 	u32 status;
 	u32 pad[2];
 	u32 clk;
-	u32 ch_ctrl[ADC_CHANNEL_NUM];
-	struct chan_data ch_data[ADC_CHANNEL_NUM];
+	u32 ch_ctrl[SPEAR_ADC_CHANNEL_NUM];
+	struct chan_data ch_data[SPEAR_ADC_CHANNEL_NUM];
 	u32 scan_rate_lo;
 	u32 scan_rate_hi;
 	struct chan_data average;
@@ -106,7 +103,7 @@ static void spear_adc_set_clk(struct spear_adc_info *info, u32 val)
 	clk_high = count - clk_low;
 	info->current_clk = apb_clk / count;
 
-	__raw_writel(CLK_LOW(clk_low) | CLK_HIGH(clk_high),
+	__raw_writel(SPEAR_ADC_CLK_LOW(clk_low) | SPEAR_ADC_CLK_HIGH(clk_high),
 		     &info->adc_base_spear6xx->clk);
 }
 
@@ -120,19 +117,19 @@ static u32 spear_adc_get_average(struct spear_adc_info *info)
 {
 	if (of_device_is_compatible(info->np, "st,spear600-adc")) {
 		return __raw_readl(&info->adc_base_spear6xx->average.msb) &
-			DATA_MASK;
+			SPEAR_ADC_DATA_MASK;
 	} else {
 		return __raw_readl(&info->adc_base_spear3xx->average) &
-			DATA_MASK;
+			SPEAR_ADC_DATA_MASK;
 	}
 }
 
 static void spear_adc_set_scanrate(struct spear_adc_info *info, u32 rate)
 {
 	if (of_device_is_compatible(info->np, "st,spear600-adc")) {
-		__raw_writel(SCAN_RATE_LO(rate),
+		__raw_writel(SPEAR600_ADC_SCAN_RATE_LO(rate),
 			     &info->adc_base_spear6xx->scan_rate_lo);
-		__raw_writel(SCAN_RATE_HI(rate),
+		__raw_writel(SPEAR600_ADC_SCAN_RATE_HI(rate),
 			     &info->adc_base_spear6xx->scan_rate_hi);
 	} else {
 		__raw_writel(rate, &info->adc_base_spear3xx->scan_rate);
@@ -152,11 +149,12 @@ static int spear_read_raw(struct iio_dev *indio_dev,
 	case IIO_CHAN_INFO_RAW:
 		mutex_lock(&indio_dev->mlock);
 
-		status = CHANNEL_NUM(chan->channel) |
-			AVG_SAMPLE(info->avg_samples) |
-			START_CONVERSION | ADC_ENABLE;
+		status = SPEAR_ADC_STATUS_CHANNEL_NUM(chan->channel) |
+			SPEAR_ADC_STATUS_AVG_SAMPLE(info->avg_samples) |
+			SPEAR_ADC_STATUS_START_CONVERSION |
+			SPEAR_ADC_STATUS_ADC_ENABLE;
 		if (info->vref_external == 0)
-			status |= VREF_INTERNAL;
+			status |= SPEAR_ADC_STATUS_VREF_INTERNAL;
 
 		spear_adc_set_status(info, status);
 		wait_for_completion(&info->completion); /* set by ISR */
@@ -168,7 +166,7 @@ static int spear_read_raw(struct iio_dev *indio_dev,
 
 	case IIO_CHAN_INFO_SCALE:
 		*val = info->vref_external;
-		*val2 = DATA_BITS;
+		*val2 = SPEAR_ADC_DATA_BITS;
 		return IIO_VAL_FRACTIONAL_LOG2;
 	}
 
@@ -253,7 +251,7 @@ static ssize_t spear_adc_write_frequency(struct device *dev,
 
 	mutex_lock(&indio_dev->mlock);
 
-	if ((lval < CLK_MIN) || (lval > CLK_MAX)) {
+	if ((lval < SPEAR_ADC_CLK_MIN) || (lval > SPEAR_ADC_CLK_MAX)) {
 		ret = -EINVAL;
 		goto out;
 	}
@@ -339,7 +337,8 @@ static int spear_adc_probe(struct platform_device *pdev)
 		goto errout3;
 	}
 
-	ret = devm_request_irq(dev, irq, spear_adc_isr, 0, MOD_NAME, info);
+	ret = devm_request_irq(dev, irq, spear_adc_isr, 0, SPEAR_ADC_MOD_NAME,
+			info);
 	if (ret < 0) {
 		dev_err(dev, "failed requesting interrupt\n");
 		goto errout3;
@@ -370,7 +369,7 @@ static int spear_adc_probe(struct platform_device *pdev)
 
 	init_completion(&info->completion);
 
-	iodev->name = MOD_NAME;
+	iodev->name = SPEAR_ADC_MOD_NAME;
 	iodev->dev.parent = dev;
 	iodev->info = &spear_adc_iio_info;
 	iodev->modes = INDIO_DIRECT_MODE;
@@ -419,7 +418,7 @@ static struct platform_driver spear_adc_driver = {
 	.probe		= spear_adc_probe,
 	.remove		= spear_adc_remove,
 	.driver		= {
-		.name	= MOD_NAME,
+		.name	= SPEAR_ADC_MOD_NAME,
 		.owner	= THIS_MODULE,
 		.of_match_table = of_match_ptr(spear_adc_dt_ids),
 	},
-- 
1.9.0

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

* [PATCH 2/5] staging:iio:adc:spear adc rework so that device tree queries are all in probe
  2014-03-11 20:36 [PATCH 0/5] iio: Minor cleanups to spear ADC driver followed by staging graduation Jonathan Cameron
  2014-03-11 20:36 ` [PATCH 1/5] staging:iio:adc:spear adc - prefix defines to avoid namespace clashes Jonathan Cameron
@ 2014-03-11 20:36 ` Jonathan Cameron
  2014-03-11 20:36 ` [PATCH 3/5] staging:iio:adc:spear_adc drop initialization of unused scan_type Jonathan Cameron
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 11+ messages in thread
From: Jonathan Cameron @ 2014-03-11 20:36 UTC (permalink / raw)
  To: linux-iio; +Cc: sr, Jonathan Cameron

Previously the driver would query what type it was in very low level
functions.  This is unintuitive and probably rather inefficient.

Also combine the two structure pointers using an anonymous union given
only one should be set for a given device.

Clearly the of_device_is_compatible related logic in probe could assign only
one of the two pointers, but I feel it is clearer as done here.

Signed-off-by: Jonathan Cameron <jic23@kernel.org>
---
 drivers/staging/iio/adc/spear_adc.c | 89 ++++++++++++++++++++++++-------------
 1 file changed, 57 insertions(+), 32 deletions(-)

diff --git a/drivers/staging/iio/adc/spear_adc.c b/drivers/staging/iio/adc/spear_adc.c
index 9234e05..886d9db 100644
--- a/drivers/staging/iio/adc/spear_adc.c
+++ b/drivers/staging/iio/adc/spear_adc.c
@@ -70,10 +70,20 @@ struct adc_regs_spear6xx {
 	struct chan_data average;
 };
 
+struct spear_adc_info;
+
+struct spear_adc_ops {
+	u32 (*get_average)(struct spear_adc_info *info);
+	void (*set_scanrate)(struct spear_adc_info *info, u32 rate);
+};
+
 struct spear_adc_info {
 	struct device_node *np;
-	struct adc_regs_spear3xx __iomem *adc_base_spear3xx;
-	struct adc_regs_spear6xx __iomem *adc_base_spear6xx;
+	union {
+		struct adc_regs_spear3xx __iomem *adc_base_spear3xx;
+		struct adc_regs_spear6xx __iomem *adc_base_spear6xx;
+	};
+	const struct spear_adc_ops *ops;
 	struct clk *clk;
 	struct completion completion;
 	u32 current_clk;
@@ -83,11 +93,6 @@ struct spear_adc_info {
 	u32 value;
 };
 
-/*
- * Functions to access some SPEAr ADC register. Abstracted into
- * static inline functions, because of different register offsets
- * on different SoC variants (SPEAr300 vs SPEAr600 etc).
- */
 static void spear_adc_set_status(struct spear_adc_info *info, u32 val)
 {
 	__raw_writel(val, &info->adc_base_spear6xx->status);
@@ -113,29 +118,41 @@ static void spear_adc_set_ctrl(struct spear_adc_info *info, int n,
 	__raw_writel(val, &info->adc_base_spear6xx->ch_ctrl[n]);
 }
 
-static u32 spear_adc_get_average(struct spear_adc_info *info)
+static u32 spear600_adc_get_average(struct spear_adc_info *info)
 {
-	if (of_device_is_compatible(info->np, "st,spear600-adc")) {
-		return __raw_readl(&info->adc_base_spear6xx->average.msb) &
-			SPEAR_ADC_DATA_MASK;
-	} else {
-		return __raw_readl(&info->adc_base_spear3xx->average) &
-			SPEAR_ADC_DATA_MASK;
-	}
+	return __raw_readl(&info->adc_base_spear6xx->average.msb) &
+		SPEAR_ADC_DATA_MASK;
 }
 
-static void spear_adc_set_scanrate(struct spear_adc_info *info, u32 rate)
+static u32 spear300_adc_get_average(struct spear_adc_info *info)
 {
-	if (of_device_is_compatible(info->np, "st,spear600-adc")) {
-		__raw_writel(SPEAR600_ADC_SCAN_RATE_LO(rate),
-			     &info->adc_base_spear6xx->scan_rate_lo);
-		__raw_writel(SPEAR600_ADC_SCAN_RATE_HI(rate),
-			     &info->adc_base_spear6xx->scan_rate_hi);
-	} else {
-		__raw_writel(rate, &info->adc_base_spear3xx->scan_rate);
-	}
+	return __raw_readl(&info->adc_base_spear3xx->average) &
+		SPEAR_ADC_DATA_MASK;
+}
+
+static void spear600_adc_set_scanrate(struct spear_adc_info *info, u32 rate)
+{
+	__raw_writel(SPEAR600_ADC_SCAN_RATE_LO(rate),
+		&info->adc_base_spear6xx->scan_rate_lo);
+	__raw_writel(SPEAR600_ADC_SCAN_RATE_HI(rate),
+		&info->adc_base_spear6xx->scan_rate_hi);
+}
+
+static void spear300_adc_set_scanrate(struct spear_adc_info *info, u32 rate)
+{
+	__raw_writel(rate, &info->adc_base_spear3xx->scan_rate);
 }
 
+static const struct spear_adc_ops spear600_adc_ops = {
+	.get_average = &spear600_adc_get_average,
+	.set_scanrate = &spear600_adc_set_scanrate,
+};
+
+static const struct spear_adc_ops spear300_adc_ops = {
+	.get_average = &spear300_adc_get_average,
+	.set_scanrate = &spear300_adc_set_scanrate,
+};
+
 static int spear_read_raw(struct iio_dev *indio_dev,
 			  struct iio_chan_spec const *chan,
 			  int *val,
@@ -201,7 +218,7 @@ static irqreturn_t spear_adc_isr(int irq, void *dev_id)
 	struct spear_adc_info *info = (struct spear_adc_info *)dev_id;
 
 	/* Read value to clear IRQ */
-	info->value = spear_adc_get_average(info);
+	info->value = info->ops->get_average(info);
 	complete(&info->completion);
 
 	return IRQ_HANDLED;
@@ -216,7 +233,7 @@ static int spear_adc_configure(struct spear_adc_info *info)
 	__raw_writel(0, &info->adc_base_spear6xx->clk);
 	for (i = 0; i < 8; i++)
 		spear_adc_set_ctrl(info, i, 0);
-	spear_adc_set_scanrate(info, 0);
+	info->ops->set_scanrate(info, 0);
 
 	spear_adc_set_clk(info, info->sampling_freq);
 
@@ -310,13 +327,21 @@ static int spear_adc_probe(struct platform_device *pdev)
 	 * (e.g. SPEAr3xx). Let's provide two register base addresses
 	 * to support multi-arch kernels.
 	 */
-	info->adc_base_spear6xx = of_iomap(np, 0);
-	if (!info->adc_base_spear6xx) {
-		dev_err(dev, "failed mapping memory\n");
-		return -ENOMEM;
+	if (of_device_is_compatible(info->np, "st,spear600-adc")) {
+		info->adc_base_spear6xx = of_iomap(np, 0);
+		if (!info->adc_base_spear6xx) {
+			dev_err(dev, "failed mapping memory\n");
+			return -ENOMEM;
+		}
+		info->ops = &spear600_adc_ops;
+	} else {
+		info->adc_base_spear3xx = of_iomap(np, 0);
+		if (!info->adc_base_spear3xx) {
+			dev_err(dev, "failed mapping memory\n");
+			return -ENOMEM;
+		}
+		info->ops = &spear300_adc_ops;
 	}
-	info->adc_base_spear3xx =
-		(struct adc_regs_spear3xx __iomem *)info->adc_base_spear6xx;
 
 	info->clk = clk_get(dev, NULL);
 	if (IS_ERR(info->clk)) {
-- 
1.9.0

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

* [PATCH 3/5] staging:iio:adc:spear_adc drop initialization of unused scan_type
  2014-03-11 20:36 [PATCH 0/5] iio: Minor cleanups to spear ADC driver followed by staging graduation Jonathan Cameron
  2014-03-11 20:36 ` [PATCH 1/5] staging:iio:adc:spear adc - prefix defines to avoid namespace clashes Jonathan Cameron
  2014-03-11 20:36 ` [PATCH 2/5] staging:iio:adc:spear adc rework so that device tree queries are all in probe Jonathan Cameron
@ 2014-03-11 20:36 ` Jonathan Cameron
  2014-03-11 20:36 ` [PATCH 4/5] staging:iio:adc:spear_adc use info_mask_shared_by_all for samp freq Jonathan Cameron
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 11+ messages in thread
From: Jonathan Cameron @ 2014-03-11 20:36 UTC (permalink / raw)
  To: linux-iio; +Cc: sr, Jonathan Cameron

As the driver does not support the buffered interfaces of IIO this is
not used.

Signed-off-by: Jonathan Cameron <jic23@kernel.org>
---
 drivers/staging/iio/adc/spear_adc.c | 4 ----
 1 file changed, 4 deletions(-)

diff --git a/drivers/staging/iio/adc/spear_adc.c b/drivers/staging/iio/adc/spear_adc.c
index 886d9db..fbe69a7 100644
--- a/drivers/staging/iio/adc/spear_adc.c
+++ b/drivers/staging/iio/adc/spear_adc.c
@@ -196,10 +196,6 @@ static int spear_read_raw(struct iio_dev *indio_dev,
 	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),	\
 	.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),	\
 	.channel = idx,					\
-	.scan_type = {					\
-		.sign = 'u',				\
-		.storagebits = 16,			\
-	},						\
 }
 
 static const struct iio_chan_spec spear_adc_iio_channels[] = {
-- 
1.9.0

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

* [PATCH 4/5] staging:iio:adc:spear_adc use info_mask_shared_by_all for samp freq
  2014-03-11 20:36 [PATCH 0/5] iio: Minor cleanups to spear ADC driver followed by staging graduation Jonathan Cameron
                   ` (2 preceding siblings ...)
  2014-03-11 20:36 ` [PATCH 3/5] staging:iio:adc:spear_adc drop initialization of unused scan_type Jonathan Cameron
@ 2014-03-11 20:36 ` Jonathan Cameron
  2014-03-12 20:31   ` Hartmut Knaack
  2014-03-11 20:36 ` [PATCH 5/5] iio:adc:spear_adc move out of staging Jonathan Cameron
  2014-03-12  6:50 ` [PATCH 0/5] iio: Minor cleanups to spear ADC driver followed by staging graduation Stefan Roese
  5 siblings, 1 reply; 11+ messages in thread
From: Jonathan Cameron @ 2014-03-11 20:36 UTC (permalink / raw)
  To: linux-iio; +Cc: sr, Jonathan Cameron

Using the core support makes this element available to in kernel users as
well as to userspace under exactly the same interface as before.  The
intent is to move all sampling frequency control to this approach
throughout IIO.

Signed-off-by: Jonathan Cameron <jic23@kernel.org>
---
 drivers/staging/iio/adc/spear_adc.c | 95 ++++++++++++++-----------------------
 1 file changed, 36 insertions(+), 59 deletions(-)

diff --git a/drivers/staging/iio/adc/spear_adc.c b/drivers/staging/iio/adc/spear_adc.c
index fbe69a7..d8232f1 100644
--- a/drivers/staging/iio/adc/spear_adc.c
+++ b/drivers/staging/iio/adc/spear_adc.c
@@ -185,16 +185,51 @@ static int spear_read_raw(struct iio_dev *indio_dev,
 		*val = info->vref_external;
 		*val2 = SPEAR_ADC_DATA_BITS;
 		return IIO_VAL_FRACTIONAL_LOG2;
+	case IIO_CHAN_INFO_SAMP_FREQ:
+		*val = info->current_clk;
+		return IIO_VAL_INT;
 	}
 
 	return -EINVAL;
 }
 
+static int spear_adc_write_raw(struct iio_dev *indio_dev,
+			       struct iio_chan_spec const *chan,
+			       int val,
+			       int val2,
+			       long mask)
+{
+	struct spear_adc_info *info = iio_priv(indio_dev);
+	u32 clk_high, clk_low, count;
+	u32 apb_clk = clk_get_rate(info->clk);
+	int ret = 0;
+
+	mutex_lock(&indio_dev->mlock);
+
+	if ((val < SPEAR_ADC_CLK_MIN) ||
+		(val > SPEAR_ADC_CLK_MAX) ||
+		(val2 != 0)) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	count = (apb_clk + val - 1) / val;
+	clk_low = count / 2;
+	clk_high = count - clk_low;
+	info->current_clk = apb_clk / count;
+	spear_adc_set_clk(info, val);
+
+out:
+	mutex_unlock(&indio_dev->mlock);
+	return ret;
+}
+
 #define SPEAR_ADC_CHAN(idx) {				\
 	.type = IIO_VOLTAGE,				\
 	.indexed = 1,					\
 	.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),\
 	.channel = idx,					\
 }
 
@@ -236,67 +271,9 @@ static int spear_adc_configure(struct spear_adc_info *info)
 	return 0;
 }
 
-static ssize_t spear_adc_read_frequency(struct device *dev,
-					struct device_attribute *attr,
-					char *buf)
-{
-	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
-	struct spear_adc_info *info = iio_priv(indio_dev);
-
-	return sprintf(buf, "%d\n", info->current_clk);
-}
-
-static ssize_t spear_adc_write_frequency(struct device *dev,
-					 struct device_attribute *attr,
-					 const char *buf,
-					 size_t len)
-{
-	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
-	struct spear_adc_info *info = iio_priv(indio_dev);
-	u32 clk_high, clk_low, count;
-	u32 apb_clk = clk_get_rate(info->clk);
-	unsigned long lval;
-	int ret;
-
-	ret = kstrtoul(buf, 10, &lval);
-	if (ret)
-		return ret;
-
-	mutex_lock(&indio_dev->mlock);
-
-	if ((lval < SPEAR_ADC_CLK_MIN) || (lval > SPEAR_ADC_CLK_MAX)) {
-		ret = -EINVAL;
-		goto out;
-	}
-
-	count = (apb_clk + lval - 1) / lval;
-	clk_low = count / 2;
-	clk_high = count - clk_low;
-	info->current_clk = apb_clk / count;
-	spear_adc_set_clk(info, lval);
-
-out:
-	mutex_unlock(&indio_dev->mlock);
-
-	return ret ? ret : len;
-}
-
-static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO,
-			      spear_adc_read_frequency,
-			      spear_adc_write_frequency);
-
-static struct attribute *spear_attributes[] = {
-	&iio_dev_attr_sampling_frequency.dev_attr.attr,
-	NULL
-};
-
-static const struct attribute_group spear_attribute_group = {
-	.attrs = spear_attributes,
-};
-
 static const struct iio_info spear_adc_iio_info = {
 	.read_raw = &spear_read_raw,
-	.attrs = &spear_attribute_group,
+	.write_raw = &spear_adc_write_raw,
 	.driver_module = THIS_MODULE,
 };
 
-- 
1.9.0

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

* [PATCH 5/5] iio:adc:spear_adc move out of staging
  2014-03-11 20:36 [PATCH 0/5] iio: Minor cleanups to spear ADC driver followed by staging graduation Jonathan Cameron
                   ` (3 preceding siblings ...)
  2014-03-11 20:36 ` [PATCH 4/5] staging:iio:adc:spear_adc use info_mask_shared_by_all for samp freq Jonathan Cameron
@ 2014-03-11 20:36 ` Jonathan Cameron
  2014-03-12 20:46   ` Hartmut Knaack
  2014-03-12  6:50 ` [PATCH 0/5] iio: Minor cleanups to spear ADC driver followed by staging graduation Stefan Roese
  5 siblings, 1 reply; 11+ messages in thread
From: Jonathan Cameron @ 2014-03-11 20:36 UTC (permalink / raw)
  To: linux-iio; +Cc: sr, Jonathan Cameron

This simple driver is ready to move out of staging.

Signed-off-by: Jonathan Cameron <jic23@kernel.org>
---
 drivers/iio/adc/Kconfig             |   8 +
 drivers/iio/adc/Makefile            |   1 +
 drivers/iio/adc/spear_adc.c         | 429 ++++++++++++++++++++++++++++++++++++
 drivers/staging/iio/adc/Kconfig     |   8 -
 drivers/staging/iio/adc/Makefile    |   1 -
 drivers/staging/iio/adc/spear_adc.c | 429 ------------------------------------
 6 files changed, 438 insertions(+), 438 deletions(-)

diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
index 5553206..2e3e1b0 100644
--- a/drivers/iio/adc/Kconfig
+++ b/drivers/iio/adc/Kconfig
@@ -164,6 +164,14 @@ config NAU7802
 	  To compile this driver as a module, choose M here: the
 	  module will be called nau7802.
 
+config SPEAR_ADC
+	tristate "ST SPEAr ADC"
+	depends on PLAT_SPEAR || COMPILE_TEST
+	depends on HAS_IOMEM
+	help
+	  Say yes here to build support for the integrated ADC inside the
+	  ST SPEAr SoC. Provides direct access via sysfs.
+
 config TI_ADC081C
 	tristate "Texas Instruments ADC081C021/027"
 	depends on I2C
diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile
index 89f1216..8378fb2 100644
--- a/drivers/iio/adc/Makefile
+++ b/drivers/iio/adc/Makefile
@@ -18,6 +18,7 @@ obj-$(CONFIG_MAX1363) += max1363.o
 obj-$(CONFIG_MCP320X) += mcp320x.o
 obj-$(CONFIG_MCP3422) += mcp3422.o
 obj-$(CONFIG_NAU7802) += nau7802.o
+obj-$(CONFIG_SPEAR_ADC) += spear_adc.o
 obj-$(CONFIG_TI_ADC081C) += ti-adc081c.o
 obj-$(CONFIG_TI_AM335X_ADC) += ti_am335x_adc.o
 obj-$(CONFIG_TWL6030_GPADC) += twl6030-gpadc.o
diff --git a/drivers/iio/adc/spear_adc.c b/drivers/iio/adc/spear_adc.c
new file mode 100644
index 0000000..d8232f1
--- /dev/null
+++ b/drivers/iio/adc/spear_adc.c
@@ -0,0 +1,429 @@
+/*
+ * ST SPEAr ADC driver
+ *
+ * Copyright 2012 Stefan Roese <sr@denx.de>
+ *
+ * Licensed under the GPL-2.
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/device.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/io.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/completion.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+
+/* SPEAR registers definitions */
+#define SPEAR600_ADC_SCAN_RATE_LO(x)	((x) & 0xFFFF)
+#define SPEAR600_ADC_SCAN_RATE_HI(x)	(((x) >> 0x10) & 0xFFFF)
+#define SPEAR_ADC_CLK_LOW(x)		(((x) & 0xf) << 0)
+#define SPEAR_ADC_CLK_HIGH(x)		(((x) & 0xf) << 4)
+
+/* Bit definitions for SPEAR_ADC_STATUS */
+#define SPEAR_ADC_STATUS_START_CONVERSION	(1 << 0)
+#define SPEAR_ADC_STATUS_CHANNEL_NUM(x)		((x) << 1)
+#define SPEAR_ADC_STATUS_ADC_ENABLE		(1 << 4)
+#define SPEAR_ADC_STATUS_AVG_SAMPLE(x)		((x) << 5)
+#define SPEAR_ADC_STATUS_VREF_INTERNAL		(1 << 9)
+
+#define SPEAR_ADC_DATA_MASK		0x03ff
+#define SPEAR_ADC_DATA_BITS		10
+
+#define SPEAR_ADC_MOD_NAME "spear-adc"
+
+#define SPEAR_ADC_CHANNEL_NUM		8
+
+#define SPEAR_ADC_CLK_MIN			2500000
+#define SPEAR_ADC_CLK_MAX			20000000
+
+struct adc_regs_spear3xx {
+	u32 status;
+	u32 average;
+	u32 scan_rate;
+	u32 clk;	/* Not avail for 1340 & 1310 */
+	u32 ch_ctrl[SPEAR_ADC_CHANNEL_NUM];
+	u32 ch_data[SPEAR_ADC_CHANNEL_NUM];
+};
+
+struct chan_data {
+	u32 lsb;
+	u32 msb;
+};
+
+struct adc_regs_spear6xx {
+	u32 status;
+	u32 pad[2];
+	u32 clk;
+	u32 ch_ctrl[SPEAR_ADC_CHANNEL_NUM];
+	struct chan_data ch_data[SPEAR_ADC_CHANNEL_NUM];
+	u32 scan_rate_lo;
+	u32 scan_rate_hi;
+	struct chan_data average;
+};
+
+struct spear_adc_info;
+
+struct spear_adc_ops {
+	u32 (*get_average)(struct spear_adc_info *info);
+	void (*set_scanrate)(struct spear_adc_info *info, u32 rate);
+};
+
+struct spear_adc_info {
+	struct device_node *np;
+	union {
+		struct adc_regs_spear3xx __iomem *adc_base_spear3xx;
+		struct adc_regs_spear6xx __iomem *adc_base_spear6xx;
+	};
+	const struct spear_adc_ops *ops;
+	struct clk *clk;
+	struct completion completion;
+	u32 current_clk;
+	u32 sampling_freq;
+	u32 avg_samples;
+	u32 vref_external;
+	u32 value;
+};
+
+static void spear_adc_set_status(struct spear_adc_info *info, u32 val)
+{
+	__raw_writel(val, &info->adc_base_spear6xx->status);
+}
+
+static void spear_adc_set_clk(struct spear_adc_info *info, u32 val)
+{
+	u32 clk_high, clk_low, count;
+	u32 apb_clk = clk_get_rate(info->clk);
+
+	count = (apb_clk + val - 1) / val;
+	clk_low = count / 2;
+	clk_high = count - clk_low;
+	info->current_clk = apb_clk / count;
+
+	__raw_writel(SPEAR_ADC_CLK_LOW(clk_low) | SPEAR_ADC_CLK_HIGH(clk_high),
+		     &info->adc_base_spear6xx->clk);
+}
+
+static void spear_adc_set_ctrl(struct spear_adc_info *info, int n,
+			       u32 val)
+{
+	__raw_writel(val, &info->adc_base_spear6xx->ch_ctrl[n]);
+}
+
+static u32 spear600_adc_get_average(struct spear_adc_info *info)
+{
+	return __raw_readl(&info->adc_base_spear6xx->average.msb) &
+		SPEAR_ADC_DATA_MASK;
+}
+
+static u32 spear300_adc_get_average(struct spear_adc_info *info)
+{
+	return __raw_readl(&info->adc_base_spear3xx->average) &
+		SPEAR_ADC_DATA_MASK;
+}
+
+static void spear600_adc_set_scanrate(struct spear_adc_info *info, u32 rate)
+{
+	__raw_writel(SPEAR600_ADC_SCAN_RATE_LO(rate),
+		&info->adc_base_spear6xx->scan_rate_lo);
+	__raw_writel(SPEAR600_ADC_SCAN_RATE_HI(rate),
+		&info->adc_base_spear6xx->scan_rate_hi);
+}
+
+static void spear300_adc_set_scanrate(struct spear_adc_info *info, u32 rate)
+{
+	__raw_writel(rate, &info->adc_base_spear3xx->scan_rate);
+}
+
+static const struct spear_adc_ops spear600_adc_ops = {
+	.get_average = &spear600_adc_get_average,
+	.set_scanrate = &spear600_adc_set_scanrate,
+};
+
+static const struct spear_adc_ops spear300_adc_ops = {
+	.get_average = &spear300_adc_get_average,
+	.set_scanrate = &spear300_adc_set_scanrate,
+};
+
+static int spear_read_raw(struct iio_dev *indio_dev,
+			  struct iio_chan_spec const *chan,
+			  int *val,
+			  int *val2,
+			  long mask)
+{
+	struct spear_adc_info *info = iio_priv(indio_dev);
+	u32 status;
+
+	switch (mask) {
+	case IIO_CHAN_INFO_RAW:
+		mutex_lock(&indio_dev->mlock);
+
+		status = SPEAR_ADC_STATUS_CHANNEL_NUM(chan->channel) |
+			SPEAR_ADC_STATUS_AVG_SAMPLE(info->avg_samples) |
+			SPEAR_ADC_STATUS_START_CONVERSION |
+			SPEAR_ADC_STATUS_ADC_ENABLE;
+		if (info->vref_external == 0)
+			status |= SPEAR_ADC_STATUS_VREF_INTERNAL;
+
+		spear_adc_set_status(info, status);
+		wait_for_completion(&info->completion); /* set by ISR */
+		*val = info->value;
+
+		mutex_unlock(&indio_dev->mlock);
+
+		return IIO_VAL_INT;
+
+	case IIO_CHAN_INFO_SCALE:
+		*val = info->vref_external;
+		*val2 = SPEAR_ADC_DATA_BITS;
+		return IIO_VAL_FRACTIONAL_LOG2;
+	case IIO_CHAN_INFO_SAMP_FREQ:
+		*val = info->current_clk;
+		return IIO_VAL_INT;
+	}
+
+	return -EINVAL;
+}
+
+static int spear_adc_write_raw(struct iio_dev *indio_dev,
+			       struct iio_chan_spec const *chan,
+			       int val,
+			       int val2,
+			       long mask)
+{
+	struct spear_adc_info *info = iio_priv(indio_dev);
+	u32 clk_high, clk_low, count;
+	u32 apb_clk = clk_get_rate(info->clk);
+	int ret = 0;
+
+	mutex_lock(&indio_dev->mlock);
+
+	if ((val < SPEAR_ADC_CLK_MIN) ||
+		(val > SPEAR_ADC_CLK_MAX) ||
+		(val2 != 0)) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	count = (apb_clk + val - 1) / val;
+	clk_low = count / 2;
+	clk_high = count - clk_low;
+	info->current_clk = apb_clk / count;
+	spear_adc_set_clk(info, val);
+
+out:
+	mutex_unlock(&indio_dev->mlock);
+	return ret;
+}
+
+#define SPEAR_ADC_CHAN(idx) {				\
+	.type = IIO_VOLTAGE,				\
+	.indexed = 1,					\
+	.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),\
+	.channel = idx,					\
+}
+
+static const struct iio_chan_spec spear_adc_iio_channels[] = {
+	SPEAR_ADC_CHAN(0),
+	SPEAR_ADC_CHAN(1),
+	SPEAR_ADC_CHAN(2),
+	SPEAR_ADC_CHAN(3),
+	SPEAR_ADC_CHAN(4),
+	SPEAR_ADC_CHAN(5),
+	SPEAR_ADC_CHAN(6),
+	SPEAR_ADC_CHAN(7),
+};
+
+static irqreturn_t spear_adc_isr(int irq, void *dev_id)
+{
+	struct spear_adc_info *info = (struct spear_adc_info *)dev_id;
+
+	/* Read value to clear IRQ */
+	info->value = info->ops->get_average(info);
+	complete(&info->completion);
+
+	return IRQ_HANDLED;
+}
+
+static int spear_adc_configure(struct spear_adc_info *info)
+{
+	int i;
+
+	/* Reset ADC core */
+	spear_adc_set_status(info, 0);
+	__raw_writel(0, &info->adc_base_spear6xx->clk);
+	for (i = 0; i < 8; i++)
+		spear_adc_set_ctrl(info, i, 0);
+	info->ops->set_scanrate(info, 0);
+
+	spear_adc_set_clk(info, info->sampling_freq);
+
+	return 0;
+}
+
+static const struct iio_info spear_adc_iio_info = {
+	.read_raw = &spear_read_raw,
+	.write_raw = &spear_adc_write_raw,
+	.driver_module = THIS_MODULE,
+};
+
+static int spear_adc_probe(struct platform_device *pdev)
+{
+	struct device_node *np = pdev->dev.of_node;
+	struct device *dev = &pdev->dev;
+	struct spear_adc_info *info;
+	struct iio_dev *iodev = NULL;
+	int ret = -ENODEV;
+	int irq;
+
+	iodev = devm_iio_device_alloc(dev, sizeof(struct spear_adc_info));
+	if (!iodev) {
+		dev_err(dev, "failed allocating iio device\n");
+		return -ENOMEM;
+	}
+
+	info = iio_priv(iodev);
+	info->np = np;
+
+	/*
+	 * SPEAr600 has a different register layout than other SPEAr SoC's
+	 * (e.g. SPEAr3xx). Let's provide two register base addresses
+	 * to support multi-arch kernels.
+	 */
+	if (of_device_is_compatible(info->np, "st,spear600-adc")) {
+		info->adc_base_spear6xx = of_iomap(np, 0);
+		if (!info->adc_base_spear6xx) {
+			dev_err(dev, "failed mapping memory\n");
+			return -ENOMEM;
+		}
+		info->ops = &spear600_adc_ops;
+	} else {
+		info->adc_base_spear3xx = of_iomap(np, 0);
+		if (!info->adc_base_spear3xx) {
+			dev_err(dev, "failed mapping memory\n");
+			return -ENOMEM;
+		}
+		info->ops = &spear300_adc_ops;
+	}
+
+	info->clk = clk_get(dev, NULL);
+	if (IS_ERR(info->clk)) {
+		dev_err(dev, "failed getting clock\n");
+		goto errout1;
+	}
+
+	ret = clk_prepare_enable(info->clk);
+	if (ret) {
+		dev_err(dev, "failed enabling clock\n");
+		goto errout2;
+	}
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq <= 0) {
+		dev_err(dev, "failed getting interrupt resource\n");
+		ret = -EINVAL;
+		goto errout3;
+	}
+
+	ret = devm_request_irq(dev, irq, spear_adc_isr, 0, SPEAR_ADC_MOD_NAME,
+			info);
+	if (ret < 0) {
+		dev_err(dev, "failed requesting interrupt\n");
+		goto errout3;
+	}
+
+	if (of_property_read_u32(np, "sampling-frequency",
+				 &info->sampling_freq)) {
+		dev_err(dev, "sampling-frequency missing in DT\n");
+		ret = -EINVAL;
+		goto errout3;
+	}
+
+	/*
+	 * Optional avg_samples defaults to 0, resulting in single data
+	 * conversion
+	 */
+	of_property_read_u32(np, "average-samples", &info->avg_samples);
+
+	/*
+	 * Optional vref_external defaults to 0, resulting in internal vref
+	 * selection
+	 */
+	of_property_read_u32(np, "vref-external", &info->vref_external);
+
+	spear_adc_configure(info);
+
+	platform_set_drvdata(pdev, iodev);
+
+	init_completion(&info->completion);
+
+	iodev->name = SPEAR_ADC_MOD_NAME;
+	iodev->dev.parent = dev;
+	iodev->info = &spear_adc_iio_info;
+	iodev->modes = INDIO_DIRECT_MODE;
+	iodev->channels = spear_adc_iio_channels;
+	iodev->num_channels = ARRAY_SIZE(spear_adc_iio_channels);
+
+	ret = iio_device_register(iodev);
+	if (ret)
+		goto errout3;
+
+	dev_info(dev, "SPEAR ADC driver loaded, IRQ %d\n", irq);
+
+	return 0;
+
+errout3:
+	clk_disable_unprepare(info->clk);
+errout2:
+	clk_put(info->clk);
+errout1:
+	iounmap(info->adc_base_spear6xx);
+	return ret;
+}
+
+static int spear_adc_remove(struct platform_device *pdev)
+{
+	struct iio_dev *iodev = platform_get_drvdata(pdev);
+	struct spear_adc_info *info = iio_priv(iodev);
+
+	iio_device_unregister(iodev);
+	clk_disable_unprepare(info->clk);
+	clk_put(info->clk);
+	iounmap(info->adc_base_spear6xx);
+
+	return 0;
+}
+
+#ifdef CONFIG_OF
+static const struct of_device_id spear_adc_dt_ids[] = {
+	{ .compatible = "st,spear600-adc", },
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, spear_adc_dt_ids);
+#endif
+
+static struct platform_driver spear_adc_driver = {
+	.probe		= spear_adc_probe,
+	.remove		= spear_adc_remove,
+	.driver		= {
+		.name	= SPEAR_ADC_MOD_NAME,
+		.owner	= THIS_MODULE,
+		.of_match_table = of_match_ptr(spear_adc_dt_ids),
+	},
+};
+
+module_platform_driver(spear_adc_driver);
+
+MODULE_AUTHOR("Stefan Roese <sr@denx.de>");
+MODULE_DESCRIPTION("SPEAr ADC driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/staging/iio/adc/Kconfig b/drivers/staging/iio/adc/Kconfig
index 3633298..a37d001 100644
--- a/drivers/staging/iio/adc/Kconfig
+++ b/drivers/staging/iio/adc/Kconfig
@@ -126,12 +126,4 @@ config MXS_LRADC
 	  To compile this driver as a module, choose M here: the
 	  module will be called mxs-lradc.
 
-config SPEAR_ADC
-	tristate "ST SPEAr ADC"
-	depends on PLAT_SPEAR || COMPILE_TEST
-	depends on HAS_IOMEM
-	help
-	  Say yes here to build support for the integrated ADC inside the
-	  ST SPEAr SoC. Provides direct access via sysfs.
-
 endmenu
diff --git a/drivers/staging/iio/adc/Makefile b/drivers/staging/iio/adc/Makefile
index 3e9fb14..b5915c1 100644
--- a/drivers/staging/iio/adc/Makefile
+++ b/drivers/staging/iio/adc/Makefile
@@ -19,4 +19,3 @@ obj-$(CONFIG_AD7192) += ad7192.o
 obj-$(CONFIG_AD7280) += ad7280a.o
 obj-$(CONFIG_LPC32XX_ADC) += lpc32xx_adc.o
 obj-$(CONFIG_MXS_LRADC) += mxs-lradc.o
-obj-$(CONFIG_SPEAR_ADC) += spear_adc.o
diff --git a/drivers/staging/iio/adc/spear_adc.c b/drivers/staging/iio/adc/spear_adc.c
deleted file mode 100644
index d8232f1..0000000
--- a/drivers/staging/iio/adc/spear_adc.c
+++ /dev/null
@@ -1,429 +0,0 @@
-/*
- * ST SPEAr ADC driver
- *
- * Copyright 2012 Stefan Roese <sr@denx.de>
- *
- * Licensed under the GPL-2.
- */
-
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/interrupt.h>
-#include <linux/device.h>
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/io.h>
-#include <linux/clk.h>
-#include <linux/err.h>
-#include <linux/completion.h>
-#include <linux/of.h>
-#include <linux/of_address.h>
-
-#include <linux/iio/iio.h>
-#include <linux/iio/sysfs.h>
-
-/* SPEAR registers definitions */
-#define SPEAR600_ADC_SCAN_RATE_LO(x)	((x) & 0xFFFF)
-#define SPEAR600_ADC_SCAN_RATE_HI(x)	(((x) >> 0x10) & 0xFFFF)
-#define SPEAR_ADC_CLK_LOW(x)		(((x) & 0xf) << 0)
-#define SPEAR_ADC_CLK_HIGH(x)		(((x) & 0xf) << 4)
-
-/* Bit definitions for SPEAR_ADC_STATUS */
-#define SPEAR_ADC_STATUS_START_CONVERSION	(1 << 0)
-#define SPEAR_ADC_STATUS_CHANNEL_NUM(x)		((x) << 1)
-#define SPEAR_ADC_STATUS_ADC_ENABLE		(1 << 4)
-#define SPEAR_ADC_STATUS_AVG_SAMPLE(x)		((x) << 5)
-#define SPEAR_ADC_STATUS_VREF_INTERNAL		(1 << 9)
-
-#define SPEAR_ADC_DATA_MASK		0x03ff
-#define SPEAR_ADC_DATA_BITS		10
-
-#define SPEAR_ADC_MOD_NAME "spear-adc"
-
-#define SPEAR_ADC_CHANNEL_NUM		8
-
-#define SPEAR_ADC_CLK_MIN			2500000
-#define SPEAR_ADC_CLK_MAX			20000000
-
-struct adc_regs_spear3xx {
-	u32 status;
-	u32 average;
-	u32 scan_rate;
-	u32 clk;	/* Not avail for 1340 & 1310 */
-	u32 ch_ctrl[SPEAR_ADC_CHANNEL_NUM];
-	u32 ch_data[SPEAR_ADC_CHANNEL_NUM];
-};
-
-struct chan_data {
-	u32 lsb;
-	u32 msb;
-};
-
-struct adc_regs_spear6xx {
-	u32 status;
-	u32 pad[2];
-	u32 clk;
-	u32 ch_ctrl[SPEAR_ADC_CHANNEL_NUM];
-	struct chan_data ch_data[SPEAR_ADC_CHANNEL_NUM];
-	u32 scan_rate_lo;
-	u32 scan_rate_hi;
-	struct chan_data average;
-};
-
-struct spear_adc_info;
-
-struct spear_adc_ops {
-	u32 (*get_average)(struct spear_adc_info *info);
-	void (*set_scanrate)(struct spear_adc_info *info, u32 rate);
-};
-
-struct spear_adc_info {
-	struct device_node *np;
-	union {
-		struct adc_regs_spear3xx __iomem *adc_base_spear3xx;
-		struct adc_regs_spear6xx __iomem *adc_base_spear6xx;
-	};
-	const struct spear_adc_ops *ops;
-	struct clk *clk;
-	struct completion completion;
-	u32 current_clk;
-	u32 sampling_freq;
-	u32 avg_samples;
-	u32 vref_external;
-	u32 value;
-};
-
-static void spear_adc_set_status(struct spear_adc_info *info, u32 val)
-{
-	__raw_writel(val, &info->adc_base_spear6xx->status);
-}
-
-static void spear_adc_set_clk(struct spear_adc_info *info, u32 val)
-{
-	u32 clk_high, clk_low, count;
-	u32 apb_clk = clk_get_rate(info->clk);
-
-	count = (apb_clk + val - 1) / val;
-	clk_low = count / 2;
-	clk_high = count - clk_low;
-	info->current_clk = apb_clk / count;
-
-	__raw_writel(SPEAR_ADC_CLK_LOW(clk_low) | SPEAR_ADC_CLK_HIGH(clk_high),
-		     &info->adc_base_spear6xx->clk);
-}
-
-static void spear_adc_set_ctrl(struct spear_adc_info *info, int n,
-			       u32 val)
-{
-	__raw_writel(val, &info->adc_base_spear6xx->ch_ctrl[n]);
-}
-
-static u32 spear600_adc_get_average(struct spear_adc_info *info)
-{
-	return __raw_readl(&info->adc_base_spear6xx->average.msb) &
-		SPEAR_ADC_DATA_MASK;
-}
-
-static u32 spear300_adc_get_average(struct spear_adc_info *info)
-{
-	return __raw_readl(&info->adc_base_spear3xx->average) &
-		SPEAR_ADC_DATA_MASK;
-}
-
-static void spear600_adc_set_scanrate(struct spear_adc_info *info, u32 rate)
-{
-	__raw_writel(SPEAR600_ADC_SCAN_RATE_LO(rate),
-		&info->adc_base_spear6xx->scan_rate_lo);
-	__raw_writel(SPEAR600_ADC_SCAN_RATE_HI(rate),
-		&info->adc_base_spear6xx->scan_rate_hi);
-}
-
-static void spear300_adc_set_scanrate(struct spear_adc_info *info, u32 rate)
-{
-	__raw_writel(rate, &info->adc_base_spear3xx->scan_rate);
-}
-
-static const struct spear_adc_ops spear600_adc_ops = {
-	.get_average = &spear600_adc_get_average,
-	.set_scanrate = &spear600_adc_set_scanrate,
-};
-
-static const struct spear_adc_ops spear300_adc_ops = {
-	.get_average = &spear300_adc_get_average,
-	.set_scanrate = &spear300_adc_set_scanrate,
-};
-
-static int spear_read_raw(struct iio_dev *indio_dev,
-			  struct iio_chan_spec const *chan,
-			  int *val,
-			  int *val2,
-			  long mask)
-{
-	struct spear_adc_info *info = iio_priv(indio_dev);
-	u32 status;
-
-	switch (mask) {
-	case IIO_CHAN_INFO_RAW:
-		mutex_lock(&indio_dev->mlock);
-
-		status = SPEAR_ADC_STATUS_CHANNEL_NUM(chan->channel) |
-			SPEAR_ADC_STATUS_AVG_SAMPLE(info->avg_samples) |
-			SPEAR_ADC_STATUS_START_CONVERSION |
-			SPEAR_ADC_STATUS_ADC_ENABLE;
-		if (info->vref_external == 0)
-			status |= SPEAR_ADC_STATUS_VREF_INTERNAL;
-
-		spear_adc_set_status(info, status);
-		wait_for_completion(&info->completion); /* set by ISR */
-		*val = info->value;
-
-		mutex_unlock(&indio_dev->mlock);
-
-		return IIO_VAL_INT;
-
-	case IIO_CHAN_INFO_SCALE:
-		*val = info->vref_external;
-		*val2 = SPEAR_ADC_DATA_BITS;
-		return IIO_VAL_FRACTIONAL_LOG2;
-	case IIO_CHAN_INFO_SAMP_FREQ:
-		*val = info->current_clk;
-		return IIO_VAL_INT;
-	}
-
-	return -EINVAL;
-}
-
-static int spear_adc_write_raw(struct iio_dev *indio_dev,
-			       struct iio_chan_spec const *chan,
-			       int val,
-			       int val2,
-			       long mask)
-{
-	struct spear_adc_info *info = iio_priv(indio_dev);
-	u32 clk_high, clk_low, count;
-	u32 apb_clk = clk_get_rate(info->clk);
-	int ret = 0;
-
-	mutex_lock(&indio_dev->mlock);
-
-	if ((val < SPEAR_ADC_CLK_MIN) ||
-		(val > SPEAR_ADC_CLK_MAX) ||
-		(val2 != 0)) {
-		ret = -EINVAL;
-		goto out;
-	}
-
-	count = (apb_clk + val - 1) / val;
-	clk_low = count / 2;
-	clk_high = count - clk_low;
-	info->current_clk = apb_clk / count;
-	spear_adc_set_clk(info, val);
-
-out:
-	mutex_unlock(&indio_dev->mlock);
-	return ret;
-}
-
-#define SPEAR_ADC_CHAN(idx) {				\
-	.type = IIO_VOLTAGE,				\
-	.indexed = 1,					\
-	.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),\
-	.channel = idx,					\
-}
-
-static const struct iio_chan_spec spear_adc_iio_channels[] = {
-	SPEAR_ADC_CHAN(0),
-	SPEAR_ADC_CHAN(1),
-	SPEAR_ADC_CHAN(2),
-	SPEAR_ADC_CHAN(3),
-	SPEAR_ADC_CHAN(4),
-	SPEAR_ADC_CHAN(5),
-	SPEAR_ADC_CHAN(6),
-	SPEAR_ADC_CHAN(7),
-};
-
-static irqreturn_t spear_adc_isr(int irq, void *dev_id)
-{
-	struct spear_adc_info *info = (struct spear_adc_info *)dev_id;
-
-	/* Read value to clear IRQ */
-	info->value = info->ops->get_average(info);
-	complete(&info->completion);
-
-	return IRQ_HANDLED;
-}
-
-static int spear_adc_configure(struct spear_adc_info *info)
-{
-	int i;
-
-	/* Reset ADC core */
-	spear_adc_set_status(info, 0);
-	__raw_writel(0, &info->adc_base_spear6xx->clk);
-	for (i = 0; i < 8; i++)
-		spear_adc_set_ctrl(info, i, 0);
-	info->ops->set_scanrate(info, 0);
-
-	spear_adc_set_clk(info, info->sampling_freq);
-
-	return 0;
-}
-
-static const struct iio_info spear_adc_iio_info = {
-	.read_raw = &spear_read_raw,
-	.write_raw = &spear_adc_write_raw,
-	.driver_module = THIS_MODULE,
-};
-
-static int spear_adc_probe(struct platform_device *pdev)
-{
-	struct device_node *np = pdev->dev.of_node;
-	struct device *dev = &pdev->dev;
-	struct spear_adc_info *info;
-	struct iio_dev *iodev = NULL;
-	int ret = -ENODEV;
-	int irq;
-
-	iodev = devm_iio_device_alloc(dev, sizeof(struct spear_adc_info));
-	if (!iodev) {
-		dev_err(dev, "failed allocating iio device\n");
-		return -ENOMEM;
-	}
-
-	info = iio_priv(iodev);
-	info->np = np;
-
-	/*
-	 * SPEAr600 has a different register layout than other SPEAr SoC's
-	 * (e.g. SPEAr3xx). Let's provide two register base addresses
-	 * to support multi-arch kernels.
-	 */
-	if (of_device_is_compatible(info->np, "st,spear600-adc")) {
-		info->adc_base_spear6xx = of_iomap(np, 0);
-		if (!info->adc_base_spear6xx) {
-			dev_err(dev, "failed mapping memory\n");
-			return -ENOMEM;
-		}
-		info->ops = &spear600_adc_ops;
-	} else {
-		info->adc_base_spear3xx = of_iomap(np, 0);
-		if (!info->adc_base_spear3xx) {
-			dev_err(dev, "failed mapping memory\n");
-			return -ENOMEM;
-		}
-		info->ops = &spear300_adc_ops;
-	}
-
-	info->clk = clk_get(dev, NULL);
-	if (IS_ERR(info->clk)) {
-		dev_err(dev, "failed getting clock\n");
-		goto errout1;
-	}
-
-	ret = clk_prepare_enable(info->clk);
-	if (ret) {
-		dev_err(dev, "failed enabling clock\n");
-		goto errout2;
-	}
-
-	irq = platform_get_irq(pdev, 0);
-	if (irq <= 0) {
-		dev_err(dev, "failed getting interrupt resource\n");
-		ret = -EINVAL;
-		goto errout3;
-	}
-
-	ret = devm_request_irq(dev, irq, spear_adc_isr, 0, SPEAR_ADC_MOD_NAME,
-			info);
-	if (ret < 0) {
-		dev_err(dev, "failed requesting interrupt\n");
-		goto errout3;
-	}
-
-	if (of_property_read_u32(np, "sampling-frequency",
-				 &info->sampling_freq)) {
-		dev_err(dev, "sampling-frequency missing in DT\n");
-		ret = -EINVAL;
-		goto errout3;
-	}
-
-	/*
-	 * Optional avg_samples defaults to 0, resulting in single data
-	 * conversion
-	 */
-	of_property_read_u32(np, "average-samples", &info->avg_samples);
-
-	/*
-	 * Optional vref_external defaults to 0, resulting in internal vref
-	 * selection
-	 */
-	of_property_read_u32(np, "vref-external", &info->vref_external);
-
-	spear_adc_configure(info);
-
-	platform_set_drvdata(pdev, iodev);
-
-	init_completion(&info->completion);
-
-	iodev->name = SPEAR_ADC_MOD_NAME;
-	iodev->dev.parent = dev;
-	iodev->info = &spear_adc_iio_info;
-	iodev->modes = INDIO_DIRECT_MODE;
-	iodev->channels = spear_adc_iio_channels;
-	iodev->num_channels = ARRAY_SIZE(spear_adc_iio_channels);
-
-	ret = iio_device_register(iodev);
-	if (ret)
-		goto errout3;
-
-	dev_info(dev, "SPEAR ADC driver loaded, IRQ %d\n", irq);
-
-	return 0;
-
-errout3:
-	clk_disable_unprepare(info->clk);
-errout2:
-	clk_put(info->clk);
-errout1:
-	iounmap(info->adc_base_spear6xx);
-	return ret;
-}
-
-static int spear_adc_remove(struct platform_device *pdev)
-{
-	struct iio_dev *iodev = platform_get_drvdata(pdev);
-	struct spear_adc_info *info = iio_priv(iodev);
-
-	iio_device_unregister(iodev);
-	clk_disable_unprepare(info->clk);
-	clk_put(info->clk);
-	iounmap(info->adc_base_spear6xx);
-
-	return 0;
-}
-
-#ifdef CONFIG_OF
-static const struct of_device_id spear_adc_dt_ids[] = {
-	{ .compatible = "st,spear600-adc", },
-	{ /* sentinel */ }
-};
-MODULE_DEVICE_TABLE(of, spear_adc_dt_ids);
-#endif
-
-static struct platform_driver spear_adc_driver = {
-	.probe		= spear_adc_probe,
-	.remove		= spear_adc_remove,
-	.driver		= {
-		.name	= SPEAR_ADC_MOD_NAME,
-		.owner	= THIS_MODULE,
-		.of_match_table = of_match_ptr(spear_adc_dt_ids),
-	},
-};
-
-module_platform_driver(spear_adc_driver);
-
-MODULE_AUTHOR("Stefan Roese <sr@denx.de>");
-MODULE_DESCRIPTION("SPEAr ADC driver");
-MODULE_LICENSE("GPL");
-- 
1.9.0

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

* Re: [PATCH 0/5] iio: Minor cleanups to spear ADC driver followed by staging graduation.
  2014-03-11 20:36 [PATCH 0/5] iio: Minor cleanups to spear ADC driver followed by staging graduation Jonathan Cameron
                   ` (4 preceding siblings ...)
  2014-03-11 20:36 ` [PATCH 5/5] iio:adc:spear_adc move out of staging Jonathan Cameron
@ 2014-03-12  6:50 ` Stefan Roese
  5 siblings, 0 replies; 11+ messages in thread
From: Stefan Roese @ 2014-03-12  6:50 UTC (permalink / raw)
  To: Jonathan Cameron, linux-iio

On 11.03.2014 21:36, Jonathan Cameron wrote:
> This driver has been reasonably clean since it was first merged within the
> staging tree.  If it had been submitted after the IIO core was outside of
> staging we might have taken it as is. I did a final review and the first 4
> patches of this series rework various minor aspects of the driver.
>
> Whilst it is a slow driver, the device tree matches at the lowest level seemed
> a little unwise so the largest rework is concerned with centralising that
> logic using a classic ops structure of function pointers.  The other large
> change was to move to using the info_mask_shared_by_all approach to handle
> sampling frequency.  This is something I am slowly propogating across the
> whole tree, but might as well be done whilst we are looking at this driver.
>
> I don't have hardware and whilst I think these are all changes that are
> possible to easily verify by eye, a tested by would be most welcome!
>
> Note this is the first driver I'm suggesting moving out of staging following
> Greg's entirely reasonable question of 'What's wrong with the stuff that is
> left?'  Any help with this sort of final cleanup and move would be most
> welcome.

Jonathan, thanks for working on this. Really appreciated. I don't have a 
spear600 board at hand right now. But all your changes seem reasonable. So:

Ackey-by: Stefan Roese <sr@denx.de>

Thanks,
Stefan

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

* Re: [PATCH 4/5] staging:iio:adc:spear_adc use info_mask_shared_by_all for samp freq
  2014-03-11 20:36 ` [PATCH 4/5] staging:iio:adc:spear_adc use info_mask_shared_by_all for samp freq Jonathan Cameron
@ 2014-03-12 20:31   ` Hartmut Knaack
  2014-03-15 14:49     ` Jonathan Cameron
  0 siblings, 1 reply; 11+ messages in thread
From: Hartmut Knaack @ 2014-03-12 20:31 UTC (permalink / raw)
  To: Jonathan Cameron, linux-iio; +Cc: sr

Jonathan Cameron schrieb:
> Using the core support makes this element available to in kernel users as
> well as to userspace under exactly the same interface as before.  The
> intent is to move all sampling frequency control to this approach
> throughout IIO.
>
> Signed-off-by: Jonathan Cameron <jic23@kernel.org>
> ---
>  drivers/staging/iio/adc/spear_adc.c | 95 ++++++++++++++-----------------------
>  1 file changed, 36 insertions(+), 59 deletions(-)
>
> diff --git a/drivers/staging/iio/adc/spear_adc.c b/drivers/staging/iio/adc/spear_adc.c
> index fbe69a7..d8232f1 100644
> --- a/drivers/staging/iio/adc/spear_adc.c
> +++ b/drivers/staging/iio/adc/spear_adc.c
> @@ -185,16 +185,51 @@ static int spear_read_raw(struct iio_dev *indio_dev,
>  		*val = info->vref_external;
>  		*val2 = SPEAR_ADC_DATA_BITS;
>  		return IIO_VAL_FRACTIONAL_LOG2;
> +	case IIO_CHAN_INFO_SAMP_FREQ:
> +		*val = info->current_clk;
> +		return IIO_VAL_INT;
>  	}
>  
>  	return -EINVAL;
>  }
>  
> +static int spear_adc_write_raw(struct iio_dev *indio_dev,
> +			       struct iio_chan_spec const *chan,
> +			       int val,
> +			       int val2,
> +			       long mask)
> +{
> +	struct spear_adc_info *info = iio_priv(indio_dev);
> +	u32 clk_high, clk_low, count;
> +	u32 apb_clk = clk_get_rate(info->clk);
> +	int ret = 0;
> +
> +	mutex_lock(&indio_dev->mlock);
> +
> +	if ((val < SPEAR_ADC_CLK_MIN) ||
> +		(val > SPEAR_ADC_CLK_MAX) ||
> +		(val2 != 0)) {
> +		ret = -EINVAL;
> +		goto out;
> +	}
> +
> +	count = (apb_clk + val - 1) / val;
> +	clk_low = count / 2;
> +	clk_high = count - clk_low;
> +	info->current_clk = apb_clk / count;
> +	spear_adc_set_clk(info, val);
> +
What is actually the purpose of clk_low and clk_high? I don't see them used after doing that calculation.
And is it really 100% safe to avoid checking mask?
> +out:
> +	mutex_unlock(&indio_dev->mlock);
> +	return ret;
> +}
> +
>  #define SPEAR_ADC_CHAN(idx) {				\
>  	.type = IIO_VOLTAGE,				\
>  	.indexed = 1,					\
>  	.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),\
>  	.channel = idx,					\
>  }
>  
> @@ -236,67 +271,9 @@ static int spear_adc_configure(struct spear_adc_info *info)
>  	return 0;
>  }
>  
> -static ssize_t spear_adc_read_frequency(struct device *dev,
> -					struct device_attribute *attr,
> -					char *buf)
> -{
> -	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
> -	struct spear_adc_info *info = iio_priv(indio_dev);
> -
> -	return sprintf(buf, "%d\n", info->current_clk);
> -}
> -
> -static ssize_t spear_adc_write_frequency(struct device *dev,
> -					 struct device_attribute *attr,
> -					 const char *buf,
> -					 size_t len)
> -{
> -	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
> -	struct spear_adc_info *info = iio_priv(indio_dev);
> -	u32 clk_high, clk_low, count;
> -	u32 apb_clk = clk_get_rate(info->clk);
> -	unsigned long lval;
> -	int ret;
> -
> -	ret = kstrtoul(buf, 10, &lval);
> -	if (ret)
> -		return ret;
> -
> -	mutex_lock(&indio_dev->mlock);
> -
> -	if ((lval < SPEAR_ADC_CLK_MIN) || (lval > SPEAR_ADC_CLK_MAX)) {
> -		ret = -EINVAL;
> -		goto out;
> -	}
> -
> -	count = (apb_clk + lval - 1) / lval;
> -	clk_low = count / 2;
> -	clk_high = count - clk_low;
> -	info->current_clk = apb_clk / count;
> -	spear_adc_set_clk(info, lval);
> -
> -out:
> -	mutex_unlock(&indio_dev->mlock);
> -
> -	return ret ? ret : len;
> -}
> -
> -static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO,
> -			      spear_adc_read_frequency,
> -			      spear_adc_write_frequency);
> -
> -static struct attribute *spear_attributes[] = {
> -	&iio_dev_attr_sampling_frequency.dev_attr.attr,
> -	NULL
> -};
> -
> -static const struct attribute_group spear_attribute_group = {
> -	.attrs = spear_attributes,
> -};
> -
>  static const struct iio_info spear_adc_iio_info = {
>  	.read_raw = &spear_read_raw,
> -	.attrs = &spear_attribute_group,
> +	.write_raw = &spear_adc_write_raw,
>  	.driver_module = THIS_MODULE,
>  };
>  


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

* Re: [PATCH 5/5] iio:adc:spear_adc move out of staging
  2014-03-11 20:36 ` [PATCH 5/5] iio:adc:spear_adc move out of staging Jonathan Cameron
@ 2014-03-12 20:46   ` Hartmut Knaack
  2014-03-13 15:45     ` Jonathan Cameron
  0 siblings, 1 reply; 11+ messages in thread
From: Hartmut Knaack @ 2014-03-12 20:46 UTC (permalink / raw)
  To: Jonathan Cameron, linux-iio; +Cc: sr

Jonathan Cameron schrieb:
> This simple driver is ready to move out of staging.
>
> Signed-off-by: Jonathan Cameron <jic23@kernel.org>
> ---
>  drivers/iio/adc/Kconfig             |   8 +
>  drivers/iio/adc/Makefile            |   1 +
>  drivers/iio/adc/spear_adc.c         | 429 ++++++++++++++++++++++++++++++++++++
>  drivers/staging/iio/adc/Kconfig     |   8 -
>  drivers/staging/iio/adc/Makefile    |   1 -
>  drivers/staging/iio/adc/spear_adc.c | 429 ------------------------------------
>  6 files changed, 438 insertions(+), 438 deletions(-)
>
> diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
> index 5553206..2e3e1b0 100644
> --- a/drivers/iio/adc/Kconfig
> +++ b/drivers/iio/adc/Kconfig
> @@ -164,6 +164,14 @@ config NAU7802
>  	  To compile this driver as a module, choose M here: the
>  	  module will be called nau7802.
>  
> +config SPEAR_ADC
> +	tristate "ST SPEAr ADC"
> +	depends on PLAT_SPEAR || COMPILE_TEST
Are you sure to keep COMPILE_TEST in?
> +	depends on HAS_IOMEM
> +	help
> +	  Say yes here to build support for the integrated ADC inside the
> +	  ST SPEAr SoC. Provides direct access via sysfs.
> +
>  config TI_ADC081C
>  	tristate "Texas Instruments ADC081C021/027"
>  	depends on I2C
>


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

* Re: [PATCH 5/5] iio:adc:spear_adc move out of staging
  2014-03-12 20:46   ` Hartmut Knaack
@ 2014-03-13 15:45     ` Jonathan Cameron
  0 siblings, 0 replies; 11+ messages in thread
From: Jonathan Cameron @ 2014-03-13 15:45 UTC (permalink / raw)
  To: Hartmut Knaack, linux-iio; +Cc: sr



On March 12, 2014 8:46:19 PM GMT+00:00, Hartmut Knaack <knaack.h@gmx.de> wrote:
>Jonathan Cameron schrieb:
>> This simple driver is ready to move out of staging.
>>
>> Signed-off-by: Jonathan Cameron <jic23@kernel.org>
>> ---
>>  drivers/iio/adc/Kconfig             |   8 +
>>  drivers/iio/adc/Makefile            |   1 +
>>  drivers/iio/adc/spear_adc.c         | 429
>++++++++++++++++++++++++++++++++++++
>>  drivers/staging/iio/adc/Kconfig     |   8 -
>>  drivers/staging/iio/adc/Makefile    |   1 -
>>  drivers/staging/iio/adc/spear_adc.c | 429
>------------------------------------
>>  6 files changed, 438 insertions(+), 438 deletions(-)
>>
>> diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
>> index 5553206..2e3e1b0 100644
>> --- a/drivers/iio/adc/Kconfig
>> +++ b/drivers/iio/adc/Kconfig
>> @@ -164,6 +164,14 @@ config NAU7802
>>  	  To compile this driver as a module, choose M here: the
>>  	  module will be called nau7802.
>>  
>> +config SPEAR_ADC
>> +	tristate "ST SPEAr ADC"
>> +	depends on PLAT_SPEAR || COMPILE_TEST
>Are you sure to keep COMPILE_TEST in?
Yes. Allows those without a spear specific config to build test. Prevents a lot of bugs sneaking in for more obscure platforms.

We do this for any drivers that don't require any other support from the platform.
>> +	depends on HAS_IOMEM
>> +	help
>> +	  Say yes here to build support for the integrated ADC inside the
>> +	  ST SPEAr SoC. Provides direct access via sysfs.
>> +
>>  config TI_ADC081C
>>  	tristate "Texas Instruments ADC081C021/027"
>>  	depends on I2C
>>

-- 
Sent from my Android phone with K-9 Mail. Please excuse my brevity.

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

* Re: [PATCH 4/5] staging:iio:adc:spear_adc use info_mask_shared_by_all for samp freq
  2014-03-12 20:31   ` Hartmut Knaack
@ 2014-03-15 14:49     ` Jonathan Cameron
  0 siblings, 0 replies; 11+ messages in thread
From: Jonathan Cameron @ 2014-03-15 14:49 UTC (permalink / raw)
  To: Hartmut Knaack, linux-iio; +Cc: sr

On 12/03/14 20:31, Hartmut Knaack wrote:
> Jonathan Cameron schrieb:
>> Using the core support makes this element available to in kernel users as
>> well as to userspace under exactly the same interface as before.  The
>> intent is to move all sampling frequency control to this approach
>> throughout IIO.
>>
>> Signed-off-by: Jonathan Cameron <jic23@kernel.org>
>> ---
>>   drivers/staging/iio/adc/spear_adc.c | 95 ++++++++++++++-----------------------
>>   1 file changed, 36 insertions(+), 59 deletions(-)
>>
>> diff --git a/drivers/staging/iio/adc/spear_adc.c b/drivers/staging/iio/adc/spear_adc.c
>> index fbe69a7..d8232f1 100644
>> --- a/drivers/staging/iio/adc/spear_adc.c
>> +++ b/drivers/staging/iio/adc/spear_adc.c
>> @@ -185,16 +185,51 @@ static int spear_read_raw(struct iio_dev *indio_dev,
>>   		*val = info->vref_external;
>>   		*val2 = SPEAR_ADC_DATA_BITS;
>>   		return IIO_VAL_FRACTIONAL_LOG2;
>> +	case IIO_CHAN_INFO_SAMP_FREQ:
>> +		*val = info->current_clk;
>> +		return IIO_VAL_INT;
>>   	}
>>
>>   	return -EINVAL;
>>   }
>>
>> +static int spear_adc_write_raw(struct iio_dev *indio_dev,
>> +			       struct iio_chan_spec const *chan,
>> +			       int val,
>> +			       int val2,
>> +			       long mask)
>> +{
>> +	struct spear_adc_info *info = iio_priv(indio_dev);
>> +	u32 clk_high, clk_low, count;
>> +	u32 apb_clk = clk_get_rate(info->clk);
>> +	int ret = 0;
>> +
>> +	mutex_lock(&indio_dev->mlock);
>> +
>> +	if ((val < SPEAR_ADC_CLK_MIN) ||
>> +		(val > SPEAR_ADC_CLK_MAX) ||
>> +		(val2 != 0)) {
>> +		ret = -EINVAL;
>> +		goto out;
>> +	}
>> +
>> +	count = (apb_clk + val - 1) / val;
>> +	clk_low = count / 2;
>> +	clk_high = count - clk_low;
>> +	info->current_clk = apb_clk / count;
>> +	spear_adc_set_clk(info, val);
>> +
> What is actually the purpose of clk_low and clk_high? I don't see them used after doing that calculation.
Good spot.  Looks like this is the result of an earlier reworking.  These get recomputed in the set_clk
function.

> And is it really 100% safe to avoid checking mask?
Fair point. No it's not. Oops.  Will fix and repost in a sec.
>> +out:
>> +	mutex_unlock(&indio_dev->mlock);
>> +	return ret;
>> +}
>> +
>>   #define SPEAR_ADC_CHAN(idx) {				\
>>   	.type = IIO_VOLTAGE,				\
>>   	.indexed = 1,					\
>>   	.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),\
>>   	.channel = idx,					\
>>   }
>>
>> @@ -236,67 +271,9 @@ static int spear_adc_configure(struct spear_adc_info *info)
>>   	return 0;
>>   }
>>
>> -static ssize_t spear_adc_read_frequency(struct device *dev,
>> -					struct device_attribute *attr,
>> -					char *buf)
>> -{
>> -	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
>> -	struct spear_adc_info *info = iio_priv(indio_dev);
>> -
>> -	return sprintf(buf, "%d\n", info->current_clk);
>> -}
>> -
>> -static ssize_t spear_adc_write_frequency(struct device *dev,
>> -					 struct device_attribute *attr,
>> -					 const char *buf,
>> -					 size_t len)
>> -{
>> -	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
>> -	struct spear_adc_info *info = iio_priv(indio_dev);
>> -	u32 clk_high, clk_low, count;
>> -	u32 apb_clk = clk_get_rate(info->clk);
>> -	unsigned long lval;
>> -	int ret;
>> -
>> -	ret = kstrtoul(buf, 10, &lval);
>> -	if (ret)
>> -		return ret;
>> -
>> -	mutex_lock(&indio_dev->mlock);
>> -
>> -	if ((lval < SPEAR_ADC_CLK_MIN) || (lval > SPEAR_ADC_CLK_MAX)) {
>> -		ret = -EINVAL;
>> -		goto out;
>> -	}
>> -
>> -	count = (apb_clk + lval - 1) / lval;
>> -	clk_low = count / 2;
>> -	clk_high = count - clk_low;
>> -	info->current_clk = apb_clk / count;
>> -	spear_adc_set_clk(info, lval);
>> -
>> -out:
>> -	mutex_unlock(&indio_dev->mlock);
>> -
>> -	return ret ? ret : len;
>> -}
>> -
>> -static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO,
>> -			      spear_adc_read_frequency,
>> -			      spear_adc_write_frequency);
>> -
>> -static struct attribute *spear_attributes[] = {
>> -	&iio_dev_attr_sampling_frequency.dev_attr.attr,
>> -	NULL
>> -};
>> -
>> -static const struct attribute_group spear_attribute_group = {
>> -	.attrs = spear_attributes,
>> -};
>> -
>>   static const struct iio_info spear_adc_iio_info = {
>>   	.read_raw = &spear_read_raw,
>> -	.attrs = &spear_attribute_group,
>> +	.write_raw = &spear_adc_write_raw,
>>   	.driver_module = THIS_MODULE,
>>   };
>>
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-iio" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>


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

end of thread, other threads:[~2014-03-15 14:48 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-03-11 20:36 [PATCH 0/5] iio: Minor cleanups to spear ADC driver followed by staging graduation Jonathan Cameron
2014-03-11 20:36 ` [PATCH 1/5] staging:iio:adc:spear adc - prefix defines to avoid namespace clashes Jonathan Cameron
2014-03-11 20:36 ` [PATCH 2/5] staging:iio:adc:spear adc rework so that device tree queries are all in probe Jonathan Cameron
2014-03-11 20:36 ` [PATCH 3/5] staging:iio:adc:spear_adc drop initialization of unused scan_type Jonathan Cameron
2014-03-11 20:36 ` [PATCH 4/5] staging:iio:adc:spear_adc use info_mask_shared_by_all for samp freq Jonathan Cameron
2014-03-12 20:31   ` Hartmut Knaack
2014-03-15 14:49     ` Jonathan Cameron
2014-03-11 20:36 ` [PATCH 5/5] iio:adc:spear_adc move out of staging Jonathan Cameron
2014-03-12 20:46   ` Hartmut Knaack
2014-03-13 15:45     ` Jonathan Cameron
2014-03-12  6:50 ` [PATCH 0/5] iio: Minor cleanups to spear ADC driver followed by staging graduation Stefan Roese

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).