AT91: Add a driver for the ADC
Subsystems (4)
PATCH v6 1/1 AT91: Add a driver for the ADC
Hi all,
This patchset adds the driver for the ADC in the AT91 SoC. It has been tested on the at91sam9g20ek and should work on sam9g45 as well.
For now, it only reads values when asked for by sysfs, but eventually will support hardware triggers and more boards.
This patchset is based on the "[PATCH 0/6 V2] IIO: Out of staging step 1: The core" patchset from Jonathan Cameron, applied on top of 3.1
Improvements from v5:
- Don't run the SoC specific code if the driver is not selected in the
configuration
- Fix the waitqueue timeout error handling to have a more sensible behaviour
- Minor cosmetic improvements
PATCH 1/3 ARM: AT91: Add platform data for the ADCs
--- arch/arm/mach-at91/include/mach/board.h | 18 ++++++++++++++++++ 1 files changed, 18 insertions(+), 0 deletions(-)
arch/arm/mach-at91/include/mach/board.h +18 -0
@@ -207,4 +207,22 @@ extern void __init at91_pwm_leds(struct gpio_led *leds, int nr);/* FIXME: this needs a better location, but gets stuff building again */ extern int at91_suspend_entering_slow_clock (void ); +/* ADC */ +struct at91_adc_data { +/* ADC Clock as specified by the datasheet, in Hz. */ +unsigned int adc_clock; +/* +* Global number of channels available (to specify which channels are +* indeed used on the board, see the channels_used bitmask). +*/ +u8 num_channels; +/* Channels in use on the board as a bitmask */ +unsigned long channels_used; +/* Startup time of the ADC, in microseconds. */ +u8 startup_time; +/* Reference voltage for the ADC in millivolts */ +unsigned short vref; +}; +extern void __init at91_add_device_adc (struct at91_adc_data *data); +#endif
Signature · 1 line
1.7.4.1
PATCH 2/3 ARM: AT91: IIO: Add AT91 ADC driver.
In reply to Maxime Ripard--- drivers/iio/adc/Kconfig | 6 + drivers/iio/adc/Makefile | 4 +- drivers/iio/adc/at91adc.c | 326 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 335 insertions(+), 1 deletions(-) create mode 100644 drivers/iio/adc/at91adc.c
drivers/iio/adc/Kconfig +6 -0
@@ -14,6 +14,12 @@ config IIO_AD799X i2c analog to digital convertors (ADC). Provides direct access via sysfs. +config IIO_AT91ADC + tristate "Atmel AT91 ADC" + depends on SYSFS && ARCH_AT91 + help + Say yes here to build support for Atmel AT91 ADC. + config IIO_MAX1363 tristate "Maxim max1363 ADC driver" depends on I2C
drivers/iio/adc/Makefile +3 -1
@@ -6,4 +6,6 @@ iio_ad799x-y := ad799x_core.o obj-$(CONFIG_IIO_AD799X) += iio_ad799x.o iio_max1363-y := max1363_core.o -obj-$(CONFIG_IIO_MAX1363) += iio_max1363.o +obj-$(CONFIG_IIO_MAX1363) += iio_max1363.o + +obj-$(CONFIG_IIO_AT91ADC) += at91adc.o
drivers/iio/adc/at91adc.c new file +326 -0
326 lines not on this page · raw message
Signature · 1 line
1.7.4.1
Jonathan Cameron
maintainerPATCH 2/3 ARM: AT91: IIO: Add AT91 ADC driver.
Quoted 4 lines · Maxime Ripard
Cc Nicolas Ferre <[email protected]>Cc Patrice Vilchez <[email protected]>Cc Jean-Christophe Plagniol-Villard <[email protected]>Cc Thomas Petazzoni <[email protected]>
Just one more query on the IIO_CHAN_INFO_SCALE read. Sorry, missed this last time. Its late so I may be going mad but the units seem out by 1000.
Also mysterious short as return value type in read_raw.
If I take this through my tree, I'll switch the ack below for a sign off.
Jonathan
Quoted 145 lines
Signed-off-by Maxime Ripard <[email protected]>Acked-by Jonathan Cameron <[email protected]>Acked-by Nicolas Ferre <[email protected]>Reviewed-by Marek Vasut <[email protected]>--- drivers/iio/adc/Kconfig | 6 + drivers/iio/adc/Makefile | 4 +- drivers/iio/adc/at91adc.c | 326 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 335 insertions(+), 1 deletions(-) create mode 100644 drivers/iio/adc/at91adc.cdrivers/iio/adc/Kconfig +6
-0@@ -14,6 +14,12 @@ config IIO_AD799X i2c analog to digital convertors (ADC). Provides direct access via sysfs. +config IIO_AT91ADC + tristate "Atmel AT91 ADC" + depends on SYSFS && ARCH_AT91 + help + Say yes here to build support for Atmel AT91 ADC. + config IIO_MAX1363 tristate "Maxim max1363 ADC driver" depends on I2Cdrivers/iio/adc/Makefile +3
-1@@ -6,4 +6,6 @@ iio_ad799x-y := ad799x_core.o obj-$(CONFIG_IIO_AD799X) += iio_ad799x.o iio_max1363-y := max1363_core.o -obj-$(CONFIG_IIO_MAX1363) += iio_max1363.o +obj-$(CONFIG_IIO_MAX1363) += iio_max1363.o + +obj-$(CONFIG_IIO_AT91ADC) += at91adc.odrivers/iio/adc/at91adc.c new file +97
-0@@ -0,0 +1,326 @@ +/* +* 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/slab.h> +#include <linux/wait.h> + +#include <linux/iio/iio.h> + +#include <mach/at91_adc.h> +#include <mach/board.h> + +struct at91adc_state { +struct clk *clk; +bool done; +struct mutex lock; +int irq; +wait_queue_head_t wq_data_avail; +u16 last_value; +void __iomem *reg_base; +unsigned int vref_mv; +}; + +static inline u32 at91adc_reg_read (struct at91adc_state *st,u8 reg) +{ +return readl_relaxed (st->reg_base + reg); +} + +static inline void at91adc_reg_write (struct at91adc_state *st,u8 reg,u32 val) +{ +writel_relaxed (val, st->reg_base + reg); +} + +static irqreturn_t at91adc_eoc_trigger (int irq,void *private) +{ +struct iio_dev *idev = private; +struct at91adc_state *st =iio_priv (idev); +unsigned int status =at91adc_reg_read (st,AT91_ADC_SR ); + +if (!(status &AT91_ADC_DRDY )) +return IRQ_HANDLED ; + +if (status & ((2 << idev->num_channels) -1 )) { + st->done = true; + st->last_value =at91adc_reg_read (st,AT91_ADC_LCDR ); + } + +wake_up_interruptible (&st->wq_data_avail); + +return IRQ_HANDLED ; +} + +static int at91adc_channel_init (struct iio_dev *idev, +struct at91_adc_data *pdata) +{ +struct iio_chan_spec *chan_array; +int bit, idx =0 ; + + idev->num_channels =bitmap_weight (&pdata->channels_used, + pdata->num_channels); + chan_array =kcalloc (idev->num_channels,sizeof (struct iio_chan_spec ), +GFP_KERNEL ); + +if (chan_array ==NULL ) +return -ENOMEM ; + +for_each_set_bit (bit, &pdata->channels_used, pdata->num_channels) { +struct iio_chan_spec *chan = chan_array + idx; + chan->type =IIO_VOLTAGE ; + chan->indexed =1 ; + chan->channel = bit; + chan->scan_type.sign ='u' ; + chan->scan_type.realbits =10 ; + chan->info_mask =IIO_CHAN_INFO_SCALE_SHARED_BIT ; + idx++; + } + + idev->channels = chan_array; +return idev->num_channels; +} + +static void at91adc_channel_remove (struct iio_dev *idev) +{
drivers/iio/adc/at91adc.c line 107
Quoted 10 lines
drivers/iio/adc/at91adc.c new file +10
-0+kfree (idev->channels); +} + +static int at91adc_read_raw (struct iio_dev *idev, +struct iio_chan_spec const *chan, +int *val,int *val2,long mask) +{ +struct at91adc_state *st =iio_priv (idev); +unsigned int scale_uv; +short ret;
Why not int?
Quoted 22 lines
drivers/iio/adc/at91adc.c new file +22
-0+ +switch (mask) { +case 0 : +mutex_lock (&st->lock); + +at91adc_reg_write (st,AT91_ADC_CHER , +AT91_ADC_CH (chan->channel)); +at91adc_reg_write (st,AT91_ADC_IER , +AT91_ADC_EOC (chan->channel)); +at91adc_reg_write (st,AT91_ADC_CR ,AT91_ADC_START ); + + ret =wait_event_interruptible_timeout (st->wq_data_avail, + st->done, +msecs_to_jiffies (1000 )); +if (ret ==0 ) +return -ETIMEDOUT ; +else if (ret <0 ) +return ret; + + *val = st->last_value; + + at91adc_reg_write(st, AT91_ADC_CHDR,
drivers/iio/adc/at91adc.c line 139
Quoted 10 lines
drivers/iio/adc/at91adc.c new file +10
-0+ AT91_ADC_CH(chan->channel)); +at91adc_reg_write (st,AT91_ADC_IDR , +AT91_ADC_EOC (chan->channel)); + + st->last_value =0 ; + st->done = false; +mutex_unlock (&st->lock); +return IIO_VAL_INT ; + +case IIO_CHAN_INFO_SCALE :
There is something a little missleading in the scaling here. If scale_uv is in microvolts as the name would suggest, then *val = scale_uv/1000000
and *val2 = (scale % 1000000);
To end up with the right units (I think). Please just check this over.
Quoted 187 lines
drivers/iio/adc/at91adc.c new file +187
-0+ scale_uv = (st->vref_mv *1000 ) >> chan->scan_type.realbits; + *val = scale_uv /1000 ; + *val2 = (scale_uv %1000 ) *1000 ; +return IIO_VAL_INT_PLUS_MICRO ; +default : +break ; + } +return -EINVAL ; +} + +static const struct iio_info at91adc_info = { + .driver_module =THIS_MODULE , + .read_raw = &at91adc_read_raw, +}; + +static int __devinit at91adc_probe (struct platform_device *pdev) +{ +unsigned int prsc, mstrclk, ticks; +int ret; +struct iio_dev *idev; +struct at91adc_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_device_allocate (sizeof (struct at91adc_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->info = &at91adc_info; + + st =iio_priv (idev); + 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 +*/ +at91adc_reg_write (st,AT91_ADC_CR ,AT91_ADC_SWRST ); +at91adc_reg_write (st,AT91_ADC_IDR ,0xFFFFFFFF ); + ret =request_irq (st->irq, + at91adc_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,"adc_clk" ); +if (IS_ERR (st->clk)) { +dev_err (&pdev->dev,"Failed to get the clock.\n" ); + ret =PTR_ERR (st->clk); + goto error_free_irq; + } + +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; + } + +if (!pdata->adc_clock) { +dev_err (&pdev->dev,"No ADCClock available.\n" ); + ret = -EINVAL ; + goto error_free_clk; + } + +/* +* Prescaler rate computation using the formula from the Atmel's +* datasheet : ADC Clock = MCK / ((Prescaler + 1) * 2), ADC Clock being +* specified by the electrical characteristics of the board. +*/ + prsc = (mstrclk / (2 * pdata->adc_clock)) -1 ; + +if (!pdata->startup_time) { +dev_err (&pdev->dev,"No startup time available.\n" ); + ret = -EINVAL ; + goto error_free_clk; + } + +/* +* Number of ticks needed to cover the startup time of the ADC as +* defined in the electrical characteristics of the board, divided by 8. +* The formula thus is : Startup Time = (ticks + 1) * 8 / ADC Clock +*/ + ticks =round_up ((pdata->startup_time * pdata->adc_clock / +1000000 ) -1 ,8 ) /8 ; +at91adc_reg_write (st,AT91_ADC_MR , + (AT91_ADC_PRESCAL_ (prsc) &AT91_ADC_PRESCAL ) | + (AT91_ADC_STARTUP_ (ticks) &AT91_ADC_STARTUP )); + +/* Setup the ADC channels available on the board */ + ret =at91adc_channel_init (idev, pdata); +if (ret <0 ) + goto error_free_clk; + +init_waitqueue_head (&st->wq_data_avail); +mutex_init (&st->lock); + + st->vref_mv = pdata->vref; + + ret =iio_device_register (idev); +if (ret <0 ) + goto error_free_channels; + +return 0 ; + +error_free_channels: +at91adc_channel_remove (idev); +error_free_clk: +clk_disable (st->clk); +clk_put (st->clk); +error_free_irq: +free_irq (st->irq, st); +error_unmap_reg: +iounmap (st->reg_base); +error_release_mem: +release_mem_region (res->start,resource_size (res)); +error_free_device: +iio_device_free (idev); +error_ret: +return ret; +} + +static int __devexit at91adc_remove(struct platform_device *pdev) +{ +struct iio_dev *idev =platform_get_drvdata (pdev); +struct resource *res =platform_get_resource (pdev,IORESOURCE_MEM ,0 ); +struct at91adc_state *st =iio_priv (idev); + +iio_device_unregister (idev); +at91adc_channel_remove (idev); +clk_disable (st->clk); +clk_put (st->clk); +free_irq (st->irq, idev); +iounmap (st->reg_base); +release_mem_region (res->start,resource_size (res)); +iio_device_free (idev); + +return 0 ; +} + +static struct platform_driver at91adc_driver = { + .probe = at91adc_probe, + .remove =__devexit_p (at91adc_remove), + .driver = { + .name ="at91adc" , + }, +}; + +module_platform_driver (at91adc_driver); + +MODULE_LICENSE ("GPL" ); +MODULE_DESCRIPTION ("Atmel AT91 ADC Driver" ); +MODULE_AUTHOR ("Maxime Ripard <[email protected]>" );
PATCH 2/3 ARM: AT91: IIO: Add AT91 ADC driver.
Quoted 3 lines · Jonathan Cameron
Just one more query on the
IIO_CHAN_INFO_SCALEread. Sorry, missed this last time. Its late so I may be going mad but the units seem out by 1000.
Wow, you're right. Indeed, if you multiply the value returned by read_raw and scale, you get a value in millivolts, not micro...
Quoted 1 line
Also mysterious short as return value type in
read_raw.
I will resend a new patchset with these two fixes.
Maxime
Signature · 4 lines
Maxime Ripard, Free Electrons Kernel, drivers, real-time and embedded Linux development, consulting, training and support. http://free-electrons.com
PATCH 3/3 ARM: AT91: Add the ADC to the sam9g20ek board
In reply to Maxime Ripard--- arch/arm/mach-at91/at91sam9260_devices.c | 55 ++++++++++++++++++++++++++++++ arch/arm/mach-at91/board-sam9g20ek.c | 11 ++++++ 2 files changed, 66 insertions(+), 0 deletions(-)
arch/arm/mach-at91/at91sam9260_devices.c +55 -0
@@ -1312,6 +1312,61 @@ 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_IIO_AT91ADC ) || defined(CONFIG_IIO_AT91ADC_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 ="at91adc" , + .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 ); + + data->adc_clock =5000000 ; + data->num_channels =4 ; + data->startup_time =10 ; + + 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 +11 -0
@@ -314,6 +314,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"),
@@ -389,6 +398,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.4.1
PATCH 3/3 ARM: AT91: Add the ADC to the sam9g20ek board
Quoted 4 lines · Maxime Ripard
Cc Nicolas Ferre <[email protected]>Cc Patrice Vilchez <[email protected]>Cc Thomas Petazzoni <[email protected]>
I'm happy with this, but the question comes of how to merge it with minimal conflicts. Clearly 2/3 is entirely in IIO so easy enough but is dependent on 1/3. 3/3 is entirely in the at91 maintainers domain but is also dependent on 1/3.
What do people what to do?
Quoted 79 lines
Signed-off-by Maxime Ripard <[email protected]>Signed-off-by Nicolas Ferre <[email protected]>--- arch/arm/mach-at91/at91sam9260_devices.c | 55 ++++++++++++++++++++++++++++++ arch/arm/mach-at91/board-sam9g20ek.c | 11 ++++++ 2 files changed, 66 insertions(+), 0 deletions(-)arch/arm/mach-at91/at91sam9260_devices.c +55
-0@@ -1312,6 +1312,61 @@ 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_IIO_AT91ADC ) || defined(CONFIG_IIO_AT91ADC_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 ="at91adc" , + .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 ); + + data->adc_clock =5000000 ; + data->num_channels =4 ; + data->startup_time =10 ; + + 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 +0
-0@@ -314,6 +314,15 @@ static void __init ek_add_device_buttons(void)static void __init ek_add_device_buttons (void ) {}
arch/arm/mach-at91/board-sam9g20ek.c static void __init ek_add_device_buttons(void) · line 324
Quoted 10 lines
arch/arm/mach-at91/board-sam9g20ek.c +8
-0#endif +/* +* ADCs +*/ + +static struct at91_adc_data ek_adc_data = { + .channels_used =BIT (0 ) |BIT (1 ) |BIT (2 ) |BIT (3 ), + .vref =3300 , +};
Feels like this should be marked as __initdata given it gets copied in the below function?
Quoted 13 lines
arch/arm/mach-at91/board-sam9g20ek.c +3
-0+#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"),@@ -389,6 +398,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) */
PATCH 3/3 ARM: AT91: Add the ADC to the sam9g20ek board
Quoted 11 lines · Jonathan Cameron
Quoted 4 lines · Maxime Ripard
Cc Nicolas Ferre <[email protected]>Cc Patrice Vilchez <[email protected]>Cc Thomas Petazzoni <[email protected]>I'm happy with this, but the question comes of how to merge it with minimal conflicts. Clearly 2/3 is entirely in IIO so easy enough but is dependent on 1/3. 3/3 is entirely in the at91 maintainers domain but is also dependent on 1/3.
What do people what to do?
It will surely be non trivial to merge. As you said, 2/3 and 3/3 depends on 1/3. But 2/3 also depends on the patchset to move out of staging the iio core you posted.
Quoted 105 lines
Quoted 79 lines
Signed-off-by Maxime Ripard <[email protected]>Signed-off-by Nicolas Ferre <[email protected]>--- arch/arm/mach-at91/at91sam9260_devices.c | 55 ++++++++++++++++++++++++++++++ arch/arm/mach-at91/board-sam9g20ek.c | 11 ++++++ 2 files changed, 66 insertions(+), 0 deletions(-)arch/arm/mach-at91/at91sam9260_devices.c +55
-0@@ -1312,6 +1312,61 @@ 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_IIO_AT91ADC ) || defined(CONFIG_IIO_AT91ADC_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 ="at91adc" , + .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 ); + + data->adc_clock =5000000 ; + data->num_channels =4 ; + data->startup_time =10 ; + + 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 +0
-0@@ -314,6 +314,15 @@ static void __init ek_add_device_buttons(void)static void __init ek_add_device_buttons (void ) {}arch/arm/mach-at91/board-sam9g20ek.c static void __init ek_add_device_buttons(void) · line 324
Quoted 10 lines
arch/arm/mach-at91/board-sam9g20ek.c +8
-0#endif +/* +* ADCs +*/ + +static struct at91_adc_data ek_adc_data = { + .channels_used =BIT (0 ) |BIT (1 ) |BIT (2 ) |BIT (3 ), + .vref =3300 , +};Feels like this should be marked as
__initdatagiven it gets copied in the below function?Quoted 13 lines
arch/arm/mach-at91/board-sam9g20ek.c +3
-0+#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"),@@ -389,6 +398,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 · 4 lines
Maxime Ripard, Free Electrons Kernel, drivers, real-time and embedded Linux development, consulting, training and support. http://free-electrons.com