[Armadeus-commitlog] armadeus branch, master, updated. armadeus-5.0-54-gf5cfcb8
Brought to you by:
sszy
|
From: Gwenhael Goavec-M. <gwe...@us...> - 2012-09-29 09:33:42
|
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "armadeus".
The branch, master has been updated
via f5cfcb8a60c12c42825c53c7c7ba5f45d3b10fe2 (commit)
via d96b8a2e2835171a988a29248f9e15849e29cdf7 (commit)
via dbfdfa33b1d20596b388470bfbe6491cbeec1092 (commit)
from 2e10489645e8b8e04f953ef6d140a0da2cf2b387 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit f5cfcb8a60c12c42825c53c7c7ba5f45d3b10fe2
Author: Gwenhael Goavec-Merou <gw...@tr...>
Date: Sat Sep 29 11:32:45 2012 +0200
[LINUX][3.6] apf28 config: Select IIO, staging and LRADC by default
commit d96b8a2e2835171a988a29248f9e15849e29cdf7
Author: Gwenhael Goavec-Merou <gw...@tr...>
Date: Sat Sep 29 11:31:59 2012 +0200
[LINUX][3.6] apf28-dev dts: Add support for LRADC
commit dbfdfa33b1d20596b388470bfbe6491cbeec1092
Author: Gwenhael Goavec-Merou <gw...@tr...>
Date: Sat Sep 29 11:31:20 2012 +0200
[LINUX][3.6] mx28: Backport patches for LRADC integration
-----------------------------------------------------------------------
Summary of changes:
.../device/armadeus/apf28/apf28-linux-3.6.config | 3 +
.../linux/3.6/0420-armadeus-Add-apf28dev-dts.patch | 18 +-
...tronix-mxs-IIO-Add_basic_MXS_LRADC_driver.patch | 678 ++++++++++++++++++++
...ts-Add_compatible_and_interrupt_for_LRADC.patch | 33 +
4 files changed, 725 insertions(+), 7 deletions(-)
create mode 100644 patches/linux/3.6/421-pengutronix-mxs-IIO-Add_basic_MXS_LRADC_driver.patch
create mode 100644 patches/linux/3.6/422-pengutronix-mx28-dts-Add_compatible_and_interrupt_for_LRADC.patch
diff --git a/buildroot/target/device/armadeus/apf28/apf28-linux-3.6.config b/buildroot/target/device/armadeus/apf28/apf28-linux-3.6.config
index 4e75dc9..edb8bee 100644
--- a/buildroot/target/device/armadeus/apf28/apf28-linux-3.6.config
+++ b/buildroot/target/device/armadeus/apf28/apf28-linux-3.6.config
@@ -150,6 +150,9 @@ CONFIG_RTC_CLASS=y
CONFIG_RTC_DRV_STMP=y
CONFIG_DMADEVICES=y
CONFIG_MXS_DMA=y
+CONFIG_STAGING=y
+CONFIG_MXS_LRADC=y
+CONFIG_IIO=y
CONFIG_PWM=y
CONFIG_PWM_MXS=y
CONFIG_EXT2_FS=y
diff --git a/patches/linux/3.6/0420-armadeus-Add-apf28dev-dts.patch b/patches/linux/3.6/0420-armadeus-Add-apf28dev-dts.patch
index 6da70f2..cbb8ddb 100644
--- a/patches/linux/3.6/0420-armadeus-Add-apf28dev-dts.patch
+++ b/patches/linux/3.6/0420-armadeus-Add-apf28dev-dts.patch
@@ -3,9 +3,9 @@ Signed-off-by: Julien Boibessot <jul...@ar...>
Index: linux-3.6-rc6/arch/arm/boot/dts/imx28-apf28dev.dts
===================================================================
---- /dev/null 1970-01-01 00:00:00.000000000 +0000
-+++ linux-3.6-rc6/arch/arm/boot/dts/imx28-apf28dev.dts 2012-09-25 21:23:27.000000000 +0200
-@@ -0,0 +1,165 @@
+--- /dev/null
++++ linux-3.6-rc6/arch/arm/boot/dts/imx28-apf28dev.dts
+@@ -0,0 +1,169 @@
+/*
+ * Copyright 2012 Armadeus Systems - <su...@ar...>
+ *
@@ -98,6 +98,10 @@ Index: linux-3.6-rc6/arch/arm/boot/dts/imx28-apf28dev.dts
+ };
+
+ apbx@80040000 {
++ lradc@80050000 {
++ status = "okay";
++ };
++
+ pwm: pwm@80064000 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pwm3_pins_a &pwm4_pins_a>;
@@ -173,9 +177,9 @@ Index: linux-3.6-rc6/arch/arm/boot/dts/imx28-apf28dev.dts
+};
Index: linux-3.6-rc6/arch/arm/mach-mxs/mach-mxs.c
===================================================================
---- linux-3.6-rc6.orig/arch/arm/mach-mxs/mach-mxs.c 2012-09-25 20:36:06.000000000 +0200
-+++ linux-3.6-rc6/arch/arm/mach-mxs/mach-mxs.c 2012-09-25 20:38:49.000000000 +0200
-@@ -97,6 +97,25 @@
+--- linux-3.6-rc6.orig/arch/arm/mach-mxs/mach-mxs.c
++++ linux-3.6-rc6/arch/arm/mach-mxs/mach-mxs.c
+@@ -97,6 +97,25 @@ static struct fb_videomode apx4devkit_vi
},
};
@@ -201,7 +205,7 @@ Index: linux-3.6-rc6/arch/arm/mach-mxs/mach-mxs.c
static struct mxsfb_platform_data mxsfb_pdata __initdata;
static struct of_dev_auxdata mxs_auxdata_lookup[] __initdata = {
-@@ -280,6 +299,12 @@
+@@ -280,6 +299,12 @@ static void __init apf28_init(void)
{
enable_clk_enet_out();
/*update_fec_mac_prop(OUI_ARMADEUS);TBDL*/
diff --git a/patches/linux/3.6/421-pengutronix-mxs-IIO-Add_basic_MXS_LRADC_driver.patch b/patches/linux/3.6/421-pengutronix-mxs-IIO-Add_basic_MXS_LRADC_driver.patch
new file mode 100644
index 0000000..84a25bb
--- /dev/null
+++ b/patches/linux/3.6/421-pengutronix-mxs-IIO-Add_basic_MXS_LRADC_driver.patch
@@ -0,0 +1,678 @@
+From bc2c90c974a0ed390327bbd94f49269e9f24e280 Mon Sep 17 00:00:00 2001
+From: Marek Vasut <ma...@de...>
+Date: Sun, 12 Aug 2012 16:21:00 +0100
+Subject: [PATCH] IIO: Add basic MXS LRADC driver
+
+This driver is very basic. It supports userland trigger, buffer and
+raw access to channels. The support for delay channels is missing
+altogether.
+
+Signed-off-by: Marek Vasut <ma...@de...>
+Signed-off-by: Jonathan Cameron <ji...@ke...>
+Cc: Jonathan Cameron <ji...@ke...>
+Cc: Juergen Beisert <jb...@pe...>
+Cc: Lars-Peter Clausen <la...@me...>
+Cc: Shawn Guo <sha...@li...>
+Cc: Wolfgang Denk <wd...@de...>
+---
+ .../bindings/staging/iio/adc/mxs-lradc.txt | 15 +
+ drivers/staging/iio/adc/Kconfig | 12 +
+ drivers/staging/iio/adc/Makefile | 1 +
+ drivers/staging/iio/adc/mxs-lradc.c | 590 ++++++++++++++++++++
+ 4 files changed, 618 insertions(+), 0 deletions(-)
+ create mode 100644 Documentation/devicetree/bindings/staging/iio/adc/mxs-lradc.txt
+ create mode 100644 drivers/staging/iio/adc/mxs-lradc.c
+
+diff --git a/Documentation/devicetree/bindings/staging/iio/adc/mxs-lradc.txt b/Documentation/devicetree/bindings/staging/iio/adc/mxs-lradc.txt
+new file mode 100644
+index 0000000..801d58c
+--- /dev/null
++++ b/Documentation/devicetree/bindings/staging/iio/adc/mxs-lradc.txt
+@@ -0,0 +1,15 @@
++* Freescale i.MX28 LRADC device driver
++
++Required properties:
++- compatible: Should be "fsl,imx28-lradc"
++- reg: Address and length of the register set for the device
++- interrupts: Should contain the LRADC interrupts
++
++Examples:
++
++ lradc@80050000 {
++ compatible = "fsl,imx28-lradc";
++ reg = <0x80050000 0x2000>;
++ interrupts = <10 14 15 16 17 18 19
++ 20 21 22 23 24 25>;
++ };
+diff --git a/drivers/staging/iio/adc/Kconfig b/drivers/staging/iio/adc/Kconfig
+index 67711b7..845fb6c 100644
+--- a/drivers/staging/iio/adc/Kconfig
++++ b/drivers/staging/iio/adc/Kconfig
+@@ -200,6 +200,18 @@ config LPC32XX_ADC
+ activate only one via device tree selection. Provides direct access
+ via sysfs.
+
++config MXS_LRADC
++ tristate "Freescale i.MX28 LRADC"
++ depends on ARCH_MXS
++ select IIO_BUFFER
++ select IIO_TRIGGERED_BUFFER
++ help
++ Say yes here to build support for i.MX28 LRADC convertor
++ built into these chips.
++
++ 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
+diff --git a/drivers/staging/iio/adc/Makefile b/drivers/staging/iio/adc/Makefile
+index 14e98b6..ecac9a0 100644
+--- a/drivers/staging/iio/adc/Makefile
++++ b/drivers/staging/iio/adc/Makefile
+@@ -38,4 +38,5 @@ obj-$(CONFIG_ADT7310) += adt7310.o
+ obj-$(CONFIG_ADT7410) += adt7410.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/mxs-lradc.c b/drivers/staging/iio/adc/mxs-lradc.c
+new file mode 100644
+index 0000000..ae549e5
+--- /dev/null
++++ b/drivers/staging/iio/adc/mxs-lradc.c
+@@ -0,0 +1,590 @@
++/*
++ * Freescale i.MX28 LRADC driver
++ *
++ * Copyright (c) 2012 DENX Software Engineering, GmbH.
++ * Marek Vasut <ma...@de...>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ */
++
++#include <linux/interrupt.h>
++#include <linux/device.h>
++#include <linux/kernel.h>
++#include <linux/slab.h>
++#include <linux/of.h>
++#include <linux/of_device.h>
++#include <linux/sysfs.h>
++#include <linux/list.h>
++#include <linux/io.h>
++#include <linux/module.h>
++#include <linux/platform_device.h>
++#include <linux/spinlock.h>
++#include <linux/wait.h>
++#include <linux/sched.h>
++#include <linux/stmp_device.h>
++#include <linux/bitops.h>
++#include <linux/completion.h>
++
++#include <mach/mxs.h>
++#include <mach/common.h>
++
++#include <linux/iio/iio.h>
++#include <linux/iio/buffer.h>
++#include <linux/iio/trigger.h>
++#include <linux/iio/trigger_consumer.h>
++#include <linux/iio/triggered_buffer.h>
++
++#define DRIVER_NAME "mxs-lradc"
++
++#define LRADC_MAX_DELAY_CHANS 4
++#define LRADC_MAX_MAPPED_CHANS 8
++#define LRADC_MAX_TOTAL_CHANS 16
++
++#define LRADC_DELAY_TIMER_HZ 2000
++
++/*
++ * Make this runtime configurable if necessary. Currently, if the buffered mode
++ * is enabled, the LRADC takes LRADC_DELAY_TIMER_LOOP samples of data before
++ * triggering IRQ. The sampling happens every (LRADC_DELAY_TIMER_PER / 2000)
++ * seconds. The result is that the samples arrive every 500mS.
++ */
++#define LRADC_DELAY_TIMER_PER 200
++#define LRADC_DELAY_TIMER_LOOP 5
++
++static const char * const mxs_lradc_irq_name[] = {
++ "mxs-lradc-touchscreen",
++ "mxs-lradc-thresh0",
++ "mxs-lradc-thresh1",
++ "mxs-lradc-channel0",
++ "mxs-lradc-channel1",
++ "mxs-lradc-channel2",
++ "mxs-lradc-channel3",
++ "mxs-lradc-channel4",
++ "mxs-lradc-channel5",
++ "mxs-lradc-channel6",
++ "mxs-lradc-channel7",
++ "mxs-lradc-button0",
++ "mxs-lradc-button1",
++};
++
++struct mxs_lradc_chan {
++ uint8_t slot;
++ uint8_t flags;
++};
++
++struct mxs_lradc {
++ struct device *dev;
++ void __iomem *base;
++ int irq[13];
++
++ uint32_t *buffer;
++ struct iio_trigger *trig;
++
++ struct mutex lock;
++
++ uint8_t enable;
++
++ struct completion completion;
++};
++
++#define LRADC_CTRL0 0x00
++#define LRADC_CTRL0_TOUCH_DETECT_ENABLE (1 << 23)
++#define LRADC_CTRL0_TOUCH_SCREEN_TYPE (1 << 22)
++
++#define LRADC_CTRL1 0x10
++#define LRADC_CTRL1_LRADC_IRQ(n) (1 << (n))
++#define LRADC_CTRL1_LRADC_IRQ_MASK 0x1fff
++#define LRADC_CTRL1_LRADC_IRQ_EN(n) (1 << ((n) + 16))
++#define LRADC_CTRL1_LRADC_IRQ_EN_MASK (0x1fff << 16)
++
++#define LRADC_CTRL2 0x20
++#define LRADC_CTRL2_TEMPSENSE_PWD (1 << 15)
++
++#define LRADC_CH(n) (0x50 + (0x10 * (n)))
++#define LRADC_CH_ACCUMULATE (1 << 29)
++#define LRADC_CH_NUM_SAMPLES_MASK (0x1f << 24)
++#define LRADC_CH_NUM_SAMPLES_OFFSET 24
++#define LRADC_CH_VALUE_MASK 0x3ffff
++#define LRADC_CH_VALUE_OFFSET 0
++
++#define LRADC_DELAY(n) (0xd0 + (0x10 * (n)))
++#define LRADC_DELAY_TRIGGER_LRADCS_MASK (0xff << 24)
++#define LRADC_DELAY_TRIGGER_LRADCS_OFFSET 24
++#define LRADC_DELAY_KICK (1 << 20)
++#define LRADC_DELAY_TRIGGER_DELAYS_MASK (0xf << 16)
++#define LRADC_DELAY_TRIGGER_DELAYS_OFFSET 16
++#define LRADC_DELAY_LOOP_COUNT_MASK (0x1f << 11)
++#define LRADC_DELAY_LOOP_COUNT_OFFSET 11
++#define LRADC_DELAY_DELAY_MASK 0x7ff
++#define LRADC_DELAY_DELAY_OFFSET 0
++
++#define LRADC_CTRL4 0x140
++#define LRADC_CTRL4_LRADCSELECT_MASK(n) (0xf << ((n) * 4))
++#define LRADC_CTRL4_LRADCSELECT_OFFSET(n) ((n) * 4)
++
++/*
++ * Raw I/O operations
++ */
++static int mxs_lradc_read_raw(struct iio_dev *iio_dev,
++ const struct iio_chan_spec *chan,
++ int *val, int *val2, long m)
++{
++ struct mxs_lradc *lradc = iio_priv(iio_dev);
++ int ret;
++
++ if (m != IIO_CHAN_INFO_RAW)
++ return -EINVAL;
++
++ /* Check for invalid channel */
++ if (chan->channel > LRADC_MAX_TOTAL_CHANS)
++ return -EINVAL;
++
++ /*
++ * See if there is no buffered operation in progess. If there is, simply
++ * bail out. This can be improved to support both buffered and raw IO at
++ * the same time, yet the code becomes horribly complicated. Therefore I
++ * applied KISS principle here.
++ */
++ ret = mutex_trylock(&lradc->lock);
++ if (!ret)
++ return -EBUSY;
++
++ INIT_COMPLETION(lradc->completion);
++
++ /*
++ * No buffered operation in progress, map the channel and trigger it.
++ * Virtual channel 0 is always used here as the others are always not
++ * used if doing raw sampling.
++ */
++ writel(LRADC_CTRL1_LRADC_IRQ_EN_MASK,
++ lradc->base + LRADC_CTRL1 + STMP_OFFSET_REG_CLR);
++ writel(0xff, lradc->base + LRADC_CTRL0 + STMP_OFFSET_REG_CLR);
++
++ writel(chan->channel, lradc->base + LRADC_CTRL4);
++ writel(0, lradc->base + LRADC_CH(0));
++
++ /* Enable the IRQ and start sampling the channel. */
++ writel(LRADC_CTRL1_LRADC_IRQ_EN(0),
++ lradc->base + LRADC_CTRL1 + STMP_OFFSET_REG_SET);
++ writel(1 << 0, lradc->base + LRADC_CTRL0 + STMP_OFFSET_REG_SET);
++
++ /* Wait for completion on the channel, 1 second max. */
++ ret = wait_for_completion_killable_timeout(&lradc->completion, HZ);
++ if (!ret)
++ ret = -ETIMEDOUT;
++ if (ret < 0)
++ goto err;
++
++ /* Read the data. */
++ *val = readl(lradc->base + LRADC_CH(0)) & LRADC_CH_VALUE_MASK;
++ ret = IIO_VAL_INT;
++
++err:
++ writel(LRADC_CTRL1_LRADC_IRQ_EN(0),
++ lradc->base + LRADC_CTRL1 + STMP_OFFSET_REG_CLR);
++
++ mutex_unlock(&lradc->lock);
++
++ return ret;
++}
++
++static const struct iio_info mxs_lradc_iio_info = {
++ .driver_module = THIS_MODULE,
++ .read_raw = mxs_lradc_read_raw,
++};
++
++/*
++ * IRQ Handling
++ */
++static irqreturn_t mxs_lradc_handle_irq(int irq, void *data)
++{
++ struct iio_dev *iio = data;
++ struct mxs_lradc *lradc = iio_priv(iio);
++ unsigned long reg = readl(lradc->base + LRADC_CTRL1);
++
++ if (!(reg & LRADC_CTRL1_LRADC_IRQ_MASK))
++ return IRQ_NONE;
++
++ /*
++ * Touchscreen IRQ handling code shall probably have priority
++ * and therefore shall be placed here.
++ */
++
++ if (iio_buffer_enabled(iio))
++ iio_trigger_poll(iio->trig, iio_get_time_ns());
++ else if (reg & LRADC_CTRL1_LRADC_IRQ(0))
++ complete(&lradc->completion);
++
++ writel(reg & LRADC_CTRL1_LRADC_IRQ_MASK,
++ lradc->base + LRADC_CTRL1 + STMP_OFFSET_REG_CLR);
++
++ return IRQ_HANDLED;
++}
++
++/*
++ * Trigger handling
++ */
++static irqreturn_t mxs_lradc_trigger_handler(int irq, void *p)
++{
++ struct iio_poll_func *pf = p;
++ struct iio_dev *iio = pf->indio_dev;
++ struct mxs_lradc *lradc = iio_priv(iio);
++ struct iio_buffer *buffer = iio->buffer;
++ const uint32_t chan_value = LRADC_CH_ACCUMULATE |
++ ((LRADC_DELAY_TIMER_LOOP - 1) << LRADC_CH_NUM_SAMPLES_OFFSET);
++ int i, j = 0;
++
++ for_each_set_bit(i, iio->active_scan_mask, iio->masklength) {
++ lradc->buffer[j] = readl(lradc->base + LRADC_CH(j));
++ writel(chan_value, lradc->base + LRADC_CH(j));
++ lradc->buffer[j] &= LRADC_CH_VALUE_MASK;
++ lradc->buffer[j] /= LRADC_DELAY_TIMER_LOOP;
++ j++;
++ }
++
++ if (iio->scan_timestamp) {
++ s64 *timestamp = (s64 *)((u8 *)lradc->buffer +
++ ALIGN(j, sizeof(s64)));
++ *timestamp = pf->timestamp;
++ }
++
++ iio_push_to_buffer(buffer, (u8 *)lradc->buffer, pf->timestamp);
++
++ iio_trigger_notify_done(iio->trig);
++
++ return IRQ_HANDLED;
++}
++
++static int mxs_lradc_configure_trigger(struct iio_trigger *trig, bool state)
++{
++ struct iio_dev *iio = trig->private_data;
++ struct mxs_lradc *lradc = iio_priv(iio);
++ const uint32_t st = state ? STMP_OFFSET_REG_SET : STMP_OFFSET_REG_CLR;
++
++ writel(LRADC_DELAY_KICK, lradc->base + LRADC_DELAY(0) + st);
++
++ return 0;
++}
++
++static const struct iio_trigger_ops mxs_lradc_trigger_ops = {
++ .owner = THIS_MODULE,
++ .set_trigger_state = &mxs_lradc_configure_trigger,
++};
++
++static int mxs_lradc_trigger_init(struct iio_dev *iio)
++{
++ int ret;
++ struct iio_trigger *trig;
++
++ trig = iio_trigger_alloc("%s-dev%i", iio->name, iio->id);
++ if (trig == NULL)
++ return -ENOMEM;
++
++ trig->dev.parent = iio->dev.parent;
++ trig->private_data = iio;
++ trig->ops = &mxs_lradc_trigger_ops;
++
++ ret = iio_trigger_register(trig);
++ if (ret) {
++ iio_trigger_free(trig);
++ return ret;
++ }
++
++ iio->trig = trig;
++
++ return 0;
++}
++
++static void mxs_lradc_trigger_remove(struct iio_dev *iio)
++{
++ iio_trigger_unregister(iio->trig);
++ iio_trigger_free(iio->trig);
++}
++
++static int mxs_lradc_buffer_preenable(struct iio_dev *iio)
++{
++ struct mxs_lradc *lradc = iio_priv(iio);
++ struct iio_buffer *buffer = iio->buffer;
++ int ret = 0, chan, ofs = 0, enable = 0;
++ uint32_t ctrl4 = 0;
++ uint32_t ctrl1_irq = 0;
++ const uint32_t chan_value = LRADC_CH_ACCUMULATE |
++ ((LRADC_DELAY_TIMER_LOOP - 1) << LRADC_CH_NUM_SAMPLES_OFFSET);
++ const int len = bitmap_weight(buffer->scan_mask, LRADC_MAX_TOTAL_CHANS);
++
++ if (!len)
++ return -EINVAL;
++
++ /*
++ * Lock the driver so raw access can not be done during buffered
++ * operation. This simplifies the code a lot.
++ */
++ ret = mutex_trylock(&lradc->lock);
++ if (!ret)
++ return -EBUSY;
++
++ lradc->buffer = kmalloc(len * sizeof(*lradc->buffer), GFP_KERNEL);
++ if (!lradc->buffer) {
++ ret = -ENOMEM;
++ goto err_mem;
++ }
++
++ ret = iio_sw_buffer_preenable(iio);
++ if (ret < 0)
++ goto err_buf;
++
++ writel(LRADC_CTRL1_LRADC_IRQ_EN_MASK,
++ lradc->base + LRADC_CTRL1 + STMP_OFFSET_REG_CLR);
++ writel(0xff, lradc->base + LRADC_CTRL0 + STMP_OFFSET_REG_CLR);
++
++ for_each_set_bit(chan, buffer->scan_mask, LRADC_MAX_TOTAL_CHANS) {
++ ctrl4 |= chan << LRADC_CTRL4_LRADCSELECT_OFFSET(ofs);
++ ctrl1_irq |= LRADC_CTRL1_LRADC_IRQ_EN(ofs);
++ writel(chan_value, lradc->base + LRADC_CH(ofs));
++ enable |= 1 << ofs;
++ ofs++;
++ };
++
++ writel(LRADC_DELAY_TRIGGER_LRADCS_MASK | LRADC_DELAY_KICK,
++ lradc->base + LRADC_DELAY(0) + STMP_OFFSET_REG_CLR);
++
++ writel(ctrl4, lradc->base + LRADC_CTRL4);
++ writel(ctrl1_irq, lradc->base + LRADC_CTRL1 + STMP_OFFSET_REG_SET);
++
++ writel(enable << LRADC_DELAY_TRIGGER_LRADCS_OFFSET,
++ lradc->base + LRADC_DELAY(0) + STMP_OFFSET_REG_SET);
++
++ return 0;
++
++err_buf:
++ kfree(lradc->buffer);
++err_mem:
++ mutex_unlock(&lradc->lock);
++ return ret;
++}
++
++static int mxs_lradc_buffer_postdisable(struct iio_dev *iio)
++{
++ struct mxs_lradc *lradc = iio_priv(iio);
++
++ writel(LRADC_DELAY_TRIGGER_LRADCS_MASK | LRADC_DELAY_KICK,
++ lradc->base + LRADC_DELAY(0) + STMP_OFFSET_REG_CLR);
++
++ writel(0xff, lradc->base + LRADC_CTRL0 + STMP_OFFSET_REG_CLR);
++ writel(LRADC_CTRL1_LRADC_IRQ_EN_MASK,
++ lradc->base + LRADC_CTRL1 + STMP_OFFSET_REG_CLR);
++
++ kfree(lradc->buffer);
++ mutex_unlock(&lradc->lock);
++
++ return 0;
++}
++
++static bool mxs_lradc_validate_scan_mask(struct iio_dev *iio,
++ const unsigned long *mask)
++{
++ const int mw = bitmap_weight(mask, iio->masklength);
++
++ return mw <= LRADC_MAX_MAPPED_CHANS;
++}
++
++static const struct iio_buffer_setup_ops mxs_lradc_buffer_ops = {
++ .preenable = &mxs_lradc_buffer_preenable,
++ .postenable = &iio_triggered_buffer_postenable,
++ .predisable = &iio_triggered_buffer_predisable,
++ .postdisable = &mxs_lradc_buffer_postdisable,
++ .validate_scan_mask = &mxs_lradc_validate_scan_mask,
++};
++
++/*
++ * Driver initialization
++ */
++
++#define MXS_ADC_CHAN(idx, chan_type) { \
++ .type = (chan_type), \
++ .indexed = 1, \
++ .scan_index = (idx), \
++ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT, \
++ .channel = (idx), \
++ .scan_type = { \
++ .sign = 'u', \
++ .realbits = 18, \
++ .storagebits = 32, \
++ }, \
++}
++
++static const struct iio_chan_spec mxs_lradc_chan_spec[] = {
++ MXS_ADC_CHAN(0, IIO_VOLTAGE),
++ MXS_ADC_CHAN(1, IIO_VOLTAGE),
++ MXS_ADC_CHAN(2, IIO_VOLTAGE),
++ MXS_ADC_CHAN(3, IIO_VOLTAGE),
++ MXS_ADC_CHAN(4, IIO_VOLTAGE),
++ MXS_ADC_CHAN(5, IIO_VOLTAGE),
++ MXS_ADC_CHAN(6, IIO_VOLTAGE),
++ MXS_ADC_CHAN(7, IIO_VOLTAGE), /* VBATT */
++ MXS_ADC_CHAN(8, IIO_TEMP), /* Temp sense 0 */
++ MXS_ADC_CHAN(9, IIO_TEMP), /* Temp sense 1 */
++ MXS_ADC_CHAN(10, IIO_VOLTAGE), /* VDDIO */
++ MXS_ADC_CHAN(11, IIO_VOLTAGE), /* VTH */
++ MXS_ADC_CHAN(12, IIO_VOLTAGE), /* VDDA */
++ MXS_ADC_CHAN(13, IIO_VOLTAGE), /* VDDD */
++ MXS_ADC_CHAN(14, IIO_VOLTAGE), /* VBG */
++ MXS_ADC_CHAN(15, IIO_VOLTAGE), /* VDD5V */
++};
++
++static void mxs_lradc_hw_init(struct mxs_lradc *lradc)
++{
++ int i;
++ const uint32_t cfg =
++ (LRADC_DELAY_TIMER_PER << LRADC_DELAY_DELAY_OFFSET);
++
++ stmp_reset_block(lradc->base);
++
++ for (i = 0; i < LRADC_MAX_DELAY_CHANS; i++)
++ writel(cfg | (1 << (LRADC_DELAY_TRIGGER_DELAYS_OFFSET + i)),
++ lradc->base + LRADC_DELAY(i));
++
++ /* Start internal temperature sensing. */
++ writel(0, lradc->base + LRADC_CTRL2);
++}
++
++static void mxs_lradc_hw_stop(struct mxs_lradc *lradc)
++{
++ int i;
++
++ writel(LRADC_CTRL1_LRADC_IRQ_EN_MASK,
++ lradc->base + LRADC_CTRL1 + STMP_OFFSET_REG_CLR);
++
++ for (i = 0; i < LRADC_MAX_DELAY_CHANS; i++)
++ writel(0, lradc->base + LRADC_DELAY(i));
++}
++
++static int __devinit mxs_lradc_probe(struct platform_device *pdev)
++{
++ struct device *dev = &pdev->dev;
++ struct mxs_lradc *lradc;
++ struct iio_dev *iio;
++ struct resource *iores;
++ int ret = 0;
++ int i;
++
++ /* Allocate the IIO device. */
++ iio = iio_device_alloc(sizeof(*lradc));
++ if (!iio) {
++ dev_err(dev, "Failed to allocate IIO device\n");
++ return -ENOMEM;
++ }
++
++ lradc = iio_priv(iio);
++
++ /* Grab the memory area */
++ iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ lradc->dev = &pdev->dev;
++ lradc->base = devm_request_and_ioremap(dev, iores);
++ if (!lradc->base) {
++ ret = -EADDRNOTAVAIL;
++ goto err_addr;
++ }
++
++ /* Grab all IRQ sources */
++ for (i = 0; i < 13; i++) {
++ lradc->irq[i] = platform_get_irq(pdev, i);
++ if (lradc->irq[i] < 0) {
++ ret = -EINVAL;
++ goto err_addr;
++ }
++
++ ret = devm_request_irq(dev, lradc->irq[i],
++ mxs_lradc_handle_irq, 0,
++ mxs_lradc_irq_name[i], iio);
++ if (ret)
++ goto err_addr;
++ }
++
++ platform_set_drvdata(pdev, iio);
++
++ init_completion(&lradc->completion);
++ mutex_init(&lradc->lock);
++
++ iio->name = pdev->name;
++ iio->dev.parent = &pdev->dev;
++ iio->info = &mxs_lradc_iio_info;
++ iio->modes = INDIO_DIRECT_MODE;
++ iio->channels = mxs_lradc_chan_spec;
++ iio->num_channels = ARRAY_SIZE(mxs_lradc_chan_spec);
++
++ ret = iio_triggered_buffer_setup(iio, &iio_pollfunc_store_time,
++ &mxs_lradc_trigger_handler,
++ &mxs_lradc_buffer_ops);
++ if (ret)
++ goto err_addr;
++
++ ret = mxs_lradc_trigger_init(iio);
++ if (ret)
++ goto err_trig;
++
++ /* Register IIO device. */
++ ret = iio_device_register(iio);
++ if (ret) {
++ dev_err(dev, "Failed to register IIO device\n");
++ goto err_dev;
++ }
++
++ /* Configure the hardware. */
++ mxs_lradc_hw_init(lradc);
++
++ return 0;
++
++err_dev:
++ mxs_lradc_trigger_remove(iio);
++err_trig:
++ iio_triggered_buffer_cleanup(iio);
++err_addr:
++ iio_device_free(iio);
++ return ret;
++}
++
++static int __devexit mxs_lradc_remove(struct platform_device *pdev)
++{
++ struct iio_dev *iio = platform_get_drvdata(pdev);
++ struct mxs_lradc *lradc = iio_priv(iio);
++
++ mxs_lradc_hw_stop(lradc);
++
++ iio_device_unregister(iio);
++ iio_triggered_buffer_cleanup(iio);
++ mxs_lradc_trigger_remove(iio);
++ iio_device_free(iio);
++
++ return 0;
++}
++
++static const struct of_device_id mxs_lradc_dt_ids[] = {
++ { .compatible = "fsl,imx28-lradc", },
++ { /* sentinel */ }
++};
++MODULE_DEVICE_TABLE(of, mxs_lradc_dt_ids);
++
++static struct platform_driver mxs_lradc_driver = {
++ .driver = {
++ .name = DRIVER_NAME,
++ .owner = THIS_MODULE,
++ .of_match_table = mxs_lradc_dt_ids,
++ },
++ .probe = mxs_lradc_probe,
++ .remove = __devexit_p(mxs_lradc_remove),
++};
++
++module_platform_driver(mxs_lradc_driver);
++
++MODULE_AUTHOR("Marek Vasut <ma...@de...>");
++MODULE_DESCRIPTION("Freescale i.MX28 LRADC driver");
++MODULE_LICENSE("GPL v2");
+--
+1.7.2.5
+
diff --git a/patches/linux/3.6/422-pengutronix-mx28-dts-Add_compatible_and_interrupt_for_LRADC.patch b/patches/linux/3.6/422-pengutronix-mx28-dts-Add_compatible_and_interrupt_for_LRADC.patch
new file mode 100644
index 0000000..4f86297
--- /dev/null
+++ b/patches/linux/3.6/422-pengutronix-mx28-dts-Add_compatible_and_interrupt_for_LRADC.patch
@@ -0,0 +1,33 @@
+From aef35104a9e5b8555cdaeebd4563df9921f6d605 Mon Sep 17 00:00:00 2001
+From: Marek Vasut <ma...@de...>
+Date: Fri, 17 Aug 2012 10:42:52 +0800
+Subject: [PATCH] ARM: dts: imx28: Add compatible and interrupt for LRADC
+
+Signed-off-by: Marek Vasut <ma...@de...>
+Cc: Jonathan Cameron <ji...@ke...>
+Cc: Juergen Beisert <jb...@pe...>
+Cc: Lars-Peter Clausen <la...@me...>
+Cc: Wolfgang Denk <wd...@de...>
+Signed-off-by: Shawn Guo <sha...@li...>
+---
+ arch/arm/boot/dts/imx28.dtsi | 3 +++
+ 1 files changed, 3 insertions(+), 0 deletions(-)
+
+diff --git a/arch/arm/boot/dts/imx28.dtsi b/arch/arm/boot/dts/imx28.dtsi
+index 3fa6d19..e2240da 100644
+--- a/arch/arm/boot/dts/imx28.dtsi
++++ b/arch/arm/boot/dts/imx28.dtsi
+@@ -638,7 +638,10 @@
+ };
+
+ lradc@80050000 {
++ compatible = "fsl,imx28-lradc";
+ reg = <0x80050000 0x2000>;
++ interrupts = <10 14 15 16 17 18 19
++ 20 21 22 23 24 25>;
+ status = "disabled";
+ };
+
+--
+1.7.2.5
+
hooks/post-receive
--
armadeus
|