summaryrefslogtreecommitdiff
path: root/arch/arm/plat-mxs
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/plat-mxs')
-rw-r--r--arch/arm/plat-mxs/Kconfig179
-rw-r--r--arch/arm/plat-mxs/Makefile24
-rw-r--r--arch/arm/plat-mxs/clock.c325
-rw-r--r--arch/arm/plat-mxs/core.c137
-rw-r--r--arch/arm/plat-mxs/cpufreq.c527
-rw-r--r--arch/arm/plat-mxs/device.c831
-rw-r--r--arch/arm/plat-mxs/dma-apbh.c243
-rw-r--r--arch/arm/plat-mxs/dma-apbx.c205
-rw-r--r--arch/arm/plat-mxs/dmaengine.c656
-rw-r--r--arch/arm/plat-mxs/gpio.c225
-rw-r--r--arch/arm/plat-mxs/icoll.c141
-rw-r--r--arch/arm/plat-mxs/include/mach/arc_otg.h174
-rw-r--r--arch/arm/plat-mxs/include/mach/bus_freq.h46
-rw-r--r--arch/arm/plat-mxs/include/mach/clkdev.h25
-rw-r--r--arch/arm/plat-mxs/include/mach/clock.h127
-rw-r--r--arch/arm/plat-mxs/include/mach/ddi_bc.h715
-rw-r--r--arch/arm/plat-mxs/include/mach/debug-macro.S42
-rw-r--r--arch/arm/plat-mxs/include/mach/device.h195
-rw-r--r--arch/arm/plat-mxs/include/mach/dmaengine.h518
-rw-r--r--arch/arm/plat-mxs/include/mach/entry-macro.S36
-rw-r--r--arch/arm/plat-mxs/include/mach/fsl_usb.h74
-rw-r--r--arch/arm/plat-mxs/include/mach/fsl_usb_gadget.h46
-rw-r--r--arch/arm/plat-mxs/include/mach/gpio.h63
-rw-r--r--arch/arm/plat-mxs/include/mach/hardware.h53
-rw-r--r--arch/arm/plat-mxs/include/mach/io.h38
-rw-r--r--arch/arm/plat-mxs/include/mach/irqs.h44
-rw-r--r--arch/arm/plat-mxs/include/mach/lradc.h61
-rw-r--r--arch/arm/plat-mxs/include/mach/memory.h59
-rw-r--r--arch/arm/plat-mxs/include/mach/pinctrl.h152
-rw-r--r--arch/arm/plat-mxs/include/mach/power.h64
-rw-r--r--arch/arm/plat-mxs/include/mach/system.h30
-rw-r--r--arch/arm/plat-mxs/include/mach/timex.h23
-rw-r--r--arch/arm/plat-mxs/include/mach/uncompress.h56
-rw-r--r--arch/arm/plat-mxs/include/mach/unique-id.h30
-rw-r--r--arch/arm/plat-mxs/include/mach/vmalloc.h19
-rw-r--r--arch/arm/plat-mxs/iram.c67
-rw-r--r--arch/arm/plat-mxs/lradc.c385
-rw-r--r--arch/arm/plat-mxs/pinctrl.c215
-rw-r--r--arch/arm/plat-mxs/regs-apbx.h433
-rw-r--r--arch/arm/plat-mxs/regs-icoll.h293
-rw-r--r--arch/arm/plat-mxs/regs-usbphy.h323
-rw-r--r--arch/arm/plat-mxs/timer-match.c164
-rw-r--r--arch/arm/plat-mxs/timer-nomatch.c195
-rw-r--r--arch/arm/plat-mxs/unique-id.c199
-rw-r--r--arch/arm/plat-mxs/usb_common.c426
-rw-r--r--arch/arm/plat-mxs/usb_wakeup.c222
-rw-r--r--arch/arm/plat-mxs/utmixc.c89
47 files changed, 9194 insertions, 0 deletions
diff --git a/arch/arm/plat-mxs/Kconfig b/arch/arm/plat-mxs/Kconfig
new file mode 100644
index 000000000000..831a24b53789
--- /dev/null
+++ b/arch/arm/plat-mxs/Kconfig
@@ -0,0 +1,179 @@
+if ARCH_MXS
+
+menu "Freescale i.MXS implementations"
+
+choice
+ prompt "Select i.MXS chip family"
+
+config ARCH_MX28
+ bool "Freescale MX28"
+ select CPU_ARM926T
+ select FIQ
+ select ZONE_DMA
+ select MXS_ICOLL
+ select MXS_DMA_ENGINE
+ select MXS_AUART_DMA_SUPPORT
+ select ARCH_HAS_CPUFREQ
+ ---help---
+ Support Freescale MX28 chips
+
+config ARCH_MX23
+ bool "Freescale MX23"
+ select CPU_ARM926T
+ select FIQ
+ select ZONE_DMA
+ select MXS_ICOLL
+ select MXS_DMA_ENGINE
+ select MXS_AUART_DMA_SUPPORT
+ select ARCH_HAS_CPUFREQ
+ ---help---
+ Support Freescale MX23 chips
+
+endchoice
+
+if ARCH_MX28
+source arch/arm/mach-mx28/Kconfig
+endif
+
+if ARCH_MX23
+source arch/arm/mach-mx23/Kconfig
+endif
+
+config DMA_ZONE_SIZE
+ int "DMA memory zone size"
+ range 0 32
+ default 16
+ help
+ This is the size in MB for the DMA zone. The DMA zone is used for
+ dedicated memory for large contiguous video buffers
+endmenu
+
+config MXS_ICOLL
+ bool
+
+config MXS_EARLY_CONSOLE
+ bool "Enable console early"
+ default y
+ help
+ Enable console early for kernel debug.
+
+config MXS_DMA_ENGINE
+ bool "Enable DMA ENGINE support"
+ default y
+ help
+ Support DMA controller on AHB-APBH and AHB-APBX Bridge
+
+config MXS_LRADC
+ bool "Low Resolution ADC support"
+ default y
+ depends on ARCH_MXS
+ help
+ Enable LRADC support
+
+config MXS_PWM_CHANNELS
+ int
+ default 8
+ help
+ The number of pwm channel on Freescale MXS platform.
+
+menu "Freescale Application UART:"
+
+config MXS_AUART_DMA_SUPPORT
+ bool
+ depends on MXS_DMA_ENGINE
+ default y
+
+config MXS_AUART_PORTS
+ int
+ default 5
+
+config MXS_AUART0_DEVICE_ENABLE
+ bool "Application uart 0 enabled"
+ default y
+ help
+ Enable applicatoin uart 0
+
+config MXS_AUART0_DMA_ENABLE
+ bool "Set application uart 0 to dma mode"
+ default n
+ depends on MXS_AUART_DMA_SUPPORT
+ help
+ Set application uart 0 to dma mode
+
+config MXS_AUART1_DEVICE_ENABLE
+ bool "Application uart 1 enabled"
+ default y
+ help
+ Enable applicatoin uart 1
+
+config MXS_AUART1_DMA_ENABLE
+ bool "Set application uart 1 to dma mode"
+ default n
+ depends on MXS_AUART_DMA_SUPPORT
+ help
+ Set application uart 1 to dma mode
+
+config MXS_AUART2_DEVICE_ENABLE
+ bool "Application uart 2 enabled"
+ default y
+ help
+ Enable applicatoin uart 2
+
+config MXS_AUART2_DMA_ENABLE
+ bool "Set application uart 2 to dma mode"
+ default n
+ depends on MXS_AUART_DMA_SUPPORT
+ help
+ Set application uart 2 to dma mode
+
+config MXS_AUART3_DEVICE_ENABLE
+ bool "Application uart 3 enabled"
+ default y
+ help
+ Enable applicatoin uart 3
+
+config MXS_AUART3_DMA_ENABLE
+ bool "Set application uart 3 to dma mode"
+ default n
+ depends on MXS_AUART_DMA_SUPPORT
+ help
+ Set application uart 3 to dma mode
+
+config MXS_AUART4_DEVICE_ENABLE
+ bool "Application uart 4 enabled"
+ default y
+ help
+ Enable applicatoin uart 4
+
+config MXS_AUART4_DMA_ENABLE
+ bool "Set application uart 4 to dma mode"
+ default n
+ depends on MXS_AUART_DMA_SUPPORT
+ help
+ Set application uart 4 to dma mode
+
+config MXS_RAM_FREQ_SCALING
+ bool "RAM frequency scaling support"
+ depends on ARCH_MXS
+ default y
+
+choice
+ prompt "Select MXS RAM chip"
+ depends on MXS_RAM_FREQ_SCALING
+
+config MXS_RAM_MDDR
+ bool "mDDR SDRAM"
+ depends on ARCH_MX23
+config MXS_RAM_DDR
+ bool "DDR SDRAM"
+ depends on ARCH_MX23
+
+endchoice
+
+config IRAM_ALLOC
+ bool
+ default y
+ select GENERIC_ALLOCATOR
+endmenu
+
+endif
diff --git a/arch/arm/plat-mxs/Makefile b/arch/arm/plat-mxs/Makefile
new file mode 100644
index 000000000000..b583737fe254
--- /dev/null
+++ b/arch/arm/plat-mxs/Makefile
@@ -0,0 +1,24 @@
+#
+# Makefile for the linux kernel.
+#
+# Object file lists.
+obj-y += core.o clock.o pinctrl.o device.o timer-nomatch.o usb_common.o usb_wakeup.o
+
+obj-$(CONFIG_MXS_TIMER_WITH_MACH) += timer-match.o
+obj-$(CONFIG_IRAM_ALLOC) += iram.o
+obj-$(CONFIG_GENERIC_GPIO) += gpio.o
+
+obj-$(CONFIG_MXS_UNIQUE_ID) += unique-id.o
+
+obj-$(CONFIG_MXS_ICOLL) += icoll.o
+
+obj-$(CONFIG_MXS_DMA_ENGINE) += dmaengine.o dma-apbh.o dma-apbx.o
+
+obj-$(CONFIG_USB_SUPPORT) += utmixc.o
+
+obj-$(CONFIG_MXS_LRADC) += lradc.o
+# Power Management
+obj-$(CONFIG_CPU_FREQ) += cpufreq.o
+
+# charging/current limitation testing
+
diff --git a/arch/arm/plat-mxs/clock.c b/arch/arm/plat-mxs/clock.c
new file mode 100644
index 000000000000..1b98b1e51164
--- /dev/null
+++ b/arch/arm/plat-mxs/clock.c
@@ -0,0 +1,325 @@
+/*
+ * Copyright (C) 2009-2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/irq.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/spinlock.h>
+#include <linux/cpufreq.h>
+
+#include <mach/clock.h>
+
+extern int cpufreq_trig_needed;
+static bool (*mxs_enable_h_autoslow)(bool enable);
+static void (*mxs_set_h_autoslow_flags)(u16 flags);
+
+static DEFINE_SPINLOCK(clockfw_lock);
+
+/*
+ *-------------------------------------------------------------------------
+ * Standard clock functions defined in include/linux/clk.h
+ *-------------------------------------------------------------------------
+ */
+int __clk_get(struct clk *clk)
+{
+ if (clk->ref < CLK_REF_LIMIT)
+ clk->ref += CLK_REF_UNIT;
+ return clk->ref < CLK_REF_LIMIT;
+}
+
+void __clk_put(struct clk *clk)
+{
+ if (clk->ref & CLK_REF_LIMIT)
+ clk->ref -= CLK_REF_UNIT;
+}
+
+static void default_clk_disable(struct clk *clk)
+{
+ if (clk->enable_reg)
+ __raw_writel(clk->enable_bits, clk->enable_reg + SET_REGISTER);
+}
+
+static int default_clk_enable(struct clk *clk)
+{
+ if (clk->enable_reg)
+ __raw_writel(clk->enable_bits, clk->enable_reg + CLR_REGISTER);
+ return 0;
+}
+
+static unsigned long default_get_rate(struct clk *clk)
+{
+ if (clk->parent && clk->parent->get_rate)
+ return clk->parent->get_rate(clk->parent);
+ return 0L;
+}
+
+static void __clk_disable(struct clk *clk)
+{
+ if (clk == NULL || IS_ERR(clk) || !clk->ref)
+ return;
+
+ if ((--clk->ref) & CLK_EN_MASK)
+ return;
+
+ if (clk->disable)
+ clk->disable(clk);
+ __clk_disable(clk->secondary);
+ __clk_disable(clk->parent);
+}
+
+static int __clk_enable(struct clk *clk)
+{
+ if (clk == NULL || IS_ERR(clk))
+ return -EINVAL;
+
+ if ((clk->ref++) & CLK_EN_MASK)
+ return 0;
+ if (clk->parent)
+ __clk_enable(clk->parent);
+ if (clk->secondary)
+ __clk_enable(clk->secondary);
+ if (clk->enable)
+ clk->enable(clk);
+ return 0;
+}
+
+int clk_enable(struct clk *clk)
+{
+ unsigned long flags;
+ int ret = 0;
+ int pre_usage;
+
+ if (clk == NULL || IS_ERR(clk))
+ return -EINVAL;
+
+ spin_lock_irqsave(&clockfw_lock, flags);
+ pre_usage = (clk->ref & CLK_EN_MASK);
+
+ if (clk->set_sys_dependent_parent)
+ clk->set_sys_dependent_parent(clk);
+
+ ret = __clk_enable(clk);
+ spin_unlock_irqrestore(&clockfw_lock, flags);
+ if ((clk->flags & CPU_FREQ_TRIG_UPDATE)
+ && (pre_usage == 0)) {
+ cpufreq_trig_needed = 1;
+ cpufreq_update_policy(0);
+ }
+ return ret;
+}
+EXPORT_SYMBOL(clk_enable);
+
+void clk_disable(struct clk *clk)
+{
+ unsigned long flags;
+
+ if (clk == NULL || IS_ERR(clk))
+ return;
+ if (clk->flags & ALWAYS_ENABLED)
+ return;
+ spin_lock_irqsave(&clockfw_lock, flags);
+ __clk_disable(clk);
+ spin_unlock_irqrestore(&clockfw_lock, flags);
+ if ((clk->flags & CPU_FREQ_TRIG_UPDATE)
+ && ((clk->ref & CLK_EN_MASK) == 0)) {
+ cpufreq_trig_needed = 1;
+ cpufreq_update_policy(0);
+ }
+}
+EXPORT_SYMBOL(clk_disable);
+
+int clk_get_usecount(struct clk *clk)
+{
+ if (clk == NULL || IS_ERR(clk))
+ return 0;
+
+ return clk->ref & CLK_EN_MASK;
+}
+EXPORT_SYMBOL(clk_get_usecount);
+
+unsigned long clk_get_rate(struct clk *clk)
+{
+ unsigned long flags, rate;
+ if (clk == NULL || IS_ERR(clk) || clk->get_rate == NULL)
+ return 0UL;
+
+ spin_lock_irqsave(&clockfw_lock, flags);
+ rate = clk->get_rate(clk);
+ spin_unlock_irqrestore(&clockfw_lock, flags);
+ return rate;
+}
+EXPORT_SYMBOL(clk_get_rate);
+
+long clk_round_rate(struct clk *clk, unsigned long rate)
+{
+ if (clk == NULL || IS_ERR(clk) || !clk->round_rate)
+ return 0;
+
+ if (clk->flags & RATE_FIXED)
+ return 0;
+
+ if (clk->round_rate)
+ return clk->round_rate(clk, rate);
+ return 0;
+}
+EXPORT_SYMBOL(clk_round_rate);
+
+int clk_set_rate(struct clk *clk, unsigned long rate)
+{
+ unsigned long flags;
+ int ret = -EINVAL;
+
+ if (clk == NULL || IS_ERR(clk) || clk->set_rate == NULL || rate == 0)
+ return ret;
+
+ if (clk->flags & RATE_FIXED)
+ return ret;
+
+ spin_lock_irqsave(&clockfw_lock, flags);
+ ret = clk->set_rate(clk, rate);
+ spin_unlock_irqrestore(&clockfw_lock, flags);
+ return ret;
+}
+EXPORT_SYMBOL(clk_set_rate);
+
+int clk_set_parent(struct clk *clk, struct clk *parent)
+{
+ unsigned long flags;
+ int ret = -EINVAL;
+ struct clk *prev_parent;
+
+ if (clk == NULL || IS_ERR(clk) || parent == NULL ||
+ IS_ERR(parent) || clk->set_parent == NULL ||
+ parent->get_rate == NULL)
+ return ret;
+
+ if (clk->ref & CLK_EN_MASK)
+ clk_enable(parent);
+
+ spin_lock_irqsave(&clockfw_lock, flags);
+ prev_parent = clk->parent;
+ ret = clk->set_parent(clk, parent);
+ if (ret) {
+ spin_unlock_irqrestore(&clockfw_lock, flags);
+ if (clk->ref & CLK_EN_MASK)
+ clk_disable(parent);
+ return ret;
+ }
+
+ clk->parent = parent;
+
+ spin_unlock_irqrestore(&clockfw_lock, flags);
+
+ if (clk->ref & CLK_EN_MASK)
+ clk_disable(prev_parent);
+ return 0;
+}
+EXPORT_SYMBOL(clk_set_parent);
+
+struct clk *clk_get_parent(struct clk *clk)
+{
+ struct clk *ret = NULL;
+
+ if (clk == NULL || IS_ERR(clk))
+ return ret;
+
+ return clk->parent;
+}
+EXPORT_SYMBOL(clk_get_parent);
+
+int clk_register(struct clk_lookup *lookup)
+{
+ if (lookup == NULL || IS_ERR(lookup) ||
+ lookup->clk == NULL || IS_ERR(lookup->clk))
+ return -EINVAL;
+
+ if (lookup->clk->ref & CLK_REF_LIMIT)
+ return -EEXIST;
+
+ if (!(lookup->clk->enable))
+ lookup->clk->enable = default_clk_enable;
+ if (!(lookup->clk->disable))
+ lookup->clk->disable = default_clk_disable;
+ if (!(lookup->clk->get_rate))
+ lookup->clk->get_rate = default_get_rate;
+
+ clkdev_add(lookup);
+
+ return 0;
+}
+EXPORT_SYMBOL(clk_register);
+
+void clk_unregister(struct clk_lookup *lookup)
+{
+ if (lookup == NULL || IS_ERR(lookup) ||
+ lookup->clk == NULL || IS_ERR(lookup->clk))
+ return;
+
+ if (lookup->clk->ref & CLK_REF_LIMIT)
+ return;
+
+ clkdev_drop(lookup);
+ if (lookup->clk->enable == default_clk_enable)
+ lookup->clk->enable = NULL;
+ if (lookup->clk->disable == default_clk_disable)
+ lookup->clk->disable = NULL;
+ if (lookup->clk->get_rate == default_get_rate)
+ lookup->clk->get_rate = NULL;
+}
+EXPORT_SYMBOL(clk_unregister);
+
+bool clk_enable_h_autoslow(bool enable)
+{
+ unsigned long flags;
+ bool ret = false;
+
+ if (mxs_enable_h_autoslow == NULL)
+ return ret;
+
+ spin_lock_irqsave(&clockfw_lock, flags);
+ ret = mxs_enable_h_autoslow(enable);
+ spin_unlock_irqrestore(&clockfw_lock, flags);
+
+ return ret;
+}
+EXPORT_SYMBOL(clk_enable_h_autoslow);
+
+void clk_set_h_autoslow_flags(u16 mask)
+{
+ unsigned long flags;
+
+ if (mxs_set_h_autoslow_flags == NULL)
+ return;
+
+ spin_lock_irqsave(&clockfw_lock, flags);
+ mxs_set_h_autoslow_flags(mask);
+ spin_unlock_irqrestore(&clockfw_lock, flags);
+}
+EXPORT_SYMBOL(clk_set_h_autoslow_flags);
+
+void clk_en_public_h_asm_ctrl(bool (*enable_func)(bool),
+ void (*set_func)(u16))
+{
+ mxs_enable_h_autoslow = enable_func;
+ mxs_set_h_autoslow_flags = set_func;
+}
+EXPORT_SYMBOL(clk_en_public_h_asm_ctrl);
diff --git a/arch/arm/plat-mxs/core.c b/arch/arm/plat-mxs/core.c
new file mode 100644
index 000000000000..b804a579397c
--- /dev/null
+++ b/arch/arm/plat-mxs/core.c
@@ -0,0 +1,137 @@
+/*
+ * Copyright (C) 2009-2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/err.h>
+
+#include <asm/proc-fns.h>
+
+#include <mach/hardware.h>
+#include <mach/regs-rtc.h>
+
+void (*machine_arch_reset) (char mode, const char *cmd);
+
+void arch_idle(void)
+{
+ cpu_do_idle();
+}
+
+void arch_reset(char mode, const char *cmd)
+{
+ if (machine_arch_reset)
+ machine_arch_reset(mode, cmd);
+ else {
+ void *base = IO_ADDRESS(RTC_PHYS_ADDR);
+
+ __raw_writel(1, base + HW_RTC_WATCHDOG);
+ __raw_writel(0x80000000, base + HW_RTC_PERSISTENT1_SET);
+ __raw_writel(BM_RTC_CTRL_WATCHDOGEN, base + HW_RTC_CTRL_SET);
+ }
+ cpu_reset(0);
+}
+
+static int __mxs_reset_block(void __iomem *hwreg, int just_enable)
+{
+ u32 c;
+ int timeout;
+
+ /* the process of software reset of IP block is done
+ in several steps:
+
+ - clear SFTRST and wait for block is enabled;
+ - clear clock gating (CLKGATE bit);
+ - set the SFTRST again and wait for block is in reset;
+ - clear SFTRST and wait for reset completion.
+ */
+ c = __raw_readl(hwreg);
+ c &= ~(1 << 31); /* clear SFTRST */
+ __raw_writel(c, hwreg);
+ for (timeout = 1000000; timeout > 0; timeout--)
+ /* still in SFTRST state ? */
+ if ((__raw_readl(hwreg) & (1 << 31)) == 0)
+ break;
+ if (timeout <= 0) {
+ printk(KERN_ERR "%s(%p): timeout when enabling\n",
+ __func__, hwreg);
+ return -ETIME;
+ }
+
+ c = __raw_readl(hwreg);
+ c &= ~(1 << 30); /* clear CLKGATE */
+ __raw_writel(c, hwreg);
+
+ if (!just_enable) {
+ c = __raw_readl(hwreg);
+ c |= (1 << 31); /* now again set SFTRST */
+ __raw_writel(c, hwreg);
+ for (timeout = 1000000; timeout > 0; timeout--)
+ /* poll until CLKGATE set */
+ if (__raw_readl(hwreg) & (1 << 30))
+ break;
+ if (timeout <= 0) {
+ printk(KERN_ERR "%s(%p): timeout when resetting\n",
+ __func__, hwreg);
+ return -ETIME;
+ }
+
+ c = __raw_readl(hwreg);
+ c &= ~(1 << 31); /* clear SFTRST */
+ __raw_writel(c, hwreg);
+ for (timeout = 1000000; timeout > 0; timeout--)
+ /* still in SFTRST state ? */
+ if ((__raw_readl(hwreg) & (1 << 31)) == 0)
+ break;
+ if (timeout <= 0) {
+ printk(KERN_ERR "%s(%p): timeout when enabling "
+ "after reset\n", __func__, hwreg);
+ return -ETIME;
+ }
+
+ c = __raw_readl(hwreg);
+ c &= ~(1 << 30); /* clear CLKGATE */
+ __raw_writel(c, hwreg);
+ }
+ for (timeout = 1000000; timeout > 0; timeout--)
+ /* still in SFTRST state ? */
+ if ((__raw_readl(hwreg) & (1 << 30)) == 0)
+ break;
+
+ if (timeout <= 0) {
+ printk(KERN_ERR "%s(%p): timeout when unclockgating\n",
+ __func__, hwreg);
+ return -ETIME;
+ }
+
+ return 0;
+}
+
+int mxs_reset_block(void __iomem *hwreg, int just_enable)
+{
+ int try = 10;
+ int r;
+
+ while (try--) {
+ r = __mxs_reset_block(hwreg, just_enable);
+ if (!r)
+ break;
+ pr_debug("%s: try %d failed\n", __func__, 10 - try);
+ }
+ return r;
+}
diff --git a/arch/arm/plat-mxs/cpufreq.c b/arch/arm/plat-mxs/cpufreq.c
new file mode 100644
index 000000000000..a188b21d9bf4
--- /dev/null
+++ b/arch/arm/plat-mxs/cpufreq.c
@@ -0,0 +1,527 @@
+/*
+ * Copyright (C) 2008-2010 Freescale Semiconductor, Inc.
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/cpufreq.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/spinlock.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
+#include <linux/notifier.h>
+
+#include <mach/hardware.h>
+#include <linux/io.h>
+#include <asm/system.h>
+#include <mach/regulator.h>
+#include <mach/power.h>
+#include <mach/clock.h>
+#include <mach/bus_freq.h>
+
+static struct regulator *cpu_regulator;
+static struct clk *cpu_clk;
+static struct clk *ahb_clk;
+static struct clk *x_clk;
+static struct clk *emi_clk;
+static struct regulator *vddd;
+static struct regulator *vdddbo;
+static struct regulator *vddio;
+static struct regulator *vdda;
+static struct cpufreq_frequency_table imx_freq_table[7];
+int cpu_freq_khz_min;
+int cpu_freq_khz_max;
+int cpufreq_trig_needed;
+int cur_freq_table_size;
+int lcd_on_freq_table_size;
+int lcd_off_freq_table_size;
+int high_freq_needed;
+
+extern char *ahb_clk_id;
+extern struct profile profiles[OPERATION_WP_SUPPORTED];
+extern int low_freq_used(void);
+
+static int set_freq_table(struct cpufreq_policy *policy, int end_index)
+{
+ int ret = 0;
+ int i;
+ int zero_no = 0;
+
+ for (i = 0; i < end_index; i++) {
+ if (profiles[i].cpu == 0)
+ zero_no++;
+ }
+
+ end_index -= zero_no;
+
+ cpu_freq_khz_min = profiles[0].cpu;
+ cpu_freq_khz_max = profiles[0].cpu;
+ for (i = 0; i < end_index; i++) {
+ imx_freq_table[end_index - 1 - i].index = end_index - i;
+ imx_freq_table[end_index - 1 - i].frequency =
+ profiles[i].cpu;
+
+ if ((profiles[i].cpu) < cpu_freq_khz_min)
+ cpu_freq_khz_min = profiles[i].cpu;
+
+ if ((profiles[i].cpu) > cpu_freq_khz_max)
+ cpu_freq_khz_max = profiles[i].cpu;
+ }
+
+ imx_freq_table[i].index = 0;
+ imx_freq_table[i].frequency = CPUFREQ_TABLE_END;
+
+ policy->cur = clk_get_rate(cpu_clk) / 1000;
+ policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
+ policy->min = policy->cpuinfo.min_freq = cpu_freq_khz_min;
+ policy->max = policy->cpuinfo.max_freq = cpu_freq_khz_max;
+
+ /* Manual states, that PLL stabilizes in two CLK32 periods */
+ policy->cpuinfo.transition_latency = 1000;
+
+ ret = cpufreq_frequency_table_cpuinfo(policy, imx_freq_table);
+
+ if (ret < 0) {
+ printk(KERN_ERR "%s: failed to register i.MXC CPUfreq\n",
+ __func__);
+ return ret;
+ }
+
+ cpufreq_frequency_table_get_attr(imx_freq_table, policy->cpu);
+
+ return ret;
+}
+
+static int set_op(struct cpufreq_policy *policy, unsigned int target_freq)
+{
+ struct cpufreq_freqs freqs;
+ int ret = 0, i;
+
+ freqs.old = clk_get_rate(cpu_clk) / 1000;
+ freqs.cpu = 0;
+
+/* work around usb problem when in updater firmare mode*/
+#ifdef CONFIG_MXS_UTP
+ return 0;
+#endif
+ for (i = cur_freq_table_size - 1; i > 0; i--) {
+ if (profiles[i].cpu <= target_freq &&
+ target_freq < profiles[i - 1].cpu) {
+ freqs.new = profiles[i].cpu;
+ break;
+ }
+
+ if (!vddd && profiles[i].cpu > freqs.old) {
+ /* can't safely set more than now */
+ freqs.new = profiles[i + 1].cpu;
+ break;
+ }
+ }
+
+ if (i == 0)
+ freqs.new = profiles[i].cpu;
+
+ if ((freqs.old / 1000) == (freqs.new / 1000)) {
+ if (regulator_get_voltage(vddd) == profiles[i].vddd)
+ return 0;
+ }
+
+ if (cpu_regulator && (freqs.old < freqs.new)) {
+ ret = regulator_set_current_limit(cpu_regulator,
+ profiles[i].cur, profiles[i].cur);
+ if (ret)
+ return ret;
+ }
+
+ cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+
+ if (freqs.old > freqs.new) {
+ int ss = profiles[i].ss;
+
+ /* change emi while cpu is fastest to minimize
+ * time spent changing emiclk
+ */
+ clk_set_rate(emi_clk, (profiles[i].emi) * 1000);
+ clk_set_rate(cpu_clk, (profiles[i].cpu) * 1000);
+ clk_set_rate(ahb_clk, (profiles[i].ahb) * 1000);
+ /* x_clk order doesn't really matter */
+ clk_set_rate(x_clk, (profiles[i].xbus) * 1000);
+ timing_ctrl_rams(ss);
+
+ if (vddd && vdddbo && vddio && vdda) {
+ ret = regulator_set_voltage(vddd,
+ profiles[i].vddd,
+ profiles[i].vddd);
+ if (ret)
+ ret = regulator_set_voltage(vddd,
+ profiles[i].vddd,
+ profiles[i].vddd);
+ regulator_set_voltage(vdddbo,
+ profiles[i].vddd_bo,
+ profiles[i].vddd_bo);
+
+ ret = regulator_set_voltage(vddio,
+ profiles[i].vddio,
+ profiles[i].vddio);
+ if (ret)
+ ret = regulator_set_voltage(vddio,
+ profiles[i].vddio,
+ profiles[i].vddio);
+ ret = regulator_set_voltage(vdda,
+ profiles[i].vdda,
+ profiles[i].vdda);
+ if (ret)
+ ret = regulator_set_voltage(vdda,
+ profiles[i].vdda,
+ profiles[i].vdda);
+ }
+ } else {
+ int ss = profiles[i].ss;
+ if (vddd && vdddbo && vddio && vdda) {
+ ret = regulator_set_voltage(vddd,
+ profiles[i].vddd,
+ profiles[i].vddd);
+ if (ret)
+ ret = regulator_set_voltage(vddd,
+ profiles[i].vddd,
+ profiles[i].vddd);
+ regulator_set_voltage(vdddbo,
+ profiles[i].vddd_bo,
+ profiles[i].vddd_bo);
+ ret = regulator_set_voltage(vddio,
+ profiles[i].vddio,
+ profiles[i].vddio);
+ if (ret)
+ ret = regulator_set_voltage(vddio,
+ profiles[i].vddio,
+ profiles[i].vddio);
+ ret = regulator_set_voltage(vdda,
+ profiles[i].vdda,
+ profiles[i].vdda);
+ if (ret)
+ ret = regulator_set_voltage(vdda,
+ profiles[i].vdda,
+ profiles[i].vdda);
+ }
+ /* x_clk order doesn't really matter */
+ clk_set_rate(x_clk, (profiles[i].xbus) * 1000);
+ timing_ctrl_rams(ss);
+ clk_set_rate(cpu_clk, (profiles[i].cpu) * 1000);
+ clk_set_rate(ahb_clk, (profiles[i].ahb) * 1000);
+ clk_set_rate(emi_clk, (profiles[i].emi) * 1000);
+ }
+
+ if (is_hclk_autoslow_ok())
+ clk_set_h_autoslow_flags(profiles[i].h_autoslow_flags);
+ else
+ clk_enable_h_autoslow(false);
+
+ if (high_freq_needed == 0)
+ cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+
+ if (cpu_regulator && (freqs.old > freqs.new)) /* will not fail */
+ regulator_set_current_limit(cpu_regulator,
+ profiles[i].cur,
+ profiles[i].cur);
+
+ if (high_freq_needed == 1) {
+ high_freq_needed = 0;
+ cur_freq_table_size = lcd_on_freq_table_size;
+ set_freq_table(policy, cur_freq_table_size);
+ cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+ }
+
+ return ret;
+}
+
+static int calc_frequency_khz(int target, unsigned int relation)
+{
+ int i;
+
+ if (target * 1000 == clk_get_rate(cpu_clk))
+ return target;
+
+ if (relation == CPUFREQ_RELATION_H) {
+ for (i = cur_freq_table_size - 1; i >= 0; i--) {
+ if (imx_freq_table[i].frequency <= target)
+ return imx_freq_table[i].frequency;
+ }
+ } else if (relation == CPUFREQ_RELATION_L) {
+ for (i = 0; i < cur_freq_table_size; i++) {
+ if (imx_freq_table[i].frequency >= target)
+ return imx_freq_table[i].frequency;
+ }
+}
+
+ printk(KERN_ERR "Error: No valid cpufreq relation\n");
+ return cpu_freq_khz_max;
+}
+
+static int mxs_target(struct cpufreq_policy *policy,
+ unsigned int target_freq,
+ unsigned int relation)
+{
+ int freq_KHz;
+ struct cpufreq_freqs freqs;
+ int low_freq_bus_ready = 0;
+
+ if (cpufreq_trig_needed == 1) {
+ /* Set the current working point. */
+ cpufreq_trig_needed = 0;
+ target_freq = clk_get_rate(cpu_clk) / 1000;
+ low_freq_bus_ready = low_freq_used();
+
+ if ((target_freq < LCD_ON_CPU_FREQ_KHZ) &&
+ (low_freq_bus_ready == 0)) {
+ high_freq_needed = 1;
+ target_freq = LCD_ON_CPU_FREQ_KHZ;
+ goto change_freq;
+ }
+
+ target_freq = clk_get_rate(cpu_clk) / 1000;
+ freq_KHz = calc_frequency_khz(target_freq, relation);
+
+ freqs.old = target_freq;
+ freqs.new = freq_KHz;
+ freqs.cpu = 0;
+ freqs.flags = 0;
+ cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+ low_freq_bus_ready = low_freq_used();
+ if (low_freq_bus_ready) {
+ int i;
+ cur_freq_table_size = lcd_off_freq_table_size;
+ /* find current table index to get
+ * hbus autoslow flags and enable hbus autoslow.
+ */
+ for (i = cur_freq_table_size - 1; i > 0; i--) {
+ if (profiles[i].cpu <= target_freq &&
+ target_freq < profiles[i - 1].cpu) {
+ clk_set_h_autoslow_flags(
+ profiles[i].h_autoslow_flags);
+ break;
+ }
+ }
+ } else {
+ cur_freq_table_size = lcd_on_freq_table_size;
+ clk_enable_h_autoslow(false);
+ }
+
+ set_freq_table(policy, cur_freq_table_size);
+ cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+ return 0;
+}
+
+ /*
+ * Some governors do not respects CPU and policy lower limits
+ * which leads to bad things (division by zero etc), ensure
+ * that such things do not happen.
+ */
+change_freq: if (target_freq < policy->cpuinfo.min_freq)
+ target_freq = policy->cpuinfo.min_freq;
+
+ if (target_freq < policy->min)
+ target_freq = policy->min;
+
+ freq_KHz = calc_frequency_khz(target_freq, relation);
+ return set_op(policy, freq_KHz);
+ }
+
+static unsigned int mxs_getspeed(unsigned int cpu)
+{
+ if (cpu)
+ return 0;
+
+ return clk_get_rate(cpu_clk) / 1000;
+}
+
+
+static int mxs_verify_speed(struct cpufreq_policy *policy)
+{
+ if (policy->cpu != 0)
+ return -EINVAL;
+
+ return cpufreq_frequency_table_verify(policy, imx_freq_table);
+}
+
+static int __init mxs_cpu_init(struct cpufreq_policy *policy)
+{
+ int ret = 0;
+ int i;
+
+ cpu_clk = clk_get(NULL, "cpu");
+ if (IS_ERR(cpu_clk)) {
+ ret = PTR_ERR(cpu_clk);
+ goto out_cpu;
+ }
+
+ ahb_clk = clk_get(NULL, "h");
+ if (IS_ERR(ahb_clk)) {
+ ret = PTR_ERR(ahb_clk);
+ goto out_ahb;
+ }
+
+ x_clk = clk_get(NULL, "x");
+ if (IS_ERR(ahb_clk)) {
+ ret = PTR_ERR(x_clk);
+ goto out_x;
+ }
+
+ emi_clk = clk_get(NULL, "emi");
+ if (IS_ERR(emi_clk)) {
+ ret = PTR_ERR(emi_clk);
+ goto out_emi;
+ }
+
+ if (policy->cpu != 0)
+ return -EINVAL;
+
+ cpu_regulator = regulator_get(NULL, "cpufreq-1");
+ if (IS_ERR(cpu_regulator)) {
+ printk(KERN_ERR "%s: failed to get CPU regulator\n", __func__);
+ cpu_regulator = NULL;
+ ret = PTR_ERR(cpu_regulator);
+ goto out_cur;
+ }
+
+ vddd = regulator_get(NULL, "vddd");
+ if (IS_ERR(vddd)) {
+ printk(KERN_ERR "%s: failed to get vddd regulator\n", __func__);
+ vddd = NULL;
+ ret = PTR_ERR(vddd);
+ goto out_cur;
+ }
+
+ vdddbo = regulator_get(NULL, "vddd_bo");
+ if (IS_ERR(vdddbo)) {
+ vdddbo = NULL;
+ pr_warning("unable to get vdddbo");
+ ret = PTR_ERR(vdddbo);
+ goto out_cur;
+ }
+
+ vddio = regulator_get(NULL, "vddio");
+ if (IS_ERR(vddio)) {
+ vddio = NULL;
+ pr_warning("unable to get vddio");
+ ret = PTR_ERR(vddio);
+ goto out_cur;
+ }
+
+ vdda = regulator_get(NULL, "vdda");
+ if (IS_ERR(vdda)) {
+ vdda = NULL;
+ pr_warning("unable to get vdda");
+ ret = PTR_ERR(vdda);
+ goto out_cur;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(profiles); i++) {
+ if ((profiles[i].cpu) == LCD_ON_CPU_FREQ_KHZ) {
+ lcd_on_freq_table_size = i + 1;
+ break;
+ }
+ }
+
+ if (i == ARRAY_SIZE(profiles)) {
+ pr_warning("unable to find frequency for LCD on");
+ printk(KERN_ERR "lcd_on_freq_table_size=%d\n",
+ lcd_on_freq_table_size);
+ goto out_cur;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(profiles); i++) {
+ if ((profiles[i].cpu) == 0) {
+ lcd_off_freq_table_size = i;
+ break;
+ }
+ }
+
+ if (i == ARRAY_SIZE(profiles))
+ lcd_off_freq_table_size = i;
+
+ /* Set the current working point. */
+ set_freq_table(policy, lcd_on_freq_table_size);
+ cpufreq_trig_needed = 0;
+ high_freq_needed = 0;
+ cur_freq_table_size = lcd_on_freq_table_size;
+
+ printk(KERN_INFO "%s: cpufreq init finished\n", __func__);
+ return 0;
+out_cur:
+ if (cpu_regulator)
+ regulator_put(cpu_regulator);
+ if (vddd)
+ regulator_put(vddd);
+ if (vddio)
+ regulator_put(vddio);
+ if (vdda)
+ regulator_put(vdda);
+
+ clk_put(emi_clk);
+out_emi:
+ clk_put(x_clk);
+out_x:
+ clk_put(ahb_clk);
+out_ahb:
+ clk_put(cpu_clk);
+out_cpu:
+ return ret;
+}
+
+static int mxs_cpu_exit(struct cpufreq_policy *policy)
+{
+ cpufreq_frequency_table_put_attr(policy->cpu);
+
+ /* Reset CPU to 392MHz */
+ set_op(policy, profiles[1].cpu);
+
+ clk_put(cpu_clk);
+ regulator_put(cpu_regulator);
+ return 0;
+}
+
+static struct cpufreq_driver mxs_driver = {
+ .flags = CPUFREQ_STICKY,
+ .verify = mxs_verify_speed,
+ .target = mxs_target,
+ .get = mxs_getspeed,
+ .init = mxs_cpu_init,
+ .exit = mxs_cpu_exit,
+ .name = "mxs",
+};
+
+static int __devinit mxs_cpufreq_init(void)
+{
+ return cpufreq_register_driver(&mxs_driver);
+}
+
+static void mxs_cpufreq_exit(void)
+{
+ cpufreq_unregister_driver(&mxs_driver);
+}
+
+module_init(mxs_cpufreq_init);
+module_exit(mxs_cpufreq_exit);
+
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_DESCRIPTION("CPUfreq driver for i.MX");
+MODULE_LICENSE("GPL");
+
diff --git a/arch/arm/plat-mxs/device.c b/arch/arm/plat-mxs/device.c
new file mode 100644
index 000000000000..87a38fa8c3d8
--- /dev/null
+++ b/arch/arm/plat-mxs/device.c
@@ -0,0 +1,831 @@
+/*
+ * Copyright (C) 2009-2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/err.h>
+#include <linux/list.h>
+#include <linux/bitops.h>
+#include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
+#include <linux/gpmi-nfc.h>
+
+#include <mach/device.h>
+
+static int mxs_device_num;
+static int mxs_device_done;
+static DEFINE_MUTEX(device_mutex);
+static struct list_head mxs_device_level[] = {
+ LIST_HEAD_INIT(mxs_device_level[0]),
+ LIST_HEAD_INIT(mxs_device_level[1]),
+ LIST_HEAD_INIT(mxs_device_level[2]),
+ LIST_HEAD_INIT(mxs_device_level[3]),
+};
+
+static u64 common_dmamask = DMA_BIT_MASK(32);
+
+void mxs_nop_release(struct device *dev)
+{
+ /* Nothing */
+}
+
+int mxs_add_devices(struct platform_device *pdev, int num, int level)
+{
+ int i, ret = -ENOMEM;
+ if (pdev == NULL || IS_ERR(pdev) || num <= 0)
+ return -EINVAL;
+
+ if (level < 0)
+ level = 0;
+ else if (level >= ARRAY_SIZE(mxs_device_level))
+ level = ARRAY_SIZE(mxs_device_level) - 1;
+
+ mutex_lock(&device_mutex);
+ if (mxs_device_done) {
+ ret = 0;
+ for (i = 0; i < num; i++)
+ ret |= platform_device_register(pdev + i);
+ goto out;
+ }
+
+ if ((mxs_device_num + num) > MXS_MAX_DEVICES)
+ goto out;
+ mxs_device_num += num;
+ for (i = 0; i < num; i++)
+ list_add_tail(&pdev[i].dev.devres_head,
+ &mxs_device_level[level]);
+ ret = 0;
+out:
+ mutex_unlock(&device_mutex);
+ return ret;
+}
+
+int mxs_add_device(struct platform_device *pdev, int level)
+{
+ return mxs_add_devices(pdev, 1, level);
+}
+
+#if defined(CONFIG_SERIAL_MXS_DUART) || \
+ defined(CONFIG_SERIAL_MXS_DUART_MODULE)
+static struct platform_device mxs_duart = {
+ .name = "mxs-duart",
+ .id = 0,
+ .dev = {
+ .release = mxs_nop_release,
+ },
+};
+#endif
+
+#if defined(CONFIG_MXS_DMA_ENGINE)
+static struct platform_device mxs_dma[] = {
+ {
+ .name = "mxs-dma-apbh",
+ .id = 0,
+ .dev = {
+ .release = mxs_nop_release,
+ },
+ },
+ {
+ .name = "mxs-dma-apbx",
+ .id = 0,
+ .dev = {
+ .release = mxs_nop_release,
+ },
+ },
+};
+#endif
+
+#if defined(CONFIG_I2C_MXS) || \
+ defined(CONFIG_I2C_MXS_MODULE)
+static struct platform_device mxs_i2c[] = {
+#if defined(CONFIG_I2C_MXS_SELECT0)
+ {
+ .name = "mxs-i2c",
+ .id = 0,
+ .dev = {
+ .dma_mask = &common_dmamask,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ .release = mxs_nop_release,
+ },
+ },
+#endif
+#if defined(CONFIG_I2C_MXS_SELECT1)
+ {
+ .name = "mxs-i2c",
+ .id = 1,
+ .dev = {
+ .dma_mask = &common_dmamask,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ .release = mxs_nop_release,
+ },
+ },
+#endif
+};
+#endif
+
+#if defined(CONFIG_MTD_NAND_GPMI_NFC) || \
+ defined(CONFIG_MTD_NAND_GPMI_NFC_MODULE)
+static struct platform_device gpmi_nfc = {
+ .name = GPMI_NFC_DRIVER_NAME,
+ .id = 0,
+ .dev = {
+ .dma_mask = &common_dmamask,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ .release = mxs_nop_release,
+ },
+};
+#endif
+
+#if defined(CONFIG_MMC_MXS) || \
+ defined(CONFIG_MMC_MXS_MODULE)
+static struct platform_device mxs_mmc[] = {
+ {
+ .name = "mxs-mmc",
+ .id = 0,
+ .dev = {
+ .dma_mask = &common_dmamask,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ .release = mxs_nop_release,
+ },
+ },
+ {
+ .name = "mxs-mmc",
+ .id = 1,
+ .dev = {
+ .dma_mask = &common_dmamask,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ .release = mxs_nop_release,
+ },
+ },
+};
+#endif
+
+#if defined(CONFIG_SPI_MXS) || defined(CONFIG_SPI_MXS_MODULE)
+static struct platform_device mxs_spi[] = {
+ {
+ .name = "mxs-spi",
+ .id = 0,
+ .dev = {
+ .dma_mask = &common_dmamask,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ .release = mxs_nop_release,
+ },
+ },
+};
+#endif
+
+#if defined(CONFIG_MXS_WATCHDOG) || defined(CONFIG_MXS_WATCHDOG_MODULE)
+static struct platform_device mxs_wdt = {
+ .name = "mxs-wdt",
+ .id = 0,
+ .dev = {
+ .release = mxs_nop_release,
+ },
+};
+#endif
+
+#if defined(CONFIG_FEC) || \
+ defined(CONFIG_FEC_MODULE)
+static struct platform_device mxs_fec[] = {
+ {
+ .name = "fec",
+ .id = 0,
+ .dev = {
+ .release = mxs_nop_release,
+ },
+ },
+ {
+ .name = "fec",
+ .id = 1,
+ .dev = {
+ .release = mxs_nop_release,
+ },
+ },
+};
+#endif
+
+#if defined(CONFIG_FEC_L2SWITCH)
+static struct platform_device mxs_l2switch[] = {
+ {
+ .name = "mxs-l2switch",
+ .id = 0,
+ .dev = {
+ .release = mxs_nop_release,
+ },
+ },
+};
+#endif
+
+#if defined(CONFIG_FB_MXS) || defined(CONFIG_FB_MXS_MODULE)
+static struct platform_device mxs_fb = {
+ .name = "mxs-fb",
+ .id = 0,
+ .dev = {
+ .dma_mask = &common_dmamask,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ .release = mxs_nop_release,
+ },
+};
+#endif
+
+#if defined(CONFIG_BACKLIGHT_MXS) || \
+ defined(CONFIG_BACKLIGHT_MXS_MODULE)
+struct platform_device mxs_bl = {
+ .name = "mxs-bl",
+ .id = 0,
+ .dev = {
+ .release = mxs_nop_release,
+ },
+};
+#endif
+
+#if defined(CONFIG_VIDEO_MXS_PXP) || \
+ defined(CONFIG_VIDEO_MXS_PXP_MODULE)
+static struct platform_device mxs_pxp = {
+ .name = "mxs-pxp",
+ .id = 0,
+ .dev = {
+ .release = mxs_nop_release,
+ .dma_mask = &common_dmamask,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ },
+};
+#endif
+
+#if defined(CONFIG_RTC_DRV_MXS) || defined(CONFIG_RTC_DRV_MXS_MODULE)
+static struct platform_device mxs_rtc = {
+ .name = "mxs-rtc",
+ .id = 0,
+ .dev = {
+ .release = mxs_nop_release,
+ },
+};
+#endif
+
+#ifdef CONFIG_MXS_LRADC
+static struct platform_device mxs_lradc = {
+ .name = "mxs-lradc",
+ .id = 0,
+ .dev = {
+ .release = mxs_nop_release,
+ },
+};
+#endif
+
+#if defined(CONFIG_KEYBOARD_MXS) || defined(CONFIG_KEYBOARD_MXS_MODULE)
+static struct platform_device mxs_kbd = {
+ .name = "mxs-kbd",
+ .id = 0,
+ .dev = {
+ .release = mxs_nop_release,
+ },
+};
+#endif
+
+#if defined(CONFIG_TOUCHSCREEN_MXS) || defined(CONFIG_TOUCHSCREEN_MXS_MODULE)
+static struct platform_device mxs_ts = {
+ .name = "mxs-ts",
+ .id = 0,
+ .dev = {
+ .release = mxs_nop_release,
+ },
+};
+#endif
+
+#if defined(CONFIG_SERIAL_MXS_AUART) || defined(CONFIG_SERIAL_MXS_AUART_MODULE)
+static struct platform_device mxs_auart[] = {
+#ifdef CONFIG_MXS_AUART0_DEVICE_ENABLE
+ {
+ .name = "mxs-auart",
+ .id = 0,
+ .dev = {
+ .release = mxs_nop_release,
+ .dma_mask = &common_dmamask,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ },
+ },
+#endif
+#ifdef CONFIG_MXS_AUART1_DEVICE_ENABLE
+ {
+ .name = "mxs-auart",
+ .id = 1,
+ .dev = {
+ .release = mxs_nop_release,
+ .dma_mask = &common_dmamask,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ },
+ },
+#endif
+#ifdef CONFIG_MXS_AUART2_DEVICE_ENABLE
+ {
+ .name = "mxs-auart",
+ .id = 2,
+ .dev = {
+ .release = mxs_nop_release,
+ .dma_mask = &common_dmamask,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ },
+ },
+#endif
+#ifdef CONFIG_MXS_AUART3_DEVICE_ENABLE
+ {
+ .name = "mxs-auart",
+ .id = 3,
+ .dev = {
+ .release = mxs_nop_release,
+ .dma_mask = &common_dmamask,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ },
+ },
+#endif
+#ifdef CONFIG_MXS_AUART4_DEVICE_ENABLE
+ {
+ .name = "mxs-auart",
+ .id = 4,
+ .dev = {
+ .release = mxs_nop_release,
+ .dma_mask = &common_dmamask,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ },
+ },
+#endif
+};
+#endif
+
+#if defined(CONFIG_LEDS_MXS) || defined(CONFIG_LEDS_MXS_MODULE)
+static struct platform_device mxs_led = {
+ .name = "mxs-leds",
+ .id = 0,
+ .dev = {
+ .release = mxs_nop_release,
+ },
+};
+#endif
+
+#if defined(CONFIG_CAN_FLEXCAN) || \
+ defined(CONFIG_CAN_FLEXCAN_MODULE)
+static struct platform_device mxs_flexcan[] = {
+ {
+ .name = "FlexCAN",
+ .id = 0,
+ .dev = {
+ .release = mxs_nop_release,
+ },
+ },
+ {
+ .name = "FlexCAN",
+ .id = 1,
+ .dev = {
+ .release = mxs_nop_release,
+ },
+ },
+};
+#endif
+
+#if defined(CONFIG_CRYPTO_DEV_DCP)
+static struct platform_device mxs_dcp = {
+ .name = "dcp",
+ .id = 0,
+ .dev = {
+ .release = mxs_nop_release,
+ .dma_mask = &common_dmamask,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ },
+};
+#endif
+
+#if defined(CONFIG_BATTERY_MXS)
+static struct platform_device mxs_battery = {
+ .name = "mxs-battery",
+ .id = 0,
+ .dev = {
+ .release = mxs_nop_release,
+ } ,
+};
+#endif
+
+#if defined(CONFIG_SND_SOC_SGTL5000) || \
+ defined(CONFIG_SND_SOC_SGTL5000_MODULE)
+static struct platform_device mxs_sgtl5000[] = {
+ {
+ .name = "mxs-sgtl5000",
+ .id = 0,
+ .dev = {
+ .release = mxs_nop_release,
+ },
+ },
+};
+#endif
+
+#if defined(CONFIG_MXS_VIIM) || defined(CONFIG_MXS_VIIM_MODULE)
+struct platform_device mxs_viim = {
+ .name = "mxs_viim",
+ .id = 0,
+ .dev = {
+ .release = mxs_nop_release,
+ },
+};
+#endif
+
+#if defined(CONFIG_SND_SOC_MXS_SPDIF) || \
+ defined(CONFIG_SND_SOC_MXS_SPDIF_MODULE)
+static struct platform_device mxs_spdif[] = {
+ {
+ .name = "mxs-spdif",
+ .id = 0,
+ .dev = {
+ .release = mxs_nop_release,
+ },
+ },
+};
+#endif
+
+#if defined(CONFIG_SND_MXS_SOC_ADC) || \
+ defined(CONFIG_SND_MXS_SOC_ADC_MODULE)
+static struct platform_device mxs_adc = {
+ .name = "mxs-adc-audio",
+ .id = 0,
+ .dev = {
+ .release = mxs_nop_release,
+ },
+};
+#endif
+
+static struct platform_device busfreq_device = {
+ .name = "busfreq",
+ .id = 0,
+ .dev = {
+ .release = mxs_nop_release,
+ },
+};
+
+#ifdef CONFIG_MXS_PERSISTENT
+static struct platform_device mxs_persistent = {
+ .name = "mxs-persistent",
+ .id = 0,
+ .dev = {
+ .release = mxs_nop_release,
+ },
+};
+#endif
+
+#ifdef CONFIG_MXS_PERFMON
+static struct platform_device mxs_perfmon = {
+ .name = "mxs-perfmon",
+ .id = 0,
+ .dev = {
+ .release = mxs_nop_release,
+ },
+};
+#endif
+
+#ifdef CONFIG_FSL_OTP
+static struct platform_device otp_device = {
+ .name = "ocotp",
+ .id = 0,
+ .dev = {
+ .release = mxs_nop_release,
+ },
+};
+#endif
+
+static inline void mxs_init_busfreq(void)
+{
+ (void)platform_device_register(&busfreq_device);
+}
+
+static struct mxs_dev_lookup dev_lookup[] = {
+#if defined(CONFIG_SERIAL_MXS_DUART) || \
+ defined(CONFIG_SERIAL_MXS_DUART_MODULE)
+ {
+ .name = "mxs-duart",
+ .size = 1,
+ .pdev = &mxs_duart,
+ },
+#endif
+#if defined(CONFIG_MXS_DMA_ENGINE)
+ {
+ .name = "mxs-dma",
+ .size = ARRAY_SIZE(mxs_dma),
+ .pdev = mxs_dma,
+ },
+#endif
+
+#if defined(CONFIG_I2C_MXS) || \
+ defined(CONFIG_I2C_MXS_MODULE)
+ {
+ .name = "mxs-i2c",
+ .size = ARRAY_SIZE(mxs_i2c),
+ .pdev = mxs_i2c,
+ },
+#endif
+
+#if defined(CONFIG_MTD_NAND_GPMI_NFC) || \
+ defined(CONFIG_MTD_NAND_GPMI_NFC_MODULE)
+ {
+ .name = GPMI_NFC_DRIVER_NAME,
+ .size = 1,
+ .pdev = &gpmi_nfc,
+ },
+#endif
+
+#if defined(CONFIG_MMC_MXS) || \
+ defined(CONFIG_MMC_MXS_MODULE)
+ {
+ .name = "mxs-mmc",
+ .size = ARRAY_SIZE(mxs_mmc),
+ .pdev = mxs_mmc,
+ },
+#endif
+
+#if defined(CONFIG_SPI_MXS) || defined(CONFIG_SPI_MXS_MODULE)
+ {
+ .name = "mxs-spi",
+ .size = ARRAY_SIZE(mxs_spi),
+ .pdev = mxs_spi,
+ },
+#endif
+
+#if defined(CONFIG_MXS_WATCHDOG) || defined(CONFIG_MXS_WATCHDOG_MODULE)
+ {
+ .name = "mxs-wdt",
+ .size = 1,
+ .pdev = &mxs_wdt,
+ },
+#endif
+
+#if defined(CONFIG_RTC_DRV_MXS) || defined(CONFIG_RTC_DRV_MXS_MODULE)
+ {
+ .name = "mxs-rtc",
+ .size = 1,
+ .pdev = &mxs_rtc,
+ },
+#endif
+
+#if defined(CONFIG_MXS_PERSISTENT)
+ {
+ .name = "mxs-persistent",
+ .size = 1,
+ .pdev = &mxs_persistent,
+ },
+#endif
+
+#if defined(CONFIG_MXS_PERFMON)
+ {
+ .name = "mxs-perfmon",
+ .size = 1,
+ .pdev = &mxs_perfmon,
+ },
+#endif
+
+#if defined(CONFIG_FSL_OTP)
+ {
+ .name = "ocotp",
+ .size = 1,
+ .pdev = &otp_device,
+ },
+#endif
+
+#if defined(CONFIG_FB_MXS) || defined(CONFIG_FB_MXS_MODULE)
+ {
+ .name = "mxs-fb",
+ .size = 1,
+ .pdev = &mxs_fb,
+ },
+#endif
+#if defined(CONFIG_BACKLIGHT_MXS) || \
+ defined(CONFIG_BACKLIGHT_MXS_MODULE)
+ {
+ .name = "mxs-bl",
+ .size = 1,
+ .pdev = &mxs_bl,
+ },
+#endif
+
+#if defined(CONFIG_VIDEO_MXS_PXP) || \
+ defined(CONFIG_VIDEO_MXS_PXP_MODULE)
+ {
+ .name = "mxs-pxp",
+ .size = 1,
+ .pdev = &mxs_pxp,
+ },
+#endif
+
+#if defined(CONFIG_MXS_VIIM) || defined(CONFIG_MXS_VIIM_MODULE)
+ {
+ .name = "mxs_viim",
+ .size = 1,
+ .pdev = &mxs_viim,
+ },
+#endif
+
+#if defined(CONFIG_FEC) || defined(CONFIG_FEC_MODULE)
+ {
+ .name = "mxs-fec",
+ .size = ARRAY_SIZE(mxs_fec),
+ .pdev = mxs_fec,
+ },
+#endif
+
+#if defined(CONFIG_FEC_L2SWITCH)
+ {
+ .name = "mxs-l2switch",
+ .size = ARRAY_SIZE(mxs_l2switch),
+ .pdev = mxs_l2switch,
+ },
+#endif
+
+#ifdef CONFIG_MXS_LRADC
+ {
+ .name = "mxs-lradc",
+ .size = 1,
+ .pdev = &mxs_lradc,
+ },
+#endif
+
+#if defined(CONFIG_KEYBOARD_MXS) || defined(CONFIG_KEYBOARD_MXS_MODULE)
+ {
+ .name = "mxs-kbd",
+ .size = 1,
+ .pdev = &mxs_kbd,
+ },
+#endif
+
+#if defined(CONFIG_TOUCHSCREEN_MXS) || defined(CONFIG_TOUCHSCREEN_MXS_MODULE)
+ {
+ .name = "mxs-ts",
+ .size = 1,
+ .pdev = &mxs_ts,
+ },
+#endif
+
+#if defined(CONFIG_SERIAL_MXS_AUART) || defined(CONFIG_SERIAL_MXS_AUART_MODULE)
+ {
+ .name = "mxs-auart",
+ .size = ARRAY_SIZE(mxs_auart),
+ .pdev = mxs_auart,
+ },
+#endif
+
+#if defined(CONFIG_LEDS_MXS) || defined(CONFIG_LEDS_MXS_MODULE)
+ {
+ .name = "mxs-leds",
+ .size = 1,
+ .pdev = &mxs_led,
+ },
+#endif
+
+#if defined(CONFIG_CAN_FLEXCAN) || \
+ defined(CONFIG_CAN_FLEXCAN_MODULE)
+ {
+ .name = "FlexCAN",
+ .size = ARRAY_SIZE(mxs_flexcan),
+ .pdev = mxs_flexcan,
+ },
+#endif
+
+#if defined(CONFIG_CRYPTO_DEV_DCP)
+ {
+ .name = "dcp",
+ .size = 1,
+ .pdev = &mxs_dcp,
+ },
+#endif
+
+#if defined(CONFIG_BATTERY_MXS)
+ {
+ .name = "mxs-battery",
+ .size = 1,
+ .pdev = &mxs_battery,
+ },
+#endif
+
+#if defined(CONFIG_SND_SOC_SGTL5000) || \
+ defined(CONFIG_SND_SOC_SGTL5000_MODULE)
+ {
+ .name = "mxs-sgtl5000",
+ .size = ARRAY_SIZE(mxs_sgtl5000),
+ .pdev = mxs_sgtl5000,
+ },
+#endif
+
+#if defined(CONFIG_SND_SOC_MXS_SPDIF) || \
+ defined(CONFIG_SND_SOC_MXS_SPDIF_MODULE)
+ {
+ .name = "mxs-spdif",
+ .size = ARRAY_SIZE(mxs_spdif),
+ .pdev = mxs_spdif,
+ },
+#endif
+
+#if defined(CONFIG_SND_MXS_SOC_ADC) || \
+ defined(CONFIG_SND_MXS_SOC_ADC_MODULE)
+ {
+ .name = "mxs-adc",
+ .size = 1,
+ .pdev = &mxs_adc,
+ },
+#endif
+
+};
+
+struct platform_device *mxs_get_device(char *name, int id)
+{
+ int i, j;
+ struct mxs_dev_lookup *lookup;
+ struct platform_device *pdev = (struct platform_device *)-ENODEV;
+ if (name == NULL || id < 0 || IS_ERR(name))
+ return (struct platform_device *)-EINVAL;
+
+ mutex_lock(&device_mutex);
+ for (i = 0; i < ARRAY_SIZE(dev_lookup); i++) {
+ lookup = &dev_lookup[i];
+ if (!strcmp(name, lookup->name)) {
+ if (test_bit(0, &lookup->lock)) {
+ pdev = (struct platform_device *)-EBUSY;
+ break;
+ }
+
+ if (id >= lookup->size)
+ break;
+ for (j = 0; j < lookup->size; j++) {
+ if (id == (lookup->pdev[j]).id) {
+ pdev = &lookup->pdev[j];
+ break;
+ }
+ }
+ break;
+ }
+
+ }
+ mutex_unlock(&device_mutex);
+ return pdev;
+}
+
+struct mxs_dev_lookup *mxs_get_devices(char *name)
+{
+ int i;
+ struct mxs_dev_lookup *lookup;
+ if (name == NULL || IS_ERR(name))
+ return (struct mxs_dev_lookup *)-EINVAL;
+
+ mutex_lock(&device_mutex);
+ for (i = 0; i < ARRAY_SIZE(dev_lookup); i++) {
+ lookup = &dev_lookup[i];
+ if (!strcmp(name, lookup->name)) {
+ if (test_and_set_bit(0, &lookup->lock))
+ lookup = (struct mxs_dev_lookup *)-EBUSY;
+ mutex_unlock(&device_mutex);
+ return lookup;
+ }
+
+ }
+ mutex_unlock(&device_mutex);
+ return (struct mxs_dev_lookup *)-ENODEV;
+}
+
+int mxs_device_init(void)
+{
+ int i, ret = 0;
+ struct list_head *p, *n;
+ struct device *dev;
+ struct platform_device *pdev;
+ mutex_lock(&device_mutex);
+ mxs_device_done = 1;
+ mutex_unlock(&device_mutex);
+
+ for (i = 0; i < ARRAY_SIZE(mxs_device_level); i++) {
+ list_for_each_safe(p, n, mxs_device_level + i) {
+ dev = list_entry(p, struct device, devres_head);
+ list_del(p);
+ pdev = container_of(dev, struct platform_device, dev);
+ ret |= platform_device_register(pdev);
+ }
+ }
+
+#if defined(CONFIG_BACKLIGHT_MXS) || \
+ defined(CONFIG_BACKLIGHT_MXS_MODULE)
+ platform_device_register(&mxs_bl);
+#endif
+
+ mxs_init_busfreq();
+ return ret;
+}
+
+device_initcall(mxs_device_init);
diff --git a/arch/arm/plat-mxs/dma-apbh.c b/arch/arm/plat-mxs/dma-apbh.c
new file mode 100644
index 000000000000..e7fb96003f6e
--- /dev/null
+++ b/arch/arm/plat-mxs/dma-apbh.c
@@ -0,0 +1,243 @@
+/*
+ * Copyright (C) 2009-2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/list.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/dmapool.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+
+#include <mach/hardware.h>
+#include <mach/device.h>
+#include <mach/dmaengine.h>
+
+#include <mach/regs-apbh.h>
+#ifndef BM_APBH_CTRL0_APB_BURST_EN
+#define BM_APBH_CTRL0_APB_BURST_EN BM_APBH_CTRL0_APB_BURST4_EN
+#endif
+
+static int mxs_dma_apbh_enable(struct mxs_dma_chan *pchan, unsigned int chan)
+{
+ unsigned int sem;
+ struct mxs_dma_device *pdev = pchan->dma;
+ struct mxs_dma_desc *pdesc;
+
+ pdesc = list_first_entry(&pchan->active, struct mxs_dma_desc, node);
+ if (pdesc == NULL)
+ return -EFAULT;
+
+ sem = __raw_readl(pdev->base + HW_APBH_CHn_SEMA(chan));
+ sem = (sem & BM_APBH_CHn_SEMA_PHORE) >> BP_APBH_CHn_SEMA_PHORE;
+ if (pchan->flags & MXS_DMA_FLAGS_BUSY) {
+ if (pdesc->cmd.cmd.bits.chain == 0)
+ return 0;
+ if (sem < 2) {
+ if (!sem)
+ return 0;
+ pdesc = list_entry(pdesc->node.next,
+ struct mxs_dma_desc, node);
+ __raw_writel(mxs_dma_cmd_address(pdesc),
+ pdev->base + HW_APBH_CHn_NXTCMDAR(chan));
+ }
+ sem = pchan->pending_num;
+ pchan->pending_num = 0;
+ __raw_writel(BF_APBH_CHn_SEMA_INCREMENT_SEMA(sem),
+ pdev->base + HW_APBH_CHn_SEMA(chan));
+ pchan->active_num += sem;
+ return 0;
+ }
+ pchan->active_num += pchan->pending_num;
+ pchan->pending_num = 0;
+ __raw_writel(mxs_dma_cmd_address(pdesc),
+ pdev->base + HW_APBH_CHn_NXTCMDAR(chan));
+ __raw_writel(pchan->active_num, pdev->base + HW_APBH_CHn_SEMA(chan));
+ __raw_writel(1 << chan, pdev->base + HW_APBH_CTRL0_CLR);
+ return 0;
+}
+
+static void mxs_dma_apbh_disable(struct mxs_dma_chan *pchan, unsigned int chan)
+{
+ struct mxs_dma_device *pdev = pchan->dma;
+ __raw_writel(1 << (chan + BP_APBH_CTRL0_CLKGATE_CHANNEL),
+ pdev->base + HW_APBH_CTRL0_SET);
+}
+
+static void mxs_dma_apbh_reset(struct mxs_dma_device *pdev, unsigned int chan)
+{
+#ifdef CONFIG_ARCH_MX28
+ __raw_writel(1 << (chan + BP_APBH_CHANNEL_CTRL_RESET_CHANNEL),
+ pdev->base + HW_APBH_CHANNEL_CTRL_SET);
+#endif
+
+#ifdef CONFIG_ARCH_MX23
+ __raw_writel(1 << (chan + BP_APBH_CTRL0_RESET_CHANNEL),
+ pdev->base + HW_APBH_CTRL0_SET);
+#endif
+}
+
+static void mxs_dma_apbh_freeze(struct mxs_dma_device *pdev, unsigned int chan)
+{
+#ifdef CONFIG_ARCH_MX28
+ __raw_writel(1 << chan, pdev->base + HW_APBH_CHANNEL_CTRL_SET);
+#endif
+
+#ifdef CONFIG_ARCH_MX23
+ __raw_writel(1 << (chan + BP_APBH_CTRL0_FREEZE_CHANNEL),
+ pdev->base + HW_APBH_CTRL0_SET);
+#endif
+}
+
+static void
+mxs_dma_apbh_unfreeze(struct mxs_dma_device *pdev, unsigned int chan)
+{
+#ifdef CONFIG_ARCH_MX28
+ __raw_writel(1 << chan, pdev->base + HW_APBH_CHANNEL_CTRL_CLR);
+#endif
+
+#ifdef CONFIG_ARCH_MX23
+ __raw_writel(1 << (chan + BP_APBH_CTRL0_FREEZE_CHANNEL),
+ pdev->base + HW_APBH_CTRL0_CLR);
+#endif
+
+}
+
+static void mxs_dma_apbh_info(struct mxs_dma_device *pdev,
+ unsigned int chan, struct mxs_dma_info *info)
+{
+ unsigned int reg;
+ reg = __raw_readl(pdev->base + HW_APBH_CTRL2);
+ info->status = reg >> chan;
+ info->buf_addr = __raw_readl(pdev->base + HW_APBH_CHn_BAR(chan));
+}
+
+static int
+mxs_dma_apbh_read_semaphore(struct mxs_dma_device *pdev, unsigned int chan)
+{
+ unsigned int reg;
+ reg = __raw_readl(pdev->base + HW_APBH_CHn_SEMA(chan));
+ return (reg & BM_APBH_CHn_SEMA_PHORE) >> BP_APBH_CHn_SEMA_PHORE;
+}
+
+static void
+mxs_dma_apbh_enable_irq(struct mxs_dma_device *pdev,
+ unsigned int chan, int enable)
+{
+ if (enable) {
+ __raw_writel(1 << (chan + 16), pdev->base + HW_APBH_CTRL1_SET);
+ } else {
+ __raw_writel(1 << (chan + 16), pdev->base + HW_APBH_CTRL1_CLR);
+ }
+}
+
+static int
+mxs_dma_apbh_irq_is_pending(struct mxs_dma_device *pdev, unsigned int chan)
+{
+ unsigned int reg;
+ reg = __raw_readl(pdev->base + HW_APBH_CTRL1);
+ reg |= __raw_readl(pdev->base + HW_APBH_CTRL2);
+ return reg & (1 << chan);
+}
+
+static void mxs_dma_apbh_ack_irq(struct mxs_dma_device *pdev, unsigned int chan)
+{
+ __raw_writel(1 << chan, pdev->base + HW_APBH_CTRL1_CLR);
+ __raw_writel(1 << chan, pdev->base + HW_APBH_CTRL2_CLR);
+}
+
+static struct mxs_dma_device mxs_dma_apbh = {
+ .name = "mxs-dma-apbh",
+ .enable = mxs_dma_apbh_enable,
+ .disable = mxs_dma_apbh_disable,
+ .reset = mxs_dma_apbh_reset,
+ .freeze = mxs_dma_apbh_freeze,
+ .unfreeze = mxs_dma_apbh_unfreeze,
+ .info = mxs_dma_apbh_info,
+ .read_semaphore = mxs_dma_apbh_read_semaphore,
+ .enable_irq = mxs_dma_apbh_enable_irq,
+ .irq_is_pending = mxs_dma_apbh_irq_is_pending,
+ .ack_irq = mxs_dma_apbh_ack_irq,
+};
+
+static int __devinit dma_apbh_probe(struct platform_device *pdev)
+{
+ int i;
+ struct resource *res;
+ struct mxs_dma_plat_data *plat;
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res)
+ return -ENOMEM;
+ mxs_dma_apbh.base = IO_ADDRESS(res->start);
+ __raw_writel(BM_APBH_CTRL0_SFTRST,
+ mxs_dma_apbh.base + HW_APBH_CTRL0_CLR);
+ for (i = 0; i < 10000; i++) {
+ if (!(__raw_readl(mxs_dma_apbh.base + HW_APBH_CTRL0_CLR) &
+ BM_APBH_CTRL0_SFTRST))
+ break;
+ udelay(2);
+ }
+ if (i >= 10000)
+ return -ETIME;
+ __raw_writel(BM_APBH_CTRL0_CLKGATE,
+ mxs_dma_apbh.base + HW_APBH_CTRL0_CLR);
+
+ plat = (struct mxs_dma_plat_data *)pdev->dev.platform_data;
+ if (!plat)
+ return -ENODEV;
+ if (plat->burst8)
+ __raw_writel(BM_APBH_CTRL0_AHB_BURST8_EN,
+ mxs_dma_apbh.base + HW_APBH_CTRL0_SET);
+ else
+ __raw_writel(BM_APBH_CTRL0_AHB_BURST8_EN,
+ mxs_dma_apbh.base + HW_APBH_CTRL0_CLR);
+
+ if (plat->burst)
+ __raw_writel(BM_APBH_CTRL0_APB_BURST_EN,
+ mxs_dma_apbh.base + HW_APBH_CTRL0_SET);
+ else
+ __raw_writel(BM_APBH_CTRL0_APB_BURST_EN,
+ mxs_dma_apbh.base + HW_APBH_CTRL0_CLR);
+
+ mxs_dma_apbh.pdev = pdev;
+ mxs_dma_apbh.chan_base = plat->chan_base;
+ mxs_dma_apbh.chan_num = plat->chan_num;
+ platform_set_drvdata(pdev, &mxs_dma_apbh);
+ return mxs_dma_device_register(&mxs_dma_apbh);
+}
+
+static int __devexit dma_apbh_remove(struct platform_device *pdev)
+{
+ return 0;
+}
+
+static struct platform_driver dma_apbh_driver = {
+ .probe = dma_apbh_probe,
+ .remove = __devexit_p(dma_apbh_remove),
+ .driver = {
+ .name = "mxs-dma-apbh"},
+};
+
+static int __init mxs_dma_apbh_init(void)
+{
+ return platform_driver_register(&dma_apbh_driver);
+}
+
+fs_initcall(mxs_dma_apbh_init);
diff --git a/arch/arm/plat-mxs/dma-apbx.c b/arch/arm/plat-mxs/dma-apbx.c
new file mode 100644
index 000000000000..6d77a6933d98
--- /dev/null
+++ b/arch/arm/plat-mxs/dma-apbx.c
@@ -0,0 +1,205 @@
+/*
+ * Copyright (C) 2009-2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/list.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/dmapool.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+
+#include <mach/hardware.h>
+#include <mach/device.h>
+#include <mach/dmaengine.h>
+
+#include "regs-apbx.h"
+
+static int mxs_dma_apbx_enable(struct mxs_dma_chan *pchan, unsigned int chan)
+{
+ unsigned int sem;
+ struct mxs_dma_device *pdev = pchan->dma;
+ struct mxs_dma_desc *pdesc;
+
+ pdesc = list_first_entry(&pchan->active, struct mxs_dma_desc, node);
+ if (pdesc == NULL)
+ return -EFAULT;
+ sem = __raw_readl(pdev->base + HW_APBX_CHn_SEMA(chan));
+ sem = (sem & BM_APBX_CHn_SEMA_PHORE) >> BP_APBX_CHn_SEMA_PHORE;
+ if (pchan->flags & MXS_DMA_FLAGS_BUSY) {
+ if (pdesc->cmd.cmd.bits.chain == 0)
+ return 0;
+ if (sem < 2) {
+ if (!sem)
+ return 0;
+ pdesc = list_entry(pdesc->node.next,
+ struct mxs_dma_desc, node);
+ __raw_writel(mxs_dma_cmd_address(pdesc),
+ pdev->base + HW_APBX_CHn_NXTCMDAR(chan));
+ }
+ sem = pchan->pending_num;
+ pchan->pending_num = 0;
+ __raw_writel(BF_APBX_CHn_SEMA_INCREMENT_SEMA(sem),
+ pdev->base + HW_APBX_CHn_SEMA(chan));
+ pchan->active_num += sem;
+ return 0;
+ }
+ pchan->active_num += pchan->pending_num;
+ pchan->pending_num = 0;
+ __raw_writel(mxs_dma_cmd_address(pdesc),
+ pdev->base + HW_APBX_CHn_NXTCMDAR(chan));
+ __raw_writel(pchan->active_num, pdev->base + HW_APBX_CHn_SEMA(chan));
+ return 0;
+}
+
+static void mxs_dma_apbx_disable(struct mxs_dma_chan *pchan, unsigned int chan)
+{
+ struct mxs_dma_device *pdev = pchan->dma;
+ __raw_writel(0, pdev->base + HW_APBX_CHn_SEMA(chan));
+}
+
+static void mxs_dma_apbx_reset(struct mxs_dma_device *pdev, unsigned int chan)
+{
+ __raw_writel(1 << (chan + BP_APBX_CHANNEL_CTRL_RESET_CHANNEL),
+ pdev->base + HW_APBX_CHANNEL_CTRL_SET);
+}
+
+static void mxs_dma_apbx_freeze(struct mxs_dma_device *pdev, unsigned int chan)
+{
+ __raw_writel(1 << chan, pdev->base + HW_APBX_CHANNEL_CTRL_SET);
+}
+
+static void
+mxs_dma_apbx_unfreeze(struct mxs_dma_device *pdev, unsigned int chan)
+{
+ __raw_writel(1 << chan, pdev->base + HW_APBX_CHANNEL_CTRL_CLR);
+}
+
+static void mxs_dma_apbx_info(struct mxs_dma_device *pdev,
+ unsigned int chan, struct mxs_dma_info *info)
+{
+ unsigned int reg;
+ reg = __raw_readl(pdev->base + HW_APBX_CTRL2);
+ info->status = reg >> chan;
+ info->buf_addr = __raw_readl(pdev->base + HW_APBX_CHn_BAR(chan));
+ reg = __raw_readl(pdev->base + HW_APBX_CHn_CMD(chan));
+ info->xfer_count = (reg & BM_APBX_CHn_CMD_XFER_COUNT) >> \
+ BP_APBX_CHn_CMD_XFER_COUNT;
+}
+
+static int
+mxs_dma_apbx_read_semaphore(struct mxs_dma_device *pdev, unsigned int chan)
+{
+ unsigned int reg;
+ reg = __raw_readl(pdev->base + HW_APBX_CHn_SEMA(chan));
+ return (reg & BM_APBX_CHn_SEMA_PHORE) >> BP_APBX_CHn_SEMA_PHORE;
+}
+
+static void
+mxs_dma_apbx_enable_irq(struct mxs_dma_device *pdev,
+ unsigned int chan, int enable)
+{
+ if (enable) {
+ __raw_writel(1 << (chan + 16), pdev->base + HW_APBX_CTRL1_SET);
+ } else {
+ __raw_writel(1 << (chan + 16), pdev->base + HW_APBX_CTRL1_CLR);
+ }
+}
+
+static int
+mxs_dma_apbx_irq_is_pending(struct mxs_dma_device *pdev, unsigned int chan)
+{
+ unsigned int reg;
+ reg = __raw_readl(pdev->base + HW_APBX_CTRL1);
+ reg |= __raw_readl(pdev->base + HW_APBX_CTRL2);
+ return reg & (1 << chan);
+}
+
+static void mxs_dma_apbx_ack_irq(struct mxs_dma_device *pdev, unsigned int chan)
+{
+ __raw_writel(1 << chan, pdev->base + HW_APBX_CTRL1_CLR);
+ __raw_writel(1 << chan, pdev->base + HW_APBX_CTRL2_CLR);
+}
+
+static struct mxs_dma_device mxs_dma_apbx = {
+ .name = "mxs-dma-apbx",
+ .enable = mxs_dma_apbx_enable,
+ .disable = mxs_dma_apbx_disable,
+ .reset = mxs_dma_apbx_reset,
+ .freeze = mxs_dma_apbx_freeze,
+ .unfreeze = mxs_dma_apbx_unfreeze,
+ .info = mxs_dma_apbx_info,
+ .read_semaphore = mxs_dma_apbx_read_semaphore,
+ .enable_irq = mxs_dma_apbx_enable_irq,
+ .irq_is_pending = mxs_dma_apbx_irq_is_pending,
+ .ack_irq = mxs_dma_apbx_ack_irq,
+};
+
+static int __devinit dma_apbx_probe(struct platform_device *pdev)
+{
+ int i;
+ struct resource *res;
+ struct mxs_dma_plat_data *plat;
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res)
+ return -ENOMEM;
+ mxs_dma_apbx.base = IO_ADDRESS(res->start);
+ __raw_writel(BM_APBX_CTRL0_SFTRST,
+ mxs_dma_apbx.base + HW_APBX_CTRL0_CLR);
+ for (i = 0; i < 10000; i++) {
+ if (!(__raw_readl(mxs_dma_apbx.base + HW_APBX_CTRL0_CLR) &
+ BM_APBX_CTRL0_SFTRST))
+ break;
+ udelay(2);
+ }
+ if (i >= 10000)
+ return -ETIME;
+ __raw_writel(BM_APBX_CTRL0_CLKGATE,
+ mxs_dma_apbx.base + HW_APBX_CTRL0_CLR);
+
+ plat = (struct mxs_dma_plat_data *)pdev->dev.platform_data;
+ if (!plat)
+ return -ENODEV;
+
+ mxs_dma_apbx.pdev = pdev;
+ mxs_dma_apbx.chan_base = plat->chan_base;
+ mxs_dma_apbx.chan_num = plat->chan_num;
+ platform_set_drvdata(pdev, &mxs_dma_apbx);
+ return mxs_dma_device_register(&mxs_dma_apbx);
+}
+
+static int __devexit dma_apbx_remove(struct platform_device *pdev)
+{
+ return 0;
+}
+
+static struct platform_driver dma_apbx_driver = {
+ .probe = dma_apbx_probe,
+ .remove = __devexit_p(dma_apbx_remove),
+ .driver = {
+ .name = "mxs-dma-apbx"},
+};
+
+static int __init mxs_dma_apbx_init(void)
+{
+ return platform_driver_register(&dma_apbx_driver);
+}
+
+fs_initcall(mxs_dma_apbx_init);
diff --git a/arch/arm/plat-mxs/dmaengine.c b/arch/arm/plat-mxs/dmaengine.c
new file mode 100644
index 000000000000..2a41644d2669
--- /dev/null
+++ b/arch/arm/plat-mxs/dmaengine.c
@@ -0,0 +1,656 @@
+/*
+ * Copyright (C) 2009-2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/list.h>
+#include <linux/device.h>
+#include <linux/dmapool.h>
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+#include <linux/mutex.h>
+#include <linux/spinlock.h>
+#include <linux/io.h>
+
+#include <mach/dma.h>
+#include <mach/dmaengine.h>
+
+static void *mxs_dma_pool;
+static int mxs_dma_alignment = MXS_DMA_ALIGNMENT;
+
+/*
+ * The mutex that arbitrates access to the array of structures that represent
+ * all the DMA channels in the system (see mxs_dma_channels, below).
+ */
+
+static DEFINE_MUTEX(mxs_dma_mutex);
+
+/*
+ * The list of DMA drivers that manage various DMA channels. A DMA device
+ * driver registers to manage DMA channels by calling mxs_dma_device_register().
+ */
+
+static LIST_HEAD(mxs_dma_devices);
+
+/*
+ * The array of struct mxs_dma_chan that represent every DMA channel in the
+ * system. The index of the structure in the array indicates the specific DMA
+ * hardware it represents (see mach-mx28/include/mach/dma.h).
+ */
+
+static struct mxs_dma_chan mxs_dma_channels[MAX_DMA_CHANNELS];
+
+int mxs_dma_request(int channel, struct device *dev, const char *name)
+{
+ int ret = 0;
+ struct mxs_dma_chan *pchan;
+
+ if ((channel < 0) || (channel >= MAX_DMA_CHANNELS))
+ return -EINVAL;
+
+ if (!dev || !name)
+ return -EINVAL;
+ pchan = mxs_dma_channels + channel;
+ mutex_lock(&mxs_dma_mutex);
+ if ((pchan->flags & MXS_DMA_FLAGS_VALID) != MXS_DMA_FLAGS_VALID) {
+ ret = -ENODEV;
+ goto out;
+ }
+ if (pchan->flags & MXS_DMA_FLAGS_ALLOCATED) {
+ ret = -EBUSY;
+ goto out;
+ }
+ pchan->flags |= MXS_DMA_FLAGS_ALLOCATED;
+ pchan->name = name;
+ pchan->dev = (unsigned long)dev;
+ pchan->active_num = 0;
+ pchan->pending_num = 0;
+ spin_lock_init(&pchan->lock);
+ INIT_LIST_HEAD(&pchan->active);
+ INIT_LIST_HEAD(&pchan->done);
+out:
+ mutex_unlock(&mxs_dma_mutex);
+ return ret;
+}
+EXPORT_SYMBOL(mxs_dma_request);
+
+void mxs_dma_release(int channel, struct device *dev)
+{
+ struct mxs_dma_chan *pchan;
+ if ((channel < 0) || (channel >= MAX_DMA_CHANNELS))
+ return;
+ pchan = mxs_dma_channels + channel;
+
+ if (!(pchan->flags & MXS_DMA_FLAGS_ALLOCATED))
+ return;
+
+ if (pchan->flags & MXS_DMA_FLAGS_BUSY)
+ return;
+
+ if (pchan->dev != (unsigned long)dev)
+ return;
+
+ mutex_lock(&mxs_dma_mutex);
+ pchan->dev = 0;
+ pchan->active_num = 0;
+ pchan->pending_num = 0;
+ pchan->flags &= ~MXS_DMA_FLAGS_ALLOCATED;
+ mutex_unlock(&mxs_dma_mutex);
+}
+EXPORT_SYMBOL(mxs_dma_release);
+
+int mxs_dma_enable(int channel)
+{
+ int ret = 0;
+ unsigned long flags;
+ struct mxs_dma_chan *pchan;
+ struct mxs_dma_device *pdma;
+ if ((channel < 0) || (channel >= MAX_DMA_CHANNELS))
+ return -EINVAL;
+ pchan = mxs_dma_channels + channel;
+ if (!(pchan->flags & MXS_DMA_FLAGS_ALLOCATED))
+ return -EINVAL;
+
+ /*
+ * neednot mutex lock, this function will be called in irq context.
+ * The mutex may cause process schedule.
+ */
+ pdma = pchan->dma;
+ spin_lock_irqsave(&pchan->lock, flags);
+ if (pchan->pending_num && pdma->enable)
+ ret = pdma->enable(pchan, channel - pdma->chan_base);
+ pchan->flags |= MXS_DMA_FLAGS_BUSY;
+ spin_unlock_irqrestore(&pchan->lock, flags);
+ return ret;
+}
+EXPORT_SYMBOL(mxs_dma_enable);
+
+void mxs_dma_disable(int channel)
+{
+ unsigned long flags;
+ struct mxs_dma_chan *pchan;
+ struct mxs_dma_device *pdma;
+ if ((channel < 0) || (channel >= MAX_DMA_CHANNELS))
+ return;
+ pchan = mxs_dma_channels + channel;
+ if (!(pchan->flags & MXS_DMA_FLAGS_ALLOCATED))
+ return;
+ if (!(pchan->flags & MXS_DMA_FLAGS_BUSY))
+ return;
+ /*
+ * neednot mutex lock, this function will be called in irq context.
+ * The mutex may cause process schedule.
+ */
+ pdma = pchan->dma;
+ spin_lock_irqsave(&pchan->lock, flags);
+ if (pdma->disable)
+ pdma->disable(pchan, channel - pdma->chan_base);
+ pchan->flags &= ~MXS_DMA_FLAGS_BUSY;
+ pchan->active_num = 0;
+ pchan->pending_num = 0;
+ list_splice_init(&pchan->active, &pchan->done);
+ spin_unlock_irqrestore(&pchan->lock, flags);
+}
+EXPORT_SYMBOL(mxs_dma_disable);
+
+int mxs_dma_get_info(int channel, struct mxs_dma_info *info)
+{
+ struct mxs_dma_chan *pchan;
+ struct mxs_dma_device *pdma;
+
+ if (!info)
+ return -EINVAL;
+ if ((channel < 0) || (channel >= MAX_DMA_CHANNELS))
+ return -EINVAL;
+ pchan = mxs_dma_channels + channel;
+ if (!(pchan->flags & MXS_DMA_FLAGS_ALLOCATED))
+ return -EFAULT;
+ pdma = pchan->dma;
+ if (pdma->info)
+ pdma->info(pdma, channel - pdma->chan_base, info);
+ return 0;
+}
+EXPORT_SYMBOL(mxs_dma_get_info);
+
+int mxs_dma_cooked(int channel, struct list_head *head)
+{
+ int sem;
+ unsigned long flags;
+ struct mxs_dma_chan *pchan;
+ struct list_head *p, *q;
+ struct mxs_dma_desc *pdesc;
+ if ((channel < 0) || (channel >= MAX_DMA_CHANNELS))
+ return -EINVAL;
+ pchan = mxs_dma_channels + channel;
+ if (!(pchan->flags & MXS_DMA_FLAGS_ALLOCATED))
+ return -EINVAL;
+
+ sem = mxs_dma_read_semaphore(channel);
+ if (sem < 0)
+ return sem;
+ if (sem == pchan->active_num)
+ return 0;
+ BUG_ON(sem > pchan->active_num);
+ spin_lock_irqsave(&pchan->lock, flags);
+ list_for_each_safe(p, q, &pchan->active) {
+ if ((pchan->active_num) <= sem)
+ break;
+ pdesc = list_entry(p, struct mxs_dma_desc, node);
+ pdesc->flags &= ~MXS_DMA_DESC_READY;
+ if (head)
+ list_move_tail(p, head);
+ else
+ list_move_tail(p, &pchan->done);
+ if (pdesc->flags & MXS_DMA_DESC_LAST)
+ pchan->active_num--;
+ }
+ if (sem == 0)
+ pchan->flags &= ~MXS_DMA_FLAGS_BUSY;
+ spin_unlock_irqrestore(&pchan->lock, flags);
+
+ BUG_ON(sem != pchan->active_num);
+ return 0;
+}
+EXPORT_SYMBOL(mxs_dma_cooked);
+
+void mxs_dma_reset(int channel)
+{
+ unsigned long flags;
+ struct mxs_dma_chan *pchan;
+ struct mxs_dma_device *pdma;
+ if ((channel < 0) || (channel >= MAX_DMA_CHANNELS))
+ return;
+ pchan = mxs_dma_channels + channel;
+ if (!(pchan->flags & MXS_DMA_FLAGS_ALLOCATED))
+ return;
+ pdma = pchan->dma;
+ spin_lock_irqsave(&pchan->lock, flags);
+ if (pdma->reset)
+ pdma->reset(pdma, channel - pdma->chan_base);
+ spin_unlock_irqrestore(&pchan->lock, flags);
+}
+EXPORT_SYMBOL(mxs_dma_reset);
+
+void mxs_dma_freeze(int channel)
+{
+ unsigned long flags;
+ struct mxs_dma_chan *pchan;
+ struct mxs_dma_device *pdma;
+ if ((channel < 0) || (channel >= MAX_DMA_CHANNELS))
+ return;
+ pchan = mxs_dma_channels + channel;
+ if (!(pchan->flags & MXS_DMA_FLAGS_ALLOCATED))
+ return;
+ pdma = pchan->dma;
+ spin_lock_irqsave(&pchan->lock, flags);
+ if (pdma->freeze)
+ pdma->freeze(pdma, channel - pdma->chan_base);
+ spin_unlock_irqrestore(&pchan->lock, flags);
+}
+EXPORT_SYMBOL(mxs_dma_freeze);
+
+void mxs_dma_unfreeze(int channel)
+{
+ unsigned long flags;
+ struct mxs_dma_chan *pchan;
+ struct mxs_dma_device *pdma;
+ if ((channel < 0) || (channel >= MAX_DMA_CHANNELS))
+ return;
+ pchan = mxs_dma_channels + channel;
+ if (!(pchan->flags & MXS_DMA_FLAGS_ALLOCATED))
+ return;
+ pdma = pchan->dma;
+ spin_lock_irqsave(&pchan->lock, flags);
+ if (pdma->unfreeze)
+ pdma->unfreeze(pdma, channel - pdma->chan_base);
+ spin_unlock_irqrestore(&pchan->lock, flags);
+}
+EXPORT_SYMBOL(mxs_dma_unfreeze);
+
+int mxs_dma_read_semaphore(int channel)
+{
+ int ret = -EINVAL;
+ unsigned long flags;
+ struct mxs_dma_chan *pchan;
+ struct mxs_dma_device *pdma;
+ if ((channel < 0) || (channel >= MAX_DMA_CHANNELS))
+ return ret;
+ pchan = mxs_dma_channels + channel;
+ if (!(pchan->flags & MXS_DMA_FLAGS_ALLOCATED))
+ return ret;
+ pdma = pchan->dma;
+ spin_lock_irqsave(&pchan->lock, flags);
+ if (pdma->read_semaphore)
+ ret = pdma->read_semaphore(pdma, channel - pdma->chan_base);
+ spin_unlock_irqrestore(&pchan->lock, flags);
+ return ret;
+}
+EXPORT_SYMBOL(mxs_dma_read_semaphore);
+
+void mxs_dma_enable_irq(int channel, int en)
+{
+ unsigned long flags;
+ struct mxs_dma_chan *pchan;
+ struct mxs_dma_device *pdma;
+ if ((channel < 0) || (channel >= MAX_DMA_CHANNELS))
+ return;
+ pchan = mxs_dma_channels + channel;
+ if (!(pchan->flags & MXS_DMA_FLAGS_ALLOCATED))
+ return;
+ pdma = pchan->dma;
+ spin_lock_irqsave(&pchan->lock, flags);
+ if (pdma->enable_irq)
+ pdma->enable_irq(pdma, channel - pdma->chan_base, en);
+ spin_unlock_irqrestore(&pchan->lock, flags);
+}
+EXPORT_SYMBOL(mxs_dma_enable_irq);
+
+int mxs_dma_irq_is_pending(int channel)
+{
+ int ret = 0;
+ unsigned long flags;
+ struct mxs_dma_chan *pchan;
+ struct mxs_dma_device *pdma;
+ if ((channel < 0) || (channel >= MAX_DMA_CHANNELS))
+ return ret;
+ pchan = mxs_dma_channels + channel;
+ if (!(pchan->flags & MXS_DMA_FLAGS_ALLOCATED))
+ return ret;
+ pdma = pchan->dma;
+ spin_lock_irqsave(&pchan->lock, flags);
+ if (pdma->irq_is_pending)
+ ret = pdma->irq_is_pending(pdma, channel - pdma->chan_base);
+ spin_unlock_irqrestore(&pchan->lock, flags);
+ return ret;
+}
+EXPORT_SYMBOL(mxs_dma_irq_is_pending);
+
+void mxs_dma_ack_irq(int channel)
+{
+ unsigned long flags;
+ struct mxs_dma_chan *pchan;
+ struct mxs_dma_device *pdma;
+ if ((channel < 0) || (channel >= MAX_DMA_CHANNELS))
+ return;
+ pchan = mxs_dma_channels + channel;
+ if (!(pchan->flags & MXS_DMA_FLAGS_ALLOCATED))
+ return;
+ pdma = pchan->dma;
+ spin_lock_irqsave(&pchan->lock, flags);
+ if (pdma->ack_irq)
+ pdma->ack_irq(pdma, channel - pdma->chan_base);
+ spin_unlock_irqrestore(&pchan->lock, flags);
+}
+EXPORT_SYMBOL(mxs_dma_ack_irq);
+
+void mxs_dma_set_target(int channel, int target)
+{
+ unsigned long flags;
+ struct mxs_dma_chan *pchan;
+ struct mxs_dma_device *pdma;
+ if ((channel < 0) || (channel >= MAX_DMA_CHANNELS))
+ return;
+ pchan = mxs_dma_channels + channel;
+ if (!(pchan->flags & MXS_DMA_FLAGS_ALLOCATED))
+ return;
+ if (pchan->flags & MXS_DMA_FLAGS_BUSY)
+ return;
+ pdma = pchan->dma;
+ spin_lock_irqsave(&pchan->lock, flags);
+ if (pdma->set_target)
+ pdma->set_target(pdma, channel - pdma->chan_base, target);
+ spin_unlock_irqrestore(&pchan->lock, flags);
+}
+EXPORT_SYMBOL(mxs_dma_set_target);
+
+/* mxs dma utility function */
+struct mxs_dma_desc *mxs_dma_alloc_desc(void)
+{
+ struct mxs_dma_desc *pdesc;
+ unsigned int address;
+ if (mxs_dma_pool == NULL)
+ return NULL;
+
+ pdesc = dma_pool_alloc(mxs_dma_pool, GFP_KERNEL, &address);
+ if (pdesc == NULL)
+ return NULL;
+ memset(pdesc, 0, sizeof(*pdesc));
+ pdesc->address = address;
+ return pdesc;
+};
+EXPORT_SYMBOL(mxs_dma_alloc_desc);
+
+void mxs_dma_free_desc(struct mxs_dma_desc *pdesc)
+{
+ if (pdesc == NULL)
+ return;
+
+ if (mxs_dma_pool == NULL)
+ return;
+
+ dma_pool_free(mxs_dma_pool, pdesc, pdesc->address);
+}
+EXPORT_SYMBOL(mxs_dma_free_desc);
+
+int mxs_dma_desc_append(int channel, struct mxs_dma_desc *pdesc)
+{
+ int ret = 0;
+ unsigned long flags;
+ struct mxs_dma_chan *pchan;
+ struct mxs_dma_desc *last;
+ struct mxs_dma_device *pdma;
+ if ((channel < 0) || (channel >= MAX_DMA_CHANNELS))
+ return -EINVAL;
+ pchan = mxs_dma_channels + channel;
+ if (!(pchan->flags & MXS_DMA_FLAGS_ALLOCATED))
+ return -EINVAL;
+ pdma = pchan->dma;
+ pdesc->cmd.next = mxs_dma_cmd_address(pdesc);
+ pdesc->flags |= MXS_DMA_DESC_FIRST | MXS_DMA_DESC_LAST;
+ spin_lock_irqsave(&pchan->lock, flags);
+ if (!list_empty(&pchan->active)) {
+ last = list_entry(pchan->active.prev,
+ struct mxs_dma_desc, node);
+ if (pdesc->cmd.cmd.bits.dec_sem != last->cmd.cmd.bits.dec_sem) {
+ ret = -EFAULT;
+ goto out;
+ }
+ if (!pdesc->cmd.cmd.bits.dec_sem) {
+ pdesc->flags &= ~MXS_DMA_DESC_FIRST;
+ last->flags &= ~MXS_DMA_DESC_LAST;
+ }
+ pdesc->cmd.next = last->cmd.next;
+ last->cmd.next = mxs_dma_cmd_address(pdesc);
+ last->cmd.cmd.bits.chain = 1;
+ }
+ pdesc->flags |= MXS_DMA_DESC_READY;
+ if (pdesc->flags & MXS_DMA_DESC_FIRST)
+ pchan->pending_num++;
+ list_add_tail(&pdesc->node, &pchan->active);
+out:
+ spin_unlock_irqrestore(&pchan->lock, flags);
+ return ret;
+}
+EXPORT_SYMBOL(mxs_dma_desc_append);
+
+int mxs_dma_desc_add_list(int channel, struct list_head *head)
+{
+ int ret = 0, size = 0;
+ unsigned long flags;
+ struct mxs_dma_chan *pchan;
+ struct mxs_dma_device *pdma;
+ struct list_head *p;
+ struct mxs_dma_desc *prev = NULL, *pcur;
+ if ((channel < 0) || (channel >= MAX_DMA_CHANNELS))
+ return -EINVAL;
+ pchan = mxs_dma_channels + channel;
+ if (!(pchan->flags & MXS_DMA_FLAGS_ALLOCATED))
+ return -EINVAL;
+
+ if (list_empty(head))
+ return 0;
+
+ pdma = pchan->dma;
+ list_for_each(p, head) {
+ pcur = list_entry(p, struct mxs_dma_desc, node);
+ if (!(pcur->cmd.cmd.bits.dec_sem || pcur->cmd.cmd.bits.chain))
+ return -EINVAL;
+ if (prev)
+ prev->cmd.next = mxs_dma_cmd_address(pcur);
+ else
+ pcur->flags |= MXS_DMA_DESC_FIRST;
+ pcur->flags |= MXS_DMA_DESC_READY;
+ prev = pcur;
+ size++;
+ }
+ pcur = list_first_entry(head, struct mxs_dma_desc, node);
+ prev->cmd.next = mxs_dma_cmd_address(pcur);
+ prev->flags |= MXS_DMA_DESC_LAST;
+
+ spin_lock_irqsave(&pchan->lock, flags);
+ if (!list_empty(&pchan->active)) {
+ pcur = list_entry(pchan->active.next,
+ struct mxs_dma_desc, node);
+ if (pcur->cmd.cmd.bits.dec_sem != prev->cmd.cmd.bits.dec_sem) {
+ ret = -EFAULT;
+ goto out;
+ }
+ prev->cmd.next = mxs_dma_cmd_address(pcur);
+ prev = list_entry(pchan->active.prev,
+ struct mxs_dma_desc, node);
+ pcur = list_first_entry(head, struct mxs_dma_desc, node);
+ pcur->flags &= ~MXS_DMA_DESC_FIRST;
+ prev->flags &= ~MXS_DMA_DESC_LAST;
+ prev->cmd.next = mxs_dma_cmd_address(pcur);
+ }
+ list_splice(head, &pchan->active);
+ pchan->pending_num += size;
+ if (!(pcur->cmd.cmd.bits.dec_sem) && (pcur->flags & MXS_DMA_DESC_FIRST))
+ pchan->pending_num += 1;
+ else
+ pchan->pending_num += size;
+out:
+ spin_unlock_irqrestore(&pchan->lock, flags);
+ return ret;
+}
+EXPORT_SYMBOL(mxs_dma_desc_add_list);
+
+int mxs_dma_get_cooked(int channel, struct list_head *head)
+{
+ unsigned long flags;
+ struct mxs_dma_chan *pchan;
+ if ((channel < 0) || (channel >= MAX_DMA_CHANNELS))
+ return -EINVAL;
+ pchan = mxs_dma_channels + channel;
+ if (!(pchan->flags & MXS_DMA_FLAGS_ALLOCATED))
+ return -EINVAL;
+
+ if (head == NULL)
+ return 0;
+
+ spin_lock_irqsave(&pchan->lock, flags);
+ list_splice(&pchan->done, head);
+ spin_unlock_irqrestore(&pchan->lock, flags);
+ return 0;
+}
+EXPORT_SYMBOL(mxs_dma_get_cooked);
+
+int mxs_dma_device_register(struct mxs_dma_device *pdev)
+{
+ int i;
+ struct mxs_dma_chan *pchan;
+
+ if (pdev == NULL || !pdev->chan_num)
+ return -EINVAL;
+
+ if ((pdev->chan_base >= MAX_DMA_CHANNELS) ||
+ ((pdev->chan_base + pdev->chan_num) > MAX_DMA_CHANNELS))
+ return -EINVAL;
+
+ mutex_lock(&mxs_dma_mutex);
+ pchan = mxs_dma_channels + pdev->chan_base;
+ for (i = 0; i < pdev->chan_num; i++, pchan++) {
+ pchan->dma = pdev;
+ pchan->flags = MXS_DMA_FLAGS_VALID;
+ }
+ list_add(&pdev->node, &mxs_dma_devices);
+ mutex_unlock(&mxs_dma_mutex);
+ return 0;
+}
+EXPORT_SYMBOL(mxs_dma_device_register);
+
+static int __init mxs_dma_alignment_setup(char *line)
+{
+ get_option(&line, &mxs_dma_alignment);
+ mxs_dma_alignment = (mxs_dma_alignment + 3) & (~3);
+ mxs_dma_alignment = max(mxs_dma_alignment, MXS_DMA_ALIGNMENT);
+ return 1;
+};
+
+__setup("mxs-dma-alignment=", mxs_dma_alignment_setup);
+
+static int mxs_dmaengine_init(void)
+{
+ mxs_dma_pool = dma_pool_create("mxs_dma", NULL,
+ sizeof(struct mxs_dma_desc),
+ mxs_dma_alignment, PAGE_SIZE);
+ if (mxs_dma_pool == NULL)
+ return -ENOMEM;
+ return 0;
+}
+
+subsys_initcall(mxs_dmaengine_init);
+
+#ifdef CONFIG_PROC_FS
+
+static void *mxs_dma_proc_seq_start(struct seq_file *file, loff_t * index)
+{
+ if (*index >= MAX_DMA_CHANNELS)
+ return NULL;
+ return mxs_dma_channels + *index;
+}
+
+static void *mxs_dma_proc_seq_next(struct seq_file *file, void *data,
+ loff_t *index)
+{
+ if (data == NULL)
+ return NULL;
+
+ if (*index >= MAX_DMA_CHANNELS)
+ return NULL;
+
+ return mxs_dma_channels + (*index)++;
+}
+
+static void mxs_dma_proc_seq_stop(struct seq_file *file, void *data)
+{
+}
+
+static int mxs_dma_proc_seq_show(struct seq_file *file, void *data)
+{
+ struct mxs_dma_chan *pchan;
+ struct mxs_dma_device *pdev;
+
+ if (data == NULL)
+ return 0;
+
+ pchan = (struct mxs_dma_chan *)data;
+ pdev = pchan->dma;
+ if (pdev == NULL)
+ return 0;
+
+ return seq_printf(file, "%s-channel%-d (%s)\n",
+ pdev->name,
+ pchan - mxs_dma_channels,
+ pchan->name ? pchan->name : "idle");
+}
+
+static const struct seq_operations mxc_dma_proc_seq_ops = {
+ .start = mxs_dma_proc_seq_start,
+ .next = mxs_dma_proc_seq_next,
+ .stop = mxs_dma_proc_seq_stop,
+ .show = mxs_dma_proc_seq_show
+};
+
+static int mxs_dma_proc_open(struct inode *inode, struct file *file)
+{
+ return seq_open(file, &mxc_dma_proc_seq_ops);
+}
+
+static const struct file_operations mxs_dma_proc_info_ops = {
+ .open = mxs_dma_proc_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = seq_release,
+};
+
+static int __init mxs_dmaengine_info_init(void)
+{
+ struct proc_dir_entry *res;
+ res = create_proc_entry("dma-engine", 0, NULL);
+ if (!res) {
+ printk(KERN_ERR "Failed to create dma info file \n");
+ return -ENOMEM;
+ }
+ res->proc_fops = &mxs_dma_proc_info_ops;
+ return 0;
+}
+
+late_initcall(mxs_dmaengine_info_init);
+#endif
diff --git a/arch/arm/plat-mxs/gpio.c b/arch/arm/plat-mxs/gpio.c
new file mode 100644
index 000000000000..6c67c2bcfc5b
--- /dev/null
+++ b/arch/arm/plat-mxs/gpio.c
@@ -0,0 +1,225 @@
+/*
+ * Copyright (C) 2009-2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/gpio.h>
+#include <linux/list.h>
+#include <linux/irq.h>
+
+#include <mach/hardware.h>
+#include <mach/pinctrl.h>
+
+#if MXS_ARCH_NR_GPIOS % PINS_PER_BANK
+#error "MXS_ARCH_NR_GPIOS must be multipled of PINS_PER_BANK"
+#endif
+
+static struct mxs_gpio_port *mxs_gpios[MXS_ARCH_NR_GPIOS / PINS_PER_BANK];
+
+static inline int mxs_valid_gpio(struct mxs_gpio_port *port)
+{
+ struct mxs_gpio_chip *chip = port->chip;
+
+ if (port->id >= (MXS_ARCH_NR_GPIOS / PINS_PER_BANK))
+ return -EINVAL;
+
+ if (port->irq < 0 && port->child_irq > 0)
+ return -EINVAL;
+ if (chip->get == NULL || chip->set == NULL || chip->set_dir == NULL)
+ return -EINVAL;
+ if (port->child_irq > 0) {
+ if (chip->get_irq_stat == NULL)
+ return -EINVAL;
+ if (chip->mask_irq == NULL || chip->unmask_irq == NULL)
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static int mxs_gpio_request(struct gpio_chip *chip, unsigned int pin)
+{
+ struct mxs_gpio_port *port;
+ port = container_of(chip, struct mxs_gpio_port, port);
+ return mxs_request_pin(MXS_PIN_ENCODE(port->id, pin),
+ PIN_GPIO, GPIO_ID_NAME);
+}
+
+static void mxs_gpio_free(struct gpio_chip *chip, unsigned int pin)
+{
+ struct mxs_gpio_port *port;
+ port = container_of(chip, struct mxs_gpio_port, port);
+ return mxs_release_pin(MXS_PIN_ENCODE(port->id, pin), GPIO_ID_NAME);
+}
+
+static int mxs_gpio_to_irq(struct gpio_chip *chip, unsigned int index)
+{
+ struct mxs_gpio_port *port;
+ port = container_of(chip, struct mxs_gpio_port, port);
+ if (port->child_irq < 0)
+ return -ENXIO;
+ return port->child_irq + index;
+}
+
+static int mxs_gpio_get(struct gpio_chip *chip, unsigned int index)
+{
+ struct mxs_gpio_port *port;
+ port = container_of(chip, struct mxs_gpio_port, port);
+ return port->chip->get(port, index);
+}
+
+static void mxs_gpio_set(struct gpio_chip *chip, unsigned int index, int v)
+{
+ struct mxs_gpio_port *port;
+ port = container_of(chip, struct mxs_gpio_port, port);
+ port->chip->set(port, index, v);
+}
+
+static int mxs_gpio_output(struct gpio_chip *chip, unsigned int index, int v)
+{
+ int ret;
+ struct mxs_gpio_port *port;
+ port = container_of(chip, struct mxs_gpio_port, port);
+ ret = port->chip->set_dir(port, index, 0);
+ if (!ret)
+ port->chip->set(port, index, v);
+ return ret;
+}
+
+static int mxs_gpio_input(struct gpio_chip *chip, unsigned int index)
+{
+ struct mxs_gpio_port *port;
+ port = container_of(chip, struct mxs_gpio_port, port);
+ return port->chip->set_dir(port, index, 1);
+}
+
+static void mxs_gpio_irq_handler(u32 irq, struct irq_desc *desc)
+{
+ struct mxs_gpio_port *port = get_irq_data(irq);
+ int gpio_irq = port->child_irq;
+ u32 irq_stat = port->chip->get_irq_stat(port);
+
+ desc->chip->mask(irq);
+
+ while (irq_stat) {
+ if (irq_stat & 1)
+ generic_handle_irq(gpio_irq);
+ gpio_irq++;
+ irq_stat >>= 1;
+ }
+
+ desc->chip->ack(irq);
+ desc->chip->unmask(irq);
+}
+
+static int mxs_gpio_set_irq_type(unsigned int irq, unsigned int type)
+{
+ struct mxs_gpio_port *port;
+ unsigned int gpio = irq_to_gpio(irq);
+ port = mxs_gpios[GPIO_TO_BANK(gpio)];
+ if (port->child_irq < 0)
+ return -ENXIO;
+ if (port->chip->set_irq_type)
+ return port->chip->set_irq_type(port, GPIO_TO_PINS(gpio), type);
+ return -ENODEV;
+}
+
+static void mxs_gpio_ack_irq(unsigned int irq)
+{
+ struct mxs_gpio_port *port;
+ unsigned int gpio = irq_to_gpio(irq);
+ port = mxs_gpios[GPIO_TO_BANK(gpio)];
+ if (port->child_irq < 0)
+ return;
+ if (port->chip->ack_irq)
+ port->chip->ack_irq(port, GPIO_TO_PINS(gpio));
+}
+
+static void mxs_gpio_mask_irq(unsigned int irq)
+{
+ struct mxs_gpio_port *port;
+ unsigned int gpio = irq_to_gpio(irq);
+ port = mxs_gpios[GPIO_TO_BANK(gpio)];
+ if (port->child_irq < 0)
+ return;
+ port->chip->mask_irq(port, GPIO_TO_PINS(gpio));
+}
+
+static void mxs_gpio_unmask_irq(unsigned int irq)
+{
+ struct mxs_gpio_port *port;
+ unsigned int gpio = irq_to_gpio(irq);
+ port = mxs_gpios[GPIO_TO_BANK(gpio)];
+ if (port->child_irq < 0)
+ return;
+ port->chip->unmask_irq(port, GPIO_TO_PINS(gpio));
+}
+
+static struct irq_chip gpio_irq_chip = {
+ .ack = mxs_gpio_ack_irq,
+ .mask = mxs_gpio_mask_irq,
+ .unmask = mxs_gpio_unmask_irq,
+ .enable = mxs_gpio_unmask_irq,
+ .disable = mxs_gpio_mask_irq,
+ .set_type = mxs_gpio_set_irq_type,
+};
+
+int __init mxs_add_gpio_port(struct mxs_gpio_port *port)
+{
+ int i, ret;
+ if (!(port && port->chip))
+ return -EINVAL;
+
+ if (mxs_valid_gpio(port))
+ return -EINVAL;
+
+ if (mxs_gpios[port->id])
+ return -EBUSY;
+
+ mxs_gpios[port->id] = port;
+
+ port->port.base = port->id * PINS_PER_BANK;
+ port->port.ngpio = PINS_PER_BANK;
+ port->port.can_sleep = 1;
+ port->port.exported = 1;
+ port->port.to_irq = mxs_gpio_to_irq;
+ port->port.direction_input = mxs_gpio_input;
+ port->port.direction_output = mxs_gpio_output;
+ port->port.get = mxs_gpio_get;
+ port->port.set = mxs_gpio_set;
+ port->port.request = mxs_gpio_request;
+ port->port.free = mxs_gpio_free;
+ port->port.owner = THIS_MODULE;
+ ret = gpiochip_add(&port->port);
+ if (ret < 0)
+ return ret;
+
+ if (port->child_irq < 0)
+ return 0;
+
+ for (i = 0; i < PINS_PER_BANK; i++) {
+ gpio_irq_chip.mask(port->child_irq + i);
+ set_irq_chip(port->child_irq + i, &gpio_irq_chip);
+ set_irq_handler(port->child_irq + i, handle_level_irq);
+ set_irq_flags(port->child_irq + i, IRQF_VALID);
+ }
+ set_irq_chained_handler(port->irq, mxs_gpio_irq_handler);
+ set_irq_data(port->irq, port);
+ return ret;
+};
diff --git a/arch/arm/plat-mxs/icoll.c b/arch/arm/plat-mxs/icoll.c
new file mode 100644
index 000000000000..1e0b55bd26a9
--- /dev/null
+++ b/arch/arm/plat-mxs/icoll.c
@@ -0,0 +1,141 @@
+/*
+ * Copyright (C) 2009-2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/delay.h>
+
+#include <mach/hardware.h>
+#include <mach/device.h>
+#include <mach/irqs.h>
+
+#include "regs-icoll.h"
+
+void __iomem *g_icoll_base;
+
+/*
+ * IRQ handling
+ */
+static void icoll_ack_irq(unsigned int irq)
+{
+ __raw_writel(0, g_icoll_base + HW_ICOLL_VECTOR);
+
+ /* ACK current interrupt */
+ __raw_writel(BV_ICOLL_LEVELACK_IRQLEVELACK__LEVEL0,
+ g_icoll_base + HW_ICOLL_LEVELACK);
+
+ /* Barrier */
+ (void)__raw_readl(g_icoll_base + HW_ICOLL_STAT);
+}
+
+static void icoll_mask_irq(unsigned int irq)
+{
+ __raw_writel(BM_ICOLL_INTERRUPTn_ENABLE,
+ g_icoll_base + HW_ICOLL_INTERRUPTn_CLR(irq));
+}
+
+static void icoll_unmask_irq(unsigned int irq)
+{
+ __raw_writel(BM_ICOLL_INTERRUPTn_ENABLE,
+ g_icoll_base + HW_ICOLL_INTERRUPTn_SET(irq));
+}
+
+static int icoll_set_wake_irq(unsigned int irq, unsigned int enabled)
+{
+ return 0;
+}
+
+static struct irq_chip icoll_chip = {
+ .ack = icoll_ack_irq,
+ .mask = icoll_mask_irq,
+ .unmask = icoll_unmask_irq,
+ .set_wake = icoll_set_wake_irq,
+};
+
+void __init avic_init_irq(void __iomem *base, int nr_irqs)
+{
+ int i;
+ g_icoll_base = base;
+
+ /* Reset icoll */
+ __raw_writel(BM_ICOLL_CTRL_SFTRST, g_icoll_base + HW_ICOLL_CTRL_CLR);
+
+ for (i = 0; i < 100000; i++) {
+ if (!(__raw_readl(g_icoll_base + HW_ICOLL_CTRL) &
+ BM_ICOLL_CTRL_SFTRST))
+ break;
+ udelay(2);
+ }
+ if (i >= 100000) {
+ printk(KERN_ERR "%s:%d timeout when enableing\n",
+ __func__, __LINE__);
+ return;
+ }
+ __raw_writel(BM_ICOLL_CTRL_CLKGATE, g_icoll_base + HW_ICOLL_CTRL_CLR);
+
+ for (i = 0; i < nr_irqs; i++) {
+ __raw_writel(0, g_icoll_base + HW_ICOLL_INTERRUPTn(i));
+ set_irq_chip(i, &icoll_chip);
+ set_irq_handler(i, handle_level_irq);
+ set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
+ }
+
+ __raw_writel(BF_ICOLL_LEVELACK_IRQLEVELACK
+ (BV_ICOLL_LEVELACK_IRQLEVELACK__LEVEL0),
+ g_icoll_base + HW_ICOLL_LEVELACK);
+ __raw_writel(BF_ICOLL_LEVELACK_IRQLEVELACK
+ (BV_ICOLL_LEVELACK_IRQLEVELACK__LEVEL1),
+ g_icoll_base + HW_ICOLL_LEVELACK);
+ __raw_writel(BF_ICOLL_LEVELACK_IRQLEVELACK
+ (BV_ICOLL_LEVELACK_IRQLEVELACK__LEVEL2),
+ g_icoll_base + HW_ICOLL_LEVELACK);
+ __raw_writel(BF_ICOLL_LEVELACK_IRQLEVELACK
+ (BV_ICOLL_LEVELACK_IRQLEVELACK__LEVEL3),
+ g_icoll_base + HW_ICOLL_LEVELACK);
+
+ __raw_writel(0, g_icoll_base + HW_ICOLL_VECTOR);
+ /* Barrier */
+ (void)__raw_readl(g_icoll_base + HW_ICOLL_STAT);
+}
+
+void mxs_set_irq_fiq(unsigned int irq, unsigned int type)
+{
+ if (type == 0)
+ __raw_writel(BM_ICOLL_INTERRUPTn_ENFIQ,
+ g_icoll_base +
+ HW_ICOLL_INTERRUPTn_CLR(irq));
+ else
+ __raw_writel(BM_ICOLL_INTERRUPTn_ENFIQ,
+ g_icoll_base +
+ HW_ICOLL_INTERRUPTn_SET(irq));
+}
+EXPORT_SYMBOL(mxs_set_irq_fiq);
+
+void mxs_enable_fiq_functionality(int enable)
+{
+ if (enable)
+ __raw_writel(BM_ICOLL_CTRL_FIQ_FINAL_ENABLE,
+ g_icoll_base + HW_ICOLL_CTRL_SET);
+ else
+ __raw_writel(BM_ICOLL_CTRL_FIQ_FINAL_ENABLE,
+ g_icoll_base + HW_ICOLL_CTRL_CLR);
+
+}
+EXPORT_SYMBOL(mxs_enable_fiq_functionality);
+
diff --git a/arch/arm/plat-mxs/include/mach/arc_otg.h b/arch/arm/plat-mxs/include/mach/arc_otg.h
new file mode 100644
index 000000000000..5ba352f90fbe
--- /dev/null
+++ b/arch/arm/plat-mxs/include/mach/arc_otg.h
@@ -0,0 +1,174 @@
+/*
+ * Copyright (C) 1999 ARM Limited
+ * Copyright (C) 2009-2010 Freescale Semiconductor, Inc.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef __ASM_ARCH_MXC_ARC_OTG_H__
+#define __ASM_ARCH_MXC_ARC_OTG_H__
+
+#include "../../regs-usbphy.h"
+#if defined(CONFIG_USB_STATIC_IRAM) \
+ || defined(CONFIG_USB_STATIC_IRAM_PPH)
+#define USB_IRAM_SIZE SZ_8K
+#else
+#define USB_IRAM_SIZE 0
+#endif
+
+#define OTG_BASE_ADDR USBCTRL0_PHYS_ADDR
+#define USB_OTGREGS_BASE (OTG_BASE_ADDR + 0x000)
+/*
+ * OTG registers
+ */
+#define UOG_ID (0x00) /* Host ID */
+#define UOG_HWGENERAL (0x04) /* Host General */
+#define UOG_HWHOST (0x08) /* Host h/w params */
+#define UOG_HWTXBUF (0x10) /* TX buffer h/w params */
+#define UOG_HWRXBUF (0x14) /* RX buffer h/w params */
+#define UOG_CAPLENGTH (0x100) /* Capability register length */
+#define UOG_HCIVERSION (0x102) /* Host Interface version */
+#define UOG_HCSPARAMS (0x104) /* Host control structural params */
+#define UOG_HCCPARAMS (0x108) /* control capability params */
+#define UOG_DCIVERSION (0x120) /* device interface version */
+/* start EHCI registers: */
+#define UOG_USBCMD (0x140) /* USB command register */
+#define UOG_USBSTS (0x144) /* USB status register */
+#define UOG_USBINTR (0x148) /* interrupt enable register */
+#define UOG_FRINDEX (0x14c) /* USB frame index */
+/* segment (0x150) addr bits 63:32 if needed */
+#define UOG_PERIODICLISTBASE (0x154) /* host crtlr frame list base addr */
+#define UOG_DEVICEADDR (0x154) /* device crtlr device address */
+#define UOG_ASYNCLISTADDR (0x158) /* host ctrlr next async addr */
+#define UOG_EPLISTADDR (0x158) /* device ctrlr endpoint list addr */
+#define UOG_BURSTSIZE (0x160) /* host ctrlr embedded TT
+ async buf status */
+#define UOG_TXFILLTUNING (0x164) /* TX FIFO fill tuning */
+#define UOG_ULPIVIEW (0x170) /* ULPI viewport */
+#define UOG_CFGFLAG (0x180) /* configflag (supports HS) */
+#define UOG_PORTSC1 (0x184) /* port status and control */
+/* end EHCI registers: */
+#define UOG_OTGSC (0x1a4) /* OTG status and control */
+#define UOG_USBMODE (0x1a8) /* USB device mode */
+#define UOG_ENDPTSETUPSTAT (0x1ac) /* endpoint setup status */
+#define UOG_ENDPTPRIME (0x1b0) /* endpoint initialization */
+#define UOG_ENDPTFLUSH (0x1b4) /* endpoint de-initialize */
+#define UOG_ENDPTSTAT (0x1b8) /* endpoint status */
+#define UOG_ENDPTCOMPLETE (0x1bc) /* endpoint complete */
+#define UOG_EPCTRL0 (0x1c0) /* endpoint control0 */
+/*
+ * register bits
+ */
+
+/* x_PORTSCx */
+#define PORTSC_PTS_MASK (3 << 30) /* parallel xcvr mask */
+#define PORTSC_PTS_UTMI (0 << 30) /* UTMI/UTMI+ */
+#define PORTSC_PTS_PHILIPS (1 << 30) /* Philips classic */
+#define PORTSC_PTS_ULPI (2 << 30) /* ULPI */
+#define PORTSC_PTS_SERIAL (3 << 30) /* serial */
+#define PORTSC_STS (1 << 29) /* serial xcvr select */
+#define PORTSC_PTW (1 << 28) /* UTMI width */
+#define PORTSC_PHCD (1 << 23) /* Low Power Suspend */
+#define PORTSC_PORT_POWER (1 << 12) /* port power */
+#define PORTSC_LS_MASK (3 << 10) /* Line State mask */
+#define PORTSC_LS_SE0 (0 << 10) /* SE0 */
+#define PORTSC_LS_K_STATE (1 << 10) /* K-state */
+#define PORTSC_LS_J_STATE (2 << 10) /* J-state */
+#define PORTSC_PORT_RESET (1 << 8) /* Port reset */
+#define PORTSC_PORT_SUSPEND (1 << 7) /* Suspend */
+#define PORTSC_PORT_FORCE_RESUME (1 << 6) /* Force port resume */
+#define PORTSC_OVER_CURRENT_CHG (1 << 5) /* over current change */
+#define PORTSC_OVER_CURRENT_ACT (1 << 4) /* over currrent active */
+#define PORTSC_PORT_EN_DIS_CHANGE (1 << 3) /* port change */
+#define PORTSC_PORT_ENABLE (1 << 2) /* port enabled */
+#define PORTSC_CONNECT_STATUS_CHANGE (1 << 1) /* connect status change */
+#define PORTSC_CURRENT_CONNECT_STATUS (1 << 0) /* current connect status */
+
+#define PORTSC_W1C_BITS \
+ (PORTSC_CONNECT_STATUS_CHANGE | \
+ PORTSC_PORT_EN_DIS_CHANGE | \
+ PORTSC_OVER_CURRENT_CHG)
+
+/* UOG_OTGSC Register Bits */
+/* control bits: */
+#define OTGSC_CTRL_VBUS_DISCHARGE (1 << 0)
+#define OTGSC_CTRL_VBUS_CHARGE (1 << 1)
+/* controls DM pulldown */
+#define OTGSC_CTRL_OTG_TERM (1 << 3)
+#define OTGSC_CTRL_DATA_PULSING (1 << 4)
+#define OTGSC_CTRL_USB_ID_PU (1 << 5)
+/* current status: (R/O) */
+/* 0=A-device 1=B-device */
+#define OTGSC_STS_USB_ID (1 << 8)
+#define OTGSC_STS_A_VBUS_VALID (1 << 9)
+#define OTGSC_STS_A_SESSION_VALID (1 << 10)
+#define OTGSC_STS_B_SESSION_VALID (1 << 11)
+#define OTGSC_STS_B_SESSION_END (1 << 12)
+#define OTGSC_STS_1ms_TIMER (1 << 13)
+#define OTGSC_STS_DATA_PULSE (1 << 14)
+/* interrupt status: (write to clear) */
+#define OTGSC_IS_MASK (0x7f << 16)
+#define OTGSC_IS_USB_ID (1 << 16)
+#define OTGSC_IS_A_VBUS_VALID (1 << 17)
+#define OTGSC_IS_A_SESSION_VALID (1 << 18)
+#define OTGSC_IS_B_SESSION_VALID (1 << 19)
+#define OTGSC_IS_B_SESSION_END (1 << 20)
+#define OTGSC_IS_1ms_TIMER (1 << 21)
+#define OTGSC_IS_DATA_PULSE (1 << 22)
+/* interrupt enables: */
+#define OTGSC_IE_MASK (0x7f << 24)
+#define OTGSC_IE_USB_ID (1 << 24)
+#define OTGSC_IE_A_VBUS_VALID (1 << 25)
+#define OTGSC_IE_A_SESSION_VALID (1 << 26)
+#define OTGSC_IE_B_SESSION_VALID (1 << 27)
+#define OTGSC_IE_B_SESSION_END (1 << 28)
+#define OTGSC_IE_1ms_TIMER (1 << 29)
+#define OTGSC_IE_DATA_PULSE (1 << 30)
+
+#if 1 /* FIXME these here for compatibility between my names and Leo's */
+/* OTG interrupt enable bit masks */
+#define OTGSC_INTERRUPT_ENABLE_BITS_MASK OTGSC_IE_MASK
+#define OTGSC_INTSTS_MASK OTGSC_IS_MASK
+
+/* OTG interrupt status bit masks */
+#define OTGSC_INTERRUPT_STATUS_BITS_MASK OTGSC_IS_MASK
+#endif
+
+/* x_USBMODE */
+#define USBMODE_SLOM (1 << 3) /* setup lockout mode */
+#define USBMODE_ES (1 << 2) /* (big) endian select */
+#define USBMODE_CM_MASK (3 << 0) /* controller mode mask */
+#define USBMODE_CM_HOST (3 << 0) /* host */
+#define USBMODE_CM_DEVICE (2 << 0) /* device */
+#define USBMODE_CM_reserved (1 << 0) /* reserved */
+
+/* USBCMD */
+#define UCMD_RUN_STOP (1 << 0) /* controller run/stop */
+#define UCMD_RESET (1 << 1) /* controller reset */
+#define UCMD_ITC_NO_THRESHOLD (~(0xff << 16)) /* Interrupt Threshold */
+
+/* OTG_MIRROR */
+#define OTGM_SESEND (1 << 4) /* B device session end */
+#define OTGM_VBUSVAL (1 << 3) /* Vbus valid */
+#define OTGM_BSESVLD (1 << 2) /* B session Valid */
+#define OTGM_ASESVLD (1 << 1) /* A session Valid */
+#define OTGM_IDIDG (1 << 0) /* OTG ID pin status */
+ /* 1=high: Operate as B-device */
+ /* 0=low : Operate as A-device */
+
+#define HCSPARAMS_PPC (0x1<<4) /* Port Power Control */
+
+extern enum fsl_usb2_modes get_usb_mode(struct fsl_usb2_platform_data *pdata);
+#endif
diff --git a/arch/arm/plat-mxs/include/mach/bus_freq.h b/arch/arm/plat-mxs/include/mach/bus_freq.h
new file mode 100644
index 000000000000..0c41cd2205ff
--- /dev/null
+++ b/arch/arm/plat-mxs/include/mach/bus_freq.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef BUS_FREQ_H__
+#define BUS_FREQ_H__
+
+#define VERY_HI_RATE 2000000000
+#define LCD_ON_CPU_FREQ_KHZ 261818
+#define OPERATION_WP_SUPPORTED 6
+
+struct profile {
+ int cpu;
+ int ahb;
+ int emi;
+ int ss;
+ int vddd;
+ int vddd_bo;
+ int cur;
+ int vddio;
+ int vdda;
+ u16 xbus;
+ /* map of the upper 16 bits of HW_CLKCTRL_HBUS register */
+ u16 h_autoslow_flags;
+};
+
+/* map of the upper 16 bits of HW_CLKCTRL_HBUS register */
+int is_hclk_autoslow_ok(void);
+
+extern int timing_ctrl_rams(int ss);
+
+#endif
diff --git a/arch/arm/plat-mxs/include/mach/clkdev.h b/arch/arm/plat-mxs/include/mach/clkdev.h
new file mode 100644
index 000000000000..d6a82c8d5782
--- /dev/null
+++ b/arch/arm/plat-mxs/include/mach/clkdev.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2009-2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef __ASM_MACH_CLKDEV_H
+#define __ASM_MACH_CLKDEV_H
+
+extern int __clk_get(struct clk *clk);
+extern void __clk_put(struct clk *clk);
+
+#endif
diff --git a/arch/arm/plat-mxs/include/mach/clock.h b/arch/arm/plat-mxs/include/mach/clock.h
new file mode 100644
index 000000000000..b506468976b5
--- /dev/null
+++ b/arch/arm/plat-mxs/include/mach/clock.h
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 2009-2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef __ASM_ARM_ARCH_CLOCK_H
+#define __ASM_ARM_ARCH_CLOCK_H
+
+#ifndef __ASSEMBLER__
+
+#include <linux/list.h>
+#include <asm/clkdev.h>
+
+struct clk {
+ int id;
+ struct clk *parent;
+ struct clk *secondary;
+ unsigned long flags;
+
+ int ref;
+ unsigned int scale_bits;
+ unsigned int enable_bits;
+ unsigned int bypass_bits;
+ unsigned int busy_bits;
+ unsigned int xtal_busy_bits;
+
+ unsigned int wait:1;
+ unsigned int invert:1;
+
+ void __iomem *enable_reg;
+ void __iomem *scale_reg;
+ void __iomem *bypass_reg;
+ void __iomem *busy_reg;
+
+ /*
+ * Function ptr to set the clock to a new rate. The rate must match a
+ * supported rate returned from round_rate. Leave blank if clock is not
+ * programmable
+ */
+ int (*set_rate) (struct clk *, unsigned long);
+ /*
+ * Function ptr to get the clock rate.
+ */
+ unsigned long (*get_rate) (struct clk *);
+ /*
+ * Function ptr to round the requested clock rate to the nearest
+ * supported rate that is less than or equal to the requested rate.
+ */
+ unsigned long (*round_rate) (struct clk *, unsigned long);
+ /*
+ * Function ptr to enable the clock. Leave blank if clock can not
+ * be gated.
+ */
+ int (*enable) (struct clk *);
+ /*
+ * Function ptr to disable the clock. Leave blank if clock can not
+ * be gated.
+ */
+ void (*disable) (struct clk *);
+ /* Function ptr to set the parent clock of the clock. */
+ int (*set_parent) (struct clk *, struct clk *);
+
+ /* Function ptr to change the parent clock depending
+ * the system configuration at that time. Will only
+ * change the parent clock if the ref count is 0 (the clock
+ * is not being used)
+ */
+ int (*set_sys_dependent_parent) (struct clk *);
+
+};
+
+int clk_get_usecount(struct clk *clk);
+extern int clk_register(struct clk_lookup *lookup);
+extern void clk_unregister(struct clk_lookup *lookup);
+
+bool clk_enable_h_autoslow(bool enable);
+void clk_set_h_autoslow_flags(u16 mask);
+void clk_en_public_h_asm_ctrl(bool (*enable_func)(bool),
+ void (*set_func)(u16));
+
+struct mxs_emi_scaling_data {
+ u32 emi_div;
+ u32 frac_div;
+ u32 cur_freq;
+ u32 new_freq;
+};
+
+
+
+#ifdef CONFIG_MXS_RAM_FREQ_SCALING
+extern int mxs_ram_freq_scale(struct mxs_emi_scaling_data *);
+extern u32 mxs_ram_funcs_sz;
+#else
+static inline int mxs_ram_freq_scale(struct mxs_emi_scaling_data *p)
+{
+}
+static u32 mxs_ram_funcs_sz;
+#endif
+
+/* Clock flags */
+/* 0 ~ 16 attribute flags */
+#define ALWAYS_ENABLED (1 << 0) /* Clock cannot be disabled */
+#define RATE_FIXED (1 << 1) /* Fixed clock rate */
+#define CPU_FREQ_TRIG_UPDATE (1 << 2) /* CPUFREQ trig update */
+
+/* 16 ~ 23 reservied */
+/* 24 ~ 31 run time flags */
+
+#define CLK_REF_UNIT 0x00010000
+#define CLK_REF_LIMIT 0xFFFF0000
+#define CLK_EN_MASK 0x0000FFFF
+#endif /* __ASSEMBLER__ */
+
+#endif
diff --git a/arch/arm/plat-mxs/include/mach/ddi_bc.h b/arch/arm/plat-mxs/include/mach/ddi_bc.h
new file mode 100644
index 000000000000..21ca9217cdaa
--- /dev/null
+++ b/arch/arm/plat-mxs/include/mach/ddi_bc.h
@@ -0,0 +1,715 @@
+/*
+ * Copyright (C) 2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#ifndef _DDI_BC_H
+#define _DDI_BC_H
+
+#include <linux/types.h>
+
+#define DDI_BC_MAX_RESTART_CYCLES 100
+
+#define DDI_BC_LIION_CHARGING_VOLTAGE 4200
+#define DDI_BC_ALKALINE_NIMH_CHARGING_VOLTAGE 1750
+
+/* brief Defines battery charger states. */
+typedef enum _ddi_bc_State {
+ /* brief TBD */
+ DDI_BC_STATE_UNINITIALIZED = 0,
+ /* brief TBD */
+ DDI_BC_STATE_BROKEN = 1,
+ /* brief TBD */
+ DDI_BC_STATE_DISABLED = 2,
+ /* brief TBD */
+ DDI_BC_STATE_WAITING_TO_CHARGE = 3,
+ /* brief TBD */
+ DDI_BC_STATE_CONDITIONING = 4,
+ /* brief TBD */
+ DDI_BC_STATE_CHARGING = 5,
+ /* brief TBD */
+ DDI_BC_STATE_TOPPING_OFF = 6,
+ /* brief TBD */
+ DDI_BC_STATE_DCDC_MODE_WAITING_TO_CHARGE = 7,
+
+} ddi_bc_State_t;
+
+typedef enum _ddi_bc_BrokenReason {
+ /* brief TBD */
+ DDI_BC_BROKEN_UNINITIALIZED = 0,
+ /* brief TBD */
+ DDI_BC_BROKEN_CHARGING_TIMEOUT = 1,
+ /* brief TBD */
+ DDI_BC_BROKEN_FORCED_BY_APPLICATION = 2,
+ /* brief TBD */
+ DDI_BC_BROKEN_EXTERNAL_BATTERY_VOLTAGE_DETECTED = 3,
+ /* brief TBD */
+ DDI_BC_BROKEN_NO_BATTERY_DETECTED = 4,
+
+} ddi_bc_BrokenReason_t;
+
+/* brief Defines the battery charger configuration. */
+typedef struct _ddi_bc_Cfg {
+ /* brief Units in milliseconds. */
+ /* */
+ /* This field configures the expected period between calls to */
+ /* ddi_bc_StateMachine. If die temperature monitoring is */
+ /* enabled, then the data sheet recommends the period be around */
+ /* 100ms or less. */
+ /* */
+ /* Note that this period defines the minimum time resolution of */
+ /* the battery charger. */
+
+ uint32_t u32StateMachinePeriod;
+
+ /* brief Units in mA/s. */
+ /* */
+ /* This field configures the slope of the current ramp. Any */
+ /* time the battery charger increases its current draw, it will */
+ /* ramp up the current no faster than this rate. */
+ /* */
+ /* Note that the minimum time resolution of the battery charger */
+ /* is the configured period between calls to advance the state */
+ /* machine. Also, the hardware has a minimum current resolution */
+ /* of 10mA. If the given ramp slope cannot be expressed */
+ /* exactly, then the largest expressible smaller slope will be */
+ /* the result. If the actual period between calls to */
+ /* ddi_bc_StateMachine is irregular, the current may ramp faster */
+ /* than indicated. */
+
+ uint16_t u16CurrentRampSlope;
+
+ /* brief Units in millivolts. */
+ /* */
+ /* This field configures the threshold conditioning voltage. If */
+ /* the battery's voltage is below this value, it will be */
+ /* conditioned until its voltage rises above the maximum */
+ /* conditioning voltage. After that, the battery will be */
+ /* charged normally. */
+ /* */
+ /* Note that the hardware has a minimum resolution of 8mV. If */
+ /* the given voltage cannot be expressed exactly, then the */
+ /* smallest expressible larger value will be used. */
+
+ uint16_t u16ConditioningThresholdVoltage;
+
+ /* brief Units in millivolts. */
+ /* */
+ /* This field configures the maximum conditioning voltage. If */
+ /* the battery charger is conditioning a battery, normal */
+ /* charging begins when the voltage rises above this value. */
+ /* */
+ /* This value should be slightly higher than the threshold */
+ /* conditioning voltage because it is measured while a */
+ /* conditioning current is actually flowing to the battery. */
+ /* With a conditioning current of 0.1C, reasonable values for */
+ /* the threshold and maximum conditioning voltages are 2.9V */
+ /* and 3.0V respectively. */
+ /* */
+ /* Note that the hardware has a minimum resolution of 8mV. If */
+ /* the given voltage cannot be expressed exactly, then the */
+ /* smallest expressible larger value will be used. */
+
+ uint16_t u16ConditioningMaxVoltage;
+
+ /* brief Units in milliamps. */
+ /* */
+ /* This field configures the maximum conditioning current. */
+ /* This is the maximum current that will be offered to a */
+ /* battery while it is being conditioned. A typical value is */
+ /* 0.1C. */
+ /* */
+ /* Note that the hardware has a minimum resolution of 10mA */
+ /* (see the data sheet for details). If the given current */
+ /* cannot be expressed exactly, then the largest expressible */
+ /* smaller value will be used. */
+
+ uint16_t u16ConditioningCurrent;
+
+ /* brief Units in milliseconds. */
+ /* */
+ /* This field configures the conditioning time-out. This is */
+ /* the maximum amount of time that a battery will be */
+ /* conditioned before the battery charger declares it to be */
+ /* broken. */
+ /* */
+ /* Note that the minimum time resolution of the battery */
+ /* charger is the configured period between calls to advance */
+ /* the state machine. If the given time-out cannot be */
+ /* expressed exactly, then the shortest expressible longer */
+ /* value will be used. */
+
+ uint32_t u32ConditioningTimeout;
+
+ /* brief Units in millivolts. */
+ /* */
+ /* This field configures the final charging voltage. At this */
+ /* writing, only two values are permitted: 4100 or 4200. */
+
+ uint16_t u16ChargingVoltage;
+
+ /* brief Units in milliamps. */
+ /* */
+ /* This field configures the maximum current offered to a */
+ /* charging battery. */
+ /* */
+ /* Note that the hardware has a minimum resolution of 10mA */
+ /* (see the data sheet for details). If the given current */
+ /* cannot be expressed exactly, then the largest expressible */
+ /* smaller value will be used. */
+
+ uint16_t u16ChargingCurrent;
+
+ /* brief Units in milliamps. */
+ /* */
+ /* This field configures the current flow below which a */
+ /* charging battery is regarded as fully charged (typical */
+ /* 0.1C). At this point, the battery will be topped off. */
+ /* */
+ /* Note that the hardware has a minimum resolution of 10mA */
+ /* (see the data sheet for details). If the given current */
+ /* cannot be expressed exactly, then the largest expressible */
+ /* smaller value will be used. */
+
+ uint16_t u16ChargingThresholdCurrent;
+
+ /* brief Units in milliamps. */
+ /* */
+ /* When charging while the DCDC converter's are enabled, the charger */
+ /* is suppling current to both the battery and the Vbat input of the */
+ /* DCDC converter. Once the total battery charger current falls */
+ /* below this level, the charger will then stop charging until the */
+ /* the battery voltage reaches the BC_LOW_DCDCMODE_BATTERY_VOLTAGE */
+ /* threshold or until the DCDCs are no longer enabled. */
+ /* */
+ /* Typically, this value should be left at 180 to avoid the risk */
+ /* of topping off the battery too long in DCDC mode and avoid */
+ /* exceeding the BC_CHARGING_TIMEOUT time which would put the charger */
+ /* driver in the broken state and completely disable charging. */
+ /* */
+ /* Note that the hardware has a minimum resolution of 10mA */
+ /* (see the data sheet for details). If the given current */
+ /* cannot be expressed exactly, then the largest expressible */
+ /* smaller value will be used. */
+ uint16_t u16DdcdModeChargingThresholdCurrent;
+
+ /* brief Units in milliseconds. */
+ /* */
+ /* This field configures the charging time-out. This is the */
+ /* maximum amount of time that a battery will be charged */
+ /* before the battery charger declares it to be broken. */
+ /* */
+ /* Note that the minimum time resolution of the battery */
+ /* charger is the configured period between calls to advance */
+ /* the state machine. If the given time-out cannot be */
+ /* expressed exactly, then the shortest expressible longer */
+ /* value will be used. */
+
+ uint32_t u32ChargingTimeout;
+
+ /* brief Units in milliseconds. */
+ /* */
+ /* This field configures the top-off period. This is the */
+ /* amount of time a battery will be held in the Topping Off */
+ /* state before it is declared fully charged. */
+ /* */
+ /* Note that the minimum time resolution of the battery */
+ /* charger is the configured period between calls to advance */
+ /* the state machine. If the given time-out cannot be */
+ /* expressed exactly, then the shortest expressible longer */
+ /* value will be used. */
+
+ uint32_t u32TopOffPeriod;
+
+ /* brief Units in milliseconds. */
+ /* */
+ /* This field configures the top-off period when the DCDC */
+ /* converters are enabled. To avoid topping off the LiIon */
+ /* battery too long and reducing it's long term capacity, */
+ /* This time should be kept failry short. */
+ /* */
+ /* Note that the minimum time resolution of the battery */
+ /* charger is the configured period between calls to advance */
+ /* the state machine. If the given time-out cannot be */
+ /* expressed exactly, then the shortest expressible longer */
+ /* value will be used. */
+ uint32_t u32DcdcModeTopOffPeriod;
+
+ /* brief Causes the battery charger to use an externally generated bias current */
+ /* */
+ /* If cleared, this causes the battery charger to use an */
+ /* externally generated bias current, which is expected to be */
+ /* quite precise. Otherwise, the battery charger will */
+ /* generate a lesser-quality bias current internally. */
+
+ uint8_t useInternalBias:1;
+
+ /* brief Indicates that the battery charger is to monitor the die temperature. */
+ /* */
+ /* If set, this field indicates that the battery charger is to */
+ /* monitor the die temperature. See below for fields that */
+ /* configure the details. */
+
+ uint8_t monitorDieTemp:1;
+
+ /* brief Indicates that the battery charger is to monitor the battery temperature. */
+ /* */
+ /* If set, this field indicates that the battery charger is to */
+ /* monitor the battery temperature. See below for fields that */
+ /* configure the details. */
+
+ uint8_t monitorBatteryTemp:1;
+
+ /* brief Units in degrees centigrade. */
+ /* */
+ /* Note that the hardware reports die temperature in ranges of */
+ /* 10 degree resolution minimum (see the data sheet for */
+ /* details). If the battery charger is monitoring the die */
+ /* temperature, and it rises to a range that includes a */
+ /* temperature greater than or equal to this value, the */
+ /* charging current will be clamped to the safe current. */
+
+ int8_t u8DieTempHigh;
+
+ /* brief Units in degrees centigrade. */
+ /* */
+ /* Note that the hardware reports die temperature in ranges of */
+ /* 10 degrees minimum (see the data sheet for details). If the */
+ /* charging current is being clamped because of a high die */
+ /* temperature, and it falls to a range that doesn't include a */
+ /* temperatures greater than or equal to this value, the */
+ /* charging current clamp will be released. */
+
+ int8_t u8DieTempLow;
+
+ /* brief Units in milliamps. */
+ /* */
+ /* If the battery charger detects a high die temperature, it */
+ /* will clamp the charging current at or below this value. */
+
+ uint16_t u16DieTempSafeCurrent;
+
+ /* brief If the battery charger is monitoring the battery */
+ /* temperature, this field indicates the LRADC channel to */
+ /* read. */
+
+ uint8_t u8BatteryTempChannel;
+
+ /* brief If the battery charger is monitoring the battery */
+ /* temperature, and it rises to a measurement greater than or */
+ /* equal to this value, the charging current will be clamped */
+ /* to the corresponding safe current. */
+
+ uint16_t u16BatteryTempHigh;
+
+ /* brief If the charging current is being clamped because of a high */
+ /* battery temperature, and it falls below this value, the */
+ /* charging current clamp will be released. */
+
+ uint16_t u16BatteryTempLow;
+
+ /* brief Units in milliamps. */
+ /* */
+ /* If the battery charger detects a high battery temperature, */
+ /* it will clamp the charging current at or below this value. */
+
+ uint16_t u16BatteryTempSafeCurrent;
+
+ /* brief Units in millivolts. */
+ /* */
+ /* In the WaitingToCharge state, if we are in DCDC */
+ /* operating modes, if the battery voltage measurement */
+ /* is below this value, we immediately proceed with charging. */
+ /* the low criteria for this value is that it must be high */
+ /* to not risk the battery voltage getting too low. The */
+ /* upper criteria is that you do not want the IR voltage */
+ /* drop under heavy loads to make you start charging too soon */
+ /* because the goal in DCDC operating mode is to not be constantly */
+ /* topping off the battery which can shorten its life */
+
+ uint16_t u16LowDcdcBatteryVoltage_mv;
+
+ uint32_t u32StateMachineNonChargingPeriod;
+} ddi_bc_Cfg_t;
+
+/* Status returned by Battery Charger functions. */
+
+typedef enum _ddi_bc_Status {
+ /* brief TBD */
+ DDI_BC_STATUS_SUCCESS = 0,
+ /* brief TBD */
+ DDI_BC_STATUS_HARDWARE_DISABLED,
+ /* brief TBD */
+ DDI_BC_STATUS_BAD_BATTERY_MODE,
+ /* brief TBD */
+ DDI_BC_STATUS_CLOCK_GATE_CLOSED,
+ /* brief TBD */
+ DDI_BC_STATUS_NOT_INITIALIZED,
+ /* brief TBD */
+ DDI_BC_STATUS_ALREADY_INITIALIZED,
+ /* brief TBD */
+ DDI_BC_STATUS_BROKEN,
+ /* brief TBD */
+ DDI_BC_STATUS_NOT_BROKEN,
+ /* brief TBD */
+ DDI_BC_STATUS_NOT_DISABLED,
+ /* brief TBD */
+ DDI_BC_STATUS_BAD_ARGUMENT,
+ /* brief TBD */
+ DDI_BC_STATUS_CFG_BAD_BATTERY_TEMP_CHANNEL,
+ /* brief TBD */
+ DDI_BC_STATUS_CFG_BAD_CHARGING_VOLTAGE,
+} ddi_bc_Status_t;
+
+
+/* BCM Event Codes */
+
+/* These are the codes that might be published to PMI Subscribers. */
+
+
+#define DDI_BC_EVENT_GROUP (11<<10)
+
+/* brief TBD */
+/* todo [PUBS] Add definition(s)... */
+typedef enum {
+ /* Use the error code group value to make events unique for the EOI */
+ /* brief TBD */
+ ddi_bc_MinEventCode = DDI_BC_EVENT_GROUP,
+ /* brief TBD */
+ ddi_bc_WaitingToChargeCode,
+ /* brief TBD */
+ ddi_bc_State_ConditioningCode,
+ /* brief TBD */
+ ddi_bc_State_Topping_OffCode,
+ /* brief TBD */
+ ddi_bc_State_BrokenCode,
+ /* brief TBD */
+ ddi_bc_SettingChargeCode,
+ /* brief TBD */
+ ddi_bc_RaisingDieTempAlarmCode,
+ /* brief TBD */
+ ddi_bc_DroppingDieTempAlarmCode,
+
+ /* brief TBD */
+ ddi_bc_MaxEventCode,
+ /* brief TBD */
+ ddi_bc_DcdcModeWaitingToChargeCode
+} ddi_bc_Event_t;
+
+
+/* Prototypes */
+
+
+
+/* brief Initialize the Battery Charger. */
+/* */
+/* fntype Function */
+/* */
+/* This function initializes the Battery Charger. */
+/* */
+/* param[in] pCfg A pointer to the new configuration. */
+/* */
+/* retval DDI_BC_STATUS_SUCCESS */
+/* If the operation succeeded. */
+/* retval DDI_BC_STATUS_ALREADY_INITIALIZED */
+/* If the Battery Charger is already initialized. */
+/* retval DDI_BC_STATUS_HARDWARE_DISABLED */
+/* If the Battery Charger hardware is disabled by a laser fuse. */
+/* retval DDI_BC_STATUS_BAD_BATTERY_MODE */
+/* If the power supply is set up for a non-rechargeable battery. */
+/* retval DDI_BC_STATUS_CLOCK_GATE_CLOSED */
+/* If the clock gate for the power supply registers is closed. */
+/* retval DDI_BC_STATUS_CFG_BAD_CHARGING_VOLTAGE */
+/* If the charging voltage is not either 4100 or 4200. */
+/* retval DDI_BC_STATUS_CFG_BAD_BATTERY_TEMP_CHANNEL */
+/* If the LRADC channel number for monitoring battery temperature */
+/* is bad. */
+/* */
+/* internal */
+/* see To view the function definition, see ddi_bc_init.c. */
+
+extern ddi_bc_Status_t ddi_bc_Init(ddi_bc_Cfg_t *pCfg);
+
+/* */
+/* brief Report the Battery Charger configuration. */
+/* */
+/* fntype Function */
+/* */
+/* This function reports the Battery Charger configuration. */
+/* */
+/* Note that, if the Battery Charger has not yet been initialized, the data */
+/* returned by this function is unknown. */
+/* */
+/* param[in,out] pCfg A pointer to a structure that will receive the data. */
+/* */
+/* internal */
+/* see To view the function definition, see ddi_bc_api.c. */
+
+extern void ddi_bc_QueryCfg(ddi_bc_Cfg_t *pCfg);
+
+/* */
+/* brief Shut down the Battery Charger. */
+/* */
+/* fntype Function */
+/* */
+/* This function immediately shuts down the Battery Charger hardware and */
+/* returns the state machine to the Uninitialized state. Use this function to */
+/* safely mummify the battery charger before retiring it from memory. */
+/* */
+/* internal */
+/* see To view the function definition, see ddi_bc_api.c. */
+
+extern void ddi_bc_ShutDown(void);
+
+/* */
+/* brief Advances the state machine. */
+/* */
+/* fntype Function */
+/* */
+/* This function advances the state machine. */
+/* */
+/* retval DDI_BC_STATUS_SUCCESS If all goes well */
+/* retval DDI_BC_STATUS_NOT_INITIALIZED If the Battery Charger is not yet */
+/* initialized. */
+/* retval DDI_BC_STATUS_BROKEN If the battery violated a time-out */
+/* and has been declared broken. */
+/* */
+/* internal */
+/* see To view the function definition, see ddi_bc_api.c. */
+
+extern ddi_bc_Status_t ddi_bc_StateMachine(void);
+
+/* */
+/* brief Get the Battery Charger's current state. */
+/* */
+/* fntype Function */
+/* */
+/* This function returns the current state. */
+/* */
+/* retval The current state. */
+/* */
+/* internal */
+/* see To view the function definition, see ddi_bc_api.c. */
+
+extern ddi_bc_State_t ddi_bc_GetState(void);
+
+/* */
+/* brief Disable the Battery Charger. */
+/* */
+/* fntype Function */
+/* */
+/* This function forces the Battery Charger into the Disabled state. */
+/* */
+/* retval DDI_BC_STATUS_SUCCESS If all goes well */
+/* retval DDI_BC_STATUS_NOT_INITIALIZED If the Battery Charger is not yet */
+/* initialized. */
+/* */
+/* internal */
+/* see To view the function definition, see ddi_bc_api.c. */
+
+extern ddi_bc_Status_t ddi_bc_SetDisable(void);
+
+/* */
+/* brief Enable the Battery Charger. */
+/* */
+/* fntype Function */
+/* */
+/* If the Battery Charger is in the Disabled state, this function moves it to */
+/* the Waiting to Charge state. */
+/* */
+/* retval DDI_BC_STATUS_SUCCESS If all goes well */
+/* retval DDI_BC_STATUS_NOT_INITIALIZED If the Battery Charger is not yet */
+/* initialized. */
+/* retval DDI_BC_STATUS_NOT_DISABLED If the Battery Charger is not */
+/* disabled. */
+/* */
+/* internal */
+/* see To view the function definition, see ddi_bc_api.c. */
+
+extern ddi_bc_Status_t ddi_bc_SetEnable(void);
+
+/* */
+/* brief Declare the battery to be broken. */
+/* */
+/* fntype Function */
+/* */
+/* This function forces the Battery Charger into the Broken state. */
+/* */
+/* retval DDI_BC_STATUS_SUCCESS If all goes well */
+/* retval DDI_BC_STATUS_NOT_INITIALIZED If the Battery Charger is not yet */
+/* initialized. */
+/* */
+/* internal */
+/* see To view the function definition, see ddi_bc_api.c. */
+
+extern ddi_bc_Status_t ddi_bc_SetBroken(void);
+
+/* */
+/* brief Declare the battery to be fixed. */
+/* */
+/* fntype Function */
+/* */
+/* If the Battery Charger is in the Broken state, this function moves it to */
+/* the Disabled state. */
+/* */
+/* retval DDI_BC_STATUS_SUCCESS If all goes well */
+/* retval DDI_BC_STATUS_NOT_INITIALIZED If the Battery Charger is not yet */
+/* initialized. */
+/* retval DDI_BC_STATUS_NOT_BROKEN If the Battery Charger is not broken. */
+/* */
+/* internal */
+/* see To view the function definition, see ddi_bc_api.c. */
+
+extern ddi_bc_Status_t ddi_bc_SetFixed(void);
+
+/* */
+/* brief Set the current limit. */
+/* */
+/* fntype Function */
+/* */
+/* This function applies a limit to the current that the Battery Charger can */
+/* draw. */
+/* */
+/* param[in] u16Limit The maximum current the Battery Charger can draw */
+/* (in mA). */
+/* */
+/* retval The expressible version of the limit. */
+/* */
+/* internal */
+/* see To view the function definition, see ddi_bc_api.c. */
+
+extern uint16_t ddi_bc_SetCurrentLimit(uint16_t u16Limit);
+
+
+/* */
+/* brief Report the current limit. */
+/* */
+/* fntype Function */
+/* */
+/* This function reports the limit to the current that the Battery Charger can */
+/* draw. */
+/* */
+/* retval The current limit. */
+/* */
+/* internal */
+/* see To view the function definition, see ddi_bc_api.c. */
+
+extern uint16_t ddi_bc_GetCurrentLimit(void);
+
+
+/* */
+/* brief Set the current threshold. */
+/* */
+/* fntype Function */
+/* */
+/* */
+/* param[in] u16Current Current threshold where charger deactivates (in mA). */
+/* */
+/* */
+
+extern uint16_t ddi_bc_SetCurrentThreshold(uint16_t u16Current);
+
+
+/* */
+/* brief Set the battery charger state machine period. */
+/* */
+/* fntype Function */
+/* */
+/* This function sets a new state machine period. The Period and Slope should */
+/* be coordinated to achieve the minimal ramp step current which will minimize */
+/* transients on the system. */
+/* */
+/* param[in] u32StateMachinePeriod (in milliseconds) */
+/* param[in] u16CurrentRampSlope (in mA/s) */
+/* */
+/* retval SUCCESS If all goes well */
+/* retval ERROR_DDI_BCM_NOT_INITIALIZED If the Battery Charger is not yet */
+/* initialized. */
+/* */
+
+extern ddi_bc_Status_t ddi_bc_SetNewPeriodAndSlope(uint32_t
+ u32StateMachinePeriod,
+ uint16_t
+ u16CurrentRampSlope);
+
+
+/* */
+/* brief Report the state machine period. */
+/* */
+/* fntype Function */
+/* */
+/* This function reports the battery charger period. */
+/* */
+/* retval The battery charger period (in milliseconds). */
+/* */
+
+extern uint32_t ddi_bc_GetStateMachinePeriod(void);
+
+
+/* */
+/* brief Report the current ramp slope. */
+/* */
+/* fntype Function */
+/* */
+/* This function reports the current ramp slope. */
+/* */
+/* retval The current ramp slope (in mA/s). */
+/* */
+
+extern uint32_t ddi_bc_GetCurrentRampSlope(void);
+
+
+/* */
+/* brief Report the time spent in the present state (milliseconds) */
+/* */
+/* fntype Function */
+/* */
+/* This function reports the time spent in the present charging state. Note that */
+/* for the states that actually charge the battery, this time does not include the */
+/* time spent under alarm conditions such as die termperature alarm or battery */
+/* temperature alarm. */
+/* */
+/* retval The time spent in the current state in milliseconds. */
+/* */
+
+uint32_t ddi_bc_GetStateTime(void);
+
+
+/* */
+/* brief Report the reason for being in the broken state */
+/* */
+/* fntype Function */
+/* */
+/* */
+/* retval ddi_bc_BrokenReason_t enumeration */
+/* */
+
+ddi_bc_BrokenReason_t ddi_bc_GetBrokenReason(void);
+
+
+/* */
+/* brief Restart the charge cycle */
+/* */
+/* fntype Function */
+/* */
+/* retval SUCCESS */
+/* */
+
+ddi_bc_Status_t ddi_bc_ForceChargingToStart(void);
+
+void fsl_enable_usb_plugindetect(void);
+
+int fsl_is_usb_plugged(void);
+
+/* End of file */
+
+#endif /* _DDI_BC_H */
+/* @} */
diff --git a/arch/arm/plat-mxs/include/mach/debug-macro.S b/arch/arm/plat-mxs/include/mach/debug-macro.S
new file mode 100644
index 000000000000..147cda360cb3
--- /dev/null
+++ b/arch/arm/plat-mxs/include/mach/debug-macro.S
@@ -0,0 +1,42 @@
+/*
+ * Debugging macro include header
+ *
+ * Embedded Alley Solutions, Inc <source@embeddedalley.com>
+ *
+ * Copyright 2008-2010 Freescale Semiconductor, Inc.
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <mach/hardware.h>
+
+ .macro addruart,rx,tmp
+ mrc p15, 0, \rx, c1, c0
+ tst \rx, #1 @ MMU enabled?
+ ldreq \rx, =MXS_LL_UART_PADDR @ physical
+ ldrne \rx, =MXS_LL_UART_VADDR @ virtual
+ .endm
+
+ .macro senduart,rd,rx
+ strb \rd, [\rx, #0] @ data register at 0
+ .endm
+
+ .macro waituart,rd,rx
+1001: ldr \rd, [\rx, #0x18] @ UARTFLG
+ tst \rd, #1 << 5 @ UARTFLGUTXFF - 1 when full
+ bne 1001b
+ .endm
+
+ .macro busyuart,rd,rx
+1001: ldr \rd, [\rx, #0x18] @ UARTFLG
+ tst \rd, #1 << 3 @ UARTFLGUBUSY - 1 when busy
+ bne 1001b
+ .endm
diff --git a/arch/arm/plat-mxs/include/mach/device.h b/arch/arm/plat-mxs/include/mach/device.h
new file mode 100644
index 000000000000..080add7d8fa2
--- /dev/null
+++ b/arch/arm/plat-mxs/include/mach/device.h
@@ -0,0 +1,195 @@
+/*
+ * Copyright (C) 2009-2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef __ASM_ARM_ARCH_DEVICE_H
+#define __ASM_ARM_ARCH_DEVICE_H
+
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/ioport.h>
+#include <linux/leds.h>
+
+#include <asm/mach/time.h>
+
+#define MXS_MAX_DEVICES 128
+
+struct mxs_sys_timer {
+ struct sys_timer timer;
+ unsigned char id;
+ unsigned char clk_sel;
+ unsigned char resv[2];
+ int irq;
+ struct clk *clk;
+ void __iomem *base;
+};
+
+struct mxs_dev_lookup {
+ char *name;
+ unsigned long lock;
+ int size;
+ struct platform_device *pdev;
+};
+
+/* Define the Platform special structure for each device type*/
+struct mxs_dma_plat_data {
+ unsigned int burst8:1;
+ unsigned int burst:1;
+ unsigned int chan_base;
+ unsigned int chan_num;
+};
+
+struct fsl_otp_data {
+ char **fuse_name;
+ char *regulator_name;
+ unsigned int fuse_num;
+};
+
+struct mxs_i2c_plat_data {
+ unsigned int pioqueue_mode:1;
+};
+
+struct mxs_lradc_plat_data {
+ unsigned int vddio_voltage;
+ unsigned int battery_voltage;
+};
+
+struct mxskbd_keypair {
+ int raw;
+ int kcode;
+};
+
+struct mxs_kbd_plat_data {
+ struct mxskbd_keypair *keypair;
+ int channel;
+ unsigned int btn_enable; /* detect enable bits */
+ unsigned int btn_irq_stat; /* detect irq status bits */
+ unsigned int btn_irq_ctrl; /* detect irq enable bits */
+};
+
+struct mxs_touchscreen_plat_data {
+ u8 x_plus_chan;
+ u8 x_minus_chan;
+ u8 y_plus_chan;
+ u8 y_minus_chan;
+ unsigned int x_plus_val;
+ unsigned int x_minus_val;
+ unsigned int y_plus_val;
+ unsigned int y_minus_val;
+ unsigned int x_plus_mask;
+ unsigned int x_minus_mask;
+ unsigned int y_plus_mask;
+ unsigned int y_minus_mask;
+};
+
+struct mxs_auart_plat_data {
+ unsigned int fifo_size:6;
+ unsigned int dma_mode:1;
+ unsigned int timeout;
+ unsigned int dma_rx_buffer_size;
+ const char *clk;
+};
+
+struct mxs_pwm_led {
+ struct led_classdev dev;
+ const char *name;
+ unsigned int pwm;
+};
+
+struct mxs_pwm_leds_plat_data {
+ unsigned int num;
+ struct mxs_pwm_led *leds;
+};
+
+struct mxs_mma7450_platform_data {
+ char *reg_dvdd_io;
+ char *reg_avdd;
+ void (*gpio_pin_get) (void);
+ void (*gpio_pin_put) (void);
+ int int1;
+ int int2;
+};
+
+struct mxs_spi_platform_data {
+ int (*hw_pin_init)(void);
+ int (*hw_pin_release)(void);
+
+ char *clk;
+};
+
+struct mxs_audio_platform_data {
+ int intr_id_hp;
+ int ext_ram;
+ struct clk *saif_mclock;
+
+ int hp_irq;
+ int (*hp_status) (void);
+
+ int sysclk;
+
+ int (*init) (void); /* board specific init */
+ int (*amp_enable) (int enable);
+ int (*finit) (void); /* board specific finit */
+ void *priv; /* used by board specific functions */
+};
+
+struct mxs_persistent_bit_config {
+ int reg;
+ int start;
+ int width;
+ const char *name;
+};
+
+struct mxs_platform_persistent_data {
+ const struct mxs_persistent_bit_config *bit_config_tab;
+ int bit_config_cnt;
+};
+
+extern void mxs_timer_init(struct mxs_sys_timer *timer);
+extern void mxs_nomatch_timer_init(struct mxs_sys_timer *timer);
+
+extern void mxs_nop_release(struct device *dev);
+extern int mxs_add_devices(struct platform_device *, int num, int level);
+extern int mxs_add_device(struct platform_device *, int level);
+extern struct platform_device *mxs_get_device(char *name, int id);
+extern struct mxs_dev_lookup *mxs_get_devices(char *name);
+
+extern int iram_init(unsigned long base, unsigned long size);
+
+/* mxs ssp sd/mmc data definitons */
+struct mxs_mmc_platform_data {
+ int (*hw_init)(void);
+ void (*hw_release)(void);
+ void (*cmd_pullup)(int enable);
+ int (*get_wp)(void);
+ unsigned long (*setclock)(unsigned long hz);
+ unsigned int caps;
+ unsigned int min_clk;
+ unsigned int max_clk;
+ int read_uA;
+ int write_uA;
+ char *power_mmc;
+ char *clock_mmc;
+};
+/* end of mxs ssp sd/mmc data definitions */
+
+#ifdef CONFIG_MXS_ICOLL
+extern void __init avic_init_irq(void __iomem *base, int nr_irqs);
+#endif
+
+#endif
diff --git a/arch/arm/plat-mxs/include/mach/dmaengine.h b/arch/arm/plat-mxs/include/mach/dmaengine.h
new file mode 100644
index 000000000000..1600d9762a9e
--- /dev/null
+++ b/arch/arm/plat-mxs/include/mach/dmaengine.h
@@ -0,0 +1,518 @@
+/*
+ * Copyright (C) 2009-2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef __ASM_ARM_ARCH_DMA_H
+#define __ASM_ARM_ARCH_DMA_H
+
+#ifndef ARCH_DMA_PIO_WORDS
+#define DMA_PIO_WORDS 15
+#else
+#define DMA_PIO_WORDS ARCH_DMA_PIO_WORDS
+#endif
+
+#define MXS_DMA_ALIGNMENT 8
+
+/**
+ * struct mxs_dma_cmd_bits - MXS DMA hardware command bits.
+ *
+ * This structure describes the in-memory layout of the command bits in a DMA
+ * command. See the appropriate reference manual for a detailed description
+ * of what these bits mean to the DMA hardware.
+ */
+struct mxs_dma_cmd_bits {
+ unsigned int command:2;
+#define NO_DMA_XFER 0x00
+#define DMA_WRITE 0x01
+#define DMA_READ 0x02
+#define DMA_SENSE 0x03
+
+ unsigned int chain:1;
+ unsigned int irq:1;
+ unsigned int nand_lock:1;
+ unsigned int nand_wait_4_ready:1;
+ unsigned int dec_sem:1;
+ unsigned int wait4end:1;
+ unsigned int halt_on_terminate:1;
+ unsigned int terminate_flush:1;
+ unsigned int resv2:2;
+ unsigned int pio_words:4;
+ unsigned int bytes:16;
+};
+
+/* fill the word 1 of the DMA channel command structure */
+#define fill_dma_word1(cmdp, _cmd, _chain, _irq, _lock, _wait_ready, _dec_sem,\
+ _wait4end, _halt_on_term, _term_flush, _pio_words, _bytes)\
+ do { \
+ struct mxs_dma_cmd_bits *bits = &(cmdp)->bits; \
+ \
+ /* reset all the fields first */ \
+ (cmdp)->data = 0; \
+ \
+ bits->command = _cmd; \
+ bits->chain = _chain; \
+ bits->irq = _irq; \
+ bits->nand_lock = _lock; \
+ bits->nand_wait_4_ready = _wait_ready; \
+ bits->dec_sem = _dec_sem; \
+ bits->wait4end = _wait4end; \
+ bits->halt_on_terminate = _halt_on_term; \
+ bits->terminate_flush = _term_flush; \
+ bits->pio_words = _pio_words; \
+ bits->bytes = _bytes; \
+ } while (0)
+
+/**
+ * struct mxs_dma_cmd - MXS DMA hardware command.
+ *
+ * This structure describes the in-memory layout of an entire DMA command,
+ * including space for the maximum number of PIO accesses. See the appropriate
+ * reference manual for a detailed description of what these fields mean to the
+ * DMA hardware.
+ */
+struct mxs_dma_cmd {
+ unsigned long next;
+ union {
+ unsigned long data;
+ struct mxs_dma_cmd_bits bits;
+ } cmd;
+ union {
+ dma_addr_t address;
+ unsigned long alternate;
+ };
+ unsigned long pio_words[DMA_PIO_WORDS];
+};
+
+/**
+ * struct mxs_dma_desc - MXS DMA command descriptor.
+ *
+ * This structure incorporates an MXS DMA hardware command structure, along
+ * with metadata.
+ *
+ * @cmd: The MXS DMA hardware command block.
+ * @flags: Flags that represent the state of this DMA descriptor.
+ * @address: The physical address of this descriptor.
+ * @buffer: A convenient place for software to put the virtual address of the
+ * associated data buffer (the physical address of the buffer
+ * appears in the DMA command). The MXS platform DMA software doesn't
+ * use this field -- it is provided as a convenience.
+ * @node: Links this structure into a list.
+ */
+struct mxs_dma_desc {
+ struct mxs_dma_cmd cmd;
+ unsigned int flags;
+#define MXS_DMA_DESC_READY 0x80000000
+#define MXS_DMA_DESC_FIRST 0x00000001
+#define MXS_DMA_DESC_LAST 0x00000002
+ dma_addr_t address;
+ void *buffer;
+ struct list_head node;
+};
+
+struct mxs_dma_info {
+ unsigned int status;
+#define MXS_DMA_INFO_ERR 0x00000001
+#define MXS_DMA_INFO_ERR_STAT 0x00010000
+ unsigned int buf_addr;
+ unsigned int xfer_count;
+};
+
+/**
+ * struct mxs_dma_chan - MXS DMA channel
+ *
+ * This structure represents a single DMA channel. The MXS platform code
+ * maintains an array of these structures to represent every DMA channel in the
+ * system (see mxs_dma_channels).
+ *
+ * @name: A human-readable string that describes how this channel is
+ * being used or what software "owns" it. This field is set when
+ * when the channel is reserved by mxs_dma_request().
+ * @dev: A pointer to a struct device *, cast to an unsigned long, and
+ * representing the software that "owns" the channel. This field
+ * is set when when the channel is reserved by mxs_dma_request().
+ * @lock: Arbitrates access to this channel.
+ * @dma: A pointer to a struct mxs_dma_device representing the driver
+ * code that operates this channel.
+ * @flags: Flag bits that represent the state of this channel.
+ * @active_num: If the channel is not busy, this value is zero. If the channel
+ * is busy, this field contains the number of DMA command
+ * descriptors at the head of the active list that the hardware
+ * has been told to process. This value is set at the moment the
+ * channel is enabled by mxs_dma_enable(). More descriptors may
+ * arrive after the channel is enabled, so the number of
+ * descriptors on the active list may be greater than this value.
+ * In fact, it should always be active_num + pending_num.
+ * @pending_num: The number of DMA command descriptors at the tail of the
+ * active list that the hardware has not been told to process.
+ * @active: The list of DMA command descriptors either currently being
+ * processed by the hardware or waiting to be processed.
+ * Descriptors being processed appear at the head of the list,
+ * while pending descriptors appear at the tail. The total number
+ * should always be active_num + pending_num.
+ * @done: The list of DMA command descriptors that have either been
+ * processed by the DMA hardware or aborted by a call to
+ * mxs_dma_disable().
+ */
+struct mxs_dma_chan {
+ const char *name;
+ unsigned long dev;
+ spinlock_t lock;
+ struct mxs_dma_device *dma;
+ unsigned int flags;
+#define MXS_DMA_FLAGS_IDLE 0x00000000
+#define MXS_DMA_FLAGS_BUSY 0x00000001
+#define MXS_DMA_FLAGS_FREE 0x00000000
+#define MXS_DMA_FLAGS_ALLOCATED 0x00010000
+#define MXS_DMA_FLAGS_VALID 0x80000000
+ unsigned int active_num;
+ unsigned int pending_num;
+ struct list_head active;
+ struct list_head done;
+};
+
+/**
+ * struct mxs_dma_device - DMA channel driver interface.
+ *
+ * This structure represents the driver that operates a DMA channel. Every
+ * struct mxs_dma_chan contains a pointer to a structure of this type, which is
+ * installed when the driver registers to "own" the channel (see
+ * mxs_dma_device_register()).
+ */
+struct mxs_dma_device {
+ struct list_head node;
+ const char *name;
+ void __iomem *base;
+ unsigned int chan_base;
+ unsigned int chan_num;
+ unsigned int data;
+ struct platform_device *pdev;
+
+ /* operations */
+ int (*enable) (struct mxs_dma_chan *, unsigned int);
+ void (*disable) (struct mxs_dma_chan *, unsigned int);
+ void (*reset) (struct mxs_dma_device *, unsigned int);
+ void (*freeze) (struct mxs_dma_device *, unsigned int);
+ void (*unfreeze) (struct mxs_dma_device *, unsigned int);
+ int (*read_semaphore) (struct mxs_dma_device *, unsigned int);
+ void (*add_semaphore) (struct mxs_dma_device *, unsigned int, unsigned);
+ void (*info)(struct mxs_dma_device *,
+ unsigned int, struct mxs_dma_info *info);
+ void (*enable_irq) (struct mxs_dma_device *, unsigned int, int);
+ int (*irq_is_pending) (struct mxs_dma_device *, unsigned int);
+ void (*ack_irq) (struct mxs_dma_device *, unsigned int);
+
+ void (*set_target) (struct mxs_dma_device *, unsigned int, int);
+};
+
+/**
+ * mxs_dma_device_register - Register a DMA driver.
+ *
+ * This function registers a driver for a contiguous group of DMA channels (the
+ * ordering of DMA channels is specified by the globally unique DMA channel
+ * numbers given in mach/dma.h).
+ *
+ * @pdev: A pointer to a structure that represents the driver. This structure
+ * contains fields that specify the first DMA channel number and the
+ * number of channels.
+ */
+extern int mxs_dma_device_register(struct mxs_dma_device *pdev);
+
+/**
+ * mxs_dma_request - Request to reserve a DMA channel.
+ *
+ * @channel: The channel number. This is one of the globally unique DMA channel
+ * numbers given in mach/dma.h.
+ * @dev: A pointer to a struct device representing the channel "owner."
+ * @name: A human-readable string that identifies the channel owner or the
+ * purpose of the channel.
+ */
+extern int mxs_dma_request(int channel, struct device *dev, const char *name);
+
+/**
+ * mxs_dma_release - Release a DMA channel.
+ *
+ * This function releases a DMA channel from its current owner.
+ *
+ * The channel will NOT be released if it's marked "busy" (see
+ * mxs_dma_enable()).
+ *
+ * @channel: The channel number. This is one of the globally unique DMA channel
+ * numbers given in mach/dma.h.
+ * @dev: A pointer to a struct device representing the channel "owner." If
+ * this doesn't match the owner given to mxs_dma_request(), the
+ * channel will NOT be released.
+ */
+extern void mxs_dma_release(int channel, struct device *dev);
+
+/**
+ * mxs_dma_enable - Enable a DMA channel.
+ *
+ * If the given channel has any DMA descriptors on its active list, this
+ * function causes the DMA hardware to begin processing them.
+ *
+ * This function marks the DMA channel as "busy," whether or not there are any
+ * descriptors to process.
+ *
+ * @channel: The channel number. This is one of the globally unique DMA channel
+ * numbers given in mach/dma.h.
+ */
+extern int mxs_dma_enable(int channel);
+
+/**
+ * mxs_dma_disable - Disable a DMA channel.
+ *
+ * This function shuts down a DMA channel and marks it as "not busy." Any
+ * descriptors on the active list are immediately moved to the head of the
+ * "done" list, whether or not they have actually been processed by the
+ * hardware. The "ready" flags of these descriptors are NOT cleared, so they
+ * still appear to be active.
+ *
+ * This function immediately shuts down a DMA channel's hardware, aborting any
+ * I/O that may be in progress, potentially leaving I/O hardware in an undefined
+ * state. It is unwise to call this function if there is ANY chance the hardware
+ * is still processing a command.
+ *
+ * @channel: The channel number. This is one of the globally unique DMA channel
+ * numbers given in mach/dma.h.
+ */
+extern void mxs_dma_disable(int channel);
+
+/**
+ * mxs_dma_reset - Resets the DMA channel hardware.
+ *
+ * @channel: The channel number. This is one of the globally unique DMA channel
+ * numbers given in mach/dma.h.
+ */
+extern void mxs_dma_reset(int channel);
+
+/**
+ * mxs_dma_freeze - Freeze a DMA channel.
+ *
+ * This function causes the channel to continuously fail arbitration for bus
+ * access, which halts all forward progress without losing any state. A call to
+ * mxs_dma_unfreeze() will cause the channel to continue its current operation
+ * with no ill effect.
+ *
+ * @channel: The channel number. This is one of the globally unique DMA channel
+ * numbers given in mach/dma.h.
+ */
+extern void mxs_dma_freeze(int channel);
+
+/**
+ * mxs_dma_unfreeze - Unfreeze a DMA channel.
+ *
+ * This function reverses the effect of mxs_dma_freeze(), enabling the DMA
+ * channel to continue from where it was frozen.
+ *
+ * @channel: The channel number. This is one of the globally unique DMA channel
+ * numbers given in mach/dma.h.
+ */
+
+extern void mxs_dma_unfreeze(int channel);
+
+/* get dma channel information */
+extern int mxs_dma_get_info(int channel, struct mxs_dma_info *info);
+
+/**
+ * mxs_dma_cooked - Clean up processed DMA descriptors.
+ *
+ * This function removes processed DMA descriptors from the "active" list. Pass
+ * in a non-NULL list head to get the descriptors moved to your list. Pass NULL
+ * to get the descriptors moved to the channel's "done" list. Descriptors on
+ * the "done" list can be retrieved with mxs_dma_get_cooked().
+ *
+ * This function marks the DMA channel as "not busy" if no unprocessed
+ * descriptors remain on the "active" list.
+ *
+ * @channel: The channel number. This is one of the globally unique DMA channel
+ * numbers given in mach/dma.h.
+ * @head: If this is not NULL, it is the list to which the processed
+ * descriptors should be moved. If this list is NULL, the descriptors
+ * will be moved to the "done" list.
+ */
+extern int mxs_dma_cooked(int channel, struct list_head *head);
+
+/**
+ * mxs_dma_read_semaphore - Read a DMA channel's hardware semaphore.
+ *
+ * As used by the MXS platform's DMA software, the DMA channel's hardware
+ * semaphore reflects the number of DMA commands the hardware will process, but
+ * has not yet finished. This is a volatile value read directly from hardware,
+ * so it must be be viewed as immediately stale.
+ *
+ * If the channel is not marked busy, or has finished processing all its
+ * commands, this value should be zero.
+ *
+ * See mxs_dma_append() for details on how DMA command blocks must be configured
+ * to maintain the expected behavior of the semaphore's value.
+ *
+ * @channel: The channel number. This is one of the globally unique DMA channel
+ * numbers given in mach/dma.h.
+ */
+extern int mxs_dma_read_semaphore(int channel);
+
+/**
+ * mxs_dma_irq_is_pending - Check if a DMA interrupt is pending.
+ *
+ * @channel: The channel number. This is one of the globally unique DMA channel
+ * numbers given in mach/dma.h.
+ */
+extern int mxs_dma_irq_is_pending(int channel);
+
+/**
+ * mxs_dma_enable_irq - Enable or disable DMA interrupt.
+ *
+ * This function enables the given DMA channel to interrupt the CPU.
+ *
+ * @channel: The channel number. This is one of the globally unique DMA channel
+ * numbers given in mach/dma.h.
+ * @en: True if the interrupt for this channel should be enabled. False
+ * otherwise.
+ */
+extern void mxs_dma_enable_irq(int channel, int en);
+
+/**
+ * mxs_dma_ack_irq - Clear DMA interrupt.
+ *
+ * The software that is using the DMA channel must register to receive its
+ * interrupts and, when they arrive, must call this function to clear them.
+ *
+ * @channel: The channel number. This is one of the globally unique DMA channel
+ * numbers given in mach/dma.h.
+ */
+extern void mxs_dma_ack_irq(int channel);
+
+/**
+ * mxs_dma_set_target - Set the target for a DMA channel.
+ *
+ * This function is NOT used on the i.MX28.
+ *
+ * @channel: The channel number. This is one of the globally unique DMA channel
+ * numbers given in mach/dma.h.
+ * @target: Indicates the target for the channel.
+ */
+extern void mxs_dma_set_target(int channel, int target);
+
+/* mxs dma utility functions */
+extern struct mxs_dma_desc *mxs_dma_alloc_desc(void);
+extern void mxs_dma_free_desc(struct mxs_dma_desc *);
+
+/**
+ * mxs_dma_cmd_address - Return the address of the command within a descriptor.
+ *
+ * @desc: The DMA descriptor of interest.
+ */
+static inline unsigned int mxs_dma_cmd_address(struct mxs_dma_desc *desc)
+{
+ return desc->address += offsetof(struct mxs_dma_desc, cmd);
+}
+
+/**
+ * mxs_dma_desc_pending - Check if descriptor is on a channel's active list.
+ *
+ * This function returns the state of a descriptor's "ready" flag. This flag is
+ * usually set only if the descriptor appears on a channel's active list. The
+ * descriptor may or may not have already been processed by the hardware.
+ *
+ * The "ready" flag is set when the descriptor is submitted to a channel by a
+ * call to mxs_dma_append() or mxs_dma_append_list(). The "ready" flag is
+ * cleared when a processed descriptor is moved off the active list by a call
+ * to mxs_dma_cooked(). The "ready" flag is NOT cleared if the descriptor is
+ * aborted by a call to mxs_dma_disable().
+ *
+ * @desc: The DMA descriptor of interest.
+ */
+static inline int mxs_dma_desc_pending(struct mxs_dma_desc *pdesc)
+{
+ return pdesc->flags & MXS_DMA_DESC_READY;
+}
+
+/**
+ * mxs_dma_desc_append - Add a DMA descriptor to a channel.
+ *
+ * If the descriptor list for this channel is not empty, this function sets the
+ * CHAIN bit and the NEXTCMD_ADDR fields in the last descriptor's DMA command so
+ * it will chain to the new descriptor's command.
+ *
+ * Then, this function marks the new descriptor as "ready," adds it to the end
+ * of the active descriptor list, and increments the count of pending
+ * descriptors.
+ *
+ * The MXS platform DMA software imposes some rules on DMA commands to maintain
+ * important invariants. These rules are NOT checked, but they must be carefully
+ * applied by software that uses MXS DMA channels.
+ *
+ * Invariant:
+ * The DMA channel's hardware semaphore must reflect the number of DMA
+ * commands the hardware will process, but has not yet finished.
+ *
+ * Explanation:
+ * A DMA channel begins processing commands when its hardware semaphore is
+ * written with a value greater than zero, and it stops processing commands
+ * when the semaphore returns to zero.
+ *
+ * When a channel finishes a DMA command, it will decrement its semaphore if
+ * the DECREMENT_SEMAPHORE bit is set in that command's flags bits.
+ *
+ * In principle, it's not necessary for the DECREMENT_SEMAPHORE to be set,
+ * unless it suits the purposes of the software. For example, one could
+ * construct a series of five DMA commands, with the DECREMENT_SEMAPHORE
+ * bit set only in the last one. Then, setting the DMA channel's hardware
+ * semaphore to one would cause the entire series of five commands to be
+ * processed. However, this example would violate the invariant given above.
+ *
+ * Rule:
+ * ALL DMA commands MUST have the DECREMENT_SEMAPHORE bit set so that the DMA
+ * channel's hardware semaphore will be decremented EVERY time a command is
+ * processed.
+ *
+ * @channel: The channel number. This is one of the globally unique DMA channel
+ * numbers given in mach/dma.h.
+ * @pdesc: A pointer to the new descriptor.
+ */
+extern int mxs_dma_desc_append(int channel, struct mxs_dma_desc *pdesc);
+
+/**
+ * mxs_dma_desc_add_list - Add a list of DMA descriptors to a channel.
+ *
+ * This function marks all the new descriptors as "ready," adds them to the end
+ * of the active descriptor list, and adds the length of the list to the count
+ * of pending descriptors.
+ *
+ * See mxs_dma_desc_append() for important rules that apply to incoming DMA
+ * descriptors.
+ *
+ * @channel: The channel number. This is one of the globally unique DMA channel
+ * numbers given in mach/dma.h.
+ * @head: A pointer to the head of the list of DMA descriptors to add.
+ */
+extern int mxs_dma_desc_add_list(int channel, struct list_head *head);
+
+/**
+ * mxs_dma_desc_get_cooked - Retrieve processed DMA descriptors.
+ *
+ * This function moves all the descriptors from the DMA channel's "done" list to
+ * the head of the given list.
+ *
+ * @channel: The channel number. This is one of the globally unique DMA channel
+ * numbers given in mach/dma.h.
+ * @head: A pointer to the head of the list that will receive the
+ * descriptors on the "done" list.
+ */
+extern int mxs_dma_get_cooked(int channel, struct list_head *head);
+
+#endif
diff --git a/arch/arm/plat-mxs/include/mach/entry-macro.S b/arch/arm/plat-mxs/include/mach/entry-macro.S
new file mode 100644
index 000000000000..353a7b2cc8fd
--- /dev/null
+++ b/arch/arm/plat-mxs/include/mach/entry-macro.S
@@ -0,0 +1,36 @@
+/*
+ * Low-level IRQ helper macros for Freescale MXS-based
+ *
+ * Copyright (C) 2009-2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+ .macro disable_fiq
+ .endm
+
+ .macro get_irqnr_and_base, irqnr, irqstat, base, tmp
+ ldr \base, =g_icoll_base
+ ldr \base, [\base]
+ ldr \irqnr, [\base, #0x70]
+ cmp \irqnr, #0x7F
+ moveqs \irqnr, #0
+ .endm
+
+ .macro get_irqnr_preamble, base, tmp
+ .endm
+
+ .macro arch_ret_to_user, tmp1, tmp2
+ .endm
diff --git a/arch/arm/plat-mxs/include/mach/fsl_usb.h b/arch/arm/plat-mxs/include/mach/fsl_usb.h
new file mode 100644
index 000000000000..f88324856fc7
--- /dev/null
+++ b/arch/arm/plat-mxs/include/mach/fsl_usb.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 1999 ARM Limited
+ * Copyright (C) 2009-2010 Freescale Semiconductor, Inc.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+/*
+ * USB Host side, platform-specific functionality.
+ */
+
+#include <linux/usb/fsl_xcvr.h>
+#include <mach/arc_otg.h>
+
+/* ehci_arc_hc_driver.flags value */
+#define FSL_PLATFORM_HC_FLAGS (HCD_USB2 | HCD_MEMORY)
+
+static void fsl_setup_phy(struct ehci_hcd *ehci,
+ enum fsl_usb2_phy_modes phy_mode,
+ int port_offset);
+
+static inline void fsl_platform_usb_setup(struct ehci_hcd *ehci)
+{
+ struct fsl_usb2_platform_data *pdata;
+
+ pdata = ehci_to_hcd(ehci)->self.controller->platform_data;
+ fsl_setup_phy(ehci, pdata->phy_mode, 0);
+}
+
+static inline void fsl_platform_set_host_mode(struct usb_hcd *hcd)
+{
+ unsigned int temp;
+ struct fsl_usb2_platform_data *pdata;
+
+ pdata = hcd->self.controller->platform_data;
+
+ if (pdata->xcvr_ops && pdata->xcvr_ops->set_host)
+ pdata->xcvr_ops->set_host();
+
+ /* set host mode */
+ temp = readl(hcd->regs + UOG_USBMODE);
+ writel(temp | USBMODE_CM_HOST, hcd->regs + UOG_USBMODE);
+}
+
+/* Needed for i2c/serial transceivers */
+static inline void
+fsl_platform_set_vbus_power(struct fsl_usb2_platform_data *pdata, int on)
+{
+ if (pdata->xcvr_ops && pdata->xcvr_ops->set_vbus_power)
+ pdata->xcvr_ops->set_vbus_power(pdata->xcvr_ops, pdata, on);
+}
+
+/* Set USB AHB burst length for host */
+static inline void fsl_platform_set_ahb_burst(struct usb_hcd *hcd)
+{
+}
+
+void fsl_phy_usb_utmi_init(struct fsl_xcvr_ops *this);
+void fsl_phy_usb_utmi_uninit(struct fsl_xcvr_ops *this);
+void fsl_phy_set_power(struct fsl_xcvr_ops *this,
+ struct fsl_usb2_platform_data *pdata, int on);
+
diff --git a/arch/arm/plat-mxs/include/mach/fsl_usb_gadget.h b/arch/arm/plat-mxs/include/mach/fsl_usb_gadget.h
new file mode 100644
index 000000000000..767b344d7e95
--- /dev/null
+++ b/arch/arm/plat-mxs/include/mach/fsl_usb_gadget.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 1999 ARM Limited
+ * Copyright (C) 2009-2010 Freescale Semiconductor, Inc.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+/*
+ * USB Gadget side, platform-specific functionality.
+ */
+
+#include <linux/usb/fsl_xcvr.h>
+
+/* Needed for i2c/serial transceivers */
+static inline void
+fsl_platform_set_device_mode(struct fsl_usb2_platform_data *pdata)
+{
+ if (pdata->xcvr_ops && pdata->xcvr_ops->set_device)
+ pdata->xcvr_ops->set_device();
+}
+
+static inline void
+fsl_platform_pullup_enable(struct fsl_usb2_platform_data *pdata)
+{
+ if (pdata->xcvr_ops && pdata->xcvr_ops->pullup)
+ pdata->xcvr_ops->pullup(1);
+}
+
+static inline void
+fsl_platform_pullup_disable(struct fsl_usb2_platform_data *pdata)
+{
+ if (pdata->xcvr_ops && pdata->xcvr_ops->pullup)
+ pdata->xcvr_ops->pullup(0);
+}
diff --git a/arch/arm/plat-mxs/include/mach/gpio.h b/arch/arm/plat-mxs/include/mach/gpio.h
new file mode 100644
index 000000000000..7b634149ec23
--- /dev/null
+++ b/arch/arm/plat-mxs/include/mach/gpio.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 1999 ARM Limited
+ * Copyright (C) 2009-2010 Freescale Semiconductor, Inc.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef __ASM_ARCH_GPIO_H__
+#define __ASM_ARCH_GPIO_H__
+
+#include <mach/hardware.h>
+#include <asm-generic/gpio.h>
+
+#define GPIO_ID_NAME "gpio"
+/* use gpiolib dispatchers */
+#define gpio_get_value __gpio_get_value
+#define gpio_set_value __gpio_set_value
+#define gpio_cansleep __gpio_cansleep
+#define gpio_to_irq __gpio_to_irq
+#define irq_to_gpio(irq) ((irq) - MXS_GPIO_IRQ_START)
+
+struct mxs_gpio_port;
+struct mxs_gpio_chip {
+ int (*set_dir) (struct mxs_gpio_port *, int, unsigned int);
+ int (*get) (struct mxs_gpio_port *, int);
+ void (*set) (struct mxs_gpio_port *, int, int);
+ unsigned int (*get_irq_stat) (struct mxs_gpio_port *);
+ int (*set_irq_type) (struct mxs_gpio_port *, int, unsigned int);
+ void (*unmask_irq) (struct mxs_gpio_port *, int);
+ void (*mask_irq) (struct mxs_gpio_port *, int);
+ void (*ack_irq) (struct mxs_gpio_port *, int);
+};
+
+struct mxs_gpio_port {
+ int id;
+ int irq;
+ int child_irq;
+ struct mxs_gpio_chip *chip;
+ struct gpio_chip port;
+};
+
+extern int mxs_add_gpio_port(struct mxs_gpio_port *port);
+
+static inline void
+mxs_set_gpio_chip(struct mxs_gpio_port *port, struct mxs_gpio_chip *chip)
+{
+ if (port && chip)
+ port->chip = chip;
+}
+
+#endif /* __ASM_ARCH_GPIO_H__ */
diff --git a/arch/arm/plat-mxs/include/mach/hardware.h b/arch/arm/plat-mxs/include/mach/hardware.h
new file mode 100644
index 000000000000..c7dd8fe1d31b
--- /dev/null
+++ b/arch/arm/plat-mxs/include/mach/hardware.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2009-2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef __ASM_ARM_ARCH_HARDWARE_H
+#define __ASM_ARM_ARCH_HARDWARE_H
+
+#ifdef CONFIG_ARCH_MX28
+# include <mach/mx28.h>
+# define cpu_is_mx28() 1
+# else
+# define cpu_is_mx28() 0
+#endif
+
+#ifdef CONFIG_ARCH_MX23
+# include <mach/mx23.h>
+# define cpu_is_mx23() 1
+# else
+# define cpu_is_mx23() 0
+#endif
+
+#ifndef MXS_EXTEND_IRQS
+#define MXS_EXTEND_IRQS 0
+#endif
+
+#ifndef MXS_ARCH_NR_GPIOS
+#define MXS_ARCH_NR_GPIOS 160
+#endif
+
+#ifndef MXS_EXTEND_NR_GPIOS
+#define MXS_EXTEND_NR_GPIOS 0
+#endif
+
+#define ARCH_NR_GPIOS (MXS_ARCH_NR_GPIOS + MXS_EXTEND_NR_GPIOS)
+
+#define MXS_GPIO_IRQ_START ARCH_NR_IRQS
+#define MXS_EXTEND_IRQ_START (ARCH_NR_IRQS + ARCH_NR_GPIOS)
+
+#endif /* __ASM_ARM_ARCH_HARDWARE_H */
diff --git a/arch/arm/plat-mxs/include/mach/io.h b/arch/arm/plat-mxs/include/mach/io.h
new file mode 100644
index 000000000000..7dff55ef7f12
--- /dev/null
+++ b/arch/arm/plat-mxs/include/mach/io.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2009-2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef __ASM_ARM_ARCH_IO_H
+#define __ASM_ARM_ARCH_IO_H
+
+#define IO_SPACE_LIMIT 0xffffffff
+
+#define __io(a) __typesafe_io(a)
+#define __mem_pci(a) (a)
+#define __mem_isa(a) (a)
+
+#define SET_REGISTER 0x4
+#define CLR_REGISTER 0x8
+#define TOG_REGISTER 0xC
+
+struct mxs_io_bank {
+ unsigned int raw;
+ unsigned int set;
+ unsigned int clr;
+ unsigned int tog;
+};
+#endif
diff --git a/arch/arm/plat-mxs/include/mach/irqs.h b/arch/arm/plat-mxs/include/mach/irqs.h
new file mode 100644
index 000000000000..62165e12a60c
--- /dev/null
+++ b/arch/arm/plat-mxs/include/mach/irqs.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 1999 ARM Limited
+ * Copyright (C) 2009-2010 Freescale Semiconductor, Inc.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef __ASM_ARCH_IRQS_H__
+#define __ASM_ARCH_IRQS_H__
+
+#include <mach/hardware.h>
+
+#define NR_IRQS (ARCH_NR_IRQS + ARCH_NR_GPIOS + MXS_EXTEND_IRQS)
+
+#ifndef __ASSEMBLY__
+struct irq_ic_info {
+ unsigned int id_val;
+ unsigned int id_mask;
+ const char *name;
+ unsigned int base;
+};
+
+#define __irq_ic_info_attr __attribute__((__section__(".irq_ic_info.array")))
+
+extern struct irq_ic_info *current_irq_ic_info;
+
+void mxs_set_irq_fiq(unsigned int irq, unsigned int type);
+void mxs_enable_fiq_functionality(int enable);
+
+#endif
+
+#endif /* __ASM_ARCH_SYSTEM_H__ */
diff --git a/arch/arm/plat-mxs/include/mach/lradc.h b/arch/arm/plat-mxs/include/mach/lradc.h
new file mode 100644
index 000000000000..c2c0a7deb0b4
--- /dev/null
+++ b/arch/arm/plat-mxs/include/mach/lradc.h
@@ -0,0 +1,61 @@
+/*
+ * Freescale STMP37XX/STMP378X LRADC helper interface
+ *
+ * Embedded Alley Solutions, Inc <source@embeddedalley.com>
+ *
+ * Copyright 2008-2010 Freescale Semiconductor, Inc.
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+#ifndef __ASM_PLAT_LRADC_H
+#define __ASM_PLAT_LRADC_H
+
+int hw_lradc_use_channel(int);
+int hw_lradc_unuse_channel(int);
+extern u32 hw_lradc_vddio(void);
+void hw_lradc_set_delay_trigger_kick(int trigger, int value);
+void hw_lradc_configure_channel(int channel, int enable_div2,
+ int enable_acc, int samples);
+int hw_lradc_present(int channel);
+int hw_lradc_init_ladder(int channel, int trigger, unsigned sampling);
+int hw_lradc_stop_ladder(int channel, int trigger);
+void hw_lradc_set_delay_trigger(int trigger, u32 trigger_lradc,
+ u32 delay_triggers, u32 loops, u32 delays);
+void hw_lradc_clear_delay_trigger(int trigger, u32 trigger_lradc,
+ u32 delay_triggers);
+
+
+#define LRADC_CH0 0
+#define LRADC_CH1 1
+#define LRADC_CH2 2
+#define LRADC_CH3 3
+#define LRADC_CH4 4
+#define LRADC_CH5 5
+#define LRADC_CH6 6
+#define LRADC_CH7 7
+#define LRADC_TOUCH_X_PLUS LRADC_CH2
+#define LRADC_TOUCH_Y_PLUS LRADC_CH3
+#define LRADC_TOUCH_X_MINUS LRADC_CH4
+#define LRADC_TOUCH_Y_MINUS LRADC_CH5
+#define VDDIO_VOLTAGE_CH LRADC_CH6
+#define BATTERY_VOLTAGE_CH LRADC_CH7
+
+#define LRADC_CLOCK_6MHZ 0
+#define LRADC_CLOCK_4MHZ 1
+#define LRADC_CLOCK_3MHZ 2
+#define LRADC_CLOCK_2MHZ 3
+
+#define LRADC_DELAY_TRIGGER_BUTTON 0
+#define LRADC_DELAY_TRIGGER_BATTERY 1
+#define LRADC_DELAY_TRIGGER_TOUCHSCREEN 2
+#define LRADC_DELAY_TRIGGER_DIE 3
+
+#endif /* __ASM_PLAT_LRADC_H */
diff --git a/arch/arm/plat-mxs/include/mach/memory.h b/arch/arm/plat-mxs/include/mach/memory.h
new file mode 100644
index 000000000000..051b1608cca4
--- /dev/null
+++ b/arch/arm/plat-mxs/include/mach/memory.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2009-2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef __ASM_ARCH_MEMORY_H
+#define __ASM_ARCH_MEMORY_H
+
+#include <asm/page.h>
+#include <asm/sizes.h>
+
+/*
+ * Physical DRAM offset.
+ */
+#define PHYS_OFFSET UL(0x40000000)
+
+#ifndef __ASSEMBLY__
+
+#ifdef CONFIG_DMA_ZONE_SIZE
+#define MXS_DMA_ZONE_SIZE ((CONFIG_DMA_ZONE_SIZE * SZ_1M) >> PAGE_SHIFT)
+#else
+#define MXS_DMA_ZONE_SIZE ((12 * SZ_1M) >> PAGE_SHIFT)
+#endif
+
+static inline void __arch_adjust_zones(int node, unsigned long *zone_size,
+ unsigned long *zhole_size)
+{
+ if (node != 0)
+ return;
+ /* Create separate zone to reserve memory for DMA */
+ zone_size[1] = zone_size[0] - MXS_DMA_ZONE_SIZE;
+ zone_size[0] = MXS_DMA_ZONE_SIZE;
+ zhole_size[1] = zhole_size[0];
+ zhole_size[0] = 0;
+}
+
+#define arch_adjust_zones(node, size, holes) \
+ __arch_adjust_zones(node, size, holes)
+
+#endif
+
+#define ISA_DMA_THRESHOLD (0x0003ffffULL)
+
+#define CONSISTENT_DMA_SIZE SZ_32M
+
+#endif
diff --git a/arch/arm/plat-mxs/include/mach/pinctrl.h b/arch/arm/plat-mxs/include/mach/pinctrl.h
new file mode 100644
index 000000000000..6e02149f5ca6
--- /dev/null
+++ b/arch/arm/plat-mxs/include/mach/pinctrl.h
@@ -0,0 +1,152 @@
+/*
+ * Copyright (C) 2009-2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef __ASM_ARM_ARCH_PINCTRL_H
+#define __ASM_ARM_ARCH_PINCTRL_H
+
+#include <linux/types.h>
+#include <linux/gpio.h>
+
+#define PINS_PER_BANK 32
+#define GPIO_TO_PINS(gpio) ((gpio) % 32)
+#define GPIO_TO_BANK(gpio) ((gpio) / 32)
+
+#define MXS_PIN_TO_GPIO(p) (((p) & MXS_PIN_PINID_MAX) |\
+ ((((p) >> MXS_PIN_BANK_BIT) &\
+ MXS_PIN_BANK_MAX) * PINS_PER_BANK))
+
+#define MXS_PIN_BANK_BIT 24
+#define MXS_PIN_BANK_MAX (0x7FFFFFFF >> (MXS_PIN_BANK_BIT - 1))
+#define MXS_PIN_PINID_MAX ((1 << MXS_PIN_BANK_BIT) - 1)
+#define MXS_PIN_TO_BANK(p) (((p) >> MXS_PIN_BANK_BIT) & MXS_PIN_BANK_MAX)
+#define MXS_PIN_TO_PINID(p) ((p) & MXS_PIN_PINID_MAX)
+
+#define MXS_PIN_ENCODE(b, p) \
+ ((((b) & MXS_PIN_BANK_MAX) << MXS_PIN_BANK_BIT) |\
+ ((p) & MXS_PIN_PINID_MAX))
+
+#define MXS_GPIO_MASK 0x7FFFFFFF
+#define MXS_NON_GPIO 0x80000000
+/*
+ * Each pin may be routed up to four different HW interfaces
+ * including GPIO
+ */
+enum pin_fun {
+ PIN_FUN1 = 0,
+ PIN_FUN2,
+ PIN_FUN3,
+ PIN_GPIO,
+};
+
+/*
+ * Each pin may have different output drive strength in range from
+ * 4mA to 20mA. The most common case is 4, 8 and 12 mA strengths.
+ */
+enum pad_strength {
+ PAD_4MA = 0,
+ PAD_8MA,
+ PAD_12MA,
+ PAD_RESV,
+ PAD_CLEAR = PAD_RESV,
+};
+
+/*
+ * Each pin can be programmed for 1.8V or 3.3V
+ */
+enum pad_voltage {
+ PAD_1_8V = 0,
+ PAD_3_3V,
+};
+
+/**
+ * struct pin_desc - Describes the configuration of a pin.
+ *
+ * @name: A human-readable name that identifies the pin.
+ * @id: A number that identifies the pin (use a macro from a chip-
+ * specific header file -- e.g., "PINID_PWM0").
+ * @fun: The function for which to configure this pin.
+ * @strength: The drive strength for this pin. Note that this field should be
+ * ignored and the driver hardware should *not* be configured if the
+ * "drive" field is not set.
+ * @voltage: The voltage rail for this pin. Note that this field should be
+ * ignored and the driver hardware should *not* be configured if the
+ * "drive" field is not set.
+ * @pullup: If set, indicates whether the pullup is enabled. Note that this
+ * field should be ignored and the pullup should *not* be configured
+ * if the "pull" field is not set.
+ * @drive: If set, indicates that the driver hardware for this pin should be
+ * configured. This field does *not* indicate *how* the driver
+ * hardware should be configured -- only whether or not it should
+ * be. See the "strength" and "voltage" fields for information about
+ * how to configure the driver hardware.
+ * @pull: If set, indicates that the pullup for this pin should be
+ * configured. This field does *not* indicate *how* the pullup
+ * should be configured -- only whether or not it should be. See the
+ * "pullup" field for information about how to configure the pullup.
+ * @input: For GPIO pins only, this indicates whether the pin is an input.
+ * @data: The data field is used when the pin is configured to GPIO output
+ * mode. When data is 0, the pin's output will be 0.
+ */
+struct pin_desc {
+ char *name;
+ unsigned int id;
+ enum pin_fun fun;
+ enum pad_strength strength;
+ enum pad_voltage voltage;
+ unsigned pullup:1;
+ unsigned drive:1;
+ unsigned pull:1;
+ unsigned output:1;
+ unsigned data:1;
+};
+
+struct pin_bank {
+ const char *label[sizeof(long) * 8];
+ unsigned long id;
+ struct pinctrl_chip *chip;
+ unsigned long bitmap;
+ unsigned long gpio_port;
+};
+
+struct pinctrl_chip {
+ char *name;
+ unsigned int nouse;
+ unsigned int bank_size;
+ struct pin_bank *banks;
+ /* OPS */
+ int (*pin2id) (struct pinctrl_chip *, unsigned int, unsigned int *);
+ unsigned int (*get_gpio) (struct pin_bank *, unsigned int);
+ void (*set_strength) (struct pin_bank *, unsigned int,
+ enum pad_strength);
+ void (*set_voltage) (struct pin_bank *, unsigned int, enum pad_voltage);
+ void (*set_pullup) (struct pin_bank *, unsigned int, int);
+ void (*set_type) (struct pin_bank *, unsigned int, enum pin_fun);
+ int (*get_type) (struct pin_bank *, unsigned int);
+};
+
+extern int __init mxs_set_pinctrl_chip(struct pinctrl_chip *);
+
+extern unsigned int mxs_pin2gpio(unsigned int);
+extern int mxs_request_pin(unsigned int, enum pin_fun, const char *);
+extern int mxs_set_type(unsigned int, enum pin_fun, const char *);
+extern int mxs_get_type(unsigned int);
+extern int mxs_set_strength(unsigned int, enum pad_strength, const char *);
+extern int mxs_set_voltage(unsigned int, enum pad_voltage, const char *);
+extern int mxs_set_pullup(unsigned int, int, const char *);
+extern void mxs_release_pin(unsigned int, const char *);
+#endif
diff --git a/arch/arm/plat-mxs/include/mach/power.h b/arch/arm/plat-mxs/include/mach/power.h
new file mode 100644
index 000000000000..28ee9fa2696d
--- /dev/null
+++ b/arch/arm/plat-mxs/include/mach/power.h
@@ -0,0 +1,64 @@
+/*
+ * Freescale MXS voltage regulator structure declarations
+ *
+ * Copyright (C) 2010 Freescale Semiconductor, Inc.
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+#ifndef __VOLTAGE_H
+#define __VOLTAGE_H
+#include <linux/completion.h>
+#include <linux/regulator/driver.h>
+
+struct mxs_regulator {
+ struct regulator_desc regulator;
+ struct mxs_regulator *parent;
+ struct mxs_platform_regulator_data *rdata;
+ struct completion done;
+
+ spinlock_t lock;
+ wait_queue_head_t wait_q;
+ struct notifier_block nb;
+
+ int mode;
+ int cur_voltage;
+ int cur_current;
+ int next_current;
+};
+
+
+struct mxs_platform_regulator_data {
+ char name[80];
+ char *parent_name;
+ int (*reg_register)(struct mxs_regulator *sreg);
+ int (*set_voltage)(struct mxs_regulator *sreg, int uv);
+ int (*get_voltage)(struct mxs_regulator *sreg);
+ int (*set_current)(struct mxs_regulator *sreg, int uA);
+ int (*get_current)(struct mxs_regulator *sreg);
+ int (*enable)(struct mxs_regulator *sreg);
+ int (*disable)(struct mxs_regulator *sreg);
+ int (*is_enabled)(struct mxs_regulator *sreg);
+ int (*set_mode)(struct mxs_regulator *sreg, int mode);
+ int (*get_mode)(struct mxs_regulator *sreg);
+ int (*get_optimum_mode)(struct mxs_regulator *sreg,
+ int input_uV, int output_uV, int load_uA);
+ u32 control_reg;
+ int min_voltage;
+ int max_voltage;
+ int max_current;
+ struct regulation_constraints *cnstraints;
+};
+
+int mxs_register_regulator(
+ struct mxs_regulator *reg_data, int reg,
+ struct regulator_init_data *initdata);
+
+#endif /* __VOLTAGE_H */
diff --git a/arch/arm/plat-mxs/include/mach/system.h b/arch/arm/plat-mxs/include/mach/system.h
new file mode 100644
index 000000000000..faaa2ff3cf13
--- /dev/null
+++ b/arch/arm/plat-mxs/include/mach/system.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 1999 ARM Limited
+ * Copyright (C) 2009-2010 Freescale Semiconductor, Inc.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef __ASM_ARCH_SYSTEM_H__
+#define __ASM_ARCH_SYSTEM_H__
+
+extern void arch_idle(void);
+
+void arch_reset(char mode, const char *cmd);
+extern void (*machine_arch_reset)(char mode, const char *cmd);
+int mxs_reset_block(void __iomem *hwreg, int just_enable);
+int get_evk_board_version(void);
+
+#endif /* __ASM_ARCH_SYSTEM_H__ */
diff --git a/arch/arm/plat-mxs/include/mach/timex.h b/arch/arm/plat-mxs/include/mach/timex.h
new file mode 100644
index 000000000000..d622dda141f2
--- /dev/null
+++ b/arch/arm/plat-mxs/include/mach/timex.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 1999 ARM Limited
+ * Copyright (C) 2009-2010 Freescale Semiconductor, Inc.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+/*
+ * System time clock is sourced from the 32k clock
+ */
+#define CLOCK_TICK_RATE 32000
diff --git a/arch/arm/plat-mxs/include/mach/uncompress.h b/arch/arm/plat-mxs/include/mach/uncompress.h
new file mode 100644
index 000000000000..fd4e4f845472
--- /dev/null
+++ b/arch/arm/plat-mxs/include/mach/uncompress.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2009-2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef __ASM_PLAT_UNCOMPRESS_H
+#define __ASM_PLAT_UNCOMPRESS_H
+
+#include <mach/hardware.h>
+
+/*
+ * Register includes are for when the MMU enabled; we need to define our
+ * own stuff here for pre-MMU use
+ */
+#define UART_PORT_BASE DUART_PHYS_ADDR
+#define UART(c) (((volatile unsigned *)UART_PORT_BASE)[c])
+
+/*
+ * This does not append a newline
+ */
+static void putc(char c)
+{
+ /* Wait for TX fifo empty */
+ while ((UART(6) & (1 << 7)) == 0)
+ continue;
+
+ /* Write byte */
+ UART(0) = c;
+
+ /* Wait for last bit to exit the UART */
+ while (UART(6) & (1 << 3))
+ continue;
+}
+
+#define flush() do { } while (0)
+/*
+ * nothing to do
+ */
+#define arch_decomp_setup()
+
+#define arch_decomp_wdog()
+
+#endif /* __ASM_PLAT_UNCOMPRESS_H */
diff --git a/arch/arm/plat-mxs/include/mach/unique-id.h b/arch/arm/plat-mxs/include/mach/unique-id.h
new file mode 100644
index 000000000000..de5e04342ef5
--- /dev/null
+++ b/arch/arm/plat-mxs/include/mach/unique-id.h
@@ -0,0 +1,30 @@
+/*
+ * Unique ID interface for ID storage providers
+ *
+ * Embedded Alley Solutions, Inc <source@embeddedalley.com>
+ *
+ * Copyright 2008-2010 Freescale Semiconductor, Inc.
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+#ifndef __UNIQUE_ID_H
+#define __UNIQUE_ID_H
+
+struct uid_ops {
+ ssize_t (*id_show)(void *context, char *page, int ascii);
+ ssize_t (*id_store)(void *context, const char *page,
+ size_t count, int ascii);
+};
+
+struct kobject *uid_provider_init(const char *name,
+ struct uid_ops *ops, void *context);
+void uid_provider_remove(const char *name);
+#endif
diff --git a/arch/arm/plat-mxs/include/mach/vmalloc.h b/arch/arm/plat-mxs/include/mach/vmalloc.h
new file mode 100644
index 000000000000..cc6d5cf3133a
--- /dev/null
+++ b/arch/arm/plat-mxs/include/mach/vmalloc.h
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2009-2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#define VMALLOC_END (0xF0000000)
diff --git a/arch/arm/plat-mxs/iram.c b/arch/arm/plat-mxs/iram.c
new file mode 100644
index 000000000000..c63b0a2a9a10
--- /dev/null
+++ b/arch/arm/plat-mxs/iram.c
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ */
+
+#include <linux/kernel.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <linux/genalloc.h>
+
+static unsigned long iram_phys_base;
+static __iomem void *iram_virt_base;
+static struct gen_pool *iram_pool;
+
+#define iram_phys_to_virt(p) (iram_virt_base + ((p) - iram_phys_base))
+
+void *iram_alloc(unsigned int size, unsigned long *dma_addr)
+{
+ if (!iram_pool)
+ return NULL;
+
+ *dma_addr = gen_pool_alloc(iram_pool, size);
+ pr_debug("iram alloc - %dB@0x%p\n", size, (void *)*dma_addr);
+
+ WARN_ON(!*dma_addr);
+ if (!*dma_addr)
+ return NULL;
+
+ return iram_phys_to_virt(*dma_addr);
+}
+EXPORT_SYMBOL(iram_alloc);
+
+void iram_free(unsigned long addr, unsigned int size)
+{
+ if (!iram_pool)
+ return;
+
+ gen_pool_free(iram_pool, addr, size);
+}
+EXPORT_SYMBOL(iram_free);
+
+int __init iram_init(unsigned long base, unsigned long size)
+{
+ iram_phys_base = base;
+
+ iram_pool = gen_pool_create(12, -1);
+ gen_pool_add(iram_pool, base, size, -1);
+ iram_virt_base = ioremap(iram_phys_base, size);
+
+ pr_info("i.MX IRAM pool: %ld KB@0x%p\n", size / 1024, iram_virt_base);
+ return 0;
+}
diff --git a/arch/arm/plat-mxs/lradc.c b/arch/arm/plat-mxs/lradc.c
new file mode 100644
index 000000000000..3d9089e3ef25
--- /dev/null
+++ b/arch/arm/plat-mxs/lradc.c
@@ -0,0 +1,385 @@
+/*
+ * Freescale STMP37XX/STMP378X LRADC helper routines
+ *
+ * Embedded Alley Solutions, Inc <source@embeddedalley.com>
+ *
+ * Copyright 2008-2010 Freescale Semiconductor, Inc.
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sysdev.h>
+#include <linux/platform_device.h>
+#include <linux/bitops.h>
+#include <linux/io.h>
+#include <linux/err.h>
+#include <linux/ioport.h>
+#include <linux/irq.h>
+#include <linux/delay.h>
+
+#include <mach/hardware.h>
+#include <mach/device.h>
+#include <mach/regs-lradc.h>
+#include <mach/lradc.h>
+
+struct lradc_device {
+ struct sys_device sys;
+ unsigned int base;
+ unsigned int vddio_voltage;
+ unsigned int battery_voltage;
+};
+
+static int channels[8];
+
+static __refdata struct lradc_device mxs_lradc;
+
+int hw_lradc_use_channel(int channel)
+{
+ if (channel < 0 || channel > 7)
+ return -EINVAL;
+ channels[channel]++;
+ return 0;
+}
+EXPORT_SYMBOL(hw_lradc_use_channel);
+
+int hw_lradc_unuse_channel(int channel)
+{
+ if (channel < 0 || channel > 7)
+ return -EINVAL;
+ channels[channel]--;
+ return 0;
+}
+EXPORT_SYMBOL(hw_lradc_unuse_channel);
+
+void hw_lradc_reinit(int enable_ground_ref, unsigned freq)
+{
+ __raw_writel(BM_LRADC_CTRL0_SFTRST,
+ mxs_lradc.base + HW_LRADC_CTRL0_SET);
+ udelay(1);
+ __raw_writel(BM_LRADC_CTRL0_SFTRST,
+ mxs_lradc.base + HW_LRADC_CTRL0_CLR);
+
+ /* Clear the Clock Gate for normal operation */
+ __raw_writel(BM_LRADC_CTRL0_CLKGATE,
+ mxs_lradc.base + HW_LRADC_CTRL0_CLR);
+
+ if (enable_ground_ref)
+ __raw_writel(BM_LRADC_CTRL0_ONCHIP_GROUNDREF,
+ mxs_lradc.base + HW_LRADC_CTRL0_SET);
+ else
+ __raw_writel(BM_LRADC_CTRL0_ONCHIP_GROUNDREF,
+ mxs_lradc.base + HW_LRADC_CTRL0_CLR);
+
+ __raw_writel(BM_LRADC_CTRL3_CYCLE_TIME,
+ mxs_lradc.base + HW_LRADC_CTRL3_CLR);
+ __raw_writel(BF_LRADC_CTRL3_CYCLE_TIME(freq),
+ mxs_lradc.base + HW_LRADC_CTRL3_SET);
+
+ __raw_writel(BM_LRADC_CTRL4_LRADC6SELECT | BM_LRADC_CTRL4_LRADC7SELECT,
+ mxs_lradc.base + HW_LRADC_CTRL4_CLR);
+ __raw_writel(BF_LRADC_CTRL4_LRADC6SELECT(mxs_lradc.vddio_voltage),
+ mxs_lradc.base + HW_LRADC_CTRL4_SET);
+ __raw_writel(BF_LRADC_CTRL4_LRADC7SELECT(mxs_lradc.battery_voltage),
+ mxs_lradc.base + HW_LRADC_CTRL4_SET);
+}
+
+int hw_lradc_init_ladder(int channel, int trigger, unsigned sampling)
+{
+ /*
+ * check if the lradc channel is present in this product
+ */
+ if (!hw_lradc_present(channel))
+ return -ENODEV;
+
+ hw_lradc_configure_channel(channel, !0 /* div2 */ ,
+ 0 /* acc */ ,
+ 0 /* num_samples */);
+
+ /* Setup the trigger loop forever */
+ hw_lradc_set_delay_trigger(trigger, 1 << channel,
+ 1 << trigger, 0, sampling);
+
+ /* Clear the accumulator & NUM_SAMPLES */
+ __raw_writel(0xFFFFFFFF, mxs_lradc.base + HW_LRADC_CHn_CLR(channel));
+ return 0;
+}
+
+EXPORT_SYMBOL(hw_lradc_init_ladder);
+
+int hw_lradc_stop_ladder(int channel, int trigger)
+{
+ /*
+ * check if the lradc channel is present in this product
+ */
+ if (!hw_lradc_present(channel))
+ return -ENODEV;
+ hw_lradc_clear_delay_trigger(trigger, 1 << channel, 1 << trigger);
+ return 0;
+}
+
+EXPORT_SYMBOL(hw_lradc_stop_ladder);
+
+int hw_lradc_present(int channel)
+{
+ if (channel < 0 || channel > 7)
+ return 0;
+ return __raw_readl(mxs_lradc.base + HW_LRADC_STATUS)
+ & (1 << (16 + channel));
+}
+
+EXPORT_SYMBOL(hw_lradc_present);
+
+void hw_lradc_configure_channel(int channel, int enable_div2,
+ int enable_acc, int samples)
+{
+ if (enable_div2)
+ __raw_writel(BF_LRADC_CTRL2_DIVIDE_BY_TWO(1 << channel),
+ mxs_lradc.base + HW_LRADC_CTRL2_SET);
+ else
+ __raw_writel(BF_LRADC_CTRL2_DIVIDE_BY_TWO(1 << channel),
+ mxs_lradc.base + HW_LRADC_CTRL2_CLR);
+
+ /* Clear the accumulator & NUM_SAMPLES */
+ __raw_writel(0xFFFFFFFF, mxs_lradc.base + HW_LRADC_CHn_CLR(channel));
+
+ /* Sets NUM_SAMPLES bitfield of HW_LRADC_CHn register. */
+ __raw_writel(BM_LRADC_CHn_NUM_SAMPLES,
+ mxs_lradc.base + HW_LRADC_CHn_CLR(channel));
+ __raw_writel(BF_LRADC_CHn_NUM_SAMPLES(samples),
+ mxs_lradc.base + HW_LRADC_CHn_SET(channel));
+
+ if (enable_acc)
+ __raw_writel(BM_LRADC_CHn_ACCUMULATE,
+ mxs_lradc.base + HW_LRADC_CHn_SET(channel));
+ else
+ __raw_writel(BM_LRADC_CHn_ACCUMULATE,
+ mxs_lradc.base + HW_LRADC_CHn_CLR(channel));
+}
+
+EXPORT_SYMBOL(hw_lradc_configure_channel);
+
+void hw_lradc_set_delay_trigger(int trigger, u32 trigger_lradc,
+ u32 delay_triggers, u32 loops, u32 delays)
+{
+ /* set TRIGGER_LRADCS in HW_LRADC_DELAYn */
+ __raw_writel(BF_LRADC_DELAYn_TRIGGER_LRADCS(trigger_lradc),
+ mxs_lradc.base + HW_LRADC_DELAYn_SET(trigger));
+ __raw_writel(BF_LRADC_DELAYn_TRIGGER_DELAYS(delay_triggers),
+ mxs_lradc.base + HW_LRADC_DELAYn_SET(trigger));
+
+ __raw_writel(BM_LRADC_DELAYn_LOOP_COUNT | BM_LRADC_DELAYn_DELAY,
+ mxs_lradc.base + HW_LRADC_DELAYn_CLR(trigger));
+ __raw_writel(BF_LRADC_DELAYn_LOOP_COUNT(loops),
+ mxs_lradc.base + HW_LRADC_DELAYn_SET(trigger));
+ __raw_writel(BF_LRADC_DELAYn_DELAY(delays),
+ mxs_lradc.base + HW_LRADC_DELAYn_SET(trigger));
+}
+
+EXPORT_SYMBOL(hw_lradc_set_delay_trigger);
+
+void hw_lradc_clear_delay_trigger(int trigger, u32 trigger_lradc,
+ u32 delay_triggers)
+{
+ __raw_writel(BF_LRADC_DELAYn_TRIGGER_LRADCS(trigger_lradc),
+ mxs_lradc.base + HW_LRADC_DELAYn_CLR(trigger));
+ __raw_writel(BF_LRADC_DELAYn_TRIGGER_DELAYS(delay_triggers),
+ mxs_lradc.base + HW_LRADC_DELAYn_CLR(trigger));
+}
+
+EXPORT_SYMBOL(hw_lradc_clear_delay_trigger);
+
+void hw_lradc_set_delay_trigger_kick(int trigger, int value)
+{
+ if (value)
+ __raw_writel(BM_LRADC_DELAYn_KICK,
+ mxs_lradc.base + HW_LRADC_DELAYn_SET(trigger));
+ else
+ __raw_writel(BM_LRADC_DELAYn_KICK,
+ mxs_lradc.base + HW_LRADC_DELAYn_CLR(trigger));
+}
+
+EXPORT_SYMBOL(hw_lradc_set_delay_trigger_kick);
+
+u32 hw_lradc_vddio(void)
+{
+ /* Clear the Soft Reset and Clock Gate for normal operation */
+ __raw_writel(BM_LRADC_CTRL0_SFTRST | BM_LRADC_CTRL0_CLKGATE,
+ mxs_lradc.base + HW_LRADC_CTRL0_CLR);
+
+ /*
+ * Clear the divide by two for channel 6 since
+ * it has a HW divide-by-two built in.
+ */
+ __raw_writel(BF_LRADC_CTRL2_DIVIDE_BY_TWO(1 << VDDIO_VOLTAGE_CH),
+ mxs_lradc.base + HW_LRADC_CTRL2_CLR);
+
+ /* Clear the accumulator & NUM_SAMPLES */
+ __raw_writel(0xFFFFFFFF,
+ mxs_lradc.base + HW_LRADC_CHn_CLR(VDDIO_VOLTAGE_CH));
+
+ /* Clear the interrupt flag */
+ __raw_writel(BM_LRADC_CTRL1_LRADC6_IRQ,
+ mxs_lradc.base + HW_LRADC_CTRL1_CLR);
+
+ /*
+ * Get VddIO; this is the max scale value for the button resistor
+ * ladder.
+ * schedule ch 6:
+ */
+ __raw_writel(BF_LRADC_CTRL0_SCHEDULE(1 << VDDIO_VOLTAGE_CH),
+ mxs_lradc.base + HW_LRADC_CTRL0_SET);
+
+ /* wait for completion */
+ while ((__raw_readl(mxs_lradc.base + HW_LRADC_CTRL1)
+ & BM_LRADC_CTRL1_LRADC6_IRQ) != BM_LRADC_CTRL1_LRADC6_IRQ)
+ cpu_relax();
+
+ /* Clear the interrupt flag */
+ __raw_writel(BM_LRADC_CTRL1_LRADC6_IRQ,
+ mxs_lradc.base + HW_LRADC_CTRL1_CLR);
+
+ /* read ch 6 value. */
+ return __raw_readl(mxs_lradc.base + HW_LRADC_CHn(VDDIO_VOLTAGE_CH)) &
+ BM_LRADC_CHn_VALUE;
+}
+
+EXPORT_SYMBOL(hw_lradc_vddio);
+
+#ifdef CONFIG_PM
+static u32 lradc_registers[0x16];
+static int do_gate;
+
+static int hw_lradc_suspend(struct sys_device *dev, pm_message_t state)
+{
+ int i;
+
+ do_gate = 1;
+ for (i = 0; i < ARRAY_SIZE(channels); i++)
+ if (channels[i] > 0) {
+ do_gate = 0;
+ break;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(lradc_registers); i++)
+ lradc_registers[i] = __raw_readl(mxs_lradc.base + (i << 4));
+
+ if (do_gate)
+ __raw_writel(BM_LRADC_CTRL0_CLKGATE,
+ mxs_lradc.base + HW_LRADC_CTRL0_SET);
+ return 0;
+}
+
+static int hw_lradc_resume(struct sys_device *dev)
+{
+ int i;
+
+ if (do_gate) {
+ __raw_writel(BM_LRADC_CTRL0_SFTRST,
+ mxs_lradc.base + HW_LRADC_CTRL0_SET);
+ udelay(10);
+ __raw_writel(BM_LRADC_CTRL0_SFTRST |
+ BM_LRADC_CTRL0_CLKGATE,
+ mxs_lradc.base + HW_LRADC_CTRL0_CLR);
+ }
+ for (i = 0; i < ARRAY_SIZE(lradc_registers); i++)
+ __raw_writel(lradc_registers[i], mxs_lradc.base + (i << 4));
+ return 0;
+}
+
+#endif
+
+static struct sysdev_class mxs_lradc_sysclass = {
+ .name = "mxs-lradc",
+#ifdef CONFIG_PM
+ .suspend = hw_lradc_suspend,
+ .resume = hw_lradc_resume,
+#endif
+};
+
+static int lradc_freq = LRADC_CLOCK_6MHZ;
+
+static int __init lradc_freq_setup(char *str)
+{
+ long freq;
+
+ if (strict_strtol(str, 0, &freq) < 0)
+ return 0;
+
+ if (freq < 0)
+ return 0;
+ if (freq >= 6)
+ lradc_freq = LRADC_CLOCK_6MHZ;
+ else if (freq >= 4)
+ lradc_freq = LRADC_CLOCK_4MHZ;
+ else if (freq >= 3)
+ lradc_freq = LRADC_CLOCK_3MHZ;
+ else if (freq >= 2)
+ lradc_freq = LRADC_CLOCK_2MHZ;
+ else
+ return 0;
+ return 1;
+}
+
+__setup("lradc_freq=", lradc_freq_setup);
+
+static int __devinit mxs_lradc_probe(struct platform_device *pdev)
+{
+ struct resource *res;
+ struct mxs_lradc_plat_data *plat_data;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (res == NULL)
+ return -ENODEV;
+
+ plat_data = (struct mxs_lradc_plat_data *)(pdev->dev.platform_data);
+ if (plat_data == NULL)
+ return -EFAULT;
+
+ mxs_lradc.base = (unsigned int)IO_ADDRESS(res->start);
+ mxs_lradc.sys.id = -1;
+ mxs_lradc.sys.cls = &mxs_lradc_sysclass;
+ mxs_lradc.vddio_voltage = plat_data->vddio_voltage;
+ mxs_lradc.battery_voltage = plat_data->battery_voltage;
+ hw_lradc_reinit(0, lradc_freq);
+ return sysdev_register(&mxs_lradc.sys);
+}
+
+static int __devexit mxs_lradc_remove(struct platform_device *pdev)
+{
+ sysdev_unregister(&mxs_lradc.sys);
+ return 0;
+}
+
+static __refdata struct platform_driver mxs_lradc_drv = {
+ .probe = mxs_lradc_probe,
+ .remove = __devexit_p(mxs_lradc_remove),
+ .driver = {
+ .name = "mxs-lradc",
+ .owner = THIS_MODULE,
+ }
+};
+
+static int __init hw_lradc_init(void)
+{
+ sysdev_class_register(&mxs_lradc_sysclass);
+ platform_driver_register(&mxs_lradc_drv);
+ return 0;
+}
+
+static void __exit hw_lradc_exit(void)
+{
+ platform_driver_unregister(&mxs_lradc_drv);
+ sysdev_class_unregister(&mxs_lradc_sysclass);
+}
+
+subsys_initcall(hw_lradc_init);
+module_exit(hw_lradc_exit);
diff --git a/arch/arm/plat-mxs/pinctrl.c b/arch/arm/plat-mxs/pinctrl.c
new file mode 100644
index 000000000000..cdef3e02d495
--- /dev/null
+++ b/arch/arm/plat-mxs/pinctrl.c
@@ -0,0 +1,215 @@
+/*
+ * Copyright (C) 2009-2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/bitops.h>
+#include <linux/gpio.h>
+#include <linux/irq.h>
+
+#include <mach/pinctrl.h>
+
+static struct pinctrl_chip *g_chip;
+
+int mxs_request_pin(unsigned int pin, enum pin_fun fun, const char *lab)
+{
+ int bank, index;
+ struct pin_bank *pb;
+ if (g_chip == NULL)
+ return -ENODEV;
+
+ bank = g_chip->pin2id(g_chip, pin, &index);
+ if (bank < 0 || index < 0 || bank >= g_chip->bank_size)
+ return -EFAULT;
+
+ pb = g_chip->banks + bank;
+ if (test_and_set_bit(index, &pb->bitmap))
+ return -EBUSY;
+ pb->label[index] = lab;
+ if (g_chip->set_type)
+ g_chip->set_type(pb, index, fun);
+ return 0;
+}
+EXPORT_SYMBOL(mxs_request_pin);
+
+int mxs_get_type(unsigned int pin)
+{
+ int bank, index;
+ struct pin_bank *pb;
+ int ret = 0;
+ if (g_chip == NULL)
+ return -ENODEV;
+
+ bank = g_chip->pin2id(g_chip, pin, &index);
+ if (bank < 0 || index < 0 || bank >= g_chip->bank_size)
+ return -EFAULT;
+
+ pb = g_chip->banks + bank;
+ if (g_chip->get_type)
+ ret = g_chip->get_type(pb, index);
+ return ret;
+}
+EXPORT_SYMBOL(mxs_get_type);
+
+int mxs_set_type(unsigned int pin, enum pin_fun fun, const char *lab)
+{
+ int bank, index;
+ struct pin_bank *pb;
+ if (g_chip == NULL)
+ return -ENODEV;
+
+ bank = g_chip->pin2id(g_chip, pin, &index);
+ if (bank < 0 || index < 0 || bank >= g_chip->bank_size)
+ return -EFAULT;
+
+ pb = g_chip->banks + bank;
+
+ if (!test_bit(index, &pb->bitmap))
+ return -ENOLCK;
+ if (lab != pb->label[index]) /* label is const string */
+ return -EINVAL;
+ if (g_chip->set_type)
+ g_chip->set_type(pb, index, fun);
+ return 0;
+}
+EXPORT_SYMBOL(mxs_set_type);
+
+int mxs_set_strength(unsigned int pin, enum pad_strength cfg, const char *lab)
+{
+ int bank, index;
+ struct pin_bank *pb;
+ if (g_chip == NULL)
+ return -ENODEV;
+
+ bank = g_chip->pin2id(g_chip, pin, &index);
+ if (bank < 0 || index < 0 || bank >= g_chip->bank_size)
+ return -EFAULT;
+
+ pb = g_chip->banks + bank;
+
+ if (!test_bit(index, &pb->bitmap))
+ return -ENOLCK;
+ if (lab != pb->label[index]) /* label is const string */
+ return -EINVAL;
+ if (g_chip->set_strength)
+ g_chip->set_strength(pb, index, cfg);
+ return 0;
+}
+EXPORT_SYMBOL(mxs_set_strength);
+
+int mxs_set_voltage(unsigned int pin, enum pad_voltage cfg, const char *lab)
+{
+ int bank, index;
+ struct pin_bank *pb;
+ if (g_chip == NULL)
+ return -ENODEV;
+
+ bank = g_chip->pin2id(g_chip, pin, &index);
+ if (bank < 0 || index < 0 || bank >= g_chip->bank_size)
+ return -EFAULT;
+
+ pb = g_chip->banks + bank;
+
+ if (!test_bit(index, &pb->bitmap))
+ return -ENOLCK;
+ if (lab != pb->label[index]) /* label is const string */
+ return -EINVAL;
+ if (g_chip->set_voltage)
+ g_chip->set_voltage(pb, index, cfg);
+ return 0;
+}
+EXPORT_SYMBOL(mxs_set_voltage);
+
+int mxs_set_pullup(unsigned int pin, int en, const char *lab)
+{
+ int bank, index;
+ struct pin_bank *pb;
+ if (g_chip == NULL)
+ return -ENODEV;
+
+ bank = g_chip->pin2id(g_chip, pin, &index);
+ if (bank < 0 || index < 0 || bank >= g_chip->bank_size)
+ return -EFAULT;
+
+ pb = g_chip->banks + bank;
+
+ if (!test_bit(index, &pb->bitmap))
+ return -ENOLCK;
+ if (lab != pb->label[index]) /* label is const string */
+ return -EINVAL;
+ if (g_chip->set_pullup)
+ g_chip->set_pullup(pb, index, en);
+ return 0;
+}
+EXPORT_SYMBOL(mxs_set_pullup);
+
+void mxs_release_pin(unsigned int pin, const char *lab)
+{
+ int bank, index;
+ struct pin_bank *pb;
+ if (g_chip == NULL)
+ return;
+
+ bank = g_chip->pin2id(g_chip, pin, &index);
+ if (bank < 0 || index < 0 || bank >= g_chip->bank_size)
+ return;
+
+ pb = g_chip->banks + bank;
+
+ if (!test_bit(index, &pb->bitmap))
+ return;
+ if (lab != pb->label[index]) /* label is const string */
+ return;
+ pb->label[index] = NULL;
+
+ clear_bit(index, &pb->bitmap);
+}
+EXPORT_SYMBOL(mxs_release_pin);
+
+unsigned int mxs_pin2gpio(unsigned int pin)
+{
+ int bank, index;
+ struct pin_bank *pb;
+ if (g_chip == NULL)
+ return -ENODEV;
+
+ if (!g_chip->get_gpio)
+ return -ENODEV;
+
+ bank = g_chip->pin2id(g_chip, pin, &index);
+ if (bank < 0 || index < 0 || bank >= g_chip->bank_size)
+ return -EFAULT;
+
+ pb = g_chip->banks + bank;
+
+ return g_chip->get_gpio(pb, index);
+}
+
+int __init mxs_set_pinctrl_chip(struct pinctrl_chip *chip)
+{
+ if (!(chip && chip->banks && chip->bank_size &&
+ chip->get_gpio && chip->pin2id))
+ return -EINVAL;
+
+ if (g_chip)
+ return -EEXIST;
+ g_chip = chip;
+ return 0;
+};
diff --git a/arch/arm/plat-mxs/regs-apbx.h b/arch/arm/plat-mxs/regs-apbx.h
new file mode 100644
index 000000000000..f788f1303ece
--- /dev/null
+++ b/arch/arm/plat-mxs/regs-apbx.h
@@ -0,0 +1,433 @@
+/*
+ * Freescale APBX Register Definitions
+ *
+ * Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * This file is created by xml file. Don't Edit it.
+ *
+ * Xml Revision: 1.30
+ * Template revision: 26195
+ */
+
+#ifndef __ARCH_ARM___APBX_H
+#define __ARCH_ARM___APBX_H
+
+#define HW_APBX_CTRL0 (0x00000000)
+#define HW_APBX_CTRL0_SET (0x00000004)
+#define HW_APBX_CTRL0_CLR (0x00000008)
+#define HW_APBX_CTRL0_TOG (0x0000000c)
+
+#define BM_APBX_CTRL0_SFTRST 0x80000000
+#define BM_APBX_CTRL0_CLKGATE 0x40000000
+#define BP_APBX_CTRL0_RSVD0 0
+#define BM_APBX_CTRL0_RSVD0 0x3FFFFFFF
+#define BF_APBX_CTRL0_RSVD0(v) \
+ (((v) << 0) & BM_APBX_CTRL0_RSVD0)
+
+#define HW_APBX_CTRL1 (0x00000010)
+#define HW_APBX_CTRL1_SET (0x00000014)
+#define HW_APBX_CTRL1_CLR (0x00000018)
+#define HW_APBX_CTRL1_TOG (0x0000001c)
+
+#define BM_APBX_CTRL1_CH15_CMDCMPLT_IRQ_EN 0x80000000
+#define BM_APBX_CTRL1_CH14_CMDCMPLT_IRQ_EN 0x40000000
+#define BM_APBX_CTRL1_CH13_CMDCMPLT_IRQ_EN 0x20000000
+#define BM_APBX_CTRL1_CH12_CMDCMPLT_IRQ_EN 0x10000000
+#define BM_APBX_CTRL1_CH11_CMDCMPLT_IRQ_EN 0x08000000
+#define BM_APBX_CTRL1_CH10_CMDCMPLT_IRQ_EN 0x04000000
+#define BM_APBX_CTRL1_CH9_CMDCMPLT_IRQ_EN 0x02000000
+#define BM_APBX_CTRL1_CH8_CMDCMPLT_IRQ_EN 0x01000000
+#define BM_APBX_CTRL1_CH7_CMDCMPLT_IRQ_EN 0x00800000
+#define BM_APBX_CTRL1_CH6_CMDCMPLT_IRQ_EN 0x00400000
+#define BM_APBX_CTRL1_CH5_CMDCMPLT_IRQ_EN 0x00200000
+#define BM_APBX_CTRL1_CH4_CMDCMPLT_IRQ_EN 0x00100000
+#define BM_APBX_CTRL1_CH3_CMDCMPLT_IRQ_EN 0x00080000
+#define BM_APBX_CTRL1_CH2_CMDCMPLT_IRQ_EN 0x00040000
+#define BM_APBX_CTRL1_CH1_CMDCMPLT_IRQ_EN 0x00020000
+#define BM_APBX_CTRL1_CH0_CMDCMPLT_IRQ_EN 0x00010000
+#define BM_APBX_CTRL1_CH15_CMDCMPLT_IRQ 0x00008000
+#define BM_APBX_CTRL1_CH14_CMDCMPLT_IRQ 0x00004000
+#define BM_APBX_CTRL1_CH13_CMDCMPLT_IRQ 0x00002000
+#define BM_APBX_CTRL1_CH12_CMDCMPLT_IRQ 0x00001000
+#define BM_APBX_CTRL1_CH11_CMDCMPLT_IRQ 0x00000800
+#define BM_APBX_CTRL1_CH10_CMDCMPLT_IRQ 0x00000400
+#define BM_APBX_CTRL1_CH9_CMDCMPLT_IRQ 0x00000200
+#define BM_APBX_CTRL1_CH8_CMDCMPLT_IRQ 0x00000100
+#define BM_APBX_CTRL1_CH7_CMDCMPLT_IRQ 0x00000080
+#define BM_APBX_CTRL1_CH6_CMDCMPLT_IRQ 0x00000040
+#define BM_APBX_CTRL1_CH5_CMDCMPLT_IRQ 0x00000020
+#define BM_APBX_CTRL1_CH4_CMDCMPLT_IRQ 0x00000010
+#define BM_APBX_CTRL1_CH3_CMDCMPLT_IRQ 0x00000008
+#define BM_APBX_CTRL1_CH2_CMDCMPLT_IRQ 0x00000004
+#define BM_APBX_CTRL1_CH1_CMDCMPLT_IRQ 0x00000002
+#define BM_APBX_CTRL1_CH0_CMDCMPLT_IRQ 0x00000001
+
+#define HW_APBX_CTRL2 (0x00000020)
+#define HW_APBX_CTRL2_SET (0x00000024)
+#define HW_APBX_CTRL2_CLR (0x00000028)
+#define HW_APBX_CTRL2_TOG (0x0000002c)
+
+#define BM_APBX_CTRL2_CH15_ERROR_STATUS 0x80000000
+#define BV_APBX_CTRL2_CH15_ERROR_STATUS__TERMINATION 0x0
+#define BV_APBX_CTRL2_CH15_ERROR_STATUS__BUS_ERROR 0x1
+#define BM_APBX_CTRL2_CH14_ERROR_STATUS 0x40000000
+#define BV_APBX_CTRL2_CH14_ERROR_STATUS__TERMINATION 0x0
+#define BV_APBX_CTRL2_CH14_ERROR_STATUS__BUS_ERROR 0x1
+#define BM_APBX_CTRL2_CH13_ERROR_STATUS 0x20000000
+#define BV_APBX_CTRL2_CH13_ERROR_STATUS__TERMINATION 0x0
+#define BV_APBX_CTRL2_CH13_ERROR_STATUS__BUS_ERROR 0x1
+#define BM_APBX_CTRL2_CH12_ERROR_STATUS 0x10000000
+#define BV_APBX_CTRL2_CH12_ERROR_STATUS__TERMINATION 0x0
+#define BV_APBX_CTRL2_CH12_ERROR_STATUS__BUS_ERROR 0x1
+#define BM_APBX_CTRL2_CH11_ERROR_STATUS 0x08000000
+#define BV_APBX_CTRL2_CH11_ERROR_STATUS__TERMINATION 0x0
+#define BV_APBX_CTRL2_CH11_ERROR_STATUS__BUS_ERROR 0x1
+#define BM_APBX_CTRL2_CH10_ERROR_STATUS 0x04000000
+#define BV_APBX_CTRL2_CH10_ERROR_STATUS__TERMINATION 0x0
+#define BV_APBX_CTRL2_CH10_ERROR_STATUS__BUS_ERROR 0x1
+#define BM_APBX_CTRL2_CH9_ERROR_STATUS 0x02000000
+#define BV_APBX_CTRL2_CH9_ERROR_STATUS__TERMINATION 0x0
+#define BV_APBX_CTRL2_CH9_ERROR_STATUS__BUS_ERROR 0x1
+#define BM_APBX_CTRL2_CH8_ERROR_STATUS 0x01000000
+#define BV_APBX_CTRL2_CH8_ERROR_STATUS__TERMINATION 0x0
+#define BV_APBX_CTRL2_CH8_ERROR_STATUS__BUS_ERROR 0x1
+#define BM_APBX_CTRL2_CH7_ERROR_STATUS 0x00800000
+#define BV_APBX_CTRL2_CH7_ERROR_STATUS__TERMINATION 0x0
+#define BV_APBX_CTRL2_CH7_ERROR_STATUS__BUS_ERROR 0x1
+#define BM_APBX_CTRL2_CH6_ERROR_STATUS 0x00400000
+#define BV_APBX_CTRL2_CH6_ERROR_STATUS__TERMINATION 0x0
+#define BV_APBX_CTRL2_CH6_ERROR_STATUS__BUS_ERROR 0x1
+#define BM_APBX_CTRL2_CH5_ERROR_STATUS 0x00200000
+#define BV_APBX_CTRL2_CH5_ERROR_STATUS__TERMINATION 0x0
+#define BV_APBX_CTRL2_CH5_ERROR_STATUS__BUS_ERROR 0x1
+#define BM_APBX_CTRL2_CH4_ERROR_STATUS 0x00100000
+#define BV_APBX_CTRL2_CH4_ERROR_STATUS__TERMINATION 0x0
+#define BV_APBX_CTRL2_CH4_ERROR_STATUS__BUS_ERROR 0x1
+#define BM_APBX_CTRL2_CH3_ERROR_STATUS 0x00080000
+#define BV_APBX_CTRL2_CH3_ERROR_STATUS__TERMINATION 0x0
+#define BV_APBX_CTRL2_CH3_ERROR_STATUS__BUS_ERROR 0x1
+#define BM_APBX_CTRL2_CH2_ERROR_STATUS 0x00040000
+#define BV_APBX_CTRL2_CH2_ERROR_STATUS__TERMINATION 0x0
+#define BV_APBX_CTRL2_CH2_ERROR_STATUS__BUS_ERROR 0x1
+#define BM_APBX_CTRL2_CH1_ERROR_STATUS 0x00020000
+#define BV_APBX_CTRL2_CH1_ERROR_STATUS__TERMINATION 0x0
+#define BV_APBX_CTRL2_CH1_ERROR_STATUS__BUS_ERROR 0x1
+#define BM_APBX_CTRL2_CH0_ERROR_STATUS 0x00010000
+#define BV_APBX_CTRL2_CH0_ERROR_STATUS__TERMINATION 0x0
+#define BV_APBX_CTRL2_CH0_ERROR_STATUS__BUS_ERROR 0x1
+#define BM_APBX_CTRL2_CH15_ERROR_IRQ 0x00008000
+#define BM_APBX_CTRL2_CH14_ERROR_IRQ 0x00004000
+#define BM_APBX_CTRL2_CH13_ERROR_IRQ 0x00002000
+#define BM_APBX_CTRL2_CH12_ERROR_IRQ 0x00001000
+#define BM_APBX_CTRL2_CH11_ERROR_IRQ 0x00000800
+#define BM_APBX_CTRL2_CH10_ERROR_IRQ 0x00000400
+#define BM_APBX_CTRL2_CH9_ERROR_IRQ 0x00000200
+#define BM_APBX_CTRL2_CH8_ERROR_IRQ 0x00000100
+#define BM_APBX_CTRL2_CH7_ERROR_IRQ 0x00000080
+#define BM_APBX_CTRL2_CH6_ERROR_IRQ 0x00000040
+#define BM_APBX_CTRL2_CH5_ERROR_IRQ 0x00000020
+#define BM_APBX_CTRL2_CH4_ERROR_IRQ 0x00000010
+#define BM_APBX_CTRL2_CH3_ERROR_IRQ 0x00000008
+#define BM_APBX_CTRL2_CH2_ERROR_IRQ 0x00000004
+#define BM_APBX_CTRL2_CH1_ERROR_IRQ 0x00000002
+#define BM_APBX_CTRL2_CH0_ERROR_IRQ 0x00000001
+
+#define HW_APBX_CHANNEL_CTRL (0x00000030)
+#define HW_APBX_CHANNEL_CTRL_SET (0x00000034)
+#define HW_APBX_CHANNEL_CTRL_CLR (0x00000038)
+#define HW_APBX_CHANNEL_CTRL_TOG (0x0000003c)
+
+#define BP_APBX_CHANNEL_CTRL_RESET_CHANNEL 16
+#define BM_APBX_CHANNEL_CTRL_RESET_CHANNEL 0xFFFF0000
+#define BF_APBX_CHANNEL_CTRL_RESET_CHANNEL(v) \
+ (((v) << 16) & BM_APBX_CHANNEL_CTRL_RESET_CHANNEL)
+#define BV_APBX_CHANNEL_CTRL_RESET_CHANNEL__UART4_RX 0x0001
+#define BV_APBX_CHANNEL_CTRL_RESET_CHANNEL__UART4_TX 0x0002
+#define BV_APBX_CHANNEL_CTRL_RESET_CHANNEL__SPDIF_TX 0x0004
+#define BV_APBX_CHANNEL_CTRL_RESET_CHANNEL__SAIF0 0x0010
+#define BV_APBX_CHANNEL_CTRL_RESET_CHANNEL__SAIF1 0x0020
+#define BV_APBX_CHANNEL_CTRL_RESET_CHANNEL__I2C0 0x0040
+#define BV_APBX_CHANNEL_CTRL_RESET_CHANNEL__I2C1 0x0080
+#define BV_APBX_CHANNEL_CTRL_RESET_CHANNEL__UART0_RX 0x0100
+#define BV_APBX_CHANNEL_CTRL_RESET_CHANNEL__UART0_TX 0x0200
+#define BV_APBX_CHANNEL_CTRL_RESET_CHANNEL__UART1_RX 0x0400
+#define BV_APBX_CHANNEL_CTRL_RESET_CHANNEL__UART1_TX 0x0800
+#define BV_APBX_CHANNEL_CTRL_RESET_CHANNEL__UART2_RX 0x1000
+#define BV_APBX_CHANNEL_CTRL_RESET_CHANNEL__UART2_TX 0x2000
+#define BV_APBX_CHANNEL_CTRL_RESET_CHANNEL__UART3_RX 0x4000
+#define BV_APBX_CHANNEL_CTRL_RESET_CHANNEL__UART3_TX 0x8000
+#define BP_APBX_CHANNEL_CTRL_FREEZE_CHANNEL 0
+#define BM_APBX_CHANNEL_CTRL_FREEZE_CHANNEL 0x0000FFFF
+#define BF_APBX_CHANNEL_CTRL_FREEZE_CHANNEL(v) \
+ (((v) << 0) & BM_APBX_CHANNEL_CTRL_FREEZE_CHANNEL)
+#define BV_APBX_CHANNEL_CTRL_FREEZE_CHANNEL__UART4_RX 0x0001
+#define BV_APBX_CHANNEL_CTRL_FREEZE_CHANNEL__UART4_TX 0x0002
+#define BV_APBX_CHANNEL_CTRL_FREEZE_CHANNEL__SPDIF_TX 0x0004
+#define BV_APBX_CHANNEL_CTRL_FREEZE_CHANNEL__SAIF0 0x0010
+#define BV_APBX_CHANNEL_CTRL_FREEZE_CHANNEL__SAIF1 0x0020
+#define BV_APBX_CHANNEL_CTRL_FREEZE_CHANNEL__I2C0 0x0040
+#define BV_APBX_CHANNEL_CTRL_FREEZE_CHANNEL__I2C1 0x0080
+#define BV_APBX_CHANNEL_CTRL_FREEZE_CHANNEL__UART0_RX 0x0100
+#define BV_APBX_CHANNEL_CTRL_FREEZE_CHANNEL__UART0_TX 0x0200
+#define BV_APBX_CHANNEL_CTRL_FREEZE_CHANNEL__UART1_RX 0x0400
+#define BV_APBX_CHANNEL_CTRL_FREEZE_CHANNEL__UART1_TX 0x0800
+#define BV_APBX_CHANNEL_CTRL_FREEZE_CHANNEL__UART2_RX 0x1000
+#define BV_APBX_CHANNEL_CTRL_FREEZE_CHANNEL__UART2_TX 0x2000
+#define BV_APBX_CHANNEL_CTRL_FREEZE_CHANNEL__UART3_RX 0x4000
+#define BV_APBX_CHANNEL_CTRL_FREEZE_CHANNEL__UART3_TX 0x8000
+
+#define HW_APBX_DEVSEL (0x00000040)
+#define HW_APBX_DEVSEL_SET (0x00000044)
+#define HW_APBX_DEVSEL_CLR (0x00000048)
+#define HW_APBX_DEVSEL_TOG (0x0000004c)
+
+#define BP_APBX_DEVSEL_CH15 30
+#define BM_APBX_DEVSEL_CH15 0xC0000000
+#define BF_APBX_DEVSEL_CH15(v) \
+ (((v) << 30) & BM_APBX_DEVSEL_CH15)
+#define BP_APBX_DEVSEL_CH14 28
+#define BM_APBX_DEVSEL_CH14 0x30000000
+#define BF_APBX_DEVSEL_CH14(v) \
+ (((v) << 28) & BM_APBX_DEVSEL_CH14)
+#define BP_APBX_DEVSEL_CH13 26
+#define BM_APBX_DEVSEL_CH13 0x0C000000
+#define BF_APBX_DEVSEL_CH13(v) \
+ (((v) << 26) & BM_APBX_DEVSEL_CH13)
+#define BP_APBX_DEVSEL_CH12 24
+#define BM_APBX_DEVSEL_CH12 0x03000000
+#define BF_APBX_DEVSEL_CH12(v) \
+ (((v) << 24) & BM_APBX_DEVSEL_CH12)
+#define BP_APBX_DEVSEL_CH11 22
+#define BM_APBX_DEVSEL_CH11 0x00C00000
+#define BF_APBX_DEVSEL_CH11(v) \
+ (((v) << 22) & BM_APBX_DEVSEL_CH11)
+#define BP_APBX_DEVSEL_CH10 20
+#define BM_APBX_DEVSEL_CH10 0x00300000
+#define BF_APBX_DEVSEL_CH10(v) \
+ (((v) << 20) & BM_APBX_DEVSEL_CH10)
+#define BP_APBX_DEVSEL_CH9 18
+#define BM_APBX_DEVSEL_CH9 0x000C0000
+#define BF_APBX_DEVSEL_CH9(v) \
+ (((v) << 18) & BM_APBX_DEVSEL_CH9)
+#define BP_APBX_DEVSEL_CH8 16
+#define BM_APBX_DEVSEL_CH8 0x00030000
+#define BF_APBX_DEVSEL_CH8(v) \
+ (((v) << 16) & BM_APBX_DEVSEL_CH8)
+#define BP_APBX_DEVSEL_CH7 14
+#define BM_APBX_DEVSEL_CH7 0x0000C000
+#define BF_APBX_DEVSEL_CH7(v) \
+ (((v) << 14) & BM_APBX_DEVSEL_CH7)
+#define BP_APBX_DEVSEL_CH6 12
+#define BM_APBX_DEVSEL_CH6 0x00003000
+#define BF_APBX_DEVSEL_CH6(v) \
+ (((v) << 12) & BM_APBX_DEVSEL_CH6)
+#define BP_APBX_DEVSEL_CH5 10
+#define BM_APBX_DEVSEL_CH5 0x00000C00
+#define BF_APBX_DEVSEL_CH5(v) \
+ (((v) << 10) & BM_APBX_DEVSEL_CH5)
+#define BP_APBX_DEVSEL_CH4 8
+#define BM_APBX_DEVSEL_CH4 0x00000300
+#define BF_APBX_DEVSEL_CH4(v) \
+ (((v) << 8) & BM_APBX_DEVSEL_CH4)
+#define BP_APBX_DEVSEL_CH3 6
+#define BM_APBX_DEVSEL_CH3 0x000000C0
+#define BF_APBX_DEVSEL_CH3(v) \
+ (((v) << 6) & BM_APBX_DEVSEL_CH3)
+#define BP_APBX_DEVSEL_CH2 4
+#define BM_APBX_DEVSEL_CH2 0x00000030
+#define BF_APBX_DEVSEL_CH2(v) \
+ (((v) << 4) & BM_APBX_DEVSEL_CH2)
+#define BP_APBX_DEVSEL_CH1 2
+#define BM_APBX_DEVSEL_CH1 0x0000000C
+#define BF_APBX_DEVSEL_CH1(v) \
+ (((v) << 2) & BM_APBX_DEVSEL_CH1)
+#define BP_APBX_DEVSEL_CH0 0
+#define BM_APBX_DEVSEL_CH0 0x00000003
+#define BF_APBX_DEVSEL_CH0(v) \
+ (((v) << 0) & BM_APBX_DEVSEL_CH0)
+
+/*
+ * multi-register-define name HW_APBX_CHn_CURCMDAR
+ * base 0x00000100
+ * count 16
+ * offset 0x70
+ */
+#define HW_APBX_CHn_CURCMDAR(n) (0x00000100 + (n) * 0x70)
+#define BP_APBX_CHn_CURCMDAR_CMD_ADDR 0
+#define BM_APBX_CHn_CURCMDAR_CMD_ADDR 0xFFFFFFFF
+#define BF_APBX_CHn_CURCMDAR_CMD_ADDR(v) (v)
+
+/*
+ * multi-register-define name HW_APBX_CHn_NXTCMDAR
+ * base 0x00000110
+ * count 16
+ * offset 0x70
+ */
+#define HW_APBX_CHn_NXTCMDAR(n) (0x00000110 + (n) * 0x70)
+#define BP_APBX_CHn_NXTCMDAR_CMD_ADDR 0
+#define BM_APBX_CHn_NXTCMDAR_CMD_ADDR 0xFFFFFFFF
+#define BF_APBX_CHn_NXTCMDAR_CMD_ADDR(v) (v)
+
+/*
+ * multi-register-define name HW_APBX_CHn_CMD
+ * base 0x00000120
+ * count 16
+ * offset 0x70
+ */
+#define HW_APBX_CHn_CMD(n) (0x00000120 + (n) * 0x70)
+#define BP_APBX_CHn_CMD_XFER_COUNT 16
+#define BM_APBX_CHn_CMD_XFER_COUNT 0xFFFF0000
+#define BF_APBX_CHn_CMD_XFER_COUNT(v) \
+ (((v) << 16) & BM_APBX_CHn_CMD_XFER_COUNT)
+#define BP_APBX_CHn_CMD_CMDWORDS 12
+#define BM_APBX_CHn_CMD_CMDWORDS 0x0000F000
+#define BF_APBX_CHn_CMD_CMDWORDS(v) \
+ (((v) << 12) & BM_APBX_CHn_CMD_CMDWORDS)
+#define BP_APBX_CHn_CMD_RSVD1 10
+#define BM_APBX_CHn_CMD_RSVD1 0x00000C00
+#define BF_APBX_CHn_CMD_RSVD1(v) \
+ (((v) << 10) & BM_APBX_CHn_CMD_RSVD1)
+#define BM_APBX_CHn_CMD_TERMINATEFLUSH 0x00000200
+#define BM_APBX_CHn_CMD_HALTONTERMINATE 0x00000100
+#define BM_APBX_CHn_CMD_WAIT4ENDCMD 0x00000080
+#define BM_APBX_CHn_CMD_SEMAPHORE 0x00000040
+#define BP_APBX_CHn_CMD_RSVD0 4
+#define BM_APBX_CHn_CMD_RSVD0 0x00000030
+#define BF_APBX_CHn_CMD_RSVD0(v) \
+ (((v) << 4) & BM_APBX_CHn_CMD_RSVD0)
+#define BM_APBX_CHn_CMD_IRQONCMPLT 0x00000008
+#define BM_APBX_CHn_CMD_CHAIN 0x00000004
+#define BP_APBX_CHn_CMD_COMMAND 0
+#define BM_APBX_CHn_CMD_COMMAND 0x00000003
+#define BF_APBX_CHn_CMD_COMMAND(v) \
+ (((v) << 0) & BM_APBX_CHn_CMD_COMMAND)
+#define BV_APBX_CHn_CMD_COMMAND__NO_DMA_XFER 0x0
+#define BV_APBX_CHn_CMD_COMMAND__DMA_WRITE 0x1
+#define BV_APBX_CHn_CMD_COMMAND__DMA_READ 0x2
+
+/*
+ * multi-register-define name HW_APBX_CHn_BAR
+ * base 0x00000130
+ * count 16
+ * offset 0x70
+ */
+#define HW_APBX_CHn_BAR(n) (0x00000130 + (n) * 0x70)
+#define BP_APBX_CHn_BAR_ADDRESS 0
+#define BM_APBX_CHn_BAR_ADDRESS 0xFFFFFFFF
+#define BF_APBX_CHn_BAR_ADDRESS(v) (v)
+
+/*
+ * multi-register-define name HW_APBX_CHn_SEMA
+ * base 0x00000140
+ * count 16
+ * offset 0x70
+ */
+#define HW_APBX_CHn_SEMA(n) (0x00000140 + (n) * 0x70)
+#define BP_APBX_CHn_SEMA_RSVD2 24
+#define BM_APBX_CHn_SEMA_RSVD2 0xFF000000
+#define BF_APBX_CHn_SEMA_RSVD2(v) \
+ (((v) << 24) & BM_APBX_CHn_SEMA_RSVD2)
+#define BP_APBX_CHn_SEMA_PHORE 16
+#define BM_APBX_CHn_SEMA_PHORE 0x00FF0000
+#define BF_APBX_CHn_SEMA_PHORE(v) \
+ (((v) << 16) & BM_APBX_CHn_SEMA_PHORE)
+#define BP_APBX_CHn_SEMA_RSVD1 8
+#define BM_APBX_CHn_SEMA_RSVD1 0x0000FF00
+#define BF_APBX_CHn_SEMA_RSVD1(v) \
+ (((v) << 8) & BM_APBX_CHn_SEMA_RSVD1)
+#define BP_APBX_CHn_SEMA_INCREMENT_SEMA 0
+#define BM_APBX_CHn_SEMA_INCREMENT_SEMA 0x000000FF
+#define BF_APBX_CHn_SEMA_INCREMENT_SEMA(v) \
+ (((v) << 0) & BM_APBX_CHn_SEMA_INCREMENT_SEMA)
+
+/*
+ * multi-register-define name HW_APBX_CHn_DEBUG1
+ * base 0x00000150
+ * count 16
+ * offset 0x70
+ */
+#define HW_APBX_CHn_DEBUG1(n) (0x00000150 + (n) * 0x70)
+#define BM_APBX_CHn_DEBUG1_REQ 0x80000000
+#define BM_APBX_CHn_DEBUG1_BURST 0x40000000
+#define BM_APBX_CHn_DEBUG1_KICK 0x20000000
+#define BM_APBX_CHn_DEBUG1_END 0x10000000
+#define BP_APBX_CHn_DEBUG1_RSVD2 25
+#define BM_APBX_CHn_DEBUG1_RSVD2 0x0E000000
+#define BF_APBX_CHn_DEBUG1_RSVD2(v) \
+ (((v) << 25) & BM_APBX_CHn_DEBUG1_RSVD2)
+#define BM_APBX_CHn_DEBUG1_NEXTCMDADDRVALID 0x01000000
+#define BM_APBX_CHn_DEBUG1_RD_FIFO_EMPTY 0x00800000
+#define BM_APBX_CHn_DEBUG1_RD_FIFO_FULL 0x00400000
+#define BM_APBX_CHn_DEBUG1_WR_FIFO_EMPTY 0x00200000
+#define BM_APBX_CHn_DEBUG1_WR_FIFO_FULL 0x00100000
+#define BP_APBX_CHn_DEBUG1_RSVD1 5
+#define BM_APBX_CHn_DEBUG1_RSVD1 0x000FFFE0
+#define BF_APBX_CHn_DEBUG1_RSVD1(v) \
+ (((v) << 5) & BM_APBX_CHn_DEBUG1_RSVD1)
+#define BP_APBX_CHn_DEBUG1_STATEMACHINE 0
+#define BM_APBX_CHn_DEBUG1_STATEMACHINE 0x0000001F
+#define BF_APBX_CHn_DEBUG1_STATEMACHINE(v) \
+ (((v) << 0) & BM_APBX_CHn_DEBUG1_STATEMACHINE)
+#define BV_APBX_CHn_DEBUG1_STATEMACHINE__IDLE 0x00
+#define BV_APBX_CHn_DEBUG1_STATEMACHINE__REQ_CMD1 0x01
+#define BV_APBX_CHn_DEBUG1_STATEMACHINE__REQ_CMD3 0x02
+#define BV_APBX_CHn_DEBUG1_STATEMACHINE__REQ_CMD2 0x03
+#define BV_APBX_CHn_DEBUG1_STATEMACHINE__XFER_DECODE 0x04
+#define BV_APBX_CHn_DEBUG1_STATEMACHINE__REQ_WAIT 0x05
+#define BV_APBX_CHn_DEBUG1_STATEMACHINE__REQ_CMD4 0x06
+#define BV_APBX_CHn_DEBUG1_STATEMACHINE__PIO_REQ 0x07
+#define BV_APBX_CHn_DEBUG1_STATEMACHINE__READ_FLUSH 0x08
+#define BV_APBX_CHn_DEBUG1_STATEMACHINE__READ_WAIT 0x09
+#define BV_APBX_CHn_DEBUG1_STATEMACHINE__WRITE 0x0C
+#define BV_APBX_CHn_DEBUG1_STATEMACHINE__READ_REQ 0x0D
+#define BV_APBX_CHn_DEBUG1_STATEMACHINE__CHECK_CHAIN 0x0E
+#define BV_APBX_CHn_DEBUG1_STATEMACHINE__XFER_COMPLETE 0x0F
+#define BV_APBX_CHn_DEBUG1_STATEMACHINE__WAIT_END 0x15
+#define BV_APBX_CHn_DEBUG1_STATEMACHINE__WRITE_WAIT 0x1C
+#define BV_APBX_CHn_DEBUG1_STATEMACHINE__CHECK_WAIT 0x1E
+
+/*
+ * multi-register-define name HW_APBX_CHn_DEBUG2
+ * base 0x00000160
+ * count 16
+ * offset 0x70
+ */
+#define HW_APBX_CHn_DEBUG2(n) (0x00000160 + (n) * 0x70)
+#define BP_APBX_CHn_DEBUG2_APB_BYTES 16
+#define BM_APBX_CHn_DEBUG2_APB_BYTES 0xFFFF0000
+#define BF_APBX_CHn_DEBUG2_APB_BYTES(v) \
+ (((v) << 16) & BM_APBX_CHn_DEBUG2_APB_BYTES)
+#define BP_APBX_CHn_DEBUG2_AHB_BYTES 0
+#define BM_APBX_CHn_DEBUG2_AHB_BYTES 0x0000FFFF
+#define BF_APBX_CHn_DEBUG2_AHB_BYTES(v) \
+ (((v) << 0) & BM_APBX_CHn_DEBUG2_AHB_BYTES)
+
+#define HW_APBX_VERSION (0x00000800)
+
+#define BP_APBX_VERSION_MAJOR 24
+#define BM_APBX_VERSION_MAJOR 0xFF000000
+#define BF_APBX_VERSION_MAJOR(v) \
+ (((v) << 24) & BM_APBX_VERSION_MAJOR)
+#define BP_APBX_VERSION_MINOR 16
+#define BM_APBX_VERSION_MINOR 0x00FF0000
+#define BF_APBX_VERSION_MINOR(v) \
+ (((v) << 16) & BM_APBX_VERSION_MINOR)
+#define BP_APBX_VERSION_STEP 0
+#define BM_APBX_VERSION_STEP 0x0000FFFF
+#define BF_APBX_VERSION_STEP(v) \
+ (((v) << 0) & BM_APBX_VERSION_STEP)
+#endif /* __ARCH_ARM___APBX_H */
diff --git a/arch/arm/plat-mxs/regs-icoll.h b/arch/arm/plat-mxs/regs-icoll.h
new file mode 100644
index 000000000000..f06ac0d4720b
--- /dev/null
+++ b/arch/arm/plat-mxs/regs-icoll.h
@@ -0,0 +1,293 @@
+/*
+ * Freescale ICOLL Register Definitions
+ *
+ * Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * This file is created by xml file. Don't Edit it.
+ *
+ * Xml Revision: 1.50
+ * Template revision: 26195
+ */
+
+#ifndef __ARCH_ARM___ICOLL_H
+#define __ARCH_ARM___ICOLL_H
+
+#define HW_ICOLL_VECTOR (0x00000000)
+#define HW_ICOLL_VECTOR_SET (0x00000004)
+#define HW_ICOLL_VECTOR_CLR (0x00000008)
+#define HW_ICOLL_VECTOR_TOG (0x0000000c)
+
+#define BP_ICOLL_VECTOR_IRQVECTOR 2
+#define BM_ICOLL_VECTOR_IRQVECTOR 0xFFFFFFFC
+#define BF_ICOLL_VECTOR_IRQVECTOR(v) \
+ (((v) << 2) & BM_ICOLL_VECTOR_IRQVECTOR)
+#define BP_ICOLL_VECTOR_RSRVD1 0
+#define BM_ICOLL_VECTOR_RSRVD1 0x00000003
+#define BF_ICOLL_VECTOR_RSRVD1(v) \
+ (((v) << 0) & BM_ICOLL_VECTOR_RSRVD1)
+
+#define HW_ICOLL_LEVELACK (0x00000010)
+
+#define BP_ICOLL_LEVELACK_RSRVD1 4
+#define BM_ICOLL_LEVELACK_RSRVD1 0xFFFFFFF0
+#define BF_ICOLL_LEVELACK_RSRVD1(v) \
+ (((v) << 4) & BM_ICOLL_LEVELACK_RSRVD1)
+#define BP_ICOLL_LEVELACK_IRQLEVELACK 0
+#define BM_ICOLL_LEVELACK_IRQLEVELACK 0x0000000F
+#define BF_ICOLL_LEVELACK_IRQLEVELACK(v) \
+ (((v) << 0) & BM_ICOLL_LEVELACK_IRQLEVELACK)
+#define BV_ICOLL_LEVELACK_IRQLEVELACK__LEVEL0 0x1
+#define BV_ICOLL_LEVELACK_IRQLEVELACK__LEVEL1 0x2
+#define BV_ICOLL_LEVELACK_IRQLEVELACK__LEVEL2 0x4
+#define BV_ICOLL_LEVELACK_IRQLEVELACK__LEVEL3 0x8
+
+#define HW_ICOLL_CTRL (0x00000020)
+#define HW_ICOLL_CTRL_SET (0x00000024)
+#define HW_ICOLL_CTRL_CLR (0x00000028)
+#define HW_ICOLL_CTRL_TOG (0x0000002c)
+
+#define BM_ICOLL_CTRL_SFTRST 0x80000000
+#define BV_ICOLL_CTRL_SFTRST__RUN 0x0
+#define BV_ICOLL_CTRL_SFTRST__IN_RESET 0x1
+#define BM_ICOLL_CTRL_CLKGATE 0x40000000
+#define BV_ICOLL_CTRL_CLKGATE__RUN 0x0
+#define BV_ICOLL_CTRL_CLKGATE__NO_CLOCKS 0x1
+#define BP_ICOLL_CTRL_RSRVD3 24
+#define BM_ICOLL_CTRL_RSRVD3 0x3F000000
+#define BF_ICOLL_CTRL_RSRVD3(v) \
+ (((v) << 24) & BM_ICOLL_CTRL_RSRVD3)
+#define BP_ICOLL_CTRL_VECTOR_PITCH 21
+#define BM_ICOLL_CTRL_VECTOR_PITCH 0x00E00000
+#define BF_ICOLL_CTRL_VECTOR_PITCH(v) \
+ (((v) << 21) & BM_ICOLL_CTRL_VECTOR_PITCH)
+#define BV_ICOLL_CTRL_VECTOR_PITCH__DEFAULT_BY4 0x0
+#define BV_ICOLL_CTRL_VECTOR_PITCH__BY4 0x1
+#define BV_ICOLL_CTRL_VECTOR_PITCH__BY8 0x2
+#define BV_ICOLL_CTRL_VECTOR_PITCH__BY12 0x3
+#define BV_ICOLL_CTRL_VECTOR_PITCH__BY16 0x4
+#define BV_ICOLL_CTRL_VECTOR_PITCH__BY20 0x5
+#define BV_ICOLL_CTRL_VECTOR_PITCH__BY24 0x6
+#define BV_ICOLL_CTRL_VECTOR_PITCH__BY28 0x7
+#define BM_ICOLL_CTRL_BYPASS_FSM 0x00100000
+#define BV_ICOLL_CTRL_BYPASS_FSM__NORMAL 0x0
+#define BV_ICOLL_CTRL_BYPASS_FSM__BYPASS 0x1
+#define BM_ICOLL_CTRL_NO_NESTING 0x00080000
+#define BV_ICOLL_CTRL_NO_NESTING__NORMAL 0x0
+#define BV_ICOLL_CTRL_NO_NESTING__NO_NEST 0x1
+#define BM_ICOLL_CTRL_ARM_RSE_MODE 0x00040000
+#define BM_ICOLL_CTRL_FIQ_FINAL_ENABLE 0x00020000
+#define BV_ICOLL_CTRL_FIQ_FINAL_ENABLE__DISABLE 0x0
+#define BV_ICOLL_CTRL_FIQ_FINAL_ENABLE__ENABLE 0x1
+#define BM_ICOLL_CTRL_IRQ_FINAL_ENABLE 0x00010000
+#define BV_ICOLL_CTRL_IRQ_FINAL_ENABLE__DISABLE 0x0
+#define BV_ICOLL_CTRL_IRQ_FINAL_ENABLE__ENABLE 0x1
+#define BP_ICOLL_CTRL_RSRVD1 0
+#define BM_ICOLL_CTRL_RSRVD1 0x0000FFFF
+#define BF_ICOLL_CTRL_RSRVD1(v) \
+ (((v) << 0) & BM_ICOLL_CTRL_RSRVD1)
+
+#define HW_ICOLL_VBASE (0x00000040)
+#define HW_ICOLL_VBASE_SET (0x00000044)
+#define HW_ICOLL_VBASE_CLR (0x00000048)
+#define HW_ICOLL_VBASE_TOG (0x0000004c)
+
+#define BP_ICOLL_VBASE_TABLE_ADDRESS 2
+#define BM_ICOLL_VBASE_TABLE_ADDRESS 0xFFFFFFFC
+#define BF_ICOLL_VBASE_TABLE_ADDRESS(v) \
+ (((v) << 2) & BM_ICOLL_VBASE_TABLE_ADDRESS)
+#define BP_ICOLL_VBASE_RSRVD1 0
+#define BM_ICOLL_VBASE_RSRVD1 0x00000003
+#define BF_ICOLL_VBASE_RSRVD1(v) \
+ (((v) << 0) & BM_ICOLL_VBASE_RSRVD1)
+
+#define HW_ICOLL_STAT (0x00000070)
+
+#define BP_ICOLL_STAT_RSRVD1 7
+#define BM_ICOLL_STAT_RSRVD1 0xFFFFFF80
+#define BF_ICOLL_STAT_RSRVD1(v) \
+ (((v) << 7) & BM_ICOLL_STAT_RSRVD1)
+#define BP_ICOLL_STAT_VECTOR_NUMBER 0
+#define BM_ICOLL_STAT_VECTOR_NUMBER 0x0000007F
+#define BF_ICOLL_STAT_VECTOR_NUMBER(v) \
+ (((v) << 0) & BM_ICOLL_STAT_VECTOR_NUMBER)
+
+/*
+ * multi-register-define name HW_ICOLL_RAWn
+ * base 0x000000A0
+ * count 4
+ * offset 0x10
+ */
+#define HW_ICOLL_RAWn(n) (0x000000a0 + (n) * 0x10)
+#define HW_ICOLL_RAWn_SET(n) (0x000000a4 + (n) * 0x10)
+#define HW_ICOLL_RAWn_CLR(n) (0x000000a8 + (n) * 0x10)
+#define HW_ICOLL_RAWn_TOG(n) (0x000000ac + (n) * 0x10)
+#define BP_ICOLL_RAWn_RAW_IRQS 0
+#define BM_ICOLL_RAWn_RAW_IRQS 0xFFFFFFFF
+#define BF_ICOLL_RAWn_RAW_IRQS(v) (v)
+
+/*
+ * multi-register-define name HW_ICOLL_INTERRUPTn
+ * base 0x00000120
+ * count 128
+ * offset 0x10
+ */
+#define HW_ICOLL_INTERRUPTn(n) (0x00000120 + (n) * 0x10)
+#define HW_ICOLL_INTERRUPTn_SET(n) (0x00000124 + (n) * 0x10)
+#define HW_ICOLL_INTERRUPTn_CLR(n) (0x00000128 + (n) * 0x10)
+#define HW_ICOLL_INTERRUPTn_TOG(n) (0x0000012c + (n) * 0x10)
+#define BP_ICOLL_INTERRUPTn_RSRVD1 5
+#define BM_ICOLL_INTERRUPTn_RSRVD1 0xFFFFFFE0
+#define BF_ICOLL_INTERRUPTn_RSRVD1(v) \
+ (((v) << 5) & BM_ICOLL_INTERRUPTn_RSRVD1)
+#define BM_ICOLL_INTERRUPTn_ENFIQ 0x00000010
+#define BV_ICOLL_INTERRUPTn_ENFIQ__DISABLE 0x0
+#define BV_ICOLL_INTERRUPTn_ENFIQ__ENABLE 0x1
+#define BM_ICOLL_INTERRUPTn_SOFTIRQ 0x00000008
+#define BV_ICOLL_INTERRUPTn_SOFTIRQ__NO_INTERRUPT 0x0
+#define BV_ICOLL_INTERRUPTn_SOFTIRQ__FORCE_INTERRUPT 0x1
+#define BM_ICOLL_INTERRUPTn_ENABLE 0x00000004
+#define BV_ICOLL_INTERRUPTn_ENABLE__DISABLE 0x0
+#define BV_ICOLL_INTERRUPTn_ENABLE__ENABLE 0x1
+#define BP_ICOLL_INTERRUPTn_PRIORITY 0
+#define BM_ICOLL_INTERRUPTn_PRIORITY 0x00000003
+#define BF_ICOLL_INTERRUPTn_PRIORITY(v) \
+ (((v) << 0) & BM_ICOLL_INTERRUPTn_PRIORITY)
+#define BV_ICOLL_INTERRUPTn_PRIORITY__LEVEL0 0x0
+#define BV_ICOLL_INTERRUPTn_PRIORITY__LEVEL1 0x1
+#define BV_ICOLL_INTERRUPTn_PRIORITY__LEVEL2 0x2
+#define BV_ICOLL_INTERRUPTn_PRIORITY__LEVEL3 0x3
+
+#define HW_ICOLL_DEBUG (0x00001120)
+#define HW_ICOLL_DEBUG_SET (0x00001124)
+#define HW_ICOLL_DEBUG_CLR (0x00001128)
+#define HW_ICOLL_DEBUG_TOG (0x0000112c)
+
+#define BP_ICOLL_DEBUG_INSERVICE 28
+#define BM_ICOLL_DEBUG_INSERVICE 0xF0000000
+#define BF_ICOLL_DEBUG_INSERVICE(v) \
+ (((v) << 28) & BM_ICOLL_DEBUG_INSERVICE)
+#define BV_ICOLL_DEBUG_INSERVICE__LEVEL0 0x1
+#define BV_ICOLL_DEBUG_INSERVICE__LEVEL1 0x2
+#define BV_ICOLL_DEBUG_INSERVICE__LEVEL2 0x4
+#define BV_ICOLL_DEBUG_INSERVICE__LEVEL3 0x8
+#define BP_ICOLL_DEBUG_LEVEL_REQUESTS 24
+#define BM_ICOLL_DEBUG_LEVEL_REQUESTS 0x0F000000
+#define BF_ICOLL_DEBUG_LEVEL_REQUESTS(v) \
+ (((v) << 24) & BM_ICOLL_DEBUG_LEVEL_REQUESTS)
+#define BV_ICOLL_DEBUG_LEVEL_REQUESTS__LEVEL0 0x1
+#define BV_ICOLL_DEBUG_LEVEL_REQUESTS__LEVEL1 0x2
+#define BV_ICOLL_DEBUG_LEVEL_REQUESTS__LEVEL2 0x4
+#define BV_ICOLL_DEBUG_LEVEL_REQUESTS__LEVEL3 0x8
+#define BP_ICOLL_DEBUG_REQUESTS_BY_LEVEL 20
+#define BM_ICOLL_DEBUG_REQUESTS_BY_LEVEL 0x00F00000
+#define BF_ICOLL_DEBUG_REQUESTS_BY_LEVEL(v) \
+ (((v) << 20) & BM_ICOLL_DEBUG_REQUESTS_BY_LEVEL)
+#define BV_ICOLL_DEBUG_REQUESTS_BY_LEVEL__LEVEL0 0x1
+#define BV_ICOLL_DEBUG_REQUESTS_BY_LEVEL__LEVEL1 0x2
+#define BV_ICOLL_DEBUG_REQUESTS_BY_LEVEL__LEVEL2 0x4
+#define BV_ICOLL_DEBUG_REQUESTS_BY_LEVEL__LEVEL3 0x8
+#define BP_ICOLL_DEBUG_RSRVD2 18
+#define BM_ICOLL_DEBUG_RSRVD2 0x000C0000
+#define BF_ICOLL_DEBUG_RSRVD2(v) \
+ (((v) << 18) & BM_ICOLL_DEBUG_RSRVD2)
+#define BM_ICOLL_DEBUG_FIQ 0x00020000
+#define BV_ICOLL_DEBUG_FIQ__NO_FIQ_REQUESTED 0x0
+#define BV_ICOLL_DEBUG_FIQ__FIQ_REQUESTED 0x1
+#define BM_ICOLL_DEBUG_IRQ 0x00010000
+#define BV_ICOLL_DEBUG_IRQ__NO_IRQ_REQUESTED 0x0
+#define BV_ICOLL_DEBUG_IRQ__IRQ_REQUESTED 0x1
+#define BP_ICOLL_DEBUG_RSRVD1 10
+#define BM_ICOLL_DEBUG_RSRVD1 0x0000FC00
+#define BF_ICOLL_DEBUG_RSRVD1(v) \
+ (((v) << 10) & BM_ICOLL_DEBUG_RSRVD1)
+#define BP_ICOLL_DEBUG_VECTOR_FSM 0
+#define BM_ICOLL_DEBUG_VECTOR_FSM 0x000003FF
+#define BF_ICOLL_DEBUG_VECTOR_FSM(v) \
+ (((v) << 0) & BM_ICOLL_DEBUG_VECTOR_FSM)
+#define BV_ICOLL_DEBUG_VECTOR_FSM__FSM_IDLE 0x000
+#define BV_ICOLL_DEBUG_VECTOR_FSM__FSM_MULTICYCLE1 0x001
+#define BV_ICOLL_DEBUG_VECTOR_FSM__FSM_MULTICYCLE2 0x002
+#define BV_ICOLL_DEBUG_VECTOR_FSM__FSM_PENDING 0x004
+#define BV_ICOLL_DEBUG_VECTOR_FSM__FSM_MULTICYCLE3 0x008
+#define BV_ICOLL_DEBUG_VECTOR_FSM__FSM_MULTICYCLE4 0x010
+#define BV_ICOLL_DEBUG_VECTOR_FSM__FSM_ISR_RUNNING1 0x020
+#define BV_ICOLL_DEBUG_VECTOR_FSM__FSM_ISR_RUNNING2 0x040
+#define BV_ICOLL_DEBUG_VECTOR_FSM__FSM_ISR_RUNNING3 0x080
+#define BV_ICOLL_DEBUG_VECTOR_FSM__FSM_MULTICYCLE5 0x100
+#define BV_ICOLL_DEBUG_VECTOR_FSM__FSM_MULTICYCLE6 0x200
+
+#define HW_ICOLL_DBGREAD0 (0x00001130)
+#define HW_ICOLL_DBGREAD0_SET (0x00001134)
+#define HW_ICOLL_DBGREAD0_CLR (0x00001138)
+#define HW_ICOLL_DBGREAD0_TOG (0x0000113c)
+
+#define BP_ICOLL_DBGREAD0_VALUE 0
+#define BM_ICOLL_DBGREAD0_VALUE 0xFFFFFFFF
+#define BF_ICOLL_DBGREAD0_VALUE(v) (v)
+
+#define HW_ICOLL_DBGREAD1 (0x00001140)
+#define HW_ICOLL_DBGREAD1_SET (0x00001144)
+#define HW_ICOLL_DBGREAD1_CLR (0x00001148)
+#define HW_ICOLL_DBGREAD1_TOG (0x0000114c)
+
+#define BP_ICOLL_DBGREAD1_VALUE 0
+#define BM_ICOLL_DBGREAD1_VALUE 0xFFFFFFFF
+#define BF_ICOLL_DBGREAD1_VALUE(v) (v)
+
+#define HW_ICOLL_DBGFLAG (0x00001150)
+#define HW_ICOLL_DBGFLAG_SET (0x00001154)
+#define HW_ICOLL_DBGFLAG_CLR (0x00001158)
+#define HW_ICOLL_DBGFLAG_TOG (0x0000115c)
+
+#define BP_ICOLL_DBGFLAG_RSRVD1 16
+#define BM_ICOLL_DBGFLAG_RSRVD1 0xFFFF0000
+#define BF_ICOLL_DBGFLAG_RSRVD1(v) \
+ (((v) << 16) & BM_ICOLL_DBGFLAG_RSRVD1)
+#define BP_ICOLL_DBGFLAG_FLAG 0
+#define BM_ICOLL_DBGFLAG_FLAG 0x0000FFFF
+#define BF_ICOLL_DBGFLAG_FLAG(v) \
+ (((v) << 0) & BM_ICOLL_DBGFLAG_FLAG)
+
+/*
+ * multi-register-define name HW_ICOLL_DBGREQUESTn
+ * base 0x00001160
+ * count 4
+ * offset 0x10
+ */
+#define HW_ICOLL_DBGREQUESTn(n) (0x00001160 + (n) * 0x10)
+#define HW_ICOLL_DBGREQUESTn_SET(n) (0x00001164 + (n) * 0x10)
+#define HW_ICOLL_DBGREQUESTn_CLR(n) (0x00001168 + (n) * 0x10)
+#define HW_ICOLL_DBGREQUESTn_TOG(n) (0x0000116c + (n) * 0x10)
+#define BP_ICOLL_DBGREQUESTn_BITS 0
+#define BM_ICOLL_DBGREQUESTn_BITS 0xFFFFFFFF
+#define BF_ICOLL_DBGREQUESTn_BITS(v) (v)
+
+#define HW_ICOLL_VERSION (0x000011e0)
+
+#define BP_ICOLL_VERSION_MAJOR 24
+#define BM_ICOLL_VERSION_MAJOR 0xFF000000
+#define BF_ICOLL_VERSION_MAJOR(v) \
+ (((v) << 24) & BM_ICOLL_VERSION_MAJOR)
+#define BP_ICOLL_VERSION_MINOR 16
+#define BM_ICOLL_VERSION_MINOR 0x00FF0000
+#define BF_ICOLL_VERSION_MINOR(v) \
+ (((v) << 16) & BM_ICOLL_VERSION_MINOR)
+#define BP_ICOLL_VERSION_STEP 0
+#define BM_ICOLL_VERSION_STEP 0x0000FFFF
+#define BF_ICOLL_VERSION_STEP(v) \
+ (((v) << 0) & BM_ICOLL_VERSION_STEP)
+#endif /* __ARCH_ARM___ICOLL_H */
diff --git a/arch/arm/plat-mxs/regs-usbphy.h b/arch/arm/plat-mxs/regs-usbphy.h
new file mode 100644
index 000000000000..cf64bfdab0e6
--- /dev/null
+++ b/arch/arm/plat-mxs/regs-usbphy.h
@@ -0,0 +1,323 @@
+/*
+ * Freescale USBPHY Register Definitions
+ *
+ * Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * This file is created by xml file. Don't Edit it.
+ *
+ * Xml Revision: 1.52
+ * Template revision: 26195
+ */
+
+#ifndef __ARCH_ARM___USBPHY_H
+#define __ARCH_ARM___USBPHY_H
+
+
+#define HW_USBPHY_PWD (0x00000000)
+#define HW_USBPHY_PWD_SET (0x00000004)
+#define HW_USBPHY_PWD_CLR (0x00000008)
+#define HW_USBPHY_PWD_TOG (0x0000000c)
+
+#define BP_USBPHY_PWD_RSVD2 21
+#define BM_USBPHY_PWD_RSVD2 0xFFE00000
+#define BF_USBPHY_PWD_RSVD2(v) \
+ (((v) << 21) & BM_USBPHY_PWD_RSVD2)
+#define BM_USBPHY_PWD_RXPWDRX 0x00100000
+#define BM_USBPHY_PWD_RXPWDDIFF 0x00080000
+#define BM_USBPHY_PWD_RXPWD1PT1 0x00040000
+#define BM_USBPHY_PWD_RXPWDENV 0x00020000
+#define BP_USBPHY_PWD_RSVD1 13
+#define BM_USBPHY_PWD_RSVD1 0x0001E000
+#define BF_USBPHY_PWD_RSVD1(v) \
+ (((v) << 13) & BM_USBPHY_PWD_RSVD1)
+#define BM_USBPHY_PWD_TXPWDV2I 0x00001000
+#define BM_USBPHY_PWD_TXPWDIBIAS 0x00000800
+#define BM_USBPHY_PWD_TXPWDFS 0x00000400
+#define BP_USBPHY_PWD_RSVD0 0
+#define BM_USBPHY_PWD_RSVD0 0x000003FF
+#define BF_USBPHY_PWD_RSVD0(v) \
+ (((v) << 0) & BM_USBPHY_PWD_RSVD0)
+
+#define HW_USBPHY_TX (0x00000010)
+#define HW_USBPHY_TX_SET (0x00000014)
+#define HW_USBPHY_TX_CLR (0x00000018)
+#define HW_USBPHY_TX_TOG (0x0000001c)
+
+#define BP_USBPHY_TX_RSVD5 29
+#define BM_USBPHY_TX_RSVD5 0xE0000000
+#define BF_USBPHY_TX_RSVD5(v) \
+ (((v) << 29) & BM_USBPHY_TX_RSVD5)
+#define BP_USBPHY_TX_USBPHY_TX_EDGECTRL 26
+#define BM_USBPHY_TX_USBPHY_TX_EDGECTRL 0x1C000000
+#define BF_USBPHY_TX_USBPHY_TX_EDGECTRL(v) \
+ (((v) << 26) & BM_USBPHY_TX_USBPHY_TX_EDGECTRL)
+#define BM_USBPHY_TX_USBPHY_TX_SYNC_INVERT 0x02000000
+#define BM_USBPHY_TX_USBPHY_TX_SYNC_MUX 0x01000000
+#define BP_USBPHY_TX_RSVD4 22
+#define BM_USBPHY_TX_RSVD4 0x00C00000
+#define BF_USBPHY_TX_RSVD4(v) \
+ (((v) << 22) & BM_USBPHY_TX_RSVD4)
+#define BM_USBPHY_TX_TXENCAL45DP 0x00200000
+#define BM_USBPHY_TX_RSVD3 0x00100000
+#define BP_USBPHY_TX_TXCAL45DP 16
+#define BM_USBPHY_TX_TXCAL45DP 0x000F0000
+#define BF_USBPHY_TX_TXCAL45DP(v) \
+ (((v) << 16) & BM_USBPHY_TX_TXCAL45DP)
+#define BP_USBPHY_TX_RSVD2 14
+#define BM_USBPHY_TX_RSVD2 0x0000C000
+#define BF_USBPHY_TX_RSVD2(v) \
+ (((v) << 14) & BM_USBPHY_TX_RSVD2)
+#define BM_USBPHY_TX_TXENCAL45DN 0x00002000
+#define BM_USBPHY_TX_RSVD1 0x00001000
+#define BP_USBPHY_TX_TXCAL45DN 8
+#define BM_USBPHY_TX_TXCAL45DN 0x00000F00
+#define BF_USBPHY_TX_TXCAL45DN(v) \
+ (((v) << 8) & BM_USBPHY_TX_TXCAL45DN)
+#define BP_USBPHY_TX_RSVD0 4
+#define BM_USBPHY_TX_RSVD0 0x000000F0
+#define BF_USBPHY_TX_RSVD0(v) \
+ (((v) << 4) & BM_USBPHY_TX_RSVD0)
+#define BP_USBPHY_TX_D_CAL 0
+#define BM_USBPHY_TX_D_CAL 0x0000000F
+#define BF_USBPHY_TX_D_CAL(v) \
+ (((v) << 0) & BM_USBPHY_TX_D_CAL)
+
+#define HW_USBPHY_RX (0x00000020)
+#define HW_USBPHY_RX_SET (0x00000024)
+#define HW_USBPHY_RX_CLR (0x00000028)
+#define HW_USBPHY_RX_TOG (0x0000002c)
+
+#define BP_USBPHY_RX_RSVD2 23
+#define BM_USBPHY_RX_RSVD2 0xFF800000
+#define BF_USBPHY_RX_RSVD2(v) \
+ (((v) << 23) & BM_USBPHY_RX_RSVD2)
+#define BM_USBPHY_RX_RXDBYPASS 0x00400000
+#define BP_USBPHY_RX_RSVD1 7
+#define BM_USBPHY_RX_RSVD1 0x003FFF80
+#define BF_USBPHY_RX_RSVD1(v) \
+ (((v) << 7) & BM_USBPHY_RX_RSVD1)
+#define BP_USBPHY_RX_DISCONADJ 4
+#define BM_USBPHY_RX_DISCONADJ 0x00000070
+#define BF_USBPHY_RX_DISCONADJ(v) \
+ (((v) << 4) & BM_USBPHY_RX_DISCONADJ)
+#define BM_USBPHY_RX_RSVD0 0x00000008
+#define BP_USBPHY_RX_ENVADJ 0
+#define BM_USBPHY_RX_ENVADJ 0x00000007
+#define BF_USBPHY_RX_ENVADJ(v) \
+ (((v) << 0) & BM_USBPHY_RX_ENVADJ)
+
+#define HW_USBPHY_CTRL (0x00000030)
+#define HW_USBPHY_CTRL_SET (0x00000034)
+#define HW_USBPHY_CTRL_CLR (0x00000038)
+#define HW_USBPHY_CTRL_TOG (0x0000003c)
+
+#define BM_USBPHY_CTRL_SFTRST 0x80000000
+#define BM_USBPHY_CTRL_CLKGATE 0x40000000
+#define BM_USBPHY_CTRL_UTMI_SUSPENDM 0x20000000
+#define BM_USBPHY_CTRL_HOST_FORCE_LS_SE0 0x10000000
+#define BM_USBPHY_CTRL_RSVD3 0x08000000
+#define BM_USBPHY_CTRL_ENAUTOSET_USBCLKS 0x04000000
+#define BM_USBPHY_CTRL_ENAUTOCLR_USBCLKGATE 0x02000000
+#define BM_USBPHY_CTRL_FSDLL_RST_EN 0x01000000
+#define BM_USBPHY_CTRL_ENVBUSCHG_WKUP 0x00800000
+#define BM_USBPHY_CTRL_ENIDCHG_WKUP 0x00400000
+#define BM_USBPHY_CTRL_ENDPDMCHG_WKUP 0x00200000
+#define BM_USBPHY_CTRL_ENAUTOCLR_PHY_PWD 0x00100000
+#define BM_USBPHY_CTRL_ENAUTOCLR_CLKGATE 0x00080000
+#define BM_USBPHY_CTRL_ENAUTO_PWRON_PLL 0x00040000
+#define BM_USBPHY_CTRL_WAKEUP_IRQ 0x00020000
+#define BM_USBPHY_CTRL_ENIRQWAKEUP 0x00010000
+#define BM_USBPHY_CTRL_ENUTMILEVEL3 0x00008000
+#define BM_USBPHY_CTRL_ENUTMILEVEL2 0x00004000
+#define BM_USBPHY_CTRL_DATA_ON_LRADC 0x00002000
+#define BM_USBPHY_CTRL_DEVPLUGIN_IRQ 0x00001000
+#define BM_USBPHY_CTRL_ENIRQDEVPLUGIN 0x00000800
+#define BM_USBPHY_CTRL_RESUME_IRQ 0x00000400
+#define BM_USBPHY_CTRL_ENIRQRESUMEDETECT 0x00000200
+#define BM_USBPHY_CTRL_RESUMEIRQSTICKY 0x00000100
+#define BM_USBPHY_CTRL_ENOTGIDDETECT 0x00000080
+#define BM_USBPHY_CTRL_RSVD1 0x00000040
+#define BM_USBPHY_CTRL_DEVPLUGIN_POLARITY 0x00000020
+#define BM_USBPHY_CTRL_ENDEVPLUGINDETECT 0x00000010
+#define BM_USBPHY_CTRL_HOSTDISCONDETECT_IRQ 0x00000008
+#define BM_USBPHY_CTRL_ENIRQHOSTDISCON 0x00000004
+#define BM_USBPHY_CTRL_ENHOSTDISCONDETECT 0x00000002
+#define BM_USBPHY_CTRL_RSVD0 0x00000001
+
+#define HW_USBPHY_STATUS (0x00000040)
+
+#define BP_USBPHY_STATUS_RSVD4 11
+#define BM_USBPHY_STATUS_RSVD4 0xFFFFF800
+#define BF_USBPHY_STATUS_RSVD4(v) \
+ (((v) << 11) & BM_USBPHY_STATUS_RSVD4)
+#define BM_USBPHY_STATUS_RESUME_STATUS 0x00000400
+#define BM_USBPHY_STATUS_RSVD3 0x00000200
+#define BM_USBPHY_STATUS_OTGID_STATUS 0x00000100
+#define BM_USBPHY_STATUS_RSVD2 0x00000080
+#define BM_USBPHY_STATUS_DEVPLUGIN_STATUS 0x00000040
+#define BP_USBPHY_STATUS_RSVD1 4
+#define BM_USBPHY_STATUS_RSVD1 0x00000030
+#define BF_USBPHY_STATUS_RSVD1(v) \
+ (((v) << 4) & BM_USBPHY_STATUS_RSVD1)
+#define BM_USBPHY_STATUS_HOSTDISCONDETECT_STATUS 0x00000008
+#define BP_USBPHY_STATUS_RSVD0 0
+#define BM_USBPHY_STATUS_RSVD0 0x00000007
+#define BF_USBPHY_STATUS_RSVD0(v) \
+ (((v) << 0) & BM_USBPHY_STATUS_RSVD0)
+
+#define HW_USBPHY_DEBUG (0x00000050)
+#define HW_USBPHY_DEBUG_SET (0x00000054)
+#define HW_USBPHY_DEBUG_CLR (0x00000058)
+#define HW_USBPHY_DEBUG_TOG (0x0000005c)
+
+#define BM_USBPHY_DEBUG_RSVD3 0x80000000
+#define BM_USBPHY_DEBUG_CLKGATE 0x40000000
+#define BM_USBPHY_DEBUG_HOST_RESUME_DEBUG 0x20000000
+#define BP_USBPHY_DEBUG_SQUELCHRESETLENGTH 25
+#define BM_USBPHY_DEBUG_SQUELCHRESETLENGTH 0x1E000000
+#define BF_USBPHY_DEBUG_SQUELCHRESETLENGTH(v) \
+ (((v) << 25) & BM_USBPHY_DEBUG_SQUELCHRESETLENGTH)
+#define BM_USBPHY_DEBUG_ENSQUELCHRESET 0x01000000
+#define BP_USBPHY_DEBUG_RSVD2 21
+#define BM_USBPHY_DEBUG_RSVD2 0x00E00000
+#define BF_USBPHY_DEBUG_RSVD2(v) \
+ (((v) << 21) & BM_USBPHY_DEBUG_RSVD2)
+#define BP_USBPHY_DEBUG_SQUELCHRESETCOUNT 16
+#define BM_USBPHY_DEBUG_SQUELCHRESETCOUNT 0x001F0000
+#define BF_USBPHY_DEBUG_SQUELCHRESETCOUNT(v) \
+ (((v) << 16) & BM_USBPHY_DEBUG_SQUELCHRESETCOUNT)
+#define BP_USBPHY_DEBUG_RSVD1 13
+#define BM_USBPHY_DEBUG_RSVD1 0x0000E000
+#define BF_USBPHY_DEBUG_RSVD1(v) \
+ (((v) << 13) & BM_USBPHY_DEBUG_RSVD1)
+#define BM_USBPHY_DEBUG_ENTX2RXCOUNT 0x00001000
+#define BP_USBPHY_DEBUG_TX2RXCOUNT 8
+#define BM_USBPHY_DEBUG_TX2RXCOUNT 0x00000F00
+#define BF_USBPHY_DEBUG_TX2RXCOUNT(v) \
+ (((v) << 8) & BM_USBPHY_DEBUG_TX2RXCOUNT)
+#define BP_USBPHY_DEBUG_RSVD0 6
+#define BM_USBPHY_DEBUG_RSVD0 0x000000C0
+#define BF_USBPHY_DEBUG_RSVD0(v) \
+ (((v) << 6) & BM_USBPHY_DEBUG_RSVD0)
+#define BP_USBPHY_DEBUG_ENHSTPULLDOWN 4
+#define BM_USBPHY_DEBUG_ENHSTPULLDOWN 0x00000030
+#define BF_USBPHY_DEBUG_ENHSTPULLDOWN(v) \
+ (((v) << 4) & BM_USBPHY_DEBUG_ENHSTPULLDOWN)
+#define BP_USBPHY_DEBUG_HSTPULLDOWN 2
+#define BM_USBPHY_DEBUG_HSTPULLDOWN 0x0000000C
+#define BF_USBPHY_DEBUG_HSTPULLDOWN(v) \
+ (((v) << 2) & BM_USBPHY_DEBUG_HSTPULLDOWN)
+#define BM_USBPHY_DEBUG_DEBUG_INTERFACE_HOLD 0x00000002
+#define BM_USBPHY_DEBUG_OTGIDPIOLOCK 0x00000001
+
+#define HW_USBPHY_DEBUG0_STATUS (0x00000060)
+
+#define BP_USBPHY_DEBUG0_STATUS_SQUELCH_COUNT 26
+#define BM_USBPHY_DEBUG0_STATUS_SQUELCH_COUNT 0xFC000000
+#define BF_USBPHY_DEBUG0_STATUS_SQUELCH_COUNT(v) \
+ (((v) << 26) & BM_USBPHY_DEBUG0_STATUS_SQUELCH_COUNT)
+#define BP_USBPHY_DEBUG0_STATUS_UTMI_RXERROR_FAIL_COUNT 16
+#define BM_USBPHY_DEBUG0_STATUS_UTMI_RXERROR_FAIL_COUNT 0x03FF0000
+#define BF_USBPHY_DEBUG0_STATUS_UTMI_RXERROR_FAIL_COUNT(v) \
+ (((v) << 16) & BM_USBPHY_DEBUG0_STATUS_UTMI_RXERROR_FAIL_COUNT)
+#define BP_USBPHY_DEBUG0_STATUS_LOOP_BACK_FAIL_COUNT 0
+#define BM_USBPHY_DEBUG0_STATUS_LOOP_BACK_FAIL_COUNT 0x0000FFFF
+#define BF_USBPHY_DEBUG0_STATUS_LOOP_BACK_FAIL_COUNT(v) \
+ (((v) << 0) & BM_USBPHY_DEBUG0_STATUS_LOOP_BACK_FAIL_COUNT)
+
+#define HW_USBPHY_DEBUG1 (0x00000070)
+#define HW_USBPHY_DEBUG1_SET (0x00000074)
+#define HW_USBPHY_DEBUG1_CLR (0x00000078)
+#define HW_USBPHY_DEBUG1_TOG (0x0000007c)
+
+#define BP_USBPHY_DEBUG1_RSVD1 15
+#define BM_USBPHY_DEBUG1_RSVD1 0xFFFF8000
+#define BF_USBPHY_DEBUG1_RSVD1(v) \
+ (((v) << 15) & BM_USBPHY_DEBUG1_RSVD1)
+#define BP_USBPHY_DEBUG1_ENTAILADJVD 13
+#define BM_USBPHY_DEBUG1_ENTAILADJVD 0x00006000
+#define BF_USBPHY_DEBUG1_ENTAILADJVD(v) \
+ (((v) << 13) & BM_USBPHY_DEBUG1_ENTAILADJVD)
+#define BM_USBPHY_DEBUG1_ENTX2TX 0x00001000
+#define BP_USBPHY_DEBUG1_RSVD0 4
+#define BM_USBPHY_DEBUG1_RSVD0 0x00000FF0
+#define BF_USBPHY_DEBUG1_RSVD0(v) \
+ (((v) << 4) & BM_USBPHY_DEBUG1_RSVD0)
+#define BP_USBPHY_DEBUG1_DBG_ADDRESS 0
+#define BM_USBPHY_DEBUG1_DBG_ADDRESS 0x0000000F
+#define BF_USBPHY_DEBUG1_DBG_ADDRESS(v) \
+ (((v) << 0) & BM_USBPHY_DEBUG1_DBG_ADDRESS)
+
+#define HW_USBPHY_VERSION (0x00000080)
+
+#define BP_USBPHY_VERSION_MAJOR 24
+#define BM_USBPHY_VERSION_MAJOR 0xFF000000
+#define BF_USBPHY_VERSION_MAJOR(v) \
+ (((v) << 24) & BM_USBPHY_VERSION_MAJOR)
+#define BP_USBPHY_VERSION_MINOR 16
+#define BM_USBPHY_VERSION_MINOR 0x00FF0000
+#define BF_USBPHY_VERSION_MINOR(v) \
+ (((v) << 16) & BM_USBPHY_VERSION_MINOR)
+#define BP_USBPHY_VERSION_STEP 0
+#define BM_USBPHY_VERSION_STEP 0x0000FFFF
+#define BF_USBPHY_VERSION_STEP(v) \
+ (((v) << 0) & BM_USBPHY_VERSION_STEP)
+
+#define HW_USBPHY_IP (0x00000090)
+#define HW_USBPHY_IP_SET (0x00000094)
+#define HW_USBPHY_IP_CLR (0x00000098)
+#define HW_USBPHY_IP_TOG (0x0000009c)
+
+#define BP_USBPHY_IP_RSVD1 25
+#define BM_USBPHY_IP_RSVD1 0xFE000000
+#define BF_USBPHY_IP_RSVD1(v) \
+ (((v) << 25) & BM_USBPHY_IP_RSVD1)
+#define BP_USBPHY_IP_DIV_SEL 23
+#define BM_USBPHY_IP_DIV_SEL 0x01800000
+#define BF_USBPHY_IP_DIV_SEL(v) \
+ (((v) << 23) & BM_USBPHY_IP_DIV_SEL)
+#define BV_USBPHY_IP_DIV_SEL__DEFAULT 0x0
+#define BV_USBPHY_IP_DIV_SEL__LOWER 0x1
+#define BV_USBPHY_IP_DIV_SEL__LOWEST 0x2
+#define BV_USBPHY_IP_DIV_SEL__UNDEFINED 0x3
+#define BP_USBPHY_IP_LFR_SEL 21
+#define BM_USBPHY_IP_LFR_SEL 0x00600000
+#define BF_USBPHY_IP_LFR_SEL(v) \
+ (((v) << 21) & BM_USBPHY_IP_LFR_SEL)
+#define BV_USBPHY_IP_LFR_SEL__DEFAULT 0x0
+#define BV_USBPHY_IP_LFR_SEL__TIMES_2 0x1
+#define BV_USBPHY_IP_LFR_SEL__TIMES_05 0x2
+#define BV_USBPHY_IP_LFR_SEL__UNDEFINED 0x3
+#define BP_USBPHY_IP_CP_SEL 19
+#define BM_USBPHY_IP_CP_SEL 0x00180000
+#define BF_USBPHY_IP_CP_SEL(v) \
+ (((v) << 19) & BM_USBPHY_IP_CP_SEL)
+#define BV_USBPHY_IP_CP_SEL__DEFAULT 0x0
+#define BV_USBPHY_IP_CP_SEL__TIMES_2 0x1
+#define BV_USBPHY_IP_CP_SEL__TIMES_05 0x2
+#define BV_USBPHY_IP_CP_SEL__UNDEFINED 0x3
+#define BM_USBPHY_IP_TSTI_TX_DP 0x00040000
+#define BM_USBPHY_IP_TSTI_TX_DM 0x00020000
+#define BM_USBPHY_IP_ANALOG_TESTMODE 0x00010000
+#define BP_USBPHY_IP_RSVD0 3
+#define BM_USBPHY_IP_RSVD0 0x0000FFF8
+#define BF_USBPHY_IP_RSVD0(v) \
+ (((v) << 3) & BM_USBPHY_IP_RSVD0)
+#define BM_USBPHY_IP_EN_USB_CLKS 0x00000004
+#define BM_USBPHY_IP_PLL_LOCKED 0x00000002
+#define BM_USBPHY_IP_PLL_POWER 0x00000001
+#endif /* __ARCH_ARM___USBPHY_H */
diff --git a/arch/arm/plat-mxs/timer-match.c b/arch/arm/plat-mxs/timer-match.c
new file mode 100644
index 000000000000..d6429e6955e6
--- /dev/null
+++ b/arch/arm/plat-mxs/timer-match.c
@@ -0,0 +1,164 @@
+/*
+ * System timer for Freescale i.MXS
+ *
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ * Copyright (C) 2009-2010 Freescale Semiconductor, Inc.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/spinlock.h>
+#include <linux/clocksource.h>
+#include <linux/clockchips.h>
+#include <linux/io.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+
+#include <asm/mach/time.h>
+
+#include <mach/device.h>
+#include <mach/regs-timrot.h>
+
+static struct mxs_sys_timer *online_timer;
+
+static irqreturn_t mxs_timer_handler(int irq, void *dev_id);
+
+static cycle_t mxs_get_cycles(struct clocksource *cs)
+{
+ return ~__raw_readl(online_timer->base +
+ HW_TIMROT_RUNNING_COUNTn(online_timer->id));
+}
+
+static int mxs_set_next_event(unsigned long delta,
+ struct clock_event_device *dev)
+{
+ unsigned int match;
+ match = __raw_readl(online_timer->base +
+ HW_TIMROT_RUNNING_COUNTn(online_timer->id)) - delta;
+ __raw_writel(match, online_timer->base +
+ HW_TIMROT_MATCH_COUNTn(online_timer->id));
+ return (int)(match -
+ __raw_readl(online_timer->base +
+ HW_TIMROT_RUNNING_COUNTn(online_timer->id)))
+ > 0 ? -ETIME : 0;
+}
+
+
+static void mxs_set_mode(enum clock_event_mode mode,
+ struct clock_event_device *evt)
+{
+ switch (mode) {
+ case CLOCK_EVT_MODE_SHUTDOWN:
+ __raw_writel(BM_TIMROT_TIMCTRLn_IRQ_EN | BM_TIMROT_TIMCTRLn_IRQ,
+ online_timer->base + HW_TIMROT_TIMCTRLn_CLR(0));
+ break;
+ case CLOCK_EVT_MODE_RESUME:
+ case CLOCK_EVT_MODE_ONESHOT:
+ __raw_writel(BM_TIMROT_ROTCTRL_SFTRST | BM_TIMROT_ROTCTRL_CLKGATE,
+ online_timer->base + HW_TIMROT_ROTCTRL_CLR);
+ __raw_writel(BF_TIMROT_TIMCTRLn_SELECT(online_timer->clk_sel) |
+ BM_TIMROT_TIMCTRLn_IRQ_EN |
+ BM_TIMROT_TIMCTRLn_MATCH_MODE,
+ online_timer->base + HW_TIMROT_TIMCTRLn(online_timer->id));
+ break;
+ default:
+ break;
+ }
+}
+
+static struct clock_event_device mxs_clockevent = {
+ .name = "mxs tick timer ",
+ .features = CLOCK_EVT_FEAT_ONESHOT,
+ .shift = 32,
+ .set_next_event = mxs_set_next_event,
+ .set_mode = mxs_set_mode,
+ .rating = 200,
+};
+
+static struct clocksource mxs_clocksource = {
+ .name = "mxs clock source",
+ .rating = 250,
+ .read = mxs_get_cycles,
+ .mask = CLOCKSOURCE_MASK(32),
+ .shift = 10,
+ .flags = CLOCK_SOURCE_IS_CONTINUOUS
+};
+
+static struct irqaction mxs_timer_irq = {
+ .name = "i.MX/mxs Timer Tick",
+ .flags = IRQF_DISABLED | IRQF_TIMER,
+ .handler = mxs_timer_handler,
+ .dev_id = &mxs_clockevent,
+};
+
+static int __init mxs_clocksource_init(struct clk *timer_clk)
+{
+ unsigned int c = clk_get_rate(timer_clk);
+
+ mxs_clocksource.mult = clocksource_hz2mult(c, mxs_clocksource.shift);
+ clocksource_register(&mxs_clocksource);
+ return 0;
+}
+
+static int __init mxs_clockevent_init(struct clk *timer_clk)
+{
+ unsigned int c = clk_get_rate(timer_clk);
+
+ mxs_clockevent.mult = div_sc(c, NSEC_PER_SEC, mxs_clockevent.shift);
+ mxs_clockevent.min_delta_ns = clockevent_delta2ns(0xF, &mxs_clockevent);
+ mxs_clockevent.max_delta_ns = clockevent_delta2ns(0xFFFFFFF0,
+ &mxs_clockevent);
+ mxs_clockevent.cpumask = cpumask_of(0);
+
+ clockevents_register_device(&mxs_clockevent);
+ return 0;
+}
+
+static irqreturn_t mxs_timer_handler(int irq, void *dev_id)
+{
+ struct clock_event_device *c = dev_id;
+ if (__raw_readl(online_timer->base +
+ HW_TIMROT_TIMCTRLn(online_timer->id)) &
+ BM_TIMROT_TIMCTRLn_IRQ) {
+ __raw_writel(BM_TIMROT_TIMCTRLn_IRQ,
+ online_timer->base +
+ HW_TIMROT_TIMCTRLn_CLR(online_timer->id));
+ c->event_handler(c);
+ }
+ return IRQ_HANDLED;
+}
+
+void mxs_timer_init(struct mxs_sys_timer *timer)
+{
+ if (!timer->base || !timer->clk || IS_ERR(timer->clk))
+ return;
+ if (online_timer)
+ return;
+ online_timer = timer;
+ clk_enable(online_timer->clk);
+ __raw_writel(BF_TIMROT_TIMCTRLn_SELECT(online_timer->clk_sel) |
+ BM_TIMROT_TIMCTRLn_IRQ_EN |
+ BM_TIMROT_TIMCTRLn_MATCH_MODE,
+ online_timer->base + HW_TIMROT_TIMCTRLn(online_timer->id));
+ mxs_clocksource_init(online_timer->clk);
+ mxs_clockevent_init(online_timer->clk);
+ setup_irq(online_timer->irq, &mxs_timer_irq);
+}
+
+
diff --git a/arch/arm/plat-mxs/timer-nomatch.c b/arch/arm/plat-mxs/timer-nomatch.c
new file mode 100644
index 000000000000..db8906192f16
--- /dev/null
+++ b/arch/arm/plat-mxs/timer-nomatch.c
@@ -0,0 +1,195 @@
+/*
+ * System timer for Freescale STMP37XX/STMP378X
+ *
+ * Embedded Alley Solutions, Inc <source@embeddedalley.com>
+ *
+ * Copyright 2009-2010 Freescale Semiconductor, Inc.
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/spinlock.h>
+#include <linux/clocksource.h>
+#include <linux/clockchips.h>
+#include <linux/io.h>
+#include <linux/clk.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+
+#include <asm/mach/time.h>
+#include <mach/hardware.h>
+#include <mach/device.h>
+#include <mach/regs-timrot.h>
+
+#ifndef HW_TIMROT_TIMCOUNTn
+#define HW_TIMROT_TIMCOUNTn HW_TIMROT_RUNNING_COUNTn
+#endif
+static struct mxs_sys_timer *online_timer;
+
+static irqreturn_t
+mxs_nomatch_timer_interrupt(int irq, void *dev_id)
+{
+ struct clock_event_device *c = dev_id;
+
+ /* timer 0 */
+ if (__raw_readl(online_timer->base + HW_TIMROT_TIMCTRLn(0)) &
+ BM_TIMROT_TIMCTRLn_IRQ) {
+
+ __raw_writel(BM_TIMROT_TIMCTRLn_IRQ,
+ online_timer->base + HW_TIMROT_TIMCTRLn_CLR(0));
+ c->event_handler(c);
+ }
+
+ /* timer 1 */
+ else if (__raw_readl(online_timer->base + HW_TIMROT_TIMCTRLn(1))
+ & BM_TIMROT_TIMCTRLn_IRQ) {
+ __raw_writel(BM_TIMROT_TIMCTRLn_IRQ,
+ online_timer->base + HW_TIMROT_TIMCTRLn_CLR(1));
+ __raw_writel(BM_TIMROT_TIMCTRLn_IRQ_EN,
+ online_timer->base + HW_TIMROT_TIMCTRLn_CLR(1));
+ __raw_writel(0xFFFF,
+ online_timer->base + HW_TIMROT_TIMCOUNTn(1));
+ }
+
+ return IRQ_HANDLED;
+}
+
+static cycle_t mxs_nomatch_clock_read(struct clocksource *cs)
+{
+ return ~((__raw_readl(online_timer->base + HW_TIMROT_TIMCOUNTn(1))
+ & 0xFFFF0000) >> 16);
+}
+
+static int
+mxs_nomatch_timrot_set_next_event(unsigned long delta,
+ struct clock_event_device *dev)
+{
+ /* reload the timer */
+ __raw_writel(delta, online_timer->base + HW_TIMROT_TIMCOUNTn(0));
+ return 0;
+}
+
+static void
+mxs_nomatch_timrot_set_mode(enum clock_event_mode mode,
+ struct clock_event_device *dev)
+{
+}
+
+static struct clock_event_device ckevt_timrot = {
+ .name = "timrot",
+ .features = CLOCK_EVT_FEAT_ONESHOT,
+ .shift = 32,
+ .set_next_event = mxs_nomatch_timrot_set_next_event,
+ .set_mode = mxs_nomatch_timrot_set_mode,
+};
+
+static struct clocksource cksrc_mxs_nomatch = {
+ .name = "mxs clock source",
+ .rating = 250,
+ .read = mxs_nomatch_clock_read,
+ .mask = CLOCKSOURCE_MASK(16),
+ .shift = 10,
+ .flags = CLOCK_SOURCE_IS_CONTINUOUS,
+};
+
+static struct irqaction mxs_nomatch_timer_irq = {
+ .name = "mxs_nomatch_timer",
+ .flags = IRQF_DISABLED | IRQF_TIMER,
+ .handler = mxs_nomatch_timer_interrupt,
+ .dev_id = &ckevt_timrot,
+};
+
+
+/*
+ * Set up timer interrupt, and return the current time in seconds.
+ */
+void mxs_nomatch_timer_init(struct mxs_sys_timer *timer)
+{
+
+ if (online_timer)
+ return;
+
+ online_timer = timer;
+
+ cksrc_mxs_nomatch.mult = clocksource_hz2mult(clk_get_rate(timer->clk),
+ cksrc_mxs_nomatch.shift);
+ ckevt_timrot.mult = div_sc(clk_get_rate(timer->clk), NSEC_PER_SEC,
+ ckevt_timrot.shift);
+ ckevt_timrot.min_delta_ns = clockevent_delta2ns(2, &ckevt_timrot);
+ ckevt_timrot.max_delta_ns = clockevent_delta2ns(0xFFF, &ckevt_timrot);
+ ckevt_timrot.cpumask = cpumask_of(0);
+
+ /* clear two timers */
+ __raw_writel(0, online_timer->base + HW_TIMROT_TIMCOUNTn(0));
+ __raw_writel(0, online_timer->base + HW_TIMROT_TIMCOUNTn(1));
+
+ /* configure them */
+ __raw_writel(
+ (8 << BP_TIMROT_TIMCTRLn_SELECT) | /* 32 kHz */
+ BM_TIMROT_TIMCTRLn_RELOAD |
+ BM_TIMROT_TIMCTRLn_UPDATE |
+ BM_TIMROT_TIMCTRLn_IRQ_EN,
+ online_timer->base + HW_TIMROT_TIMCTRLn(0));
+ __raw_writel(
+ (8 << BP_TIMROT_TIMCTRLn_SELECT) | /* 32 kHz */
+ BM_TIMROT_TIMCTRLn_RELOAD |
+ BM_TIMROT_TIMCTRLn_UPDATE |
+ BM_TIMROT_TIMCTRLn_IRQ_EN,
+ online_timer->base + HW_TIMROT_TIMCTRLn(1));
+
+ __raw_writel(clk_get_rate(timer->clk) / HZ - 1,
+ online_timer->base + HW_TIMROT_TIMCOUNTn(0));
+ __raw_writel(0xFFFF, online_timer->base + HW_TIMROT_TIMCOUNTn(1));
+
+ setup_irq(IRQ_TIMER0, &mxs_nomatch_timer_irq);
+
+ clocksource_register(&cksrc_mxs_nomatch);
+ clockevents_register_device(&ckevt_timrot);
+}
+
+#ifdef CONFIG_PM
+
+void mxs_nomatch_suspend_timer(void)
+{
+ __raw_writel(BM_TIMROT_TIMCTRLn_IRQ_EN | BM_TIMROT_TIMCTRLn_IRQ,
+ online_timer->base + HW_TIMROT_TIMCTRLn_CLR(0));
+ __raw_writel(BM_TIMROT_ROTCTRL_CLKGATE,
+ online_timer->base + HW_TIMROT_ROTCTRL_SET);
+}
+
+void mxs_nomatch_resume_timer(void)
+{
+ __raw_writel(BM_TIMROT_ROTCTRL_SFTRST | BM_TIMROT_ROTCTRL_CLKGATE,
+ online_timer->base + HW_TIMROT_ROTCTRL_CLR);
+ __raw_writel(
+ 8 << BP_TIMROT_TIMCTRLn_SELECT | /* 32 kHz */
+ BM_TIMROT_TIMCTRLn_RELOAD |
+ BM_TIMROT_TIMCTRLn_UPDATE |
+ BM_TIMROT_TIMCTRLn_IRQ_EN,
+ online_timer->base + HW_TIMROT_TIMCTRLn(0));
+ __raw_writel(
+ 8 << BP_TIMROT_TIMCTRLn_SELECT | /* 32 kHz */
+ BM_TIMROT_TIMCTRLn_RELOAD |
+ BM_TIMROT_TIMCTRLn_UPDATE |
+ BM_TIMROT_TIMCTRLn_IRQ_EN,
+ online_timer->base + HW_TIMROT_TIMCTRLn(1));
+ __raw_writel(clk_get_rate(online_timer->clk) / HZ - 1,
+ online_timer->base + HW_TIMROT_TIMCOUNTn(0));
+ __raw_writel(0xFFFF, online_timer->base + HW_TIMROT_TIMCOUNTn(1));
+}
+
+#else
+
+#define mxs_nomatch_suspend_timer NULL
+#define mxs_nomatch_resume_timer NULL
+
+#endif /* CONFIG_PM */
diff --git a/arch/arm/plat-mxs/unique-id.c b/arch/arm/plat-mxs/unique-id.c
new file mode 100644
index 000000000000..adb8286230cc
--- /dev/null
+++ b/arch/arm/plat-mxs/unique-id.c
@@ -0,0 +1,199 @@
+/*
+ * Unique ID manipulation sysfs access generic functions
+ *
+ * Author: dmitry pervushin <dimka@embeddedalley.com>
+ *
+ * Copyright 2008-2010 Freescale Semiconductor, Inc.
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+#include <linux/kobject.h>
+#include <linux/string.h>
+#include <linux/sysfs.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/list.h>
+#include <linux/err.h>
+#include <linux/timer.h>
+#include <linux/spinlock.h>
+#include <linux/slab.h>
+
+#include <mach/unique-id.h>
+
+static int unlock;
+static spinlock_t u_lock;
+static const unsigned long UID_AUTOLOCK_TIMEOUT = HZ * 60 * 3;
+static struct timer_list u_timer;
+
+static void uid_timer_autolock(unsigned long param)
+{
+ struct timer_list *tmr = (struct timer_list *)param;
+
+ if (spin_trylock(&u_lock)) {
+ if (unlock)
+ pr_debug("%s: locked down.\n", __func__);
+ unlock = 0;
+ spin_unlock(&u_lock);
+ }
+ mod_timer(tmr, jiffies + UID_AUTOLOCK_TIMEOUT);
+}
+
+static LIST_HEAD(uid_provider_list);
+
+struct uid_provider {
+ struct kobject *kobj;
+ struct list_head list;
+ struct uid_ops *ops;
+ void *context;
+};
+
+static struct uid_provider *uid_provider_find(const char *name);
+
+#define UID_FWD_SYSFS_FILE(var, file, param) \
+ static ssize_t var##_show(struct kobject *kobj, \
+ struct kobj_attribute *attr, char *buf) \
+ { \
+ struct uid_provider *p = \
+ uid_provider_find(kobject_name(kobj)); \
+ ssize_t r; \
+ BUG_ON(p == NULL); \
+ r = (p->ops && p->ops->file##_show) ? \
+ p->ops->file##_show(p->context, buf, param) : 0;\
+ return r; \
+ } \
+ \
+ static ssize_t var##_store(struct kobject *kobj, \
+ struct kobj_attribute *attr, const char *buf, \
+ size_t count) \
+ { \
+ struct uid_provider *p = \
+ uid_provider_find(kobject_name(kobj)); \
+ ssize_t r; \
+ int ul; \
+ BUG_ON(p == NULL); \
+ spin_lock(&u_lock); \
+ ul = unlock; \
+ spin_unlock(&u_lock); \
+ if (ul) \
+ r = (p->ops && p->ops->file##_store) ? \
+ p->ops->file##_store(p->context, buf, count, param) \
+ : count; \
+ else \
+ r = -EACCES; \
+ return r; \
+ }
+
+struct kobject *uid_kobj;
+
+#define UID_ATTR(_name, _varname) \
+ static struct kobj_attribute _varname##_attr = \
+ __ATTR(_name, 0644, _varname##_show, _varname##_store)
+
+UID_FWD_SYSFS_FILE(id, id, 1);
+UID_FWD_SYSFS_FILE(id_bin, id, 0);
+UID_ATTR(id, id);
+UID_ATTR(id.bin, id_bin);
+
+static struct attribute *uid_attrs[] = {
+ &id_attr.attr,
+ &id_bin_attr.attr,
+ NULL
+};
+
+static struct attribute_group uid_attr_group = {
+ .attrs = uid_attrs,
+};
+
+struct kobject *uid_provider_init(const char *name,
+ struct uid_ops *ops, void *context)
+{
+ struct uid_provider *new;
+ int err;
+
+ new = kzalloc(sizeof(*new), GFP_KERNEL);
+ if (!new) {
+ err = -ENOMEM;
+ goto out;
+ }
+
+ new->kobj = kobject_create_and_add(name, uid_kobj);
+ if (!new->kobj) {
+ err = -ENOMEM;
+ goto out;
+ }
+ new->ops = ops;
+ new->context = context;
+
+ err = sysfs_create_group(new->kobj, &uid_attr_group);
+ if (err)
+ goto out2;
+
+ list_add_tail(&new->list, &uid_provider_list);
+ return new->kobj;
+out2:
+ kobject_del(new->kobj);
+out:
+ kfree(new);
+ return ERR_PTR(err);
+}
+EXPORT_SYMBOL_GPL(uid_provider_init);
+
+static struct uid_provider *uid_provider_find(const char *name)
+{
+ struct uid_provider *p;
+
+ list_for_each_entry(p, &uid_provider_list, list) {
+ if (strcmp(kobject_name(p->kobj), name) == 0)
+ return p;
+ }
+ return NULL;
+}
+
+void uid_provider_remove(const char *name)
+{
+ struct uid_provider *p;
+
+ p = uid_provider_find(name);
+ if (!p)
+ return;
+ kobject_del(p->kobj);
+ list_del(&p->list);
+ kfree(p);
+}
+EXPORT_SYMBOL_GPL(uid_provider_remove);
+
+static int uid_sysfs_init(void)
+{
+ int error;
+
+ uid_kobj = kobject_create_and_add("uid", NULL);
+ if (!uid_kobj) {
+ error = -ENOMEM;
+ goto out1;
+ }
+
+ spin_lock_init(&u_lock);
+ setup_timer(&u_timer, uid_timer_autolock, (unsigned long)&u_timer);
+
+ /* try to lock each 3 minutes */
+ mod_timer(&u_timer, jiffies + UID_AUTOLOCK_TIMEOUT);
+ return 0;
+
+out1:
+ printk(KERN_ERR"%s failed, error %d.", __func__, error);
+ return error;
+}
+
+module_param(unlock, int, 0600)
+core_initcall(uid_sysfs_init);
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("dmitry pervushin <dimka@embeddedalley.com>");
+MODULE_DESCRIPTION("Unique ID simple framework");
diff --git a/arch/arm/plat-mxs/usb_common.c b/arch/arm/plat-mxs/usb_common.c
new file mode 100644
index 000000000000..16ef4736b4d0
--- /dev/null
+++ b/arch/arm/plat-mxs/usb_common.c
@@ -0,0 +1,426 @@
+/*
+ * Copyright (C) 2009-2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+/*!
+ *@defgroup USB ARC OTG USB Driver
+ */
+
+/*!
+ * @file usb_common.c
+ *
+ * @brief platform related part of usb driver.
+ * @ingroup USB
+ */
+
+/*!
+ *Include files
+ */
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/fsl_devices.h>
+#include <linux/usb/otg.h>
+#include <linux/usb/fsl_xcvr.h>
+#include <mach/arc_otg.h>
+#include <mach/hardware.h>
+#include <linux/io.h>
+#define MXC_NUMBER_USB_TRANSCEIVER 6
+struct fsl_xcvr_ops *g_xc_ops[MXC_NUMBER_USB_TRANSCEIVER] = { NULL };
+
+void fsl_usb_xcvr_register(struct fsl_xcvr_ops *xcvr_ops)
+{
+ int i;
+
+ pr_debug("%s\n", __func__);
+ for (i = 0; i < MXC_NUMBER_USB_TRANSCEIVER; i++) {
+ if (g_xc_ops[i] == NULL) {
+ g_xc_ops[i] = xcvr_ops;
+ return;
+ }
+ }
+
+ pr_debug("Failed %s\n", __func__);
+}
+EXPORT_SYMBOL(fsl_usb_xcvr_register);
+
+void fsl_usb_xcvr_unregister(struct fsl_xcvr_ops *xcvr_ops)
+{
+ int i;
+
+ pr_debug("%s\n", __func__);
+ for (i = 0; i < MXC_NUMBER_USB_TRANSCEIVER; i++) {
+ if (g_xc_ops[i] == xcvr_ops) {
+ g_xc_ops[i] = NULL;
+ return;
+ }
+ }
+
+ pr_debug("Failed %s\n", __func__);
+}
+EXPORT_SYMBOL(fsl_usb_xcvr_unregister);
+
+void fsl_platform_set_test_mode(
+ struct fsl_usb2_platform_data *pdata,
+ enum usb_test_mode mode)
+{
+}
+EXPORT_SYMBOL(fsl_platform_set_test_mode);
+
+/* enable/disable high-speed disconnect detector of phy ctrl */
+void fsl_platform_set_usb_phy_dis(struct fsl_usb2_platform_data *pdata,
+ bool enable)
+{
+ if (enable)
+ __raw_writel(BM_USBPHY_CTRL_ENHOSTDISCONDETECT,
+ IO_ADDRESS(pdata->phy_regs) + HW_USBPHY_CTRL_SET);
+ else
+ __raw_writel(BM_USBPHY_CTRL_ENHOSTDISCONDETECT,
+ IO_ADDRESS(pdata->phy_regs) + HW_USBPHY_CTRL_CLR);
+}
+EXPORT_SYMBOL(fsl_platform_set_usb_phy_dis);
+
+
+#if defined(CONFIG_USB_OTG)
+static struct resource *otg_resources;
+
+struct resource *otg_get_resources(void)
+{
+ pr_debug("otg_get_resources\n");
+ return otg_resources;
+}
+EXPORT_SYMBOL(otg_get_resources);
+
+int otg_set_resources(struct resource *resources)
+{
+ otg_resources = resources;
+ return 0;
+}
+EXPORT_SYMBOL(otg_set_resources);
+#endif
+
+/*!
+ * Register remote wakeup by this usb controller
+ *
+ * @param pdev: platform_device for this usb controller
+ *
+ * @return 0 or negative error code in case not supportted.
+ */
+static int usb_register_remote_wakeup(struct platform_device *pdev)
+{
+ struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data;
+ struct resource *res;
+ int irq;
+
+ pr_debug("%s: pdev=0x%p \n", __func__, pdev);
+ if (!(pdata->wake_up_enable))
+ return -ECANCELED;
+
+ res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+ if (!res) {
+ dev_err(&pdev->dev,
+ "Found HC with no IRQ. Check %s setup!\n",
+ dev_name(&pdev->dev));
+ return -ENODEV;
+ }
+ irq = res->start;
+ pdev->dev.power.can_wakeup = 1;
+ enable_irq_wake(irq);
+
+ return 0;
+}
+
+static struct fsl_xcvr_ops *fsl_usb_get_xcvr(char *name)
+{
+ int i;
+
+ pr_debug("%s\n", __func__);
+ if (name == NULL) {
+ printk(KERN_ERR "get_xcvr(): No tranceiver name\n");
+ return NULL;
+ }
+
+ for (i = 0; i < MXC_NUMBER_USB_TRANSCEIVER; i++) {
+ if (strcmp(g_xc_ops[i]->name, name) == 0)
+ return g_xc_ops[i];
+ }
+ pr_debug("Failed %s\n", __func__);
+ return NULL;
+}
+
+/* The dmamask must be set for EHCI to work */
+static u64 ehci_dmamask = ~(u32) 0;
+
+static int instance_id = ~(u32) 0;
+struct platform_device *host_pdev_register(struct resource *res, int n_res,
+ struct fsl_usb2_platform_data
+ *config)
+{
+ struct platform_device *pdev;
+ int rc;
+
+ pr_debug("register host res=0x%p, size=%d\n", res, n_res);
+
+ pdev = platform_device_register_simple("fsl-ehci",
+ instance_id, res, n_res);
+ if (IS_ERR(pdev)) {
+ pr_debug("can't register %s Host, %ld\n",
+ config->name, PTR_ERR(pdev));
+ return NULL;
+ }
+
+ pdev->dev.coherent_dma_mask = 0xffffffff;
+ pdev->dev.dma_mask = &ehci_dmamask;
+
+ /*
+ * platform_device_add_data() makes a copy of
+ * the platform_data passed in. That makes it
+ * impossible to share the same config struct for
+ * all OTG devices (host,gadget,otg). So, just
+ * set the platorm_data pointer ourselves.
+ */
+ rc = platform_device_add_data(pdev, config,
+ sizeof(struct fsl_usb2_platform_data));
+ if (rc) {
+ platform_device_unregister(pdev);
+ return NULL;
+ }
+
+ pr_debug(KERN_INFO "usb: %s host (%s) registered\n", config->name,
+ config->transceiver);
+ pr_debug("pdev=0x%p dev=0x%p resources=0x%p pdata=0x%p\n",
+ pdev, &pdev->dev, pdev->resource, pdev->dev.platform_data);
+
+ instance_id++;
+
+ return pdev;
+}
+
+int usb_phy_enable(struct fsl_usb2_platform_data *pdata)
+{
+ u32 tmp;
+ void __iomem *phy_reg = IO_ADDRESS(pdata->phy_regs);
+ void __iomem *usb_reg = pdata->regs;
+ void __iomem *usbcmd, *phy_ctrl, *portsc;
+
+ /* Reset USB IP */
+ usbcmd = usb_reg + UOG_USBCMD;
+ tmp = __raw_readl(usbcmd); /* usb command */
+ tmp &= ~UCMD_RUN_STOP;
+ __raw_writel(tmp, usbcmd);
+ while (__raw_readl(usbcmd) & UCMD_RUN_STOP)
+ ;
+
+ tmp |= UCMD_RESET;
+ __raw_writel(tmp, usbcmd);
+ while (__raw_readl(usbcmd) & UCMD_RESET)
+ ;
+ mdelay(10);
+
+ /* Reset USBPHY module */
+ phy_ctrl = phy_reg + HW_USBPHY_CTRL;
+ tmp = __raw_readl(phy_ctrl);
+ tmp |= BM_USBPHY_CTRL_SFTRST;
+ __raw_writel(tmp, phy_ctrl);
+ udelay(10);
+
+ /* Remove CLKGATE and SFTRST */
+ tmp = __raw_readl(phy_ctrl);
+ tmp &= ~(BM_USBPHY_CTRL_CLKGATE | BM_USBPHY_CTRL_SFTRST);
+ __raw_writel(tmp, phy_ctrl);
+ udelay(10);
+
+ /* set UTMI xcvr */
+ /* Workaround an IC issue for ehci driver:
+ * when turn off root hub port power, EHCI set
+ * PORTSC reserved bits to be 0, but PTW with 0
+ * means 8 bits tranceiver width, here change
+ * it back to be 16 bits and do PHY diable and
+ * then enable.
+ */
+ portsc = usb_reg + UOG_PORTSC1;
+ tmp = __raw_readl(portsc);
+ tmp &= ~PORTSC_PTS_MASK;
+ tmp |= (PORTSC_PTS_UTMI | PORTSC_PTW);
+ __raw_writel(tmp, portsc);
+
+ /* Power up the PHY */
+ __raw_writel(0, phy_reg + HW_USBPHY_PWD);
+
+ return 0;
+}
+EXPORT_SYMBOL(usb_phy_enable);
+
+static int otg_used;
+
+int usbotg_init(struct platform_device *pdev)
+{
+ struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data;
+ struct fsl_xcvr_ops *xops;
+
+ pr_debug("%s: pdev=0x%p pdata=0x%p\n", __func__, pdev, pdata);
+
+ xops = fsl_usb_get_xcvr(pdata->transceiver);
+ if (!xops) {
+ printk(KERN_ERR "DR transceiver ops missing\n");
+ return -EINVAL;
+ }
+ pdata->xcvr_ops = xops;
+ pdata->xcvr_type = xops->xcvr_type;
+ pdata->pdev = pdev;
+
+ if (!otg_used) {
+ pr_debug("%s: grab pins\n", __func__);
+ if (xops->init)
+ xops->init(xops);
+ usb_phy_enable(pdata);
+ }
+
+ if ((pdata->operating_mode == FSL_USB2_DR_HOST) ||
+ (pdata->operating_mode == FSL_USB2_DR_OTG)) {
+ /* enable FS/LS device */
+ __raw_writel(BM_USBPHY_CTRL_ENUTMILEVEL2 | BM_USBPHY_CTRL_ENUTMILEVEL3
+ , IO_ADDRESS(pdata->phy_regs) + HW_USBPHY_CTRL_SET);
+ }
+
+ if (usb_register_remote_wakeup(pdev))
+ pr_debug("%s port is not a wakeup source.\n", pdata->name);
+
+ otg_used++;
+ pr_debug("%s: success\n", __func__);
+ return 0;
+}
+EXPORT_SYMBOL(usbotg_init);
+
+void usbotg_uninit(struct fsl_usb2_platform_data *pdata)
+{
+ pr_debug("%s\n", __func__);
+
+ if (pdata->xcvr_ops && pdata->xcvr_ops->uninit)
+ pdata->xcvr_ops->uninit(pdata->xcvr_ops);
+
+ pdata->regs = NULL;
+ otg_used--;
+}
+EXPORT_SYMBOL(usbotg_uninit);
+
+int fsl_usb_host_init(struct platform_device *pdev)
+{
+ struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data;
+ struct fsl_xcvr_ops *xops;
+ u32 tmp;
+ void __iomem *phy_reg = IO_ADDRESS(pdata->phy_regs);
+
+ pr_debug("%s: pdev=0x%p pdata=0x%p\n", __func__, pdev, pdata);
+
+ xops = fsl_usb_get_xcvr(pdata->transceiver);
+ if (!xops) {
+ printk(KERN_ERR "%s transceiver ops missing\n", pdata->name);
+ return -EINVAL;
+ }
+ pdata->xcvr_ops = xops;
+ pdata->xcvr_type = xops->xcvr_type;
+ pdata->pdev = pdev;
+
+ if (xops->init)
+ xops->init(xops);
+ usb_phy_enable(pdata);
+ /* enable FS/LS device */
+ tmp = __raw_readl(phy_reg + HW_USBPHY_CTRL);
+ tmp |= (BM_USBPHY_CTRL_ENUTMILEVEL2 | BM_USBPHY_CTRL_ENUTMILEVEL3);
+ __raw_writel(tmp, phy_reg + HW_USBPHY_CTRL);
+
+ if (usb_register_remote_wakeup(pdev))
+ pr_debug("%s port is not a wakeup source.\n", pdata->name);
+
+ pr_debug("%s: %s success\n", __func__, pdata->name);
+ return 0;
+}
+EXPORT_SYMBOL(fsl_usb_host_init);
+
+void fsl_usb_host_uninit(struct fsl_usb2_platform_data *pdata)
+{
+ pr_debug("%s\n", __func__);
+
+ if (pdata->xcvr_ops && pdata->xcvr_ops->uninit)
+ pdata->xcvr_ops->uninit(pdata->xcvr_ops);
+
+ pdata->regs = NULL;
+}
+EXPORT_SYMBOL(fsl_usb_host_uninit);
+
+/*
+ * This function is used to debounce the reading value for id/vbus at
+ * the register of otgsc
+ */
+void usb_debounce_id_vbus(void)
+{
+ mdelay(3);
+}
+EXPORT_SYMBOL(usb_debounce_id_vbus);
+
+int usb_host_wakeup_irq(struct device *wkup_dev)
+{
+ return 0;
+}
+EXPORT_SYMBOL(usb_host_wakeup_irq);
+
+void usb_host_set_wakeup(struct device *wkup_dev, bool para)
+{
+ struct fsl_usb2_platform_data *pdata = wkup_dev->platform_data;
+ if (pdata->wake_up_enable)
+ pdata->wake_up_enable(pdata, para);
+}
+EXPORT_SYMBOL(usb_host_set_wakeup);
+
+#ifdef CONFIG_ARCH_MX28
+#define USBPHY_PHYS_ADDR USBPHY0_PHYS_ADDR
+#endif
+
+int usb_event_is_otg_wakeup(void)
+{
+ u32 wakeup_irq_bits;
+ wakeup_irq_bits = BM_USBPHY_CTRL_RESUME_IRQ | BM_USBPHY_CTRL_WAKEUP_IRQ;
+
+ if (__raw_readl(IO_ADDRESS(USBPHY_PHYS_ADDR) + HW_USBPHY_STATUS) && wakeup_irq_bits) {
+ return true;
+ }
+ return false;
+}
+EXPORT_SYMBOL(usb_event_is_otg_wakeup);
+
+int fsl_is_usb_plugged(void)
+{
+ return __raw_readl(IO_ADDRESS(USBPHY_PHYS_ADDR) + HW_USBPHY_STATUS) & \
+ BM_USBPHY_STATUS_DEVPLUGIN_STATUS;
+}
+EXPORT_SYMBOL(fsl_is_usb_plugged);
+
+void fsl_enable_usb_plugindetect(void)
+{
+ __raw_writel(BM_USBPHY_CTRL_ENDEVPLUGINDETECT,
+ IO_ADDRESS(USBPHY_PHYS_ADDR) + HW_USBPHY_CTRL_SET);
+}
+EXPORT_SYMBOL(fsl_enable_usb_plugindetect);
+
diff --git a/arch/arm/plat-mxs/usb_wakeup.c b/arch/arm/plat-mxs/usb_wakeup.c
new file mode 100644
index 000000000000..a020e85445f1
--- /dev/null
+++ b/arch/arm/plat-mxs/usb_wakeup.c
@@ -0,0 +1,222 @@
+/*
+ * Copyright 2009-2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ * *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+*/
+
+#include <linux/sched.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/slab.h>
+#include <linux/kthread.h>
+#include <linux/platform_device.h>
+#include <linux/mutex.h>
+#include <linux/fsl_devices.h>
+#include <linux/suspend.h>
+#include <linux/io.h>
+#include <mach/arc_otg.h>
+
+struct wakeup_ctrl {
+ int wakeup_irq;
+ int usb_irq;
+ struct fsl_usb2_wakeup_platform_data *pdata;
+ struct task_struct *thread;
+ struct completion event;
+};
+static struct wakeup_ctrl *g_ctrl;
+
+extern int usb_event_is_otg_wakeup(void);
+extern void usb_debounce_id_vbus(void);
+
+static void wakeup_clk_gate(struct fsl_usb2_wakeup_platform_data *pdata, bool on)
+{
+ if (pdata->usb_clock_for_pm)
+ pdata->usb_clock_for_pm(on);
+}
+
+static bool usb2_is_in_lowpower(struct wakeup_ctrl *ctrl)
+{
+ int i;
+ struct fsl_usb2_wakeup_platform_data *pdata = ctrl->pdata;
+ /* all the usb module related the wakeup is in lowpower mode */
+ for (i = 0; i < 3; i++) {
+ if (pdata->usb_pdata[i]) {
+ if (pdata->usb_pdata[i]->phy_lowpower_suspend && !pdata->usb_pdata[i]->lowpower)
+ return false;
+ }
+ }
+
+ return true;
+}
+
+static void delay_process_wakeup(struct wakeup_ctrl *ctrl)
+{
+ struct fsl_usb2_wakeup_platform_data *pdata = ctrl->pdata;
+ disable_irq_nosync(ctrl->wakeup_irq);
+ if ((ctrl->usb_irq > 0) && (ctrl->wakeup_irq != ctrl->usb_irq))
+ disable_irq_nosync(ctrl->usb_irq);
+
+ pdata->usb_wakeup_is_pending = true;
+ complete(&ctrl->event);
+}
+
+static irqreturn_t usb_wakeup_handler(int irq, void *_dev)
+{
+ struct wakeup_ctrl *ctrl = (struct wakeup_ctrl *)_dev;
+ irqreturn_t ret = IRQ_NONE;
+ if (usb2_is_in_lowpower(ctrl)) {
+ pr_debug("usb wakeup is here\n");
+ delay_process_wakeup(ctrl);
+ ret = IRQ_HANDLED;
+ }
+ return ret;
+}
+
+static enum usb_wakeup_event is_wakeup(struct fsl_usb2_platform_data *pdata)
+{
+ if (pdata->is_wakeup_event)
+ return pdata->is_wakeup_event(pdata);
+ else
+ return WAKEUP_EVENT_INVALID;
+}
+
+static void wakeup_event_handler(struct wakeup_ctrl *ctrl)
+{
+ struct fsl_usb2_wakeup_platform_data *pdata = ctrl->pdata;
+ int already_waked = 0;
+ enum usb_wakeup_event wakeup_evt;
+ int i;
+
+ wakeup_clk_gate(ctrl->pdata, true);
+
+ /* In order to get the real id/vbus value */
+ if (usb_event_is_otg_wakeup())
+ usb_debounce_id_vbus();
+
+ for (i = 0; i < 3; i++) {
+ struct fsl_usb2_platform_data *usb_pdata = pdata->usb_pdata[i];
+ if (usb_pdata) {
+ wakeup_evt = is_wakeup(usb_pdata);
+ if (wakeup_evt != WAKEUP_EVENT_INVALID) {
+ if (usb2_is_in_lowpower(ctrl))
+ if (usb_pdata->usb_clock_for_pm)
+ usb_pdata->usb_clock_for_pm(true);
+ usb_pdata->lowpower = 0;
+ already_waked = 1;
+ if (usb_pdata->wakeup_handler) {
+ usb_pdata->wakeup_handler(usb_pdata);
+ }
+ }
+ }
+ }
+
+ /* If nothing to wakeup, clear wakeup event */
+ if ((already_waked == 0) && pdata->usb_wakeup_exhandle)
+ pdata->usb_wakeup_exhandle();
+
+ wakeup_clk_gate(ctrl->pdata, false);
+ pdata->usb_wakeup_is_pending = false;
+ wake_up(&pdata->wq);
+}
+
+static int wakeup_event_thread(void *param)
+{
+ struct wakeup_ctrl *ctrl = (struct wakeup_ctrl *)param;
+ struct sched_param sch_param = {.sched_priority = 1};
+
+ sched_setscheduler(current, SCHED_RR, &sch_param);
+ while (1) {
+ wait_for_completion_interruptible(&ctrl->event);
+ if (kthread_should_stop())
+ break;
+ wakeup_event_handler(ctrl);
+ enable_irq(ctrl->wakeup_irq);
+ if ((ctrl->usb_irq > 0) && (ctrl->wakeup_irq != ctrl->usb_irq))
+ enable_irq(ctrl->usb_irq);
+ }
+ return 0;
+}
+
+static int wakeup_dev_probe(struct platform_device *pdev)
+{
+ struct fsl_usb2_wakeup_platform_data *pdata;
+ struct wakeup_ctrl *ctrl = NULL;
+ int status;
+ unsigned long interrupt_flag;
+
+ printk(KERN_INFO "IMX usb wakeup probe\n");
+
+ if (!pdev || !pdev->dev.platform_data)
+ return -ENODEV;
+ ctrl = kzalloc(sizeof(*ctrl), GFP_KERNEL);
+ if (!ctrl)
+ return -ENOMEM;
+ pdata = pdev->dev.platform_data;
+ ctrl->pdata = pdata;
+ init_waitqueue_head(&pdata->wq);
+ pdata->usb_wakeup_is_pending = false;
+
+ init_completion(&ctrl->event);
+ ctrl->wakeup_irq = platform_get_irq(pdev, 0);
+ ctrl->usb_irq = platform_get_irq(pdev, 1);
+ if (ctrl->wakeup_irq != ctrl->wakeup_irq)
+ interrupt_flag = IRQF_DISABLED;
+ else
+ interrupt_flag = IRQF_SHARED;
+ status = request_irq(ctrl->wakeup_irq, usb_wakeup_handler, interrupt_flag, "usb_wakeup", (void *)ctrl);
+ if (status)
+ goto error1;
+
+ ctrl->thread = kthread_run(wakeup_event_thread, (void *)ctrl, "usb_wakeup thread");
+ status = IS_ERR(ctrl->thread) ? -1 : 0;
+ if (status)
+ goto error2;
+ g_ctrl = ctrl;
+
+ printk(KERN_DEBUG "the wakeup pdata is 0x%p\n", pdata);
+ return 0;
+error2:
+ free_irq(ctrl->wakeup_irq, (void *)ctrl);
+error1:
+ kfree(ctrl);
+ return status;
+}
+
+static int wakeup_dev_exit(struct platform_device *pdev)
+{
+ if (g_ctrl->thread) {
+ complete(&g_ctrl->event);
+ kthread_stop(g_ctrl->thread);
+ }
+ free_irq(g_ctrl->wakeup_irq, (void *)g_ctrl);
+ kfree(g_ctrl);
+ return 0;
+}
+static struct platform_driver wakeup_d = {
+ .probe = wakeup_dev_probe,
+ .remove = wakeup_dev_exit,
+ .driver = {
+ .name = "usb_wakeup",
+ },
+};
+
+static int __init wakeup_dev_init(void)
+{
+ return platform_driver_register(&wakeup_d);
+}
+static void __exit wakeup_dev_uninit(void)
+{
+ platform_driver_unregister(&wakeup_d);
+}
+
+subsys_initcall(wakeup_dev_init);
+module_exit(wakeup_dev_uninit);
+
diff --git a/arch/arm/plat-mxs/utmixc.c b/arch/arm/plat-mxs/utmixc.c
new file mode 100644
index 000000000000..8e842840e87a
--- /dev/null
+++ b/arch/arm/plat-mxs/utmixc.c
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2009-2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/device.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/fsl_devices.h>
+#include <linux/usb/fsl_xcvr.h>
+#include <linux/pmic_external.h>
+
+#include <mach/hardware.h>
+#include <mach/arc_otg.h>
+#include <asm/mach-types.h>
+
+extern void fsl_phy_usb_utmi_init(struct fsl_xcvr_ops *this);
+extern void fsl_phy_usb_utmi_uninit(struct fsl_xcvr_ops *this);
+extern void fsl_phy_set_power(struct fsl_xcvr_ops *this,
+ struct fsl_usb2_platform_data *pdata, int on);
+#include <mach/regs-power.h>
+#include <asm/io.h>
+
+
+static void set_vbus_draw(struct fsl_xcvr_ops *this,
+ struct fsl_usb2_platform_data *pdata, unsigned mA)
+{
+#ifdef CONFIG_MXS_VBUS_CURRENT_DRAW
+ if ((__raw_readl(REGS_POWER_BASE + HW_POWER_5VCTRL)
+ & BM_POWER_5VCTRL_CHARGE_4P2_ILIMIT) == 0x20000) {
+ printk(KERN_INFO "USB enumeration done,current limitation release\r\n");
+ __raw_writel(__raw_readl(REGS_POWER_BASE + HW_POWER_5VCTRL) |
+ BM_POWER_5VCTRL_CHARGE_4P2_ILIMIT, REGS_POWER_BASE +
+ HW_POWER_5VCTRL);
+ }
+#endif
+}
+static struct fsl_xcvr_ops utmi_ops = {
+ .name = "utmi",
+ .xcvr_type = PORTSC_PTS_UTMI,
+ .init = fsl_phy_usb_utmi_init,
+ .uninit = fsl_phy_usb_utmi_uninit,
+ .set_vbus_power = fsl_phy_set_power,
+ .set_vbus_draw = set_vbus_draw,
+};
+
+extern void fsl_usb_xcvr_register(struct fsl_xcvr_ops *xcvr_ops);
+
+static int __init utmixc_init(void)
+{
+ fsl_usb_xcvr_register(&utmi_ops);
+ return 0;
+}
+
+extern void fsl_usb_xcvr_unregister(struct fsl_xcvr_ops *xcvr_ops);
+
+static void __exit utmixc_exit(void)
+{
+ fsl_usb_xcvr_unregister(&utmi_ops);
+}
+
+#ifdef CONFIG_MXS_VBUS_CURRENT_DRAW
+ fs_initcall(utmixc_init);
+#else
+ subsys_initcall(utmixc_init);
+#endif
+module_exit(utmixc_exit);
+
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_DESCRIPTION("utmi xcvr driver");
+MODULE_LICENSE("GPL");