Skip to contentSkip to conversation

Add ADC driver for G20 and G45 evaluation boards

PATCH Superseded Maxime Ripard 3 participants 13 messages Apr 5, 2012 – Apr 13, 2012

Subsystems (6)

v1 of 5 Superseded Latest is v5 →

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 Add ADC driver for G20 and G45 evaluation boards

Hi all,

Here is the improved version of what I've been posting some time ago. Some things changed since last version:
- Support for Hardware triggers for the G20 has been added
- Support for the AT91SAM9M10G45 board has been added too, both for software and hardware triggers
- The driver is now in drivers/staging/iio to include all these features.

The first three patches should not have changed much since last post, so it should be pretty ok.

Thanks,
Maxime

#1 lore raw

PATCH 1/5 ARM: AT91: Add platform data for the AT91 ADCs

The AT91 SoCs often embeds an ADC. This patch adds the needed platform data to specify the informations required by the driver to work properly.

For now, we only need the reference voltage and which channels are available on the board.

Cc Nicolas Ferre <[email protected]>
Cc Patrice Vilchez <[email protected]>
Cc Thomas Petazzoni <[email protected]>
Cc Jean-Christophe PLAGNIOL-VILLARD <[email protected]>
---
 include/linux/platform_data/at91_adc.h |   23 +++++++++++++++++++++++
 1 files changed, 23 insertions(+), 0 deletions(-)
 create mode 100644 include/linux/platform_data/at91_adc.h
include/linux/platform_data/at91_adc.h new file +23 -0
new file mode 100644
index 0000000..1f71510
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2011 Free Electrons
+ *
+ * Licensed under the GPLv2 or later.
+ *
+ */
+
+#ifndef _AT91_ADC_H_
+#define _AT91_ADC_H_
+
+/**
+ * struct at91_adc_data - platform data for ADC driver
+ * @channels_used:	channels in use on the board as a bitmask
+ * @vref:		Reference voltage for the ADC in millivolts
+ */
+struct at91_adc_data {
+	unsigned long	channels_used;
+	u16		vref;
+};
+
+extern void __init at91_add_device_adc(struct at91_adc_data *data);
+
+#endif
Signature · 1 line
1.7.5.4
maintainer
#2 lore raw

PATCH 1/5 ARM: AT91: Add platform data for the AT91 ADCs

Quoted 6 lines · Maxime Ripard

The AT91 SoCs often embeds an ADC. This patch adds the needed platform data to specify the informations required by the driver to work properly.

For now, we only need the reference voltage and which channels are available on the board.

Trivial, though I'm in a fussy mood so see below.

Quoted 2 lines
Quoted 16 lines
Cc Nicolas Ferre<[email protected]>
Cc Patrice Vilchez<[email protected]>
Cc Thomas Petazzoni<[email protected]>
Cc Jean-Christophe PLAGNIOL-VILLARD<[email protected]>
---
  include/linux/platform_data/at91_adc.h |   23 +++++++++++++++++++++++
  1 files changed, 23 insertions(+), 0 deletions(-)

create mode 100644 include/linux/platform_data/at91_adc.h

include/linux/platform_data/at91_adc.h new file +0 -0
new file mode 100644
index 0000000..1f71510

include/linux/platform_data/at91_adc.h line 4

Quoted 4 lines
include/linux/platform_data/at91_adc.h new file +4 -0
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2011 Free Electrons
+ *
+ * Licensed under the GPLv2 or later.

If we are really being nitpicky, no point in the next blank line!

Quoted 19 lines
include/linux/platform_data/at91_adc.h new file +19 -0
+ *
+ */
+
+#ifndef _AT91_ADC_H_
+#define _AT91_ADC_H_
+
+/**
+ * struct at91_adc_data - platform data for ADC driver
+ * @channels_used:	channels in use on the board as a bitmask
+ * @vref:		Reference voltage for the ADC in millivolts
+ */
+struct at91_adc_data {
+	unsigned long	channels_used;
+	u16		vref;
+};
+
+extern void __init at91_add_device_adc(struct at91_adc_data *data);
+
+#endif
#3 lore raw

PATCH 2/5 ARM: AT91: IIO: Add AT91 ADC driver.

In reply to Maxime Ripard

Add the IIO driver for the AT91 ADCs. It only supports and has been tested on the SAM9G20 evaluation boards, but support for other boards will come eventually.

This ADC is a multi-channel ADC with support for both hardware and software triggers.

This first version only supports software triggers.

Cc Nicolas Ferre <[email protected]>
Cc Jean-Christophe PLAGNIOL-VILLARD <[email protected]>
Cc Patrice Vilchez <[email protected]>
Cc Thomas Petazzoni <[email protected]>
Cc Jonathan Cameron <[email protected]>
---
 drivers/staging/iio/adc/Kconfig    |    6 +
 drivers/staging/iio/adc/Makefile   |    1 +
 drivers/staging/iio/adc/at91_adc.c |  382 ++++++++++++++++++++++++++++++++++++
 3 files changed, 389 insertions(+), 0 deletions(-)
 create mode 100644 drivers/staging/iio/adc/at91_adc.c
drivers/staging/iio/adc/Kconfig +6 -0
index 592eabd..1494838 100644
@@ -169,6 +169,12 @@ config AD7280
 	  To compile this driver as a module, choose M here: the
 	  module will be called ad7280a
 
+config AT91_ADC
+	tristate "Atmel AT91 ADC"
+	depends on SYSFS && ARCH_AT91
+	help
+	  Say yes here to build support for Atmel AT91 ADC.
+
 config MAX1363
 	tristate "Maxim max1363 ADC driver"
 	depends on I2C
drivers/staging/iio/adc/Makefile +1 -0
index f83ab95..8cb6d1c 100644
@@ -38,3 +38,4 @@ obj-$(CONFIG_ADT7310) += adt7310.o
 obj-$(CONFIG_ADT7410) += adt7410.o
 obj-$(CONFIG_AD7280) += ad7280a.o
 obj-$(CONFIG_LPC32XX_ADC) += lpc32xx_adc.o
+obj-$(CONFIG_AT91_ADC) += at91_adc.o
drivers/staging/iio/adc/at91_adc.c new file +382 -0

382 lines not on this page · raw message

Signature · 1 line
1.7.5.4
#4 lore raw

PATCH 2/5 ARM: AT91: IIO: Add AT91 ADC driver.

Quoted 105 lines · Maxime Ripard

Add the IIO driver for the AT91 ADCs. It only supports and has been tested on the SAM9G20 evaluation boards, but support for other boards will come eventually.

This ADC is a multi-channel ADC with support for both hardware and software triggers.

This first version only supports software triggers.

Cc Nicolas Ferre <[email protected]>
Cc Jean-Christophe PLAGNIOL-VILLARD <[email protected]>
Cc Patrice Vilchez <[email protected]>
Cc Thomas Petazzoni <[email protected]>
Cc Jonathan Cameron <[email protected]>
---
 drivers/staging/iio/adc/Kconfig    |    6 +
 drivers/staging/iio/adc/Makefile   |    1 +
 drivers/staging/iio/adc/at91_adc.c |  382 ++++++++++++++++++++++++++++++++++++
 3 files changed, 389 insertions(+), 0 deletions(-)
 create mode 100644 drivers/staging/iio/adc/at91_adc.c
drivers/staging/iio/adc/Kconfig +6 -0
index 592eabd..1494838 100644
@@ -169,6 +169,12 @@ config AD7280
 	  To compile this driver as a module, choose M here: the
 	  module will be called ad7280a
 
+config AT91_ADC
+	tristate "Atmel AT91 ADC"
+	depends on SYSFS && ARCH_AT91
+	help
+	  Say yes here to build support for Atmel AT91 ADC.
+
 config MAX1363
 	tristate "Maxim max1363 ADC driver"
 	depends on I2C
drivers/staging/iio/adc/Makefile +1 -0
index f83ab95..8cb6d1c 100644
@@ -38,3 +38,4 @@ obj-$(CONFIG_ADT7310) += adt7310.o
 obj-$(CONFIG_ADT7410) += adt7410.o
 obj-$(CONFIG_AD7280) += ad7280a.o
 obj-$(CONFIG_LPC32XX_ADC) += lpc32xx_adc.o
+obj-$(CONFIG_AT91_ADC) += at91_adc.o
drivers/staging/iio/adc/at91_adc.c new file +50 -0
new file mode 100644
index 0000000..c76516a
@@ -0,0 +1,382 @@
+/*
+ * Driver for the ADC present in the Atmel AT91 evaluation boards.
+ *
+ * Copyright 2011 Free Electrons
+ *
+ * Licensed under the GPLv2 or later.
+ */
+
+#include <linux/bitmap.h>
+#include <linux/bitops.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/interrupt.h>
+#include <linux/jiffies.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/wait.h>
+
+#include "../iio.h"
+#include <linux/platform_data/at91_adc.h>
+
+#include <mach/at91_adc.h>
+#include <mach/cpu.h>
+
+/**
+ * struct at91_adc_desc - description of the ADC on the board
+ * @clock:		ADC clock as specified by the datasheet, in Hz.
+ * @clock_name		Name of the ADC clock as defined in the clock tree
+ * @num_channels:	global number of channels available on the board (to
+			specify which channels are indeed in use on the
+			board, see the channels_used bitmask in the platform
+			data)
+ * @startup_time:	startup time of the ADC in microseconds
+ */
+struct at91_adc_desc {
+	u32			clock;
+	char			*clock_name;
+	u8			num_channels;
+	u8			startup_time;
+};
+
+struct at91_adc_state {
+	unsigned long		channels_mask;
+	struct clk		*clk;
+	bool			done;
+	struct at91_adc_desc	*desc;

drivers/staging/iio/adc/at91_adc.c line 60

Quoted 10 lines
drivers/staging/iio/adc/at91_adc.c new file +10 -0
+	int			irq;
+	u16			last_value;
+	struct mutex		lock;
+	void __iomem		*reg_base;
+	u32			vref_mv;
+	wait_queue_head_t	wq_data_avail;
+};
+
+static struct at91_adc_desc at91_adc_desc_sam9g20 = {
+	.clock = 5000000,

why 5Mhz?

drivers/staging/iio/adc/at91_adc.c line 65

Quoted 5 lines
drivers/staging/iio/adc/at91_adc.c new file +5 -0
+	.clock_name = "adc_clk",
+	.num_channels = 4,
+	.startup_time = 10,
+};
+

this is soc specific nedd to be in the soc not in the driver

drivers/staging/iio/adc/at91_adc.c line 74

Quoted 9 lines
drivers/staging/iio/adc/at91_adc.c new file +9 -0
+static int at91_adc_select_soc(struct at91_adc_state *st)
+{
+	if (cpu_is_at91sam9g20()) {
+		st->desc = &at91_adc_desc_sam9g20;
+		return 0;
+	}
+
+	return -ENODEV;
+}

ditto

Quoted 66 lines
drivers/staging/iio/adc/at91_adc.c new file +65 -0
+
 
+
+static int __devinit at91_adc_probe(struct platform_device *pdev)
+{
+	unsigned int prsc, mstrclk, ticks;
+	int ret;
+	struct iio_dev *idev;
+	struct at91_adc_state *st;
+	struct resource *res;
+	struct at91_adc_data *pdata = pdev->dev.platform_data;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		dev_err(&pdev->dev, "No resource defined\n");
+		ret = -ENXIO;
+		goto error_ret;
+	}
+
+	idev = iio_allocate_device(sizeof(struct at91_adc_state));
+	if (idev == NULL) {
+		ret = -ENOMEM;
+		goto error_ret;
+	}
+
+	platform_set_drvdata(pdev, idev);
+
+	idev->dev.parent = &pdev->dev;
+	idev->name = dev_name(&pdev->dev);
+	idev->modes = INDIO_DIRECT_MODE;
+	idev->info = &at91_adc_info;
+
+	st = iio_priv(idev);
+	ret = at91_adc_select_soc(st);
+	if (ret) {
+		dev_err(&pdev->dev, "SoC unknown\n");
+		goto error_free_device;
+	}
+
+	st->irq = platform_get_irq(pdev, 0);
+	if (st->irq < 0) {
+		dev_err(&pdev->dev, "No IRQ ID is designated\n");
+		ret = -ENODEV;
+		goto error_free_device;
+	}
+
+	if (!request_mem_region(res->start, resource_size(res),
+				"AT91 adc registers")) {
+		dev_err(&pdev->dev, "Resources are unavailable.\n");
+		ret = -EBUSY;
+		goto error_free_device;
+	}
+
+	st->reg_base = ioremap(res->start, resource_size(res));
+	if (!st->reg_base) {
+		dev_err(&pdev->dev, "Failed to map registers.\n");
+		ret = -ENOMEM;
+		goto error_release_mem;
+	}
+
+	/*
+	 * Disable all IRQs before setting up the handler
+	 */
+	at91_adc_reg_write(st, AT91_ADC_CR, AT91_ADC_SWRST);
+	at91_adc_reg_write(st, AT91_ADC_IDR, 0xFFFFFFFF);
+	ret = request_irq(st->irq,

drivers/staging/iio/adc/at91_adc.c line 268

Quoted 10 lines
drivers/staging/iio/adc/at91_adc.c new file +10 -0
+			  at91_adc_eoc_trigger,
+			  0,
+			  pdev->dev.driver->name,
+			  idev);
+	if (ret) {
+		dev_err(&pdev->dev, "Failed to allocate IRQ.\n");
+		goto error_unmap_reg;
+	}
+
+	st->clk = clk_get(&pdev->dev, st->desc->clock_name);

use a fixed clock name

drivers/staging/iio/adc/at91_adc.c line 274

Quoted 6 lines
drivers/staging/iio/adc/at91_adc.c new file +6 -0
+	if (IS_ERR(st->clk)) {
+		dev_err(&pdev->dev, "Failed to get the clock.\n");
+		ret = PTR_ERR(st->clk);
+		goto error_free_irq;
+	}
+

use clk_prepare & co

drivers/staging/iio/adc/at91_adc.c line 282

Quoted 8 lines
drivers/staging/iio/adc/at91_adc.c new file +8 -0
+	clk_enable(st->clk);
+	mstrclk = clk_get_rate(st->clk);
+
+	if (!pdata) {
+		dev_err(&pdev->dev, "No platform data available.\n");
+		ret = -EINVAL;
+		goto error_free_clk;
+	}

need to be check first

Best Regards,
J.

#5 lore raw

PATCH 2/5 ARM: AT91: IIO: Add AT91 ADC driver.

Hi,

Le 07/04/2012 05:27, Jean-Christophe PLAGNIOL-VILLARD a ?crit :

Quoted 109 lines · Maxime Ripard
Quoted 108 lines

Add the IIO driver for the AT91 ADCs. It only supports and has been tested on the SAM9G20 evaluation boards, but support for other boards will come eventually.

This ADC is a multi-channel ADC with support for both hardware and software triggers.

This first version only supports software triggers.

Cc Nicolas Ferre <[email protected]>
Cc Jean-Christophe PLAGNIOL-VILLARD <[email protected]>
Cc Patrice Vilchez <[email protected]>
Cc Thomas Petazzoni <[email protected]>
Cc Jonathan Cameron <[email protected]>
---
 drivers/staging/iio/adc/Kconfig    |    6 +
 drivers/staging/iio/adc/Makefile   |    1 +
 drivers/staging/iio/adc/at91_adc.c |  382 ++++++++++++++++++++++++++++++++++++
 3 files changed, 389 insertions(+), 0 deletions(-)
 create mode 100644 drivers/staging/iio/adc/at91_adc.c
drivers/staging/iio/adc/Kconfig +6 -0
index 592eabd..1494838 100644
@@ -169,6 +169,12 @@ config AD7280
 	  To compile this driver as a module, choose M here: the
 	  module will be called ad7280a
 
+config AT91_ADC
+	tristate "Atmel AT91 ADC"
+	depends on SYSFS && ARCH_AT91
+	help
+	  Say yes here to build support for Atmel AT91 ADC.
+
 config MAX1363
 	tristate "Maxim max1363 ADC driver"
 	depends on I2C
drivers/staging/iio/adc/Makefile +1 -0
index f83ab95..8cb6d1c 100644
@@ -38,3 +38,4 @@ obj-$(CONFIG_ADT7310) += adt7310.o
 obj-$(CONFIG_ADT7410) += adt7410.o
 obj-$(CONFIG_AD7280) += ad7280a.o
 obj-$(CONFIG_LPC32XX_ADC) += lpc32xx_adc.o
+obj-$(CONFIG_AT91_ADC) += at91_adc.o
drivers/staging/iio/adc/at91_adc.c new file +53 -0
new file mode 100644
index 0000000..c76516a
@@ -0,0 +1,382 @@
+/*
+ * Driver for the ADC present in the Atmel AT91 evaluation boards.
+ *
+ * Copyright 2011 Free Electrons
+ *
+ * Licensed under the GPLv2 or later.
+ */
+
+#include <linux/bitmap.h>
+#include <linux/bitops.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/interrupt.h>
+#include <linux/jiffies.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/wait.h>
+
+#include "../iio.h"
+#include <linux/platform_data/at91_adc.h>
+
+#include <mach/at91_adc.h>
+#include <mach/cpu.h>
+
+/**
+ * struct at91_adc_desc - description of the ADC on the board
+ * @clock:		ADC clock as specified by the datasheet, in Hz.
+ * @clock_name		Name of the ADC clock as defined in the clock tree
+ * @num_channels:	global number of channels available on the board (to
+			specify which channels are indeed in use on the
+			board, see the channels_used bitmask in the platform
+			data)
+ * @startup_time:	startup time of the ADC in microseconds
+ */
+struct at91_adc_desc {
+	u32			clock;
+	char			*clock_name;
+	u8			num_channels;
+	u8			startup_time;
+};
+
+struct at91_adc_state {
+	unsigned long		channels_mask;
+	struct clk		*clk;
+	bool			done;
+	struct at91_adc_desc	*desc;
+	int			irq;
+	u16			last_value;
+	struct mutex		lock;
Quoted 8 lines

drivers/staging/iio/adc/at91_adc.c line 60

Quoted 7 lines
drivers/staging/iio/adc/at91_adc.c new file +7 -0
+	void __iomem		*reg_base;
+	u32			vref_mv;
+	wait_queue_head_t	wq_data_avail;
+};
+
+static struct at91_adc_desc at91_adc_desc_sam9g20 = {
+	.clock = 5000000,

why 5Mhz?

This is the value given by the datasheet of the G20 SoC.

Quoted 6 lines

drivers/staging/iio/adc/at91_adc.c line 65

Quoted 5 lines
drivers/staging/iio/adc/at91_adc.c new file +5 -0
+	.clock_name = "adc_clk",
+	.num_channels = 4,
+	.startup_time = 10,
+};
+

this is soc specific nedd to be in the soc not in the driver

Some time ago, Nicolas Ferre asked me to move the SoC specific part to the driver, mostly because of two things:
* *_devices.c files were suppose to disappear with the DT
* Triggers are not all supported by the driver, so only the driver
knows which triggers it can expose (pen-down or periodic triggers for the G45 are not supported for example). This can't be done through the SoC files.

Quoted 79 lines

drivers/staging/iio/adc/at91_adc.c line 74

Quoted 9 lines
drivers/staging/iio/adc/at91_adc.c new file +9 -0
+static int at91_adc_select_soc(struct at91_adc_state *st)
+{
+	if (cpu_is_at91sam9g20()) {
+		st->desc = &at91_adc_desc_sam9g20;
+		return 0;
+	}
+
+	return -ENODEV;
+}

ditto

Quoted 69 lines
drivers/staging/iio/adc/at91_adc.c new file +68 -0
+
 
+
+static int __devinit at91_adc_probe(struct platform_device *pdev)
+{
+	unsigned int prsc, mstrclk, ticks;
+	int ret;
+	struct iio_dev *idev;
+	struct at91_adc_state *st;
+	struct resource *res;
+	struct at91_adc_data *pdata = pdev->dev.platform_data;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		dev_err(&pdev->dev, "No resource defined\n");
+		ret = -ENXIO;
+		goto error_ret;
+	}
+
+	idev = iio_allocate_device(sizeof(struct at91_adc_state));
+	if (idev == NULL) {
+		ret = -ENOMEM;
+		goto error_ret;
+	}
+
+	platform_set_drvdata(pdev, idev);
+
+	idev->dev.parent = &pdev->dev;
+	idev->name = dev_name(&pdev->dev);
+	idev->modes = INDIO_DIRECT_MODE;
+	idev->info = &at91_adc_info;
+
+	st = iio_priv(idev);
+	ret = at91_adc_select_soc(st);
+	if (ret) {
+		dev_err(&pdev->dev, "SoC unknown\n");
+		goto error_free_device;
+	}
+
+	st->irq = platform_get_irq(pdev, 0);
+	if (st->irq < 0) {
+		dev_err(&pdev->dev, "No IRQ ID is designated\n");
+		ret = -ENODEV;
+		goto error_free_device;
+	}
+
+	if (!request_mem_region(res->start, resource_size(res),
+				"AT91 adc registers")) {
+		dev_err(&pdev->dev, "Resources are unavailable.\n");
+		ret = -EBUSY;
+		goto error_free_device;
+	}
+
+	st->reg_base = ioremap(res->start, resource_size(res));
+	if (!st->reg_base) {
+		dev_err(&pdev->dev, "Failed to map registers.\n");
+		ret = -ENOMEM;
+		goto error_release_mem;
+	}
+
+	/*
+	 * Disable all IRQs before setting up the handler
+	 */
+	at91_adc_reg_write(st, AT91_ADC_CR, AT91_ADC_SWRST);
+	at91_adc_reg_write(st, AT91_ADC_IDR, 0xFFFFFFFF);
+	ret = request_irq(st->irq,
+			  at91_adc_eoc_trigger,
+			  0,
+			  pdev->dev.driver->name,
Quoted 8 lines

drivers/staging/iio/adc/at91_adc.c line 268

Quoted 7 lines
drivers/staging/iio/adc/at91_adc.c new file +7 -0
+			  idev);
+	if (ret) {
+		dev_err(&pdev->dev, "Failed to allocate IRQ.\n");
+		goto error_unmap_reg;
+	}
+
+	st->clk = clk_get(&pdev->dev, st->desc->clock_name);

use a fixed clock name

I can't. The clock name is "adc_clk" for the G20, "tsc_clk" for the G45.

Quoted 7 lines

drivers/staging/iio/adc/at91_adc.c line 274

Quoted 6 lines
drivers/staging/iio/adc/at91_adc.c new file +6 -0
+	if (IS_ERR(st->clk)) {
+		dev_err(&pdev->dev, "Failed to get the clock.\n");
+		ret = PTR_ERR(st->clk);
+		goto error_free_irq;
+	}
+

use clk_prepare & co

Ok, I will look into this.

Quoted 9 lines

drivers/staging/iio/adc/at91_adc.c line 282

Quoted 8 lines
drivers/staging/iio/adc/at91_adc.c new file +8 -0
+	clk_enable(st->clk);
+	mstrclk = clk_get_rate(st->clk);
+
+	if (!pdata) {
+		dev_err(&pdev->dev, "No platform data available.\n");
+		ret = -EINVAL;
+		goto error_free_clk;
+	}

need to be check first

Ok

Thanks,
Maxime

Signature · 4 lines
Maxime Ripard, Free Electrons
Kernel, drivers, real-time and embedded Linux
development, consulting, training and support.
http://free-electrons.com
#6 lore raw

PATCH 3/5 ARM: AT91: Add the ADC to the sam9g20ek board

In reply to Maxime Ripard

This patch adds platform data for the AT91 ADC driver support for the AT91SAM9G20-EK board.

Cc Nicolas Ferre <[email protected]>
Cc Patrice Vilchez <[email protected]>
Cc Thomas Petazzoni <[email protected]>
Cc Jean-Christophe PLAGNIOL-VILLARD <[email protected]>
---
 arch/arm/mach-at91/at91sam9260_devices.c |   53 ++++++++++++++++++++++++++++++
 arch/arm/mach-at91/board-sam9g20ek.c     |   13 +++++++
 2 files changed, 66 insertions(+), 0 deletions(-)
arch/arm/mach-at91/at91sam9260_devices.c +53 -0
index 7e5651e..08464fe 100644
@@ -17,6 +17,8 @@
 #include <linux/platform_device.h>
 #include <linux/i2c-gpio.h>
 
+#include <linux/platform_data/at91_adc.h>
+
 #include <mach/board.h>
 #include <mach/cpu.h>
 #include <mach/at91sam9260.h>
@@ -1366,6 +1368,57 @@ void __init at91_add_device_cf(struct at91_cf_data *data)
 void __init at91_add_device_cf(struct at91_cf_data * data) {}
 #endif
 
+/* --------------------------------------------------------------------
+ *  ADCs
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_AT91_ADC) || defined(CONFIG_AT91_ADC_MODULE)
+static struct at91_adc_data adc_data;
+
+static struct resource adc_resources[] = {
+	[0] = {
+		.start	= AT91SAM9260_BASE_ADC,
+		.end	= AT91SAM9260_BASE_ADC + SZ_16K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= AT91SAM9260_ID_ADC,
+		.end	= AT91SAM9260_ID_ADC,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device at91_adc_device = {
+	.name		= "at91_adc",
+	.id		= -1,
+	.dev		= {
+				.platform_data		= &adc_data,
+	},
+	.resource	= adc_resources,
+	.num_resources	= ARRAY_SIZE(adc_resources),
+};
+
+void __init at91_add_device_adc(struct at91_adc_data *data)
+{
+	if (!data)
+		return;
+
+	if (test_bit(0, &data->channels_used))
+		at91_set_A_periph(AT91_PIN_PC0, 0);
+	if (test_bit(1, &data->channels_used))
+		at91_set_A_periph(AT91_PIN_PC1, 0);
+	if (test_bit(2, &data->channels_used))
+		at91_set_A_periph(AT91_PIN_PC2, 0);
+	if (test_bit(3, &data->channels_used))
+		at91_set_A_periph(AT91_PIN_PC3, 0);
+
+	adc_data = *data;
+	platform_device_register(&at91_adc_device);
+}
+#else
+void __init at91_add_device_adc(struct at91_adc_data *data) {}
+#endif
+
 /* -------------------------------------------------------------------- */
 /*
  * These devices are always present and don't need any board-specific
arch/arm/mach-at91/board-sam9g20ek.c +13 -0
index 8923ec9..2ce4e26 100644
@@ -32,6 +32,8 @@
 #include <linux/regulator/fixed.h>
 #include <linux/regulator/consumer.h>
 
+#include <linux/platform_data/at91_adc.h>
+
 #include <mach/hardware.h>
 #include <asm/setup.h>
 #include <asm/mach-types.h>
@@ -318,6 +320,15 @@ static void __init ek_add_device_buttons(void)
 static void __init ek_add_device_buttons(void) {}
 #endif
 
+/*
+ * ADCs
+ */
+
+static struct at91_adc_data ek_adc_data = {
+	.channels_used = BIT(0) | BIT(1) | BIT(2) | BIT(3),
+	.vref = 3300,
+};
+
 #if defined(CONFIG_REGULATOR_FIXED_VOLTAGE) || defined(CONFIG_REGULATOR_FIXED_VOLTAGE_MODULE)
 static struct regulator_consumer_supply ek_audio_consumer_supplies[] = {
 	REGULATOR_SUPPLY("AVDD", "0-001b"),
@@ -393,6 +404,8 @@ static void __init ek_board_init(void)
 	ek_add_device_gpio_leds();
 	/* Push Buttons */
 	ek_add_device_buttons();
+	/* ADCs */
+	at91_add_device_adc(&ek_adc_data);
 	/* PCK0 provides MCLK to the WM8731 */
 	at91_set_B_periph(AT91_PIN_PC1, 0);
 	/* SSC (for WM8731) */
Signature · 1 line
1.7.5.4
#8 lore raw

PATCH 3/5 ARM: AT91: Add the ADC to the sam9g20ek board

Le 07/04/2012 05:29, Jean-Christophe PLAGNIOL-VILLARD a ?crit :

Quoted 6 lines · Maxime Ripard
Quoted 4 lines

This patch adds platform data for the AT91 ADC driver support for the AT91SAM9G20-EK board.

Do you have a plan for DT?

My plan was to take a look at it while adding support for the X25 and X35, presumably this week or next week.

I admit I have not looked much into it for now.

Maxime

Signature · 4 lines
Maxime Ripard, Free Electrons
Kernel, drivers, real-time and embedded Linux
development, consulting, training and support.
http://free-electrons.com
#9 lore raw

PATCH 4/5 IIO: AT91: ADC: Add support for the AT91SAM9M10G45-EK board

In reply to Maxime Ripard

This patch adds the necessary logic and the required platform_data to support the ADC present in the AT91SAM9M10G45-EK board from Atmel. It only supports software triggers for now.

Cc Jean-Christophe PLAGNIOL-VILLARD <[email protected]>
Cc Patrice Vilchez <[email protected]>
Cc Thomas Petazzoni <[email protected]>
Cc Nicolas Ferre <[email protected]>
---
 arch/arm/mach-at91/at91sam9g45_devices.c |   61 ++++++++++++++++++++++++++++++
 arch/arm/mach-at91/board-sam9m10g45ek.c  |   11 +++++
 drivers/staging/iio/adc/at91_adc.c       |   12 ++++++
 3 files changed, 84 insertions(+), 0 deletions(-)
arch/arm/mach-at91/at91sam9g45_devices.c +61 -0
index 698479f..7827139 100644
@@ -19,6 +19,8 @@
 #include <linux/i2c-gpio.h>
 #include <linux/atmel-mci.h>
 
+#include <linux/platform_data/at91_adc.h>
+
 #include <linux/fb.h>
 #include <video/atmel_lcdc.h>
 
@@ -1202,6 +1204,65 @@ void __init at91_add_device_tsadcc(struct at91_tsadcc_data *data) {}
 
 
 /* --------------------------------------------------------------------
+ *  ADC
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_AT91_ADC) || defined(CONFIG_AT91_ADC_MODULE)
+static struct at91_adc_data adc_data;
+
+static struct resource adc_resources[] = {
+	[0] = {
+		.start	= AT91SAM9G45_BASE_TSC,
+		.end	= AT91SAM9G45_BASE_TSC + SZ_16K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= AT91SAM9G45_ID_TSC,
+		.end	= AT91SAM9G45_ID_TSC,
+		.flags	= IORESOURCE_IRQ,
+	}
+};
+
+static struct platform_device at91_adc_device = {
+	.name		= "at91_adc",
+	.id		= -1,
+	.dev		= {
+				.platform_data	= &adc_data,
+	},
+	.resource	= adc_resources,
+	.num_resources	= ARRAY_SIZE(adc_resources),
+};
+
+void __init at91_add_device_adc(struct at91_adc_data *data)
+{
+	if (!data)
+		return;
+
+	if (test_bit(0, &data->channels_used))
+		at91_set_gpio_input(AT91_PIN_PD20, 0);
+	if (test_bit(1, &data->channels_used))
+		at91_set_gpio_input(AT91_PIN_PD21, 0);
+	if (test_bit(2, &data->channels_used))
+		at91_set_gpio_input(AT91_PIN_PD22, 0);
+	if (test_bit(3, &data->channels_used))
+		at91_set_gpio_input(AT91_PIN_PD23, 0);
+	if (test_bit(4, &data->channels_used))
+		at91_set_gpio_input(AT91_PIN_PD24, 0);
+	if (test_bit(5, &data->channels_used))
+		at91_set_gpio_input(AT91_PIN_PD25, 0);
+	if (test_bit(6, &data->channels_used))
+		at91_set_gpio_input(AT91_PIN_PD26, 0);
+	if (test_bit(7, &data->channels_used))
+		at91_set_gpio_input(AT91_PIN_PD27, 0);
+
+	adc_data = *data;
+	platform_device_register(&at91_adc_device);
+}
+#else
+void __init at91_add_device_adc(struct at91_adc_data *data) {}
+#endif
+
+/* --------------------------------------------------------------------
  *  RTT
  * -------------------------------------------------------------------- */
 
arch/arm/mach-at91/board-sam9m10g45ek.c +11 -0
index e1bea73..dca46c8 100644
@@ -27,6 +27,8 @@
 #include <linux/atmel-mci.h>
 #include <linux/delay.h>
 
+#include <linux/platform_data/at91_adc.h>
+
 #include <mach/hardware.h>
 #include <video/atmel_lcdc.h>
 #include <media/soc_camera.h>
@@ -314,6 +316,13 @@ static struct at91_tsadcc_data ek_tsadcc_data = {
 	.ts_sample_hold_time	= 0x0a,
 };
 
+/*
+ * ADCs
+ */
+static struct at91_adc_data ek_adc_data = {
+	.channels_used = BIT(0) | BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5) | BIT(6) | BIT(7),
+	.vref = 3300,
+};
 
 /*
  * GPIO Buttons
@@ -479,6 +488,8 @@ static void __init ek_board_init(void)
 	at91_add_device_lcdc(&ek_lcdc_data);
 	/* Touch Screen */
 	at91_add_device_tsadcc(&ek_tsadcc_data);
+	/* ADC */
+	at91_add_device_adc(&ek_adc_data);
 	/* Push Buttons */
 	ek_add_device_buttons();
 	/* AC97 */
drivers/staging/iio/adc/at91_adc.c +12 -0
index c76516a..04bac43 100644
@@ -56,6 +56,13 @@ struct at91_adc_state {
 	wait_queue_head_t	wq_data_avail;
 };
 
+static struct at91_adc_desc at91_adc_desc_sam9g45 = {
+	.clock = 13200000,
+	.clock_name = "tsc_clk",
+	.num_channels = 8,
+	.startup_time = 40,
+};
+
 static struct at91_adc_desc at91_adc_desc_sam9g20 = {
 	.clock = 5000000,
 	.clock_name = "adc_clk",
@@ -70,6 +77,11 @@ static int at91_adc_select_soc(struct at91_adc_state *st)
 		return 0;
 	}
 
+	if (cpu_is_at91sam9g45()) {
+		st->desc = &at91_adc_desc_sam9g45;
+		return 0;
+	}
+
 	return -ENODEV;
 }
 
Signature · 1 line
1.7.5.4
#10 lore raw

PATCH 4/5 IIO: AT91: ADC: Add support for the AT91SAM9M10G45-EK board

Quoted 56 lines
arch/arm/mach-at91/board-sam9m10g45ek.c +11 -0
index e1bea73..dca46c8 100644
@@ -27,6 +27,8 @@
 #include <linux/atmel-mci.h>
 #include <linux/delay.h>
 
+#include <linux/platform_data/at91_adc.h>
+
 #include <mach/hardware.h>
 #include <video/atmel_lcdc.h>
 #include <media/soc_camera.h>
@@ -314,6 +316,13 @@ static struct at91_tsadcc_data ek_tsadcc_data = {
 	.ts_sample_hold_time	= 0x0a,
 };
 
+/*
+ * ADCs
+ */
+static struct at91_adc_data ek_adc_data = {
+	.channels_used = BIT(0) | BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5) | BIT(6) | BIT(7),
+	.vref = 3300,
+};
 
 /*
  * GPIO Buttons
@@ -479,6 +488,8 @@ static void __init ek_board_init(void)
 	at91_add_device_lcdc(&ek_lcdc_data);
 	/* Touch Screen */
 	at91_add_device_tsadcc(&ek_tsadcc_data);
+	/* ADC */
+	at91_add_device_adc(&ek_adc_data);
 	/* Push Buttons */
 	ek_add_device_buttons();
 	/* AC97 */
drivers/staging/iio/adc/at91_adc.c +7 -0
index c76516a..04bac43 100644
@@ -56,6 +56,13 @@ struct at91_adc_state {
 	wait_queue_head_t	wq_data_avail;
 };
 
+static struct at91_adc_desc at91_adc_desc_sam9g45 = {
+	.clock = 13200000,
+	.clock_name = "tsc_clk",
+	.num_channels = 8,
+	.startup_time = 40,
+};
+
 static struct at91_adc_desc at91_adc_desc_sam9g20 = {
 	.clock = 5000000,
 	.clock_name = "adc_clk",
@@ -70,6 +77,11 @@ static int at91_adc_select_soc(struct at91_adc_state *st)
 		return 0;

drivers/staging/iio/adc/at91_adc.c static int at91_adc_select_soc(struct at91_adc_state *st) · line 87

Quoted 10 lines
drivers/staging/iio/adc/at91_adc.c +5 -0
 	}
 
+	if (cpu_is_at91sam9g45()) {
+		st->desc = &at91_adc_desc_sam9g45;
+		return 0;
+	}
+
 	return -ENODEV;
 }
 

soc specific

Best Regards,
J.

#11 lore raw

PATCH 5/5 IIO: AT91: Add support for hardware triggers for the ADC

In reply to Maxime Ripard

This patch adds support for the hardware triggers for both the AT91SAM9G20-EK and AT91SAM9M10G45-EK evaluation board from Atmel.

Cc Jean-Christophe PLAGNIOL-VILLARD <[email protected]>
Cc Patrice Vilchez <[email protected]>
Cc Thomas Petazzoni <[email protected]>
Cc Nicolas Ferre <[email protected]>
---
 arch/arm/mach-at91/at91sam9260_devices.c |    3 +
 arch/arm/mach-at91/at91sam9g45_devices.c |    3 +
 arch/arm/mach-at91/board-sam9g20ek.c     |    1 +
 arch/arm/mach-at91/board-sam9m10g45ek.c  |    1 +
 drivers/staging/iio/adc/Kconfig          |    3 +
 drivers/staging/iio/adc/at91_adc.c       |  390 +++++++++++++++++++++++++++++-
 include/linux/platform_data/at91_adc.h   |    2 +
 7 files changed, 396 insertions(+), 7 deletions(-)
arch/arm/mach-at91/at91sam9260_devices.c +3 -0
index 08464fe..66df43a 100644
@@ -1412,6 +1412,9 @@ void __init at91_add_device_adc(struct at91_adc_data *data)
 	if (test_bit(3, &data->channels_used))
 		at91_set_A_periph(AT91_PIN_PC3, 0);
 
+	if (data->use_external)
+		at91_set_A_periph(AT91_PIN_PA22, 0);
+
 	adc_data = *data;
 	platform_device_register(&at91_adc_device);
 }
arch/arm/mach-at91/at91sam9g45_devices.c +3 -0
index 7827139..13ac3932 100644
@@ -1255,6 +1255,9 @@ void __init at91_add_device_adc(struct at91_adc_data *data)
 	if (test_bit(7, &data->channels_used))
 		at91_set_gpio_input(AT91_PIN_PD27, 0);
 
+	if (data->use_external)
+		at91_set_A_periph(AT91_PIN_PD28, 0);
+
 	adc_data = *data;
 	platform_device_register(&at91_adc_device);
 }
arch/arm/mach-at91/board-sam9g20ek.c +1 -0
index 2ce4e26..3bb6e4d 100644
@@ -326,6 +326,7 @@ static void __init ek_add_device_buttons(void) {}
 
 static struct at91_adc_data ek_adc_data = {
 	.channels_used = BIT(0) | BIT(1) | BIT(2) | BIT(3),
+	.use_external = true,
 	.vref = 3300,
 };
 
arch/arm/mach-at91/board-sam9m10g45ek.c +1 -0
index dca46c8..9a89afc 100644
@@ -321,6 +321,7 @@ static struct at91_tsadcc_data ek_tsadcc_data = {
  */
 static struct at91_adc_data ek_adc_data = {
 	.channels_used = BIT(0) | BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5) | BIT(6) | BIT(7),
+	.use_external = true,
 	.vref = 3300,
 };
 
drivers/staging/iio/adc/Kconfig +3 -0
index 1494838..9ee7ed9 100644
@@ -172,6 +172,9 @@ config AD7280
 config AT91_ADC
 	tristate "Atmel AT91 ADC"
 	depends on SYSFS && ARCH_AT91
+	select IIO_BUFFER
+	select IIO_SW_RING
+	select IIO_TRIGGER
 	help
 	  Say yes here to build support for Atmel AT91 ADC.
 
drivers/staging/iio/adc/at91_adc.c +383 -7

495 lines not on this page · raw message

include/linux/platform_data/at91_adc.h +2 -0
index 1f71510..5e063b3 100644
@@ -11,10 +11,12 @@
 /**
  * struct at91_adc_data - platform data for ADC driver
  * @channels_used:	channels in use on the board as a bitmask
+ * @use_external:	does the board has external triggers availables
  * @vref:		Reference voltage for the ADC in millivolts
  */
 struct at91_adc_data {
 	unsigned long	channels_used;
+	bool		use_external;
 	u16		vref;
 };
 
Signature · 1 line
1.7.5.4
#12 lore raw

PATCH 5/5 IIO: AT91: Add support for hardware triggers for the ADC

Quoted 64 lines
drivers/staging/iio/adc/at91_adc.c +54 -0
+static struct at91_adc_trigger at91_adc_trigger_sam9g45[] = {
+	[0] = {
+		.name = "external-rising",
+		.value = AT91_TSADCC_TRGMOD_EXT_RISING,
+		.is_external = true,
+	},
+	[1] = {
+		.name = "external-falling",
+		.value = AT91_TSADCC_TRGMOD_EXT_FALLING,
+		.is_external = true,
+	},
+	[2] = {
+		.name = "external-any",
+		.value = AT91_TSADCC_TRGMOD_EXT_ANY,
+		.is_external = true,
+	},
+	[3] = {
+		.name = "continuous",
+		.value = AT91_TSADCC_TRGMOD_CONTINUOUS,
+		.is_external = false,
+	},
+	[4] = {
+		.name = NULL,
+	},
+};
+
 static struct at91_adc_desc at91_adc_desc_sam9g45 = {
 	.clock = 13200000,
 	.clock_name = "tsc_clk",
 	.num_channels = 8,
 	.startup_time = 40,
+	.triggers = at91_adc_trigger_sam9g45,
+	.trigger_register = AT91_TSADCC_TRGR,
+};
+
+static struct at91_adc_trigger at91_adc_trigger_sam9g20[] = {
+	[0] = {
+		.name = "timer-counter-0",
+		.value = AT91_ADC_TRGSEL_TC0 | AT91_ADC_TRGEN,
+		.is_external = false,
+	},
+	[1] = {
+		.name = "timer-counter-1",
+		.value = AT91_ADC_TRGSEL_TC1 | AT91_ADC_TRGEN,
+		.is_external = false,
+	},
+	[2] = {
+		.name = "timer-counter-2",
+		.value = AT91_ADC_TRGSEL_TC2 | AT91_ADC_TRGEN,
+		.is_external = false,
+	},
+	[3] = {
+		.name = "external",
+		.value = AT91_ADC_TRGSEL_EXTERNAL | AT91_ADC_TRGEN,
+		.is_external = true,
+	},
+	[4] = {
+		.name = NULL,
+	},
 };
 
 static struct at91_adc_desc at91_adc_desc_sam9g20 = {

drivers/staging/iio/adc/at91_adc.c static struct at91_adc_desc at91_adc_desc_sam9g20 = { · line 158

Quoted 6 lines
drivers/staging/iio/adc/at91_adc.c +2 -0
@@ -68,6 +153,8 @@ static struct at91_adc_desc at91_adc_desc_sam9g20 = {
 	.clock_name = "adc_clk",
 	.num_channels = 4,
 	.startup_time = 10,
+	.triggers = at91_adc_trigger_sam9g20,
+	.trigger_register = AT91_ADC_MR,
 };

same comment as before this soc specific

Best Regards,
J.

drivers/staging/iio/adc/at91_adc.c static int at91_adc_channel_init(struct iio_dev *idev, · line 263

Quoted 11 lines
drivers/staging/iio/adc/at91_adc.c +3 -2
@@ -125,8 +257,9 @@ static int at91_adc_channel_init(struct iio_dev *idev,
 	int bit, idx = 0;
 
 	idev->num_channels = bitmap_weight(&pdata->channels_used,
-					   st->desc->num_channels);
-	chan_array = kcalloc(idev->num_channels, sizeof(struct iio_chan_spec),
+					   st->desc->num_channels) + 1;
+	chan_array = kcalloc(idev->num_channels + 1,
+			     sizeof(struct iio_chan_spec),
 			     GFP_KERNEL);

devm_kzalloc

drivers/staging/iio/adc/at91_adc.c static int at91_adc_channel_init(struct iio_dev *idev, · line 279

Quoted 13 lines
drivers/staging/iio/adc/at91_adc.c +1 -0
 	if (chan_array == NULL)
@@ -137,6 +270,7 @@ static int at91_adc_channel_init(struct iio_dev *idev,
 		chan->type = IIO_VOLTAGE;
 		chan->indexed = 1;
 		chan->channel = bit;
+		chan->scan_index = idx;
 		chan->scan_type.sign = 'u';
 		chan->scan_type.realbits = 10;
 		chan->scan_type.storagebits = 16;
@@ -144,6 +278,13 @@ static int at91_adc_channel_init(struct iio_dev *idev,
 		idx++;
 	}

Best Regards,
J.