summaryrefslogtreecommitdiff
path: root/arch/arm/plat-mxc
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/plat-mxc')
-rw-r--r--arch/arm/plat-mxc/Kconfig127
-rw-r--r--arch/arm/plat-mxc/Makefile52
-rw-r--r--arch/arm/plat-mxc/clock.c335
-rw-r--r--arch/arm/plat-mxc/cpu_common.c84
-rw-r--r--arch/arm/plat-mxc/cpufreq.c347
-rw-r--r--arch/arm/plat-mxc/dma_mx2.c1316
-rw-r--r--arch/arm/plat-mxc/dptc.c621
-rw-r--r--arch/arm/plat-mxc/dvfs_core.c802
-rw-r--r--arch/arm/plat-mxc/entry-pm.S315
-rw-r--r--arch/arm/plat-mxc/gpio.c175
-rw-r--r--arch/arm/plat-mxc/include/mach/arc_otg.h343
-rw-r--r--arch/arm/plat-mxc/include/mach/audio_controls.h220
-rw-r--r--arch/arm/plat-mxc/include/mach/clock.h19
-rw-r--r--arch/arm/plat-mxc/include/mach/common.h12
-rw-r--r--arch/arm/plat-mxc/include/mach/dma.h293
-rw-r--r--arch/arm/plat-mxc/include/mach/dptc.h186
-rw-r--r--arch/arm/plat-mxc/include/mach/dvfs_dptc_struct.h169
-rw-r--r--arch/arm/plat-mxc/include/mach/entry-macro.S33
-rw-r--r--arch/arm/plat-mxc/include/mach/fsl_usb.h86
-rw-r--r--arch/arm/plat-mxc/include/mach/fsl_usb_gadget.h40
-rw-r--r--arch/arm/plat-mxc/include/mach/gpio.h3
-rw-r--r--arch/arm/plat-mxc/include/mach/hardware.h64
-rw-r--r--arch/arm/plat-mxc/include/mach/hw_events.h65
-rw-r--r--arch/arm/plat-mxc/include/mach/io.h42
-rw-r--r--arch/arm/plat-mxc/include/mach/irqs.h34
-rw-r--r--arch/arm/plat-mxc/include/mach/memory.h49
-rw-r--r--arch/arm/plat-mxc/include/mach/mmc.h17
-rw-r--r--arch/arm/plat-mxc/include/mach/mtd-xip.h30
-rw-r--r--arch/arm/plat-mxc/include/mach/mx25.h462
-rw-r--r--arch/arm/plat-mxc/include/mach/mx2_dma.h261
-rw-r--r--arch/arm/plat-mxc/include/mach/mx31.h95
-rw-r--r--arch/arm/plat-mxc/include/mach/mx35.h127
-rw-r--r--arch/arm/plat-mxc/include/mach/mx37.h474
-rw-r--r--arch/arm/plat-mxc/include/mach/mx3x.h45
-rw-r--r--arch/arm/plat-mxc/include/mach/mx51.h511
-rw-r--r--arch/arm/plat-mxc/include/mach/mxc.h570
-rw-r--r--arch/arm/plat-mxc/include/mach/mxc_dptc.h111
-rw-r--r--arch/arm/plat-mxc/include/mach/mxc_dvfs.h51
-rw-r--r--arch/arm/plat-mxc/include/mach/mxc_edid.h33
-rw-r--r--arch/arm/plat-mxc/include/mach/mxc_gpc.h74
-rw-r--r--arch/arm/plat-mxc/include/mach/mxc_pm.h252
-rw-r--r--arch/arm/plat-mxc/include/mach/mxc_scc.h45
-rw-r--r--arch/arm/plat-mxc/include/mach/mxc_timer.h157
-rw-r--r--arch/arm/plat-mxc/include/mach/mxc_uart.h275
-rw-r--r--arch/arm/plat-mxc/include/mach/mxc_vpu.h94
-rw-r--r--arch/arm/plat-mxc/include/mach/pcmcia.h218
-rw-r--r--arch/arm/plat-mxc/include/mach/pmic_audio.h2315
-rw-r--r--arch/arm/plat-mxc/include/mach/pmic_convity.h873
-rw-r--r--arch/arm/plat-mxc/include/mach/pmic_power.h1358
-rw-r--r--arch/arm/plat-mxc/include/mach/sdma.h561
-rw-r--r--arch/arm/plat-mxc/include/mach/spba.h66
-rw-r--r--arch/arm/plat-mxc/include/mach/system.h7
-rw-r--r--arch/arm/plat-mxc/include/mach/timex.h8
-rw-r--r--arch/arm/plat-mxc/include/mach/uncompress.h2
-rw-r--r--arch/arm/plat-mxc/io.c41
-rw-r--r--arch/arm/plat-mxc/irq.c146
-rw-r--r--arch/arm/plat-mxc/isp1301xc.c290
-rw-r--r--arch/arm/plat-mxc/isp1504xc.c279
-rw-r--r--arch/arm/plat-mxc/leds.c111
-rw-r--r--arch/arm/plat-mxc/mc13783_xc.c299
-rw-r--r--arch/arm/plat-mxc/pwm.c26
-rw-r--r--arch/arm/plat-mxc/sdma/Makefile18
-rw-r--r--arch/arm/plat-mxc/sdma/dma_sdma.c697
-rw-r--r--arch/arm/plat-mxc/sdma/iapi/Makefile5
-rw-r--r--arch/arm/plat-mxc/sdma/iapi/include/epm.h187
-rw-r--r--arch/arm/plat-mxc/sdma/iapi/include/iapi.h49
-rw-r--r--arch/arm/plat-mxc/sdma/iapi/include/iapiDefaults.h128
-rw-r--r--arch/arm/plat-mxc/sdma/iapi/include/iapiHigh.h136
-rw-r--r--arch/arm/plat-mxc/sdma/iapi/include/iapiLow.h78
-rw-r--r--arch/arm/plat-mxc/sdma/iapi/include/iapiLowDsp.h50
-rw-r--r--arch/arm/plat-mxc/sdma/iapi/include/iapiLowMcu.h60
-rw-r--r--arch/arm/plat-mxc/sdma/iapi/include/iapiMiddle.h52
-rw-r--r--arch/arm/plat-mxc/sdma/iapi/include/iapiMiddleMcu.h41
-rw-r--r--arch/arm/plat-mxc/sdma/iapi/include/iapiOS.h96
-rw-r--r--arch/arm/plat-mxc/sdma/iapi/include/sdmaStruct.h426
-rw-r--r--arch/arm/plat-mxc/sdma/iapi/src/Makefile18
-rw-r--r--arch/arm/plat-mxc/sdma/iapi/src/iapiDefaults.c110
-rw-r--r--arch/arm/plat-mxc/sdma/iapi/src/iapiHigh.c2798
-rw-r--r--arch/arm/plat-mxc/sdma/iapi/src/iapiLow.c149
-rw-r--r--arch/arm/plat-mxc/sdma/iapi/src/iapiLowDsp.c79
-rw-r--r--arch/arm/plat-mxc/sdma/iapi/src/iapiLowMcu.c518
-rw-r--r--arch/arm/plat-mxc/sdma/iapi/src/iapiMiddle.c623
-rw-r--r--arch/arm/plat-mxc/sdma/iapi/src/iapiMiddleMcu.c52
-rw-r--r--arch/arm/plat-mxc/sdma/iapi/src/iapiOS.c64
-rw-r--r--arch/arm/plat-mxc/sdma/sdma.c1481
-rw-r--r--arch/arm/plat-mxc/sdma/sdma_malloc.c387
-rw-r--r--arch/arm/plat-mxc/serialxc.c64
-rw-r--r--arch/arm/plat-mxc/snoop.c133
-rw-r--r--arch/arm/plat-mxc/spba.c133
-rw-r--r--arch/arm/plat-mxc/time.c30
-rw-r--r--arch/arm/plat-mxc/tzic.c181
-rw-r--r--arch/arm/plat-mxc/usb_common.c860
-rw-r--r--arch/arm/plat-mxc/utmixc.c106
-rw-r--r--arch/arm/plat-mxc/wdog.c68
94 files changed, 25875 insertions, 118 deletions
diff --git a/arch/arm/plat-mxc/Kconfig b/arch/arm/plat-mxc/Kconfig
index 8986b7412235..e09407b66a5e 100644
--- a/arch/arm/plat-mxc/Kconfig
+++ b/arch/arm/plat-mxc/Kconfig
@@ -22,9 +22,30 @@ config ARCH_MX2
config ARCH_MX3
bool "MX3-based"
select CPU_V6
- select COMMON_CLKDEV
+# select COMMON_CLKDEV
+ help
+ This enables support for systems based on the Freescale i.MX31 and i.MX32
+
+config ARCH_MX25
+ bool "MX25-based"
+ select MX25_OPTIONS
+ help
+ This enables support for systems based on the Freescale i.MX25
+
+config ARCH_MX35
+ bool "MX35-based"
+ help
+ This enables support for systems based on Freescale i.MX35
+
+config ARCH_MX37
+ bool "MX37-based"
help
- This enables support for systems based on the Freescale i.MX3 family
+ This enables support for systems based on Freescale i.MX37
+
+config ARCH_MX51
+ bool "MX51-based"
+ help
+ This enables support for systems based on Freescale i.MX51
endchoice
@@ -32,8 +53,106 @@ source "arch/arm/mach-mx1/Kconfig"
source "arch/arm/mach-mx2/Kconfig"
source "arch/arm/mach-mx3/Kconfig"
+source "arch/arm/mach-mx25/Kconfig"
+source "arch/arm/mach-mx35/Kconfig"
+source "arch/arm/mach-mx37/Kconfig"
+source "arch/arm/mach-mx51/Kconfig"
+
endmenu
+config MXC_TZIC
+ bool
+ depends on ARCH_MXC
+
+config MXC_DSP_BRINGUP
+ bool
+ depends on ARCH_MXC
+
+config ARCH_HAS_EVTMON
+ bool
+ depends on ARCH_MXC
+
+config MXC_EMMA
+ bool
+ depends on ARCH_MXC
+
+config MXC_FB_IRAM
+ bool
+ depends on ARCH_MXC
+
+config DMA_ZONE_SIZE
+ int "DMA memory zone size"
+ range 0 64
+ default 24
+ help
+ This is the size in MB for the DMA zone. The DMA zone is used for
+ dedicated memory for large contiguous video buffers
+
+# set iff we need the 1504 transceiver code
+config ISP1504_MXC
+ bool
+ select ISP1504_MXC_OTG if USB_GADGET && USB_EHCI_HCD && USB_OTG
+ default y if USB_EHCI_FSL_1504 || USB_GADGET_FSL_1504
+
+config ISP1504_MXC_OTG
+ tristate
+ help
+ Support for USB OTG pin detect using the ISP1504 transceiver on MXC platforms.
+
+# set iff we need the UTMI transceiver code
+config UTMI_MXC
+ bool
+ select UTMI_MXC_OTG if ARCH_MX25 && USB_GADGET && USB_EHCI_HCD && USB_OTG
+ default y if USB_EHCI_FSL_UTMI || USB_GADGET_FSL_UTMI
+ depends on ARCH_MX25 || ARCH_MX35 || ARCH_MX37 || ARCH_MX51
+
+config UTMI_MXC_OTG
+ tristate
+ help
+ Support for USB OTG pin detect using the UTMI transceiver on MXC platforms.
+
+# set iff we need the 1301 transceiver code
+config ISP1301_MXC
+ bool
+ default y if USB_EHCI_FSL_1301 || USB_GADGET_FSL_1301
+ select I2C_MXC
+
+# set iff we need the mx13783 transceiver code
+config MC13783_MXC
+ bool
+ default y if USB_EHCI_FSL_MC13783 || USB_GADGET_FSL_MC13783
+ select SPI_MXC
+
+choice
+ prompt "Select serial USB transceiver mode"
+ depends on ISP1301_MXC || MC13783_MXC
+ default MXC_USB_SU6
+
+config MXC_USB_SU6
+ bool "Single Ended Unidirectional Mode"
+ help
+ If you say yes to this option, the serial tranceiver operates in SU6 mode.
+ This option will work for either the Freescale MC13783 or Philips ISP1301
+ transceiver.
+
+config MXC_USB_SB3
+ bool "Single Ended Bidirectional Mode"
+ help
+ If you say yes to this option, the serial tranceiver operates in SB3 mode.
+ Not recommended for the Freescale MC13783.
+
+config MXC_USB_DU6
+ bool "Differential Unidirectional Mode"
+ help
+ If you say yes to this option, the serial tranceiver operates in DU6 mode.
+
+config MXC_USB_DB4
+ bool "Differential Bidirectional Mode"
+ help
+ If you say yes to this option, the serial tranceiver operates in DB4 mode.
+
+endchoice
+
config MXC_IRQ_PRIOR
bool "Use IRQ priority"
depends on ARCH_MXC
@@ -56,6 +175,10 @@ config ARCH_HAS_RNGA
bool
depends on ARCH_MXC
+config ARCH_HAS_RNGC
+ bool
+ depends on ARCH_MXC
+
config ARCH_MXC_IOMUX_V3
bool
endif
diff --git a/arch/arm/plat-mxc/Makefile b/arch/arm/plat-mxc/Makefile
index e3212c8ff421..56da7aa5d278 100644
--- a/arch/arm/plat-mxc/Makefile
+++ b/arch/arm/plat-mxc/Makefile
@@ -3,9 +3,59 @@
#
# Common support
-obj-y := irq.o clock.o gpio.o time.o devices.o cpu.o system.o
+obj-y := cpu.o cpu_common.o gpio.o clock.o wdog.o snoop.o io.o time.o
obj-$(CONFIG_ARCH_MX1) += iomux-mx1-mx2.o dma-mx1-mx2.o
obj-$(CONFIG_ARCH_MX2) += iomux-mx1-mx2.o dma-mx1-mx2.o
obj-$(CONFIG_ARCH_MXC_IOMUX_V3) += iomux-v3.o
obj-$(CONFIG_MXC_PWM) += pwm.o
+
+ifneq ($(CONFIG_ARCH_MX27),y)
+obj-y += spba.o sdma/
+endif
+
+ifeq ($(CONFIG_MXC_TZIC),y)
+obj-y += tzic.o
+else
+obj-y += irq.o
+endif
+
+obj-$(CONFIG_ARCH_MX27) += dma_mx2.o usb_common.o
+obj-$(CONFIG_ARCH_MX3) += dptc.o usb_common.o entry-pm.o
+obj-$(CONFIG_ARCH_MX35) += usb_common.o serialxc.o
+obj-$(CONFIG_ARCH_MX37) += usb_common.o utmixc.o dptc.o dvfs_core.o
+obj-$(CONFIG_ARCH_MX51) += usb_common.o utmixc.o dvfs_core.o
+
+# LEDs support
+obj-$(CONFIG_LEDS) += leds.o
+
+# CPU FREQ support
+obj-$(CONFIG_CPU_FREQ_IMX) += cpufreq.o
+
+# USB support
+obj-$(CONFIG_ISP1504_MXC) += isp1504xc.o
+obj-$(CONFIG_ISP1301_MXC) += isp1301xc.o
+obj-$(CONFIG_MC13783_MXC) += mc13783_xc.o
+
+# obj-$(CONFIG_USB_EHCI_FSL_UTMI) += utmixc.o
+ifneq ($(strip $(CONFIG_USB_EHCI_FSL_UTMI) $(CONFIG_USB_GADGET_FSL_UTMI)),)
+obj-y += utmixc.o
+endif
+
+ifneq ($(CONFIG_USB_EHCI_ARC_H1)$(CONFIG_USB_EHCI_ARC_H2),)
+ifneq ($(CONFIG_ARCH_MX51),y)
+obj-y += serialxc.o
+else
+obj-y += isp1504xc.o
+endif
+endif
+
+ifneq ($(CONFIG_ARCH_MX25)$(CONFIG_USB),)
+obj-y += usb_common.o
+endif
+
+ifeq ($(CONFIG_ARCH_MX25),y)
+ifneq ($(CONFIG_USB_EHCI_ARC_H2),)
+obj-y += serialxc.o
+endif
+endif
diff --git a/arch/arm/plat-mxc/clock.c b/arch/arm/plat-mxc/clock.c
index 92e13566cd4f..4ba52f106bfb 100644
--- a/arch/arm/plat-mxc/clock.c
+++ b/arch/arm/plat-mxc/clock.c
@@ -4,7 +4,7 @@
* Copyright (C) 2004 - 2005 Nokia corporation
* Written by Tuukka Tikkanen <tuukka.tikkanen@elektrobit.com>
* Modified for omap shared clock framework by Tony Lindgren <tony@atomide.com>
- * Copyright 2007 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2007-2009 Freescale Semiconductor, Inc. All Rights Reserved.
* Copyright 2008 Juergen Beisert, kernel@pengutronix.de
*
* This program is free software; you can redistribute it and/or
@@ -25,6 +25,7 @@
/* #define DEBUG */
#include <linux/clk.h>
+#include <linux/cpufreq.h>
#include <linux/err.h>
#include <linux/errno.h>
#include <linux/init.h>
@@ -35,13 +36,27 @@
#include <linux/mutex.h>
#include <linux/platform_device.h>
#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
#include <linux/semaphore.h>
#include <linux/string.h>
#include <mach/clock.h>
+#if (defined(CONFIG_ARCH_MX51) || defined(CONFIG_ARCH_MX37))
+extern int dvfs_core_is_active;
+extern int lp_high_freq;
+extern int lp_med_freq;
+extern void dvfs_core_set_bus_freq(void);
+#else
+int dvfs_core_is_active;
+void dvfs_core_set_bus_freq(void)
+{
+};
+#endif
+
static LIST_HEAD(clocks);
static DEFINE_MUTEX(clocks_mutex);
+static DEFINE_SPINLOCK(clockfw_lock);
/*-------------------------------------------------------------------------
* Standard clock functions defined in include/linux/clk.h
@@ -119,14 +134,16 @@ EXPORT_SYMBOL(clk_get);
static void __clk_disable(struct clk *clk)
{
- if (clk == NULL || IS_ERR(clk))
+ if (clk == NULL || IS_ERR(clk) || !clk->usecount)
return;
- __clk_disable(clk->parent);
- __clk_disable(clk->secondary);
+ if (!(--clk->usecount)) {
+ if (clk->disable)
+ clk->disable(clk);
- if (!(--clk->usecount) && clk->disable)
- clk->disable(clk);
+ __clk_disable(clk->parent);
+ __clk_disable(clk->secondary);
+ }
}
static int __clk_enable(struct clk *clk)
@@ -134,12 +151,13 @@ static int __clk_enable(struct clk *clk)
if (clk == NULL || IS_ERR(clk))
return -EINVAL;
- __clk_enable(clk->parent);
- __clk_enable(clk->secondary);
-
- if (clk->usecount++ == 0 && clk->enable)
- clk->enable(clk);
+ if (clk->usecount++ == 0) {
+ __clk_enable(clk->parent);
+ __clk_enable(clk->secondary);
+ if (clk->enable)
+ clk->enable(clk);
+ }
return 0;
}
@@ -148,15 +166,36 @@ static int __clk_enable(struct clk *clk)
*/
int clk_enable(struct clk *clk)
{
+ unsigned long flags;
int ret = 0;
if (clk == NULL || IS_ERR(clk))
return -EINVAL;
- mutex_lock(&clocks_mutex);
+ spin_lock_irqsave(&clockfw_lock, flags);
+
ret = __clk_enable(clk);
- mutex_unlock(&clocks_mutex);
+ spin_unlock_irqrestore(&clockfw_lock, flags);
+
+ if ((clk->flags & CPU_FREQ_TRIG_UPDATE)
+ && (clk_get_usecount(clk) == 1)) {
+#if defined(CONFIG_CPU_FREQ)
+ if (dvfs_core_is_active)
+ dvfs_core_set_bus_freq();
+#if (defined(CONFIG_ARCH_MX51) || defined(CONFIG_ARCH_MX37))
+ else if ((lp_high_freq == 0 && lp_med_freq == 0) ||
+ (lp_high_freq == 1) ||
+ (lp_high_freq == 0 && lp_med_freq == 1))
+#else
+ else
+#endif
+ cpufreq_update_policy(0);
+#else
+ if (dvfs_core_is_active)
+ dvfs_core_set_bus_freq();
+#endif
+ }
return ret;
}
EXPORT_SYMBOL(clk_enable);
@@ -167,15 +206,56 @@ EXPORT_SYMBOL(clk_enable);
*/
void clk_disable(struct clk *clk)
{
+ unsigned long flags;
+
if (clk == NULL || IS_ERR(clk))
return;
- mutex_lock(&clocks_mutex);
+ spin_lock_irqsave(&clockfw_lock, flags);
+
__clk_disable(clk);
- mutex_unlock(&clocks_mutex);
+
+ spin_unlock_irqrestore(&clockfw_lock, flags);
+
+ if ((clk->flags & CPU_FREQ_TRIG_UPDATE)
+ && (clk_get_usecount(clk) == 0)) {
+#if defined(CONFIG_CPU_FREQ)
+ if (dvfs_core_is_active)
+ dvfs_core_set_bus_freq();
+#if (defined(CONFIG_ARCH_MX51) || defined(CONFIG_ARCH_MX37))
+ else if (lp_high_freq == 0)
+#else
+ else
+#endif
+ cpufreq_update_policy(0);
+#else
+ if (dvfs_core_is_active)
+ dvfs_core_set_bus_freq();
+#endif
+ }
}
+
EXPORT_SYMBOL(clk_disable);
+/*!
+ * @brief Function to get the usage count for the requested clock.
+ *
+ * This function returns the reference count for the clock.
+ *
+ * @param clk Handle to clock to disable.
+ *
+ * @return Returns the usage count for the requested clock.
+ */
+int clk_get_usecount(struct clk *clk)
+{
+ if (clk == NULL || IS_ERR(clk))
+ return 0;
+
+ return clk->usecount;
+}
+
+EXPORT_SYMBOL(clk_get_usecount);
+
/* Retrieve the *current* clock rate. If the clock itself
* does not provide a special calculation routine, ask
* its parent and so on, until one is able to return
@@ -186,10 +266,7 @@ unsigned long clk_get_rate(struct clk *clk)
if (clk == NULL || IS_ERR(clk))
return 0UL;
- if (clk->get_rate)
- return clk->get_rate(clk);
-
- return clk_get_rate(clk->parent);
+ return clk->rate;
}
EXPORT_SYMBOL(clk_get_rate);
@@ -216,19 +293,48 @@ long clk_round_rate(struct clk *clk, unsigned long rate)
}
EXPORT_SYMBOL(clk_round_rate);
+/* Propagate rate to children */
+void propagate_rate(struct clk *tclk)
+{
+ struct clk *clkp;
+
+ if (tclk == NULL || IS_ERR(tclk))
+ return;
+
+ pr_debug("mxc clock: finding children of %s-%d\n", tclk->name,
+ tclk->id);
+ list_for_each_entry(clkp, &clocks, node) {
+ if (likely(clkp->parent != tclk))
+ continue;
+ pr_debug("mxc clock: %s-%d: recalculating rate: old = %lu, ",
+ clkp->name, clkp->id, clkp->rate);
+ if (likely((u32) clkp->recalc))
+ clkp->recalc(clkp);
+ else
+ clkp->rate = tclk->rate;
+ pr_debug("new = %lu\n", clkp->rate);
+ propagate_rate(clkp);
+ }
+}
+
/* Set the clock to the requested clock rate. The rate must
* match a supported rate exactly based on what clk_round_rate returns
*/
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;
- mutex_lock(&clocks_mutex);
+ spin_lock_irqsave(&clockfw_lock, flags);
+
ret = clk->set_rate(clk, rate);
- mutex_unlock(&clocks_mutex);
+ if (unlikely((ret == 0) && (clk->flags & RATE_PROPAGATES)))
+ propagate_rate(clk);
+
+ spin_unlock_irqrestore(&clockfw_lock, flags);
return ret;
}
@@ -237,17 +343,35 @@ EXPORT_SYMBOL(clk_set_rate);
/* Set the clock's parent to another clock source */
int clk_set_parent(struct clk *clk, struct clk *parent)
{
+ unsigned long flags;
int ret = -EINVAL;
+ struct clk *prev_parent = clk->parent;
if (clk == NULL || IS_ERR(clk) || parent == NULL ||
IS_ERR(parent) || clk->set_parent == NULL)
return ret;
- mutex_lock(&clocks_mutex);
+ if (clk->usecount != 0) {
+ clk_enable(parent);
+ }
+
+ spin_lock_irqsave(&clockfw_lock, flags);
ret = clk->set_parent(clk, parent);
- if (ret == 0)
+ if (ret == 0) {
clk->parent = parent;
- mutex_unlock(&clocks_mutex);
+ if (clk->recalc) {
+ clk->recalc(clk);
+ } else {
+ clk->rate = parent->rate;
+ }
+ if (unlikely(clk->flags & RATE_PROPAGATES))
+ propagate_rate(clk);
+ }
+ spin_unlock_irqrestore(&clockfw_lock, flags);
+
+ if (clk->usecount != 0) {
+ clk_disable(prev_parent);
+ }
return ret;
}
@@ -295,43 +419,164 @@ void clk_unregister(struct clk *clk)
EXPORT_SYMBOL(clk_unregister);
#ifdef CONFIG_PROC_FS
-static int mxc_clock_read_proc(char *page, char **start, off_t off,
- int count, int *eof, void *data)
+
+static void *mxc_proc_clocks_seq_start(struct seq_file *file, loff_t *index)
{
- struct clk *clkp;
- char *p = page;
- int len;
+ unsigned int i;
+ unsigned int name_length;
+ unsigned int longest_length = 0;
+ struct clk *current_clock = 0;
+ struct clk *clock;
+
+ /* Examine the clock list. */
+
+ i = 0;
+
+ list_for_each_entry(clock, &clocks, node) {
+ if (i++ == *index)
+ current_clock = clock;
+ name_length = strlen(clock->name);
+ if (name_length > longest_length)
+ longest_length = name_length;
+ }
- list_for_each_entry(clkp, &clocks, node) {
- p += sprintf(p, "%s-%d:\t\t%lu, %d", clkp->name, clkp->id,
- clk_get_rate(clkp), clkp->usecount);
- if (clkp->parent)
- p += sprintf(p, ", %s-%d\n", clkp->parent->name,
- clkp->parent->id);
- else
- p += sprintf(p, "\n");
+ /* Check if we found the indicated clock. */
+
+ if (!current_clock)
+ return NULL;
+
+ /* Stash the length of the longest clock name for later use. */
+
+ file->private = (void *) longest_length;
+
+ /* Return success. */
+
+ return current_clock;
+}
+
+static void *mxc_proc_clocks_seq_next(struct seq_file *file, void *data,
+ loff_t *index)
+{
+ struct clk *current_clock = (struct clk *) data;
+
+ /* Check for nonsense. */
+
+ if (!current_clock)
+ return NULL;
+
+ /* Check if the current clock is the last. */
+
+ if (list_is_last(&current_clock->node, &clocks))
+ return NULL;
+
+ /* Move to the next clock structure. */
+
+ current_clock = list_entry(current_clock->node.next,
+ typeof(*current_clock), node);
+
+ (*index)++;
+
+ /* Return the new current clock. */
+
+ return current_clock;
+
+}
+
+static void mxc_proc_clocks_seq_stop(struct seq_file *file, void *data)
+{
+}
+
+static int mxc_proc_clocks_seq_show(struct seq_file *file, void *data)
+{
+ int result;
+ struct clk *clock = (struct clk *) data;
+ struct clk *parent = clock->parent;
+ unsigned int longest_length = (unsigned int) file->private;
+ unsigned long range_divisor;
+ const char *range_units;
+
+ if (clock->rate >= 1000000) {
+ range_divisor = 1000000;
+ range_units = "MHz";
+ } else if (clock->rate >= 1000) {
+ range_divisor = 1000;
+ range_units = "KHz";
+ } else {
+ range_divisor = 1;
+ range_units = "Hz";
}
- len = (p - page) - off;
- if (len < 0)
- len = 0;
+ if (parent)
+ result = seq_printf(file,
+ "%s-%-d%*s %s-%-d%*s %c%c%c%c%c%c %3d",
+ clock->name,
+ clock->id,
+ longest_length - strlen(clock->name), "",
+ parent->name,
+ parent->id,
+ longest_length - strlen(parent->name), "",
+ (clock->flags & RATE_PROPAGATES) ? 'P' : '_',
+ (clock->flags & ALWAYS_ENABLED) ? 'A' : '_',
+ (clock->flags & RATE_FIXED) ? 'F' : '_',
+ (clock->flags & CPU_FREQ_TRIG_UPDATE) ? 'T' : '_',
+ (clock->flags & AHB_HIGH_SET_POINT) ? 'H' : '_',
+ (clock->flags & AHB_MED_SET_POINT) ? 'M' : '_',
+ clock->usecount);
+ else
+ result = seq_printf(file,
+ "%s-%-d%*s %*s %c%c%c%c%c%c %3d",
+ clock->name,
+ clock->id,
+ longest_length - strlen(clock->name), "",
+ longest_length + 2, "",
+ (clock->flags & RATE_PROPAGATES) ? 'P' : '_',
+ (clock->flags & ALWAYS_ENABLED) ? 'A' : '_',
+ (clock->flags & RATE_FIXED) ? 'F' : '_',
+ (clock->flags & CPU_FREQ_TRIG_UPDATE) ? 'T' : '_',
+ (clock->flags & AHB_HIGH_SET_POINT) ? 'H' : '_',
+ (clock->flags & AHB_MED_SET_POINT) ? 'M' : '_',
+ clock->usecount);
+
+ if (result)
+ return result;
+
+ result = seq_printf(file, " %10lu (%lu%s)\n",
+ clock->rate,
+ clock->rate / range_divisor, range_units);
+
+ return result;
+
+}
- *eof = (len <= count) ? 1 : 0;
- *start = page + off;
+static const struct seq_operations mxc_proc_clocks_seq_ops = {
+ .start = mxc_proc_clocks_seq_start,
+ .next = mxc_proc_clocks_seq_next,
+ .stop = mxc_proc_clocks_seq_stop,
+ .show = mxc_proc_clocks_seq_show
+};
- return len;
+static int mxc_proc_clocks_open(struct inode *inode, struct file *file)
+{
+ return seq_open(file, &mxc_proc_clocks_seq_ops);
}
+static const struct file_operations mxc_proc_clocks_ops = {
+ .open = mxc_proc_clocks_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = seq_release,
+};
+
static int __init mxc_setup_proc_entry(void)
{
struct proc_dir_entry *res;
- res = create_proc_read_entry("cpu/clocks", 0, NULL,
- mxc_clock_read_proc, NULL);
+ res = create_proc_entry("cpu/clocks", 0, NULL);
if (!res) {
printk(KERN_ERR "Failed to create proc/cpu/clocks\n");
return -ENOMEM;
}
+ res->proc_fops = &mxc_proc_clocks_ops;
return 0;
}
diff --git a/arch/arm/plat-mxc/cpu_common.c b/arch/arm/plat-mxc/cpu_common.c
new file mode 100644
index 000000000000..07e92e17289a
--- /dev/null
+++ b/arch/arm/plat-mxc/cpu_common.c
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2004-2007 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/init.h>
+#include <linux/module.h>
+#include <asm/setup.h>
+#include <mach/common.h>
+#include <mach/hardware.h>
+
+extern int mxc_early_serial_console_init(char *);
+
+/*!
+ * @file plat-mxc/cpu_common.c
+ *
+ * @brief This file contains the common CPU initialization code.
+ *
+ * @ingroup MSL_MX31 MSL_MXC91321
+ */
+
+static void __init system_rev_setup(char **p)
+{
+ system_rev = simple_strtoul(*p, NULL, 16);
+}
+
+__early_param("system_rev=", system_rev_setup);
+
+int mxc_jtag_enabled; /* OFF: 0 (default), ON: 1 */
+
+/*
+ * Here are the JTAG options from the command line. By default JTAG
+ * is OFF which means JTAG is not connected and WFI is enabled
+ *
+ * "on" -- JTAG is connected, so WFI is disabled
+ * "off" -- JTAG is disconnected, so WFI is enabled
+ */
+
+static void __init jtag_wfi_setup(char **p)
+{
+ if (memcmp(*p, "on", 2) == 0) {
+ mxc_jtag_enabled = 1;
+ *p += 2;
+ } else if (memcmp(*p, "off", 3) == 0) {
+ mxc_jtag_enabled = 0;
+ *p += 3;
+ }
+}
+
+__early_param("jtag=", jtag_wfi_setup);
+
+void __init mxc_cpu_common_init(void)
+{
+ mxc_set_cpu_type((((system_rev >> 20) & 0xF) * 10) + ((system_rev >> 16) & 0xF));
+ pr_info("CPU is %s%x Revision %u.%u\n",
+ (mxc_cpu() < 0x100) ? "i.MX" : "MXC",
+ mxc_cpu(), mxc_cpu_rev_major(), mxc_cpu_rev_minor());
+}
+
+/**
+ * early_console_setup - setup debugging console
+ *
+ * Consoles started here require little enough setup that we can start using
+ * them very early in the boot process, either right after the machine
+ * vector initialization, or even before if the drivers can detect their hw.
+ *
+ * Returns non-zero if a console couldn't be setup.
+ * This function is developed based on
+ * early_console_setup function as defined in arch/ia64/kernel/setup.c
+ */
+void __init early_console_setup(char *cmdline)
+{
+#ifdef CONFIG_SERIAL_MXC_CONSOLE
+ mxc_early_serial_console_init(cmdline);
+#endif
+}
diff --git a/arch/arm/plat-mxc/cpufreq.c b/arch/arm/plat-mxc/cpufreq.c
new file mode 100644
index 000000000000..bc3d1c97526c
--- /dev/null
+++ b/arch/arm/plat-mxc/cpufreq.c
@@ -0,0 +1,347 @@
+/*
+ * Copyright 2009 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
+ */
+
+/*!
+ * @file cpufreq.c
+ *
+ * @brief A driver for the Freescale Semiconductor i.MXC CPUfreq module.
+ *
+ * The CPUFREQ driver is for controling CPU frequency. It allows you to change
+ * the CPU clock speed on the fly.
+ *
+ * @ingroup PM
+ */
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/cpufreq.h>
+#include <linux/init.h>
+#include <linux/proc_fs.h>
+#include <linux/regulator/consumer.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <mach/hardware.h>
+#include <asm/setup.h>
+#include <mach/clock.h>
+#include <asm/cacheflush.h>
+#include <linux/hrtimer.h>
+
+int cpu_freq_khz_min;
+int cpu_freq_khz_max;
+int arm_lpm_clk;
+int arm_normal_clk;
+int cpufreq_suspended;
+
+static struct clk *cpu_clk;
+static struct regulator *gp_regulator;
+static struct cpu_wp *cpu_wp_tbl;
+static struct cpufreq_frequency_table imx_freq_table[4];
+extern int low_bus_freq_mode;
+extern int high_bus_freq_mode;
+extern int dvfs_core_is_active;
+extern int cpu_wp_nr;
+extern char *gp_reg_id;
+
+extern int set_low_bus_freq(void);
+extern int set_high_bus_freq(int high_bus_speed);
+extern int low_freq_bus_used(void);
+
+#ifdef CONFIG_ARCH_MX51
+extern struct cpu_wp *(*get_cpu_wp)(int *wp);
+#endif
+
+static int set_cpu_freq(int freq)
+{
+ int ret = 0;
+ int org_cpu_rate;
+ int gp_volt = 0;
+ int i;
+
+ org_cpu_rate = clk_get_rate(cpu_clk);
+
+ if (org_cpu_rate == freq)
+ return ret;
+
+ for (i = 0; i < cpu_wp_nr; i++) {
+ if (freq == cpu_wp_tbl[i].cpu_rate)
+ gp_volt = cpu_wp_tbl[i].cpu_voltage;
+ }
+
+ if (gp_volt == 0)
+ return ret;
+
+ /*Set the voltage for the GP domain. */
+ if (freq > org_cpu_rate) {
+ ret = regulator_set_voltage(gp_regulator, gp_volt, gp_volt);
+ if (ret < 0) {
+ printk(KERN_DEBUG "COULD NOT SET GP VOLTAGE!!!!\n");
+ return ret;
+ }
+ }
+
+ ret = clk_set_rate(cpu_clk, freq);
+ if (ret != 0) {
+ printk(KERN_DEBUG "cannot set CPU clock rate\n");
+ return ret;
+ }
+
+ if (freq < org_cpu_rate) {
+ ret = regulator_set_voltage(gp_regulator, gp_volt, gp_volt);
+ if (ret < 0) {
+ printk(KERN_DEBUG "COULD NOT SET GP VOLTAGE!!!!\n");
+ return ret;
+ }
+ }
+
+ return ret;
+}
+
+static int mxc_verify_speed(struct cpufreq_policy *policy)
+{
+ if (policy->cpu != 0)
+ return -EINVAL;
+
+ return cpufreq_frequency_table_verify(policy, imx_freq_table);
+}
+
+static unsigned int mxc_get_speed(unsigned int cpu)
+{
+ if (cpu)
+ return 0;
+
+ return clk_get_rate(cpu_clk) / 1000;
+}
+
+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 = cpu_wp_nr - 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 < cpu_wp_nr; 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 mxc_set_target(struct cpufreq_policy *policy,
+ unsigned int target_freq, unsigned int relation)
+{
+ struct cpufreq_freqs freqs;
+ int freq_Hz;
+ int low_freq_bus_ready = 0;
+ int ret = 0;
+
+ if (cpufreq_suspended)
+ return 0;
+
+ if (dvfs_core_is_active) {
+ target_freq = clk_get_rate(cpu_clk) / 1000;
+ freq_Hz = calc_frequency_khz(target_freq, relation) * 1000;
+ if (freq_Hz == arm_lpm_clk)
+ freqs.old = cpu_wp_tbl[cpu_wp_nr - 2].cpu_rate / 1000;
+ else
+ freqs.old = arm_lpm_clk / 1000;
+
+ freqs.new = freq_Hz / 1000;
+ freqs.cpu = 0;
+ freqs.flags = 0;
+ cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+ cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+ return ret;
+ }
+ /*
+ * 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.
+ */
+ if (target_freq < policy->cpuinfo.min_freq)
+ target_freq = policy->cpuinfo.min_freq;
+
+ if (target_freq < policy->min)
+ target_freq = policy->min;
+
+ freq_Hz = calc_frequency_khz(target_freq, relation) * 1000;
+
+ freqs.old = clk_get_rate(cpu_clk) / 1000;
+ freqs.new = freq_Hz / 1000;
+ freqs.cpu = 0;
+ freqs.flags = 0;
+ low_freq_bus_ready = low_freq_bus_used();
+ cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+ if (!dvfs_core_is_active) {
+ if ((freq_Hz == arm_lpm_clk) && (!low_bus_freq_mode)
+ && (low_freq_bus_ready)) {
+ if (freqs.old != freqs.new)
+ ret = set_cpu_freq(freq_Hz);
+ set_low_bus_freq();
+
+ } else {
+ set_high_bus_freq(0);
+ ret = set_cpu_freq(freq_Hz);
+ }
+ }
+
+ cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+
+ return ret;
+}
+
+static int __init mxc_cpufreq_driver_init(struct cpufreq_policy *policy)
+{
+ int ret;
+ int i;
+
+ printk(KERN_INFO "i.MXC CPU frequency driver\n");
+
+ if (policy->cpu != 0)
+ return -EINVAL;
+
+ cpu_clk = clk_get(NULL, "cpu_clk");
+ if (IS_ERR(cpu_clk)) {
+ printk(KERN_ERR "%s: failed to get cpu clock\n", __func__);
+ return PTR_ERR(cpu_clk);
+ }
+
+ gp_regulator = regulator_get(NULL, gp_reg_id);
+ if (IS_ERR(gp_regulator)) {
+ clk_put(cpu_clk);
+ printk(KERN_ERR "%s: failed to get gp regulator\n", __func__);
+ return PTR_ERR(gp_regulator);
+ }
+
+ /* Set the current working point. */
+ cpu_wp_tbl = get_cpu_wp(&cpu_wp_nr);
+
+ cpu_freq_khz_min = cpu_wp_tbl[0].cpu_rate / 1000;
+ cpu_freq_khz_max = cpu_wp_tbl[0].cpu_rate / 1000;
+
+ for (i = 0; i < cpu_wp_nr; i++) {
+ imx_freq_table[cpu_wp_nr - 1 - i].index = cpu_wp_nr - i;
+ imx_freq_table[cpu_wp_nr - 1 - i].frequency =
+ cpu_wp_tbl[i].cpu_rate / 1000;
+
+ if ((cpu_wp_tbl[i].cpu_rate / 1000) < cpu_freq_khz_min)
+ cpu_freq_khz_min = cpu_wp_tbl[i].cpu_rate / 1000;
+
+ if ((cpu_wp_tbl[i].cpu_rate / 1000) > cpu_freq_khz_max)
+ cpu_freq_khz_max = cpu_wp_tbl[i].cpu_rate / 1000;
+ }
+
+ 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;
+
+ arm_lpm_clk = cpu_freq_khz_min * 1000;
+ arm_normal_clk = cpu_freq_khz_max * 1000;
+
+ /* Manual states, that PLL stabilizes in two CLK32 periods */
+ policy->cpuinfo.transition_latency = 10;
+
+ ret = cpufreq_frequency_table_cpuinfo(policy, imx_freq_table);
+
+ if (ret < 0) {
+ clk_put(cpu_clk);
+ regulator_put(gp_regulator);
+ 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 0;
+}
+
+static int mxc_cpufreq_suspend(struct cpufreq_policy *policy,
+ pm_message_t state)
+{
+ struct cpufreq_freqs freqs;
+ int ret = 0;
+ cpufreq_suspended = 1;
+
+ freqs.old = clk_get_rate(cpu_clk) / 1000;
+ freqs.new = arm_normal_clk / 1000;
+ freqs.cpu = 0;
+ freqs.flags = 0;
+
+ if (clk_get_rate(cpu_clk) != arm_normal_clk) {
+ set_high_bus_freq(1);
+ ret = set_cpu_freq(arm_normal_clk);
+ }
+ return ret;
+}
+
+static int mxc_cpufreq_resume(struct cpufreq_policy *policy)
+{
+ cpufreq_suspended = 0;
+ return 0;
+}
+
+static int mxc_cpufreq_driver_exit(struct cpufreq_policy *policy)
+{
+ cpufreq_frequency_table_put_attr(policy->cpu);
+
+ /* Reset CPU to 665MHz */
+ if (!dvfs_core_is_active)
+ set_cpu_freq(arm_normal_clk);
+ if (!high_bus_freq_mode)
+ set_high_bus_freq(1);
+
+ clk_put(cpu_clk);
+ regulator_put(gp_regulator);
+ return 0;
+}
+
+static struct cpufreq_driver mxc_driver = {
+ .flags = CPUFREQ_STICKY,
+ .verify = mxc_verify_speed,
+ .target = mxc_set_target,
+ .get = mxc_get_speed,
+ .init = mxc_cpufreq_driver_init,
+ .exit = mxc_cpufreq_driver_exit,
+ .suspend = mxc_cpufreq_suspend,
+ .resume = mxc_cpufreq_resume,
+ .name = "imx",
+};
+
+static int __devinit mxc_cpufreq_init(void)
+{
+ return cpufreq_register_driver(&mxc_driver);
+}
+
+static void mxc_cpufreq_exit(void)
+{
+ cpufreq_unregister_driver(&mxc_driver);
+}
+
+module_init(mxc_cpufreq_init);
+module_exit(mxc_cpufreq_exit);
+
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_DESCRIPTION("CPUfreq driver for i.MX");
+MODULE_LICENSE("GPL");
diff --git a/arch/arm/plat-mxc/dma_mx2.c b/arch/arm/plat-mxc/dma_mx2.c
new file mode 100644
index 000000000000..5a7e93b31d57
--- /dev/null
+++ b/arch/arm/plat-mxc/dma_mx2.c
@@ -0,0 +1,1316 @@
+/*
+ * Copyright 2004-2009 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
+ */
+
+/* Front-end to the DMA handling. This handles the allocation/freeing
+ * of DMA channels, and provides a unified interface to the machines
+ * DMA facilities.
+ */
+
+/*!
+ * @file plat-mxc/dma_mx2.c
+ * @brief This file contains functions for DMA API
+ *
+ * @ingroup DMA_MX27
+ */
+
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/sched.h>
+#include <linux/mman.h>
+#include <linux/init.h>
+#include <linux/spinlock.h>
+#include <linux/interrupt.h>
+#include <linux/clk.h>
+
+#include <linux/proc_fs.h>
+#include <linux/io.h>
+
+#include <mach/hardware.h>
+#include <mach/dma.h>
+#include <asm/delay.h>
+
+#include <asm/atomic.h>
+
+/* commented temperily for mx27 compilation
+#define DMA_PM
+*/
+#ifdef DMA_PM
+#include <linux/pm.h>
+#include <mach/apmc.h>
+struct apmc_user *dma_apmc_user;
+struct pm_dev *dma_pm;
+#define DMA_PMST_RESUME 0
+#define DMA_PMST_STANDBY 1
+#define DMA_PMST_SUSPEND 2
+static unsigned int dma_pm_status = DMA_PMST_RESUME;
+#endif
+
+/*!
+ * This variable is used to controll the clock of DMA.
+ * It counts the number of actived channels
+ */
+static atomic_t g_dma_actived = ATOMIC_INIT(0);
+
+/*!
+ * This variable point a proc file which contains the information
+ * of DMA channels
+ */
+static struct proc_dir_entry *g_proc_dir;
+
+/*!
+ * The dma channels
+ */
+static mxc_dma_channel_t g_dma_channels[MAX_DMA_CHANNELS];
+static mx2_dma_priv_t g_dma_privates[MXC_DMA_CHANNELS];
+static mx2_dma_bd_t g_dma_bd_table[MXC_DMA_CHANNELS][MAX_BD_SIZE];
+
+static DEFINE_SPINLOCK(dma_list_lock);
+
+static struct clk *dma_clk;
+
+/*!@brief flush buffer descriptor ring*/
+#define flush_dma_bd(private) \
+ { \
+ atomic_set(&(private->bd_used), 0); \
+ private->bd_rd = private->bd_wr;\
+ }
+
+/*!@brief get next buffer discriptor */
+#define next_dma_bd(private) \
+ ({ \
+ int bd_next = (private->bd_rd+1)%MAX_BD_SIZE; \
+ (bd_next == private->bd_wr) ? NULL: private->bd_ring+bd_next;\
+ })
+
+static inline int consume_dma_bd(mxc_dma_channel_t * dma, int error);
+/*!
+ *@brief allocate a dma channel.
+ *
+ *@param idx Requested channel NO.
+ * @li MXC_INVLAID_CHANNEL System allocates a free channel which is not statically allocated.
+ * @li Others User requests a specific channel
+ *@return @li MXC_INVLAID_CHANNEL Failure
+ * @li Others Success
+ */
+static inline int get_dma_channel(int idx)
+{
+ int i;
+ mxc_dma_channel_t *p;
+
+ if ((idx >= MAX_DMA_CHANNELS) && (idx != MXC_DMA_DYNAMIC_CHANNEL)) {
+ return -1;
+ }
+ if (idx != MXC_DMA_DYNAMIC_CHANNEL) {
+ p = g_dma_channels + idx;
+ BUG_ON(p->dynamic != 0);
+ if (xchg(&p->lock, 1) != 0) {
+ return -1;
+ }
+ return idx;
+ }
+
+ p = g_dma_channels;
+ for (i = 0; (i < MAX_DMA_CHANNELS); i++, p++) {
+ if (p->dynamic && (xchg(&p->lock, 1) == 0)) {
+ return i;
+ }
+ }
+ return -1;
+}
+
+/*!
+ *@brief release a dma channel.
+ *
+ *@param idx channel number
+ *@return none;
+ */
+static inline void put_dma_channel(int idx)
+{
+ mxc_dma_channel_t *p;
+
+ if ((idx < MAX_DMA_CHANNELS) && (idx >= 0)) {
+ p = g_dma_channels + idx;
+ (void)xchg(&p->lock, 0);
+ }
+}
+
+/*!
+ *@brief Get dma list for /proc/dma
+ */
+static int mxc_get_dma_list(char *buf)
+{
+ mxc_dma_channel_t *dma;
+ char *p = buf;
+ int i;
+
+ for (i = 0, dma = g_dma_channels; i < MAX_DMA_CHANNELS; i++, dma++) {
+ if (dma->lock) {
+ p += sprintf(p, "dma channel %2d: %s\n", i,
+ dma->dev_name ? dma->dev_name : "unknown");
+ } else {
+ p += sprintf(p, "dma channel %2d: unused\n", i);
+ }
+ }
+
+ return p - buf;
+}
+
+/*!@brief save the mask of dma interrupts*/
+#define save_dma_interrupt(flags) \
+ flags = __raw_readl(IO_ADDRESS(DMA_BASE_ADDR) + DMA_DIMR)
+
+/*!@brief restore the mask of dma interrupts*/
+#define restore_dma_interrupt(flags) \
+ __raw_writel(flags, IO_ADDRESS(DMA_BASE_ADDR) + DMA_DIMR)
+
+/*!@brief disable interrupt of dma channel*/
+static inline void mask_dma_interrupt(int channel)
+{
+ unsigned long reg;
+ save_dma_interrupt(reg);
+ reg |= 1 << channel; /*mask interrupt; */
+ restore_dma_interrupt(reg);
+}
+
+/*!@brief enable interrupt of dma channel */
+static inline void unmask_dma_interrupt(int channel)
+{
+ unsigned long reg;
+ save_dma_interrupt(reg);
+ reg &= ~(1 << channel); /*unmask interrupt; */
+ restore_dma_interrupt(reg);
+}
+
+/*!@brief get interrupt event of dma channel */
+static unsigned long inline __get_dma_interrupt(int channel)
+{
+ unsigned long mode;
+ mode = 0;
+ if (__raw_readl(IO_ADDRESS(DMA_BASE_ADDR) + DMA_DISR) & (1 << channel))
+ mode |= DMA_DONE;
+
+ if (__raw_readl(IO_ADDRESS(DMA_BASE_ADDR) + DMA_DBTOSR) &
+ (1 << channel))
+ mode |= DMA_BURST_TIMEOUT;
+ if (__raw_readl(IO_ADDRESS(DMA_BASE_ADDR) + DMA_DSESR) & (1 << channel))
+ mode |= DMA_TRANSFER_ERROR;
+
+ if (__raw_readl(IO_ADDRESS(DMA_BASE_ADDR) + DMA_DBOSR) & (1 << channel))
+ mode |= DMA_BUFFER_OVERFLOW;
+ if (__raw_readl(IO_ADDRESS(DMA_BASE_ADDR) + DMA_DRTOSR) &
+ (1 << channel))
+ mode |= DMA_REQUEST_TIMEOUT;
+ return mode;
+}
+
+/*!
+ *@brief clean all event of dma interrupt and return the valid event.
+ */
+static unsigned long inline __clear_dma_interrupt(int channel)
+{
+ unsigned long mode;
+ mode = __get_dma_interrupt(channel);
+ __raw_writel(1 << channel, IO_ADDRESS(DMA_BASE_ADDR) + DMA_DISR);
+ __raw_writel(1 << channel, IO_ADDRESS(DMA_BASE_ADDR) + DMA_DBTOSR);
+ __raw_writel(1 << channel, IO_ADDRESS(DMA_BASE_ADDR) + DMA_DRTOSR);
+ __raw_writel(1 << channel, IO_ADDRESS(DMA_BASE_ADDR) + DMA_DSESR);
+ __raw_writel(1 << channel, IO_ADDRESS(DMA_BASE_ADDR) + DMA_DBOSR);
+
+ return mode;
+}
+
+/*!@brief This function enables dma clocks without lock */
+static void inline __enable_dma_clk(void)
+{
+ unsigned long reg;
+ clk_enable(dma_clk);
+ reg = __raw_readl(IO_ADDRESS(DMA_BASE_ADDR) + DMA_DCR);
+ reg |= 0x1;
+ __raw_writel(reg, IO_ADDRESS(DMA_BASE_ADDR) + DMA_DCR);
+}
+
+/*!@brief This function disables dma clocks without lock */
+static void inline __disable_dma_clk(void)
+{
+ unsigned long reg;
+ reg = __raw_readl(IO_ADDRESS(DMA_BASE_ADDR) + DMA_DCR);
+ reg &= ~0x1;
+ __raw_writel(reg, IO_ADDRESS(DMA_BASE_ADDR) + DMA_DCR);
+ clk_disable(dma_clk);
+}
+
+/*!@brief This function enables dma clocks with lock */
+static void inline enable_dma_clk(void)
+{
+ unsigned long flags;
+ spin_lock_irqsave(&dma_list_lock, flags);
+ if (atomic_read(&g_dma_actived) == 0) {
+ __enable_dma_clk();
+ }
+ spin_unlock_irqrestore(&dma_list_lock, flags);
+ return;
+}
+
+/*!@brief This function disables dma clocks without locked */
+static void inline disable_dma_clk(void)
+{
+ unsigned long flags;
+ spin_lock_irqsave(&dma_list_lock, flags);
+ if (atomic_read(&g_dma_actived) == 0) {
+ __disable_dma_clk();
+ }
+ spin_unlock_irqrestore(&dma_list_lock, flags);
+ return;
+}
+
+/*!@brief select a buffer to transfer and
+ * setup dma channel for current transfer
+ */
+static void setup_dmac(mxc_dma_channel_t * dma)
+{
+ mx2_dma_priv_t *priv = (mx2_dma_priv_t *) dma->private;
+ dma_regs_t *dma_base = (dma_regs_t *) (priv->dma_base);
+ mx2_dma_bd_t *p, *q;
+ unsigned long ctrl_val;
+
+ if (dma->active == 0) {
+ printk(KERN_ERR
+ "dma channel %d is not enabled, when receiving this channel 's interrupt\n",
+ dma->channel);
+ return;
+ }
+ if (atomic_read(&(priv->bd_used)) <= 0) {
+ printk(KERN_ERR "dma channel %d is empty\n", dma->channel);
+ dma->active = 0;
+ atomic_dec(&g_dma_actived);
+ return;
+ }
+ /* BUSY: transfering
+ * PEND: Wait for set to DMAC.
+ * s1: no transfering:
+ * set first(one BUSY). if there are more than one tranfer. set second &repeat is enabled(two BUSY).
+ *
+ * s2: transfering & just on transfer
+ * one BUSY. set the tranesfer and set repeat bit(two BUSY)
+ * s3: transfering & repeat has set
+ * has two BUSY.
+ */
+ p = priv->bd_ring + priv->bd_rd;
+ q = next_dma_bd(priv);
+ if (!(p->state & DMA_BD_ST_BUSY)) {
+ /*NOTICE:: This is first buffer or dma chain does not support chain-buffer. So CEN must clear & set again */
+ ctrl_val =
+ __raw_readl(&(dma_base->Ctl)) &
+ (~(DMA_CTL_ACRPT | DMA_CTL_RPT | DMA_CTL_CEN));
+ __raw_writel(ctrl_val, &(dma_base->Ctl));
+ if (p->mode != dma->mode) {
+ dma->mode = p->mode; /* bi-dir channel do mode change */
+ if (dma->mode == MXC_DMA_MODE_READ) {
+ DMA_CTL_SET_SMOD(ctrl_val,
+ priv->dma_info->sourceType);
+ DMA_CTL_SET_SSIZ(ctrl_val,
+ priv->dma_info->sourcePort);
+ DMA_CTL_SET_DMOD(ctrl_val,
+ priv->dma_info->destType);
+ DMA_CTL_SET_DSIZ(ctrl_val,
+ priv->dma_info->destPort);
+ } else {
+ DMA_CTL_SET_SMOD(ctrl_val,
+ priv->dma_info->destType);
+ DMA_CTL_SET_SSIZ(ctrl_val,
+ priv->dma_info->destPort);
+ DMA_CTL_SET_DMOD(ctrl_val,
+ priv->dma_info->sourceType);
+ DMA_CTL_SET_DSIZ(ctrl_val,
+ priv->dma_info->sourcePort);
+ }
+ }
+ __raw_writel(p->src_addr, &(dma_base->SourceAddr));
+ __raw_writel(p->dst_addr, &(dma_base->DestAddr));
+ __raw_writel(p->count, &(dma_base->Count));
+ p->state |= DMA_BD_ST_BUSY;
+ p->state &= ~(DMA_BD_ST_PEND);
+ ctrl_val |= DMA_CTL_CEN;
+ __raw_writel(ctrl_val, &(dma_base->Ctl));
+ if (q && priv->dma_chaining) { /*DO chain-buffer */
+ __raw_writel(q->src_addr, &(dma_base->SourceAddr));
+ __raw_writel(q->dst_addr, &(dma_base->DestAddr));
+ __raw_writel(q->count, &(dma_base->Count));
+ q->state |= DMA_BD_ST_BUSY;
+ q->state &= ~(DMA_BD_ST_PEND);
+ ctrl_val |= DMA_CTL_ACRPT | DMA_CTL_RPT | DMA_CTL_CEN;
+ __raw_writel(ctrl_val, &(dma_base->Ctl));
+ }
+ } else { /* Just dma channel which supports dma buffer can run to there */
+ BUG_ON(!priv->dma_chaining);
+ if (q) { /* p is tranfering, then q must be set into dma controller */
+ /*WARNING:: [1] dangerous area begin.
+ * If the p is completed during MCU run in this erea, the dma channel is crashed.
+ */
+ __raw_writel(q->src_addr, &(dma_base->SourceAddr));
+ __raw_writel(q->dst_addr, &(dma_base->DestAddr));
+ __raw_writel(q->count, &(dma_base->Count));
+ /*WARNING:: [2] dangerous area end */
+ ctrl_val =
+ __raw_readl(&(dma_base->Ctl)) | (DMA_CTL_ACRPT |
+ DMA_CTL_RPT |
+ DMA_CTL_CEN);
+ __raw_writel(ctrl_val, &(dma_base->Ctl));
+
+ /* WARNING:: This is workaround and it is dangerous:
+ * the judgement is not safety.
+ */
+ if (!__get_dma_interrupt(dma->channel)) {
+ q->state |= DMA_BD_ST_BUSY;
+ q->state &= ~(DMA_BD_ST_PEND);
+ } else {
+ /*Waiting re-enable is in ISR */
+ printk(KERN_ERR
+ "Warning:: The privous transfer is completed. Maybe the chain buffer is stopped.");
+ }
+ } else { /* Last buffer is transfering: just clear RPT bit */
+ ctrl_val =
+ __raw_readl(&(dma_base->Ctl)) &
+ (~(DMA_CTL_ACRPT | DMA_CTL_RPT));
+ __raw_writel(ctrl_val, &(dma_base->Ctl));
+ }
+ }
+}
+
+/*!
+ * @brief interrupt handler of dma channel
+ */
+static irqreturn_t dma_irq_handler(int irq, void *dev_id)
+{
+ mxc_dma_channel_t *dma = (mxc_dma_channel_t *) dev_id;
+ mx2_dma_priv_t *priv = (mx2_dma_priv_t *) (dma ? dma->private : NULL);
+ dma_regs_t *dma_base;
+ int state, error = MXC_DMA_DONE;
+
+ BUG_ON(priv == NULL);
+
+ dma_base = (dma_regs_t *) priv->dma_base;
+
+ state = __clear_dma_interrupt(dma->channel);
+
+ priv->trans_bytes += dma_base->transferd;
+ if (state != DMA_DONE) {
+ if (state & DMA_REQUEST_TIMEOUT) {
+ error = MXC_DMA_REQUEST_TIMEOUT;
+ } else {
+ error = MXC_DMA_TRANSFER_ERROR;
+ }
+ }
+ if (consume_dma_bd(dma, error)) {
+ disable_dma_clk();
+ if (dma->cb_fn) {
+ dma->cb_fn(dma->cb_args, error, priv->trans_bytes);
+ }
+ priv->trans_bytes = 0;
+ } else {
+ disable_dma_clk();
+ }
+ return IRQ_HANDLED;
+}
+
+/*!
+ *@brief Set DMA channel parameters
+ *
+ *@param dma Requested channel NO.
+ *@param dma_info Channel configuration
+ *@return @li 0 Success
+ * @li others Failure
+ */
+static int setup_dma_channel(mxc_dma_channel_t * dma, mx2_dma_info_t * dma_info)
+{
+ mx2_dma_priv_t *priv = (mx2_dma_priv_t *) (dma ? dma->private : NULL);
+ dma_regs_t *dma_base;
+ unsigned long reg;
+
+ if (!dma_info || !priv) {
+ return -1;
+ }
+
+ if (dma_info->sourceType > 3) {
+ return -1;
+ }
+ if (dma_info->destType > 3) {
+ return -1;
+ }
+ if (dma_info->destPort > 3) {
+ return -1;
+ }
+ if (dma_info->sourcePort > 3) {
+ return -1;
+ }
+ if (dma_info->M2D_Valid) {
+ /*add for second dma */
+ if (dma_info->W < dma_info->X) {
+ return -1;
+ }
+ }
+
+ priv->dma_chaining = dma_info->dma_chaining;
+ priv->ren = dma_info->ren;
+
+ if (dma_info->sourceType != DMA_TYPE_FIFO
+ && dma_info->destType != DMA_TYPE_FIFO) {
+ if (dma_info->ren) {
+ printk(KERN_INFO
+ "Warning:request enable just affect source or destination port is FIFO !\n");
+ priv->ren = 0;
+ }
+ }
+
+ if (dma_info->M2D_Valid) {
+ if (dma_info->msel) {
+ __raw_writel(dma_info->W,
+ IO_ADDRESS(DMA_BASE_ADDR) + DMA_WSRB);
+ __raw_writel(dma_info->X,
+ IO_ADDRESS(DMA_BASE_ADDR) + DMA_XSRB);
+ __raw_writel(dma_info->Y,
+ IO_ADDRESS(DMA_BASE_ADDR) + DMA_YSRB);
+
+ } else {
+ __raw_writel(dma_info->W,
+ IO_ADDRESS(DMA_BASE_ADDR) + DMA_WSRA);
+ __raw_writel(dma_info->X,
+ IO_ADDRESS(DMA_BASE_ADDR) + DMA_XSRA);
+ __raw_writel(dma_info->Y,
+ IO_ADDRESS(DMA_BASE_ADDR) + DMA_YSRA);
+ }
+ }
+
+ dma_base = (dma_regs_t *) (priv->dma_base);
+
+ __raw_writel(dma_info->burstLength, &(dma_base->BurstLength));
+ __raw_writel(dma_info->request, &(dma_base->RequestSource));
+
+ if (dma_info->ren) {
+ reg = dma_info->busuntils & 0x1FFFF;
+ if (dma_info->rto_en) {
+ reg |= 0xE000;
+ }
+ __raw_writel(reg, &(dma_base->BusUtilt));
+ } else {
+ __raw_writel(dma_info->busuntils, &(dma_base->BusUtilt));
+ }
+
+ reg = __raw_readl(&(dma_base->Ctl)) & (~(DMA_CTL_ACRPT | DMA_CTL_RPT));
+
+ if (dma_info->dir) {
+ reg |= DMA_CTL_MDIR;
+ } else {
+ reg &= ~DMA_CTL_MDIR;
+ }
+
+ if (priv->ren) {
+ reg |= DMA_CTL_REN;
+ } else {
+ reg &= ~DMA_CTL_REN;
+ }
+
+ if ((dma_info->M2D_Valid) && (dma_info->msel)) {
+ reg |= DMA_CTL_MSEL;
+ } else {
+ reg &= ~DMA_CTL_MSEL;
+ }
+
+ if (dma_info->mode) {
+ DMA_CTL_SET_SMOD(reg, dma_info->destType);
+ DMA_CTL_SET_SSIZ(reg, dma_info->destPort);
+ DMA_CTL_SET_DMOD(reg, dma_info->sourceType);
+ DMA_CTL_SET_DSIZ(reg, dma_info->sourcePort);
+ } else {
+ DMA_CTL_SET_SMOD(reg, dma_info->sourceType);
+ DMA_CTL_SET_SSIZ(reg, dma_info->sourcePort);
+ DMA_CTL_SET_DMOD(reg, dma_info->destType);
+ DMA_CTL_SET_DSIZ(reg, dma_info->destPort);
+ }
+
+ __raw_writel(reg, &(dma_base->Ctl));
+
+ __clear_dma_interrupt(dma->channel);
+ unmask_dma_interrupt(dma->channel);
+
+ disable_dma_clk();
+ return 0;
+}
+
+/*!@brief setup interrupt and setup dma channel by dma parameter */
+static inline int __init_dma_channel(mxc_dma_channel_t * chan,
+ mx2_dma_info_t * dma_info)
+{
+ mx2_dma_priv_t *dma_private = (mx2_dma_priv_t *) chan->private;
+ dma_regs_t *dma_base;
+ int ret;
+
+ mask_dma_interrupt(chan->channel);
+ ret =
+ request_irq(dma_private->dma_irq, dma_irq_handler,
+ IRQF_DISABLED | IRQF_SHARED, chan->dev_name,
+ (void *)chan);
+ if (ret) {
+ printk(KERN_ERR
+ "%s: unable to request IRQ %d for DMA channel\n",
+ chan->dev_name, dma_private->dma_irq);
+ return ret;
+ }
+
+ enable_dma_clk();
+
+ dma_base = (dma_regs_t *) (dma_private->dma_base);
+ __raw_writel(0, &(dma_base->Ctl));
+
+ ret = 0;
+ if ((ret = setup_dma_channel(chan, dma_info))) {
+ free_irq(dma_private->dma_irq, (void *)chan);
+ }
+ disable_dma_clk();
+ return 0;
+}
+
+/*!@brief initialize buffer descriptor ring.*/
+static inline void init_dma_bd(mx2_dma_priv_t * private)
+{
+ int i;
+ mx2_dma_bd_t *pbd;
+ private->bd_rd = private->bd_wr = 0;
+ atomic_set(&(private->bd_used), 0);
+ for (i = 0, pbd = private->bd_ring; i < MAX_BD_SIZE; i++, pbd++) {
+ pbd->state = 0;
+ }
+}
+
+/*!@brief add dma buffer into buffer descriptor ring */
+static inline int fill_dma_bd(mxc_dma_channel_t * dma,
+ mxc_dma_requestbuf_t * buf, int num,
+ mxc_dma_mode_t mode)
+{
+ int i, wr;
+ unsigned long flags, mask;
+ mx2_dma_priv_t *priv = dma->private;
+ mx2_dma_bd_t *p, *q;
+
+ if ((atomic_read(&(priv->bd_used)) + num) > MAX_BD_SIZE) {
+ return -EBUSY;
+ }
+
+ for (i = 0; i < num; i++) {
+ wr = priv->bd_wr;
+ p = priv->bd_ring + wr;
+ p->mode = mode;
+ p->count = buf[i].num_of_bytes;
+ p->src_addr = buf[i].src_addr;
+ p->dst_addr = buf[i].dst_addr;
+ if (i == num - 1) {
+ p->state = DMA_BD_ST_LAST | DMA_BD_ST_PEND;
+ } else {
+ p->state = DMA_BD_ST_PEND;
+ }
+ priv->bd_wr = (wr + 1) % MAX_BD_SIZE;
+ atomic_inc(&(priv->bd_used));
+
+ if (atomic_read(&(priv->bd_used)) != 2)
+ continue;
+ /* Disable interrupt of this channel */
+ local_irq_save(flags);
+ local_irq_disable();
+ save_dma_interrupt(mask);
+ mask_dma_interrupt(dma->channel);
+ local_irq_restore(flags);
+ /*TODO ::
+ * If channel is transfering and supports chain_buffer,
+ * when the new buffer is 2st buffer , repeat must be enabled
+ */
+ if (priv->dma_chaining && dma->active) {
+ q = priv->bd_ring + priv->bd_rd;
+ if (q && (q->state & DMA_BD_ST_BUSY)) {
+ if (atomic_read(&(priv->bd_used)) == 2) {
+ setup_dmac(dma);
+ }
+ }
+ }
+ restore_dma_interrupt(mask);
+ }
+ return 0;
+}
+
+/*!@brief add sg-list into buffer descriptor ring */
+static inline int fill_dma_bd_by_sg(mxc_dma_channel_t * dma,
+ struct scatterlist *sg, int num,
+ int real_bytes, mxc_dma_mode_t mode)
+{
+ int i, wr, total_bytes = real_bytes;
+ unsigned long flags, mask;
+ mx2_dma_priv_t *priv = dma->private;
+ mx2_dma_bd_t *p, *q;
+ if ((atomic_read(&(priv->bd_used)) + num) > MAX_BD_SIZE) {
+ return -EBUSY;
+ }
+
+ for (i = 0; i < num && ((real_bytes <= 0) || (total_bytes > 0)); i++) {
+ wr = priv->bd_wr;
+ p = priv->bd_ring + wr;
+ p->mode = mode;
+ if (real_bytes > 0) {
+ if (sg[i].length >= total_bytes) {
+ p->count = total_bytes;
+ } else {
+ p->count = sg[i].length;
+ }
+ total_bytes -= p->count;
+ } else {
+ p->count = sg[i].length;
+ }
+ if (mode == MXC_DMA_MODE_READ) {
+ p->src_addr = priv->dma_info->per_address;
+ p->dst_addr = sg[i].dma_address;
+ } else {
+ p->dst_addr = priv->dma_info->per_address;
+ p->src_addr = sg[i].dma_address;
+ }
+ if ((i == num - 1) || ((real_bytes > 0) && (total_bytes == 0))) {
+ p->state = DMA_BD_ST_LAST | DMA_BD_ST_PEND;
+ } else {
+ p->state = DMA_BD_ST_PEND;
+ }
+ priv->bd_wr = (wr + 1) % MAX_BD_SIZE;
+ atomic_inc(&(priv->bd_used));
+
+ if (atomic_read(&(priv->bd_used)) != 2)
+ continue;
+ /* Disable interrupt of this channel */
+ local_irq_save(flags);
+ local_irq_disable();
+ save_dma_interrupt(mask);
+ mask_dma_interrupt(dma->channel);
+ local_irq_restore(flags);
+ /*TODO ::
+ * If channel is transfering and supports chain_buffer,
+ * when the new buffer is 2st buffer , repeat must be enabled
+ */
+ if (priv->dma_chaining && dma->active) {
+ q = next_dma_bd(priv);
+ if (q && (q->state & DMA_BD_ST_BUSY)) {
+ if ((atomic_read(&(priv->bd_used))) == 2) {
+ setup_dmac(dma);
+ }
+ }
+ }
+ restore_dma_interrupt(mask);
+ }
+ return 0;
+}
+
+/*!@brief select next buffer descripter to transfer.
+ * return 1: need call call-back function. 0: Not need call call-back.
+ * it just is called in ISR
+ */
+static inline int consume_dma_bd(mxc_dma_channel_t * dma, int error)
+{
+ mx2_dma_priv_t *priv = dma->private;
+ mx2_dma_bd_t *p;
+ int notify = 0;
+ if (priv == NULL) {
+ printk(KERN_ERR
+ "request dma channel %d which is not initialize completed.!\n",
+ dma->channel);
+ return 1;
+ }
+ if (error != MXC_DMA_DONE) {
+ for (p = priv->bd_ring + priv->bd_rd;
+ atomic_read(&(priv->bd_used)) > 0;) {
+ priv->bd_rd = (priv->bd_rd + 1) % MAX_BD_SIZE;
+ atomic_dec(&(priv->bd_used));
+ if (p->state & DMA_BD_ST_LAST) {
+ p->state = 0;
+ break;
+ }
+ p->state = 0;
+ }
+ notify = 1;
+ } else {
+ p = priv->bd_ring + priv->bd_rd;
+ priv->bd_rd = (priv->bd_rd + 1) % MAX_BD_SIZE;
+ atomic_dec(&(priv->bd_used));
+ notify = (p->state & DMA_BD_ST_LAST) == DMA_BD_ST_LAST;
+ }
+ if (atomic_read(&(priv->bd_used)) <= 0) {
+ dma->active = 0;
+ atomic_dec(&g_dma_actived);
+ } else {
+ setup_dmac(dma);
+ }
+ return notify;
+}
+
+/*!
+ * This function is generally called by the driver at open time.
+ * The DMA driver would do any initialization steps that is required
+ * to get the channel ready for data transfer.
+ *
+ * @param channel_id a pre-defined id. The peripheral driver would specify
+ * the id associated with its peripheral. This would be
+ * used by the DMA driver to identify the peripheral
+ * requesting DMA and do the necessary setup on the
+ * channel associated with the particular peripheral.
+ * The DMA driver could use static or dynamic DMA channel
+ * allocation.
+ * @param dev_name module name or device name
+ * @return returns a negative number on error if request for a DMA channel did not
+ * succeed, returns the channel number to be used on success.
+ */
+int mxc_dma_request_ext(mxc_dma_device_t channel_id, char *dev_name,
+ struct dma_channel_info *info)
+{
+ mxc_dma_channel_t *dma;
+ mx2_dma_priv_t *dma_private = NULL;
+ mx2_dma_info_t *dma_info = mxc_dma_get_info(channel_id);
+ int index;
+ int ret;
+
+ if (dma_info == NULL) {
+ return -EINVAL;
+ }
+
+ if ((index = get_dma_channel(dma_info->dma_chan)) < 0) {
+ return -ENODEV;
+ }
+
+ dma = g_dma_channels + index;
+ dma_private = (mx2_dma_priv_t *) dma->private;
+ if (dma_private == NULL) {
+ printk(KERN_ERR
+ "request dma channel %d which is not initialize completed.!\n",
+ index);
+ ret = -EFAULT;
+ goto exit;
+ }
+
+ dma->active = 0;
+ dma_private->dma_info = NULL;
+ dma->cb_fn = NULL;
+ dma->cb_args = NULL;
+ dma->dev_name = dev_name;
+ dma->mode = dma_info->mode ? MXC_DMA_MODE_WRITE : MXC_DMA_MODE_READ;
+ init_dma_bd(dma_private);
+
+ if (!(ret = __init_dma_channel(dma, dma_info))) {
+ dma_private->dma_info = dma_info;
+ return index;
+ }
+ exit:
+ put_dma_channel(index);
+ return ret;
+}
+
+/*!
+ * This function is generally called by the driver at close time. The DMA
+ * driver would do any cleanup associated with this channel.
+ *
+ * @param channel_num the channel number returned at request time. This
+ * would be used by the DMA driver to identify the calling
+ * driver and do the necessary cleanup on the channel
+ * associated with the particular peripheral
+ * @return returns a negative number on error or 0 on success
+ */
+int mxc_dma_free(int channel_num)
+{
+ mxc_dma_channel_t *dma;
+ mx2_dma_priv_t *dma_private;
+
+ if ((channel_num >= MAX_DMA_CHANNELS) || (channel_num < 0)) {
+ return -EINVAL;
+ }
+
+ dma = g_dma_channels + channel_num;
+ dma_private = (mx2_dma_priv_t *) dma->private;
+ if (dma_private == NULL) {
+ printk(KERN_ERR
+ "Free dma %d which is not completed initialization \n",
+ channel_num);
+ return -EFAULT;
+ }
+ if (dma->lock) {
+ if (dma->active) { /*Channel is busy */
+ mxc_dma_disable(channel_num);
+ }
+
+ dma_private = (mx2_dma_priv_t *) dma->private;
+
+ enable_dma_clk();
+ mask_dma_interrupt(channel_num);
+ disable_dma_clk();
+
+ free_irq(dma_private->dma_irq, (void *)dma);
+ put_dma_channel(channel_num);
+ }
+ return 0;
+}
+
+/*!
+ * This function would just configure the buffers specified by the user into
+ * dma channel. The caller must call mxc_dma_enable to start this transfer.
+ *
+ * @param channel_num the channel number returned at request time. This
+ * would be used by the DMA driver to identify the calling
+ * driver and do the necessary cleanup on the channel
+ * associated with the particular peripheral
+ * @param dma_buf an array of physical addresses to the user defined
+ * buffers. The caller must guarantee the dma_buf is
+ * available until the transfer is completed.
+ * @param num_buf number of buffers in the array
+ * @param mode specifies whether this is READ or WRITE operation
+ * @return This function returns a negative number on error if buffer could not be
+ * added with DMA for transfer. On Success, it returns 0
+ */
+int mxc_dma_config(int channel_num, mxc_dma_requestbuf_t * dma_buf, int num_buf,
+ mxc_dma_mode_t mode)
+{
+ mxc_dma_channel_t *dma;
+ mx2_dma_priv_t *dma_private;
+
+ if ((dma_buf == NULL) || (num_buf < 1)) {
+ return -EINVAL;
+ }
+
+ if ((channel_num >= MAX_DMA_CHANNELS) || (channel_num < 0)) {
+ return -EINVAL;
+ }
+
+ dma = g_dma_channels + channel_num;
+ dma_private = (mx2_dma_priv_t *) dma->private;
+ if (dma_private == NULL) {
+ printk(KERN_ERR
+ "config dma %d which is not completed initialization \n",
+ channel_num);
+ return -EFAULT;
+ }
+
+ if (dma->lock == 0) {
+ return -ENODEV;
+ }
+
+ /*TODO: dma chainning can not support on bi-dir channel */
+ if (dma_private->dma_chaining && (dma->mode != mode)) {
+ return -EINVAL;
+ }
+
+ /*TODO: fill dma buffer into driver .
+ * If driver is no enought buffer to save them , it will return -EBUSY
+ */
+ if (fill_dma_bd(dma, dma_buf, num_buf, mode)) {
+ return -EBUSY;
+ }
+
+ return 0;
+}
+
+/*!
+ * This function would just configure the scatterlist specified by the
+ * user into dma channel. This is a slight variation of mxc_dma_config(),
+ * it is provided for the convenience of drivers that have a scatterlist
+ * passed into them. It is the calling driver's responsibility to have the
+ * correct physical address filled in the "dma_address" field of the
+ * scatterlist.
+ *
+ * @param channel_num the channel number returned at request time. This
+ * would be used by the DMA driver to identify the calling
+ * driver and do the necessary cleanup on the channel
+ * associated with the particular peripheral
+ * @param sg a scatterlist of buffers. The caller must guarantee
+ * the dma_buf is available until the transfer is
+ * completed.
+ * @param num_buf number of buffers in the array
+ * @param num_of_bytes total number of bytes to transfer. If set to 0, this
+ * would imply to use the length field of the scatterlist
+ * for each DMA transfer. Else it would calculate the size
+ * for each DMA transfer.
+ * @param mode specifies whether this is READ or WRITE operation
+ * @return This function returns a negative number on error if buffer could not
+ * be added with DMA for transfer. On Success, it returns 0
+ */
+int mxc_dma_sg_config(int channel_num, struct scatterlist *sg,
+ int num_buf, int num_of_bytes, mxc_dma_mode_t mode)
+{
+ mxc_dma_channel_t *dma;
+ mx2_dma_priv_t *dma_private;
+
+ if ((sg == NULL) || (num_buf < 1) || (num_of_bytes < 0)) {
+ return -EINVAL;
+ }
+
+ if ((channel_num >= MAX_DMA_CHANNELS) || (channel_num < 0)) {
+ return -EINVAL;
+ }
+
+ dma = g_dma_channels + channel_num;
+ dma_private = (mx2_dma_priv_t *) dma->private;
+ if (dma_private == NULL) {
+ printk(KERN_ERR
+ "config_sg dma %d which is not completed initialization \n",
+ channel_num);
+ return -EFAULT;
+ }
+
+ if (dma->lock == 0) {
+ return -ENODEV;
+ }
+
+ /*TODO: dma chainning can not support on bi-dir channel */
+ if (dma_private->dma_chaining && (dma->mode != mode)) {
+ return -EINVAL;
+ }
+
+ /*TODO: fill dma buffer into driver .
+ * If driver is no enought buffer to save them , it will return -EBUSY
+ */
+ if (fill_dma_bd_by_sg(dma, sg, num_buf, num_of_bytes, mode)) {
+ return -EBUSY;
+ }
+ return 0;
+}
+
+/*!
+ * This function is provided if the driver would like to set/change its
+ * callback function.
+ *
+ * @param channel_num the channel number returned at request time. This
+ * would be used by the DMA driver to identify the calling
+ * driver and do the necessary cleanup on the channel
+ * associated with the particular peripheral
+ * @param callback a callback function to provide notification on transfer
+ * completion, user could specify NULL if he does not wish
+ * to be notified
+ * @param arg an argument that gets passed in to the callback
+ * function, used by the user to do any driver specific
+ * operations.
+ * @return this function returns an error if the callback could not be set
+ * for the channel
+ */
+int mxc_dma_callback_set(int channel_num, mxc_dma_callback_t callback,
+ void *arg)
+{
+ mxc_dma_channel_t *dma;
+
+ if ((channel_num >= MAX_DMA_CHANNELS) || (channel_num < 0)) {
+ return -EINVAL;
+ }
+ dma = g_dma_channels + channel_num;
+
+ if (!dma->lock) {
+ return -ENODEV;
+ }
+
+ if (dma->active) {
+ return -EBUSY;
+ }
+ dma->cb_fn = callback;
+ dma->cb_args = arg;
+ return 0;
+
+}
+
+/*!
+ * This stops the DMA channel and any ongoing transfers. Subsequent use of
+ * mxc_dma_enable() will restart the channel and restart the transfer.
+ *
+ * @param channel_num the channel number returned at request time. This
+ * would be used by the DMA driver to identify the calling
+ * driver and do the necessary cleanup on the channel
+ * associated with the particular peripheral
+ * @return returns a negative number on error or 0 on success
+ */
+int mxc_dma_disable(int channel_num)
+{
+ mxc_dma_channel_t *dma;
+ mx2_dma_priv_t *priv;
+ unsigned long ctrl_val;
+
+ if ((channel_num >= MAX_DMA_CHANNELS) || (channel_num < 0)) {
+ return -EINVAL;
+ }
+
+ dma = g_dma_channels + channel_num;
+
+ if (dma->lock == 0) {
+ return -EINVAL;
+ }
+
+ if (!dma->active) {
+ return -EINVAL;
+ }
+
+ priv = (mx2_dma_priv_t *) dma->private;
+ if (priv == NULL) {
+ printk(KERN_ERR "disable a uncompleted dma channel %d\n",
+ channel_num);
+ return -EFAULT;
+ }
+
+ dma->active = 0;
+ enable_dma_clk();
+
+ __clear_dma_interrupt(channel_num);
+ ctrl_val =
+ __raw_readl(IO_ADDRESS(DMA_BASE_ADDR) + DMA_CCR(channel_num));
+ ctrl_val &= ~DMA_CTL_CEN; /* clear CEN bit */
+ __raw_writel(ctrl_val,
+ IO_ADDRESS(DMA_BASE_ADDR) + DMA_CCR(channel_num));
+ disable_dma_clk();
+ atomic_dec(&g_dma_actived);
+
+ /*TODO: Clear all request buffers */
+ flush_dma_bd(priv);
+ return 0;
+}
+
+/*!
+ * This starts DMA transfer. Or it restarts DMA on a stopped channel
+ * previously stopped with mxc_dma_disable().
+ *
+ * @param channel_num the channel number returned at request time. This
+ * would be used by the DMA driver to identify the calling
+ * driver and do the necessary cleanup on the channel
+ * associated with the particular peripheral
+ * @return returns a negative number on error or 0 on success
+ */
+int mxc_dma_enable(int channel_num)
+{
+ mxc_dma_channel_t *dma;
+ mx2_dma_priv_t *priv;
+
+ if ((channel_num >= MAX_DMA_CHANNELS) || (channel_num < 0)) {
+ return -EINVAL;
+ }
+
+ dma = g_dma_channels + channel_num;
+
+ if (dma->lock == 0) {
+ return -EINVAL;
+ }
+
+ priv = (mx2_dma_priv_t *) dma->private;
+ if (priv == NULL) {
+ printk(KERN_ERR "enable a uncompleted dma channel %d\n",
+ channel_num);
+ return -EFAULT;
+ }
+
+ if (dma->active) {
+ return 0;
+ }
+ dma->active = 1;
+ priv->trans_bytes = 0;
+
+ enable_dma_clk();
+
+ atomic_inc(&g_dma_actived);
+ __clear_dma_interrupt(channel_num);
+
+ setup_dmac(dma);
+ disable_dma_clk();
+ return 0;
+}
+
+/*!
+*@brief Dump DMA registers
+*
+*@param channel Requested channel NO.
+*@return none
+*/
+
+void mxc_dump_dma_register(int channel)
+{
+ mxc_dma_channel_t *dma = &g_dma_channels[channel];
+ mx2_dma_priv_t *priv = (mx2_dma_priv_t *) dma->private;
+ dma_regs_t *dma_base;
+
+ printk(KERN_INFO "======== Dump dma channel %d \n", channel);
+ if ((unsigned)channel >= MXC_DMA_CHANNELS) {
+ printk(KERN_INFO "Channel number is invalid \n");
+ return;
+ }
+ if (!dma->lock) {
+ printk(KERN_INFO "Channel is not allocated \n");
+ return;
+ }
+
+ printk(KERN_INFO "g_dma_actived = %d\n", atomic_read(&g_dma_actived));
+
+ enable_dma_clk();
+ dma_base = (dma_regs_t *) (priv->dma_base);
+ printk(KERN_INFO "DMA COMMON REGISTER\n");
+ printk(KERN_INFO "DMA CONTROL DMA_DCR: %08x\n",
+ __raw_readl(IO_ADDRESS(DMA_BASE_ADDR) + DMA_DCR));
+ printk(KERN_INFO "DMA Interrupt status DMA_DISR: %08x\n",
+ __raw_readl(IO_ADDRESS(DMA_BASE_ADDR) + DMA_DISR));
+ printk(KERN_INFO "DMA Interrupt Mask DMA_DIMR: %08x\n",
+ __raw_readl(IO_ADDRESS(DMA_BASE_ADDR) + DMA_DIMR));
+ printk(KERN_INFO "DMA Burst Time Out DMA_DBTOSR: %08x\n",
+ __raw_readl(IO_ADDRESS(DMA_BASE_ADDR) + DMA_DBTOSR));
+ printk(KERN_INFO "DMA request Time Out DMA_DRTOSR: %08x\n",
+ __raw_readl(IO_ADDRESS(DMA_BASE_ADDR) + DMA_DRTOSR));
+ printk(KERN_INFO "DMA Transfer Error DMA_DSESR: %08x\n",
+ __raw_readl(IO_ADDRESS(DMA_BASE_ADDR) + DMA_DSESR));
+ printk(KERN_INFO "DMA DMA_Overflow DMA_DBOSR: %08x\n",
+ __raw_readl(IO_ADDRESS(DMA_BASE_ADDR) + DMA_DBOSR));
+ printk(KERN_INFO "DMA Burst Time OutCtl DMA_BurstTOCtl: %08x\n",
+ __raw_readl(IO_ADDRESS(DMA_BASE_ADDR) + DMA_DBTOCR));
+
+ printk(KERN_INFO "DMA 2D X size: %08x\n",
+ __raw_readl(IO_ADDRESS(DMA_BASE_ADDR) + DMA_XSRA));
+ printk(KERN_INFO "DMA 2D Y size: %08x\n",
+ __raw_readl(IO_ADDRESS(DMA_BASE_ADDR) + DMA_YSRA));
+ printk(KERN_INFO "DMA 2D Z size: %08x\n",
+ __raw_readl(IO_ADDRESS(DMA_BASE_ADDR) + DMA_WSRA));
+
+ printk(KERN_INFO "DMA Chan %2d Sourc SourceAddr: %08x\n", channel,
+ __raw_readl(&(dma_base->SourceAddr)));
+ printk(KERN_INFO "DMA Chan %2d dest DestAddr: %08x\n", channel,
+ __raw_readl(&(dma_base->DestAddr)));
+ printk(KERN_INFO "DMA Chan %2d count Count: %08x\n", channel,
+ __raw_readl(&(dma_base->Count)));
+ printk(KERN_INFO "DMA Chan %2d Ctl Ctl: %08x\n", channel,
+ __raw_readl(&(dma_base->Ctl)));
+ printk(KERN_INFO "DMA Chan %2d request RequestSource: %08x\n",
+ channel, __raw_readl(&(dma_base->RequestSource)));
+ printk(KERN_INFO "DMA Chan %2d burstL BurstLength: %08x\n", channel,
+ __raw_readl(&(dma_base->BurstLength)));
+ printk(KERN_INFO "DMA Chan %2d requestTO ReqTimeout: %08x\n", channel,
+ __raw_readl(&(dma_base->ReqTimeout)));
+ printk(KERN_INFO "DMA Chan %2d BusUtilt BusUtilt: %08x\n", channel,
+ __raw_readl(&(dma_base->BusUtilt)));
+
+ disable_dma_clk();
+}
+
+#ifdef DMA_PM
+
+static int channel_in_use(void)
+{
+ int i;
+ for (i = 0; i < MXC_DMA_CHANNELS; i++) {
+ if (dma_chan[i].lock)
+ return 1;
+ }
+ return 0;
+}
+
+int mxc_dma_pm_standby(void)
+{
+ unsigned long reg;
+ if (dma_pm_status == DMA_PMST_STANDBY)
+ return 0;
+
+ if (!channel_in_use()) {
+ /*Disable DMA */
+ __disable_dma_clk();
+ dma_pm_status = DMA_PMST_STANDBY;
+ return 0;
+ }
+ return -1;
+}
+
+int mxc_dma_pm_resume(void)
+{
+ unsigned long reg;
+ if (dma_pm_status == DMA_PMST_RESUME)
+ return 0;
+
+ /*Enable HCLK_DMA and DMA(ipg clock) */
+ dma_pm_status = DMA_PMST_RESUME;
+ return 0;
+}
+
+int mxc_dma_pm_suspend(void)
+{
+ unsigned long reg;
+ if (dma_pm_status == DMA_PMST_SUSPEND)
+ return 0;
+
+ if (!channel_in_use()) {
+ /*Disable DMA */
+ __disable_dma_clk();
+ dma_pm_status = DMA_PMST_SUSPEND;
+ return 0;
+ }
+ return -1;
+}
+
+int mxc_dma_pm_handler(struct pm_dev *dev, pm_request_t rqst, void *data)
+{
+ int ret = 0;
+ switch (rqst) {
+ /*APM doesn't send PM_STANDBY and PM_STANDBY_RESUME request now. */
+ case PM_SUSPEND:
+ ret = dma_pm_suspend();
+ break;
+ case PM_RESUME:
+ ret = dma_pm_resume();
+ break;
+ }
+ return ret;
+}
+
+#endif /*DMA_PM */
+
+int __init mxc_dma_init(void)
+{
+ int i;
+ mxc_dma_channel_t *dma = g_dma_channels;
+ mx2_dma_priv_t *private = g_dma_privates;
+
+ memset(dma, 0, sizeof(mxc_dma_channel_t) * MXC_DMA_CHANNELS);
+ for (i = 0; i < MXC_DMA_CHANNELS; i++, dma++, private++) {
+ dma->channel = i;
+ dma->private = private;
+ private->dma_base =
+ (unsigned int)(IO_ADDRESS(DMA_BASE_ADDR + DMA_CH_BASE(i)));
+ private->dma_irq = i + MXC_DMA_INTR_0; /*Dma channel interrupt number */
+ private->bd_ring = &g_dma_bd_table[i][0];
+ }
+
+ mxc_dma_load_info(g_dma_channels);
+
+ dma_clk = clk_get(NULL, "dma_clk");
+ clk_enable(dma_clk);
+
+ __raw_writel(0x2, IO_ADDRESS(DMA_BASE_ADDR) + DMA_DCR); /*reset DMA; */
+
+ disable_dma_clk();
+
+ /*use module init because create_proc after init_dma */
+ g_proc_dir = create_proc_entry("dma", 0, NULL);
+ g_proc_dir->read_proc = (read_proc_t *) mxc_get_dma_list;
+ g_proc_dir->data = NULL;
+
+#ifdef DMA_PM
+ /* Register the device with power management. */
+ dma_pm = pm_register(PM_DMA_DEV, PM_SYS_UNKNOWN, dma_pm_handler);
+#endif
+
+ return 0;
+}
+
+arch_initcall(mxc_dma_init);
+
+EXPORT_SYMBOL(mxc_dma_request_ext);
+EXPORT_SYMBOL(mxc_dma_free);
+EXPORT_SYMBOL(mxc_dma_callback_set);
+EXPORT_SYMBOL(mxc_dma_enable);
+EXPORT_SYMBOL(mxc_dma_disable);
+EXPORT_SYMBOL(mxc_dma_config);
+EXPORT_SYMBOL(mxc_dma_sg_config);
+EXPORT_SYMBOL(mxc_dump_dma_register);
diff --git a/arch/arm/plat-mxc/dptc.c b/arch/arm/plat-mxc/dptc.c
new file mode 100644
index 000000000000..6b7f5599909e
--- /dev/null
+++ b/arch/arm/plat-mxc/dptc.c
@@ -0,0 +1,621 @@
+/*
+ * Copyright 2005-2009 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
+ */
+
+/*!
+ * @file dptc.c
+ *
+ * @brief Driver for the Freescale Semiconductor MXC DPTC module.
+ *
+ * The DPTC driver is designed to control the MXC DPTC hardware.
+ * hardware. Upon initialization, the DPTC driver initializes the DPTC hardware
+ * sets up driver nodes attaches to the DPTC interrupt and initializes internal
+ * data structures. When the DPTC interrupt occurs the driver checks the cause
+ * of the interrupt (lower frequency, increase frequency or emergency) and changes
+ * the CPU voltage according to translation table that is loaded into the driver.
+ * The driver read method is used to read the log buffer.
+ * Driver ioctls are used to change driver parameters and enable/disable the
+ * DVFS operation.
+ *
+ * @ingroup PM
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/jiffies.h>
+#include <linux/device.h>
+#include <linux/delay.h>
+#include <linux/clk.h>
+#include <linux/workqueue.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
+
+#include <mach/clock.h>
+#include <mach/gpio.h>
+#include <mach/hardware.h>
+#include <mach/mxc_dptc.h>
+
+/*
+ * Convenience conversion.
+ * Here atm, maybe there is somewhere better for this.
+ */
+#define mV_to_uV(mV) (mV * 1000)
+#define uV_to_mV(uV) (uV / 1000)
+#define V_to_uV(V) (mV_to_uV(V * 1000))
+#define uV_to_V(uV) (uV_to_mV(uV) / 1000)
+
+enum {
+ DPTC_PTVAI_NOCHANGE = 0x0,
+ DPTC_PTVAI_DECREASE,
+ DPTC_PTVAI_INCREASE,
+ DPTC_PTVAI_EMERG,
+};
+
+struct device *dev_data0;
+struct device *dev_data1;
+
+/*!
+ * In case the MXC device has multiple DPTC modules, this structure is used to
+ * store information specific to each DPTC module.
+ */
+struct dptc_device {
+ /* DPTC delayed work */
+ struct delayed_work dptc_work;
+ /* DPTC spinlock */
+ spinlock_t lock;
+ /* DPTC regulator */
+ struct regulator *dptc_reg;
+ /* DPTC clock */
+ struct clk *dptc_clk;
+ /* DPTC is active flag */
+ int dptc_is_active;
+ /* turbo mode active flag */
+ int turbo_mode_active;
+ /* DPTC current working point */
+ int curr_wp;
+ /* DPTC vai bits */
+ u32 ptvai;
+ /* The interrupt number used by the DPTC device */
+ int irq;
+ /* DPTC platform data pointer */
+ struct mxc_dptc_data *dptc_platform_data;
+};
+
+static void update_dptc_wp(struct dptc_device *drv_data, u32 wp)
+{
+ struct mxc_dptc_data *dptc_data = drv_data->dptc_platform_data;
+ int voltage_uV;
+ int ret = 0;
+
+ voltage_uV = dptc_data->dptc_wp_allfreq[wp].voltage * 1000;
+
+ __raw_writel(dptc_data->dptc_wp_allfreq[wp].dcvr0,
+ dptc_data->dcvr0_reg_addr);
+ __raw_writel(dptc_data->dptc_wp_allfreq[wp].dcvr1,
+ dptc_data->dcvr0_reg_addr + 0x4);
+ __raw_writel(dptc_data->dptc_wp_allfreq[wp].dcvr2,
+ dptc_data->dcvr0_reg_addr + 0x8);
+ __raw_writel(dptc_data->dptc_wp_allfreq[wp].dcvr3,
+ dptc_data->dcvr0_reg_addr + 0xC);
+
+ /* Set the voltage */
+ ret = regulator_set_voltage(drv_data->dptc_reg, voltage_uV, voltage_uV);
+ if (ret < 0)
+ printk(KERN_DEBUG "COULD NOT SET VOLTAGE!!!!!\n");
+
+ pr_debug("dcvr0-3: 0x%x, 0x%x, 0x%x, 0x%x; vol: %d\n",
+ dptc_data->dptc_wp_allfreq[wp].dcvr0,
+ dptc_data->dptc_wp_allfreq[wp].dcvr1,
+ dptc_data->dptc_wp_allfreq[wp].dcvr2,
+ dptc_data->dptc_wp_allfreq[wp].dcvr3,
+ dptc_data->dptc_wp_allfreq[wp].voltage);
+}
+
+static irqreturn_t dptc_irq(int irq, void *dev_id)
+{
+ struct device *dev = dev_id;
+ struct dptc_device *drv_data = dev->driver_data;
+ struct mxc_dptc_data *dptc_data = dev->platform_data;
+ u32 dptccr = __raw_readl(dptc_data->dptccr_reg_addr);
+ u32 gpc_cntr = __raw_readl(dptc_data->gpc_cntr_reg_addr);
+
+ gpc_cntr = (gpc_cntr & dptc_data->dptccr);
+
+ if (gpc_cntr) {
+ drv_data->ptvai =
+ (dptccr & dptc_data->vai_mask) >> dptc_data->vai_offset;
+ pr_debug("dptc_irq: vai = 0x%x (0x%x)!!!!!!!\n",
+ drv_data->ptvai, dptccr);
+
+ /* disable DPTC and mask its interrupt */
+ dptccr = (dptccr & ~(dptc_data->dptc_enable_bit)) |
+ (dptc_data->irq_mask);
+ dptccr = (dptccr & ~(dptc_data->dptc_nvcr_bit));
+ __raw_writel(dptccr, dptc_data->dptccr_reg_addr);
+
+ if (drv_data->turbo_mode_active == 1)
+ schedule_delayed_work(&drv_data->dptc_work, 0);
+ return IRQ_HANDLED;
+ }
+
+ return IRQ_NONE;
+}
+
+static void dptc_workqueue_handler(struct work_struct *work1)
+{
+ struct delayed_work *dptc_work_tmp =
+ container_of(work1, struct delayed_work, work);
+ struct dptc_device *drv_data =
+ container_of(dptc_work_tmp, struct dptc_device, dptc_work);
+ struct mxc_dptc_data *dptc_data = drv_data->dptc_platform_data;
+ u32 dptccr = __raw_readl(dptc_data->dptccr_reg_addr);
+
+ switch (drv_data->ptvai) {
+ case DPTC_PTVAI_DECREASE:
+ drv_data->curr_wp++;
+ break;
+ case DPTC_PTVAI_INCREASE:
+ case DPTC_PTVAI_EMERG:
+ drv_data->curr_wp--;
+ if (drv_data->curr_wp < 0) {
+ /* already max voltage */
+ drv_data->curr_wp = 0;
+ printk(KERN_WARNING "dptc: already maximum voltage\n");
+ }
+ break;
+
+ /* Unknown interrupt cause */
+ default:
+ BUG();
+ }
+
+ if (drv_data->curr_wp > dptc_data->dptc_wp_supported
+ || drv_data->curr_wp < 0) {
+ panic("Can't support this working point: %d\n",
+ drv_data->curr_wp);
+ }
+ update_dptc_wp(drv_data, drv_data->curr_wp);
+
+ /* Enable DPTC and unmask its interrupt */
+ dptccr = (dptccr & ~(dptc_data->irq_mask)) |
+ dptc_data->dptc_nvcr_bit | dptc_data->dptc_enable_bit;
+ __raw_writel(dptccr, dptc_data->dptccr_reg_addr);
+}
+
+/* Start DPTC unconditionally */
+static int start_dptc(struct device *dev)
+{
+ struct mxc_dptc_data *dptc_data = dev->platform_data;
+ struct dptc_device *drv_data = dev->driver_data;
+ u32 dptccr;
+ unsigned long flags;
+ unsigned long clk_rate;
+ int voltage_uV;
+
+ /* Get the voltage */
+ voltage_uV = regulator_get_voltage(drv_data->dptc_reg);
+ drv_data->curr_wp =
+ (dptc_data->dptc_wp_allfreq[0].voltage - (voltage_uV / 1000)) / 25;
+
+ update_dptc_wp(drv_data, drv_data->curr_wp);
+
+ /* Set the voltage */
+ spin_lock_irqsave(&drv_data->lock, flags);
+
+ clk_rate = clk_get_rate(drv_data->dptc_clk);
+
+ if (clk_rate < dptc_data->clk_max_val)
+ goto err;
+
+ if (dptc_data->gpc_irq_bit != 0x0) {
+ /* Enable ARM domain frequency and/or voltage update needed
+ and enable ARM IRQ */
+ __raw_writel(dptc_data->gpc_irq_bit | dptc_data->gpc_adu,
+ dptc_data->gpc_cntr_reg_addr);
+ }
+
+ dptccr = __raw_readl(dptc_data->dptccr_reg_addr);
+
+ /* Enable DPTC and unmask its interrupt */
+ dptccr = ((dptccr & ~(dptc_data->irq_mask)) | dptc_data->enable_config);
+
+ __raw_writel(dptccr, dptc_data->dptccr_reg_addr);
+
+ spin_unlock_irqrestore(&drv_data->lock, flags);
+
+ drv_data->dptc_is_active = 1;
+ drv_data->turbo_mode_active = 1;
+
+ pr_info("DPTC has been started \n");
+
+ return 0;
+
+err:
+ spin_unlock_irqrestore(&drv_data->lock, flags);
+ pr_info("DPTC is not enabled\n");
+ return -1;
+}
+
+/* Stop DPTC unconditionally */
+static void stop_dptc(struct device *dev)
+{
+ struct mxc_dptc_data *dptc_data = dev->platform_data;
+ struct dptc_device *drv_data = dev->driver_data;
+ u32 dptccr;
+
+ dptccr = __raw_readl(dptc_data->dptccr_reg_addr);
+
+ /* disable DPTC and mask its interrupt */
+ dptccr = ((dptccr & ~(dptc_data->dptc_enable_bit)) |
+ dptc_data->irq_mask) & (~dptc_data->dptc_nvcr_bit);
+
+ __raw_writel(dptccr, dptc_data->dptccr_reg_addr);
+
+ /* Restore Turbo Mode voltage to highest wp */
+ update_dptc_wp(drv_data, 0);
+ drv_data->curr_wp = 0;
+
+ regulator_put(drv_data->dptc_reg);
+
+ pr_info("DPTC has been stopped\n");
+}
+
+/*
+ This function does not change the working point. It can be
+ called from an interrupt context.
+*/
+void dptc_suspend(int id)
+{
+ struct mxc_dptc_data *dptc_data;
+ struct dptc_device *drv_data;
+ u32 dptccr;
+
+ switch (id) {
+ case DPTC_GP_ID:
+ dptc_data = dev_data0->platform_data;
+ drv_data = dev_data0->driver_data;
+ break;
+ case DPTC_LP_ID:
+ if (dev_data1 == NULL)
+ return;
+
+ dptc_data = dev_data1->platform_data;
+ drv_data = dev_data1->driver_data;
+ break;
+ /* Unknown DPTC ID */
+ default:
+ return;
+ }
+
+ if (!drv_data->dptc_is_active)
+ return;
+
+ dptccr = __raw_readl(dptc_data->dptccr_reg_addr);
+
+ /* Disable DPTC and mask its interrupt */
+ dptccr = (dptccr & ~(dptc_data->dptc_enable_bit)) | dptc_data->irq_mask;
+
+ __raw_writel(dptccr, dptc_data->dptccr_reg_addr);
+}
+EXPORT_SYMBOL(dptc_suspend);
+
+/*
+ This function does not change the working point. It can be
+ called from an interrupt context.
+*/
+void dptc_resume(int id)
+{
+ struct mxc_dptc_data *dptc_data;
+ struct dptc_device *drv_data;
+ u32 dptccr;
+
+ switch (id) {
+ case DPTC_GP_ID:
+ dptc_data = dev_data0->platform_data;
+ drv_data = dev_data0->driver_data;
+ break;
+ case DPTC_LP_ID:
+ if (dev_data1 == NULL)
+ return;
+
+ dptc_data = dev_data1->platform_data;
+ drv_data = dev_data1->driver_data;
+ break;
+ /* Unknown DPTC ID */
+ default:
+ return;
+ }
+
+ if (!drv_data->dptc_is_active)
+ return;
+
+ __raw_writel(dptc_data->dptc_wp_allfreq[0].dcvr0,
+ dptc_data->dcvr0_reg_addr);
+ __raw_writel(dptc_data->dptc_wp_allfreq[0].dcvr1,
+ dptc_data->dcvr0_reg_addr + 0x4);
+ __raw_writel(dptc_data->dptc_wp_allfreq[0].dcvr2,
+ dptc_data->dcvr0_reg_addr + 0x8);
+ __raw_writel(dptc_data->dptc_wp_allfreq[0].dcvr3,
+ dptc_data->dcvr0_reg_addr + 0xC);
+
+ dptccr = __raw_readl(dptc_data->dptccr_reg_addr);
+
+ /* Enable DPTC and unmask its interrupt */
+ dptccr = (dptccr & ~(dptc_data->irq_mask)) | dptc_data->dptc_enable_bit;
+
+ __raw_writel(dptccr, dptc_data->dptccr_reg_addr);
+}
+EXPORT_SYMBOL(dptc_resume);
+
+/*!
+ * This function is called to put the DPTC in a low power state.
+ *
+ */
+void dptc_disable(struct device *dev)
+{
+ struct dptc_device *drv_data = dev->driver_data;
+
+ if (!(drv_data->dptc_is_active))
+ return;
+
+ stop_dptc(dev);
+ drv_data->dptc_is_active = 0;
+ drv_data->turbo_mode_active = 0;
+}
+
+/*!
+ * This function is called to resume the DPTC from a low power state.
+ *
+ */
+int dptc_enable(struct device *dev)
+{
+ struct dptc_device *drv_data = dev->driver_data;
+
+ if (drv_data->dptc_is_active)
+ return 0;
+
+ return start_dptc(dev);
+}
+
+static ssize_t dptc_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct dptc_device *drv_data = dev->driver_data;
+
+ if (drv_data->dptc_is_active)
+ return sprintf(buf, "DPTC is enabled\n");
+ else
+ return sprintf(buf, "DPTC is disabled\n");
+}
+
+static ssize_t dptc_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ if (strstr(buf, "0") != NULL) {
+ dptc_disable(dev);
+ } else if (strstr(buf, "1") != NULL) {
+ dptc_enable(dev);
+ }
+
+ return size;
+}
+
+static DEVICE_ATTR(enable, 0644, dptc_show, dptc_store);
+
+/*!
+ * This is the probe routine for the DPTC driver.
+ *
+ * @param pdev The platform device structure
+ *
+ * @return The function returns 0 on success
+ *
+ */
+static int __devinit mxc_dptc_probe(struct platform_device *pdev)
+{
+ struct dptc_device *dptc_device_data;
+ int ret = 0;
+ struct resource *res;
+ u32 dptccr = 0;
+ struct clk *ckih_clk;
+ struct mxc_dptc_data *dptc_data = pdev->dev.platform_data;
+
+ if (dptc_data == NULL) {
+ printk(KERN_ERR "DPTC: Pointer to DPTC data is NULL\
+ not started\n");
+ return -1;
+ }
+
+ dptc_device_data = kzalloc(sizeof(struct dptc_device), GFP_KERNEL);
+ if (!dptc_device_data)
+ return -ENOMEM;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (res == NULL) {
+ ret = -ENODEV;
+ goto err1;
+ }
+
+ /*
+ * Request the DPTC interrupt
+ */
+ dptc_device_data->irq = platform_get_irq(pdev, 0);
+ if (dptc_device_data->irq < 0) {
+ ret = dptc_device_data->irq;
+ goto err1;
+ }
+
+ ret =
+ request_irq(dptc_device_data->irq, dptc_irq, IRQF_SHARED,
+ pdev->name, &pdev->dev);
+ if (ret) {
+ printk(KERN_ERR "DPTC: Unable to attach to DPTC interrupt\n");
+ goto err1;
+ }
+
+ dptc_device_data->curr_wp = 0;
+ dptc_device_data->dptc_is_active = 0;
+ dptc_device_data->turbo_mode_active = 0;
+ dptc_device_data->ptvai = 0;
+
+ dptccr = __raw_readl(dptc_data->dptccr_reg_addr);
+
+ printk(KERN_INFO "DPTC mxc_dptc_probe()\n");
+
+ spin_lock_init(&dptc_device_data->lock);
+
+ if (dptc_data->dptc_wp_allfreq == NULL) {
+ ckih_clk = clk_get(NULL, "ckih");
+ if (cpu_is_mx31() &
+ (mxc_cpu_is_rev(CHIP_REV_2_0) < 0) &
+ (clk_get_rate(ckih_clk) == 27000000))
+ printk(KERN_ERR "DPTC: DPTC not supported on TO1.x \
+ & ckih = 27M\n");
+ else
+ printk(KERN_ERR "DPTC: Pointer to DPTC table is NULL\
+ not started\n");
+ goto err1;
+ }
+
+ dptc_device_data->dptc_reg = regulator_get(NULL, dptc_data->reg_id);
+ if (IS_ERR(dptc_device_data->dptc_reg)) {
+ clk_put(dptc_device_data->dptc_clk);
+ printk(KERN_ERR "%s: failed to get regulator\n", __func__);
+ goto err1;
+ }
+
+ INIT_DELAYED_WORK(&dptc_device_data->dptc_work, dptc_workqueue_handler);
+
+ /* Enable Reference Circuits */
+ dptccr = (dptccr & ~(dptc_data->dcr_mask)) | dptc_data->init_config;
+ __raw_writel(dptccr, dptc_data->dptccr_reg_addr);
+
+ ret = sysfs_create_file(&pdev->dev.kobj, &dev_attr_enable.attr);
+ if (ret) {
+ printk(KERN_ERR
+ "DPTC: Unable to register sysdev entry for dptc");
+ goto err1;
+ }
+
+ if (ret != 0) {
+ printk(KERN_ERR "DPTC: Unable to start");
+ goto err1;
+ }
+
+ dptc_device_data->dptc_clk = clk_get(NULL, dptc_data->clk_id);
+
+ if (pdev->id == 0)
+ dev_data0 = &pdev->dev;
+ else
+ dev_data1 = &pdev->dev;
+
+ dptc_device_data->dptc_platform_data = pdev->dev.platform_data;
+
+ /* Set driver data */
+ platform_set_drvdata(pdev, dptc_device_data);
+
+ return 0;
+
+err1:
+ dev_err(&pdev->dev, "Failed to probe DPTC\n");
+ kfree(dptc_device_data);
+ return ret;
+}
+
+/*!
+ * This function is called to put DPTC in a low power state.
+ *
+ * @param pdev the device structure
+ * @param state the power state the device is entering
+ *
+ * @return The function always returns 0.
+ */
+static int mxc_dptc_suspend(struct platform_device *pdev, pm_message_t state)
+{
+ struct dptc_device *drv_data = pdev->dev.driver_data;
+
+ if (drv_data->dptc_is_active)
+ stop_dptc(&pdev->dev);
+
+ return 0;
+}
+
+/*!
+ * This function is called to resume the MU from a low power state.
+ *
+ * @param dev the device structure
+ * @param level the stage in device suspension process that we want the
+ * device to be put in
+ *
+ * @return The function always returns 0.
+ */
+static int mxc_dptc_resume(struct platform_device *pdev)
+{
+ struct dptc_device *drv_data = pdev->dev.driver_data;
+
+ if (drv_data->dptc_is_active)
+ return start_dptc(&pdev->dev);
+
+ return 0;
+}
+
+static struct platform_driver mxc_dptc_driver = {
+ .driver = {
+ .name = "mxc_dptc",
+ .owner = THIS_MODULE,
+ },
+ .probe = mxc_dptc_probe,
+ .suspend = mxc_dptc_suspend,
+ .resume = mxc_dptc_resume,
+};
+
+/*!
+ * This function is called to resume the MU from a low power state.
+ *
+ * @param dev the device structure used to give information on which MU
+ * device (0 through 3 channels) to suspend
+ * @param level the stage in device suspension process that we want the
+ * device to be put in
+ *
+ * @return The function always returns 0.
+ */
+
+static int __init dptc_init(void)
+{
+ if (platform_driver_register(&mxc_dptc_driver) != 0) {
+ printk(KERN_ERR "mxc_dptc_driver register failed\n");
+ return -ENODEV;
+ }
+
+ printk(KERN_INFO "DPTC driver module loaded\n");
+
+ return 0;
+}
+
+static void __exit dptc_cleanup(void)
+{
+ /* Unregister the device structure */
+ platform_driver_unregister(&mxc_dptc_driver);
+
+ printk("DPTC driver module unloaded\n");
+}
+
+module_init(dptc_init);
+module_exit(dptc_cleanup);
+
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_DESCRIPTION("DPTC driver");
+MODULE_LICENSE("GPL");
diff --git a/arch/arm/plat-mxc/dvfs_core.c b/arch/arm/plat-mxc/dvfs_core.c
new file mode 100644
index 000000000000..d14bac145344
--- /dev/null
+++ b/arch/arm/plat-mxc/dvfs_core.c
@@ -0,0 +1,802 @@
+/*
+ * Copyright 2008-2009 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
+ */
+
+/*!
+ * @file dvfs_core.c
+ *
+ * @brief A simplied driver for the Freescale Semiconductor MXC DVFS module.
+ *
+ * Upon initialization, the DVFS driver initializes the DVFS hardware
+ * sets up driver nodes attaches to the DVFS interrupt and initializes internal
+ * data structures. When the DVFS interrupt occurs the driver checks the cause
+ * of the interrupt (lower frequency, increase frequency or emergency) and
+ * changes the CPU voltage according to translation table that is loaded into
+ * the driver.
+ *
+ * @ingroup PM
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/fs.h>
+#include <linux/interrupt.h>
+#include <linux/jiffies.h>
+#include <linux/device.h>
+#include <linux/sysdev.h>
+#include <linux/delay.h>
+#include <linux/clk.h>
+#include <linux/regulator/consumer.h>
+#include <linux/input.h>
+#include <linux/platform_device.h>
+#include <linux/cpufreq.h>
+#include <mach/hardware.h>
+#include <mach/mxc_dvfs.h>
+
+#define MXC_DVFSTHRS_UPTHR_MASK 0x0FC00000
+#define MXC_DVFSTHRS_UPTHR_OFFSET 22
+#define MXC_DVFSTHRS_DNTHR_MASK 0x003F0000
+#define MXC_DVFSTHRS_DNTHR_OFFSET 16
+#define MXC_DVFSTHRS_PNCTHR_MASK 0x0000003F
+#define MXC_DVFSTHRS_PNCTHR_OFFSET 0
+
+#define MXC_DVFSCOUN_DNCNT_MASK 0x00FF0000
+#define MXC_DVFSCOUN_DNCNT_OFFSET 16
+#define MXC_DVFSCOUN_UPCNT_MASK 0x000000FF
+#define MXC_DVFSCOUN_UPCNT_OFFSET 0
+
+#define MXC_DVFSEMAC_EMAC_MASK 0x000001FF
+#define MXC_DVFSEMAC_EMAC_OFFSET 0
+
+#define MXC_DVFSCNTR_DVFEV 0x10000000
+#define MXC_DVFSCNTR_LBMI 0x08000000
+#define MXC_DVFSCNTR_LBFL 0x06000000
+#define MXC_DVFSCNTR_DVFIS 0x01000000
+#define MXC_DVFSCNTR_FSVAIM 0x00400000
+#define MXC_DVFSCNTR_FSVAI_MASK 0x00300000
+#define MXC_DVFSCNTR_FSVAI_OFFSET 20
+#define MXC_DVFSCNTR_WFIM 0x00080000
+#define MXC_DVFSCNTR_WFIM_OFFSET 19
+#define MXC_DVFSCNTR_MAXF_MASK 0x00040000
+#define MXC_DVFSCNTR_MAXF_OFFSET 18
+#define MXC_DVFSCNTR_MINF_MASK 0x00020000
+#define MXC_DVFSCNTR_MINF_OFFSET 17
+#define MXC_DVFSCNTR_LTBRSR_MASK 0x00000018
+#define MXC_DVFSCNTR_LTBRSR_OFFSET 3
+#define MXC_DVFSCNTR_DVFEN 0x00000001
+
+#define MXC_GPCCNTR_GPCIRQ 0x00100000
+#define MXC_GPCCNTR_DVFS0CR 0x00010000
+#define MXC_GPCCNTR_ADU 0x00008000
+#define MXC_GPCCNTR_STRT 0x00004000
+#define MXC_GPCCNTR_FUPD 0x00002000
+#define MXC_GPCCNTR_HTRI_MASK 0x0000000F
+#define MXC_GPCCNTR_HTRI_OFFSET 0
+#define MXC_GPCCNTR_GPCIRQM 0x00200000
+
+#define MXC_GPCVCR_VINC_MASK 0x00020000
+#define MXC_GPCVCR_VINC_OFFSET 17
+#define MXC_GPCVCR_VCNTU_MASK 0x00010000
+#define MXC_GPCVCR_VCNTU_OFFSET 16
+#define MXC_GPCVCR_VCNT_MASK 0x00007FFF
+#define MXC_GPCVCR_VCNT_OFFSET 0
+
+extern void setup_pll(void);
+static struct delayed_work dvfs_core_work;
+static struct mxc_dvfs_platform_data *dvfs_data;
+static struct device *dvfs_dev;
+static struct cpu_wp *cpu_wp_tbl;
+int dvfs_core_resume;
+int curr_wp;
+int old_wp;
+int dvfs_core_is_active;
+int cpufreq_trig_needed;
+struct timeval core_prev_intr;
+
+/*
+ * Clock structures
+ */
+static struct clk *pll1_sw_clk;
+static struct clk *cpu_clk;
+static struct clk *dvfs_clk;
+static struct regulator *core_regulator;
+
+extern int cpu_wp_nr;
+#ifdef CONFIG_ARCH_MX51
+extern struct cpu_wp *(*get_cpu_wp)(int *wp);
+#endif
+
+enum {
+ FSVAI_FREQ_NOCHANGE = 0x0,
+ FSVAI_FREQ_INCREASE,
+ FSVAI_FREQ_DECREASE,
+ FSVAI_FREQ_EMERG,
+};
+
+/*
+ * Load tracking buffer source: 1 for ld_add; 0 for pre_ld_add; 2 for after EMA
+ */
+#define DVFS_LTBRSR (2 << MXC_DVFSCNTR_LTBRSR_OFFSET)
+
+extern struct dvfs_wp dvfs_core_setpoint[2];
+extern int low_bus_freq_mode;
+extern int high_bus_freq_mode;
+extern int set_low_bus_freq(void);
+extern int set_high_bus_freq(int high_bus_speed);
+extern int low_freq_bus_used(void);
+extern void propagate_rate(struct clk *tclk);
+
+DEFINE_SPINLOCK(mxc_dvfs_core_lock);
+
+void dvfs_core_set_bus_freq(void)
+{
+ u32 reg;
+ int low_freq_bus_ready = 0;
+
+ /* Mask DVFS irq */
+ reg = __raw_readl(dvfs_data->dvfs_cntr_reg_addr);
+ /* FSVAIM=1 */
+ reg |= MXC_DVFSCNTR_FSVAIM;
+ __raw_writel(reg, dvfs_data->dvfs_cntr_reg_addr);
+
+ low_freq_bus_ready = low_freq_bus_used();
+
+ if ((curr_wp == cpu_wp_nr - 1) && (!low_bus_freq_mode)
+ && (low_freq_bus_ready))
+ set_low_bus_freq();
+ else if (!low_freq_bus_ready)
+ set_high_bus_freq(0);
+ /* Enable DVFS interrupt */
+ /* FSVAIM=0 */
+ reg = (reg & ~MXC_DVFSCNTR_FSVAIM);
+ /* LBFL=1 */
+ reg = (reg & ~MXC_DVFSCNTR_LBFL);
+ reg |= MXC_DVFSCNTR_LBFL;
+ __raw_writel(reg, dvfs_data->dvfs_cntr_reg_addr);
+}
+
+static void dvfs_load_config(int set_point)
+{
+ u32 reg;
+ reg = 0;
+
+ reg |= dvfs_core_setpoint[set_point].upthr << MXC_DVFSTHRS_UPTHR_OFFSET;
+ reg |= dvfs_core_setpoint[set_point].downthr <<
+ MXC_DVFSTHRS_DNTHR_OFFSET;
+ reg |= dvfs_core_setpoint[set_point].panicthr;
+ __raw_writel(reg, dvfs_data->dvfs_thrs_reg_addr);
+
+ reg = 0;
+ reg |= dvfs_core_setpoint[set_point].downcnt <<
+ MXC_DVFSCOUN_DNCNT_OFFSET;
+ reg |= dvfs_core_setpoint[set_point].upcnt << MXC_DVFSCOUN_UPCNT_OFFSET;
+ __raw_writel(reg, dvfs_data->dvfs_coun_reg_addr);
+}
+
+static int set_cpu_freq(int wp)
+{
+ int arm_podf;
+ int podf;
+ int vinc = 0;
+ int ret = 0;
+ int org_cpu_rate;
+ unsigned long rate = 0;
+ int gp_volt = 0;
+ u32 reg;
+ u32 reg1;
+
+ if (cpu_wp_tbl[wp].pll_rate != cpu_wp_tbl[old_wp].pll_rate) {
+ /* PLL_RELOCK, set ARM_FREQ_SHIFT_DIVIDER */
+ reg = __raw_readl(dvfs_data->ccm_cdcr_reg_addr);
+ reg &= 0xFFFFFFFB;
+ __raw_writel(reg, dvfs_data->ccm_cdcr_reg_addr);
+ org_cpu_rate = clk_get_rate(cpu_clk);
+ rate = cpu_wp_tbl[wp].cpu_rate;
+
+ if (org_cpu_rate == rate)
+ return ret;
+
+ gp_volt = cpu_wp_tbl[wp].cpu_voltage;
+
+ if (gp_volt == 0)
+ return ret;
+
+ /*Set the voltage for the GP domain. */
+ if (rate > org_cpu_rate) {
+ ret = regulator_set_voltage(core_regulator, gp_volt,
+ gp_volt);
+ if (ret < 0) {
+ printk(KERN_DEBUG "COULD NOT SET GP VOLTAGE\n");
+ return ret;
+ }
+ udelay(dvfs_data->delay_time);
+ }
+
+ setup_pll();
+ /* START the GPC main control FSM */
+ /* set VINC */
+ reg = __raw_readl(dvfs_data->gpc_vcr_reg_addr);
+ reg &= ~(MXC_GPCVCR_VINC_MASK | MXC_GPCVCR_VCNTU_MASK |
+ MXC_GPCVCR_VCNT_MASK);
+
+ if (rate > org_cpu_rate)
+ reg |= 1 << MXC_GPCVCR_VINC_OFFSET;
+
+ reg |= (1 << MXC_GPCVCR_VCNTU_OFFSET) |
+ (100 << MXC_GPCVCR_VCNT_OFFSET);
+ __raw_writel(reg, dvfs_data->gpc_vcr_reg_addr);
+
+ reg = __raw_readl(dvfs_data->gpc_cntr_reg_addr);
+ reg |= MXC_GPCCNTR_FUPD;
+ reg |= MXC_GPCCNTR_ADU;
+ __raw_writel(reg, dvfs_data->gpc_cntr_reg_addr);
+
+ reg |= MXC_GPCCNTR_STRT;
+ __raw_writel(reg, dvfs_data->gpc_cntr_reg_addr);
+ while (__raw_readl(dvfs_data->gpc_cntr_reg_addr) & 0x4000)
+ udelay(10);
+
+ if (rate < org_cpu_rate) {
+ ret = regulator_set_voltage(core_regulator,
+ gp_volt, gp_volt);
+ if (ret < 0) {
+ printk(KERN_DEBUG
+ "COULD NOT SET GP VOLTAGE!!!!\n");
+ return ret;
+ }
+ old_wp = wp;
+ }
+
+ clk_set_rate(cpu_clk, rate);
+ } else {
+ podf = cpu_wp_tbl[wp].cpu_podf;
+ gp_volt = cpu_wp_tbl[wp].cpu_voltage;
+
+ /* Change arm_podf only */
+ /* set ARM_FREQ_SHIFT_DIVIDER */
+ reg = __raw_readl(dvfs_data->ccm_cdcr_reg_addr);
+ reg &= 0xFFFFFFFB;
+ reg |= 1 << 2;
+ __raw_writel(reg, dvfs_data->ccm_cdcr_reg_addr);
+
+ /* Get ARM_PODF */
+ reg = __raw_readl(dvfs_data->ccm_cacrr_reg_addr);
+ arm_podf = reg & 0x07;
+ if (podf == arm_podf) {
+ printk(KERN_DEBUG
+ "No need to change freq and voltage!!!!\n");
+ return 0;
+ }
+
+ /* Check if FSVAI indicate freq up */
+ if (podf < arm_podf) {
+ ret = regulator_set_voltage(core_regulator,
+ gp_volt, gp_volt);
+ if (ret < 0) {
+ printk(KERN_DEBUG
+ "COULD NOT SET GP VOLTAGE!!!!\n");
+ return 0;
+ }
+ udelay(dvfs_data->delay_time);
+ vinc = 1;
+ dvfs_load_config(0);
+ } else {
+ vinc = 0;
+ dvfs_load_config(1);
+ }
+
+ arm_podf = podf;
+ /* Set ARM_PODF */
+ reg &= 0xFFFFFFF8;
+ reg |= arm_podf;
+
+ reg1 = __raw_readl(dvfs_data->ccm_cdhipr_reg_addr);
+ if ((reg1 & 0x00010000) == 0)
+ __raw_writel(reg, dvfs_data->ccm_cacrr_reg_addr);
+ else {
+ printk(KERN_DEBUG "ARM_PODF still in busy!!!!\n");
+ return 0;
+ }
+
+ /* START the GPC main control FSM */
+ reg = __raw_readl(dvfs_data->gpc_cntr_reg_addr);
+ reg |= MXC_GPCCNTR_FUPD;
+ /* ADU=1, select ARM domain */
+ reg |= MXC_GPCCNTR_ADU;
+ __raw_writel(reg, dvfs_data->gpc_cntr_reg_addr);
+ /* set VINC */
+ reg = __raw_readl(dvfs_data->gpc_vcr_reg_addr);
+ reg &=
+ ~(MXC_GPCVCR_VINC_MASK | MXC_GPCVCR_VCNTU_MASK |
+ MXC_GPCVCR_VCNT_MASK);
+ reg |= (1 << MXC_GPCVCR_VCNTU_OFFSET) |
+ (100 << MXC_GPCVCR_VCNT_OFFSET) |
+ (vinc << MXC_GPCVCR_VINC_OFFSET);
+ __raw_writel(reg, dvfs_data->gpc_vcr_reg_addr);
+
+ reg = __raw_readl(dvfs_data->gpc_cntr_reg_addr);
+ reg &= (~(MXC_GPCCNTR_ADU | MXC_GPCCNTR_FUPD));
+ reg |= MXC_GPCCNTR_ADU | MXC_GPCCNTR_FUPD | MXC_GPCCNTR_STRT;
+ __raw_writel(reg, dvfs_data->gpc_cntr_reg_addr);
+
+ /* Wait for arm podf Enable */
+ while ((__raw_readl(dvfs_data->gpc_cntr_reg_addr) &
+ MXC_GPCCNTR_STRT) == MXC_GPCCNTR_STRT) {
+ printk(KERN_DEBUG "Waiting arm_podf enabled!\n");
+ udelay(10);
+ }
+
+ if (vinc == 0) {
+ ret = regulator_set_voltage(core_regulator,
+ gp_volt, gp_volt);
+ if (ret < 0) {
+ printk(KERN_DEBUG
+ "COULD NOT SET GP VOLTAGE!!!!\n");
+ return ret;
+ }
+ udelay(dvfs_data->delay_time);
+ }
+
+ propagate_rate(pll1_sw_clk);
+#if defined(CONFIG_CPU_FREQ)
+ cpufreq_trig_needed = 1;
+#endif
+ old_wp = wp;
+ }
+
+ return ret;
+}
+
+static int start_dvfs(void)
+{
+ u32 reg;
+ unsigned long flags;
+
+ if (dvfs_core_is_active)
+ return 0;
+
+ spin_lock_irqsave(&mxc_dvfs_core_lock, flags);
+
+ clk_enable(dvfs_clk);
+
+ /* config reg GPC_CNTR */
+ reg = __raw_readl(dvfs_data->gpc_cntr_reg_addr);
+
+ /* GPCIRQ=1, select ARM IRQ */
+ reg |= MXC_GPCCNTR_GPCIRQ;
+ /* ADU=1, select ARM domain */
+ reg |= MXC_GPCCNTR_ADU;
+ __raw_writel(reg, dvfs_data->gpc_cntr_reg_addr);
+
+ /* Set PREDIV bits */
+ reg = __raw_readl(dvfs_data->dvfs_cntr_reg_addr);
+ reg = (reg & ~(dvfs_data->prediv_mask));
+ reg |= (dvfs_data->prediv_val) << (dvfs_data->prediv_offset);
+ __raw_writel(reg, dvfs_data->dvfs_cntr_reg_addr);
+
+ /* Enable DVFS interrupt */
+ reg = __raw_readl(dvfs_data->dvfs_cntr_reg_addr);
+ /* FSVAIM=0 */
+ reg = (reg & ~MXC_DVFSCNTR_FSVAIM);
+ /* Set MAXF, MINF */
+ reg = (reg & ~(MXC_DVFSCNTR_MAXF_MASK | MXC_DVFSCNTR_MINF_MASK));
+ reg |= 1 << MXC_DVFSCNTR_MAXF_OFFSET;
+ /* Select ARM domain */
+ reg |= MXC_DVFSCNTR_DVFIS;
+ /* Enable DVFS frequency adjustment interrupt */
+ reg = (reg & ~MXC_DVFSCNTR_FSVAIM);
+ /* Set load tracking buffer register source */
+ reg = (reg & ~MXC_DVFSCNTR_LTBRSR_MASK);
+ reg |= DVFS_LTBRSR;
+ /* Set DIV3CK */
+ reg = (reg & ~(dvfs_data->div3ck_mask));
+ reg |= (dvfs_data->div3ck_val) << (dvfs_data->div3ck_offset);
+ /* Enable DVFS */
+ reg |= MXC_DVFSCNTR_DVFEN;
+ __raw_writel(reg, dvfs_data->dvfs_cntr_reg_addr);
+
+ dvfs_core_is_active = 1;
+
+ spin_unlock_irqrestore(&mxc_dvfs_core_lock, flags);
+
+ printk(KERN_DEBUG "DVFS is started\n");
+
+ return 0;
+}
+
+/*!
+ * This function is called for module initialization.
+ * It sets up the DVFS hardware.
+ * It sets default values for DVFS thresholds and counters. The default
+ * values was chosen from a set of different reasonable values. They was tested
+ * and the default values in the driver gave the best results.
+ * More work should be done to find optimal values.
+ *
+ * @return 0 if successful; non-zero otherwise.
+ *
+ */
+static int init_dvfs_controller(void)
+{
+ /* DVFS loading config */
+ dvfs_load_config(0);
+
+ /* Set EMAC value */
+ __raw_writel((dvfs_data->emac_val << MXC_DVFSEMAC_EMAC_OFFSET),
+ dvfs_data->dvfs_emac_reg_addr);
+
+ return 0;
+}
+
+static irqreturn_t dvfs_irq(int irq, void *dev_id)
+{
+ u32 reg;
+
+ /* Check if DVFS0 (ARM) id requesting for freqency/voltage update */
+ if ((__raw_readl(dvfs_data->gpc_cntr_reg_addr) & MXC_GPCCNTR_DVFS0CR) ==
+ 0)
+ return IRQ_NONE;
+
+ /* Mask DVFS irq */
+ reg = __raw_readl(dvfs_data->dvfs_cntr_reg_addr);
+ /* FSVAIM=1 */
+ reg |= MXC_DVFSCNTR_FSVAIM;
+ __raw_writel(reg, dvfs_data->dvfs_cntr_reg_addr);
+
+ /* Mask GPC1 irq */
+ reg = __raw_readl(dvfs_data->gpc_cntr_reg_addr);
+ reg |= MXC_GPCCNTR_GPCIRQM | 0x1000000;
+ __raw_writel(reg, dvfs_data->gpc_cntr_reg_addr);
+
+ schedule_delayed_work(&dvfs_core_work, 0);
+
+ return IRQ_HANDLED;
+}
+
+static void dvfs_core_workqueue_handler(struct work_struct *work)
+{
+ u32 fsvai;
+ u32 reg;
+ u32 curr_cpu;
+ int ret = 0;
+ int maxf = 0, minf = 0;
+ int low_freq_bus_ready = 0;
+
+ /* Check DVFS frequency adjustment interrupt status */
+ reg = __raw_readl(dvfs_data->dvfs_cntr_reg_addr);
+ fsvai = (reg & MXC_DVFSCNTR_FSVAI_MASK) >> MXC_DVFSCNTR_FSVAI_OFFSET;
+
+ /* Check FSVAI, FSVAI=0 is error */
+ if (fsvai == FSVAI_FREQ_NOCHANGE) {
+ /* Do nothing. Freq change is not required */
+ goto END;
+ }
+
+ curr_cpu = clk_get_rate(cpu_clk);
+
+ /* If FSVAI indicate freq down,
+ check arm-clk is not in lowest frequency 200 MHz */
+ if (fsvai == FSVAI_FREQ_DECREASE) {
+ if (curr_cpu == cpu_wp_tbl[cpu_wp_nr - 1].cpu_rate) {
+ minf = 1;
+ goto END;
+ } else {
+ /* freq down */
+ curr_wp++;
+ if (curr_wp >= cpu_wp_nr) {
+ curr_wp = cpu_wp_nr - 1;
+ goto END;
+ }
+
+ if (curr_wp == cpu_wp_nr - 1)
+ minf = 1;
+ }
+ } else {
+ if (curr_cpu == cpu_wp_tbl[0].cpu_rate) {
+ maxf = 1;
+ goto END;
+ } else {
+ /* freq up */
+ curr_wp = 0;
+ maxf = 1;
+ }
+ }
+
+ low_freq_bus_ready = low_freq_bus_used();
+ if ((curr_wp == cpu_wp_nr - 1) && (!low_bus_freq_mode)
+ && (low_freq_bus_ready)) {
+ ret = set_cpu_freq(curr_wp);
+ set_low_bus_freq();
+ } else {
+ set_high_bus_freq(0);
+ ret = set_cpu_freq(curr_wp);
+ }
+
+#if defined(CONFIG_CPU_FREQ)
+ if (cpufreq_trig_needed == 1) {
+ cpufreq_trig_needed = 0;
+ cpufreq_update_policy(0);
+ }
+#endif
+
+END: /* Set MAXF, MINF */
+ reg = __raw_readl(dvfs_data->dvfs_cntr_reg_addr);
+ reg = (reg & ~(MXC_DVFSCNTR_MAXF_MASK | MXC_DVFSCNTR_MINF_MASK));
+ reg |= maxf << MXC_DVFSCNTR_MAXF_OFFSET;
+ reg |= minf << MXC_DVFSCNTR_MINF_OFFSET;
+
+ /* Enable DVFS interrupt */
+ /* FSVAIM=0 */
+ reg = (reg & ~MXC_DVFSCNTR_FSVAIM);
+ reg |= FSVAI_FREQ_NOCHANGE;
+ /* LBFL=1 */
+ reg = (reg & ~MXC_DVFSCNTR_LBFL);
+ reg |= MXC_DVFSCNTR_LBFL;
+ __raw_writel(reg, dvfs_data->dvfs_cntr_reg_addr);
+ /*Unmask GPC1 IRQ */
+ reg = __raw_readl(dvfs_data->gpc_cntr_reg_addr);
+ reg &= ~MXC_GPCCNTR_GPCIRQM;
+ __raw_writel(reg, dvfs_data->gpc_cntr_reg_addr);
+}
+
+/*!
+ * This function disables the DVFS module.
+ */
+static void stop_dvfs(void)
+{
+ u32 reg = 0;
+ unsigned long flags;
+ u32 curr_cpu;
+
+ if (dvfs_core_is_active) {
+ spin_lock_irqsave(&mxc_dvfs_core_lock, flags);
+
+ /* Mask dvfs irq, disable DVFS */
+ reg = __raw_readl(dvfs_data->dvfs_cntr_reg_addr);
+ /* FSVAIM=1 */
+ reg |= MXC_DVFSCNTR_FSVAIM;
+ __raw_writel(reg, dvfs_data->dvfs_cntr_reg_addr);
+
+ dvfs_core_is_active = 0;
+ spin_unlock_irqrestore(&mxc_dvfs_core_lock, flags);
+
+ curr_wp = 0;
+ if (!high_bus_freq_mode)
+ set_high_bus_freq(1);
+
+ curr_cpu = clk_get_rate(cpu_clk);
+ if (curr_cpu != cpu_wp_tbl[curr_wp].cpu_rate) {
+ set_cpu_freq(curr_wp);
+ /* disable DVFS */
+ reg = __raw_readl(dvfs_data->dvfs_cntr_reg_addr);
+ reg = (reg & ~MXC_DVFSCNTR_DVFEN);
+ __raw_writel(reg, dvfs_data->dvfs_cntr_reg_addr);
+#if defined(CONFIG_CPU_FREQ)
+ if (cpufreq_trig_needed == 1) {
+ cpufreq_trig_needed = 0;
+ cpufreq_update_policy(0);
+ }
+#endif
+ }
+
+ clk_disable(dvfs_clk);
+ }
+
+ printk(KERN_DEBUG "DVFS is stopped\n");
+}
+
+static ssize_t dvfs_enable_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ if (dvfs_core_is_active)
+ return sprintf(buf, "DVFS is enabled\n");
+ else
+ return sprintf(buf, "DVFS is disabled\n");
+}
+
+static ssize_t dvfs_enable_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ if (strstr(buf, "1") != NULL) {
+ if (start_dvfs() != 0)
+ printk(KERN_ERR "Failed to start DVFS\n");
+ } else if (strstr(buf, "0") != NULL)
+ stop_dvfs();
+
+ return size;
+}
+
+static DEVICE_ATTR(enable, 0644, dvfs_enable_show, dvfs_enable_store);
+
+/*!
+ * This is the probe routine for the DVFS driver.
+ *
+ * @param pdev The platform device structure
+ *
+ * @return The function returns 0 on success
+ */
+static int __devinit mxc_dvfs_core_probe(struct platform_device *pdev)
+{
+ int err = 0;
+ struct resource *res;
+ int irq;
+
+ printk(KERN_INFO "mxc_dvfs_core_probe\n");
+ dvfs_dev = &pdev->dev;
+ dvfs_data = pdev->dev.platform_data;
+
+ INIT_DELAYED_WORK(&dvfs_core_work, dvfs_core_workqueue_handler);
+
+ pll1_sw_clk = clk_get(NULL, "pll1_sw_clk");
+ if (IS_ERR(pll1_sw_clk)) {
+ printk(KERN_INFO "%s: failed to get pll1_sw_clk\n", __func__);
+ return PTR_ERR(pll1_sw_clk);
+ }
+
+ cpu_clk = clk_get(NULL, dvfs_data->clk1_id);
+ if (IS_ERR(cpu_clk)) {
+ printk(KERN_ERR "%s: failed to get cpu clock\n", __func__);
+ return PTR_ERR(cpu_clk);
+ }
+
+ dvfs_clk = clk_get(NULL, dvfs_data->clk2_id);
+ if (IS_ERR(dvfs_clk)) {
+ printk(KERN_ERR "%s: failed to get dvfs clock\n", __func__);
+ return PTR_ERR(dvfs_clk);
+ }
+
+ core_regulator = regulator_get(NULL, dvfs_data->reg_id);
+ if (IS_ERR(core_regulator)) {
+ clk_put(cpu_clk);
+ clk_put(dvfs_clk);
+ printk(KERN_ERR "%s: failed to get gp regulator\n", __func__);
+ return PTR_ERR(core_regulator);
+ }
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (res == NULL) {
+ err = -ENODEV;
+ goto err1;
+ }
+
+ /*
+ * Request the DVFS interrupt
+ */
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0) {
+ err = irq;
+ goto err1;
+ }
+
+ /* request the DVFS interrupt */
+ err = request_irq(irq, dvfs_irq, IRQF_SHARED, "dvfs", dvfs_dev);
+ if (err)
+ printk(KERN_ERR
+ "DVFS: Unable to attach to DVFS interrupt,err = %d",
+ err);
+
+ clk_enable(dvfs_clk);
+ err = init_dvfs_controller();
+ if (err) {
+ printk(KERN_ERR "DVFS: Unable to initialize DVFS");
+ return err;
+ }
+ clk_disable(dvfs_clk);
+
+ err = sysfs_create_file(&dvfs_dev->kobj, &dev_attr_enable.attr);
+ if (err) {
+ printk(KERN_ERR
+ "DVFS: Unable to register sysdev entry for DVFS");
+ return err;
+ }
+
+ /* Set the current working point. */
+ cpu_wp_tbl = get_cpu_wp(&cpu_wp_nr);
+ old_wp = 0;
+ curr_wp = 0;
+ dvfs_core_resume = 0;
+ cpufreq_trig_needed = 0;
+
+ return err;
+
+err1:
+ dev_err(&pdev->dev, "Failed to probe DVFS CORE\n");
+ return err;
+}
+
+/*!
+ * This function is called to put DVFS in a low power state.
+ *
+ * @param pdev the device structure
+ * @param state the power state the device is entering
+ *
+ * @return The function always returns 0.
+ */
+static int mxc_dvfs_core_suspend(struct platform_device *pdev,
+ pm_message_t state)
+{
+ if (dvfs_core_is_active) {
+ dvfs_core_resume = 1;
+ stop_dvfs();
+ }
+
+ return 0;
+}
+
+/*!
+ * This function is called to resume the MU from a low power state.
+ *
+ * @param dev the device structure
+ * @param level the stage in device suspension process that we want the
+ * device to be put in
+ *
+ * @return The function always returns 0.
+ */
+static int mxc_dvfs_core_resume(struct platform_device *pdev)
+{
+ if (dvfs_core_resume) {
+ dvfs_core_resume = 0;
+ start_dvfs();
+ }
+
+ return 0;
+}
+
+static struct platform_driver mxc_dvfs_core_driver = {
+ .driver = {
+ .name = "mxc_dvfs_core",
+ },
+ .probe = mxc_dvfs_core_probe,
+ .suspend = mxc_dvfs_core_suspend,
+ .resume = mxc_dvfs_core_resume,
+};
+
+static int __init dvfs_init(void)
+{
+ if (platform_driver_register(&mxc_dvfs_core_driver) != 0) {
+ printk(KERN_ERR "mxc_dvfs_core_driver register failed\n");
+ return -ENODEV;
+ }
+
+ dvfs_core_is_active = 0;
+ printk(KERN_INFO "DVFS driver module loaded\n");
+ return 0;
+}
+
+static void __exit dvfs_cleanup(void)
+{
+ stop_dvfs();
+
+ /* release the DVFS interrupt */
+ free_irq(MXC_INT_GPC1, NULL);
+
+ sysfs_remove_file(&dvfs_dev->kobj, &dev_attr_enable.attr);
+
+ /* Unregister the device structure */
+ platform_driver_unregister(&mxc_dvfs_core_driver);
+
+ clk_put(cpu_clk);
+ clk_put(dvfs_clk);
+
+ dvfs_core_is_active = 0;
+ printk(KERN_INFO "DVFS driver module unloaded\n");
+
+}
+
+module_init(dvfs_init);
+module_exit(dvfs_cleanup);
+
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_DESCRIPTION("DVFS driver");
+MODULE_LICENSE("GPL");
diff --git a/arch/arm/plat-mxc/entry-pm.S b/arch/arm/plat-mxc/entry-pm.S
new file mode 100644
index 000000000000..4a3af0e16191
--- /dev/null
+++ b/arch/arm/plat-mxc/entry-pm.S
@@ -0,0 +1,315 @@
+/*
+ * Copyright 2008-2009 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
+ */
+
+/*!
+ * @file plat-mxc/entry-pm.S
+ *
+ * @brief This file contains common pm entry .
+ *
+ * @ingroup MXC_PM
+ */
+
+#include <asm/assembler.h>
+#include <asm/ptrace.h>
+#include <asm/memory.h>
+#include <asm/system.h>
+#include <mach/hardware.h>
+#include <asm/asm-offsets.h>
+#include <asm/thread_info.h>
+#include <asm/proc-fns.h>
+#include <asm/vfpmacros.h>
+
+#define WAIT_MODE 111
+#define DOZE_MODE 112
+#define STOP_MODE 113
+#define DSM_MODE 114
+
+#define PM_XLOAD_SIZE 0x04
+#define PM_XLOAD_ENTRY 0x08
+#define PM_XLOAD_SUSPEND_MODE 0x0C
+#define PM_XLOAD_CORE_SP 0x10
+
+#define PROCINFO_PROC_FNS 36
+#define PROC_FIN_FN 12
+#define PROC_IDLE_FN 20
+
+#ifdef CONFIG_FIQ
+#define ARM_CONTEXT_SIZE 12
+#else
+#define ARM_CONTEXT_SIZE 8
+#endif
+
+#ifdef CONFIG_PM_VERBOSE
+resume_str:
+ .string "Resume from DSM..."
+ .size resume_str, . - resume_str
+
+.macro show_resume_str
+ ldr r0, =resume_str
+ bl printk
+.endm
+
+#else
+.macro show_resume_str
+.endm
+#endif
+
+ .data
+ .align 3
+arm_core_context:
+ .rept ARM_CONTEXT_SIZE
+ .long 0
+ .endr
+
+#ifdef CONFIG_VFP
+ .text
+ .align 5
+arm_vfp_save:
+ mov ip, sp
+ stmdb sp!, {r0-r8, fp, ip, lr, pc}
+ sub fp, ip, #4
+ mov r1, #THREAD_SIZE
+ sub r1, r1, #1
+ bic r0, sp, r1
+ ldr r8, [r0, #TI_CPU]
+ add r4, r0, #TI_VFPSTATE
+
+ ldr r3, =last_VFP_context
+ VFPFMRX r2, FPEXC
+ tst r2, #FPEXC_EN
+ bne 1f
+
+ ldr r4, [r3, r8, lsl #2]
+ cmp r4, #0
+ beq dead_vfp
+1:
+ bic r1, r2, #FPEXC_EN
+ VFPFMXR FPEXC, r1
+ /*TODO: SMP */
+ VFPFSTMIA r4, r1
+ VFPFMRX r5, FPSCR
+ tst r2, #FPEXC_EX
+ VFPFMRX r6, FPINST, NE
+ tstne r2, #FPEXC_FP2V
+ VFPFMRX r7, FPINST2, NE
+ stmia r4, {r2, r5, r6, r7}
+
+ mov r1, #0
+ str r1, [r3, r8, lsl #2]
+dead_vfp:
+ ldmia sp, {r0-r8, fp, sp, pc}
+#endif
+/*
+ * The function just be called in this file
+ * Current r0 ~r4 are not saved.
+ * Otherwise, the working registers should be saved
+ */
+ .text
+ .align 5
+arm_core_save:
+ mov ip, sp
+ stmdb sp!, {r8, r9, sl, fp, ip, lr, pc}
+ sub fp, ip, #4
+ ldr r0, =arm_core_context
+ mov r3, r0
+ /* SVC mode */
+ mrs r1, spsr @Save spsr
+ mrs r2, cpsr @Save cpsr
+ stmia r0!, {r1, r2}
+ /* Abort mode */
+ msr cpsr_c, #PSR_F_BIT | PSR_I_BIT | ABT_MODE
+ stmia r0!, {sp} @Save stack pointer for abort mode
+ msr cpsr_c, #PSR_F_BIT | PSR_I_BIT | UND_MODE
+ stmia r0!, {sp} @Save stack pointer for undefine mode
+ msr cpsr_c, #PSR_F_BIT | PSR_I_BIT | IRQ_MODE
+ stmia r0!, {sp} @Save stack pointer for irq mode
+#ifdef CONFIG_FIQ
+ msr cpsr_c, #PSR_F_BIT | PSR_I_BIT | FIQ_MODE
+ /*Save general register and sp for fiq mode*/
+ stmia r0!, {r8-r9, sl, fp, ip, sp}
+#endif
+ ldr r0, [r3, #4]
+ msr cpsr_c, r0
+ ldmia sp, {r8-r9, sl, fp, sp, pc}
+
+/*
+ * The function just be called in this file
+ * Current r0 ~r4 are not saved.
+ * Otherwise, the working registers should be saved
+ */
+arm_core_restore:
+ mov ip, sp
+ stmdb sp!, {fp, ip, lr, pc}
+ sub fp, ip, #4
+ ldr r0, =arm_core_context
+ mov r3, r0
+ /* SVC mode */
+ add r0, r0, #8 @skip svc mode
+ /* Abort mode */
+ msr cpsr_c, #PSR_F_BIT | PSR_I_BIT | ABT_MODE
+ ldmia r0!, {sp} @restore stack pointer for abort mode
+ msr cpsr_c, #PSR_F_BIT | PSR_I_BIT | UND_MODE
+ ldmia r0!, {sp} @restore stack pointer for undefine mode
+ msr cpsr_c, #PSR_F_BIT | PSR_I_BIT | IRQ_MODE
+ ldmia r0!, {sp} @restore stack pointer for irq mode
+#ifdef CONFIG_FIQ
+ msr cpsr_c, #PSR_F_BIT | PSR_I_BIT | FIQ_MODE
+ /*Save general register and sp for fiq mode*/
+ ldmia r0!, {r8-r9, sl, fp, ip, sp}
+#endif
+ ldmia r3!, {r1, r2}
+ msr cpsr, r2 @restore cpsr
+ msr spsr, r1 @restore spsr
+ ldmia sp, {fp, sp, pc}
+
+mxc_cp15_context:
+ .rept 16
+ .long 0
+ .endr
+
+ .align 5
+mxc_cp15_restore:
+ /* Physical address */
+ adr r0, mxc_cp15_context
+ ldmia r0, {r1-r9}
+#ifndef CONFIG_PM_DEBUG
+ @Add dynamic check to skip this block when debug
+ sub lr, lr, #PHYS_OFFSET
+ add lr, lr, #PAGE_OFFSET
+#endif
+ mcr p15, 0, r3, c1, c0, 2 @CP Access Register
+ mcr p15, 0, r2, c1, c0, 1 @Aux Control register
+
+#ifndef CONFIG_PM_DEBUG
+ mcr p15, 0, r0, c7, c5, 6 @flush BTAC/BTB
+ mcr p15, 0, r0, c7, c7, 0 @invalidate both caches
+ mcr p15, 0, r0, c8, c7, 0 @Inval TLBs
+#endif
+
+ mcr p15, 0, r4, c13, c0, 0 @PID
+ mcr p15, 0, r5, c13, c0, 1 @Context ID
+
+ mcr p15, 0, r6, c3, c0, 0 @Domain Access Register
+ mcr p15, 0, r7, c2, c0, 0 @TTB0
+ mcr p15, 0, r8, c2, c0, 1 @TTB1
+ mcr p15, 0, r9, c2, c0, 2 @TTBC
+
+ mcr p15, 0, r1, c1, c0, 0 @Control Register
+ /* mcu enabled */
+ mrc p15, 0, r0, c2, c0, 0
+
+ mov pc, lr
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+
+mxc_cp15_save:
+ mov ip, sp
+ stmdb sp!, {r8-r9, fp, ip, lr, pc}
+ sub fp, ip, #4
+ ldr r0, =mxc_cp15_context
+/* System Control Registers */
+ mrc p15, 0, r1, c1, c0, 0 @Control Register
+ mrc p15, 0, r2, c1, c0, 1 @Aux Control Register
+ mrc p15, 0, r3, c1, c0, 2 @CP access Register
+
+/* Memory management Registers */
+ mrc p15, 0, r4, c13, c0, 0 @PID
+ mrc p15, 0, r5, c13, c0, 1 @Context ID
+
+ mrc p15, 0, r6, c3, c0, 0 @Domain Access Register
+
+ mrc p15, 0, r7, c2, c0, 0 @TTB0
+ mrc p15, 0, r8, c2, c0, 1 @TTB1
+ mrc p15, 0, r9, c2, c0, 2 @TTBC
+ stmia r0, {r1-r9}
+ ldmia sp, {r8, r9, fp, sp, pc}
+
+/*
+ * int __mxc_pm_arch_entry(u32 entry, u32 size)
+ */
+ .align 5
+ .globl mxc_pm_arch_entry
+mxc_pm_arch_entry:
+ mov ip, sp
+ stmdb sp!, {r4-r9, sl, fp, ip, lr, pc}
+ sub fp, ip, #4
+ sub sp, sp, #4
+ mov r8, r0 @save entry
+ mov r9, r1 @save entry size
+#ifdef CONFIG_VFP
+ bl arm_vfp_save
+#endif
+ /* r0 ~r3, ip is dirty*/
+ bl arm_core_save @save arm context
+ bl mxc_cp15_save
+ mov r0, sp
+ mov r1, r8 @restore entry
+ mov r2, r9 @restore entry size
+ bl __mxc_pm_xload_setup
+1: bl cpu_v6_proc_fin
+ bl cpu_v6_do_idle
+ nop
+ nop
+ nop
+ nop
+__mxc_pm_arch_leave:
+ adr r0, __mxc_pm_xload_info
+ ldr sp, [r0, #PM_XLOAD_CORE_SP]
+
+#ifndef CONFIG_PM_DEBUG
+ sub sp, sp, #PAGE_OFFSET
+ add sp, sp, #PHYS_OFFSET
+#endif
+ bl mxc_cp15_restore
+#ifndef CONFIG_PM_DEBUG
+ sub sp, sp, #PHYS_OFFSET
+ add sp, sp, #PAGE_OFFSET
+#endif
+ show_resume_str
+ bl arm_core_restore
+ ldmib sp, {r4-r9, sl, fp, sp, pc}
+
+__mxc_pm_xload_info:
+ adr pc, __mxc_pm_xload_entry @Jump instruction
+ .long __mxc_pm_xload_end - __mxc_pm_xload_info @loader size
+ .long (__mxc_pm_arch_leave - PAGE_OFFSET + PHYS_OFFSET) @resume entry
+ .long 0 @suspend state
+ .long 0 @Core Stack pointer
+__mxc_pm_xload_entry:
+ adr r0, __mxc_pm_xload_info
+ ldr pc, [r0, #PM_XLOAD_ENTRY]
+__mxc_pm_xload_end:
+
+/*
+ * __mxc_pm_xload_setup(u32 sp, u32 entry, u32 size)
+ * r0~r6 is dirty
+ */
+__mxc_pm_xload_setup:
+ ldr r3, =__mxc_pm_xload_info
+ str r0, [r3, #PM_XLOAD_CORE_SP]
+ ldr r4, [r3, #PM_XLOAD_SIZE]
+ cmp r2, r4
+ blo 2f
+1: ldr r5, [r3], #4
+ str r5, [r1], #4
+ subs r4, r4, #4
+ bhi 1b
+ b 3f
+2: str r3, [r1]
+3: mov pc, lr
diff --git a/arch/arm/plat-mxc/gpio.c b/arch/arm/plat-mxc/gpio.c
index 7506d963be4b..a4ff5d768484 100644
--- a/arch/arm/plat-mxc/gpio.c
+++ b/arch/arm/plat-mxc/gpio.c
@@ -20,12 +20,32 @@
*/
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/irq.h>
#include <linux/gpio.h>
+#include <linux/sysdev.h>
+#include <mach/gpio.h>
#include <mach/hardware.h>
#include <asm-generic/bug.h>
+#if defined(CONFIG_ARCH_MX2)
+#else
+/* gpio and gpio based interrupt handling */
+#define GPIO_DR 0x00
+#define GPIO_GDIR 0x04
+#define GPIO_PSR 0x08
+#define GPIO_ICR1 0x0C
+#define GPIO_ICR2 0x10
+#define GPIO_IMR 0x14
+#define GPIO_ISR 0x18
+#define GPIO_INT_LOW_LEV 0x0
+#define GPIO_INT_HIGH_LEV 0x1
+#define GPIO_INT_RISE_EDGE 0x2
+#define GPIO_INT_FALL_EDGE 0x3
+#define GPIO_INT_NONE 0x4
+#endif
+
static struct mxc_gpio_port *mxc_gpio_ports;
static int gpio_table_size;
@@ -162,16 +182,23 @@ static void mxc_gpio_irq_handler(struct mxc_gpio_port *port, u32 irq_stat)
}
}
-#if defined(CONFIG_ARCH_MX3) || defined(CONFIG_ARCH_MX1)
-/* MX1 and MX3 has one interrupt *per* gpio port */
-static void mx3_gpio_irq_handler(u32 irq, struct irq_desc *desc)
+#ifndef CONFIG_ARCH_MX2
+/* one interrupt *per* gpio port */
+static void gpio_irq_handler(u32 irq, struct irq_desc *desc)
{
u32 irq_stat;
+ u32 mask = 0xFFFFFFFF;
struct mxc_gpio_port *port = (struct mxc_gpio_port *)get_irq_data(irq);
- irq_stat = __raw_readl(port->base + GPIO_ISR) &
- __raw_readl(port->base + GPIO_IMR);
+#ifdef MXC_GPIO_SPLIT_IRQ_2
+ if (irq == port->irq)
+ mask = 0x0000FFFF;
+ else
+ mask = 0xFFFF0000;
+#endif
+ irq_stat = __raw_readl(port->base + GPIO_ISR) &
+ (__raw_readl(port->base + GPIO_IMR) & mask);
mxc_gpio_irq_handler(port, irq_stat);
}
#endif
@@ -197,11 +224,44 @@ static void mx2_gpio_irq_handler(u32 irq, struct irq_desc *desc)
}
#endif
+/*
+ * Set interrupt number "irq" in the GPIO as a wake-up source.
+ * While system is running all registered GPIO interrupts need to have
+ * wake-up enabled. When system is suspended, only selected GPIO interrupts
+ * need to have wake-up enabled.
+ * @param irq interrupt source number
+ * @param enable enable as wake-up if equal to non-zero
+ * @return This function returns 0 on success.
+ */
+static int gpio_set_wake_irq(u32 irq, u32 enable)
+{
+ u32 gpio = irq_to_gpio(irq);
+ u32 gpio_idx = gpio & 0x1F;
+ struct mxc_gpio_port *port = &mxc_gpio_ports[gpio / 32];
+
+ if (enable) {
+ port->suspend_wakeup |= (1 << gpio_idx);
+ if (port->irq_high && (gpio_idx >= 16))
+ enable_irq_wake(port->irq_high);
+ else
+ enable_irq_wake(port->irq);
+ } else {
+ port->suspend_wakeup &= ~(1 << gpio_idx);
+ if (port->irq_high && (gpio_idx >= 16))
+ disable_irq_wake(port->irq_high);
+ else
+ disable_irq_wake(port->irq);
+ }
+
+ return 0;
+}
+
static struct irq_chip gpio_irq_chip = {
.ack = gpio_ack_irq,
.mask = gpio_mask_irq,
.unmask = gpio_unmask_irq,
.set_type = gpio_set_irq_type,
+ .set_wake = gpio_set_wake_irq,
};
static void _set_gpio_direction(struct gpio_chip *chip, unsigned offset,
@@ -252,9 +312,98 @@ static int mxc_gpio_direction_output(struct gpio_chip *chip,
return 0;
}
+#ifdef CONFIG_PM
+/*!
+ * This function puts the GPIO in low-power mode/state.
+ * All the interrupts that are enabled are first saved.
+ * Only those interrupts which registers as a wake source by calling
+ * enable_irq_wake are enabled. All other interrupts are disabled.
+ *
+ * @param dev the system device structure used to give information
+ * on GPIO to suspend
+ * @param mesg the power state the device is entering
+ *
+ * @return The function always returns 0.
+ */
+static int mxc_gpio_suspend(struct sys_device *dev, pm_message_t mesg)
+{
+ int i;
+ struct mxc_gpio_port *port = mxc_gpio_ports;
+
+ for (i = 0; i < gpio_table_size; i++) {
+ void __iomem *isr_reg;
+ void __iomem *imr_reg;
+
+ isr_reg = port[i].base + GPIO_ISR;
+ imr_reg = port[i].base + GPIO_IMR;
+
+ if (__raw_readl(isr_reg) & port[i].suspend_wakeup)
+ return -EPERM;
+
+ port[i].saved_wakeup = __raw_readl(imr_reg);
+ __raw_writel(port[i].suspend_wakeup, imr_reg);
+ }
+
+ return 0;
+}
+
+/*!
+ * This function brings the GPIO back from low-power state.
+ * All the interrupts enabled before suspension are re-enabled from
+ * the saved information.
+ *
+ * @param dev the system device structure used to give information
+ * on GPIO to resume
+ *
+ * @return The function always returns 0.
+ */
+static int mxc_gpio_resume(struct sys_device *dev)
+{
+ int i;
+ struct mxc_gpio_port *port = mxc_gpio_ports;
+
+ for (i = 0; i < gpio_table_size; i++) {
+ void __iomem *isr_reg;
+ void __iomem *imr_reg;
+
+ isr_reg = port[i].base + GPIO_ISR;
+ imr_reg = port[i].base + GPIO_IMR;
+
+ __raw_writel(port[i].saved_wakeup, imr_reg);
+ }
+
+ return 0;
+}
+#else
+#define mxc_gpio_suspend NULL
+#define mxc_gpio_resume NULL
+#endif /* CONFIG_PM */
+
+/*!
+ * This structure contains pointers to the power management callback functions.
+ */
+static struct sysdev_class mxc_gpio_sysclass = {
+ .name = "mxc_gpio",
+ .suspend = mxc_gpio_suspend,
+ .resume = mxc_gpio_resume,
+};
+
+/*!
+ * This structure represents GPIO as a system device.
+ * System devices follow a slightly different driver model.
+ * They don't need to do dynammic driver binding, can't be probed,
+ * and don't reside on any type of peripheral bus.
+ * So, it is represented and treated a little differently.
+ */
+static struct sys_device mxc_gpio_device = {
+ .id = 0,
+ .cls = &mxc_gpio_sysclass,
+};
+
int __init mxc_gpio_init(struct mxc_gpio_port *port, int cnt)
{
int i, j;
+ int ret = 0;
/* save for local usage */
mxc_gpio_ports = port;
@@ -284,10 +433,13 @@ int __init mxc_gpio_init(struct mxc_gpio_port *port, int cnt)
/* its a serious configuration bug when it fails */
BUG_ON( gpiochip_add(&port[i].chip) < 0 );
-#if defined(CONFIG_ARCH_MX3) || defined(CONFIG_ARCH_MX1)
- /* setup one handler for each entry */
- set_irq_chained_handler(port[i].irq, mx3_gpio_irq_handler);
+#ifndef CONFIG_ARCH_MX2
+ set_irq_chained_handler(port[i].irq, gpio_irq_handler);
set_irq_data(port[i].irq, &port[i]);
+ if (port[i].irq_high) {
+ set_irq_chained_handler(port[i].irq_high, gpio_irq_handler);
+ set_irq_data(port[i].irq_high, &port[i]);
+ }
#endif
}
@@ -296,5 +448,10 @@ int __init mxc_gpio_init(struct mxc_gpio_port *port, int cnt)
set_irq_chained_handler(port[0].irq, mx2_gpio_irq_handler);
set_irq_data(port[0].irq, port);
#endif
- return 0;
+
+ ret = sysdev_class_register(&mxc_gpio_sysclass);
+ if (ret == 0)
+ ret = sysdev_register(&mxc_gpio_device);
+
+ return ret;
}
diff --git a/arch/arm/plat-mxc/include/mach/arc_otg.h b/arch/arm/plat-mxc/include/mach/arc_otg.h
new file mode 100644
index 000000000000..2d58f2e6d6fd
--- /dev/null
+++ b/arch/arm/plat-mxc/include/mach/arc_otg.h
@@ -0,0 +1,343 @@
+/*
+ * Copyright 2005-2009 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 __ASM_ARCH_MXC_ARC_OTG_H__
+#define __ASM_ARCH_MXC_ARC_OTG_H__
+
+#define USB_OTGREGS_BASE (OTG_BASE_ADDR + 0x000)
+#define USB_H1REGS_BASE (OTG_BASE_ADDR + 0x200)
+#define USB_H2REGS_BASE (OTG_BASE_ADDR + 0x400)
+#ifdef CONFIG_ARCH_MX51
+#define USB_H3REGS_BASE (OTG_BASE_ADDR + 0x600)
+#define USB_OTHERREGS_BASE (OTG_BASE_ADDR + 0x800)
+#else
+#define USB_OTHERREGS_BASE (OTG_BASE_ADDR + 0x600)
+#endif
+
+
+#define USBOTG_REG32(offset) (*((volatile u32 *)(IO_ADDRESS(USB_OTGREGS_BASE + (offset)))))
+#define USBOTG_REG16(offset) (*((volatile u16 *)(IO_ADDRESS(USB_OTGREGS_BASE + (offset)))))
+
+#define USBH1_REG32(offset) (*((volatile u32 *)(IO_ADDRESS(USB_H1REGS_BASE + (offset)))))
+#define USBH1_REG16(offset) (*((volatile u16 *)(IO_ADDRESS(USB_H1REGS_BASE + (offset)))))
+
+#define USBH2_REG32(offset) (*((volatile u32 *)(IO_ADDRESS(USB_H2REGS_BASE + (offset)))))
+#define USBH2_REG16(offset) (*((volatile u16 *)(IO_ADDRESS(USB_H2REGS_BASE + (offset)))))
+
+#define USBOTHER_REG(offset) (*((volatile u32 *)(IO_ADDRESS(USB_OTHERREGS_BASE + (offset)))))
+
+/*
+ * OTG registers
+ */
+#define UOG_ID USBOTG_REG32(0x00) /* Host ID */
+#define UOG_HWGENERAL USBOTG_REG32(0x04) /* Host General */
+#define UOG_HWHOST USBOTG_REG32(0x08) /* Host h/w params */
+#define UOG_HWTXBUF USBOTG_REG32(0x10) /* TX buffer h/w params */
+#define UOG_HWRXBUF USBOTG_REG32(0x14) /* RX buffer h/w params */
+#define UOG_CAPLENGTH USBOTG_REG16(0x100) /* Capability register length */
+#define UOG_HCIVERSION USBOTG_REG16(0x102) /* Host Interface version */
+#define UOG_HCSPARAMS USBOTG_REG32(0x104) /* Host control structural params */
+#define UOG_HCCPARAMS USBOTG_REG32(0x108) /* control capability params */
+#define UOG_DCIVERSION USBOTG_REG32(0x120) /* device interface version */
+/* start EHCI registers: */
+#define UOG_USBCMD USBOTG_REG32(0x140) /* USB command register */
+#define UOG_USBSTS USBOTG_REG32(0x144) /* USB status register */
+#define UOG_USBINTR USBOTG_REG32(0x148) /* interrupt enable register */
+#define UOG_FRINDEX USBOTG_REG32(0x14c) /* USB frame index */
+/* segment (0x150) addr bits 63:32 if needed */
+#define UOG_PERIODICLISTBASE USBOTG_REG32(0x154) /* host crtlr frame list base addr */
+#define UOG_DEVICEADDR USBOTG_REG32(0x154) /* device crtlr device address */
+#define UOG_ASYNCLISTADDR USBOTG_REG32(0x158) /* host ctrlr next async addr */
+#define UOG_EPLISTADDR USBOTG_REG32(0x158) /* device ctrlr endpoint list addr */
+#define UOG_BURSTSIZE USBOTG_REG32(0x160) /* host ctrlr embedded TT async buf status */
+#define UOG_TXFILLTUNING USBOTG_REG32(0x164) /* TX FIFO fill tuning */
+#define UOG_ULPIVIEW USBOTG_REG32(0x170) /* ULPI viewport */
+#define UOG_CFGFLAG USBOTG_REG32(0x180) /* configflag (supports HS) */
+#define UOG_PORTSC1 USBOTG_REG32(0x184) /* port status and control */
+/* end EHCI registers: */
+#define UOG_OTGSC USBOTG_REG32(0x1a4) /* OTG status and control */
+#define UOG_USBMODE USBOTG_REG32(0x1a8) /* USB device mode */
+#define UOG_ENDPTSETUPSTAT USBOTG_REG32(0x1ac) /* endpoint setup status */
+#define UOG_ENDPTPRIME USBOTG_REG32(0x1b0) /* endpoint initialization */
+#define UOG_ENDPTFLUSH USBOTG_REG32(0x1b4) /* endpoint de-initialize */
+#define UOG_ENDPTSTAT USBOTG_REG32(0x1b8) /* endpoint status */
+#define UOG_ENDPTCOMPLETE USBOTG_REG32(0x1bc) /* endpoint complete */
+#define UOG_EPCTRL0 USBOTG_REG32(0x1c0) /* endpoint control0 */
+#define UOG_EPCTRL1 USBOTG_REG32(0x1c4) /* endpoint control1 */
+#define UOG_EPCTRL2 USBOTG_REG32(0x1c8) /* endpoint control2 */
+#define UOG_EPCTRL3 USBOTG_REG32(0x1cc) /* endpoint control3 */
+#define UOG_EPCTRL4 USBOTG_REG32(0x1d0) /* endpoint control4 */
+#define UOG_EPCTRL5 USBOTG_REG32(0x1d4) /* endpoint control5 */
+#define UOG_EPCTRL6 USBOTG_REG32(0x1d8) /* endpoint control6 */
+#define UOG_EPCTRL7 USBOTG_REG32(0x1dc) /* endpoint control7 */
+
+/*
+ * Host 1 registers
+ */
+#define UH1_ID USBH1_REG32(0x00) /* Host ID */
+#define UH1_HWGENERAL USBH1_REG32(0x04) /* Host General */
+#define UH1_HWHOST USBH1_REG32(0x08) /* Host h/w params */
+#define UH1_HWTXBUF USBH1_REG32(0x10) /* TX buffer h/w params */
+#define UH1_HWRXBUF USBH1_REG32(0x14) /* RX buffer h/w params */
+#define UH1_CAPLENGTH USBH1_REG16(0x100) /* Capability register length */
+#define UH1_HCIVERSION USBH1_REG16(0x102) /* Host Interface version */
+#define UH1_HCSPARAMS USBH1_REG32(0x104) /* Host control structural params */
+#define UH1_HCCPARAMS USBH1_REG32(0x108) /* control capability params */
+/* start EHCI registers: */
+#define UH1_USBCMD USBH1_REG32(0x140) /* USB command register */
+#define UH1_USBSTS USBH1_REG32(0x144) /* USB status register */
+#define UH1_USBINTR USBH1_REG32(0x148) /* interrupt enable register */
+#define UH1_FRINDEX USBH1_REG32(0x14c) /* USB frame index */
+/* segment (0x150) addr bits 63:32 if needed */
+#define UH1_PERIODICLISTBASE USBH1_REG32(0x154) /* host crtlr frame list base addr */
+#define UH1_ASYNCLISTADDR USBH1_REG32(0x158) /* host ctrlr nest async addr */
+#define UH1_BURSTSIZE USBH1_REG32(0x160) /* host ctrlr embedded TT async buf status */
+#define UH1_TXFILLTUNING USBH1_REG32(0x164) /* TX FIFO fill tuning */
+/* configured_flag (0x180) configflag (supports HS) */
+#define UH1_PORTSC1 USBH1_REG32(0x184) /* port status and control */
+/* end EHCI registers: */
+#define UH1_USBMODE USBH1_REG32(0x1a8) /* USB device mode */
+
+/*
+ * Host 2 registers
+ */
+#define UH2_ID USBH2_REG32(0x00) /* Host ID */
+#define UH2_HWGENERAL USBH2_REG32(0x04) /* Host General */
+#define UH2_HWHOST USBH2_REG32(0x08) /* Host h/w params */
+#define UH2_HWTXBUF USBH2_REG32(0x10) /* TX buffer h/w params */
+#define UH2_HWRXBUF USBH2_REG32(0x14) /* RX buffer h/w params */
+#define UH2_CAPLENGTH USBH2_REG16(0x100) /* Capability register length */
+#define UH2_HCIVERSION USBH2_REG16(0x102) /* Host Interface version */
+#define UH2_HCSPARAMS USBH2_REG32(0x104) /* Host control structural params */
+#define UH2_HCCPARAMS USBH2_REG32(0x108) /* control capability params */
+/* start EHCI registers: */
+#define UH2_USBCMD USBH2_REG32(0x140) /* USB command register */
+#define UH2_USBSTS USBH2_REG32(0x144) /* USB status register */
+#define UH2_USBINTR USBH2_REG32(0x148) /* interrupt enable register */
+#define UH2_FRINDEX USBH2_REG32(0x14c) /* USB frame index */
+/* segment (0x150) addr bits 63:32 if needed */
+#define UH2_PERIODICLISTBASE USBH2_REG32(0x154) /* host crtlr frame list base addr */
+#define UH2_ASYNCLISTADDR USBH2_REG32(0x158) /* host ctrlr nest async addr */
+#define UH2_BURSTSIZE USBH2_REG32(0x160) /* host ctrlr embedded TT async buf status */
+#define UH2_TXFILLTUNING USBH2_REG32(0x164) /* TX FIFO fill tuning */
+#define UH2_ULPIVIEW USBH2_REG32(0x170) /* ULPI viewport */
+/* configured_flag (0x180) configflag (supports HS) */
+#define UH2_PORTSC1 USBH2_REG32(0x184) /* port status and control */
+/* end EHCI registers */
+#define UH2_USBMODE USBH2_REG32(0x1a8) /* USB device mode */
+
+/*
+ * other regs (not part of ARC core)
+ */
+#define USBCTRL USBOTHER_REG(0x00) /* USB Control register */
+#define USB_OTG_MIRROR USBOTHER_REG(0x04) /* USB OTG mirror register */
+#define USB_PHY_CTR_FUNC USBOTHER_REG(0x08) /* OTG UTMI PHY Function Control register */
+#define USB_PHY_CTR_FUNC2 USBOTHER_REG(0x0c) /* OTG UTMI PHY Function Control register */
+#define USB_CTRL_1 USBOTHER_REG(0x10) /* USB Cotrol Register 1*/
+#define USBCTRL_HOST2 USBOTHER_REG(0x14) /* USB Cotrol Register 1*/
+#define USBCTRL_HOST3 USBOTHER_REG(0x18) /* USB Cotrol Register 1*/
+
+/*
+ * register bits
+ */
+
+/* x_PORTSCx */
+#define PORTSC_PTS_MASK (3 << 30) /* parallel xcvr select 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 {en,dis}able 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)
+#define OTGSC_CTRL_OTG_TERM (1 << 3) /* controls DM pulldown */
+#define OTGSC_CTRL_DATA_PULSING (1 << 4)
+#define OTGSC_CTRL_USB_ID_PU (1 << 5) /* enable ID pullup */
+/* current status: (R/O) */
+#define OTGSC_STS_USB_ID (1 << 8) /* 0=A-device 1=B-device */
+#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 */
+
+/* USBCTRL */
+#define UCTRL_OWIR (1 << 31) /* OTG wakeup intr request received */
+#define UCTRL_OSIC_MASK (3 << 29) /* OTG Serial Interface Config: */
+#define UCTRL_OSIC_DU6 (0 << 29) /* Differential/unidirectional 6 wire */
+#define UCTRL_OSIC_DB4 (1 << 29) /* Differential/bidirectional 4 wire */
+#define UCTRL_OSIC_SU6 (2 << 29) /* single-ended/unidirectional 6 wire */
+#define UCTRL_OSIC_SB3 (3 << 29) /* single-ended/bidirectional 3 wire */
+
+#define UCTRL_OUIE (1 << 28) /* OTG ULPI intr enable */
+#define UCTRL_OWIE (1 << 27) /* OTG wakeup intr enable */
+#define UCTRL_OBPVAL_RXDP (1 << 26) /* OTG RxDp status in bypass mode */
+#define UCTRL_OBPVAL_RXDM (1 << 25) /* OTG RxDm status in bypass mode */
+#define UCTRL_OPM (1 << 24) /* OTG power mask */
+#define UCTRL_H2WIR (1 << 23) /* HOST2 wakeup intr request received */
+#define UCTRL_H2SIC_MASK (3 << 21) /* HOST2 Serial Interface Config: */
+#define UCTRL_H2SIC_DU6 (0 << 21) /* Differential/unidirectional 6 wire */
+#define UCTRL_H2SIC_DB4 (1 << 21) /* Differential/bidirectional 4 wire */
+#define UCTRL_H2SIC_SU6 (2 << 21) /* single-ended/unidirectional 6 wire */
+#define UCTRL_H2SIC_SB3 (3 << 21) /* single-ended/bidirectional 3 wire */
+
+#ifdef CONFIG_ARCH_MX51
+#define UCTRL_H2UIE (1 << 8) /* HOST2 ULPI intr enable */
+#define UCTRL_H2WIE (1 << 7) /* HOST2 wakeup intr enable */
+#define UCTRL_H2PP 0 /* Power Polarity for uh2 */
+#define UCTRL_H2PM (1 << 4) /* HOST2 power mask */
+#else
+#define UCTRL_H2UIE (1 << 20) /* HOST2 ULPI intr enable */
+#define UCTRL_H2WIE (1 << 19) /* HOST2 wakeup intr enable */
+#define UCTRL_H2PP (1 << 18) /* Power Polarity for uh2 */
+#define UCTRL_H2PM (1 << 16) /* HOST2 power mask */
+#endif
+
+#define UCTRL_H1WIR (1 << 15) /* HOST1 wakeup intr request received */
+#define UCTRL_H1SIC_MASK (3 << 13) /* HOST1 Serial Interface Config: */
+#define UCTRL_H1SIC_DU6 (0 << 13) /* Differential/unidirectional 6 wire */
+#define UCTRL_H1SIC_DB4 (1 << 13) /* Differential/bidirectional 4 wire */
+#define UCTRL_H1SIC_SU6 (2 << 13) /* single-ended/unidirectional 6 wire */
+#define UCTRL_H1SIC_SB3 (3 << 13) /* single-ended/bidirectional 3 wire */
+#define UCTRL_OLOCKD (1 << 13) /* otg lock disable */
+#define UCTRL_H2LOCKD (1 << 12) /* HOST2 lock disable */
+#define UCTRL_H1UIE (1 << 12) /* Host1 ULPI interrupt enable */
+
+#define UCTRL_PP (1 << 11) /* power polarity bit */
+#define UCTRL_H1WIE (1 << 11) /* HOST1 wakeup intr enable */
+#define UCTRL_H1BPVAL_RXDP (1 << 10) /* HOST1 RxDp status in bypass mode */
+#define UCTRL_XCSO (1 << 10) /* Xcvr Clock Select for OTG port */
+#define UCTRL_H1BPVAL_RXDM (1 << 9) /* HOST1 RxDm status in bypass mode */
+#define UCTRL_XCSH2 (1 << 9) /* Xcvr Clock Select for Host port */
+#define UCTRL_H1PM (1 << 8) /* HOST1 power mask */
+#define UCTRL_IP_PULIDP (1 << 8) /* Ipp_Puimpel_Pullup_Dp */
+
+#define UCTRL_IP_PUE_UP (1 << 7) /* ipp_pue_pullup_dp */
+#define UCTRL_IP_PUE_DOWN (1 << 6) /* ipp_pue_pulldwn_dpdm */
+#define UCTRL_H2DT (1 << 5) /* HOST2 TLL disabled */
+#define UCTRL_H1DT (1 << 4) /* HOST1 TLL disabled */
+#define UCTRL_USBTE (1 << 4) /* USBT Transceiver enable */
+#define UCTRL_OCPOL (1 << 3) /* OverCurrent Polarity */
+#define UCTRL_OCE (1 << 2) /* OverCurrent Enable */
+#define UCTRL_H2OCPOL (1 << 2) /* OverCurrent Polarity of Host2 */
+#define UCTRL_H2OCS (1 << 1) /* Host OverCurrent State */
+#define UCTRL_BPE (1 << 0) /* bypass mode enable */
+#define UCTRL_OTD (1 << 0) /* OTG TLL Disable */
+#define UCTRL_OOCS (1 << 0) /* OTG OverCurrent State */
+
+/* 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 Control */
+
+/* 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 */
+
+/* USB_PHY_CTRL_FUNC */
+#define USB_UTMI_PHYCTRL_UTMI_ENABLE (1 << 24)
+#define USB_UTMI_PHYCTRL_CHGRDETEN (1 << 24) /* Enable Charger Detector */
+#define USB_UTMI_PHYCTRL_CHGRDETON (1 << 23) /* Charger Detector Power On Control */
+#define USB_UTMI_PHYCTRL_OC_POL (1 << 9) /* OTG Polarity of Overcurrent */
+#define USB_UTMI_PHYCTRL_OC_DIS (1 << 8) /* OTG Disable Overcurrent Event */
+/* USB_PHY_CTRL_FUNC2*/
+#define USB_UTMI_PHYCTRL2_PLLDIV_MASK 0x3
+#define USB_UTMI_PHYCTRL2_PLLDIV_SHIFT 0
+#define USB_UTMI_PHYCTRL2_HSDEVSEL_MASK 0x3
+#define USB_UTMI_PHYCTRL2_HSDEVSEL_SHIFT 19
+
+/* USB_CTRL_1 */
+#define USB_CTRL_UH1_EXT_CLK_EN (1 << 25)
+#define USB_CTRL_UH2_EXT_CLK_EN (1 << 26)
+
+/* ULPIVIEW register bits */
+#define ULPIVW_OFF (0x170)
+#define ULPIVW_WU (1 << 31) /* Wakeup */
+#define ULPIVW_RUN (1 << 30) /* read/write run */
+#define ULPIVW_WRITE (1 << 29) /* 0=read 1=write */
+#define ULPIVW_SS (1 << 27) /* SyncState */
+#define ULPIVW_PORT_MASK 0x07 /* Port field */
+#define ULPIVW_PORT_SHIFT 24
+#define ULPIVW_ADDR_MASK 0xFF /* data address field */
+#define ULPIVW_ADDR_SHIFT 16
+#define ULPIVW_RDATA_MASK 0xFF /* read data field */
+#define ULPIVW_RDATA_SHIFT 8
+#define ULPIVW_WDATA_MASK 0xFF /* write data field */
+#define ULPIVW_WDATA_SHIFT 0
+
+#define HCSPARAMS_PPC (0x1<<4) /* Port Power Control */
+#endif
diff --git a/arch/arm/plat-mxc/include/mach/audio_controls.h b/arch/arm/plat-mxc/include/mach/audio_controls.h
new file mode 100644
index 000000000000..810bf50b16a8
--- /dev/null
+++ b/arch/arm/plat-mxc/include/mach/audio_controls.h
@@ -0,0 +1,220 @@
+/*
+ * Copyright 2007-2009 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
+ */
+
+ /*!
+ * @file include/asm-arm/arch-mxc/audio_controls.h
+ * @brief this file implements the mxc sound driver interface to OSS framework
+ * @ingroup SOUND_DRV
+ */
+#ifndef __ASM_ARCH_MXC_AUDIO_CONTROLS_H__
+#define __ASM_ARCH_MXC_AUDIO_CONTROLS_H__
+
+/*!
+ * This ioctl can be used to get the adder configuration, use the audio control
+ * SNDCTL_MC13783_READ_OUT_MIXER.\n
+ * Possible returned values are :
+ * @see MC13783_AUDIO_ADDER_STEREO
+ * @see MC13783_AUDIO_ADDER_STEREO_OPPOSITE
+ * @see MC13783_AUDIO_ADDER_MONO
+ * @see MC13783_AUDIO_ADDER_MONO_OPPOSITE
+ *
+ */
+#define SNDCTL_MC13783_READ_OUT_ADDER _SIOR('Z', 6, int)
+
+/*!
+ * To set the adder configuration, use the audio control
+ * SNDCTL_MC13783_WRITE_OUT_MIXER. Possible arguments are : \n
+ * @see MC13783_AUDIO_ADDER_STEREO
+ * @see MC13783_AUDIO_ADDER_STEREO_OPPOSITE
+ * @see MC13783_AUDIO_ADDER_MONO
+ * @see MC13783_AUDIO_ADDER_MONO_OPPOSITE
+ *
+ */
+#define SNDCTL_MC13783_WRITE_OUT_ADDER _SIOWR('Z', 7, int)
+
+/*!
+ * To get the codec balance configuration, use the audio control
+ * SNDCTL_MC13783_READ_OUT_BALANCE.\n
+ * Range is 0 (-21 dB left) to 100 (-21 dB right), linear, 3dB step ;
+ * 50 is no balance.
+ * \n Examples:
+ * \n 0 : -21dB left 50 : balance deactivated 100 : -21 dB right
+ *
+ */
+#define SNDCTL_MC13783_READ_OUT_BALANCE _SIOR('Z', 8, int)
+
+/*!
+ * To set the codec balance configuration, use the audio control
+ * SNDCTL_MC13783_WRITE_OUT_BALANCE.\n
+ * Range is 0 (-21 dB left) to 100 (-21 dB right), linear, 3dB step ;
+ * 50 is no balance.
+ * \n Examples:
+ * \n 0 : -21dB left 50 : balance deactivated 100 : -21 dB right
+ *
+ */
+#define SNDCTL_MC13783_WRITE_OUT_BALANCE _SIOWR('Z', 9, int)
+
+/*!
+ * To set the codec filter configuration, use the audio control
+ * SNDCTL_MC13783_WRITE_CODEC_FILTER.
+ * The new configuration replaces the old one.\n
+ * Possible arguments are :
+ * @see MC13783_CODEC_FILTER_DISABLE
+ * @see MC13783_CODEC_FILTER_HIGH_PASS_IN
+ * @see MC13783_CODEC_FILTER_HIGH_PASS_OUT
+ * @see MC13783_CODEC_FILTER_DITHERING \n
+ *
+ */
+#define SNDCTL_MC13783_WRITE_CODEC_FILTER _SIOWR('Z', 20, int)
+
+/*!
+ * To get the codec filter configuration, use the audio control :
+ * SNDCTL_MC13783_READ_CODEC_FILTER.
+ * The new configuration replaces the old one.\n
+ * Possible returned values are :
+ * @see MC13783_CODEC_FILTER_DISABLE
+ * @see MC13783_CODEC_FILTER_HIGH_PASS_IN
+ * @see MC13783_CODEC_FILTER_HIGH_PASS_OUT
+ * @see MC13783_CODEC_FILTER_DITHERING \n
+ *
+ */
+#define SNDCTL_MC13783_READ_CODEC_FILTER _SIOR('Z', 21, int)
+
+/*
+ * To set the clock configuration, use the audio control
+ * SNDCTL_MC13783_WRITE_MASTER_CLOCK. \n
+ * Possible arguments are : \n
+ * 1 : to MCU master \n
+ * 2 : to MC13783 master
+ */
+#define SNDCTL_MC13783_WRITE_MASTER_CLOCK _SIOR('Z', 30, int)
+
+/*!
+ * To set the output port, use the audio control
+ * SNDCTL_MC13783_WRITE_PORT.\n
+ * Possible returned values are :
+ * \n 1 : to port 4
+ * \n 2 : to port 5
+ * Possible returned values are :
+ * \n 1 : port 4
+ * \n 2 : port 5
+ */
+#define SNDCTL_MC13783_WRITE_PORT _SIOR('Z', 31, int)
+
+/*!
+ * Argument for the mc13783 adder configuration
+ * @see SNDCTL_MC13783_WRITE_OUT_ADDER
+ * @see SNDCTL_MC13783_READ_OUT_ADDER
+ */
+#define MC13783_AUDIO_ADDER_STEREO 0x1
+/*!
+ * Argument for the mc13783 adder configuration
+ * @see SNDCTL_MC13783_WRITE_OUT_ADDER
+ * @see SNDCTL_MC13783_READ_OUT_ADDER
+ */
+#define MC13783_AUDIO_ADDER_STEREO_OPPOSITE 0x2
+/*!
+ * Argument for the mc13783 adder configuration
+ * @see SNDCTL_MC13783_WRITE_OUT_ADDER
+ * @see SNDCTL_MC13783_READ_OUT_ADDER
+ */
+#define MC13783_AUDIO_ADDER_MONO 0x4
+/*!
+ * Argument for the mc13783 adder configuration
+ * @see SNDCTL_MC13783_WRITE_OUT_ADDER
+ * @see SNDCTL_MC13783_READ_OUT_ADDER
+ */
+#define MC13783_AUDIO_ADDER_MONO_OPPOSITE 0x8
+
+/*!
+ * Argument for the mc13783 codec filter configuration
+ * @see SNDCTL_MC13783_WRITE_CODEC_FILTER
+ * @see SNDCTL_MC13783_READ_CODEC_FILTER
+ */
+#define MC13783_CODEC_FILTER_DISABLE 0x0
+/*!
+ * Argument for the mc13783 codec filter configuration
+ * @see SNDCTL_MC13783_WRITE_CODEC_FILTER
+ * @see SNDCTL_MC13783_READ_CODEC_FILTER
+ */
+#define MC13783_CODEC_FILTER_HIGH_PASS_IN 0x1
+/*!
+ * Argument for the mc13783 codec filter configuration
+ * @see SNDCTL_MC13783_WRITE_CODEC_FILTER
+ * @see SNDCTL_MC13783_READ_CODEC_FILTER
+ */
+#define MC13783_CODEC_FILTER_HIGH_PASS_OUT 0x2
+/*!
+ * Argument for the mc13783 codec filter configuration
+ * @see SNDCTL_MC13783_WRITE_CODEC_FILTER
+ * @see SNDCTL_MC13783_READ_CODEC_FILTER
+ */
+#define MC13783_CODEC_FILTER_DITHERING 0x4
+
+/*!
+ * Argument for the system audio clocking selection
+ * @see MXC_AUDIO_CLOCKING_MCU_MASTER
+ * @see SNDCTL_CLK_SET_MASTER
+ */
+#define MXC_AUDIO_CLOCKING_MC13783_MASTER 0x0
+
+/*!
+ * Argument for the system audio clocking selection
+ * @see MXC_AUDIO_CLOCKING_MC13783_MASTER
+ * @see SNDCTL_CLK_SET_MASTER
+ */
+#define MXC_AUDIO_CLOCKING_MCU_MASTER 0x1
+
+/*!
+ * Argument for the DAM output port selection
+ * @see SNDCTL_DAM_SET_OUT_PORT
+ * @see MXC_DAM_OUT_PORT_AD2
+ */
+#define MXC_DAM_OUT_PORT_AD1 0x0
+
+/*!
+ * Argument for the DAM output port selection
+ * @see SNDCTL_DAM_SET_OUT_PORT
+ * @see MXC_DAM_OUT_PORT_AD1
+ */
+#define MXC_DAM_OUT_PORT_AD2 0x1
+
+/*!
+ * Argument for the mc13783 codec filter configuration
+ * @see SNDCTL_MC13783_WRITE_CODEC_FILTER
+ * @see SNDCTL_MC13783_READ_CODEC_FILTER
+ */
+#define MC13783_CODEC_FILTER_DISABLE 0x0
+
+/*!
+ * Argument for the mc13783 codec filter configuration
+ * @see SNDCTL_MC13783_WRITE_CODEC_FILTER
+ * @see SNDCTL_MC13783_READ_CODEC_FILTER
+ */
+#define MC13783_CODEC_FILTER_HIGH_PASS_IN 0x1
+
+/*!
+ * Argument for the mc13783 codec filter configuration
+ * @see SNDCTL_MC13783_WRITE_CODEC_FILTER
+ * @see SNDCTL_MC13783_READ_CODEC_FILTER
+ */
+#define MC13783_CODEC_FILTER_HIGH_PASS_OUT 0x2
+
+/*!
+ * Argument for the mc13783 codec filter configuration
+ * @see SNDCTL_MC13783_WRITE_CODEC_FILTER
+ * @see SNDCTL_MC13783_READ_CODEC_FILTER
+ */
+#define MC13783_CODEC_FILTER_DITHERING 0x4
+
+#endif /* __ASM_ARCH_MXC_AUDIO_CONTROLS_H__ */
diff --git a/arch/arm/plat-mxc/include/mach/clock.h b/arch/arm/plat-mxc/include/mach/clock.h
index 43a82d0c534d..e9333bb1729b 100644
--- a/arch/arm/plat-mxc/include/mach/clock.h
+++ b/arch/arm/plat-mxc/include/mach/clock.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2005-2007 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2005-2009 Freescale Semiconductor, Inc. All Rights Reserved.
* Copyright 2008 Juergen Beisert, kernel@pengutronix.de
*
* This program is free software; you can redistribute it and/or
@@ -38,6 +38,8 @@ struct clk {
struct clk *parent;
/* Secondary clock to enable/disable with this clock */
struct clk *secondary;
+ /* Current clock rate */
+ unsigned long rate;
/* Reference count of clock enable/disable */
__s8 usecount;
/* Register bit position for clock's enable/disable control. */
@@ -45,8 +47,9 @@ struct clk {
/* Register address for clock's enable/disable control. */
void __iomem *enable_reg;
u32 flags;
- /* get the current clock rate (always a fresh value) */
- unsigned long (*get_rate) (struct clk *);
+ /* Function ptr to recalculate the clock's rate based on parent
+ clock's rate */
+ void (*recalc) (struct clk *);
/* 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 */
@@ -66,6 +69,16 @@ struct clk {
int clk_register(struct clk *clk);
void clk_unregister(struct clk *clk);
+int clk_get_usecount(struct clk *clk);
+int clk_set_pll_dither(struct clk *clk, unsigned int pll_ppm);
+
+/* Clock flags */
+#define RATE_PROPAGATES (1 << 0) /* Program children too */
+#define ALWAYS_ENABLED (1 << 1) /* Clock cannot be disabled */
+#define RATE_FIXED (1 << 2) /* Fixed clock rate */
+#define CPU_FREQ_TRIG_UPDATE (1 << 3) /* CPUFREQ trig update */
+#define AHB_HIGH_SET_POINT (1 << 4) /* Requires max AHB clock */
+#define AHB_MED_SET_POINT (1 << 5) /* Requires med AHB clock */
unsigned long mxc_decode_pll(unsigned int pll, u32 f_ref);
diff --git a/arch/arm/plat-mxc/include/mach/common.h b/arch/arm/plat-mxc/include/mach/common.h
index 02c3cd004db3..b66644df843c 100644
--- a/arch/arm/plat-mxc/include/mach/common.h
+++ b/arch/arm/plat-mxc/include/mach/common.h
@@ -16,16 +16,26 @@ struct clk;
extern void mx1_map_io(void);
extern void mx21_map_io(void);
+extern void mx25_map_io(void);
extern void mx27_map_io(void);
extern void mx31_map_io(void);
extern void mx35_map_io(void);
+extern void mx37_map_io(void);
+extern void mx51_map_io(void);
extern void mxc_init_irq(void);
-extern void mxc_timer_init(struct clk *timer_clk);
+extern void mxc_timer_init(struct clk *timer_clk, void __iomem *base, int irq);
extern int mx1_clocks_init(unsigned long fref);
extern int mx21_clocks_init(unsigned long lref, unsigned long fref);
+extern int mx25_clocks_init(unsigned long fref);
extern int mx27_clocks_init(unsigned long fref);
extern int mx31_clocks_init(unsigned long fref);
extern int mx35_clocks_init(void);
+extern int mx37_clocks_init(unsigned long ckil, unsigned long osc, unsigned long ckih1, unsigned long ckih2);
+extern int mx51_clocks_init(unsigned long ckil, unsigned long osc, unsigned long ckih1, unsigned long ckih2);
+extern int mxc_init_devices(void);
+extern void mxc_cpu_init(void) __init;
+extern void mxc_cpu_common_init(void);
+extern void __init early_console_setup(char *);
extern int mxc_register_gpios(void);
extern int mxc_register_device(struct platform_device *pdev, void *data);
extern void mxc_set_cpu_type(unsigned int type);
diff --git a/arch/arm/plat-mxc/include/mach/dma.h b/arch/arm/plat-mxc/include/mach/dma.h
new file mode 100644
index 000000000000..d2f6091cebb3
--- /dev/null
+++ b/arch/arm/plat-mxc/include/mach/dma.h
@@ -0,0 +1,293 @@
+/*
+ * Copyright 2004-2009 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 version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __ASM_ARCH_MXC_DMA_H__
+#define __ASM_ARCH_MXC_DMA_H__
+
+#include <linux/scatterlist.h>
+
+#define MXC_DMA_DYNAMIC_CHANNEL 255
+
+#define MXC_DMA_DONE 0x0
+#define MXC_DMA_REQUEST_TIMEOUT 0x1
+#define MXC_DMA_TRANSFER_ERROR 0x2
+
+/*! This defines the list of device ID's for DMA */
+typedef enum mxc_dma_device {
+ MXC_DMA_UART1_RX,
+ MXC_DMA_UART1_TX,
+ MXC_DMA_UART2_RX,
+ MXC_DMA_UART2_TX,
+ MXC_DMA_UART3_RX,
+ MXC_DMA_UART3_TX,
+ MXC_DMA_UART4_RX,
+ MXC_DMA_UART4_TX,
+ MXC_DMA_UART5_RX,
+ MXC_DMA_UART5_TX,
+ MXC_DMA_UART6_RX,
+ MXC_DMA_UART6_TX,
+ MXC_DMA_MMC1_WIDTH_1,
+ MXC_DMA_MMC1_WIDTH_4,
+ MXC_DMA_MMC2_WIDTH_1,
+ MXC_DMA_MMC2_WIDTH_4,
+ MXC_DMA_SSI1_8BIT_RX0,
+ MXC_DMA_SSI1_8BIT_TX0,
+ MXC_DMA_SSI1_16BIT_RX0,
+ MXC_DMA_SSI1_16BIT_TX0,
+ MXC_DMA_SSI1_24BIT_RX0,
+ MXC_DMA_SSI1_24BIT_TX0,
+ MXC_DMA_SSI1_8BIT_RX1,
+ MXC_DMA_SSI1_8BIT_TX1,
+ MXC_DMA_SSI1_16BIT_RX1,
+ MXC_DMA_SSI1_16BIT_TX1,
+ MXC_DMA_SSI1_24BIT_RX1,
+ MXC_DMA_SSI1_24BIT_TX1,
+ MXC_DMA_SSI2_8BIT_RX0,
+ MXC_DMA_SSI2_8BIT_TX0,
+ MXC_DMA_SSI2_16BIT_RX0,
+ MXC_DMA_SSI2_16BIT_TX0,
+ MXC_DMA_SSI2_24BIT_RX0,
+ MXC_DMA_SSI2_24BIT_TX0,
+ MXC_DMA_SSI2_8BIT_RX1,
+ MXC_DMA_SSI2_8BIT_TX1,
+ MXC_DMA_SSI2_16BIT_RX1,
+ MXC_DMA_SSI2_16BIT_TX1,
+ MXC_DMA_SSI2_24BIT_RX1,
+ MXC_DMA_SSI2_24BIT_TX1,
+ MXC_DMA_FIR_RX,
+ MXC_DMA_FIR_TX,
+ MXC_DMA_CSPI1_RX,
+ MXC_DMA_CSPI1_TX,
+ MXC_DMA_CSPI2_RX,
+ MXC_DMA_CSPI2_TX,
+ MXC_DMA_CSPI3_RX,
+ MXC_DMA_CSPI3_TX,
+ MXC_DMA_ATA_RX,
+ MXC_DMA_ATA_TX,
+ MXC_DMA_MEMORY,
+ MXC_DMA_FIFO_MEMORY,
+ MXC_DMA_DSP_PACKET_DATA0_RD,
+ MXC_DMA_DSP_PACKET_DATA0_WR,
+ MXC_DMA_DSP_PACKET_DATA1_RD,
+ MXC_DMA_DSP_PACKET_DATA1_WR,
+ MXC_DMA_DSP_LOG0_CHNL,
+ MXC_DMA_DSP_LOG1_CHNL,
+ MXC_DMA_DSP_LOG2_CHNL,
+ MXC_DMA_DSP_LOG3_CHNL,
+ MXC_DMA_CSI_RX,
+ MXC_DMA_SPDIF_16BIT_TX,
+ MXC_DMA_SPDIF_16BIT_RX,
+ MXC_DMA_SPDIF_32BIT_TX,
+ MXC_DMA_SPDIF_32BIT_RX,
+ MXC_DMA_ASRC_A_RX,
+ MXC_DMA_ASRC_A_TX,
+ MXC_DMA_ASRC_B_RX,
+ MXC_DMA_ASRC_B_TX,
+ MXC_DMA_ASRC_C_RX,
+ MXC_DMA_ASRC_C_TX,
+ MXC_DMA_ASRCA_ESAI,
+ MXC_DMA_ASRCB_ESAI,
+ MXC_DMA_ASRCC_ESAI,
+ MXC_DMA_ASRCA_SSI1_TX0,
+ MXC_DMA_ASRCA_SSI1_TX1,
+ MXC_DMA_ASRCA_SSI2_TX0,
+ MXC_DMA_ASRCA_SSI2_TX1,
+ MXC_DMA_ASRCB_SSI1_TX0,
+ MXC_DMA_ASRCB_SSI1_TX1,
+ MXC_DMA_ASRCB_SSI2_TX0,
+ MXC_DMA_ASRCB_SSI2_TX1,
+ MXC_DMA_ESAI_16BIT_RX,
+ MXC_DMA_ESAI_16BIT_TX,
+ MXC_DMA_ESAI_24BIT_RX,
+ MXC_DMA_ESAI_24BIT_TX,
+ MXC_DMA_TEST_RAM2D2RAM,
+ MXC_DMA_TEST_RAM2RAM2D,
+ MXC_DMA_TEST_RAM2D2RAM2D,
+ MXC_DMA_TEST_RAM2RAM,
+ MXC_DMA_TEST_HW_CHAINING,
+ MXC_DMA_TEST_SW_CHAINING
+} mxc_dma_device_t;
+
+/*! This defines the prototype of callback funtion registered by the drivers */
+typedef void (*mxc_dma_callback_t) (void *arg, int error_status,
+ unsigned int count);
+
+/*! This defines the type of DMA transfer requested */
+typedef enum mxc_dma_mode {
+ MXC_DMA_MODE_READ,
+ MXC_DMA_MODE_WRITE,
+} mxc_dma_mode_t;
+
+/*! This defines the DMA channel parameters */
+typedef struct mxc_dma_channel {
+ unsigned int active:1; /*!< When there has a active tranfer, it is set to 1 */
+ unsigned int lock; /*!< Defines the channel is allocated or not */
+ int curr_buf; /*!< Current buffer */
+ mxc_dma_mode_t mode; /*!< Read or Write */
+ unsigned int channel; /*!< Channel info */
+ unsigned int dynamic:1; /*!< Channel not statically allocated when 1 */
+ char *dev_name; /*!< Device name */
+ void *private; /*!< Private structure for platform */
+ mxc_dma_callback_t cb_fn; /*!< The callback function */
+ void *cb_args; /*!< The argument of callback function */
+} mxc_dma_channel_t;
+
+/*! This structure contains the information about a dma transfer */
+typedef struct mxc_dma_requestbuf {
+ dma_addr_t src_addr; /*!< source address */
+ dma_addr_t dst_addr; /*!< destination address */
+ int num_of_bytes; /*!< the length of this transfer : bytes */
+} mxc_dma_requestbuf_t;
+
+/*! This struct contains the information for asrc special*/
+struct dma_channel_asrc_info {
+ u32 channs; /*!< data channels in asrc */
+};
+
+/*! This struct contains the information for device special*/
+struct dma_channel_info {
+ struct dma_channel_asrc_info asrc; /*!< asrc special information */
+};
+
+#if defined(CONFIG_ARCH_MX27) || defined(CONFIG_ARCH_MX21)
+#include <mach/mx2_dma.h>
+#else
+#include <mach/sdma.h>
+#endif
+
+/*!
+ * This function is generally called by the driver at open time.
+ * The DMA driver would do any initialization steps that is required
+ * to get the channel ready for data transfer.
+ *
+ * @param channel_id a pre-defined id. The peripheral driver would specify
+ * the id associated with its peripheral. This would be
+ * used by the DMA driver to identify the peripheral
+ * requesting DMA and do the necessary setup on the
+ * channel associated with the particular peripheral.
+ * The DMA driver could use static or dynamic DMA channel
+ * allocation.
+ * @param dev_name module name or device name
+ * @param data the customized parameter for special channel.
+ * @return returns a negative number on error if request for a DMA channel did not
+ * succeed, returns the channel number to be used on success.
+ */
+extern int mxc_dma_request_ext(mxc_dma_device_t channel_id, char *dev_name,
+ struct dma_channel_info *info);
+
+static inline int mxc_dma_request(mxc_dma_device_t channel_id, char *dev_name)
+{
+ return mxc_dma_request_ext(channel_id, dev_name, NULL);
+}
+
+/*!
+ * This function is generally called by the driver at close time. The DMA
+ * driver would do any cleanup associated with this channel.
+ *
+ * @param channel_num the channel number returned at request time. This
+ * would be used by the DMA driver to identify the calling
+ * driver and do the necessary cleanup on the channel
+ * associated with the particular peripheral
+ * @return returns a negative number on error or 0 on success
+ */
+extern int mxc_dma_free(int channel_num);
+
+/*!
+ * This function would just configure the buffers specified by the user into
+ * dma channel. The caller must call mxc_dma_enable to start this transfer.
+ *
+ * @param channel_num the channel number returned at request time. This
+ * would be used by the DMA driver to identify the calling
+ * driver and do the necessary cleanup on the channel
+ * associated with the particular peripheral
+ * @param dma_buf an array of physical addresses to the user defined
+ * buffers. The caller must guarantee the dma_buf is
+ * available until the transfer is completed.
+ * @param num_buf number of buffers in the array
+ * @param mode specifies whether this is READ or WRITE operation
+ * @return This function returns a negative number on error if buffer could not be
+ * added with DMA for transfer. On Success, it returns 0
+ */
+extern int mxc_dma_config(int channel_num, mxc_dma_requestbuf_t *dma_buf,
+ int num_buf, mxc_dma_mode_t mode);
+
+/*!
+ * This function would just configure the scatterlist specified by the
+ * user into dma channel. This is a slight variation of mxc_dma_config(),
+ * it is provided for the convenience of drivers that have a scatterlist
+ * passed into them. It is the calling driver's responsibility to have the
+ * correct physical address filled in the "dma_address" field of the
+ * scatterlist.
+ *
+ * @param channel_num the channel number returned at request time. This
+ * would be used by the DMA driver to identify the calling
+ * driver and do the necessary cleanup on the channel
+ * associated with the particular peripheral
+ * @param sg a scatterlist of buffers. The caller must guarantee
+ * the dma_buf is available until the transfer is
+ * completed.
+ * @param num_buf number of buffers in the array
+ * @param num_of_bytes total number of bytes to transfer. If set to 0, this
+ * would imply to use the length field of the scatterlist
+ * for each DMA transfer. Else it would calculate the size
+ * for each DMA transfer.
+ * @param mode specifies whether this is READ or WRITE operation
+ * @return This function returns a negative number on error if buffer could not
+ * be added with DMA for transfer. On Success, it returns 0
+ */
+extern int mxc_dma_sg_config(int channel_num, struct scatterlist *sg,
+ int num_buf, int num_of_bytes,
+ mxc_dma_mode_t mode);
+
+/*!
+ * This function is provided if the driver would like to set/change its
+ * callback function.
+ *
+ * @param channel_num the channel number returned at request time. This
+ * would be used by the DMA driver to identify the calling
+ * driver and do the necessary cleanup on the channel
+ * associated with the particular peripheral
+ * @param callback a callback function to provide notification on transfer
+ * completion, user could specify NULL if he does not wish
+ * to be notified
+ * @param arg an argument that gets passed in to the callback
+ * function, used by the user to do any driver specific
+ * operations.
+ * @return this function returns a negative number on error if the callback
+ * could not be set for the channel or 0 on success
+ */
+extern int mxc_dma_callback_set(int channel_num, mxc_dma_callback_t callback,
+ void *arg);
+
+/*!
+ * This stops the DMA channel and any ongoing transfers. Subsequent use of
+ * mxc_dma_enable() will restart the channel and restart the transfer.
+ *
+ * @param channel_num the channel number returned at request time. This
+ * would be used by the DMA driver to identify the calling
+ * driver and do the necessary cleanup on the channel
+ * associated with the particular peripheral
+ * @return returns a negative number on error or 0 on success
+ */
+extern int mxc_dma_disable(int channel_num);
+
+/*!
+ * This starts DMA transfer. Or it restarts DMA on a stopped channel
+ * previously stopped with mxc_dma_disable().
+ *
+ * @param channel_num the channel number returned at request time. This
+ * would be used by the DMA driver to identify the calling
+ * driver and do the necessary cleanup on the channel
+ * associated with the particular peripheral
+ * @return returns a negative number on error or 0 on success
+ */
+extern int mxc_dma_enable(int channel_num);
+
+#endif
diff --git a/arch/arm/plat-mxc/include/mach/dptc.h b/arch/arm/plat-mxc/include/mach/dptc.h
new file mode 100644
index 000000000000..ac897bbea2a7
--- /dev/null
+++ b/arch/arm/plat-mxc/include/mach/dptc.h
@@ -0,0 +1,186 @@
+
+/*
+ * Copyright 2004-2009 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 __ASM_ARCH_MXC_DPTC_H__
+#define __ASM_ARCH_MXC_DPTC_H__
+
+#include <mach/dvfs_dptc_struct.h>
+
+/*!
+ * DPTC proc file system entry name
+ */
+#define PROC_NODE_NAME "dptc"
+
+int __init init_dptc_controller(dvfs_dptc_params_s * params);
+
+/*!
+ * This function enables the DPTC module. this function updates the DPTC
+ * thresholds, updates the PMIC, unmasks the DPTC interrupt and enables
+ * the DPTC module
+ *
+ * @param params pointer to the DVFS & DPTC driver parameters structure.
+ *
+ * @return 0 if DPTC module was enabled else returns -EINVAL.
+ */
+int start_dptc(dvfs_dptc_params_s * params);
+/*!
+ * This function disables the DPTC module.
+ *
+ * @param params pointer to the DVFS & DPTC driver parameters structure.
+ *
+ * @return 0 if DPTC module was disabled else returns -EINVAL.
+ */
+int stop_dptc(dvfs_dptc_params_s * params);
+/*!
+ * This function updates the drivers current working point index. This index is
+ * used for access the current DTPC table entry and it corresponds to the
+ * current CPU working point measured by the DPTC hardware.
+ *
+ * @param params pointer to the DVFS & DPTC driver parameters structure.
+ * @param new_wp New working point index value to be set.
+ *
+ */
+void set_dptc_wp(dvfs_dptc_params_s * params, int new_wp);
+/*!
+ * This function updates the DPTC threshold registers.
+ *
+ * @param dvfs_dptc_tables_ptr pointer to the DPTC translation table.
+ * @param wp current wp value.
+ * @param freq_index translation table index of the current CPU
+ * frequency.
+ *
+ */
+void update_dptc_thresholds(dvfs_dptc_tables_s * dptc_tables_ptr,
+ int wp, int freq_index);
+/*!
+ * This function adds a new entry to the DPTC log buffer.
+ *
+ * @param params pointer to the DVFS & DPTC driver parameters structure.
+ * @param dptc_log pointer to the DPTC log buffer structure.
+ * @param wp value of the working point index written
+ * to the log buffer.
+ * @param freq_index value of the frequency index written to
+ * the log buffer.
+ *
+ * @return number of log buffer entries.
+ *
+ */
+
+void add_dptc_log_entry(dvfs_dptc_params_s * params,
+ dptc_log_s * dptc_log, int wp, int freq_index);
+
+/*!
+ * This function updates the CPU voltage, produced by PMIC, by calling PMIC
+ * driver functions.
+ *
+ * @param dptc_tables_ptr pointer to the DPTC translation table.
+ * @param wp current wp value.
+ */
+void set_pmic_voltage(dvfs_dptc_tables_s * dptc_tables_ptr, int wp);
+
+/*!
+ * This function enables the DPTC reference circuits.
+ *
+ * @param params pointer to the DVFS & DPTC driver parameters structure.
+ * @param rc_state each high bit specifies which
+ * reference circuite to enable.
+ * @return 0 on success, error code on failure
+ */
+int enable_ref_circuits(dvfs_dptc_params_s * params, unsigned char rc_state);
+
+/*!
+ * This function disables the DPTC reference circuits.
+ *
+ * @param params pointer to the DVFS & DPTC driver parameters structure.
+ * @param rc_state each high bit specifies which
+ * reference circuite to disable
+ * @return 0 on success, error code on failure
+ */
+int disable_ref_circuits(dvfs_dptc_params_s * params, unsigned char rc_state);
+
+/*!
+ * This function is the DPTC Interrupt handler.
+ * This function wakes-up the dptc_workqueue_handler function that handles the
+ * DPTC interrupt.
+ */
+void dptc_irq(void);
+
+/*!
+ * This function updates the drivers current frequency index.This index is
+ * used for access the current DTPC table entry and it corresponds to the
+ * current CPU frequency (each CPU frequency has a separate index number
+ * according to the loaded DPTC table).
+ *
+ * @param params pointer to the DVFS & DPTC driver parameters structure.
+ * @param freq_index New frequency index value to be set.
+ *
+ * @return 0 if the frequency index was updated (the new index is a
+ * valid index and the DPTC module isn't active) else returns
+ * -EINVAL.
+ *
+ */
+int set_dptc_curr_freq(dvfs_dptc_params_s * params, unsigned int freq_index);
+
+#ifdef CONFIG_MXC_DVFS_SDMA
+/*
+ * DPTC SDMA callback.
+ * Updates the PMIC voltage
+ *
+ * @param params pointer to the DVFS & DPTC driver parameters structure.
+ */
+void dptc_sdma_callback(dvfs_dptc_params_s * params);
+#endif
+
+/*!
+ * This function is called to put the DPTC in a low power state.
+ *
+ * @param pdev the device structure used to give information on which
+ * device to suspend (not relevant for DPTC)
+ * @param state the power state the device is entering
+ *
+ * @return The function always returns 0.
+ */
+int mxc_dptc_suspend(struct platform_device *pdev, pm_message_t state);
+
+/*!
+ * This function is called to put the DPTC in a low power state.
+ *
+ */
+void dptc_suspend(void);
+
+/*!
+ * This function is called to resume the DPTC from a low power state.
+ *
+ * @param pdev the device structure used to give information on which
+ * device to suspend (not relevant for DPTC)
+ *
+ * @return The function always returns 0.
+ */
+int mxc_dptc_resume(struct platform_device *dev);
+
+/*!
+ * This function is called to resume the DPTC from a low power state.
+ *
+ */
+void dptc_resume(void);
+
+/*!
+ * This function initializes DPTC according to turbo mode status
+ *
+ * @param status Turbo mode disable, 1 - turbo mode enabled
+ *
+ */
+void dptc_set_turbo_mode(unsigned int status);
+
+#endif /* __ASM_ARCH_MXC_DPTC_H__ */
diff --git a/arch/arm/plat-mxc/include/mach/dvfs_dptc_struct.h b/arch/arm/plat-mxc/include/mach/dvfs_dptc_struct.h
new file mode 100644
index 000000000000..006bcf293d63
--- /dev/null
+++ b/arch/arm/plat-mxc/include/mach/dvfs_dptc_struct.h
@@ -0,0 +1,169 @@
+/*
+ * Copyright 2004-2009 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
+ */
+
+/*!
+ * @file arch-mxc/dvfs_dptc_struct.h
+ *
+ * @brief MXC dvfs & dptc structure definitions file.
+ *
+ * @ingroup PM_MX27 PM_MX31 PM_MXC91321 PM_MXC91311
+ */
+#ifndef __ASM_ARCH_MXC_DVFS_DPTC_STRUCT_H__
+#define __ASM_ARCH_MXC_DVFS_DPTC_STRUCT_H__
+
+#include <linux/semaphore.h>
+#include <mach/pm_api.h>
+
+/*!
+ * Number of entries in the DPTC log buffer
+ */
+#define LOG_ENTRIES 1024
+
+/*!
+ * Log buffer Structure.\n
+ * This structure records the DPTC changes. \n
+ * This structure can be read by the user using the proc file system DPTC read entry.
+ */
+typedef struct {
+ /*!
+ * Index to the head of the log buffer
+ */
+ int head;
+
+ /*!
+ * Index to the tail of the log buffer
+ */
+ int tail;
+
+ /*!
+ * Mutex to allow access to the log buffer
+ */
+ struct semaphore mutex;
+
+ /*!
+ * Array of log buffer entries
+ */
+ dptc_log_entry_s entries[LOG_ENTRIES];
+} dptc_log_s;
+
+/*!
+ * DPTC driver data structure.\n
+ * Holds all driver parameters and data structures.
+ */
+typedef struct {
+ /*!
+ * This variable holds the current frequency index
+ */
+ int current_freq_index;
+
+ /*!
+ * Boolean variable, if TRUE the DPTC module is enabled
+ * if FALSE the DPTC module is disabled
+ */
+ int dptc_is_active;
+
+ /*!
+ * Boolean variable, if TRUE turbo mode enable
+ * if FALSE turbo mode disabled
+ */
+ int turbo_mode_active;
+
+ /*!
+ * Boolean variable, if TRUE the DVFS module is enabled
+ * if FALSE the DPTC module is disabled
+ */
+ int dvfs_is_active;
+
+ /*!
+ * Boolean variable, if TRUE the DPTC module is suspended
+ */
+ int suspended;
+
+ unsigned char rc_state;
+
+ /*!
+ * Pointer to the DVFS & DPTC translation table
+ */
+ dvfs_dptc_tables_s *dvfs_dptc_tables_ptr;
+
+ /*!
+ * The DPTC log buffer
+ */
+ dptc_log_s dptc_log_buffer;
+
+ /*!
+ * The DVFS log buffer
+ */
+ unsigned char *dvfs_log_buffer;
+
+ /*!
+ * The DVFS log buffer physical address (for SDMA)
+ */
+ dma_addr_t dvfs_log_buffer_phys;
+
+#ifdef CONFIG_MXC_DVFS_SDMA
+ /*!
+ * SDMA channel number
+ */
+ int sdma_channel;
+
+ /*!
+ * This holds the previous working point
+ */
+ int prev_wp;
+
+ /*!
+ * Wait entry for predictive DVFS
+ */
+ wait_queue_head_t dvfs_pred_wait;
+#endif
+
+ /*!
+ * This holds the current DVFS mode
+ */
+ unsigned int dvfs_mode;
+
+ /*!
+ * Log buffer read pointer
+ */
+ unsigned char *read_ptr;
+
+ /*
+ * Number of characters in log buffer
+ */
+ int chars_in_buffer;
+} dvfs_dptc_params_s;
+
+/*!
+ * This struct contains the array with values of supported frequencies in Hz
+ */
+typedef struct {
+ /*
+ * Number of supported states
+ */
+ unsigned int num_of_states;
+ /*!
+ * Array of frequencies
+ */
+ unsigned int *freqs;
+} dvfs_states_table;
+
+/*
+ * if not defined define TREU and FALSE values.
+ */
+#ifndef TRUE
+#define TRUE 1
+#define FALSE 0
+#endif /* TRUE */
+
+#endif
diff --git a/arch/arm/plat-mxc/include/mach/entry-macro.S b/arch/arm/plat-mxc/include/mach/entry-macro.S
index 5f01d60da845..92f553baf447 100644
--- a/arch/arm/plat-mxc/include/mach/entry-macro.S
+++ b/arch/arm/plat-mxc/include/mach/entry-macro.S
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2007 Lennert Buytenhek <buytenh@wantstofly.org>
- * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2004-2009 Freescale Semiconductor, Inc. All Rights Reserved.
*/
/*
@@ -18,10 +18,14 @@
.endm
.macro get_irqnr_preamble, base, tmp
+#ifdef CONFIG_MXC_TZIC
+ ldr \base, =TZIC_IO_ADDRESS(TZIC_BASE_ADDR)
+#else
ldr \base, =AVIC_IO_ADDRESS(AVIC_BASE_ADDR)
#ifdef CONFIG_MXC_IRQ_PRIOR
ldr r4, [\base, #AVIC_NIMASK]
#endif
+#endif
.endm
.macro arch_ret_to_user, tmp1, tmp2
@@ -31,6 +35,32 @@
@ and returns its number in irqnr
@ and returns if an interrupt occured in irqstat
.macro get_irqnr_and_base, irqnr, irqstat, base, tmp
+#ifdef CONFIG_MXC_TZIC
+ @ Load offset & priority of the highest priority
+ @ interrupt pending.
+ @ 0xD80 is HIPND0 register
+ ldr \irqnr, =0
+ ldr \irqstat, =0x0D80
+1000:
+ ldr \tmp, [\irqstat, \base]
+ cmp \tmp, #0
+ bne 1001f
+ addeq \irqnr, \irqnr, #32
+ addeq \irqstat, \irqstat, #4
+ cmp \irqnr, #128
+ blo 1000b
+ b 2001f
+1001: ldr \irqstat, =1
+1002: tst \tmp, \irqstat
+ bne 2002f
+ movs \tmp, \tmp, lsr #1
+ addne \irqnr, \irqnr, #1
+ bne 1002b
+2001:
+ ldr \irqnr, =0
+2002:
+ movs \irqnr, \irqnr
+#else
@ Load offset & priority of the highest priority
@ interrupt pending from AVIC_NIVECSR
ldr \irqstat, [\base, #0x40]
@@ -44,6 +74,7 @@
strne \tmp, [\base, #AVIC_NIMASK]
streq r4, [\base, #AVIC_NIMASK]
#endif
+#endif
.endm
@ irq priority table (not used)
diff --git a/arch/arm/plat-mxc/include/mach/fsl_usb.h b/arch/arm/plat-mxc/include/mach/fsl_usb.h
new file mode 100644
index 000000000000..2149d38c91c5
--- /dev/null
+++ b/arch/arm/plat-mxc/include/mach/fsl_usb.h
@@ -0,0 +1,86 @@
+/*
+ * Copyright 2005-2009 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
+ */
+
+/*
+ * USB Host side, platform-specific functionality.
+ */
+
+#include <linux/usb/fsl_xcvr.h>
+#include <mach/arc_otg.h>
+
+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 + 0x1a8);
+ writel(temp | USBMODE_CM_HOST, hcd->regs + 0x1a8);
+}
+
+/* Needed for enable PP and i2c/serial transceivers */
+static inline void
+fsl_platform_set_vbus_power(struct fsl_usb2_platform_data *pdata, int on)
+{
+ u32 temp;
+
+ /* HCSPARAMS */
+ temp = readl(pdata->regs + 0x104);
+ /* Port Power Control */
+ if (temp & HCSPARAMS_PPC) {
+ temp = readl(pdata->regs + FSL_SOC_USB_PORTSC1);
+ writel(temp | PORT_POWER, pdata->regs + FSL_SOC_USB_PORTSC1);
+ }
+
+ 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)
+{
+ struct fsl_usb2_platform_data *pdata;
+ unsigned int temp;
+
+ pdata = hcd->self.controller->platform_data;
+ if (pdata->change_ahb_burst) {
+ temp = readl(hcd->regs + FSL_SOC_USB_SBUSCFG);
+ writel((temp & (~(0x7))) | pdata->ahb_burst_mode,
+ hcd->regs + FSL_SOC_USB_SBUSCFG);
+ }
+
+ /* Increase TX fifo threshold for USB+ATA for i.mx35 2.0 */
+ if (cpu_is_mx35_rev(CHIP_REV_2_0) >= 1) {
+ temp = readl(hcd->regs + FSL_SOC_USB_TXFILLTUNING);
+ /* Change TX FIFO threshold to be 0x20 */
+ writel((temp & (~(0x3f << 16))) | (0x20 << 16),
+ hcd->regs + FSL_SOC_USB_TXFILLTUNING);
+ }
+}
diff --git a/arch/arm/plat-mxc/include/mach/fsl_usb_gadget.h b/arch/arm/plat-mxc/include/mach/fsl_usb_gadget.h
new file mode 100644
index 000000000000..d3c581e70765
--- /dev/null
+++ b/arch/arm/plat-mxc/include/mach/fsl_usb_gadget.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2005-2008 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
+ */
+
+/*
+ * 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-mxc/include/mach/gpio.h b/arch/arm/plat-mxc/include/mach/gpio.h
index 894d2f87c856..9f382e64ccfd 100644
--- a/arch/arm/plat-mxc/include/mach/gpio.h
+++ b/arch/arm/plat-mxc/include/mach/gpio.h
@@ -33,9 +33,12 @@
struct mxc_gpio_port {
void __iomem *base;
int irq;
+ int irq_high;
int virtual_irq_start;
struct gpio_chip chip;
u32 both_edges;
+ u32 suspend_wakeup;
+ u32 saved_wakeup;
};
int mxc_gpio_init(struct mxc_gpio_port*, int);
diff --git a/arch/arm/plat-mxc/include/mach/hardware.h b/arch/arm/plat-mxc/include/mach/hardware.h
index 42e4ee37ca1f..b110686e3651 100644
--- a/arch/arm/plat-mxc/include/mach/hardware.h
+++ b/arch/arm/plat-mxc/include/mach/hardware.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2004-2009 Freescale Semiconductor, Inc. All Rights Reserved.
* Copyright 2008 Juergen Beisert, kernel@pengutronix.de
*
* This program is free software; you can redistribute it and/or
@@ -22,9 +22,33 @@
#include <asm/sizes.h>
+/*
+ * ---------------------------------------------------------------------------
+ * Processor specific defines
+ * ---------------------------------------------------------------------------
+ */
+#define CHIP_REV_1_0 0x10
+#define CHIP_REV_1_1 0x11
+#define CHIP_REV_1_2 0x12
+#define CHIP_REV_1_3 0x13
+#define CHIP_REV_2_0 0x20
+#define CHIP_REV_2_1 0x21
+#define CHIP_REV_2_2 0x22
+#define CHIP_REV_2_3 0x23
+#define CHIP_REV_3_0 0x30
+#define CHIP_REV_3_1 0x31
+#define CHIP_REV_3_2 0x32
+
+#define BOARD_REV_1 0x000
+#define BOARD_REV_2 0x100
+
#ifdef CONFIG_ARCH_MX3
#include <mach/mx3x.h>
#include <mach/mx31.h>
+#endif
+
+#ifdef CONFIG_ARCH_MX35
+#include <mach/mx3x.h>
#include <mach/mx35.h>
#endif
@@ -42,6 +66,44 @@
# include <mach/mx1.h>
#endif
+#ifdef CONFIG_ARCH_MX37
+#include <mach/mx37.h>
+#endif
+
+#ifdef CONFIG_ARCH_MX51
+#include <mach/mx51.h>
+#endif
+
+#ifdef CONFIG_ARCH_MX25
+#include <mach/mx25.h>
+#endif
+
+#ifndef __ASSEMBLY__
+extern unsigned int system_rev;
+#define board_is_rev(rev) (((system_rev & 0x0F00) == rev) ? 1 : 0)
+#endif
+
#include <mach/mxc.h>
+/*!
+ * Register an interrupt handler for the SMN as well as the SCC. In some
+ * implementations, the SMN is not connected at all, and in others, it is
+ * on the same interrupt line as the SCM. Comment this line out accordingly
+ */
+#define USE_SMN_INTERRUPT
+
+/*!
+ * This option is used to set or clear the RXDMUXSEL bit in control reg 3.
+ * Certain platforms need this bit to be set in order to receive Irda data.
+ */
+#define MXC_UART_IR_RXDMUX 0x0004
+/*!
+ * This option is used to set or clear the RXDMUXSEL bit in control reg 3.
+ * Certain platforms need this bit to be set in order to receive UART data.
+ */
+#define MXC_UART_RXDMUX 0x0004
+
+#ifndef MXC_INT_FORCE
+#define MXC_INT_FORCE -1
+#endif
#endif /* __ASM_ARCH_MXC_HARDWARE_H__ */
diff --git a/arch/arm/plat-mxc/include/mach/hw_events.h b/arch/arm/plat-mxc/include/mach/hw_events.h
new file mode 100644
index 000000000000..f0aa3ad7a266
--- /dev/null
+++ b/arch/arm/plat-mxc/include/mach/hw_events.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2007-2008 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
+ */
+
+/*!
+ * hw_events.h
+ * include the headset/cvbs interrupt detect
+ */
+
+#ifndef HW_EVENT_H
+#define HW_EVENT_H
+
+#define HW_EVENT_GROUP 2
+#define HWE_DEF_PRIORITY 1
+#define HWE_HIGH_PRIORITY 0
+
+typedef enum {
+
+ HWE_PHONEJACK_PLUG = 0,
+ HWE_BAT_CHARGER_PLUG,
+ HWE_BAT_CHARGER_OVERVOLTAGE,
+ HWE_BAT_BATTERY_LOW,
+ HWE_BAT_POWER_FAILED,
+ HWE_BAT_CHARGER_FULL,
+ HWE_POWER_KEY,
+} HW_EVENT_T;
+
+typedef enum {
+
+ PJT_NONE = 0,
+ PJT_CVBS,
+ PJT_HEADSET,
+} PHONEJACK_TYPE;
+
+typedef enum {
+
+ PWRK_UNPRESS = 0,
+ PWRK_PRESS,
+} POWERKEY_TYPE;
+
+typedef enum {
+
+ UNPLUG = 0,
+ PLUGGED,
+} PLUG_TYPE;
+
+struct mxc_hw_event {
+ unsigned int event;
+ int args;
+};
+
+#ifdef __KERNEL__
+extern int hw_event_send(int priority, struct mxc_hw_event *new_event);
+#endif
+
+#endif /* HW_EVENT_H */
diff --git a/arch/arm/plat-mxc/include/mach/io.h b/arch/arm/plat-mxc/include/mach/io.h
index b4f2de769466..311bb6337b64 100644
--- a/arch/arm/plat-mxc/include/mach/io.h
+++ b/arch/arm/plat-mxc/include/mach/io.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2004-2008 Freescale Semiconductor, Inc. All Rights Reserved.
*/
/*
@@ -14,29 +14,33 @@
/* Allow IO space to be anywhere in the memory */
#define IO_SPACE_LIMIT 0xffffffff
-#ifdef CONFIG_ARCH_MX3
-#define __arch_ioremap __mx3_ioremap
-#define __arch_iounmap __iounmap
+extern void __iomem *__mxc_ioremap(unsigned long cookie, size_t size,
+ unsigned int mtype);
-static inline void __iomem *
-__mx3_ioremap(unsigned long phys_addr, size_t size, unsigned int mtype)
-{
- if (mtype == MT_DEVICE) {
- /* Access all peripherals below 0x80000000 as nonshared device
- * but leave l2cc alone.
- */
- if ((phys_addr < 0x80000000) && ((phys_addr < 0x30000000) ||
- (phys_addr >= 0x30000000 + SZ_1M)))
- mtype = MT_DEVICE_NONSHARED;
- }
-
- return __arm_ioremap(phys_addr, size, mtype);
-}
-#endif
+#define __arch_ioremap(a, s, f) __mxc_ioremap(a, s, f)
+#define __arch_iounmap __iounmap
/* io address mapping macro */
#define __io(a) __typesafe_io(a)
#define __mem_pci(a) (a)
+/*!
+ * This function is called to read a CPLD register over CSPI.
+ *
+ * @param offset number of the cpld register to be read
+ *
+ * @return Returns 0 on success -1 on failure.
+ */
+unsigned int __weak spi_cpld_read(unsigned int offset);
+
+/*!
+ * This function is called to write to a CPLD register over CSPI.
+ *
+ * @param offset number of the cpld register to be written
+ * @param reg_val value to be written
+ *
+ * @return Returns 0 on success -1 on failure.
+ */
+unsigned int __weak spi_cpld_write(unsigned int offset, unsigned int reg_val);
#endif
diff --git a/arch/arm/plat-mxc/include/mach/irqs.h b/arch/arm/plat-mxc/include/mach/irqs.h
index 518a36504b88..59a9c4548634 100644
--- a/arch/arm/plat-mxc/include/mach/irqs.h
+++ b/arch/arm/plat-mxc/include/mach/irqs.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2004-2009 Freescale Semiconductor, Inc. All Rights Reserved.
*/
/*
@@ -12,9 +12,9 @@
#define __ASM_ARCH_MXC_IRQS_H__
/*
- * So far all i.MX SoCs have 64 internal interrupts
+ * So far all i.MX SoCs have 128 internal interrupts
*/
-#define MXC_INTERNAL_IRQS 64
+#define MXC_INTERNAL_IRQS 128
#define MXC_GPIO_IRQ_START MXC_INTERNAL_IRQS
@@ -22,8 +22,14 @@
#define MXC_GPIO_IRQS (32 * 4)
#elif defined CONFIG_ARCH_MX2
#define MXC_GPIO_IRQS (32 * 6)
-#elif defined CONFIG_ARCH_MX3
+#elif defined CONFIG_ARCH_MX25
+#define MXC_GPIO_IRQS (32 * 4)
+#elif defined CONFIG_ARCH_MX3 || defined CONFIG_ARCH_MX35
+#define MXC_GPIO_IRQS (32 * 3)
+#elif defined CONFIG_ARCH_MX37
#define MXC_GPIO_IRQS (32 * 3)
+#elif defined CONFIG_ARCH_MX51
+#define MXC_GPIO_IRQS (32 * 4)
#endif
/*
@@ -33,7 +39,14 @@
* within sensible limits.
*/
#define MXC_BOARD_IRQ_START (MXC_INTERNAL_IRQS + MXC_GPIO_IRQS)
+#ifdef CONFIG_MXC_PSEUDO_IRQS
+#define MXC_PSEUDO_IO_BASE (MXC_BOARD_IRQ_START + 16)
+#define MXC_MAX_PSEUDO_IO_LINES 16
+#define MXC_BOARD_IRQS 32
+#else
#define MXC_BOARD_IRQS 16
+#define MXC_MAX_PSEUDO_IO_LINES 0
+#endif
#define MXC_IPU_IRQ_START (MXC_BOARD_IRQ_START + MXC_BOARD_IRQS)
@@ -52,4 +65,17 @@ extern int imx_irq_set_priority(unsigned char irq, unsigned char prio);
/* switch betwean IRQ and FIQ */
extern int mxc_set_irq_fiq(unsigned int irq, unsigned int type);
+#define MXC_IRQ_TO_EXPIO(irq) ((irq) - MXC_BOARD_IRQ_START)
+
+/*
+ * This function is used to get the AVIC Lo and Hi interrupts
+ * that are enabled as wake up sources to wake up the core from suspend
+ */
+void mxc_get_wake_irq(u32 * wake_src[]);
+
+/* Define interrupt number for OProfile */
+#if defined CONFIG_ARCH_MX51
+#define MXC_INT_PMU 77
+#endif
+
#endif /* __ASM_ARCH_MXC_IRQS_H__ */
diff --git a/arch/arm/plat-mxc/include/mach/memory.h b/arch/arm/plat-mxc/include/mach/memory.h
index 6065e00176ed..c898f884a371 100644
--- a/arch/arm/plat-mxc/include/mach/memory.h
+++ b/arch/arm/plat-mxc/include/mach/memory.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2004-2009 Freescale Semiconductor, Inc. All Rights Reserved.
*/
/*
@@ -11,6 +11,9 @@
#ifndef __ASM_ARCH_MXC_MEMORY_H__
#define __ASM_ARCH_MXC_MEMORY_H__
+#include <asm/page.h>
+#include <asm/sizes.h>
+
#if defined CONFIG_ARCH_MX1
#define PHYS_OFFSET UL(0x08000000)
#elif defined CONFIG_ARCH_MX2
@@ -24,6 +27,19 @@
#define PHYS_OFFSET UL(0x80000000)
#endif
+#ifdef CONFIG_ARCH_MX51
+#define PHYS_OFFSET UL(0x90000000)
+#endif
+
+#ifdef CONFIG_ARCH_MX37
+#define PHYS_OFFSET UL(0x40000000)
+#endif
+
+#ifndef PHYS_OFFSET
+#define PHYS_OFFSET UL(0x80000000)
+#endif
+
+/* Size of contiguous memory for DMA and other h/w blocks */
#if defined(CONFIG_MX1_VIDEO)
/*
* Increase size of DMA-consistent memory region.
@@ -40,4 +56,35 @@
#define CONSISTENT_DMA_SIZE SZ_8M
#endif /* CONFIG_MX3_VIDEO */
+#ifdef CONFIG_ARCH_MX51
+#define CONSISTENT_DMA_SIZE (64 * SZ_1M)
+#else
+#define CONSISTENT_DMA_SIZE (32 * SZ_1M)
+#endif
+
+#ifndef __ASSEMBLY__
+
+#ifdef CONFIG_DMA_ZONE_SIZE
+#define MXC_DMA_ZONE_SIZE ((CONFIG_DMA_ZONE_SIZE * SZ_1M) >> PAGE_SHIFT)
+#else
+#define MXC_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] - MXC_DMA_ZONE_SIZE;
+ zone_size[0] = MXC_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
+
#endif /* __ASM_ARCH_MXC_MEMORY_H__ */
diff --git a/arch/arm/plat-mxc/include/mach/mmc.h b/arch/arm/plat-mxc/include/mach/mmc.h
index de2128dada5c..80cc61c175ea 100644
--- a/arch/arm/plat-mxc/include/mach/mmc.h
+++ b/arch/arm/plat-mxc/include/mach/mmc.h
@@ -33,4 +33,21 @@ struct imxmmc_platform_data {
void (*setpower)(struct device *, unsigned int vdd);
};
+struct mxc_mmc_platform_data {
+ unsigned int ocr_mask; /* available voltages */
+ unsigned int vendor_ver;
+ unsigned int caps;
+ unsigned int min_clk;
+ unsigned int max_clk;
+ unsigned int clk_flg; /* 1 clock enable, 0 not */
+ unsigned int reserved:16;
+ unsigned int card_fixed:1;
+ unsigned int card_inserted_state:1;
+// u32 (*translate_vdd)(struct device *, unsigned int);
+ unsigned int (*status) (struct device *);
+ int (*wp_status) (struct device *);
+ char *power_mmc;
+ char *clock_mmc;
+};
+
#endif
diff --git a/arch/arm/plat-mxc/include/mach/mtd-xip.h b/arch/arm/plat-mxc/include/mach/mtd-xip.h
index 1ab1bba5688d..0e74f19b1eae 100644
--- a/arch/arm/plat-mxc/include/mach/mtd-xip.h
+++ b/arch/arm/plat-mxc/include/mach/mtd-xip.h
@@ -4,6 +4,7 @@
* Do not include this file directly. It's included from linux/mtd/xip.h
*
* Copyright (C) 2008 Darius Augulis <augulis.darius@gmail.com>, Teltonika, Inc.
+ * Copyright 2007-2009 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 version 2 as
@@ -11,12 +12,14 @@
*
*/
+#include <linux/clocksource.h>
+#include <mach/hardware.h>
+#include <mach/system.h>
#include <mach/mxc_timer.h>
#ifndef __ARCH_IMX_MTD_XIP_H__
#define __ARCH_IMX_MTD_XIP_H__
-#ifdef CONFIG_ARCH_MX1
/* AITC registers */
#define AITC_BASE IO_ADDRESS(AVIC_BASE_ADDR)
#define NIPNDH (AITC_BASE + 0x58)
@@ -26,9 +29,34 @@
/* MTD macros */
#define xip_irqpending() ((__raw_readl(INTENABLEH) & __raw_readl(NIPNDH)) \
|| (__raw_readl(INTENABLEL) & __raw_readl(NIPNDL)))
+#ifdef CONFIG_ARCH_MX1
#define xip_currtime() (__raw_readl(TIMER_BASE + MXC_TCN))
#define xip_elapsed_since(x) (signed)((__raw_readl(TIMER_BASE + MXC_TCN) - (x)) / 96)
#define xip_cpu_idle() asm volatile ("mcr p15, 0, %0, c7, c0, 4" :: "r" (0))
+#else
+
+extern struct clocksource *mtd_xip_clksrc;
+
+#define xip_currtime() (unsigned long)clocksource_read(mtd_xip_clksrc)
+
+#if CLOCK_TICK_RATE > 1000000
+#define NUMERATOR 1
+#define DENOMINATOR (CLOCK_TICK_RATE/1000000 + 1)
+#else
+#define NUMERATOR (1000000/CLOCK_TICK_RATE)
+#define DENOMINATOR 1
+#endif
+
+static inline unsigned long xip_elapsed_since(unsigned long x)
+{
+ return (((xip_currtime() - x) * NUMERATOR) / DENOMINATOR);
+}
+
+/*
+ * Wait For Interrupt command for XIP kernel to put CPU in Idle mode
+ */
+#define xip_cpu_idle() arch_idle()
+
#endif /* CONFIG_ARCH_MX1 */
#endif /* __ARCH_IMX_MTD_XIP_H__ */
diff --git a/arch/arm/plat-mxc/include/mach/mx25.h b/arch/arm/plat-mxc/include/mach/mx25.h
new file mode 100644
index 000000000000..6b1622906c20
--- /dev/null
+++ b/arch/arm/plat-mxc/include/mach/mx25.h
@@ -0,0 +1,462 @@
+/*
+ * Copyright 2008-2009 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
+ */
+
+/*!
+ * @file arch-mxc/mx25.h
+ * @brief This file contains register definitions.
+ *
+ * @ingroup MSL_MX25
+ */
+
+#ifndef __ASM_ARCH_MXC_MX25_H__
+#define __ASM_ARCH_MXC_MX25_H__
+
+#ifndef __ASM_ARCH_MXC_HARDWARE_H__
+#error "Do not include directly."
+#endif
+
+/*!
+ * Define this option to specify we are using the newer SDMA module.
+ */
+#define MXC_SDMA_V2
+
+/*
+ * MX25 memory map:
+ *
+ * Virt Phys Size What
+ * ---------------------------------------------------------------------------
+ * FC000000 43F00000 1M AIPS 1
+ * FC100000 50000000 1M SPBA
+ * FC200000 53F00000 1M AIPS 2
+ * FC300000 60000000 1M ROMPATCH (128M)
+ * FC400000 68000000 1M ASIC (128M)
+ * FC500000 78000000 128K FBC RAM (IRAM)
+ * 80000000 256M SDRAM0
+ * 90000000 256M SDRAM1
+ * A0000000 128M CS0 Flash
+ * A8000000 128M CS1 Flash
+ * B0000000 32M CS2 SRAM
+ * B2000000 32M CS3
+ * B4000000 32M CS4
+ * B6000000 32M CS5
+ * FC520000 B8000000 64K SDRAM, WEIM, M3IF, EMI controllers
+ * FC530000 BB000000 8K NFC
+ */
+
+/*
+ * IRAM
+ */
+#define IRAM_BASE_ADDR 0x78000000 /* internal ram */
+#define IRAM_BASE_ADDR_VIRT 0xFC500000
+#define IRAM_SIZE SZ_128K
+
+#ifndef CONFIG_SDMA_IRAM
+#define CONFIG_SDMA_IRAM_SIZE 0
+#endif
+#ifdef CONFIG_SND_MXC_SOC_IRAM
+#define SND_RAM_SIZE 0x10000
+#else
+#define SND_RAM_SIZE 0
+#endif
+
+#define SND_RAM_BASE_ADDR (IRAM_BASE_ADDR + CONFIG_SDMA_IRAM_SIZE)
+
+#define USB_IRAM_BASE_ADDR (SND_RAM_BASE_ADDR + SND_RAM_SIZE)
+#ifdef CONFIG_USB_STATIC_IRAM_PPH
+#define USB_IRAM_SIZE (2*SZ_8K)
+#else
+#define USB_IRAM_SIZE 0
+#endif
+
+/*
+ * AIPS 1
+ */
+#define AIPS1_BASE_ADDR 0x43F00000
+#define AIPS1_BASE_ADDR_VIRT 0xFC000000
+#define AIPS1_SIZE SZ_1M
+
+#define MAX_BASE_ADDR (AIPS1_BASE_ADDR + 0x00004000)
+#define CLKCTL_BASE_ADDR (AIPS1_BASE_ADDR + 0x00008000)
+#define ETB_SLOT4_BASE_ADDR (AIPS1_BASE_ADDR + 0x0000C000)
+#define ETB_SLOT5_BASE_ADDR (AIPS1_BASE_ADDR + 0x00010000)
+#define AAPE_BASE_ADDR (AIPS1_BASE_ADDR + 0x00014000)
+#define I2C_BASE_ADDR (AIPS1_BASE_ADDR + 0x00080000)
+#define I2C3_BASE_ADDR (AIPS1_BASE_ADDR + 0x00084000)
+#define CAN1_BASE_ADDR (AIPS1_BASE_ADDR + 0x00088000)
+#define CAN3_BASE_ADDR (AIPS1_BASE_ADDR + 0x0008C000)
+#define UART1_BASE_ADDR (AIPS1_BASE_ADDR + 0x00090000)
+#define UART2_BASE_ADDR (AIPS1_BASE_ADDR + 0x00094000)
+#define I2C2_BASE_ADDR (AIPS1_BASE_ADDR + 0x00098000)
+#define OWIRE_BASE_ADDR (AIPS1_BASE_ADDR + 0x0009C000)
+#define ATA_BASE_ADDR (AIPS1_BASE_ADDR + 0x000A0000)
+#define CSPI1_BASE_ADDR (AIPS1_BASE_ADDR + 0x000A4000)
+#define KPP_BASE_ADDR (AIPS1_BASE_ADDR + 0x000A8000)
+#define IOMUXC_BASE_ADDR (AIPS1_BASE_ADDR + 0x000AC000)
+#define AUDMUX_BASE_ADDR (AIPS1_BASE_ADDR + 0x000B0000)
+#define ECT_A_BASE_ADDR (AIPS1_BASE_ADDR + 0x000B8000)
+#define ECT_B_BASE_ADDR (AIPS1_BASE_ADDR + 0x000BC000)
+
+/*
+ * SPBA global module enabled #0
+ */
+#define SPBA0_BASE_ADDR 0x50000000
+#define SPBA0_BASE_ADDR_VIRT 0xFC100000
+#define SPBA0_SIZE SZ_1M
+
+#define CSPI3_BASE_ADDR (SPBA0_BASE_ADDR + 0x00004000)
+#define UART4_BASE_ADDR (SPBA0_BASE_ADDR + 0x00008000)
+#define UART3_BASE_ADDR (SPBA0_BASE_ADDR + 0x0000C000)
+#define CSPI2_BASE_ADDR (SPBA0_BASE_ADDR + 0x00010000)
+#define SSI2_BASE_ADDR (SPBA0_BASE_ADDR + 0x00014000)
+#define ESAI_BASE_ADDR (SPBA0_BASE_ADDR + 0x00018000)
+#define ATA_DMA_BASE_ADDR (SPBA0_BASE_ADDR + 0x00020000)
+#define SIM1_BASE_ADDR (SPBA0_BASE_ADDR + 0x00024000)
+#define SIM2_BASE_ADDR (SPBA0_BASE_ADDR + 0x00028000)
+#define UART5_BASE_ADDR (SPBA0_BASE_ADDR + 0x0002C000)
+#define TSC_BASE_ADDR (SPBA0_BASE_ADDR + 0x00030000)
+#define SSI1_BASE_ADDR (SPBA0_BASE_ADDR + 0x00034000)
+#define FEC_BASE_ADDR (SPBA0_BASE_ADDR + 0x00038000)
+#define SPBA_CTRL_BASE_ADDR (SPBA0_BASE_ADDR + 0x0003C000)
+
+/*!
+ * defines for SPBA modules
+ */
+#define SPBA_CSPI3 (0x1 << 2)
+#define SPBA_UART4 (0x2 << 2)
+#define SPBA_UART3 (0x3 << 2)
+#define SPBA_CSPI2 (0x4 << 2)
+#define SPBA_SSI2 (0x5 << 2)
+#define SPBA_ESAI (0x6 << 2)
+#define SPBA_ATA (0x8 << 2)
+#define SPBA_SIM1 (0x9 << 2)
+#define SPBA_SIM2 (0xA << 2)
+#define SPBA_UART5 (0xB << 2)
+#define SPBA_ANALOG (0xC << 2)
+#define SPBA_SSI1 (0xD << 2)
+#define SPBA_FEC (0xE << 2)
+
+/*!
+ * Defines for modules using static and dynamic DMA channels
+ */
+#define MXC_DMA_CHANNEL_IRAM 30
+#define MXC_DMA_CHANNEL_UART1_RX MXC_DMA_DYNAMIC_CHANNEL
+#define MXC_DMA_CHANNEL_UART1_TX MXC_DMA_DYNAMIC_CHANNEL
+#define MXC_DMA_CHANNEL_UART2_RX MXC_DMA_DYNAMIC_CHANNEL
+#define MXC_DMA_CHANNEL_UART2_TX MXC_DMA_DYNAMIC_CHANNEL
+#define MXC_DMA_CHANNEL_UART3_RX MXC_DMA_DYNAMIC_CHANNEL
+#define MXC_DMA_CHANNEL_UART3_TX MXC_DMA_DYNAMIC_CHANNEL
+#define MXC_DMA_CHANNEL_UART4_RX MXC_DMA_DYNAMIC_CHANNEL
+#define MXC_DMA_CHANNEL_UART4_TX MXC_DMA_DYNAMIC_CHANNEL
+#define MXC_DMA_CHANNEL_UART5_RX MXC_DMA_DYNAMIC_CHANNEL
+#define MXC_DMA_CHANNEL_UART5_TX MXC_DMA_DYNAMIC_CHANNEL
+#define MXC_DMA_CHANNEL_MMC1 MXC_DMA_DYNAMIC_CHANNEL
+#define MXC_DMA_CHANNEL_SSI1_RX MXC_DMA_DYNAMIC_CHANNEL
+#ifdef CONFIG_SDMA_IRAM
+#define MXC_DMA_CHANNEL_SSI1_TX (MXC_DMA_CHANNEL_IRAM + 1)
+#else
+#define MXC_DMA_CHANNEL_SSI1_TX MXC_DMA_DYNAMIC_CHANNEL
+#endif
+#define MXC_DMA_CHANNEL_SSI2_RX MXC_DMA_DYNAMIC_CHANNEL
+#define MXC_DMA_CHANNEL_SSI2_TX MXC_DMA_DYNAMIC_CHANNEL
+#define MXC_DMA_CHANNEL_CSPI1_RX MXC_DMA_DYNAMIC_CHANNEL
+#define MXC_DMA_CHANNEL_CSPI1_TX MXC_DMA_DYNAMIC_CHANNEL
+#define MXC_DMA_CHANNEL_CSPI2_RX MXC_DMA_DYNAMIC_CHANNEL
+#define MXC_DMA_CHANNEL_CSPI2_TX MXC_DMA_DYNAMIC_CHANNEL
+#define MXC_DMA_CHANNEL_CSPI3_RX MXC_DMA_DYNAMIC_CHANNEL
+#define MXC_DMA_CHANNEL_CSPI3_TX MXC_DMA_DYNAMIC_CHANNEL
+#define MXC_DMA_CHANNEL_ATA_RX MXC_DMA_DYNAMIC_CHANNEL
+#define MXC_DMA_CHANNEL_ATA_TX MXC_DMA_DYNAMIC_CHANNEL
+#define MXC_DMA_CHANNEL_MEMORY MXC_DMA_DYNAMIC_CHANNEL
+#define MXC_DMA_CHANNEL_ESAI_RX MXC_DMA_DYNAMIC_CHANNEL
+#define MXC_DMA_CHANNEL_ESAI_TX MXC_DMA_DYNAMIC_CHANNEL
+
+/*
+ * AIPS 2
+ */
+#define AIPS2_BASE_ADDR 0x53F00000
+#define AIPS2_BASE_ADDR_VIRT 0xFC200000
+#define AIPS2_SIZE SZ_1M
+
+#define CCM_BASE_ADDR (AIPS2_BASE_ADDR + 0x00080000)
+#define GPT4_BASE_ADDR (AIPS2_BASE_ADDR + 0x00084000)
+#define GPT3_BASE_ADDR (AIPS2_BASE_ADDR + 0x00088000)
+#define GPT2_BASE_ADDR (AIPS2_BASE_ADDR + 0x0008C000)
+#define GPT1_BASE_ADDR (AIPS2_BASE_ADDR + 0x00090000)
+#define EPIT1_BASE_ADDR (AIPS2_BASE_ADDR + 0x00094000)
+#define EPIT2_BASE_ADDR (AIPS2_BASE_ADDR + 0x00098000)
+#define GPIO4_BASE_ADDR (AIPS2_BASE_ADDR + 0x0009C000)
+#define PWM2_BASE_ADDR (AIPS2_BASE_ADDR + 0x000A0000)
+#define GPIO3_BASE_ADDR (AIPS2_BASE_ADDR + 0x000AD000)
+#define PWM3_BASE_ADDR (AIPS2_BASE_ADDR + 0x000A8000)
+#define SCC_BASE_ADDR (AIPS2_BASE_ADDR + 0x000AC000)
+#define RNGB_BASE_ADDR (AIPS2_BASE_ADDR + 0x000B0000)
+#define MMC_SDHC1_BASE_ADDR (AIPS2_BASE_ADDR + 0x000B4000)
+#define MMC_SDHC2_BASE_ADDR (AIPS2_BASE_ADDR + 0x000B8000)
+#define LCDC_BASE_ADDR (AIPS2_BASE_ADDR + 0x000BC000)
+#define SLCDC_BASE_ADDR (AIPS2_BASE_ADDR + 0x000C0000)
+#define PWM4_BASE_ADDR (AIPS2_BASE_ADDR + 0x000C8000)
+#define GPIO1_BASE_ADDR (AIPS2_BASE_ADDR + 0x000CC000)
+#define GPIO2_BASE_ADDR (AIPS2_BASE_ADDR + 0x000D0000)
+#define SDMA_BASE_ADDR (AIPS2_BASE_ADDR + 0x000D4000)
+#define WDOG1_BASE_ADDR (AIPS2_BASE_ADDR + 0x000DC000)
+#define PWM1_BASE_ADDR (AIPS2_BASE_ADDR + 0x000E0000)
+#define RTIC_BASE_ADDR (AIPS2_BASE_ADDR + 0x000EC000)
+#define IIM_BASE_ADDR (AIPS2_BASE_ADDR + 0x000F0000)
+#define USBOTG_BASE_ADDR (AIPS2_BASE_ADDR + 0x000F4000)
+#define OTG_BASE_ADDR USBOTG_BASE_ADDR
+#define CSI_BASE_ADDR (AIPS2_BASE_ADDR + 0x000F8000)
+#define DRYICE_BASE_ADDR (AIPS2_BASE_ADDR + 0x000FC000)
+#define SRTC_BASE_ADDR (DRYICE_BASE_ADDR)
+
+/*
+ * ROMP and ASIC
+ */
+#define ROMP_BASE_ADDR 0x60000000
+#define ROMP_BASE_ADDR_VIRT 0xFC300000
+#define ROMP_SIZE SZ_1M
+
+#define ASIC_BASE_ADDR 0x68000000
+#define ASIC_BASE_ADDR_VIRT 0xFC400000
+#define ASIC_SIZE SZ_1M
+#define AVIC_BASE_ADDR ASIC_BASE_ADDR
+#define AVIC_BASE_ADDR_VIRT ASIC_BASE_ADDR_VIRT
+#define AVIC_SIZE ASIC_SIZE
+
+/*
+ * SDRAM, WEIM, M3IF, EMI controllers
+ */
+#define X_MEMC_BASE_ADDR 0xB8000000
+#define X_MEMC_BASE_ADDR_VIRT 0xFC520000
+#define X_MEMC_SIZE SZ_64K
+
+#define SDRAMC_BASE_ADDR (X_MEMC_BASE_ADDR + 0x1000)
+#define WEIM_BASE_ADDR (X_MEMC_BASE_ADDR + 0x2000)
+#define M3IF_BASE_ADDR (X_MEMC_BASE_ADDR + 0x3000)
+#define EMI_CTL_BASE_ADDR (X_MEMC_BASE_ADDR + 0x4000)
+
+/*
+ * NFC controller
+ */
+#define NFC_BASE_ADDR 0xBB000000
+#define NFC_BASE_ADDR_VIRT 0xFC530000
+#define NFC_SIZE SZ_8K
+
+/*
+ * Memory regions and CS
+ */
+#define CSD0_BASE_ADDR 0x80000000
+#define CSD1_BASE_ADDR 0x90000000
+
+#define SDRAM_BASE_ADDR CSD0_BASE_ADDR
+
+#define CS0_BASE_ADDR 0xA0000000
+#define CS1_BASE_ADDR 0xA8000000
+#define CS2_BASE_ADDR 0xB0000000
+#define CS3_BASE_ADDR 0xB2000000
+#define CS4_BASE_ADDR 0xB4000000
+#define CS4_SIZE SZ_32M
+#define CS5_BASE_ADDR 0xB6000000
+#define CS5_SIZE SZ_32M
+
+/*!
+ * This macro defines the physical to virtual address mapping for all the
+ * peripheral modules. It is used by passing in the physical address as x
+ * and returning the virtual address. If the physical address is not mapped,
+ * it returns 0xDEADBEEF
+ */
+#define IO_ADDRESS(x) \
+ (void __force __iomem *) \
+ (((x >= AIPS1_BASE_ADDR) && (x < (AIPS1_BASE_ADDR + AIPS1_SIZE))) ? AIPS1_IO_ADDRESS(x):\
+ ((x >= SPBA0_BASE_ADDR) && (x < (SPBA0_BASE_ADDR + SPBA0_SIZE))) ? SPBA0_IO_ADDRESS(x):\
+ ((x >= AIPS2_BASE_ADDR) && (x < (AIPS2_BASE_ADDR + AIPS2_SIZE))) ? AIPS2_IO_ADDRESS(x):\
+ ((x >= ROMP_BASE_ADDR) && (x < (ROMP_BASE_ADDR + ROMP_SIZE))) ? ROMP_IO_ADDRESS(x):\
+ ((x >= ASIC_BASE_ADDR) && (x < (ASIC_BASE_ADDR + AVIC_SIZE))) ? ASIC_IO_ADDRESS(x):\
+ ((x >= IRAM_BASE_ADDR) && (x < (IRAM_BASE_ADDR + IRAM_SIZE))) ? IRAM_IO_ADDRESS(x):\
+ ((x >= X_MEMC_BASE_ADDR) && (x < (X_MEMC_BASE_ADDR + X_MEMC_SIZE))) ? X_MEMC_IO_ADDRESS(x):\
+ ((x >= NFC_BASE_ADDR) && (x < (NFC_BASE_ADDR + NFC_SIZE))) ? NFC_IO_ADDRESS(x):\
+ 0xDEADBEEF)
+
+/*
+ * define the address mapping macros: in physical address order
+ */
+
+#define AIPS1_IO_ADDRESS(x) \
+ (((x) - AIPS1_BASE_ADDR) + AIPS1_BASE_ADDR_VIRT)
+
+#define SPBA0_IO_ADDRESS(x) \
+ (((x) - SPBA0_BASE_ADDR) + SPBA0_BASE_ADDR_VIRT)
+
+#define AIPS2_IO_ADDRESS(x) \
+ (((x) - AIPS2_BASE_ADDR) + AIPS2_BASE_ADDR_VIRT)
+
+#define ROMP_IO_ADDRESS(x) \
+ (((x) - ROMP_BASE_ADDR) + ROMP_BASE_ADDR_VIRT)
+
+#define ASIC_IO_ADDRESS(x) \
+ (((x) - ASIC_BASE_ADDR) + ASIC_BASE_ADDR_VIRT)
+
+/* for entry-macro.S */
+#define AVIC_IO_ADDRESS(x) ASIC_IO_ADDRESS(x)
+
+#define IRAM_IO_ADDRESS(x) \
+ (((x) - IRAM_BASE_ADDR) + IRAM_BASE_ADDR_VIRT)
+
+#define X_MEMC_IO_ADDRESS(x) \
+ (((x) - X_MEMC_BASE_ADDR) + X_MEMC_BASE_ADDR_VIRT)
+
+#define NFC_IO_ADDRESS(x) \
+ (((x) - NFC_BASE_ADDR) + NFC_BASE_ADDR_VIRT)
+
+#define IS_MEM_DEVICE_NONSHARED(x) 0
+
+/*
+ * DMA request assignments
+ */
+#define DMA_REQ_EXTREQ0 0
+#define DMA_REQ_CCM 1
+#define DMA_REQ_ATA_TX_END 2
+#define DMA_REQ_ATA_TX 3
+#define DMA_REQ_ATA_RX 4
+#define DMA_REQ_CSPI2_RX 6
+#define DMA_REQ_CSPI2_TX 7
+#define DMA_REQ_CSPI1_RX 8
+#define DMA_REQ_CSPI1_TX 9
+#define DMA_REQ_UART3_RX 10
+#define DMA_REQ_UART3_TX 11
+#define DMA_REQ_UART4_RX 12
+#define DMA_REQ_UART4_TX 13
+#define DMA_REQ_EXTREQ1 14
+#define DMA_REQ_EXTREQ2 15
+#define DMA_REQ_UART2_RX 16
+#define DMA_REQ_UART2_TX 17
+#define DMA_REQ_UART1_RX 18
+#define DMA_REQ_UART1_TX 19
+#define DMA_REQ_SSI2_RX1 22
+#define DMA_REQ_SSI2_TX1 23
+#define DMA_REQ_SSI2_RX0 24
+#define DMA_REQ_SSI2_TX0 25
+#define DMA_REQ_SSI1_RX1 26
+#define DMA_REQ_SSI1_TX1 27
+#define DMA_REQ_SSI1_RX0 28
+#define DMA_REQ_SSI1_TX0 29
+#define DMA_REQ_NFC 30
+#define DMA_REQ_ECT 31
+#define DMA_REQ_ESAI_RX 32
+#define DMA_REQ_ESAI_TX 33
+#define DMA_REQ_CSPI3_RX 34
+#define DMA_REQ_CSPI3_TX 35
+#define DMA_REQ_SIM2_RX 36
+#define DMA_REQ_SIM2_TX 37
+#define DMA_REQ_SIM1_RX 38
+#define DMA_REQ_SIM1_TX 39
+#define DMA_REQ_TSC_GCQ 44
+#define DMA_REQ_TSC_TCQ 45
+#define DMA_REQ_UART5_RX 46
+#define DMA_REQ_UART5_TX 47
+
+/*
+ * Interrupt numbers
+ */
+#define MXC_INT_CSPI3 0
+#define MXC_INT_GPT4 1
+#define MXC_INT_OWIRE 2
+#define MXC_INT_I2C 3
+#define MXC_INT_I2C2 4
+#define MXC_INT_UART4 5
+#define MXC_INT_RTIC 6
+#define MXC_INT_ESAI 7
+#define MXC_INT_SDHC2 8
+#define MXC_INT_SDHC1 9
+#define MXC_INT_I2C3 10
+#define MXC_INT_SSI2 11
+#define MXC_INT_SSI1 12
+#define MXC_INT_CSPI2 13
+#define MXC_INT_CSPI1 14
+#define MXC_INT_ATA 15
+#define MXC_INT_GPIO3 16
+#define MXC_INT_CSI 17
+#define MXC_INT_UART3 18
+#define MXC_INT_IIM 19
+#define MXC_INT_SIM1 20
+#define MXC_INT_SIM2 21
+#define MXC_INT_RNG 22
+#define MXC_INT_GPIO4 23
+#define MXC_INT_KPP 24
+#define MXC_INT_DRYICE_NORM 25
+#define MXC_INT_PWM 26
+#define MXC_INT_EPIT2 27
+#define MXC_INT_EPIT1 28
+#define MXC_INT_GPT3 29
+#define MXC_INT_POWER_FAIL 30
+#define MXC_INT_CRM 31
+#define MXC_INT_UART2 32
+#define MXC_INT_NANDFC 33
+#define MXC_INT_SDMA 34
+#define MXC_INT_USB_HTG 35
+#define MXC_INT_PWM2 36
+#define MXC_INT_USB_OTG 37
+#define MXC_INT_SLCDC 38
+#define MXC_INT_LCDC 39
+#define MXC_INT_UART5 40
+#define MXC_INT_PWM3 41
+#define MXC_INT_PWM4 42
+#define MXC_INT_CAN1 43
+#define MXC_INT_CAN2 44
+#define MXC_INT_UART1 45
+#define MXC_INT_TSC 46
+#define MXC_INT_ECT 48
+#define MXC_INT_SCC_SCM 49
+#define MXC_INT_SCC_SMN 50
+#define MXC_INT_GPIO2 51
+#define MXC_INT_GPIO1 52
+#define MXC_INT_GPT2 53
+#define MXC_INT_GPT1 54
+#define MXC_INT_WDOG 55
+#define MXC_INT_DRYICE_SEC 56
+#define MXC_INT_FEC 57
+#define MXC_INT_EXT_INT5 58
+#define MXC_INT_EXT_INT4 59
+#define MXC_INT_EXT_INT3 60
+#define MXC_INT_EXT_INT2 61
+#define MXC_INT_EXT_INT1 62
+#define MXC_INT_EXT_INT0 63
+
+#define MXC_INT_GPT MXC_INT_GPT1
+
+/* gpio and gpio based interrupt handling */
+#define GPIO_DR 0x00
+#define GPIO_GDIR 0x04
+#define GPIO_PSR 0x08
+#define GPIO_ICR1 0x0C
+#define GPIO_ICR2 0x10
+#define GPIO_IMR 0x14
+#define GPIO_ISR 0x18
+#define GPIO_INT_LOW_LEV 0x0
+#define GPIO_INT_HIGH_LEV 0x1
+#define GPIO_INT_RISE_EDGE 0x2
+#define GPIO_INT_FALL_EDGE 0x3
+#define GPIO_INT_NONE 0x4
+
+#define MXC_TIMER_GPT1 1
+#define MXC_TIMER_GPT2 2
+#define MXC_TIMER_GPT3 3
+#define MXC_TIMER_GPT4 4
+
+/*!
+ * NFMS bit in RCSR register for pagesize of nandflash
+ */
+#define NFMS (*((volatile u32 *)IO_ADDRESS(CCM_BASE_ADDR + 0x28)))
+#define NFMS_NF_DWIDTH 14
+#define NFMS_NF_PG_SZ 8
+
+#endif /* __ASM_ARCH_MXC_MX25_H__ */
diff --git a/arch/arm/plat-mxc/include/mach/mx2_dma.h b/arch/arm/plat-mxc/include/mach/mx2_dma.h
new file mode 100644
index 000000000000..8f5ae658f96b
--- /dev/null
+++ b/arch/arm/plat-mxc/include/mach/mx2_dma.h
@@ -0,0 +1,261 @@
+/*
+ * Copyright 2004-2007 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 __ASM_ARCH_MXC_MX2_H__
+#define __ASM_ARCH_MXC_MX2_H__
+
+/*!
+ * @defgroup DMA_MX27 DMA driver for i.MX27
+ */
+
+/*!
+ *@file arch-mxc/mx2_dma.h
+ *@brief DMA driver header file
+ *
+ * @ingroup DMA_MX27
+ *
+ */
+
+#include <mach/hardware.h>
+#include <asm/dma.h>
+#include <stdarg.h>
+
+#define MXC_DMA_INTR_0 32
+
+#define DMA_DCR 0x000 /* 32bit dma control reg */
+#define DMA_DISR 0x004 /* 32bit dma interrupt status reg */
+#define DMA_DIMR 0x008 /* 32bit dma interrupt mask reg */
+#define DMA_DBTOSR 0x00c /* 32bit dma burst timeout stat reg */
+#define DMA_DRTOSR 0x010 /* 32bit dma req timeout status reg */
+#define DMA_DSESR 0x014 /* 32bit dma transfer err status reg */
+#define DMA_DBOSR 0x018 /* 32bit dma buffer overflow stat reg */
+#define DMA_DBTOCR 0x01c /* 32bit dma burst timeout ctrl reg */
+
+#define DMA_WSRA 0x040 /* 32bit dma W-size A reg */
+#define DMA_XSRA 0x044 /* 32bit dma X-size A reg */
+#define DMA_YSRA 0x048 /* 32bit dma Y-size A reg */
+#define DMA_WSRB 0x04C /* 32bit dma W-size B reg */
+#define DMA_XSRB 0x050 /* 32bit dma X-size B reg */
+#define DMA_YSRB 0x054 /* 32bit dma Y-size B reg */
+
+#define DMA_CH_BASE(x) (0x080+0x040*(x))
+
+#define DMA_SAR(x) (DMA_CH_BASE(x)+0x000)
+#define DMA_DAR(x) (DMA_CH_BASE(x)+0x004)
+#define DMA_CNTR(x) (DMA_CH_BASE(x)+0x008)
+#define DMA_CCR(x) (DMA_CH_BASE(x)+0x00C) /* 32bit dma ch0 control reg */
+#define DMA_RSSR(x) (DMA_CH_BASE(x)+0x010) /* 32bit dma ch0 req source sel reg */
+#define DMA_BLR(x) (DMA_CH_BASE(x)+0x014) /* 32bit dma ch0 burst lenght reg */
+#define DMA_RTOR(x) (DMA_CH_BASE(x)+0x018) /* 32bit dma ch0 req time out reg */
+#define DMA_BUCR(x) (DMA_CH_BASE(x)+0x018) /* 32bit dma ch0 bus utilization reg */
+#define DMA_CCNR(x) (DMA_CH_BASE(x)+0x01C) /* 32bit dma ch0 */
+
+#define DMA_TCR 0x480 /*32bit dma test control reg */
+#define DMA_TFIFOA 0x484 /* 32bit dma test fifo A reg */
+#define DMA_TDRR 0x488 /* 32bit dma test request reg */
+#define DMA_TDIPR 0x48c /* 32bit dma test in progress reg */
+#define DMA_TFIFOB 0x490 /* 32bit dma test fifo B reg */
+
+/*!
+ * This defines maximum DMA address
+ */
+#define MAX_DMA_ADDRESS 0xffffffff
+
+#define MXC_DMA_CHANNELS 16
+#define MAX_DMA_CHANNELS MXC_DMA_CHANNELS
+
+#define MX_DMA_CHANNELS MXC_DMA_CHANNELS
+
+/*!@def DMA_MEM_SIZE_8 DMA access port size, 8 bit*/
+/*!@def DMA_MEM_SIZE_16 DMA access port size, 16 bit*/
+/*!@def DMA_MEM_SIZE_32 DMA access port size, 32 bit*/
+#define DMA_MEM_SIZE_8 0x1
+#define DMA_MEM_SIZE_16 0x2
+#define DMA_MEM_SIZE_32 0x0
+
+/*!@def DMA_TYPE_LINEAR DMA transfer type, linear*/
+/*!@def DMA_TYPE_2D DMA transfer type, 2D*/
+/*!@def DMA_TYPE_FIFO DMA transfer type, FIFO*/
+/*!@def DMA_TYPE_EBE DMA transfer type, end-of-burst enable FIFO*/
+#define DMA_TYPE_LINEAR 0x0
+#define DMA_TYPE_2D 0x01
+#define DMA_TYPE_FIFO 0x2
+#define DMA_TYPE_EBE 0x3
+
+/*!@def DMA_DONE DMA transfer done*/
+/*!@def DMA_BURST_TIMEOUT DMA transfer timeout error*/
+/*!@def DMA_REQUEST_TIMEOUT DMA transfer request timeout error*/
+/*!@def DMA_TRANSFER_ERROR DMA transfer error*/
+/*!@def DMA_BUFFER_OVERFLOW DMA transfer buffer overflow error*/
+#define DMA_DONE 0x1000
+#define DMA_BURST_TIMEOUT 0x1
+#define DMA_REQUEST_TIMEOUT 0x2
+#define DMA_TRANSFER_ERROR 0x4
+#define DMA_BUFFER_OVERFLOW 0x8
+
+/*!@brief DMA control register*/
+typedef struct {
+ volatile u32 CEN:1; /*!< Dma channel enable */
+ volatile u32 FRC:1; /*!< Force a dma cycle bit */
+ volatile u32 RPT:1; /*!< Repeat bit */
+ volatile u32 REN:1; /*!< Request enable bit */
+ volatile u32 SSIZ:2; /*!< Source port size, 2 bit in length */
+ volatile u32 DSIZ:2; /*!< Dest port size, 2 bit in length */
+ volatile u32 MSEL:1; /*!< 2D memory register set bit */
+ volatile u32 MDIR:1; /*!< Transfer direction, inversed or normal */
+ volatile u32 SMOD:2; /*!< Source mode, 2 bit in length */
+ volatile u32 DMOD:2; /*!< Dest mode, 2 bit in length */
+ volatile u32 ACRPT:1; /*!< Auto clear repeat bit */
+ volatile u32 Reserver:17; /*!< Reserved bits */
+
+} dma_regs_control;
+
+#define DMA_CTL_CEN 0x1
+#define DMA_CTL_FRC 0x2
+#define DMA_CTL_RPT 0x4
+#define DMA_CTL_REN 0x8
+
+#define DMA_CTL_MSEL 0x100
+#define DMA_CTL_MDIR 0x200
+#define DMA_CTL_ACRPT 0x4000
+
+#define DMA_CTL_GET_SSIZ(x) (((x)>>4)&0x3)
+#define DMA_CTL_GET_DSIZ(x) (((x)>>6)&0x3)
+#define DMA_CTL_GET_SMOD(x) (((x)>>10)&0x3)
+#define DMA_CTL_GET_DMOD(x) (((x)>>12)&0x3)
+
+#define DMA_CTL_SET_SSIZ(x,value) do{ \
+ (x)&=~(0x3<<4); \
+ (x)|=(value)<<4; \
+ }while(0)
+
+#define DMA_CTL_SET_DSIZ(x,value) do{ \
+ (x)&=~(0x3<<6); \
+ (x)|=(value)<<6; \
+ }while(0)
+
+#define DMA_CTL_SET_SMOD(x,value) do{ \
+ (x)&=~(0x3<<10); \
+ (x)|=(value)<<10; \
+ }while(0)
+
+#define DMA_CTL_SET_DMOD(x,value) do{ \
+ (x)&=~(0x3<<12); \
+ (x)|=(value)<<12; \
+ }while(0)
+
+typedef struct {
+ volatile u32 SourceAddr;
+ volatile u32 DestAddr;
+ volatile u32 Count;
+ volatile u32 Ctl;
+ volatile u32 RequestSource;
+ volatile u32 BurstLength;
+ union {
+ volatile u32 ReqTimeout;
+ volatile u32 BusUtilt;
+ };
+ volatile u32 transferd;
+} dma_regs_t;
+
+#ifndef TRANSFER_32BIT
+/*!
+ * This defines DMA access data size
+ */
+
+#define TRANSFER_8BIT DMA_MEM_SIZE_8
+#define TRANSFER_16BIT DMA_MEM_SIZE_16
+#define TRANSFER_32BIT DMA_MEM_SIZE_32
+
+#endif
+
+/*!
+ * This defines maximum device name length passed during mxc_request_dma().
+ */
+#define MAX_DEVNAME_LENGTH 32
+#define MAX_BD_SIZE 32
+
+/*!
+ * Structure containing dma channel parameters.
+ */
+typedef struct {
+ unsigned long dma_chan; /*!< the dma channel information: dynamic or channel number */
+ u32 mode:1; /*!< the initialized dma mode, 0 for dma read, 1 for dma write */
+ u32 rto_en:1; /*!< enable request-timeout. It is valid when REN=1 */
+ u32 dir:1; /*!< Transfer direction, 0 for increment, 1 for decrement */
+ u32 dma_chaining:1; /*!< Autoclear bit for chainbuffer */
+ u32 ren:1; /*!< enable transfer based request signal */
+ u32 M2D_Valid:1; /*!< enable 2D address module. 0 for disable it. 1 for enabled it */
+ u32 msel:1; /*!<2D memory selection, 0 for set A, 1 for set B */
+ u32 burstLength; /*!< Channel burst length */
+ u32 request; /*!< Request source. */
+ u32 busuntils; /*!< when REN=0, Bus utilization, otherwise it it request timeout */
+ u32 sourceType; /*!< Source type, see DMA_TYPE_* */
+ u32 sourcePort; /*!< Source port size, see DMA_MEM_SIZE_* */
+ u32 destType; /*!< Destination type, see DMA_TYPE_* */
+ u32 destPort; /*!< Destination port size, see DMA_MEM_SIZE_* */
+ __u32 per_address; /*< Peripheral source/destination
+ * physical address
+ */
+ u32 W; /*!< 2D Wide-size */
+ u32 X; /*!< 2D X-size */
+ u32 Y; /*!< 2D Y-size */
+} mx2_dma_info_t;
+
+/*!
+ * Structure of dma buffer descriptor
+ */
+typedef struct {
+ unsigned long state; /*!< dma bd state */
+ int mode; /*!< the dma mode of this bd */
+ unsigned long count; /*!< the length of the dma transfer */
+ unsigned long src_addr; /*!< the source address of the dma transfer */
+ unsigned long dst_addr; /*!< the destination address of the dma transfer */
+} mx2_dma_bd_t;
+
+/*!
+ * the states of dma buffer descriptor
+ */
+#define DMA_BD_ST_BUSY 0x20000000 /*!< dma bd is transfering or has be configured into controller */
+#define DMA_BD_ST_PEND 0x10000000 /*!< dma bd is waiting to be configured into controller */
+#define DMA_BD_ST_LAST 0x08000000 /*!< dma bd is the last dma bd which is built in one dma transfer request
+ * When completed this bd, the callback function must be called.
+ */
+
+/*!
+ * This structure containing the private information for MX2
+ */
+typedef struct mx2_dma_priv_s {
+ unsigned int dma_chaining:1; /* 1: using headware dma chaining feature */
+ unsigned int ren:1; /* 1: dma start besed on request signal */
+ unsigned long trans_bytes; /* To store the transfered data bytes in this transfer */
+ mx2_dma_info_t *dma_info; /* To store the pointer for dma parameter for reading and wirting */
+ int bd_rd; /* the read index of bd ring */
+ int bd_wr; /* the write index of bd ring */
+ atomic_t bd_used; /* the valid bd number in bd ring */
+ mx2_dma_bd_t *bd_ring; /* the pointer of bd ring */
+ unsigned long dma_base; /* register base address of this channel */
+ int dma_irq; /* irq number of this channel */
+} mx2_dma_priv_t;
+
+/*!
+ * @brief get the dma info by channel_id
+ */
+extern mx2_dma_info_t *mxc_dma_get_info(mxc_dma_device_t channel_id);
+
+/*!
+ * @brief: scan dma parameter list . And collect information about which channels are dynamic .
+ */
+extern void mxc_dma_load_info(mxc_dma_channel_t * dma);
+
+#endif
diff --git a/arch/arm/plat-mxc/include/mach/mx31.h b/arch/arm/plat-mxc/include/mach/mx31.h
index 0b06941b6139..2ca31d6413a6 100644
--- a/arch/arm/plat-mxc/include/mach/mx31.h
+++ b/arch/arm/plat-mxc/include/mach/mx31.h
@@ -3,6 +3,14 @@
*/
#define MX31_IRAM_BASE_ADDR 0x1FFC0000 /* internal ram */
#define MX31_IRAM_SIZE SZ_16K
+#define MX31_IRAM_BASE_ADDR_VIRT 0xFC340000
+
+#define USB_IRAM_BASE_ADDR (MX31_IRAM_BASE_ADDR)
+#ifdef CONFIG_USB_STATIC_IRAM
+#define USB_IRAM_SIZE (2*SZ_8K)
+#else
+#define USB_IRAM_SIZE 0
+#endif
#define OTG_BASE_ADDR (AIPS1_BASE_ADDR + 0x00088000)
#define ATA_BASE_ADDR (AIPS1_BASE_ADDR + 0x0008C000)
@@ -14,21 +22,98 @@
#define SIM1_BASE_ADDR (SPBA0_BASE_ADDR + 0x00018000)
#define IIM_BASE_ADDR (SPBA0_BASE_ADDR + 0x0001C000)
+/*!
+ * defines for SPBA modules
+ */
+#define SPBA_SDHC1 0x04
+#define SPBA_SDHC2 0x08
+#define SPBA_SIM 0x18
+#define SPBA_IIM 0x1C
+
#define CSPI3_BASE_ADDR (AIPS2_BASE_ADDR + 0x00084000)
#define FIRI_BASE_ADDR (AIPS2_BASE_ADDR + 0x0008C000)
#define SCM_BASE_ADDR (AIPS2_BASE_ADDR + 0x000AE000)
#define SMN_BASE_ADDR (AIPS2_BASE_ADDR + 0x000AF000)
#define MPEG4_ENC_BASE_ADDR (AIPS2_BASE_ADDR + 0x000C8000)
+#define VPU_BASE_ADDR MPEG4_ENC_BASE_ADDR
#define MX31_NFC_BASE_ADDR (X_MEMC_BASE_ADDR + 0x0000)
+#define NFC_BASE_ADDR (X_MEMC_BASE_ADDR + 0x0000)
+#define NFC_SIZE 0x1000
+#define NFC_IO_ADDRESS(x) 0
+
+/*
+ * VL2CC for i.MX32
+ */
+#define VL2CC_BASE_ADDR 0xE0000000
+
+/*!
+ * Defines for modules using static and dynamic DMA channels
+ */
+
+#ifdef CONFIG_SDMA_IRAM
+#define MXC_DMA_CHANNEL_IRAM 30
+#endif /*CONFIG_SDMA_IRAM */
+
+#define MXC_DMA_CHANNEL_UART1_RX MXC_DMA_DYNAMIC_CHANNEL
+#define MXC_DMA_CHANNEL_UART1_TX MXC_DMA_DYNAMIC_CHANNEL
+#define MXC_DMA_CHANNEL_UART2_RX MXC_DMA_DYNAMIC_CHANNEL
+#define MXC_DMA_CHANNEL_UART2_TX MXC_DMA_DYNAMIC_CHANNEL
+#define MXC_DMA_CHANNEL_UART3_RX MXC_DMA_DYNAMIC_CHANNEL
+#define MXC_DMA_CHANNEL_UART3_TX MXC_DMA_DYNAMIC_CHANNEL
+#define MXC_DMA_CHANNEL_UART4_RX MXC_DMA_DYNAMIC_CHANNEL
+#define MXC_DMA_CHANNEL_UART4_TX MXC_DMA_DYNAMIC_CHANNEL
+#define MXC_DMA_CHANNEL_UART5_RX MXC_DMA_DYNAMIC_CHANNEL
+#define MXC_DMA_CHANNEL_UART5_TX MXC_DMA_DYNAMIC_CHANNEL
+#define MXC_DMA_CHANNEL_MMC1 MXC_DMA_DYNAMIC_CHANNEL
+#define MXC_DMA_CHANNEL_MMC2 MXC_DMA_DYNAMIC_CHANNEL
+#define MXC_DMA_CHANNEL_SSI1_TX MXC_DMA_DYNAMIC_CHANNEL
+#define MXC_DMA_CHANNEL_SSI1_RX MXC_DMA_DYNAMIC_CHANNEL
+#define MXC_DMA_CHANNEL_SSI2_RX MXC_DMA_DYNAMIC_CHANNEL
+
+#ifdef CONFIG_SDMA_IRAM
+#define MXC_DMA_CHANNEL_SSI2_TX (MXC_DMA_CHANNEL_IRAM + 1)
+#else /*CONFIG_SDMA_IRAM */
+#define MXC_DMA_CHANNEL_SSI2_TX MXC_DMA_DYNAMIC_CHANNEL
+#endif /*CONFIG_SDMA_IRAM */
+
+#define MXC_DMA_CHANNEL_FIR_RX MXC_DMA_DYNAMIC_CHANNEL
+#define MXC_DMA_CHANNEL_FIR_TX MXC_DMA_DYNAMIC_CHANNEL
+#define MXC_DMA_CHANNEL_CSPI1_RX MXC_DMA_DYNAMIC_CHANNEL
+#define MXC_DMA_CHANNEL_CSPI1_TX MXC_DMA_DYNAMIC_CHANNEL
+#define MXC_DMA_CHANNEL_CSPI2_RX MXC_DMA_DYNAMIC_CHANNEL
+#define MXC_DMA_CHANNEL_CSPI2_TX MXC_DMA_DYNAMIC_CHANNEL
+#define MXC_DMA_CHANNEL_ATA_RX MXC_DMA_DYNAMIC_CHANNEL
+#define MXC_DMA_CHANNEL_ATA_TX MXC_DMA_DYNAMIC_CHANNEL
+#define MXC_DMA_CHANNEL_MEMORY MXC_DMA_DYNAMIC_CHANNEL
+#define MXC_DMA_CHANNEL_FIFO_MEMORY MXC_DMA_DYNAMIC_CHANNEL
+
+/*
+ * DMA request assignments
+ */
+#define DMA_REQ_SDHC2 21
+#define DMA_REQ_SDHC1 20
+#define DMA_REQ_FIRI_TX 17
+#define DMA_REQ_FIRI_RX 16
+#define DMA_REQ_UART4_TX 13
+#define DMA_REQ_UART4_RX 12
+#define DMA_REQ_CSPI3_TX 11
+#define DMA_REQ_CSPI3_RX 10
+#define DMA_REQ_UART5_TX 11
+#define DMA_REQ_UART5_RX 10
+#define DMA_REQ_UART3_TX 9
+#define DMA_REQ_UART3_RX 8
+#define DMA_REQ_SIM 5
#define MXC_INT_MPEG4_ENCODER 5
#define MXC_INT_FIRI 7
#define MX31_INT_MMC_SDHC2 8
+#define MXC_INT_MMC_SDHC2 8
#define MXC_INT_MMC_SDHC1 9
#define MX31_INT_SSI2 11
#define MX31_INT_SSI1 12
#define MXC_INT_MBX 16
+#define MXC_INT_VPU MXC_INT_MBX
#define MXC_INT_CSPI3 17
#define MXC_INT_SIM2 20
#define MXC_INT_SIM1 21
@@ -43,3 +128,13 @@
#define MXC_INT_CCM 53
#define MXC_INT_PCMCIA 54
+#define ARM11_PMU_IRQ MXC_INT_EVTMON
+
+/*!
+ * NFMS bit in RCSR register for pagesize of nandflash
+ */
+#define NFMS (*((volatile u32 *)IO_ADDRESS(CCM_BASE_ADDR+0xc)))
+#define NFMS_BIT 30
+#define NFMS_NF_DWIDTH 31
+#define NFMS_NF_PG_SZ 30
+
diff --git a/arch/arm/plat-mxc/include/mach/mx35.h b/arch/arm/plat-mxc/include/mach/mx35.h
index 6465fefb42e3..da83e11b4070 100644
--- a/arch/arm/plat-mxc/include/mach/mx35.h
+++ b/arch/arm/plat-mxc/include/mach/mx35.h
@@ -1,11 +1,56 @@
+
+/*!
+ * Define this option to specify we are using the newer SDMA module.
+ */
+#define MXC_SDMA_V2
+
/*
* IRAM
*/
#define MX35_IRAM_BASE_ADDR 0x10000000 /* internal ram */
+#define IRAM_BASE_ADDR MX35_IRAM_BASE_ADDR
+#define IRAM_BASE_ADDR_VIRT 0xFC600000
#define MX35_IRAM_SIZE SZ_128K
+#ifndef CONFIG_SDMA_IRAM
+#define CONFIG_SDMA_IRAM_SIZE 0
+#endif
+#ifdef CONFIG_SND_MXC_SOC_IRAM
+#define SND_RAM_SIZE 0x10000
+#else
+#define SND_RAM_SIZE 0
+#endif
+
+#define SND_RAM_BASE_ADDR (MX35_IRAM_BASE_ADDR + CONFIG_SDMA_IRAM_SIZE)
+#define MLB_IRAM_ADDR_OFFSET (CONFIG_SDMA_IRAM_SIZE + SND_RAM_SIZE)
+
#define MXC_FEC_BASE_ADDR 0x50038000
#define MX35_NFC_BASE_ADDR 0xBB000000
+#define NFC_BASE_ADDR MX35_NFC_BASE_ADDR
+#define NFC_BASE_ADDR_VIRT 0xFC700000
+#define NFC_SIZE SZ_1M
+#define NFC_IO_ADDRESS(x) (((x) - NFC_BASE_ADDR) + NFC_BASE_ADDR_VIRT)
+
+
+#define MMC_SDHC1_BASE_ADDR (AIPS2_BASE_ADDR + 0x000B4000)
+#define MMC_SDHC2_BASE_ADDR (AIPS2_BASE_ADDR + 0x000B8000)
+#define MMC_SDHC3_BASE_ADDR (AIPS2_BASE_ADDR + 0x000BC000)
+#define CAN1_BASE_ADDR (AIPS2_BASE_ADDR + 0x000E4000)
+#define CAN2_BASE_ADDR (AIPS2_BASE_ADDR + 0x000E8000)
+#define IIM_BASE_ADDR (AIPS2_BASE_ADDR + 0x000F0000)
+#define OTG_BASE_ADDR (AIPS2_BASE_ADDR + 0x000F4000)
+#define MLB_BASE_ADDR (AIPS2_BASE_ADDR + 0x000F8000)
+#define SPDIF_BASE_ADDR (SPBA0_BASE_ADDR + 0x00028000)
+#define ATA_BASE_ADDR (SPBA0_BASE_ADDR + 0x00020000)
+#define ASRC_BASE_ADDR (SPBA0_BASE_ADDR + 0x0002C000)
+#define ESAI_BASE_ADDR (SPBA0_BASE_ADDR + 0x00034000)
+#define RNGC_BASE_ADDR (AIPS2_BASE_ADDR + 0x000B0000)
+
+#define SPBA_MSHC 0x24
+#define SPBA_SPDIR 0x28
+#define SPBA_ASRC 0x2C
+#define SPBA_ESAI 0x34
+#define SPBA_FEC 0x38
/*
* Interrupt numbers
@@ -16,6 +61,8 @@
#define MXC_INT_MMC_SDHC3 9
#define MX35_INT_SSI1 11
#define MX35_INT_SSI2 12
+#define MXC_INT_SSI1 MX35_INT_SSI1
+#define MXC_INT_SSI2 MX35_INT_SSI2
#define MXC_INT_GPU2D 16
#define MXC_INT_ASRC 17
#define MXC_INT_USBHS 35
@@ -26,4 +73,84 @@
#define MXC_INT_MLB 46
#define MXC_INT_SPDIF 47
#define MXC_INT_FEC 57
+#define MXC_INT_RNGC MXC_INT_RNGA
+
+#define MXC_INT_FORCE MXC_INT_RESV1
+
+/*!
+ * Defines for modules using static and dynamic DMA channels
+ */
+#define MXC_DMA_CHANNEL_IRAM 30
+#define MXC_DMA_CHANNEL_UART1_RX MXC_DMA_DYNAMIC_CHANNEL
+#define MXC_DMA_CHANNEL_UART1_TX MXC_DMA_DYNAMIC_CHANNEL
+#define MXC_DMA_CHANNEL_UART2_RX MXC_DMA_DYNAMIC_CHANNEL
+#define MXC_DMA_CHANNEL_UART2_TX MXC_DMA_DYNAMIC_CHANNEL
+#define MXC_DMA_CHANNEL_UART3_RX MXC_DMA_DYNAMIC_CHANNEL
+#define MXC_DMA_CHANNEL_UART3_TX MXC_DMA_DYNAMIC_CHANNEL
+#define MXC_DMA_CHANNEL_MMC1 MXC_DMA_DYNAMIC_CHANNEL
+#define MXC_DMA_CHANNEL_MMC2 MXC_DMA_DYNAMIC_CHANNEL
+#define MXC_DMA_CHANNEL_MMC3 MXC_DMA_DYNAMIC_CHANNEL
+#define MXC_DMA_CHANNEL_SSI1_RX MXC_DMA_DYNAMIC_CHANNEL
+#ifdef CONFIG_SDMA_IRAM
+#define MXC_DMA_CHANNEL_SSI1_TX (MXC_DMA_CHANNEL_IRAM + 1)
+#else
+#define MXC_DMA_CHANNEL_SSI1_TX MXC_DMA_DYNAMIC_CHANNEL
+#endif
+#define MXC_DMA_CHANNEL_SSI2_RX MXC_DMA_DYNAMIC_CHANNEL
+#define MXC_DMA_CHANNEL_SSI2_TX MXC_DMA_DYNAMIC_CHANNEL
+#define MXC_DMA_CHANNEL_CSPI1_RX MXC_DMA_DYNAMIC_CHANNEL
+#define MXC_DMA_CHANNEL_CSPI1_TX MXC_DMA_DYNAMIC_CHANNEL
+#define MXC_DMA_CHANNEL_CSPI2_RX MXC_DMA_DYNAMIC_CHANNEL
+#define MXC_DMA_CHANNEL_CSPI2_TX MXC_DMA_DYNAMIC_CHANNEL
+#define MXC_DMA_CHANNEL_ATA_RX MXC_DMA_DYNAMIC_CHANNEL
+#define MXC_DMA_CHANNEL_ATA_TX MXC_DMA_DYNAMIC_CHANNEL
+#define MXC_DMA_CHANNEL_MEMORY MXC_DMA_DYNAMIC_CHANNEL
+#define MXC_DMA_CHANNEL_SPDIF_TX MXC_DMA_DYNAMIC_CHANNEL
+#define MXC_DMA_CHANNEL_SPDIF_RX MXC_DMA_DYNAMIC_CHANNEL
+#define MXC_DMA_CHANNEL_ASRCA_RX MXC_DMA_DYNAMIC_CHANNEL
+#define MXC_DMA_CHANNEL_ASRCA_TX MXC_DMA_DYNAMIC_CHANNEL
+#define MXC_DMA_CHANNEL_ASRCB_RX MXC_DMA_DYNAMIC_CHANNEL
+#define MXC_DMA_CHANNEL_ASRCB_TX MXC_DMA_DYNAMIC_CHANNEL
+#define MXC_DMA_CHANNEL_ASRCC_RX MXC_DMA_DYNAMIC_CHANNEL
+#define MXC_DMA_CHANNEL_ASRCC_TX MXC_DMA_DYNAMIC_CHANNEL
+#define MXC_DMA_CHANNEL_ESAI_RX MXC_DMA_DYNAMIC_CHANNEL
+#define MXC_DMA_CHANNEL_ESAI_TX MXC_DMA_DYNAMIC_CHANNEL
+#define MXC_DMA_CHANNEL_ASRCA_ESAI MXC_DMA_DYNAMIC_CHANNEL
+#define MXC_DMA_CHANNEL_ASRCB_ESAI MXC_DMA_DYNAMIC_CHANNEL
+#define MXC_DMA_CHANNEL_ASRCC_ESAI MXC_DMA_DYNAMIC_CHANNEL
+#define MXC_DMA_CHANNEL_ASRCA_SSI1_TX0 MXC_DMA_DYNAMIC_CHANNEL
+#define MXC_DMA_CHANNEL_ASRCA_SSI1_TX1 MXC_DMA_DYNAMIC_CHANNEL
+#define MXC_DMA_CHANNEL_ASRCA_SSI2_TX0 MXC_DMA_DYNAMIC_CHANNEL
+#define MXC_DMA_CHANNEL_ASRCA_SSI2_TX1 MXC_DMA_DYNAMIC_CHANNEL
+#define MXC_DMA_CHANNEL_ASRCB_SSI1_TX0 MXC_DMA_DYNAMIC_CHANNEL
+#define MXC_DMA_CHANNEL_ASRCB_SSI1_TX1 MXC_DMA_DYNAMIC_CHANNEL
+#define MXC_DMA_CHANNEL_ASRCB_SSI2_TX0 MXC_DMA_DYNAMIC_CHANNEL
+#define MXC_DMA_CHANNEL_ASRCB_SSI2_TX1 MXC_DMA_DYNAMIC_CHANNEL
+
+#define DMA_REQ_ASRC_DMA6 41
+#define DMA_REQ_ASRC_DMA5 40
+#define DMA_REQ_ASRC_DMA4 39
+#define DMA_REQ_ASRC_DMA3 38
+#define DMA_REQ_ASRC_DMA2 37
+#define DMA_REQ_ASRC_DMA1 36
+#define DMA_REQ_RSVD3 35
+#define DMA_REQ_RSVD2 34
+#define DMA_REQ_ESAI_TX 33
+#define DMA_REQ_ESAI_RX 32
+#define DMA_REQ_IPU 21
+#define DMA_REQ_RSVD1 20
+#define DMA_REQ_SPDIF_TX 13
+#define DMA_REQ_SPDIF_RX 12
+#define DMA_REQ_UART3_TX 11
+#define DMA_REQ_UART3_RX 10
+#define DMA_REQ_MSHC 5
+#define DMA_REQ_DPTC 1
+#define DMA_REQ_DVFS 1
+/*!
+ * NFMS bit in RCSR register for pagesize of nandflash
+ */
+#define NFMS (*((volatile u32 *)IO_ADDRESS(CCM_BASE_ADDR+0x18)))
+#define NFMS_BIT 8
+#define NFMS_NF_DWIDTH 14
+#define NFMS_NF_PG_SZ 8
diff --git a/arch/arm/plat-mxc/include/mach/mx37.h b/arch/arm/plat-mxc/include/mach/mx37.h
new file mode 100644
index 000000000000..7539900cbacd
--- /dev/null
+++ b/arch/arm/plat-mxc/include/mach/mx37.h
@@ -0,0 +1,474 @@
+/*
+ * Copyright 2009 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 __ASM_ARCH_MXC_MX37_H__
+#define __ASM_ARCH_MXC_MX37_H__
+
+#ifndef __ASM_ARCH_MXC_HARDWARE_H__
+#error "Do not include directly."
+#endif
+
+/*!
+ * @file arch-mxc/mx37.h
+ * @brief This file contains register definitions.
+ *
+ * @ingroup MSL_MX37
+ */
+
+/*!
+ * Define this option to specify we are using the newer SDMA module.
+ */
+#define MXC_SDMA_V2
+
+/*
+ * IRAM
+ */
+#define IRAM_BASE_ADDR 0x10000000 /* internal ram */
+#define IRAM_BASE_ADDR_VIRT 0xF8000000
+#define IRAM_SIZE (9*SZ_8K) /* 72KB */
+
+#if defined(CONFIG_MXC_SECURITY_SCC2) \
+ || defined(CONFIG_MXC_SECURITY_SCC2_MODULE)
+#define SCC_IRAM_SIZE SZ_16K
+#else
+#define SCC_IRAM_SIZE 0
+#endif
+
+/*#ifndef CONFIG_SDMA_IRAM
+#define CONFIG_SDMA_IRAM_SIZE 0
+#endif*/
+#ifdef CONFIG_SDMA_IRAM
+#define SDMA_IRAM_SIZE CONFIG_SDMA_IRAM_SIZE
+#else
+#define SDMA_IRAM_SIZE 0
+#endif
+
+#ifdef CONFIG_SND_MXC_SOC_IRAM
+#define SND_RAM_SIZE 0x6000
+#else
+#define SND_RAM_SIZE 0
+#endif
+
+#ifdef CONFIG_USB_STATIC_IRAM
+#define USB_IRAM_SIZE SZ_8K
+#else
+#define USB_IRAM_SIZE 0
+#endif
+
+#if (IRAM_SIZE < (SCC_IRAM_SIZE + SDMA_IRAM_SIZE + SND_RAM_SIZE + \
+ USB_IRAM_SIZE))
+#error "IRAM size exceeded"
+#endif
+
+#ifdef CONFIG_MXC_VPU_IRAM
+#define VPU_IRAM_SIZE (IRAM_BASE_ADDR + IRAM_SIZE - VPU_IRAM_BASE_ADDR)
+#else
+#define VPU_IRAM_SIZE 0
+#endif
+
+#define SCC_IRAM_BASE_ADDR (IRAM_BASE_ADDR + IRAM_SIZE - SCC_IRAM_SIZE)
+#define SDMA_RAM_BASE_ADDR (IRAM_BASE_ADDR)
+#define SND_RAM_BASE_ADDR (IRAM_BASE_ADDR + SDMA_IRAM_SIZE)
+#define USB_IRAM_BASE_ADDR (SND_RAM_BASE_ADDR + SND_RAM_SIZE)
+#define VPU_IRAM_BASE_ADDR (USB_IRAM_BASE_ADDR + USB_IRAM_SIZE)
+
+/*
+ * NFC
+ */
+#define NFC_BASE_ADDR_AXI 0x7FFF0000 /* NAND flash AXI */
+#define NFC_BASE_ADDR_AXI_VIRT 0xF9000000
+#define NFC_AXI_SIZE SZ_64K
+
+/*
+ * L2CC
+ */
+#define L2CC_BASE_ADDR 0xB0000000
+
+#define PLATFORM_BASE_ADDR 0xB0400000
+#define PLATFORM_BASE_ADDR_VIRT 0xFA000000
+#define PLATFORM_SIZE SZ_1M
+#define EVTMON_BASE_ADDR (PLATFORM_BASE_ADDR + 0x00000000)
+#define ARM1176_BASE_ADDR (PLATFORM_BASE_ADDR + 0x00004000)
+
+#define TZIC_BASE_ADDR 0xB0800000
+#define TZIC_BASE_ADDR_VIRT 0xFA100000
+#define TZIC_SIZE SZ_1M
+
+#define DEBUG_BASE_ADDR 0xB0C00000
+#define DEBUG_BASE_ADDR_VIRT 0xFA200000
+#define DEBUG_SIZE SZ_1M
+#define ETB_BASE_ADDR (DEBUG_BASE_ADDR + 0x00001000)
+#define ETM_BASE_ADDR (DEBUG_BASE_ADDR + 0x00002000)
+#define TPIU_BASE_ADDR (DEBUG_BASE_ADDR + 0x00003000)
+#define CTI0_BASE_ADDR (DEBUG_BASE_ADDR + 0x00004000)
+#define CTI1_BASE_ADDR (DEBUG_BASE_ADDR + 0x00005000)
+#define CTI2_BASE_ADDR (DEBUG_BASE_ADDR + 0x00006000)
+
+/*
+ * AIPS 1
+ */
+#define AIPS1_BASE_ADDR 0xC3F00000
+#define AIPS1_BASE_ADDR_VIRT 0xFC000000
+#define AIPS1_SIZE SZ_1M
+
+#define MAX_BASE_ADDR (AIPS1_BASE_ADDR + 0x00080000)
+#define GPIO1_BASE_ADDR (AIPS1_BASE_ADDR + 0x00084000)
+#define GPIO2_BASE_ADDR (AIPS1_BASE_ADDR + 0x00088000)
+#define GPIO3_BASE_ADDR (AIPS1_BASE_ADDR + 0x0008C000)
+#define KPP_BASE_ADDR (AIPS1_BASE_ADDR + 0x00094000)
+#define WDOG1_BASE_ADDR (AIPS1_BASE_ADDR + 0x00098000)
+#define WDOG2_BASE_ADDR (AIPS1_BASE_ADDR + 0x0009C000)
+#define GPT1_BASE_ADDR (AIPS1_BASE_ADDR + 0x000A0000)
+#define SRTC_BASE_ADDR (AIPS1_BASE_ADDR + 0x000A4000)
+#define IOMUXC_BASE_ADDR (AIPS1_BASE_ADDR + 0x000A8000)
+#define IIM_BASE_ADDR (AIPS1_BASE_ADDR + 0x000AC000)
+#define CSU_BASE_ADDR (AIPS1_BASE_ADDR + 0x000B0000)
+#define SDMA_BASE_ADDR (AIPS1_BASE_ADDR + 0x000B4000)
+#define SCC_BASE_ADDR (AIPS1_BASE_ADDR + 0x000BC000)
+#define ROMCP_BASE_ADDR (AIPS1_BASE_ADDR + 0x000C0000)
+#define RTIC_BASE_ADDR (AIPS1_BASE_ADDR + 0x000C4000)
+#define VPU_BASE_ADDR (AIPS1_BASE_ADDR + 0x000D0000)
+#define OTG_BASE_ADDR (AIPS1_BASE_ADDR + 0x000D4000)
+#define ATA_BASE_ADDR (AIPS1_BASE_ADDR + 0x000D8000)
+#define MSHC1_BASE_ADDR (AIPS1_BASE_ADDR + 0x000E0000)
+#define FEC_BASE_ADDR (AIPS1_BASE_ADDR + 0x000E8000)
+#define RNGC_BASE_ADDR (AIPS1_BASE_ADDR + 0x000EC000)
+#define TVE_BASE_ADDR (AIPS1_BASE_ADDR + 0x000F0000)
+
+/*
+ * SPBA global module enabled #0
+ */
+#define SPBA0_BASE_ADDR 0xC0000000
+#define SPBA0_BASE_ADDR_VIRT 0xFC100000
+#define SPBA0_SIZE SZ_1M
+
+#define MMC_SDHC1_BASE_ADDR (SPBA0_BASE_ADDR + 0x00004000)
+#define MMC_SDHC2_BASE_ADDR (SPBA0_BASE_ADDR + 0x00008000)
+#define UART3_BASE_ADDR (SPBA0_BASE_ADDR + 0x0000C000)
+#define CSPI2_BASE_ADDR (SPBA0_BASE_ADDR + 0x00010000)
+#define SSI2_BASE_ADDR (SPBA0_BASE_ADDR + 0x00014000)
+#define MMC_SDHC3_BASE_ADDR (SPBA0_BASE_ADDR + 0x00020000)
+#define SPDIF_BASE_ADDR (SPBA0_BASE_ADDR + 0x00028000)
+#define ATA_DMA_BASE_ADDR (SPBA0_BASE_ADDR + 0x00034000)
+#define SPBA_CTRL_BASE_ADDR (SPBA0_BASE_ADDR + 0x0003C000)
+
+/*!
+ * defines for SPBA modules
+ */
+#define SPBA_SDHC1 0x04
+#define SPBA_SDHC2 0x08
+#define SPBA_UART3 0x0C
+#define SPBA_CSPI2 0x10
+#define SPBA_SSI2 0x14
+#define SPBA_SDHC3 0x20
+#define SPBA_SPDIF 0x28
+#define SPBA_ATA 0x34
+
+/*!
+ * Defines for modules using static and dynamic DMA channels
+ */
+#define MXC_DMA_CHANNEL_IRAM 30
+#define MXC_DMA_CHANNEL_SPDIF_TX MXC_DMA_DYNAMIC_CHANNEL
+#define MXC_DMA_CHANNEL_UART1_RX MXC_DMA_DYNAMIC_CHANNEL
+#define MXC_DMA_CHANNEL_UART1_TX MXC_DMA_DYNAMIC_CHANNEL
+#define MXC_DMA_CHANNEL_UART2_RX MXC_DMA_DYNAMIC_CHANNEL
+#define MXC_DMA_CHANNEL_UART2_TX MXC_DMA_DYNAMIC_CHANNEL
+#define MXC_DMA_CHANNEL_UART3_RX MXC_DMA_DYNAMIC_CHANNEL
+#define MXC_DMA_CHANNEL_UART3_TX MXC_DMA_DYNAMIC_CHANNEL
+#define MXC_DMA_CHANNEL_MMC1 MXC_DMA_DYNAMIC_CHANNEL
+#define MXC_DMA_CHANNEL_MMC2 MXC_DMA_DYNAMIC_CHANNEL
+#define MXC_DMA_CHANNEL_SSI1_RX MXC_DMA_DYNAMIC_CHANNEL
+#define MXC_DMA_CHANNEL_SSI1_TX MXC_DMA_DYNAMIC_CHANNEL
+#define MXC_DMA_CHANNEL_SSI2_RX MXC_DMA_DYNAMIC_CHANNEL
+#ifdef CONFIG_SDMA_IRAM
+#define MXC_DMA_CHANNEL_SSI2_TX (MXC_DMA_CHANNEL_IRAM + 1)
+#else /*CONFIG_SDMA_IRAM */
+#define MXC_DMA_CHANNEL_SSI2_TX MXC_DMA_DYNAMIC_CHANNEL
+#endif /*CONFIG_SDMA_IRAM */
+#define MXC_DMA_CHANNEL_CSPI1_RX MXC_DMA_DYNAMIC_CHANNEL
+#define MXC_DMA_CHANNEL_CSPI1_TX MXC_DMA_DYNAMIC_CHANNEL
+#define MXC_DMA_CHANNEL_CSPI2_RX MXC_DMA_DYNAMIC_CHANNEL
+#define MXC_DMA_CHANNEL_CSPI2_TX MXC_DMA_DYNAMIC_CHANNEL
+#define MXC_DMA_CHANNEL_CSPI3_RX MXC_DMA_DYNAMIC_CHANNEL
+#define MXC_DMA_CHANNEL_CSPI3_TX MXC_DMA_DYNAMIC_CHANNEL
+#define MXC_DMA_CHANNEL_ATA_RX MXC_DMA_DYNAMIC_CHANNEL
+#define MXC_DMA_CHANNEL_ATA_TX MXC_DMA_DYNAMIC_CHANNEL
+#define MXC_DMA_CHANNEL_MEMORY MXC_DMA_DYNAMIC_CHANNEL
+
+/*
+ * AIPS 2
+ */
+#define AIPS2_BASE_ADDR 0xE3F00000
+#define AIPS2_BASE_ADDR_VIRT 0xFC200000
+#define AIPS2_SIZE SZ_1M
+
+#define PLL0_BASE_ADDR (AIPS2_BASE_ADDR + 0x00080000)
+#define PLL1_BASE_ADDR (AIPS2_BASE_ADDR + 0x00084000)
+#define PLL2_BASE_ADDR (AIPS2_BASE_ADDR + 0x00088000)
+#define CCM_BASE_ADDR (AIPS2_BASE_ADDR + 0x0008C000)
+#define GPC_BASE_ADDR (AIPS2_BASE_ADDR + 0x00090000)
+#define SRC_BASE_ADDR (AIPS2_BASE_ADDR + 0x00094000)
+#define EPIT1_BASE_ADDR (AIPS2_BASE_ADDR + 0x00098000)
+#define EPIT2_BASE_ADDR (AIPS2_BASE_ADDR + 0x0009C000)
+#define PWM_BASE_ADDR (AIPS2_BASE_ADDR + 0x000A0000)
+#define OWIRE_BASE_ADDR (AIPS2_BASE_ADDR + 0x000A4000)
+#define CSPI3_BASE_ADDR (AIPS2_BASE_ADDR + 0x000A8000)
+#define CSPI1_BASE_ADDR (AIPS2_BASE_ADDR + 0x000AC000)
+#define UART1_BASE_ADDR (AIPS2_BASE_ADDR + 0x000B0000)
+#define UART2_BASE_ADDR (AIPS2_BASE_ADDR + 0x000BC000)
+#define I2C3_BASE_ADDR (AIPS2_BASE_ADDR + 0x000C0000)
+#define I2C2_BASE_ADDR (AIPS2_BASE_ADDR + 0x000C4000)
+#define I2C_BASE_ADDR (AIPS2_BASE_ADDR + 0x000C8000)
+#define SSI1_BASE_ADDR (AIPS2_BASE_ADDR + 0x000CC000)
+#define AUDMUX_BASE_ADDR (AIPS2_BASE_ADDR + 0x000D0000)
+#define EMI_BASE_ADDR (AIPS2_BASE_ADDR + 0x000DBF00)
+
+#define M4IF_BASE_ADDR (AIPS2_BASE_ADDR + 0x000D8000)
+#define ESDCTL_BASE_ADDR (AIPS2_BASE_ADDR + 0x000D9000)
+#define WEIM_BASE_ADDR (AIPS2_BASE_ADDR + 0x000DA000)
+#define NFC_BASE_ADDR (AIPS2_BASE_ADDR + 0x000DB000)
+
+/*
+ * Memory regions and CS
+ */
+#define IPU_CTRL_BASE_ADDR 0x80000000
+#define CSD0_BASE_ADDR 0x40000000
+#define CSD1_BASE_ADDR 0x50000000
+
+#define CS0_BASE_ADDR 0x60000000
+#define CS1_BASE_ADDR 0x68000000
+#define CS2_BASE_ADDR 0x70000000
+
+/*!
+ * This macro defines the physical to virtual address mapping for all the
+ * peripheral modules. It is used by passing in the physical address as x
+ * and returning the virtual address. If the physical address is not mapped,
+ * it returns 0xDEADBEEF
+ */
+#define IO_ADDRESS(x) \
+ (void __force __iomem *) \
+ (((x >= (unsigned long)IRAM_BASE_ADDR) && (x < (unsigned long)IRAM_BASE_ADDR + IRAM_SIZE)) ? IRAM_IO_ADDRESS(x):\
+ ((x >= (unsigned long)PLATFORM_BASE_ADDR) && (x < (unsigned long)PLATFORM_BASE_ADDR + PLATFORM_SIZE)) ? PLATFORM_IO_ADDRESS(x):\
+ ((x >= (unsigned long)TZIC_BASE_ADDR) && (x < (unsigned long)TZIC_BASE_ADDR + TZIC_SIZE)) ? TZIC_IO_ADDRESS(x):\
+ ((x >= (unsigned long)DEBUG_BASE_ADDR) && (x < (unsigned long)DEBUG_BASE_ADDR + DEBUG_SIZE)) ? DEBUG_IO_ADDRESS(x):\
+ ((x >= (unsigned long)SPBA0_BASE_ADDR) && (x < (unsigned long)SPBA0_BASE_ADDR + SPBA0_SIZE)) ? SPBA0_IO_ADDRESS(x):\
+ ((x >= (unsigned long)AIPS1_BASE_ADDR) && (x < (unsigned long)AIPS1_BASE_ADDR + AIPS1_SIZE)) ? AIPS1_IO_ADDRESS(x):\
+ ((x >= (unsigned long)AIPS2_BASE_ADDR) && (x < (unsigned long)AIPS2_BASE_ADDR + AIPS2_SIZE)) ? AIPS2_IO_ADDRESS(x):\
+ ((x >= (unsigned long)NFC_BASE_ADDR_AXI) && (x < (unsigned long)NFC_BASE_ADDR_AXI + NFC_AXI_SIZE)) ? NFC_BASE_ADDR_AXI_IO_ADDRESS(x):\
+ 0xDEADBEEF)
+
+/*
+ * define the address mapping macros: in physical address order
+ */
+
+#define IRAM_IO_ADDRESS(x) \
+ (((x) - IRAM_BASE_ADDR) + IRAM_BASE_ADDR_VIRT)
+
+#define PLATFORM_IO_ADDRESS(x) \
+ (((x) - PLATFORM_BASE_ADDR) + PLATFORM_BASE_ADDR_VIRT)
+
+#define TZIC_IO_ADDRESS(x) \
+ (((x) - TZIC_BASE_ADDR) + TZIC_BASE_ADDR_VIRT)
+
+#define DEBUG_IO_ADDRESS(x) \
+ (((x) - DEBUG_BASE_ADDR) + DEBUG_BASE_ADDR_VIRT)
+
+#define SPBA0_IO_ADDRESS(x) \
+ (((x) - SPBA0_BASE_ADDR) + SPBA0_BASE_ADDR_VIRT)
+
+#define AIPS1_IO_ADDRESS(x) \
+ (((x) - AIPS1_BASE_ADDR) + AIPS1_BASE_ADDR_VIRT)
+
+#define AIPS2_IO_ADDRESS(x) \
+ (((x) - AIPS2_BASE_ADDR) + AIPS2_BASE_ADDR_VIRT)
+
+#define NFC_BASE_ADDR_AXI_IO_ADDRESS(x) \
+ (((x) - NFC_BASE_ADDR_AXI) + NFC_BASE_ADDR_AXI_VIRT)
+
+#define IS_MEM_DEVICE_NONSHARED(x) ((x) >= 0x80000000)
+
+/*
+ * DMA request assignments
+ */
+#define DMA_REQ_RESV47 47
+#define DMA_REQ_VPU 46
+#define DMA_REQ_SPDIF_TX 45
+#define DMA_REQ_UART3_TX 44
+#define DMA_REQ_UART3_RX 43
+#define DMA_REQ_I2C2 42
+#define DMA_REQ_I2C1 41
+#define DMA_REQ_SDHC3 40
+#define DMA_REQ_CSPI3_TX 39
+#define DMA_REQ_CSPI3_RX 38
+#define DMA_REQ_RESV37 37
+#define DMA_REQ_IPU 36
+#define DMA_REQ_RESV35 35
+#define DMA_REQ_EPIT2 34
+#define DMA_REQ_RESV33 33
+#define DMA_REQ_RESV32 32
+#define DMA_REQ_ECT 31
+#define DMA_REQ_NFC 30
+#define DMA_REQ_SSI1_TX1 29
+#define DMA_REQ_SSI1_RX1 28
+#define DMA_REQ_SSI1_TX2 27
+#define DMA_REQ_SSI1_RX2 26
+#define DMA_REQ_SSI2_TX1 25
+#define DMA_REQ_SSI2_RX1 24
+#define DMA_REQ_SSI2_TX2 23
+#define DMA_REQ_SSI2_RX2 22
+#define DMA_REQ_SDHC2 21
+#define DMA_REQ_SDHC1 20
+#define DMA_REQ_UART1_TX 19
+#define DMA_REQ_UART1_RX 18
+#define DMA_REQ_UART2_TX 17
+#define DMA_REQ_UART2_RX 16
+#define DMA_REQ_GPIO1_0 15
+#define DMA_REQ_GPIO1_1 14
+#define DMA_REQ_RESV13 13
+#define DMA_REQ_RESV12 12
+#define DMA_REQ_RESV11 11
+#define DMA_REQ_RESV10 10
+#define DMA_REQ_CSPI1_TX 9
+#define DMA_REQ_CSPI1_RX 8
+#define DMA_REQ_CSPI2_TX 7
+#define DMA_REQ_CSPI2_RX 6
+#define DMA_REQ_RESV5 5
+#define DMA_REQ_ATA_TX_END 4
+#define DMA_REQ_ATA_TX 3
+#define DMA_REQ_ATA_RX 2
+#define DMA_REQ_GPC 1
+#define DMA_REQ_RESV0 0
+
+/*
+ * Interrupt numbers
+ */
+#define MXC_INT_BASE 0
+#define MXC_INT_RESV0 0
+#define MXC_INT_MMC_SDHC1 1
+#define MXC_INT_MMC_SDHC2 2
+#define MXC_INT_MMC_SDHC3 3
+#define MXC_INT_RESV4 4
+#define MXC_INT_RESV5 5
+#define MXC_INT_SDMA 6
+#define MXC_INT_IOMUX 7
+#define MXC_INT_RESV8 8
+#define MXC_INT_VPU 9
+#define MXC_INT_IPU_ERR 10
+#define MXC_INT_IPU_SYN 11
+#define MXC_INT_RESV12 12
+#define MXC_INT_RESV13 13
+#define MXC_INT_RNG 14
+#define MXC_INT_EMI 15
+#define MXC_INT_RESV16 16
+#define MXC_INT_RESV17 17
+#define MXC_INT_USB_OTG 18
+#define MXC_INT_RESV19 19
+#define MXC_INT_RESV20 20
+#define MXC_INT_SCC_SMN 21
+#define MXC_INT_SCC_STZ 22
+#define MXC_INT_SCC_SCM 23
+#define MXC_INT_SRTC_NTZ 24
+#define MXC_INT_SRTC_TZ 25
+#define MXC_INT_RTIC 26
+#define MXC_INT_CSU 27
+#define MXC_INT_RESV28 28
+#define MXC_INT_SSI1 29
+#define MXC_INT_SSI2 30
+#define MXC_INT_UART1 31
+#define MXC_INT_UART2 32
+#define MXC_INT_UART3 33
+#define MXC_INT_RESV34 34
+#define MXC_INT_RESV35 35
+#define MXC_INT_CSPI1 36
+#define MXC_INT_CSPI2 37
+#define MXC_INT_CSPI3 38
+#define MXC_INT_GPT 39
+#define MXC_INT_EPIT1 40
+#define MXC_INT_EPIT2 41
+#define MXC_INT_GPIO1_INT7 42
+#define MXC_INT_GPIO1_INT6 43
+#define MXC_INT_GPIO1_INT5 44
+#define MXC_INT_GPIO1_INT4 45
+#define MXC_INT_GPIO1_INT3 46
+#define MXC_INT_GPIO1_INT2 47
+#define MXC_INT_GPIO1_INT1 48
+#define MXC_INT_GPIO1_INT0 49
+#define MXC_INT_GPIO1_LOW 50
+#define MXC_INT_GPIO1_HIGH 51
+#define MXC_INT_GPIO2_LOW 52
+#define MXC_INT_GPIO2_HIGH 53
+#define MXC_INT_GPIO3_LOW 54
+#define MXC_INT_GPIO3_HIGH 55
+#define MXC_INT_RESV56 56
+#define MXC_INT_RESV57 57
+#define MXC_INT_WDOG1 58
+#define MXC_INT_WDOG2 59
+#define MXC_INT_KPP 60
+#define MXC_INT_PWM 61
+#define MXC_INT_I2C 62
+#define MXC_INT_I2C2 63
+#define MXC_INT_I2C3 64
+#define MXC_INT_MSHC1 65
+#define MXC_INT_RESV66 66
+#define MXC_INT_RESV67 67
+#define MXC_INT_RESV68 68
+#define MXC_INT_IIM 69
+#define MXC_INT_ATA 70
+#define MXC_INT_CCM1 71
+#define MXC_INT_CCM2 72
+#define MXC_INT_GPC1 73
+#define MXC_INT_GPC2 74
+#define MXC_INT_SRC 75
+#define MXC_INT_EVTMON 76
+#define MXC_INT_PER_MEASURE 77
+#define MXC_INT_DECODE_ERR 78
+#define MXC_INT_EVT_COUNT 79
+#define MXC_INT_SLAVE_ERR 80
+#define MXC_INT_RESV81 81
+#define MXC_INT_RESV82 82
+#define MXC_INT_RESV83 83
+#define MXC_INT_RESV84 84
+#define MXC_INT_RESV85 85
+#define MXC_INT_RESV86 86
+#define MXC_INT_FEC 87
+#define MXC_INT_OWIRE 88
+#define MXC_INT_CTI0 89
+#define MXC_INT_CTM0 90
+#define MXC_INT_SPDIF 91
+#define MXC_INT_TVOUT 92
+
+/*!
+ * Interrupt Number for ARM11 PMU
+ */
+#define ARM11_PMU_IRQ MXC_INT_EVTMON
+
+/* gpio and gpio based interrupt handling */
+#define GPIO_DR 0x00
+#define GPIO_GDIR 0x04
+#define GPIO_PSR 0x08
+#define GPIO_ICR1 0x0C
+#define GPIO_ICR2 0x10
+#define GPIO_IMR 0x14
+#define GPIO_ISR 0x18
+#define GPIO_INT_LOW_LEV 0x0
+#define GPIO_INT_HIGH_LEV 0x1
+#define GPIO_INT_RISE_EDGE 0x2
+#define GPIO_INT_FALL_EDGE 0x3
+#define GPIO_INT_NONE 0x4
+
+/*!
+ * Macro to convert elv, llv, ulv to a data which is used to set DCVR0, DCVR1,
+ * DCVR2, or DCVR3.
+ */
+#define DCVR(elv, llv, ulv) ((elv << 0) | (llv << 10) | (ulv << 21))
+
+#endif /* __ASM_ARCH_MXC_MX37_H__ */
diff --git a/arch/arm/plat-mxc/include/mach/mx3x.h b/arch/arm/plat-mxc/include/mach/mx3x.h
index b559a4bb5769..d297a832d3ad 100644
--- a/arch/arm/plat-mxc/include/mach/mx3x.h
+++ b/arch/arm/plat-mxc/include/mach/mx3x.h
@@ -8,8 +8,8 @@
* published by the Free Software Foundation.
*/
-#ifndef __ASM_ARCH_MXC_MX31_H__
-#define __ASM_ARCH_MXC_MX31_H__
+#ifndef __ASM_ARCH_MXC_MX3X_H__
+#define __ASM_ARCH_MXC_MX3X_H__
#ifndef __ASM_ARCH_MXC_HARDWARE_H__
#error "Do not include directly."
@@ -99,6 +99,11 @@
#define MSHC1_BASE_ADDR (SPBA0_BASE_ADDR + 0x00024000)
#define SPBA_CTRL_BASE_ADDR (SPBA0_BASE_ADDR + 0x0003C000)
+#define SPBA_UART3 0x0C
+#define SPBA_CSPI2 0x10
+#define SPBA_SSI2 0x14
+#define SPBA_ATA 0x20
+
/*
* AIPS 2
*/
@@ -118,7 +123,7 @@
#define GPIO2_BASE_ADDR (AIPS2_BASE_ADDR + 0x000D0000)
#define SDMA_BASE_ADDR (AIPS2_BASE_ADDR + 0x000D4000)
#define RTC_BASE_ADDR (AIPS2_BASE_ADDR + 0x000D8000)
-#define WDOG_BASE_ADDR (AIPS2_BASE_ADDR + 0x000DC000)
+#define WDOG1_BASE_ADDR (AIPS2_BASE_ADDR + 0x000DC000)
#define PWM_BASE_ADDR (AIPS2_BASE_ADDR + 0x000E0000)
#define RTIC_BASE_ADDR (AIPS2_BASE_ADDR + 0x000EC000)
@@ -168,6 +173,7 @@
((x >= AVIC_BASE_ADDR) && (x < (AVIC_BASE_ADDR + AVIC_SIZE))) ? AVIC_IO_ADDRESS(x):\
((x >= CS4_BASE_ADDR) && (x < (CS4_BASE_ADDR + CS4_SIZE))) ? CS4_IO_ADDRESS(x):\
((x >= X_MEMC_BASE_ADDR) && (x < (X_MEMC_BASE_ADDR + X_MEMC_SIZE))) ? X_MEMC_IO_ADDRESS(x):\
+ ((x >= NFC_BASE_ADDR) && (x < (NFC_BASE_ADDR + NFC_SIZE))) ? NFC_IO_ADDRESS(x):\
0xDEADBEEF)
/*
@@ -204,8 +210,38 @@
(((x) - X_MEMC_BASE_ADDR) + X_MEMC_BASE_ADDR_VIRT)
/*
+ * DMA request assignments
+ */
+#define DMA_REQ_ECT 31
+#define DMA_REQ_NFC 30
+#define DMA_REQ_SSI1_TX1 29
+#define DMA_REQ_SSI1_RX1 28
+#define DMA_REQ_SSI1_TX2 27
+#define DMA_REQ_SSI1_RX2 26
+#define DMA_REQ_SSI2_TX1 25
+#define DMA_REQ_SSI2_RX1 24
+#define DMA_REQ_SSI2_TX2 23
+#define DMA_REQ_SSI2_RX2 22
+#define DMA_REQ_UART1_TX 19
+#define DMA_REQ_UART1_RX 18
+#define DMA_REQ_UART2_TX 17
+#define DMA_REQ_UART2_RX 16
+#define DMA_REQ_EXTREQ1 15
+#define DMA_REQ_EXTREQ2 14
+#define DMA_REQ_CSPI1_TX 9
+#define DMA_REQ_CSPI1_RX 8
+#define DMA_REQ_CSPI2_TX 7
+#define DMA_REQ_CSPI2_RX 6
+#define DMA_REQ_ATA_RX 4
+#define DMA_REQ_ATA_TX 3
+#define DMA_REQ_ATA_TX_END 2
+#define DMA_REQ_CCM 1
+#define DMA_REQ_EXTREQ0 0
+
+/*
* Interrupt numbers
*/
+#define MXC_INT_RESV1 1
#define MXC_INT_I2C3 3
#define MXC_INT_I2C2 4
#define MXC_INT_RTIC 6
@@ -224,6 +260,7 @@
#define MXC_INT_EPIT1 28
#define MXC_INT_GPT 29
#define MXC_INT_POWER_FAIL 30
+#define MXC_INT_DVFS 31
#define MXC_INT_UART2 32
#define MXC_INT_NANDFC 33
#define MXC_INT_SDMA 34
@@ -245,6 +282,8 @@
#define MXC_INT_EXT_WDOG 62
#define MXC_INT_EXT_TV 63
+#define ARM11_PMU_IRQ MXC_INT_EVTMON
+
#define PROD_SIGNATURE 0x1 /* For MX31 */
/* silicon revisions specific to i.MX31 */
diff --git a/arch/arm/plat-mxc/include/mach/mx51.h b/arch/arm/plat-mxc/include/mach/mx51.h
new file mode 100644
index 000000000000..ab9ddb2c07e1
--- /dev/null
+++ b/arch/arm/plat-mxc/include/mach/mx51.h
@@ -0,0 +1,511 @@
+/*
+ * Copyright 2008-2009 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 __ASM_ARCH_MXC_MX51_H__
+#define __ASM_ARCH_MXC_MX51_H__
+
+#ifndef __ASM_ARCH_MXC_HARDWARE_H__
+#error "Do not include directly."
+#endif
+
+/*!
+ * @file arch-mxc/mx51.h
+ * @brief This file contains register definitions.
+ *
+ * @ingroup MSL_MX51
+ */
+
+/*!
+ * Register an interrupt handler for the SMN as well as the SCC. In some
+ * implementations, the SMN is not connected at all, and in others, it is
+ * on the same interrupt line as the SCM. Comment this line out accordingly
+ */
+#define USE_SMN_INTERRUPT
+
+/*!
+ * This option is used to set or clear the RXDMUXSEL bit in control reg 3.
+ * Certain platforms need this bit to be set in order to receive Irda data.
+ */
+#define MXC_UART_IR_RXDMUX 0x0004
+/*!
+ * This option is used to set or clear the RXDMUXSEL bit in control reg 3.
+ * Certain platforms need this bit to be set in order to receive UART data.
+ */
+#define MXC_UART_RXDMUX 0x0004
+
+/*!
+ * This option is used to set or clear the dspdma bit in the SDMA config
+ * register.
+ */
+#define MXC_SDMA_DSPDMA 0
+
+/*!
+ * Define this option to specify we are using the newer SDMA module.
+ */
+#define MXC_SDMA_V2
+
+ /*
+ * IRAM
+ */
+#define IRAM_BASE_ADDR 0x1FFE0000 /* internal ram */
+#define IRAM_BASE_ADDR_VIRT 0xFA3E0000
+#define IRAM_PARTITIONS 16
+#define IRAM_PARTITIONS_TO1 12
+#define IRAM_SIZE (IRAM_PARTITIONS*SZ_8K) /* 128KB */
+
+#if defined(CONFIG_MXC_SECURITY_SCC2) \
+ || defined(CONFIG_MXC_SECURITY_SCC2_MODULE)
+#define SCC_IRAM_SIZE SZ_16K
+#else
+#define SCC_IRAM_SIZE 0
+#endif
+
+#ifdef CONFIG_SDMA_IRAM
+#define SDMA_IRAM_SIZE CONFIG_SDMA_IRAM_SIZE
+#else
+#define SDMA_IRAM_SIZE 0
+#endif
+
+#ifdef CONFIG_SND_MXC_SOC_IRAM
+#define SND_RAM_SIZE 0x6000
+#else
+#define SND_RAM_SIZE 0
+#endif
+
+#ifdef CONFIG_MXC_VPU_IRAM
+#define VPU_IRAM_SIZE 0x7000
+#else
+#define VPU_IRAM_SIZE 0
+#endif
+
+#if (IRAM_SIZE < (SDMA_IRAM_SIZE + SND_RAM_SIZE + VPU_IRAM_SIZE + \
+ SCC_IRAM_SIZE))
+#error "IRAM size exceeded"
+#endif
+
+#define SCC_IRAM_BASE_ADDR (IRAM_BASE_ADDR + IRAM_SIZE - SCC_IRAM_SIZE)
+#define VPU_IRAM_BASE_ADDR (SCC_IRAM_BASE_ADDR - VPU_IRAM_SIZE)
+#define SND_RAM_BASE_ADDR (VPU_IRAM_BASE_ADDR - SND_RAM_SIZE)
+#define SDMA_IRAM_BASE_ADDR (SND_RAM_BASE_ADDR - SDMA_IRAM_SIZE)
+#define IDLE_IRAM_BASE_ADDR (SDMA_IRAM_BASE_ADDR - SZ_4K)
+#define SUSPEND_IRAM_BASE_ADDR (IDLE_IRAM_BASE_ADDR - SZ_4K)
+/*
+ * NFC
+ */
+#define NFC_BASE_ADDR_AXI 0xCFFF0000 /* NAND flash AXI */
+#define NFC_BASE_ADDR_AXI_VIRT 0xF9000000
+#define NFC_AXI_SIZE SZ_64K
+
+/*
+ * Graphics Memory of GPU
+ */
+#define GPU_BASE_ADDR 0x20000000
+#define GPU2D_BASE_ADDR 0xD0000000
+
+#define TZIC_BASE_ADDR 0x8FFFC000
+#define TZIC_BASE_ADDR_VIRT 0xFA100000
+#define TZIC_SIZE SZ_16K
+
+#define DEBUG_BASE_ADDR 0x60000000
+#define DEBUG_BASE_ADDR_VIRT 0xFA200000
+#define DEBUG_SIZE SZ_1M
+#define ETB_BASE_ADDR (DEBUG_BASE_ADDR + 0x00001000)
+#define ETM_BASE_ADDR (DEBUG_BASE_ADDR + 0x00002000)
+#define TPIU_BASE_ADDR (DEBUG_BASE_ADDR + 0x00003000)
+#define CTI0_BASE_ADDR (DEBUG_BASE_ADDR + 0x00004000)
+#define CTI1_BASE_ADDR (DEBUG_BASE_ADDR + 0x00005000)
+#define CTI2_BASE_ADDR (DEBUG_BASE_ADDR + 0x00006000)
+#define CTI3_BASE_ADDR (DEBUG_BASE_ADDR + 0x00007000)
+#define CORTEX_DBG_BASE_ADDR (DEBUG_BASE_ADDR + 0x00008000)
+
+/*
+ * SPBA global module enabled #0
+ */
+#define SPBA0_BASE_ADDR 0x70000000
+#define SPBA0_BASE_ADDR_VIRT 0xFB100000
+#define SPBA0_SIZE SZ_1M
+
+#define MMC_SDHC1_BASE_ADDR (SPBA0_BASE_ADDR + 0x00004000)
+#define MMC_SDHC2_BASE_ADDR (SPBA0_BASE_ADDR + 0x00008000)
+#define UART3_BASE_ADDR (SPBA0_BASE_ADDR + 0x0000C000)
+#define CSPI1_BASE_ADDR (SPBA0_BASE_ADDR + 0x00010000)
+#define SSI2_BASE_ADDR (SPBA0_BASE_ADDR + 0x00014000)
+#define MMC_SDHC3_BASE_ADDR (SPBA0_BASE_ADDR + 0x00020000)
+#define MMC_SDHC4_BASE_ADDR (SPBA0_BASE_ADDR + 0x00024000)
+#define SPDIF_BASE_ADDR (SPBA0_BASE_ADDR + 0x00028000)
+#define ATA_DMA_BASE_ADDR (SPBA0_BASE_ADDR + 0x00030000)
+#define SLIM_DMA_BASE_ADDR (SPBA0_BASE_ADDR + 0x00034000)
+#define HSI2C_DMA_BASE_ADDR (SPBA0_BASE_ADDR + 0x00038000)
+#define SPBA_CTRL_BASE_ADDR (SPBA0_BASE_ADDR + 0x0003C000)
+
+/*!
+ * defines for SPBA modules
+ */
+#define SPBA_SDHC1 0x04
+#define SPBA_SDHC2 0x08
+#define SPBA_UART3 0x0C
+#define SPBA_CSPI1 0x10
+#define SPBA_SSI2 0x14
+#define SPBA_SDHC3 0x20
+#define SPBA_SDHC4 0x24
+#define SPBA_SPDIF 0x28
+#define SPBA_ATA 0x30
+#define SPBA_SLIM 0x34
+#define SPBA_HSI2C 0x38
+#define SPBA_CTRL 0x3C
+
+/*
+ * AIPS 1
+ */
+#define AIPS1_BASE_ADDR 0x73F00000
+#define AIPS1_BASE_ADDR_VIRT 0xFB000000
+#define AIPS1_SIZE SZ_1M
+
+#define OTG_BASE_ADDR (AIPS1_BASE_ADDR + 0x00080000)
+#define GPIO1_BASE_ADDR (AIPS1_BASE_ADDR + 0x00084000)
+#define GPIO2_BASE_ADDR (AIPS1_BASE_ADDR + 0x00088000)
+#define GPIO3_BASE_ADDR (AIPS1_BASE_ADDR + 0x0008C000)
+#define GPIO4_BASE_ADDR (AIPS1_BASE_ADDR + 0x00090000)
+#define KPP_BASE_ADDR (AIPS1_BASE_ADDR + 0x00094000)
+#define WDOG1_BASE_ADDR (AIPS1_BASE_ADDR + 0x00098000)
+#define WDOG2_BASE_ADDR (AIPS1_BASE_ADDR + 0x0009C000)
+#define GPT1_BASE_ADDR (AIPS1_BASE_ADDR + 0x000A0000)
+#define SRTC_BASE_ADDR (AIPS1_BASE_ADDR + 0x000A4000)
+#define IOMUXC_BASE_ADDR (AIPS1_BASE_ADDR + 0x000A8000)
+#define EPIT1_BASE_ADDR (AIPS1_BASE_ADDR + 0x000AC000)
+#define EPIT2_BASE_ADDR (AIPS1_BASE_ADDR + 0x000B0000)
+#define PWM1_BASE_ADDR (AIPS1_BASE_ADDR + 0x000B4000)
+#define PWM2_BASE_ADDR (AIPS1_BASE_ADDR + 0x000B8000)
+#define UART1_BASE_ADDR (AIPS1_BASE_ADDR + 0x000BC000)
+#define UART2_BASE_ADDR (AIPS1_BASE_ADDR + 0x000C0000)
+#define SRC_BASE_ADDR (AIPS1_BASE_ADDR + 0x000D0000)
+#define CCM_BASE_ADDR (AIPS1_BASE_ADDR + 0x000D4000)
+#define GPC_BASE_ADDR (AIPS1_BASE_ADDR + 0x000D8000)
+
+/*!
+ * Defines for modules using static and dynamic DMA channels
+ */
+#define MXC_DMA_CHANNEL_IRAM 30
+#define MXC_DMA_CHANNEL_SPDIF_TX MXC_DMA_DYNAMIC_CHANNEL
+#define MXC_DMA_CHANNEL_UART1_RX MXC_DMA_DYNAMIC_CHANNEL
+#define MXC_DMA_CHANNEL_UART1_TX MXC_DMA_DYNAMIC_CHANNEL
+#define MXC_DMA_CHANNEL_UART2_RX MXC_DMA_DYNAMIC_CHANNEL
+#define MXC_DMA_CHANNEL_UART2_TX MXC_DMA_DYNAMIC_CHANNEL
+#define MXC_DMA_CHANNEL_UART3_RX MXC_DMA_DYNAMIC_CHANNEL
+#define MXC_DMA_CHANNEL_UART3_TX MXC_DMA_DYNAMIC_CHANNEL
+#define MXC_DMA_CHANNEL_MMC1 MXC_DMA_DYNAMIC_CHANNEL
+#define MXC_DMA_CHANNEL_MMC2 MXC_DMA_DYNAMIC_CHANNEL
+#define MXC_DMA_CHANNEL_SSI1_RX MXC_DMA_DYNAMIC_CHANNEL
+#define MXC_DMA_CHANNEL_SSI1_TX MXC_DMA_DYNAMIC_CHANNEL
+#define MXC_DMA_CHANNEL_SSI2_RX MXC_DMA_DYNAMIC_CHANNEL
+#ifdef CONFIG_SDMA_IRAM
+#define MXC_DMA_CHANNEL_SSI2_TX (MXC_DMA_CHANNEL_IRAM + 1)
+#else /*CONFIG_SDMA_IRAM */
+#define MXC_DMA_CHANNEL_SSI2_TX MXC_DMA_DYNAMIC_CHANNEL
+#endif /*CONFIG_SDMA_IRAM */
+#define MXC_DMA_CHANNEL_CSPI1_RX MXC_DMA_DYNAMIC_CHANNEL
+#define MXC_DMA_CHANNEL_CSPI1_TX MXC_DMA_DYNAMIC_CHANNEL
+#define MXC_DMA_CHANNEL_CSPI2_RX MXC_DMA_DYNAMIC_CHANNEL
+#define MXC_DMA_CHANNEL_CSPI2_TX MXC_DMA_DYNAMIC_CHANNEL
+#define MXC_DMA_CHANNEL_CSPI3_RX MXC_DMA_DYNAMIC_CHANNEL
+#define MXC_DMA_CHANNEL_CSPI3_TX MXC_DMA_DYNAMIC_CHANNEL
+#define MXC_DMA_CHANNEL_ATA_RX MXC_DMA_DYNAMIC_CHANNEL
+#define MXC_DMA_CHANNEL_ATA_TX MXC_DMA_DYNAMIC_CHANNEL
+#define MXC_DMA_CHANNEL_MEMORY MXC_DMA_DYNAMIC_CHANNEL
+
+/*
+ * AIPS 2
+ */
+#define AIPS2_BASE_ADDR 0x83F00000
+#define AIPS2_BASE_ADDR_VIRT 0xFB200000
+#define AIPS2_SIZE SZ_1M
+
+#define PLL1_BASE_ADDR (AIPS2_BASE_ADDR + 0x00080000)
+#define PLL2_BASE_ADDR (AIPS2_BASE_ADDR + 0x00084000)
+#define PLL3_BASE_ADDR (AIPS2_BASE_ADDR + 0x00088000)
+#define AHBMAX_BASE_ADDR (AIPS2_BASE_ADDR + 0x00094000)
+#define IIM_BASE_ADDR (AIPS2_BASE_ADDR + 0x00098000)
+#define CSU_BASE_ADDR (AIPS2_BASE_ADDR + 0x0009C000)
+#define ARM_BASE_ADDR (AIPS2_BASE_ADDR + 0x000A0000)
+#define OWIRE_BASE_ADDR (AIPS2_BASE_ADDR + 0x000A4000)
+#define FIRI_BASE_ADDR (AIPS2_BASE_ADDR + 0x000A8000)
+#define CSPI2_BASE_ADDR (AIPS2_BASE_ADDR + 0x000AC000)
+#define SDMA_BASE_ADDR (AIPS2_BASE_ADDR + 0x000B0000)
+#define SCC_BASE_ADDR (AIPS2_BASE_ADDR + 0x000B4000)
+#define ROMCP_BASE_ADDR (AIPS2_BASE_ADDR + 0x000B8000)
+#define RTIC_BASE_ADDR (AIPS2_BASE_ADDR + 0x000BC000)
+#define CSPI3_BASE_ADDR (AIPS2_BASE_ADDR + 0x000C0000)
+#define I2C2_BASE_ADDR (AIPS2_BASE_ADDR + 0x000C4000)
+#define I2C1_BASE_ADDR (AIPS2_BASE_ADDR + 0x000C8000)
+#define SSI1_BASE_ADDR (AIPS2_BASE_ADDR + 0x000CC000)
+#define AUDMUX_BASE_ADDR (AIPS2_BASE_ADDR + 0x000D0000)
+#define M4IF_BASE_ADDR (AIPS2_BASE_ADDR + 0x000D8000)
+#define ESDCTL_BASE_ADDR (AIPS2_BASE_ADDR + 0x000D9000)
+#define WEIM_BASE_ADDR (AIPS2_BASE_ADDR + 0x000DA000)
+#define NFC_BASE_ADDR (AIPS2_BASE_ADDR + 0x000DB000)
+#define EMI_BASE_ADDR (AIPS2_BASE_ADDR + 0x000DBF00)
+#define MIPI_HSC_BASE_ADDR (AIPS2_BASE_ADDR + 0x000DC000)
+#define ATA_BASE_ADDR (AIPS2_BASE_ADDR + 0x000E0000)
+#define SIM_BASE_ADDR (AIPS2_BASE_ADDR + 0x000E4000)
+#define SSI3BASE_ADDR (AIPS2_BASE_ADDR + 0x000E8000)
+#define FEC_BASE_ADDR (AIPS2_BASE_ADDR + 0x000EC000)
+#define TVE_BASE_ADDR (AIPS2_BASE_ADDR + 0x000F0000)
+#define VPU_BASE_ADDR (AIPS2_BASE_ADDR + 0x000F4000)
+#define SAHARA_BASE_ADDR (AIPS2_BASE_ADDR + 0x000F8000)
+
+/*
+ * Memory regions and CS
+ */
+#define GPU_CTRL_BASE_ADDR 0x30000000
+#define IPU_CTRL_BASE_ADDR 0x40000000
+#define CSD0_BASE_ADDR 0x90000000
+#define CSD1_BASE_ADDR 0xA0000000
+#define CS0_BASE_ADDR 0xB0000000
+#define CS1_BASE_ADDR 0xB8000000
+#define CS2_BASE_ADDR 0xC0000000
+#define CS3_BASE_ADDR 0xC8000000
+#define CS4_BASE_ADDR 0xCC000000
+#define CS5_BASE_ADDR 0xCE000000
+
+/*!
+ * This macro defines the physical to virtual address mapping for all the
+ * peripheral modules. It is used by passing in the physical address as x
+ * and returning the virtual address. If the physical address is not mapped,
+ * it returns 0xDEADBEEF
+ */
+#define IO_ADDRESS(x) \
+ (void __force __iomem *) \
+ ((((x) >= (unsigned long)IRAM_BASE_ADDR) && \
+ ((x) < (unsigned long)IRAM_BASE_ADDR + IRAM_SIZE)) ? \
+ IRAM_IO_ADDRESS(x):\
+ (((x) >= (unsigned long)TZIC_BASE_ADDR) && \
+ ((x) < (unsigned long)TZIC_BASE_ADDR + TZIC_SIZE)) ? \
+ TZIC_IO_ADDRESS(x):\
+ (((x) >= (unsigned long)DEBUG_BASE_ADDR) && \
+ ((x) < (unsigned long)DEBUG_BASE_ADDR + DEBUG_SIZE)) ? \
+ DEBUG_IO_ADDRESS(x):\
+ (((x) >= (unsigned long)SPBA0_BASE_ADDR) && \
+ ((x) < (unsigned long)SPBA0_BASE_ADDR + SPBA0_SIZE)) ? \
+ SPBA0_IO_ADDRESS(x):\
+ (((x) >= (unsigned long)AIPS1_BASE_ADDR) && \
+ ((x) < (unsigned long)AIPS1_BASE_ADDR + AIPS1_SIZE)) ? \
+ AIPS1_IO_ADDRESS(x):\
+ (((x) >= (unsigned long)AIPS2_BASE_ADDR) && \
+ ((x) < (unsigned long)AIPS2_BASE_ADDR + AIPS2_SIZE)) ? \
+ AIPS2_IO_ADDRESS(x):\
+ (((x) >= (unsigned long)NFC_BASE_ADDR_AXI) && \
+ ((x) < (unsigned long)NFC_BASE_ADDR_AXI + NFC_AXI_SIZE)) ? \
+ NFC_BASE_ADDR_AXI_IO_ADDRESS(x):\
+ 0xDEADBEEF)
+
+/*
+ * define the address mapping macros: in physical address order
+ */
+#define IRAM_IO_ADDRESS(x) \
+ (((x) - IRAM_BASE_ADDR) + IRAM_BASE_ADDR_VIRT)
+
+#define TZIC_IO_ADDRESS(x) \
+ (((x) - TZIC_BASE_ADDR) + TZIC_BASE_ADDR_VIRT)
+
+#define DEBUG_IO_ADDRESS(x) \
+ (((x) - DEBUG_BASE_ADDR) + DEBUG_BASE_ADDR_VIRT)
+
+#define SPBA0_IO_ADDRESS(x) \
+ (((x) - SPBA0_BASE_ADDR) + SPBA0_BASE_ADDR_VIRT)
+
+#define AIPS1_IO_ADDRESS(x) \
+ (((x) - AIPS1_BASE_ADDR) + AIPS1_BASE_ADDR_VIRT)
+
+#define AIPS2_IO_ADDRESS(x) \
+ (((x) - AIPS2_BASE_ADDR) + AIPS2_BASE_ADDR_VIRT)
+
+#define NFC_BASE_ADDR_AXI_IO_ADDRESS(x) \
+ (((x) - NFC_BASE_ADDR_AXI) + NFC_BASE_ADDR_AXI_VIRT)
+
+#define IS_MEM_DEVICE_NONSHARED(x) 0
+
+/*
+ * DMA request assignments
+ */
+#define DMA_REQ_SSI3_TX1 47
+#define DMA_REQ_SSI3_RX1 46
+#define DMA_REQ_SPDIF 45
+#define DMA_REQ_UART3_TX 44
+#define DMA_REQ_UART3_RX 43
+#define DMA_REQ_SLIM_B_TX 42
+#define DMA_REQ_SDHC4 41
+#define DMA_REQ_SDHC3 40
+#define DMA_REQ_CSPI_TX 39
+#define DMA_REQ_CSPI_RX 38
+#define DMA_REQ_SSI3_TX2 37
+#define DMA_REQ_IPU 36
+#define DMA_REQ_SSI3_RX2 35
+#define DMA_REQ_EPIT2 34
+#define DMA_REQ_CTI2_1 33
+#define DMA_REQ_EMI_WR 32
+#define DMA_REQ_CTI2_0 31
+#define DMA_REQ_EMI_RD 30
+#define DMA_REQ_SSI1_TX1 29
+#define DMA_REQ_SSI1_RX1 28
+#define DMA_REQ_SSI1_TX2 27
+#define DMA_REQ_SSI1_RX2 26
+#define DMA_REQ_SSI2_TX1 25
+#define DMA_REQ_SSI2_RX1 24
+#define DMA_REQ_SSI2_TX2 23
+#define DMA_REQ_SSI2_RX2 22
+#define DMA_REQ_SDHC2 21
+#define DMA_REQ_SDHC1 20
+#define DMA_REQ_UART1_TX 19
+#define DMA_REQ_UART1_RX 18
+#define DMA_REQ_UART2_TX 17
+#define DMA_REQ_UART2_RX 16
+#define DMA_REQ_GPU 15
+#define DMA_REQ_EXTREQ1 14
+#define DMA_REQ_FIRI_TX 13
+#define DMA_REQ_FIRI_RX 12
+#define DMA_REQ_HS_I2C_RX 11
+#define DMA_REQ_HS_I2C_TX 10
+#define DMA_REQ_CSPI2_TX 9
+#define DMA_REQ_CSPI2_RX 8
+#define DMA_REQ_CSPI1_TX 7
+#define DMA_REQ_CSPI1_RX 6
+#define DMA_REQ_SLIM_B 5
+#define DMA_REQ_ATA_TX_END 4
+#define DMA_REQ_ATA_TX 3
+#define DMA_REQ_ATA_RX 2
+#define DMA_REQ_GPC 1
+#define DMA_REQ_VPU 0
+
+/*
+ * Interrupt numbers
+ */
+#define MXC_INT_BASE 0
+#define MXC_INT_RESV0 0
+#define MXC_INT_MMC_SDHC1 1
+#define MXC_INT_MMC_SDHC2 2
+#define MXC_INT_MMC_SDHC3 3
+#define MXC_INT_MMC_SDHC4 4
+#define MXC_INT_RESV5 5
+#define MXC_INT_SDMA 6
+#define MXC_INT_IOMUX 7
+#define MXC_INT_NFC 8
+#define MXC_INT_VPU 9
+#define MXC_INT_IPU_ERR 10
+#define MXC_INT_IPU_SYN 11
+#define MXC_INT_GPU 12
+#define MXC_INT_RESV13 13
+#define MXC_INT_USB_H1 14
+#define MXC_INT_EMI 15
+#define MXC_INT_USB_H2 16
+#define MXC_INT_USB_H3 17
+#define MXC_INT_USB_OTG 18
+#define MXC_INT_SAHARA_H0 19
+#define MXC_INT_SAHARA_H1 20
+#define MXC_INT_SCC_SMN 21
+#define MXC_INT_SCC_STZ 22
+#define MXC_INT_SCC_SCM 23
+#define MXC_INT_SRTC_NTZ 24
+#define MXC_INT_SRTC_TZ 25
+#define MXC_INT_RTIC 26
+#define MXC_INT_CSU 27
+#define MXC_INT_SLIM_B 28
+#define MXC_INT_SSI1 29
+#define MXC_INT_SSI2 30
+#define MXC_INT_UART1 31
+#define MXC_INT_UART2 32
+#define MXC_INT_UART3 33
+#define MXC_INT_RESV34 34
+#define MXC_INT_RESV35 35
+#define MXC_INT_CSPI1 36
+#define MXC_INT_CSPI2 37
+#define MXC_INT_CSPI 38
+#define MXC_INT_GPT 39
+#define MXC_INT_EPIT1 40
+#define MXC_INT_EPIT2 41
+#define MXC_INT_GPIO1_INT7 42
+#define MXC_INT_GPIO1_INT6 43
+#define MXC_INT_GPIO1_INT5 44
+#define MXC_INT_GPIO1_INT4 45
+#define MXC_INT_GPIO1_INT3 46
+#define MXC_INT_GPIO1_INT2 47
+#define MXC_INT_GPIO1_INT1 48
+#define MXC_INT_GPIO1_INT0 49
+#define MXC_INT_GPIO1_LOW 50
+#define MXC_INT_GPIO1_HIGH 51
+#define MXC_INT_GPIO2_LOW 52
+#define MXC_INT_GPIO2_HIGH 53
+#define MXC_INT_GPIO3_LOW 54
+#define MXC_INT_GPIO3_HIGH 55
+#define MXC_INT_GPIO4_LOW 56
+#define MXC_INT_GPIO4_HIGH 57
+#define MXC_INT_WDOG1 58
+#define MXC_INT_WDOG2 59
+#define MXC_INT_KPP 60
+#define MXC_INT_PWM1 61
+#define MXC_INT_I2C1 62
+#define MXC_INT_I2C2 63
+#define MXC_INT_HS_I2C 64
+#define MXC_INT_RESV65 65
+#define MXC_INT_RESV66 66
+#define MXC_INT_SIM_IPB 67
+#define MXC_INT_SIM_DAT 68
+#define MXC_INT_IIM 69
+#define MXC_INT_ATA 70
+#define MXC_INT_CCM1 71
+#define MXC_INT_CCM2 72
+#define MXC_INT_GPC1 73
+#define MXC_INT_GPC2 74
+#define MXC_INT_SRC 75
+#define MXC_INT_NM 76
+#define MXC_INT_PMU 77
+#define MXC_INT_CTI_IRQ 78
+#define MXC_INT_CTI1_TG0 79
+#define MXC_INT_CTI1_TG1 80
+#define MXC_INT_MCG_ERR 81
+#define MXC_INT_MCG_TMR 82
+#define MXC_INT_MCG_FUNC 83
+#define MXC_INT_GPU2_IRQ 84
+#define MXC_INT_GPU2_BUSY 85
+#define MXC_INT_RESV86 86
+#define MXC_INT_FEC 87
+#define MXC_INT_OWIRE 88
+#define MXC_INT_CTI1_TG2 89
+#define MXC_INT_SJC 90
+#define MXC_INT_SPDIF 91
+#define MXC_INT_TVE 92
+#define MXC_INT_FIRI 93
+#define MXC_INT_PWM2 94
+#define MXC_INT_SLIM_EXP 95
+#define MXC_INT_SSI3 96
+#define MXC_INT_EMI_BOOT 97
+#define MXC_INT_CTI1_TG3 98
+#define MXC_INT_SMC_RX 99
+#define MXC_INT_VPU_IDLE 100
+#define MXC_INT_EMI_NFC 101
+#define MXC_INT_GPU_IDLE 102
+
+/* gpio and gpio based interrupt handling */
+#define GPIO_DR 0x00
+#define GPIO_GDIR 0x04
+#define GPIO_PSR 0x08
+#define GPIO_ICR1 0x0C
+#define GPIO_ICR2 0x10
+#define GPIO_IMR 0x14
+#define GPIO_ISR 0x18
+#define GPIO_INT_LOW_LEV 0x0
+#define GPIO_INT_HIGH_LEV 0x1
+#define GPIO_INT_RISE_EDGE 0x2
+#define GPIO_INT_FALL_EDGE 0x3
+#define GPIO_INT_NONE 0x4
+
+#endif /* __ASM_ARCH_MXC_MX51_H__ */
diff --git a/arch/arm/plat-mxc/include/mach/mxc.h b/arch/arm/plat-mxc/include/mach/mxc.h
index 5fa2a07f4eaf..f1cbce461cac 100644
--- a/arch/arm/plat-mxc/include/mach/mxc.h
+++ b/arch/arm/plat-mxc/include/mach/mxc.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2004-2009 Freescale Semiconductor, Inc. All Rights Reserved.
* Copyright (C) 2008 Juergen Beisert (kernel@pengutronix.de)
*
* This program is free software; you can redistribute it and/or
@@ -26,9 +26,13 @@
#define MXC_CPU_MX1 1
#define MXC_CPU_MX21 21
+#define MXC_CPU_MX25 25
#define MXC_CPU_MX27 27
#define MXC_CPU_MX31 31
+#define MXC_CPU_MX32 32
#define MXC_CPU_MX35 35
+#define MXC_CPU_MX37 37
+#define MXC_CPU_MX51 51
#ifndef __ASSEMBLY__
extern unsigned int __mxc_cpu_type;
@@ -58,6 +62,18 @@ extern unsigned int __mxc_cpu_type;
# define cpu_is_mx21() (0)
#endif
+#ifdef CONFIG_ARCH_MX25
+# ifdef mxc_cpu_type
+# undef mxc_cpu_type
+# define mxc_cpu_type __mxc_cpu_type
+# else
+# define mxc_cpu_type MXC_CPU_MX25
+# endif
+# define cpu_is_mx25() (mxc_cpu_type == MXC_CPU_MX25)
+#else
+# define cpu_is_mx25() (0)
+#endif
+
#ifdef CONFIG_MACH_MX27
# ifdef mxc_cpu_type
# undef mxc_cpu_type
@@ -94,6 +110,558 @@ extern unsigned int __mxc_cpu_type;
# define cpu_is_mx35() (0)
#endif
+#ifdef CONFIG_ARCH_MX37
+# ifdef mxc_cpu_type
+# undef mxc_cpu_type
+# define mxc_cpu_type __mxc_cpu_type
+# else
+# define mxc_cpu_type MXC_CPU_MX37
+# endif
+# define cpu_is_mx37() (mxc_cpu_type == MXC_CPU_MX37)
+#else
+# define cpu_is_mx37() (0)
+#endif
+
+#ifdef CONFIG_ARCH_MX51
+# ifdef mxc_cpu_type
+# undef mxc_cpu_type
+# define mxc_cpu_type __mxc_cpu_type
+# else
+# define mxc_cpu_type MXC_CPU_MX51
+# endif
+# define cpu_is_mx51() (mxc_cpu_type == MXC_CPU_MX51)
+#else
+# define cpu_is_mx51() (0)
+#endif
+
+#define cpu_is_mx32() (0)
+
+/*
+ * Create inline functions to test for cpu revision
+ * Function name is cpu_is_<cpu name>_rev(rev)
+ *
+ * Returns:
+ * 0 - not the cpu queried
+ * 1 - cpu and revision match
+ * 2 - cpu matches, but cpu revision is greater than queried rev
+ * -1 - cpu matches, but cpu revision is less than queried rev
+ */
+#ifndef __ASSEMBLY__
+extern unsigned int system_rev;
+#define mxc_set_system_rev(part, rev) ({ \
+ system_rev = (part << 12) | rev; \
+})
+#define mxc_cpu() (system_rev >> 12)
+#define mxc_cpu_rev() (system_rev & 0xFF)
+#define mxc_cpu_rev_major() ((system_rev >> 4) & 0xF)
+#define mxc_cpu_rev_minor() (system_rev & 0xF)
+#define mxc_cpu_is_rev(rev) \
+ ((mxc_cpu_rev() == rev) ? 1 : ((mxc_cpu_rev() < rev) ? -1 : 2))
+#define cpu_rev(type) \
+static inline int type## _rev (int rev) \
+{ \
+ return (type() ? mxc_cpu_is_rev(rev) : 0); \
+}
+cpu_rev(cpu_is_mx21);
+cpu_rev(cpu_is_mx25);
+cpu_rev(cpu_is_mx27);
+cpu_rev(cpu_is_mx31);
+cpu_rev(cpu_is_mx35);
+cpu_rev(cpu_is_mx37);
+cpu_rev(cpu_is_mx51);
+
+
+#include <linux/types.h>
+
+/*!
+ * This structure is used to define the One wire platform data.
+ * It includes search rom accelerator.
+ */
+struct mxc_w1_config {
+ int search_rom_accelerator;
+};
+/*!
+ * This structure is used to define the SPI master controller's platform
+ * data. It includes the SPI bus number and the maximum number of
+ * slaves/chips it supports.
+ */
+struct mxc_spi_master {
+ /*!
+ * SPI Master's bus number.
+ */
+ unsigned int bus_num;
+ /*!
+ * SPI Master's maximum number of chip selects.
+ */
+ unsigned int maxchipselect;
+ /*!
+ * CSPI Hardware Version.
+ */
+ unsigned int spi_version;
+ /*!
+ * CSPI chipselect pin table.
+ * Workaround for ecspi chipselect pin may not keep correct level when
+ * idle.
+ */
+ void (*chipselect_active) (int cspi_mode, int status, int chipselect);
+ void (*chipselect_inactive) (int cspi_mode, int status, int chipselect);
+};
+
+struct mxc_ipu_config {
+ int rev;
+ struct clk *di_clk[2];
+};
+
+struct mxc_ir_platform_data {
+ int uart_ir_mux;
+ int ir_rx_invert;
+ int ir_tx_invert;
+ struct clk *uart_clk;
+};
+
+struct mxc_i2c_platform_data {
+ u32 i2c_clk;
+};
+
+/*
+ * This struct is to define the number of SSIs on a platform,
+ * DAM source port config, DAM external port config,
+ * regulator names, and other stuff audio needs.
+ */
+struct mxc_audio_platform_data {
+ int ssi_num;
+ int src_port;
+ int ext_port;
+
+ int intr_id_hp;
+ int ext_ram;
+ struct clk *ssi_clk[2];
+ char *regulator1;
+ char *regulator2;
+
+ int hp_irq;
+ int (*hp_status) (void);
+
+ char *vddio_reg;
+ char *vdda_reg;
+ char *vddd_reg;
+ int vddio; /* voltage of VDDIO (uv) */
+ int vdda; /* voltage of vdda (uv) */
+ int vddd; /* voltage of vddd (uv), 0 if not connected */
+ 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 mxc_spdif_platform_data {
+ int spdif_tx;
+ int spdif_rx;
+ int spdif_clk_44100;
+ int spdif_clk_48000;
+ int spdif_clkid;
+ struct clk *spdif_clk;
+ struct clk *spdif_core_clk;
+ struct clk *spdif_audio_clk;
+};
+
+struct mxc_asrc_platform_data {
+ struct clk *asrc_core_clk;
+ struct clk *asrc_audio_clk;
+ unsigned int channel_bits;
+};
+
+struct mxc_bt_platform_data {
+ char *bt_vdd;
+ char *bt_vdd_parent;
+ char *bt_vusb;
+ char *bt_vusb_parent;
+ void (*bt_reset) (void);
+};
+
+struct mxc_lightsensor_platform_data {
+ char *vdd_reg;
+ int rext;
+};
+
+struct mxc_fb_platform_data {
+ struct fb_videomode *mode;
+ char *mode_str;
+ u32 interface_pix_fmt;
+};
+
+struct mxc_lcd_platform_data {
+ char *io_reg;
+ char *core_reg;
+ char *analog_reg;
+ void (*reset) (void);
+};
+
+struct mxc_dvfs_platform_data {
+ /** Supply voltage regulator name string */
+ char *reg_id;
+ /* CPU clock name string */
+ char *clk1_id;
+ /* DVFS clock name string */
+ char *clk2_id;
+ /* GPC control reg address */
+ void __iomem *gpc_cntr_reg_addr;
+ /* GPC voltage counter reg address */
+ void __iomem *gpc_vcr_reg_addr;
+ /* CCM DVFS control reg address */
+ void __iomem *ccm_cdcr_reg_addr;
+ /* CCM ARM clock root reg address */
+ void __iomem *ccm_cacrr_reg_addr;
+ /* CCM divider handshake in-progree reg address */
+ void __iomem *ccm_cdhipr_reg_addr;
+ /* DVFS threshold reg address */
+ void __iomem *dvfs_thrs_reg_addr;
+ /* DVFS counters reg address */
+ void __iomem *dvfs_coun_reg_addr;
+ /* DVFS EMAC reg address */
+ void __iomem *dvfs_emac_reg_addr;
+ /* DVFS control reg address */
+ void __iomem *dvfs_cntr_reg_addr;
+ /* PREDIV mask */
+ u32 prediv_mask;
+ /* PREDIV offset */
+ int prediv_offset;
+ /* PREDIV value */
+ int prediv_val;
+ /* DIV3CK mask */
+ u32 div3ck_mask;
+ /* DIV3CK offset */
+ int div3ck_offset;
+ /* DIV3CK value */
+ int div3ck_val;
+ /* EMAC value */
+ int emac_val;
+ /* Frequency increase threshold. Increase frequency change request
+ will be sent if DVFS counter value will be more than this value */
+ int upthr_val;
+ /* Frequency decrease threshold. Decrease frequency change request
+ will be sent if DVFS counter value will be less than this value */
+ int dnthr_val;
+ /* Panic threshold. Panic frequency change request
+ will be sent if DVFS counter value will be more than this value */
+ int pncthr_val;
+ /* The amount of times the up threshold should be exceeded
+ before DVFS will trigger frequency increase request */
+ int upcnt_val;
+ /* The amount of times the down threshold should be exceeded
+ before DVFS will trigger frequency decrease request */
+ int dncnt_val;
+ /* Delay time in us */
+ int delay_time;
+ /* Number of woking points supported */
+ int num_wp;
+};
+
+struct mxc_tsc_platform_data {
+ char *vdd_reg;
+ int penup_threshold;
+ void (*active) (void);
+ void (*inactive) (void);
+};
+
+struct mxc_tvout_platform_data {
+ char *io_reg;
+ char *core_reg;
+ char *analog_reg;
+ u32 detect_line;
+};
+
+struct mxc_tvin_platform_data {
+ char *dvddio_reg;
+ char *dvdd_reg;
+ char *avdd_reg;
+ char *pvdd_reg;
+ void (*pwdn) (int pwdn);
+ void (*reset) (void);
+};
+
+/*! Platform data for the IDE drive structure. */
+struct mxc_ide_platform_data {
+ char *power_drive; /*!< The power pointer */
+ char *power_io; /*!< The power pointer */
+};
+
+struct mxc_camera_platform_data {
+ char *core_regulator;
+ char *io_regulator;
+ char *analog_regulator;
+ char *gpo_regulator;
+ u32 mclk;
+ u32 csi;
+};
+
+/*gpo1-3 is in fixed state by hardware design,
+ * only deal with reset pin and clock_enable pin
+ * only poll mode can be used to control the chip,
+ * interrupt mode is not supported by 3ds*/
+struct mxc_fm_platform_data {
+ char *reg_vio;
+ char *reg_vdd;
+ void (*gpio_get) (void);
+ void (*gpio_put) (void);
+ void (*reset) (void);
+ void (*clock_ctl) (int flag);
+ u8 sksnr; /*0,disable;1,most stop;0xf,fewest stop*/
+ u8 skcnt; /*0,disable;1,most stop;0xf,fewest stop*/
+ /*
+ 00 = 87.5-108 MHz (USA,Europe) (Default).
+ 01 = 76-108 MHz (Japan wide band).
+ 10 = 76-90 MHz (Japan).
+ 11 = Reserved.
+ */
+ u8 band;
+ /*
+ 00 = 200 kHz (USA, Australia) (default).
+ 01 = 100 kHz (Europe, Japan).
+ 10 = 50 kHz.
+ */
+ u8 space;
+ u8 seekth;
+};
+
+struct mxc_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 mxc_keyp_platform_data {
+ u16 *matrix;
+ void (*active) (void);
+ void (*inactive) (void);
+ char *vdd_reg;
+};
+
+struct mxc_unifi_platform_data {
+ void (*hardreset) (int pin_level);
+ void (*enable) (int en);
+ /* power parameters */
+ char *reg_gpo1;
+ char *reg_gpo2;
+ char *reg_1v5_ana_bb;
+ char *reg_vdd_vpa;
+ char *reg_1v5_dd;
+
+ int host_id;
+
+ void *priv;
+};
+
+struct mxc_gps_platform_data {
+ char *core_reg;
+ char *analog_reg;
+ struct regulator *gps_regu_core;
+ struct regulator *gps_regu_analog;
+};
+
+struct mxc_mlb_platform_data {
+ u32 buf_address;
+ u32 phy_address;
+ char *reg_nvcc;
+ char *mlb_clk;
+};
+
+struct flexcan_platform_data {
+ char *core_reg;
+ char *io_reg;
+ void (*xcvr_enable) (int id, int en);
+ void (*active) (int id);
+ void (*inactive) (int id);
+};
+
+struct mxc_srtc_platform_data {
+ u32 srtc_sec_mode_addr;
+};
+
+struct tve_platform_data {
+ char *dac_reg;
+ char *dig_reg;
+};
+
+/* The name that links the i.MX NAND Flash Controller driver to its devices. */
+
+#define IMX_NFC_DRIVER_NAME ("imx_nfc")
+
+/* Resource names for the i.MX NAND Flash Controller driver. */
+
+#define IMX_NFC_BUFFERS_ADDR_RES_NAME \
+ ("i.MX NAND Flash Controller Buffer")
+#define IMX_NFC_PRIMARY_REGS_ADDR_RES_NAME \
+ ("i.MX NAND Flash Controller Primary Registers")
+#define IMX_NFC_SECONDARY_REGS_ADDR_RES_NAME \
+ ("i.MX NAND Flash Controller Secondary Registers")
+#define IMX_NFC_INTERRUPT_RES_NAME \
+ ("i.MX NAND Flash Controller Interrupt")
+
+/**
+ * struct imx_nfc_platform_data - i.MX NFC driver platform data.
+ *
+ * This structure communicates information to the i.MX NFC driver that can't be
+ * expressed as resources.
+ *
+ * @nfc_major_version: The "major version" of the NFC hardware.
+ * @nfc_minor_version: The "minor version" of the NFC hardware.
+ * @force_ce: If true, this flag causes the driver to assert the
+ * hardware chip enable signal for the currently selected
+ * chip as long as the MTD NAND Flash HAL has the chip
+ * selected (not just when an I/O transaction is in
+ * progress).
+ * @target_cycle_in_ns: The target read and write cycle period, in nanoseconds.
+ * NAND Flash part data sheets give minimum times for read
+ * and write cycles in nanoseconds (usually tRC and tWC,
+ * respectively). Set this value to the maximum of these
+ * two parameters. The driver will set the NFC clock as
+ * close as possible without violating this value.
+ * @clock_name: The name of the clock used by the NAND Flash controller.
+ * @init: A pointer to a function the driver must call so the
+ * platform can prepare for this device to operate. This
+ * pointer may be NULL.
+ * @exit: A pointer to a function the driver must call so the
+ * platform clean up after this device stops operating.
+ * This pointer may be NULL.
+ * @set_page_size: A pointer to a function the driver can call to set the
+ * page size. This pointer may be NULL.
+ *
+ * For some i.MX SoC's, the NFC gets information about the
+ * page size from signals driven by a system register
+ * outside the NFC. The address and format of this external
+ * register varies across SoC's. In other SoC's, the NFC
+ * still receives this signal, but it is overridden by a
+ * page size register in the NFC itself.
+ *
+ * For SoC's where the page size *must* be set in an
+ * external register, the driver must rely on a platform-
+ * specific function, and this member must point to it.
+ *
+ * For SoC's where the NFC has its own page size register,
+ * the driver will set that register itself and ignore the
+ * external signals. In this case, there's no need for the
+ * platform-specific function and this member must be NULL.
+ *
+ * This function accepts the page size in bytes (MTD calls
+ * this the "writesize") discovered by the NAND Flash MTD
+ * base driver (e.g., 512, 2048, 4096). This size refers
+ * specifically to the the data bytes in the page, *not*
+ * including out-of-band bytes. The return value is zero if
+ * the operation succeeded. The driver does *not* view a
+ * non-zero value as an error code - only an indication of
+ * failure. The driver will decide for itself what error
+ * code to return to its caller.
+ * @interleave: Indicates that the driver should "interleave" the NAND
+ * Flash chips it finds. If true, the driver will aggregate
+ * the chips "horizontally" such that MTD will see a single
+ * chip with a potentially very large page size. This can
+ * improve write performance for some applications.
+ * @partitions: An optional pointer to an array of partitions. If this
+ * is NULL, the driver will create a single MTD that
+ * represents the entire medium.
+ * @partition_count: The number of elements in the partition array.
+ */
+
+struct imx_nfc_platform_data {
+ unsigned int nfc_major_version;
+ unsigned int nfc_minor_version;
+ int force_ce;
+ unsigned int target_cycle_in_ns;
+ char *clock_name;
+ int (*init)(void);
+ void (*exit)(void);
+ int (*set_page_size)(unsigned int data_size_in_bytes);
+ int interleave;
+ struct mtd_partition *partitions;
+ unsigned int partition_count;
+};
+
+extern void mxc_wd_reset(void);
+unsigned long board_get_ckih_rate(void);
+
+int mxc_snoop_set_config(u32 num, unsigned long base, int size);
+int mxc_snoop_get_status(u32 num, u32 * statl, u32 * stath);
+
+struct platform_device;
+void mxc_pg_enable(struct platform_device *pdev);
+void mxc_pg_disable(struct platform_device *pdev);
+
+struct mxc_unifi_platform_data *get_unifi_plat_data(void);
+
+struct mxc_sim_platform_data {
+ unsigned int clk_rate;
+ char *clock_sim;
+ char *power_sim;
+ int (*init)(struct platform_device *pdev);
+ void (*exit)(void);
+ unsigned int detect; /* 1 have detect pin, 0 not */
+};
+
+#endif /* __ASSEMBLY__ */
+
+#define MUX_IO_P 29
+#define MUX_IO_I 24
+#define IOMUX_TO_GPIO(pin) ((((unsigned int)pin >> MUX_IO_P) * 32) + ((pin >> MUX_IO_I) & ((1 << (MUX_IO_P - MUX_IO_I)) -1)))
+#define IOMUX_TO_IRQ(pin) (MXC_GPIO_IRQ_START + IOMUX_TO_GPIO(pin))
+
+/* DMA driver defines */
+#define MXC_IDE_DMA_WATERMARK 32 /* DMA watermark level in bytes */
+#define MXC_IDE_DMA_BD_NR (512/3/4) /* Number of BDs per channel */
+
+#ifndef IS_MEM_DEVICE_NONSHARED
+/* all peripherals on MXC so far are below 0x80000000 but leave L2CC alone */
+#define IS_MEM_DEVICE_NONSHARED(x) ((x) < 0x80000000 && (x) != L2CC_BASE_ADDR)
+#endif
+/*!
+ * DPTC GP and LP ID
+ */
+#define DPTC_GP_ID 0
+#define DPTC_LP_ID 1
+
+#ifndef __ASSEMBLY__
+
+struct cpu_wp {
+ u32 pll_reg;
+ u32 pll_rate;
+ u32 cpu_rate;
+ u32 pdr0_reg;
+ u32 pdf;
+ u32 mfi;
+ u32 mfd;
+ u32 mfn;
+ u32 cpu_voltage;
+ u32 cpu_podf;
+};
+
+#ifndef CONFIG_ARCH_MX51
+struct cpu_wp *get_cpu_wp(int *wp);
+#endif
+
+enum mxc_cpu_pwr_mode {
+ WAIT_CLOCKED, /* wfi only */
+ WAIT_UNCLOCKED, /* WAIT */
+ WAIT_UNCLOCKED_POWER_OFF, /* WAIT + SRPG */
+ STOP_POWER_ON, /* just STOP */
+ STOP_POWER_OFF, /* STOP + SRPG */
+};
+
+void mxc_cpu_lp_set(enum mxc_cpu_pwr_mode mode);
+int tzic_enable_wake(int is_idle);
+void gpio_activate_audio_ports(void);
+void gpio_inactivate_audio_ports(void);
+void gpio_activate_bt_audio_port(void);
+void gpio_inactivate_bt_audio_port(void);
+void gpio_activate_esai_ports(void);
+void gpio_deactivate_esai_ports(void);
+
+#endif
+
#if defined(CONFIG_ARCH_MX3) || defined(CONFIG_ARCH_MX2)
#define CSCR_U(n) (IO_ADDRESS(WEIM_BASE_ADDR) + n * 0x10)
#define CSCR_L(n) (IO_ADDRESS(WEIM_BASE_ADDR) + n * 0x10 + 0x4)
diff --git a/arch/arm/plat-mxc/include/mach/mxc_dptc.h b/arch/arm/plat-mxc/include/mach/mxc_dptc.h
new file mode 100644
index 000000000000..b42fc36af3e1
--- /dev/null
+++ b/arch/arm/plat-mxc/include/mach/mxc_dptc.h
@@ -0,0 +1,111 @@
+/*
+ * Copyright 2008 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
+ */
+
+/*!
+ * @defgroup DPTC Dynamic Process and Temperatur Compensation (DPTC) Driver
+ */
+
+/*!
+ * @file arch-mxc/mxc_dptc.h
+ *
+ * @brief This file contains the DPTC configuration structure definition.
+ *
+ *
+ * @ingroup DPTC
+ */
+
+#ifndef __ASM_ARCH_MXC_DPTC_H__
+#define __ASM_ARCH_MXC_DPTC_H__
+
+#ifdef __KERNEL__
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/workqueue.h>
+#include <linux/device.h>
+
+#define DPTC_WP_SUPPORTED 17
+#define DPTC_GP_WP_SUPPORTED 7
+#define DPTC_LP_WP_SUPPORTED 9
+
+struct dptc_wp {
+ u32 dcvr0;
+ u32 dcvr1;
+ u32 dcvr2;
+ u32 dcvr3;
+ u32 voltage;
+};
+
+/*!
+ * This structure is used to define the dptc controller's platform
+ * data. It includes the regulator name string and DPTC clock name string.
+ */
+struct mxc_dptc_data {
+ /** Regulator name string */
+ char *reg_id;
+ /* DPTC clock name string */
+ char *clk_id;
+ /* Control reg address */
+ unsigned int dptccr_reg_addr;
+ /* Comparator value reg 0 address */
+ unsigned int dcvr0_reg_addr;
+ /* GPC control reg address */
+ unsigned int gpc_cntr_reg_addr;
+ /* DPTC interrupt status bit */
+ unsigned int dptccr;
+ /* The number of DPTC working points */
+ unsigned int dptc_wp_supported;
+ /* Maximum value of DPTC clock rate */
+ unsigned long clk_max_val;
+ /* DPTC working points */
+ struct dptc_wp *dptc_wp_allfreq;
+ /* DPTC enable bit */
+ u32 dptc_enable_bit;
+ /* DPTC ADU bit */
+ int gpc_adu;
+ /* VAI mask */
+ u32 vai_mask;
+ /* VAI offset */
+ int vai_offset;
+ /* Mask DPTC interrupt */
+ u32 irq_mask;
+ /* DPTC no voltage change request bit */
+ u32 dptc_nvcr_bit;
+ /* ARM interrrupt bit */
+ u32 gpc_irq_bit;
+ /* dptc init config */
+ u32 init_config;
+ /* dptc enable config */
+ u32 enable_config;
+ /* dptc counting range mask */
+ u32 dcr_mask;
+};
+
+/*!
+ * This function is called to put the DPTC in a low power state.
+ *
+ * @param id The DPTC device id. DPTC_GP_ID is for DPTC GP;
+ * DPTC_LP_ID is for DPTC LP
+ */
+void dptc_suspend(int id);
+/*!
+ * This function is called to resume the DPTC from a low power state.
+ *
+ * @param id The DPTC device id. DPTC_GP_ID is for DPTC GP;
+ * DPTC_LP_ID is for DPTC LP
+ */
+void dptc_resume(int id);
+
+#endif /* __KERNEL__ */
+
+#endif /* __ASM_ARCH_MXC_DPTC_H__ */
diff --git a/arch/arm/plat-mxc/include/mach/mxc_dvfs.h b/arch/arm/plat-mxc/include/mach/mxc_dvfs.h
new file mode 100644
index 000000000000..99ddb077d9d1
--- /dev/null
+++ b/arch/arm/plat-mxc/include/mach/mxc_dvfs.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2009 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
+ */
+
+/*!
+ * @defgroup DVFS Dynamic Voltage and Frequency Scaling (DVFS) Driver
+ */
+
+/*!
+ * @file arch-mxc/mxc_dvfs.h
+ *
+ * @brief This file contains the DVFS configuration structure definition.
+ *
+ *
+ * @ingroup DVFS
+ */
+
+#ifndef __ASM_ARCH_MXC_DVFS_H__
+#define __ASM_ARCH_MXC_DVFS_H__
+
+#ifdef __KERNEL__
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/workqueue.h>
+#include <linux/device.h>
+
+/*
+ * DVFS structure
+ */
+struct dvfs_wp {
+ int upthr;
+ int downthr;
+ int panicthr;
+ int upcnt;
+ int downcnt;
+ int emac;
+};
+
+#endif /* __KERNEL__ */
+
+#endif /* __ASM_ARCH_MXC_DVFS_H__ */
diff --git a/arch/arm/plat-mxc/include/mach/mxc_edid.h b/arch/arm/plat-mxc/include/mach/mxc_edid.h
new file mode 100644
index 000000000000..aac49ad93ec5
--- /dev/null
+++ b/arch/arm/plat-mxc/include/mach/mxc_edid.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2009 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
+ */
+
+/*!
+ * @defgroup Framebuffer Framebuffer Driver for SDC and ADC.
+ */
+
+/*!
+ * @file mxc_edid.h
+ *
+ * @brief MXC EDID tools
+ *
+ * @ingroup Framebuffer
+ */
+
+#ifndef MXC_EDID_H
+#define MXC_EDID_H
+
+int read_edid(struct i2c_adapter *adp,
+ struct fb_var_screeninfo *einfo,
+ int *dvi);
+
+#endif
diff --git a/arch/arm/plat-mxc/include/mach/mxc_gpc.h b/arch/arm/plat-mxc/include/mach/mxc_gpc.h
new file mode 100644
index 000000000000..d3b3ae2d1b13
--- /dev/null
+++ b/arch/arm/plat-mxc/include/mach/mxc_gpc.h
@@ -0,0 +1,74 @@
+
+/*
+ * Copyright 2004-2007 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
+ */
+
+/*!
+ * @defgroup LPMD Low-Level Power Management Driver
+ */
+
+/*!
+ * @file arch-mxc/mxc_gpc.h
+ *
+ * @brief This file contains the chip level configuration details and
+ * public API declarations for GPC module
+ *
+ * @ingroup LPMD
+ */
+
+#ifndef __ASM_ARCH_MXC_GPC_H__
+#define __ASM_ARCH_MXC_GPC_H__
+
+/* AP Power Gating modules */
+typedef enum {
+ POWER_GATING_MODULE_AP_EMBEDDED_MEM_DEEPSLEEP,
+ POWER_GATING_MODULE_DISPLAY_BUFFER,
+ POWER_GATING_MODULE_EMI_DEEPSLEEP,
+ POWER_GATING_MODULE_IPU_STOP,
+ POWER_GATING_MODULE_L2_MEM_STOP,
+ POWER_GATING_MODULE_ARM_PLATFORM_STOP,
+} mxc_pm_ap_power_gating_modules_t;
+
+/* AP Power Gating pull-down config of modules */
+typedef enum {
+ POWER_GATING_PULL_DOWN_DISPLAY_BUFFER,
+ POWER_GATING_PULL_DOWN_EMI,
+ POWER_GATING_PULL_DOWN_IPU,
+ POWER_GATING_PULL_DOWN_L2_MEM,
+ POWER_GATING_PULL_DOWN_ARMPLATFORM,
+} mxc_pm_ap_power_gating_pulldown_t;
+
+/*!
+ * This function enables/disables the AP power gating by writing the APPCR
+ * register of the GPC module.
+ *
+ * @param enable Enable/Disable module power down
+ * 0 - disable; 1 - enable
+ * @param modules The desired module to be power gated
+ *
+ */
+void mxc_gpc_powergate_module(int enable,
+ mxc_pm_ap_power_gating_modules_t module);
+
+/*!
+ * This function enables/disables the AP power gating pull down selection of a
+ * module by writing the APPCR register of the GPC module.
+ *
+ * @param enable Enable/Disable module pull down
+ * 0 - disable; 1 - enable
+ * @param modules The desired module to be pulled down
+ *
+ */
+void mxc_gpc_powergate_pulldown(int enable,
+ mxc_pm_ap_power_gating_pulldown_t pulldown);
+
+#endif
diff --git a/arch/arm/plat-mxc/include/mach/mxc_pm.h b/arch/arm/plat-mxc/include/mach/mxc_pm.h
new file mode 100644
index 000000000000..b4d389a6611e
--- /dev/null
+++ b/arch/arm/plat-mxc/include/mach/mxc_pm.h
@@ -0,0 +1,252 @@
+
+/*
+ * Copyright 2004-2009 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
+ */
+
+/*!
+ * @defgroup LPMD Low-Level Power Management Driver
+ */
+
+/*!
+ * @file arch-mxc/mxc_pm.h
+ *
+ * @brief This file contains the chip level configuration details and
+ * public API declarations for CRM_AP module
+ *
+ * @ingroup LPMD
+ */
+
+#ifndef __ASM_ARCH_MXC_PM_H__
+#define __ASM_ARCH_MXC_PM_H__
+
+#define WAIT_MODE 111
+#define DOZE_MODE 112
+#define STOP_MODE 113
+#define DSM_MODE 114
+/*
+ * MXC91231 Break-Point Frequency below which is low frequency and
+ * above which is high frequency
+ */
+#define BREAKPT_FREQ ((long)(400000000))
+
+#define GATE_STOP_WAIT 9
+#define GATE_STOP 10
+
+/*
+ * Used for MHz conversion
+ */
+#define MEGA_HERTZ 1000000
+
+/*
+ * If invalid frequency value other than the following
+ * CORE_133 - ARM desired to run @133MHz, LoV (1.2V)
+ * CORE_266 - ARM desired to run @266MHz, LoV (1.2V)
+ * CORE_399 - ARM desired to run @399MHz, LoV (1.2V)
+ * CORE_532 - ARM desired to run @133MHz, HiV (1.6V)
+ * are passed then this error is returned,
+ */
+#define ERR_FREQ_INVALID 1
+
+/*
+ * For MXC91231 Pass1, Integer DVFS greater than 133MHz is not allowed
+ * due to the hardware issue
+ */
+#define INTEGER_DVFS_NOT_ALLOW 1
+
+/*
+ * If PLL freq is less than desired ARM frequency during Integer
+ * DVFS, then return this error
+ */
+#define PLL_LESS_ARM_ERR 2
+
+/*
+ * Frequency change within the same-lo voltage is not approved.
+ * Inorder to do Integer DFS, move to the high voltage range and
+ * then set LFDF and move to the low voltage range
+ */
+#define INT_DFS_LOW_NOT_ALLOW 3
+
+/*
+ * If the desired AHB or IPG exceeds 133MHz or 66.5MHz respectively,
+ * then return this error
+ */
+#define AHB_IPG_EXCEED_LIMIT 4
+
+/*
+ * If the desired ARM frequency is too low to get by PLL scaling
+ * and the mxc_pm_pllscale API is called, return this error:
+ */
+#define PLL_DVFS_FREQ_TOO_LOW 5
+
+/*
+ * Invalid frequencies requested
+ */
+#define MXC_PM_INVALID_PARAM 6
+
+/*
+ * If AHB and/or IPG frequencies are greater than maximum allowed
+ */
+#define FREQ_OUT_OF_RANGE 2
+
+/*
+ * If AHB and/or IPG frequencies are other than 100 or 50Mhz
+ */
+#define BUS_FREQ_INVALID 2
+
+/*
+ * If MAX_PDF is greater than max value (8) then return this error
+ */
+#define AHB_MAX_DIV_ERR 3
+
+/*
+ * If IPG_PDF is greater than max value (2) then return this error
+ */
+#define IPG_MAX_DIV_ERR 4
+
+/*
+ * If ARM freq is out of range i.e., less than 133 or greater than
+ * 399 then return this error
+ */
+#define INVALID_ARM_FREQ 5
+
+/*
+ * This file includes all platform APIs. Some of the APIs are not
+ * appicable to some platforms. So, this error is used to indicate
+ * that a particular API is not available
+ */
+#define MXC_PM_API_NOT_SUPPORTED 6
+
+/*
+ * Error when frequency scaling is attempted while switch between MPLL and
+ * TPLL is in progress on MXC91321
+ */
+#define ERR_DFSP_SWITCH 2
+
+/*!
+ * Additional define for stop mode
+ */
+#define PM_SUSPEND_STOP ((__force suspend_state_t) 2)
+
+/*!
+ * CKOH pins configuration
+ */
+#define CKOH_AP_SEL 1
+#define CKOH_AHB_SEL 2
+#define CKOH_IP_SEL 3
+
+/*!
+ * Defines for Stop and DSM mode acknowledgements
+ */
+#define MXC_PM_LOWPWR_ACK_SDMA 0x01
+#define MXC_PM_LOWPWR_ACK_IPU 0x02
+#define MXC_PM_LOWPWR_ACK_MAX 0x04
+#define MXC_PM_LOWPWR_ACK_MQSPI 0x08
+#define MXC_PM_LOWPWR_ACK_USB 0x10
+#define MXC_PM_LOWPWR_ACK_RTIC 0x20
+
+/*
+ * PMIC configuration
+ */
+#define MXC_PMIC_1_2_VOLT 0xC
+#define MXC_PMIC_1_6_VOLT 0x1C
+#define MXC_PMIC_1_0_VOLT 0x4
+#if defined(CONFIG_ARCH_MXC91321) || defined(CONFIG_ARCH_MXC91231)
+#define MXC_PMIC_DVS_SPEED 0x1
+#else
+#define MXC_PMIC_DVS_SPEED 0x3
+#endif
+
+/*!
+ * Implementing Level 1 CRM Gate Control. Level 2 gate control
+ * is provided at module level using LPMD registers
+ *
+ * @param group The desired clock gate control register bits.
+ * Possible values are 0 through 6
+ * @param opt The desired option requesting clock to run during stop
+ * and wait modes or just during the stop mode. Possible
+ * values are GATE_STOP_WAIT and GATE_STOP.
+ *
+ */
+void mxc_pm_clockgate(int group, int opt);
+
+/*!
+ * Implementing steps required to transition to low-power modes
+ *
+ * @param mode The desired low-power mode. Possible values are,
+ * WAIT_MODE, STOP_MODE or DSM_MODE
+ *
+ */
+void mxc_pm_lowpower(int mode);
+
+/*!
+ * Enables acknowledgement from module when entering stop or DSM mode.
+ *
+ * @param ack The desired module acknowledgement to enable.
+ *
+ */
+void mxc_pm_lp_ack_enable(int ack);
+
+/*!
+ * Disables acknowledgement from module when entering stop or DSM mode.
+ *
+ * @param ack The desired module acknowledgement to disable.
+ *
+ */
+void mxc_pm_lp_ack_disable(int ack);
+
+/*!
+ * Implementing steps required to set Integer Scaling
+ *
+ * @param armfreq The desired ARM frequency. AHB and IP
+ * frequency are changed depending on ARM
+ * frequency and the divider values.
+ * @param ahbfreq The desired AHB frequency
+ * @param ipfreq The desired IP frequency
+ *
+ * @return Returns 0 on success or
+ * Returns -PLL_LESS_ARM_ERR if pllfreq is less than
+ * desired core freq
+ */
+int mxc_pm_intscale(long armfreq, long ahbfreq, long ipfreq);
+
+/*!
+ * To calculate MFI, MFN, MFD values. Using this the output frequency
+ * whose value is calculated using,
+ * 2 * REF_FREQ * (MF / PDF), where
+ * REF_FREQ is 26 Mhz
+ * MF = MFI + (MFN + MFD)
+ * PDF is assumed to be 1
+ *
+ * @param armfreq The desired ARM frequency
+ * @param ahbfreq The desired AHB frequency
+ * @param ipfreq The desired IP frequency
+ *
+ * @return Returns 0 on success or
+ * Returns -1 on error
+ */
+int mxc_pm_pllscale(long armfreq, long ahbfreq, long ipfreq);
+
+/*!
+ * To change AP core frequency and/or voltage suitably
+ *
+ * @param armfreq The desired ARM frequency
+ * @param ahbfreq The desired AHB frequency
+ * @param ipfreq The desired IP frequency
+ *
+ * @return Returns -ERR_FREQ_INVALID on failure
+ * Returns 0 on success
+ */
+int mxc_pm_dvfs(unsigned long armfreq, long ahbfreq, long ipfreq);
+
+extern void mxc_pm_arch_entry(void *entry, u32 size);
+
+#endif
diff --git a/arch/arm/plat-mxc/include/mach/mxc_scc.h b/arch/arm/plat-mxc/include/mach/mxc_scc.h
new file mode 100644
index 000000000000..d23f6c3e9913
--- /dev/null
+++ b/arch/arm/plat-mxc/include/mach/mxc_scc.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2004-2009 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
+ */
+
+/*!
+ * @file arch-mxc/mxc_scc.h
+ *
+ * @brief This is intended to be the file which contains all of code or changes
+ * needed to port the driver.
+ *
+ * @ingroup MXCSCC
+ */
+
+#ifndef __ASM_ARCH_MXC_SCC_H__
+#define __ASM_ARCH_MXC_SCC_H__
+
+#include <mach/hardware.h>
+
+/*!
+ * Expected to come from platform header files.
+ * This symbol must be the address of the SCC
+ */
+#define SCC_BASE SCC_BASE_ADDR
+
+/*!
+ * This must be the interrupt line number of the SCM interrupt.
+ */
+#define INT_SCC_SCM MXC_INT_SCC_SCM
+
+/*!
+ * if #USE_SMN_INTERRUPT is defined, this must be the interrupt line number of
+ * the SMN interrupt.
+ */
+#define INT_SCC_SMN MXC_INT_SCC_SMN
+
+#endif
diff --git a/arch/arm/plat-mxc/include/mach/mxc_timer.h b/arch/arm/plat-mxc/include/mach/mxc_timer.h
new file mode 100644
index 000000000000..59fe2dceeb07
--- /dev/null
+++ b/arch/arm/plat-mxc/include/mach/mxc_timer.h
@@ -0,0 +1,157 @@
+/*
+ * mxc_timer.h
+ *
+ * Copyright (C) 2008 Juergen Beisert (kernel@pengutronix.de)
+ *
+ * Platform independent (i.MX1, i.MX2, i.MX3) definition for timer handling.
+ *
+ * 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 __PLAT_MXC_TIMER_H
+#define __PLAT_MXC_TIMER_H
+
+#include <linux/clk.h>
+#include <mach/hardware.h>
+
+#ifdef CONFIG_ARCH_IMX
+#define TIMER_BASE IO_ADDRESS(TIM1_BASE_ADDR)
+#define TIMER_INTERRUPT TIM1_INT
+
+#define TCTL_VAL TCTL_CLK_PCLK1
+#define TCTL_IRQEN (1<<4)
+#define TCTL_FRR (1<<8)
+#define TCTL_CLK_PCLK1 (1<<1)
+#define TCTL_CLK_PCLK1_4 (2<<1)
+#define TCTL_CLK_TIN (3<<1)
+#define TCTL_CLK_32 (4<<1)
+
+#define MXC_TCTL 0x00
+#define MXC_TPRER 0x04
+#define MXC_TCMP 0x08
+#define MXC_TCR 0x0c
+#define MXC_TCN 0x10
+#define MXC_TSTAT 0x14
+#define TSTAT_CAPT (1<<1)
+#define TSTAT_COMP (1<<0)
+
+static inline void gpt_irq_disable(void)
+{
+ unsigned int tmp;
+
+ tmp = __raw_readl(TIMER_BASE + MXC_TCTL);
+ __raw_writel(tmp & ~TCTL_IRQEN, TIMER_BASE + MXC_TCTL);
+}
+
+static inline void gpt_irq_enable(void)
+{
+ __raw_writel(__raw_readl(TIMER_BASE + MXC_TCTL) | TCTL_IRQEN,
+ TIMER_BASE + MXC_TCTL);
+}
+
+static void gpt_irq_acknowledge(void)
+{
+ __raw_writel(0, TIMER_BASE + MXC_TSTAT);
+}
+
+#elif defined(CONFIG_ARCH_MX2)
+#define TIMER_BASE IO_ADDRESS(GPT1_BASE_ADDR)
+#define TIMER_INTERRUPT MXC_INT_GPT1
+
+#define MXC_TCTL 0x00
+#define TCTL_VAL TCTL_CLK_PCLK1
+#define TCTL_CLK_PCLK1 (1<<1)
+#define TCTL_CLK_PCLK1_4 (2<<1)
+#define TCTL_IRQEN (1<<4)
+#define TCTL_FRR (1<<8)
+#define MXC_TPRER 0x04
+#define MXC_TCMP 0x08
+#define MXC_TCR 0x0c
+#define MXC_TCN 0x10
+#define MXC_TSTAT 0x14
+#define TSTAT_CAPT (1<<1)
+#define TSTAT_COMP (1<<0)
+
+static inline void gpt_irq_disable(void)
+{
+ unsigned int tmp;
+
+ tmp = __raw_readl(TIMER_BASE + MXC_TCTL);
+ __raw_writel(tmp & ~TCTL_IRQEN, TIMER_BASE + MXC_TCTL);
+}
+
+static inline void gpt_irq_enable(void)
+{
+ __raw_writel(__raw_readl(TIMER_BASE + MXC_TCTL) | TCTL_IRQEN,
+ TIMER_BASE + MXC_TCTL);
+}
+
+static void gpt_irq_acknowledge(void)
+{
+ __raw_writel(TSTAT_CAPT | TSTAT_COMP, TIMER_BASE + MXC_TSTAT);
+}
+
+#else
+#define TIMER_BASE IO_ADDRESS(GPT1_BASE_ADDR)
+#define TIMER_INTERRUPT MXC_INT_GPT
+
+#define MXC_TCTL 0x00
+#define TCTL_VAL (TCTL_CLK_HIGH_FREQ | TCTL_WAITEN)
+#define TCTL_CLK_IPG (1<<6)
+#define TCTL_CLK_HIGH_FREQ (2<<6)
+#define TCTL_FRR (1<<9)
+#define TCTL_WAITEN (1<<3)
+
+#define MXC_TPRER 0x04
+#define MXC_TSTAT 0x08
+#define TSTAT_OF1 (1<<0)
+#define TSTAT_OF2 (1<<1)
+#define TSTAT_OF3 (1<<2)
+#define TSTAT_IF1 (1<<3)
+#define TSTAT_IF2 (1<<4)
+#define TSTAT_ROV (1<<5)
+#define MXC_IR 0x0c
+#define MXC_TCMP 0x10
+#define MXC_TCMP2 0x14
+#define MXC_TCMP3 0x18
+#define MXC_TCR 0x1c
+#define MXC_TCN 0x24
+
+static inline void gpt_irq_disable(void)
+{
+ __raw_writel(0, TIMER_BASE + MXC_IR);
+}
+
+static inline void gpt_irq_enable(void)
+{
+ __raw_writel(1<<0, TIMER_BASE + MXC_IR);
+}
+
+static inline void gpt_irq_acknowledge(void)
+{
+ __raw_writel(TSTAT_OF1, TIMER_BASE + MXC_TSTAT);
+}
+#endif /* CONFIG_ARCH_MX3 */
+
+#define TCTL_SWR (1<<15)
+#define TCTL_CC (1<<10)
+#define TCTL_OM (1<<9)
+#define TCTL_CAP_RIS (1<<6)
+#define TCTL_CAP_FAL (2<<6)
+#define TCTL_CAP_RIS_FAL (3<<6)
+#define TCTL_CAP_ENA (1<<5)
+#define TCTL_TEN (1<<0)
+
+#endif
diff --git a/arch/arm/plat-mxc/include/mach/mxc_uart.h b/arch/arm/plat-mxc/include/mach/mxc_uart.h
new file mode 100644
index 000000000000..d1db8023d724
--- /dev/null
+++ b/arch/arm/plat-mxc/include/mach/mxc_uart.h
@@ -0,0 +1,275 @@
+/*
+ * Copyright 2004-2009 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
+ */
+
+/*!
+ * @defgroup UART Universal Asynchronous Receiver Transmitter (UART) Driver
+ */
+
+/*!
+ * @file arch-mxc/mxc_uart.h
+ *
+ * @brief This file contains the UART configuration structure definition.
+ *
+ *
+ * @ingroup UART
+ */
+
+#ifndef __ASM_ARCH_MXC_UART_H__
+#define __ASM_ARCH_MXC_UART_H__
+
+#ifdef __KERNEL__
+
+#include <linux/serial_core.h>
+#include <mach/dma.h>
+
+/*
+ * The modes of the UART ports
+ */
+#define MODE_DTE 0
+#define MODE_DCE 1
+/*
+ * Is the UART configured to be a IR port
+ */
+#define IRDA 0
+#define NO_IRDA 1
+
+/*!
+ * This structure is used to store the the physical and virtual
+ * addresses of the UART DMA receive buffer.
+ */
+typedef struct {
+ /*!
+ * DMA Receive buffer virtual address
+ */
+ char *rx_buf;
+ /*!
+ * DMA Receive buffer physical address
+ */
+ dma_addr_t rx_handle;
+} mxc_uart_rxdmamap;
+
+/*!
+ * This structure is a way for the low level driver to define their own
+ * \b uart_port structure. This structure includes the core \b uart_port
+ * structure that is provided by Linux as an element and has other
+ * elements that are specifically required by this low-level driver.
+ */
+typedef struct {
+ /*!
+ * The port structure holds all the information about the UART
+ * port like base address, and so on.
+ */
+ struct uart_port port;
+ /*!
+ * Flag to determine if the interrupts are muxed.
+ */
+ int ints_muxed;
+ /*!
+ * Array that holds the receive and master interrupt numbers
+ * when the interrupts are not muxed.
+ */
+ int irqs[2];
+ /*!
+ * Flag to determine the DTE/DCE mode.
+ */
+ int mode;
+ /*!
+ * Flag to hold the IR mode of the port.
+ */
+ int ir_mode;
+ /*!
+ * Flag to enable/disable the UART port.
+ */
+ int enabled;
+ /*!
+ * Flag to indicate if we wish to use hardware-driven hardware
+ * flow control.
+ */
+ int hardware_flow;
+ /*!
+ * Holds the threshold value at which the CTS line is deasserted in
+ * case we use hardware-driven hardware flow control.
+ */
+ unsigned int cts_threshold;
+ /*!
+ * Flag to enable/disable DMA data transfer.
+ */
+ int dma_enabled;
+ /*!
+ * Holds the DMA receive buffer size.
+ */
+ int dma_rxbuf_size;
+ /*!
+ * DMA Receive buffers information
+ */
+ mxc_uart_rxdmamap *rx_dmamap;
+ /*!
+ * DMA RX buffer id
+ */
+ int dma_rxbuf_id;
+ /*!
+ * DMA Transmit buffer virtual address
+ */
+ char *tx_buf;
+ /*!
+ * DMA Transmit buffer physical address
+ */
+ dma_addr_t tx_handle;
+ /*!
+ * Holds the RxFIFO threshold value.
+ */
+ unsigned int rx_threshold;
+ /*!
+ * Holds the TxFIFO threshold value.
+ */
+ unsigned int tx_threshold;
+ /*!
+ * Information whether this is a shared UART
+ */
+ unsigned int shared;
+ /*!
+ * Clock id for UART clock
+ */
+ struct clk *clk;
+ /*!
+ * Information whether RXDMUXSEL must be set or not for IR port
+ */
+ int rxd_mux;
+ int ir_tx_inv;
+ int ir_rx_inv;
+ /*!
+ * DMA ID for transmit
+ */
+ mxc_dma_device_t dma_tx_id;
+ /*!
+ * DMA ID for receive
+ */
+ mxc_dma_device_t dma_rx_id;
+} uart_mxc_port;
+
+/* Address offsets of the UART registers */
+#define MXC_UARTURXD 0x000 /* Receive reg */
+#define MXC_UARTUTXD 0x040 /* Transmitter reg */
+#define MXC_UARTUCR1 0x080 /* Control reg 1 */
+#define MXC_UARTUCR2 0x084 /* Control reg 2 */
+#define MXC_UARTUCR3 0x088 /* Control reg 3 */
+#define MXC_UARTUCR4 0x08C /* Control reg 4 */
+#define MXC_UARTUFCR 0x090 /* FIFO control reg */
+#define MXC_UARTUSR1 0x094 /* Status reg 1 */
+#define MXC_UARTUSR2 0x098 /* Status reg 2 */
+#define MXC_UARTUESC 0x09C /* Escape character reg */
+#define MXC_UARTUTIM 0x0A0 /* Escape timer reg */
+#define MXC_UARTUBIR 0x0A4 /* BRM incremental reg */
+#define MXC_UARTUBMR 0x0A8 /* BRM modulator reg */
+#define MXC_UARTUBRC 0x0AC /* Baud rate count reg */
+#define MXC_UARTONEMS 0x0B0 /* One millisecond reg */
+#define MXC_UARTUTS 0x0B4 /* Test reg */
+
+/* Bit definations of UCR1 */
+#define MXC_UARTUCR1_ADEN 0x8000
+#define MXC_UARTUCR1_ADBR 0x4000
+#define MXC_UARTUCR1_TRDYEN 0x2000
+#define MXC_UARTUCR1_IDEN 0x1000
+#define MXC_UARTUCR1_RRDYEN 0x0200
+#define MXC_UARTUCR1_RXDMAEN 0x0100
+#define MXC_UARTUCR1_IREN 0x0080
+#define MXC_UARTUCR1_TXMPTYEN 0x0040
+#define MXC_UARTUCR1_RTSDEN 0x0020
+#define MXC_UARTUCR1_SNDBRK 0x0010
+#define MXC_UARTUCR1_TXDMAEN 0x0008
+#define MXC_UARTUCR1_ATDMAEN 0x0004
+#define MXC_UARTUCR1_DOZE 0x0002
+#define MXC_UARTUCR1_UARTEN 0x0001
+
+/* Bit definations of UCR2 */
+#define MXC_UARTUCR2_ESCI 0x8000
+#define MXC_UARTUCR2_IRTS 0x4000
+#define MXC_UARTUCR2_CTSC 0x2000
+#define MXC_UARTUCR2_CTS 0x1000
+#define MXC_UARTUCR2_PREN 0x0100
+#define MXC_UARTUCR2_PROE 0x0080
+#define MXC_UARTUCR2_STPB 0x0040
+#define MXC_UARTUCR2_WS 0x0020
+#define MXC_UARTUCR2_RTSEN 0x0010
+#define MXC_UARTUCR2_ATEN 0x0008
+#define MXC_UARTUCR2_TXEN 0x0004
+#define MXC_UARTUCR2_RXEN 0x0002
+#define MXC_UARTUCR2_SRST 0x0001
+
+/* Bit definations of UCR3 */
+#define MXC_UARTUCR3_DTREN 0x2000
+#define MXC_UARTUCR3_PARERREN 0x1000
+#define MXC_UARTUCR3_FRAERREN 0x0800
+#define MXC_UARTUCR3_DSR 0x0400
+#define MXC_UARTUCR3_DCD 0x0200
+#define MXC_UARTUCR3_RI 0x0100
+#define MXC_UARTUCR3_RXDSEN 0x0040
+#define MXC_UARTUCR3_AWAKEN 0x0010
+#define MXC_UARTUCR3_DTRDEN 0x0008
+#define MXC_UARTUCR3_RXDMUXSEL 0x0004
+#define MXC_UARTUCR3_INVT 0x0002
+
+/* Bit definations of UCR4 */
+#define MXC_UARTUCR4_CTSTL_OFFSET 10
+#define MXC_UARTUCR4_CTSTL_MASK (0x3F << 10)
+#define MXC_UARTUCR4_INVR 0x0200
+#define MXC_UARTUCR4_ENIRI 0x0100
+#define MXC_UARTUCR4_REF16 0x0040
+#define MXC_UARTUCR4_IRSC 0x0020
+#define MXC_UARTUCR4_TCEN 0x0008
+#define MXC_UARTUCR4_OREN 0x0002
+#define MXC_UARTUCR4_DREN 0x0001
+
+/* Bit definations of UFCR */
+#define MXC_UARTUFCR_RFDIV 0x0200 /* Ref freq div is set to 2 */
+#define MXC_UARTUFCR_RFDIV_OFFSET 7
+#define MXC_UARTUFCR_RFDIV_MASK (0x7 << 7)
+#define MXC_UARTUFCR_TXTL_OFFSET 10
+#define MXC_UARTUFCR_DCEDTE 0x0040
+
+/* Bit definations of URXD */
+#define MXC_UARTURXD_ERR 0x4000
+#define MXC_UARTURXD_OVRRUN 0x2000
+#define MXC_UARTURXD_FRMERR 0x1000
+#define MXC_UARTURXD_BRK 0x0800
+#define MXC_UARTURXD_PRERR 0x0400
+
+/* Bit definations of USR1 */
+#define MXC_UARTUSR1_PARITYERR 0x8000
+#define MXC_UARTUSR1_RTSS 0x4000
+#define MXC_UARTUSR1_TRDY 0x2000
+#define MXC_UARTUSR1_RTSD 0x1000
+#define MXC_UARTUSR1_FRAMERR 0x0400
+#define MXC_UARTUSR1_RRDY 0x0200
+#define MXC_UARTUSR1_AGTIM 0x0100
+#define MXC_UARTUSR1_DTRD 0x0080
+#define MXC_UARTUSR1_AWAKE 0x0010
+
+/* Bit definations of USR2 */
+#define MXC_UARTUSR2_TXFE 0x4000
+#define MXC_UARTUSR2_IDLE 0x1000
+#define MXC_UARTUSR2_RIDELT 0x0400
+#define MXC_UARTUSR2_RIIN 0x0200
+#define MXC_UARTUSR2_DCDDELT 0x0040
+#define MXC_UARTUSR2_DCDIN 0x0020
+#define MXC_UARTUSR2_TXDC 0x0008
+#define MXC_UARTUSR2_ORE 0x0002
+#define MXC_UARTUSR2_RDR 0x0001
+#define MXC_UARTUSR2_BRCD 0x0004
+
+/* Bit definations of UTS */
+#define MXC_UARTUTS_LOOP 0x1000
+
+#endif /* __KERNEL__ */
+
+#endif /* __ASM_ARCH_MXC_UART_H__ */
diff --git a/arch/arm/plat-mxc/include/mach/mxc_vpu.h b/arch/arm/plat-mxc/include/mach/mxc_vpu.h
new file mode 100644
index 000000000000..8a42c7de5634
--- /dev/null
+++ b/arch/arm/plat-mxc/include/mach/mxc_vpu.h
@@ -0,0 +1,94 @@
+/*
+ * Copyright 2004-2009 Freescale Semiconductor, Inc. All Rights Reserved.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU Lesser General
+ * Public License. You may obtain a copy of the GNU Lesser General
+ * Public License Version 2.1 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/lgpl-license.html
+ * http://www.gnu.org/copyleft/lgpl.html
+ */
+
+/*!
+ * @defgroup VPU Video Processor Unit Driver
+ */
+
+/*!
+ * @file arch-mxc/mxc_vpu.h
+ *
+ * @brief VPU system initialization and file operation definition
+ *
+ * @ingroup VPU
+ */
+
+#ifndef __ASM_ARCH_MXC_VPU_H__
+#define __ASM_ARCH_MXC_VPU_H__
+
+#include <linux/fs.h>
+
+struct vpu_mem_desc {
+ u32 size;
+ dma_addr_t phy_addr;
+ u32 cpu_addr; /* cpu address to free the dma mem */
+ u32 virt_uaddr; /* virtual user space address */
+};
+
+#define VPU_IOC_MAGIC 'V'
+
+#define VPU_IOC_PHYMEM_ALLOC _IO(VPU_IOC_MAGIC, 0)
+#define VPU_IOC_PHYMEM_FREE _IO(VPU_IOC_MAGIC, 1)
+#define VPU_IOC_WAIT4INT _IO(VPU_IOC_MAGIC, 2)
+#define VPU_IOC_PHYMEM_DUMP _IO(VPU_IOC_MAGIC, 3)
+#define VPU_IOC_REG_DUMP _IO(VPU_IOC_MAGIC, 4)
+#define VPU_IOC_VL2CC_FLUSH _IO(VPU_IOC_MAGIC, 5)
+#define VPU_IOC_IRAM_SETTING _IO(VPU_IOC_MAGIC, 6)
+#define VPU_IOC_CLKGATE_SETTING _IO(VPU_IOC_MAGIC, 7)
+#define VPU_IOC_GET_WORK_ADDR _IO(VPU_IOC_MAGIC, 8)
+#define VPU_IOC_GET_PIC_PARA_ADDR _IO(VPU_IOC_MAGIC, 9)
+#define VPU_IOC_GET_USER_DATA_ADDR _IO(VPU_IOC_MAGIC, 10)
+#define VPU_IOC_SYS_SW_RESET _IO(VPU_IOC_MAGIC, 11)
+#define VPU_IOC_GET_SHARE_MEM _IO(VPU_IOC_MAGIC, 12)
+
+#define BIT_CODE_RUN 0x000
+#define BIT_CODE_DOWN 0x004
+#define BIT_INT_CLEAR 0x00C
+#define BIT_INT_STATUS 0x010
+
+#define BIT_WORK_CTRL_BUF_BASE 0x100
+#define BIT_WORK_CTRL_BUF_REG(i) (BIT_WORK_CTRL_BUF_BASE + i * 4)
+#define BIT_CODE_BUF_ADDR BIT_WORK_CTRL_BUF_REG(0)
+#define BIT_WORK_BUF_ADDR BIT_WORK_CTRL_BUF_REG(1)
+#define BIT_PARA_BUF_ADDR BIT_WORK_CTRL_BUF_REG(2)
+#define BIT_BIT_STREAM_CTRL BIT_WORK_CTRL_BUF_REG(3)
+#define BIT_FRAME_MEM_CTRL BIT_WORK_CTRL_BUF_REG(4)
+#define BIT_BIT_STREAM_PARAM BIT_WORK_CTRL_BUF_REG(5)
+
+#define BIT_RESET_CTRL 0x11C
+
+/* i could be 0, 1, 2, 3 */
+#define BIT_RD_PTR_BASE 0x120
+#define BIT_RD_PTR_REG(i) (BIT_RD_PTR_BASE + i * 8)
+#define BIT_WR_PTR_REG(i) (BIT_RD_PTR_BASE + i * 8 + 4)
+
+/* i could be 0, 1, 2, 3 */
+#define BIT_FRM_DIS_FLG_BASE (cpu_is_mx51() ? 0x150 : 0x140)
+#define BIT_FRM_DIS_FLG_REG(i) (BIT_FRM_DIS_FLG_BASE + i * 4)
+
+#define BIT_BUSY_FLAG 0x160
+#define BIT_RUN_COMMAND 0x164
+#define BIT_INT_ENABLE 0x170
+
+#define BITVAL_PIC_RUN 8
+
+#define VPU_SLEEP_REG_VALUE 10
+#define VPU_WAKE_REG_VALUE 11
+
+int vl2cc_init(u32 vl2cc_hw_base);
+void vl2cc_enable(void);
+void vl2cc_flush(void);
+void vl2cc_disable(void);
+void vl2cc_cleanup(void);
+
+#endif
diff --git a/arch/arm/plat-mxc/include/mach/pcmcia.h b/arch/arm/plat-mxc/include/mach/pcmcia.h
new file mode 100644
index 000000000000..c50302bbbac5
--- /dev/null
+++ b/arch/arm/plat-mxc/include/mach/pcmcia.h
@@ -0,0 +1,218 @@
+/*
+ * Copyright 2005-2009 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 __ASM_ARCH_MXC_PCMCIA_H__
+#define __ASM_ARCH_MXC_PCMCIA_H__
+
+#include <mach/hardware.h>
+
+#define WINDOW_SIZE 0x1000000 /* The size of a window: 16M */
+#define PCMCIA_WINDOWS 5 /* How many windows / socket */
+#define SOCKET_NO 1 /* How many sockets */
+
+#define ATTRIBUTE_MEMORY_WINDOW 0
+#define IO_WINDOW 1
+#define COMMON_MEMORY_WINDOW 2
+
+/*
+ * PCMCIA socket
+ */
+#define PCMCIAPrtSp WINDOW_SIZE /* PCMCIA window size */
+#define PCMCIASp (4*PCMCIAPrtSp) /* PCMCIA Space [byte] */
+#define PCMCIAIOSp PCMCIAPrtSp /* PCMCIA I/O Space [byte] */
+#define PCMCIAAttrSp PCMCIAPrtSp /* PCMCIA Attribute Space [byte] */
+#define PCMCIAMemSp PCMCIAPrtSp /* PCMCIA Memory Space [byte] */
+
+#define PCMCIA0Sp PCMCIASp /* PCMCIA 0 Space [byte] */
+#define PCMCIA0IOSp PCMCIAIOSp /* PCMCIA 0 I/O Space [byte] */
+#define PCMCIA0AttrSp PCMCIAAttrSp /* PCMCIA 0 Attribute Space [byte] */
+#define PCMCIA0MemSp PCMCIAMemSp /* PCMCIA 0 Memory Space [byte] */
+
+#define _PCMCIA(Nb) /* PCMCIA [0..1] */ \
+ (PCMCIA_MEM_BASE_ADDR + (Nb) * PCMCIASp)
+
+#define _PCMCIAAttr(Nb) _PCMCIA (Nb) /* PCMCIA I/O [0..1] */
+
+#define _PCMCIAIO(Nb) /* PCMCIA Attribute [0..1] */ \
+ (_PCMCIA (Nb) + (IO_WINDOW) * PCMCIAPrtSp)
+#define _PCMCIAMem(Nb) /* PCMCIA Memory [0..1] */ \
+ (_PCMCIA (Nb) + (COMMON_MEMORY_WINDOW) * PCMCIAPrtSp)
+
+#define _PCMCIA0 _PCMCIA (0) /* PCMCIA 0 */
+#define _PCMCIA0IO _PCMCIAIO (0) /* PCMCIA 0 I/O */
+#define _PCMCIA0Attr _PCMCIAAttr (0) /* PCMCIA 0 Attribute */
+#define _PCMCIA0Mem _PCMCIAMem (0) /* PCMCIA 0 Memory */
+
+/*
+ * Module: PCMCIA, Addr Range: 0xB8004000 - 0xB8004FFF, Size: 4 Kbyte
+ */
+#define PCMCIA_BASE_ADDR (PCMCIA_CTL_BASE_ADDR) /* PCMCIA Base Address */
+#define PCMCIA_IO_ADDR(x) (* (volatile u32 *)PCMCIA_IO_ADDRESS(x))
+
+#define _reg_PCMCIA_PIPR PCMCIA_IO_ADDR(PCMCIA_BASE_ADDR + 0x00) /* PCMCIA input pins register */
+#define _reg_PCMCIA_PSCR PCMCIA_IO_ADDR(PCMCIA_BASE_ADDR + 0x04) /* PCMCIA Status Changed Register */
+#define _reg_PCMCIA_PER PCMCIA_IO_ADDR(PCMCIA_BASE_ADDR + 0x08) /* PCMCIA Enable Register */
+
+/* win: 0-4 */
+#define _reg_PCMCIA_PBR(win) PCMCIA_IO_ADDR(PCMCIA_BASE_ADDR + 0x0C + 4 * (win)) /* PCMCIA Base Register x */
+#define _reg_PCMCIA_POR(win) PCMCIA_IO_ADDR(PCMCIA_BASE_ADDR + 0x28 + 4 * (win)) /* PCMCIA Option Register x */
+#define _reg_PCMCIA_POFR(win) PCMCIA_IO_ADDR(PCMCIA_BASE_ADDR + 0x44 + 4 * (win)) /* PCMCIA Offset Register x */
+
+#define _reg_PCMCIA_PGCR PCMCIA_IO_ADDR(PCMCIA_BASE_ADDR + 0x60) /* PCMCIA General Control Register */
+#define _reg_PCMCIA_PGSR PCMCIA_IO_ADDR(PCMCIA_BASE_ADDR + 0x64) /* PCMCIA General Status Register */
+
+/* PCMCIA_PIPR - PCMCIA Input Pins Register - fields */
+#define PCMCIA_PIPR_POWERON (1 << 8) /* card indicates "power on" */
+#define PCMCIA_PIPR_RDY (1 << 7) /* card is ready */
+#define PCMCIA_PIPR_BVD2 (1 << 6) /* battery voltage 2/SPKR in */
+#define PCMCIA_PIPR_BVD1 (1 << 5) /* battery voltage 1/STSCHG */
+#define PCMCIA_PIPR_CD (3 << 3) /* card detect 1 and 2 */
+#define PCMCIA_PIPR_WP (1 << 2) /* write protect switch enabled */
+#define PCMCIA_PIPR_VS (3 << 0) /* voltage sense bits */
+#define PCMCIA_PIPR_VS_5V (1 << 0) /* 5v */
+
+/* PCMCIA_PSCR - PCMCIA Status Change Register - fields */
+#define PCMCIA_PSCR_POWC (1 << 11) /* */
+#define PCMCIA_PSCR_RDYR (1 << 10) /* */
+#define PCMCIA_PSCR_RDYF (1 << 9) /* */
+#define PCMCIA_PSCR_RDYH (1 << 8) /* */
+#define PCMCIA_PSCR_RDYL (1 << 7) /* */
+#define PCMCIA_PSCR_BVDC2 (1 << 6) /* */
+#define PCMCIA_PSCR_BVDC1 (1 << 5) /* */
+#define PCMCIA_PSCR_CDC2 (1 << 4) /* */
+#define PCMCIA_PSCR_CDC1 (1 << 3) /* */
+#define PCMCIA_PSCR_WPC (1 << 2) /* */
+#define PCMCIA_PSCR_VSC2 (1 << 1) /* */
+#define PCMCIA_PSCR_VSC1 (1 << 0) /* */
+
+/* PCMCIA_PER - PCMCIA Enable Register - fields */
+#define PCMCIA_PER_ERRINTEN (1 << 12) /* error interrupt enable */
+#define PCMCIA_PER_POWERONEN (1 << 11) /* power on interrupt enable */
+#define PCMCIA_PER_RDYRE (1 << 10) /* RDY/nIREQ pin rising edge */
+#define PCMCIA_PER_RDYFE (1 << 9) /* RDY/nIREQ pin falling edge */
+#define PCMCIA_PER_RDYHE (1 << 8) /* RDY/nIREQ pin high */
+#define PCMCIA_PER_RDYLE (1 << 7) /* RDY/nIREQ pin low */
+#define PCMCIA_PER_BVDE2 (1 << 6) /* battery voltage 2/SPKR in */
+#define PCMCIA_PER_BVDE1 (1 << 5) /* battery voltage 1/STSCHG */
+#define PCMCIA_PER_CDE2 (1 << 4) /* card detect 2 */
+#define PCMCIA_PER_CDE1 (1 << 3) /* card detect 1 */
+#define PCMCIA_PER_WPE (1 << 2) /* write protect */
+#define PCMCIA_PER_VSE2 (1 << 1) /* voltage sense 2 */
+#define PCMCIA_PER_VSE1 (1 << 0) /* voltage sense 1 */
+
+/* PCMCIA_POR[0-4] - PCMCIA Option Registers 0-4 - fields */
+#define PCMCIA_POR_PV (1 << 29) /* set iff bank is valid */
+#define PCMCIA_POR_WPEN (1 << 28) /* write protect (WP) input signal is enabled */
+#define PCMCIA_POR_WP (1 << 27) /* write protected */
+
+#define PCMCIA_POR_PRS_SHIFT (25)
+#define PCMCIA_POR_PRS(x) (((x) & 0x3) << PCMCIA_POR_PRS_SHIFT )
+#define PCMCIA_POR_PRS_MASK PCMCIA_POR_PRS(3) /* PCMCIA region select */
+#define PCMCIA_POR_PRS_COMMON (0) /* values of POR_PRS field */
+#define PCMCIA_POR_PRS_TRUE_IDE (1)
+#define PCMCIA_POR_PRS_ATTRIBUTE (2)
+#define PCMCIA_POR_PRS_IO (3)
+
+#define PCMCIA_POR_PPS_8 (1 << 24) /* PCMCIA Port size = 8bits */
+#define PCMCIA_POR_PPS_16 (0 << 24) /* PCMCIA Port size = 16bits */
+
+#define PCMCIA_POR_PSL_SHIFT (17) /* strobe length */
+#define PCMCIA_POR_PSL(x) (((x) & 0x7F) << PCMCIA_POR_PSL_SHIFT)
+#define PCMCIA_POR_PSL_MASK PCMCIA_POR_PSL(0x7f)
+
+#define PCMCIA_POR_PSST_SHIFT (11) /* strobe setup time */
+#define PCMCIA_POR_PSST(x) (((x) & 0x3F) << PCMCIA_POR_PSST_SHIFT)
+#define PCMCIA_POR_PSST_MASK PCMCIA_POR_PSST(0x3f)
+
+#define PCMCIA_POR_PSHT_SHIFT (5) /* strobe hold time */
+#define PCMCIA_POR_PSHT(x) (((x) & 0x3F) << PCMCIA_POR_PSHT_SHIFT)
+#define PCMCIA_POR_PSHT_MASK PCMCIA_POR_PSHT(0x3f)
+
+#define PCMCIA_POR_BSIZE_SHIFT (0) /* bank size */
+#define PCMCIA_POR_BSIZE(x) (((x) & 0x1F) << PCMCIA_POR_BSIZE_SHIFT)
+#define PCMCIA_POR_BSIZE_MASK PCMCIA_POR_BSIZE(0x1F)
+
+/* some handy BSIZE values */
+#define POR_BSIZE_1 PCMCIA_POR_BSIZE(0x00)
+#define POR_BSIZE_2 PCMCIA_POR_BSIZE(0x01)
+#define POR_BSIZE_4 PCMCIA_POR_BSIZE(0x03)
+#define POR_BSIZE_8 PCMCIA_POR_BSIZE(0x02)
+#define POR_BSIZE_16 PCMCIA_POR_BSIZE(0x06)
+#define POR_BSIZE_32 PCMCIA_POR_BSIZE(0x07)
+#define POR_BSIZE_64 PCMCIA_POR_BSIZE(0x05)
+#define POR_BSIZE_128 PCMCIA_POR_BSIZE(0x04)
+#define POR_BSIZE_256 PCMCIA_POR_BSIZE(0x0C)
+#define POR_BSIZE_512 PCMCIA_POR_BSIZE(0x0D)
+#define POR_BSIZE_1K PCMCIA_POR_BSIZE(0x0F)
+#define POR_BSIZE_2K PCMCIA_POR_BSIZE(0x0E)
+
+#define POR_BSIZE_4K PCMCIA_POR_BSIZE(0x0A)
+#define POR_BSIZE_8K PCMCIA_POR_BSIZE(0x0B)
+#define POR_BSIZE_16K PCMCIA_POR_BSIZE(0x09)
+#define POR_BSIZE_32K PCMCIA_POR_BSIZE(0x08)
+#define POR_BSIZE_64K PCMCIA_POR_BSIZE(0x18)
+#define POR_BSIZE_128K PCMCIA_POR_BSIZE(0x19)
+#define POR_BSIZE_256K PCMCIA_POR_BSIZE(0x1B)
+#define POR_BSIZE_512K PCMCIA_POR_BSIZE(0x1A)
+#define POR_BSIZE_1M PCMCIA_POR_BSIZE(0x1E)
+#define POR_BSIZE_2M PCMCIA_POR_BSIZE(0x1F)
+#define POR_BSIZE_4M PCMCIA_POR_BSIZE(0x1D)
+#define POR_BSIZE_8M PCMCIA_POR_BSIZE(0x1C)
+#define POR_BSIZE_16M PCMCIA_POR_BSIZE(0x14)
+#define POR_BSIZE_32M PCMCIA_POR_BSIZE(0x15)
+#define POR_BSIZE_64M PCMCIA_POR_BSIZE(0x17)
+
+/* Window size */
+#define POR_1 0x1
+#define POR_2 0x2
+#define POR_4 0x4
+#define POR_8 0x8
+#define POR_16 0x10
+#define POR_32 0x20
+#define POR_64 0x40
+#define POR_128 0x80
+#define POR_256 0x100
+#define POR_512 0x200
+
+#define POR_1K 0x400
+#define POR_2K 0x800
+#define POR_4K 0x1000
+#define POR_8K 0x2000
+#define POR_16K 0x4000
+#define POR_32K 0x8000
+#define POR_64K 0x10000
+#define POR_128K 0x20000
+#define POR_256K 0x40000
+#define POR_512K 0x80000
+
+#define POR_1M 0x100000
+#define POR_2M 0x200000
+#define POR_4M 0x400000
+#define POR_8M 0x800000
+#define POR_16M 0x1000000
+#define POR_32M 0x2000000
+#define POR_64M 0x4000000
+
+/* PCMCIA_PGCR - PCMCIA General Control Register - fields */
+#define PCMCIA_PGCR_LPMEN (1 << 3) /* Low power Mode Enable */
+#define PCMCIA_PGCR_SPKREN (1 << 2) /* SPKROUT routing enable */
+#define PCMCIA_PGCR_POE (1 << 1) /* Controller out enable */
+#define PCMCIA_PGCR_RESET (1 << 0) /* Card reset */
+
+/* PCMCIA_PGSR - PCMCIA General Status Register - fields */
+#define PCMCIA_PGSR_NWINE (1 << 4) /* No Window error */
+#define PCMCIA_PGSR_LPE (1 << 3) /* Low Power error */
+#define PCMCIA_PGSR_SE (1 << 2) /* Size error */
+#define PCMCIA_PGSR_CDE (1 << 1) /* Card Detect error */
+#define PCMCIA_PGSR_WPE (1 << 0) /* Write Protect error */
+
+#endif /* __ASM_ARCH_MXC_PCMCIA_H__ */
diff --git a/arch/arm/plat-mxc/include/mach/pmic_audio.h b/arch/arm/plat-mxc/include/mach/pmic_audio.h
new file mode 100644
index 000000000000..8ec3d2c642e4
--- /dev/null
+++ b/arch/arm/plat-mxc/include/mach/pmic_audio.h
@@ -0,0 +1,2315 @@
+/*
+ * Copyright 2004-2009 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 __ASM_ARCH_MXC_PMIC_AUDIO_H__
+#define __ASM_ARCH_MXC_PMIC_AUDIO_H__
+
+/*!
+ * @defgroup PMIC_AUDIO PMIC Audio Driver
+ * @ingroup PMIC_DRVRS
+ */
+
+/*!
+ * @file arch-mxc/pmic_audio.h
+ * @brief External definitions for the PMIC Audio Client driver.
+ *
+ * The PMIC Audio driver and this API were developed to support the
+ * audio playback, recording, and mixing capabilities of the power
+ * management ICs that are available from Freescale Semiconductor, Inc.
+ *
+ * The following table shows which audio-related capabilities are supported
+ * by each power management IC:
+ *
+ * @ingroup PMIC_AUDIO
+ */
+
+#include <linux/pmic_status.h>
+#include <linux/pmic_external.h>
+
+/***************************************************************************
+ * TYPEDEFS AND ENUMERATIONS *
+ ***************************************************************************/
+
+/*!
+ * @name General Setup and Audio Device Access Typedefs and Enumerations
+ * Typedefs and enumerations that are used for initial access to the
+ * PMIC Audio hardware.
+ */
+/*@{*/
+
+/*!
+ * @typedef PMIC_AUDIO_HANDLE
+ * @brief Define typedef for a handle to the PMIC Audio hardware.
+ *
+ * Define a "handle" that is returned when the PMIC Audio hardware
+ * is opened. This handle grants exclusive access to the PMIC Audio
+ * hardware and must be used in all subsequent function calls. When access
+ * to the PMIC Audio hardware is no longer required, then a close
+ * operation must be done with this handle. The handle is no longer valid
+ * if the close operation was successful.
+ */
+typedef long *PMIC_AUDIO_HANDLE;
+
+/*!
+ * @enum PMIC_AUDIO_EVENTS
+ * @brief Identify the audio events that have been detected and should be
+ * handled.
+ *
+ * This enumeration defines all of the possible PMIC Audio events. Multiple
+ * events may be selected when defining a mask and multiple events may be
+ * signalled together.
+ *
+ * Note that the MICROPHONE_DETECT and MICROPHONE_REMOVED events may also be
+ * used to signal the operation of a serial or parallel microphone switch
+ * when used with a combined headset+microphone device. In that case the
+ * HEADSET_DETECT state must also be checked to determine if it's only the
+ * microphone switch being operated or whether the microphone has truly been
+ * inserted/removed (along with the headset).
+ */
+typedef enum {
+ HEADSET_DETECTED = 1, /*!< Detected headset insertion. */
+ HEADSET_STEREO = 2, /*!< Detected stereo headset device. */
+ HEADSET_MONO = 4, /*!< Detected mono headset device. */
+ HEADSET_THERMAL_SHUTDOWN = 8, /*!< Detected output amplifier
+ shutdown due to thermal
+ limits . */
+ HEADSET_SHORT_CIRCUIT = 16, /*!< Detected output amplifier
+ short circuit condition
+ . */
+ HEADSET_REMOVED = 32, /*!< Detected headset removal. */
+ MICROPHONE_DETECTED = 64, /*!< Detected microphone insertion. */
+ MICROPHONE_REMOVED = 128, /*!< Detected microphone removal. */
+ PTT_BUTTON_PRESS = 256, /*!< Detected PTT button down
+ . */
+ PTT_BUTTON_RANGE = 512, /*!< Detected PTT button within
+ voltage range
+ . */
+ PTT_SHORT_OR_INVALID = 1024 /*!< Detected PTT button outside
+ of voltage range or invalid
+ device . */
+} PMIC_AUDIO_EVENTS;
+
+/*!
+ * @typedef PMIC_AUDIO_CALLBACK
+ * @brief Typedef for PMIC Audio event notification callback function.
+ *
+ * Define a typedef for the PMIC Audio event notification callback
+ * function. The signalled events are passed to the function as the first
+ * argument. The callback function should then process whatever events it
+ * can and then return the set of unhandled events (if any).
+ */
+typedef PMIC_AUDIO_EVENTS(*PMIC_AUDIO_CALLBACK) (const PMIC_AUDIO_EVENTS event);
+
+typedef struct {
+ int hs_state;
+ int event_type;
+} PMIC_HS_STATE;
+
+/*!
+ * @enum PMIC_AUDIO_SOURCE
+ * @brief Select an audio signal processing component.
+ *
+ * This enumeration defines all of the possible PMIC audio signal handling
+ * components which can be acquired by calling pmic_audio_open().
+ *
+ * Note that the EXTERNAL_STEREO_IN selection is used to simply gain access
+ * to the stereo input pins. The stereo input signal can then be routed
+ * directly to the output amplifiers. In this case, no signal processing is
+ * done by either the Voice CODEC or the Stereo DAC.
+ */
+typedef enum {
+ STEREO_DAC, /*!< Open connection to Stereo DAC. */
+ VOICE_CODEC, /*!< Open connection to Voice CODEC. */
+ EXTERNAL_STEREO_IN /*!< Open connection to external stereo inputs. */
+} PMIC_AUDIO_SOURCE;
+
+/*@}*/
+
+/*!
+ * @name Data Bus Setup and Configuration Typedefs and Enumerations
+ * Typedefs and enumerations that are used to define and configure
+ * the data bus protocol in order to communicate with the Stereo DAC
+ * or the Voice CODEC.
+ */
+/*@{*/
+
+/*!
+ * @enum PMIC_AUDIO_DATA_BUS
+ * @brief Select the data bus used to transfer data between the host and
+ * Voice CODEC and/or the Stereo DAC.
+ *
+ * This enumeration defines all of the possible PMIC audio data buses that
+ * can be used to transfer data between the host and the Voice CODEC and/or
+ * the Stereo DAC on the PMIC.
+ *
+ * Note that the same data bus may be used to transfer audio data to/from
+ * the Voice CODEC and the Stereo DAC. However, in this case, the data bus
+ * must be configured for network mode with different timeslots assigned to
+ * the Voice CODEC and the Stereo DAC. Also, the sampling rates must be
+ * identical for both the Voice CODEC and the Stereo DAC in order to avoid
+ * a data bus timing conflict and audio signal distortion.
+ */
+typedef enum {
+ AUDIO_DATA_BUS_1, /*!< Use data bus 1 for audio data. */
+ AUDIO_DATA_BUS_2 /*!< Use data bus 2 for audio data. */
+} PMIC_AUDIO_DATA_BUS;
+
+/*!
+ * @enum PMIC_AUDIO_BUS_PROTOCOL
+ * @brief Select the data bus protocol to be used.
+ *
+ * This enumeration defines all of the possible PMIC audio data bus protocols
+ * that may be selected.
+ */
+typedef enum {
+ NORMAL_MSB_JUSTIFIED_MODE, /*!< Transmit and receive audio data
+ in normal MSB-justified mode. */
+ NETWORK_MODE, /*!< Transmit and receive audio data
+ in network mode. */
+ I2S_MODE, /*!< Transmit and receive audio data
+ in I2S mode. */
+ SPD_IF_MODE /*!< Transmit and receive audio data
+ in SPD/IF mode . */
+} PMIC_AUDIO_BUS_PROTOCOL;
+
+/*!
+ * @enum PMIC_AUDIO_BUS_MODE
+ * @brief Select the data bus mode to be used.
+ *
+ * This enumeration defines all of the possible PMIC audio data bus modes
+ * that may be selected. When configured in BUS_MASTER_MODE, the PMIC is
+ * responsible for supplying the data bus clock signals. Alternatively,
+ * when configured in BUS_SLAVE_MODE, the PMIC will use the data bus clock
+ * signals that are supplied by the bus master.
+ */
+typedef enum {
+ BUS_MASTER_MODE = 0, /*!< Operate as bus master. */
+ BUS_SLAVE_MODE = 1 /*!< Operate as bus slave. */
+} PMIC_AUDIO_BUS_MODE;
+
+/*!
+ * @enum PMIC_AUDIO_CLOCK_IN_SOURCE
+ * @brief Select the clock signal source when in bus master mode.
+ *
+ * This enumeration defines all of the possible PMIC audio clock signal
+ * sources that may be selected. One of these clock signal sources must
+ * be selected in order to use either the Voice CODEC or the Stereo DAC.
+ *
+ * When configured in BUS_MASTER_MODE, the PMIC's onboard PLL circuits
+ * will also be driven by the selected clock input signal.
+ */
+typedef enum {
+ CLOCK_IN_DEFAULT, /*!< Just use default (power-up) clock input. */
+ CLOCK_IN_CLIA, /*!< Use the CLIA clock source (Stereo DAC
+ default) . */
+ CLOCK_IN_CLIB, /*!< Use the CLIB clock source (Voice CODEC
+ default) . */
+ CLOCK_IN_CLKIN, /*!< Use the CLKIN clock source
+ . */
+ CLOCK_IN_MCLK, /*!< Disable the internal PLL and use the MCLK
+ clock source (Stereo DAC only)
+ . */
+ CLOCK_IN_FSYNC, /*!< Internal PLL input from external framesync
+ (Stereo DAC only) . */
+ CLOCK_IN_BITCLK /*!< Internal PLL input from external bitclock
+ (Stereo DAC only) */
+} PMIC_AUDIO_CLOCK_IN_SOURCE;
+
+/*!
+ * @enum PMIC_AUDIO_CLOCK_INVERT
+ * @brief Select whether to invert the frame sync or bit clock signals.
+ *
+ * This enumeration enables or disables the inversion of the incoming
+ * frame sync or bit clock signals.
+ */
+typedef enum {
+ NO_INVERT = 0, /*!< Do not invert the clock signals. */
+ INVERT_BITCLOCK = 1, /*!< Invert the BCLK input signal. */
+ INVERT_FRAMESYNC = 2 /*!< Invert the FSYNC input signal. */
+} PMIC_AUDIO_CLOCK_INVERT;
+
+/*!
+ * @enum PMIC_AUDIO_NUMSLOTS
+ * @brief Select whether to invert the frame sync or bit clock signals.
+ *
+ * This enumeration defines all of the possible number of timeslots that may
+ * be selected when the PMIC is configured as the data bus master. One of these
+ * options must be selected if the Stereo DAC is to provide the data bus
+ * clock signals.
+ *
+ * Note that the Voice CODEC currently only allows USE_4_TIMESLOTS when
+ * operating in data bus master mode.
+ */
+typedef enum {
+ USE_2_TIMESLOTS, /*!< Configure for 2 timeslots. */
+ USE_4_TIMESLOTS, /*!< Configure for 4 timeslots. */
+ USE_8_STAR_TIMESLOTS, /*!< Configure for 8 (Left, Right, 6 other) timeslots. */
+ USE_8_TIMESLOTS /*!< Configure for 8 timeslots. */
+} PMIC_AUDIO_NUMSLOTS;
+
+/*!
+ * @enum PMIC_AUDIO_STDAC_SAMPLING_RATE
+ * @brief Select the audio data sampling rate for the Stereo DAC.
+ *
+ * This enumeration defines all of the possible sampling rates currently
+ * supported by the Stereo DAC. One of these sampling rates must be selected
+ * and it must match that of the audio stream or else signal distortion will
+ * occur.
+ */
+typedef enum {
+ STDAC_RATE_8_KHZ, /*!< Use 8 kHz sampling rate. */
+ STDAC_RATE_11_025_KHZ, /*!< Use 11.025 kHz sampling rate. */
+ STDAC_RATE_12_KHZ, /*!< Use 12 kHz sampling rate. */
+ STDAC_RATE_16_KHZ, /*!< Use 16 kHz sampling rate. */
+ STDAC_RATE_22_050_KHZ, /*!< Use 22.050 kHz sampling rate. */
+ STDAC_RATE_24_KHZ, /*!< Use 24 kHz sampling rate. */
+ STDAC_RATE_32_KHZ, /*!< Use 32 kHz sampling rate. */
+ STDAC_RATE_44_1_KHZ, /*!< Use 44.1 kHz sampling rate. */
+ STDAC_RATE_48_KHZ, /*!< Use 48 kHz sampling rate. */
+ STDAC_RATE_64_KHZ, /*!< Use 64 kHz sampling rate
+ . */
+ STDAC_RATE_96_KHZ /*!< Use 96 kHz sampling rate.
+ . */
+} PMIC_AUDIO_STDAC_SAMPLING_RATE;
+
+/*!
+ * @enum PMIC_AUDIO_VCODEC_SAMPLING_RATE
+ * @brief Select the audio data sampling rate for the Voice CODEC.
+ *
+ * This enumeration defines all of the possible sampling rates currently
+ * supported by the Voice CODEC. One of these sampling rates must be selected
+ * and it must match that of the audio stream or else signal distortion will
+ * occur.
+ */
+typedef enum {
+ VCODEC_RATE_8_KHZ, /*!< Use 8 kHz sampling rate. */
+ VCODEC_RATE_16_KHZ, /*!< Use 16 kHz sampling rate. */
+} PMIC_AUDIO_VCODEC_SAMPLING_RATE;
+
+/*!
+ * @enum PMIC_AUDIO_ANTI_POP_RAMP_SPEED
+ * @brief Select the anti-pop circuitry's ramp up speed.
+ *
+ * This enumeration defines all of the possible ramp up speeds for the
+ * anti-pop circuitry. A slow ramp up speed may be required in order to
+ * avoid the popping noise that is typically generated during the insertion
+ * or removal of a headset or microphone.
+ */
+typedef enum {
+ ANTI_POP_RAMP_FAST, /*!< Select fast ramp up. */
+ ANTI_POP_RAMP_SLOW /*!< Select slow ramp up. */
+} PMIC_AUDIO_ANTI_POP_RAMP_SPEED;
+
+/*@}*/
+
+/*!
+ * @name General Voice CODEC Configuration Typedefs and Enumerations
+ * Typedefs and enumerations that are used to define and configure
+ * the basic operating options for the Voice CODEC.
+ */
+/*@{*/
+
+/*!
+ * @enum PMIC_AUDIO_VCODEC_CLOCK_IN_FREQ
+ * @brief Select the Voice CODEC input clock frequency.
+ *
+ * This enumeration defines all of the supported Voice CODEC input clock
+ * frequencies. One of these frequencies must be selected in order to
+ * properly configure the Voice CODEC to operate at the required sampling
+ * rate.
+ */
+typedef enum {
+ VCODEC_CLI_13MHZ, /*!< Clock frequency is 13MHz. */
+ VCODEC_CLI_15_36MHZ, /*!< Clock frequency is 15.36MHz. */
+ VCODEC_CLI_16_8MHZ, /*!< Clock frequency is 16.8MHz
+ . */
+ VCODEC_CLI_26MHZ, /*!< Clock frequency is 26MHz. */
+ VCODEC_CLI_33_6MHZ, /*!< Clock frequency is 33.6MHz. */
+} PMIC_AUDIO_VCODEC_CLOCK_IN_FREQ;
+
+/*!
+ * @enum PMIC_AUDIO_VCODEC_CONFIG
+ * @brief Select the Voice CODEC configuration options.
+ *
+ * This enumeration is used to enable/disable each of the Voice CODEC options.
+ * This includes the use of highpass digital filters and audio signal
+ * loopback modes.
+ *
+ * Note that resetting the digital filters is now handled by the
+ * pmic_audio_digital_filter_reset() API.
+ */
+typedef enum {
+ DITHERING = 1, /*!< Enable/disable dithering. */
+ INPUT_HIGHPASS_FILTER = 2, /*!< Enable/disable the input high
+ pass digital filter. */
+ OUTPUT_HIGHPASS_FILTER = 4, /*!< Enable/disable the output high
+ pass digital filter. */
+ ANALOG_LOOPBACK = 8, /*!< Enable/disable the analog
+ loopback path
+ . */
+ DIGITAL_LOOPBACK = 16, /*!< Enable/disable the digital
+ loopback path. */
+ VCODEC_MASTER_CLOCK_OUTPUTS = 32, /*!< Enable/disable the bus master
+ clock outputs. */
+ TRISTATE_TS = 64 /*!< Enable/disable FSYNC, BITCLK,
+ and TX tristate. */
+} PMIC_AUDIO_VCODEC_CONFIG;
+
+/*@}*/
+
+/*!
+ * @name General Stereo DAC Configuration Typedefs and Enumerations
+ * Typedefs and enumerations that are used to define and configure
+ * the basic operating options for the Stereo DAC.
+ */
+/*@{*/
+
+/*!
+ * @enum PMIC_AUDIO_STDAC_CLOCK_IN_FREQ
+ * @brief Select the Stereo DAC input clock frequency.
+ *
+ * This enumeration defines all of the supported Stereo DAC input clock
+ * frequencies. One of these frequencies must be selected in order to
+ * properly configure the Stereo DAC to operate at the required sampling
+ * rate.
+ */
+typedef enum {
+ STDAC_CLI_3_36864MHZ, /*!< Clock frequency is 3.36864MHz
+ . */
+ STDAC_CLI_12MHZ, /*!< Clock frequency is 12MHz.
+ . */
+ STDAC_CLI_13MHZ, /*!< Clock frequency is 13MHz. */
+ STDAC_CLI_15_36MHZ, /*!< Clock frequency is 15.36MHz. */
+ STDAC_CLI_16_8MHZ, /*!< Clock frequency is 16.8MHz
+ . */
+ STDAC_CLI_26MHZ, /*!< Clock frequency is 26MHz. */
+ STDAC_CLI_33_6MHZ, /*!< Clock frequency is 33.6MHz. */
+ STDAC_MCLK_PLL_DISABLED, /*!< Use MCLK and disable internal PLL. */
+ STDAC_FSYNC_IN_PLL, /*!< Use FSYNC as internal PLL input. */
+ STDAC_BCLK_IN_PLL /*!< Use BCLK as internal PLL input. */
+} PMIC_AUDIO_STDAC_CLOCK_IN_FREQ;
+
+/*!
+ * @enum PMIC_AUDIO_STDAC_CONFIG
+ * @brief Select the Stereo DAC configuration options.
+ *
+ * This enumeration is used to enable/disable each of the Stereo DAC options.
+ */
+typedef enum {
+ STDAC_MASTER_CLOCK_OUTPUTS = 1 /*!< Enable/disable the bus master clock
+ outputs. */
+} PMIC_AUDIO_STDAC_CONFIG;
+
+/*@}*/
+
+/*!
+ * @name Voice CODEC Audio Port Mixing Typedefs and Enumerations
+ * Typedefs and enumerations that are used for setting up the audio mixer
+ * within the Voice CODEC.
+ */
+/*@{*/
+
+/*!
+ * @enum PMIC_AUDIO_VCODEC_TIMESLOT
+ * @brief Select the Stereo DAC configuration options.
+ *
+ * This enumeration is used to select the timeslot for both the primary and
+ * secondary (for mc13783-only) audio channels to the Voice CODEC.
+ */
+typedef enum {
+ USE_TS0, /*!< Use timeslot 0 for audio signal source
+ . */
+ USE_TS1, /*!< Use timeslot 1 for audio signal source
+ . */
+ USE_TS2, /*!< Use timeslot 2 for audio signal source
+ . */
+ USE_TS3 /*!< Use timeslot 3 for audio signal source
+ . */
+} PMIC_AUDIO_VCODEC_TIMESLOT;
+
+/*!
+ * @enum PMIC_AUDIO_VCODEC_MIX_IN_GAIN
+ * @brief Select the secondary channel input gain for the Voice CODEC mixer.
+ *
+ * This enumeration selects the secondary channel input gain for the Voice
+ * CODEC mixer.
+ */
+typedef enum {
+ VCODEC_NO_MIX, /*!< No audio mixing . */
+ VCODEC_MIX_IN_0DB, /*!< Mix with 0dB secondary channel gain
+ . */
+ VCODEC_MIX_IN_MINUS_6DB, /*!< Mix with -6dB secondary channel gain
+ . */
+ VCODEC_MIX_IN_MINUS_12DB, /*!< Mix with -12dB secondary channel gain
+ . */
+} PMIC_AUDIO_VCODEC_MIX_IN_GAIN;
+
+/*!
+ * @enum PMIC_AUDIO_VCODEC_MIX_OUT_GAIN
+ * @brief Select the output gain for the Voice CODEC mixer.
+ *
+ * This enumeration selects the output gain for the Voice CODEC mixer.
+ */
+typedef enum {
+ VCODEC_MIX_OUT_0DB, /*!< Select 0dB mixer output gain
+ . */
+ VCODEC_MIX_OUT_MINUS_6DB, /*!< Select -6dB mixer output gain
+ . */
+} PMIC_AUDIO_VCODEC_MIX_OUT_GAIN;
+
+/*@}*/
+
+/*!
+ * @name Stereo DAC Audio Port Mixing Typedefs and Enumerations
+ * Typedefs and enumerations that are used for setting up the audio mixer
+ * within the Stereo DAC.
+ */
+/*@{*/
+
+/*!
+ * @enum PMIC_AUDIO_STDAC_TIMESLOTS
+ * @brief Select the timeslots used to transmit the left and right audio
+ * channels to the Stereo DAC.
+ *
+ * This enumeration is used to select the timeslots used to transmit the
+ * data corresponding to the left and right audio channels to the Stereo
+ * DAC.
+ */
+typedef enum {
+ USE_TS0_TS1, /*!< Use timeslots 0 and 1 for left and
+ right channels, respectively. */
+ USE_TS2_TS3, /*!< Use timeslots 2 and 3 for left and
+ right channels, respectively
+ . */
+ USE_TS4_TS5, /*!< Use timeslots 4 and 5 for left and
+ right channels, respectively
+ . */
+ USE_TS6_TS7 /*!< Use timeslots 6 and 7 for left and
+ right channels, respectively
+ . */
+} PMIC_AUDIO_STDAC_TIMESLOTS;
+
+/*!
+ * @enum PMIC_AUDIO_STDAC_MIX_IN_GAIN
+ * @brief Select the secondary channel input gain for the Stereo DAC mixer.
+ *
+ * This enumeration is used to select the secondary channel input gain for
+ * the Stereo DAC mixer.
+ */
+typedef enum {
+ STDAC_NO_MIX, /*!< No mixing, keep separate left
+ and right audio channels. */
+ STDAC_MIX_IN_0DB, /*!< Mix left and right audio channels
+ together with 0dB secondary
+ channel gain. */
+ STDAC_MIX_IN_MINUS_6DB, /*!< Mix left and right audio channels
+ together with -6dB secondary
+ channel gain. */
+ STDAC_MIX_IN_MINUS_12DB /*!< Mix left and right audio channels
+ together with -12dB secondary
+ channel gain . */
+} PMIC_AUDIO_STDAC_MIX_IN_GAIN;
+
+/*!
+ * @enum PMIC_AUDIO_STDAC_MIX_OUT_GAIN
+ * @brief Select the output gain for the Stereo DAC mixer.
+ *
+ * This enumeration is used to select the output gain for the Stereo DAC
+ * mixer.
+ */
+typedef enum {
+ STDAC_MIX_OUT_0DB, /*!< Select 0dB mixer output gain. */
+ STDAC_MIX_OUT_MINUS_6DB, /*!< Select -6dB mixer output gain
+ . */
+} PMIC_AUDIO_STDAC_MIX_OUT_GAIN;
+
+/*@}*/
+
+/*!
+ * @name Microphone Input Typedefs and Enumerations
+ * Typedefs and enumerations that are used for selecting and setting up
+ * one or more or microphone inputs for recording.
+ */
+/*@{*/
+
+/*!
+ * @enum PMIC_AUDIO_MIC_BIAS
+ * @brief Select the microphone bias circuit to be enabled/disabled.
+ *
+ * This enumeration lists all of the available microphone bias circuits that
+ * may be enabled or disabled.
+ */
+typedef enum {
+ NO_BIAS = 0, /*!< No microphone bias circuit selected. */
+ MIC_BIAS1 = 1, /*!< Enable/disable microphone bias 1 circuit. */
+ MIC_BIAS2 = 2, /*!< Enable/disable microphone bias 2 circuit. */
+} PMIC_AUDIO_MIC_BIAS;
+
+/*!
+ * @enum PMIC_AUDIO_INPUT_PORT
+ * @brief Select an audio input port for recording.
+ *
+ * This enumeration lists all of the available audio input ports that may
+ * be selected for a recording operation.
+ */
+typedef enum {
+ NO_MIC, /*!< No microphone input selected. */
+ MIC1_LEFT, /*!< Enable left/mono channel microphone input
+ . */
+ MIC1_RIGHT_MIC_MONO, /*!< Enable right channel microphone input. */
+ MIC2_AUX, /*!< Enable auxiliary microphone input. */
+ TXIN_EXT /*!< Enable external mono input. */
+} PMIC_AUDIO_INPUT_PORT;
+
+/*!
+ * @enum PMIC_AUDIO_INPUT_MIC_STATE
+ * @brief Control whether the input microphone is on/off.
+ *
+ * This enumeration allows the currently selected input microphone amplifier
+ * to be turned on/off.
+ */
+typedef enum {
+ MICROPHONE_ON, /*!< Turn microphone input on for recording. */
+ MICROPHONE_OFF /*!< Turn microphone input off (mute). */
+} PMIC_AUDIO_INPUT_MIC_STATE;
+
+/*!
+ * @enum PMIC_AUDIO_INPUT_CONFIG
+ * @brief Enable/disable the audio input options.
+ *
+ * This enumeration allows for enabling/disabling any of the audio input
+ * section options.
+ */
+typedef enum {
+ MIC_AMP_AUTO_DISABLE = 1 /*!< Enable/disable automatic disabling of
+ microphone input amplifiers following
+ headset insertion/removal */
+} PMIC_AUDIO_INPUT_CONFIG;
+
+/*!
+ * @enum PMIC_AUDIO_MIC_AMP_MODE
+ * @brief Select the operating mode for the microphone amplifiers.
+ *
+ * This enumeration is used to select the operating mode for the microphone
+ * amplifier.
+ */
+typedef enum {
+ AMP_OFF, /*!< Disable input amplifier. */
+ VOLTAGE_TO_VOLTAGE, /*!< Operate input amplifier in
+ voltage-to-voltage mode
+ . */
+ CURRENT_TO_VOLTAGE /*!< Operate input amplifier in
+ current-to-voltage mode */
+} PMIC_AUDIO_MIC_AMP_MODE;
+
+/*!
+ * @enum PMIC_AUDIO_MIC_GAIN
+ * @brief Select the microphone amplifier gain level.
+ *
+ * This enumeration lists all of the available microphone amplifier gain
+ * levels.
+ */
+typedef enum {
+ MIC_GAIN_MINUS_8DB, /*!< Select -8dB microphone amplifier gain
+ . */
+ MIC_GAIN_MINUS_7DB, /*!< Select -7dB microphone amplifier gain
+ . */
+ MIC_GAIN_MINUS_6DB, /*!< Select -6dB microphone amplifier gain
+ . */
+ MIC_GAIN_MINUS_5DB, /*!< Select -5dB microphone amplifier gain
+ . */
+ MIC_GAIN_MINUS_4DB, /*!< Select -4dB microphone amplifier gain
+ . */
+ MIC_GAIN_MINUS_3DB, /*!< Select -3dB microphone amplifier gain
+ . */
+ MIC_GAIN_MINUS_2DB, /*!< Select -2dB microphone amplifier gain
+ . */
+ MIC_GAIN_MINUS_1DB, /*!< Select -1dB microphone amplifier gain
+ . */
+ MIC_GAIN_0DB, /*!< Select 0dB microphone amplifier gain. */
+ MIC_GAIN_PLUS_1DB, /*!< Select 1dB microphone amplifier gain. */
+ MIC_GAIN_PLUS_2DB, /*!< Select 2dB microphone amplifier gain. */
+ MIC_GAIN_PLUS_3DB, /*!< Select 3dB microphone amplifier gain. */
+ MIC_GAIN_PLUS_4DB, /*!< Select 4dB microphone amplifier gain. */
+ MIC_GAIN_PLUS_5DB, /*!< Select 5dB microphone amplifier gain. */
+ MIC_GAIN_PLUS_6DB, /*!< Select 6dB microphone amplifier gain. */
+ MIC_GAIN_PLUS_7DB, /*!< Select 7dB microphone amplifier gain. */
+ MIC_GAIN_PLUS_8DB, /*!< Select 8dB microphone amplifier gain. */
+ MIC_GAIN_PLUS_9DB, /*!< Select 9dB microphone amplifier gain. */
+ MIC_GAIN_PLUS_10DB, /*!< Select 10dB microphone amplifier gain. */
+ MIC_GAIN_PLUS_11DB, /*!< Select 11dB microphone amplifier gain. */
+ MIC_GAIN_PLUS_12DB, /*!< Select 12dB microphone amplifier gain. */
+ MIC_GAIN_PLUS_13DB, /*!< Select 13dB microphone amplifier gain. */
+ MIC_GAIN_PLUS_14DB, /*!< Select 14dB microphone amplifier gain. */
+ MIC_GAIN_PLUS_15DB, /*!< Select 15dB microphone amplifier gain. */
+ MIC_GAIN_PLUS_16DB, /*!< Select 16dB microphone amplifier gain. */
+ MIC_GAIN_PLUS_17DB, /*!< Select 17dB microphone amplifier gain. */
+ MIC_GAIN_PLUS_18DB, /*!< Select 18dB microphone amplifier gain. */
+ MIC_GAIN_PLUS_19DB, /*!< Select 19dB microphone amplifier gain. */
+ MIC_GAIN_PLUS_20DB, /*!< Select 20dB microphone amplifier gain. */
+ MIC_GAIN_PLUS_21DB, /*!< Select 21dB microphone amplifier gain. */
+ MIC_GAIN_PLUS_22DB, /*!< Select 22dB microphone amplifier gain. */
+ MIC_GAIN_PLUS_23DB, /*!< Select 23dB microphone amplifier gain. */
+ MIC_GAIN_PLUS_24DB, /*!< Select 24dB microphone amplifier gain
+ . */
+ MIC_GAIN_PLUS_25DB, /*!< Select 25dB microphone amplifier gain
+ . */
+ MIC_GAIN_PLUS_26DB, /*!< Select 26dB microphone amplifier gain
+ . */
+ MIC_GAIN_PLUS_27DB, /*!< Select 27dB microphone amplifier gain
+ . */
+ MIC_GAIN_PLUS_28DB, /*!< Select 28dB microphone amplifier gain
+ . */
+ MIC_GAIN_PLUS_29DB, /*!< Select 29dB microphone amplifier gain
+ . */
+ MIC_GAIN_PLUS_30DB, /*!< Select 30dB microphone amplifier gain
+ . */
+ MIC_GAIN_PLUS_31DB /*!< Select 31dB microphone amplifier gain
+ . */
+} PMIC_AUDIO_MIC_GAIN;
+
+/*@}*/
+
+/*!
+ * @name Audio Output Section Typedefs and Enumerations
+ * Typedefs and enumerations that are used for selecting and setting up
+ * one or more or audio output ports for playback.
+ */
+/*@{*/
+
+/*!
+ * @enum PMIC_AUDIO_OUTPUT_PORT
+ * @brief Select the audio output port.
+ *
+ * This enumeration lists all of the available audio output ports. One or
+ * more may be selected as desired to handle the output audio stream from
+ * either the Voice CODEC or the Stereo DAC.
+ */
+typedef enum {
+ MONO_SPEAKER = 1, /*!< Select mono output speaker. */
+ MONO_LOUDSPEAKER = 2, /*!< Select mono loudspeaker
+ . */
+ MONO_ALERT = 4, /*!< Select mono alert output */
+ MONO_EXTOUT = 8, /*!< Select mono external output */
+ MONO_CDCOUT = 16, /*!< Select dedicated Voice CODEC output
+ . */
+ STEREO_LEFT_LOW_POWER = 32, /*!< Select stereo left channel low power
+ output . */
+ STEREO_HEADSET_LEFT = 64, /*!< Select stereo headset left channel. */
+ STEREO_HEADSET_RIGHT = 128, /*!< Select stereo headset right channel. */
+ STEREO_OUT_LEFT = 256, /*!< Select stereo external left channel
+ output . */
+ STEREO_OUT_RIGHT = 512 /*!< Select stereo external right channel
+ output . */
+} PMIC_AUDIO_OUTPUT_PORT;
+
+/*!
+ * @enum PMIC_AUDIO_OUTPUT_CONFIG
+ * @brief Enable/disable the audio output section options.
+ *
+ * This enumeration is used to enable/disable any of the audio output section
+ * options.
+ */
+typedef enum {
+ MONO_SPEAKER_INVERT_OUT_ONLY = 1, /*!< Enable/disable the non-inverted
+ mono speaker output */
+ MONO_LOUDSPEAKER_COMMON_BIAS = 2, /*!< Enable/disable the loudspeaker
+ output amplifier common bias
+ . */
+ HEADSET_DETECT_ENABLE = 4, /*!< Enable/disable headset
+ insertion/removal detection
+ . */
+ STEREO_HEADSET_AMP_AUTO_DISABLE = 8 /*!< Enable/disable automatic
+ disabling of the stereo headset
+ output amplifiers following
+ headset insertion/removal. */
+} PMIC_AUDIO_OUTPUT_CONFIG;
+
+/*!
+ * @enum PMIC_AUDIO_STEREO_IN_GAIN
+ * @brief Select the amplifier gain for the external stereo inputs.
+ *
+ * This enumeration is used to select the amplifier gain level to be used for
+ * the external stereo inputs.
+ */
+typedef enum {
+ STEREO_IN_GAIN_0DB, /*!< Select 0dB external stereo signal
+ input gain. */
+ STEREO_IN_GAIN_PLUS_18DB /*!< Select 18dB external stereo signal
+ input gain . */
+} PMIC_AUDIO_STEREO_IN_GAIN;
+
+/*!
+ * @enum PMIC_AUDIO_OUTPUT_PGA_GAIN
+ * @brief Select the output PGA amplifier gain level.
+ *
+ * This enumeration is used to select the output PGA amplifier gain level.
+ */
+typedef enum {
+ OUTPGA_GAIN_MINUS_33DB, /*!< Select -33dB output PGA gain
+ . */
+ OUTPGA_GAIN_MINUS_30DB, /*!< Select -30dB output PGA gain
+ . */
+ OUTPGA_GAIN_MINUS_27DB, /*!< Select -27dB output PGA gain
+ . */
+ OUTPGA_GAIN_MINUS_24DB, /*!< Select -24dB output PGA gain. */
+ OUTPGA_GAIN_MINUS_21DB, /*!< Select -21dB output PGA gain. */
+ OUTPGA_GAIN_MINUS_18DB, /*!< Select -18dB output PGA gain. */
+ OUTPGA_GAIN_MINUS_15DB, /*!< Select -15dB output PGA gain. */
+ OUTPGA_GAIN_MINUS_12DB, /*!< Select -12dB output PGA gain. */
+ OUTPGA_GAIN_MINUS_9DB, /*!< Select -9dB output PGA gain. */
+ OUTPGA_GAIN_MINUS_6DB, /*!< Select -6dB output PGA gain. */
+ OUTPGA_GAIN_MINUS_3DB, /*!< Select -3dB output PGA gain. */
+ OUTPGA_GAIN_0DB, /*!< Select 0dB output PGA gain. */
+ OUTPGA_GAIN_PLUS_3DB, /*!< Select 3dB output PGA gain. */
+ OUTPGA_GAIN_PLUS_6DB, /*!< Select 6dB output PGA gain. */
+ OUTPGA_GAIN_PLUS_9DB, /*!< Select 9dB output PGA gain.
+ . */
+ OUTPGA_GAIN_PLUS_12DB, /*!< Select 12dB output PGA gain
+ . */
+ OUTPGA_GAIN_PLUS_15DB, /*!< Select 15dB output PGA gain
+ . */
+ OUTPGA_GAIN_PLUS_18DB, /*!< Select 18dB output PGA gain
+ . */
+ OUTPGA_GAIN_PLUS_21DB /*!< Select 21dB output PGA gain
+ . */
+} PMIC_AUDIO_OUTPUT_PGA_GAIN;
+
+/*!
+ * @enum PMIC_AUDIO_OUTPUT_BALANCE_GAIN
+ * @brief Select the left/right channel balance gain level.
+ *
+ * This enumeration is used to select the balance gain level that is to be
+ * separately applied to the left and right audio channels.
+ */
+typedef enum {
+ BAL_GAIN_MINUS_21DB, /*!< Select -21dB channel balance
+ gain . */
+ BAL_GAIN_MINUS_18DB, /*!< Select -18dB channel balance
+ gain . */
+ BAL_GAIN_MINUS_15DB, /*!< Select -15dB channel balance
+ gain . */
+ BAL_GAIN_MINUS_12DB, /*!< Select -12dB channel balance
+ gain . */
+ BAL_GAIN_MINUS_9DB, /*!< Select -9dB channel balance
+ gain . */
+ BAL_GAIN_MINUS_6DB, /*!< Select -6dB channel balance
+ gain . */
+ BAL_GAIN_MINUS_3DB, /*!< Select -3dB channel balance
+ gain . */
+ BAL_GAIN_0DB /*!< Select 0dB channel balance gain. */
+} PMIC_AUDIO_OUTPUT_BALANCE_GAIN;
+
+/*!
+ * @enum PMIC_AUDIO_MONO_ADDER_MODE
+ * @brief Select the output mono adder operating mode.
+ *
+ * This enumeration is used to select the operating mode for the mono adder
+ * in the audio output section.
+ */
+typedef enum {
+ MONO_ADDER_OFF, /*!< Disable mono adder (keep separate
+ left and right channels). */
+ MONO_ADD_LEFT_RIGHT, /*!< Add left and right channels. */
+ MONO_ADD_OPPOSITE_PHASE, /*!< Add left and right channels but
+ with outputs in opposite phase
+ . */
+ STEREO_OPPOSITE_PHASE /*!< Keep separate left and right
+ channels but invert phase of
+ left channel . */
+} PMIC_AUDIO_MONO_ADDER_MODE;
+
+/*!
+ * @enum PMIC_AUDIO_MONO_ADDER_OUTPUT_GAIN
+ * @brief Select the mono adder output amplifier gain level.
+ *
+ * This enumeration is used to select the output amplifier gain level for
+ * the mono adder.
+ */
+typedef enum {
+ MONOADD_GAIN_MINUS_6DB, /*!< Select -6dB mono adder output gain
+ . */
+ MONOADD_GAIN_MINUS_3DB, /*!< Select -3dB mono adder output gain
+ . */
+ MONOADD_GAIN_0DB /*!< Select 0dB mono adder output gain. */
+} PMIC_AUDIO_MONO_ADDER_OUTPUT_GAIN;
+
+/*@}*/
+
+/***************************************************************************
+ * PMIC-SPECIFIC DEFINITIONS *
+ ***************************************************************************/
+
+/*!
+ * @name Definition of PMIC-specific Capabilities
+ * Constants that are used to define PMIC-specific capabilities.
+ */
+/*@{*/
+
+/*!
+ * Define the minimum Stereo DAC sampling rate (Hz).
+ */
+extern const unsigned MIN_STDAC_SAMPLING_RATE_HZ;
+/*!
+ * Define the maximum Stereo DAC sampling rate (Hz).
+ */
+extern const unsigned MAX_STDAC_SAMPLING_RATE_HZ;
+
+/*@}*/
+
+#define DEBUG_AUDIO
+
+#ifdef __KERNEL__
+
+/***************************************************************************
+ * PMIC API DEFINITIONS *
+ ***************************************************************************/
+
+/*!
+ * @name General Setup and Configuration APIs
+ * Functions for general setup and configuration of the PMIC Audio
+ * hardware.
+ */
+/*@{*/
+
+/*!
+ * This function enables the Headset detection mechanism in hardware
+ */
+PMIC_STATUS pmic_audio_set_autodetect(int val);
+
+/*!
+ * @brief Request exclusive access to the PMIC Audio hardware.
+ *
+ * Attempt to open and gain exclusive access to a key PMIC audio hardware
+ * component (e.g., the Stereo DAC or the Voice CODEC). Depending upon the
+ * type of audio operation that is desired and the nature of the audio data
+ * stream, the Stereo DAC and/or the Voice CODEC will be a required hardware
+ * component and needs to be acquired by calling this function.
+ *
+ * If the open request is successful, then a numeric handle is returned
+ * and this handle must be used in all subsequent function calls to complete
+ * the configuration of either the Stereo DAC or the Voice CODEC and along
+ * with any other associated audio hardware components that will be needed.
+ *
+ * The same handle must also be used in the close call when use of the PMIC
+ * audio hardware is no longer required.
+ *
+ * The open request will fail if the requested audio hardware component has
+ * already been acquired by a previous open call but not yet closed.
+ *
+ * @param[out] handle Device handle to be used for subsequent PMIC
+ * Connectivity API calls.
+ * @param[in] device The required PMIC audio hardware component.
+ *
+ * @retval PMIC_SUCCESS If the open request was successful
+ * @retval PMIC_PARAMETER_ERROR If the handle argument is NULL.
+ * @retval PMIC_ERROR If the audio hardware component is
+ * unavailable.
+ */
+PMIC_STATUS pmic_audio_open(PMIC_AUDIO_HANDLE * const handle,
+ const PMIC_AUDIO_SOURCE device);
+
+/*!
+ * @brief Terminate further access to the PMIC audio hardware.
+ *
+ * Terminate further access to the PMIC audio hardware that was previously
+ * acquired by calling pmic_audio_open(). This now allows another thread to
+ * successfully call pmic_audio_open() to gain access.
+ *
+ * @param[in] handle Device handle from pmic_audio_open() call.
+ *
+ * @retval PMIC_SUCCESS If the close request was successful.
+ * @retval PMIC_PARAMETER_ERROR If the handle is invalid.
+ */
+PMIC_STATUS pmic_audio_close(const PMIC_AUDIO_HANDLE handle);
+
+/*!
+ * @brief Configure the data bus protocol to be used.
+ *
+ * Provide the parameters needed to properly configure the audio data bus
+ * protocol so that data can be read/written to either the Stereo DAC or
+ * the Voice CODEC.
+ *
+ * @param[in] handle Device handle from pmic_audio_open() call.
+ * @param[in] busID Select data bus to be used.
+ * @param[in] protocol Select the data bus protocol.
+ * @param[in] masterSlave Select the data bus timing mode.
+ * @param[in] numSlots Define the number of timeslots (only if in
+ * master mode).
+ *
+ * @retval PMIC_SUCCESS If the protocol was successful configured.
+ * @retval PMIC_PARAMETER_ERROR If the handle or the protocol parameters
+ * are invalid.
+ */
+PMIC_STATUS pmic_audio_set_protocol(const PMIC_AUDIO_HANDLE handle,
+ const PMIC_AUDIO_DATA_BUS busID,
+ const PMIC_AUDIO_BUS_PROTOCOL protocol,
+ const PMIC_AUDIO_BUS_MODE masterSlave,
+ const PMIC_AUDIO_NUMSLOTS numSlots);
+
+/*!
+ * @brief Retrieve the current data bus protocol configuration.
+ *
+ * Retrieve the parameters that define the current audio data bus protocol.
+ *
+ * @param[in] handle Device handle from pmic_audio_open() call.
+ * @param[out] busID The data bus being used.
+ * @param[out] protocol The data bus protocol being used.
+ * @param[out] masterSlave The data bus timing mode being used.
+ * @param[out] numSlots The number of timeslots being used (if in
+ * master mode).
+ *
+ * @retval PMIC_SUCCESS If the protocol was successful retrieved.
+ * @retval PMIC_PARAMETER_ERROR If the handle is invalid.
+ */
+PMIC_STATUS pmic_audio_get_protocol(const PMIC_AUDIO_HANDLE handle,
+ PMIC_AUDIO_DATA_BUS * const busID,
+ PMIC_AUDIO_BUS_PROTOCOL * const protocol,
+ PMIC_AUDIO_BUS_MODE * const masterSlave,
+ PMIC_AUDIO_NUMSLOTS * const numSlots);
+
+/*!
+ * @brief Enable the Stereo DAC or the Voice CODEC.
+ *
+ * Explicitly enable the Stereo DAC or the Voice CODEC to begin audio
+ * playback or recording as required. This should only be done after
+ * successfully configuring all of the associated audio components (e.g.,
+ * microphones, amplifiers, etc.).
+ *
+ * @param[in] handle Device handle from pmic_audio_open() call.
+ *
+ * @retval PMIC_SUCCESS If the device was successful enabled.
+ * @retval PMIC_PARAMETER_ERROR If the handle is invalid.
+ * @retval PMIC_ERROR If the device could not be enabled.
+ */
+PMIC_STATUS pmic_audio_enable(const PMIC_AUDIO_HANDLE handle);
+
+/*!
+ * @brief Disable the Stereo DAC or the Voice CODEC.
+ *
+ * Explicitly disable the Stereo DAC or the Voice CODEC to end audio
+ * playback or recording as required.
+ *
+ * @param[in] handle Device handle from pmic_audio_open() call.
+ *
+ * @retval PMIC_SUCCESS If the device was successful disabled.
+ * @retval PMIC_PARAMETER_ERROR If the handle is invalid.
+ * @retval PMIC_ERROR If the device could not be disabled.
+ */
+PMIC_STATUS pmic_audio_disable(const PMIC_AUDIO_HANDLE handle);
+
+/*!
+ * @brief Reset the selected audio hardware control registers to their
+ * power on state.
+ *
+ * This resets all of the audio hardware control registers currently
+ * associated with the device handle back to their power on states. For
+ * example, if the handle is associated with the Stereo DAC and a
+ * specific output port and output amplifiers, then this function will
+ * reset all of those components to their power on state.
+ *
+ * @param[in] handle Device handle from pmic_audio_open() call.
+ *
+ * @retval PMIC_SUCCESS If the reset operation was successful.
+ * @retval PMIC_PARAMETER_ERROR If the handle is invalid.
+ * @retval PMIC_ERROR If the reset was unsuccessful.
+ */
+PMIC_STATUS pmic_audio_reset(const PMIC_AUDIO_HANDLE handle);
+
+/*!
+ * @brief Reset all audio hardware control registers to their power on state.
+ *
+ * This resets all of the audio hardware control registers back to their
+ * power on states. Use this function with care since it also invalidates
+ * (i.e., automatically closes) all currently opened device handles.
+ *
+ * @retval PMIC_SUCCESS If the reset operation was successful.
+ * @retval PMIC_ERROR If the reset was unsuccessful.
+ */
+PMIC_STATUS pmic_audio_reset_all(void);
+
+/*!
+ * @brief Set the Audio callback function.
+ *
+ * Register a callback function that will be used to signal PMIC audio
+ * events. For example, the OSS audio driver should register a callback
+ * function in order to be notified of headset connect/disconnect events.
+ *
+ * @param[in] func A pointer to the callback function.
+ * @param[in] eventMask A mask selecting events to be notified.
+ * @param[in] hs_state To know the headset state.
+ *
+ * @retval PMIC_SUCCESS If the callback was successfully
+ * registered.
+ * @retval PMIC_PARAMETER_ERROR If the handle or the eventMask is invalid.
+ */
+PMIC_STATUS pmic_audio_set_callback(void *func,
+ const PMIC_AUDIO_EVENTS eventMask,
+ PMIC_HS_STATE * hs_state);
+
+/*!
+ * @brief Deregisters the existing audio callback function.
+ *
+ * Deregister the callback function that was previously registered by calling
+ * pmic_audio_set_callback().
+ *
+ *
+ * @retval PMIC_SUCCESS If the callback was successfully
+ * deregistered.
+ * @retval PMIC_PARAMETER_ERROR If the handle is invalid.
+ */
+PMIC_STATUS pmic_audio_clear_callback(void);
+
+/*!
+ * @brief Get the current audio callback function settings.
+ *
+ * Get the current callback function and event mask.
+ *
+ * @param[out] func The current callback function.
+ * @param[out] eventMask The current event selection mask.
+ *
+ * @retval PMIC_SUCCESS If the callback information was
+ * successfully retrieved.
+ * @retval PMIC_PARAMETER_ERROR If the handle is invalid.
+ */
+PMIC_STATUS pmic_audio_get_callback(PMIC_AUDIO_CALLBACK * const func,
+ PMIC_AUDIO_EVENTS * const eventMask);
+
+/*!
+ * @brief Enable the anti-pop circuitry to avoid extra noise when inserting
+ * or removing a external device (e.g., a headset).
+ *
+ * Enable the use of the built-in anti-pop circuitry to prevent noise from
+ * being generated when an external audio device is inserted or removed
+ * from an audio plug. A slow ramp speed may be needed to avoid extra noise.
+ *
+ * @param[in] rampSpeed The desired anti-pop circuitry ramp speed.
+ *
+ * @retval PMIC_SUCCESS If the anti-pop circuitry was successfully
+ * enabled.
+ * @retval PMIC_ERROR If the anti-pop circuitry could not be
+ * enabled.
+ */
+PMIC_STATUS pmic_audio_antipop_enable(const PMIC_AUDIO_ANTI_POP_RAMP_SPEED
+ rampSpeed);
+
+/*!
+ * @brief Disable the anti-pop circuitry.
+ *
+ * Disable the use of the built-in anti-pop circuitry to prevent noise from
+ * being generated when an external audio device is inserted or removed
+ * from an audio plug.
+ *
+ * @retval PMIC_SUCCESS If the anti-pop circuitry was successfully
+ * disabled.
+ * @retval PMIC_ERROR If the anti-pop circuitry could not be
+ * disabled.
+ */
+PMIC_STATUS pmic_audio_antipop_disable(void);
+
+/*!
+ * @brief Performs a reset of the Voice CODEC/Stereo DAC digital filter.
+ *
+ * This function performs a reset of the digital filter using the back-to-back
+ * SPI write procedure.
+ *
+ * @retval PMIC_SUCCESS If the digital filter was successfully
+ * reset.
+ * @retval PMIC_ERROR If the digital filter could not be reset.
+ */
+PMIC_STATUS pmic_audio_digital_filter_reset(const PMIC_AUDIO_HANDLE handle);
+
+/*!
+ * @brief Get the most recent PTT button voltage reading.
+ *
+ * This function returns the most recent reading for the PTT button voltage.
+ * The value may be used during the processing of the PTT_BUTTON_RANGE event
+ * as part of the headset ID detection process.
+ *
+ * @retval PMIC_SUCCESS If the most recent PTT button voltage was
+ * returned.
+ * @retval PMIC_PARAMETER_ERROR If a NULL pointer argument was given.
+ */
+PMIC_STATUS pmic_audio_get_ptt_button_level(unsigned int *const level);
+
+#ifdef DEBUG_AUDIO
+
+/*!
+ * @brief Provide a hexadecimal dump of all PMIC audio registers (DEBUG only).
+ *
+ * This function is intended strictly for debugging purposes only (i.e.,
+ * the DEBUG macro must be defined) and will print the current values of the
+ * following PMIC registers:
+ *
+ * - AUD_CODEC (Voice CODEC state)
+ * - ST_DAC (Stereo DAC state)
+ * - RX_AUD_AMPS (audio input section state)
+ * - TX_AUD_AMPS (audio output section state)
+ *
+ * The register fields will also be decoded.
+ */
+void pmic_audio_dump_registers(void);
+
+#endif /* DEBUG */
+
+/*@}*/
+
+/*!
+ * @name General Voice CODEC Setup and Configuration APIs
+ * Functions for general setup and configuration of the PMIC Voice
+ * CODEC hardware.
+ */
+/*@{*/
+
+/*!
+ * @brief Set the Voice CODEC clock source and operating characteristics.
+ *
+ * Define the Voice CODEC clock source and operating characteristics. This
+ * must be done before the Voice CODEC is enabled.
+ *
+ * @param[in] handle Device handle from pmic_audio_open() call.
+ * @param[in] clockIn Select the clock signal source.
+ * @param[in] clockFreq Select the clock signal frequency.
+ * @param[in] samplingRate Select the audio data sampling rate.
+ * @param[in] invert Enable inversion of the frame sync and/or
+ * bit clock inputs.
+ *
+ * @retval PMIC_SUCCESS If the Voice CODEC clock settings were
+ * successfully configured.
+ * @retval PMIC_PARAMETER_ERROR If the handle or clock configuration was
+ * invalid.
+ * @retval PMIC_ERROR If the Voice CODEC clock configuration
+ * could not be set.
+ */
+PMIC_STATUS pmic_audio_vcodec_set_clock(const PMIC_AUDIO_HANDLE handle,
+ const PMIC_AUDIO_CLOCK_IN_SOURCE
+ clockIn,
+ const PMIC_AUDIO_VCODEC_CLOCK_IN_FREQ
+ clockFreq,
+ const PMIC_AUDIO_VCODEC_SAMPLING_RATE
+ samplingRate,
+ const PMIC_AUDIO_CLOCK_INVERT invert);
+
+/*!
+ * @brief Get the Voice CODEC clock source and operating characteristics.
+ *
+ * Get the current Voice CODEC clock source and operating characteristics.
+ *
+ * @param[in] handle Device handle from pmic_audio_open() call.
+ * @param[out] clockIn The clock signal source.
+ * @param[out] clockFreq The clock signal frequency.
+ * @param[out] samplingRate The audio data sampling rate.
+ * @param[out] invert Inversion of the frame sync and/or
+ * bit clock inputs is enabled/disabled.
+ *
+ * @retval PMIC_SUCCESS If the Voice CODEC clock settings were
+ * successfully retrieved.
+ * @retval PMIC_PARAMETER_ERROR If the handle invalid.
+ * @retval PMIC_ERROR If the Voice CODEC clock configuration
+ * could not be retrieved.
+ */
+PMIC_STATUS pmic_audio_vcodec_get_clock(const PMIC_AUDIO_HANDLE handle,
+ PMIC_AUDIO_CLOCK_IN_SOURCE *
+ const clockIn,
+ PMIC_AUDIO_VCODEC_CLOCK_IN_FREQ *
+ const clockFreq,
+ PMIC_AUDIO_VCODEC_SAMPLING_RATE *
+ const samplingRate,
+ PMIC_AUDIO_CLOCK_INVERT * const invert);
+
+/*!
+ * @brief Set the Voice CODEC primary audio channel timeslot.
+ *
+ * Set the Voice CODEC primary audio channel timeslot. This function must be
+ * used if the default timeslot for the primary audio channel is to be changed.
+ *
+ * @param[in] handle Device handle from pmic_audio_open() call.
+ * @param[in] timeslot Select the primary audio channel timeslot.
+ *
+ * @retval PMIC_SUCCESS If the Voice CODEC primary audio channel
+ * timeslot was successfully configured.
+ * @retval PMIC_PARAMETER_ERROR If the handle or audio channel timeslot
+ * was invalid.
+ * @retval PMIC_ERROR If the Voice CODEC primary audio channel
+ * timeslot could not be set.
+ */
+PMIC_STATUS pmic_audio_vcodec_set_rxtx_timeslot(const PMIC_AUDIO_HANDLE handle,
+ const PMIC_AUDIO_VCODEC_TIMESLOT
+ timeslot);
+
+/*!
+ * @brief Get the current Voice CODEC primary audio channel timeslot.
+ *
+ * Get the current Voice CODEC primary audio channel timeslot.
+ *
+ * @param[in] handle Device handle from pmic_audio_open() call.
+ * @param[out] timeslot The primary audio channel timeslot.
+ *
+ * @retval PMIC_SUCCESS If the Voice CODEC primary audio channel
+ * timeslot was successfully retrieved.
+ * @retval PMIC_PARAMETER_ERROR If the handle was invalid.
+ * @retval PMIC_ERROR If the Voice CODEC primary audio channel
+ * timeslot could not be retrieved.
+ */
+PMIC_STATUS pmic_audio_vcodec_get_rxtx_timeslot(const PMIC_AUDIO_HANDLE handle,
+ PMIC_AUDIO_VCODEC_TIMESLOT *
+ const timeslot);
+
+/*!
+ * @brief Set the Voice CODEC secondary recording audio channel timeslot.
+ *
+ * Set the Voice CODEC secondary audio channel timeslot. This function must be
+ * used if the default timeslot for the secondary audio channel is to be
+ * changed. The secondary audio channel timeslot is used to transmit the audio
+ * data that was recorded by the Voice CODEC from the secondary audio input
+ * channel.
+ *
+ * @param[in] handle Device handle from pmic_audio_open() call.
+ * @param[in] timeslot Select the secondary audio channel timeslot.
+ *
+ * @retval PMIC_SUCCESS If the Voice CODEC secondary audio channel
+ * timeslot was successfully configured.
+ * @retval PMIC_PARAMETER_ERROR If the handle or audio channel timeslot
+ * was invalid.
+ * @retval PMIC_ERROR If the Voice CODEC secondary audio channel
+ * timeslot could not be set.
+ */
+PMIC_STATUS pmic_audio_vcodec_set_secondary_txslot(const PMIC_AUDIO_HANDLE
+ handle,
+ const
+ PMIC_AUDIO_VCODEC_TIMESLOT
+ timeslot);
+
+/*!
+ * @brief Get the Voice CODEC secondary recording audio channel timeslot.
+ *
+ * Get the Voice CODEC secondary audio channel timeslot.
+ *
+ * @param[in] handle Device handle from pmic_audio_open() call.
+ * @param[out] timeslot The secondary audio channel timeslot.
+ *
+ * @retval PMIC_SUCCESS If the Voice CODEC secondary audio channel
+ * timeslot was successfully retrieved.
+ * @retval PMIC_PARAMETER_ERROR If the handle was invalid.
+ * @retval PMIC_ERROR If the Voice CODEC secondary audio channel
+ * timeslot could not be retrieved.
+ */
+PMIC_STATUS pmic_audio_vcodec_get_secondary_txslot(const PMIC_AUDIO_HANDLE
+ handle,
+ PMIC_AUDIO_VCODEC_TIMESLOT *
+ const timeslot);
+
+/*!
+ * @brief Set/Enable the Voice CODEC options.
+ *
+ * Set or enable various Voice CODEC options. The available options include
+ * the use of dithering, highpass digital filters, and loopback modes.
+ *
+ * @param[in] handle Device handle from pmic_audio_open() call.
+ * @param[in] config The Voice CODEC options to enable.
+ *
+ * @retval PMIC_SUCCESS If the Voice CODEC options were
+ * successfully configured.
+ * @retval PMIC_PARAMETER_ERROR If the handle or Voice CODEC options
+ * were invalid.
+ * @retval PMIC_ERROR If the Voice CODEC options could not be
+ * successfully set/enabled.
+ */
+PMIC_STATUS pmic_audio_vcodec_set_config(const PMIC_AUDIO_HANDLE handle,
+ const PMIC_AUDIO_VCODEC_CONFIG config);
+
+/*!
+ * @brief Clear/Disable the Voice CODEC options.
+ *
+ * Clear or disable various Voice CODEC options.
+ *
+ * @param[in] handle Device handle from pmic_audio_open() call.
+ * @param[in] config The Voice CODEC options to be cleared/disabled.
+ *
+ * @retval PMIC_SUCCESS If the Voice CODEC options were
+ * successfully cleared/disabled.
+ * @retval PMIC_PARAMETER_ERROR If the handle or the Voice CODEC options
+ * were invalid.
+ * @retval PMIC_ERROR If the Voice CODEC options could not be
+ * cleared/disabled.
+ */
+PMIC_STATUS pmic_audio_vcodec_clear_config(const PMIC_AUDIO_HANDLE handle,
+ const PMIC_AUDIO_VCODEC_CONFIG
+ config);
+
+/*!
+ * @brief Get the current Voice CODEC options.
+ *
+ * Get the current Voice CODEC options.
+ *
+ * @param[in] handle Device handle from pmic_audio_open() call.
+ * @param[out] config The current set of Voice CODEC options.
+ *
+ * @retval PMIC_SUCCESS If the Voice CODEC options were
+ * successfully retrieved.
+ * @retval PMIC_PARAMETER_ERROR If the handle was invalid.
+ * @retval PMIC_ERROR If the Voice CODEC options could not be
+ * retrieved.
+ */
+PMIC_STATUS pmic_audio_vcodec_get_config(const PMIC_AUDIO_HANDLE handle,
+ PMIC_AUDIO_VCODEC_CONFIG *
+ const config);
+
+/*!
+ * @brief Enable the Voice CODEC bypass audio pathway.
+ *
+ * Enables the Voice CODEC bypass pathway for audio data. This allows direct
+ * output of the voltages on the TX data bus line to the output amplifiers
+ * (bypassing the digital-to-analog converters within the Voice CODEC).
+ *
+ * @param[in] handle Device handle from pmic_audio_open() call.
+ *
+ * @retval PMIC_SUCCESS If the Voice CODEC bypass was successfully
+ * enabled.
+ * @retval PMIC_PARAMETER_ERROR If the handle was invalid.
+ * @retval PMIC_ERROR If the Voice CODEC bypass could not be
+ * enabled.
+ */
+PMIC_STATUS pmic_audio_vcodec_enable_bypass(const PMIC_AUDIO_HANDLE handle);
+
+/*!
+ * @brief Disable the Voice CODEC bypass audio pathway.
+ *
+ * Disables the Voice CODEC bypass pathway for audio data. This means that
+ * the TX data bus line will deliver digital data to the digital-to-analog
+ * converters within the Voice CODEC.
+ *
+ * @param[in] handle Device handle from pmic_audio_open() call.
+ *
+ * @retval PMIC_SUCCESS If the Voice CODEC bypass was successfully
+ * disabled.
+ * @retval PMIC_PARAMETER_ERROR If the handle was invalid.
+ * @retval PMIC_ERROR If the Voice CODEC bypass could not be
+ * disabled.
+ */
+PMIC_STATUS pmic_audio_vcodec_disable_bypass(const PMIC_AUDIO_HANDLE handle);
+
+/*@}*/
+
+/*!
+ * @name General Stereo DAC Setup and Configuration APIs
+ * Functions for general setup and configuration of the PMIC Stereo
+ * DAC hardware.
+ */
+/*@{*/
+
+/*!
+ * @brief Set the Stereo DAC clock source and operating characteristics.
+ *
+ * Define the Stereo DAC clock source and operating characteristics. This
+ * must be done before the Stereo DAC is enabled.
+ *
+ * @param[in] handle Device handle from pmic_audio_open() call.
+ * @param[in] clockIn Select the clock signal source.
+ * @param[in] clockFreq Select the clock signal frequency.
+ * @param[in] samplingRate Select the audio data sampling rate.
+ * @param[in] invert Enable inversion of the frame sync and/or
+ * bit clock inputs.
+ *
+ * @retval PMIC_SUCCESS If the Stereo DAC clock settings were
+ * successfully configured.
+ * @retval PMIC_PARAMETER_ERROR If the handle or clock configuration was
+ * invalid.
+ * @retval PMIC_ERROR If the Stereo DAC clock configuration
+ * could not be set.
+ */
+PMIC_STATUS pmic_audio_stdac_set_clock(const PMIC_AUDIO_HANDLE handle,
+ const PMIC_AUDIO_CLOCK_IN_SOURCE clockIn,
+ const PMIC_AUDIO_STDAC_CLOCK_IN_FREQ
+ clockFreq,
+ const PMIC_AUDIO_STDAC_SAMPLING_RATE
+ samplingRate,
+ const PMIC_AUDIO_CLOCK_INVERT invert);
+
+/*!
+ * @brief Get the Stereo DAC clock source and operating characteristics.
+ *
+ * Get the current Stereo DAC clock source and operating characteristics.
+ *
+ * @param[in] handle Device handle from pmic_audio_open() call.
+ * @param[out] clockIn The clock signal source.
+ * @param[out] clockFreq The clock signal frequency.
+ * @param[out] samplingRate The audio data sampling rate.
+ * @param[out] invert Inversion of the frame sync and/or
+ * bit clock inputs is enabled/disabled.
+ *
+ * @retval PMIC_SUCCESS If the Stereo DAC clock settings were
+ * successfully retrieved.
+ * @retval PMIC_PARAMETER_ERROR If the handle invalid.
+ * @retval PMIC_ERROR If the Stereo DAC clock configuration
+ * could not be retrieved.
+ */
+PMIC_STATUS pmic_audio_stdac_get_clock(const PMIC_AUDIO_HANDLE handle,
+ PMIC_AUDIO_CLOCK_IN_SOURCE *
+ const clockIn,
+ PMIC_AUDIO_STDAC_SAMPLING_RATE *
+ const samplingRate,
+ PMIC_AUDIO_STDAC_CLOCK_IN_FREQ *
+ const clockFreq,
+ PMIC_AUDIO_CLOCK_INVERT * const invert);
+
+/*!
+ * @brief Set the Stereo DAC primary audio channel timeslot.
+ *
+ * Set the Stereo DAC primary audio channel timeslot. This function must be
+ * used if the default timeslot for the primary audio channel is to be changed.
+ *
+ * @param[in] handle Device handle from pmic_audio_open() call.
+ * @param[in] timeslot Select the primary audio channel timeslot.
+ *
+ * @retval PMIC_SUCCESS If the Stereo DAC primary audio channel
+ * timeslot was successfully configured.
+ * @retval PMIC_PARAMETER_ERROR If the handle or audio channel timeslot
+ * was invalid.
+ * @retval PMIC_ERROR If the Stereo DAC primary audio channel
+ * timeslot could not be set.
+ */
+PMIC_STATUS pmic_audio_stdac_set_rxtx_timeslot(const PMIC_AUDIO_HANDLE handle,
+ const PMIC_AUDIO_STDAC_TIMESLOTS
+ timeslot);
+
+/*!
+ * @brief Get the current Stereo DAC primary audio channel timeslot.
+ *
+ * Get the current Stereo DAC primary audio channel timeslot.
+ *
+ * @param[in] handle Device handle from pmic_audio_open() call.
+ * @param[out] timeslot The primary audio channel timeslot.
+ *
+ * @retval PMIC_SUCCESS If the Stereo DAC primary audio channel
+ * timeslot was successfully retrieved.
+ * @retval PMIC_PARAMETER_ERROR If the handle was invalid.
+ * @retval PMIC_ERROR If the Stereo DAC primary audio channel
+ * timeslot could not be retrieved.
+ */
+PMIC_STATUS pmic_audio_stdac_get_rxtx_timeslot(const PMIC_AUDIO_HANDLE handle,
+ PMIC_AUDIO_STDAC_TIMESLOTS *
+ const timeslot);
+
+/*!
+ * @brief Set/Enable the Stereo DAC options.
+ *
+ * Set or enable various Stereo DAC options. The available options include
+ * enabling/disabling the bus master clock outputs.
+ *
+ * @param[in] handle Device handle from pmic_audio_open() call.
+ * @param[in] config The Stereo DAC options to enable.
+ *
+ * @retval PMIC_SUCCESS If the Stereo DAC options were
+ * successfully configured.
+ * @retval PMIC_PARAMETER_ERROR If the handle or Stereo DAC options
+ * were invalid.
+ * @retval PMIC_ERROR If the Stereo DAC options could not be
+ * successfully set/enabled.
+ */
+PMIC_STATUS pmic_audio_stdac_set_config(const PMIC_AUDIO_HANDLE handle,
+ const PMIC_AUDIO_STDAC_CONFIG config);
+
+/*!
+ * @brief Clear/Disable the Stereo DAC options.
+ *
+ * Clear or disable various Stereo DAC options.
+ *
+ * @param[in] handle Device handle from pmic_audio_open() call.
+ * @param[in] config The Stereo DAC options to be cleared/disabled.
+ *
+ * @retval PMIC_SUCCESS If the Stereo DAC options were
+ * successfully cleared/disabled.
+ * @retval PMIC_PARAMETER_ERROR If the handle or the Stereo DAC options
+ * were invalid.
+ * @retval PMIC_ERROR If the Stereo DAC options could not be
+ * cleared/disabled.
+ */
+PMIC_STATUS pmic_audio_stdac_clear_config(const PMIC_AUDIO_HANDLE handle,
+ const PMIC_AUDIO_STDAC_CONFIG config);
+
+/*!
+ * @brief Get the current Stereo DAC options.
+ *
+ * Get the current Stereo DAC options.
+ *
+ * @param[in] handle Device handle from pmic_audio_open() call.
+ * @param[out] config The current set of Stereo DAC options.
+ *
+ * @retval PMIC_SUCCESS If the Stereo DAC options were
+ * successfully retrieved.
+ * @retval PMIC_PARAMETER_ERROR If the handle was invalid.
+ * @retval PMIC_ERROR If the Stereo DAC options could not be
+ * retrieved.
+ */
+PMIC_STATUS pmic_audio_stdac_get_config(const PMIC_AUDIO_HANDLE handle,
+ PMIC_AUDIO_STDAC_CONFIG * const config);
+
+/*@}*/
+
+/*!
+ * @name Audio Input Setup and Configuration APIs
+ * Functions for general setup and configuration of the PMIC audio
+ * input hardware.
+ */
+/*@{*/
+
+/*!
+ * @brief Set/Enable the audio input section options.
+ *
+ * Set or enable various audio input section options. The only available
+ * option right now is to enable the automatic disabling of the microphone
+ * input amplifiers when a microphone/headset is inserted or removed.
+ *
+ * @param[in] handle Device handle from pmic_audio_open() call.
+ * @param[in] config The audio input section options to enable.
+ *
+ * @retval PMIC_SUCCESS If the audio input section options were
+ * successfully configured.
+ * @retval PMIC_PARAMETER_ERROR If the handle or audio input section
+ * options were invalid.
+ * @retval PMIC_ERROR If the audio input section options could
+ * not be successfully set/enabled.
+ */
+PMIC_STATUS pmic_audio_input_set_config(const PMIC_AUDIO_HANDLE handle,
+ const PMIC_AUDIO_INPUT_CONFIG config);
+
+/*!
+ * @brief Clear/Disable the audio input section options.
+ *
+ * Clear or disable various audio input section options.
+ *
+ * @param[in] handle Device handle from pmic_audio_open() call.
+ * @param[in] config The audio input section options to be
+ * cleared/disabled.
+ *
+ * @retval PMIC_SUCCESS If the audio input section options were
+ * successfully cleared/disabled.
+ * @retval PMIC_PARAMETER_ERROR If the handle or the audio input section
+ * options were invalid.
+ * @retval PMIC_ERROR If the audio input section options could
+ * not be cleared/disabled.
+ */
+PMIC_STATUS pmic_audio_input_clear_config(const PMIC_AUDIO_HANDLE handle,
+ const PMIC_AUDIO_INPUT_CONFIG config);
+
+/*!
+ * @brief Get the current audio input section options.
+ *
+ * Get the current audio input section options.
+ *
+ * @param[in] handle Device handle from pmic_audio_open() call.
+ * @param[out] config The current set of audio input section options.
+ *
+ * @retval PMIC_SUCCESS If the audio input section options were
+ * successfully retrieved.
+ * @retval PMIC_PARAMETER_ERROR If the handle was invalid.
+ * @retval PMIC_ERROR If the audio input section options could
+ * not be retrieved.
+ */
+PMIC_STATUS pmic_audio_input_get_config(const PMIC_AUDIO_HANDLE handle,
+ PMIC_AUDIO_INPUT_CONFIG * const config);
+
+/*@}*/
+
+/*!
+ * @name Audio Recording Using the Voice CODEC Setup and Configuration APIs
+ * Functions for general setup and configuration of the PMIC Voice CODEC
+ * to perform audio recording.
+ */
+/*@{*/
+
+/*!
+ * @brief Select the microphone inputs to be used for Voice CODEC recording.
+ *
+ * Select left and right microphone inputs for Voice CODEC
+ * recording. It is possible to disable or not use a particular microphone
+ * input channel by specifying NO_MIC as a parameter.
+ *
+ * @param[in] handle Device handle from pmic_audio_open() call.
+ * @param[in] leftChannel Select the left microphone input channel.
+ * @param[in] rightChannel Select the right microphone input channel.
+ *
+ * @retval PMIC_SUCCESS If the microphone input channels were
+ * successfully enabled.
+ * @retval PMIC_PARAMETER_ERROR If the handle or microphone input ports
+ * were invalid.
+ * @retval PMIC_ERROR If the microphone input channels could
+ * not be successfully enabled.
+ */
+PMIC_STATUS pmic_audio_vcodec_set_mic(const PMIC_AUDIO_HANDLE handle,
+ const PMIC_AUDIO_INPUT_PORT leftChannel,
+ const PMIC_AUDIO_INPUT_PORT rightChannel);
+
+/*!
+ * @brief Get the current microphone inputs being used for Voice CODEC
+ * recording.
+ *
+ * Get the left and right microphone inputs currently being
+ * used for Voice CODEC recording.
+ *
+ * @param[in] handle Device handle from pmic_audio_open() call.
+ * @param[out] leftChannel The left microphone input channel.
+ * @param[out] rightChannel The right microphone input channel.
+ *
+ * @retval PMIC_SUCCESS If the microphone input channels were
+ * successfully retrieved.
+ * @retval PMIC_PARAMETER_ERROR If the handle was invalid.
+ * @retval PMIC_ERROR If the microphone input channels could
+ * not be retrieved.
+ */
+PMIC_STATUS pmic_audio_vcodec_get_mic(const PMIC_AUDIO_HANDLE handle,
+ PMIC_AUDIO_INPUT_PORT * const leftChannel,
+ PMIC_AUDIO_INPUT_PORT *
+ const rightChannel);
+
+/*!
+ * @brief Enable/disable the microphone input.
+ *
+ * This function enables/disables the current microphone input channel. The
+ * input amplifier is automatically turned off when the microphone input is
+ * disabled.
+ *
+ * @param[in] handle Device handle from pmic_audio_open() call.
+ * @param[in] leftChannel The left microphone input channel state.
+ * @param[in] rightChannel the right microphone input channel state.
+ *
+ * @retval PMIC_SUCCESS If the microphone input channels were
+ * successfully reconfigured.
+ * @retval PMIC_PARAMETER_ERROR If the handle or microphone input states
+ * were invalid.
+ * @retval PMIC_ERROR If the microphone input channels could
+ * not be reconfigured.
+ */
+PMIC_STATUS pmic_audio_vcodec_set_mic_on_off(const PMIC_AUDIO_HANDLE handle,
+ const PMIC_AUDIO_INPUT_MIC_STATE
+ leftChannel,
+ const PMIC_AUDIO_INPUT_MIC_STATE
+ rightChannel);
+
+/*!
+ * @brief Return the current state of the microphone inputs.
+ *
+ * This function returns the current state (on/off) of the microphone
+ * input channels.
+ *
+ * @param[in] handle Device handle from pmic_audio_open() call.
+ * @param[out] leftChannel The current left microphone input channel
+ * state.
+ * @param[out] rightChannel the current right microphone input channel
+ * state.
+ *
+ * @retval PMIC_SUCCESS If the microphone input channel states
+ * were successfully retrieved.
+ * @retval PMIC_PARAMETER_ERROR If the handle was invalid.
+ * @retval PMIC_ERROR If the microphone input channel states
+ * could not be retrieved.
+ */
+PMIC_STATUS pmic_audio_vcodec_get_mic_on_off(const PMIC_AUDIO_HANDLE handle,
+ PMIC_AUDIO_INPUT_MIC_STATE *
+ const leftChannel,
+ PMIC_AUDIO_INPUT_MIC_STATE *
+ const rightChannel);
+
+/*!
+ * @brief Set the microphone input amplifier mode and gain level.
+ *
+ * This function sets the current microphone input amplifier operating mode
+ * and gain level.
+ *
+ * @param[in] handle Device handle from pmic_audio_open() call.
+ * @param[in] leftChannelMode The left microphone input amplifier mode.
+ * @param[in] leftChannelGain The left microphone input amplifier gain level.
+ * @param[in] rightChannelMode The right microphone input amplifier mode.
+ * @param[in] rightChannelGain The right microphone input amplifier gain
+ * level.
+ *
+ * @retval PMIC_SUCCESS If the microphone input amplifiers were
+ * successfully reconfigured.
+ * @retval PMIC_PARAMETER_ERROR If the handle or microphone input amplifier
+ * modes or gain levels were invalid.
+ * @retval PMIC_ERROR If the microphone input amplifiers could
+ * not be reconfigured.
+ */
+PMIC_STATUS pmic_audio_vcodec_set_record_gain(const PMIC_AUDIO_HANDLE handle,
+ const PMIC_AUDIO_MIC_AMP_MODE
+ leftChannelMode,
+ const PMIC_AUDIO_MIC_GAIN
+ leftChannelGain,
+ const PMIC_AUDIO_MIC_AMP_MODE
+ rightChannelMode,
+ const PMIC_AUDIO_MIC_GAIN
+ rightChannelGain);
+
+/*!
+ * @brief Get the current microphone input amplifier mode and gain level.
+ *
+ * This function gets the current microphone input amplifier operating mode
+ * and gain level.
+ *
+ * @param[in] handle Device handle from pmic_audio_open() call.
+ * @param[out] leftChannelMode The left microphone input amplifier mode.
+ * @param[out] leftChannelGain The left microphone input amplifier gain level.
+ * @param[out] rightChannelMode The right microphone input amplifier mode.
+ * @param[out] rightChannelGain The right microphone input amplifier gain
+ * level.
+ *
+ * @retval PMIC_SUCCESS If the microphone input amplifier modes
+ * and gain levels were successfully
+ * retrieved.
+ * @retval PMIC_PARAMETER_ERROR If the handle was invalid.
+ * @retval PMIC_ERROR If the microphone input amplifier modes
+ * and gain levels could not be retrieved.
+ */
+PMIC_STATUS pmic_audio_vcodec_get_record_gain(const PMIC_AUDIO_HANDLE handle,
+ PMIC_AUDIO_MIC_AMP_MODE *
+ const leftChannelMode,
+ PMIC_AUDIO_MIC_GAIN *
+ const leftChannelGain,
+ PMIC_AUDIO_MIC_AMP_MODE *
+ const rightChannelMode,
+ PMIC_AUDIO_MIC_GAIN *
+ const rightChannelGain);
+
+/*!
+ * @brief Enable a microphone bias circuit.
+ *
+ * This function enables one of the available microphone bias circuits.
+ *
+ * @param[in] handle Device handle from pmic_audio_open() call.
+ * @param[in] biasCircuit The microphone bias circuit to be enabled.
+ *
+ * @retval PMIC_SUCCESS If the microphone bias circuit was
+ * successfully enabled.
+ * @retval PMIC_PARAMETER_ERROR If the handle or selected microphone bias
+ * circuit was invalid.
+ * @retval PMIC_ERROR If the microphone bias circuit could not
+ * be enabled.
+ */
+PMIC_STATUS pmic_audio_vcodec_enable_micbias(const PMIC_AUDIO_HANDLE handle,
+ const PMIC_AUDIO_MIC_BIAS
+ biasCircuit);
+
+/*!
+ * @brief Disable a microphone bias circuit.
+ *
+ * This function disables one of the available microphone bias circuits.
+ *
+ * @param[in] handle Device handle from pmic_audio_open() call.
+ * @param[in] biasCircuit The microphone bias circuit to be disabled.
+ *
+ * @retval PMIC_SUCCESS If the microphone bias circuit was
+ * successfully disabled.
+ * @retval PMIC_PARAMETER_ERROR If the handle or selected microphone bias
+ * circuit was invalid.
+ * @retval PMIC_ERROR If the microphone bias circuit could not
+ * be disabled.
+ */
+PMIC_STATUS pmic_audio_vcodec_disable_micbias(const PMIC_AUDIO_HANDLE handle,
+ const PMIC_AUDIO_MIC_BIAS
+ biasCircuit);
+
+/*@}*/
+
+/*!
+ * @name Audio Playback Using the Voice CODEC Setup and Configuration APIs
+ * Functions for general setup and configuration of the PMIC Voice CODEC
+ * to perform audio playback.
+ */
+/*@{*/
+
+/*!
+ * @brief Configure and enable the Voice CODEC mixer.
+ *
+ * This function configures and enables the Voice CODEC mixer.
+ *
+ * @param[in] handle Device handle from pmic_audio_open() call.
+ * @param[in] rxSecondaryTimeslot The timeslot used for the secondary audio
+ * channel.
+ * @param[in] gainIn The secondary audio channel gain level.
+ * @param[in] gainOut The mixer output gain level.
+ *
+ * @retval PMIC_SUCCESS If the Voice CODEC mixer was successfully
+ * configured and enabled.
+ * @retval PMIC_PARAMETER_ERROR If the handle or mixer configuration
+ * was invalid.
+ * @retval PMIC_ERROR If the Voice CODEC mixer could not be
+ * reconfigured or enabled.
+ */
+PMIC_STATUS pmic_audio_vcodec_enable_mixer(const PMIC_AUDIO_HANDLE handle,
+ const PMIC_AUDIO_VCODEC_TIMESLOT
+ rxSecondaryTimeslot,
+ const PMIC_AUDIO_VCODEC_MIX_IN_GAIN
+ gainIn,
+ const PMIC_AUDIO_VCODEC_MIX_OUT_GAIN
+ gainOut);
+
+/*!
+ * @brief Disable the Voice CODEC mixer.
+ *
+ * This function disables the Voice CODEC mixer.
+ *
+ * @param[in] handle Device handle from pmic_audio_open() call.
+ *
+ * @retval PMIC_SUCCESS If the Voice CODEC mixer was successfully
+ * disabled.
+ * @retval PMIC_PARAMETER_ERROR If the handle was invalid.
+ * @retval PMIC_ERROR If the Voice CODEC mixer could not be
+ * disabled.
+ */
+PMIC_STATUS pmic_audio_vcodec_disable_mixer(const PMIC_AUDIO_HANDLE handle);
+
+/*@}*/
+
+/*!
+ * @name Audio Playback Using the Stereo DAC Setup and Configuration APIs
+ * Functions for general setup and configuration of the PMIC Stereo DAC
+ * to perform audio playback.
+ */
+/*@{*/
+
+/*!
+ * @brief Configure and enable the Stereo DAC mixer.
+ *
+ * This function configures and enables the Stereo DAC mixer.
+ *
+ * @param[in] handle Device handle from pmic_audio_open() call.
+ * @param[in] rxSecondaryTimeslot The timeslot used for the secondary audio
+ * channel.
+ * @param[in] gainIn The secondary audio channel gain level.
+ * @param[in] gainOut The mixer output gain level.
+ *
+ * @retval PMIC_SUCCESS If the Stereo DAC mixer was successfully
+ * configured and enabled.
+ * @retval PMIC_PARAMETER_ERROR If the handle or mixer configuration
+ * was invalid.
+ * @retval PMIC_ERROR If the Stereo DAC mixer could not be
+ * reconfigured or enabled.
+ */
+PMIC_STATUS pmic_audio_stdac_enable_mixer(const PMIC_AUDIO_HANDLE handle,
+ const PMIC_AUDIO_STDAC_TIMESLOTS
+ rxSecondaryTimeslot,
+ const PMIC_AUDIO_STDAC_MIX_IN_GAIN
+ gainIn,
+ const PMIC_AUDIO_STDAC_MIX_OUT_GAIN
+ gainOut);
+
+/*!
+ * @brief Disable the Stereo DAC mixer.
+ *
+ * This function disables the Stereo DAC mixer.
+ *
+ * @param[in] handle Device handle from pmic_audio_open() call.
+ *
+ * @retval PMIC_SUCCESS If the Stereo DAC mixer was successfully
+ * disabled.
+ * @retval PMIC_PARAMETER_ERROR If the handle was invalid.
+ * @retval PMIC_ERROR If the Stereo DAC mixer could not be
+ * disabled.
+ */
+PMIC_STATUS pmic_audio_stdac_disable_mixer(const PMIC_AUDIO_HANDLE handle);
+
+/*@}*/
+
+/*!
+ * @name Audio Output Section Setup and Configuration APIs
+ * Functions for general setup and configuration of the PMIC audio output
+ * section to support playback.
+ */
+/*@{*/
+
+/*!
+ * @brief Select the audio output ports.
+ *
+ * This function selects the audio output ports to be used. This also enables
+ * the appropriate output amplifiers.
+ *
+ * @param[in] handle Device handle from pmic_audio_open() call.
+ * @param[in] port The audio output ports to be used.
+ *
+ * @retval PMIC_SUCCESS If the audio output ports were successfully
+ * acquired.
+ * @retval PMIC_PARAMETER_ERROR If the handle or output ports were
+ * invalid.
+ * @retval PMIC_ERROR If the audio output ports could not be
+ * acquired.
+ */
+PMIC_STATUS pmic_audio_output_set_port(const PMIC_AUDIO_HANDLE handle,
+ const PMIC_AUDIO_OUTPUT_PORT port);
+
+/*!
+ * @brief Deselect/disable the audio output ports.
+ *
+ * This function disables the audio output ports that were previously enabled
+ * by calling pmic_audio_output_set_port().
+ *
+ * @param[in] handle Device handle from pmic_audio_open() call.
+ * @param[in] port The audio output ports to be disabled.
+ *
+ * @retval PMIC_SUCCESS If the audio output ports were successfully
+ * disabled.
+ * @retval PMIC_PARAMETER_ERROR If the handle or output ports were
+ * invalid.
+ * @retval PMIC_ERROR If the audio output ports could not be
+ * disabled.
+ */
+PMIC_STATUS pmic_audio_output_clear_port(const PMIC_AUDIO_HANDLE handle,
+ const PMIC_AUDIO_OUTPUT_PORT port);
+
+/*!
+ * @brief Get the current audio output ports.
+ *
+ * This function retrieves the audio output ports that are currently being
+ * used.
+ *
+ * @param[in] handle Device handle from pmic_audio_open() call.
+ * @param[out] port The audio output ports currently being used.
+ *
+ * @retval PMIC_SUCCESS If the audio output ports were successfully
+ * retrieved.
+ * @retval PMIC_PARAMETER_ERROR If the handle was invalid.
+ * @retval PMIC_ERROR If the audio output ports could not be
+ * retrieved.
+ */
+PMIC_STATUS pmic_audio_output_get_port(const PMIC_AUDIO_HANDLE handle,
+ PMIC_AUDIO_OUTPUT_PORT * const port);
+
+/*!
+ * @brief Set the gain level for the external stereo inputs.
+ *
+ * This function sets the gain levels for the external stereo inputs.
+ *
+ * @param[in] handle Device handle from pmic_audio_open() call.
+ * @param[in] gain The external stereo input gain level.
+ *
+ * @retval PMIC_SUCCESS If the gain level was successfully set.
+ * @retval PMIC_PARAMETER_ERROR If the handle or gain level was invalid.
+ * @retval PMIC_ERROR If the gain level could not be set.
+ */
+PMIC_STATUS pmic_audio_output_set_stereo_in_gain(const PMIC_AUDIO_HANDLE handle,
+ const PMIC_AUDIO_STEREO_IN_GAIN
+ gain);
+
+/*!
+ * @brief Get the current gain level for the external stereo inputs.
+ *
+ * This function retrieves the current gain levels for the external stereo
+ * inputs.
+ *
+ * @param[in] handle Device handle from pmic_audio_open() call.
+ * @param[out] gain The current external stereo input gain
+ * level.
+ *
+ * @retval PMIC_SUCCESS If the gain level was successfully
+ * retrieved.
+ * @retval PMIC_PARAMETER_ERROR If the handle was invalid.
+ * @retval PMIC_ERROR If the gain level could not be retrieved.
+ */
+PMIC_STATUS pmic_audio_output_get_stereo_in_gain(const PMIC_AUDIO_HANDLE handle,
+ PMIC_AUDIO_STEREO_IN_GAIN *
+ const gain);
+
+/*!
+ * @brief Set the output PGA gain level.
+ *
+ * This function sets the audio output PGA gain level.
+ *
+ * @param[in] handle Device handle from pmic_audio_open() call.
+ * @param[in] gain The output PGA gain level.
+ *
+ * @retval PMIC_SUCCESS If the gain level was successfully set.
+ * @retval PMIC_PARAMETER_ERROR If the handle or gain level was invalid.
+ * @retval PMIC_ERROR If the gain level could not be set.
+ */
+PMIC_STATUS pmic_audio_output_set_pgaGain(const PMIC_AUDIO_HANDLE handle,
+ const PMIC_AUDIO_OUTPUT_PGA_GAIN
+ gain);
+
+/*!
+ * @brief Get the output PGA gain level.
+ *
+ * This function retrieves the current audio output PGA gain level.
+ *
+ * @param[in] handle Device handle from pmic_audio_open() call.
+ * @param[out] gain The current output PGA gain level.
+ *
+ * @retval PMIC_SUCCESS If the gain level was successfully
+ * retrieved.
+ * @retval PMIC_PARAMETER_ERROR If the handle was invalid.
+ * @retval PMIC_ERROR If the gain level could not be retrieved.
+ */
+PMIC_STATUS pmic_audio_output_get_pgaGain(const PMIC_AUDIO_HANDLE handle,
+ PMIC_AUDIO_OUTPUT_PGA_GAIN *
+ const gain);
+
+/*!
+ * @brief Enable the output mixer.
+ *
+ * This function enables the output mixer for the audio stream that
+ * corresponds to the current handle (i.e., the Voice CODEC, Stereo DAC, or
+ * the external stereo inputs).
+ *
+ * @param[in] handle Device handle from pmic_audio_open() call.
+ *
+ * @retval PMIC_SUCCESS If the mixer was successfully enabled.
+ * @retval PMIC_PARAMETER_ERROR If the handle was invalid.
+ * @retval PMIC_ERROR If the mixer could not be enabled.
+ */
+PMIC_STATUS pmic_audio_output_enable_mixer(const PMIC_AUDIO_HANDLE handle);
+
+/*!
+ * @brief Disable the output mixer.
+ *
+ * This function disables the output mixer for the audio stream that
+ * corresponds to the current handle (i.e., the Voice CODEC, Stereo DAC, or
+ * the external stereo inputs).
+ *
+ * @param[in] handle Device handle from pmic_audio_open() call.
+ *
+ * @retval PMIC_SUCCESS If the mixer was successfully disabled.
+ * @retval PMIC_PARAMETER_ERROR If the handle was invalid.
+ * @retval PMIC_ERROR If the mixer could not be disabled.
+ */
+PMIC_STATUS pmic_audio_output_disable_mixer(const PMIC_AUDIO_HANDLE handle);
+
+/*!
+ * @brief Configure and enable the output balance amplifiers.
+ *
+ * This function configures and enables the output balance amplifiers.
+ *
+ * @param[in] handle Device handle from pmic_audio_open() call.
+ * @param[in] leftGain The desired left channel gain level.
+ * @param[in] rightGain The desired right channel gain level.
+ *
+ * @retval PMIC_SUCCESS If the output balance amplifiers were
+ * successfully configured and enabled.
+ * @retval PMIC_PARAMETER_ERROR If the handle or gain levels were invalid.
+ * @retval PMIC_ERROR If the output balance amplifiers could not
+ * be reconfigured or enabled.
+ */
+PMIC_STATUS pmic_audio_output_set_balance(const PMIC_AUDIO_HANDLE handle,
+ const PMIC_AUDIO_OUTPUT_BALANCE_GAIN
+ leftGain,
+ const PMIC_AUDIO_OUTPUT_BALANCE_GAIN
+ rightGain);
+
+/*!
+ * @brief Get the current output balance amplifier gain levels.
+ *
+ * This function retrieves the current output balance amplifier gain levels.
+ *
+ * @param[in] handle Device handle from pmic_audio_open() call.
+ * @param[out] leftGain The current left channel gain level.
+ * @param[out] rightGain The current right channel gain level.
+ *
+ * @retval PMIC_SUCCESS If the output balance amplifier gain levels
+ * were successfully retrieved.
+ * @retval PMIC_PARAMETER_ERROR If the handle was invalid.
+ * @retval PMIC_ERROR If the output balance amplifier gain levels
+ * could be retrieved.
+ */
+PMIC_STATUS pmic_audio_output_get_balance(const PMIC_AUDIO_HANDLE handle,
+ PMIC_AUDIO_OUTPUT_BALANCE_GAIN *
+ const leftGain,
+ PMIC_AUDIO_OUTPUT_BALANCE_GAIN *
+ const rightGain);
+
+/*!
+ * @brief Configure and enable the output mono adder.
+ *
+ * This function configures and enables the output mono adder.
+ *
+ * @param[in] handle Device handle from pmic_audio_open() call.
+ * @param[in] mode The desired mono adder operating mode.
+ *
+ * @retval PMIC_SUCCESS If the mono adder was successfully
+ * configured and enabled.
+ * @retval PMIC_PARAMETER_ERROR If the handle or mono adder mode was
+ * invalid.
+ * @retval PMIC_ERROR If the mono adder could not be reconfigured
+ * or enabled.
+ */
+PMIC_STATUS pmic_audio_output_enable_mono_adder(const PMIC_AUDIO_HANDLE handle,
+ const PMIC_AUDIO_MONO_ADDER_MODE
+ mode);
+
+/*!
+ * @brief Disable the output mono adder.
+ *
+ * This function disables the output mono adder.
+ *
+ * @param[in] handle Device handle from pmic_audio_open() call.
+ *
+ * @retval PMIC_SUCCESS If the mono adder was successfully
+ * disabled.
+ * @retval PMIC_PARAMETER_ERROR If the handle was invalid.
+ * @retval PMIC_ERROR If the mono adder could not be disabled.
+ */
+PMIC_STATUS pmic_audio_output_disable_mono_adder(const PMIC_AUDIO_HANDLE
+ handle);
+
+/*!
+ * @brief Configure the mono adder output gain level.
+ *
+ * This function configures the mono adder output amplifier gain level.
+ *
+ * @param[in] handle Device handle from pmic_audio_open() call.
+ * @param[in] gain The desired output gain level.
+ *
+ * @retval PMIC_SUCCESS If the mono adder output amplifier gain
+ * level was successfully set.
+ * @retval PMIC_PARAMETER_ERROR If the handle or gain level was invalid.
+ * @retval PMIC_ERROR If the mono adder output amplifier gain
+ * level could not be reconfigured.
+ */
+PMIC_STATUS pmic_audio_output_set_mono_adder_gain(const PMIC_AUDIO_HANDLE
+ handle,
+ const
+ PMIC_AUDIO_MONO_ADDER_OUTPUT_GAIN
+ gain);
+
+/*!
+ * @brief Get the current mono adder output gain level.
+ *
+ * This function retrieves the current mono adder output amplifier gain level.
+ *
+ * @param[in] handle Device handle from pmic_audio_open() call.
+ * @param[out] gain The current output gain level.
+ *
+ * @retval PMIC_SUCCESS If the mono adder output amplifier gain
+ * level was successfully retrieved.
+ * @retval PMIC_PARAMETER_ERROR If the handle was invalid.
+ * @retval PMIC_ERROR If the mono adder output amplifier gain
+ * level could not be retrieved.
+ */
+PMIC_STATUS pmic_audio_output_get_mono_adder_gain(const PMIC_AUDIO_HANDLE
+ handle,
+ PMIC_AUDIO_MONO_ADDER_OUTPUT_GAIN
+ * const gain);
+
+/*!
+ * @brief Set various audio output section options.
+ *
+ * This function sets one or more audio output section configuration
+ * options. The currently supported options include whether to disable
+ * the non-inverting mono speaker output, enabling the loudspeaker common
+ * bias circuit, enabling detection of headset insertion/removal, and
+ * whether to automatically disable the headset amplifiers when a headset
+ * insertion/removal has been detected.
+ *
+ * @param[in] handle Device handle from pmic_audio_open() call.
+ * @param[in] config The desired audio output section
+ * configuration options to be set.
+ *
+ * @retval PMIC_SUCCESS If the desired configuration options were
+ * all successfully set.
+ * @retval PMIC_PARAMETER_ERROR If the handle or configuration options
+ * were invalid.
+ * @retval PMIC_ERROR If the desired configuration options
+ * could not be set.
+ */
+PMIC_STATUS pmic_audio_output_set_config(const PMIC_AUDIO_HANDLE handle,
+ const PMIC_AUDIO_OUTPUT_CONFIG config);
+
+/*!
+ * @brief Clear various audio output section options.
+ *
+ * This function clears one or more audio output section configuration
+ * options.
+ *
+ * @param[in] handle Device handle from pmic_audio_open() call.
+ * @param[in] config The desired audio output section
+ * configuration options to be cleared.
+ *
+ * @retval PMIC_SUCCESS If the desired configuration options were
+ * all successfully cleared.
+ * @retval PMIC_PARAMETER_ERROR If the handle or configuration options
+ * were invalid.
+ * @retval PMIC_ERROR If the desired configuration options
+ * could not be cleared.
+ */
+PMIC_STATUS pmic_audio_output_clear_config(const PMIC_AUDIO_HANDLE handle,
+ const PMIC_AUDIO_OUTPUT_CONFIG
+ config);
+
+/*!
+ * @brief Get the current audio output section options.
+ *
+ * This function retrieves the current audio output section configuration
+ * option settings.
+ *
+ * @param[in] handle Device handle from pmic_audio_open() call.
+ * @param[out] config The current audio output section
+ * configuration option settings.
+ *
+ * @retval PMIC_SUCCESS If the current configuration options were
+ * successfully retrieved.
+ * @retval PMIC_PARAMETER_ERROR If the handle was invalid.
+ * @retval PMIC_ERROR If the current configuration options
+ * could not be retrieved.
+ */
+PMIC_STATUS pmic_audio_output_get_config(const PMIC_AUDIO_HANDLE handle,
+ PMIC_AUDIO_OUTPUT_CONFIG *
+ const config);
+
+/*!
+ * @brief Enable the phantom ground circuit that is used to help identify
+ * the type of headset that has been inserted.
+ *
+ * This function enables the phantom ground circuit that is used to help
+ * identify the type of headset (e.g., stereo or mono) that has been inserted.
+ *
+ * @param[in] handle Device handle from pmic_audio_open() call.
+ *
+ * @retval PMIC_SUCCESS If the phantom ground circuit was
+ * successfully enabled.
+ * @retval PMIC_PARAMETER_ERROR If the handle was invalid.
+ * @retval PMIC_ERROR If the phantom ground circuit could not
+ * be enabled.
+ */
+PMIC_STATUS pmic_audio_output_enable_phantom_ground(void);
+
+/*!
+ * @brief Disable the phantom ground circuit that is used to help identify
+ * the type of headset that has been inserted.
+ *
+ * This function disables the phantom ground circuit that is used to help
+ * identify the type of headset (e.g., stereo or mono) that has been inserted.
+ *
+ * @param[in] handle Device handle from pmic_audio_open() call.
+ *
+ * @retval PMIC_SUCCESS If the phantom ground circuit was
+ * successfully disabled.
+ * @retval PMIC_PARAMETER_ERROR If the handle was invalid.
+ * @retval PMIC_ERROR If the phantom ground circuit could not
+ * be disabled.
+ */
+PMIC_STATUS pmic_audio_output_disable_phantom_ground(void);
+
+/*!
+ * @brief Enable/Disable fm output
+ *
+ * This function enables/disables the fm output.
+ *
+ * @param[in] enable True to enable and false to disable
+ *
+ * @retval PMIC_SUCCESS If the fm output was
+ * successfully enable or disabled
+ * @retval PMIC_ERROR If the operation fails
+ */
+PMIC_STATUS pmic_audio_fm_output_enable(bool enable);
+
+/*@}*/
+
+#endif /* __KERNEL__ */
+
+#endif /* __ASM_ARCH_MXC_PMIC_AUDIO_H__ */
diff --git a/arch/arm/plat-mxc/include/mach/pmic_convity.h b/arch/arm/plat-mxc/include/mach/pmic_convity.h
new file mode 100644
index 000000000000..b88bb54bad26
--- /dev/null
+++ b/arch/arm/plat-mxc/include/mach/pmic_convity.h
@@ -0,0 +1,873 @@
+/*
+ * Copyright 2004-2009 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 __ASM_ARCH_MXC_PMIC_CONVITY_H__
+#define __ASM_ARCH_MXC_PMIC_CONVITY_H__
+
+/*!
+ * @defgroup PMIC_CONNECTIVITY PMIC Connectivity Driver
+ * @ingroup PMIC_DRVRS
+ */
+
+/*!
+ * @file arch-mxc/pmic_convity.h
+ * @brief External definitions for the PMIC Connectivity Client driver.
+ *
+ * The PMIC Connectivity driver and this API were developed to support the
+ * external connectivity capabilities of several power management ICs that
+ * are available from Freescale Semiconductor, Inc.
+ *
+ * The following operating modes, in terms of external connectivity, are
+ * supported:
+ *
+ *
+ *
+ * @ingroup PMIC_CONNECTIVITY
+ */
+
+#include <linux/pmic_status.h>
+#include <linux/pmic_external.h>
+
+/***************************************************************************
+ * TYPEDEFS AND ENUMERATIONS *
+ ***************************************************************************/
+
+/*!
+ * @name General Setup and Configuration Typedefs and Enumerations
+ * Typedefs and enumerations that are used for initial access to and
+ * configuration of the PMIC Connectivity hardware.
+ */
+/*@{*/
+
+#define DEBUG_CONVITY
+
+/*!
+ * @typedef PMIC_CONVITY_HANDLE
+ * @brief Define typedef for a handle to the PMIC Connectivity hardware.
+ *
+ * Define a "handle" that is returned when the PMIC Connectivity hardware
+ * is opened. This handle grants exclusive access to the PMIC Connectivity
+ * hardware and must be used in all subsequent function calls. When access
+ * to the PMIC Connectivity hardware is no longer required, then a close
+ * operation must be done with this handle. The handle is no longer valid
+ * if the close operation was successful.
+ */
+typedef long PMIC_CONVITY_HANDLE;
+
+/*!
+ * @enum PMIC_CONVITY_MODE
+ * @brief Select the main Connectivity operating mode.
+ *
+ * Defines all possible PMIC Connectivity main operating modes. Only one of
+ * these modes can be active at a time.
+ */
+typedef enum {
+ USB, /*!< Select USB mode (this is also the Reset/Default
+ mode). */
+ RS232, /*!< Select RS-232 mode. for SC55112 */
+ RS232_1, /*!< Select RS-232_1 mode. */
+ RS232_2, /*!< Select RS-232_2 mode. */
+ CEA936_MONO, /*!< Select CE-936 Mono mode . */
+ CEA936_STEREO, /*!< Select CE-936 Stereo mode . */
+ CEA936_TEST_RIGHT, /*!< Select CE-936 Right Channel Test mode
+ . */
+ CEA936_TEST_LEFT /*!< Select CE-936 Left Channel Test mode
+ . */
+} PMIC_CONVITY_MODE;
+
+/*!
+ * @enum PMIC_CONVITY_EVENTS
+ * @brief Identify the connectivity events that have been detected and should
+ * be handled.
+ *
+ * Defines all possible PMIC Connectivity events. Multiple events may be
+ * selected when defining a mask.
+ */
+typedef enum {
+ USB_DETECT_4V4_RISE = 1, /*!< Detected 4.4V rising edge. */
+ USB_DETECT_4V4_FALL = 2, /*!< Detected 4.4V falling edge. */
+ USB_DETECT_2V0_RISE = 4, /*!< Detected 2.0V rising edge. */
+ USB_DETECT_2V0_FALL = 8, /*!< Detected 2.0V falling edge. */
+ USB_DETECT_0V8_RISE = 16, /*!< Detected 0.8V rising edge. */
+ USB_DETECT_0V8_FALL = 32, /*!< Detected 0.8V falling edge. */
+ USB_DETECT_MINI_A = 64, /*!< Detected USB mini A plug. */
+ USB_DETECT_MINI_B = 128, /*!< Detected USB mini B plug. */
+ USB_DETECT_NON_USB_ACCESSORY = 256, /*!< Detected a non-USB connection
+ . */
+ USB_DETECT_FACTORY_MODE = 512, /*!< Detected a factory-mode
+ connection . */
+ USB_DP_HI = 1024,
+
+ USB_DM_HI = 2048
+} PMIC_CONVITY_EVENTS;
+
+/*!
+ * @typedef PMIC_CONVITY_CALLBACK
+ * @brief Typedef for PMIC Connectivity event notification callback function.
+ *
+ * Define a typedef for the PMIC Connectivity event notification callback
+ * function. The signalled events are passed to the function as the first
+ * argument. The callback function should then process whatever events it
+ * can and then return the set of unhandled events (if any).
+ */
+typedef void (*PMIC_CONVITY_CALLBACK) (const PMIC_CONVITY_EVENTS event);
+
+/*@}*/
+
+/*!
+ * @name USB and USB On-The-Go Mode-specific Typedefs and Enumerations
+ * Typedefs and enumerations that are used only for setting up and controlling
+ * the USB and USB On-The-Go modes of operation.
+ */
+/*@{*/
+
+/*!
+ * @enum PMIC_CONVITY_USB_DEVICE_TYPE
+ * @brief Select the USB device type (either A or B).
+ *
+ * Defines all possible USB device types. This must match the physical
+ * connector being used.
+ */
+typedef enum {
+ USB_A_DEVICE,
+ USB_B_DEVICE
+} PMIC_CONVITY_USB_DEVICE_TYPE;
+
+/*!
+ * @enum PMIC_CONVITY_USB_SPEED
+ * @brief Select the USB transceiver operating speed.
+ *
+ * Defines all possible USB transceiver operating speeds. Only one
+ * speed setting may be used at a time.
+ */
+typedef enum {
+ USB_LOW_SPEED, /*!< Select 1.5 Mbps. */
+ USB_FULL_SPEED, /*!< Select 12 Mbps. */
+ USB_HIGH_SPEED /*!< Select 480 Mbps <b>(currently
+ not supported)</b>. */
+} PMIC_CONVITY_USB_SPEED;
+
+/*!
+ * @enum PMIC_CONVITY_USB_MODE
+ * @brief Select the USB transceiver operating mode.
+ *
+ * Defines all possible USB transceiver operating modes. Only one
+ * mode may be used at a time. The selected mode, in combination with
+ * the USB bus speed, determines the selection of pull-up and pull-down
+ * resistors.
+ */
+typedef enum {
+ USB_HOST,
+ USB_PERIPHERAL
+} PMIC_CONVITY_USB_MODE;
+
+/*!
+ * @enum PMIC_CONVITY_USB_POWER_IN
+ * @brief Select the USB transceiver's power regulator input source.
+ *
+ * Defines all possible input power sources for the USB transceiver power
+ * regulator. Only one power supply source may be selected at a time.
+ */
+typedef enum {
+
+ USB_POWER_INTERNAL_BOOST, /*!< Select internal power source
+ with boost. */
+
+ USB_POWER_VBUS, /*!< Select VBUS power source. */
+
+ USB_POWER_INTERNAL /*!< Select internal power source
+ . */
+} PMIC_CONVITY_USB_POWER_IN;
+
+/*!
+ * @enum PMIC_CONVITY_USB_POWER_OUT
+ * @brief Select the USB transceiver power regulator output voltage.
+ *
+ * Defines all possible output voltages for the USB transceiver power
+ * regulator. Only one power output voltage level may be selected at
+ * a time.
+ */
+typedef enum {
+ USB_POWER_2V775, /*!< Select 2.775V output voltage
+ . */
+ USB_POWER_3V3 /*!< Select 3.3V output voltage. */
+} PMIC_CONVITY_USB_POWER_OUT;
+
+/*!
+ * @enum PMIC_CONVITY_USB_TRANSCEIVER_MODE
+ * @brief Select the USB transceiver operating mode.
+ *
+ * Defines all valid USB transceiver operating modes. Only one of the
+ * following USB transceiver modes may be selected at a time.
+ */
+typedef enum {
+ USB_TRANSCEIVER_OFF, /*!< USB transceiver currently off
+ . */
+ USB_SINGLE_ENDED_UNIDIR, /*!< Select Single-ended
+ unidirectional transmit mode. */
+ USB_SINGLE_ENDED_UNIDIR_TX, /*!< Select Single-ended
+ unidirectional transmit mode. */
+ USB_SINGLE_ENDED_UNIDIR_RX, /*!< Select Single-ended
+ unidirectional receive mode. */
+ USB_SINGLE_ENDED_BIDIR, /*!< Select Single-ended
+ bidirectional transmit mode. */
+ USB_SINGLE_ENDED_LOW, /*!< Select USB SE0 mode. */
+ USB_DIFFERENTIAL_UNIDIR_TX, /*!< Select Differential
+ unidirectional transmit mode
+ . */
+ USB_DIFFERENTIAL_UNIDIR, /*!< Select Differential
+ unidirectional transmit mode
+ . */
+
+ USB_DIFFERENTIAL_UNIDIR_RX, /*!< Select Differential
+ unidirectional receive mode. */
+ USB_DIFFERENTIAL_BIDIR, /*!< Select Differential
+ bidirectional transmit mode
+ */
+ USB_SUSPEND_ON, /*!< Select Suspend mode. */
+ USB_SUSPEND_OFF, /*!< Terminate Suspend mode. */
+ USB_OTG_SRP_DLP_START, /*!< Start USB On-The-Go Session
+ Request Protocol using Data
+ Line Pulsing. */
+ USB_OTG_SRP_DLP_STOP /*!< Terminate USB On-The-Go Session
+ Request Protocol using Data
+ Line Pulsing. */
+} PMIC_CONVITY_USB_TRANSCEIVER_MODE;
+
+/*!
+ * @enum PMIC_CONVITY_USB_OTG_CONFIG
+ * @brief Select the USB On-The-Go configuration options.
+ *
+ * Defines all possible USB On-The-Go configuration options. Multiple
+ * configuration options may be selected at the same time. However, only one
+ * VBUS current limit may be selected at a time. Selecting more than one
+ * VBUS current limit will result in undefined and implementation-dependent
+ * behavior.
+ */
+typedef enum {
+ USB_OTG_SE0CONN = 0x00001, /*!< Enable automatic
+ connection of a pull-up
+ resistor to VUSB when the
+ SE0 condition is detected. */
+ USB_OTG_DLP_SRP = 0x00002, /*!< Enable use of the hardware
+ timer to control the
+ duration of the data line
+ pulse during the session
+ request protocol. */
+ USB_PULL_OVERRIDE = 0x00004, /*!< Enable automatic disconnect
+ of pull-up and pull-down
+ resistors when transmitter
+ is enabled. */
+
+ USB_DP150K_PU = 0x00008,
+
+ USB_VBUS_CURRENT_LIMIT_HIGH = 0x00010, /*!< Select current limit to 200mA
+ for VBUS regulator. */
+ USB_VBUS_CURRENT_LIMIT_LOW = 0x00020, /*!< Select low current limit
+ for VBUS regulator. */
+ USB_VBUS_CURRENT_LIMIT_LOW_10MS = 0x00040, /*!< Select low current limit
+ for VBUS regulator for
+ 10 ms . */
+ USB_VBUS_CURRENT_LIMIT_LOW_20MS = 0x00080, /*!< Select low current limit
+ for VBUS regulator for
+ 20 ms . */
+ USB_VBUS_CURRENT_LIMIT_LOW_30MS = 0x00100, /*!< Select low current limit
+ for VBUS regulator for
+ 30 ms . */
+ USB_VBUS_CURRENT_LIMIT_LOW_40MS = 0x00200, /*!< Select low current limit
+ for VBUS regulator for
+ 40 ms . */
+ USB_VBUS_CURRENT_LIMIT_LOW_50MS = 0x00400, /*!< Select low current limit
+ for VBUS regulator for
+ 50 ms . */
+ USB_VBUS_CURRENT_LIMIT_LOW_60MS = 0x00800, /*!< Select low current limit
+ for VBUS regulator for
+ 60 ms . */
+
+ USB_VBUS_PULLDOWN = 0x01000, /*!< Enable VBUS pull-down. */
+
+ USB_USBCNTRL = 0x02000,
+
+ USB_UDP_PD = 0x04000,
+
+ USB_UDM_PD = 0x08000,
+
+ USB_PU = 0x10000,
+
+ USBXCVREN = 0x20000
+} PMIC_CONVITY_USB_OTG_CONFIG;
+/*@}*/
+
+/*!
+ * @name RS-232 Mode-specific Typedefs and Enumerations
+ * Typedefs and enumerations that are used only for setting up and controlling
+ * the RS-232 mode of operation.
+ */
+/*@{*/
+
+/*!
+ * @enum PMIC_CONVITY_RS232_EXTERNAL
+ * @brief Select the RS-232 transceiver external connections.
+ *
+ * Defines all valid RS-232 transceiver external RX/TX connection options.
+ * Only one connection mode may be selected at a time.
+ */
+typedef enum {
+ RS232_TX_UDM_RX_UDP, /*!< Select RS-232 TX on UDM */
+ RS232_TX_UDP_RX_UDM, /*!< Select RS-232 TX on UDP
+ . */
+ RS232_TX_RX_EXTERNAL_DEFAULT /*!< Use power on default. */
+} PMIC_CONVITY_RS232_EXTERNAL;
+
+/*!
+ * @enum PMIC_CONVITY_RS232_INTERNAL
+ * @brief Select the RS-232 transceiver internal connections.
+ *
+ * Defines all valid RS-232 transceiver internal RX/TX connection options.
+ * Only one connection mode can be selected at a time.
+ */
+typedef enum {
+ RS232_TX_USE0VM_RX_UDATVP, /*!< Select RS-232 TX from USE0VM
+ . */
+ RS232_TX_UDATVP_RX_URXVM, /*!< Select RS-232 TX from UDATVP
+ . */
+ RS232_TX_UTXDI_RX_URXDO, /*!< Select RS-232 TX from UTXDI
+ . */
+ RS232_TX_RX_INTERNAL_DEFAULT /*!< Use power on default. */
+} PMIC_CONVITY_RS232_INTERNAL;
+
+/*@}*/
+
+/*!
+ * @name CEA-936 Mode-specific Typedefs and Enumerations
+ * Typedefs and enumerations that are used only for setting up and controlling
+ * the CEA-936 mode of operation.
+ */
+/*@{*/
+
+/*!
+ * @enum PMIC_CONVITY_CEA936_EXIT_SIGNAL
+ * @brief Select the CEA-936 mode exit signal.
+ *
+ * Defines all valid CEA-936 connection termination signals. Only one
+ * termination signal can be selected at a time.
+ */
+typedef enum {
+ CEA936_UID_NO_PULLDOWN, /*!< No UID pull-down . */
+ CEA936_UID_PULLDOWN_6MS, /*!< UID pull-down for 6 ms (+/-2 ms)
+ . */
+ CEA936_UID_PULLDOWN, /*!< UID pulled down . */
+ CEA936_UDMPULSE /*!< UDM pulsed . */
+} PMIC_CONVITY_CEA936_EXIT_SIGNAL;
+
+/*@}*/
+
+/***************************************************************************
+ * PMIC API DEFINITIONS *
+ ***************************************************************************/
+
+/*!
+ * @name General Setup and Configuration APIs
+ * Functions for general setup and configuration of the PMIC Connectivity
+ * hardware.
+ */
+/*@{*/
+
+/*!
+ * @brief Request exclusive access to the PMIC Connectivity hardware.
+ *
+ * Attempt to open and gain exclusive access to the PMIC Connectivity
+ * hardware. An initial operating mode (e.g., USB or RS-232) must also
+ * be specified.
+ *
+ * If the open request is successful, then a numeric handle is returned
+ * and this handle must be used in all subsequent function calls. The
+ * same handle must also be used in the close call when use of the PMIC
+ * connectivity hardware is no longer required.
+ *
+ * The open request will fail if another thread has already obtained the
+ * device handle and has not yet called pmic_convity_close() with it.
+ *
+ * @param handle Device handle to be used for subsequent PMIC
+ * Connectivity API calls.
+ * @param mode Initial connectivity operating mode.
+ *
+ * @retval PMIC_SUCCESS If the open request was successful
+ * @retval PMIC_ERROR If the connectivity hardware cannot be opened.
+ */
+PMIC_STATUS pmic_convity_open(PMIC_CONVITY_HANDLE * const handle,
+ const PMIC_CONVITY_MODE mode);
+
+/*!
+ * @brief Terminate further access to the PMIC Connectivity hardware.
+ *
+ * Terminate further access to the PMIC Connectivity hardware. This also
+ * allows another thread to successfully call pmic_convity_open() to gain
+ * access.
+ *
+ * @param handle Device handle from open() call.
+ *
+ * @retval PMIC_SUCCESS If the close request was successful.
+ * @retval PMIC_PARAMETER_ERROR If the handle is invalid.
+ */
+PMIC_STATUS pmic_convity_close(const PMIC_CONVITY_HANDLE handle);
+
+/*!
+ * @brief Set the PMIC Connectivity main operating mode.
+ *
+ * Change the current operating mode of the PMIC Connectivity hardware.
+ * The available connectivity operating modes are hardware-dependent and
+ * consists of one or more of the following: USB (including USB On-the-Go),
+ * RS-232, and CEA-936. Requesting an operating mode that is not supported
+ * by the PMIC hardware will return PMIC_NOT_SUPPORTED.
+ *
+ * @param handle Device handle from open() call.
+ * @param mode Desired operating mode.
+ *
+ * @retval PMIC_SUCCESS If the requested mode was successfully set.
+ * @retval PMIC_PARAMETER_ERROR If the handle is invalid.
+ * @retval PMIC_NOT_SUPPORTED If the PMIC hardware does not support
+ * the desired operating mode.
+ */
+PMIC_STATUS pmic_convity_set_mode(const PMIC_CONVITY_HANDLE handle,
+ const PMIC_CONVITY_MODE mode);
+
+/*!
+ * @brief Get the current PMIC Connectivity main operating mode.
+ *
+ * Get the current operating mode for the PMIC Connectivity hardware.
+ *
+ * @param handle Device handle from open() call.
+ * @param mode The current PMIC Connectivity operating mode.
+ *
+ * @retval PMIC_SUCCESS If the requested mode was successfully set.
+ * @retval PMIC_PARAMETER_ERROR If the handle is invalid.
+ */
+PMIC_STATUS pmic_convity_get_mode(const PMIC_CONVITY_HANDLE handle,
+ PMIC_CONVITY_MODE * const mode);
+
+/*!
+ * @brief Reset the Connectivity hardware to it's power on state.
+ *
+ * Restore all registers to the initial power-on/reset state.
+ *
+ * @param handle Device handle from open() call.
+ *
+ * @retval PMIC_SUCCESS If the reset was successful.
+ * @retval PMIC_PARAMETER_ERROR If the handle is invalid.
+ */
+PMIC_STATUS pmic_convity_reset(const PMIC_CONVITY_HANDLE handle);
+
+/*!
+ * @brief Set the Connectivity callback function.
+ *
+ * Register a callback function that will be used to signal PMIC Connectivity
+ * events. For example, the USB subsystem should register a callback function
+ * in order to be notified of device connect/disconnect events. Note, however,
+ * that non-USB events may also be signalled depending upon the PMIC hardware
+ * capabilities. Therefore, the callback function must be able to properly
+ * handle all of the possible events if support for non-USB peripherals is
+ * also to be included.
+ *
+ * @param handle Device handle from open() call.
+ * @param func A pointer to the callback function.
+ * @param eventMask A mask selecting events to be notified.
+ *
+ * @retval PMIC_SUCCESS If the callback was successfully registered.
+ * @retval PMIC_PARAMETER_ERROR If the handle or the eventMask is invalid.
+ */
+PMIC_STATUS pmic_convity_set_callback(const PMIC_CONVITY_HANDLE handle,
+ const PMIC_CONVITY_CALLBACK func,
+ const PMIC_CONVITY_EVENTS eventMask);
+
+/*!
+ * @brief Deregisters the existing Connectivity callback function.
+ *
+ * Deregister the callback function that was previously registered by calling
+ * pmic_convity_set_callback().
+ *
+ * @param handle Device handle from open() call.
+ *
+ * @retval PMIC_SUCCESS If the callback was successfully deregistered.
+ * @retval PMIC_PARAMETER_ERROR If the handle is invalid.
+ */
+PMIC_STATUS pmic_convity_clear_callback(const PMIC_CONVITY_HANDLE handle);
+
+/*!
+ * @brief Get the current Connectivity callback function settings.
+ *
+ * Get the current callback function and event mask.
+ *
+ * @param handle Device handle from open() call.
+ * @param func The current callback function.
+ * @param eventMask The current event selection mask.
+ *
+ * @retval PMIC_SUCCESS If the callback information was successfully
+ * retrieved.
+ * @retval PMIC_PARAMETER_ERROR If the handle is invalid.
+ */
+PMIC_STATUS pmic_convity_get_callback(const PMIC_CONVITY_HANDLE handle,
+ PMIC_CONVITY_CALLBACK * const func,
+ PMIC_CONVITY_EVENTS * const eventMask);
+
+/*@}*/
+
+/***************************************************************************/
+
+/*!
+ * @name USB and USB On-The-Go APIs
+ * USB Connectivity mode-specific configuration and setup functions.
+ */
+/*@{*/
+
+/*!
+ * @brief Set the USB transceiver's operating speed.
+ *
+ * Set the USB transceiver speed.
+ *
+ * @param handle Device handle from open() call.
+ * @param speed The desired USB transceiver speed.
+ *
+ * @retval PMIC_SUCCESS If the transceiver speed was successfully
+ * set.
+ * @retval PMIC_PARAMETER_ERROR If the handle is invalid.
+ * @retval PMIC_NOT_SUPPORTED If the high speed (480 Mbps) mode is
+ * requested.
+ */
+PMIC_STATUS pmic_convity_usb_set_speed(const PMIC_CONVITY_HANDLE handle,
+ const PMIC_CONVITY_USB_SPEED speed);
+
+/*!
+ * This function enables/disables VUSB and VBUS output.
+ * This API configures the VUSBEN and VBUSEN bits of USB register
+ *
+ * @param handle Device handle from open() call.
+ * @param out_type true, for VUSB
+ * false, for VBUS
+ * @param out if true, output is enabled
+ * if false, output is disabled
+ *
+ * @return This function returns PMIC_SUCCESS if successful.
+ */
+
+PMIC_STATUS pmic_convity_set_output(const PMIC_CONVITY_HANDLE handle,
+ bool out_type, bool out);
+
+/*!
+ * @brief Get the USB transceiver's operating speed.
+ *
+ * Get the USB transceiver speed.
+ *
+ * @param handle Device handle from open() call.
+ * @param speed The current USB transceiver speed.
+ * @param mode The current USB transceiver mode.
+ *
+ * @retval PMIC_SUCCESS If the transceiver speed was successfully
+ * set.
+ * @retval PMIC_PARAMETER_ERROR If the handle is invalid.
+ * obtained
+ */
+PMIC_STATUS pmic_convity_usb_get_speed(const PMIC_CONVITY_HANDLE handle,
+ PMIC_CONVITY_USB_SPEED * const speed,
+ PMIC_CONVITY_USB_MODE * const mode);
+
+/*!
+ * @brief Set the USB transceiver's power supply configuration.
+ *
+ * Set the USB transceiver's power supply configuration.
+ *
+ * @param handle Device handle from open() call.
+ * @param pwrin USB transceiver regulator input power source.
+ * @param pwrout USB transceiver regulator output power level.
+ *
+ * @retval PMIC_SUCCESS If the USB transceiver's power supply
+ * configuration was successfully set.
+ * @retval PMIC_PARAMETER_ERROR If the handle is invalid.
+ * @retval PMIC_NOT_SUPPORTED If the PMIC hardware does not support
+ * the desired configuration.
+ */
+PMIC_STATUS pmic_convity_usb_set_power_source(const PMIC_CONVITY_HANDLE handle,
+ const PMIC_CONVITY_USB_POWER_IN
+ pwrin,
+ const PMIC_CONVITY_USB_POWER_OUT
+ pwrout);
+
+/*!
+ * @brief Get the USB transceiver's power supply configuration.
+ *
+ * Get the USB transceiver's current power supply configuration.
+ *
+ * @param handle Device handle from open() call.
+ * @param pwrin USB transceiver regulator input power source
+ * @param pwrout USB transceiver regulator output power level
+ *
+ * @retval PMIC_SUCCESS If the USB transceiver's power supply
+ * configuration was successfully retrieved.
+ * @retval PMIC_PARAMETER_ERROR If the handle is invalid.
+ */
+PMIC_STATUS pmic_convity_usb_get_power_source(const PMIC_CONVITY_HANDLE handle,
+ PMIC_CONVITY_USB_POWER_IN *
+ const pwrin,
+ PMIC_CONVITY_USB_POWER_OUT *
+ const pwrout);
+
+/*!
+ * @brief Set the current USB transceiver operating mode.
+ *
+ * Set the USB transceiver's operating mode.
+ *
+ * @param handle Device handle from open() call.
+ * @param mode Desired operating mode.
+ *
+ * @retval PMIC_SUCCESS If the USB transceiver's operating mode
+ * was successfully configured.
+ * @retval PMIC_PARAMETER_ERROR If the handle is invalid.
+ * @retval PMIC_NOT_SUPPORTED If the desired USB transceiver mode is
+ * not supported by the PMIC hardware.
+ */
+PMIC_STATUS pmic_convity_usb_set_xcvr(const PMIC_CONVITY_HANDLE handle,
+ const PMIC_CONVITY_USB_TRANSCEIVER_MODE
+ mode);
+
+/*!
+ * @brief Get the current USB transceiver operating mode.
+ *
+ * Get the USB transceiver's current operating mode.
+ *
+ * @param handle Device handle from open() call.
+ * @param mode Current operating mode.
+ *
+ * @retval PMIC_SUCCESS If the USB transceiver's operating mode
+ * was successfully retrieved.
+ * @retval PMIC_PARAMETER_ERROR If the handle is invalid.
+ */
+PMIC_STATUS pmic_convity_usb_get_xcvr(const PMIC_CONVITY_HANDLE handle,
+ PMIC_CONVITY_USB_TRANSCEIVER_MODE *
+ const mode);
+
+/*!
+ * @brief Set the current USB On-The-Go data line pulse duration (ms).
+ *
+ * Set the Data Line Pulse duration (in milliseconds) for the USB OTG
+ * Session Request Protocol.
+ *
+ * Note that for mc13783 the duration is fixed at 7.5 ms and calling this
+ * function will simply return PMIC_NOT_SUPPORTED.
+ *
+ * @param handle Device handle from open() call.
+ * @param duration The data line pulse duration (ms).
+ *
+ * @retval PMIC_SUCCESS If the pulse duration was successfully set.
+ * @retval PMIC_PARAMETER_ERROR If the handle or the data line pulse
+ * duration is invalid.
+ * @retval PMIC_NOT_SUPPORTED If the desired data line pulse duration
+ * is not supported by the PMIC hardware.
+ */
+PMIC_STATUS pmic_convity_usb_otg_set_dlp_duration(const PMIC_CONVITY_HANDLE
+ handle,
+ const unsigned int duration);
+
+/*!
+ * @brief Get the current USB On-The-Go data line pulse duration (ms).
+ *
+ * Get the current Data Line Pulse duration (in milliseconds) for the USB
+ * OTG Session Request Protocol.
+ *
+ * Note that the Data Line Pulse duration is fixed at 7.5 ms for the mc13783
+ * PMIC. Therefore, calling this function while using the mc13783 PMIC will
+ * simply return PMIC_NOT_SUPPORTED.
+ *
+ * @param handle Device handle from open() call.
+ * @param duration The data line pulse duration (ms).
+ *
+ * @retval PMIC_SUCCESS If the pulse duration was successfully
+ * obtained.
+ * @retval PMIC_PARAMETER_ERROR If the handle is invalid.
+ * @retval PMIC_NOT_SUPPORTED If called using the mc13783 PMIC.
+ */
+PMIC_STATUS pmic_convity_usb_otg_get_dlp_duration(const PMIC_CONVITY_HANDLE
+ handle,
+ unsigned int *const duration);
+
+/*!
+ * @brief Start the USB OTG Host Negotiation Protocol (HNP) process.
+ *
+ * This function must be called during the start of the HNP process to
+ * properly reconfigure the pull-up resistor on the D+ line for both
+ * the USB A and B devices.
+ *
+ * @param handle device handle from open() call
+ * @param deviceType the USB device type (either A or B)
+ *
+ * @return PMIC_SUCCESS if the HNP was successfully started
+ */
+PMIC_STATUS pmic_convity_usb_otg_begin_hnp(const PMIC_CONVITY_HANDLE handle,
+ const PMIC_CONVITY_USB_DEVICE_TYPE
+ deviceType);
+
+/*!
+ * @brief Complete the USB OTG Host Negotiation Protocol (HNP) process.
+ *
+ * This function must be called during the end of the HNP process to
+ * properly reconfigure the pull-up resistor on the D+ line for both
+ * the USB A and B devices.
+ *
+ * @param handle device handle from open() call
+ * @param deviceType the USB device type (either A or B)
+ *
+ * @return PMIC_SUCCESS if the HNP was successfully ended
+ */
+PMIC_STATUS pmic_convity_usb_otg_end_hnp(const PMIC_CONVITY_HANDLE handle,
+ const PMIC_CONVITY_USB_DEVICE_TYPE
+ deviceType);
+
+/*!
+ * @brief Set the current USB On-The-Go configuration.
+ *
+ * Set the USB On-The-Go (OTG) configuration. Multiple configuration settings
+ * may be OR'd together in a single call. However, selecting conflicting
+ * settings (e.g., multiple VBUS current limits) will result in undefined
+ * behavior.
+ *
+ * @param handle Device handle from open() call.
+ * @param cfg Desired USB OTG configuration.
+ *
+ * @retval PMIC_SUCCESS If the OTG configuration was successfully
+ * set.
+ * @retval PMIC_PARAMETER_ERROR If the handle is invalid.
+ * @retval PMIC_NOT_SUPPORTED If the desired USB OTG configuration is
+ * not supported by the PMIC hardware.
+ */
+PMIC_STATUS pmic_convity_usb_otg_set_config(const PMIC_CONVITY_HANDLE handle,
+ const PMIC_CONVITY_USB_OTG_CONFIG
+ cfg);
+
+/*!
+ * @brief Clear the current USB On-The-Go configuration.
+ *
+ * Clears the USB On-The-Go (OTG) configuration. Multiple configuration settings
+ * may be OR'd together in a single call. However, selecting conflicting
+ * settings (e.g., multiple VBUS current limits) will result in undefined
+ * behavior.
+ *
+ * @param handle Device handle from open() call.
+ * @param cfg USB OTG configuration settings to be cleared.
+ *
+ * @retval PMIC_SUCCESS If the OTG configuration was successfully
+ * cleared.
+ * @retval PMIC_PARAMETER_ERROR If the handle is invalid.
+ * @retval PMIC_NOT_SUPPORTED If the desired USB OTG configuration is
+ * not supported by the PMIC hardware.
+ */
+PMIC_STATUS pmic_convity_usb_otg_clear_config(const PMIC_CONVITY_HANDLE handle,
+ const PMIC_CONVITY_USB_OTG_CONFIG
+ cfg);
+
+/*!
+ * @brief Get the current USB On-The-Go configuration.
+ *
+ * Get the current USB On-The-Go (OTG) configuration.
+ *
+ * @param handle Device handle from open() call.
+ * @param cfg The current USB OTG configuration.
+ *
+ * @retval PMIC_SUCCESS If the OTG configuration was successfully
+ * retrieved.
+ * @retval PMIC_PARAMETER_ERROR If the handle is invalid.
+ */
+PMIC_STATUS pmic_convity_usb_otg_get_config(const PMIC_CONVITY_HANDLE handle,
+ PMIC_CONVITY_USB_OTG_CONFIG *
+ const cfg);
+
+/*@}*/
+
+/***************************************************************************/
+
+/*!
+ * @name RS-232 APIs
+ * RS-232 Connectivity mode-specific configuration and setup functions.
+ */
+/*@{*/
+
+/*!
+ * @brief Set the current RS-232 operating configuration.
+ *
+ * Set the connectivity interface to the selected RS-232 operating mode.
+ * Note that the RS-232 operating mode will be automatically overridden
+ * if the USB_EN is asserted at any time (e.g., when a USB device is
+ * attached).
+ *
+ * @param handle Device handle from open() call.
+ * @param cfgInternal RS-232 transceiver internal connections.
+ * @param cfgExternal RS-232 transceiver external connections.
+ *
+ * @retval PMIC_SUCCESS If the requested RS-232 mode was set.
+ * @retval PMIC_PARAMETER_ERROR If the handle is invalid.
+ * @retval PMIC_NOT_SUPPORTED If the desired RS-232 configuration is
+ * not supported by the PMIC hardware.
+ */
+PMIC_STATUS pmic_convity_rs232_set_config(const PMIC_CONVITY_HANDLE handle,
+ const PMIC_CONVITY_RS232_INTERNAL
+ cfgInternal,
+ const PMIC_CONVITY_RS232_EXTERNAL
+ cfgExternal);
+
+/*!
+ * @brief Get the current RS-232 operating configuration.
+ *
+ * Get the connectivity interface's current RS-232 operating mode.
+ *
+ * @param handle Device handle from open() call.
+ * @param cfgInternal RS-232 transceiver internal connections.
+ * @param cfgExternal RS-232 transceiver external connections.
+ *
+ * @retval PMIC_SUCCESS If the requested RS-232 mode was retrieved.
+ * @retval PMIC_PARAMETER_ERROR If the handle is invalid.
+ */
+PMIC_STATUS pmic_convity_rs232_get_config(const PMIC_CONVITY_HANDLE handle,
+ PMIC_CONVITY_RS232_INTERNAL *
+ const cfgInternal,
+ PMIC_CONVITY_RS232_EXTERNAL *
+ const cfgExternal);
+
+/***************************************************************************/
+
+/*@}*/
+
+/*!
+ * @name CE-936 APIs
+ * CE-936 Connectivity mode-specific configuration and setup functions.
+ */
+/*@{*/
+
+/*!
+ * @brief Send a signal to exit CEA-936 mode.
+ *
+ * Signal the attached device to exit the current CEA-936 operating mode.
+ * Returns an error if the current operating mode is not CEA-936.
+ *
+ * @param handle Device handle from open() call.
+ * @param signal Type of exit signal to be sent.
+ *
+ * @retval PMIC_SUCCESS If the CEA-936 exit mode signal was sent.
+ * @retval PMIC_PARAMETER_ERROR If the handle is invalid.
+ * @retval PMIC_NOT_SUPPORTED If the desired CEA-936 exit mode signal
+ * is not supported by the PMIC hardware.
+ */
+PMIC_STATUS pmic_convity_cea936_exit_signal(const PMIC_CONVITY_HANDLE handle,
+ const
+ PMIC_CONVITY_CEA936_EXIT_SIGNAL
+ signal);
+
+/*@}*/
+
+#endif /* __ASM_ARCH_MXC_PMIC_CONVITY_H__ */
diff --git a/arch/arm/plat-mxc/include/mach/pmic_power.h b/arch/arm/plat-mxc/include/mach/pmic_power.h
new file mode 100644
index 000000000000..60f23ab9c888
--- /dev/null
+++ b/arch/arm/plat-mxc/include/mach/pmic_power.h
@@ -0,0 +1,1358 @@
+/*
+ * Copyright 2004-2009 Freescale Semiconductor, Inc. All Rights Reserved.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU Lesser General
+ * Public License. You may obtain a copy of the GNU Lesser General
+ * Public License Version 2.1 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/lgpl-license.html
+ * http://www.gnu.org/copyleft/lgpl.html
+ */
+#ifndef __ASM_ARCH_MXC_PMIC_POWER_H__
+#define __ASM_ARCH_MXC_PMIC_POWER_H__
+
+/*!
+ * @defgroup PMIC_POWER PMIC Power Driver
+ * @ingroup PMIC_DRVRS
+ */
+
+/*!
+ * @file arch-mxc/pmic_power.h
+ * @brief This is the header of PMIC power driver.
+ *
+ * @ingroup PMIC_POWER
+ */
+
+#include <linux/ioctl.h>
+#include <linux/pmic_status.h>
+#include <linux/pmic_external.h>
+
+/*!
+ * @name IOCTL user space interface
+ */
+/*! @{ */
+
+/*!
+ * Turn on a regulator.
+ */
+#define PMIC_REGULATOR_ON _IOWR('p', 0xf0, int)
+
+/*!
+ * Turn off a regulator.
+ */
+#define PMIC_REGULATOR_OFF _IOWR('p', 0xf1, int)
+
+/*!
+ * Set regulator configuration.
+ */
+#define PMIC_REGULATOR_SET_CONFIG _IOWR('p', 0xf2, int)
+
+/*!
+ * Get regulator configuration.
+ */
+#define PMIC_REGULATOR_GET_CONFIG _IOWR('p', 0xf3, int)
+
+/*!
+ * Miscellaneous Power Test.
+ */
+#define PMIC_POWER_CHECK_MISC _IOWR('p', 0xf4, int)
+
+/*! @} */
+
+/*!
+ * This enumeration define all power interrupts
+ */
+typedef enum {
+ /*!
+ * BP turn on threshold detection
+ */
+ PWR_IT_BPONI = 0,
+ /*!
+ * End of life / low battery detect
+ */
+ PWR_IT_LOBATLI,
+ /*!
+ * Low battery warning
+ */
+ PWR_IT_LOBATHI,
+ /*!
+ * ON1B event
+ */
+ PWR_IT_ONOFD1I,
+ /*!
+ * ON2B event
+ */
+ PWR_IT_ONOFD2I,
+ /*!
+ * ON3B event
+ */
+ PWR_IT_ONOFD3I,
+ /*!
+ * System reset
+ */
+ PWR_IT_SYSRSTI,
+ /*!
+ * Power ready
+ */
+ PWR_IT_PWRRDYI,
+ /*!
+ * Power cut event
+ */
+ PWR_IT_PCI,
+ /*!
+ * Warm start event
+ */
+ PWR_IT_WARMI,
+ /*!
+ * Memory hold event
+ */
+} t_pwr_int;
+
+/*!
+ * VHOLD regulator output voltage setting.
+ */
+typedef enum {
+ VH_1_875V, /*!< 1.875V */
+ VH_2_5V, /*!< 2.5V */
+ VH_1_55V, /*!< 1.55V */
+ VH_PASSTHROUGH, /*!< Pass-through mode */
+} t_vhold_voltage;
+
+/*!
+ * PMIC power control configuration.
+ */
+
+typedef struct {
+ bool pc_enable; /*!< Power cut enable */
+ unsigned char pc_timer; /*!< Power cut timer value */
+ bool pc_count_enable; /*!< Power cut counter enable,
+ If TURE, Power cuts are disabled
+ when pc_count > pc_max_count;
+ If FALSE, Power cuts are not
+ disabled when
+ pc_count > pc_max_count */
+ unsigned char pc_count; /*!< Power cut count */
+ unsigned char pc_max_count; /*!< Power cut maximum count */
+ bool warm_enable; /*!< User Off state enable */
+ bool user_off_pc; /*!< Automatic transition to user off
+ during power cut */
+ bool clk_32k_enable; /*!< 32 kHz output buffer enable
+ during memory hold */
+ bool clk_32k_user_off; /*!< Keeps the CLK32KMCU active during
+ user off power cut modes */
+ bool en_vbkup1; /*!< enable VBKUP1 regulator */
+ bool auto_en_vbkup1; /*!< automatically enable VBKUP1
+ regulator in the memory hold
+ and user of modes */
+ t_vhold_voltage vhold_voltage; /*!< output voltage for VBKUP1 */
+ bool en_vbkup2; /*!< enable VBKUP2 regulator */
+ bool auto_en_vbkup2; /*!< automatically enable VBKUP2
+ regulator in the memory hold
+ and user of modes */
+ t_vhold_voltage vhold_voltage2; /*!< output voltage for VBKUP2 */
+ unsigned char mem_timer; /*!< duration of the memory hold
+ timer */
+ bool mem_allon; /*!< memory hold timer infinity mode,
+ If TRUE, the memory hold timer
+ will be set to infinity and
+ the mem_timer filed will be
+ ignored */
+} t_pc_config;
+
+/*!
+ * brief PMIC regulators.
+ */
+
+typedef enum {
+ SW_SW1A = 0, /*!< SW1A or SW1 */
+ SW_SW1B, /*!< SW1B */
+ SW_SW2A, /*!< SW2A or SW2 */
+ SW_SW2B, /*!< SW2B */
+ SW_SW3, /*!< SW3 */
+ SW_PLL, /*!< PLL */
+ REGU_VAUDIO, /*!< VAUDIO */
+ REGU_VIOHI, /*!< VIOHI */
+ REGU_VIOLO, /*!< VIOLO */
+ REGU_VDIG, /*!< VDIG */
+ REGU_VGEN, /*!< VGEN */
+ REGU_VRFDIG, /*!< VRFDIG */
+ REGU_VRFREF, /*!< VRFREF */
+ REGU_VRFCP, /*!< VRFCP */
+ REGU_VSIM, /*!< VSIM */
+ REGU_VESIM, /*!< VESIM */
+ REGU_VCAM, /*!< VCAM */
+ REGU_VRFBG, /*!< VRFBG */
+ REGU_VVIB, /*!< VVIB */
+ REGU_VRF1, /*!< VRF1 */
+ REGU_VRF2, /*!< VRF2 */
+ REGU_VMMC1, /*!< VMMC1 or VMMC */
+ REGU_VMMC2, /*!< VMMC2 */
+ REGU_GPO1, /*!< GPIO1 */
+ REGU_GPO2, /*!< GPO2 */
+ REGU_GPO3, /*!< GPO3 */
+ REGU_GPO4, /*!< GPO4 */
+ REGU_V1, /*!< V1 */
+ REGU_V2, /*!< V2 */
+ REGU_V3, /*!< V3 */
+ REGU_V4, /*!< V4 */
+} t_pmic_regulator;
+
+/*!
+ * @enum t_pmic_regulator_voltage_sw1
+ * @brief PMIC Switch mode regulator SW1 output voltages.
+ */
+
+typedef enum {
+ SW1_1V = 0, /*!< 1.0 V */
+ SW1_1_1V, /*!< 1.1 V */
+ SW1_1_2V, /*!< 1.2 V */
+ SW1_1_3V, /*!< 1.3 V */
+ SW1_1_4V, /*!< 1.4 V */
+ SW1_1_55V, /*!< 1.55 V */
+ SW1_1_625V, /*!< 1.625 V */
+ SW1_1_875V, /*!< 1.875 V */
+} t_pmic_regulator_voltage_sw1;
+
+/*!
+ * @enum t_pmic_regulator_voltage_sw1a
+ * @brief PMIC regulator SW1A output voltage.
+ */
+typedef enum {
+ SW1A_0_9V = 0, /*!< 0.900 V */
+ SW1A_0_925V, /*!< 0.925 V */
+ SW1A_0_95V, /*!< 0.950 V */
+ SW1A_0_975V, /*!< 0.975 V */
+ SW1A_1V, /*!< 1.000 V */
+ SW1A_1_025V, /*!< 1.025 V */
+ SW1A_1_05V, /*!< 1.050 V */
+ SW1A_1_075V, /*!< 1.075 V */
+ SW1A_1_1V, /*!< 1.100 V */
+ SW1A_1_125V, /*!< 1.125 V */
+ SW1A_1_15V, /*!< 1.150 V */
+ SW1A_1_175V, /*!< 1.175 V */
+ SW1A_1_2V, /*!< 1.200 V */
+ SW1A_1_225V, /*!< 1.225 V */
+ SW1A_1_25V, /*!< 1.250 V */
+ SW1A_1_275V, /*!< 1.275 V */
+ SW1A_1_3V, /*!< 1.300 V */
+ SW1A_1_325V, /*!< 1.325 V */
+ SW1A_1_35V, /*!< 1.350 V */
+ SW1A_1_375V, /*!< 1.375 V */
+ SW1A_1_4V, /*!< 1.400 V */
+ SW1A_1_425V, /*!< 1.425 V */
+ SW1A_1_45V, /*!< 1.450 V */
+ SW1A_1_475V, /*!< 1.475 V */
+ SW1A_1_5V, /*!< 1.500 V */
+ SW1A_1_525V, /*!< 1.525 V */
+ SW1A_1_55V, /*!< 1.550 V */
+ SW1A_1_575V, /*!< 1.575 V */
+ SW1A_1_6V, /*!< 1.600 V */
+ SW1A_1_625V, /*!< 1.625 V */
+ SW1A_1_65V, /*!< 1.650 V */
+ SW1A_1_675V, /*!< 1.675 V */
+ SW1A_1_7V, /*!< 1.700 V */
+ SW1A_1_8V = 36, /*!< 1.800 V */
+ SW1A_1_85V = 40, /*!< 1.850 V */
+ SW1A_2V = 44, /*!< 2_000 V */
+ SW1A_2_1V = 48, /*!< 2_100 V */
+ SW1A_2_2V = 52, /*!< 2_200 V */
+} t_pmic_regulator_voltage_sw1a;
+
+/*!
+ * @enum t_pmic_regulator_voltage_sw1b
+ * @brief PMIC regulator SW1B output voltage.
+ */
+typedef enum {
+ SW1B_0_9V = 0, /*!< 0.900 V */
+ SW1B_0_925V, /*!< 0.925 V */
+ SW1B_0_95V, /*!< 0.950 V */
+ SW1B_0_975V, /*!< 0.975 V */
+ SW1B_1V, /*!< 1.000 V */
+ SW1B_1_025V, /*!< 1.025 V */
+ SW1B_1_05V, /*!< 1.050 V */
+ SW1B_1_075V, /*!< 1.075 V */
+ SW1B_1_1V, /*!< 1.100 V */
+ SW1B_1_125V, /*!< 1.125 V */
+ SW1B_1_15V, /*!< 1.150 V */
+ SW1B_1_175V, /*!< 1.175 V */
+ SW1B_1_2V, /*!< 1.200 V */
+ SW1B_1_225V, /*!< 1.225 V */
+ SW1B_1_25V, /*!< 1.250 V */
+ SW1B_1_275V, /*!< 1.275 V */
+ SW1B_1_3V, /*!< 1.300 V */
+ SW1B_1_325V, /*!< 1.325 V */
+ SW1B_1_35V, /*!< 1.350 V */
+ SW1B_1_375V, /*!< 1.375 V */
+ SW1B_1_4V, /*!< 1.400 V */
+ SW1B_1_425V, /*!< 1.425 V */
+ SW1B_1_45V, /*!< 1.450 V */
+ SW1B_1_475V, /*!< 1.475 V */
+ SW1B_1_5V, /*!< 1.500 V */
+ SW1B_1_525V, /*!< 1.525 V */
+ SW1B_1_55V, /*!< 1.550 V */
+ SW1B_1_575V, /*!< 1.575 V */
+ SW1B_1_6V, /*!< 1.600 V */
+ SW1B_1_625V, /*!< 1.625 V */
+ SW1B_1_65V, /*!< 1.650 V */
+ SW1B_1_675V, /*!< 1.675 V */
+ SW1B_1_7V, /*!< 1.700 V */
+ SW1B_1_8V = 36, /*!< 1.800 V */
+ SW1B_1_85V = 40, /*!< 1.850 V */
+ SW1B_2V = 44, /*!< 2_000 V */
+ SW1B_2_1V = 48, /*!< 2_100 V */
+ SW1B_2_2V = 52, /*!< 2_200 V */
+} t_pmic_regulator_voltage_sw1b;
+
+/*!
+ * @enum t_pmic_regulator_voltage_sw2
+ * @brief PMIC Switch mode regulator SW2 output voltages.
+ */
+typedef enum {
+ SW2_1V = 0, /*!< 1.0 V */
+ SW2_1_1V, /*!< 1.1 V */
+ SW2_1_2V, /*!< 1.2 V */
+ SW2_1_3V, /*!< 1.3 V */
+ SW2_1_4V, /*!< 1.4 V */
+ SW2_1_55V, /*!< 1.55 V */
+ SW2_1_625V, /*!< 1.625 V */
+ SW2_1_875V, /*!< 1.875 V */
+} t_pmic_regulator_voltage_sw2;
+
+/*!
+ * @enum t_pmic_regulator_voltage_sw2a
+ * @brief PMIC regulator SW2A output voltage.
+ */
+typedef enum {
+ SW2A_0_9V = 0, /*!< 0.900 V */
+ SW2A_0_925V, /*!< 0.925 V */
+ SW2A_0_95V, /*!< 0.950 V */
+ SW2A_0_975V, /*!< 0.975 V */
+ SW2A_1V, /*!< 1.000 V */
+ SW2A_1_025V, /*!< 1.025 V */
+ SW2A_1_05V, /*!< 1.050 V */
+ SW2A_1_075V, /*!< 1.075 V */
+ SW2A_1_1V, /*!< 1.100 V */
+ SW2A_1_125V, /*!< 1.125 V */
+ SW2A_1_15V, /*!< 1.150 V */
+ SW2A_1_175V, /*!< 1.175 V */
+ SW2A_1_2V, /*!< 1.200 V */
+ SW2A_1_225V, /*!< 1.225 V */
+ SW2A_1_25V, /*!< 1.250 V */
+ SW2A_1_275V, /*!< 1.275 V */
+ SW2A_1_3V, /*!< 1.300 V */
+ SW2A_1_325V, /*!< 1.325 V */
+ SW2A_1_35V, /*!< 1.350 V */
+ SW2A_1_375V, /*!< 1.375 V */
+ SW2A_1_4V, /*!< 1.400 V */
+ SW2A_1_425V, /*!< 1.425 V */
+ SW2A_1_45V, /*!< 1.450 V */
+ SW2A_1_475V, /*!< 1.475 V */
+ SW2A_1_5V, /*!< 1.500 V */
+ SW2A_1_525V, /*!< 1.525 V */
+ SW2A_1_55V, /*!< 1.550 V */
+ SW2A_1_575V, /*!< 1.575 V */
+ SW2A_1_6V, /*!< 1.600 V */
+ SW2A_1_625V, /*!< 1.625 V */
+ SW2A_1_65V, /*!< 1.650 V */
+ SW2A_1_675V, /*!< 1.675 V */
+ SW2A_1_7V, /*!< 1.700 V */
+ SW2A_1_8V = 36, /*!< 1.800 V */
+ SW2A_1_9V = 40, /*!< 1.900 V */
+ SW2A_2V = 44, /*!< 2_000 V */
+ SW2A_2_1V = 48, /*!< 2_100 V */
+ SW2A_2_2V = 52, /*!< 2_200 V */
+} t_pmic_regulator_voltage_sw2a;
+
+/*!
+ * @enum t_pmic_regulator_voltage_sw2b
+ * @brief PMIC regulator SW2B output voltage.
+ */
+typedef enum {
+ SW2B_0_9V = 0, /*!< 0.900 V */
+ SW2B_0_925V, /*!< 0.925 V */
+ SW2B_0_95V, /*!< 0.950 V */
+ SW2B_0_975V, /*!< 0.975 V */
+ SW2B_1V, /*!< 1.000 V */
+ SW2B_1_025V, /*!< 1.025 V */
+ SW2B_1_05V, /*!< 1.050 V */
+ SW2B_1_075V, /*!< 1.075 V */
+ SW2B_1_1V, /*!< 1.100 V */
+ SW2B_1_125V, /*!< 1.125 V */
+ SW2B_1_15V, /*!< 1.150 V */
+ SW2B_1_175V, /*!< 1.175 V */
+ SW2B_1_2V, /*!< 1.200 V */
+ SW2B_1_225V, /*!< 1.225 V */
+ SW2B_1_25V, /*!< 1.250 V */
+ SW2B_1_275V, /*!< 1.275 V */
+ SW2B_1_3V, /*!< 1.300 V */
+ SW2B_1_325V, /*!< 1.325 V */
+ SW2B_1_35V, /*!< 1.350 V */
+ SW2B_1_375V, /*!< 1.375 V */
+ SW2B_1_4V, /*!< 1.400 V */
+ SW2B_1_425V, /*!< 1.425 V */
+ SW2B_1_45V, /*!< 1.450 V */
+ SW2B_1_475V, /*!< 1.475 V */
+ SW2B_1_5V, /*!< 1.500 V */
+ SW2B_1_525V, /*!< 1.525 V */
+ SW2B_1_55V, /*!< 1.550 V */
+ SW2B_1_575V, /*!< 1.575 V */
+ SW2B_1_6V, /*!< 1.600 V */
+ SW2B_1_625V, /*!< 1.625 V */
+ SW2B_1_65V, /*!< 1.650 V */
+ SW2B_1_675V, /*!< 1.675 V */
+ SW2B_1_7V, /*!< 1.700 V */
+ SW2B_1_8V = 36, /*!< 1.800 V */
+ SW2B_1_9V = 40, /*!< 1.900 V */
+ SW2B_2V = 44, /*!< 2_000 V */
+ SW2B_2_1V = 48, /*!< 2_100 V */
+ SW2B_2_2V = 52, /*!< 2_200 V */
+} t_pmic_regulator_voltage_sw2b;
+
+/*!
+ * @enum t_pmic_regulator_voltage_sw3
+ * @brief PMIC Switch mode regulator SW3 output voltages.
+ */
+typedef enum {
+ SW3_5V = 0, /*!< 5.0 V */
+ SW3_5_1V = 0, /*!< 5.1 V */
+ SW3_5_6V, /*!< 5.6 V */
+} t_pmic_regulator_voltage_sw3;
+
+/*!
+ * @enum t_switcher_factor
+ * @brief PLL multiplication factor
+ */
+typedef enum {
+ FACTOR_28 = 0, /*!< 917 504 kHz */
+ FACTOR_29, /*!< 950 272 kHz */
+ FACTOR_30, /*!< 983 040 kHz */
+ FACTOR_31, /*!< 1 015 808 kHz */
+ FACTOR_32, /*!< 1 048 576 kHz */
+ FACTOR_33, /*!< 1 081 344 kHz */
+ FACTOR_34, /*!< 1 114 112 kHz */
+ FACTOR_35, /*!< 1 146 880 kHz */
+} t_switcher_factor;
+
+/*!
+ * @enum t_pmic_regulator_voltage_violo
+ * @brief PMIC regulator VIOLO output voltage.
+ */
+typedef enum {
+ VIOLO_1_2V = 0, /*!< 1.2 V */
+ VIOLO_1_3V, /*!< 1.3 V */
+ VIOLO_1_5V, /*!< 1.5 V */
+ VIOLO_1_8V, /*!< 1.8 V */
+} t_pmic_regulator_voltage_violo;
+
+/*!
+ * @enum t_pmic_regulator_voltage_vdig
+ * @brief PMIC regulator VDIG output voltage.
+ */
+typedef enum {
+ VDIG_1_2V = 0, /*!< 1.2 V */
+ VDIG_1_3V, /*!< 1.3 V */
+ VDIG_1_5V, /*!< 1.5 V */
+ VDIG_1_8V, /*!< 1.8 V */
+} t_pmic_regulator_voltage_vdig;
+
+/*!
+ * @enum t_pmic_regulator_voltage_vgen
+ * @brief PMIC regulator VGEN output voltage.
+ */
+typedef enum {
+ VGEN_1_2V = 0, /*!< 1.2 V */
+ VENG_1_3V, /*!< 1.3 V */
+ VGEN_1_5V, /*!< 1.5 V */
+ VGEN_1_8V, /*!< 1.8 V */
+ VGEN_1_1V, /*!< 1.1 V */
+ VGEN_2V, /*!< 2 V */
+ VGEN_2_775V, /*!< 2.775 V */
+ VGEN_2_4V, /*!< 2.4 V */
+} t_pmic_regulator_voltage_vgen;
+
+/*!
+ * @enum t_pmic_regulator_voltage_vrfdig
+ * @brief PMIC regulator VRFDIG output voltage.
+ */
+typedef enum {
+ VRFDIG_1_2V = 0, /*!< 1.2 V */
+ VRFDIG_1_5V, /*!< 1.5 V */
+ VRFDIG_1_8V, /*!< 1.8 V */
+ VRFDIG_1_875V, /*!< 1.875 V */
+} t_pmic_regulator_voltage_vrfdig;
+
+/*!
+ * @enum t_pmic_regulator_voltage_vrfref
+ * @brief PMIC regulator VRFREF output voltage.
+ */
+typedef enum {
+ VRFREF_2_475V = 0, /*!< 2.475 V */
+ VRFREF_2_6V, /*!< 2.600 V */
+ VRFREF_2_7V, /*!< 2.700 V */
+ VRFREF_2_775V, /*!< 2.775 V */
+} t_pmic_regulator_voltage_vrfref;
+
+/*!
+ * @enum t_pmic_regulator_voltage_vrfcp
+ * @brief PMIC regulator VRFCP output voltage.
+ */
+typedef enum {
+ VRFCP_2_7V = 0, /*!< 2.700 V */
+ VRFCP_2_775V, /*!< 2.775 V */
+} t_pmic_regulator_voltage_vrfcp;
+
+/*!
+ * @enum t_pmic_regulator_voltage_vsim
+ * @brief PMIC linear regulator VSIM output voltage.
+ */
+typedef enum {
+ VSIM_1_8V = 0, /*!< 1.8 V */
+ VSIM_2_9V, /*!< 2.90 V */
+ VSIM_3V = 1, /*!< 3 V */
+} t_pmic_regulator_voltage_vsim;
+
+/*!
+ * @enum t_pmic_regulator_voltage_vesim
+ * @brief PMIC regulator VESIM output voltage.
+ */
+typedef enum {
+ VESIM_1_8V = 0, /*!< 1.80 V */
+ VESIM_2_9V, /*!< 2.90 V */
+} t_pmic_regulator_voltage_vesim;
+
+/*!
+ * @enum t_pmic_regulator_voltage_vcam
+ * @brief PMIC regulator VCAM output voltage.
+ */
+typedef enum {
+ VCAM_1_5V = 0, /*!< 1.50 V */
+ VCAM_1_8V, /*!< 1.80 V */
+ VCAM_2_5V, /*!< 2.50 V */
+ VCAM_2_55V, /*!< 2.55 V */
+ VCAM_2_6V, /*!< 2.60 V */
+ VCAM_2_75V, /*!< 2.75 V */
+ VCAM_2_8V, /*!< 2.80 V */
+ VCAM_3V, /*!< 3.00 V */
+} t_pmic_regulator_voltage_vcam;
+
+/*!
+ * @enum t_pmic_regulator_voltage_vvib
+ * @brief PMIC linear regulator V_VIB output voltage.
+ */
+typedef enum {
+ VVIB_1_3V = 0, /*!< 1.30 V */
+ VVIB_1_8V, /*!< 1.80 V */
+ VVIB_2V, /*!< 2 V */
+ VVIB_3V, /*!< 3 V */
+} t_pmic_regulator_voltage_vvib;
+
+/*!
+ * @enum t_pmic_regulator_voltage_vrf1
+ * @brief PMIC regulator VRF1 output voltage.
+ */
+typedef enum {
+ VRF1_1_5V = 0, /*!< 1.500 V */
+ VRF1_1_875V, /*!< 1.875 V */
+ VRF1_2_7V, /*!< 2.700 V */
+ VRF1_2_775V, /*!< 2.775 V */
+} t_pmic_regulator_voltage_vrf1;
+
+/*!
+ * @enum t_pmic_regulator_voltage_vrf2
+ * @brief PMIC regulator VRF2 output voltage.
+ */
+typedef enum {
+ VRF2_1_5V = 0, /*!< 1.500 V */
+ VRF2_1_875V, /*!< 1.875 V */
+ VRF2_2_7V, /*!< 2.700 V */
+ VRF2_2_775V, /*!< 2.775 V */
+} t_pmic_regulator_voltage_vrf2;
+
+/*!
+ * @enum t_pmic_regulator_voltage_vmmc
+ * @brief PMIC linear regulator VMMC output voltage.
+ */
+typedef enum {
+ VMMC_OFF = 0, /*!< Output off */
+ VMMC_1_6V, /*!< 1.6 V */
+ VMMC_1_8V, /*!< 1.8 V */
+ VMMC_2V, /*!< 2 V */
+ VMMC_2_2V, /*!< 2.2 V */
+ VMMC_2_4V, /*!< 2.4 V */
+ VMMC_2_6V, /*!< 2.6 V */
+ VMMC_2_8V, /*!< 2.8 V */
+ VMMC_3V, /*!< 3 V */
+ VMMC_3_2V, /*!< 3.2 V */
+ VMMC_3_3V, /*!< 3.3 V */
+ VMMC_3_4V, /*!< 3.4 V */
+} t_pmic_regulator_voltage_vmmc;
+
+/*!
+ * @enum t_pmic_regulator_voltage_vmmc1
+ * @brief PMIC regulator VMMC1 output voltage.
+ */
+typedef enum {
+ VMMC1_1_6V = 0, /*!< 1.60 V */
+ VMMC1_1_8V, /*!< 1.80 V */
+ VMMC1_2V, /*!< 2.00 V */
+ VMMC1_2_6V, /*!< 2.60 V */
+ VMMC1_2_7V, /*!< 2.70 V */
+ VMMC1_2_8V, /*!< 2.80 V */
+ VMMC1_2_9V, /*!< 2.90 V */
+ VMMC1_3V, /*!< 3.00 V */
+} t_pmic_regulator_voltage_vmmc1;
+
+/*!
+ * @enum t_pmic_regulator_voltage_vmmc2
+ * @brief PMIC regulator VMMC2 output voltage.
+ */
+typedef enum {
+ VMMC2_1_6V = 0, /*!< 1.60 V */
+ VMMC2_1_8V, /*!< 1.80 V */
+ VMMC2_2V, /*!< 2.00 V */
+ VMMC2_2_6V, /*!< 2.60 V */
+ VMMC2_2_7V, /*!< 2.70 V */
+ VMMC2_2_8V, /*!< 2.80 V */
+ VMMC2_2_9V, /*!< 2.90 V */
+ VMMC2_3V, /*!< 3.00 V */
+} t_pmic_regulator_voltage_vmmc2;
+
+/*!
+ * @enum t_pmic_regulator_voltage_v1
+ * @brief PMIC linear regulator V1 output voltages.
+ */
+typedef enum {
+ V1_2_775V = 0, /*!< 2.775 V */
+ V1_1_2V, /*!< 1.2 V */
+ V1_1_3V, /*!< 1.3 V */
+ V1_1_4V, /*!< 1.4 V */
+ V1_1_55V, /*!< 1.55 V */
+ V1_1_75V, /*!< 1.75 V */
+ V1_1_875V, /*!< 1.875 V */
+ V1_2_475V, /*!< 2.475 V */
+} t_pmic_regulator_voltage_v1;
+
+/*!
+ * @enum t_pmic_regulator_voltage_v2
+ * @brief PMIC linear regulator V2 output voltage, V2 has fixed
+ * output voltage 2.775 volts.
+ */
+typedef enum {
+ V2_2_775V = 0, /*!< 2.775 V */
+} t_pmic_regulator_voltage_v2;
+
+/*!
+ * @enum t_pmic_regulator_voltage_v3
+ * @brief PMIC linear regulator V3 output voltage.
+ */
+typedef enum {
+ V3_1_875V = 0, /*!< 1.875 V */
+ V3_2_775V, /*!< 2.775 V */
+} t_pmic_regulator_voltage_v3;
+
+/*!
+ * @enum t_pmic_regulator_voltage_v4
+ * @brief PMIC linear regulator V4 output voltage, V4 has fixed
+ * output voltage 2.775 volts.
+ */
+typedef enum {
+ V4_2_775V = 0, /*!< 2.775 V */
+} t_pmic_regulator_voltage_v4;
+
+/*!
+ * @union t_regulator_voltage
+ * @brief PMIC regulator output voltages.
+ */
+typedef union {
+ t_pmic_regulator_voltage_sw1 sw1; /*!< SW1 voltage */
+ t_pmic_regulator_voltage_sw1a sw1a; /*!< SW1A voltage */
+ t_pmic_regulator_voltage_sw1b sw1b; /*!< SW1B voltage */
+ t_pmic_regulator_voltage_sw2 sw2; /*!< SW2 voltage */
+ t_pmic_regulator_voltage_sw2a sw2a; /*!< SW2A voltage */
+ t_pmic_regulator_voltage_sw2b sw2b; /*!< SW2B voltage */
+ t_pmic_regulator_voltage_sw3 sw3; /*!< SW3 voltage */
+ t_pmic_regulator_voltage_violo violo; /*!< VIOLO voltage */
+ t_pmic_regulator_voltage_vdig vdig; /*!< VDIG voltage */
+ t_pmic_regulator_voltage_vgen vgen; /*!< VGEN voltage */
+ t_pmic_regulator_voltage_vrfdig vrfdig; /*!< VRFDIG voltage */
+ t_pmic_regulator_voltage_vrfref vrfref; /*!< VRFREF voltage */
+ t_pmic_regulator_voltage_vrfcp vrfcp; /*!< VRFCP voltage */
+ t_pmic_regulator_voltage_vsim vsim; /*!< VSIM voltage */
+ t_pmic_regulator_voltage_vesim vesim; /*!< VESIM voltage */
+ t_pmic_regulator_voltage_vcam vcam; /*!< VCAM voltage */
+ t_pmic_regulator_voltage_vvib vvib; /*!< VVIB voltage */
+ t_pmic_regulator_voltage_vrf1 vrf1; /*!< VRF1 voltage */
+ t_pmic_regulator_voltage_vrf2 vrf2; /*!< VRF2 voltage */
+ t_pmic_regulator_voltage_vmmc vmmc; /*!< VMMC voltage */
+ t_pmic_regulator_voltage_vmmc1 vmmc1; /*!< VMMC1 voltage */
+ t_pmic_regulator_voltage_vmmc2 vmmc2; /*!< VMMC2 voltage */
+ t_pmic_regulator_voltage_v1 v1; /*!< V1 voltage */
+ t_pmic_regulator_voltage_v2 v2; /*!< V2 voltage */
+ t_pmic_regulator_voltage_v3 v3; /*!< V3 voltage */
+ t_pmic_regulator_voltage_v4 v4; /*!< V4 voltage */
+} t_regulator_voltage;
+
+/*!
+ * @enum t_pmic_regulator_sw_mode
+ * @brief define switch mode regulator mode.
+ *
+ * The synchronous rectifier can be disabled (and pulse-skipping enabled)
+ * to improve low current efficiency. Software should disable synchronous
+ * rectifier / enable the pulse skipping for average loads less than
+ * approximately 30 mA, depending on the quiescent current penalty due to
+ * synchronous mode.
+ */
+typedef enum {
+ SYNC_RECT = 0,
+ NO_PULSE_SKIP,
+ PULSE_SKIP,
+ LOW_POWER,
+} t_pmic_regulator_sw_mode;
+
+/*!
+ * Generic PMIC switch mode regulator mode.
+ */
+typedef t_pmic_regulator_sw_mode t_regulator_sw_mode;
+typedef t_pmic_regulator_sw_mode t_regulator_stby_mode;
+
+/*!
+ * @enum t_regulator_lp_mode
+ * @brief Low power mode control modes.
+ */
+
+typedef enum {
+ /*!
+ * Low Power Mode is disabled
+ */
+ LOW_POWER_DISABLED = 0,
+ /*!
+ * Low Power Mode is controlled by STANDBY pin and/or LVS pin
+ */
+ LOW_POWER_CTRL_BY_PIN,
+ /*!
+ * Set Low Power mode no matter of hardware pins
+ */
+ LOW_POWER_EN,
+ /*!
+ * Set Low Power mode and control by STANDBY
+ */
+ LOW_POWER_AND_LOW_POWER_CTRL_BY_PIN,
+} t_regulator_lp_mode;
+
+/*!
+ * @enum t_switcher_dvs_speed
+ * @brief DVS speed setting
+ */
+typedef enum {
+ /*!
+ * Transition speed is dictated by the current
+ * limit and input -output conditions
+ */
+ DICTATED = 0,
+ /*!
+ * 25mV step each 4us
+ */
+ DVS_4US,
+ /*!
+ * 25mV step each 8us
+ */
+ DVS_8US,
+ /*!
+ * 25mV step each 16us
+ */
+ DVS_16US,
+} t_switcher_dvs_speed;
+
+/*!
+ * @struct t_regulator_config
+ * @brief regulator configuration.
+ *
+ */
+
+typedef struct {
+ /*!
+ * Switch mode regulator operation mode. This field only applies to
+ * switch mode regulators.
+ */
+ t_regulator_sw_mode mode;
+ /*!
+ * Switch mode stby regulator operation mode. This field only applies
+ * to switch mode regulators.
+ */
+ t_regulator_stby_mode stby_mode;
+ /*!
+ * Regulator output voltage.
+ */
+ t_regulator_voltage voltage;
+ /*!
+ * Regulator output voltage in LVS mode.
+ */
+ t_regulator_voltage voltage_lvs;
+ /*!
+ * Regulator output voltage in standby mode.
+ */
+ t_regulator_voltage voltage_stby;
+ /*!
+ * Regulator low power mode.
+ */
+ t_regulator_lp_mode lp_mode;
+ /*!
+ * Switcher dvs speed
+ */
+ t_switcher_dvs_speed dvs_speed;
+ /*!
+ * Switcher panic mode
+ */
+ bool panic_mode;
+ /*!
+ * Switcher softstart
+ */
+ bool softstart;
+ /*!
+ * PLL Multiplication factor
+ */
+ t_switcher_factor factor;
+} t_regulator_config;
+
+/*!
+ * @struct t_regulator_cfg_param
+ * @brief regulator configuration structure for IOCTL.
+ *
+ */
+typedef struct {
+ /*!
+ * Regulator.
+ */
+ t_pmic_regulator regulator;
+ /*!
+ * Regulator configuration.
+ */
+ t_regulator_config cfg;
+} t_regulator_cfg_param;
+
+/*!
+ * This struct list all state reads in Power Up Sense
+ */
+struct t_p_up_sense {
+ /*!
+ * power up sense ictest
+ */
+ bool state_ictest;
+ /*!
+ * power up sense clksel
+ */
+ bool state_clksel;
+ /*!
+ * power up mode supply 1
+ */
+ bool state_pums1;
+ /*!
+ * power up mode supply 2
+ */
+ bool state_pums2;
+ /*!
+ * power up mode supply 3
+ */
+ bool state_pums3;
+ /*!
+ * power up sense charge mode 0
+ */
+ bool state_chrgmode0;
+ /*!
+ * power up sense charge mode 1
+ */
+ bool state_chrgmode1;
+ /*!
+ * power up sense USB mode
+ */
+ bool state_umod;
+ /*!
+ * power up sense boot mode enable for USB/RS232
+ */
+ bool state_usben;
+ /*!
+ * power up sense switcher 1a1b joined
+ */
+ bool state_sw_1a1b_joined;
+ /*!
+ * power up sense switcher 1a1b joined
+ */
+ bool state_sw_2a2b_joined;
+};
+
+/*!
+ * This enumeration define all On_OFF button
+ */
+typedef enum {
+ /*!
+ * ON1B
+ */
+ BT_ON1B = 0,
+ /*!
+ * ON2B
+ */
+ BT_ON2B,
+ /*!
+ * ON3B
+ */
+ BT_ON3B,
+} t_button;
+
+#ifdef __KERNEL__
+/* EXPORTED FUNCTIONS */
+
+/*!
+ * This function sets user power off in power control register and thus powers
+ * off the phone.
+ *
+ * @return This function returns PMIC_SUCCESS if successful.
+ */
+void pmic_power_off(void);
+
+/*!
+ * This function sets the power control configuration.
+ *
+ * @param pc_config power control configuration.
+ *
+ * @return This function returns PMIC_SUCCESS if successful.
+ */
+PMIC_STATUS pmic_power_set_pc_config(t_pc_config * pc_config);
+
+/*!
+ * This function retrives the power control configuration.
+ *
+ * @param pc_config pointer to power control configuration.
+ *
+ * @return This function returns PMIC_SUCCESS if successful.
+ */
+PMIC_STATUS pmic_power_get_pc_config(t_pc_config * pc_config);
+
+/*!
+ * This function turns on a regulator.
+ *
+ * @param regulator The regulator to be turned on.
+ *
+ * @return This function returns PMIC_SUCCESS if successful.
+ */
+PMIC_STATUS pmic_power_regulator_on(t_pmic_regulator regulator);
+
+/*!
+ * This function turns off a regulator.
+ *
+ * @param regulator The regulator to be turned off.
+ *
+ * @return This function returns PMIC_SUCCESS if successful.
+ */
+PMIC_STATUS pmic_power_regulator_off(t_pmic_regulator regulator);
+
+/*!
+ * This function sets the regulator output voltage.
+ *
+ * @param regulator The regulator to be turned off.
+ * @param voltage The regulator output voltage.
+ *
+ * @return This function returns PMIC_SUCCESS if successful.
+ */
+PMIC_STATUS pmic_power_regulator_set_voltage(t_pmic_regulator regulator,
+ t_regulator_voltage voltage);
+
+/*!
+ * This function retrieves the regulator output voltage.
+ *
+ * @param regulator The regulator to be turned off.
+ * @param voltage Pointer to regulator output voltage.
+ *
+ * @return This function returns PMIC_SUCCESS if successful.
+ */
+PMIC_STATUS pmic_power_regulator_get_voltage(t_pmic_regulator regulator,
+ t_regulator_voltage * voltage);
+
+/*!
+ * This function sets the DVS voltage
+ *
+ * @param regulator The regulator to be configured.
+ * @param dvs The switch Dynamic Voltage Scaling
+ *
+ * @return This function returns PMIC_SUCCESS if successful.
+ */
+PMIC_STATUS pmic_power_switcher_set_dvs(t_pmic_regulator regulator,
+ t_regulator_voltage dvs);
+
+/*!
+ * This function gets the DVS voltage
+ *
+ * @param regulator The regulator to be handled.
+ * @param dvs The switch Dynamic Voltage Scaling
+ *
+ * @return This function returns PMIC_SUCCESS if successful.
+ */
+PMIC_STATUS pmic_power_switcher_get_dvs(t_pmic_regulator regulator,
+ t_regulator_voltage * dvs);
+
+/*!
+ * This function sets the standby voltage
+ *
+ * @param regulator The regulator to be configured.
+ * @param stby The switch standby voltage
+ *
+ * @return This function returns PMIC_SUCCESS if successful.
+ */
+PMIC_STATUS pmic_power_switcher_set_stby(t_pmic_regulator regulator,
+ t_regulator_voltage stby);
+
+/*!
+ * This function gets the standby voltage
+ *
+ * @param regulator The regulator to be handled.
+ * @param stby The switch standby voltage
+ *
+ * @return This function returns PMIC_SUCCESS if successful.
+ */
+PMIC_STATUS pmic_power_switcher_get_stby(t_pmic_regulator regulator,
+ t_regulator_voltage * stby);
+
+/*!
+ * This function sets the switchers mode.
+ *
+ * @param regulator The regulator to be configured.
+ * @param mode The switcher mode
+ * @param stby Switch between main and standby.
+ *
+ * @return This function returns PMIC_SUCCESS if successful.
+ */
+PMIC_STATUS pmic_power_switcher_set_mode(t_pmic_regulator regulator,
+ t_regulator_sw_mode mode, bool stby);
+
+/*!
+ * This function gets the switchers mode.
+ *
+ * @param regulator The regulator to be handled.
+ * @param mode The switcher mode.
+ * @param stby Switch between main and standby.
+ *
+ * @return This function returns PMIC_SUCCESS if successful.
+ */
+PMIC_STATUS pmic_power_switcher_get_mode(t_pmic_regulator regulator,
+ t_regulator_sw_mode * mode, bool stby);
+
+/*!
+ * This function sets the switch dvs speed
+ *
+ * @param regulator The regulator to be configured.
+ * @param speed The dvs speed.
+ *
+ * @return This function returns PMIC_SUCCESS if successful.
+ */
+PMIC_STATUS pmic_power_switcher_set_dvs_speed(t_pmic_regulator regulator,
+ t_switcher_dvs_speed speed);
+
+/*!
+ * This function gets the switch dvs speed
+ *
+ * @param regulator The regulator to be handled.
+ * @param speed The dvs speed.
+ *
+ * @return This function returns PMIC_SUCCESS if successful.
+ */
+PMIC_STATUS pmic_power_switcher_get_dvs_speed(t_pmic_regulator regulator,
+ t_switcher_dvs_speed * speed);
+
+/*!
+ * This function sets the switch panic mode
+ *
+ * @param regulator The regulator to be configured.
+ * @param panic_mode Enable or disable panic mode
+ *
+ * @return This function returns PMIC_SUCCESS if successful.
+ */
+PMIC_STATUS pmic_power_switcher_set_panic_mode(t_pmic_regulator regulator,
+ bool panic_mode);
+
+/*!
+ * This function gets the switch panic mode
+ *
+ * @param regulator The regulator to be handled
+ * @param panic_mode Enable or disable panic mode
+ *
+ * @return This function returns PMIC_SUCCESS if successful.
+ */
+PMIC_STATUS pmic_power_switcher_get_panic_mode(t_pmic_regulator regulator,
+ bool * panic_mode);
+
+/*!
+ * This function sets the switch softstart mode
+ *
+ * @param regulator The regulator to be configured.
+ * @param softstart Enable or disable softstart.
+ *
+ * @return This function returns PMIC_SUCCESS if successful.
+ */
+PMIC_STATUS pmic_power_switcher_set_softstart(t_pmic_regulator regulator,
+ bool softstart);
+
+/*!
+ * This function gets the switch softstart mode
+ *
+ * @param regulator The regulator to be handled
+ * @param softstart Enable or disable softstart.
+ *
+ * @return This function returns PMIC_SUCCESS if successful.
+ */
+PMIC_STATUS pmic_power_switcher_get_softstart(t_pmic_regulator regulator,
+ bool * softstart);
+
+/*!
+ * This function sets the PLL multiplication factor
+ *
+ * @param regulator The regulator to be configured.
+ * @param factor The multiplication factor.
+ *
+ * @return This function returns PMIC_SUCCESS if successful.
+ */
+PMIC_STATUS pmic_power_switcher_set_factor(t_pmic_regulator regulator,
+ t_switcher_factor factor);
+
+/*!
+ * This function gets the PLL multiplication factor
+ *
+ * @param regulator The regulator to be handled
+ * @param factor The multiplication factor.
+ *
+ * @return This function returns PMIC_SUCCESS if successful.
+ */
+PMIC_STATUS pmic_power_switcher_get_factor(t_pmic_regulator regulator,
+ t_switcher_factor * factor);
+
+/*!
+ * This function enables or disables low power mode.
+ *
+ * @param regulator The regulator to be configured.
+ * @param mode Select nominal or low power mode.
+ *
+ * @return This function returns PMIC_SUCCESS if successful.
+ */
+PMIC_STATUS pmic_power_regulator_set_lp_mode(t_pmic_regulator regulator,
+ t_regulator_lp_mode lp_mode);
+
+/*!
+ * This function gets low power mode.
+ *
+ * @param regulator The regulator to be handled
+ * @param mode Select nominal or low power mode.
+ *
+ * @return This function returns PMIC_SUCCESS if successful.
+ */
+PMIC_STATUS pmic_power_regulator_get_lp_mode(t_pmic_regulator regulator,
+ t_regulator_lp_mode * lp_mode);
+
+/*!
+ * This function sets the regulator configuration.
+ *
+ * @param regulator The regulator to be turned off.
+ * @param config The regulator output configuration.
+ *
+ * @return This function returns PMIC_SUCCESS if successful.
+ */
+PMIC_STATUS pmic_power_regulator_set_config(t_pmic_regulator regulator,
+ t_regulator_config * config);
+
+/*!
+ * This function retrieves the regulator output configuration.
+ *
+ * @param regulator The regulator to be turned off.
+ * @param config Pointer to regulator configuration.
+ *
+ * @return This function returns PMIC_SUCCESS if successful.
+ */
+PMIC_STATUS pmic_power_regulator_get_config(t_pmic_regulator regulator,
+ t_regulator_config * config);
+
+/*!
+ * This function enables automatically VBKUP2 in the memory hold modes.
+ *
+ * @param en if true, enable VBKUP2AUTOMH
+ *
+ * @return This function returns PMIC_SUCCESS if successful.
+ */
+PMIC_STATUS pmic_power_vbkup2_auto_en(bool en);
+
+/*!
+ * This function gets state of automatically VBKUP2.
+ *
+ * @param en if true, VBKUP2AUTOMH is enabled
+ *
+ * @return This function returns PMIC_SUCCESS if successful.
+ */
+PMIC_STATUS pmic_power_get_vbkup2_auto_state(bool * en);
+
+/*!
+ * This function enables battery detect function.
+ *
+ * @param en if true, enable BATTDETEN
+ *
+ * @return This function returns PMIC_SUCCESS if successful.
+ */
+PMIC_STATUS pmic_power_bat_det_en(bool en);
+
+/*!
+ * This function gets state of battery detect function.
+ *
+ * @param en if true, BATTDETEN is enabled
+ *
+ * @return This function returns PMIC_SUCCESS if successful.
+ */
+PMIC_STATUS pmic_power_get_bat_det_state(bool * en);
+
+/*!
+ * This function enables control of VVIB by VIBEN pin.
+ *
+ * @param en if true, enable VIBPINCTRL
+ *
+ * @return This function returns PMIC_SUCCESS if successful.
+ */
+PMIC_STATUS pmic_power_vib_pin_en(bool en);
+
+/*!
+ * This function gets state of control of VVIB by VIBEN pin.
+ * @param en if true, VIBPINCTRL is enabled
+ *
+ * @return This function returns PMIC_SUCCESS if successful.
+ */
+PMIC_STATUS pmic_power_gets_vib_pin_state(bool * en);
+
+/*!
+ * This function returns power up sense value
+ *
+ * @param p_up_sense value of power up sense
+ * @return This function returns PMIC_SUCCESS if successful.
+ */
+PMIC_STATUS pmic_power_get_power_mode_sense(struct t_p_up_sense *p_up_sense);
+
+/*!
+ * This function configures the Regen assignment for all regulator
+ *
+ * @param regulator type of regulator
+ * @param en_dis if true, the regulator is enabled by regen.
+ *
+ * @return This function returns 0 if successful.
+ */
+PMIC_STATUS pmic_power_set_regen_assig(t_pmic_regulator regulator, bool en_dis);
+
+/*!
+ * This function gets the Regen assignment for all regulator
+ *
+ * @param regulator type of regulator
+ * @param en_dis return value, if true :
+ * the regulator is enabled by regen.
+ * @return This function returns 0 if successful.
+ */
+PMIC_STATUS pmic_power_get_regen_assig(t_pmic_regulator regu, bool * en_dis);
+
+/*!
+ * This function sets the Regen polarity.
+ *
+ * @param en_dis If true regen is inverted.
+ *
+ * @return This function returns 0 if successful.
+ */
+PMIC_STATUS pmic_power_set_regen_inv(bool en_dis);
+
+/*!
+ * This function gets the Regen polarity.
+ *
+ * @param en_dis If true regen is inverted.
+ *
+ * @return This function returns 0 if successful.
+ */
+
+PMIC_STATUS pmic_power_get_regen_inv(bool * en_dis);
+
+/*!
+ * This function enables esim control voltage.
+ *
+ * @param vesim if true, enable VESIMESIMEN
+ * @param vmmc1 if true, enable VMMC1ESIMEN
+ * @param vmmc2 if true, enable VMMC2ESIMEN
+ *
+ * @return This function returns 0 if successful.
+ */
+PMIC_STATUS pmic_power_esim_v_en(bool vesim, bool vmmc1, bool vmmc2);
+
+/*!
+ * This function gets esim control voltage values.
+ *
+ * @param vesim if true, enable VESIMESIMEN
+ * @param vmmc1 if true, enable VMMC1ESIMEN
+ * @param vmmc2 if true, enable VMMC2ESIMEN
+ *
+ * @return This function returns 0 if successful.
+ */
+PMIC_STATUS pmic_power_gets_esim_v_state(bool * vesim,
+ bool * vmmc1, bool * vmmc2);
+
+/*!
+ * This function enables auto reset after a system reset.
+ *
+ * @param en if true, the auto reset is enabled
+ *
+ * @return This function returns 0 if successful.
+ */
+PMIC_STATUS pmic_power_set_auto_reset_en(bool en);
+
+/*!
+ * This function gets auto reset configuration.
+ *
+ * @param en if true, the auto reset is enabled
+ *
+ * @return This function returns 0 if successful.
+ */
+PMIC_STATUS pmic_power_get_auto_reset_en(bool * en);
+
+/*!
+ * This function configures a system reset on a button.
+ *
+ * @param bt type of button.
+ * @param sys_rst if true, enable the system reset on this button
+ * @param deb_time sets the debounce time on this button pin
+ *
+ * @return This function returns 0 if successful.
+ */
+PMIC_STATUS pmic_power_set_conf_button(t_button bt, bool sys_rst, int deb_time);
+
+/*!
+ * This function gets configuration of a button.
+ *
+ * @param bt type of button.
+ * @param sys_rst if true, the system reset is enabled on this button
+ * @param deb_time gets the debounce time on this button pin
+ *
+ * @return This function returns 0 if successful.
+ */
+PMIC_STATUS pmic_power_get_conf_button(t_button bt,
+ bool * sys_rst, int *deb_time);
+
+/*!
+ * This function is used to subscribe on power event IT.
+ *
+ * @param event type of event.
+ * @param callback event callback function.
+ *
+ * @return This function returns 0 if successful.
+ */
+PMIC_STATUS pmic_power_event_sub(t_pwr_int event, void *callback);
+
+/*!
+ * This function is used to un subscribe on power event IT.
+ *
+ * @param event type of event.
+ * @param callback event callback function.
+ *
+ * @return This function returns 0 if successful.
+ */
+PMIC_STATUS pmic_power_event_unsub(t_pwr_int event, void *callback);
+
+#endif /* __KERNEL__ */
+
+#endif /* __ASM_ARCH_MXC_PMIC_POWER_H__ */
diff --git a/arch/arm/plat-mxc/include/mach/sdma.h b/arch/arm/plat-mxc/include/mach/sdma.h
new file mode 100644
index 000000000000..d864b0680fbd
--- /dev/null
+++ b/arch/arm/plat-mxc/include/mach/sdma.h
@@ -0,0 +1,561 @@
+
+/*
+ * Copyright 2004-2009 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 __ASM_ARCH_MXC_SDMA_H__
+#define __ASM_ARCH_MXC_SDMA_H__
+
+/*!
+ * @defgroup SDMA Smart Direct Memory Access (SDMA) Driver
+ */
+
+/*!
+ * @file arch-mxc/sdma.h
+ *
+ * @brief This file contains the SDMA API declarations.
+ *
+ * SDMA is responsible on moving data between peripherals and memories (MCU, EMI and DSP).
+ *
+ * @ingroup SDMA
+ */
+
+#include <linux/interrupt.h>
+#include <asm/dma.h>
+#include <stdarg.h>
+
+#include <mach/hardware.h>
+#include <mach/dma.h>
+
+/*!
+ * This defines maximum DMA address
+ */
+#define MAX_DMA_ADDRESS 0xffffffff
+
+/*!
+ * This defines maximum number of DMA channels
+ */
+#ifdef CONFIG_MXC_SDMA_API
+#define MAX_DMA_CHANNELS 32
+#define MAX_BD_NUMBER 16
+#define MXC_SDMA_DEFAULT_PRIORITY 1
+#define MXC_SDMA_MIN_PRIORITY 1
+#define MXC_SDMA_MAX_PRIORITY 7
+#else
+#define MAX_DMA_CHANNELS 0
+#endif
+
+#define MXC_FIFO_MEM_DEST_FIXED 0x1
+#define MXC_FIFO_MEM_SRC_FIXED 0x2
+
+#define SDMA_ASRC_INFO_WML_OFF 0
+#define SDMA_ASRC_INFO_WML_MASK ((1 << 10) - 1)
+#define SDMA_ASRC_INFO_PS (1 << 10)
+#define SDMA_ASRC_INFO_PA (1 << 11)
+#define SDMA_ASRC_INFO_TXFR_DIR (1 << 14)
+#define SDMA_ASRC_INFO_N_OFF (24)
+#define SDMA_ASRC_INFO_N_MASK ((1 << 4) - 1)
+
+#define SDMA_ASRC_P2P_INFO_LWML_OFF 0
+#define SDMA_ASRC_P2P_INFO_LWML_MASK ((1 << 8) - 1)
+#define SDMA_ASRC_P2P_INFO_PS (1 << 8)
+#define SDMA_ASRC_P2P_INFO_PA (1 << 9)
+#define SDMA_ASRC_P2P_INFO_SPDIF (1 << 10)
+#define SDMA_ASRC_P2P_INFO_SP (1 << 11)
+#define SDMA_ASRC_P2P_INFO_DP (1 << 12)
+#define SDMA_ASRC_P2P_INFO_HWML_OFF 14
+#define SDMA_ASRC_P2P_INFO_HWML_MASK ((1 << 10) - 1)
+#define SDMA_ASRC_P2P_INFO_LWE (1 << 28)
+#define SDMA_ASRC_P2P_INFO_HWE (1 << 29)
+#define SDMA_ASRC_P2P_INFO_CONT (1 << 31)
+
+/*!
+ * This enumerates transfer types
+ */
+typedef enum {
+ emi_2_per = 0, /*!< EMI memory to peripheral */
+ emi_2_int, /*!< EMI memory to internal RAM */
+ emi_2_emi, /*!< EMI memory to EMI memory */
+ emi_2_dsp, /*!< EMI memory to DSP memory */
+ per_2_int, /*!< Peripheral to internal RAM */
+ per_2_emi, /*!< Peripheral to internal EMI memory */
+ per_2_dsp, /*!< Peripheral to DSP memory */
+ per_2_per, /*!< Peripheral to Peripheral */
+ int_2_per, /*!< Internal RAM to peripheral */
+ int_2_int, /*!< Internal RAM to Internal RAM */
+ int_2_emi, /*!< Internal RAM to EMI memory */
+ int_2_dsp, /*!< Internal RAM to DSP memory */
+ dsp_2_per, /*!< DSP memory to peripheral */
+ dsp_2_int, /*!< DSP memory to internal RAM */
+ dsp_2_emi, /*!< DSP memory to EMI memory */
+ dsp_2_dsp, /*!< DSP memory to DSP memory */
+ emi_2_dsp_loop, /*!< EMI memory to DSP memory loopback */
+ dsp_2_emi_loop, /*!< DSP memory to EMI memory loopback */
+ dvfs_pll, /*!< DVFS script with PLL change */
+ dvfs_pdr /*!< DVFS script without PLL change */
+} sdma_transferT;
+
+/*!
+ * This enumerates peripheral types
+ */
+typedef enum {
+ SSI, /*!< MCU domain SSI */
+ SSI_SP, /*!< Shared SSI */
+ MMC, /*!< MMC */
+ SDHC, /*!< SDHC */
+ UART, /*!< MCU domain UART */
+ UART_SP, /*!< Shared UART */
+ FIRI, /*!< FIRI */
+ CSPI, /*!< MCU domain CSPI */
+ CSPI_SP, /*!< Shared CSPI */
+ SIM, /*!< SIM */
+ ATA, /*!< ATA */
+ CCM, /*!< CCM */
+ EXT, /*!< External peripheral */
+ MSHC, /*!< Memory Stick Host Controller */
+ MSHC_SP, /*!< Shared Memory Stick Host Controller */
+ DSP, /*!< DSP */
+ MEMORY, /*!< Memory */
+ FIFO_MEMORY, /*!< FIFO type Memory */
+ SPDIF, /*!< SPDIF */
+ IPU_MEMORY, /*!< IPU Memory */
+ ASRC, /*!< ASRC */
+ ESAI, /*!< ESAI */
+} sdma_periphT;
+
+#ifndef TRANSFER_32BIT
+/*!
+ * This defines SDMA access data size
+ */
+#define TRANSFER_32BIT 0x00
+#define TRANSFER_8BIT 0x01
+#define TRANSFER_16BIT 0x02
+#define TRANSFER_24BIT 0x03
+
+#endif
+
+/*!
+ * This defines maximum device name length passed during mxc_request_dma().
+ */
+#define MAX_DEVNAME_LENGTH 32
+
+/*!
+ * This defines SDMA interrupt callback function prototype.
+ */
+typedef void (*dma_callback_t) (void *arg);
+
+/*!
+ * Structure containing sdma channel parameters.
+ */
+typedef struct {
+ __u32 watermark_level; /*!< Lower/upper threshold that
+ * triggers SDMA event
+ * for p2p, this is event1 watermark level
+ */
+ __u32 per_address; /*!< Peripheral source/destination
+ * physical address
+ * for p2p, this is destination address
+ */
+ sdma_periphT peripheral_type; /*!< Peripheral type */
+ sdma_transferT transfer_type; /*!< Transfer type */
+ int event_id; /*!< Event number,
+ * needed by all channels
+ * that started by peripherals dma
+ * request (per_2_*,*_2_per)
+ * Not used for memory and DSP
+ * transfers.
+ */
+ int event_id2; /*!< Second event number,
+ * used in ATA scripts only.
+ */
+ int bd_number; /*!< Buffer descriptors number.
+ * If not set, single buffer
+ * descriptor will be used.
+ */
+ dma_callback_t callback; /*! callback function */
+ void *arg; /*! callback argument */
+ unsigned long word_size:8; /*!< SDMA data access word size */
+ unsigned long ext:1; /*!< 1: extend parameter structure */
+} dma_channel_params;
+
+typedef struct {
+ dma_channel_params common;
+ unsigned long p2p_dir:1; /*!< 0: per2 to per.
+ * the device of peripheral_type is per.
+ * 1: per to per2
+ * the device of peripheral_type is per2
+ */
+ unsigned long info_bits; /*!< info field in context */
+ unsigned long info_mask; /*!< info field mask in context */
+ __u32 watermark_level2; /*!< event2 threshold that
+ * triggers SDMA event
+ * just valid for p2p.
+ */
+ __u32 per_address2; /*!< Peripheral source
+ * physical address.
+ * just valid for p2p.
+ */
+ struct dma_channel_info info; /*!< the channel special parameter */
+} dma_channel_ext_params;
+
+/*!
+ * Structure containing sdma request parameters.
+ */
+typedef struct {
+ /*! physical source memory address */
+ __u8 *sourceAddr;
+ /*! physical destination memory address */
+ __u8 *destAddr;
+ /*! amount of data to transfer,
+ * updated during mxc_dma_get_config
+ */
+ __u16 count;
+ /*!< DONE bit of the buffer descriptor,
+ * updated during mxc_dma_get_config
+ * 0 - means the BD is done and closed by SDMA
+ * 1 - means the BD is still being processed by SDMA
+ */
+ int bd_done;
+ /*!< CONT bit of the buffer descriptor,
+ * set it if full multi-buffer descriptor mechanism
+ * required.
+ */
+ int bd_cont;
+ /*!< ERROR bit of the buffer descriptor,
+ * updated during mxc_dma_get_config.
+ * If it is set - there was an error during BD processing.
+ */
+ int bd_error;
+} dma_request_t;
+
+/*!
+ * Structure containing sdma request parameters.
+ */
+typedef struct {
+ /*! address of ap_2_ap script */
+ int mxc_sdma_ap_2_ap_addr;
+ /*! address of ap_2_bp script */
+ int mxc_sdma_ap_2_bp_addr;
+ /*! address of ap_2_ap_fixed script */
+ int mxc_sdma_ap_2_ap_fixed_addr;
+ /*! address of bp_2_ap script */
+ int mxc_sdma_bp_2_ap_addr;
+ /*! address of loopback_on_dsp_side script */
+ int mxc_sdma_loopback_on_dsp_side_addr;
+ /*! address of mcu_interrupt_only script */
+ int mxc_sdma_mcu_interrupt_only_addr;
+
+ /*! address of firi_2_per script */
+ int mxc_sdma_firi_2_per_addr;
+ /*! address of firi_2_mcu script */
+ int mxc_sdma_firi_2_mcu_addr;
+ /*! address of per_2_firi script */
+ int mxc_sdma_per_2_firi_addr;
+ /*! address of mcu_2_firi script */
+ int mxc_sdma_mcu_2_firi_addr;
+
+ /*! address of uart_2_per script */
+ int mxc_sdma_uart_2_per_addr;
+ /*! address of uart_2_mcu script */
+ int mxc_sdma_uart_2_mcu_addr;
+ /*! address of per_2_app script */
+ int mxc_sdma_per_2_app_addr;
+ /*! address of mcu_2_app script */
+ int mxc_sdma_mcu_2_app_addr;
+ /*! address of per_2_per script */
+ int mxc_sdma_per_2_per_addr;
+
+ /*! address of uartsh_2_per script */
+ int mxc_sdma_uartsh_2_per_addr;
+ /*! address of uartsh_2_mcu script */
+ int mxc_sdma_uartsh_2_mcu_addr;
+ /*! address of per_2_shp script */
+ int mxc_sdma_per_2_shp_addr;
+ /*! address of mcu_2_shp script */
+ int mxc_sdma_mcu_2_shp_addr;
+
+ /*! address of ata_2_mcu script */
+ int mxc_sdma_ata_2_mcu_addr;
+ /*! address of mcu_2_ata script */
+ int mxc_sdma_mcu_2_ata_addr;
+
+ /*! address of app_2_per script */
+ int mxc_sdma_app_2_per_addr;
+ /*! address of app_2_mcu script */
+ int mxc_sdma_app_2_mcu_addr;
+ /*! address of shp_2_per script */
+ int mxc_sdma_shp_2_per_addr;
+ /*! address of shp_2_mcu script */
+ int mxc_sdma_shp_2_mcu_addr;
+
+ /*! address of mshc_2_mcu script */
+ int mxc_sdma_mshc_2_mcu_addr;
+ /*! address of mcu_2_mshc script */
+ int mxc_sdma_mcu_2_mshc_addr;
+
+ /*! address of spdif_2_mcu script */
+ int mxc_sdma_spdif_2_mcu_addr;
+ /*! address of mcu_2_spdif script */
+ int mxc_sdma_mcu_2_spdif_addr;
+
+ /*! address of asrc_2_mcu script */
+ int mxc_sdma_asrc_2_mcu_addr;
+
+ /*! address of ext_mem_2_ipu script */
+ int mxc_sdma_ext_mem_2_ipu_addr;
+
+ /*! address of descrambler script */
+ int mxc_sdma_descrambler_addr;
+
+ /*! address of dptc_dvfs script */
+ int mxc_sdma_dptc_dvfs_addr;
+
+ int mxc_sdma_utra_addr;
+
+ /*! address where ram code starts */
+ int mxc_sdma_ram_code_start_addr;
+ /*! size of the ram code */
+ int mxc_sdma_ram_code_size;
+ /*! RAM image address */
+ unsigned short *mxc_sdma_start_addr;
+} sdma_script_start_addrs;
+
+/*! Structure to store the initialized dma_channel parameters */
+typedef struct mxc_sdma_channel_params {
+ /*! Channel type (static channel number or dynamic channel) */
+ unsigned int channel_num;
+ /*! Channel priority [0x1(lowest) - 0x7(highest)] */
+ unsigned int chnl_priority;
+ /*! Channel params */
+ dma_channel_params chnl_params;
+} mxc_sdma_channel_params_t;
+
+/*! Structure to store the initialized dma_channel extend parameters */
+typedef struct mxc_sdma_channel_ext_params {
+ /*! Channel type (static channel number or dynamic channel) */
+ unsigned int channel_num;
+ /*! Channel priority [0x1(lowest) - 0x7(highest)] */
+ unsigned int chnl_priority;
+ /*! Channel extend params */
+ dma_channel_ext_params chnl_ext_params;
+} mxc_sdma_channel_ext_params_t;
+
+/*! Private SDMA data structure */
+typedef struct mxc_dma_channel_private {
+ /*! ID of the buffer that was processed */
+ unsigned int buf_tail;
+ /*! Tasklet for the channel */
+ struct tasklet_struct chnl_tasklet;
+ /*! Flag indicates if interrupt is required after every BD transfer */
+ int intr_after_every_bd;
+} mxc_dma_channel_private_t;
+
+/*!
+ * Setup channel according to parameters.
+ * Must be called once after mxc_request_dma()
+ *
+ * @param channel channel number
+ * @param p channel parameters pointer
+ * @return 0 on success, error code on fail
+ */
+int mxc_dma_setup_channel(int channel, dma_channel_params * p);
+
+/*!
+ * Setup the channel priority. This can be used to change the default priority
+ * for the channel.
+ *
+ * @param channel channel number
+ * @param priority priority to be set for the channel
+ *
+ * @return 0 on success, error code on failure
+ */
+int mxc_dma_set_channel_priority(unsigned int channel, unsigned int priority);
+
+/*!
+ * Allocates dma channel.
+ * If channel's value is 0, then the function allocates a free channel
+ * dynamically and sets its value to channel.
+ * Else allocates requested channel if it is free.
+ * If the channel is busy or no free channels (in dynamic allocation) -EBUSY returned.
+ *
+ * @param channel pointer to channel number
+ * @param devicename device name
+ * @return 0 on success, error code on fail
+ */
+int mxc_request_dma(int *channel, const char *devicename);
+
+/*!
+ * Configures request parameters. Can be called multiple times after
+ * mxc_request_dma() and mxc_dma_setup_channel().
+ *
+ *
+ * @param channel channel number
+ * @param p request parameters pointer
+ * @param bd_index index of buffer descriptor to set
+ * @return 0 on success, error code on fail
+ */
+/* int mxc_dma_set_config(int channel, dma_request_t *p, int bd_index); */
+int mxc_dma_set_config(int channel, dma_request_t * p, int bd_index);
+
+/*!
+ * Returns request parameters.
+ *
+ * @param channel channel number
+ * @param p request parameters pointer
+ * @param bd_index index of buffer descriptor to get
+ * @return 0 on success, error code on fail
+ */
+/* int mxc_dma_get_config(int channel, dma_request_t *p, int bd_index); */
+int mxc_dma_get_config(int channel, dma_request_t * p, int bd_index);
+
+/*!
+ * This function is used by MXC IPC's write_ex2. It passes the a pointer to the
+ * data control structure to iapi_write_ipcv2()
+ *
+ * @param channel SDMA channel number
+ * @param ctrl_ptr Data Control structure pointer
+ */
+int mxc_sdma_write_ipcv2(int channel, void *ctrl_ptr);
+
+/*!
+ * This function is used by MXC IPC's read_ex2. It passes the a pointer to the
+ * data control structure to iapi_read_ipcv2()
+ *
+ * @param channel SDMA channel number
+ * @param ctrl_ptr Data Control structure pointer
+ */
+int mxc_sdma_read_ipcv2(int channel, void *ctrl_ptr);
+
+/*!
+ * Starts dma channel.
+ *
+ * @param channel channel number
+ */
+int mxc_dma_start(int channel);
+
+/*!
+ * Stops dma channel.
+ *
+ * @param channel channel number
+ */
+int mxc_dma_stop(int channel);
+
+/*!
+ * Frees dma channel.
+ *
+ * @param channel channel number
+ */
+void mxc_free_dma(int channel);
+
+/*!
+ * Sets callback function. Used with standard dma api
+ * for supporting interrupts
+ *
+ * @param channel channel number
+ * @param callback callback function pointer
+ * @param arg argument for callback function
+ */
+void mxc_dma_set_callback(int channel, dma_callback_t callback, void *arg);
+
+/*!
+ * Allocates uncachable buffer. Uses hash table.
+ *
+ * @param size size of allocated buffer
+ * @return pointer to buffer
+ */
+void *sdma_malloc(size_t size);
+
+#ifdef CONFIG_SDMA_IRAM
+/*!
+ * Allocates uncachable buffer from IRAM..
+ *
+ * @param size size of allocated buffer
+ * @return pointer to buffer
+ */
+void *sdma_iram_malloc(size_t size);
+#endif /*CONFIG_SDMA_IRAM */
+
+/*!
+ * Frees uncachable buffer. Uses hash table.
+ */
+void sdma_free(void *buf);
+
+/*!
+ * Converts virtual to physical address. Uses hash table.
+ *
+ * @param buf virtual address pointer
+ * @return physical address value
+ */
+unsigned long sdma_virt_to_phys(void *buf);
+
+/*!
+ * Converts physical to virtual address. Uses hash table.
+ *
+ * @param buf physical address value
+ * @return virtual address pointer
+ */
+void *sdma_phys_to_virt(unsigned long buf);
+
+/*!
+ * Configures the BD_INTR bit on a buffer descriptor parameters.
+ *
+ *
+ * @param channel channel number
+ * @param bd_index index of buffer descriptor to set
+ * @param bd_intr flag to set or clear the BD_INTR bit
+ */
+void mxc_dma_set_bd_intr(int channel, int bd_index, int bd_intr);
+
+/*!
+ * Gets the BD_INTR bit on a buffer descriptor.
+ *
+ *
+ * @param channel channel number
+ * @param bd_index index of buffer descriptor to set
+ *
+ * @return returns the BD_INTR bit status
+ */
+int mxc_dma_get_bd_intr(int channel, int bd_index);
+
+/*!
+ * Stop the current transfer
+ *
+ * @param channel channel number
+ * @param buffer_number number of buffers (beginning with 0),
+ * whose done bits should be reset to 0
+ */
+int mxc_dma_reset(int channel, int buffer_number);
+
+/*!
+ * This functions Returns the SDMA paramaters associated for a module
+ *
+ * @param channel_id the ID of the module requesting DMA
+ * @return returns the sdma parameters structure for the device
+ */
+mxc_sdma_channel_params_t *mxc_sdma_get_channel_params(mxc_dma_device_t
+ channel_id);
+
+/*!
+ * This functions marks the SDMA channels that are statically allocated
+ *
+ * @param chnl the channel array used to store channel information
+ */
+void mxc_get_static_channels(mxc_dma_channel_t * chnl);
+
+/*!
+ * Initializes SDMA driver
+ */
+int __init sdma_init(void);
+
+#define DEFAULT_ERR 1
+
+#endif
diff --git a/arch/arm/plat-mxc/include/mach/spba.h b/arch/arm/plat-mxc/include/mach/spba.h
new file mode 100644
index 000000000000..8d018be8a0b7
--- /dev/null
+++ b/arch/arm/plat-mxc/include/mach/spba.h
@@ -0,0 +1,66 @@
+
+/*
+ * Copyright 2004-2008 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
+ */
+
+/*!
+ * @defgroup SPBA Shared Peripheral Bus Arbiter (SPBA)
+ * @ingroup MSL_MX31 MSL_MX35 MSL_MX37 MSL_MX51 MSL_MXC91321
+ */
+
+/*!
+ * @file arch-mxc/spba.h
+ * @brief This file contains the Shared Peripheral Bus Arbiter (spba) API.
+ *
+ * @ingroup SPBA
+ */
+
+#ifndef __ASM_ARCH_MXC_SPBA_H__
+#define __ASM_ARCH_MXC_SPBA_H__
+
+#ifdef __KERNEL__
+
+#define MXC_SPBA_RAR_MASK 0x7
+
+/*!
+ * Defines three SPBA masters: A - ARM, C - SDMA (no master B for MX31)
+ */
+enum spba_masters {
+ SPBA_MASTER_A = 1,
+ SPBA_MASTER_B = 2,
+ SPBA_MASTER_C = 4,
+};
+
+/*!
+ * This function allows the three masters (A, B, C) to take ownership of a
+ * shared peripheral.
+ *
+ * @param mod specified module as defined in \b enum \b #spba_module
+ * @param master one of more (or-ed together) masters as defined in \b enum \b #spba_masters
+ *
+ * @return 0 if successful; -1 otherwise.
+ */
+int spba_take_ownership(int mod, int master);
+
+/*!
+ * This function releases the ownership for a shared peripheral.
+ *
+ * @param mod specified module as defined in \b enum \b #spba_module
+ * @param master one of more (or-ed together) masters as defined in \b enum \b #spba_masters
+ *
+ * @return 0 if successful; -1 otherwise.
+ */
+int spba_rel_ownership(int mod, int master);
+
+#endif /* __KERNEL__ */
+
+#endif /* __ASM_ARCH_MXC_SPBA_H__ */
diff --git a/arch/arm/plat-mxc/include/mach/system.h b/arch/arm/plat-mxc/include/mach/system.h
index e56241af870e..126bc8713159 100644
--- a/arch/arm/plat-mxc/include/mach/system.h
+++ b/arch/arm/plat-mxc/include/mach/system.h
@@ -1,7 +1,7 @@
/*
* Copyright (C) 1999 ARM Limited
* Copyright (C) 2000 Deep Blue Solutions Ltd
- * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2004-2008 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
@@ -21,10 +21,7 @@
#ifndef __ASM_ARCH_MXC_SYSTEM_H__
#define __ASM_ARCH_MXC_SYSTEM_H__
-static inline void arch_idle(void)
-{
- cpu_do_idle();
-}
+extern void arch_idle(void);
void arch_reset(char mode, const char *cmd);
diff --git a/arch/arm/plat-mxc/include/mach/timex.h b/arch/arm/plat-mxc/include/mach/timex.h
index 07b4a73c9d2f..46ebeabf8bce 100644
--- a/arch/arm/plat-mxc/include/mach/timex.h
+++ b/arch/arm/plat-mxc/include/mach/timex.h
@@ -22,10 +22,14 @@
#if defined CONFIG_ARCH_MX1
#define CLOCK_TICK_RATE 16000000
-#elif defined CONFIG_ARCH_MX2
+#elif defined CONFIG_ARCH_MX2 || defined CONFIG_ARCH_MX25
#define CLOCK_TICK_RATE 13300000
-#elif defined CONFIG_ARCH_MX3
+#elif defined CONFIG_ARCH_MX3 || defined CONFIG_ARCH_MX35
#define CLOCK_TICK_RATE 16625000
+#elif defined CONFIG_ARCH_MX37
+#define CLOCK_TICK_RATE 8000000
+#elif defined CONFIG_ARCH_MX51
+#define CLOCK_TICK_RATE 8000000
#endif
#endif /* __ASM_ARCH_MXC_TIMEX_H__ */
diff --git a/arch/arm/plat-mxc/include/mach/uncompress.h b/arch/arm/plat-mxc/include/mach/uncompress.h
index de6fe0365982..8314fafacfd5 100644
--- a/arch/arm/plat-mxc/include/mach/uncompress.h
+++ b/arch/arm/plat-mxc/include/mach/uncompress.h
@@ -27,6 +27,8 @@
#include <mach/hardware.h>
+unsigned int system_rev;
+
#define UART(x) (*(volatile unsigned long *)(serial_port + (x)))
#define USR2 0x98
diff --git a/arch/arm/plat-mxc/io.c b/arch/arm/plat-mxc/io.c
new file mode 100644
index 000000000000..7681ecf8dfb6
--- /dev/null
+++ b/arch/arm/plat-mxc/io.c
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2007-2009 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
+ */
+
+/*
+ * mxc custom ioremap implementation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <mach/hardware.h>
+#include <linux/io.h>
+
+void *__iomem __mxc_ioremap(unsigned long cookie, size_t size,
+ unsigned int mtype)
+{
+ if (mtype == MT_DEVICE && IS_MEM_DEVICE_NONSHARED(cookie)) {
+ mtype = MT_DEVICE_NONSHARED;
+ }
+ return __arm_ioremap(cookie, size, mtype);
+}
+
+EXPORT_SYMBOL(__mxc_ioremap);
+
+void __mxc_iounmap(void __iomem * addr)
+{
+ extern void __iounmap(volatile void __iomem * addr);
+
+ __iounmap(addr);
+}
+
+EXPORT_SYMBOL(__mxc_iounmap);
diff --git a/arch/arm/plat-mxc/irq.c b/arch/arm/plat-mxc/irq.c
index 8aee76304f8f..c98e5b3c7edf 100644
--- a/arch/arm/plat-mxc/irq.c
+++ b/arch/arm/plat-mxc/irq.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2004-2009 Freescale Semiconductor, Inc. All Rights Reserved.
* Copyright 2008 Juergen Beisert, kernel@pengutronix.de
*
* This program is free software; you can redistribute it and/or
@@ -20,6 +20,7 @@
#include <linux/module.h>
#include <linux/irq.h>
#include <linux/io.h>
+#include <linux/sysdev.h>
#include <mach/common.h>
#include <asm/mach/irq.h>
#include <mach/hardware.h>
@@ -46,6 +47,11 @@
static void __iomem *avic_base;
+#define IRQ_BIT(irq) (1 << (irq))
+
+static uint32_t saved_wakeup_low, saved_wakeup_high;
+static uint32_t suspend_wakeup_low, suspend_wakeup_high;
+
int imx_irq_set_priority(unsigned char irq, unsigned char prio)
{
#ifdef CONFIG_MXC_IRQ_PRIOR
@@ -102,13 +108,122 @@ static void mxc_unmask_irq(unsigned int irq)
__raw_writel(irq, avic_base + AVIC_INTENNUM);
}
+/*!
+ * Set interrupt number "irq" in the AVIC as a wake-up source.
+ *
+ * @param irq interrupt source number
+ * @param enable enable as wake-up if equal to non-zero
+ * disble as wake-up if equal to zero
+ *
+ * @return This function returns 0 on success.
+ */
+static int mxc_set_wake_irq(unsigned int irq, unsigned int enable)
+{
+ uint32_t *wakeup_intr;
+ uint32_t irq_bit;
+
+ if (irq < 32) {
+ wakeup_intr = &suspend_wakeup_low;
+ irq_bit = IRQ_BIT(irq);
+ } else {
+ wakeup_intr = &suspend_wakeup_high;
+ irq_bit = IRQ_BIT(irq - 32);
+ }
+
+ if (enable) {
+ *wakeup_intr |= irq_bit;
+ } else {
+ *wakeup_intr &= ~irq_bit;
+ }
+
+ return 0;
+}
+
static struct irq_chip mxc_avic_chip = {
.ack = mxc_mask_irq,
.mask = mxc_mask_irq,
.unmask = mxc_unmask_irq,
+ .set_wake = mxc_set_wake_irq,
+};
+
+#ifdef CONFIG_PM
+/*!
+ * This function puts the AVIC in low-power mode/state.
+ * All the interrupts that are enabled are first saved.
+ * Only those interrupts which registers as a wake source by calling
+ * enable_irq_wake are enabled. All other interrupts are disabled.
+ *
+ * @param dev the system device structure used to give information
+ * on AVIC to suspend
+ * @param mesg the power state the device is entering
+ *
+ * @return The function always returns 0.
+ */
+static int mxc_avic_suspend(struct sys_device *dev, pm_message_t mesg)
+{
+ saved_wakeup_high = __raw_readl(avic_base + AVIC_INTENABLEH);
+ saved_wakeup_low = __raw_readl(avic_base + AVIC_INTENABLEL);
+
+ __raw_writel(suspend_wakeup_high, avic_base + AVIC_INTENABLEH);
+ __raw_writel(suspend_wakeup_low, avic_base + AVIC_INTENABLEL);
+
+ return 0;
+}
+
+/*!
+ * This function brings the AVIC back from low-power state.
+ * All the interrupts enabled before suspension are re-enabled from
+ * the saved information.
+ *
+ * @param dev the system device structure used to give information
+ * on AVIC to resume
+ *
+ * @return The function always returns 0.
+ */
+static int mxc_avic_resume(struct sys_device *dev)
+{
+ __raw_writel(saved_wakeup_high, avic_base + AVIC_INTENABLEH);
+ __raw_writel(saved_wakeup_low, avic_base + AVIC_INTENABLEL);
+
+ return 0;
+}
+
+#else
+#define mxc_avic_suspend NULL
+#define mxc_avic_resume NULL
+#endif /* CONFIG_PM */
+/*!
+ * This structure contains pointers to the power management callback functions.
+ */
+static struct sysdev_class mxc_avic_sysclass = {
+ .name = "mxc_irq",
+ .suspend = mxc_avic_suspend,
+ .resume = mxc_avic_resume,
+};
+
+/*!
+ * This structure represents AVIC as a system device.
+ * System devices follow a slightly different driver model.
+ * They don't need to do dynammic driver binding, can't be probed,
+ * and don't reside on any type of peripheral bus.
+ * So, it is represented and treated a little differently.
+ */
+static struct sys_device mxc_avic_device = {
+ .id = 0,
+ .cls = &mxc_avic_sysclass,
};
/*
+ * This function is used to get the AVIC Lo and Hi interrupts
+ * that are enabled as wake up sources to wake up the core from suspend
+ */
+void mxc_get_wake_irq(u32 * wake_src[])
+{
+ *wake_src[0] = __raw_readl(avic_base + AVIC_INTENABLEL);
+ *wake_src[1] = __raw_readl(avic_base + AVIC_INTENABLEH);
+}
+
+/*
* This function initializes the AVIC hardware and disables all the
* interrupts. It registers the interrupt enable and disable functions
* to the kernel for each interrupt source.
@@ -142,14 +257,39 @@ void __init mxc_init_irq(void)
for (i = 0; i < 8; i++)
__raw_writel(0, avic_base + AVIC_NIPRIORITY(i));
- /* init architectures chained interrupt handler */
- mxc_register_gpios();
#ifdef CONFIG_FIQ
/* Initialize FIQ */
init_FIQ();
#endif
+ if (MXC_INT_FORCE >= 32)
+ __raw_writel(1 << (MXC_INT_FORCE & 31), avic_base + AVIC_INTFRCH);
+ else if (MXC_INT_FORCE >= 0)
+ __raw_writel(1 << MXC_INT_FORCE, avic_base + AVIC_INTFRCL);
+
printk(KERN_INFO "MXC IRQ initialized\n");
}
+/*!
+ * This function registers AVIC hardware as a system device.
+ * System devices will only be suspended with interrupts disabled, and
+ * after all other devices have been suspended. On resume, they will be
+ * resumed before any other devices, and also with interrupts disabled.
+ *
+ * @return This function returns 0 on success.
+ */
+static int __init mxc_avic_sysinit(void)
+{
+ int ret = 0;
+
+ ret = sysdev_class_register(&mxc_avic_sysclass);
+ if (ret == 0) {
+ ret = sysdev_register(&mxc_avic_device);
+ }
+
+ return ret;
+}
+
+arch_initcall(mxc_avic_sysinit);
+
diff --git a/arch/arm/plat-mxc/isp1301xc.c b/arch/arm/plat-mxc/isp1301xc.c
new file mode 100644
index 000000000000..dceea44fd4da
--- /dev/null
+++ b/arch/arm/plat-mxc/isp1301xc.c
@@ -0,0 +1,290 @@
+/*
+ * Copyright 2005-2009 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/module.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/usb/fsl_xcvr.h>
+#include <linux/i2c.h>
+
+#include <mach/arc_otg.h>
+
+/*
+ * ISP1301 register addresses,all register of ISP1301
+ * is one-byte length register
+ */
+
+/* ISP1301: I2C device address */
+#define ISP1301_DEV_ADDR 0x2D
+
+/* ISP 1301 register set*/
+#define ISP1301_MODE_REG1_SET 0x04
+#define ISP1301_MODE_REG1_CLR 0x05
+
+#define ISP1301_CTRL_REG1_SET 0x06
+#define ISP1301_CTRL_REG1_CLR 0x07
+
+#define ISP1301_INT_SRC_REG 0x08
+#define ISP1301_INT_LAT_REG_SET 0x0a
+#define ISP1301_INT_LAT_REG_CLR 0x0b
+#define ISP1301_INT_FALSE_REG_SET 0x0c
+#define ISP1301_INT_FALSE_REG_CLR 0x0d
+#define ISP1301_INT_TRUE_REG_SET 0x0e
+#define ISP1301_INT_TRUE_REG_CLR 0x0f
+
+#define ISP1301_CTRL_REG2_SET 0x10
+#define ISP1301_CTRL_REG2_CLR 0x11
+
+#define ISP1301_MODE_REG2_SET 0x12
+#define ISP1301_MODE_REG2_CLR 0x13
+
+#define ISP1301_BCD_DEV_REG0 0x14
+#define ISP1301_BCD_DEV_REG1 0x15
+
+/* OTG Control register bit description */
+#define DP_PULLUP 0x01
+#define DM_PULLUP 0x02
+#define DP_PULLDOWN 0x04
+#define DM_PULLDOWN 0x08
+#define ID_PULLDOWN 0x10
+#define VBUS_DRV 0x20
+#define VBUS_DISCHRG 0x40
+#define VBUS_CHRG 0x80
+
+/* Mode Control 1 register bit description */
+#define SPEED_REG 0x01
+#define SUSPEND_REG 0x02
+#define DAT_SE0 0x04
+#define TRANSP_EN 0x08
+#define BDIS_ACON_EN 0x10
+#define OE_INT_EN 0x20
+#define UART_EN 0x40
+
+/* Mode Control 2 register bit description */
+#define SPD_SUSP_CTRL 0x02
+#define BI_DI 0x04
+
+static int isp1301_attach(struct i2c_adapter *adapter);
+static int isp1301_detach(struct i2c_client *client);
+
+static struct i2c_driver isp1301_i2c_driver = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "isp1301 Client",
+ },
+ .attach_adapter = isp1301_attach,
+ .detach_client = isp1301_detach,
+};
+
+static struct i2c_client isp1301_i2c_client = {
+ .name = "isp1301 I2C dev",
+ .addr = ISP1301_DEV_ADDR,
+ .driver = &isp1301_i2c_driver,
+};
+
+static unsigned short normal_i2c[] = { ISP1301_DEV_ADDR, I2C_CLIENT_END };
+
+/* Magic definition of all other variables and things */
+I2C_CLIENT_INSMOD;
+
+static int isp1301_detect_client(struct i2c_adapter *adapter, int address,
+ int kind)
+{
+ isp1301_i2c_client.adapter = adapter;
+ if (i2c_attach_client(&isp1301_i2c_client)) {
+ isp1301_i2c_client.adapter = NULL;
+ printk(KERN_ERR "isp1301_attach: i2c_attach_client failed\n");
+ return -1;
+ }
+
+ printk(KERN_INFO "isp1301 Detected\n");
+ return 0;
+}
+
+/*!
+ * isp1301 I2C attach function
+ *
+ * @param adapter struct i2c_adapter *
+ * @return Error code indicating success or failure
+ */
+static int isp1301_attach(struct i2c_adapter *adapter)
+{
+ return i2c_probe(adapter, &addr_data, &isp1301_detect_client);
+}
+
+/*!
+ * isp1301 I2C detach function
+ *
+ * @param client struct i2c_client *
+ * @return Error code indicating success or failure
+ */
+static int isp1301_detach(struct i2c_client *client)
+{
+ int err;
+
+ if (!isp1301_i2c_client.adapter)
+ return -1;
+
+ err = i2c_detach_client(&isp1301_i2c_client);
+ isp1301_i2c_client.adapter = NULL;
+
+ return err;
+}
+
+static void isp1301_init(struct fsl_xcvr_ops *this)
+{
+ pr_debug("%s\n", __FUNCTION__);
+
+ i2c_add_driver(&isp1301_i2c_driver);
+}
+
+static void isp1301_uninit(struct fsl_xcvr_ops *this)
+{
+ // DDD do this for host only:
+ /* disable OTG VBUS */
+ i2c_del_driver(&isp1301_i2c_driver);
+}
+
+/* Write ISP1301 register*/
+static inline void isp1301_write_reg(char reg, char data)
+{
+ i2c_smbus_write_byte_data(&isp1301_i2c_client, reg, data);
+}
+
+/* read ISP1301 register*/
+static inline char isp1301_read_reg(char reg)
+{
+ return i2c_smbus_read_byte_data(&isp1301_i2c_client, reg);
+}
+
+/* set ISP1301 as USB host*/
+static inline void isp1301_set_serial_host(void)
+{
+ pr_debug("%s\n", __FUNCTION__);
+
+ isp1301_write_reg(ISP1301_MODE_REG2_CLR, 0xFF);
+#if defined(CONFIG_MXC_USB_SB3) || defined(CONFIG_MXC_USB_DB4)
+ isp1301_write_reg(ISP1301_MODE_REG2_SET, SPD_SUSP_CTRL | BI_DI);
+#else
+ isp1301_write_reg(ISP1301_MODE_REG2_SET, SPD_SUSP_CTRL);
+#endif
+
+ isp1301_write_reg(ISP1301_MODE_REG1_CLR, 0xFF);
+#if defined(CONFIG_MXC_USB_SB3) || defined(CONFIG_MXC_USB_SU6)
+ isp1301_write_reg(ISP1301_MODE_REG1_SET, DAT_SE0 | SPEED_REG);
+#else
+ isp1301_write_reg(ISP1301_MODE_REG1_SET, SPEED_REG);
+#endif
+
+ /* configure transceiver for host mode */
+ isp1301_write_reg(ISP1301_CTRL_REG1_SET,
+ (VBUS_DRV | DP_PULLDOWN | DM_PULLDOWN));
+}
+
+/* set ISP1301 as USB device */
+static inline void isp1301_set_serial_dev(void)
+{
+ pr_debug("%s\n", __FUNCTION__);
+
+ isp1301_write_reg(ISP1301_MODE_REG2_CLR, 0xFF);
+#if defined(CONFIG_MXC_USB_SB3) || defined(CONFIG_MXC_USB_DB4)
+ isp1301_write_reg(ISP1301_MODE_REG2_SET, SPD_SUSP_CTRL | BI_DI);
+#else
+ isp1301_write_reg(ISP1301_MODE_REG2_SET, SPD_SUSP_CTRL);
+#endif
+
+ isp1301_write_reg(ISP1301_MODE_REG1_CLR, 0xFF);
+#if defined(CONFIG_MXC_USB_SB3) || defined(CONFIG_MXC_USB_SU6)
+ isp1301_write_reg(ISP1301_MODE_REG1_SET, DAT_SE0 | SPEED_REG);
+#else
+ isp1301_write_reg(ISP1301_MODE_REG1_SET, SPEED_REG);
+#endif
+
+ /* FS mode, DP pull down, DM pull down */
+ isp1301_write_reg(ISP1301_CTRL_REG1_SET,
+ (DP_PULLDOWN | DM_PULLDOWN | DP_PULLUP));
+}
+
+static void isp1301_set_vbus_power(struct fsl_xcvr_ops *this,
+ struct fsl_usb2_platform_data *pdata, int on)
+{
+ pr_debug("%s(on=%d)\n", __FUNCTION__, on);
+ if (on) {
+ /* disable D+ pull-up */
+ isp1301_write_reg(ISP1301_CTRL_REG1_CLR, DP_PULLUP);
+ /* enable D+ pull-down */
+ isp1301_write_reg(ISP1301_CTRL_REG1_SET, DP_PULLDOWN);
+ /* turn on Vbus */
+ isp1301_write_reg(ISP1301_CTRL_REG1_SET, VBUS_DRV);
+ } else {
+ /* D+ pull up, D- pull down */
+ isp1301_write_reg(ISP1301_CTRL_REG1_SET,
+ (DP_PULLUP | DM_PULLDOWN));
+ /* disable D- pull up, disable D+ pull down */
+ isp1301_write_reg(ISP1301_CTRL_REG1_CLR,
+ (DM_PULLUP | DP_PULLDOWN));
+ }
+}
+
+/*
+ * Enable or disable the D+ pullup.
+ */
+static void isp1301_pullup(int on)
+{
+ pr_debug("%s(%d)\n", __func__, on);
+
+ if (on)
+ isp1301_write_reg(ISP1301_CTRL_REG1_SET, DP_PULLUP);
+ else
+ isp1301_write_reg(ISP1301_CTRL_REG1_CLR, DP_PULLUP);
+}
+
+static struct fsl_xcvr_ops isp1301_ops_otg = {
+ .name = "isp1301",
+ .xcvr_type = PORTSC_PTS_SERIAL,
+ .init = isp1301_init,
+ .uninit = isp1301_uninit,
+ .set_host = isp1301_set_serial_host,
+ .set_device = isp1301_set_serial_dev,
+ .set_vbus_power = isp1301_set_vbus_power,
+ .pullup = isp1301_pullup,
+};
+
+extern void fsl_usb_xcvr_register(struct fsl_xcvr_ops *xcvr_ops);
+
+static int __init isp1301xc_init(void)
+{
+ pr_debug("%s\n", __FUNCTION__);
+
+ fsl_usb_xcvr_register(&isp1301_ops_otg);
+
+ return 0;
+}
+
+extern void fsl_usb_xcvr_unregister(struct fsl_xcvr_ops *xcvr_ops);
+
+static void __exit isp1301xc_exit(void)
+{
+ fsl_usb_xcvr_unregister(&isp1301_ops_otg);
+}
+
+module_init(isp1301xc_init);
+module_exit(isp1301xc_exit);
+
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_DESCRIPTION("isp1301");
+MODULE_LICENSE("GPL");
diff --git a/arch/arm/plat-mxc/isp1504xc.c b/arch/arm/plat-mxc/isp1504xc.c
new file mode 100644
index 000000000000..e9a126454d53
--- /dev/null
+++ b/arch/arm/plat-mxc/isp1504xc.c
@@ -0,0 +1,279 @@
+/*
+ * Copyright 2005-2009 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/module.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/platform_device.h>
+#include <linux/fsl_devices.h>
+#include <linux/delay.h>
+#include <linux/usb/fsl_xcvr.h>
+
+#include <mach/hardware.h>
+#include <mach/arc_otg.h>
+#include <asm/mach-types.h>
+
+/* ISP 1504 register addresses */
+#define ISP1504_VID_LOW 0x00 /* Vendor ID low */
+#define ISP1504_VID_HIGH 0x01 /* Vendor ID high */
+#define ISP1504_PID_LOW 0x02 /* Product ID low */
+#define ISP1504_PID_HIGH 0x03 /* Product ID high */
+#define ISP1504_FUNC 0x04 /* Function Control */
+#define ISP1504_ITFCTL 0x07 /* Interface Control */
+#define ISP1504_OTGCTL 0x0A /* OTG Control */
+
+/* add to above register address to access Set/Clear functions */
+#define ISP1504_REG_SET 0x01
+#define ISP1504_REG_CLEAR 0x02
+
+/* 1504 OTG Control Register bits */
+#define USE_EXT_VBUS_IND (1 << 7) /* Use ext. Vbus indicator */
+#define DRV_VBUS_EXT (1 << 6) /* Drive Vbus external */
+#define DRV_VBUS (1 << 5) /* Drive Vbus */
+#define CHRG_VBUS (1 << 4) /* Charge Vbus */
+#define DISCHRG_VBUS (1 << 3) /* Discharge Vbus */
+#define DM_PULL_DOWN (1 << 2) /* enable DM Pull Down */
+#define DP_PULL_DOWN (1 << 1) /* enable DP Pull Down */
+#define ID_PULL_UP (1 << 0) /* enable ID Pull Up */
+
+/* 1504 OTG Function Control Register bits */
+#define SUSPENDM (1 << 6) /* places the PHY into
+ low-power mode */
+#define DRV_RESET (1 << 5) /* Active HIGH transceiver
+ reset */
+
+/*!
+ * read ULPI register 'reg' thru VIEWPORT register 'view'
+ *
+ * @param reg register to read
+ * @param view the ULPI VIEWPORT register address
+ * @return return isp1504 register value
+ */
+static u8 isp1504_read(int reg, volatile u32 *view)
+{
+ u32 data;
+
+ /* make sure interface is running */
+ if (!(__raw_readl(view) && ULPIVW_SS)) {
+ __raw_writel(ULPIVW_WU, view);
+ do { /* wait for wakeup */
+ data = __raw_readl(view);
+ } while (data & ULPIVW_WU);
+ }
+
+ /* read the register */
+ __raw_writel((ULPIVW_RUN | (reg << ULPIVW_ADDR_SHIFT)), view);
+
+ do { /* wait for completion */
+ data = __raw_readl(view);
+ } while (data & ULPIVW_RUN);
+
+ return (u8) (data >> ULPIVW_RDATA_SHIFT) & ULPIVW_RDATA_MASK;
+}
+
+/*!
+ * set bits into OTG ISP1504 register 'reg' thru VIEWPORT register 'view'
+ *
+ * @param bits set value
+ * @param reg which register
+ * @param view the ULPI VIEWPORT register address
+ */
+static void isp1504_set(u8 bits, int reg, volatile u32 *view)
+{
+ u32 data;
+
+ /* make sure interface is running */
+ if (!(__raw_readl(view) && ULPIVW_SS)) {
+ __raw_writel(ULPIVW_WU, view);
+ do { /* wait for wakeup */
+ data = __raw_readl(view);
+ } while (data & ULPIVW_WU);
+ }
+
+ __raw_writel((ULPIVW_RUN | ULPIVW_WRITE |
+ ((reg + ISP1504_REG_SET) << ULPIVW_ADDR_SHIFT) |
+ ((bits & ULPIVW_WDATA_MASK) << ULPIVW_WDATA_SHIFT)),
+ view);
+
+ while (__raw_readl(view) & ULPIVW_RUN) /* wait for completion */
+ continue;
+}
+
+/*!
+ * clear bits in OTG ISP1504 register 'reg' thru VIEWPORT register 'view'
+ *
+ * @param bits bits to clear
+ * @param reg in this register
+ * @param view the ULPI VIEWPORT register address
+ */
+static void isp1504_clear(u8 bits, int reg, volatile u32 *view)
+{
+ __raw_writel((ULPIVW_RUN | ULPIVW_WRITE |
+ ((reg + ISP1504_REG_CLEAR) << ULPIVW_ADDR_SHIFT) |
+ ((bits & ULPIVW_WDATA_MASK) << ULPIVW_WDATA_SHIFT)),
+ view);
+
+ while (__raw_readl(view) & ULPIVW_RUN) /* wait for completion */
+ continue;
+}
+
+extern int gpio_usbotg_hs_active(void);
+
+static void isp1508_fix(u32 *view)
+{
+ if (!machine_is_mx31_3ds())
+ gpio_usbotg_hs_active();
+
+ /* Set bits IND_PASS_THRU and IND_COMPL */
+ isp1504_set(0x60, ISP1504_ITFCTL, view);
+
+ /* Set bit USE_EXT_VBUS_IND */
+ isp1504_set(USE_EXT_VBUS_IND, ISP1504_OTGCTL, view);
+}
+
+/*!
+ * set vbus power
+ *
+ * @param view viewport register
+ * @param on power on or off
+ */
+static void isp1504_set_vbus_power(struct fsl_xcvr_ops *this,
+ struct fsl_usb2_platform_data *pdata, int on)
+{
+ u32 *view = pdata->regs + ULPIVW_OFF;
+
+ pr_debug("real %s(on=%d) view=0x%p\n", __FUNCTION__, on, view);
+
+ pr_debug("ULPI Vendor ID 0x%x Product ID 0x%x\n",
+ (isp1504_read(ISP1504_VID_HIGH, view) << 8) |
+ isp1504_read(ISP1504_VID_LOW, view),
+ (isp1504_read(ISP1504_PID_HIGH, view) << 8) |
+ isp1504_read(ISP1504_PID_LOW, view));
+
+ pr_debug("OTG Control before=0x%x\n",
+ isp1504_read(ISP1504_OTGCTL, view));
+
+ if (on) {
+ isp1504_set(DRV_VBUS_EXT | /* enable external Vbus */
+ DRV_VBUS | /* enable internal Vbus */
+ USE_EXT_VBUS_IND | /* use external indicator */
+ CHRG_VBUS, /* charge Vbus */
+ ISP1504_OTGCTL, view);
+
+ } else {
+ isp1508_fix(view);
+
+ isp1504_clear(DRV_VBUS_EXT | /* disable external Vbus */
+ DRV_VBUS, /* disable internal Vbus */
+ ISP1504_OTGCTL, view);
+
+ isp1504_set(USE_EXT_VBUS_IND | /* use external indicator */
+ DISCHRG_VBUS, /* discharge Vbus */
+ ISP1504_OTGCTL, view);
+ }
+
+ pr_debug("OTG Control after = 0x%x\n",
+ isp1504_read(ISP1504_OTGCTL, view));
+}
+
+/*!
+ * set remote wakeup
+ *
+ * @param view viewport register
+ */
+static void isp1504_set_remote_wakeup(u32 * view)
+{
+ __raw_writel(~ULPIVW_WRITE & __raw_readl(view), view);
+ __raw_writel((1 << ULPIVW_PORT_SHIFT) | __raw_readl(view), view);
+ __raw_writel(ULPIVW_RUN | __raw_readl(view), view);
+
+ while (__raw_readl(view) & ULPIVW_RUN) /* wait for completion */
+ continue;
+}
+
+static void isp1504_init(struct fsl_xcvr_ops *this)
+{
+ pr_debug("%s:\n", __FUNCTION__);
+}
+
+static void isp1504_uninit(struct fsl_xcvr_ops *this)
+{
+ pr_debug("%s:\n", __FUNCTION__);
+}
+
+static void isp1504_suspend(struct fsl_xcvr_ops *this)
+{
+ pr_debug("%s\n", __func__);
+
+ /* send suspend command */
+ isp1504_clear(SUSPENDM, ISP1504_FUNC, &UOG_ULPIVIEW);
+ pr_debug("%s.\n", __func__);
+}
+
+/*!
+ * Set the 1504 transceiver to the proper mode for testing purposes.
+ *
+ * @param view the ULPI VIEWPORT register address
+ * @param test_mode Set the 1504 transceiver to disable bit stuffing and NRZI
+ */
+ static void isp1504_set_test_mode(u32 *view, enum usb_test_mode test_mode)
+{
+ if (test_mode == USB_TEST_J || test_mode == USB_TEST_K) {
+ printk(KERN_INFO "udc: disable bit stuffing and NRZI\n");
+ /* Disable bit-stuffing and NRZI encoding. */
+ isp1504_set(0x10, 0x04, view);
+ }
+}
+
+static struct fsl_xcvr_ops isp1504_ops = {
+ .name = "isp1504",
+ .xcvr_type = PORTSC_PTS_ULPI,
+ .init = isp1504_init,
+ .uninit = isp1504_uninit,
+ .suspend = isp1504_suspend,
+ .set_vbus_power = isp1504_set_vbus_power,
+ .set_remote_wakeup = isp1504_set_remote_wakeup,
+ .set_test_mode = isp1504_set_test_mode,
+};
+
+extern void fsl_usb_xcvr_register(struct fsl_xcvr_ops *xcvr_ops);
+extern int fsl_usb_xcvr_suspend(struct fsl_xcvr_ops *xcvr_ops);
+
+static int __init isp1504xc_init(void)
+{
+ pr_debug("%s\n", __FUNCTION__);
+
+ fsl_usb_xcvr_register(&isp1504_ops);
+
+ /* suspend isp1504 */
+ if (fsl_usb_xcvr_suspend(&isp1504_ops))
+ pr_debug("%s: failed to suspend isp1504\n", __func__);
+
+ return 0;
+}
+
+extern void fsl_usb_xcvr_unregister(struct fsl_xcvr_ops *xcvr_ops);
+
+static void __exit isp1504xc_exit(void)
+{
+ fsl_usb_xcvr_unregister(&isp1504_ops);
+}
+
+module_init(isp1504xc_init);
+module_exit(isp1504xc_exit);
+
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_DESCRIPTION("isp1504 xcvr driver");
+MODULE_LICENSE("GPL");
diff --git a/arch/arm/plat-mxc/leds.c b/arch/arm/plat-mxc/leds.c
new file mode 100644
index 000000000000..e059d238f82b
--- /dev/null
+++ b/arch/arm/plat-mxc/leds.c
@@ -0,0 +1,111 @@
+/*
+ * Copyright 2007-2009 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
+ */
+
+/*
+ * The LED can be used for debugging purpose. To enalbe the LEDs, in the
+ * config file, select:
+ * CONFIG_LEDS
+ * CONFIG_LEDS_TIMER --- enable the OS tick LED once every 50 ticks (.5sec)
+ * CONFIG_LEDS_CPU --- enable the cpu idle in/out LED (blink fast)
+ *
+ * The two LEDs can be disabled through user space by issuing:
+ * echo "claim" > /sys/devices/system/leds/leds0/event
+ * To release the LEDs back to the normal operation, do:
+ * echo "release" > /sys/devices/system/leds/leds0/event
+ */
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/ioport.h>
+#include <asm/mach-types.h>
+#include <mach/hardware.h>
+#include <asm/leds.h>
+
+#define LED_STATE_ENABLED (1 << 0)
+#define LED_STATE_CLAIMED (1 << 1)
+
+static unsigned int led_state;
+static unsigned int hw_led_state;
+
+static void mxc_leds_event(led_event_t evt)
+{
+ unsigned long flags;
+
+ local_irq_save(flags);
+
+ switch (evt) {
+ case led_start:
+ hw_led_state = MXC_BD_LED1 | MXC_BD_LED2;
+ led_state = LED_STATE_ENABLED;
+ break;
+
+ case led_stop:
+ case led_halted:
+ hw_led_state = 0;
+ led_state &= ~LED_STATE_ENABLED;
+ MXC_BD_LED_OFF(MXC_BD_LED1 | MXC_BD_LED2);
+ break;
+
+ case led_claim:
+ led_state |= LED_STATE_CLAIMED;
+ hw_led_state = 0;
+ break;
+
+ case led_release:
+ led_state &= ~LED_STATE_CLAIMED;
+ hw_led_state = 0;
+ break;
+
+#ifdef CONFIG_LEDS_TIMER
+ case led_timer:
+ if (!(led_state & LED_STATE_CLAIMED))
+ hw_led_state ^= MXC_BD_LED1;
+ break;
+#endif
+
+#ifdef CONFIG_LEDS_CPU
+ case led_idle_start:
+ if (!(led_state & LED_STATE_CLAIMED))
+ hw_led_state &= ~MXC_BD_LED2;
+ break;
+
+ case led_idle_end:
+ if (!(led_state & LED_STATE_CLAIMED))
+ hw_led_state |= MXC_BD_LED2;
+ break;
+#endif
+
+ default:
+ break;
+ }
+
+ if (led_state & LED_STATE_ENABLED) {
+ MXC_BD_LED_OFF(~hw_led_state);
+ MXC_BD_LED_ON(hw_led_state);
+ }
+
+ local_irq_restore(flags);
+}
+
+static int __init mxc_leds_init(void)
+{
+ led_state = LED_STATE_ENABLED;
+ leds_event = mxc_leds_event;
+ return 0;
+}
+
+core_initcall(mxc_leds_init);
diff --git a/arch/arm/plat-mxc/mc13783_xc.c b/arch/arm/plat-mxc/mc13783_xc.c
new file mode 100644
index 000000000000..3fad32f3b230
--- /dev/null
+++ b/arch/arm/plat-mxc/mc13783_xc.c
@@ -0,0 +1,299 @@
+/*
+ * Copyright 2005-2009 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/kernel.h>
+#include <linux/workqueue.h>
+#include <linux/platform_device.h>
+#include <linux/usb/fsl_xcvr.h>
+#include <mach/pmic_external.h>
+#include <mach/pmic_convity.h>
+#include <mach/arc_otg.h>
+
+/* Events to be passed to the thread */
+#define MC13783_USB_VBUS_ON 0x0001
+#define MC13783_USB_VBUS_OFF 0x0002
+#define MC13783_USB_DETECT_MINI_A 0x0004
+#define MC13783_USB_DETECT_MINI_B 0x0008
+
+extern void otg_set_serial_peripheral(void);
+extern void otg_set_serial_host(void);
+
+static unsigned int p_event;
+static PMIC_CONVITY_EVENTS g_event;
+static PMIC_CONVITY_HANDLE pmic_handle = (PMIC_CONVITY_HANDLE) NULL;
+
+static void xc_workqueue_handler(struct work_struct *work);
+
+DECLARE_WORK(xc_work, xc_workqueue_handler);
+
+DECLARE_MUTEX(pmic_mx);
+
+static void pmic_event_handler(const PMIC_CONVITY_EVENTS event)
+{
+ if (event & USB_DETECT_4V4_RISE)
+ pr_debug("%s: USB_DETECT_4V4_RISE\n", __func__);
+
+ if (event & USB_DETECT_4V4_FALL)
+ pr_debug("%s: USB_DETECT_4V4_FALL\n", __func__);
+
+ if (event & USB_DETECT_2V0_RISE)
+ pr_debug("%s: USB_DETECT_2V0_RISE\n", __func__);
+
+ if (event & USB_DETECT_2V0_FALL)
+ pr_debug("%s: USB_DETECT_2V0_FALL\n", __func__);
+
+ if (event & USB_DETECT_0V8_RISE)
+ pr_debug("%s: USB_DETECT_0V8_RISE\n", __func__);
+
+ if (event & USB_DETECT_0V8_FALL)
+ pr_debug("%s: USB_DETECT_0V8_FALL\n", __func__);
+
+ if (event & USB_DETECT_MINI_B) {
+ pr_debug("%s: USB_DETECT_MINI_B\n", __func__);
+ otg_set_serial_peripheral();
+ g_event = USB_DETECT_MINI_B;
+ p_event = MC13783_USB_DETECT_MINI_B;
+ schedule_work(&xc_work);
+ }
+ if (event & USB_DETECT_MINI_A) {
+ pr_debug("%s: USB_DETECT_MINI_A\n", __func__);
+ otg_set_serial_host();
+ g_event = USB_DETECT_MINI_A;
+ p_event = MC13783_USB_DETECT_MINI_A;
+ schedule_work(&xc_work);
+ }
+
+ /*
+ * Mini-B cable insertion/removal does not generate cable-detect
+ * event, so we rely on the VBUS changes to identify a mini-b cable
+ * connect. This logic is only used if mini-b is the first cable that
+ * is connected after bootup. At all other times, removal of mini-a
+ * cable is used to initialize peripheral.
+ */
+ if (g_event != USB_DETECT_MINI_A && g_event != USB_DETECT_MINI_B) {
+ if ((event & USB_DETECT_0V8_RISE) &&
+ (event & USB_DETECT_2V0_RISE) &&
+ (event & USB_DETECT_4V4_RISE)) {
+ otg_set_serial_peripheral();
+ g_event = USB_DETECT_MINI_B;
+ p_event = MC13783_USB_DETECT_MINI_B;
+ schedule_work(&xc_work);
+ }
+ }
+}
+
+static int usb_pmic_mod_init(void)
+{
+ PMIC_STATUS rs = PMIC_ERROR;
+
+ init_MUTEX_LOCKED(&pmic_mx);
+
+ rs = pmic_convity_open(&pmic_handle, USB);
+ if (rs != PMIC_SUCCESS) {
+ printk(KERN_ERR "pmic_convity_open returned error %d\n", rs);
+ return rs;
+ }
+
+ rs = pmic_convity_set_callback(pmic_handle, pmic_event_handler,
+ USB_DETECT_4V4_RISE | USB_DETECT_4V4_FALL
+ | USB_DETECT_2V0_RISE |
+ USB_DETECT_2V0_FALL | USB_DETECT_0V8_RISE
+ | USB_DETECT_0V8_FALL | USB_DETECT_MINI_A
+ | USB_DETECT_MINI_B);
+
+ if (rs != PMIC_SUCCESS) {
+ printk(KERN_ERR
+ "pmic_convity_set_callback returned error %d\n", rs);
+ return rs;
+ }
+
+ return rs;
+}
+
+static void usb_pmic_mod_exit(void)
+{
+ PMIC_STATUS rs;
+
+ pmic_convity_set_mode(pmic_handle, RS232_1);
+ pmic_convity_clear_callback(pmic_handle);
+
+ if (pmic_handle != (PMIC_CONVITY_HANDLE) NULL) {
+ rs = pmic_convity_close(pmic_handle);
+ if (rs != PMIC_SUCCESS) {
+ printk(KERN_ERR
+ "pmic_convity_close() returned error %d", rs);
+ } else {
+ pmic_handle = (PMIC_CONVITY_HANDLE) NULL;
+ }
+ }
+}
+
+static inline void mc13783_set_host(void)
+{
+ PMIC_STATUS rs = PMIC_ERROR;
+
+ rs = pmic_convity_usb_otg_clear_config(pmic_handle, USB_OTG_SE0CONN);
+ rs |= pmic_convity_usb_otg_clear_config(pmic_handle, USB_PU);
+
+ rs |= pmic_convity_usb_otg_set_config(pmic_handle, USB_UDM_PD);
+ rs |= pmic_convity_usb_otg_set_config(pmic_handle, USB_UDP_PD);
+
+ if (rs != PMIC_SUCCESS)
+ printk(KERN_ERR "mc13783_set_host failed\n");
+
+}
+
+static inline void mc13783_set_peripheral(void)
+{
+ PMIC_STATUS rs = PMIC_ERROR;
+
+ rs = pmic_convity_usb_otg_clear_config(pmic_handle, USB_UDM_PD);
+ rs |= pmic_convity_usb_otg_clear_config(pmic_handle, USB_UDP_PD);
+
+ rs |= pmic_convity_usb_set_speed(pmic_handle, USB_FULL_SPEED);
+ rs |= pmic_convity_usb_otg_set_config(pmic_handle, USB_OTG_SE0CONN);
+ rs |= pmic_convity_usb_otg_set_config(pmic_handle, USB_PU);
+
+ if (rs != PMIC_SUCCESS)
+ printk(KERN_ERR "mc13783_set_peripheral failed\n");
+}
+
+void mc13783_set_vbus_power(struct fsl_xcvr_ops *this,
+ struct fsl_usb2_platform_data *pdata, int on)
+{
+ if (on) {
+ p_event = MC13783_USB_VBUS_ON;
+ schedule_work(&xc_work);
+ }
+}
+
+static struct fsl_xcvr_ops mc13783_ops_otg = {
+ .name = "mc13783",
+ .xcvr_type = PORTSC_PTS_SERIAL,
+ .set_host = mc13783_set_host,
+ .set_device = mc13783_set_peripheral,
+ .set_vbus_power = mc13783_set_vbus_power,
+};
+
+extern void fsl_usb_xcvr_register(struct fsl_xcvr_ops *xcvr_ops);
+
+static void xc_workqueue_handler(struct work_struct *work)
+{
+ PMIC_STATUS rs = PMIC_ERROR;
+
+ down(&pmic_mx);
+
+ switch (p_event) {
+ case MC13783_USB_VBUS_OFF:
+ mc13783_set_peripheral();
+ break;
+ case MC13783_USB_VBUS_ON:
+ mc13783_set_host();
+ break;
+ case MC13783_USB_DETECT_MINI_B:
+ rs = pmic_convity_set_output(pmic_handle, true, false);
+ rs |=
+ pmic_convity_usb_otg_clear_config(pmic_handle,
+ USB_VBUS_CURRENT_LIMIT_LOW_30MS);
+
+ if (rs != PMIC_SUCCESS)
+ printk(KERN_ERR "MC13783_USB_VBUS_OFF failed\n");
+ break;
+ case MC13783_USB_DETECT_MINI_A:
+ rs = pmic_convity_set_output(pmic_handle, true, true);
+ rs |=
+ pmic_convity_usb_otg_set_config(pmic_handle,
+ USB_VBUS_CURRENT_LIMIT_LOW_30MS);
+
+ if (rs != PMIC_SUCCESS)
+ printk(KERN_ERR "MC13783_USB_VBUS_ON failed\n");
+ break;
+ default:
+ break;
+ }
+ up(&pmic_mx);
+}
+
+int mc13783xc_init(void)
+{
+ PMIC_STATUS rs = PMIC_ERROR;
+
+#if defined(CONFIG_MXC_USB_SB3)
+ int xc_mode = USB_SINGLE_ENDED_BIDIR;
+#elif defined(CONFIG_MXC_USB_SU6)
+ int xc_mode = USB_SINGLE_ENDED_UNIDIR;
+#elif defined(CONFIG_MXC_USB_DB4)
+ int xc_mode = USB_DIFFERENTIAL_BIDIR;
+#else
+ int xc_mode = USB_DIFFERENTIAL_UNIDIR;
+#endif
+
+ rs = usb_pmic_mod_init();
+ if (rs != PMIC_SUCCESS) {
+ usb_pmic_mod_exit();
+ printk(KERN_ERR "usb_pmic_mod_init failed\n");
+ return rs;
+ }
+
+ rs = pmic_convity_usb_set_xcvr(pmic_handle, xc_mode);
+ rs |= pmic_convity_usb_otg_set_config(pmic_handle, USB_OTG_SE0CONN);
+ rs |= pmic_convity_usb_otg_set_config(pmic_handle, USBXCVREN);
+ rs |= pmic_convity_set_output(pmic_handle, false, true);
+
+ rs |= pmic_convity_usb_otg_set_config(pmic_handle, USB_PULL_OVERRIDE);
+ rs |= pmic_convity_usb_otg_clear_config(pmic_handle, USB_USBCNTRL);
+ rs |= pmic_convity_usb_otg_clear_config(pmic_handle, USB_DP150K_PU);
+
+ if (rs != PMIC_SUCCESS)
+ printk(KERN_ERR "pmic configuration failed\n");
+
+ fsl_usb_xcvr_register(&mc13783_ops_otg);
+
+ mc13783_set_peripheral();
+
+ return rs;
+}
+
+extern void fsl_usb_xcvr_unregister(struct fsl_xcvr_ops *xcvr_ops);
+
+void mc13783xc_uninit(void)
+{
+ /* Clear stuff from init */
+ pmic_convity_usb_otg_clear_config(pmic_handle, USB_OTG_SE0CONN);
+ pmic_convity_usb_otg_clear_config(pmic_handle, USBXCVREN);
+ pmic_convity_set_output(pmic_handle, false, false);
+ pmic_convity_usb_otg_clear_config(pmic_handle, USB_PULL_OVERRIDE);
+
+ /* Clear host mode */
+ pmic_convity_usb_otg_clear_config(pmic_handle, USB_UDP_PD);
+ pmic_convity_usb_otg_clear_config(pmic_handle, USB_UDM_PD);
+
+ /* Clear peripheral mode */
+ pmic_convity_usb_otg_clear_config(pmic_handle, USB_PU);
+
+ /* Vbus off */
+ pmic_convity_set_output(pmic_handle, true, false);
+ pmic_convity_usb_otg_clear_config(pmic_handle,
+ USB_VBUS_CURRENT_LIMIT_LOW_30MS);
+
+ usb_pmic_mod_exit();
+
+ fsl_usb_xcvr_unregister(&mc13783_ops_otg);
+}
+
+module_init(mc13783xc_init);
+module_exit(mc13783xc_uninit);
+
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_DESCRIPTION("mc13783xc");
+MODULE_LICENSE("GPL");
diff --git a/arch/arm/plat-mxc/pwm.c b/arch/arm/plat-mxc/pwm.c
index ae34198a79dd..1c663acd89fa 100644
--- a/arch/arm/plat-mxc/pwm.c
+++ b/arch/arm/plat-mxc/pwm.c
@@ -6,6 +6,7 @@
* published by the Free Software Foundation.
*
* Derived from pxa PWM driver by eric miao <eric.miao@marvell.com>
+ * Copyright 2009 Freescale Semiconductor, Inc. All Rights Reserved.
*/
#include <linux/module.h>
@@ -34,7 +35,12 @@
#define MX3_PWMCR_CLKSRC_IPG_HIGH (2 << 16)
#define MX3_PWMCR_EN (1 << 0)
-
+#define MX3_PWMCR_STOPEN (1 << 25)
+#define MX3_PWMCR_DOZEEN (1 << 24)
+#define MX3_PWMCR_WAITEN (1 << 23)
+#define MX3_PWMCR_DBGEN (1 << 22)
+#define MX3_PWMCR_CLKSRC_IPG (1 << 16)
+#define MX3_PWMCR_CLKSRC_IPG_32k (3 << 16)
struct pwm_device {
struct list_head node;
@@ -55,7 +61,7 @@ int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns)
if (pwm == NULL || period_ns == 0 || duty_ns > period_ns)
return -EINVAL;
- if (cpu_is_mx27() || cpu_is_mx3()) {
+ if (cpu_is_mx27() || cpu_is_mx3() || cpu_is_mx51()) {
unsigned long long c;
unsigned long period_cycles, duty_cycles, prescale;
c = clk_get_rate(pwm->clk);
@@ -73,7 +79,9 @@ int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns)
writel(duty_cycles, pwm->mmio_base + MX3_PWMSAR);
writel(period_cycles, pwm->mmio_base + MX3_PWMPR);
writel(MX3_PWMCR_PRESCALER(prescale - 1) |
- MX3_PWMCR_CLKSRC_IPG_HIGH | MX3_PWMCR_EN,
+ MX3_PWMCR_CLKSRC_IPG_HIGH |
+ MX3_PWMCR_STOPEN | MX3_PWMCR_DOZEEN |
+ MX3_PWMCR_WAITEN | MX3_PWMCR_DBGEN,
pwm->mmio_base + MX3_PWMCR);
} else if (cpu_is_mx1() || cpu_is_mx21()) {
/* The PWM subsystem allows for exact frequencies. However,
@@ -105,6 +113,7 @@ EXPORT_SYMBOL(pwm_config);
int pwm_enable(struct pwm_device *pwm)
{
+ unsigned long reg;
int rc = 0;
if (!pwm->clk_enabled) {
@@ -112,16 +121,27 @@ int pwm_enable(struct pwm_device *pwm)
if (!rc)
pwm->clk_enabled = 1;
}
+
+ reg = readl(pwm->mmio_base + MX3_PWMCR);
+ reg |= MX3_PWMCR_EN;
+ writel(reg, pwm->mmio_base + MX3_PWMCR);
return rc;
}
EXPORT_SYMBOL(pwm_enable);
void pwm_disable(struct pwm_device *pwm)
{
+ unsigned long reg;
+
if (pwm->clk_enabled) {
clk_disable(pwm->clk);
pwm->clk_enabled = 0;
}
+
+ reg = readl(pwm->mmio_base + MX3_PWMCR);
+ reg &= ~MX3_PWMCR_EN;
+ writel(reg, pwm->mmio_base + MX3_PWMCR);
+
}
EXPORT_SYMBOL(pwm_disable);
diff --git a/arch/arm/plat-mxc/sdma/Makefile b/arch/arm/plat-mxc/sdma/Makefile
new file mode 100644
index 000000000000..59f94b2da7d0
--- /dev/null
+++ b/arch/arm/plat-mxc/sdma/Makefile
@@ -0,0 +1,18 @@
+ifneq ($(KBUILD_SRC),)
+ccflags-y += -I$(KBUILD_SRC)/arch/arm/plat-mxc/sdma/iapi/include \
+ -I$(KBUILD_SRC)/include/linux \
+ -DMCU -DOS=LINUX \
+ -DL_I_T_T_L_E_ENDIAN=0 -DB_I_G_ENDIAN=1 \
+ -DENDIANNESS=L_I_T_T_L_E_ENDIAN
+else
+ccflags-y += -Iarch/arm/plat-mxc/sdma/iapi/include \
+ -Iinclude/linux \
+ -DMCU -DOS=LINUX \
+ -DL_I_T_T_L_E_ENDIAN=0 -DB_I_G_ENDIAN=1 \
+ -DENDIANNESS=L_I_T_T_L_E_ENDIAN
+endif
+
+obj-y += dma_sdma.o
+obj-$(CONFIG_MXC_SDMA_API) += sdma.o
+obj-$(CONFIG_MXC_SDMA_API) += iapi/
+obj-$(CONFIG_MXC_SDMA_API) += sdma_malloc.o
diff --git a/arch/arm/plat-mxc/sdma/dma_sdma.c b/arch/arm/plat-mxc/sdma/dma_sdma.c
new file mode 100644
index 000000000000..5ca75d08bd08
--- /dev/null
+++ b/arch/arm/plat-mxc/sdma/dma_sdma.c
@@ -0,0 +1,697 @@
+/*
+ * Copyright 2004-2009 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
+ */
+
+/*!
+ * @file plat-mxc/sdma/dma_sdma.c
+ * @brief Front-end to the DMA handling. This handles the allocation/freeing
+ * of DMA channels, and provides a unified interface to the machines
+ * DMA facilities. This file contains functions for Smart DMA.
+ *
+ * @ingroup SDMA
+ */
+
+#include <linux/init.h>
+#include <linux/clk.h>
+#include <linux/dma-mapping.h>
+#include <mach/dma.h>
+#include <mach/hardware.h>
+
+#ifdef CONFIG_MXC_SDMA_API
+
+static mxc_dma_channel_t mxc_sdma_channels[MAX_DMA_CHANNELS];
+static mxc_dma_channel_private_t mxc_sdma_private[MAX_DMA_CHANNELS];
+
+extern struct clk *mxc_sdma_ahb_clk, *mxc_sdma_ipg_clk;
+
+/*!
+ * Tasket to handle processing the channel buffers
+ *
+ * @param arg channel id
+ */
+static void mxc_sdma_channeltasklet(unsigned long arg)
+{
+ dma_request_t request_t;
+ dma_channel_params chnl_param;
+ mxc_dma_channel_t *chnl_info;
+ mxc_dma_channel_private_t *data_priv;
+ int bd_intr = 0, error = MXC_DMA_DONE;
+
+ chnl_info = &mxc_sdma_channels[arg];
+ data_priv = chnl_info->private;
+ chnl_param =
+ mxc_sdma_get_channel_params(chnl_info->channel)->chnl_params;
+
+ mxc_dma_get_config(arg, &request_t, data_priv->buf_tail);
+
+ while (request_t.bd_done == 0) {
+ bd_intr = mxc_dma_get_bd_intr(arg, data_priv->buf_tail);
+ if ((data_priv->buf_tail += 1) >= chnl_param.bd_number) {
+ data_priv->buf_tail = 0;
+ }
+ chnl_info->active = 0;
+ if (request_t.bd_error) {
+ error = MXC_DMA_TRANSFER_ERROR;
+ }
+
+ if (bd_intr != 0) {
+ chnl_info->cb_fn(chnl_info->cb_args, error,
+ request_t.count);
+ error = MXC_DMA_DONE;
+ }
+
+ if (data_priv->buf_tail == chnl_info->curr_buf) {
+ break;
+ }
+ memset(&request_t, 0, sizeof(dma_request_t));
+ mxc_dma_get_config(arg, &request_t, data_priv->buf_tail);
+ }
+}
+
+/*!
+ * This function is generally called by the driver at open time.
+ * The DMA driver would do any initialization steps that is required
+ * to get the channel ready for data transfer.
+ *
+ * @param channel_id a pre-defined id. The peripheral driver would specify
+ * the id associated with its peripheral. This would be
+ * used by the DMA driver to identify the peripheral
+ * requesting DMA and do the necessary setup on the
+ * channel associated with the particular peripheral.
+ * The DMA driver could use static or dynamic DMA channel
+ * allocation.
+ * @param dev_name module name or device name
+ * @return returns a negative number on error if request for a DMA channel did not
+ * succeed, returns the channel number to be used on success.
+ */
+int mxc_dma_request_ext(mxc_dma_device_t channel_id, char *dev_name,
+ struct dma_channel_info *info)
+{
+ mxc_sdma_channel_params_t *chnl;
+ mxc_dma_channel_private_t *data_priv;
+ int ret = 0, i = 0, channel_num = 0;
+ mxc_sdma_channel_ext_params_t *p;
+
+ chnl = mxc_sdma_get_channel_params(channel_id);
+ if (chnl == NULL) {
+ return -EINVAL;
+ }
+
+ if (info) {
+ if (!chnl->chnl_params.ext)
+ return -EINVAL;
+ p = (mxc_sdma_channel_ext_params_t *)chnl;
+ memcpy(&p->chnl_ext_params.info, info, sizeof(info));
+ }
+
+
+ /* Enable the SDMA clock */
+ clk_enable(mxc_sdma_ahb_clk);
+ clk_enable(mxc_sdma_ipg_clk);
+
+ channel_num = chnl->channel_num;
+ if (chnl->channel_num == MXC_DMA_DYNAMIC_CHANNEL) {
+ /* Get the first free channel */
+ for (i = (MAX_DMA_CHANNELS - 1); i > 0; i--) {
+ /* See if channel is available */
+ if ((mxc_sdma_channels[i].dynamic != 1)
+ || (mxc_sdma_channels[i].lock != 0)) {
+ continue;
+ }
+ channel_num = i;
+ /* Check to see if we can get this channel */
+ ret = mxc_request_dma(&channel_num, dev_name);
+ if (ret == 0) {
+ break;
+ } else {
+ continue;
+ }
+ }
+ if (ret != 0) {
+ /* No free channel */
+ goto err_ret;
+ }
+ } else {
+ if (mxc_sdma_channels[chnl->channel_num].lock == 1) {
+ ret = -ENODEV;
+ goto err_ret;
+ }
+ ret = mxc_request_dma(&channel_num, dev_name);
+ if (ret != 0) {
+ goto err_ret;
+ }
+ }
+
+ ret = mxc_dma_setup_channel(channel_num, &chnl->chnl_params);
+
+ if (ret == 0) {
+ if (chnl->chnl_priority != MXC_SDMA_DEFAULT_PRIORITY) {
+ ret =
+ mxc_dma_set_channel_priority(channel_num,
+ chnl->chnl_priority);
+ if (ret != 0) {
+ pr_info("Failed to set channel prority,\
+ continue with the existing \
+ priority\n");
+ goto err_ret;
+ }
+ }
+ mxc_sdma_channels[channel_num].lock = 1;
+ if ((chnl->chnl_params.transfer_type == per_2_emi)
+ || (chnl->chnl_params.transfer_type == dsp_2_emi)) {
+ mxc_sdma_channels[channel_num].mode = MXC_DMA_MODE_READ;
+ } else {
+ mxc_sdma_channels[channel_num].mode =
+ MXC_DMA_MODE_WRITE;
+ }
+ mxc_sdma_channels[channel_num].channel = channel_id;
+ data_priv = mxc_sdma_channels[channel_num].private;
+ tasklet_init(&data_priv->chnl_tasklet,
+ mxc_sdma_channeltasklet, channel_num);
+ if ((channel_id == MXC_DMA_ATA_RX)
+ || (channel_id == MXC_DMA_ATA_TX)) {
+ data_priv->intr_after_every_bd = 0;
+ } else {
+ data_priv->intr_after_every_bd = 1;
+ }
+ }
+ err_ret:
+ if (ret != 0) {
+ clk_disable(mxc_sdma_ahb_clk);
+ clk_disable(mxc_sdma_ipg_clk);
+ channel_num = -ENODEV;
+ }
+
+ return channel_num;
+}
+
+/*!
+ * This function is generally called by the driver at close time. The DMA
+ * driver would do any cleanup associated with this channel.
+ *
+ * @param channel_num the channel number returned at request time. This
+ * would be used by the DMA driver to identify the calling
+ * driver and do the necessary cleanup on the channel
+ * associated with the particular peripheral
+ * @return returns a negative number on error or 0 on success
+ */
+int mxc_dma_free(int channel_num)
+{
+ mxc_dma_channel_private_t *data_priv;
+
+ if ((channel_num >= MAX_DMA_CHANNELS) || (channel_num < 0)) {
+ return -EINVAL;
+ }
+
+ if (mxc_sdma_channels[channel_num].lock != 1) {
+ return -ENODEV;
+ }
+
+ mxc_free_dma(channel_num);
+
+ /* Disable the SDMA clock */
+ clk_disable(mxc_sdma_ahb_clk);
+ clk_disable(mxc_sdma_ipg_clk);
+
+ mxc_sdma_channels[channel_num].lock = 0;
+ mxc_sdma_channels[channel_num].active = 0;
+ mxc_sdma_channels[channel_num].curr_buf = 0;
+ data_priv = mxc_sdma_channels[channel_num].private;
+ data_priv->buf_tail = 0;
+ tasklet_kill(&data_priv->chnl_tasklet);
+
+ return 0;
+}
+
+/*!
+ * Callback function called from the SDMA Interrupt routine
+ *
+ * @param arg driver specific argument that was registered
+ */
+static void mxc_dma_chnl_callback(void *arg)
+{
+ int priv;
+ mxc_dma_channel_private_t *data_priv;
+
+ priv = (int)arg;
+ data_priv = mxc_sdma_channels[priv].private;
+ /* Process the buffers in a tasklet */
+ tasklet_schedule(&data_priv->chnl_tasklet);
+}
+
+/*!
+ * This function would just configure the buffers specified by the user into
+ * dma channel. The caller must call mxc_dma_enable to start this transfer.
+ *
+ * @param channel_num the channel number returned at request time. This
+ * would be used by the DMA driver to identify the calling
+ * driver and do the necessary cleanup on the channel
+ * associated with the particular peripheral
+ * @param dma_buf an array of physical addresses to the user defined
+ * buffers. The caller must guarantee the dma_buf is
+ * available until the transfer is completed.
+ * @param num_buf number of buffers in the array
+ * @param mode specifies whether this is READ or WRITE operation
+ * @return This function returns a negative number on error if buffer could not be
+ * added with DMA for transfer. On Success, it returns 0
+ */
+int mxc_dma_config(int channel_num, mxc_dma_requestbuf_t * dma_buf,
+ int num_buf, mxc_dma_mode_t mode)
+{
+ int ret = 0, i = 0, prev_buf;
+ mxc_dma_channel_t *chnl_info;
+ mxc_dma_channel_private_t *data_priv;
+ mxc_sdma_channel_params_t *chnl;
+ dma_channel_params chnl_param;
+ dma_request_t request_t;
+
+ if ((channel_num >= MAX_DMA_CHANNELS) || (channel_num < 0)) {
+ return -EINVAL;
+ }
+
+ if (num_buf <= 0) {
+ return -EINVAL;
+ }
+
+ chnl_info = &mxc_sdma_channels[channel_num];
+ data_priv = chnl_info->private;
+ if (chnl_info->lock != 1) {
+ return -ENODEV;
+ }
+
+ /* Check to see if all buffers are taken */
+ if (chnl_info->active == 1) {
+ return -EBUSY;
+ }
+
+ chnl = mxc_sdma_get_channel_params(chnl_info->channel);
+ chnl_param = chnl->chnl_params;
+
+ /* Re-setup the SDMA channel if the transfer direction is changed */
+ if ((chnl_param.peripheral_type != MEMORY) && (mode != chnl_info->mode)) {
+ if (chnl_param.peripheral_type == DSP) {
+ if (mode == MXC_DMA_MODE_READ) {
+ chnl_param.transfer_type = dsp_2_emi;
+ } else {
+ chnl_param.transfer_type = emi_2_dsp;
+ }
+ } else if (chnl_param.peripheral_type == FIFO_MEMORY) {
+ if (mode == MXC_DMA_MODE_READ)
+ chnl_param.per_address = MXC_FIFO_MEM_SRC_FIXED;
+ else
+ chnl_param.per_address =
+ MXC_FIFO_MEM_DEST_FIXED;
+ } else {
+ if (mode == MXC_DMA_MODE_READ) {
+ chnl_param.transfer_type = per_2_emi;
+ } else {
+ chnl_param.transfer_type = emi_2_per;
+ }
+ }
+ chnl_param.callback = mxc_dma_chnl_callback;
+ chnl_param.arg = (void *)channel_num;
+ ret = mxc_dma_setup_channel(channel_num, &chnl_param);
+ if (ret != 0) {
+ return ret;
+ }
+ if (chnl->chnl_priority != MXC_SDMA_DEFAULT_PRIORITY) {
+ ret =
+ mxc_dma_set_channel_priority(channel_num,
+ chnl->chnl_priority);
+ if (ret != 0) {
+ pr_info("Failed to set channel prority,\
+ continue with the existing \
+ priority\n");
+ }
+ }
+ chnl_info->mode = mode;
+ }
+
+ for (i = 0; i < num_buf; i++, dma_buf++) {
+ /* Check to see if all buffers are taken */
+ if (chnl_info->active == 1) {
+ break;
+ }
+ request_t.destAddr = (__u8 *) dma_buf->dst_addr;
+ request_t.sourceAddr = (__u8 *) dma_buf->src_addr;
+ if (chnl_param.peripheral_type == ASRC)
+ request_t.count = dma_buf->num_of_bytes / 4;
+ else
+ request_t.count = dma_buf->num_of_bytes;
+ request_t.bd_cont = 1;
+ ret = mxc_dma_set_config(channel_num, &request_t,
+ chnl_info->curr_buf);
+ if (ret != 0) {
+ break;
+ }
+ if (data_priv->intr_after_every_bd == 0) {
+ if (i == num_buf - 1) {
+ mxc_dma_set_bd_intr(channel_num,
+ chnl_info->curr_buf, 1);
+ } else {
+ mxc_dma_set_bd_intr(channel_num,
+ chnl_info->curr_buf, 0);
+ }
+ }
+
+ prev_buf = chnl_info->curr_buf;
+ if ((chnl_info->curr_buf += 1) >= chnl_param.bd_number) {
+ chnl_info->curr_buf = 0;
+ }
+ if (chnl_info->curr_buf == data_priv->buf_tail) {
+ if ((data_priv->intr_after_every_bd == 0)
+ && (i != num_buf - 1)) {
+ /*
+ * Set the BD_INTR flag on the last BD that
+ * was queued
+ */
+ mxc_dma_set_bd_intr(channel_num, prev_buf, 1);
+ }
+ chnl_info->active = 1;
+ }
+ }
+
+ if (i == 0) {
+ return -EBUSY;
+ }
+ return 0;
+}
+
+/*!
+ * This function would just configure the scatterlist specified by the
+ * user into dma channel. This is a slight variation of mxc_dma_config(),
+ * it is provided for the convenience of drivers that have a scatterlist
+ * passed into them. It is the calling driver's responsibility to have the
+ * correct physical address filled in the "dma_address" field of the
+ * scatterlist.
+ *
+ * @param channel_num the channel number returned at request time. This
+ * would be used by the DMA driver to identify the calling
+ * driver and do the necessary cleanup on the channel
+ * associated with the particular peripheral
+ * @param sg a scatterlist of buffers. The caller must guarantee
+ * the dma_buf is available until the transfer is
+ * completed.
+ * @param num_buf number of buffers in the array
+ * @param num_of_bytes total number of bytes to transfer. If set to 0, this
+ * would imply to use the length field of the scatterlist
+ * for each DMA transfer. Else it would calculate the size
+ * for each DMA transfer.
+ * @param mode specifies whether this is READ or WRITE operation
+ * @return This function returns a negative number on error if buffer could not
+ * be added with DMA for transfer. On Success, it returns 0
+ */
+int mxc_dma_sg_config(int channel_num, struct scatterlist *sg,
+ int num_buf, int num_of_bytes, mxc_dma_mode_t mode)
+{
+ int ret = 0, i = 0;
+ mxc_dma_requestbuf_t *dma_buf;
+
+ if ((channel_num >= MAX_DMA_CHANNELS) || (channel_num < 0)) {
+ return -EINVAL;
+ }
+
+ if (mxc_sdma_channels[channel_num].lock != 1) {
+ return -ENODEV;
+ }
+
+ dma_buf =
+ (mxc_dma_requestbuf_t *) kmalloc(num_buf *
+ sizeof(mxc_dma_requestbuf_t),
+ GFP_KERNEL);
+
+ if (dma_buf == NULL) {
+ return -EFAULT;
+ }
+
+ for (i = 0; i < num_buf; i++) {
+ if (mode == MXC_DMA_MODE_READ) {
+ (dma_buf + i)->dst_addr = sg->dma_address;
+ } else {
+ (dma_buf + i)->src_addr = sg->dma_address;
+ }
+
+ if ((num_of_bytes > sg->length) || (num_of_bytes == 0)) {
+ (dma_buf + i)->num_of_bytes = sg->length;
+ } else {
+ (dma_buf + i)->num_of_bytes = num_of_bytes;
+ }
+ sg++;
+ num_of_bytes -= (dma_buf + i)->num_of_bytes;
+ }
+
+ ret = mxc_dma_config(channel_num, dma_buf, num_buf, mode);
+ kfree(dma_buf);
+ return ret;
+}
+
+/*!
+ * This function is provided if the driver would like to set/change its
+ * callback function.
+ *
+ * @param channel_num the channel number returned at request time. This
+ * would be used by the DMA driver to identify the calling
+ * driver and do the necessary cleanup on the channel
+ * associated with the particular peripheral
+ * @param callback a callback function to provide notification on transfer
+ * completion, user could specify NULL if he does not wish
+ * to be notified
+ * @param arg an argument that gets passed in to the callback
+ * function, used by the user to do any driver specific
+ * operations.
+ * @return this function returns a negative number on error if the callback
+ * could not be set for the channel or 0 on success
+ */
+int mxc_dma_callback_set(int channel_num,
+ mxc_dma_callback_t callback, void *arg)
+{
+ if ((channel_num >= MAX_DMA_CHANNELS) || (channel_num < 0)) {
+ return -EINVAL;
+ }
+
+ if (mxc_sdma_channels[channel_num].lock != 1) {
+ return -ENODEV;
+ }
+
+ mxc_sdma_channels[channel_num].cb_fn = callback;
+ mxc_sdma_channels[channel_num].cb_args = arg;
+
+ mxc_dma_set_callback(channel_num, mxc_dma_chnl_callback,
+ (void *)channel_num);
+
+ return 0;
+}
+
+/*!
+ * This stops the DMA channel and any ongoing transfers. Subsequent use of
+ * mxc_dma_enable() will restart the channel and restart the transfer.
+ *
+ * @param channel_num the channel number returned at request time. This
+ * would be used by the DMA driver to identify the calling
+ * driver and do the necessary cleanup on the channel
+ * associated with the particular peripheral
+ * @return returns a negative number on error or 0 on success
+ */
+int mxc_dma_disable(int channel_num)
+{
+ if ((channel_num >= MAX_DMA_CHANNELS) || (channel_num < 0)) {
+ return -EINVAL;
+ }
+
+ if (mxc_sdma_channels[channel_num].lock != 1) {
+ return -ENODEV;
+ }
+
+ mxc_dma_stop(channel_num);
+ return 0;
+}
+
+/*!
+ * This starts DMA transfer. Or it restarts DMA on a stopped channel
+ * previously stopped with mxc_dma_disable().
+ *
+ * @param channel_num the channel number returned at request time. This
+ * would be used by the DMA driver to identify the calling
+ * driver and do the necessary cleanup on the channel
+ * associated with the particular peripheral
+ * @return returns a negative number on error or 0 on success
+ */
+int mxc_dma_enable(int channel_num)
+{
+ if ((channel_num >= MAX_DMA_CHANNELS) || (channel_num < 0)) {
+ return -EINVAL;
+ }
+
+ if (mxc_sdma_channels[channel_num].lock != 1) {
+ return -ENODEV;
+ }
+
+ mxc_dma_start(channel_num);
+ return 0;
+}
+
+/*!
+ * Initializes dma structure with dma_operations
+ *
+ * @param dma dma structure
+ * @return returns 0 on success
+ */
+static int __init mxc_dma_init(void)
+{
+ int i;
+ for (i = 0; i < MAX_DMA_CHANNELS; i++) {
+ mxc_sdma_channels[i].active = 0;
+ mxc_sdma_channels[i].lock = 0;
+ mxc_sdma_channels[i].curr_buf = 0;
+ mxc_sdma_channels[i].dynamic = 1;
+ mxc_sdma_private[i].buf_tail = 0;
+ mxc_sdma_channels[i].private = &mxc_sdma_private[i];
+ }
+ /*
+ * Make statically allocated channels unavailable for dynamic channel
+ * requests
+ */
+ mxc_get_static_channels(mxc_sdma_channels);
+
+ return 0;
+}
+
+arch_initcall(mxc_dma_init);
+
+#else
+int mxc_request_dma(int *channel, const char *devicename)
+{
+ return -ENODEV;
+}
+
+int mxc_dma_setup_channel(int channel, dma_channel_params * p)
+{
+ return -ENODEV;
+}
+
+int mxc_dma_set_channel_priority(unsigned int channel, unsigned int priority)
+{
+ return -ENODEV;
+}
+
+int mxc_dma_set_config(int channel, dma_request_t * p, int bd_index)
+{
+ return -ENODEV;
+}
+
+int mxc_dma_get_config(int channel, dma_request_t * p, int bd_index)
+{
+ return -ENODEV;
+}
+
+int mxc_dma_start(int channel)
+{
+ return -ENODEV;
+}
+
+int mxc_dma_stop(int channel)
+{
+ return -ENODEV;
+}
+
+void mxc_free_dma(int channel)
+{
+}
+
+void mxc_dma_set_callback(int channel, dma_callback_t callback, void *arg)
+{
+}
+
+void *sdma_malloc(size_t size)
+{
+ return 0;
+}
+
+void sdma_free(void *buf)
+{
+}
+
+void *sdma_phys_to_virt(unsigned long buf)
+{
+ return 0;
+}
+
+unsigned long sdma_virt_to_phys(void *buf)
+{
+ return 0;
+}
+
+int mxc_dma_request(mxc_dma_device_t channel_id, char *dev_name)
+{
+ return -ENODEV;
+}
+
+int mxc_dma_free(int channel_num)
+{
+ return -ENODEV;
+}
+
+int mxc_dma_config(int channel_num, mxc_dma_requestbuf_t * dma_buf,
+ int num_buf, mxc_dma_mode_t mode)
+{
+ return -ENODEV;
+}
+
+int mxc_dma_sg_config(int channel_num, struct scatterlist *sg,
+ int num_buf, int num_of_bytes, mxc_dma_mode_t mode)
+{
+ return -ENODEV;
+}
+
+int mxc_dma_callback_set(int channel_num, mxc_dma_callback_t callback,
+ void *arg)
+{
+ return -ENODEV;
+}
+
+int mxc_dma_disable(int channel_num)
+{
+ return -ENODEV;
+}
+
+int mxc_dma_enable(int channel_num)
+{
+ return -ENODEV;
+}
+
+EXPORT_SYMBOL(mxc_request_dma);
+EXPORT_SYMBOL(mxc_dma_setup_channel);
+EXPORT_SYMBOL(mxc_dma_set_channel_priority);
+EXPORT_SYMBOL(mxc_dma_set_config);
+EXPORT_SYMBOL(mxc_dma_get_config);
+EXPORT_SYMBOL(mxc_dma_start);
+EXPORT_SYMBOL(mxc_dma_stop);
+EXPORT_SYMBOL(mxc_free_dma);
+EXPORT_SYMBOL(mxc_dma_set_callback);
+EXPORT_SYMBOL(sdma_malloc);
+EXPORT_SYMBOL(sdma_free);
+EXPORT_SYMBOL(sdma_phys_to_virt);
+EXPORT_SYMBOL(sdma_virt_to_phys);
+
+#endif
+
+EXPORT_SYMBOL(mxc_dma_request_ext);
+EXPORT_SYMBOL(mxc_dma_free);
+EXPORT_SYMBOL(mxc_dma_config);
+EXPORT_SYMBOL(mxc_dma_sg_config);
+EXPORT_SYMBOL(mxc_dma_callback_set);
+EXPORT_SYMBOL(mxc_dma_disable);
+EXPORT_SYMBOL(mxc_dma_enable);
+
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_DESCRIPTION("MXC Linux SDMA API");
+MODULE_LICENSE("GPL");
diff --git a/arch/arm/plat-mxc/sdma/iapi/Makefile b/arch/arm/plat-mxc/sdma/iapi/Makefile
new file mode 100644
index 000000000000..b6a5d6aebda0
--- /dev/null
+++ b/arch/arm/plat-mxc/sdma/iapi/Makefile
@@ -0,0 +1,5 @@
+#
+# Makefile for I.API sources.
+#
+
+obj-y := src/ \ No newline at end of file
diff --git a/arch/arm/plat-mxc/sdma/iapi/include/epm.h b/arch/arm/plat-mxc/sdma/iapi/include/epm.h
new file mode 100644
index 000000000000..a12fff923a15
--- /dev/null
+++ b/arch/arm/plat-mxc/sdma/iapi/include/epm.h
@@ -0,0 +1,187 @@
+/*
+ * Copyright 2007-2009 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 __ASM_ARCH_MXC_SDMA_REGS_H__
+#define __ASM_ARCH_MXC_SDMA_REGS_H__
+
+#include <mach/hardware.h>
+
+/* SDMA Reg definition */
+#define SDMA_BASE_IO_ADDR IO_ADDRESS(SDMA_BASE_ADDR)
+
+#define SDMA_H_C0PTR *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x000))
+#define SDMA_H_INTR *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x004))
+#define SDMA_H_STATSTOP *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x008))
+#define SDMA_H_START *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x00C))
+#define SDMA_H_EVTOVR *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x010))
+#define SDMA_H_DSPOVR *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x014))
+#define SDMA_H_HOSTOVR *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x018))
+#define SDMA_H_EVTPEND *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x01C))
+#define SDMA_H_DSPENBL *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x020))
+#define SDMA_H_RESET *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x024))
+#define SDMA_H_EVTERR *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x028))
+#define SDMA_H_INTRMSK *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x02C))
+#define SDMA_H_PSW *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x030))
+#define SDMA_H_EVTERRDBG *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x034))
+#define SDMA_H_CONFIG *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x038))
+#define SDMA_ONCE_ENB *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x040))
+#define SDMA_ONCE_DATA *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x044))
+#define SDMA_ONCE_INSTR *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x048))
+#define SDMA_ONCE_STAT *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x04C))
+#define SDMA_ONCE_CMD *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x050))
+#define SDMA_EVT_MIRROR *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x054))
+#define SDMA_ILLINSTADDR *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x058))
+#define SDMA_CHN0ADDR *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x05C))
+#define SDMA_ONCE_RTB *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x060))
+#define SDMA_XTRIG_CONF1 *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x070))
+#define SDMA_XTRIG_CONF2 *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x074))
+
+#ifdef MXC_SDMA_V2
+#define SDMA_CHNENBL_0 *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x200))
+#define SDMA_CHNENBL_1 *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x204))
+#define SDMA_CHNENBL_2 *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x208))
+#define SDMA_CHNENBL_3 *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x20C))
+#define SDMA_CHNENBL_4 *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x210))
+#define SDMA_CHNENBL_5 *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x214))
+#define SDMA_CHNENBL_6 *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x218))
+#define SDMA_CHNENBL_7 *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x21C))
+#define SDMA_CHNENBL_8 *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x220))
+#define SDMA_CHNENBL_9 *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x224))
+#define SDMA_CHNENBL_10 *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x228))
+#define SDMA_CHNENBL_11 *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x22C))
+#define SDMA_CHNENBL_12 *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x230))
+#define SDMA_CHNENBL_13 *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x234))
+#define SDMA_CHNENBL_14 *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x238))
+#define SDMA_CHNENBL_15 *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x23C))
+#define SDMA_CHNENBL_16 *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x240))
+#define SDMA_CHNENBL_17 *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x244))
+#define SDMA_CHNENBL_18 *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x248))
+#define SDMA_CHNENBL_19 *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x24C))
+#define SDMA_CHNENBL_20 *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x250))
+#define SDMA_CHNENBL_21 *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x254))
+#define SDMA_CHNENBL_22 *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x258))
+#define SDMA_CHNENBL_23 *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x25C))
+#define SDMA_CHNENBL_24 *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x260))
+#define SDMA_CHNENBL_25 *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x264))
+#define SDMA_CHNENBL_26 *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x268))
+#define SDMA_CHNENBL_27 *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x26C))
+#define SDMA_CHNENBL_28 *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x270))
+#define SDMA_CHNENBL_29 *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x274))
+#define SDMA_CHNENBL_30 *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x278))
+#define SDMA_CHNENBL_31 *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x27C))
+#define SDMA_CHNENBL_32 *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x280))
+#define SDMA_CHNENBL_33 *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x284))
+#define SDMA_CHNENBL_34 *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x288))
+#define SDMA_CHNENBL_35 *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x28C))
+#define SDMA_CHNENBL_36 *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x290))
+#define SDMA_CHNENBL_37 *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x294))
+#define SDMA_CHNENBL_38 *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x298))
+#define SDMA_CHNENBL_39 *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x29C))
+#define SDMA_CHNENBL_40 *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x2A0))
+#define SDMA_CHNENBL_41 *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x2A4))
+#define SDMA_CHNENBL_42 *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x2A8))
+#define SDMA_CHNENBL_43 *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x2AC))
+#define SDMA_CHNENBL_44 *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x2B0))
+#define SDMA_CHNENBL_45 *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x2B4))
+#define SDMA_CHNENBL_46 *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x2B8))
+#define SDMA_CHNENBL_47 *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x2BC))
+
+#define SDMA_ONCE_COUNT *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x300))
+#define SDMA_ONCE_ECTL *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x304))
+#define SDMA_ONCE_EAA *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x308))
+#define SDMA_ONCE_EAB *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x30C))
+#define SDMA_ONCE_EAM *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x310))
+#define SDMA_ONCE_ED *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x314))
+#define SDMA_ONCE_EDM *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x318))
+#define SDMA_ONCE_PCMATCH *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x31C))
+
+#else
+
+#define SDMA_CHNENBL_0 *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x080))
+#define SDMA_CHNENBL_1 *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x084))
+#define SDMA_CHNENBL_2 *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x088))
+#define SDMA_CHNENBL_3 *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x08C))
+#define SDMA_CHNENBL_4 *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x090))
+#define SDMA_CHNENBL_5 *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x094))
+#define SDMA_CHNENBL_6 *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x098))
+#define SDMA_CHNENBL_7 *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x09C))
+#define SDMA_CHNENBL_8 *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x0A0))
+#define SDMA_CHNENBL_9 *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x0A4))
+#define SDMA_CHNENBL_10 *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x0A8))
+#define SDMA_CHNENBL_11 *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x0AC))
+#define SDMA_CHNENBL_12 *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x0B0))
+#define SDMA_CHNENBL_13 *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x0B4))
+#define SDMA_CHNENBL_14 *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x0B8))
+#define SDMA_CHNENBL_15 *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x0BC))
+#define SDMA_CHNENBL_16 *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x0C0))
+#define SDMA_CHNENBL_17 *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x0C4))
+#define SDMA_CHNENBL_18 *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x0C8))
+#define SDMA_CHNENBL_19 *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x0CC))
+#define SDMA_CHNENBL_20 *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x0D0))
+#define SDMA_CHNENBL_21 *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x0D4))
+#define SDMA_CHNENBL_22 *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x0D8))
+#define SDMA_CHNENBL_23 *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x0DC))
+#define SDMA_CHNENBL_24 *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x0E0))
+#define SDMA_CHNENBL_25 *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x0E4))
+#define SDMA_CHNENBL_26 *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x0E8))
+#define SDMA_CHNENBL_27 *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x0EC))
+#define SDMA_CHNENBL_28 *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x0F0))
+#define SDMA_CHNENBL_29 *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x0F4))
+#define SDMA_CHNENBL_30 *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x0F8))
+#define SDMA_CHNENBL_31 *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x0FC))
+
+#define SDMA_ONCE_COUNT *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x200))
+#define SDMA_ONCE_ECTL *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x204))
+#define SDMA_ONCE_EAA *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x208))
+#define SDMA_ONCE_EAB *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x20C))
+#define SDMA_ONCE_EAM *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x210))
+#define SDMA_ONCE_ED *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x214))
+#define SDMA_ONCE_EDM *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x218))
+#define SDMA_ONCE_PCMATCH *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x21C))
+
+#endif /* MXC_SDMA_V2 */
+
+#define SDMA_CHNPRI_0 *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x100))
+#define SDMA_CHNPRI_1 *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x104))
+#define SDMA_CHNPRI_2 *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x108))
+#define SDMA_CHNPRI_3 *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x10C))
+#define SDMA_CHNPRI_4 *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x110))
+#define SDMA_CHNPRI_5 *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x114))
+#define SDMA_CHNPRI_6 *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x118))
+#define SDMA_CHNPRI_7 *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x11C))
+#define SDMA_CHNPRI_8 *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x120))
+#define SDMA_CHNPRI_9 *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x124))
+#define SDMA_CHNPRI_10 *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x128))
+#define SDMA_CHNPRI_11 *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x12C))
+#define SDMA_CHNPRI_12 *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x130))
+#define SDMA_CHNPRI_13 *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x134))
+#define SDMA_CHNPRI_14 *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x138))
+#define SDMA_CHNPRI_15 *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x13C))
+#define SDMA_CHNPRI_16 *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x140))
+#define SDMA_CHNPRI_17 *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x144))
+#define SDMA_CHNPRI_18 *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x148))
+#define SDMA_CHNPRI_19 *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x14C))
+#define SDMA_CHNPRI_20 *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x150))
+#define SDMA_CHNPRI_21 *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x154))
+#define SDMA_CHNPRI_22 *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x158))
+#define SDMA_CHNPRI_23 *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x15C))
+#define SDMA_CHNPRI_24 *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x160))
+#define SDMA_CHNPRI_25 *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x164))
+#define SDMA_CHNPRI_26 *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x168))
+#define SDMA_CHNPRI_27 *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x16C))
+#define SDMA_CHNPRI_28 *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x170))
+#define SDMA_CHNPRI_29 *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x174))
+#define SDMA_CHNPRI_30 *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x178))
+#define SDMA_CHNPRI_31 *((volatile unsigned long *)(SDMA_BASE_IO_ADDR + 0x17C))
+
+#endif /* _mcuEpm_h */
diff --git a/arch/arm/plat-mxc/sdma/iapi/include/iapi.h b/arch/arm/plat-mxc/sdma/iapi/include/iapi.h
new file mode 100644
index 000000000000..d7300218057b
--- /dev/null
+++ b/arch/arm/plat-mxc/sdma/iapi/include/iapi.h
@@ -0,0 +1,49 @@
+/******************************************************************************
+ *
+ * Copyright 2007 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
+ *
+ ******************************************************************************
+ *
+ * File: iapi.h
+ *
+ * $Id iapi.h $
+ *
+ * Description:
+ * Unique include for the whole IAPI library.
+ *
+ *
+ * http//compass.mot.com/go/115342679
+ *
+ * $Log iapi.h $
+ *
+ * ***************************************************************************/
+
+#ifndef _iapi_h
+#define _iapi_h
+
+/* ****************************************************************************
+ * Include File Section
+ * ***************************************************************************/
+
+#include "sdmaStruct.h"
+#include "iapiDefaults.h"
+#include "iapiLow.h"
+#include "iapiMiddle.h"
+#include "iapiHigh.h"
+
+#ifdef MCU
+#include "iapiLowMcu.h"
+#include "iapiMiddleMcu.h"
+#endif /* MCU */
+
+
+
+#endif /* _iapi_h */
diff --git a/arch/arm/plat-mxc/sdma/iapi/include/iapiDefaults.h b/arch/arm/plat-mxc/sdma/iapi/include/iapiDefaults.h
new file mode 100644
index 000000000000..b03a53ae1893
--- /dev/null
+++ b/arch/arm/plat-mxc/sdma/iapi/include/iapiDefaults.h
@@ -0,0 +1,128 @@
+/******************************************************************************
+ *
+ * Copyright 2007 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
+ *
+ ******************************************************************************
+ *
+ * File: iapiDefaults.h
+ *
+ * $Id iapiDefaults.h $
+ *
+ * Description:
+ * This library is written in C to guarantee functionality and integrity in
+ * the usage of SDMA virtual DMA channels. This API (Application Programming
+ * Interface) allow SDMA channels' access in an OPEN, READ, WRITE, CLOSE
+ * fashion.
+ *
+ *
+ *
+ *
+ * $Log iapiDefaults.h $
+ *
+ *****************************************************************************/
+
+
+#ifndef _iapi_defaults_h
+#define _iapi_defaults_h
+
+/******************************************************************************
+ * Include File Section
+ *****************************************************************************/
+#include "epm.h"
+#include "sdmaStruct.h"
+
+/* ****************************************************************************
+ * Macro-command Section
+ * ***************************************************************************/
+
+/**
+ * Error codes
+ * lower 5 bits free to include channel number when available
+ * and bit number 6 must be set when channel number is available
+ *
+ * Note :
+ * 1) Abbreviations / naming convention :
+ * - BD : Buffer Descriptor
+ * - CC : Channel Context
+ * - CCB : Channel Control Block
+ * - CD : Channel Descriptor
+ * - B : Buffer
+ * - CH : Channel
+ *
+ */
+#define IAPI_SUCCESS 0
+#define IAPI_FAILURE -1
+#define IAPI_ERR_CH_AVAILABLE 0x00020
+#define IAPI_ERR_NO_ERROR 0x00000
+#define IAPI_ERR_NO_CCB_DEFINED 0x01000
+#define IAPI_ERR_BD_UNINITIALIZED 0x02000
+#define IAPI_ERR_BD_ALLOCATED 0x03000
+#define IAPI_ERR_BD_ALLOCATION 0x04000
+#define IAPI_ERR_CCB_ALLOC_FAILED 0x05000
+#define IAPI_ERR_CCB_UNINITIALIZED 0x06000
+#define IAPI_ERR_CC_ALREADY_DEFINED 0x07000
+#define IAPI_ERR_CC_ALLOC_FAILED 0x08000
+#define IAPI_ERR_CD_ALREADY_DEFINED 0x09000
+#define IAPI_ERR_CD_ALLOC_FAILED 0x0A000
+#define IAPI_ERR_CD_CHANGE_CH_NUMBER 0x0B000
+#define IAPI_ERR_CD_CHANGE_CCB_PTR 0x0C000
+#define IAPI_ERR_CD_CHANGE_UNKNOWN 0x0D000
+#define IAPI_ERR_CD_CHANGE 0x0E000
+#define IAPI_ERR_CD_UNINITIALIZED 0x0F000
+#define IAPI_ERR_CLOSE 0x10000
+#define IAPI_ERR_B_ALLOC_FAILED 0x11000
+#define IAPI_ERR_CONFIG_OVERRIDE 0x12000
+#define IAPI_ERR_CH_IN_USE 0x13000
+#define IAPI_ERR_CALLBACKSYNCH_UNKNOWN 0x14000
+#define IAPI_ERR_INVALID_PARAMETER 0x15000
+#define IAPI_ERR_TRUST 0x16000
+#define IAPI_ERR_CHANNEL_UNINITIALIZED 0x17000
+#define IAPI_ERR_RROR_BIT_READ 0x18000
+#define IAPI_ERR_RROR_BIT_WRITE 0x19000
+#define IAPI_ERR_NOT_ALLOWED 0x1A000
+#define IAPI_ERR_NO_OS_FN 0x1B000
+
+
+/*
+ * Global Variable Section
+ */
+
+/*
+ * Table to hold pointers to the callback functions registered by the users of
+ *I.API
+ */
+extern void (* callbackIsrTable[CH_NUM])(channelDescriptor * cd_p, void * arg);
+
+/*
+ * Table to hold user registered data pointers, to be privided in the callback
+ *function
+ */
+extern void * userArgTable[CH_NUM];
+
+/* channelDescriptor data structure filled with default data*/
+extern channelDescriptor iapi_ChannelDefaults;
+
+/* Global variable to hold the last error encountered in I.API operations*/
+extern unsigned int iapi_errno;
+
+/* Used in synchronization, to mark started channels*/
+extern volatile unsigned long iapi_SDMAIntr;
+
+/* Hold a pointer to the start of the CCB array, to be used in the IRQ routine
+ *to find the channel descriptor for the channed sending the interrupt to the
+ *core.
+ */
+extern channelControlBlock * iapi_CCBHead;
+
+/* configs_data structure filled with default data*/
+extern configs_data iapi_ConfigDefaults;
+
+#endif /* iapiDefaults_h */
diff --git a/arch/arm/plat-mxc/sdma/iapi/include/iapiHigh.h b/arch/arm/plat-mxc/sdma/iapi/include/iapiHigh.h
new file mode 100644
index 000000000000..14cfae539eb8
--- /dev/null
+++ b/arch/arm/plat-mxc/sdma/iapi/include/iapiHigh.h
@@ -0,0 +1,136 @@
+/******************************************************************************
+ *
+ * Copyright 2007 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
+ *
+ ******************************************************************************
+ *
+ * File: iapiHigh.h
+ *
+ * $Id iapiHigh.h $
+ *
+ * Description:
+ * prototypes for high level function of I.API
+ *
+ *
+ * http://venerque.sps.mot.com/pjt/sfs/www/iapi/softsim_api.pdf
+ *
+ * $Log iapiHigh.h
+ *
+ * ***************************************************************************/
+
+#ifndef _iapiHigh_h
+#define _iapiHigh_h
+
+/* ****************************************************************************
+ * Include File Section
+ *****************************************************************************/
+#include "sdmaStruct.h"
+
+/* ****************************************************************************
+ * Macro-command Section
+ *****************************************************************************/
+enum {
+ IAPI_CHANGE_CHANDESC,
+ IAPI_CHANGE_BDNUM,
+ IAPI_CHANGE_BUFFSIZE,
+ IAPI_CHANGE_CHANBLOCK,
+ IAPI_CHANGE_INSTANCE,
+ IAPI_CHANGE_OWNERSHIP,
+ IAPI_CHANGE_SYNCH,
+ IAPI_CHANGE_TRUST,
+ IAPI_CHANGE_CALLBACKFUNC,
+ IAPI_CHANGE_CHANCCB,
+ IAPI_CHANGE_PRIORITY,
+ IAPI_CHANGE_BDWRAP,
+ IAPI_CHANGE_WATERMARK,
+ IAPI_CHANGE_SET_BDCONT,
+ IAPI_CHANGE_UNSET_BDCONT,
+ IAPI_CHANGE_SET_BDEXTD,
+ IAPI_CHANGE_UNSET_BDEXTD,
+ IAPI_CHANGE_EVTMASK1,
+ IAPI_CHANGE_EVTMASK2,
+ IAPI_CHANGE_PERIPHADDR,
+ IAPI_CHANGE_SET_BDINTR,
+ IAPI_CHANGE_UNSET_BDINTR,
+ IAPI_CHANGE_SET_TRANSFER_CD,
+ IAPI_CHANGE_FORCE_CLOSE,
+ IAPI_CHANGE_SET_TRANSFER,
+ IAPI_CHANGE_USER_ARG,
+ IAPI_CHANGE_SET_BUFFERADDR,
+ IAPI_CHANGE_SET_EXTDBUFFERADDR,
+ IAPI_CHANGE_SET_COMMAND,
+ IAPI_CHANGE_SET_COUNT,
+ IAPI_CHANGE_SET_STATUS,
+ IAPI_CHANGE_GET_BUFFERADDR,
+ IAPI_CHANGE_GET_EXTDBUFFERADDR,
+ IAPI_CHANGE_GET_COMMAND,
+ IAPI_CHANGE_GET_COUNT,
+ IAPI_CHANGE_GET_STATUS,
+ IAPI_CHANGE_SET_ENDIANNESS
+};
+
+
+/*
+ * Public Function Prototype Section
+ */
+int iapi_Open ( channelDescriptor * cd_p, unsigned char channelNumber );
+int iapi_Close( channelDescriptor * cd_p );
+int iapi_Read ( channelDescriptor * cd_p, void * buf, unsigned short nbyte );
+int iapi_Write( channelDescriptor * cd_p, void * buf, unsigned short nbyte );
+int iapi_MemCopy(channelDescriptor * cd_p, void* dest, void* src,
+ unsigned long size);
+int iapi_IoCtl( channelDescriptor * cd_p, unsigned long ctlRequest,
+ unsigned long param);
+
+
+int iapi_Read_ipcv2( channelDescriptor * cd_p, void * data_control_struct_ipcv2);
+
+int iapi_Write_ipcv2( channelDescriptor * cd_p, void * data_control_struct_ipcv2);
+
+#ifdef MCU
+int iapi_Init(channelDescriptor * cd_p, configs_data * config_p,
+ unsigned short* ram_image, unsigned short code_size,
+ unsigned long start_addr);
+#endif /* MCU */
+#ifdef DSP
+int iapi_Init(channelDescriptor * cd_p);
+#endif /* DSP */
+
+int iapi_StartChannel(unsigned char channel);
+int iapi_StopChannel(unsigned char channel);
+int iapi_SynchChannel(unsigned char channel);
+
+int iapi_GetChannelNumber(channelDescriptor * cd_p);
+unsigned long iapi_GetError(channelDescriptor * cd_p);
+int iapi_GetCount(channelDescriptor * cd_p);
+int iapi_GetCountAll(channelDescriptor * cd_p);
+
+#ifndef IRQ_KEYWORD
+#define IRQ_KEYWORD
+#endif /* IRQ_KEYWORD */
+
+IRQ_KEYWORD void IRQ_Handler(void);
+
+#ifdef MCU
+int iapi_GetScript(channelDescriptor * cd_p, void * buf, unsigned short size,
+ unsigned long address);
+int iapi_GetContext(channelDescriptor * cd_p, void * buf,
+ unsigned char channel);
+int iapi_SetScript(channelDescriptor * cd_p, void * buf, unsigned short nbyte,
+ unsigned long destAddr);
+int iapi_SetContext(channelDescriptor * cd_p, void * buf,
+ unsigned char channel);
+int iapi_AssignScript(channelDescriptor * cd_p, script_data * data_p);
+
+int iapi_SetChannelEventMapping(unsigned char event, unsigned long channel_map);
+#endif /* MCU */
+
+#endif /* _iapiHigh_h */
diff --git a/arch/arm/plat-mxc/sdma/iapi/include/iapiLow.h b/arch/arm/plat-mxc/sdma/iapi/include/iapiLow.h
new file mode 100644
index 000000000000..43aff7a4e903
--- /dev/null
+++ b/arch/arm/plat-mxc/sdma/iapi/include/iapiLow.h
@@ -0,0 +1,78 @@
+/******************************************************************************
+ *
+ * Copyright 2007 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
+ *
+ ******************************************************************************
+ *
+ * File: iapiLow.h
+ *
+ * $Id iapiLow.h $
+ *
+ * Description:
+ * prototypes for low level function of I.API
+ *
+ *
+ *
+ *
+ * $Log iapiLow.h
+ *
+ * ***************************************************************************/
+
+#ifndef _iapiLow_h
+#define _iapiLow_h
+
+/* ****************************************************************************
+ * Boolean identifiers
+ *****************************************************************************/
+#define NO_OS 0
+#define LINUX 1
+#define SYMBIAN 2
+#define WINCE 3
+
+/* ****************************************************************************
+ * Include File Section
+ *****************************************************************************/
+#include "sdmaStruct.h"
+#include "iapiDefaults.h"
+#include "iapiOS.h"
+#ifdef MCU
+#include "iapiLowMcu.h"
+#endif /*MCU*/
+#if OS == NO_OS
+#include <stdlib.h>
+#elif OS == LINUX
+#include <linux/types.h>
+#endif
+
+
+/* ****************************************************************************
+ * Macro-command Section
+ *****************************************************************************/
+
+#define GOTO_SLEEP(x) (iapi_GotoSleep)(x)
+#define INIT_SLEEP(x) (iapi_InitSleep)(x)
+
+/* ****************************************************************************
+ * Public Function Prototype Section
+ *****************************************************************************/
+void iapi_lowStartChannel ( unsigned char channel );
+void iapi_lowStopChannel ( unsigned char channel );
+void iapi_AttachCallbackISR (channelDescriptor * cd_p,
+ void (* func_p)(channelDescriptor * cd_p, void * arg));
+void iapi_DetachCallbackISR (channelDescriptor * cd_p);
+void iapi_ChangeCallbackISR (channelDescriptor * cd_p,
+ void (* func_p)(channelDescriptor * cd_p, void * arg));
+void iapi_lowSynchChannel ( unsigned char channel );
+void iapi_SetBufferDescriptor(bufferDescriptor *bd_p, unsigned char command,
+ unsigned char status, unsigned short count,
+ void * buffAddr, void * extBufferAddr);
+
+#endif /* _iapiLow_h */
diff --git a/arch/arm/plat-mxc/sdma/iapi/include/iapiLowDsp.h b/arch/arm/plat-mxc/sdma/iapi/include/iapiLowDsp.h
new file mode 100644
index 000000000000..0adaa2548b9e
--- /dev/null
+++ b/arch/arm/plat-mxc/sdma/iapi/include/iapiLowDsp.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2007 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
+ */
+
+/* ****************************************************************************
+ *
+ * File: iapiLowDsp.h
+ *
+ * $Id iapiLowDsp.h $
+ *
+ * Description:
+ * prototypes for low level function of I.API for DSP side only
+ *
+ *
+ *
+ *
+ * $Log iapiLowDsp.h
+ *
+ * ***************************************************************************/
+
+#ifndef _iapiLowDsp_h
+#define _iapiLowDsp_h
+
+/* ****************************************************************************
+ * Include File Section
+ *****************************************************************************/
+
+
+/* ****************************************************************************
+ * Public Function Prototype Section
+ *****************************************************************************/
+/* WARNING !!!!!
+ * This file is empty and it is normal, because there is no low level functions
+ * dedicated to the DSP but the file (iapi_LowDsp.h) must still exist because
+ * some project directly links the file. Previously, there were function
+ * iapi_EnableInterrupts,iapi_DisableInterrupts,iapi_WaitCore,iapi_StartChannel
+ * iapi_StopChannel but they are common to both MCU and DSP, so they have been
+ * moved to iapi_Low.h file.
+ */
+
+#endif /* _iapiLowDsp_h */
diff --git a/arch/arm/plat-mxc/sdma/iapi/include/iapiLowMcu.h b/arch/arm/plat-mxc/sdma/iapi/include/iapiLowMcu.h
new file mode 100644
index 000000000000..12bea564c116
--- /dev/null
+++ b/arch/arm/plat-mxc/sdma/iapi/include/iapiLowMcu.h
@@ -0,0 +1,60 @@
+/******************************************************************************
+ *
+ * Copyright 2007 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
+ *
+ ******************************************************************************
+ *
+ * File: iapiLowMcu.h
+ *
+ * $Id iapiLowMcu.h $
+ *
+ * Description:
+ * prototypes for low level function of I.API of MCU side only
+ *
+ *
+ *
+ *
+ * $Log iapiLowMcu.h $
+ *
+ * ***************************************************************************/
+
+#ifndef _iapiLowMcu_h
+#define _iapiLowMcu_h
+
+/******************************************************************************
+ * Include File Section
+ *****************************************************************************/
+#include "sdmaStruct.h"
+#include "iapiDefaults.h"
+
+/* ****************************************************************************
+ * Public Function Prototype Section
+ * ***************************************************************************/
+
+
+void iapi_InitChannelTables ( void );
+int iapi_ChannelConfig(unsigned char channel, unsigned eventOverride,
+ unsigned mcuOverride, unsigned dspOverride);
+int iapi_Channel0Command(channelDescriptor * cd_p, void * buf,
+ unsigned short nbyte, unsigned char command);
+void iapi_lowGetScript(channelDescriptor * cd_p, void * buf, unsigned short size,
+ unsigned long address);
+void iapi_lowGetContext(channelDescriptor * cd_p, void * buf,
+ unsigned char channel);
+void iapi_lowSetScript(channelDescriptor * cd_p, void * buf, unsigned short nbyte,
+ unsigned long destAddr);
+void iapi_lowSetContext(channelDescriptor * cd_p, void * buf,
+ unsigned char channel);
+int iapi_lowAssignScript(channelDescriptor * cd_p, script_data * data_p);
+
+int iapi_lowSetChannelEventMapping(unsigned char event, unsigned long channel_map);
+
+#endif /* _iapiLowMcu_h */
diff --git a/arch/arm/plat-mxc/sdma/iapi/include/iapiMiddle.h b/arch/arm/plat-mxc/sdma/iapi/include/iapiMiddle.h
new file mode 100644
index 000000000000..2470ffcaabf1
--- /dev/null
+++ b/arch/arm/plat-mxc/sdma/iapi/include/iapiMiddle.h
@@ -0,0 +1,52 @@
+/******************************************************************************
+ *
+ * Copyright 2007 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
+ *
+ ******************************************************************************
+ *
+ * File: iapiMiddle.h
+ *
+ * $Id iapiMiddle.h $
+ *
+ * Description:
+ * prototypes for middle level function of I.API
+ *
+ *
+ *
+ *
+ * $Log iapiMiddle.h
+ *
+ * ***************************************************************************/
+
+#ifndef _iapiMiddle_h
+#define _iapiMiddle_h
+
+/* ****************************************************************************
+ * Include File Section
+ ******************************************************************************/
+#include "sdmaStruct.h"
+#ifdef MCU
+#include "iapiMiddleMcu.h"
+#endif /* MCU */
+
+/* ****************************************************************************
+ * Public Function Prototype Section
+ ******************************************************************************/
+bufferDescriptor * iapi_AllocBD (channelControlBlock * ccb_p);
+int iapi_AllocContext(contextData ** ctxd_p, unsigned char channel);
+int iapi_AllocChannelDesc(channelDescriptor ** cd_p, unsigned char channel);
+int iapi_ChangeChannelDesc (channelDescriptor * cd_p,
+ unsigned char whatToChange, unsigned long newval);
+void iapi_InitializeCallbackISR (void (* func_p)(channelDescriptor * cd_p,
+ void * arg));
+int iapi_InitializeMemory (channelControlBlock * ccb_p);
+
+#endif /* iapiMiddle_h */
diff --git a/arch/arm/plat-mxc/sdma/iapi/include/iapiMiddleMcu.h b/arch/arm/plat-mxc/sdma/iapi/include/iapiMiddleMcu.h
new file mode 100644
index 000000000000..a47c02d4440b
--- /dev/null
+++ b/arch/arm/plat-mxc/sdma/iapi/include/iapiMiddleMcu.h
@@ -0,0 +1,41 @@
+/******************************************************************************
+ *
+ * Copyright 2007 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
+ *
+ ******************************************************************************
+ *
+ * File: iapiMiddleMcu.h
+ *
+ * $Id iapiMiddleMcu.h $
+ *
+ * Description:
+ * prototypes for middle level function of I.API
+ *
+ *
+ *
+ *
+ * $Log iapiMiddleMcu.h
+ *
+ * ***************************************************************************/
+
+#ifndef _iapiMiddleMcu_h
+#define _iapiMiddleMcu_h
+
+/* ****************************************************************************
+ * Include File Section
+ ******************************************************************************/
+#include "sdmaStruct.h"
+
+/* ****************************************************************************
+ * Public Function Prototype Section
+ ******************************************************************************/
+
+#endif /* iapiMiddleMcu_h */
diff --git a/arch/arm/plat-mxc/sdma/iapi/include/iapiOS.h b/arch/arm/plat-mxc/sdma/iapi/include/iapiOS.h
new file mode 100644
index 000000000000..17186dae0fd5
--- /dev/null
+++ b/arch/arm/plat-mxc/sdma/iapi/include/iapiOS.h
@@ -0,0 +1,96 @@
+/******************************************************************************
+ *
+ * Copyright 2007 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
+ *
+ ******************************************************************************
+ *
+ * File: iapiOS.h
+ *
+ * $Id iapiOS.h $
+ *
+ * Description:
+ * prototypes for OS level function of I.API
+ *
+ *
+ *
+ *
+ * $Log iapiOS.h
+ *
+ * ***************************************************************************/
+
+#ifndef _iapiOS_h
+#define _iapiOS_h
+
+/* ****************************************************************************
+ * Boolean identifiers
+ *****************************************************************************/
+#define NO_OS 0
+#define LINUX 1
+#define SYMBIAN 2
+#define WINCE 3
+
+/* ****************************************************************************
+ * Include File Section
+ *****************************************************************************/
+#include "sdmaStruct.h"
+#include "iapiDefaults.h"
+#ifdef MCU
+#include "iapiLowMcu.h"
+#endif /*MCU*/
+#if OS == NO_OS
+#include <stdlib.h>
+#elif OS == LINUX
+#include <linux/types.h>
+#endif
+
+/* ****************************************************************************
+ * Macro-command Section
+ *****************************************************************************/
+#define SDMA_ERAM 0
+#define SDMA_IRAM 1
+#ifdef CONFIG_SDMA_IRAM
+#define MALLOC(x, s) (s == SDMA_ERAM)? (* iapi_Malloc)(x):(* iapi_iram_Malloc)(x)
+#else /*CONFIG_SDMA_IRAM */
+#define MALLOC(x, s) (* iapi_Malloc)(x)
+#endif /*CONFIG_SDMA_IRAM */
+#define FREE(x) if (x!=NULL) (* iapi_Free)(x)
+
+#define GOTO_SLEEP(x) (iapi_GotoSleep)(x)
+#define INIT_SLEEP(x) (iapi_InitSleep)(x)
+
+/* ****************************************************************************
+ * Public Function Prototype Section
+ *****************************************************************************/
+
+#ifdef CONFIG_SDMA_IRAM
+extern void*(* iapi_iram_Malloc) (size_t size);
+#endif /*CONFIG_SDMA_IRAM*/
+
+extern void*(* iapi_Malloc) (size_t size);
+extern void (* iapi_Free) (void * ptr);
+
+extern void*(* iapi_Virt2Phys) (void * ptr);
+extern void*(* iapi_Phys2Virt) (void * ptr);
+
+extern void (* iapi_WakeUp)(int);
+extern void (* iapi_GotoSleep)(int);
+extern void (* iapi_InitSleep)(int);
+
+extern void*(* iapi_memcpy)(void *dest, const void *src, size_t count);
+extern void*(* iapi_memset)(void *dest, int c, size_t count);
+
+extern void (* iapi_EnableInterrupts)(void);
+extern void (* iapi_DisableInterrupts)(void);
+
+extern int (* iapi_GetChannel)(int);
+extern int (* iapi_ReleaseChannel)(int);
+
+#endif /* _iapiOS_h */
diff --git a/arch/arm/plat-mxc/sdma/iapi/include/sdmaStruct.h b/arch/arm/plat-mxc/sdma/iapi/include/sdmaStruct.h
new file mode 100644
index 000000000000..bc42dabba554
--- /dev/null
+++ b/arch/arm/plat-mxc/sdma/iapi/include/sdmaStruct.h
@@ -0,0 +1,426 @@
+/******************************************************************************
+ *
+ * Copyright 2007-2009 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
+ *
+ ******************************************************************************
+ *
+ * File: sdmaStruct.h
+ *
+ * $Id sdmaStruct.h $
+ *
+ * Description: provides necessary definitions and inclusion for ipcmStruct.c
+ *
+ * $Log $
+ *
+ *****************************************************************************/
+#ifndef _sdmaStruct_h
+#define _sdmaStruct_h
+
+/* ****************************************************************************
+ * Include File Section
+ ******************************************************************************/
+
+/* ****************************************************************************
+ * Macro-command Section
+ ******************************************************************************/
+
+/**
+ * Identifier NULL
+ */
+#ifndef NULL
+#define NULL 0
+#endif
+
+/**
+ * Boolean identifiers
+ */
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+/**
+ * Number of channels
+ */
+#define CH_NUM 32
+/**
+ * Number of events
+ */
+#ifdef MXC_SDMA_V2
+#define EVENTS_NUM 48
+#else
+#define EVENTS_NUM 32
+#endif
+/**
+ * Channel configuration
+ */
+#define DONT_OWN_CHANNEL 0
+#define OWN_CHANNEL 1
+
+/**
+ * Ownership (value defined to computed decimal value)
+ */
+#define CH_OWNSHP_OFFSET_EVT 0
+#define CH_OWNSHP_OFFSET_MCU 1
+#define CH_OWNSHP_OFFSET_DSP 2
+/**
+ * Indexof the greg which holds address to start a script from when channel
+ * becomes current.
+ */
+#define SDMA_NUMBER_GREGS 8
+
+/**
+ * Channel contexts management
+ */
+
+#define CHANNEL_CONTEXT_BASE_ADDRESS 0x800
+/**
+ * Buffer descriptor status values.
+ */
+#define BD_DONE 0x01
+#define BD_WRAP 0x02
+#define BD_CONT 0x04
+#define BD_INTR 0x08
+#define BD_RROR 0x10
+#define BD_LAST 0x20
+#define BD_EXTD 0x80
+
+
+/**
+ * Data Node descriptor status values.
+ */
+#define DND_END_OF_FRAME 0x80
+#define DND_END_OF_XFER 0x40
+#define DND_DONE 0x20
+#define DND_UNUSED 0x01
+
+/**
+ * IPCV2 descriptor status values.
+ */
+#define BD_IPCV2_END_OF_FRAME 0x40
+
+
+#define IPCV2_MAX_NODES 50
+/**
+ * Error bit set in the CCB status field by the SDMA,
+ * in setbd routine, in case of a transfer error
+ */
+#define DATA_ERROR 0x10000000
+
+/**
+ * Buffer descriptor commands.
+ */
+#define C0_ADDR 0x01
+#define C0_LOAD 0x02
+#define C0_DUMP 0x03
+#define C0_SETCTX 0x07
+#define C0_GETCTX 0x03
+#define C0_SETDM 0x01
+#define C0_SETPM 0x04
+#define C0_GETDM 0x02
+#define C0_GETPM 0x08
+/**
+ * Transfer types, encoded in the BD command field
+ */
+#define TRANSFER_32BIT 0x00
+#define TRANSFER_8BIT 0x01
+#define TRANSFER_16BIT 0x02
+#define TRANSFER_24BIT 0x03
+/**
+ * Change endianness indicator in the BD command field
+ */
+#define CHANGE_ENDIANNESS 0x80
+/**
+ * Size in bytes
+ */
+#define SDMA_BD_SIZE 8
+#define SDMA_EXTENDED_BD_SIZE 12
+#define BD_NUMBER 4
+/**
+ * Channel interrupt policy
+ */
+#define DEFAULT_POLL 0
+#define CALLBACK_ISR 1
+/**
+ * Channel status
+ */
+#define UNINITIALIZED 0
+#define INITIALIZED 1
+
+/**
+ * IoCtl particular values
+ */
+#define SET_BIT_ALL 0xFFFFFFFF
+#define BD_NUM_OFFSET 16
+#define BD_NUM_MASK 0xFFFF0000
+
+/**
+ * Maximum values for IoCtl calls, used in high or middle level calls
+ */
+#define MAX_BD_NUM 256
+#define MAX_BD_SIZE 65536
+#define MAX_BLOCKING 2
+#define MAX_SYNCH 2
+#define MAX_OWNERSHIP 8
+#define MAX_CH_PRIORITY 8
+#define MAX_TRUST 2
+#define MAX_WML 256
+
+
+/**
+ * Access to channelDescriptor fields
+ */
+enum {
+ IAPI_CHANNELNUMBER,
+ IAPI_BUFFERDESCNUMBER,
+ IAPI_BUFFERSIZE,
+ IAPI_BLOCKING,
+ IAPI_CALLBACKSYNCH,
+ IAPI_OWNERSHIP,
+ IAPI_PRIORITY,
+ IAPI_TRUST,
+ IAPI_UNUSED,
+ IAPI_CALLBACKISR_PTR,
+ IAPI_CCB_PTR,
+ IAPI_BDWRAP,
+ IAPI_WML
+};
+
+/**
+ * Default values for channel descriptor - nobody ownes the channel
+ */
+#define CD_DEFAULT_OWNERSHIP 7
+
+
+/**
+ * User Type Section
+ */
+
+/**
+ * Command/Mode/Count of buffer descriptors
+ */
+
+#if (ENDIANNESS==B_I_G_ENDIAN)
+typedef struct iapi_modeCount_ipcv2 {
+ unsigned long status : 8; /**< L, E , D bits stored here */
+ unsigned long reserved : 8;
+ unsigned long count : 16; /**< <size of the buffer pointed by this BD */
+} modeCount_ipcv2;
+#else
+typedef struct iapi_modeCount_ipcv2 {
+ unsigned long count : 16; /**<size of the buffer pointed by this BD */
+ unsigned long reserved : 8; /**Reserved*/
+ unsigned long status : 8; /**< L, E , D bits stored here */
+} modeCount_ipcv2;
+#endif
+/**
+ * Data Node descriptor - IPCv2
+ * (differentiated between evolutions of SDMA)
+ */
+typedef struct iapi_dataNodeDescriptor {
+ modeCount_ipcv2 mode; /**<command, status and count */
+ void * bufferAddr; /**<address of the buffer described */
+} dataNodeDescriptor;
+
+#if (ENDIANNESS==B_I_G_ENDIAN)
+typedef struct iapi_modeCount_ipcv1_v2 {
+ unsigned long endianness: 1;
+ unsigned long reserved: 7;
+ unsigned long status : 8; /**< E,R,I,C,W,D status bits stored here */
+ unsigned long count : 16; /**< size of the buffer pointed by this BD */
+} modeCount_ipcv1_v2;
+#else
+typedef struct iapi_modeCount_ipcv1_v2 {
+ unsigned long count : 16; /**<size of the buffer pointed by this BD */
+ unsigned long status : 8; /**< E,R,I,C,W,D status bits stored here */
+ unsigned long reserved: 7;
+ unsigned long endianness: 1;
+} modeCount_ipcv1_v2;
+#endif
+/**
+ * Buffer descriptor
+ * (differentiated between evolutions of SDMA)
+ */
+typedef struct iapi_bufferDescriptor_ipcv1_v2 {
+ modeCount_ipcv1_v2 mode; /**<command, status and count */
+ void * bufferAddr; /**<address of the buffer described */
+ void * extBufferAddr; /**<extended buffer address */
+} bufferDescriptor_ipcv1_v2;
+
+
+/**
+ * Mode/Count of data node descriptors - IPCv2
+ */
+
+#if (ENDIANNESS==B_I_G_ENDIAN)
+typedef struct iapi_modeCount {
+ unsigned long command : 8; /**< command mostlky used for channel 0 */
+ unsigned long status : 8; /**< E,R,I,C,W,D status bits stored here */
+ unsigned long count : 16; /**< size of the buffer pointed by this BD */
+} modeCount;
+#else
+typedef struct iapi_modeCount {
+ unsigned long count : 16; /**<size of the buffer pointed by this BD */
+ unsigned long status : 8; /**< E,R,I,C,W,D status bits stored here */
+ unsigned long command : 8; /**< command mostlky used for channel 0 */
+} modeCount;
+#endif
+
+
+/**
+ * Buffer descriptor
+ * (differentiated between evolutions of SDMA)
+ */
+typedef struct iapi_bufferDescriptor {
+ modeCount mode; /**<command, status and count */
+ void * bufferAddr; /**<address of the buffer described */
+ void * extBufferAddr; /**<extended buffer address */
+} bufferDescriptor;
+
+
+
+struct iapi_channelControlBlock;
+struct iapi_channelDescriptor;
+/**
+ * Channel Descriptor
+ */
+typedef struct iapi_channelDescriptor {
+ unsigned char channelNumber ;/**<stores the channel number */
+ unsigned char bufferDescNumber;/**<number of BD's automatically allocated for this channel */
+ unsigned short bufferSize ;/**<size (in bytes) of buffer descriptors */
+ unsigned long blocking :3;/**<blocking / non blocking feature selection */
+ unsigned long callbackSynch :1;/**<polling/ callback method selection */
+ unsigned long ownership :3;/**<ownership of the channel (host+dedicated+event)*/
+ unsigned long priority :3;/**<reflects the SDMA channel priority register */
+ unsigned long trust :1;/**<trusted buffers or kernel allocated */
+ unsigned long useDataSize :1;/**<indicates if the dataSize field is meaningfull */
+ unsigned long dataSize :2;/**<data transfer size - 8,16,24 or 32 bits*/
+ unsigned long forceClose :1;/**<if TRUE, close channel even with BD owned by SDMA*/
+ unsigned long scriptId :7;/**<number of the script */
+ unsigned long watermarkLevel:10;/**<Watermark level for the peripheral access*/
+ unsigned long eventMask1; /**<First Event mask */
+ unsigned long eventMask2; /**<Second Event mask */
+ unsigned long peripheralAddr; /**<Address of the peripheral or its fifo when needed */
+ void (* callbackISR_ptr)(struct iapi_channelDescriptor*, void*); /**<pointer to the callback function (or NULL) */
+ struct iapi_channelControlBlock * ccb_ptr; /**<pointer to the channel control block associated to this channel */
+} channelDescriptor;
+
+/**
+ * Channel Status
+ */
+typedef struct iapi_channelStatus {
+ unsigned long unused :29;/**<*/
+ unsigned long openedInit : 1;/**<channel is initialized or not */
+ unsigned long stateDirection: 1;/**<sdma is reading/writing (as seen from channel owner core) */
+ unsigned long execute : 1;/**<channel is being processed (started) or not */
+} channelStatus;
+
+/**
+ * Channel control Block
+ */
+typedef struct iapi_channelControlBlock {
+ bufferDescriptor * currentBDptr; /**<current buffer descriptor processed */
+ bufferDescriptor * baseBDptr; /**<first element of buffer descriptor array */
+ channelDescriptor * channelDescriptor; /**<pointer to the channel descriptor */
+ channelStatus status; /**<open/close ; started/stopped ; read/write */
+} channelControlBlock;
+
+/**
+ * Context structure.
+ */
+#if (ENDIANNESS==B_I_G_ENDIAN)
+typedef struct iapi_stateRegisters {
+ unsigned long sf : 1;/**<source falut while loading data */
+ unsigned long unused0: 1;/**<*/
+ unsigned long rpc :14;/**<return program counter */
+ unsigned long t : 1;/**<test bit:status of arithmetic & test instruction*/
+ unsigned long unused1: 1;/**<*/
+ unsigned long pc :14;/**<program counter */
+ unsigned long lm : 2;/**<loop mode */
+ unsigned long epc :14;/**<loop end program counter */
+ unsigned long df : 1;/**<destiantion falut while storing data */
+ unsigned long unused2: 1;/**<*/
+ unsigned long spc :14;/**<loop start program counter */
+} stateRegiters;
+#else
+typedef struct iapi_stateRegisters {
+ unsigned long pc :14;/**<program counter */
+ unsigned long unused1: 1;/**<*/
+ unsigned long t : 1;/**<test bit: status of arithmetic & test instruction*/
+ unsigned long rpc :14;/**<return program counter */
+ unsigned long unused0: 1;/**<*/
+ unsigned long sf : 1;/**<source falut while loading data */
+ unsigned long spc :14;/**<loop start program counter */
+ unsigned long unused2: 1;/**<*/
+ unsigned long df : 1;/**<destiantion falut while storing data */
+ unsigned long epc :14;/**<loop end program counter */
+ unsigned long lm : 2;/**<loop mode */
+} stateRegiters;
+#endif
+
+/**
+ * This is SDMA version of SDMA
+ */
+typedef struct iapi_contextData {
+ stateRegiters channelState; /**<channel state bits */
+ unsigned long gReg[ SDMA_NUMBER_GREGS ]; /**<general registers */
+ unsigned long mda; /**<burst dma destination address register */
+ unsigned long msa; /**<burst dma source address register */
+ unsigned long ms; /**<burst dma status register */
+ unsigned long md; /**<burst dma data register */
+ unsigned long pda; /**<peripheral dma destination address register */
+ unsigned long psa; /**<peripheral dma source address register */
+ unsigned long ps; /**<peripheral dma status register */
+ unsigned long pd; /**<peripheral dma data register */
+ unsigned long ca; /**<CRC polynomial register */
+ unsigned long cs; /**<CRC accumulator register */
+ unsigned long dda; /**<dedicated core destination address register */
+ unsigned long dsa; /**<dedicated core source address register */
+ unsigned long ds; /**<dedicated core status register */
+ unsigned long dd; /**<dedicated core data register */
+ unsigned long scratch0; /**<scratch */
+ unsigned long scratch1; /**<scratch */
+ unsigned long scratch2; /**<scratch */
+ unsigned long scratch3; /**<scratch */
+ unsigned long scratch4; /**<scratch */
+ unsigned long scratch5; /**<scratch */
+ unsigned long scratch6; /**<scratch */
+ unsigned long scratch7; /**<scratch */
+
+} contextData;
+
+/**
+ *This structure holds the necessary data for the assignment in the
+ * dynamic channel-script association
+ */
+typedef struct iapi_script_data {
+ unsigned short load_address;/**<start address of the script*/
+ unsigned long wml; /**<parameters for the channel descriptor*/
+ unsigned long shp_addr; /**<shared peripheral base address*/
+ unsigned long per_addr; /**<peripheral base address for p2p source*/
+ unsigned long event_mask1; /**<First Event mask */
+ unsigned long event_mask2; /**<Second Event mask */
+} script_data;
+
+/**
+ *This structure holds the the useful bits of the CONFIG register
+ */
+typedef struct iapi_configs_data {
+ unsigned long dspdma :1; /*indicates if the DSPDMA is used */
+ unsigned long rtdobs :1; /*indicates if Real-Time Debug pins are enabled */
+ unsigned long acr :1; /**indicates if AHB freq /core freq = 2 or 1 */
+ unsigned long csm :2; /**indicates which context switch mode is selected*/
+} configs_data;
+
+#endif /* _sdmaStruct_h */
diff --git a/arch/arm/plat-mxc/sdma/iapi/src/Makefile b/arch/arm/plat-mxc/sdma/iapi/src/Makefile
new file mode 100644
index 000000000000..4c112bf22384
--- /dev/null
+++ b/arch/arm/plat-mxc/sdma/iapi/src/Makefile
@@ -0,0 +1,18 @@
+#
+# Makefile for I.API sources.
+#
+ifneq ($(KBUILD_SRC),)
+ccflags-y += -I$(KBUILD_SRC)/arch/arm/plat-mxc/sdma/iapi/include \
+ -I$(KBUILD_SRC)/include/linux \
+ -DMCU -DOS=LINUX \
+ -DL_I_T_T_L_E_ENDIAN=0 -DB_I_G_ENDIAN=1 \
+ -DENDIANNESS=L_I_T_T_L_E_ENDIAN
+else
+ccflags-y += -Iarch/arm/plat-mxc/sdma/iapi/include \
+ -Iinclude/linux \
+ -DMCU -DOS=LINUX \
+ -DL_I_T_T_L_E_ENDIAN=0 -DB_I_G_ENDIAN=1 \
+ -DENDIANNESS=L_I_T_T_L_E_ENDIAN
+endif
+
+obj-y += iapiLow.o iapiLowMcu.o iapiMiddle.o iapiMiddleMcu.o iapiHigh.o iapiDefaults.o iapiOS.o
diff --git a/arch/arm/plat-mxc/sdma/iapi/src/iapiDefaults.c b/arch/arm/plat-mxc/sdma/iapi/src/iapiDefaults.c
new file mode 100644
index 000000000000..345c240cb15c
--- /dev/null
+++ b/arch/arm/plat-mxc/sdma/iapi/src/iapiDefaults.c
@@ -0,0 +1,110 @@
+/******************************************************************************
+ *
+ * Copyright 2007 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
+ *
+ ******************************************************************************
+ *
+ * File: iapiDefaults.c
+ *
+ * $Id iapiDefaults.c $
+ *
+ * Description:
+ * This library is written in C to guarantee functionality and integrity in
+ * the usage of SDMA virtual DMA channels. This API (Application Programming
+ * Interface) allow SDMA channels' access in an OPEN, READ, WRITE, CLOSE
+ * fashion.
+ *
+ * Usage:
+ *
+ * Files:
+ *
+ *
+* /
+ *
+ * $Log iapiDefaults.c $
+ *
+ *****************************************************************************/
+
+/* ****************************************************************************
+ * Include File Section
+ ******************************************************************************/
+#include "iapiDefaults.h"
+
+/* ****************************************************************************
+ * Global Variable Section
+ ******************************************************************************/
+
+/**
+ * @brief System Call-back ISRs Table
+ */
+void (* callbackIsrTable[CH_NUM])(channelDescriptor* cd_p, void* arg);
+
+/**
+ * @brief User registered pointers table
+ */
+void * userArgTable[CH_NUM];
+
+/**
+ * @brief Pointer to the first CCB in the CCB array
+ */
+channelControlBlock * iapi_CCBHead = NULL;
+
+
+/**Default channel description.
+ *
+ * Initialization values are:\n
+ * - channelNumber = 0
+ * - bufferDescNumber = 1
+ * - bufferSize = 8
+ * - blocking = 0
+ * - callbackSynch = DEFAULT_POLL
+ * - ownership = CD_DEFAULT_OWNERSHIP
+ * - priority = 1
+ * - trust = TRUE
+ * - useDataSize = 0
+ * - dataSize = 0
+ * - forceClose = 0
+ * - scriptId = 0
+ * - watermarkLevel = 0
+ * - eventMask1 = 0
+ * - eventMask2 = 0
+ * - peripheralAddr = NULL
+ * - callbackISR_ptr = NULL
+ * - iapi_channelControlBlock = NULL
+ */
+channelDescriptor iapi_ChannelDefaults = {0, 1, 8, 0, DEFAULT_POLL,
+ CD_DEFAULT_OWNERSHIP, 1, TRUE, 0, 0, 0, 0,
+ 0, 0x00, 0x00, 0x00, NULL, NULL};
+
+/**
+ * Integrated error management
+ */
+unsigned int iapi_errno = 0;
+volatile unsigned long iapi_SDMAIntr = 0;
+
+/* Default config register.
+ * Initialization values are:
+ * dspdma used
+ * Real-Time Debug pins disabled
+ * AHB freq / core freq = 2
+ * dynamic context switch
+*/
+configs_data iapi_ConfigDefaults = {1, 0, 0, 3};
+
+#ifdef SDMA_SKYE
+/* Default sdma State : UNDEF
+ *possible value are UNDEF, OPEN, LOCK, CLOSED, CLOSE_LOCK
+ */
+
+sdmaState iapi_SdmaState= UNDEF;
+#endif
+
+/* ***************************************************************************/
diff --git a/arch/arm/plat-mxc/sdma/iapi/src/iapiHigh.c b/arch/arm/plat-mxc/sdma/iapi/src/iapiHigh.c
new file mode 100644
index 000000000000..abdd2d89ab67
--- /dev/null
+++ b/arch/arm/plat-mxc/sdma/iapi/src/iapiHigh.c
@@ -0,0 +1,2798 @@
+/******************************************************************************
+ *
+ * Copyright 2007-2008 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
+ *
+ ******************************************************************************
+ *
+ * File: iapiHigh.c
+ *
+ * $Id iapiHigh.c $
+ *
+ * Description:
+ * This library is written in C to guarantee functionality and integrity in
+ * the usage of SDMA virtual DMA channels. This API (Application Programming
+ * Interface) allow SDMA channels' access in an OPEN, READ, WRITE, CLOSE
+ * fashion.
+ * These are the HIGH level functions of the I.API.
+ *
+ *
+ * /
+ *
+ * $Log iapiHigh.c $
+ *
+ *****************************************************************************/
+
+/* ****************************************************************************
+ * Include File Section
+ *****************************************************************************/
+#include <stdarg.h>
+#include <string.h>
+
+#include "epm.h"
+#include "iapi.h"
+
+/* ****************************************************************************
+ * External Reference Section (for compatibility with already developed code)
+ *****************************************************************************/
+static void iapi_read_ipcv2_callback(struct iapi_channelDescriptor* cd_p, void* data);
+
+/* ****************************************************************************
+ * Global Variable Section
+ *****************************************************************************/
+#define MAX_CHANNEL 32
+
+static dataNodeDescriptor* dnd_read_control_struct[MAX_CHANNEL];
+
+/* MASK to get Nullify all the bits of Status in Data Node descriptor apart from L, E and D*/
+
+#define GET_LED_MASK 0xE0
+
+/*Table defines mapping of Data Node Descriptor to Buffer Descriptor status*/
+
+static unsigned char dnd_2_bd_status[]=
+{
+0x85, /*00 L = 0, E = 0, D = 0*/
+0x00, /*01*/
+0x00, /*02*/
+0x00, /*03*/
+0x00, /*04*/
+0x00, /*05*/
+0x00, /*06*/
+0x00, /*07*/
+0x00, /*08*/
+0x00, /*09*/
+0x00, /*0A*/
+0x00, /*0B*/
+0x00, /*0C*/
+0x00, /*0D*/
+0x00, /*0E*/
+0x00, /*0F*/
+0x00, /*10*/
+0x00,/*11*/
+0x00,/*12*/
+0x00,/*13*/
+0x00,/*14*/
+0x00,/*15*/
+0x00,/*16*/
+0x00,/*17*/
+0x00,/*18*/
+0x00,/*19*/
+0x00,/*1A*/
+0x00,/*1B*/
+0x00,/*1C*/
+0x00,/*1D*/
+0x00,/*1E*/
+0x00,/*1F*/
+0x84,/*20 L = 0, E = 0, D = 1 */
+0x00,/*21*/
+0x00,/*22*/
+0x00,/*23*/
+0x00,/*24*/
+0x00,/*25*/
+0x00,/*26*/
+0x00,/*27*/
+0x00,/*28*/
+0x00,/*29*/
+0x00,/*2A*/
+0x00,/*2B*/
+0x00,/*2C*/
+0x00,/*2D*/
+0x00,/*2E*/
+0x00,/*2F*/
+0x00,/*30*/
+0x00,/*31*/
+0x00,/*32*/
+0x00,/*33*/
+0x00,/*34*/
+0x00,/*35*/
+0x00,/*36*/
+0x00,/*37*/
+0x00,/*38*/
+0x00,/*39*/
+0x00,/*3A*/
+0x00,/*3B*/
+0x00,/*3C*/
+0x00,/*3D*/
+0x00,/*3E*/
+0x00,/*3F*/
+0xAB,/*40 L = 0, E = 1, D = 0*/
+0x00,/*41*/
+0x00,/*42*/
+0x00,/*43*/
+0x00,/*44*/
+0x00,/*45*/
+0x00,/*46*/
+0x00,/*47*/
+0x00,/*48*/
+0x00,/*49*/
+0x00,/*4A*/
+0x00,/*4B*/
+0x00,/*4C*/
+0x00,/*4D*/
+0x00,/*4E*/
+0x00,/*4F*/
+0x00,/*50*/
+0x00,/*51*/
+0x00,/*52*/
+0x00,/*53*/
+0x00,/*54*/
+0x00,/*55*/
+0x00,/*56*/
+0x00,/*57*/
+0x00,/*58*/
+0x00,/*59*/
+0x00,/*5A*/
+0x00,/*5B*/
+0x00,/*5C*/
+0x00,/*5D*/
+0x00,/*5E*/
+0x00,/*5F*/
+0xAA,/*60 L = 0, E = 1, D = 1*/
+0x00,/*61*/
+0x00,/*62*/
+0x00,/*63*/
+0x00,/*64*/
+0x00,/*65*/
+0x00,/*66*/
+0x00,/*67*/
+0x00,/*68*/
+0x00,/*69*/
+0x00,/*6A*/
+0x00,/*6B*/
+0x00,/*6C*/
+0x00,/*6D*/
+0x00,/*6E*/
+0x00,/*6F*/
+0x00,/*70*/
+0x00,/*71*/
+0x00,/*72*/
+0x00,/*73*/
+0x00,/*74*/
+0x00,/*75*/
+0x00,/*76*/
+0x00,/*77*/
+0x00,/*78*/
+0x00,/*79*/
+0x00,/*7A*/
+0x00,/*7B*/
+0x00,/*7C*/
+0x00,/*7D*/
+0x00,/*7E*/
+0x00,/*7F*/
+0xC5,/*80 L = 1, E = 0, D = 0*/
+0x00,/*81*/
+0x00,/*82*/
+0x00,/*83*/
+0x00,/*84*/
+0x00,/*85*/
+0x00,/*86*/
+0x00,/*87*/
+0x00,/*88*/
+0x00,/*89*/
+0x00,/*8A*/
+0x00,/*8B*/
+0x00,/*8C*/
+0x00,/*8D*/
+0x00,/*8E*/
+0x00,/*8F*/
+0x00,/*90*/
+0x00,/*91*/
+0x00,/*92*/
+0x00,/*93*/
+0x00,/*94*/
+0x00,/*95*/
+0x00,/*96*/
+0x00,/*97*/
+0x00,/*98*/
+0x00,/*99*/
+0x00,/*9A*/
+0x00,/*9B*/
+0x00,/*9C*/
+0x00,/*9D*/
+0x00,/*9E*/
+0x00,/*9F*/
+0xC4,/*A0 L = 1, E = 0, D = 1*/
+0x00,/*A1*/
+0x00,/*A2*/
+0x00,/*A3*/
+0x00,/*A4*/
+0x00,/*A5*/
+0x00,/*A6*/
+0x00,/*A7*/
+0x00,/*A8*/
+0x00,/*A9*/
+0x00,/*AA*/
+0x00,/*AB*/
+0x00,/*AC*/
+0x00,/*AD*/
+0x00,/*AE*/
+0x00,/*AF*/
+0x00,/*B0*/
+0x00,/*B1*/
+0x00,/*B2*/
+0x00,/*B3*/
+0x00,/*B4*/
+0x00,/*B5*/
+0x00,/*B6*/
+0x00,/*B7*/
+0x00,/*B8*/
+0x00,/*B9*/
+0x00,/*BA*/
+0x00,/*BB*/
+0x00,/*BC*/
+0x00,/*BD*/
+0x00,/*BE*/
+0x00,/*BF*/
+0xEB,/*C0 L = 1, E = 1, D = 0*/
+0x00,/*C1*/
+0x00,/*C2*/
+0x00,/*C3*/
+0x00,/*C4*/
+0x00,/*C5*/
+0x00,/*C6*/
+0x00,/*C7*/
+0x00,/*C8*/
+0x00,/*C9*/
+0x00,/*CA*/
+0x00,/*CB*/
+0x00,/*CC*/
+0x00,/*CD*/
+0x00,/*CE*/
+0x00,/*CF*/
+0x00,/*D0*/
+0x00,/*D1*/
+0x00,/*D2*/
+0x00,/*D3*/
+0x00,/*D4*/
+0x00,/*D5*/
+0x00,/*D6*/
+0x00,/*D7*/
+0x00,/*D8*/
+0x00,/*D9*/
+0x00,/*DA*/
+0x00,/*DB*/
+0x00,/*DC*/
+0x00,/*DD*/
+0x00,/*DE*/
+0x00,/*DF*/
+0xEA,/*E0 L = 1, E = 1, D = 1*/
+0x00,/*E1*/
+0x00,/*E2*/
+0x00,/*E3*/
+0x00,/*E4*/
+0x00,/*E5*/
+0x00,/*E6*/
+0x00,/*E7*/
+0x00,/*E8*/
+0x00,/*E9*/
+0x00,/*EA*/
+0x00,/*EB*/
+0x00,/*EC*/
+0x00,/*ED*/
+0x00,/*EE*/
+0x00,/*EF*/
+0x00,/*F0*/
+0x00,/*F1*/
+0x00,/*F2*/
+0x00,/*F3*/
+0x00,/*F4*/
+0x00,/*F5*/
+0x00,/*F6*/
+0x00,/*F7*/
+0x00,/*F8*/
+0x00,/*F9*/
+0x00,/*FA*/
+0x00,/*FB*/
+0x00,/*FC*/
+0x00,/*FD*/
+0x00,/*FE*/
+0x00/*FF*/
+};
+/* ****************************************************************************
+ * Function Section
+ *****************************************************************************/
+
+/* ***************************************************************************/
+/**Opens an SDMA channel to be used by the library.
+ *
+ * <b>Algorithm:</b>\n
+ *
+ * - Check if initialization is necessary.
+ * - Check that user initialized OS dependant functions.
+ * - Test validity of input parameters
+ * - Check whole channel control block data structure
+ * - Finish initializations (tables with default values)
+ * - Initialize channel 0 is dedicated to communications with SDMA
+ * - Check channel control block definition
+ * - if the channel descriptor is not initialized, initialize it with
+ * the default value
+ * - If buffer descriptor already allocated, exit with iapi_errno filled
+ * complete the lowest bits with the number of 'D' bits set
+ * - Buffer Descriptors allocation
+ * - Channel's configuration properties (mcu side only)
+ * - read/write direction => enable/disable channel setting
+ *
+ * @param *cd_p -If channelNumber is 0, it is pointer to channel descriptor for the channnel 0 to be opened and
+ has default values.
+ * For other channels,this function should be called after channel 0 has been opened, and it is channel descriptor for
+ channel 0.Must be allocated.
+ * @param channelNumber channel to be opened
+ *
+ * @return
+ * - IAPI_SUCCESS : OK
+ * - -iapi_errno : close failed, return negated value of iapi_errno
+ */
+int
+iapi_Open (channelDescriptor * cd_p, unsigned char channelNumber)
+{
+ channelControlBlock * ccb_p;
+ channelControlBlock * local_ccb_p;
+ channelDescriptor * local_cd_p;
+ bufferDescriptor * bd_p;
+ unsigned char index = 0;
+ int result = IAPI_SUCCESS;
+#ifdef MCU
+ volatile unsigned long * channelPriorityMatx;
+#endif /* MCU */
+
+
+ /*
+ * 1. Check if initialization is necessary
+ */
+ if (cd_p == NULL){
+ result = IAPI_ERR_CD_UNINITIALIZED |
+ IAPI_ERR_CH_AVAILABLE | channelNumber;
+ iapi_errno = result;
+ return -result;
+ }
+
+ /* Verify these functions every time*/
+ if((iapi_GetChannel == NULL)||(iapi_ReleaseChannel == NULL))
+ {
+ result = IAPI_ERR_NO_OS_FN | channelNumber;
+ iapi_errno = result;
+ return -result;
+ }
+
+ /* Try to aquire channel*/
+ if(iapi_GetChannel(channelNumber) != 0)
+ {
+ result = IAPI_ERR_CH_IN_USE | channelNumber;
+ iapi_errno = result;
+ return -result;
+ }
+
+ if (channelNumber == 0 && cd_p->ccb_ptr == NULL){
+ /* Verify that the user initialized all OS dependant functions required
+ * by the library.
+ */
+ if((iapi_Malloc == NULL)||(iapi_Free == NULL)||(iapi_Virt2Phys == NULL)||
+ (iapi_Phys2Virt == NULL)||(iapi_GotoSleep == NULL)||
+ (iapi_WakeUp == NULL)||(iapi_InitSleep == NULL)||(iapi_memset == NULL)||
+ (iapi_memcpy == NULL))
+ {
+ result = IAPI_ERR_NO_OS_FN | channelNumber;
+ iapi_errno = result;
+ iapi_ReleaseChannel(channelNumber);
+ return -result;
+ }
+ /* Whole channel control block data structure */
+ ccb_p = (channelControlBlock *)
+ MALLOC(CH_NUM*sizeof(channelControlBlock), SDMA_IRAM);
+ if (ccb_p == NULL){
+ result = IAPI_ERR_CCB_ALLOC_FAILED |
+ IAPI_ERR_CH_AVAILABLE | channelNumber;
+ iapi_errno = result;
+ iapi_ReleaseChannel(channelNumber);
+ return -result;
+ }
+ /* Zero-out the CCB structures array just allocated*/
+ iapi_memset(ccb_p, 0x00, CH_NUM*sizeof(channelControlBlock));
+ /* Save the address of the CCB structures array*/
+ iapi_CCBHead = ccb_p;
+
+ cd_p->ccb_ptr = (struct iapi_channelControlBlock *)ccb_p;
+ ccb_p->channelDescriptor = cd_p;
+#ifdef MCU
+ /* finish initializations */
+ iapi_InitChannelTables();
+#endif /* MCU */
+ /* Channel 0 is dedicated to communications with SDMA */
+ cd_p->ownership = ((DONT_OWN_CHANNEL << CH_OWNSHP_OFFSET_EVT ) |
+ ( OWN_CHANNEL << CH_OWNSHP_OFFSET_MCU ) |
+ (DONT_OWN_CHANNEL << CH_OWNSHP_OFFSET_DSP ));
+ cd_p->bufferDescNumber = 1;
+ }
+
+ /*
+ * 2. Check channel control block
+ */
+ ccb_p = cd_p->ccb_ptr;
+ if (ccb_p == NULL){
+ result = IAPI_ERR_NO_CCB_DEFINED | IAPI_ERR_CH_AVAILABLE|channelNumber;
+ iapi_errno = result;
+ iapi_ReleaseChannel(channelNumber);
+ return -result;
+ }
+
+ /* Control block & Descriptor associated with the channel being worked on */
+ local_ccb_p = &ccb_p[channelNumber];
+ local_cd_p = ccb_p[channelNumber].channelDescriptor;
+
+ /* If the channel is not initialized, initialize it with the default value */
+ if (local_cd_p == NULL){
+ result = iapi_AllocChannelDesc (&local_cd_p, channelNumber);
+ if ( result!= IAPI_SUCCESS)
+ {
+ iapi_ReleaseChannel(channelNumber);
+ return result; //is allready negated from iapi_AllocChannelDesc
+ }
+
+ local_cd_p->ccb_ptr = (struct iapi_channelControlBlock *)local_ccb_p;
+ local_ccb_p->channelDescriptor = local_cd_p;
+ }
+
+ /*
+ * 3. If buffer descriptor already allocated, exit with iapi_errno filled
+ */
+ if ( local_ccb_p->baseBDptr != NULL ){
+ bd_p = (bufferDescriptor *)iapi_Phys2Virt(local_ccb_p->baseBDptr);
+ result = IAPI_ERR_BD_ALLOCATED;
+ for (index=1 ; index< local_cd_p->bufferDescNumber ; index++){
+ if ((bd_p->mode.status & BD_DONE) == BD_DONE){
+ /* complete the lowest bits with the number of 'D' bits set */
+ result++;
+ }
+ bd_p++;
+ }
+ iapi_errno = result;
+ iapi_ReleaseChannel(channelNumber);
+ return -result;
+ }
+
+ /*
+ * 4. Buffer Descriptors allocation
+ */
+ iapi_InitializeMemory(local_ccb_p);
+
+#ifdef MCU
+ /*
+ * 5. Channel's configuration properties (mcu side only)
+ */
+ iapi_ChannelConfig( channelNumber,
+ ( local_cd_p->ownership >> CH_OWNSHP_OFFSET_EVT ) & 1UL,
+ ( local_cd_p->ownership >> CH_OWNSHP_OFFSET_MCU ) & 1UL,
+ ( local_cd_p->ownership >> CH_OWNSHP_OFFSET_DSP ) & 1UL);
+#endif /* MCU */
+
+ /* Setting interrupt handling */
+ iapi_ChangeCallbackISR(local_cd_p, local_cd_p->callbackISR_ptr);
+
+ /* Call initialization fn for polling synch on this channel*/
+ INIT_SLEEP(channelNumber);
+
+ /* No user arg pointer yet*/
+ userArgTable[cd_p->channelNumber]= NULL;
+
+ /*
+ * 6. read/write direction => enable/disable channel
+ */
+#ifdef MCU
+ channelPriorityMatx = &SDMA_CHNPRI_0;
+ channelPriorityMatx[channelNumber] = 1;
+#endif /* MCU */
+
+ local_ccb_p->status.openedInit = TRUE;
+ iapi_ReleaseChannel(channelNumber);
+ return IAPI_SUCCESS;
+}
+
+/* ***************************************************************************/
+/** Attempts to read nbyte from the data buffer descriptor associated with the
+ * channel channelNumber, into the user's data buffer pointed to by buf.
+ *
+ * <b>Algorithm:</b>\n
+ * - Check data structures are properly initialized:
+ * - Channel descriptor validity
+ * - Control block & Descriptor associated with the channel being worked on
+ * - Check initialization has been done for trusted channels
+ * - If transfer data size is used, check validity of combination transfer
+ * size/requested bytes
+ * - Set the 'D' done bits on all buffer descriptors
+ * - Starting of the channel
+ * - Synchronization mechanism handling:
+ * - for callback: just exit function
+ * - for polling: call the synchronization function then read data from
+ * buffer until either nbyte parameter is reached or all buffer descriptors
+ * have been processed.
+ *
+ * <b>Notes:</b>\n
+ * 1) Virtual DMA SDMA channels are unidirectional, an iapi_Read authorized
+ * on a channel means that we are expecting to receive from the SDMA. The
+ * meaning of an interrupt received from the SDMA is therefore that the
+ * data has been copied from the SDMA to the host's data buffers and is
+ * already passed on upper layers of the application.\n
+ *
+ * @param *cd_p chanenl descriptor for the channel to read from
+ * @param *buf buffer to receive the data
+ * @param nbyte number of bytes to read from channel
+ *
+ * @return
+ * - number of bytes read
+ * - -iapi_errno : in case of failure return negated value of iapi_errno
+ */
+int
+iapi_Read (channelDescriptor * cd_p, void * buf, unsigned short nbyte)
+{
+ int index = 0;
+ int readBytes;
+ int toRead;
+ int result = IAPI_SUCCESS;
+ unsigned int copyFinished;
+ int bufsize;
+ bufferDescriptor * bd_p;
+ channelControlBlock * ccb_p;
+ unsigned char * local_buf;
+ unsigned char chNum;
+ unsigned char div;
+
+ iapi_errno = IAPI_ERR_NO_ERROR;
+
+ /*
+ * 1. Check data structures are properly initialized
+ */
+ /* Channel descriptor validity */
+ if (cd_p == NULL){
+ result = IAPI_ERR_CD_UNINITIALIZED;
+ iapi_errno = result;
+ return -result;
+ }
+
+ /* Channel control block validity */
+ if (cd_p->ccb_ptr == NULL){
+ result = IAPI_ERR_CCB_UNINITIALIZED;
+ iapi_errno = result;
+ return -result;
+ }
+
+ /* Control block & Descriptor associated with the channel being worked on */
+ chNum = cd_p->channelNumber;
+ ccb_p = cd_p->ccb_ptr;
+
+ /* Try to aquire channel*/
+ if(iapi_GetChannel(chNum) != 0)
+ {
+ result = IAPI_ERR_CH_IN_USE | chNum;
+ iapi_errno = result;
+ return -result;
+ }
+
+ /* Check if channel is already opened/initialized */
+ if (ccb_p->status.openedInit == FALSE) {
+ result = IAPI_ERR_CHANNEL_UNINITIALIZED | IAPI_ERR_CH_AVAILABLE | chNum;
+ iapi_errno = result;
+ iapi_ReleaseChannel(chNum);
+ return -result;
+ }
+
+ /* Buffer descriptor validity */
+ bd_p = (bufferDescriptor *)iapi_Phys2Virt(ccb_p->baseBDptr);
+ if (bd_p == NULL ){
+ result = IAPI_ERR_BD_UNINITIALIZED | IAPI_ERR_CH_AVAILABLE | chNum;
+ iapi_errno = result;
+ iapi_ReleaseChannel(chNum);
+ return -result;
+ }
+
+
+ /* Check initialization has been done for trusted channels */
+ if (cd_p->trust == TRUE) {
+ bd_p = (bufferDescriptor *)iapi_Phys2Virt(ccb_p->baseBDptr);
+ for(index=0 ; index < cd_p->bufferDescNumber ; index++){
+ if ((bd_p->bufferAddr == NULL) || (bd_p->mode.count == 0)){
+ result = IAPI_ERR_BD_UNINITIALIZED | IAPI_ERR_CH_AVAILABLE | chNum;
+ iapi_errno = result;
+ iapi_ReleaseChannel(chNum);
+ return -result;
+ }
+ bd_p++;
+ }
+ }
+
+ bd_p = (bufferDescriptor *)iapi_Phys2Virt(ccb_p->baseBDptr);
+ /*If transfer data size is used, check that the required read length is
+ * divisible by transfer data size expressed in bytes
+ */
+ if(cd_p->useDataSize)
+ {
+ /*Check for divisibility only if data size different then 8bit*/
+ if(cd_p->dataSize != TRANSFER_8BIT)
+ {
+ switch(cd_p->dataSize)
+ {
+ case TRANSFER_32BIT:
+ div = 4;
+ break;
+ case TRANSFER_16BIT:
+ div = 2;
+ break;
+ case TRANSFER_24BIT:
+ div = 3;
+ break;
+ /*we should not get to default*/
+ default:
+ result = IAPI_ERR_INVALID_PARAMETER | chNum;
+ iapi_errno = result;
+ iapi_ReleaseChannel(chNum);
+ return -result;
+ }
+ /*check the total number of bytes requested*/
+ if((nbyte % div) != 0)
+ {
+ result = IAPI_ERR_INVALID_PARAMETER | chNum;
+ iapi_errno = result;
+ iapi_ReleaseChannel(chNum);
+ return -result;
+ }
+ /*now check the length of every BD*/
+ for(index=0 ; index < cd_p->bufferDescNumber ; index++)
+ {
+ if((bd_p->mode.count % div) != 0)
+ {
+ result = IAPI_ERR_INVALID_PARAMETER | chNum;
+ iapi_errno = result;
+ iapi_ReleaseChannel(chNum);
+ return -result;
+ }
+ bd_p++;
+ }
+ }
+ }
+
+ /*
+ * 2. Set the 'D' done bits on all buffer descriptors
+ */
+ bd_p = (bufferDescriptor *)iapi_Phys2Virt(ccb_p->baseBDptr);
+ for (index=0 ; index < cd_p->bufferDescNumber ; index++) {
+ bd_p->mode.status |= BD_DONE;
+ bd_p++;
+ }
+
+ /*
+ * 3. Starting of the channel
+ */
+ iapi_lowStartChannel (chNum);
+ ccb_p->status.execute = TRUE;
+ readBytes = 0;
+
+ /*
+ * 4. Synchronization mechanism handling
+ */
+ if( cd_p->callbackSynch == DEFAULT_POLL){
+ iapi_SynchChannel(chNum);
+
+ bd_p = (bufferDescriptor *)iapi_Phys2Virt(ccb_p->baseBDptr);
+ toRead = nbyte;
+ copyFinished = FALSE;
+ local_buf = (unsigned char *)buf;
+
+ /*
+ * Check the 'RROR' bit on all buffer descriptors, set error number
+ * and return IAPI_FAILURE if set.
+ */
+ for (index=0 ; index < cd_p->bufferDescNumber ; index++)
+ {
+ if(bd_p->mode.status & BD_RROR)
+ {
+ result = IAPI_ERR_RROR_BIT_READ | chNum;
+ iapi_errno = result;
+ iapi_ReleaseChannel(chNum);
+ return -result;
+ }
+ bd_p++;
+ }
+
+
+ /*
+ * 5. Read loop
+ */
+
+ bd_p = (bufferDescriptor *)iapi_Phys2Virt(ccb_p->baseBDptr);
+ while (!copyFinished)
+ {
+ if (!(bd_p->mode.status & BD_DONE))
+ {
+ if (cd_p->trust == FALSE) {
+ bufsize = cd_p->bufferSize;
+ } else {
+ bufsize = bd_p->mode.count;
+ }
+ /*if L bit is set, read only "count" bytes and exit the loop*/
+ if(bd_p->mode.status & BD_LAST)
+ {
+ bufsize = bd_p->mode.count;
+ copyFinished = TRUE;
+ }
+ if (toRead > bufsize)
+ {
+ if (cd_p->trust == FALSE)
+ {
+ iapi_memcpy(local_buf, iapi_Phys2Virt(bd_p->bufferAddr), bufsize);
+ local_buf += bufsize;
+ }
+ readBytes += bufsize;
+ toRead -= bufsize;
+ /*advance bd_p only if bit L is not set. The loop will exit anyway.*/
+ if(!(bd_p->mode.status & BD_LAST))
+ {
+ if (bd_p->mode.status & BD_WRAP)
+ {
+ bd_p = (bufferDescriptor *)iapi_Phys2Virt(ccb_p->baseBDptr);
+ }
+ else if(((bufferDescriptor *)iapi_Phys2Virt(ccb_p->baseBDptr) +
+ (cd_p->bufferDescNumber - 1)*sizeof(bufferDescriptor)) != bd_p)
+ {
+ bd_p++;
+ }
+ else
+ {
+ /* finished here : end of buffer descriptors */
+ copyFinished = TRUE;
+ }
+ }
+ }
+ else
+ {
+ if (cd_p->trust == FALSE)
+ {
+ iapi_memcpy(local_buf, iapi_Phys2Virt(bd_p->bufferAddr), toRead);
+ local_buf += toRead;
+ }
+ readBytes += toRead;
+ toRead = 0;
+ /* finished successfully : readBytes = nbytes */
+ copyFinished = TRUE;
+ }
+ }
+ else
+ {
+ /* finished here : buffer not already done*/
+ copyFinished = TRUE;
+ }
+ }
+ iapi_ReleaseChannel(chNum);
+ }
+
+ /*
+ *If synchronization type is callback, the user of I.API must
+ *release the channel
+ */
+ return readBytes;
+}
+
+/* ***************************************************************************/
+/*Attempts to write nbyte from the buffer pointed to by buf to the channel
+ * data buffers associated with the opened channel number channelNumber
+ *
+ * <b>Algorithm:</b>\n
+ *
+ * - Check data structures are properly initialized:
+ * - Channel descriptor validity
+ * - Channel control block validity
+ * - Buffer descriptor validity
+ * - If transfer data size is used, check validity of combination transfer
+ * size/requested bytes
+ * - Write loop\n
+ * Write occurs in the buffer acceded form buffer descriptor and continues
+ * to the "next" buffer which can be:\n
+ * -# the last BD of the ring so re-start from beginning\n
+ * -# the last BD of the BD array but no ring so finish\n
+ * -# (general case) the next BD in the BD array\n
+ * And copy continues until data fit in the current buffer or the nbyte
+ * parameter is reached.
+ * - Starting of the channel
+ *
+ * <b>Notes:</b>\n
+ * 1) Virtual DMA SDMA channels are unidirectionnal, an iapi_Write authorized
+ * on a channel means that we are expecting to send to the SDMA. The
+ * meaning of an interrupt received from the SDMA is therfore that the
+ * data has been delivered to the SDMA.
+ *
+ * @param *cd_p chanenl descriptor for the channel to write to
+ * @param *buf buffer with data to be written
+ * @param nbyte number of bytes to write to channel
+ *
+ * @return
+ * - number of bytes written
+ * - -iapi_errno if failure
+ */
+int
+iapi_Write (channelDescriptor * cd_p, void * buf, unsigned short nbyte)
+{
+ unsigned int writtenBytes = 0;
+ unsigned int toWrite;
+ int result = IAPI_SUCCESS;
+ unsigned int copyFinished;
+ unsigned int buffsize;
+ unsigned int index = 0;
+ bufferDescriptor * bd_p;
+ channelControlBlock * ccb_p;
+ unsigned char * local_buf;
+ unsigned char chNum;
+ unsigned char div;
+
+ iapi_errno = IAPI_ERR_NO_ERROR;
+
+ /*
+ * 1. Check data structures are properly initialized
+ */
+ /* Channel descriptor validity */
+ if (cd_p == NULL){
+ result = IAPI_ERR_CD_UNINITIALIZED;
+ iapi_errno = result;
+ return -result;
+ }
+
+ /* Channel control block validity */
+ if (cd_p->ccb_ptr == NULL){
+ result = IAPI_ERR_CCB_UNINITIALIZED;
+ iapi_errno = result;
+ return -result;
+ }
+
+ /* Control block & Descriptpor associated with the channel being worked on */
+ chNum = cd_p->channelNumber;
+ ccb_p = cd_p->ccb_ptr;
+
+ /* Try to aquire channel*/
+ if(iapi_GetChannel(chNum) != 0)
+ {
+ result = IAPI_ERR_CH_IN_USE | chNum;
+ iapi_errno = result;
+ return -result;
+ }
+
+ /* Buffer descriptor validity */
+ bd_p = (bufferDescriptor *)iapi_Phys2Virt(ccb_p->baseBDptr);
+ if (bd_p == NULL ){
+ result = IAPI_ERR_BD_UNINITIALIZED | IAPI_ERR_CH_AVAILABLE | chNum;
+ iapi_errno = result;
+ iapi_ReleaseChannel(chNum);
+ return -result;
+ }
+
+ /* Check initialization has been done for trusted channels */
+ if (cd_p->trust == TRUE) {
+ bd_p = (bufferDescriptor *)iapi_Phys2Virt(ccb_p->baseBDptr);
+ for(index=0 ; index < cd_p->bufferDescNumber ; index++){
+ if ((bd_p->bufferAddr == NULL) || (bd_p->mode.count == 0)){
+ result = IAPI_ERR_BD_UNINITIALIZED | IAPI_ERR_CH_AVAILABLE | chNum;
+ iapi_errno = result;
+ iapi_ReleaseChannel(chNum);
+ return -result;
+ }
+ bd_p++;
+ }
+ }
+
+
+ bd_p = (bufferDescriptor *)iapi_Phys2Virt(ccb_p->baseBDptr);
+ /*If transfer data size is used, check that the required write length is
+ * divisible by transfer data size expressed in bytes
+ */
+ if(cd_p->useDataSize)
+ {
+ /*Check for divisibility only if data size different then 8bit*/
+ if(cd_p->dataSize != TRANSFER_8BIT)
+ {
+ switch(cd_p->dataSize)
+ {
+ case TRANSFER_32BIT:
+ div = 4;
+ break;
+ case TRANSFER_16BIT:
+ div = 2;
+ break;
+ case TRANSFER_24BIT:
+ div = 3;
+ break;
+ /*we should not get to default*/
+ default:
+ result = IAPI_ERR_INVALID_PARAMETER | chNum;
+ iapi_errno = result;
+ iapi_ReleaseChannel(chNum);
+ return -result;
+ }
+ /*check the total number of bytes requested*/
+ if((nbyte % div) != 0)
+ {
+ result = IAPI_ERR_INVALID_PARAMETER | chNum;
+ iapi_errno = result;
+ iapi_ReleaseChannel(chNum);
+ return -result;
+ }
+ /*now check the length of every BD*/
+ for(index=0 ; index < cd_p->bufferDescNumber ; index++)
+ {
+ if((bd_p->mode.count % div) != 0)
+ {
+ result = IAPI_ERR_INVALID_PARAMETER | chNum;
+ iapi_errno = result;
+ iapi_ReleaseChannel(chNum);
+ return -result;
+ }
+ bd_p++;
+ }
+ }
+ }
+
+ /*
+ * 2. Write loop
+ */
+
+ local_buf = (unsigned char *)buf;
+ toWrite = nbyte;
+ copyFinished = FALSE;
+ bd_p = (bufferDescriptor *)iapi_Phys2Virt(ccb_p->baseBDptr);
+
+ while (!copyFinished){
+
+ /* variable buffsize contains the nb of bytes that the SDMA will transfer at each pass of the while loop*/
+
+ /* in NON trusted mode, buffsize is copied from Channel descriptor bufferSize (same size for all transfers) */
+ if (cd_p->trust == FALSE) {
+ buffsize = cd_p->bufferSize;
+ }
+ /* in TRUSTED mode, it's up to the user to specify the size of each buffer thru an IoCtl call */
+ /* This IoCtl has directly modified the bd_p->mode.count */
+ /* therefore, buffersize is copied from the bd_p->mode.count */
+ else {
+ buffsize = bd_p->mode.count;
+ }
+
+ /* in any mode (trusted or non trusted), the transfer size must be overridden by */
+ /* "toWrite" when there is less remaining bytes to transfer than the current buffer size */
+ if (toWrite < buffsize) {
+ buffsize = toWrite;
+ }
+
+
+ if (!(bd_p->mode.status & BD_DONE)){
+ /* More data to write than a single buffer can contain */
+ if (cd_p->trust == FALSE ){
+ iapi_memcpy(iapi_Phys2Virt(bd_p->bufferAddr), local_buf, buffsize);
+ local_buf += buffsize;
+ }
+
+ /* update the BD count that will be used by the SDMA to transfer the proper nb of bytes */
+ bd_p->mode.count = buffsize;
+
+ bd_p->mode.status |= BD_DONE;
+ writtenBytes += buffsize;
+ toWrite -= buffsize;
+ /* Prepares access to the "next" buffer */
+ /* - case 1 - finished successfully : writtenBytes = nbytes */
+ if (toWrite == 0) {
+ copyFinished = TRUE;
+ }
+ /* - case 2 - Last BD and WRAP bit set so re-start from beginning */
+ /*else if ((bd_p->mode.status & BD_WRAP)){
+ bd_p = (bufferDescriptor *)iapi_Phys2Virt(ccb_p->baseBDptr);
+ }*/
+ /* - case 3 - Last BD of the BD but nor ring*/
+ else if (((bufferDescriptor *)iapi_Phys2Virt(ccb_p->baseBDptr) +
+ (cd_p->bufferDescNumber - 1) * sizeof(bufferDescriptor)) == bd_p){
+ copyFinished = TRUE;
+ }
+ /* - case 4 - general : next BD in the BD array */
+ else {
+ bd_p++;
+ }
+
+ } else {
+ /* finished here : buffer not already done */
+ copyFinished = TRUE;
+ }
+ }
+
+ ccb_p->currentBDptr = ccb_p->baseBDptr;
+
+ /*
+ * 3. Starting of the channel
+ */
+ iapi_lowStartChannel(chNum);
+ ccb_p->status.execute = TRUE;
+
+ if( cd_p->callbackSynch == DEFAULT_POLL)
+ {
+ iapi_SynchChannel(chNum);
+ /*
+ * Check the 'RROR' bit on all buffer descriptors, set error number
+ * and return IAPI_FAILURE if set.
+ */
+ bd_p = (bufferDescriptor *)iapi_Phys2Virt(ccb_p->baseBDptr);
+ for (index=0 ; index < cd_p->bufferDescNumber ; index++)
+ {
+ if(bd_p->mode.status & BD_RROR)
+ {
+ result = IAPI_ERR_RROR_BIT_WRITE | chNum;
+ iapi_errno = result;
+ iapi_ReleaseChannel(chNum);
+ return -result;
+ }
+ bd_p++;
+ }
+ iapi_ReleaseChannel(chNum);
+ }
+
+ /*
+ *If synchronization type is callback, the user of I.API must
+ *release the channel
+ */
+ return writtenBytes;
+}
+
+
+
+
+/* ***************************************************************************/
+/* This function is used to receive data from the SDMA.
+ *
+ * <b>Algorithm:</b>\n
+ *
+ * The data control structure would be copied to IPCv1 complied Buffer
+ * Descriptor Array. This array shall be allocated from non cacheable memory.
+ * It would then provide this buffer descriptor array as an input to SDMA using
+ * channel control block and then configure the Host Enable (HE) or
+ * DSP enable (DE) bit of SDMA for the channel used for this transfer depending
+ * on the source.
+ *
+ * <b>Notes:</b>\n
+ * Virtual DMA channels are unidirectional, an iapi_Write_ipcv2 authorized
+ * on a channel means that source processor is expecting to send to the destination
+ * processor. The meaning of an interrupt received from the SDMA notifies that the
+ * data has been delivered to the destination processor.
+ *
+ * @param *cd_p chanenl descriptor for the channel to receive from
+ * @param *data_control_struct_ipcv2
+
+ * Data Control structure:
+ * -------------------------
+ * | Data Node Descriptor 1|
+ * -------------------------
+ * | Data Node Descriptor 2|
+ * -------------------------
+ * | : |
+ * | : |
+ * -------------------------
+ * |Data Node Descriptor n |
+ * -------------------------
+ *
+ * Data Node Descriptor (Buffer Descriptor):
+ *------------------------------------------------------------------------------
+ *| 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 … 0|
+ *------------------------------------------------------------------------------
+ *| L E D R R R R R |<---- Reserved ----> |<- Length-> |
+ *------------------------------------------------------------------------------
+ *| <---------------------------- Data Ptr ----------------------------------->|
+ *------------------------------------------------------------------------------
+ *
+ * L bit (LAST): If set, means that this buffer of data is the last buffer of the frame
+ * E bit (END): If set, we reached the end of the buffers passed to the function
+ * D bit (DONE): Only valid on the read callback. When set, means that the buffer has been
+ * filled by the SDMA.
+ * Length: Length of data pointed by this node in bytes
+ * Data Ptr: Pointer to the data pointed to by this node.
+ * The Function Shall not be called for the same channel unless the Read callback has been
+ * received for channel for which it has been called already.
+ *
+ * @return
+ * - IAPI_SUCCESS on success, IAPI_ERROR otherwise
+ *
+ *- -iapi_errno if failure
+ */
+
+int iapi_Read_ipcv2( channelDescriptor * cd_p, void * data_control_struct_ipcv2)
+{
+ channelControlBlock * ccb_p;
+
+
+/* The Parameters passed are considered to be validated by the upper layers*/
+
+ bufferDescriptor_ipcv1_v2 *bd_ipcv2_p;
+ dataNodeDescriptor *dnd_p = (dataNodeDescriptor*)data_control_struct_ipcv2;
+
+ ccb_p = cd_p->ccb_ptr;
+ iapi_errno = IAPI_ERR_NO_ERROR;
+
+ if(ccb_p->baseBDptr == NULL)
+{
+ iapi_errno = IAPI_ERR_BD_UNINITIALIZED;
+ return -(IAPI_ERR_BD_UNINITIALIZED);
+}
+
+ ccb_p->currentBDptr = ccb_p->baseBDptr;
+
+ /* Copy the data Node descriptor information to new BDs */
+ bd_ipcv2_p = (bufferDescriptor_ipcv1_v2*)iapi_Phys2Virt(ccb_p->baseBDptr);
+
+ while(1)
+ {
+ bd_ipcv2_p->bufferAddr = dnd_p->bufferAddr;
+ bd_ipcv2_p->mode.count = dnd_p->mode.count;
+#ifdef MCU
+ bd_ipcv2_p->mode.endianness = 1;
+#endif
+#ifdef DSP
+ bd_ipcv2_p->mode.endianness = 0;
+#endif
+
+ bd_ipcv2_p->mode.status = dnd_2_bd_status[dnd_p->mode.status & GET_LED_MASK];
+
+ if((dnd_p->mode.status & DND_END_OF_XFER) != 0)
+ {
+ /* Break the loop at End of Transfer */
+ break;
+
+ }
+ bd_ipcv2_p++;
+ dnd_p++;
+
+ }
+ /*
+ * Store the buffer address
+ */
+ dnd_read_control_struct[cd_p->channelNumber] = (dataNodeDescriptor*)data_control_struct_ipcv2;
+ /*
+ * Register the Call Back
+ */
+
+ iapi_AttachCallbackISR(cd_p, iapi_read_ipcv2_callback);
+
+ /*
+ * Starting of the channel
+ */
+ iapi_lowStartChannel(cd_p->channelNumber);
+ ccb_p->status.execute = TRUE;
+
+ return IAPI_SUCCESS;
+
+}
+
+
+/* ***************************************************************************/
+/*
+ * The function is used send a group of buffers to SDMA.
+ * <b>Algorithm:</b>\n
+ *
+ * The data control structure would be copied to IPCv1 complied Buffer
+ * Descriptor Array. This array shall be allocated from non cacheable memory.
+ * It would then provide this buffer descriptor array as an input to SDMA using
+ * channel control block and then configure the Host Enable (HE) or
+ * DSP enable (DE) bit of SDMA for the channel used for this transfer depending
+ * on the source.
+ * The Function Shall not be called for the same channel unless the Read callback has been
+ * received for channel for which it has been called already.
+ *
+ * <b>Notes:</b>\n
+ * Virtual DMA channels are unidirectional, an iapi_Write_ipcv2 authorized
+ * on a channel means that source processor is expecting to send to the destination
+ * processor. The meaning of an interrupt received from the SDMA notifies that the
+ * data has been delivered to the destination processor.
+ *
+ * @param *cd_p chanenl descriptor for the channel to write to
+ * @param *data_control_struct_ipcv2
+
+ * Data Control structure:
+ * -------------------------
+ * | Data Node Descriptor 1|
+ * -------------------------
+ * | Data Node Descriptor 2|
+ * -------------------------
+ * | : |
+ * | : |
+ * -------------------------
+ * |Data Node Descriptor n |
+ * -------------------------
+ *
+ * Data Node Descriptor (Buffer Descriptor):
+ *------------------------------------------------------------------------------
+ *| 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 … 0|
+ *------------------------------------------------------------------------------
+ *| L E D R R R R R |<---- Reserved ----> |<- Length-> |
+ *------------------------------------------------------------------------------
+ *| <---------------------------- Data Ptr ----------------------------------->|
+ *------------------------------------------------------------------------------
+ *
+ * L bit (LAST): If set, means that this buffer of data is the last buffer of the frame
+ * E bit (END): If set, we reached the end of the buffers passed to the function
+ * D bit (DONE): Only valid on the read callback. When set, means that the buffer has been
+ * filled by the SDMA.
+ * Length: Length of data pointed by this node in bytes
+ * Data Ptr: Pointer to the data pointed to by this node.
+ *
+ *
+ * @return
+ * - iapi sucess on success.
+ * - -iapi_errno if failure
+ */
+
+int iapi_Write_ipcv2( channelDescriptor * cd_p, void * data_control_struct_ipcv2)
+{
+
+ channelControlBlock * ccb_p;
+
+/* The Parameters passed are considered to be validated by the upper layers*/
+
+ bufferDescriptor_ipcv1_v2 *bd_ipcv2_p;
+ dataNodeDescriptor *dnd_p = (dataNodeDescriptor*)data_control_struct_ipcv2;
+ ccb_p = cd_p->ccb_ptr;
+ iapi_errno = IAPI_ERR_NO_ERROR;
+
+ if(ccb_p->baseBDptr == NULL)
+{
+ iapi_errno = IAPI_ERR_BD_UNINITIALIZED;
+ return -(IAPI_ERR_BD_UNINITIALIZED);
+}
+
+
+ ccb_p->currentBDptr = ccb_p->baseBDptr;
+
+ bd_ipcv2_p = (bufferDescriptor_ipcv1_v2*)iapi_Phys2Virt(ccb_p->currentBDptr);
+ /* Copy the data Node descriptor information to new BDs */
+ while(1)
+ {
+ bd_ipcv2_p->bufferAddr = dnd_p->bufferAddr;
+ bd_ipcv2_p->mode.count = dnd_p->mode.count;
+
+#ifdef MCU
+ bd_ipcv2_p->mode.endianness = 1;
+#endif
+#ifdef DSP
+ bd_ipcv2_p->mode.endianness = 0;
+#endif
+
+ bd_ipcv2_p->mode.status = dnd_2_bd_status[dnd_p->mode.status & GET_LED_MASK];
+
+ if((dnd_p->mode.status & DND_END_OF_XFER) != 0)
+ {
+ /* Break the loop at End of Transfer */
+ break;
+ }
+ bd_ipcv2_p++;
+ dnd_p++;
+
+ }
+
+ /*
+ * Starting of the channel
+ */
+ iapi_lowStartChannel(cd_p->channelNumber);
+ ccb_p->status.execute = TRUE;
+
+ return IAPI_SUCCESS;
+
+}
+
+/* ***************************************************************************/
+/** Call back ISR for the IPCv2 Receive.
+ *
+ * <b>Algorithm:</b>\n
+ * - This would copy back the informationfrom IPCv1 BD to IPCv2 BD on
+ * the receiving processor
+ *
+ * @return
+ * - void
+ */
+
+void iapi_read_ipcv2_callback(struct iapi_channelDescriptor* cd_p, void* data)
+{
+ dataNodeDescriptor *dnd_p = dnd_read_control_struct[cd_p->channelNumber];//cd_p->ccb_ptr->channelDNDBuffer;
+ bufferDescriptor_ipcv1_v2 *bd_ipcv2_p = (bufferDescriptor_ipcv1_v2*)iapi_Phys2Virt(cd_p->ccb_ptr->baseBDptr);
+ int index = MAX_BD_NUM - 1;
+
+
+ do
+ {
+ dnd_p->mode.status = 0;
+ dnd_p->mode.count = bd_ipcv2_p->mode.count;
+
+ dnd_p->mode.status |= bd_ipcv2_p->mode.status & BD_DONE ? 0x00 : DND_DONE ;
+ dnd_p->mode.status |= bd_ipcv2_p->mode.status & BD_IPCV2_END_OF_FRAME ? DND_END_OF_FRAME : 0x00;
+ dnd_p->mode.status |= bd_ipcv2_p->mode.status & BD_LAST ? DND_END_OF_XFER : 0x00;
+ cd_p->ccb_ptr->currentBDptr = (bufferDescriptor*)iapi_Virt2Phys(bd_ipcv2_p);
+
+ if((bd_ipcv2_p->mode.status & BD_LAST) != 0 ||
+ (bd_ipcv2_p->mode.status & BD_CONT) == 0
+ )
+ break;
+ dnd_p++;
+ bd_ipcv2_p++;
+
+ }while(index--);
+
+ /*Call back the Original ISR */
+ cd_p->callbackISR_ptr(cd_p, data);
+}
+
+/* ***************************************************************************/
+/**Terminates a channel.
+ *
+ * <b>Algorithm:</b>\n
+ * - Check input parameters ans data structures
+ * - Check that all buffes have been processed (test all 'D' bits)
+ * - Stop the channel execution
+ * - Free alocated memory structures
+ * - Re-instantiate default interrupt handling
+ *
+ * @param *cd_p chanenl descriptor for the channel to close
+ *
+ * @return
+ * - IAPI_SUCCESS : OK
+ * - -iapi_errno : close failed
+ */
+int
+iapi_Close (channelDescriptor * cd_p)
+{
+ int index = 0;
+ int result = IAPI_SUCCESS;
+ unsigned char chNum;
+ bufferDescriptor * bd_p;
+ channelControlBlock * ccb_p;
+
+ /*
+ * 1. Check input parameters ans data structures
+ */
+ if (cd_p != NULL){
+ if (cd_p->ccb_ptr != NULL) {
+ chNum = cd_p->channelNumber;
+ ccb_p = cd_p->ccb_ptr;
+ } else {
+ result = IAPI_ERR_NO_CCB_DEFINED | IAPI_ERR_CH_AVAILABLE;
+ iapi_errno = result;
+ return -result;
+ }
+ } else {
+ result = IAPI_ERR_CD_UNINITIALIZED | IAPI_ERR_CH_AVAILABLE;
+ iapi_errno = result;
+ return -result;
+ }
+ /* Try to aquire channel*/
+ if(iapi_GetChannel(chNum) != 0)
+ {
+ result = IAPI_ERR_CH_IN_USE | chNum;
+ iapi_errno = result;
+ return -result;
+ }
+
+ /*
+ * 2. Check that all buffes have been processed (test all 'D' bits),
+ * only if the forceClose bit in channel descriptor is set to FALSE
+ */
+ bd_p = (bufferDescriptor *)iapi_Phys2Virt(ccb_p->baseBDptr);
+ if (bd_p == NULL){
+ result = IAPI_ERR_BD_UNINITIALIZED | IAPI_ERR_CH_AVAILABLE | chNum;
+ iapi_errno = result;
+ return -result;
+ }
+ if(cd_p->forceClose == FALSE)
+ {
+ for (index=cd_p->bufferDescNumber ; index>0 ; index--){
+ if (bd_p->mode.status & BD_DONE){
+ result = IAPI_ERR_CLOSE | IAPI_ERR_CH_AVAILABLE | chNum;
+ iapi_errno = result;
+ iapi_ReleaseChannel(chNum);
+ return -result;
+ }
+ bd_p++;
+ }
+ }
+ /*if the closing is forced,mark channel unused,set BD ownership to processor*/
+ else
+ {
+ ccb_p->status.execute = FALSE;
+ for (index=cd_p->bufferDescNumber ; index>0 ; index--)
+ {
+ bd_p->mode.status &= ~BD_DONE;
+ bd_p++;
+ }
+ }
+
+ /*
+ * 3. Stop the channel execution
+ */
+ iapi_lowStopChannel(chNum);
+
+ /*
+ * 4. Free alocated memory structures
+ */
+ if (cd_p->trust == FALSE ){
+ bd_p = (bufferDescriptor *)iapi_Phys2Virt(ccb_p->baseBDptr);
+ for (index=cd_p->bufferDescNumber ; index>0 ; index--){
+ FREE (iapi_Phys2Virt(bd_p->bufferAddr));
+ bd_p++;
+ }
+ }
+
+ /*
+ * 5. Re-instantiate default interrupt handling
+ */
+ iapi_DetachCallbackISR (cd_p);
+ FREE ((bufferDescriptor *)iapi_Phys2Virt(ccb_p->baseBDptr));
+ FREE (cd_p);
+ ccb_p->baseBDptr = NULL;
+ ccb_p->currentBDptr = NULL;
+ ccb_p->channelDescriptor = NULL;
+ ccb_p->status.openedInit = FALSE;
+
+ iapi_ReleaseChannel(chNum);
+
+ return IAPI_SUCCESS;
+}
+
+/* ***************************************************************************/
+/**The request argument selects the control function to be performed.
+ *
+ * <b>Algorithm:</b>\n
+ *
+ * - Check data structures are properly initialized:
+ * - Channel descriptor validity
+ * - Channel control block validity
+ * - The ctlRequest parameter contains in the lower 16 bits the control code of
+ * the change to be performed, and in the upper 16 bits, the BD to be
+ * modified if the change affects a BD od the channel.
+ * - Selection of the parameter to change and appropriate sanity checks:
+ * - Channel Descriptor: changes the pointer to the channel descriptor
+ * structure, the pointer to the new channel descriptor is given in the third
+ * argument call
+ * - Buffer Descriptor Number: changes the number of buffer descriptor for the
+ * channel
+ * - Buffer size: changes the size of the data buffers pointed to by the
+ * buffer descriptor; note that all buffer descriptors are assumed to have the
+ * same size for a given buffer descripotr chain
+ * - Blocking policy: changes the blocking policy for the read and write calls
+ * - Ownership: changes direction: turnaround
+ * - Synchronization method: changes the callback type, default or user. The*
+ * callback function table is set accordingly
+ * - Trust property: trust can only be changed through ChangeChannelDesc first
+ * request, this guarantees the close/open sequence for the channel
+ * - Callback Interrupt service routine pointer: changes the callback function
+ * pointer, when this method is used, to replace it with a new one
+ * - Channel control block pointer: not available
+ * - Priority: changes the channel priority directly in SDMA register
+ * - Watermark level: changes the value of the peripheral watermark level that
+ * passed to the script. The new value is passed in the third parameter call.
+ * - Wrap bit: changes to set to 1 the Wrap bit of the last buffer descriptor
+ *
+ * @param *cd_p channel descriptor for the channel to modify
+ * @param ctlRequest request control code and, if tha case, number of BD to be
+ * changed
+ * @param param parameter for the modification
+ *
+ * @return
+ * - IAPI_SUCCESS : OK
+ * - -iapi_errno : operation failed
+ */
+int
+iapi_IoCtl (channelDescriptor * cd_p, unsigned long ctlRequest,
+ unsigned long param)
+{
+ int retvalue;
+ int result = IAPI_SUCCESS;
+ unsigned char chNum;
+ unsigned long clean_ctlRequest; /* lower 16 bits of the ctlRequest*/
+ unsigned long bd_num; /* upper 16 bits of the ctlRequest*/
+
+ /*
+ * 1. Check data structures are properly initialized
+ */
+ /* Channel descriptor validity */
+ if (cd_p == NULL){
+ result = IAPI_ERR_CD_UNINITIALIZED;
+ iapi_errno = result;
+ return -result;
+ }
+
+ /* Channel control block validity */
+ if (cd_p->ccb_ptr == NULL){
+ result = IAPI_ERR_CCB_UNINITIALIZED;
+ iapi_errno = result;
+ return -result;
+ }
+
+ /* Control block & Descriptor associated with the channel being worked on */
+ chNum = cd_p->channelNumber;
+
+ /* Remove, if exists, BD number specified in upper bits of ctlRequest*/
+ clean_ctlRequest = ctlRequest & (~BD_NUM_MASK);
+
+ /* Extract, if exists, BD number specified in upper bits of ctlRequest*/
+ bd_num = (ctlRequest & BD_NUM_MASK) >> BD_NUM_OFFSET;
+
+ /* Check that the bd_num is valid*/
+ if(bd_num > cd_p->bufferDescNumber)
+ {
+ result = IAPI_ERR_INVALID_PARAMETER | chNum;
+ iapi_errno = result;
+ return -result;
+ }
+
+ /*All checks OK, try to aquire channel*/
+ if(iapi_GetChannel(chNum) != 0)
+ {
+ result = IAPI_ERR_CH_IN_USE | chNum;
+ iapi_errno = result;
+ return -result;
+ }
+
+ /*
+ * 2. Selection of the parameter to change and appropriate sanity checks
+ */
+ switch (clean_ctlRequest){
+
+ /*
+ * Channel Descriptor
+ * --- Changes the pointer to the channel descriptor structure: the pointer
+ * to the new channel descriptor is given in the third argument call.
+ */
+ case IAPI_CHANGE_CHANDESC:
+ if ((void *) param == NULL) {
+ result = IAPI_ERR_INVALID_PARAMETER;
+ iapi_errno = result;
+ iapi_ReleaseChannel(chNum);
+ return -result;
+ } else {
+ channelDescriptor * chParam = (channelDescriptor *)param;
+ if (chParam->channelNumber != chNum){
+ /* Release ch so it can be aquired by the Close fn*/
+ iapi_ReleaseChannel(chNum);
+ result = iapi_Close(cd_p);
+ if (result == IAPI_SUCCESS){
+ FREE((void*)cd_p);
+ iapi_AllocChannelDesc (&cd_p, chParam->channelNumber);
+ iapi_memcpy((void*)cd_p, (void*)chParam, sizeof (channelDescriptor));
+ /* Channel is released allready, so Open can get the channel*/
+ result = iapi_Open(cd_p, chParam->channelNumber);
+ if(result != IAPI_SUCCESS)
+ {
+ return result; /* error code already set in iapi_Open*/
+ }
+ } else {
+ return result; /* error code already set in iapi_Close*/
+ }
+ } else {
+ result = IAPI_ERR_CD_CHANGE | IAPI_ERR_CH_AVAILABLE |
+ cd_p->channelNumber;
+ iapi_ReleaseChannel(chNum);
+ iapi_errno = result;
+ return -result;
+ }
+ return IAPI_SUCCESS;
+ }
+
+ /*
+ * Buffer Descriptor Number
+ * --- Changes the number of buffer descriptor for the channel.
+ */
+ case IAPI_CHANGE_BDNUM:
+ result = iapi_ChangeChannelDesc(cd_p, IAPI_BUFFERDESCNUMBER, param);
+ iapi_ReleaseChannel(chNum);
+ return result;
+
+ /*
+ * Buffer size
+ * --- Changes the size of the data buffers pointed to by the buffer
+ * descriptor; note that all buffer descriptors are assumed to have the
+ * same size for a given buffer descripotr chain.
+ */
+ case IAPI_CHANGE_BUFFSIZE:
+ result = iapi_ChangeChannelDesc(cd_p, IAPI_BUFFERSIZE, param);
+ iapi_ReleaseChannel(chNum);
+ return result;
+
+ /*
+ * Blocking policy
+ * --- Changes the blocking policy for the read and write calls.
+ */
+ case IAPI_CHANGE_CHANBLOCK:
+ result = iapi_ChangeChannelDesc(cd_p, IAPI_BLOCKING, param);
+ iapi_ReleaseChannel(chNum);
+ return result;
+
+ /*
+ * Ownership
+ * --- Changes direction: turnaround
+ */
+ case IAPI_CHANGE_OWNERSHIP:
+ result = iapi_ChangeChannelDesc(cd_p, IAPI_OWNERSHIP, param);
+ iapi_ReleaseChannel(chNum);
+ return result;
+
+ /*
+ * Synchronization method
+ * --- Changes the callback type, default or user. The callback function
+ * table is set accordingly.
+ */
+ case IAPI_CHANGE_SYNCH:
+ result = iapi_ChangeChannelDesc(cd_p, IAPI_CALLBACKSYNCH, param);
+ iapi_ReleaseChannel(chNum);
+ return result;
+
+ /*
+ * Trust property
+ * --- trust can only be changed through ChangeChannelDesc first request,
+ * this guarantees the close/open sequence for the channel.
+ */
+ case IAPI_CHANGE_TRUST:
+ result = iapi_ChangeChannelDesc(cd_p, IAPI_TRUST, param);
+ iapi_ReleaseChannel(chNum);
+ return result;
+
+ /*
+ * Callback Interrupt service routine pointer
+ * --- Cahnges the callback function pointer, when this method is used, to
+ * replace it with a new one.
+ */
+ case IAPI_CHANGE_CALLBACKFUNC:
+ result = iapi_ChangeChannelDesc(cd_p, IAPI_CALLBACKISR_PTR, param);
+ iapi_ReleaseChannel(chNum);
+ return result;
+
+ /*
+ * Channel control block pointer
+ * --- NA
+ */
+ case IAPI_CHANGE_CHANCCB:
+ result = iapi_ChangeChannelDesc(cd_p, IAPI_CCB_PTR, param);
+ iapi_ReleaseChannel(chNum);
+ return result;
+
+#ifdef MCU
+ /*
+ * Priority
+ * --- Changes the channel priority directly in SDMA register
+ */
+ case IAPI_CHANGE_PRIORITY:
+ {
+ volatile unsigned long * ChannelPriorities = &SDMA_CHNPRI_0;
+ if(param < MAX_CH_PRIORITY)
+ {
+ ChannelPriorities[ cd_p->channelNumber ] = param;
+ }
+ else
+ {
+ iapi_ReleaseChannel(chNum);
+ return IAPI_FAILURE;
+ }
+ }
+ break;
+#endif /* MCU */
+
+ /*
+ * Wrap
+ * --- Set to 1 the wrap bit of the last buffer descriptor of the array.
+ * it provides the possibility to have a circular buffer structure.
+ */
+ case IAPI_CHANGE_BDWRAP:
+ {
+ result = iapi_ChangeChannelDesc(cd_p,IAPI_BDWRAP , param);
+ iapi_ReleaseChannel(chNum);
+ return result;
+ }
+
+ /*
+ * Watermark
+ * --- Changes the value of the peripheral watermark level that triggers
+ * a DMA request. It impacts context of the channel, therefore channel 0
+ * must be started to update the context with this new value.
+ */
+ case IAPI_CHANGE_WATERMARK:
+ {
+ result = iapi_ChangeChannelDesc(cd_p,IAPI_WML , param);
+ iapi_ReleaseChannel(chNum);
+ return result;
+ }
+ /*
+ * INTR
+ * --- Set the INTR bit on specified BD or on all BD's if SET_BIT_ALL
+ * is passed as parameter.
+ */
+ case IAPI_CHANGE_SET_BDINTR:
+ {
+ bufferDescriptor * bde_p;
+ int j = 0;
+
+ retvalue = IAPI_SUCCESS;
+ if(param == SET_BIT_ALL)
+ {
+ bde_p = (bufferDescriptor *)iapi_Phys2Virt(cd_p->ccb_ptr->baseBDptr);
+ for(j = 0; j < cd_p->bufferDescNumber; j++)
+ {
+ bde_p->mode.status |= BD_INTR;
+ bde_p++;
+ }
+ }
+ else if(param < cd_p->bufferDescNumber)
+ {
+ bde_p = (bufferDescriptor *)iapi_Phys2Virt(cd_p->ccb_ptr->baseBDptr) +
+ param;
+ bde_p->mode.status |= BD_INTR;
+ }
+ else
+ {
+ retvalue = IAPI_FAILURE;
+ }
+ iapi_ReleaseChannel(chNum);
+ return retvalue;
+ }
+ /*
+ * INTR
+ * --- Unset the INTR bit on specified BD or on all BD's if SET_BIT_ALL
+ * is passed as parameter.
+ */
+ case IAPI_CHANGE_UNSET_BDINTR:
+ {
+ bufferDescriptor * bde_p;
+
+ int j = 0;
+
+ retvalue = IAPI_SUCCESS;
+ if(param == SET_BIT_ALL)
+ {
+ bde_p = (bufferDescriptor *)iapi_Phys2Virt(cd_p->ccb_ptr->baseBDptr);
+ for(j = 0; j < cd_p->bufferDescNumber; j++)
+ {
+ bde_p->mode.status &= ~BD_INTR;
+ bde_p++;
+ }
+ }
+ else if(param < cd_p->bufferDescNumber)
+ {
+ bde_p = (bufferDescriptor *)iapi_Phys2Virt(cd_p->ccb_ptr->baseBDptr) +
+ param;
+ bde_p->mode.status &= ~BD_INTR;
+ }
+ else
+ {
+ retvalue = IAPI_FAILURE;
+ }
+ iapi_ReleaseChannel(chNum);
+ return retvalue;
+ }
+/*
+ * EventMask1
+ * --- Changes the value of the eventMask1
+ */
+ case IAPI_CHANGE_EVTMASK1:
+ {
+ cd_p->eventMask1 = param;
+ }
+ break;
+ /*
+ * EventMask2
+ * --- Changes the value of the eventMask2
+ */
+ case IAPI_CHANGE_EVTMASK2:
+ {
+ cd_p->eventMask2 = param;
+ }
+ break;
+ /*
+ * Peripheral Address
+ * --- Changes the value of the peripheralAddr
+ */
+ case IAPI_CHANGE_PERIPHADDR:
+ {
+ cd_p->peripheralAddr = param;
+ }
+ break;
+ /*
+ * Cont
+ * --- Set the CONT bit on specified BD on all BD's if SET_BIT_ALL
+ * is passed as parameter.
+ */
+ case IAPI_CHANGE_SET_BDCONT:
+ {
+ bufferDescriptor * bde_p;
+ int j = 0;
+
+ retvalue = IAPI_SUCCESS;
+ if(param == SET_BIT_ALL)
+ {
+ bde_p = (bufferDescriptor *)iapi_Phys2Virt(cd_p->ccb_ptr->baseBDptr);
+ for(j = 0; j < cd_p->bufferDescNumber; j++)
+ {
+ bde_p->mode.status |= BD_CONT;
+ bde_p++;
+ }
+ }
+ else if(param < cd_p->bufferDescNumber)
+ {
+ bde_p = (bufferDescriptor *)iapi_Phys2Virt(cd_p->ccb_ptr->baseBDptr) +
+ param;
+ bde_p->mode.status |= BD_CONT;
+ }
+ else
+ {
+ retvalue = IAPI_FAILURE;
+ }
+ iapi_ReleaseChannel(chNum);
+ return retvalue;
+ }
+ /*
+ * Cont
+ * --- Unset the CONT bit on specified BD or on all BD's if SET_BIT_ALL
+ * is passed as parameter.
+ */
+ case IAPI_CHANGE_UNSET_BDCONT:
+ {
+ bufferDescriptor * bde_p;
+
+ int j = 0;
+
+ retvalue = IAPI_SUCCESS;
+ if(param == SET_BIT_ALL)
+ {
+ bde_p = (bufferDescriptor *)iapi_Phys2Virt(cd_p->ccb_ptr->baseBDptr);
+ for(j = 0; j < cd_p->bufferDescNumber; j++)
+ {
+ bde_p->mode.status &= ~BD_CONT;
+ bde_p++;
+ }
+ }
+ else if(param < cd_p->bufferDescNumber)
+ {
+ bde_p = (bufferDescriptor *)iapi_Phys2Virt(cd_p->ccb_ptr->baseBDptr) +
+ param;
+ bde_p->mode.status &= ~BD_CONT;
+ }
+ else
+ {
+ retvalue = IAPI_FAILURE;
+ }
+ iapi_ReleaseChannel(chNum);
+ return retvalue;
+ }
+
+ /*
+ * EXTD
+ * --- Set the EXTD bit on specified BD or on all BD's if SET_BIT_ALL
+ * is passed as parameter.
+ */
+ case IAPI_CHANGE_SET_BDEXTD:
+ {
+ bufferDescriptor * bde_p;
+ int j = 0;
+
+ retvalue = IAPI_SUCCESS;
+ if(param == SET_BIT_ALL)
+ {
+ bde_p = (bufferDescriptor *)iapi_Phys2Virt(cd_p->ccb_ptr->baseBDptr);
+ for(j = 0; j < cd_p->bufferDescNumber; j++)
+ {
+ bde_p->mode.status |= BD_EXTD;
+ bde_p++;
+ }
+ }
+ else if(param < cd_p->bufferDescNumber)
+ {
+ bde_p = (bufferDescriptor *)iapi_Phys2Virt(cd_p->ccb_ptr->baseBDptr) +
+ param;
+ bde_p->mode.status |= BD_EXTD;
+ }
+ else
+ {
+ retvalue = IAPI_FAILURE;
+ }
+ iapi_ReleaseChannel(chNum);
+ return retvalue;
+ }
+ /*
+ * EXTD
+ * --- Unset the EXTD bit on specified BD or on all BD's if SET_BIT_ALL
+ * is passed as parameter.
+ */
+ case IAPI_CHANGE_UNSET_BDEXTD:
+ {
+ bufferDescriptor * bde_p;
+
+ int j = 0;
+
+ retvalue = IAPI_SUCCESS;
+ if(param == SET_BIT_ALL)
+ {
+ bde_p = (bufferDescriptor *)iapi_Phys2Virt(cd_p->ccb_ptr->baseBDptr);
+ for(j = 0; j < cd_p->bufferDescNumber; j++)
+ {
+ bde_p->mode.status &= ~BD_EXTD;
+ bde_p++;
+ }
+ }
+ else if(param < cd_p->bufferDescNumber)
+ {
+ bde_p = (bufferDescriptor *)iapi_Phys2Virt(cd_p->ccb_ptr->baseBDptr) +
+ param;
+ bde_p->mode.status &= ~BD_EXTD;
+ }
+ else
+ {
+ retvalue = IAPI_FAILURE;
+ }
+ iapi_ReleaseChannel(chNum);
+ return retvalue;
+ }
+
+ /*
+ * TRANSFER SIZE to be used for this channel
+ * --- Set the transfer size used indicator and code for transfer size in
+ * the CD
+ */
+case IAPI_CHANGE_SET_TRANSFER_CD:
+ {
+ bufferDescriptor * bde_p;
+ int j = 0;
+ retvalue = IAPI_SUCCESS;
+ if((param == TRANSFER_8BIT) || (param == TRANSFER_16BIT) ||
+ (param == TRANSFER_24BIT) || (param == TRANSFER_32BIT))
+ {
+ cd_p->useDataSize = TRUE;
+ cd_p->dataSize = param;
+ bde_p = (bufferDescriptor *)iapi_Phys2Virt(cd_p->ccb_ptr->baseBDptr);
+ for(j = 0; j < cd_p->bufferDescNumber; j++)
+ {
+ bde_p->mode.command = param;
+ bde_p++;
+ }
+ }
+ else
+ {
+ retvalue = IAPI_FAILURE;
+ }
+ iapi_ReleaseChannel(chNum);
+ return retvalue;
+ }
+
+
+ /*
+ * USER_ARG
+ * --- Set the user selectable pointer to be received by the callback
+ * function, if IRQ synch is used
+ */
+ case IAPI_CHANGE_USER_ARG:
+ {
+ userArgTable[cd_p->channelNumber]= (void*)param;
+ iapi_ReleaseChannel(chNum);
+ return IAPI_SUCCESS;
+ }
+ /*
+ * FORCE_CLOSE
+ * --- Set the forceClose bit in channelDescriptor to value passed in param.
+ * If this bit is TRUE, the channel in closed even if some BD are still
+ * owned by the SDMA.
+ */
+ case IAPI_CHANGE_FORCE_CLOSE:
+ {
+ retvalue = IAPI_SUCCESS;
+ if((param == TRUE) || (param == FALSE))
+ {
+ cd_p->forceClose = param;
+ }
+ else
+ {
+ iapi_errno = IAPI_ERR_INVALID_PARAMETER | cd_p->channelNumber;
+ retvalue = -iapi_errno;
+ }
+ iapi_ReleaseChannel(chNum);
+ return retvalue;
+ }
+ /*
+ * TRANSFER type
+ * --- Set the last 2 bits in the command field of the BD to specify the
+ * transfer type 8, 16, 24, or 32 bits on all BD's, allready set in the CD
+ */
+ case IAPI_CHANGE_SET_TRANSFER:
+ {
+ bufferDescriptor * bde_p;
+ int j = 0;
+
+ retvalue = IAPI_SUCCESS;
+ if((param == TRANSFER_8BIT)||(param == TRANSFER_16BIT)||
+ (param == TRANSFER_24BIT)||(param == TRANSFER_32BIT))
+ {
+ bde_p = cd_p->ccb_ptr->baseBDptr;
+ for(j = 0; j < cd_p->bufferDescNumber; j++)
+ {
+ bde_p->mode.command = param;
+ bde_p++;
+ }
+ }
+ else
+ {
+ retvalue = IAPI_FAILURE;
+ }
+ iapi_ReleaseChannel(chNum);
+ return retvalue;
+ }
+ /*
+ * BUFFER address
+ * --- Change buffer address in BD specified in the upper 16 bits of the
+ * ctlRequest.
+ */
+ case IAPI_CHANGE_SET_BUFFERADDR:
+ {
+ bufferDescriptor * bde_p;
+ retvalue = IAPI_SUCCESS;
+
+ /* Get pointer to the BD structure to change*/
+ bde_p = (bufferDescriptor *)iapi_Phys2Virt(cd_p->ccb_ptr->baseBDptr);
+ bde_p+= bd_num;
+
+ /* DO NOT translate address to physical */
+ bde_p->bufferAddr = (void*)param;
+
+ iapi_ReleaseChannel(chNum);
+ return retvalue;
+ }
+ /*
+ * BUFFER address
+ * --- Get the buffer address from the BD specified in the upper 16 bits of the
+ * ctlRequest.
+ */
+ case IAPI_CHANGE_GET_BUFFERADDR:
+ {
+ bufferDescriptor * bde_p;
+ retvalue = IAPI_SUCCESS;
+
+ /* Get pointer to the BD structure to change*/
+ bde_p = (bufferDescriptor *)iapi_Phys2Virt(cd_p->ccb_ptr->baseBDptr);
+ bde_p+= bd_num;
+ /* Translate to virtual*/
+ *((unsigned long*)param) = (unsigned long)bde_p->bufferAddr;
+
+ iapi_ReleaseChannel(chNum);
+ return retvalue;
+ }
+ /*
+ * EXTENDED BUFFER address
+ * --- Change extended buffer address in BD specified in the upper 16 bits
+ * of the ctlRequest.
+ */
+ case IAPI_CHANGE_SET_EXTDBUFFERADDR:
+ {
+ bufferDescriptor * bde_p;
+ retvalue = IAPI_SUCCESS;
+
+ /* Get pointer to the BD structure to change*/
+ bde_p = (bufferDescriptor *)iapi_Phys2Virt(cd_p->ccb_ptr->baseBDptr);
+ bde_p+= bd_num;
+
+ /* DO NOT translate address to physical. The user might want something else
+ *here
+ */
+ bde_p->extBufferAddr = (void*)param;
+
+ iapi_ReleaseChannel(chNum);
+ return retvalue;
+ }
+ /*
+ * EXTENDED BUFFER address
+ * --- Get extended buffer address from the BD specified in the upper 16 bits
+ * of the ctlRequest.
+ */
+ case IAPI_CHANGE_GET_EXTDBUFFERADDR:
+ {
+ bufferDescriptor * bde_p;
+ retvalue = IAPI_SUCCESS;
+
+ /* Get pointer to the BD structure to change*/
+ bde_p = (bufferDescriptor *)iapi_Phys2Virt(cd_p->ccb_ptr->baseBDptr);
+ bde_p+= bd_num;
+
+ /* DO NOT translate address to vitual - user knows what is here.
+ */
+ *((unsigned long*)param) = (unsigned long)bde_p->extBufferAddr;
+
+ iapi_ReleaseChannel(chNum);
+ return retvalue;
+ }
+ /*
+ * COMMAND field
+ * --- Change command field in BD specified in the upper 16 bits of the
+ * ctlRequest.
+ */
+ case IAPI_CHANGE_SET_COMMAND:
+ {
+ bufferDescriptor * bde_p;
+ retvalue = IAPI_SUCCESS;
+
+ /* Get pointer to the BD structure to change*/
+ bde_p = (bufferDescriptor *)iapi_Phys2Virt(cd_p->ccb_ptr->baseBDptr);
+ bde_p+= bd_num;
+ /* Update command field*/
+ bde_p->mode.command = param;
+
+ iapi_ReleaseChannel(chNum);
+ return retvalue;
+ }
+ /*
+ * COMMAND field
+ * --- Get the command field from the BD specified in the upper 16 bits
+ * of the ctlRequest.
+ */
+ case IAPI_CHANGE_GET_COMMAND:
+ {
+ bufferDescriptor * bde_p;
+ retvalue = IAPI_SUCCESS;
+
+ /* Get pointer to the BD structure to change*/
+ bde_p = (bufferDescriptor *)iapi_Phys2Virt(cd_p->ccb_ptr->baseBDptr);
+ bde_p+= bd_num;
+ /* Get the command field*/
+ *((unsigned long*)param) = bde_p->mode.command;
+
+ iapi_ReleaseChannel(chNum);
+ return retvalue;
+ }
+ /*
+ * COUNT field
+ * --- Change count field in BD specified in the upper 16 bits of the
+ * ctlRequest.
+ */
+ case IAPI_CHANGE_SET_COUNT:
+ {
+ bufferDescriptor * bde_p;
+ retvalue = IAPI_SUCCESS;
+
+ /* Get pointer to the BD structure to change*/
+ bde_p = (bufferDescriptor *)iapi_Phys2Virt(cd_p->ccb_ptr->baseBDptr);
+ bde_p+= bd_num;
+ /* Update count field*/
+ bde_p->mode.count = param;
+
+ iapi_ReleaseChannel(chNum);
+ return retvalue;
+ }
+ /*
+ * COUNT field
+ * --- Get the count field of the BD specified in the upper 16 bits of the
+ * ctlRequest.
+ */
+ case IAPI_CHANGE_GET_COUNT:
+ {
+ bufferDescriptor * bde_p;
+ retvalue = IAPI_SUCCESS;
+
+ /* Get pointer to the BD structure to change*/
+ bde_p = (bufferDescriptor *)iapi_Phys2Virt(cd_p->ccb_ptr->baseBDptr);
+ bde_p+= bd_num;
+ /* Update count field*/
+ *((unsigned long*)param) = bde_p->mode.count;
+
+ iapi_ReleaseChannel(chNum);
+ return retvalue;
+ }
+ /*
+ * STATUS field
+ * --- Change status field in BD specified in the upper 16 bits of the
+ * ctlRequest.
+ */
+ case IAPI_CHANGE_SET_STATUS:
+ {
+ bufferDescriptor * bde_p;
+ retvalue = IAPI_SUCCESS;
+
+ /* Get pointer to the BD structure to change*/
+ bde_p = (bufferDescriptor *)iapi_Phys2Virt(cd_p->ccb_ptr->baseBDptr);
+ bde_p+= bd_num;
+ /* Update status field*/
+ bde_p->mode.status = param;
+
+ iapi_ReleaseChannel(chNum);
+ return retvalue;
+ }
+ /*
+ * STATUS field
+ * --- Get the status field of the BD specified in the upper 16 bits
+ * of the ctlRequest.
+ */
+ case IAPI_CHANGE_GET_STATUS:
+ {
+ bufferDescriptor * bde_p;
+ retvalue = IAPI_SUCCESS;
+
+ /* Get pointer to the BD structure to change*/
+ bde_p = (bufferDescriptor *)iapi_Phys2Virt(cd_p->ccb_ptr->baseBDptr);
+ bde_p+= bd_num;
+ /* Update status field*/
+ *((unsigned long*)param) = bde_p->mode.status;
+
+ iapi_ReleaseChannel(chNum);
+ return retvalue;
+ }
+
+#ifdef MCU
+ /*
+ * Endianness
+ * --- Set the ENDIANNESS indicator in the command filed of the specified BD
+ * or on all BD's if SET_BIT_ALL is passed as parameter.
+ */
+ case IAPI_CHANGE_SET_ENDIANNESS:
+ {
+ bufferDescriptor * bde_p;
+ int j = 0;
+
+ retvalue = IAPI_SUCCESS;
+ if(param == SET_BIT_ALL)
+ {
+ bde_p = (bufferDescriptor *)iapi_Phys2Virt(cd_p->ccb_ptr->baseBDptr);
+ for(j = 0; j < cd_p->bufferDescNumber; j++)
+ {
+ bde_p->mode.command = CHANGE_ENDIANNESS;
+ bde_p++;
+ }
+ }
+ else if(param < cd_p->bufferDescNumber)
+ {
+ bde_p = (bufferDescriptor *)iapi_Phys2Virt(cd_p->ccb_ptr->baseBDptr) +
+ param;
+ bde_p->mode.command = CHANGE_ENDIANNESS;
+ }
+ else
+ {
+ retvalue = IAPI_FAILURE;
+ }
+ iapi_ReleaseChannel(chNum);
+ return retvalue;
+ }
+#endif
+
+#ifdef SDMA_SKYE
+#ifdef MCU
+
+ /*
+ * SDMA State
+ * --- Enter the SDMA into LOCK Mode. No RAM updation allowed except same Context
+ * update with same PC Value.
+ */
+ case IAPI_ENTER_LOCK_MODE:
+ {
+ if(param == RESET_CLEAR_LOCK)
+ {
+ SDMA_SDMA_LOCK = (1 << RESET_CLR_BIT_OFFSET);
+ SDMA_SDMA_LOCK = (1 << LOCK_BIT_OFFSET);
+ iapi_SdmaState = LOCK;
+ }
+ else if(param == RESET_NOCLEAR_LOCK)
+ {
+ SDMA_SDMA_LOCK = (1 << LOCK_BIT_OFFSET);
+ iapi_SdmaState = LOCK;
+ }
+
+ }
+ break;
+
+#endif
+#endif
+ default:
+ retvalue = IAPI_ERR_CD_CHANGE_UNKNOWN | IAPI_ERR_CH_AVAILABLE | chNum;
+ iapi_errno = retvalue;
+ iapi_ReleaseChannel(chNum);
+ return -retvalue;
+ }
+
+
+ iapi_ReleaseChannel(chNum);
+ return IAPI_SUCCESS;
+}
+/* ***************************************************************************/
+/**Initialization of the SDMA - opening of channel 0, download RAM image.
+ *
+ * <b>Algorithm:</b>\n
+ * - open channel 0
+ * - if ram_image pointer passed is not NULL, download RAM image to SDMA
+ *
+ * @param
+ * - cd_p channel descriptor pointer for channel 0
+ * - ram_image pointer to RAM image to download, or NULL if this operation
+ * is not required
+ * - code_size size of the RAM image, in bytes
+ * - start_addr start address for the RAM image
+ *
+ * @return
+ * - IAPI_SUCCESS if all operations were successful
+ * - negated I.API error code if any operation failed
+ */
+#ifdef MCU
+int
+iapi_Init(channelDescriptor * cd_p, configs_data * config_p, unsigned short* ram_image,
+ unsigned short code_size, unsigned long start_addr)
+{
+#endif
+#ifdef DSP
+int
+iapi_Init(channelDescriptor * cd_p)
+{
+#endif
+
+int retvalue = IAPI_SUCCESS; /* Variable to store the results from I.API calls */
+
+ /* Check initialization not allredy done*/
+ if(iapi_CCBHead != NULL)
+ {
+ retvalue = IAPI_ERR_NOT_ALLOWED;
+ iapi_errno = retvalue;
+ return -retvalue;
+ }
+ /* Be sure SDMA has not started yet */
+#ifdef MCU
+ SDMA_H_C0PTR = 0x0;
+#endif
+#ifdef DSP
+ SDMA_D_C0PTR = 0x0;
+#endif
+
+ /*Try to open channel 0*/
+ retvalue = iapi_Open(cd_p, 0);
+ if(retvalue != IAPI_SUCCESS)
+ {
+ return retvalue;
+ }
+
+#ifdef MCU
+ /* Set Command Channel (Channel Zero) */
+ SDMA_CHN0ADDR = 0x4050;
+
+ /* Set bits of CONFIG register but with static context switching */
+ SDMA_H_CONFIG = (config_p->dspdma << 12) | (config_p->rtdobs << 11) |
+ (config_p->acr << 4) | (0);
+
+ /* Send the address for the host channel table to the SDMA*/
+ SDMA_H_C0PTR = (unsigned long)iapi_Virt2Phys(iapi_CCBHead);
+ /* If required, download the RAM image for SDMA*/
+ if(ram_image != NULL)
+ {
+ retvalue = iapi_SetScript(cd_p, (void*)ram_image, code_size,
+ start_addr);
+ }
+
+ /* Set bits of CONFIG register with given context switching mode */
+ SDMA_H_CONFIG = (config_p->dspdma << 12) | (config_p->rtdobs << 11) |
+ (config_p->acr << 4) | (config_p->csm);
+
+#endif
+#ifdef DSP
+ /* Send the address for the host channel table to the SDMA*/
+ SDMA_D_C0PTR = (unsigned long)iapi_Virt2Phys(iapi_CCBHead);
+#endif
+
+#ifdef SDMA_SKYE
+ iapi_SdmaState = OPEN;
+#endif
+
+ return retvalue;
+}
+
+
+/* ***************************************************************************/
+/**High layer interface for starting a channel
+ *
+ * <b>Algorithm:</b>\n
+ * - call low layer function for starting a channel
+ *
+ * @return
+ * - IAPI_SUCCESS
+ */
+int
+iapi_StartChannel(unsigned char channel)
+{
+ iapi_lowStartChannel(channel);
+ return IAPI_SUCCESS;
+}
+/* ***************************************************************************/
+/**High layer interface for stopping a channel
+ *
+ * <b>Algorithm:</b>\n
+ * - call low layer function for stopping a channel
+ *
+ * @return
+ * - IAPI_SUCCESS
+ */
+int
+iapi_StopChannel(unsigned char channel)
+{
+ iapi_lowStopChannel(channel);
+ return IAPI_SUCCESS;
+}
+
+/* ***************************************************************************/
+/**High layer interface for synchronising a channel
+ *
+ * <b>Algorithm:</b>\n
+ * - call low layer function for stopping a channel
+ *
+ * @return
+ * - IAPI_SUCCESS
+ */
+int iapi_SynchChannel(unsigned char channel)
+{
+ iapi_lowSynchChannel(channel);
+ return IAPI_SUCCESS;
+}
+
+#ifdef MCU
+/* ***************************************************************************/
+/**High layer interface for getting program memory data from SDMA
+ *
+ * <b>Algorithm:</b>\n
+ * - call coresponding low layer function
+ *
+ * @return
+ * - IAPI_SUCCESS
+ */
+int
+iapi_GetScript(channelDescriptor * cd_p, void * buf, unsigned short size,
+ unsigned long address)
+{
+ iapi_lowGetScript(cd_p, buf, size, address);
+ return IAPI_SUCCESS;
+}
+
+/* ***************************************************************************/
+/**High layer interface for getting data memory from SDMA
+ *
+ * <b>Algorithm:</b>\n
+ * - call coresponding low layer function
+ *
+ * @return
+ * - IAPI_SUCCESS
+ */
+int
+iapi_GetContext(channelDescriptor * cd_p, void * buf,
+ unsigned char channel)
+{
+ iapi_lowGetContext(cd_p, buf, channel);
+ return IAPI_SUCCESS;
+}
+
+/* ***************************************************************************/
+/**High layer interface for set program memory data to SDMA - e.g. scripts
+ *
+ * <b>Algorithm:</b>\n
+ * - call coresponding low layer function
+ *
+ * @return
+ * - IAPI_SUCCESS
+ */
+int
+iapi_SetScript(channelDescriptor * cd_p, void * buf, unsigned short nbyte,
+ unsigned long destAddr)
+{
+ iapi_lowSetScript(cd_p, buf, nbyte, destAddr);
+ return IAPI_SUCCESS;
+}
+
+/* ***************************************************************************/
+/**High layer interface for set data memory to SDMA - e.g. contexts.
+ *
+ * <b>Algorithm:</b>\n
+ * - call coresponding low layer function
+ *
+ * @return
+ * - IAPI_SUCCESS
+ */
+int
+iapi_SetContext(channelDescriptor * cd_p, void * buf,
+ unsigned char channel)
+{
+ iapi_lowSetContext(cd_p, buf, channel);
+ return IAPI_SUCCESS;
+}
+
+/* ***************************************************************************/
+/**High layer interface used to associate specified channel with a script.
+ *
+ * <b>Algorithm:</b>\n
+ * - call coresponding low layer function
+ *
+ * @return
+ * - IAPI_SUCCESS
+ */
+int
+iapi_AssignScript(channelDescriptor * cd_p, script_data * data_p)
+{
+ /* VERIFY THAT THE CHANNEL IT IS OPENED !!!!*/
+ return iapi_lowAssignScript(cd_p, data_p);
+}
+
+/* ***************************************************************************/
+/**High layer interface used to associate specified channel with a script.
+ *
+ * <b>Algorithm:</b>\n
+ * - call coresponding low layer function
+ *
+ * @return
+ * - IAPI_SUCCESS
+ */
+int
+iapi_SetChannelEventMapping(unsigned char event, unsigned long channel_map)
+{
+ return iapi_lowSetChannelEventMapping(event, channel_map);
+}
+#endif
+
+
+
+#ifdef DSP
+#define SDMA_DI SDMA_D_INTR
+void IRQ_Handler();
+#pragma interrupt IRQ_Handler
+#endif
+
+#ifdef MCU
+#define SDMA_DI SDMA_H_INTR
+#endif
+
+#ifndef IRQ_KEYWORD
+#define IRQ_KEYWORD
+#endif /* IRQ_KEYWORD */
+
+/* ***************************************************************************/
+/**
+ *@brief Find the first set bit in data parameter.
+ *
+ * Find the first set bit in unsigned integer parameter data. Data is scanned
+ * from MSB to LSB, searching for the set bit. The value returned is the
+ * offset from the most significant bit of data. If bit 31 is set, the value
+ * returned is zero. If no bits are set, a value of 32 is returned. This is compliant
+ * with the MCore FF1 instruction.
+ *
+ *
+ *
+ * @param
+ * - data: variable to check
+ *
+ * @return
+ * - the offset of the most significant bit set from the MSB
+ */
+unsigned int
+quartz_FF1( unsigned int data )
+{
+ register unsigned int result = 0;
+ while ( (result <= 31 ) && !( data & 0x80000000U) )
+ {
+ data <<= 1U;
+ result++;
+ }
+
+ return result;
+}
+
+IRQ_KEYWORD
+void
+IRQ_Handler(void)
+{
+ unsigned int intrReg;/* interrupt register mask for clearing the interrupt bit */
+ unsigned char chNum; /* SDMA channel number generating the a IRQ*/
+
+ /* Disable interrupts */
+ iapi_DisableInterrupts();
+ /*
+ * Clear interrupt in SDMA DI register => ACK to the SDMA the IT request.
+ * Get each interrupt number, clear them one after the other.
+ */
+ if(SDMA_DI != 0)
+ {
+ chNum = (unsigned char)(CH_NUM - 1 - quartz_FF1(SDMA_DI));
+ intrReg = (unsigned int)(1 << chNum);
+ }
+ else
+ {
+ chNum = 32;
+ intrReg = 0;
+ }
+
+ while (intrReg != 0)
+ {
+ SDMA_DI &= intrReg;
+ iapi_SDMAIntr |= intrReg;
+ iapi_WakeUp(chNum);
+ if (callbackIsrTable[chNum] != NULL)
+ {
+ /* release channel before callback, so IoCtl's are available*/
+ iapi_ReleaseChannel(chNum);
+ callbackIsrTable[chNum](iapi_CCBHead[chNum].channelDescriptor,
+ userArgTable[chNum]);
+ }
+
+ chNum = (unsigned char)(CH_NUM - 1 - quartz_FF1(SDMA_DI));
+ intrReg = (unsigned int)(1 << chNum);
+ }
+
+ /* Enable interrupts */
+ iapi_EnableInterrupts();
+}
+
+/* ***************************************************************************/
+/**
+ *@brief Perform a memory copy operation, in the memory of the same processor
+ *
+ * Size bytes are copied from the src address to dest address. It is used
+ * the channel pointed by cd_p, which must be configured prior to this call:
+ * opened, associated with the script to perform the operation - DSP_2_DSP,
+ * or MCU_2_MCU - and have the synchronization option set.
+ *
+ *
+ *
+ * @param
+ * - cd_p: channel configured to perform DSP_2_DSP or MCU_2_MCU transfers
+ * - dest: destination memory address
+ * - src : source memory address
+ * - size: number of bytes to copy from src to dest
+ *
+ * @return
+ * - the offset of the most significant bit set from the MSB
+ */
+
+int iapi_MemCopy(channelDescriptor * cd_p, void* dest, void* src, unsigned long size)
+{
+ int result = IAPI_SUCCESS;
+ bufferDescriptor * bd_p;
+
+ /* Channel descriptor validity */
+ if (cd_p == NULL)
+ {
+ result = IAPI_ERR_CD_UNINITIALIZED;
+ iapi_errno = result;
+ return -result;
+ }
+
+ /* Check and set correct parameter */
+ if(cd_p->trust != TRUE)
+ {
+ result = iapi_ChangeChannelDesc(cd_p, IAPI_TRUST, TRUE);
+ }
+
+ if(cd_p->bufferDescNumber != 1)
+ {
+ result = iapi_ChangeChannelDesc(cd_p, IAPI_BUFFERDESCNUMBER, 1);
+ if(result != IAPI_SUCCESS)
+ {
+ return result;
+ }
+ }
+
+ if(cd_p->bufferSize != size)
+ {
+ result = iapi_ChangeChannelDesc(cd_p, IAPI_BUFFERSIZE, size);
+ if(result != IAPI_SUCCESS)
+ {
+ return result;
+ }
+ }
+ /* Set addresses*/
+ bd_p = (bufferDescriptor *)iapi_Phys2Virt(cd_p->ccb_ptr->baseBDptr);
+ bd_p->bufferAddr = iapi_Virt2Phys(src);
+ bd_p->extBufferAddr = iapi_Virt2Phys(dest);
+
+ /* Set mode*/
+ bd_p->mode.count = size;
+ bd_p->mode.command = 0x00;
+ bd_p->mode.status = BD_INTR|BD_EXTD|BD_DONE|BD_WRAP;
+
+ /*Decide if we sleep or not*/
+ if(cd_p->callbackSynch == DEFAULT_POLL)
+ {
+ iapi_StartChannel(cd_p->channelNumber);
+ /* Call synchronization routine*/
+ iapi_SynchChannel(cd_p->channelNumber);
+ }
+ else
+ {
+ /* Just start the channel*/
+ iapi_StartChannel(cd_p->channelNumber);
+ }
+
+ return result;
+}
+
+/* ***************************************************************************/
+/**Return the channel number from the channel descriptor
+ *
+ * @param cd_p pointer to channel descriptor to obtain the channel number
+ *
+ * @return
+ * - the channel number
+ *
+ */
+int iapi_GetChannelNumber(channelDescriptor * cd_p)
+{
+ return cd_p->channelNumber;
+}
+
+/* ***************************************************************************/
+/**Return the error bit from the current BD of the channel
+ *
+ *
+ * @param cd_p pointer to channel descriptor
+ *
+ * @return
+ * - 0 if no error detected
+ * - BD_RROR | DATA_ERROR if error detected
+ *
+ */
+unsigned long iapi_GetError(channelDescriptor * cd_p)
+{
+ return ((cd_p->ccb_ptr->currentBDptr->mode.status & BD_RROR) |
+ (*(unsigned long*)&cd_p->ccb_ptr->status & DATA_ERROR));
+}
+
+/* ***************************************************************************/
+/**Return the count from the current BD of the channel
+ *
+ *
+ * @param cd_p pointer to channel descriptor
+ *
+ * @return
+ * - count field of the current BD for the channel
+ *
+ */
+int iapi_GetCount(channelDescriptor * cd_p)
+{
+ return (int)(cd_p->ccb_ptr->currentBDptr->mode.count);
+}
+
+/* ***************************************************************************/
+/**Return the sum of counts for all the BD's owned by the processor for
+ * the channel specified by the received parameter.
+ *
+ *
+ * @param cd_p pointer to channel descriptor
+ *
+ * @return
+ * - sum of count fields
+ *
+ */
+int iapi_GetCountAll(channelDescriptor * cd_p)
+{
+ int retval = 0;
+ int i = 0;
+ bufferDescriptor* bd_p;
+
+ bd_p = cd_p->ccb_ptr->baseBDptr;
+
+ while((i < cd_p->bufferDescNumber) && ((bd_p->mode.status & BD_DONE) == 0))
+ {
+ retval += bd_p->mode.count;
+ i++;
+ bd_p++;
+ }
+ return retval;
+}
diff --git a/arch/arm/plat-mxc/sdma/iapi/src/iapiLow.c b/arch/arm/plat-mxc/sdma/iapi/src/iapiLow.c
new file mode 100644
index 000000000000..205969f82533
--- /dev/null
+++ b/arch/arm/plat-mxc/sdma/iapi/src/iapiLow.c
@@ -0,0 +1,149 @@
+/******************************************************************************
+ *
+ * Copyright 2007-2008 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
+ *
+ ******************************************************************************
+ *
+ * File: iapiLow.c
+ *
+ * $Id iapiLow.c $
+ *
+ * Description:
+ * This library is written in C to guarantee functionality and integrity in
+ * the usage of SDMA virtual DMA channels. This API (Application Programming
+ * Interface) allow SDMA channels' access in an OPEN, READ, WRITE, CLOSE
+ * fashion.
+ * These are the LOW level functions of the I.API.
+ *
+ *
+ * /
+ *
+ * $Log iapiLow.c $
+ *
+ *****************************************************************************/
+
+/* ****************************************************************************
+ * Include File Section
+ *****************************************************************************/
+#include "epm.h"
+#include "iapiLow.h"
+
+/**
+ * Function Section
+ */
+
+
+/* ***************************************************************************/
+/**Records an ISR callback function pointer into the ISR callback
+ * function table
+ *
+ * @param cd_p channel descriptor to attach callback to
+ * @param func_p pointer to the callback function to be registered
+ *
+ * @return none
+ */
+void
+iapi_AttachCallbackISR (channelDescriptor * cd_p,
+ void (* func_p)(channelDescriptor * cd_p, void * arg))
+
+{
+ if (cd_p->callbackSynch == CALLBACK_ISR) {
+ iapi_DisableInterrupts();
+ callbackIsrTable[cd_p->channelNumber] = func_p;
+ iapi_EnableInterrupts();
+ } else if (cd_p->callbackSynch == DEFAULT_POLL) {
+ callbackIsrTable[cd_p->channelNumber] = NULL;
+ } else {
+ iapi_errno = IAPI_ERR_CALLBACKSYNCH_UNKNOWN | IAPI_ERR_CH_AVAILABLE |
+ cd_p->channelNumber;
+ }
+}
+
+
+/* ***************************************************************************/
+/**Detaches (removes) an ISR callback function pointer from the ISR callback
+ * function table
+ *
+ * <b>Algorithm:</b>\n
+ * - Attach a null function to replace the original one.
+ *
+ * @param cd_p channel descriptor to detach callback from
+ *
+ * @return none
+ */
+void
+iapi_DetachCallbackISR (channelDescriptor * cd_p)
+
+{
+ iapi_AttachCallbackISR (cd_p, NULL);
+}
+
+/* ***************************************************************************/
+/**Updates an ISR callback function pointer into the ISR callback function
+ * table
+ *
+ * <b>Algorithm:</b>\n
+ * - Detach the old function pointer (if any) and attach the new one
+ *
+ * @param cd_p channel descriptor to attach callback to
+ * @param func_p pointer to the callback function to be registered
+ *
+ * @return none
+ */
+void
+iapi_ChangeCallbackISR (channelDescriptor * cd_p,
+ void (* func_p)(channelDescriptor * cd_p, void * arg))
+{
+ iapi_DetachCallbackISR(cd_p);
+ iapi_AttachCallbackISR(cd_p, func_p);
+}
+
+/* ***************************************************************************/
+/**Loop while the channel is not done on the SDMA
+ *
+ * <b>Algorithm:</b>\n
+ * - Loop doing nothing but checking the I.API global variable to indicate
+ * that the channel has been completed (interrupt from SDMA)
+ *
+ * <b>Notes:</b>\n
+ * - The ISR must update the I.API global variable iapi_SDMAIntr.
+ *
+ * @param channel channel number to poll on
+ *
+ * @return none
+ */
+void
+iapi_lowSynchChannel (unsigned char channel)
+{
+ while (!((1UL << channel) & iapi_SDMAIntr)) ;
+ iapi_SDMAIntr &= ~(1UL << channel);
+}
+
+/* ***************************************************************************/
+/**Fill the buffer descriptor with the values given in parameter.
+ *
+ * @return none
+ */
+void
+iapi_SetBufferDescriptor( bufferDescriptor * bd_p, unsigned char command,
+ unsigned char status, unsigned short count,
+ void * buffAddr, void * extBufferAddr)
+{
+ bd_p->mode.command = command;
+ bd_p->mode.status = status;
+ bd_p->mode.count = count;
+ if (buffAddr != NULL) {
+ bd_p->bufferAddr = iapi_Virt2Phys(buffAddr);
+ } else {
+ bd_p->bufferAddr = buffAddr;
+ }
+ bd_p->extBufferAddr = extBufferAddr;
+}
diff --git a/arch/arm/plat-mxc/sdma/iapi/src/iapiLowDsp.c b/arch/arm/plat-mxc/sdma/iapi/src/iapiLowDsp.c
new file mode 100644
index 000000000000..df7d44a9bd46
--- /dev/null
+++ b/arch/arm/plat-mxc/sdma/iapi/src/iapiLowDsp.c
@@ -0,0 +1,79 @@
+/******************************************************************************
+ *
+ * Copyright 2007 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
+ *
+ ******************************************************************************
+ *
+ * File: iapiLowDsp.c
+ *
+ * $Id iapiLowDsp.c $
+ *
+ * Description:
+ * This library is written in C to guarantee functionality and integrity in
+ * the usage of SDMA virtual DMA channels. This API (Application Programming
+ * Interface) allow SDMA channels' access in an OPEN, READ, WRITE, CLOSE
+ * fashion.
+ * These are the LOW level functions of the I.API specific to MCU.
+ *
+ *
+ *
+ *
+ * $Log iapiLowDsp.c $
+ *
+ *****************************************************************************/
+
+/* ****************************************************************************
+ * Include File Section
+ *****************************************************************************/
+#include "epm.h"
+#include "iapiLow.h"
+
+/* ****************************************************************************
+ * Function Section
+ *****************************************************************************/
+#ifdef DSP
+
+/* ***************************************************************************/
+/**Starts the channel (core specific register)
+ *
+ * <b>Algorithm:</b>\n
+ * - Bit numbered "channel" of DspEnStartReg register is set
+ *
+ * @param channel channel to start
+ *
+ * @return none
+ */
+void
+iapi_lowStartChannel (unsigned char channel)
+{
+ SDMA_D_START |= (1 << channel);
+}
+
+/* ***************************************************************************/
+/**Stops the channel (core specific register)
+ *
+ * <b>Algorithm:</b>
+ * - Bit numbered "channel" of DspEnStopReg register is cleared
+ *
+ * <b>Notes:</b>\n
+ * - This is a write one to clear register
+ *
+ * @param channel channel to stop
+ *
+ * @return none
+ */
+void
+iapi_lowStopChannel (unsigned char channel)
+{
+ SDMA_D_STATSTOP &= (1 << channel);
+}
+
+#endif /* DSP */
diff --git a/arch/arm/plat-mxc/sdma/iapi/src/iapiLowMcu.c b/arch/arm/plat-mxc/sdma/iapi/src/iapiLowMcu.c
new file mode 100644
index 000000000000..886c70c4c3d3
--- /dev/null
+++ b/arch/arm/plat-mxc/sdma/iapi/src/iapiLowMcu.c
@@ -0,0 +1,518 @@
+/******************************************************************************
+ *
+ * Copyright 2007-2009 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
+ *
+ ******************************************************************************
+ *
+ * File: iapiLowMcu.c
+ *
+ * $Id iapiLowMcu.c $
+ *
+ * Description:
+ * This library is written in C to guarantee functionality and integrity in
+ * the usage of SDMA virtual DMA channels. This API (Application Programming
+ * Interface) allow SDMA channels' access in an OPEN, READ, WRITE, CLOSE
+ * fashion.
+ * These are the LOW level functions of the I.API specific to MCU.
+ *
+ *
+ * http://compass/mot.com/go/115342679
+ *
+ * $Log iapiLowMcu.c $
+ *
+ *****************************************************************************/
+
+/* ****************************************************************************
+ * Include File Section
+ *****************************************************************************/
+#include <string.h>
+
+#include "epm.h"
+#include "iapiLow.h"
+
+/* ****************************************************************************
+ * Function Section
+ *****************************************************************************/
+#ifdef MCU
+
+/* ***************************************************************************/
+/**Send a command on SDMA's channel zero.
+ * Check if buffer descriptor is already used by the sdma, if yes return
+ * an error as c0BDNum is wrong.
+ *
+ * <b>Notes</b>\n
+ * There is an upgrade in the script on the Context load command and
+ * the fact that the context structure has a fixed length of 20 or 24
+ * depending on SDMA versions.
+ *
+ * @return
+ * - IAPI_SUCCESS
+ * - -iapi_errno if failure
+ */
+int
+iapi_Channel0Command( channelDescriptor * cd_p, void * buf,
+ unsigned short nbyte, unsigned char command)
+{
+ channelControlBlock * ccb_p;
+ bufferDescriptor * bd_p;
+ int result = IAPI_SUCCESS;
+ unsigned char chNum;
+
+
+ /*
+ * Check data structures are properly initialized
+ */
+ /* Channel descriptor validity */
+ if (cd_p == NULL){
+ result = IAPI_ERR_CD_UNINITIALIZED;
+ iapi_errno = result;
+ return -result;
+ }
+
+ /* Channel control block validity */
+ if (cd_p->ccb_ptr == NULL){
+ result = IAPI_ERR_CCB_UNINITIALIZED;
+ iapi_errno = result;
+ return -result;
+ }
+
+ /* Control block & Descriptpor associated with the channel being worked on */
+ chNum = cd_p->channelNumber;
+ ccb_p = cd_p->ccb_ptr;
+
+ /* Is channel already in use ? */
+ if (ccb_p->baseBDptr != NULL ) {
+ result = IAPI_ERR_BD_ALLOCATED | IAPI_ERR_CH_AVAILABLE | chNum;
+ iapi_errno = result;
+ return -result;
+ }
+
+ /* Allocation of buffer descriptors */
+ bd_p = (bufferDescriptor *)MALLOC(sizeof( bufferDescriptor ), SDMA_ERAM);
+ if (bd_p != NULL) {
+ ccb_p->baseBDptr = (bufferDescriptor *)iapi_Virt2Phys(bd_p);
+ } else {
+ result = IAPI_ERR_BD_ALLOCATION | IAPI_ERR_CH_AVAILABLE | chNum;
+ iapi_errno = result;
+ return -result;
+ }
+
+ /* Buffer descriptor setting */
+ iapi_SetBufferDescriptor( bd_p, command , BD_WRAP|BD_DONE|BD_INTR , nbyte,
+ buf,NULL);
+
+ /* Actually the transfer */
+ iapi_lowStartChannel( cd_p->channelNumber );
+ iapi_lowSynchChannel( cd_p->channelNumber );
+
+ /* Cleaning of allocation */
+ FREE( bd_p );
+ ccb_p->baseBDptr = NULL;
+
+ return IAPI_SUCCESS;
+
+}
+
+/* ***************************************************************************/
+/**Starts the channel (core specific register)
+ *
+ * <b>Algorithm:</b>\n
+ * - Bit numbered "channel" of HostEnStartReg register is set
+ *
+ * @param channel channel to start
+ *
+ * @return none
+ */
+void
+iapi_lowStartChannel (unsigned char channel)
+{
+ SDMA_H_START |= 1 << channel;
+}
+
+/* ***************************************************************************/
+/**Stops the channel (core specific register)
+ *
+ * <b>Algorithm:</b>
+ * - Bit numbered "channel" of HostEnStopReg register is cleared
+ *
+ * <b>Notes:</b>\n
+ * - This is a write one to clear register
+ *
+ * @param channel channel to stop
+ *
+ * @return none
+ */
+void
+iapi_lowStopChannel (unsigned char channel)
+{
+ SDMA_H_STATSTOP &= 1 << channel;
+}
+
+/* ***************************************************************************/
+/**Initialize the initial priority of registers and channel enable
+ * RAM from the MCU side. No channels are enabled, all priorities are set to 0.
+ *
+ * @return none
+ */
+void
+iapi_InitChannelTables(void)
+{
+
+ /* No channel is enabled*/
+ iapi_memset((void *)&SDMA_CHNENBL_0, 0x00, sizeof(unsigned long)*EVENTS_NUM);
+ /* All channels have priority 0*/
+ iapi_memset((void *)&SDMA_CHNPRI_0, 0x00, sizeof(unsigned long)*CH_NUM);
+}
+
+/* ***************************************************************************/
+/** The host enable (HE), hosts override (HO), dsp enable (DE), dsp override
+ * (DO) registers are involved here.
+ * Host and Dsp enable registers are here to signify that the MCU or DSP side
+ * have prepared the appropriate buffers and are now ready. If the channel is
+ * owned by the MCU the override bit for that channel needs to be cleared :
+ * the host allows the channel to be used.\n
+ *
+ * Then the override bits can define (mcuOverride dspOverride):\n
+ * - 0 0 channel is public: transfer to/from MCU to DSP
+ * - 0 1 channel if owned by DSP
+ * - 1 0 channel if owned by MCU
+ * - 1 1 channel zero config
+ *
+ * See also :\n
+ * IAPI Table 1.1 "Channel configuration properties"
+ *
+ * @param channel channel to configure
+ * @param eventOverride event ownership
+ * @param mcuOverride ARM ownership
+ * @param dspOverride DSP ownership
+ *
+ * @return
+ * - -iapi_errno if the 3 override parameters are all set
+ * - IAPI_SUCCESS in other cases (valid cases)
+ */
+int
+iapi_ChannelConfig (unsigned char channel, unsigned eventOverride,
+ unsigned mcuOverride, unsigned dspOverride)
+{
+ int result = IAPI_SUCCESS;
+
+ if ( ( eventOverride == 1 ) &&
+ ( mcuOverride == 1 ) &&
+ ( dspOverride == 1 ) ){
+ result = IAPI_ERR_CONFIG_OVERRIDE ;
+ iapi_errno = result;
+ return -result;
+ } else {
+ /*
+ * DSP side
+ */
+ if ( dspOverride ){
+ SDMA_H_DSPOVR &= ~( 1 << channel );
+ } else {
+ SDMA_H_DSPOVR |= ( 1 << channel );
+ }
+ /*
+ * Event
+ */
+ if ( eventOverride ){
+ SDMA_H_EVTOVR &= ~( 1 << channel );
+ } else {
+ SDMA_H_EVTOVR |= ( 1 << channel );
+ }
+ /*
+ * MCU side
+ */
+ if ( mcuOverride ) {
+ SDMA_H_HOSTOVR &= ~( 1 << channel );
+ } else {
+ SDMA_H_HOSTOVR |= ( 1 << channel );
+ }
+ }
+ return IAPI_SUCCESS;
+}
+/* ***************************************************************************/
+/**Load the context data of a channel from SDMA
+ *
+ * <b>Algorithm:</b>\n
+ * - Setup BD with appropiate parameters
+ * - Start channel
+ * - Poll for answer
+ *
+ * @param *cd_p channel descriptor for channel 0
+ * @param *buf pointer to receive context data
+ * @param channel channel for which the context data is requested
+ *
+ * @return none
+ */
+void
+iapi_lowGetContext(channelDescriptor * cd_p, void * buf, unsigned char channel)
+{
+ bufferDescriptor * bd_p;
+
+ bd_p = (bufferDescriptor *)iapi_Phys2Virt(cd_p->ccb_ptr->baseBDptr);
+
+ /*Setup buffer descriptor with channel 0 command*/
+ iapi_SetBufferDescriptor(&bd_p[0],
+ C0_GETDM,
+ (unsigned char)(BD_DONE | BD_INTR | BD_WRAP | BD_EXTD),
+ (unsigned short)sizeof(contextData)/4,
+ buf,
+ (void *)(CHANNEL_CONTEXT_BASE_ADDRESS + (sizeof(contextData)*channel/4)));
+ /* Receive, polling method*/
+ iapi_lowStartChannel(cd_p->channelNumber);
+ iapi_lowSynchChannel(cd_p->channelNumber);
+}
+/* ***************************************************************************/
+/**Read "size" byte /2 at SDMA address (address) and write them in buf
+ *
+ * <b>Algorithm:</b>\n
+ * - Setup BD with appropiate parameters (C0_GETPM)
+ * - Start channel
+ * - Poll for answer
+ *
+ * <b>Notes</b>\n
+ * - Parameter "size" is in bytes, it represents the size of "buf", e.g.
+ * the size in bytes of the script to be loaded.
+ * - Parameter "address" denotes the RAM address for the script in SDMA
+ *
+ * @param *cd_p channel descriptor for channel 0
+ * @param *buf pointer to receive the data
+ * @param size number of bytes to read
+ * @param address address in SDMA RAM to start reading from
+ *
+ * @return none
+ */
+void
+iapi_lowGetScript(channelDescriptor * cd_p, void * buf, unsigned short size,
+ unsigned long address)
+{
+ bufferDescriptor * bd_p;
+
+ bd_p = (bufferDescriptor *)iapi_Phys2Virt(cd_p->ccb_ptr->baseBDptr);
+
+ /*Setup buffer descriptor with channel 0 command*/
+ iapi_SetBufferDescriptor(&bd_p[0],
+ C0_GETPM,
+ (unsigned char)(BD_DONE | BD_INTR | BD_WRAP | BD_EXTD),
+ (unsigned short)size/2,/*count in shorts*/
+ buf,
+ (void *)address);
+ /* Receive, polling method*/
+ iapi_lowStartChannel(cd_p->channelNumber);
+ iapi_lowSynchChannel(cd_p->channelNumber);
+}
+
+/* ***************************************************************************/
+/**Load a SDMA script to SDMA
+ *
+ * <b>Algorithm:</b>\n
+ * - Setup BD with appropiate parameters (C0_SETPM)
+ * - Start channel
+ * - Poll for answer
+ *
+ * <b>Notes</b>\b
+ * - Parameter "size" is in bytes, it represents the size of "buf", e.g.
+ * the size in bytes of the script to be uploaded.
+ * - Parameter "address" denotes the RAM address for the script in SDMA
+ *
+ * @param *cd_p channel descriptor for channel 0
+ * @param *buf pointer to the script
+ * @param size size of the script, in bytes
+ * @param address address in SDMA RAM to place the script
+ *
+ * @return none
+ */
+void
+iapi_lowSetScript(channelDescriptor * cd_p, void * buf, unsigned short size,
+ unsigned long address)
+{
+ bufferDescriptor * bd_p;
+
+ bd_p = (bufferDescriptor *)iapi_Phys2Virt(cd_p->ccb_ptr->baseBDptr);
+
+ /*Setup buffer descriptor with channel 0 command*/
+ iapi_SetBufferDescriptor(&bd_p[0],
+ C0_SETPM,
+ (unsigned char)(BD_DONE | BD_INTR | BD_WRAP | BD_EXTD),
+ (unsigned short)size/2,/*count in shorts*/
+ buf,
+ (void *)(address));
+ /* Receive, polling method*/
+ iapi_lowStartChannel(cd_p->channelNumber);
+ iapi_lowSynchChannel(cd_p->channelNumber);
+}
+
+
+/* ***************************************************************************/
+/**Load the context for a channel to SDMA
+ *
+ * <b>Algorithm:</b>\n
+ * - Send context and poll for answer.
+ *
+ * @param *cd_p channel descriptor for channel 0
+ * @param *buf pointer to context data
+ * @param channel channel to place the context for
+ *
+ * @return none
+ */
+void
+iapi_lowSetContext(channelDescriptor * cd_p, void * buf, unsigned char channel)
+{
+
+ bufferDescriptor * local_bd_p;
+#ifdef SDMA_SKYE
+
+ unsigned char command =0;
+
+ local_bd_p = (bufferDescriptor *)iapi_Phys2Virt(cd_p->ccb_ptr->baseBDptr);
+
+
+ command = channel <<3 ;
+ command = command | C0_SETCTX;
+ iapi_SetBufferDescriptor( &local_bd_p[0],
+ command,
+ (unsigned char)(BD_DONE | BD_INTR | BD_WRAP),
+ (unsigned short)(sizeof(contextData)/4),
+ buf,
+ NULL);
+#else
+
+ local_bd_p = (bufferDescriptor *)iapi_Phys2Virt(cd_p->ccb_ptr->baseBDptr);
+
+
+
+
+ iapi_SetBufferDescriptor( &local_bd_p[0],
+ C0_SETDM,
+ (unsigned char)(BD_DONE | BD_INTR | BD_WRAP|BD_EXTD),
+ (unsigned short)(sizeof(contextData)/4),
+ buf,
+ (void *)(2048+(sizeof(contextData)/4)*channel));
+#endif
+ /* Send */
+ iapi_lowStartChannel( cd_p->channelNumber );
+ iapi_lowSynchChannel( cd_p->channelNumber );
+
+}
+
+/* ***************************************************************************/
+/**Associate specified channel with the script starting at the
+ * specified address. Channel 0 command is used to load the set-up context
+ * for the channel. The address used must be generated by the GUI tool
+ * used to create RAM images for SDMA.
+ *
+ * <b>Algorithm:</b>\n
+ * - Set-up and load the context.
+ *
+ * @param *cd_p pointer to the channel descriptor of the channel
+ * @param *data_p: pointer to the data identifying the script to be associated
+ * with the channel
+ *
+ * @return
+ * - IAPI_SUCCESS : OK
+ * - -iapi_errno : operation failed, return negated value of iapi_errno
+ */
+
+int
+iapi_lowAssignScript(channelDescriptor * cd_p, script_data * data_p)
+{
+ contextData * chContext; /* context to be loaded for the channel */
+ channelDescriptor * cd0_p; /* pointer to channel descriptor of channel 0*/
+ int result = IAPI_SUCCESS;
+
+ /*Verify passed data*/
+ if(cd_p == NULL || data_p == NULL)
+ {
+ result = IAPI_ERR_INVALID_PARAMETER;
+ iapi_errno = result;
+ return -result;
+ }
+
+ /* Allocate context and initialize PC to required script start adress*/
+ chContext = (contextData *) MALLOC(sizeof(contextData), SDMA_ERAM);
+ if (chContext == NULL)
+ {
+ result = IAPI_ERR_B_ALLOC_FAILED | cd_p->channelNumber;
+ iapi_errno = result;
+ return -result;
+ }
+
+ iapi_memset(chContext, 0x00, sizeof(contextData));
+ chContext->channelState.pc = data_p->load_address;
+
+ /* Send by context the event mask,base address for peripheral
+ * and watermark level
+ */
+ chContext->gReg[0] = data_p->event_mask2;
+ chContext->gReg[1] = data_p->event_mask1;
+ chContext->gReg[6] = data_p->shp_addr;
+ chContext->gReg[7] = data_p->wml;
+ if (data_p->per_addr)
+ chContext->gReg[2] = data_p->per_addr;
+
+ /* Set transmited data to the CD*/
+ cd_p->watermarkLevel = data_p->wml;
+ cd_p->eventMask1 = data_p->event_mask1;
+ cd_p->eventMask2 = data_p->event_mask2;
+
+ /* Get the cd0_p*/
+ cd0_p = (cd_p->ccb_ptr - cd_p->channelNumber)->channelDescriptor;
+
+ /*load the context*/
+ iapi_lowSetContext(cd0_p, chContext, cd_p->channelNumber);
+
+ /* release allocated memory*/
+ FREE(chContext);
+
+ return IAPI_SUCCESS;
+}
+
+/* ***************************************************************************/
+/** Set the channels to be triggered by an event. The for every channel that
+ *must be triggered by the event, the corresponding bit from channel_map
+ *parameter must be set to 1. (e.g. for the event to trigger channels 31 and
+ *0 one must pass 0x80000001)
+ *
+ *
+ * <b>Algorithm:</b>\n
+ * - Update the register from Channel Enable RAM with the channel_map
+ *
+ * @param event event for which to set the channel association
+ * @param channel_map channels to be triggered by event. Put the corresponding
+ * bit from this 32-bit value to 1 for every channel that should be
+ * triggered by the event.
+ *
+ * @return
+ * - IAPI_SUCCESS : OK
+ * - -iapi_errno : operation failed, return negated value of iapi_errno
+ */
+int
+iapi_lowSetChannelEventMapping(unsigned char event, unsigned long channel_map)
+{
+ volatile unsigned long * channelEnableMatx;
+ int result = IAPI_SUCCESS;
+
+ /* Check validity of event*/
+ if (event < EVENTS_NUM)
+ {
+ channelEnableMatx = &SDMA_CHNENBL_0;
+ channelEnableMatx[event] |= channel_map;
+ return result;
+ }
+ else
+ {
+ result = IAPI_ERR_INVALID_PARAMETER | event;
+ iapi_errno = result;
+ return -result;
+ }
+}
+
+#endif /* MCU */
diff --git a/arch/arm/plat-mxc/sdma/iapi/src/iapiMiddle.c b/arch/arm/plat-mxc/sdma/iapi/src/iapiMiddle.c
new file mode 100644
index 000000000000..b2423ed2fbd6
--- /dev/null
+++ b/arch/arm/plat-mxc/sdma/iapi/src/iapiMiddle.c
@@ -0,0 +1,623 @@
+/******************************************************************************
+ *
+ * Copyright 2007 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
+ *
+ ******************************************************************************
+ *
+ * File: iapiMiddle.c
+ *
+ * $Id iapiMiddle.c $
+ *
+ * Description:
+ * This library is written in C to guarantee functionality and integrity in
+ * the usage of SDMA virtual DMA channels. This API (Application Programming
+ * Interface) allow SDMA channels' access in an OPEN, READ, WRITE, CLOSE
+ * fashion.
+ * These are the MIDDLE level functions of the I.API.
+ *
+ *
+ *
+ *
+ * $Log iapiMiddle.c $
+ *
+ *****************************************************************************/
+
+
+/* ****************************************************************************
+ * Include File Section
+ *****************************************************************************/
+#include "epm.h"
+#include <string.h>
+
+#include "iapiLow.h"
+#include "iapiMiddle.h"
+
+/* ****************************************************************************
+ * Global Variable Section
+ *****************************************************************************/
+
+
+/* ****************************************************************************
+ * Function Section
+ *****************************************************************************/
+
+/* ***************************************************************************/
+/**Allocates one Buffer Descriptor structure using information present in the
+ * channel descriptor.
+ *
+ * @param *ccb_p channel control block used to get the channel descriptor
+ *
+ * @return
+ * - pointer on the new Buffer Descriptor
+ * - NULL if allocation failed
+ *
+ */
+bufferDescriptor *
+iapi_AllocBD (channelControlBlock * ccb_p)
+
+{
+ bufferDescriptor * ptrBD = NULL;
+
+ if (ccb_p->channelDescriptor->bufferDescNumber != 0){
+#ifdef CONFIG_SDMA_IRAM
+ channelDescriptor * cd_p = ccb_p->channelDescriptor;
+ if(cd_p->channelNumber >= MXC_DMA_CHANNEL_IRAM) {
+ ptrBD = (bufferDescriptor *)
+ MALLOC( ccb_p->channelDescriptor->bufferDescNumber *
+ sizeof(bufferDescriptor), SDMA_IRAM);
+ } else
+#endif /*CONFIG_SDMA_IRAM*/
+ {
+ ptrBD = (bufferDescriptor *)
+ MALLOC( ccb_p->channelDescriptor->bufferDescNumber *
+ sizeof(bufferDescriptor), SDMA_ERAM);
+ }
+ }
+ if (ptrBD != NULL) {
+ ptrBD->mode.command = 0;
+ ptrBD->mode.status = 0;
+ ptrBD->mode.count = 0;
+ ptrBD->bufferAddr = NULL;
+ }
+
+ return ptrBD;
+}
+
+/* ***************************************************************************/
+/**Allocate one channel context data structure.
+ *
+ * @param **ctxd_p pointer to context data to be allocated
+ * @param channel channel number of context data structure
+ *
+ * @return
+ * - IAPI_SUCCESS
+ * - -iapi_errno if allocation failed
+ */
+int
+iapi_AllocContext(contextData ** ctxd_p, unsigned char channel)
+{
+ contextData * ctxData;
+ int result = IAPI_SUCCESS;
+
+ if (*ctxd_p != NULL){
+ result = IAPI_ERR_CC_ALREADY_DEFINED | IAPI_ERR_CH_AVAILABLE | channel;
+ iapi_errno = result;
+ return -result;
+ }
+
+ ctxData = (contextData *)MALLOC(sizeof(contextData), SDMA_ERAM);
+
+ if (ctxData !=NULL) {
+ *ctxd_p = ctxData;
+ return IAPI_SUCCESS;
+
+ } else {
+ *ctxd_p = NULL;
+ result = IAPI_ERR_CC_ALLOC_FAILED | IAPI_ERR_CH_AVAILABLE | channel;
+ iapi_errno = result;
+ return -result;
+ }
+}
+
+/* ***************************************************************************/
+/**Allocates channel description and fill in with default values.
+ *
+ * <b>Algorithm:</b>\n
+ * - Check channel properties.
+ * - Then modifies the properties of the channel description with default
+ *
+ * @param **cd_p pointer to channel descriptor to be allocated
+ * @param channel channel number of channel descriptor
+ *
+ * @return
+ * - IAPI_SUCCESS
+ * - -iapi_errno if allocation failed
+ *
+ */
+int
+iapi_AllocChannelDesc (channelDescriptor ** cd_p, unsigned char channel)
+{
+#ifdef MCU
+ volatile unsigned long * chPriorities = &SDMA_CHNPRI_0;
+#endif /* MCU */
+ channelDescriptor * tmpCDptr;
+ int result = IAPI_SUCCESS;
+
+
+ if (*cd_p != NULL){
+ result = IAPI_ERR_CD_ALREADY_DEFINED | IAPI_ERR_CH_AVAILABLE | channel;
+ iapi_errno = result;
+ return -result;
+ }
+
+ tmpCDptr = (channelDescriptor *)MALLOC(sizeof(channelDescriptor), SDMA_ERAM);
+
+ if (tmpCDptr != NULL){
+ iapi_memcpy(tmpCDptr, &iapi_ChannelDefaults, sizeof (channelDescriptor));
+ tmpCDptr->channelNumber = channel;
+#ifdef MCU
+ if (chPriorities[channel] != 0) {
+ tmpCDptr->priority = chPriorities[channel];
+ } else {
+ chPriorities[channel] = tmpCDptr->priority;
+ }
+#endif
+ * cd_p = tmpCDptr ;
+ return IAPI_SUCCESS;
+ } else {
+ * cd_p = NULL;
+ result = IAPI_ERR_CD_ALLOC_FAILED | IAPI_ERR_CH_AVAILABLE | channel;
+ iapi_errno = result;
+ return -result;
+ }
+}
+
+/* ***************************************************************************/
+/**Changes channel description information after performing sanity checks.
+ *
+ * <b>Algorithm:</b>\n
+ * - Check channel properties.
+ * - Then modifies the properties of the channel description.
+ *
+ * @param *cd_p channel descriptor of the channel to change
+ * @param whatToChange control code indicating the desired change
+ * @param newval new value
+ *
+ * @return
+ * - IAPI_SUCCESS
+ * - IAPI_FAILURE if change failed
+ *
+ */
+int
+iapi_ChangeChannelDesc (channelDescriptor * cd_p, unsigned char whatToChange,
+ unsigned long newval)
+{
+ bufferDescriptor * tmpBDptr;
+ unsigned char index = 0;
+ int result = IAPI_SUCCESS;
+
+ /* verify parameter validity */
+ if (cd_p == NULL) {
+ result = IAPI_ERR_CD_UNINITIALIZED;
+ iapi_errno = result;
+ return -result;
+ }
+
+ /* verify channel descriptor initialization */
+ if (cd_p->ccb_ptr == NULL){
+ result = IAPI_ERR_CCB_UNINITIALIZED | IAPI_ERR_CH_AVAILABLE |
+ cd_p->channelNumber;
+ iapi_errno = result;
+ return -result;
+ }
+
+ /* verify channel is not in use */
+ tmpBDptr = (bufferDescriptor *)iapi_Phys2Virt(cd_p->ccb_ptr->baseBDptr);
+ for (index=cd_p->bufferDescNumber ; index>0 ; index--){
+ if (tmpBDptr->mode.status & BD_DONE){
+ result = IAPI_ERR_CH_IN_USE | IAPI_ERR_CH_AVAILABLE |
+ cd_p->channelNumber;
+ iapi_errno = result;
+ return -result;
+ }
+ tmpBDptr++;
+ }
+
+ /* Select the change accorded to the selector given in parameter */
+ switch (whatToChange){
+
+ /*
+ * Channel Number
+ */
+ case IAPI_CHANNELNUMBER:
+ /* Channel number can not be changed (description remains attached) */
+ result = IAPI_ERR_CD_CHANGE_CH_NUMBER | IAPI_ERR_CH_AVAILABLE |
+ cd_p->channelNumber;
+ iapi_errno = result;
+ return -result;
+
+ /*
+ * Buffer Descriptor Number
+ */
+ case IAPI_BUFFERDESCNUMBER:
+ if (newval < MAX_BD_NUM){
+ if (newval != cd_p->bufferDescNumber){
+ /* Free memory used for previous old data */
+ if (cd_p->ccb_ptr->baseBDptr != NULL){
+ tmpBDptr = (bufferDescriptor *)iapi_Phys2Virt(cd_p->ccb_ptr->baseBDptr);
+ for (index=0 ; index < cd_p->bufferDescNumber ; index++){
+ if (tmpBDptr->bufferAddr != NULL){
+ if (cd_p->trust == FALSE) {
+ FREE(iapi_Phys2Virt(tmpBDptr->bufferAddr));
+ }
+ }
+ tmpBDptr ++ ;
+ }
+ FREE((bufferDescriptor *)iapi_Phys2Virt((cd_p->ccb_ptr)->baseBDptr));
+ }
+ (cd_p->ccb_ptr)->baseBDptr = NULL;
+ (cd_p->ccb_ptr)->currentBDptr = NULL;
+ /* Allocate and initialize structures */
+ cd_p->bufferDescNumber = (unsigned char)newval;
+ cd_p->ccb_ptr->status.openedInit = FALSE;
+ if (IAPI_SUCCESS !=iapi_InitializeMemory (cd_p->ccb_ptr))
+ {
+ result = IAPI_ERR_BD_ALLOCATION | cd_p->channelNumber;
+ iapi_errno = result;
+ return -result;
+ }
+ cd_p->ccb_ptr->status.openedInit = TRUE;
+ }
+ break;
+ } else {
+ result = IAPI_ERR_INVALID_PARAMETER | IAPI_ERR_CH_AVAILABLE |
+ cd_p->channelNumber;
+ iapi_errno = result;
+ return -result;
+ }
+
+ /*
+ * Buffer size
+ */
+ case IAPI_BUFFERSIZE:
+ if (newval < MAX_BD_SIZE)
+ {
+ if (newval != cd_p->bufferSize)
+ {
+ /* Free memory used for previous old data */
+ if (cd_p->ccb_ptr->baseBDptr != NULL)
+ {
+ tmpBDptr = (bufferDescriptor *)iapi_Phys2Virt(cd_p->ccb_ptr->baseBDptr);
+ for (index=0 ; index < cd_p->bufferDescNumber ; index++)
+ {
+ if (cd_p->trust == FALSE)
+ {
+ FREE(iapi_Phys2Virt(tmpBDptr->bufferAddr));
+ }
+ tmpBDptr ++ ;
+ }
+ FREE((bufferDescriptor *)iapi_Phys2Virt((cd_p->ccb_ptr)->baseBDptr));
+ }
+ (cd_p->ccb_ptr)->baseBDptr = NULL;
+ (cd_p->ccb_ptr)->currentBDptr = NULL;
+ /* Allocate and initialize structures */
+ cd_p->bufferSize = (unsigned short)newval;
+ cd_p->ccb_ptr->status.openedInit = FALSE;
+ if (IAPI_SUCCESS !=iapi_InitializeMemory (cd_p->ccb_ptr))
+ {
+ result = IAPI_ERR_BD_ALLOCATION | cd_p->channelNumber;
+ iapi_errno = result;
+ return -result;
+ }
+ cd_p->ccb_ptr->status.openedInit = TRUE;
+ }
+ break;
+ }
+ else
+ {
+ result = IAPI_ERR_INVALID_PARAMETER | IAPI_ERR_CH_AVAILABLE |
+ cd_p->channelNumber;
+ iapi_errno = result;
+ return -result;
+ }
+
+
+ /*
+ * Blocking / non blocking feature
+ */
+ case IAPI_BLOCKING:
+ if (newval < MAX_BLOCKING){
+ cd_p->blocking = newval;
+ break;
+ } else {
+ result = IAPI_ERR_INVALID_PARAMETER | IAPI_ERR_CH_AVAILABLE |
+ cd_p->channelNumber;
+ iapi_errno = result;
+ return -result;
+ }
+
+ /*
+ * Synchronization method
+ */
+ case IAPI_CALLBACKSYNCH:
+ if (newval < MAX_SYNCH){
+ cd_p->callbackSynch = newval;
+ iapi_ChangeCallbackISR( cd_p, cd_p->callbackISR_ptr);
+ break;
+ } else {
+ result = IAPI_ERR_INVALID_PARAMETER | IAPI_ERR_CH_AVAILABLE |
+ cd_p->channelNumber;
+ iapi_errno = result;
+ return -result;
+ }
+
+
+ /*
+ * Ownership of the channel
+ */
+ case IAPI_OWNERSHIP:
+#ifdef DSP
+ result = IAPI_ERR_NOT_ALLOWED | cd_p->channelNumber;
+ iapi_errno = result;
+ return -result;
+#endif /* DSP */
+#ifdef MCU
+ if (newval < MAX_OWNERSHIP){
+ cd_p->ownership = newval;
+ iapi_ChannelConfig( cd_p->channelNumber,
+ ( newval >> CH_OWNSHP_OFFSET_EVT ) & 1,
+ ( newval >> CH_OWNSHP_OFFSET_MCU ) & 1,
+ ( newval >> CH_OWNSHP_OFFSET_DSP ) & 1);
+ break;
+ } else {
+ result = IAPI_ERR_INVALID_PARAMETER | IAPI_ERR_CH_AVAILABLE |
+ cd_p->channelNumber;
+ iapi_errno = result;
+ return -result;
+ }
+
+#endif /* MCU */
+
+ /*
+ * Priority
+ */
+ case IAPI_PRIORITY:
+#ifdef DSP
+ result = IAPI_ERR_NOT_ALLOWED | cd_p->channelNumber;
+ iapi_errno = result;
+ return -result;
+#endif /* DSP */
+
+#ifdef MCU
+ if (newval < MAX_CH_PRIORITY){
+ volatile unsigned long * ChannelPriorities = &SDMA_CHNPRI_0;
+ ChannelPriorities[ cd_p->channelNumber ] = newval;
+ break;
+ } else {
+ result = IAPI_ERR_INVALID_PARAMETER | IAPI_ERR_CH_AVAILABLE |
+ cd_p->channelNumber;
+ iapi_errno = result;
+ return -result;
+ }
+#endif /* MCU */
+
+
+ /*
+ * "Trust" property
+ */
+ case IAPI_TRUST:
+ if (newval < MAX_TRUST){
+ if (cd_p->trust != newval){
+ cd_p->trust = newval;
+ if (newval == FALSE) {
+ if (IAPI_SUCCESS !=iapi_InitializeMemory (cd_p->ccb_ptr))
+ {
+ result = IAPI_ERR_BD_ALLOCATION | cd_p->channelNumber;
+ iapi_errno = result;
+ return -result;
+ }
+ }
+ }
+ break;
+ } else {
+ result = IAPI_ERR_INVALID_PARAMETER | IAPI_ERR_CH_AVAILABLE |
+ cd_p->channelNumber;
+ iapi_errno = result;
+ return -result;
+ }
+
+ /*
+ * Callback function pointer
+ */
+ case IAPI_CALLBACKISR_PTR:
+ if ( (void *)newval != NULL){
+ {
+ union {
+ void * voidstar;
+ void (* funcptr)(channelDescriptor * cd_p, void * arg);
+ } value;
+ value.voidstar = (void*) newval;
+ cd_p->callbackISR_ptr = value.funcptr;
+ }
+ iapi_ChangeCallbackISR( cd_p, cd_p->callbackISR_ptr);
+ break;
+ } else {
+ result = IAPI_ERR_INVALID_PARAMETER | IAPI_ERR_CH_AVAILABLE |
+ cd_p->channelNumber;
+ iapi_errno = result;
+ return -result;
+ }
+
+
+ /*
+ * Channel Control Block pointer
+ */
+ case IAPI_CCB_PTR:
+ cd_p->ccb_ptr = (channelControlBlock *)newval;
+ cd_p->ccb_ptr->channelDescriptor = cd_p;
+ break;
+
+ /*
+ * WRAP/UNWRAP
+ */
+ case IAPI_BDWRAP:
+ /* point to first BD */
+ tmpBDptr = (bufferDescriptor *)iapi_Phys2Virt(cd_p->ccb_ptr->baseBDptr);
+ /* to point to last BD */
+ tmpBDptr += cd_p->bufferDescNumber - 1;
+ if (newval == TRUE){
+ /* wrap last BD */
+ tmpBDptr->mode.status |= BD_WRAP;
+ break;
+ }
+ else if (newval == FALSE){
+ /* unwrap last BD */
+ tmpBDptr->mode.status &= ~BD_WRAP;
+ break;
+ }
+ else {
+ result = IAPI_ERR_INVALID_PARAMETER | IAPI_ERR_CH_AVAILABLE |
+ cd_p->channelNumber;
+ iapi_errno = result;
+ return -result;
+ }
+
+
+ /*
+ * Watermark level
+ */
+ case IAPI_WML:
+#ifdef DSP
+ result = IAPI_ERR_NOT_ALLOWED | cd_p->channelNumber;
+ iapi_errno = result;
+ return -result;
+#endif /* DSP */
+#ifdef MCU
+ if (newval < MAX_WML){
+ if (cd_p->watermarkLevel != newval){
+ cd_p->watermarkLevel = newval;
+ }
+ break;
+ }
+ else {
+ result = IAPI_ERR_INVALID_PARAMETER | IAPI_ERR_CH_AVAILABLE |
+ cd_p->channelNumber;
+ iapi_errno = result;
+ return -result;
+ }
+#endif /* MCU */
+
+ /*
+ * Detect errors
+ */
+ default:
+ result = IAPI_ERR_CD_CHANGE_UNKNOWN | IAPI_ERR_CH_AVAILABLE |
+ cd_p->channelNumber;
+ iapi_errno = result;
+ return -result;
+ }
+
+ return IAPI_SUCCESS;
+}
+
+
+/* ***************************************************************************/
+/**Initialize a table of function pointers that contain the interrupt Service
+ * Routine callback pointers for the SDMA channels with a default value
+ *
+ * <b>Algorithm:</b>\n
+ * - Loop on each element of the global IAPI variable callbackIsrTable
+ *
+ * @param *func_p default callback functon for all SDMA channels
+ *
+ * @return none
+ */
+void
+iapi_InitializeCallbackISR(void(* func_p)(channelDescriptor * cd_p, void * arg))
+{
+ unsigned long chCnt;
+
+ for (chCnt = 0 ; chCnt < CH_NUM ; chCnt++){
+ callbackIsrTable[chCnt] = func_p;
+ }
+}
+
+/* ***************************************************************************/
+/**For the specified channel control block, attach the array of buffer
+ * descriptors, the channel description structure and initialize channel's
+ * status using information in the channel descriptor.
+ *
+ * @param *ccb_p pointer to channel control block
+ *
+ * @return none
+ *
+ */
+int
+iapi_InitializeMemory (channelControlBlock * ccb_p)
+{
+ bufferDescriptor * bd_p;
+ unsigned char index;
+ int result = IAPI_SUCCESS;
+
+ /* Attach the array of Buffer descriptors */
+ bd_p = iapi_AllocBD( ccb_p );
+ if (bd_p != NULL)
+ {
+ ccb_p->baseBDptr = (bufferDescriptor *)iapi_Virt2Phys(bd_p);
+ ccb_p->currentBDptr = ccb_p->baseBDptr;
+ for(index=0 ;index < ccb_p->channelDescriptor->bufferDescNumber-1 ; index++)
+ {
+ if (ccb_p->channelDescriptor->trust == TRUE)
+ {
+ iapi_SetBufferDescriptor(bd_p,
+ (unsigned char)ccb_p->channelDescriptor->dataSize,
+ BD_CONT|BD_EXTD, ccb_p->channelDescriptor->bufferSize,
+ NULL, NULL);
+ }
+ else
+ {
+ if (ccb_p->channelDescriptor->bufferSize != 0)
+ {
+ iapi_SetBufferDescriptor(bd_p,
+ (unsigned char)ccb_p->channelDescriptor->dataSize,
+ BD_CONT|BD_EXTD, ccb_p->channelDescriptor->bufferSize,
+ MALLOC(ccb_p->channelDescriptor->bufferSize, SDMA_ERAM), NULL);
+ }
+ }
+ bd_p++;
+ }
+
+ if (ccb_p->channelDescriptor->trust == TRUE)
+ {
+ iapi_SetBufferDescriptor(bd_p,
+ (unsigned char)ccb_p->channelDescriptor->dataSize,
+ BD_EXTD|BD_WRAP|BD_INTR, ccb_p->channelDescriptor->bufferSize,
+ NULL, NULL);
+ }
+ else
+ {
+ if (ccb_p->channelDescriptor->bufferSize != 0)
+ {
+ iapi_SetBufferDescriptor(bd_p,
+ (unsigned char)ccb_p->channelDescriptor->dataSize,
+ BD_EXTD|BD_WRAP|BD_INTR,
+ ccb_p->channelDescriptor->bufferSize,
+ MALLOC(ccb_p->channelDescriptor->bufferSize, SDMA_ERAM), NULL);
+ }
+ }
+ }
+ else
+ {
+ result = IAPI_ERR_BD_ALLOCATION;
+ return -result;
+ }
+ return result;
+}
diff --git a/arch/arm/plat-mxc/sdma/iapi/src/iapiMiddleMcu.c b/arch/arm/plat-mxc/sdma/iapi/src/iapiMiddleMcu.c
new file mode 100644
index 000000000000..8dc814418e4c
--- /dev/null
+++ b/arch/arm/plat-mxc/sdma/iapi/src/iapiMiddleMcu.c
@@ -0,0 +1,52 @@
+/******************************************************************************
+ *
+ * Copyright 2007 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
+ *
+ ******************************************************************************
+ *
+ * File: iapiMiddleMcu.c
+ *
+ * $Id iapiMiddleMcu.c $
+ *
+ * Description:
+ * This library is written in C to guarantee functionality and integrity in
+ * the usage of SDMA virtual DMA channels. This API (Application Programming
+ * Interface) allow SDMA channels' access in an OPEN, READ, WRITE, CLOSE
+ * fashion.
+ * These are the MIDDLE level functions of the I.API specific to MCU.
+ *
+ *
+ *
+ *
+ * $Log iapiMiddleMcu.c $
+ *
+ *****************************************************************************/
+
+/* ****************************************************************************
+ * Include File Section
+ *****************************************************************************/
+#include "epm.h"
+#include <string.h>
+
+#include "iapiLow.h"
+#include "iapiMiddle.h"
+
+/* ****************************************************************************
+ * Global Variable Section
+ *****************************************************************************/
+
+/*extern void * __HEAP_START;
+extern void * __HEAP_END;
+*/
+
+/* ****************************************************************************
+ * Function Section
+ *****************************************************************************/
diff --git a/arch/arm/plat-mxc/sdma/iapi/src/iapiOS.c b/arch/arm/plat-mxc/sdma/iapi/src/iapiOS.c
new file mode 100644
index 000000000000..643cab549742
--- /dev/null
+++ b/arch/arm/plat-mxc/sdma/iapi/src/iapiOS.c
@@ -0,0 +1,64 @@
+/******************************************************************************
+ *
+ * Copyright 2007 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
+ *
+ ******************************************************************************
+ *
+ * File: iapiOS.c
+ *
+ * $Id iapiOS.c $
+ *
+ * Description:
+ * This library is written in C to guarantee functionality and integrity in
+ * the usage of SDMA virtual DMA channels. This API (Application Programming
+ * Interface) allow SDMA channels' access in an OPEN, READ, WRITE, CLOSE
+ * fashion.
+ * These are the OS level functions of the I.API - are OS dependant and must
+ * be provided by the user of I.API.
+ *
+ *
+ * /
+ *
+ * $Log iapiOS.c $
+ *
+ *****************************************************************************/
+
+/* ****************************************************************************
+ * Include File Section
+ *****************************************************************************/
+#include "epm.h"
+#include "iapiLow.h"
+
+/**
+ * Function Section
+ */
+#ifdef CONFIG_SDMA_IRAM
+void*(* iapi_iram_Malloc) (size_t size);
+#endif /*CONFIG_SDMA_IRAM*/
+
+void*(* iapi_Malloc) (size_t size);
+void (* iapi_Free) (void * ptr);
+
+void*(* iapi_Virt2Phys) (void * ptr);
+void*(* iapi_Phys2Virt) (void * ptr);
+
+void (* iapi_WakeUp)(int);
+void (* iapi_GotoSleep)(int);
+void (* iapi_InitSleep)(int);
+
+void*(* iapi_memcpy)(void *dest, const void *src, size_t count);
+void*(* iapi_memset)(void *dest, int c, size_t count);
+
+void (* iapi_EnableInterrupts)(void);
+void (* iapi_DisableInterrupts)(void);
+
+int (* iapi_GetChannel)(int);
+int (* iapi_ReleaseChannel)(int);
diff --git a/arch/arm/plat-mxc/sdma/sdma.c b/arch/arm/plat-mxc/sdma/sdma.c
new file mode 100644
index 000000000000..6bdce3375134
--- /dev/null
+++ b/arch/arm/plat-mxc/sdma/sdma.c
@@ -0,0 +1,1481 @@
+/*
+ * Copyright 2004-2009 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
+ */
+
+/*!
+ * @file plat-mxc/sdma/sdma.c
+ * @brief This file contains functions for Smart DMA API
+ *
+ * SDMA (Smart DMA) is used for transferring data between MCU and peripherals
+ *
+ * @ingroup SDMA
+ */
+
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+#include <linux/clk.h>
+#include <linux/semaphore.h>
+#include <linux/spinlock.h>
+#include <linux/device.h>
+#include <linux/dma-mapping.h>
+#include <linux/proc_fs.h>
+
+#include <asm/uaccess.h>
+#include <asm/irq.h>
+#include <mach/dma.h>
+#include <mach/hardware.h>
+
+#include "iapi.h"
+
+#define M3_BASE_ADDRESS CSD0_BASE_ADDR
+#define CHAD(ch) sdma_data[0].cd->ccb_ptr[ch].channelDescriptor
+
+/*!
+ * SDMA status mutex
+ */
+static struct semaphore sdma_status_mutex;
+
+/*!
+ * SDMA channel sleep queues
+ */
+//static struct semaphore sdma_sleep_mutex[MAX_DMA_CHANNELS];
+static wait_queue_head_t sdma_sleep_queue[MAX_DMA_CHANNELS];
+
+/*!
+ * SDMA channel synchronization
+ */
+static struct semaphore sdma_synch_mutex[MAX_DMA_CHANNELS];
+
+/*!
+ * SDMA buffers pool initialization function
+ */
+extern void init_sdma_pool(void);
+
+/*!
+ * Flags are save and restored during interrupt handler
+ */
+unsigned long flags;
+
+struct clk *mxc_sdma_ahb_clk, *mxc_sdma_ipg_clk;
+
+/*!
+ * Structure containing sdma channels information.
+ */
+typedef struct {
+ /*! Channel number */
+ int channel;
+ /*! Channel usage name */
+ int in_use;
+ /*! Name of device using the channel */
+ char devicename[MAX_DEVNAME_LENGTH];
+ /*! Transfer type. Needed for setting SDMA script */
+ sdma_transferT transfer_type;
+ /*! Peripheral type. Needed for setting SDMA script */
+ sdma_periphT peripheral_type;
+ /*! Watermark level of device's fifo */
+ __u32 watermark_level;
+ /*! Peripheral event id */
+ int event_id;
+ /*! Peripheral event id2 (for channels that use 2 events) */
+ int event_id2;
+ /*! Running status (boolean) */
+ int running;
+ /*! buffer descriptors number */
+ int bd_number;
+ /*! callback function */
+ dma_callback_t callback;
+ /*! callback argument */
+ void *arg;
+ /*! SDMA data access word size */
+ unsigned long word_size:8;
+ /*! channel descriptor pointer */
+ channelDescriptor *cd;
+} sdma_struct;
+
+/*!
+ * Used to save the status of channels.
+ */
+static sdma_struct sdma_data[MAX_DMA_CHANNELS];
+
+/*!
+ * Stores the start address of the SDMA scripts
+ */
+static sdma_script_start_addrs sdma_script_addrs;
+
+extern void mxc_sdma_get_script_info(sdma_script_start_addrs * sdma_script_add);
+
+/*!
+ * Init sleep mutex of the channel
+ *
+ * @param channel channel number
+ */
+static void sdma_init_sleep(int channel)
+{
+ init_waitqueue_head(&sdma_sleep_queue[channel]);
+}
+
+/*!
+ * Puts channel to sleep
+ *
+ * @param channel channel number
+ */
+static void sdma_sleep_channel(int channel)
+{
+ while ((iapi_SDMAIntr & (1 << channel)) == 0) {
+ wait_event_interruptible(sdma_sleep_queue[channel],
+ ((iapi_SDMAIntr & (1 << channel)) !=
+ 0));
+ }
+}
+
+/*!
+ * Wake up channel from sleep
+ *
+ * @param channel channel number
+ */
+static void sdma_wakeup_channel(int channel)
+{
+ wake_up_interruptible(&sdma_sleep_queue[channel]);
+}
+
+/*!
+ * Sdma interrupt handler routine.
+ * Calls channels callback function
+ *
+ * @param irq the interrupt number
+ * @param dev_id driver private data
+ * @return the function returns \b IRQ_RETVAL(1) - interrupt was handled
+ */
+static irqreturn_t sdma_int_handler(int irq, void *dev_id)
+{
+ IRQ_Handler();
+ return IRQ_RETVAL(1);
+}
+
+/*!
+ * I.API channel callback function
+ *
+ * @param cd channel descriptor structure
+ * @param channel_data SDMA struct of the current channel
+ */
+static void iapi_interrupt_callback(channelDescriptor * cd,
+ sdma_struct * channel_data)
+{
+ int channel;
+ dma_callback_t callback;
+ void *arg;
+
+ channel = channel_data->channel;
+
+ channel_data->running = 0;
+
+ arg = channel_data->arg;
+
+ if (arg == 0) {
+ arg = (void *)&channel;
+ }
+
+ callback = channel_data->callback;
+
+ if (callback != 0) {
+ callback(arg);
+ }
+}
+
+/*!
+ * Returns pc of SDMA script according to peripheral and transfer type
+ *
+ * @param peripheral_type peripheral type
+ * @param transfer_type transfer type
+ *
+ * @return PC of SDMA script
+*/
+static unsigned short sdma_get_pc(sdma_periphT peripheral_type,
+ sdma_transferT transfer_type)
+{
+ int res = 0;
+
+ if (peripheral_type == MEMORY) {
+ switch (transfer_type) {
+ case emi_2_int:
+ res = sdma_script_addrs.mxc_sdma_ap_2_ap_addr;
+ break;
+ case emi_2_emi:
+ res = sdma_script_addrs.mxc_sdma_ap_2_ap_addr;
+ break;
+ case int_2_emi:
+ res = sdma_script_addrs.mxc_sdma_ap_2_ap_addr;
+ break;
+ default:
+ res = -EINVAL;
+ }
+ } else if (peripheral_type == DSP) {
+ switch (transfer_type) {
+ case emi_2_dsp:
+ res = sdma_script_addrs.mxc_sdma_ap_2_bp_addr;
+ break;
+ case dsp_2_emi:
+ res = sdma_script_addrs.mxc_sdma_bp_2_ap_addr;
+ break;
+ case dsp_2_emi_loop:
+ res =
+ sdma_script_addrs.
+ mxc_sdma_loopback_on_dsp_side_addr;
+ break;
+ case emi_2_dsp_loop:
+ res =
+ sdma_script_addrs.mxc_sdma_mcu_interrupt_only_addr;
+ break;
+ default:
+ res = -EINVAL;
+ }
+ } else if (peripheral_type == FIRI) {
+ switch (transfer_type) {
+ case per_2_int:
+ res = sdma_script_addrs.mxc_sdma_firi_2_per_addr;
+ break;
+ case per_2_emi:
+ res = sdma_script_addrs.mxc_sdma_firi_2_mcu_addr;
+ break;
+ case int_2_per:
+ res = sdma_script_addrs.mxc_sdma_per_2_firi_addr;
+ break;
+ case emi_2_per:
+ res = sdma_script_addrs.mxc_sdma_mcu_2_firi_addr;
+ break;
+ default:
+ res = -EINVAL;
+ }
+ } else if (peripheral_type == UART) {
+ switch (transfer_type) {
+ case per_2_int:
+ res = sdma_script_addrs.mxc_sdma_uart_2_per_addr;
+ break;
+ case per_2_emi:
+ res = sdma_script_addrs.mxc_sdma_uart_2_mcu_addr;
+ break;
+ case int_2_per:
+ res = sdma_script_addrs.mxc_sdma_per_2_app_addr;
+ break;
+ case emi_2_per:
+ res = sdma_script_addrs.mxc_sdma_mcu_2_app_addr;
+ break;
+ default:
+ res = -EINVAL;
+ }
+ } else if (peripheral_type == UART_SP) {
+ switch (transfer_type) {
+ case per_2_int:
+ res = sdma_script_addrs.mxc_sdma_uartsh_2_per_addr;
+ break;
+ case per_2_emi:
+ res = sdma_script_addrs.mxc_sdma_uartsh_2_mcu_addr;
+ break;
+ case int_2_per:
+ res = sdma_script_addrs.mxc_sdma_per_2_shp_addr;
+ break;
+ case emi_2_per:
+ res = sdma_script_addrs.mxc_sdma_mcu_2_shp_addr;
+ break;
+ default:
+ res = -EINVAL;
+ }
+ } else if (peripheral_type == ATA) {
+ switch (transfer_type) {
+ case per_2_emi:
+ res = sdma_script_addrs.mxc_sdma_ata_2_mcu_addr;
+ break;
+ case emi_2_per:
+ res = sdma_script_addrs.mxc_sdma_mcu_2_ata_addr;
+ break;
+ default:
+ res = -EINVAL;
+ }
+ } else if (peripheral_type == CSPI || peripheral_type == EXT ||
+ peripheral_type == SSI) {
+ switch (transfer_type) {
+ case per_2_int:
+ res = sdma_script_addrs.mxc_sdma_app_2_per_addr;
+ break;
+ case per_2_emi:
+ res = sdma_script_addrs.mxc_sdma_app_2_mcu_addr;
+ break;
+ case int_2_per:
+ res = sdma_script_addrs.mxc_sdma_per_2_app_addr;
+ break;
+ case emi_2_per:
+ res = sdma_script_addrs.mxc_sdma_mcu_2_app_addr;
+ break;
+ default:
+ res = -EINVAL;
+ }
+ } else if (peripheral_type == SSI_SP || peripheral_type == MMC ||
+ peripheral_type == SDHC || peripheral_type == CSPI_SP ||
+ peripheral_type == ESAI || peripheral_type == MSHC_SP) {
+ switch (transfer_type) {
+ case per_2_int:
+ res = sdma_script_addrs.mxc_sdma_shp_2_per_addr;
+ break;
+ case per_2_emi:
+ res = sdma_script_addrs.mxc_sdma_shp_2_mcu_addr;
+ break;
+ case int_2_per:
+ res = sdma_script_addrs.mxc_sdma_per_2_shp_addr;
+ break;
+ case emi_2_per:
+ res = sdma_script_addrs.mxc_sdma_mcu_2_shp_addr;
+ break;
+ default:
+ res = -EINVAL;
+ }
+ } else if (peripheral_type == ASRC) {
+ switch (transfer_type) {
+ case per_2_emi:
+ res = sdma_script_addrs.mxc_sdma_asrc_2_mcu_addr;
+ break;
+ case emi_2_per:
+ res = sdma_script_addrs.mxc_sdma_asrc_2_mcu_addr;
+ break;
+ case per_2_per:
+ res = sdma_script_addrs.mxc_sdma_per_2_per_addr;
+ break;
+ default:
+ res = -EINVAL;
+ }
+ } else if (peripheral_type == MSHC) {
+ switch (transfer_type) {
+ case per_2_emi:
+ res = sdma_script_addrs.mxc_sdma_mshc_2_mcu_addr;
+ break;
+ case emi_2_per:
+ res = sdma_script_addrs.mxc_sdma_mcu_2_mshc_addr;
+ break;
+ default:
+ res = -EINVAL;
+ }
+ } else if (peripheral_type == CCM) {
+ switch (transfer_type) {
+ case per_2_emi:
+ res = sdma_script_addrs.mxc_sdma_dptc_dvfs_addr;
+ break;
+ default:
+ res = -EINVAL;
+ }
+ } else if (peripheral_type == FIFO_MEMORY) {
+ res = sdma_script_addrs.mxc_sdma_ap_2_ap_fixed_addr;
+ } else if (peripheral_type == SPDIF) {
+ switch (transfer_type) {
+ case per_2_emi:
+ res = sdma_script_addrs.mxc_sdma_spdif_2_mcu_addr;
+ break;
+ case emi_2_per:
+ res = sdma_script_addrs.mxc_sdma_mcu_2_spdif_addr;
+ break;
+ default:
+ res = -EINVAL;
+ }
+ } else if (peripheral_type == IPU_MEMORY) {
+ if (transfer_type == emi_2_per) {
+ res = sdma_script_addrs.mxc_sdma_ext_mem_2_ipu_addr;
+ } else {
+ res = -EINVAL;
+ }
+ }
+
+ if (res < 0) {
+ printk(KERN_ERR "SDMA script not found\n");
+ }
+
+ return res;
+
+}
+
+static inline int sdma_asrc_set_info(dma_channel_params *p,
+ script_data *pcontext, int eflags)
+{
+ dma_channel_ext_params *ep = (dma_channel_ext_params *) p;
+ unsigned int wml, tmp, wml1, wml2;
+ struct dma_channel_asrc_info *info = &(ep->info.asrc);
+ wml = 0;
+ if (p->transfer_type == per_2_per) {
+ if (!p->ext)
+ return wml;
+ wml1 = p->watermark_level;
+ wml2 = ep->watermark_level2;
+ if (info->channs) {
+ wml |= (info->channs & SDMA_ASRC_INFO_N_MASK) <<
+ SDMA_ASRC_INFO_N_OFF;
+ if (ep->p2p_dir)
+ wml2 *= info->channs & SDMA_ASRC_INFO_N_MASK;
+ else
+ wml1 *= info->channs & SDMA_ASRC_INFO_N_MASK;
+ }
+ if (info->channs & 1) {
+ if (ep->p2p_dir)
+ wml |= SDMA_ASRC_P2P_INFO_PS;
+ else
+ wml |= SDMA_ASRC_P2P_INFO_PA;
+ }
+ if (wml1 > wml2) {
+ tmp = wml2 & SDMA_ASRC_P2P_INFO_LWML_MASK;
+ wml |= tmp << SDMA_ASRC_P2P_INFO_LWML_OFF;
+ tmp = wml1 & SDMA_ASRC_P2P_INFO_HWML_MASK;
+ wml |= tmp << SDMA_ASRC_P2P_INFO_HWML_OFF;
+ if (eflags & (1 << 31))
+ wml |= SDMA_ASRC_P2P_INFO_LWE;
+ if (eflags & (1 << 30))
+ wml |= SDMA_ASRC_P2P_INFO_HWE;
+ } else {
+ tmp = wml1 & SDMA_ASRC_P2P_INFO_LWML_MASK;
+ wml |= tmp << SDMA_ASRC_P2P_INFO_LWML_OFF;
+ tmp = wml2 & SDMA_ASRC_P2P_INFO_HWML_MASK;
+ wml |= tmp << SDMA_ASRC_P2P_INFO_HWML_OFF;
+ wml |= eflags >> 2;
+ tmp = pcontext->event_mask2;
+ pcontext->event_mask2 = pcontext->event_mask1;
+ pcontext->event_mask1 = tmp;
+ }
+ } else {
+ if (p->ext && info->channs) {
+ wml |= (info->channs & SDMA_ASRC_INFO_N_MASK) <<
+ SDMA_ASRC_INFO_N_OFF;
+ tmp = (info->channs * p->watermark_level) &
+ SDMA_ASRC_INFO_WML_MASK;
+ wml |= tmp << SDMA_ASRC_INFO_WML_OFF;
+ } else {
+ tmp = (p->watermark_level & SDMA_ASRC_INFO_WML_MASK);
+ wml |= tmp << SDMA_ASRC_INFO_WML_OFF;
+ }
+
+ if (p->transfer_type == per_2_emi)
+ wml |= SDMA_ASRC_INFO_TXFR_DIR;
+
+ if (p->ext && (info->channs & 1)) {
+ if (p->transfer_type == per_2_emi)
+ wml |= SDMA_ASRC_INFO_PS;
+ else
+ wml |= SDMA_ASRC_INFO_PA;
+ }
+ wml |= eflags;
+ }
+ return wml;
+}
+
+/*!
+ * Downloads channel context according to channel parameters
+ *
+ * @param channel channel number
+ * @param p channel parameters
+ */
+static int sdma_load_context(int channel, dma_channel_params * p)
+{
+ script_data context;
+ int res;
+ int event1_greater_than_32;
+ int event2_greater_than_32;
+ dma_channel_ext_params *ep = (dma_channel_ext_params *) p;
+
+ res = 0;
+
+ memset(&context, 0, sizeof(script_data));
+ context.load_address = sdma_get_pc(p->peripheral_type,
+ p->transfer_type);
+
+ if (context.load_address > 0) {
+ if ((p->peripheral_type != MEMORY)
+ && (p->peripheral_type != DSP)) {
+ /* Handle multiple event channels differently */
+ if (p->event_id2) {
+ if (p->event_id2 < 32) {
+ context.event_mask2 =
+ 0x1 << p->event_id2;
+ event2_greater_than_32 = 0;
+ } else {
+ context.event_mask2 =
+ 0x1 << (p->event_id2 - 32);
+ event2_greater_than_32 = 1 << 31;
+ }
+ if (p->event_id < 32) {
+ context.event_mask1 =
+ 0x1 << p->event_id;
+ event1_greater_than_32 = 0;
+ } else {
+ context.event_mask1 =
+ 0x1 << (p->event_id - 32);
+ event1_greater_than_32 = 1 << 30;
+ }
+ } else {
+ event1_greater_than_32 = 0;
+ event2_greater_than_32 = 0;
+ if (p->event_id < 32) {
+ context.event_mask1 =
+ 0x1 << p->event_id;
+ context.event_mask2 = 0;
+ } else {
+ context.event_mask1 = 0;
+ context.event_mask2 =
+ 0x1 << (p->event_id - 32);
+ }
+ }
+
+ if (p->ext)
+ context.wml = ep->info_bits;
+ /* Watermark Level */
+ if (p->peripheral_type == ASRC) {
+ context.wml |= sdma_asrc_set_info(p,
+ &context,
+ event2_greater_than_32
+ |
+ event1_greater_than_32);
+ } else
+ context.wml |= event2_greater_than_32 |
+ event1_greater_than_32 | p->watermark_level;
+
+ /* Address */
+ context.shp_addr = (unsigned long)(p->per_address);
+ if (p->ext)
+ context.per_addr = ep->per_address2;
+ iapi_IoCtl(sdma_data[channel].cd,
+ IAPI_CHANGE_PERIPHADDR, p->per_address);
+ } else {
+ context.wml = M3_BASE_ADDRESS;
+ }
+
+ sdma_data[channel].transfer_type = p->transfer_type;
+ sdma_data[channel].peripheral_type = p->peripheral_type;
+ sdma_data[channel].watermark_level = p->watermark_level;
+ iapi_AssignScript(sdma_data[channel].cd, &context);
+ } else {
+ res = context.load_address;
+ }
+
+ return res;
+}
+
+/*!
+ * Setup channel according to parameters. Must be called once after mxc_request_dma()
+ *
+ * @param channel channel number
+ * @param p channel parameters pointer
+ * @return 0 on success, error code on fail
+ */
+int mxc_dma_setup_channel(int channel, dma_channel_params * p)
+{
+ int err = 0;
+ int i;
+
+ mxc_dma_stop(channel);
+
+ for (i = 0; i < sdma_data[channel].bd_number; i++) {
+ iapi_IoCtl(sdma_data[channel].cd,
+ (i << BD_NUM_OFFSET) |
+ IAPI_CHANGE_SET_STATUS, (unsigned long)0);
+ }
+
+ sdma_data[channel].bd_number = (p->bd_number <= 0) ? 1 : p->bd_number;
+
+ sdma_data[channel].word_size = p->word_size;
+
+ sdma_data[channel].event_id = p->event_id;
+ sdma_data[channel].event_id2 = p->event_id2;
+
+ sdma_data[channel].callback = p->callback;
+
+ sdma_data[channel].arg = p->arg;
+
+ err = iapi_IoCtl(sdma_data[channel].cd,
+ IAPI_CHANGE_BDNUM, sdma_data[channel].bd_number);
+
+ if (err < 0) {
+ printk(KERN_ERR "Failed allocating buffer \
+descriptors (0x%x)\n", err);
+ err = -ENOMEM;
+ goto setup_channel_fail;
+ }
+
+ if (channel != 0) {
+ switch (p->transfer_type) {
+ case dsp_2_per:
+ break;
+ case emi_2_per:
+ case int_2_per:
+ case per_2_int:
+ case per_2_emi:
+ case per_2_per:
+ /*
+ * Peripheral <------> Memory
+ * evtOvr = 0 dspOvr = 1
+ */
+ iapi_IoCtl(sdma_data[channel].cd, IAPI_CHANGE_OWNERSHIP,
+ (OWN_CHANNEL << CH_OWNSHP_OFFSET_EVT) |
+ (OWN_CHANNEL << CH_OWNSHP_OFFSET_MCU) |
+ (DONT_OWN_CHANNEL << CH_OWNSHP_OFFSET_DSP));
+ if (p->event_id) {
+ err = iapi_SetChannelEventMapping(p->event_id,
+ 0x1 <<
+ channel);
+ }
+ if (!err && p->event_id2) {
+ err = iapi_SetChannelEventMapping(p->event_id2,
+ 0x1 <<
+ channel);
+ }
+ break;
+ case emi_2_dsp:
+ case int_2_dsp:
+ case dsp_2_int:
+ case dsp_2_emi:
+ case dsp_2_dsp:
+ /*
+ * DSP <-----------> Memory
+ * evtOvr = 1 dspOvr = 0
+ */
+ iapi_IoCtl(sdma_data[channel].cd, IAPI_CHANGE_OWNERSHIP,
+ (DONT_OWN_CHANNEL << CH_OWNSHP_OFFSET_EVT) |
+ (OWN_CHANNEL << CH_OWNSHP_OFFSET_MCU) |
+ (OWN_CHANNEL << CH_OWNSHP_OFFSET_DSP));
+ break;
+ case emi_2_int:
+ case emi_2_emi:
+ case int_2_int:
+ case int_2_emi:
+ case emi_2_dsp_loop:
+ case dsp_2_emi_loop:
+ /* evtOvr = 1 dspOvr = 1 */
+ iapi_IoCtl(sdma_data[channel].cd, IAPI_CHANGE_OWNERSHIP,
+ (DONT_OWN_CHANNEL << CH_OWNSHP_OFFSET_EVT) |
+ (OWN_CHANNEL << CH_OWNSHP_OFFSET_MCU) |
+ (DONT_OWN_CHANNEL << CH_OWNSHP_OFFSET_DSP));
+ break;
+ case per_2_dsp:
+ /* evtOvr = 0 dspOvr = 0 */
+ iapi_IoCtl(sdma_data[channel].cd, IAPI_CHANGE_OWNERSHIP,
+ (OWN_CHANNEL << CH_OWNSHP_OFFSET_EVT) |
+ (DONT_OWN_CHANNEL << CH_OWNSHP_OFFSET_MCU) |
+ (OWN_CHANNEL << CH_OWNSHP_OFFSET_DSP));
+ err = iapi_SetChannelEventMapping(p->event_id,
+ 0x1 << channel);
+ break;
+ default:
+ break;
+ printk(KERN_ERR "Wrong SDMA transfer type\n");
+ err = -EINVAL;
+ }
+ if (err == 0) {
+ err = sdma_load_context(channel, p);
+ iapi_IoCtl(sdma_data[channel].cd, IAPI_CHANGE_PRIORITY,
+ MXC_SDMA_DEFAULT_PRIORITY);
+ }
+ }
+ setup_channel_fail:
+ return err;
+}
+
+/*!
+ * Setup the channel priority. This can be used to change the default priority
+ * for the channel.
+ *
+ * @param channel channel number
+ * @param priority priority to be set for the channel
+ *
+ * @return 0 on success, error code on failure
+ */
+int mxc_dma_set_channel_priority(unsigned int channel, unsigned int priority)
+{
+ if (priority < MXC_SDMA_MIN_PRIORITY
+ || priority > MXC_SDMA_MAX_PRIORITY) {
+ return -EINVAL;
+ }
+ return iapi_IoCtl(sdma_data[channel].cd, IAPI_CHANGE_PRIORITY,
+ priority);
+}
+
+/*!
+ * Allocates dma channel.
+ * If channel's value is 0, then the function allocates a free channel
+ * dynamically and sets its value to channel.
+ * Else allocates requested channel if it is free.
+ * If the channel is busy or no free channels (in dynamic allocation) -EBUSY returned.
+ *
+ * @param channel pointer to channel number
+ * @param devicename device name
+ * @return 0 on success, error code on fail
+ */
+int mxc_request_dma(int *channel, const char *devicename)
+{
+ int i, res;
+
+ res = 0;
+
+ down(&sdma_status_mutex);
+
+ /* Dynamic allocation */
+ if (*channel == 0) {
+ for (i = MAX_DMA_CHANNELS - 1; i > 0; i--) {
+#ifdef CONFIG_SDMA_IRAM
+ /*TODO:It will be removed after DPTC used UDMA interface */
+ if (i >= MXC_DMA_CHANNEL_IRAM)
+ continue;
+#endif /*CONFIG_SDMA_IRAM */
+ if (!sdma_data[i].in_use) {
+ *channel = i;
+ break;
+ }
+ }
+ }
+
+ if (*channel > 0 && *channel < MAX_DMA_CHANNELS &&
+ sdma_data[*channel].in_use == 0) {
+ res = iapi_Open(sdma_data[0].cd, *channel);
+
+ if (res < 0) {
+ printk(KERN_ERR "Failed iapi_Open channel %d, 0x%x\n",
+ *channel, res);
+ } else {
+ sdma_data[*channel].in_use = 1;
+ strcpy(sdma_data[*channel].devicename, devicename);
+ sdma_data[*channel].cd = CHAD(*channel);
+
+ iapi_IoCtl(sdma_data[*channel].cd, IAPI_CHANGE_SYNCH,
+ CALLBACK_ISR);
+ iapi_IoCtl(sdma_data[*channel].cd,
+ IAPI_CHANGE_CALLBACKFUNC,
+ (unsigned long)iapi_interrupt_callback);
+ iapi_IoCtl(sdma_data[*channel].cd,
+ IAPI_CHANGE_USER_ARG,
+ (unsigned long)&(sdma_data[*channel]));
+ }
+ } else {
+ res = -EBUSY;
+ }
+
+ up(&sdma_status_mutex);
+
+ return res;
+}
+
+/*!
+ * Configures request parameters. Can be called multiple times after
+ * mxc_request_dma() and mxc_dma_setup_channel().
+ *
+ *
+ * @param channel channel number
+ * @param p request parameters pointer
+ * @param bd_index index of buffer descriptor to set
+ * @return 0 on success, error code on fail
+ */
+int mxc_dma_set_config(int channel, dma_request_t * p, int bd_index)
+{
+ unsigned char param;
+
+ if (!sdma_data[channel].in_use) {
+ return -EINVAL;
+ }
+
+ iapi_IoCtl(sdma_data[channel].cd,
+ (bd_index << BD_NUM_OFFSET) |
+ IAPI_CHANGE_SET_TRANSFER_CD, sdma_data[channel].word_size);
+
+ param = BD_DONE | BD_INTR | BD_EXTD;
+
+ if (sdma_data[channel].bd_number > 1 && p->bd_cont == 1) {
+ param |= BD_CONT;
+ }
+
+ if (bd_index == sdma_data[channel].bd_number - 1) {
+ param |= BD_WRAP;
+ }
+
+ switch (sdma_data[channel].transfer_type) {
+ case emi_2_per:
+ case dsp_2_per:
+ case int_2_per:
+ case emi_2_dsp:
+ case int_2_dsp:
+ case emi_2_dsp_loop:
+ iapi_IoCtl(sdma_data[channel].cd,
+ (bd_index << BD_NUM_OFFSET) |
+ IAPI_CHANGE_SET_BUFFERADDR,
+ (unsigned long)p->sourceAddr);
+ break;
+ case per_2_int:
+ case per_2_emi:
+ case per_2_dsp:
+ case dsp_2_int:
+ case dsp_2_emi:
+ case dsp_2_dsp:
+ case dsp_2_emi_loop:
+ iapi_IoCtl(sdma_data[channel].cd,
+ (bd_index << BD_NUM_OFFSET) |
+ IAPI_CHANGE_SET_BUFFERADDR,
+ (unsigned long)p->destAddr);
+ break;
+ case emi_2_int:
+ case emi_2_emi:
+ case int_2_int:
+ case int_2_emi:
+ iapi_IoCtl(sdma_data[channel].cd,
+ (bd_index << BD_NUM_OFFSET) |
+ IAPI_CHANGE_SET_BUFFERADDR,
+ (unsigned long)p->sourceAddr);
+ iapi_IoCtl(sdma_data[channel].cd,
+ (bd_index << BD_NUM_OFFSET) |
+ IAPI_CHANGE_SET_EXTDBUFFERADDR,
+ (unsigned long)p->destAddr);
+ break;
+ default:
+ break;
+ }
+
+ /* Change the endianness for DSP to MCU Data transfers */
+ if (sdma_data[channel].transfer_type == dsp_2_emi ||
+ sdma_data[channel].transfer_type == emi_2_dsp) {
+ iapi_IoCtl(sdma_data[channel].cd, IAPI_CHANGE_SET_ENDIANNESS,
+ SET_BIT_ALL);
+ }
+
+ iapi_IoCtl(sdma_data[channel].cd,
+ (bd_index << BD_NUM_OFFSET) |
+ IAPI_CHANGE_SET_COUNT, p->count);
+
+ iapi_IoCtl(sdma_data[channel].cd,
+ (bd_index << BD_NUM_OFFSET) | IAPI_CHANGE_SET_STATUS, param);
+
+ return 0;
+}
+
+/*!
+ * Configures the BD_INTR bit on a buffer descriptor parameters.
+ *
+ *
+ * @param channel channel number
+ * @param bd_index index of buffer descriptor to set
+ * @param bd_intr flag to set or clear the BD_INTR bit
+ * @return 0 on success, error code on fail
+ */
+void mxc_dma_set_bd_intr(int channel, int bd_index, int bd_intr)
+{
+ unsigned long param;
+
+ iapi_IoCtl(sdma_data[channel].cd,
+ (bd_index << BD_NUM_OFFSET) |
+ IAPI_CHANGE_GET_STATUS, (unsigned long)&param);
+
+ if (bd_intr) {
+ param |= BD_INTR;
+ } else {
+ param &= ~BD_INTR;
+ }
+ iapi_IoCtl(sdma_data[channel].cd,
+ (bd_index << BD_NUM_OFFSET) | IAPI_CHANGE_SET_STATUS, param);
+
+}
+
+/*!
+ * Gets the BD_INTR bit on a buffer descriptor.
+ *
+ *
+ * @param channel channel number
+ * @param bd_index index of buffer descriptor to set
+ *
+ * @return returns the BD_INTR bit status
+ */
+int mxc_dma_get_bd_intr(int channel, int bd_index)
+{
+ unsigned long bd_status = 0;
+
+ iapi_IoCtl(sdma_data[channel].cd,
+ (bd_index << BD_NUM_OFFSET) |
+ IAPI_CHANGE_GET_STATUS, (unsigned long)&bd_status);
+
+ return (bd_status & BD_INTR);
+}
+
+/*!
+ * Stop the current transfer
+ *
+ * @param channel channel number
+ * @param buffer_number number of buffers (beginning with 0),
+ * whose done bits should be reset to 0
+ */
+int mxc_dma_reset(int channel, int buffer_number)
+{
+ unsigned char param = 0;
+ int i = 0;
+
+ if (!sdma_data[channel].in_use) {
+ return -EINVAL;
+ }
+
+ /* clear the BD_DONE bits for all the necessary buffers */
+ for (i = 0; i < buffer_number; i++) {
+
+ iapi_IoCtl(sdma_data[channel].cd, (i << BD_NUM_OFFSET) |
+ IAPI_CHANGE_GET_STATUS, (unsigned long)&param);
+
+ /* clear the BD_DONE bit of the buffer */
+ param = param & (~BD_DONE);
+
+ iapi_IoCtl(sdma_data[channel].cd, (i << BD_NUM_OFFSET) |
+ IAPI_CHANGE_SET_STATUS, param);
+ }
+
+ return 0;
+}
+
+/*!
+ * Returns request parameters.
+ *
+ * @param channel channel number
+ * @param p request parameters pointer
+ * @param bd_index index of buffer descriptor to get
+ * @return 0 on success, error code on fail
+ */
+int mxc_dma_get_config(int channel, dma_request_t * p, int bd_index)
+{
+ int err = 0;
+ unsigned long bd_status;
+ unsigned long bd_count;
+ __u8 *sourceAddr;
+ __u8 *destAddr;
+
+ iapi_IoCtl(sdma_data[channel].cd,
+ (bd_index << BD_NUM_OFFSET) |
+ IAPI_CHANGE_GET_STATUS, (unsigned long)&bd_status);
+ iapi_IoCtl(sdma_data[channel].cd,
+ (bd_index << BD_NUM_OFFSET) |
+ IAPI_CHANGE_GET_COUNT, (unsigned long)&bd_count);
+ iapi_IoCtl(sdma_data[channel].cd,
+ (bd_index << BD_NUM_OFFSET) |
+ IAPI_CHANGE_GET_BUFFERADDR, (unsigned long)&sourceAddr);
+
+ switch (sdma_data[channel].transfer_type) {
+ case emi_2_per:
+ case dsp_2_per:
+ case int_2_per:
+ case emi_2_dsp:
+ case int_2_dsp:
+ case emi_2_dsp_loop:
+ p->sourceAddr = sourceAddr;
+ break;
+ case per_2_int:
+ case per_2_emi:
+ case per_2_dsp:
+ case dsp_2_int:
+ case dsp_2_emi:
+ case dsp_2_dsp:
+ case dsp_2_emi_loop:
+ p->destAddr = sourceAddr;
+ break;
+ case emi_2_int:
+ case emi_2_emi:
+ case int_2_int:
+ case int_2_emi:
+ p->sourceAddr = sourceAddr;
+ iapi_IoCtl(sdma_data[channel].cd,
+ (bd_index << BD_NUM_OFFSET) |
+ IAPI_CHANGE_GET_EXTDBUFFERADDR,
+ (unsigned long)&destAddr);
+ p->destAddr = destAddr;
+ break;
+ default:
+ break;
+ }
+
+ p->count = bd_count;
+ p->bd_done = bd_status & BD_DONE;
+ p->bd_cont = bd_status & BD_CONT;
+ p->bd_error = bd_status & BD_RROR;
+
+ return err;
+}
+
+/*!
+ * This function is used by MXC IPC's write_ex2. It passes the pointer to the
+ * data control structure to iapi_write_ipcv2()
+ *
+ * @param channel SDMA channel number
+ * @param ctrl_ptr Data Control structure pointer
+ */
+int mxc_sdma_write_ipcv2(int channel, void *ctrl_ptr)
+{
+ return iapi_Write_ipcv2(sdma_data[channel].cd, ctrl_ptr);
+}
+
+/*!
+ * This function is used by MXC IPC's read_ex2. It passes the pointer to the
+ * data control structure to iapi_read_ipcv2()
+ *
+ * @param channel SDMA channel number
+ * @param ctrl_ptr Data Control structure pointer
+ */
+int mxc_sdma_read_ipcv2(int channel, void *ctrl_ptr)
+{
+ return iapi_Read_ipcv2(sdma_data[channel].cd, ctrl_ptr);
+}
+
+/*!
+ * Starts dma channel.
+ *
+ * @param channel channel number
+ */
+int mxc_dma_start(int channel)
+{
+ if (sdma_data[channel].running == 0) {
+ sdma_data[channel].running = 1;
+ iapi_StartChannel(channel);
+ }
+
+ return 0;
+}
+
+/*!
+ * Stops dma channel.
+ *
+ * @param channel channel number
+ */
+int mxc_dma_stop(int channel)
+{
+ iapi_StopChannel(channel);
+ sdma_data[channel].running = 0;
+
+ return 0;
+}
+
+/*!
+ * Frees dma channel.
+ *
+ * @param channel channel number
+ */
+void mxc_free_dma(int channel)
+{
+ int i;
+
+ mxc_dma_stop(channel);
+
+ if (sdma_data[channel].event_id != 0) {
+ iapi_SetChannelEventMapping(sdma_data[channel].event_id, 0x0);
+ }
+ if (sdma_data[channel].event_id2 != 0) {
+ iapi_SetChannelEventMapping(sdma_data[channel].event_id2, 0x0);
+ }
+
+ sdma_data[channel].event_id = 0;
+
+ iapi_IoCtl(sdma_data[channel].cd, IAPI_CHANGE_PRIORITY, 0x0);
+ iapi_IoCtl(sdma_data[channel].cd, IAPI_CHANGE_OWNERSHIP,
+ (OWN_CHANNEL << CH_OWNSHP_OFFSET_EVT) |
+ (OWN_CHANNEL << CH_OWNSHP_OFFSET_MCU) |
+ (OWN_CHANNEL << CH_OWNSHP_OFFSET_DSP));
+
+ for (i = 0; i < sdma_data[channel].bd_number; i++) {
+ iapi_IoCtl(sdma_data[channel].cd,
+ (i << BD_NUM_OFFSET) |
+ IAPI_CHANGE_SET_STATUS, (unsigned long)0);
+ }
+
+ iapi_Close(sdma_data[channel].cd);
+
+ strcpy(sdma_data[channel].devicename, "not used");
+
+ sdma_data[channel].in_use = 0;
+}
+
+/*!
+ * Initializes channel's priorities
+ *
+ */
+static void __init init_priorities(void)
+{
+ iapi_IoCtl(sdma_data[0].cd, IAPI_CHANGE_PRIORITY, 0x7);
+}
+
+/*!
+ * Initializes events table
+ */
+static void __init init_event_table(void)
+{
+ int channel;
+
+ for (channel = 0; channel < MAX_DMA_CHANNELS; channel++) {
+ iapi_SetChannelEventMapping(channel, 0);
+ }
+}
+
+/*!
+ * Sets callback function. Used with standard dma api
+ * for supporting interrupts
+ *
+ * @param channel channel number
+ * @param callback callback function pointer
+ * @param arg argument for callback function
+ */
+void mxc_dma_set_callback(int channel, dma_callback_t callback, void *arg)
+{
+ sdma_data[channel].callback = callback;
+ sdma_data[channel].arg = arg;
+}
+
+/*!
+ * Synchronization function used by I.API
+ *
+ * @param channel channel number
+ */
+static int getChannel(int channel)
+{
+ if (irqs_disabled() || in_atomic()) {
+ if (down_trylock(&sdma_synch_mutex[channel])) {
+ return -EBUSY;
+ }
+ } else {
+ if (down_interruptible(&sdma_synch_mutex[channel])) {
+ return -EBUSY;
+ }
+ }
+
+ return 0;
+}
+
+/*!
+ * Synchronization function used by I.API
+ *
+ * @param channel channel number
+ */
+static int releaseChannel(int channel)
+{
+ up(&sdma_synch_mutex[channel]);
+ return 0;
+}
+
+/*!
+ * Unmask interrupt function. Used by I.API
+ *
+ */
+static void unmask_sdma_interrupt(void)
+{
+ /* Commented out tp take care of the PREEMPT_RT option
+ * local_irq_restore(flags);
+ */
+}
+
+/*!
+ * Mask interrupt function. Used by I.API
+ *
+ */
+static void mask_sdma_interrupt(void)
+{
+ /* Commented to take of the PREEMPT_RT option
+ * local_irq_save(flags);
+ */
+}
+
+/*!
+ * Initializes I.API
+ */
+static void __init init_iapi_struct(void)
+{
+ channelDescriptor *cd;
+
+ printk(KERN_INFO "Using SDMA I.API\n");
+
+ iapi_Malloc = &sdma_malloc;
+#ifdef CONFIG_SDMA_IRAM
+ iapi_iram_Malloc = &sdma_iram_malloc;
+#endif /*CONFIG_SDMA_IRAM */
+
+ iapi_Free = &sdma_free;
+ iapi_Virt2Phys = (void *(*)(void *))&sdma_virt_to_phys;
+ iapi_Phys2Virt = (void *(*)(void *))&sdma_phys_to_virt;
+ iapi_memset = &memset;
+ iapi_memcpy = &memcpy;
+
+ iapi_GotoSleep = &sdma_sleep_channel;
+ iapi_WakeUp = &sdma_wakeup_channel;
+ iapi_InitSleep = &sdma_init_sleep;
+ iapi_ReleaseChannel = &releaseChannel;
+ iapi_GetChannel = &getChannel;
+
+ iapi_EnableInterrupts = &unmask_sdma_interrupt;
+ iapi_DisableInterrupts = &mask_sdma_interrupt;
+
+ cd = kmalloc(sizeof(channelDescriptor), GFP_KERNEL);
+
+ memset(cd, 0, sizeof(channelDescriptor));
+
+ sdma_data[0].cd = cd;
+}
+
+/*!
+ * Initializes channel synchronization mutexes
+ */
+static void __init init_mutexes(void)
+{
+ int i;
+
+ for (i = 0; i < MAX_DMA_CHANNELS; i++) {
+ init_MUTEX(&sdma_synch_mutex[i]);
+ }
+
+ init_MUTEX(&sdma_status_mutex);
+}
+
+/*!
+ * Channels status read proc file system function
+ *
+ * @param buf pointer to the buffer the data shuld be written to.
+ * @param start pointer to the pointer where the new data is
+ * written to.
+ * procedure should update the start pointer to point to
+ * where in the buffer the data was written.
+ * @param offset offset from start of the file
+ * @param count number of bytes to read.
+ * @param eof pointer to eof flag. sould be set to 1 when
+ * reaching eof.
+ * @param data driver specific data pointer.
+ *
+ * @return number byte read from the log buffer.
+ */
+static int proc_read_channels(char *buf, char **start, off_t offset, int count,
+ int *eof, void *data)
+{
+ char *log;
+ char *log_ptr;
+ char tmp[48];
+ int i;
+
+ log = kmalloc(4096, GFP_KERNEL);
+ memset(log, 0, 4096);
+ log_ptr = log;
+
+ for (i = 0; i < MAX_DMA_CHANNELS; i++) {
+ if (sdma_data[i].in_use == 0) {
+ continue;
+ }
+
+ memset(tmp, 0, 48);
+ sprintf(tmp, "Channel %d: %s\n", i, sdma_data[i].devicename);
+
+ strcpy(log_ptr, tmp);
+ log_ptr += strlen(tmp);
+ }
+
+ if (offset > strlen(log)) {
+ *eof = 1;
+ count = 0;
+ } else {
+ if (offset + count > strlen(log)) {
+ count = strlen(log) - offset;
+ *eof = 1;
+ } else {
+ *eof = 0;
+ }
+
+ memcpy(buf, log, count);
+ *start = buf;
+ kfree(log);
+ }
+
+ return count;
+}
+
+/*!
+ * SDMA proc file system read function
+ */
+static int __init init_proc_fs(void)
+{
+ struct proc_dir_entry *sdma_proc_dir;
+ int res;
+
+ res = 0;
+
+ sdma_proc_dir = proc_mkdir("sdma", NULL);
+ create_proc_read_entry("channels", 0, sdma_proc_dir,
+ proc_read_channels, NULL);
+
+ if (res < 0) {
+ printk(KERN_WARNING "Failed create SDMA proc entry\n");
+ }
+
+ return res;
+}
+
+/*!
+ * Initializes SDMA private data
+ */
+static void __init init_sdma_data(void)
+{
+ int i;
+
+ memset(sdma_data, 0, sizeof(sdma_struct) * MAX_DMA_CHANNELS);
+ sdma_data[0].in_use = 1;
+ strcpy(sdma_data[0].devicename, "MCU");
+
+ for (i = 0; i < MAX_DMA_CHANNELS; i++) {
+ sdma_data[i].channel = i;
+ }
+}
+
+#if defined(CONFIG_MXC_SUPER_GEM)
+/*!
+ * Initialize the Super GEM SDMA channel
+ *
+ * @return returns -1 on error, 0 on success.
+ */
+static int __init init_super_gem(void)
+{
+ channelDescriptor *cd;
+ script_data context;
+ int res = 0;
+
+ res = iapi_Open(sdma_data[0].cd, MXC_DMA_CHANNEL_GEM);
+ if (res < 0) {
+ return -1;
+ }
+ sdma_data[MXC_DMA_CHANNEL_GEM].in_use = 1;
+ cd = CHAD(MXC_DMA_CHANNEL_GEM);
+ memset(&context, 0, sizeof(script_data));
+ context.load_address = sdma_script_addrs.mxc_sdma_utra_addr;
+ context.wml = M3_BASE_ADDRESS;
+ res = iapi_AssignScript(cd, &context);
+ if (res < 0) {
+ iapi_Close(cd);
+ sdma_data[MXC_DMA_CHANNEL_GEM].in_use = 0;
+ return -1;
+ }
+ res =
+ iapi_IoCtl(cd, IAPI_CHANGE_OWNERSHIP,
+ (OWN_CHANNEL << CH_OWNSHP_OFFSET_EVT) |
+ (DONT_OWN_CHANNEL << CH_OWNSHP_OFFSET_MCU) |
+ (OWN_CHANNEL << CH_OWNSHP_OFFSET_DSP));
+ if (res < 0) {
+ iapi_Close(cd);
+ sdma_data[MXC_DMA_CHANNEL_GEM].in_use = 0;
+ return -1;
+ }
+ /* Set EP=1, which is required to start SuperGem script the first time */
+ /* This can be done only on the AP side */
+ SDMA_H_EVTPEND |= 1 << MXC_DMA_CHANNEL_GEM;
+
+ res =
+ iapi_SetChannelEventMapping(DMA_REQ_GEM, 1 << MXC_DMA_CHANNEL_GEM);
+ if (res < 0) {
+ iapi_Close(cd);
+ sdma_data[MXC_DMA_CHANNEL_GEM].in_use = 0;
+ return -1;
+ }
+
+ return 0;
+}
+#endif
+
+/*!
+ * Initializes dma
+ */
+int __init sdma_init(void)
+{
+ int res = 0;
+ configs_data confreg_data;
+
+ /* Initialize to the default values */
+ confreg_data = iapi_ConfigDefaults;
+
+ confreg_data.dspdma = 0;
+ /* Set ACR bit */
+ mxc_sdma_ahb_clk = clk_get(NULL, "sdma_ahb_clk");
+ mxc_sdma_ipg_clk = clk_get(NULL, "sdma_ipg_clk");
+ clk_enable(mxc_sdma_ahb_clk);
+ clk_enable(mxc_sdma_ipg_clk);
+ if (clk_get_rate(mxc_sdma_ahb_clk) / clk_get_rate(mxc_sdma_ipg_clk) < 2) {
+ printk(KERN_INFO "Setting SDMA ACR\n");
+ confreg_data.acr = 1;
+ }
+
+ init_sdma_data();
+
+ init_sdma_pool();
+
+ res = request_irq(MXC_INT_SDMA, sdma_int_handler, 0, "mxcsdma", 0);
+
+ if (res < 0) {
+ goto sdma_init_fail;
+ }
+
+ init_mutexes();
+
+ init_iapi_struct();
+
+ mxc_sdma_get_script_info(&sdma_script_addrs);
+
+ res = iapi_Init(sdma_data[0].cd, &confreg_data,
+ sdma_script_addrs.mxc_sdma_start_addr,
+ sdma_script_addrs.mxc_sdma_ram_code_size * 2,
+ sdma_script_addrs.mxc_sdma_ram_code_start_addr);
+
+ if (res < 0) {
+ free_irq(MXC_INT_SDMA, 0);
+ goto sdma_init_fail;
+ }
+
+ init_priorities();
+
+ init_event_table();
+
+#if defined(CONFIG_MXC_SUPER_GEM)
+ res = init_super_gem();
+ if (res < 0) {
+ free_irq(MXC_INT_SDMA, 0);
+ goto sdma_init_fail;
+ }
+#endif
+
+ init_proc_fs();
+
+ printk(KERN_INFO "MXC DMA API initialized\n");
+
+ clk_disable(mxc_sdma_ahb_clk);
+ clk_disable(mxc_sdma_ipg_clk);
+ return res;
+
+ sdma_init_fail:
+ printk(KERN_ERR "Error 0x%x in sdma_init\n", res);
+ clk_disable(mxc_sdma_ahb_clk);
+ clk_disable(mxc_sdma_ipg_clk);
+ return res;
+
+}
+
+arch_initcall(sdma_init);
+
+EXPORT_SYMBOL(mxc_request_dma);
+EXPORT_SYMBOL(mxc_free_dma);
+EXPORT_SYMBOL(mxc_dma_setup_channel);
+EXPORT_SYMBOL(mxc_dma_set_channel_priority);
+EXPORT_SYMBOL(mxc_dma_set_config);
+EXPORT_SYMBOL(mxc_dma_get_config);
+EXPORT_SYMBOL(mxc_dma_set_bd_intr);
+EXPORT_SYMBOL(mxc_dma_get_bd_intr);
+EXPORT_SYMBOL(mxc_dma_reset);
+EXPORT_SYMBOL(mxc_sdma_write_ipcv2);
+EXPORT_SYMBOL(mxc_sdma_read_ipcv2);
+EXPORT_SYMBOL(mxc_dma_start);
+EXPORT_SYMBOL(mxc_dma_stop);
+EXPORT_SYMBOL(sdma_malloc);
+EXPORT_SYMBOL(sdma_free);
+EXPORT_SYMBOL(mxc_dma_set_callback);
+EXPORT_SYMBOL(sdma_virt_to_phys);
+EXPORT_SYMBOL(sdma_phys_to_virt);
+
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_DESCRIPTION("MXC Linux SDMA API");
+MODULE_LICENSE("GPL");
diff --git a/arch/arm/plat-mxc/sdma/sdma_malloc.c b/arch/arm/plat-mxc/sdma/sdma_malloc.c
new file mode 100644
index 000000000000..21118b42c855
--- /dev/null
+++ b/arch/arm/plat-mxc/sdma/sdma_malloc.c
@@ -0,0 +1,387 @@
+/*
+ * Copyright 2004-2009 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
+ */
+
+/*!
+ * @file plat-mxc/sdma/sdma_malloc.c
+ * @brief This file contains functions for SDMA non-cacheable buffers allocation
+ *
+ * SDMA (Smart DMA) is used for transferring data between MCU and peripherals
+ *
+ * @ingroup SDMA
+ */
+
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <asm/dma.h>
+#include <mach/hardware.h>
+
+#include <linux/device.h>
+#include <linux/dma-mapping.h>
+#include <linux/dmapool.h>
+
+#define DEBUG 0
+
+#if DEBUG
+#define DPRINTK(fmt, args...) printk("%s: " fmt, __FUNCTION__ , ## args)
+#else
+#define DPRINTK(fmt, args...)
+#endif
+
+#ifdef CONFIG_SDMA_IRAM
+#define IRAM_VIRT_BASE IRAM_BASE_ADDR_VIRT
+#define IRAM_PHYS_BASE IRAM_BASE_ADDR
+#if (CONFIG_SDMA_IRAM_SIZE&0x3FF)
+#error "IRAM size of SDMA should be multiple of 1Kbytes"
+#else
+#define IRAM_SDMA_SIZE CONFIG_SDMA_IRAM_SIZE /* 4K */
+#endif
+#define IRAM_UNIT_SIZE 512
+#define IRAM_POOL_SIZE (IRAM_SDMA_SIZE/IRAM_UNIT_SIZE)
+
+#define IS_IRAM_VIRT(x) (((x)<IRAM_VIRT_BASE)?0:\
+ (((x) - IRAM_VIRT_BASE)>IRAM_SDMA_SIZE)?0:1)
+
+#define IS_IRAM_PHYS(x) (((x)<IRAM_PHYS_BASE)?0:\
+ (((x) - IRAM_PHYS_BASE)>IRAM_SDMA_SIZE)?0:1)
+#endif /*CONFIG_SDMA_IRAM */
+
+/*!
+ * Defines SDMA non-cacheable buffers pool
+ */
+static struct dma_pool *pool;
+
+#ifdef CONFIG_SDMA_IRAM
+typedef struct iram_head_s {
+ struct list_head list;
+} iram_head_t;
+
+static spinlock_t iram_pool_lock = SPIN_LOCK_UNLOCKED;
+static struct list_head iram_free_list;
+static unsigned char iram_pool_flag[IRAM_POOL_SIZE];
+
+static void sdma_iram_free(void *buf);
+#endif /*CONFIG_SDMA_IRAM */
+
+/*!
+ * SDMA memory conversion hashing structure
+ */
+typedef struct {
+ struct list_head node;
+ int use_count;
+ /*! Virtual address */
+ void *virt;
+ /*! Physical address */
+ unsigned long phys;
+} virt_phys_struct;
+
+static struct list_head buf_map;
+
+/*!
+ * Defines the size of each buffer in SDMA pool.
+ * The size must be at least 512 bytes, because
+ * sdma channel control blocks array size is 512 bytes
+ */
+#define SDMA_POOL_SIZE 1024
+
+/*!
+ * Adds new buffer structure into conversion hash tables
+ *
+ * @param vf SDMA memory conversion hashing structure
+ *
+ * @return 1 on success, 0 on fail
+ */
+static int add_entry(virt_phys_struct * vf)
+{
+ virt_phys_struct *p;
+
+ vf->phys &= PAGE_MASK;
+ vf->virt = (void *)((u32) vf->virt & PAGE_MASK);
+
+ list_for_each_entry(p, &buf_map, node) {
+ if (p->virt == vf->virt) {
+ p->use_count++;
+ return 0;
+ }
+ }
+
+ p = kmalloc(sizeof(virt_phys_struct), GFP_KERNEL);
+ if (p == 0) {
+ return -ENOMEM;
+ }
+
+ *p = *vf;
+ p->use_count = 1;
+ list_add_tail(&p->node, &buf_map);
+
+ DPRINTK("added vaddr 0x%p, paddr 0x%08X to list\n", p->virt, p->phys);
+
+ return 0;
+}
+
+/*!
+ * Deletes buffer stracture from conversion hash tables
+ *
+ * @param buf SDMA memory buffer virtual addr
+ *
+ * @return 0 on success, -1 on fail
+ */
+static int delete_entry(void *buf)
+{
+ virt_phys_struct *p;
+
+ buf = (void *)((u32) buf & PAGE_MASK);
+
+ list_for_each_entry(p, &buf_map, node) {
+ if (p->virt == buf) {
+ p->use_count--;
+ break;
+ }
+ }
+
+ if (p->use_count == 0) {
+ list_del(&p->node);
+ kfree(p);
+ }
+
+ return 0;
+}
+
+/*!
+ * Virtual to physical address conversion functio
+ *
+ * @param buf pointer to virtual address
+ *
+ * @return physical address
+ */
+unsigned long sdma_virt_to_phys(void *buf)
+{
+ u32 offset = (u32) buf & (~PAGE_MASK);
+ virt_phys_struct *p;
+
+ DPRINTK("searching for vaddr 0x%p\n", buf);
+
+#ifdef CONFIG_SDMA_IRAM
+ if (IS_IRAM_VIRT((unsigned long)buf)) {
+ if ((unsigned long)buf & (IRAM_UNIT_SIZE - 1)) {
+ printk(KERN_WARNING "%s buffer offset = %ld\n",
+ __FUNCTION__, (unsigned long)buf);
+ }
+ return (unsigned long)buf + IRAM_PHYS_BASE - IRAM_VIRT_BASE;
+ }
+#endif /*CONFIG_SDMA_IRAM */
+
+ list_for_each_entry(p, &buf_map, node) {
+ if ((u32) p->virt == ((u32) buf & PAGE_MASK)) {
+ return p->phys | offset;
+ }
+ }
+
+ if (virt_addr_valid(buf)) {
+ return virt_to_phys(buf);
+ }
+
+ printk(KERN_WARNING
+ "SDMA malloc: could not translate virt address 0x%p\n", buf);
+ return 0;
+}
+
+/*!
+ * Physical to virtual address conversion functio
+ *
+ * @param buf pointer to physical address
+ *
+ * @return virtual address
+ */
+void *sdma_phys_to_virt(unsigned long buf)
+{
+ u32 offset = buf & (~PAGE_MASK);
+ virt_phys_struct *p;
+
+#ifdef CONFIG_SDMA_IRAM
+ if (IS_IRAM_PHYS((unsigned long)buf)) {
+ if (buf & (IRAM_UNIT_SIZE - 1)) {
+ printk(KERN_WARNING "%s buffer offset = %ld\n",
+ __FUNCTION__, (unsigned long)buf);
+ }
+ return (void *)buf + IRAM_VIRT_BASE - IRAM_PHYS_BASE;
+ }
+#endif /*CONFIG_SDMA_IRAM */
+
+ list_for_each_entry(p, &buf_map, node) {
+ if (p->phys == (buf & PAGE_MASK)) {
+ return (void *)((u32) p->virt | offset);
+ }
+ }
+
+ printk(KERN_WARNING
+ "SDMA malloc: could not translate phys address 0x%lx\n", buf);
+ return 0;
+}
+
+/*!
+ * Allocates uncacheable buffer
+ *
+ * @param size size of allocated buffer
+ * @return pointer to buffer
+ */
+void *sdma_malloc(size_t size)
+{
+ void *buf;
+ dma_addr_t dma_addr;
+ virt_phys_struct vf;
+
+ if (size > SDMA_POOL_SIZE) {
+ printk(KERN_WARNING
+ "size in sdma_malloc is more than %d bytes\n",
+ SDMA_POOL_SIZE);
+ buf = 0;
+ } else {
+ buf = dma_pool_alloc(pool, GFP_KERNEL, &dma_addr);
+ if (buf > 0) {
+ vf.virt = buf;
+ vf.phys = dma_addr;
+
+ if (add_entry(&vf) < 0) {
+ dma_pool_free(pool, buf, dma_addr);
+ buf = 0;
+ }
+ }
+ }
+
+ DPRINTK("allocated vaddr 0x%p\n", buf);
+ return buf;
+}
+
+/*!
+ * Frees uncacheable buffer
+ *
+ * @param buf buffer pointer for deletion
+ */
+void sdma_free(void *buf)
+{
+#ifdef CONFIG_SDMA_IRAM
+ if (IS_IRAM_VIRT((unsigned long)buf)) {
+ sdma_iram_free(buf);
+ return;
+ }
+#endif /*CONFIG_SDMA_IRAM */
+
+ dma_pool_free(pool, buf, sdma_virt_to_phys(buf));
+ delete_entry(buf);
+}
+
+#ifdef CONFIG_SDMA_IRAM
+/*!
+ * Allocates uncacheable buffer from IRAM
+ */
+void *sdma_iram_malloc(size_t size)
+{
+ void *buf = NULL;
+ int index = -1;
+ unsigned long flags;
+ if (size > IRAM_UNIT_SIZE) {
+ printk(KERN_WARNING
+ "size in sdma_iram_malloc is more than %d bytes\n",
+ IRAM_UNIT_SIZE);
+ } else {
+ spin_lock_irqsave(&iram_pool_lock, flags);
+ if (!list_empty(&iram_free_list)) {
+ buf =
+ list_entry(iram_free_list.next, iram_head_t, list);
+ list_del(iram_free_list.next);
+ index =
+ ((unsigned long)buf -
+ IRAM_VIRT_BASE) / IRAM_UNIT_SIZE;
+ if (index < 0 || index >= IRAM_POOL_SIZE) {
+ spin_unlock_irqrestore(&iram_pool_lock, flags);
+ printk(KERN_ERR "The iram pool has crashed\n");
+ return NULL;
+ }
+ if (iram_pool_flag[index]) {
+ spin_unlock_irqrestore(&iram_pool_lock, flags);
+ printk(KERN_WARNING
+ "iram block %d already has been allocated \n",
+ index);
+ }
+ iram_pool_flag[index] = 1;
+ }
+ spin_unlock_irqrestore(&iram_pool_lock, flags);
+ if ((unsigned long)buf & (IRAM_UNIT_SIZE - 1)) {
+ printk(KERN_WARNING
+ "the start address is not align of %d, buffer offset %ld\n",
+ IRAM_UNIT_SIZE, (unsigned long)buf);
+
+ buf = PTR_ALIGN(buf, IRAM_UNIT_SIZE);
+ }
+ }
+ return buf;
+}
+
+/*!
+ * Free uncacheable buffer into IRAM.
+ */
+static void sdma_iram_free(void *buf)
+{
+ iram_head_t *p;
+ int index;
+ unsigned long flags;
+ /* The check of parameter will be done in sdma_free */
+ index = ((unsigned long)buf - IRAM_VIRT_BASE) / IRAM_UNIT_SIZE;
+ spin_lock_irqsave(&iram_pool_lock, flags);
+ p = (iram_head_t *) ((unsigned long)buf & (~(IRAM_UNIT_SIZE - 1)));
+ list_add_tail(&(p->list), &iram_free_list);
+ if (iram_pool_flag[index]) {
+ iram_pool_flag[index] = 0;
+ spin_unlock_irqrestore(&iram_pool_lock, flags);
+ } else {
+ printk(KERN_WARNING
+ "Free %p which IRAM block %d is already freed\n", buf,
+ index);
+ spin_unlock_irqrestore(&iram_pool_lock, flags);
+ }
+}
+
+/*!
+ * Initialized the free list of IRAM.
+ */
+static void iram_pool_init(void)
+{
+ int i;
+ iram_head_t *p;
+ memset(iram_pool_flag, 0, IRAM_POOL_SIZE);
+ INIT_LIST_HEAD(&iram_free_list);
+ for (i = 0; i < IRAM_POOL_SIZE; i++) {
+ p = (iram_head_t *) (IRAM_VIRT_BASE + i * IRAM_UNIT_SIZE);
+ list_add_tail(&(p->list), &iram_free_list);
+ }
+}
+#endif /*CONFIG_SDMA_IRAM */
+
+/*!
+ * SDMA buffers pool initialization function
+ */
+void __init init_sdma_pool(void)
+{
+#ifdef CONFIG_SDMA_IRAM
+ iram_pool_init();
+#endif /*CONFIG_SDMA_IRAM */
+
+ pool = dma_pool_create("SDMA", NULL, SDMA_POOL_SIZE, 0, 0);
+
+ INIT_LIST_HEAD(&buf_map);
+}
+
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_DESCRIPTION("MXC Linux SDMA API");
+MODULE_LICENSE("GPL");
diff --git a/arch/arm/plat-mxc/serialxc.c b/arch/arm/plat-mxc/serialxc.c
new file mode 100644
index 000000000000..cf18bfdc8a76
--- /dev/null
+++ b/arch/arm/plat-mxc/serialxc.c
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2005-2009 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/module.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/usb/fsl_xcvr.h>
+
+#include <mach/hardware.h>
+#include <mach/arc_otg.h>
+
+static void usb_serial_init(struct fsl_xcvr_ops *this)
+{
+}
+
+static void usb_serial_uninit(struct fsl_xcvr_ops *this)
+{
+}
+
+static struct fsl_xcvr_ops serial_ops = {
+ .name = "serial",
+ .xcvr_type = PORTSC_PTS_SERIAL,
+ .init = usb_serial_init,
+ .uninit = usb_serial_uninit,
+};
+
+extern void fsl_usb_xcvr_register(struct fsl_xcvr_ops *xcvr_ops);
+
+static int __init serialxc_init(void)
+{
+ pr_debug("%s\n", __FUNCTION__);
+
+ fsl_usb_xcvr_register(&serial_ops);
+
+ return 0;
+}
+
+extern void fsl_usb_xcvr_unregister(struct fsl_xcvr_ops *xcvr_ops);
+
+static void __exit serialxc_exit(void)
+{
+ fsl_usb_xcvr_unregister(&serial_ops);
+}
+
+module_init(serialxc_init);
+module_exit(serialxc_exit);
+
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_DESCRIPTION("serial xcvr driver");
+MODULE_LICENSE("GPL");
diff --git a/arch/arm/plat-mxc/snoop.c b/arch/arm/plat-mxc/snoop.c
new file mode 100644
index 000000000000..b6e48c7e59d0
--- /dev/null
+++ b/arch/arm/plat-mxc/snoop.c
@@ -0,0 +1,133 @@
+/*
+ * Copyright 2005-2009 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/kernel.h>
+#include <linux/module.h>
+#include <linux/err.h>
+#include <mach/hardware.h>
+#include <linux/io.h>
+
+#ifdef M4IF_BASE_ADDR
+#define SNOOP_V2
+#define MAX_SNOOP 2
+#define g_snoop_base (IO_ADDRESS(M4IF_BASE_ADDR) + 0x4C)
+#elif defined(M3IF_BASE_ADDR)
+#define MAX_SNOOP 1
+#define g_snoop_base (IO_ADDRESS(M3IF_BASE_ADDR) + 0x28)
+#else
+#define MAX_SNOOP 0
+#define g_snoop_base 0
+#endif
+
+/* M3IF Snooping Configuration Register 0 (M3IFSCFG0) READ/WRITE*/
+#define SBAR(x) (x * 0x14)
+/* M3IF Snooping Configuration Register 1 (M3IFSCFG1) READ/WRITE*/
+#define SERL(x) ((x * 0x14) + 0x4)
+/* M3IF Snooping Configuration Register 2 (M3IFSCFG2) READ/WRITE*/
+#define SERH(x) ((x * 0x14) + 0x8)
+/* M3IF Snooping Status Register 0 (M3IFSSR0) READ/WRITE */
+#define SSRL(x) ((x * 0x14) + 0xC)
+/* M3IF Snooping Status Register 1 (M3IFSSR1) */
+#define SSRH(x) ((x * 0x14) + 0x10)
+
+#if MAX_SNOOP
+
+int mxc_snoop_set_config(u32 num, unsigned long base, int size)
+{
+ u32 reg;
+ uint32_t msb;
+ uint32_t seg_size;
+ uint32_t window_size = 0;
+ int i;
+
+ if (num >= MAX_SNOOP) {
+ return -EINVAL;
+ }
+
+ /* Setup M3IF for snooping */
+ if (size) {
+
+ if (base == 0) {
+ return -EINVAL;
+ }
+
+ msb = fls(size);
+ if (!(size & ((1UL << msb) - 1)))
+ msb--; /* Already aligned to power 2 */
+ if (msb < 11)
+ msb = 11;
+
+ window_size = (1UL << msb);
+ seg_size = window_size / 64;
+
+ msb -= 11;
+
+ reg = base & ~((1UL << msb) - 1);
+ reg |= msb << 1;
+ reg |= 1; /* enable snooping */
+ reg |= 0x80; /* Set pulse width to default (M4IF only) */
+ __raw_writel(reg, g_snoop_base + SBAR(num));
+
+ reg = 0;
+ for (i = 0; i < 32; i++) {
+ if (i * seg_size >= size)
+ break;
+ reg |= 1UL << i;
+ }
+ __raw_writel(reg, g_snoop_base + SERL(num));
+
+ reg = 0;
+ for (i = 32; i < 64; i++) {
+ if (i * seg_size >= size)
+ break;
+ reg |= 1UL << (i - 32);
+ }
+ __raw_writel(reg, g_snoop_base + SERH(num));
+
+ pr_debug
+ ("Snooping unit # %d enabled: window size = 0x%X, M3IFSCFG0=0x%08X, M3IFSCFG1=0x%08X, M3IFSCFG2=0x%08X\n",
+ num, window_size, __raw_readl(g_snoop_base + SBAR(num)),
+ __raw_readl(g_snoop_base + SERL(num)),
+ __raw_readl(g_snoop_base + SERH(num)));
+ } else {
+ __raw_writel(0, g_snoop_base + SBAR(num));
+ }
+
+ return window_size;
+}
+
+EXPORT_SYMBOL(mxc_snoop_set_config);
+
+int mxc_snoop_get_status(u32 num, u32 * statl, u32 * stath)
+{
+ if (num >= MAX_SNOOP) {
+ return -EINVAL;
+ }
+
+ *statl = __raw_readl(g_snoop_base + SSRL(num));
+ *stath = __raw_readl(g_snoop_base + SSRH(num));
+ /* DPRINTK("status = 0x%08X%08X\n", stat[1], stat[0]); */
+
+#ifdef SNOOP_V2
+ __raw_writel(*statl, g_snoop_base + SSRL(num));
+ __raw_writel(*stath, g_snoop_base + SSRH(num));
+#else
+ __raw_writel(0x0, g_snoop_base + SSRL(num));
+ __raw_writel(0x0, g_snoop_base + SSRH(num));
+#endif
+ return 0;
+}
+
+EXPORT_SYMBOL(mxc_snoop_get_status);
+
+#endif /* MAX_SNOOP */
diff --git a/arch/arm/plat-mxc/spba.c b/arch/arm/plat-mxc/spba.c
new file mode 100644
index 000000000000..a7f21a9e36df
--- /dev/null
+++ b/arch/arm/plat-mxc/spba.c
@@ -0,0 +1,133 @@
+/*
+ * Copyright 2004-2009 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/types.h>
+#include <linux/clk.h>
+#include <linux/module.h>
+#include <linux/io.h>
+#include <mach/hardware.h>
+#include <mach/spba.h>
+
+/*!
+ * @file plat-mxc/spba.c
+ *
+ * @brief This file contains the SPBA API implementation details.
+ *
+ * @ingroup SPBA
+ */
+
+static DEFINE_SPINLOCK(spba_lock);
+
+#define SPBA_MASTER_MIN 1
+#define SPBA_MASTER_MAX 7
+
+/*!
+ * the base addresses for the SPBA modules
+ */
+static unsigned long spba_base = (unsigned long)IO_ADDRESS(SPBA_CTRL_BASE_ADDR);
+
+/*!
+ * SPBA clock
+ */
+static struct clk *spba_clk;
+/*!
+ * This function allows the three masters (A, B, C) to take ownership of a
+ * shared peripheral.
+ *
+ * @param mod specified module as defined in \b enum \b #spba_module
+ * @param master one of more (or-ed together) masters as defined in \b enum \b #spba_masters
+ *
+ * @return 0 if successful; -1 otherwise.
+ */
+int spba_take_ownership(int mod, int master)
+{
+ unsigned long spba_flags;
+ __u32 rtn_val = -1;
+
+ if (master < SPBA_MASTER_MIN || master > SPBA_MASTER_MAX) {
+ printk("spba_take_ownership() invalide master= %d\n", master);
+ BUG(); /* oops */
+ }
+
+ if (spba_clk == NULL)
+ spba_clk = clk_get(NULL, "spba_clk");
+
+ clk_enable(spba_clk);
+
+ spin_lock_irqsave(&spba_lock, spba_flags);
+ __raw_writel(master, spba_base + mod);
+
+ if ((__raw_readl(spba_base + mod) & MXC_SPBA_RAR_MASK) == master) {
+ rtn_val = 0;
+ }
+
+ spin_unlock_irqrestore(&spba_lock, spba_flags);
+
+ clk_disable(spba_clk);
+ return rtn_val;
+}
+
+/*!
+ * This function releases the ownership for a shared peripheral.
+ *
+ * @param mod specified module as defined in \b enum \b #spba_module
+ * @param master one of more (or-ed together) masters as defined in \b enum \b #spba_masters
+ *
+ * @return 0 if successful; -1 otherwise.
+ */
+int spba_rel_ownership(int mod, int master)
+{
+ unsigned long spba_flags;
+ volatile unsigned long rar;
+
+ if (master < SPBA_MASTER_MIN || master > SPBA_MASTER_MAX) {
+ printk("spba_take_ownership() invalide master= %d\n", master);
+ BUG(); /* oops */
+ }
+
+ if (spba_clk == NULL)
+ spba_clk = clk_get(NULL, "spba_clk");
+
+ clk_enable(spba_clk);
+
+ if ((__raw_readl(spba_base + mod) & master) == 0) {
+ clk_disable(spba_clk);
+ return 0; /* does not own it */
+ }
+
+ spin_lock_irqsave(&spba_lock, spba_flags);
+
+ /* Since only the last 3 bits are writeable, doesn't need to mask off
+ bits 31-3 */
+ rar = __raw_readl(spba_base + mod) & (~master);
+ __raw_writel(rar, spba_base + mod);
+
+ if ((__raw_readl(spba_base + mod) & master) != 0) {
+ spin_unlock_irqrestore(&spba_lock, spba_flags);
+ clk_disable(spba_clk);
+ return -1;
+ }
+
+ spin_unlock_irqrestore(&spba_lock, spba_flags);
+
+ clk_disable(spba_clk);
+
+ return 0;
+}
+
+EXPORT_SYMBOL(spba_take_ownership);
+EXPORT_SYMBOL(spba_rel_ownership);
+
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_DESCRIPTION("SPBA");
+MODULE_LICENSE("GPL");
diff --git a/arch/arm/plat-mxc/time.c b/arch/arm/plat-mxc/time.c
index 88fb3a57e029..fbf86e42c3f4 100644
--- a/arch/arm/plat-mxc/time.c
+++ b/arch/arm/plat-mxc/time.c
@@ -50,6 +50,7 @@
/* MX31, MX35 */
#define MX3_TCTL_WAITEN (1 << 3)
#define MX3_TCTL_CLK_IPG (1 << 6)
+#define MX3_TCTL_CLK_PER (2 << 6)
#define MX3_TCTL_FRR (1 << 9)
#define MX3_IR 0x0c
#define MX3_TSTAT 0x08
@@ -57,6 +58,8 @@
#define MX3_TCN 0x24
#define MX3_TCMP 0x10
+#define timer_is_v2() (!(cpu_is_mx1() || cpu_is_mx2()) || cpu_is_mx25())
+
static struct clock_event_device clockevent_mxc;
static enum clock_event_mode clockevent_mode = CLOCK_EVT_MODE_UNUSED;
@@ -66,7 +69,7 @@ static inline void gpt_irq_disable(void)
{
unsigned int tmp;
- if (cpu_is_mx3())
+ if (timer_is_v2())
__raw_writel(0, timer_base + MX3_IR);
else {
tmp = __raw_readl(timer_base + MXC_TCTL);
@@ -76,7 +79,7 @@ static inline void gpt_irq_disable(void)
static inline void gpt_irq_enable(void)
{
- if (cpu_is_mx3())
+ if (timer_is_v2())
__raw_writel(1<<0, timer_base + MX3_IR);
else {
__raw_writel(__raw_readl(timer_base + MXC_TCTL) | MX1_2_TCTL_IRQEN,
@@ -90,7 +93,7 @@ static void gpt_irq_acknowledge(void)
__raw_writel(0, timer_base + MX1_2_TSTAT);
if (cpu_is_mx2())
__raw_writel(MX2_TSTAT_CAPT | MX2_TSTAT_COMP, timer_base + MX1_2_TSTAT);
- if (cpu_is_mx3())
+ if (timer_is_v2())
__raw_writel(MX3_TSTAT_OF1, timer_base + MX3_TSTAT);
}
@@ -117,7 +120,7 @@ static int __init mxc_clocksource_init(struct clk *timer_clk)
{
unsigned int c = clk_get_rate(timer_clk);
- if (cpu_is_mx3())
+ if (timer_is_v2())
clocksource_mxc.read = mx3_get_cycles;
clocksource_mxc.mult = clocksource_hz2mult(c,
@@ -180,7 +183,7 @@ static void mxc_set_mode(enum clock_event_mode mode,
if (mode != clockevent_mode) {
/* Set event time into far-far future */
- if (cpu_is_mx3())
+ if (timer_is_v2())
__raw_writel(__raw_readl(timer_base + MX3_TCN) - 3,
timer_base + MX3_TCMP);
else
@@ -233,7 +236,7 @@ static irqreturn_t mxc_timer_interrupt(int irq, void *dev_id)
struct clock_event_device *evt = &clockevent_mxc;
uint32_t tstat;
- if (cpu_is_mx3())
+ if (timer_is_v2())
tstat = __raw_readl(timer_base + MX3_TSTAT);
else
tstat = __raw_readl(timer_base + MX1_2_TSTAT);
@@ -264,7 +267,7 @@ static int __init mxc_clockevent_init(struct clk *timer_clk)
{
unsigned int c = clk_get_rate(timer_clk);
- if (cpu_is_mx3())
+ if (timer_is_v2())
clockevent_mxc.set_next_event = mx3_set_next_event;
clockevent_mxc.mult = div_sc(c, NSEC_PER_SEC,
@@ -281,10 +284,9 @@ static int __init mxc_clockevent_init(struct clk *timer_clk)
return 0;
}
-void __init mxc_timer_init(struct clk *timer_clk)
+void __init mxc_timer_init(struct clk *timer_clk, void __iomem *base, int irq)
{
uint32_t tctl_val;
- int irq;
clk_enable(timer_clk);
@@ -303,8 +305,10 @@ void __init mxc_timer_init(struct clk *timer_clk)
timer_base = IO_ADDRESS(GPT1_BASE_ADDR);
irq = MXC_INT_GPT;
#endif
- } else
- BUG();
+ }
+ if (base) {
+ timer_base = base;
+ }
/*
* Initialise to a known state (all timers off, and timing reset)
@@ -313,8 +317,8 @@ void __init mxc_timer_init(struct clk *timer_clk)
__raw_writel(0, timer_base + MXC_TCTL);
__raw_writel(0, timer_base + MXC_TPRER); /* see datasheet note */
- if (cpu_is_mx3())
- tctl_val = MX3_TCTL_CLK_IPG | MX3_TCTL_FRR | MX3_TCTL_WAITEN | MXC_TCTL_TEN;
+ if (timer_is_v2())
+ tctl_val = MX3_TCTL_CLK_PER | MX3_TCTL_FRR | MX3_TCTL_WAITEN | MXC_TCTL_TEN;
else
tctl_val = MX1_2_TCTL_FRR | MX1_2_TCTL_CLK_PCLK1 | MXC_TCTL_TEN;
diff --git a/arch/arm/plat-mxc/tzic.c b/arch/arm/plat-mxc/tzic.c
new file mode 100644
index 000000000000..630d9f789f95
--- /dev/null
+++ b/arch/arm/plat-mxc/tzic.c
@@ -0,0 +1,181 @@
+/*
+ * Copyright 2004-2009 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/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/errno.h>
+#include <mach/hardware.h>
+#include <linux/io.h>
+#include <asm/irq.h>
+#include <asm/mach/irq.h>
+
+/*
+ *****************************************
+ * TZIC Registers *
+ *****************************************
+ */
+#define TZIC_BASE IO_ADDRESS(TZIC_BASE_ADDR)
+#define TZIC_INTCNTL (TZIC_BASE + 0x0000) /* control register */
+#define TZIC_INTTYPE (TZIC_BASE + 0x0004) /* Controller type register */
+#define TZIC_IMPID (TZIC_BASE + 0x0008) /* Distributor Implementer Identification Register */
+#define TZIC_PRIOMASK (TZIC_BASE + 0x000C) /* Priority Mask Reg */
+#define TZIC_SYNCCTRL (TZIC_BASE + 0x0010) /* Synchronizer Control register */
+#define TZIC_DSMINT (TZIC_BASE + 0x0014) /* DSM interrupt Holdoffregister */
+#define TZIC_INTSEC0 (TZIC_BASE + 0x0080) /* interrupt security register 0 */
+#define TZIC_ENSET0 (TZIC_BASE + 0x0100) /* Enable Set Register 0 */
+#define TZIC_ENCLEAR0 (TZIC_BASE + 0x0180) /* Enable Clear Register 0 */
+#define TZIC_SRCSET0 (TZIC_BASE + 0x0200) /* Source Set Register 0 */
+#define TZIC_SRCCLAR0 (TZIC_BASE + 0x0280) /* Source Clear Register 0 */
+#define TZIC_PRIORITY0 (TZIC_BASE + 0x0400) /* Priority Register 0 */
+#define TZIC_PND0 (TZIC_BASE + 0x0D00) /* Pending Register 0 */
+#define TZIC_HIPND0 (TZIC_BASE + 0x0D80) /* High Priority Pending Register */
+#define TZIC_WAKEUP0 (TZIC_BASE + 0x0E00) /* Wakeup Config Register */
+#define TZIC_SWINT (TZIC_BASE + 0x0F00) /* Software Interrupt Rigger Register */
+#define TZIC_ID0 (TZIC_BASE + 0x0FD0) /* Indentification Register 0 */
+
+#define TZIC_NUM_IRQS 128
+
+/*!
+ * Disable interrupt number "irq" in the TZIC
+ *
+ * @param irq interrupt source number
+ */
+static void mxc_mask_irq(unsigned int irq)
+{
+ int index, off;
+
+ index = irq >> 5;
+ off = irq & 0x1F;
+ __raw_writel(1 << off, TZIC_ENCLEAR0 + (index << 2));
+}
+
+/*!
+ * Enable interrupt number "irq" in the TZIC
+ *
+ * @param irq interrupt source number
+ */
+static void mxc_unmask_irq(unsigned int irq)
+{
+ int index, off;
+
+ index = irq >> 5;
+ off = irq & 0x1F;
+ __raw_writel(1 << off, TZIC_ENSET0 + (index << 2));
+}
+
+static unsigned int wakeup_intr[4];
+
+/*!
+ * Set interrupt number "irq" in the TZIC as a wake-up source.
+ *
+ * @param irq interrupt source number
+ * @param enable enable as wake-up if equal to non-zero
+ * disble as wake-up if equal to zero
+ *
+ * @return This function returns 0 on success.
+ */
+static int mxc_set_wake_irq(unsigned int irq, unsigned int enable)
+{
+ unsigned int index, off;
+
+ index = irq >> 5;
+ off = irq & 0x1F;
+
+ if (index > 3)
+ return -1;
+
+ if (enable)
+ wakeup_intr[index] |= (1 << off);
+ else
+ wakeup_intr[index] &= ~(1 << off);
+
+ return 0;
+}
+
+static struct irq_chip mxc_tzic_chip = {
+ .name = "MXC_TZIC",
+ .ack = mxc_mask_irq,
+ .mask = mxc_mask_irq,
+ .unmask = mxc_unmask_irq,
+ .set_wake = mxc_set_wake_irq,
+};
+
+/*!
+ * This function initializes the TZIC hardware and disables all the
+ * interrupts. It registers the interrupt enable and disable functions
+ * to the kernel for each interrupt source.
+ */
+void __init mxc_init_irq(void)
+{
+ int i;
+
+ /* put the TZIC into the reset value with
+ * all interrupts disabled
+ */
+ i = __raw_readl(TZIC_INTCNTL);
+
+ __raw_writel(0x80010001, TZIC_INTCNTL);
+ i = __raw_readl(TZIC_INTCNTL);
+ __raw_writel(0x1f, TZIC_PRIOMASK);
+ i = __raw_readl(TZIC_PRIOMASK);
+ __raw_writel(0x02, TZIC_SYNCCTRL);
+ i = __raw_readl(TZIC_SYNCCTRL);
+ for (i = 0; i < 4; i++) {
+ __raw_writel(0xFFFFFFFF, TZIC_INTSEC0 + i * 4);
+ }
+ /* disable all interrupts */
+ for (i = 0; i < 4; i++) {
+ __raw_writel(0xFFFFFFFF, TZIC_ENCLEAR0 + i * 4);
+ }
+
+ /* all IRQ no FIQ Warning :: No selection */
+
+ for (i = 0; i < TZIC_NUM_IRQS; i++) {
+ set_irq_chip(i, &mxc_tzic_chip);
+ set_irq_handler(i, handle_level_irq);
+ set_irq_flags(i, IRQF_VALID);
+ }
+
+ printk(KERN_INFO "MXC IRQ initialized\n");
+}
+
+/*!
+ * enable wakeup interrupt
+ *
+ * @param is_idle 1 if called in idle loop (enset registers);
+ * 0 to be used when called from low power entry
+ * @return 0 if successful; non-zero otherwise
+ */
+int tzic_enable_wake(int is_idle)
+{
+ unsigned int i, v;
+
+ __raw_writel(1, TZIC_DSMINT);
+ if (unlikely(__raw_readl(TZIC_DSMINT) == 0))
+ return -EAGAIN;
+
+ if (likely(is_idle)) {
+ for (i = 0; i < 4; i++) {
+ v = __raw_readl(TZIC_ENSET0 + i * 4);
+ __raw_writel(v, TZIC_WAKEUP0 + i * 4);
+ }
+ } else {
+ for (i = 0; i < 4; i++) {
+ v = wakeup_intr[i];
+ __raw_writel(v, TZIC_WAKEUP0 + i * 4);
+ }
+ }
+ return 0;
+}
diff --git a/arch/arm/plat-mxc/usb_common.c b/arch/arm/plat-mxc/usb_common.c
new file mode 100644
index 000000000000..a1f53fd9f3be
--- /dev/null
+++ b/arch/arm/plat-mxc/usb_common.c
@@ -0,0 +1,860 @@
+/*
+ * Copyright 2004-2009 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * otg_{get,set}_transceiver() are from arm/plat-omap/usb.c.
+ * which is Copyright (C) 2004 Texas Instruments, Inc.
+ */
+
+/*
+ * 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
+ */
+
+/*!
+ *@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 <linux/regulator/consumer.h>
+#include <mach/arc_otg.h>
+#include <mach/hardware.h>
+#include <asm/mach-types.h>
+
+#define MXC_NUMBER_USB_TRANSCEIVER 6
+struct fsl_xcvr_ops *g_xc_ops[MXC_NUMBER_USB_TRANSCEIVER] = { NULL };
+
+static struct clk *usb_clk;
+static struct clk *usb_ahb_clk;
+
+extern int gpio_usbotg_hs_active(void);
+extern int gpio_usbotg_hs_inactive(void);
+
+/*
+ * make sure USB_CLK is running at 60 MHz +/- 1000 Hz
+ */
+static int fsl_check_usbclk(void)
+{
+ unsigned long freq;
+
+ usb_ahb_clk = clk_get(NULL, "usb_ahb_clk");
+ if (clk_enable(usb_ahb_clk)) {
+ printk(KERN_ERR "clk_enable(usb_ahb_clk) failed\n");
+ return -EINVAL;
+ }
+ clk_put(usb_ahb_clk);
+
+ usb_clk = clk_get(NULL, "usb_clk");
+ freq = clk_get_rate(usb_clk);
+ clk_put(usb_clk);
+ if ((freq < 59999000) || (freq > 60001000)) {
+ printk(KERN_ERR "USB_CLK=%lu, should be 60MHz\n", freq);
+ return -1;
+ }
+
+ return 0;
+}
+
+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_platform_set_test_mode (struct fsl_usb2_platform_data *pdata, enum usb_test_mode mode)
+{
+ if (pdata->xcvr_ops && pdata->xcvr_ops->set_test_mode)
+ pdata->xcvr_ops->set_test_mode((u32 *)(pdata->regs + ULPIVW_OFF), mode);
+}
+EXPORT_SYMBOL(fsl_platform_set_test_mode);
+
+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);
+
+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;
+
+/*!
+ * Register an instance of a USB host platform device.
+ *
+ * @param res: resource pointer
+ * @param n_res: number of resources
+ * @param config: config pointer
+ *
+ * @return newly-registered platform_device
+ *
+ * The USB controller supports 3 host interfaces, and the
+ * kernel can be configured to support some number of them.
+ * Each supported host interface is registered as an instance
+ * of the "fsl-ehci" device. Call this function multiple times
+ * to register each host interface.
+ */
+static int instance_id = 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;
+ }
+
+ printk(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;
+}
+
+#if defined(CONFIG_USB_OTG)
+static struct otg_transceiver *xceiv;
+
+/**
+ * otg_get_transceiver - find the (single) OTG transceiver driver
+ *
+ * Returns the transceiver driver, after getting a refcount to it; or
+ * null if there is no such transceiver. The caller is responsible for
+ * releasing that count.
+ */
+struct otg_transceiver *otg_get_transceiver(void)
+{
+ pr_debug("%s xceiv=0x%p\n", __func__, xceiv);
+ if (xceiv)
+ get_device(xceiv->dev);
+ return xceiv;
+}
+EXPORT_SYMBOL(otg_get_transceiver);
+
+int otg_set_transceiver(struct otg_transceiver *x)
+{
+ pr_debug("%s xceiv=0x%p x=0x%p\n", __func__, xceiv, x);
+ if (xceiv && x)
+ return -EBUSY;
+ xceiv = x;
+ return 0;
+}
+EXPORT_SYMBOL(otg_set_transceiver);
+
+static struct resource *otg_resources;
+
+struct resource *otg_get_resources(void)
+{
+ 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
+
+static void usbh1_set_serial_xcvr(void)
+{
+ pr_debug("%s: \n", __func__);
+ USBCTRL &= ~(UCTRL_H1SIC_MASK | UCTRL_BPE); /* disable bypass mode */
+ USBCTRL |= UCTRL_H1SIC_SU6 | /* single-ended / unidir. */
+ UCTRL_H1WIE | UCTRL_H1DT | /* disable H1 TLL */
+ UCTRL_H1PM; /* power mask */
+}
+
+static void usbh1_set_ulpi_xcvr(void)
+{
+ pr_debug("%s: \n", __func__);
+
+ /* Stop then Reset */
+ UH1_USBCMD &= ~UCMD_RUN_STOP;
+ while (UH1_USBCMD & UCMD_RUN_STOP) ;
+
+ UH1_USBCMD |= UCMD_RESET;
+ while (UH1_USBCMD & UCMD_RESET) ;
+
+ /* Select the clock from external PHY */
+ USB_CTRL_1 |= USB_CTRL_UH1_EXT_CLK_EN;
+
+ /* select ULPI PHY PTS=2 */
+ UH1_PORTSC1 = (UH1_PORTSC1 & ~PORTSC_PTS_MASK) | PORTSC_PTS_ULPI;
+
+ USBCTRL |= UCTRL_H1WIE; /* HOST1 wakeup intr enable */
+ USBCTRL |= UCTRL_H1UIE; /* Host1 ULPI interrupt enable */
+ USBCTRL &= ~UCTRL_H1PM; /* HOST1 power mask */
+
+ /* Interrupt Threshold Control:Immediate (no threshold) */
+ UH1_USBCMD &= UCMD_ITC_NO_THRESHOLD;
+
+ UH1_USBCMD |= UCMD_RESET; /* reset the controller */
+
+ /* allow controller to reset, and leave time for
+ * the ULPI transceiver to reset too.
+ */
+ msleep(100);
+
+ /* Turn off the usbpll for ulpi tranceivers */
+ clk_disable(usb_clk);
+}
+static void usbh2_set_ulpi_xcvr(void)
+{
+ u32 tmp;
+
+ pr_debug("%s\n", __func__);
+ USBCTRL &= ~(UCTRL_H2SIC_MASK | UCTRL_BPE);
+ USBCTRL |= UCTRL_H2WIE | /* wakeup intr enable */
+ UCTRL_H2UIE | /* ULPI intr enable */
+ UCTRL_H2DT | /* disable H2 TLL */
+ UCTRL_H2PM; /* power mask */
+
+ /* must set ULPI phy before turning off clock */
+ tmp = UH2_PORTSC1 & ~PORTSC_PTS_MASK;
+ tmp |= PORTSC_PTS_ULPI;
+ UH2_PORTSC1 = tmp;
+
+ UH2_USBCMD |= UCMD_RESET; /* reset the controller */
+
+ /* allow controller to reset, and leave time for
+ * the ULPI transceiver to reset too.
+ */
+ msleep(100);
+
+ /* Turn off the usbpll for ulpi tranceivers */
+ clk_disable(usb_clk);
+}
+
+static void usbh2_set_serial_xcvr(void)
+{
+ pr_debug("%s: \n", __func__);
+
+ /* Stop then Reset */
+ UH2_USBCMD &= ~UCMD_RUN_STOP;
+ while (UH2_USBCMD & UCMD_RUN_STOP) ;
+
+ UH2_USBCMD |= UCMD_RESET;
+ while (UH2_USBCMD & UCMD_RESET) ;
+
+ USBCTRL &= ~(UCTRL_H2SIC_MASK); /* Disable bypass mode */
+ USBCTRL &= ~(UCTRL_H2PM); /* Power Mask */
+ USBCTRL &= ~UCTRL_H2OCPOL; /* OverCurrent Polarity is Low Active */
+ USBCTRL &= ~UCTRL_H2WIE; /* Wakeup intr disable */
+ USBCTRL |= UCTRL_IP_PUE_DOWN | /* ipp_pue_pulldwn_dpdm */
+ UCTRL_USBTE | /* USBT is enabled */
+ UCTRL_H2DT; /* Disable H2 TLL */
+
+ if (cpu_is_mx35_rev(CHIP_REV_2_0) < 0) {
+ /* Disable Host2 bus Lock for i.MX35 1.0 */
+ USBCTRL |= UCTRL_H2LOCKD;
+ /* USBOTG_PWR low active */
+ USBCTRL &= ~UCTRL_PP;
+ /* OverCurrent Polarity is Low Active */
+ USBCTRL &= ~UCTRL_OCPOL;
+ } else if (cpu_is_mx35_rev(CHIP_REV_2_0) >= 1) {
+ /* i.MX35 2.0 OTG and Host2 have seperate OC/PWR polarity */
+ USBCTRL &= ~UCTRL_H2PP;
+ USBCTRL &= ~UCTRL_H2OCPOL;
+ } else if (cpu_is_mx25()) {
+ /*
+ * USBH2_PWR and USBH2_OC are active high.
+ * Must force xcvr clock to "internal" so that
+ * we can write to PTS field after it's been
+ * cleared by ehci_turn_off_all_ports().
+ */
+ USBCTRL |= UCTRL_H2PP | UCTRL_H2OCPOL | UCTRL_XCSH2;
+ /* Disable Host2 bus Lock */
+ USBCTRL |= UCTRL_H2LOCKD;
+ }
+
+ USBCTRL &= ~(UCTRL_PP);
+ UH2_PORTSC1 = (UH2_PORTSC1 & (~PORTSC_PTS_MASK)) | PORTSC_PTS_SERIAL;
+
+ if (UH2_HCSPARAMS & HCSPARAMS_PPC)
+ UH2_PORTSC1 |= PORTSC_PORT_POWER;
+
+ /* Reset controller before set host mode */
+ UH2_USBCMD |= UCMD_RESET;
+ while (UH2_USBCMD & UCMD_RESET) ;
+
+ msleep(100);
+}
+
+/*!
+ * 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 resource *res;
+ int irq;
+
+ pr_debug("%s: pdev=0x%p \n", __func__, pdev);
+ if (!cpu_is_mx51())
+ 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;
+}
+
+extern void gpio_usbh1_setback_stp(void);
+extern void gpio_usbh2_setback_stp(void);
+
+int fsl_usb_host_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 "%s transceiver ops missing\n", pdata->name);
+ return -EINVAL;
+ }
+ pdata->xcvr_ops = xops;
+ pdata->xcvr_type = xops->xcvr_type;
+ pdata->pdev = pdev;
+
+ if (fsl_check_usbclk() != 0)
+ return -EINVAL;
+
+ pr_debug("%s: grab pins\n", __func__);
+ if (pdata->gpio_usb_active())
+ return -EINVAL;
+
+ if (clk_enable(usb_clk)) {
+ printk(KERN_ERR "clk_enable(usb_clk) failed\n");
+ return -EINVAL;
+ }
+
+ if (cpu_is_mx51()) {
+ usb_clk = clk_get(NULL, "usboh3_clk");
+ clk_enable(usb_clk);
+ clk_put(usb_clk);
+ }
+
+ /* enable board power supply for xcvr */
+ if (pdata->xcvr_pwr) {
+ if (pdata->xcvr_pwr->regu1)
+ regulator_enable(pdata->xcvr_pwr->regu1);
+ if (pdata->xcvr_pwr->regu2)
+ regulator_enable(pdata->xcvr_pwr->regu2);
+ }
+
+ if (xops->init)
+ xops->init(xops);
+
+ if (usb_register_remote_wakeup(pdev))
+ pr_debug("%s port is not a wakeup source.\n", pdata->name);
+
+ if (xops->xcvr_type == PORTSC_PTS_SERIAL) {
+ if (cpu_is_mx35()) {
+ usbh2_set_serial_xcvr();
+ /* Close the internal 60Mhz */
+ USBCTRL &= ~UCTRL_XCSH2;
+ } else if (cpu_is_mx25())
+ usbh2_set_serial_xcvr();
+ else
+ usbh1_set_serial_xcvr();
+ } else if (xops->xcvr_type == PORTSC_PTS_ULPI) {
+ if (!strcmp("Host 1", pdata->name)) {
+ usbh1_set_ulpi_xcvr();
+ if (cpu_is_mx51()) {
+#ifdef CONFIG_USB_EHCI_ARC_H1
+ gpio_usbh1_setback_stp();
+ /* disable remote wakeup irq */
+ USBCTRL &= ~UCTRL_H1WIE;
+#endif
+ }
+ }
+ if (!strcmp("Host 2", pdata->name)) {
+ usbh2_set_ulpi_xcvr();
+ if (cpu_is_mx51()) {
+#ifdef CONFIG_USB_EHCI_ARC_H2
+ gpio_usbh2_setback_stp();
+#endif
+ }
+ }
+ }
+
+ 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;
+
+ pdata->gpio_usb_inactive();
+ if (pdata->xcvr_type == PORTSC_PTS_SERIAL) {
+ /* Workaround an IC issue for ehci driver.
+ * when turn off root hub port power, EHCI set
+ * PORTSC reserved bits to be 0, but PTS with 0
+ * means UTMI interface, so here force the Host2
+ * port use the internal 60Mhz.
+ */
+ if (cpu_is_mx35())
+ USBCTRL |= UCTRL_XCSH2;
+ clk_disable(usb_clk);
+ }
+
+ /* disable board power supply for xcvr */
+ if (pdata->xcvr_pwr) {
+ if (pdata->xcvr_pwr->regu1)
+ regulator_disable(pdata->xcvr_pwr->regu1);
+ if (pdata->xcvr_pwr->regu2)
+ regulator_disable(pdata->xcvr_pwr->regu2);
+ }
+
+ if (cpu_is_mx51()) {
+ usb_clk = clk_get(NULL, "usboh3_clk");
+ clk_disable(usb_clk);
+ clk_put(usb_clk);
+ }
+}
+EXPORT_SYMBOL(fsl_usb_host_uninit);
+
+static void otg_set_serial_xcvr(void)
+{
+ pr_debug("%s\n", __func__);
+}
+
+void otg_set_serial_host(void)
+{
+ pr_debug("%s\n", __func__);
+ /* set USBCTRL for host operation
+ * disable: bypass mode,
+ * set: single-ended/unidir/6 wire, OTG wakeup intr enable,
+ * power mask
+ */
+ USBCTRL &= ~UCTRL_OSIC_MASK;
+#if defined(CONFIG_ARCH_MX27) || defined(CONFIG_ARCH_MX3)
+ USBCTRL &= ~UCTRL_BPE;
+#endif
+
+#if defined(CONFIG_MXC_USB_SB3)
+ USBCTRL |= UCTRL_OSIC_SB3 | UCTRL_OWIE | UCTRL_OPM;
+#elif defined(CONFIG_MXC_USB_SU6)
+ USBCTRL |= UCTRL_OSIC_SU6 | UCTRL_OWIE | UCTRL_OPM;
+#elif defined(CONFIG_MXC_USB_DB4)
+ USBCTRL |= UCTRL_OSIC_DB4 | UCTRL_OWIE | UCTRL_OPM;
+#else
+ USBCTRL |= UCTRL_OSIC_DU6 | UCTRL_OWIE | UCTRL_OPM;
+#endif
+
+ USB_OTG_MIRROR = OTGM_VBUSVAL | OTGM_ASESVLD; /* 0xa */
+}
+EXPORT_SYMBOL(otg_set_serial_host);
+
+void otg_set_serial_peripheral(void)
+{
+ /* set USBCTRL for device operation
+ * disable: bypass mode
+ * set: differential/unidir/6 wire, OTG wakeup intr enable,
+ * power mask
+ */
+ USBCTRL &= ~UCTRL_OSIC_MASK;
+#if defined(CONFIG_ARCH_MX27) || defined(CONFIG_ARCH_MX3)
+ USBCTRL &= ~UCTRL_BPE;
+#endif
+
+#if defined(CONFIG_MXC_USB_SB3)
+ USBCTRL |= UCTRL_OSIC_SB3 | UCTRL_OWIE | UCTRL_OPM;
+#elif defined(CONFIG_MXC_USB_SU6)
+ USBCTRL |= UCTRL_OSIC_SU6 | UCTRL_OWIE | UCTRL_OPM;
+#elif defined(CONFIG_MXC_USB_DB4)
+ USBCTRL |= UCTRL_OSIC_DB4 | UCTRL_OWIE | UCTRL_OPM;
+#else
+ USBCTRL |= UCTRL_OSIC_DU6 | UCTRL_OWIE | UCTRL_OPM;
+#endif
+
+ USB_OTG_MIRROR = OTGM_VBUSVAL | OTGM_BSESVLD | OTGM_IDIDG; /* oxd */
+}
+EXPORT_SYMBOL(otg_set_serial_peripheral);
+
+static void otg_set_ulpi_xcvr(void)
+{
+ u32 tmp;
+
+ pr_debug("%s\n", __func__);
+ USBCTRL &= ~UCTRL_OSIC_MASK;
+#if defined(CONFIG_ARCH_MX27) || defined(CONFIG_ARCH_MX3)
+ USBCTRL &= ~UCTRL_BPE;
+#endif
+ USBCTRL |= UCTRL_OUIE | /* ULPI intr enable */
+ UCTRL_OWIE | /* OTG wakeup intr enable */
+ UCTRL_OPM; /* power mask */
+
+ /* must set ULPI phy before turning off clock */
+ tmp = UOG_PORTSC1 & ~PORTSC_PTS_MASK;
+ tmp |= PORTSC_PTS_ULPI;
+ UOG_PORTSC1 = tmp;
+
+ /* need to reset the controller here so that the ID pin
+ * is correctly detected.
+ */
+ UOG_USBCMD |= UCMD_RESET;
+
+ /* allow controller to reset, and leave time for
+ * the ULPI transceiver to reset too.
+ */
+ msleep(100);
+
+ /* Turn off the usbpll for ulpi tranceivers */
+ clk_disable(usb_clk);
+}
+
+int fsl_usb_xcvr_suspend(struct fsl_xcvr_ops *xcvr_ops)
+{
+ if (!machine_is_mx31_3ds())
+ return -ECANCELED;
+
+ if (xcvr_ops->xcvr_type == PORTSC_PTS_ULPI) {
+ if (fsl_check_usbclk() != 0)
+ return -EINVAL;
+ if (gpio_usbotg_hs_active())
+ return -EINVAL;
+ clk_enable(usb_clk);
+
+ otg_set_ulpi_xcvr();
+
+ if (xcvr_ops->suspend)
+ /* suspend transceiver */
+ xcvr_ops->suspend(xcvr_ops);
+
+ gpio_usbotg_hs_inactive();
+ clk_disable(usb_clk);
+ }
+ return 0;
+}
+EXPORT_SYMBOL(fsl_usb_xcvr_suspend);
+
+static void otg_set_utmi_xcvr(void)
+{
+ u32 tmp;
+
+ /* Stop then Reset */
+ UOG_USBCMD &= ~UCMD_RUN_STOP;
+ while (UOG_USBCMD & UCMD_RUN_STOP) ;
+
+ UOG_USBCMD |= UCMD_RESET;
+ while ((UOG_USBCMD) & (UCMD_RESET)) ;
+
+ if (cpu_is_mx51()) {
+ /* OTG Polarity of Overcurrent is Low active */
+ USB_PHY_CTR_FUNC |= USB_UTMI_PHYCTRL_OC_POL;
+ /* Enable OTG Overcurrent Event */
+ USB_PHY_CTR_FUNC &= ~USB_UTMI_PHYCTRL_OC_DIS;
+ } else if (cpu_is_mx25()) {
+ USBCTRL |= UCTRL_OCPOL;
+ USBCTRL &= ~UCTRL_PP;
+ } else {
+ /* USBOTG_PWR low active */
+ USBCTRL &= ~UCTRL_PP;
+ /* OverCurrent Polarity is Low Active */
+ USBCTRL &= ~UCTRL_OCPOL;
+
+ if (cpu_is_mx35_rev(CHIP_REV_2_0) < 0)
+ /* OTG Lock Disable */
+ USBCTRL |= UCTRL_OLOCKD;
+ }
+
+ USBCTRL &= ~UCTRL_OPM; /* OTG Power Mask */
+ USBCTRL &= ~UCTRL_OWIE; /* OTG Wakeup Intr Disable */
+
+ /* set UTMI xcvr */
+ tmp = UOG_PORTSC1 & ~PORTSC_PTS_MASK;
+ tmp |= PORTSC_PTS_UTMI;
+ UOG_PORTSC1 = tmp;
+
+ if (cpu_is_mx51()) {
+ /* Set the PHY clock to 19.2MHz */
+ USB_PHY_CTR_FUNC2 &= ~USB_UTMI_PHYCTRL2_PLLDIV_MASK;
+ USB_PHY_CTR_FUNC2 |= 0x01;
+ } else if (machine_is_mx37_3ds()) {
+ /* Reference voltage for HS disconnect envelope detector */
+ /* adjust the Squelch level */
+ USB_PHY_CTR_FUNC2 &= ~(USB_UTMI_PHYCTRL2_HSDEVSEL_MASK <<
+ USB_UTMI_PHYCTRL2_HSDEVSEL_SHIFT);
+ }
+
+ /* 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.
+ */
+ UOG_PORTSC1 |= PORTSC_PTW;
+
+ if (cpu_is_mx35() || cpu_is_mx25()) {
+ /* Enable UTMI interface in PHY control Reg */
+ USB_PHY_CTR_FUNC &= ~USB_UTMI_PHYCTRL_UTMI_ENABLE;
+ USB_PHY_CTR_FUNC |= USB_UTMI_PHYCTRL_UTMI_ENABLE;
+ }
+
+ /* need to reset the controller here so that the ID pin
+ * is correctly detected.
+ */
+ /* Stop then Reset */
+ UOG_USBCMD &= ~UCMD_RUN_STOP;
+ while (UOG_USBCMD & UCMD_RUN_STOP) ;
+
+ UOG_USBCMD |= UCMD_RESET;
+ while ((UOG_USBCMD) & (UCMD_RESET)) ;
+
+ /* allow controller to reset, and leave time for
+ * the ULPI transceiver to reset too.
+ */
+ msleep(100);
+
+ /* Turn off the usbpll for mx25 UTMI tranceivers */
+ /* DDD: can we do this UTMI xcvrs on all boards? */
+ if (cpu_is_mx25()) {
+ clk_disable(usb_clk);
+ } else if (cpu_is_mx37()) {
+ /* fix USB PHY Power Gating leakage issue for i.MX37 */
+ USB_PHY_CTR_FUNC &= ~USB_UTMI_PHYCTRL_CHGRDETON;
+ USB_PHY_CTR_FUNC &= ~USB_UTMI_PHYCTRL_CHGRDETEN;
+ }
+}
+
+static int otg_used = 0;
+
+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) {
+ if (fsl_check_usbclk() != 0)
+ return -EINVAL;
+
+ pr_debug("%s: grab pins\n", __func__);
+ if (pdata->gpio_usb_active())
+ return -EINVAL;
+
+ if (clk_enable(usb_clk)) {
+ printk(KERN_ERR "clk_enable(usb_clk) failed\n");
+ return -EINVAL;
+ }
+
+ if (xops->init)
+ xops->init(xops);
+
+ UOG_PORTSC1 = UOG_PORTSC1 & ~PORTSC_PHCD;
+ if (xops->xcvr_type == PORTSC_PTS_SERIAL) {
+ if (pdata->operating_mode == FSL_USB2_DR_HOST) {
+ otg_set_serial_host();
+ /* need reset */
+ UOG_USBCMD |= UCMD_RESET;
+ msleep(100);
+ } else if (pdata->operating_mode == FSL_USB2_DR_DEVICE)
+ otg_set_serial_peripheral();
+ otg_set_serial_xcvr();
+ } else if (xops->xcvr_type == PORTSC_PTS_ULPI) {
+ otg_set_ulpi_xcvr();
+ } else if (xops->xcvr_type == PORTSC_PTS_UTMI) {
+ otg_set_utmi_xcvr();
+ }
+ }
+
+ if (usb_register_remote_wakeup(pdev))
+ pr_debug("DR is not a wakeup source.\n");
+
+ 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__);
+
+ otg_used--;
+ if (!otg_used) {
+ if (pdata->xcvr_ops && pdata->xcvr_ops->uninit)
+ pdata->xcvr_ops->uninit(pdata->xcvr_ops);
+
+ pdata->regs = NULL;
+
+ if (machine_is_mx31_3ds()) {
+ if (pdata->xcvr_ops && pdata->xcvr_ops->suspend)
+ pdata->xcvr_ops->suspend(pdata->xcvr_ops);
+ clk_disable(usb_clk);
+ }
+ msleep(1);
+ UOG_PORTSC1 = UOG_PORTSC1 | PORTSC_PHCD;
+ pdata->gpio_usb_inactive();
+ if (pdata->xcvr_type == PORTSC_PTS_SERIAL)
+ clk_disable(usb_clk);
+ clk_disable(usb_ahb_clk);
+ }
+}
+EXPORT_SYMBOL(usbotg_uninit);
+
+int usb_host_wakeup_irq(struct device *wkup_dev)
+{
+ int wakeup_req = 0;
+ struct fsl_usb2_platform_data *pdata = wkup_dev->platform_data;
+
+ if (!strcmp("Host 1", pdata->name)) {
+ wakeup_req = USBCTRL & UCTRL_H1WIR;
+ } else if (!strcmp("DR", pdata->name)) {
+ wakeup_req = USBCTRL & UCTRL_OWIR;
+ /* If DR is in device mode, let udc handle it */
+ if (wakeup_req && ((UOG_USBMODE & 0x3) == 0x2))
+ wakeup_req = 0;
+ }
+
+ return wakeup_req;
+}
+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 this device may wakeup */
+ if (device_may_wakeup(wkup_dev) && para) {
+ if (!strcmp("Host 1", pdata->name)) {
+ USBCTRL |= UCTRL_H1WIE;
+ } else if (!strcmp("DR", pdata->name)) {
+ USBCTRL |= UCTRL_OWIE;
+ /* Enable OTG ID Wakeup */
+ USBCTRL_HOST2 |= (1 << 5);
+ }
+ }
+
+ if (!para) {
+ if (!strcmp("Host 1", pdata->name))
+ USBCTRL &= ~UCTRL_H1WIE;
+ else if (!strcmp("DR", pdata->name)) {
+ USBCTRL &= ~UCTRL_OWIE;
+ USBCTRL_HOST2 &= ~(1 << 5);
+ }
+ }
+}
+EXPORT_SYMBOL(usb_host_set_wakeup);
diff --git a/arch/arm/plat-mxc/utmixc.c b/arch/arm/plat-mxc/utmixc.c
new file mode 100644
index 000000000000..a3b2bad03444
--- /dev/null
+++ b/arch/arm/plat-mxc/utmixc.c
@@ -0,0 +1,106 @@
+/*
+ * Copyright 2005-2009 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/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>
+
+static struct regulator *usbotg_regux;
+
+static void usb_utmi_init(struct fsl_xcvr_ops *this)
+{
+#if defined(CONFIG_MXC_PMIC_MC13892_MODULE) || defined(CONFIG_MXC_PMIC_MC13892)
+ if (machine_is_mx51_3ds()) {
+ unsigned int value;
+
+ /* VUSBIN */
+ pmic_read_reg(REG_USB1, &value, 0xffffff);
+ value |= 0x1;
+ value |= (0x1 << 3);
+ pmic_write_reg(REG_USB1, value, 0xffffff);
+ }
+#endif
+}
+
+static void usb_utmi_uninit(struct fsl_xcvr_ops *this)
+{
+}
+
+/*!
+ * set vbus power
+ *
+ * @param view viewport register
+ * @param on power on or off
+ */
+static void set_power(struct fsl_xcvr_ops *this,
+ struct fsl_usb2_platform_data *pdata, int on)
+{
+ struct device *dev = &pdata->pdev->dev;
+
+ pr_debug("real %s(on=%d) pdata=0x%p\n", __func__, on, pdata);
+ if (machine_is_mx37_3ds()) {
+ if (on) {
+ if (!board_is_rev(BOARD_REV_2))
+ usbotg_regux = regulator_get(dev, "DCDC2");
+ else
+ usbotg_regux = regulator_get(dev, "SWBST");
+
+ regulator_enable(usbotg_regux);
+ } else {
+ regulator_disable(usbotg_regux);
+ regulator_put(usbotg_regux);
+ }
+ }
+}
+
+static struct fsl_xcvr_ops utmi_ops = {
+ .name = "utmi",
+ .xcvr_type = PORTSC_PTS_UTMI,
+ .init = usb_utmi_init,
+ .uninit = usb_utmi_uninit,
+ .set_vbus_power = set_power,
+};
+
+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);
+}
+
+module_init(utmixc_init);
+module_exit(utmixc_exit);
+
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_DESCRIPTION("utmi xcvr driver");
+MODULE_LICENSE("GPL");
diff --git a/arch/arm/plat-mxc/wdog.c b/arch/arm/plat-mxc/wdog.c
new file mode 100644
index 000000000000..8f242e707f58
--- /dev/null
+++ b/arch/arm/plat-mxc/wdog.c
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2004-2009 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
+ */
+
+/*!
+ * @file plat-mxc/wdog.c
+ * @brief This file contains watchdog timer implementations.
+ *
+ * This file contains watchdog timer implementations for timer tick.
+ *
+ * @ingroup WDOG
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <mach/hardware.h>
+
+#define WDOG_WT 0x8 /* WDOG WT starting bit inside WCR */
+#define WCR_WOE_BIT (1 << 6)
+#define WCR_WDA_BIT (1 << 5)
+#define WCR_SRS_BIT (1 << 4)
+#define WCR_WRE_BIT (1 << 3)
+#define WCR_WDE_BIT (1 << 2)
+#define WCR_WDBG_BIT (1 << 1)
+#define WCR_WDZST_BIT (1 << 0)
+
+/*
+ * WatchDog
+ */
+#define WDOG_WCR 0 /* 16bit watchdog control reg */
+#define WDOG_WSR 2 /* 16bit watchdog service reg */
+#define WDOG_WRSR 4 /* 16bit watchdog reset status reg */
+
+/*!
+ * The base addresses for the WDOG modules
+ */
+static void __iomem *wdog_base[2] = {
+ IO_ADDRESS(WDOG1_BASE_ADDR),
+#ifdef WDOG2_BASE_ADDR
+ IO_ADDRESS(WDOG2_BASE_ADDR),
+#endif
+};
+
+void mxc_wd_reset(void)
+{
+ u16 reg;
+ struct clk *clk;
+
+ clk = clk_get(NULL, "wdog_clk");
+ clk_enable(clk);
+
+ reg = __raw_readw(wdog_base[0] + WDOG_WCR) & ~WCR_SRS_BIT;
+ reg |= WCR_WDE_BIT;
+ __raw_writew(reg, wdog_base[0] + WDOG_WCR);
+}